diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 00000000..ee93ab06 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,49 @@ +indentation: 4 +disabled_rules: + - cyclomatic_complexity + - file_length + - function_body_length + - function_parameter_count + - identifier_name + - implicit_return + - large_tuple + - line_length + - todo + - type_body_length + - type_name +opt_in_rules: + - anyobject_protocol + - array_init + - attributes + #- closure_end_indentation ## commented as --format removes option + - closure_spacing + - conditional_returns_on_newline + - contains_over_range_nil_comparison + - empty_count + - empty_string + - explicit_init + - fatal_error_message + - first_where + - implicitly_unwrapped_optional + - joined_default_parameter + #- literal_expression_end_indentation ## commented as --format removes option + - legacy_random + - let_var_whitespace + - lower_acl_than_parent + - multiline_function_chains + - operator_usage_whitespace + - pattern_matching_keywords + - redundant_nil_coalescing + - redundant_type_annotation + - sorted_imports + - trailing_closure + - unneeded_parentheses_in_closure_argument + - untyped_error_in_catch + - vertical_whitespace_closing_braces + - xct_specific_matcher + - yoda_condition +trailing_comma: + mandatory_comma: true +excluded: + - keychain/trust/cuttlefish/ + - keychain/Trieste/OctagonTriesteTests/.build diff --git a/Analytics/Clients/LocalKeychainAnalytics.h b/Analytics/Clients/LocalKeychainAnalytics.h index f3344093..48b2af03 100644 --- a/Analytics/Clients/LocalKeychainAnalytics.h +++ b/Analytics/Clients/LocalKeychainAnalytics.h @@ -35,6 +35,9 @@ void LKAReportKeychainUpgradeOutcomeWithError(int fromversion, int toversion, LK void LKABackupReportStart(bool hasKeybag, bool hasPasscode, bool isEMCS); void LKABackupReportEnd(bool hasBackup, CFErrorRef error); +// For tests only +void LKAForceClose(void); + #if __OBJC2__ #import @@ -44,6 +47,8 @@ typedef NSString* LKAnalyticsFailableEvent NS_STRING_ENUM; typedef NSString* LKAnalyticsMetric NS_STRING_ENUM; extern LKAnalyticsFailableEvent const LKAEventUpgrade; +extern LKAnalyticsFailableEvent const LKAEventStash; +extern LKAnalyticsFailableEvent const LKAEventStashLoad; @interface LocalKeychainAnalytics : SFAnalytics diff --git a/Analytics/Clients/LocalKeychainAnalytics.m b/Analytics/Clients/LocalKeychainAnalytics.m index 75a694a0..9fad7b1d 100644 --- a/Analytics/Clients/LocalKeychainAnalytics.m +++ b/Analytics/Clients/LocalKeychainAnalytics.m @@ -8,10 +8,6 @@ #include #include -#ifdef DARLING -#import -#endif - @interface LKAUpgradeOutcomeReport : NSObject @property LKAKeychainUpgradeOutcome outcome; @property NSDictionary* attributes; @@ -28,7 +24,6 @@ } @end -#if !defined(DARLING) || defined(__OBJC2__) // Approved event types // rdar://problem/41745059 SFAnalytics: collect keychain upgrade outcome information LKAnalyticsFailableEvent const LKAEventUpgrade = (LKAnalyticsFailableEvent)@"LKAEventUpgrade"; @@ -37,6 +32,10 @@ LKAnalyticsFailableEvent const LKAEventUpgrade = (LKAnalyticsFailableEvent)@"LKA LKAnalyticsFailableEvent const LKAEventBackup = (LKAnalyticsFailableEvent)@"LKAEventBackup"; LKAnalyticsMetric const LKAMetricBackupDuration = (LKAnalyticsMetric)@"LKAMetricBackupDuration"; +// SFAnalytics: Collect keychain masterkey stash success/failure rates and failure codes on macOS SUs +LKAnalyticsFailableEvent const LKAEventStash = (LKAnalyticsFailableEvent)@"LKAEventStash"; +LKAnalyticsFailableEvent const LKAEventStashLoad = (LKAnalyticsFailableEvent)@"LKAEventStashLoad"; + // Internal consts NSString* const LKAOldSchemaKey = @"oldschema"; NSString* const LKANewSchemaKey = @"newschema"; @@ -156,40 +155,41 @@ NSString* const LKABackupLastSuccessDate = @"backupLastSuccess"; [self logSuccessForEventNamed:LKAEventBackup timestampBucket:SFAnalyticsTimestampBucketHour]; } else { NSInteger daysSinceSuccess = [SFAnalytics fuzzyDaysSinceDate:[self datePropertyForKey:LKABackupLastSuccessDate]]; - [self logResultForEvent:LKAEventBackup - hardFailure:YES - result:error - withAttributes:@{@"daysSinceSuccess" : @(daysSinceSuccess), - @"duration" : @(backupDuration), - @"type" : @(_backupType), - } - timestampBucket:SFAnalyticsTimestampBucketHour]; + + // Backups fail all the time due to devices being locked. If a backup has happened recently, + // let's not even report it, to avoid crowding out more useful data + bool boringError = error.code == errSecInteractionNotAllowed && daysSinceSuccess == 0; + + if(!boringError) { + [self logResultForEvent:LKAEventBackup + hardFailure:YES + result:error + withAttributes:@{@"daysSinceSuccess" : @(daysSinceSuccess), + @"duration" : @(backupDuration), + @"type" : @(_backupType), + } + timestampBucket:SFAnalyticsTimestampBucketHour]; + } } } @end -#endif // MARK: C Bridging void LKAReportKeychainUpgradeOutcome(int fromversion, int toversion, LKAKeychainUpgradeOutcome outcome) { - #if !defined(DARLING) || defined(__OBJC2__) @autoreleasepool { [[LocalKeychainAnalytics logger] reportKeychainUpgradeFrom:fromversion to:toversion outcome:outcome error:NULL]; } - #endif } void LKAReportKeychainUpgradeOutcomeWithError(int fromversion, int toversion, LKAKeychainUpgradeOutcome outcome, CFErrorRef error) { - #if !defined(DARLING) || defined(__OBJC2__) @autoreleasepool { [[LocalKeychainAnalytics logger] reportKeychainUpgradeFrom:fromversion to:toversion outcome:outcome error:(__bridge NSError*)error]; } - #endif } void LKABackupReportStart(bool hasKeybag, bool hasPasscode, bool isEMCS) { - #if !defined(DARLING) || defined(__OBJC2__) LKAKeychainBackupType type; if (isEMCS) { type = LKAKeychainBackupTypeEMCS; @@ -207,13 +207,17 @@ void LKABackupReportStart(bool hasKeybag, bool hasPasscode, bool isEMCS) { @autoreleasepool { [[LocalKeychainAnalytics logger] reportKeychainBackupStartWithType:type]; } - #endif } void LKABackupReportEnd(bool hasBackup, CFErrorRef error) { - #if !defined(DARLING) || defined(__OBJC2__) @autoreleasepool { [[LocalKeychainAnalytics logger] reportKeychainBackupEnd:hasBackup error:(__bridge NSError*)error]; } - #endif +} + +void LKAForceClose(void) +{ + @autoreleasepool { + [[LocalKeychainAnalytics logger] removeState]; + } } diff --git a/Analytics/Clients/SOSAnalytics.h b/Analytics/Clients/SOSAnalytics.h index 53e81312..87287418 100644 --- a/Analytics/Clients/SOSAnalytics.h +++ b/Analytics/Clients/SOSAnalytics.h @@ -26,7 +26,7 @@ #define SOSAnalytics_h #import -#import "Analytics/SFAnalytics.h" +#import extern NSString* const CKDKVSPerformanceCountersSampler; diff --git a/Analytics/SFAnalytics+Internal.h b/Analytics/SFAnalytics+Internal.h index 05aa19a7..2d5554db 100644 --- a/Analytics/SFAnalytics+Internal.h +++ b/Analytics/SFAnalytics+Internal.h @@ -31,6 +31,7 @@ @interface SFAnalytics (Internal) - (void)logMetric:(NSNumber*)metric withName:(NSString*)metricName oncePerReport:(BOOL)once; ++ (NSString*)hwModelID; @end diff --git a/Analytics/SFAnalytics.h b/Analytics/SFAnalytics.h index 55d35ba6..bfe5008a 100644 --- a/Analytics/SFAnalytics.h +++ b/Analytics/SFAnalytics.h @@ -26,9 +26,9 @@ #define SFAnalytics_h #import -#import "SFAnalyticsSampler.h" -#import "SFAnalyticsMultiSampler.h" -#import "SFAnalyticsActivityTracker.h" +#import +#import +#import NS_ASSUME_NONNULL_BEGIN @@ -66,10 +66,18 @@ typedef NS_ENUM(uint32_t, SFAnalyticsTimestampBucket) { + (instancetype _Nullable)logger; + (NSInteger)fuzzyDaysSinceDate:(NSDate*)date; + +// Rounds to the nearest 5 (unless 1 or 2, that rounds to 5 as well) ++ (NSInteger)fuzzyInteger:(NSInteger)num; ++ (NSNumber*)fuzzyNumber:(NSNumber*)num; + + (void)addOSVersionToEvent:(NSMutableDictionary*)event; // Help for the subclass to pick a prefered location + (NSString *)defaultAnalyticsDatabasePath:(NSString *)basename; ++ (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename uuid:(NSUUID * __nullable)userUuid; ++ (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename; // uses current user UUID for path + - (void)dailyCoreAnalyticsMetrics:(NSString *)eventName; // Log event-based metrics: create an event corresponding to some event in your feature diff --git a/Analytics/SFAnalytics.m b/Analytics/SFAnalytics.m index 4f6933a4..09436d72 100644 --- a/Analytics/SFAnalytics.m +++ b/Analytics/SFAnalytics.m @@ -40,6 +40,13 @@ #import +#if TARGET_OS_OSX +#include +#include +#else +#import +#endif + // SFAnalyticsDefines constants NSString* const SFAnalyticsTableSuccessCount = @"success_count"; NSString* const SFAnalyticsTableHardFailures = @"hard_failures"; @@ -53,6 +60,7 @@ NSString* const SFAnalyticsColumnSoftFailureCount = @"soft_failure_count"; NSString* const SFAnalyticsColumnSampleValue = @"value"; NSString* const SFAnalyticsColumnSampleName = @"name"; +NSString* const SFAnalyticsPostTime = @"postTime"; NSString* const SFAnalyticsEventTime = @"eventTime"; NSString* const SFAnalyticsEventType = @"eventType"; NSString* const SFAnalyticsEventTypeErrorEvent = @"errorEvent"; @@ -73,6 +81,7 @@ NSString* const SFAnalyticsTopicCloudServices = @"CloudServicesTopic"; NSString* const SFAnalyticsTopicKeySync = @"KeySyncTopic"; NSString* const SFAnalyticsTopicTrust = @"TrustTopic"; NSString* const SFAnalyticsTopicTransparency = @"TransparencyTopic"; +NSString* const SFAnalyticsTopicNetworking = @"NetworkingTopic"; NSString* const SFAnalyticsTableSchema = @"CREATE TABLE IF NOT EXISTS hard_failures (\n" @"id INTEGER PRIMARY KEY AUTOINCREMENT,\n" @@ -130,6 +139,7 @@ NSString* const SFAnalyticsErrorDomain = @"com.apple.security.sfanalytics"; // Local constants NSString* const SFAnalyticsEventBuild = @"build"; NSString* const SFAnalyticsEventProduct = @"product"; +NSString* const SFAnalyticsEventModelID = @"modelid"; NSString* const SFAnalyticsEventInternal = @"internal"; const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; @@ -175,7 +185,8 @@ const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; { WithPathInKeychainDirectory(CFSTR("Analytics"), ^(const char *path) { #if TARGET_OS_IPHONE - mode_t permissions = 0775; + /* We need _securityd, _trustd, and root all to be able to write. They share no groups. */ + mode_t permissions = 0777; #else mode_t permissions = 0700; #endif // TARGET_OS_IPHONE @@ -189,6 +200,62 @@ const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)path) path]; } ++ (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename uuid:(NSUUID * __nullable)userUuid +{ + // Create the top-level directory with full access + NSMutableString *directory = [NSMutableString stringWithString:@"sfanalytics"]; + WithPathInProtectedDirectory((__bridge CFStringRef)directory, ^(const char *path) { + mode_t permissions = 0777; + int ret = mkpath_np(path, permissions); + if (!(ret == 0 || ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + } + chmod(path, permissions); + }); + + // create per-user directory + if (userUuid) { + [directory appendString:@"/"]; + [directory appendString:[userUuid UUIDString]]; + WithPathInProtectedDirectory((__bridge CFStringRef)directory, ^(const char *path) { +#if TARGET_OS_IPHONE + /* We need _securityd, _trustd, and root all to be able to write. They share no groups. */ + mode_t permissions = 0777; +#else + mode_t permissions = 0700; + if (geteuid() == 0 || geteuid() == 282) { + // Root/_trustd user directory needs to be read/write for group so that user supd can upload system data + permissions = 0775; + } +#endif // TARGET_OS_IPHONE + int ret = mkpath_np(path, permissions); + if (!(ret == 0 || ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + } + chmod(path, permissions); + }); + } + NSString *path = [NSString stringWithFormat:@"%@/%@.db", directory, basename]; + return [(__bridge_transfer NSURL*)SecCopyURLForFileInProtectedDirectory((__bridge CFStringRef)path) path]; +} + ++ (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename +{ +#if TARGET_OS_OSX + uid_t euid = geteuid(); + uuid_t currentUserUuid; + int ret = mbr_uid_to_uuid(euid, currentUserUuid); + if (ret != 0) { + secerror("failed to get UUID for user(%d) - %d", euid, ret); + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:basename uuid:nil]; + } + NSUUID *userUuid = [[NSUUID alloc] initWithUUIDBytes:currentUserUuid]; + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:basename uuid:userUuid]; +#else + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:basename uuid:nil]; +#endif // TARGET_OS_IPHONE +} + + (NSInteger)fuzzyDaysSinceDate:(NSDate*)date { // Sentinel: it didn't happen at all @@ -222,6 +289,38 @@ const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; } } ++ (NSInteger)fuzzyInteger:(NSInteger)num +{ + NSInteger sign = 1; + if(num < 0) { + sign = -1; + num = -num; + } + + // Differentiate zero and non-zero.... + if(num == 0) { + return 0; + } + + if(num <= 5) { + return sign*5; + } + + // Otherwise, round to the nearest five + NSInteger mod = num % 5; + + if(mod <= 2) { + return sign*(num - mod); + } else { + return sign*(num + (5-mod)); + } +} + ++ (NSNumber*)fuzzyNumber:(NSNumber*)num +{ + return [NSNumber numberWithInteger:[self fuzzyInteger:[num integerValue]]]; +} + // Instantiate lazily so unit tests can have clean databases each - (SFAnalyticsSQLiteStore*)database { @@ -314,11 +413,37 @@ const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; return result; } ++ (NSString*)hwModelID +{ + static NSString *hwModel = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ +#if TARGET_OS_SIMULATOR + // Asking for a real value in the simulator gives the results for the underlying mac. Not particularly useful. + hwModel = [NSString stringWithFormat:@"%s", getenv("SIMULATOR_MODEL_IDENTIFIER")]; +#elif TARGET_OS_OSX + size_t size; + sysctlbyname("hw.model", NULL, &size, NULL, 0); + char *sysctlString = malloc(size); + sysctlbyname("hw.model", sysctlString, &size, NULL, 0); + hwModel = [[NSString alloc] initWithUTF8String:sysctlString]; + free(sysctlString); +#else + struct utsname systemInfo; + uname(&systemInfo); + + hwModel = [NSString stringWithCString:systemInfo.machine + encoding:NSUTF8StringEncoding]; +#endif + }); + return hwModel; +} + (void)addOSVersionToEvent:(NSMutableDictionary*)eventDict { static dispatch_once_t onceToken; static NSString *build = NULL; static NSString *product = NULL; + static NSString *modelID = nil; static BOOL internal = NO; dispatch_once(&onceToken, ^{ NSDictionary *version = CFBridgingRelease(_CFCopySystemVersionDictionary()); @@ -327,6 +452,8 @@ const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; build = version[(__bridge NSString *)_kCFSystemVersionBuildVersionKey]; product = version[(__bridge NSString *)_kCFSystemVersionProductNameKey]; internal = os_variant_has_internal_diagnostics("com.apple.security"); + + modelID = [self hwModelID]; }); if (build) { eventDict[SFAnalyticsEventBuild] = build; @@ -334,6 +461,9 @@ const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; if (product) { eventDict[SFAnalyticsEventProduct] = product; } + if (modelID) { + eventDict[SFAnalyticsEventModelID] = modelID; + } if (internal) { eventDict[SFAnalyticsEventInternal] = @YES; } diff --git a/Analytics/SFAnalytics.plist b/Analytics/SFAnalytics.plist index 76b0892b..3004659b 100644 --- a/Analytics/SFAnalytics.plist +++ b/Analytics/SFAnalytics.plist @@ -4,6 +4,8 @@ KeySyncTopic + uploadSizeLimit + 1000000 splunk_allowInsecureCertificate splunk_topic @@ -13,6 +15,8 @@ CloudServicesTopic + uploadSizeLimit + 1000000 splunk_allowInsecureCertificate splunk_topic @@ -24,6 +28,8 @@ TrustTopic + uploadSizeLimit + 1000000 splunk_allowInsecureCertificate splunk_topic @@ -35,6 +41,8 @@ TransparencyTopic + uploadSizeLimit + 10000 splunk_allowInsecureCertificate splunk_topic @@ -42,5 +50,18 @@ splunk_bagURL https://metrics-config.icloud.com/config/TransparencyAnalytics + NetworkingTopic + + uploadSizeLimit + 1000000 + splunk_allowInsecureCertificate + + splunk_topic + xp_swe_network_perf + splunk_bagURL + https://xp.apple.com/config/1/report/xp_swe_network_perf + disableClientId + + diff --git a/Analytics/SFAnalyticsDefines.h b/Analytics/SFAnalyticsDefines.h index 2291ca02..06bff295 100644 --- a/Analytics/SFAnalyticsDefines.h +++ b/Analytics/SFAnalyticsDefines.h @@ -38,6 +38,7 @@ extern NSString* const SFAnalyticsColumnSoftFailureCount; extern NSString* const SFAnalyticsColumnSampleValue; extern NSString* const SFAnalyticsColumnSampleName; +extern NSString* const SFAnalyticsPostTime; extern NSString* const SFAnalyticsEventTime; extern NSString* const SFAnalyticsEventType; extern NSString* const SFAnalyticsEventTypeErrorEvent; @@ -60,6 +61,7 @@ extern NSString* const SFAnalyticsTopicCloudServices; extern NSString* const SFAnalyticsTopicKeySync; extern NSString* const SFAnalyticsTopicTrust; extern NSString* const SFAnalyticsTopicTransparency; +extern NSString* const SFAnalyticsTopicNetworking; typedef NS_ENUM(NSInteger, SFAnalyticsEventClass) { SFAnalyticsEventClassSuccess, diff --git a/Analytics/SFAnalyticsSQLiteStore.h b/Analytics/SFAnalyticsSQLiteStore.h index 16531fa5..c7bbade4 100644 --- a/Analytics/SFAnalyticsSQLiteStore.h +++ b/Analytics/SFAnalyticsSQLiteStore.h @@ -23,8 +23,8 @@ #if __OBJC2__ -#import "Analytics/SQLite/SFSQLite.h" -#import "SFAnalytics.h" +#import +#import @interface SFAnalyticsSQLiteStore : SFSQLite diff --git a/Analytics/SFAnalyticsSQLiteStore.m b/Analytics/SFAnalyticsSQLiteStore.m index 872b0d2b..11fe71f3 100644 --- a/Analytics/SFAnalyticsSQLiteStore.m +++ b/Analytics/SFAnalyticsSQLiteStore.m @@ -79,6 +79,7 @@ NSString* const SFAnalyticsUploadDate = @"upload_date"; if (!self.isOpen) { NSError* error = nil; if (![self openWithError:&error]) { + secerror("SFAnalytics: failed to open analytics db: %@", error); return NO; } secnotice("SFAnalytics", "successfully opened analytics db"); diff --git a/Analytics/SQLite/SFSQLite.m b/Analytics/SQLite/SFSQLite.m index fcde86f7..9daac349 100644 --- a/Analytics/SQLite/SFSQLite.m +++ b/Analytics/SQLite/SFSQLite.m @@ -28,6 +28,7 @@ #include #include #import "utilities/debugging.h" +#import "utilities/simulatecrash_assert.h" #include #define kSFSQLiteBusyTimeout (5*60*1000) @@ -300,7 +301,6 @@ allDone: */ - (void)attemptProperDatabasePermissions { -#if TARGET_OS_IPHONE NSFileManager* fm = [NSFileManager defaultManager]; [fm setAttributes:@{NSFilePosixPermissions : [NSNumber numberWithShort:0666]} ofItemAtPath:_path @@ -311,7 +311,6 @@ allDone: [fm setAttributes:@{NSFilePosixPermissions : [NSNumber numberWithShort:0666]} ofItemAtPath:[NSString stringWithFormat:@"%@-shm",_path] error:nil]; -#endif } - (BOOL)openWithError:(NSError **)error { @@ -340,7 +339,12 @@ allDone: #endif int rc = sqlite3_open_v2([arcSafePath fileSystemRepresentation], &_db, flags, NULL); if (rc != SQLITE_OK) { - localError = [NSError errorWithDomain:NSCocoaErrorDomain code:rc userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Error opening db at %@, rc=%d(0x%x)", _path, rc, rc]}]; + int reportedErrno = sqlite3_system_errno(_db); + + localError = [NSError errorWithDomain:NSCocoaErrorDomain code:rc userInfo:@{ + NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Error opening db at %@, rc=%d(0x%x), errno=%d(0x%x)", + _path, rc, rc, reportedErrno, reportedErrno], + }]; goto done; } @@ -911,7 +915,7 @@ done: - (NSString *)_tableNameForClass:(Class)objectClass { NSString *className = [objectClass SFSQLiteClassName]; if (![className hasPrefix:_objectClassPrefix]) { - secerror("sfsqlite: %@", [NSString stringWithFormat:@"Object class \"%@\" does not have prefix \"%@\"", className, _objectClassPrefix]); + secerror("sfsqlite: Object class \"%@\" does not have prefix \"%@\"", className, _objectClassPrefix); return nil; } return [className substringFromIndex:_objectClassPrefix.length]; diff --git a/CMS/CMSDecoder.h b/CMS/CMSDecoder.h index 031ad4a4..30e4f01c 100644 --- a/CMS/CMSDecoder.h +++ b/CMS/CMSDecoder.h @@ -68,7 +68,7 @@ typedef CF_ENUM(uint32_t, CMSSignerStatus) { * Create a CMSDecoder. Result must eventually be freed via CFRelease(). */ OSStatus CMSDecoderCreate(CMSDecoderRef * __nonnull CF_RETURNS_RETAINED cmsDecoderOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Feed raw bytes of the message to be decoded into the decoder. Can be called @@ -80,7 +80,7 @@ OSStatus CMSDecoderUpdateMessage( CMSDecoderRef cmsDecoder, const void *msgBytes, size_t msgBytesLen) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming; @@ -89,7 +89,7 @@ OSStatus CMSDecoderUpdateMessage( * message. */ OSStatus CMSDecoderFinalizeMessage(CMSDecoderRef cmsDecoder) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * A signed CMS message optionally includes the data which was signed. If the @@ -105,7 +105,7 @@ OSStatus CMSDecoderFinalizeMessage(CMSDecoderRef cmsDecoder) OSStatus CMSDecoderSetDetachedContent( CMSDecoderRef cmsDecoder, CFDataRef detachedContent) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the detached content specified in CMSDecoderSetDetachedContent(). @@ -115,7 +115,7 @@ OSStatus CMSDecoderSetDetachedContent( OSStatus CMSDecoderCopyDetachedContent( CMSDecoderRef cmsDecoder, CFDataRef * __nonnull CF_RETURNS_RETAINED detachedContentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); #if SEC_OS_OSX /* @@ -125,7 +125,7 @@ OSStatus CMSDecoderCopyDetachedContent( OSStatus CMSDecoderSetSearchKeychain( CMSDecoderRef cmsDecoder, CFTypeRef keychainOrArray) - API_DEPRECATED_WITH_REPLACEMENT("SecKeychainSetSearchList",macos(10.5, 10.13)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecKeychainSetSearchList",macos(10.5, 10.13)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #endif // SEC_OS_OSX /* @@ -136,7 +136,7 @@ OSStatus CMSDecoderSetSearchKeychain( OSStatus CMSDecoderGetNumSigners( CMSDecoderRef cmsDecoder, size_t *numSignersOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the status of a CMS message's signature. A CMS message can @@ -220,7 +220,7 @@ OSStatus CMSDecoderCopySignerStatus( CMSSignerStatus * __nullable signerStatusOut, /* optional; RETURNED */ SecTrustRef * __nullable CF_RETURNS_RETAINED secTrustOut, /* optional; RETURNED */ OSStatus * __nullable certVerifyResultCodeOut) /* optional; RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the email address of signer 'signerIndex' of a CMS message, if @@ -235,7 +235,7 @@ OSStatus CMSDecoderCopySignerEmailAddress( CMSDecoderRef cmsDecoder, size_t signerIndex, CFStringRef * __nonnull CF_RETURNS_RETAINED signerEmailAddressOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the certificate of signer 'signerIndex' of a CMS message, if @@ -250,7 +250,7 @@ OSStatus CMSDecoderCopySignerCert( CMSDecoderRef cmsDecoder, size_t signerIndex, SecCertificateRef * __nonnull CF_RETURNS_RETAINED signerCertOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Determine whether a CMS message was encrypted. Returns TRUE if so, FALSE if not. @@ -262,7 +262,7 @@ OSStatus CMSDecoderCopySignerCert( OSStatus CMSDecoderIsContentEncrypted( CMSDecoderRef cmsDecoder, Boolean *isEncryptedOut) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if @@ -274,7 +274,7 @@ OSStatus CMSDecoderIsContentEncrypted( OSStatus CMSDecoderCopyEncapsulatedContentType( CMSDecoderRef cmsDecoder, CFDataRef * __nonnull CF_RETURNS_RETAINED eContentTypeOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain an array of all of the certificates in a message. Elements of the @@ -287,7 +287,7 @@ OSStatus CMSDecoderCopyEncapsulatedContentType( OSStatus CMSDecoderCopyAllCerts( CMSDecoderRef cmsDecoder, CFArrayRef * __nonnull CF_RETURNS_RETAINED certsOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the actual message content (payload), if any. If the message was @@ -298,7 +298,7 @@ OSStatus CMSDecoderCopyAllCerts( OSStatus CMSDecoderCopyContent( CMSDecoderRef cmsDecoder, CFDataRef * __nonnull CF_RETURNS_RETAINED contentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the signing time of signer 'signerIndex' of a CMS message, if @@ -314,7 +314,7 @@ OSStatus CMSDecoderCopySignerSigningTime( CMSDecoderRef cmsDecoder, size_t signerIndex, CFAbsoluteTime *signingTime) /* RETURNED */ - __API_AVAILABLE(macos(10.8)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.8)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the timestamp of signer 'signerIndex' of a CMS message, if @@ -330,7 +330,7 @@ OSStatus CMSDecoderCopySignerTimestamp( CMSDecoderRef cmsDecoder, size_t signerIndex, CFAbsoluteTime *timestamp) /* RETURNED */ - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * Obtain the timestamp of signer 'signerIndex' of a CMS message, if @@ -347,7 +347,7 @@ OSStatus CMSDecoderCopySignerTimestampWithPolicy( CFTypeRef __nullable timeStampPolicy, size_t signerIndex, /* usually 0 */ CFAbsoluteTime *timestamp) /* RETURNED */ - API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * Obtain an array of the certificates in a timestamp response. Elements of the @@ -365,7 +365,7 @@ OSStatus CMSDecoderCopySignerTimestampCertificates( CMSDecoderRef cmsDecoder, size_t signerIndex, /* usually 0 */ CFArrayRef * __nonnull CF_RETURNS_RETAINED certificateRefs) /* RETURNED */ - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/CMS/CMSEncoder.h b/CMS/CMSEncoder.h index 276b72ef..02128b6c 100644 --- a/CMS/CMSEncoder.h +++ b/CMS/CMSEncoder.h @@ -62,13 +62,13 @@ CF_ASSUME_NONNULL_BEGIN typedef struct CF_BRIDGED_TYPE(id) _CMSEncoder *CMSEncoderRef; CFTypeID CMSEncoderGetTypeID(void) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Create a CMSEncoder. Result must eventually be freed via CFRelease(). */ OSStatus CMSEncoderCreate(CMSEncoderRef * __nonnull CF_RETURNS_RETAINED cmsEncoderOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); extern const CFStringRef kCMSEncoderDigestAlgorithmSHA1; extern const CFStringRef kCMSEncoderDigestAlgorithmSHA256; @@ -76,7 +76,7 @@ extern const CFStringRef kCMSEncoderDigestAlgorithmSHA256; OSStatus CMSEncoderSetSignerAlgorithm( CMSEncoderRef cmsEncoder, CFStringRef digestAlgorithm) - __API_AVAILABLE(macos(10.11)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.11)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Specify signers of the CMS message; implies that the message will be signed. @@ -91,7 +91,7 @@ OSStatus CMSEncoderSetSignerAlgorithm( OSStatus CMSEncoderAddSigners( CMSEncoderRef cmsEncoder, CFTypeRef signerOrArray) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain an array of signers as specified in CMSEncoderSetSigners(). @@ -101,7 +101,7 @@ OSStatus CMSEncoderAddSigners( OSStatus CMSEncoderCopySigners( CMSEncoderRef cmsEncoder, CFArrayRef * __nonnull CF_RETURNS_RETAINED signersOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Specify recipients of the message. Implies that the message will @@ -117,7 +117,7 @@ OSStatus CMSEncoderCopySigners( OSStatus CMSEncoderAddRecipients( CMSEncoderRef cmsEncoder, CFTypeRef recipientOrArray) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain an array of recipients as specified in CMSEncoderSetRecipients(). @@ -128,7 +128,7 @@ OSStatus CMSEncoderAddRecipients( OSStatus CMSEncoderCopyRecipients( CMSEncoderRef cmsEncoder, CFArrayRef * __nonnull CF_RETURNS_RETAINED recipientsOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * A signed message optionally includes the data to be signed. If the message @@ -144,7 +144,7 @@ OSStatus CMSEncoderCopyRecipients( OSStatus CMSEncoderSetHasDetachedContent( CMSEncoderRef cmsEncoder, Boolean detachedContent) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain a Boolean indicating whether the current message will have detached @@ -155,7 +155,7 @@ OSStatus CMSEncoderSetHasDetachedContent( OSStatus CMSEncoderGetHasDetachedContent( CMSEncoderRef cmsEncoder, Boolean *detachedContentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); #if SEC_OS_OSX /* @@ -173,7 +173,7 @@ OSStatus CMSEncoderGetHasDetachedContent( OSStatus CMSEncoderSetEncapsulatedContentType( CMSEncoderRef cmsEncoder, const CSSM_OID *eContentType) - API_DEPRECATED_WITH_REPLACEMENT("CMSEncoderSetEncapsulatedContentTypeOID", macos(10.5, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("CMSEncoderSetEncapsulatedContentTypeOID", macos(10.5, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #endif // SEC_OS_OSX /* @@ -191,7 +191,7 @@ OSStatus CMSEncoderSetEncapsulatedContentType( OSStatus CMSEncoderSetEncapsulatedContentTypeOID( CMSEncoderRef cmsEncoder, CFTypeRef eContentTypeOID) - __API_AVAILABLE(macos(10.7)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.7)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the eContentType OID specified in CMSEncoderSetEncapsulatedContentType(). @@ -204,7 +204,7 @@ OSStatus CMSEncoderSetEncapsulatedContentTypeOID( OSStatus CMSEncoderCopyEncapsulatedContentType( CMSEncoderRef cmsEncoder, CFDataRef * __nonnull CF_RETURNS_RETAINED eContentTypeOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Signed CMS messages can contain arbitrary sets of certificates beyond those @@ -229,7 +229,7 @@ OSStatus CMSEncoderCopyEncapsulatedContentType( OSStatus CMSEncoderAddSupportingCerts( CMSEncoderRef cmsEncoder, CFTypeRef certOrArray) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the SecCertificates provided in CMSEncoderAddSupportingCerts(). @@ -240,7 +240,7 @@ OSStatus CMSEncoderAddSupportingCerts( OSStatus CMSEncoderCopySupportingCerts( CMSEncoderRef cmsEncoder, CFArrayRef * __nonnull CF_RETURNS_RETAINED certsOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Standard signed attributes, optionally specified in @@ -285,7 +285,7 @@ typedef CF_OPTIONS(uint32_t, CMSSignedAttributes) { OSStatus CMSEncoderAddSignedAttributes( CMSEncoderRef cmsEncoder, CMSSignedAttributes signedAttributes) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Specification of what certificates to include in a signed message. @@ -313,7 +313,7 @@ typedef CF_ENUM(uint32_t, CMSCertificateChainMode) { OSStatus CMSEncoderSetCertificateChainMode( CMSEncoderRef cmsEncoder, CMSCertificateChainMode chainMode) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain indication of which signer certs are to be included @@ -322,7 +322,7 @@ OSStatus CMSEncoderSetCertificateChainMode( OSStatus CMSEncoderGetCertificateChainMode( CMSEncoderRef cmsEncoder, CMSCertificateChainMode *chainModeOut) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Feed content bytes into the encoder. @@ -333,7 +333,7 @@ OSStatus CMSEncoderUpdateContent( CMSEncoderRef cmsEncoder, const void *content, size_t contentLen) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Finish encoding the message and obtain the encoded result. @@ -342,7 +342,7 @@ OSStatus CMSEncoderUpdateContent( OSStatus CMSEncoderCopyEncodedContent( CMSEncoderRef cmsEncoder, CFDataRef * __nonnull CF_RETURNS_RETAINED encodedContentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); #if TARGET_OS_OSX /* @@ -377,7 +377,7 @@ OSStatus CMSEncode( const void * content, size_t contentLen, CFDataRef * __nonnull CF_RETURNS_RETAINED encodedContentOut) /* RETURNED */ - API_DEPRECATED_WITH_REPLACEMENT("CMSEncodeContent", macos(10.5, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("CMSEncodeContent", macos(10.5, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #endif // TARGET_OS_OSX /* @@ -410,20 +410,20 @@ OSStatus CMSEncodeContent( const void *content, size_t contentLen, CFDataRef * __nullable CF_RETURNS_RETAINED encodedContentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.7)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.7)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); OSStatus CMSEncoderCopySignerTimestamp( CMSEncoderRef cmsEncoder, size_t signerIndex, /* usually 0 */ CFAbsoluteTime *timestamp) /* RETURNED */ - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); OSStatus CMSEncoderCopySignerTimestampWithPolicy( CMSEncoderRef cmsEncoder, CFTypeRef __nullable timeStampPolicy, size_t signerIndex, /* usually 0 */ CFAbsoluteTime *timestamp) /* RETURNED */ - API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/CMS/CMSPrivate.h b/CMS/CMSPrivate.h index 548a2792..b8a5c137 100644 --- a/CMS/CMSPrivate.h +++ b/CMS/CMSPrivate.h @@ -115,7 +115,7 @@ OSStatus CMSEncoderSetAppleExpirationTime( void CmsMessageSetTSAContext(CMSEncoderRef cmsEncoder, CFTypeRef tsaContext) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); /*** *** Private CMSDecoder routines diff --git a/CMS/SecCmsBase.h b/CMS/SecCmsBase.h index 44f7eade..77ec4ac5 100644 --- a/CMS/SecCmsBase.h +++ b/CMS/SecCmsBase.h @@ -69,9 +69,9 @@ typedef SecAsn1AlgId SECAlgorithmID; @discussion XXX This should probably move to SecKey.h */ #if TARGET_OS_OSX -typedef SecKeyRef SecSymmetricKeyRef API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +typedef SecKeyRef SecSymmetricKeyRef API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else -typedef void * SecSymmetricKeyRef API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +typedef void * SecSymmetricKeyRef API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif /*! @@ -173,7 +173,7 @@ typedef void (*SecCmsContentCallback)(void *arg, const char *buf, size_t len); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" typedef SecSymmetricKeyRef(*SecCmsGetDecryptKeyCallback)(void *arg, SECAlgorithmID *algid) - API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop /*! diff --git a/CMS/SecCmsContentInfo.h b/CMS/SecCmsContentInfo.h index c799eb43..2a4eafeb 100644 --- a/CMS/SecCmsContentInfo.h +++ b/CMS/SecCmsContentInfo.h @@ -71,7 +71,7 @@ SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo); */ extern CSSM_DATA_PTR SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -80,7 +80,7 @@ SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) */ extern const SecAsn1Item * SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -99,7 +99,7 @@ SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo); */ extern CSSM_OID * SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -108,7 +108,7 @@ SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) */ extern SecAsn1Oid * SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -143,7 +143,7 @@ SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo) */ extern OSStatus SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -157,7 +157,7 @@ SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinf */ extern OSStatus SecCmsContentInfoSetContentData(SecCmsContentInfoRef cinfo, CFDataRef data, Boolean detached) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -173,7 +173,7 @@ SecCmsContentInfoSetContentData(SecCmsContentInfoRef cinfo, CFDataRef data, Bool */ extern OSStatus SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -186,7 +186,7 @@ SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRe */ extern OSStatus SecCmsContentInfoSetContentSignedData(SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // TARGET_OS_OSX #if TARGET_OS_OSX @@ -202,7 +202,7 @@ SecCmsContentInfoSetContentSignedData(SecCmsContentInfoRef cinfo, SecCmsSignedDa */ extern OSStatus SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -215,7 +215,7 @@ SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInf */ extern OSStatus SecCmsContentInfoSetContentEnvelopedData(SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -231,7 +231,7 @@ SecCmsContentInfoSetContentEnvelopedData(SecCmsContentInfoRef cinfo, SecCmsEnvel */ extern OSStatus SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -244,7 +244,7 @@ SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfo */ extern OSStatus SecCmsContentInfoSetContentDigestedData(SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -260,7 +260,7 @@ SecCmsContentInfoSetContentDigestedData(SecCmsContentInfoRef cinfo, SecCmsDigest */ extern OSStatus SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -273,41 +273,41 @@ SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInf */ extern OSStatus SecCmsContentInfoSetContentEncryptedData(SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX OSStatus SecCmsContentInfoSetContentOther(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached, const CSSM_OID *eContentType) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX OSStatus SecCmsContentInfoSetContentOther(SecCmsContentInfoRef cinfo, SecAsn1Item *data, Boolean detached, const SecAsn1Oid *eContentType) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX extern OSStatus SecCmsContentInfoSetContentEncAlg(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, SECOidTag bulkalgtag, CSSM_DATA_PTR parameters, int keysize) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX extern OSStatus SecCmsContentInfoSetContentEncAlg(SecCmsContentInfoRef cinfo, SECOidTag bulkalgtag, const SecAsn1Item *parameters, int keysize) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX extern OSStatus SecCmsContentInfoSetContentEncAlgID(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, SECAlgorithmID *algid, int keysize) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX extern OSStatus SecCmsContentInfoSetContentEncAlgID(SecCmsContentInfoRef cinfo, SECAlgorithmID *algid, int keysize) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !!TARGET_OS_OSX /*! @@ -315,14 +315,14 @@ SecCmsContentInfoSetContentEncAlgID(SecCmsContentInfoRef cinfo, */ extern void SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey) - API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); /*! @function */ extern SecSymmetricKeyRef SecCmsContentInfoGetBulkKey(SecCmsContentInfoRef cinfo) - API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); /*! @function diff --git a/CMS/SecCmsDecoder.h b/CMS/SecCmsDecoder.h index b1eb50ec..1098f80d 100644 --- a/CMS/SecCmsDecoder.h +++ b/CMS/SecCmsDecoder.h @@ -68,7 +68,7 @@ SecCmsDecoderCreate(SecArenaPoolRef arena, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsDecoderRef *outDecoder) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -94,7 +94,7 @@ SecCmsDecoderCreate(SecCmsContentCallback cb, void *cb_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsDecoderRef *outDecoder) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -161,7 +161,7 @@ SecCmsMessageDecode(const CSSM_DATA *encodedMessage, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsMessageRef *outMessage) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -190,7 +190,7 @@ SecCmsMessageDecode(const SecAsn1Item *encodedMessage, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsMessageRef *outMessage) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX diff --git a/CMS/SecCmsDigestContext.h b/CMS/SecCmsDigestContext.h index 159a2827..0a6e0194 100644 --- a/CMS/SecCmsDigestContext.h +++ b/CMS/SecCmsDigestContext.h @@ -44,7 +44,7 @@ __BEGIN_DECLS #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern SecCmsDigestContextRef SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) - API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop /*! @@ -70,7 +70,7 @@ SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx); */ extern void SecCmsDigestContextDestroy(SecCmsDigestContextRef cmsdigcx) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // TARGET_OS_IPHONE #if TARGET_OS_OSX @@ -83,7 +83,7 @@ SecCmsDigestContextDestroy(SecCmsDigestContextRef cmsdigcx) extern OSStatus SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef arena, CSSM_DATA_PTR **digestsp) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #endif // TARGET_OS_OSX diff --git a/CMS/SecCmsDigestedData.h b/CMS/SecCmsDigestedData.h index 6fc48c99..466b3139 100644 --- a/CMS/SecCmsDigestedData.h +++ b/CMS/SecCmsDigestedData.h @@ -51,7 +51,7 @@ __BEGIN_DECLS #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern SecCmsDigestedDataRef SecCmsDigestedDataCreate(SecCmsMessageRef cmsg, SECAlgorithmID *digestalg) - API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop /*! diff --git a/CMS/SecCmsEncoder.h b/CMS/SecCmsEncoder.h index 102c39af..f43037ac 100644 --- a/CMS/SecCmsEncoder.h +++ b/CMS/SecCmsEncoder.h @@ -77,7 +77,7 @@ SecCmsEncoderCreate(SecCmsMessageRef cmsg, SecCmsGetDecryptKeyCallback encrypt_key_cb, void *encrypt_key_cb_arg, SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests, SecCmsEncoderRef *outEncoder) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -107,7 +107,7 @@ SecCmsEncoderCreate(SecCmsMessageRef cmsg, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback encrypt_key_cb, void *encrypt_key_cb_arg, SecCmsEncoderRef *outEncoder) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -157,7 +157,7 @@ SecCmsEncoderFinish(SecCmsEncoderRef encoder); extern OSStatus SecCmsMessageEncode(SecCmsMessageRef cmsg, const CSSM_DATA *input, SecArenaPoolRef arena, CSSM_DATA_PTR outBer) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -172,7 +172,7 @@ SecCmsMessageEncode(SecCmsMessageRef cmsg, const CSSM_DATA *input, SecArenaPoolR extern OSStatus SecCmsMessageEncode(SecCmsMessageRef cmsg, const SecAsn1Item *input, CFMutableDataRef outBer) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX __END_DECLS diff --git a/CMS/SecCmsMessage.h b/CMS/SecCmsMessage.h index 497c4677..7cbb8277 100644 --- a/CMS/SecCmsMessage.h +++ b/CMS/SecCmsMessage.h @@ -55,7 +55,7 @@ __BEGIN_DECLS */ extern SecCmsMessageRef SecCmsMessageCreate(SecArenaPoolRef poolp) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX @@ -69,7 +69,7 @@ SecCmsMessageCreate(SecArenaPoolRef poolp) */ extern SecCmsMessageRef SecCmsMessageCreate(void) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX @@ -119,7 +119,7 @@ SecCmsMessageGetContentInfo(SecCmsMessageRef cmsg); #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern CSSM_DATA_PTR SecCmsMessageGetContent(SecCmsMessageRef cmsg) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -130,7 +130,7 @@ SecCmsMessageGetContent(SecCmsMessageRef cmsg) */ extern const SecAsn1Item * SecCmsMessageGetContent(SecCmsMessageRef cmsg) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! diff --git a/CMS/SecCmsRecipientInfo.h b/CMS/SecCmsRecipientInfo.h index f57481fd..66db12de 100644 --- a/CMS/SecCmsRecipientInfo.h +++ b/CMS/SecCmsRecipientInfo.h @@ -47,7 +47,7 @@ __BEGIN_DECLS */ extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreate(SecCmsMessageRef cmsg, SecCertificateRef cert) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX @@ -59,7 +59,7 @@ SecCmsRecipientInfoCreate(SecCmsMessageRef cmsg, SecCertificateRef cert) */ extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreate(SecCmsEnvelopedDataRef envd, SecCertificateRef cert) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX @@ -70,14 +70,14 @@ extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsEnvelopedDataRef envd, const SecAsn1Item *subjKeyID, SecPublicKeyRef pubKey) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX @@ -85,12 +85,12 @@ SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsEnvelopedDataRef envd, extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsMessageRef cmsg, SecCertificateRef cert) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsEnvelopedDataRef envd, SecCertificateRef cert) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX diff --git a/CMS/SecCmsSignedData.h b/CMS/SecCmsSignedData.h index f74f89b2..a6e3c2a2 100644 --- a/CMS/SecCmsSignedData.h +++ b/CMS/SecCmsSignedData.h @@ -165,7 +165,7 @@ SecCmsSignedDataContainsCertsOrCrls(SecCmsSignedDataRef sigd); #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern CSSM_DATA_PTR * SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -174,7 +174,7 @@ SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) */ extern SecAsn1Item * * SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -200,7 +200,7 @@ SecCmsSignedDataCreateCertsOnly(SecCmsMessageRef cmsg, SecCertificateRef cert, B */ extern OSStatus SecCmsSignedDataSetDigestContext(SecCmsSignedDataRef sigd, SecCmsDigestContextRef digestContext) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macos, iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macos, macCatalyst); #endif #if TARGET_OS_OSX @@ -214,7 +214,7 @@ extern OSStatus SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, SECAlgorithmID **digestalgs, CSSM_DATA_PTR *digests) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #endif diff --git a/CMS/SecCmsSignerInfo.h b/CMS/SecCmsSignerInfo.h index f3f80d6e..095950c4 100644 --- a/CMS/SecCmsSignerInfo.h +++ b/CMS/SecCmsSignerInfo.h @@ -44,13 +44,13 @@ __BEGIN_DECLS #if TARGET_OS_OSX extern SecCmsSignerInfoRef SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag digestalgtag) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OSX extern SecCmsSignerInfoRef SecCmsSignerInfoCreate(SecCmsSignedDataRef sigd, SecIdentityRef identity, SECOidTag digestalgtag) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -58,12 +58,12 @@ SecCmsSignerInfoCreate(SecCmsSignedDataRef sigd, SecIdentityRef identity, SECOid #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern SecCmsSignerInfoRef SecCmsSignerInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX extern SecCmsSignerInfoRef SecCmsSignerInfoCreateWithSubjKeyID(SecCmsSignedDataRef sigd, const SecAsn1Item *subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -73,7 +73,7 @@ SecCmsSignerInfoCreateWithSubjKeyID(SecCmsSignedDataRef sigd, const SecAsn1Item */ extern void SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #endif /*! @@ -291,26 +291,26 @@ SecCertificateRef SecCmsSignerInfoCopyCertFromEncryptionKeyPreference(SecCmsSign extern OSStatus SecCmsSignerInfoVerifyUnAuthAttrs(SecCmsSignerInfoRef signerinfo) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); extern OSStatus SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeStampPolicy) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern CSSM_DATA * SecCmsSignerInfoGetEncDigest(SecCmsSignerInfoRef signerinfo) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma clang diagnostic pop extern CFArrayRef SecCmsSignerInfoGetTimestampCertList(SecCmsSignerInfoRef signerinfo) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); extern SecCertificateRef SecCmsSignerInfoGetTimestampSigningCert(SecCmsSignerInfoRef signerinfo) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function @@ -321,7 +321,7 @@ SecCmsSignerInfoGetTimestampSigningCert(SecCmsSignerInfoRef signerinfo) */ OSStatus SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function @@ -332,7 +332,7 @@ SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stim */ OSStatus SecCmsSignerInfoGetTimestampTimeWithPolicy(SecCmsSignerInfoRef sinfo, CFTypeRef timeStampPolicy, CFAbsoluteTime *stime) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function @@ -342,7 +342,7 @@ SecCmsSignerInfoGetTimestampTimeWithPolicy(SecCmsSignerInfoRef sinfo, CFTypeRef #pragma clang diagnostic ignored "-Wdeprecated-declarations" OSStatus SecCmsSignerInfoAddTimeStamp(SecCmsSignerInfoRef signerinfo, CSSM_DATA *tstoken) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma clang diagnostic pop #endif // TARGET_OS_OSX diff --git a/CircleJoinRequested/Applicant.m b/CircleJoinRequested/Applicant.m index 5cce5177..58692652 100644 --- a/CircleJoinRequested/Applicant.m +++ b/CircleJoinRequested/Applicant.m @@ -13,14 +13,10 @@ -(id)initWithPeerInfo:(SOSPeerInfoRef)peerInfo { - self = [super init]; - if (!self) { - return self; - } - - self.rawPeerInfo = CFRetainSafe(peerInfo); - self.applicantUIState = ApplicantWaiting; - + if ((self = [super init])) { + self.rawPeerInfo = CFRetainSafe(peerInfo); + self.applicantUIState = ApplicantWaiting; + } return self; } diff --git a/CircleJoinRequested/CircleJoinRequested.m b/CircleJoinRequested/CircleJoinRequested.m index 38e7c8ea..88d42276 100644 --- a/CircleJoinRequested/CircleJoinRequested.m +++ b/CircleJoinRequested/CircleJoinRequested.m @@ -31,8 +31,7 @@ #import #import #import -#import -#import +#import #import #import #import @@ -144,6 +143,8 @@ static void keybagDidUnlock() NSError *localError = nil; CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; + + secnotice("followup", "Posting a follow up (for SOS) of type repair"); [cdpd postFollowUpWithContext:context error:&localError ]; secnotice("cjr", "account is icdp"); if(localError){ @@ -628,6 +629,8 @@ static void kickOutChoice(CFUserNotificationRef userNotification, CFOptionFlags CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; NSError *localError = nil; CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; + + secnotice("followup", "Posting a follow up (for SOS) of type repair"); [cdpd postFollowUpWithContext:context error:&localError ]; if(localError){ secnotice("cjr", "request to CoreCDP to follow up failed: %@", localError); @@ -772,6 +775,8 @@ static void askForCDPFollowup() { NSError *localError = nil; CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; + + secnotice("followup", "Posting a follow up (for SOS) of type repair"); [cdpd postFollowUpWithContext:context error:&localError ]; if(localError){ secnotice("cjr", "request to CoreCDP to follow up failed: %@", localError); @@ -910,6 +915,8 @@ static bool processEvents() NSError *localError = nil; CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; + + secnotice("followup", "Posting a follow up (for SOS) of type repair"); [cdpd postFollowUpWithContext:context error:&localError ]; if(localError){ secnotice("cjr", "request to CoreCDP to follow up failed: %@", localError); diff --git a/ISACLProtectedItems/KeychainItemsAclTest.sh b/ISACLProtectedItems/KeychainItemsAclTest.sh old mode 100644 new mode 100755 diff --git a/KVSKeychainSyncingProxy/CKDAKSLockMonitor.m b/KVSKeychainSyncingProxy/CKDAKSLockMonitor.m index 8686852b..f971c794 100644 --- a/KVSKeychainSyncingProxy/CKDAKSLockMonitor.m +++ b/KVSKeychainSyncingProxy/CKDAKSLockMonitor.m @@ -31,9 +31,7 @@ } - (instancetype)init { - self = [super init]; - - if (self) { + if ((self = [super init])) { XPCNotificationDispatcher* dispatcher = [XPCNotificationDispatcher dispatcher]; _queue = dispatch_queue_create("CKDAKSLockMonitor", NULL); @@ -86,6 +84,7 @@ } - (void) _onqueueRecheck { + dispatch_assert_queue(_queue); CFErrorRef aksError = NULL; bool locked = true; // Assume locked if we get an error diff --git a/KVSKeychainSyncingProxy/CKDKVSProxy.m b/KVSKeychainSyncingProxy/CKDKVSProxy.m index d586951c..84b79828 100644 --- a/KVSKeychainSyncingProxy/CKDKVSProxy.m +++ b/KVSKeychainSyncingProxy/CKDKVSProxy.m @@ -40,12 +40,10 @@ #include "keychain/SecureObjectSync/SOSARCDefines.h" #include "keychain/SecureObjectSync/SOSKVSKeys.h" #include -#include #include "SOSCloudKeychainConstants.h" #include -#include #include #import "XPCNotificationDispatcher.h" @@ -202,7 +200,7 @@ static NSString *kMonitorWroteInTimeSlice = @"TimeSlice"; } - (void)synchronizeStore { - [self.store pushWrites]; + [self.store pushWrites:[NSArray array] requiresForceSync:YES]; } - (id) objectForKey: (NSString*) key { @@ -336,9 +334,9 @@ static NSString *kMonitorWroteInTimeSlice = @"TimeSlice"; [[self store] addOneToOutGoing]; [self.store setObject:obj forKey:key]; } - }]; - - [self.store pushWrites]; + }]; + + [self.store pushWrites:[mutableValues allKeys] requiresForceSync:NO]; } - (void)setObjectsFromDictionary:(NSDictionary *)values diff --git a/KVSKeychainSyncingProxy/CKDKVSStore.h b/KVSKeychainSyncingProxy/CKDKVSStore.h index 4e4b87dd..f20f0bf0 100644 --- a/KVSKeychainSyncingProxy/CKDKVSStore.h +++ b/KVSKeychainSyncingProxy/CKDKVSStore.h @@ -25,7 +25,7 @@ - (NSDictionary*) copyAsDictionary; -- (void)pushWrites; +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync; - (BOOL)pullUpdates:(NSError**) failure; - (void)kvsStoreChanged: (NSNotification*) notification; diff --git a/KVSKeychainSyncingProxy/CKDKVSStore.m b/KVSKeychainSyncingProxy/CKDKVSStore.m index 03386203..c46a6a41 100644 --- a/KVSKeychainSyncingProxy/CKDKVSStore.m +++ b/KVSKeychainSyncingProxy/CKDKVSStore.m @@ -19,6 +19,9 @@ #import "Analytics/Clients/SOSAnalytics.h" +#include "keychain/SecureObjectSync/SOSKVSKeys.h" +#include + struct CKDKVSCounters { uint64_t synchronize; uint64_t synchronizeWithCompletionHandler; @@ -29,8 +32,6 @@ struct CKDKVSCounters { uint64_t synchronizeFailures; }; - - @interface CKDKVSStore () @property (readwrite, weak) UbiqitousKVSProxy* proxy; @property (readwrite) NSUbiquitousKeyValueStore* cloudStore; @@ -45,20 +46,20 @@ struct CKDKVSCounters { } - (instancetype)init { - self = [super init]; + if ((self = [super init])) { - self->_cloudStore = [NSUbiquitousKeyValueStore defaultStore]; - self->_proxy = nil; + self->_cloudStore = [NSUbiquitousKeyValueStore defaultStore]; + self->_proxy = nil; - if (!self.cloudStore) { - secerror("NO NSUbiquitousKeyValueStore defaultStore!!!"); - return nil; - } - self.perfQueue = dispatch_queue_create("CKDKVSStorePerfQueue", NULL); - self.perfCounters = calloc(1, sizeof(struct CKDKVSCounters)); + if (!self.cloudStore) { + secerror("NO NSUbiquitousKeyValueStore defaultStore!!!"); + return nil; + } + self.perfQueue = dispatch_queue_create("CKDKVSStorePerfQueue", NULL); + self.perfCounters = calloc(1, sizeof(struct CKDKVSCounters)); - [self setupSamplers]; - + [self setupSamplers]; + } return self; } @@ -106,13 +107,70 @@ struct CKDKVSCounters { }]; } -- (void)pushWrites { - [[self cloudStore] synchronize]; + +- (void)forceSynchronizeWithKVS +{ + secnoticeq("pushWrites", "requesting force synchronization with KVS on CloudKit"); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSError *error = nil; + bool success = [self pullUpdates:&error]; + if(!success || error != nil) { + secerror("pushWrites: failed to synchronize with KVS: %@", error); + } else { + secnoticeq("pushWrites", "successfully synced with KVS!"); + } + }); dispatch_async(self.perfQueue, ^{ self.perfCounters->synchronize++; }); } +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync +{ + secnoticeq("pushWrites", "Push writes"); + + if (SecKVSOnCloudKitIsEnabled() == NO) { + secnoticeq("pushWrites", "KVS on CloudKit not enabled"); + + [[self cloudStore] synchronize]; + dispatch_async(self.perfQueue, ^{ + self.perfCounters->synchronize++; + }); + return; + } + + if(requiresForceSync == YES) { + secnoticeq("pushWrites", "requested to force synchronize"); + [self forceSynchronizeWithKVS]; + return; + } + + //if KVS on CK is enabled we should only force sync rings, circles, and key parameters + secnoticeq("pushWrites", "KVS on CloudKit enabled. Evaluating changed keys"); + + if (keys == nil || [keys count] == 0){ + secnoticeq("pushWrites", "key set is empty, returning"); + return; + } + + __block BOOL proceedWithSync = NO; + [keys enumerateObjectsUsingBlock:^(NSString *kvsKey, NSUInteger idx, BOOL *stop) { + if ([kvsKey containsString:(__bridge_transfer NSString*)sRingPrefix] || + [kvsKey containsString:(__bridge_transfer NSString*)sCirclePrefix] || + [kvsKey containsString:(__bridge_transfer NSString*)kSOSKVSKeyParametersKey]) { + proceedWithSync = YES; + } + }]; + + if (proceedWithSync == NO) { + secnoticeq("pushWrites", "no keys to force push, returning"); + return; + } + + [self forceSynchronizeWithKVS]; +} + // Runs on the same thread that posted the notification, and that thread _may_ be the // kdkvsproxy_queue (see 30470419). Avoid deadlock by bouncing through global queue. - (void)kvsStoreChangedAsync:(NSNotification *)notification @@ -217,8 +275,10 @@ struct CKDKVSCounters { self.perfCounters->synchronize++; }); secnotice("fresh", "%s RETURNING FROM syncdefaultsd SWCH: %@", kWAIT2MINID, self); - [[self cloudStore] synchronize]; // Per olivier in , sync before getting values - secnotice("fresh", "%s RETURNING FROM syncdefaultsd SYNC: %@", kWAIT2MINID, self); + if(SecKVSOnCloudKitIsEnabled() == NO) { + [[self cloudStore] synchronize]; // Per olivier in , sync before getting values + secnotice("fresh", "%s RETURNING FROM syncdefaultsd SYNC: %@", kWAIT2MINID, self); + } } dispatch_semaphore_signal(freshSemaphore); }]; diff --git a/KVSKeychainSyncingProxy/CKDStore.h b/KVSKeychainSyncingProxy/CKDStore.h index ec68f709..3fec1119 100644 --- a/KVSKeychainSyncingProxy/CKDStore.h +++ b/KVSKeychainSyncingProxy/CKDStore.h @@ -22,7 +22,7 @@ - (NSDictionary*) copyAsDictionary; -- (void)pushWrites; +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync; - (BOOL)pullUpdates:(NSError**) failure; - (void)perfCounters:(void(^)(NSDictionary *counters))callback; diff --git a/KVSKeychainSyncingProxy/XPCNotificationDispatcher.m b/KVSKeychainSyncingProxy/XPCNotificationDispatcher.m index 3b6d7dca..0c010d13 100644 --- a/KVSKeychainSyncingProxy/XPCNotificationDispatcher.m +++ b/KVSKeychainSyncingProxy/XPCNotificationDispatcher.m @@ -61,9 +61,7 @@ static const char *kXPCNotificationNameKey = "Notification"; } - (instancetype) init { - self = [super init]; - - if (self) { + if ((self = [super init])) { self.queue = dispatch_queue_create("XPC Notification Dispatch", DISPATCH_QUEUE_SERIAL); self.listeners = [NSPointerArray weakObjectsPointerArray]; __weak typeof(self) weakSelf = self; diff --git a/KVSKeychainSyncingProxy/cloudkeychainproxy.m b/KVSKeychainSyncingProxy/cloudkeychainproxy.m index b0f39a4c..b3a56ba8 100644 --- a/KVSKeychainSyncingProxy/cloudkeychainproxy.m +++ b/KVSKeychainSyncingProxy/cloudkeychainproxy.m @@ -70,52 +70,129 @@ #import "CKDSecuritydAccount.h" #import "CKDKVSStore.h" #import "CKDAKSLockMonitor.h" +#import "SOSCloudKeychainConstants.h" +#include -void finalize_connection(void *not_used); -void handle_connection_event(const xpc_connection_t peer); -static void cloudkeychainproxy_peer_dictionary_handler(const xpc_connection_t peer, xpc_object_t event); - -static bool operation_put_dictionary(xpc_object_t event); -static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event); - -int ckdproxymain(int argc, const char *argv[]); #define PROXYXPCSCOPE "xpcproxy" -static void describeXPCObject(char *prefix, xpc_object_t object) -{ -//#ifndef NDEBUG - // This is useful for debugging. - if (object) - { - char *desc = xpc_copy_description(object); - secdebug(PROXYXPCSCOPE, "%s%s\n", prefix, desc); - free(desc); - } - else - secdebug(PROXYXPCSCOPE, "%s\n", prefix); +@interface CloudKeychainProxy : NSObject +-(id _Nullable) init; -//#endif +@property (nonatomic, retain) UbiqitousKVSProxy *proxyID; +@property (nonatomic, retain) xpc_connection_t listener; +@property (nonatomic, retain) dispatch_source_t sigterm_source; +@property (nonatomic, retain) NSURL *registrationFileName; + ++ (CloudKeychainProxy *) sharedObject; +- (void) cloudkeychainproxy_peer_dictionary_handler: (const xpc_connection_t) peer forEvent: (xpc_object_t) event; + +@end + +static void cloudkeychainproxy_event_handler(xpc_connection_t peer) +{ + if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) { + secinfo(PROXYXPCSCOPE, "expected XPC_TYPE_CONNECTION"); + return; + } + + xpc_object_t ent = xpc_connection_copy_entitlement_value(peer, "com.apple.CloudKeychainProxy.client"); + if (ent == NULL || xpc_get_type(ent) != XPC_TYPE_BOOL || xpc_bool_get_value(ent) != true) { + secnotice(PROXYXPCSCOPE, "cloudkeychainproxy_event_handler: rejected client %d", xpc_connection_get_pid(peer)); + xpc_connection_cancel(peer); + return; + } + + xpc_connection_set_target_queue(peer, [[CloudKeychainProxy sharedObject].proxyID ckdkvsproxy_queue]); + xpc_connection_set_event_handler(peer, ^(xpc_object_t event) + { + // We could handle other peer events (e.g.) disconnects, + // but we don't keep per-client state so there is no need. + if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { + [[CloudKeychainProxy sharedObject] cloudkeychainproxy_peer_dictionary_handler: peer forEvent: event]; + } + }); + + // This will tell the connection to begin listening for events. If you + // have some other initialization that must be done asynchronously, then + // you can defer this call until after that initialization is done. + xpc_connection_resume(peer); } -static NSObject *CreateNSObjectForCFXPCObjectFromKey(xpc_object_t xdict, const char * _Nonnull key) -{ - xpc_object_t xObj = xpc_dictionary_get_value(xdict, key); +static void finalize_connection(void *not_used) { + secinfo(PROXYXPCSCOPE, "finalize_connection"); + [[CloudKeychainProxy sharedObject].proxyID synchronizeStore]; + xpc_transaction_end(); +} +@implementation CloudKeychainProxy + +static CFStringRef kRegistrationFileName = CFSTR("com.apple.security.cloudkeychainproxy3.keysToRegister.plist"); + ++ (CloudKeychainProxy *) sharedObject { + static CloudKeychainProxy *sharedCKP = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedCKP = [CloudKeychainProxy new]; + }); + + return sharedCKP; +} + +-(id _Nullable) init { + if ((self = [super init])) { + _registrationFileName = (NSURL *)CFBridgingRelease(SecCopyURLForFileInPreferencesDirectory(kRegistrationFileName)); + _proxyID = [UbiqitousKVSProxy withAccount: [CKDSecuritydAccount securitydAccount] + store: [CKDKVSStore kvsInterface] + lockMonitor: [CKDAKSLockMonitor monitor] + persistence: _registrationFileName]; + + _listener = xpc_connection_create_mach_service(kCKPServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + xpc_connection_set_finalizer_f(_listener, finalize_connection); + xpc_connection_set_event_handler(_listener, ^(xpc_object_t object){ cloudkeychainproxy_event_handler(object); }); + + // It looks to me like there is insufficient locking to allow a request to come in on the XPC connection while doing the initial all items. + // Therefore I'm leaving the XPC connection suspended until that has time to process. + xpc_connection_resume(_listener); + + (void)signal(SIGTERM, SIG_IGN); + _sigterm_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, _proxyID.ckdkvsproxy_queue); + dispatch_source_set_event_handler(_sigterm_source, ^{ + secnotice(PROXYXPCSCOPE, "exiting due to SIGTERM"); + xpc_transaction_exit_clean(); + }); + dispatch_activate(_sigterm_source); + } + return self; +} + + +- (void) describeXPCObject: (char *) prefix withObject: (xpc_object_t) object { + if(object) { + char *desc = xpc_copy_description(object); + secinfo(PROXYXPCSCOPE, "%s%s", prefix, desc); + free(desc); + } else { + secinfo(PROXYXPCSCOPE, "%s", prefix); + } +} + +- (NSObject *) CreateNSObjectForCFXPCObjectFromKey: (xpc_object_t) xdict withKey: (const char * _Nonnull) key { + xpc_object_t xObj = xpc_dictionary_get_value(xdict, key); if (!xObj) { return nil; } - return (__bridge_transfer NSObject *)(_CFXPCCreateCFObjectFromXPCObject(xObj)); } -static NSArray *CreateArrayOfStringsForCFXPCObjectFromKey(xpc_object_t xdict, const char * _Nonnull key) { - NSObject * possibleArray = CreateNSObjectForCFXPCObjectFromKey(xdict, key); +- (NSArray *) CreateArrayOfStringsForCFXPCObjectFromKey: (xpc_object_t) xdict withKey: (const char * _Nonnull) key { + NSObject * possibleArray = [self CreateNSObjectForCFXPCObjectFromKey: xdict withKey: key]; - if (![possibleArray isNSArray__]) + if (![possibleArray isNSArray__]) { return nil; - + } + __block bool onlyStrings = true; [(NSArray*) possibleArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (![obj isNSString__]) { @@ -127,208 +204,187 @@ static NSArray *CreateArrayOfStringsForCFXPCObjectFromKey(xpc_object_ return onlyStrings ? (NSArray*) possibleArray : nil; } -static CFStringRef kRegistrationFileName = CFSTR("com.apple.security.cloudkeychainproxy3.keysToRegister.plist"); - -static UbiqitousKVSProxy *SharedProxy(void) { - static UbiqitousKVSProxy *sProxy = NULL; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sProxy = [UbiqitousKVSProxy withAccount: [CKDSecuritydAccount securitydAccount] - store: [CKDKVSStore kvsInterface] - lockMonitor: [CKDAKSLockMonitor monitor] - persistence: (NSURL *)CFBridgingRelease(SecCopyURLForFileInPreferencesDirectory(kRegistrationFileName))]; - }); - - return sProxy; -} - -static void sendAckResponse(const xpc_connection_t peer, xpc_object_t event) { +- (void) sendAckResponse: (const xpc_connection_t) peer forEvent: (xpc_object_t) event { xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) // Caller wanted an ACK, so give one - { + if (replyMessage) { // Caller wanted an ACK, so give one xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); xpc_connection_send_message(peer, replyMessage); } } -static void cloudkeychainproxy_peer_dictionary_handler(const xpc_connection_t peer, xpc_object_t event) -{ +- (void) cloudkeychainproxy_peer_dictionary_handler: (const xpc_connection_t) peer forEvent: (xpc_object_t) event { bool result = false; int err = 0; - require_action_string(xpc_get_type(event) == XPC_TYPE_DICTIONARY, xit, err = -51, "expected XPC_TYPE_DICTIONARY"); + @autoreleasepool { - const char *operation = xpc_dictionary_get_string(event, kMessageKeyOperation); - require_action(operation, xit, result = false); + require_action_string(xpc_get_type(event) == XPC_TYPE_DICTIONARY, xit, err = -51, "expected XPC_TYPE_DICTIONARY"); - // Check protocol version - uint64_t version = xpc_dictionary_get_uint64(event, kMessageKeyVersion); - secdebug(PROXYXPCSCOPE, "Reply version: %lld\n", version); - require_action(version == kCKDXPCVersion, xit, result = false); + const char *operation = xpc_dictionary_get_string(event, kMessageKeyOperation); + require_action(operation, xit, result = false); - // Operations - secdebug(PROXYXPCSCOPE, "Handling %s operation", operation); + // Check protocol version + uint64_t version = xpc_dictionary_get_uint64(event, kMessageKeyVersion); + secinfo(PROXYXPCSCOPE, "Reply version: %lld", version); + require_action(version == kCKDXPCVersion, xit, result = false); + + // Operations + secinfo(PROXYXPCSCOPE, "Handling %s operation", operation); - if (!strcmp(operation, kOperationPUTDictionary)) - { - operation_put_dictionary(event); - sendAckResponse(peer, event); - } - else if (!strcmp(operation, kOperationGETv2)) - { - operation_get_v2(peer, event); - // operationg_get_v2 sends the response - } - else if (!strcmp(operation, kOperationClearStore)) - { - [SharedProxy() clearStore]; - sendAckResponse(peer, event); - } - else if (!strcmp(operation, kOperationSynchronize)) - { - [SharedProxy() synchronizeStore]; - sendAckResponse(peer, event); - } - else if (!strcmp(operation, kOperationSynchronizeAndWait)) - { - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - secnotice(XPROXYSCOPE, "%s XPC request: %s", kWAIT2MINID, kOperationSynchronizeAndWait); - - [SharedProxy() waitForSynchronization:^(__unused NSDictionary *values, NSError *error) - { - secnotice(PROXYXPCSCOPE, "%s Result from [Proxy waitForSynchronization:]: %@", kWAIT2MINID, error); - - if (replyMessage) // Caller wanted an ACK, so give one - { - if (error) - { - xpc_object_t xerrobj = SecCreateXPCObjectWithCFError((__bridge CFErrorRef)(error)); - xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj); - } else { - xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); - } - xpc_connection_send_message(peer, replyMessage); - } - }]; - } - else if (!strcmp(operation, kOperationRegisterKeys)) - { - xpc_object_t xkeysToRegisterDict = xpc_dictionary_get_value(event, kMessageKeyValue); - - xpc_object_t xKTRallkeys = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageAllKeys); - - NSString* accountUUID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyAccountUUID); - - if (![accountUUID isKindOfClass:[NSString class]]) { - accountUUID = nil; - } - - NSDictionary *KTRallkeys = (__bridge_transfer NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xKTRallkeys)); - - [SharedProxy() registerKeys: KTRallkeys forAccount: accountUUID]; - sendAckResponse(peer, event); - - secdebug(PROXYXPCSCOPE, "RegisterKeys message sent"); - } - else if (!strcmp(operation, kOperationRemoveKeys)) - { - xpc_object_t xkeysToRemoveDict = xpc_dictionary_get_value(event, kMessageKeyValue); - - NSString* accountUUID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyAccountUUID); - - if (![accountUUID isKindOfClass:[NSString class]]) { - accountUUID = nil; - } - - NSArray *KTRallkeys = (__bridge_transfer NSArray *)(_CFXPCCreateCFObjectFromXPCObject(xkeysToRemoveDict)); - - [SharedProxy() removeKeys:KTRallkeys forAccount:accountUUID]; - sendAckResponse(peer, event); - - secdebug(PROXYXPCSCOPE, "RemoveKeys message sent"); - } - else if (!strcmp(operation, kOperationRequestSyncWithPeers)) - { - - NSArray * peerIDs = CreateArrayOfStringsForCFXPCObjectFromKey(event, kMessageKeyPeerIDList); - NSArray * backupPeerIDs = CreateArrayOfStringsForCFXPCObjectFromKey(event, kMesssgeKeyBackupPeerIDList); - - require_action(peerIDs && backupPeerIDs, xit, (secnotice(XPROXYSCOPE, "Bad call to sync with peers"), result = false)); - - [SharedProxy() requestSyncWithPeerIDs: peerIDs backupPeerIDs: backupPeerIDs]; - sendAckResponse(peer, event); - - secdebug(PROXYXPCSCOPE, "RequestSyncWithAllPeers reply sent"); - } - else if (!strcmp(operation, kOperationHasPendingSyncWithPeer)) { - NSString *peerID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyPeerID); - - BOOL hasPending = [SharedProxy() hasSyncPendingFor: peerID]; - - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) + if (!strcmp(operation, kOperationPUTDictionary)) { - xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, hasPending); - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "HasPendingSyncWithPeer reply sent"); + [self operation_put_dictionary: event]; + [self sendAckResponse: peer forEvent: event]; } - } - else if (!strcmp(operation, kOperationHasPendingKey)) { - NSString *peerID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyPeerID); - - BOOL hasPending = [SharedProxy() hasPendingKey: peerID]; - - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) + else if (!strcmp(operation, kOperationGETv2)) { - xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, hasPending); - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "HasIncomingMessageFromPeer reply sent"); + [self operation_get_v2: peer forEvent: event]; + // operationg_get_v2 sends the response } - } - else if (!strcmp(operation, kOperationRequestEnsurePeerRegistration)) - { - [SharedProxy() requestEnsurePeerRegistration]; - sendAckResponse(peer, event); - secdebug(PROXYXPCSCOPE, "RequestEnsurePeerRegistration reply sent"); - } - else if (!strcmp(operation, kOperationFlush)) - { - [SharedProxy() doAfterFlush:^{ - sendAckResponse(peer, event); - secdebug(PROXYXPCSCOPE, "flush reply sent"); - }]; - } - else if (!strcmp(operation, kOperationPerfCounters)) { - [SharedProxy() perfCounters:^(NSDictionary *counters){ + else if (!strcmp(operation, kOperationClearStore)) + { + [_proxyID clearStore]; + [self sendAckResponse: peer forEvent: event]; + } + else if (!strcmp(operation, kOperationSynchronize)) + { + [_proxyID synchronizeStore]; + [self sendAckResponse: peer forEvent: event]; + } + else if (!strcmp(operation, kOperationSynchronizeAndWait)) + { xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_object_t object = _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)counters); - xpc_dictionary_set_value(replyMessage, kMessageKeyValue, object); - xpc_connection_send_message(peer, replyMessage); - }]; - } - else - { - char *description = xpc_copy_description(event); - secdebug(PROXYXPCSCOPE, "Unknown op=%s request from pid %d: %s", operation, xpc_connection_get_pid(peer), description); - free(description); - } - result = true; + secnotice(XPROXYSCOPE, "%s XPC request: %s", kWAIT2MINID, kOperationSynchronizeAndWait); + + [_proxyID waitForSynchronization:^(__unused NSDictionary *values, NSError *error) + { + secnotice(PROXYXPCSCOPE, "%s Result from [Proxy waitForSynchronization:]: %@", kWAIT2MINID, error); + + if (replyMessage) // Caller wanted an ACK, so give one + { + if (error) + { + xpc_object_t xerrobj = SecCreateXPCObjectWithCFError((__bridge CFErrorRef)(error)); + xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj); + } else { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + } + xpc_connection_send_message(peer, replyMessage); + } + }]; + } + else if (!strcmp(operation, kOperationRegisterKeys)) + { + xpc_object_t xkeysToRegisterDict = xpc_dictionary_get_value(event, kMessageKeyValue); + + xpc_object_t xKTRallkeys = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageAllKeys); + + NSString* accountUUID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey:event withKey: kMessageKeyAccountUUID]; + + if (![accountUUID isKindOfClass:[NSString class]]) { + accountUUID = nil; + } + + NSDictionary *KTRallkeys = (__bridge_transfer NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xKTRallkeys)); + + [_proxyID registerKeys: KTRallkeys forAccount: accountUUID]; + [self sendAckResponse: peer forEvent: event]; + + secinfo(PROXYXPCSCOPE, "RegisterKeys message sent"); + } + else if (!strcmp(operation, kOperationRemoveKeys)) + { + xpc_object_t xkeysToRemoveDict = xpc_dictionary_get_value(event, kMessageKeyValue); + + NSString* accountUUID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey: event withKey: kMessageKeyAccountUUID]; + + if (![accountUUID isKindOfClass:[NSString class]]) { + accountUUID = nil; + } + + NSArray *KTRallkeys = (__bridge_transfer NSArray *)(_CFXPCCreateCFObjectFromXPCObject(xkeysToRemoveDict)); + + [_proxyID removeKeys:KTRallkeys forAccount:accountUUID]; + [self sendAckResponse: peer forEvent: event]; + + secinfo(PROXYXPCSCOPE, "RemoveKeys message sent"); + } + else if (!strcmp(operation, kOperationRequestSyncWithPeers)) + { + + NSArray * peerIDs = [self CreateArrayOfStringsForCFXPCObjectFromKey: event withKey: kMessageKeyPeerIDList]; + NSArray * backupPeerIDs = [self CreateArrayOfStringsForCFXPCObjectFromKey: event withKey: kMesssgeKeyBackupPeerIDList]; + + require_action(peerIDs && backupPeerIDs, xit, (secnotice(XPROXYSCOPE, "Bad call to sync with peers"), result = false)); + + [_proxyID requestSyncWithPeerIDs: peerIDs backupPeerIDs: backupPeerIDs]; + [self sendAckResponse: peer forEvent: event]; + + secinfo(PROXYXPCSCOPE, "RequestSyncWithAllPeers reply sent"); + } + else if (!strcmp(operation, kOperationHasPendingSyncWithPeer)) { + NSString *peerID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey: event withKey: kMessageKeyPeerID]; + + BOOL hasPending = [_proxyID hasSyncPendingFor: peerID]; + + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) + { + xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, hasPending); + xpc_connection_send_message(peer, replyMessage); + secinfo(PROXYXPCSCOPE, "HasPendingSyncWithPeer reply sent"); + } + } + else if (!strcmp(operation, kOperationHasPendingKey)) { + NSString *peerID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey: event withKey: kMessageKeyPeerID]; + + BOOL hasPending = [_proxyID hasPendingKey: peerID]; + + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) + { + xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, hasPending); + xpc_connection_send_message(peer, replyMessage); + secinfo(PROXYXPCSCOPE, "HasIncomingMessageFromPeer reply sent"); + } + } + else if (!strcmp(operation, kOperationRequestEnsurePeerRegistration)) + { + [_proxyID requestEnsurePeerRegistration]; + [self sendAckResponse: peer forEvent: event]; + secinfo(PROXYXPCSCOPE, "RequestEnsurePeerRegistration reply sent"); + } + else if (!strcmp(operation, kOperationFlush)) + { + [_proxyID doAfterFlush:^{ + [self sendAckResponse: peer forEvent: event]; + secinfo(PROXYXPCSCOPE, "flush reply sent"); + }]; + } + else if (!strcmp(operation, kOperationPerfCounters)) { + [_proxyID perfCounters:^(NSDictionary *counters){ + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + xpc_object_t object = _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)counters); + xpc_dictionary_set_value(replyMessage, kMessageKeyValue, object); + xpc_connection_send_message(peer, replyMessage); + }]; + } + else + { + char *description = xpc_copy_description(event); + secinfo(PROXYXPCSCOPE, "Unknown op=%s request from pid %d: %s", operation, xpc_connection_get_pid(peer), description); + free(description); + } + result = true; xit: - if (!result) - describeXPCObject("handle_operation fail: ", event); + if (!result) { + [self describeXPCObject: "handle_operation fail: " withObject: event]; + } + } } -void finalize_connection(void *not_used) -{ - secdebug(PROXYXPCSCOPE, "finalize_connection"); - [SharedProxy() synchronizeStore]; - xpc_transaction_end(); -} - -static bool operation_put_dictionary(xpc_object_t event) -{ +- (bool) operation_put_dictionary: (xpc_object_t) event { // PUT a set of objects into the KVS store. Return false if error xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); if (!xvalue) { @@ -337,29 +393,28 @@ static bool operation_put_dictionary(xpc_object_t event) NSObject* object = (__bridge_transfer NSObject*) _CFXPCCreateCFObjectFromXPCObject(xvalue); if (![object isKindOfClass:[NSDictionary class]]) { - describeXPCObject("operation_put_dictionary unable to convert to CF: ", xvalue); + [self describeXPCObject: "operation_put_dictionary unable to convert to CF: " withObject: xvalue]; return false; } - [SharedProxy() setObjectsFromDictionary: (NSDictionary *)object]; + [_proxyID setObjectsFromDictionary: (NSDictionary *)object]; return true; } -static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) -{ +- (bool) operation_get_v2: (xpc_connection_t) peer forEvent: (xpc_object_t) event { // GET a set of objects from the KVS store. Return false if error xpc_object_t replyMessage = xpc_dictionary_create_reply(event); if (!replyMessage) { - secdebug(PROXYXPCSCOPE, "can't create replyMessage"); + secinfo(PROXYXPCSCOPE, "can't create replyMessage"); assert(false); //must have a reply handler return false; } xpc_object_t returnedValues = xpc_dictionary_create(NULL, NULL, 0); if (!returnedValues) { - secdebug(PROXYXPCSCOPE, "can't create returnedValues"); + secinfo(PROXYXPCSCOPE, "can't create returnedValues"); assert(false); // must have a spot for the returned values return false; } @@ -367,18 +422,18 @@ static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); if (!xvalue) { - secdebug(PROXYXPCSCOPE, "missing \"value\" key"); + secinfo(PROXYXPCSCOPE, "missing \"value\" key"); return false; } xpc_object_t xkeystoget = xpc_dictionary_get_value(xvalue, kMessageKeyKeysToGet); if (xkeystoget) { - secdebug(PROXYXPCSCOPE, "got xkeystoget"); + secinfo(PROXYXPCSCOPE, "got xkeystoget"); CFTypeRef keystoget = _CFXPCCreateCFObjectFromXPCObject(xkeystoget); if (!keystoget || (CFGetTypeID(keystoget)!=CFArrayGetTypeID())) // not "getAll", this is an error of some kind { - secdebug(PROXYXPCSCOPE, "can't convert keystoget or is not an array"); + secinfo(PROXYXPCSCOPE, "can't convert keystoget or is not an array"); CFReleaseSafe(keystoget); return false; } @@ -386,16 +441,16 @@ static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) [(__bridge NSArray *)keystoget enumerateObjectsUsingBlock: ^ (id obj, NSUInteger idx, BOOL *stop) { NSString *key = (NSString *)obj; - id object = [SharedProxy() objectForKey:key]; - secdebug(PROXYXPCSCOPE, "get: key: %@, object: %@", key, object); + id object = [_proxyID objectForKey:key]; + secinfo(PROXYXPCSCOPE, "get: key: %@, object: %@", key, object); xpc_object_t xobject = object ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)object) : xpc_null_create(); xpc_dictionary_set_value(returnedValues, [key UTF8String], xobject); }]; } else // get all values from kvs { - secdebug(PROXYXPCSCOPE, "get all values from kvs"); - NSDictionary *all = [SharedProxy() copyAsDictionary]; + secinfo(PROXYXPCSCOPE, "get all values from kvs"); + NSDictionary *all = [_proxyID copyAsDictionary]; [all enumerateKeysAndObjectsUsingBlock: ^ (id key, id obj, BOOL *stop) { xpc_object_t xobject = obj ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)obj) : xpc_null_create(); @@ -410,53 +465,23 @@ static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) return true; } -static void cloudkeychainproxy_event_handler(xpc_connection_t peer) -{ - if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) - { - secdebug(PROXYXPCSCOPE, "expected XPC_TYPE_CONNECTION"); - return; - } - xpc_object_t ent = xpc_connection_copy_entitlement_value(peer, "com.apple.CloudKeychainProxy.client"); - if (ent == NULL || xpc_get_type(ent) != XPC_TYPE_BOOL || xpc_bool_get_value(ent) != true) { - secnotice(PROXYXPCSCOPE, "cloudkeychainproxy_event_handler: rejected client %d", xpc_connection_get_pid(peer)); - xpc_connection_cancel(peer); - return; - } +@end - xpc_connection_set_target_queue(peer, [SharedProxy() ckdkvsproxy_queue]); - xpc_connection_set_event_handler(peer, ^(xpc_object_t event) - { - // We could handle other peer events (e.g.) disconnects, - // but we don't keep per-client state so there is no need. - if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { - cloudkeychainproxy_peer_dictionary_handler(peer, event); - } - }); - - // This will tell the connection to begin listening for events. If you - // have some other initialization that must be done asynchronously, then - // you can defer this call until after that initialization is done. - xpc_connection_resume(peer); -} - -static void diagnostics(int argc, const char *argv[]) -{ - @autoreleasepool - { - NSDictionary *all = [SharedProxy() copyAsDictionary]; +static void diagnostics(int argc, const char *argv[]) { + @autoreleasepool { + NSDictionary *all = [[CloudKeychainProxy sharedObject].proxyID copyAsDictionary]; NSLog(@"All: %@",all); } } -int ckdproxymain(int argc, const char *argv[]) -{ - secdebug(PROXYXPCSCOPE, "Starting CloudKeychainProxy"); + + +int main(int argc, const char *argv[]) { + secinfo(PROXYXPCSCOPE, "Starting CloudKeychainProxy"); char *wait4debugger = getenv("WAIT4DEBUGGER"); - if (wait4debugger && !strcasecmp("YES", wait4debugger)) - { + if (wait4debugger && !strcasecmp("YES", wait4debugger)) { syslog(LOG_ERR, "Waiting for debugger"); kill(getpid(), SIGTSTP); } @@ -465,31 +490,18 @@ int ckdproxymain(int argc, const char *argv[]) diagnostics(argc, argv); return 0; } - - UbiqitousKVSProxy* proxyID = SharedProxy(); - - if (proxyID) { // nothing bad happened when initializing - xpc_connection_t listener = xpc_connection_create_mach_service(kCKPServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); - xpc_connection_set_event_handler(listener, ^(xpc_object_t object){ cloudkeychainproxy_event_handler(object); }); - - // It looks to me like there is insufficient locking to allow a request to come in on the XPC connection while doing the initial all items. - // Therefore I'm leaving the XPC connection suspended until that has time to process. - xpc_connection_resume(listener); - - @autoreleasepool - { - secdebug(PROXYXPCSCOPE, "Starting mainRunLoop"); - NSRunLoop *runLoop = [NSRunLoop mainRunLoop]; - [runLoop run]; - } + + CloudKeychainProxy *ckp = nil; + @autoreleasepool { + ckp = [CloudKeychainProxy sharedObject]; } - - secdebug(PROXYXPCSCOPE, "Exiting CloudKeychainProxy"); + + if (ckp) { // nothing bad happened when initializing + secinfo(PROXYXPCSCOPE, "Starting mainRunLoop"); + NSRunLoop *runLoop = [NSRunLoop mainRunLoop]; + [runLoop run]; + } + secinfo(PROXYXPCSCOPE, "Exiting CloudKeychainProxy"); return EXIT_FAILURE; } - -int main(int argc, const char *argv[]) -{ - return ckdproxymain(argc, argv); -} diff --git a/KeychainCircle/KCAESGCMDuplexSession.m b/KeychainCircle/KCAESGCMDuplexSession.m index 3bc684cd..bd17f5a6 100644 --- a/KeychainCircle/KCAESGCMDuplexSession.m +++ b/KeychainCircle/KCAESGCMDuplexSession.m @@ -162,29 +162,28 @@ static NSString* KCDSEpoch= @"epoch"; freeWhenDone: false]; }); - self = [super init]; + if ((self = [super init])) { + self.asSender = sender; + self.secret = sharedSecret; + self.send = malloc(ccgcm_context_size(ccaes_gcm_encrypt_mode())); + self.receive = malloc(ccgcm_context_size(ccaes_gcm_decrypt_mode())); + self.context = context; - self.asSender = sender; - self.secret = sharedSecret; - self.send = malloc(ccgcm_context_size(ccaes_gcm_encrypt_mode())); - self.receive = malloc(ccgcm_context_size(ccaes_gcm_decrypt_mode())); - self.context = context; + _pairingUUID = pairingUUID; + _piggybackingVersion = piggybackingVersion; + _epoch = epoch; - _pairingUUID = pairingUUID; - _piggybackingVersion = piggybackingVersion; - _epoch = epoch; + if (self.send == nil || self.receive == nil) { + return nil; + } - if (self.send == nil || self.receive == nil) { - return nil; + derive_and_init(ccaes_gcm_encrypt_mode(), + self.send, self.secret, + sender ? kdfInfoSendToReceive : kdfInfoReceiveToSend); + derive_and_init(ccaes_gcm_decrypt_mode(), + self.receive, self.secret, + !sender ? kdfInfoSendToReceive : kdfInfoReceiveToSend); } - - derive_and_init(ccaes_gcm_encrypt_mode(), - self.send, self.secret, - sender ? kdfInfoSendToReceive : kdfInfoReceiveToSend); - derive_and_init(ccaes_gcm_decrypt_mode(), - self.receive, self.secret, - !sender ? kdfInfoSendToReceive : kdfInfoReceiveToSend); - return self; } diff --git a/KeychainCircle/KCError.h b/KeychainCircle/KCError.h index 1f9d1874..9b140fe5 100644 --- a/KeychainCircle/KCError.h +++ b/KeychainCircle/KCError.h @@ -18,6 +18,8 @@ typedef enum { kUnexpectedMessage, kInternalError, kDERUnknownVersion, + kProcessApplicationFailure, + kUnsupportedTrustPlatform, } KCJoiningError; @interface NSError(KCJoiningError) diff --git a/KeychainCircle/KCJoiningAcceptSession+Internal.h b/KeychainCircle/KCJoiningAcceptSession+Internal.h index ea2c1be2..a0a9d584 100644 --- a/KeychainCircle/KCJoiningAcceptSession+Internal.h +++ b/KeychainCircle/KCJoiningAcceptSession+Internal.h @@ -31,6 +31,9 @@ #import "KCJoiningSession.h" @interface KCJoiningAcceptSession (Internal) + +- (KCAESGCMDuplexSession*)accessSession; + -(void)setControlObject:(OTControl*)control; - (void)setConfiguration:(OTJoiningConfiguration *)config; @end diff --git a/KeychainCircle/KCJoiningAcceptSession.m b/KeychainCircle/KCJoiningAcceptSession.m index 01285024..8e865fdf 100644 --- a/KeychainCircle/KCJoiningAcceptSession.m +++ b/KeychainCircle/KCJoiningAcceptSession.m @@ -20,7 +20,6 @@ #include #include #include -#include #include #if OCTAGON @@ -30,6 +29,9 @@ #import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTGlobalEnums.h" +#import "keychain/ot/proto/generated_source/OTSupportSOSMessage.h" +#import "keychain/ot/proto/generated_source/OTSupportOctagonMessage.h" #import "keychain/ot/proto/generated_source/OTPairingMessage.h" #endif @@ -103,38 +105,39 @@ typedef enum { dsid: (uint64_t) dsid rng: (struct ccrng_state *)rng error: (NSError**) error { - self = [super init]; + if ((self = [super init])) { - secnotice("accepting", "initWithSecretDelegate"); + secnotice("accepting", "initWithSecretDelegate"); - NSString* name = [NSString stringWithFormat: @"%llu", dsid]; + NSString* name = [NSString stringWithFormat: @"%llu", dsid]; - self->_context = [[KCSRPServerContext alloc] initWithUser: name - password: [secretDelegate secret] - digestInfo: ccsha256_di() - group: ccsrp_gp_rfc5054_3072() - randomSource: rng]; - self.secretDelegate = secretDelegate; - self.circleDelegate = circleDelegate; - self->_state = kExpectingA; - self->_dsid = dsid; - self->_piggy_uuid = nil; - self->_defaults = [NSMutableDictionary dictionary]; + self->_context = [[KCSRPServerContext alloc] initWithUser: name + password: [secretDelegate secret] + digestInfo: ccsha256_di() + group: ccsrp_gp_rfc5054_3072() + randomSource: rng]; + self.secretDelegate = secretDelegate; + self.circleDelegate = circleDelegate; + self->_state = kExpectingA; + self->_dsid = dsid; + self->_piggy_uuid = nil; + self->_defaults = [NSMutableDictionary dictionary]; #if OCTAGON - self->_otControl = [OTControl controlObject:true error:error]; - self->_piggy_version = KCJoiningOctagonPiggybackingEnabled()? kPiggyV2 : kPiggyV1; - self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:@"OctagonPiggybacking" - uniqueDeviceID:@"acceptor-deviceid" - uniqueClientID:@"requester-deviceid" - containerName:nil - contextID:OTDefaultContext - epoch:0 - isInitiator:false]; + self->_otControl = [OTControl controlObject:true error:error]; + self->_piggy_version = KCJoiningOctagonPiggybackingEnabled()? kPiggyV2 : kPiggyV1; + self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:@"OctagonPiggybacking" + uniqueDeviceID:@"acceptor-deviceid" + uniqueClientID:@"requester-deviceid" + pairingUUID:[[NSUUID UUID] UUIDString] + containerName:nil + contextID:OTDefaultContext + epoch:0 + isInitiator:false]; #else - self->_piggy_version = kPiggyV1; + self->_piggy_version = kPiggyV1; #endif - + } return self; } @@ -242,8 +245,14 @@ typedef enum { captureError = epochError; }else{ OTPairingMessage* responseMessage = [[OTPairingMessage alloc] init]; + responseMessage.supportsSOS = [[OTSupportSOSMessage alloc] init]; + responseMessage.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; + responseMessage.epoch = [[OTSponsorToApplicantRound1M2 alloc] init]; responseMessage.epoch.epoch = epoch; + + responseMessage.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + responseMessage.supportsOctagon.supported = OTSupportType_supported; next = responseMessage.data; } dispatch_semaphore_signal(sema); @@ -402,7 +411,58 @@ typedef enum { } #endif +- (NSData*) createTLKRequestResponse: (NSError**) error { + NSError* localError = NULL; + NSData* initialSync = [self.circleDelegate circleGetInitialSyncViews:kSOSInitialSyncFlagTLKsRequestOnly error:&localError]; + if (!initialSync) { + secnotice("joining", "Failed to get initial sync view: %@", localError); + if ( error!=NULL && localError != NULL ) + *error = localError; + return nil; + } + + NSData* encryptedOutgoing = [self.session encrypt:initialSync error:&localError]; + if (!encryptedOutgoing) { + secnotice("joining", "TLK request failed to encrypt: %@", localError); + if ( error!=NULL && localError != NULL ) + *error = localError; + return nil; + } + self->_state = kAcceptDone; + + secnotice("joining", "TLKRequest done."); + + return [[KCJoiningMessage messageWithType:kTLKRequest + data:encryptedOutgoing + error:error] der]; +} + + +- (BOOL)shouldProcessSOSApplication:(KCJoiningMessage*)message pairingMessage:(OTPairingMessage*)pairingMessage +{ + BOOL shouldProcess = YES; + + if (OctagonPlatformSupportsSOS() == NO) { + secnotice("joining", "platform does not support SOS"); + shouldProcess = NO; + } else if (message.secondData == nil) { + secnotice("joining", "message does not contain SOS data"); + shouldProcess = NO; + } else if (pairingMessage.hasSupportsSOS && pairingMessage.supportsSOS.supported == OTSupportType_not_supported) { + secnotice("joining", "requester explicitly does not support SOS"); + shouldProcess = NO; + } + + return shouldProcess; +} + + - (NSData*) processApplication: (KCJoiningMessage*) message error:(NSError**) error { + + if ([message type] == kTLKRequest) { + return [self createTLKRequestResponse: error]; + } + if ([message type] != kPeerInfo) { KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected peerInfo!"); return nil; @@ -441,9 +501,14 @@ typedef enum { localError = err; }else{ OTPairingMessage *pairingResponse = [[OTPairingMessage alloc] init]; + pairingResponse.supportsSOS = [[OTSupportSOSMessage alloc] init]; + pairingResponse.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; pairingResponse.voucher = [[OTSponsorToApplicantRound2M2 alloc] init]; pairingResponse.voucher.voucher = voucher; pairingResponse.voucher.voucherSignature = voucherSig; + + pairingMessage.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + pairingMessage.supportsOctagon.supported = OTSupportType_supported; next = pairingResponse.data; } dispatch_semaphore_signal(sema); @@ -461,17 +526,19 @@ typedef enum { } NSData* encryptedOutgoing = nil; - if (OctagonPlatformSupportsSOS() && message.secondData) { + if ([self shouldProcessSOSApplication:message pairingMessage:pairingMessage]) { secnotice("joining", "doing SOS processSOSApplication"); - //note we are stuffing SOS into the payload "secondData" encryptedOutgoing = [self processSOSApplication: message.secondData error:error]; - } else { - secnotice("joining", "no platform support processSOSApplication, peer sent data: %s", - message.secondData ? "yes" : "no"); + if (encryptedOutgoing == nil) { + secerror("joining: failed to process SOS application: %@", error && *error ? *error : nil); + KCJoiningErrorCreate(kProcessApplicationFailure, error, @"message failed to process application"); + return nil; + } } self->_state = kAcceptDone; + //note we are stuffing SOS into the payload return [[KCJoiningMessage messageWithType:kCircleBlob data:next payload:encryptedOutgoing @@ -531,6 +598,11 @@ typedef enum { { self.joiningConfiguration = config; } + +- (KCAESGCMDuplexSession*)accessSession +{ + return self.session; +} #endif @end diff --git a/KeychainCircle/KCJoiningMessages.h b/KeychainCircle/KCJoiningMessages.h index a6ad9e38..e6dbb84c 100644 --- a/KeychainCircle/KCJoiningMessages.h +++ b/KeychainCircle/KCJoiningMessages.h @@ -9,7 +9,7 @@ // Initial messages are versioned and not typed for negotiation. NS_ASSUME_NONNULL_BEGIN -NSData* extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString* _Nullable * _Nullable uuidString, NSData* _Nullable * _Nullable octagon, NSError** error); +NSData* _Nullable extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString* _Nullable * _Nullable uuidString, NSData* _Nullable * _Nullable octagon, NSError** error); size_t sizeof_initialmessage(NSData*data); size_t sizeof_initialmessage_version1(NSData*data, uint64_t version1, NSData *uuid); @@ -84,6 +84,8 @@ typedef enum { kPeerInfo = 4, kCircleBlob = 5, + kTLKRequest = 6, + kError = 0, kUnknown = 255, @@ -109,7 +111,7 @@ typedef enum { + (nullable instancetype) messageWithType: (KCJoiningMessageType) type data: (NSData*) firstData - payload: (NSData*) secondData + payload: (nullable NSData*) secondData error: (NSError**) error; diff --git a/KeychainCircle/KCJoiningMessages.m b/KeychainCircle/KCJoiningMessages.m index 2eb0c94b..162b0482 100644 --- a/KeychainCircle/KCJoiningMessages.m +++ b/KeychainCircle/KCJoiningMessages.m @@ -32,14 +32,14 @@ + (nullable instancetype) messageWithType: (KCJoiningMessageType) type data: (NSData*) firstData - secondData: (NSData*) secondData + secondData: (nullable NSData*) secondData error: (NSError**) error { return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:secondData error:error]; } + (nullable instancetype) messageWithType: (KCJoiningMessageType) type data: (NSData*) firstData - payload: (NSData*) secondData + payload: (nullable NSData*) secondData error: (NSError**) error { return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:secondData error:error]; @@ -140,10 +140,9 @@ - (nullable instancetype) initWithDER: (NSData*) message error: (NSError**) error { - self = [super init]; - - self->_der = [NSData dataWithData: message]; - + if ((self = [super init])) { + self->_der = [NSData dataWithData: message]; + } return [self inflatePartsOfEncoding: error] ? self : nil; } @@ -151,14 +150,13 @@ data: (NSData*) firstData payload: (nullable NSData*) secondData error: (NSError**) error { - self = [super init]; - - self->_der = [KCJoiningMessage encodeToDERType:type - data:firstData - payload:secondData - error:error]; - if (self->_der == nil) return nil; - + if ((self = [super init])) { + self->_der = [KCJoiningMessage encodeToDERType:type + data:firstData + payload:secondData + error:error]; + if (self->_der == nil) return nil; + } return [self inflatePartsOfEncoding: error] ? self : nil; } @@ -262,7 +260,8 @@ @end -NSData* extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString** uuidString, NSData** octagon, NSError** error) { +NSData* _Nullable extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString** uuidString, NSData** octagon, NSError** error) +{ NSData* result = nil; const uint8_t *der = [initialMessage bytes]; const uint8_t *der_end = der + [initialMessage length]; diff --git a/KeychainCircle/KCJoiningRequestCircleSession.m b/KeychainCircle/KCJoiningRequestCircleSession.m index ed9db950..e0fffb47 100644 --- a/KeychainCircle/KCJoiningRequestCircleSession.m +++ b/KeychainCircle/KCJoiningRequestCircleSession.m @@ -26,6 +26,9 @@ #import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTGlobalEnums.h" +#import "keychain/ot/proto/generated_source/OTSupportSOSMessage.h" +#import "keychain/ot/proto/generated_source/OTSupportOctagonMessage.h" #import "keychain/ot/proto/generated_source/OTPairingMessage.h" #endif #import @@ -52,9 +55,13 @@ typedef enum { - (void)setControlObject:(OTControl *)control{ self.otControl = control; } -- (void)setJoiningConfigurationObject:(OTJoiningConfiguration *)joiningConfiguration +- (void)setContextIDOnJoiningConfiguration:(NSString*)contextID { - self.joiningConfiguration = joiningConfiguration; + self.joiningConfiguration.contextID = contextID; +} +- (KCAESGCMDuplexSession*)accessSession +{ + return self.session; } #endif @@ -98,6 +105,7 @@ typedef enum { return [self->_session encrypt:initialMessage.data error:error]; } + - (nullable NSData*) initialMessage: (NSError**) error { secnotice("joining", "joining: KCJoiningRequestCircleSession initialMessage called"); @@ -125,6 +133,8 @@ typedef enum { localError = err; } else{ OTPairingMessage *pairingMessage = [[OTPairingMessage alloc]init]; + pairingMessage.supportsSOS = [[OTSupportSOSMessage alloc] init]; + pairingMessage.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; OTApplicantToSponsorRound2M1 *prepareMessage = [[OTApplicantToSponsorRound2M1 alloc]init]; prepareMessage.peerID = peerID; prepareMessage.permanentInfo = permanentInfo; @@ -133,6 +143,10 @@ typedef enum { prepareMessage.stableInfoSig = stableInfoSig; pairingMessage.prepare = prepareMessage; + + pairingMessage.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + pairingMessage.supportsOctagon.supported = OTSupportType_supported; + next = pairingMessage.data; } dispatch_semaphore_signal(sema); @@ -158,7 +172,7 @@ typedef enum { self->_state = kExpectingCircleBlob; NSData *encryptedInitialMessage = [self encryptedInitialMessage:next error:error]; - return [[KCJoiningMessage messageWithType: kPeerInfo + return [[KCJoiningMessage messageWithType:kPeerInfo data:encryptedInitialMessage payload:encryptedPi error:error] der]; @@ -176,13 +190,34 @@ typedef enum { } -- (void) attemptSosUpgrade +- (void) waitForOctagonUpgrade { - [self.otControl attemptSosUpgrade:self.joiningConfiguration.containerName context:self.joiningConfiguration.contextID reply:^(NSError *error) { +#if OCTAGON + [self.otControl waitForOctagonUpgrade:self.joiningConfiguration.containerName context:self.joiningConfiguration.contextID reply:^(NSError *error) { if(error){ secerror("pairing: failed to upgrade initiator into Octagon: %@", error); } }]; +#endif +} + +- (BOOL)shouldJoinSOS:(KCJoiningMessage*)message pairingMessage:(OTPairingMessage*)pairingMessage +{ + + BOOL shouldJoin = YES; + + if (OctagonPlatformSupportsSOS() == NO) { + secnotice("joining", "platform does not support SOS"); + shouldJoin = NO; + } else if (message.secondData == nil) { + secnotice("joining", "message does not contain SOS data"); + shouldJoin = NO; + } else if (pairingMessage.hasSupportsSOS && pairingMessage.supportsSOS.supported == OTSupportType_not_supported) { + secnotice("joining", "acceptor explicitly does not support SOS"); + shouldJoin = NO; + } + + return shouldJoin; } - (NSData*) handleCircleBlob: (KCJoiningMessage*) message error: (NSError**) error { @@ -202,10 +237,14 @@ typedef enum { secerror("octagon: expected voucher! returning from piggybacking."); return nil; } + OTSponsorToApplicantRound2M2 *voucher = pairingMessage.voucher; //handle voucher message then join octagon - [self.otControl rpcJoinWithConfiguration:self.joiningConfiguration vouchData:voucher.voucher vouchSig:voucher.voucherSignature preapprovedKeys:voucher.preapprovedKeys reply:^(NSError * _Nullable err) { + [self.otControl rpcJoinWithConfiguration:self.joiningConfiguration + vouchData:voucher.voucher + vouchSig:voucher.voucherSignature + reply:^(NSError * _Nullable err) { if(err){ secerror("octagon: error joining octagon: %@", err); localError = err; @@ -221,16 +260,18 @@ typedef enum { return nil; } - if (OctagonPlatformSupportsSOS()) { + if ([self shouldJoinSOS:message pairingMessage:pairingMessage]) { secnotice("joining", "doing SOS processCircleJoinData"); //note we are stuffing SOS into the payload "secondData" NSData* circleBlob = [self.session decryptAndVerify:message.secondData error:error]; - if (circleBlob == nil) return nil; - - if (![self.circleDelegate processCircleJoinData: circleBlob version:kPiggyV1 error:error]) + if (circleBlob == nil) { + secnotice("joining", "decryptAndVerify failed: %@", error && *error ? *error : nil); return nil; - } else { - secnotice("joining", "platform doesn't support SOS"); + } + if (![self.circleDelegate processCircleJoinData: circleBlob version:kPiggyV1 error:error]){ + secerror("joining: processCircleJoinData failed %@", error && *error ? *error : nil); + return nil; + } } self->_state = kRequestCircleDone; @@ -250,10 +291,12 @@ typedef enum { return nil; } else { secnotice("joining", "joined the SOS circle!"); +#if OCTAGON if(OctagonIsEnabled()) { secnotice("joining", "kicking off SOS Upgrade into Octagon!"); - [self attemptSosUpgrade]; + [self waitForOctagonUpgrade]; } +#endif } self->_state = kRequestCircleDone; @@ -304,27 +347,26 @@ typedef enum { error:(NSError**) error { secnotice("joining", "joining: KCJoiningRequestCircleSession initWithCircleDelegate called, uuid=%@", session.pairingUUID); - self = [super init]; - - self->_circleDelegate = circleDelegate; - self->_session = session; - self.state = kExpectingCircleBlob; + if ((self = [super init])) { + self->_circleDelegate = circleDelegate; + self->_session = session; + self.state = kExpectingCircleBlob; #if OCTAGON - self->_otControl = otcontrol; - self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:@"OctagonPiggybacking" - uniqueDeviceID:@"requester-id" - uniqueClientID:@"requester-id" - pairingUUID:session.pairingUUID - containerName:nil - contextID:OTDefaultContext - epoch:session.epoch - isInitiator:true]; + self->_otControl = otcontrol; + self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:@"OctagonPiggybacking" + uniqueDeviceID:@"requester-id" + uniqueClientID:@"requester-id" + pairingUUID:session.pairingUUID + containerName:nil + contextID:OTDefaultContext + epoch:session.epoch + isInitiator:true]; - self->_piggy_version = session.piggybackingVersion; + self->_piggy_version = session.piggybackingVersion; #else - self->_piggy_version = kPiggyV1; + self->_piggy_version = kPiggyV1; #endif - + } return self; } diff --git a/KeychainCircle/KCJoiningRequestSecretSession.m b/KeychainCircle/KCJoiningRequestSecretSession.m index 2cb52bcf..db52d630 100644 --- a/KeychainCircle/KCJoiningRequestSecretSession.m +++ b/KeychainCircle/KCJoiningRequestSecretSession.m @@ -18,7 +18,6 @@ #include #include #include -#include #import #include @@ -33,6 +32,9 @@ #import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTGlobalEnums.h" +#import "keychain/ot/proto/generated_source/OTSupportSOSMessage.h" +#import "keychain/ot/proto/generated_source/OTSupportOctagonMessage.h" #import "keychain/ot/proto/generated_source/OTPairingMessage.h" #endif #import @@ -70,8 +72,9 @@ bool KCJoiningOctagonPiggybackingEnabled() { @property (readwrite) uint64_t epoch; @property (readwrite) NSData* challenge; @property (readwrite) NSData* salt; +@property (readwrite) NSString* sessionUUID; + #if OCTAGON -@property (nonatomic, strong) OTJoiningConfiguration* joiningConfiguration; @property (nonatomic, strong) OTControl *otControl; #endif @property (nonatomic, strong) NSMutableDictionary *defaults; @@ -147,7 +150,7 @@ bool KCJoiningOctagonPiggybackingEnabled() { } self->_session = [KCAESGCMDuplexSession sessionAsSender:key context:self.dsid]; - self.session.pairingUUID = self.joiningConfiguration.pairingUUID; + self.session.pairingUUID = self.sessionUUID; self.session.piggybackingVersion = self.piggy_version; return self.session != nil; @@ -211,17 +214,16 @@ bool KCJoiningOctagonPiggybackingEnabled() { } #if OCTAGON //handle octagon data if it exists - if(KCJoiningOctagonPiggybackingEnabled()){ + if (KCJoiningOctagonPiggybackingEnabled()){ self.piggy_version = [message secondData] ? kPiggyV2 : kPiggyV1; // The session may or may not exist at this point. If it doesn't, the version will be set at object creation time. self.session.piggybackingVersion = self.piggy_version; - if(self.piggy_version == kPiggyV2){ + if (self.piggy_version == kPiggyV2){ OTPairingMessage* pairingMessage = [[OTPairingMessage alloc]initWithData: [message secondData]]; - - if(pairingMessage.epoch.epoch){ - secnotice("octagon", "received epoch"); + if (pairingMessage.hasEpoch) { + secnotice("octagon", "received epoch message: %@", [pairingMessage.epoch dictionaryRepresentation]); self.epoch = pairingMessage.epoch.epoch; } else{ @@ -340,36 +342,30 @@ bool KCJoiningOctagonPiggybackingEnabled() { rng: (struct ccrng_state *)rng error: (NSError**)error { secnotice("joining", "joining: initWithSecretDelegate called"); - self = [super init]; - - self->_secretDelegate = secretDelegate; - self->_state = kExpectingB; - self->_dsid = dsid; - self->_defaults = [NSMutableDictionary dictionary]; + if ((self = [super init])) { + self->_secretDelegate = secretDelegate; + self->_state = kExpectingB; + self->_dsid = dsid; + self->_defaults = [NSMutableDictionary dictionary]; #if OCTAGON - self->_piggy_version = KCJoiningOctagonPiggybackingEnabled() ? kPiggyV2 : kPiggyV1; - self->_otControl = [OTControl controlObject:true error:error]; - self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:OTProtocolPiggybacking - uniqueDeviceID:@"requester-id" - uniqueClientID:@"requester-id" - containerName:nil - contextID:OTDefaultContext - epoch:0 - isInitiator:true]; + self->_piggy_version = KCJoiningOctagonPiggybackingEnabled() ? kPiggyV2 : kPiggyV1; + self->_otControl = [OTControl controlObject:true error:error]; + + _sessionUUID = [[NSUUID UUID] UUIDString]; #else - self->_piggy_version = kPiggyV1; + self->_piggy_version = kPiggyV1; #endif - secnotice("joining", "joining: initWithSecretDelegate called, uuid=%@", self.joiningConfiguration.pairingUUID); + secnotice("joining", "joining: initWithSecretDelegate called, uuid=%@", self.sessionUUID); - NSString* name = [NSString stringWithFormat: @"%llu", dsid]; + NSString* name = [NSString stringWithFormat: @"%llu", dsid]; - self->_context = [[KCSRPClientContext alloc] initWithUser: name - digestInfo: ccsha256_di() - group: ccsrp_gp_rfc5054_3072() - randomSource: rng]; - + self->_context = [[KCSRPClientContext alloc] initWithUser: name + digestInfo: ccsha256_di() + group: ccsrp_gp_rfc5054_3072() + randomSource: rng]; + } return self; } @@ -391,11 +387,6 @@ bool KCJoiningOctagonPiggybackingEnabled() { { self.otControl = control; } - -- (void)setConfiguration:(OTJoiningConfiguration *)config -{ - self.joiningConfiguration = config; -} #endif @end diff --git a/KeychainCircle/KCJoiningRequestSession+Internal.h b/KeychainCircle/KCJoiningRequestSession+Internal.h index 917529c3..340d23cb 100644 --- a/KeychainCircle/KCJoiningRequestSession+Internal.h +++ b/KeychainCircle/KCJoiningRequestSession+Internal.h @@ -32,13 +32,14 @@ @interface KCJoiningRequestSecretSession (Internal) - (void)setControlObject:(OTControl*)control; -- (void)setConfiguration:(OTJoiningConfiguration *)config; @end @interface KCJoiningRequestCircleSession (Internal) +- (KCAESGCMDuplexSession*)accessSession; + - (void)setControlObject:(OTControl*)control; -- (void)setJoiningConfigurationObject:(OTJoiningConfiguration *)config; +- (void)setContextIDOnJoiningConfiguration:(NSString*)contextID; @end #endif /* Header_h */ #endif diff --git a/KeychainCircle/KCSRPContext.h b/KeychainCircle/KCSRPContext.h index c0d8149e..792456a7 100644 --- a/KeychainCircle/KCSRPContext.h +++ b/KeychainCircle/KCSRPContext.h @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN // Returns an NSData that refers to the key in the context. // It becomes invalid when this context is released. -- (NSData*) getKey; +- (NSData* _Nullable) getKey; @end diff --git a/KeychainCircle/KCSRPContext.m b/KeychainCircle/KCSRPContext.m index 3d9d8a8e..1650489f 100644 --- a/KeychainCircle/KCSRPContext.m +++ b/KeychainCircle/KCSRPContext.m @@ -50,14 +50,13 @@ static const NSStringEncoding srpStringEncoding = NSUTF8StringEncoding; group: (ccsrp_const_gp_t) gp randomSource: (struct ccrng_state *) rng { - self = [super init]; - - self.context = malloc(ccsrp_sizeof_srp(di, gp)); - ccsrp_ctx_init(self.context, di, gp); - - self.user = user; - self.rng = rng; + if ((self = [super init])) { + self.context = malloc(ccsrp_sizeof_srp(di, gp)); + ccsrp_ctx_init(self.context, di, gp); + self.user = user; + self.rng = rng; + } return self; } @@ -72,7 +71,8 @@ static const NSStringEncoding srpStringEncoding = NSUTF8StringEncoding; } #pragma clang diagnostic pop -- (NSData*) getKey { +- (NSData* _Nullable)getKey +{ size_t key_length = 0; const void * key = ccsrp_get_session_key(self.context, &key_length); @@ -179,15 +179,14 @@ static bool ExactDataSizeRequirement(NSData* data, NSUInteger expectedLength, NS digestInfo: (const struct ccdigest_info *) di group: (ccsrp_const_gp_t) gp randomSource: (struct ccrng_state *) rng { - self = [super initWithUser: user - digestInfo: di - group: gp - randomSource: rng]; - - if (![self resetWithPassword:password error:nil]) { - return nil; + if ((self = [super initWithUser: user + digestInfo: di + group: gp + randomSource: rng])) { + if (![self resetWithPassword:password error:nil]) { + return nil; + } } - return self; } @@ -197,14 +196,13 @@ static bool ExactDataSizeRequirement(NSData* data, NSUInteger expectedLength, NS digestInfo: (const struct ccdigest_info *) di group: (ccsrp_const_gp_t) gp randomSource: (struct ccrng_state *) rng { - self = [super initWithUser: user - digestInfo: di - group: gp - randomSource: rng]; - - self.verifier = verifier; - self->_salt = salt; - + if ((self = [super initWithUser: user + digestInfo: di + group: gp + randomSource: rng])) { + self.verifier = verifier; + self->_salt = salt; + } return self; } diff --git a/KeychainCircle/PairingChannel.h b/KeychainCircle/PairingChannel.h index 6f65dd6f..d6c19033 100644 --- a/KeychainCircle/PairingChannel.h +++ b/KeychainCircle/PairingChannel.h @@ -61,5 +61,9 @@ extern KCPairingIntent_Type KCPairingIntent_Type_UserDriven; - (void)setOctagonMessageFailForTesting:(BOOL)value; + (bool)isSupportedPlatform; - (void)setSessionSupportsOctagonForTesting:(bool)value; + ++ (NSData *)pairingChannelCompressData:(NSData *)data; ++ (NSData *)pairingChannelDecompressData:(NSData *)data; + @end diff --git a/KeychainCircle/PairingChannel.m b/KeychainCircle/PairingChannel.m index b65d3f6b..60b5cf5e 100644 --- a/KeychainCircle/PairingChannel.m +++ b/KeychainCircle/PairingChannel.m @@ -11,17 +11,19 @@ #import #import #import +#import "utilities/SecCoreAnalytics.h" #import #import "keychain/ot/OTManager.h" #import "keychain/ot/OctagonControlServer.h" #import "keychain/ot/OTControl.h" #import "keychain/ot/OctagonControlServer.h" #import "keychain/ot/OTJoiningConfiguration.h" -#import "keychain/ot/proto/generated_source/OTPairingMessage.h" -#import "keychain/ot/proto/generated_source/OTSOSMessage.h" #import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTGlobalEnums.h" +#import "keychain/ot/proto/generated_source/OTSupportSOSMessage.h" +#import "keychain/ot/proto/generated_source/OTSupportOctagonMessage.h" #import "keychain/ot/proto/generated_source/OTPairingMessage.h" #include @@ -30,7 +32,6 @@ #import #endif -#import "utilities/SecADWrapper.h" KCPairingIntent_Type KCPairingIntent_Type_None = @"none"; KCPairingIntent_Type KCPairingIntent_Type_SilentRepair = @"repair"; @@ -79,8 +80,7 @@ typedef void(^OTNextState)(NSData *inData, OTPairingInternalCompletion complete) - (nullable instancetype)initWithCoder:(NSCoder *)decoder { - self = [super init]; - if (self) { + if ((self = [super init])) { _model = [decoder decodeObjectOfClass:[NSString class] forKey:@"model"]; _modelVersion = [decoder decodeObjectOfClass:[NSString class] forKey:@"modelVersion"]; _modelClass = [decoder decodeObjectOfClass:[NSString class] forKey:@"modelClass"]; @@ -109,6 +109,7 @@ typedef void(^OTNextState)(NSData *inData, OTPairingInternalCompletion complete) @property (assign) bool initiator; @property (assign) unsigned counter; @property (assign) bool acceptorWillSendInitialSyncCredentials; +@property (assign) uint32_t acceptorInitialSyncCredentialsFlags; @property (strong) NSXPCConnection *connection; @property (strong) OTControl *otControl; @property (strong) NSString* contextID; @@ -170,6 +171,7 @@ typedef void(^OTNextState)(NSData *inData, OTPairingInternalCompletion complete) _joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:OTProtocolPairing uniqueDeviceID:peerVersionContext.uniqueDeviceID uniqueClientID:peerVersionContext.uniqueClientID + pairingUUID:[[NSUUID UUID] UUIDString] containerName:nil contextID:OTDefaultContext epoch:0 @@ -207,7 +209,7 @@ typedef void(^OTNextState)(NSData *inData, OTPairingInternalCompletion complete) const compression_algorithm pairingCompression = COMPRESSION_LZFSE; #define EXTRA_SIZE 100 -- (NSData *)compressData:(NSData *)data ++ (NSData *)pairingChannelCompressData:(NSData *)data { NSMutableData *scratch = [NSMutableData dataWithLength:compression_encode_scratch_buffer_size(pairingCompression)]; @@ -226,7 +228,7 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; return o; } -- (NSData *)decompressData:(NSData *)data ++ (NSData *)pairingChannelDecompressData:(NSData *)data { NSMutableData *scratch = [NSMutableData dataWithLength:compression_decode_scratch_buffer_size(pairingCompression)]; @@ -255,9 +257,9 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; //MARK: - Initiator -- (void) attemptSosUpgrade +- (void) waitForOctagonUpgrade { - [self.otControl attemptSosUpgrade:nil context:self.contextID reply:^(NSError *error) { + [self.otControl waitForOctagonUpgrade:nil context:self.contextID reply:^(NSError *error) { if(error){ secerror("pairing: failed to upgrade initiator into Octagon: %@", error); } @@ -406,12 +408,17 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; return; } else { OTPairingMessage *octagonMessage = [[OTPairingMessage alloc]init]; + octagonMessage.supportsSOS = [[OTSupportSOSMessage alloc] init]; + octagonMessage.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; OTApplicantToSponsorRound2M1 *prepare = [[OTApplicantToSponsorRound2M1 alloc] init]; prepare.peerID = peerID; prepare.permanentInfo = permanentInfo; prepare.permanentInfoSig = permanentInfoSig; prepare.stableInfo = stableInfo; prepare.stableInfoSig = stableInfoSig; + + octagonMessage.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + octagonMessage.supportsOctagon.supported = OTSupportType_supported; octagonMessage.prepare = prepare; if(application){ secnotice(pairingScope, "initiatorCompleteSecondPacketOctagon returning octagon and sos data"); @@ -464,7 +471,7 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; } else { //kick off SOS ugprade if(OctagonIsEnabled() && !self.sessionSupportsOctagon) { - [self attemptSosUpgrade]; + [self waitForOctagonUpgrade]; } typeof(self) strongSelf = weakSelf; secnotice("pairing", "initiator circle join complete, more data: %s: %@", @@ -499,7 +506,10 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; OTSponsorToApplicantRound2M2 *voucher = pairingMessage.voucher; //handle voucher and join octagon - [self.otControl rpcJoinWithConfiguration:self.joiningConfiguration vouchData:voucher.voucher vouchSig:voucher.voucherSignature preapprovedKeys:voucher.preapprovedKeys reply:^(NSError *error) { + [self.otControl rpcJoinWithConfiguration:self.joiningConfiguration + vouchData:voucher.voucher + vouchSig:voucher.voucherSignature + reply:^(NSError *error) { if (error || self.testFailOctagon) { secerror("ot-pairing: failed to create %d message: %@", self.counter, error); complete(true, NULL, error); @@ -507,7 +517,7 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; }else{ secnotice(pairingScope, "initiatorThirdPacket successfully joined Octagon"); typeof(self) strongSelf = weakSelf; - if(OctagonPlatformSupportsSOS() && strongSelf->_acceptorWillSendInitialSyncCredentials == true) { + if(OctagonPlatformSupportsSOS() && strongSelf->_acceptorWillSendInitialSyncCredentials) { strongSelf.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ [weakSelf initiatorFourthPacket:nsdata complete:kscomplete]; }; @@ -567,6 +577,11 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; if (self.sessionSupportsSOS && indata[@"d"]) { secnotice("pairing", "acceptor initialSyncCredentials requested"); self.acceptorWillSendInitialSyncCredentials = true; + self.acceptorInitialSyncCredentialsFlags = + SOSControlInitialSyncFlagTLK| + SOSControlInitialSyncFlagPCS| + SOSControlInitialSyncFlagBluetoothMigration; + } if (indata[@"o"] == nil) { @@ -647,10 +662,13 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; [weakSelf acceptorSecondPacket:nsdata complete:kscomplete]; }; OTPairingMessage *response = [[OTPairingMessage alloc] init]; + response.supportsSOS = [[OTSupportSOSMessage alloc] init]; + response.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; response.epoch = [[OTSponsorToApplicantRound1M2 alloc] init]; response.epoch.epoch = epoch; + response.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + response.supportsOctagon.supported = OTSupportType_supported; reply[@"o"] = response.data; - secnotice("pairing", "acceptor reply to packet 1"); complete(false, reply, error); } @@ -746,9 +764,19 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; finished = false; } OTPairingMessage *response = [[OTPairingMessage alloc] init]; + response.supportsSOS = [[OTSupportSOSMessage alloc] init]; + response.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; response.voucher = [[OTSponsorToApplicantRound2M2 alloc] init]; response.voucher.voucher = voucher; response.voucher.voucherSignature = voucherSig; + response.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + response.supportsOctagon.supported = OTSupportType_supported; + + if (self.acceptorWillSendInitialSyncCredentials) { + // no need to share TLKs over the pairing channel, that's provided by octagon + self.acceptorInitialSyncCredentialsFlags &= ~(SOSControlInitialSyncFlagTLK | SOSControlInitialSyncFlagPCS); + } + reply[@"o"] = response.data; secnotice("pairing", "acceptor reply to packet 2"); @@ -761,10 +789,7 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; { secnotice("pairing", "acceptor packet 3"); - const uint32_t initialSyncCredentialsFlags = - SOSControlInitialSyncFlagTLK| - SOSControlInitialSyncFlagPCS| - SOSControlInitialSyncFlagBluetoothMigration; + const uint32_t initialSyncCredentialsFlags = self.acceptorInitialSyncCredentialsFlags; [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { complete(true, NULL, error); @@ -824,7 +849,7 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; if (inputCompressedData) { - NSData *data = [self decompressData:inputCompressedData]; + NSData *data = [[self class] pairingChannelDecompressData:inputCompressedData]; if (data == NULL) { secnotice("pairing", "failed to decompress"); complete(true, NULL, NULL); @@ -849,12 +874,12 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; if (outdata == NULL && error) error = error2; if (outdata) - compressedData = [self compressData:outdata]; + compressedData = [[self class] pairingChannelCompressData:outdata]; if (compressedData) { NSString *key = [NSString stringWithFormat:@"com.apple.ckks.pairing.packet-size.%s.%u", self->_initiator ? "initiator" : "acceptor", self->_counter]; - SecADClientPushValueForDistributionKey((__bridge CFStringRef)key, [compressedData length]); + [SecCoreAnalytics sendEvent:key event:@{SecCoreAnalyticsValue: [NSNumber numberWithUnsignedInteger:[compressedData length]]}]; secnotice("pairing", "pairing packet size %lu", (unsigned long)[compressedData length]); } } diff --git a/KeychainCircle/Tests/FakeSOSControl.m b/KeychainCircle/Tests/FakeSOSControl.m index b8edbae9..33329b63 100644 --- a/KeychainCircle/Tests/FakeSOSControl.m +++ b/KeychainCircle/Tests/FakeSOSControl.m @@ -4,8 +4,7 @@ @implementation FakeNSXPCConnection - (instancetype) initWithControl:(id)control { - self = [super init]; - if (self) { + if ((self = [super init])) { _control = control; } return self; @@ -131,12 +130,29 @@ - (void)initialSyncCredentials:(uint32_t)flags complete:(void (^)(NSArray *, NSError *))complete { - complete(@[], NULL); + // Make up a fake TLK + NSMutableArray *items = [NSMutableArray array]; + if (flags & SOSControlInitialSyncFlagTLK) { + NSString *tlkUUID = [[NSUUID UUID] UUIDString]; + NSDictionary *fakeTLK = @{ + @"class": @"inet", + @"agrp": @"com.apple.security.ckks", + @"vwht": @"PCS-master", + @"pdmn": @"ck", + @"desc": @"tlk", + @"srvr": @"fakeZone", + @"acct": tlkUUID, + @"path": tlkUUID, + @"v_Data": [NSData data], + }; + [items addObject:fakeTLK]; + } + complete(items, nil); } - (void)importInitialSyncCredentials:(NSArray *)items complete:(void (^)(bool success, NSError *))complete { - complete(true, NULL); + complete(true, nil); } - (void)rpcTriggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete @@ -328,6 +344,14 @@ complete(nil, nil); } +- (void)iCloudIdentityStatus_internal: (void(^)(NSDictionary *tableSpid, NSError *error))complete { + complete(nil, nil); +} + +- (void) iCloudIdentityStatus: (void(^)(NSData *json, NSError *error))complete { + complete(nil, nil); +} + - (void)rpcTriggerBackup:(NSArray *)backupPeers complete:(void (^)(NSError *))complete { complete(nil); } @@ -336,5 +360,8 @@ complete(nil); } +- (void)removeV0Peers:(void (^)(bool, NSError *))reply { + reply(true, nil); +} @end diff --git a/KeychainCircle/Tests/KCJoiningSessionTest.m b/KeychainCircle/Tests/KCJoiningSessionTest.m index a3d71d0f..f34ee649 100644 --- a/KeychainCircle/Tests/KCJoiningSessionTest.m +++ b/KeychainCircle/Tests/KCJoiningSessionTest.m @@ -17,26 +17,6 @@ #include "keychain/SecureObjectSync/SOSFullPeerInfo.h" #include "keychain/SecureObjectSync/SOSPeerInfoInternal.h" -#include - - -__unused static SOSFullPeerInfoRef SOSNSFullPeerInfoCreate(NSDictionary* gestalt, - NSData* backupKey, SecKeyRef signingKey, - SecKeyRef octagonSigningKey, - SecKeyRef octagonEncryptionKey, - NSError**error) -{ - CFErrorRef errorRef = NULL; - - SOSFullPeerInfoRef result = SOSFullPeerInfoCreate(NULL, (__bridge CFDictionaryRef) gestalt, (__bridge CFDataRef) backupKey, signingKey, octagonSigningKey, octagonEncryptionKey, &errorRef); - - if (errorRef && error) { - *error = (__bridge_transfer NSError*) errorRef; - errorRef = NULL; - } - - return result; -} static SecKeyRef GenerateFullECKey_internal(int keySize, NSError** error) { @@ -106,25 +86,26 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { - (id) initWithSecret: (NSString*) secret incorrectSecret: (NSString*) incorrectSecret incorrectTries: (int) retries { - self = [super init]; + if ((self = [super init])) { - SecKeyRef signingKey = GenerateFullECKey(256, NULL); - SecKeyRef octagonSigningKey = GenerateFullECKey(384, NULL); - SecKeyRef octagonEncryptionKey = GenerateFullECKey(384, NULL); + SecKeyRef signingKey = GenerateFullECKey(256, NULL); + SecKeyRef octagonSigningKey = GenerateFullECKey(384, NULL); + SecKeyRef octagonEncryptionKey = GenerateFullECKey(384, NULL); - SOSPeerInfoRef newPeerInfo = SOSPeerInfoCreate(NULL, (__bridge CFDictionaryRef) @{(__bridge NSString*)kPIUserDefinedDeviceNameKey:@"Fakey"}, NULL, signingKey, octagonSigningKey, octagonEncryptionKey, NULL); + SOSPeerInfoRef newPeerInfo = SOSPeerInfoCreate(NULL, (__bridge CFDictionaryRef) @{(__bridge NSString*)kPIUserDefinedDeviceNameKey:@"Fakey"}, NULL, signingKey, octagonSigningKey, octagonEncryptionKey, NULL); + + if (newPeerInfo == NULL) { + return nil; + } + self.peerInfo = newPeerInfo; + CFRelease(newPeerInfo); + newPeerInfo = NULL; + + self.sharedSecret = secret; + self.incorrectSecret = incorrectSecret; + self.incorrectTries = retries; - if (newPeerInfo == NULL) { - return nil; } - self.peerInfo = newPeerInfo; - CFRelease(newPeerInfo); - newPeerInfo = NULL; - - self.sharedSecret = secret; - self.incorrectSecret = incorrectSecret; - self.incorrectTries = retries; - return self; } @@ -206,18 +187,17 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { } - (id) initWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code { - self = [super init]; + if ((self = [super init])) { + self->_secrets = secrets; + self.currentSecret = 0; + self->_retriesPerSecret = retries; + self->_retriesLeft = self.retriesPerSecret; - self->_secrets = secrets; - self.currentSecret = 0; - self->_retriesPerSecret = retries; - self->_retriesLeft = self.retriesPerSecret; - - self->_codeToUse = code; - - uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; - self->_circleJoinData = [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ]; + self->_codeToUse = code; + uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + self->_circleJoinData = [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ]; + } return self; } @@ -288,7 +268,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret]; KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; NSData* initialMessage = [requestSession initialMessage: &error]; @@ -300,7 +280,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate circleDelegate:acceptDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; error = nil; @@ -383,7 +363,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret incorrectSecret:@"777888" incorrectTries:3]; KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; NSData* initialMessage = [requestSession initialMessage: &error]; @@ -395,7 +375,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate circleDelegate:acceptDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; error = nil; @@ -489,7 +469,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret]; KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; NSData* initialMessage = [requestSession initialMessage: &error]; @@ -501,7 +481,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate circleDelegate:acceptDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; error = nil; diff --git a/KeychainCircle/Tests/KCParing.plist b/KeychainCircle/Tests/KCParing.plist index 137bf077..112ebe33 100644 --- a/KeychainCircle/Tests/KCParing.plist +++ b/KeychainCircle/Tests/KCParing.plist @@ -24,7 +24,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testSecPairBasicTest KCPairing.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testSecPairBasicTest + KCPairing.xctest diff --git a/KeychainCircle/Tests/KCSRPTests.m b/KeychainCircle/Tests/KCSRPTests.m index e518a261..6a516cd4 100644 --- a/KeychainCircle/Tests/KCSRPTests.m +++ b/KeychainCircle/Tests/KCSRPTests.m @@ -10,7 +10,6 @@ #include #include #include -#include @interface KCSRPTests : XCTestCase @@ -102,7 +101,7 @@ [self negotiateWithUser: @"TestUser" digestInfo: ccsha256_di() group: ccsrp_gp_rfc5054_3072() - randomSource: ccDRBGGetRngState()]; + randomSource: ccrng(NULL)]; } @end diff --git a/KeychainCircle/Tests/KCTLKRequestTest.m b/KeychainCircle/Tests/KCTLKRequestTest.m new file mode 100644 index 00000000..8ab9c015 --- /dev/null +++ b/KeychainCircle/Tests/KCTLKRequestTest.m @@ -0,0 +1,304 @@ +#import + +#import + +#import +#import +#import +#import +#import +#import + +#include +#include "keychain/SecureObjectSync/SOSFullPeerInfo.h" +#include "keychain/SecureObjectSync/SOSPeerInfoInternal.h" + +#include + +static NSData* createTlkRequestMessage (KCAESGCMDuplexSession* aesSession) { + char someData[] = {1,2,3,4,5,6}; + NSError* error = NULL; + NSData* rndPadding = [NSData dataWithBytes:(void*)someData length:sizeof(someData)]; + KCJoiningMessage* tlkRequestMessage = [KCJoiningMessage messageWithType: kTLKRequest data:rndPadding error:&error]; + return [tlkRequestMessage der]; +} + +@interface KCJoiningRequestTestDelegate : NSObject +@property (readwrite) NSString* sharedSecret; + +@property (readonly) NSString* accountCode; +@property (readonly) NSData* circleJoinData; + +@property (readwrite) NSString* incorrectSecret; +@property (readwrite) int incorrectTries; + + ++ (id) requestDelegateWithSecret:(NSString*) secret; +- (id) init NS_UNAVAILABLE; +- (id) initWithSecret: (NSString*) secret + incorrectSecret: (NSString*) wrongSecret + incorrectTries: (int) retries NS_DESIGNATED_INITIALIZER; +- (NSString*) secret; +- (NSString*) verificationFailed: (bool) codeChanged; +- (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error; +- (bool) processCircleJoinData: (NSData*) circleJoinData version:(PiggyBackProtocolVersion)version error: (NSError**)error ; +- (bool) processAccountCode: (NSString*) accountCode error: (NSError**)error; + +@end + +@implementation KCJoiningRequestTestDelegate + ++ (id) requestDelegateWithSecret:(NSString*) secret { + return [[KCJoiningRequestTestDelegate alloc] initWithSecret:secret + incorrectSecret:@"" + incorrectTries:0]; +} + ++ (id) requestDelegateWithSecret:(NSString*) secret + incorrectSecret:(NSString*) wrongSecret + incorrectTries:(int) retries { + return [[KCJoiningRequestTestDelegate alloc] initWithSecret:secret + incorrectSecret:wrongSecret + incorrectTries:retries]; +} + + +- (id) initWithSecret: (NSString*) secret + incorrectSecret: (NSString*) incorrectSecret + incorrectTries: (int) retries { + if ( self = [super init] ) { + self.sharedSecret = secret; + self.incorrectSecret = incorrectSecret; + self.incorrectTries = retries; + } + return self; +} + +- (NSString*) nextSecret { + if (self.incorrectTries > 0) { + self.incorrectTries -= 1; + return self.incorrectSecret; + } + return self.sharedSecret; +} + +- (NSString*) secret { + return [self nextSecret]; +} + +- (NSString*) verificationFailed: (bool) codeChanged { + return [self nextSecret]; +} + +- (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error { + return NULL; +} + +- (bool) processCircleJoinData: (NSData*) circleJoinData version:(PiggyBackProtocolVersion)version error: (NSError**)error { + self->_circleJoinData = circleJoinData; + return true; +} + +- (bool) processAccountCode: (NSString*) accountCode error: (NSError**)error { + self->_accountCode = accountCode; + return true; +} + +@end + +@interface KCJoiningAcceptTestDelegate : NSObject +@property (readonly) NSArray* secrets; +@property (readwrite) NSUInteger currentSecret; +@property (readwrite) int retriesLeft; +@property (readwrite) int retriesPerSecret; + +@property (readonly) NSString* codeToUse; +@property (readonly) NSData* circleJoinData; +@property (readonly) SOSPeerInfoRef peerInfo; + ++ (id) acceptDelegateWithSecret: (NSString*) secret code: (NSString*) code; ++ (id) acceptDelegateWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code; +- (id) initWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code NS_DESIGNATED_INITIALIZER; + +- (NSString*) secret; +- (NSString*) accountCode; + +- (KCRetryOrNot) verificationFailed: (NSError**) error; +- (NSData*) circleJoinDataFor: (SOSPeerInfoRef) peer + error: (NSError**) error; + +- (id) init NS_UNAVAILABLE; + +@end + +@implementation KCJoiningAcceptTestDelegate + ++ (id) acceptDelegateWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code { + return [[KCJoiningAcceptTestDelegate alloc] initWithSecrets:secrets retries:retries code:code]; + +} + ++ (id) acceptDelegateWithSecret: (NSString*) secret code: (NSString*) code { + return [[KCJoiningAcceptTestDelegate alloc] initWithSecret:secret code:code]; +} + +- (id) initWithSecret: (NSString*) secret code: (NSString*) code { + return [self initWithSecrets:@[secret] retries:3 code:code]; +} + +- (id) initWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code { + if ((self = [super init])) { + self->_secrets = secrets; + self.currentSecret = 0; + self->_retriesPerSecret = retries; + self->_retriesLeft = self.retriesPerSecret; + + self->_codeToUse = code; + + uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + self->_circleJoinData = [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ]; + } + return self; +} + +- (KCRetryOrNot) advanceSecret { + if (self.retriesLeft == 0) { + self.currentSecret += 1; + if (self.currentSecret >= [self.secrets count]) { + self.currentSecret = [self.secrets count] - 1; + } + self.retriesLeft = self.retriesPerSecret; + return kKCRetryWithNewChallenge; + } else { + self.retriesLeft -= 1; + return kKCRetryWithSameChallenge; + } +} + +- (NSString*) secret { + return self.secrets[self.currentSecret]; +} +- (NSString*) accountCode { + return self.codeToUse; +} + +- (KCRetryOrNot) verificationFailed: (NSError**) error { + return [self advanceSecret]; +} + +- (NSData*) circleJoinDataFor: (SOSPeerInfoRef) peer + error: (NSError**) error { + uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + + self->_peerInfo = peer; + return [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ]; +} + +-(NSData*) circleGetInitialSyncViews:(SOSInitialSyncFlags)flags error:(NSError**) error{ + char testData[] = {0,1,2,3,4,5,6,7,8,9}; + return [NSData dataWithBytes:testData length:sizeof(testData)]; + //return [[KCJoiningAcceptAccountCircleDelegate delegate] circleGetInitialSyncViews:flags error:error]; //Need security entitlements! +} + +@end + +@interface KCTLKRequestTest : XCTestCase + +@end + +@implementation KCTLKRequestTest + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testTLKRequest { + NSError* error = nil; + + NSString* secret = @"123456"; + NSString* code = @"987654"; + + uint64_t dsid = 0x1234567887654321; + + KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret]; + KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate + dsid:dsid + rng:ccDRBGGetRngState() + error:&error]; + + NSData* initialMessage = [requestSession initialMessage: &error]; + + XCTAssertNotNil(initialMessage, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + KCJoiningAcceptTestDelegate* acceptDelegate = [KCJoiningAcceptTestDelegate acceptDelegateWithSecret:secret code:code]; + KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate + circleDelegate:acceptDelegate + dsid:dsid + rng:ccDRBGGetRngState() + error:&error]; + + error = nil; + NSData* challenge = [acceptSession processMessage: initialMessage error: &error]; + + XCTAssertNotNil(challenge, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + error = nil; + NSData* response = [requestSession processMessage: challenge error: &error]; + + XCTAssertNotNil(response, @"No response message"); + XCTAssertNil(error, @"Got error %@", error); + + error = nil; + NSData* verification = [acceptSession processMessage: response error: &error]; + + XCTAssertNotNil(verification, @"No verification message"); + XCTAssertNil(error, @"Got error %@", error); + + error = nil; + NSData* doneMessage = [requestSession processMessage: verification error: &error]; + + XCTAssertNotNil(doneMessage, @"No response message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertTrue([requestSession isDone], @"SecretSession done"); + XCTAssertFalse([acceptSession isDone], @"Unexpected accept session done"); + + KCAESGCMDuplexSession* aesSession = [requestSession session]; + requestSession = nil; + + KCJoiningRequestCircleSession* requestSecretSession = [KCJoiningRequestCircleSession sessionWithCircleDelegate:requestDelegate session:aesSession error:&error]; + + XCTAssertNotNil(requestSecretSession, @"No request secret session"); + XCTAssertNil(error, @"Got error %@", error); + + NSData* tlkRequestMessage = createTlkRequestMessage(aesSession); + XCTAssertNotNil(tlkRequestMessage, @"No TLKRequest message"); + + NSData* tlkMessage = [acceptSession processMessage:tlkRequestMessage error:&error]; + XCTAssertNotNil(tlkMessage, @"No tlkData message"); + XCTAssertNil(error, @"Got error %@", error); + + KCJoiningMessage* receivedKCJoinMessage = [KCJoiningMessage messageWithDER:tlkMessage error:&error]; + XCTAssertNotNil(receivedKCJoinMessage, @"No receivedKCJoinMessage message"); + XCTAssertNil(error, @"Got error %@", error); + + NSData* tlkDecryptedData = [aesSession decryptAndVerify:receivedKCJoinMessage.firstData error:&error]; + XCTAssertNotNil(tlkDecryptedData, @"No tlkDecryptedData message"); + XCTAssertNil(error, @"Got error %@", error); + + //check for tlkc content + NSData* initialSync = [acceptDelegate circleGetInitialSyncViews:kSOSInitialSyncFlagTLKs error:&error]; + XCTAssertNotNil(initialSync, @"No initialSync data"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertEqualObjects(initialSync, tlkDecryptedData, @"TLK data is different."); +} +@end diff --git a/KeychainCircle/Tests/KeychainCircle.plist b/KeychainCircle/Tests/KeychainCircle.plist index daf13f84..d34989d6 100644 --- a/KeychainCircle/Tests/KeychainCircle.plist +++ b/KeychainCircle/Tests/KeychainCircle.plist @@ -24,7 +24,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest KCDerTest KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + KCDerTest + KeychainCircleTests.xctest @@ -38,7 +45,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testAESGCMDuplex KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testAESGCMDuplex + KeychainCircleTests.xctest @@ -52,7 +66,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testAESGCMDuplexCoding KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testAESGCMDuplexCoding + KeychainCircleTests.xctest @@ -66,7 +87,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSession KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testJoiningSession + KeychainCircleTests.xctest @@ -80,7 +108,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSessionRetry KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testJoiningSessionRetry + KeychainCircleTests.xctest @@ -94,7 +129,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSessionCodeChange KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testJoiningSessionCodeChange + KeychainCircleTests.xctest diff --git a/KeychainEntitledTestApp_ios/AppDelegate.h b/KeychainEntitledTestApp_ios/AppDelegate.h deleted file mode 100644 index 998155c0..00000000 --- a/KeychainEntitledTestApp_ios/AppDelegate.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// AppDelegate.h -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/KeychainEntitledTestApp_ios/AppDelegate.m b/KeychainEntitledTestApp_ios/AppDelegate.m deleted file mode 100644 index 7905ddac..00000000 --- a/KeychainEntitledTestApp_ios/AppDelegate.m +++ /dev/null @@ -1,51 +0,0 @@ -// -// AppDelegate.m -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. -} - - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. -} - - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - - -@end diff --git a/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json b/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d8db8d65..00000000 --- a/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - }, - { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/KeychainEntitledTestApp_ios/Info.plist b/KeychainEntitledTestApp_ios/Info.plist deleted file mode 100644 index d0524738..00000000 --- a/KeychainEntitledTestApp_ios/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/KeychainEntitledTestApp_ios/ViewController.h b/KeychainEntitledTestApp_ios/ViewController.h deleted file mode 100644 index 2300ca20..00000000 --- a/KeychainEntitledTestApp_ios/ViewController.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// ViewController.h -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -@interface ViewController : UIViewController - - -@end - diff --git a/KeychainEntitledTestApp_ios/ViewController.m b/KeychainEntitledTestApp_ios/ViewController.m deleted file mode 100644 index 30c0bb6d..00000000 --- a/KeychainEntitledTestApp_ios/ViewController.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// ViewController.m -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import "ViewController.h" - -@interface ViewController () - -@end - -@implementation ViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view, typically from a nib. -} - - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - - -@end diff --git a/KeychainEntitledTestApp_mac/AppDelegate.h b/KeychainEntitledTestApp_mac/AppDelegate.h deleted file mode 100644 index 5452eb93..00000000 --- a/KeychainEntitledTestApp_mac/AppDelegate.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// AppDelegate.h -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -@interface AppDelegate : NSObject - - -@end - diff --git a/KeychainEntitledTestApp_mac/AppDelegate.m b/KeychainEntitledTestApp_mac/AppDelegate.m deleted file mode 100644 index e1e6dc39..00000000 --- a/KeychainEntitledTestApp_mac/AppDelegate.m +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.m -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - // Insert code here to initialize your application -} - - -- (void)applicationWillTerminate:(NSNotification *)aNotification { - // Insert code here to tear down your application -} - - -@end diff --git a/KeychainEntitledTestApp_mac/ViewController.h b/KeychainEntitledTestApp_mac/ViewController.h deleted file mode 100644 index 3a40d4b2..00000000 --- a/KeychainEntitledTestApp_mac/ViewController.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// ViewController.h -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -@interface ViewController : NSViewController - - -@end - diff --git a/KeychainEntitledTestApp_mac/main.m b/KeychainEntitledTestApp_mac/main.m deleted file mode 100644 index bc0cd59e..00000000 --- a/KeychainEntitledTestApp_mac/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -int main(int argc, const char * argv[]) { - return NSApplicationMain(argc, argv); -} diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m index 030606c4..cc31d676 100644 --- a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m @@ -30,10 +30,12 @@ // was asked to file this radar for accounts: Invoke DataclassOwner when enabling or signing into an account - (void)account:(ACAccount *)account didChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount { - if((changeType == kACAccountChangeTypeAdded || changeType == kACAccountChangeTypeModified) && + if((changeType == kACAccountChangeTypeAdded || changeType == kACAccountChangeTypeModified || changeType == kACAccountChangeTypeWarmingUp) && [account.accountType.identifier isEqualToString: ACAccountTypeIdentifierAppleAccount] && [self accountIsPrimary:account]) { + SOSCCLoggedIntoAccount(NULL); + #if OCTAGON if(OctagonIsEnabled()){ NSString* altDSID = [account aa_altDSID]; diff --git a/Modules/OctagonTrust.modulemap b/Modules/OctagonTrust.modulemap new file mode 100644 index 00000000..be8cef68 --- /dev/null +++ b/Modules/OctagonTrust.modulemap @@ -0,0 +1,6 @@ +framework module OctagonTrust [system] { + umbrella header "OctagonTrust.h" + + export * + module * { export * } +} diff --git a/Modules/Security.iOS.modulemap b/Modules/Security.iOS.modulemap index 19cd51d0..7672ee88 100644 --- a/Modules/Security.iOS.modulemap +++ b/Modules/Security.iOS.modulemap @@ -1,4 +1,4 @@ -framework module Security [extern_c] { +framework module Security [extern_c][system] { umbrella header "Security.h" export * diff --git a/Modules/Security.macOS.modulemap b/Modules/Security.macOS.modulemap index e183b646..935d8655 100644 --- a/Modules/Security.macOS.modulemap +++ b/Modules/Security.macOS.modulemap @@ -1,4 +1,4 @@ -framework module Security [extern_c] { +framework module Security [extern_c][system] { umbrella header "Security.h" export * diff --git a/Modules/Security.macOS.private.modulemap b/Modules/Security.macOS.private.modulemap index 9645c117..83865039 100644 --- a/Modules/Security.macOS.private.modulemap +++ b/Modules/Security.macOS.private.modulemap @@ -1,4 +1,4 @@ -module Security.SecTask [extern_c] { +module Security.SecTask [extern_c][system] { header "SecTask.h" export * } diff --git a/OSX/Breadcrumb/README b/OSX/Breadcrumb/README deleted file mode 100644 index 894c607d..00000000 --- a/OSX/Breadcrumb/README +++ /dev/null @@ -1,99 +0,0 @@ -Breadcrumbs -=========== - -simple defintions: - - old password - new password - K = random 16 byte key - EK = Encrypted K - EKold = ECB(PBKDF2(password_old), K) - EKnew = ECB(PBKDF2(password_new), K) - Breadcrumb = AES-GCM(K, old password) - - -Breadcrumbs are to make life easier when using AppleID password as -local password by allowing upgrade of keychains from old password to new -password. - -When changing the password on one machine, the keychains for the user are -still encrypted (AES-GCM, key derived using PBKDF2) with the old password on -all machines. - -This happens for one machine when changing password on the AppleID.apple.com webpage. - -An EK is stored on the apple server. Each machine have its own EK stored on the web server. - -When user change the password on the AppleID.apple.com website, the -web server will unwrap the key K with the old password and then rewrap -it with the new password. - - unwrap(EKold, old password) -> K - wrap(K, new password) -> EKnew - -This means that if the user changes password more then ones, the computer can still upgrade the keychain to the current password since K will be the same until a new EK is uploaded the the computer. - -PKDF2 is used to avoid prebuilt lists of string2key tables attacks on -the breadcrumb + encryptedKey if the attacker possesses both. - -Breadcrumb contain current password that encrypts the keychain. The breadcrumb itself is encrypted with a machine-specific key K. - -The breadcrumb is stored on the local machine and never leaves the -local machine. - -When the computer have upgrade keychain to the current password and new K, EK, and breadcrumb is generated. - -Format -====== - -K = Random 16 byte -EK = ECB(PBKDF2(pw), key K) (16byte) | pbkdf-salt (20byte) | 4byte int network order of pbdf-iter -Breadcrumb = version (1) 1byte | AES-GCM-ENC(key K, password length (4byte, network order) | password | pad ) | tag - -The encrypted key (EK) is a PKDF2 salt + iteration count + random AES-128 key (K) -encrypted with ECB of the PKDF2(salt, iteration, password). - -There is no integrity on this encryption on purpose since that would make the -EK an verifier. - -The format of the EncryptedKey is - - ECB(PBKDF2(pw), key K) (16byte) | pbkdf-salt (20byte) | 4byte int network order of pbdf-iter - -The random key (K) is used to encrypt a breadcrumb that is stored -locally on the machine. The breadcrumb allows you to recover the old -password if you know the new password and have the encrypted key. - -The client machine encrypts the password with AES-GCM using key K. The data -is padded to 256 bytes to no tell password length. - -The format of the breadcrumb - - version (1) 1byte | AES-GCM-ENC(key K, password length (4byte, network order) | password | pad ) | tag - -tag is the 16 byte GCM tag -key is the key (K) from the EncryptedKey (EK) -assoc data i AES-GCM covers version byte - -Password length including up to pad is encrypted with AES-GCM - -Password is padded to paddingSize (256) to avoid exposing length of password. - -The PBKDF2 function is PBKDF2-HMAC-SHA256. - - -Updating the Encrypted Key (EK) on server -========================================= - -When a user update the password on the apple id server the server -updates the breadcrumb for each machine that the user have associsated -with the account. - -1. The server takes the old password generates a the key using PBKDF2 - using the salt and interation count. - -2. The server takes the new password generates a the key using PBKDF2 - using the same salt and interation count. - -3. Decrypts the first block with the key of old password and - re-encrypt with the key of new password. diff --git a/OSX/Breadcrumb/SecBreadcrumb.c b/OSX/Breadcrumb/SecBreadcrumb.c deleted file mode 100644 index 067c93c5..00000000 --- a/OSX/Breadcrumb/SecBreadcrumb.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (c) 2014 - 2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#import "SecCFAllocator.h" - -#define CFReleaseNull(CF) ({ __typeof__(CF) *const _pcf = &(CF), _cf = *_pcf; (_cf ? (*_pcf) = ((__typeof__(CF))0), (CFRelease(_cf), ((__typeof__(CF))0)) : _cf); }) - -#define kBCKeySize CCAES_KEY_SIZE_128 -#define kBCSaltSize 20 -#define kBCIterations 5000 -#define BCTagLen 16 -#define BCIVLen 16 -#define BCversion1 1 -#define BCversion2 2 -#define BCPaddingSize 256 -#define BCMaxSize 1024 - -Boolean -SecBreadcrumbCreateFromPassword(CFStringRef inPassword, - CFDataRef *outBreadcrumb, - CFDataRef *outEncryptedKey, - CFErrorRef *outError) -{ - const struct ccmode_ecb *ecb = ccaes_ecb_encrypt_mode(); - const struct ccmode_gcm *gcm = ccaes_gcm_encrypt_mode(); - uint8_t iv[BCIVLen]; - CFMutableDataRef key, npw; - CFDataRef pw; - - *outBreadcrumb = NULL; - *outEncryptedKey = NULL; - if (outError) - *outError = NULL; - - key = CFDataCreateMutable(SecCFAllocatorZeroize(), 0); - if (key == NULL) - return false; - - CFDataSetLength(key, kBCKeySize + kBCSaltSize + 4); - if (SecRandomCopyBytes(kSecRandomDefault, CFDataGetLength(key) - 4, CFDataGetMutableBytePtr(key)) != 0) { - CFReleaseNull(key); - return false; - } - if (SecRandomCopyBytes(kSecRandomDefault, BCIVLen, iv) != 0) { - CFReleaseNull(key); - return false; - } - - uint32_t size = htonl(kBCIterations); - memcpy(CFDataGetMutableBytePtr(key) + kBCKeySize + kBCSaltSize, &size, sizeof(size)); - - /* - * Create data for password - */ - - pw = CFStringCreateExternalRepresentation(SecCFAllocatorZeroize(), inPassword, kCFStringEncodingUTF8, 0); - if (pw == NULL) { - CFReleaseNull(key); - return false; - } - - const CFIndex passwordLength = CFDataGetLength(pw); - - if (passwordLength > BCMaxSize) { - CFReleaseNull(pw); - CFReleaseNull(key); - return false; - } - - CFIndex paddedSize = passwordLength + BCPaddingSize - (passwordLength % BCPaddingSize); - const CFIndex outLength = 1 + BCIVLen + 4 + paddedSize + BCTagLen; - - npw = CFDataCreateMutable(NULL, outLength); - if (npw == NULL) { - CFReleaseNull(pw); - CFReleaseNull(key); - return false; - } - CFDataSetLength(npw, outLength); - - cc_clear(outLength, CFDataGetMutableBytePtr(npw)); - CFDataGetMutableBytePtr(npw)[0] = BCversion2; - memcpy(CFDataGetMutableBytePtr(npw) + 1, iv, BCIVLen); - size = htonl(passwordLength); - memcpy(CFDataGetMutableBytePtr(npw) + 1 + BCIVLen, &size, sizeof(size)); - memcpy(CFDataGetMutableBytePtr(npw) + 1 + BCIVLen + 4, CFDataGetBytePtr(pw), passwordLength); - - /* - * Now create a GCM encrypted password using the random key - */ - - ccgcm_ctx_decl(gcm->size, ctx); - ccgcm_init(gcm, ctx, kBCKeySize, CFDataGetMutableBytePtr(key)); - ccgcm_set_iv(gcm, ctx, BCIVLen, iv); - ccgcm_gmac(gcm, ctx, 1, CFDataGetMutableBytePtr(npw)); - ccgcm_update(gcm, ctx, outLength - BCTagLen - BCIVLen - 1, CFDataGetMutableBytePtr(npw) + 1 + BCIVLen, CFDataGetMutableBytePtr(npw) + 1 + BCIVLen); - ccgcm_finalize(gcm, ctx, BCTagLen, CFDataGetMutableBytePtr(npw) + outLength - BCTagLen); - ccgcm_ctx_clear(gcm->size, ctx); - - /* - * Wrapping key is PBKDF2(sha256) over password - */ - - const struct ccdigest_info *di = ccsha256_di(); - uint8_t rawkey[CCSHA256_OUTPUT_SIZE]; - _Static_assert(sizeof(rawkey) >= kBCKeySize, "keysize changed w/o updating digest"); - if (sizeof(rawkey) != di->output_size) abort(); - - if (ccpbkdf2_hmac(di, CFDataGetLength(pw), CFDataGetBytePtr(pw), - kBCSaltSize, CFDataGetMutableBytePtr(key) + kBCKeySize, - kBCIterations, - sizeof(rawkey), rawkey) != 0) - abort(); - - /* - * Wrap the random key with one round of ECB cryto - */ - - ccecb_ctx_decl(ccecb_context_size(ecb), ecbkey); - ccecb_init(ecb, ecbkey, kBCKeySize, rawkey); - ccecb_update(ecb, ecbkey, 1, CFDataGetMutableBytePtr(key), CFDataGetMutableBytePtr(key)); - ccecb_ctx_clear(ccecb_context_size(ecb), ecbkey); - - /* - * - */ - - cc_clear(sizeof(rawkey), rawkey); - CFReleaseNull(pw); - - *outBreadcrumb = npw; - *outEncryptedKey = key; - - return true; -} - - -Boolean -SecBreadcrumbCopyPassword(CFStringRef inPassword, - CFDataRef inBreadcrumb, - CFDataRef inEncryptedKey, - CFStringRef *outPassword, - CFErrorRef *outError) -{ - const struct ccmode_ecb *ecb = ccaes_ecb_decrypt_mode(); - CFMutableDataRef gcmkey, oldpw; - CFIndex outLength; - CFDataRef pw; - uint32_t size; - - *outPassword = NULL; - if (outError) - *outError = NULL; - - if (CFDataGetLength(inEncryptedKey) < kBCKeySize + kBCSaltSize + 4) { - return false; - } - - if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion1) { - if (CFDataGetLength(inBreadcrumb) < 1 + 4 + BCPaddingSize + BCTagLen) - return false; - - outLength = CFDataGetLength(inBreadcrumb) - 1 - BCTagLen; - } else if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion2) { - if (CFDataGetLength(inBreadcrumb) < 1 + BCIVLen + 4 + BCPaddingSize + BCTagLen) - return false; - outLength = CFDataGetLength(inBreadcrumb) - 1 - BCIVLen - BCTagLen; - } else { - return false; - } - - gcmkey = CFDataCreateMutableCopy(SecCFAllocatorZeroize(), 0, inEncryptedKey); - if (gcmkey == NULL) { - return false; - } - - if ((outLength % 16) != 0 && outLength < 4) { - CFReleaseNull(gcmkey); - return false; - } - - oldpw = CFDataCreateMutable(SecCFAllocatorZeroize(), outLength); - if (oldpw == NULL) { - CFReleaseNull(gcmkey); - return false; - } - CFDataSetLength(oldpw, outLength); - - /* - * Create data for password - */ - - pw = CFStringCreateExternalRepresentation(SecCFAllocatorZeroize(), inPassword, kCFStringEncodingUTF8, 0); - if (pw == NULL) { - CFReleaseNull(oldpw); - CFReleaseNull(gcmkey); - return false; - } - - /* - * Wrapping key is HMAC(sha256) over password - */ - - const struct ccdigest_info *di = ccsha256_di(); - uint8_t rawkey[CCSHA256_OUTPUT_SIZE]; - _Static_assert(sizeof(rawkey) >= kBCKeySize, "keysize changed w/o updating digest"); - if (sizeof(rawkey) != di->output_size) abort(); - - memcpy(&size, CFDataGetMutableBytePtr(gcmkey) + kBCKeySize + kBCSaltSize, sizeof(size)); - size = ntohl(size); - - if (ccpbkdf2_hmac(di, CFDataGetLength(pw), CFDataGetBytePtr(pw), - kBCSaltSize, CFDataGetMutableBytePtr(gcmkey) + kBCKeySize, - size, - sizeof(rawkey), rawkey) != 0) - abort(); - - CFReleaseNull(pw); - - /* - * Unwrap the random key with one round of ECB cryto - */ - - ccecb_ctx_decl(ccecb_context_size(ecb), ecbkey); - ccecb_init(ecb, ecbkey, kBCKeySize, rawkey); - ccecb_update(ecb, ecbkey, 1, CFDataGetMutableBytePtr(gcmkey), CFDataGetMutableBytePtr(gcmkey)); - ccecb_ctx_clear(ccecb_context_size(ecb), ecbkey); - /* - * GCM unwrap - */ - - uint8_t tag[BCTagLen]; - - if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion1) { - memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, BCTagLen); - - ccgcm_one_shot_legacy(ccaes_gcm_decrypt_mode(), kBCKeySize, CFDataGetMutableBytePtr(gcmkey), 0, NULL, 1, CFDataGetBytePtr(inBreadcrumb), - outLength, CFDataGetBytePtr(inBreadcrumb) + 1, CFDataGetMutableBytePtr(oldpw), BCTagLen, tag); - if (memcmp(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, BCTagLen) != 0) { - CFReleaseNull(oldpw); - CFReleaseNull(gcmkey); - return false; - } - - } else { - const uint8_t *iv = CFDataGetBytePtr(inBreadcrumb) + 1; - int res; - memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + BCIVLen + outLength, BCTagLen); - - res = ccgcm_one_shot(ccaes_gcm_decrypt_mode(), kBCKeySize, CFDataGetMutableBytePtr(gcmkey), - BCIVLen, iv, - 1, CFDataGetBytePtr(inBreadcrumb), - outLength, CFDataGetBytePtr(inBreadcrumb) + 1 + BCIVLen, CFDataGetMutableBytePtr(oldpw), - BCTagLen, tag); - if (res) { - CFReleaseNull(gcmkey); - CFReleaseNull(oldpw); - CFReleaseNull(gcmkey); - return false; - } - } - - CFReleaseNull(gcmkey); - - - memcpy(&size, CFDataGetMutableBytePtr(oldpw), sizeof(size)); - size = ntohl(size); - if ((ssize_t) size > outLength - 4) { - CFReleaseNull(oldpw); - return false; - } - memmove(CFDataGetMutableBytePtr(oldpw), CFDataGetMutableBytePtr(oldpw) + 4, size); - CFDataSetLength(oldpw, size); - - *outPassword = CFStringCreateFromExternalRepresentation(SecCFAllocatorZeroize(), oldpw, kCFStringEncodingUTF8); - CFReleaseNull(oldpw); - - return true; -} - -CFDataRef -SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, - CFStringRef newPassword, - CFDataRef encryptedKey, - CFErrorRef *outError) -{ - const struct ccmode_ecb *enc = ccaes_ecb_encrypt_mode(); - const struct ccmode_ecb *dec = ccaes_ecb_decrypt_mode(); - const struct ccdigest_info *di = ccsha256_di(); - uint8_t rawkey[CCSHA256_OUTPUT_SIZE]; - CFDataRef newpw = NULL, oldpw = NULL; - CFMutableDataRef newEncryptedKey; - - _Static_assert(sizeof(rawkey) >= kBCKeySize, "keysize changed w/o updating digest"); - if (sizeof(rawkey) != di->output_size) abort(); - - if (CFDataGetLength(encryptedKey) < kBCKeySize + kBCSaltSize + 4) { - return NULL; - } - - newEncryptedKey = CFDataCreateMutableCopy(SecCFAllocatorZeroize(), 0, encryptedKey); - if (newEncryptedKey == NULL) { - return NULL; - } - - oldpw = CFStringCreateExternalRepresentation(SecCFAllocatorZeroize(), oldPassword, kCFStringEncodingUTF8, 0); - if (oldpw == NULL) { - CFReleaseNull(newEncryptedKey); - return false; - } - - newpw = CFStringCreateExternalRepresentation(SecCFAllocatorZeroize(), newPassword, kCFStringEncodingUTF8, 0); - if (newpw == NULL) { - CFReleaseNull(newEncryptedKey); - CFReleaseNull(oldpw); - return false; - } - - /* - * Unwrap with new key - */ - - uint32_t iter; - - memcpy(&iter, CFDataGetMutableBytePtr(newEncryptedKey) + kBCKeySize + kBCSaltSize, sizeof(iter)); - iter = ntohl(iter); - - if (ccpbkdf2_hmac(di, CFDataGetLength(oldpw), CFDataGetBytePtr(oldpw), - kBCSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kBCKeySize, - iter, - sizeof(rawkey), rawkey) != 0) - abort(); - - CFReleaseNull(oldpw); - - - ccecb_ctx_decl(dec->size, deckey); - ccecb_init(dec, deckey, kBCKeySize, rawkey); - ccecb_update(dec, deckey, 1, CFDataGetMutableBytePtr(newEncryptedKey), CFDataGetMutableBytePtr(newEncryptedKey)); - ccecb_ctx_clear(ccecb_context_size(dec), deckey); - - cc_clear(sizeof(rawkey), rawkey); - - /* - * Re-wrap with new key - */ - - if (ccpbkdf2_hmac(di, CFDataGetLength(newpw), CFDataGetBytePtr(newpw), - kBCSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kBCKeySize, - iter, - sizeof(rawkey), rawkey) != 0) - abort(); - - CFReleaseNull(newpw); - - - ccecb_ctx_decl(enc->size, enckey); - ccecb_init(enc, enckey, kBCKeySize, rawkey); - ccecb_update(enc, enckey, 1, CFDataGetMutableBytePtr(newEncryptedKey), CFDataGetMutableBytePtr(newEncryptedKey)); - ccecb_ctx_clear(ccecb_context_size(enc), enckey); - - cc_clear(sizeof(rawkey), rawkey); - - return newEncryptedKey; -} diff --git a/OSX/Breadcrumb/SecBreadcrumb.h b/OSX/Breadcrumb/SecBreadcrumb.h deleted file mode 100644 index e7cc4088..00000000 --- a/OSX/Breadcrumb/SecBreadcrumb.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2014 - 2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - @function SecBreadcrumbCreateFromPassword - @abstract Encryptes the password using a random key and then returns - the encrypted password (breadcrumb) and the password encrypted random key. - - @param inPassword is the password to encrypt and use to encrypt the random key. - @param outBreadcrumb is the password encrypted using a random key. - @param outEncryptedKey is the random key encrypted using inPassword. - @param outError An optional pointer to a CFErrorRef. This value is set - if an error occurred. If not NULL, the caller is responsible for - releasing the CFErrorRef. - @result On return a Boolean indicating success or failure. - - @discussion This function generates the breadcrumb that will be used to - update the user's keychain password when their Apple ID Login password - is changed on appleid.apple.com. -*/ - -Boolean -SecBreadcrumbCreateFromPassword(CFStringRef inPassword, - CFDataRef *outBreadcrumb, - CFDataRef *outEncryptedKey, - CFErrorRef *outError); - - -/*! - @function SecBreadcrumbCopyPassword - @abstract Decryptes the encrypted key using the password and uses the key to - decrypt the breadcrumb and returns the password stored in the breadcrumb. - - @param inPassword is the password to decrypt the encrypted random key. - @param inBreadcrumb is the breadcrumb encrypted by the key. It contains - and encrypted version of the users old password. - @param inEncryptedKey is an encrypted version of the key used to encrypt the - breadcrumb. - @param outPassword is the cleartext password that was stored in the breadcrumb. - @param outError An optional pointer to a CFErrorRef. This value is set - if an error occurred. If not NULL, the caller is responsible for - releasing the CFErrorRef. - @result On return a Boolean indicating success or failure. - - @discussion This function uses the password to decrypt the encrypted key and then - uses that key to decrypt the breadcrumb. -*/ - -Boolean -SecBreadcrumbCopyPassword(CFStringRef inPassword, - CFDataRef inBreadcrumb, - CFDataRef inEncryptedKey, - CFStringRef *outPassword, - CFErrorRef *outError); - -/* - * Change password used to encrypt the key from old password to new password - */ - -CFDataRef -SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, - CFStringRef newPassword, - CFDataRef encryptedKey, - CFErrorRef *outError); diff --git a/OSX/Breadcrumb/bc-10-knife-on-bread.m b/OSX/Breadcrumb/bc-10-knife-on-bread.m deleted file mode 100644 index a3f80db3..00000000 --- a/OSX/Breadcrumb/bc-10-knife-on-bread.m +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include -#include -#include -#include - -#include "breadcrumb_regressions.h" - -static NSString *after1 = @"XAKyA0TbLKpDOBl+Ur1CQpjGDtn3wp8bYiM07iJSGVIhaaG4AAATiA=="; -static NSString *bc1 = @"AdSXILtQrtsD+eT/UjMxxu4QTjlIJjvFDhpMXfk2eZ1CCJVhCuAhNcoL4DsU85DgSBCAswzVcSEU+bLMt+DT1jJfjJKVBus1Hd5lCA+N4wVtC66w3GK/WDQdGvLZ+BL86GkeRM2/+wH4/t5qOtxIJPS5SYZhnM5EP8xFYg30MLqXZqpwZhqYBJmVPMqEbLuihYAcAJreiZm4NN09CxvD36mvU3NyQOdHzAiQ+ADMiVI84qjU0qFH1KaZEoMHn3AqjAdviHUTOaNQXNepidedBZhSl4QBeuT2CaCYHjCXny9BYT+hCEU1yXn3RYeWyjcmFKmIz8gRvWf3ckF3XaSVL7MwqfsWw1tdI9OPi7zhauqphRGELw=="; - -static NSString *after2 = @"l/y+EOCUEeQHudNLQd5SoCJ2s/+rfH/kdbxbwZ7YGGb/U2FMAAATiA=="; -static NSString *bc2 = @"AuuaJCuKmffY3XAqTYNygSFQ4QnlkSqTHGYUMaxDRA1lQhbxJh58zAOvcsahYH9lSb4+YoMR6G7hDmqlKae8h3jrn0vhT4FlIySFS3MUPvmGOuhUecb+Gi2AYwc9x1uz7f0FSRxxL+v04r2AkmH1Cv6cL7pvued7vxUjzX4VrexFj+uF7i/HSGStg2+D3L+CRs2+dKZZ9BqiKjavsX9XPkvJAD0r8rKHncOBrRxL7A3+ysBTZi2VCi/8QTDSGp6DmpXEJ4NTo/IrZ+trOXe0MuocLMg+Jf6V8jy5ZfaQoGTuM3fJiD6EFGT68QtLrjqU9KdtHhQdCmFVi60zbWqEBRNN7IyRNyPJX48NqFPZuAUW7BL0YbuhdUX2Oj7+hFz99vch1T0="; - -#define kTestCount 10 -int bc_10_password(int argc, char *const *argv) -{ - CFDataRef breadcrumb = NULL, encryptedKey = NULL; - CFStringRef oldPassword = NULL; - CFStringRef password = CFSTR("password"); - CFStringRef newpassword = CFSTR("newpassword"); - CFErrorRef error = NULL; - - plan_tests(kTestCount); - - ok(SecBreadcrumbCreateFromPassword(password, &breadcrumb, &encryptedKey, &error), "wrap failed"); - - ok(SecBreadcrumbCopyPassword(password, breadcrumb, encryptedKey, &oldPassword, NULL), "unwrap failed"); - - ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); - CFReleaseSafe(oldPassword); - - CFDataRef newEncryptedKey; - - printf("changing password from \"password\" to \"newpassword\"\n"); - - newEncryptedKey = SecBreadcrumbCreateNewEncryptedKey(password, - newpassword, - encryptedKey, - &error); - ok(newEncryptedKey, "no new encrypted key"); - - ok(SecBreadcrumbCopyPassword(newpassword, breadcrumb, newEncryptedKey, &oldPassword, NULL), "unwrap failed"); - - ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); - - CFReleaseSafe(breadcrumb); - CFReleaseSafe(oldPassword); - CFReleaseSafe(newEncryptedKey); - - /* - * Check KAT for IV less operation (version1) - */ - - breadcrumb = CFBridgingRetain([[NSData alloc] initWithBase64EncodedString:bc1 options:0]); - newEncryptedKey = CFBridgingRetain([[NSData alloc] initWithBase64EncodedString:after1 options:0]); - - ok(SecBreadcrumbCopyPassword(newpassword, breadcrumb, newEncryptedKey, &oldPassword, NULL), "unwrap failed"); - - ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); - - CFReleaseSafe(breadcrumb); - CFReleaseSafe(oldPassword); - CFReleaseSafe(newEncryptedKey); - - /* - * Check KAT for IV less operation (version2) - */ - - breadcrumb = CFBridgingRetain([[NSData alloc] initWithBase64EncodedString:bc2 options:0]); - newEncryptedKey = CFBridgingRetain([[NSData alloc] initWithBase64EncodedString:after2 options:0]); - - ok(SecBreadcrumbCopyPassword(newpassword, breadcrumb, newEncryptedKey, &oldPassword, NULL), "unwrap failed"); - - ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); - - CFReleaseSafe(breadcrumb); - CFReleaseSafe(oldPassword); - CFReleaseSafe(newEncryptedKey); - - return 0; -} diff --git a/OSX/Breadcrumb/breadcrumb_regressions.h b/OSX/Breadcrumb/breadcrumb_regressions.h deleted file mode 100644 index 29894bf2..00000000 --- a/OSX/Breadcrumb/breadcrumb_regressions.h +++ /dev/null @@ -1,7 +0,0 @@ -/* To add a test: - 1) add it here - 2) Add it as command line argument for SecurityTest.app in the Release and Debug schemes - */ -#include - -ONE_TEST(bc_10_password) diff --git a/OSX/Keychain Circle Notification/KNAppDelegate.m b/OSX/Keychain Circle Notification/KNAppDelegate.m index 2c913826..742abf4a 100644 --- a/OSX/Keychain Circle Notification/KNAppDelegate.m +++ b/OSX/Keychain Circle Notification/KNAppDelegate.m @@ -104,6 +104,8 @@ static void PSKeychainSyncIsUsingICDP(void) NSError *localError = NULL; CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; + + secnotice("followup", "Posting a follow up (for SOS) of type repair"); [cdpd postFollowUpWithContext:context error:&localError ]; if(localError){ secnotice("kcn", "request to CoreCDP to follow up failed: %@", localError); diff --git a/OSX/Keychain Circle Notification/Keychain Circle Notification.8 b/OSX/Keychain Circle Notification/Keychain Circle Notification.8 index d4bdc363..686d1654 100644 --- a/OSX/Keychain Circle Notification/Keychain Circle Notification.8 +++ b/OSX/Keychain Circle Notification/Keychain Circle Notification.8 @@ -1,9 +1,9 @@ .Dd November 02, 2016 -.Dt Keychain Circle Notification 8 +.Dt Keychain\ Circle\ Notification 8 .Os .Sh NAME .Nm Keychain Circle Notification -.Nd part of iCloud Keychain syncing. +.Nd Part of iCloud Keychain syncing. .Sh DESCRIPTION .Nm -part of iCloud Keychain syncing. +Part of iCloud Keychain syncing. diff --git a/OSX/Keychain/KDCirclePeer.m b/OSX/Keychain/KDCirclePeer.m index 91f8864e..563467dc 100644 --- a/OSX/Keychain/KDCirclePeer.m +++ b/OSX/Keychain/KDCirclePeer.m @@ -38,16 +38,12 @@ -(id)initWithPeerObject:(id)peerObject { - self = [super init]; - if (!self) { - return self; - } - - self.peerObject = peerObject; - self.name = (__bridge NSString *)(SOSPeerInfoGetPeerName((__bridge SOSPeerInfoRef)peerObject)); - self.idString = (__bridge NSString *)(SOSPeerInfoGetPeerID((__bridge SOSPeerInfoRef)peerObject)); - - return self; + if ((self = [super init])) { + self.peerObject = peerObject; + self.name = (__bridge NSString *)(SOSPeerInfoGetPeerName((__bridge SOSPeerInfoRef)peerObject)); + self.idString = (__bridge NSString *)(SOSPeerInfoGetPeerID((__bridge SOSPeerInfoRef)peerObject)); + } + return self; } -(NSString*)description diff --git a/OSX/Keychain/KDSecCircle.m b/OSX/Keychain/KDSecCircle.m index 66e36e7c..114784bf 100644 --- a/OSX/Keychain/KDSecCircle.m +++ b/OSX/Keychain/KDSecCircle.m @@ -160,14 +160,15 @@ typedef void (^applicantBlock)(id applicant); -(id)init { - self = [super init]; - int token; + if ((self = [super init])) { + int token; - self->_queue_ = dispatch_queue_create([[NSString stringWithFormat:@"KDSecCircle@%p", self] UTF8String], NULL); - self->_callbacks = [NSMutableArray new]; - notify_register_dispatch(kSOSCCCircleChangedNotification, &token, self.queue_, ^(int token1){ - [self updateCheck]; - }); + self->_queue_ = dispatch_queue_create([[NSString stringWithFormat:@"KDSecCircle@%p", self] UTF8String], NULL); + self->_callbacks = [NSMutableArray new]; + notify_register_dispatch(kSOSCCCircleChangedNotification, &token, self.queue_, ^(int token1) { + [self updateCheck]; + }); + } return self; } diff --git a/OSX/Modules b/OSX/Modules deleted file mode 120000 index 6ca77eb8..00000000 --- a/OSX/Modules +++ /dev/null @@ -1 +0,0 @@ -../Modules \ No newline at end of file diff --git a/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist b/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist index c1dd8e6c..899819c1 100644 --- a/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist +++ b/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist @@ -44,5 +44,11 @@ 123456.test.group2 com.apple.bluetooth + com.apple.private.AuthorizationServices + + com.apple.trust-settings.admin + + com.apple.private.security.storage.Keychains + diff --git a/OSX/SecurityTestsOSX/testlist.h b/OSX/SecurityTestsOSX/testlist.h index 5c3ef633..6bee84a9 100644 --- a/OSX/SecurityTestsOSX/testlist.h +++ b/OSX/SecurityTestsOSX/testlist.h @@ -1,7 +1,6 @@ /* Don't prevent multiple inclusion of this file. */ #include #include -#include #include #include #include diff --git a/OSX/authd/PreloginUserDb.h b/OSX/authd/PreloginUserDb.h new file mode 100644 index 00000000..722b3b9f --- /dev/null +++ b/OSX/authd/PreloginUserDb.h @@ -0,0 +1,8 @@ +// +// PreloginUserDb.h +// authd +// + +OSStatus preloginudb_copy_userdb(const char * _Nullable uuid, UInt32 flags, CFArrayRef _Nonnull * _Nonnull output); +OSStatus prelogin_copy_pref_value(const char * _Nullable uuid, const char * _Nullable user, const char * _Nonnull domain, const char * _Nonnull item, CFTypeRef _Nonnull * _Nonnull output); +OSStatus prelogin_smartcardonly_override(const char * _Nonnull uuid, unsigned char operation, Boolean * _Nullable status); diff --git a/OSX/authd/PreloginUserDb.m b/OSX/authd/PreloginUserDb.m new file mode 100644 index 00000000..5d6a774c --- /dev/null +++ b/OSX/authd/PreloginUserDb.m @@ -0,0 +1,884 @@ +// +// PreloginUserDb.m +// authd +// +// Copyright © 2019 Apple. All rights reserved. +// + +#import +#import +#import +#import +#import "PreloginUserDb.h" +#import +#import +#import "debugging.h" +#import +#import +#import +#import +#import "authutilities.h" + +AUTHD_DEFINE_LOG + +SOFT_LINK_FRAMEWORK(Frameworks, LocalAuthentication) +SOFT_LINK_FRAMEWORK(PrivateFrameworks, DiskManagement) +SOFT_LINK_FRAMEWORK(Frameworks, DiskArbitration) +SOFT_LINK_FRAMEWORK(PrivateFrameworks, APFS) + +SOFT_LINK_CLASS(LocalAuthentication, LAContext) +SOFT_LINK_CLASS(DiskManagement, DMManager) +SOFT_LINK_CLASS(DiskManagement, DMAPFS) +SOFT_LINK_FUNCTION(APFS, APFSVolumeGetUnlockRecord, soft_APFSVolumeGetUnlockRecord, errno_t, (const char *disk, uuid_t wrecUUID, CFDataRef *data), (disk, wrecUUID, data)) +SOFT_LINK_FUNCTION(DiskArbitration, DADiskMount, soft_DADiskMount, void, ( DADiskRef disk, CFURLRef __nullable path, DADiskMountOptions options, DADiskMountCallback __nullable callback, void * __nullable context), (disk, path, options, callback, context )) +SOFT_LINK_FUNCTION(DiskArbitration, DADiskUnmount, soft_DADiskUnmount, void, ( DADiskRef disk, DADiskUnmountOptions options, DADiskUnmountCallback __nullable callback, void * __nullable context), (disk, options, callback, context )) +SOFT_LINK_FUNCTION(DiskArbitration, DADissenterGetStatusString, soft_DADissenterGetStatusString, CFStringRef __nullable, ( DADissenterRef dissenter ), ( dissenter )) +SOFT_LINK_FUNCTION(DiskManagement, DMUnlocalizedTechnicalErrorString, soft_DMUnlocalizedTechnicalErrorString, NSString *, ( DMDiskErrorType inError ), ( inError )) +SOFT_LINK_FUNCTION(DiskArbitration, DASessionCreate, soft_DASessionCreate, DASessionRef __nullable, ( CFAllocatorRef __nullable allocator ), ( allocator )) +SOFT_LINK_FUNCTION(DiskArbitration, DADissenterGetStatus, soft_DADissenterGetStatus, DAReturn, ( DADissenterRef dissenter ), ( dissenter )) +SOFT_LINK_FUNCTION(DiskArbitration, DASessionSetDispatchQueue, soft_DASessionSetDispatchQueue, void, ( DASessionRef session, dispatch_queue_t __nullable queue ), ( session, queue )) + +static NSString *kVekItemName = @"SecureAccessToken"; +static NSString *kGUIDItemName = @"GeneratedUID"; +static NSString *kAuthenticationAuthority = @"AuthenticationAuthority"; +static NSString *kIsAdmintemName = @"Admin"; +static NSString *kSCUnlockDataItemName = @"FVTokenSecret"; +static NSString *kSCEnforcementItemName = @"SmartCardEnforcement"; +static NSString *kSCUacItemName = @"userAccountControl"; + +static NSString *kLongNameItemName = @"RealName"; +static NSString *kUidItemName = @"UID"; +static NSString *kVekFile = @"%@/%@/var/db/secureaccesstoken.plist"; +static NSString *kUsersFile = @"%@/%@/var/db/AllUsersInfo.plist"; + +static NSString *kUsersGUID = @"UserIdent"; +static NSString *kUsersNameSection = @"UserNamesData"; +static NSString *kUsersSection = @"CryptoUsers"; + +static NSString *globalConfigPath = @"%@/%@/Library/Preferences"; +static NSString *managedConfigPath = @"%@/%@/Library/Managed Preferences"; +static NSString *homeDirPath = @"%@/%@/Users"; + +static NSString *fvunlockOverrideScEnforcementPrefsName = @"com.apple.smartcard.fvunlock"; +static NSString *fvunlockOverrideScEnforcementFileName = @"%@/%@/var/db/.scnotenforced"; + +@interface PreloginUserDb : NSObject { + Boolean scEnforcementOverriden; +} + +- (instancetype)init; + +- (BOOL) loadWithError:(NSError **)error; + +- (NSArray *) users; +- (NSArray *) users:(NSString *)volumeUuid; +- (NSDictionary *) globalPrefs:(NSString *)uuid domain:(NSString *)domain; +- (NSDictionary *) managedPrefs:(NSString *)uuid domain:(NSString *)domain; +- (NSDictionary *) userPrefs:(NSString *)uuid user:(NSString *)user domain:(NSString *)domain; +@end + +typedef void (^AIRDBDACommonCompletionHandler)(DADissenterRef dissenter); +static void _commonDACompletionCallback(DADiskRef disk, DADissenterRef dissenter, void *context) +{ + AIRDBDACommonCompletionHandler handler = (__bridge AIRDBDACommonCompletionHandler)context; + handler(dissenter); +} + +OSStatus preloginDb(PreloginUserDb * _Nonnull * _Nonnull _Nonnulldb); + +@implementation PreloginUserDb { + DMManager *_diskMgr; + id _daSession; + NSMutableDictionary *_globalPrefs; // NSString *prefDomain indexed by volume UUID (NSString *) + NSMutableDictionary *_userPrefs; // NSString *username indexed by volume UUID (NSString *) + NSMutableDictionary *_managedPrefs; // NSString *prefDomain indexed by volume UUID (NSString *) + NSMutableDictionary *_dbDataDict; // NSDictionary indexed by volume UUID (NSString *) + NSMutableDictionary *_dbVolumeGroupMap; + dispatch_queue_t _queue; +} + +- (instancetype)init +{ + if ((self = [super init])) { + _queue = dispatch_queue_create("com.apple.PLUDB", DISPATCH_QUEUE_SERIAL); + if (!_queue) { + os_log_error(AUTHD_LOG, "Failed to create queue"); + return nil; + } + + _diskMgr = [[getDMManagerClass() alloc] init]; + if (!_diskMgr) { + os_log_error(AUTHD_LOG, "Failed to get DM"); + return nil; + } + + _daSession = (__bridge_transfer id)soft_DASessionCreate(kCFAllocatorDefault); + if (!_daSession) { + os_log_error(AUTHD_LOG, "Failed to get DA"); + return nil; + } + + soft_DASessionSetDispatchQueue((__bridge DASessionRef _Nullable)_daSession, _queue); + [_diskMgr setDefaultDASession:(__bridge DASessionRef _Nullable)(_daSession)]; + + _dbDataDict = [NSMutableDictionary new]; + _dbVolumeGroupMap = [NSMutableDictionary new]; + _userPrefs = [NSMutableDictionary new]; + _globalPrefs = [NSMutableDictionary new]; + _managedPrefs = [NSMutableDictionary new]; + } + return self; +} + +- (BOOL)loadWithError:(NSError **)err +{ + // get all preboot volumes + NSArray *prebootVolumes = [self allPrebootVolumes]; + if (prebootVolumes.count == 0) { + os_log_error(AUTHD_LOG, "Failed to get preboot volumes for Prelogin userDB"); + if (err) { + *err = [NSError errorWithDomain:@"com.apple.authorization" code:-1000 userInfo:@{ NSLocalizedDescriptionKey : @"Failed to get preboot volumes for Prelogin userDB"}]; + } + return NO; + } + + NSUUID *uuid = [self currentRecoveryVolumeUUID]; + os_log_info(AUTHD_LOG, "Current Recovery Volume UUID: %{public}@", uuid); + + OSStatus (^volumeWorker)(NSUUID *volumeUuid, NSString *mountPoint) = ^OSStatus(NSUUID *volumeUuid, NSString *mountPoint) { + [self processVolumeData:volumeUuid mountPoint:mountPoint]; + return noErr; + }; + + [self processPrebootVolumes:prebootVolumes currentRecoveryVolumeUUID:uuid worker:volumeWorker]; + + if (_dbDataDict.count == 0 && uuid != nil) { + os_log(AUTHD_LOG, "No admins found. Try to load all preboot partitions"); + _dbDataDict = [NSMutableDictionary new]; + [self processPrebootVolumes:prebootVolumes currentRecoveryVolumeUUID:nil worker:volumeWorker]; // load admins from ALL preboot partitions + } + + if (err) { + *err = nil; + } + return YES; +} + +- (NSArray *)users +{ + return [self users:nil]; +} + +- (NSArray *)users:(NSString *)requestedUuid +{ + if (!_dbDataDict.allValues) { + return nil; + } + if (requestedUuid && !_dbDataDict[requestedUuid]) { + NSString *realUuid = _dbVolumeGroupMap[requestedUuid]; + if (!realUuid) { + os_log_info(AUTHD_LOG, "Requested volume %{public}@ was not found and is not volumeGroup", requestedUuid); + NSArray *keys = [_dbVolumeGroupMap allKeysForObject:requestedUuid]; + for(NSString *uuid in keys) { + if (_dbDataDict[uuid]) { + realUuid = uuid; + break; + } + } + if (!realUuid) { + os_log_info(AUTHD_LOG, "Requested volumeGroup %{public}@ was not found", requestedUuid); + return nil; // no users for requested partition and no mapping for VolumeGroup or vice versa + } + } + os_log_info(AUTHD_LOG, "Requested volume %{public}@ has no users, trying volume %{public}@", requestedUuid, realUuid); + requestedUuid = realUuid; + } + + NSMutableArray *allUsers = [NSMutableArray new]; + for (NSString *uuid in _dbDataDict) { + if (requestedUuid && ![requestedUuid isEqualToString:uuid]) { + os_log_info(AUTHD_LOG, "Requested volume %{public}@ so ignoring volume %{public}@", requestedUuid, uuid); + continue; + } + [allUsers addObjectsFromArray:_dbDataDict[uuid]]; + } + return allUsers; +} + +- (NSDictionary *)globalPrefs:(NSString *)uuid domain:(NSString *)domain +{ + NSDictionary *volumeGlobalPrefs = _globalPrefs[uuid]; + if (!volumeGlobalPrefs) { + os_log_debug(AUTHD_LOG, "No global prefs for volume %{public}@ were found", uuid); + return nil; + } + return volumeGlobalPrefs[domain]; +} + +- (NSDictionary *)managedPrefs:(NSString *)uuid domain:(NSString *)domain +{ + NSDictionary *volumeManagedPrefs = _managedPrefs[uuid]; + if (!volumeManagedPrefs) { + return nil; + } + return volumeManagedPrefs[domain]; +} + +- (NSDictionary *)userPrefs:(NSString *)uuid user:(NSString *)user domain:(NSString *)domain +{ + NSDictionary *volumeUserPrefs = _userPrefs[uuid]; + if (!volumeUserPrefs) { + os_log_debug(AUTHD_LOG, "No user prefs for volume %{public}@ were found", uuid); + return nil; + } + NSDictionary *userPrefs = volumeUserPrefs[user]; + if (!userPrefs) { + os_log_debug(AUTHD_LOG, "No user prefs for volume %{public}@ and user %{public}@ were found", uuid, user); + return nil; + } + return userPrefs[domain]; +} + +- (OSStatus)setEnforcedSmartcardOverride:(NSUUID *)uuid operation:(unsigned char)operation status:(Boolean *)status internal:(Boolean)internal +{ + if (!isInFVUnlock()) { + if (operation == kAuthorizationOverrideOperationQuery && !internal) { + if (status) { + *status = scEnforcementOverriden; + } + return noErr; + } else if (!internal) { + os_log_error(AUTHD_LOG, "SmartCard enforcement can be set only from Recovery"); + return errSecNotAvailable; + } + } + + NSArray *prebootVolumes = [self allPrebootVolumes]; + __block OSStatus retval = errAuthorizationInternal; + + OSStatus (^volumeWorker)(NSUUID *volumeUuid, NSString *mountPoint) = ^OSStatus(NSUUID *volumeUuid, NSString *mountPoint) { + + NSString *usersPath = [NSString stringWithFormat:kUsersFile, mountPoint, volumeUuid.UUIDString]; + if (access(usersPath.UTF8String, F_OK)) { + os_log_info(AUTHD_LOG, "This preboot volume is not usable for FVUnlock"); + return errSecInvalidItemRef; + } + os_log_info(AUTHD_LOG, "Preboot volume %{public}@ is usable for FVUnlock", volumeUuid); + + NSString *filePath = [NSString stringWithFormat:fvunlockOverrideScEnforcementFileName, mountPoint, volumeUuid.UUIDString]; + BOOL overrideFileExists = !access(filePath.UTF8String, F_OK); + + switch(operation) { + case kAuthorizationOverrideOperationSet: // set + { + if (overrideFileExists) { + os_log(AUTHD_LOG, "SmartCard enforcement override is already active."); + retval = noErr; + } else { + mode_t mode = S_IRUSR | S_IWUSR; + int fd = creat(filePath.UTF8String, mode); + if (fd != -1) { + os_log(AUTHD_LOG, "SmartCard enforcement override turned on"); + retval = noErr; + close(fd); + } else { + os_log_error(AUTHD_LOG, "Unable to write override file: %d", errno); + retval = errno; + } + } + break; + } + case kAuthorizationOverrideOperationReset: // reset + { + if (!overrideFileExists) { + os_log(AUTHD_LOG, "SmartCard enforcement override not active."); + retval = errSecNoSuchAttr; + } else { + os_log(AUTHD_LOG, "SmartCard enforcement override turned off"); + retval = (OSStatus)remove(filePath.UTF8String); + } + break; + } + case kAuthorizationOverrideOperationQuery: // status + { + if (!status) { + break; + } + + *status = overrideFileExists; + os_log_debug(AUTHD_LOG, "SmartCard enforcement override status %d", overrideFileExists); + retval = noErr; + break; + } + default: { + os_log_error(AUTHD_LOG, "Unknown operation %d", operation); + } + } + + return retval; + }; + + [self processPrebootVolumes:prebootVolumes currentRecoveryVolumeUUID:uuid worker:volumeWorker]; + + return retval; +} + +#pragma mark - Private Methods + +- (void)processPrebootVolumes:(NSArray*)prebootVolumes currentRecoveryVolumeUUID:(NSUUID *)currentRecoveryVolumeUUID worker:(OSStatus (^)(NSUUID *volumeUuid, NSString *mountPoint))workerBlock +{ + // process each preboot volume + for (id prebootVolume in prebootVolumes) { + + // mount the preboot volume. If it fails it could be already mounted. Try to get mountPoint anyway. + Boolean mounted = [self mountPrebootVolume:prebootVolume]; + + // get a mount point of the preboot volume + NSString *mountPoint = [self mountPointForPrebootVolume:prebootVolume]; + if (!mountPoint) { + os_log_info(AUTHD_LOG, "Volume %{public}@ has no mountpoint", prebootVolume); + continue; + } + + // process the preboot volume + NSDirectoryEnumerator *dirEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:mountPoint isDirectory:YES] includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:nil]; + for (NSURL *url in dirEnumerator) { + BOOL isDir = NO; + [[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDir]; + if (!isDir) { + os_log_info(AUTHD_LOG, "Skipping file %{public}@ (not a directory)", url.path); + continue; + } + + NSUUID *volumeUUID = [[NSUUID alloc] initWithUUIDString:url.lastPathComponent]; // the dir has the name as UUID + if (!volumeUUID) { + os_log_info(AUTHD_LOG, "Ignoring folder %{public}@ (not UUID)", url); + continue; + } + + if (currentRecoveryVolumeUUID && ![currentRecoveryVolumeUUID isEqualTo:volumeUUID]) { + os_log_info(AUTHD_LOG, "The preboot volume skipped: %{public}@ (not the currentRecoveryVolumeUUID %{public}@)", url, currentRecoveryVolumeUUID); + continue; + } + + if (workerBlock) { + workerBlock(volumeUUID, mountPoint); + } + } + + // unmount the preboot volume + if (mounted) { + [self unmountPrebootVolume:prebootVolume]; + } + } +} + +#define kEFISystemVolumeUUIDVariableName "SystemVolumeUUID" +- (NSUUID *)currentRecoveryVolumeUUID +{ + NSData *data; + NSString * const LANVRAMNamespaceStartupManager = @"5EEB160F-45FB-4CE9-B4E3-610359ABF6F8"; + + NSString *key = [NSString stringWithFormat:@"%@:%@", LANVRAMNamespaceStartupManager, @kEFISystemVolumeUUIDVariableName]; + + io_registry_entry_t match = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options"); + if (match) { + CFTypeRef entry = IORegistryEntryCreateCFProperty(match, (__bridge CFStringRef)key, kCFAllocatorDefault, 0); + IOObjectRelease(match); + + if (entry) + { + if (CFGetTypeID(entry) == CFDataGetTypeID()) + data = CFBridgingRelease(entry); + else + CFRelease(entry); + } + } + os_log_info(AUTHD_LOG, "Current boot volume: %{public}@", data); + + if (data) { + return [[NSUUID alloc] initWithUUIDBytes:data.bytes]; + } else { + return nil; + } +} + +- (NSArray *)allPrebootVolumes +{ + NSMutableArray* result = [NSMutableArray new]; + + DMAPFS* dmAPFS = [[getDMAPFSClass() alloc] initWithManager:_diskMgr]; + + for (id tmp in _diskMgr.disks) { + DADiskRef diskRef = (__bridge DADiskRef)(tmp); + os_log_info(AUTHD_LOG, "Found disk %{public}@", diskRef); + + BOOL preboot; + DMDiskErrorType diskErr = [dmAPFS isPrebootVolume:diskRef prebootRole:&preboot]; + if (diskErr) { + os_log(AUTHD_LOG, "Failed to determine preboot state for %{public}@: %{public}@", diskRef, soft_DMUnlocalizedTechnicalErrorString(diskErr)); + continue; + } + if (!preboot) { + os_log_info(AUTHD_LOG, "Not a preboot volume: %{public}@", diskRef); + continue; + } + + id prebootVolume = CFBridgingRelease([_diskMgr copyBooterDiskForDisk:diskRef error:&diskErr]); + if (prebootVolume) { + os_log_info(AUTHD_LOG, "Found APFS preboot %{public}@", prebootVolume); + [result addObject:prebootVolume]; + } else { + os_log_error(AUTHD_LOG, "Failed to copy preboot for disk %{public}@, err: %{public}@", diskRef, soft_DMUnlocalizedTechnicalErrorString(diskErr)); + } + } + + return result; +} + +- (BOOL)mountPrebootVolume:(id)preboot +{ + __block BOOL success = NO; + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + AIRDBDACommonCompletionHandler completionHandler = ^(DADissenterRef dissenter) { + success = (dissenter == NULL); + if (dissenter != NULL) { + os_log(AUTHD_LOG, "Failed to mount preboot volume %{public}@ (status: 0x%x, reason: \"%{public}@\").", preboot, soft_DADissenterGetStatus(dissenter), soft_DADissenterGetStatusString(dissenter)); + } + dispatch_semaphore_signal(sem); + }; + soft_DADiskMount((__bridge DADiskRef _Nonnull)(preboot), NULL, kDADiskMountOptionDefault, _commonDACompletionCallback, (__bridge void * _Nullable)(completionHandler)); + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + return success; +} + +- (NSString *)mountPointForPrebootVolume:(id)preboot +{ + DMDiskErrorType diskErr; + NSString* result = [_diskMgr mountPointForDisk:(__bridge DADiskRef _Nonnull)(preboot) error:&diskErr]; + if (result) { + os_log_info(AUTHD_LOG, "Mounted preboot partition %{public}@ at %{public}@", preboot, result); + } else { + os_log_error(AUTHD_LOG, "Failed to get preboot mount point: %{public}@", soft_DMUnlocalizedTechnicalErrorString(diskErr)); + } + return result; +} + +- (void)unmountPrebootVolume:(id)preboot +{ + soft_DADiskUnmount((__bridge DADiskRef _Nonnull)(preboot), kDADiskUnmountOptionDefault, nil, nil); + os_log_info(AUTHD_LOG, "Preboot partition unmounted: %{public}@", preboot); +} + +- (NSString *)deviceNodeForVolumeWithUUID:(NSUUID *)volumeUuid diskRef:(DADiskRef *)diskRef +{ + DMDiskErrorType diskErr; + DADiskRef localDiskRef = [_diskMgr copyDiskForVolumeUUID:volumeUuid.UUIDString error:&diskErr]; + if (!localDiskRef) { + os_log_error(AUTHD_LOG, "Failed to find disk with volume %{public}@: %{public}@", volumeUuid, soft_DMUnlocalizedTechnicalErrorString(diskErr)); + return nil; + } + if (diskRef) { + *diskRef = localDiskRef; + CFRetain(*diskRef); + } + os_log_info(AUTHD_LOG, "Found disk %{public}@ with volume UUID %{public}@", localDiskRef, volumeUuid); + NSString* deviceNode = [self deviceNodeForDisk:localDiskRef]; + CFRelease(localDiskRef); + return deviceNode; +} + +- (NSString *)deviceNodeForDisk:(DADiskRef)diskRef +{ + DMDiskErrorType diskErr; + NSString *deviceNode = [_diskMgr deviceNodeForDisk:diskRef error:&diskErr]; + if (!deviceNode) { + os_log_error(AUTHD_LOG, "Failed to find device node for disk %{public}@: %{public}@", diskRef, soft_DMUnlocalizedTechnicalErrorString(diskErr)); + return nil; + } + os_log_info(AUTHD_LOG, "Device node found: %{public}@", deviceNode); + return deviceNode; +} + +- (NSData *)loadVEKforVolumeWithUUID:(NSUUID *)volumeUuid mountPoint:(NSString *)mountPoint +{ + NSString *vekPath = [NSString stringWithFormat:kVekFile, mountPoint, volumeUuid.UUIDString]; + NSDictionary *vekDict = [NSDictionary dictionaryWithContentsOfFile:vekPath]; + NSData *vek = vekDict[kVekItemName]; + if (!vek) { + os_log_error(AUTHD_LOG, "Failed to load DiskToken from %{public}@", vekPath); + return nil; + } + os_log_info(AUTHD_LOG, "Loaded DiskToken from %{public}@", vekPath); + + return vek; +} + +- (NSData *)loadKEKforUuid:(NSString *)userUuid deviceNode:(NSString *)deviceNode +{ + NSUUID *nsUuid = [[NSUUID alloc] initWithUUIDString:userUuid]; + uuid_t uuid; + [nsUuid getUUIDBytes:uuid]; + CFDataRef dataCF; + errno_t err = soft_APFSVolumeGetUnlockRecord(deviceNode.UTF8String, uuid, &dataCF); + if(err != 0) { + os_log_error(AUTHD_LOG, "Failed to find SecureToken on device node %{public}@ and UUID %{public}@ (%d)", deviceNode, userUuid, err); + return nil; + } + os_log_info(AUTHD_LOG, "Loaded SecureToken from device node %{public}@", deviceNode); + + NSData *kek = CFBridgingRelease(dataCF); + return kek; +} + +- (NSDictionary *)loadUserDatabaseForVolumeUUID:(NSUUID *)volumeUuid mountPoint:(NSString *)mountPoint +{ + NSString *usersPath = [NSString stringWithFormat:kUsersFile, mountPoint, volumeUuid.UUIDString]; + NSDictionary *users = [NSDictionary dictionaryWithContentsOfFile:usersPath]; + if (users.count == 0) { + os_log_error(AUTHD_LOG, "Failed to find user records in file %{public}@", usersPath); + return nil; + } + os_log_debug(AUTHD_LOG, "Loaded %lu user records from file %{public}@", (unsigned long)users.count, usersPath); + return users; +} + +- (void)processVolumeData:(NSUUID *)volumeUuid mountPoint:(NSString *)mountPoint +{ + os_log_info(AUTHD_LOG, "Processing volume data: %{public}@", volumeUuid); + NSData *vek = [self loadVEKforVolumeWithUUID:volumeUuid mountPoint:mountPoint]; + if (!vek) { + return; + } + + DADiskRef cfDiskRef = NULL; + NSString* deviceNode = [self deviceNodeForVolumeWithUUID:volumeUuid diskRef:&cfDiskRef]; + id diskRef = CFBridgingRelease(cfDiskRef); + if (!deviceNode) { + return; + } + NSString *volumeGroupUuid; + DMAPFS* dmAPFS = [[getDMAPFSClass() alloc] initWithManager:_diskMgr]; + DMDiskErrorType diskErr = [dmAPFS volumeGroupForVolume:(__bridge DADiskRef _Nonnull)(diskRef) id:&volumeGroupUuid]; + if (diskErr != kDiskErrorNoError || volumeGroupUuid == nil) { + os_log_error(AUTHD_LOG, "Error %d while trying to get volume group for %{public}@", diskErr, volumeUuid); + } else { + if ([volumeUuid.UUIDString isEqualTo:volumeGroupUuid]) { + NSArray *systemVolumeDisks = nil; + diskErr = [dmAPFS disksForVolumeGroup:volumeGroupUuid volumeDisks:nil systemVolumeDisks:&systemVolumeDisks dataVolumeDisks:nil userVolumeDisks:nil container:nil]; + if (diskErr != kDiskErrorNoError || systemVolumeDisks == nil) { + os_log_error(AUTHD_LOG, "Error %d while trying to get volume group disks for %{public}@", diskErr, volumeGroupUuid); + } else { + // There should be only one systemVolume, but the API returns an array so we'll process as many as it wants to give us + for (id tmp in systemVolumeDisks) { + DADiskRef systemVolumeDiskRef = (__bridge DADiskRef)(tmp); + NSString *systemVolumeUuid = nil; + diskErr = [dmAPFS volumeUUIDForVolume:systemVolumeDiskRef UUID:&systemVolumeUuid]; + if (diskErr != kDiskErrorNoError || systemVolumeUuid == nil) { + os_log_error(AUTHD_LOG, "Error %d while trying to get volume uuid disks for some system volumes of group %{public}@", diskErr, volumeGroupUuid); + } else { + os_log(AUTHD_LOG, "Volume %{public}@ belongs to the group %{public}@", systemVolumeUuid, volumeGroupUuid); + _dbVolumeGroupMap[systemVolumeUuid] = volumeGroupUuid; + } + } + } + } + } + + NSDictionary *users = [self loadUserDatabaseForVolumeUUID:volumeUuid mountPoint:mountPoint]; + for (NSString *userName in users) { + NSDictionary *userData = users[userName]; + os_log_debug(AUTHD_LOG, "Processing user: %{public}@", userData); + NSString *userGuid = userData[kGUIDItemName]; + if (userGuid == nil) { + os_log_error(AUTHD_LOG, "Failed to find GUID for user %{public}@", userName); + continue; + } + NSData* kek = [self loadKEKforUuid:userGuid deviceNode:deviceNode]; + if (!kek) { + os_log_error(AUTHD_LOG, "Failed to find SecureToken for user %{public}@", userName); + continue; + } + + NSArray *aauthority = userData[kAuthenticationAuthority]; + NSMutableDictionary *dict = @{}.mutableCopy; + if (aauthority) { + dict[@PLUDB_SCPAIR] = aauthority; + os_log_debug(AUTHD_LOG, "Using authority: %{public}@", aauthority); + } + + Boolean owner; + struct aks_fv_param_s params = {}; + aks_fv_blob_state_s verifier_state = {}; + struct aks_fv_data_s kekData = { .data = (void *)kek.bytes, .len = kek.length }; + + int res = aks_fv_get_blob_state(¶ms, &kekData, &verifier_state); + if (res) { + os_log_error(AUTHD_LOG, "Blob state failed: %x", res); + owner = NO; + } else { + owner = ((verifier_state.flags & aks_fv_state_is_owner) == aks_fv_state_is_owner); + } + + dict[@PLUDB_USERNAME] = userName; + dict[@PLUDB_GUID] = userGuid; + dict[@PLUDB_ADMIN] = userData[kIsAdmintemName]; + dict[@PLUDB_KEK] = kek; + dict[@PLUDB_VEK] = vek; + dict[@PLUDB_DNODE] = deviceNode; + dict[@PLUDB_OWNER] = @(owner); + + if ([userData.allKeys containsObject:kSCUnlockDataItemName]) { + dict[@PLUDB_SCUNLOCK_DATA] = userData[kSCUnlockDataItemName]; + } + if ([userData.allKeys containsObject:kSCEnforcementItemName]) { + dict[@PLUDB_SCENF] = userData[kSCEnforcementItemName]; + } + if ([userData.allKeys containsObject:kSCUacItemName]) { + dict[@PLUDB_SCUAC] = userData[kSCUacItemName]; + } + if ([userData.allKeys containsObject:kLongNameItemName]) { + dict[@PLUDB_LUSERNAME] = userData[kLongNameItemName]; + } + + NSMutableArray *array = _dbDataDict[volumeUuid.UUIDString]; + if (array == nil) { + array = [NSMutableArray new]; + if (!array) { + os_log_error(AUTHD_LOG, "Failed to create users array"); + return; + } + _dbDataDict[volumeUuid.UUIDString] = array; + } + + os_log_info(AUTHD_LOG, "Prelogin UserDB added entry: %{public}@", dict); + [array addObject:dict]; + } + + // check for SC override + scEnforcementOverriden = NO; + [self setEnforcedSmartcardOverride:volumeUuid operation:kAuthorizationOverrideOperationQuery status:&scEnforcementOverriden internal:YES]; + os_log_info(AUTHD_LOG, "SC enforcement override: %d", scEnforcementOverriden); + + if (!isInFVUnlock()) { + os_log_debug(AUTHD_LOG, "Not processing prefs"); + + // remove SCenforcement override flag + if (scEnforcementOverriden) { + [self setEnforcedSmartcardOverride:volumeUuid operation:kAuthorizationOverrideOperationReset status:nil internal:YES]; + } + return; // do not process prefs when not in FVUnlock + } + + // process preferences + // global prefs + NSMutableDictionary *global = @{}.mutableCopy; + NSString *filePath = [NSString stringWithFormat:globalConfigPath, mountPoint, volumeUuid.UUIDString]; + + NSDirectoryEnumerator *dirEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:filePath isDirectory:YES] includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:nil]; + for (NSURL *url in dirEnumerator) { + BOOL isDir = NO; + [[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDir]; + if (isDir) { + os_log_info(AUTHD_LOG, "Skipping dir %{public}@ (not a file)", url.path); + continue; + } + NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:url.path]; + if (prefs) { + NSString *prefName = url.URLByDeletingPathExtension.lastPathComponent; + global[prefName] = prefs; + } + } + + if (scEnforcementOverriden) { + os_log_info(AUTHD_LOG, "SC enforcement overriden for this boot"); + global[fvunlockOverrideScEnforcementPrefsName] = @{ @"overrideScEnforcement": @YES }; + } + + if (global.count) { + _globalPrefs[volumeUuid.UUIDString] = global; + } + + // managed prefs + NSMutableDictionary *managed = @{}.mutableCopy; + filePath = [NSString stringWithFormat:managedConfigPath, mountPoint, volumeUuid.UUIDString]; + + dirEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:filePath isDirectory:YES] includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:nil]; + for (NSURL *url in dirEnumerator) { + BOOL isDir = NO; + [[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDir]; + if (isDir) { + os_log_info(AUTHD_LOG, "Skipping dir %{public}@ (not a file)", url.path); + continue; + } + NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:url.path]; + if (prefs) { + NSString *prefName = url.URLByDeletingPathExtension.lastPathComponent; + managed[prefName] = prefs; + } + } + if (managed.count) { + _managedPrefs[volumeUuid.UUIDString] = managed; + } + + // per user prefs + NSMutableDictionary *user = @{}.mutableCopy; + filePath = [NSString stringWithFormat:homeDirPath, mountPoint, volumeUuid.UUIDString]; + + dirEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:filePath isDirectory:YES] includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:nil]; + for (NSURL *url in dirEnumerator) { + BOOL isDir = NO; + [[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDir]; + if (!isDir) { + os_log_info(AUTHD_LOG, "Skipping file %{public}@ (not a directory)", url.path); + continue; + } + + NSMutableDictionary *userPrefs = @{}.mutableCopy; + NSString *userName = url.lastPathComponent; + NSString *userPrefPath = [NSString stringWithFormat:@"%@/Library/Preferences", url.path]; + NSDirectoryEnumerator *dirEnumerator2 = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:userPrefPath isDirectory:YES] includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:nil]; + for (NSURL *userUrl in dirEnumerator2) { + isDir = NO; + [[NSFileManager defaultManager] fileExistsAtPath:userUrl.path isDirectory:&isDir]; + if (isDir) { + os_log_info(AUTHD_LOG, "Skipping dir %{public}@ (not a file)", userUrl.path); + continue; + } + NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:userUrl.path]; + if (prefs) { + NSString *prefName = userUrl.URLByDeletingPathExtension.lastPathComponent; + userPrefs[prefName] = prefs; + } + } + + if (userPrefs.count) { + user[userName] = userPrefs; + } + } + if (user.count) { + _userPrefs[volumeUuid.UUIDString] = user; + } + os_log_debug(AUTHD_LOG, "Global prefs for volume %@: %@", volumeUuid.UUIDString, global); + os_log_debug(AUTHD_LOG, "Managed prefs for volume %@: %@", volumeUuid.UUIDString, managed); + os_log_debug(AUTHD_LOG, "User prefs for volume %@: %@", volumeUuid.UUIDString, user); +} + +@end + +OSStatus preloginDb(PreloginUserDb **db) +{ + static PreloginUserDb *database; + static OSStatus loadError = errAuthorizationSuccess; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + os_log_info(AUTHD_LOG, "Going to load User DB"); + + database = [[PreloginUserDb alloc] init]; + if (!database) { + loadError = errAuthorizationInvalidSet; + } else { + NSError *error; + if ([database loadWithError:&error]) { + loadError = (int)error.code; + } + } + }); + + if (loadError) { + return loadError; + } + if (db) { + *db = database; + } + return noErr; +} + +OSStatus preloginudb_copy_userdb(const char *uuid, UInt32 flags, CFArrayRef *output) +{ + if (!output) { + return errAuthorizationBadAddress; + } + PreloginUserDb *database; + OSStatus retval = preloginDb(&database); + if (retval) { + os_log_error(AUTHD_LOG, "Unable to read db"); + return retval; + } + + os_log_debug(AUTHD_LOG, "Processing user db for volume %{public}s with flags %d", uuid, flags); + + *output = CFBridgingRetain([database users:uuid ? [NSString stringWithUTF8String:uuid] : nil]); + return errAuthorizationSuccess; +} + +OSStatus prelogin_copy_pref_value(const char * _Nullable uuid, const char *user, const char *domain, const char *item, CFTypeRef *output) +{ + if (!output || !uuid) { + return errAuthorizationBadAddress; + } + PreloginUserDb *database; + OSStatus retval = preloginDb(&database); + if (retval) { + os_log_error(AUTHD_LOG, "Unable to read db"); + return retval; + } + + NSDictionary *prefs; + NSDictionary *managed; + NSString *_domain = [NSString stringWithUTF8String:domain]; + NSString *_uuid = [NSString stringWithUTF8String:uuid]; + if (user) { + os_log_debug(AUTHD_LOG, "Reading user pref volume %{public}s %{public}s/%{public}s for user %s", uuid, domain, item, user); + prefs = [database userPrefs:_uuid user:[NSString stringWithUTF8String:user] domain:_domain]; + } else { + os_log_debug(AUTHD_LOG, "Reading global pref volume %{public}s %{public}s/%{public}s", uuid, domain, item); + managed = [database managedPrefs:_uuid domain:_domain]; + prefs = [database globalPrefs:_uuid domain:_domain]; + } + + if (!prefs && !managed) { + os_log_debug(AUTHD_LOG, "No pref found"); + return errAuthorizationInvalidSet; + } + + id value = managed[[NSString stringWithUTF8String:item]]; + if (value) { + os_log_info(AUTHD_LOG, "Using managed prefs for %{public}s", item); + } else { + os_log_debug(AUTHD_LOG, "Using global prefs for %{public}s", item); + value = prefs[[NSString stringWithUTF8String:item]]; + } + if (!value) { + os_log_debug(AUTHD_LOG, "No pref value with name %{public}s was found", item); + return errAuthorizationInvalidTag; + } + + *output = CFBridgingRetain(value); + return errAuthorizationSuccess; +} + +OSStatus prelogin_smartcardonly_override(const char *uuid, unsigned char operation, Boolean *status) +{ + if (!uuid) { + os_log_error(AUTHD_LOG, "No volume UUID provided"); + return errSecParam; + } + + NSUUID *volumeUuid = [[NSUUID alloc] initWithUUIDString:[NSString stringWithUTF8String:uuid]]; + if (!volumeUuid) { + os_log_error(AUTHD_LOG, "Invalid volume UUID provided: %{public}s", uuid); + return errSecParam; + } + + PreloginUserDb *database; + OSStatus retval = preloginDb(&database); + if (retval) { + os_log_error(AUTHD_LOG, "Unable to read db"); + return retval; + } + + + return [database setEnforcedSmartcardOverride:volumeUuid operation:operation status:status internal:NO]; +} + diff --git a/OSX/authd/authd-Entitlements.plist b/OSX/authd/authd-Entitlements.plist index 7ef4f57c..2b11ecb8 100644 --- a/OSX/authd/authd-Entitlements.plist +++ b/OSX/authd/authd-Entitlements.plist @@ -2,9 +2,15 @@ + com.apple.keystore.console + com.apple.private.LocalAuthentication.ExtractCredential - com.apple.keystore.console + com.apple.private.security.clear-library-validation + + com.apple.keystore.filevault + + com.apple.rootless.volume.Preboot diff --git a/OSX/authd/authd_private.h b/OSX/authd/authd_private.h index 4fc95b64..1d8fbdb5 100644 --- a/OSX/authd/authd_private.h +++ b/OSX/authd/authd_private.h @@ -106,7 +106,10 @@ enum { AUTHORIZATION_DISMISS, AUTHORIZATION_SETUP, AUTHORIZATION_ENABLE_SMARTCARD, - AUTHORIZATION_PREAUTHORIZE_CREDENTIALS + AUTHORIZATION_COPY_PRELOGIN_USERDB, + AUTHORIZATION_COPY_PRELOGIN_PREFS, + AUTHORIZATION_COPY_RIGHT_PROPERTIES, + AUTHORIZATION_PRELOGIN_SC_OVERRIDE, }; #if defined(__cplusplus) diff --git a/OSX/authd/authdb.c b/OSX/authd/authdb.c index c10ce840..df0c1257 100644 --- a/OSX/authd/authdb.c +++ b/OSX/authd/authdb.c @@ -277,6 +277,18 @@ static void _repair_all_kofns(authdb_connection_t dbconn, auth_items_t config) CFRelease(plist); } +static void _check_for_db_update(authdb_connection_t dbconn) +{ + const char *rightName = "com.apple.installassistant.requestpassword"; + rule_t right = rule_create_with_string(rightName, dbconn); + if (!right || rule_get_class(right) != RC_USER || rule_get_shared(right) != false || rule_get_type(right) != RT_RIGHT) { + os_log_fault(AUTHD_LOG, "Old and not updated database found"); + } else { + os_log(AUTHD_LOG, "Database check OK"); + } + CFReleaseNull(right); +} + static void _db_load_data(authdb_connection_t dbconn, auth_items_t config) { CFAbsoluteTime ts = 0; @@ -289,6 +301,9 @@ static void _db_load_data(authdb_connection_t dbconn, auth_items_t config) auth_items_set_double(update, "data_ts", ts); authdb_set_key_value(dbconn, "config", update); CFReleaseSafe(update); + int32_t rc = sqlite3_db_cacheflush(dbconn->handle); + os_log_debug(AUTHD_LOG, "Flush result: %d", rc); + _check_for_db_update(dbconn); } } CFReleaseSafe(plist); @@ -362,9 +377,12 @@ static int32_t _db_maintenance(authdb_connection_t dbconn) if (currentVersion < AUTHDB_VERSION) { os_log_debug(AUTHD_LOG, "authdb: upgrading schema"); s3e = _db_upgrade_from_version(dbconn, (int32_t)currentVersion); - - auth_items_set_int64(config, "version", AUTHDB_VERSION); - authdb_set_key_value(dbconn, "config", config); + if (s3e != SQLITE_OK) { + os_log_error(AUTHD_LOG, "authdb: failed to upgrade DB schema %i", s3e); + } else { + auth_items_set_int64(config, "version", AUTHDB_VERSION); + authdb_set_key_value(dbconn, "config", config); + } } done: @@ -943,13 +961,18 @@ _import_rules(authdb_connection_t dbconn, CFMutableArrayRef rules, bool version_ if (version_check) { if (rule_get_id(rule) != 0) { // rule already exists see if we need to update rule_t current = rule_create_with_string(rule_get_name(rule), dbconn); - if (rule_get_version(rule) > rule_get_version(current)) { + int64_t currVer = rule_get_version(current); + int64_t newVer = rule_get_version(rule); + + if (newVer > currVer) { update = true; } CFReleaseSafe(current); if (!update) { continue; + } else { + os_log(AUTHD_LOG, "authdb: right %{public}s new version %lld vs existing version %lld, will update", rule_get_name(rule), newVer, currVer); } } } @@ -977,7 +1000,7 @@ _import_rules(authdb_connection_t dbconn, CFMutableArrayRef rules, bool version_ if (!delayCommit) { bool success = rule_sql_commit(rule, dbconn, now, NULL); - os_log_debug(AUTHD_LOG, "authdb: %{public}s %{public}s %{public}s %{public}s", + os_log(AUTHD_LOG, "authdb: %{public}s %{public}s %{public}s %{public}s", update ? "updating" : "importing", rule_get_type(rule) == RT_RULE ? "rule" : "right", rule_get_name(rule), success ? "success" : "FAIL"); diff --git a/OSX/authd/authitems.c b/OSX/authd/authitems.c index ea49287a..4e5945f0 100644 --- a/OSX/authd/authitems.c +++ b/OSX/authd/authitems.c @@ -6,9 +6,12 @@ #include "authutilities.h" #include +#include #include #include +#include + AUTHD_DEFINE_LOG typedef struct _auth_item_s * auth_item_t; @@ -48,7 +51,7 @@ auth_item_copy_auth_item_xpc(auth_item_t item) xpc_dictionary_set_string(xpc_data, AUTH_XPC_ITEM_NAME, item->data.name); if (item->data.value) { // authd is holding on to multiple copies of my password in the clear - bool sensitive = strcmp(item->data.name, "password") == 0; + bool sensitive = strcmp(item->data.name, AGENT_PASSWORD) == 0; if (sensitive) { vm_address_t vmBytes = 0; size_t xpcOutOfBandBlockSize = (item->data.valueLength > 32768 ? item->data.valueLength : 32768); // min 16K on 64-bit systems and 12K on 32-bit systems diff --git a/OSX/authd/authorization.plist b/OSX/authd/authorization.plist index 2a1930aa..a83f0fb2 100644 --- a/OSX/authd/authorization.plist +++ b/OSX/authd/authorization.plist @@ -578,14 +578,19 @@ See remaining rules for examples. com.apple.trust-settings.admin - allow-root - - class - user comment - For modifying Trust Settings in the Local Admin domain. - group - admin + For modifying Trust Settings in the Admin domain. Requires entitlement or admin authentication. + class + rule + k-of-n + 1 + rule + + entitled + authenticate-admin + + version + 1 com.apple.trust-settings.user @@ -596,10 +601,14 @@ See remaining rules for examples. com.apple.uninstalld.uninstall + authenticate-user + class - rule - rule - entitled-admin-or-authenticate-admin + user + entitled + + version + 1 config.add. @@ -675,6 +684,23 @@ See remaining rules for examples. comment For burning media. + com.apple.installassistant.requestpassword + + authenticate-user + + class + user + comment + Authenticate as an administrator, password only. + group + admin + password-only + + shared + + timeout + 0 + system.csfde.requestpassword.weak class @@ -825,7 +851,7 @@ See remaining rules for examples. class rule comment - Checked when user is installing Apple-provided software. + Checked when user is installing Apple software. rule root-or-entitled-admin-or-authenticate-admin @@ -914,6 +940,7 @@ See remaining rules for examples. mechanisms builtin:policy-banner + builtin:prelogin loginwindow:login builtin:login-begin builtin:reset-password,privileged @@ -931,7 +958,24 @@ See remaining rules for examples. loginwindow:done version - 7 + 8 + + system.login.filevault + + class + evaluate-mechanisms + comment + Login mechanism based rule for Filevault. + mechanisms + + builtin:policy-banner + loginwindow:login + builtin:login-begin + builtin:authenticate,privileged + builtin:login-success + loginwindow:success + loginwindow:done + system.login.fus @@ -1601,6 +1645,36 @@ See remaining rules for examples. version 1 + com.apple.configurationprofiles.deviceenrollment.install + + class + user + comment + This right is used by UserManagement to ask for an admin password. + group + admin + password-only + + shared + + version + 1 + + com.apple.configurationprofiles.deviceenrollment.uninstall + + class + user + comment + This right is used by UserManagement to ask for an admin password. + group + admin + password-only + + shared + + version + 1 + com.apple.safaridriver.allow comment @@ -1670,7 +1744,18 @@ See remaining rules for examples. timeout 300 - com.apple.system-extensions.admin + com.apple.tcc.util.admin + + comment + For modification of TCC settings. + class + rule + rule + authenticate-admin-nonshared + shared + + + com.apple.system-extensions.admin comment Authorize a 3rd party application which wants to manipulate system extensions. @@ -1681,7 +1766,40 @@ See remaining rules for examples. shared - + com.apple.system-migration.launch + + comment + Used by Migration Assistant. + class + rule + rule + authenticate-admin-nonshared + shared + + + com.apple.system-migration.launch-password + + comment + Used by Migration Assistant. + class + rule + rule + authenticate-admin-nonshared-password + shared + + + com.apple.system-migration.cleanup + + comment + Used by System Migration. + class + rule + rule + authenticate-admin-nonshared + shared + + + rules admin @@ -1730,8 +1848,9 @@ See remaining rules for examples. builtin:authenticate builtin:reset-password,privileged builtin:authenticate,privileged - PKINITMechanism:auth,privileged + version + 1 kcunlock @@ -1773,6 +1892,21 @@ See remaining rules for examples. version 1 + authenticate-admin-nonshared-password + + class + user + comment + Authenticate as an administrator with the password. + group + admin + password-only + + timeout + 30 + version + 1 + _mbsetupuser-nonshared class diff --git a/OSX/authd/authtoken.c b/OSX/authd/authtoken.c index 6b0568aa..b39d393c 100644 --- a/OSX/authd/authtoken.c +++ b/OSX/authd/authtoken.c @@ -13,6 +13,8 @@ #include #include +#include + AUTHD_DEFINE_LOG static Boolean AuthTokenEqualCallBack(const void *value1, const void *value2) @@ -395,7 +397,8 @@ auth_token_has_entitlement(auth_token_t auth, const char * entitlement) entitled = process_has_entitlement(auth->creator, entitlement); } }); - + os_log_debug(AUTHD_LOG, "authtoken: PID %d is%{public}s entitled for %{public}s", auth->auditInfo.pid, entitled ? "":" not", entitlement); + return entitled; } @@ -409,7 +412,8 @@ auth_token_has_entitlement_for_right(auth_token_t auth, const char * right) entitled = process_has_entitlement_for_right(auth->creator, right); } }); - + os_log_debug(AUTHD_LOG, "authtoken: PID %d is%{public}s entitled for right %{public}s", auth->auditInfo.pid, entitled ? "":" not", right); + return entitled; } diff --git a/OSX/authd/authutilities.c b/OSX/authd/authutilities.c index 60b6b2fd..c9d0236e 100644 --- a/OSX/authd/authutilities.c +++ b/OSX/authd/authutilities.c @@ -5,7 +5,6 @@ #include "debugging.h" #include -#include AUTHD_DEFINE_LOG @@ -23,6 +22,11 @@ SerializeItemSet(const AuthorizationItemSet * itemSet) xpc_object_t item = xpc_dictionary_create(NULL, NULL, 0); require(item != NULL, done); + if (itemSet->items[i].name == NULL) { + os_log_error(AUTHD_LOG, "ItemSet - item #%d name is NULL", i); + xpc_release(item); + continue; + } xpc_dictionary_set_string(item, AUTH_XPC_ITEM_NAME, itemSet->items[i].name); xpc_dictionary_set_uint64(item, AUTH_XPC_ITEM_FLAGS, itemSet->items[i].flags); xpc_dictionary_set_data(item, AUTH_XPC_ITEM_VALUE, itemSet->items[i].value, itemSet->items[i].valueLength); @@ -305,3 +309,9 @@ done: free_safe(values); return result; } + +bool isInFVUnlock() +{ + // temporary solution until we find a better way + return getenv("__OSINSTALL_ENVIRONMENT") != NULL; +} diff --git a/OSX/authd/authutilities.h b/OSX/authd/authutilities.h index ebe1e5a4..80745b9c 100644 --- a/OSX/authd/authutilities.h +++ b/OSX/authd/authutilities.h @@ -26,7 +26,9 @@ void * _copy_data(const void * data, size_t dataLen); bool _cf_set_iterate(CFSetRef, bool(^iterator)(CFTypeRef value)); bool _cf_bag_iterate(CFBagRef, bool(^iterator)(CFTypeRef value)); bool _cf_dictionary_iterate(CFDictionaryRef, bool(^iterator)(CFTypeRef key,CFTypeRef value)); - + +bool isInFVUnlock(void); + #if defined(__cplusplus) } #endif diff --git a/OSX/authd/com.apple.authd.sb b/OSX/authd/com.apple.authd.sb index 5b94ca8a..c63d2c71 100644 --- a/OSX/authd/com.apple.authd.sb +++ b/OSX/authd/com.apple.authd.sb @@ -9,7 +9,8 @@ (allow file-read*) -(allow file-read* file-write* +(allow file-write* + (regex #"^(/System)?/Volumes/Preboot/.*/var/db/\.scnotenforced") (regex #"^/private/var/db/auth\.db.*$") (literal "/private/var/db/mds/system/mds.lock") (subpath (param "TMP_DIR"))) @@ -27,7 +28,9 @@ (global-name "com.apple.security.authhost") (global-name "com.apple.SecurityServer") (global-name "com.apple.system.opendirectoryd.api") - (global-name "com.apple.ocspd")) + (global-name "com.apple.ocspd") + (global-name "com.apple.DiskArbitration.diskarbitrationd") + (global-name "com.apple.diskmanagementd")) (allow ipc-posix-shm (ipc-posix-name "apple.shm.notification_center") @@ -40,3 +43,7 @@ (preference-domain "com.apple.authd")) (allow system-audit system-sched) + +(allow iokit-open + (iokit-user-client-class "AppleAPFSUserClient") + (iokit-user-client-class "AppleKeyStoreUserClient")) diff --git a/OSX/authd/crc.h b/OSX/authd/crc.h index 85184384..fab34a2c 100644 --- a/OSX/authd/crc.h +++ b/OSX/authd/crc.h @@ -19,7 +19,7 @@ crc64_init() AUTH_INLINE uint64_t crc64_final(uint64_t crc) { - return crc ^= xorout; + return crc ^ xorout; } AUTH_INLINE AUTH_NONNULL_ALL uint64_t diff --git a/OSX/authd/credential.c b/OSX/authd/credential.c index 6fd46fc0..280d260d 100644 --- a/OSX/authd/credential.c +++ b/OSX/authd/credential.c @@ -2,6 +2,8 @@ #include "credential.h" #include "authutilities.h" +#include "authitems.h" +#include #include "debugging.h" #include "crc.h" @@ -101,7 +103,7 @@ static credential_t _credential_create() { credential_t cred = NULL; - + cred = (credential_t)_CFRuntimeCreateInstance(kCFAllocatorDefault, credential_get_type_id(), AUTH_CLASS_SIZE(credential), NULL); require(cred != NULL, done); @@ -141,6 +143,23 @@ done: return cred; } +credential_t +credential_create_fvunlock(auth_items_t context, bool session) +{ + credential_t cred = NULL; + + cred = _credential_create(); + require(cred != NULL, done); + + const char *username = session ? "system session" : auth_items_get_string(context, AGENT_USERNAME); + cred->uid = session ? 0 : -500; + cred->name = _copy_string(username); + cred->realName = _copy_string(username); + cred->valid = false; +done: + return cred; +} + credential_t credential_create_with_credential(credential_t srcCred, bool shared) { @@ -220,9 +239,14 @@ credential_is_right(credential_t cred) } bool -credential_check_membership(credential_t cred,const char* group) +credential_check_membership(credential_t cred, const char* group) { bool result = false; + + if (isInFVUnlock()) { + return false; // cannot succeed in FVUnlock as we do not have group data + } + CFStringRef cachedGroup = NULL; require(group != NULL, done); require(cred->uid != 0 || cred->uid != (uid_t)-2, done); diff --git a/OSX/authd/credential.h b/OSX/authd/credential.h index 1f7576e7..1090180d 100644 --- a/OSX/authd/credential.h +++ b/OSX/authd/credential.h @@ -20,6 +20,9 @@ credential_t credential_create_with_credential(credential_t,bool); AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED credential_t credential_create_with_right(const char *); +AUTH_WARN_RESULT AUTH_MALLOC AUTH_RETURNS_RETAINED +credential_t credential_create_fvunlock(auth_items_t context, bool session); + AUTH_NONNULL_ALL uid_t credential_get_uid(credential_t); diff --git a/OSX/authd/engine.c b/OSX/authd/engine.c index 1e4584db..4e7ab2e2 100644 --- a/OSX/authd/engine.c +++ b/OSX/authd/engine.c @@ -37,8 +37,8 @@ static void _set_auth_token_hints(auth_items_t, auth_items_t, auth_token_t); static OSStatus _evaluate_user_credential_for_rule(engine_t, credential_t, rule_t, bool, bool, enum Reason *); static void _engine_set_credential(engine_t, credential_t, bool); static OSStatus _evaluate_rule(engine_t, rule_t, bool *); -static bool _preevaluate_class_rule(engine_t engine, rule_t rule); -static bool _preevaluate_rule(engine_t engine, rule_t rule); +static bool _preevaluate_class_rule(engine_t engine, rule_t rule, const char **group); +static bool _preevaluate_rule(engine_t engine, rule_t rule, const char **group); static uint64_t global_engine_count; @@ -65,7 +65,6 @@ struct _engine_s { auth_rights_t grantedRights; CFTypeRef la_context; - bool preauthorizing; enum Reason reason; int32_t tries; @@ -156,14 +155,16 @@ engine_create(connection_t conn, auth_token_t auth) engine->reason = noReason; - engine->preauthorizing = false; - engine->la_context = NULL; engine->now = CFAbsoluteTimeGetCurrent(); session_update(auth_token_get_session(engine->auth)); - engine->sessionCredential = credential_create(session_get_uid(auth_token_get_session(engine->auth))); + if (isInFVUnlock()) { + engine->sessionCredential = credential_create_fvunlock(NULL, true); + } else { + engine->sessionCredential = credential_create(session_get_uid(auth_token_get_session(engine->auth))); + } engine->credentials = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); engine->effectiveCredentials = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); @@ -313,6 +314,27 @@ _evaluate_credential_for_rule(engine_t engine, credential_t cred, rule_t rule, b } } +static bool _is_fvunlock_user_in_group(engine_t engine, rule_t rule) +{ + if (!isInFVUnlock()) { + return false; + } + + const char *group = rule_get_group(rule); + if (!(group && strcmp(group, "admin") == 0)) { + os_log_error(AUTHD_LOG, "Group %{public}s not supported in FV mode (engine %lld)", group, engine->engine_index); + return false; + } + + const char *data = auth_items_get_string(engine->context, kAuthorizationFVAdmin); + if (!data) { + os_log_error(AUTHD_LOG, "User is not member of the group %{public}s (engine %lld)", group, engine->engine_index); + return false; + } + + return (strcmp(data, "1") == 0); +} + static OSStatus _evaluate_user_credential_for_rule(engine_t engine, credential_t cred, rule_t rule, bool ignoreShared, bool sessionOwner, enum Reason * reason) { @@ -329,7 +351,7 @@ _evaluate_user_credential_for_rule(engine_t engine, credential_t cred, rule_t ru return errAuthorizationDenied; } - if (credential_get_valid(cred) != true) { + if (credential_get_valid(cred) != true && !isInFVUnlock()) { os_log(AUTHD_LOG, "%{public}s %i invalid (does NOT satisfy rule) (engine %lld)", cred_label, credential_get_uid(cred), engine->engine_index); if (reason) { *reason = invalidPassphrase; } return errAuthorizationDenied; @@ -376,7 +398,7 @@ _evaluate_user_credential_for_rule(engine_t engine, credential_t cred, rule_t ru } } - if (credential_check_membership(cred, rule_get_group(rule))) { + if (credential_check_membership(cred, rule_get_group(rule)) || _is_fvunlock_user_in_group(engine, rule)) { os_log(AUTHD_LOG, "%{public}s %i is member of group %{public}s (does satisfy rule) (engine %lld)", cred_label, credential_get_uid(cred), rule_get_group(rule), engine->engine_index); return errAuthorizationSuccess; } else { @@ -612,6 +634,7 @@ _evaluate_mechanisms(engine_t engine, CFArrayRef mechanisms) } done: + auth_items_set_flags(context, AGENT_CONTEXT_AP_PAM_SERVICE_NAME, kAuthorizationContextFlagExtractable); if ((result == kAuthorizationResultUserCanceled) || (result == kAuthorizationResultAllow)) { // only make non-sticky context values available externally auth_items_set_flags(context, kAuthorizationEnvironmentPassword, kAuthorizationContextFlagVolatile); @@ -650,11 +673,16 @@ done: static OSStatus _evaluate_authentication(engine_t engine, rule_t rule) { + os_log_debug(AUTHD_LOG, "engine %lld: FV mode %d", engine->engine_index, isInFVUnlock()); + OSStatus status = errAuthorizationDenied; ccaudit_t ccaudit = ccaudit_create(engine->proc, engine->auth, AUE_ssauthint); os_log_debug(AUTHD_LOG, "engine %lld: evaluate authentication", engine->engine_index); _set_rule_hints(engine->hints, rule); - _set_session_hints(engine, rule); + if (!isInFVUnlock()) { + // we do not need to set hints in FVUnlock as we do not know which user will be authenticated + _set_session_hints(engine, rule); + } CFArrayRef mechanisms = rule_get_mechanisms(rule); if (!(CFArrayGetCount(mechanisms) > 0)) { @@ -683,10 +711,14 @@ _evaluate_authentication(engine_t engine, rule_t rule) status = errAuthorizationDenied; credential_t newCred = NULL; - if (auth_items_exist(engine->context, "uid")) { - newCred = credential_create(auth_items_get_uint(engine->context, "uid")); + + if (isInFVUnlock() && auth_items_exist(engine->context, kAuthorizationFVAdmin)) { + os_log_debug(AUTHD_LOG, "Credentials for FV unlock (engine %lld)", engine->engine_index); + newCred = credential_create_fvunlock(engine->context, false); + } else if (auth_items_exist(engine->context, AGENT_CONTEXT_UID)) { + newCred = credential_create(auth_items_get_uint(engine->context, AGENT_CONTEXT_UID)); } else { - os_log_info(AUTHD_LOG, "Mechanism failed to return a valid uid (engine %lld)", engine->engine_index); + os_log_error(AUTHD_LOG, "Mechanism failed to return a valid UID (engine %lld)", engine->engine_index); if (engine->la_context) { // sheet failed so remove sheet reference and next time, standard dialog will be displayed CFReleaseNull(engine->la_context); @@ -694,12 +726,12 @@ _evaluate_authentication(engine_t engine, rule_t rule) } if (newCred) { - if (credential_get_valid(newCred)) { - os_log(AUTHD_LOG, "UID %u authenticated as user %{public}s (UID %u) for right '%{public}s'", auth_token_get_uid(engine->auth), credential_get_name(newCred), credential_get_uid(newCred), engine->currentRightName); + if (credential_get_valid(newCred) || isInFVUnlock()) { + os_log(AUTHD_LOG, "UID %u authenticated as user %{public}s (UID %i) for right '%{public}s'", auth_token_get_uid(engine->auth), credential_get_name(newCred), credential_get_uid(newCred), engine->currentRightName); ccaudit_log_success(ccaudit, newCred, engine->currentRightName); } else { - os_log(AUTHD_LOG, "UID %u failed to authenticate as user '%{public}s' for right '%{public}s'", auth_token_get_uid(engine->auth), auth_items_get_string(engine->context, "username"), engine->currentRightName); - ccaudit_log_failure(ccaudit, auth_items_get_string(engine->context, "username"), engine->currentRightName); + os_log(AUTHD_LOG, "UID %u failed to authenticate as user '%{public}s' for right '%{public}s'", auth_token_get_uid(engine->auth), auth_items_get_string(engine->context, AGENT_USERNAME), engine->currentRightName); + ccaudit_log_failure(ccaudit, auth_items_get_string(engine->context, AGENT_USERNAME), engine->currentRightName); } status = _evaluate_user_credential_for_rule(engine, newCred, rule, true, false, &engine->reason); @@ -798,10 +830,12 @@ _evaluate_class_user(engine_t engine, rule_t rule) } if (!rule_get_authenticate_user(rule)) { - status = _evaluate_user_credential_for_rule(engine, engine->sessionCredential, rule, true, true, NULL); - - if (status == errAuthorizationSuccess) { - return errAuthorizationSuccess; + if (!isInFVUnlock()) { + status = _evaluate_user_credential_for_rule(engine, engine->sessionCredential, rule, true, true, NULL); + + if (status == errAuthorizationSuccess) { + return errAuthorizationSuccess; + } } return errAuthorizationDenied; @@ -859,22 +893,22 @@ _evaluate_class_user(engine_t engine, rule_t rule) return errAuthorizationSuccess; } - if (!engine->preauthorizing) { - if (!(engine->flags & kAuthorizationFlagInteractionAllowed)) { + if (!(engine->flags & kAuthorizationFlagSheet)) { + if (!(engine->flags & kAuthorizationFlagInteractionAllowed)) { os_log_error(AUTHD_LOG, "Fatal: interaction not allowed (kAuthorizationFlagInteractionAllowed not set) (engine %lld)", engine->engine_index); - return errAuthorizationInteractionNotAllowed; - } - - if (!(session_get_attributes(auth_token_get_session(engine->auth)) & AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS)) { - os_log_error(AUTHD_LOG, "Fatal: interaction not allowed (session has no ui access) (engine %lld)", engine->engine_index); - return errAuthorizationInteractionNotAllowed; - } - - if (server_in_dark_wake() && !(engine->flags & kAuthorizationFlagIgnoreDarkWake)) { - os_log_error(AUTHD_LOG, "Fatal: authorization denied (DW) (engine %lld)", engine->engine_index); - return errAuthorizationDenied; - } - } + return errAuthorizationInteractionNotAllowed; + } + + if (!(session_get_attributes(auth_token_get_session(engine->auth)) & AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS)) { + os_log_error(AUTHD_LOG, "Fatal: interaction not allowed (session has no ui access) (engine %lld)", engine->engine_index); + return errAuthorizationInteractionNotAllowed; + } + + if (server_in_dark_wake() && !(engine->flags & kAuthorizationFlagIgnoreDarkWake)) { + os_log_error(AUTHD_LOG, "Fatal: authorization denied (DW) (engine %lld)", engine->engine_index); + return errAuthorizationDenied; + } + } return _evaluate_authentication(engine, rule); } @@ -924,15 +958,14 @@ _evaluate_class_rule(engine_t engine, rule_t rule, bool *save_pwd) } static bool -_preevaluate_class_rule(engine_t engine, rule_t rule) +_preevaluate_class_rule(engine_t engine, rule_t rule, const char **group) { os_log_debug(AUTHD_LOG, "engine %lld: _preevaluate_class_rule %{public}s", engine->engine_index, rule_get_name(rule)); __block bool password_only = false; rule_delegates_iterator(rule, ^bool(rule_t delegate) { - if (_preevaluate_rule(engine, delegate)) { + if (_preevaluate_rule(engine, delegate, group)) { password_only = true; - return false; } return true; }); @@ -971,8 +1004,8 @@ _evaluate_class_mechanism(engine_t engine, rule_t rule) if (status == errAuthorizationSuccess) { credential_t newCred = NULL; - if (auth_items_exist(engine->context, "uid")) { - newCred = credential_create(auth_items_get_uint(engine->context, "uid")); + if (auth_items_exist(engine->context, AGENT_CONTEXT_UID)) { + newCred = credential_create(auth_items_get_uint(engine->context, AGENT_CONTEXT_UID)); } else { os_log_info(AUTHD_LOG, "Mechanism did not return a uid (engine %lld)", engine->engine_index); } @@ -1048,7 +1081,7 @@ _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) // returns true if this rule or its children contain RC_USER rule with password_only==true static bool -_preevaluate_rule(engine_t engine, rule_t rule) +_preevaluate_rule(engine_t engine, rule_t rule, const char **group) { os_log_debug(AUTHD_LOG, "engine %lld: _preevaluate_rule %{public}s", engine->engine_index, rule_get_name(rule)); @@ -1057,9 +1090,12 @@ _preevaluate_rule(engine_t engine, rule_t rule) case RC_DENY: return false; case RC_USER: + if (group && !*group) { + *group = rule_get_group(rule); + } return rule_get_password_only(rule); case RC_RULE: - return _preevaluate_class_rule(engine, rule); + return _preevaluate_class_rule(engine, rule, group); case RC_MECHANISM: return false; default: @@ -1182,129 +1218,49 @@ static bool _verify_sandbox(engine_t engine, const char * right) #pragma mark - #pragma mark engine methods -OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials) +OSStatus engine_get_right_properties(engine_t engine, const char *rightName, CFDictionaryRef *output) { - os_log(AUTHD_LOG, "engine %lld: preauthorizing", engine->engine_index); + OSStatus status = errAuthorizationInternal; + + CFMutableDictionaryRef properties = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + require(properties != NULL, done); + require(rightName != NULL, done); - OSStatus status = errAuthorizationDenied; - bool save_password = false; - - engine->flags = kAuthorizationFlagExtendRights; - engine->preauthorizing = true; - CFAssignRetained(engine->la_context, engine_copy_context(engine, credentials)); - _extract_password_from_la(engine); - - const char *user = auth_items_get_string(credentials, kAuthorizationEnvironmentUsername); - require(user, done); - - auth_items_set_string(engine->context, kAuthorizationEnvironmentUsername, user); - struct passwd *pwd = getpwnam(user); - require(pwd, done); - - auth_items_set_int(engine->context, AGENT_CONTEXT_UID, pwd->pw_uid); - - const char *service = auth_items_get_string(credentials, AGENT_CONTEXT_AP_PAM_SERVICE_NAME); - - if (service) { - auth_items_set_string(engine->context, AGENT_CONTEXT_AP_USER_NAME, user); - auth_items_set_string(engine->context, AGENT_CONTEXT_AP_PAM_SERVICE_NAME, service); - } - - if (auth_items_exist(credentials, AGENT_CONTEXT_AP_TOKEN)) { - size_t datalen = 0; - const void *data = auth_items_get_data(credentials, AGENT_CONTEXT_AP_TOKEN, &datalen); - if (data) { - auth_items_set_data(engine->context, AGENT_CONTEXT_AP_TOKEN, data, datalen); - } - } - - auth_items_t decrypted_items = auth_items_create(); - require_action(decrypted_items != NULL, done, os_log_error(AUTHD_LOG, "Unable to create items (engine %lld)", engine->engine_index)); - auth_items_content_copy(decrypted_items, auth_token_get_context(engine->auth)); - auth_items_decrypt(decrypted_items, auth_token_get_encryption_key(engine->auth)); - auth_items_copy(engine->context, decrypted_items); - CFReleaseSafe(decrypted_items); - - engine->dismissed = false; - auth_rights_clear(engine->grantedRights); - - rule_t rule = rule_create_preauthorization(); - engine->currentRightName = rule_get_name(rule); - engine->currentRule = rule; - status = _evaluate_rule(engine, rule, &save_password); - switch (status) { - case errAuthorizationSuccess: - os_log(AUTHD_LOG, "Succeeded preauthorizing client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d) (engine %lld)", - process_get_code_url(engine->proc), process_get_pid(engine->proc), - auth_token_get_code_url(engine->auth), auth_token_get_pid(engine->auth), (unsigned int)engine->flags, auth_token_least_privileged(engine->auth), engine->engine_index); - status = errAuthorizationSuccess; - break; - case errAuthorizationDenied: - case errAuthorizationInteractionNotAllowed: - case errAuthorizationCanceled: - os_log(AUTHD_LOG, "Failed to preauthorize client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d) (%i) (engine %lld)", - process_get_code_url(engine->proc), process_get_pid(engine->proc), - auth_token_get_code_url(engine->auth), auth_token_get_pid(engine->auth), (unsigned int)engine->flags, auth_token_least_privileged(engine->auth), (int)status, engine->engine_index); - break; - default: - os_log_error(AUTHD_LOG, "Preauthorize returned %d => returning errAuthorizationInternal (engine %lld)", (int)status, engine->engine_index); - status = errAuthorizationInternal; - break; - } - - CFReleaseSafe(rule); - - if (engine->dismissed) { - os_log_error(AUTHD_LOG, "Engine dismissed (engine %lld)", engine->engine_index); - status = errAuthorizationDenied; - } - - os_log_debug(AUTHD_LOG, "engine %lld: preauthorize result: %d", engine->engine_index, (int)status); - - _cf_set_iterate(engine->credentials, ^bool(CFTypeRef value) { - credential_t cred = (credential_t)value; - // skip all uid credentials when running in least privileged - if (auth_token_least_privileged(engine->auth) && !credential_is_right(cred)) - return true; - - session_t session = auth_token_get_session(engine->auth); - auth_token_set_credential(engine->auth, cred); - if (credential_get_shared(cred)) { - session_set_credential(session, cred); - } - if (credential_is_right(cred)) { - os_log(AUTHD_LOG, "engine %lld: adding least privileged %{public}scredential %{public}s to authorization", engine->engine_index, credential_get_shared(cred) ? "shared " : "", credential_get_name(cred)); - } else { - os_log(AUTHD_LOG, "engine %lld: adding %{public}scredential %{public}s (%i) to authorization", engine->engine_index, credential_get_shared(cred) ? "shared " : "", credential_get_name(cred), credential_get_uid(cred)); - } - return true; - }); - - - if (status == errAuthorizationSuccess && save_password) { - auth_items_set_flags(engine->context, kAuthorizationEnvironmentPassword, kAuthorizationContextFlagExtractable); - } - - if ((status == errAuthorizationSuccess) || (status == errAuthorizationCanceled)) { - auth_items_t encrypted_items = auth_items_create(); - require_action(encrypted_items != NULL, done, os_log_error(AUTHD_LOG, "Unable to create items (engine %lld)", engine->engine_index)); - auth_items_content_copy_with_flags(encrypted_items, engine->context, kAuthorizationContextFlagExtractable); -#if DEBUG - os_log_debug(AUTHD_LOG, "engine %lld: ********** Dumping preauthorized context for encryption **********", engine->engine_index); - os_log_debug(AUTHD_LOG, "%@", encrypted_items); -#endif - auth_items_encrypt(encrypted_items, auth_token_get_encryption_key(engine->auth)); - auth_items_copy_with_flags(auth_token_get_context(engine->auth), encrypted_items, kAuthorizationContextFlagExtractable); - os_log_debug(AUTHD_LOG, "engine %lld: encrypted preauthorization context data", engine->engine_index); - CFReleaseSafe(encrypted_items); - } + // first check if any of rights uses rule with password-only set to true + // if so, set appropriate hint so SecurityAgent won't use alternate authentication methods like smartcard etc. + authdb_connection_t dbconn = authdb_connection_acquire(server_get_database()); // get db handle + + os_log_debug(AUTHD_LOG, "engine %lld: get right properties %{public}s", engine->engine_index, rightName); + rule_t rule = _find_rule(engine, dbconn, rightName); + + if (rule) { + const char *group = NULL; + bool passwordOnly = _preevaluate_rule(engine, rule, &group); + CFDictionarySetValue(properties, CFSTR(kAuthorizationRuleParameterPasswordOnly), passwordOnly ? kCFBooleanTrue : kCFBooleanFalse); + if (group) { + CFStringRef groupCf = CFStringCreateWithCString(kCFAllocatorDefault, group, kCFStringEncodingUTF8); + if (groupCf) { + CFDictionarySetValue(properties, CFSTR(kAuthorizationRuleParameterGroup), groupCf); + CFRelease(groupCf); + } + } + CFRelease(rule); + status = errAuthorizationSuccess; + } else { + os_log_debug(AUTHD_LOG, "engine %lld: cannot get right properties %{public}s", engine->engine_index, rightName); + status = errAuthorizationInvalidRef; + } + + authdb_connection_release(&dbconn); // release db handle + os_log_debug(AUTHD_LOG, "engine %lld: right properties %@", engine->engine_index, properties); + if (output && status == errAuthorizationSuccess) { + *output = properties; + CFRetain(*output); + } done: - engine->preauthorizing = false; - auth_items_clear(engine->context); - auth_items_clear(engine->sticky_context); - CFDictionaryRemoveAllValues(engine->mechanism_agents); - return status; + CFReleaseSafe(properties); + return status; } OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t environment, AuthorizationFlags flags) @@ -1312,11 +1268,12 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en __block OSStatus status = errAuthorizationSuccess; __block bool save_password = false; __block bool password_only = false; - CFIndex rights_count = auth_rights_get_count(rights); + CFIndex rights_count = 0; ccaudit_t ccaudit = NULL; - require(rights != NULL, done); + rights_count = auth_rights_get_count(rights); + ccaudit = ccaudit_create(engine->proc, engine->auth, AUE_ssauthorize); if (auth_rights_get_count(rights) > 0) { ccaudit_log(ccaudit, "begin evaluation", NULL, 0); @@ -1404,7 +1361,6 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en engine_acquire_sheet_data(engine); _extract_password_from_la(engine); - engine->preauthorizing = true; } engine->dismissed = false; @@ -1421,8 +1377,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en os_log_debug(AUTHD_LOG, "engine %lld: checking if rule %{public}s contains password-only item", engine->engine_index, key); rule_t rule = _find_rule(engine, dbconn, key); - - if (rule && _preevaluate_rule(engine, rule)) { + if (rule && _preevaluate_rule(engine, rule, NULL)) { password_only = true; CFReleaseSafe(rule); return false; @@ -1459,9 +1414,10 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en } os_log_debug(AUTHD_LOG, "engine %lld: using rule %{public}s", engine->engine_index, rule_name); + _set_right_hints(engine->hints, key); // set authorization right name for authorizationhost as well // only need the hints & mechanisms if we are going to show ui if (engine->flags & kAuthorizationFlagInteractionAllowed || engine->flags & kAuthorizationFlagSheet) { - _set_right_hints(engine->hints, key); + os_log_debug(AUTHD_LOG, "setting hints for UI authorization"); _set_localization_hints(dbconn, engine->hints, rule); if (!engine->authenticateRule) { engine->authenticateRule = rule_create_with_string("authenticate", dbconn); @@ -1544,10 +1500,6 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en os_log_debug(AUTHD_LOG, "engine %lld: authorize result: %d", engine->engine_index, (int)status); - if (engine->flags & kAuthorizationFlagSheet) { - engine->preauthorizing = false; - } - if ((engine->flags & kAuthorizationFlagExtendRights) && !(engine->flags & kAuthorizationFlagDestroyRights)) { _cf_set_iterate(engine->credentials, ^bool(CFTypeRef value) { credential_t cred = (credential_t)value; diff --git a/OSX/authd/engine.h b/OSX/authd/engine.h index aec7c296..5ef5ce41 100644 --- a/OSX/authd/engine.h +++ b/OSX/authd/engine.h @@ -17,7 +17,7 @@ AUTH_NONNULL1 AUTH_NONNULL2 OSStatus engine_authorize(engine_t, auth_rights_t rights, auth_items_t environment, AuthorizationFlags); AUTH_NONNULL1 AUTH_NONNULL2 -OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials); +OSStatus engine_get_right_properties(engine_t engine, const char *rightName, CFDictionaryRef *output); AUTH_NONNULL_ALL OSStatus engine_verify_modification(engine_t, rule_t, bool remove, bool force_modify); diff --git a/OSX/authd/main.c b/OSX/authd/main.c index dbdcf436..9758737f 100644 --- a/OSX/authd/main.c +++ b/OSX/authd/main.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #if DEBUG @@ -109,9 +109,18 @@ security_auth_peer_event_handler(xpc_connection_t connection, xpc_object_t event } status = errAuthorizationSuccess; break; - case AUTHORIZATION_PREAUTHORIZE_CREDENTIALS: - status = authorization_preauthorize_credentials(conn,event,reply); + case AUTHORIZATION_COPY_RIGHT_PROPERTIES: + status = authorization_copy_right_properties(conn,event,reply); break; + case AUTHORIZATION_COPY_PRELOGIN_USERDB: + status = authorization_copy_prelogin_userdb(conn,event,reply); + break; + case AUTHORIZATION_COPY_PRELOGIN_PREFS: + status = authorization_copy_prelogin_pref_value(conn, event, reply); + break; + case AUTHORIZATION_PRELOGIN_SC_OVERRIDE: + status = authorization_prelogin_smartcardonly_override(conn, event, reply); + break; #if DEBUG case AUTHORIZATION_DEV: server_dev(); diff --git a/OSX/authd/process.c b/OSX/authd/process.c index 4a245757..9affe424 100644 --- a/OSX/authd/process.c +++ b/OSX/authd/process.c @@ -8,10 +8,13 @@ #include "authtoken.h" #include "authutilities.h" #include "ccaudit.h" +#include #include #include +#include + AUTHD_DEFINE_LOG struct _process_s { @@ -139,6 +142,12 @@ process_create(const audit_info_s * auditInfo, session_t session) proc->dispatch_queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); check(proc->dispatch_queue != NULL); + // to have at least some code URL just for case later methods fail + int retval = proc_pidpath(proc->auditInfo.pid, proc->code_url, sizeof(proc->code_url)); + if ( retval <= 0 ) { + os_log_error(AUTHD_LOG, "process: PID %d pidpathfailed %d", proc->auditInfo.pid, retval); + } + CFMutableDictionaryRef codeDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDataRef auditToken = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *)&auditInfo->opaqueToken, sizeof(auditInfo->opaqueToken), kCFAllocatorNull); if (auditToken) { @@ -152,13 +161,22 @@ process_create(const audit_info_s * auditInfo, session_t session) } status = SecCodeCopyGuestWithAttributes(NULL, codeDict, kSecCSDefaultFlags, &codeRef); CFReleaseSafe(codeDict); - if (status) { os_log_error(AUTHD_LOG, "process: PID %d failed to create code ref %d", proc->auditInfo.pid, (int)status); CFReleaseNull(proc); goto done; } + status = SecCodeCopyPath(codeRef, kSecCSDefaultFlags, &code_url); + if (status == errSecSuccess) { + CFURLGetFileSystemRepresentation(code_url, true, (UInt8*)proc->code_url, sizeof(proc->code_url)); + } else { + os_log_error(AUTHD_LOG, "process: PID %d failed to get path %d", proc->auditInfo.pid, (int)status); + } + + status = SecCodeCheckValidity(codeRef, kSecCSDefaultFlags, NULL); + require_noerr_action(status, done, os_log_error(AUTHD_LOG, "process: PID %d SecCodeCheckValidity failed with %d", proc->auditInfo.pid, (int)status)); + status = SecCodeCopySigningInformation(codeRef, kSecCSRequirementInformation, &code_info); require_noerr_action(status, done, os_log_debug(AUTHD_LOG, "process: PID %d SecCodeCopySigningInformation failed with %d", proc->auditInfo.pid, (int)status)); @@ -173,10 +191,6 @@ process_create(const audit_info_s * auditInfo, session_t session) value = NULL; } - if (SecCodeCopyPath(codeRef, kSecCSDefaultFlags, &code_url) == errSecSuccess) { - CFURLGetFileSystemRepresentation(code_url, true, (UInt8*)proc->code_url, sizeof(proc->code_url)); - } - if (CFDictionaryGetValueIfPresent(code_info, kSecCodeInfoIdentifier, &value)) { if (CFGetTypeID(value) == CFStringGetTypeID()) { proc->code_identifier = _copy_cf_string(value, NULL); diff --git a/OSX/authd/rule.c b/OSX/authd/rule.c index a706b4d3..405f0ad0 100644 --- a/OSX/authd/rule.c +++ b/OSX/authd/rule.c @@ -175,36 +175,11 @@ rule_create_default() mech = mechanism_create_with_string("builtin:authenticate,privileged", NULL); CFArrayAppendValue(rule->mechanisms, mech); CFReleaseNull(mech); - - mech = mechanism_create_with_string("PKINITMechanism:auth,privileged", NULL); - CFArrayAppendValue(rule->mechanisms, mech); - CFReleaseNull(mech); done: return rule; } -rule_t -rule_create_preauthorization() -{ - rule_t rule = _rule_create(); - require(rule != NULL, done); - - auth_items_set_int64(rule->data, RULE_TYPE, RT_RIGHT); - auth_items_set_string(rule->data, RULE_NAME, "(preauthorization)"); - auth_items_set_int64(rule->data, RULE_CLASS, RC_USER); - auth_items_set_string(rule->data, RULE_GROUP, "admin"); - auth_items_set_int64(rule->data, RULE_TRIES, 1); - auth_items_set_int64(rule->data, RULE_FLAGS, RuleFlagShared | RuleFlagAuthenticateUser | RuleFlagRequireAppleSigned); - - mechanism_t mech = mechanism_create_with_string("builtin:authenticate,privileged", NULL); - CFArrayAppendValue(rule->mechanisms, mech); - CFReleaseNull(mech); - -done: - return rule; -} - rule_t rule_create_with_string(const char * str, authdb_connection_t dbconn) { @@ -766,7 +741,7 @@ rule_sql_commit(rule_t rule, authdb_connection_t dbconn, CFAbsoluteTime modified mechanism_sql_fetch(mech, dbconn); } } - if (!mechanism_exists(mech)) { + if (!mechanism_exists(mech) && !isInFVUnlock()) { os_log_error(AUTHD_LOG, "Warning mechanism not found on disk %{public}s during import of %{public}s", mechanism_get_string(mech), rule_get_name(rule)); } require_action(mechanism_get_id(mech) != 0, done, os_log_error(AUTHD_LOG, "rule: commit, invalid mechanism %{public}s:%{public}s for %{public}s", mechanism_get_plugin(mech), mechanism_get_param(mech), rule_get_name(rule))); @@ -1168,6 +1143,9 @@ rule_check_flags(rule_t rule, RuleFlags flags) bool rule_get_shared(rule_t rule) { + if (isInFVUnlock()) { + return false; + } return rule_check_flags(rule, RuleFlagShared); } diff --git a/OSX/authd/rule.h b/OSX/authd/rule.h index 098087d5..2d9b630e 100644 --- a/OSX/authd/rule.h +++ b/OSX/authd/rule.h @@ -50,9 +50,6 @@ typedef enum { AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED rule_t rule_create_default(void); -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -rule_t rule_create_preauthorization(void); - AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL1 AUTH_RETURNS_RETAINED rule_t rule_create_with_string(const char *,authdb_connection_t); diff --git a/OSX/authd/server.c b/OSX/authd/server.c index 728ae6e2..cbb4459d 100644 --- a/OSX/authd/server.c +++ b/OSX/authd/server.c @@ -15,6 +15,7 @@ #include "engine.h" #include "connection.h" #include "AuthorizationTags.h" +#include "PreloginUserDb.h" #include #include @@ -29,6 +30,8 @@ #include #include +#include + AUTHD_DEFINE_LOG #define MAX_PROCESS_RIGHTS 100 @@ -384,27 +387,26 @@ done: return status; } -static OSStatus _server_preauthorize(connection_t conn, auth_token_t auth, auth_items_t context, engine_t * engine_out) +static OSStatus _server_get_right_properties(connection_t conn, const char *rightName, CFDictionaryRef *properties) { - __block OSStatus status = errAuthorizationDenied; - engine_t engine = NULL; + OSStatus status = errAuthorizationDenied; + auth_token_t auth = NULL; + engine_t engine = NULL; - require_action(conn, done, status = errAuthorizationInternal); + require_action(conn, done, status = errAuthorizationInternal); + + auth = auth_token_create(connection_get_process(conn), false); + require_action(auth, done, status = errAuthorizationInternal); - engine = engine_create(conn, auth); - require_action(engine, done, status = errAuthorizationInternal); + engine = engine_create(conn, auth); + require_action(engine, done, status = errAuthorizationInternal); - status = engine_preauthorize(engine, context); + status = engine_get_right_properties(engine, rightName, properties); done: - if (engine) { - if (engine_out) { - *engine_out = engine; - } else { - CFRelease(engine); - } - } - return status; + CFReleaseSafe(engine); + CFReleaseSafe(auth); + return status; } static OSStatus _server_authorize(connection_t conn, auth_token_t auth, AuthorizationFlags flags, auth_rights_t rights, auth_items_t environment, engine_t * engine_out) @@ -546,28 +548,31 @@ done: // IN: AUTH_XPC_BLOB, AUTH_XPC_DATA // OUT: OSStatus -authorization_preauthorize_credentials(connection_t conn, xpc_object_t message, xpc_object_t reply) +authorization_copy_right_properties(connection_t conn, xpc_object_t message, xpc_object_t reply) { - OSStatus status = errAuthorizationDenied; - engine_t engine = NULL; + OSStatus status = errAuthorizationDenied; + CFDataRef serializedProperties = NULL; + CFDictionaryRef properties = NULL; + + // Passed in args + const char *right = xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME); + os_log_debug(AUTHD_LOG, "server: right %s", right); - process_t proc = connection_get_process(conn); - - // Passed in args - auth_items_t context = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_DATA)); - - auth_token_t auth = NULL; - status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); - require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "preauthorize_credentials: no auth token")); - - status = _server_preauthorize(conn, auth, context, &engine); - require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "preauthorize_credentials: authorization failed")); + require_action(right != NULL, done, status = errAuthorizationInvalidPointer); + status = _server_get_right_properties(conn, right, &properties); + require_noerr(status, done); + + if (properties) { + serializedProperties = CFPropertyListCreateData(kCFAllocatorDefault, properties, kCFPropertyListBinaryFormat_v1_0, 0, NULL); + if (serializedProperties) { + xpc_dictionary_set_data(reply, AUTH_XPC_OUT_ITEMS, CFDataGetBytePtr(serializedProperties), CFDataGetLength(serializedProperties)); + } + } + done: - CFReleaseSafe(context); - CFReleaseSafe(auth); - CFReleaseSafe(engine); - + CFReleaseSafe(serializedProperties); + CFReleaseSafe(properties); return status; } @@ -1175,3 +1180,93 @@ server_dev() { // CFReleaseSafe(items); } +// IN: AUTH_XPC_TAG, AUTH_XPC_FLAGS +// OUT: AUTH_XPC_DATA +OSStatus +authorization_copy_prelogin_userdb(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationDenied; + xpc_object_t xpcarr = NULL; + CFArrayRef cfarray = NULL; + + const char *uuid = xpc_dictionary_get_string(message, AUTH_XPC_TAG); + UInt32 flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); + + status = preloginudb_copy_userdb(uuid, flags, &cfarray); + xpc_dictionary_set_int64(reply, AUTH_XPC_STATUS, status); + require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "authorization_copy_prelogin_userdb: database failed %d", (int)status)); + + xpcarr = _CFXPCCreateXPCObjectFromCFObject(cfarray); + require(xpcarr != NULL, done); + xpc_dictionary_set_value(reply, AUTH_XPC_DATA, xpcarr); + +done: + CFReleaseSafe(cfarray); + xpc_release_safe(xpcarr); + + return status; +} + +// IN: AUTH_XPC_RIGHT_NAME, AUTH_XPC_HINTS_NAME, AUTH_XPC_FLAGS +// OUT: AUTH_XPC_DATA +OSStatus +authorization_copy_prelogin_pref_value(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationDenied; + xpc_object_t xpcoutput = NULL; + const char *uuid = xpc_dictionary_get_string(message, AUTH_XPC_TAG); + const char *user = xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME); + const char *domain = xpc_dictionary_get_string(message, AUTH_XPC_HINTS_NAME); + const char *item = xpc_dictionary_get_string(message, AUTH_XPC_ITEM_NAME); + + CFTypeRef output = NULL; + status = prelogin_copy_pref_value(uuid, user, domain, item, &output); + xpc_dictionary_set_int64(reply, AUTH_XPC_STATUS, status); + + xpcoutput = _CFXPCCreateXPCObjectFromCFObject(output); + require(xpcoutput != NULL, done); + xpc_dictionary_set_value(reply, AUTH_XPC_DATA, xpcoutput); + +done: + CFReleaseSafe(output); + xpc_release_safe(xpcoutput); + + return status; +} + +// IN: AUTH_XPC_RIGHT_NAME, AUTH_XPC_ITEM_NAME +// OUT: AUTH_XPC_ITEM_VALUE +OSStatus +authorization_prelogin_smartcardonly_override(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationDenied; + + process_t proc = connection_get_process(conn); + + uint64 operation = xpc_dictionary_get_uint64(message, AUTH_XPC_ITEM_NAME); + + if (operation != kAuthorizationOverrideOperationQuery) { + // check if caller is entitled to handle the override + Boolean entitlementCheckPassed = false; + CFTypeRef overrideEntitlement = process_copy_entitlement_value(proc, "com.apple.authorization.smartcard.override"); + if (overrideEntitlement && (CFGetTypeID(overrideEntitlement) == CFBooleanGetTypeID()) && overrideEntitlement == kCFBooleanTrue) { + os_log_debug(AUTHD_LOG, "server: caller allowed to handle override"); + entitlementCheckPassed = true; + } else { + os_log_error(AUTHD_LOG, "server: caller NOT allowed to handle override"); + } + CFReleaseSafe(overrideEntitlement); + require(entitlementCheckPassed, done); + } + + const char *uuid = xpc_dictionary_get_string(message, AUTH_XPC_TAG); + Boolean result = false; + status = prelogin_smartcardonly_override(uuid, operation, &result); + xpc_dictionary_set_int64(reply, AUTH_XPC_STATUS, status); + if (operation == kAuthorizationOverrideOperationQuery) { + xpc_dictionary_set_bool(reply, AUTH_XPC_ITEM_VALUE, result); + } + +done: + return status; +} diff --git a/OSX/authd/server.h b/OSX/authd/server.h index 7889bb32..a320b5ef 100644 --- a/OSX/authd/server.h +++ b/OSX/authd/server.h @@ -47,7 +47,7 @@ AUTH_NONNULL_ALL OSStatus authorization_free(connection_t,xpc_object_t,xpc_object_t); AUTH_NONNULL_ALL -OSStatus authorization_preauthorize_credentials(connection_t, xpc_object_t, xpc_object_t); +OSStatus authorization_copy_right_properties(connection_t, xpc_object_t, xpc_object_t); AUTH_NONNULL_ALL OSStatus authorization_copy_rights(connection_t,xpc_object_t,xpc_object_t); @@ -76,6 +76,17 @@ OSStatus authorization_right_remove(connection_t,xpc_object_t,xpc_object_t); AUTH_NONNULL_ALL OSStatus session_set_user_preferences(connection_t,xpc_object_t,xpc_object_t); +AUTH_NONNULL_ALL +OSStatus authorization_copy_prelogin_userdb(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus +authorization_copy_prelogin_pref_value(connection_t conn, xpc_object_t message, xpc_object_t reply); + +AUTH_NONNULL_ALL +OSStatus +authorization_prelogin_smartcardonly_override(connection_t conn, xpc_object_t message, xpc_object_t reply); + #if defined(__cplusplus) } #endif diff --git a/OSX/authd/session.c b/OSX/authd/session.c index 83d548e8..0df2882e 100644 --- a/OSX/authd/session.c +++ b/OSX/authd/session.c @@ -6,6 +6,8 @@ #include #include +#include + AUTHD_DEFINE_LOG struct _session_s { diff --git a/OSX/authd/tests/authdtestlist.h b/OSX/authd/tests/authdtestlist.h index 1987df61..befca8f5 100644 --- a/OSX/authd/tests/authdtestlist.h +++ b/OSX/authd/tests/authdtestlist.h @@ -4,3 +4,4 @@ ONE_TEST(authd_01_authorizationdb) ONE_TEST(authd_02_basicauthorization) ONE_TEST(authd_04_executewithprivileges) +ONE_TEST(authd_05_rightproperties) diff --git a/OSX/authd/tests/authdtests.m b/OSX/authd/tests/authdtests.m index c6c45180..99bb8eac 100644 --- a/OSX/authd/tests/authdtests.m +++ b/OSX/authd/tests/authdtests.m @@ -4,6 +4,7 @@ // #import +#import #import #import #import @@ -282,3 +283,42 @@ int authd_04_executewithprivileges(int argc, char *const *argv) AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); return 0; } + +int authd_05_rightproperties(int argc, char *const *argv) +{ + plan_tests(5); + + NSDictionary *properties; + CFDictionaryRef cfProperties; + NSString *group; + NSNumber *passwordOnly; + + OSStatus status = AuthorizationCopyRightProperties("system.csfde.requestpassword", &cfProperties); + properties = CFBridgingRelease(cfProperties); + if (status != errAuthorizationSuccess) { + fail("AuthorizationCopyRightProperties failed with %d", (int)status); + goto done; + } + + pass("AuthorizationCopyRightProperties call succeess"); + passwordOnly = properties[@(kAuthorizationRuleParameterPasswordOnly)]; + ok(passwordOnly.boolValue, "Returned system.csfde.requestpassword as password only right"); + group = properties[@(kAuthorizationRuleParameterGroup)]; + ok([group isEqualToString:@"admin"], "Returned admin as a required group for system.csfde.requestpassword"); + + status = AuthorizationCopyRightProperties("com.apple.Safari.allow-unsigned-app-extensions", &cfProperties); + properties = CFBridgingRelease(cfProperties); + if (status != errAuthorizationSuccess) { + fail("AuthorizationCopyRightProperties failed with %d", (int)status); + goto done; + } + group = properties[@(kAuthorizationRuleParameterGroup)]; + passwordOnly = properties[@(kAuthorizationRuleParameterPasswordOnly)]; + ok(group.length == 0 && passwordOnly.boolValue == NO, "Returned safari right as non-password only, no specific group"); + + status = AuthorizationCopyRightProperties("non-existing-right", &cfProperties); + ok(status == errAuthorizationSuccess, "Returned success for default for unknown right: %d", (int)status); + +done: + return 0; +} diff --git a/OSX/codesign_tests/CaspianTests/CaspianTests b/OSX/codesign_tests/CaspianTests/CaspianTests old mode 100644 new mode 100755 diff --git a/OSX/codesign_tests/CaspianTests/LocalCaspianTestRun.sh b/OSX/codesign_tests/CaspianTests/LocalCaspianTestRun.sh old mode 100644 new mode 100755 diff --git a/OSX/codesign_tests/teamid.sh b/OSX/codesign_tests/teamid.sh old mode 100644 new mode 100755 diff --git a/OSX/codesign_tests/validation.sh b/OSX/codesign_tests/validation.sh old mode 100644 new mode 100755 diff --git a/OSX/config/lib.xcconfig b/OSX/config/lib.xcconfig index 7c298b95..81c1da20 100644 --- a/OSX/config/lib.xcconfig +++ b/OSX/config/lib.xcconfig @@ -14,7 +14,7 @@ SKIP_INSTALL = YES ALWAYS_SEARCH_USER_PATHS = NO -GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_C_LANGUAGE_STANDARD = gnu2x GCC_TREAT_WARNINGS_AS_ERRORS = YES; diff --git a/OSX/config/security_framework_macos.xcconfig b/OSX/config/security_framework_macos.xcconfig index f341fbd7..3ee4720d 100644 --- a/OSX/config/security_framework_macos.xcconfig +++ b/OSX/config/security_framework_macos.xcconfig @@ -12,16 +12,23 @@ DYLIB_CURRENT_VERSION = $(CURRENT_PROJECT_VERSION) MODULEMAP_FILE = Modules/Security.macOS.modulemap DEFINES_MODULE = YES -EXPORTED_SYMBOLS_FILE = $(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).exp +EXPORTED_SYMBOLS_FILE = $(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).$(CURRENT_ARCH).exp ORDER_FILE = OSX/lib/Security.order INFOPLIST_FILE = OSX/lib/Info-Security.plist INSTALL_PATH = $(SYSTEM_LIBRARY_DIR)/Frameworks ASAN_EXTRA_LDFLAGS_YES = -Wl,-no_warn_inits -ASAN_EXTRA_LDFLAGS_NO = -Wl,-no_inits +ASAN_EXTRA_LDFLAGS_NO = ASAN_EXTRA_LDFLAGS_ = $(ASAN_EXTRA_LDFLAGS_NO) -OTHER_LDFLAGS = -laks -lCrashReporterClient -Wl,-upward_framework,Foundation $(ASAN_EXTRA_LDFLAGS_$(ENABLE_ADDRESS_SANITIZER)) +TSAN_EXTRA_LDFLAGS_YES = -Wl,-no_warn_inits +TSAN_EXTRA_LDFLAGS_NO = +TSAN_EXTRA_LDFLAGS_ = $(TSAN_EXTRA_LDFLAGS_NO) + +// order here matters, so later more specific options override earlier. +NOINIT_LDFLAGS = -Wl,-no_inits $(ASAN_EXTRA_LDFLAGS_$(ENABLE_ADDRESS_SANITIZER)) $(TSAN_EXTRA_LDFLAGS_$(ENABLE_THREAD_SANITIZER)) + +OTHER_LDFLAGS = -laks -lCrashReporterClient -Wl,-upward_framework,Foundation $(NOINIT_LDFLAGS) SECTORDER_FLAGS = -order_file_statistics APPLY_RULES_IN_COPY_FILES = NO diff --git a/OSX/config/security_macos.xcconfig b/OSX/config/security_macos.xcconfig index 58ed08ab..bdd02709 100644 --- a/OSX/config/security_macos.xcconfig +++ b/OSX/config/security_macos.xcconfig @@ -11,7 +11,7 @@ LIBRARY_SEARCH_PATHS = $(inherited) /usr/lib/system STRIP_INSTALLED_PRODUCT = YES DEPLOYMENT_POSTPROCESSING = NO -GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_C_LANGUAGE_STANDARD = gnu2x SUPPORTED_PLATFORMS = macosx GCC_TREAT_WARNINGS_AS_ERRORS = YES diff --git a/OSX/include/security_asn1 b/OSX/include/security_asn1 deleted file mode 120000 index 2464d12b..00000000 --- a/OSX/include/security_asn1 +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_asn1/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_client b/OSX/include/security_cdsa_client deleted file mode 120000 index a166f753..00000000 --- a/OSX/include/security_cdsa_client +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_cdsa_client/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_plugin b/OSX/include/security_cdsa_plugin deleted file mode 120000 index 6b95dcfd..00000000 --- a/OSX/include/security_cdsa_plugin +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_cdsa_plugin/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_utilities b/OSX/include/security_cdsa_utilities deleted file mode 120000 index 5c56ce5d..00000000 --- a/OSX/include/security_cdsa_utilities +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_cdsa_utilities/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_utils b/OSX/include/security_cdsa_utils deleted file mode 120000 index de7e2fdb..00000000 --- a/OSX/include/security_cdsa_utils +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_cdsa_utils/lib \ No newline at end of file diff --git a/OSX/include/security_codesigning b/OSX/include/security_codesigning deleted file mode 120000 index 9cb3210a..00000000 --- a/OSX/include/security_codesigning +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_codesigning/lib \ No newline at end of file diff --git a/OSX/include/security_comcryption b/OSX/include/security_comcryption deleted file mode 120000 index b2f66cb9..00000000 --- a/OSX/include/security_comcryption +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_comcryption/lib \ No newline at end of file diff --git a/OSX/include/security_cryptkit b/OSX/include/security_cryptkit deleted file mode 120000 index 0a024633..00000000 --- a/OSX/include/security_cryptkit +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_cryptkit/lib \ No newline at end of file diff --git a/OSX/include/security_filedb b/OSX/include/security_filedb deleted file mode 120000 index 7f3fdeae..00000000 --- a/OSX/include/security_filedb +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_filedb/lib \ No newline at end of file diff --git a/OSX/include/security_keychain b/OSX/include/security_keychain deleted file mode 120000 index b30a4c54..00000000 --- a/OSX/include/security_keychain +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_keychain/lib \ No newline at end of file diff --git a/OSX/include/security_ocspd b/OSX/include/security_ocspd deleted file mode 120000 index 9e886da7..00000000 --- a/OSX/include/security_ocspd +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_ocspd/common \ No newline at end of file diff --git a/OSX/include/security_pkcs12 b/OSX/include/security_pkcs12 deleted file mode 120000 index 05fccd76..00000000 --- a/OSX/include/security_pkcs12 +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_pkcs12/lib \ No newline at end of file diff --git a/OSX/include/security_smime b/OSX/include/security_smime deleted file mode 120000 index 834197e7..00000000 --- a/OSX/include/security_smime +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_smime/lib \ No newline at end of file diff --git a/OSX/include/security_utilities b/OSX/include/security_utilities deleted file mode 120000 index a33e77fb..00000000 --- a/OSX/include/security_utilities +++ /dev/null @@ -1 +0,0 @@ -../libsecurity_utilities/lib \ No newline at end of file diff --git a/OSX/include/securityd_client b/OSX/include/securityd_client deleted file mode 120000 index 12e15c0f..00000000 --- a/OSX/include/securityd_client +++ /dev/null @@ -1 +0,0 @@ -../libsecurityd/lib \ No newline at end of file diff --git a/OSX/lib/en.lproj/InfoPlist.strings b/OSX/lib/en.lproj/InfoPlist.strings index b99cba58..79058ccc 100644 Binary files a/OSX/lib/en.lproj/InfoPlist.strings and b/OSX/lib/en.lproj/InfoPlist.strings differ diff --git a/OSX/lib/en.lproj/authorization.buttons.strings b/OSX/lib/en.lproj/authorization.buttons.strings index 1871c226..b7c044ed 100644 --- a/OSX/lib/en.lproj/authorization.buttons.strings +++ b/OSX/lib/en.lproj/authorization.buttons.strings @@ -143,3 +143,7 @@ "com.apple.security.sudo" = "Allow"; "com.apple.configurationprofiles.userenrollment.install" = "Enroll"; + +"com.apple.configurationprofiles.deviceenrollment.install" = "Enroll"; + +"com.apple.configurationprofiles.deviceenrollment.uninstall" = "Unenroll"; diff --git a/OSX/lib/en.lproj/authorization.dfr.prompts.strings b/OSX/lib/en.lproj/authorization.dfr.prompts.strings index e54e35f7..d434c80d 100644 --- a/OSX/lib/en.lproj/authorization.dfr.prompts.strings +++ b/OSX/lib/en.lproj/authorization.dfr.prompts.strings @@ -1,6 +1,6 @@ "system.preferences.accounts" = "Touch ID to Unlock Users & Groups Preferences."; -"com.apple.SoftwareUpdate.scan" = "Touch ID to Check for New Apple-provided Software."; +"com.apple.SoftwareUpdate.scan" = "Touch ID to Check for New Apple Software."; "system.preferences.datetime" = "Touch ID to Unlock the Date & Time Preferences."; @@ -48,9 +48,9 @@ "system.preferences.energysaver" = "Touch ID to Unlock the Energy Saver Preferences."; -"system.install.apple-software" = "Touch ID to Install Apple-provided Software."; +"system.install.apple-software" = "Touch ID to Install Apple Software."; -"system.install.apple-software.standard-user" = "Touch ID to Install Apple-provided software."; +"system.install.apple-software.standard-user" = "Touch ID to Install Apple software."; "com.apple.security.assessment.update" = "Touch ID to Install an App from an Unidentified Developer."; diff --git a/OSX/lib/en.lproj/authorization.prompts.strings b/OSX/lib/en.lproj/authorization.prompts.strings index 1686dbd6..568c080a 100644 --- a/OSX/lib/en.lproj/authorization.prompts.strings +++ b/OSX/lib/en.lproj/authorization.prompts.strings @@ -1,6 +1,6 @@ "system.preferences.accounts" = "__APPNAME__ is trying to unlock Users & Groups preferences."; -"com.apple.SoftwareUpdate.scan" = "__APPNAME__ is trying to check for new Apple-provided software."; +"com.apple.SoftwareUpdate.scan" = "__APPNAME__ is trying to check for new Apple software."; "system.preferences.datetime" = "__APPNAME__ is trying to unlock the Date & Time preferences."; @@ -48,9 +48,9 @@ "system.preferences.energysaver" = "__APPNAME__ is trying to unlock the Energy Saver preferences."; -"system.install.apple-software" = "__APPNAME__ is trying to install Apple-provided software."; +"system.install.apple-software" = "__APPNAME__ is trying to install Apple software."; -"system.install.apple-software.standard-user" = "__APPNAME__ is trying to install Apple-provided software."; +"system.install.apple-software.standard-user" = "__APPNAME__ is trying to install Apple software."; "com.apple.security.assessment.update" = "You are overriding your security preferences to install an app from an unidentified developer."; @@ -173,3 +173,9 @@ "com.apple.configurationprofiles.userenrollment.install" = "__APPNAME__ is trying to enroll you in a remote management (MDM) service."; "com.apple.system-extensions.admin" = "__APPNAME__ is trying to modify a System Extension."; + +"com.apple.tcc.util.admin" = "__APPNAME__ is trying to modify your Security & Privacy settings."; + +"com.apple.configurationprofiles.deviceenrollment.install" = "__APPNAME__ is trying to enroll you in a remote management (MDM) service."; + +"com.apple.configurationprofiles.deviceenrollment.uninstall" = "__APPNAME__ is trying to unenroll you from a remote management (MDM) service."; diff --git a/OSX/lib/framework.sb b/OSX/lib/framework.sb deleted file mode 100644 index e37bf7c4..00000000 --- a/OSX/lib/framework.sb +++ /dev/null @@ -1,11 +0,0 @@ -;; allow clients to communicate with secd -(allow mach-lookup (global-name "com.apple.secd")) -;; allow clients to communicate with coreauthd -(allow mach-lookup (global-name "com.apple.CoreAuthentication.daemon")) -(allow mach-lookup (global-name "com.apple.CoreAuthentication.agent")) -;; allow clients to communicate with ctkd -(allow mach-lookup (global-name "com.apple.ctkd.token-client")) - -;; On internal builds, allow clients to read the AMFITrustedKeys NVRAM variable -(with-filter (system-attribute apple-internal) - (allow nvram-get (nvram-variable "AMFITrustedKeys"))) diff --git a/OSX/libsecurity_apple_csp/lib/CryptKitSpace.h b/OSX/libsecurity_apple_csp/lib/CryptKitSpace.h old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_apple_csp/lib/DH_keys.cpp b/OSX/libsecurity_apple_csp/lib/DH_keys.cpp index 6060dfe5..d5dc2e4e 100644 --- a/OSX/libsecurity_apple_csp/lib/DH_keys.cpp +++ b/OSX/libsecurity_apple_csp/lib/DH_keys.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_apple_csp/lib/DH_utils.cpp b/OSX/libsecurity_apple_csp/lib/DH_utils.cpp index aec4d18d..33232c7a 100644 --- a/OSX/libsecurity_apple_csp/lib/DH_utils.cpp +++ b/OSX/libsecurity_apple_csp/lib/DH_utils.cpp @@ -121,7 +121,7 @@ DH *rawCssmKeyToDh( // someone else's key (should never happen) CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); } - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); /* validate and figure out what we're dealing with */ switch(hdr->KeyClass) { case CSSM_KEYCLASS_PUBLIC_KEY: diff --git a/OSX/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp b/OSX/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp index 080d555d..d9c08703 100644 --- a/OSX/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp @@ -106,7 +106,7 @@ void CryptKit::FEEDContext::init( mAllocdPrivKey); } else { - assert(opStarted()); + assert(opStarted()); } if(mPubKey == NULL) { assert(!opStarted()); @@ -118,7 +118,7 @@ void CryptKit::FEEDContext::init( mAllocdPubKey); } else { - assert(opStarted()); + assert(opStarted()); } /* validate context - no other attributes allowed */ diff --git a/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp b/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp index 8c317b80..4966db8d 100644 --- a/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp @@ -168,7 +168,7 @@ feePubKey CryptKit::rawCssmKeyToFee( const CssmKey &cssmKey) { const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); switch(hdr->AlgorithmId) { case CSSM_ALGID_FEE: diff --git a/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp b/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp index e906bdf8..1dc36ae7 100644 --- a/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp @@ -31,7 +31,7 @@ #include #include "AppleCSPSession.h" #include "AppleCSPUtils.h" -#include +#include #include #define feeKeyDebug(args...) secinfo("feeKey", ## args) diff --git a/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp b/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp index 413b6cf1..4175a0cb 100644 --- a/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #define feeSigObjDebug(args...) secinfo("feeSig", ##args) diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp index e73c092f..5974f788 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include "RSA_DSA_utils.h" #include diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp index ae818296..fdcbf96b 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp @@ -23,7 +23,7 @@ #include "RSA_DSA_signature.h" #include "RSA_DSA_utils.h" #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp index 8fb48fd1..7b8f894e 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp @@ -114,7 +114,7 @@ RSAKeySizes::RSAKeySizes() if (d->dict()) { - auto_ptrapd(d); + unique_ptrapd(d); rsaLookupVal(*apd, kRSAMaxKeySizePref, maxKeySize); rsaLookupVal(*apd, kRSAMaxPublicExponentPref, maxPubExponentSize); } @@ -223,7 +223,7 @@ RSA *rawCssmKeyToRsa( bool isPub; bool isOaep = false; - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); switch(hdr->AlgorithmId) { case CSSM_ALGID_RSA: @@ -504,7 +504,7 @@ DSA *rawCssmKeyToDsa( const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; bool isPub; - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); if(hdr->AlgorithmId != CSSM_ALGID_DSA) { // someone else's key (should never happen) diff --git a/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp b/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp index d0983f5b..2d394aca 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp @@ -85,7 +85,7 @@ void RSA_CryptContext::init(const Context &context, bool encoding /*= true*/) } } else { - assert(opStarted()); + assert(opStarted()); } unsigned cipherBlockSize = RSA_size(mRsaKey); diff --git a/OSX/libsecurity_apple_csp/lib/pkcs12Derive.cpp b/OSX/libsecurity_apple_csp/lib/pkcs12Derive.cpp index 6e0b4279..dce62a69 100644 --- a/OSX/libsecurity_apple_csp/lib/pkcs12Derive.cpp +++ b/OSX/libsecurity_apple_csp/lib/pkcs12Derive.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/OSX/libsecurity_apple_csp/lib/pkcs8.cpp b/OSX/libsecurity_apple_csp/lib/pkcs8.cpp index 6d1a16c7..d68c3170 100644 --- a/OSX/libsecurity_apple_csp/lib/pkcs8.cpp +++ b/OSX/libsecurity_apple_csp/lib/pkcs8.cpp @@ -88,7 +88,7 @@ void AppleCSPSession::pkcs8InferKeyHeader( */ CSSM_KEY_SIZE keySize; try { - auto_ptr provider(infoProvider(key)); + unique_ptr provider(infoProvider(key)); provider->QueryKeySizeInBits(keySize); } catch(const CssmError &cerror) { @@ -103,7 +103,7 @@ void AppleCSPSession::pkcs8InferKeyHeader( (hdr.AlgorithmId == CSSM_ALGID_DSA)) { hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186; try { - auto_ptr provider(infoProvider(key)); + unique_ptr provider(infoProvider(key)); provider->QueryKeySizeInBits(keySize); } catch(...) { @@ -198,7 +198,7 @@ void AppleCSPSession::opensslInferKeyHeader( /* now figure out the key size by finding a provider for this key */ CSSM_KEY_SIZE keySize; try { - auto_ptr provider(infoProvider(key)); + unique_ptr provider(infoProvider(key)); provider->QueryKeySizeInBits(keySize); } catch(...) { diff --git a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_asm.c b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_asm.c index b956a092..eb23d658 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_asm.c +++ b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_asm.c @@ -80,7 +80,7 @@ #endif #include -#include +#include #include "cryptlib.h" #include "bn_lcl.h" diff --git a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c index c896a752..c769764d 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c +++ b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c @@ -78,7 +78,7 @@ #endif #include -#include +#include #include "cryptlib.h" #include diff --git a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_exp.c b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_exp.c index 81173237..6c67c1b9 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_exp.c +++ b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_exp.c @@ -116,7 +116,7 @@ #ifdef ATALLA # include # include -# include +# include # include #endif diff --git a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h index af312c7f..801b6fe2 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h +++ b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h @@ -225,13 +225,8 @@ extern "C" { #define Lw(t) (((BN_ULONG)(t))&BN_MASK2) #define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) -/* This is used for internal error checking and is not normally used */ -#ifdef BN_DEBUG -# include -# define bn_check_top(a) assert ((a)->top >= 0 && (a)->top <= (a)->dmax); -#else -# define bn_check_top(a) -#endif +#include +#define bn_check_top(a) assert((a)->top >= 0 && (a)->top <= (a)->max); /* This macro is to add extra stuff for development checking */ #ifdef BN_DEBUG diff --git a/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp b/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp index cd652271..cb01bce2 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp +++ b/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp @@ -35,7 +35,7 @@ #include #include -#include +#include #define sslAsn1Debug(args...) secinfo("sslAsn1", ##args) diff --git a/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c b/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c index 55029916..1264b623 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c +++ b/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c @@ -155,8 +155,10 @@ int RSA_verify_ASN1_OCTET_STRING(int dtype, unsigned char *m, ret=1; err: if (sig != NULL) M_ASN1_OCTET_STRING_free(sig); - memset(s,0,(unsigned int)siglen); - Free(s); + if(s) { + memset(s,0,(unsigned int)siglen); + Free(s); + } return(ret); - } +} diff --git a/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c b/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c index fff3be5f..323dc930 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c +++ b/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c @@ -232,8 +232,10 @@ int RSA_verify(int dtype, unsigned char *m, unsigned int m_len, } err: if (sig != NULL) X509_SIG_free(sig); - memset(s,0,(unsigned int)siglen); - Free(s); + if(s) { + memset(s,0,(unsigned int)siglen); + Free(s); + } return(ret); - } +} diff --git a/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp b/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp index d079b3f0..48c60120 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp @@ -357,9 +357,9 @@ SSCSPSession::FreeKey(const AccessCredentials *accessCred, // that! // Find the key in the map. Tell tell the key to free itself - // (when the auto_ptr deletes the key it removes itself from the map). + // (when the unique_ptr deletes the key it removes itself from the map). secinfo("freeKey", "CSPDL FreeKey"); - auto_ptr ssKey(&mSSCSPDLSession.find(ioKey)); + unique_ptr ssKey(&mSSCSPDLSession.find(ioKey)); ssKey->free(accessCred, ioKey, deleteKey); } else diff --git a/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp b/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp index b0523932..4f23d986 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp @@ -488,7 +488,7 @@ SSCryptContext::final(CssmData &out) if(!inSize) return; const CssmData in(const_cast(mNullDigest.digestPtr()), inSize); - IFDEBUG(size_t origOutSize = out.length()); + size_t origOutSize = out.length(); if (encoding()) { clientSession().encrypt(*mContext, mKeyHandle, in, out); } diff --git a/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp b/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp index aa198e08..de2e019b 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp +++ b/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp @@ -335,7 +335,7 @@ bool getFieldSubjectKeyId( /* if this fails, we're out of sync with nssExtenInfo[] in * CLFieldsCommon.cpp */ - assert(nssObj != NULL); + assert(nssObj != NULL); clAllocCopyData(alloc, *nssObj, *cdsaObj); getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); return true; diff --git a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp index d94b373d..3ebe668b 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp +++ b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp @@ -37,7 +37,7 @@ /* * Avoid inlining this for debuggability */ -void *ArenaAllocator::malloc(size_t len) throw(std::bad_alloc) +void *ArenaAllocator::malloc(size_t len) { try { return mCoder.malloc(len); @@ -48,11 +48,11 @@ void *ArenaAllocator::malloc(size_t len) throw(std::bad_alloc) } /* intentionally not implemented, should never be called */ -void ArenaAllocator::free(void *p) throw() +void ArenaAllocator::free(void *p) _NOEXCEPT { } -void *ArenaAllocator::realloc(void *p, size_t len) throw(std::bad_alloc) +void *ArenaAllocator::realloc(void *p, size_t len) { throw std::bad_alloc(); } diff --git a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.h b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.h index e62cffac..ebca2ebd 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.h +++ b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.h @@ -42,9 +42,9 @@ public: ArenaAllocator(SecNssCoder &coder) : mCoder(coder) { } ~ArenaAllocator() { } - void *malloc(size_t) throw(std::bad_alloc) ; - void free(void *) throw() ; - void *realloc(void *, size_t) throw(std::bad_alloc); + void *malloc(size_t); + void free(void *) _NOEXCEPT ; + void *realloc(void *, size_t); private: SecNssCoder &mCoder; }; diff --git a/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp b/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp index 460af75a..e5554ff0 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp index 0ad65a53..3bf095dc 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp @@ -30,154 +30,6 @@ #include #include -/* - * This is a temporary hack to allow verification of PKINIT server certs - * which are self-signed and not in the system anchors list. If the self- - * signed cert is in a magic keychain (whose location is not published), - * we'll allow it as if it were indeed a full-fledged anchor cert. - */ -#define TP_PKINIT_SERVER_HACK 1 -#if TP_PKINIT_SERVER_HACK - -#include -#include -#include -#include -#include -#include - -#define CFRELEASE(cf) if(cf) { CFRelease(cf); } - -/* - * Returns true if we are to allow/trust the specified - * cert as a PKINIT-only anchor. - */ -static bool tpCheckPkinitServerCert( - TPCertGroup &certGroup) -{ - /* - * Basic requirement: exactly one cert, self-signed. - * The numCerts == 1 requirement might change... - */ - unsigned numCerts = certGroup.numCerts(); - if(numCerts != 1) { - tpDebug("tpCheckPkinitServerCert: too many certs"); - return false; - } - /* end of chain... */ - TPCertInfo *theCert = certGroup.certAtIndex(numCerts - 1); - if(!theCert->isSelfSigned()) { - tpDebug("tpCheckPkinitServerCert: 1 cert, not self-signed"); - return false; - } - const CSSM_DATA *subjectName = theCert->subjectName(); - - /* - * Open the magic keychain. - * We're going up and over the Sec layer here, not generally - * kosher, but this is a hack. - */ - OSStatus ortn; - SecKeychainRef kcRef = NULL; - string fullPathName; - const char *homeDir = getenv("HOME"); - if (homeDir == NULL) - { - // If $HOME is unset get the current user's home directory - // from the passwd file. - uid_t uid = geteuid(); - if (!uid) uid = getuid(); - struct passwd *pw = getpwuid(uid); - if (!pw) { - return false; - } - homeDir = pw->pw_dir; - } - fullPathName = homeDir; - fullPathName += "/Library/Application Support/PKINIT/TrustedServers.keychain"; - ortn = SecKeychainOpen(fullPathName.c_str(), &kcRef); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: keychain not found (1)"); - return false; - } - /* subsequent errors to errOut: */ - - bool ourRtn = false; - SecKeychainStatus kcStatus; - CSSM_DATA_PTR subjSerial = NULL; - CSSM_RETURN crtn; - SecKeychainSearchRef srchRef = NULL; - SecKeychainAttributeList attrList; - SecKeychainAttribute attrs[2]; - SecKeychainItemRef foundItem = NULL; - - ortn = SecKeychainGetStatus(kcRef, &kcStatus); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: keychain not found (2)"); - goto errOut; - } - - /* - * We already have this cert's normalized name; get its - * serial number. - */ - crtn = theCert->fetchField(&CSSMOID_X509V1SerialNumber, &subjSerial); - if(crtn) { - /* should never happen */ - tpDebug("tpCheckPkinitServerCert: error fetching serial number"); - goto errOut; - } - - attrs[0].tag = kSecSubjectItemAttr; - attrs[0].length = (UInt32)subjectName->Length; - attrs[0].data = subjectName->Data; - attrs[1].tag = kSecSerialNumberItemAttr; - attrs[1].length = (UInt32)subjSerial->Length; - attrs[1].data = subjSerial->Data; - attrList.count = 2; - attrList.attr = attrs; - - ortn = SecKeychainSearchCreateFromAttributes(kcRef, - kSecCertificateItemClass, - &attrList, - &srchRef); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: search failure"); - goto errOut; - } - for(;;) { - ortn = SecKeychainSearchCopyNext(srchRef, &foundItem); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: end search"); - break; - } - - /* found a matching cert; do byte-for-byte compare */ - CSSM_DATA certData; - ortn = SecCertificateGetData((SecCertificateRef)foundItem, &certData); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: SecCertificateGetData failure"); - continue; - } - if(tpCompareCssmData(&certData, theCert->itemData())){ - tpDebug("tpCheckPkinitServerCert: FOUND CERT"); - ourRtn = true; - break; - } - tpDebug("tpCheckPkinitServerCert: skipping matching cert"); - CFRelease(foundItem); - foundItem = NULL; - } -errOut: - CFRELEASE(kcRef); - CFRELEASE(srchRef); - CFRELEASE(foundItem); - if(subjSerial != NULL) { - theCert->freeField(&CSSMOID_X509V1SerialNumber, subjSerial); - } - return ourRtn; -} -#endif /* TP_PKINIT_SERVER_HACK */ /*----------------------------------------------------------------------------- * CertGroupConstruct @@ -829,16 +681,6 @@ void AppleTPSession::CertGroupVerify(CSSM_CL_HANDLE clHand, if(policyAbort) { break; } - #if TP_PKINIT_SERVER_HACK - if(tpPolicy == kTP_PKINIT_Server) { - /* possible override of "root not in anchors" */ - if(constructReturn == CSSMERR_TP_INVALID_ANCHOR_CERT) { - if(tpCheckPkinitServerCert(outCertGroup)) { - constructReturn = CSSM_OK; - } - } - } - #endif /* TP_PKINIT_SERVER_HACK */ } /* diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp index 28e9e179..2eb31d08 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #define tpCredDebug(args...) secinfo("tpCred", ## args) diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp index 5ac0ef4f..786e2f8a 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include /* * Set this flag nonzero to turn off this cache module. Generally used to debug diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp index 17c152f8..24a24e2e 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpTime.c b/OSX/libsecurity_apple_x509_tp/lib/tpTime.c index 058cab00..b0983af0 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpTime.c +++ b/OSX/libsecurity_apple_x509_tp/lib/tpTime.c @@ -28,6 +28,8 @@ #include #include +#include + /* * Given a string containing either a UTC-style or "generalized time" * time string, convert to a CFDateRef. Returns nonzero on diff --git a/OSX/libsecurity_asn1/lib/SecNssCoder.cpp b/OSX/libsecurity_asn1/lib/SecNssCoder.cpp index 067fb8d8..ef321524 100644 --- a/OSX/libsecurity_asn1/lib/SecNssCoder.cpp +++ b/OSX/libsecurity_asn1/lib/SecNssCoder.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #ifdef NDEBUG #define THROW_ENABLE 1 diff --git a/OSX/libsecurity_asn1/lib/X509Templates.c b/OSX/libsecurity_asn1/lib/X509Templates.c index 93dda3e7..302445c5 100644 --- a/OSX/libsecurity_asn1/lib/X509Templates.c +++ b/OSX/libsecurity_asn1/lib/X509Templates.c @@ -26,7 +26,6 @@ #include "SecAsn1Templates.h" #include "X509Templates.h" #include "keyTemplates.h" -#include #include /* diff --git a/OSX/libsecurity_asn1/lib/certExtensionTemplates.c b/OSX/libsecurity_asn1/lib/certExtensionTemplates.c index 02315128..2c9e98d3 100644 --- a/OSX/libsecurity_asn1/lib/certExtensionTemplates.c +++ b/OSX/libsecurity_asn1/lib/certExtensionTemplates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012,2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -310,12 +310,12 @@ const SecAsn1Template kSecAsn1PolicyMappingsTemplate[] = { const SecAsn1Template kSecAsn1PolicyConstraintsTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_PolicyConstraints) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | - SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, - offsetof(NSS_PolicyConstraints,requireExplicitPolicy) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | - SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, - offsetof(NSS_PolicyConstraints,inhibitPolicyMapping) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSS_PolicyConstraints,requireExplicitPolicy), + kSecAsn1IntegerTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(NSS_PolicyConstraints,inhibitPolicyMapping), + kSecAsn1IntegerTemplate }, { 0 } }; diff --git a/OSX/libsecurity_asn1/lib/nameTemplates.c b/OSX/libsecurity_asn1/lib/nameTemplates.c index 84ce8b34..370512d9 100644 --- a/OSX/libsecurity_asn1/lib/nameTemplates.c +++ b/OSX/libsecurity_asn1/lib/nameTemplates.c @@ -28,7 +28,7 @@ #include "X509Templates.h" #include "keyTemplates.h" #include -#include +#include typedef struct { SecAsn1Oid typeId; diff --git a/OSX/libsecurity_asn1/lib/ocspTemplates.c b/OSX/libsecurity_asn1/lib/ocspTemplates.c index 0dcbf947..8721457f 100644 --- a/OSX/libsecurity_asn1/lib/ocspTemplates.c +++ b/OSX/libsecurity_asn1/lib/ocspTemplates.c @@ -27,7 +27,6 @@ #include "keyTemplates.h" /* for kSecAsn1AlgorithmIDTemplate */ #include "SecAsn1Templates.h" #include -#include // MARK: ----- OCSP Request ----- diff --git a/OSX/libsecurity_asn1/lib/plarena.c b/OSX/libsecurity_asn1/lib/plarena.c index 48c69b3e..b072da1e 100644 --- a/OSX/libsecurity_asn1/lib/plarena.c +++ b/OSX/libsecurity_asn1/lib/plarena.c @@ -300,8 +300,9 @@ static void FreeArenaList(PLArenaPool *pool, PLArena *head, PRBool reallyFree) ap = &head->next; a = *ap; - if (!a) + if (!a) { return; + } do { *ap = a->next; diff --git a/OSX/libsecurity_asn1/lib/prlog.h b/OSX/libsecurity_asn1/lib/prlog.h index c0b3b841..9256da95 100644 --- a/OSX/libsecurity_asn1/lib/prlog.h +++ b/OSX/libsecurity_asn1/lib/prlog.h @@ -236,7 +236,7 @@ NSPR_API(void) PR_LogFlush(void); #ifdef __APPLE__ -#include +#include #define PR_ASSERT(_exp) assert(_exp) #define PR_NOT_REACHED(_reas) assert(0) @@ -250,10 +250,19 @@ NSPR_API(void) PR_Assert(const char *s, const char *file, PRIntn ln); PR_Assert(_reasonStr,__FILE__,__LINE__) #endif -#else +#else /* defined(DEBUG) || defined(FORCE_PR_ASSERT) */ +#ifdef __APPLE__ + +#include + +#define PR_ASSERT(_exp) assert(_exp) +#define PR_NOT_REACHED(_reas) assert(0) + +#else #define PR_ASSERT(expr) ((void) 0) #define PR_NOT_REACHED(reasonStr) +#endif #endif /* defined(DEBUG) || defined(FORCE_PR_ASSERT) */ diff --git a/OSX/libsecurity_asn1/lib/secasn1d.c b/OSX/libsecurity_asn1/lib/secasn1d.c index cd37fc4a..564e1877 100644 --- a/OSX/libsecurity_asn1/lib/secasn1d.c +++ b/OSX/libsecurity_asn1/lib/secasn1d.c @@ -41,7 +41,7 @@ #include "secasn1.h" #include "secerr.h" -#include "assert.h" +#include #ifdef NDEBUG #define DEBUG_DECASN1 0 @@ -434,9 +434,6 @@ loser: PORT_ArenaRelease(cx->our_pool, state->our_mark); state->our_mark = NULL; } - if (new_state != NULL) { - PORT_Free(new_state); - } return NULL; } @@ -1794,19 +1791,13 @@ sec_asn1d_parse_bit_string (sec_asn1d_state *state, /*PORT_Assert (state->pending > 0); */ PORT_Assert (state->place == beforeBitString); - if ((state->pending == 0) || (state->contents_length == 1)) { + if (state->pending == 0) { if (state->dest != NULL) { SecAsn1Item *item = (SecAsn1Item *)(state->dest); item->Data = NULL; item->Length = 0; state->place = beforeEndOfContents; - } - if(state->contents_length == 1) { - /* skip over (unused) remainder byte */ - return 1; - } - else { - return 0; + return 0; } } @@ -1879,8 +1870,9 @@ sec_asn1d_add_to_subitems (sec_asn1d_state *state, if (copy == NULL) { dprintf("decodeError: alloc\n"); state->top->status = decodeError; - if (!state->top->our_pool) + if (!state->top->our_pool) { PORT_Free(thing); + } return NULL; } PORT_Memcpy (copy, data, len); @@ -1912,9 +1904,9 @@ sec_asn1d_record_any_header (sec_asn1d_state *state, item = (SecAsn1Item *)(state->dest); if (item != NULL && item->Data != NULL) { - PORT_Assert (state->substring); - PORT_Memcpy (item->Data + item->Length, buf, len); - item->Length += len; + dprintf("decodeError: sec_asn1d_record_any_header unknown allocation size\n"); + PORT_SetError (SEC_ERROR_LIBRARY_FAILURE); + state->top->status = decodeError; } else { sec_asn1d_add_to_subitems (state, buf, len, PR_TRUE); } diff --git a/OSX/libsecurity_asn1/security_asn1 b/OSX/libsecurity_asn1/security_asn1 deleted file mode 120000 index 7951405f..00000000 --- a/OSX/libsecurity_asn1/security_asn1 +++ /dev/null @@ -1 +0,0 @@ -lib \ No newline at end of file diff --git a/OSX/libsecurity_authorization/lib/Authorization.c b/OSX/libsecurity_authorization/lib/Authorization.c index bd929ed8..9aaa6dc5 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.c +++ b/OSX/libsecurity_authorization/lib/Authorization.c @@ -14,14 +14,9 @@ #include #include #include -#include #include #include -#ifndef DARLING #include -#else -typedef uint32_t CGWindowID; -#endif #include #include @@ -57,20 +52,24 @@ get_authorization_connection() connection = xpc_connection_create(SECURITY_AUTH_NAME, NULL); if (!connection) { - syslog(LOG_ERR, "Authorization, failed to create xpc connection to %s", SECURITY_AUTH_NAME); + os_log_error(AUTH_LOG, "Failed to create xpc connection to %s", SECURITY_AUTH_NAME); connection = xpc_connection_create(SECURITY_AUTH_NAME, NULL); } + if (connection == NULL) { + os_log_error(AUTH_LOG, "Still failed to create xpc connection to %s", SECURITY_AUTH_NAME); + return; + } xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { if (xpc_get_type(event) == XPC_TYPE_ERROR) { if (event == XPC_ERROR_CONNECTION_INVALID) { - syslog(LOG_ERR, "Authorization, server not available"); + os_log_error(AUTH_LOG, "Server not available"); } // XPC_ERROR_CONNECTION_INTERRUPTED // XPC_ERROR_TERMINATION_IMMINENT } else { char * desc = xpc_copy_description(event); - syslog(LOG_ERR, "Authorization, we should never get messages on this connection: %s", desc); + os_log_error(AUTH_LOG, "We should never get messages on this connection: %s", desc); free(desc); } }); @@ -123,7 +122,9 @@ OSStatus AuthorizationCreate(const AuthorizationRights *rights, xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags | (authorization ? 0 : kAuthorizationFlagNoData)); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action_quiet(reply != NULL, done, status = errAuthorizationInternal); require_action_quiet(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal;); @@ -135,7 +136,7 @@ OSStatus AuthorizationCreate(const AuthorizationRights *rights, size_t len; const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len); require_action(data != NULL, done, status = errAuthorizationInternal); - assert(len == sizeof(AuthorizationBlob)); + require_action(len == sizeof(AuthorizationBlob), done, status = errAuthorizationInternal); AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob)); require_action(blob != NULL, done, status = errAuthorizationInternal); @@ -171,7 +172,9 @@ OSStatus AuthorizationCreateWithAuditToken(audit_token_t token, xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -183,8 +186,8 @@ OSStatus AuthorizationCreateWithAuditToken(audit_token_t token, size_t len; const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len); require_action(data != NULL, done, status = errAuthorizationInternal); - assert(len == sizeof(AuthorizationBlob)); - + require_action(len == sizeof(AuthorizationBlob), done, status = errAuthorizationInternal); + AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob)); require_action(blob != NULL, done, status = errAuthorizationInternal); *blob = *(AuthorizationBlob*)data; @@ -217,7 +220,9 @@ OSStatus AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags fl xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -233,62 +238,40 @@ done: return status; } -static OSStatus -_AuthorizationPreauthorizeCredentials_send_message(xpc_object_t message) +OSStatus AuthorizationCopyRightProperties(const char *rightName, CFDictionaryRef *output) { - OSStatus status = errAuthorizationInternal; - xpc_object_t reply = NULL; - - // Send - require_action(message != NULL, done, status = errAuthorizationInternal); - - // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); - require_action(reply != NULL, done, status = errAuthorizationInternal); - require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); - - // Status - status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); - -done: - xpc_release_safe(reply); - return status; -} - -static OSStatus -_AuthorizationPreauthorizeCredentials_prepare_message(AuthorizationRef authorization, const AuthorizationItemSet *credentials, xpc_object_t *message_out) -{ - OSStatus status = errAuthorizationInternal; - AuthorizationBlob *blob = NULL; - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - require_action(message != NULL, done, status = errAuthorizationInternal); - - require_action(authorization != NULL, done, status = errAuthorizationInvalidRef); - blob = (AuthorizationBlob *)authorization; - - xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_PREAUTHORIZE_CREDENTIALS); - xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); - setItemSet(message, AUTH_XPC_DATA, credentials); - - *message_out = message; - message = NULL; - status = errAuthorizationSuccess; - -done: - xpc_release_safe(message); - return status; -} - -OSStatus AuthorizationPreauthorizeCredentials(AuthorizationRef authorization, const AuthorizationItemSet *credentials) -{ - OSStatus status = errAuthorizationInternal; - xpc_object_t message = NULL; - - require_noerr(status = _AuthorizationPreauthorizeCredentials_prepare_message(authorization, credentials, &message), done); - require_noerr(status = _AuthorizationPreauthorizeCredentials_send_message(message), done); - + OSStatus status = errAuthorizationInternal; + xpc_object_t reply = NULL; + CFDataRef data = NULL; + xpc_object_t message = NULL; + require_action(rightName != NULL, done, status = errAuthorizationInvalidPointer); + + message = xpc_dictionary_create(NULL, NULL, 0); + require_action(message != NULL, done, status = errAuthorizationInternal); + + xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_RIGHT_PROPERTIES); + xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName); + + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); + require_action(reply != NULL, done, status = errAuthorizationInternal); + require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); + + // Status + status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); + if (output && status == errAuthorizationSuccess) { + size_t len; + const void *bytes = xpc_dictionary_get_data(reply, AUTH_XPC_OUT_ITEMS, &len); + data = CFDataCreate(kCFAllocatorDefault, bytes, len); + require_action(data != NULL, done, status = errAuthorizationInternal); + *output = CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL, NULL); + } done: xpc_release_safe(message); + xpc_release_safe(reply); + CFReleaseSafe(data); + return status; } @@ -302,7 +285,9 @@ _AuthorizationCopyRights_send_message(xpc_object_t message, AuthorizationRights require_action(message != NULL, done, status = errAuthorizationInternal); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -395,6 +380,7 @@ OSStatus AuthorizationCopyRights(AuthorizationRef authorization, os_log_debug(AUTH_LOG, "Failed to find sheet support in SecurityInterface"); } // fall back to the standard (windowed) version if sheets are not available + flags &= ~kAuthorizationFlagSheet; } } @@ -444,7 +430,9 @@ OSStatus AuthorizationDismiss() xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_DISMISS); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -481,7 +469,9 @@ OSStatus AuthorizationCopyInfo(AuthorizationRef authorization, } // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -523,7 +513,9 @@ OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization, xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -535,8 +527,8 @@ OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization, size_t len; const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_EXTERNAL, &len); require_action(data != NULL, done, status = errAuthorizationInternal); - assert(len == sizeof(AuthorizationExternalForm)); - + require_action(len == sizeof(AuthorizationExternalForm), done, status = errAuthorizationInternal); + *extForm = *(AuthorizationExternalForm*)data; } @@ -564,7 +556,9 @@ OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *ex xpc_dictionary_set_data(message, AUTH_XPC_EXTERNAL, extForm, sizeof(AuthorizationExternalForm)); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -576,8 +570,8 @@ OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *ex size_t len; const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len); require_action(data != NULL, done, status = errAuthorizationInternal); - assert(len == sizeof(AuthorizationBlob)); - + require_action(len == sizeof(AuthorizationBlob), done, status = errAuthorizationInternal); + AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob)); require_action(blob != NULL, done, status = errAuthorizationInternal); *blob = *(AuthorizationBlob*)data; @@ -614,7 +608,9 @@ OSStatus AuthorizationEnableSmartCard(AuthorizationRef authRef, Boolean enable) xpc_dictionary_set_bool(message, AUTH_XPC_DATA, enable); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -644,7 +640,9 @@ OSStatus AuthorizationRightGet(const char *rightName, xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -788,7 +786,9 @@ OSStatus AuthorizationRightSet(AuthorizationRef authRef, xpc_release_safe(value); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -824,7 +824,9 @@ OSStatus AuthorizationRightRemove(AuthorizationRef authorization, xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -836,3 +838,117 @@ done: xpc_release_safe(reply); return status; } + +OSStatus AuthorizationCopyPreloginUserDatabase(const char * _Nullable const volumeUuid, const UInt32 flags, CFArrayRef _Nonnull * _Nonnull output) +{ + OSStatus status = errAuthorizationInternal; + xpc_object_t message = NULL; + xpc_object_t reply = NULL; + + require_action(output != NULL, done, status = errAuthorizationInvalidRef); + + // Send + message = xpc_dictionary_create(NULL, NULL, 0); + require_action(message != NULL, done, status = errAuthorizationInternal); + xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_PRELOGIN_USERDB); + if (volumeUuid) { + xpc_dictionary_set_string(message, AUTH_XPC_TAG, volumeUuid); + } + xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags); + + // Reply + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); + require_action(reply != NULL, done, status = errAuthorizationInternal); + require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); + + status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); + + // fill the output + if (status == errAuthorizationSuccess) { + *output = _CFXPCCreateCFObjectFromXPCObject(xpc_dictionary_get_value(reply, AUTH_XPC_DATA)); + } + +done: + xpc_release_safe(message); + xpc_release_safe(reply); + return status; +} + +OSStatus AuthorizationCopyPreloginPreferencesValue(const char * _Nonnull const volumeUuid, const char * _Nullable const username, const char * _Nonnull const domain, const char * _Nullable const item, CFTypeRef _Nonnull * _Nonnull output) +{ + OSStatus status = errAuthorizationInternal; + xpc_object_t message = NULL; + xpc_object_t reply = NULL; + + require_action(output != NULL, done, status = errAuthorizationInvalidRef); + + // Send + message = xpc_dictionary_create(NULL, NULL, 0); + require_action(message != NULL, done, status = errAuthorizationInternal); + xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_PRELOGIN_PREFS); + if (volumeUuid) { + xpc_dictionary_set_string(message, AUTH_XPC_TAG, volumeUuid); + } + if (username) { + xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, username); + } + if (domain) { + xpc_dictionary_set_string(message, AUTH_XPC_HINTS_NAME, domain); + } + if (item) { + xpc_dictionary_set_string(message, AUTH_XPC_ITEM_NAME, item); + } + + // Reply + reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + require_action(reply != NULL, done, status = errAuthorizationInternal); + require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); + + status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); + + // fill the output + if (status == errAuthorizationSuccess) { + *output = _CFXPCCreateCFObjectFromXPCObject(xpc_dictionary_get_value(reply, AUTH_XPC_DATA)); + } + +done: + xpc_release_safe(message); + xpc_release_safe(reply); + return status; +} + +OSStatus AuthorizationHandlePreloginOverride(const char * _Nonnull const volumeUuid, const char operation, Boolean * _Nullable result) +{ + OSStatus status = errAuthorizationInternal; + xpc_object_t message = NULL; + xpc_object_t reply = NULL; + + // Send + message = xpc_dictionary_create(NULL, NULL, 0); + require_action(message != NULL, done, status = errAuthorizationInternal); + xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_PRELOGIN_SC_OVERRIDE); + if (volumeUuid) { + xpc_dictionary_set_string(message, AUTH_XPC_TAG, volumeUuid); + } + uint64_t op = operation; + xpc_dictionary_set_uint64(message, AUTH_XPC_ITEM_NAME, op); + + // Reply + reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + require_action(reply != NULL, done, status = errAuthorizationInternal); + require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); + + status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); + + // fill the output only if it is present in the dictionary and caller requested it + if (status == errAuthorizationSuccess && result && xpc_dictionary_get_value(reply, AUTH_XPC_ITEM_VALUE)) { + *result = xpc_dictionary_get_bool(reply, AUTH_XPC_ITEM_VALUE); + } + +done: + xpc_release_safe(message); + xpc_release_safe(reply); + return status; +} diff --git a/OSX/libsecurity_authorization/lib/Authorization.cpp b/OSX/libsecurity_authorization/lib/Authorization.cpp index 71db80cf..c4dd7051 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.cpp +++ b/OSX/libsecurity_authorization/lib/Authorization.cpp @@ -34,6 +34,7 @@ #include #include #include +#include "LegacyAPICounts.h" // // This no longer talks to securityd; it is a kernel function. @@ -42,7 +43,11 @@ OSStatus SessionGetInfo(SecuritySessionId requestedSession, SecuritySessionId *sessionId, SessionAttributeBits *attributes) { - BEGIN_API + BEGIN_API_NO_METRICS + if (requestedSession != noSecuritySession && requestedSession != callerSecuritySession) { + static dispatch_once_t countToken; + countLegacyAPI(&countToken, __FUNCTION__); + } CommonCriteria::AuditInfo session; if (requestedSession == callerSecuritySession) session.get(); @@ -105,75 +110,7 @@ OSStatus SessionGetDistinguishedUser(SecuritySessionId session, uid_t *user) END_API(CSSM) } -//OSStatus _SessionSetUserPreferences(SecuritySessionId session); -// -//static -//void SessionUserPreferencesChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) -//{ -//#warning "The cast will loose some information" -// _SessionSetUserPreferences((SecuritySessionId)uintptr_t(observer)); -//} -// -//OSStatus _SessionSetUserPreferences(SecuritySessionId session) -//{ -// BEGIN_API -// CFStringRef appleLanguagesStr = CFSTR("AppleLanguages"); -// CFStringRef controlTintStr = CFSTR("AppleAquaColorVariant"); -// CFStringRef keyboardUIModeStr = CFSTR("AppleKeyboardUIMode"); -// CFStringRef textDirectionStr = CFSTR("AppleTextDirection"); -// CFStringRef hitoolboxAppIDStr = CFSTR("com.apple.HIToolbox"); -// CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); -// -// CFRef userPrefsDict(CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); -// CFRef globalPrefsDict(CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); -// -// if (!userPrefsDict || !globalPrefsDict) -// return errSessionValueNotSet; -// -// CFRef appleLanguagesArray(static_cast(CFPreferencesCopyAppValue(appleLanguagesStr, kCFPreferencesCurrentApplication))); -// if (appleLanguagesArray) -// CFDictionarySetValue(globalPrefsDict, appleLanguagesStr, appleLanguagesArray); -// -// CFRef controlTintNumber(static_cast(CFPreferencesCopyAppValue(controlTintStr, kCFPreferencesCurrentApplication))); -// if (controlTintNumber) -// CFDictionarySetValue(globalPrefsDict, controlTintStr, controlTintNumber); -// -// CFRef keyboardUIModeNumber(static_cast(CFPreferencesCopyAppValue(keyboardUIModeStr, kCFPreferencesCurrentApplication))); -// if (keyboardUIModeNumber) -// CFDictionarySetValue(globalPrefsDict, keyboardUIModeStr, keyboardUIModeNumber); -// -// CFRef textDirectionNumber(static_cast(CFPreferencesCopyAppValue(textDirectionStr, kCFPreferencesCurrentApplication))); -// if (textDirectionNumber) -// CFDictionarySetValue(globalPrefsDict, textDirectionStr, textDirectionNumber); -// -// if (CFDictionaryGetCount(globalPrefsDict) > 0) -// CFDictionarySetValue(userPrefsDict, kCFPreferencesAnyApplication, globalPrefsDict); -// -// CFPreferencesSynchronize(hitoolboxAppIDStr, kCFPreferencesCurrentUser, -// kCFPreferencesCurrentHost); -// CFRef hitoolboxPrefsDict(static_cast(CFPreferencesCopyMultiple(NULL, hitoolboxAppIDStr, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost))); -// if (hitoolboxPrefsDict) { -// CFDictionarySetValue(userPrefsDict, hitoolboxAppIDStr, hitoolboxPrefsDict); -// CFNotificationCenterPostNotification(center, CFSTR("com.apple.securityagent.InputPrefsChanged"), CFSTR("com.apple.loginwindow"), hitoolboxPrefsDict, true); -// } -// -// CFRef userPrefsData(CFPropertyListCreateXMLData(NULL, userPrefsDict)); -// if (!userPrefsData) -// return errSessionValueNotSet; -// server().setSessionUserPrefs(session, (uint32_t)CFDataGetLength(userPrefsData), CFDataGetBytePtr(userPrefsData)); -// -// END_API(CSSM) -//} - OSStatus SessionSetUserPreferences(SecuritySessionId session) { -// OSStatus status = _SessionSetUserPreferences(session); -// if (errSecSuccess == status) { -// CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); -// // We've succeeded in setting up a static set of prefs, now set up -// CFNotificationCenterAddObserver(center, (void*)session, SessionUserPreferencesChanged, CFSTR("com.apple.Carbon.TISNotifySelectedKeyboardInputSourceChanged"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); -// CFNotificationCenterAddObserver(center, (void*)session, SessionUserPreferencesChanged, CFSTR("com.apple.Carbon.TISNotifyEnabledKeyboardInputSourcesChanged"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); -// } -// return status; return errSecSuccess; } diff --git a/OSX/libsecurity_authorization/lib/Authorization.h b/OSX/libsecurity_authorization/lib/Authorization.h index e92e6c2d..534c8adf 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.h +++ b/OSX/libsecurity_authorization/lib/Authorization.h @@ -145,7 +145,7 @@ typedef const char *AuthorizationString; /*! - @struct AuthorizationItem + @typedef AuthorizationItem Each AuthorizationItem describes a single string-named item with optional parameter value. The value must be contiguous memory of valueLength bytes; internal structure is defined separately for each name. @@ -165,7 +165,7 @@ typedef struct { /*! - @struct AuthorizationItemSet + @typedef AuthorizationItemSet An AuthorizationItemSet structure represents a set of zero or more AuthorizationItems. Since it is a set it should not contain any identical AuthorizationItems. @field count Number of items identified by items. @@ -179,7 +179,7 @@ typedef struct { static const size_t kAuthorizationExternalFormLength = 32; /*! - @struct AuthorizationExternalForm + @typedef AuthorizationExternalForm An AuthorizationExternalForm structure can hold the externalized form of an AuthorizationRef. As such, it can be transmitted across IPC channels to other processes, which can re-internalize it to recover a valid AuthorizationRef @@ -190,16 +190,7 @@ static const size_t kAuthorizationExternalFormLength = 32; potential attackers since it would authorize rights to them. */ typedef struct { -#if defined(DARLING) && defined(__clang__) - // this warning is useless and repeated throughout MANY compilation units if left enabled - // it's easier to disable it here than to disable in each and every CMakeLists.txt - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wgnu-folding-constant" -#endif char bytes[kAuthorizationExternalFormLength]; -#if defined(DARLING) && defined(__clang__) - #pragma GCC diagnostic pop -#endif } AuthorizationExternalForm; diff --git a/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h b/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h index de083b3f..4447c72a 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h @@ -181,7 +181,7 @@ enum { /*! - @struct + @typedef Callback API provided by the AuthorizationEngine. @field version Engine callback version. @@ -289,7 +289,7 @@ typedef struct AuthorizationCallbacks { /*! - @struct + @typedef Interface that must be implemented by each plugin. @field version Must be set to kAuthorizationPluginInterfaceVersion diff --git a/OSX/libsecurity_authorization/lib/AuthorizationPriv.h b/OSX/libsecurity_authorization/lib/AuthorizationPriv.h index bd9ec936..1ee1f67e 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationPriv.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationPriv.h @@ -35,6 +35,7 @@ #include #include // uid_t #include +#include #if defined(__cplusplus) extern "C" { @@ -59,6 +60,15 @@ enum { kAuthorizationFlagIgnoreDarkWake = (1 << 8), }; +/*! + @enum Private operations for AuthorizationHandlePreloginOverride +*/ +enum { + kAuthorizationOverrideOperationSet, + kAuthorizationOverrideOperationReset, + kAuthorizationOverrideOperationQuery +}; + /*! @function AuthorizationCreateWithAuditToken @abstract Create a AuthorizationRef for the process that sent the mach message @@ -133,12 +143,13 @@ OSStatus AuthorizationExecuteWithPrivileges(AuthorizationRef _Nonnull authorizat FILE * __nullable * __nullable communicationsPipe) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_7,__IPHONE_NA,__IPHONE_NA); /*! - @function AuthorizationPreauthorizeCredentials - Tries to preauthorize provided credentials by authorizationhost PAM. No user interface will be shown. - Credentials is set of the context items which will be passed to the authorizationhost. + @function AuthorizationCopyRightProperties + Returns a dictionary with the properties associated with the given authorization right + @param rightName right name for which we need the propertiers + @param output CFDictionaryRef which will hold the properties + */ -OSStatus AuthorizationPreauthorizeCredentials(AuthorizationRef _Nonnull authorization, - const AuthorizationItemSet * __nonnull credentials) __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); +OSStatus AuthorizationCopyRightProperties(const char * __nonnull rightName, CFDictionaryRef __nullable * __nullable output) __OSX_AVAILABLE_STARTING(__MAC_10_15, __IPHONE_NA); /*! @function AuthorizationCopyPrivilegedReference @@ -230,7 +241,7 @@ OSStatus AuthorizationEnableSmartCard(AuthorizationRef _Nonnull authRef, Boolean @param stdIn File descriptor which will contain write-end of the stdin pipe of the privileged tool, use -1 if not needed. @param processFinished This block is called when privileged process finishes. */ - OSStatus AuthorizationExecuteWithPrivilegesInternal(const AuthorizationRef _Nonnull authorization, +OSStatus AuthorizationExecuteWithPrivilegesInternal(const AuthorizationRef _Nonnull authorization, const char * _Nonnull pathToTool, const char * _Nonnull const * _Nonnull arguments, pid_t * _Nullable newProcessPid, @@ -259,7 +270,7 @@ OSStatus AuthorizationEnableSmartCard(AuthorizationRef _Nonnull authRef, Boolean @param stdIn File descriptor which will contain write-end of the stdin pipe of the privileged tool, use -1 if not needed. @param processFinished This block is called when privileged process finishes. */ - OSStatus AuthorizationExecuteWithPrivilegesExternalFormInternal(const AuthorizationExternalForm * _Nonnull extAuthorization, +OSStatus AuthorizationExecuteWithPrivilegesExternalFormInternal(const AuthorizationExternalForm * _Nonnull extAuthorization, const char * _Nonnull pathToTool, const char * _Nullable const * _Nullable arguments, pid_t * _Nullable newProcessPid, @@ -268,6 +279,42 @@ OSStatus AuthorizationEnableSmartCard(AuthorizationRef _Nonnull authRef, Boolean int stdErr, int stdIn, void(^__nullable processFinished)(const int exitStatus)); + +/*! + @function AuthorizationCopyPreloginUserDatabase + Fills output with a CFArrayRef with user database from Prelogin volume + + @param volumeUuid Optional uuid of the volume for which user database will be returned. If not set, users from all volumes are returned. + @param flags Specifies subset of data required in the output + @param output Output array of dictionaries - each dictionary with details for each user +*/ +OSStatus AuthorizationCopyPreloginUserDatabase(const char * _Nullable const volumeUuid, const UInt32 flags, CFArrayRef _Nonnull * _Nonnull output); + +/*! + @function AuthorizationCopyPreloginPreferencesValue + Fills output with a CFTypeRef of a value of the item + + @param volumeUuid Specifies uuid of the volume for which preferences are stored + @param username If NULL, global pref value is queried, otherwise user-specific preferences are queried + @param domain preference domain like "com.apple.tokenlogin" + @param item specifies name of the item to be returned + @param output Output CFTypeRef with the value of the desired preference +*/ +OSStatus AuthorizationCopyPreloginPreferencesValue(const char * _Nonnull const volumeUuid, const char * _Nullable const username, const char * _Nonnull const domain, const char * _Nullable const item, CFTypeRef _Nonnull * _Nonnull output); + +/*! + @function AuthorizationHandlePreloginOverride + Handles FVUnlock Smartcard Enforcement + + @param volumeUuid Specifies uuid of the volume for which the operation will be executed + @param operation Specifies required operation: + kAuthorizationOverrideOperationSet - temporarily disable SC enforcement + kAuthorizationOverrideOperationReset - turn off temporary SC enforcement + kAuthorizationOverrideOperationQuery - query current status + @param result If operation was to query current status, true will be set if SC enforcement is temporarily disabled or false if not +*/ +OSStatus AuthorizationHandlePreloginOverride(const char * _Nonnull const volumeUuid, const char operation, Boolean * _Nullable result); + #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h b/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h index 8800d326..2bae9f2b 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h @@ -265,6 +265,8 @@ #define AGENT_HINT_SHOW_RESET "show-reset" #define AGENT_HINT_PASSWORD_ONLY "password-only" #define AGENT_HINT_SHEET_CONTEXT "sheet-context" +#define AGENT_HINT_LACONTEXT "lacontext" +#define AGENT_HINT_REQUIRED_USER "required-user" // Public Key Hash from certificate used for login #define AGENT_HINT_TOKEN_HASH "token-hash" @@ -298,6 +300,9 @@ #define AGENT_HINT_IGNORE_SESSION "ignore-session-state" #define AGENT_HINT_NO_UI_EXPECTED "no-ui-expected" +/* LocalAuthentication specific */ +#define AGENT_HINT_EXT_PASSWORD "la-ext-passwd" + /* Keychain synchronization */ // iDisk keychain blob metainfo dictionary; follows "defaults" naming #define AGENT_HINT_KCSYNC_DICT "com.apple.keychainsync.dictionary" @@ -359,4 +364,32 @@ /* Sheet window ID */ #define kAuthorizationEnvironmentWindowId "cgwindowid" +/* FVUnlock authenticate approval and admin status */ +#define kAuthorizationFVAdmin "fvadmin" + +/* Prelogin user database defines */ +#define PLUDB_USERNAME "username" +#define PLUDB_LUSERNAME "lusername" +#define PLUDB_KEK "kek" +#define PLUDB_VEK "vek" +#define PLUDB_GUID "guid" +#define PLUDB_ADMIN "admin" +#define PLUDB_SCPAIR "scpairing" +#define PLUDB_IMAGE "image" +#define PLUDB_PWDHINT "pwdhint" +#define PLUDB_SCUNLOCK_DATA "scunl" +#define PLUDB_SCENF "scen" +#define PLUDB_SCUAC "scuac" +#define PLUDB_DNODE "dnode" +#define PLUDB_OWNER "owner" + +/* FVUnlock related defines */ +#define AGENT_FVUNLOCK_USER "fvusername" +#define AGENT_FVUNLOCK_PASSWORD "fvpassword" + +/* PRL related defines */ +#define AGENT_CONTEXT_AKS_MAX_ATTEMPTS "aks-max-attempts" +#define AGENT_CONTEXT_AKS_FAILURES "aks-fail-count" +#define AGENT_CONTEXT_AKS_BACKOFF "aks-backoff" + #endif /* !_SECURITY_AUTHORIZATIONTAGSPRIV_H_ */ diff --git a/OSX/libsecurity_authorization/lib/trampolineClient.cpp b/OSX/libsecurity_authorization/lib/trampolineClient.cpp index b7c5ee85..943a8bad 100644 --- a/OSX/libsecurity_authorization/lib/trampolineClient.cpp +++ b/OSX/libsecurity_authorization/lib/trampolineClient.cpp @@ -25,7 +25,6 @@ // // trampolineClient - Authorization trampoline client-side implementation // -#include #include #include #include @@ -106,13 +105,6 @@ FILE **communicationsPipe) if (extForm == NULL) return errAuthorizationInvalidPointer; - // report the caller to the authorities - aslmsg m = asl_new(ASL_TYPE_MSG); - asl_set(m, "com.apple.message.domain", "com.apple.libsecurity_authorization.AuthorizationExecuteWithPrivileges"); - asl_set(m, "com.apple.message.signature", getprogname()); - asl_log(NULL, m, ASL_LEVEL_NOTICE, "AuthorizationExecuteWithPrivileges!"); - asl_free(m); - // flags are currently reserved if (flags != 0) return errAuthorizationInvalidFlags; diff --git a/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp b/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp index 1fd0e6e8..bf2fccfa 100644 --- a/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp +++ b/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp @@ -38,7 +38,7 @@ using namespace CssmClient; // Exception model // const char * -Error::what () const throw() +Error::what () const _NOEXCEPT { return "CSSM client library error"; } diff --git a/OSX/libsecurity_cdsa_client/lib/cssmclient.h b/OSX/libsecurity_cdsa_client/lib/cssmclient.h index a7bc57ea..34fa6643 100644 --- a/OSX/libsecurity_cdsa_client/lib/cssmclient.h +++ b/OSX/libsecurity_cdsa_client/lib/cssmclient.h @@ -66,7 +66,7 @@ private: class Error : public CssmError { public: Error(CSSM_RETURN err) : CssmError(err, false) { } - virtual const char *what () const throw(); + virtual const char *what () const _NOEXCEPT; enum { objectBusy = -1, diff --git a/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp index 6caef051..7a8bf719 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp @@ -6,7 +6,8 @@ #include #include #include - +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" ACAbstractPluginSession::~ACAbstractPluginSession() { /* virtual */ } diff --git a/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp index bfb5e7fe..daeade84 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp @@ -6,7 +6,8 @@ #include #include #include - +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" CLAbstractPluginSession::~CLAbstractPluginSession() { /* virtual */ } diff --git a/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp index a138ed2e..980e4cd9 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp @@ -6,7 +6,8 @@ #include #include #include - +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" CSPAbstractPluginSession::~CSPAbstractPluginSession() { /* virtual */ } diff --git a/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp index d29da3d4..a6dc6dcc 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp @@ -6,6 +6,8 @@ #include #include #include +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" DLAbstractPluginSession::~DLAbstractPluginSession() diff --git a/OSX/libsecurity_cdsa_plugin/lib/DLsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/DLsession.cpp index 89a88690..1b9ee4bf 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/DLsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/DLsession.cpp @@ -47,11 +47,11 @@ DLPluginSession::DLPluginSession(CSSM_MODULE_HANDLE theHandle, // // Implement Allocator methods from the PluginSession side // -void *DLPluginSession::malloc(size_t size) throw(std::bad_alloc) +void *DLPluginSession::malloc(size_t size) { return PluginSession::malloc(size); } -void DLPluginSession::free(void *addr) throw() +void DLPluginSession::free(void *addr) _NOEXCEPT { return PluginSession::free(addr); } -void *DLPluginSession::realloc(void *addr, size_t size) throw(std::bad_alloc) +void *DLPluginSession::realloc(void *addr, size_t size) { return PluginSession::realloc(addr, size); } diff --git a/OSX/libsecurity_cdsa_plugin/lib/DLsession.h b/OSX/libsecurity_cdsa_plugin/lib/DLsession.h index 67c35ecb..cbd56135 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/DLsession.h +++ b/OSX/libsecurity_cdsa_plugin/lib/DLsession.h @@ -44,9 +44,9 @@ public: const CSSM_UPCALLS &upcalls, DatabaseManager &databaseManager); - void *malloc(size_t size) throw(std::bad_alloc); - void free(void *addr) throw(); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); + void *malloc(size_t size); + void free(void *addr) _NOEXCEPT; + void *realloc(void *addr, size_t size); protected: CSSM_MODULE_FUNCS_PTR construct(); diff --git a/OSX/libsecurity_cdsa_plugin/lib/Database.cpp b/OSX/libsecurity_cdsa_plugin/lib/Database.cpp index ef7da434..f34f5ba4 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/Database.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/Database.cpp @@ -39,7 +39,7 @@ DatabaseManager::get (const DbName &inDbName) DatabaseMap::iterator anIterator = mDatabaseMap.find (inDbName); if (anIterator == mDatabaseMap.end()) { - auto_ptr aDatabase(make(inDbName)); + unique_ptr aDatabase(make(inDbName)); mDatabaseMap.insert(DatabaseMap::value_type(aDatabase->mDbName, aDatabase.get())); return aDatabase.release(); } @@ -164,7 +164,7 @@ Database::_dbOpen(DatabaseSession &inDatabaseSession, const AccessCredentials *inAccessCred, const void *inOpenParameters) { - auto_ptraDbContext(makeDbContext(inDatabaseSession, + unique_ptraDbContext(makeDbContext(inDatabaseSession, inAccessRequest, inAccessCred, inOpenParameters)); @@ -195,7 +195,7 @@ Database::_dbCreate(DatabaseSession &inDatabaseSession, const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, const void *inOpenParameters) { - auto_ptraDbContext(makeDbContext(inDatabaseSession, + unique_ptraDbContext(makeDbContext(inDatabaseSession, inAccessRequest, (inCredAndAclEntry ? AccessCredentials::optional(inCredAndAclEntry->AccessCred) diff --git a/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp b/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp index 15a6f695..723b1e2f 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp @@ -192,7 +192,7 @@ DatabaseSession::DbClose(CSSM_DB_HANDLE inDbHandle) DbContextMap::iterator it = mDbContextMap.find(inDbHandle); if (it == mDbContextMap.end()) CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE); - auto_ptr aDbContext(it->second); + unique_ptr aDbContext(it->second); mDbContextMap.erase(it); mDatabaseManager.dbClose(*aDbContext); } diff --git a/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp index acfb0493..1396717f 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp @@ -6,7 +6,8 @@ #include #include #include - +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" TPAbstractPluginSession::~TPAbstractPluginSession() { /* virtual */ } diff --git a/OSX/libsecurity_cdsa_plugin/lib/csputilities.cpp b/OSX/libsecurity_cdsa_plugin/lib/csputilities.cpp index e0d78ff1..55a43002 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/csputilities.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/csputilities.cpp @@ -33,9 +33,10 @@ using LowLevelMemoryUtilities::increment; CSPFullPluginSession::Writer::Writer(CssmData *v, uint32 n, CssmData *rem) : vec(v), firstVec(v), lastVec(v + n - 1), remData(rem) { - if (vec == NULL || n == 0) + if (vec == NULL || n == 0) { CssmError::throwMe(CSSMERR_CSP_INVALID_OUTPUT_VECTOR); // CDSA p.253, amended - useData(vec); + } + useData(vec); written = 0; } diff --git a/OSX/libsecurity_cdsa_plugin/lib/cssmplugin.cpp b/OSX/libsecurity_cdsa_plugin/lib/cssmplugin.cpp index c8680c4b..c1c7e7c6 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/cssmplugin.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/cssmplugin.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "LegacyAPICounts.h" ModuleNexus CssmPlugin::sessionMap; @@ -54,10 +55,13 @@ void CssmPlugin::moduleLoad(const Guid &cssmGuid, const Guid &moduleGuid, const ModuleCallback &newCallback) { - if (mLoaded) + static dispatch_once_t onceToken; + countLegacyAPI(&onceToken, "CssmPlugin::moduleLoad"); + if (mLoaded) { CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); - - mMyGuid = moduleGuid; + } + + mMyGuid = moduleGuid; // let the implementation know that we're loading this->load(); @@ -78,12 +82,16 @@ void CssmPlugin::moduleUnload(const Guid &cssmGuid, const Guid &moduleGuid, const ModuleCallback &oldCallback) { + // These are called from the public pluginspi.h + static dispatch_once_t onceToken; + countLegacyAPI(&onceToken, "CssmPlugin::moduleUnload"); // check the callback vector - if (!mLoaded || oldCallback != mCallback) + if (!mLoaded || oldCallback != mCallback) { CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + } // tell our subclass that we're closing down - this->unload(); + this->unload(); // commit closure mLoaded = false; @@ -108,12 +116,14 @@ void CssmPlugin::moduleAttach(CSSM_MODULE_HANDLE theHandle, const CSSM_UPCALLS &upcalls, CSSM_MODULE_FUNCS_PTR &funcTbl) { + static dispatch_once_t onceToken; + countLegacyAPI(&onceToken, "CssmPlugin::moduleAttach"); // basic (in)sanity checks if (moduleGuid != mMyGuid) CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); // make the new session object, hanging in thin air - auto_ptr session(this->makeSession(theHandle, + unique_ptr session(this->makeSession(theHandle, version, subserviceId, subserviceType, attachFlags, @@ -140,6 +150,8 @@ void CssmPlugin::moduleAttach(CSSM_MODULE_HANDLE theHandle, // void CssmPlugin::moduleDetach(CSSM_MODULE_HANDLE handle) { + static dispatch_once_t onceToken; + countLegacyAPI(&onceToken, "CssmPlugin::moduleDetach"); // locate the plugin and hold the sessionMapLock PluginSession *session; { diff --git a/OSX/libsecurity_cdsa_plugin/lib/pluginsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/pluginsession.cpp index c73328ce..8de73c8d 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/pluginsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/pluginsession.cpp @@ -61,18 +61,20 @@ void PluginSession::detach() // // Allocation management // -void *PluginSession::malloc(size_t size) throw(std::bad_alloc) +void *PluginSession::malloc(size_t size) { - if (void *addr = upcalls.malloc_func(handle(), size)) + if (void *addr = upcalls.malloc_func(handle(), size)) { return addr; - throw std::bad_alloc(); + } + throw std::bad_alloc(); } -void *PluginSession::realloc(void *oldAddr, size_t size) throw(std::bad_alloc) +void *PluginSession::realloc(void *oldAddr, size_t size) { - if (void *addr = upcalls.realloc_func(handle(), oldAddr, size)) + if (void *addr = upcalls.realloc_func(handle(), oldAddr, size)) { return addr; - throw std::bad_alloc(); + } + throw std::bad_alloc(); } diff --git a/OSX/libsecurity_cdsa_plugin/lib/pluginsession.h b/OSX/libsecurity_cdsa_plugin/lib/pluginsession.h index d58ba5ea..fe8c6461 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/pluginsession.h +++ b/OSX/libsecurity_cdsa_plugin/lib/pluginsession.h @@ -68,9 +68,9 @@ protected: public: // implement Allocator - void *malloc(size_t size) throw(std::bad_alloc); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); - void free(void *addr) throw() { upcalls.free_func(handle(), addr); } + void *malloc(size_t size); + void *realloc(void *addr, size_t size); + void free(void *addr) _NOEXCEPT { upcalls.free_func(handle(), addr); } // about ourselves const CSSM_VERSION &version() const { return mVersion; } diff --git a/OSX/libsecurity_cdsa_plugin/lib/pluginspi.h b/OSX/libsecurity_cdsa_plugin/lib/pluginspi.h index f5d8d491..3bc97d29 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/pluginspi.h +++ b/OSX/libsecurity_cdsa_plugin/lib/pluginspi.h @@ -47,7 +47,7 @@ SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleLoad) (const CSSM_GUID *CssmGuid, CSSM_SPI_ModuleEventHandler CssmNotifyCallback, void *CssmNotifyCallbackCtx) { - BEGIN_API + BEGIN_API_NO_METRICS plugin().moduleLoad(Guid::required(CssmGuid), Guid::required(ModuleGuid), ModuleCallback(CssmNotifyCallback, CssmNotifyCallbackCtx)); @@ -64,7 +64,7 @@ SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleUnload) (const CSSM_GUID *CssmGuid, CSSM_SPI_ModuleEventHandler CssmNotifyCallback, void *CssmNotifyCallbackCtx) { - BEGIN_API + BEGIN_API_NO_METRICS plugin().moduleUnload(Guid::required(CssmGuid), Guid::required(ModuleGuid), ModuleCallback(CssmNotifyCallback, CssmNotifyCallbackCtx)); @@ -97,7 +97,7 @@ SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleAttach) (const CSSM_GUID *ModuleGui const CSSM_UPCALLS *Upcalls, CSSM_MODULE_FUNCS_PTR *FuncTbl) { - BEGIN_API + BEGIN_API_NO_METRICS plugin().moduleAttach(ModuleHandle, Guid::required(CssmGuid), Guid::required(ModuleGuid), @@ -117,7 +117,7 @@ SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleDetach) (CSSM_MODULE_HANDLE ModuleH SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleDetach) (CSSM_MODULE_HANDLE ModuleHandle) { - BEGIN_API + BEGIN_API_NO_METRICS plugin().moduleDetach(ModuleHandle); END_API(CSSM) } diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp index fdc29c9f..dccd5d93 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp @@ -104,9 +104,7 @@ CommentAclSubject *CommentAclSubject::Maker::make(Version, Reader &pub, Reader & // Phew. I'd rather be lucky than good... // // So let's get started: -#ifndef NDEBUG static const size_t minCssmList = 12; // min(sizeof(CSSM_LIST)) of all architectures -#endif pub.get(4); // skip first 4 bytes uint32_t lop; pub(lop); // read L4n-or-(bottom of)P8h uint32_t tol; pub(tol); // read T4h-or-L4n diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp index 7918ff47..d9773dae 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp @@ -89,11 +89,12 @@ ProcessAclSubject *ProcessAclSubject::Maker::make(const TypedList &list) const // validate input if (selector.version != CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION) CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); - if (!selector.uses(CSSM_ACL_MATCH_BITS)) + if (!selector.uses(CSSM_ACL_MATCH_BITS)) { CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } // okay - return new ProcessAclSubject(selector); + return new ProcessAclSubject(selector); } ProcessAclSubject *ProcessAclSubject::Maker::make(Version, Reader &pub, Reader &priv) const diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp index 7cccfa6d..9d45cd8e 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp @@ -112,8 +112,9 @@ ThresholdAclSubject *ThresholdAclSubject::Maker::make(const TypedList &list) con // now compile the subSubjects AclSubjectVector elements(totalSubjects); const ListElement *subSubject = &list[3]; - for (uint32 n = 0; n < totalSubjects; n++, subSubject = subSubject->next()) + for (uint32 n = 0; n < totalSubjects; n++, subSubject = subSubject->next()) { elements[n] = ObjectAcl::make(subSubject->typedList()); + } return new ThresholdAclSubject(totalSubjects, minimumNeeded, elements); } diff --git a/OSX/libsecurity_cdsa_utilities/lib/callback.cpp b/OSX/libsecurity_cdsa_utilities/lib/callback.cpp index 72a16361..e8f0e28d 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/callback.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/callback.cpp @@ -76,47 +76,25 @@ void ModuleCallbackSet::erase(const ModuleCallback &oldCallback) // // Invoke an entire callback set. // THREADS: Caller is ensuring single-thread access on these calls. +// Note that the callbacks are background thread, and so is the ->exit() call // +// NOTE WELL, if this is called, you can't safely call add/remove + void ModuleCallbackSet::operator () (CSSM_MODULE_EVENT event, const Guid &guid, uint32 subId, CSSM_SERVICE_TYPE serviceType) const { if (callbacks.empty()) // nothing to do; quick exit return; - -#if _USE_THREADS == _USE_NO_THREADS || defined(SYNCHRONOUS_CALLBACKS) - // no threading model supported - we HAVE to do this right here - // note that the user better not re-enter CSSM too much, - // or we might deadlock... - for (CallbackMap::const_iterator it = callbacks.begin(); - it != callbacks.end(); it++) { - it->first(event, guid, subId, serviceType); - } -#else // real threads available - // lock down all callback elements - still protected by global lock (via caller) - for (CallbackMap::iterator it = callbacks.begin(); - it != callbacks.end(); it++) + + for (auto it = callbacks.begin(); it != callbacks.end(); it++) { it->second->enter(); - - // get out of this thread - now! - (new Runner(callbacks, event, guid, subId, serviceType))->run(); -#endif -} - -void ModuleCallbackSet::Runner::action() -{ - // - // NOTE WELL: Our callbacks map shares (pointed-to) values with the ModuleCallbackSet - // we were created from. Some of these values may be dangling pointers since they have - // been destroyed by other threads, but only *after* we are done with them, since - // we must call exit() on them before they become eligible for destruction. - // In all cases, it is the responsibility of other threads to destroy those mutexi. - // - // @@@ Could also fan out to multiple callback threads in parallel. - for (CallbackMap::iterator it = callbacks.begin(); - it != callbacks.end(); it++) { - //@@@ safety vs. convenience - recheck - it->first(event, guid, subserviceId, serviceType); - it->second->exit(); } + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + for (auto it = callbacks.begin(); it != callbacks.end(); it++) { + it->first(event, guid, subId, serviceType); + it->second->exit(); + } + }); } diff --git a/OSX/libsecurity_cdsa_utilities/lib/callback.h b/OSX/libsecurity_cdsa_utilities/lib/callback.h index 05695891..49d244dc 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/callback.h +++ b/OSX/libsecurity_cdsa_utilities/lib/callback.h @@ -87,24 +87,6 @@ private: // note mutex *: we don't want to rely on copy-ability of Mutex objects typedef multimap CallbackMap; mutable CallbackMap callbacks; - - struct Runner : public Thread { - Runner(CallbackMap &inCallbacks, - CSSM_MODULE_EVENT inEvent, - const Guid &inGuid, - uint32 inSSId, - CSSM_SERVICE_TYPE inServiceType) - : callbacks(inCallbacks), event(inEvent), guid(inGuid), - subserviceId(inSSId), serviceType(inServiceType) { } - - CallbackMap callbacks; // note that we share the CountingMutex * values! - const CSSM_MODULE_EVENT event; - const Guid guid; - const uint32 subserviceId; - const CSSM_SERVICE_TYPE serviceType; - - void action(); - }; }; } // end namespace Security diff --git a/OSX/libsecurity_cdsa_utilities/lib/context.h b/OSX/libsecurity_cdsa_utilities/lib/context.h index d5e9532d..03db058f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/context.h +++ b/OSX/libsecurity_cdsa_utilities/lib/context.h @@ -187,11 +187,11 @@ public: } public: - void *operator new (size_t size, Allocator &alloc) throw(std::bad_alloc) + void *operator new (size_t size, Allocator &alloc) { return alloc.malloc(size); } - void operator delete (void *addr, size_t, Allocator &alloc) throw() + void operator delete (void *addr, size_t, Allocator &alloc) _NOEXCEPT { return alloc.free(addr); } - static void destroy(Context *context, Allocator &alloc) throw() + static void destroy(Context *context, Allocator &alloc) _NOEXCEPT { alloc.free(context->ContextAttributes); alloc.free(context); } public: diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp index 63d262b2..a7bb291c 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp @@ -40,13 +40,13 @@ namespace Security { // // CssmMemoryFunctionsAllocators // -void *CssmMemoryFunctionsAllocator::malloc(size_t size) throw(std::bad_alloc) +void *CssmMemoryFunctionsAllocator::malloc(size_t size) { return functions.malloc(size); } -void CssmMemoryFunctionsAllocator::free(void *addr) throw() +void CssmMemoryFunctionsAllocator::free(void *addr) _NOEXCEPT { return functions.free(addr); } -void *CssmMemoryFunctionsAllocator::realloc(void *addr, size_t size) throw(std::bad_alloc) +void *CssmMemoryFunctionsAllocator::realloc(void *addr, size_t size) { return functions.realloc(addr, size); } @@ -62,16 +62,16 @@ CssmAllocatorMemoryFunctions::CssmAllocatorMemoryFunctions(Allocator &alloc) calloc_func = relayCalloc; } -void *CssmAllocatorMemoryFunctions::relayMalloc(size_t size, void *ref) throw(std::bad_alloc) +void *CssmAllocatorMemoryFunctions::relayMalloc(size_t size, void *ref) { return allocator(ref).malloc(size); } -void CssmAllocatorMemoryFunctions::relayFree(void *mem, void *ref) throw() +void CssmAllocatorMemoryFunctions::relayFree(void *mem, void *ref) _NOEXCEPT { allocator(ref).free(mem); } -void *CssmAllocatorMemoryFunctions::relayRealloc(void *mem, size_t size, void *ref) throw(std::bad_alloc) +void *CssmAllocatorMemoryFunctions::relayRealloc(void *mem, size_t size, void *ref) { return allocator(ref).realloc(mem, size); } -void *CssmAllocatorMemoryFunctions::relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc) +void *CssmAllocatorMemoryFunctions::relayCalloc(uint32 count, size_t size, void *ref) { // Allocator doesn't have a calloc() method size_t alloc_size = 0; diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.h b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.h index 01a14e37..6c4365ea 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.h @@ -46,30 +46,30 @@ public: { *(CSSM_MEMORY_FUNCS *)this = funcs; } CssmMemoryFunctions() { } - void *malloc(size_t size) const throw(std::bad_alloc); - void free(void *mem) const throw() { free_func(mem, AllocRef); } - void *realloc(void *mem, size_t size) const throw(std::bad_alloc); - void *calloc(uint32 count, size_t size) const throw(std::bad_alloc); + void *malloc(size_t size) const; + void free(void *mem) const _NOEXCEPT { free_func(mem, AllocRef); } + void *realloc(void *mem, size_t size) const; + void *calloc(uint32 count, size_t size) const; - bool operator == (const CSSM_MEMORY_FUNCS &other) const throw() + bool operator == (const CSSM_MEMORY_FUNCS &other) const _NOEXCEPT { return !memcmp(this, &other, sizeof(*this)); } }; -inline void *CssmMemoryFunctions::malloc(size_t size) const throw(std::bad_alloc) +inline void *CssmMemoryFunctions::malloc(size_t size) const { if (void *addr = malloc_func(size, AllocRef)) return addr; throw std::bad_alloc(); } -inline void *CssmMemoryFunctions::calloc(uint32 count, size_t size) const throw(std::bad_alloc) +inline void *CssmMemoryFunctions::calloc(uint32 count, size_t size) const { if (void *addr = calloc_func(count, size, AllocRef)) return addr; throw std::bad_alloc(); } -inline void *CssmMemoryFunctions::realloc(void *mem, size_t size) const throw(std::bad_alloc) +inline void *CssmMemoryFunctions::realloc(void *mem, size_t size) const { if (void *addr = realloc_func(mem, size, AllocRef)) return addr; @@ -84,11 +84,11 @@ class CssmMemoryFunctionsAllocator : public Allocator { public: CssmMemoryFunctionsAllocator(const CssmMemoryFunctions &memFuncs) : functions(memFuncs) { } - void *malloc(size_t size) throw(std::bad_alloc); - void free(void *addr) throw(); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); + void *malloc(size_t size); + void free(void *addr) _NOEXCEPT; + void *realloc(void *addr, size_t size); - operator const CssmMemoryFunctions & () const throw() { return functions; } + operator const CssmMemoryFunctions & () const _NOEXCEPT { return functions; } private: const CssmMemoryFunctions functions; @@ -106,12 +106,12 @@ public: CssmAllocatorMemoryFunctions() { /*IFDEBUG(*/ AllocRef = NULL /*)*/ ; } // later assignment req'd private: - static void *relayMalloc(size_t size, void *ref) throw(std::bad_alloc); - static void relayFree(void *mem, void *ref) throw(); - static void *relayRealloc(void *mem, size_t size, void *ref) throw(std::bad_alloc); - static void *relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc); + static void *relayMalloc(size_t size, void *ref); + static void relayFree(void *mem, void *ref) _NOEXCEPT; + static void *relayRealloc(void *mem, size_t size, void *ref); + static void *relayCalloc(uint32 count, size_t size, void *ref); - static Allocator &allocator(void *ref) throw() + static Allocator &allocator(void *ref) _NOEXCEPT { return *reinterpret_cast(ref); } }; diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmbridge.h b/OSX/libsecurity_cdsa_utilities/lib/cssmbridge.h index f2f92dbd..73e0d4b2 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmbridge.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmbridge.h @@ -32,10 +32,8 @@ #include #include - namespace Security { - // // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions. // Usage: @@ -46,7 +44,12 @@ namespace Security { // END_API0 // completely ignores exceptions; falls through in all cases // END_API1(bad) // return (bad) on exception; fall through on success // -#define BEGIN_API try { +#define BEGIN_API try { \ + static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); + +#define BEGIN_API_NO_METRICS try { + #define END_API(base) } \ catch (const CommonError &err) { return CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \ catch (const std::bad_alloc &) { return CssmError::cssmError(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmdata.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmdata.cpp index 5dec094e..28165909 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmdata.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmdata.cpp @@ -240,7 +240,7 @@ CssmDateData::CssmDateData(const CSSM_DATE &date) } -CssmData& CssmOwnedData::get() const throw() +CssmData& CssmOwnedData::get() const _NOEXCEPT { return referent; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmdata.h b/OSX/libsecurity_cdsa_utilities/lib/cssmdata.h index eee84a0a..c69172d7 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmdata.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmdata.h @@ -243,7 +243,7 @@ public: void *data() const { return get().data(); } size_t length() const { return get().length(); } - virtual CssmData &get() const throw() = 0; // get shared copy, no ownership change + virtual CssmData &get() const _NOEXCEPT = 0; // get shared copy, no ownership change virtual CssmData release() = 0; // give up copy, ownership is transferred virtual void reset() = 0; // give up copy, data is discarded }; @@ -372,7 +372,7 @@ public: void operator = (CssmOwnedData &source) { set(source); } void operator = (const CSSM_DATA &source) { copy(source); } - CssmData &get() const throw(); + CssmData &get() const _NOEXCEPT; public: void fromOid(const char *oid); // fill from text OID form (1.2.3...) diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h b/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h index 186e7669..be227a3b 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h @@ -199,8 +199,13 @@ public: CssmDlDbHandle *handles() const { return CssmDlDbHandle::overlay(DLDBHandle); } CssmDlDbHandle * &handles() { return CssmDlDbHandle::overlayVar(DLDBHandle); } - CssmDlDbHandle &operator [] (uint32 ix) const - { assert(ix < count()); return CssmDlDbHandle::overlay(DLDBHandle[ix]); } + CssmDlDbHandle &operator [] (uint32 ix) const { + if (ix >= count()) { + secemergency("CssmDlDbList: attempt to index beyond bounds"); + abort(); + } + return CssmDlDbHandle::overlay(DLDBHandle[ix]); + } void setDlDbList(uint32 n, CSSM_DL_DB_HANDLE *list) { count() = n; handles() = CssmDlDbHandle::overlay(list); } @@ -215,9 +220,7 @@ class CssmDLPolyData public: CssmDLPolyData(const CSSM_DATA &data, CSSM_DB_ATTRIBUTE_FORMAT format) : mData(CssmData::overlay(data)) -#ifndef NDEBUG , mFormat(format) -#endif {} // @@@ Don't use assert, but throw an exception. @@ -264,9 +267,7 @@ public: private: const CssmData &mData; -#ifndef NDEBUG CSSM_DB_ATTRIBUTE_FORMAT mFormat; -#endif }; @@ -345,8 +346,13 @@ public: { return CssmDbAttributeInfo::overlayVar(AttributeInfo); } CssmDbAttributeInfo *attributes() const { return CssmDbAttributeInfo::overlay(AttributeInfo); } - CssmDbAttributeInfo &at(uint32 ix) const - { assert(ix < size()); return attributes()[ix]; } + CssmDbAttributeInfo &at(uint32 ix) const { + if (ix >= size()) { + secemergency("CssmDbRecordAttributeInfo: attempt to index beyond bounds"); + abort(); + } + return attributes()[ix]; + } CssmDbAttributeInfo &operator [] (uint32 ix) const { return at(ix); } }; @@ -481,8 +487,13 @@ public: { return CssmDbAttributeData::overlay(AttributeData); } // Attributes by position - CssmDbAttributeData &at(unsigned int ix) const - { assert(ix < size()); return attributes()[ix]; } + CssmDbAttributeData &at(unsigned int ix) const { + if (ix >= size()) { + secemergency("CssmDbRecordAttributeData: attempt to index beyond bounds"); + abort(); + } + return attributes()[ix]; + } CssmDbAttributeData &operator [] (unsigned int ix) const { return at(ix); } @@ -596,8 +607,13 @@ public: CssmSelectionPredicate *predicates() const { return CssmSelectionPredicate::overlay(SelectionPredicate); } - CssmSelectionPredicate &at(uint32 ix) const - { assert(ix < size()); return predicates()[ix]; } + CssmSelectionPredicate &at(uint32 ix) const { + if (ix >= size()) { + secemergency("CssmDbRecordAttributeData: attempt to index beyond bounds"); + abort(); + } + return predicates()[ix]; + } CssmSelectionPredicate &operator[] (uint32 ix) const { return at(ix); } @@ -666,6 +682,8 @@ public: const CSSM_NET_ADDRESS *location = NULL) : mImpl(new Impl(CssmSubserviceUid(guid, NULL, ssid, sstype), name, location)) { } + DLDbIdentifier(const DLDbIdentifier& i) : mImpl(i.mImpl) {} + // Conversion Operators bool operator !() const { return !mImpl; } operator bool() const { return mImpl; } @@ -729,7 +747,10 @@ struct DLDbFlatIdentifier { address(const_cast(ident.dbLocation())) { } - operator DLDbIdentifier () { return DLDbIdentifier(*uid, name, address); } + operator DLDbIdentifier () { + DLDbIdentifier db(*uid, name, address); + return db; + } }; template diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp index 98ec8dd8..12e3bc74 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp @@ -53,7 +53,7 @@ CssmError::CssmError(CSSM_RETURN err, bool suppresslogging) : error(err) } -const char *CssmError::what() const throw () +const char *CssmError::what() const _NOEXCEPT { return whatBuffer; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.h b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.h index 7da29adb..6da470fa 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.h @@ -46,7 +46,7 @@ public: const CSSM_RETURN error; virtual OSStatus osStatus() const; virtual int unixError() const; - virtual const char *what () const throw (); + virtual const char *what () const _NOEXCEPT; static CSSM_RETURN merge(CSSM_RETURN error, CSSM_RETURN base); diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.cpp index 911cf2c6..055bf7da 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.cpp @@ -152,6 +152,14 @@ ListElement &CssmList::operator [] (unsigned ix) const throw 999; //@@@ } +CssmList &CssmList::operator =(const CssmList& other) +{ + ListType = other.ListType; + Head = other.Head; + Tail = other.Tail; + return *this; +} + unsigned int CssmList::length() const { unsigned int len = 0; diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h index 40f77b76..1e65adbd 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h @@ -141,6 +141,8 @@ public: // logically remove the first element (skip it) void snip(); + + CssmList &operator =(const CssmList& other); public: void clear(Allocator &alloc); // free my contents diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmpods.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmpods.cpp index 8915894d..2a067c44 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmpods.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmpods.cpp @@ -38,9 +38,10 @@ char *Guid::toString(char buffer[stringRepLength+1]) const { sprintf(buffer, "{%8.8x-%4.4hx-%4.4hx-", int(n2h(Data1)), n2h(Data2), n2h(Data3)); - for (int n = 0; n < 2; n++) + for (int n = 0; n < 2; n++) { sprintf(buffer + 20 + 2*n, "%2.2hhx", Data4[n]); - buffer[24] = '-'; + } + buffer[24] = '-'; for (int n = 2; n < 8; n++) sprintf(buffer + 21 + 2*n, "%2.2hhx", Data4[n]); buffer[37] = '}'; @@ -86,8 +87,9 @@ void Guid::parseGuid(const char *string) int d1; uint16 d2, d3; - if (sscanf(string, "{%8x-%4hx-%4hx-", &d1, &d2, &d3) != 3) + if (sscanf(string, "{%8x-%4hx-%4hx-", &d1, &d2, &d3) != 3) { CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); + } Data1 = h2n(uint32(d1)); Data2 = h2n(d2); Data3 = h2n(d3); @@ -131,7 +133,7 @@ CssmSubserviceUid::CssmSubserviceUid(const CSSM_GUID &guid, } -bool CssmSubserviceUid::operator == (const CSSM_SUBSERVICE_UID &otherUid) const +bool CssmSubserviceUid::operator == (const CssmSubserviceUid &otherUid) const { // make sure we don't crash if we get bad data #pragma clang diagnostic push @@ -145,7 +147,7 @@ bool CssmSubserviceUid::operator == (const CSSM_SUBSERVICE_UID &otherUid) const && guid() == other.guid(); } -bool CssmSubserviceUid::operator < (const CSSM_SUBSERVICE_UID &otherUid) const +bool CssmSubserviceUid::operator < (const CssmSubserviceUid &otherUid) const { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-undefined-compare" @@ -173,7 +175,7 @@ CryptoDataClass::~CryptoDataClass() CSSM_RETURN CryptoDataClass::callbackShim(CSSM_DATA *output, void *ctx) { - BEGIN_API + BEGIN_API_NO_METRICS *output = reinterpret_cast(ctx)->yield(); END_API(CSSM) } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmpods.h b/OSX/libsecurity_cdsa_utilities/lib/cssmpods.h index c1b1c542..55d7e2ed 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmpods.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmpods.h @@ -43,17 +43,18 @@ class Guid : public PodWrapper { public: Guid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; } Guid(const CSSM_GUID &rGuid) { memcpy(this, &rGuid, sizeof(*this)); } + Guid(const Guid &rGuid) { memcpy(this, &rGuid, sizeof(*this)); } Guid(const char *string); Guid(const std::string &s); - Guid &operator = (const CSSM_GUID &rGuid) + Guid &operator = (const Guid &rGuid) { memcpy(this, &rGuid, sizeof(CSSM_GUID)); return *this; } - bool operator == (const CSSM_GUID &other) const + bool operator == (const Guid &other) const { return (this == &other) || !memcmp(this, &other, sizeof(CSSM_GUID)); } - bool operator != (const CSSM_GUID &other) const + bool operator != (const Guid &other) const { return (this != &other) && memcmp(this, &other, sizeof(CSSM_GUID)); } - bool operator < (const CSSM_GUID &other) const + bool operator < (const Guid &other) const { return memcmp(this, &other, sizeof(CSSM_GUID)) < 0; } size_t hash() const { //@@@ revisit this hash return Data1 + (Data2 << 3) + (Data3 << 11) + (Data4[3]) + (Data4[6] << 22); @@ -84,12 +85,12 @@ public: CssmSubserviceUid() { clearPod(); } CssmSubserviceUid(const CSSM_SUBSERVICE_UID &rSSuid) { memcpy(this, &rSSuid, sizeof(*this)); } - CssmSubserviceUid &operator = (const CSSM_SUBSERVICE_UID &rSSuid) + CssmSubserviceUid &operator = (const CssmSubserviceUid &rSSuid) { memcpy(this, &rSSuid, sizeof(CSSM_SUBSERVICE_UID)); return *this; } - bool operator == (const CSSM_SUBSERVICE_UID &other) const; - bool operator != (const CSSM_SUBSERVICE_UID &other) const { return !(*this == other); } - bool operator < (const CSSM_SUBSERVICE_UID &other) const; + bool operator == (const CssmSubserviceUid &other) const; + bool operator != (const CssmSubserviceUid &other) const { return !(*this == other); } + bool operator < (const CssmSubserviceUid &other) const; CssmSubserviceUid(const CSSM_GUID &guid, const CSSM_VERSION *version = NULL, uint32 subserviceId = 0, diff --git a/OSX/libsecurity_cdsa_utilities/lib/handletemplates.h b/OSX/libsecurity_cdsa_utilities/lib/handletemplates.h index f9a6d504..52ddac8f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/handletemplates.h +++ b/OSX/libsecurity_cdsa_utilities/lib/handletemplates.h @@ -199,7 +199,7 @@ inline Subclass &MappingHandle<_Handle>::findAndLock(_Handle handle, CssmError::throwMe(error); // bad type if (it->second->tryLock()) // try to lock it return *sub; // okay, go - Thread::yield(); // object lock failed, backoff and retry + Thread::threadYield(); // object lock failed, backoff and retry } } @@ -222,7 +222,7 @@ inline Subclass &MappingHandle<_Handle>::findAndKill(_Handle handle, state().erase(it); // kill the handle return *sub; // okay, go } - Thread::yield(); // object lock failed, backoff and retry + Thread::threadYield(); // object lock failed, backoff and retry } } @@ -252,7 +252,7 @@ inline RefPointer MappingHandle<_Handle>::findRefAndLock(_Handle handl CssmError::throwMe(error); // bad type if (it->second->tryLock()) // try to lock it return sub; // okay, go - Thread::yield(); // object lock failed, backoff and retry + Thread::threadYield(); // object lock failed, backoff and retry } } @@ -271,7 +271,7 @@ inline RefPointer MappingHandle<_Handle>::findRefAndKill(_Handle handl state().erase(it); // kill the handle return sub; // okay, go } - Thread::yield(); // object lock failed, backoff and retry + Thread::threadYield(); // object lock failed, backoff and retry } } diff --git a/OSX/libsecurity_cms/lib/CMSUtils.h b/OSX/libsecurity_cms/lib/CMSUtils.h index 6211a11d..d715d72c 100644 --- a/OSX/libsecurity_cms/lib/CMSUtils.h +++ b/OSX/libsecurity_cms/lib/CMSUtils.h @@ -31,7 +31,6 @@ #include #include /* cssmPerror() */ #include -#include #ifdef __cplusplus extern "C" { @@ -65,13 +64,14 @@ OSStatus cmsRtnToOSStatus( #define CFRELEASE(cfr) if(cfr != NULL) { CFRelease(cfr); } +#include +#define ASSERT(s) assert(s) + #define CMS_DEBUG 0 #if CMS_DEBUG -#define ASSERT(s) assert(s) #define CSSM_PERROR(s, r) cssmPerror(s, r) #define dprintf(args...) printf(args) #else -#define ASSERT(s) #define CSSM_PERROR(s, r) #define dprintf(args...) #endif diff --git a/OSX/libsecurity_codesigning/CodeSigningHelper/main.c b/OSX/libsecurity_codesigning/CodeSigningHelper/main.c index f81de057..7a493755 100644 --- a/OSX/libsecurity_codesigning/CodeSigningHelper/main.c +++ b/OSX/libsecurity_codesigning/CodeSigningHelper/main.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp b/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp index a7e46bcd..10465dff 100644 --- a/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp +++ b/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp @@ -34,8 +34,6 @@ static void request(xpc_connection_t peer, xpc_object_t event) { - OSStatus rc; - pid_t pid = (pid_t)xpc_dictionary_get_int64(event, "pid"); if (pid <= 0) return; @@ -61,11 +59,11 @@ request(xpc_connection_t peer, xpc_object_t event) auditData); } CFRef code; - if ((rc = SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code.aref())) == noErr) { + if (SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code.aref()) == noErr) { // path to base of client code CFRef codePath; - if ((rc = SecCodeCopyPath(code, kSecCSDefaultFlags, &codePath.aref())) == noErr) { + if (SecCodeCopyPath(code, kSecCSDefaultFlags, &codePath.aref()) == noErr) { CFRef data = CFURLCreateData(NULL, codePath, kCFStringEncodingUTF8, true); xpc_dictionary_set_data(reply, "bundleURL", CFDataGetBytePtr(data), CFDataGetLength(data)); } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp index c91e927d..47c974a8 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp @@ -27,7 +27,7 @@ public: : text(s) { } - virtual ~ANTLRException() throw() + virtual ~ANTLRException() _NOEXCEPT { } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp index ee7ad437..96e3b416 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp @@ -19,7 +19,7 @@ class ANTLR_API CharStreamException : public ANTLRException { public: CharStreamException(const ANTLR_USE_NAMESPACE(std)string& s) : ANTLRException(s) {} - ~CharStreamException() throw() {} + ~CharStreamException() _NOEXCEPT {} }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp index ebbb0fd6..f4bdcd22 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp @@ -21,7 +21,7 @@ public: CharStreamIOException(ANTLR_USE_NAMESPACE(std)exception& e) : CharStreamException(e.what()), io(e) {} - ~CharStreamIOException() throw() {} + ~CharStreamIOException() _NOEXCEPT {} }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/IOException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/IOException.hpp index ed87f8ac..41840d47 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/IOException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/IOException.hpp @@ -33,7 +33,7 @@ public: : ANTLRException(mesg) { } - virtual ~IOException() throw() + virtual ~IOException() _NOEXCEPT { } }; diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp index 45054129..ce10e42d 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp @@ -87,7 +87,7 @@ public: CharScanner* scanner_ ); - ~MismatchedCharException() throw() {} + ~MismatchedCharException() _NOEXCEPT {} /** * Returns a clean error message (no line number/column information) diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp index 4631f50b..6099efc7 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp @@ -81,7 +81,7 @@ public: bool matchNot, const ANTLR_USE_NAMESPACE(std)string& fileName_ ); - ~MismatchedTokenException() throw() {} + ~MismatchedTokenException() _NOEXCEPT {} /** * Returns a clean error message (no line number/column information) diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp index e3677ded..51f30610 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp @@ -25,7 +25,7 @@ public: NoViableAltException(RefAST t); NoViableAltException(RefToken t,const ANTLR_USE_NAMESPACE(std)string& fileName_); - ~NoViableAltException() throw() {} + ~NoViableAltException() _NOEXCEPT {} /** * Returns a clean error message (no line number/column information) diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp index d61c18b0..54c1344c 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp @@ -24,7 +24,7 @@ public: NoViableAltForCharException(int c, const ANTLR_USE_NAMESPACE(std)string& fileName_, int line_, int column_); - virtual ~NoViableAltForCharException() throw() + virtual ~NoViableAltForCharException() _NOEXCEPT { } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp index c131831b..410adb3d 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp @@ -24,26 +24,26 @@ namespace antlr const ANTLR_USE_NAMESPACE(std)string& fileName, int line, int column ); - virtual ~RecognitionException() throw() + virtual ~RecognitionException() _NOEXCEPT { } /// Return file where mishap occurred. - virtual ANTLR_USE_NAMESPACE(std)string getFilename() const throw() + virtual ANTLR_USE_NAMESPACE(std)string getFilename() const _NOEXCEPT { return fileName; } /** * @return the line number that this exception happened on. */ - virtual int getLine() const throw() + virtual int getLine() const _NOEXCEPT { return line; } /** * @return the column number that this exception happened on. */ - virtual int getColumn() const throw() + virtual int getColumn() const _NOEXCEPT { return column; } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp index c8e9ea39..71aab7bb 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp @@ -28,7 +28,7 @@ public: { } - ~SemanticException() throw() + ~SemanticException() _NOEXCEPT { } }; diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp index a3f4d548..7763c072 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp @@ -29,7 +29,7 @@ public: : ANTLRException(s) { } - virtual ~TokenStreamException() throw() + virtual ~TokenStreamException() _NOEXCEPT { } }; diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp index 29f508bf..9ad18556 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp @@ -26,7 +26,7 @@ public: , io(e) { } - ~TokenStreamIOException() throw() + ~TokenStreamIOException() _NOEXCEPT { } private: diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp index 39685789..9c8ec589 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp @@ -26,7 +26,7 @@ public: , recog(re) { } - virtual ~TokenStreamRecognitionException() throw() + virtual ~TokenStreamRecognitionException() _NOEXCEPT { } virtual ANTLR_USE_NAMESPACE(std)string toString() const @@ -34,15 +34,15 @@ public: return recog.getFileLineColumnString()+getMessage(); } - virtual ANTLR_USE_NAMESPACE(std)string getFilename() const throw() + virtual ANTLR_USE_NAMESPACE(std)string getFilename() const _NOEXCEPT { return recog.getFilename(); } - virtual int getLine() const throw() + virtual int getLine() const _NOEXCEPT { return recog.getLine(); } - virtual int getColumn() const throw() + virtual int getColumn() const _NOEXCEPT { return recog.getColumn(); } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp index 7d17b3cd..a50cfb07 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp @@ -18,7 +18,7 @@ namespace antlr { class TokenStreamRetryException : public TokenStreamException { public: TokenStreamRetryException() {} - ~TokenStreamRetryException() throw() {} + ~TokenStreamRetryException() _NOEXCEPT {} }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE diff --git a/OSX/libsecurity_codesigning/antlr2/scripts/make_change_log.tcl b/OSX/libsecurity_codesigning/antlr2/scripts/make_change_log.tcl old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/antlr2/src/Makefile.in b/OSX/libsecurity_codesigning/antlr2/src/Makefile.in old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp b/OSX/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp index 4279355e..a44f3ef0 100644 --- a/OSX/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp +++ b/OSX/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp @@ -129,29 +129,30 @@ void TokenStreamRewriteEngine::toStream( std::ostream& out, size_t tokenCursor = firstToken; // make sure we don't run out of the tokens we have... - if( lastToken > (tokens.size() - 1) ) - lastToken = tokens.size() - 1; + if( lastToken > (tokens.size() - 1) ) { + lastToken = tokens.size() - 1; + } - while ( tokenCursor <= lastToken ) - { + while ( tokenCursor <= lastToken ) + { // std::cout << "tokenCursor = " << tokenCursor << " first prog index = " << (*rewriteOpIndex)->getIndex() << std::endl; - if( rewriteOpIndex != rewriteOpEnd ) - { - size_t up_to_here = std::min(lastToken,(*rewriteOpIndex)->getIndex()); - while( tokenCursor < up_to_here ) - out << tokens[tokenCursor++]->getText(); - } - while ( rewriteOpIndex != rewriteOpEnd && - tokenCursor == (*rewriteOpIndex)->getIndex() && - tokenCursor <= lastToken ) - { - tokenCursor = (*rewriteOpIndex)->execute(out); - ++rewriteOpIndex; - } - if( tokenCursor <= lastToken ) - out << tokens[tokenCursor++]->getText(); - } + if( rewriteOpIndex != rewriteOpEnd ) + { + size_t up_to_here = std::min(lastToken,(*rewriteOpIndex)->getIndex()); + while( tokenCursor < up_to_here ) + out << tokens[tokenCursor++]->getText(); + } + while ( rewriteOpIndex != rewriteOpEnd && + tokenCursor == (*rewriteOpIndex)->getIndex() && + tokenCursor <= lastToken ) + { + tokenCursor = (*rewriteOpIndex)->execute(out); + ++rewriteOpIndex; + } + if( tokenCursor <= lastToken ) + out << tokens[tokenCursor++]->getText(); + } // std::cout << "Handling tail operations # left = " << std::distance(rewriteOpIndex,rewriteOpEnd) << std::endl; // now see if there are operations (append) beyond last token index std::for_each( rewriteOpIndex, rewriteOpEnd, executeOperation(out) ); diff --git a/OSX/libsecurity_codesigning/dtrace/codesign-watch.d b/OSX/libsecurity_codesigning/dtrace/codesign-watch.d old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/dtrace/reqint.d b/OSX/libsecurity_codesigning/dtrace/reqint.d old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/dtrace/sp-watch.d b/OSX/libsecurity_codesigning/dtrace/sp-watch.d old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/gke/gkclear b/OSX/libsecurity_codesigning/gke/gkclear old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/gke/gkgenerate b/OSX/libsecurity_codesigning/gke/gkgenerate old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/gke/gkhandmake b/OSX/libsecurity_codesigning/gke/gkhandmake old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/gke/gklist b/OSX/libsecurity_codesigning/gke/gklist old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/gke/gkmerge b/OSX/libsecurity_codesigning/gke/gkmerge old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/gke/gkrecord b/OSX/libsecurity_codesigning/gke/gkrecord old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/gke/gkreport b/OSX/libsecurity_codesigning/gke/gkreport old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_codesigning/lib/CSCommon.h b/OSX/libsecurity_codesigning/lib/CSCommon.h index d3a6bb18..b39fbe6f 100644 --- a/OSX/libsecurity_codesigning/lib/CSCommon.h +++ b/OSX/libsecurity_codesigning/lib/CSCommon.h @@ -215,6 +215,7 @@ typedef CF_OPTIONS(uint32_t, SecCSFlags) { kSecCSReportProgress = 1 << 28, /* make progress report call-backs when configured */ kSecCSCheckTrustedAnchors = 1 << 27, /* build certificate chain to system trust anchors, not to any self-signed certificate */ kSecCSQuickCheck = 1 << 26, /* (internal) */ + kSecCSApplyEmbeddedPolicy = 1 << 25, /* Apply Embedded (iPhone) policy regardless of the platform we're running on */ }; @@ -251,6 +252,9 @@ typedef CF_OPTIONS(uint32_t, SecCSFlags) { @constant kSecCodeSignatureRuntime Instructs the kernel to apply runtime hardening policies as required by the hardened runtime version + @constant kSecCodeSignatureLinkerSigned + The code was automatically signed by the linker. This signature should be + ignored in any new signing operation. */ typedef CF_OPTIONS(uint32_t, SecCodeSignatureFlags) { kSecCodeSignatureHost = 0x0001, /* may host guest code */ @@ -262,6 +266,7 @@ typedef CF_OPTIONS(uint32_t, SecCodeSignatureFlags) { kSecCodeSignatureEnforcement = 0x1000, /* enforce code signing */ kSecCodeSignatureLibraryValidation = 0x2000, /* library validation required */ kSecCodeSignatureRuntime = 0x10000, /* apply runtime hardening policies */ + kSecCodeSignatureLinkerSigned = 0x20000, /* identify that the signature was auto-generated by the linker*/ }; /*! diff --git a/OSX/libsecurity_codesigning/lib/Code.cpp b/OSX/libsecurity_codesigning/lib/Code.cpp index 712b2ff4..a3f11c4f 100644 --- a/OSX/libsecurity_codesigning/lib/Code.cpp +++ b/OSX/libsecurity_codesigning/lib/Code.cpp @@ -48,7 +48,7 @@ SecCode::SecCode(SecCode *host) // // Clean up a SecCode object // -SecCode::~SecCode() throw() +SecCode::~SecCode() _NOEXCEPT try { } catch (...) { return; diff --git a/OSX/libsecurity_codesigning/lib/Code.h b/OSX/libsecurity_codesigning/lib/Code.h index aa5942c9..bb189a6c 100644 --- a/OSX/libsecurity_codesigning/lib/Code.h +++ b/OSX/libsecurity_codesigning/lib/Code.h @@ -49,7 +49,7 @@ public: SECCFFUNCTIONS(SecCode, SecCodeRef, errSecCSInvalidObjectRef, gCFObjects().Code) SecCode(SecCode *host); - virtual ~SecCode() throw(); + virtual ~SecCode() _NOEXCEPT; bool equal(SecCFObject &other); CFHashCode hash(); diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp index bc11737f..8cbc67f8 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp @@ -121,7 +121,7 @@ SecCodeSigner::SecCodeSigner(SecCSFlags flags) // // Clean up a SecCodeSigner // -SecCodeSigner::~SecCodeSigner() throw() +SecCodeSigner::~SecCodeSigner() _NOEXCEPT try { delete mLimitedAsync; } catch (...) { @@ -182,9 +182,13 @@ bool SecCodeSigner::valid() const // void SecCodeSigner::sign(SecStaticCode *code, SecCSFlags flags) { - code->setValidationFlags(flags); - if (code->isSigned() && (flags & kSecCSSignPreserveSignature)) + //Never preserve a linker signature. + if (code->isSigned() && + (flags & kSecCSSignPreserveSignature) && + !code->flag(kSecCodeSignatureLinkerSigned)) { return; + } + code->setValidationFlags(flags); Signer operation(*this, code); if ((flags | mOpFlags) & kSecCSRemoveSignature) { secinfo("signer", "%p will remove signature from %p", this, code); diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.h b/OSX/libsecurity_codesigning/lib/CodeSigner.h index 099d18c7..7e897850 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.h +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.h @@ -51,7 +51,7 @@ public: SECCFFUNCTIONS(SecCodeSigner, SecCodeSignerRef, errSecCSInvalidObjectRef, gCFObjects().CodeSigner) SecCodeSigner(SecCSFlags flags); - virtual ~SecCodeSigner() throw(); + virtual ~SecCodeSigner() _NOEXCEPT; void parameters(CFDictionaryRef args); // parse and set parameters bool valid() const; diff --git a/OSX/libsecurity_codesigning/lib/Requirements.cpp b/OSX/libsecurity_codesigning/lib/Requirements.cpp index d2fb04fe..36a2786f 100644 --- a/OSX/libsecurity_codesigning/lib/Requirements.cpp +++ b/OSX/libsecurity_codesigning/lib/Requirements.cpp @@ -62,7 +62,7 @@ SecRequirement::SecRequirement(const Requirement *req, bool transferOwnership) // // Clean up a SecRequirement object // -SecRequirement::~SecRequirement() throw() +SecRequirement::~SecRequirement() _NOEXCEPT try { ::free((void *)mReq); } catch (...) { diff --git a/OSX/libsecurity_codesigning/lib/Requirements.h b/OSX/libsecurity_codesigning/lib/Requirements.h index 8a266f1c..f4212685 100644 --- a/OSX/libsecurity_codesigning/lib/Requirements.h +++ b/OSX/libsecurity_codesigning/lib/Requirements.h @@ -46,7 +46,7 @@ public: SecRequirement(const void *data, size_t length); SecRequirement(const Requirement *req, bool transferOwnership = false); - virtual ~SecRequirement() throw(); + virtual ~SecRequirement() _NOEXCEPT; bool equal(SecCFObject &other); CFHashCode hash(); diff --git a/OSX/libsecurity_codesigning/lib/SecAssessment.cpp b/OSX/libsecurity_codesigning/lib/SecAssessment.cpp index 1db11311..84f5c10e 100644 --- a/OSX/libsecurity_codesigning/lib/SecAssessment.cpp +++ b/OSX/libsecurity_codesigning/lib/SecAssessment.cpp @@ -425,10 +425,10 @@ CFDictionaryRef SecAssessmentCopyUpdate(CFTypeRef target, if (flags & kSecAssessmentFlagDirect) { // ask the engine right here to do its thing - result = gEngine().update(target, flags, ctx); + result.take(gEngine().update(target, flags, ctx)); } else { // relay the question to our daemon for consideration - result = xpcEngineUpdate(target, flags, ctx); + result.take(xpcEngineUpdate(target, flags, ctx)); } traceUpdate(target, context, result); diff --git a/OSX/libsecurity_codesigning/lib/SecCode.cpp b/OSX/libsecurity_codesigning/lib/SecCode.cpp index 2a494dc7..444c0cf9 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecCode.cpp @@ -33,6 +33,7 @@ #include "cskernel.h" #include #include +#include using namespace CodeSigning; @@ -213,6 +214,31 @@ OSStatus SecCodeCreateWithAuditToken(const audit_token_t *audit, END_CSAPI } + +OSStatus SecCodeCreateWithXPCMessage(xpc_object_t message, SecCSFlags flags, + SecCodeRef * __nonnull CF_RETURNS_RETAINED target) +{ + BEGIN_CSAPI + + checkFlags(flags); + + if (xpc_get_type(message) != XPC_TYPE_DICTIONARY) { + return errSecCSInvalidObjectRef; + } + + xpc_connection_t connection = xpc_dictionary_get_remote_connection(message); + if (connection == NULL) { + return errSecCSInvalidObjectRef; + } + + audit_token_t t = {0}; + xpc_connection_get_audit_token(connection, &t); + + return SecCodeCreateWithAuditToken(&t, flags, target); + + END_CSAPI +} + #endif // TARGET_OS_OSX @@ -236,6 +262,8 @@ OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags, | kSecCSStrictValidateStructure | kSecCSRestrictSidebandData | kSecCSEnforceRevocationChecks + | kSecCSAllowNetworkAccess + | kSecCSNoNetworkAccess ); SecPointer code = SecCode::required(codeRef); code->checkValidity(flags); @@ -289,6 +317,7 @@ const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory"); const CFStringRef kSecCodeInfoNotarizationDate = CFSTR("NotarizationDate"); const CFStringRef kSecCodeInfoCMSDigestHashType = CFSTR("CMSDigestHashType"); const CFStringRef kSecCodeInfoCMSDigest = CFSTR("CMSDigest"); +const CFStringRef kSecCodeInfoSignatureVersion = CFSTR("SignatureVersion"); /* DiskInfoRepInfo types */ const CFStringRef kSecCodeInfoDiskRepVersionPlatform = CFSTR("VersionPlatform"); @@ -308,7 +337,7 @@ OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flag | kSecCSRequirementInformation | kSecCSDynamicInformation | kSecCSContentInformation - | kSecCSSkipResourceDirectory + | kSecCSSkipResourceDirectory | kSecCSCalculateCMSDigest); SecPointer code = SecStaticCode::requiredStatic(codeRef); diff --git a/OSX/libsecurity_codesigning/lib/SecCode.h b/OSX/libsecurity_codesigning/lib/SecCode.h index aa53b5ac..14009a51 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.h +++ b/OSX/libsecurity_codesigning/lib/SecCode.h @@ -32,6 +32,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -187,6 +188,28 @@ extern const CFStringRef kSecGuestAttributeSubarchitecture; OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef __nullable host, CFDictionaryRef __nullable attributes, SecCSFlags flags, SecCodeRef * __nonnull CF_RETURNS_RETAINED guest); + +/*! + @function SecCodeCreateWithXPCMessage + Creates a SecCode reference to the process that sent the provided XPC message, using the + associated audit token. + + @param message The xpc_object_t of a message recieved via xpc to look up the audit token + of the process that sent the message. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param processRef On successful return, a SecCode object reference identifying + the particular guest of the process from the audit token. This argument will not be + changed if the call fails (does not return errSecSuccess). + @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. In particular: + @error errSecCSInvalidObjectRef The xpc_object_t was not of type XPC_TYPE_DICTIONARY. + @error errSecCSInvalidObjectRef The xpc_object_t was not an xpc message with an associated + connection. + For a complete list of errors, please see {@link SecCodeCopyGuestWithAttributes}. +*/ +OSStatus SecCodeCreateWithXPCMessage(xpc_object_t message, SecCSFlags flags, + SecCodeRef * __nonnull CF_RETURNS_RETAINED target); + #endif // TARGET_OS_OSX @@ -215,7 +238,7 @@ OSStatus SecCodeCheckValidity(SecCodeRef code, SecCSFlags flags, SecRequirementRef __nullable requirement); /*! - @function SecCodeCheckValidityWifErrors + @function SecCodeCheckValidityWithErrors Performs dynamic validation of the given SecCode object. The call obtains and verifies the signature on the code object. It checks the validity of only those sealed components required to establish identity. It checks the SecCode's @@ -290,7 +313,10 @@ OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef code, SecCSFlags flag @function SecCodeCopySigningInformation For a given Code or StaticCode object, extract various pieces of information from its code signature and return them in the form of a CFDictionary. The amount - and detail level of the data is controlled by the flags passed to the call. + and detail level of the data is controlled by the flags passed to the call. For + Code objects, some of the signing information returned will be from disk. You can + call one of the CheckValidity functions to check that the content on disk matches + the signing information attached to the running Code. If the code exists but is not signed at all, this call will succeed and return a dictionary that does NOT contain the kSecCodeInfoIdentifier key. This is the diff --git a/OSX/libsecurity_codesigning/lib/SecCodePriv.h b/OSX/libsecurity_codesigning/lib/SecCodePriv.h index d88239c8..a5b128cd 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodePriv.h +++ b/OSX/libsecurity_codesigning/lib/SecCodePriv.h @@ -47,6 +47,7 @@ extern const CFStringRef kSecCodeInfoResourceDirectory; /* Internal */ extern const CFStringRef kSecCodeInfoNotarizationDate; /* Internal */ extern const CFStringRef kSecCodeInfoCMSDigestHashType; /* Internal */ extern const CFStringRef kSecCodeInfoCMSDigest; /* Internal */ +extern const CFStringRef kSecCodeInfoSignatureVersion; /* Internal */ extern const CFStringRef kSecCodeInfoDiskRepVersionPlatform; /* Number */ extern const CFStringRef kSecCodeInfoDiskRepVersionMin; /* Number */ @@ -229,7 +230,10 @@ OSStatus SecCodeValidateFileResource(SecStaticCodeRef code, CFStringRef relative entirely eventually, we makes this a private flag. */ CF_ENUM(uint32_t) { + // NOTE: These values needs to align with the public definitions for static code validity too. kSecCSStrictValidateStructure = 1 << 13, + kSecCSSkipRootVolumeExceptions = 1 << 14, + kSecCSSkipXattrFiles = 1 << 15, }; #if TARGET_OS_OSX diff --git a/OSX/libsecurity_codesigning/lib/SecCodeSigner.h b/OSX/libsecurity_codesigning/lib/SecCodeSigner.h index eba11830..c1a83ba4 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodeSigner.h +++ b/OSX/libsecurity_codesigning/lib/SecCodeSigner.h @@ -38,7 +38,11 @@ extern "C" { @typedef SecCodeSignerRef This is the type of a reference to a code requirement. */ +#ifdef BRIDGED_SECCODESIGNER +typedef struct CF_BRIDGED_TYPE(id) __SecCodeSigner *SecCodeSignerRef; /* code signing object */ +#else typedef struct __SecCodeSigner *SecCodeSignerRef; /* code signing object */ +#endif /*! @@ -215,10 +219,13 @@ enum { kSecCSEditSignature = 1 << 10, // edit existing signature }; - +#ifdef BRIDGED_SECCODESIGNER +OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, + SecCodeSignerRef * __nonnull CF_RETURNS_RETAINED signer); +#else OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, SecCodeSignerRef *signer); - +#endif /*! @function SecCodeSignerAddSignature diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp index b240b4b8..da60c8bc 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp @@ -122,21 +122,28 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se | kSecCSCheckGatekeeperArchitectures | kSecCSRestrictSymlinks | kSecCSRestrictToAppLike - | kSecCSUseSoftwareSigningCert - | kSecCSValidatePEH + | kSecCSUseSoftwareSigningCert + | kSecCSValidatePEH | kSecCSSingleThreaded + | kSecCSApplyEmbeddedPolicy + | kSecCSSkipRootVolumeExceptions + | kSecCSSkipXattrFiles + | kSecCSAllowNetworkAccess ); if (errors) flags |= kSecCSFullReport; // internal-use flag +#if !TARGET_OS_OSX + flags |= kSecCSApplyEmbeddedPolicy; +#endif + SecPointer code = SecStaticCode::requiredStatic(staticCodeRef); code->setValidationFlags(flags); const SecRequirement *req = SecRequirement::optional(requirementRef); DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str()); code->staticValidate(flags, req); -#if TARGET_OS_IPHONE // Everything checked out correctly but we need to make sure that when // we validated the code directory, we trusted the signer. We defer this // until now because the caller may still trust the signer via a @@ -144,15 +151,38 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se // the directory, we potentially skip resource validation even though the // caller will go on to trust the signature // Applications that are validated against a provisioning profile do not have their resources checked - if (code->trustedSigningCertChain() == false) { + if ((flags & kSecCSApplyEmbeddedPolicy) && code->trustedSigningCertChain() == false) { return CSError::cfError(errors, errSecCSSignatureUntrusted); } -#endif END_CSAPI_ERRORS } +OSStatus SecStaticCodeValidateResourceWithErrors(SecStaticCodeRef staticCodeRef, CFURLRef resourcePath, SecCSFlags flags, CFErrorRef *errors) +{ + BEGIN_CSAPI + + checkFlags(flags, + kSecCSCheckAllArchitectures + | kSecCSConsiderExpiration + | kSecCSEnforceRevocationChecks + | kSecCSNoNetworkAccess + | kSecCSStrictValidate + | kSecCSStrictValidateStructure + | kSecCSRestrictSidebandData + | kSecCSCheckGatekeeperArchitectures + | kSecCSSkipRootVolumeExceptions + | kSecCSAllowNetworkAccess + | kSecCSFastExecutableValidation + ); + + SecPointer code = SecStaticCode::requiredStatic(staticCodeRef); + code->setValidationFlags(flags); + code->staticValidateResource(cfString(resourcePath), flags, NULL); + + END_CSAPI_ERRORS +} // // ==================================================================================== @@ -251,7 +281,7 @@ OSStatus SecCodeMapMemory(SecStaticCodeRef codeRef, SecCSFlags flags) MacOSError::throwMe(errSecCSNoMainExecutable); } - auto_ptr arch(execImage->architecture()); + unique_ptr arch(execImage->architecture()); if (arch.get() == NULL) { MacOSError::throwMe(errSecCSNoMainExecutable); } @@ -334,6 +364,24 @@ CFDataRef SecCodeCopyComponent(SecCodeRef codeRef, int slot, CFDataRef hash) END_CSAPI1(NULL) } +// +// Updates the flags to indicate whether this object wants to enable online notarization checks. +// +OSStatus SecStaticCodeEnableOnlineNotarizationCheck(SecStaticCodeRef codeRef, Boolean enable) +{ + BEGIN_CSAPI + + SecStaticCode* code = SecStaticCode::requiredStatic(codeRef); + SecCSFlags flags = code->getFlags(); + if (enable) { + flags = addFlags(flags, kSecCSForceOnlineNotarizationCheck); + } else { + flags = clearFlags(flags, kSecCSForceOnlineNotarizationCheck); + } + code->setFlags(flags); + + END_CSAPI +} // // Validate a single plain file's resource seal against a memory copy. diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.h b/OSX/libsecurity_codesigning/lib/SecStaticCode.h index b053623e..565b10c3 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.h +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.h @@ -155,7 +155,13 @@ OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flag For code in bundle form, perform additional checks to verify that the bundle is not structured in a way that would allow tampering, and reject any resource envelope that introduces weaknesses into the signature. - + @constant kSecCSSingleThreaded + Perform all resource validation serially on a single thread instead of dispatching + work in parallel. + @constant kSecCSAllowNetworkAccess + Enables network access for certificate trust evaluation performed while validating the + bundle or its contents. + @param requirement On optional code requirement specifying additional conditions the staticCode object must satisfy to be considered valid. If NULL, no additional requirements are imposed. @@ -178,9 +184,12 @@ CF_ENUM(uint32_t) { kSecCSRestrictSymlinks = 1 << 7, kSecCSRestrictToAppLike = 1 << 8, kSecCSRestrictSidebandData = 1 << 9, - kSecCSUseSoftwareSigningCert = 1 << 10, + kSecCSUseSoftwareSigningCert = 1 << 10, kSecCSValidatePEH = 1 << 11, kSecCSSingleThreaded = 1 << 12, + // NOTE: These values have gaps for internal usage. + kSecCSAllowNetworkAccess CF_ENUM_AVAILABLE(11_3, 14_5) = 1 << 16, + kSecCSFastExecutableValidation CF_ENUM_AVAILABLE(11_3, 14_5) = 1 << 17, }; OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCode, SecCSFlags flags, diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCodePriv.h b/OSX/libsecurity_codesigning/lib/SecStaticCodePriv.h index a5376f44..5ecc85c7 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCodePriv.h +++ b/OSX/libsecurity_codesigning/lib/SecStaticCodePriv.h @@ -91,6 +91,41 @@ OSStatus SecStaticCodeSetValidationConditions(SecStaticCodeRef code, CFDictionar */ OSStatus SecStaticCodeCancelValidation(SecStaticCodeRef code, SecCSFlags flags); +/* + @function SecStaticCodeEnableOnlineNotarizationCheck + Sets a flag on the object to allow an online notarization check once for the lifetime of the object during + the next validation. + + @param code A StaticCode object whose validation should be modified. + @param enable Whether to enable or disable online notarization checks. + */ +OSStatus SecStaticCodeEnableOnlineNotarizationCheck(SecStaticCodeRef code, Boolean enable) __SPI_AVAILABLE(macos(11.3)); + +/* + @function SecStaticCodeValidateResource + For a SecStaticCodeRef, check that the resource at the provided path is part of the signature and unaltered. + This call will fail if the file is not in the bundle, missing from the bundle, optional, or signed + into the bundle in a way that it cannot be fully verified. + + @param code A SecStaticCode object for the outer bundle. + @param resourcePath A CFStringRef containing the absolute path to a sealed resource file. + This path will be checked and must be to something within the code object's base path. + @param flags Flags to use during validation, see SecStaticCodeCheckValidity + @param errors An optional pointer to a CFErrorRef variable. If the call fails + (something other than errSecSuccess is returned), and this argument is non-NULL, + a CFErrorRef is stored there further describing the nature and circumstances + of the failure. The caller must CFRelease() this error object when done with it. + + @result noErr if the file at resourcePath validates as a resource of the bundle represented by code. Can return a + variety of errors from CSCommon.h or other Security framework headers, but notable errors are: + + errSecParam if the resource is not within the code object. + errSecCSResourcesNotFound if the resources in the bundle could not be loaded. + errSecCSResourcesNotSealed if the requested resource was found but cannot be verified. + errSecCSBadResource if the resource couldn't be found or was altered. + errSecCSSignatureFailed if the executable resource was found and was altered. + */ +OSStatus SecStaticCodeValidateResourceWithErrors(SecStaticCodeRef code, CFURLRef resourcePath, SecCSFlags flags, CFErrorRef *errors) __SPI_AVAILABLE(macos(11.3)); #ifdef __cplusplus } diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.cpp b/OSX/libsecurity_codesigning/lib/StaticCode.cpp index 2d5a3e90..0c4be9d3 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/StaticCode.cpp @@ -25,8 +25,10 @@ // StaticCode - SecStaticCode API objects // #include "StaticCode.h" +#include "SecTask.h" #include "Code.h" #include "reqmaker.h" +#include "machorep.h" #if TARGET_OS_OSX #include "drmaker.h" #include "notarization.h" @@ -66,7 +68,10 @@ #include #include #include +#include +#include #include +#import namespace Security { @@ -97,6 +102,39 @@ static inline OSStatus errorForSlot(CodeDirectory::SpecialSlot slot) } } +/// Determines if the current process is marked as platform, cached with dispatch_once. +static bool isCurrentProcessPlatform(void) +{ + static dispatch_once_t sOnceToken; + static bool sIsPlatform = false; + + dispatch_once(&sOnceToken, ^{ + SecTaskRef task = SecTaskCreateFromSelf(NULL); + if (task) { + uint32_t flags = SecTaskGetCodeSignStatus(task); + if (flags & kSecCodeStatusPlatform) { + sIsPlatform = true; + } + CFRelease(task); + } + }); + + return sIsPlatform; +} + +/// Determines if the item qualifies for a resource validity exemption based on its filesystem location. +static bool itemQualifiesForResourceExemption(string &item) +{ + if (isOnRootFilesystem(item.c_str())) { + return true; + } + if (os_variant_allows_internal_security_policies("com.apple.security.codesigning")) { + if (isPathPrefix("/AppleInternal/", item)) { + return true; + } + } + return false; +} // // Construct a SecStaticCode object given a disk representation object @@ -108,17 +146,21 @@ SecStaticCode::SecStaticCode(DiskRep *rep, uint32_t flags) mProgressQueue("com.apple.security.validation-progress", false, QOS_CLASS_UNSPECIFIED), mOuterScope(NULL), mResourceScope(NULL), mDesignatedReq(NULL), mGotResourceBase(false), mMonitor(NULL), mLimitedAsync(NULL), - mFlags(flags), mNotarizationChecked(false), mStaplingChecked(false), mNotarizationDate(NAN) -#if TARGET_OS_OSX - , mEvalDetails(NULL) -#else - , mTrustedSigningCertChain(false) -#endif + mFlags(flags), mNotarizationChecked(false), mStaplingChecked(false), mNotarizationDate(NAN), + mNetworkEnabledByDefault(true), mTrustedSigningCertChain(false) { CODESIGN_STATIC_CREATE(this, rep); #if TARGET_OS_OSX checkForSystemSignature(); + + // By default, platform code will no longer use the network. + if (os_feature_enabled(Security, SecCodeOCSPDefault)) { + if (isCurrentProcessPlatform()) { + mNetworkEnabledByDefault = false; + } + } + secinfo("staticCode", "SecStaticCode network default: %s", mNetworkEnabledByDefault ? "YES" : "NO"); #endif } @@ -126,7 +168,7 @@ SecStaticCode::SecStaticCode(DiskRep *rep, uint32_t flags) // // Clean up a SecStaticCode object // -SecStaticCode::~SecStaticCode() throw() +SecStaticCode::~SecStaticCode() _NOEXCEPT try { ::free(const_cast(mDesignatedReq)); delete mResourcesValidContext; @@ -361,9 +403,6 @@ void SecStaticCode::resetValidity() mNotarizationChecked = false; mStaplingChecked = false; mNotarizationDate = NAN; -#if TARGET_OS_OSX - mEvalDetails = NULL; -#endif mRep->flush(); #if TARGET_OS_OSX @@ -771,297 +810,292 @@ bool SecStaticCode::verifySignature() DTRACK(CODESIGN_EVAL_STATIC_SIGNATURE, this, (char*)this->mainExecutablePath().c_str()); #if TARGET_OS_OSX - // decode CMS and extract SecTrust for verification - CFRef cms; - MacOSError::check(CMSDecoderCreate(&cms.aref())); // create decoder - CFDataRef sig = this->signature(); - MacOSError::check(CMSDecoderUpdateMessage(cms, CFDataGetBytePtr(sig), CFDataGetLength(sig))); - this->codeDirectory(); // load CodeDirectory (sets mDir) - MacOSError::check(CMSDecoderSetDetachedContent(cms, mBaseDir)); - MacOSError::check(CMSDecoderFinalizeMessage(cms)); - MacOSError::check(CMSDecoderSetSearchKeychain(cms, cfEmptyArray())); - CFRef vf_policies(createVerificationPolicies()); - CFRef ts_policies(createTimeStampingAndRevocationPolicies()); + if (!(mValidationFlags & kSecCSApplyEmbeddedPolicy)) { + // decode CMS and extract SecTrust for verification + CFRef cms; + MacOSError::check(CMSDecoderCreate(&cms.aref())); // create decoder + CFDataRef sig = this->signature(); + MacOSError::check(CMSDecoderUpdateMessage(cms, CFDataGetBytePtr(sig), CFDataGetLength(sig))); + this->codeDirectory(); // load CodeDirectory (sets mDir) + MacOSError::check(CMSDecoderSetDetachedContent(cms, mBaseDir)); + MacOSError::check(CMSDecoderFinalizeMessage(cms)); + MacOSError::check(CMSDecoderSetSearchKeychain(cms, cfEmptyArray())); + CFRef vf_policies(createVerificationPolicies()); + CFRef ts_policies(createTimeStampingAndRevocationPolicies()); - CMSSignerStatus status; - MacOSError::check(CMSDecoderCopySignerStatus(cms, 0, vf_policies, - false, &status, &mTrust.aref(), NULL)); + CMSSignerStatus status; + MacOSError::check(CMSDecoderCopySignerStatus(cms, 0, vf_policies, + false, &status, &mTrust.aref(), NULL)); - if (status != kCMSSignerValid) { - const char *reason; - switch (status) { - case kCMSSignerUnsigned: reason="kCMSSignerUnsigned"; break; - case kCMSSignerNeedsDetachedContent: reason="kCMSSignerNeedsDetachedContent"; break; - case kCMSSignerInvalidSignature: reason="kCMSSignerInvalidSignature"; break; - case kCMSSignerInvalidCert: reason="kCMSSignerInvalidCert"; break; - case kCMSSignerInvalidIndex: reason="kCMSSignerInvalidIndex"; break; - default: reason="unknown"; break; + if (status != kCMSSignerValid) { + const char *reason; + switch (status) { + case kCMSSignerUnsigned: reason="kCMSSignerUnsigned"; break; + case kCMSSignerNeedsDetachedContent: reason="kCMSSignerNeedsDetachedContent"; break; + case kCMSSignerInvalidSignature: reason="kCMSSignerInvalidSignature"; break; + case kCMSSignerInvalidCert: reason="kCMSSignerInvalidCert"; break; + case kCMSSignerInvalidIndex: reason="kCMSSignerInvalidIndex"; break; + default: reason="unknown"; break; + } + Security::Syslog::error("CMSDecoderCopySignerStatus failed with %s error (%d)", + reason, (int)status); + MacOSError::throwMe(errSecCSSignatureFailed); } - Security::Syslog::error("CMSDecoderCopySignerStatus failed with %s error (%d)", - reason, (int)status); - MacOSError::throwMe(errSecCSSignatureFailed); - } - // retrieve auxiliary v1 data bag and verify against current state - CFRef hashAgilityV1; - switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgility(cms, 0, &hashAgilityV1.aref())) { - case noErr: - if (hashAgilityV1) { - CFRef hashDict = makeCFDictionaryFrom(hashAgilityV1); - CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); - CFArrayRef myCdList = this->cdHashes(); - - /* Note that this is not very "agile": There's no way to calculate the exact - * list for comparison if it contains hash algorithms we don't know yet... */ - if (cdList == NULL || !CFEqual(cdList, myCdList)) - MacOSError::throwMe(errSecCSSignatureFailed); - } - break; - case -1: /* CMS used to return this for "no attribute found", so tolerate it. Now returning noErr/NULL */ - break; - default: - MacOSError::throwMe(rc); - } - - // retrieve auxiliary v2 data bag and verify against current state - CFRef hashAgilityV2; - switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgilityV2(cms, 0, &hashAgilityV2.aref())) { + // retrieve auxiliary v1 data bag and verify against current state + CFRef hashAgilityV1; + switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgility(cms, 0, &hashAgilityV1.aref())) { case noErr: - if (hashAgilityV2) { - /* Require number of code directoris and entries in the hash agility - * dict to be the same size (no stripping out code directories). - */ - if (CFDictionaryGetCount(hashAgilityV2) != mCodeDirectories.size()) { + if (hashAgilityV1) { + CFRef hashDict = makeCFDictionaryFrom(hashAgilityV1); + CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); + CFArrayRef myCdList = this->cdHashes(); + + /* Note that this is not very "agile": There's no way to calculate the exact + * list for comparison if it contains hash algorithms we don't know yet... */ + if (cdList == NULL || !CFEqual(cdList, myCdList)) MacOSError::throwMe(errSecCSSignatureFailed); - } - - /* Require every cdhash of every code directory whose hash - * algorithm we know to be in the agility dictionary. - * - * We check untruncated cdhashes here because we can. - */ - bool foundOurs = false; - for (auto& entry : mCodeDirectories) { - SECOidTag tag = CodeDirectorySet::SECOidTagForAlgorithm(entry.first); - - if (tag == SEC_OID_UNKNOWN) { - // Unknown hash algorithm, ignore. - continue; - } - - CFRef key = makeCFNumber(int(tag)); - CFRef entryCdhash; - entryCdhash = (CFDataRef)CFDictionaryGetValue(hashAgilityV2, (void*)key.get()); - - CodeDirectory const *cd = (CodeDirectory const*)CFDataGetBytePtr(entry.second); - CFRef ourCdhash = cd->cdhash(false); // Untruncated cdhash! - if (!CFEqual(entryCdhash, ourCdhash)) { - MacOSError::throwMe(errSecCSSignatureFailed); - } - - if (entry.first == this->hashAlgorithm()) { - foundOurs = true; - } - } - - /* Require the cdhash of our chosen code directory to be in the dictionary. - * In theory, the dictionary could be full of unsupported cdhashes, but we - * really want ours, which is bound to be supported, to be covered. - */ - if (!foundOurs) { - MacOSError::throwMe(errSecCSSignatureFailed); - } } break; case -1: /* CMS used to return this for "no attribute found", so tolerate it. Now returning noErr/NULL */ break; default: MacOSError::throwMe(rc); - } + } - // internal signing time (as specified by the signer; optional) - mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) - switch (OSStatus rc = CMSDecoderCopySignerSigningTime(cms, 0, &mSigningTime)) { - case errSecSuccess: - case errSecSigningTimeMissing: - break; - default: - Security::Syslog::error("Could not get signing time (error %d)", (int)rc); - MacOSError::throwMe(rc); - } + // retrieve auxiliary v2 data bag and verify against current state + CFRef hashAgilityV2; + switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgilityV2(cms, 0, &hashAgilityV2.aref())) { + case noErr: + if (hashAgilityV2) { + /* Require number of code directoris and entries in the hash agility + * dict to be the same size (no stripping out code directories). + */ + if (CFDictionaryGetCount(hashAgilityV2) != mCodeDirectories.size()) { + MacOSError::throwMe(errSecCSSignatureFailed); + } - // certified signing time (as specified by a TSA; optional) - mSigningTimestamp = 0; - switch (OSStatus rc = CMSDecoderCopySignerTimestampWithPolicy(cms, ts_policies, 0, &mSigningTimestamp)) { - case errSecSuccess: - case errSecTimestampMissing: - break; - default: - Security::Syslog::error("Could not get timestamp (error %d)", (int)rc); - MacOSError::throwMe(rc); - } + /* Require every cdhash of every code directory whose hash + * algorithm we know to be in the agility dictionary. + * + * We check untruncated cdhashes here because we can. + */ + bool foundOurs = false; + for (auto& entry : mCodeDirectories) { + SECOidTag tag = CodeDirectorySet::SECOidTagForAlgorithm(entry.first); - // set up the environment for SecTrust - if (mValidationFlags & kSecCSNoNetworkAccess) { - MacOSError::check(SecTrustSetNetworkFetchAllowed(mTrust,false)); // no network? - } - MacOSError::check(SecTrustSetKeychainsAllowed(mTrust, false)); + if (tag == SEC_OID_UNKNOWN) { + // Unknown hash algorithm, ignore. + continue; + } - CSSM_APPLE_TP_ACTION_DATA actionData = { - CSSM_APPLE_TP_ACTION_VERSION, // version of data structure - 0 // action flags - }; + CFRef key = makeCFNumber(int(tag)); + CFRef entryCdhash; + entryCdhash = (CFDataRef)CFDictionaryGetValue(hashAgilityV2, (void*)key.get()); - if (!(mValidationFlags & kSecCSCheckTrustedAnchors)) { - /* no need to evaluate anchor trust when building cert chain */ - MacOSError::check(SecTrustSetAnchorCertificates(mTrust, cfEmptyArray())); // no anchors - actionData.ActionFlags |= CSSM_TP_ACTION_IMPLICIT_ANCHORS; // action flags - } + CodeDirectory const *cd = (CodeDirectory const*)CFDataGetBytePtr(entry.second); + CFRef ourCdhash = cd->cdhash(false); // Untruncated cdhash! + if (!CFEqual(entryCdhash, ourCdhash)) { + MacOSError::throwMe(errSecCSSignatureFailed); + } - for (;;) { // at most twice - MacOSError::check(SecTrustSetParameters(mTrust, - CSSM_TP_ACTION_DEFAULT, CFTempData(&actionData, sizeof(actionData)))); + if (entry.first == this->hashAlgorithm()) { + foundOurs = true; + } + } - // evaluate trust and extract results + /* Require the cdhash of our chosen code directory to be in the dictionary. + * In theory, the dictionary could be full of unsupported cdhashes, but we + * really want ours, which is bound to be supported, to be covered. + */ + if (!foundOurs) { + MacOSError::throwMe(errSecCSSignatureFailed); + } + } + break; + case -1: /* CMS used to return this for "no attribute found", so tolerate it. Now returning noErr/NULL */ + break; + default: + MacOSError::throwMe(rc); + } + + // internal signing time (as specified by the signer; optional) + mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) + switch (OSStatus rc = CMSDecoderCopySignerSigningTime(cms, 0, &mSigningTime)) { + case errSecSuccess: + case errSecSigningTimeMissing: + break; + default: + Security::Syslog::error("Could not get signing time (error %d)", (int)rc); + MacOSError::throwMe(rc); + } + + // certified signing time (as specified by a TSA; optional) + mSigningTimestamp = 0; + switch (OSStatus rc = CMSDecoderCopySignerTimestampWithPolicy(cms, ts_policies, 0, &mSigningTimestamp)) { + case errSecSuccess: + case errSecTimestampMissing: + break; + default: + Security::Syslog::error("Could not get timestamp (error %d)", (int)rc); + MacOSError::throwMe(rc); + } + + // set up the environment for SecTrust + if (validationCannotUseNetwork()) { + MacOSError::check(SecTrustSetNetworkFetchAllowed(mTrust, false)); // no network? + } + MacOSError::check(SecTrustSetKeychainsAllowed(mTrust, false)); + + CSSM_APPLE_TP_ACTION_DATA actionData = { + CSSM_APPLE_TP_ACTION_VERSION, // version of data structure + 0 // action flags + }; + + if (!(mValidationFlags & kSecCSCheckTrustedAnchors)) { + /* no need to evaluate anchor trust when building cert chain */ + MacOSError::check(SecTrustSetAnchorCertificates(mTrust, cfEmptyArray())); // no anchors + actionData.ActionFlags |= CSSM_TP_ACTION_IMPLICIT_ANCHORS; // action flags + } + + for (;;) { // at most twice + MacOSError::check(SecTrustSetParameters(mTrust, + CSSM_TP_ACTION_DEFAULT, CFTempData(&actionData, sizeof(actionData)))); + + // evaluate trust and extract results + SecTrustResultType trustResult; + MacOSError::check(SecTrustEvaluate(mTrust, &trustResult)); + mCertChain.take(copyCertChain(mTrust)); + + // if this is an Apple developer cert.... + if (teamID() && SecStaticCode::isAppleDeveloperCert(mCertChain)) { + CFRef teamIDFromCert; + if (CFArrayGetCount(mCertChain) > 0) { + SecCertificateRef leaf = (SecCertificateRef)CFArrayGetValueAtIndex(mCertChain, Requirement::leafCert); + CFArrayRef organizationalUnits = SecCertificateCopyOrganizationalUnit(leaf); + if (organizationalUnits) { + teamIDFromCert.take((CFStringRef)CFRetain(CFArrayGetValueAtIndex(organizationalUnits, 0))); + CFRelease(organizationalUnits); + } else { + teamIDFromCert = NULL; + } + + if (teamIDFromCert) { + CFRef teamIDFromCD = CFStringCreateWithCString(NULL, teamID(), kCFStringEncodingUTF8); + if (!teamIDFromCD) { + Security::Syslog::error("Could not get team identifier (%s)", teamID()); + MacOSError::throwMe(errSecCSInvalidTeamIdentifier); + } + + if (CFStringCompare(teamIDFromCert, teamIDFromCD, 0) != kCFCompareEqualTo) { + Security::Syslog::error("Team identifier in the signing certificate (%s) does not match the team identifier (%s) in the code directory", + cfString(teamIDFromCert).c_str(), teamID()); + MacOSError::throwMe(errSecCSBadTeamIdentifier); + } + } + } + } + + CODESIGN_EVAL_STATIC_SIGNATURE_RESULT(this, trustResult, mCertChain ? (int)CFArrayGetCount(mCertChain) : 0); + switch (trustResult) { + case kSecTrustResultProceed: + case kSecTrustResultUnspecified: + break; // success + case kSecTrustResultDeny: + MacOSError::throwMe(CSSMERR_APPLETP_TRUST_SETTING_DENY); // user reject + case kSecTrustResultInvalid: + assert(false); // should never happen + MacOSError::throwMe(CSSMERR_TP_NOT_TRUSTED); + default: + { + OSStatus result; + MacOSError::check(SecTrustGetCssmResultCode(mTrust, &result)); + // if we have a valid timestamp, CMS validates against (that) signing time and all is well. + // If we don't have one, may validate against *now*, and must be able to tolerate expiration. + if (mSigningTimestamp == 0) { // no timestamp available + if (((result == CSSMERR_TP_CERT_EXPIRED) || (result == CSSMERR_TP_CERT_NOT_VALID_YET)) + && !(actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED)) { + CODESIGN_EVAL_STATIC_SIGNATURE_EXPIRED(this); + actionData.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED; // (this also allows postdated certs) + continue; // retry validation while tolerating expiration + } + } + if (checkfix41082220(result)) { + break; // success + } + Security::Syslog::error("SecStaticCode: verification failed (trust result %d, error %d)", trustResult, (int)result); + MacOSError::throwMe(result); + } + } + + if (mSigningTimestamp) { + CFIndex rootix = CFArrayGetCount(mCertChain); + if (SecCertificateRef mainRoot = SecCertificateRef(CFArrayGetValueAtIndex(mCertChain, rootix-1))) + if (isAppleCA(mainRoot)) { + // impose policy: if the signature itself draws to Apple, then so must the timestamp signature + CFRef tsCerts; + OSStatus result = CMSDecoderCopySignerTimestampCertificates(cms, 0, &tsCerts.aref()); + if (result) { + Security::Syslog::error("SecStaticCode: could not get timestamp certificates (error %d)", (int)result); + MacOSError::check(result); + } + CFIndex tsn = CFArrayGetCount(tsCerts); + bool good = tsn > 0 && isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(tsCerts, tsn-1))); + if (!good) { + result = CSSMERR_TP_NOT_TRUSTED; + Security::Syslog::error("SecStaticCode: timestamp policy verification failed (error %d)", (int)result); + MacOSError::throwMe(result); + } + } + } + + return actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED; + } + + } else +#endif + { + // Do some pre-verification initialization + CFDataRef sig = this->signature(); + this->codeDirectory(); // load CodeDirectory (sets mDir) + mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) + + CFRef attrs; + CFRef vf_policies(createVerificationPolicies()); + + // Verify the CMS signature against mBaseDir (SHA1) + MacOSError::check(SecCMSVerifyCopyDataAndAttributes(sig, mBaseDir, vf_policies, &mTrust.aref(), NULL, &attrs.aref())); + + // Copy the signing time + mSigningTime = SecTrustGetVerifyTime(mTrust); + + // Validate the cert chain SecTrustResultType trustResult; MacOSError::check(SecTrustEvaluate(mTrust, &trustResult)); - MacOSError::check(SecTrustGetResult(mTrust, &trustResult, &mCertChain.aref(), &mEvalDetails)); - // if this is an Apple developer cert.... - if (teamID() && SecStaticCode::isAppleDeveloperCert(mCertChain)) { - CFRef teamIDFromCert; - if (CFArrayGetCount(mCertChain) > 0) { - /* Note that SecCertificateCopySubjectComponent sets the out parameter to NULL if there is no field present */ - MacOSError::check(SecCertificateCopySubjectComponent((SecCertificateRef)CFArrayGetValueAtIndex(mCertChain, Requirement::leafCert), - &CSSMOID_OrganizationalUnitName, - &teamIDFromCert.aref())); - - if (teamIDFromCert) { - CFRef teamIDFromCD = CFStringCreateWithCString(NULL, teamID(), kCFStringEncodingUTF8); - if (!teamIDFromCD) { - Security::Syslog::error("Could not get team identifier (%s)", teamID()); - MacOSError::throwMe(errSecCSInvalidTeamIdentifier); - } - - if (CFStringCompare(teamIDFromCert, teamIDFromCD, 0) != kCFCompareEqualTo) { - Security::Syslog::error("Team identifier in the signing certificate (%s) does not match the team identifier (%s) in the code directory", - cfString(teamIDFromCert).c_str(), teamID()); - MacOSError::throwMe(errSecCSBadTeamIdentifier); - } - } - } + // retrieve auxiliary data bag and verify against current state + CFRef hashBag; + hashBag = CFDataRef(CFDictionaryGetValue(attrs, kSecCMSHashAgility)); + if (hashBag) { + CFRef hashDict = makeCFDictionaryFrom(hashBag); + CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); + CFArrayRef myCdList = this->cdHashes(); + if (cdList == NULL || !CFEqual(cdList, myCdList)) + MacOSError::throwMe(errSecCSSignatureFailed); } - CODESIGN_EVAL_STATIC_SIGNATURE_RESULT(this, trustResult, mCertChain ? (int)CFArrayGetCount(mCertChain) : 0); - switch (trustResult) { - case kSecTrustResultProceed: - case kSecTrustResultUnspecified: - break; // success - case kSecTrustResultDeny: - MacOSError::throwMe(CSSMERR_APPLETP_TRUST_SETTING_DENY); // user reject - case kSecTrustResultInvalid: - assert(false); // should never happen - MacOSError::throwMe(CSSMERR_TP_NOT_TRUSTED); - default: - { - OSStatus result; - MacOSError::check(SecTrustGetCssmResultCode(mTrust, &result)); - // if we have a valid timestamp, CMS validates against (that) signing time and all is well. - // If we don't have one, may validate against *now*, and must be able to tolerate expiration. - if (mSigningTimestamp == 0) { // no timestamp available - if (((result == CSSMERR_TP_CERT_EXPIRED) || (result == CSSMERR_TP_CERT_NOT_VALID_YET)) - && !(actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED)) { - CODESIGN_EVAL_STATIC_SIGNATURE_EXPIRED(this); - actionData.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED; // (this also allows postdated certs) - continue; // retry validation while tolerating expiration - } - } - if (checkfix41082220(result)) { - break; // success - } - Security::Syslog::error("SecStaticCode: verification failed (trust result %d, error %d)", trustResult, (int)result); - MacOSError::throwMe(result); - } - } + /* + * Populate mCertChain with the certs. If we failed validation, the + * signer's cert will be checked installed provisioning profiles as an + * alternative to verification against the policy for store-signed binaries + */ + mCertChain.take(copyCertChain(mTrust)); - if (mSigningTimestamp) { - CFIndex rootix = CFArrayGetCount(mCertChain); - if (SecCertificateRef mainRoot = SecCertificateRef(CFArrayGetValueAtIndex(mCertChain, rootix-1))) - if (isAppleCA(mainRoot)) { - // impose policy: if the signature itself draws to Apple, then so must the timestamp signature - CFRef tsCerts; - OSStatus result = CMSDecoderCopySignerTimestampCertificates(cms, 0, &tsCerts.aref()); - if (result) { - Security::Syslog::error("SecStaticCode: could not get timestamp certificates (error %d)", (int)result); - MacOSError::check(result); - } - CFIndex tsn = CFArrayGetCount(tsCerts); - bool good = tsn > 0 && isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(tsCerts, tsn-1))); - if (!good) { - result = CSSMERR_TP_NOT_TRUSTED; - Security::Syslog::error("SecStaticCode: timestamp policy verification failed (error %d)", (int)result); - MacOSError::throwMe(result); - } - } - } + // Did we implicitly trust the signer? + mTrustedSigningCertChain = (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed); - return actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED; + return false; // XXX: Not checking for expired certs } -#else - // Do some pre-verification initialization - CFDataRef sig = this->signature(); - this->codeDirectory(); // load CodeDirectory (sets mDir) - mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) - - CFRef attrs; - CFRef vf_policies(createVerificationPolicies()); - - // Verify the CMS signature against mBaseDir (SHA1) - MacOSError::check(SecCMSVerifyCopyDataAndAttributes(sig, mBaseDir, vf_policies, &mTrust.aref(), NULL, &attrs.aref())); - - // Copy the signing time - mSigningTime = SecTrustGetVerifyTime(mTrust); - - // Validate the cert chain - SecTrustResultType trustResult; - MacOSError::check(SecTrustEvaluate(mTrust, &trustResult)); - - // retrieve auxiliary data bag and verify against current state - CFRef hashBag; - hashBag = CFDataRef(CFDictionaryGetValue(attrs, kSecCMSHashAgility)); - if (hashBag) { - CFRef hashDict = makeCFDictionaryFrom(hashBag); - CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); - CFArrayRef myCdList = this->cdHashes(); - if (cdList == NULL || !CFEqual(cdList, myCdList)) - MacOSError::throwMe(errSecCSSignatureFailed); - } - - /* - * Populate mCertChain with the certs. If we failed validation, the - * signer's cert will be checked installed provisioning profiles as an - * alternative to verification against the policy for store-signed binaries - */ - SecCertificateRef leafCert = SecTrustGetCertificateAtIndex(mTrust, 0); - if (leafCert != NULL) { - CFIndex count = SecTrustGetCertificateCount(mTrust); - - CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, count, - &kCFTypeArrayCallBacks); - - CFArrayAppendValue(certs, leafCert); - for (CFIndex i = 1; i < count; ++i) { - CFArrayAppendValue(certs, SecTrustGetCertificateAtIndex(mTrust, i)); - } - - mCertChain.take((CFArrayRef)certs); - } - - // Did we implicitly trust the signer? - mTrustedSigningCertChain = (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed); - - return false; // XXX: Not checking for expired certs -#endif } #if TARGET_OS_OSX @@ -1077,6 +1111,23 @@ static SecPolicyRef makeRevocationPolicy(CFOptionFlags flags) } #endif +bool SecStaticCode::validationCannotUseNetwork() +{ + bool blockNetwork = false; + bool validationEnablesNetwork = ((mValidationFlags & kSecCSAllowNetworkAccess) != 0); + bool validationDisablesNetwork = ((mValidationFlags & kSecCSNoNetworkAccess) != 0); + + if (mNetworkEnabledByDefault) { + // If network is enabled by default, block it only if the flags explicitly block. + blockNetwork = validationDisablesNetwork; + } else { + // If network is disabled by default, block it if the flags don't explicitly enable it. + blockNetwork = !validationEnablesNetwork; + } + secinfo("staticCode", "SecStaticCode network allowed: %s", blockNetwork ? "NO" : "YES"); + return blockNetwork; +} + CFArrayRef SecStaticCode::createVerificationPolicies() { if (mValidationFlags & kSecCSUseSoftwareSigningCert) { @@ -1084,10 +1135,15 @@ CFArrayRef SecStaticCode::createVerificationPolicies() return makeCFArray(1, ssRef.get()); } #if TARGET_OS_OSX + if (mValidationFlags & kSecCSApplyEmbeddedPolicy) { + CFRef iOSRef = SecPolicyCreateiPhoneApplicationSigning(); + return makeCFArray(1, iOSRef.get()); + } + CFRef core; MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_CODE_SIGNING, &core.aref())); - if (mValidationFlags & kSecCSNoNetworkAccess) { + if (validationCannotUseNetwork()) { // Skips all revocation since they require network connectivity // therefore annihilates kSecCSEnforceRevocationChecks if present CFRef no_revoc = makeRevocationPolicy(kSecRevocationNetworkAccessDisabled); @@ -1114,7 +1170,7 @@ CFArrayRef SecStaticCode::createTimeStampingAndRevocationPolicies() { CFRef tsPolicy = SecPolicyCreateAppleTimeStamping(); #if TARGET_OS_OSX - if (mValidationFlags & kSecCSNoNetworkAccess) { + if (validationCannotUseNetwork()) { // Skips all revocation since they require network connectivity // therefore annihilates kSecCSEnforceRevocationChecks if present CFRef no_revoc = makeRevocationPolicy(kSecRevocationNetworkAccessDisabled); @@ -1134,6 +1190,25 @@ CFArrayRef SecStaticCode::createTimeStampingAndRevocationPolicies() } +CFArrayRef SecStaticCode::copyCertChain(SecTrustRef trust) +{ + SecCertificateRef leafCert = SecTrustGetCertificateAtIndex(trust, 0); + if (leafCert != NULL) { + CFIndex count = SecTrustGetCertificateCount(trust); + + CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, count, + &kCFTypeArrayCallBacks); + + CFArrayAppendValue(certs, leafCert); + for (CFIndex i = 1; i < count; ++i) { + CFArrayAppendValue(certs, SecTrustGetCertificateAtIndex(trust, i)); + } + + return certs; + } + return NULL; +} + // // Validate a particular sealed, cached resource against its (special) CodeDirectory slot. @@ -1214,7 +1289,6 @@ void SecStaticCode::validateExecutable() MacOSError::throwMe(mExecutableValidResult); } - // // Perform static validation of sealed resources and nested code. // @@ -1242,6 +1316,17 @@ void SecStaticCode::validateResources(SecCSFlags flags) } if (doit) { + string root = cfStringRelease(copyCanonicalPath()); + bool itemIsOnRootFS = itemQualifiesForResourceExemption(root); + bool skipRootVolumeExceptions = (mValidationFlags & kSecCSSkipRootVolumeExceptions); + bool useRootFSPolicy = itemIsOnRootFS && !skipRootVolumeExceptions; + + bool itemMightUseXattrFiles = pathFileSystemUsesXattrFiles(root.c_str()); + bool skipXattrFiles = itemMightUseXattrFiles && (mValidationFlags & kSecCSSkipXattrFiles); + + secinfo("staticCode", "performing resource validation for %s (%d, %d, %d, %d, %d)", root.c_str(), + itemIsOnRootFS, skipRootVolumeExceptions, useRootFSPolicy, itemMightUseXattrFiles, skipXattrFiles); + if (mLimitedAsync == NULL) { bool runMultiThreaded = ((flags & kSecCSSingleThreaded) == kSecCSSingleThreaded) ? false : (diskRep()->fd().mediumType() == kIOPropertyMediumTypeSolidStateKey); @@ -1264,13 +1349,15 @@ void SecStaticCode::validateResources(SecCSFlags flags) // check for weak resource rules bool strict = flags & kSecCSStrictValidate; - if (strict) { - if (hasWeakResourceRules(rules, version, mAllowOmissions)) - if (mTolerateErrors.find(errSecCSWeakResourceRules) == mTolerateErrors.end()) - MacOSError::throwMe(errSecCSWeakResourceRules); - if (version == 1) - if (mTolerateErrors.find(errSecCSWeakResourceEnvelope) == mTolerateErrors.end()) - MacOSError::throwMe(errSecCSWeakResourceEnvelope); + if (!useRootFSPolicy) { + if (strict) { + if (hasWeakResourceRules(rules, version, mAllowOmissions)) + if (mTolerateErrors.find(errSecCSWeakResourceRules) == mTolerateErrors.end()) + MacOSError::throwMe(errSecCSWeakResourceRules); + if (version == 1) + if (mTolerateErrors.find(errSecCSWeakResourceEnvelope) == mTolerateErrors.end()) + MacOSError::throwMe(errSecCSWeakResourceEnvelope); + } } Dispatch::Group group; @@ -1283,23 +1370,99 @@ void SecStaticCode::validateResources(SecCSFlags flags) this->mResourceScope = &resources; diskRep()->adjustResources(resources); - resources.scan(^(FTSENT *ent, uint32_t ruleFlags, const string relpath, ResourceBuilder::Rule *rule) { + void (^unhandledScanner)(FTSENT *, uint32_t , const string, ResourceBuilder::Rule *) = nil; + + if (isFlagSet(flags, kSecCSEnforceRevocationChecks)) { + unhandledScanner = ^(FTSENT *ent, uint32_t ruleFlags, const string relpath, ResourceBuilder::Rule *rule) { + bool userControlledRule = ((ruleFlags & ResourceBuilder::user_controlled) == ResourceBuilder::user_controlled); + secinfo("staticCode", "Visiting unhandled file: %d, %s", userControlledRule, relpath.c_str()); + if (!userControlledRule) { + // No need to look at exemptions added by the runtime rule adjustments (ex. main executable). + return; + } + + CFRef validationURL; + bool doValidation = false; + switch (ent->fts_info) { + case FTS_SL: + char resolved[PATH_MAX]; + if (realpath(ent->fts_path, resolved)) { + doValidation = true; + validationURL.take(makeCFURL(resolved)); + secinfo("staticCode", "Checking symlink target: %s", resolved); + } else { + secerror("realpath failed checking symlink: %d", errno); + } + break; + case FTS_F: + doValidation = true; + validationURL.take(makeCFURL(relpath, false, resourceBase())); + break; + default: + // Unexpected type for the unhandled scanner. + doValidation = false; + secerror("Unexpected scan input: %d, %s", ent->fts_info, relpath.c_str()); + break; + } + + if (doValidation) { + // Here we yield our reference to hand over to the block's CFRef object, which will + // hold it until the block is complete and also handle releasing in case of an exception. + CFURLRef transferURL = validationURL.yield(); + + void (^validate)() = ^{ + CFRef localURL = transferURL; + AutoFileDesc fd(cfString(localURL), O_RDONLY, FileDesc::modeMissingOk); + checkRevocationOnNestedBinary(fd, localURL, flags); + }; + mLimitedAsync->perform(groupRef, validate); + } + }; + } + + void (^validationScanner)(FTSENT *, uint32_t , const string, ResourceBuilder::Rule *) = ^(FTSENT *ent, uint32_t ruleFlags, const string relpath, ResourceBuilder::Rule *rule) { CFDictionaryRemoveValue(resourceMap, CFTempString(relpath)); bool isSymlink = (ent->fts_info == FTS_SL); void (^validate)() = ^{ - validateResource(files, relpath, isSymlink, *mResourcesValidContext, flags, version); + bool needsValidation = true; + + if (skipXattrFiles && pathIsValidXattrFile(cfString(resourceBase()) + "/" + relpath, "staticCode")) { + secinfo("staticCode", "resource validation on xattr file skipped: %s", relpath.c_str()); + needsValidation = false; + } + + if (useRootFSPolicy) { + CFRef itemURL = makeCFURL(relpath, false, resourceBase()); + string itemPath = cfString(itemURL); + if (itemQualifiesForResourceExemption(itemPath)) { + secinfo("staticCode", "resource validation on root volume skipped: %s", itemPath.c_str()); + needsValidation = false; + } + } + + if (needsValidation) { + secinfo("staticCode", "performing resource validation on item: %s", relpath.c_str()); + validateResource(files, relpath, isSymlink, *mResourcesValidContext, flags, version); + } reportProgress(); }; mLimitedAsync->perform(groupRef, validate); - }); + }; + + resources.scan(validationScanner, unhandledScanner); group.wait(); // wait until all async resources have been validated as well - unsigned leftovers = unsigned(CFDictionaryGetCount(resourceMap)); - if (leftovers > 0) { - secinfo("staticCode", "%d sealed resource(s) not found in code", int(leftovers)); - CFDictionaryApplyFunction(resourceMap, SecStaticCode::checkOptionalResource, mResourcesValidContext); + if (useRootFSPolicy) { + // It's ok to allow leftovers on the root filesystem for now. + } else { + // Look through the leftovers and make sure they're all properly optional resources. + unsigned leftovers = unsigned(CFDictionaryGetCount(resourceMap)); + if (leftovers > 0) { + secinfo("staticCode", "%d sealed resource(s) not found in code", int(leftovers)); + CFDictionaryApplyFunction(resourceMap, SecStaticCode::checkOptionalResource, mResourcesValidContext); + } } // now check for any errors found in the reporting context @@ -1521,9 +1684,9 @@ CFDictionaryRef SecStaticCode::getDictionary(CodeDirectory::SpecialSlot slot, bo // // // -CFDictionaryRef SecStaticCode::diskRepInformation() +CFDictionaryRef SecStaticCode::copyDiskRepInformation() { - return mRep->diskRepInformation(); + return mRep->copyDiskRepInformation(); } bool SecStaticCode::checkfix30814861(string path, bool addition) { @@ -1533,9 +1696,9 @@ bool SecStaticCode::checkfix30814861(string path, bool addition) { // We started signing correctly in 2014, 9.0 was first seeded mid-2016. - CFRef inf = diskRepInformation(); + CFRef inf = copyDiskRepInformation(); try { - CFDictionary info(diskRepInformation(), errSecCSNotSupported); + CFDictionary info(inf.get(), errSecCSNotSupported); uint32_t platform = cfNumber(info.get(kSecCodeInfoDiskRepVersionPlatform, errSecCSNotSupported), 0); uint32_t sdkVersion = @@ -1612,19 +1775,22 @@ void SecStaticCode::validateResource(CFDictionaryRef files, string path, bool is ResourceSeal seal(file); const ResourceSeal& rseal = seal; if (seal.nested()) { - if (isSymlink) + if (isSymlink) { return ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // changed type + } string suffix = ".framework"; - bool isFramework = (path.length() > suffix.length()) - && (path.compare(path.length()-suffix.length(), suffix.length(), suffix) == 0); + bool isFramework = (path.length() > suffix.length()) && + (path.compare(path.length()-suffix.length(), suffix.length(), suffix) == 0); validateNestedCode(fullpath, seal, flags, isFramework); } else if (seal.link()) { - if (!isSymlink) + if (!isSymlink) { return ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // changed type + } validateSymlinkResource(cfString(fullpath), cfString(seal.link()), ctx, flags); } else if (seal.hash(hashAlgorithm())) { // genuine file - if (isSymlink) + if (isSymlink) { return ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // changed type + } AutoFileDesc fd(cfString(fullpath), O_RDONLY, FileDesc::modeMissingOk); // open optional file if (fd) { __block bool good = true; @@ -1639,14 +1805,20 @@ void SecStaticCode::validateResource(CFDictionaryRef files, string path, bool is ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // altered } } + + if (good && isFlagSet(flags, kSecCSEnforceRevocationChecks)) { + checkRevocationOnNestedBinary(fd, fullpath, flags); + } } else { - if (!seal.optional()) + if (!seal.optional()) { ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceMissing, fullpath); // was sealed but is now missing - else + } else { return; // validly missing + } } - } else + } else { ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // changed type + } return; } if (version == 1) { // version 1 ignores symlinks altogether @@ -1731,6 +1903,44 @@ void SecStaticCode::validateSymlinkResource(std::string fullpath, std::string se } } +/// Uses the provided file descriptor to check if the file is macho, and if so validates the file at the url as a binary to check for a revoked certificate. +void SecStaticCode::checkRevocationOnNestedBinary(UnixPlusPlus::FileDesc &fd, CFURLRef url, SecCSFlags flags) +{ +#if TARGET_OS_OSX + secinfo("staticCode", "validating embedded resource: %@", url); + + try { + SecPointer code; + + if (MachORep::candidate(fd)) { + DiskRep *rep = new MachORep(cfString(url).c_str(), NULL); + if (rep) { + code = new SecStaticCode(rep); + } + } + + if (code) { + code->initializeFromParent(*this); + code->setValidationFlags(flags); + // Validate just the code directory, which performs signature validation. + code->validateDirectory(); + secinfo("staticCode", "successfully validated nested resource binary: %@", url); + } + } catch (const MacOSError &err) { + if (err.error == CSSMERR_TP_CERT_REVOKED) { + secerror("Rejecting binary with revoked certificate: %@", url); + throw; + } else { + // Any other errors, but only revocation checks are fatal so just continue. + secinfo("staticCode", "Found unexpected error other error validating resource binary: %d, %@", err.error, url); + } + } +#else + // This type of resource checking doesn't make sense on embedded devices right now, so just do nothing. + return; +#endif // TARGET_OS_OSX +} + void SecStaticCode::validateNestedCode(CFURLRef path, const ResourceSeal &seal, SecCSFlags flags, bool isFramework) { CFRef req; @@ -1739,8 +1949,9 @@ void SecStaticCode::validateNestedCode(CFURLRef path, const ResourceSeal &seal, // recursively verify this nested code try { - if (!(flags & kSecCSCheckNestedCode)) + if (!(flags & kSecCSCheckNestedCode)) { flags |= kSecCSBasicValidateOnly | kSecCSQuickCheck; + } SecPointer code = new SecStaticCode(DiskRep::bestGuess(cfString(path))); code->initializeFromParent(*this); code->staticValidate(flags & (~kSecCSRestrictToAppLike), SecRequirement::required(req)); @@ -2070,7 +2281,7 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) //DR not currently supported on iOS #if TARGET_OS_OSX - try { + try { if (const Requirements *reqs = this->internalRequirements()) { CFDictionaryAddValue(dict, kSecCodeInfoRequirements, CFTempString(Dumper::dump(reqs))); @@ -2090,10 +2301,26 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) #endif try { - if (CFDataRef ent = this->component(cdEntitlementSlot)) { - CFDictionaryAddValue(dict, kSecCodeInfoEntitlements, ent); - if (CFDictionaryRef entdict = this->entitlements()) - CFDictionaryAddValue(dict, kSecCodeInfoEntitlementsDict, entdict); + if (CFDataRef ent = this->component(cdEntitlementSlot)) { + CFDictionaryAddValue(dict, kSecCodeInfoEntitlements, ent); + if (CFDictionaryRef entdict = this->entitlements()) { + if (needsCatalystEntitlementFixup(entdict)) { + // If this entitlement dictionary needs catalyst entitlements, make a copy and stick that into the + // output dictionary instead. + secinfo("staticCode", "%p fixed catalyst entitlements", this); + CFRef tempEntitlements = makeCFMutableDictionary(entdict); + updateCatalystEntitlements(tempEntitlements); + CFRef newEntitlements = CFDictionaryCreateCopy(NULL, tempEntitlements); + if (newEntitlements) { + CFDictionaryAddValue(dict, kSecCodeInfoEntitlementsDict, newEntitlements.get()); + } else { + secerror("%p unable to fixup entitlement dictionary", this); + CFDictionaryAddValue(dict, kSecCodeInfoEntitlementsDict, entdict); + } + } else { + CFDictionaryAddValue(dict, kSecCodeInfoEntitlementsDict, entdict); + } + } } } catch (...) { } @@ -2112,7 +2339,7 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) if (CFRef rdict = getDictionary(cdResourceDirSlot, false)) // suppress validation CFDictionaryAddValue(dict, kSecCodeInfoResourceDirectory, rdict); } - if (CFRef ddict = diskRepInformation()) + if (CFRef ddict = copyDiskRepInformation()) CFDictionaryAddValue(dict, kSecCodeInfoDiskRepInfo, ddict); } catch (...) { } if (mNotarizationChecked && !isnan(mNotarizationDate)) { @@ -2123,6 +2350,10 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) secerror("Error creating date from timestamp: %f", mNotarizationDate); } } + if (this->codeDirectory()) { + uint32_t version = this->codeDirectory()->version; + CFDictionaryAddValue(dict, kSecCodeInfoSignatureVersion, CFTempNumber(version)); + } } if (flags & kSecCSCalculateCMSDigest) { @@ -2210,7 +2441,7 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) mStaplingChecked = true; } - if (mFlags & kSecCSForceOnlineNotarizationCheck) { + if (isFlagSet(mFlags, kSecCSForceOnlineNotarizationCheck) && !validationCannotUseNetwork()) { if (!mNotarizationChecked) { if (this->cdHash()) { bool is_revoked = checkNotarizationServiceForRevocation(this->cdHash(), (SecCSDigestAlgorithm)this->hashAlgorithm(), &mNotarizationDate); @@ -2224,13 +2455,13 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) #endif // TARGET_OS_OSX // initialize progress/cancellation state - if (flags & kSecCSReportProgress) + if (flags & kSecCSReportProgress) { prepareProgress(estimateResourceWorkload() + 2); // +1 head, +1 tail - + } // core components: once per architecture (if any) this->staticValidateCore(flags, req); - if (flags & kSecCSCheckAllArchitectures) + if (flags & kSecCSCheckAllArchitectures) { handleOtherArchitectures(^(SecStaticCode* subcode) { if (flags & kSecCSCheckGatekeeperArchitectures) { Universal *fat = subcode->diskRep()->mainExecutableImage(); @@ -2242,19 +2473,21 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) subcode->detachedSignature(this->mDetachedSig); // carry over explicit (but not implicit) detached signature subcode->staticValidateCore(flags, req); }); + } reportProgress(); // allow monitor intervention in source validation phase reportEvent(CFSTR("prepared"), NULL); // resources: once for all architectures - if (!(flags & kSecCSDoNotValidateResources)) + if (!(flags & kSecCSDoNotValidateResources)) { this->validateResources(flags); + } // perform strict validation if desired if (flags & kSecCSStrictValidate) { mRep->strictValidate(codeDirectory(), mTolerateErrors, mValidationFlags); - reportProgress(); + reportProgress(); } else if (flags & kSecCSStrictValidateStructure) { mRep->strictValidateStructure(codeDirectory(), mTolerateErrors, mValidationFlags); } @@ -2296,6 +2529,173 @@ void SecStaticCode::staticValidateCore(SecCSFlags flags, const SecRequirement *r } } +void SecStaticCode::staticValidateResource(string resourcePath, SecCSFlags flags, const SecRequirement *req) +{ + // resourcePath is always the absolute path to the resource, each analysis can make a relative path + // if it needs one. Passing through relative paths but then needing to re-create the full path is + // more complicated in the case where a subpath is no longer contained within the resource envelope + // of the next subcode. + + // Validate the resource is inside the outer bundle by finding the bundle's resource path in the string + // of the full resource. If its a prefix match this will also compute the remaining relative path + // that we'll need later. + string baseResourcePath; + string relativePath; + + if (this->mainExecutablePath() == resourcePath) { + // Nothing to do here, we're just validating the main executable so proceed + // to the validation below. + } else { + baseResourcePath = cfString(resourceBase()); + relativePath = pathRemaining(resourcePath, baseResourcePath); + if (relativePath == "") { + // The resource is not a prefix match with the bundle or the arguments are bad. + secerror("Requested resource was not within the code object: %s, %s", resourcePath.c_str(), baseResourcePath.c_str()); + MacOSError::throwMe(errSecParam); + } + } + + // In general, we never want to be validating executables of the bundles as we traverse, so just ensure the + // bit is always set to skip them as we go. + flags = addFlags(flags, kSecCSDoNotValidateExecutable); + + // First special case is the main executable, which means we're about to validate it as part of the + // static validation here. + bool needsAdditionalValidation = true; + if (this->mainExecutablePath() == resourcePath) { + needsAdditionalValidation = false; + + // If the caller did not request fast validation of an executable, ensure we clear the 'do + // not validate' bit here before validating. + if (!isFlagSet(flags, kSecCSFastExecutableValidation)) { + flags = clearFlags(flags, kSecCSDoNotValidateExecutable); + } + } + + // The Info.plist is covered by the core validation, so there's no more work to be done. + if (relativePath == "Info.plist") { + needsAdditionalValidation = false; + } + + // Perform basic validation of the code object itself, since thats required for the rest of the comparison + // to be valid. + this->staticValidateCore(flags, NULL); + if (req) { + // If we have an explicit requirement we must meet and fail, then it should actually + // be recorded as the resource being modified. + this->validateRequirement(req->requirement(), errSecCSBadResource); + } + + if (!needsAdditionalValidation) { + // staticValidateCore has already validated the main executable so we're all done! + return; + } + + if (!isFlagSet(flags, kSecCSSkipRootVolumeExceptions)) { + if (itemQualifiesForResourceExemption(resourcePath)) { + secinfo("staticCode", "Requested resource was on root filesystem: %s", resourcePath.c_str()); + return; + } + } + + // We need to load resource rules to be able to do a single file resource comparison against. + CFDictionaryRef rules; + CFDictionaryRef files; + uint32_t version; + if (!loadResources(rules, files, version)) { + MacOSError::throwMe(errSecCSResourcesNotFound); + } + + // Load up a full resource builder so we can properly parse all the rules. + bool strict = (flags & kSecCSStrictValidate); + MacOSErrorSet toleratedErrors; + ResourceBuilder resources(baseResourcePath, baseResourcePath, rules, strict, toleratedErrors); + diskRep()->adjustResources(resources); + + // First, check if the path itself is inside of an omission or exclusion hole. + ResourceBuilder::Rule *rule = resources.findRule(relativePath); + if (rule) { + if (rule->flags & (ResourceBuilder::omitted | ResourceBuilder::exclusion)) { + secerror("Requested resource was not sealed: %d", rule->flags); + MacOSError::throwMe(errSecCSResourcesNotSealed); + } + } + + // Otherwise look for an exact file match, or find the most deeply nested code. + CFTypeRef file = CFDictionaryGetValue(files, CFTempString(relativePath)); + if (file) { + // This item matched a file rule exactly, so just validate it directly with this object. + AutoFileDesc fd = AutoFileDesc(resourcePath); + bool isSymlink = fd.isA(S_IFLNK); + + // Since this is a direct file match, if its for a nested bundle then we want to enable executable + // validation based on whether fast executable validation was requested. + if (!isFlagSet(flags, kSecCSFastExecutableValidation)) { + flags = clearFlags(flags, kSecCSDoNotValidateExecutable); + } + + ResourceSeal seal(file); + if (seal.nested()) { + CFRef req; + if (SecRequirementCreateWithString(seal.requirement(), kSecCSDefaultFlags, &req.aref())) { + MacOSError::throwMe(errSecCSResourcesInvalid); + } + + // If the resource seal indicates this is nested code, create a new code object for this + // nested code and then validate the resource within that object. + SecPointer subcode = new SecStaticCode(DiskRep::bestGuess(resourcePath)); + subcode->initializeFromParent(*this); + // If there was an exact match but its nested code, then the ask is really to validate the + // main executable of the nested code. + subcode->staticValidateResource(subcode->mainExecutablePath(), flags, SecRequirement::required(req)); + } else { + // For other resource types, just a single file resource validation with a ValidationContext that + // will immediately throw an error if any issues are encountered. + ValidationContext *context = new ValidationContext(*this); + validateResource(files, relativePath, isSymlink, *context, flags, version); + } + } else { + // It wasn't a simple file resource within the current code signature, so we're looking for a nested code. + __block bool itemFound = false; + + // Iterate through the largest possible chunks of paths looking for nested code matches. + iterateLargestSubpaths(relativePath, ^bool(string subpath) { + CFTypeRef file = CFDictionaryGetValue(files, CFTempString(subpath)); + if (file) { + itemFound = true; + + ResourceSeal seal(file); + if (seal.nested()) { + CFRef req; + if (SecRequirementCreateWithString(seal.requirement(), kSecCSDefaultFlags, &req.aref())) { + MacOSError::throwMe(errSecCSResourcesInvalid); + } + + // If the resource seal indicates this is nested code, create a new code object for this + // nested code and then validate the resource within that object. + CFRef itemURL = makeCFURL(subpath, false, resourceBase()); + string fullPath = cfString(itemURL); + SecPointer subcode = new SecStaticCode(DiskRep::bestGuess(fullPath)); + subcode->initializeFromParent(*this); + subcode->staticValidateResource(resourcePath, flags, SecRequirement::required(req)); + } else { + // Any other type of nested resource is not ok, so just bail. + secerror("Unexpected item hit traversing resource: %@", file); + MacOSError::throwMe(errSecCSBadResource); + } + // If we find a match, stop walking up for further matching. + return true; + } + return false; + }); + + // If we finished everything and didn't find the item, its not a valid resource. + if (!itemFound) { + secerror("Requested resource was not found: %s", resourcePath.c_str()); + MacOSError::throwMe(errSecCSBadResource); + } + } +} // // A helper that generates SecStaticCode objects for all but the primary architecture @@ -2317,6 +2717,12 @@ void SecStaticCode::handleOtherArchitectures(void (^handle)(SecStaticCode* other ctx.size = fat->lengthOfSlice(int_cast(ctx.offset)); if (ctx.offset != activeOffset) { // inactive architecture; check it SecPointer subcode = new SecStaticCode(DiskRep::bestGuess(this->mainExecutablePath(), &ctx)); + + // There may not actually be a full validation happening, but any operations that do occur should respect the + // same network settings as the existing validation, so propagate those flags forward here. + SecCSFlags flagsToPropagate = (kSecCSAllowNetworkAccess | kSecCSNoNetworkAccess); + subcode->setValidationFlags(mValidationFlags & flagsToPropagate); + subcode->detachedSignature(this->mDetachedSig); // carry over explicit (but not implicit) detached signature if (this->teamID() == NULL || subcode->teamID() == NULL) { if (this->teamID() != subcode->teamID()) diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.h b/OSX/libsecurity_codesigning/lib/StaticCode.h index 56726824..7fbbeb08 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.h +++ b/OSX/libsecurity_codesigning/lib/StaticCode.h @@ -107,7 +107,7 @@ public: static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL if static SecStaticCode(DiskRep *rep, uint32_t flags = 0); - virtual ~SecStaticCode() throw(); + virtual ~SecStaticCode() _NOEXCEPT; void initializeFromParent(const SecStaticCode& parent); @@ -140,7 +140,7 @@ public: std::string signatureSource(); virtual CFDataRef component(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); virtual CFDictionaryRef infoDictionary(); - CFDictionaryRef diskRepInformation(); + CFDictionaryRef copyDiskRepInformation(); CFDictionaryRef entitlements(); CFDataRef copyComponent(CodeDirectory::SpecialSlot slot, CFDataRef hash); @@ -156,7 +156,9 @@ public: void setMonitor(SecCodeCallback monitor) { mMonitor = monitor; } CFTypeRef reportEvent(CFStringRef stage, CFDictionaryRef info); void reportProgress(unsigned amount = 1); - + + SecCSFlags getFlags() { return mFlags; } + void setFlags(SecCSFlags flags) { mFlags = flags; } void setValidationFlags(SecCSFlags flags) { mValidationFlags = flags; } void setValidationModifiers(CFDictionaryRef modifiers); @@ -180,6 +182,8 @@ public: void validateResources(SecCSFlags flags); void validateExecutable(); void validateNestedCode(CFURLRef path, const ResourceSeal &seal, SecCSFlags flags, bool isFramework); + void checkRevocationOnNestedBinary(UnixPlusPlus::FileDesc &fd, CFURLRef url, SecCSFlags flags); + bool validationCannotUseNetwork(); void validatePlainMemoryResource(string path, CFDataRef fileData, SecCSFlags flags); @@ -200,9 +204,7 @@ public: CFDictionaryRef signingInformation(SecCSFlags flags); // omnibus information-gathering API (creates new dictionary) static bool isAppleDeveloperCert(CFArrayRef certs); // determines if this is an apple developer certificate for library validation -#if !TARGET_OS_OSX bool trustedSigningCertChain() { return mTrustedSigningCertChain; } -#endif void handleOtherArchitectures(void (^handle)(SecStaticCode* other)); @@ -211,6 +213,7 @@ public: public: void staticValidate(SecCSFlags flags, const SecRequirement *req); void staticValidateCore(SecCSFlags flags, const SecRequirement *req); + void staticValidateResource(string resourcePath, SecCSFlags flags, const SecRequirement *req); protected: bool loadCodeDirectories(CodeDirectoryMap& cdMap) const; @@ -231,6 +234,7 @@ private: void validateOtherVersions(CFURLRef path, SecCSFlags flags, SecRequirementRef req, SecStaticCode *code); bool checkfix30814861(string path, bool addition); bool checkfix41082220(OSStatus result); + CFArrayRef copyCertChain(SecTrustRef trust); ResourceBuilder *mCheckfix30814861builder1; dispatch_once_t mCheckfix30814861builder1_once; @@ -298,20 +302,16 @@ private: LimitedAsync *mLimitedAsync; // limited async workers for verification - uint32_t mFlags; // flags from creation + SecCSFlags mFlags; // flags from creation bool mNotarizationChecked; // ensure notarization check only performed once bool mStaplingChecked; // ensure stapling check only performed once double mNotarizationDate; // the notarization ticket's date, if online check failed + bool mNetworkEnabledByDefault; // whether this code object uses the network by default // signature verification outcome (mTrust == NULL => not done yet) CFRef mTrust; // outcome of crypto validation (valid or not) CFRef mCertChain; -#if TARGET_OS_OSX - CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails; -#else bool mTrustedSigningCertChain; -#endif - }; diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp index 7c490970..8afdf40f 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp @@ -24,6 +24,7 @@ #include "filediskrep.h" #include "dirscanner.h" #include "notarization.h" +#include "csutilities.h" #include #include #include @@ -198,7 +199,7 @@ void BundleDiskRep::setup(const Context *ctx) // we're getting desperate here. Perhaps an oldish-style installer package? Look for a *.dist file std::string distFile = findDistFile(this->resourcesRootPath()); if (!distFile.empty()) { - mMainExecutableURL = makeCFURL(distFile); + mMainExecutableURL.take(makeCFURL(distFile)); mExecRep = new FileDiskRep(this->mainExecutablePath().c_str()); checkPlainFile(mExecRep->fd(), this->mainExecutablePath()); mInstallerPackage = true; @@ -541,9 +542,9 @@ void BundleDiskRep::flush() mExecRep->flush(); } -CFDictionaryRef BundleDiskRep::diskRepInformation() +CFDictionaryRef BundleDiskRep::copyDiskRepInformation() { - return mExecRep->diskRepInformation(); + return mExecRep->copyDiskRepInformation(); } // @@ -728,7 +729,7 @@ void BundleDiskRep::strictValidateStructure(const CodeDirectory* cd, const Toler { // scan our metadirectory (_CodeSignature) for unwanted guests if (!(flags & kSecCSQuickCheck)) - validateMetaDirectory(cd); + validateMetaDirectory(cd, flags); // check accumulated strict errors and report them if (!(flags & kSecCSRestrictSidebandData)) // tolerate resource forks etc. @@ -752,7 +753,7 @@ void BundleDiskRep::recordStrictError(OSStatus error) } -void BundleDiskRep::validateMetaDirectory(const CodeDirectory* cd) +void BundleDiskRep::validateMetaDirectory(const CodeDirectory* cd, SecCSFlags flags) { // we know the resource directory will be checked after this call, so we'll give it a pass here if (cd->slotIsPresent(-cdResourceDirSlot)) @@ -771,6 +772,12 @@ void BundleDiskRep::validateMetaDirectory(const CodeDirectory* cd) break; } } + + bool shouldSkipXattrFiles = false; + if ((flags & kSecCSSkipXattrFiles) && pathFileSystemUsesXattrFiles(mMetaPath.c_str())) { + shouldSkipXattrFiles = true; + } + DirScanner scan(mMetaPath); if (scan.initialized()) { while (struct dirent* ent = scan.getNext()) { @@ -782,6 +789,9 @@ void BundleDiskRep::validateMetaDirectory(const CodeDirectory* cd) AutoFileDesc fd(metaPath(kSecCS_SIGNATUREFILE)); if (fd.fileSize() == 0) continue; // that's okay, then + } else if (shouldSkipXattrFiles && pathIsValidXattrFile(mMetaPath + "/" + ent->d_name, "bundlediskrep")) { + secinfo("bundlediskrep", "meta directory validation on xattr file skipped: %s", ent->d_name); + continue; } // not on list of needed files; it's a freeloading rogue! recordStrictError(errSecCSUnsealedAppRoot); // funnel through strict set so GKOpaque can override it diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.h b/OSX/libsecurity_codesigning/lib/bundlediskrep.h index af3e40e2..acbafed9 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.h +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.h @@ -80,7 +80,7 @@ public: CFArrayRef modifiedFiles(); UnixPlusPlus::FileDesc &fd(); void flush(); - CFDictionaryRef diskRepInformation(); + CFDictionaryRef copyDiskRepInformation(); std::string recommendedIdentifier(const SigningContext &ctx); CFDictionaryRef defaultResourceRules(const SigningContext &ctx); @@ -113,7 +113,7 @@ private: void checkModifiedFile(CFMutableArrayRef files, CodeDirectory::SpecialSlot slot); CFDataRef loadRegularFile(CFURLRef url); void recordStrictError(OSStatus error); - void validateMetaDirectory(const CodeDirectory* cd); + void validateMetaDirectory(const CodeDirectory* cd, SecCSFlags flags); void validateFrameworkRoot(std::string root); void checkPlainFile(UnixPlusPlus::FileDesc fd, const std::string& path); void checkForks(UnixPlusPlus::FileDesc fd); diff --git a/OSX/libsecurity_codesigning/lib/codedirectory.cpp b/OSX/libsecurity_codesigning/lib/codedirectory.cpp index 4d3c1c80..9c559dcd 100644 --- a/OSX/libsecurity_codesigning/lib/codedirectory.cpp +++ b/OSX/libsecurity_codesigning/lib/codedirectory.cpp @@ -419,5 +419,6 @@ const SecCodeDirectoryFlagTable kSecCodeDirectoryFlagTable[] = { { "enforcement", kSecCodeSignatureEnforcement, true }, { "library-validation", kSecCodeSignatureLibraryValidation, true }, { "runtime", kSecCodeSignatureRuntime, true }, + { "linker-signed", kSecCodeSignatureLinkerSigned, true }, { NULL } }; diff --git a/OSX/libsecurity_codesigning/lib/codesigning_dtrace.h b/OSX/libsecurity_codesigning/lib/codesigning_dtrace.h deleted file mode 100644 index e595630e..00000000 --- a/OSX/libsecurity_codesigning/lib/codesigning_dtrace.h +++ /dev/null @@ -1,1071 +0,0 @@ -/* - * Generated by dtrace(1M). - */ - -#ifndef _CODESIGNING_DTRACE_H -#define _CODESIGNING_DTRACE_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define CODESIGN_STABILITY "___dtrace_stability$codesign$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0" - -#define CODESIGN_TYPEDEFS "___dtrace_typedefs$codesign$v2" - -#if !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED - -#define CODESIGN_ALLOCATE_ARCH(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$allocate__arch$v1$63686172202a$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_ALLOCATE_ARCH_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$allocate__arch$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_ALLOCATE_ARCHN(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$allocate__archn$v1$756e7369676e6564$756e7369676e6564$756e7369676e6564(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_ALLOCATE_ARCHN_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$allocate__archn$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_ALLOCATE_VALIDATE(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$allocate__validate$v1$63686172202a$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_ALLOCATE_VALIDATE_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$allocate__validate$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_ALLOCATE_WRITE(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$allocate__write$v1$63686172202a$75696e7436345f74$756e7369676e6564$756e7369676e6564(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_ALLOCATE_WRITE_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$allocate__write$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DISKREP_CREATE_BUNDLE_PATH(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$diskrep__create__bundle__path$v1$766f6964202a$63686172202a$766f6964202a$766f6964202a(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DISKREP_CREATE_BUNDLE_PATH_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$diskrep__create__bundle__path$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DISKREP_CREATE_BUNDLE_REF(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$diskrep__create__bundle__ref$v1$766f6964202a$766f6964202a$766f6964202a$766f6964202a(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DISKREP_CREATE_BUNDLE_REF_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$diskrep__create__bundle__ref$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DISKREP_CREATE_CFM(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$diskrep__create__cfm$v1$766f6964202a$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DISKREP_CREATE_CFM_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$diskrep__create__cfm$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DISKREP_CREATE_DETACHED(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$diskrep__create__detached$v1$766f6964202a$766f6964202a$63686172202a$766f6964202a(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DISKREP_CREATE_DETACHED_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$diskrep__create__detached$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DISKREP_CREATE_FILE(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$diskrep__create__file$v1$766f6964202a$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DISKREP_CREATE_FILE_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$diskrep__create__file$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DISKREP_CREATE_KERNEL(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$diskrep__create__kernel$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DISKREP_CREATE_KERNEL_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$diskrep__create__kernel$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DISKREP_CREATE_MACHO(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$diskrep__create__macho$v1$766f6964202a$63686172202a$766f6964202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DISKREP_CREATE_MACHO_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$diskrep__create__macho$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DISKREP_CREATE_SLC(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$diskrep__create__slc$v1$766f6964202a$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DISKREP_CREATE_SLC_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$diskrep__create__slc$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DISKREP_DESTROY(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$diskrep__destroy$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DISKREP_DESTROY_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$diskrep__destroy$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_DYNAMIC_CREATE(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$dynamic__create$v1$766f6964202a$766f6964202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_DYNAMIC_CREATE_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$dynamic__create$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_DYNAMIC_END(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__dynamic__end$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_DYNAMIC_END_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__dynamic__end$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_DYNAMIC_ROOT(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__dynamic__root$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_DYNAMIC_ROOT_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__dynamic__root$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_DYNAMIC_START(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__dynamic__start$v1$766f6964202a$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_DYNAMIC_START_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__dynamic__start$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_REQINT_END(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__reqint__end$v1$766f6964202a$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_REQINT_END_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__reqint__end$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_REQINT_FRAGMENT_HIT(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__reqint__fragment__hit$v1$63686172202a$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_REQINT_FRAGMENT_HIT_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__reqint__fragment__hit$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_REQINT_FRAGMENT_LOAD(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__reqint__fragment__load$v1$63686172202a$63686172202a$766f6964202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_REQINT_FRAGMENT_LOAD_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__reqint__fragment__load$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_REQINT_OP(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__reqint__op$v1$756e7369676e6564$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_REQINT_OP_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__reqint__op$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_REQINT_START(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__reqint__start$v1$766f6964202a$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_REQINT_START_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__reqint__start$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_REQINT_UNKNOWN_FALSE(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__reqint__unknown_false$v1$756e7369676e6564(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_REQINT_UNKNOWN_FALSE_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__reqint__unknown_false$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_REQINT_UNKNOWN_SKIPPED(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__reqint__unknown_skipped$v1$756e7369676e6564(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_REQINT_UNKNOWN_SKIPPED_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__reqint__unknown_skipped$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_DIRECTORY(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__directory$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_DIRECTORY_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__directory$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_END(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__end$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_END_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__end$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_END(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__executable__end$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_END_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__executable__end$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_FAIL(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__executable__fail$v1$766f6964202a$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_FAIL_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__executable__fail$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_START(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__executable__start$v1$766f6964202a$63686172202a$756e7369676e6564(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_START_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__executable__start$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_INTREQ_END(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__intreq__end$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_INTREQ_END_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__intreq__end$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_INTREQ_START(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__intreq__start$v1$766f6964202a$756e7369676e6564$766f6964202a$696e74(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_INTREQ_START_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__intreq__start$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_RESET(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__reset$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_RESET_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__reset$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_RESOURCES_END(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__resources__end$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_RESOURCES_END_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__resources__end$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_RESOURCES_START(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__resources__start$v1$766f6964202a$63686172202a$696e74(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_RESOURCES_START_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__resources__start$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_SIGNATURE_ADHOC(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__signature__adhoc$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_ADHOC_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__signature__adhoc$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_SIGNATURE_END(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__signature__end$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_END_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__signature__end$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_SIGNATURE_EXPIRED(arg0) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__signature__expired$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_EXPIRED_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__signature__expired$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_SIGNATURE_RESULT(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__signature__result$v1$766f6964202a$756e7369676e6564$756e7369676e6564(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_RESULT_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__signature__result$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_SIGNATURE_START(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__signature__start$v1$766f6964202a$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_START_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__signature__start$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_EVAL_STATIC_START(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$eval__static__start$v1$766f6964202a$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_EVAL_STATIC_START_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$eval__static__start$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_GUEST_CDHASH_GENERIC(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$guest__cdhash__generic$v1$766f6964202a$766f6964202a$756e7369676e6564(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_GUEST_CDHASH_GENERIC_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$guest__cdhash__generic$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_GUEST_CDHASH_PROCESS(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$guest__cdhash__process$v1$766f6964202a$766f6964202a$756e7369676e6564(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_GUEST_CDHASH_PROCESS_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$guest__cdhash__process$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_GUEST_HOSTINGPORT(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$guest__hostingport$v1$766f6964202a$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_GUEST_HOSTINGPORT_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$guest__hostingport$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_GUEST_IDENTIFY_GENERIC(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$guest__identify__generic$v1$766f6964202a$756e7369676e6564$766f6964202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_GUEST_IDENTIFY_GENERIC_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$guest__identify__generic$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_GUEST_IDENTIFY_PROCESS(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$guest__identify__process$v1$766f6964202a$756e7369676e6564$766f6964202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_GUEST_IDENTIFY_PROCESS_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$guest__identify__process$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_GUEST_LOCATE_GENERIC(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$guest__locate__generic$v1$766f6964202a$756e7369676e6564202a$756e7369676e6564$756e7369676e6564(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_GUEST_LOCATE_GENERIC_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$guest__locate__generic$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_LOAD_ANTLR() \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$load__antlr$v1(); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_LOAD_ANTLR_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$load__antlr$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_SIGN_DEP_INTERP(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$sign__dep__interp$v1$766f6964202a$63686172202a$766f6964202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_SIGN_DEP_INTERP_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$sign__dep__interp$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_SIGN_DEP_MACHO(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$sign__dep__macho$v1$766f6964202a$63686172202a$766f6964202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_SIGN_DEP_MACHO_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$sign__dep__macho$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_STATIC_ATTACH_EXPLICIT(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$static__attach__explicit$v1$766f6964202a$766f6964202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_STATIC_ATTACH_EXPLICIT_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$static__attach__explicit$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_STATIC_ATTACH_SYSTEM(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$static__attach__system$v1$766f6964202a$766f6964202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_STATIC_ATTACH_SYSTEM_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$static__attach__system$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_STATIC_CDHASH(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$static__cdhash$v1$766f6964202a$766f6964202a$756e7369676e6564(arg0, arg1, arg2); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_STATIC_CDHASH_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$static__cdhash$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define CODESIGN_STATIC_CREATE(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " CODESIGN_TYPEDEFS); \ - __dtrace_probe$codesign$static__create$v1$766f6964202a$766f6964202a(arg0, arg1); \ - __asm__ volatile(".reference " CODESIGN_STABILITY); \ -} while (0) -#define CODESIGN_STATIC_CREATE_ENABLED() \ - ({ int _r = __dtrace_isenabled$codesign$static__create$v1(); \ - __asm__ volatile(""); \ - _r; }) - - -extern void __dtrace_probe$codesign$allocate__arch$v1$63686172202a$756e7369676e6564(const char *, unsigned); -extern int __dtrace_isenabled$codesign$allocate__arch$v1(void); -extern void __dtrace_probe$codesign$allocate__archn$v1$756e7369676e6564$756e7369676e6564$756e7369676e6564(unsigned, unsigned, unsigned); -extern int __dtrace_isenabled$codesign$allocate__archn$v1(void); -extern void __dtrace_probe$codesign$allocate__validate$v1$63686172202a$756e7369676e6564(const char *, unsigned); -extern int __dtrace_isenabled$codesign$allocate__validate$v1(void); -extern void __dtrace_probe$codesign$allocate__write$v1$63686172202a$75696e7436345f74$756e7369676e6564$756e7369676e6564(const char *, uint64_t, unsigned, unsigned); -extern int __dtrace_isenabled$codesign$allocate__write$v1(void); -extern void __dtrace_probe$codesign$diskrep__create__bundle__path$v1$766f6964202a$63686172202a$766f6964202a$766f6964202a(const void *, const char *, const void *, const void *); -extern int __dtrace_isenabled$codesign$diskrep__create__bundle__path$v1(void); -extern void __dtrace_probe$codesign$diskrep__create__bundle__ref$v1$766f6964202a$766f6964202a$766f6964202a$766f6964202a(const void *, const void *, const void *, const void *); -extern int __dtrace_isenabled$codesign$diskrep__create__bundle__ref$v1(void); -extern void __dtrace_probe$codesign$diskrep__create__cfm$v1$766f6964202a$63686172202a(const void *, const char *); -extern int __dtrace_isenabled$codesign$diskrep__create__cfm$v1(void); -extern void __dtrace_probe$codesign$diskrep__create__detached$v1$766f6964202a$766f6964202a$63686172202a$766f6964202a(const void *, const void *, const char *, const void *); -extern int __dtrace_isenabled$codesign$diskrep__create__detached$v1(void); -extern void __dtrace_probe$codesign$diskrep__create__file$v1$766f6964202a$63686172202a(const void *, const char *); -extern int __dtrace_isenabled$codesign$diskrep__create__file$v1(void); -extern void __dtrace_probe$codesign$diskrep__create__kernel$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$diskrep__create__kernel$v1(void); -extern void __dtrace_probe$codesign$diskrep__create__macho$v1$766f6964202a$63686172202a$766f6964202a(const void *, const char *, const void *); -extern int __dtrace_isenabled$codesign$diskrep__create__macho$v1(void); -extern void __dtrace_probe$codesign$diskrep__create__slc$v1$766f6964202a$63686172202a(const void *, const char *); -extern int __dtrace_isenabled$codesign$diskrep__create__slc$v1(void); -extern void __dtrace_probe$codesign$diskrep__destroy$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$diskrep__destroy$v1(void); -extern void __dtrace_probe$codesign$dynamic__create$v1$766f6964202a$766f6964202a(const void *, const void *); -extern int __dtrace_isenabled$codesign$dynamic__create$v1(void); -extern void __dtrace_probe$codesign$eval__dynamic__end$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__dynamic__end$v1(void); -extern void __dtrace_probe$codesign$eval__dynamic__root$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__dynamic__root$v1(void); -extern void __dtrace_probe$codesign$eval__dynamic__start$v1$766f6964202a$63686172202a(const void *, const char *); -extern int __dtrace_isenabled$codesign$eval__dynamic__start$v1(void); -extern void __dtrace_probe$codesign$eval__reqint__end$v1$766f6964202a$756e7369676e6564(const void *, unsigned); -extern int __dtrace_isenabled$codesign$eval__reqint__end$v1(void); -extern void __dtrace_probe$codesign$eval__reqint__fragment__hit$v1$63686172202a$63686172202a(const char *, const char *); -extern int __dtrace_isenabled$codesign$eval__reqint__fragment__hit$v1(void); -extern void __dtrace_probe$codesign$eval__reqint__fragment__load$v1$63686172202a$63686172202a$766f6964202a(const char *, const char *, const void *); -extern int __dtrace_isenabled$codesign$eval__reqint__fragment__load$v1(void); -extern void __dtrace_probe$codesign$eval__reqint__op$v1$756e7369676e6564$756e7369676e6564(unsigned, unsigned); -extern int __dtrace_isenabled$codesign$eval__reqint__op$v1(void); -extern void __dtrace_probe$codesign$eval__reqint__start$v1$766f6964202a$756e7369676e6564(const void *, unsigned); -extern int __dtrace_isenabled$codesign$eval__reqint__start$v1(void); -extern void __dtrace_probe$codesign$eval__reqint__unknown_false$v1$756e7369676e6564(unsigned); -extern int __dtrace_isenabled$codesign$eval__reqint__unknown_false$v1(void); -extern void __dtrace_probe$codesign$eval__reqint__unknown_skipped$v1$756e7369676e6564(unsigned); -extern int __dtrace_isenabled$codesign$eval__reqint__unknown_skipped$v1(void); -extern void __dtrace_probe$codesign$eval__static__directory$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__static__directory$v1(void); -extern void __dtrace_probe$codesign$eval__static__end$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__static__end$v1(void); -extern void __dtrace_probe$codesign$eval__static__executable__end$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__static__executable__end$v1(void); -extern void __dtrace_probe$codesign$eval__static__executable__fail$v1$766f6964202a$756e7369676e6564(const void *, unsigned); -extern int __dtrace_isenabled$codesign$eval__static__executable__fail$v1(void); -extern void __dtrace_probe$codesign$eval__static__executable__start$v1$766f6964202a$63686172202a$756e7369676e6564(const void *, const char *, unsigned); -extern int __dtrace_isenabled$codesign$eval__static__executable__start$v1(void); -extern void __dtrace_probe$codesign$eval__static__intreq__end$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__static__intreq__end$v1(void); -extern void __dtrace_probe$codesign$eval__static__intreq__start$v1$766f6964202a$756e7369676e6564$766f6964202a$696e74(const void *, unsigned, const void *, int); -extern int __dtrace_isenabled$codesign$eval__static__intreq__start$v1(void); -extern void __dtrace_probe$codesign$eval__static__reset$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__static__reset$v1(void); -extern void __dtrace_probe$codesign$eval__static__resources__end$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__static__resources__end$v1(void); -extern void __dtrace_probe$codesign$eval__static__resources__start$v1$766f6964202a$63686172202a$696e74(const void *, const char *, int); -extern int __dtrace_isenabled$codesign$eval__static__resources__start$v1(void); -extern void __dtrace_probe$codesign$eval__static__signature__adhoc$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__static__signature__adhoc$v1(void); -extern void __dtrace_probe$codesign$eval__static__signature__end$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__static__signature__end$v1(void); -extern void __dtrace_probe$codesign$eval__static__signature__expired$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$codesign$eval__static__signature__expired$v1(void); -extern void __dtrace_probe$codesign$eval__static__signature__result$v1$766f6964202a$756e7369676e6564$756e7369676e6564(const void *, unsigned, unsigned); -extern int __dtrace_isenabled$codesign$eval__static__signature__result$v1(void); -extern void __dtrace_probe$codesign$eval__static__signature__start$v1$766f6964202a$63686172202a(const void *, const char *); -extern int __dtrace_isenabled$codesign$eval__static__signature__start$v1(void); -extern void __dtrace_probe$codesign$eval__static__start$v1$766f6964202a$63686172202a(const void *, const char *); -extern int __dtrace_isenabled$codesign$eval__static__start$v1(void); -extern void __dtrace_probe$codesign$guest__cdhash__generic$v1$766f6964202a$766f6964202a$756e7369676e6564(const void *, const void *, unsigned); -extern int __dtrace_isenabled$codesign$guest__cdhash__generic$v1(void); -extern void __dtrace_probe$codesign$guest__cdhash__process$v1$766f6964202a$766f6964202a$756e7369676e6564(const void *, const void *, unsigned); -extern int __dtrace_isenabled$codesign$guest__cdhash__process$v1(void); -extern void __dtrace_probe$codesign$guest__hostingport$v1$766f6964202a$756e7369676e6564(const void *, unsigned); -extern int __dtrace_isenabled$codesign$guest__hostingport$v1(void); -extern void __dtrace_probe$codesign$guest__identify__generic$v1$766f6964202a$756e7369676e6564$766f6964202a(const void *, unsigned, const void *); -extern int __dtrace_isenabled$codesign$guest__identify__generic$v1(void); -extern void __dtrace_probe$codesign$guest__identify__process$v1$766f6964202a$756e7369676e6564$766f6964202a(const void *, unsigned, const void *); -extern int __dtrace_isenabled$codesign$guest__identify__process$v1(void); -extern void __dtrace_probe$codesign$guest__locate__generic$v1$766f6964202a$756e7369676e6564202a$756e7369676e6564$756e7369676e6564(const void *, const unsigned *, unsigned, unsigned); -extern int __dtrace_isenabled$codesign$guest__locate__generic$v1(void); -extern void __dtrace_probe$codesign$load__antlr$v1(void); -extern int __dtrace_isenabled$codesign$load__antlr$v1(void); -extern void __dtrace_probe$codesign$sign__dep__interp$v1$766f6964202a$63686172202a$766f6964202a(const void *, const char *, const void *); -extern int __dtrace_isenabled$codesign$sign__dep__interp$v1(void); -extern void __dtrace_probe$codesign$sign__dep__macho$v1$766f6964202a$63686172202a$766f6964202a(const void *, const char *, const void *); -extern int __dtrace_isenabled$codesign$sign__dep__macho$v1(void); -extern void __dtrace_probe$codesign$static__attach__explicit$v1$766f6964202a$766f6964202a(const void *, const void *); -extern int __dtrace_isenabled$codesign$static__attach__explicit$v1(void); -extern void __dtrace_probe$codesign$static__attach__system$v1$766f6964202a$766f6964202a(const void *, const void *); -extern int __dtrace_isenabled$codesign$static__attach__system$v1(void); -extern void __dtrace_probe$codesign$static__cdhash$v1$766f6964202a$766f6964202a$756e7369676e6564(const void *, const void *, unsigned); -extern int __dtrace_isenabled$codesign$static__cdhash$v1(void); -extern void __dtrace_probe$codesign$static__create$v1$766f6964202a$766f6964202a(const void *, const void *); -extern int __dtrace_isenabled$codesign$static__create$v1(void); - -#else - -#define CODESIGN_ALLOCATE_ARCH(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_ALLOCATE_ARCH_ENABLED() (0) -#define CODESIGN_ALLOCATE_ARCHN(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_ALLOCATE_ARCHN_ENABLED() (0) -#define CODESIGN_ALLOCATE_VALIDATE(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_ALLOCATE_VALIDATE_ENABLED() (0) -#define CODESIGN_ALLOCATE_WRITE(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define CODESIGN_ALLOCATE_WRITE_ENABLED() (0) -#define CODESIGN_DISKREP_CREATE_BUNDLE_PATH(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define CODESIGN_DISKREP_CREATE_BUNDLE_PATH_ENABLED() (0) -#define CODESIGN_DISKREP_CREATE_BUNDLE_REF(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define CODESIGN_DISKREP_CREATE_BUNDLE_REF_ENABLED() (0) -#define CODESIGN_DISKREP_CREATE_CFM(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_DISKREP_CREATE_CFM_ENABLED() (0) -#define CODESIGN_DISKREP_CREATE_DETACHED(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define CODESIGN_DISKREP_CREATE_DETACHED_ENABLED() (0) -#define CODESIGN_DISKREP_CREATE_FILE(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_DISKREP_CREATE_FILE_ENABLED() (0) -#define CODESIGN_DISKREP_CREATE_KERNEL(arg0) \ -do { \ - } while (0) -#define CODESIGN_DISKREP_CREATE_KERNEL_ENABLED() (0) -#define CODESIGN_DISKREP_CREATE_MACHO(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_DISKREP_CREATE_MACHO_ENABLED() (0) -#define CODESIGN_DISKREP_CREATE_SLC(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_DISKREP_CREATE_SLC_ENABLED() (0) -#define CODESIGN_DISKREP_DESTROY(arg0) \ -do { \ - } while (0) -#define CODESIGN_DISKREP_DESTROY_ENABLED() (0) -#define CODESIGN_DYNAMIC_CREATE(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_DYNAMIC_CREATE_ENABLED() (0) -#define CODESIGN_EVAL_DYNAMIC_END(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_DYNAMIC_END_ENABLED() (0) -#define CODESIGN_EVAL_DYNAMIC_ROOT(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_DYNAMIC_ROOT_ENABLED() (0) -#define CODESIGN_EVAL_DYNAMIC_START(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_EVAL_DYNAMIC_START_ENABLED() (0) -#define CODESIGN_EVAL_REQINT_END(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_EVAL_REQINT_END_ENABLED() (0) -#define CODESIGN_EVAL_REQINT_FRAGMENT_HIT(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_EVAL_REQINT_FRAGMENT_HIT_ENABLED() (0) -#define CODESIGN_EVAL_REQINT_FRAGMENT_LOAD(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_EVAL_REQINT_FRAGMENT_LOAD_ENABLED() (0) -#define CODESIGN_EVAL_REQINT_OP(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_EVAL_REQINT_OP_ENABLED() (0) -#define CODESIGN_EVAL_REQINT_START(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_EVAL_REQINT_START_ENABLED() (0) -#define CODESIGN_EVAL_REQINT_UNKNOWN_FALSE(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_REQINT_UNKNOWN_FALSE_ENABLED() (0) -#define CODESIGN_EVAL_REQINT_UNKNOWN_SKIPPED(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_REQINT_UNKNOWN_SKIPPED_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_DIRECTORY(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_DIRECTORY_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_END(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_END_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_END(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_END_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_FAIL(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_FAIL_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_START(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_EXECUTABLE_START_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_INTREQ_END(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_INTREQ_END_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_INTREQ_START(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_INTREQ_START_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_RESET(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_RESET_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_RESOURCES_END(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_RESOURCES_END_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_RESOURCES_START(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_RESOURCES_START_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_ADHOC(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_ADHOC_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_END(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_END_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_EXPIRED(arg0) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_EXPIRED_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_RESULT(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_RESULT_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_START(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_SIGNATURE_START_ENABLED() (0) -#define CODESIGN_EVAL_STATIC_START(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_EVAL_STATIC_START_ENABLED() (0) -#define CODESIGN_GUEST_CDHASH_GENERIC(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_GUEST_CDHASH_GENERIC_ENABLED() (0) -#define CODESIGN_GUEST_CDHASH_PROCESS(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_GUEST_CDHASH_PROCESS_ENABLED() (0) -#define CODESIGN_GUEST_HOSTINGPORT(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_GUEST_HOSTINGPORT_ENABLED() (0) -#define CODESIGN_GUEST_IDENTIFY_GENERIC(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_GUEST_IDENTIFY_GENERIC_ENABLED() (0) -#define CODESIGN_GUEST_IDENTIFY_PROCESS(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_GUEST_IDENTIFY_PROCESS_ENABLED() (0) -#define CODESIGN_GUEST_LOCATE_GENERIC(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define CODESIGN_GUEST_LOCATE_GENERIC_ENABLED() (0) -#define CODESIGN_LOAD_ANTLR() \ -do { \ - } while (0) -#define CODESIGN_LOAD_ANTLR_ENABLED() (0) -#define CODESIGN_SIGN_DEP_INTERP(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_SIGN_DEP_INTERP_ENABLED() (0) -#define CODESIGN_SIGN_DEP_MACHO(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_SIGN_DEP_MACHO_ENABLED() (0) -#define CODESIGN_STATIC_ATTACH_EXPLICIT(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_STATIC_ATTACH_EXPLICIT_ENABLED() (0) -#define CODESIGN_STATIC_ATTACH_SYSTEM(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_STATIC_ATTACH_SYSTEM_ENABLED() (0) -#define CODESIGN_STATIC_CDHASH(arg0, arg1, arg2) \ -do { \ - } while (0) -#define CODESIGN_STATIC_CDHASH_ENABLED() (0) -#define CODESIGN_STATIC_CREATE(arg0, arg1) \ -do { \ - } while (0) -#define CODESIGN_STATIC_CREATE_ENABLED() (0) - -#endif /* !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED */ - -#define SYSPOLICY_STABILITY "___dtrace_stability$syspolicy$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0" - -#define SYSPOLICY_TYPEDEFS "___dtrace_typedefs$syspolicy$v2" - -#if !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED - -#define SYSPOLICY_ASSESS_OUTCOME_ACCEPT(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$assess__outcome__accept$v1$63686172202a$696e74$63686172202a$766f6964202a(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_ASSESS_OUTCOME_ACCEPT_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$assess__outcome__accept$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_ASSESS_OUTCOME_BROKEN(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$assess__outcome__broken$v1$63686172202a$696e74$75696e74385f74(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_ASSESS_OUTCOME_BROKEN_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$assess__outcome__broken$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_ASSESS_OUTCOME_DEFAULT(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$assess__outcome__default$v1$63686172202a$696e74$63686172202a$766f6964202a(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_ASSESS_OUTCOME_DEFAULT_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$assess__outcome__default$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_ASSESS_OUTCOME_DENY(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$assess__outcome__deny$v1$63686172202a$696e74$63686172202a$766f6964202a(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_ASSESS_OUTCOME_DENY_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$assess__outcome__deny$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_ASSESS_OUTCOME_UNSIGNED(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$assess__outcome__unsigned$v1$63686172202a$696e74(arg0, arg1); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_ASSESS_OUTCOME_UNSIGNED_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$assess__outcome__unsigned$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_ASSESS_API(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$assess_api$v1$63686172202a$696e74$75696e7436345f74(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_ASSESS_API_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$assess_api$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_ASSESS_CACHE_HIT() \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$assess_cache_hit$v1(); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_ASSESS_CACHE_HIT_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$assess_cache_hit$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_ASSESS_LOCAL() \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$assess_local$v1(); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_ASSESS_LOCAL_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$assess_local$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_ASSESS_REMOTE() \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$assess_remote$v1(); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_ASSESS_REMOTE_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$assess_remote$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_RECORDER_MODE(arg0, arg1, arg2, arg3, arg4) \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$recorder_mode$v1$63686172202a$696e74$63686172202a$766f6964202a$696e74(arg0, arg1, arg2, arg3, arg4); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_RECORDER_MODE_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$recorder_mode$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SYSPOLICY_RECORDER_MODE_ADHOC_PATH(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SYSPOLICY_TYPEDEFS); \ - __dtrace_probe$syspolicy$recorder_mode_adhoc_path$v1$63686172202a$696e74$63686172202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SYSPOLICY_STABILITY); \ -} while (0) -#define SYSPOLICY_RECORDER_MODE_ADHOC_PATH_ENABLED() \ - ({ int _r = __dtrace_isenabled$syspolicy$recorder_mode_adhoc_path$v1(); \ - __asm__ volatile(""); \ - _r; }) - - -extern void __dtrace_probe$syspolicy$assess__outcome__accept$v1$63686172202a$696e74$63686172202a$766f6964202a(const char *, int, const char *, const void *); -extern int __dtrace_isenabled$syspolicy$assess__outcome__accept$v1(void); -extern void __dtrace_probe$syspolicy$assess__outcome__broken$v1$63686172202a$696e74$75696e74385f74(const char *, int, uint8_t); -extern int __dtrace_isenabled$syspolicy$assess__outcome__broken$v1(void); -extern void __dtrace_probe$syspolicy$assess__outcome__default$v1$63686172202a$696e74$63686172202a$766f6964202a(const char *, int, const char *, const void *); -extern int __dtrace_isenabled$syspolicy$assess__outcome__default$v1(void); -extern void __dtrace_probe$syspolicy$assess__outcome__deny$v1$63686172202a$696e74$63686172202a$766f6964202a(const char *, int, const char *, const void *); -extern int __dtrace_isenabled$syspolicy$assess__outcome__deny$v1(void); -extern void __dtrace_probe$syspolicy$assess__outcome__unsigned$v1$63686172202a$696e74(const char *, int); -extern int __dtrace_isenabled$syspolicy$assess__outcome__unsigned$v1(void); -extern void __dtrace_probe$syspolicy$assess_api$v1$63686172202a$696e74$75696e7436345f74(const char *, int, uint64_t); -extern int __dtrace_isenabled$syspolicy$assess_api$v1(void); -extern void __dtrace_probe$syspolicy$assess_cache_hit$v1(void); -extern int __dtrace_isenabled$syspolicy$assess_cache_hit$v1(void); -extern void __dtrace_probe$syspolicy$assess_local$v1(void); -extern int __dtrace_isenabled$syspolicy$assess_local$v1(void); -extern void __dtrace_probe$syspolicy$assess_remote$v1(void); -extern int __dtrace_isenabled$syspolicy$assess_remote$v1(void); -extern void __dtrace_probe$syspolicy$recorder_mode$v1$63686172202a$696e74$63686172202a$766f6964202a$696e74(const char *, int, const char *, const void *, int); -extern int __dtrace_isenabled$syspolicy$recorder_mode$v1(void); -extern void __dtrace_probe$syspolicy$recorder_mode_adhoc_path$v1$63686172202a$696e74$63686172202a(const char *, int, const char *); -extern int __dtrace_isenabled$syspolicy$recorder_mode_adhoc_path$v1(void); - -#else - -#define SYSPOLICY_ASSESS_OUTCOME_ACCEPT(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define SYSPOLICY_ASSESS_OUTCOME_ACCEPT_ENABLED() (0) -#define SYSPOLICY_ASSESS_OUTCOME_BROKEN(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SYSPOLICY_ASSESS_OUTCOME_BROKEN_ENABLED() (0) -#define SYSPOLICY_ASSESS_OUTCOME_DEFAULT(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define SYSPOLICY_ASSESS_OUTCOME_DEFAULT_ENABLED() (0) -#define SYSPOLICY_ASSESS_OUTCOME_DENY(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define SYSPOLICY_ASSESS_OUTCOME_DENY_ENABLED() (0) -#define SYSPOLICY_ASSESS_OUTCOME_UNSIGNED(arg0, arg1) \ -do { \ - } while (0) -#define SYSPOLICY_ASSESS_OUTCOME_UNSIGNED_ENABLED() (0) -#define SYSPOLICY_ASSESS_API(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SYSPOLICY_ASSESS_API_ENABLED() (0) -#define SYSPOLICY_ASSESS_CACHE_HIT() \ -do { \ - } while (0) -#define SYSPOLICY_ASSESS_CACHE_HIT_ENABLED() (0) -#define SYSPOLICY_ASSESS_LOCAL() \ -do { \ - } while (0) -#define SYSPOLICY_ASSESS_LOCAL_ENABLED() (0) -#define SYSPOLICY_ASSESS_REMOTE() \ -do { \ - } while (0) -#define SYSPOLICY_ASSESS_REMOTE_ENABLED() (0) -#define SYSPOLICY_RECORDER_MODE(arg0, arg1, arg2, arg3, arg4) \ -do { \ - } while (0) -#define SYSPOLICY_RECORDER_MODE_ENABLED() (0) -#define SYSPOLICY_RECORDER_MODE_ADHOC_PATH(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SYSPOLICY_RECORDER_MODE_ADHOC_PATH_ENABLED() (0) - -#endif /* !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _CODESIGNING_DTRACE_H */ diff --git a/OSX/libsecurity_codesigning/lib/cs.h b/OSX/libsecurity_codesigning/lib/cs.h index 4e360e91..3bb9183d 100644 --- a/OSX/libsecurity_codesigning/lib/cs.h +++ b/OSX/libsecurity_codesigning/lib/cs.h @@ -162,6 +162,20 @@ static inline void checkFlags(SecCSFlags flags, SecCSFlags acceptable = 0) MacOSError::throwMe(errSecCSInvalidFlags); } +static inline Boolean isFlagSet(SecCSFlags flags, SecCSFlags toTest) +{ + return ((flags & toTest) == toTest); +} + +static inline SecCSFlags addFlags(SecCSFlags flags, SecCSFlags toAdd) +{ + return (flags | toAdd); +} + +static inline SecCSFlags clearFlags(SecCSFlags flags, SecCSFlags toClear) +{ + return (flags & ~toClear); +} // // DTrace USDT function bracket. diff --git a/OSX/libsecurity_codesigning/lib/cserror.cpp b/OSX/libsecurity_codesigning/lib/cserror.cpp index 1e6d98e7..907e1ee3 100644 --- a/OSX/libsecurity_codesigning/lib/cserror.cpp +++ b/OSX/libsecurity_codesigning/lib/cserror.cpp @@ -34,7 +34,7 @@ namespace CodeSigning { // // We need a nothrow destructor // -CSError::~CSError() throw () +CSError::~CSError() _NOEXCEPT { } diff --git a/OSX/libsecurity_codesigning/lib/cserror.h b/OSX/libsecurity_codesigning/lib/cserror.h index f46528f1..41b97ac3 100644 --- a/OSX/libsecurity_codesigning/lib/cserror.h +++ b/OSX/libsecurity_codesigning/lib/cserror.h @@ -42,7 +42,7 @@ class CSError : public MacOSError { public: CSError(OSStatus rc) : MacOSError(rc) { } CSError(OSStatus rc, CFDictionaryRef dict) : MacOSError(rc), mInfoDict(dict) { } // takes dict - ~CSError() throw (); + ~CSError() _NOEXCEPT; static void throwMe(OSStatus rc) __attribute__((noreturn)); static void throwMe(OSStatus rc, CFDictionaryRef info) __attribute__ ((noreturn)); // takes dict diff --git a/OSX/libsecurity_codesigning/lib/cskernel.cpp b/OSX/libsecurity_codesigning/lib/cskernel.cpp index ed47d1c2..0eca9653 100644 --- a/OSX/libsecurity_codesigning/lib/cskernel.cpp +++ b/OSX/libsecurity_codesigning/lib/cskernel.cpp @@ -130,17 +130,16 @@ SecStaticCode *KernelCode::identifyGuest(SecCode *iguest, CFDataRef *cdhash) SecPointer code = new ProcessDynamicCode(guest); guest->pidBased()->setCredentials(code->codeDirectory()); -#ifndef DARLING + SHA1::Digest kernelHash; MacOSError::check(guest->csops(CS_OPS_CDHASH, kernelHash, sizeof(kernelHash))); *cdhash = makeCFData(kernelHash, sizeof(kernelHash)); -#endif + return code.yield(); } char path[2 * MAXPATHLEN]; // reasonable upper limit if (::proc_pidpath(guest->pid(), path, sizeof(path))) { -#ifndef DARLING off_t offset; csops(guest, CS_OPS_PIDOFFSET, &offset, sizeof(offset)); SecPointer code = new ProcessStaticCode(DiskRep::bestGuess(path, (size_t)offset)); @@ -161,9 +160,6 @@ SecStaticCode *KernelCode::identifyGuest(SecCode *iguest, CFDataRef *cdhash) *cdhash = makeCFData(kernelHash, sizeof(kernelHash)); CODESIGN_GUEST_CDHASH_PROCESS(guest, kernelHash, sizeof(kernelHash)); } -#else - SecPointer code = new ProcessStaticCode(DiskRep::bestGuess(path)); -#endif return code.yield(); } else UnixError::throwMe(); @@ -179,7 +175,7 @@ SecCodeStatus KernelCode::getGuestStatus(SecCode *iguest) { if (ProcessCode *guest = dynamic_cast(iguest)) { uint32_t pFlags; - csops(guest, CS_OPS_STATUS, &pFlags); + csops(guest, CS_OPS_STATUS, &pFlags, sizeof(pFlags)); secinfo("kcode", "guest %p(%d) kernel status 0x%x", guest, guest->pid(), pFlags); return pFlags; } else @@ -229,7 +225,6 @@ void KernelCode::identify() // void KernelCode::csops(ProcessCode *proc, unsigned int op, void *addr, size_t length) { -#ifndef DARLING if (proc->csops(op, addr, length) == -1) { switch (errno) { case ESRCH: @@ -238,7 +233,6 @@ void KernelCode::csops(ProcessCode *proc, unsigned int op, void *addr, size_t le UnixError::throwMe(); } } -#endif } diff --git a/OSX/libsecurity_codesigning/lib/csprocess.h b/OSX/libsecurity_codesigning/lib/csprocess.h index b0a370e4..0d717e55 100644 --- a/OSX/libsecurity_codesigning/lib/csprocess.h +++ b/OSX/libsecurity_codesigning/lib/csprocess.h @@ -43,7 +43,7 @@ namespace CodeSigning { class ProcessCode : public SecCode { public: ProcessCode(pid_t pid, const audit_token_t* token, PidDiskRep *pidDiskRep = NULL); - ~ProcessCode() throw () { delete mAudit; } + ~ProcessCode() _NOEXCEPT { delete mAudit; } pid_t pid() const { return mPid; } const audit_token_t* audit() const { return mAudit; } diff --git a/OSX/libsecurity_codesigning/lib/csutilities.cpp b/OSX/libsecurity_codesigning/lib/csutilities.cpp index 774b6ee2..680c0eb7 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.cpp +++ b/OSX/libsecurity_codesigning/lib/csutilities.cpp @@ -34,13 +34,20 @@ #include #include #include +#include #include #include #include "requirement.h" #include #include #include +#include #include +#include +#include +#include +#include +#include "debugging.h" extern "C" { @@ -85,13 +92,7 @@ void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest dig void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest) { assert(cert); -#if TARGET_OS_OSX - CSSM_DATA certData; - MacOSError::check(SecCertificateGetData(cert, &certData)); - hashOfCertificate(certData.Data, certData.Length, digest); -#else hashOfCertificate(SecCertificateGetBytePtr(cert), SecCertificateGetLength(cert), digest); -#endif } @@ -112,36 +113,32 @@ bool verifyHash(SecCertificateRef cert, const Hashing::Byte *digest) // bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid) { - assert(cert); - CSSM_DATA *value; - switch (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &oid, &value)) { - case errSecSuccess: - MacOSError::check(SecCertificateReleaseFirstFieldValue(cert, &oid, value)); - return true; // extension found by oid - case errSecUnknownTag: - break; // oid not recognized by CL - continue below - default: - MacOSError::throwMe(rc); // error: fail + CFDataRef oidData = NULL; + CFDataRef data = NULL; + bool isCritical = false; + bool matched = false; + + oidData = CFDataCreateWithBytesNoCopy(NULL, oid.Data, oid.Length, + kCFAllocatorNull); + if (!(cert && oidData)) { + goto out; } - - // check the CL's bag of unrecognized extensions - CSSM_DATA **values; - bool found = false; - if (SecCertificateCopyFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, &values)) - return false; // no unrecognized extensions - no match - if (values) - for (CSSM_DATA **p = values; *p; p++) { - const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)(*p)->Data; - if (oid == ext->extnId) { - found = true; - break; - } - } - MacOSError::check(SecCertificateReleaseFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, values)); - return found; + data = SecCertificateCopyExtensionValue(cert, oidData, &isCritical); + if (data == NULL) { + goto out; + } + matched = true; +out: + if (data) { + CFRelease(data); + } + if (oidData) { + CFRelease(oidData); + } + return matched; } - - + + // // Retrieve X.509 policy extension OIDs, if any. // This currently ignores policy qualifiers. @@ -149,24 +146,16 @@ bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid) bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid) { bool matched = false; - assert(cert); - CSSM_DATA *data; - if (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_CertificatePolicies, &data)) - MacOSError::throwMe(rc); - if (data && data->Data && data->Length == sizeof(CSSM_X509_EXTENSION)) { - const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)data->Data; - assert(ext->format == CSSM_X509_DATAFORMAT_PARSED); - const CE_CertPolicies *policies = (const CE_CertPolicies *)ext->value.parsedValue; - if (policies) - for (unsigned int n = 0; n < policies->numPolicies; n++) { - const CE_PolicyInformation &cp = policies->policies[n]; - if (cp.certPolicyId == policyOid) { - matched = true; - break; - } - } + CFDataRef oidData = CFDataCreateWithBytesNoCopy(NULL, policyOid.Data, policyOid.Length, + kCFAllocatorNull); + if (!(cert && oidData)) { + goto out; + } + matched = SecPolicyCheckCertCertificatePolicy(cert, oidData); +out: + if (oidData) { + CFRelease(oidData); } - SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_PolicyConstraints, data); return matched; } @@ -337,5 +326,291 @@ bool LimitedAsync::perform(Dispatch::Group &groupRef, void (^block)()) { } } +bool isOnRootFilesystem(const char *path) +{ + int rc = 0; + struct statfs sfb; + + rc = statfs(path, &sfb); + if (rc != 0) { + secerror("Unable to check if path is on rootfs: %d, %s", errno, path); + return false; + } + return ((sfb.f_flags & MNT_ROOTFS) == MNT_ROOTFS); +} + +bool pathExists(const char *path) +{ + int rc; + + if (!path) { + secerror("path is NULL"); + return false; + } + + rc = access(path, F_OK); + if (rc != 0) { + if (errno != ENOENT) { + secerror("Unable to check if path exists: %d, %s", errno, path); + } + return false; + } + + return true; +} + +bool pathMatchesXattrFilenameSpec(const char *path) +{ + char *baseName = NULL; + bool ret = false; + + if (!path) { + secerror("path is NULL"); + goto done; + } + + // Extra byte for NULL storage. + baseName = (char *)malloc(strlen(path) + 1); + if (!baseName) { + secerror("Unable to allocate space for storing basename: %d [%s]", errno, strerror(errno)); + goto done; + } + + // basename_r will return a "/" if path is only slashes. It will return + // a "." for a NULL/empty path. Both of these cases are handled by the logic + // later. The only situation where basename_r will return a NULL is when path + // is longer than MAXPATHLEN. + + if (basename_r(path, baseName) == NULL) { + secerror("Could not get basename of %s: %d [%s]", path, errno, strerror(errno)); + goto done; + } + + // The file name must start with "._", followed by the name + // of the file for which it stores the xattrs. Hence, its length + // must be at least three --> 2 for "._" and 1 for a non-empty file + // name. + if (strlen(baseName) < 3) { + goto done; + } + + if (baseName[0] != '.' || baseName[1] != '_') { + goto done; + } + + ret = true; + +done: + if (baseName) { + free(baseName); + } + + return ret; +} + +bool pathIsRegularFile(const char *path) +{ + if (!path) { + secerror("path is NULL"); + return false; + } + + struct stat sb; + if (stat(path, &sb)) { + secerror("Unable to stat %s: %d [%s]", path, errno, strerror(errno)); + return false; + } + + return (sb.st_mode & S_IFREG) == S_IFREG; +} + +bool pathHasXattrs(const char *path) +{ + if (!path) { + secerror("path is NULL"); + return false; + } + + ssize_t xattrSize = listxattr(path, NULL, 0, 0); + if (xattrSize == -1) { + secerror("Unable to acquire the xattr list from %s", path); + return false; + } + + return (xattrSize > 0); +} + +bool pathFileSystemUsesXattrFiles(const char *path) +{ + struct _VolumeCapabilitiesWrapped { + uint32_t length; + vol_capabilities_attr_t volume_capabilities; + } __attribute__((aligned(4), packed)); + + struct attrlist attr_list; + struct _VolumeCapabilitiesWrapped volume_cap_wrapped; + struct statfs sfb; + + if (!path) { + secerror("path is NULL"); + return false; + } + + int ret = statfs(path, &sfb); + if (ret != 0) { + secerror("Unable to convert %s to its filesystem mount [statfs failed]: %d [%s]", path, errno, strerror(errno)); + return false; + } + path = sfb.f_mntonname; + + memset(&attr_list, 0, sizeof(attr_list)); + attr_list.bitmapcount = ATTR_BIT_MAP_COUNT; + attr_list.volattr = ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES; + + ret = getattrlist(path, &attr_list, &volume_cap_wrapped, sizeof(volume_cap_wrapped), 0); + if (ret) { + secerror("Unable to get volume capabilities from %s: %d [%s]", path, errno, strerror(errno)); + return false; + } + + if (volume_cap_wrapped.length != sizeof(volume_cap_wrapped)) { + secerror("getattrlist return length incorrect, expected %lu, got %u", sizeof(volume_cap_wrapped), volume_cap_wrapped.length); + return false; + } + + // The valid bit tells us whether the corresponding bit in capabilities is valid + // or not. For file systems where the valid bit isn't set, we can safely assume that + // extended attributes aren't supported natively. + + bool xattr_valid = (volume_cap_wrapped.volume_capabilities.valid[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_EXTENDED_ATTR) == VOL_CAP_INT_EXTENDED_ATTR; + if (!xattr_valid) { + return true; + } + + bool xattr_capability = (volume_cap_wrapped.volume_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_EXTENDED_ATTR) == VOL_CAP_INT_EXTENDED_ATTR; + if (!xattr_capability) { + return true; + } + + return false; +} + +bool pathIsValidXattrFile(const string fullPath, const char *scope) +{ + // Confirm that fullPath begins from root. + if (fullPath[0] != '/') { + secinfo(scope, "%s isn't a full path, but a relative path", fullPath.c_str()); + return false; + } + + // Confirm that fullPath is a regular file. + if (!pathIsRegularFile(fullPath.c_str())) { + secinfo(scope, "%s isn't a regular file", fullPath.c_str()); + return false; + } + + // Check that the file name matches the Xattr file spec. + if (!pathMatchesXattrFilenameSpec(fullPath.c_str())) { + secinfo(scope, "%s doesn't match Xattr file path spec", fullPath.c_str()); + return false; + } + + // We are guaranteed to have at least one "/" by virtue of fullPath + // being a path from the root of the filesystem hierarchy. + // + // We construct the real file name by copying everything up to + // the last "/", adding the "/" back in, then skipping + // over the backslash (+1) and the "._" (+2) in the rest of the + // string. + + size_t lastBackSlash = fullPath.find_last_of("/"); + const string realFilePath = fullPath.substr(0, lastBackSlash) + "/" + fullPath.substr(lastBackSlash + 1 + 2); + + if (!pathExists(realFilePath.c_str())) { + secinfo(scope, "%s does not exist, forcing resource validation on %s", realFilePath.c_str(), fullPath.c_str()); + return false; + } + + // Lastly, we need to confirm that the real file contains some xattrs. If not, + // then the file represented by fullPath isn't an xattr file. + if (!pathHasXattrs(realFilePath.c_str())) { + secinfo(scope, "%s does not contain xattrs, forcing resource validation on %s", realFilePath.c_str(), fullPath.c_str()); + return false; + } + + return true; +} + +string pathRemaining(string fullPath, string prefix) +{ + if ((fullPath.length() < prefix.length()) || + (prefix.length() == 0) || + (fullPath.length() == 0) || + !isPathPrefix(prefix, fullPath)) { + return ""; + } + + size_t currentPosition = prefix.length(); + if (prefix[currentPosition-1] != '/') { + // If the prefix doesn't already end with a /, add one to the position so the remaining + // doesn't start with one. + currentPosition += 1; + } + + // Ensure we're not indexing outside the bounds of fullPath. + if (currentPosition >= fullPath.length()) { + return ""; + } + + return fullPath.substr(currentPosition, string::npos); +} + +bool isPathPrefix(string prefixPath, string fullPath) +{ + size_t pos = fullPath.find(prefixPath); + if (pos == 0) { + // If they're a perfect match, its not really a path prefix. + if (prefixPath.length() == fullPath.length()) { + return false; + } + + // Ensure the prefix starts a relative path under the prefix. + if (prefixPath.back() == '/') { + // If the prefix ends with a delimeter, we're good. + return true; + } else { + // Otherwise, the next character in the fullPath needs to be a delimeter. + return fullPath.at(prefixPath.length()) == '/'; + } + } + return false; +} + +bool iterateLargestSubpaths(string path, bool (^pathHandler)(string)) +{ + size_t lastPossibleSlash = path.length(); + size_t currentPosition = 0; + bool stopped = false; + + while (!stopped) { + currentPosition = path.find_last_of("/", lastPossibleSlash); + if (currentPosition == string::npos || currentPosition == 0) { + break; + } + + // Erase from the current position to the end of the string. + path.erase(currentPosition, string::npos); + stopped = pathHandler(path); + if (!stopped) { + if (currentPosition == 0) { + break; + } + lastPossibleSlash = currentPosition - 1; + } + } + return stopped; +} + + } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/csutilities.h b/OSX/libsecurity_codesigning/lib/csutilities.h index bd4408cd..aaf706e1 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.h +++ b/OSX/libsecurity_codesigning/lib/csutilities.h @@ -225,7 +225,39 @@ private: Dispatch::Semaphore *mResourceSemaphore; }; +// Check if the path is on the root filesystem, protected by the OS. +bool isOnRootFilesystem(const char *path); +// Check if a path exists. +bool pathExists(const char *path); + +// Check if the path name represents an extended attribute file (on file systems which don't support +// them natively). +bool pathMatchesXattrFilenameSpec(const char *path); + +// Check if path is a regular file. +bool pathIsRegularFile(const char *path); + +// Check if a path has any extended attributes. +bool pathHasXattrs(const char *path); + +// Check if the path is on a file system that requires files to store extended attributes. +bool pathFileSystemUsesXattrFiles(const char *path); + +// Check if path is a valid extended attribute file. +bool pathIsValidXattrFile(const string fullPath, const char *scope = "csutilities"); + +// Check whether the provided fullPath is prefixed by the prefixPath on a directory boundary. +// Also rejects if the prefixPath is a perfect match since its no longer a strict prefix. +bool isPathPrefix(string prefixPath, string fullPath); + +// Retrieves the path remaining of fullPath after the prefixPath is removed, including any leading /'s. +string pathRemaining(string fullPath, string prefix); + +// Iterates the path by removing the last path component and calling the handler, which returns +// whether to continue iterating. Returns whether any pathHandler call resulted +// in stopping the iteration. +bool iterateLargestSubpaths(string path, bool (^pathHandler)(string)); } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/dirscanner.cpp b/OSX/libsecurity_codesigning/lib/dirscanner.cpp index 15140fac..83d96190 100644 --- a/OSX/libsecurity_codesigning/lib/dirscanner.cpp +++ b/OSX/libsecurity_codesigning/lib/dirscanner.cpp @@ -28,6 +28,8 @@ #include #include "dirscanner.h" +#include + namespace Security { namespace CodeSigning { @@ -157,7 +159,9 @@ void DirValidator::validate(const string &root, OSStatus error) reqMatched.insert(rule); } if (reqMatched.size() != (unsigned long) mRequireCount) { - secinfo("dirval", "matched %lu of %d required rules", reqMatched.size(), mRequireCount); + ostringstream os; + os << "matched " << reqMatched.size() << " of " << mRequireCount << " required rules"; + secinfo("dirval", "%s", os.str().c_str()); MacOSError::throwMe(error); // not all required rules were matched } } diff --git a/OSX/libsecurity_codesigning/lib/diskimagerep.cpp b/OSX/libsecurity_codesigning/lib/diskimagerep.cpp index be2443d1..86b056c0 100644 --- a/OSX/libsecurity_codesigning/lib/diskimagerep.cpp +++ b/OSX/libsecurity_codesigning/lib/diskimagerep.cpp @@ -69,13 +69,19 @@ bool DiskImageRep::readHeader(FileDesc& fd, UDIFFileHeader& header) // Object management. // DiskImageRep::DiskImageRep(const char *path) - : SingleDiskRep(path) + : SingleDiskRep(path), mSigningData(NULL) { this->setup(); } +DiskImageRep::~DiskImageRep() +{ + free((void*)mSigningData); +} + void DiskImageRep::setup() { + free((void*)mSigningData); mSigningData = NULL; // the UDIF "header" is in fact the last 512 bytes of the file, with no particular alignment @@ -211,7 +217,7 @@ void DiskImageRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef // void DiskImageRep::Writer::flush() { - delete mSigningData; // ditch previous blob just in case + free((void*)mSigningData); // ditch previous blob just in case mSigningData = Maker::make(); // assemble new signature SuperBlob // write signature superblob diff --git a/OSX/libsecurity_codesigning/lib/diskimagerep.h b/OSX/libsecurity_codesigning/lib/diskimagerep.h index 91a09193..06a556e8 100644 --- a/OSX/libsecurity_codesigning/lib/diskimagerep.h +++ b/OSX/libsecurity_codesigning/lib/diskimagerep.h @@ -43,6 +43,7 @@ namespace CodeSigning { class DiskImageRep : public SingleDiskRep { public: DiskImageRep(const char *path); + virtual ~DiskImageRep(); CFDataRef identification(); CFDataRef component(CodeDirectory::SpecialSlot slot); @@ -70,7 +71,7 @@ private: UDIFFileHeader mHeader; // disk image header (all fields NBO) size_t mEndOfDataOffset; // end of payload data (data fork + XML) size_t mHeaderOffset; // trailing header offset - const EmbeddedSignatureBlob *mSigningData; // pointer to signature SuperBlob (in mapped memory) + const EmbeddedSignatureBlob *mSigningData; // pointer to signature SuperBlob (malloc'd memory during setup) }; diff --git a/OSX/libsecurity_codesigning/lib/diskrep.cpp b/OSX/libsecurity_codesigning/lib/diskrep.cpp index 0fd4ede8..32cf28cf 100644 --- a/OSX/libsecurity_codesigning/lib/diskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/diskrep.cpp @@ -216,7 +216,7 @@ void DiskRep::flush() // nothing cached } -CFDictionaryRef DiskRep::diskRepInformation() +CFDictionaryRef DiskRep::copyDiskRepInformation() { return NULL; } diff --git a/OSX/libsecurity_codesigning/lib/diskrep.h b/OSX/libsecurity_codesigning/lib/diskrep.h index 1f1a10c5..e7abf97f 100644 --- a/OSX/libsecurity_codesigning/lib/diskrep.h +++ b/OSX/libsecurity_codesigning/lib/diskrep.h @@ -80,7 +80,7 @@ public: virtual CFArrayRef modifiedFiles(); // list of files modified by signing [main execcutable only] virtual UnixPlusPlus::FileDesc &fd() = 0; // a cached file descriptor for main executable file virtual void flush(); // flush caches (refetch as needed) - virtual CFDictionaryRef diskRepInformation(); // information from diskrep + virtual CFDictionaryRef copyDiskRepInformation(); // information from diskrep virtual void registerStapledTicket(); diff --git a/OSX/libsecurity_codesigning/lib/machorep.cpp b/OSX/libsecurity_codesigning/lib/machorep.cpp index 02e7faa8..0101bb26 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.cpp +++ b/OSX/libsecurity_codesigning/lib/machorep.cpp @@ -25,6 +25,7 @@ // machorep - DiskRep mix-in for handling Mach-O main executables // #include "machorep.h" +#include "notarization.h" #include "StaticCode.h" #include "reqmaker.h" #include @@ -53,7 +54,7 @@ MachORep::MachORep(const char *path, const Context *ctx) if (ctx->offset) mExecutable = new Universal(fd(), (size_t)ctx->offset, ctx->size); else if (ctx->arch) { - auto_ptr full(new Universal(fd())); + unique_ptr full(new Universal(fd())); mExecutable = new Universal(fd(), full->archOffset(ctx->arch), full->archLength(ctx->arch)); } else mExecutable = new Universal(fd()); @@ -109,31 +110,46 @@ Universal *MachORep::mainExecutableImage() void MachORep::prepareForSigning(SigningContext &context) { if (context.digestAlgorithms().empty()) { - auto_ptr macho(mainExecutableImage()->architecture()); - - uint32_t limit = 0; - switch (macho->platform()) { - case 0: - // If we don't know the platform, we stay agile. - return; - case PLATFORM_MACOS: - // 10.11.4 had first proper sha256 support. - limit = (10 << 16 | 11 << 8 | 4 << 0); - break; - case PLATFORM_TVOS: - case PLATFORM_IOS: - // iOS 11 and tvOS 11 had first proper sha256 support. - limit = (11 << 16 | 0 << 8 | 0 << 0); - break; - case PLATFORM_WATCHOS: - // We stay agile on the watch right now. - return; - default: - // All other platforms are assumed to be new and support SHA256. - break; + bool requiresAgileHashes = false; + + Universal::Architectures architectures; + mExecutable->architectures(architectures); + + for (Universal::Architectures::const_iterator arch = architectures.begin(); arch != architectures.end(); ++arch) { + unique_ptr slice(mExecutable->architecture(*arch)); + + uint32_t limit = 0; + switch (slice->platform()) { + case 0: + // If we don't know the platform, we stay agile. + requiresAgileHashes = true; + continue; + case PLATFORM_MACOS: + // 10.11.4 had first proper sha256 support. + limit = (10 << 16 | 11 << 8 | 4 << 0); + break; + case PLATFORM_TVOS: + case PLATFORM_IOS: + // iOS 11 and tvOS 11 had first proper sha256 support. + limit = (11 << 16 | 0 << 8 | 0 << 0); + break; + case PLATFORM_WATCHOS: + // We stay agile on the watch right now. + requiresAgileHashes = true; + continue; + default: + // All other platforms are assumed to be new and support SHA256. + continue; + } + if (slice->minVersion() < limit) { + // If any slice has a min version less than the limit, than we must remain agile. + requiresAgileHashes = true; + } } - if (macho->minVersion() >= limit) { - // young enough not to need SHA-1 legacy support + + // Only if every slice met the minimum requirements can we set the digest algorithm to SHA256. + // Otherwise, we leave it empty and let it pick the default which will include legacy hash types. + if (!requiresAgileHashes) { context.setDigestAlgorithm(kSecCodeSignatureHashSHA256); } } @@ -150,19 +166,22 @@ size_t MachORep::signingBase() size_t MachORep::signingLimit() { - auto_ptr macho(mExecutable->architecture()); + unique_ptr macho(mExecutable->architecture()); return macho->signingExtent(); } bool MachORep::needsExecSeg(const MachO& macho) { uint32_t platform = macho.platform(); - // Everything embedded gets an exec segment. - return platform != 0 && platform != PLATFORM_MACOS; + + // Everything gets an exec segment. This is ignored + // on non-PPL devices, and explicitly wastes some + // space on those devices, but is simpler logic. + return platform != 0; } size_t MachORep::execSegBase(const Architecture *arch) { - auto_ptr macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture()); + unique_ptr macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture()); if (!needsExecSeg(*macho)) { return 0; @@ -187,7 +206,7 @@ size_t MachORep::execSegBase(const Architecture *arch) size_t MachORep::execSegLimit(const Architecture *arch) { - auto_ptr macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture()); + unique_ptr macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture()); if (!needsExecSeg(*macho)) { return 0; @@ -218,7 +237,7 @@ size_t MachORep::execSegLimit(const Architecture *arch) // CFDataRef MachORep::identification() { - std::auto_ptr macho(mainExecutableImage()->architecture()); + std::unique_ptr macho(mainExecutableImage()->architecture()); return identificationFor(macho.get()); } @@ -271,6 +290,12 @@ CFDataRef MachORep::component(CodeDirectory::SpecialSlot slot) EditableDiskRep::RawComponentMap MachORep::createRawComponents() { EditableDiskRep::RawComponentMap blobMap; + + // First call to signingData() caches the result, so this + // _should_ not cause performance issues. + if (NULL == signingData()) { + MacOSError::throwMe(errSecCSUnsigned); + } const EmbeddedSignatureBlob &blobs = *signingData(); for (unsigned int i = 0; i < blobs.count(); ++i) { @@ -304,7 +329,7 @@ CFDataRef MachORep::embeddedComponent(CodeDirectory::SpecialSlot slot) EmbeddedSignatureBlob *MachORep::signingData() { if (!mSigningData) { // fetch and cache - auto_ptr macho(mainExecutableImage()->architecture()); + unique_ptr macho(mainExecutableImage()->architecture()); if (macho.get()) if (const linkedit_data_command *cs = macho->findCodeSignature()) { size_t offset = macho->flip(cs->dataoff); @@ -332,7 +357,7 @@ CFDataRef MachORep::infoPlist() { CFRef info; try { - auto_ptr macho(mainExecutableImage()->architecture()); + unique_ptr macho(mainExecutableImage()->architecture()); if (const section *sect = macho->findSection("__TEXT", "__info_plist")) { if (macho->is64()) { const section_64 *sect64 = reinterpret_cast(sect); @@ -389,9 +414,9 @@ void MachORep::flush() mExecutable = new Universal(fd(), offset, length); } -CFDictionaryRef MachORep::diskRepInformation() +CFDictionaryRef MachORep::copyDiskRepInformation() { - auto_ptr macho (mainExecutableImage()->architecture()); + unique_ptr macho (mainExecutableImage()->architecture()); CFRef info; uint32_t platform = 0; @@ -469,7 +494,7 @@ const Requirements *MachORep::defaultRequirements(const Architecture *arch, cons Requirement *MachORep::libraryRequirements(const Architecture *arch, const SigningContext &ctx) { - auto_ptr macho(mainExecutableImage()->architecture(*arch)); + unique_ptr macho(mainExecutableImage()->architecture(*arch)); Requirement::Maker maker; Requirement::Maker::Chain chain(maker, opOr); @@ -564,6 +589,14 @@ void MachORep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data MacOSError::throwMe(errSecCSInternalError); } +void MachORep::registerStapledTicket() +{ + CFRef data = NULL; + if (mSigningData) { + data.take(mSigningData->component(cdTicketSlot)); + registerStapledTicketInMachO(data); + } +} } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/machorep.h b/OSX/libsecurity_codesigning/lib/machorep.h index ef2181bb..d66b5307 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.h +++ b/OSX/libsecurity_codesigning/lib/machorep.h @@ -60,7 +60,7 @@ public: size_t execSegBase(const Architecture *arch); size_t execSegLimit(const Architecture *arch); std::string format(); - CFDictionaryRef diskRepInformation(); + CFDictionaryRef copyDiskRepInformation(); std::string recommendedIdentifier(const SigningContext &ctx); const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx); @@ -71,6 +71,7 @@ public: void flush(); // flush cache static bool candidate(UnixPlusPlus::FileDesc &fd); + void registerStapledTicket(); public: static CFDataRef identificationFor(MachO *macho); diff --git a/OSX/libsecurity_codesigning/lib/notarization.cpp b/OSX/libsecurity_codesigning/lib/notarization.cpp index fa75c0d0..6587dccd 100644 --- a/OSX/libsecurity_codesigning/lib/notarization.cpp +++ b/OSX/libsecurity_codesigning/lib/notarization.cpp @@ -49,9 +49,9 @@ registerStapledTicketWithSystem(CFDataRef data) secinfo("notarization", "Registering stapled ticket with system"); #if TARGET_OS_OSX - CFErrorRef error = NULL; - if (!SecAssessmentTicketRegister(data, &error)) { - secerror("Error registering stapled ticket: %@", data); + CFRef error; + if (!SecAssessmentTicketRegister(data, &error.aref())) { + secerror("Error registering stapled ticket: %@", error.get()); } #endif // TARGET_OS_OSX } @@ -208,7 +208,7 @@ registerStapledTicketInPackage(const std::string& path) goto lb_exit; } - data = CFDataCreateWithBytesNoCopy(NULL, ticketData, trailer.length, NULL); + data.take(makeCFDataMalloc(ticketData, trailer.length)); if (data.get() == NULL) { secerror("unable to create cfdata for notarization"); goto lb_exit; @@ -221,9 +221,6 @@ lb_exit: if (fd) { close(fd); } - if (ticketData) { - free(ticketData); - } } void @@ -277,7 +274,7 @@ registerStapledTicketInBundle(const std::string& path) goto lb_exit; } - data = CFDataCreateWithBytesNoCopy(NULL, ticketData, ticketLength, NULL); + data.take(makeCFDataMalloc(ticketData, ticketLength)); if (data.get() == NULL) { secerror("unable to create cfdata for notarization"); goto lb_exit; @@ -290,9 +287,6 @@ lb_exit: if (fd) { close(fd); } - if (ticketData) { - free(ticketData); - } } void @@ -305,5 +299,15 @@ registerStapledTicketInDMG(CFDataRef ticketData) registerStapledTicketWithSystem(ticketData); } +void +registerStapledTicketInMachO(CFDataRef ticketData) +{ + if (ticketData == NULL) { + return; + } + secinfo("notarization", "successfully found stapled ticket in MachO"); + registerStapledTicketWithSystem(ticketData); +} + } } diff --git a/OSX/libsecurity_codesigning/lib/notarization.h b/OSX/libsecurity_codesigning/lib/notarization.h index 21ae3c16..1e2a22b4 100644 --- a/OSX/libsecurity_codesigning/lib/notarization.h +++ b/OSX/libsecurity_codesigning/lib/notarization.h @@ -44,6 +44,7 @@ bool isNotarized(const Requirement::Context *context); void registerStapledTicketInPackage(const std::string& path); void registerStapledTicketInBundle(const std::string& path); void registerStapledTicketInDMG(CFDataRef ticketData); +void registerStapledTicketInMachO(CFDataRef ticketData); } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/piddiskrep.cpp b/OSX/libsecurity_codesigning/lib/piddiskrep.cpp index 0aeeb81e..7f74d24b 100644 --- a/OSX/libsecurity_codesigning/lib/piddiskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/piddiskrep.cpp @@ -86,10 +86,11 @@ PidDiskRep::fetchData(void) xpc_release(request); xpc_release(conn); - if (!mBundleURL) + if (!mBundleURL) { MacOSError::throwMe(errSecCSNoSuchCode); - - mDataFetched = true; + } + + mDataFetched = true; } diff --git a/OSX/libsecurity_codesigning/lib/policyengine.cpp b/OSX/libsecurity_codesigning/lib/policyengine.cpp index a2993716..a6fe9dd3 100644 --- a/OSX/libsecurity_codesigning/lib/policyengine.cpp +++ b/OSX/libsecurity_codesigning/lib/policyengine.cpp @@ -389,7 +389,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment CFCopyRef code; MacOSError::check(SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags | kSecCSForceOnlineNotarizationCheck, &code.aref())); - SecCSFlags validationFlags = kSecCSEnforceRevocationChecks | kSecCSCheckAllArchitectures; + SecCSFlags validationFlags = kSecCSEnforceRevocationChecks | kSecCSCheckAllArchitectures | kSecCSAllowNetworkAccess; if (!(flags & kSecAssessmentFlagAllowWeak)) validationFlags |= kSecCSStrictValidate; adjustValidation(code); diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.cpp b/OSX/libsecurity_codesigning/lib/reqinterp.cpp index 4ff17212..f3970650 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.cpp +++ b/OSX/libsecurity_codesigning/lib/reqinterp.cpp @@ -34,10 +34,20 @@ #include #include #include +#include #include "csutilities.h" #include "notarization.h" #include "legacydevid.h" +#define WAITING_FOR_LIB_AMFI_INTERFACE 1 + +#if WAITING_FOR_LIB_AMFI_INTERFACE +#define __mac_syscall __sandbox_ms +#include + +#define AMFI_INTF_CD_HASH_LEN 20 +#endif + namespace Security { namespace CodeSigning { @@ -242,7 +252,6 @@ bool Requirement::Interpreter::entitlementValue(const string &key, const Match & bool Requirement::Interpreter::certFieldValue(const string &key, const Match &match, SecCertificateRef cert) { -// XXX: Not supported on embedded yet due to lack of supporting API #if TARGET_OS_OSX // no cert, no chance if (cert == NULL) @@ -251,32 +260,31 @@ bool Requirement::Interpreter::certFieldValue(const string &key, const Match &ma // a table of recognized keys for the "certificate[foo]" syntax static const struct CertField { const char *name; - const CSSM_OID *oid; + const DERItem *oid; } certFields[] = { - { "subject.C", &CSSMOID_CountryName }, - { "subject.CN", &CSSMOID_CommonName }, - { "subject.D", &CSSMOID_Description }, - { "subject.L", &CSSMOID_LocalityName }, + { "subject.C", &oidCountryName}, + { "subject.CN", &oidCommonName }, + { "subject.D", &oidDescription }, + { "subject.L", &oidLocalityName }, // { "subject.C-L", &CSSMOID_CollectiveLocalityName }, // missing from Security.framework headers - { "subject.O", &CSSMOID_OrganizationName }, - { "subject.C-O", &CSSMOID_CollectiveOrganizationName }, - { "subject.OU", &CSSMOID_OrganizationalUnitName }, - { "subject.C-OU", &CSSMOID_CollectiveOrganizationalUnitName }, - { "subject.ST", &CSSMOID_StateProvinceName }, - { "subject.C-ST", &CSSMOID_CollectiveStateProvinceName }, - { "subject.STREET", &CSSMOID_StreetAddress }, - { "subject.C-STREET", &CSSMOID_CollectiveStreetAddress }, - { "subject.UID", &CSSMOID_UserID }, + { "subject.O", &oidOrganizationName }, + { "subject.C-O", &oidCollectiveOrganizationName }, + { "subject.OU", &oidOrganizationalUnitName}, + { "subject.C-OU", &oidCollectiveOrganizationalUnitName}, + { "subject.ST", &oidStateOrProvinceName}, + { "subject.C-ST", &oidCollectiveStateOrProvinceName }, + { "subject.STREET", &oidStreetAddress }, + { "subject.C-STREET", &oidCollectiveStreetAddress }, + { "subject.UID", &oidUserId }, { NULL, NULL } }; // DN-component single-value match for (const CertField *cf = certFields; cf->name; cf++) if (cf->name == key) { - CFRef value; - OSStatus rc = SecCertificateCopySubjectComponent(cert, cf->oid, &value.aref()); - if (rc) { - secinfo("csinterp", "cert %p lookup for DN.%s failed rc=%d", cert, key.c_str(), (int)rc); + CFRef value(SecCertificateCopySubjectAttributeValue(cert, (DERItem *)cf->oid)); + if (!value.get()) { + secinfo("csinterp", "cert %p lookup for DN.%s failed", cert, key.c_str()); return false; } return match(value); @@ -403,14 +411,15 @@ CFArrayRef Requirement::Interpreter::getAdditionalTrustedAnchors() bool Requirement::Interpreter::appleLocalAnchored() { - static CFArrayRef additionalTrustedCertificates = NULL; + static CFArrayRef additionalTrustedCertificates = NULL; - if (csr_check(CSR_ALLOW_APPLE_INTERNAL)) + if (csr_check(CSR_ALLOW_APPLE_INTERNAL)) { return false; + } - if (mContext->forcePlatform) { - return true; - } + if (mContext->forcePlatform) { + return true; + } static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -430,18 +439,76 @@ bool Requirement::Interpreter::appleLocalAnchored() return false; } +#if WAITING_FOR_LIB_AMFI_INTERFACE +// These bits are here until we get get a new build alias for libamfi-interface. + +#define MAC_AMFI_POLICY_NAME "AMFI" + +#define AMFI_SYSCALL_CDHASH_IN_TRUSTCACHE 95 + +typedef struct amfi_cdhash_in_trustcache_ { + uint8_t cdhash[20]; + uint64_t result; +} amfi_cdhash_in_trustcache_t; + +static int +__amfi_interface_cdhash_in_trustcache(const uint8_t cdhash[], uint64_t* trustcache_result) +{ + amfi_cdhash_in_trustcache_t args; + static_assert(AMFI_INTF_CD_HASH_LEN == sizeof(args.cdhash), "Error: cdhash length mismatch"); + int err; + memcpy(args.cdhash, cdhash, sizeof(args.cdhash)); + args.result = 0; + err = __mac_syscall(MAC_AMFI_POLICY_NAME, AMFI_SYSCALL_CDHASH_IN_TRUSTCACHE, &args); + if (err) { + err = errno; + } + *trustcache_result = args.result; + return err; +} + +static int +amfi_interface_cdhash_in_trustcache(const uint8_t cdhash[], size_t cdhash_len, uint64_t* trustcache_result) +{ + int err = EINVAL; + + if (cdhash == nullptr || cdhash_len != AMFI_INTF_CD_HASH_LEN || trustcache_result == nullptr) { + goto lb_end; + } + *trustcache_result = 0; + + err = __amfi_interface_cdhash_in_trustcache(cdhash, trustcache_result); + +lb_end: + return err; +} +#endif + +bool Requirement::Interpreter::inTrustCache() +{ + uint64_t result = 0; + CFRef cdhashRef = mContext->directory->cdhash(true); + const uint8_t *cdhash = CFDataGetBytePtr(cdhashRef); + size_t cdhash_len = CFDataGetLength(cdhashRef); + int err = amfi_interface_cdhash_in_trustcache(cdhash, cdhash_len, &result); + return (err == 0) && (result != 0); +} + bool Requirement::Interpreter::appleSigned() { - if (appleAnchored()) { - if (SecCertificateRef intermed = mContext->cert(-2)) // first intermediate - // first intermediate common name match (exact) - if (certFieldValue("subject.CN", Match(appleIntermediateCN, matchEqual), intermed) - && certFieldValue("subject.O", Match(appleIntermediateO, matchEqual), intermed)) - return true; + if (inTrustCache()) { + return true; + } + else if (appleAnchored()) { + if (SecCertificateRef intermed = mContext->cert(-2)) // first intermediate + // first intermediate common name match (exact) + if (certFieldValue("subject.CN", Match(appleIntermediateCN, matchEqual), intermed) + && certFieldValue("subject.O", Match(appleIntermediateO, matchEqual), intermed)) + return true; } else if (appleLocalAnchored()) { return true; - } - return false; + } + return false; } @@ -453,15 +520,7 @@ bool Requirement::Interpreter::verifyAnchor(SecCertificateRef cert, const unsign // get certificate bytes if (cert) { SHA1 hasher; -#if TARGET_OS_OSX - CSSM_DATA certData; - MacOSError::check(SecCertificateGetData(cert, &certData)); - - // verify hash - hasher(certData.Data, certData.Length); -#else hasher(SecCertificateGetBytePtr(cert), SecCertificateGetLength(cert)); -#endif return hasher.verify(digest); } return false; diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.h b/OSX/libsecurity_codesigning/lib/reqinterp.h index 83b2fb02..7e828f5e 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.h +++ b/OSX/libsecurity_codesigning/lib/reqinterp.h @@ -88,6 +88,7 @@ protected: bool verifyAnchor(SecCertificateRef cert, const unsigned char *digest); bool appleSigned(); bool appleAnchored(); + bool inTrustCache(); bool trustedCerts(); bool trustedCert(int slot); diff --git a/OSX/libsecurity_codesigning/lib/resources.cpp b/OSX/libsecurity_codesigning/lib/resources.cpp index 221e2984..52d8357f 100644 --- a/OSX/libsecurity_codesigning/lib/resources.cpp +++ b/OSX/libsecurity_codesigning/lib/resources.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2006-2021 Apple Inc. All Rights Reserved. + * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -35,7 +35,7 @@ // These are pretty nasty, but are a quick safe fix // to pass information down to the gatekeeper collection tool extern "C" { - int GKBIS_DS_Store_Present; + int GKBIS_DS_Store_Present; int GKBIS_Dot_underbar_Present; int GKBIS_Num_localizations; int GKBIS_Num_files; @@ -49,36 +49,41 @@ namespace CodeSigning { static string removeTrailingSlash(string path) { - if (path.substr(path.length()-2, 2) == "/.") + if (path.substr(path.length()-2, 2) == "/.") { return path.substr(0, path.length()-2); - else if (path.substr(path.length()-1, 1) == "/") + } else if (path.substr(path.length()-1, 1) == "/") { return path.substr(0, path.length()-1); - else + } else { return path; + } } // // Construction and maintainance // ResourceBuilder::ResourceBuilder(const std::string &root, const std::string &relBase, - CFDictionaryRef rulesDict, bool strict, const MacOSErrorSet& toleratedErrors) - : mCheckUnreadable(strict && toleratedErrors.find(errSecCSSignatureNotVerifiable) == toleratedErrors.end()), - mCheckUnknownType(strict && toleratedErrors.find(errSecCSResourceNotSupported) == toleratedErrors.end()) + CFDictionaryRef rulesDict, bool strict, const MacOSErrorSet& toleratedErrors) + : mCheckUnreadable(strict && toleratedErrors.find(errSecCSSignatureNotVerifiable) == toleratedErrors.end()), + mCheckUnknownType(strict && toleratedErrors.find(errSecCSResourceNotSupported) == toleratedErrors.end()) { assert(!root.empty()); char realroot[PATH_MAX]; - if (realpath(root.c_str(), realroot) == NULL) + if (realpath(root.c_str(), realroot) == NULL) { UnixError::throwMe(); + } mRoot = realroot; - if (realpath(removeTrailingSlash(relBase).c_str(), realroot) == NULL) + if (realpath(removeTrailingSlash(relBase).c_str(), realroot) == NULL) { UnixError::throwMe(); + } mRelBase = realroot; - if (mRoot != mRelBase && mRelBase != mRoot + "/Contents") + if (mRoot != mRelBase && mRelBase != mRoot + "/Contents") { MacOSError::throwMe(errSecCSBadBundleFormat); + } const char * paths[2] = { mRoot.c_str(), NULL }; mFTS = fts_open((char * const *)paths, FTS_PHYSICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL); - if (!mFTS) + if (!mFTS) { UnixError::throwMe(); + } mRawRules = rulesDict; CFDictionary rules(rulesDict, errSecCSResourceRulesInvalid); rules.apply(this, &ResourceBuilder::addRule); @@ -86,8 +91,9 @@ ResourceBuilder::ResourceBuilder(const std::string &root, const std::string &rel ResourceBuilder::~ResourceBuilder() { - for (Rules::iterator it = mRules.begin(); it != mRules.end(); ++it) + for (Rules::iterator it = mRules.begin(); it != mRules.end(); ++it) { delete *it; + } fts_close(mFTS); // do not check error - it's not worth aborting over (double fault etc.) } @@ -101,47 +107,74 @@ void ResourceBuilder::addRule(CFTypeRef key, CFTypeRef value) unsigned weight = 1; uint32_t flags = 0; if (CFGetTypeID(value) == CFBooleanGetTypeID()) { - if (value == kCFBooleanFalse) + if (value == kCFBooleanFalse) { flags |= omitted; + } } else { CFDictionary rule(value, errSecCSResourceRulesInvalid); - if (CFNumberRef weightRef = rule.get("weight")) + if (CFNumberRef weightRef = rule.get("weight")) { weight = cfNumber(weightRef); - if (CFBooleanRef omitRef = rule.get("omit")) - if (omitRef == kCFBooleanTrue) + } + if (CFBooleanRef omitRef = rule.get("omit")) { + if (omitRef == kCFBooleanTrue) { flags |= omitted; - if (CFBooleanRef optRef = rule.get("optional")) - if (optRef == kCFBooleanTrue) + } + } + if (CFBooleanRef optRef = rule.get("optional")) { + if (optRef == kCFBooleanTrue) { flags |= optional; - if (CFBooleanRef nestRef = rule.get("nested")) - if (nestRef == kCFBooleanTrue) + } + } + if (CFBooleanRef nestRef = rule.get("nested")) { + if (nestRef == kCFBooleanTrue) { flags |= nested; + } + } } + // All rules coming in through addRule come from the user supplied data, so make that clear. + flags |= user_controlled; addRule(new Rule(pattern, weight, flags)); } static bool findStringEndingNoCase(const char *path, const char * end) { - size_t len_path = strlen(path); - size_t len_end = strlen(end); - - if (len_path >= len_end) { - return strcasecmp(path + (len_path - len_end), end) == 0; - } else - return false; + size_t len_path = strlen(path); + size_t len_end = strlen(end); + + if (len_path >= len_end) { + return strcasecmp(path + (len_path - len_end), end) == 0; + } else { + return false; + } +} + +void ResourceBuilder::scan(Scanner next) +{ + scan(next, nil); } // // Locate the next non-ignored file, look up its rule, and return it. +// If the unhandledScanner is passed, call it with items the original scan may +// have chosen to skip. // Returns NULL when we're out of files. // -void ResourceBuilder::scan(Scanner next) +void ResourceBuilder::scan(Scanner next, Scanner unhandledScanner) { bool first = true; + // The FTS scan needs to visit skipped regions if the caller is requesting callbacks + // for anything unhandled. In that case, don't skip the entries in FTS but instead + // keep track of entry and exit locally. + bool visitSkippedDirectories = (unhandledScanner != NULL); + bool isSkippingDirectory = false; + string skippingDirectoryRoot; + while (FTSENT *ent = fts_read(mFTS)) { static const char ds_store[] = ".DS_Store"; const char *relpath = ent->fts_path + mRoot.size(); // skip prefix + bool wasScanned = false; + Rule *rule = NULL; if (strlen(relpath) > 0) { relpath += 1; // skip "/" @@ -151,76 +184,116 @@ void ResourceBuilder::scan(Scanner next) if (mRelBase != mRoot) { assert(mRelBase == mRoot + "/Contents"); rp = "../" + string(relpath); - if (rp.substr(0, 12) == "../Contents/") + if (rp.substr(0, 12) == "../Contents/") { rp = rp.substr(12); + } relpath = rp.c_str(); } switch (ent->fts_info) { - case FTS_F: - secinfo("rdirenum", "file %s", ent->fts_path); - GKBIS_Num_files++; - - // These are checks for the gatekeeper collection - static const char underbar[] = "._"; - if (strncasecmp(ent->fts_name, underbar, strlen(underbar)) == 0) - GKBIS_Dot_underbar_Present++; + case FTS_F: + secinfo("rdirenum", "file %s", ent->fts_path); + GKBIS_Num_files++; - if (strcasecmp(ent->fts_name, ds_store) == 0) - GKBIS_DS_Store_Present++; - - if (Rule *rule = findRule(relpath)) - if (!(rule->flags & (omitted | exclusion))) - next(ent, rule->flags, string(relpath), rule); - break; - case FTS_SL: - // symlinks cannot ever be nested code, so quietly convert to resource file - secinfo("rdirenum", "symlink %s", ent->fts_path); - GKBIS_Num_symlinks++; - - if (strcasecmp(ent->fts_name, ds_store) == 0) - MacOSError::throwMe(errSecCSDSStoreSymlink); - - if (Rule *rule = findRule(relpath)) - if (!(rule->flags & (omitted | exclusion))) - next(ent, rule->flags & ~nested, string(relpath), rule); - break; - case FTS_D: - secinfo("rdirenum", "entering %s", ent->fts_path); - GKBIS_Num_dirs++; - - if (!first) { // skip root directory - if (Rule *rule = findRule(relpath)) { - if (rule->flags & nested) { - if (strchr(ent->fts_name, '.')) { // nested, has extension -> treat as nested bundle - next(ent, rule->flags, string(relpath), rule); - fts_set(mFTS, ent, FTS_SKIP); - } - } else if (rule->flags & exclusion) { // exclude the whole directory - fts_set(mFTS, ent, FTS_SKIP); - } - // else treat as normal directory and descend into it + // These are checks for the gatekeeper collection + static const char underbar[] = "._"; + if (strncasecmp(ent->fts_name, underbar, strlen(underbar)) == 0) { + GKBIS_Dot_underbar_Present++; } - } - // Report the number of localizations - if (findStringEndingNoCase(ent->fts_name, ".lproj")) - GKBIS_Num_localizations++; - first = false; - break; - case FTS_DP: - secinfo("rdirenum", "leaving %s", ent->fts_path); - break; - case FTS_DNR: - secinfo("rdirenum", "cannot read directory %s", ent->fts_path); - if (mCheckUnreadable) - MacOSError::throwMe(errSecCSSignatureNotVerifiable); - break; - default: - secinfo("rdirenum", "type %d (errno %d): %s", - ent->fts_info, ent->fts_errno, ent->fts_path); - if (mCheckUnknownType) - MacOSError::throwMe(errSecCSResourceNotSupported); - break; + if (strcasecmp(ent->fts_name, ds_store) == 0) { + GKBIS_DS_Store_Present++; + } + + rule = findRule(relpath); + if (rule && !isSkippingDirectory) { + if (!(rule->flags & (omitted | exclusion))) { + wasScanned = true; + next(ent, rule->flags, string(relpath), rule); + } + } + + if (unhandledScanner && !wasScanned) { + unhandledScanner(ent, rule ? rule->flags : 0, string(relpath), rule); + } + + break; + case FTS_SL: + // symlinks cannot ever be nested code, so quietly convert to resource file + secinfo("rdirenum", "symlink %s", ent->fts_path); + GKBIS_Num_symlinks++; + + if (strcasecmp(ent->fts_name, ds_store) == 0) { + MacOSError::throwMe(errSecCSDSStoreSymlink); + } + + rule = findRule(relpath); + if (rule && !isSkippingDirectory) { + if (!(rule->flags & (omitted | exclusion))) { + wasScanned = true; + next(ent, rule->flags & ~nested, string(relpath), rule); + } + } + + if (unhandledScanner && !wasScanned) { + unhandledScanner(ent, rule ? rule->flags : 0, string(relpath), rule); + } + + break; + case FTS_D: + secinfo("rdirenum", "entering %s", ent->fts_path); + GKBIS_Num_dirs++; + + // Directories don't need to worry about calling the unhandled scanner directly because + // we'll always traverse deeply to visit anything inside, even if it was inside + // an exlusion rule. + + if (!first && !isSkippingDirectory) { // skip root directory or anything we're skipping + rule = findRule(relpath); + if (rule) { + if (rule->flags & nested) { + if (strchr(ent->fts_name, '.')) { // nested, has extension -> treat as nested bundle + wasScanned = true; + next(ent, rule->flags, string(relpath), rule); + fts_set(mFTS, ent, FTS_SKIP); + } + } else if (rule->flags & exclusion) { // exclude the whole directory + if (visitSkippedDirectories) { + isSkippingDirectory = true; + skippingDirectoryRoot = relpath; + secinfo("rdirenum", "entering excluded path: %s", skippingDirectoryRoot.c_str()); + } else { + fts_set(mFTS, ent, FTS_SKIP); + } + } + } + } + + // Report the number of localizations + if (findStringEndingNoCase(ent->fts_name, ".lproj")) { + GKBIS_Num_localizations++; + } + first = false; + break; + case FTS_DP: + secinfo("rdirenum", "leaving %s", ent->fts_path); + if (isSkippingDirectory && skippingDirectoryRoot == relpath) { + secinfo("rdirenum", "exiting excluded path: %s", skippingDirectoryRoot.c_str()); + isSkippingDirectory = false; + skippingDirectoryRoot.clear(); + } + break; + case FTS_DNR: + secinfo("rdirenum", "cannot read directory %s", ent->fts_path); + if (mCheckUnreadable) { + MacOSError::throwMe(errSecCSSignatureNotVerifiable); + } + break; + default: + secinfo("rdirenum", "type %d (errno %d): %s", ent->fts_info, ent->fts_errno, ent->fts_path); + if (mCheckUnknownType) { + MacOSError::throwMe(errSecCSResourceNotSupported); + } + break; } } } @@ -233,16 +306,20 @@ bool ResourceBuilder::includes(string path) const { // process first-directory exclusions size_t firstslash = path.find('/'); - if (firstslash != string::npos) - if (Rule *rule = findRule(path.substr(0, firstslash))) - if (rule->flags & exclusion) + if (firstslash != string::npos) { + if (Rule *rule = findRule(path.substr(0, firstslash))) { + if (rule->flags & exclusion) { return rule->flags & softTarget; + } + } + } // process full match - if (Rule *rule = findRule(path)) + if (Rule *rule = findRule(path)) { return !(rule->flags & (omitted | exclusion)) || (rule->flags & softTarget); - else + } else { return false; + } } @@ -263,21 +340,22 @@ ResourceBuilder::Rule *ResourceBuilder::findRule(string path) const secinfo("rscan", "excluded"); return rule; } - if (!bestRule || rule->weight > bestRule->weight) + if (!bestRule || rule->weight > bestRule->weight) { bestRule = rule; - + } #if TARGET_OS_WATCH -/* rdar://problem/30517969 */ - if (bestRule && bestRule->weight == rule->weight && !(bestRule->flags & omitted) && (rule->flags & omitted)) + /* rdar://problem/30517969 */ + if (bestRule && bestRule->weight == rule->weight && !(bestRule->flags & omitted) && (rule->flags & omitted)) { bestRule = rule; + } #endif } } secinfo("rscan", "choosing %s (%d,0x%x)", - bestRule ? bestRule->source.c_str() : "NOTHING", - bestRule ? bestRule->weight : 0, - bestRule ? bestRule->flags : 0); + bestRule ? bestRule->source.c_str() : "NOTHING", + bestRule ? bestRule->weight : 0, + bestRule ? bestRule->flags : 0); return bestRule; } @@ -293,8 +371,7 @@ CFDataRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorit hashFileData(fd, hasher.get()); vector digest_vector(hasher->digestLength()); hasher->finish(digest_vector.data()); - return CFDataCreate(NULL, digest_vector.data(), - digest_vector.size() * sizeof(Hashing::Byte)); + return CFDataCreate(NULL, digest_vector.data(), digest_vector.size() * sizeof(Hashing::Byte)); } @@ -305,9 +382,11 @@ CFMutableDictionaryRef ResourceBuilder::hashFile(const char *path, CodeDirectory { UnixPlusPlus::AutoFileDesc fd(path); fd.fcntl(F_NOCACHE, true); // turn off page caching (one-pass) - if (strictCheck) - if (fd.hasExtendedAttribute(XATTR_RESOURCEFORK_NAME) || fd.hasExtendedAttribute(XATTR_FINDERINFO_NAME)) + if (strictCheck) { + if (fd.hasExtendedAttribute(XATTR_RESOURCEFORK_NAME) || fd.hasExtendedAttribute(XATTR_FINDERINFO_NAME)) { MacOSError::throwMe(errSecCSInvalidAssociatedFileData); + } + } CFRef result = makeCFMutableDictionary(); CFMutableDictionaryRef resultRef = result; CodeDirectory::multipleHashFileData(fd, 0, types, ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) { @@ -318,17 +397,17 @@ CFMutableDictionaryRef ResourceBuilder::hashFile(const char *path, CodeDirectory }); return result.yield(); } - - + + std::string ResourceBuilder::hashName(CodeDirectory::HashAlgorithm type) { switch (type) { - case kSecCodeSignatureHashSHA1: - return "hash"; - default: - char name[20]; - snprintf(name, sizeof(name), "hash%d", int(type)); - return name; + case kSecCodeSignatureHashSHA1: + return "hash"; + default: + char name[20]; + snprintf(name, sizeof(name), "hash%d", int(type)); + return name; } } @@ -339,10 +418,10 @@ std::string ResourceBuilder::hashName(CodeDirectory::HashAlgorithm type) ResourceBuilder::Rule::Rule(const std::string &pattern, unsigned w, uint32_t f) : weight(w), flags(f), source(pattern) { - if (::regcomp(this, pattern.c_str(), REG_EXTENDED | REG_NOSUB)) //@@@ REG_ICASE? + if (::regcomp(this, pattern.c_str(), REG_EXTENDED | REG_NOSUB)) { //@@@ REG_ICASE? MacOSError::throwMe(errSecCSResourceRulesInvalid); - secinfo("csresource", "%p rule %s added (weight %d, flags 0x%x)", - this, pattern.c_str(), w, f); + } + secinfo("csresource", "%p rule %s added (weight %d, flags 0x%x)", this, pattern.c_str(), w, f); } ResourceBuilder::Rule::~Rule() @@ -353,12 +432,12 @@ ResourceBuilder::Rule::~Rule() bool ResourceBuilder::Rule::match(const char *s) const { switch (::regexec(this, s, 0, NULL, 0)) { - case 0: - return true; - case REG_NOMATCH: - return false; - default: - MacOSError::throwMe(errSecCSResourceRulesInvalid); + case 0: + return true; + case REG_NOMATCH: + return false; + default: + MacOSError::throwMe(errSecCSResourceRulesInvalid); } } @@ -368,8 +447,9 @@ std::string ResourceBuilder::escapeRE(const std::string &s) string r; for (string::const_iterator it = s.begin(); it != s.end(); ++it) { char c = *it; - if (strchr("\\[]{}().+*?^$|", c)) + if (strchr("\\[]{}().+*?^$|", c)) { r.push_back('\\'); + } r.push_back(c); } return r; @@ -382,40 +462,49 @@ std::string ResourceBuilder::escapeRE(const std::string &s) ResourceSeal::ResourceSeal(CFTypeRef it) : mDict(NULL), mRequirement(NULL), mLink(NULL), mFlags(0) { - if (it == NULL) + if (it == NULL) { MacOSError::throwMe(errSecCSResourcesInvalid); - if (CFGetTypeID(it) == CFDataGetTypeID()) // old-style form with just a hash + } + if (CFGetTypeID(it) == CFDataGetTypeID()) { // old-style form with just a hash mDict.take(cfmake("{hash=%O}", it)); - else if (CFGetTypeID(it) == CFDictionaryGetTypeID()) + } else if (CFGetTypeID(it) == CFDictionaryGetTypeID()) { mDict = CFDictionaryRef(it); - else + } else { MacOSError::throwMe(errSecCSResourcesInvalid); + } int optional = 0; bool err; - if (CFDictionaryGetValue(mDict, CFSTR("requirement"))) + if (CFDictionaryGetValue(mDict, CFSTR("requirement"))) { err = !cfscan(mDict, "{requirement=%SO,?optional=%B}", &mRequirement, &optional); - else if (CFDictionaryGetValue(mDict, CFSTR("symlink"))) + } else if (CFDictionaryGetValue(mDict, CFSTR("symlink"))) { err = !cfscan(mDict, "{symlink=%SO,?optional=%B}", &mLink, &optional); - else + } else { err = !cfscan(mDict, "{?optional=%B}", &optional); - if (err) + } + + if (err) { MacOSError::throwMe(errSecCSResourcesInvalid); - if (optional) + } + if (optional) { mFlags |= ResourceBuilder::optional; - if (mRequirement) + } + if (mRequirement) { mFlags |= ResourceBuilder::nested; + } } - - + + const Hashing::Byte *ResourceSeal::hash(CodeDirectory::HashAlgorithm type) const { std::string name = ResourceBuilder::hashName(type); CFTypeRef hash = CFDictionaryGetValue(mDict, CFTempString(name)); - if (hash == NULL) // pre-agility fallback + if (hash == NULL) { // pre-agility fallback hash = CFDictionaryGetValue(mDict, CFSTR("hash")); - if (hash == NULL || CFGetTypeID(hash) != CFDataGetTypeID()) + } + if (hash == NULL || CFGetTypeID(hash) != CFDataGetTypeID()) { MacOSError::throwMe(errSecCSResourcesInvalid); + } return CFDataGetBytePtr(CFDataRef(hash)); } diff --git a/OSX/libsecurity_codesigning/lib/resources.h b/OSX/libsecurity_codesigning/lib/resources.h index 7e122587..68dce1e2 100644 --- a/OSX/libsecurity_codesigning/lib/resources.h +++ b/OSX/libsecurity_codesigning/lib/resources.h @@ -61,6 +61,7 @@ public: nested = 0x04, // nested code (recursively signed) exclusion = 0x10, // overriding exclusion (stop looking) softTarget = 0x20, // valid symlink target even though omitted/excluded + user_controlled = 0x40, // whether the rule was read from a user controlled file }; typedef unsigned int Weight; @@ -84,6 +85,7 @@ public: typedef void (^Scanner)(FTSENT *ent, uint32_t flags, const std::string relpath, Rule *rule); void scan(Scanner next); + void scan(Scanner next, Scanner unhandled); bool includes(string path) const; Rule *findRule(string path) const; diff --git a/OSX/libsecurity_codesigning/lib/signer.cpp b/OSX/libsecurity_codesigning/lib/signer.cpp index 89279238..044bf91d 100644 --- a/OSX/libsecurity_codesigning/lib/signer.cpp +++ b/OSX/libsecurity_codesigning/lib/signer.cpp @@ -143,12 +143,17 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) if (CFRef infoData = rep->component(cdInfoSlot)) infoDict.take(makeCFDictionaryFrom(infoData)); - uint32_t inherit = code->isSigned() ? state.mPreserveMetadata : 0; + uint32_t inherit = 0; + + if (code->isSigned() && (code->codeDirectory(false)->flags & kSecCodeSignatureLinkerSigned) == 0) { + inherit = state.mPreserveMetadata; + } // work out the canonical identifier identifier = state.mIdentifier; - if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier)) + if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier)) { identifier = code->identifier(); + } if (identifier.empty()) { identifier = rep->recommendedIdentifier(*this); if (identifier.find('.') == string::npos) @@ -174,8 +179,6 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) entitlements = state.mEntitlementData; if (!entitlements && (inherit & kSecCodeSignerPreserveEntitlements)) entitlements = code->component(cdEntitlementSlot); - - generateEntitlementDER = signingFlags() & kSecCSSignGenerateEntitlementDER; // work out the CodeDirectory flags word bool haveCdFlags = false; @@ -409,12 +412,12 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase if (!(signingFlags() & kSecCSSignV1)) { CFCopyRef rules2 = cfget(rulesDict, "rules2"); if (!rules2) { - // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules, - // because the default weight, according to ResourceBuilder::addRule(), is 1). + // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules, + // because the default weight, according to ResourceBuilder::addRule(), is 1). // V1 rules typically do not cover these places so we'll prevail, but if they do, we defer to them. - rules2 = cfmake("{+%O" + rules2.take(cfmake("{+%O" "'^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/' = {nested=#T, weight=0}" // exclude dynamic repositories - "}", rules); + "}", rules)); } Dispatch::Group group; @@ -429,11 +432,12 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase resources.scan(^(FTSENT *ent, uint32_t ruleFlags, const std::string relpath, Rule *rule) { bool isSymlink = (ent->fts_info == FTS_SL); + bool isNested = (ruleFlags & ResourceBuilder::nested); const std::string path(ent->fts_path); const std::string accpath(ent->fts_accpath); this->state.mLimitedAsync->perform(groupRef, ^{ CFRef seal; - if (ruleFlags & ResourceBuilder::nested) { + if (isNested) { seal.take(signNested(path, relpath)); } else if (isSymlink) { char target[PATH_MAX]; @@ -445,6 +449,10 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase } else { seal.take(resources.hashFile(accpath.c_str(), digestAlgorithms(), signingFlags() & kSecCSSignStrictPreflight)); } + if (seal.get() == NULL) { + secerror("Failed to generate sealed resource: %d, %d, %s", isNested, isSymlink, accpath.c_str()); + MacOSError::throwMe(errSecCSBadResource); + } if (ruleFlags & ResourceBuilder::optional) CFDictionaryAddValue(seal, CFSTR("optional"), kCFBooleanTrue); CFTypeRef hash; @@ -481,7 +489,9 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase } if (!hash) hash.take(resources.hashFile(ent->fts_accpath, kSecCodeSignatureHashSHA1)); - if (ruleFlags == 0) { // default case - plain hash + // The user controlled rule flag is a runtime only flag and shouldn't cause use of a more + // complex resource serialization as doing so would break serialized adhoc opaque hashes. + if ((ruleFlags & ~ResourceBuilder::user_controlled) == 0) { // default case - plain hash cfadd(files, "{%s=%O}", relpath.c_str(), hash.get()); secinfo("csresource", "%s added simple (rule %p)", relpath.c_str(), rule); } else { // more complicated - use a sub-dictionary @@ -535,7 +545,7 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context if (state.mPreserveAFSC) writer->setPreserveAFSC(state.mPreserveAFSC); - auto_ptr editor(state.mDetached + unique_ptr editor(state.mDetached ? static_cast(new BlobEditor(*fat, *this)) : new MachOEditor(writer, *fat, this->digestAlgorithms(), rep->mainExecutablePath())); assert(editor->count() > 0); @@ -553,6 +563,22 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context MacOSError::throwMe(errSecCSBadLVArch); } } + + bool generateEntitlementDER = false; + if (signingFlags() & kSecCSSignGenerateEntitlementDER) { + generateEntitlementDER = true; + } else { + uint32_t platform = arch.source->platform(); + switch (platform) { + case PLATFORM_WATCHOS: + case PLATFORM_BRIDGEOS: + generateEntitlementDER = false; + break; + default: + generateEntitlementDER = true; + break; + } + } bool mainBinary = arch.source.get()->type() == MH_EXECUTE; @@ -576,7 +602,7 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context arch.source->offset(), arch.source->signingExtent(), mainBinary, rep->execSegBase(&(arch.architecture)), rep->execSegLimit(&(arch.architecture)), unsigned(digestAlgorithms().size()-1), - preEncryptHashMaps[arch.architecture], runtimeVersionToUse); + preEncryptHashMaps[arch.architecture], runtimeVersionToUse, generateEntitlementDER); }); } @@ -655,7 +681,8 @@ void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context rep->execSegBase(NULL), rep->execSegLimit(NULL), unsigned(digestAlgorithms().size()-1), preEncryptHashMaps[preEncryptMainArch], // Only one map, the default. - (cdFlags & kSecCodeSignatureRuntime) ? state.mRuntimeVersionOverride : 0); + (cdFlags & kSecCodeSignatureRuntime) ? state.mRuntimeVersionOverride : 0, + signingFlags() & kSecCSSignGenerateEntitlementDER); CodeDirectory *cd = builder.build(); if (!state.mDryRun) @@ -703,7 +730,7 @@ void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::W bool mainBinary, size_t execSegBase, size_t execSegLimit, unsigned alternateDigestCount, PreEncryptHashMap const &preEncryptHashMap, - uint32_t runtimeVersion) + uint32_t runtimeVersion, bool generateEntitlementDER) { // fill the CodeDirectory builder.executable(rep->mainExecutablePath(), pagesize, offset, length); diff --git a/OSX/libsecurity_codesigning/lib/signer.h b/OSX/libsecurity_codesigning/lib/signer.h index 960cf796..346f51ef 100644 --- a/OSX/libsecurity_codesigning/lib/signer.h +++ b/OSX/libsecurity_codesigning/lib/signer.h @@ -96,7 +96,7 @@ protected: bool mainBinary, size_t execSegBase, size_t execSegLimit, unsigned alternateDigestCount, const PreEncryptHashMap& preEncryptHashMap, - uint32_t runtimeVersion); // per-architecture + uint32_t runtimeVersion, bool generateEntitlementDER); // per-architecture CFDataRef signCodeDirectory(const CodeDirectory *cd, CFDictionaryRef hashDict, CFArrayRef hashList); @@ -146,7 +146,6 @@ private: CFAbsoluteTime signingTime; // signing time for CMS signature (0 => now) bool emitSigningTime; // emit signing time as a signed CMS attribute bool strict; // strict validation - bool generateEntitlementDER; // generate entitlement DER // Signature Editing Architecture editMainArch; // main architecture for editing diff --git a/OSX/libsecurity_codesigning/lib/signerutils.h b/OSX/libsecurity_codesigning/lib/signerutils.h index 1bd01d8c..e40752a2 100644 --- a/OSX/libsecurity_codesigning/lib/signerutils.h +++ b/OSX/libsecurity_codesigning/lib/signerutils.h @@ -103,7 +103,7 @@ public: // struct Arch : public BlobWriter { Architecture architecture; // our architecture - auto_ptr source; // Mach-O object to be signed + unique_ptr source; // Mach-O object to be signed std::map > cdBuilders; InternalRequirements ireqs; // consolidated internal requirements size_t blobSize; // calculated SuperBlob size diff --git a/OSX/libsecurity_codesigning/lib/xpcengine.cpp b/OSX/libsecurity_codesigning/lib/xpcengine.cpp index d6e37ed9..8189f0c0 100644 --- a/OSX/libsecurity_codesigning/lib/xpcengine.cpp +++ b/OSX/libsecurity_codesigning/lib/xpcengine.cpp @@ -269,11 +269,13 @@ CFDictionaryRef xpcEngineUpdate(CFTypeRef target, SecAssessmentFlags flags, CFDi msg.send(); - if (localAuthorization) + if (localAuthorization) { AuthorizationFree(localAuthorization, kAuthorizationFlagDefaults); + } - if (int64_t error = xpc_dictionary_get_int64(msg, "error")) - MacOSError::throwMe((int)error); + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) { + MacOSError::throwMe((int)error); + } size_t resultLength; const void *resultData = xpc_dictionary_get_data(msg, "result", &resultLength); diff --git a/OSX/libsecurity_codesigning/update_requirement_syntax b/OSX/libsecurity_codesigning/update_requirement_syntax old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp b/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp index bb9db996..de3b8979 100644 --- a/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp +++ b/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp @@ -55,8 +55,8 @@ class feeException protected: feeException(feeReturn frtn, const char *op); public: - ~feeException() throw() {} - feeReturn frtn() const throw() { return mFrtn; } + ~feeException() _NOEXCEPT {} + feeReturn frtn() const _NOEXCEPT { return mFrtn; } static void throwMe(feeReturn frtn, const char *op = NULL) __attribute__((noreturn)); private: feeReturn mFrtn; diff --git a/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c b/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c index 8c950d38..a26d61bc 100644 --- a/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c +++ b/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c @@ -37,7 +37,6 @@ *************************************************************/ #include -#include #include #include #include "giants.h" diff --git a/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c b/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c index bf70b3ab..cf8ac154 100644 --- a/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c +++ b/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c @@ -31,7 +31,6 @@ *************************************************************/ #include -#include #include #include"giants.h" #include "tools.h" diff --git a/OSX/libsecurity_cryptkit/lib/feeFEED.c b/OSX/libsecurity_cryptkit/lib/feeFEED.c index 9c6ae1d3..ed0ac83c 100644 --- a/OSX/libsecurity_cryptkit/lib/feeFEED.c +++ b/OSX/libsecurity_cryptkit/lib/feeFEED.c @@ -924,14 +924,6 @@ feeReturn feeFEEDDecryptBlock(feeFEED feed, return FR_BadCipherText; } - /* - * we already know how long this should be... - */ - if(finst->initialRSSize != finst->initialRSSize) { - dbgLog(("feeFEEDDecryptBlock: initialRS sync error\n")); - return FR_BadCipherText; - } - /* * Set up clues */ diff --git a/OSX/libsecurity_cssm/lib/attachment.cpp b/OSX/libsecurity_cssm/lib/attachment.cpp index 59ab540c..f697dbb1 100644 --- a/OSX/libsecurity_cssm/lib/attachment.cpp +++ b/OSX/libsecurity_cssm/lib/attachment.cpp @@ -145,28 +145,28 @@ Attachment::~Attachment() // void *Attachment::upcallMalloc(CSSM_HANDLE handle, size_t size) { - BEGIN_API + BEGIN_API_NO_METRICS return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).malloc(size); END_API1(NULL) } void Attachment::upcallFree(CSSM_HANDLE handle, void *mem) { - BEGIN_API + BEGIN_API_NO_METRICS return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).free(mem); END_API0 } void *Attachment::upcallRealloc(CSSM_HANDLE handle, void *mem, size_t size) { - BEGIN_API + BEGIN_API_NO_METRICS return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).realloc(mem, size); END_API1(NULL) } void *Attachment::upcallCalloc(CSSM_HANDLE handle, size_t num, size_t size) { - BEGIN_API + BEGIN_API_NO_METRICS return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).calloc(size, num); END_API1(NULL) } @@ -174,7 +174,7 @@ void *Attachment::upcallCalloc(CSSM_HANDLE handle, size_t num, size_t size) CSSM_RETURN Attachment::upcallCcToHandle(CSSM_CC_HANDLE handle, CSSM_MODULE_HANDLE *modHandle) { - BEGIN_API + BEGIN_API_NO_METRICS Required(modHandle) = HandleObject::find((CSSM_HANDLE)handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).attachment.handle(); END_API(CSP) } @@ -190,7 +190,7 @@ CSSM_RETURN Attachment::upcallGetModuleInfo(CSSM_MODULE_HANDLE handle, CSSM_FUNC_NAME_ADDR_PTR FunctionTable, uint32 NumFunctions) { - BEGIN_API + BEGIN_API_NO_METRICS Attachment &attachment = HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); Required(guid) = attachment.myGuid(); Required(version) = attachment.mVersion; diff --git a/OSX/libsecurity_cssm/lib/cssm.cpp b/OSX/libsecurity_cssm/lib/cssm.cpp index 496d039c..c41afa38 100644 --- a/OSX/libsecurity_cssm/lib/cssm.cpp +++ b/OSX/libsecurity_cssm/lib/cssm.cpp @@ -31,7 +31,7 @@ #include "module.h" #include #include - +#include "LegacyAPICounts.h" // // We currently use exactly one instance of CssmManager. diff --git a/OSX/libsecurity_cssm/lib/cssmconfig.h b/OSX/libsecurity_cssm/lib/cssmconfig.h index 560e0828..139d5183 100644 --- a/OSX/libsecurity_cssm/lib/cssmconfig.h +++ b/OSX/libsecurity_cssm/lib/cssmconfig.h @@ -32,7 +32,7 @@ /* #if defined(TARGET_API_MAC_OS8) || defined(TARGET_API_MAC_CARBON) || defined(TARGET_API_MAC_OSX) */ -#if defined(TARGET_OS_MAC) +#if TARGET_OS_MAC #include #include #else diff --git a/OSX/libsecurity_cssm/lib/cssmcontext.h b/OSX/libsecurity_cssm/lib/cssmcontext.h index 6f825019..4a5ae461 100644 --- a/OSX/libsecurity_cssm/lib/cssmcontext.h +++ b/OSX/libsecurity_cssm/lib/cssmcontext.h @@ -68,18 +68,18 @@ public: void mergeAttributes(const CSSM_CONTEXT_ATTRIBUTE *attributes, uint32 count); CSSM_RETURN validateChange(CSSM_CONTEXT_EVENT event); - void *operator new (size_t size, Allocator &alloc) throw(std::bad_alloc) + void *operator new (size_t size, Allocator &alloc) { return alloc.malloc(size); } - void operator delete (void *addr, size_t, Allocator &alloc) throw() + void operator delete (void *addr, size_t, Allocator &alloc) _NOEXCEPT { return alloc.free(addr); } - static void destroy(HandleContext *context, Allocator &alloc) throw() + static void destroy(HandleContext *context, Allocator &alloc) _NOEXCEPT { context->~HandleContext(); alloc.free(context); } class Maker; // deluxe builder #if __GNUC__ > 2 private: - void operator delete (void *addr) throw() { assert(0); } + void operator delete (void *addr) _NOEXCEPT { assert(0); } #endif protected: diff --git a/OSX/libsecurity_cssm/lib/cssmerr.h b/OSX/libsecurity_cssm/lib/cssmerr.h index 4465dbc0..3d8bd1c0 100644 --- a/OSX/libsecurity_cssm/lib/cssmerr.h +++ b/OSX/libsecurity_cssm/lib/cssmerr.h @@ -38,18 +38,6 @@ extern "C" { * (i.e. those with names like kSec...). */ - -/* Common error codes. */ -enum { - CSSM_BASE_ERROR = -0x7FFF0000 /* 0x80010000 */ -}; - -enum { - CSSM_ERRORCODE_MODULE_EXTENT = 0x00000800, - CSSM_ERRORCODE_CUSTOM_OFFSET = 0x00000400, - CSSM_ERRORCODE_COMMON_EXTENT = 0x100 -}; - /* Macros for convertible error code manipulation. */ #define CSSM_ERRCODE(CODE) \ (((CODE) - CSSM_BASE_ERROR) & (CSSM_ERRORCODE_MODULE_EXTENT - 1)) @@ -65,6 +53,12 @@ enum { /* Error Bases for different module types. */ enum { + CSSM_BASE_ERROR = -0x7FFF0000, /* 0x80010000 */ + + CSSM_ERRORCODE_MODULE_EXTENT = 0x00000800, + CSSM_ERRORCODE_CUSTOM_OFFSET = 0x00000400, + CSSM_ERRORCODE_COMMON_EXTENT = 0x100, + CSSM_CSSM_BASE_ERROR = CSSM_BASE_ERROR, CSSM_CSSM_PRIVATE_ERROR = CSSM_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET, CSSM_CSP_BASE_ERROR = CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT, diff --git a/OSX/libsecurity_cssm/lib/module.cpp b/OSX/libsecurity_cssm/lib/module.cpp index 7dce28fe..713a31dc 100644 --- a/OSX/libsecurity_cssm/lib/module.cpp +++ b/OSX/libsecurity_cssm/lib/module.cpp @@ -155,7 +155,7 @@ CSSM_RETURN Module::spiEventRelay(const CSSM_GUID *ModuleGuid, CSSM_SERVICE_TYPE ServiceType, CSSM_MODULE_EVENT EventType) { - BEGIN_API + BEGIN_API_NO_METRICS static_cast(Context)->spiEvent(EventType, Guid::required(ModuleGuid), SubserviceId, diff --git a/OSX/libsecurity_cssm/lib/transition.cpp b/OSX/libsecurity_cssm/lib/transition.cpp index 8f78be84..5e844f3f 100644 --- a/OSX/libsecurity_cssm/lib/transition.cpp +++ b/OSX/libsecurity_cssm/lib/transition.cpp @@ -46,6 +46,7 @@ #include #include #include +#include "LegacyAPICounts.h" // diff --git a/OSX/libsecurity_filedb/lib/AppleDatabase.cpp b/OSX/libsecurity_filedb/lib/AppleDatabase.cpp index 60b47123..7f37d472 100644 --- a/OSX/libsecurity_filedb/lib/AppleDatabase.cpp +++ b/OSX/libsecurity_filedb/lib/AppleDatabase.cpp @@ -110,7 +110,7 @@ Table::readIndexSection() uint32 indexOffset = mTableSection.at(indexSectionOffset + (i + 2) * AtomSize); ReadSection indexSection(mTableSection.subsection(indexOffset)); - auto_ptr index(new DbConstIndex(*this, indexSection)); + unique_ptr index(new DbConstIndex(*this, indexSection)); mIndexMap.insert(ConstIndexMap::value_type(index->indexId(), index.get())); index.release(); } @@ -289,7 +289,7 @@ ModifiedTable::insertRecord(uint32 inVersionId, { modifyTable(); - auto_ptr aWriteSection(new WriteSection()); + unique_ptr aWriteSection(new WriteSection()); getMetaRecord().packRecord(*aWriteSection, inAttributes, inData); uint32 aRecordNumber = nextRecordNumber(); @@ -341,7 +341,7 @@ ModifiedTable::updateRecord(const RecordId &inRecordId, #endif // Update the actual packed record. - auto_ptr aDbRecord(new WriteSection()); + unique_ptr aDbRecord(new WriteSection()); getMetaRecord().updateRecord(anOldDbRecord, *aDbRecord, CssmDbRecordAttributeData::overlay(inAttributes), inData, inModifyMode); @@ -507,7 +507,7 @@ ModifiedTable::createMutableIndexes() Table::ConstIndexMap::const_iterator it; for (it = mTable->mIndexMap.begin(); it != mTable->mIndexMap.end(); it++) { - auto_ptr mutableIndex(new DbMutableIndex(*it->second)); + unique_ptr mutableIndex(new DbMutableIndex(*it->second)); mIndexMap.insert(MutableIndexMap::value_type(it->first, mutableIndex.get())); mutableIndex.release(); } @@ -522,7 +522,7 @@ ModifiedTable::findIndex(uint32 indexId, const MetaRecord &metaRecord, bool isUn if (it == mIndexMap.end()) { // create the new index - auto_ptr index(new DbMutableIndex(metaRecord, indexId, isUniqueIndex)); + unique_ptr index(new DbMutableIndex(metaRecord, indexId, isUniqueIndex)); it = mIndexMap.insert(MutableIndexMap::value_type(indexId, index.get())).first; index.release(); } @@ -932,7 +932,7 @@ DbVersion::open() // XXX Set the size boundary on aTableSection. const ReadSection aTableSection = aSchemaSection.subsection(aTableOffset); - auto_ptr aTable(new Table(aTableSection)); + unique_ptr
aTable(new Table(aTableSection)); Table::Id aTableId = aTable->getMetaRecord().dataRecordType(); mTableMap.insert(TableMap::value_type(aTableId, aTable.get())); aTable.release(); @@ -1048,7 +1048,7 @@ DbVersion::open() uint32 anAttributeId = aRecordData[1]; uint32 anAttributeNameFormat = aRecordData[2]; uint32 anAttributeFormat = aRecordData[5]; - auto_ptr aName; + unique_ptr aName; const CssmData *aNameID = NULL; if (aRecordData[3].size() == 1) @@ -1056,8 +1056,8 @@ DbVersion::open() if (aRecordData[3].format() != CSSM_DB_ATTRIBUTE_FORMAT_STRING) CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); - auto_ptr aName2(new string(static_cast(aRecordData[3]))); - aName = aName2; + unique_ptr aName2(new string(static_cast(aRecordData[3]))); + aName = std::move(aName2); } if (aRecordData[4].size() == 1) @@ -1300,7 +1300,7 @@ IndexCursor::IndexCursor(DbQueryKey *queryKey, const DbVersion &inDbVersion, IndexCursor::~IndexCursor() { - // the query key will be deleted automatically, since it's an auto_ptr + // the query key will be deleted automatically, since it's an unique_ptr } bool @@ -1554,7 +1554,7 @@ DbModifier::modifyDatabase() mDbVersion->mTableMap.end(); for (; anIt != anEnd; ++anIt) { - auto_ptr aTable(new ModifiedTable(anIt->second)); + unique_ptr aTable(new ModifiedTable(anIt->second)); mModifiedTableMap.insert(ModifiedTableMap::value_type(anIt->first, aTable.get())); aTable.release(); @@ -1601,8 +1601,8 @@ DbModifier::updateRecord(Table::Id inTableId, const RecordId &inRecordId, ModifiedTable * DbModifier::createTable(MetaRecord *inMetaRecord) { - auto_ptr aMetaRecord(inMetaRecord); - auto_ptr aModifiedTable(new ModifiedTable(inMetaRecord)); + unique_ptr aMetaRecord(inMetaRecord); + unique_ptr aModifiedTable(new ModifiedTable(inMetaRecord)); // Now that aModifiedTable is fully constructed it owns inMetaRecord aMetaRecord.release(); @@ -1744,7 +1744,7 @@ DbModifier::commit() } void -DbModifier::rollback() throw() +DbModifier::rollback() _NOEXCEPT { // This will destroy the AtomicTempFile if we have one causing it to rollback. mAtomicTempFile = NULL; @@ -2367,7 +2367,7 @@ AppleDatabase::dataGetFirst(DbContext &inDbContext, { // XXX: register Cursor with DbContext and have DbContext call // dataAbortQuery for all outstanding Query objects on close. - auto_ptr aCursor(mDbModifier.createCursor(inQuery)); + unique_ptr aCursor(mDbModifier.createCursor(inQuery)); Table::Id aTableId; RecordId aRecordId; @@ -2387,7 +2387,7 @@ AppleDatabase::dataGetNext(DbContext &inDbContext, CssmData *inoutData, CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) { - auto_ptr aCursor(&HandleObject::find(inResultsHandle, CSSMERR_DL_INVALID_RESULTS_HANDLE)); + unique_ptr aCursor(&HandleObject::find(inResultsHandle, CSSMERR_DL_INVALID_RESULTS_HANDLE)); Table::Id aTableId; RecordId aRecordId; diff --git a/OSX/libsecurity_filedb/lib/AppleDatabase.h b/OSX/libsecurity_filedb/lib/AppleDatabase.h index 1ad330fd..bd341397 100644 --- a/OSX/libsecurity_filedb/lib/AppleDatabase.h +++ b/OSX/libsecurity_filedb/lib/AppleDatabase.h @@ -361,7 +361,7 @@ public: RecordId &recordId); private: - auto_ptr mQueryKey; + unique_ptr mQueryKey; const Table &mTable; const DbConstIndex *mIndex; @@ -383,10 +383,10 @@ public: Allocator &inAllocator, RecordId &recordId); private: - auto_ptr mQuery; + unique_ptr mQuery; DbVersion::const_iterator mTableIterator; - auto_ptr mCursor; + unique_ptr mCursor; }; // @@ -413,7 +413,7 @@ public: void deleteDatabase(); void commit(); - void rollback() throw(); + void rollback() _NOEXCEPT; // Record changing members void deleteRecord(Table::Id inTableId, const RecordId &inRecordId); diff --git a/OSX/libsecurity_filedb/lib/AtomicFile.cpp b/OSX/libsecurity_filedb/lib/AtomicFile.cpp index 6c21d12d..24ca9907 100644 --- a/OSX/libsecurity_filedb/lib/AtomicFile.cpp +++ b/OSX/libsecurity_filedb/lib/AtomicFile.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #define kAtomicFileMaxBlockSize INT_MAX @@ -391,8 +391,8 @@ AtomicBufferedFile::~AtomicBufferedFile() { if (mFileRef >= 0) { - // In release mode, the assert() is compiled out so rv may be unused. - __unused int rv = AtomicFile::rclose(mFileRef); + // In release mode, the assert() is compiled out so rv may be unused. + __unused int rv = AtomicFile::rclose(mFileRef); assert(rv == 0); secinfo("atomicfile", "%p closed %s", this, mPath.c_str()); } @@ -830,7 +830,7 @@ AtomicTempFile::commit() // Rollback the current create or write (happens automatically if commit() isn't called before the destructor is. void -AtomicTempFile::rollback() throw() +AtomicTempFile::rollback() _NOEXCEPT { if (mFileRef >= 0) { @@ -1240,7 +1240,7 @@ AtomicLockedFile::lock(mode_t mode) -void AtomicLockedFile::unlock() throw() +void AtomicLockedFile::unlock() _NOEXCEPT { mFileLocker->unlock(); } diff --git a/OSX/libsecurity_filedb/lib/AtomicFile.h b/OSX/libsecurity_filedb/lib/AtomicFile.h index 86be8bea..0662eedb 100644 --- a/OSX/libsecurity_filedb/lib/AtomicFile.h +++ b/OSX/libsecurity_filedb/lib/AtomicFile.h @@ -160,7 +160,7 @@ private: void close(); // Rollback the current create or write (happens automatically if commit() isn't called before the destructor is). - void rollback() throw(); + void rollback() _NOEXCEPT; private: // Our AtomicFile object. @@ -241,7 +241,7 @@ public: private: void lock(mode_t mode = (S_IRUSR|S_IRGRP|S_IROTH) /* === 0444 */); - void unlock() throw(); + void unlock() _NOEXCEPT; private: FileLocker* mFileLocker; diff --git a/OSX/libsecurity_filedb/lib/DbIndex.cpp b/OSX/libsecurity_filedb/lib/DbIndex.cpp index e95603b5..007b2f69 100644 --- a/OSX/libsecurity_filedb/lib/DbIndex.cpp +++ b/OSX/libsecurity_filedb/lib/DbIndex.cpp @@ -64,8 +64,8 @@ DbKeyComparator::operator () (uint32 offset1, uint32 offset2) const for (uint32 i = 0; i < mKey.mNumKeyValues; i++) { const MetaAttribute &metaAttribute = *mKey.mIndex.mAttributes[i]; - auto_ptr value1(metaAttribute.createValue(*key1, valueOffset1)); - auto_ptr value2(metaAttribute.createValue(*key2, valueOffset2)); + unique_ptr value1(metaAttribute.createValue(*key1, valueOffset1)); + unique_ptr value2(metaAttribute.createValue(*key2, valueOffset2)); if (metaAttribute.evaluate(value1.get(), value2.get(), CSSM_DB_LESS_THAN)) return true; @@ -92,9 +92,9 @@ DbIndexKey::operator < (const DbIndexKey &other) const for (uint32 i = 0; i < numAttributes; i++) { const MetaAttribute &metaAttribute = *mIndex.mAttributes[i]; - auto_ptr value1(metaAttribute.createValue(mKeySection.subsection(mKeyRange), + unique_ptr value1(metaAttribute.createValue(mKeySection.subsection(mKeyRange), valueOffset1)); - auto_ptr value2(metaAttribute.createValue(other.mKeySection.subsection(other.mKeyRange), + unique_ptr value2(metaAttribute.createValue(other.mKeySection.subsection(other.mKeyRange), valueOffset2)); if (metaAttribute.evaluate(value1.get(), value2.get(), CSSM_DB_LESS_THAN)) diff --git a/OSX/libsecurity_filedb/lib/ReadWriteSection.cpp b/OSX/libsecurity_filedb/lib/ReadWriteSection.cpp index 9fe1b489..c97dfdbf 100644 --- a/OSX/libsecurity_filedb/lib/ReadWriteSection.cpp +++ b/OSX/libsecurity_filedb/lib/ReadWriteSection.cpp @@ -49,9 +49,10 @@ void WriteSection::grow(size_t inNewCapacity) size_t aNewCapacity = max(n, inNewCapacity); mAddress = reinterpret_cast(mAllocator.realloc(mAddress, aNewCapacity)); - if (mAddress == NULL) + if (mAddress == NULL) { CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } - memset(mAddress + mCapacity, 0, aNewCapacity - mCapacity); - mCapacity = aNewCapacity; + memset(mAddress + mCapacity, 0, aNewCapacity - mCapacity); + mCapacity = aNewCapacity; } diff --git a/OSX/libsecurity_filedb/lib/ReadWriteSection.h b/OSX/libsecurity_filedb/lib/ReadWriteSection.h index f77e8c4c..7b2b5147 100644 --- a/OSX/libsecurity_filedb/lib/ReadWriteSection.h +++ b/OSX/libsecurity_filedb/lib/ReadWriteSection.h @@ -76,7 +76,7 @@ public: uint32 at(uint32 inOffset) const { - if (inOffset > mLength) + if (CheckUInt32Add(inOffset, AtomSize) > mLength) { CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); } diff --git a/OSX/libsecurity_keychain/Security b/OSX/libsecurity_keychain/Security deleted file mode 120000 index 7951405f..00000000 --- a/OSX/libsecurity_keychain/Security +++ /dev/null @@ -1 +0,0 @@ -lib \ No newline at end of file diff --git a/OSX/libsecurity_keychain/lib/CertificateValues.cpp b/OSX/libsecurity_keychain/lib/CertificateValues.cpp index a2f1ec1b..e20ee2cf 100644 --- a/OSX/libsecurity_keychain/lib/CertificateValues.cpp +++ b/OSX/libsecurity_keychain/lib/CertificateValues.cpp @@ -78,7 +78,7 @@ CertificateValues::CertificateValues(SecCertificateRef certificateRef) : mCertif CFRetain(mCertificateRef); } -CertificateValues::~CertificateValues() throw() +CertificateValues::~CertificateValues() _NOEXCEPT { if (mCertificateProperties) CFRelease(mCertificateProperties); diff --git a/OSX/libsecurity_keychain/lib/CertificateValues.h b/OSX/libsecurity_keychain/lib/CertificateValues.h index 41d17c3f..64150acb 100644 --- a/OSX/libsecurity_keychain/lib/CertificateValues.h +++ b/OSX/libsecurity_keychain/lib/CertificateValues.h @@ -43,7 +43,7 @@ class CertificateValues public: CertificateValues(SecCertificateRef certificateRef); - virtual ~CertificateValues() throw(); + virtual ~CertificateValues() _NOEXCEPT; static CFStringRef remapLabelToKey(CFStringRef label); CFArrayRef copyPropertyValues(CFErrorRef *error); diff --git a/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp b/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp index aa168bd8..14774788 100644 --- a/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp +++ b/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp @@ -415,13 +415,14 @@ DLDbListCFPref::resetCachedValues() void DLDbListCFPref::save() { - if (!hasChanged()) + if (!hasChanged()) { return; + } - // Resync from disc to make sure we don't clobber anyone elses changes. - // @@@ This is probably already done by the next layer up so we don't - // really need to do it here again. - loadPropertyList(true); + // Resync from disc to make sure we don't clobber anyone elses changes. + // @@@ This is probably already done by the next layer up so we don't + // really need to do it here again. + loadPropertyList(true); // Do the searchList first since it might end up invoking defaultDLDbIdentifier() which can set // mLoginDLDbIdentifierSet and mDefaultDLDbIdentifierSet to true. diff --git a/OSX/libsecurity_keychain/lib/ExtendedAttribute.cpp b/OSX/libsecurity_keychain/lib/ExtendedAttribute.cpp index 791c0cc2..d81650d3 100644 --- a/OSX/libsecurity_keychain/lib/ExtendedAttribute.cpp +++ b/OSX/libsecurity_keychain/lib/ExtendedAttribute.cpp @@ -116,7 +116,7 @@ ExtendedAttribute::ExtendedAttribute( setupAttrs(); } -ExtendedAttribute::~ExtendedAttribute() throw() +ExtendedAttribute::~ExtendedAttribute() _NOEXCEPT { } diff --git a/OSX/libsecurity_keychain/lib/ExtendedAttribute.h b/OSX/libsecurity_keychain/lib/ExtendedAttribute.h index ed2b1f75..2469fce6 100644 --- a/OSX/libsecurity_keychain/lib/ExtendedAttribute.h +++ b/OSX/libsecurity_keychain/lib/ExtendedAttribute.h @@ -69,7 +69,7 @@ public: ExtendedAttribute(ExtendedAttribute &extendedAttribute); - virtual ~ExtendedAttribute() throw(); + virtual ~ExtendedAttribute() _NOEXCEPT; virtual PrimaryKey add(Keychain &keychain); bool operator == (const ExtendedAttribute &other) const; diff --git a/OSX/libsecurity_keychain/lib/Identity.cpp b/OSX/libsecurity_keychain/lib/Identity.cpp index 85b0636d..6447eb9b 100644 --- a/OSX/libsecurity_keychain/lib/Identity.cpp +++ b/OSX/libsecurity_keychain/lib/Identity.cpp @@ -113,7 +113,7 @@ Identity::Identity(const StorageManager::KeychainList &keychains, const SecPoint } } -Identity::~Identity() throw() +Identity::~Identity() _NOEXCEPT { if (mPrivateKey) CFRelease(mPrivateKey); diff --git a/OSX/libsecurity_keychain/lib/Identity.h b/OSX/libsecurity_keychain/lib/Identity.h index 29170a27..e942f6a3 100644 --- a/OSX/libsecurity_keychain/lib/Identity.h +++ b/OSX/libsecurity_keychain/lib/Identity.h @@ -47,7 +47,7 @@ public: Identity(const SecKeyRef privateKey, const SecPointer &certificate); Identity(const StorageManager::KeychainList &keychains, const SecPointer &certificate); - virtual ~Identity() throw(); + virtual ~Identity() _NOEXCEPT; SecPointer privateKey() const; SecPointer certificate() const; diff --git a/OSX/libsecurity_keychain/lib/IdentityCursor.cpp b/OSX/libsecurity_keychain/lib/IdentityCursor.cpp index 519b47c2..773800c8 100644 --- a/OSX/libsecurity_keychain/lib/IdentityCursor.cpp +++ b/OSX/libsecurity_keychain/lib/IdentityCursor.cpp @@ -55,7 +55,7 @@ IdentityCursorPolicyAndID::IdentityCursorPolicyAndID(const StorageManager::Keych } } -IdentityCursorPolicyAndID::~IdentityCursorPolicyAndID() throw() +IdentityCursorPolicyAndID::~IdentityCursorPolicyAndID() _NOEXCEPT { if (mPolicy) { CFRelease(mPolicy); @@ -271,7 +271,7 @@ IdentityCursor::IdentityCursor(const StorageManager::KeychainList &searchList, C mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Unwrap, true); } -IdentityCursor::~IdentityCursor() throw() +IdentityCursor::~IdentityCursor() _NOEXCEPT { } @@ -281,7 +281,7 @@ IdentityCursor::pubKeyHashForSystemIdentity(CFStringRef domain) StLock_(mMutex); CFDataRef entryValue = nil; - auto_ptr identDict; + unique_ptr identDict; Dictionary* d = Dictionary::CreateDictionary("com.apple.security.systemidentities", Dictionary::US_System); if (d) { diff --git a/OSX/libsecurity_keychain/lib/IdentityCursor.h b/OSX/libsecurity_keychain/lib/IdentityCursor.h index aa9d7f58..1e0e275c 100644 --- a/OSX/libsecurity_keychain/lib/IdentityCursor.h +++ b/OSX/libsecurity_keychain/lib/IdentityCursor.h @@ -50,7 +50,7 @@ public: SECCFFUNCTIONS(IdentityCursor, SecIdentitySearchRef, errSecInvalidSearchRef, gTypes().IdentityCursor) IdentityCursor(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage); - virtual ~IdentityCursor() throw(); + virtual ~IdentityCursor() _NOEXCEPT; virtual bool next(SecPointer &identity); CFDataRef pubKeyHashForSystemIdentity(CFStringRef domain); @@ -69,7 +69,7 @@ class IdentityCursorPolicyAndID : public IdentityCursor { public: IdentityCursorPolicyAndID(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage, CFStringRef idString, SecPolicyRef policy, bool returnOnlyValidIdentities); - virtual ~IdentityCursorPolicyAndID() throw(); + virtual ~IdentityCursorPolicyAndID() _NOEXCEPT; virtual bool next(SecPointer &identity); virtual void findPreferredIdentity(); diff --git a/OSX/libsecurity_keychain/lib/Item.cpp b/OSX/libsecurity_keychain/lib/Item.cpp index 4d4dc772..f6720512 100644 --- a/OSX/libsecurity_keychain/lib/Item.cpp +++ b/OSX/libsecurity_keychain/lib/Item.cpp @@ -331,7 +331,7 @@ DbAttributes* ItemImpl::getCurrentAttributes() { void ItemImpl::encodeAttributes(CssmOwnedData &attributeBlob) { // Sometimes we don't have our attributes. Find them. - auto_ptr dbAttributes(getCurrentAttributes()); + unique_ptr dbAttributes(getCurrentAttributes()); encodeAttributesFromDictionary(attributeBlob, dbAttributes.get()); } @@ -456,7 +456,7 @@ void ItemImpl::encodeAttributesFromDictionary(CssmOwnedData &attributeBlob, DbAt } void ItemImpl::computeDigest(CssmOwnedData &sha2) { - auto_ptr dbAttributes(getCurrentAttributes()); + unique_ptr dbAttributes(getCurrentAttributes()); ItemImpl::computeDigestFromDictionary(sha2, dbAttributes.get()); } @@ -593,7 +593,7 @@ bool ItemImpl::checkIntegrity(AclBearer& aclBearer) { return true; } - auto_ptr dbAttributes(getCurrentAttributes()); + unique_ptr dbAttributes(getCurrentAttributes()); return checkIntegrityFromDictionary(aclBearer, dbAttributes.get()); } @@ -607,7 +607,7 @@ bool ItemImpl::checkIntegrityFromDictionary(AclBearer& aclBearer, DbAttributes* // them. AclEntryInfo &info = aclInfos.at(0); - auto_ptr acl(new ACL(info, Allocator::standard())); + unique_ptr acl(new ACL(info, Allocator::standard())); for(int i = 1; i < aclInfos.count(); i++) { secnotice("integrity", "*** DUPLICATE INTEGRITY ACL, something has gone wrong"); @@ -1073,7 +1073,7 @@ ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryC } catch (CssmError cssme) { // If there's a "duplicate" of this item, it might be an item with corrupt/invalid attributes // Try to extract the item and check its attributes, then try again if necessary - auto_ptr primaryKeyAttrs; + unique_ptr primaryKeyAttrs; if(cssme.error == CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA) { secnotice("integrity", "possible duplicate, trying to delete invalid items"); @@ -1113,7 +1113,7 @@ ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryC // The item on-disk might have more or different attributes than we do, since we're // only searching via primary key. Fetch all of its attributes. - auto_ptrdbDupAttributes (new DbAttributes(kc->database(), 1)); + unique_ptrdbDupAttributes (new DbAttributes(kc->database(), 1)); fillDbAttributesFromSchema(*dbDupAttributes, recordType, kc); // Occasionally this cursor won't return the item attributes (for an unknown reason). diff --git a/OSX/libsecurity_keychain/lib/Item.h b/OSX/libsecurity_keychain/lib/Item.h index 8e9460dd..bbcacb51 100644 --- a/OSX/libsecurity_keychain/lib/Item.h +++ b/OSX/libsecurity_keychain/lib/Item.h @@ -179,8 +179,8 @@ public: void postItemEvent (SecKeychainEvent theEvent); // Only call these functions while holding globals().apiLock. - bool inCache() const throw() { return mInCache; } - void inCache(bool inCache) throw() { mInCache = inCache; } + bool inCache() const _NOEXCEPT { return mInCache; } + void inCache(bool inCache) _NOEXCEPT { mInCache = inCache; } /* For binding to extended attributes. */ virtual const CssmData &itemID(); @@ -222,7 +222,7 @@ protected: // new item members RefPointer mData; - auto_ptr mDbAttributes; + unique_ptr mDbAttributes; SecPointer mAccess; // db item members diff --git a/OSX/libsecurity_keychain/lib/KCCursor.cpp b/OSX/libsecurity_keychain/lib/KCCursor.cpp index ad7039cf..41221977 100644 --- a/OSX/libsecurity_keychain/lib/KCCursor.cpp +++ b/OSX/libsecurity_keychain/lib/KCCursor.cpp @@ -172,7 +172,7 @@ KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const } } -KCCursorImpl::~KCCursorImpl() throw() +KCCursorImpl::~KCCursorImpl() _NOEXCEPT { } diff --git a/OSX/libsecurity_keychain/lib/KCCursor.h b/OSX/libsecurity_keychain/lib/KCCursor.h index 91027f16..4ce190a1 100644 --- a/OSX/libsecurity_keychain/lib/KCCursor.h +++ b/OSX/libsecurity_keychain/lib/KCCursor.h @@ -47,7 +47,7 @@ protected: KCCursorImpl(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList); public: - virtual ~KCCursorImpl() throw(); + virtual ~KCCursorImpl() _NOEXCEPT; bool next(Item &item); bool mayDelete(); diff --git a/OSX/libsecurity_keychain/lib/KeyItem.cpp b/OSX/libsecurity_keychain/lib/KeyItem.cpp index 6bec5672..1f079ff5 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.cpp +++ b/OSX/libsecurity_keychain/lib/KeyItem.cpp @@ -75,7 +75,7 @@ KeyItem *KeyItem::optional(SecKeyRef ptr) } } -KeyItem::operator CFTypeRef() const throw() +KeyItem::operator CFTypeRef() const _NOEXCEPT { StMaybeLock _(this->getMutexForObject()); @@ -758,8 +758,8 @@ KeyItem::createPair( pubKeyHash.set(*pubKeyHashData); passThrough.allocator().free(pubKeyHashData); - auto_ptr privDescription; - auto_ptr pubDescription; + unique_ptr privDescription; + unique_ptr pubDescription; try { privDescription.reset(new string(initialAccess->promptDescription())); pubDescription.reset(new string(initialAccess->promptDescription())); @@ -997,8 +997,8 @@ KeyItem::importPair( csp.allocator().free(cssmData->Data); csp.allocator().free(cssmData); - auto_ptrprivDescription; - auto_ptrpubDescription; + unique_ptrprivDescription; + unique_ptrpubDescription; try { privDescription.reset(new string(initialAccess->promptDescription())); pubDescription.reset(new string(initialAccess->promptDescription())); diff --git a/OSX/libsecurity_keychain/lib/KeyItem.h b/OSX/libsecurity_keychain/lib/KeyItem.h index 8f048f5c..326279d9 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.h +++ b/OSX/libsecurity_keychain/lib/KeyItem.h @@ -46,7 +46,7 @@ public: // SECCFUNCTIONS macro to retarget SecKeyRef to foreign object instead of normal way through SecCFObject. static KeyItem *required(SecKeyRef ptr); static KeyItem *optional(SecKeyRef ptr); - operator CFTypeRef() const throw(); + operator CFTypeRef() const _NOEXCEPT; static SecCFObject *fromSecKeyRef(CFTypeRef ref); void attachSecKeyRef() const; void initializeWithSecKeyRef(SecKeyRef ref); diff --git a/OSX/libsecurity_keychain/lib/Keychains.h b/OSX/libsecurity_keychain/lib/Keychains.h index 507b270c..b33ae6a4 100644 --- a/OSX/libsecurity_keychain/lib/Keychains.h +++ b/OSX/libsecurity_keychain/lib/Keychains.h @@ -218,8 +218,8 @@ public: const AccessCredentials *defaultCredentials(); // Only call these functions while holding globals().apiLock. - bool inCache() const throw() { return mInCache; } - void inCache(bool inCache) throw() { mInCache = inCache; } + bool inCache() const _NOEXCEPT { return mInCache; } + void inCache(bool inCache) _NOEXCEPT { mInCache = inCache; } void postEvent(SecKeychainEvent kcEvent, ItemImpl* item); void postEvent(SecKeychainEvent kcEvent, ItemImpl* item, PrimaryKey pk); diff --git a/libDER/libDERUtils/libDERUtils.h b/OSX/libsecurity_keychain/lib/LegacyAPICounts.h similarity index 69% rename from libDER/libDERUtils/libDERUtils.h rename to OSX/libsecurity_keychain/lib/LegacyAPICounts.h index 6cd93078..00293163 100644 --- a/libDER/libDERUtils/libDERUtils.h +++ b/OSX/libsecurity_keychain/lib/LegacyAPICounts.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,34 +17,27 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ +#ifndef LegacyAPICounts_h +#define LegacyAPICounts_h -/* - * libDERUtils.h - support routines for libDER tests & examples - * - */ +#include +#include -#ifndef _LIB_DER_UTILS_H_ -#define _LIB_DER_UTILS_H_ - -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif -#include +void countLegacyAPI(dispatch_once_t* token, const char* api); +void setCountLegacyAPIEnabledForThread(bool value); -const char *DERReturnString( - DERReturn drtn); - -void DERPerror( - const char *op, - DERReturn rtn); - -#ifdef __cplusplus +void countLegacyMDSPlugin(const char* path, const char* guid); + +#ifdef __cplusplus } #endif -#endif /* _LIB_DER_UTILS_H_ */ +#endif /* LegacyAPICounts_h */ diff --git a/OSX/libsecurity_keychain/lib/LegacyAPICounts.m b/OSX/libsecurity_keychain/lib/LegacyAPICounts.m new file mode 100644 index 00000000..42d1fa12 --- /dev/null +++ b/OSX/libsecurity_keychain/lib/LegacyAPICounts.m @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#import "LegacyAPICounts.h" +#import "utilities/SecCoreAnalytics.h" +#import "SecEntitlements.h" +#import "debugging.h" +#import "SecInternalReleasePriv.h" + +#pragma mark - File-Private + +static NSString* applicationIdentifierForSelf() { + NSString* identifier = nil; + SecTaskRef task = SecTaskCreateFromSelf(kCFAllocatorDefault); + + if (task) { + CFStringRef val = (CFStringRef)SecTaskCopyValueForEntitlement(task, kSecEntitlementApplicationIdentifier, NULL); + if (val && CFGetTypeID(val) != CFStringGetTypeID()) { + CFRelease(val); + } else { + identifier = CFBridgingRelease(val); + } + + if (!identifier) { + CFBundleRef mainbundle = CFBundleGetMainBundle(); + if (mainbundle != NULL) { + CFStringRef tmp = CFBundleGetIdentifier(mainbundle); + if (tmp != NULL) { + identifier = (__bridge NSString*)tmp; + } + } + } + + if (!identifier) { + identifier = CFBridgingRelease(SecTaskCopySigningIdentifier(task, NULL)); + } + + if (!identifier) { + identifier = [NSString stringWithCString:getprogname() encoding:NSUTF8StringEncoding]; + } + + CFRelease(task); + } + + return identifier; +} + +static BOOL countLegacyAPIEnabledForThread() { + NSNumber* value = [[NSThread currentThread] threadDictionary][@"countLegacyAPIEnabled"]; + + // No value means not set at all, so not disabled by SecItem* + if (!value || (value && [value isKindOfClass:[NSNumber class]] && [value boolValue])) { + return YES; + } + return NO; +} + +static NSString* identifier; +static BOOL shouldCount; + +static void setup() { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + identifier = applicationIdentifierForSelf() ?: @"unknown"; + shouldCount = os_feature_enabled(Security, LegacyAPICounts); + }); +} + +#pragma mark - SPI + +void setCountLegacyAPIEnabledForThread(bool value) { + [[NSThread currentThread] threadDictionary][@"countLegacyAPIEnabled"] = value ? @YES : @NO; +} + +void countLegacyAPI(dispatch_once_t* token, const char* api) { + setup(); + + if (api == nil) { + secerror("LegacyAPICounts: Attempt to count API without name"); + return; + } + + if (!shouldCount || !countLegacyAPIEnabledForThread()) { + return; + } + + dispatch_once(token, ^{ + NSString* apiStringObject = [NSString stringWithCString:api encoding:NSUTF8StringEncoding]; + if (!apiStringObject) { + secerror("LegacyAPICounts: Surprisingly, char* for api name \"%s\" did not turn into NSString", api); + return; + } + + [SecCoreAnalytics sendEventLazy:@"com.apple.security.LegacyAPICounts" builder:^NSDictionary * _Nonnull{ + return @{ + @"app" : identifier, + @"api" : apiStringObject, + }; + }]; + }); +} + +void countLegacyMDSPlugin(const char* path, const char* guid) { + setup(); + + if (!shouldCount) { + return; + } + + NSString* pathString = [NSString stringWithCString:path encoding:NSUTF8StringEncoding]; + if (!pathString) { + secerror("LegacyAPICounts: Unable to make NSString from path %s", path); + return; + } + + NSString* guidString = [NSString stringWithCString:guid encoding:NSUTF8StringEncoding]; + if (!guidString) { + secerror("LegacyAPICounts: Unable to make NSString from guid %s", guid); + return; + } + + if(path && *path == '*') { + // These are apparently 'built-in psuedopaths'. Don't log. + secinfo("mds", "Ignoring the built-in MDS plugin: %@ %@", pathString, guidString); + + } else { + secnotice("mds", "Recording an MDS plugin: %@ %@", pathString, guidString); + + [SecCoreAnalytics sendEventLazy:@"com.apple.security.LegacyMDSPluginCounts" builder:^NSDictionary * _Nonnull{ + return @{ + @"app" : identifier, + @"mdsPath" : pathString, + @"mdsGuid" : guidString, + }; + }]; + } +} diff --git a/OSX/libsecurity_keychain/lib/Password.cpp b/OSX/libsecurity_keychain/lib/Password.cpp index 68cdcce2..783e0152 100644 --- a/OSX/libsecurity_keychain/lib/Password.cpp +++ b/OSX/libsecurity_keychain/lib/Password.cpp @@ -64,7 +64,7 @@ PasswordImpl::PasswordImpl(PasswordImpl& existing) -PasswordImpl::~PasswordImpl() throw() +PasswordImpl::~PasswordImpl() _NOEXCEPT { } diff --git a/OSX/libsecurity_keychain/lib/Password.h b/OSX/libsecurity_keychain/lib/Password.h index f142a9a4..a633fa0a 100644 --- a/OSX/libsecurity_keychain/lib/Password.h +++ b/OSX/libsecurity_keychain/lib/Password.h @@ -44,7 +44,7 @@ public: PasswordImpl(SecItemClass itemClass, SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList); PasswordImpl(PasswordImpl& existing); - virtual ~PasswordImpl() throw(); + virtual ~PasswordImpl() _NOEXCEPT; bool getData(UInt32 *length, const void **data); void setData(UInt32 length,const void *data); diff --git a/OSX/libsecurity_keychain/lib/Policies.cpp b/OSX/libsecurity_keychain/lib/Policies.cpp index 4f0cd433..c78e5356 100644 --- a/OSX/libsecurity_keychain/lib/Policies.cpp +++ b/OSX/libsecurity_keychain/lib/Policies.cpp @@ -85,7 +85,7 @@ Policy::Policy(TP supportingTp, const CssmOid &policyOid) secinfo("policy", "Policy() this %p", this); } -Policy::~Policy() throw() +Policy::~Policy() _NOEXCEPT { secinfo("policy", "~Policy() this %p", this); } diff --git a/OSX/libsecurity_keychain/lib/Policies.h b/OSX/libsecurity_keychain/lib/Policies.h index f4331b4d..b2c934a0 100644 --- a/OSX/libsecurity_keychain/lib/Policies.h +++ b/OSX/libsecurity_keychain/lib/Policies.h @@ -55,7 +55,7 @@ public: Policy(TP supportingTp, const CssmOid &policyOid); public: - virtual ~Policy() throw(); + virtual ~Policy() _NOEXCEPT; TP &tp() { return mTp; } const TP &tp() const { return mTp; } diff --git a/OSX/libsecurity_keychain/lib/PolicyCursor.cpp b/OSX/libsecurity_keychain/lib/PolicyCursor.cpp index d8db218b..6c11e107 100644 --- a/OSX/libsecurity_keychain/lib/PolicyCursor.cpp +++ b/OSX/libsecurity_keychain/lib/PolicyCursor.cpp @@ -85,7 +85,7 @@ PolicyCursor::PolicyCursor(const CSSM_OID* oid, const CSSM_DATA* value) // // Destroy // -PolicyCursor::~PolicyCursor() throw() +PolicyCursor::~PolicyCursor() _NOEXCEPT { } diff --git a/OSX/libsecurity_keychain/lib/PolicyCursor.h b/OSX/libsecurity_keychain/lib/PolicyCursor.h index c7503b68..351b641a 100644 --- a/OSX/libsecurity_keychain/lib/PolicyCursor.h +++ b/OSX/libsecurity_keychain/lib/PolicyCursor.h @@ -49,7 +49,7 @@ public: SECCFFUNCTIONS(PolicyCursor, SecPolicySearchRef, errSecInvalidSearchRef, gTypes().PolicyCursor) PolicyCursor(const CSSM_OID* oid, const CSSM_DATA* value); - virtual ~PolicyCursor() throw(); + virtual ~PolicyCursor() _NOEXCEPT; bool next(SecPointer &policy); bool oidProvided() { return mOidGiven; } diff --git a/OSX/libsecurity_keychain/lib/SecACL.cpp b/OSX/libsecurity_keychain/lib/SecACL.cpp index 5e5dbb7b..23cb2413 100644 --- a/OSX/libsecurity_keychain/lib/SecACL.cpp +++ b/OSX/libsecurity_keychain/lib/SecACL.cpp @@ -30,6 +30,8 @@ #include "SecBridge.h" +#include "LegacyAPICounts.h" + // Forward reference /*! @function GetACLAuthorizationTagFromString @@ -89,6 +91,7 @@ OSStatus SecACLCreateWithSimpleContents(SecAccessRef access, SecKeychainPromptSelector promptSelector, SecACLRef *newAcl) { + COUNTLEGACYAPI CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; cdsaPromptSelector.version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION; cdsaPromptSelector.flags = promptSelector; @@ -156,6 +159,7 @@ OSStatus SecACLCopyContents(SecACLRef acl, CFStringRef *description, SecKeychainPromptSelector *promptSelector) { + COUNTLEGACYAPI CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector)); OSStatus err = errSecSuccess; @@ -208,6 +212,7 @@ OSStatus SecACLSetContents(SecACLRef acl, CFStringRef description, SecKeychainPromptSelector promptSelector) { + COUNTLEGACYAPI CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION; cdsaPromptSelector.flags = promptSelector; @@ -248,6 +253,7 @@ OSStatus SecACLGetAuthorizations(SecACLRef acl, CFArrayRef SecACLCopyAuthorizations(SecACLRef acl) { + COUNTLEGACYAPI CFArrayRef result = NULL; if (NULL == acl) { @@ -310,6 +316,7 @@ OSStatus SecACLSetAuthorizations(SecACLRef aclRef, OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations) { + COUNTLEGACYAPI if (NULL == acl || NULL == authorizations) { return errSecParam; diff --git a/OSX/libsecurity_keychain/lib/SecAccess.cpp b/OSX/libsecurity_keychain/lib/SecAccess.cpp index 91680d82..44368992 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.cpp +++ b/OSX/libsecurity_keychain/lib/SecAccess.cpp @@ -34,6 +34,7 @@ #include +#include "LegacyAPICounts.h" /* No restrictions. Permission to perform all operations on the resource or available to an ACL owner. */ @@ -289,6 +290,7 @@ OSStatus SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE *owner, SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAccessOwnerType ownerType, CFArrayRef acls, CFErrorRef *error) { + COUNTLEGACYAPI SecAccessRef result = NULL; CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = @@ -416,6 +418,7 @@ OSStatus SecAccessGetOwnerAndACL(SecAccessRef accessRef, OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t* userId, gid_t* groupId, SecAccessOwnerType* ownerType, CFArrayRef* aclList) { + COUNTLEGACYAPI CSSM_ACL_OWNER_PROTOTYPE_PTR owner = NULL; CSSM_ACL_ENTRY_INFO_PTR acls = NULL; uint32 aclCount = 0; @@ -532,6 +535,7 @@ OSStatus SecAccessCopySelectedACLList(SecAccessRef accessRef, CFArrayRef SecAccessCopyMatchingACLList(SecAccessRef accessRef, CFTypeRef authorizationTag) { + COUNTLEGACYAPI CFArrayRef result = NULL; CSSM_ACL_AUTHORIZATION_TAG tag = GetACLAuthorizationTagFromString((CFStringRef)authorizationTag); OSStatus err = SecAccessCopySelectedACLList(accessRef, tag, &result); @@ -564,8 +568,9 @@ CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trus // Make a bundle instance using the URLRef. secBundle = CFBundleCreate(kCFAllocatorDefault,bundleURL); - if (!secBundle) + if (!secBundle) { goto xit; + } trustedAppListFileNameWithoutExtension = CFStringCreateMutableCopy(NULL,CFStringGetLength(trustedAppListFileName),trustedAppListFileName); @@ -575,11 +580,13 @@ CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trus // Look for a resource in the bundle by name and type trustedAppsURL = CFBundleCopyResourceURL(secBundle,trustedAppListFileNameWithoutExtension,CFSTR("plist"),NULL); - if (!trustedAppsURL) + if (!trustedAppsURL) { goto xit; + } - if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,trustedAppsURL,&xmlDataRef,NULL,NULL,&errorCode)) + if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,trustedAppsURL,&xmlDataRef,NULL,NULL,&errorCode)) { goto xit; + } trustedAppsPlist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,xmlDataRef,kCFPropertyListImmutable,&errorString); trustedAppList = (CFArrayRef)trustedAppsPlist; @@ -602,6 +609,7 @@ xit: OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) { + COUNTLEGACYAPI OSStatus err = errSecSuccess; SecAccessRef accessToReturn=nil; CFMutableArrayRef trustedApplications=nil; diff --git a/OSX/libsecurity_keychain/lib/SecAccess.h b/OSX/libsecurity_keychain/lib/SecAccess.h index d9e151ce..01946113 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.h +++ b/OSX/libsecurity_keychain/lib/SecAccess.h @@ -127,7 +127,7 @@ CFTypeID SecAccessGetTypeID(void); @param accessRef On return, a pointer to the new access reference. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef __nullable trustedlist, SecAccessRef * __nonnull CF_RETURNS_RETAINED accessRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef __nullable trustedlist, SecAccessRef * __nonnull CF_RETURNS_RETAINED accessRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecAccessCreateFromOwnerAndACL @@ -189,7 +189,7 @@ OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t * __nullable use @param aclList On return, a pointer to a new created CFArray of SecACL instances. The caller is responsible for calling CFRelease on this array. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecAccessCopyACLList(SecAccessRef accessRef, CFArrayRef * __nonnull CF_RETURNS_RETAINED aclList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecAccessCopyACLList(SecAccessRef accessRef, CFArrayRef * __nonnull CF_RETURNS_RETAINED aclList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecAccessCopySelectedACLList diff --git a/OSX/libsecurity_keychain/lib/SecAccessPriv.h b/OSX/libsecurity_keychain/lib/SecAccessPriv.h index 9596f4fc..c9982afe 100644 --- a/OSX/libsecurity_keychain/lib/SecAccessPriv.h +++ b/OSX/libsecurity_keychain/lib/SecAccessPriv.h @@ -39,9 +39,6 @@ extern "C" { #endif -OSStatus SecKeychainAddIToolsPassword(SecKeychainRef keychain, UInt32 accountNameLength, const char *accountName, - UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) __deprecated_msg("iTools is no longer supported") API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - /*! @function SecAccessCreateWithTrustedApplications @abstract Creates a SecAccess object with the specified trusted applications. @@ -53,7 +50,7 @@ OSStatus SecKeychainAddIToolsPassword(SecKeychainRef keychain, UInt32 accountNam @discussion The SecAccessCreateWithPList creates a SecAccess with the provided list of trusted applications. */ -OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) diff --git a/OSX/libsecurity_keychain/lib/SecBase.cpp b/OSX/libsecurity_keychain/lib/SecBase.cpp index 2d82dd36..cf69d48a 100644 --- a/OSX/libsecurity_keychain/lib/SecBase.cpp +++ b/OSX/libsecurity_keychain/lib/SecBase.cpp @@ -141,10 +141,11 @@ copyErrorMessageFromBundle(OSStatus status,CFStringRef tableName) // Convert status to Int32 string representation, e.g. "-25924" keyString = CFStringCreateWithFormat (kCFAllocatorDefault,NULL,CFSTR("%d"),(int)status); - if (!keyString) + if (!keyString) { goto xit; + } - errorString = CFCopyLocalizedStringFromTableInBundle(keyString,tableName,secBundle,NULL); + errorString = CFCopyLocalizedStringFromTableInBundle(keyString,tableName,secBundle,NULL); if (CFStringCompare(errorString, keyString, 0)==kCFCompareEqualTo) // no real error message { if (errorString) diff --git a/OSX/libsecurity_keychain/lib/SecBridge.h b/OSX/libsecurity_keychain/lib/SecBridge.h index c52a5b29..c9e39bf9 100644 --- a/OSX/libsecurity_keychain/lib/SecBridge.h +++ b/OSX/libsecurity_keychain/lib/SecBridge.h @@ -30,9 +30,13 @@ #include #include #include +#include "LegacyAPICounts.h" using namespace KeychainCore; +#define COUNTLEGACYAPI static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); + // // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions. // Usage: @@ -46,6 +50,8 @@ using namespace KeychainCore; // #define BEGIN_SECAPI \ OSStatus __secapiresult = errSecSuccess; \ + static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); \ try { #define END_SECAPI }\ catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \ @@ -73,6 +79,8 @@ using namespace KeychainCore; // #define BEGIN_SECKCITEMAPI \ OSStatus __secapiresult=errSecSuccess; \ + static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); \ SecKeychainItemRef __itemImplRef=NULL; \ bool __is_certificate=(itemRef && (CFGetTypeID(itemRef) == SecCertificateGetTypeID())); \ if (__is_certificate) { \ @@ -108,6 +116,8 @@ using namespace KeychainCore; // #define BEGIN_SECCERTAPI \ OSStatus __secapiresult=errSecSuccess; \ + static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); \ SecCertificateRef __itemImplRef=NULL; \ if (SecCertificateIsItemImplInstance(certificate)) { __itemImplRef=(SecCertificateRef)CFRetain(certificate); } \ if (!__itemImplRef && certificate) { __itemImplRef=(SecCertificateRef)SecCertificateCopyKeychainItem(certificate); } \ diff --git a/OSX/libsecurity_keychain/lib/SecCertificate.cpp b/OSX/libsecurity_keychain/lib/SecCertificate.cpp index ca154314..72086112 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificate.cpp +++ b/OSX/libsecurity_keychain/lib/SecCertificate.cpp @@ -45,6 +45,7 @@ #include #include #include "CertificateValues.h" +#include "LegacyAPICounts.h" OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle); extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); @@ -72,13 +73,6 @@ SecCertificateIsItemImplInstance(SecCertificateRef certificate) CFTypeID typeID = CFGetTypeID(certificate); -#if 0 /* debug code to verify type IDs */ - syslog(LOG_ERR, "SecCertificate typeID=%d [STU=%d, OSX=%d, SKI=%d]", - (int)typeID, - (int)SecCertificateGetTypeID(), - (int)SecCertificateGetTypeID_osx(), - (int)SecKeychainItemGetTypeID()); -#endif if (typeID == _kCFRuntimeNotATypeID) { return false; } @@ -622,12 +616,14 @@ SecCertificateCopyPreference( FourCharCode itemType = 'cprf'; cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } - Item prefItem; - if (!cursor->next(prefItem)) - MacOSError::throwMe(errSecItemNotFound); + Item prefItem; + if (!cursor->next(prefItem)) { + MacOSError::throwMe(errSecItemNotFound); + } // get persistent certificate reference SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } }; @@ -707,8 +703,9 @@ SecCertificateFindPreferenceItemWithNameAndKeyUsage( CssmData service(const_cast(idUTF8), idUTF8Len); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf'); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } Item item; if (!cursor->next(item)) @@ -814,12 +811,11 @@ OSStatus SecCertificateSetPreference( FourCharCode itemType = 'cprf'; cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); - if (date) - ; // %%%TBI + } - Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); + Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); bool add = (!cursor->next(item)); // at this point, we either have a new item to add or an existing item to update @@ -830,10 +826,6 @@ OSStatus SecCertificateSetPreference( item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); - // date - if (date) - ; // %%%TBI - // generic attribute (store persistent certificate reference) CFDataRef pItemRef = nil; Certificate::required(__itemImplRef)->copyPersistentReference(pItemRef); @@ -876,6 +868,7 @@ OSStatus SecCertificateSetPreferred( CFStringRef name, CFArrayRef keyUsage) { + COUNTLEGACYAPI CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); return SecCertificateSetPreference(certificate, name, keyUse, NULL); } diff --git a/OSX/libsecurity_keychain/lib/SecCertificateBundle.cpp b/OSX/libsecurity_keychain/lib/SecCertificateBundle.cpp deleted file mode 100644 index 5e60033d..00000000 --- a/OSX/libsecurity_keychain/lib/SecCertificateBundle.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2002-2004,2011,2013-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include - -#include "SecBridge.h" - -#if defined(__cplusplus) -extern "C" { -#endif -// misspelled function name is declared here so symbol won't be stripped -OSStatus SecCertifcateBundleExport( - CFArrayRef itemList, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data); -#if defined(__cplusplus) -} -#endif - - -OSStatus -SecCertificateBundleImport( - SecKeychainRef keychain, - const CSSM_CERT_BUNDLE* bundle, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CFArrayRef keychainListToSkipDuplicates) -{ - BEGIN_SECAPI - - MacOSError::throwMe(errSecUnimplemented);//%%%for now - - END_SECAPI -} - - -OSStatus -SecCertificateBundleExport( - CFArrayRef certificates, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data) -{ - BEGIN_SECAPI - - MacOSError::throwMe(errSecUnimplemented);//%%%for now - - END_SECAPI -} - -// note: misspelled function name is still exported as a precaution; -// can remove this after deprecation -OSStatus -SecCertifcateBundleExport( - CFArrayRef itemList, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data) -{ - return SecCertificateBundleExport(itemList, type, encodingType, data); -} diff --git a/OSX/libsecurity_keychain/lib/SecCertificateBundle.h b/OSX/libsecurity_keychain/lib/SecCertificateBundle.h deleted file mode 100644 index a20f1bc1..00000000 --- a/OSX/libsecurity_keychain/lib/SecCertificateBundle.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - @header SecCertificateBundle - The functions provided in SecCertificateBundle implement a way to issue a certificate request to a - certificate authority. -*/ - -#ifndef _SECURITY_SECCERTIFICATEBUNDLE_H_ -#define _SECURITY_SECCERTIFICATEBUNDLE_H_ - -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @function SecCertificateBundleImport - @abstract Imports one or more certificates into a keychain with the specified encoding and bundle type. - @param keychain The destination keychain for the import. Specify NULL for the default keychain. - @param bundle A pointer to the bundle data. - @param type The bundle type as defined in cssmtype.h. - @param encodingType The bundle encoding type as defined in cssmtype.h. - @param keychainListToSkipDuplicates A reference to an array of keychains. These keychains contain certificates that shouldn't be duplicated during the import. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecCertificateBundleImport( - SecKeychainRef keychain, - const CSSM_CERT_BUNDLE* bundle, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CFArrayRef keychainListToSkipDuplicates) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateBundleExport - @abstract Exports one or more certificates into a bundle with the specified encoding and bundle type. - @param certificates An array of certificate and keychain items used to help build the bundle. - @param type The bundle type as defined in cssmtype.h. If the bundle type is unknown, an attempt will be made to determine the type for you. - @param encodingType The encoding type as defined in cssmtype.h. - @param data A pointer to data. On return, this points to the bundle data. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecCertificateBundleExport( - CFArrayRef certificates, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* misspelled version of above */ -OSStatus SecCertifcateBundleExport( - CFArrayRef itemList, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECCERTIFICATEBUNDLE_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecExport.cpp b/OSX/libsecurity_keychain/lib/SecExport.cpp index 6473cf15..da93a08a 100644 --- a/OSX/libsecurity_keychain/lib/SecExport.cpp +++ b/OSX/libsecurity_keychain/lib/SecExport.cpp @@ -33,6 +33,7 @@ #include #include #include +#include using namespace Security; using namespace KeychainCore; diff --git a/OSX/libsecurity_keychain/lib/SecIdentity.cpp b/OSX/libsecurity_keychain/lib/SecIdentity.cpp index 5d21959b..7e0a1501 100644 --- a/OSX/libsecurity_keychain/lib/SecIdentity.cpp +++ b/OSX/libsecurity_keychain/lib/SecIdentity.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -36,9 +36,11 @@ #include #include #include +#include #include #include #include +#include "LegacyAPICounts.h" /* private function declarations */ OSStatus @@ -216,6 +218,7 @@ SecIdentityCreate( SecCertificateRef certificate, SecKeyRef privateKey) { + COUNTLEGACYAPI SecIdentityRef identityRef = NULL; OSStatus __secapiresult; SecCertificateRef __itemImplRef = NULL; @@ -244,45 +247,28 @@ SecIdentityCreate( return identityRef; } -CFComparisonResult -SecIdentityCompare( - SecIdentityRef identity1, - SecIdentityRef identity2, - CFOptionFlags compareOptions) +static +bool _SecIdentityNameIsURL(CFStringRef name) { - if (!identity1 || !identity2) - { - if (identity1 == identity2) - return kCFCompareEqualTo; - else if (identity1 < identity2) - return kCFCompareLessThan; - else - return kCFCompareGreaterThan; - } - - try { - SecPointer id1(Identity::required(identity1)); - SecPointer id2(Identity::required(identity2)); - - if (id1 == id2) - return kCFCompareEqualTo; - else if (id1 < id2) - return kCFCompareLessThan; - else - return kCFCompareGreaterThan; - } catch(...) - {} - - return kCFCompareGreaterThan; + CFURLRef url = (name) ? CFURLCreateWithString(NULL, name, NULL) : NULL; + bool result = (url && CFURLCanBeDecomposed(url)); + if (result) { + CFStringRef schemeStr = CFURLCopyScheme(url); + result = (schemeStr && (CFStringGetLength(schemeStr) > 0)); + CFReleaseSafe(schemeStr); + } + CFReleaseSafe(url); + return result; } static CFArrayRef _SecIdentityCopyPossiblePaths( - CFStringRef name) + CFStringRef name, CFStringRef appIdentifier) { // utility function to build and return an array of possible paths for the given name. // if name is not a URL, this returns a single-element array. // if name is a URL, the array may contain 1..N elements, one for each level of the path hierarchy. + // if name is a URL and appIdentifier is non-NULL, it is appended in parentheses to each array entry. CFMutableArrayRef names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); if (!name) { @@ -375,8 +361,22 @@ CFArrayRef _SecIdentityCopyPossiblePaths( } CFRelease(url); } + if (appIdentifier) { + CFIndex count = CFArrayGetCount(names); + for (CFIndex idx=0; idx < count; idx++) { + CFStringRef oldStr = (CFStringRef)CFArrayGetValueAtIndex(names, idx); + CFStringRef appStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%@)"), oldStr, appIdentifier); + if (appStr) { + // only use app identifier string if name is a URL + if (_SecIdentityNameIsURL(oldStr)) { + CFArraySetValueAtIndex(names, idx, appStr); + } + CFRelease(appStr); + } + } + } - return names; + return names; } static @@ -401,8 +401,9 @@ OSStatus _SecIdentityCopyPreferenceMatchingName( FourCharCode itemType = 'iprf'; cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } Item prefItem; if (!cursor->next(prefItem)) @@ -437,6 +438,26 @@ OSStatus _SecIdentityCopyPreferenceMatchingName( return status; } +static CFStringRef SecIdentityCopyPerAppNameForName(CFStringRef name) +{ + CFStringRef perAppName = NULL; + // Currently, per-app identity preferences require a URL form name, + // and the client must not be one whose role is to edit the item's ownership. + if (_SecIdentityNameIsURL(name) && !SecXPCClientCanEditPreferenceOwnership()) { + CFStringRef identifier = SecXPCCopyClientApplicationIdentifier(); + if (identifier) { + // create per-app name with application identifier in parentheses + perAppName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%@)"), name, identifier); + } + CFReleaseNull(identifier); + } + if (!perAppName && name) { + // no application identifier, use name unchanged + perAppName = (CFStringRef)CFRetain(name); + } + return perAppName; +} + SecIdentityRef SecIdentityCopyPreferred(CFStringRef name, CFArrayRef keyUsage, CFArrayRef validIssuers) { // This function will look for a matching preference in the following order: @@ -482,10 +503,17 @@ OSStatus SecIdentityCopyPreference( logging = CFBooleanGetValue((CFBooleanRef)val); } } - CFReleaseNull(val); + CFReleaseNull(val); OSStatus status = errSecItemNotFound; - CFArrayRef names = _SecIdentityCopyPossiblePaths(name); + CFStringRef appIdentifier = NULL; + // We don't want to include the identifier if the app creating this pref has an editing role, + // e.g. Keychain Access or security; this lets it create an item for another client, e.g. Safari. + if (!SecXPCClientCanEditPreferenceOwnership()) { + appIdentifier = SecXPCCopyClientApplicationIdentifier(); + } + CFArrayRef names = _SecIdentityCopyPossiblePaths(name, appIdentifier); + CFReleaseNull(appIdentifier); if (!names) { return status; } @@ -527,11 +555,11 @@ OSStatus SecIdentityCopyPreference( } syslog(LOG_NOTICE, "preferred identity: \"%s\" found for \"%s\"\n", labelBuf, serviceBuf); - if (!status && name) { + if (!status && aName) { char *nameBuf = NULL; - CFIndex nameBufSize = CFStringGetLength(name) * 4; + CFIndex nameBufSize = CFStringGetLength(aName) * 4; nameBuf = (char *)malloc(nameBufSize); - if (!CFStringGetCString(name, nameBuf, nameBufSize, kCFStringEncodingUTF8)) { + if (!CFStringGetCString(aName, nameBuf, nameBufSize, kCFStringEncodingUTF8)) { nameBuf[0] = 0; } syslog(LOG_NOTICE, "lookup complete; will use: \"%s\" for \"%s\"\n", labelBuf, nameBuf); @@ -558,14 +586,20 @@ OSStatus SecIdentitySetPreference( CFStringRef name, CSSM_KEYUSE keyUsage) { - if (!name) { - return errSecParam; - } - if (!identity) { - // treat NULL identity as a request to clear the preference - // (note: if keyUsage is 0, this clears all key usage prefs for name) - return SecIdentityDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage); - } + if (!name) { + return errSecParam; + } + CFStringRef perAppName = SecIdentityCopyPerAppNameForName(name); + if (!perAppName) { + return errSecInternal; + } + if (!identity) { + // treat NULL identity as a request to clear the preference + // (note: if keyUsage is 0, this clears all key usage prefs for name) + OSStatus result = SecIdentityDeletePreferenceItemWithNameAndKeyUsage(NULL, perAppName, keyUsage); + CFReleaseNull(perAppName); + return result; + } BEGIN_SECAPI os_activity_t activity = os_activity_create("SecIdentitySetPreference", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); @@ -575,105 +609,114 @@ OSStatus SecIdentitySetPreference( CFRef certRef; OSStatus status = SecIdentityCopyCertificate(identity, certRef.take()); if(status != errSecSuccess) { + CFReleaseNull(perAppName); MacOSError::throwMe(status); } - // determine the account attribute - // - // This attribute must be synthesized from certificate label + pref item type + key usage, - // as only the account and service attributes can make a generic keychain item unique. - // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that - // we can save a certificate preference if an identity preference already exists for the - // given service name, and vice-versa. - // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. - // + // determine the account attribute + // + // This attribute must be synthesized from certificate label + pref item type + key usage, + // as only the account and service attributes can make a generic keychain item unique. + // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that + // we can save a certificate preference if an identity preference already exists for the + // given service name, and vice-versa. + // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. + // CFStringRef labelStr = nil; SecCertificateInferLabel(certRef.get(), &labelStr); - if (!labelStr) { + if (!labelStr) { + CFReleaseNull(perAppName); MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed" - } - CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; - const char *templateStr = "%s [key usage 0x%X]"; - const int keyUsageMaxStrLen = 8; - accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; - char *accountUTF8 = (char *)malloc(accountUTF8Len); - if (!accountUTF8) { - MacOSError::throwMe(errSecMemoryError); - } - if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) - accountUTF8[0] = (char)'\0'; - if (keyUsage) - snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); - snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); + } + CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; + const char *templateStr = "%s [key usage 0x%X]"; + const int keyUsageMaxStrLen = 8; + accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; + char *accountUTF8 = (char *)malloc(accountUTF8Len); + if (!accountUTF8) { + CFReleaseNull(perAppName); + MacOSError::throwMe(errSecMemoryError); + } + if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) { + accountUTF8[0] = (char)'\0'; + } + if (keyUsage) { + snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); + } + snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); CssmDataContainer account(const_cast(accountUTF8), strlen(accountUTF8)); free(accountUTF8); CFRelease(labelStr); - // service attribute (name provided by the caller) - CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;; - char *serviceUTF8 = (char *)malloc(serviceUTF8Len); - if (!serviceUTF8) { - MacOSError::throwMe(errSecMemoryError); - } - if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) + // service attribute (name provided by the caller) + CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(perAppName), kCFStringEncodingUTF8) + 1;; + char *serviceUTF8 = (char *)malloc(serviceUTF8Len); + if (!serviceUTF8) { + CFReleaseNull(perAppName); + MacOSError::throwMe(errSecMemoryError); + } + if (!CFStringGetCString(perAppName, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) { serviceUTF8[0] = (char)'\0'; + } CssmDataContainer service(const_cast(serviceUTF8), strlen(serviceUTF8)); free(serviceUTF8); + CFRelease(perAppName); // look for existing identity preference item, in case this is an update - StorageManager::KeychainList keychains; - globals().storageManager.getSearchList(keychains); - KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); + StorageManager::KeychainList keychains; + globals().storageManager.getSearchList(keychains); + KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); FourCharCode itemType = 'iprf'; cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); - cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); - } + } - Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); + Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); bool add = (!cursor->next(item)); - // at this point, we either have a new item to add or an existing item to update + // at this point, we either have a new item to add or an existing item to update // set item attribute values item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType); item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); - item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); - // generic attribute (store persistent certificate reference) - CFDataRef pItemRef = nil; + // generic attribute (store persistent certificate reference) + CFDataRef pItemRef = nil; SecKeychainItemCreatePersistentReference((SecKeychainItemRef)certRef.get(), &pItemRef); - if (!pItemRef) { - MacOSError::throwMe(errSecInvalidItemRef); + if (!pItemRef) { + MacOSError::throwMe(errSecInvalidItemRef); } - const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); - CFIndex dataLen = CFDataGetLength(pItemRef); - CssmData pref(const_cast(reinterpret_cast(dataPtr)), dataLen); - item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); - CFRelease(pItemRef); + const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); + CFIndex dataLen = CFDataGetLength(pItemRef); + CssmData pref(const_cast(reinterpret_cast(dataPtr)), dataLen); + item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); + CFRelease(pItemRef); if (add) { Keychain keychain = nil; try { keychain = globals().storageManager.defaultKeychain(); if (!keychain->exists()) - MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. + MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. } catch(...) { keychain = globals().storageManager.defaultKeychainUI(item); } - try { - keychain->add(item); - } - catch (const MacOSError &err) { - if (err.osStatus() != errSecDuplicateItem) - throw; // if item already exists, fall through to update - } + try { + keychain->add(item); + } + catch (const MacOSError &err) { + if (err.osStatus() != errSecDuplicateItem) { + throw; // if item already exists, fall through to update + } + } } - item->update(); + item->update(); END_SECAPI } @@ -681,50 +724,11 @@ OSStatus SecIdentitySetPreference( OSStatus SecIdentitySetPreferred(SecIdentityRef identity, CFStringRef name, CFArrayRef keyUsage) { + COUNTLEGACYAPI CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); return SecIdentitySetPreference(identity, name, keyUse); } -OSStatus -SecIdentityFindPreferenceItem( - CFTypeRef keychainOrArray, - CFStringRef idString, - SecKeychainItemRef *itemRef) -{ - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecIdentityFindPreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); - - StorageManager::KeychainList keychains; - globals().storageManager.optionalSearchList(keychainOrArray, keychains); - KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); - - char idUTF8[MAXPATHLEN]; - idUTF8[0] = (char)'\0'; - if (idString) - { - if (!CFStringGetCString(idString, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) - idUTF8[0] = (char)'\0'; - } - size_t idUTF8Len = strlen(idUTF8); - if (!idUTF8Len) - MacOSError::throwMe(errSecParam); - - CssmData service(const_cast(idUTF8), idUTF8Len); - cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); - cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - - Item item; - if (!cursor->next(item)) - MacOSError::throwMe(errSecItemNotFound); - - if (itemRef) - *itemRef=item->handle(); - - END_SECAPI -} - OSStatus SecIdentityFindPreferenceItemWithNameAndKeyUsage( CFTypeRef keychainOrArray, @@ -755,8 +759,9 @@ SecIdentityFindPreferenceItemWithNameAndKeyUsage( CssmData service(const_cast(idUTF8), idUTF8Len); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } Item item; if (!cursor->next(item)) @@ -773,6 +778,7 @@ OSStatus SecIdentityDeletePreferenceItemWithNameAndKeyUsage( CFStringRef name, int32_t keyUsage) { + COUNTLEGACYAPI // when a specific key usage is passed, we'll only match & delete that pref; // when a key usage of 0 is passed, all matching prefs should be deleted. // maxUsages represents the most matches there could theoretically be, so @@ -793,292 +799,72 @@ OSStatus SecIdentityDeletePreferenceItemWithNameAndKeyUsage( return (status == errSecItemNotFound) ? errSecSuccess : status; } - -static -OSStatus _SecIdentityAddPreferenceItemWithName( - SecKeychainRef keychainRef, - SecIdentityRef identityRef, - CFStringRef idString, - SecKeychainItemRef *itemRef) +OSStatus SecIdentityDeleteApplicationPreferenceItems(void) { - // this is NOT exported, and called only from SecIdentityAddPreferenceItem (below), so no BEGIN/END macros here; - // caller must handle exceptions - - if (!identityRef || !idString) - return errSecParam; - SecPointer cert(Identity::required(identityRef)->certificate()); - Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); - sint32 keyUsage = 0; - - // determine the account attribute - // - // This attribute must be synthesized from certificate label + pref item type + key usage, - // as only the account and service attributes can make a generic keychain item unique. - // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that - // we can save a certificate preference if an identity preference already exists for the - // given service name, and vice-versa. - // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. - // - CFStringRef labelStr = nil; - cert->inferLabel(false, &labelStr); - if (!labelStr) { - return errSecDataTooLarge; // data is "in a format which cannot be displayed" - } - CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; - const char *templateStr = "%s [key usage 0x%X]"; - const int keyUsageMaxStrLen = 8; - accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; - char *accountUTF8 = (char *)malloc(accountUTF8Len); - if (!accountUTF8) { - MacOSError::throwMe(errSecMemoryError); - } - if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) - accountUTF8[0] = (char)'\0'; - if (keyUsage) - snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); - snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); - CssmDataContainer account(const_cast(accountUTF8), strlen(accountUTF8)); - free(accountUTF8); - CFRelease(labelStr); - - // service attribute (name provided by the caller) - CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(idString), kCFStringEncodingUTF8) + 1;; - char *serviceUTF8 = (char *)malloc(serviceUTF8Len); - if (!serviceUTF8) { - MacOSError::throwMe(errSecMemoryError); - } - if (!CFStringGetCString(idString, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) - serviceUTF8[0] = (char)'\0'; - CssmDataContainer service(const_cast(serviceUTF8), strlen(serviceUTF8)); - free(serviceUTF8); - - // set item attribute values - item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); - item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); - item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); - item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), keyUsage); - - // generic attribute (store persistent certificate reference) - CFDataRef pItemRef = nil; - OSStatus status = SecKeychainItemCreatePersistentReference((SecKeychainItemRef)cert->handle(), &pItemRef); - if (!pItemRef) - status = errSecInvalidItemRef; - if (status) - return status; - const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); - CFIndex dataLen = CFDataGetLength(pItemRef); - CssmData pref(const_cast(reinterpret_cast(dataPtr)), dataLen); - item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); - CFRelease(pItemRef); - - Keychain keychain = nil; - try { - keychain = Keychain::optional(keychainRef); - if (!keychain->exists()) - MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. - } - catch(...) { - keychain = globals().storageManager.defaultKeychainUI(item); - } - - try { - keychain->add(item); - } - catch (const MacOSError &err) { - if (err.osStatus() != errSecDuplicateItem) - throw; // if item already exists, fall through to update - } - - item->update(); - - if (itemRef) - *itemRef = item->handle(); - - return status; -} - -OSStatus SecIdentityAddPreferenceItem( - SecKeychainRef keychainRef, - SecIdentityRef identityRef, - CFStringRef idString, - SecKeychainItemRef *itemRef) -{ - // The original implementation of SecIdentityAddPreferenceItem adds the exact string only. - // That implementation has been moved to _SecIdentityAddPreferenceItemWithName (above), - // and this function is a wrapper which calls it, so that existing clients will get the - // extended behavior of server domain matching for items that specify URLs. - // (Note that behavior is unchanged if the specified idString is not a URL.) - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecIdentityAddPreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + os_activity_t activity = os_activity_create("SecIdentityDeleteApplicationPreferenceItems", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); - OSStatus status = errSecInternalComponent; - CFArrayRef names = _SecIdentityCopyPossiblePaths(idString); - if (!names) { - return status; - } + StorageManager::KeychainList keychains; + globals().storageManager.optionalSearchList(NULL, keychains); + KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); + cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - CFIndex total = CFArrayGetCount(names); - if (total > 0) { - // add item for name (first element in array) - CFStringRef aName = (CFStringRef)CFArrayGetValueAtIndex(names, 0); - try { - status = _SecIdentityAddPreferenceItemWithName(keychainRef, identityRef, aName, itemRef); + CFMutableArrayRef matches = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFStringRef appIdentifier = SecXPCCopyClientApplicationIdentifier(); + CFStringRef suffixString = NULL; + if (appIdentifier) { + suffixString = CFStringCreateWithFormat(NULL, NULL, CFSTR(" (%@)"), appIdentifier); + CFReleaseNull(appIdentifier); + } + if (!suffixString || !matches) { + CFReleaseNull(matches); + CFReleaseNull(suffixString); + MacOSError::throwMe(errSecItemNotFound); + } + // iterate through candidate items and add matches to array + Item item; + while (cursor->next(item)) { + SecKeychainAttribute attr[] = { + { kSecServiceItemAttr, 0, NULL }, + }; + SecKeychainAttributeList attrList = { sizeof(attr) / sizeof(SecKeychainAttribute), attr }; + SecKeychainItemRef itemRef = item->handle(); + if (errSecSuccess == SecKeychainItemCopyContent(itemRef, NULL, &attrList, NULL, NULL)) { + if (attr[0].length > 0 && attr[0].data != NULL) { + CFStringRef serviceString = CFStringCreateWithBytes(NULL, + (const UInt8 *)attr[0].data, attr[0].length, + kCFStringEncodingUTF8, false); + if (serviceString && (CFStringHasSuffix(serviceString, suffixString))) { + CFArrayAppendValue(matches, itemRef); + } + CFReleaseNull(serviceString); + } + SecKeychainItemFreeContent(&attrList, NULL); } - catch (const MacOSError &err) { status=err.osStatus(); } - catch (const CommonError &err) { status=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { status=errSecAllocate; } - catch (...) { status=errSecInternalComponent; } + CFReleaseNull(itemRef); } - if (total > 2) { - Boolean setDomainDefaultIdentity = FALSE; - CFTypeRef val = (CFTypeRef)CFPreferencesCopyValue(CFSTR("SetDomainDefaultIdentity"), - CFSTR("com.apple.security.identities"), - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - if (val) { - if (CFGetTypeID(val) == CFBooleanGetTypeID()) - setDomainDefaultIdentity = CFBooleanGetValue((CFBooleanRef)val) ? TRUE : FALSE; - CFRelease(val); - } - if (setDomainDefaultIdentity) { - // add item for domain (second-to-last element in array, e.g. "*.apple.com") - OSStatus tmpStatus = errSecSuccess; - CFStringRef aName = (CFStringRef)CFArrayGetValueAtIndex(names, total-2); - try { - tmpStatus = _SecIdentityAddPreferenceItemWithName(keychainRef, identityRef, aName, itemRef); - } - catch (const MacOSError &err) { tmpStatus=err.osStatus(); } - catch (const CommonError &err) { tmpStatus=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { tmpStatus=errSecAllocate; } - catch (...) { tmpStatus=errSecInternalComponent; } - } + // delete matching items, if any + CFIndex numDeleted=0, count = CFArrayGetCount(matches); + OSStatus status = (count > 0) ? errSecSuccess : errSecItemNotFound; + for (CFIndex idx=0; idx < count; idx++) { + SecKeychainItemRef itemRef = (SecKeychainItemRef)CFArrayGetValueAtIndex(matches, idx); + OSStatus tmpStatus = SecKeychainItemDelete(itemRef); + if (errSecSuccess == tmpStatus) { + ++numDeleted; + } else { + status = tmpStatus; // remember failure, but keep going + } } + syslog(LOG_NOTICE, "identity preferences found: %ld, deleted: %ld (status: %ld)", + (long)count, (long)numDeleted, (long)status); + CFReleaseNull(matches); + CFReleaseNull(suffixString); - CFRelease(names); - return status; - - END_SECAPI -} - -/* deprecated in 10.5 */ -OSStatus SecIdentityUpdatePreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef identityRef) -{ - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecIdentityUpdatePreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); - - if (!itemRef || !identityRef) - MacOSError::throwMe(errSecParam); - SecPointer certificate(Identity::required(identityRef)->certificate()); - Item prefItem = ItemImpl::required(itemRef); - - // get the current key usage value for this item - sint32 keyUsage = 0; - UInt32 actLen = 0; - SecKeychainAttribute attr = { kSecScriptCodeItemAttr, sizeof(sint32), &keyUsage }; - try { - prefItem->getAttribute(attr, &actLen); - } - catch(...) { - keyUsage = 0; - }; - - // set the account attribute - // - // This attribute must be synthesized from certificate label + pref item type + key usage, - // as only the account and service attributes can make a generic keychain item unique. - // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that - // we can save a certificate preference if an identity preference already exists for the - // given service name, and vice-versa. - // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. - // - CFStringRef labelStr = nil; - certificate->inferLabel(false, &labelStr); - if (!labelStr) { - MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed" - } - CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; - const char *templateStr = "%s [key usage 0x%X]"; - const int keyUsageMaxStrLen = 8; - accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; - char *accountUTF8 = (char *)malloc(accountUTF8Len); - if (!accountUTF8) { - MacOSError::throwMe(errSecMemoryError); - } - if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) - accountUTF8[0] = (char)'\0'; - if (keyUsage) - snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); - snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); - CssmDataContainer account(const_cast(accountUTF8), strlen(accountUTF8)); - prefItem->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); - free(accountUTF8); - CFRelease(labelStr); - - // generic attribute (store persistent certificate reference) - CFDataRef pItemRef = nil; - OSStatus status = SecKeychainItemCreatePersistentReference((SecKeychainItemRef)certificate->handle(), &pItemRef); - if (!pItemRef) - status = errSecInvalidItemRef; - if (status) - MacOSError::throwMe(status); - const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); - CFIndex dataLen = CFDataGetLength(pItemRef); - CssmData pref(const_cast(reinterpret_cast(dataPtr)), dataLen); - prefItem->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); - CFRelease(pItemRef); - - prefItem->update(); - - END_SECAPI -} - -OSStatus SecIdentityCopyFromPreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef *identityRef) -{ - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecIdentityCopyFromPreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); - - if (!itemRef || !identityRef) - MacOSError::throwMe(errSecParam); - Item prefItem = ItemImpl::required(itemRef); - - // get persistent certificate reference - SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } }; - SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs }; - prefItem->getContent(NULL, &itemAttrList, NULL, NULL); - - // find certificate, given persistent reference data - CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull); - SecKeychainItemRef certItemRef = nil; - OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl - prefItem->freeContent(&itemAttrList, NULL); - if (pItemRef) - CFRelease(pItemRef); - if (status) - return status; - - // create identity reference, given certificate - StorageManager::KeychainList keychains; - globals().storageManager.optionalSearchList((CFTypeRef)NULL, keychains); - Item certItem = ItemImpl::required(SecKeychainItemRef(certItemRef)); - SecPointer certificate(static_cast(certItem.get())); - SecPointer identity(new Identity(keychains, certificate)); - if (certItemRef) - CFRelease(certItemRef); - - Required(identityRef) = identity->handle(); - + if (status != errSecSuccess) { + MacOSError::throwMe(status); + } END_SECAPI } @@ -1114,7 +900,7 @@ OSStatus SecIdentityCopySystemIdentity( os_release(activity); StLock _(systemIdentityLock()); - auto_ptr identDict; + unique_ptr identDict; /* get top-level dictionary - if not present, we're done */ Dictionary* d = Dictionary::CreateDictionary(IDENTITY_DOMAIN, Dictionary::US_System); @@ -1189,7 +975,7 @@ OSStatus SecIdentitySetSystemIdentity( MacOSError::throwMe(errSecAuthFailed); } - auto_ptr identDict; + unique_ptr identDict; MutableDictionary *d = MutableDictionary::CreateMutableDictionary(IDENTITY_DOMAIN, Dictionary::US_System); if (d) { diff --git a/OSX/libsecurity_keychain/lib/SecIdentitySearch.cpp b/OSX/libsecurity_keychain/lib/SecIdentitySearch.cpp index b3f58d60..d91069cc 100644 --- a/OSX/libsecurity_keychain/lib/SecIdentitySearch.cpp +++ b/OSX/libsecurity_keychain/lib/SecIdentitySearch.cpp @@ -29,7 +29,7 @@ #include #include "SecBridge.h" - +#include "LegacyAPICounts.h" CFTypeID SecIdentitySearchGetTypeID(void) diff --git a/OSX/libsecurity_keychain/lib/SecImportExportPem.cpp b/OSX/libsecurity_keychain/lib/SecImportExportPem.cpp index df675564..3a4fb9a0 100644 --- a/OSX/libsecurity_keychain/lib/SecImportExportPem.cpp +++ b/OSX/libsecurity_keychain/lib/SecImportExportPem.cpp @@ -32,6 +32,8 @@ #include #include +#include + /* * Text parsing routines. * diff --git a/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp b/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp index 165d567c..f0b988f4 100644 --- a/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp +++ b/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #define SecPkcs8Dbg(args...) secinfo("SecPkcs8", ## args) diff --git a/OSX/libsecurity_keychain/lib/SecItem.cpp b/OSX/libsecurity_keychain/lib/SecItem.cpp index b1b571c2..e5b078ad 100644 --- a/OSX/libsecurity_keychain/lib/SecItem.cpp +++ b/OSX/libsecurity_keychain/lib/SecItem.cpp @@ -41,6 +41,8 @@ #include "TrustSettingsSchema.h" #include #include "utilities/array_size.h" +#include "utilities/SecCFWrappers.h" +#include "LegacyAPICounts.h" #include #include @@ -70,8 +72,6 @@ OSStatus SecItemAdd_ios(CFDictionaryRef attributes, CFTypeRef *result); OSStatus SecItemCopyMatching_ios(CFDictionaryRef query, CFTypeRef *result); OSStatus SecItemUpdate_ios(CFDictionaryRef query, CFDictionaryRef attributesToUpdate); OSStatus SecItemDelete_ios(CFDictionaryRef query); -OSStatus SecItemUpdateTokenItems_ios(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes); - OSStatus SecItemValidateAppleApplicationGroupAccess(CFStringRef group); CFDictionaryRef SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass, @@ -3826,6 +3826,8 @@ AddItemResults(SecKeychainItemRef item, // // Note that we allocate *items if needed. + CFTypeRef localResult = NULL; + if (!item || !itemParams || !result) return errSecParam; @@ -3854,7 +3856,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, itemRef); } else { - *result = CFRetain((CFTypeRef)itemRef); + CFReleaseNull(localResult); + localResult = CFRetain((CFTypeRef)itemRef); } } @@ -3873,7 +3876,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, persistentRef); } else { - *result = CFRetain(persistentRef); + CFReleaseNull(localResult); + localResult = CFRetain(persistentRef); } CFRelease(persistentRef); } @@ -3897,7 +3901,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, dataRef); } else { - *result = CFRetain(dataRef); + CFReleaseNull(localResult); + localResult = CFRetain(dataRef); } CFRelease(dataRef); status = errSecSuccess; @@ -3919,7 +3924,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, dataRef); } else { - *result = CFRetain(dataRef); + CFReleaseNull(localResult); + localResult = CFRetain(dataRef); } CFRelease(dataRef); (void) SecKeychainItemFreeContent(NULL, data); @@ -3948,7 +3954,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, attrsDict); } else { - *result = CFRetain(attrsDict); + CFReleaseNull(localResult); + localResult = CFRetain(attrsDict); } CFRelease(attrsDict); } @@ -3961,14 +3968,22 @@ AddItemResults(SecKeychainItemRef item, if (itemArray) { CFArrayAppendValue(itemArray, itemDict); CFRelease(itemDict); - *result = itemArray; + CFReleaseNull(localResult); + localResult = itemArray; } else { - *result = itemDict; + CFReleaseNull(localResult); + localResult = itemDict; } } else if (itemArray) { - *result = itemArray; + CFReleaseNull(localResult); + localResult = itemArray; + } + + if (localResult) { + *result = localResult; + localResult = NULL; } return status; @@ -4309,7 +4324,7 @@ SecItemCreateFromAttributeDictionary_osx(CFDictionaryRef refAttributes) { CFTypeRef v; Item item = Item(item_class, &attrs, 0, ""); - v = CFDictionaryGetValue(refAttributes, kSecValuePersistentRef); + v = CFCast(CFData, CFDictionaryGetValue(refAttributes, kSecValuePersistentRef)); if (v) { item->setPersistentRef((CFDataRef)v); } @@ -5081,14 +5096,6 @@ SecItemDelete(CFDictionaryRef query) return status; } -OSStatus -SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes) -{ - OSStatus status = SecItemUpdateTokenItems_ios(tokenID, tokenItemsAttributes); - secitemlog(LOG_NOTICE, "SecItemUpdateTokenItems_ios result: %d", status); - return status; -} - OSStatus SecItemCopyMatching_osx( CFDictionaryRef query, @@ -5099,6 +5106,8 @@ SecItemCopyMatching_osx( else *result = NULL; + setCountLegacyAPIEnabledForThread(false); + CFAllocatorRef allocator = CFGetAllocator(query); CFIndex matchCount = 0; CFMutableArrayRef itemArray = NULL; @@ -5143,20 +5152,9 @@ error_exit: } _FreeSecItemParams(itemParams); - return status; -} + setCountLegacyAPIEnabledForThread(true); -OSStatus -SecItemCopyDisplayNames( - CFArrayRef items, - CFArrayRef *displayNames) -{ - BEGIN_SECAPI - Required(items); - Required(displayNames); - //%%%TBI - return errSecUnimplemented; - END_SECAPI + return status; } OSStatus @@ -5169,6 +5167,8 @@ SecItemAdd_osx( else if (result) *result = NULL; + setCountLegacyAPIEnabledForThread(false); + CFAllocatorRef allocator = CFGetAllocator(attributes); CFMutableArrayRef itemArray = NULL; SecKeychainItemRef item = NULL; @@ -5302,6 +5302,7 @@ error_exit: *result = NULL; } _FreeSecItemParams(itemParams); + setCountLegacyAPIEnabledForThread(true); return status; } @@ -5329,6 +5330,8 @@ SecItemUpdate_osx( CFRelease(results); } + setCountLegacyAPIEnabledForThread(false); + OSStatus result = errSecSuccess; CFIndex ix, count = CFArrayGetCount(items); for (ix=0; ix < count; ix++) { @@ -5339,6 +5342,8 @@ SecItemUpdate_osx( } } + setCountLegacyAPIEnabledForThread(true); + if (items) { CFRelease(items); } @@ -5367,6 +5372,8 @@ SecItemDelete_osx( CFRelease(results); } + setCountLegacyAPIEnabledForThread(false); + OSStatus result = errSecSuccess; CFIndex ix, count = CFArrayGetCount(items); for (ix=0; ix < count; ix++) { @@ -5382,6 +5389,8 @@ SecItemDelete_osx( } } + setCountLegacyAPIEnabledForThread(true); + if (items) CFRelease(items); diff --git a/OSX/libsecurity_keychain/lib/SecItemConstants.c b/OSX/libsecurity_keychain/lib/SecItemConstants.c index 4f56a5c7..40552090 100644 --- a/OSX/libsecurity_keychain/lib/SecItemConstants.c +++ b/OSX/libsecurity_keychain/lib/SecItemConstants.c @@ -126,6 +126,13 @@ SEC_CONST_DECL (kSecAttrRounds, "rounds"); //SEC_CONST_DECL (kSecAttrPCSPlaintextPublicKey, "pcsk"); //SEC_CONST_DECL (kSecAttrPCSPlaintextPublicIdentity, "pcsi"); +//SEC_CONST_DECL (kSecDataInetExtraNotes, "binn"); +//SEC_CONST_DECL (kSecDataInetExtraHistory, "bini"); +//SEC_CONST_DECL (kSecDataInetExtraClientDefined0, "bin0"); +//SEC_CONST_DECL (kSecDataInetExtraClientDefined1, "bin1"); +//SEC_CONST_DECL (kSecDataInetExtraClientDefined2, "bin2"); +//SEC_CONST_DECL (kSecDataInetExtraClientDefined3, "bin3"); + /* Predefined access groups constants */ //SEC_CONST_DECL (kSecAttrAccessGroupToken, "com.apple.token"); diff --git a/OSX/libsecurity_keychain/lib/SecKey.cpp b/OSX/libsecurity_keychain/lib/SecKey.cpp index 7ef6027b..940caae2 100644 --- a/OSX/libsecurity_keychain/lib/SecKey.cpp +++ b/OSX/libsecurity_keychain/lib/SecKey.cpp @@ -804,20 +804,19 @@ static Boolean SecCDSAKeySetParameter(SecKeyRef key, CFStringRef name, CFPropert const SecKeyDescriptor kSecCDSAKeyDescriptor = { .version = kSecKeyDescriptorVersion, .name = "CDSAKey", + .extraBytes = (sizeof(class CDSASecKey) > sizeof(struct __SecKey) ? (sizeof(class CDSASecKey) - sizeof(struct __SecKey)) : 0), .init = SecCDSAKeyInit, .destroy = SecCDSAKeyDestroy, .blockSize = SecCDSAKeyGetBlockSize, - .getAlgorithmID = SecCDSAKeyGetAlgorithmId, .copyDictionary = SecCDSAKeyCopyAttributeDictionary, + .getAlgorithmID = SecCDSAKeyGetAlgorithmId, .copyPublic = SecCDSAKeyCopyPublicBytes, .copyExternalRepresentation = SecCDSAKeyCopyExternalRepresentation, .copyPublicKey = SecCDSAKeyCopyPublicKey, .copyOperationResult = SecCDSAKeyCopyOperationResult, .isEqual = SecCDSAKeyIsEqual, .setParameter = SecCDSAKeySetParameter, - - .extraBytes = (sizeof(class CDSASecKey) > sizeof(struct __SecKey) ? (sizeof(class CDSASecKey) - sizeof(struct __SecKey)) : 0), }; namespace Security { diff --git a/OSX/libsecurity_keychain/lib/SecKeychain.cpp b/OSX/libsecurity_keychain/lib/SecKeychain.cpp index 53265b95..ca80c80b 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychain.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychain.cpp @@ -39,12 +39,18 @@ #include #include #include "TokenLogin.h" +#include "LegacyAPICounts.h" + +extern "C" { +#include "ctkloginhelper.h" +} OSStatus SecKeychainMDSInstall() { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainMDSInstall", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainMDSInstall", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -68,6 +74,7 @@ SecKeychainGetTypeID(void) OSStatus SecKeychainGetVersion(UInt32 *returnVers) { + COUNTLEGACYAPI if (!returnVers) return errSecSuccess; @@ -80,7 +87,8 @@ OSStatus SecKeychainOpen(const char *pathName, SecKeychainRef *keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainOpen", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainOpen", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -89,38 +97,13 @@ SecKeychainOpen(const char *pathName, SecKeychainRef *keychainRef) END_SECAPI } - -OSStatus -SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subserviceType, const char* dbName, - const CSSM_NET_ADDRESS *dbLocation, SecKeychainRef *keychain) -{ - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainOpenWithGuid", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); - - // range check parameters - RequiredParam (guid); - RequiredParam (dbName); - - // create a DLDbIdentifier that describes what should be opened - const CSSM_VERSION *version = NULL; - const CssmSubserviceUid ssuid(*guid, version, subserviceId, subserviceType); - DLDbIdentifier dLDbIdentifier(ssuid, dbName, dbLocation); - - // make a keychain from the supplied info - RequiredParam(keychain) = globals().storageManager.makeKeychain(dLDbIdentifier, false, false)->handle (); - - END_SECAPI -} - - OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void *password, Boolean promptUser, SecAccessRef initialAccess, SecKeychainRef *keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCreate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCreate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -147,7 +130,8 @@ OSStatus SecKeychainDelete(SecKeychainRef keychainOrArray) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -165,7 +149,8 @@ OSStatus SecKeychainSetSettings(SecKeychainRef keychainRef, const SecKeychainSettings *newSettings) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetSettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetSettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -185,7 +170,8 @@ OSStatus SecKeychainCopySettings(SecKeychainRef keychainRef, SecKeychainSettings *outSettings) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopySettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopySettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -208,7 +194,8 @@ OSStatus SecKeychainUnlock(SecKeychainRef keychainRef, UInt32 passwordLength, const void *password, Boolean usePassword) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainUnlock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainUnlock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -227,7 +214,8 @@ OSStatus SecKeychainLock(SecKeychainRef keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainLock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainLock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -242,7 +230,8 @@ OSStatus SecKeychainLockAll(void) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainLockAll", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainLockAll", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -255,7 +244,8 @@ SecKeychainLockAll(void) OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Boolean resetSearchList) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainResetLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainResetLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); // @@ -322,7 +312,8 @@ OSStatus SecKeychainSetDefault(SecKeychainRef keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -334,7 +325,8 @@ SecKeychainSetDefault(SecKeychainRef keychainRef) OSStatus SecKeychainCopySearchList(CFArrayRef *searchList) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopySearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopySearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -350,7 +342,8 @@ OSStatus SecKeychainCopySearchList(CFArrayRef *searchList) OSStatus SecKeychainSetSearchList(CFArrayRef searchList) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -366,7 +359,8 @@ OSStatus SecKeychainSetSearchList(CFArrayRef searchList) OSStatus SecKeychainCopyDomainDefault(SecPreferencesDomain domain, SecKeychainRef *keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopyDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopyDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -378,7 +372,8 @@ OSStatus SecKeychainCopyDomainDefault(SecPreferencesDomain domain, SecKeychainRe OSStatus SecKeychainSetDomainDefault(SecPreferencesDomain domain, SecKeychainRef keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -403,7 +398,8 @@ OSStatus SecKeychainCopyDomainSearchList(SecPreferencesDomain domain, CFArrayRef OSStatus SecKeychainSetDomainSearchList(SecPreferencesDomain domain, CFArrayRef searchList) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetDomainSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetDomainSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -419,7 +415,8 @@ OSStatus SecKeychainSetDomainSearchList(SecPreferencesDomain domain, CFArrayRef OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -431,7 +428,8 @@ OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain) OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainGetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainGetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -478,7 +476,7 @@ SecKeychainGetKeychainVersion(SecKeychainRef keychainRef, UInt32* version) { BEGIN_SECAPI - RequiredParam(version); + RequiredParam(version); *version = Keychain::optional(keychainRef)->database()->dbBlobVersion(); @@ -489,7 +487,8 @@ OSStatus SecKeychainAttemptMigrationWithMasterKey(SecKeychainRef keychain, UInt32 version, const char* masterKeyFilename) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAttemptMigrationWithMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAttemptMigrationWithMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -587,7 +586,8 @@ pascal OSStatus SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void* userContext) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAddCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAddCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -602,7 +602,8 @@ OSStatus SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainRemoveCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainRemoveCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -616,7 +617,8 @@ OSStatus SecKeychainAddInternetPassword(SecKeychainRef keychainRef, UInt32 serverNameLength, const char *serverName, UInt32 securityDomainLength, const char *securityDomain, UInt32 accountNameLength, const char *accountName, UInt32 pathLength, const char *path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAddInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAddInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -678,7 +680,8 @@ SecKeychainFindInternetPassword(CFTypeRef keychainOrArray, UInt32 serverNameLeng { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainFindInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainFindInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -757,7 +760,8 @@ OSStatus SecKeychainAddGenericPassword(SecKeychainRef keychainRef, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAddGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAddGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -806,7 +810,8 @@ SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLeng { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainFindGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainFindGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -878,7 +883,8 @@ OSStatus SecKeychainGetDLDBHandle(SecKeychainRef keychainRef, CSSM_DL_DB_HANDLE *dldbHandle) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainGetDLDBHandle", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainGetDLDBHandle", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -944,7 +950,8 @@ OSStatus SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainChangePassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainChangePassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -959,7 +966,8 @@ OSStatus SecKeychainCopyLogin(SecKeychainRef *keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopyLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopyLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -973,7 +981,8 @@ OSStatus SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, const void* password) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1009,7 +1018,8 @@ SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, con OSStatus SecKeychainStash() { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainStash", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainStash", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1036,7 +1046,8 @@ OSStatus SecKeychainLogout() { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainLogout", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainLogout", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1059,7 +1070,8 @@ static Keychain make(const char *name) OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef) { BEGIN_SECAPI - RequiredParam(fullPathName); + + RequiredParam(fullPathName); RequiredParam(keychainRef)=make(fullPathName)->handle(); END_SECAPI } @@ -1070,7 +1082,8 @@ OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *k OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid) { BEGIN_SECAPI - *isValid = false; + + *isValid = false; if (KeychainImpl::optional(keychainRef)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL) *isValid = true; END_SECAPI @@ -1081,7 +1094,8 @@ OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid) OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainRemoveFromSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainRemoveFromSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); StorageManager::KeychainList singleton; @@ -1095,7 +1109,8 @@ OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef) OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCreateNew", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCreateNew", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); RequiredParam(inPassword); @@ -1108,7 +1123,8 @@ OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlobArray, CFDataRef extraData) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainRecodeKeychain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainRecodeKeychain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1186,7 +1202,8 @@ OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlob OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychainSignature) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopySignature", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopySignature", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1213,7 +1230,8 @@ OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychai OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopyBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopyBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1235,7 +1253,8 @@ OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob) OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCreateWithBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCreateWithBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1262,7 +1281,8 @@ OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char const CSSM_GUID *guid, uint32 subServiceType) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAddDBToKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAddDBToKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1278,7 +1298,8 @@ OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* const CSSM_GUID *guid, uint32 subServiceType) { BEGIN_SECAPI - RequiredParam(dbName); + + RequiredParam(dbName); StorageManager &smr = globals().storageManager; smr.isInDomainList(domain, dbName, *guid, subServiceType); END_SECAPI @@ -1289,7 +1310,8 @@ OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const const CSSM_GUID *guid, uint32 subServiceType) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainRemoveDBFromKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainRemoveDBFromKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); RequiredParam(dbName); @@ -1310,7 +1332,8 @@ void SecKeychainSetServerMode() OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetBatchMode", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetBatchMode", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); RequiredParam(kcRef); @@ -1324,13 +1347,15 @@ OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean ro OSStatus SecKeychainCleanupHandles() { BEGIN_SECAPI - END_SECAPI // which causes the handle cache cleanup routine to run + + END_SECAPI // which causes the handle cache cleanup routine to run } OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainVerifyKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainVerifyKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); SecurityServer::ClientSession().verifyKeyStorePassphrase(retries); @@ -1340,7 +1365,8 @@ OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries) OSStatus SecKeychainChangeKeyStorePassphrase() { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainChangeKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainChangeKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); SecurityServer::ClientSession().changeKeyStorePassphrase(); @@ -1350,7 +1376,8 @@ OSStatus SecKeychainChangeKeyStorePassphrase() static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRef *masterKey, CFStringRef password) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainGetMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainGetMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1468,6 +1495,7 @@ static bool _SASetAutologinPW(CFStringRef inAutologinPW) } OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) { + COUNTLEGACYAPI SecTrustedApplicationRef itemPath; SecAccessRef ourAccessRef = NULL; @@ -1568,6 +1596,7 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe OSStatus SecKeychainGetUserPromptAttempts(uint32_t * attempts) { BEGIN_SECAPI + os_activity_t activity = os_activity_create("SecKeychainGetUserPromptAttempts", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1582,6 +1611,7 @@ OSStatus SecKeychainGetUserPromptAttempts(uint32_t * attempts) OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringRef tokenID, CFDataRef wrapPubKeyHash, SecKeychainRef userKeychain, CFStringRef password) { + COUNTLEGACYAPI CFRef pwd; OSStatus result; @@ -1667,15 +1697,32 @@ OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringR } secnotice("SecKeychain", "SecKeychainStoreUnlockKeyWithPubKeyHash result %d", (int) result); + + // create SC KEK + // this might fail if KC password is different from user's password + uid_t uid = geteuid(); + if (!uid) { + uid = getuid(); + } + struct passwd *passwd = getpwuid(uid); + if (passwd) { + CFRef username = CFStringCreateWithCString(kCFAllocatorDefault, passwd->pw_name, kCFStringEncodingUTF8); + OSStatus kekRes = TKAddSecureToken(username, pwd, tokenID, wrapPubKeyHash); + if (kekRes != noErr) { + secnotice("SecKeychain", "Failed to register SC token: %d", (int) kekRes); // do not fail because KC functionality be still OK + } + } else { + secnotice("SecKeychain", "Unable to get name for uid %d", uid); + } return result; } OSStatus SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash) { + COUNTLEGACYAPI OSStatus result = TokenLoginDeleteUnlockData(pubKeyHash); if (result != errSecSuccess) { secnotice("SecKeychain", "Failed to erase stored wrapped unlock key: %d", (int) result); } return result; } - diff --git a/OSX/libsecurity_keychain/lib/SecKeychain.h b/OSX/libsecurity_keychain/lib/SecKeychain.h index b8329154..b95f2ec5 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychain.h +++ b/OSX/libsecurity_keychain/lib/SecKeychain.h @@ -250,14 +250,14 @@ typedef CF_OPTIONS(UInt32, SecKeychainEventMask) @field pid The id of the process that generated this event. @discussion The SecKeychainCallbackInfo type represents a structure that contains information about the keychain event for which your application is being notified. For information on how to write a keychain event callback function, see SecKeychainCallback. */ -struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) SecKeychainCallbackInfo +struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) SecKeychainCallbackInfo { UInt32 version; SecKeychainItemRef __nonnull item; SecKeychainRef __nonnull keychain; pid_t pid; }; -typedef struct SecKeychainCallbackInfo SecKeychainCallbackInfo API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct SecKeychainCallbackInfo SecKeychainCallbackInfo API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainGetTypeID @@ -297,7 +297,7 @@ OSStatus SecKeychainOpen(const char *pathName, SecKeychainRef * __nonnull CF_RET @param keychain On return, a pointer to a keychain reference. The memory that keychain occupies must be released by calling CFRelease when finished with it. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if the keychain parameter is invalid (NULL). */ -OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void * __nullable password, Boolean promptUser, SecAccessRef __nullable initialAccess, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void * __nullable password, Boolean promptUser, SecAccessRef __nullable initialAccess, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainDelete @@ -305,7 +305,7 @@ OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const vo @param keychainOrArray A single keychain reference or a reference to an array of keychains to delete. IMPORTANT: SecKeychainDelete does not dispose the memory occupied by keychain references; use the CFRelease function when you are completely finished with a keychain. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecInvalidKeychain (-25295) may be returned if the keychain parameter is invalid (NULL). */ -OSStatus SecKeychainDelete(SecKeychainRef __nullable keychainOrArray) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainDelete(SecKeychainRef __nullable keychainOrArray) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSetSettings @@ -314,7 +314,7 @@ OSStatus SecKeychainDelete(SecKeychainRef __nullable keychainOrArray) API_UNAVAI @param newSettings A pointer to the new keychain settings. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainSetSettings(SecKeychainRef __nullable keychain, const SecKeychainSettings *newSettings) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainSetSettings(SecKeychainRef __nullable keychain, const SecKeychainSettings *newSettings) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainCopySettings @@ -323,7 +323,7 @@ OSStatus SecKeychainSetSettings(SecKeychainRef __nullable keychain, const SecKey @param outSettings A pointer to a keychain settings structure. Since this structure is versioned, you must preallocate it and fill in the version of the structure. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainCopySettings(SecKeychainRef __nullable keychain, SecKeychainSettings *outSettings) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainCopySettings(SecKeychainRef __nullable keychain, SecKeychainSettings *outSettings) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainUnlock @@ -335,7 +335,7 @@ OSStatus SecKeychainCopySettings(SecKeychainRef __nullable keychain, SecKeychain @result A result code. See "Security Error Codes" (SecBase.h). @discussion In most cases, your application does not need to call the SecKeychainUnlock function directly, since most Keychain Manager functions that require an unlocked keychain call SecKeychainUnlock automatically. If your application needs to verify that a keychain is unlocked, call the function SecKeychainGetStatus. */ -OSStatus SecKeychainUnlock(SecKeychainRef __nullable keychain, UInt32 passwordLength, const void * __nullable password, Boolean usePassword) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainUnlock(SecKeychainRef __nullable keychain, UInt32 passwordLength, const void * __nullable password, Boolean usePassword) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainLock @@ -343,14 +343,14 @@ OSStatus SecKeychainUnlock(SecKeychainRef __nullable keychain, UInt32 passwordLe @param keychain A reference to the keychain to lock. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainLock(SecKeychainRef __nullable keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainLock(SecKeychainRef __nullable keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainLockAll @abstract Locks all keychains belonging to the current user. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainLockAll(void) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainLockAll(void) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainCopyDefault @@ -358,7 +358,7 @@ OSStatus SecKeychainLockAll(void) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, @param keychain On return, a pointer to the default keychain reference. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainCopyDefault(SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainCopyDefault(SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSetDefault @@ -366,7 +366,7 @@ OSStatus SecKeychainCopyDefault(SecKeychainRef * __nonnull CF_RETURNS_RETAINED k @param keychain A reference to the keychain to set as default. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if the keychain parameter is invalid (NULL). */ -OSStatus SecKeychainSetDefault(SecKeychainRef __nullable keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainSetDefault(SecKeychainRef __nullable keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainCopySearchList @@ -374,7 +374,7 @@ OSStatus SecKeychainSetDefault(SecKeychainRef __nullable keychain) API_UNAVAILAB @param searchList The returned list of keychains to search. When finished with the array, you must call CFRelease() to release the memory. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if the keychain list is not specified (NULL). */ -OSStatus SecKeychainCopySearchList(CFArrayRef * __nonnull CF_RETURNS_RETAINED searchList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainCopySearchList(CFArrayRef * __nonnull CF_RETURNS_RETAINED searchList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSetSearchList @@ -382,7 +382,7 @@ OSStatus SecKeychainCopySearchList(CFArrayRef * __nonnull CF_RETURNS_RETAINED se @param searchList The list of keychains to use in a search list when the SecKeychainCopySearchList function is called. An empty array clears the search list. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if the keychain list is not specified (NULL). */ -OSStatus SecKeychainSetSearchList(CFArrayRef searchList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainSetSearchList(CFArrayRef searchList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* @@ -411,7 +411,7 @@ OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain); @param keychainStatus On return, a pointer to the status of the specified keychain. See KeychainStatus for valid status constants. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainGetStatus(SecKeychainRef __nullable keychain, SecKeychainStatus *keychainStatus) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainGetStatus(SecKeychainRef __nullable keychain, SecKeychainStatus *keychainStatus) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainGetPath @@ -421,7 +421,7 @@ OSStatus SecKeychainGetStatus(SecKeychainRef __nullable keychain, SecKeychainSta @param pathName On return, the POSIX path to the keychain. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainGetPath(SecKeychainRef __nullable keychain, UInt32 *ioPathLength, char *pathName) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainGetPath(SecKeychainRef __nullable keychain, UInt32 *ioPathLength, char *pathName) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- Keychain Item Attribute Information ---- /*! @@ -433,7 +433,7 @@ OSStatus SecKeychainGetPath(SecKeychainRef __nullable keychain, UInt32 *ioPathLe @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters were supplied (NULL). @discussion Warning, this call returns more attributes than are support by the old style Keychain API and passing them into older calls will yield an invalid attribute error. The recommended call to retrieve the attribute values is the SecKeychainItemCopyAttributesAndData function. */ -OSStatus SecKeychainAttributeInfoForItemID(SecKeychainRef __nullable keychain, UInt32 itemID, SecKeychainAttributeInfo * __nullable * __nonnull info) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainAttributeInfoForItemID(SecKeychainRef __nullable keychain, UInt32 itemID, SecKeychainAttributeInfo * __nullable * __nonnull info) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainFreeAttributeInfo @@ -441,7 +441,7 @@ OSStatus SecKeychainAttributeInfoForItemID(SecKeychainRef __nullable keychain, @param info A pointer to the keychain attribute information to release. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters were supplied (NULL). */ -OSStatus SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- Keychain Manager Callbacks ---- @@ -460,7 +460,7 @@ OSStatus SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info) API_UNAVAI To add your callback function, use the SecKeychainAddCallback function. To remove your callback function, use the SecKeychainRemoveCallback function. */ -typedef OSStatus (*SecKeychainCallback)(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void * __nullable context) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef OSStatus (*SecKeychainCallback)(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void * __nullable context) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainAddCallback @@ -470,7 +470,7 @@ typedef OSStatus (*SecKeychainCallback)(SecKeychainEvent keychainEvent, SecKeych @param userContext A pointer to application-defined storage that will be passed to your callback function. Your application can use this to associate any particular call of SecKeychainAddCallback with any particular call of your keychain event callback function. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void * __nullable userContext) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void * __nullable userContext) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainRemoveCallback @@ -478,7 +478,7 @@ OSStatus SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychai @param callbackFunction The callback function pointer to remove @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- High Level Keychain Manager Calls ---- /*! @@ -502,7 +502,7 @@ OSStatus SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) API_UNA @result A result code. See "Security Error Codes" (SecBase.h). @discussion The SecKeychainAddInternetPassword function adds a new Internet server password to the specified keychain. Required parameters to identify the password are serverName and accountName (you cannot pass NULL for both parameters). In addition, some protocols may require an optional securityDomain when authentication is requested. SecKeychainAddInternetPassword optionally returns a reference to the newly added item. */ -OSStatus SecKeychainAddInternetPassword(SecKeychainRef __nullable keychain, UInt32 serverNameLength, const char * __nullable serverName, UInt32 securityDomainLength, const char * __nullable securityDomain, UInt32 accountNameLength, const char * __nullable accountName, UInt32 pathLength, const char * __nullable path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainAddInternetPassword(SecKeychainRef __nullable keychain, UInt32 serverNameLength, const char * __nullable serverName, UInt32 securityDomainLength, const char * __nullable securityDomain, UInt32 accountNameLength, const char * __nullable accountName, UInt32 pathLength, const char * __nullable path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainFindInternetPassword @@ -525,7 +525,7 @@ OSStatus SecKeychainAddInternetPassword(SecKeychainRef __nullable keychain, UInt @result A result code. See "Security Error Codes" (SecBase.h). @discussion The SecKeychainFindInternetPassword function finds the first Internet password item which matches the attributes you provide. Most attributes are optional; you should pass only as many as you need to narrow the search sufficiently for your application's intended use. SecKeychainFindInternetPassword optionally returns a reference to the found item. */ -OSStatus SecKeychainFindInternetPassword(CFTypeRef __nullable keychainOrArray, UInt32 serverNameLength, const char * __nullable serverName, UInt32 securityDomainLength, const char * __nullable securityDomain, UInt32 accountNameLength, const char * __nullable accountName, UInt32 pathLength, const char * __nullable path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 * __nullable passwordLength, void * __nullable * __nullable passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainFindInternetPassword(CFTypeRef __nullable keychainOrArray, UInt32 serverNameLength, const char * __nullable serverName, UInt32 securityDomainLength, const char * __nullable securityDomain, UInt32 accountNameLength, const char * __nullable accountName, UInt32 pathLength, const char * __nullable path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 * __nullable passwordLength, void * __nullable * __nullable passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainAddGenericPassword @@ -541,7 +541,7 @@ OSStatus SecKeychainFindInternetPassword(CFTypeRef __nullable keychainOrArray, U @result A result code. See "Security Error Codes" (SecBase.h). @discussion The SecKeychainAddGenericPassword function adds a new generic password to the default keychain. Required parameters to identify the password are serviceName and accountName, which are application-defined strings. SecKeychainAddGenericPassword optionally returns a reference to the newly added item. */ -OSStatus SecKeychainAddGenericPassword(SecKeychainRef __nullable keychain, UInt32 serviceNameLength, const char * __nullable serviceName, UInt32 accountNameLength, const char * __nullable accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainAddGenericPassword(SecKeychainRef __nullable keychain, UInt32 serviceNameLength, const char * __nullable serviceName, UInt32 accountNameLength, const char * __nullable accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainFindGenericPassword @@ -557,7 +557,7 @@ OSStatus SecKeychainAddGenericPassword(SecKeychainRef __nullable keychain, UInt3 @result A result code. See "Security Error Codes" (SecBase.h). @discussion The SecKeychainFindGenericPassword function finds the first generic password item which matches the attributes you provide. Most attributes are optional; you should pass only as many as you need to narrow the search sufficiently for your application's intended use. SecKeychainFindGenericPassword optionally returns a reference to the found item. */ -OSStatus SecKeychainFindGenericPassword(CFTypeRef __nullable keychainOrArray, UInt32 serviceNameLength, const char * __nullable serviceName, UInt32 accountNameLength, const char * __nullable accountName, UInt32 * __nullable passwordLength, void * __nullable * __nullable passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainFindGenericPassword(CFTypeRef __nullable keychainOrArray, UInt32 serviceNameLength, const char * __nullable serviceName, UInt32 accountNameLength, const char * __nullable accountName, UInt32 * __nullable passwordLength, void * __nullable * __nullable passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- Managing User Interaction ---- /*! @@ -566,7 +566,7 @@ OSStatus SecKeychainFindGenericPassword(CFTypeRef __nullable keychainOrArray, U @param state A boolean representing the state of user interaction. You should pass TRUE to allow user interaction, and FALSE to disallow user interaction @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainSetUserInteractionAllowed(Boolean state) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainSetUserInteractionAllowed(Boolean state) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainGetUserInteractionAllowed @@ -574,7 +574,7 @@ OSStatus SecKeychainSetUserInteractionAllowed(Boolean state) API_UNAVAILABLE(ios @param state On return, a pointer to the current state of user interaction. If this is TRUE then user interaction is allowed, if it is FALSE, then user interaction is not allowed. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainGetUserInteractionAllowed(Boolean *state) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainGetUserInteractionAllowed(Boolean *state) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- CSSM Bridge Functions ---- /*! diff --git a/OSX/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp b/OSX/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp deleted file mode 100644 index db82b83a..00000000 --- a/OSX/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2003-2013 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - * - * SecKeychainAddIToolsPassword.c - * - * Based on Keychain item access control example - * -- added "always allow" ACL support - */ - -#include -#include -#include -#include -#include -#include -#include - - -OSStatus SecKeychainAddIToolsPassword(SecKeychainRef __unused keychain, - UInt32 __unused accountNameLength, - const char * __unused accountName, - UInt32 __unused passwordLength, - const void * __unused passwordData, - SecKeychainItemRef * __unused itemRef) -{ - return errSecParam; -} diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp b/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp index 6b31ddea..b5bd9748 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp @@ -44,6 +44,7 @@ #include "KCExceptions.h" #include "Access.h" #include "SecKeychainItemExtendedAttributes.h" +#include "LegacyAPICounts.h" extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref); @@ -79,7 +80,6 @@ CFTypeID SecKeychainItemGetTypeID(void) { BEGIN_SECAPI - return gTypes().ItemImpl.typeID; END_SECAPI1(_kCFRuntimeNotATypeID) @@ -127,7 +127,7 @@ SecKeychainItemCreateFromContent(SecItemClass itemClass, SecKeychainAttributeLis OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttributeList *attrList, UInt32 length, const void *data) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI os_activity_t activity = os_activity_create("SecKeychainItemModifyContent", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -171,7 +171,7 @@ SecKeychainItemFreeContent(SecKeychainAttributeList *attrList, void *data) OSStatus SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeychainAttributeList *attrList, UInt32 length, const void *data) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI os_activity_t activity = os_activity_create("SecKeychainItemModifyAttributesAndData", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -186,7 +186,7 @@ SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeyc OSStatus SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo *info, SecItemClass *itemClass, SecKeychainAttributeList **attrList, UInt32 *length, void **outData) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI Item item = ItemImpl::required(__itemImplRef); item->getAttributesAndData(info, itemClass, attrList, length, outData); @@ -199,7 +199,6 @@ OSStatus SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList *attrList, void *data) { BEGIN_SECAPI - ItemImpl::freeAttributesAndData(attrList, data); END_SECAPI @@ -209,7 +208,7 @@ SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList *attrList, void *d OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI os_activity_t activity = os_activity_create("SecKeychainItemDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -244,7 +243,7 @@ SecKeychainItemDelete(SecKeychainItemRef itemRef) OSStatus SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef* keychainRef) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI // make sure this item has a keychain Keychain kc = ItemImpl::required(__itemImplRef)->keychain(); @@ -263,7 +262,7 @@ OSStatus SecKeychainItemCreateCopy(SecKeychainItemRef itemRef, SecKeychainRef destKeychainRef, SecAccessRef initialAccess, SecKeychainItemRef *itemCopy) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI os_activity_t activity = os_activity_create("SecKeychainItemCreateCopy", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -304,34 +303,6 @@ SecKeychainItemGetDLDBHandle(SecKeychainItemRef itemRef, CSSM_DL_DB_HANDLE* dldb END_SECKCITEMAPI } -#if 0 -static -OSStatus SecAccessCreateFromObject(CFTypeRef sourceRef, - SecAccessRef *accessRef) -{ - BEGIN_SECAPI - - Required(accessRef); // preflight - SecPointer access = new Access(*aclBearer(sourceRef)); - *accessRef = access->handle(); - - END_SECAPI -} - - -/*! - */ -static -OSStatus SecAccessModifyObject(SecAccessRef accessRef, CFTypeRef sourceRef) -{ - BEGIN_SECAPI - - Access::required(accessRef)->setAccess(*aclBearer(sourceRef), true); - - END_SECAPI -} -#endif - OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef* accessRef) { @@ -567,6 +538,7 @@ OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainA static OSStatus SecKeychainItemCreatePersistentReferenceFromCertificate(SecCertificateRef certRef, CFDataRef *persistentItemRef, Boolean isIdentity) { + COUNTLEGACYAPI OSStatus __secapiresult; if (!certRef || !persistentItemRef) { return errSecParam; diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItem.h b/OSX/libsecurity_keychain/lib/SecKeychainItem.h index 764cea36..ec6f0057 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItem.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainItem.h @@ -160,7 +160,7 @@ CFTypeID SecKeychainItemGetTypeID(void); @result A result code. See "Security Error Codes" (SecBase.h). @discussion The keychain item is written to the keychain's permanent data store. If the keychain item has not previously been added to a keychain, a call to the SecKeychainItemModifyContent function does nothing and returns errSecSuccess. */ -OSStatus SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeychainAttributeList * __nullable attrList, UInt32 length, const void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeychainAttributeList * __nullable attrList, UInt32 length, const void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCreateFromContent @@ -176,7 +176,7 @@ OSStatus SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, cons */ OSStatus SecKeychainItemCreateFromContent(SecItemClass itemClass, SecKeychainAttributeList *attrList, UInt32 length, const void * __nullable data, SecKeychainRef __nullable keychainRef, - SecAccessRef __nullable initialAccess, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecAccessRef __nullable initialAccess, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemModifyContent @@ -187,7 +187,7 @@ OSStatus SecKeychainItemCreateFromContent(SecItemClass itemClass, SecKeychainAtt @param data A pointer to a buffer containing the data to store. Pass NULL if you don't need to modify the data. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttributeList * __nullable attrList, UInt32 length, const void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttributeList * __nullable attrList, UInt32 length, const void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyContent @@ -199,7 +199,7 @@ OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeych @param outData On return, a pointer to a buffer containing the data in this item. Pass NULL if you don't need to retrieve the data. You must call SecKeychainItemFreeContent when you no longer need the data. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters are supplied. */ -OSStatus SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass * __nullable itemClass, SecKeychainAttributeList * __nullable attrList, UInt32 * __nullable length, void * __nullable * __nullable outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass * __nullable itemClass, SecKeychainAttributeList * __nullable attrList, UInt32 * __nullable length, void * __nullable * __nullable outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemFreeContent @@ -207,7 +207,7 @@ OSStatus SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass * _ @param attrList A pointer to the attribute list to release. Pass NULL to ignore this parameter. @param data A pointer to the data buffer to release. Pass NULL to ignore this parameter. */ -OSStatus SecKeychainItemFreeContent(SecKeychainAttributeList * __nullable attrList, void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemFreeContent(SecKeychainAttributeList * __nullable attrList, void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyAttributesAndData @@ -220,7 +220,7 @@ OSStatus SecKeychainItemFreeContent(SecKeychainAttributeList * __nullable attrLi @param outData On return, a pointer to a buffer containing the data in this item. Pass NULL if you don't need to retrieve the data. You must call SecKeychainItemFreeAttributesAndData when you no longer need the data. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters are supplied. */ -OSStatus SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo * __nullable info, SecItemClass * __nullable itemClass, SecKeychainAttributeList * __nullable * __nullable attrList, UInt32 * __nullable length, void * __nullable * __nullable outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo * __nullable info, SecItemClass * __nullable itemClass, SecKeychainAttributeList * __nullable * __nullable attrList, UInt32 * __nullable length, void * __nullable * __nullable outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemFreeAttributesAndData @@ -229,7 +229,7 @@ OSStatus SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKey @param data A pointer to the data buffer to release. Pass NULL to ignore this parameter. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList * __nullable attrList, void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList * __nullable attrList, void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemDelete @@ -238,7 +238,7 @@ OSStatus SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList * __nulla @result A result code. See "Security Error Codes" (SecBase.h). @discussion If itemRef has not previously been added to the keychain, SecKeychainItemDelete does nothing and returns errSecSuccess. IMPORTANT: SecKeychainItemDelete does not dispose the memory occupied by the item reference itself; use the CFRelease function when you are completely finished with an item. */ -OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyKeychain @@ -247,7 +247,7 @@ OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, @param keychainRef On return, the keychain reference for the specified item. Release this reference by calling the CFRelease function. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychainRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychainRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCreateCopy @@ -259,7 +259,7 @@ OSStatus SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef @result A result code. See "Security Error Codes" (SecBase.h). */ OSStatus SecKeychainItemCreateCopy(SecKeychainItemRef itemRef, SecKeychainRef __nullable destKeychainRef, - SecAccessRef __nullable initialAccess, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemCopy) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecAccessRef __nullable initialAccess, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemCopy) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCreatePersistentReference @@ -268,7 +268,7 @@ OSStatus SecKeychainItemCreateCopy(SecKeychainItemRef itemRef, SecKeychainRef __ @param persistentItemRef On return, a CFDataRef containing a persistent reference. You must release this data reference by calling the CFRelease function. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CFDataRef * __nonnull CF_RETURNS_RETAINED persistentItemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CFDataRef * __nonnull CF_RETURNS_RETAINED persistentItemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @@ -278,7 +278,7 @@ OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CF @param itemRef On return, a SecKeychainItemRef for the keychain item described by the persistent reference. You must release this item reference by calling the CFRelease function. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- CSSM Bridge Functions ---- @@ -312,7 +312,7 @@ OSStatus SecKeychainItemGetUniqueRecordID(SecKeychainItemRef itemRef, const CSSM @param access On return, a reference to the keychain item's access. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef * __nonnull CF_RETURNS_RETAINED access) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef * __nonnull CF_RETURNS_RETAINED access) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemSetAccess @@ -321,7 +321,7 @@ OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef * __ @param access A reference to an access to replace the keychain item's current access. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemSetAccess(SecKeychainItemRef itemRef, SecAccessRef access) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemSetAccess(SecKeychainItemRef itemRef, SecAccessRef access) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp index 60c98f31..3ae8d1bf 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp @@ -30,19 +30,7 @@ #include "KCCursor.h" #include -/* I'm not sure we need this */ -#if 0 -CFTypeID SecKeychainItemExtendedAttributesGetTypeID(void); - -static CFTypeID SecKeychainItemExtendedAttributesGetTypeID(void) -{ - BEGIN_SECAPI - - return gTypes().ExtendedAttribute.typeID; - - END_SECAPI1(_kCFRuntimeNotATypeID) -} -#endif +#include "LegacyAPICounts.h" extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref); diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h index 1bd1caea..9e925f2d 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h @@ -77,7 +77,7 @@ OSStatus SecKeychainItemSetExtendedAttribute( CFStringRef attrName, /* identifies the attribute */ CFDataRef attrValue) /* value to set; NULL means delete the * attribute */ - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * SecKeychainItemCopyExtendedAttribute() - Obtain the value of an an extended attribute. @@ -91,7 +91,7 @@ OSStatus SecKeychainItemSetExtendedAttribute( OSStatus SecKeychainItemCopyExtendedAttribute( SecKeychainItemRef itemRef, CFStringRef attrName, - CFDataRef *attrValue) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); /* RETURNED */ + CFDataRef *attrValue) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* RETURNED */ /* * SecKeychainItemCopyAllExtendedAttributes() - obtain all of an item's extended attributes. @@ -119,7 +119,7 @@ OSStatus SecKeychainItemCopyAllExtendedAttributes( CFArrayRef *attrNames, /* RETURNED, each element is a CFStringRef */ CFArrayRef *attrValues) /* optional, RETURNED, each element is a * CFDataRef */ - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h b/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h index 96e89d0e..d9b13b26 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h @@ -72,23 +72,23 @@ enum { /* also kSecModDateItemAttr from SecKeychainItem.h */ }; -OSStatus SecKeychainItemCreateNew(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, SecKeychainItemRef* itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCreateNew(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, SecKeychainItemRef* itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemGetData(SecKeychainItemRef itemRef, UInt32 maxLength, void* data, UInt32* actualLength) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemGetData(SecKeychainItemRef itemRef, UInt32 maxLength, void* data, UInt32* actualLength) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemGetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute, UInt32* actualLength) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemGetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute, UInt32* actualLength) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemSetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemSetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemAdd(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemAdd(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemAddNoUI(SecKeychainRef keychainRef, SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemAddNoUI(SecKeychainRef keychainRef, SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemUpdate(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemUpdate(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemSetData(SecKeychainItemRef itemRef, UInt32 length, const void* data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemSetData(SecKeychainItemRef itemRef, UInt32 length, const void* data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef, SecKeychainItemRef *itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef, SecKeychainItemRef *itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyRecordIdentifier @@ -98,7 +98,7 @@ OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainA @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCopyRecordIdentifier(SecKeychainItemRef itemRef, CFDataRef *recordIdentifier) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyRecordIdentifier(SecKeychainItemRef itemRef, CFDataRef *recordIdentifier) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyFromRecordIdentifier @@ -111,7 +111,7 @@ OSStatus SecKeychainItemCopyRecordIdentifier(SecKeychainItemRef itemRef, CFDataR OSStatus SecKeychainItemCopyFromRecordIdentifier(SecKeychainRef keychain, SecKeychainItemRef *itemRef, - CFDataRef recordIdentifier) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + CFDataRef recordIdentifier) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyAttributesAndEncryptedData @@ -128,7 +128,7 @@ OSStatus SecKeychainItemCopyFromRecordIdentifier(SecKeychainRef keychain, */ OSStatus SecKeychainItemCopyAttributesAndEncryptedData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo *info, SecItemClass *itemClass, SecKeychainAttributeList **attrList, - UInt32 *length, void **outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + UInt32 *length, void **outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemModifyEncryptedData @@ -140,7 +140,7 @@ OSStatus SecKeychainItemCopyAttributesAndEncryptedData(SecKeychainItemRef itemRe @result A result code. See "Security Error Codes" (SecBase.h). @discussion The keychain item is written to the keychain's permanent data store. If the keychain item has not previously been added to a keychain, a call to the SecKeychainItemModifyContent function does nothing and returns errSecSuccess. */ -OSStatus SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef, UInt32 length, const void *data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef, UInt32 length, const void *data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCreateFromEncryptedContent @@ -156,7 +156,7 @@ OSStatus SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef, UInt32 l */ OSStatus SecKeychainItemCreateFromEncryptedContent(SecItemClass itemClass, UInt32 length, const void *data, SecKeychainRef keychainRef, SecAccessRef initialAccess, - SecKeychainItemRef *itemRef, CFDataRef *itemLocalID) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecKeychainItemRef *itemRef, CFDataRef *itemLocalID) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemSetAccessWithPassword @@ -167,7 +167,7 @@ OSStatus SecKeychainItemCreateFromEncryptedContent(SecItemClass itemClass, UInt3 @param password A buffer containing the password for the keychain. if this password is incorrect, this call might fail---it will not prompt the user. @result A result code. See "Security Error Codes" (SecBase.h). */ - OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_keychain/lib/SecKeychainPriv.h b/OSX/libsecurity_keychain/lib/SecKeychainPriv.h index 2b035d94..7caaad33 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainPriv.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainPriv.h @@ -48,8 +48,6 @@ OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); OSStatus SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword) __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_NA); -OSStatus SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subserviceType, const char* dbName, const CSSM_NET_ADDRESS *dbLocation, SecKeychainRef *keychain) - API_DEPRECATED("CSSM_GUID/CSSM_NET_ADDRESS is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); @@ -98,11 +96,11 @@ OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, S /* Keychain list manipulation */ OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType) - API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType) - API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType) - API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* server operation (keychain inhibit) */ void SecKeychainSetServerMode(void) diff --git a/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp b/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp index 5e94b58c..a84f0e3e 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp @@ -32,12 +32,12 @@ #include #include "SecBridge.h" +#include "LegacyAPICounts.h" CFTypeID SecKeychainSearchGetTypeID(void) { BEGIN_SECAPI - return gTypes().KCCursorImpl.typeID; END_SECAPI1(_kCFRuntimeNotATypeID) diff --git a/OSX/libsecurity_keychain/lib/SecKeychainSearch.h b/OSX/libsecurity_keychain/lib/SecKeychainSearch.h index fed709fa..3a85f485 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainSearch.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainSearch.h @@ -45,7 +45,7 @@ CF_ASSUME_NONNULL_BEGIN @discussion This API is deprecated in 10.7. The SecKeychainSearchRef type is no longer used. */ CFTypeID SecKeychainSearchGetTypeID(void) - API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSearchCreateFromAttributes @@ -58,7 +58,7 @@ CFTypeID SecKeychainSearchGetTypeID(void) @discussion This function is deprecated in Mac OS X 10.7 and later; to find keychain items which match specified attributes, please use the SecItemCopyMatching API (see SecItem.h). */ OSStatus SecKeychainSearchCreateFromAttributes(CFTypeRef __nullable keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList * __nullable attrList, SecKeychainSearchRef * __nonnull CF_RETURNS_RETAINED searchRef) - API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSearchCopyNext @@ -69,7 +69,7 @@ OSStatus SecKeychainSearchCreateFromAttributes(CFTypeRef __nullable keychainOrAr @discussion This function is deprecated in Mac OS X 10.7 and later; to find keychain items which match specified attributes, please use the SecItemCopyMatching API (see SecItem.h). */ OSStatus SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemRef) - API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_keychain/lib/SecPassword.cpp b/OSX/libsecurity_keychain/lib/SecPassword.cpp index 6ac71ed4..f56197ae 100644 --- a/OSX/libsecurity_keychain/lib/SecPassword.cpp +++ b/OSX/libsecurity_keychain/lib/SecPassword.cpp @@ -32,17 +32,7 @@ #include -#if 0 -static CFTypeID -SecPasswordGetTypeID(void) -{ - BEGIN_SECAPI - - return gTypes().PasswordImpl.typeID; - - END_SECAPI1(_kCFRuntimeNotATypeID) -} -#endif +#include "LegacyAPICounts.h" OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList, SecPasswordRef *itemRef) @@ -254,7 +244,7 @@ SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt3 } - // If we're still here the use gave us his password, store it if keychain is in use + // If we're still here the user gave us their password, store it if keychain is in use if (passwordRef->useKeychain()) { if (passwordRef->rememberInKeychain()) { diff --git a/OSX/libsecurity_keychain/lib/SecPassword.h b/OSX/libsecurity_keychain/lib/SecPassword.h index 9be0a79d..7ffaaa69 100644 --- a/OSX/libsecurity_keychain/lib/SecPassword.h +++ b/OSX/libsecurity_keychain/lib/SecPassword.h @@ -65,7 +65,7 @@ enum { @param itemAttrList (in/opt) A list of attributes which will be used for item creation. @param itemRef (out) On return, a pointer to a password reference. Release this by calling the CFRelease function. */ -OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList, SecPasswordRef *itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList, SecPasswordRef *itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecPasswordAction @@ -80,13 +80,13 @@ OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecK @param data A pointer to a buffer containing the data to store. */ -OSStatus SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt32 *length, const void **data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt32 *length, const void **data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecPasswordSetInitialAccess @abstract Set the initial access ref. Only used when a password is first added to the keychain. */ -OSStatus SecPasswordSetInitialAccess(SecPasswordRef itemRef, SecAccessRef accessRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecPasswordSetInitialAccess(SecPasswordRef itemRef, SecAccessRef accessRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) } diff --git a/OSX/libsecurity_keychain/lib/SecPolicy.cpp b/OSX/libsecurity_keychain/lib/SecPolicy.cpp index 56aeaefd..7f20d626 100644 --- a/OSX/libsecurity_keychain/lib/SecPolicy.cpp +++ b/OSX/libsecurity_keychain/lib/SecPolicy.cpp @@ -435,54 +435,6 @@ SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE* tpHandle) return errSecServiceNotAvailable; } -/* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */ -OSStatus -SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef* policies) -{ - /* bridge to support old functionality */ -#if SECTRUST_DEPRECATION_WARNINGS - syslog(LOG_ERR, "WARNING: SecPolicyCopyAll was deprecated in 10.7. Please use SecPolicy creation functions instead."); -#endif - if (!policies) { - return errSecParam; - } - CFMutableArrayRef curPolicies = CFArrayCreateMutable(NULL, 0, NULL); - if (!curPolicies) { - return errSecAllocate; - } - /* build the subset of policies which were supported on OS X, - and which are also implemented on iOS */ - CFStringRef supportedPolicies[] = { - kSecPolicyAppleX509Basic, /* CSSMOID_APPLE_X509_BASIC */ - kSecPolicyAppleSSL, /* CSSMOID_APPLE_TP_SSL */ - kSecPolicyAppleSMIME, /* CSSMOID_APPLE_TP_SMIME */ - kSecPolicyAppleEAP, /*CSSMOID_APPLE_TP_EAP */ - kSecPolicyAppleSWUpdateSigning, /* CSSMOID_APPLE_TP_SW_UPDATE_SIGNING */ - kSecPolicyAppleIPsec, /* CSSMOID_APPLE_TP_IP_SEC */ - kSecPolicyAppleCodeSigning, /* CSSMOID_APPLE_TP_CODE_SIGNING */ - kSecPolicyMacAppStoreReceipt, /* CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT */ - kSecPolicyAppleIDValidation, /* CSSMOID_APPLE_TP_APPLEID_SHARING */ - kSecPolicyAppleTimeStamping, /* CSSMOID_APPLE_TP_TIMESTAMPING */ - kSecPolicyAppleRevocation, /* CSSMOID_APPLE_TP_REVOCATION_{CRL,OCSP} */ - NULL - }; - CFIndex ix = 0; - while (true) { - CFStringRef policyID = supportedPolicies[ix++]; - if (!policyID) { - break; - } - SecPolicyRef curPolicy = SecPolicyCreateWithProperties(policyID, NULL); - if (curPolicy) { - CFArrayAppendValue(curPolicies, curPolicy); - CFRelease(curPolicy); - } - } - *policies = CFArrayCreateCopy(NULL, curPolicies); - CFRelease(curPolicies); - return errSecSuccess; -} - /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */ OSStatus SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy) diff --git a/OSX/libsecurity_keychain/lib/SecPolicySearch.cpp b/OSX/libsecurity_keychain/lib/SecPolicySearch.cpp index 6bde1086..9bb6dfd1 100644 --- a/OSX/libsecurity_keychain/lib/SecPolicySearch.cpp +++ b/OSX/libsecurity_keychain/lib/SecPolicySearch.cpp @@ -33,7 +33,6 @@ CFTypeID SecPolicySearchGetTypeID(void) { BEGIN_SECAPI - return gTypes().PolicyCursor.typeID; END_SECAPI1(_kCFRuntimeNotATypeID) @@ -67,7 +66,6 @@ SecPolicySearchCopyNext( SecPolicyRef* policyRef) { BEGIN_SECAPI - RequiredParam(policyRef); SecPointer policy; diff --git a/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp b/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp index 3d64c65d..9e17b255 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp +++ b/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp @@ -43,10 +43,11 @@ void SecTrustLegacySourcesListenForKeychainEvents(void) { notify_register_dispatch(kSecServerCertificateTrustNotification, &out_token, dispatch_get_main_queue(), ^(int token __unused) { - // Purge keychain parent cache - SecItemParentCachePurge(); - // Purge unrestricted roots cache - SecTrustSettingsPurgeUserAdminCertsCache(); - - }); + // Purge keychain parent cache + SecItemParentCachePurge(); + // Purge tust settings cert cache + SecTrustSettingsPurgeUserAdminCertsCache(); + // Purge the trust settings cache + SecTrustSettingsPurgeCache(); + }); } diff --git a/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp b/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp index f4ecc54e..c2a7e133 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp +++ b/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include #include @@ -108,7 +108,7 @@ static bool tsUserTrustSettingsDisabled() Dictionary* dictionary = Dictionary::CreateDictionary(kSecTrustSettingsPrefsDomain, Dictionary::US_System); if (dictionary) { - auto_ptr prefsDict(dictionary); + unique_ptr prefsDict(dictionary); /* this returns false if the pref isn't there, just like we want */ tsUserTrustDisable = prefsDict->getBoolValue(kSecTrustSettingsDisableUserTrustSettings); } @@ -348,7 +348,7 @@ static OSStatus tsCopyTrustSettings( return result; } - auto_ptr_(ts); // make sure this gets deleted just in case something throws underneath + unique_ptr_(ts); // make sure this gets deleted just in case something throws underneath if(trustSettings) { *trustSettings = ts->copyTrustSettings(cert); @@ -360,6 +360,59 @@ static OSStatus tsCopyTrustSettings( END_RCSAPI } +/* + * Common code for SecTrustSettingsCopyTrustSettings(), + * SecTrustSettingsCopyModificationDate(). + */ +static OSStatus tsCopyTrustSettings_cached( + SecCertificateRef cert, + SecTrustSettingsDomain domain, + CFArrayRef CF_RETURNS_RETAINED *trustSettings) +{ + BEGIN_RCSAPI + + TS_REQUIRED(cert) + + StLock _(sutCacheLock()); + TrustSettings* ts = tsGetGlobalTrustSettings(domain); + + // rather than throw these results, just return them because we are at the top level + if (ts == NULL) { + return errSecItemNotFound; + } + + if(trustSettings) { + *trustSettings = ts->copyTrustSettings(cert); + } + + END_RCSAPI +} + +static OSStatus tsContains( + SecCertificateRef cert, + SecTrustSettingsDomain domain) +{ + BEGIN_RCSAPI + + TS_REQUIRED(cert) + + StLock _(sutCacheLock()); + TrustSettings* ts = tsGetGlobalTrustSettings(domain); + + // rather than throw these results, just return them because we are at the top level + if (ts == NULL) { + return errSecItemNotFound; + } + + if (ts->contains(cert)) { + return errSecSuccess; + } else { + return errSecItemNotFound; + } + + END_RCSAPI +} + static void tsAddConditionalCerts(CFMutableArrayRef certArray); /* @@ -727,7 +780,7 @@ OSStatus SecTrustSettingsSetTrustSettingsExternal( return result; } - auto_ptr_(ts); + unique_ptr_(ts); if(certRef != NULL) { ts->setTrustSettings(certRef, trustSettingsDictOrArray); @@ -738,6 +791,25 @@ OSStatus SecTrustSettingsSetTrustSettingsExternal( END_RCSAPI } +void SecTrustSettingsPurgeCache(void) { + tsPurgeCache(); +} + +OSStatus SecTrustSettingsCopyTrustSettings_Cached( + SecCertificateRef certRef, + SecTrustSettingsDomain domain, + CFArrayRef CF_RETURNS_RETAINED *trustSettings) /* RETURNED */ +{ + TS_REQUIRED(certRef) + TS_REQUIRED(trustSettings) + + OSStatus result = tsCopyTrustSettings_cached(certRef, domain, trustSettings); + if (result == errSecSuccess && *trustSettings == NULL) { + result = errSecItemNotFound; /* documented result if no trust settings exist */ + } + return result; +} + #pragma mark --- API functions --- OSStatus SecTrustSettingsCopyTrustSettings( @@ -792,7 +864,7 @@ OSStatus SecTrustSettingsSetTrustSettings( return result; } - auto_ptr_(ts); + unique_ptr_(ts); ts->setTrustSettings(certRef, trustSettingsDictOrArray); ts->flushToDisk(); @@ -822,7 +894,7 @@ OSStatus SecTrustSettingsRemoveTrustSettings( return result; } - auto_ptr_(ts); + unique_ptr_(ts); /* deleteTrustSettings throws if record not found */ trustSettingsDbg("SecTrustSettingsRemoveTrustSettings: deleting from domain %d", @@ -854,7 +926,7 @@ OSStatus SecTrustSettingsCopyCertificates( return status; } - auto_ptr_(ts); + unique_ptr_(ts); CFMutableArrayRef outArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); @@ -1003,6 +1075,16 @@ OSStatus SecTrustSettingsCopyCertificatesForUserAdminDomains( return result; } +bool SecTrustSettingsUserAdminDomainsContain(SecCertificateRef certRef) +{ + TS_REQUIRED(certRef) + if (tsContains(certRef, kSecTrustSettingsDomainAdmin) == errSecSuccess || + tsContains(certRef, kSecTrustSettingsDomainUser) == errSecSuccess) { + return true; + } + return false; +} + /* * Obtain an external, portable representation of the specified * domain's TrustSettings. Caller must CFRelease the returned data. @@ -1023,7 +1105,7 @@ OSStatus SecTrustSettingsCreateExternalRepresentation( return result; } - auto_ptr_(ts); + unique_ptr_(ts); *trustSettings = ts->createExternal(); return errSecSuccess; @@ -1053,7 +1135,7 @@ OSStatus SecTrustSettingsImportExternalRepresentation( return result; } - auto_ptr_(ts); + unique_ptr_(ts); ts->flushToDisk(); tsTrustSettingsChanged(); diff --git a/OSX/libsecurity_keychain/lib/SecTrustedApplication.cpp b/OSX/libsecurity_keychain/lib/SecTrustedApplication.cpp index 5f9e0c78..6a240424 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustedApplication.cpp +++ b/OSX/libsecurity_keychain/lib/SecTrustedApplication.cpp @@ -44,7 +44,6 @@ CFTypeID SecTrustedApplicationGetTypeID(void) { BEGIN_SECAPI - return gTypes().TrustedApplication.typeID; END_SECAPI1(_kCFRuntimeNotATypeID) @@ -195,7 +194,6 @@ OSStatus SecTrustedApplicationCreateApplicationGroup(const char *groupName, SecCertificateRef anchor, SecTrustedApplicationRef *appRef) { BEGIN_SECAPI - CFRef req; MacOSError::check(SecRequirementCreateGroup(CFTempString(groupName), anchor, kSecCSDefaultFlags, &req.aref())); diff --git a/OSX/libsecurity_keychain/lib/SecTrustedApplication.h b/OSX/libsecurity_keychain/lib/SecTrustedApplication.h index b1f37a6e..286ce287 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustedApplication.h +++ b/OSX/libsecurity_keychain/lib/SecTrustedApplication.h @@ -58,7 +58,7 @@ CFTypeID SecTrustedApplicationGetTypeID(void); */ OSStatus SecTrustedApplicationCreateFromPath(const char * __nullable path, SecTrustedApplicationRef * __nonnull CF_RETURNS_RETAINED app) API_DEPRECATED("No longer supported", macos(10.0, 10.15)) - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationCopyData @@ -69,7 +69,7 @@ OSStatus SecTrustedApplicationCreateFromPath(const char * __nullable path, SecTr */ OSStatus SecTrustedApplicationCopyData(SecTrustedApplicationRef appRef, CFDataRef * __nonnull CF_RETURNS_RETAINED data) API_DEPRECATED("No longer supported", macos(10.0, 10.15)) - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationSetData @@ -80,7 +80,7 @@ OSStatus SecTrustedApplicationCopyData(SecTrustedApplicationRef appRef, CFDataRe */ OSStatus SecTrustedApplicationSetData(SecTrustedApplicationRef appRef, CFDataRef data) API_DEPRECATED("No longer supported", macos(10.0, 10.15)) - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_keychain/lib/SecTrustedApplicationPriv.h b/OSX/libsecurity_keychain/lib/SecTrustedApplicationPriv.h index 1b9911ad..6c6badad 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustedApplicationPriv.h +++ b/OSX/libsecurity_keychain/lib/SecTrustedApplicationPriv.h @@ -42,7 +42,7 @@ extern "C" { * Determine whether the application at path satisfies the trust expressed in appRef. */ OSStatus -SecTrustedApplicationValidateWithPath(SecTrustedApplicationRef appRef, const char *path) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +SecTrustedApplicationValidateWithPath(SecTrustedApplicationRef appRef, const char *path) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationCreateFromRequirement @@ -60,7 +60,7 @@ SecTrustedApplicationValidateWithPath(SecTrustedApplicationRef appRef, const cha @result A result code. See SecBase.h and CSCommon.h. */ OSStatus SecTrustedApplicationCreateFromRequirement(const char *description, - SecRequirementRef requirement, SecTrustedApplicationRef *app) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecRequirementRef requirement, SecTrustedApplicationRef *app) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationCopyRequirement @@ -78,7 +78,7 @@ OSStatus SecTrustedApplicationCreateFromRequirement(const char *description, no SecRequirementRef could be obtained. */ OSStatus SecTrustedApplicationCopyRequirement(SecTrustedApplicationRef appRef, - SecRequirementRef *requirement) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecRequirementRef *requirement) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @@ -101,7 +101,7 @@ OSStatus SecTrustedApplicationCopyRequirement(SecTrustedApplicationRef appRef, @result A result code. See SecBase.h and CSCommon.h. */ OSStatus SecTrustedApplicationCreateApplicationGroup(const char *groupName, - SecCertificateRef anchor, SecTrustedApplicationRef *app) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecCertificateRef anchor, SecTrustedApplicationRef *app) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @@ -118,7 +118,7 @@ OSStatus SecTrustedApplicationCreateApplicationGroup(const char *groupName, */ OSStatus SecTrustedApplicationCopyExternalRepresentation( SecTrustedApplicationRef appRef, - CFDataRef *externalRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + CFDataRef *externalRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationCreateWithExternalRepresentation @@ -133,7 +133,7 @@ OSStatus SecTrustedApplicationCopyExternalRepresentation( */ OSStatus SecTrustedApplicationCreateWithExternalRepresentation( CFDataRef externalRef, - SecTrustedApplicationRef *appRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecTrustedApplicationRef *appRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* @@ -146,10 +146,10 @@ enum { OSStatus SecTrustedApplicationMakeEquivalent(SecTrustedApplicationRef oldRef, - SecTrustedApplicationRef newRef, UInt32 flags) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecTrustedApplicationRef newRef, UInt32 flags) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); OSStatus -SecTrustedApplicationRemoveEquivalence(SecTrustedApplicationRef appRef, UInt32 flags) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +SecTrustedApplicationRemoveEquivalence(SecTrustedApplicationRef appRef, UInt32 flags) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* @@ -157,7 +157,7 @@ SecTrustedApplicationRemoveEquivalence(SecTrustedApplicationRef appRef, UInt32 f * pre-emptive code equivalency establishment */ OSStatus -SecTrustedApplicationIsUpdateCandidate(const char *installroot, const char *path) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +SecTrustedApplicationIsUpdateCandidate(const char *installroot, const char *path) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* @@ -165,7 +165,7 @@ SecTrustedApplicationIsUpdateCandidate(const char *installroot, const char *path * This is for system update installers (only)! */ OSStatus -SecTrustedApplicationUseAlternateSystem(const char *systemRoot) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +SecTrustedApplicationUseAlternateSystem(const char *systemRoot) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) diff --git a/OSX/libsecurity_keychain/lib/SecWrappedKeys.cpp b/OSX/libsecurity_keychain/lib/SecWrappedKeys.cpp index 83b8db37..a438f948 100644 --- a/OSX/libsecurity_keychain/lib/SecWrappedKeys.cpp +++ b/OSX/libsecurity_keychain/lib/SecWrappedKeys.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include using namespace Security; using namespace KeychainCore; diff --git a/OSX/libsecurity_keychain/lib/StorageManager.cpp b/OSX/libsecurity_keychain/lib/StorageManager.cpp index efab9b8b..e173e851 100644 --- a/OSX/libsecurity_keychain/lib/StorageManager.cpp +++ b/OSX/libsecurity_keychain/lib/StorageManager.cpp @@ -1356,10 +1356,11 @@ void StorageManager::login(ConstStringPtr name, ConstStringPtr password) { StLock_(mMutex); - if ( name == NULL || password == NULL ) + if ( name == NULL || password == NULL ) { MacOSError::throwMe(errSecParam); + } - login(name[0], name + 1, password[0], password + 1, false); + login(name[0], name + 1, password[0], password + 1, false); } void StorageManager::login(UInt32 nameLength, const void *name, diff --git a/OSX/libsecurity_keychain/lib/TrustAdditions.cpp b/OSX/libsecurity_keychain/lib/TrustAdditions.cpp index 3fa9aabb..0710cadb 100644 --- a/OSX/libsecurity_keychain/lib/TrustAdditions.cpp +++ b/OSX/libsecurity_keychain/lib/TrustAdditions.cpp @@ -377,10 +377,11 @@ CFArrayRef potentialEVChainWithCertificates(CFArrayRef certificates) // static SecCertificateRef _rootCertificateWithSubjectOfCertificate(SecCertificateRef certificate) { - if (!certificate) + if (!certificate) { return NULL; + } - StLock _(SecTrustKeychainsGetMutex()); + StLock _(SecTrustKeychainsGetMutex()); // get data+length for the provided certificate CSSM_CL_HANDLE clHandle = 0; @@ -519,8 +520,9 @@ static SecCertificateRef _rootCertificateWithSubjectKeyIDOfCertificate(SecCertif SecCertificateRef resultCert = NULL; OSStatus status = errSecSuccess; - if (!certificate) + if (!certificate) { return NULL; + } StLock _(SecTrustKeychainsGetMutex()); @@ -557,8 +559,9 @@ CFArrayRef CF_RETURNS_RETAINED _possibleRootCertificatesForOidString(CFStringRef { StLock _(SecTrustKeychainsGetMutex()); - if (!oidString) + if (!oidString) { return NULL; + } CFDictionaryRef evOidDict = _evCAOidDict(); if (!evOidDict) return NULL; diff --git a/OSX/libsecurity_keychain/lib/TrustRevocation.cpp b/OSX/libsecurity_keychain/lib/TrustRevocation.cpp index 6338d1c0..8cd49615 100644 --- a/OSX/libsecurity_keychain/lib/TrustRevocation.cpp +++ b/OSX/libsecurity_keychain/lib/TrustRevocation.cpp @@ -261,7 +261,7 @@ CFMutableArrayRef Trust::addPreferenceRevocationPolicies( pd = new Dictionary(tempDict); CFRelease(tempDict); - auto_ptr prefsDict(pd); + unique_ptr prefsDict(pd); bool doOcsp = false; bool doCrl = false; diff --git a/OSX/libsecurity_keychain/lib/TrustSettings.cpp b/OSX/libsecurity_keychain/lib/TrustSettings.cpp index 7474aca6..c834712c 100644 --- a/OSX/libsecurity_keychain/lib/TrustSettings.cpp +++ b/OSX/libsecurity_keychain/lib/TrustSettings.cpp @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include @@ -1019,6 +1019,14 @@ CFDateRef TrustSettings::copyModDate( return modDate; } +bool TrustSettings::contains(SecCertificateRef certRef) +{ + if(findDictionaryForCert(certRef) != NULL) { + return true; + } + return false; +} + /* * Modify cert's trust settings, or add a new cert to the record. */ diff --git a/OSX/libsecurity_keychain/lib/TrustSettings.h b/OSX/libsecurity_keychain/lib/TrustSettings.h index d1362d53..c98d1a26 100644 --- a/OSX/libsecurity_keychain/lib/TrustSettings.h +++ b/OSX/libsecurity_keychain/lib/TrustSettings.h @@ -177,6 +177,11 @@ public: */ CFDataRef createExternal(); + /* + * Indicates whether the trust settings contain any settings for this cert. + */ + bool contains(SecCertificateRef certRef); + private: /* common code to init mPropList from raw data */ void initFromData( diff --git a/OSX/libsecurity_keychain/lib/TrustSettingsUtils.cpp b/OSX/libsecurity_keychain/lib/TrustSettingsUtils.cpp index e001afd0..934449a6 100644 --- a/OSX/libsecurity_keychain/lib/TrustSettingsUtils.cpp +++ b/OSX/libsecurity_keychain/lib/TrustSettingsUtils.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/OSX/libsecurity_keychain/regressions/kc-28-p12-import.m b/OSX/libsecurity_keychain/regressions/kc-28-p12-import.m index 77641dda..3598f633 100644 --- a/OSX/libsecurity_keychain/regressions/kc-28-p12-import.m +++ b/OSX/libsecurity_keychain/regressions/kc-28-p12-import.m @@ -248,8 +248,8 @@ setIdentityPreferenceForImportedIdentity(SecKeychainRef importKeychain, NSString OSStatus status = noErr; importedIdRef = (SecIdentityRef)item; - status = SecIdentitySetPreference(importedIdRef, (CFStringRef)name, (CSSM_KEYUSE)0); - ok_status(status, "%s: SecIdentitySetPreference", testName); + status = SecIdentitySetPreferred(importedIdRef, (CFStringRef)name, NULL); + ok_status(status, "%s: SecIdentitySetPreferred", testName); break; } } @@ -264,17 +264,12 @@ setIdentityPreferenceForImportedIdentity(SecKeychainRef importKeychain, NSString static void removeIdentityPreference(bool test) { // Clean up the identity preference, since it's in the default keychain - CFMutableDictionaryRef q = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionarySetValue(q, kSecClass, kSecClassGenericPassword); - q = addLabel(q, CFSTR("kc-28-p12-import@apple.com")); - + OSStatus status = SecIdentitySetPreferred(NULL, CFSTR("kc-28-p12-import@apple.com"), NULL); if(test) { - ok_status(SecItemDelete(q), "%s: SecItemDelete (identity preference)", testName); + ok_status(status, "%s: SecItemSetPreferred (clear identity preference)", testName); } else { // Our caller doesn't care if this works or not. - SecItemDelete(q); } - CFReleaseNull(q); } diff --git a/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c b/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c deleted file mode 100644 index 557e5447..00000000 --- a/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c +++ /dev/null @@ -1,759 +0,0 @@ -/* - * Copyright (c) 2014-2019 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include - -#include "keychain_regressions.h" -#include "utilities/SecCFRelease.h" -#include "utilities/SecCFWrappers.h" - -/* subject:/businessCategory=Private Organization/jurisdictionC=US/jurisdictionST=Delaware/serialNumber=3014267/C=US/ST=California/L=San Jose/O=PayPal, Inc./OU=CDN Support/CN=www.paypal.com */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA */ -/* EXPIRES Aug 18 12:00:00 2020 GMT */ - -unsigned char leaf_certificate[2012]={ - 0x30,0x82,0x07,0xD8,0x30,0x82,0x06,0xC0,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x01, - 0x5B,0xDA,0x66,0x5F,0xC4,0x4B,0x75,0x17,0xB6,0x88,0x2C,0x1E,0xAB,0xD4,0xDC,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x75, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x34,0x30,0x32,0x06,0x03,0x55,0x04,0x03,0x13,0x2B,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x53,0x48,0x41,0x32,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64, - 0x20,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x72,0x76, - 0x65,0x72,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x38,0x30,0x38,0x31,0x34,0x30, - 0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x30,0x30,0x38,0x31,0x38,0x31,0x32, - 0x30,0x30,0x30,0x30,0x5A,0x30,0x81,0xDC,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04, - 0x0F,0x0C,0x14,0x50,0x72,0x69,0x76,0x61,0x74,0x65,0x20,0x4F,0x72,0x67,0x61,0x6E, - 0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x31,0x13,0x30,0x11,0x06,0x0B,0x2B,0x06,0x01, - 0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,0x13,0x02,0x55,0x53,0x31,0x19,0x30,0x17, - 0x06,0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x02,0x13,0x08,0x44, - 0x65,0x6C,0x61,0x77,0x61,0x72,0x65,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x05, - 0x13,0x07,0x33,0x30,0x31,0x34,0x32,0x36,0x37,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13, - 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x11,0x30,0x0F,0x06, - 0x03,0x55,0x04,0x07,0x13,0x08,0x53,0x61,0x6E,0x20,0x4A,0x6F,0x73,0x65,0x31,0x15, - 0x30,0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x50,0x61,0x79,0x50,0x61,0x6C,0x2C, - 0x20,0x49,0x6E,0x63,0x2E,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B,0x13,0x0B, - 0x43,0x44,0x4E,0x20,0x53,0x75,0x70,0x70,0x6F,0x72,0x74,0x31,0x17,0x30,0x15,0x06, - 0x03,0x55,0x04,0x03,0x13,0x0E,0x77,0x77,0x77,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C, - 0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A, - 0x02,0x82,0x01,0x01,0x00,0xCE,0xA1,0xFA,0xE0,0x19,0x8B,0xD7,0x8D,0x51,0xC7,0xD5, - 0x62,0x84,0x83,0x13,0xB9,0xD7,0xF6,0xCD,0x93,0xC5,0x70,0xD1,0x69,0x59,0x03,0x2B, - 0xB4,0x8B,0x00,0x14,0x50,0xB6,0x77,0x9A,0xB2,0x3C,0xFB,0x13,0xB0,0x80,0x4E,0x55, - 0x1A,0x08,0x60,0xA1,0x06,0x3D,0x40,0xD2,0x00,0xD2,0x67,0x45,0x3E,0xB1,0x26,0x45, - 0x14,0x00,0x65,0x78,0xAD,0xB3,0x39,0x4B,0xE6,0xCF,0x28,0x92,0xCE,0x3E,0xB4,0x5C, - 0xC1,0x1C,0x7B,0x49,0xA7,0x60,0xFD,0x06,0x2C,0x51,0x2B,0x10,0x11,0x01,0xFA,0x3A, - 0x73,0x9E,0x2D,0xB9,0xF6,0x89,0x52,0xB4,0x32,0x20,0xCC,0x2B,0xDA,0x6A,0x5F,0x6C, - 0xFA,0x31,0xDE,0x96,0xA5,0x90,0xAE,0xD1,0x98,0x77,0x62,0x99,0xC3,0xAA,0xB5,0x48, - 0xE3,0x43,0x24,0xBF,0x59,0xC1,0xF1,0x32,0x4C,0x97,0xDF,0x06,0xBD,0x7B,0x52,0x68, - 0x10,0x1F,0x68,0x7C,0x91,0xAE,0xA4,0xD9,0xC2,0xF7,0x4B,0x86,0x83,0x18,0xA5,0x58, - 0xBB,0xCE,0xB6,0x7F,0xF6,0xEF,0x0E,0x7A,0xA7,0x60,0x18,0x90,0xAA,0x12,0x1A,0x05, - 0xEC,0x35,0x11,0x84,0xE7,0x24,0xB1,0x9E,0xCD,0xB7,0xB1,0x93,0xA8,0xB6,0x04,0x9E, - 0x4D,0x17,0xB5,0xE8,0xAE,0xD7,0xE4,0x9B,0xB3,0x3D,0xC1,0xAD,0x64,0x63,0x11,0xC6, - 0x59,0x15,0x6A,0x06,0x6C,0xAE,0x9F,0x2B,0x36,0xC7,0xF8,0x6A,0xAD,0x30,0x2A,0x40, - 0x63,0x92,0xF5,0x73,0x4A,0xF2,0x53,0x68,0x32,0x52,0x0E,0xA1,0x2D,0x85,0x5F,0x99, - 0xA0,0x64,0x85,0x62,0x9C,0x1A,0x1C,0x0A,0xD5,0x8A,0xBD,0x2C,0x27,0xAD,0xC4,0xFD, - 0xAA,0xB6,0x4D,0xBF,0x7B,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x03,0xFA,0x30,0x82, - 0x03,0xF6,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x3D, - 0xD3,0x50,0xA5,0xD6,0xA0,0xAD,0xEE,0xF3,0x4A,0x60,0x0A,0x65,0xD3,0x21,0xD4,0xF8, - 0xF8,0xD6,0x0F,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xBB,0x3A, - 0xE6,0xA8,0x29,0x00,0x98,0x84,0x32,0x79,0xCE,0x77,0xF0,0x01,0x6D,0x5F,0x0A,0x79, - 0x63,0xB9,0x30,0x81,0xA5,0x06,0x03,0x55,0x1D,0x11,0x04,0x81,0x9D,0x30,0x81,0x9A, - 0x82,0x0E,0x77,0x77,0x77,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D, - 0x82,0x12,0x68,0x69,0x73,0x74,0x6F,0x72,0x79,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C, - 0x2E,0x63,0x6F,0x6D,0x82,0x0C,0x74,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63, - 0x6F,0x6D,0x82,0x0C,0x63,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D, - 0x82,0x0D,0x63,0x36,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D,0x82, - 0x14,0x64,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x2E,0x70,0x61,0x79,0x70,0x61, - 0x6C,0x2E,0x63,0x6F,0x6D,0x82,0x0C,0x70,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E, - 0x63,0x6F,0x6D,0x82,0x15,0x77,0x77,0x77,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x6F, - 0x62,0x6A,0x65,0x63,0x74,0x73,0x2E,0x63,0x6F,0x6D,0x82,0x0E,0x63,0x6D,0x73,0x2E, - 0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D,0x30,0x0E,0x06,0x03,0x55,0x1D, - 0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06,0x03,0x55,0x1D, - 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06, - 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x75,0x06,0x03,0x55,0x1D,0x1F, - 0x04,0x6E,0x30,0x6C,0x30,0x34,0xA0,0x32,0xA0,0x30,0x86,0x2E,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x33,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74, - 0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x68,0x61,0x32,0x2D,0x65,0x76,0x2D,0x73,0x65,0x72, - 0x76,0x65,0x72,0x2D,0x67,0x32,0x2E,0x63,0x72,0x6C,0x30,0x34,0xA0,0x32,0xA0,0x30, - 0x86,0x2E,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x34,0x2E,0x64,0x69, - 0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x68,0x61,0x32,0x2D, - 0x65,0x76,0x2D,0x73,0x65,0x72,0x76,0x65,0x72,0x2D,0x67,0x32,0x2E,0x63,0x72,0x6C, - 0x30,0x4B,0x06,0x03,0x55,0x1D,0x20,0x04,0x44,0x30,0x42,0x30,0x37,0x06,0x09,0x60, - 0x86,0x48,0x01,0x86,0xFD,0x6C,0x02,0x01,0x30,0x2A,0x30,0x28,0x06,0x08,0x2B,0x06, - 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F, - 0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D, - 0x2F,0x43,0x50,0x53,0x30,0x07,0x06,0x05,0x67,0x81,0x0C,0x01,0x01,0x30,0x81,0x88, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x7C,0x30,0x7A,0x30,0x24, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74, - 0x2E,0x63,0x6F,0x6D,0x30,0x52,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02, - 0x86,0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x61,0x63,0x65,0x72,0x74,0x73, - 0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x44,0x69, - 0x67,0x69,0x43,0x65,0x72,0x74,0x53,0x48,0x41,0x32,0x45,0x78,0x74,0x65,0x6E,0x64, - 0x65,0x64,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x72,0x76, - 0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01, - 0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x82,0x01,0x7E,0x06,0x0A,0x2B,0x06,0x01,0x04, - 0x01,0xD6,0x79,0x02,0x04,0x02,0x04,0x82,0x01,0x6E,0x04,0x82,0x01,0x6A,0x01,0x68, - 0x00,0x77,0x00,0xA4,0xB9,0x09,0x90,0xB4,0x18,0x58,0x14,0x87,0xBB,0x13,0xA2,0xCC, - 0x67,0x70,0x0A,0x3C,0x35,0x98,0x04,0xF9,0x1B,0xDF,0xB8,0xE3,0x77,0xCD,0x0E,0xC8, - 0x0D,0xDC,0x10,0x00,0x00,0x01,0x65,0x3A,0xAE,0x43,0x7C,0x00,0x00,0x04,0x03,0x00, - 0x48,0x30,0x46,0x02,0x21,0x00,0xCB,0xD9,0x94,0x2A,0x60,0x3F,0x6F,0xAF,0xF2,0x01, - 0xFC,0xDB,0x2D,0xCF,0x42,0x83,0x0D,0x55,0x45,0x50,0x34,0x18,0xC6,0xE0,0x36,0x72, - 0xEE,0xA4,0x45,0x06,0x8D,0x09,0x02,0x21,0x00,0x93,0x31,0x1F,0x36,0x47,0x36,0xFC, - 0x1F,0xBC,0xF1,0x54,0x77,0x42,0x3B,0xAD,0x9D,0xA1,0x75,0x42,0x98,0xF4,0x42,0x44, - 0xA8,0x74,0xF1,0x80,0xB4,0x1D,0xFB,0xED,0x45,0x00,0x75,0x00,0x56,0x14,0x06,0x9A, - 0x2F,0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC, - 0x99,0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x65, - 0x3A,0xAE,0x43,0xD9,0x00,0x00,0x04,0x03,0x00,0x46,0x30,0x44,0x02,0x20,0x70,0x2F, - 0xCD,0xBB,0x18,0x85,0xB3,0x32,0xE6,0x35,0x1A,0xCE,0x3E,0x97,0xDE,0x60,0xCC,0x8E, - 0x3C,0xAB,0xC8,0xDE,0x41,0x33,0x06,0xC3,0x20,0x5B,0xF9,0xF1,0x3F,0x67,0x02,0x20, - 0x71,0xCD,0x42,0x11,0x4D,0xF8,0xFE,0x29,0xEB,0xE9,0xD2,0x69,0x8E,0x39,0xEF,0x6A, - 0xE8,0xAF,0xE4,0x94,0xE5,0x36,0x92,0x54,0x6E,0x56,0x67,0x2C,0xEC,0x6C,0xF0,0xF0, - 0x00,0x76,0x00,0xBB,0xD9,0xDF,0xBC,0x1F,0x8A,0x71,0xB5,0x93,0x94,0x23,0x97,0xAA, - 0x92,0x7B,0x47,0x38,0x57,0x95,0x0A,0xAB,0x52,0xE8,0x1A,0x90,0x96,0x64,0x36,0x8E, - 0x1E,0xD1,0x85,0x00,0x00,0x01,0x65,0x3A,0xAE,0x44,0x68,0x00,0x00,0x04,0x03,0x00, - 0x47,0x30,0x45,0x02,0x21,0x00,0xCB,0xF3,0x70,0x9C,0x39,0x96,0x83,0x9F,0x56,0x70, - 0xCD,0x14,0x4A,0xF8,0xF9,0xCE,0x32,0xFE,0xEB,0x00,0xDA,0x95,0x39,0x33,0xBB,0xE1, - 0x1C,0xD0,0xFA,0xF3,0x4B,0x47,0x02,0x20,0x12,0xA8,0xF7,0x7B,0x29,0x73,0x5A,0x35, - 0x32,0x6C,0x04,0x9F,0x48,0x7C,0x13,0x7A,0x27,0x65,0xF0,0x18,0x98,0xF1,0x71,0xC4, - 0x72,0xF5,0xF2,0x5C,0xF7,0xE5,0x20,0x62,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xA1,0xEB,0x9E,0x7F, - 0xC7,0x17,0x2E,0x28,0x2F,0x4D,0x0B,0x38,0x95,0xBB,0x5B,0xCA,0x9E,0x14,0x38,0x8C, - 0xEC,0xA6,0x23,0x26,0x1F,0x3B,0x6A,0x07,0xDE,0x4E,0x4B,0x41,0x11,0xFE,0xEE,0xFD, - 0xF7,0x94,0x8E,0xD0,0x2D,0x26,0x42,0x3B,0xF2,0x3D,0xE8,0xA9,0xB5,0x0E,0x58,0x87, - 0xEF,0xCE,0x54,0x2A,0x95,0xEA,0x9D,0x99,0xA4,0x19,0x92,0x73,0xE9,0xA7,0xE6,0xDC, - 0xE3,0x3F,0x72,0xDA,0x57,0x1A,0x32,0x8F,0x08,0x21,0x8D,0xAD,0x37,0x98,0xD0,0x57, - 0x3E,0x67,0x64,0x10,0x81,0xBE,0x57,0xBF,0x0E,0xBF,0x98,0x88,0x9B,0xAB,0xF1,0x18, - 0x7D,0x71,0x4A,0x31,0xEC,0xB1,0x5F,0x22,0x5E,0x95,0xA8,0xDE,0x02,0x7E,0xC4,0x7D, - 0xE4,0xAE,0xD6,0x35,0x02,0xD9,0x20,0xDB,0x8D,0xC9,0x83,0x03,0x42,0x23,0x7C,0x60, - 0xA7,0x4D,0x55,0x30,0xB0,0x26,0xBC,0x8B,0xEF,0x4E,0xA9,0x88,0x29,0xE1,0x1D,0xF3, - 0xC5,0x24,0x73,0xA9,0x07,0x71,0x9B,0x04,0x8F,0x1C,0x2D,0x36,0x2B,0xD6,0xC7,0x69, - 0xE5,0xD5,0xCC,0x83,0xBB,0xD0,0x75,0xC0,0x92,0xB4,0x0F,0x93,0x2E,0x20,0x15,0xE0, - 0x6C,0x52,0xA6,0xA9,0x48,0x56,0x94,0x45,0xD1,0x8A,0x6A,0x61,0xBC,0xE3,0x4E,0x24, - 0x67,0x7B,0xD6,0xA4,0xFD,0xE1,0xB4,0xFF,0xF9,0xB8,0x6A,0xDB,0xCA,0x06,0x95,0xE1, - 0xF5,0x95,0xE4,0xEF,0xA9,0xFB,0x74,0x7E,0x3F,0x9E,0xFD,0xAE,0xDE,0x1F,0x1D,0x6E, - 0xDD,0xF6,0x00,0xC4,0xD5,0xA3,0x34,0x02,0x26,0x23,0x1A,0x46,0x53,0x25,0x30,0x49, - 0x5A,0x36,0xF7,0x0F,0xC2,0x61,0x87,0x36,0x71,0x2E,0xBD,0xCB, -}; - -/* subject:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA */ -/* EXPIRES Oct 22 12:00:00 2028 GMT */ - -unsigned char CA_certificate[1210]={ - 0x30,0x82,0x04,0xB6,0x30,0x82,0x03,0x9E,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x0C, - 0x79,0xA9,0x44,0xB0,0x8C,0x11,0x95,0x20,0x92,0x61,0x5F,0xE2,0x6B,0x1D,0x83,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6C, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63, - 0x65,0x20,0x45,0x56,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, - 0x31,0x33,0x31,0x30,0x32,0x32,0x31,0x32,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32, - 0x38,0x31,0x30,0x32,0x32,0x31,0x32,0x30,0x30,0x30,0x30,0x5A,0x30,0x75,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x20,0x49, - 0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77,0x77,0x77, - 0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31,0x34,0x30, - 0x32,0x06,0x03,0x55,0x04,0x03,0x13,0x2B,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x53,0x48,0x41,0x32,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56, - 0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x72,0x76,0x65,0x72, - 0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, - 0x82,0x01,0x01,0x00,0xD7,0x53,0xA4,0x04,0x51,0xF8,0x99,0xA6,0x16,0x48,0x4B,0x67, - 0x27,0xAA,0x93,0x49,0xD0,0x39,0xED,0x0C,0xB0,0xB0,0x00,0x87,0xF1,0x67,0x28,0x86, - 0x85,0x8C,0x8E,0x63,0xDA,0xBC,0xB1,0x40,0x38,0xE2,0xD3,0xF5,0xEC,0xA5,0x05,0x18, - 0xB8,0x3D,0x3E,0xC5,0x99,0x17,0x32,0xEC,0x18,0x8C,0xFA,0xF1,0x0C,0xA6,0x64,0x21, - 0x85,0xCB,0x07,0x10,0x34,0xB0,0x52,0x88,0x2B,0x1F,0x68,0x9B,0xD2,0xB1,0x8F,0x12, - 0xB0,0xB3,0xD2,0xE7,0x88,0x1F,0x1F,0xEF,0x38,0x77,0x54,0x53,0x5F,0x80,0x79,0x3F, - 0x2E,0x1A,0xAA,0xA8,0x1E,0x4B,0x2B,0x0D,0xAB,0xB7,0x63,0xB9,0x35,0xB7,0x7D,0x14, - 0xBC,0x59,0x4B,0xDF,0x51,0x4A,0xD2,0xA1,0xE2,0x0C,0xE2,0x90,0x82,0x87,0x6A,0xAE, - 0xEA,0xD7,0x64,0xD6,0x98,0x55,0xE8,0xFD,0xAF,0x1A,0x50,0x6C,0x54,0xBC,0x11,0xF2, - 0xFD,0x4A,0xF2,0x9D,0xBB,0x7F,0x0E,0xF4,0xD5,0xBE,0x8E,0x16,0x89,0x12,0x55,0xD8, - 0xC0,0x71,0x34,0xEE,0xF6,0xDC,0x2D,0xEC,0xC4,0x87,0x25,0x86,0x8D,0xD8,0x21,0xE4, - 0xB0,0x4D,0x0C,0x89,0xDC,0x39,0x26,0x17,0xDD,0xF6,0xD7,0x94,0x85,0xD8,0x04,0x21, - 0x70,0x9D,0x6F,0x6F,0xFF,0x5C,0xBA,0x19,0xE1,0x45,0xCB,0x56,0x57,0x28,0x7E,0x1C, - 0x0D,0x41,0x57,0xAA,0xB7,0xB8,0x27,0xBB,0xB1,0xE4,0xFA,0x2A,0xEF,0x21,0x23,0x75, - 0x1A,0xAD,0x2D,0x9B,0x86,0x35,0x8C,0x9C,0x77,0xB5,0x73,0xAD,0xD8,0x94,0x2D,0xE4, - 0xF3,0x0C,0x9D,0xEE,0xC1,0x4E,0x62,0x7E,0x17,0xC0,0x71,0x9E,0x2C,0xDE,0xF1,0xF9, - 0x10,0x28,0x19,0x33,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x49,0x30,0x82,0x01, - 0x45,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01, - 0x01,0xFF,0x02,0x01,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, - 0x04,0x03,0x02,0x01,0x86,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x03,0x02,0x30,0x34,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, - 0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, - 0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69, - 0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x4B,0x06,0x03,0x55,0x1D, - 0x1F,0x04,0x44,0x30,0x42,0x30,0x40,0xA0,0x3E,0xA0,0x3C,0x86,0x3A,0x68,0x74,0x74, - 0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x34,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72, - 0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x48,0x69, - 0x67,0x68,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63,0x65,0x45,0x56,0x52,0x6F,0x6F, - 0x74,0x43,0x41,0x2E,0x63,0x72,0x6C,0x30,0x3D,0x06,0x03,0x55,0x1D,0x20,0x04,0x36, - 0x30,0x34,0x30,0x32,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x2A,0x30,0x28,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70,0x73,0x3A, - 0x2F,0x2F,0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63, - 0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, - 0x14,0x3D,0xD3,0x50,0xA5,0xD6,0xA0,0xAD,0xEE,0xF3,0x4A,0x60,0x0A,0x65,0xD3,0x21, - 0xD4,0xF8,0xF8,0xD6,0x0F,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, - 0x80,0x14,0xB1,0x3E,0xC3,0x69,0x03,0xF8,0xBF,0x47,0x01,0xD4,0x98,0x26,0x1A,0x08, - 0x02,0xEF,0x63,0x64,0x2B,0xC3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x9D,0xB6,0xD0,0x90,0x86,0xE1, - 0x86,0x02,0xED,0xC5,0xA0,0xF0,0x34,0x1C,0x74,0xC1,0x8D,0x76,0xCC,0x86,0x0A,0xA8, - 0xF0,0x4A,0x8A,0x42,0xD6,0x3F,0xC8,0xA9,0x4D,0xAD,0x7C,0x08,0xAD,0xE6,0xB6,0x50, - 0xB8,0xA2,0x1A,0x4D,0x88,0x07,0xB1,0x29,0x21,0xDC,0xE7,0xDA,0xC6,0x3C,0x21,0xE0, - 0xE3,0x11,0x49,0x70,0xAC,0x7A,0x1D,0x01,0xA4,0xCA,0x11,0x3A,0x57,0xAB,0x7D,0x57, - 0x2A,0x40,0x74,0xFD,0xD3,0x1D,0x85,0x18,0x50,0xDF,0x57,0x47,0x75,0xA1,0x7D,0x55, - 0x20,0x2E,0x47,0x37,0x50,0x72,0x8C,0x7F,0x82,0x1B,0xD2,0x62,0x8F,0x2D,0x03,0x5A, - 0xDA,0xC3,0xC8,0xA1,0xCE,0x2C,0x52,0xA2,0x00,0x63,0xEB,0x73,0xBA,0x71,0xC8,0x49, - 0x27,0x23,0x97,0x64,0x85,0x9E,0x38,0x0E,0xAD,0x63,0x68,0x3C,0xBA,0x52,0x81,0x58, - 0x79,0xA3,0x2C,0x0C,0xDF,0xDE,0x6D,0xEB,0x31,0xF2,0xBA,0xA0,0x7C,0x6C,0xF1,0x2C, - 0xD4,0xE1,0xBD,0x77,0x84,0x37,0x03,0xCE,0x32,0xB5,0xC8,0x9A,0x81,0x1A,0x4A,0x92, - 0x4E,0x3B,0x46,0x9A,0x85,0xFE,0x83,0xA2,0xF9,0x9E,0x8C,0xA3,0xCC,0x0D,0x5E,0xB3, - 0x3D,0xCF,0x04,0x78,0x8F,0x14,0x14,0x7B,0x32,0x9C,0xC7,0x00,0xA6,0x5C,0xC4,0xB5, - 0xA1,0x55,0x8D,0x5A,0x56,0x68,0xA4,0x22,0x70,0xAA,0x3C,0x81,0x71,0xD9,0x9D,0xA8, - 0x45,0x3B,0xF4,0xE5,0xF6,0xA2,0x51,0xDD,0xC7,0x7B,0x62,0xE8,0x6F,0x0C,0x74,0xEB, - 0xB8,0xDA,0xF8,0xBF,0x87,0x0D,0x79,0x50,0x91,0x90,0x9B,0x18,0x3B,0x91,0x59,0x27, - 0xF1,0x35,0x28,0x13,0xAB,0x26,0x7E,0xD5,0xF7,0x7A, -}; - -unsigned char smime_leaf_certificate[1338]={ - 0x30,0x82,0x05,0x36,0x30,0x82,0x04,0x1E,0xA0,0x03,0x02,0x01,0x02,0x02,0x0D,0x14, - 0x00,0x01,0x00,0x02,0x9C,0xE1,0xB9,0xE0,0x7C,0xD1,0x7B,0xEC,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x7C,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03, - 0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E, - 0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04, - 0x0B,0x13,0x1C,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65, - 0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20,0x43,0x41,0x31, - 0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1F,0x54,0x43,0x20,0x54,0x72,0x75, - 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31, - 0x20,0x4C,0x31,0x20,0x43,0x41,0x20,0x49,0x58,0x30,0x1E,0x17,0x0D,0x31,0x30,0x31, - 0x31,0x31,0x32,0x30,0x36,0x33,0x36,0x34,0x35,0x5A,0x17,0x0D,0x31,0x31,0x31,0x31, - 0x31,0x33,0x30,0x36,0x33,0x36,0x34,0x35,0x5A,0x30,0x24,0x31,0x0B,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04, - 0x03,0x13,0x0C,0x51,0x75,0x69,0x6E,0x6E,0x20,0x54,0x61,0x79,0x6C,0x6F,0x72,0x30, - 0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, - 0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00, - 0xC1,0x11,0xAA,0x04,0xCF,0x04,0xA0,0x07,0xF3,0x43,0x2A,0xB2,0x27,0x1A,0x13,0x35, - 0x97,0x9A,0xBA,0x34,0xE5,0x84,0xF3,0xD5,0xE5,0xD9,0xAB,0x23,0x8D,0xB4,0x7E,0x68, - 0x5C,0xF2,0x9A,0xF1,0x08,0x9B,0x04,0x34,0xC1,0x09,0x14,0x68,0xD8,0x9C,0xC1,0x6C, - 0x27,0xF5,0x92,0x54,0xAF,0x66,0x65,0xF1,0x50,0xAA,0x7E,0xE3,0xFC,0xC1,0xB0,0x3E, - 0xEF,0xAA,0x86,0x58,0x4F,0xE7,0x86,0x0A,0x74,0xA6,0x97,0xBD,0x7D,0xF6,0xCE,0xA6, - 0x8B,0xF7,0xC0,0x90,0x6E,0x50,0x69,0x36,0x65,0x82,0x0F,0x65,0xA7,0x2C,0x16,0xFA, - 0x6C,0xCA,0x54,0x45,0x7C,0x06,0x20,0x72,0xF0,0x00,0x7B,0xD7,0x17,0xCD,0x94,0x64, - 0x6A,0xB7,0x28,0xF3,0x62,0xB1,0x29,0xAE,0x0C,0x8A,0x2F,0x3C,0x06,0x89,0xE8,0x81, - 0x77,0xAD,0x1F,0x65,0xED,0x6F,0x51,0x64,0x65,0x68,0x76,0xD8,0xEE,0xEC,0xA6,0x28, - 0xA9,0x1C,0x4F,0x98,0x4A,0x6D,0xD0,0xC8,0x5C,0x59,0x17,0x9B,0xF8,0x6D,0xF5,0x93, - 0xD3,0x4C,0x2A,0x37,0x80,0x65,0xB4,0x34,0xBA,0x64,0x2F,0xA1,0x8E,0x1C,0x6A,0x88, - 0x7C,0xA3,0xDB,0xDD,0x00,0x9B,0x78,0x51,0x7B,0xA6,0x8D,0xDD,0x43,0x9B,0xB2,0x2E, - 0x4B,0x1E,0xB3,0x34,0x37,0x3F,0x63,0x08,0x8C,0xC8,0xCF,0xD0,0xB0,0x8C,0xBF,0x8F, - 0xA7,0x49,0xBD,0x48,0x1D,0xB5,0x1E,0x6A,0x42,0x48,0x16,0x9A,0x7C,0xD3,0x55,0x6B, - 0xFF,0xD6,0xBA,0x70,0xF3,0x5F,0x1F,0x57,0x16,0xE0,0x1C,0xF1,0x73,0x22,0xD9,0x33, - 0xA7,0x20,0xE8,0xED,0x52,0x2A,0xE9,0x6F,0xCF,0xFB,0x76,0xAC,0xB8,0x5D,0x9B,0xAB, - 0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x02,0x0D,0x30,0x82,0x02,0x09,0x30,0x81,0xA5, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x81,0x98,0x30,0x81,0x95, - 0x30,0x51,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x45,0x68,0x74, - 0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65, - 0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x65,0x72,0x74,0x73,0x65,0x72,0x76, - 0x69,0x63,0x65,0x73,0x2F,0x63,0x61,0x63,0x65,0x72,0x74,0x73,0x2F,0x74,0x63,0x5F, - 0x63,0x6C,0x61,0x73,0x73,0x31,0x5F,0x4C,0x31,0x5F,0x43,0x41,0x5F,0x49,0x58,0x2E, - 0x63,0x72,0x74,0x30,0x40,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86, - 0x34,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x69,0x78,0x2E, - 0x74,0x63,0x63,0x6C,0x61,0x73,0x73,0x31,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65, - 0x72,0x73,0x61,0x6C,0x2D,0x69,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2E,0x64,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, - 0x80,0x14,0xE9,0xB8,0x28,0x1D,0x46,0xCF,0xFC,0xCD,0xF8,0x4E,0x9B,0xC5,0xEE,0x4B, - 0x60,0xEB,0xD8,0x3B,0x3F,0xD1,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, - 0x04,0x02,0x30,0x00,0x30,0x4A,0x06,0x03,0x55,0x1D,0x20,0x04,0x43,0x30,0x41,0x30, - 0x3F,0x06,0x09,0x2A,0x82,0x14,0x00,0x2C,0x01,0x01,0x01,0x01,0x30,0x32,0x30,0x30, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x24,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2E,0x64,0x65,0x2F,0x67,0x75,0x69,0x64,0x65,0x6C,0x69,0x6E,0x65,0x73, - 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x04,0xF0, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xF8,0x4D,0x7F,0xDE,0xFA, - 0x21,0x2E,0xAF,0x96,0xBB,0xAA,0x9B,0x22,0x56,0x80,0xF0,0x8E,0xD4,0x6A,0x52,0x30, - 0x62,0x06,0x03,0x55,0x1D,0x1F,0x04,0x5B,0x30,0x59,0x30,0x57,0xA0,0x55,0xA0,0x53, - 0x86,0x51,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x69,0x78,0x2E, - 0x74,0x63,0x63,0x6C,0x61,0x73,0x73,0x31,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65, - 0x72,0x73,0x61,0x6C,0x2D,0x69,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x72,0x6C,0x2F,0x76,0x32,0x2F,0x74,0x63,0x5F, - 0x43,0x6C,0x61,0x73,0x73,0x31,0x5F,0x4C,0x31,0x5F,0x43,0x41,0x5F,0x49,0x58,0x2E, - 0x63,0x72,0x6C,0x30,0x33,0x06,0x03,0x55,0x1D,0x25,0x04,0x2C,0x30,0x2A,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x03,0x04,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x07,0x06,0x0A,0x2B,0x06, - 0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02,0x30,0x1C,0x06,0x03,0x55,0x1D,0x11,0x04, - 0x15,0x30,0x13,0x81,0x11,0x71,0x74,0x61,0x79,0x6C,0x6F,0x72,0x40,0x61,0x70,0x70, - 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x0D,0xCF,0x33,0xAB,0x3D,0xD3, - 0xD2,0x06,0x2C,0x20,0x3C,0xEC,0x0C,0xE4,0xA5,0x19,0x86,0xB3,0xA7,0xA9,0xA6,0xE9, - 0xDC,0xB4,0x35,0xBB,0x0D,0x67,0xD5,0xBD,0x5F,0x93,0xD9,0x2E,0xA0,0x05,0x2A,0xED, - 0xAE,0x41,0xD9,0xEE,0x30,0xA8,0x82,0x50,0xD0,0x4B,0x04,0x6B,0x37,0xAE,0xC0,0x10, - 0x89,0x05,0x68,0x82,0x91,0x2B,0x5B,0xE2,0x7D,0xA6,0x87,0xF7,0x26,0x96,0xBA,0x2A, - 0x52,0x03,0x97,0xF6,0x2E,0x0D,0x81,0x65,0x24,0x10,0xD5,0x8C,0xB3,0xCD,0x19,0x58, - 0xAF,0x3A,0x3D,0x2F,0x10,0x30,0x79,0x6A,0xD6,0x08,0x8F,0x8B,0x9D,0x1D,0xF8,0x19, - 0xE4,0x24,0x2B,0xE0,0x7F,0x73,0xE1,0x50,0x9C,0x53,0xE1,0x46,0xC7,0xA7,0xBD,0x71, - 0xCD,0xFF,0x39,0xA0,0x50,0xA5,0xA8,0xD9,0x50,0x39,0x6C,0x36,0x1C,0x13,0x89,0x8A, - 0x0D,0x9D,0x06,0x1B,0xAA,0x59,0x40,0xC1,0xAF,0xED,0x66,0x31,0xB8,0xA0,0x9F,0xCF, - 0xA6,0x8A,0x2E,0xC2,0x1A,0x4B,0xDB,0x62,0x15,0x6E,0x10,0x2F,0x82,0x3C,0xF8,0xA2, - 0x18,0x63,0xCC,0x67,0x13,0x42,0x07,0x43,0xDB,0x20,0x13,0xC7,0xAC,0xCE,0xCB,0xEA, - 0x7E,0x53,0xA6,0x01,0x81,0xB2,0x6E,0x92,0x2B,0x0C,0xF9,0x01,0x2C,0x11,0xC9,0x00, - 0x10,0x58,0x64,0x56,0x91,0xAC,0xAA,0xF6,0xE0,0x73,0xC7,0x59,0xEC,0xCE,0x51,0x7E, - 0xAD,0x9F,0x04,0xA4,0x38,0x74,0x65,0xD0,0x23,0xBD,0x6E,0xDF,0x64,0x79,0xE2,0xA3, - 0x37,0x19,0x2F,0x8C,0x41,0x8B,0x5F,0x6D,0x84,0x61,0x54,0xD1,0x26,0x18,0x70,0xAD, - 0xE5,0xF4,0xCD,0x59,0xED,0x9E,0xE0,0xC9,0x9F,0xD3, -}; - -unsigned char smime_CA_certificate[1500]={ - 0x30,0x82,0x05,0xD8,0x30,0x82,0x04,0xC0,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x06, - 0xE8,0x00,0x01,0x00,0x02,0x4A,0x96,0x2D,0x24,0x0C,0xFE,0xC5,0xC9,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x79,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, - 0x6E,0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x1B,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74, - 0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31, - 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75, - 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73, - 0x61,0x6C,0x20,0x43,0x41,0x20,0x49,0x30,0x1E,0x17,0x0D,0x30,0x39,0x31,0x31,0x30, - 0x33,0x31,0x34,0x30,0x38,0x31,0x39,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x33,0x31, - 0x32,0x31,0x35,0x39,0x35,0x39,0x5A,0x30,0x7C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20, - 0x47,0x6D,0x62,0x48,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C,0x54, - 0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x43,0x6C, - 0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20,0x43,0x41,0x31,0x28,0x30,0x26,0x06, - 0x03,0x55,0x04,0x03,0x13,0x1F,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, - 0x6E,0x74,0x65,0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20, - 0x43,0x41,0x20,0x49,0x58,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, - 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, - 0x0A,0x02,0x82,0x01,0x01,0x00,0xBB,0xE6,0x90,0x6E,0xCF,0x62,0xE9,0xE9,0x0B,0xAA, - 0xB6,0x10,0xD5,0x47,0xE5,0x7C,0x5D,0x2B,0x27,0x71,0x9A,0x68,0xCD,0x55,0x6D,0xE4, - 0xA2,0xEF,0xE4,0xFE,0xF2,0x7A,0x63,0x11,0xC2,0x57,0x8A,0xC8,0x7D,0xCF,0x8E,0x66, - 0x1F,0x65,0x45,0x4B,0xEB,0x80,0x62,0x69,0xBD,0x46,0x8E,0x8B,0xC5,0x6E,0x5A,0x95, - 0x18,0x2A,0xDE,0xA7,0xF1,0x1F,0x75,0x1A,0x27,0xAB,0x6D,0x32,0x53,0xE3,0xFB,0x4D, - 0x58,0x62,0x2C,0xFF,0x19,0xE5,0xC7,0xA0,0x0D,0x9A,0x2D,0x21,0x88,0x59,0x84,0xCD, - 0x1D,0xF1,0xC3,0xC8,0x8A,0x3E,0xB0,0xE5,0xDE,0x08,0x24,0xCF,0xFC,0x40,0x2C,0xBA, - 0x41,0x23,0x94,0xBB,0x80,0x12,0x89,0x35,0x48,0xB6,0x86,0x04,0xE0,0x01,0x4F,0x8C, - 0xBA,0xA9,0x98,0xFC,0x1C,0x89,0xED,0x1F,0x8A,0xA1,0xC7,0x86,0x98,0x26,0x1E,0x72, - 0x65,0x6B,0xFE,0xCF,0x65,0xD9,0x0C,0x64,0x4B,0x1A,0x09,0xF5,0x43,0x11,0x60,0x66, - 0x26,0xE3,0x33,0x56,0x9A,0xC9,0x3D,0x3E,0x34,0x6A,0x78,0xC6,0xE5,0x50,0x4B,0xC8, - 0xCD,0x88,0xE4,0x39,0x6C,0x50,0x26,0x9E,0x40,0x2C,0xB6,0x3B,0x7C,0x37,0xB2,0xA7, - 0xF5,0xDD,0xDC,0xB3,0x51,0xCB,0xF4,0xDC,0x82,0x02,0xB8,0xD7,0x3A,0xDE,0xDA,0x30, - 0x5C,0x0D,0xF5,0x42,0xDD,0x13,0x69,0x53,0x54,0xE9,0x80,0x26,0x42,0x33,0x1E,0xA5, - 0xD7,0xCC,0x6E,0xCA,0x66,0x09,0x9F,0x86,0xF0,0x3D,0xBE,0xC6,0x8A,0x61,0x10,0xF3, - 0xD1,0xFF,0x5B,0xE4,0xB2,0xDB,0x2D,0xB2,0x65,0x0C,0xA9,0x7D,0x17,0xAC,0xBA,0x27, - 0x4D,0x42,0x5C,0xCE,0x09,0x4F,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x02,0x59,0x30, - 0x82,0x02,0x55,0x30,0x81,0x9A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, - 0x04,0x81,0x8D,0x30,0x81,0x8A,0x30,0x52,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x30,0x02,0x86,0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74, - 0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x65, - 0x72,0x74,0x73,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x2F,0x63,0x61,0x63,0x65,0x72, - 0x74,0x73,0x2F,0x74,0x63,0x5F,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x5F, - 0x72,0x6F,0x6F,0x74,0x5F,0x49,0x2E,0x63,0x72,0x74,0x30,0x34,0x06,0x08,0x2B,0x06, - 0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x28,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F, - 0x63,0x73,0x70,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x2D, - 0x49,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65, - 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x92,0xA4,0x75, - 0x2C,0xA4,0x9E,0xBE,0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75, - 0x73,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01, - 0x01,0xFF,0x02,0x01,0x00,0x30,0x52,0x06,0x03,0x55,0x1D,0x20,0x04,0x4B,0x30,0x49, - 0x30,0x06,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x3F,0x06,0x09,0x2A,0x82,0x14,0x00, - 0x2C,0x01,0x01,0x01,0x01,0x30,0x32,0x30,0x30,0x06,0x08,0x2B,0x06,0x01,0x05,0x05, - 0x07,0x02,0x01,0x16,0x24,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E, - 0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x67, - 0x75,0x69,0x64,0x65,0x6C,0x69,0x6E,0x65,0x73,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, - 0x04,0x16,0x04,0x14,0xE9,0xB8,0x28,0x1D,0x46,0xCF,0xFC,0xCD,0xF8,0x4E,0x9B,0xC5, - 0xEE,0x4B,0x60,0xEB,0xD8,0x3B,0x3F,0xD1,0x30,0x81,0xFD,0x06,0x03,0x55,0x1D,0x1F, - 0x04,0x81,0xF5,0x30,0x81,0xF2,0x30,0x81,0xEF,0xA0,0x81,0xEC,0xA0,0x81,0xE9,0x86, - 0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x74,0x63,0x75,0x6E, - 0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x2D,0x49,0x2E,0x74,0x72,0x75,0x73,0x74,0x63, - 0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x72,0x6C,0x2F,0x76,0x32,0x2F, - 0x74,0x63,0x5F,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x5F,0x72,0x6F,0x6F, - 0x74,0x5F,0x49,0x2E,0x63,0x72,0x6C,0x86,0x81,0x9E,0x6C,0x64,0x61,0x70,0x3A,0x2F, - 0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72, - 0x2E,0x64,0x65,0x2F,0x43,0x4E,0x3D,0x54,0x43,0x25,0x32,0x30,0x54,0x72,0x75,0x73, - 0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x25,0x32,0x30,0x55,0x6E,0x69,0x76,0x65,0x72, - 0x73,0x61,0x6C,0x25,0x32,0x30,0x43,0x41,0x25,0x32,0x30,0x49,0x2C,0x4F,0x3D,0x54, - 0x43,0x25,0x32,0x30,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x25, - 0x32,0x30,0x47,0x6D,0x62,0x48,0x2C,0x4F,0x55,0x3D,0x72,0x6F,0x6F,0x74,0x63,0x65, - 0x72,0x74,0x73,0x2C,0x44,0x43,0x3D,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2C,0x44,0x43,0x3D,0x64,0x65,0x3F,0x63,0x65,0x72,0x74,0x69,0x66,0x69, - 0x63,0x61,0x74,0x65,0x52,0x65,0x76,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x4C,0x69, - 0x73,0x74,0x3F,0x62,0x61,0x73,0x65,0x3F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x39,0xC8,0xC4,0x9B, - 0xEE,0xBE,0x98,0xEE,0x48,0x72,0x6F,0x8D,0xE7,0x71,0xB6,0x0E,0x90,0x8C,0xD3,0xB2, - 0xC1,0x15,0x21,0xA8,0x46,0x90,0x68,0x5F,0x4A,0x04,0xF1,0x3A,0xC9,0x68,0x84,0x21, - 0xD8,0xA5,0xE6,0x04,0x75,0x5D,0x9F,0xD2,0xD4,0xF2,0x4B,0x77,0x43,0x32,0xDC,0x95, - 0xCB,0x60,0xBF,0x02,0x55,0xD0,0xAC,0x1C,0xB0,0xC5,0x14,0x97,0x9B,0x65,0x0A,0xC3, - 0x0F,0xA5,0x1D,0xEC,0xD8,0x49,0x39,0x95,0xB5,0xA9,0xBE,0xFA,0xF4,0x1E,0xAB,0x56, - 0xE7,0xA6,0xE5,0x01,0x08,0x88,0x35,0x5F,0x67,0x05,0xDD,0x44,0x24,0x50,0x12,0x22, - 0x44,0x63,0x79,0xF1,0x9B,0x57,0x69,0xCE,0xAB,0xD6,0x33,0x51,0x4F,0x8D,0xF0,0x70, - 0x3B,0x8E,0xAD,0x51,0x3A,0x17,0x7F,0x35,0x96,0x6B,0x68,0x68,0x63,0xB6,0x1C,0x0A, - 0xC9,0xF8,0xDF,0x1D,0x5E,0xCF,0x2B,0x11,0xA5,0x63,0xED,0xCC,0xD0,0xC6,0xD3,0x20, - 0x6F,0xAA,0xFC,0x68,0x48,0x7E,0x6D,0x1E,0xB8,0x3A,0x45,0xAA,0x12,0x86,0xF3,0xC7, - 0xBD,0x00,0xB5,0xEB,0xFE,0xEA,0x12,0x9F,0x73,0x33,0x78,0xE7,0x28,0x39,0x68,0xD3, - 0xA5,0x6D,0xDA,0x76,0xD1,0x4E,0xE1,0x55,0x95,0x80,0xA6,0xE0,0x1B,0xB8,0xCD,0xAC, - 0x56,0xEF,0x45,0x59,0x47,0x98,0x52,0xDB,0x3A,0x6E,0x26,0xB2,0x31,0x39,0x69,0x75, - 0xB1,0x2E,0x24,0xF0,0xA4,0x9D,0x97,0x88,0x5E,0x33,0x29,0xC6,0xB5,0xBC,0x07,0x40, - 0x3A,0x0C,0x3D,0xBA,0xCF,0x74,0x8C,0x4B,0x4E,0x7A,0x21,0xFA,0x1B,0x38,0xCD,0xC4, - 0x43,0x2F,0x6F,0xB4,0xDF,0x78,0xEE,0x99,0x92,0xE7,0x3A,0x1C, -}; - -unsigned char smime_root_certificate[993]={ - 0x30,0x82,0x03,0xDD,0x30,0x82,0x02,0xC5,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x1D, - 0xA2,0x00,0x01,0x00,0x02,0xEC,0xB7,0x60,0x80,0x78,0x8D,0xB6,0x06,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x79,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, - 0x6E,0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x1B,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74, - 0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31, - 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75, - 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73, - 0x61,0x6C,0x20,0x43,0x41,0x20,0x49,0x30,0x1E,0x17,0x0D,0x30,0x36,0x30,0x33,0x32, - 0x32,0x31,0x35,0x35,0x34,0x32,0x38,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x33,0x31, - 0x32,0x32,0x35,0x39,0x35,0x39,0x5A,0x30,0x79,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20, - 0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x0B,0x13,0x1B,0x54, - 0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E, - 0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03, - 0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E, - 0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41, - 0x20,0x49,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82, - 0x01,0x01,0x00,0xA4,0x77,0x23,0x96,0x44,0xAF,0x90,0xF4,0x31,0xA7,0x10,0xF4,0x26, - 0x87,0x9C,0xF3,0x38,0xD9,0x0F,0x5E,0xDE,0xCF,0x41,0xE8,0x31,0xAD,0xC6,0x74,0x91, - 0x24,0x96,0x78,0x1E,0x09,0xA0,0x9B,0x9A,0x95,0x4A,0x4A,0xF5,0x62,0x7C,0x02,0xA8, - 0xCA,0xAC,0xFB,0x5A,0x04,0x76,0x39,0xDE,0x5F,0xF1,0xF9,0xB3,0xBF,0xF3,0x03,0x58, - 0x55,0xD2,0xAA,0xB7,0xE3,0x04,0x22,0xD1,0xF8,0x94,0xDA,0x22,0x08,0x00,0x8D,0xD3, - 0x7C,0x26,0x5D,0xCC,0x77,0x79,0xE7,0x2C,0x78,0x39,0xA8,0x26,0x73,0x0E,0xA2,0x5D, - 0x25,0x69,0x85,0x4F,0x55,0x0E,0x9A,0xEF,0xC6,0xB9,0x44,0xE1,0x57,0x3D,0xDF,0x1F, - 0x54,0x22,0xE5,0x6F,0x65,0xAA,0x33,0x84,0x3A,0xF3,0xCE,0x7A,0xBE,0x55,0x97,0xAE, - 0x8D,0x12,0x0F,0x14,0x33,0xE2,0x50,0x70,0xC3,0x49,0x87,0x13,0xBC,0x51,0xDE,0xD7, - 0x98,0x12,0x5A,0xEF,0x3A,0x83,0x33,0x92,0x06,0x75,0x8B,0x92,0x7C,0x12,0x68,0x7B, - 0x70,0x6A,0x0F,0xB5,0x9B,0xB6,0x77,0x5B,0x48,0x59,0x9D,0xE4,0xEF,0x5A,0xAD,0xF3, - 0xC1,0x9E,0xD4,0xD7,0x45,0x4E,0xCA,0x56,0x34,0x21,0xBC,0x3E,0x17,0x5B,0x6F,0x77, - 0x0C,0x48,0x01,0x43,0x29,0xB0,0xDD,0x3F,0x96,0x6E,0xE6,0x95,0xAA,0x0C,0xC0,0x20, - 0xB6,0xFD,0x3E,0x36,0x27,0x9C,0xE3,0x5C,0xCF,0x4E,0x81,0xDC,0x19,0xBB,0x91,0x90, - 0x7D,0xEC,0xE6,0x97,0x04,0x1E,0x93,0xCC,0x22,0x49,0xD7,0x97,0x86,0xB6,0x13,0x0A, - 0x3C,0x43,0x23,0x77,0x7E,0xF0,0xDC,0xE6,0xCD,0x24,0x1F,0x3B,0x83,0x9B,0x34,0x3A, - 0x83,0x34,0xE3,0x02,0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x1F,0x06,0x03, - 0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x92,0xA4,0x75,0x2C,0xA4,0x9E,0xBE, - 0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75,0x73,0x30,0x0F,0x06, - 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E, - 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x1D, - 0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x92,0xA4,0x75,0x2C,0xA4,0x9E,0xBE, - 0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75,0x73,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01, - 0x00,0x28,0xD2,0xE0,0x86,0xD5,0xE6,0xF8,0x7B,0xF0,0x97,0xDC,0x22,0x6B,0x3B,0x95, - 0x14,0x56,0x0F,0x11,0x30,0xA5,0x9A,0x4F,0x3A,0xB0,0x3A,0xE0,0x06,0xCB,0x65,0xF5, - 0xED,0xC6,0x97,0x27,0xFE,0x25,0xF2,0x57,0xE6,0x5E,0x95,0x8C,0x3E,0x64,0x60,0x15, - 0x5A,0x7F,0x2F,0x0D,0x01,0xC5,0xB1,0x60,0xFD,0x45,0x35,0xCF,0xF0,0xB2,0xBF,0x06, - 0xD9,0xEF,0x5A,0xBE,0xB3,0x62,0x21,0xB4,0xD7,0xAB,0x35,0x7C,0x53,0x3E,0xA6,0x27, - 0xF1,0xA1,0x2D,0xDA,0x1A,0x23,0x9D,0xCC,0xDD,0xEC,0x3C,0x2D,0x9E,0x27,0x34,0x5D, - 0x0F,0xC2,0x36,0x79,0xBC,0xC9,0x4A,0x62,0x2D,0xED,0x6B,0xD9,0x7D,0x41,0x43,0x7C, - 0xB6,0xAA,0xCA,0xED,0x61,0xB1,0x37,0x82,0x15,0x09,0x1A,0x8A,0x16,0x30,0xD8,0xEC, - 0xC9,0xD6,0x47,0x72,0x78,0x4B,0x10,0x46,0x14,0x8E,0x5F,0x0E,0xAF,0xEC,0xC7,0x2F, - 0xAB,0x10,0xD7,0xB6,0xF1,0x6E,0xEC,0x86,0xB2,0xC2,0xE8,0x0D,0x92,0x73,0xDC,0xA2, - 0xF4,0x0F,0x3A,0xBF,0x61,0x23,0x10,0x89,0x9C,0x48,0x40,0x6E,0x70,0x00,0xB3,0xD3, - 0xBA,0x37,0x44,0x58,0x11,0x7A,0x02,0x6A,0x88,0xF0,0x37,0x34,0xF0,0x19,0xE9,0xAC, - 0xD4,0x65,0x73,0xF6,0x69,0x8C,0x64,0x94,0x3A,0x79,0x85,0x29,0xB0,0x16,0x2B,0x0C, - 0x82,0x3F,0x06,0x9C,0xC7,0xFD,0x10,0x2B,0x9E,0x0F,0x2C,0xB6,0x9E,0xE3,0x15,0xBF, - 0xD9,0x36,0x1C,0xBA,0x25,0x1A,0x52,0x3D,0x1A,0xEC,0x22,0x0C,0x1C,0xE0,0xA4,0xA2, - 0x3D,0xF0,0xE8,0x39,0xCF,0x81,0xC0,0x7B,0xED,0x5D,0x1F,0x6F,0xC5,0xD0,0x0B,0xD7, - 0x98, -}; - -/* - * Note: this test requires Network connectivity! - */ - -static void tests(void) -{ - SecCertificateRef leaf_cert; - SecCertificateRef CA_cert; - - // Import certificates from byte array above - isnt(leaf_cert = SecCertificateCreateWithBytes(NULL, leaf_certificate, sizeof(leaf_certificate)), - NULL, "Leaf Cert"); - isnt(CA_cert = SecCertificateCreateWithBytes(NULL, CA_certificate, sizeof(CA_certificate)), - NULL, "CA Cert"); - - /* - * 1) Test explicit revocation with no OCSP/CRL - */ - - OSStatus status; - SecPolicyRef policy_ssl_default = SecPolicyCreateSSL(true, CFSTR("www.paypal.com")); - SecPolicyRef policy_revoc_disabled = SecPolicyCreateRevocation(kSecRevocationNetworkAccessDisabled); - - // Default Policies - CFMutableArrayRef DefaultSSLPolicy = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(DefaultSSLPolicy, policy_ssl_default); - - // Default Policies + explicit revocation disabled - CFMutableArrayRef DefaultSSLPolicyWithNoRevocation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(DefaultSSLPolicyWithNoRevocation, policy_ssl_default); - CFArrayAppendValue(DefaultSSLPolicyWithNoRevocation, policy_revoc_disabled); - - // Valid chain of Cert (leaf + CA) - CFMutableArrayRef CertFullChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(CertFullChain, leaf_cert); - CFArrayAppendValue(CertFullChain, CA_cert); - - // Chain of cert minus the issuer - CFMutableArrayRef CertMissingIssuer = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(CertMissingIssuer, leaf_cert); - - // Free Resources since all are in arrays - CFReleaseSafe(leaf_cert); - CFReleaseSafe(CA_cert); - CFReleaseSafe(policy_ssl_default); - CFReleaseSafe(policy_revoc_disabled); - - // a) First evaluate an entire EV certificate chain with default policy - // OCSP/CRL performed (online/from cache) - - // Array of policy to add explicit revocation policy - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - // Proceed to trust evaluation in two steps - ok_status(status = SecTrustCreateWithCertificates(CertFullChain, DefaultSSLPolicy, &trust), - "SecTrustCreateWithCertificates"); - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); - CFDictionaryRef TrustResultsDict = SecTrustCopyResult(trust); - CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(TrustResultsDict, - kSecTrustExtendedValidation); - ok(ev && CFEqual(kCFBooleanTrue, ev), "extended validation succeeded"); - - CFReleaseNull(TrustResultsDict); - CFReleaseNull(trust); - } - - // b) Set explicit revocation policy to disable revocation checking, - // and now expect EV marker to be dropped. - // Network packet logging can be used to confirm no OCSP/CRL message is sent. - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - // Proceed to trust evaluation in two steps - ok_status(status = SecTrustCreateWithCertificates(CertFullChain, DefaultSSLPolicyWithNoRevocation, &trust), - "SecTrustCreateWithCertificates"); - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); - CFDictionaryRef TrustResultsDict = SecTrustCopyResult(trust); - CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(TrustResultsDict, - kSecTrustExtendedValidation); - // With SecTrust Unification, the OCSP response is cached by the previous evaluation. - // FIXME The semantics of the input to SecPolicyCreateRevocation are technically not honored, - // since if neither the OCSP or CRL bits are set, we should not be using either. Unfortunately, - // the iOS implementation treats this as a no-op, which for EV certs means an OCSP check by default. - - ok(ev && CFEqual(kCFBooleanTrue, ev), "Expect success even if unable to use network, due to caching"); - - CFReleaseNull(TrustResultsDict); - CFReleaseNull(trust); - } - - /* - * 2) Test retrieving of issuer being blocked - */ - - // a) Evaluate leaf EV certificate and expect success (issuer retrieved online) - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - // Proceed to trust evaluation in two steps - ok_status(status = SecTrustCreateWithCertificates(CertMissingIssuer, DefaultSSLPolicy, &trust), - "SecTrustCreateWithCertificates"); - ok_status(status = SecTrustSetNetworkFetchAllowed(trust,true), "SecTrustSetNetworkFetchAllowed"); - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); - CFDictionaryRef TrustResultsDict = SecTrustCopyResult(trust); - CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(TrustResultsDict, - kSecTrustExtendedValidation); - ok(ev && CFEqual(kCFBooleanTrue, ev), "extended validation succeeded"); - - CFReleaseNull(TrustResultsDict); - CFReleaseNull(trust); - } - - // b) Set SecTrustSetNetworkFetchAllowed to false which should prevent issuer cert to be fetched - // and therefore cause evaluation failure. - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - // Proceed to trust evaluation in two steps, forcing no network allowed - ok_status(status = SecTrustCreateWithCertificates(CertMissingIssuer, DefaultSSLPolicy, &trust), - "SecTrustCreateWithCertificates"); - ok_status(status = SecTrustSetNetworkFetchAllowed(trust,false), "SecTrustSetNetworkFetchAllowed"); - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - // with SecTrust Unification, the issuing cert may or may not be cached from the previous test - if (trust_result == kSecTrustResultUnspecified) - trust_result = kSecTrustResultRecoverableTrustFailure; - is_status(trust_result, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); - - CFReleaseNull(trust); - } - - /* - * 3) Test verification requiring a positive response from the revocation server - */ - - SecCertificateRef smime_leaf_cert; - SecCertificateRef smime_CA_cert; - SecCertificateRef smime_root_cert; - - // Import certificates from byte array above - isnt(smime_leaf_cert = SecCertificateCreateWithBytes(NULL, smime_leaf_certificate, sizeof(smime_leaf_certificate)), - NULL, "SMIME Leaf Cert"); - isnt(smime_CA_cert = SecCertificateCreateWithBytes(NULL, smime_CA_certificate, sizeof(smime_CA_certificate)), - NULL, "SMIME CA Cert"); - isnt(smime_root_cert = SecCertificateCreateWithBytes(NULL, smime_root_certificate, sizeof(smime_root_certificate)), - NULL, "SMIME Root Cert"); - - SecPolicyRef smimePolicy = SecPolicyCreateWithProperties(kSecPolicyAppleSMIME, NULL); - SecPolicyRef revocPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod | kSecRevocationRequirePositiveResponse); - isnt(smimePolicy, NULL, "SMIME Policy"); - isnt(revocPolicy, NULL, "SMIME Revocation Policy"); - - // Default Policies - CFMutableArrayRef SMIMEDefaultPolicy = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMEDefaultPolicy, smimePolicy); - - // Default Policies + explicit revocation - CFMutableArrayRef SMIMEDefaultPolicyWithRevocation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, smimePolicy); - CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, revocPolicy); - - // Valid chain of Cert (leaf + CA) - CFMutableArrayRef SMIMECertChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMECertChain, smime_leaf_cert); - CFArrayAppendValue(SMIMECertChain, smime_CA_cert); - - // Valid anchor certs - CFMutableArrayRef SMIMEAnchors = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMEAnchors, smime_root_cert); - - // Free Resources contained in arrays - CFReleaseSafe(smime_leaf_cert); - CFReleaseSafe(smime_CA_cert); - CFReleaseSafe(smime_root_cert); - CFReleaseSafe(smimePolicy); - CFReleaseSafe(revocPolicy); - - CFDateRef VerifyDate; - isnt(VerifyDate = CFDateCreate(NULL, 332900000.0), NULL, "Create verify date"); - - // Standard evaluation for the given verify date - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - ok_status(status = SecTrustCreateWithCertificates(SMIMECertChain, SMIMEDefaultPolicy, &trust), - "SecTrustCreateWithCertificates"); - ok_status(SecTrustSetVerifyDate(trust, VerifyDate), "Set date"); - ok_status(SecTrustSetAnchorCertificates(trust, SMIMEAnchors), "Set anchors"); - - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - // %%% This is expected to fail, since the "TC TrustCenter Class 1 L1 CA IX" CA is revoked. - // While it is still present in the CRL, we no longer check revocation for it because the root - // "TC TrustCenter Universal CA I" is not system-trusted. Accept either failure mode here. - ok((trust_result == kSecTrustResultRecoverableTrustFailure) || - (trust_result == kSecTrustResultFatalTrustFailure), "trust result failure"); - - CFReleaseNull(trust); - } - - // Revocation-required evaluation should fail, since this CA's servers no longer exist - // and no valid responses are available - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - ok_status(status = SecTrustCreateWithCertificates(SMIMECertChain, SMIMEDefaultPolicyWithRevocation, &trust), - "SecTrustCreateWithCertificates"); - ok_status(SecTrustSetVerifyDate(trust, VerifyDate), "Set date"); - ok_status(SecTrustSetAnchorCertificates(trust, SMIMEAnchors), "Set anchors"); - - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - // %%% This is expected to fail, since the "TC TrustCenter Class 1 L1 CA IX" CA is revoked. - // While it is still present in the CRL, we no longer check revocation for it because the root - // "TC TrustCenter Universal CA I" is not system-trusted. Accept either failure mode here. - ok((trust_result == kSecTrustResultRecoverableTrustFailure) || - (trust_result == kSecTrustResultFatalTrustFailure), "trust result failure"); - - CFReleaseNull(trust); - } - - // Free remaining resources - CFReleaseSafe(DefaultSSLPolicy); - CFReleaseSafe(DefaultSSLPolicyWithNoRevocation); - CFReleaseSafe(CertFullChain); - CFReleaseSafe(CertMissingIssuer); - - CFReleaseSafe(VerifyDate); - CFReleaseSafe(SMIMEDefaultPolicy); - CFReleaseSafe(SMIMEDefaultPolicyWithRevocation); - CFReleaseSafe(SMIMECertChain); - CFReleaseSafe(SMIMEAnchors); -} - -int kc_42_trust_revocation(int argc, char *const *argv) -{ - plan_tests(35); - tests(); - - return 0; -} - - diff --git a/OSX/libsecurity_keychain/regressions/kc-key-helpers.h b/OSX/libsecurity_keychain/regressions/kc-key-helpers.h index a3508aa5..8cc1201a 100644 --- a/OSX/libsecurity_keychain/regressions/kc-key-helpers.h +++ b/OSX/libsecurity_keychain/regressions/kc-key-helpers.h @@ -227,16 +227,19 @@ static void checkKeyUse(SecKeyRef key, OSStatus expectedStatus) { CFErrorRef error = NULL; CFDataRef ciphertextData = SecTransformExecute(transform, &error); + CFDataRef roundtripData = NULL; if(error) { - is(CFErrorGetCode(error), expectedStatus, "%s: Encrypting data failed: %d %s (and expected %d)", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(CFErrorCopyDescription(error), kCFStringEncodingUTF8), (int) expectedStatus); + CFStringRef errorStr = CFErrorCopyDescription(error); + is(CFErrorGetCode(error), expectedStatus, "%s: Encrypting data failed: %d %s (and expected %d)", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(errorStr, kCFStringEncodingUTF8), (int) expectedStatus); + CFReleaseSafe(errorStr); if(expectedStatus != errSecSuccess) { // make test numbers match and quit for(int i = 1; i < checkKeyUseTests; i++) { pass("test numbers match"); } - return; + goto cleanup; } } else { @@ -251,21 +254,21 @@ static void checkKeyUse(SecKeyRef key, OSStatus expectedStatus) { SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, NULL); SecTransformSetAttribute(transform, kSecTransformInputAttributeName, ciphertextData, NULL); - CFDataRef roundtripData = SecTransformExecute(transform, &error); + roundtripData = SecTransformExecute(transform, &error); is(error, NULL, "%s: checkKeyUse: SecTransformExecute (decrypt)", testName); if(error) { CFStringRef errorStr = CFErrorCopyDescription(error); fail("%s: Decrypting data failed: %d %s", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(errorStr, kCFStringEncodingUTF8)); - CFRelease(errorStr); + CFReleaseSafe(errorStr); } else { pass("%s: make test numbers match", testName); } - CFReleaseSafe(transform); - eq_cf(plaintextData, roundtripData, "%s: checkKeyUse: roundtripped data is input data", testName); + cleanup: + CFReleaseSafe(transform); CFReleaseSafe(plaintext); CFReleaseSafe(plaintextData); CFReleaseSafe(ciphertextData); diff --git a/OSX/libsecurity_keychain/regressions/keychain_regressions.h b/OSX/libsecurity_keychain/regressions/keychain_regressions.h index 7599d26c..9fe6589a 100644 --- a/OSX/libsecurity_keychain/regressions/keychain_regressions.h +++ b/OSX/libsecurity_keychain/regressions/keychain_regressions.h @@ -41,10 +41,10 @@ ONE_TEST(kc_28_cert_sign) ONE_TEST(kc_30_xara) ONE_TEST(kc_40_seckey) ONE_TEST(kc_41_sececkey) -ONE_TEST(kc_42_trust_revocation) ONE_TEST(kc_43_seckey_interop) ONE_TEST(kc_44_secrecoverypassword) ONE_TEST(kc_45_change_password) -ONE_TEST(si_20_sectrust_provisioning) +ONE_TEST(si_20_certificate_copy_values) ONE_TEST(si_33_keychain_backup) ONE_TEST(si_34_one_true_keychain) +ONE_TEST(si_40_identity_tests) diff --git a/OSX/libsecurity_keychain/regressions/si-20-sectrust-provisioning.c b/OSX/libsecurity_keychain/regressions/si-20-certificate-copy-values.c similarity index 64% rename from OSX/libsecurity_keychain/regressions/si-20-sectrust-provisioning.c rename to OSX/libsecurity_keychain/regressions/si-20-certificate-copy-values.c index 3793fa6f..6f65d926 100644 --- a/OSX/libsecurity_keychain/regressions/si-20-sectrust-provisioning.c +++ b/OSX/libsecurity_keychain/regressions/si-20-certificate-copy-values.c @@ -31,8 +31,6 @@ #include "utilities/SecCFRelease.h" #include "utilities/SecCFWrappers.h" -#include "si-20-sectrust-provisioning.h" - /* SHA1 Fingerprint=45:27:70:FE:5F:E9:C2:DD:F9:77:17:29:F7:2B:71:DC:23:37:D1:1B */ /* subject:/CN=Mac OS X Provisioning Profile Signing/O=Apple Inc./C=US */ /* issuer :/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority */ @@ -124,81 +122,6 @@ static unsigned char c0[1334]={ 0xDA,0xA6,0xD7,0x89,0x1B,0xAF, }; -/* SHA1 Fingerprint=09:50:B6:CD:3D:2F:37:EA:24:6A:1A:AA:20:DF:AA:DB:D6:FE:1F:75 */ -/* subject:/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority */ -/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA */ - -static unsigned char c1[1063]={ - 0x30,0x82,0x04,0x23,0x30,0x82,0x03,0x0B,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x19, - 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30, - 0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70, - 0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, - 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06, - 0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74, - 0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x38,0x30,0x32,0x31,0x34,0x31,0x38,0x35, - 0x36,0x33,0x35,0x5A,0x17,0x0D,0x31,0x36,0x30,0x32,0x31,0x34,0x31,0x38,0x35,0x36, - 0x33,0x35,0x5A,0x30,0x81,0x96,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, - 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, - 0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04, - 0x0B,0x0C,0x23,0x41,0x70,0x70,0x6C,0x65,0x20,0x57,0x6F,0x72,0x6C,0x64,0x77,0x69, - 0x64,0x65,0x20,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x20,0x52,0x65,0x6C, - 0x61,0x74,0x69,0x6F,0x6E,0x73,0x31,0x44,0x30,0x42,0x06,0x03,0x55,0x04,0x03,0x0C, - 0x3B,0x41,0x70,0x70,0x6C,0x65,0x20,0x57,0x6F,0x72,0x6C,0x64,0x77,0x69,0x64,0x65, - 0x20,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x20,0x52,0x65,0x6C,0x61,0x74, - 0x69,0x6F,0x6E,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, - 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x82,0x01,0x22, - 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03, - 0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xCA,0x38,0x54, - 0xA6,0xCB,0x56,0xAA,0xC8,0x24,0x39,0x48,0xE9,0x8C,0xEE,0xEC,0x5F,0xB8,0x7F,0x26, - 0x91,0xBC,0x34,0x53,0x7A,0xCE,0x7C,0x63,0x80,0x61,0x77,0x64,0x5E,0xA5,0x07,0x23, - 0xB6,0x39,0xFE,0x50,0x2D,0x15,0x56,0x58,0x70,0x2D,0x7E,0xC4,0x6E,0xC1,0x4A,0x85, - 0x3E,0x2F,0xF0,0xDE,0x84,0x1A,0xA1,0x57,0xC9,0xAF,0x7B,0x18,0xFF,0x6A,0xFA,0x15, - 0x12,0x49,0x15,0x08,0x19,0xAC,0xAA,0xDB,0x2A,0x32,0xED,0x96,0x63,0x68,0x52,0x15, - 0x3D,0x8C,0x8A,0xEC,0xBF,0x6B,0x18,0x95,0xE0,0x03,0xAC,0x01,0x7D,0x97,0x05,0x67, - 0xCE,0x0E,0x85,0x95,0x37,0x6A,0xED,0x09,0xB6,0xAE,0x67,0xCD,0x51,0x64,0x9F,0xC6, - 0x5C,0xD1,0xBC,0x57,0x6E,0x67,0x35,0x80,0x76,0x36,0xA4,0x87,0x81,0x6E,0x38,0x8F, - 0xD8,0x2B,0x15,0x4E,0x7B,0x25,0xD8,0x5A,0xBF,0x4E,0x83,0xC1,0x8D,0xD2,0x93,0xD5, - 0x1A,0x71,0xB5,0x60,0x9C,0x9D,0x33,0x4E,0x55,0xF9,0x12,0x58,0x0C,0x86,0xB8,0x16, - 0x0D,0xC1,0xE5,0x77,0x45,0x8D,0x50,0x48,0xBA,0x2B,0x2D,0xE4,0x94,0x85,0xE1,0xE8, - 0xC4,0x9D,0xC6,0x68,0xA5,0xB0,0xA3,0xFC,0x67,0x7E,0x70,0xBA,0x02,0x59,0x4B,0x77, - 0x42,0x91,0x39,0xB9,0xF5,0xCD,0xE1,0x4C,0xEF,0xC0,0x3B,0x48,0x8C,0xA6,0xE5,0x21, - 0x5D,0xFD,0x6A,0x6A,0xBB,0xA7,0x16,0x35,0x60,0xD2,0xE6,0xAD,0xF3,0x46,0x29,0xC9, - 0xE8,0xC3,0x8B,0xE9,0x79,0xC0,0x6A,0x61,0x67,0x15,0xB2,0xF0,0xFD,0xE5,0x68,0xBC, - 0x62,0x5F,0x6E,0xCF,0x99,0xDD,0xEF,0x1B,0x63,0xFE,0x92,0x65,0xAB,0x02,0x03,0x01, - 0x00,0x01,0xA3,0x81,0xAE,0x30,0x81,0xAB,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, - 0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01, - 0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, - 0x04,0x16,0x04,0x14,0x88,0x27,0x17,0x09,0xA9,0xB6,0x18,0x60,0x8B,0xEC,0xEB,0xBA, - 0xF6,0x47,0x59,0xC5,0x52,0x54,0xA3,0xB7,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04, - 0x18,0x30,0x16,0x80,0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D, - 0x2E,0x40,0xA6,0xF7,0x47,0x4D,0x7F,0x08,0x5E,0x30,0x36,0x06,0x03,0x55,0x1D,0x1F, - 0x04,0x2F,0x30,0x2D,0x30,0x2B,0xA0,0x29,0xA0,0x27,0x86,0x25,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, - 0x2F,0x61,0x70,0x70,0x6C,0x65,0x63,0x61,0x2F,0x72,0x6F,0x6F,0x74,0x2E,0x63,0x72, - 0x6C,0x30,0x10,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x02,0x01,0x04, - 0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, - 0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xDA,0x32,0x00,0x96,0xC5,0x54,0x94,0xD3,0x3B, - 0x82,0x37,0x66,0x7D,0x2E,0x68,0xD5,0xC3,0xC6,0xB8,0xCB,0x26,0x8C,0x48,0x90,0xCF, - 0x13,0x24,0x6A,0x46,0x8E,0x63,0xD4,0xF0,0xD0,0x13,0x06,0xDD,0xD8,0xC4,0xC1,0x37, - 0x15,0xF2,0x33,0x13,0x39,0x26,0x2D,0xCE,0x2E,0x55,0x40,0xE3,0x0B,0x03,0xAF,0xFA, - 0x12,0xC2,0xE7,0x0D,0x21,0xB8,0xD5,0x80,0xCF,0xAC,0x28,0x2F,0xCE,0x2D,0xB3,0x4E, - 0xAF,0x86,0x19,0x04,0xC6,0xE9,0x50,0xDD,0x4C,0x29,0x47,0x10,0x23,0xFC,0x6C,0xBB, - 0x1B,0x98,0x6B,0x48,0x89,0xE1,0x5B,0x9D,0xDE,0x46,0xDB,0x35,0x85,0x35,0xEF,0x3E, - 0xD0,0xE2,0x58,0x4B,0x38,0xF4,0xED,0x75,0x5A,0x1F,0x5C,0x70,0x1D,0x56,0x39,0x12, - 0xE5,0xE1,0x0D,0x11,0xE4,0x89,0x25,0x06,0xBD,0xD5,0xB4,0x15,0x8E,0x5E,0xD0,0x59, - 0x97,0x90,0xE9,0x4B,0x81,0xE2,0xDF,0x18,0xAF,0x44,0x74,0x1E,0x19,0xA0,0x3A,0x47, - 0xCC,0x91,0x1D,0x3A,0xEB,0x23,0x5A,0xFE,0xA5,0x2D,0x97,0xF7,0x7B,0xBB,0xD6,0x87, - 0x46,0x42,0x85,0xEB,0x52,0x3D,0x26,0xB2,0x63,0xA8,0xB4,0xB1,0xCA,0x8F,0xF4,0xCC, - 0xE2,0xB3,0xC8,0x47,0xE0,0xBF,0x9A,0x59,0x83,0xFA,0xDA,0x98,0x53,0x2A,0x82,0xF5, - 0x7C,0x65,0x2E,0x95,0xD9,0x33,0x5D,0xF5,0xED,0x65,0xCC,0x31,0x37,0xC5,0x5A,0x04, - 0xE8,0x6B,0xE1,0xE7,0x88,0x03,0x4A,0x75,0x9E,0x9B,0x28,0xCB,0x4A,0x40,0x88,0x65, - 0x43,0x75,0xDD,0xCB,0x3A,0x25,0x23,0xC5,0x9E,0x57,0xF8,0x2E,0xCE,0xD2,0xA9,0x92, - 0x5E,0x73,0x2E,0x2F,0x25,0x75,0x15, -}; - - static CFStringRef copyIssuerCN(SecCertificateRef certificate) { if (!certificate || @@ -359,62 +282,18 @@ finish: static void tests(void) { - SecTrustRef trust = NULL; - SecPolicyRef policy = NULL; - SecCertificateRef cert0, cert1; - SecTrustResultType trustResult; + SecCertificateRef cert0; isnt(cert0 = SecCertificateCreateWithBytes(NULL, c0, sizeof(c0)), NULL, "create cert0"); - isnt(cert1 = SecCertificateCreateWithBytes(NULL, c1, sizeof(c1)), NULL, "create cert1"); - const void *v_certs[] = { cert0, cert1 }; - CFArrayRef certs = CFArrayCreate(NULL, v_certs, sizeof(v_certs)/sizeof(*v_certs), &kCFTypeArrayCallBacks); - - /* Create Mac Provisioning Profile policy instance. */ - isnt(policy = SecPolicyCreateOSXProvisioningProfileSigning(), NULL, "create policy"); - - /* Create trust reference. */ - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); - - /* Set explicit verify date: Sep 1 2015. */ - CFDateRef date = NULL; - isnt(date = CFDateCreate(NULL, 462823871.0), NULL, "Create verify date"); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, "trustResult is kSecTrustResultUnspecified"); - is(SecTrustGetCertificateCount(trust), 3, "cert count is 3"); - - /* Verify signed content with this policy. */ - CMSDecoderRef decoder = NULL; - CMSSignerStatus signerStatus = kCMSSignerInvalidIndex; - OSStatus verifyResult = 0; - ok_status(CMSDecoderCreate(&decoder), - "create decoder"); - ok_status(CMSDecoderUpdateMessage(decoder, _TestProvisioningProfile, sizeof(_TestProvisioningProfile)), - "update message"); - ok_status(CMSDecoderFinalizeMessage(decoder), - "finalize message"); - ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, true, &signerStatus, NULL, &verifyResult), - "copy signer status"); - is(signerStatus, kCMSSignerValid, "signer status valid"); - is(verifyResult, errSecSuccess, "verify result valid"); - - /* Add some basic subject/issuer field value tests */ + /* some basic subject/issuer field value tests */ CertificateValuesTests(cert0); - - CFReleaseSafe(decoder); - CFReleaseSafe(date); - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(certs); - CFReleaseSafe(cert1); CFReleaseSafe(cert0); } -int si_20_sectrust_provisioning(int argc, char *const *argv); +int si_20_certificate_copy_values(int argc, char *const *argv); -int si_20_sectrust_provisioning(int argc, char *const *argv) +int si_20_certificate_copy_values(int argc, char *const *argv) { plan_tests(17); diff --git a/OSX/libsecurity_keychain/regressions/si-40-identity-tests.m b/OSX/libsecurity_keychain/regressions/si-40-identity-tests.m new file mode 100644 index 00000000..cbbb6cee --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/si-40-identity-tests.m @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "keychain_regressions.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include "OSX/utilities/SecCFWrappers.h" +#include "OSX/sec/Security/SecFramework.h" + +#include "si-40-identity-tests_data.h" + +/* entry point prototype */ +int si_40_identity_tests(int argc, char *const *argv); + +static void tests() { + OSStatus status = 0; + CFDataRef p12Blob = NULL; + isnt(p12Blob = (__bridge CFDataRef)[NSData dataWithBytes:test_p12 length:sizeof(test_p12)], NULL, "copy test_p12"); + + CFArrayRef items = NULL; /* return value is retained, must release it */ + SecKeychainRef keychain = NULL; /* return value is retained, must release it */ + status = SecKeychainCopyDefault(&keychain); + is(status, errSecSuccess, "keychain status"); + isnt(keychain, NULL, "no default keychain"); + + CFMutableDictionaryRef options = NULL; /* return value is retained, must release it */ + options = CFDictionaryCreateMutableForCFTypes(NULL); + isnt(options, NULL, "no options dictionary"); + CFDictionaryAddValue(options, kSecImportExportPassphrase, CFSTR("test")); + CFDictionaryAddValue(options, kSecImportExportKeychain, keychain); + + status = SecPKCS12Import(p12Blob, options, &items); + if (status == errSecDuplicateItem) { + status = errSecSuccess; // ok if it already exists + } + is(status, errSecSuccess, "import p12 status"); + isnt(items, NULL, "import p12 items"); + + NSDictionary *itemDict = (__bridge NSDictionary*)CFArrayGetValueAtIndex(items, 0); + SecIdentityRef identity = (__bridge SecIdentityRef)itemDict[(__bridge NSString*)kSecImportItemIdentity]; + isnt(identity, NULL, "import identity"); + + SecIdentityRef foundIdentity = NULL; /* return value is retained, must release it */ + + // PLAIN NAMES: make sure these test cases produce identity preference items + // which are not per-application. + + NSString *plainNameOne = @"Test Identity Preference Item"; + status = SecIdentitySetPreferred(identity, (__bridge CFStringRef)plainNameOne, NULL); + is(status, errSecSuccess, "set preferred identity with plain name containing spaces"); + + NSString *plainNameTwo = @"Test.Identity.Preference.Item"; + status = SecIdentitySetPreferred(identity, (__bridge CFStringRef)plainNameTwo, NULL); + is(status, errSecSuccess, "set preferred identity with plain name containing dots"); + + NSString *plainNameThree = @"@Test.Identity.Preference.Item"; + status = SecIdentitySetPreferred(identity, (__bridge CFStringRef)plainNameThree, NULL); + is(status, errSecSuccess, "set preferred identity with plain name containing at-sign"); + + NSString *plainNameFour = @"TestIdentityPreferenceItem"; + status = SecIdentitySetPreferred(identity, (__bridge CFStringRef)plainNameFour, NULL); + is(status, errSecSuccess, "set preferred identity with plain name containing no spaces"); + + NSString *plainNameFive = @"*.Identity.Preference.Item"; + status = SecIdentitySetPreferred(identity, (__bridge CFStringRef)plainNameFive, NULL); + is(status, errSecSuccess, "set preferred identity with plain name wildcard entry"); + + NSString *plainNameSix = @"si-40-identity-tests@apple.com"; + status = SecIdentitySetPreferred(identity, (__bridge CFStringRef)plainNameSix, NULL); + is(status, errSecSuccess, "set preferred identity with RFC822 email address"); + + status = SecIdentityDeleteApplicationPreferenceItems(); + if (status == errSecItemNotFound) { + // it's ok if there were no per-app items found to delete at this point. + // We are only testing that calling this function does NOT delete any of the + // plain name preferences we created above. + status = errSecSuccess; + } + is(status, errSecSuccess, "per-app preference item deletion failed with unexpected error"); + + // check that the plain name prefs exist and survived the per-app item deletion. + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameOne, NULL, NULL); + isnt(foundIdentity, NULL, "plain name identity preference 1 should not be deleted"); + CFReleaseNull(foundIdentity); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameTwo, NULL, NULL); + isnt(foundIdentity, NULL, "plain name identity preference 2 should not be deleted"); + CFReleaseNull(foundIdentity); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameThree, NULL, NULL); + isnt(foundIdentity, NULL, "plain name identity preference 3 should not be deleted"); + CFReleaseNull(foundIdentity); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameFour, NULL, NULL); + isnt(foundIdentity, NULL, "plain name identity preference 4 should not be deleted"); + CFReleaseNull(foundIdentity); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameFive, NULL, NULL); + isnt(foundIdentity, NULL, "plain name identity preference 5 should not be deleted"); + CFReleaseNull(foundIdentity); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameSix, NULL, NULL); + isnt(foundIdentity, NULL, "plain name identity preference 6 should not be deleted"); + CFReleaseNull(foundIdentity); + + // clear the plain name prefs + status = SecIdentitySetPreferred(NULL, (__bridge CFStringRef)plainNameOne, NULL); + is(status, errSecSuccess, "clear preferred identity with plain name 1"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameOne, NULL, NULL); + is(foundIdentity, NULL, "plain name identity preference 1 found after being cleared"); + CFReleaseNull(foundIdentity); + status = SecIdentitySetPreferred(NULL, (__bridge CFStringRef)plainNameTwo, NULL); + is(status, errSecSuccess, "clear preferred identity with plain name 2"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameTwo, NULL, NULL); + is(foundIdentity, NULL, "plain name identity preference 2 found after being cleared"); + CFReleaseNull(foundIdentity); + status = SecIdentitySetPreferred(NULL, (__bridge CFStringRef)plainNameThree, NULL); + is(status, errSecSuccess, "clear preferred identity with plain name 3"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameThree, NULL, NULL); + is(foundIdentity, NULL, "plain name identity preference 3 found after being cleared"); + CFReleaseNull(foundIdentity); + status = SecIdentitySetPreferred(NULL, (__bridge CFStringRef)plainNameFour, NULL); + is(status, errSecSuccess, "clear preferred identity with plain name 4"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameFour, NULL, NULL); + is(foundIdentity, NULL, "plain name identity preference 4 found after being cleared"); + CFReleaseNull(foundIdentity); + status = SecIdentitySetPreferred(NULL, (__bridge CFStringRef)plainNameFive, NULL); + is(status, errSecSuccess, "clear preferred identity with plain name 5"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameFive, NULL, NULL); + is(foundIdentity, NULL, "plain name identity preference 5 found after being cleared"); + CFReleaseNull(foundIdentity); + status = SecIdentitySetPreferred(NULL, (__bridge CFStringRef)plainNameSix, NULL); + is(status, errSecSuccess, "clear preferred identity with plain name 6"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)plainNameSix, NULL, NULL); + is(foundIdentity, NULL, "plain name identity preference 6 found after being cleared"); + CFReleaseNull(foundIdentity); + + // + // URL NAMES: make sure that these produce per-app preference items. + // + + NSString *uriNameOne = @"https://test-pref.apple.com/"; + status = SecIdentitySetPreferred(identity, (__bridge CFStringRef)uriNameOne, NULL); + is(status, errSecSuccess, "set preferred identity with uri name 1"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)uriNameOne, NULL, NULL); + isnt(foundIdentity, NULL, "preferred identity 1 not found after being set"); + CFReleaseNull(foundIdentity); + + NSString *uriNameTwo = @"ldaps://test-pref.apple.com/cn=si-40-identity-tests"; + status = SecIdentitySetPreferred(identity, (__bridge CFStringRef)uriNameTwo, NULL); + is(status, errSecSuccess, "set preferred identity with uri name 2"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)uriNameTwo, NULL, NULL); + isnt(foundIdentity, NULL, "preferred identity 2 not found after being set"); + CFReleaseNull(foundIdentity); + + // Check that the new API deletes all of our per-app URL preference items. + // We always expect errSecSuccess here, since we know we have items to delete. + status = SecIdentityDeleteApplicationPreferenceItems(); + is(status, errSecSuccess, "should find and delete our app uri preference items"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)uriNameOne, NULL, NULL); + is(foundIdentity, NULL, "preferred identity 1 should not be found after deleting prefs"); + CFReleaseNull(foundIdentity); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)uriNameTwo, NULL, NULL); + is(foundIdentity, NULL, "preferred identity 2 should not be found after deleting prefs"); + CFReleaseNull(foundIdentity); + + // + // WILDCARD NAMES: make sure these are still supported for URL name lookups + // + + // add wildcard entry + NSString *wildcardNameOne = @"*.test-pref-subdomain.apple.com"; + status = SecIdentitySetPreferred(identity, (__bridge CFStringRef)wildcardNameOne, NULL); + is(status, errSecSuccess, "set preferred identity for wildcard name 1"); + // check that preferred identity is found for URI matching this wildcard + NSString *uriWildcardMatchOne = @"https://match.test-pref-subdomain.apple.com"; + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)uriWildcardMatchOne, NULL, NULL); + isnt(foundIdentity, NULL, "preferred identity not found for wildcard match 1"); + CFReleaseNull(foundIdentity); + // clear wildcard entry, then check that match is not found + status = SecIdentitySetPreferred(NULL, (__bridge CFStringRef)wildcardNameOne, NULL); + is(status, errSecSuccess, "clear preferred identity for wildcard name 1"); + foundIdentity = SecIdentityCopyPreferred((__bridge CFStringRef)uriWildcardMatchOne, NULL, NULL); + is(foundIdentity, NULL, "preferred identity found after wildcard name 1 was cleared"); + CFReleaseNull(foundIdentity); + + + CFReleaseNull(options); + CFReleaseNull(items); + CFReleaseNull(keychain); +} + +int si_40_identity_tests(int argc, char *const *argv) +{ + plan_tests(43); + + tests(); + + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/si-40-identity-tests_data.h b/OSX/libsecurity_keychain/regressions/si-40-identity-tests_data.h new file mode 100644 index 00000000..a9b8f546 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/si-40-identity-tests_data.h @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#ifndef _TRUSTTESTS_IDENTITY_INTERFACE_H_ +#define _TRUSTTESTS_IDENTITY_INTERFACE_H_ + +/* MARK: testImportIdentity */ + +static +const uint8_t test_p12[] = { + 0x30, 0x82, 0x0a, 0xb9, 0x02, 0x01, 0x03, 0x30, 0x82, 0x0a, 0x80, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, + 0x0a, 0x71, 0x04, 0x82, 0x0a, 0x6d, 0x30, 0x82, 0x0a, 0x69, 0x30, 0x82, + 0x04, 0xcf, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x06, 0xa0, 0x82, 0x04, 0xc0, 0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x04, 0xb5, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0x8f, 0x4d, 0x29, + 0x1d, 0x21, 0x48, 0x05, 0x13, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x04, + 0x88, 0x16, 0xac, 0xed, 0xf0, 0x0c, 0x6e, 0x05, 0x00, 0x2b, 0xa7, 0xd8, + 0x73, 0xfa, 0x08, 0xc0, 0x54, 0x06, 0x1f, 0x19, 0xf4, 0x76, 0x2a, 0x0c, + 0xa7, 0xd8, 0x0e, 0xcb, 0x8b, 0x1a, 0xac, 0xb7, 0x8b, 0xe9, 0xc8, 0xe7, + 0xe1, 0x05, 0xfe, 0xaf, 0x35, 0x55, 0xf3, 0x97, 0xf0, 0x54, 0x6a, 0xf4, + 0xac, 0xb2, 0xe8, 0xf6, 0x05, 0xa4, 0xea, 0x6d, 0xba, 0xc7, 0x4b, 0x64, + 0xbe, 0xea, 0xce, 0x36, 0x54, 0xf7, 0xbd, 0x0b, 0x19, 0x68, 0x22, 0x55, + 0xd0, 0xd9, 0x83, 0x08, 0x1d, 0x20, 0x6f, 0x42, 0x0b, 0xf1, 0x84, 0x71, + 0x57, 0x2c, 0x32, 0xb4, 0x9a, 0x26, 0x63, 0x1c, 0x6c, 0x4b, 0x97, 0xfb, + 0xb6, 0x45, 0x12, 0xe6, 0x9f, 0xaa, 0x25, 0xa6, 0xfc, 0x3c, 0xef, 0x25, + 0xc4, 0x3a, 0x9c, 0x7b, 0x84, 0xc9, 0x44, 0xc7, 0xca, 0xc2, 0xa2, 0x2d, + 0x58, 0x34, 0x38, 0xbe, 0x4f, 0xd8, 0x57, 0xa7, 0x55, 0x47, 0xb6, 0x10, + 0x92, 0x90, 0xb4, 0x0a, 0x9d, 0x4a, 0xdd, 0xd2, 0xce, 0x03, 0xe8, 0x17, + 0x01, 0xaa, 0xac, 0x69, 0xa0, 0x24, 0xd9, 0x10, 0x51, 0x65, 0x5c, 0x4f, + 0x2a, 0x85, 0x4a, 0x4d, 0x0a, 0x23, 0xf6, 0x52, 0x0c, 0xac, 0xf2, 0x49, + 0x3d, 0xd9, 0x85, 0x87, 0x2e, 0x7a, 0xe3, 0x88, 0x47, 0xef, 0xfd, 0x28, + 0x9d, 0x9c, 0xd9, 0xc2, 0xdd, 0x49, 0xb2, 0x63, 0x3f, 0x06, 0x8c, 0x6d, + 0x2e, 0x72, 0x34, 0x74, 0x3f, 0x2c, 0x31, 0xbb, 0xaf, 0xc1, 0x4a, 0x6e, + 0xd5, 0xf1, 0xfe, 0xa4, 0x77, 0x33, 0x84, 0x50, 0x24, 0xfd, 0x7a, 0xfd, + 0xa3, 0x23, 0x4b, 0xa7, 0x87, 0x92, 0xe9, 0x15, 0x43, 0xc8, 0xdf, 0x5e, + 0x2b, 0x7c, 0xed, 0x1d, 0xf0, 0xef, 0x36, 0x4f, 0x6a, 0x74, 0xbc, 0xe5, + 0xd0, 0xd7, 0xe6, 0xfc, 0x4d, 0x8d, 0x0d, 0xb2, 0xaa, 0xb0, 0xd1, 0xb9, + 0x0f, 0xb4, 0x44, 0x26, 0x0d, 0x21, 0xca, 0x4d, 0x53, 0x50, 0x20, 0xe4, + 0x3e, 0xa0, 0xdf, 0xe9, 0x17, 0x17, 0x04, 0x3f, 0xa5, 0x2e, 0xeb, 0x85, + 0x72, 0x8f, 0x59, 0xce, 0x6f, 0x7e, 0x5d, 0x32, 0xda, 0xe8, 0x43, 0x29, + 0x12, 0x0b, 0xba, 0x66, 0xf5, 0x93, 0x1f, 0x33, 0x56, 0xa3, 0xe6, 0x2d, + 0xeb, 0x6e, 0xad, 0x64, 0x3d, 0x38, 0x0d, 0x67, 0x7d, 0xe9, 0x12, 0x85, + 0x46, 0x15, 0x9e, 0x6c, 0xfb, 0xc2, 0xd6, 0x7c, 0xd0, 0x57, 0x3d, 0x5a, + 0xa8, 0x54, 0xa5, 0x0c, 0x8c, 0x46, 0x17, 0xb5, 0xf4, 0xe7, 0x41, 0x5e, + 0x6a, 0x49, 0x04, 0x1f, 0x99, 0xef, 0xe0, 0x7d, 0xcf, 0xdd, 0x2a, 0x63, + 0x77, 0x8c, 0xe3, 0x65, 0x7e, 0xab, 0x6f, 0x34, 0x15, 0x75, 0xf3, 0xdc, + 0x6e, 0xa0, 0x29, 0x39, 0xe1, 0x64, 0x89, 0xe1, 0x00, 0x8e, 0x2f, 0x3a, + 0x0e, 0xd8, 0xa3, 0x8d, 0x30, 0x3b, 0x26, 0x34, 0x99, 0xa7, 0xcc, 0xcd, + 0x09, 0x16, 0xd8, 0x65, 0x28, 0xdb, 0xc9, 0x04, 0x80, 0xa3, 0x41, 0x05, + 0x7b, 0x3d, 0xf0, 0xd5, 0x9e, 0x11, 0xca, 0x6e, 0xa1, 0x16, 0xaf, 0x0c, + 0x71, 0xc4, 0xd1, 0x00, 0x12, 0xfb, 0x13, 0xef, 0xf6, 0x55, 0x8f, 0xb4, + 0xff, 0x3c, 0x76, 0x57, 0x1e, 0x73, 0x5d, 0x46, 0x5c, 0xdf, 0xf7, 0x13, + 0xbe, 0x6f, 0xf7, 0x8b, 0x65, 0xf9, 0x6d, 0xd4, 0xcd, 0x6f, 0x56, 0x28, + 0xbd, 0x64, 0xb2, 0xd4, 0xd3, 0x31, 0xa9, 0x75, 0xda, 0x5f, 0xf1, 0xfd, + 0xc1, 0x90, 0x1c, 0xb0, 0xd9, 0x8d, 0x96, 0x8e, 0xec, 0xa7, 0x2c, 0x48, + 0x93, 0x44, 0x45, 0x67, 0x73, 0x5b, 0xe8, 0x0f, 0x97, 0x95, 0x19, 0x53, + 0x55, 0x75, 0x69, 0x39, 0x38, 0xe4, 0x18, 0xb5, 0x64, 0x14, 0x9b, 0x95, + 0x7c, 0x25, 0xcb, 0x27, 0x1d, 0x6e, 0x48, 0xff, 0xc2, 0x69, 0x7f, 0x4e, + 0x96, 0x6c, 0x0b, 0x0a, 0x3d, 0xe6, 0xe6, 0xd5, 0xa0, 0xe7, 0x2d, 0xad, + 0x55, 0xf4, 0xfb, 0x29, 0x3f, 0xf3, 0x6e, 0x06, 0x6b, 0x1d, 0xa9, 0x41, + 0xec, 0x1e, 0x8a, 0x20, 0xf1, 0x49, 0x75, 0xda, 0x8a, 0x6f, 0xb3, 0xb6, + 0x07, 0x23, 0xdb, 0xe1, 0x43, 0x36, 0x64, 0xda, 0x31, 0x39, 0x41, 0xfc, + 0xa1, 0x18, 0xc1, 0xaa, 0xa9, 0x7b, 0xf3, 0x7c, 0x10, 0x40, 0xd9, 0xfd, + 0x7b, 0x0d, 0x85, 0x4f, 0x47, 0x2c, 0x9c, 0xb8, 0xb0, 0xec, 0x00, 0x0e, + 0xf7, 0xf5, 0xb6, 0x36, 0xb6, 0x7c, 0xf9, 0x0c, 0xf3, 0xa5, 0x1a, 0x0a, + 0x39, 0x0e, 0x33, 0xde, 0x1b, 0x51, 0xac, 0xe2, 0x8f, 0x72, 0xbe, 0x3e, + 0xe0, 0x97, 0xeb, 0xd6, 0xc3, 0xcc, 0x4e, 0x5f, 0xb4, 0xa4, 0xf1, 0x95, + 0x45, 0x7a, 0x34, 0xc1, 0x92, 0x9a, 0x92, 0x42, 0xef, 0xfd, 0x49, 0xe7, + 0x2a, 0xed, 0x73, 0x43, 0x6f, 0xd4, 0xd6, 0x58, 0xeb, 0x79, 0x53, 0x9b, + 0xa4, 0x2a, 0x12, 0x17, 0x04, 0x0e, 0x2c, 0x6d, 0x16, 0x9f, 0xb9, 0x13, + 0x6a, 0x8f, 0x60, 0x81, 0x8b, 0x2f, 0xae, 0x5e, 0x32, 0x31, 0x1d, 0x58, + 0x71, 0x77, 0x4d, 0xc2, 0x13, 0x94, 0xcf, 0x1d, 0x3e, 0x19, 0x3c, 0x26, + 0x69, 0x8e, 0x0e, 0x78, 0xfd, 0x4b, 0xf2, 0xf3, 0x3b, 0xb8, 0x30, 0x96, + 0xde, 0x8d, 0x14, 0xba, 0xe1, 0x1c, 0x18, 0x6e, 0x46, 0x14, 0x8d, 0x78, + 0x55, 0x34, 0x25, 0xfa, 0x72, 0x37, 0xa8, 0x40, 0x0b, 0x9f, 0x1d, 0x4f, + 0x76, 0x19, 0x6b, 0x5d, 0xba, 0x9e, 0x75, 0x31, 0xe9, 0x59, 0x0e, 0xfd, + 0xb6, 0x6a, 0x96, 0xaa, 0xf8, 0xab, 0xa7, 0x19, 0x89, 0x49, 0xee, 0x82, + 0x8c, 0x46, 0xef, 0x2f, 0xe7, 0x0a, 0xa8, 0x87, 0x07, 0x9e, 0x7e, 0x1e, + 0x48, 0xad, 0x07, 0x3e, 0x1a, 0x84, 0xfa, 0xda, 0xf1, 0x58, 0xb1, 0x72, + 0xd2, 0x9c, 0xcc, 0x9d, 0x68, 0x08, 0x1b, 0xd5, 0x29, 0x6e, 0x8c, 0xfe, + 0x37, 0x9f, 0x97, 0x57, 0x4d, 0xe8, 0x93, 0x6b, 0x14, 0x8d, 0xf2, 0x67, + 0x47, 0xde, 0x36, 0x9a, 0xc9, 0x4b, 0x89, 0x74, 0x11, 0xef, 0x35, 0x1c, + 0x14, 0xfd, 0xfd, 0xe1, 0x95, 0xf9, 0x39, 0xe0, 0x4f, 0xad, 0xc3, 0x08, + 0x1a, 0x24, 0x18, 0xd7, 0x60, 0xec, 0x10, 0xf3, 0x1c, 0xb9, 0x9b, 0x31, + 0x5f, 0xf3, 0x81, 0xa7, 0xf8, 0x20, 0xd1, 0xe3, 0x89, 0xed, 0xe1, 0x59, + 0x8d, 0x76, 0xb2, 0x90, 0x09, 0x0d, 0x3a, 0xb2, 0xb8, 0xca, 0x82, 0x11, + 0xa9, 0xcb, 0xb2, 0xfc, 0x24, 0xb0, 0x75, 0x92, 0xc1, 0xd9, 0x21, 0x60, + 0x8c, 0xe5, 0x95, 0xbf, 0x17, 0xe8, 0x2a, 0x4a, 0x18, 0xcf, 0x1b, 0x91, + 0x5b, 0xe3, 0xfd, 0x23, 0xee, 0x53, 0x54, 0xdd, 0x8f, 0x38, 0x84, 0x8d, + 0x1c, 0x5c, 0x60, 0x47, 0x65, 0x8d, 0xd4, 0x7a, 0x13, 0xf8, 0x5d, 0xda, + 0x30, 0x37, 0xdd, 0x4c, 0xc2, 0xe9, 0xcf, 0x77, 0xde, 0xdc, 0x4c, 0xff, + 0xd8, 0x2f, 0x81, 0x7a, 0xbe, 0x44, 0x4a, 0xa1, 0xf4, 0x12, 0x01, 0x53, + 0x46, 0x99, 0x26, 0xb5, 0xd8, 0x5d, 0x77, 0x6c, 0xf1, 0x47, 0x62, 0x32, + 0x37, 0x3c, 0x8d, 0x0d, 0xbb, 0x69, 0x44, 0x44, 0x12, 0xe6, 0xb7, 0xea, + 0xa7, 0xb1, 0x0a, 0x69, 0x85, 0xbe, 0xf3, 0x47, 0xe0, 0x90, 0xfc, 0x6a, + 0xa5, 0x4d, 0x5b, 0xf6, 0x6d, 0x6f, 0xd6, 0x59, 0x52, 0xff, 0x1f, 0xea, + 0x2d, 0x00, 0x90, 0xdd, 0x64, 0xaf, 0xac, 0x8b, 0x93, 0x5c, 0xd0, 0x58, + 0x92, 0x7e, 0x44, 0x1c, 0x7d, 0xb7, 0x37, 0x8a, 0x4c, 0x23, 0xf8, 0xe5, + 0xff, 0x4d, 0x6b, 0x9b, 0xa5, 0x4a, 0x99, 0xa9, 0xdc, 0x09, 0xc7, 0x2d, + 0xee, 0x60, 0x41, 0x6f, 0xfc, 0x96, 0x96, 0x7d, 0xc9, 0xe8, 0x80, 0x36, + 0xff, 0x12, 0x29, 0x10, 0x4e, 0x02, 0x57, 0x6c, 0x0e, 0x86, 0xa8, 0x1e, + 0x2f, 0x0e, 0x05, 0x70, 0x84, 0x83, 0xcb, 0x3b, 0x22, 0x15, 0x4a, 0x07, + 0x74, 0x01, 0xb5, 0xca, 0x5c, 0x9e, 0x88, 0x8c, 0x13, 0x01, 0xf3, 0x22, + 0xb3, 0x05, 0x99, 0xa1, 0xfc, 0xf4, 0x01, 0x2b, 0xe2, 0x4f, 0x04, 0x13, + 0x12, 0xad, 0xfc, 0xf9, 0xd4, 0x24, 0x78, 0x46, 0x52, 0x94, 0x93, 0x9f, + 0xcd, 0x5c, 0x04, 0x6a, 0xa3, 0x09, 0x25, 0x95, 0xb4, 0x20, 0x51, 0x40, + 0x72, 0x32, 0xc0, 0xea, 0x69, 0x01, 0x6e, 0xb3, 0xf5, 0xb3, 0x11, 0xc5, + 0xa0, 0x8a, 0x8e, 0x62, 0x92, 0x77, 0x8f, 0x33, 0x03, 0xed, 0x77, 0xba, + 0xe7, 0x01, 0x01, 0x78, 0x19, 0x45, 0x9e, 0x84, 0xe1, 0x91, 0xb2, 0x18, + 0x53, 0xbd, 0xdf, 0x65, 0x92, 0xa7, 0xef, 0x9f, 0x2a, 0xdc, 0xc6, 0x62, + 0xff, 0xa0, 0x9f, 0xc9, 0x2c, 0x28, 0x1e, 0xa7, 0xe7, 0x66, 0x7e, 0xcc, + 0x4f, 0x88, 0x91, 0x8e, 0xad, 0x91, 0x20, 0x97, 0x59, 0x29, 0xa0, 0xd3, + 0xc4, 0x2c, 0x14, 0x81, 0xdc, 0x39, 0x09, 0x39, 0xae, 0x30, 0x82, 0x05, + 0x92, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0xa0, 0x82, 0x05, 0x83, 0x04, 0x82, 0x05, 0x7f, 0x30, 0x82, 0x05, 0x7b, + 0x30, 0x82, 0x05, 0x77, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04, 0xee, 0x30, 0x82, 0x04, + 0xea, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0x42, 0x31, 0xa4, 0x16, 0x28, + 0x32, 0x3c, 0x4b, 0x02, 0x02, 0x08, 0x00, 0x04, 0x82, 0x04, 0xc8, 0xee, + 0x3e, 0xfb, 0xcb, 0xa9, 0x11, 0xc9, 0xd6, 0x3f, 0x03, 0x59, 0x2c, 0x91, + 0x8c, 0x9d, 0x6d, 0xba, 0x13, 0xbc, 0xcd, 0x40, 0x6b, 0x02, 0x6c, 0xdd, + 0x06, 0x33, 0x55, 0x35, 0x40, 0x91, 0xb5, 0x04, 0xd0, 0x4f, 0xe4, 0x40, + 0x00, 0x28, 0xa6, 0x38, 0x47, 0xdc, 0x9d, 0xda, 0xd3, 0x39, 0x68, 0x2e, + 0x26, 0xb8, 0xfe, 0xc8, 0x2f, 0xf3, 0xe4, 0xb6, 0x45, 0x02, 0xa4, 0xe5, + 0x57, 0x31, 0x57, 0x33, 0x8c, 0x18, 0x95, 0x47, 0xab, 0xac, 0x96, 0x88, + 0x94, 0x2f, 0x92, 0xb3, 0x60, 0x30, 0x12, 0x1c, 0xca, 0xa9, 0x03, 0x3a, + 0xb4, 0xe8, 0x3f, 0x75, 0x1b, 0xfc, 0xa2, 0x94, 0x8a, 0x6c, 0x14, 0xc0, + 0x55, 0x38, 0xb6, 0xc0, 0x68, 0x76, 0x45, 0x81, 0x90, 0x68, 0xf1, 0xce, + 0x11, 0x8d, 0x35, 0x49, 0xe3, 0x64, 0xa4, 0x9d, 0x9d, 0xf7, 0xb2, 0x9e, + 0x17, 0x26, 0x7e, 0x90, 0x62, 0xc1, 0xa2, 0x9e, 0x3e, 0xda, 0xce, 0x8c, + 0xfd, 0xc8, 0x24, 0xb6, 0x7b, 0x51, 0x96, 0xa2, 0xa5, 0x03, 0xca, 0x52, + 0xc6, 0x04, 0x41, 0xa2, 0xea, 0xb4, 0xbf, 0x77, 0xda, 0x81, 0xa2, 0x3c, + 0x92, 0x70, 0x41, 0xbc, 0x78, 0xb0, 0x20, 0xcf, 0x4f, 0x52, 0xad, 0xb7, + 0xa4, 0x68, 0x84, 0xa7, 0x36, 0x0b, 0x94, 0x7c, 0x34, 0x76, 0xe4, 0x08, + 0x2f, 0x50, 0x69, 0xba, 0x42, 0x1c, 0x63, 0xd4, 0x10, 0xf8, 0xaa, 0xaa, + 0xb9, 0xdf, 0x15, 0xbc, 0x56, 0x00, 0x27, 0x4f, 0x33, 0x01, 0x72, 0x06, + 0x6a, 0xca, 0xb5, 0xa4, 0xbe, 0x20, 0xe8, 0xe5, 0x50, 0xce, 0x43, 0x0b, + 0xad, 0x50, 0x45, 0x58, 0x48, 0xce, 0x49, 0xb9, 0x09, 0x7a, 0xf4, 0x4f, + 0x24, 0x71, 0x68, 0x4c, 0x7f, 0x53, 0xd2, 0x91, 0xed, 0x9b, 0xbc, 0x76, + 0x6d, 0x96, 0x66, 0x9c, 0xfd, 0xee, 0xdd, 0x95, 0xc2, 0x33, 0xdf, 0x36, + 0x37, 0x75, 0x35, 0x5e, 0x7c, 0xbe, 0x85, 0x35, 0x27, 0x65, 0x98, 0xa1, + 0x57, 0xd5, 0xf1, 0x9b, 0xc1, 0x3c, 0x74, 0x0f, 0xfd, 0x21, 0x2e, 0x6d, + 0x3f, 0xae, 0x87, 0xfb, 0x8f, 0x1f, 0x20, 0x06, 0x97, 0x43, 0xc2, 0x6c, + 0xec, 0x55, 0xc2, 0x62, 0xbb, 0xe7, 0x9b, 0x9c, 0x49, 0xd7, 0xb5, 0xd0, + 0x4b, 0x5b, 0x33, 0x29, 0xa9, 0xf0, 0x00, 0x80, 0xcf, 0xaa, 0xf1, 0x52, + 0x45, 0x86, 0x37, 0x98, 0x64, 0x98, 0x1c, 0xab, 0xdc, 0x0e, 0x87, 0xa6, + 0x52, 0x2b, 0xb3, 0xe6, 0xff, 0xa8, 0x57, 0xd2, 0xe7, 0x25, 0x66, 0x01, + 0x34, 0x80, 0x5a, 0xa5, 0x5d, 0x96, 0x3a, 0xe0, 0xe5, 0x39, 0xa3, 0x71, + 0xa3, 0x33, 0x1d, 0xbb, 0x97, 0x99, 0x62, 0x15, 0x9d, 0x12, 0x62, 0xbd, + 0x45, 0xc1, 0xcd, 0xd4, 0x37, 0xb2, 0x10, 0x7a, 0xf8, 0x66, 0xd9, 0xe4, + 0x6e, 0xa8, 0xb8, 0xe8, 0x59, 0x3a, 0xbd, 0xe8, 0x1e, 0x82, 0x62, 0xb2, + 0x7f, 0xf1, 0x5f, 0x45, 0x0c, 0x8e, 0x1c, 0x4f, 0x25, 0xa9, 0xaa, 0xae, + 0xee, 0x2c, 0x93, 0x2d, 0x0b, 0x01, 0xfb, 0xbb, 0x78, 0xed, 0x26, 0x02, + 0x81, 0x41, 0xea, 0xcd, 0xa8, 0x64, 0x9d, 0x38, 0x9d, 0xe9, 0xa3, 0x33, + 0x02, 0xd8, 0x3a, 0x3c, 0xdd, 0x2c, 0xed, 0xc2, 0x90, 0x66, 0x48, 0x97, + 0x12, 0x36, 0xfb, 0xb2, 0xf9, 0x5c, 0xe7, 0x37, 0xe3, 0xf8, 0x0d, 0xb0, + 0x09, 0x38, 0xd8, 0x4b, 0xcf, 0xa5, 0x2e, 0xfd, 0x54, 0xa8, 0xaf, 0x83, + 0xa5, 0xb7, 0x5a, 0x2b, 0xee, 0x09, 0xce, 0x5a, 0x23, 0x9c, 0xa5, 0x07, + 0x63, 0x04, 0x4a, 0xaf, 0x18, 0x9b, 0x56, 0xa5, 0xd8, 0xc5, 0xe0, 0x5d, + 0xab, 0x07, 0x60, 0xd9, 0xf8, 0x32, 0xd1, 0x73, 0x3f, 0xfa, 0x2b, 0xa5, + 0xd1, 0xe3, 0xdf, 0x6c, 0x90, 0x92, 0x7d, 0x80, 0xe8, 0x99, 0x74, 0x9c, + 0x00, 0x0c, 0x6c, 0x65, 0xe4, 0x0e, 0xc0, 0xa0, 0x8d, 0x99, 0x38, 0xe4, + 0xff, 0x7e, 0x30, 0x95, 0x9e, 0xfa, 0xbf, 0x80, 0xfc, 0x28, 0xd8, 0x73, + 0x1b, 0xd9, 0x42, 0x67, 0x17, 0x7e, 0xa9, 0x00, 0x1e, 0x88, 0x27, 0x10, + 0x98, 0x79, 0x7a, 0x21, 0x77, 0x5f, 0x65, 0x2c, 0x94, 0xfe, 0x38, 0x55, + 0x67, 0xca, 0xce, 0x01, 0x24, 0x8a, 0xb0, 0x80, 0x76, 0xca, 0x07, 0xfb, + 0x0f, 0x09, 0xb2, 0xa3, 0xb2, 0x8e, 0xbf, 0xa0, 0x8d, 0xf9, 0x09, 0xe8, + 0x25, 0x41, 0xd7, 0x93, 0x9b, 0xcc, 0xee, 0x33, 0x1e, 0x3d, 0xa9, 0x5e, + 0xb7, 0x68, 0xd8, 0x63, 0x7b, 0x33, 0xcd, 0x87, 0x79, 0x4d, 0xca, 0x2f, + 0xfd, 0xf8, 0xe8, 0xb6, 0xb1, 0x8a, 0xb9, 0xc7, 0xb7, 0x6b, 0xa6, 0x41, + 0xda, 0x7e, 0x20, 0x0e, 0xd8, 0x5c, 0x54, 0xee, 0x2b, 0x15, 0xe7, 0xb7, + 0x7c, 0x42, 0x31, 0xce, 0xbd, 0x40, 0x27, 0xeb, 0x7d, 0xbb, 0x30, 0x56, + 0x0b, 0xa9, 0x82, 0xcd, 0x54, 0x4d, 0x79, 0x64, 0x5b, 0x6e, 0x76, 0x67, + 0xdc, 0x51, 0xb4, 0x65, 0x80, 0x7a, 0x24, 0x48, 0xbc, 0x93, 0xf4, 0x32, + 0xe7, 0xcd, 0x9e, 0x54, 0x0f, 0x0b, 0x66, 0xf7, 0x7c, 0xd1, 0x41, 0xf3, + 0xf4, 0x17, 0x94, 0xf6, 0xd3, 0x5f, 0x13, 0x4a, 0x7a, 0x03, 0x85, 0x3d, + 0xc0, 0xc2, 0x42, 0x30, 0xc1, 0xdf, 0x04, 0xa1, 0x25, 0x1b, 0x40, 0x19, + 0x27, 0x1b, 0xcf, 0x32, 0xbc, 0x53, 0x9a, 0xd8, 0x5e, 0x65, 0x3c, 0x3b, + 0x6e, 0x65, 0x29, 0x3b, 0x1c, 0x48, 0xb5, 0x0d, 0xe1, 0xc6, 0xe6, 0x33, + 0x60, 0xfd, 0x23, 0x62, 0x03, 0xba, 0x35, 0x00, 0xf3, 0xec, 0x46, 0x06, + 0x91, 0xd5, 0x22, 0x16, 0x93, 0xd9, 0x8f, 0xae, 0xf7, 0x36, 0x55, 0x67, + 0xc5, 0x3b, 0x79, 0x11, 0xea, 0x99, 0x26, 0xab, 0xd2, 0xce, 0xdb, 0x07, + 0xaa, 0xc3, 0x67, 0x2a, 0x64, 0xbd, 0xd4, 0xd0, 0x92, 0xef, 0xec, 0xba, + 0x23, 0xf1, 0x03, 0x89, 0x31, 0x53, 0xed, 0x56, 0xf6, 0x42, 0xd4, 0x05, + 0x82, 0xf7, 0x9b, 0xd6, 0xb6, 0x99, 0xd0, 0x2c, 0x5f, 0xba, 0x5d, 0x82, + 0xe7, 0xbc, 0x1c, 0x95, 0xa0, 0x1e, 0xf8, 0xdd, 0x0d, 0x3a, 0xc3, 0xc5, + 0x62, 0x0f, 0xb4, 0x25, 0x5f, 0x29, 0x76, 0x18, 0x6b, 0x00, 0xe2, 0xda, + 0xe0, 0x06, 0x38, 0x30, 0x05, 0xe3, 0x2a, 0x62, 0xd3, 0x66, 0x4b, 0x0f, + 0x67, 0x08, 0x09, 0xea, 0x5c, 0xb8, 0x19, 0x96, 0x43, 0x2d, 0x97, 0x7e, + 0x41, 0x43, 0x1e, 0x17, 0x0a, 0xdf, 0xc5, 0xe7, 0x33, 0xe2, 0x3f, 0xb9, + 0xb6, 0x85, 0xf4, 0x35, 0x8a, 0x3f, 0x08, 0x3c, 0x06, 0x18, 0xb1, 0xd0, + 0x6a, 0x64, 0x6e, 0x43, 0xe1, 0x22, 0x36, 0xe5, 0xf7, 0x09, 0x7d, 0xda, + 0xf9, 0x43, 0x9d, 0x09, 0x55, 0xa4, 0xc8, 0x62, 0x78, 0x66, 0x9c, 0xcf, + 0x38, 0xd2, 0xc5, 0xb4, 0x2e, 0xdc, 0x6d, 0xde, 0xf0, 0xc7, 0xed, 0x24, + 0x98, 0x57, 0xb4, 0xd0, 0x93, 0x12, 0x26, 0xe2, 0x3f, 0x44, 0xbc, 0xd0, + 0x99, 0x69, 0x32, 0x34, 0xf8, 0xa6, 0x8d, 0xbf, 0x13, 0x02, 0x63, 0x1e, + 0x69, 0x61, 0x94, 0x9c, 0xcf, 0xf2, 0x8f, 0x3a, 0x54, 0xcd, 0x97, 0xea, + 0x84, 0x53, 0xd9, 0xf6, 0x44, 0x3c, 0xbd, 0x54, 0x48, 0x3d, 0x05, 0x55, + 0x8b, 0x85, 0xb4, 0xec, 0x41, 0xf8, 0xdf, 0x06, 0xae, 0x0b, 0x41, 0x73, + 0x79, 0xe0, 0x89, 0xa9, 0xb5, 0x68, 0x18, 0x38, 0xb0, 0xe7, 0xb9, 0x2c, + 0x09, 0xd9, 0xb9, 0x06, 0x47, 0xe8, 0xcf, 0xae, 0xb9, 0x5d, 0x88, 0x33, + 0xe1, 0x3c, 0xc5, 0x3f, 0x49, 0xda, 0x16, 0x8d, 0xa3, 0xa4, 0x27, 0x1e, + 0x51, 0xce, 0x8f, 0x52, 0x7e, 0xec, 0x90, 0x5d, 0x03, 0x70, 0xee, 0x5b, + 0xcb, 0xc1, 0x17, 0x2c, 0x45, 0x97, 0x55, 0x58, 0xb4, 0xeb, 0xa4, 0xfb, + 0x1a, 0x70, 0x5f, 0xac, 0x72, 0x59, 0x20, 0x04, 0x37, 0x57, 0x18, 0x6f, + 0x87, 0x29, 0xfc, 0x58, 0x0a, 0x8f, 0x2e, 0xc6, 0xff, 0x55, 0xc6, 0x4c, + 0x55, 0xa4, 0x06, 0x11, 0x13, 0xbc, 0xa2, 0x14, 0x77, 0xeb, 0x26, 0x21, + 0x79, 0xbb, 0x0d, 0x96, 0x7a, 0x80, 0x8a, 0xd2, 0x2d, 0x29, 0x85, 0x3d, + 0x04, 0x5a, 0x43, 0x45, 0x9d, 0x51, 0xf5, 0xaf, 0x24, 0x25, 0x85, 0xad, + 0xe2, 0xf8, 0xc4, 0x0b, 0x44, 0x84, 0x9c, 0xd0, 0x27, 0x00, 0x67, 0x48, + 0x02, 0x9f, 0x05, 0x2d, 0x3e, 0xe8, 0xf6, 0xb6, 0xeb, 0xde, 0xa9, 0xe2, + 0xd9, 0x62, 0x99, 0x02, 0x84, 0x65, 0xfb, 0x0a, 0x9b, 0x2b, 0x73, 0xb8, + 0x03, 0x8c, 0xc4, 0x98, 0xf9, 0x9d, 0xbf, 0x86, 0x5b, 0x84, 0xab, 0xe3, + 0xc6, 0x50, 0x34, 0xc6, 0x38, 0x5a, 0x41, 0x46, 0xff, 0xa6, 0xe8, 0x13, + 0x1d, 0x1a, 0x6a, 0x96, 0x6f, 0xfa, 0x87, 0xa1, 0x14, 0x15, 0x91, 0x43, + 0xad, 0xdb, 0x15, 0x48, 0x9f, 0x54, 0x41, 0x27, 0x38, 0x60, 0xbb, 0x17, + 0x01, 0xcd, 0x01, 0xab, 0x5e, 0x09, 0x74, 0x14, 0x77, 0xcd, 0xba, 0xf9, + 0x69, 0x37, 0x8f, 0xcc, 0xcc, 0x57, 0xde, 0xf9, 0xa1, 0xe7, 0x3b, 0x2f, + 0x03, 0x8b, 0xc2, 0x7b, 0x13, 0x03, 0x9c, 0x67, 0x80, 0x4e, 0xfe, 0x0d, + 0x30, 0xe2, 0x97, 0x62, 0xf6, 0xbe, 0x59, 0x89, 0xb9, 0xc8, 0x38, 0x25, + 0x3f, 0x3d, 0x66, 0xbe, 0x3a, 0x8d, 0x43, 0x84, 0x7d, 0x18, 0xa5, 0x31, + 0x76, 0x30, 0x4f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x14, 0x31, 0x42, 0x1e, 0x40, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, + 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, + 0x00, 0x72, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, 0x20, 0x00, 0x46, + 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x77, 0x00, 0x6f, + 0x00, 0x72, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x49, 0x00, 0x64, 0x00, 0x65, + 0x00, 0x6e, 0x00, 0x74, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x30, 0x23, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, + 0x16, 0x04, 0x14, 0x54, 0x36, 0xb0, 0x72, 0x55, 0x52, 0x47, 0x60, 0xa3, + 0x66, 0x0a, 0xef, 0x0d, 0x3b, 0x1c, 0x51, 0x2d, 0x0e, 0xa9, 0xfe, 0x30, + 0x30, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, + 0x05, 0x00, 0x04, 0x14, 0xbc, 0x8a, 0xfc, 0x3b, 0x75, 0x62, 0xaf, 0xb0, + 0x63, 0xd5, 0x2d, 0x34, 0xef, 0xac, 0x88, 0xe4, 0x7d, 0xe3, 0x2a, 0x48, + 0x04, 0x08, 0xd0, 0x1a, 0xbd, 0xe0, 0x7c, 0xb5, 0xdc, 0x5b, 0x02, 0x01, + 0x01 +}; + +#endif /* _TRUSTTESTS_IDENTITY_INTERFACE_H_ */ diff --git a/OSX/libsecurity_keychain/xpc-tsa/timestampclient.m b/OSX/libsecurity_keychain/xpc-tsa/timestampclient.m index 148be634..180950ac 100644 --- a/OSX/libsecurity_keychain/xpc-tsa/timestampclient.m +++ b/OSX/libsecurity_keychain/xpc-tsa/timestampclient.m @@ -48,7 +48,8 @@ void sendTSARequest(CFDataRef tsaReq, const char *tsaURL, TSARequestCompletionBl - (id)init { - self = [super init]; + if ((self = [super init])) { + } return self; } diff --git a/OSX/libsecurity_manifest/lib/AppleManifest.cpp b/OSX/libsecurity_manifest/lib/AppleManifest.cpp index c7d3429f..d181e1ef 100644 --- a/OSX/libsecurity_manifest/lib/AppleManifest.cpp +++ b/OSX/libsecurity_manifest/lib/AppleManifest.cpp @@ -584,12 +584,13 @@ void AppleManifest::ReconstructOther (uint32& finger, const uint8* data, Manifes void AppleManifest::ReconstructManifestItemList (uint32 &finger, const uint8* data, ManifestItemList &itemList) { - uint32 start = finger; - uint64_t length = ReconstructUInt64 (finger, data); + uint32 start = finger; + uint64_t length = ReconstructUInt64 (finger, data); uint32 end = (uint32)(start + length); - if (length > UINT32_MAX || (length + (uint64_t)start) > (uint64_t)UINT32_MAX) + if (length > UINT32_MAX || (length + (uint64_t)start) > (uint64_t)UINT32_MAX) { MacOSError::throwMe (errSecManifestDamaged); + } while (finger < end) { diff --git a/OSX/libsecurity_manifest/lib/Manifest.cpp b/OSX/libsecurity_manifest/lib/Manifest.cpp index 42b75c6a..b8d9d835 100644 --- a/OSX/libsecurity_manifest/lib/Manifest.cpp +++ b/OSX/libsecurity_manifest/lib/Manifest.cpp @@ -35,7 +35,7 @@ Manifest::Manifest () : mManifestSigner (NULL) -Manifest::~Manifest () throw () +Manifest::~Manifest () _NOEXCEPT { delete mManifestSigner; } diff --git a/OSX/libsecurity_manifest/lib/Manifest.h b/OSX/libsecurity_manifest/lib/Manifest.h index 27ebff42..8e0e223f 100644 --- a/OSX/libsecurity_manifest/lib/Manifest.h +++ b/OSX/libsecurity_manifest/lib/Manifest.h @@ -49,7 +49,7 @@ public: Manifest (); - virtual ~Manifest () throw (); + virtual ~Manifest () _NOEXCEPT; ManifestInternal& GetManifestInternal () {return mManifestInternal;} ManifestSigner* GetSigner () {return mManifestSigner;} diff --git a/OSX/libsecurity_manifest/lib/SecureDownloadInternal.c b/OSX/libsecurity_manifest/lib/SecureDownloadInternal.c index e035ca50..7e5a4921 100644 --- a/OSX/libsecurity_manifest/lib/SecureDownloadInternal.c +++ b/OSX/libsecurity_manifest/lib/SecureDownloadInternal.c @@ -3,6 +3,8 @@ #include "SecureDownloadInternal.h" #include "SecCFRelease.h" +#include "simulatecrash_assert.h" + // // SecureDownloadXML: SecureDownloadXML.c // cc -g -framework CoreFoundation -o $@ $^ diff --git a/OSX/libsecurity_mds/lib/MDSSession.cpp b/OSX/libsecurity_mds/lib/MDSSession.cpp index 199839e6..a0b9e8e1 100644 --- a/OSX/libsecurity_mds/lib/MDSSession.cpp +++ b/OSX/libsecurity_mds/lib/MDSSession.cpp @@ -37,12 +37,14 @@ #include #include #include -#include +#include #include #include #include #include +#include "LegacyAPICounts.h" + using namespace CssmClient; /* @@ -333,12 +335,7 @@ static bool doesFileExist( /* it's there...how does it look? */ mode_t fileType = sb.st_mode & S_IFMT; -#ifdef DARLING - // we don't care about UIDs in Darling - if((fileType == S_IFREG)) { -#else if((fileType == S_IFREG) && (sb.st_uid == forUid)) { -#endif return true; } if(!purge) { @@ -456,12 +453,10 @@ static bool doesDirectExist( directStatus = MDS_NotDirectory; return false; } -#ifndef DARLING if(sb.st_uid != forUid) { directStatus = MDS_BadOwnerMode; return false; } -#endif if((sb.st_mode & 07777) != mode) { directStatus = MDS_BadOwnerMode; return false; @@ -1445,7 +1440,7 @@ MDSSession::DbFilesInfo::~DbFilesInfo() } } -/* lazy evaluation of both DB handles�*/ +/* lazy evaluation of both DB handles*/ CSSM_DB_HANDLE MDSSession::DbFilesInfo::objDbHand() { if(mObjDbHand != 0) { @@ -1560,6 +1555,18 @@ void MDSSession::DbFilesInfo::removeOutdatedPlugins() CSSM_DB_ATTRIBUTE_DATA theAttrs[2]; CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo; TbdVector tbdRecords; + + __block bool countPlugins = false; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // We will set this to true exactly once + countPlugins = true; + }); + + // The clang analyzer does not understand that DataGetNext fills in theAttrs with malloc'ed pointers, + // through a chain of structs, pointers, and confusing names. Then, it has false-positive use-after-free + // warnings. So, disable the analyzer for this function. +#ifndef __clang_analyzer__ /* * First, scan object directory. All we need are the path and GUID attributes. @@ -1608,6 +1615,13 @@ void MDSSession::DbFilesInfo::removeOutdatedPlugins() } if(resultHand) { if(theAttrs[0].NumberOfValues && theAttrs[1].NumberOfValues) { + if(countPlugins) { + string path = CssmData::overlay(*theAttrs[1].Value).toString(); + string guid = CssmData::overlay(*theAttrs[0].Value).toString(); + + countLegacyMDSPlugin(path.c_str(), guid.c_str()); + } + checkOutdatedPlugin(*theAttrs[1].Value, *theAttrs[0].Value, tbdRecords); } @@ -1647,6 +1661,13 @@ void MDSSession::DbFilesInfo::removeOutdatedPlugins() mSession.FreeUniqueRecord(mObjDbHand, *record); } if(theAttrs[0].NumberOfValues && theAttrs[1].NumberOfValues) { + if(countPlugins) { + string path = CssmData::overlay(*theAttrs[1].Value).toString(); + string guid = CssmData::overlay(*theAttrs[0].Value).toString(); + + countLegacyMDSPlugin(path.c_str(), guid.c_str()); + } + checkOutdatedPlugin(*theAttrs[1].Value, *theAttrs[0].Value, tbdRecords); @@ -1681,6 +1702,10 @@ void MDSSession::DbFilesInfo::removeOutdatedPlugins() for(size_t i=0; i #include #include +#include "LegacyAPICounts.h" #define MSApiDebug(args...) secinfo("MDS_API", ## args) @@ -286,7 +287,7 @@ CSSM_RETURN CSSMAPI MDS_Terminate (MDS_HANDLE inMDSHandle) { BEGIN_API - auto_ptr aMDSSession (&HandleObject::findAndKill (inMDSHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE)); + unique_ptr aMDSSession (&HandleObject::findAndKill (inMDSHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE)); aMDSSession->terminate (); // Even if terminate throws the MDSSession object will be deleted. END_API(MDS) } diff --git a/OSX/libsecurity_ocspd/client/ocspdClient.cpp b/OSX/libsecurity_ocspd/client/ocspdClient.cpp index 4c48f253..be931ce6 100644 --- a/OSX/libsecurity_ocspd/client/ocspdClient.cpp +++ b/OSX/libsecurity_ocspd/client/ocspdClient.cpp @@ -32,11 +32,7 @@ #include #include #include -#ifdef DARLING -#include "ocspd.h" -#else #include /* MIG interface */ -#endif #include class ocspdGlobals { @@ -317,10 +313,11 @@ CSSM_RETURN ocspdCRLStatus( issuers.Data, (mach_msg_type_number_t)issuers.Length, crlIssuer ? crlIssuer->Data : NULL, crlIssuer ? (mach_msg_type_number_t)crlIssuer->Length : 0, crlURL ? crlURL->Data : NULL, crlURL ? (mach_msg_type_number_t)crlURL->Length : 0); - if (krtn == MACH_SEND_INVALID_DEST) + if (krtn == MACH_SEND_INVALID_DEST) { OcspdGlobals().resetServerPort(); + } - return krtn; + return krtn; } /* diff --git a/OSX/libsecurity_ocspd/common/ocspdClient.h b/OSX/libsecurity_ocspd/common/ocspdClient.h deleted file mode 120000 index 2bac10f1..00000000 --- a/OSX/libsecurity_ocspd/common/ocspdClient.h +++ /dev/null @@ -1 +0,0 @@ -../client/ocspdClient.h \ No newline at end of file diff --git a/OSX/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp b/OSX/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp index a1e93fd2..b1902a05 100644 --- a/OSX/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp +++ b/OSX/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp @@ -31,7 +31,7 @@ #include "pkcs12BagAttrs.h" #include "pkcs12Utils.h" #include -#include +#include #include /* * Copying constructor used by P12SafeBag during encoding diff --git a/OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp b/OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp index f2e068bc..4620c438 100644 --- a/OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp +++ b/OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp @@ -29,7 +29,7 @@ #include "pkcs12Debug.h" #include "pkcs12Utils.h" #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp b/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp index b72e2e52..802f98e6 100644 --- a/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp +++ b/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp @@ -360,9 +360,9 @@ SDCSPSession::FreeKey(const AccessCredentials *accessCred, // that! // Find the key in the map. Tell tell the key to free itself - // (when the auto_ptr deletes the key it removes itself from the map). + // (when the unique_ptr deletes the key it removes itself from the map). secinfo("freeKey", "CSPDL FreeKey"); - auto_ptr ssKey(&mSDCSPDLSession.find(ioKey)); + unique_ptr ssKey(&mSDCSPDLSession.find(ioKey)); ssKey->free(accessCred, ioKey, deleteKey); } else diff --git a/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp b/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp index 1717eaf5..788b0b3f 100644 --- a/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp +++ b/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp @@ -486,7 +486,7 @@ SDCryptContext::final(CssmData &out) if(!inSize) return; const CssmData in(const_cast(mNullDigest.digestPtr()), inSize); - IFDEBUG(size_t origOutSize = out.length()); + size_t origOutSize = out.length(); if (encoding()) { clientSession().encrypt(*mContext, mKeyHandle, in, out); } diff --git a/OSX/libsecurity_smime/lib/cert.c b/OSX/libsecurity_smime/lib/cert.c index a0a8b4d9..dd737709 100644 --- a/OSX/libsecurity_smime/lib/cert.c +++ b/OSX/libsecurity_smime/lib/cert.c @@ -39,10 +39,11 @@ #include #include #include +#include #include /* for errKCDuplicateItem */ -#include +#include #define CERT_DEBUG 0 #if CERT_DEBUG @@ -51,10 +52,6 @@ #define dprintf(args...) #endif -/* @@@ Remove this once it's back in the appropriate header. */ -static const uint8 X509V1IssuerNameStd[] = {INTEL_X509V3_CERT_R08, 23}; -static const CSSM_OID OID_X509V1IssuerNameStd = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1IssuerNameStd}; - /* * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case * insensitive and we're supposed to ignore leading and trailing @@ -579,100 +576,59 @@ SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert, SECItem *retIt // Extract the issuer and serial number from a certificate SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert) { - OSStatus status; SecCmsIssuerAndSN *certIssuerAndSN; - SecCertificateRef certRef; - SecCertificateRef itemImplRef = NULL; - CSSM_CL_HANDLE clHandle = 0; - CSSM_DATA_PTR serialNumber = 0; - CSSM_DATA_PTR issuer = 0; - CSSM_DATA certData = {}; - CSSM_HANDLE resultsHandle = 0; - uint32 numberOfFields = 0; - CSSM_RETURN result; + void *mark; - mark = PORT_ArenaMark(pl); - - /* Retain input cert and get pointer to its data */ - certRef = (SecCertificateRef)((cert) ? CFRetain(cert) : NULL); - if (!certRef || SecCertificateGetData(certRef, &certData)) { + CFDataRef issuer_data = SecCertificateCopyIssuerSequence(cert); + CFDataRef serial_data = SecCertificateCopySerialNumberData(cert, NULL); + if (!issuer_data || !serial_data) { goto loser; } -#if 1 - // Convert unified input certRef to itemImpl instance. - // note: must not release this instance while we're using its CL handle! - itemImplRef = SecCertificateCreateItemImplInstance(cert); - status = SecCertificateGetCLHandle_legacy(itemImplRef, &clHandle); -#else - status = SecCertificateGetCLHandle(certRef, &clHandle); -#endif - if (status) - goto loser; - /* Get the issuer from the cert. */ - result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, - &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer); - - if (result || numberOfFields < 1) - goto loser; - result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); - if (result) - goto loser; - - /* Get the serialNumber from the cert. */ - result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, - &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber); - if (result || numberOfFields < 1) - goto loser; - result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); - if (result) - goto loser; + SecAsn1Item serialNumber = { + .Length = CFDataGetLength(serial_data), + .Data = (uint8_t *)CFDataGetBytePtr(serial_data) + }; + SecAsn1Item issuer = { + .Length = CFDataGetLength(issuer_data), + .Data = (uint8_t *)CFDataGetBytePtr(issuer_data) + }; /* Allocate the SecCmsIssuerAndSN struct. */ certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN)); - if (certIssuerAndSN == NULL) + if (certIssuerAndSN == NULL) { goto loser; + } /* Copy the issuer. */ - certIssuerAndSN->derIssuer.Data = (uint8 *) PORT_ArenaAlloc(pl, issuer->Length); - if (!certIssuerAndSN->derIssuer.Data) + certIssuerAndSN->derIssuer.Data = (uint8_t *) PORT_ArenaAlloc(pl, issuer.Length); + if (!certIssuerAndSN->derIssuer.Data) { goto loser; - PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer->Data, issuer->Length); - certIssuerAndSN->derIssuer.Length = issuer->Length; + } + PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer.Data, issuer.Length); + certIssuerAndSN->derIssuer.Length = issuer.Length; /* Copy the serialNumber. */ - certIssuerAndSN->serialNumber.Data = (uint8 *) PORT_ArenaAlloc(pl, serialNumber->Length); - if (!certIssuerAndSN->serialNumber.Data) + certIssuerAndSN->serialNumber.Data = (uint8_t *) PORT_ArenaAlloc(pl, serialNumber.Length); + if (!certIssuerAndSN->serialNumber.Data) { goto loser; - PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber->Data, serialNumber->Length); - certIssuerAndSN->serialNumber.Length = serialNumber->Length; + } + PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length); + certIssuerAndSN->serialNumber.Length = serialNumber.Length; + + CFRelease(serial_data); + CFRelease(issuer_data); PORT_ArenaUnmark(pl, mark); - - CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); - CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); - - if (itemImplRef) - CFRelease(itemImplRef); - if (certRef) - CFRelease(certRef); - return certIssuerAndSN; loser: + CFReleaseNull(serial_data); + CFReleaseNull(issuer_data); PORT_ArenaRelease(pl, mark); - - if (serialNumber) - CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); - if (issuer) - CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); - if (itemImplRef) - CFRelease(itemImplRef); - if (certRef) - CFRelease(certRef); - PORT_SetError(SEC_INTERNAL_ONLY); + return NULL; } diff --git a/OSX/libsecurity_smime/lib/cmscinfo.c b/OSX/libsecurity_smime/lib/cmscinfo.c index fd0456c6..1850d4d5 100644 --- a/OSX/libsecurity_smime/lib/cmscinfo.c +++ b/OSX/libsecurity_smime/lib/cmscinfo.c @@ -50,7 +50,7 @@ #include "secitem.h" #include -#include +#include /* * SecCmsContentInfoCreate - create a content info diff --git a/OSX/libsecurity_smime/lib/cmsdigest.c b/OSX/libsecurity_smime/lib/cmsdigest.c index cbdc0912..42d5ae51 100644 --- a/OSX/libsecurity_smime/lib/cmsdigest.c +++ b/OSX/libsecurity_smime/lib/cmsdigest.c @@ -3,25 +3,25 @@ * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ - * + * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. - * + * * The Original Code is the Netscape security libraries. - * + * * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are + * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. - * + * * Contributor(s): - * + * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and @@ -34,24 +34,30 @@ /* * CMS digesting. */ +#include #include "cmslocal.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" #include -#include +#include + +#include #include -/* Return the maximum value between S and T */ +/* Return the maximum value between S and T (and U) */ #define MAX(S, T) ({__typeof__(S) _max_s = S; __typeof__(T) _max_t = T; _max_s > _max_t ? _max_s : _max_t;}) +#define MAX_OF_3(S, T, U) ({__typeof__(U) _max_st = MAX(S,T); MAX(_max_st,U);}) struct SecCmsDigestContextStr { - Boolean saw_contents; - int digcnt; - CSSM_CC_HANDLE * digobjs; + PLArenaPool * poolp; + Boolean saw_contents; + int digcnt; + void ** digobjs; + SECAlgorithmID ** digestalgs; }; /* @@ -61,25 +67,38 @@ struct SecCmsDigestContextStr { SecCmsDigestContextRef SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) { - SecCmsDigestContextRef cmsdigcx; - CSSM_CC_HANDLE digobj; + PLArenaPool *poolp; + SecCmsDigestContextRef cmsdigcx = NULL; + void * digobj; int digcnt; int i; + poolp = PORT_NewArena(1024); + if (poolp == NULL) { + goto loser; + } + digcnt = (digestalgs == NULL) ? 0 : SecCmsArrayCount((void **)digestalgs); - cmsdigcx = (SecCmsDigestContextRef)PORT_ZAlloc(sizeof(struct SecCmsDigestContextStr)); - if (cmsdigcx == NULL) - return NULL; + cmsdigcx = (SecCmsDigestContextRef)PORT_ArenaAlloc(poolp, sizeof(struct SecCmsDigestContextStr)); + if (cmsdigcx == NULL) { + goto loser; + } + cmsdigcx->poolp = poolp; if (digcnt > 0) { /* Security check to prevent under-allocation */ - if (digcnt >= (int)(INT_MAX/sizeof(CSSM_CC_HANDLE))) { + if (digcnt >= (int)((INT_MAX/(MAX(sizeof(void *),sizeof(SECAlgorithmID *))))-1)) { + goto loser; + } + cmsdigcx->digobjs = (void**)PORT_ArenaAlloc(poolp, digcnt * sizeof(void *)); + if (cmsdigcx->digobjs == NULL) { + goto loser; + } + cmsdigcx->digestalgs = (SECAlgorithmID **)PORT_ArenaZAlloc(poolp, (digcnt + 1) * sizeof(SECAlgorithmID *)); + if (cmsdigcx->digestalgs == NULL) { goto loser; } - cmsdigcx->digobjs = (CSSM_CC_HANDLE *)PORT_ZAlloc(digcnt * sizeof(CSSM_CC_HANDLE)); - if (cmsdigcx->digobjs == NULL) - goto loser; } cmsdigcx->digcnt = 0; @@ -88,27 +107,27 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) * Create a digest object context for each algorithm. */ for (i = 0; i < digcnt; i++) { - digobj = SecCmsUtilGetHashObjByAlgID(digestalgs[i]); - /* - * Skip any algorithm we do not even recognize; obviously, - * this could be a problem, but if it is critical then the - * result will just be that the signature does not verify. - * We do not necessarily want to error out here, because - * the particular algorithm may not actually be important, - * but we cannot know that until later. - */ - if (digobj) - { - CSSM_RETURN result; - result = CSSM_DigestDataInit(digobj); - if (result != CSSM_OK) - { - goto loser; - } + digobj = SecCmsUtilGetHashObjByAlgID(digestalgs[i]); + /* + * Skip any algorithm we do not even recognize; obviously, + * this could be a problem, but if it is critical then the + * result will just be that the signature does not verify. + * We do not necessarily want to error out here, because + * the particular algorithm may not actually be important, + * but we cannot know that until later. + */ + + cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj; + cmsdigcx->digestalgs[cmsdigcx->digcnt] = PORT_ArenaAlloc(poolp, sizeof(SECAlgorithmID)); + if (SECITEM_CopyItem(poolp, + &(cmsdigcx->digestalgs[cmsdigcx->digcnt]->algorithm), + &(digestalgs[i]->algorithm)) + || SECITEM_CopyItem(poolp, + &(cmsdigcx->digestalgs[cmsdigcx->digcnt]->parameters), + &(digestalgs[i]->parameters))) { + goto loser; } - - cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj; - cmsdigcx->digcnt++; + cmsdigcx->digcnt++; } cmsdigcx->saw_contents = PR_FALSE; @@ -116,13 +135,15 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) return cmsdigcx; loser: - if (cmsdigcx) { - if (cmsdigcx->digobjs) { - PORT_Free(cmsdigcx->digobjs); - cmsdigcx->digobjs = NULL; - cmsdigcx->digcnt = 0; - } + if (poolp) { + PORT_FreeArena(poolp, PR_FALSE); } + if (cmsdigcx && cmsdigcx->digobjs) { + PORT_Free(cmsdigcx->digobjs); + cmsdigcx->digobjs = NULL; + cmsdigcx->digcnt = 0; + } + return NULL; } @@ -133,7 +154,7 @@ loser: SecCmsDigestContextRef SecCmsDigestContextStartSingle(SECAlgorithmID *digestalg) { - SECAlgorithmID *digestalgs[] = { NULL, NULL }; /* fake array */ + SECAlgorithmID *digestalgs[] = { NULL, NULL }; /* fake array */ digestalgs[0] = digestalg; return SecCmsDigestContextStartMultiple(digestalgs); @@ -145,15 +166,40 @@ SecCmsDigestContextStartSingle(SECAlgorithmID *digestalg) void SecCmsDigestContextUpdate(SecCmsDigestContextRef cmsdigcx, const unsigned char *data, size_t len) { - CSSM_DATA dataBuf; + SecAsn1Item dataBuf; int i; dataBuf.Length = len; - dataBuf.Data = (uint8 *)data; + dataBuf.Data = (uint8_t *)data; cmsdigcx->saw_contents = PR_TRUE; - for (i = 0; i < cmsdigcx->digcnt; i++) - if (cmsdigcx->digobjs && cmsdigcx->digobjs[i]) - CSSM_DigestDataUpdate(cmsdigcx->digobjs[i], &dataBuf, 1); + for (i = 0; i < cmsdigcx->digcnt; i++) { + if (cmsdigcx->digobjs[i]) { + /* 64 bits cast: worst case is we truncate the length and we dont hash all the data. + This may cause an invalid CMS blob larger than 4GB to be validated. Unlikely, but + possible security issue. There is no way to return an error here, but a check at + the upper level may happen. */ + /* + rdar://problem/20642513 + Let's just die a horrible death rather than have the security issue. + CMS blob over 4GB? Oh well. + */ + if (len > UINT32_MAX) { + /* Ugh. */ + abort(); + } + assert(len<=UINT32_MAX); /* Debug check. Correct as long as CC_LONG is uint32_t */ + switch (SECOID_GetAlgorithmTag(cmsdigcx->digestalgs[i])) { + case SEC_OID_SHA1: CC_SHA1_Update((CC_SHA1_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_MD5: CC_MD5_Update((CC_MD5_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA224: CC_SHA224_Update((CC_SHA256_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA256: CC_SHA256_Update((CC_SHA256_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA384: CC_SHA384_Update((CC_SHA512_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA512: CC_SHA512_Update((CC_SHA512_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + default: + break; + } + } + } } /* @@ -164,109 +210,113 @@ SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx) { int i; - for (i = 0; i < cmsdigcx->digcnt; i++) + for (i = 0; i < cmsdigcx->digcnt; i++) { if (cmsdigcx->digobjs && cmsdigcx->digobjs[i]) { - CSSM_DeleteContext(cmsdigcx->digobjs[i]); - cmsdigcx->digobjs[i] = 0; + free(cmsdigcx->digobjs[i]); + cmsdigcx->digobjs[i] = NULL; } + } + + PORT_FreeArena(cmsdigcx->poolp, PR_TRUE); } /* - * SecCmsDigestContextFinishMultiple - finish the digests and put them - * into an array of CSSM_DATAs (allocated on poolp) + * SecCmsDigestContextFinishMultiple - finish the digests + * Note that on macOS, this call cancels and frees the digest context (because the digests are allocated from an input arena pool). + * The iOS version only frees the digest objects and requires a call to SecCmsDisgestContextDestroy + * or SecCmsDisgestContextCancel (because the digests are allocated out of the context's pool). */ OSStatus -SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef poolp, - CSSM_DATA_PTR **digestsp) +SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, + SecArenaPoolRef poolp, + SecAsn1Item * **digestsp) { - CSSM_CC_HANDLE digobj; - CSSM_DATA_PTR *digests, digest; + void * digobj; + SecAsn1Item **digests, *digest; int i; void *mark; OSStatus rv = SECFailure; + assert(cmsdigcx != NULL); + /* no contents? do not update digests */ if (digestsp == NULL || !cmsdigcx->saw_contents) { - for (i = 0; i < cmsdigcx->digcnt; i++) + for (i = 0; i < cmsdigcx->digcnt; i++) { if (cmsdigcx->digobjs && cmsdigcx->digobjs[i]) { - CSSM_DeleteContext(cmsdigcx->digobjs[i]); - cmsdigcx->digobjs[i] = 0; + free(cmsdigcx->digobjs[i]); } - rv = SECSuccess; - goto cleanup; + } + rv = SECSuccess; + goto cleanup; } + assert(digestsp != NULL); + mark = PORT_ArenaMark ((PLArenaPool *)poolp); /* Security check to prevent under-allocation */ - if (cmsdigcx->digcnt >= (int)((INT_MAX/(MAX(sizeof(CSSM_DATA_PTR),sizeof(CSSM_DATA))))-1)) { + if (cmsdigcx->digcnt >= (int)((INT_MAX/(MAX(sizeof(SecAsn1Item *),sizeof(SecAsn1Item))))-1)) { goto loser; } - /* allocate digest array & CSSM_DATAs on arena */ - digests = (CSSM_DATA_PTR *)PORT_ArenaAlloc((PLArenaPool *)poolp, (cmsdigcx->digcnt+1) * sizeof(CSSM_DATA_PTR)); - digest = (CSSM_DATA_PTR)PORT_ArenaZAlloc((PLArenaPool *)poolp, cmsdigcx->digcnt * sizeof(CSSM_DATA)); + /* allocate digest array & SecAsn1Items on arena */ + digests = (SecAsn1Item * *)PORT_ArenaZAlloc((PLArenaPool *)poolp, (cmsdigcx->digcnt+1) * sizeof(SecAsn1Item *)); + digest = (SecAsn1Item *)PORT_ArenaZAlloc((PLArenaPool *)poolp, cmsdigcx->digcnt * sizeof(SecAsn1Item)); if (digests == NULL || digest == NULL) { - goto loser; + goto loser; } for (i = 0; i < cmsdigcx->digcnt; i++, digest++) { - if (cmsdigcx->digobjs) { - digobj = cmsdigcx->digobjs[i]; - } else { - digobj = 0; + SECOidTag hash_alg = SECOID_GetAlgorithmTag(cmsdigcx->digestalgs[i]); + int diglength = 0; + + switch (hash_alg) { + case SEC_OID_SHA1: diglength = CC_SHA1_DIGEST_LENGTH; break; + case SEC_OID_MD5: diglength = CC_MD5_DIGEST_LENGTH; break; + case SEC_OID_SHA224: diglength = CC_SHA224_DIGEST_LENGTH; break; + case SEC_OID_SHA256: diglength = CC_SHA256_DIGEST_LENGTH; break; + case SEC_OID_SHA384: diglength = CC_SHA384_DIGEST_LENGTH; break; + case SEC_OID_SHA512: diglength = CC_SHA512_DIGEST_LENGTH; break; + default: goto loser; } - CSSM_QUERY_SIZE_DATA dataSize; - rv = CSSM_QuerySize(digobj, CSSM_FALSE, 1, &dataSize); - if (rv != CSSM_OK) - { - goto loser; - } - - int diglength = dataSize.SizeOutputBlock; - - if (digobj) - { - digest->Data = (unsigned char*)PORT_ArenaAlloc((PLArenaPool *)poolp, diglength); - if (digest->Data == NULL) - goto loser; - digest->Length = diglength; - rv = CSSM_DigestDataFinal(digobj, digest); - if (rv != CSSM_OK) - { + digobj = cmsdigcx->digobjs[i]; + if (digobj) { + digest->Data = (unsigned char*)PORT_ArenaAlloc((PLArenaPool *)poolp, diglength); + if (digest->Data == NULL) goto loser; + digest->Length = diglength; + switch (hash_alg) { + case SEC_OID_SHA1: CC_SHA1_Final(digest->Data, digobj); break; + case SEC_OID_MD5: CC_MD5_Final(digest->Data, digobj); break; + case SEC_OID_SHA224: CC_SHA224_Final(digest->Data, digobj); break; + case SEC_OID_SHA256: CC_SHA256_Final(digest->Data, digobj); break; + case SEC_OID_SHA384: CC_SHA384_Final(digest->Data, digobj); break; + case SEC_OID_SHA512: CC_SHA512_Final(digest->Data, digobj); break; + default: goto loser; } - - CSSM_DeleteContext(digobj); - cmsdigcx->digobjs[i] = 0; - } - else - { - digest->Data = NULL; - digest->Length = 0; - } - - digests[i] = digest; - } + + free(digobj); + digests[i] = digest; + } else { + digest->Data = NULL; + digest->Length = 0; + } + } digests[i] = NULL; *digestsp = digests; rv = SECSuccess; loser: - if (rv == SECSuccess) - PORT_ArenaUnmark((PLArenaPool *)poolp, mark); - else - PORT_ArenaRelease((PLArenaPool *)poolp, mark); + if (rv == SECSuccess) { + PORT_ArenaUnmark((PLArenaPool *)poolp, mark); + } else { + PORT_ArenaRelease((PLArenaPool *)poolp, mark); + } cleanup: - if (cmsdigcx->digcnt > 0) { - SecCmsDigestContextCancel(cmsdigcx); - PORT_Free(cmsdigcx->digobjs); - cmsdigcx->digobjs = NULL; - cmsdigcx->digcnt = 0; - } - PORT_Free(cmsdigcx); + cmsdigcx->digcnt = 0; // We've already freed the digests above + SecCmsDigestContextCancel(cmsdigcx); return rv; } @@ -277,28 +327,30 @@ cleanup: */ OSStatus SecCmsDigestContextFinishSingle(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef poolp, - CSSM_DATA_PTR digest) + SecAsn1Item * digest) { OSStatus rv = SECFailure; - CSSM_DATA_PTR *dp; + SecAsn1Item **dp; PLArenaPool *arena = NULL; if ((arena = PORT_NewArena(1024)) == NULL) goto loser; /* get the digests into arena, then copy the first digest into poolp */ - if (SecCmsDigestContextFinishMultiple(cmsdigcx, (SecArenaPoolRef)arena, &dp) != SECSuccess) - goto loser; + if (SecCmsDigestContextFinishMultiple(cmsdigcx, (SecArenaPoolRef)arena, &dp) != SECSuccess) { + goto loser; + } /* now copy it into poolp */ - if (SECITEM_CopyItem((PLArenaPool *)poolp, digest, dp[0]) != SECSuccess) - goto loser; + if (SECITEM_CopyItem((PLArenaPool *)poolp, digest, dp[0]) != SECSuccess) { + goto loser; + } rv = SECSuccess; loser: - if (arena) - PORT_FreeArena(arena, PR_FALSE); - + if (arena) { + PORT_FreeArena(arena, PR_FALSE); + } return rv; } diff --git a/OSX/libsecurity_smime/lib/cmsencode.c b/OSX/libsecurity_smime/lib/cmsencode.c index f49e4454..04d20168 100644 --- a/OSX/libsecurity_smime/lib/cmsencode.c +++ b/OSX/libsecurity_smime/lib/cmsencode.c @@ -47,7 +47,7 @@ #include #include -#include +#include struct nss_cms_encoder_output { SecCmsContentCallback outputfn; diff --git a/OSX/libsecurity_smime/lib/cmspriv.h b/OSX/libsecurity_smime/lib/cmspriv.h index 5e41d83e..cd7220b6 100644 --- a/OSX/libsecurity_smime/lib/cmspriv.h +++ b/OSX/libsecurity_smime/lib/cmspriv.h @@ -95,7 +95,7 @@ SecCmsAlgArrayGetIndexByAlgID(SECAlgorithmID **algorithmArray, SECAlgorithmID *a extern int SecCmsAlgArrayGetIndexByAlgTag(SECAlgorithmID **algorithmArray, SECOidTag algtag); -extern CSSM_CC_HANDLE +extern void * SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid); /* diff --git a/OSX/libsecurity_smime/lib/cmspubkey.c b/OSX/libsecurity_smime/lib/cmspubkey.c index 636dd040..04a12859 100644 --- a/OSX/libsecurity_smime/lib/cmspubkey.c +++ b/OSX/libsecurity_smime/lib/cmspubkey.c @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_smime/lib/cmssiginfo.c b/OSX/libsecurity_smime/lib/cmssiginfo.c index 40f3f4c9..c3cd380b 100644 --- a/OSX/libsecurity_smime/lib/cmssiginfo.c +++ b/OSX/libsecurity_smime/lib/cmssiginfo.c @@ -55,7 +55,7 @@ #include #include #include -#include +#include #include #include #include @@ -456,24 +456,22 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_ SECITEM_FreeItem(&signature, PR_FALSE); - if(pubkAlgTag == SEC_OID_EC_PUBLIC_KEY) { - /* - * RFC 3278 section section 2.1.1 states that the signatureAlgorithm - * field contains the full ecdsa-with-SHA1 OID, not plain old ecPublicKey - * as would appear in other forms of signed datas. However Microsoft doesn't - * do this, it puts ecPublicKey there, and if we put ecdsa-with-SHA1 there, - * MS can't verify - presumably because it takes the digest of the digest - * before feeding it to ECDSA. - * We handle this with a preference; default if it's not there is - * "Microsoft compatibility mode". - */ - if(!SecCmsMsEcdsaCompatMode()) { - pubkAlgTag = SEC_OID_ECDSA_WithSHA1; - } - /* else violating the spec for compatibility */ + SECOidTag sigAlgTag = SecCmsUtilMakeSignatureAlgorithm(digestalgtag, pubkAlgTag); + if(pubkAlgTag == SEC_OID_EC_PUBLIC_KEY && SecCmsMsEcdsaCompatMode()) { + /* + * RFC 3278 section section 2.1.1 states that the signatureAlgorithm + * field contains the full ecdsa-with-SHA1 OID, not plain old ecPublicKey + * as would appear in other forms of signed datas. However Microsoft doesn't + * do this, it puts ecPublicKey there, and if we put ecdsa-with-SHA1 there, + * MS can't verify - presumably because it takes the digest of the digest + * before feeding it to ECDSA. + * We handle this with a preference; default if it's not there is + * "Microsoft compatibility mode". + */ + sigAlgTag = SEC_OID_EC_PUBLIC_KEY; } - if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), pubkAlgTag, + if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), sigAlgTag, NULL) != SECSuccess) goto loser; @@ -599,16 +597,6 @@ SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeSt digestAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestAlg)); digestEncAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)); - /* - * Gross hack necessitated by RFC 3278 section 2.1.1, which states - * that the signature algorithm (here, digestEncAlg) contains ecdsa_with-SHA1, - * *not* (as in all other algorithms) the raw signature algorithm, e.g. - * pkcs1RSAEncryption. - */ - if(digestEncAlgTag == SEC_OID_ECDSA_WithSHA1) { - digestEncAlgTag = SEC_OID_EC_PUBLIC_KEY; - } - if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr)) { if (contentType) { /* @@ -1182,12 +1170,19 @@ SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo) SecCertificateRef signercert; CFStringRef emailAddress = NULL; - if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) - return NULL; + if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) { + return NULL; + } - SecCertificateGetEmailAddress(signercert, &emailAddress); - - return CFRetainSafe(emailAddress); + CFArrayRef names = SecCertificateCopyRFC822Names(signercert); + if (names) { + if (CFArrayGetCount(names) > 0) { + emailAddress = (CFStringRef)CFArrayGetValueAtIndex(names, 0); + } + CFRetainSafe(emailAddress); + CFRelease(names); + } + return emailAddress; } diff --git a/OSX/libsecurity_smime/lib/cmsutil.c b/OSX/libsecurity_smime/lib/cmsutil.c index 6f3f4364..f07f98e4 100644 --- a/OSX/libsecurity_smime/lib/cmsutil.c +++ b/OSX/libsecurity_smime/lib/cmsutil.c @@ -47,7 +47,8 @@ #include #include #include -#include +#include +#include /* @@ -213,21 +214,42 @@ SecCmsAlgArrayGetIndexByAlgTag(SECAlgorithmID **algorithmArray, return i; } -CSSM_CC_HANDLE +void * SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid) { SECOidData *oidData = SECOID_FindOID(&(algid->algorithm)); if (oidData) { - CSSM_ALGORITHMS alg = oidData->cssmAlgorithm; - if (alg) - { - CSSM_CC_HANDLE digobj; - CSSM_CSP_HANDLE cspHandle = SecCspHandleForAlgorithm(alg); - - if (!CSSM_CSP_CreateDigestContext(cspHandle, alg, &digobj)) - return digobj; - } + void *digobj = NULL; + switch (oidData->offset) { + case SEC_OID_SHA1: + digobj = calloc(1, sizeof(CC_SHA1_CTX)); + CC_SHA1_Init(digobj); + break; + case SEC_OID_MD5: + digobj = calloc(1, sizeof(CC_MD5_CTX)); + CC_MD5_Init(digobj); + break; + case SEC_OID_SHA224: + digobj = calloc(1, sizeof(CC_SHA256_CTX)); + CC_SHA224_Init(digobj); + break; + case SEC_OID_SHA256: + digobj = calloc(1, sizeof(CC_SHA256_CTX)); + CC_SHA256_Init(digobj); + break; + case SEC_OID_SHA384: + digobj = calloc(1, sizeof(CC_SHA512_CTX)); + CC_SHA384_Init(digobj); + break; + case SEC_OID_SHA512: + digobj = calloc(1, sizeof(CC_SHA512_CTX)); + CC_SHA512_Init(digobj); + break; + default: + break; + } + return digobj; } return 0; diff --git a/OSX/libsecurity_smime/lib/testcms b/OSX/libsecurity_smime/lib/testcms old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_smime/lib/tsaSupport.c b/OSX/libsecurity_smime/lib/tsaSupport.c index d58eb057..85711fd1 100644 --- a/OSX/libsecurity_smime/lib/tsaSupport.c +++ b/OSX/libsecurity_smime/lib/tsaSupport.c @@ -31,7 +31,7 @@ */ #include -#include +#include #include #include @@ -1158,9 +1158,10 @@ static OSStatus impExpImportCertUnCommon( } xit: - if (certRef) + if (certRef) { CFRelease(certRef); - return status; + } + return status; } static void saveTSACertificates(CSSM_DATA **signingCerts, CFMutableArrayRef outArray) diff --git a/OSX/libsecurity_smime/lib/tsaTemplates.c b/OSX/libsecurity_smime/lib/tsaTemplates.c index 342d0341..6e627be2 100644 --- a/OSX/libsecurity_smime/lib/tsaTemplates.c +++ b/OSX/libsecurity_smime/lib/tsaTemplates.c @@ -26,7 +26,6 @@ #include /* for kSecAsn1AlgorithmIDTemplate */ #include #include -#include #include "tsaTemplates.h" #include "cmslocal.h" diff --git a/OSX/libsecurity_smime/regressions/cms-01-basic.c b/OSX/libsecurity_smime/regressions/cms-01-basic.c index 7af821b7..79816473 100644 --- a/OSX/libsecurity_smime/regressions/cms-01-basic.c +++ b/OSX/libsecurity_smime/regressions/cms-01-basic.c @@ -102,12 +102,12 @@ out: } #define kNumberCleanupTests 1 -static void cleanup_keychain(SecKeychainRef keychain, SecIdentityRef identity, SecCertificateRef cert) { +static void cleanup_keychain(SecKeychainRef* keychain, SecIdentityRef* identity, SecCertificateRef* cert) { /* Delete keychain - from the search list and from disk */ - ok_status(SecKeychainDelete(keychain), "Delete temporary keychain"); - CFReleaseNull(keychain); - CFReleaseNull(cert); - CFReleaseNull(identity); + ok_status(SecKeychainDelete(*keychain), "Delete temporary keychain"); + CFReleaseNull(*keychain); + CFReleaseNull(*cert); + CFReleaseNull(*identity); } static OSStatus sign_please(SecIdentityRef identity, SECOidTag digestAlgTag, bool withAttrs, uint8_t *expected_output, size_t expected_len) { @@ -370,7 +370,7 @@ static void sign_tests(SecIdentityRef identity, bool isRSA) { is(sign_please(identity, SEC_OID_SHA1, false, (isRSA) ? rsa_sha1 : NULL, (isRSA) ? sizeof(rsa_sha1) : 0), errSecSuccess, "Signed with SHA-1"); - is(sign_please(identity, SEC_OID_SHA256, false, (isRSA) ? rsa_sha256 : NULL, + is(sign_please(identity, SEC_OID_SHA256, false, (isRSA) ? new_sig_alg_rsa_sha256 : NULL, (isRSA) ? sizeof(rsa_sha256) : 0), errSecSuccess, "Signed with SHA-256"); is(sign_please(identity, SEC_OID_SHA384, false, NULL, 0), errSecSuccess, "Signed with SHA-384"); @@ -494,7 +494,7 @@ int cms_01_basic(int argc, char *const *argv) verify_tests(kc, true); encrypt_tests(certificate); decrypt_tests(true); - cleanup_keychain(kc, identity, certificate); + cleanup_keychain(&kc, &identity, &certificate); /* EC tests */ kc = setup_keychain(_ec_identity, sizeof(_ec_identity), &identity, &certificate); @@ -502,7 +502,7 @@ int cms_01_basic(int argc, char *const *argv) verify_tests(kc, false); encrypt_tests(certificate); decrypt_tests(false); - cleanup_keychain(kc, identity, certificate); + cleanup_keychain(&kc, &identity, &certificate); return 0; } diff --git a/OSX/libsecurity_smime/regressions/cms-01-basic.h b/OSX/libsecurity_smime/regressions/cms-01-basic.h index 371b8f69..c7ad36b9 100644 --- a/OSX/libsecurity_smime/regressions/cms-01-basic.h +++ b/OSX/libsecurity_smime/regressions/cms-01-basic.h @@ -465,7 +465,7 @@ unsigned char rsa_sha1[] = { 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, - 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, + 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x29, 0xbb, 0xc2, 0xc1, 0x17, 0xb9, 0x7d, 0x8b, 0x43, 0xc6, 0x25, 0xad, 0xf1, 0xae, 0xb6, 0x26, 0x78, 0x9c, 0x92, 0x47, 0x77, 0xf8, 0xac, 0x53, 0xca, 0x17, 0x58, 0x4a, 0x8d, 0x66, 0x44, 0x99, 0x14, 0x3f, 0x63, 0x98, 0x3a, 0x7c, 0xe6, 0x65, 0xf0, 0x2a, 0x5e, 0x49, 0xbe, 0xdd, 0x40, 0x6e, 0x21, 0x43, 0xe1, 0xb9, 0x13, 0xa8, 0x31, 0xbf, 0x12, 0xb2, 0x78, 0x97, @@ -565,6 +565,89 @@ unsigned char rsa_sha256[] = { 0x45, 0xc2, 0x99, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +unsigned char new_sig_alg_rsa_sha256[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x80, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, + 0x41, 0x69, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0x82, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, + 0x00, 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, + 0x53, 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, + 0x34, 0x30, 0x30, 0x31, 0x38, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x38, + 0x32, 0x39, 0x5a, 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, + 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, + 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x9b, 0xcb, 0x6c, 0x77, 0xb7, 0xd1, 0x05, 0xa0, 0xae, 0x86, 0x20, 0x45, 0xd3, + 0xf4, 0x24, 0x8d, 0x25, 0x34, 0x31, 0xa9, 0xe2, 0x10, 0x36, 0xf5, 0x0a, 0x0b, 0x90, 0x4a, 0xa5, 0x6b, 0x5c, 0x16, 0xcd, + 0xb0, 0x72, 0xe9, 0xa9, 0x80, 0x5f, 0x6d, 0xb2, 0x4d, 0xd9, 0x58, 0x16, 0x9f, 0x68, 0x81, 0x9a, 0x6b, 0xeb, 0xd5, 0x4b, + 0xf7, 0x7d, 0x59, 0xe9, 0x46, 0x2b, 0x5b, 0x8f, 0xe4, 0xec, 0xab, 0x5c, 0x07, 0x74, 0xa2, 0x0e, 0x59, 0xbb, 0xfc, 0xd3, + 0xcf, 0xf7, 0x21, 0x88, 0x6c, 0x88, 0xd9, 0x6b, 0xa3, 0xa3, 0x4e, 0x5b, 0xd1, 0x1c, 0xfb, 0x04, 0xf5, 0xb2, 0x12, 0x0e, + 0x54, 0x59, 0x4d, 0xce, 0x0a, 0xe0, 0x26, 0x24, 0x06, 0xeb, 0xc8, 0xa2, 0xc6, 0x41, 0x28, 0xf9, 0x79, 0xe4, 0xb1, 0x4e, + 0x00, 0x6f, 0x6e, 0xf8, 0x96, 0x9e, 0x45, 0x28, 0x70, 0xec, 0xc7, 0xdc, 0xa2, 0xdd, 0x92, 0xab, 0xdd, 0x6f, 0xd8, 0x57, + 0xba, 0xcc, 0x29, 0xbe, 0xb7, 0x00, 0x1e, 0x8d, 0x13, 0x3f, 0x47, 0x34, 0x3c, 0xd0, 0xc6, 0xc8, 0x17, 0xdf, 0x74, 0x8a, + 0xb1, 0xc3, 0x68, 0xd5, 0xba, 0x76, 0x60, 0x55, 0x5f, 0x8d, 0xfa, 0xbd, 0xe7, 0x11, 0x9e, 0x59, 0x96, 0xe5, 0x93, 0x70, + 0xad, 0x41, 0xfb, 0x61, 0x46, 0x70, 0xc4, 0x05, 0x12, 0x23, 0x23, 0xc0, 0x9d, 0xc8, 0xc5, 0xf5, 0x96, 0xe5, 0x48, 0x10, + 0x86, 0x8a, 0x1e, 0x3b, 0x83, 0xd1, 0x47, 0x3a, 0x27, 0x00, 0x71, 0x10, 0xa3, 0x52, 0xba, 0xae, 0x01, 0x43, 0x87, 0x9c, + 0x6a, 0x1b, 0xea, 0x1a, 0x44, 0x4f, 0x4a, 0xac, 0xd4, 0x82, 0x55, 0xee, 0x1f, 0x25, 0x9c, 0x55, 0xca, 0xd2, 0xd0, 0x3a, + 0x0b, 0x70, 0x90, 0x60, 0x49, 0x47, 0x02, 0xfd, 0x89, 0x2c, 0x9a, 0x26, 0x36, 0x34, 0x8f, 0x24, 0x39, 0x8c, 0xe9, 0xa2, + 0x52, 0x8f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, + 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4c, 0xed, 0x5b, 0xaf, 0x13, 0x16, 0x5d, 0xe2, 0xdd, 0x5c, 0x48, 0x1c, + 0xd5, 0x6e, 0x8b, 0x04, 0x51, 0xd6, 0x38, 0x80, 0xfd, 0x52, 0x4a, 0x34, 0xdc, 0x13, 0x35, 0x6e, 0x64, 0x39, 0x39, 0x39, + 0x09, 0xa7, 0x6c, 0x2d, 0x39, 0xf2, 0x04, 0x21, 0xe3, 0xea, 0x8f, 0xf8, 0xbe, 0x46, 0x0e, 0x20, 0x82, 0xd0, 0xc5, 0x60, + 0xbf, 0x57, 0x6f, 0xd8, 0x29, 0xb4, 0x66, 0xdb, 0xbf, 0x92, 0xc9, 0xdc, 0x90, 0x97, 0x0f, 0x2f, 0x59, 0xa0, 0x13, 0xf3, + 0xa4, 0xca, 0xde, 0x3f, 0x80, 0x2a, 0x99, 0xb4, 0xee, 0x71, 0xc3, 0x56, 0x71, 0x51, 0x37, 0x55, 0xa1, 0x60, 0x89, 0xab, + 0x94, 0x0e, 0xb9, 0x70, 0xa5, 0x55, 0xf3, 0x1a, 0x87, 0xa4, 0x41, 0x4c, 0x45, 0xba, 0xb6, 0x56, 0xd6, 0x45, 0x56, 0x12, + 0x60, 0xe5, 0x91, 0xec, 0xf7, 0xbe, 0x39, 0xa4, 0x80, 0x08, 0x9f, 0xea, 0x17, 0x12, 0x0e, 0xa6, 0xe6, 0xef, 0x09, 0xf7, + 0x61, 0x51, 0x57, 0x73, 0xe3, 0x57, 0x88, 0xd7, 0xf8, 0x5f, 0xaf, 0x5d, 0xaf, 0x88, 0x32, 0xb4, 0x09, 0x3e, 0x7c, 0x25, + 0x77, 0x35, 0xe9, 0x3e, 0x6e, 0x0a, 0xb9, 0xb4, 0xa3, 0x06, 0x07, 0x0f, 0x7e, 0x93, 0x26, 0x16, 0x38, 0x1e, 0x4e, 0x72, + 0xaf, 0x06, 0x44, 0x1e, 0x8d, 0x96, 0xa6, 0x15, 0x9c, 0x82, 0x6d, 0x71, 0x99, 0x84, 0x8d, 0x12, 0x46, 0xf2, 0xbb, 0xa7, + 0x63, 0x7a, 0x32, 0xda, 0xa9, 0xde, 0xb6, 0x34, 0x14, 0xfb, 0x07, 0x0c, 0xab, 0x3b, 0x0a, 0xa1, 0x8b, 0xda, 0x15, 0xb3, + 0x63, 0xf3, 0x5c, 0x45, 0x2f, 0x0b, 0x6e, 0xc7, 0x27, 0x72, 0xc1, 0x37, 0x56, 0x30, 0xe3, 0x26, 0xbb, 0x19, 0x4f, 0x91, + 0xa1, 0xd0, 0x30, 0x29, 0x5b, 0x79, 0x79, 0x5c, 0xe6, 0x4f, 0xed, 0xcf, 0x81, 0xb2, 0x50, 0x35, 0x96, 0x23, 0xb2, 0x9f, + 0xca, 0x3f, 0xb5, 0x54, 0x31, 0x82, 0x01, 0xdc, 0x30, 0x82, 0x01, 0xd8, 0x02, 0x01, 0x01, 0x30, 0x81, 0xb0, 0x30, 0x81, + 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0b, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xc9, 0x25, 0xbe, 0xb8, 0xf2, 0x2c, 0x7f, 0xc8, 0x3a, 0xc3, 0xc2, 0x4b, + 0xac, 0x54, 0xcf, 0xa6, 0x75, 0xaa, 0xeb, 0x40, 0x68, 0xee, 0xe2, 0xb1, 0xa8, 0x70, 0x9e, 0xe9, 0x8b, 0xf1, 0x0a, 0x85, + 0x88, 0x40, 0xef, 0xb8, 0xa5, 0x04, 0x87, 0x63, 0x03, 0xf5, 0x41, 0x81, 0x29, 0x42, 0x7f, 0x31, 0x8f, 0x5b, 0xde, 0xe8, + 0x15, 0xc1, 0xa3, 0x45, 0xf1, 0xbc, 0xff, 0x81, 0x58, 0xbd, 0xac, 0x4c, 0xa5, 0xb3, 0x30, 0x9a, 0xb8, 0x9e, 0x69, 0x10, + 0xad, 0x44, 0x7b, 0x93, 0x28, 0xba, 0xca, 0x6f, 0x2e, 0xf8, 0x1b, 0x03, 0xc2, 0x0a, 0x4a, 0x06, 0x32, 0x4d, 0x30, 0x50, + 0xb7, 0x9c, 0x57, 0x4d, 0x4b, 0x6c, 0x34, 0x53, 0xd8, 0xf5, 0xca, 0x91, 0xa5, 0xdf, 0xa6, 0x67, 0x0a, 0x2e, 0x02, 0x47, + 0x1c, 0x1c, 0xd6, 0x2b, 0xe2, 0x85, 0xc1, 0xda, 0x79, 0xa2, 0xe2, 0x1e, 0xf8, 0x5e, 0xf9, 0x76, 0x55, 0xaf, 0x61, 0xaf, + 0xde, 0x0a, 0x7b, 0xeb, 0xa1, 0xa8, 0xc6, 0xef, 0x76, 0x2f, 0x50, 0xd1, 0x0a, 0xce, 0xdb, 0x14, 0xc3, 0x13, 0x72, 0xe5, + 0x26, 0x67, 0x90, 0x19, 0x15, 0x7b, 0x79, 0x05, 0xeb, 0x20, 0xb3, 0x5a, 0x4e, 0x78, 0xae, 0x2d, 0x9c, 0xd1, 0x31, 0xfd, + 0x2e, 0xcb, 0x84, 0xb9, 0x67, 0xea, 0xaf, 0xb3, 0xc2, 0x5f, 0xf5, 0xcd, 0x7b, 0x66, 0x3f, 0xdf, 0xf7, 0xe7, 0x76, 0x46, + 0x57, 0xd9, 0xee, 0x4b, 0xb2, 0xc8, 0x7b, 0xf9, 0x88, 0xab, 0x8e, 0xca, 0xfc, 0x39, 0xd1, 0x8e, 0x1c, 0xba, 0x3e, 0x63, + 0xb7, 0xe8, 0x0e, 0x2f, 0xde, 0x6b, 0x76, 0x81, 0xbf, 0x78, 0x26, 0x0c, 0xa0, 0x2c, 0x35, 0x21, 0xde, 0xb4, 0x45, 0x0a, + 0x84, 0xea, 0x68, 0xa5, 0x37, 0xe8, 0x4a, 0xbc, 0xa6, 0xcf, 0x24, 0x85, 0x46, 0x33, 0x9e, 0xd9, 0xba, 0x58, 0x75, 0xd7, + 0x45, 0xc2, 0x99, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + /* * MARK: RSA-signed messages (with attributes) */ @@ -726,7 +809,7 @@ unsigned char rsa_sha1_attr[] = { 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x38, 0x31, 0x33, 0x32, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0xef, 0x53, 0x0b, 0xfa, 0xcf, 0x34, 0x18, 0xb3, 0x30, 0xff, 0xf8, 0x9e, 0x09, 0xb3, 0xb6, 0x21, 0xd6, 0x83, 0xb9, 0xe9, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x52, 0xbd, 0xa1, 0x0a, 0x41, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x52, 0xbd, 0xa1, 0x0a, 0x41, 0xce, 0xc1, 0xe8, 0xe8, 0x2f, 0x2e, 0x1f, 0x73, 0xd1, 0x2f, 0x2e, 0x53, 0x53, 0x21, 0xec, 0x88, 0x30, 0x6a, 0x9d, 0x58, 0x64, 0x95, 0xef, 0xf2, 0x20, 0x55, 0xb0, 0x15, 0x64, 0x02, 0x1d, 0xf9, 0x44, 0xdd, 0xcb, 0x7a, 0x9c, 0x50, 0x10, 0xea, 0xfa, 0x6f, 0x07, 0x64, 0xaf, 0x30, 0x6e, 0xe2, 0xc1, 0x34, 0x55, 0xd0, 0x6a, 0x6e, 0xe1, 0x09, 0x91, 0xb7, 0xe3, 0x7b, @@ -814,7 +897,7 @@ unsigned char rsa_sha256_attr[] = { 0x31, 0x33, 0x32, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x33, 0x1f, 0x3a, 0xc4, 0x95, 0x97, 0x64, 0x1c, 0x99, 0x9b, 0x37, 0xc8, 0xf2, 0xba, 0xd0, 0xb4, 0x38, 0xa5, 0x9c, 0x3a, 0xa3, 0x78, 0xf9, 0xfb, 0x66, 0x28, 0x4e, 0x6a, 0x90, 0xcc, 0x0e, 0x4c, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xae, 0x6d, 0xa9, 0xa7, 0xee, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xae, 0x6d, 0xa9, 0xa7, 0xee, 0x0c, 0x94, 0x1b, 0xf3, 0x93, 0x40, 0x43, 0x11, 0x41, 0x20, 0x11, 0x60, 0xd9, 0x4e, 0xb6, 0x2d, 0x3e, 0x98, 0xfe, 0x06, 0xd2, 0xc4, 0xe4, 0x0a, 0x66, 0xdc, 0xbb, 0xbd, 0x4d, 0x8e, 0xcb, 0xe1, 0x87, 0x39, 0x3f, 0xb3, 0x4b, 0xf8, 0xe7, 0x18, 0x6f, 0x39, 0xad, 0x01, 0xd4, 0xe8, 0x85, 0x8c, 0x84, 0x96, 0x2c, 0x3a, 0xd4, 0xcf, 0x3c, 0xe5, 0x05, 0xdd, 0xc7, 0xc0, diff --git a/OSX/libsecurity_ssl/Security b/OSX/libsecurity_ssl/Security deleted file mode 120000 index 7951405f..00000000 --- a/OSX/libsecurity_ssl/Security +++ /dev/null @@ -1 +0,0 @@ -lib \ No newline at end of file diff --git a/OSX/libsecurity_ssl/lib/CipherSuite.h b/OSX/libsecurity_ssl/lib/CipherSuite.h index 0a4ac115..a4e737ff 100644 --- a/OSX/libsecurity_ssl/lib/CipherSuite.h +++ b/OSX/libsecurity_ssl/lib/CipherSuite.h @@ -36,7 +36,7 @@ * Defined as enum for debugging, but in the protocol * it is actually exactly two bytes */ -#if TARGET_OS_IPHONE && !TARGET_OS_IOSMAC +#if ((TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST) || (TARGET_OS_OSX && TARGET_CPU_ARM64)) /* 16-bit value on iOS */ typedef uint16_t SSLCipherSuite; #else diff --git a/OSX/libsecurity_ssl/lib/SSLRecordInternal.c b/OSX/libsecurity_ssl/lib/SSLRecordInternal.c index 8da7af2a..28cf1a6b 100644 --- a/OSX/libsecurity_ssl/lib/SSLRecordInternal.c +++ b/OSX/libsecurity_ssl/lib/SSLRecordInternal.c @@ -330,8 +330,8 @@ SSLRecordSetOption(SSLRecordContextRef ref, SSLRecordOption option, bool value) /***** Internal Record Layer APIs *****/ -#include -#define CCRNGSTATE ccDRBGGetRngState() +#include +#define CCRNGSTATE ccrng(NULL) SSLRecordContextRef SSLCreateInternalRecordLayer(SSLContextRef sslCtx) diff --git a/OSX/libsecurity_ssl/lib/SecureTransportPriv.h b/OSX/libsecurity_ssl/lib/SecureTransportPriv.h index f7a6c5f9..34e7521a 100644 --- a/OSX/libsecurity_ssl/lib/SecureTransportPriv.h +++ b/OSX/libsecurity_ssl/lib/SecureTransportPriv.h @@ -516,7 +516,7 @@ OSStatus SSLGetDHEEnabled(SSLContextRef ctx, bool *enabled); OSStatus _SSLSetProtocolVersionEnabled (SSLContextRef context, SSLProtocol protocol, - Boolean enable) API_UNAVAILABLE(iosmac); + Boolean enable) API_UNAVAILABLE(macCatalyst); /* * Obtain a value specified in SSLSetProtocolVersionEnabled. @@ -526,7 +526,7 @@ _SSLSetProtocolVersionEnabled (SSLContextRef context, OSStatus _SSLGetProtocolVersionEnabled(SSLContextRef context, SSLProtocol protocol, - Boolean *enable) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *enable) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Get/set SSL protocol version; optional. Default is kSSLProtocolUnknown, @@ -541,7 +541,7 @@ _SSLGetProtocolVersionEnabled(SSLContextRef context, */ OSStatus _SSLSetProtocolVersion (SSLContextRef context, - SSLProtocol version) API_UNAVAILABLE(iosmac); + SSLProtocol version) API_UNAVAILABLE(macCatalyst); /* * Obtain the protocol version specified in SSLSetProtocolVersion. @@ -555,7 +555,7 @@ _SSLSetProtocolVersion (SSLContextRef context, */ OSStatus _SSLGetProtocolVersion (SSLContextRef context, - SSLProtocol *protocol) API_UNAVAILABLE(iosmac); /* RETURNED */ + SSLProtocol *protocol) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* API REVIEW: The following 15 calls were used to change the behaviour of the trust @@ -573,11 +573,11 @@ _SSLGetProtocolVersion (SSLContextRef context, */ OSStatus _SSLSetEnableCertVerify (SSLContextRef context, - Boolean enableVerify) API_UNAVAILABLE(iosmac); + Boolean enableVerify) API_UNAVAILABLE(macCatalyst); OSStatus _SSLGetEnableCertVerify (SSLContextRef context, - Boolean *enableVerify) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *enableVerify) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Specify the option of ignoring certificates' "expired" times. @@ -587,14 +587,14 @@ _SSLGetEnableCertVerify (SSLContextRef context, */ OSStatus _SSLSetAllowsExpiredCerts (SSLContextRef context, - Boolean allowsExpired) API_UNAVAILABLE(iosmac); + Boolean allowsExpired) API_UNAVAILABLE(macCatalyst); /* * Obtain the current value of an SSLContext's "allowExpiredCerts" flag. */ OSStatus _SSLGetAllowsExpiredCerts (SSLContextRef context, - Boolean *allowsExpired) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *allowsExpired) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Similar to SSLSetAllowsExpiredCerts(), this function allows the @@ -604,11 +604,11 @@ _SSLGetAllowsExpiredCerts (SSLContextRef context, */ OSStatus _SSLSetAllowsExpiredRoots (SSLContextRef context, - Boolean allowsExpired) API_UNAVAILABLE(iosmac); + Boolean allowsExpired) API_UNAVAILABLE(macCatalyst); OSStatus _SSLGetAllowsExpiredRoots (SSLContextRef context, - Boolean *allowsExpired) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *allowsExpired) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Specify option of allowing for an unknown root cert, i.e., one which @@ -627,14 +627,14 @@ _SSLGetAllowsExpiredRoots (SSLContextRef context, */ OSStatus _SSLSetAllowsAnyRoot (SSLContextRef context, - Boolean anyRoot) API_UNAVAILABLE(iosmac); + Boolean anyRoot) API_UNAVAILABLE(macCatalyst); /* * Obtain the current value of an SSLContext's "allow any root" flag. */ OSStatus _SSLGetAllowsAnyRoot (SSLContextRef context, - Boolean *anyRoot) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *anyRoot) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Augment or replace the system's default trusted root certificate set @@ -651,7 +651,7 @@ _SSLGetAllowsAnyRoot (SSLContextRef context, OSStatus _SSLSetTrustedRoots (SSLContextRef context, CFArrayRef trustedRoots, - Boolean replaceExisting) API_UNAVAILABLE(iosmac); + Boolean replaceExisting) API_UNAVAILABLE(macCatalyst); /* * Obtain an array of SecCertificateRefs representing the current @@ -662,7 +662,7 @@ _SSLSetTrustedRoots (SSLContextRef context, */ OSStatus _SSLCopyTrustedRoots (SSLContextRef context, - CFArrayRef *trustedRoots) API_UNAVAILABLE(iosmac); /* RETURNED */ + CFArrayRef *trustedRoots) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Add a SecCertificateRef, or a CFArray of them, to a server's list @@ -680,7 +680,7 @@ _SSLCopyTrustedRoots (SSLContextRef context, OSStatus _SSLSetCertificateAuthorities(SSLContextRef context, CFTypeRef certificateOrArray, - Boolean replaceExisting) API_UNAVAILABLE(iosmac); + Boolean replaceExisting) API_UNAVAILABLE(macCatalyst); /* * Obtain the certificates specified in SSLSetCertificateAuthorities(), @@ -691,7 +691,7 @@ _SSLSetCertificateAuthorities(SSLContextRef context, OSStatus _SSLCopyCertificateAuthorities(SSLContextRef context, - CFArrayRef *certificates) API_UNAVAILABLE(iosmac); /* RETURNED */ + CFArrayRef *certificates) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Request peer certificates. Valid anytime, subsequent to @@ -716,7 +716,7 @@ _SSLCopyCertificateAuthorities(SSLContextRef context, */ OSStatus _SSLCopyPeerCertificates (SSLContextRef context, - CFArrayRef *certs) API_UNAVAILABLE(iosmac); /* RETURNED */ + CFArrayRef *certs) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Specify Diffie-Hellman parameters. Optional; if we are configured to allow @@ -726,7 +726,7 @@ _SSLCopyPeerCertificates (SSLContextRef context, */ OSStatus _SSLSetDiffieHellmanParams (SSLContextRef context, const void *dhParams, - size_t dhParamsLen) API_UNAVAILABLE(iosmac); + size_t dhParamsLen) API_UNAVAILABLE(macCatalyst); /* * Return parameter block specified in SSLSetDiffieHellmanParams. @@ -734,7 +734,7 @@ OSStatus _SSLSetDiffieHellmanParams (SSLContextRef context, */ OSStatus _SSLGetDiffieHellmanParams (SSLContextRef context, const void **dhParams, - size_t *dhParamsLen) API_UNAVAILABLE(iosmac); + size_t *dhParamsLen) API_UNAVAILABLE(macCatalyst); /* * Enable/Disable RSA blinding. This feature thwarts a known timing @@ -743,10 +743,10 @@ OSStatus _SSLGetDiffieHellmanParams (SSLContextRef context, * enabled. */ OSStatus _SSLSetRsaBlinding (SSLContextRef context, - Boolean blinding) API_UNAVAILABLE(iosmac); + Boolean blinding) API_UNAVAILABLE(macCatalyst); OSStatus _SSLGetRsaBlinding (SSLContextRef context, - Boolean *blinding) API_UNAVAILABLE(iosmac); + Boolean *blinding) API_UNAVAILABLE(macCatalyst); /* * Create a new SSL/TLS session context. @@ -754,14 +754,14 @@ OSStatus _SSLGetRsaBlinding (SSLContextRef context, */ OSStatus _SSLNewContext (Boolean isServer, - SSLContextRef *tlsContextPtr) API_UNAVAILABLE(iosmac); /* RETURNED */ + SSLContextRef *tlsContextPtr) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Dispose of an SSLContextRef. This is effectivly a CFRelease. * Deprecated. */ OSStatus -_SSLDisposeContext (SSLContextRef context) API_UNAVAILABLE(iosmac); +_SSLDisposeContext (SSLContextRef context) API_UNAVAILABLE(macCatalyst); /* We redefine the names of all SPIs to avoid collision with unavailable APIs */ #define SSLSetProtocolVersionEnabled _SSLSetProtocolVersionEnabled @@ -807,7 +807,7 @@ _SSLProtocolVersionToWireFormatValue (SSLProtocol protocol); */ OSStatus SSLNewDatagramContext (Boolean isServer, - SSLContextRef *dtlsContextPtr) API_UNAVAILABLE(iosmac); /* RETURNED */ + SSLContextRef *dtlsContextPtr) API_UNAVAILABLE(macCatalyst); /* RETURNED */ diff --git a/OSX/libsecurity_ssl/lib/sslCipherSpecs.c b/OSX/libsecurity_ssl/lib/sslCipherSpecs.c index 47588641..8633fbef 100644 --- a/OSX/libsecurity_ssl/lib/sslCipherSpecs.c +++ b/OSX/libsecurity_ssl/lib/sslCipherSpecs.c @@ -36,7 +36,6 @@ #include #include -#include #include #include diff --git a/OSX/libsecurity_ssl/lib/sslContext.c b/OSX/libsecurity_ssl/lib/sslContext.c index fc1826fe..26e01a85 100644 --- a/OSX/libsecurity_ssl/lib/sslContext.c +++ b/OSX/libsecurity_ssl/lib/sslContext.c @@ -2246,21 +2246,23 @@ SSLCopyPeerTrust( SSLContextRef ctx, SecTrustRef *trust) /* RETURNED */ { - OSStatus status = errSecSuccess; - if (ctx == NULL || trust == NULL) - return errSecParam; - - /* Create a SecTrustRef if this was a resumed session and we - didn't have one yet. */ - if (!ctx->peerSecTrust) { - status = sslCreateSecTrust(ctx, &ctx->peerSecTrust); + OSStatus status = errSecSuccess; + if (ctx == NULL || trust == NULL) { + return errSecParam; } - *trust = ctx->peerSecTrust; - if (ctx->peerSecTrust) - CFRetain(ctx->peerSecTrust); + /* Create a SecTrustRef if this was a resumed session and we + didn't have one yet. */ + if (!ctx->peerSecTrust) { + status = sslCreateSecTrust(ctx, &ctx->peerSecTrust); + } - return status; + *trust = ctx->peerSecTrust; + if (ctx->peerSecTrust) { + CFRetain(ctx->peerSecTrust); + } + + return status; } OSStatus SSLGetPeerSecTrust( diff --git a/OSX/libsecurity_ssl/lib/sslCrypto.c b/OSX/libsecurity_ssl/lib/sslCrypto.c index e26fff2f..bd4c071c 100644 --- a/OSX/libsecurity_ssl/lib/sslCrypto.c +++ b/OSX/libsecurity_ssl/lib/sslCrypto.c @@ -32,7 +32,7 @@ #include #include -#include +#include "utilities/simulatecrash_assert.h" #include #include diff --git a/OSX/libsecurity_ssl/lib/sslKeychain.c b/OSX/libsecurity_ssl/lib/sslKeychain.c index 387c34ab..9c4c997c 100644 --- a/OSX/libsecurity_ssl/lib/sslKeychain.c +++ b/OSX/libsecurity_ssl/lib/sslKeychain.c @@ -41,7 +41,7 @@ #include "sslDebug.h" #include "sslKeychain.h" #include -#include +#include "utilities/simulatecrash_assert.h" #include diff --git a/OSX/libsecurity_ssl/lib/sslRecord.c b/OSX/libsecurity_ssl/lib/sslRecord.c index d5ec8974..564b3614 100644 --- a/OSX/libsecurity_ssl/lib/sslRecord.c +++ b/OSX/libsecurity_ssl/lib/sslRecord.c @@ -34,7 +34,6 @@ #include "SSLRecordInternal.h" #include -#include #include diff --git a/OSX/libsecurity_ssl/lib/sslTransport.c b/OSX/libsecurity_ssl/lib/sslTransport.c index c22cf500..a56d10d7 100644 --- a/OSX/libsecurity_ssl/lib/sslTransport.c +++ b/OSX/libsecurity_ssl/lib/sslTransport.c @@ -32,11 +32,12 @@ #include "sslDebug.h" #include "sslCipherSpecs.h" -#include +#include #include #include #include +#import #include #include @@ -476,14 +477,12 @@ SSLHandshake(SSLContext *ctx) #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) -#include "SecADWrapper.h" - static void ad_log_SecureTransport_early_fail(long signature) { CFStringRef key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("com.apple.SecureTransport.early_fail.%ld"), signature); if (key) { - SecADAddValueForScalarKey(key, 1); + SecCoreAnalyticsSendValue(key, 1); CFRelease(key); } } diff --git a/OSX/libsecurity_ssl/lib/tlsCallbacks.c b/OSX/libsecurity_ssl/lib/tlsCallbacks.c index d17e73d4..13a2c8c7 100644 --- a/OSX/libsecurity_ssl/lib/tlsCallbacks.c +++ b/OSX/libsecurity_ssl/lib/tlsCallbacks.c @@ -35,6 +35,8 @@ #include #include +#include "utilities/simulatecrash_assert.h" + static int tls_handshake_write_callback(tls_handshake_ctx_t ctx, const SSLBuffer data, uint8_t content_type) { diff --git a/OSX/libsecurity_ssl/regressions/CreateCerts.sh b/OSX/libsecurity_ssl/regressions/CreateCerts.sh old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+falsestart.m b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+falsestart.m index 9eaa1ff7..11cd1447 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+falsestart.m +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+falsestart.m @@ -86,6 +86,7 @@ static int SocketConnect(const char *hostName, int port) int sock; int err; struct hostent *ent; + char **h_addr_list = NULL; if (hostName[0] >= '0' && hostName[0] <= '9') { host.s_addr = inet_addr(hostName); @@ -95,11 +96,14 @@ static int SocketConnect(const char *hostName, int port) printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno)); return -2; } - memcpy(&host, ent->h_addr, sizeof(struct in_addr)); + h_addr_list = malloc(sizeof(char *)); + memcpy(h_addr_list, ent->h_addr_list, sizeof(char *)); + memcpy(&host, h_addr_list[0], sizeof(struct in_addr)); } sock = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = host; + addr.sin_addr.s_addr = host.s_addr; + free(h_addr_list); addr.sin_port = htons((u_short)port); addr.sin_family = AF_INET; @@ -113,7 +117,6 @@ static int SocketConnect(const char *hostName, int port) /* make non blocking */ fcntl(sock, F_SETFL, O_NONBLOCK); - return sock; } diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sessionstate.m b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sessionstate.m index 441ae283..657402e8 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sessionstate.m +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sessionstate.m @@ -46,9 +46,8 @@ #define test_printf(x...) -/* extern struct ccrng_state *ccDRBGGetRngState(); */ -#include -#define CCRNGSTATE ccDRBGGetRngState() +#include +#define CCRNGSTATE ccrng(NULL) struct RecQueueItem { STAILQ_ENTRY(RecQueueItem) next; /* link to next queued entry or NULL */ diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+tls12.m b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+tls12.m index adaa8a98..9c20b57c 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+tls12.m +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+tls12.m @@ -100,6 +100,7 @@ static int SocketConnect(const char *hostName, int port) int sock; int err; struct hostent *ent; + char **h_addr_list = NULL; if (hostName[0] >= '0' && hostName[0] <= '9') { host.s_addr = inet_addr(hostName); @@ -109,11 +110,14 @@ static int SocketConnect(const char *hostName, int port) printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno)); return -2; } - memcpy(&host, ent->h_addr, sizeof(struct in_addr)); + h_addr_list = malloc(sizeof(char *)); + memcpy(h_addr_list, ent->h_addr_list, sizeof(char *)); + memcpy(&host, h_addr_list[0], sizeof(struct in_addr)); } sock = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = host; + addr.sin_addr.s_addr = host.s_addr; + free(h_addr_list); addr.sin_port = htons((u_short)port); addr.sin_family = AF_INET; diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan new file mode 100644 index 00000000..9b1a6a27 --- /dev/null +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan @@ -0,0 +1,24 @@ +{ + "configurations" : [ + { + "id" : "5A402836-E1DD-4825-904B-BFAEC12C977B", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Security.xcodeproj", + "identifier" : "3DD1FFAC201FDB1D0086D049", + "name" : "SecureTransportTests_ios" + } + } + ], + "version" : 1 +} diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan new file mode 100644 index 00000000..ec8f30de --- /dev/null +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan @@ -0,0 +1,24 @@ +{ + "configurations" : [ + { + "id" : "C4B1D35D-6AAD-4F4E-A674-0453730B68EB", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Security.xcodeproj", + "identifier" : "3DD1FEF5201C07F30086D049", + "name" : "SecureTransportTests_macos" + } + } + ], + "version" : 1 +} diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_iosTests.plist b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_iosTests.plist index ef1755a2..539e4876 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_iosTests.plist +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_iosTests.plist @@ -13,7 +13,14 @@ /AppleInternal/XCTests/com.apple.security/ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest Self SecureTransport_ios_tests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + Self + SecureTransport_ios_tests.xctest diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_macosTests.plist b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_macosTests.plist index 64a927ab..266c4f56 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_macosTests.plist +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_macosTests.plist @@ -13,7 +13,14 @@ /AppleInternal/XCTests/com.apple.security/ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest Self SecureTransport_macos_tests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + Self + SecureTransport_macos_tests.xctest diff --git a/OSX/libsecurity_ssl/regressions/gencerts.sh b/OSX/libsecurity_ssl/regressions/gencerts.sh old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_ssl/regressions/ssl-39-echo.c b/OSX/libsecurity_ssl/regressions/ssl-39-echo.c index cce99baa..7652b715 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-39-echo.c +++ b/OSX/libsecurity_ssl/regressions/ssl-39-echo.c @@ -1,3 +1,4 @@ +#include #if TARGET_OS_IPHONE // Currently only supported for iOS @@ -31,6 +32,8 @@ #include +#include + #include "testlist.h" /* @@ -480,7 +483,7 @@ static SSLContextRef make_ssl_ref(bool server, bool client_side_auth, bool dh_an require_noerr(SSLNewContext(server, &ctx), out); require_noerr(SSLSetIOFuncs(ctx, (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); - require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)sock), out); + require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out); static const char *peer_domain_name = "localhost"; require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name, strlen(peer_domain_name)), out); diff --git a/OSX/libsecurity_ssl/regressions/ssl-50-server.c b/OSX/libsecurity_ssl/regressions/ssl-50-server.c index b20a9b02..bc766e70 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-50-server.c +++ b/OSX/libsecurity_ssl/regressions/ssl-50-server.c @@ -185,7 +185,7 @@ ssl_test_handle_create(int comm, CFArrayRef certs) static void *securetransport_ssl_thread(void *arg) { OSStatus ortn; - int sock = (int)arg; + int sock = *((int*)arg); int socket = accept(sock, NULL, NULL); @@ -244,7 +244,7 @@ tests(void) } //fprintf(stderr, "session_id: %d\n", session_id); - pthread_create(&server_thread, NULL, securetransport_ssl_thread, (void*)socket); + pthread_create(&server_thread, NULL, securetransport_ssl_thread, (void*)&socket); system("/usr/bin/openssl s_client -msg -debug -connect localhost:4443"); diff --git a/OSX/libsecurity_ssl/regressions/ssl-51-state.c b/OSX/libsecurity_ssl/regressions/ssl-51-state.c index 91a48385..f5840500 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-51-state.c +++ b/OSX/libsecurity_ssl/regressions/ssl-51-state.c @@ -46,9 +46,8 @@ #define test_printf(x...) -/* extern struct ccrng_state *ccDRBGGetRngState(); */ -#include -#define CCRNGSTATE ccDRBGGetRngState() +#include +#define CCRNGSTATE ccrng(NULL) struct RecQueueItem { STAILQ_ENTRY(RecQueueItem) next; /* link to next queued entry or NULL */ diff --git a/OSX/libsecurity_ssl/regressions/ssl_regressions.h b/OSX/libsecurity_ssl/regressions/ssl_regressions.h index 630b601a..779205cf 100644 --- a/OSX/libsecurity_ssl/regressions/ssl_regressions.h +++ b/OSX/libsecurity_ssl/regressions/ssl_regressions.h @@ -1,14 +1,15 @@ #include -DISABLED_ONE_TEST(ssl_39_echo) #if TARGET_OS_IPHONE +OFF_ONE_TEST(ssl_39_echo) ONE_TEST(ssl_40_clientauth) ONE_TEST(ssl_41_clientauth) #else +DISABLED_ONE_TEST(ssl_39_echo) DISABLED_ONE_TEST(ssl_40_clientauth) DISABLED_ONE_TEST(ssl_41_clientauth) diff --git a/OSX/libsecurity_ssl/security_ssl b/OSX/libsecurity_ssl/security_ssl deleted file mode 120000 index 7951405f..00000000 --- a/OSX/libsecurity_ssl/security_ssl +++ /dev/null @@ -1 +0,0 @@ -lib \ No newline at end of file diff --git a/OSX/libsecurity_transform/lib/SecDecodeTransform.h b/OSX/libsecurity_transform/lib/SecDecodeTransform.h index 28e10484..1327a2e8 100644 --- a/OSX/libsecurity_transform/lib/SecDecodeTransform.h +++ b/OSX/libsecurity_transform/lib/SecDecodeTransform.h @@ -24,7 +24,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "SecEncodeTransform.h" +#include #ifdef __cplusplus extern "C" { diff --git a/OSX/libsecurity_transform/lib/SecDigestTransform.h b/OSX/libsecurity_transform/lib/SecDigestTransform.h index d61f6e2d..00e0a9e1 100644 --- a/OSX/libsecurity_transform/lib/SecDigestTransform.h +++ b/OSX/libsecurity_transform/lib/SecDigestTransform.h @@ -25,7 +25,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "SecTransform.h" +#include #ifdef __cplusplus extern "C" { diff --git a/OSX/libsecurity_transform/lib/SecEncodeTransform.h b/OSX/libsecurity_transform/lib/SecEncodeTransform.h index 499b242f..169bbf79 100644 --- a/OSX/libsecurity_transform/lib/SecEncodeTransform.h +++ b/OSX/libsecurity_transform/lib/SecEncodeTransform.h @@ -24,7 +24,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "SecTransform.h" +#include #ifdef __cplusplus extern "C" { diff --git a/OSX/libsecurity_transform/lib/SecEncryptTransform.h b/OSX/libsecurity_transform/lib/SecEncryptTransform.h index 0a744fcf..541d1ce1 100644 --- a/OSX/libsecurity_transform/lib/SecEncryptTransform.h +++ b/OSX/libsecurity_transform/lib/SecEncryptTransform.h @@ -36,7 +36,7 @@ #include #include -#include "SecTransform.h" +#include #ifdef __cplusplus extern "C" { diff --git a/OSX/libsecurity_transform/lib/SecSignVerifyTransform.c b/OSX/libsecurity_transform/lib/SecSignVerifyTransform.c index a4665279..00f5cbed 100644 --- a/OSX/libsecurity_transform/lib/SecSignVerifyTransform.c +++ b/OSX/libsecurity_transform/lib/SecSignVerifyTransform.c @@ -27,7 +27,9 @@ #include "Utilities.h" #include #include "misc.h" -#include // for dyld_get_program_sdk_version +#include + +#include "simulatecrash_assert.h" const static CFStringRef SignName = CFSTR("com.apple.security.Sign"), VerifyName = CFSTR("com.apple.security.Verify"); const CFStringRef __nonnull kSecKeyAttributeName = CFSTR("KEY"), kSecSignatureAttributeName = CFSTR("Signature"), kSecInputIsAttributeName = CFSTR("InputIs"); @@ -410,8 +412,8 @@ static SecTransformInstanceBlock SignTransform(CFStringRef name, OSStatus rc = SecKeyGetCSSMKey(key, &cssm_key); SEC_FAIL(rc); - if (((!cssm_key->KeyHeader.KeyUsage) & CSSM_KEYUSE_SIGN) // Keep the previous test to be compatible with existing apps - || ((dyld_get_program_sdk_version() >= DYLD_MACOSX_VERSION_10_13) // Better check for newly compiled apps + if (((!cssm_key->KeyHeader.KeyUsage) & CSSM_KEYUSE_SIGN) + || (dyld_program_sdk_at_least(dyld_platform_version_macOS_10_13) // Keep the previous test to be compatible with existing apps && !(cssm_key->KeyHeader.KeyUsage & (CSSM_KEYUSE_SIGN|CSSM_KEYUSE_ANY)))) { key = NULL; // This key cannot sign! @@ -539,8 +541,8 @@ static SecTransformInstanceBlock VerifyTransform(CFStringRef name, rc = SecKeyGetCSSMKey((SecKeyRef)value, &cssm_key); SEC_FAIL(rc); - if (((!cssm_key->KeyHeader.KeyUsage) & CSSM_KEYUSE_SIGN) // Keep the previous test to be compatible with existing apps - || ((dyld_get_program_sdk_version() >= DYLD_MACOSX_VERSION_10_13) // Better check for newly compiled apps + if (((!cssm_key->KeyHeader.KeyUsage) & CSSM_KEYUSE_SIGN) + || (dyld_program_sdk_at_least(dyld_platform_version_macOS_10_13) // Keep the previous test to be compatible with existing apps && !(cssm_key->KeyHeader.KeyUsage & (CSSM_KEYUSE_VERIFY|CSSM_KEYUSE_ANY)))) { key = NULL; // This key cannot verify! diff --git a/OSX/libsecurity_transform/lib/SecSignVerifyTransform.h b/OSX/libsecurity_transform/lib/SecSignVerifyTransform.h index 0753aad0..073ff69e 100644 --- a/OSX/libsecurity_transform/lib/SecSignVerifyTransform.h +++ b/OSX/libsecurity_transform/lib/SecSignVerifyTransform.h @@ -25,7 +25,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "SecTransform.h" +#include #include diff --git a/OSX/libsecurity_transform/lib/Transform.cpp b/OSX/libsecurity_transform/lib/Transform.cpp index a9d1fc7c..6a1e6406 100644 --- a/OSX/libsecurity_transform/lib/Transform.cpp +++ b/OSX/libsecurity_transform/lib/Transform.cpp @@ -156,9 +156,11 @@ SecTransformAttributeRef Transform::getAH(SecTransformStringOrAttributeRef attri SecTransformAttributeRef search_for = pthread_getspecific(ah_search_key_slot); if (!search_for) { - search_for = makeAH((transform_attribute*)malloc(sizeof(transform_attribute))); + transform_attribute* ta = (transform_attribute*)malloc(sizeof(transform_attribute)); + search_for = makeAH(ta); if (!search_for) { + free(ta); return NULL; } @@ -185,12 +187,14 @@ SecTransformAttributeRef Transform::getAH(SecTransformStringOrAttributeRef attri ah = makeAH(ta); if (!ah) { + free(ta); return NULL; } ta->name = CFStringCreateCopy(NULL, label); if (!ta->name) { + CFRelease(ah); free(ta); return NULL; } @@ -200,6 +204,7 @@ SecTransformAttributeRef Transform::getAH(SecTransformStringOrAttributeRef attri { CFReleaseNull(ta->name); free(ta); + CFRelease(ah); return NULL; } @@ -265,7 +270,7 @@ bool Transform::HasNoOutboundConnections() { // make an array big enough to hold all of the attributes CFIndex numAttributes = CFSetGetCount(mAttributes); - transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute)); + transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute*)); if (attributes == NULL) { // No more memory, we assume it's orphaned @@ -296,7 +301,7 @@ bool Transform::HasNoInboundConnections() { // make an array big enough to hold all of the attributes CFIndex numAttributes = CFSetGetCount(mAttributes); - transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute)); + transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute*)); if (attributes == NULL) { // No more memory, we assume it's orphaned @@ -1622,7 +1627,7 @@ CFDictionaryRef Transform::GetAHDictForSaveState(SecTransformStringOrAttributeRe CFDictionaryRef Transform::CopyState() { CFIndex i, j, cnt = CFSetGetCount(mAttributes); - transform_attribute **attrs = (transform_attribute**)malloc(cnt*sizeof(transform_attribute)); + transform_attribute **attrs = (transform_attribute**)malloc(cnt*sizeof(transform_attribute*)); CFStringRef *names = (CFStringRef*)malloc(cnt*sizeof(CFStringRef)); CFDictionaryRef *values = (CFDictionaryRef*)malloc(sizeof(CFDictionaryRef) * cnt); @@ -1819,7 +1824,7 @@ CFErrorRef Transform::ProcessExternalize(CFMutableArrayRef transforms, CFMutable // now walk the attribute list CFIndex numAttributes = CFSetGetCount(mAttributes); - transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute)); + transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute*)); if (attributes == NULL) { return GetNoMemoryErrorAndRetain(); diff --git a/OSX/libsecurity_transform/misc/base32alpha2vals b/OSX/libsecurity_transform/misc/base32alpha2vals old mode 100644 new mode 100755 diff --git a/OSX/libsecurity_transform/misc/speed-test.mm b/OSX/libsecurity_transform/misc/speed-test.mm index b33aea64..1e8e9cff 100644 --- a/OSX/libsecurity_transform/misc/speed-test.mm +++ b/OSX/libsecurity_transform/misc/speed-test.mm @@ -26,7 +26,7 @@ #include "SecTransform.h" #include "SecExternalSourceTransform.h" #include "SecNullTransform.h" -#include +#include @implementation speed_test diff --git a/OSX/libsecurity_translocate/lib/SecTranslocate.cpp b/OSX/libsecurity_translocate/lib/SecTranslocate.cpp index a86aa4c8..439c6b14 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocate.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocate.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #include "SecTranslocate.h" #include "SecTranslocateShared.hpp" @@ -49,16 +49,16 @@ To create a translocation mountpoint, if no destination path is provided, first the app path to be translocated is realpathed to ensure it exists and there are no symlink's in - the path we work with. Then the calling user's _CS_DARWIN_USER_TEMP_DIR is found. This + the path we work with. Then the calling user's _CS_DARWIN_USER_TEMP_DIR is found. This is used to calculate the user's AppTranslocation directory. The formula is: - User's App Translocation Directory = realpath(confstr(_CS_DARWIN_USER_TEMP_DIR))+/AppTranslocation/ + User's App Translocation Directory = realpath(confstr(_CS_DARWIN_USER_TEMP_DIR))+/AppTranslocation/ Then the mount table is checked to see whether or not a translocation point already exists for this user for the app being requested. The rule for an already existing mount is that - there must exist a mountpoint in the user's app translocation directory that is mounted + there must exist a mountpoint in the user's app translocation directory that is mounted from realpath of the requested app. - If a mount exists already for this user, then the path to the app in that mountpoint is + If a mount exists already for this user, then the path to the app in that mountpoint is calculated and sanity checked. The rules to create the app path inside the mountpoint are: @@ -74,11 +74,11 @@ If the sanity checks pass for the new app path, then that path is returned to the caller. If no translocation mount point exists already per the mount table then an AppTranslocation - directory is created within the temp dir if it doesn't already exist. After that a UUID is + directory is created within the temp dir if it doesn't already exist. After that a UUID is generated, that UUID is used as the name of a new directory in the AppTranslocation directory. - Once the new directory has been created and sanity checked, mount is called to create the + Once the new directory has been created and sanity checked, mount is called to create the translocation between the original path and the new directory. Then the new path to the app - within the mountpoint is calculated and sanity checked. + within the mountpoint is calculated and sanity checked. The sanity check rules for the mountpoint before the mount are: 1. Something exists at the expected path @@ -92,17 +92,17 @@ (This functionality is implemented in SecTranslocateShared.hpp/cpp) If a destination path is provided, a sequence similar to that described above is followed - with the following modifications. + with the following modifications. - The destination path is expected to be of the same form as new app path. This expectation + The destination path is expected to be of the same form as new app path. This expectation is verified. - First we verify that the destination path ends with /d/ and that the - component of the destination path matches the of the original app app path - requested. If not, an error occurs. Everything before the /d/ is treated becomes the + First we verify that the destination path ends with /d/ and that the + component of the destination path matches the of the original app app path + requested. If not, an error occurs. Everything before the /d/ is treated becomes the requested destination mount point. - After the user's app translocation directory is calculated, we ensure that the requested + After the user's app translocation directory is calculated, we ensure that the requested destination mount point is prefixed by the translocation directory, and contains only one path component after the user's app translocation path, otherwise an error occurs. @@ -112,7 +112,7 @@ If no mountpoint exists for the app, then we attempt to create the requested directory within the user's app translocation directory. This becomes the mount point, and the mount point - sanity checks listed above are applied. + sanity checks listed above are applied. If the requested destination mountpoint is successfully created, the flow continues as above to create the mount and verify the requested path within the mountpoint. The only extra step @@ -135,7 +135,7 @@ remove the translocation point. Regardless of whether or not the requested path is a translocation point, we opportunistically - attempt to cleanup the app translocation directory. Clean up means, looping through all the + attempt to cleanup the app translocation directory. Clean up means, looping through all the directories currently in the user's app translocation directory and checking whether or not they are a mount point. If a directory inside the user's app translocation directory is not a mountpoint, then we attempt to delete it. @@ -154,17 +154,17 @@ mountpoint and applied to the created app translocation mountpoint. **** Concurrency considerations **** - This library treats the kernel as the source of truth for the status of the file system. + This library treats the kernel as the source of truth for the status of the file system. Unfortunately it has no way to lock the state of the file system and mount table while it is operating. Because of this, there are two potential areas that have race windows. - First, if any other system entity (thread within the same process, or other process + First, if any other system entity (thread within the same process, or other process within the system) is adding or removing entries from the mount table while SecTranslocateCreateSecureDirectoryForURL is executing, then there is the possibility that an incorrect decision will be made about the current existence of a mount point for a user - for an app. This is because getfsstat gets a snapshot of the mount table state rather than a + for an app. This is because getfsstat gets a snapshot of the mount table state rather than a locked window into the kernel and because we make two seperate calls to getfsstat, one to get - the number of mountpoints, and a second to actually read the mountpoint data. If more than + the number of mountpoints, and a second to actually read the mountpoint data. If more than one process is using this library for the same user, then both processes could attempt to create a translocation for the same app, and this could result in more than one translocation for that app for the user. This shouldn't effect the user other than using additional @@ -172,10 +172,10 @@ the first call and then trying the process again (once) if the initial memory was filled. Second, if more than one process is using this library simultaneously and one process calls - SecTranslocateDeleteSecureDirectory for a user and the other calls + SecTranslocateDeleteSecureDirectory for a user and the other calls SecTranslocateCreateSecureDirectoryForURL for that same user, then the call to SecTranslocateDeleteSecureDirectory may cause SecTranslocateCreateSecureDirectoryForURL to - fail. This will occur if the loop checking for unmounted directories in the user's app + fail. This will occur if the loop checking for unmounted directories in the user's app translocation directory deletes a newly created directory before the mount call finishes. This race condition will probably result in a failed app launch. A second attempt to launch the app will probably succeed. @@ -201,23 +201,17 @@ Boolean SecTranslocateStartListening(CFErrorRef* __nullable error) { Boolean result = false; CFIndex errorCode = 0; - try - { + try { /* ask getTranslocator for the server */ result = Security::SecTranslocate::getTranslocator(true) != NULL; - } - catch (Security::UnixError err) - { + } catch (Security::UnixError err) { errorCode = err.unixError(); - } - catch(...) - { - Syslog::critical("SecTranslocate: uncaught exception during server initialization"); + } catch(...) { + seccritical("SecTranslocate: uncaught exception during server initialization"); errorCode = EINVAL; } - if (error && errorCode) - { + if (error && errorCode) { *error = SecTranslocateMakePosixError(errorCode); } @@ -233,13 +227,10 @@ Boolean SecTranslocateStartListeningWithOptions(CFDictionaryRef __unused options /* Register that a (translocated) pid has launched */ void SecTranslocateAppLaunchCheckin(pid_t pid) { - try - { + try { Security::SecTranslocate::getTranslocator()->appLaunchCheckin(pid); - } - catch (...) - { - Syslog::error("SecTranslocate: error in SecTranslocateAppLaunchCheckin"); + } catch (...) { + secerror("SecTranslocate: error in SecTranslocateAppLaunchCheckin"); } } @@ -251,14 +242,12 @@ CFURLRef __nullable SecTranslocateCreateSecureDirectoryForURL (CFURLRef pathToTr CFURLRef result = NULL; CFIndex errorCode = 0; - try - { + try { string sourcePath = cfString(pathToTranslocate); // returns an absolute path - Security::SecTranslocate::TranslocationPath toTranslocatePath(sourcePath); + Security::SecTranslocate::TranslocationPath toTranslocatePath(sourcePath, Security::SecTranslocate::TranslocationOptions::Default); - if(!toTranslocatePath.shouldTranslocate()) - { + if (!toTranslocatePath.shouldTranslocate()) { /* We shouldn't translocate so, just retain so that the return value can be treated as a copy */ CFRetain(pathToTranslocate); return pathToTranslocate; @@ -266,37 +255,31 @@ CFURLRef __nullable SecTranslocateCreateSecureDirectoryForURL (CFURLRef pathToTr /* We need to translocate so keep going */ string destPath; + + Security::SecTranslocate::ExtendedAutoFileDesc destFd; - if(destinationPath) - { + if (destinationPath) { destPath = cfString(destinationPath); //returns an absolute path + destFd.open(destPath); } - string out_path = Security::SecTranslocate::getTranslocator()->translocatePathForUser(toTranslocatePath, destPath); + string out_path = Security::SecTranslocate::getTranslocator()->translocatePathForUser(toTranslocatePath, destFd); - if(!out_path.empty()) - { + if(!out_path.empty()) { result = makeCFURL(out_path, true); - } - else - { - Syslog::error("SecTranslocateCreateSecureDirectoryForURL: No mountpoint and no prior exception. Shouldn't be here"); + } else { + secerror("SecTranslocateCreateSecureDirectoryForURL: No mountpoint and no prior exception. Shouldn't be here"); UnixError::throwMe(EINVAL); } - } - catch (Security::UnixError err) - { + } catch (Security::UnixError err) { errorCode = err.unixError(); - } - catch(...) - { - Syslog::critical("SecTranslocate: uncaught exception during mountpoint creation"); + } catch(...) { + seccritical("SecTranslocate: uncaught exception during mountpoint creation"); errorCode = EACCES; } - if (error && errorCode) - { + if (error && errorCode) { *error = SecTranslocateMakePosixError(errorCode); } return result; @@ -308,67 +291,95 @@ Boolean SecTranslocateDeleteSecureDirectory(CFURLRef translocatedPath, CFErrorRe bool result = false; int errorCode = 0; - if(translocatedPath == NULL) - { + if(translocatedPath == NULL) { errorCode = EINVAL; goto end; } - try - { + try { string pathToDestroy = cfString(translocatedPath); result = Security::SecTranslocate::getTranslocator()->destroyTranslocatedPathForUser(pathToDestroy); - } - catch (Security::UnixError err) - { + } catch (Security::UnixError err) { errorCode = err.unixError(); - } - catch(...) - { - Syslog::critical("SecTranslocate: uncaught exception during mountpoint deletion"); + } catch(...) { + seccritical("SecTranslocate: uncaught exception during mountpoint deletion"); errorCode = EACCES; } end: - if (error && errorCode) - { + if (error && errorCode) { *error = SecTranslocateMakePosixError(errorCode); } return result; } +CFURLRef __nullable SecTranslocateCreateGeneric (CFURLRef pathToTranslocate, + CFURLRef destinationPath, + CFErrorRef* __nullable error) +{ + CFURLRef result = NULL; + CFIndex errorCode = 0; + bool owned = false; + Security::SecTranslocate::ExtendedAutoFileDesc destFd; + + try { + string sourcePath = cfString(pathToTranslocate); + Security::SecTranslocate::GenericTranslocationPath path{sourcePath, Security::SecTranslocate::TranslocationOptions::Unveil}; + + string dpath = cfString(destinationPath); + destFd = Security::SecTranslocate::getFDForDirectory(dpath, &owned); + string out_path = Security::SecTranslocate::getTranslocator()->translocatePathForUser(path, destFd); + + if (!out_path.empty()) { + result = makeCFURL(out_path, true); + } else { + secerror("SecTranslocateCreateGeneric: No mountpoint and no prior exception. Shouldn't be here"); + UnixError::throwMe(EINVAL); + } + } catch (Security::UnixError err) { + errorCode = err.unixError(); + } catch(...) { + seccritical("SecTranslocateCreateGeneric: uncaught exception during mountpoint creation"); + errorCode = EACCES; + } + + if (errorCode) { + if (destFd.isOpen() && owned) { + rmdir(destFd.getRealPath().c_str()); + } + } + + if (error && errorCode) { + *error = SecTranslocateMakePosixError(errorCode); + } + return result; +} + /* Decide whether we need to translocate */ Boolean SecTranslocateURLShouldRunTranslocated(CFURLRef path, bool* shouldTranslocate, CFErrorRef* __nullable error) { bool result = false; int errorCode = 0; - if(path == NULL || shouldTranslocate == NULL) - { + if (path == NULL || shouldTranslocate == NULL){ errorCode = EINVAL; goto end; } - try - { + try { string pathToCheck = cfString(path); - Security::SecTranslocate::TranslocationPath tPath(pathToCheck); + Security::SecTranslocate::TranslocationPath tPath(pathToCheck, Security::SecTranslocate::TranslocationOptions::Default); *shouldTranslocate = tPath.shouldTranslocate(); result = true; - } - catch (Security::UnixError err) - { + } catch (Security::UnixError err) { errorCode = err.unixError(); - } - catch(...) - { - Syslog::critical("SecTranslocate: uncaught exception during policy check"); + } catch(...) { + seccritical("SecTranslocate: uncaught exception during policy check"); errorCode = EACCES; } end: - if (error && errorCode) - { + if (error && errorCode) { *error = SecTranslocateMakePosixError(errorCode); } @@ -376,19 +387,17 @@ end: } /* Answer whether or not the passed in URL is a nullfs URL. This just checks nullfs rather than - nullfs + in the user's translocation path to allow callers like LaunchServices to apply special - handling to nullfs mounts regardless of the calling user (i.e. root lsd can identify all translocated - mount points for all users). + nullfs + in the user's translocation path to allow callers like LaunchServices to apply special + handling to nullfs mounts regardless of the calling user (i.e. root lsd can identify all translocated + mount points for all users). */ Boolean SecTranslocateIsTranslocatedURL(CFURLRef path, bool* isTranslocated, CFErrorRef* __nullable error) { bool result = false; int errorCode = 0; - if(path == NULL || isTranslocated == NULL) - { - if(error) - { + if (path == NULL || isTranslocated == NULL) { + if(error) { *error = SecTranslocateMakePosixError(EINVAL); } return result; @@ -396,47 +405,35 @@ Boolean SecTranslocateIsTranslocatedURL(CFURLRef path, bool* isTranslocated, CFE *isTranslocated = false; - try - { + try { string cpp_path = cfString(path); /* "/" i.e. the root volume, cannot be translocated (or mounted on by other file system after boot) - so don't bother to make system calls if "/" is what is being asked about. - This is an optimization to help LaunchServices which expects to use SecTranslocateIsTranslocatedURL - on every App Launch. + so don't bother to make system calls if "/" is what is being asked about. + This is an optimization to help LaunchServices which expects to use SecTranslocateIsTranslocatedURL + on every App Launch. */ - if (cpp_path != "/") - { + if (cpp_path != "/") { /* to avoid AppSandbox violations, use a path based check here. - We only look for nullfs file type anyway. */ + We only look for nullfs file type anyway. */ struct statfs sfb; - if (statfs(cpp_path.c_str(), &sfb) == 0) - { + if (statfs(cpp_path.c_str(), &sfb) == 0) { *isTranslocated = (strcmp(sfb.f_fstypename, NULLFS_FSTYPE) == 0); result = true; - } - else - { + } else { errorCode = errno; - Syslog::error("SecTranslocate: can not access %s, error: %s", cpp_path.c_str(), strerror(errorCode)); + secerror("SecTranslocate: can not access %s, error: %s", cpp_path.c_str(), strerror(errorCode)); } - } - else - { + } else { result = true; } - } - catch (Security::UnixError err) - { + } catch (Security::UnixError err) { errorCode = err.unixError(); - } - catch(...) - { - Syslog::critical("SecTranslocate: uncaught exception during policy check"); + } catch(...) { + seccritical("SecTranslocate: uncaught exception during policy check"); errorCode = EACCES; } - if (error && errorCode) - { + if (error && errorCode) { *error = SecTranslocateMakePosixError(errorCode); } @@ -444,56 +441,43 @@ Boolean SecTranslocateIsTranslocatedURL(CFURLRef path, bool* isTranslocated, CFE } /* Find the original path for translocation mounts belonging to the calling user. - if the url isn't on a nullfs volume then returned a retained copy of the passed in url. - if the url is on a nullfs volume but that volume doesn't belong to the user, or another - error occurs then null is returned */ + if the url isn't on a nullfs volume then returned a retained copy of the passed in url. + if the url is on a nullfs volume but that volume doesn't belong to the user, or another + error occurs then null is returned */ CFURLRef __nullable SecTranslocateCreateOriginalPathForURL(CFURLRef translocatedPath, CFErrorRef* __nullable error) { CFURLRef result = NULL; int errorCode = 0; - if(translocatedPath == NULL) - { + if (translocatedPath == NULL) { errorCode = EINVAL; goto end; } - try - { + try { string path = cfString(translocatedPath); Security::SecTranslocate::ExtendedAutoFileDesc fd(path); - if(fd.isFileSystemType(NULLFS_FSTYPE)) - { + if (fd.isFileSystemType(NULLFS_FSTYPE)) { bool isDir = false; string out_path = Security::SecTranslocate::getOriginalPath(fd, &isDir); - if(!out_path.empty()) - { + if (!out_path.empty()) { result = makeCFURL(out_path, isDir); - } - else - { - Syslog::error("SecTranslocateCreateOriginalPath: No original and no prior exception. Shouldn't be here"); + } else { + secerror("SecTranslocateCreateOriginalPath: No original and no prior exception. Shouldn't be here"); UnixError::throwMe(EINVAL); } - } - else - { + } else { result = translocatedPath; CFRetain(result); } - } - catch (Security::UnixError err) - { + } catch (Security::UnixError err) { errorCode = err.unixError(); - } - catch(...) - { - Syslog::critical("SecTranslocate: uncaught exception during policy check"); + } catch(...) { + seccritical("SecTranslocate: uncaught exception during policy check"); errorCode = EACCES; } end: - if (error && errorCode) - { + if (error && errorCode) { *error = SecTranslocateMakePosixError(errorCode); } return result; diff --git a/OSX/libsecurity_translocate/lib/SecTranslocate.h b/OSX/libsecurity_translocate/lib/SecTranslocate.h index c01e4127..ce31fb1f 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocate.h +++ b/OSX/libsecurity_translocate/lib/SecTranslocate.h @@ -98,6 +98,33 @@ __OSX_AVAILABLE(10.12); CFURLRef __nullable SecTranslocateCreateSecureDirectoryForURL (CFURLRef pathToTranslocate, CFURLRef __nullable destinationPath, CFErrorRef* __nullable error) __OSX_AVAILABLE(10.12); +/*! + @function SecTranslocateCreateGeneric + + @abstract Create a CFURL pointing to a translocated location from which to access the directory specified by pathToTranslocate. + + @param pathToTranslocate URL of the directory to be accessed from a translocated location. + @param destinationPath URL where the directory of interest should be translocated + @param error On error will be populated with an error object describing the failure (a posix domain error such as EINVAL) + + @result A CFURL pointing to the translocated location of the directory. + + @discussion + Calls to this function, and the others dealng with creation / deletion of mounts are serialized to ensure only one call to either + is operating at a time. + Translocations will be created in specified destinationPath + + pathToTranslocated is expected to be a folder + + If pathToTranslocate is in a quarantined mountpoint, the quarantine attributes will be propagated to the + translocated location. + + pathToTranslocate will cause a failure if it doesn't resolve to a path that exists, or it exceeds MAXPATHLEN + This function can be run from any process. If the process is not the xpc server, then an xpc call is made. + */ +CFURLRef __nullable SecTranslocateCreateGeneric (CFURLRef pathToTranslocate, CFURLRef destinationPath, CFErrorRef* __nullable error) +__OSX_AVAILABLE(10.16); + /*! @function SecTranslocateAppLaunchCheckin diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp index 99095aa3..ca174e06 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include "SecTranslocateClient.hpp" #include "SecTranslocateShared.hpp" @@ -42,9 +42,8 @@ using namespace std; TranslocatorClient::TranslocatorClient(dispatch_queue_t q):syncQ(q) { - if(syncQ == NULL) - { - Syslog::critical("SecTranslocate::TranslocatorClient initialized without a queue."); + if(syncQ == NULL) { + seccritical("SecTranslocate::TranslocatorClient initialized without a queue."); UnixError::throwMe(EINVAL); } @@ -52,31 +51,26 @@ TranslocatorClient::TranslocatorClient(dispatch_queue_t q):syncQ(q) uid_t euid = geteuid(); /* 0 - is root so it gets the root lsd - 1-300 = are treated by launch services as "role users" They share a copy of the LS Database with root - and thus must be sent to the root lsd. */ - if (euid <= 300) - { + 1-300 = are treated by launch services as "role users" They share a copy of the LS Database with root + and thus must be sent to the root lsd. */ + if (euid <= 300) { flags |= XPC_CONNECTION_MACH_SERVICE_PRIVILEGED; //forces call to the root lsd } service = xpc_connection_create_mach_service(SECTRANSLOCATE_XPC_SERVICE_NAME, syncQ, flags); - if (service == NULL) - { - Syslog::critical("SecTranslocate: TranslocatorClient, failed to create xpc mach service"); + if (service == NULL) { + seccritical("SecTranslocate: TranslocatorClient, failed to create xpc mach service"); UnixError::throwMe(ENOMEM); } xpc_connection_set_event_handler(service, ^(xpc_object_t event) { xpc_type_t type = xpc_get_type(event); - if (type == XPC_TYPE_ERROR) - { - Syslog::error("SecTranslocate, client, xpc error: %s", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); - } - else - { + if (type == XPC_TYPE_ERROR) { + secerror("SecTranslocate, client, xpc error: %s", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); + } else { char* description = xpc_copy_description(event); - Syslog::error("SecTranslocate, client, xpc unexpected type: %s", description); + secerror("SecTranslocate, client, xpc unexpected type: %s", description); free(description); } }); @@ -91,73 +85,59 @@ TranslocatorClient::~TranslocatorClient() dispatch_release(syncQ); } -string TranslocatorClient::translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) +string TranslocatorClient::requestTranslocation(const int fdToTranslocate, + const int destFd, + const TranslocationOptions flags) { string outPath; - - if (!originalPath.shouldTranslocate()) - { - return originalPath.getOriginalRealPath(); //return original path if we shouldn't translocate - } - + //We should run translocated, so get a translocation point xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0); - if( msg == NULL) - { - Syslog::error("SecTranslocate: TranslocatorClient, failed to allocate message to send"); + if (msg == NULL) { + secerror("SecTranslocate: TranslocatorClient, failed to allocate message to send"); UnixError::throwMe(ENOMEM); } xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageFunction, kSecTranslocateXPCFuncCreate); - /* send the original real path rather than the calculated path to let the server do all the work */ - xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageOriginalPath, originalPath.getOriginalRealPath().c_str()); - if(!destPath.empty()) - { - xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageDestinationPath, destPath.c_str()); + xpc_dictionary_set_fd(msg, kSecTranslocateXPCMessageOriginalPath, fdToTranslocate); + xpc_dictionary_set_int64(msg, kSecTranslocateXPCMessageOptions, static_cast(flags)); + if (destFd != -1) { + xpc_dictionary_set_fd(msg, kSecTranslocateXPCMessageDestinationPath, destFd); } xpc_object_t reply = xpc_connection_send_message_with_reply_sync(service, msg); xpc_release(msg); - if(reply == NULL) - { - Syslog::error("SecTranslocate, TranslocatorClient, create, no reply returned"); + if (reply == NULL) { + secerror("SecTranslocate, TranslocatorClient, create, no reply returned"); UnixError::throwMe(ENOMEM); } xpc_type_t type = xpc_get_type(reply); - if (type == XPC_TYPE_DICTIONARY) - { - if(int64_t error = xpc_dictionary_get_int64(reply, kSecTranslocateXPCReplyError)) - { - Syslog::error("SecTranslocate, TranslocatorClient, create, error received %lld", error); + if (type == XPC_TYPE_DICTIONARY) { + if(int64_t error = xpc_dictionary_get_int64(reply, kSecTranslocateXPCReplyError)) { + secerror("SecTranslocate, TranslocatorClient, create, error received %lld", error); xpc_release(reply); UnixError::throwMe((int)error); } const char * result = xpc_dictionary_get_string(reply, kSecTranslocateXPCReplySecurePath); - if (result == NULL) - { - Syslog::error("SecTranslocate, TranslocatorClient, create, no result path received"); + if (result == NULL) { + secerror("SecTranslocate, TranslocatorClient, create, no result path received"); xpc_release(reply); UnixError::throwMe(EINVAL); } outPath=result; xpc_release(reply); - } - else - { + } else { const char* errorMsg = NULL; - if (type == XPC_TYPE_ERROR) - { - errorMsg = "SecTranslocate, TranslocatorClient, create, xpc error returned: %s"; - } - else - { - errorMsg = "SecTranslocate, TranslocatorClient, create, unexpected type of return object: %s"; + if (type == XPC_TYPE_ERROR) { + errorMsg = "SecTranslocate, TranslocatorClient, create, xpc error returned"; + } else { + errorMsg = "SecTranslocate, TranslocatorClient, create, unexpected type of return object"; } const char *s = xpc_copy_description(reply); - Syslog::error(errorMsg, s); + secerror("%s: %s",errorMsg, s); free((char*)s); xpc_release(reply); UnixError::throwMe(EINVAL); @@ -166,6 +146,24 @@ string TranslocatorClient::translocatePathForUser(const TranslocationPath &origi return outPath; } +string TranslocatorClient::translocatePathForUser(const TranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) +{ + if (!originalPath.shouldTranslocate()) { + return originalPath.getOriginalRealPath(); //return original path if we shouldn't translocate + } + + return requestTranslocation(originalPath.getFdForPathToTranslocate(), destFd.fd(), TranslocationOptions::Default); +} + +string TranslocatorClient::translocatePathForUser(const GenericTranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) +{ + if (!originalPath.shouldTranslocate()) { + return originalPath.getOriginalRealPath(); //return original path if we shouldn't translocate + } + + return requestTranslocation(originalPath.getFdForPathToTranslocate(), destFd.fd(), TranslocationOptions::Generic); +} + void TranslocatorClient::appLaunchCheckin(pid_t pid) { xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0); @@ -181,7 +179,7 @@ void TranslocatorClient::appLaunchCheckin(pid_t pid) bool TranslocatorClient::destroyTranslocatedPathForUser(const string &translocatedPath) { - Syslog::error("SecTranslocate, TranslocatorClient, delete operation not allowed"); + secerror("SecTranslocate, TranslocatorClient, delete operation not allowed"); UnixError::throwMe(EPERM); } diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp index bff27ef0..b7897918 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp @@ -46,13 +46,17 @@ public: TranslocatorClient(dispatch_queue_t q); ~TranslocatorClient(); - string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) override; + string translocatePathForUser(const TranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) override; + string translocatePathForUser(const GenericTranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) override; bool destroyTranslocatedPathForUser(const string &translocatedPath) override; void appLaunchCheckin(pid_t pid) override; private: TranslocatorClient() = delete; TranslocatorClient(const TranslocatorClient &that) = delete; + + string requestTranslocation(const int fdToTranslocate, const int destFd, const TranslocationOptions flags); + dispatch_queue_t syncQ; xpc_connection_t service; }; diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateEnumUtils.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateEnumUtils.hpp new file mode 100644 index 00000000..fba90b9f --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateEnumUtils.hpp @@ -0,0 +1,40 @@ +// +// SecTranslocateEnumUtils.h +// Security +// +// + +#ifndef SecTranslocateEnumUtils_h +#define SecTranslocateEnumUtils_h + +#include + +template +Enum operator |(Enum lhs, Enum rhs) +{ + static_assert(std::is_enum::value, + "template parameter is not an enum type"); + + using underlying = typename std::underlying_type::type; + + return static_cast ( + static_cast(lhs) | + static_cast(rhs) + ); +} + +template +Enum operator &(Enum lhs, Enum rhs) +{ + static_assert(std::is_enum::value, + "template parameter is not an enum type"); + + using underlying = typename std::underlying_type::type; + + return static_cast ( + static_cast(lhs) & + static_cast(rhs) + ); +} + +#endif /* SecTranslocateEnumUtils_h */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp index 8ed15544..85a6be79 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp @@ -44,7 +44,8 @@ class Translocator { public: virtual ~Translocator() {}; - virtual string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) = 0; + virtual string translocatePathForUser(const TranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) = 0; + virtual string translocatePathForUser(const GenericTranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) = 0; virtual bool destroyTranslocatedPathForUser(const string &translocatedPath) = 0; virtual void appLaunchCheckin(pid_t pid) = 0; }; diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp index a515ba69..4c2c8b7e 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp @@ -81,23 +81,38 @@ TranslocatorServer::~TranslocatorServer() // This is intended for use by the host process of the server if necessary // Create a translocation for original path if appropriate -string TranslocatorServer::translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) +string TranslocatorServer::translocatePathForUser(const TranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) { __block string newPath; __block exception_ptr exception(0); dispatch_sync(syncQ, ^{ - try - { - newPath = Security::SecTranslocate::translocatePathForUser(originalPath,destPath); - } - catch (...) - { + try { + newPath = Security::SecTranslocate::translocatePathForUser(originalPath,destFd); + } catch (...) { exception = current_exception(); } }); - if (exception) - { + if (exception) { + rethrow_exception(exception); + } + return newPath; +} + +string TranslocatorServer::translocatePathForUser(const GenericTranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) +{ + __block string newPath; + __block exception_ptr exception(0); + + dispatch_sync(syncQ, ^{ + try { + newPath = Security::SecTranslocate::translocatePathForUser(originalPath,destFd); + } + catch (...) { + exception = current_exception(); + } + }); + if (exception) { rethrow_exception(exception); } return newPath; diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp index b8cf62ec..709281a9 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp @@ -51,7 +51,8 @@ public: TranslocatorServer(dispatch_queue_t q); ~TranslocatorServer(); - string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) override; + string translocatePathForUser(const TranslocationPath &originalPath, ExtendedAutoFileDesc &destPath) override; + string translocatePathForUser(const GenericTranslocationPath &originalPath, ExtendedAutoFileDesc &destPath) override; bool destroyTranslocatedPathForUser(const string &translocatedPath) override; void appLaunchCheckin(pid_t pid) override; diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp index 9c1595ae..dfc7e7b4 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -40,17 +41,23 @@ #include #include -#include +#include #include #include "SecTranslocateShared.hpp" #include "SecTranslocateUtilities.hpp" +#include "SecTranslocateEnumUtils.hpp" + +#define NULLM_UNVEIL 0x1ULL << 2 +struct null_mount_conf { + uint64_t flags; +}; namespace Security { - + namespace SecTranslocate { - + using namespace std; /* String Constants for XPC dictionary passing */ @@ -62,6 +69,7 @@ const char* kSecTranslocateXPCFuncCheckIn = "check-in"; const char* kSecTranslocateXPCMessageFunction = "function"; const char* kSecTranslocateXPCMessageOriginalPath = "original"; const char* kSecTranslocateXPCMessageDestinationPath = "dest"; +const char* kSecTranslocateXPCMessageOptions= "opts"; const char* kSecTranslocateXPCMessagePid = "pid"; /*XPC message reply keys */ @@ -76,14 +84,14 @@ static vector getMountTableSnapshot(); static string mountExistsForUser(const string &translationDirForUser, const TranslocationPath &originalPath, const string &destMount); -static void validateMountpoint(const string &mountpoint, bool owned=false); -static string makeNewMountpoint(const string &translationDir); -static string newAppPath (const string &mountPoint, const TranslocationPath &originalPath); +static void validateMountpoint(ExtendedAutoFileDesc &mountpointFd, bool owned = false); +static ExtendedAutoFileDesc makeNewMountpoint(const string &translationDir); +static string newAppPath (ExtendedAutoFileDesc &mountPointFd, const TranslocationPath &originalPath); static void cleanupTranslocationDirForUser(const string &userDir); static int removeMountPoint(const string &mountpoint, bool force = false); /* calculate whether a translocation should occur and where from */ -TranslocationPath::TranslocationPath(string originalPath) +void TranslocationPath::init() { /* To support testing of translocation the policy is as follows: @@ -112,65 +120,59 @@ TranslocationPath::TranslocationPath(string originalPath) bundle can not be unquarantined. If the inner bundle is quarantined then any bundle containing it must also have been quarantined. */ - - ExtendedAutoFileDesc fd(originalPath); - - should = false; - realOriginalPath = fd.getRealPath(); + + mShould = false; + mRealOriginalPath = mFd.getRealPath(); /* don't translocate if it already is */ /* only consider translocation if the thing being asked about is marked for translocation */ - /* Nullfs can't translocate other mount's roots so abort if its a mountpoint */ - if(!fd.isFileSystemType(NULLFS_FSTYPE) && fd.isQuarantined() && fd.shouldTranslocate() && !fd.isMountPoint()) - { - ExtendedAutoFileDesc &&outermost = findOuterMostCodeBundleForFD(fd); + /* Nullfs can't translocate other mount's roots so abort if its a mountpoint */ + if (!mFd.isFileSystemType(NULLFS_FSTYPE) && mFd.isQuarantined() && mFd.shouldTranslocate() && !mFd.isMountPoint()) { + ExtendedAutoFileDesc &&outermost = findOuterMostCodeBundleForFD(mFd); - should = outermost.isQuarantined() && outermost.shouldTranslocate(); - pathToTranslocate = outermost.getRealPath(); + mShould = outermost.isQuarantined() && outermost.shouldTranslocate(); + if (mShould && outermost.isSandcastleProtected()) { + seccritical("SecTranslocate, Translocation Path, path should be translocated but is sandcastle restricted: outermost(%s), original(%s)", + outermost.getRealPath().c_str(), + mRealOriginalPath.c_str()); + UnixError::throwMe(EPERM); + } + mPathToTranslocate = outermost.getRealPath(); + mFd = std::move(outermost); /* Calculate the path that will be needed to give the caller the path they asked for originally but in the translocated place */ - if (should) - { - vector originalComponents = splitPath(realOriginalPath); - vector toTranslocateComponents = splitPath(pathToTranslocate); + if (mShould) { + vector originalComponents = splitPath(mRealOriginalPath); + vector toTranslocateComponents = splitPath(mPathToTranslocate); if (toTranslocateComponents.size() == 0 || - toTranslocateComponents.size() > originalComponents.size()) - { - Syslog::error("SecTranslocate, TranslocationPath, path calculation failed:\n\toriginal: %s\n\tcalculated: %s", - realOriginalPath.c_str(), - pathToTranslocate.c_str()); + toTranslocateComponents.size() > originalComponents.size()) { + secerror("SecTranslocate, TranslocationPath, path calculation failed:\n\toriginal: %s\n\tcalculated: %s", + mRealOriginalPath.c_str(), + mPathToTranslocate.c_str()); UnixError::throwMe(EINVAL); } - componentNameToTranslocate = toTranslocateComponents.back(); + mComponentNameToTranslocate = toTranslocateComponents.back(); - for(size_t cnt = 0; cnt < originalComponents.size(); cnt++) - { - if (cnt < toTranslocateComponents.size()) - { - if (toTranslocateComponents[cnt] != originalComponents[cnt]) - { - Syslog::error("SecTranslocate, TranslocationPath, translocation path calculation failed:\n\toriginal: %s\n\tcalculated: %s", - realOriginalPath.c_str(), - pathToTranslocate.c_str()); + for (size_t cnt = 0; cnt < originalComponents.size(); cnt++) { + if (cnt < toTranslocateComponents.size()) { + if (toTranslocateComponents[cnt] != originalComponents[cnt]) { + secerror("SecTranslocate, TranslocationPath, translocation path calculation failed:\n\toriginal: %s\n\tcalculated: %s", + mRealOriginalPath.c_str(), + mPathToTranslocate.c_str()); UnixError::throwMe(EINVAL); } - } - else - { + } else { /* want pathInsideTranslocationPoint to look like: a/b/c i.e. internal / but not at the front or back. */ - if(pathInsideTranslocationPoint.empty()) - { - pathInsideTranslocationPoint = originalComponents[cnt]; - } - else - { - pathInsideTranslocationPoint += "/" + originalComponents[cnt]; + if (mPathInsideTranslocationPoint.empty()) { + mPathInsideTranslocationPoint = originalComponents[cnt]; + } else { + mPathInsideTranslocationPoint += "/" + originalComponents[cnt]; } } } @@ -179,37 +181,40 @@ TranslocationPath::TranslocationPath(string originalPath) } /* if we should translocate and a stored path inside the translocation point exists, then add it to the - passed in string. If no path inside is stored, then return the passed in string if translocation - should occur, and the original path for the TranslocationPath if translocation shouldn't occur */ + passed in string. If no path inside is stored, then return the passed in string if translocation + should occur, and the original path for the TranslocationPath if translocation shouldn't occur */ string TranslocationPath::getTranslocatedPathToOriginalPath(const string &translocationPoint) const { string seperator = translocationPoint.back() != '/' ? "/" : ""; - if (should) - { - if(!pathInsideTranslocationPoint.empty()) - { - return translocationPoint + seperator + pathInsideTranslocationPoint; - } - else - { + if (mShould) { + if (!mPathInsideTranslocationPoint.empty()) { + return translocationPoint + seperator + mPathInsideTranslocationPoint; + } else { return translocationPoint; } - } - else - { + } else { //If we weren't supposed to translocate return the original path. - return realOriginalPath; + return mRealOriginalPath; + } +} + +int TranslocationPath::getFdForPathToTranslocate() const +{ + if (mFd.isOpen()) { + return mFd.fd(); + } else { + secerror("SecTranslocate: no open fd for path: %s", mPathToTranslocate.c_str()); + UnixError::throwMe(ENOENT); } } /* Given an fd for a path find the outermost acceptable code bundle and return an fd for that. - an acceptable outermost bundle is quarantined, user approved, and a code bundle. - If nothing is found outside the path to the fd provided, then passed in fd or a copy there of is returned.*/ + an acceptable outermost bundle is quarantined, user approved, and a code bundle. + If nothing is found outside the path to the fd provided, then passed in fd or a copy there of is returned.*/ ExtendedAutoFileDesc TranslocationPath::findOuterMostCodeBundleForFD(ExtendedAutoFileDesc &fd) { - if( fd.isMountPoint() || !fd.isQuarantined()) - { + if (fd.isMountPoint() || !fd.isQuarantined()) { return fd; } vector path = splitPath(fd.getRealPath()); @@ -222,25 +227,22 @@ ExtendedAutoFileDesc TranslocationPath::findOuterMostCodeBundleForFD(ExtendedAut lastGood := path := canonicalized path to be launched while path is not a mount point - if path is quarantined and not user-approved then exit loop # Gatekeeper has not cleared this code - if SecStaticCodeCreateWithPath(path) succeeds # used as an “is a code bundle” oracle - then lastGood := path - path := parent directory of path + if path is quarantined and not user-approved then exit loop # Gatekeeper has not cleared this code + if SecStaticCodeCreateWithPath(path) succeeds # used as an “is a code bundle” oracle + then lastGood := path + path := parent directory of path return lastGood */ - while(currentIndex) - { + while (currentIndex) { ExtendedAutoFileDesc currFd(pathToCheck); - if (currFd.isMountPoint() || !currFd.isQuarantined() || !currFd.isUserApproved()) - { + if (currFd.isMountPoint() || !currFd.isQuarantined() || !currFd.isUserApproved()) { break; } SecStaticCodeRef staticCodeRef = NULL; - if( SecStaticCodeCreateWithPath(CFTempURL(currFd.getRealPath()), kSecCSDefaultFlags, &staticCodeRef) == errSecSuccess) - { + if (SecStaticCodeCreateWithPath(CFTempURL(currFd.getRealPath()), kSecCSDefaultFlags, &staticCodeRef) == errSecSuccess) { lastGoodIndex = currentIndex; CFRelease(staticCodeRef); } @@ -252,41 +254,60 @@ ExtendedAutoFileDesc TranslocationPath::findOuterMostCodeBundleForFD(ExtendedAut return ExtendedAutoFileDesc(joinPathUpTo(path, lastGoodIndex)); } +void GenericTranslocationPath::init() +{ + mRealOriginalPath = mFd.getRealPath(); + mShould = false; + + /* don't translocate if it already is */ + /* Nullfs can't translocate other mount's roots so abort if its a mountpoint */ + if (mFd.isFileSystemType(NULLFS_FSTYPE) || mFd.isMountPoint()) { + return; + } + + mComponentNameToTranslocate = splitPath(mRealOriginalPath).back(); + + if (mFd.isSandcastleProtected()) { + seccritical("SecTranslocate, GenericTranslocation Path, path should be translocated but is sandcastle restricted: %s", + mRealOriginalPath.c_str()); + UnixError::throwMe(EPERM); + } + mShould = true; +} + +int GenericTranslocationPath::getFdForPathToTranslocate() const +{ + if (mFd.isOpen()) { + return mFd.fd(); + } else { + secerror("SecTranslocate: no open fd for path: %s", mRealOriginalPath.c_str()); + UnixError::throwMe(ENOENT); + } +} + /* Given an fd to a translocated file, build the path to the original file - Throws if the fd isn't in a nullfs mount for the calling user. */ + Throws if the fd isn't in a nullfs mount. */ string getOriginalPath(const ExtendedAutoFileDesc& fd, bool* isDir) { if (!fd.isFileSystemType(NULLFS_FSTYPE) || isDir == NULL || - !fd.isInPrefixDir(fd.getMountPoint())) - { - Syslog::error("SecTranslocate::getOriginalPath called with invalid params: fs_type = %s, isDir = %p, realPath = %s, mountpoint = %s", - fd.getFsType().c_str(), - isDir, - fd.getRealPath().c_str(), - fd.getMountPoint().c_str()); + !fd.isInPrefixDir(fd.getMountPoint())) { + secerror("SecTranslocate::getOriginalPath called with invalid params: fs_type = %s, isDir = %p, realPath = %s, mountpoint = %s", + fd.getFsType().c_str(), + isDir, + fd.getRealPath().c_str(), + fd.getMountPoint().c_str()); UnixError::throwMe(EINVAL); } - string translocationBaseDir = translocationDirForUser(); - - if(!fd.isInPrefixDir(translocationBaseDir)) - { - Syslog::error("SecTranslocate::getOriginal path called with path (%s) that doesn't belong to user (%d)", - fd.getRealPath().c_str(), - getuid()); - UnixError::throwMe(EPERM); - } - *isDir = fd.isA(S_IFDIR); vector mountFromPath = splitPath(fd.getMountFromPath()); vector mountPointPath = splitPath(fd.getMountPoint()); vector translocatedRealPath = splitPath(fd.getRealPath()); - if (mountPointPath.size() > translocatedRealPath.size()) - { - Syslog::warning("SecTranslocate: invalid translocated path %s", fd.getRealPath().c_str()); + if (mountPointPath.size() > translocatedRealPath.size()) { + secwarning("SecTranslocate: invalid translocated path %s", fd.getRealPath().c_str()); UnixError::throwMe(EINVAL); } @@ -294,56 +315,43 @@ string getOriginalPath(const ExtendedAutoFileDesc& fd, bool* isDir) int i; - for( i = 0; i app = splitPath(appPath); // throws if empty or not absolute vector original = splitPath(originalPath); //throws if empty or not absolute - if (original.size() == 0) // had to have at least one directory, can't null mount / - { - Syslog::error("SecTranslocate: invalid original path: %s", originalPath.c_str()); + if (original.size() == 0) { // had to have at least one directory, can't null mount / + secerror("SecTranslocate: invalid original path: %s", originalPath.c_str()); UnixError::throwMe(EINVAL); } if (app.size() >= 3 && //the app path must have at least 3 directories, can't null mount onto / - app.back() == original.back()) //last directory of both match - { + app.back() == original.back()) { //last directory of both match app.pop_back(); - if(app.back() == "d") //last directory of app path is preceded by /d/ - { + if (app.back() == "d") { //last directory of app path is preceded by /d/ app.pop_back(); result = joinPath(app); goto end; } } - Syslog::error("SecTranslocate: invalid app path: %s", appPath.c_str()); + secerror("SecTranslocate: invalid app path: %s", appPath.c_str()); UnixError::throwMe(EINVAL); end: @@ -412,17 +417,14 @@ static vector getMountTableSnapshot() 4. if the read actually filled up that double size try again once otherwise we are done */ - while(retry) - { + while (retry) { fs_cnt_first = getfsstat(NULL, 0 , MNT_WAIT); - if(fs_cnt_first <= 0) - { - Syslog::warning("SecTranslocate: error(%d) getting mount table info.", errno); + if (fs_cnt_first <= 0) { + secwarning("SecTranslocate: error(%d) getting mount table info.", errno); UnixError::throwMe(); } - if( fs_cnt_first == fs_cnt_second) - { + if (fs_cnt_first == fs_cnt_second) { /* this path only applies on a retry. If our second attempt to get the size is the same as what we already read then break. */ break; @@ -431,31 +433,75 @@ static vector getMountTableSnapshot() mntInfo.resize(fs_cnt_first*2); fs_cnt_second = getfsstat(mntInfo.data(), (int)(mntInfo.size() * sizeof(struct statfs)), MNT_WAIT); - if (fs_cnt_second <= 0) - { - Syslog::warning("SecTranslocate: error(%d) getting mount table info.", errno); + if (fs_cnt_second <= 0) { + secwarning("SecTranslocate: error(%d) getting mount table info.", errno); UnixError::throwMe(); } - if( fs_cnt_second == mntInfo.size()) - { + if (fs_cnt_second == mntInfo.size()) { retry--; - } - else - { + } else { mntInfo.resize(fs_cnt_second); // trim the vector to what we actually need break; } } - if( retry == 0) - { - Syslog::warning("SecTranslocate: mount table is growing very quickly"); + if (retry == 0) { + secwarning("SecTranslocate: mount table is growing very quickly"); } return mntInfo; } +static bool pathExistsInMountTable(const GenericTranslocationPath& path, const string& mountpoint) +{ + vector mntbuf = getMountTableSnapshot(); + + /* Save the untranslocated inode number*/ + ExtendedAutoFileDesc::UnixStat untranslocatedStat; + + if (stat(path.getOriginalRealPath().c_str(), &untranslocatedStat)) { + errno_t err = errno; + secwarning("SecTranslocate: failed to stat original path (%d): %s", + err, + path.getOriginalRealPath().c_str()); + UnixError::throwMe(err); + } + + for (auto &i : mntbuf) { + string mountOnName = i.f_mntonname; + + if (path.getOriginalRealPath() == i.f_mntfromname && //mount is for the requested path + mountpoint == mountOnName && //mount to is the same + strcmp(i.f_fstypename, NULLFS_FSTYPE) == 0) {// mount is a nullfs mount + /* + find the inode number for mountOnName + */ + string pathToTranslocatedApp = mountOnName+"/d/"+path.getComponentNameToTranslocate(); + + ExtendedAutoFileDesc::UnixStat oldTranslocatedStat; + + if (stat(pathToTranslocatedApp.c_str(), &oldTranslocatedStat)) { + /* We should have access to this path and it should be real so complain if thats not true. */ + errno_t err = errno; + secwarning("SecTranslocate: expected app not inside mountpoint: %s (error: %d)", pathToTranslocatedApp.c_str(), err); + UnixError::throwMe(err); + } + + if (untranslocatedStat.st_ino != oldTranslocatedStat.st_ino) { + /* We have two Apps with the same name at the same path but different inodes. This means that the + translocated path is broken and should be removed */ + destroyTranslocatedPathForUser(pathToTranslocatedApp); + continue; + } + + return true; + } + } + + return false; +} + /* Given the directory where app translocations go for this user, the path to the app to be translocated and an optional destination mountpoint path. Check the mount table to see if a mount point already user, for this app. If a destMountPoint is provided, make sure it is for this user, and that @@ -464,17 +510,15 @@ static string mountExistsForUser(const string &translationDirForUser, const Tran { string result; // start empty - if(!destMountPoint.empty()) - { + if (!destMountPoint.empty()) { /* Validate that destMountPoint path is well formed and for this user well formed means it is === translationDirForUser/<1 directory> */ vector splitDestMount = splitPath(destMountPoint); - if(splitDestMount.size() < 2) //translationDirForUser is never / - { - Syslog::warning("SecTranslocate: invalid destination mount point: %s", - destMountPoint.c_str()); + if (splitDestMount.size() < 2) { //translationDirForUser is never / + secwarning("SecTranslocate: invalid destination mount point: %s", + destMountPoint.c_str()); UnixError::throwMe(EINVAL); } @@ -482,11 +526,10 @@ static string mountExistsForUser(const string &translationDirForUser, const Tran string destBaseDir = joinPath(splitDestMount)+"/"; //translationDirForUser has a / at the end - if (translationDirForUser != destBaseDir) - { - Syslog::warning("SecTranslocate: invalid destination mount point for user\n\tExpected: %s\n\tRequested: %s", - translationDirForUser.c_str(), - destBaseDir.c_str()); + if (translationDirForUser != destBaseDir) { + secwarning("SecTranslocate: invalid destination mount point for user\n\tExpected: %s\n\tRequested: %s", + translationDirForUser.c_str(), + destBaseDir.c_str()); /* requested destination isn't valid for the user */ UnixError::throwMe(EINVAL); } @@ -497,17 +540,15 @@ static string mountExistsForUser(const string &translationDirForUser, const Tran /* Save the untranslocated inode number*/ ExtendedAutoFileDesc::UnixStat untranslocatedStat; - if (stat(originalPath.getPathToTranslocate().c_str(), &untranslocatedStat)) - { + if (stat(originalPath.getPathToTranslocate().c_str(), &untranslocatedStat)) { errno_t err = errno; - Syslog::warning("SecTranslocate: failed to stat original path (%d): %s", - err, - originalPath.getPathToTranslocate().c_str()); + secwarning("SecTranslocate: failed to stat original path (%d): %s", + err, + originalPath.getPathToTranslocate().c_str()); UnixError::throwMe(err); } - for (auto &i : mntbuf) - { + for (auto &i : mntbuf) { string mountOnName = i.f_mntonname; size_t lastNonSlashPos = mountOnName.length() - 1; //start at the end of the string @@ -521,16 +562,13 @@ static string mountExistsForUser(const string &translationDirForUser, const Tran if (i.f_mntfromname == originalPath.getPathToTranslocate() && //mount is for the requested path strcmp(i.f_fstypename, NULLFS_FSTYPE) == 0 && // mount is a nullfs mount lastNonSlashPos > translationDirForUser.length()-1 && // no shenanigans, there must be more directory here than just the translation dir - strncmp(i.f_mntonname, translationDirForUser.c_str(), translationDirForUser.length()) == 0) //mount is inside the translocation dir - { - if(!destMountPoint.empty()) - { - if (mountOnName != destMountPoint) - { + strncmp(i.f_mntonname, translationDirForUser.c_str(), translationDirForUser.length()) == 0) { //mount is inside the translocation dir + if (!destMountPoint.empty()) { + if (mountOnName != destMountPoint) { /* a mount exists for this path, but its not the one requested */ - Syslog::warning("SecTranslocate: requested destination doesn't match existing\n\tExpected: %s\n\tRequested: %s", - i.f_mntonname, - destMountPoint.c_str()); + secwarning("SecTranslocate: requested destination doesn't match existing\n\tExpected: %s\n\tRequested: %s", + i.f_mntonname, + destMountPoint.c_str()); UnixError::throwMe(EEXIST); } } @@ -541,18 +579,16 @@ static string mountExistsForUser(const string &translationDirForUser, const Tran ExtendedAutoFileDesc::UnixStat oldTranslocatedStat; - if (stat(pathToTranslocatedApp.c_str(), &oldTranslocatedStat)) - { + if (stat(pathToTranslocatedApp.c_str(), &oldTranslocatedStat)) { /* We should have access to this path and it should be real so complain if thats not true. */ errno_t err = errno; - Syslog::warning("SecTranslocate: expected app not inside mountpoint: %s (error: %d)", pathToTranslocatedApp.c_str(), err); + secwarning("SecTranslocate: expected app not inside mountpoint: %s (error: %d)", pathToTranslocatedApp.c_str(), err); UnixError::throwMe(err); } - if(untranslocatedStat.st_ino != oldTranslocatedStat.st_ino) - { + if (untranslocatedStat.st_ino != oldTranslocatedStat.st_ino) { /* We have two Apps with the same name at the same path but different inodes. This means that the - translocated path is broken and should be removed */ + translocated path is broken and should be removed */ destroyTranslocatedPathForUser(pathToTranslocatedApp); continue; } @@ -566,7 +602,7 @@ static string mountExistsForUser(const string &translationDirForUser, const Tran } /* Given what we think is a valid mountpoint, perform a sanity check, and clean up if we are wrong */ -static void validateMountpoint(const string &mountpoint, bool owned) +static void validateMountpoint(ExtendedAutoFileDesc& mountpointFd, bool owned) { /* Requirements: 1. can be opened @@ -584,14 +620,14 @@ static void validateMountpoint(const string &mountpoint, bool owned) unfortunately this is still racy, and mount() is path based so we can't lock down the directory until the mount succeeds (lock down is because of the entitlement checks in nullfs))*/ - DIR* dir = opendir(mountpoint.c_str()); + FileDesc dirFd = mountpointFd.dup(); + DIR* dir = fdopendir(dirFd.fd()); int error = 0; - if (dir == NULL) - { + if (dir == NULL) { error = errno; - Syslog::warning("SecTranslocate: mountpoint is not a directory or doesn't exist: %s", - mountpoint.c_str()); + secwarning("SecTranslocate: mountpoint is not a directory or doesn't exist: %s", + mountpointFd.getRealPath().c_str()); UnixError::throwMe(error); } @@ -601,12 +637,10 @@ static void validateMountpoint(const string &mountpoint, bool owned) struct dirent dirbuf; int cnt = 0; int err = 0; - while(((err = readdir_r(dir, &dirbuf, &d)) == 0) && - d != NULL) - { + while (((err = readdir_r(dir, &dirbuf, &d)) == 0) && + d != NULL) { /* skip . and .. but break if there is more than that */ - if(++cnt > 2) - { + if (++cnt > 2) { isEmpty = false; break; } @@ -615,67 +649,45 @@ static void validateMountpoint(const string &mountpoint, bool owned) error = errno; (void)closedir(dir); - if(err) - { - Syslog::warning("SecTranslocate: error while checking that mountpoint is empty"); + if (err) { + secwarning("SecTranslocate: error while checking that mountpoint is empty"); UnixError::throwMe(error); } - if(!isEmpty) - { - Syslog::warning("Sectranslocate: mountpoint is not empty: %s", - mountpoint.c_str()); + if (!isEmpty) { + secwarning("SecTranslocate: mountpoint is not empty: %s", + mountpointFd.getRealPath().c_str()); UnixError::throwMe(EBUSY); } - /* now check that the path is not a mountpoint */ - ExtendedAutoFileDesc fd(mountpoint); + isMount = mountpointFd.isMountPoint(); - if(!fd.pathIsAbsolute()) - { - Syslog::warning("SecTranslocate: mountpoint isn't fully resolved\n\tExpected: %s\n\tActual: %s", - fd.getRealPath().c_str(), - mountpoint.c_str()); + if (isMount) { + secwarning("SecTranslocate:Translocation failed, new mountpoint is already a mountpoint (%s)", + mountpointFd.getRealPath().c_str()); UnixError::throwMe(EINVAL); } - - isMount = fd.isMountPoint(); - - if(isMount) - { - Syslog::warning("SecTranslocate:Translocation failed, new mountpoint is already a mountpoint (%s)", - mountpoint.c_str()); - UnixError::throwMe(EINVAL); - } - } - catch(...) - { - if(owned) - { - if (!isMount) - { - if (isDir) - { - if(isEmpty) - { - rmdir(mountpoint.c_str()); + } catch(...) { + if (owned) { + if (!isMount) { + if (isDir) { + if (isEmpty) { + rmdir(mountpointFd.getRealPath().c_str()); } /* Already logged the else case above */ - } - else - { - Syslog::warning("SecTranslocate: unexpected file detected at mountpoint location (%s). Deleting.", - mountpoint.c_str()); - unlink(mountpoint.c_str()); + } else { + secwarning("SecTranslocate: unexpected file detected at mountpoint location (%s). Deleting.", + mountpointFd.getRealPath().c_str()); + unlink(mountpointFd.getRealPath().c_str()); } } } - rethrow_exception(current_exception()); + throw; } } /* Create and validate the directory that we should mount at but don't create the mount yet */ -static string makeNewMountpoint(const string &translationDir) +static ExtendedAutoFileDesc makeNewMountpoint(const string &translationDir) { AutoFileDesc fd(getFDForDirectory(translationDir)); @@ -683,11 +695,12 @@ static string makeNewMountpoint(const string &translationDir) UnixError::check(mkdirat(fd, uuid.c_str(), 0500)); - string mountpoint = translationDir+uuid; + string mountpoint = translationDir + uuid; + ExtendedAutoFileDesc mountpointFd(mountpoint); - validateMountpoint(mountpoint); + validateMountpoint(mountpointFd); - return mountpoint; + return mountpointFd; } /* If the original path has mountpoint quarantine info, apply it to the new mountpoint*/ @@ -699,57 +712,50 @@ static void setMountPointQuarantineIfNecessary(const string &mountPoint, const s UnixError::check(statfs(originalPath.c_str(), &sfsbuf)); qtn_file_t original_attr = qtn_file_alloc(); - if (original_attr != NULL) - { - if (qtn_file_init_with_mount_point(original_attr, sfsbuf.f_mntonname) == 0) - { + if (original_attr != NULL) { + if (qtn_file_init_with_mount_point(original_attr, sfsbuf.f_mntonname) == 0) { error = qtn_file_apply_to_mount_point(original_attr, mountPoint.c_str()); } qtn_file_free(original_attr); - } - else - { + } else { error = errno; } - if (error) - { - Syslog::warning("SecTranslocate: Failed to apply quarantine information\n\tMountpoint: %s\n\tOriginal Path: %s", - mountPoint.c_str(), - originalPath.c_str()); + if (error) { + secwarning("SecTranslocate: Failed to apply quarantine information\n\tMountpoint: %s\n\tOriginal Path: %s", + mountPoint.c_str(), + originalPath.c_str()); UnixError::throwMe(error); } } -/* Given the path to a new mountpoint and the original path to translocate, calculate the path - to the desired app in the new mountpoint, and sanity check that calculation */ -static string newAppPath (const string &mountPoint, const TranslocationPath &originalPath) +static string newAppPathFrom (ExtendedAutoFileDesc &mountPointFd, const string &outPath) { - string midPath = mountPoint+"/d"; - string outPath = originalPath.getTranslocatedPathToOriginalPath(midPath+"/"+originalPath.getComponentNameToTranslocate()); - + string midPath = mountPointFd.getRealPath()+"/d"; + /* ExtendedAutoFileDesc will throw if one of these doesn't exist or isn't accessible */ - ExtendedAutoFileDesc mountFd(mountPoint); + /* Note mountFd and mountPointFd are not the same. mountPointFd refers to the mount point vnode before mounting + and mountFd refers to the same path after mounting. That means the mountPointFd should report being an + apfs vnode where as mountfd should report being a nullfs vnode.*/ + ExtendedAutoFileDesc mountFd(mountPointFd.getRealPath()); ExtendedAutoFileDesc midFd(midPath); ExtendedAutoFileDesc outFd(outPath); - if(!outFd.isFileSystemType(NULLFS_FSTYPE) || - !mountFd.isFileSystemType(NULLFS_FSTYPE) || - !midFd.isFileSystemType(NULLFS_FSTYPE)) - { - Syslog::warning("SecTranslocate::App exists at expected translocation path (%s) but isn't a nullfs mount (%s)", - outPath.c_str(), - outFd.getFsType().c_str()); + if (!outFd.isFileSystemType(NULLFS_FSTYPE) || + !mountFd.isFileSystemType(NULLFS_FSTYPE) || + !midFd.isFileSystemType(NULLFS_FSTYPE)) { + secwarning("SecTranslocate::App exists at expected translocation path (%s) but isn't a nullfs mount (%s)", + outPath.c_str(), + outFd.getFsType().c_str()); UnixError::throwMe(EINVAL); } - if(!outFd.pathIsAbsolute() || - !mountFd.pathIsAbsolute() || - !midFd.pathIsAbsolute() ) - { - Syslog::warning("SecTranslocate::App path isn't resolved\n\tGot: %s\n\tExpected: %s", - outFd.getRealPath().c_str(), - outPath.c_str()); + if (!outFd.pathIsAbsolute() || + !mountFd.pathIsAbsolute() || + !midFd.pathIsAbsolute()) { + secwarning("SecTranslocate::App path isn't resolved\n\tGot: %s\n\tExpected: %s", + outFd.getRealPath().c_str(), + outPath.c_str()); UnixError::throwMe(EINVAL); } @@ -759,96 +765,148 @@ static string newAppPath (const string &mountPoint, const TranslocationPath &ori /* different fsids mean that there is more than one volume between the expected mountpoint and the expected app path */ if (memcmp(&outFsid, &midFsid, sizeof(fsid_t)) != 0 || - memcmp(&outFsid, &mountFsid, sizeof(fsid_t)) != 0) - { - Syslog::warning("SecTranslocate:: the fsid is not consistent between app, /d/ and mountpoint"); + memcmp(&outFsid, &mountFsid, sizeof(fsid_t)) != 0) { + secwarning("SecTranslocate:: the fsid is not consistent between app, /d/ and mountpoint"); UnixError::throwMe(EINVAL); } return outFd.getRealPath(); } + +static string newAppPath (ExtendedAutoFileDesc &mountPointFd, const GenericTranslocationPath &originalPath) +{ + string outPath = mountPointFd.getRealPath()+"/d/"+originalPath.getComponentNameToTranslocate(); + return newAppPathFrom(mountPointFd, outPath); +} + +/* Given the path to a new mountpoint and the original path to translocate, calculate the path + to the desired app in the new mountpoint, and sanity check that calculation */ +static string newAppPath (ExtendedAutoFileDesc &mountPointFd, const TranslocationPath &originalPath) +{ + string outPath = originalPath.getTranslocatedPathToOriginalPath(mountPointFd.getRealPath()+"/d/"+originalPath.getComponentNameToTranslocate()); + return newAppPathFrom(mountPointFd, outPath); +} + +static std::vector getMountData(const string& toTranslocate, TranslocationOptions opts) { + std::vector data; + data.reserve(sizeof(null_mount_conf) + toTranslocate.size() + 1); + null_mount_conf conf = {0}; + if ((opts & TranslocationOptions::Unveil) == TranslocationOptions::Unveil) { + conf.flags = NULLM_UNVEIL; + } + data.insert(data.end(), reinterpret_cast(&conf), reinterpret_cast(&conf + 1)); + data.insert(data.end(), toTranslocate.c_str(), toTranslocate.c_str() + toTranslocate.size()); + data.push_back('\0'); + return data; +} + /* Create an app translocation point given the original path and an optional destination path. note the destination path can only be an outermost path (where the translocation would happen) and not a path to nested code synchronize the process on the dispatch queue. */ -string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) +string translocatePathForUser(const TranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) { string newPath; - exception_ptr exception(0); string mountpoint; - bool owned = false; - try - { + ExtendedAutoFileDesc mountpointFd; + bool ownedDirectory = false; + bool ownedMount = false; + try { const string &toTranslocate = originalPath.getPathToTranslocate(); string baseDirForUser = translocationDirForUser(); //throws string destMountPoint; - if(!destPath.empty()) - { - destMountPoint = getMountpointFromAppPath(destPath, toTranslocate); //throws or returns a mountpoint + if (destFd.isOpen()) { + destMountPoint = getMountpointFromAppPath(destFd.realPath(), toTranslocate); //throws or returns a mountpoint } mountpoint = mountExistsForUser(baseDirForUser, originalPath, destMountPoint); //throws, detects invalid destMountPoint string - if (!mountpoint.empty()) - { + if (!mountpoint.empty()) { + ExtendedAutoFileDesc fd(mountpoint); /* A mount point exists already so bail*/ - newPath = newAppPath(mountpoint, originalPath); + newPath = newAppPath(fd, originalPath); return newPath; /* exit the block */ } - if (destMountPoint.empty()) - { - mountpoint = makeNewMountpoint(baseDirForUser); //throws - owned = true; - } - else - { - AutoFileDesc fd(getFDForDirectory(destMountPoint, &owned)); //throws, makes the directory if it doesn't exist - - validateMountpoint(destMountPoint, owned); //throws - mountpoint = destMountPoint; + if (destMountPoint.empty()) { + mountpointFd = makeNewMountpoint(baseDirForUser); //throws + ownedDirectory = true; + } else { + mountpointFd = getFDForDirectory(destMountPoint, &ownedDirectory); //throws, makes the directory if it doesn't exist + validateMountpoint(mountpointFd, ownedDirectory); //throws } - UnixError::check(mount(NULLFS_FSTYPE, mountpoint.c_str(), MNT_RDONLY, (void*)toTranslocate.c_str())); + auto mount_data = getMountData(toTranslocate, originalPath.getOptions()); + UnixError::check(fmount(NULLFS_FSTYPE, mountpointFd.fd(), MNT_RDONLY, mount_data.data())); + ownedMount = true; - setMountPointQuarantineIfNecessary(mountpoint, toTranslocate); //throws + setMountPointQuarantineIfNecessary(mountpointFd.getRealPath(), toTranslocate); //throws - newPath = newAppPath(mountpoint, originalPath); //throws + newPath = newAppPath(mountpointFd, originalPath); //throws - if (!destPath.empty()) - { - if (newPath != originalPath.getTranslocatedPathToOriginalPath(destPath)) - { - Syslog::warning("SecTranslocate: created app translocation point did not equal requested app translocation point\n\texpected: %s\n\tcreated: %s", - newPath.c_str(), - destPath.c_str()); + if (destFd.isOpen()) { + if (newPath != originalPath.getTranslocatedPathToOriginalPath(destFd.getRealPath())) { + secwarning("SecTranslocate: created app translocation point did not equal requested app translocation point\n\texpected: %s\n\tcreated: %s", + newPath.c_str(), + destFd.getRealPath().c_str()); /* the app at originalPath didn't match the one at destPath */ UnixError::throwMe(EINVAL); } } // log that we created a new mountpoint (we don't log when we are re-using) - Syslog::warning("SecTranslocateCreateSecureDirectoryForURL: created %s", - newPath.c_str()); - } - catch (...) - { - exception = current_exception(); - - if (!mountpoint.empty()) - { - if (owned) - { - /* try to unmount/delete (best effort)*/ - unmount(mountpoint.c_str(), 0); - rmdir(mountpoint.c_str()); + secwarning("SecTranslocateCreateSecureDirectoryForURL: created %s", + newPath.c_str()); + } catch (...) { + if (mountpointFd.isOpen()) { + if (ownedMount) { + // Try to unmount (best effort) + unmount(mountpointFd.getRealPath().c_str(), 0); + } + if (ownedDirectory) { + // Try to delete (best effort) + rmdir(mountpointFd.getRealPath().c_str()); } } + throw; } - /* rethrow outside the dispatch block */ - if (exception) - { - rethrow_exception(exception); + return newPath; +} + +string translocatePathForUser(const GenericTranslocationPath &originalPath, ExtendedAutoFileDesc &destFd) +{ + string newPath; + bool ownedMount = false; + + try { + const string &toTranslocate = originalPath.getOriginalRealPath(); + if (pathExistsInMountTable(originalPath, destFd.getRealPath())) { + /* A mount point exists already so bail*/ + newPath = newAppPath(destFd, originalPath); + return newPath; /* exit the block */ + } + + validateMountpoint(destFd, false); //throws + + auto mount_data = getMountData(toTranslocate, originalPath.getOptions()); + UnixError::check(fmount(NULLFS_FSTYPE, destFd.fd(), MNT_RDONLY, mount_data.data())); + ownedMount = true; + + setMountPointQuarantineIfNecessary(destFd.getRealPath(), toTranslocate); //throws + + newPath = newAppPath(destFd, originalPath); //throws + + // log that we created a new mountpoint (we don't log when we are re-using) + secwarning("SecTranslocateCreateGeneric: created %s", + newPath.c_str()); + } catch (...) { + if (destFd.isOpen()) { + if (ownedMount) { + //Try to unmount (best effort) + unmount(destFd.getRealPath().c_str(), 0); + } + } + throw; } return newPath; @@ -859,41 +917,34 @@ static void cleanupTranslocationDirForUser(const string &userDir) { DIR* translocationDir = opendir(userDir.c_str()); - if( translocationDir ) - { + if (translocationDir) { struct dirent de; struct statfs sfbuf; struct dirent * result = NULL; - while (readdir_r(translocationDir, &de, &result) == 0 && result) - { - if(result->d_type == DT_DIR) - { - if (result->d_name[0] == '.') - { - if(result->d_namlen == 1 || - (result->d_namlen == 2 && - result->d_name[1] == '.')) - { + while (readdir_r(translocationDir, &de, &result) == 0 && result) { + if (result->d_type == DT_DIR) { + if (result->d_name[0] == '.') { + if (result->d_namlen == 1 || + (result->d_namlen == 2 && + result->d_name[1] == '.')) { /* skip . and .. */ continue; } } string nextDir = userDir+string(result->d_name); if (0 == statfs(nextDir.c_str(), &sfbuf) && - nextDir == sfbuf.f_mntonname) - { + nextDir == sfbuf.f_mntonname) { /* its a mount point so continue */ continue; } /* not a mountpoint so delete it */ - if(unlinkat(dirfd(translocationDir), result->d_name, AT_REMOVEDIR)) - { - Syslog::warning("SecTranslocate: failed to delete directory during cleanup (error %d)\n\tUser Dir: %s\n\tDir to delete: %s", - errno, - userDir.c_str(), - result->d_name); + if (unlinkat(dirfd(translocationDir), result->d_name, AT_REMOVEDIR)) { + secwarning("SecTranslocate: failed to delete directory during cleanup (error %d)\n\tUser Dir: %s\n\tDir to delete: %s", + errno, + userDir.c_str(), + result->d_name); } } } @@ -907,15 +958,12 @@ static int removeMountPoint(const string &mountpoint, bool force) int error = 0; if (0 == unmount(mountpoint.c_str(), force ? MNT_FORCE : 0) && - 0 == rmdir(mountpoint.c_str())) - { - Syslog::warning("SecTranslocate: removed mountpoint: %s", - mountpoint.c_str()); - } - else - { + 0 == rmdir(mountpoint.c_str())) { + secwarning("SecTranslocate: removed mountpoint: %s", + mountpoint.c_str()); + } else { error = errno; - Syslog::warning("SecTranslocate: failed to unmount/remove mount point (errno: %d): %s", + secwarning("SecTranslocate: failed to unmount/remove mount point (errno: %d): %s", error, mountpoint.c_str()); } @@ -923,17 +971,16 @@ static int removeMountPoint(const string &mountpoint, bool force) } /* Destroy the specified translocated path, and clean up the user's translocation directory. - It is the caller's responsibility to synchronize the operation on the dispatch queue. */ + It is the caller's responsibility to synchronize the operation on the dispatch queue. */ bool destroyTranslocatedPathForUser(const string &translocatedPath) { bool result = false; int error = 0; /* steps - 1. verify the translocatedPath is for the user - 2. verify it is a nullfs mountpoint (with app path) - 3. unmount it - 4. delete it - 5. loop through all the other directories in the app translation directory looking for directories not mounted on and delete them. + 1. verify it is a nullfs mountpoint (with app path) + 2. unmount it + 3. delete it + 4. loop through all the other directories in the app translation directory looking for directories not mounted on and delete them. */ string baseDirForUser = translocationDirForUser(); // throws @@ -947,27 +994,24 @@ bool destroyTranslocatedPathForUser(const string &translocatedPath) To support unmount when nested apps end, just make sure that the requested path is on a translocation point for this user, not that they asked for a translocation point to be removed. */ - shouldUnmount = fd.isInPrefixDir(baseDirForUser) && fd.isFileSystemType(NULLFS_FSTYPE); + shouldUnmount = fd.isFileSystemType(NULLFS_FSTYPE); } - if (shouldUnmount) - { + if (shouldUnmount) { error = removeMountPoint(translocatedMountpoint); result = error == 0; } - if (!result && !error) - { - Syslog::warning("SecTranslocate: mountpoint does not belong to user(%d): %s", - getuid(), - translocatedPath.c_str()); + if (!result && !error) { + secwarning("SecTranslocate: mountpoint does not belong to user(%d): %s", + getuid(), + translocatedPath.c_str()); error = EPERM; } cleanupTranslocationDirForUser(baseDirForUser); - if (error) - { + if (error) { UnixError::throwMe(error); } @@ -989,16 +1033,15 @@ bool destroyTranslocatedPathsForUserOnVolume(const string &volumePath) struct statfs sb; fsid_t unmountingFsid; int haveUnmountingFsid = statfs(volumePath.c_str(), &sb); - int haveMntFromState = 0; + int haveMntFromState = 0; - memset(&unmountingFsid, 0, sizeof(unmountingFsid)); + memset(&unmountingFsid, 0, sizeof(unmountingFsid)); - if(haveUnmountingFsid == 0) { + if (haveUnmountingFsid == 0) { unmountingFsid = sb.f_fsid; } - for (auto &mnt : mountTable) - { + for (auto &mnt : mountTable) { /* we need to look at each translocation mount and check 1. is it ours @@ -1006,23 +1049,17 @@ bool destroyTranslocatedPathsForUserOnVolume(const string &volumePath) 3. if it does, is it the same as the volume we are cleaning up?, if so unmount it. */ if (strcmp(mnt.f_fstypename, NULLFS_FSTYPE) == 0 && - strncmp(mnt.f_mntonname, baseDirForUser.c_str(), baseDirForUser.length()) == 0) - { + strncmp(mnt.f_mntonname, baseDirForUser.c_str(), baseDirForUser.length()) == 0) { haveMntFromState = statfs(mnt.f_mntfromname, &sb); - if (haveMntFromState != 0) - { + if (haveMntFromState != 0) { // In this case we are trying to unmount a translocation point that points to nothing. Force it. // Not forcing it currently hangs in UBC cleanup. (void)removeMountPoint(mnt.f_mntonname , true); - } - else if (haveUnmountingFsid == 0) - { + } else if (haveUnmountingFsid == 0) { fsid_t toCheckFsid = sb.f_fsid; - if( memcmp(&unmountingFsid, &toCheckFsid, sizeof(fsid_t)) == 0) - { - if(removeMountPoint(mnt.f_mntonname) != 0) - { + if (memcmp(&unmountingFsid, &toCheckFsid, sizeof(fsid_t)) == 0) { + if(removeMountPoint(mnt.f_mntonname) != 0) { cleanupError = true; } } @@ -1039,11 +1076,9 @@ void tryToDestroyUnusedTranslocationMounts() vector mountTable = getMountTableSnapshot(); string baseDirForUser = translocationDirForUser(); - for (auto &mnt : mountTable) - { + for (auto &mnt : mountTable) { if (strcmp(mnt.f_fstypename, NULLFS_FSTYPE) == 0 && - strncmp(mnt.f_mntonname, baseDirForUser.c_str(), baseDirForUser.length()) == 0) - { + strncmp(mnt.f_mntonname, baseDirForUser.c_str(), baseDirForUser.length()) == 0) { ExtendedAutoFileDesc volumeToCheck(mnt.f_mntfromname, O_RDONLY, FileDesc::modeMissingOk); // Try to destroy the mount point. If the mirroed volume (volumeToCheck) isn't open then force it. diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp index a55961c5..f0ccfb68 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp @@ -22,10 +22,10 @@ */ /* Purpose: This header exposes shared functions that actually implement mount creation, policy question - answering and mount deletion. + answering and mount deletion. - Important: None of these functions implement synchronization and they all throw exceptions. It is up - to the caller to handle those concerns. + Important: None of these functions implement synchronization and they all throw exceptions. It is up + to the caller to handle those concerns. */ #include @@ -35,9 +35,9 @@ #define SecTranslocateShared_hpp namespace Security { - + namespace SecTranslocate { - + using namespace std; /* XPC Function keys */ @@ -48,30 +48,64 @@ extern const char* kSecTranslocateXPCFuncCheckIn; extern const char* kSecTranslocateXPCMessageFunction; extern const char* kSecTranslocateXPCMessageOriginalPath; extern const char* kSecTranslocateXPCMessageDestinationPath; +extern const char* kSecTranslocateXPCMessageOptions; extern const char* kSecTranslocateXPCMessagePid; /*XPC message reply keys */ extern const char* kSecTranslocateXPCReplyError; extern const char* kSecTranslocateXPCReplySecurePath; +enum class TranslocationOptions : int64_t { + Default = 0, + Generic = 1 << 0, + Unveil = 1 << 1 +}; + +class GenericTranslocationPath +{ +public: + GenericTranslocationPath(const string& path, TranslocationOptions opts): mOptions(opts), mFd(path) { init(); }; + GenericTranslocationPath(int fd, TranslocationOptions opts): mOptions(opts), mFd(fd) { init(); }; + inline bool shouldTranslocate() const { return mShould; }; + inline const string & getOriginalRealPath() const { return mRealOriginalPath; }; + inline const string & getComponentNameToTranslocate() const { return mComponentNameToTranslocate; }; + inline TranslocationOptions getOptions() const { return mOptions; }; + int getFdForPathToTranslocate() const; +private: + GenericTranslocationPath() = delete; + void init(); + + bool mShould; + string mRealOriginalPath; + string mComponentNameToTranslocate; + TranslocationOptions mOptions; + ExtendedAutoFileDesc mFd; +}; + class TranslocationPath { public: - TranslocationPath(string originalPath); - inline bool shouldTranslocate() const { return should; }; - inline const string & getOriginalRealPath() const { return realOriginalPath; }; - inline const string & getPathToTranslocate() const { return pathToTranslocate; }; - inline const string & getPathInsideTranslocation() const { return pathInsideTranslocationPoint; }; - inline const string & getComponentNameToTranslocate() const { return componentNameToTranslocate; }; + TranslocationPath(string originalPath, TranslocationOptions opts): mOptions(opts), mFd(originalPath) { init(); }; + TranslocationPath(int fd, TranslocationOptions opts): mOptions(opts), mFd(fd) { init(); }; + inline bool shouldTranslocate() const { return mShould; }; + inline const string & getOriginalRealPath() const { return mRealOriginalPath; }; + inline const string & getPathToTranslocate() const { return mPathToTranslocate; }; + inline const string & getPathInsideTranslocation() const { return mPathInsideTranslocationPoint; }; + inline const string & getComponentNameToTranslocate() const { return mComponentNameToTranslocate; }; string getTranslocatedPathToOriginalPath(const string &translocationPoint) const; + inline TranslocationOptions getOptions() const { return mOptions; }; + int getFdForPathToTranslocate() const; private: TranslocationPath() = delete; + void init(); - bool should; - string realOriginalPath; - string pathToTranslocate; - string componentNameToTranslocate; //the final component of pathToTranslocate - string pathInsideTranslocationPoint; + bool mShould; + string mRealOriginalPath; + string mPathToTranslocate; + string mComponentNameToTranslocate; //the final component of pathToTranslocate + string mPathInsideTranslocationPoint; + TranslocationOptions mOptions; + ExtendedAutoFileDesc mFd; ExtendedAutoFileDesc findOuterMostCodeBundleForFD(ExtendedAutoFileDesc &fd); }; @@ -80,7 +114,8 @@ string getOriginalPath(const ExtendedAutoFileDesc& fd, bool* isDir); //throws // For methods below, the caller is responsible for ensuring that only one thread is // accessing/modifying the mount table at a time -string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath); //throws +string translocatePathForUser(const TranslocationPath &originalPath, ExtendedAutoFileDesc &destFd); //throws +string translocatePathForUser(const GenericTranslocationPath &originalPath, ExtendedAutoFileDesc &destFd); //throws bool destroyTranslocatedPathForUser(const string &translocatedPath); //throws bool destroyTranslocatedPathsForUserOnVolume(const string &volumePath = ""); //throws void tryToDestroyUnusedTranslocationMounts(); @@ -88,4 +123,5 @@ void tryToDestroyUnusedTranslocationMounts(); } //namespace SecTranslocate }// namespace Security + #endif /* SecTranslocateShared_hpp */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.cpp index 103dd357..43628e60 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.cpp @@ -28,12 +28,13 @@ #include #include #include +#include #define __APPLE_API_PRIVATE #include #undef __APPLE_API_PRIVATE -#include +#include #include #include @@ -49,103 +50,115 @@ namespace SecTranslocate { using namespace std; +ExtendedAutoFileDesc & ExtendedAutoFileDesc::operator=(ExtendedAutoFileDesc &&rhs) +{ + AutoFileDesc::operator=(std::move(rhs)); + mFsInfo = rhs.mFsInfo; + mRealPath = rhs.mRealPath; + mOriginalPath = rhs.mOriginalPath; + mQuarantineFetched = rhs.mQuarantineFetched; + mQuarantined = rhs.mQuarantined; + mQtn_flags = rhs.mQtn_flags; + return *this; +} + /* store the real path and fstatfs for the file descriptor. This throws if either fail */ void ExtendedAutoFileDesc::init() { - char absPath[MAXPATHLEN]; - if(isOpen()) - { - UnixError::check(fstatfs(fd(), &fsInfo)); - fcntl(F_GETPATH, absPath); - realPath = absPath; - quarantined = false; - qtn_flags = 0; - quarantineFetched = false; //only fetch quarantine info when we need it + if(isOpen()) { + UnixError::check(fstatfs(fd(), &mFsInfo)); + mRealPath = realPath(); + mQuarantined = false; + mQtn_flags = 0; + mQuarantineFetched = false; //only fetch quarantine info when we need it } } +void ExtendedAutoFileDesc::open(const std::string &path, int flag, mode_t mode) +{ + FileDesc::open(path, flag, mode); + if (isOpen()) { + init(); + } +} + bool ExtendedAutoFileDesc::isFileSystemType(const string &fsType) const { notOpen(); //Throws if not Open - return fsType == fsInfo.f_fstypename; + return fsType == mFsInfo.f_fstypename; } bool ExtendedAutoFileDesc::pathIsAbsolute() const { notOpen(); //Throws if not Open - return originalPath == realPath; + return mOriginalPath == mRealPath; } bool ExtendedAutoFileDesc::isMountPoint() const { notOpen(); //Throws if not Open - return realPath == fsInfo.f_mntonname; + return mRealPath == mFsInfo.f_mntonname; } bool ExtendedAutoFileDesc::isInPrefixDir(const string &prefixDir) const { notOpen(); //Throws if not Open - return strncmp(realPath.c_str(), prefixDir.c_str(), prefixDir.length()) == 0; + return strncmp(mRealPath.c_str(), prefixDir.c_str(), prefixDir.length()) == 0; } string ExtendedAutoFileDesc::getFsType() const { notOpen(); //Throws if not Open - return fsInfo.f_fstypename; + return mFsInfo.f_fstypename; } string ExtendedAutoFileDesc::getMountPoint() const { notOpen(); //Throws if not Open - return fsInfo.f_mntonname; + return mFsInfo.f_mntonname; } string ExtendedAutoFileDesc::getMountFromPath() const { notOpen(); //Throws if not Open - return fsInfo.f_mntfromname; + return mFsInfo.f_mntfromname; } const string& ExtendedAutoFileDesc::getRealPath() const { notOpen(); //Throws if not Open - return realPath; + return mRealPath; } fsid_t const ExtendedAutoFileDesc::getFsid() const { notOpen(); //Throws if not Open - return fsInfo.f_fsid; + return mFsInfo.f_fsid; } void ExtendedAutoFileDesc::fetchQuarantine() { - if(!quarantineFetched) - { + if (!mQuarantineFetched) { notOpen(); qtn_file_t qf = qtn_file_alloc(); - if(qf) - { - if(0 == qtn_file_init_with_fd(qf, fd())) - { - quarantined = true; - qtn_flags = qtn_file_get_flags(qf); + if (qf) { + if (0 == qtn_file_init_with_fd(qf, fd())) { + mQuarantined = true; + mQtn_flags = qtn_file_get_flags(qf); } qtn_file_free(qf); - quarantineFetched = true; - } - else - { - Syslog::error("SecTranslocate: failed to allocate memory for quarantine struct"); + mQuarantineFetched = true; + } else { + secerror("SecTranslocate: failed to allocate memory for quarantine struct"); UnixError::throwMe(); } } @@ -156,7 +169,7 @@ bool ExtendedAutoFileDesc::isQuarantined() notOpen(); fetchQuarantine(); - return quarantined; + return mQuarantined; } bool ExtendedAutoFileDesc::isUserApproved() @@ -164,7 +177,7 @@ bool ExtendedAutoFileDesc::isUserApproved() notOpen(); fetchQuarantine(); - return ((qtn_flags & QTN_FLAG_USER_APPROVED) == QTN_FLAG_USER_APPROVED); + return ((mQtn_flags & QTN_FLAG_USER_APPROVED) == QTN_FLAG_USER_APPROVED); } bool ExtendedAutoFileDesc::shouldTranslocate() @@ -172,7 +185,37 @@ bool ExtendedAutoFileDesc::shouldTranslocate() notOpen(); fetchQuarantine(); - return ((qtn_flags & (QTN_FLAG_TRANSLOCATE | QTN_FLAG_DO_NOT_TRANSLOCATE)) == QTN_FLAG_TRANSLOCATE); + return ((mQtn_flags & (QTN_FLAG_TRANSLOCATE | QTN_FLAG_DO_NOT_TRANSLOCATE)) == QTN_FLAG_TRANSLOCATE); +} + +bool ExtendedAutoFileDesc::isSandcastleProtected() +{ + notOpen(); + bool result = false; + char* approval = NULL; + int rv = sandbox_query_approval_policy_for_path("file-read-data", mRealPath.c_str(), &approval); + if (rv < 0) { + secwarning("SecTranslocate: failed to get sandbox policy for: %s", mRealPath.c_str()); + // assuming no policy == not protected + } else if (rv == 0) { + // approved + if (approval != NULL) { + secerror("SecTranslocate: Do not allow translocation, access controled by (%s) for path: %s", approval, mRealPath.c_str()); + result = true; + } + } else { + // denied + result = true; + if (approval != NULL) { + secerror("SecTranslocate: Do not allow translocation, access controled by (%s) for path: %s", approval, mRealPath.c_str()); + } else { + secerror("SecTranslocate: Do not allow translocation, access unconditionally denied for path: %s", mRealPath.c_str()); + } + } + if (approval != NULL) { + free(approval); + } + return result; } /* Take an absolute path and split it into a vector of path components */ @@ -183,20 +226,17 @@ vector splitPath(const string &path) size_t end = 0; size_t len = 0; - if(path.empty() || path.front() != '/') - { - Syslog::error("SecTranslocate::splitPath: asked to split a non-absolute or empty path: %s",path.c_str()); + if (path.empty() || path.front() != '/') { + secerror("SecTranslocate::splitPath: asked to split a non-absolute or empty path: %s",path.c_str()); UnixError::throwMe(EINVAL); } - while(end != string::npos) - { + while (end != string::npos) { end = path.find('/', start); len = (end == string::npos) ? end : (end - start); string temp = path.substr(start,len); - if(!temp.empty()) - { + if (!temp.empty()) { out.push_back(temp); } start = end + 1; @@ -209,8 +249,7 @@ vector splitPath(const string &path) string joinPath(vector& path) { string out = ""; - for(auto &i : path) - { + for (auto &i : path) { out += "/"+i; } return out; @@ -218,9 +257,8 @@ string joinPath(vector& path) string joinPathUpTo(vector &path, size_t index) { - if (path.size() == 0 || index > path.size()-1) - { - Syslog::error("SecTranslocate::joinPathUpTo invalid index %lu (size %lu)",index, path.size()-1); + if (path.size() == 0 || index > path.size() - 1) { + secerror("SecTranslocate::joinPathUpTo invalid index %lu (size %lu)",index, path.size()-1); UnixError::throwMe(EINVAL); } @@ -246,14 +284,12 @@ string getRealPath(const string &path) string makeUUID() { CFRef newUUID = CFUUIDCreate(NULL); - if (!newUUID) - { + if (!newUUID) { UnixError::throwMe(ENOMEM); } CFRef str = CFUUIDCreateString(NULL, newUUID.get()); - if (!str) - { + if (!str) { UnixError::throwMe(ENOMEM); } @@ -264,9 +300,8 @@ void* checkedDlopen(const char* path, int mode) { void* handle = dlopen(path, mode); - if(handle == NULL) - { - Syslog::critical("SecTranslocate: failed to load library %s: %s", path, dlerror()); + if (handle == NULL) { + seccritical("SecTranslocate: failed to load library %s: %s", path, dlerror()); UnixError::throwMe(); } @@ -277,9 +312,8 @@ void* checkedDlsym(void* handle, const char* symbol) { void* result = dlsym(handle, symbol); - if(result == NULL) - { - Syslog::critical("SecTranslocate: failed to load symbol %s: %s", symbol, dlerror()); + if (result == NULL) { + seccritical("SecTranslocate: failed to load symbol %s: %s", symbol, dlerror()); UnixError::throwMe(); } return result; @@ -290,11 +324,11 @@ string translocationDirForUser() { char userTempPath[MAXPATHLEN]; - if(confstr(_CS_DARWIN_USER_TEMP_DIR, userTempPath, sizeof(userTempPath)) == 0) + if (confstr(_CS_DARWIN_USER_TEMP_DIR, userTempPath, sizeof(userTempPath)) == 0) { - Syslog::error("SecTranslocate: Failed to get temp dir for user %d (error:%d)", - getuid(), - errno); + secerror("SecTranslocate: Failed to get temp dir for user %d (error:%d)", + getuid(), + errno); UnixError::throwMe(); } @@ -305,26 +339,23 @@ string translocationDirForUser() /* Get a file descriptor for the provided path. if the last component of the provided path doesn't exist, create it and then re-attempt to get the file descriptor. */ -int getFDForDirectory(const string &directoryPath, bool *owned) +ExtendedAutoFileDesc getFDForDirectory(const string &directoryPath, bool *owned) { - FileDesc fd(directoryPath, O_RDONLY, FileDesc::modeMissingOk); - if(!fd) - { + ExtendedAutoFileDesc fd(directoryPath, O_RDONLY, FileDesc::modeMissingOk); + if (!fd) { UnixError::check(mkdir(directoryPath.c_str(),0755)); fd.open(directoryPath); /* owned means that the library created the directory rather than it being pre-existent. We just made a directory that didn't exist before, so set owned to true. */ - if(owned) - { + if(owned) { *owned = true; } - } - else if (owned) - { + } else if (owned) { *owned = false; } return fd; } -} -} + +} // namespace SecTranslocate +} // namespace Security diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp index e2503e2d..98e6c21d 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp @@ -40,21 +40,27 @@ #define NULLFS_FSTYPE "nullfs" namespace Security { - + using namespace Security::UnixPlusPlus; namespace SecTranslocate { using namespace std; - + class ExtendedAutoFileDesc : public AutoFileDesc { public: - ExtendedAutoFileDesc() = delete; //Always want these initialized with a path - + ExtendedAutoFileDesc():AutoFileDesc() {}; ExtendedAutoFileDesc(const char *path, int flag = O_RDONLY, mode_t mode = 0666) - : AutoFileDesc(path, flag, mode), originalPath(path) { init(); } + : AutoFileDesc(path, flag, mode), mOriginalPath(path) { init(); } ExtendedAutoFileDesc(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666) - : AutoFileDesc(path, flag, mode),originalPath(path) { init(); } + : AutoFileDesc(path, flag, mode), mOriginalPath(path) { init(); } + ExtendedAutoFileDesc(int fd):AutoFileDesc(fd) { init(); } + ExtendedAutoFileDesc(const ExtendedAutoFileDesc&) = default; + ExtendedAutoFileDesc(ExtendedAutoFileDesc&&) = default; + + ExtendedAutoFileDesc & operator=(ExtendedAutoFileDesc&&); + + void open(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666); bool isFileSystemType(const string &fsType) const; bool pathIsAbsolute() const; @@ -68,18 +74,19 @@ public: bool isQuarantined(); bool isUserApproved(); bool shouldTranslocate(); + bool isSandcastleProtected(); // implicit destructor should call AutoFileDesc destructor. Nothing else to clean up. private: void init(); inline void notOpen() const { if(!isOpen()) UnixError::throwMe(EINVAL); }; - struct statfs fsInfo; - string realPath; - string originalPath; - bool quarantineFetched; - bool quarantined; - uint32_t qtn_flags; + struct statfs mFsInfo; + string mRealPath; + string mOriginalPath; + bool mQuarantineFetched; + bool mQuarantined; + uint32_t mQtn_flags; void fetchQuarantine(); }; @@ -91,11 +98,11 @@ void* checkedDlsym(void* handle, const char* symbol); //Path parsing functions vector splitPath(const string &path); string joinPath(vector& path); - string joinPathUpTo(vector &path, size_t index); +string joinPathUpTo(vector &path, size_t index); //File system utlities string getRealPath(const string &path); -int getFDForDirectory(const string &directoryPath, bool *owned = NULL); //creates the directory if it can +ExtendedAutoFileDesc getFDForDirectory(const string &directoryPath, bool *owned = NULL); //creates the directory if it can //Translocation specific utilities diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp index 769f72ac..261a93b5 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp @@ -26,77 +26,104 @@ #include #include +#include +#include #include -#include +#include #include "SecTranslocateInterface.hpp" #include "SecTranslocateXPCServer.hpp" #include "SecTranslocateUtilities.hpp" #include "SecTranslocateShared.hpp" +#include "SecTranslocateEnumUtils.hpp" namespace Security { namespace SecTranslocate { -static void doCreate(xpc_object_t msg, xpc_object_t reply) +static void doCreate(xpc_object_t msg, xpc_object_t reply, audit_token_t audit_token) { - const char* original = xpc_dictionary_get_string(msg, kSecTranslocateXPCMessageOriginalPath); - const char* dest = xpc_dictionary_get_string(msg, kSecTranslocateXPCMessageDestinationPath); + const int original = xpc_dictionary_dup_fd(msg, kSecTranslocateXPCMessageOriginalPath); + const int dest = xpc_dictionary_dup_fd(msg, kSecTranslocateXPCMessageDestinationPath); + const int64_t opts = xpc_dictionary_get_int64(msg, kSecTranslocateXPCMessageOptions); - string originalPath = original ? original : ""; - string destPath = dest ? dest: ""; + TranslocationOptions options = static_cast(opts); - if( originalPath.empty()) - { - Syslog::error("SecTranslocate: XPCServer, doCreate no path to translocate"); + if (original == -1) { + secerror("SecTranslocate: XPCServer, doCreate no path to translocate"); UnixError::throwMe(EINVAL); } - - TranslocationPath tPath(originalPath); - - string result = tPath.getOriginalRealPath(); - - if(tPath.shouldTranslocate()) - { - result = Security::SecTranslocate::translocatePathForUser(tPath, destPath); + ExtendedAutoFileDesc destFd(dest); + int rc = sandbox_check_by_audit_token(audit_token, "file-read*", SANDBOX_FILTER_DESCRIPTOR, original); + if (rc == 1) { + secerror("SecTranslocate: XPCServer, doCreate path to translocate disallowed by sandbox"); + UnixError::throwMe(EPERM); + } else if (rc == -1) { + int error = errno; + secerror("SecTranslocate: XPCServer, doCreate error checking path to translocate against sandbox"); + UnixError::throwMe(error); } + if (destFd.isOpen()) { + rc = sandbox_check_by_audit_token(audit_token, "file-mount", SANDBOX_FILTER_DESCRIPTOR, destFd.fd()); + if (rc == 1) { + secerror("SecTranslocate: XPCServer, doCreate destination path disallowed by sandbox"); + UnixError::throwMe(EPERM); + } else if (rc == -1) { + int error = errno; + secerror("SecTranslocate: XPCServer, doCreate error checking destination path against sandbox"); + UnixError::throwMe(error); + } + } + + string result; + + if ((options & TranslocationOptions::Generic) == TranslocationOptions::Generic) { + GenericTranslocationPath tPath(original, TranslocationOptions::Unveil); + result = tPath.getOriginalRealPath(); + + if (tPath.shouldTranslocate()) { + result = Security::SecTranslocate::translocatePathForUser(tPath, destFd); + } + } else { + TranslocationPath tPath(original, TranslocationOptions::Default); + result = tPath.getOriginalRealPath(); + + if (tPath.shouldTranslocate()) { + result = Security::SecTranslocate::translocatePathForUser(tPath, destFd); + } + } + xpc_dictionary_set_string(reply, kSecTranslocateXPCReplySecurePath, result.c_str()); } static void doCheckIn(xpc_object_t msg) { - if (xpc_dictionary_get_value(msg, kSecTranslocateXPCMessagePid) == NULL) - { - Syslog::error("SecTranslocate, XpcServer, doCheckin, no pid provided"); + if (xpc_dictionary_get_value(msg, kSecTranslocateXPCMessagePid) == NULL) { + secerror("SecTranslocate, XpcServer, doCheckin, no pid provided"); UnixError::throwMe(EINVAL); } int64_t pid = xpc_dictionary_get_int64(msg, kSecTranslocateXPCMessagePid); Translocator * t = getTranslocator(); - if(t) - { + if (t) { t->appLaunchCheckin((pid_t)pid); - } - else - { - Syslog::critical("SecTranslocate, XpcServer, doCheckin, No top level translocator"); + } else { + seccritical("SecTranslocate, XpcServer, doCheckin, No top level translocator"); UnixError::throwMe(EINVAL); } } XPCServer::XPCServer(dispatch_queue_t q):notificationQ(q) { - if(q == NULL) - { - Syslog::critical("SecTranslocate: XPCServer, no dispatch queue provided"); + if (q == NULL) { + seccritical("SecTranslocate: XPCServer, no dispatch queue provided"); UnixError::throwMe(EINVAL); } //notificationQ is assumed to be serial service = xpc_connection_create_mach_service(SECTRANSLOCATE_XPC_SERVICE_NAME, notificationQ, XPC_CONNECTION_MACH_SERVICE_LISTENER); - if (service == NULL) - { - Syslog::critical("SecTranslocate: XPCServer, failed to create xpc mach service"); + if (service == NULL) { + seccritical("SecTranslocate: XPCServer, failed to create xpc mach service"); UnixError::throwMe(ENOMEM); } @@ -104,19 +131,21 @@ XPCServer::XPCServer(dispatch_queue_t q):notificationQ(q) xpc_connection_set_event_handler(service, ^(xpc_object_t cmsg) { if (xpc_get_type(cmsg) == XPC_TYPE_CONNECTION) { xpc_connection_t connection = xpc_connection_t(cmsg); - Syslog::debug("SecTranslocate: XPCServer, Connection from pid %d", xpc_connection_get_pid(connection)); + secdebug("sectranslocate","SecTranslocate: XPCServer, Connection from pid %d", xpc_connection_get_pid(connection)); xpc_connection_set_event_handler(connection, ^(xpc_object_t msg) { if (xpc_get_type(msg) == XPC_TYPE_DICTIONARY) { xpc_retain(msg); dispatch_async(notificationQ, ^{ // async from here const char *function = xpc_dictionary_get_string(msg, kSecTranslocateXPCMessageFunction); - Syslog::debug("SecTranslocate: XPCServer, pid %d requested %s", xpc_connection_get_pid(connection), function); + audit_token_t audit_token; + xpc_connection_get_audit_token(connection, &audit_token); + secdebug("sectranslocate","SecTranslocate: XPCServer, pid %d requested %s", xpc_connection_get_pid(connection), function); xpc_object_t reply = xpc_dictionary_create_reply(msg); try { if (function == NULL) { xpc_dictionary_set_int64(reply, kSecTranslocateXPCReplyError, EINVAL); } else if (!strcmp(function, kSecTranslocateXPCFuncCreate)) { - doCreate(msg, reply); + doCreate(msg, reply, audit_token); } else if (!strcmp(function, kSecTranslocateXPCFuncCheckIn)) { doCheckIn(msg); } else { @@ -138,7 +167,7 @@ XPCServer::XPCServer(dispatch_queue_t q):notificationQ(q) xpc_connection_resume(connection); } else { const char *s = xpc_copy_description(cmsg); - Syslog::error("SecTranslocate: XPCServer, unepxected incoming message - %s", s); + secerror("SecTranslocate: XPCServer, unexpected incoming message - %s", s); free((char*)s); } }); diff --git a/OSX/libsecurity_utilities/lib/alloc.cpp b/OSX/libsecurity_utilities/lib/alloc.cpp index 5d297087..fed1a610 100644 --- a/OSX/libsecurity_utilities/lib/alloc.cpp +++ b/OSX/libsecurity_utilities/lib/alloc.cpp @@ -46,7 +46,7 @@ extern "C" size_t malloc_size(void *); // // Features of the Allocator root class // -bool Allocator::operator == (const Allocator &alloc) const throw() +bool Allocator::operator == (const Allocator &alloc) const _NOEXCEPT { return this == &alloc; } @@ -63,14 +63,14 @@ Allocator::~Allocator() // pool). This is trivially achieved here by using singletons. // struct DefaultAllocator : public Allocator { - void *malloc(size_t size) throw(std::bad_alloc); - void free(void *addr) throw(); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); + void *malloc(size_t size); + void free(void *addr) _NOEXCEPT; + void *realloc(void *addr, size_t size); }; struct SensitiveAllocator : public DefaultAllocator { - void free(void *addr) throw(); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); + void free(void *addr) _NOEXCEPT; + void *realloc(void *addr, size_t size); }; struct DefaultAllocators { @@ -93,33 +93,33 @@ Allocator &Allocator::standard(UInt32 request) } } -void *DefaultAllocator::malloc(size_t size) throw(std::bad_alloc) +void *DefaultAllocator::malloc(size_t size) { if (void *result = ::malloc(size)) return result; throw std::bad_alloc(); } -void DefaultAllocator::free(void *addr) throw() +void DefaultAllocator::free(void *addr) _NOEXCEPT { ::free(addr); } -void *DefaultAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) +void *DefaultAllocator::realloc(void *addr, size_t newSize) { if (void *result = ::realloc(addr, newSize)) return result; throw std::bad_alloc(); } -void SensitiveAllocator::free(void *addr) throw() +void SensitiveAllocator::free(void *addr) _NOEXCEPT { size_t size = malloc_size(addr); ::memset_s(addr, size, 0, size); DefaultAllocator::free(addr); } -void *SensitiveAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) +void *SensitiveAllocator::realloc(void *addr, size_t newSize) { size_t oldSize = malloc_size(addr); if (newSize < oldSize) @@ -135,7 +135,7 @@ void *SensitiveAllocator::realloc(void *addr, size_t newSize) throw(std::bad_all // functions to safely free our (hidden) pointer without knowing about it. // An allocator argument of NULL is interpreted as the standard allocator. // -void *CssmHeap::operator new (size_t size, Allocator *alloc) throw(std::bad_alloc) +void *CssmHeap::operator new (size_t size, Allocator *alloc) { if (size > SIZE_T_MAX / 2) { throw std::bad_alloc(); @@ -150,12 +150,12 @@ void *CssmHeap::operator new (size_t size, Allocator *alloc) throw(std::bad_allo return addr; } -void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) throw() +void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) _NOEXCEPT { alloc->free(addr); // as per C++ std, called (only) if construction fails } -void CssmHeap::operator delete (void *addr, size_t size) throw() +void CssmHeap::operator delete (void *addr, size_t size) _NOEXCEPT { void *end = increment(addr, alignUp(size, alignof_template())); (*(Allocator **)end)->free(addr); diff --git a/OSX/libsecurity_utilities/lib/alloc.h b/OSX/libsecurity_utilities/lib/alloc.h index 8d276227..b77f9451 100644 --- a/OSX/libsecurity_utilities/lib/alloc.h +++ b/OSX/libsecurity_utilities/lib/alloc.h @@ -43,18 +43,18 @@ namespace Security class Allocator { public: virtual ~Allocator(); - virtual void *malloc(size_t) throw(std::bad_alloc) = 0; - virtual void free(void *) throw() = 0; - virtual void *realloc(void *, size_t) throw(std::bad_alloc) = 0; + virtual void *malloc(size_t)= 0; + virtual void free(void *) _NOEXCEPT = 0; + virtual void *realloc(void *, size_t)= 0; // // Template versions for added expressiveness. // Note that the integers are element counts, not byte sizes. // - template T *alloc() throw(std::bad_alloc) + template T *alloc() { return reinterpret_cast(malloc(sizeof(T))); } - template T *alloc(UInt32 count) throw(std::bad_alloc) + template T *alloc(UInt32 count) { size_t bytes = 0; if (__builtin_mul_overflow(sizeof(T), count, &bytes)) { @@ -64,7 +64,7 @@ public: } - template T *alloc(T *old, UInt32 count) throw(std::bad_alloc) + template T *alloc(T *old, UInt32 count) { size_t bytes = 0; if (__builtin_mul_overflow(sizeof(T), count, &bytes)) { @@ -78,14 +78,14 @@ public: // Happier malloc/realloc for any type. Note that these still have // the original (byte-sized) argument profile. // - template T *malloc(size_t size) throw(std::bad_alloc) + template T *malloc(size_t size) { return reinterpret_cast(malloc(size)); } - template T *realloc(void *addr, size_t size) throw(std::bad_alloc) + template T *realloc(void *addr, size_t size) { return reinterpret_cast(realloc(addr, size)); } // All right, if you *really* have to have calloc... - void *calloc(size_t size, size_t count) throw(std::bad_alloc) + void *calloc(size_t size, size_t count) { size_t bytes = 0; if(__builtin_mul_overflow(size, count, &bytes)) { @@ -98,7 +98,7 @@ public: } // compare Allocators for identity - virtual bool operator == (const Allocator &alloc) const throw(); + virtual bool operator == (const Allocator &alloc) const _NOEXCEPT; public: // allocator chooser options @@ -117,14 +117,14 @@ public: // Use this to cleanly destroy things. // template -inline void destroy(T *obj, Allocator &alloc) throw() +inline void destroy(T *obj, Allocator &alloc) _NOEXCEPT { obj->~T(); alloc.free(obj); } // untyped (release memory only, no destructor call) -inline void destroy(void *obj, Allocator &alloc) throw() +inline void destroy(void *obj, Allocator &alloc) _NOEXCEPT { alloc.free(obj); } @@ -145,17 +145,17 @@ inline void destroy(void *obj, Allocator &alloc) throw() // class CssmHeap { public: - void *operator new (size_t size, Allocator *alloc = NULL) throw(std::bad_alloc); - void operator delete (void *addr, size_t size) throw(); - void operator delete (void *addr, size_t size, Allocator *alloc) throw(); + void *operator new (size_t size, Allocator *alloc = NULL); + void operator delete (void *addr, size_t size) _NOEXCEPT; + void operator delete (void *addr, size_t size, Allocator *alloc) _NOEXCEPT; }; // -// Here is a version of auto_ptr that works with Allocators. It is designed +// Here is a version of unique_ptr that works with Allocators. It is designed // to be pretty much a drop-in replacement. It requires an allocator as a constructor // argument, of course. -// Note that CssmAutoPtr is perfectly valid, unlike its auto_ptr look-alike. +// Note that CssmAutoPtr is perfectly valid, unlike its unique_ptr look-alike. // You can't dereference it, naturally. // template @@ -176,7 +176,7 @@ public: ~CssmAutoPtr() { allocator.free(mine); } - T *get() const throw() { return mine; } + T *get() const _NOEXCEPT { return mine; } T *release() { T *result = mine; mine = NULL; return result; } void reset() { allocator.free(mine); mine = NULL; } @@ -203,7 +203,7 @@ public: ~CssmAutoPtr() { destroy(mine, allocator); } - void *get() throw() { return mine; } + void *get() _NOEXCEPT { return mine; } void *release() { void *result = mine; mine = NULL; return result; } void reset() { allocator.free(mine); mine = NULL; } @@ -248,10 +248,10 @@ public: // // Global C++ allocation hooks to use Allocators (global namespace) // -inline void *operator new (size_t size, Allocator &allocator) throw (std::bad_alloc) +inline void *operator new (size_t size, Allocator &allocator) { return allocator.malloc(size); } -inline void *operator new[] (size_t size, Allocator &allocator) throw (std::bad_alloc) +inline void *operator new[] (size_t size, Allocator &allocator) { return allocator.malloc(size); } diff --git a/OSX/libsecurity_utilities/lib/cfclass.cpp b/OSX/libsecurity_utilities/lib/cfclass.cpp index 530edb4b..6beabd29 100644 --- a/OSX/libsecurity_utilities/lib/cfclass.cpp +++ b/OSX/libsecurity_utilities/lib/cfclass.cpp @@ -89,7 +89,7 @@ CFClass::cleanupObject(intptr_t op, CFTypeRef cf, bool &zap) } uint32_t -CFClass::refCountForType(intptr_t op, CFTypeRef cf) throw() +CFClass::refCountForType(intptr_t op, CFTypeRef cf) _NOEXCEPT { uint32_t result = 0; bool zap = false; @@ -127,7 +127,7 @@ CFClass::refCountForType(intptr_t op, CFTypeRef cf) throw() void -CFClass::finalizeType(CFTypeRef cf) throw() +CFClass::finalizeType(CFTypeRef cf) _NOEXCEPT { /* We need to control the lifetime of the object. This means @@ -168,7 +168,7 @@ CFClass::finalizeType(CFTypeRef cf) throw() } Boolean -CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2) throw() +CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2) _NOEXCEPT { // CF checks for pointer equality and ensures type equality already try { @@ -179,7 +179,7 @@ CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2) throw() } CFHashCode -CFClass::hashType(CFTypeRef cf) throw() +CFClass::hashType(CFTypeRef cf) _NOEXCEPT { try { return SecCFObject::optional(cf)->hash(); @@ -189,7 +189,7 @@ CFClass::hashType(CFTypeRef cf) throw() } CFStringRef -CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw() +CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) _NOEXCEPT { try { return SecCFObject::optional(cf)->copyFormattingDesc(dict); @@ -199,7 +199,7 @@ CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw() } CFStringRef -CFClass::copyDebugDescType(CFTypeRef cf) throw() +CFClass::copyDebugDescType(CFTypeRef cf) _NOEXCEPT { try { return SecCFObject::optional(cf)->copyDebugDesc(); diff --git a/OSX/libsecurity_utilities/lib/cfclass.h b/OSX/libsecurity_utilities/lib/cfclass.h index 6203f112..1adbbe18 100644 --- a/OSX/libsecurity_utilities/lib/cfclass.h +++ b/OSX/libsecurity_utilities/lib/cfclass.h @@ -41,12 +41,12 @@ public: CFTypeID typeID; private: - static void finalizeType(CFTypeRef cf) throw(); - static Boolean equalType(CFTypeRef cf1, CFTypeRef cf2) throw(); - static CFHashCode hashType(CFTypeRef cf) throw(); - static CFStringRef copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw(); - static CFStringRef copyDebugDescType(CFTypeRef cf) throw(); - static uint32_t refCountForType(intptr_t op, CFTypeRef cf) throw(); + static void finalizeType(CFTypeRef cf) _NOEXCEPT; + static Boolean equalType(CFTypeRef cf1, CFTypeRef cf2) _NOEXCEPT; + static CFHashCode hashType(CFTypeRef cf) _NOEXCEPT; + static CFStringRef copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) _NOEXCEPT; + static CFStringRef copyDebugDescType(CFTypeRef cf) _NOEXCEPT; + static uint32_t refCountForType(intptr_t op, CFTypeRef cf) _NOEXCEPT; static uint32_t cleanupObject(intptr_t op, CFTypeRef cf, bool &zap); }; diff --git a/OSX/libsecurity_utilities/lib/cfmunge.cpp b/OSX/libsecurity_utilities/lib/cfmunge.cpp index f26ccc72..2854e600 100644 --- a/OSX/libsecurity_utilities/lib/cfmunge.cpp +++ b/OSX/libsecurity_utilities/lib/cfmunge.cpp @@ -221,17 +221,21 @@ CFTypeRef CF_RETURNS_RETAINED CFMake::makedictionary() return dict; } else return NULL; // bad syntax - } else + } else { dict = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (dict == NULL) + } + + if (dict == NULL) { return dict; - if (add(dict)) - return dict; - else { - CFReleaseSafe(dict); - return NULL; - } + } + + if (add(dict)) { + return dict; + } else { + CFReleaseSafe(dict); + return NULL; + } } CFDictionaryRef CFMake::add(CFMutableDictionaryRef dict) diff --git a/OSX/libsecurity_utilities/lib/daemon.cpp b/OSX/libsecurity_utilities/lib/daemon.cpp index f06ced98..780174a7 100644 --- a/OSX/libsecurity_utilities/lib/daemon.cpp +++ b/OSX/libsecurity_utilities/lib/daemon.cpp @@ -36,7 +36,6 @@ namespace Security { namespace Daemon { - // // Daemonize this process, the UNIX way. // @@ -82,31 +81,5 @@ bool incarnate(bool doFork /*=true*/) return true; } - -// -// Re-execute myself. -// This is a pretty bad hack for libraries that are pretty broken and (essentially) -// don't work after a fork() unless you also exec(). -// -// WARNING: Don't even THINK of doing this in a setuid-anything program. -// -bool executeSelf(char **argv) -{ - static const char reExecEnv[] = "_RE_EXECUTE"; - if (getenv(reExecEnv)) { // was re-executed - secinfo("daemon", "self-execution complete"); - unsetenv(reExecEnv); - return true; - } else { - setenv(reExecEnv, "go", 1); - secinfo("daemon", "self-executing (ouch!)"); - execv(argv[0], argv); - perror("re-execution"); - Syslog::error("Re-execution attempt failed"); - return false; - } -} - - } // end namespace Daemon } // end namespace Security diff --git a/OSX/libsecurity_utilities/lib/daemon.h b/OSX/libsecurity_utilities/lib/daemon.h index 6e51747d..e65800b5 100644 --- a/OSX/libsecurity_utilities/lib/daemon.h +++ b/OSX/libsecurity_utilities/lib/daemon.h @@ -35,7 +35,6 @@ namespace Security { namespace Daemon { bool incarnate(bool doFork=true); -bool executeSelf(char **argv); } // end namespace Daemon } // end namespace Security diff --git a/OSX/libsecurity_utilities/lib/debugging.h b/OSX/libsecurity_utilities/lib/debugging.h deleted file mode 120000 index 04530179..00000000 --- a/OSX/libsecurity_utilities/lib/debugging.h +++ /dev/null @@ -1 +0,0 @@ -../../utilities/debugging.h \ No newline at end of file diff --git a/OSX/libsecurity_utilities/lib/debugging_internal.cpp b/OSX/libsecurity_utilities/lib/debugging_internal.cpp index 55c74a7c..c95c802e 100644 --- a/OSX/libsecurity_utilities/lib/debugging_internal.cpp +++ b/OSX/libsecurity_utilities/lib/debugging_internal.cpp @@ -218,9 +218,11 @@ void Target::message(const char *scope, const char *format, va_list args) // now stuff the message body in, slightly roasted size_t left = buffer + sizeof(buffer) - bufp - 1; // reserve one size_t written = vsnprintf(bufp, left, format, args); - for (char *p = bufp; *p; p++) - if (!isprint(*p)) + for (char *p = bufp; *p; p++) { + if (!isprint(*p)) { *p = '?'; + } + } if (written >= left) { // snprintf overflowed bufp += left; strcpy(bufp - 3, "..."); diff --git a/OSX/libsecurity_utilities/lib/dispatch.h b/OSX/libsecurity_utilities/lib/dispatch.h index 39d680a1..c8d2d9ff 100644 --- a/OSX/libsecurity_utilities/lib/dispatch.h +++ b/OSX/libsecurity_utilities/lib/dispatch.h @@ -106,11 +106,7 @@ private: class SemaphoreWait { -// this has to be disabled because Clang 13 incorrectly detects a block variable non-const copy as a const copy in `libsecurity_codesigning/lib/csutilities.cpp`. -// it still compiles correctly, it just generates an incorrect error if this is left in. -#ifndef DARLING NOCOPY(SemaphoreWait) -#endif public: SemaphoreWait(SemaphoreWait& originalWait); SemaphoreWait(Semaphore& semaphore, dispatch_time_t timeout = DISPATCH_TIME_FOREVER); diff --git a/OSX/libsecurity_utilities/lib/errors.cpp b/OSX/libsecurity_utilities/lib/errors.cpp index e715b11d..5072da2f 100644 --- a/OSX/libsecurity_utilities/lib/errors.cpp +++ b/OSX/libsecurity_utilities/lib/errors.cpp @@ -60,7 +60,7 @@ CommonError::CommonError(const CommonError &source) strlcpy(whatBuffer, source.whatBuffer, whatBufferSize); } -CommonError::~CommonError() throw () +CommonError::~CommonError() _NOEXCEPT { } @@ -135,7 +135,7 @@ UnixError::UnixError(int err, bool suppresslogging) : error(err) } } -const char *UnixError::what() const throw () +const char *UnixError::what() const _NOEXCEPT { return whatBuffer; } @@ -175,7 +175,7 @@ MacOSError::MacOSError(int err) : error(err) } } -const char *MacOSError::what() const throw () +const char *MacOSError::what() const _NOEXCEPT { return whatBuffer; } @@ -219,7 +219,7 @@ CFError::CFError() LogBacktrace(); } -const char *CFError::what() const throw () +const char *CFError::what() const _NOEXCEPT { return "CoreFoundation error"; } OSStatus CFError::osStatus() const diff --git a/OSX/libsecurity_utilities/lib/errors.h b/OSX/libsecurity_utilities/lib/errors.h index 4baae8f3..b0cf718d 100644 --- a/OSX/libsecurity_utilities/lib/errors.h +++ b/OSX/libsecurity_utilities/lib/errors.h @@ -50,7 +50,7 @@ protected: CommonError(); CommonError(const CommonError &source); public: - virtual ~CommonError() throw (); + virtual ~CommonError() _NOEXCEPT; virtual OSStatus osStatus() const = 0; virtual int unixError() const = 0; @@ -74,7 +74,7 @@ public: const int error; virtual OSStatus osStatus() const; virtual int unixError() const; - virtual const char *what () const throw (); + virtual const char *what () const _NOEXCEPT; static void check(int result) { if (result == -1) throwMe(); } static void throwMe(int err = errno) __attribute__((noreturn)); @@ -96,7 +96,7 @@ public: const int error; virtual OSStatus osStatus() const; virtual int unixError() const; - virtual const char *what () const throw (); + virtual const char *what () const _NOEXCEPT; static void check(OSStatus status) { if (status != errSecSuccess) throwMe(status); } static void throwMe(int err) __attribute__((noreturn)); @@ -120,7 +120,7 @@ protected: public: virtual OSStatus osStatus() const; virtual int unixError() const; - virtual const char *what () const throw (); + virtual const char *what () const _NOEXCEPT; template static void check(const T &p) { if (!p) throwMe(); } diff --git a/OSX/libsecurity_utilities/lib/globalizer.cpp b/OSX/libsecurity_utilities/lib/globalizer.cpp index df5af3bc..7d8306a1 100644 --- a/OSX/libsecurity_utilities/lib/globalizer.cpp +++ b/OSX/libsecurity_utilities/lib/globalizer.cpp @@ -42,7 +42,7 @@ // // The Error class thrown if Nexus operations fail // -GlobalNexus::Error::~Error() throw() +GlobalNexus::Error::~Error() _NOEXCEPT { } @@ -80,7 +80,7 @@ ProcessNexusBase::ProcessNexusBase(const char *identifier) { const char *env = getenv(identifier); if (env == NULL) { // perhaps we're first... - auto_ptr store(new Store); + unique_ptr store(new Store); char form[2*sizeof(Store *) + 2]; sprintf(form, "*%p", &store); setenv(identifier, form, 0); // do NOT overwrite... diff --git a/OSX/libsecurity_utilities/lib/globalizer.h b/OSX/libsecurity_utilities/lib/globalizer.h index 5610cc8a..db0e20ff 100644 --- a/OSX/libsecurity_utilities/lib/globalizer.h +++ b/OSX/libsecurity_utilities/lib/globalizer.h @@ -47,10 +47,10 @@ class GlobalNexus { public: class Error : public std::exception { public: - virtual ~Error() throw(); + virtual ~Error() _NOEXCEPT; const char * const message; Error(const char *m) : message(m) { } - const char *what() const throw() { return message; } + const char *what() const _NOEXCEPT { return message; } }; }; diff --git a/OSX/libsecurity_utilities/lib/mach++.cpp b/OSX/libsecurity_utilities/lib/mach++.cpp index ab6bb982..9708a823 100644 --- a/OSX/libsecurity_utilities/lib/mach++.cpp +++ b/OSX/libsecurity_utilities/lib/mach++.cpp @@ -47,7 +47,7 @@ Error::Error(kern_return_t err) : error(err) secnotice("security_exception", "mach error: %d", err); } -Error::~Error() throw() +Error::~Error() _NOEXCEPT { } @@ -142,9 +142,10 @@ mach_port_t Port::cancelNotify(mach_msg_id_t type) { // Mach won't let us unset the DPN port if we are already dead // (EVEN if the DPN has already been sent!) So just ignore that case... - if (isDead()) + if (isDead()) { return MACH_PORT_NULL; - return requestNotify(MACH_PORT_NULL, type); + } + return requestNotify(MACH_PORT_NULL, type); } mach_port_msgcount_t Port::qlimit() const diff --git a/OSX/libsecurity_utilities/lib/mach++.h b/OSX/libsecurity_utilities/lib/mach++.h index dba14c37..ba7f02b1 100644 --- a/OSX/libsecurity_utilities/lib/mach++.h +++ b/OSX/libsecurity_utilities/lib/mach++.h @@ -53,7 +53,7 @@ protected: // actually, kern_return_t can be just about any subsystem type return code Error(kern_return_t err); public: - virtual ~Error() throw(); + virtual ~Error() _NOEXCEPT; virtual OSStatus osStatus() const; virtual int unixError() const; @@ -107,8 +107,13 @@ public: // port allocation and management void allocate(mach_port_right_t right = MACH_PORT_RIGHT_RECEIVE) { check(mach_port_allocate(self(), right, &mPort)); } - void deallocate() { check(mach_port_deallocate(self(), mPort)); mPort = MACH_PORT_NULL;} - void destroy() { check(mach_port_destroy(self(), mPort)); mPort = MACH_PORT_NULL; } + /* + * (╯ರ ~ ರ)╯︵ ┻━┻ + * mach_port_deallocate() only deallocates send, send-once, dead-name, or port-set. + * Since allocate() defaults to receive, allocate() and deallocate() do not actually + * balance each other; deallocate() will fail with an invalid-right error. + */ + void deallocate() { check(mach_port_deallocate(self(), mPort)); mPort = MACH_PORT_NULL;} void insertRight(mach_msg_type_name_t type) { check(mach_port_insert_right(self(), mPort, mPort, type)); } @@ -134,25 +139,13 @@ protected: }; -// -// A simple Port that deallocates itself on destruction. -// If you need a subclass of Port, just assign it to a separate AutoPort. -// -class AutoPort : public Port { -public: - AutoPort() { } - AutoPort(mach_port_t port) : Port(port) { } - ~AutoPort() { if (mPort != MACH_PORT_NULL) deallocate(); } -}; - - // // Ports representing PortSets // class PortSet : public Port { public: PortSet() { allocate(MACH_PORT_RIGHT_PORT_SET); } - ~PortSet() { destroy(); } + ~PortSet() { deallocate(); } void operator += (const Port &port) { check(mach_port_move_member(self(), port, mPort)); } @@ -222,7 +215,7 @@ class ReceivePort : public Port { public: ReceivePort() { allocate(); } ReceivePort(const char *name, const Bootstrap &bootstrap, bool tryCheckin = true); - ~ReceivePort() { destroy(); } + ~ReceivePort() { modRefs(MACH_PORT_RIGHT_RECEIVE, -1); } }; diff --git a/OSX/libsecurity_utilities/lib/macho++.cpp b/OSX/libsecurity_utilities/lib/macho++.cpp index 32836ab0..f7f8c81d 100644 --- a/OSX/libsecurity_utilities/lib/macho++.cpp +++ b/OSX/libsecurity_utilities/lib/macho++.cpp @@ -768,11 +768,12 @@ const fat_arch *Universal::findArch(const Architecture &target) const // exact match for (const fat_arch *arch = mArchList; arch < end; ++arch) if (arch->cputype == target.cpuType() - && arch->cpusubtype == target.cpuSubtype()) + && (arch->cpusubtype & ~CPU_SUBTYPE_MASK) == target.cpuSubtype()) return arch; // match for generic model of main architecture for (const fat_arch *arch = mArchList; arch < end; ++arch) - if (arch->cputype == target.cpuType() && arch->cpusubtype == 0) + if (arch->cputype == target.cpuType() + && (arch->cpusubtype & ~CPU_SUBTYPE_MASK) == 0) return arch; // match for any subarchitecture of the main architecture (questionable) for (const fat_arch *arch = mArchList; arch < end; ++arch) @@ -790,7 +791,7 @@ MachO *Universal::findImage(const Architecture &target) const MachO* Universal::make(MachO* macho) const { - auto_ptr mo(macho); // safe resource + unique_ptr mo(macho); // safe resource uint32_t type = mo->type(); if (type == 0) // not a recognized Mach-O type UnixError::throwMe(ENOEXEC); @@ -829,7 +830,7 @@ void Universal::architectures(Architectures &archs) const for (unsigned n = 0; n < mArchCount; n++) archs.insert(mArchList[n]); } else { - auto_ptr macho(architecture()); + unique_ptr macho(architecture()); archs.insert(macho->architecture()); } } @@ -880,7 +881,7 @@ bool Universal::isSuspicious() const Universal::Architectures archList; architectures(archList); for (Universal::Architectures::const_iterator it = archList.begin(); it != archList.end(); ++it) { - auto_ptr macho(architecture(*it)); + unique_ptr macho(architecture(*it)); if (macho->isSuspicious()) return true; } diff --git a/OSX/libsecurity_utilities/lib/macho++.h b/OSX/libsecurity_utilities/lib/macho++.h index a58ec309..f479c686 100644 --- a/OSX/libsecurity_utilities/lib/macho++.h +++ b/OSX/libsecurity_utilities/lib/macho++.h @@ -53,7 +53,7 @@ public: Architecture(const char *name); cpu_type_t cpuType() const { return this->first; } - cpu_subtype_t cpuSubtype() const { return this->second; } + cpu_subtype_t cpuSubtype() const { return this->second & ~CPU_SUBTYPE_MASK; } const char *name() const; // NULL if unknown std::string displayName() const; // always display-able diff --git a/OSX/libsecurity_utilities/lib/machserver.cpp b/OSX/libsecurity_utilities/lib/machserver.cpp index 4fca0b64..1281e480 100644 --- a/OSX/libsecurity_utilities/lib/machserver.cpp +++ b/OSX/libsecurity_utilities/lib/machserver.cpp @@ -177,6 +177,8 @@ void MachServer::runServerThread(bool doTimeout) for (;;) { // progress hook eventDone(); + + cleanupWorkers(); // cleanup worker threads that have exited // process all pending timers while (processTimer()) {} @@ -448,7 +450,7 @@ void MachServer::ensureReadyThread() this->threadLimitReached(workerCount); // call remedial handler } if (workerCount < maxWorkerCount) { // threadLimit() may have raised maxWorkerCount - (new LoadThread(*this))->run(); + (new LoadThread(*this))->threadRun(); } } } @@ -469,7 +471,7 @@ void MachServer::threadLimitReached(UInt32 limit) // // What our (non-primary) load threads do // -void MachServer::LoadThread::action() +void MachServer::LoadThread::threadAction() { //@@@ race condition?! can server exit before helpers thread gets here? @@ -504,8 +506,28 @@ void MachServer::removeThread(Thread *thread) workerCount--; idleCount--; workers.erase(thread); + deadWorkers.insert(thread); } +// Cleanup workers is a hack that make sure whe delete the object LoadThread +// that inheirit from Thread, this because there is no notification that the +// thread have completed. +// +// As I said, it a hack, but better then compeletely restructure how threads +// are brought up or replaced by XPC. Doing the XPC conversion should +// be done, because the current IPC mechanism doesn't handle that the server +// process dies and never comes back. + +void MachServer::cleanupWorkers() +{ + StLock _(managerLock); + while (!deadWorkers.empty()) { + auto item = deadWorkers.begin(); + auto worker = *item; + deadWorkers.erase(item); + delete worker; + } +} // // Timer management diff --git a/OSX/libsecurity_utilities/lib/machserver.h b/OSX/libsecurity_utilities/lib/machserver.h index 5b153ab1..1d276cc3 100644 --- a/OSX/libsecurity_utilities/lib/machserver.h +++ b/OSX/libsecurity_utilities/lib/machserver.h @@ -207,15 +207,16 @@ protected: protected: class LoadThread : public Thread { public: - LoadThread(MachServer &srv) : server(srv) { } + LoadThread(MachServer &srv) : Thread("MachServer"), server(srv) { } MachServer &server; - void action(); // code implementation + void threadAction(); // code implementation }; Mutex managerLock; // lock for thread-global management info below set workers; // threads running for this server + set deadWorkers; // threads that are no longer running and need to be freed UInt32 workerCount; // number of worker threads (including primary) UInt32 maxWorkerCount; // administrative limit to workerCount bool useFloatingThread; // keep a "floating" idle thread (instead of using longTermActivity) @@ -229,6 +230,7 @@ protected: void addThread(Thread *thread); // add thread to worker pool void removeThread(Thread *thread); // remove thread from worker pool + void cleanupWorkers(); bool processTimer(); // handle one due timer object, if any (return true if there was one) private: diff --git a/OSX/libsecurity_utilities/lib/muscle++.cpp b/OSX/libsecurity_utilities/lib/muscle++.cpp index face9600..5511fbd9 100644 --- a/OSX/libsecurity_utilities/lib/muscle++.cpp +++ b/OSX/libsecurity_utilities/lib/muscle++.cpp @@ -45,7 +45,7 @@ Error::Error(MSC_RV err) : error(err) } -const char *Error::what() const throw () +const char *Error::what() const _NOEXCEPT { return msc_error(error); } @@ -92,7 +92,10 @@ void Connection::open(const PCSC::ReaderState &reader, unsigned share) strncpy(info.slotName, reader.name(), MAX_READERNAME); // set ATR in info - assert(reader.length() <= MAX_ATR_SIZE); + if (reader.length() > MAX_ATR_SIZE) { + Error::throwMe(MSC_INVALID_PARAMETER); + } + memcpy(info.tokenId, reader.data(), reader.length()); info.tokenIdLength = (MSCULong32)reader.length(); diff --git a/OSX/libsecurity_utilities/lib/muscle++.h b/OSX/libsecurity_utilities/lib/muscle++.h index 016940ec..4c32be90 100644 --- a/OSX/libsecurity_utilities/lib/muscle++.h +++ b/OSX/libsecurity_utilities/lib/muscle++.h @@ -56,7 +56,7 @@ public: const MSC_RV error; OSStatus osStatus() const; int unixError() const; - const char *what () const throw (); + const char *what () const _NOEXCEPT; static void check(MSC_RV err) { if (err != MSC_SUCCESS) throwMe(err); } static void throwMe(MSC_RV err); diff --git a/OSX/libsecurity_utilities/lib/pcsc++.cpp b/OSX/libsecurity_utilities/lib/pcsc++.cpp index 67161287..2efb4c96 100644 --- a/OSX/libsecurity_utilities/lib/pcsc++.cpp +++ b/OSX/libsecurity_utilities/lib/pcsc++.cpp @@ -66,7 +66,7 @@ Error::Error(unsigned long err) : error(err) } -const char *Error::what() const throw () +const char *Error::what() const _NOEXCEPT { return pcsc_stringify_error((int32_t)error); } diff --git a/OSX/libsecurity_utilities/lib/pcsc++.h b/OSX/libsecurity_utilities/lib/pcsc++.h index 5ca469d7..b6eacebf 100644 --- a/OSX/libsecurity_utilities/lib/pcsc++.h +++ b/OSX/libsecurity_utilities/lib/pcsc++.h @@ -60,7 +60,7 @@ public: const unsigned long error; OSStatus osStatus() const; int unixError() const; - const char *what () const throw (); + const char *what () const _NOEXCEPT; static void check(unsigned long err) { if (err != SCARD_S_SUCCESS) throwMe(err); } static void throwMe(unsigned long err); diff --git a/OSX/libsecurity_utilities/lib/powerwatch.cpp b/OSX/libsecurity_utilities/lib/powerwatch.cpp index 9d733bab..f23735db 100644 --- a/OSX/libsecurity_utilities/lib/powerwatch.cpp +++ b/OSX/libsecurity_utilities/lib/powerwatch.cpp @@ -65,18 +65,14 @@ void PowerWatcher::systemWillPowerOn() IOPowerWatcher::IOPowerWatcher() : mKernelPort(0) { -#ifndef DARLING if (!(mKernelPort = ::IORegisterForSystemPower(this, &mPortRef, ioCallback, &mHandle))) UnixError::throwMe(EINVAL); // no clue -#endif } IOPowerWatcher::~IOPowerWatcher() { -#ifndef DARLING if (mKernelPort) ::IODeregisterForSystemPower(&mHandle); -#endif } // @@ -153,17 +149,13 @@ void IOPowerWatcher::ioCallback(void *refCon, io_service_t service, // PortPowerWatcher::PortPowerWatcher() { -#ifndef DARLING port(IONotificationPortGetMachPort(mPortRef)); -#endif } boolean_t PortPowerWatcher::handle(mach_msg_header_t *in) { -#ifndef DARLING IODispatchCalloutFromMessage(NULL, in, mPortRef); return TRUE; -#endif } diff --git a/OSX/libsecurity_utilities/lib/refcount.h b/OSX/libsecurity_utilities/lib/refcount.h index e94f5657..71b8c203 100644 --- a/OSX/libsecurity_utilities/lib/refcount.h +++ b/OSX/libsecurity_utilities/lib/refcount.h @@ -112,7 +112,7 @@ public: RefPointer& operator = (const RefPointer& p) { setPointer(p.ptr); return *this; } // dereference operations - T* get () const { _check(); return ptr; } // mimic auto_ptr + T* get () const { _check(); return ptr; } // mimic unique_ptr operator T * () const { _check(); return ptr; } T * operator -> () const { _check(); return ptr; } T & operator * () const { _check(); return *ptr; } diff --git a/OSX/libsecurity_utilities/lib/seccfobject.cpp b/OSX/libsecurity_utilities/lib/seccfobject.cpp index 93185ffc..04972e7c 100644 --- a/OSX/libsecurity_utilities/lib/seccfobject.cpp +++ b/OSX/libsecurity_utilities/lib/seccfobject.cpp @@ -112,7 +112,7 @@ void SecPointerBase::copy(SecCFObject * p) // SecCFObject // SecCFObject * -SecCFObject::optional(CFTypeRef cfTypeRef) throw() +SecCFObject::optional(CFTypeRef cfTypeRef) _NOEXCEPT { if (!cfTypeRef) return NULL; @@ -131,7 +131,7 @@ SecCFObject::required(CFTypeRef cfTypeRef, OSStatus error) } void * -SecCFObject::allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc) +SecCFObject::allocate(size_t size, const CFClass &cfclass) { CFTypeRef p = _CFRuntimeCreateInstance(NULL, cfclass.typeID, size + kAlignedRuntimeSize - sizeof(CFRuntimeBase), NULL); @@ -146,7 +146,7 @@ SecCFObject::allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc) } void -SecCFObject::operator delete(void *object) throw() +SecCFObject::operator delete(void *object) _NOEXCEPT { CFTypeRef cfType = reinterpret_cast(reinterpret_cast(object) - kAlignedRuntimeSize); @@ -217,7 +217,7 @@ SecCFObject::copyDebugDesc() } CFTypeRef -SecCFObject::handle(bool retain) throw() +SecCFObject::handle(bool retain) _NOEXCEPT { CFTypeRef cfType = *this; if (retain && !isNew()) CFRetain(cfType); diff --git a/OSX/libsecurity_utilities/lib/seccfobject.h b/OSX/libsecurity_utilities/lib/seccfobject.h index 29e9a5d3..6ea5445e 100644 --- a/OSX/libsecurity_utilities/lib/seccfobject.h +++ b/OSX/libsecurity_utilities/lib/seccfobject.h @@ -54,7 +54,7 @@ APIPTR handle(bool retain) \ #define SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \ SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR)\ \ -void *operator new(size_t size) throw(std::bad_alloc) \ +void *operator new(size_t size)\ { return SecCFObject::allocate(size, CFCLASS); } #define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \ @@ -79,7 +79,7 @@ struct SecRuntimeBase: CFRuntimeBase class SecCFObject { private: - void *operator new(size_t) throw(std::bad_alloc); + void *operator new(size_t); // Align up to a multiple of 16 bytes static const size_t kAlignedRuntimeSize = SECALIGNUP(sizeof(SecRuntimeBase), 4); @@ -97,23 +97,23 @@ public: return !atomic_flag_test_and_set(&(base->isOld)); } - static SecCFObject *optional(CFTypeRef) throw(); + static SecCFObject *optional(CFTypeRef) _NOEXCEPT; static SecCFObject *required(CFTypeRef, OSStatus error); - static void *allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc); + static void *allocate(size_t size, const CFClass &cfclass); SecCFObject(); virtual ~SecCFObject(); uint32_t updateRetainCount(intptr_t direction, uint32_t *oldCount); uint32_t getRetainCount() {return updateRetainCount(0, NULL);} - static void operator delete(void *object) throw(); - virtual operator CFTypeRef() const throw() + static void operator delete(void *object) _NOEXCEPT; + virtual operator CFTypeRef() const _NOEXCEPT { return reinterpret_cast(reinterpret_cast(this) - kAlignedRuntimeSize); } // This bumps up the retainCount by 1, by calling CFRetain(), iff retain is true - CFTypeRef handle(bool retain = true) throw(); + CFTypeRef handle(bool retain = true) _NOEXCEPT; virtual bool equal(SecCFObject &other); virtual CFHashCode hash(); @@ -156,10 +156,12 @@ public: T *yield() { T *result = static_cast(ptr); ptr = NULL; return result; } // dereference operations - T* get () const { return static_cast(ptr); } // mimic auto_ptr + T* get () const { return static_cast(ptr); } // mimic unique_ptr operator T * () const { return static_cast(ptr); } T * operator -> () const { return static_cast(ptr); } T & operator * () const { return *static_cast(ptr); } + + SecPointer& operator=(const SecPointer& other) { SecPointerBase::operator=(other); return *this; } }; template diff --git a/OSX/libsecurity_utilities/lib/simpleprefs.cpp b/OSX/libsecurity_utilities/lib/simpleprefs.cpp index c4d09774..26f40934 100644 --- a/OSX/libsecurity_utilities/lib/simpleprefs.cpp +++ b/OSX/libsecurity_utilities/lib/simpleprefs.cpp @@ -30,7 +30,7 @@ #include "errors.h" #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_utilities/lib/sqlite++.h b/OSX/libsecurity_utilities/lib/sqlite++.h index 888fcc8e..4f690c25 100644 --- a/OSX/libsecurity_utilities/lib/sqlite++.h +++ b/OSX/libsecurity_utilities/lib/sqlite++.h @@ -50,11 +50,11 @@ public: Error(Database &db); Error(int err) : error(err) { } Error(int err, const char *msg) : error(err), message(msg) { } - ~Error() throw () { } + ~Error() _NOEXCEPT { } const int error; const std::string message; - const char *what() const throw () { return message.c_str(); } + const char *what() const _NOEXCEPT { return message.c_str(); } OSStatus osStatus() const; int unixError() const; diff --git a/OSX/libsecurity_utilities/lib/superblob.h b/OSX/libsecurity_utilities/lib/superblob.h index ba7a5811..ce20f30a 100644 --- a/OSX/libsecurity_utilities/lib/superblob.h +++ b/OSX/libsecurity_utilities/lib/superblob.h @@ -6,6 +6,7 @@ #include #include +#include #include namespace Security { @@ -262,8 +263,10 @@ _BlobType *SuperBlobCore<_BlobType, _magic, _Type>::Maker::make() const pc += it->second->length(); n++; } - secinfo("superblob", "Maker %p assembles %ld blob(s) into %p (size=%d)", - this, mPieces.size(), result, total); + ostringstream os; + os << "Maker " << this << " assembles " << mPieces.size() << " blob(s) into " << result + << " (size=" << total << ")"; + secinfo("superblob", "%s", os.str().c_str()); return result; } diff --git a/OSX/libsecurity_utilities/lib/threading.cpp b/OSX/libsecurity_utilities/lib/threading.cpp index 4472c7f7..61ca1509 100644 --- a/OSX/libsecurity_utilities/lib/threading.cpp +++ b/OSX/libsecurity_utilities/lib/threading.cpp @@ -253,7 +253,7 @@ Thread::~Thread() { } -void Thread::run() +void Thread::threadRun() { pthread_t pt; pthread_attr_t ptattrs; @@ -284,10 +284,10 @@ void *Thread::runner(void *arg) // otherwise it will crash if something underneath throws. { Thread *me = static_cast(arg); - secinfo("thread", "%p starting", pthread_self()); - me->action(); - secinfo("thread", "%p terminating", pthread_self()); - delete me; + pthread_setname_np(me->threadName); + secinfo("thread", "%p: %s starting", pthread_self(), me->threadName); + me->threadAction(); + secinfo("thread", "%p: %s terminating", pthread_self(), me->threadName); return NULL; } catch (...) @@ -296,22 +296,7 @@ void *Thread::runner(void *arg) } } -void Thread::yield() +void Thread::threadYield() { ::sched_yield(); } - - -// -// ThreadRunner implementation -// -ThreadRunner::ThreadRunner(Action *todo) -{ - mAction = todo; - run(); -} - -void ThreadRunner::action() -{ - mAction(); -} diff --git a/OSX/libsecurity_utilities/lib/threading.h b/OSX/libsecurity_utilities/lib/threading.h index 5886f047..60d64b6c 100644 --- a/OSX/libsecurity_utilities/lib/threading.h +++ b/OSX/libsecurity_utilities/lib/threading.h @@ -380,37 +380,24 @@ public: // class Thread { NOCOPY(Thread) + const char *threadName; public: - Thread() { } // constructor + Thread(const char *name): threadName(name) { } // constructor virtual ~Thread(); // virtual destructor - void run(); // begin running the thread + void threadRun(); // begin running the thread public: - static void yield(); // unstructured short-term processor yield + static void threadYield(); // unstructured short-term processor yield protected: - virtual void action() = 0; // the action to be performed + virtual void threadAction() = 0; // the action to be performed private: static void *runner(void *); // argument to pthread_create }; -// -// A "just run this function in a thread" variant of Thread -// -class ThreadRunner : public Thread { - typedef void Action(); -public: - ThreadRunner(Action *todo); - -private: - void action(); - Action *mAction; -}; - - } // end namespace Security #endif //_H_THREADING diff --git a/OSX/libsecurity_utilities/lib/trackingallocator.cpp b/OSX/libsecurity_utilities/lib/trackingallocator.cpp index 33650037..bab8ab47 100644 --- a/OSX/libsecurity_utilities/lib/trackingallocator.cpp +++ b/OSX/libsecurity_utilities/lib/trackingallocator.cpp @@ -43,20 +43,20 @@ TrackingAllocator::~TrackingAllocator() // Standard allocation operations. // We pass them down to our subAllocator and keep track of what we've got. // -void *TrackingAllocator::malloc(size_t inSize) throw(std::bad_alloc) +void *TrackingAllocator::malloc(size_t inSize) { void *anAddress = subAllocator.malloc(inSize); mAllocSet.insert(anAddress); return anAddress; } -void TrackingAllocator::free(void *inAddress) throw() +void TrackingAllocator::free(void *inAddress) _NOEXCEPT { subAllocator.free(inAddress); mAllocSet.erase(inAddress); } -void *TrackingAllocator::realloc(void *inAddress, size_t inNewSize) throw(std::bad_alloc) +void *TrackingAllocator::realloc(void *inAddress, size_t inNewSize) { void *anAddress = subAllocator.realloc(inAddress, inNewSize); if (anAddress != inAddress) diff --git a/OSX/libsecurity_utilities/lib/trackingallocator.h b/OSX/libsecurity_utilities/lib/trackingallocator.h index 01e2ccce..09fbee4e 100644 --- a/OSX/libsecurity_utilities/lib/trackingallocator.h +++ b/OSX/libsecurity_utilities/lib/trackingallocator.h @@ -47,9 +47,9 @@ public: Allocator &subAllocator; // standard Allocator operations - void *malloc(size_t inSize) throw(std::bad_alloc); - void free(void *inAddress) throw(); - void *realloc(void *inAddress, size_t inNewSize) throw(std::bad_alloc); + void *malloc(size_t inSize); + void free(void *inAddress) _NOEXCEPT; + void *realloc(void *inAddress, size_t inNewSize); // reset frees all memory; commit forgets about it all void reset(); diff --git a/OSX/libsecurity_utilities/lib/unix++.cpp b/OSX/libsecurity_utilities/lib/unix++.cpp index 225e8150..e8208576 100644 --- a/OSX/libsecurity_utilities/lib/unix++.cpp +++ b/OSX/libsecurity_utilities/lib/unix++.cpp @@ -439,6 +439,12 @@ bool FileDesc::isA(int mode) const return (st.st_mode & S_IFMT) == mode; } +string FileDesc::realPath() const +{ + char absPath[MAXPATHLEN]; + fcntl(F_GETPATH, absPath); + return absPath; +} void FileDesc::chown(uid_t uid) { @@ -480,6 +486,20 @@ AutoFileDesc::AutoFileDesc(const AutoFileDesc& rhs) mAtEnd = rhs.mAtEnd; } +AutoFileDesc::AutoFileDesc(AutoFileDesc&& rhs) +{ + setFd(rhs.fd()); + rhs.setFd(invalidFd); + mAtEnd = rhs.mAtEnd; +} + +AutoFileDesc& AutoFileDesc::operator=(AutoFileDesc&& rhs) +{ + setFd(rhs.fd()); + rhs.setFd(invalidFd); + mAtEnd = rhs.mAtEnd; + return *this; +} // // Device characteristics diff --git a/OSX/libsecurity_utilities/lib/unix++.h b/OSX/libsecurity_utilities/lib/unix++.h index b41ccd7d..d6c09aaa 100644 --- a/OSX/libsecurity_utilities/lib/unix++.h +++ b/OSX/libsecurity_utilities/lib/unix++.h @@ -96,6 +96,8 @@ public: FileDesc() : mFd(invalidFd), mAtEnd(false) { } FileDesc(int fd) : mFd(fd), mAtEnd(false) { } + FileDesc(const FileDesc& fd) : mFd(fd.mFd), mAtEnd(fd.mAtEnd) { } + static const mode_t modeMissingOk = S_IFIFO; // in mode means "do not throw on ENOENT" // implicit file system open() construction @@ -224,6 +226,8 @@ public: void fstat(UnixStat &st) const; size_t fileSize() const; bool isA(int type) const; + + string realPath() const; // change various permissions-related features on the open file void chown(uid_t uid); @@ -273,7 +277,10 @@ public: AutoFileDesc(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666) : FileDesc(path, flag, mode) { } AutoFileDesc(const AutoFileDesc& rhs); + AutoFileDesc(AutoFileDesc&& rhs); ~AutoFileDesc() { closeAndLog(); } + + AutoFileDesc& operator=(AutoFileDesc&& rhs); }; diff --git a/OSX/libsecurity_utilities/lib/unixchild.cpp b/OSX/libsecurity_utilities/lib/unixchild.cpp index 9e1c9f75..b6369d5c 100644 --- a/OSX/libsecurity_utilities/lib/unixchild.cpp +++ b/OSX/libsecurity_utilities/lib/unixchild.cpp @@ -42,6 +42,7 @@ #include #include +#include namespace Security { namespace UnixPlusPlus { @@ -371,7 +372,7 @@ bool Child::checkStatus(int options) secinfo("unixchild", "checking %p (pid %d)", this, this->pid()); int status; again: - switch (IFDEBUG(pid_t pid =) ::wait4(this->pid(), &status, options, NULL)) { + switch (pid_t pid = ::wait4(this->pid(), &status, options, NULL)) { case pid_t(-1): switch (errno) { case EINTR: @@ -420,7 +421,9 @@ void Child::checkChildren() } else if (!mChildren().empty()) { int status; while (pid_t pid = ::wait4(0, &status, WNOHANG, NULL)) { - secinfo("unixchild", "universal child check (%ld children known alive)", mChildren().size()); + ostringstream os; + os << "universal child check (" << mChildren().size() << " children known alive)"; + secinfo("unixchild", "%s", os.str().c_str()); switch (pid) { case pid_t(-1): switch (errno) { diff --git a/OSX/libsecurity_utilities/lib/utilities.h b/OSX/libsecurity_utilities/lib/utilities.h index 2bd28d56..b3bd7de1 100644 --- a/OSX/libsecurity_utilities/lib/utilities.h +++ b/OSX/libsecurity_utilities/lib/utilities.h @@ -35,6 +35,8 @@ #include #include +#include + namespace Security { diff --git a/OSX/libsecurity_utilities/lib/utilities_dtrace.h b/OSX/libsecurity_utilities/lib/utilities_dtrace.h deleted file mode 100644 index b44b6fa6..00000000 --- a/OSX/libsecurity_utilities/lib/utilities_dtrace.h +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Generated by dtrace(1M). - */ - -#ifndef _UTILITIES_DTRACE_H -#define _UTILITIES_DTRACE_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define SECURITY_DEBUG_STABILITY "___dtrace_stability$security_debug$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0" - -#define SECURITY_DEBUG_TYPEDEFS "___dtrace_typedefs$security_debug$v2" - -#if !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED - -#define SECURITY_DEBUG_DELAY(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_DEBUG_TYPEDEFS); \ - __dtrace_probe$security_debug$delay$v1$63686172202a(arg0); \ - __asm__ volatile(".reference " SECURITY_DEBUG_STABILITY); \ -} while (0) -#define SECURITY_DEBUG_DELAY_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_debug$delay$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_DEBUG_LOG(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_DEBUG_TYPEDEFS); \ - __dtrace_probe$security_debug$log$v1$63686172202a$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_DEBUG_STABILITY); \ -} while (0) -#define SECURITY_DEBUG_LOG_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_debug$log$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_DEBUG_LOGP(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITY_DEBUG_TYPEDEFS); \ - __dtrace_probe$security_debug$logp$v1$63686172202a$766f6964202a$63686172202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITY_DEBUG_STABILITY); \ -} while (0) -#define SECURITY_DEBUG_LOGP_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_debug$logp$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_DEBUG_REFCOUNT_CREATE(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_DEBUG_TYPEDEFS); \ - __dtrace_probe$security_debug$refcount__create$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " SECURITY_DEBUG_STABILITY); \ -} while (0) -#define SECURITY_DEBUG_REFCOUNT_CREATE_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_debug$refcount__create$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_DEBUG_REFCOUNT_DOWN(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_DEBUG_TYPEDEFS); \ - __dtrace_probe$security_debug$refcount__down$v1$766f6964202a$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_DEBUG_STABILITY); \ -} while (0) -#define SECURITY_DEBUG_REFCOUNT_DOWN_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_debug$refcount__down$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_DEBUG_REFCOUNT_UP(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_DEBUG_TYPEDEFS); \ - __dtrace_probe$security_debug$refcount__up$v1$766f6964202a$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_DEBUG_STABILITY); \ -} while (0) -#define SECURITY_DEBUG_REFCOUNT_UP_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_debug$refcount__up$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_DEBUG_SEC_CREATE(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITY_DEBUG_TYPEDEFS); \ - __dtrace_probe$security_debug$sec__create$v1$766f6964202a$63686172202a$756e7369676e6564(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITY_DEBUG_STABILITY); \ -} while (0) -#define SECURITY_DEBUG_SEC_CREATE_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_debug$sec__create$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_DEBUG_SEC_DESTROY(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_DEBUG_TYPEDEFS); \ - __dtrace_probe$security_debug$sec__destroy$v1$766f6964202a(arg0); \ - __asm__ volatile(".reference " SECURITY_DEBUG_STABILITY); \ -} while (0) -#define SECURITY_DEBUG_SEC_DESTROY_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_debug$sec__destroy$v1(); \ - __asm__ volatile(""); \ - _r; }) - - -extern void __dtrace_probe$security_debug$delay$v1$63686172202a(const char *); -extern int __dtrace_isenabled$security_debug$delay$v1(void); -extern void __dtrace_probe$security_debug$log$v1$63686172202a$63686172202a(const char *, const char *); -extern int __dtrace_isenabled$security_debug$log$v1(void); -extern void __dtrace_probe$security_debug$logp$v1$63686172202a$766f6964202a$63686172202a(const char *, const void *, const char *); -extern int __dtrace_isenabled$security_debug$logp$v1(void); -extern void __dtrace_probe$security_debug$refcount__create$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$security_debug$refcount__create$v1(void); -extern void __dtrace_probe$security_debug$refcount__down$v1$766f6964202a$756e7369676e6564(const void *, unsigned); -extern int __dtrace_isenabled$security_debug$refcount__down$v1(void); -extern void __dtrace_probe$security_debug$refcount__up$v1$766f6964202a$756e7369676e6564(const void *, unsigned); -extern int __dtrace_isenabled$security_debug$refcount__up$v1(void); -extern void __dtrace_probe$security_debug$sec__create$v1$766f6964202a$63686172202a$756e7369676e6564(const void *, const char *, unsigned); -extern int __dtrace_isenabled$security_debug$sec__create$v1(void); -extern void __dtrace_probe$security_debug$sec__destroy$v1$766f6964202a(const void *); -extern int __dtrace_isenabled$security_debug$sec__destroy$v1(void); - -#else - -#define SECURITY_DEBUG_DELAY(arg0) \ -do { \ - } while (0) -#define SECURITY_DEBUG_DELAY_ENABLED() (0) -#define SECURITY_DEBUG_LOG(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_DEBUG_LOG_ENABLED() (0) -#define SECURITY_DEBUG_LOGP(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITY_DEBUG_LOGP_ENABLED() (0) -#define SECURITY_DEBUG_REFCOUNT_CREATE(arg0) \ -do { \ - } while (0) -#define SECURITY_DEBUG_REFCOUNT_CREATE_ENABLED() (0) -#define SECURITY_DEBUG_REFCOUNT_DOWN(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_DEBUG_REFCOUNT_DOWN_ENABLED() (0) -#define SECURITY_DEBUG_REFCOUNT_UP(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_DEBUG_REFCOUNT_UP_ENABLED() (0) -#define SECURITY_DEBUG_SEC_CREATE(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITY_DEBUG_SEC_CREATE_ENABLED() (0) -#define SECURITY_DEBUG_SEC_DESTROY(arg0) \ -do { \ - } while (0) -#define SECURITY_DEBUG_SEC_DESTROY_ENABLED() (0) - -#endif /* !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED */ - -#define SECURITY_EXCEPTION_STABILITY "___dtrace_stability$security_exception$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0" - -#define SECURITY_EXCEPTION_TYPEDEFS "___dtrace_typedefs$security_exception$v2$4454457863657074696f6e" - -#if !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED - -#define SECURITY_EXCEPTION_COPY(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$copy$v1$4454457863657074696f6e$4454457863657074696f6e(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_COPY_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$copy$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_EXCEPTION_HANDLED(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$handled$v1$4454457863657074696f6e(arg0); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_HANDLED_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$handled$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_EXCEPTION_THROW_CF(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$throw__cf$v1$4454457863657074696f6e(arg0); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_THROW_CF_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$throw__cf$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_EXCEPTION_THROW_CSSM(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$throw__cssm$v1$4454457863657074696f6e$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_THROW_CSSM_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$throw__cssm$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_EXCEPTION_THROW_MACH(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$throw__mach$v1$4454457863657074696f6e$696e74(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_THROW_MACH_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$throw__mach$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_EXCEPTION_THROW_OSSTATUS(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$throw__osstatus$v1$4454457863657074696f6e$696e74(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_THROW_OSSTATUS_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$throw__osstatus$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_EXCEPTION_THROW_OTHER(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$throw__other$v1$4454457863657074696f6e$756e7369676e6564$63686172202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_THROW_OTHER_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$throw__other$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_EXCEPTION_THROW_PCSC(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$throw__pcsc$v1$4454457863657074696f6e$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_THROW_PCSC_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$throw__pcsc$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_EXCEPTION_THROW_SQLITE(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$throw__sqlite$v1$4454457863657074696f6e$696e74$63686172202a(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_THROW_SQLITE_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$throw__sqlite$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_EXCEPTION_THROW_UNIX(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_TYPEDEFS); \ - __dtrace_probe$security_exception$throw__unix$v1$4454457863657074696f6e$696e74(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_EXCEPTION_STABILITY); \ -} while (0) -#define SECURITY_EXCEPTION_THROW_UNIX_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_exception$throw__unix$v1(); \ - __asm__ volatile(""); \ - _r; }) - - -extern void __dtrace_probe$security_exception$copy$v1$4454457863657074696f6e$4454457863657074696f6e(DTException, DTException); -extern int __dtrace_isenabled$security_exception$copy$v1(void); -extern void __dtrace_probe$security_exception$handled$v1$4454457863657074696f6e(DTException); -extern int __dtrace_isenabled$security_exception$handled$v1(void); -extern void __dtrace_probe$security_exception$throw__cf$v1$4454457863657074696f6e(DTException); -extern int __dtrace_isenabled$security_exception$throw__cf$v1(void); -extern void __dtrace_probe$security_exception$throw__cssm$v1$4454457863657074696f6e$756e7369676e6564(DTException, unsigned); -extern int __dtrace_isenabled$security_exception$throw__cssm$v1(void); -extern void __dtrace_probe$security_exception$throw__mach$v1$4454457863657074696f6e$696e74(DTException, int); -extern int __dtrace_isenabled$security_exception$throw__mach$v1(void); -extern void __dtrace_probe$security_exception$throw__osstatus$v1$4454457863657074696f6e$696e74(DTException, int); -extern int __dtrace_isenabled$security_exception$throw__osstatus$v1(void); -extern void __dtrace_probe$security_exception$throw__other$v1$4454457863657074696f6e$756e7369676e6564$63686172202a(DTException, unsigned, const char *); -extern int __dtrace_isenabled$security_exception$throw__other$v1(void); -extern void __dtrace_probe$security_exception$throw__pcsc$v1$4454457863657074696f6e$756e7369676e6564(DTException, unsigned); -extern int __dtrace_isenabled$security_exception$throw__pcsc$v1(void); -extern void __dtrace_probe$security_exception$throw__sqlite$v1$4454457863657074696f6e$696e74$63686172202a(DTException, int, const char *); -extern int __dtrace_isenabled$security_exception$throw__sqlite$v1(void); -extern void __dtrace_probe$security_exception$throw__unix$v1$4454457863657074696f6e$696e74(DTException, int); -extern int __dtrace_isenabled$security_exception$throw__unix$v1(void); - -#else - -#define SECURITY_EXCEPTION_COPY(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_COPY_ENABLED() (0) -#define SECURITY_EXCEPTION_HANDLED(arg0) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_HANDLED_ENABLED() (0) -#define SECURITY_EXCEPTION_THROW_CF(arg0) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_THROW_CF_ENABLED() (0) -#define SECURITY_EXCEPTION_THROW_CSSM(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_THROW_CSSM_ENABLED() (0) -#define SECURITY_EXCEPTION_THROW_MACH(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_THROW_MACH_ENABLED() (0) -#define SECURITY_EXCEPTION_THROW_OSSTATUS(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_THROW_OSSTATUS_ENABLED() (0) -#define SECURITY_EXCEPTION_THROW_OTHER(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_THROW_OTHER_ENABLED() (0) -#define SECURITY_EXCEPTION_THROW_PCSC(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_THROW_PCSC_ENABLED() (0) -#define SECURITY_EXCEPTION_THROW_SQLITE(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_THROW_SQLITE_ENABLED() (0) -#define SECURITY_EXCEPTION_THROW_UNIX(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_EXCEPTION_THROW_UNIX_ENABLED() (0) - -#endif /* !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED */ - -#define SECURITY_MACHSERVER_STABILITY "___dtrace_stability$security_machserver$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0" - -#define SECURITY_MACHSERVER_TYPEDEFS "___dtrace_typedefs$security_machserver$v2" - -#if !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED - -#define SECURITY_MACHSERVER_ALLOC_REGISTER(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$alloc__register$v1$766f6964202a$766f6964202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_ALLOC_REGISTER_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$alloc__register$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_ALLOC_RELEASE(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$alloc__release$v1$766f6964202a$766f6964202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_ALLOC_RELEASE_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$alloc__release$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_BEGIN(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$begin$v1$756e7369676e6564$696e74(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_BEGIN_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$begin$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_END() \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$end$v1(); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_END_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$end$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_END_THREAD(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$end_thread$v1$696e74(arg0); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_END_THREAD_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$end_thread$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_PORT_ADD(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$port__add$v1$756e7369676e6564(arg0); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_PORT_ADD_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$port__add$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_PORT_REMOVE(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$port__remove$v1$756e7369676e6564(arg0); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_PORT_REMOVE_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$port__remove$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_REAP(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$reap$v1$756e7369676e6564$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_REAP_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$reap$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_RECEIVE(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$receive$v1$646f75626c65(arg0); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_RECEIVE_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$receive$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_RECEIVE_ERROR(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$receive_error$v1$756e7369676e6564(arg0); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_RECEIVE_ERROR_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$receive_error$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_SEND_ERROR(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$send_error$v1$756e7369676e6564$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_SEND_ERROR_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$send_error$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_START_THREAD(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$start_thread$v1$696e74(arg0); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_START_THREAD_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$start_thread$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_TIMER_END(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$timer__end$v1$696e74(arg0); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_TIMER_END_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$timer__end$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITY_MACHSERVER_TIMER_START(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_TYPEDEFS); \ - __dtrace_probe$security_machserver$timer__start$v1$766f6964202a$696e74$646f75626c65(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITY_MACHSERVER_STABILITY); \ -} while (0) -#define SECURITY_MACHSERVER_TIMER_START_ENABLED() \ - ({ int _r = __dtrace_isenabled$security_machserver$timer__start$v1(); \ - __asm__ volatile(""); \ - _r; }) - - -extern void __dtrace_probe$security_machserver$alloc__register$v1$766f6964202a$766f6964202a(const void *, const void *); -extern int __dtrace_isenabled$security_machserver$alloc__register$v1(void); -extern void __dtrace_probe$security_machserver$alloc__release$v1$766f6964202a$766f6964202a(const void *, const void *); -extern int __dtrace_isenabled$security_machserver$alloc__release$v1(void); -extern void __dtrace_probe$security_machserver$begin$v1$756e7369676e6564$696e74(unsigned, int); -extern int __dtrace_isenabled$security_machserver$begin$v1(void); -extern void __dtrace_probe$security_machserver$end$v1(void); -extern int __dtrace_isenabled$security_machserver$end$v1(void); -extern void __dtrace_probe$security_machserver$end_thread$v1$696e74(int); -extern int __dtrace_isenabled$security_machserver$end_thread$v1(void); -extern void __dtrace_probe$security_machserver$port__add$v1$756e7369676e6564(unsigned); -extern int __dtrace_isenabled$security_machserver$port__add$v1(void); -extern void __dtrace_probe$security_machserver$port__remove$v1$756e7369676e6564(unsigned); -extern int __dtrace_isenabled$security_machserver$port__remove$v1(void); -extern void __dtrace_probe$security_machserver$reap$v1$756e7369676e6564$756e7369676e6564(unsigned, unsigned); -extern int __dtrace_isenabled$security_machserver$reap$v1(void); -extern void __dtrace_probe$security_machserver$receive$v1$646f75626c65(double); -extern int __dtrace_isenabled$security_machserver$receive$v1(void); -extern void __dtrace_probe$security_machserver$receive_error$v1$756e7369676e6564(unsigned); -extern int __dtrace_isenabled$security_machserver$receive_error$v1(void); -extern void __dtrace_probe$security_machserver$send_error$v1$756e7369676e6564$756e7369676e6564(unsigned, unsigned); -extern int __dtrace_isenabled$security_machserver$send_error$v1(void); -extern void __dtrace_probe$security_machserver$start_thread$v1$696e74(int); -extern int __dtrace_isenabled$security_machserver$start_thread$v1(void); -extern void __dtrace_probe$security_machserver$timer__end$v1$696e74(int); -extern int __dtrace_isenabled$security_machserver$timer__end$v1(void); -extern void __dtrace_probe$security_machserver$timer__start$v1$766f6964202a$696e74$646f75626c65(const void *, int, double); -extern int __dtrace_isenabled$security_machserver$timer__start$v1(void); - -#else - -#define SECURITY_MACHSERVER_ALLOC_REGISTER(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_ALLOC_REGISTER_ENABLED() (0) -#define SECURITY_MACHSERVER_ALLOC_RELEASE(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_ALLOC_RELEASE_ENABLED() (0) -#define SECURITY_MACHSERVER_BEGIN(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_BEGIN_ENABLED() (0) -#define SECURITY_MACHSERVER_END() \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_END_ENABLED() (0) -#define SECURITY_MACHSERVER_END_THREAD(arg0) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_END_THREAD_ENABLED() (0) -#define SECURITY_MACHSERVER_PORT_ADD(arg0) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_PORT_ADD_ENABLED() (0) -#define SECURITY_MACHSERVER_PORT_REMOVE(arg0) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_PORT_REMOVE_ENABLED() (0) -#define SECURITY_MACHSERVER_REAP(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_REAP_ENABLED() (0) -#define SECURITY_MACHSERVER_RECEIVE(arg0) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_RECEIVE_ENABLED() (0) -#define SECURITY_MACHSERVER_RECEIVE_ERROR(arg0) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_RECEIVE_ERROR_ENABLED() (0) -#define SECURITY_MACHSERVER_SEND_ERROR(arg0, arg1) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_SEND_ERROR_ENABLED() (0) -#define SECURITY_MACHSERVER_START_THREAD(arg0) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_START_THREAD_ENABLED() (0) -#define SECURITY_MACHSERVER_TIMER_END(arg0) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_TIMER_END_ENABLED() (0) -#define SECURITY_MACHSERVER_TIMER_START(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITY_MACHSERVER_TIMER_START_ENABLED() (0) - -#endif /* !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _UTILITIES_DTRACE_H */ diff --git a/OSX/libsecurity_utilities/lib/utility_config.h b/OSX/libsecurity_utilities/lib/utility_config.h index 7919078e..94611ebc 100644 --- a/OSX/libsecurity_utilities/lib/utility_config.h +++ b/OSX/libsecurity_utilities/lib/utility_config.h @@ -29,7 +29,7 @@ #define _H_UTILITY_CONFIG #include -#include +#include // // Decide what io apis we'll be using diff --git a/OSX/libsecurityd/lib/eventlistener.cpp b/OSX/libsecurityd/lib/eventlistener.cpp index efe37a67..ed26dbf8 100644 --- a/OSX/libsecurityd/lib/eventlistener.cpp +++ b/OSX/libsecurityd/lib/eventlistener.cpp @@ -42,14 +42,7 @@ typedef std::list EventListenerList; static const char* GetNotificationName () { - // the name we give the client depends on the value of the environment variable "SECURITYSERVER" - const char* name = getenv (SECURITYSERVER_BOOTSTRAP_ENV); - if (name == NULL) - { - name = SharedMemoryCommon::kDefaultSecurityMessagesName; - } - - return name; + return SharedMemoryCommon::kDefaultSecurityMessagesName; } diff --git a/OSX/libsecurityd/lib/sec_xdr.c b/OSX/libsecurityd/lib/sec_xdr.c index e3ae277a..2e72e060 100644 --- a/OSX/libsecurityd/lib/sec_xdr.c +++ b/OSX/libsecurityd/lib/sec_xdr.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include "sec_xdr.h" diff --git a/OSX/libsecurityd/lib/sec_xdr_array.c b/OSX/libsecurityd/lib/sec_xdr_array.c index a0f710f1..e5bcc87a 100644 --- a/OSX/libsecurityd/lib/sec_xdr_array.c +++ b/OSX/libsecurityd/lib/sec_xdr_array.c @@ -72,7 +72,7 @@ static char *sccsid = "@(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC"; #include #include #include -#include +#include #include "sec_xdr.h" diff --git a/OSX/libsecurityd/lib/sec_xdr_reference.c b/OSX/libsecurityd/lib/sec_xdr_reference.c index 0ceadc0f..e36a6da7 100644 --- a/OSX/libsecurityd/lib/sec_xdr_reference.c +++ b/OSX/libsecurityd/lib/sec_xdr_reference.c @@ -59,7 +59,7 @@ static char *sccsid = "@(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC"; static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_reference.c,v 1.11 2002/03/22 21:53:26 obrien Exp $"; #endif #include -#include +#include /* * xdr_reference.c, Generic XDR routines impelmentation. * diff --git a/OSX/libsecurityd/lib/ss_types.defs b/OSX/libsecurityd/lib/ss_types.defs deleted file mode 120000 index 7003782e..00000000 --- a/OSX/libsecurityd/lib/ss_types.defs +++ /dev/null @@ -1 +0,0 @@ -../mig/ss_types.defs \ No newline at end of file diff --git a/OSX/libsecurityd/lib/ssclient.cpp b/OSX/libsecurityd/lib/ssclient.cpp index a6341b12..98d27a6b 100644 --- a/OSX/libsecurityd/lib/ssclient.cpp +++ b/OSX/libsecurityd/lib/ssclient.cpp @@ -26,6 +26,7 @@ // ssclient - SecurityServer client interface library // #include "sstransit.h" +#include #include #include @@ -67,6 +68,31 @@ ClientSession::registerForAclEdits(DidChangeKeyAclCallback *callback, void *cont mCallbackContext = context; } +// chroot safety: revert to old behavior on old kernel +static task_id_token_t +self_token_create(void) +{ + task_id_token_t self_token = TASK_ID_TOKEN_NULL; + + kern_return_t kr = task_create_identity_token(mach_task_self(), &self_token); + if (kr == MIG_BAD_ID) { + self_token = mach_task_self(); + } else { + os_assert_zero(kr); + } + + return self_token; +} + +// chroot safety: self_token_create may have returned the task port +static void +self_token_deallocate(task_id_token_t token) +{ + if (token != mach_task_self()) { + (void)mach_port_deallocate(mach_task_self(), token); + } +} + // // Perform any preambles required to be a securityd client in good standing. // This includes initial setup calls, thread registration, fork management, @@ -87,7 +113,9 @@ void ClientSession::activate() Thread &thread = global.thread(); if (!thread) { // first time for this thread - use abbreviated registration - IPCN(ucsp_client_setupThread(UCSP_ARGS, mach_task_self())); + task_id_token_t token = self_token_create(); + IPCN(ucsp_client_setupThread(UCSP_ARGS, token)); + self_token_deallocate(token); thread.registered = true; secinfo("SSclnt", "Thread registered with %s", mContactName); } @@ -135,8 +163,10 @@ ClientSession::Global::Global() // cannot use UCSP_ARGS here because it uses mGlobal() -> deadlock Thread &thread = this->thread(); + task_id_token_t token = self_token_create(); IPCBASIC(ucsp_client_setup(serverPort, thread.replyPort, &securitydCreds, &rcode, - mach_task_self(), info, extForm)); + token, info, extForm)); + self_token_deallocate(token); thread.registered = true; // as a side-effect of setup call above IFDEBUG(serverPort.requestNotify(thread.replyPort)); secinfo("SSclnt", "contact with %s established", mContactName); @@ -166,9 +196,7 @@ Port ClientSession::findSecurityd() { if (!mContactName) { - mContactName = getenv(SECURITYSERVER_BOOTSTRAP_ENV); - if (!mContactName) - mContactName = SECURITYSERVER_BOOTSTRAP_NAME; + mContactName = SECURITYSERVER_BOOTSTRAP_NAME; } secinfo("SSclnt", "Locating %s", mContactName); diff --git a/OSX/libsecurityd/lib/sscommon.h b/OSX/libsecurityd/lib/sscommon.h index e0710366..96b37163 100644 --- a/OSX/libsecurityd/lib/sscommon.h +++ b/OSX/libsecurityd/lib/sscommon.h @@ -61,11 +61,9 @@ using MachPlusPlus::ReceivePort; // -// The default Mach bootstrap registration name for SecurityServer, -// and the environment variable to override it +// The Mach bootstrap registration name for SecurityServer // #define SECURITYSERVER_BOOTSTRAP_NAME "com.apple.SecurityServer" -#define SECURITYSERVER_BOOTSTRAP_ENV "SECURITYSERVER" // // Types of ACL bearers diff --git a/OSX/libsecurityd/lib/sstransit.cpp b/OSX/libsecurityd/lib/sstransit.cpp index a59d7b3f..cf209e67 100644 --- a/OSX/libsecurityd/lib/sstransit.cpp +++ b/OSX/libsecurityd/lib/sstransit.cpp @@ -155,7 +155,10 @@ DataRetrieval::~DataRetrieval() { if (mAddr) { relocate(mAddr, mBase); - assert(mAttributes->size() == mAddr->size()); + if (mAttributes->size() != mAddr->size()) { + secemergency("~DataRetrieval: size mismatch, %u != %u", mAttributes->size(), mAddr->size()); + abort(); + } // global (per-record) fields mAttributes->recordType(mAddr->recordType()); diff --git a/OSX/libsecurityd/lib/xdr_auth.c b/OSX/libsecurityd/lib/xdr_auth.c index 69ac9335..a4539cab 100644 --- a/OSX/libsecurityd/lib/xdr_auth.c +++ b/OSX/libsecurityd/lib/xdr_auth.c @@ -26,7 +26,6 @@ #include #include #include -#include bool_t xdr_AuthorizationItem(XDR *xdrs, AuthorizationItem *objp) diff --git a/OSX/libsecurityd/lib/xdr_cssm.c b/OSX/libsecurityd/lib/xdr_cssm.c index f74ce46e..e7200777 100644 --- a/OSX/libsecurityd/lib/xdr_cssm.c +++ b/OSX/libsecurityd/lib/xdr_cssm.c @@ -24,7 +24,7 @@ #include #include /* bzero() */ #include /* exit() */ -#include /* assert() */ +#include /* assert() */ #include /* XXX/gh because utilities/debugging.h doesn't */ #include diff --git a/OSX/macos_tapi_hacks.h b/OSX/macos_tapi_hacks.h index a03e17e8..02666f37 100644 --- a/OSX/macos_tapi_hacks.h +++ b/OSX/macos_tapi_hacks.h @@ -82,12 +82,20 @@ bool securityd_message_no_error(xpc_object_t message, CFErrorRef *error); void SecAccessGroupsSetCurrent(CFArrayRef accessGroups); CFArrayRef SecAccessGroupsGetCurrent(void); +void SecSecurityClientRegularToAppClip(void); +void SecSecurityClientAppClipToRegular(void); +void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier); void SecServerSetTrustdMachServiceName(const char *name); // checkpw.c int checkpw_internal( const struct passwd* pw, const char* password ); +#ifdef __arm64__ +extern SecKeyRef SecCertificateCopyPublicKey_ios(SecCertificateRef certificate) __asm("_SecCertificateCopyPublicKey"); +extern CFDataRef SecCertificateCopySerialNumber_ios(SecCertificateRef certificate) __asm("_SecCertificateCopySerialNumber"); +#endif + #pragma clang diagnostic pop #endif /* macos_tapi_hack_h */ diff --git a/OSX/regressions/t/security.pl b/OSX/regressions/t/security.pl old mode 100644 new mode 100755 diff --git a/OSX/regressions/test/testenv.h b/OSX/regressions/test/testenv.h index 6c7b177d..bc53356d 100644 --- a/OSX/regressions/test/testenv.h +++ b/OSX/regressions/test/testenv.h @@ -33,7 +33,6 @@ extern "C" { extern int test_strict_bats; extern int test_verbose; extern int test_check_leaks; -extern char **test_skip_leaks_test; int tests_begin(int argc, char * const *argv); diff --git a/OSX/regressions/test/testenv.m b/OSX/regressions/test/testenv.m index 8692ff3c..f644cbe1 100644 --- a/OSX/regressions/test/testenv.m +++ b/OSX/regressions/test/testenv.m @@ -59,7 +59,6 @@ int test_strict_bats = 1; int test_verbose = 0; int test_onebatstest = 0; int test_check_leaks = 0; -char **test_skip_leaks_test = NULL; #ifdef NO_SERVER #include "keychain/securityd/spi.h" @@ -210,34 +209,8 @@ static int tests_run_test(struct one_test_s *test, int argc, char * const *argv) free(cmd); } if (ret != 0) { - unsigned n = 0; fprintf(stdout, "leaks found in test %s\n", test->name); - - if (test_skip_leaks_test) { - while (test_skip_leaks_test[n]) { - if (strcmp(test_skip_leaks_test[n], test->name) == 0) { - fprintf(stdout, "test %s known to be leaky, skipping\n", test->name); - ret = 0; - break; - } - } - } - if (ret) { - token = "FAIL"; - } - } else { - if (test_skip_leaks_test) { - unsigned n = 0; - - while (test_skip_leaks_test[n]) { - if (strcmp(test_skip_leaks_test[n], test->name) == 0) { - fprintf(stdout, "leaks didn't find leak in test %s, yet it was ignore\n", test->name); - token = "FAIL"; - break; - } - } - } - + token = "FAIL"; } } diff --git a/OSX/regressions/test/testmore.h b/OSX/regressions/test/testmore.h index 7bf5e726..cea9ccdb 100644 --- a/OSX/regressions/test/testmore.h +++ b/OSX/regressions/test/testmore.h @@ -41,12 +41,12 @@ __BEGIN_DECLS #define DISABLED_ONE_TEST(x) ONE_TEST(x) #define OFF_ONE_TEST(x) ONE_TEST(x) -typedef int (*one_test_entry)(int argc, char *const *argv); +typedef int (*_Nonnull one_test_entry)(int argc, char *_Nonnull const *_Nonnull argv); #define ONE_TEST_ENTRY(x) int x(int argc, char *const *argv) struct one_test_s { - char *name; /* test name. */ + const char * _Nonnull name; /* test name. */ one_test_entry entry; /* entry point. */ int off; /* off by default. */ int sub_tests; /* number of subtests. */ @@ -55,7 +55,7 @@ struct one_test_s { int todo_tests; /* number of todo tests that failed as expected. */ int actual_tests; /* number of tests attempted. */ int planned_tests; /* number of planned tests. */ - const char *plan_file; /* full path to file that called plan_tests() */ + const char *_Nonnull plan_file; /* full path to file that called plan_tests() */ int plan_line; /* line number in plan_file at which plan_tests was called. */ unsigned long duration; /* test duration in msecs. */ /* add more later: timing, etc... */ @@ -215,22 +215,22 @@ static void test_failed_noreturn() __attribute((analyzer_noreturn)) { }) -extern const char *test_directive; -extern const char *test_reason; +extern const char * _Nonnull test_directive; +extern const char * _Nonnull test_reason; -void test_bail_out(const char *reason, const char *file, unsigned line); -int test_diag(const char *directive, const char *reason, - const char *file, unsigned line, const char *fmt, ...) __attribute__((format(printf, 5, 6))); -int test_ok(int passed, __attribute((cf_consumed)) CFStringRef description, const char *directive, - const char *reason, const char *file, unsigned line, const char *fmt, ...); -void test_plan_skip_all(const char *reason); -void test_plan_tests(int count, const char *file, unsigned line); +void test_bail_out(const char * _Nonnull reason, const char * _Nonnull file, unsigned line); +int test_diag(const char *_Nonnull directive, const char *_Nonnull reason, + const char *_Nonnull file, unsigned line, const char *_Nonnull fmt, ...) __attribute__((format(printf, 5, 6))); +int test_ok(int passed, __attribute((cf_consumed)) CFStringRef _Nullable description, const char *_Nonnull directive, + const char *_Nonnull reason, const char *_Nonnull file, unsigned line, const char *_Nullable fmt, ...); +void test_plan_skip_all(const char *_Nonnull reason); +void test_plan_tests(int count, const char *_Nonnull file, unsigned line); int test_plan_ok(void); -void test_plan_final(int *failed, int *todo_pass, int *todo, int *actual, int *planned, const char **file, int *line); +void test_plan_final(int *_Nonnull failed, int *_Nonnull todo_pass, int *_Nonnull todo, int *_Nonnull actual, int *_Nonnull planned, const char *_Nonnull *_Nonnull file, int *_Nonnull line); -void test_skip(const char *reason, int how_many, int unless); +void test_skip(const char *_Nonnull reason, int how_many, int unless); -const char *sec_errstr(int err); +const char *_Nonnull sec_errstr(int err); __END_DECLS diff --git a/OSX/sec/Security/AppleBaselineEscrowCertificates.h b/OSX/sec/Security/AppleBaselineEscrowCertificates.h index a2483bac..46f6f653 100644 --- a/OSX/sec/Security/AppleBaselineEscrowCertificates.h +++ b/OSX/sec/Security/AppleBaselineEscrowCertificates.h @@ -296,6 +296,71 @@ static const UInt8 kBaseLineEscrowRoot102[] = { 0xF6,0x05,0xC3,0xD2, }; +static const UInt8 kBaseLinePCSEscrowRoot300[] = { + 0x30, 0x82, 0x03, 0xd1, 0x30, 0x82, 0x02, 0xb9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x01, + 0x2c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, + 0x30, 0x79, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x03, 0x33, 0x30, 0x30, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x16, 0x45, 0x73, 0x63, 0x72, 0x6f, 0x77, 0x20, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x32, + 0x31, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x37, 0x30, 0x31, 0x5a, 0x17, 0x0d, 0x33, 0x31, + 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x37, 0x30, 0x31, 0x5a, 0x30, 0x79, 0x31, 0x0c, 0x30, + 0x0a, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x03, 0x33, 0x30, 0x30, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, + 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, + 0x45, 0x73, 0x63, 0x72, 0x6f, 0x77, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x52, + 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb2, 0x90, 0xf8, 0x1e, 0x2d, 0xe8, 0x22, 0xab, 0xa7, + 0x85, 0xe2, 0x38, 0xe2, 0x77, 0x94, 0x23, 0x57, 0xce, 0x6a, 0x74, 0x39, 0xd9, 0x91, 0xe5, 0x27, + 0xc1, 0xe2, 0x99, 0x4e, 0x63, 0x4f, 0xe4, 0xde, 0xa8, 0x7c, 0x6e, 0x3a, 0x3d, 0x99, 0x03, 0xe8, + 0x53, 0xab, 0x97, 0x97, 0x53, 0xb6, 0xba, 0xff, 0x48, 0xee, 0x67, 0x3b, 0xe7, 0xea, 0x11, 0x6a, + 0x5a, 0x28, 0xbd, 0x8d, 0x9f, 0xd1, 0xd0, 0xc4, 0x72, 0xb5, 0xe9, 0x44, 0x0a, 0x6a, 0xd9, 0x3c, + 0x23, 0x8e, 0xec, 0xc4, 0xaf, 0x02, 0x12, 0xd8, 0x17, 0x62, 0x75, 0x87, 0xaa, 0x61, 0xd1, 0x92, + 0xba, 0x06, 0xf6, 0x58, 0x85, 0xd4, 0x77, 0xca, 0xaf, 0x33, 0x6f, 0x90, 0xe8, 0xe8, 0xa4, 0x24, + 0xe9, 0x1c, 0x82, 0x5a, 0x5f, 0x85, 0xae, 0x25, 0xbc, 0x28, 0xe4, 0x49, 0xac, 0xfc, 0x47, 0xc7, + 0xc5, 0x11, 0xef, 0x1d, 0x93, 0xb0, 0xc2, 0xa4, 0x1c, 0xeb, 0xc4, 0xfb, 0xa1, 0xee, 0x95, 0x45, + 0xf0, 0x61, 0x30, 0xbe, 0xa1, 0xf5, 0x63, 0x16, 0xfa, 0x44, 0x99, 0x8c, 0x04, 0x41, 0x29, 0xd7, + 0xf5, 0x59, 0x0f, 0xc8, 0xf0, 0x16, 0xc2, 0xf1, 0x8e, 0x83, 0xd1, 0x76, 0xcd, 0x3b, 0xc5, 0x6d, + 0xb9, 0xe4, 0x88, 0x68, 0xf4, 0xc1, 0x83, 0xbf, 0xec, 0x20, 0x7f, 0x34, 0x30, 0x4d, 0x3a, 0x5d, + 0x62, 0xfe, 0x50, 0x5a, 0x01, 0xb9, 0xfb, 0xab, 0x0a, 0x49, 0x61, 0xef, 0x79, 0xbf, 0x03, 0xe8, + 0x48, 0x8d, 0x62, 0x65, 0xc1, 0x87, 0xf4, 0x94, 0xa3, 0xfc, 0x81, 0x82, 0xad, 0x81, 0xbc, 0x08, + 0x5a, 0x75, 0xea, 0xc8, 0x08, 0x94, 0xc1, 0xe9, 0x3d, 0x10, 0xf6, 0x4c, 0xc6, 0x6e, 0x9c, 0x66, + 0x4e, 0xfc, 0xfe, 0xba, 0x9e, 0x47, 0x7a, 0x31, 0x46, 0x18, 0x54, 0xc8, 0xae, 0xd1, 0x6f, 0x9f, + 0xd1, 0xf1, 0x48, 0x4e, 0x4f, 0xe8, 0x3f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, + 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb4, 0xc4, 0x5e, 0x40, + 0x39, 0x80, 0xd4, 0xb3, 0x56, 0x86, 0xc3, 0x92, 0x12, 0xab, 0x4b, 0xcb, 0x10, 0x7d, 0xfb, 0x9b, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4, 0xc4, 0x5e, + 0x40, 0x39, 0x80, 0xd4, 0xb3, 0x56, 0x86, 0xc3, 0x92, 0x12, 0xab, 0x4b, 0xcb, 0x10, 0x7d, 0xfb, + 0x9b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x2d, 0x5e, 0x70, 0xfe, 0x59, 0x6a, 0xf3, 0xea, 0xad, 0x86, 0x82, + 0x69, 0xc6, 0x30, 0x54, 0xd4, 0x31, 0xe5, 0xd9, 0xbd, 0x5e, 0x07, 0x8e, 0x96, 0x5e, 0xee, 0x73, + 0xd9, 0xdf, 0xc7, 0xd3, 0x2b, 0x3f, 0x1a, 0x9a, 0x2e, 0xf1, 0x4a, 0x51, 0x9a, 0x75, 0xc2, 0xd9, + 0x65, 0xcb, 0x4e, 0x98, 0x18, 0xc4, 0xce, 0x50, 0xd2, 0x5c, 0xc7, 0x18, 0xcc, 0xcf, 0xc2, 0x27, + 0x20, 0x39, 0x11, 0x1e, 0x66, 0x9f, 0x6c, 0x06, 0x3f, 0xf0, 0x01, 0xef, 0xa1, 0x3e, 0x33, 0xe5, + 0x8e, 0x62, 0x02, 0xd4, 0x86, 0xc2, 0xed, 0x25, 0xa6, 0x95, 0x40, 0xec, 0xc3, 0xe1, 0xdd, 0x46, + 0x01, 0xd2, 0x0a, 0x54, 0x0a, 0x70, 0xcf, 0xeb, 0x40, 0xf4, 0xd2, 0x92, 0xdd, 0xa1, 0xbd, 0x19, + 0x32, 0x28, 0xca, 0x87, 0xeb, 0xa5, 0x08, 0xcc, 0x5c, 0x79, 0x25, 0x64, 0x4e, 0x48, 0x4d, 0x7d, + 0x00, 0x65, 0x56, 0x53, 0xd3, 0x83, 0xe6, 0x30, 0xe3, 0x2e, 0x41, 0x7c, 0x46, 0x2d, 0xe8, 0x4b, + 0xb6, 0xa3, 0x1f, 0x9a, 0x9a, 0xf4, 0x86, 0xf1, 0x8f, 0xae, 0xa7, 0x8b, 0x55, 0xcb, 0x8b, 0x3f, + 0x88, 0x66, 0x5b, 0xa6, 0xc6, 0xe9, 0x26, 0x89, 0xd3, 0x77, 0x82, 0xc8, 0xca, 0xab, 0x01, 0x64, + 0x11, 0xa2, 0x35, 0x4d, 0xa5, 0x56, 0xfe, 0xc1, 0xee, 0x68, 0xd3, 0xbf, 0x07, 0x66, 0x27, 0xd8, + 0xeb, 0x78, 0xb6, 0xd7, 0x14, 0xbb, 0xcd, 0xf6, 0x4b, 0xe6, 0x6f, 0x87, 0x13, 0x7b, 0xdf, 0xba, + 0x2f, 0xb1, 0xf4, 0x96, 0x53, 0x83, 0x91, 0xef, 0x7e, 0xf2, 0x41, 0xd2, 0x7d, 0xd8, 0xe4, 0x17, + 0x46, 0xbb, 0x44, 0xd8, 0x5c, 0x3e, 0xe2, 0x56, 0x81, 0xd8, 0xcb, 0x73, 0xf8, 0x54, 0x2c, 0xf5, + 0x1d, 0x6c, 0xa9, 0x44, 0xdb, 0xa1, 0x86, 0x86, 0x03, 0xd7, 0x0f, 0x49, 0xe8, 0x89, 0xa2, 0xd0, + 0xed, 0x7d, 0xe3, 0xe7, 0x2c +}; + static struct RootRecord kBaseLineEscrowRootRecord100 = {sizeof(kBaseLineEscrowRoot100), (UInt8*)kBaseLineEscrowRoot100}; static struct RootRecord kBaseLineEscrowRootRecord101 = {sizeof(kBaseLineEscrowRoot101), (UInt8*)kBaseLineEscrowRoot101}; static struct RootRecord kBaseLineEscrowRootRecord102 = {sizeof(kBaseLineEscrowRoot102), (UInt8*)kBaseLineEscrowRoot102}; @@ -313,8 +378,9 @@ static const int kNumberOfBaseLineEscrowBackupRoots = (int)(sizeof(kBaseLineEscr static const int kNumberOfBaseLineEscrowEnrollmentRoots = (int)(sizeof(kBaseLineEscrowEnrollmentRoots)/sizeof(kBaseLineEscrowEnrollmentRoots[0])); static struct RootRecord kBaseLinePCSEscrowRootRecord100 = {sizeof(kBaseLinePCSEscrowRoot100), (UInt8*)kBaseLinePCSEscrowRoot100}; +static struct RootRecord kBaseLinePCSEscrowRootRecord300 = {sizeof(kBaseLinePCSEscrowRoot300), (UInt8*)kBaseLinePCSEscrowRoot300}; static struct RootRecord* kBaseLinePCSEscrowRoots[] = { - &kBaseLinePCSEscrowRootRecord100 + &kBaseLinePCSEscrowRootRecord100, &kBaseLinePCSEscrowRootRecord300 }; static const int kNumberOfBaseLinePCSEscrowRoots = (int)(sizeof(kBaseLinePCSEscrowRoots)/sizeof(kBaseLinePCSEscrowRoots[0])); diff --git a/OSX/sec/Security/AppleExternalRootCertificates.h b/OSX/sec/Security/AppleExternalRootCertificates.h new file mode 100644 index 00000000..392314ca --- /dev/null +++ b/OSX/sec/Security/AppleExternalRootCertificates.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _sec_AppleExternalRootCertificates_h +#define _sec_AppleExternalRootCertificates_h + +#include + +/* subject:/CN=Apple External EC Root/O=Apple Inc./C=US */ +/* issuer :/CN=Apple External EC Root/O=Apple Inc./C=US */ +uint8_t _AppleExternalECRootCA[519]={ + 0x30,0x82,0x02,0x03,0x30,0x82,0x01,0x89,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x76, + 0xAD,0x18,0xDB,0x88,0x12,0xB0,0x56,0xA1,0x26,0x9D,0x44,0x91,0x4E,0xEB,0xD4,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x30,0x43,0x31,0x1F,0x30, + 0x1D,0x06,0x03,0x55,0x04,0x03,0x0C,0x16,0x41,0x70,0x70,0x6C,0x65,0x20,0x45,0x78, + 0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x43,0x20,0x52,0x6F,0x6F,0x74,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 0x30,0x1E,0x17,0x0D,0x32,0x30,0x30,0x31,0x32,0x33,0x30,0x30,0x34,0x36,0x34,0x38, + 0x5A,0x17,0x0D,0x34,0x35,0x30,0x31,0x31,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x5A, + 0x30,0x43,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03,0x0C,0x16,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x43,0x20,0x52, + 0x6F,0x6F,0x74,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x30,0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, + 0x02,0x01,0x06,0x05,0x2B,0x81,0x04,0x00,0x22,0x03,0x62,0x00,0x04,0x17,0xC7,0x4A, + 0xDD,0xD2,0x3C,0xAF,0xB0,0x76,0xA3,0x2A,0x57,0x1E,0x2C,0x7F,0x38,0x0B,0x62,0x04, + 0x75,0x54,0x36,0xBB,0x0E,0xB7,0xAA,0x2C,0x7B,0xF9,0xE8,0xB3,0xC5,0x09,0x08,0xB3, + 0xDF,0x20,0x27,0xB1,0x95,0x96,0x16,0x63,0x46,0x6C,0xFF,0x24,0xA4,0x00,0xF2,0x87, + 0xC1,0x7F,0xED,0xE7,0x28,0x49,0xB3,0x5A,0xBC,0x02,0xAA,0x93,0x47,0x62,0x9E,0x5F, + 0x9F,0x43,0xC9,0xF2,0x25,0x89,0x83,0x62,0x60,0xBB,0x57,0x6A,0x59,0xA8,0x0B,0xB3, + 0x32,0x25,0x75,0xD7,0x8B,0xEF,0xF1,0xD2,0x41,0xD3,0x57,0x90,0x4B,0xA3,0x42,0x30, + 0x40,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01, + 0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x3F,0xA4,0xC0, + 0x94,0x20,0x70,0xCB,0x3B,0xDD,0xA8,0x54,0xE6,0x14,0x1E,0x29,0xCC,0x4D,0x14,0x38, + 0x53,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01, + 0x06,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x68,0x00, + 0x30,0x65,0x02,0x31,0x00,0x9D,0x4D,0x05,0x75,0x65,0x76,0xD8,0x70,0x03,0x14,0x39, + 0x8E,0x41,0xC7,0xB2,0xFE,0x53,0xDC,0x6E,0xE6,0x13,0x18,0x51,0x0A,0x1F,0xC4,0xB5, + 0xCF,0x22,0x40,0x75,0x79,0xCA,0x98,0x6E,0xB0,0xF5,0x88,0x71,0x11,0x3E,0x3B,0x7C, + 0x38,0x35,0xD7,0x1F,0xB9,0x02,0x30,0x5B,0x7C,0x87,0xF3,0xF6,0xDD,0x51,0x96,0x6D, + 0xF8,0x7E,0xF2,0x78,0x3A,0xC6,0xA6,0x85,0x55,0xE8,0xBD,0x20,0xAC,0xE1,0x58,0x79, + 0x14,0x50,0x3D,0x54,0xC3,0xF1,0x22,0x15,0x18,0x87,0x95,0x67,0x9E,0x19,0x69,0x89, + 0x51,0x2C,0xD0,0x55,0xEA,0x52,0x6C, +}; + +/* subject:/CN=Test Apple External EC Root/O=Apple Inc./C=US */ +/* issuer :/CN=Test Apple External EC Root/O=Apple Inc./C=US */ +uint8_t _TestAppleExternalECRootCA[530]={ + 0x30,0x82,0x02,0x0E,0x30,0x82,0x01,0x93,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x70, + 0x1B,0x1A,0x15,0x07,0x97,0x6A,0x6A,0x8D,0xBD,0x23,0x36,0xF2,0x48,0x4A,0x4E,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x30,0x48,0x31,0x24,0x30, + 0x22,0x06,0x03,0x55,0x04,0x03,0x0C,0x1B,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x43,0x20,0x52, + 0x6F,0x6F,0x74,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x39,0x31,0x31,0x30,0x35,0x31, + 0x38,0x30,0x30,0x34,0x36,0x5A,0x17,0x0D,0x34,0x34,0x31,0x30,0x32,0x39,0x31,0x38, + 0x30,0x30,0x34,0x36,0x5A,0x30,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x03, + 0x0C,0x1B,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x45,0x78,0x74, + 0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x43,0x20,0x52,0x6F,0x6F,0x74,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x05,0x2B,0x81, + 0x04,0x00,0x22,0x03,0x62,0x00,0x04,0x91,0xC2,0xB5,0xBC,0x6A,0x99,0x8B,0x68,0x5A, + 0xCE,0xD4,0x8C,0x48,0xF1,0x0F,0xD2,0x00,0x8D,0x88,0x6A,0x14,0x53,0xEC,0xFA,0xE7, + 0xCC,0x97,0x01,0x0A,0x64,0x9F,0x69,0xE2,0xF8,0xC8,0x54,0x0E,0xD2,0x7C,0x9A,0x22, + 0xE5,0xEF,0xE1,0x56,0xF3,0x2A,0xB0,0x99,0xAD,0x88,0x4A,0xCE,0x2C,0xD4,0x60,0x90, + 0xF1,0x90,0xA6,0xB0,0x45,0xC4,0x82,0x0B,0xB0,0x46,0xE5,0xE7,0x14,0xCC,0x98,0x9E, + 0x13,0xD0,0x43,0x51,0x64,0x0C,0xCD,0xA6,0xAF,0x5C,0x14,0x52,0x5A,0xF2,0x08,0x8D, + 0xE4,0x04,0x54,0x74,0x13,0x91,0x02,0xA3,0x42,0x30,0x40,0x30,0x0F,0x06,0x03,0x55, + 0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x07,0x6B,0x07,0x47,0x33,0xE4,0x96,0xB4,0xFC, + 0x6F,0xFA,0x32,0x2C,0x8E,0xBE,0x70,0xC2,0x8F,0x80,0x3C,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0A,0x06,0x08,0x2A, + 0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x69,0x00,0x30,0x66,0x02,0x31,0x00,0xED, + 0xC0,0xC6,0x05,0x62,0x3E,0x4C,0x76,0x0C,0x5B,0x62,0xF9,0x54,0x2E,0x90,0xC4,0xDB, + 0x29,0xD1,0x2D,0x2F,0x30,0x15,0x8A,0xCF,0x9F,0xA0,0x5A,0x40,0x6C,0x6A,0x9F,0x76, + 0xC1,0x5E,0xC3,0x37,0x40,0xA1,0x9B,0xA4,0x0D,0x31,0x9D,0x4C,0xBB,0x2B,0xAE,0x02, + 0x31,0x00,0xDA,0xCB,0xE4,0x1D,0x12,0x4E,0x03,0x2F,0x91,0xCF,0x2A,0xB3,0xF4,0xB3, + 0x8D,0x89,0x69,0xF2,0x9B,0xFC,0xB4,0x05,0x95,0x0B,0xCB,0x63,0x12,0xC8,0xAA,0x8D, + 0x58,0xE8,0xF3,0x2A,0xF6,0x36,0x32,0xAC,0x0A,0x24,0x94,0x84,0x85,0x00,0x96,0x62, + 0x62,0x57, +}; + +#endif /* _sec_AppleExternalRootCertificates_h */ diff --git a/OSX/sec/Security/Regressions/otr/otr-00-identity.c b/OSX/sec/Security/Regressions/otr/otr-00-identity.c index 0439e50a..71652028 100644 --- a/OSX/sec/Security/Regressions/otr/otr-00-identity.c +++ b/OSX/sec/Security/Regressions/otr/otr-00-identity.c @@ -30,6 +30,10 @@ #include #include #include +#include +#include +#include +#include static void RegressionsLogError(CFErrorRef error) { if (error == NULL) { @@ -52,13 +56,59 @@ static void RegressionsLogError(CFErrorRef error) { CFReleaseSafe(tempDictionary); } -static int kTestTestCount = 18; +static int kTestTestCount = 27; + +static void otr_00_identity_MessageProtectionKeys() +{ + // We create a MessageProtection-style key. + int32_t keysz32 = 256; + CFNumberRef ksizeNumber = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFDictionaryRef dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrKeySizeInBits, ksizeNumber, + kSecAttrIsPermanent, kCFBooleanFalse, NULL); + + CFErrorRef error = NULL; + SecKeyRef testIdentityKey = SecKeyCreateRandomKey(dict, &error); + ok(testIdentityKey != NULL, "Failed to create test key."); + + CFReleaseSafe(ksizeNumber); + CFReleaseSafe(dict); + + SecOTRFullIdentityRef identity1 = SecOTRFullIdentityCreateFromSecKeyRef(kCFAllocatorDefault, testIdentityKey, &error); + ok(identity1->isMessageProtectionKey, "Should be MessageProtection Key"); + ok(identity1->privateKeyPersistentRef == NULL, "MessageProtection key shouldn't have a peristent ref."); + + CFMutableDataRef serializeInto = CFDataCreateMutable(kCFAllocatorDefault, 100); + SecOTRFIAppendSerialization(identity1, serializeInto, &error); + + SecOTRFullIdentityRef identity2 = SecOTRFullIdentityCreateFromData(kCFAllocatorDefault, serializeInto, &error); + ok(identity2->isMessageProtectionKey, "Should still be a MessageProtection Key"); + ok(identity2->privateKeyPersistentRef == NULL, "MessageProtection key shouldn't have a peristent ref."); + + CFDataRef serializedKey1 = SecKeyCopyExternalRepresentation(identity1->privateSigningKey, &error); + CFDataRef serializedKey2 = SecKeyCopyExternalRepresentation(identity2->privateSigningKey, &error); + + ok(CFEqual(serializedKey1, serializedKey2)); + ok(error == NULL, "Testing shouldn't cause any errors"); + + CFReleaseSafe(error); + CFReleaseSafe(serializedKey1); + CFReleaseSafe(serializedKey2); + CFReleaseSafe(identity1); + CFReleaseSafe(identity2); + CFReleaseSafe(testIdentityKey); + CFReleaseNull(serializeInto); +} + static void tests(void) { CFErrorRef testError = NULL; SecOTRFullIdentityRef idToPurge = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError); ok(idToPurge != NULL, "Make Identity: %@", testError); + ok(idToPurge->isMessageProtectionKey == false, "Keys shouldn't be defaulting to MessageProtection type"); RegressionsLogError(testError); CFReleaseNull(testError); @@ -70,6 +120,7 @@ static void tests(void) SecOTRFullIdentityRef purgeIdInflate = SecOTRFullIdentityCreateFromData(kCFAllocatorDefault, purgeExport, &testError); ok(purgeIdInflate != NULL, "Inflate Identity: %@", testError); + ok(idToPurge->isMessageProtectionKey == false, "Keys shouldn't be re-imported as MessageProtection types"); RegressionsLogError(testError); CFReleaseNull(testError); @@ -195,8 +246,12 @@ static void tests(void) CFReleaseSafe(failIDInflate2); CFReleaseSafe(testInteropImport); CFReleaseSafe(interopIDInflate); + + otr_00_identity_MessageProtectionKeys(); } + + int otr_00_identity(int argc, char *const *argv) { plan_tests(kTestTestCount); diff --git a/OSX/sec/Security/Regressions/secitem/si-21-sectrust-asr.c b/OSX/sec/Security/Regressions/secitem/si-21-sectrust-asr.c deleted file mode 100644 index 0e7e5350..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-21-sectrust-asr.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * si-21-sectrust-asr.c - * Security - * - * Copyright (c) 2009-2010,2012 Apple Inc.. All Rights Reserved. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "shared_regressions.h" - -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } -#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); (CF) = NULL; } - -static const UInt8 sITunesStoreRootCertificate[] = -{ - 0x30, 0x82, 0x04, 0x65, 0x30, 0x82, 0x03, 0x4d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, - 0xcb, 0x06, 0xa3, 0x3b, 0x30, 0xc3, 0x24, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x7e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x15, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, - 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, - 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x52, 0x6f, 0x6f, - 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, - 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, - 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x31, 0x30, 0x30, - 0x39, 0x31, 0x37, 0x35, 0x31, 0x33, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x32, 0x31, 0x30, 0x30, 0x32, - 0x31, 0x37, 0x35, 0x31, 0x33, 0x30, 0x5a, 0x30, 0x7e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x15, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, - 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, - 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x52, 0x6f, 0x6f, - 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, - 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, - 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, - 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa9, 0x78, 0xc0, 0xaf, 0x1a, 0x96, 0x59, 0xad, - 0xf8, 0x3c, 0x16, 0xe1, 0xfc, 0xc4, 0x7a, 0xaf, 0xf0, 0x80, 0xed, 0x7f, 0x3a, 0xff, 0xf2, 0x2a, - 0xb6, 0xf3, 0x1a, 0xdd, 0xbd, 0x14, 0xb1, 0x5d, 0x9d, 0x66, 0xaf, 0xc7, 0xaf, 0x2b, 0x26, 0x78, - 0x9c, 0xb8, 0x0b, 0x41, 0x9c, 0xdc, 0x17, 0xf1, 0x40, 0x18, 0x09, 0xa1, 0x0a, 0xbc, 0x01, 0x9a, - 0x0c, 0xbe, 0x89, 0xdb, 0x9d, 0x34, 0xc7, 0x52, 0x8a, 0xf2, 0xbf, 0x35, 0x2b, 0x24, 0x04, 0xb0, - 0x0c, 0x9d, 0x41, 0x7d, 0x63, 0xe3, 0xad, 0xcf, 0x8b, 0x34, 0xbf, 0x5c, 0x42, 0x82, 0x9b, 0x78, - 0x7f, 0x00, 0x10, 0x88, 0xd9, 0xfd, 0xf8, 0xbf, 0x63, 0x2c, 0x91, 0x87, 0x03, 0xda, 0xbc, 0xc6, - 0x71, 0x2b, 0x9a, 0x21, 0x30, 0x95, 0xd6, 0x88, 0xe8, 0xbd, 0x0a, 0x74, 0xa4, 0xa6, 0x39, 0xd0, - 0x61, 0xd3, 0xb6, 0xe0, 0x2b, 0x1e, 0xe4, 0x78, 0x5c, 0x70, 0x32, 0x66, 0x97, 0x34, 0xa9, 0x79, - 0xfc, 0x96, 0xaf, 0x4b, 0x8a, 0xd5, 0x12, 0x07, 0x8c, 0x1c, 0xf6, 0x3e, 0x5f, 0xdc, 0x8f, 0x92, - 0x10, 0xe8, 0x7e, 0xa0, 0x14, 0x1e, 0x61, 0x28, 0xfa, 0xcc, 0xcf, 0x3c, 0xdb, 0x2b, 0xe3, 0xe9, - 0x44, 0x4a, 0x9d, 0x5f, 0x92, 0x3d, 0xa3, 0xfd, 0x1a, 0x63, 0xb4, 0xbb, 0xab, 0x67, 0x45, 0xc6, - 0x4d, 0x84, 0x4a, 0xaa, 0x33, 0xe4, 0xde, 0xd3, 0x04, 0x92, 0xbf, 0xf7, 0x00, 0x48, 0x76, 0xc6, - 0x4e, 0x17, 0xea, 0x70, 0xdb, 0x09, 0xbc, 0x22, 0x07, 0x7b, 0x97, 0x49, 0xe5, 0x29, 0xa7, 0x1a, - 0x04, 0xd2, 0x0d, 0x0e, 0x73, 0xf1, 0x49, 0x43, 0x34, 0x35, 0x61, 0xe5, 0x67, 0xdf, 0x3c, 0x58, - 0x42, 0x51, 0xfb, 0xc3, 0xa4, 0x15, 0x6d, 0x39, 0x6b, 0x2a, 0x22, 0xde, 0xdd, 0xe2, 0x36, 0x5b, - 0xd7, 0x37, 0x53, 0x96, 0x9d, 0x3a, 0x9f, 0x4b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe5, - 0x30, 0x81, 0xe2, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb0, 0xda, - 0xe1, 0x7f, 0xa8, 0x8b, 0x4a, 0x6a, 0x81, 0x5d, 0x0c, 0xa1, 0x84, 0x56, 0x46, 0x1e, 0x6a, 0xef, - 0xe5, 0xcf, 0x30, 0x81, 0xb2, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xaa, 0x30, 0x81, 0xa7, - 0x80, 0x14, 0xb0, 0xda, 0xe1, 0x7f, 0xa8, 0x8b, 0x4a, 0x6a, 0x81, 0x5d, 0x0c, 0xa1, 0x84, 0x56, - 0x46, 0x1e, 0x6a, 0xef, 0xe5, 0xcf, 0xa1, 0x81, 0x83, 0xa4, 0x81, 0x80, 0x30, 0x7e, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, - 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x11, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, - 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, - 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x82, 0x09, 0x00, 0xcb, - 0x06, 0xa3, 0x3b, 0x30, 0xc3, 0x24, 0x03, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0xcc, 0xfb, 0x34, 0x4e, 0xec, 0x27, - 0x05, 0xf9, 0x10, 0xc9, 0xdf, 0x8e, 0x22, 0x21, 0x94, 0x70, 0xe9, 0x74, 0x64, 0x11, 0xce, 0x07, - 0x91, 0xc2, 0x58, 0x0d, 0xff, 0x51, 0x6d, 0x97, 0x64, 0x32, 0x1a, 0x1c, 0xdf, 0x4a, 0x93, 0xdb, - 0x94, 0x62, 0x14, 0xcb, 0x00, 0x13, 0x37, 0x98, 0x0e, 0x3d, 0x96, 0x19, 0x5f, 0x44, 0xc9, 0x11, - 0xd2, 0xc9, 0x8c, 0xa3, 0x19, 0x2f, 0x88, 0x4f, 0x5f, 0x3c, 0x46, 0x56, 0xe2, 0xbd, 0x78, 0x4f, - 0xfe, 0x8e, 0x39, 0xb5, 0xed, 0x37, 0x3e, 0xfb, 0xf6, 0xae, 0x56, 0x2c, 0x49, 0x37, 0x4a, 0x94, - 0x05, 0x4b, 0x8f, 0x67, 0xdb, 0xe6, 0x24, 0xa6, 0x75, 0xae, 0xc8, 0xa2, 0x26, 0x87, 0x70, 0xb8, - 0x1d, 0xc2, 0xfc, 0x8d, 0xff, 0x41, 0x23, 0x8a, 0x01, 0x8a, 0xc3, 0x78, 0x5a, 0x61, 0x4a, 0xed, - 0x48, 0x96, 0xb5, 0x82, 0xa7, 0xaa, 0x2e, 0xb5, 0xed, 0xdd, 0xf4, 0xe6, 0xb5, 0xa1, 0x27, 0x3b, - 0xda, 0xf9, 0x18, 0x26, 0x7e, 0x8e, 0xec, 0xef, 0xe1, 0x00, 0x7d, 0x3d, 0xf7, 0x3d, 0x01, 0x68, - 0x14, 0x92, 0xfc, 0x9c, 0xbb, 0x0a, 0xa1, 0xc3, 0x60, 0x31, 0x16, 0x08, 0x9b, 0xef, 0x4d, 0xaf, - 0x46, 0xc7, 0xcc, 0x4e, 0x05, 0x34, 0xa8, 0x44, 0xb2, 0x85, 0x03, 0x67, 0x6c, 0x31, 0xae, 0xa3, - 0x18, 0xb5, 0x5f, 0x75, 0xae, 0xe0, 0x5a, 0xbf, 0x64, 0x32, 0x2b, 0x28, 0x99, 0x24, 0xcd, 0x01, - 0x34, 0xc2, 0xfc, 0xf1, 0x88, 0xba, 0x8c, 0x9b, 0x90, 0x85, 0x56, 0x6d, 0xaf, 0xd5, 0x2e, 0x88, - 0x12, 0x61, 0x7c, 0x76, 0x33, 0x6b, 0xc4, 0xf7, 0x31, 0x77, 0xe4, 0x02, 0xb7, 0x9e, 0x9c, 0x8c, - 0xbe, 0x04, 0x2e, 0x51, 0xa3, 0x04, 0x4c, 0xcd, 0xe2, 0x71, 0x5e, 0x36, 0xfb, 0xf1, 0x68, 0xf0, - 0xad, 0x37, 0x80, 0x98, 0x26, 0xc0, 0xef, 0x9b, 0x3c -}; - -static const unsigned char url_bag[] = -"" -" " -" signature" -" IIHLRC69w8K+iJQYKEh5U1wo/H2+U27lFzQlLrUWZIqBkd2rvUOcxBJlAG/5rCnq/mNwfhvrRZjpBzC9FzzH4a1mImPPGBYQtkD2pw/deJ67jPymyDlseH85grcDBgbRYaTR4+pbr4XTsMyQ1wEEF8OExKw9pNfHu1XyLg4iS3A=" -" certs" -" " -" MIIDOTCCAiGgAwIBAgIBATANBgkqhkiG9w0BAQQFADB+MRMwEQYDVQQKEwpBcHBsZSBJbmMuMRUwEwYDVQQLEwxpVHVuZXMgU3RvcmUxGjAYBgNVBAMTEWlUdW5lcyBTdG9yZSBSb290MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAGA1UEBxMJQ3VwZXJ0aW5vMB4XDTA3MTAwOTIxNTkxNFoXDTA4MTEwNzIxNTkxNFowgYExEzARBgNVBAoTCkFwcGxlIEluYy4xFTATBgNVBAsTDGlUdW5lcyBTdG9yZTEdMBsGA1UEAxMUaVR1bmVzIFN0b3JlIFVSTCBCYWcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlDdXBlcnRpbm8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOLMu/eV+eSLVEGtn536FkXAsi/vtpXdHpTNS9muEVlvlkubKXdPDd5jV5WnQpAKY4GZrBn8azP9UKBd85nhIb5nqHQHCmH5DpBK9GZPFpoIdXguJSre8pZwQaYEXQGtTt3nXvk9k8OHs5W/9xFLuD7fpkKSIl+0KLPFULdyEtlvAgMBAAGjQjBAMB0GA1UdDgQWBBTd4gDjfN3LFr3b5G8dvUTpC56JZTAfBgNVHSMEGDAWgBSw2uF/qItKaoFdDKGEVkYeau/lzzANBgkqhkiG9w0BAQQFAAOCAQEAIDpkK1CqTNyl7SEZWvUTRYPdZzn9Y4QjnbSQ6hFkF/PClJkXn3TzMW3ojnxNLphKZxOY53s6D/Hf1B5UX2bJDAnfQ/W8d10SPubGJ1FnUZK8KaKeOzAgks5ob9dnOUe4CZKhZ5FyggIJfgd38Q0s8WF474j5OA/5XRPczgjt+OiIfzEVX5Xqpm1TU7T4013eHze5umqAsd9fFxUXdTC+bl9xdj5VOmqUUfOivoiqiBK2/6XAaDIFF/PEnxVou+BpqkdsyTZz/HiQApve+7NONqS58ciq3Ov+wivpVJKxMyFgcXFWb/d2ZTc04i+fGf0OA4QmkSRcAZOxQkv0oggtTw==" -" " -" bag" -" PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlIENvbXB1dGVyLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPiAKCiAgPHBsaXN0IHZlcnNpb249IjEuMCI+CiAgICA8ZGljdD4KICAgICAgCiAgICAgIAogICAgICAKICAgICAgCiAgICAgICAgPGtleT5zdG9yZUZyb250PC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evc3RvcmVGcm9udDwvc3RyaW5nPgogICAgPGtleT5uZXdVc2VyU3RvcmVGcm9udDwva2V5PjxzdHJpbmc+aHR0cDovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9maXJzdExhdW5jaDwvc3RyaW5nPgogICAgPGtleT5uZXdJUG9kVXNlclN0b3JlRnJvbnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9uZXdJUG9kVXNlcj9uZXdJUG9kVXNlcj10cnVlPC9zdHJpbmc+CiAgICA8a2V5Pm5ld1Bob25lVXNlcjwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3Bob25lTGFuZGluZ1BhZ2U8L3N0cmluZz4gICAgICAgICAgICAgICAgICAKICAgIDxrZXk+c2VhcmNoPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTZWFyY2gud29hL3dhL3NlYXJjaDwvc3RyaW5nPgogICAgPGtleT5hZHZhbmNlZFNlYXJjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU2VhcmNoLndvYS93YS9hZHZhbmNlZFNlYXJjaDwvc3RyaW5nPgogICAgPGtleT5zZWFyY2hIaW50czwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU2VhcmNoSGludHMud29hL3dhL2hpbnRzPC9zdHJpbmc+CiAgICA8a2V5PnBhcmVudGFsQWR2aXNvcnk8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9wYXJlbnRhbEFkdmlzb3J5PC9zdHJpbmc+CiAgICA8a2V5PnNvbmdNZXRhRGF0YTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3NvbmdNZXRhRGF0YTwvc3RyaW5nPgogICAgPGtleT5icm93c2U8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9icm93c2U8L3N0cmluZz4KICAgIDxrZXk+YnJvd3NlU3RvcmU8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9icm93c2VTdG9yZTwvc3RyaW5nPgogICAgPGtleT5icm93c2VHZW5yZTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2Jyb3dzZUdlbnJlPC9zdHJpbmc+CiAgICA8a2V5PmJyb3dzZUFydGlzdDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2Jyb3dzZUFydGlzdDwvc3RyaW5nPgogICAgPGtleT5icm93c2VBbGJ1bTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2Jyb3dzZUFsYnVtPC9zdHJpbmc+CiAgICA8a2V5PnZpZXdBbGJ1bTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdBbGJ1bTwvc3RyaW5nPgogICAgPGtleT52aWV3QXJ0aXN0PC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0FydGlzdDwvc3RyaW5nPgogICAgPGtleT52aWV3Q29tcG9zZXI8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3Q29tcG9zZXI8L3N0cmluZz4KICAgIDxrZXk+dmlld0dlbnJlPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0dlbnJlPC9zdHJpbmc+CiAgICA8a2V5PnZpZXdQb2RjYXN0PC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1BvZGNhc3Q8L3N0cmluZz4KICAgIDxrZXk+dmlld1B1Ymxpc2hlZFBsYXlsaXN0PC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1B1Ymxpc2hlZFBsYXlsaXN0PC9zdHJpbmc+CiAgICA8a2V5PnZpZXdWaWRlbzwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdWaWRlbzwvc3RyaW5nPgogICAgPGtleT5wb2RjYXN0czwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdQb2RjYXN0RGlyZWN0b3J5PC9zdHJpbmc+CiAgICA8a2V5PmV4dGVybmFsVVJMU2VhcmNoS2V5PC9rZXk+PHN0cmluZz5heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQ8L3N0cmluZz4KICAgIDxrZXk+ZXh0ZXJuYWxVUkxSZXBsYWNlS2V5PC9rZXk+PHN0cmluZz5waG9ib3MuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8a2V5PnNlbGVjdGVkSXRlbXNQYWdlPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evc2VsZWN0ZWRJdGVtc1BhZ2U8L3N0cmluZz4KCiAgICAKCiAgICAKCiAgICA8a2V5Pm1pbmktc3RvcmU8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9taW5pc3RvcmVWMjwvc3RyaW5nPgogICAgPGtleT5taW5pLXN0b3JlLWZpZWxkczwva2V5PjxzdHJpbmc+YSxraW5kLHA8L3N0cmluZz4KICAgIDxrZXk+bWluaS1zdG9yZS1tYXRjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd2EvbWluaXN0b3JlTWF0Y2hWMjwvc3RyaW5nPgogICAgPGtleT5taW5pLXN0b3JlLW1hdGNoLWZpZWxkczwva2V5PjxzdHJpbmc+YW4sZ24sa2luZCxwbjwvc3RyaW5nPgogICAgPGtleT5taW5pLXN0b3JlLXdlbGNvbWU8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9taW5pc3RvcmVXZWxjb21lP3dpdGhDbGllbnRPcHRJbj0xPC9zdHJpbmc+CgogICAgPGtleT5jb3Zlci1hcnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlU2VydmljZXMud29hL3dhL2NvdmVyQXJ0TWF0Y2g8L3N0cmluZz4KICAgIDxrZXk+Y292ZXItYXJ0LWZpZWxkczwva2V5PjxzdHJpbmc+YSxwPC9zdHJpbmc+CiAgICA8a2V5PmNvdmVyLWFydC1jZC1maWVsZHM8L2tleT48c3RyaW5nPmNkZGI8L3N0cmluZz4KICAgIDxrZXk+Y292ZXItYXJ0LW1hdGNoPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9jb3ZlckFydE1hdGNoPC9zdHJpbmc+CiAgICA8a2V5PmNvdmVyLWFydC1tYXRjaC1maWVsZHM8L2tleT48c3RyaW5nPmNkZGIsYW4scG48L3N0cmluZz4KICAgIDxrZXk+Y292ZXItYXJ0LXVzZXI8L2tleT48c3RyaW5nPmh0dHA6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpQZXJzb25hbGl6ZXIud29hL3dhL2NvdmVyQXJ0VXNlcjwvc3RyaW5nPgoKICAgIDxrZXk+bWF0Y2hVUkxzPC9rZXk+PGFycmF5PjxzdHJpbmc+aHR0cDovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy88L3N0cmluZz48L2FycmF5PgoKICAgIAogICAgPGtleT5saWJyYXJ5LWxpbms8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlU2VydmljZXMud29hL3dhL2xpYnJhcnlMaW5rPC9zdHJpbmc+CiAgICAKICAgIDxrZXk+bGlicmFyeS1saW5rLWZpZWxkcy1saXN0PC9rZXk+CiAgICA8YXJyYXk+CiAgICAgIDxzdHJpbmc+YW4sY24sZ24sa2luZCxuLHBuPC9zdHJpbmc+CiAgICA8L2FycmF5PgogICAgCiAgICA8a2V5PmxpYnJhcnlMaW5rPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9saWJyYXJ5TGluazwvc3RyaW5nPgoKICAgIAogICAgPGtleT5hdmFpbGFibGUtcmluZ3RvbmVzPC9rZXk+PHN0cmluZz5odHRwOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aUGVyc29uYWxpemVyLndvYS93YS9hdmFpbGFibGVSaW5ndG9uZXM8L3N0cmluZz4KCiAgICAKICAgIDxrZXk+Y3JlYXRlLXJpbmd0b25lPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NyZWF0ZVJpbmd0b25lPC9zdHJpbmc+CiAgICA8a2V5PnJpbmd0b25lLWluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaXNSaW5ndG9uZWFibGU8L3N0cmluZz4KICAgIDxrZXk+cmluZ3RvbmUtaW5mby1maWVsZHMtbGlzdDwva2V5PgogICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+aWQscyxkc2lkPC9zdHJpbmc+CiAgICA8L2FycmF5PgogICAgCgoKICAgIDxrZXk+bWF4Q29tcHV0ZXJzPC9rZXk+PHN0cmluZz41PC9zdHJpbmc+CiAgICA8a2V5Pm1heFB1Ymxpc2hlZFBsYXlsaXN0SXRlbXM8L2tleT48aW50ZWdlcj4xMDA8L2ludGVnZXI+CiAgICAKICAgIDxrZXk+dHJ1c3RlZERvbWFpbnM8L2tleT4KICAgIDxhcnJheT4KICAgICAgPHN0cmluZz4uYXBwbGUuY29tPC9zdHJpbmc+CiAgICAgIDxzdHJpbmc+LmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0PC9zdHJpbmc+CiAgICAgIDxzdHJpbmc+c3VwcG9ydC5tYWMuY29tPC9zdHJpbmc+CiAgICAgIDxzdHJpbmc+Lml0dW5lcy5jb208L3N0cmluZz4KICAgICAgPHN0cmluZz5pdHVuZXMuY29tPC9zdHJpbmc+CiAgICA8L2FycmF5PgoKICAgIDxrZXk+cGx1cy1pbmZvPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvaVR1bmVzUGx1c0xlYXJuTW9yZVBhZ2U8L3N0cmluZz4KCiAgICA8a2V5PmFwcGxldHYteW91dHViZS1hdXRoLXVybDwva2V5PjxzdHJpbmc+aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS88L3N0cmluZz4KICAgIDxrZXk+YXBwbGV0di15b3V0dWJlLXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2dkYXRhLnlvdXR1YmUuY29tLzwvc3RyaW5nPgogICAgPGtleT5pdHVuZXMtcHJlc2VudHMtZGlyZWN0b3J5LXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd3MvUlNTL2RpcmVjdG9yeTwvc3RyaW5nPgogICAgPGtleT5HaG9zdHJpZGVyPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KCiAgICA8a2V5PnAyLXRvcC10ZW48L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VG9wVGVuc0xpc3Q8L3N0cmluZz4KICAgIDxrZXk+cDItc2VydmljZS10ZXJtcy11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly93d3cuYXBwbGUuY29tL3N1cHBvcnQvaXR1bmVzL2xlZ2FsL3Rlcm1zLmh0bWw8L3N0cmluZz4KCiAgICA8a2V5Pm5vdy1wbGF5aW5nLXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL25vd1BsYXlpbmc8L3N0cmluZz4KICAgIDxrZXk+bm93LXBsYXlpbmctbmV0d29yay1kZXRlY3QtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evbm93UGxheWluZzwvc3RyaW5nPgogICAgPGtleT5hZGFtaWQtbG9va3VwLXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2FkYW1JZExvb2t1cDwvc3RyaW5nPgoKICAgIAoKICAgIAoKICAgICAgICA8a2V5PmF1dGhlbnRpY2F0ZUFjY291bnQ8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYXV0aGVudGljYXRlPC9zdHJpbmc+CiAgICA8a2V5PmlQaG9uZUFjdGl2YXRpb248L2tleT48c3RyaW5nPmh0dHBzOi8vYWxiZXJ0LmFwcGxlLmNvbS9XZWJPYmplY3RzL0FMQWN0aXZhdGlvbi53b2Evd2EvaVBob25lUmVnaXN0cmF0aW9uPC9zdHJpbmc+CiAgICA8a2V5PmRldmljZS1hY3RpdmF0aW9uPC9rZXk+PHN0cmluZz5odHRwczovL2FsYmVydC5hcHBsZS5jb20vV2ViT2JqZWN0cy9BTEFjdGl2YXRpb24ud29hL3dhL2RldmljZUFjdGl2YXRpb248L3N0cmluZz4KICAgIDxrZXk+YXV0aG9yaXplTWFjaGluZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9hdXRob3JpemVNYWNoaW5lPC9zdHJpbmc+CiAgICA8a2V5PmJ1eVByb2R1Y3Q8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYnV5UHJvZHVjdDwvc3RyaW5nPgogICAgPGtleT5idXlDYXJ0PC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2J1eUNhcnQ8L3N0cmluZz4KICAgIDxrZXk+ZGVhdXRob3JpemVNYWNoaW5lPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2RlYXV0aG9yaXplTWFjaGluZTwvc3RyaW5nPgogICAgPGtleT5tYWNoaW5lQXV0aG9yaXphdGlvbkluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmFzdEZpbmFuY2Uud29hL3dhL21hY2hpbmVBdXRob3JpemF0aW9uSW5mbzwvc3RyaW5nPgogICAgPGtleT5tb2RpZnlBY2NvdW50PC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2FjY291bnRTdW1tYXJ5PC9zdHJpbmc+CiAgICA8a2V5PnBlbmRpbmdTb25nczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9wZW5kaW5nU29uZ3M8L3N0cmluZz4KICAgIDxrZXk+c2lnbnVwPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3NpZ251cFdpemFyZDwvc3RyaW5nPgogICAgPGtleT5zb25nRG93bmxvYWREb25lPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZhc3RGaW5hbmNlLndvYS93YS9zb25nRG93bmxvYWREb25lPC9zdHJpbmc+CiAgICA8a2V5PmZvcmdvdHRlblBhc3N3b3JkPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2lGb3Jnb3Q8L3N0cmluZz4KICAgIDxrZXk+bXlJbmZvPC9rZXk+PHN0cmluZz5odHRwczovL215aW5mby5hcHBsZS5jb20vPC9zdHJpbmc+CiAgICA8a2V5Pm5vQU9MQWNjb3VudHM8L2tleT48ZmFsc2UvPgogICAgPGtleT51cGxvYWRQdWJsaXNoZWRQbGF5bGlzdDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS91cGxvYWRQdWJsaXNoZWRQbGF5TGlzdDwvc3RyaW5nPgogICAgPGtleT5sb2dvdXQ8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvbG9nb3V0PC9zdHJpbmc+CiAgICA8a2V5PmFkZFRvQ2FydDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9hZGRUb0NhcnQ8L3N0cmluZz4KICAgIDxrZXk+cmVtb3ZlRnJvbUNhcnQ8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVtb3ZlRnJvbUNhcnQ8L3N0cmluZz4KICAgIDxrZXk+c2hvcHBpbmdDYXJ0PC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3Nob3BwaW5nQ2FydDwvc3RyaW5nPgogICAgPGtleT5iY1VSTHM8L2tleT48YXJyYXk+PHN0cmluZz5odHRwOi8vLnBob2Jvcy5hcHBsZS5jb208L3N0cmluZz48c3RyaW5nPmh0dHA6Ly93d3cuYXRkbXQuY29tPC9zdHJpbmc+PC9hcnJheT4KICAgIDxrZXk+dXBncmFkZVBob25lPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3VwZ3JhZGVQaG9uZTwvc3RyaW5nPgogICAgPGtleT51cGdyYWRlRHJtPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3VwZ3JhZGVEcm08L3N0cmluZz4KICAgIDxrZXk+cmVwb3J0UG9kY2FzdDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9yZXBvcnRQb2RjYXN0PC9zdHJpbmc+CiAgICA8a2V5PmdpZnRQbGF5bGlzdDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9naWZ0U29uZ3NXaXphcmQ8L3N0cmluZz4KICAgIDxrZXk+Z2l2ZS1wbGF5bGlzdDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9naWZ0U29uZ3NXaXphcmQ8L3N0cmluZz4KICAgIDxrZXk+Y2hlY2stZG93bmxvYWQtcXVldWU8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvY2hlY2tEb3dubG9hZFF1ZXVlPC9zdHJpbmc+CiAgICA8a2V5PnNldC1hdXRvLWRvd25sb2FkPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3NldEF1dG9Eb3dubG9hZDwvc3RyaW5nPgogICAgPGtleT5uZXctaXBvZC11c2VyPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2lQb2RSZWdpc3RyYXRpb248L3N0cmluZz4KICAgIDxrZXk+bmV3LXR2LXVzZXI8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaVRWUmVnaXN0cmF0aW9uPC9zdHJpbmc+CiAgICA8a2V5Pm1kNS1taXNtYXRjaDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9tZDVNaXNtYXRjaDwvc3RyaW5nPgogICAgPGtleT5yZXBvcnQtZXJyb3I8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVwb3J0RXJyb3JGcm9tQ2xpZW50PC9zdHJpbmc+CiAgICA8a2V5PnVwZGF0ZUFzc2V0PC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3VwZGF0ZUFzc2V0PC9zdHJpbmc+CiAgICA8a2V5PmNyZWF0ZS10b2tlbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jcmVhdGVUb2tlbjwvc3RyaW5nPgogICAgPGtleT5jcmVhdGUtc2Vzc2lvbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jcmVhdGVTZXNzaW9uPC9zdHJpbmc+CiAgICAKCiAgICAgIAogICAgICAKICAgIDwvZGljdD4KICA8L3BsaXN0PgoKCg==" -" " -""; - -/* Test basic add delete update copy matching stuff. */ -static void tests(void) -{ - SecTrustRef trust; - SecCertificateRef leaf, root; - SecPolicyRef policy; - CFDataRef urlBagData; - CFDictionaryRef urlBagDict; - - isnt(urlBagData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, url_bag, sizeof(url_bag), kCFAllocatorNull), NULL, - "load url bag"); - isnt(urlBagDict = CFPropertyListCreateWithData(kCFAllocatorDefault, urlBagData, kCFPropertyListImmutable, NULL, NULL), NULL, - "parse url bag"); - CFReleaseSafe(urlBagData); - CFArrayRef certs_data = CFDictionaryGetValue(urlBagDict, CFSTR("certs")); - CFDataRef cert_data = CFArrayGetValueAtIndex(certs_data, 0); - isnt(leaf = SecCertificateCreateWithData(kCFAllocatorDefault, cert_data), NULL, "create leaf"); - isnt(root = SecCertificateCreateWithBytes(kCFAllocatorDefault, sITunesStoreRootCertificate, sizeof(sITunesStoreRootCertificate)), NULL, "create root"); - - CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **)&leaf, 1, NULL); - CFDataRef signature = CFDictionaryGetValue(urlBagDict, CFSTR("signature")); - CFDataRef bag = CFDictionaryGetValue(urlBagDict, CFSTR("bag")); - unsigned char sha1_hash[CC_SHA1_DIGEST_LENGTH]; - CFDataRef sha1Data = NULL; - CCDigest(kCCDigestSHA1, CFDataGetBytePtr(bag), CFDataGetLength(bag), sha1_hash); - sha1Data = CFDataCreate(NULL, sha1_hash, sizeof(sha1_hash)); - - isnt(policy = SecPolicyCreateBasicX509(), NULL, "create policy instance"); - - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for leaf"); - - SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - TODO: { - todo("Only works in !NO_SERVER setup"); - is_status(trustResult, kSecTrustResultOtherError, - "trust is kSecTrustResultOtherError"); - } - SecKeyRef pub_key_leaf; - isnt(pub_key_leaf = SecTrustCopyPublicKey(trust), NULL, "get leaf pub key"); - if (!pub_key_leaf) { goto errOut; } - CFErrorRef error = NULL; - ok(SecKeyVerifySignature(pub_key_leaf, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, sha1Data, signature, &error), - "verify signature on bag"); - CFReleaseNull(error); - -errOut: - CFReleaseSafe(sha1Data); - CFReleaseSafe(pub_key_leaf); - CFReleaseSafe(urlBagDict); - CFReleaseSafe(certs); - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(leaf); - CFReleaseSafe(root); -} - -int si_21_sectrust_asr(int argc, char *const *argv) -{ - plan_tests(10); - - - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-22-sectrust-iap.c b/OSX/sec/Security/Regressions/secitem/si-22-sectrust-iap.c deleted file mode 100644 index 934d1161..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-22-sectrust-iap.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (c) 2006-2017 Apple Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -#include "si-22-sectrust-iap.h" - -static void test_v1(void) -{ - SecTrustRef trust; - SecCertificateRef iAP1CA, iAP2CA, leaf0, leaf1; - isnt(iAP1CA = SecCertificateCreateWithBytes(NULL, _iAP1CA, sizeof(_iAP1CA)), - NULL, "create iAP1CA"); - isnt(iAP2CA = SecCertificateCreateWithBytes(NULL, _iAP2CA, sizeof(_iAP2CA)), - NULL, "create iAP2CA"); - isnt(leaf0 = SecCertificateCreateWithBytes(NULL, _leaf0, sizeof(_leaf0)), - NULL, "create leaf0"); - isnt(leaf1 = SecCertificateCreateWithBytes(NULL, _leaf1, sizeof(_leaf1)), - NULL, "create leaf1"); - { - // temporarily grab some stack space and fill it with 0xFF; - // when we exit this scope, the stack pointer should shrink but leave the memory filled. - // this tests for a stack overflow bug inside SecPolicyCreateiAP (rdar://16056248) - char buf[2048]; - memset(buf, 0xFF, sizeof(buf)); - } - SecPolicyRef policy = SecPolicyCreateiAP(); - const void *v_anchors[] = { - iAP1CA, - iAP2CA - }; - CFArrayRef anchors = CFArrayCreate(NULL, v_anchors, - array_size(v_anchors), NULL); - CFArrayRef certs0 = CFArrayCreate(NULL, (const void **)&leaf0, 1, &kCFTypeArrayCallBacks); - CFArrayRef certs1 = CFArrayCreate(NULL, (const void **)&leaf1, 1, &kCFTypeArrayCallBacks); - ok_status(SecTrustCreateWithCertificates(certs0, policy, &trust), "create trust for leaf0"); - ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); - - /* Jan 1st 2008. */ - CFDateRef date = CFDateCreate(NULL, 220752000.0); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - - SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - - is(SecTrustGetCertificateCount(trust), 2, "cert count is 2"); - - CFReleaseSafe(trust); - ok_status(SecTrustCreateWithCertificates(certs1, policy, &trust), "create trust for leaf1"); - ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); - - CFReleaseSafe(anchors); - CFReleaseSafe(certs1); - CFReleaseSafe(certs0); - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(leaf0); - CFReleaseSafe(leaf1); - CFReleaseSafe(iAP1CA); - CFReleaseSafe(iAP2CA); - CFReleaseSafe(date); -} - -static void test_v3(void) { - SecCertificateRef v3CA = NULL, v3leaf = NULL; - isnt(v3CA = SecCertificateCreateWithBytes(NULL, _v3ca, sizeof(_v3ca)), - NULL, "create v3 CA"); - isnt(v3leaf = SecCertificateCreateWithBytes(NULL, _v3leaf, sizeof(_v3leaf)), - NULL, "create v3leaf"); - - /* Test v3 certs meet iAP policy */ - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFArrayRef certs = NULL, anchors = NULL; - CFDateRef date = NULL; - SecTrustResultType trustResult; - - certs = CFArrayCreate(NULL, (const void **)&v3leaf, 1, &kCFTypeArrayCallBacks); - anchors = CFArrayCreate(NULL, (const void **)&v3CA, 1, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateiAP(); - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust ref"); - ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchor"); - ok(date = CFDateCreate(NULL, 484000000.0), "create date"); /* 3 May 2016 */ - if (!date) { goto trustFail; } - ok_status(SecTrustSetVerifyDate(trust, date), "set verify date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate"); - is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); - - /* Test v3 certs fail iAP SW Auth policy */ - CFReleaseNull(policy); - CFReleaseNull(trust); - policy = SecPolicyCreateiAPSWAuth(); - require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); - require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); - require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); - require_noerr(SecTrustEvaluate(trust, &trustResult), trustFail); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); - -trustFail: - CFReleaseSafe(policy); - CFReleaseSafe(trust); - CFReleaseSafe(certs); - CFReleaseSafe(anchors); - CFReleaseSafe(date); - - /* Test interface for determining iAuth version */ - SecCertificateRef leaf0 = NULL, leaf1 = NULL; - isnt(leaf0 = SecCertificateCreateWithBytes(NULL, _leaf0, sizeof(_leaf0)), - NULL, "create leaf0"); - isnt(leaf1 = SecCertificateCreateWithBytes(NULL, _leaf1, sizeof(_leaf1)), - NULL, "create leaf1"); - - is_status(SecCertificateGetiAuthVersion(leaf0), kSeciAuthVersion2, "v2 certificate"); - is_status(SecCertificateGetiAuthVersion(leaf1), kSeciAuthVersion2, "v2 certificate"); - is_status(SecCertificateGetiAuthVersion(v3leaf), kSeciAuthVersion3, "v3 certificate"); - - CFReleaseSafe(leaf0); - CFReleaseSafe(leaf1); - - /* Test the extension-copying interface */ - CFDataRef extensionData = NULL; - uint8_t extensionValue[32] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A, - }; - ok(extensionData = SecCertificateCopyiAPAuthCapabilities(v3leaf), - "copy iAuthv3 extension data"); - is(CFDataGetLength(extensionData), 32, "compare expected size"); - is(memcmp(extensionValue, CFDataGetBytePtr(extensionData), 32), 0, - "compare expected output"); - CFReleaseNull(extensionData); - - /* Test extension-copying interface with a malformed extension. */ - uint8_t extensionValue2[32] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, - }; - SecCertificateRef malformedV3leaf = NULL; - isnt(malformedV3leaf = SecCertificateCreateWithBytes(NULL, _malformedV3Leaf, sizeof(_malformedV3Leaf)), - NULL, "create malformed v3 leaf"); - ok(extensionData = SecCertificateCopyiAPAuthCapabilities(malformedV3leaf), - "copy iAuthv3 extension data for malformed leaf"); - is(CFDataGetLength(extensionData), 32, "compare expected size"); - is(memcmp(extensionValue2, CFDataGetBytePtr(extensionData), 32), 0, - "compare expected output"); - CFReleaseNull(extensionData); - CFReleaseNull(malformedV3leaf); - CFReleaseSafe(v3leaf); - CFReleaseSafe(v3CA); -} - -static void test_sw_auth_trust(void) { - SecCertificateRef sw_auth_test_CA = NULL, sw_auth_test_leaf = NULL; - isnt(sw_auth_test_CA = SecCertificateCreateWithBytes(NULL, _iAPSWAuthTestRoot, sizeof(_iAPSWAuthTestRoot)), - NULL, "create sw auth test ca"); - isnt(sw_auth_test_leaf = SecCertificateCreateWithBytes(NULL, _iAPSWAuth_leaf, sizeof(_iAPSWAuth_leaf)), - NULL, "create sw auth leaf"); - - /* Test SW Auth certs meet iAP SW Auth policy */ - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFArrayRef certs = NULL, anchors = NULL; - CFDateRef date = NULL; - SecTrustResultType trustResult; - - certs = CFArrayCreate(NULL, (const void **)&sw_auth_test_leaf, 1, &kCFTypeArrayCallBacks); - anchors = CFArrayCreate(NULL, (const void **)&sw_auth_test_CA, 1, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateiAPSWAuth(); - require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); - require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); - require(date = CFDateCreate(NULL, 530000000.0), trustFail); /* 17 Oct 2017, BEFORE issuance */ - require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); - require_noerr(SecTrustEvaluate(trust, &trustResult), trustFail); - is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); - - /* Test SW Auth certs fail iAP policy */ - CFReleaseNull(policy); - CFReleaseNull(trust); - policy = SecPolicyCreateiAP(); - require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); - require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); - require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); - require_noerr(SecTrustEvaluate(trust, &trustResult), trustFail); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); - - /* Test SW Auth certs fail when not-yet-valid with expiration check */ - CFReleaseNull(policy); - CFReleaseNull(trust); - policy = SecPolicyCreateiAPSWAuthWithExpiration(true); - require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); - require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); - require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); - require_noerr(SecTrustEvaluate(trust, &trustResult), trustFail); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); - -trustFail: - CFReleaseSafe(policy); - CFReleaseSafe(trust); - CFReleaseSafe(certs); - CFReleaseSafe(anchors); - CFReleaseSafe(date); - CFReleaseSafe(sw_auth_test_CA); - CFReleaseSafe(sw_auth_test_leaf); -} - -static void test_sw_auth_cert(void) { - SecCertificateRef good_leaf = NULL, bad_leaf = NULL; - isnt(good_leaf = SecCertificateCreateWithBytes(NULL, _iAPSWAuth_leaf, sizeof(_iAPSWAuth_leaf)), - NULL, "create good iAP SW Auth cert"); - isnt(bad_leaf = SecCertificateCreateWithBytes(NULL, _malformed_iAPSWAuth_leaf, sizeof(_malformed_iAPSWAuth_leaf)), - NULL, "create bad iAP SW Auth cert"); - - /* Test Auth version interface */ - ok(SecCertificateGetiAuthVersion(good_leaf) == kSeciAuthVersionSW, "Get version of well-formed SW Auth cert"); - ok(SecCertificateGetiAuthVersion(bad_leaf) == kSeciAuthVersionSW, "Get version of malformed SW Auth cert"); - - /* Test extension copying with malformed extensions */ - is(SecCertificateCopyiAPSWAuthCapabilities(bad_leaf, kSeciAPSWAuthGeneralCapabilities), NULL, - "Fail to get capabilities of malformed SW auth cert"); - is(SecCertificateCopyiAPSWAuthCapabilities(bad_leaf, kSeciAPSWAuthAirPlayCapabilities), NULL, - "Fail to get AirPlay capabilities of malformed SW auth cert"); - is(SecCertificateCopyiAPSWAuthCapabilities(bad_leaf, kSeciAPSWAuthHomeKitCapabilities), NULL, - "Fail to get HomeKit capabilities of malformed SW auth cert"); - - uint8_t byte0 = 0x00; - uint8_t byte1 = 0x01; - CFDataRef data0 = CFDataCreate(NULL, &byte0, 1); - CFDataRef data1 = CFDataCreate(NULL, &byte1, 1); - - /* Test extension copying with well-formed extensions */ - CFDataRef extensionValue = NULL; - isnt(extensionValue = SecCertificateCopyiAPSWAuthCapabilities(good_leaf, kSeciAPSWAuthGeneralCapabilities), NULL, - "Get capabilities of well-formed SW auth cert"); - ok(CFEqual(extensionValue, data1), "Got correct general extension value"); - CFReleaseNull(extensionValue); - - isnt(extensionValue = SecCertificateCopyiAPSWAuthCapabilities(good_leaf, kSeciAPSWAuthAirPlayCapabilities), NULL, - "Get AirPlay capabilities of well-formed SW auth cert"); - ok(CFEqual(extensionValue, data0), "Got correct AirPlay extension value"); - CFReleaseNull(extensionValue); - - isnt(extensionValue = SecCertificateCopyiAPSWAuthCapabilities(good_leaf, kSeciAPSWAuthHomeKitCapabilities), NULL, - "Get capabilities of well-formed SW auth cert"); - ok(CFEqual(extensionValue, data1), "Got correct HomeKit extension value"); - CFReleaseNull(extensionValue); - - CFReleaseNull(good_leaf); - CFReleaseNull(bad_leaf); - CFReleaseNull(data0); - CFReleaseNull(data1); -} - -static void test_component_type_cert(void) { - SecCertificateRef batteryCA = NULL, nonComponent = NULL; - isnt(batteryCA = SecCertificateCreateWithBytes(NULL, _componentCABattery, sizeof(_componentCABattery)), - NULL, "create battery component CA cert"); - isnt(nonComponent = SecCertificateCreateWithBytes(NULL, _iAP2CA, sizeof(_iAP2CA)), - NULL, "create non-component cert"); - - CFStringRef componentType = NULL; - isnt(componentType = SecCertificateCopyComponentType(batteryCA), NULL, "Get component type"); - ok(CFEqual(componentType, CFSTR("Battery")), "Got correct component type"); - CFReleaseNull(componentType); - - is(componentType = SecCertificateCopyComponentType(nonComponent), NULL, "Get component type"); - - CFReleaseNull(batteryCA); - CFReleaseNull(nonComponent); -} - -static void test_component_type_trust(void) { - SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFMutableArrayRef certs = NULL; - CFArrayRef anchors = NULL; - CFDateRef date = NULL; - SecTrustResultType trustResult; - - isnt(leaf = SecCertificateCreateWithBytes(NULL, _batteryLeaf, sizeof(_batteryLeaf)), - NULL, "create battery leaf"); - isnt(subCA = SecCertificateCreateWithBytes(NULL, _componentCABattery, sizeof(_componentCABattery)), - NULL, "create battery subCA"); - isnt(root = SecCertificateCreateWithBytes(NULL, _componentRoot, sizeof(_componentRoot)), - NULL, "create component root"); - - /* Test Battery component certs meet component policy */ - certs = CFArrayCreateMutable(NULL, 2, &kCFTypeArrayCallBacks); - CFArrayAppendValue(certs, leaf); - CFArrayAppendValue(certs, subCA); - anchors = CFArrayCreate(NULL, (const void **)&root, 1, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateAppleComponentCertificate(NULL); - require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); - require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); - require(date = CFDateCreate(NULL, 576000000.0), trustFail); /* April 3, 2019 at 9:00:00 AM PDT */ - require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); - require_noerr(SecTrustEvaluate(trust, &trustResult), trustFail); - is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); - -trustFail: - CFReleaseNull(leaf); - CFReleaseNull(subCA); - CFReleaseNull(root); - CFReleaseNull(date); - CFReleaseNull(policy); - CFReleaseNull(trust); -} - - -int si_22_sectrust_iap(int argc, char *const *argv) -{ - plan_tests(14+21+5+13+5+4); - - test_v1(); - test_v3(); - test_sw_auth_trust(); - test_sw_auth_cert(); - test_component_type_cert(); - test_component_type_trust(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-22-sectrust-iap.h b/OSX/sec/Security/Regressions/secitem/si-22-sectrust-iap.h deleted file mode 100644 index 1589d431..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-22-sectrust-iap.h +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright (c) 2007-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _SECURITY_SI_22_SECTRUST_IAP_H_ -#define _SECURITY_SI_22_SECTRUST_IAP_H_ - -/* - subject= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple iPod Accessories Certification Authority - issuer= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA - serial=16 - */ -const uint8_t _iAP1CA[] = { - 0x30, 0x82, 0x04, 0x3F, 0x30, 0x82, 0x03, 0x27, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x0D, - 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x86, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, - 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x14, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, - 0x43, 0x6F, 0x6D, 0x70, 0x75, 0x74, 0x65, 0x72, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x2D, - 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x24, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x43, - 0x6F, 0x6D, 0x70, 0x75, 0x74, 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x29, 0x30, - 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x52, 0x6F, - 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x36, 0x30, 0x35, - 0x31, 0x32, 0x32, 0x30, 0x35, 0x33, 0x30, 0x39, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x35, 0x31, - 0x32, 0x32, 0x30, 0x35, 0x33, 0x30, 0x39, 0x5A, 0x30, 0x81, 0x92, 0x31, 0x0B, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, - 0x0A, 0x13, 0x14, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x75, 0x74, 0x65, - 0x72, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, - 0x13, 0x24, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x75, 0x74, 0x65, 0x72, - 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, - 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x2C, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x69, 0x50, 0x6F, 0x64, 0x20, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x6F, 0x72, 0x69, 0x65, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, - 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, - 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9F, 0x2B, - 0x5A, 0x43, 0x27, 0x3A, 0x1B, 0x7E, 0xC4, 0xB8, 0x4A, 0x36, 0x45, 0x0E, 0x61, 0x4F, 0xA4, 0x51, - 0xD7, 0x9F, 0xCD, 0x22, 0x63, 0x09, 0x86, 0x50, 0xAE, 0xB2, 0xD6, 0x49, 0xEF, 0xE6, 0xBF, 0x2E, - 0xD7, 0x4D, 0x56, 0x03, 0xF5, 0x4F, 0x39, 0x26, 0x86, 0xF5, 0xF2, 0xD9, 0xB3, 0xDF, 0x11, 0x57, - 0x93, 0x51, 0xB7, 0x3A, 0x06, 0x63, 0xCD, 0x9B, 0x99, 0x37, 0xB9, 0x69, 0x8D, 0x03, 0x7F, 0xDE, - 0xA3, 0xB8, 0x38, 0x69, 0xF4, 0x41, 0x04, 0x40, 0xEB, 0x2F, 0x95, 0xEC, 0x1B, 0x21, 0x25, 0xE9, - 0x6A, 0xBB, 0x2E, 0x88, 0xB6, 0x0F, 0x20, 0x89, 0xF4, 0x13, 0x39, 0x3E, 0x29, 0x17, 0x69, 0xC8, - 0x6B, 0xBC, 0xF3, 0xE7, 0xDA, 0x65, 0x9C, 0xF9, 0x9E, 0x34, 0x0B, 0xE6, 0x60, 0x28, 0xFB, 0x80, - 0x80, 0x0C, 0x6A, 0x5E, 0xDA, 0x1D, 0x8D, 0x38, 0xE6, 0xD4, 0x61, 0xD5, 0x66, 0x82, 0x7C, 0x3E, - 0xF8, 0x30, 0xA6, 0xE1, 0xAA, 0x1E, 0xB0, 0xA0, 0x1E, 0x77, 0xD7, 0xA7, 0xED, 0x97, 0x9E, 0xA3, - 0xFD, 0x6F, 0xA1, 0x68, 0xBB, 0xC5, 0x89, 0x75, 0xE3, 0x65, 0x43, 0x67, 0x4E, 0x11, 0x77, 0x40, - 0x5F, 0xA1, 0x48, 0x3F, 0x9E, 0x23, 0xB0, 0x0F, 0x45, 0x68, 0x52, 0x0B, 0x8A, 0x73, 0x2B, 0x01, - 0x35, 0x2B, 0xAC, 0xFA, 0x9B, 0x1B, 0x9B, 0xA2, 0x46, 0xAE, 0x78, 0x05, 0xE8, 0xAC, 0xB7, 0xB4, - 0x01, 0xD0, 0x3D, 0x5A, 0x76, 0x4F, 0x8D, 0x89, 0x94, 0x61, 0x9D, 0xBC, 0xA0, 0xD6, 0xF9, 0x48, - 0xF1, 0x0F, 0xF9, 0x89, 0x4A, 0xCD, 0xAB, 0x53, 0x86, 0x4D, 0x4E, 0xF4, 0x35, 0x8B, 0x57, 0x64, - 0x5A, 0x5F, 0x52, 0xD3, 0xF7, 0x1F, 0x17, 0xC0, 0xA2, 0x8C, 0x21, 0x69, 0x4A, 0x2B, 0x30, 0x3F, - 0x0F, 0x37, 0x56, 0xE8, 0xE3, 0x6E, 0x5C, 0xEA, 0x98, 0x71, 0x12, 0xF0, 0x28, 0xAD, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xA3, 0x81, 0xA9, 0x30, 0x81, 0xA6, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, - 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, - 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, - 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC9, 0xAA, 0x84, 0x6B, 0x06, 0xB8, 0x76, 0xE2, 0x96, 0x4F, 0xE7, - 0x27, 0x02, 0xD7, 0x2E, 0x3B, 0xDA, 0xF7, 0xB0, 0x18, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x2B, 0xD0, 0x69, 0x47, 0x94, 0x76, 0x09, 0xFE, 0xF4, 0x6B, - 0x8D, 0x2E, 0x40, 0xA6, 0xF7, 0x47, 0x4D, 0x7F, 0x08, 0x5E, 0x30, 0x43, 0x06, 0x03, 0x55, 0x1D, - 0x1F, 0x04, 0x3C, 0x30, 0x3A, 0x30, 0x38, 0xA0, 0x36, 0xA0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, - 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x61, 0x70, 0x70, 0x6C, 0x65, 0x2E, 0x63, 0x6F, - 0x6D, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x61, 0x75, 0x74, - 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x2F, 0x72, 0x6F, 0x6F, 0x74, 0x2E, 0x63, 0x72, 0x6C, 0x30, - 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x01, 0x00, 0xC5, 0x74, 0x7A, 0x7E, 0x5C, 0x75, 0x0E, 0xD3, 0x8A, 0x1C, 0x8D, 0x26, 0x20, - 0xDF, 0x1F, 0xC3, 0x04, 0x0E, 0x81, 0x1E, 0xE2, 0x13, 0x85, 0xB7, 0x64, 0xE3, 0x97, 0x5D, 0x46, - 0x27, 0x1D, 0x08, 0x98, 0x77, 0xA5, 0xC3, 0x9F, 0x63, 0x84, 0xD1, 0x66, 0x4F, 0x0A, 0xE8, 0x13, - 0xF6, 0xE5, 0x94, 0x07, 0xB0, 0x06, 0xC5, 0x56, 0xEB, 0x04, 0x4B, 0xD2, 0xD0, 0x1D, 0xB4, 0xE1, - 0xB6, 0x2D, 0x30, 0x8C, 0x61, 0xCE, 0xC2, 0x54, 0xC5, 0xAD, 0xE2, 0x43, 0x33, 0x1F, 0x23, 0x21, - 0xCB, 0xBD, 0xFD, 0x35, 0x7F, 0x5F, 0xEC, 0x31, 0x0D, 0x03, 0xA6, 0x39, 0x28, 0x55, 0xBC, 0x23, - 0x78, 0xB4, 0x03, 0xF8, 0x24, 0xEB, 0x0D, 0x24, 0xB7, 0xAA, 0x3A, 0xCB, 0x7C, 0x02, 0x8F, 0xD5, - 0x86, 0x96, 0xA3, 0xE7, 0x8A, 0xF4, 0x8F, 0x84, 0xF7, 0x57, 0xF7, 0x8C, 0xA0, 0xF5, 0xAE, 0x9F, - 0x8F, 0x31, 0x62, 0x4F, 0xA7, 0xB3, 0x5E, 0x4B, 0xC3, 0x20, 0xA3, 0x40, 0xFA, 0xED, 0x13, 0x70, - 0x77, 0xAB, 0x59, 0x65, 0x89, 0x6B, 0xFD, 0xA9, 0x92, 0x9B, 0xFB, 0x54, 0xB1, 0x25, 0x37, 0xE0, - 0x7C, 0x49, 0x8F, 0x86, 0x3C, 0x99, 0xF4, 0x17, 0x11, 0x3D, 0x2E, 0x41, 0x7D, 0x00, 0x98, 0xB4, - 0x1A, 0xA4, 0xEC, 0x5F, 0xE7, 0xC6, 0xC9, 0xE8, 0x90, 0x01, 0x2F, 0xB5, 0xF3, 0x4C, 0x6E, 0x4F, - 0x36, 0xBC, 0x7D, 0xCF, 0x56, 0x6C, 0x9B, 0xEB, 0xEB, 0x8B, 0xCE, 0x02, 0xE1, 0x82, 0xA0, 0x00, - 0x0A, 0x10, 0x33, 0x06, 0xEB, 0xD5, 0x5E, 0xC3, 0x62, 0xE2, 0xBA, 0xF5, 0x25, 0x7D, 0xFC, 0xDA, - 0xE1, 0x49, 0x3D, 0x9F, 0xE9, 0x9F, 0x12, 0xDA, 0xF9, 0x7D, 0x22, 0x7C, 0x8F, 0x13, 0xCA, 0x06, - 0x34, 0xD7, 0x4C, 0xF6, 0x40, 0x71, 0x78, 0xB1, 0xAF, 0xEC, 0xC1, 0x66, 0xDF, 0xAE, 0xAD, 0x3B, - 0xCC, 0x0E, 0xC0 -}; - -/* - subject= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple iPod Accessories Certification Authority - issuer= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA - serial=16 - */ -const uint8_t _iAP2CA[] = { - 0x30, 0x82, 0x03, 0xfe, 0x30, 0x82, 0x02, 0xe6, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x16, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x16, 0x30, 0x14, 0x06, - 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, - 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x32, 0x31, 0x34, 0x32, 0x32, 0x31, - 0x38, 0x30, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x32, 0x31, 0x34, 0x32, 0x32, 0x31, 0x38, - 0x30, 0x38, 0x5a, 0x30, 0x81, 0x83, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, - 0x0b, 0x13, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x65, - 0x20, 0x69, 0x50, 0x6f, 0x64, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x69, 0x65, - 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, - 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa1, 0xf6, 0xca, 0xdb, 0x3d, 0x4a, - 0x5a, 0x3e, 0xef, 0x74, 0x78, 0xf1, 0xb7, 0xb0, 0x32, 0x82, 0x1f, 0x90, 0xc6, 0x08, 0xdf, 0xaa, - 0x3b, 0xd2, 0xcb, 0x0f, 0xe6, 0x37, 0x13, 0xf8, 0xff, 0x71, 0xfc, 0x28, 0x86, 0x24, 0x36, 0x85, - 0x3f, 0xd0, 0x1d, 0x9c, 0xd0, 0x9c, 0xb2, 0x5d, 0x20, 0x41, 0xdc, 0xb0, 0xd8, 0xa8, 0x86, 0x3c, - 0x42, 0x3c, 0xbe, 0x5a, 0x48, 0xdf, 0x34, 0x74, 0x9a, 0x61, 0x05, 0x0d, 0xce, 0xc8, 0x25, 0x14, - 0xc8, 0x0a, 0xcd, 0xbd, 0xba, 0x12, 0x1b, 0x3b, 0x41, 0x13, 0x8e, 0x38, 0x65, 0x1d, 0xac, 0x1d, - 0xd5, 0x38, 0x95, 0x9d, 0x3a, 0xd0, 0x79, 0x5c, 0x66, 0x9c, 0x47, 0x4b, 0x2c, 0xb8, 0x44, 0x3b, - 0x7e, 0x8b, 0x68, 0x39, 0x3e, 0x46, 0xc1, 0xb8, 0xc0, 0x85, 0xd6, 0x84, 0xfb, 0x0e, 0xa6, 0xdd, - 0x34, 0x06, 0xda, 0x1c, 0x78, 0xd9, 0xc4, 0x63, 0x11, 0x1b, 0xcf, 0x20, 0x15, 0xd2, 0x7a, 0xef, - 0x60, 0x40, 0xdf, 0xba, 0xe0, 0x05, 0x45, 0x41, 0x82, 0x0e, 0x9b, 0x78, 0x2d, 0x2a, 0xb4, 0x94, - 0xb5, 0xca, 0x79, 0xcd, 0xdb, 0xb5, 0x95, 0x02, 0xbe, 0x55, 0x2c, 0x36, 0x21, 0xaf, 0x6e, 0x39, - 0xb6, 0x76, 0x5a, 0xec, 0x5d, 0x6a, 0xf3, 0xcc, 0xfa, 0x90, 0x8a, 0x15, 0x77, 0xbb, 0xba, 0x5c, - 0x2b, 0xa1, 0x87, 0xf8, 0x0e, 0x70, 0x5d, 0x23, 0x01, 0x08, 0x79, 0xef, 0xab, 0xd7, 0x91, 0x38, - 0x81, 0x35, 0xb3, 0x07, 0xd4, 0x79, 0xa2, 0x25, 0xa7, 0xf7, 0x90, 0x75, 0xeb, 0xeb, 0x71, 0xa2, - 0xd0, 0xc1, 0xab, 0x02, 0x06, 0xf9, 0x07, 0x08, 0x97, 0x35, 0xda, 0x7e, 0x4d, 0x61, 0x51, 0x75, - 0x92, 0xf6, 0x19, 0xf5, 0xdf, 0xfb, 0xc9, 0xa5, 0x4e, 0x9b, 0x8a, 0x14, 0x11, 0x4c, 0x10, 0x74, - 0x83, 0xaf, 0x2f, 0xfc, 0xb6, 0xd6, 0x6b, 0x57, 0x46, 0x1d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, - 0x81, 0x9c, 0x30, 0x81, 0x99, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, - 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, - 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0xff, 0x4b, 0x1a, 0x43, 0x9a, 0xf5, 0x19, 0x96, 0xab, 0x18, 0x00, 0x2b, 0x61, 0xc9, 0xee, - 0x40, 0x9d, 0x8e, 0xc7, 0x04, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, - 0x80, 0x14, 0x2b, 0xd0, 0x69, 0x47, 0x94, 0x76, 0x09, 0xfe, 0xf4, 0x6b, 0x8d, 0x2e, 0x40, 0xa6, - 0xf7, 0x47, 0x4d, 0x7f, 0x08, 0x5e, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, - 0x2d, 0x30, 0x2b, 0xa0, 0x29, 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, - 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x01, 0x00, 0x9e, 0xb4, 0xaf, 0x3d, 0xb7, 0x61, 0xe0, 0x64, 0xc3, 0x86, 0x27, 0xd2, 0x3f, 0xe9, - 0xe4, 0x08, 0x50, 0x77, 0xa2, 0x81, 0x09, 0x8c, 0x7d, 0xb7, 0xd0, 0x54, 0x52, 0xde, 0xfe, 0x8d, - 0x48, 0xf2, 0x86, 0xc1, 0x17, 0xe5, 0x1a, 0x5d, 0x29, 0x20, 0xd3, 0x81, 0xca, 0xee, 0xc8, 0xa3, - 0x61, 0xb3, 0x90, 0x9f, 0x73, 0xe8, 0xe3, 0xc8, 0xbc, 0xa7, 0x12, 0xb4, 0x8c, 0x2d, 0xaa, 0xf5, - 0x39, 0x27, 0x19, 0xf5, 0xfb, 0xf9, 0x14, 0x7b, 0x3a, 0xb4, 0x78, 0x1a, 0x9a, 0x4c, 0x96, 0xeb, - 0x36, 0xc7, 0xfe, 0xb5, 0xe7, 0x14, 0x7e, 0x6c, 0x4f, 0xa8, 0x22, 0xba, 0x23, 0x82, 0xf0, 0xce, - 0xfa, 0x09, 0x7b, 0x8a, 0x0d, 0x5a, 0x61, 0x21, 0x74, 0x7a, 0xca, 0xc2, 0xca, 0x6b, 0xc2, 0x63, - 0x40, 0x77, 0x23, 0x2b, 0x8f, 0xa0, 0x29, 0x5c, 0xeb, 0xad, 0xfc, 0xcc, 0xdc, 0x5a, 0x42, 0x42, - 0x2e, 0xc8, 0x4f, 0xb4, 0x90, 0xd2, 0x6e, 0xfc, 0x4f, 0x8a, 0x0e, 0xa8, 0xb7, 0x83, 0x5c, 0x5c, - 0x12, 0x02, 0x15, 0x17, 0xa8, 0x65, 0x7d, 0x5a, 0x28, 0x2b, 0x69, 0x5f, 0x76, 0x9e, 0x2f, 0xe0, - 0x9e, 0xec, 0x41, 0x57, 0x97, 0xc5, 0x0f, 0x9a, 0xa0, 0x70, 0xb8, 0x2c, 0x8f, 0x6d, 0x80, 0xb5, - 0x46, 0xec, 0xe8, 0x58, 0xb0, 0x04, 0x40, 0x3c, 0xc3, 0x62, 0x8a, 0x0a, 0xb7, 0xa9, 0x5b, 0x58, - 0x7d, 0xea, 0x7b, 0x8c, 0xff, 0xf7, 0xf8, 0xbf, 0xd2, 0xc1, 0x95, 0x76, 0x05, 0xd7, 0x5d, 0x16, - 0x4d, 0xf1, 0x1e, 0x7d, 0xb2, 0x81, 0x10, 0xe8, 0x47, 0x74, 0x12, 0xf1, 0xe6, 0x60, 0x3f, 0xe3, - 0x6f, 0xb6, 0xa4, 0xc6, 0xe1, 0x08, 0xb3, 0xe4, 0x7d, 0x98, 0xf1, 0xfb, 0xd0, 0x42, 0xb2, 0x59, - 0x26, 0x17, 0xfb, 0x72, 0x6b, 0x05, 0xa9, 0xac, 0x94, 0xbf, 0x88, 0x0a, 0x09, 0xef, 0xd2, 0xa5, - 0x25, 0xae -}; - -/* - subject= /C=US/O=Apple Inc./OU=Apple iPod Accessories/CN=IPA_3333AA070313AA06AA0007AA000001 - issuer= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple iPod Accessories Certification Authority - serial=3333AA070313AA06AA0007AA000001 - */ -const uint8_t _leaf0[] = { - 0x30,0x82,0x03,0x59,0x30,0x82,0x02,0x41,0xA0,0x03,0x02,0x01,0x02,0x02,0x0F,0x33, - 0x33,0xAA,0x07,0x03,0x13,0xAA,0x06,0xAA,0x00,0x07,0xAA,0x00,0x00,0x01,0x30,0x0D, - 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x83, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30, - 0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E, - 0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70, - 0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, - 0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x37,0x30,0x35,0x06,0x03, - 0x55,0x04,0x03,0x13,0x2E,0x41,0x70,0x70,0x6C,0x65,0x20,0x69,0x50,0x6F,0x64,0x20, - 0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72,0x74, - 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72, - 0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x30,0x37,0x30,0x33,0x31,0x33,0x32,0x31,0x31, - 0x37,0x32,0x36,0x5A,0x17,0x0D,0x31,0x35,0x30,0x33,0x31,0x33,0x32,0x31,0x31,0x37, - 0x32,0x36,0x5A,0x30,0x70,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, - 0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70, - 0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x0B, - 0x13,0x16,0x41,0x70,0x70,0x6C,0x65,0x20,0x69,0x50,0x6F,0x64,0x20,0x41,0x63,0x63, - 0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x31,0x2B,0x30,0x29,0x06,0x03,0x55,0x04, - 0x03,0x14,0x22,0x49,0x50,0x41,0x5F,0x33,0x33,0x33,0x33,0x41,0x41,0x30,0x37,0x30, - 0x33,0x31,0x33,0x41,0x41,0x30,0x36,0x41,0x41,0x30,0x30,0x30,0x37,0x41,0x41,0x30, - 0x30,0x30,0x30,0x30,0x31,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81,0x89,0x02,0x81, - 0x81,0x00,0xCB,0x76,0xE3,0xA7,0x3B,0xF0,0x42,0xD5,0x48,0x93,0x62,0x0A,0x10,0x17, - 0x37,0xB9,0xC8,0x52,0xDD,0xDE,0x8A,0x40,0xA0,0xF8,0xDA,0xE8,0x64,0x0A,0x67,0xF5, - 0x8F,0x91,0xA6,0xB5,0x93,0xE8,0xC2,0x28,0xB3,0xAC,0xF4,0xAF,0x40,0xC6,0xBB,0x49, - 0x85,0x5A,0x7C,0x1B,0x42,0xC3,0x3C,0xC8,0x95,0x36,0x0B,0x85,0xBE,0x36,0x85,0xB7, - 0x0D,0x04,0x0E,0x4E,0x4C,0x3C,0x28,0xFB,0x03,0x78,0x42,0xAC,0xF1,0x9E,0xAD,0x22, - 0x7C,0x86,0xD3,0xA6,0x0E,0xC8,0x42,0xBD,0x9C,0x7C,0xD9,0x2C,0xE4,0x1F,0xD5,0x91, - 0x4E,0x9D,0xB7,0xFF,0x83,0x2E,0x06,0x3E,0xD4,0x95,0xE4,0x0E,0x8E,0x2D,0x46,0x8F, - 0xCF,0xE6,0x32,0xCE,0x47,0x56,0x57,0x97,0x1A,0x87,0xC8,0xD4,0xF3,0x32,0xF9,0xD6, - 0x80,0x83,0x02,0x03,0x01,0x00,0x01,0xA3,0x60,0x30,0x5E,0x30,0x0E,0x06,0x03,0x55, - 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x03,0xB8,0x30,0x0C,0x06,0x03,0x55, - 0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, - 0x04,0x16,0x04,0x14,0x71,0x53,0x3F,0x7F,0x72,0x47,0xBB,0xE3,0x60,0xD9,0xD9,0xD8, - 0x39,0x6D,0x8D,0x33,0xA3,0x74,0xC3,0x59,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04, - 0x18,0x30,0x16,0x80,0x14,0xFF,0x4B,0x1A,0x43,0x9A,0xF5,0x19,0x96,0xAB,0x18,0x00, - 0x2B,0x61,0xC9,0xEE,0x40,0x9D,0x8E,0xC7,0x04,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, - 0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x0F,0xD9,0x40, - 0x27,0x1C,0x00,0x01,0x2D,0x4C,0x67,0xA6,0x0D,0x74,0xA8,0xBD,0xF6,0x97,0x16,0x46, - 0xB1,0x02,0xD7,0x51,0xF6,0x02,0xC1,0x0F,0xB1,0x34,0x8A,0xCB,0xB7,0x81,0x29,0xBD, - 0x7B,0x67,0xA3,0xE6,0x49,0x3D,0xBB,0x3E,0x0D,0x26,0x75,0x1D,0xDC,0x37,0xA7,0x38, - 0x86,0xD8,0x81,0x5A,0xC5,0xAF,0xCD,0xD6,0xCB,0x0E,0xBA,0x53,0x28,0x57,0x83,0x16, - 0x23,0xCC,0x11,0x01,0x0E,0x18,0x4D,0xFE,0x29,0x1B,0x7C,0x3F,0x33,0xD5,0x4B,0x7C, - 0x74,0xB5,0xFD,0x62,0xC5,0x45,0xEC,0x08,0xE4,0xC0,0xD3,0xCE,0xBA,0xB0,0x04,0x0D, - 0x7C,0xEF,0x5C,0x3F,0x92,0xDC,0x45,0x24,0xA3,0x02,0xFE,0xA4,0x60,0x15,0x28,0x43, - 0x1B,0x46,0x51,0x1F,0x9F,0x0D,0x89,0x62,0x6C,0x30,0xE2,0x2B,0xF7,0x8C,0x7B,0xD6, - 0xE3,0x71,0x11,0xD1,0xE5,0xF5,0x83,0xAE,0xD8,0xEB,0x5A,0x40,0xB6,0x09,0x00,0x53, - 0x8F,0xAF,0x4D,0xA7,0x3D,0x50,0xB0,0x1B,0x88,0x6B,0x9D,0x18,0x79,0x1E,0xCB,0xBF, - 0x86,0xBA,0xDE,0x48,0x28,0x3A,0x53,0x17,0x59,0x2D,0xC2,0x98,0xE0,0xE7,0x54,0x03, - 0xD0,0x1D,0xFB,0xC1,0xCA,0x68,0x43,0x2D,0x23,0xC3,0xA3,0x12,0x04,0x89,0x77,0x41, - 0xB8,0x96,0x3F,0xDC,0x00,0x73,0x07,0xD0,0xA6,0x8C,0x35,0x45,0xB4,0x07,0x69,0xF8, - 0x79,0x6E,0x7B,0x04,0x6D,0x0F,0x95,0x20,0x5B,0x76,0x17,0x78,0x91,0x91,0xA4,0xBE, - 0x6D,0x5C,0xE9,0x71,0x12,0x68,0x6C,0xB7,0xA4,0x36,0xC3,0x82,0xCF,0x65,0x7D,0xE3, - 0x50,0x92,0x02,0x54,0x3D,0xFE,0x16,0x8D,0x4F,0xE0,0x11,0xE0,0xB5, -}; - -/* - subject= /C=US/O=Apple Computer, Inc./OU=Apple Computer iPod Accessories/CN=IPA_3333AA070313AA06AA0011AA000001 - issuer= /C=US/O=Apple Computer, Inc./OU=Apple Computer Certificate Authority/CN=Apple iPod Accessories Certificate Authority - serial=3333AA070313AA06AA0011AA000001 - */ -const uint8_t _leaf1[] = { - 0x30,0x82,0x03,0x7C,0x30,0x82,0x02,0x64,0xA0,0x03,0x02,0x01,0x02,0x02,0x0F,0x33, - 0x33,0xAA,0x07,0x03,0x13,0xAA,0x06,0xAA,0x00,0x11,0xAA,0x00,0x00,0x01,0x30,0x0D, - 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x92, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1D,0x30, - 0x1B,0x06,0x03,0x55,0x04,0x0A,0x13,0x14,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F, - 0x6D,0x70,0x75,0x74,0x65,0x72,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x2D,0x30,0x2B, - 0x06,0x03,0x55,0x04,0x0B,0x13,0x24,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x6D, - 0x70,0x75,0x74,0x65,0x72,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, - 0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x35,0x30,0x33,0x06, - 0x03,0x55,0x04,0x03,0x13,0x2C,0x41,0x70,0x70,0x6C,0x65,0x20,0x69,0x50,0x6F,0x64, - 0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72, - 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, - 0x74,0x79,0x30,0x1E,0x17,0x0D,0x30,0x37,0x30,0x33,0x31,0x33,0x32,0x31,0x32,0x37, - 0x33,0x35,0x5A,0x17,0x0D,0x31,0x35,0x30,0x33,0x31,0x33,0x32,0x31,0x32,0x37,0x33, - 0x35,0x5A,0x30,0x81,0x83,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, - 0x55,0x53,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0A,0x13,0x14,0x41,0x70,0x70, - 0x6C,0x65,0x20,0x43,0x6F,0x6D,0x70,0x75,0x74,0x65,0x72,0x2C,0x20,0x49,0x6E,0x63, - 0x2E,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0B,0x13,0x1F,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x43,0x6F,0x6D,0x70,0x75,0x74,0x65,0x72,0x20,0x69,0x50,0x6F,0x64,0x20, - 0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x31,0x2B,0x30,0x29,0x06, - 0x03,0x55,0x04,0x03,0x14,0x22,0x49,0x50,0x41,0x5F,0x33,0x33,0x33,0x33,0x41,0x41, - 0x30,0x37,0x30,0x33,0x31,0x33,0x41,0x41,0x30,0x36,0x41,0x41,0x30,0x30,0x31,0x31, - 0x41,0x41,0x30,0x30,0x30,0x30,0x30,0x31,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A, - 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81, - 0x89,0x02,0x81,0x81,0x00,0x91,0x66,0xDB,0x40,0x0E,0xC4,0xE5,0x8D,0xB3,0x86,0xFD, - 0x36,0x06,0x38,0xCC,0x83,0xA4,0xD7,0xFF,0x14,0xA6,0x77,0x3B,0x63,0x7A,0xAE,0xE8, - 0x76,0xDB,0xD8,0x2F,0x7C,0x70,0x84,0xE8,0x0A,0x63,0x33,0xA7,0xCB,0x0E,0x17,0x94, - 0x80,0x39,0xB7,0xE6,0x16,0x0C,0xA7,0x1F,0x7D,0x11,0x02,0x76,0xDA,0x1D,0x0B,0xED, - 0x8D,0x2A,0xEB,0x60,0xCF,0x55,0x85,0xBD,0x92,0x32,0xC9,0xC9,0xB2,0x16,0xEA,0xBA, - 0xA8,0xC8,0x8C,0xE4,0x93,0x7A,0x0A,0xAA,0x40,0x24,0x0F,0x96,0xC7,0xC5,0x95,0x21, - 0xD9,0xB0,0x98,0x51,0x8D,0xE4,0xC6,0x63,0x6E,0x73,0x92,0xAB,0x77,0xE9,0x71,0xAF, - 0x0E,0x50,0xA3,0xB4,0x68,0xA8,0x82,0x67,0x88,0xF9,0xA5,0xC8,0x68,0x7B,0x49,0x36, - 0x72,0xEE,0x06,0x1A,0x95,0x02,0x03,0x01,0x00,0x01,0xA3,0x60,0x30,0x5E,0x30,0x0E, - 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x03,0xB8,0x30,0x0C, - 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1D,0x06,0x03, - 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xDE,0x6A,0x9D,0x5E,0x83,0x77,0xA6,0xFE,0xA9, - 0x65,0x30,0x5F,0x98,0xE8,0xA4,0x7C,0xDE,0x0A,0xB3,0x48,0x30,0x1F,0x06,0x03,0x55, - 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xC9,0xAA,0x84,0x6B,0x06,0xB8,0x76,0xE2, - 0x96,0x4F,0xE7,0x27,0x02,0xD7,0x2E,0x3B,0xDA,0xF7,0xB0,0x18,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00, - 0x96,0x07,0x3B,0x68,0xE8,0x2F,0x97,0xA5,0x42,0xFF,0x9D,0x34,0xFD,0x3A,0xD2,0x01, - 0x69,0xD7,0x67,0x46,0x9A,0x7D,0x56,0xE0,0x7F,0x91,0xEE,0xC3,0x5C,0xD2,0x51,0x54, - 0xE3,0xD2,0x17,0x08,0xB2,0xBC,0xCD,0x85,0xF8,0x8E,0xAD,0x49,0x53,0xE1,0x07,0x5A, - 0x9B,0x03,0xA2,0x35,0xCA,0xCF,0xC6,0xB6,0xC9,0x71,0x53,0xBC,0x2E,0xA3,0x1B,0x03, - 0x5C,0x55,0x57,0xA3,0x10,0xBC,0x15,0x81,0xD5,0xE6,0xA3,0xB8,0x21,0x50,0x2E,0x44, - 0xD4,0xEA,0x71,0x17,0xE5,0xFC,0x71,0xC3,0xF9,0xE8,0x99,0x98,0xF3,0x5F,0xFF,0xB2, - 0x8E,0xC7,0x56,0x74,0x46,0xEC,0x63,0x3F,0x4A,0xA6,0x9C,0x85,0x7C,0x08,0x61,0x32, - 0xB7,0x35,0x36,0x01,0x0C,0xCE,0xD8,0xE3,0xC4,0x6A,0x0D,0xF2,0x25,0x56,0x59,0xBA, - 0x88,0x1B,0xB4,0x21,0x80,0xB9,0x69,0x9E,0x93,0xF7,0xB1,0x22,0x19,0x8B,0x8B,0xD8, - 0xBD,0xDC,0x0C,0xA7,0x69,0x4B,0x5B,0xE9,0xD7,0x7A,0x1D,0xEF,0x37,0x0D,0x24,0xDC, - 0xA7,0x67,0xBC,0x0D,0xE1,0x0D,0x28,0xA0,0xB8,0x83,0x28,0x6A,0x8A,0xD6,0x59,0x40, - 0x4A,0xF1,0x06,0x0D,0x75,0xB9,0x81,0x4B,0x4C,0x2D,0xCB,0x57,0xE0,0x7A,0x32,0x5B, - 0xE0,0xEA,0xDD,0x0C,0xDC,0xFD,0x5E,0x7E,0xB0,0x77,0x07,0x0D,0xA7,0x14,0x0B,0x41, - 0x94,0x4F,0x10,0x3E,0xA5,0x0C,0x68,0x3F,0x8C,0x70,0x5C,0x29,0xB7,0xE9,0xFC,0x09, - 0x35,0x5C,0x2D,0xB3,0xA9,0x4F,0x51,0xB0,0xA7,0xD5,0xAD,0x3F,0xE2,0xA2,0x4C,0x73, - 0xFC,0x2F,0x6E,0x21,0x38,0xE5,0xBB,0x8B,0x57,0x51,0xE5,0x9B,0x8B,0xA6,0xAA,0x0B -}; - -/* subject:/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Accessories Certification Authority - 00000000 */ -/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Accessories Certification Authority - 00000000 */ -const uint8_t _v3ca[618]={ - 0x30,0x82,0x02,0x66,0x30,0x82,0x02,0x0C,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x00, - 0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x89,0x31, - 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, - 0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, - 0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20, - 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x3D,0x30,0x3B,0x06,0x03,0x55, - 0x04,0x03,0x13,0x34,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65,0x73,0x73, - 0x6F,0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, - 0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x2D,0x20, - 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x32, - 0x32,0x34,0x30,0x30,0x31,0x39,0x33,0x33,0x5A,0x17,0x0D,0x34,0x36,0x30,0x32,0x32, - 0x34,0x30,0x30,0x31,0x39,0x33,0x33,0x5A,0x30,0x81,0x89,0x31,0x0B,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30, - 0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65, - 0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68, - 0x6F,0x72,0x69,0x74,0x79,0x31,0x3D,0x30,0x3B,0x06,0x03,0x55,0x04,0x03,0x13,0x34, - 0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65, - 0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20, - 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x2D,0x20,0x30,0x30,0x30,0x30, - 0x30,0x30,0x30,0x30,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02, - 0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xF3, - 0xA9,0x19,0x0B,0xFA,0xF5,0xAB,0x2A,0x99,0xC0,0x6A,0x08,0x7E,0x6C,0x21,0x88,0x88, - 0x3C,0xDC,0xE0,0xB1,0x80,0x11,0x00,0x35,0xF5,0x03,0x6B,0x82,0x81,0xAD,0x73,0x8B, - 0x76,0xE7,0xD5,0x6B,0x7E,0x6A,0xE4,0xF6,0x10,0x7A,0x30,0x32,0xC9,0xBE,0x75,0x28, - 0xBA,0x7C,0xF7,0x02,0x19,0x1C,0x18,0x68,0xBB,0x2F,0xEC,0xEC,0x06,0x66,0xF9,0xA3, - 0x63,0x30,0x61,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30, - 0x03,0x01,0x01,0xFF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, - 0x03,0x02,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x69, - 0x96,0xE3,0x5B,0x36,0x2A,0xAE,0x8B,0xB1,0x02,0x94,0x1D,0xA6,0x13,0x5B,0xB2,0x6E, - 0xE9,0x9B,0x31,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, - 0x69,0x96,0xE3,0x5B,0x36,0x2A,0xAE,0x8B,0xB1,0x02,0x94,0x1D,0xA6,0x13,0x5B,0xB2, - 0x6E,0xE9,0x9B,0x31,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02, - 0x03,0x48,0x00,0x30,0x45,0x02,0x20,0x7B,0x11,0x63,0x57,0xFE,0x7B,0xA3,0xF7,0xF2, - 0x32,0x4D,0x04,0x21,0x8F,0x97,0xDB,0xF5,0xE8,0x74,0x3E,0x2A,0x3F,0x18,0x1A,0xCC, - 0xE4,0x7A,0xB5,0x73,0x68,0x9C,0xB3,0x02,0x21,0x00,0xEC,0x33,0xC9,0xF9,0xE8,0xC1, - 0x40,0x10,0xD8,0x88,0xF7,0x2B,0xC3,0x30,0x8F,0xF1,0x22,0xFF,0x66,0x32,0xB4,0x69, - 0x05,0xFA,0x92,0x9C,0xB6,0xEF,0x6C,0x61,0xE7,0xFA, -}; - -/* subject:/C=US/O=Apple Inc./OU=Apple Accessories/CN=IPA_019256C98E8DCE6074DEE81A0002A756 */ -/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Accessories Certification Authority - 00000000 */ -const unsigned char _v3leaf[558]={ - 0x30,0x82,0x02,0x2A,0x30,0x82,0x01,0xD1,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x01, - 0x92,0x56,0xC9,0x8E,0x8D,0xCE,0x60,0x74,0xDE,0xE8,0x1A,0x00,0x02,0xA7,0x56,0x30, - 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x89,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, - 0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65, - 0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, - 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x3D,0x30,0x3B,0x06,0x03,0x55,0x04, - 0x03,0x13,0x34,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F, - 0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, - 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x2D,0x20,0x30, - 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x34,0x31, - 0x34,0x32,0x30,0x34,0x30,0x33,0x31,0x5A,0x17,0x0D,0x34,0x39,0x31,0x32,0x33,0x31, - 0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x6D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1A,0x30,0x18,0x06, - 0x03,0x55,0x04,0x0B,0x13,0x11,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65, - 0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04,0x03, - 0x14,0x24,0x49,0x50,0x41,0x5F,0x30,0x31,0x39,0x32,0x35,0x36,0x43,0x39,0x38,0x45, - 0x38,0x44,0x43,0x45,0x36,0x30,0x37,0x34,0x44,0x45,0x45,0x38,0x31,0x41,0x30,0x30, - 0x30,0x32,0x41,0x37,0x35,0x36,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE, - 0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00, - 0x04,0xD7,0x21,0x4D,0x08,0x7F,0xEA,0x11,0x15,0xEA,0xF3,0x4D,0x9D,0x86,0x79,0x42, - 0xE0,0xA2,0x72,0x68,0x08,0xD5,0xF4,0xD2,0x8F,0x79,0x20,0x45,0xE5,0xFD,0xE8,0x8E, - 0xFE,0x08,0xD0,0x72,0x0B,0x88,0x9F,0xDD,0x8B,0xC3,0x55,0x91,0x09,0xD1,0xFB,0x9E, - 0x8B,0xFA,0x7A,0x64,0xD5,0x70,0xD6,0x33,0xB4,0xAF,0x80,0xA4,0xAB,0x0A,0xE3,0x3D, - 0x23,0xA3,0x36,0x30,0x34,0x30,0x32,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64, - 0x06,0x24,0x01,0x01,0xFF,0x04,0x22,0x04,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48, - 0xCE,0x3D,0x04,0x03,0x02,0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x5E,0xDD,0x00,0x88, - 0x4C,0x1F,0x58,0xF1,0x44,0xC9,0x0C,0xE1,0x9B,0x54,0x1F,0xB9,0x20,0xC1,0xDE,0x00, - 0x9F,0xEC,0xA8,0xDD,0x5E,0xDC,0x2A,0xF4,0xFC,0xFC,0x36,0x8A,0x02,0x20,0x0A,0x4C, - 0x2F,0x9D,0xA0,0x4C,0xEB,0xA0,0xF1,0xAF,0xAE,0xDA,0x0F,0x2C,0x93,0x22,0x0B,0x74, - 0xD5,0x2B,0x80,0x3D,0x81,0x33,0x33,0xB6,0x6C,0xFB,0xC0,0xB5,0x70,0x9B, -}; - -/* subject:/C=US/O=Apple Inc./OU=Apple Accessories/CN=IPA_204E6F2CB683A518F7726D190000C5DA */ -/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Accessories Certification Authority - 00000002 */ -const unsigned char _malformedV3Leaf[] = { - 0x30,0x82,0x02,0x2B,0x30,0x82,0x01,0xD1,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x20, - 0x4E,0x6F,0x2C,0xB6,0x83,0xA5,0x18,0xF7,0x72,0x6D,0x19,0x00,0x00,0xC5,0xDA,0x30, - 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x89,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, - 0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65, - 0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, - 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x3D,0x30,0x3B,0x06,0x03,0x55,0x04, - 0x03,0x13,0x34,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F, - 0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, - 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x2D,0x20,0x30, - 0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x33, - 0x31,0x31,0x31,0x35,0x31,0x31,0x37,0x5A,0x17,0x0D,0x34,0x39,0x31,0x32,0x33,0x31, - 0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x6D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1A,0x30,0x18,0x06, - 0x03,0x55,0x04,0x0B,0x13,0x11,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65, - 0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04,0x03, - 0x14,0x24,0x49,0x50,0x41,0x5F,0x32,0x30,0x34,0x45,0x36,0x46,0x32,0x43,0x42,0x36, - 0x38,0x33,0x41,0x35,0x31,0x38,0x46,0x37,0x37,0x32,0x36,0x44,0x31,0x39,0x30,0x30, - 0x30,0x30,0x43,0x35,0x44,0x41,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE, - 0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00, - 0x04,0x9A,0x21,0x88,0x3D,0x3B,0xCD,0xA9,0x9F,0x1B,0xC6,0x5F,0x47,0x5D,0xA8,0xEB, - 0x52,0x18,0x9F,0x1E,0xF3,0xD8,0x7C,0xB6,0x1D,0x39,0x7A,0x8C,0xE0,0xDB,0x79,0xB4, - 0x9D,0x37,0x16,0xB8,0x6F,0x1C,0x29,0x42,0x59,0xA5,0x4E,0xA2,0x9A,0xB1,0x0E,0xC4, - 0x55,0xCC,0x89,0x79,0x4A,0x9E,0xDB,0x95,0x7A,0xF3,0x3D,0x7F,0x58,0xAD,0xF7,0x61, - 0xB3,0xA3,0x36,0x30,0x34,0x30,0x32,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64, - 0x06,0x24,0x01,0x01,0xFF,0x04,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48, - 0xCE,0x3D,0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x20,0x80,0x6B,0x96,0x6C, - 0x83,0x04,0x29,0x68,0x52,0xF9,0x74,0x42,0x7C,0x49,0x81,0x39,0x53,0x91,0x53,0x0D, - 0x95,0xB7,0x4F,0x18,0xFC,0xA5,0x38,0x9A,0x55,0x68,0x53,0x02,0x02,0x21,0x00,0xF5, - 0xE4,0xF2,0xB7,0x0B,0x7F,0x43,0xFA,0xDB,0xC2,0x1A,0x05,0xEF,0xF9,0x0E,0x31,0xFC, - 0x0A,0xCB,0xCD,0x6C,0x03,0x8A,0x73,0x95,0x74,0xB1,0x57,0x03,0x09,0x55,0x8D, -}; - -/* subject:/CN=Test Accessories Software Authentication Root CA/OU=Apple Certification Authority/O=Apple Inc./C=US */ -/* issuer :/CN=Test Accessories Software Authentication Root CA/OU=Apple Certification Authority/O=Apple Inc./C=US */ -const uint8_t _iAPSWAuthTestRoot[584]={ - 0x30,0x82,0x02,0x44,0x30,0x82,0x01,0xEA,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x59, - 0x29,0x18,0xB6,0x20,0x80,0x90,0x94,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, - 0x04,0x03,0x02,0x30,0x81,0x85,0x31,0x39,0x30,0x37,0x06,0x03,0x55,0x04,0x03,0x0C, - 0x30,0x54,0x65,0x73,0x74,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65, - 0x73,0x20,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x41,0x75,0x74,0x68,0x65, - 0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, - 0x41,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20, - 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55, - 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31, - 0x37,0x31,0x31,0x30,0x39,0x30,0x30,0x31,0x35,0x31,0x32,0x5A,0x17,0x0D,0x33,0x37, - 0x31,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x81,0x85,0x31,0x39, - 0x30,0x37,0x06,0x03,0x55,0x04,0x03,0x0C,0x30,0x54,0x65,0x73,0x74,0x20,0x41,0x63, - 0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x20,0x53,0x6F,0x66,0x74,0x77,0x61, - 0x72,0x65,0x20,0x41,0x75,0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F, - 0x6E,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03,0x55, - 0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66, - 0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74, - 0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, - 0x02,0x55,0x53,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, - 0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x00,0x28, - 0x4C,0xD4,0xFA,0x57,0x5C,0xB5,0x62,0xE6,0x10,0x30,0x60,0xBB,0x4E,0x8E,0xE9,0x34, - 0x52,0xFC,0xAB,0x74,0x4C,0x62,0xDA,0xEE,0x66,0x47,0x5E,0x5D,0x0D,0x04,0x2A,0x22, - 0x49,0xC4,0xF0,0x2C,0x93,0xC6,0xA8,0x5E,0x26,0x69,0xAA,0x3C,0x43,0xF8,0x49,0xCC, - 0x89,0x03,0x98,0xB3,0x7A,0x90,0xC8,0x79,0xFD,0x5A,0x13,0xE7,0x26,0x8C,0xA3,0x42, - 0x30,0x40,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03, - 0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x6F,0x79, - 0x89,0xE2,0x11,0xB0,0x49,0xE2,0xC1,0x5C,0xC4,0xDC,0xC7,0xE0,0x62,0x9F,0x3B,0x0A, - 0xC6,0x8C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02, - 0x01,0x06,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48, - 0x00,0x30,0x45,0x02,0x21,0x00,0x9A,0x4F,0xA8,0xC3,0xC2,0x06,0x7D,0x86,0x3D,0x6F, - 0x9B,0x02,0xD7,0xBC,0xD6,0x28,0xE2,0x22,0xAA,0x90,0x62,0x73,0xED,0x91,0x34,0xD7, - 0x62,0xF0,0x4D,0xD7,0xD4,0x38,0x02,0x20,0x23,0x7B,0x01,0x88,0xBB,0xB9,0xF2,0x00, - 0x04,0x20,0x9B,0xC7,0x69,0x97,0x4B,0xAE,0xC6,0xB0,0x2E,0x93,0xE3,0x9B,0x50,0x8B, - 0xC8,0x1E,0xA4,0x94,0xF6,0x97,0x78,0x78, -}; - -/* subject:/CN=0/O=TestPPID1234 */ -/* issuer :/CN=Test Accessories Software Authentication Root CA/OU=Apple Certification Authority/O=Apple Inc./C=US */ -const uint8_t _malformed_iAPSWAuth_leaf[739]={ - 0x30,0x82,0x02,0xDF,0x30,0x82,0x02,0x85,0xA0,0x03,0x02,0x01,0x02,0x02,0x0A,0x12, - 0x34,0x56,0x78,0x90,0x12,0x34,0x56,0x78,0x90,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48, - 0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x85,0x31,0x39,0x30,0x37,0x06,0x03,0x55,0x04, - 0x03,0x0C,0x30,0x54,0x65,0x73,0x74,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72, - 0x69,0x65,0x73,0x20,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x41,0x75,0x74, - 0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x52,0x6F,0x6F,0x74, - 0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70, - 0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, - 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06, - 0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17, - 0x0D,0x31,0x37,0x31,0x31,0x31,0x35,0x32,0x30,0x34,0x33,0x35,0x38,0x5A,0x17,0x0D, - 0x32,0x37,0x31,0x32,0x31,0x33,0x32,0x30,0x34,0x33,0x35,0x38,0x5A,0x30,0x23,0x31, - 0x0A,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x0C,0x01,0x30,0x31,0x15,0x30,0x13,0x06, - 0x03,0x55,0x04,0x0A,0x0C,0x0C,0x54,0x65,0x73,0x74,0x50,0x50,0x49,0x44,0x31,0x32, - 0x33,0x34,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06, - 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xC1,0xBD,0x0B, - 0x4E,0xBA,0xD3,0xC6,0x8F,0x70,0x39,0x73,0xBF,0x58,0xB7,0x75,0x02,0x41,0x60,0x62, - 0x70,0x6A,0x4D,0xA6,0x5C,0xF6,0xE7,0x5B,0xA9,0xAF,0x50,0x60,0x35,0x90,0xED,0x7D, - 0x28,0xF1,0x3C,0xF5,0x1D,0x4B,0xF4,0x32,0x41,0x3E,0x05,0x79,0x0B,0xEB,0xDD,0x89, - 0xA0,0x30,0x11,0xC9,0xB0,0x3F,0x83,0x77,0xC4,0xB3,0x2B,0x0A,0xE4,0xA3,0x82,0x01, - 0x3C,0x30,0x82,0x01,0x38,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, - 0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, - 0x6F,0x79,0x89,0xE2,0x11,0xB0,0x49,0xE2,0xC1,0x5C,0xC4,0xDC,0xC7,0xE0,0x62,0x9F, - 0x3B,0x0A,0xC6,0x8C,0x30,0x57,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, - 0x04,0x4B,0x30,0x49,0x30,0x47,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, - 0x86,0x3B,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D,0x75,0x61, - 0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, - 0x2F,0x6F,0x63,0x73,0x70,0x30,0x33,0x2D,0x74,0x65,0x73,0x74,0x61,0x63,0x63,0x73, - 0x77,0x61,0x75,0x74,0x68,0x72,0x6F,0x6F,0x74,0x63,0x61,0x30,0x31,0x30,0x46,0x06, - 0x03,0x55,0x1D,0x1F,0x04,0x3F,0x30,0x3D,0x30,0x3B,0xA0,0x39,0xA0,0x37,0x86,0x35, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61,0x74,0x2E,0x63, - 0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65, - 0x73,0x74,0x61,0x63,0x63,0x73,0x77,0x61,0x75,0x74,0x68,0x72,0x6F,0x6F,0x74,0x63, - 0x61,0x2E,0x63,0x72,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, - 0x95,0x87,0xEF,0xFB,0xDF,0x1F,0x26,0x48,0x67,0x29,0xEC,0x94,0x70,0xD6,0x29,0x5D, - 0x9A,0x95,0xC8,0x88,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, - 0x03,0x02,0x07,0x80,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06, - 0x3B,0x01,0x04,0x03,0x0C,0x01,0x30,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7, - 0x63,0x64,0x06,0x3B,0x02,0x04,0x03,0x0C,0x01,0x30,0x30,0x11,0x06,0x0A,0x2A,0x86, - 0x48,0x86,0xF7,0x63,0x64,0x06,0x3B,0x03,0x04,0x03,0x0C,0x01,0x30,0x30,0x0A,0x06, - 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x21, - 0x00,0x9B,0xF6,0xD2,0x7D,0x61,0x1F,0xFD,0x73,0x9C,0x1D,0x54,0x3F,0x3C,0x9A,0xDF, - 0xAA,0x1D,0xEA,0x35,0xF6,0x41,0xF8,0xB5,0xC5,0x0E,0x92,0x14,0xA3,0x87,0xED,0xE6, - 0xD2,0x02,0x20,0x60,0xDA,0x7A,0x30,0xC3,0xEB,0x24,0x58,0xE2,0xBF,0x83,0xFC,0x41, - 0x51,0xF3,0xFB,0x50,0xE1,0x0F,0x53,0x6A,0x41,0x7A,0x59,0xA9,0x04,0x01,0x84,0xF9, - 0x81,0x89,0x87, -}; - -/* subject:/CN=0/O=PPID1234 */ -/* issuer :/CN=Test Accessories Software Authentication Root CA/OU=Apple Certification Authority/O=Apple Inc./C=US */ -const uint8_t _iAPSWAuth_leaf[735]={ - 0x30,0x82,0x02,0xDB,0x30,0x82,0x02,0x82,0xA0,0x03,0x02,0x01,0x02,0x02,0x0B,0x00, - 0x8A,0x71,0xFE,0xCD,0xA2,0xF3,0x00,0x00,0x00,0x00,0x30,0x0A,0x06,0x08,0x2A,0x86, - 0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x85,0x31,0x39,0x30,0x37,0x06,0x03,0x55, - 0x04,0x03,0x0C,0x30,0x54,0x65,0x73,0x74,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F, - 0x72,0x69,0x65,0x73,0x20,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x41,0x75, - 0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x52,0x6F,0x6F, - 0x74,0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41, - 0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, - 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11, - 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, - 0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E, - 0x17,0x0D,0x31,0x37,0x31,0x32,0x31,0x32,0x30,0x32,0x35,0x36,0x35,0x30,0x5A,0x17, - 0x0D,0x32,0x38,0x30,0x31,0x30,0x39,0x30,0x32,0x35,0x36,0x35,0x30,0x5A,0x30,0x1F, - 0x31,0x0A,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x0C,0x01,0x30,0x31,0x11,0x30,0x0F, - 0x06,0x03,0x55,0x04,0x0A,0x0C,0x08,0x50,0x50,0x49,0x44,0x31,0x32,0x33,0x34,0x30, - 0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86, - 0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x64,0xFA,0xB0,0xFD,0xAF,0xD3, - 0xBF,0x9A,0xF6,0x48,0x03,0x9D,0x6B,0xBB,0x55,0x81,0x5E,0x6C,0x47,0x7D,0x2E,0xD4, - 0xF2,0xAE,0xA9,0xD3,0xA7,0x13,0xFA,0x69,0x16,0x16,0xC9,0x46,0x16,0xA2,0x38,0xB7, - 0x39,0xAC,0xFE,0x0B,0x9B,0x01,0x81,0x8A,0x94,0xA5,0x49,0x44,0x48,0x22,0x50,0x13, - 0x6B,0x06,0x28,0x6E,0x2D,0x09,0x1A,0x40,0x62,0x35,0xA3,0x82,0x01,0x3C,0x30,0x82, - 0x01,0x38,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00, - 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x6F,0x79,0x89, - 0xE2,0x11,0xB0,0x49,0xE2,0xC1,0x5C,0xC4,0xDC,0xC7,0xE0,0x62,0x9F,0x3B,0x0A,0xC6, - 0x8C,0x30,0x57,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x4B,0x30, - 0x49,0x30,0x47,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x3B,0x68, - 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D,0x75,0x61,0x74,0x2E,0x63, - 0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63, - 0x73,0x70,0x30,0x33,0x2D,0x74,0x65,0x73,0x74,0x61,0x63,0x63,0x73,0x77,0x61,0x75, - 0x74,0x68,0x72,0x6F,0x6F,0x74,0x63,0x61,0x30,0x31,0x30,0x46,0x06,0x03,0x55,0x1D, - 0x1F,0x04,0x3F,0x30,0x3D,0x30,0x3B,0xA0,0x39,0xA0,0x37,0x86,0x35,0x68,0x74,0x74, - 0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70, - 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65,0x73,0x74,0x61, - 0x63,0x63,0x73,0x77,0x61,0x75,0x74,0x68,0x72,0x6F,0x6F,0x74,0x63,0x61,0x2E,0x63, - 0x72,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xE3,0xA0,0x9F, - 0x50,0x4D,0x31,0xB6,0xB3,0xED,0x16,0x5B,0xA3,0x91,0x68,0xB8,0xC2,0x65,0x40,0x73, - 0x4D,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, - 0x80,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x3B,0x01,0x04, - 0x03,0x04,0x01,0x01,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06, - 0x3B,0x02,0x04,0x03,0x04,0x01,0x00,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7, - 0x63,0x64,0x06,0x3B,0x03,0x04,0x03,0x04,0x01,0x01,0x30,0x0A,0x06,0x08,0x2A,0x86, - 0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x39,0x57,0x87, - 0x0B,0x53,0xB3,0x24,0x14,0x96,0x26,0xD2,0xA5,0x06,0xC2,0xA8,0x4C,0x5C,0x40,0xD4, - 0xC4,0x8D,0xEC,0x2D,0x2F,0x80,0xFB,0x2B,0xAF,0x56,0xF1,0x10,0x32,0x02,0x20,0x6D, - 0xCC,0xA8,0x41,0x92,0x89,0xD4,0xB8,0xEF,0xE5,0xB3,0x30,0xF7,0x94,0xBE,0x85,0x52, - 0xFE,0x75,0x5E,0xB2,0xEF,0x34,0x2F,0x71,0x8B,0xCD,0xD2,0xF0,0x9F,0xF7,0x63, -}; - -/* subject:/CN=Component Root CA/O=Apple Inc./ST=California */ -/* issuer :/CN=Component Root CA/O=Apple Inc./ST=California */ -const uint8_t _componentRoot[] = { - 0x30,0x82,0x02,0x01,0x30,0x82,0x01,0x87,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x60, - 0x38,0x41,0xE4,0xE2,0xE9,0x38,0x31,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, - 0x04,0x03,0x03,0x30,0x46,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11, - 0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, - 0x41,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, - 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x30,0x1E,0x17,0x0D,0x31, - 0x38,0x31,0x32,0x31,0x39,0x31,0x39,0x33,0x31,0x35,0x34,0x5A,0x17,0x0D,0x34,0x33, - 0x31,0x32,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x46,0x31,0x1A,0x30, - 0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E, - 0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x31,0x13,0x30,0x11,0x06,0x03,0x55, - 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, - 0x6E,0x69,0x61,0x30,0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, - 0x06,0x05,0x2B,0x81,0x04,0x00,0x22,0x03,0x62,0x00,0x04,0x98,0x15,0xB6,0x3A,0x39, - 0xC0,0xBA,0x4D,0xC6,0x27,0xE2,0xB1,0x74,0x1E,0x99,0x0B,0xEB,0x2D,0x37,0xC5,0x3F, - 0x20,0xA9,0x8E,0xB3,0xFC,0x42,0x2E,0x33,0x07,0x40,0x47,0xF1,0x27,0xEC,0x02,0xC4, - 0x46,0xEC,0x2F,0x3C,0xC0,0xF8,0xAE,0xD7,0x0C,0x95,0xA9,0x90,0x3C,0x39,0x8C,0xAD, - 0x2F,0x20,0x8F,0x57,0xD9,0x96,0x6C,0xAD,0x89,0x6D,0x2B,0x10,0x06,0x00,0x5E,0x1C, - 0xD3,0xC2,0xD0,0x3F,0xDC,0x4E,0x89,0x1A,0xCC,0x41,0xC4,0xC1,0x75,0x37,0xC6,0xCB, - 0xFB,0xA2,0x6C,0xB5,0xCE,0x90,0x77,0x1D,0xC7,0x2C,0x9C,0xA3,0x42,0x30,0x40,0x30, - 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x90,0xD1,0x56,0xA9,0x3E, - 0xB4,0xEE,0x8C,0xD0,0x10,0x4B,0x9F,0x17,0x1C,0x5B,0x55,0xF2,0x12,0xF6,0x4C,0x30, - 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x02,0x04,0x30, - 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x68,0x00,0x30,0x65, - 0x02,0x31,0x00,0x9D,0x5A,0xE3,0x17,0xA8,0x56,0xB4,0x3C,0xB1,0x61,0x30,0x01,0xDC, - 0x03,0x3D,0xD4,0xEC,0xA4,0xAA,0xA4,0x2D,0xF9,0xE5,0x79,0x59,0x88,0xF7,0xE3,0xAC, - 0x3C,0xD0,0x68,0x76,0x79,0xCC,0x81,0x64,0xEC,0x34,0x2F,0x94,0x7D,0xF0,0x70,0x5D, - 0x65,0x8D,0xFC,0x02,0x30,0x71,0x6A,0x4F,0xE9,0x2E,0x38,0x87,0xDE,0x90,0x89,0x3B, - 0x1B,0x75,0xAD,0xED,0xE2,0x5C,0x53,0x75,0x71,0x1E,0x5A,0x2A,0xF2,0xD7,0x95,0xF7, - 0x32,0x1B,0xB6,0x0A,0x09,0x12,0x60,0x94,0xAE,0x55,0x2C,0xBE,0xCE,0x3F,0x4B,0xF4, - 0x4C,0x02,0xFB,0x9B,0x8C, -}; - -/* subject:/CN=Battery CA M1/OU=Component CA/O=Apple Inc./ST=California */ -/* issuer :/CN=Component Root CA/O=Apple Inc./ST=California */ -const uint8_t _componentCABattery[] = { - 0x30,0x82,0x02,0x36,0x30,0x82,0x01,0xBD,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x6A, - 0x22,0x01,0x3F,0xEB,0x2B,0x0D,0xA2,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, - 0x04,0x03,0x03,0x30,0x46,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11, - 0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, - 0x41,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, - 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x30,0x1E,0x17,0x0D,0x31, - 0x39,0x30,0x31,0x32,0x33,0x31,0x38,0x35,0x39,0x35,0x31,0x5A,0x17,0x0D,0x33,0x38, - 0x31,0x32,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x59,0x31,0x16,0x30, - 0x14,0x06,0x03,0x55,0x04,0x03,0x0C,0x0D,0x42,0x61,0x74,0x74,0x65,0x72,0x79,0x20, - 0x43,0x41,0x20,0x4D,0x31,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0C, - 0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x20,0x43,0x41,0x31,0x13,0x30,0x11, - 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, - 0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, - 0x66,0x6F,0x72,0x6E,0x69,0x61,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE, - 0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00, - 0x04,0xAF,0x9C,0xF2,0x4B,0x8C,0xBD,0xA3,0x47,0xDF,0xA6,0x18,0x58,0x11,0xA0,0xF9, - 0x54,0xEE,0x5C,0x1E,0xA6,0x49,0x6B,0x74,0x6E,0x79,0xB5,0x36,0x36,0xB6,0x44,0x04, - 0x91,0x0E,0x4C,0x15,0xBD,0x8B,0xA1,0x7D,0x61,0x28,0xB8,0x6A,0x0F,0xE4,0x4C,0x39, - 0x57,0x1B,0x72,0x5B,0xBE,0x5C,0x1D,0x88,0x87,0xBD,0x37,0x3A,0xBC,0x0C,0x10,0x69, - 0x12,0xA3,0x81,0x81,0x30,0x7F,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, - 0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D, - 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x90,0xD1,0x56,0xA9,0x3E,0xB4,0xEE,0x8C,0xD0, - 0x10,0x4B,0x9F,0x17,0x1C,0x5B,0x55,0xF2,0x12,0xF6,0x4C,0x30,0x1D,0x06,0x03,0x55, - 0x1D,0x0E,0x04,0x16,0x04,0x14,0x8C,0x3D,0xFA,0x31,0xF4,0x32,0x17,0x69,0x22,0xA3, - 0x4F,0x5F,0xC1,0x91,0x8E,0xF8,0x07,0xDA,0x84,0xD2,0x30,0x0E,0x06,0x03,0x55,0x1D, - 0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x19,0x06,0x09,0x2A,0x86, - 0x48,0x86,0xF7,0x63,0x64,0x0B,0x01,0x01,0x01,0xFF,0x04,0x09,0x16,0x07,0x42,0x61, - 0x74,0x74,0x65,0x72,0x79,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03, - 0x03,0x03,0x67,0x00,0x30,0x64,0x02,0x30,0x6D,0x3D,0xD2,0x6F,0x08,0xEA,0xA3,0x4B, - 0xBD,0x62,0xFA,0x33,0xCC,0xE6,0xD7,0xD8,0x99,0xD7,0x5E,0x34,0x26,0x9B,0x7C,0x92, - 0x1D,0xF2,0x78,0x41,0xED,0x34,0x1E,0x38,0x56,0x27,0xB4,0x41,0xCE,0xBE,0xFC,0x64, - 0x0B,0x12,0x17,0x4D,0xE0,0x26,0xC6,0xCA,0x02,0x30,0x7A,0x0D,0xC5,0x67,0xA7,0x9D, - 0xA9,0xFA,0x72,0x66,0x8E,0xF8,0xAD,0x40,0x68,0xC4,0xDB,0xE4,0xDB,0x57,0xBF,0x10, - 0x86,0x60,0x14,0x5F,0x4F,0x50,0x01,0x66,0xDB,0x45,0x89,0x8D,0xBC,0x13,0xA8,0x33, - 0xA1,0x26,0xCB,0x84,0x3B,0x2B,0xDB,0xA3,0xE6,0x4E, -}; - -/* subject:/C=US/O=Apple Inc./OU=Components/CN=F5D91143R5LMCRH1P-6A2E0F00 */ -/* issuer :/CN=Battery CA M1/OU=Component CA/O=Apple Inc./ST=California */ -const uint8_t _batteryLeaf[] = { - 0x30,0x82,0x02,0x0E,0x30,0x82,0x01,0xB4,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x2D, - 0x95,0x4B,0x3A,0x9B,0x74,0x5C,0x9A,0xA6,0x8E,0x45,0xD6,0x99,0xC2,0x30,0x0A,0x06, - 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x59,0x31,0x16,0x30,0x14,0x06, - 0x03,0x55,0x04,0x03,0x0C,0x0D,0x42,0x61,0x74,0x74,0x65,0x72,0x79,0x20,0x43,0x41, - 0x20,0x4D,0x31,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0C,0x43,0x6F, - 0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x20,0x43,0x41,0x31,0x13,0x30,0x11,0x06,0x03, - 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, - 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, - 0x72,0x6E,0x69,0x61,0x30,0x1E,0x17,0x0D,0x31,0x39,0x30,0x33,0x32,0x36,0x32,0x30, - 0x32,0x34,0x31,0x34,0x5A,0x17,0x0D,0x32,0x39,0x30,0x33,0x32,0x33,0x32,0x32,0x32, - 0x34,0x31,0x34,0x5A,0x30,0x5C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, - 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, - 0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x0B,0x0C,0x0A,0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x73,0x31,0x23,0x30, - 0x21,0x06,0x03,0x55,0x04,0x03,0x0C,0x1A,0x46,0x35,0x44,0x39,0x31,0x31,0x34,0x33, - 0x52,0x35,0x4C,0x4D,0x43,0x52,0x48,0x31,0x50,0x2D,0x36,0x41,0x32,0x45,0x30,0x46, - 0x30,0x30,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06, - 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xBB,0x20,0x19, - 0xBF,0x3F,0xDC,0x9A,0xA6,0x8F,0xEF,0x94,0x34,0x82,0x29,0x01,0xB3,0xA8,0xF4,0x47, - 0xFA,0x51,0xEC,0x77,0x68,0x1C,0xC1,0xF6,0xD1,0xFE,0x79,0xD0,0xCC,0xEC,0x2D,0xF7, - 0x8D,0xF6,0x07,0xD1,0xDE,0x13,0xF5,0x39,0x4B,0xBF,0xBF,0x11,0x81,0x7F,0x73,0x99, - 0x2A,0x6F,0x6C,0x88,0x2C,0xF7,0x4F,0xA9,0x8B,0x4C,0x72,0x3E,0x5D,0xA3,0x5D,0x30, - 0x5B,0x30,0x2E,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x11,0x04,0x21, - 0x0C,0x1F,0x36,0x38,0x3A,0x66,0x65,0x3A,0x66,0x37,0x3A,0x30,0x34,0x3A,0x62,0x35, - 0x3A,0x34,0x34,0x2F,0x31,0x37,0x32,0x2E,0x31,0x38,0x2E,0x32,0x37,0x2E,0x31,0x36, - 0x37,0x30,0x14,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x0B,0x01,0x04,0x07, - 0x42,0x61,0x74,0x74,0x65,0x72,0x79,0x30,0x13,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x63,0x64,0x0B,0x02,0x04,0x06,0x66,0x33,0x36,0x66,0x38,0x64,0x30,0x0A,0x06,0x08, - 0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x21,0x00, - 0xA1,0x7A,0xC9,0x6B,0xB1,0xC5,0x75,0x80,0x91,0x6C,0xBB,0xF3,0x39,0xC0,0xE1,0xFF, - 0x9C,0xA8,0x9E,0x3D,0xA6,0xA6,0x3A,0x57,0xCD,0x57,0x72,0xA6,0x4C,0x63,0xFD,0x43, - 0x02,0x20,0x33,0xB5,0x9E,0x7C,0x52,0x29,0xDD,0x9A,0xB8,0x10,0x34,0xB8,0x53,0xD4, - 0xAA,0x69,0x6B,0x4E,0xDF,0x69,0xA9,0x56,0x9F,0xBA,0xED,0x66,0xDA,0xD5,0x81,0x67, - 0xE0,0x3D, -}; - -#endif /* _SECURITY_SI_22_SECTRUST_IAP_H_ */ diff --git a/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.h b/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.h deleted file mode 100644 index cc78fcf5..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.h +++ /dev/null @@ -1,1603 +0,0 @@ -/* - * Copyright (c) 2018 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#ifndef _SECURITY_SI_23_SECTRUST_OCSP_H_ -#define _SECURITY_SI_23_SECTRUST_OCSP_H_ - -/* subject:/businessCategory=Private Organization/jurisdictionCountryName=US/jurisdictionStateOrProvinceName=California/serialNumber=C0806592/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Internet Services for Akamai/CN=www.apple.com */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA */ -static const uint8_t _ocsp_c0[]={ - 0x30,0x82,0x06,0xF1,0x30,0x82,0x05,0xD9,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x0F, - 0x8E,0x4E,0x4C,0x9C,0xF5,0x5E,0xA5,0xFE,0x2E,0x9B,0x2B,0x7E,0xFF,0xDE,0x8F,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x75, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x34,0x30,0x32,0x06,0x03,0x55,0x04,0x03,0x13,0x2B,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x53,0x48,0x41,0x32,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64, - 0x20,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x72,0x76, - 0x65,0x72,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x39,0x30,0x33,0x30,0x37,0x30, - 0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x30,0x30,0x33,0x30,0x37,0x31,0x32, - 0x30,0x30,0x30,0x30,0x5A,0x30,0x81,0xEE,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04, - 0x0F,0x0C,0x14,0x50,0x72,0x69,0x76,0x61,0x74,0x65,0x20,0x4F,0x72,0x67,0x61,0x6E, - 0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x31,0x13,0x30,0x11,0x06,0x0B,0x2B,0x06,0x01, - 0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,0x13,0x02,0x55,0x53,0x31,0x1B,0x30,0x19, - 0x06,0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x02,0x13,0x0A,0x43, - 0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x11,0x30,0x0F,0x06,0x03,0x55, - 0x04,0x05,0x13,0x08,0x43,0x30,0x38,0x30,0x36,0x35,0x39,0x32,0x31,0x0B,0x30,0x09, - 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55, - 0x04,0x08,0x13,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12, - 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, - 0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70, - 0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B, - 0x13,0x1C,0x49,0x6E,0x74,0x65,0x72,0x6E,0x65,0x74,0x20,0x53,0x65,0x72,0x76,0x69, - 0x63,0x65,0x73,0x20,0x66,0x6F,0x72,0x20,0x41,0x6B,0x61,0x6D,0x61,0x69,0x31,0x16, - 0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x77,0x77,0x77,0x2E,0x61,0x70,0x70, - 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86, - 0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82, - 0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xED,0x5E,0x5D,0xC6,0x85,0xBE,0xE5,0x2A,0x78, - 0x7A,0x1F,0x77,0x1F,0x42,0x17,0xEA,0xC1,0xE3,0x75,0xAE,0xC9,0x38,0x7A,0xE0,0xCF, - 0x9F,0xEB,0xBA,0x47,0x42,0xCF,0x63,0x75,0x26,0xD3,0x4C,0x8E,0x6C,0x2F,0xC7,0xBC, - 0x1C,0xBB,0x37,0xC9,0xA5,0xA0,0xD3,0x8F,0xEA,0x3D,0x02,0xC8,0xE8,0x06,0xA1,0xA7, - 0x2B,0x4C,0x7B,0x91,0x55,0xBC,0x51,0xAB,0xE7,0xC8,0xB8,0xA8,0xA6,0x49,0x3E,0x94, - 0x45,0xF1,0x00,0x90,0x26,0xB9,0xB5,0xAF,0xB5,0xA0,0x22,0x41,0x2C,0x10,0x52,0x8B, - 0xD9,0xF0,0x91,0xE5,0x40,0x76,0x60,0xFD,0xC2,0xB1,0xFE,0xD0,0x55,0xC3,0x4F,0x18, - 0x7D,0x20,0x00,0x0C,0x8B,0x41,0x2C,0x2D,0xC1,0x0A,0xC0,0xE1,0x2E,0xDE,0xF8,0x47, - 0x84,0xB2,0x36,0x4E,0x03,0x5F,0x77,0x90,0xF6,0xF5,0x60,0xD8,0xAA,0x25,0x10,0xEB, - 0x37,0x38,0x03,0x7F,0x4B,0x46,0x36,0x76,0x2E,0x66,0xFE,0x18,0xE4,0x9B,0x31,0xEC, - 0xD5,0x2A,0xDB,0x60,0x90,0xD7,0xA0,0xD5,0xAB,0x79,0x9C,0x01,0xF6,0xAC,0x87,0x88, - 0x73,0x43,0x08,0xE0,0x48,0xF0,0x09,0xAC,0x41,0x40,0x60,0xE4,0x9C,0xA7,0xCC,0xBD, - 0x2F,0xC7,0x5D,0x32,0x32,0x2E,0x42,0xD7,0x69,0x2F,0x46,0x30,0xD3,0x6E,0x17,0xBA, - 0x1C,0xA6,0xBA,0xBC,0xB5,0x62,0x53,0x89,0xC7,0x4A,0xEF,0xB9,0xF8,0x0F,0x25,0x2F, - 0xB4,0x7A,0x5C,0x05,0xFB,0xE4,0xFD,0x13,0x47,0x1B,0xFF,0x60,0x6F,0x40,0xF2,0x0F, - 0x2D,0x53,0x38,0x3F,0x21,0x87,0x4D,0x08,0xB1,0x1B,0xD3,0xDA,0xAB,0xD5,0x9E,0x94, - 0x69,0x43,0xA3,0xA2,0x5E,0xF1,0xE9,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x03,0x01, - 0x30,0x82,0x02,0xFD,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80, - 0x14,0x3D,0xD3,0x50,0xA5,0xD6,0xA0,0xAD,0xEE,0xF3,0x4A,0x60,0x0A,0x65,0xD3,0x21, - 0xD4,0xF8,0xF8,0xD6,0x0F,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, - 0xD8,0xF5,0xFF,0x6D,0xDC,0x96,0x30,0x5C,0xAD,0x80,0x75,0xFF,0xCE,0xC5,0xF7,0x9D, - 0x16,0x73,0xCB,0x16,0x30,0x2A,0x06,0x03,0x55,0x1D,0x11,0x04,0x23,0x30,0x21,0x82, - 0x10,0x69,0x6D,0x61,0x67,0x65,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, - 0x6D,0x82,0x0D,0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, - 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01, - 0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30, - 0x75,0x06,0x03,0x55,0x1D,0x1F,0x04,0x6E,0x30,0x6C,0x30,0x34,0xA0,0x32,0xA0,0x30, - 0x86,0x2E,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x33,0x2E,0x64,0x69, - 0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x68,0x61,0x32,0x2D, - 0x65,0x76,0x2D,0x73,0x65,0x72,0x76,0x65,0x72,0x2D,0x67,0x32,0x2E,0x63,0x72,0x6C, - 0x30,0x34,0xA0,0x32,0xA0,0x30,0x86,0x2E,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63, - 0x72,0x6C,0x34,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D, - 0x2F,0x73,0x68,0x61,0x32,0x2D,0x65,0x76,0x2D,0x73,0x65,0x72,0x76,0x65,0x72,0x2D, - 0x67,0x32,0x2E,0x63,0x72,0x6C,0x30,0x4B,0x06,0x03,0x55,0x1D,0x20,0x04,0x44,0x30, - 0x42,0x30,0x37,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xFD,0x6C,0x02,0x01,0x30,0x2A, - 0x30,0x28,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74, - 0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65, - 0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x07,0x06,0x05,0x67,0x81, - 0x0C,0x01,0x01,0x30,0x81,0x88,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, - 0x04,0x7C,0x30,0x7A,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, - 0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69, - 0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x52,0x06,0x08,0x2B,0x06, - 0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63, - 0x61,0x63,0x65,0x72,0x74,0x73,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E, - 0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x53,0x48,0x41,0x32, - 0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69, - 0x6F,0x6E,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x09, - 0x06,0x03,0x55,0x1D,0x13,0x04,0x02,0x30,0x00,0x30,0x82,0x01,0x04,0x06,0x0A,0x2B, - 0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02,0x04,0x81,0xF5,0x04,0x81,0xF2,0x00, - 0xF0,0x00,0x76,0x00,0xBB,0xD9,0xDF,0xBC,0x1F,0x8A,0x71,0xB5,0x93,0x94,0x23,0x97, - 0xAA,0x92,0x7B,0x47,0x38,0x57,0x95,0x0A,0xAB,0x52,0xE8,0x1A,0x90,0x96,0x64,0x36, - 0x8E,0x1E,0xD1,0x85,0x00,0x00,0x01,0x69,0x58,0x42,0xD1,0x06,0x00,0x00,0x04,0x03, - 0x00,0x47,0x30,0x45,0x02,0x20,0x68,0x81,0x0C,0x54,0x88,0x45,0x7A,0xC6,0x84,0xB8, - 0x65,0x9B,0xFD,0x9C,0x34,0x80,0xF6,0x38,0x91,0xEF,0xCF,0x58,0xF9,0xFD,0xF3,0x50, - 0x6F,0xAD,0x8E,0xA0,0xAD,0xE8,0x02,0x21,0x00,0xCE,0x32,0x9D,0x5B,0x3D,0xA2,0x8B, - 0xB6,0x04,0x48,0xEE,0x01,0x26,0x6C,0xD3,0x50,0xA1,0xEA,0x7F,0x25,0x0C,0x00,0x2A, - 0x42,0x6D,0x42,0x0D,0x13,0xC0,0xA9,0x85,0xBC,0x00,0x76,0x00,0x56,0x14,0x06,0x9A, - 0x2F,0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC, - 0x99,0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x69, - 0x58,0x42,0xD1,0x44,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x4B,0xD4, - 0x64,0x52,0xD3,0x52,0xF0,0x3E,0xD8,0xD4,0x3D,0xC5,0x40,0x72,0xED,0xC3,0x04,0x8C, - 0x3C,0x16,0x46,0x5D,0x38,0x02,0xBA,0xA2,0x1E,0x52,0xAA,0xE1,0xDA,0xB6,0x02,0x21, - 0x00,0xA3,0x5E,0x2F,0x6B,0xCC,0xB9,0x34,0xD9,0xA4,0x00,0x70,0xE1,0x3A,0x99,0xB4, - 0x0D,0x25,0x6D,0xD3,0x59,0x77,0xC2,0x98,0x8C,0x6A,0xA0,0xAE,0xA7,0xE1,0x06,0x73, - 0x32,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, - 0x03,0x82,0x01,0x01,0x00,0x3F,0xD9,0xA1,0x19,0xB3,0x7C,0x56,0xA5,0x89,0xE5,0xA2, - 0x33,0x33,0xE3,0xFC,0xBB,0x29,0xDB,0xD7,0x69,0x76,0x31,0x2F,0x69,0x97,0x90,0xA1, - 0x0C,0x11,0x0B,0x5A,0xCB,0xAB,0x41,0x66,0xB2,0x9B,0xDF,0x71,0xD6,0xDC,0x92,0x91, - 0xB6,0x17,0x8B,0xD3,0x9C,0x83,0x3C,0xDC,0x7C,0xA7,0x29,0x5D,0xBA,0x38,0x97,0x9B, - 0x0D,0x07,0xE0,0x46,0xCA,0x27,0x5F,0x41,0xA0,0xC0,0x84,0x1E,0x47,0x00,0xDC,0x87, - 0x79,0xFD,0xAF,0x3E,0x34,0xC2,0x6D,0xB1,0x47,0x0C,0x52,0x14,0x81,0xAC,0xB2,0x6C, - 0xB4,0x30,0xB2,0x41,0x61,0x77,0x07,0x96,0x05,0x5B,0x26,0x36,0xA2,0x94,0xC2,0x70, - 0xC3,0xCD,0xC1,0x15,0xAC,0x33,0x0D,0x60,0x68,0xFA,0x19,0x95,0x3E,0x28,0x14,0xDE, - 0x19,0x15,0xF2,0x4B,0x43,0xAB,0x00,0xBF,0x54,0xE3,0xAF,0x5A,0x29,0x0F,0x32,0xCB, - 0xCC,0xBE,0x7F,0x07,0x30,0xF6,0xD9,0x49,0xE6,0x27,0x1F,0xC0,0x3B,0x9C,0x3D,0x2E, - 0xD1,0x6C,0xC5,0xB6,0x0E,0x8D,0x17,0xDC,0x48,0x5C,0x1F,0xC1,0x7E,0x4B,0xBA,0x8C, - 0x43,0xCA,0xAF,0x99,0x76,0x88,0x9B,0xA4,0x68,0x60,0xFA,0xC2,0xD3,0x87,0xEF,0x39, - 0x16,0x8C,0x49,0x36,0x2C,0x09,0xF9,0x07,0x2A,0x2E,0x7B,0x61,0x3E,0x76,0x76,0xEF, - 0x74,0x96,0xA5,0xAE,0xFF,0x6B,0x4C,0xF7,0x7F,0x96,0x41,0xBE,0x9C,0x09,0x41,0xBA, - 0x8A,0x1C,0xFD,0xC2,0x4A,0xE1,0x0A,0xA8,0x7E,0x7B,0xA8,0x98,0xA8,0x01,0x5D,0xAB, - 0xEF,0xDB,0x36,0xB3,0xE6,0x93,0x5D,0x27,0x0C,0x26,0xC3,0x33,0x93,0x74,0xAF,0x79, - 0x81,0xE5,0xD4,0x46,0x4E, -}; - -/* subject:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA */ -static const uint8_t _ocsp_c1[]= { - 0x30,0x82,0x04,0xB6,0x30,0x82,0x03,0x9E,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x0C, - 0x79,0xA9,0x44,0xB0,0x8C,0x11,0x95,0x20,0x92,0x61,0x5F,0xE2,0x6B,0x1D,0x83,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6C, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63, - 0x65,0x20,0x45,0x56,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, - 0x31,0x33,0x31,0x30,0x32,0x32,0x31,0x32,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32, - 0x38,0x31,0x30,0x32,0x32,0x31,0x32,0x30,0x30,0x30,0x30,0x5A,0x30,0x75,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x20,0x49, - 0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77,0x77,0x77, - 0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31,0x34,0x30, - 0x32,0x06,0x03,0x55,0x04,0x03,0x13,0x2B,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x53,0x48,0x41,0x32,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56, - 0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x72,0x76,0x65,0x72, - 0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, - 0x82,0x01,0x01,0x00,0xD7,0x53,0xA4,0x04,0x51,0xF8,0x99,0xA6,0x16,0x48,0x4B,0x67, - 0x27,0xAA,0x93,0x49,0xD0,0x39,0xED,0x0C,0xB0,0xB0,0x00,0x87,0xF1,0x67,0x28,0x86, - 0x85,0x8C,0x8E,0x63,0xDA,0xBC,0xB1,0x40,0x38,0xE2,0xD3,0xF5,0xEC,0xA5,0x05,0x18, - 0xB8,0x3D,0x3E,0xC5,0x99,0x17,0x32,0xEC,0x18,0x8C,0xFA,0xF1,0x0C,0xA6,0x64,0x21, - 0x85,0xCB,0x07,0x10,0x34,0xB0,0x52,0x88,0x2B,0x1F,0x68,0x9B,0xD2,0xB1,0x8F,0x12, - 0xB0,0xB3,0xD2,0xE7,0x88,0x1F,0x1F,0xEF,0x38,0x77,0x54,0x53,0x5F,0x80,0x79,0x3F, - 0x2E,0x1A,0xAA,0xA8,0x1E,0x4B,0x2B,0x0D,0xAB,0xB7,0x63,0xB9,0x35,0xB7,0x7D,0x14, - 0xBC,0x59,0x4B,0xDF,0x51,0x4A,0xD2,0xA1,0xE2,0x0C,0xE2,0x90,0x82,0x87,0x6A,0xAE, - 0xEA,0xD7,0x64,0xD6,0x98,0x55,0xE8,0xFD,0xAF,0x1A,0x50,0x6C,0x54,0xBC,0x11,0xF2, - 0xFD,0x4A,0xF2,0x9D,0xBB,0x7F,0x0E,0xF4,0xD5,0xBE,0x8E,0x16,0x89,0x12,0x55,0xD8, - 0xC0,0x71,0x34,0xEE,0xF6,0xDC,0x2D,0xEC,0xC4,0x87,0x25,0x86,0x8D,0xD8,0x21,0xE4, - 0xB0,0x4D,0x0C,0x89,0xDC,0x39,0x26,0x17,0xDD,0xF6,0xD7,0x94,0x85,0xD8,0x04,0x21, - 0x70,0x9D,0x6F,0x6F,0xFF,0x5C,0xBA,0x19,0xE1,0x45,0xCB,0x56,0x57,0x28,0x7E,0x1C, - 0x0D,0x41,0x57,0xAA,0xB7,0xB8,0x27,0xBB,0xB1,0xE4,0xFA,0x2A,0xEF,0x21,0x23,0x75, - 0x1A,0xAD,0x2D,0x9B,0x86,0x35,0x8C,0x9C,0x77,0xB5,0x73,0xAD,0xD8,0x94,0x2D,0xE4, - 0xF3,0x0C,0x9D,0xEE,0xC1,0x4E,0x62,0x7E,0x17,0xC0,0x71,0x9E,0x2C,0xDE,0xF1,0xF9, - 0x10,0x28,0x19,0x33,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x49,0x30,0x82,0x01, - 0x45,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01, - 0x01,0xFF,0x02,0x01,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, - 0x04,0x03,0x02,0x01,0x86,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x03,0x02,0x30,0x34,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, - 0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, - 0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69, - 0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x4B,0x06,0x03,0x55,0x1D, - 0x1F,0x04,0x44,0x30,0x42,0x30,0x40,0xA0,0x3E,0xA0,0x3C,0x86,0x3A,0x68,0x74,0x74, - 0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x34,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72, - 0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x48,0x69, - 0x67,0x68,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63,0x65,0x45,0x56,0x52,0x6F,0x6F, - 0x74,0x43,0x41,0x2E,0x63,0x72,0x6C,0x30,0x3D,0x06,0x03,0x55,0x1D,0x20,0x04,0x36, - 0x30,0x34,0x30,0x32,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x2A,0x30,0x28,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70,0x73,0x3A, - 0x2F,0x2F,0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63, - 0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, - 0x14,0x3D,0xD3,0x50,0xA5,0xD6,0xA0,0xAD,0xEE,0xF3,0x4A,0x60,0x0A,0x65,0xD3,0x21, - 0xD4,0xF8,0xF8,0xD6,0x0F,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, - 0x80,0x14,0xB1,0x3E,0xC3,0x69,0x03,0xF8,0xBF,0x47,0x01,0xD4,0x98,0x26,0x1A,0x08, - 0x02,0xEF,0x63,0x64,0x2B,0xC3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x9D,0xB6,0xD0,0x90,0x86,0xE1, - 0x86,0x02,0xED,0xC5,0xA0,0xF0,0x34,0x1C,0x74,0xC1,0x8D,0x76,0xCC,0x86,0x0A,0xA8, - 0xF0,0x4A,0x8A,0x42,0xD6,0x3F,0xC8,0xA9,0x4D,0xAD,0x7C,0x08,0xAD,0xE6,0xB6,0x50, - 0xB8,0xA2,0x1A,0x4D,0x88,0x07,0xB1,0x29,0x21,0xDC,0xE7,0xDA,0xC6,0x3C,0x21,0xE0, - 0xE3,0x11,0x49,0x70,0xAC,0x7A,0x1D,0x01,0xA4,0xCA,0x11,0x3A,0x57,0xAB,0x7D,0x57, - 0x2A,0x40,0x74,0xFD,0xD3,0x1D,0x85,0x18,0x50,0xDF,0x57,0x47,0x75,0xA1,0x7D,0x55, - 0x20,0x2E,0x47,0x37,0x50,0x72,0x8C,0x7F,0x82,0x1B,0xD2,0x62,0x8F,0x2D,0x03,0x5A, - 0xDA,0xC3,0xC8,0xA1,0xCE,0x2C,0x52,0xA2,0x00,0x63,0xEB,0x73,0xBA,0x71,0xC8,0x49, - 0x27,0x23,0x97,0x64,0x85,0x9E,0x38,0x0E,0xAD,0x63,0x68,0x3C,0xBA,0x52,0x81,0x58, - 0x79,0xA3,0x2C,0x0C,0xDF,0xDE,0x6D,0xEB,0x31,0xF2,0xBA,0xA0,0x7C,0x6C,0xF1,0x2C, - 0xD4,0xE1,0xBD,0x77,0x84,0x37,0x03,0xCE,0x32,0xB5,0xC8,0x9A,0x81,0x1A,0x4A,0x92, - 0x4E,0x3B,0x46,0x9A,0x85,0xFE,0x83,0xA2,0xF9,0x9E,0x8C,0xA3,0xCC,0x0D,0x5E,0xB3, - 0x3D,0xCF,0x04,0x78,0x8F,0x14,0x14,0x7B,0x32,0x9C,0xC7,0x00,0xA6,0x5C,0xC4,0xB5, - 0xA1,0x55,0x8D,0x5A,0x56,0x68,0xA4,0x22,0x70,0xAA,0x3C,0x81,0x71,0xD9,0x9D,0xA8, - 0x45,0x3B,0xF4,0xE5,0xF6,0xA2,0x51,0xDD,0xC7,0x7B,0x62,0xE8,0x6F,0x0C,0x74,0xEB, - 0xB8,0xDA,0xF8,0xBF,0x87,0x0D,0x79,0x50,0x91,0x90,0x9B,0x18,0x3B,0x91,0x59,0x27, - 0xF1,0x35,0x28,0x13,0xAB,0x26,0x7E,0xD5,0xF7,0x7A, -}; - -/* subject:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA */ -static const uint8_t _ocsp_c2[]= { - 0x30,0x82,0x03,0xC5,0x30,0x82,0x02,0xAD,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x02, - 0xAC,0x5C,0x26,0x6A,0x0B,0x40,0x9B,0x8F,0x0B,0x79,0xF2,0xAE,0x46,0x25,0x77,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x6C, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63, - 0x65,0x20,0x45,0x56,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, - 0x30,0x36,0x31,0x31,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x33, - 0x31,0x31,0x31,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x6C,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x20,0x49, - 0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77,0x77,0x77, - 0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31,0x2B,0x30, - 0x29,0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63,0x65,0x20, - 0x45,0x56,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D, - 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01, - 0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC6,0xCC,0xE5,0x73,0xE6, - 0xFB,0xD4,0xBB,0xE5,0x2D,0x2D,0x32,0xA6,0xDF,0xE5,0x81,0x3F,0xC9,0xCD,0x25,0x49, - 0xB6,0x71,0x2A,0xC3,0xD5,0x94,0x34,0x67,0xA2,0x0A,0x1C,0xB0,0x5F,0x69,0xA6,0x40, - 0xB1,0xC4,0xB7,0xB2,0x8F,0xD0,0x98,0xA4,0xA9,0x41,0x59,0x3A,0xD3,0xDC,0x94,0xD6, - 0x3C,0xDB,0x74,0x38,0xA4,0x4A,0xCC,0x4D,0x25,0x82,0xF7,0x4A,0xA5,0x53,0x12,0x38, - 0xEE,0xF3,0x49,0x6D,0x71,0x91,0x7E,0x63,0xB6,0xAB,0xA6,0x5F,0xC3,0xA4,0x84,0xF8, - 0x4F,0x62,0x51,0xBE,0xF8,0xC5,0xEC,0xDB,0x38,0x92,0xE3,0x06,0xE5,0x08,0x91,0x0C, - 0xC4,0x28,0x41,0x55,0xFB,0xCB,0x5A,0x89,0x15,0x7E,0x71,0xE8,0x35,0xBF,0x4D,0x72, - 0x09,0x3D,0xBE,0x3A,0x38,0x50,0x5B,0x77,0x31,0x1B,0x8D,0xB3,0xC7,0x24,0x45,0x9A, - 0xA7,0xAC,0x6D,0x00,0x14,0x5A,0x04,0xB7,0xBA,0x13,0xEB,0x51,0x0A,0x98,0x41,0x41, - 0x22,0x4E,0x65,0x61,0x87,0x81,0x41,0x50,0xA6,0x79,0x5C,0x89,0xDE,0x19,0x4A,0x57, - 0xD5,0x2E,0xE6,0x5D,0x1C,0x53,0x2C,0x7E,0x98,0xCD,0x1A,0x06,0x16,0xA4,0x68,0x73, - 0xD0,0x34,0x04,0x13,0x5C,0xA1,0x71,0xD3,0x5A,0x7C,0x55,0xDB,0x5E,0x64,0xE1,0x37, - 0x87,0x30,0x56,0x04,0xE5,0x11,0xB4,0x29,0x80,0x12,0xF1,0x79,0x39,0x88,0xA2,0x02, - 0x11,0x7C,0x27,0x66,0xB7,0x88,0xB7,0x78,0xF2,0xCA,0x0A,0xA8,0x38,0xAB,0x0A,0x64, - 0xC2,0xBF,0x66,0x5D,0x95,0x84,0xC1,0xA1,0x25,0x1E,0x87,0x5D,0x1A,0x50,0x0B,0x20, - 0x12,0xCC,0x41,0xBB,0x6E,0x0B,0x51,0x38,0xB8,0x4B,0xCB,0x02,0x03,0x01,0x00,0x01, - 0xA3,0x63,0x30,0x61,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, - 0x03,0x02,0x01,0x86,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05, - 0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, - 0xB1,0x3E,0xC3,0x69,0x03,0xF8,0xBF,0x47,0x01,0xD4,0x98,0x26,0x1A,0x08,0x02,0xEF, - 0x63,0x64,0x2B,0xC3,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80, - 0x14,0xB1,0x3E,0xC3,0x69,0x03,0xF8,0xBF,0x47,0x01,0xD4,0x98,0x26,0x1A,0x08,0x02, - 0xEF,0x63,0x64,0x2B,0xC3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, - 0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x1C,0x1A,0x06,0x97,0xDC,0xD7,0x9C, - 0x9F,0x3C,0x88,0x66,0x06,0x08,0x57,0x21,0xDB,0x21,0x47,0xF8,0x2A,0x67,0xAA,0xBF, - 0x18,0x32,0x76,0x40,0x10,0x57,0xC1,0x8A,0xF3,0x7A,0xD9,0x11,0x65,0x8E,0x35,0xFA, - 0x9E,0xFC,0x45,0xB5,0x9E,0xD9,0x4C,0x31,0x4B,0xB8,0x91,0xE8,0x43,0x2C,0x8E,0xB3, - 0x78,0xCE,0xDB,0xE3,0x53,0x79,0x71,0xD6,0xE5,0x21,0x94,0x01,0xDA,0x55,0x87,0x9A, - 0x24,0x64,0xF6,0x8A,0x66,0xCC,0xDE,0x9C,0x37,0xCD,0xA8,0x34,0xB1,0x69,0x9B,0x23, - 0xC8,0x9E,0x78,0x22,0x2B,0x70,0x43,0xE3,0x55,0x47,0x31,0x61,0x19,0xEF,0x58,0xC5, - 0x85,0x2F,0x4E,0x30,0xF6,0xA0,0x31,0x16,0x23,0xC8,0xE7,0xE2,0x65,0x16,0x33,0xCB, - 0xBF,0x1A,0x1B,0xA0,0x3D,0xF8,0xCA,0x5E,0x8B,0x31,0x8B,0x60,0x08,0x89,0x2D,0x0C, - 0x06,0x5C,0x52,0xB7,0xC4,0xF9,0x0A,0x98,0xD1,0x15,0x5F,0x9F,0x12,0xBE,0x7C,0x36, - 0x63,0x38,0xBD,0x44,0xA4,0x7F,0xE4,0x26,0x2B,0x0A,0xC4,0x97,0x69,0x0D,0xE9,0x8C, - 0xE2,0xC0,0x10,0x57,0xB8,0xC8,0x76,0x12,0x91,0x55,0xF2,0x48,0x69,0xD8,0xBC,0x2A, - 0x02,0x5B,0x0F,0x44,0xD4,0x20,0x31,0xDB,0xF4,0xBA,0x70,0x26,0x5D,0x90,0x60,0x9E, - 0xBC,0x4B,0x17,0x09,0x2F,0xB4,0xCB,0x1E,0x43,0x68,0xC9,0x07,0x27,0xC1,0xD2,0x5C, - 0xF7,0xEA,0x21,0xB9,0x68,0x12,0x9C,0x3C,0x9C,0xBF,0x9E,0xFC,0x80,0x5C,0x9B,0x63, - 0xCD,0xEC,0x47,0xAA,0x25,0x27,0x67,0xA0,0x37,0xF3,0x00,0x82,0x7D,0x54,0xD7,0xA9, - 0xF8,0xE9,0x2E,0x13,0xA3,0x77,0xE8,0x1F,0x4A, -}; - -/* subject:/CN=Apple IST CA 2 OCSP Responder NL01/O=Apple Inc./C=US */ -/* issuer :/CN=Apple IST CA 2 - G1/OU=Certification Authority/O=Apple Inc./C=US */ -static const uint8_t _responderCert[]= { - 0x30,0x82,0x03,0xBB,0x30,0x82,0x02,0xA3,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x5B, - 0x1B,0xA7,0xF8,0x9D,0xF4,0x7B,0x7C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04, - 0x03,0x13,0x13,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20, - 0x32,0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13, - 0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, - 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x38, - 0x30,0x38,0x31,0x31,0x30,0x30,0x34,0x36,0x35,0x33,0x5A,0x17,0x0D,0x31,0x38,0x30, - 0x39,0x32,0x32,0x30,0x30,0x34,0x36,0x35,0x33,0x5A,0x30,0x4F,0x31,0x2B,0x30,0x29, - 0x06,0x03,0x55,0x04,0x03,0x0C,0x22,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54, - 0x20,0x43,0x41,0x20,0x32,0x20,0x4F,0x43,0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6F, - 0x6E,0x64,0x65,0x72,0x20,0x4E,0x4C,0x30,0x31,0x31,0x13,0x30,0x11,0x06,0x03,0x55, - 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, - 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xA5,0x35,0xB2,0xC4, - 0xF2,0xAB,0x4C,0xFE,0xAA,0x5D,0xC7,0x23,0x52,0x68,0x42,0xC7,0x77,0x27,0x78,0x4E, - 0x80,0xFD,0x06,0xA3,0x51,0xA2,0x4F,0xF7,0x7A,0xD0,0x19,0x78,0xFD,0xEA,0x94,0xD8, - 0xE3,0x0C,0x3C,0x50,0x17,0x30,0xDB,0x84,0x38,0x13,0xE1,0xCF,0x6C,0xA0,0x1F,0x01, - 0xC7,0x12,0xC7,0x96,0x64,0x09,0x45,0x2F,0xA2,0x83,0xFE,0x4E,0x2C,0xF2,0x39,0x6F, - 0x20,0x34,0x6D,0xEC,0xBE,0xF9,0x86,0xA3,0xEF,0x40,0x1B,0x61,0x2D,0xE1,0xA4,0xB9, - 0xD4,0x3E,0x8E,0x65,0x7B,0x2F,0x26,0xD5,0x54,0xA6,0x12,0xC7,0x50,0xC8,0x89,0x94, - 0x86,0xFA,0x41,0x48,0xCF,0xE2,0xF1,0xF8,0xF2,0x0E,0xCC,0x25,0x43,0x0C,0x66,0x85, - 0xDC,0x88,0xA0,0x76,0x90,0x45,0xFC,0x4E,0x95,0x8F,0xA2,0x17,0x2F,0xAF,0x7C,0x41, - 0x59,0xA0,0xA1,0x36,0x98,0x18,0x20,0x4D,0x07,0xF5,0x7F,0xD1,0x66,0x65,0xC6,0x74, - 0xEA,0xBE,0xB8,0x20,0x88,0x29,0x27,0x5D,0x06,0x55,0xD0,0xB2,0x11,0xAF,0x52,0x58, - 0xD1,0x8A,0x57,0x6E,0x85,0x8D,0x0C,0xBD,0x6A,0xD3,0x87,0x09,0xF6,0x0F,0x07,0x7B, - 0x5C,0x8F,0x96,0x16,0xB5,0x89,0xB7,0x63,0xC4,0x33,0xDA,0x67,0x63,0xA3,0xC4,0x4B, - 0x73,0xEF,0x57,0x96,0x4F,0x15,0x2F,0x1B,0xF7,0x8E,0x35,0x24,0x18,0x68,0x87,0x16, - 0x0A,0x76,0x71,0x8B,0x94,0x11,0xB9,0xCC,0x02,0x97,0x2D,0x6F,0x94,0x00,0x1A,0x31, - 0xA6,0x9A,0x6B,0x4A,0xD3,0x64,0xB0,0x0F,0xA2,0xB0,0x5E,0xC0,0x2A,0x13,0xD6,0x7C, - 0x90,0xA6,0x5C,0xEE,0x7F,0x78,0xCA,0x7F,0x62,0x2F,0xF9,0x47,0x02,0x03,0x01,0x00, - 0x01,0xA3,0x81,0x87,0x30,0x81,0x84,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, - 0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, - 0x80,0x14,0xD8,0x7A,0x94,0x44,0x7C,0x90,0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C,0x01, - 0x44,0x03,0x86,0xD6,0x2A,0x29,0x30,0x0F,0x06,0x09,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x30,0x01,0x05,0x04,0x02,0x05,0x00,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C, - 0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x09,0x30,0x1D,0x06,0x03, - 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x75,0xDB,0x74,0x13,0x4A,0xCB,0xCB,0x5A,0x6B, - 0x78,0x40,0x5A,0x81,0x67,0x42,0xA5,0xD9,0xD0,0x4E,0x38,0x30,0x0E,0x06,0x03,0x55, - 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x0D,0x06,0x09,0x2A, - 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x3A, - 0x7E,0x84,0xE2,0x58,0xED,0x07,0xDD,0xE5,0xBD,0x5E,0x88,0x55,0x06,0x23,0x16,0x20, - 0xD1,0x85,0x89,0x60,0x83,0x19,0x21,0x04,0x9C,0x57,0xFE,0x91,0x30,0xBD,0x7C,0x83, - 0x45,0xA3,0xA1,0x11,0x0A,0x29,0xCF,0x6C,0x55,0x47,0xC3,0x7B,0x8C,0xEE,0x43,0xFE, - 0x42,0x0F,0xE6,0xCE,0xC7,0x24,0xAF,0x21,0x2E,0xC7,0xFD,0xFA,0xBA,0x7E,0xCE,0xA3, - 0x9D,0x92,0x5B,0x54,0x4C,0x4F,0x14,0x55,0xD6,0x5F,0xB0,0xB0,0x73,0xFD,0x78,0x61, - 0xDC,0xF6,0xA1,0xB6,0xFF,0xAF,0x3B,0x49,0x6F,0x62,0x95,0xD0,0x4E,0xA9,0x3F,0xE8, - 0x5C,0xCD,0x36,0xEA,0xED,0x57,0x04,0x32,0xB6,0xB0,0x91,0xDC,0x32,0xA6,0xC7,0x84, - 0x9C,0x3F,0x24,0x3A,0x64,0x56,0x62,0xA2,0x02,0x15,0xC9,0x63,0x96,0x8E,0x6C,0xF5, - 0x3E,0xB1,0xE4,0x3C,0x79,0x63,0xE0,0x94,0xE8,0xD0,0x73,0x31,0x7B,0x3C,0x99,0x66, - 0x82,0x2D,0x47,0x49,0x22,0x33,0xD4,0xD1,0x80,0x35,0xF1,0xB1,0xFD,0x01,0x92,0x07, - 0x6B,0x1E,0xF1,0xD0,0x02,0x84,0x24,0xD6,0xDF,0x2F,0x10,0x06,0x0F,0x36,0x5D,0x4B, - 0x1A,0xE3,0xDB,0x1F,0x8C,0x54,0x07,0x63,0x41,0x9E,0x74,0x6E,0x6F,0x9D,0xCE,0xCC, - 0x36,0x7B,0xE0,0xC5,0xCB,0x04,0x12,0xFF,0xF3,0x09,0xD7,0x36,0x5D,0x09,0xD0,0xCD, - 0xF2,0x73,0xAA,0x10,0x5D,0x0D,0xC2,0x12,0x21,0x00,0x89,0xE5,0x34,0x17,0x6C,0x76, - 0xE2,0x2F,0xDA,0xBD,0xCA,0xFB,0x9D,0xF2,0x1C,0x3B,0x62,0xCA,0xC0,0x97,0x82,0x54, - 0x92,0x4E,0x0C,0xD0,0x3B,0x79,0xD0,0x41,0x29,0x84,0xF5,0x75,0x40,0xB4,0xE8, -}; - -/* subject:/serialNumber=424761419/jurisdictionC=FR/businessCategory=Private Organization/C=FR/postalCode=59100/ST=Nord/L=Roubaix/street=2 rue Kellermann/O=OVH SAS/OU=IT/OU=COMODO EV SSL/CN=ovh.com */ -/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ -static unsigned char ovh_certificate[1884]={ - 0x30,0x82,0x07,0x58,0x30,0x82,0x06,0x40,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x40, - 0x46,0x47,0xDC,0xC2,0x4B,0x04,0x42,0xD4,0x89,0x8D,0x08,0x4D,0x4B,0xC2,0x01,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81, - 0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, - 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, - 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, - 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, - 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, - 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55, - 0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45, - 0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69, - 0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, - 0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x37,0x30,0x34,0x32,0x38,0x30,0x30,0x30, - 0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x39,0x30,0x34,0x32,0x38,0x32,0x33,0x35,0x39, - 0x35,0x39,0x5A,0x30,0x81,0xEA,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x05,0x13, - 0x09,0x34,0x32,0x34,0x37,0x36,0x31,0x34,0x31,0x39,0x31,0x13,0x30,0x11,0x06,0x0B, - 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,0x13,0x02,0x46,0x52,0x31, - 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0F,0x13,0x14,0x50,0x72,0x69,0x76,0x61,0x74, - 0x65,0x20,0x4F,0x72,0x67,0x61,0x6E,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x46,0x52,0x31,0x0E,0x30,0x0C,0x06, - 0x03,0x55,0x04,0x11,0x13,0x05,0x35,0x39,0x31,0x30,0x30,0x31,0x0D,0x30,0x0B,0x06, - 0x03,0x55,0x04,0x08,0x13,0x04,0x4E,0x6F,0x72,0x64,0x31,0x10,0x30,0x0E,0x06,0x03, - 0x55,0x04,0x07,0x13,0x07,0x52,0x6F,0x75,0x62,0x61,0x69,0x78,0x31,0x19,0x30,0x17, - 0x06,0x03,0x55,0x04,0x09,0x13,0x10,0x32,0x20,0x72,0x75,0x65,0x20,0x4B,0x65,0x6C, - 0x6C,0x65,0x72,0x6D,0x61,0x6E,0x6E,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0A, - 0x13,0x07,0x4F,0x56,0x48,0x20,0x53,0x41,0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x02,0x49,0x54,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x0B,0x13, - 0x0D,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x45,0x56,0x20,0x53,0x53,0x4C,0x31,0x10, - 0x30,0x0E,0x06,0x03,0x55,0x04,0x03,0x13,0x07,0x6F,0x76,0x68,0x2E,0x63,0x6F,0x6D, - 0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, - 0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, - 0x00,0x93,0xA1,0x5D,0x05,0x5F,0x1A,0x26,0x56,0x3D,0xDC,0xC2,0x7C,0x1B,0xA1,0x7A, - 0x63,0x16,0x4F,0xBD,0xE0,0x77,0x85,0x04,0xB0,0x9B,0x49,0xE9,0x2B,0x5C,0xB1,0x51, - 0xFD,0x8A,0x14,0x51,0xC7,0xD9,0x50,0xDE,0x64,0x2F,0xFE,0x8C,0x27,0xC3,0x01,0x48, - 0x64,0x7C,0x85,0x3F,0x93,0xD4,0x09,0xE6,0x42,0xDF,0xC1,0xE4,0xEB,0x6A,0xC0,0x87, - 0x90,0xA5,0xF6,0x9C,0xD4,0x6B,0x08,0x77,0xFB,0x56,0x44,0x2B,0x8A,0xE0,0x05,0x73, - 0x14,0x6B,0x02,0x7D,0x76,0x44,0x7B,0x3E,0xA6,0xE5,0x23,0xA9,0xE1,0x8F,0x99,0xDD, - 0x15,0xCD,0xD9,0xD9,0x6D,0xB9,0x95,0x5B,0xE8,0xB6,0xE2,0x52,0xDD,0xF0,0xB0,0x80, - 0x1B,0xC1,0x95,0x4B,0x2C,0x9D,0x5E,0x8D,0x02,0x6B,0x59,0x6C,0x26,0x8B,0xC3,0x19, - 0x0D,0x3E,0xA8,0x34,0xD0,0x43,0x81,0xD7,0xBD,0xB3,0xA7,0x04,0xE1,0x05,0x82,0xA6, - 0x1F,0x4D,0x70,0x67,0x05,0x96,0x88,0xE8,0xE9,0x2E,0x95,0xD2,0x36,0x75,0xD6,0xC8, - 0x0C,0x59,0xBF,0x9F,0x1F,0x9F,0xB4,0xFF,0xF0,0x10,0x8C,0xC3,0xE6,0x8B,0x9F,0xE2, - 0x8E,0x00,0x60,0x58,0xCB,0x6F,0xAD,0x84,0x7B,0xA5,0x36,0xDB,0xB2,0xA4,0xEB,0xC6, - 0xC8,0xD8,0x61,0x6E,0x4A,0xDC,0x5C,0x3E,0x2C,0x33,0xCB,0x1E,0x16,0x8B,0x8C,0xA3, - 0x5F,0x0F,0x30,0x4E,0x0A,0x5D,0xA0,0x53,0x7C,0xCE,0xAB,0x29,0x9A,0xC6,0x64,0xC5, - 0x5A,0xD7,0x94,0x3D,0x81,0xB1,0x05,0x3F,0x2A,0x6D,0xD7,0xB8,0x9D,0xF1,0x6D,0x13, - 0xFD,0x82,0xB4,0xF9,0x88,0x77,0xAB,0xB8,0x2C,0x7A,0x81,0x6E,0x68,0xFF,0x6E,0x04, - 0xC1,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x03,0x4E,0x30,0x82,0x03,0x4A,0x30,0x1F, - 0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x39,0xDA,0xFF,0xCA,0x28, - 0x14,0x8A,0xA8,0x74,0x13,0x08,0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30, - 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x0B,0x0F,0xAD,0xA6,0xC3,0xBF, - 0x98,0xA1,0xEC,0xCD,0x20,0xB3,0x2C,0x75,0x03,0x56,0x3A,0xA6,0xD3,0xE6,0x30,0x0E, - 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x0C, - 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1D,0x06,0x03, - 0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03, - 0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55, - 0x1D,0x20,0x04,0x3F,0x30,0x3D,0x30,0x3B,0x06,0x0C,0x2B,0x06,0x01,0x04,0x01,0xB2, - 0x31,0x01,0x02,0x01,0x05,0x01,0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x02,0x01,0x16,0x1D,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65, - 0x63,0x75,0x72,0x65,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F, - 0x43,0x50,0x53,0x30,0x56,0x06,0x03,0x55,0x1D,0x1F,0x04,0x4F,0x30,0x4D,0x30,0x4B, - 0xA0,0x49,0xA0,0x47,0x86,0x45,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C, - 0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F, - 0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x56, - 0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x63,0x75,0x72,0x65,0x53, - 0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x6C,0x30,0x81,0x87,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x7B,0x30,0x79,0x30,0x51,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x45,0x68,0x74,0x74,0x70,0x3A,0x2F, - 0x2F,0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F, - 0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x45,0x78,0x74,0x65,0x6E, - 0x64,0x65,0x64,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x63, - 0x75,0x72,0x65,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x74,0x30, - 0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74, - 0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63, - 0x61,0x2E,0x63,0x6F,0x6D,0x30,0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16, - 0x82,0x07,0x6F,0x76,0x68,0x2E,0x63,0x6F,0x6D,0x82,0x0B,0x77,0x77,0x77,0x2E,0x6F, - 0x76,0x68,0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01,0x7E,0x06,0x0A,0x2B,0x06,0x01,0x04, - 0x01,0xD6,0x79,0x02,0x04,0x02,0x04,0x82,0x01,0x6E,0x04,0x82,0x01,0x6A,0x01,0x68, - 0x00,0x76,0x00,0xA4,0xB9,0x09,0x90,0xB4,0x18,0x58,0x14,0x87,0xBB,0x13,0xA2,0xCC, - 0x67,0x70,0x0A,0x3C,0x35,0x98,0x04,0xF9,0x1B,0xDF,0xB8,0xE3,0x77,0xCD,0x0E,0xC8, - 0x0D,0xDC,0x10,0x00,0x00,0x01,0x5B,0xB5,0x7B,0xC8,0x2D,0x00,0x00,0x04,0x03,0x00, - 0x47,0x30,0x45,0x02,0x21,0x00,0xD5,0x1B,0x6C,0xAE,0x75,0x46,0x62,0x0C,0x8B,0x2E, - 0x14,0xB1,0xDE,0x7C,0xA5,0xFE,0x5C,0x4F,0x3E,0xB0,0xFF,0xFF,0x33,0xA2,0x84,0x58, - 0x51,0x57,0x97,0x09,0xAF,0x09,0x02,0x20,0x49,0xD7,0x12,0x12,0x6C,0x2A,0x00,0x21, - 0x5E,0x48,0xF8,0xD0,0xF2,0xA5,0x81,0x2A,0x4E,0xE9,0x22,0x0A,0x4E,0x46,0x8F,0xDB, - 0xA5,0x9C,0x4B,0x43,0x7E,0x51,0x24,0xE4,0x00,0x76,0x00,0x56,0x14,0x06,0x9A,0x2F, - 0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC,0x99, - 0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x5B,0xB5, - 0x7B,0xC5,0xC8,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x36,0xA9,0x1D, - 0x52,0x63,0x04,0x11,0x1F,0x65,0xC6,0x97,0x7C,0x17,0xFC,0x17,0x8D,0xDB,0x9D,0xA7, - 0xB7,0x84,0x66,0x03,0x55,0x95,0x7D,0x42,0x39,0x98,0x60,0xDE,0x19,0x02,0x21,0x00, - 0x8B,0xB7,0x16,0xC0,0x20,0x17,0xBF,0x31,0x36,0xBD,0xBC,0x1C,0x12,0x61,0x42,0xC0, - 0x5C,0x19,0x97,0x0A,0xFA,0x85,0xDB,0x5D,0xC3,0x65,0xBE,0x18,0xBF,0x89,0x6F,0xB9, - 0x00,0x76,0x00,0xEE,0x4B,0xBD,0xB7,0x75,0xCE,0x60,0xBA,0xE1,0x42,0x69,0x1F,0xAB, - 0xE1,0x9E,0x66,0xA3,0x0F,0x7E,0x5F,0xB0,0x72,0xD8,0x83,0x00,0xC4,0x7B,0x89,0x7A, - 0xA8,0xFD,0xCB,0x00,0x00,0x01,0x5B,0xB5,0x7B,0xC7,0xFA,0x00,0x00,0x04,0x03,0x00, - 0x47,0x30,0x45,0x02,0x21,0x00,0xF8,0xFE,0x02,0xC9,0xAF,0x02,0x18,0xF4,0x12,0x00, - 0x39,0x3C,0x15,0xE0,0x9C,0x78,0x04,0x19,0x55,0xAE,0x8F,0xB4,0x22,0xB9,0x08,0x66, - 0x9E,0x21,0x3E,0xF0,0x7D,0xC6,0x02,0x20,0x47,0x45,0x31,0xC7,0x2C,0xC3,0xBE,0xC7, - 0x5B,0xD8,0x31,0x0A,0xD6,0xAF,0x9D,0xAF,0x04,0x45,0xAA,0x51,0x7D,0x43,0xEF,0x35, - 0x4D,0x81,0xB3,0x0A,0x2F,0x8D,0xD8,0x61,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6C,0x8E,0xB5,0x58, - 0x8A,0xC5,0x66,0xAC,0x99,0x68,0xF9,0x80,0x68,0x8E,0xC5,0x10,0xF7,0xD7,0x37,0x5E, - 0x09,0x8C,0x6B,0xCF,0x30,0x2B,0x98,0x3F,0x76,0x4D,0x69,0xBA,0xE8,0x61,0x1D,0xDE, - 0x1A,0x14,0x4F,0x5A,0x0B,0x54,0x0F,0x66,0xEF,0xB9,0xB3,0x51,0x6C,0x9B,0x86,0x1D, - 0xB9,0x13,0xC8,0x54,0x24,0x6C,0x82,0x6E,0x4B,0x3C,0x53,0xC7,0x7D,0x0B,0x40,0x4A, - 0x7E,0x23,0xF2,0x79,0x6B,0xC3,0xFF,0x9D,0xDF,0xC0,0x16,0x7B,0xFF,0x7B,0x04,0xC9, - 0xE0,0xEB,0x3F,0x28,0xC6,0xD2,0x79,0xEE,0xAE,0x7E,0x38,0x5F,0x0D,0xDF,0x71,0xE7, - 0xAA,0x38,0x7E,0xF3,0x28,0xE8,0xB2,0xAC,0x69,0xB9,0x69,0xD4,0x05,0x8E,0xF1,0x00, - 0x71,0x77,0x97,0x7F,0x94,0x36,0x45,0xE5,0x9C,0x15,0xA3,0xF1,0x40,0xD7,0xB5,0xEA, - 0x95,0x56,0x75,0x60,0x86,0xFB,0xCD,0xB7,0x81,0x5A,0x34,0x1A,0x83,0x1E,0xC2,0x50, - 0xA2,0x57,0x16,0x13,0x53,0x95,0xFA,0x95,0xD0,0x64,0x1E,0x09,0x45,0x50,0x05,0x63, - 0x3A,0x86,0xB2,0x1D,0x9B,0x19,0x0E,0x89,0x7E,0x75,0x17,0xDA,0xC5,0x4D,0x4F,0x71, - 0x55,0x82,0x3E,0x5F,0x41,0x25,0x2F,0x86,0x9E,0x3D,0xF1,0x32,0xFA,0x77,0x7C,0x30, - 0x6C,0x50,0x2F,0xE7,0x11,0x7B,0xE1,0x3F,0xA8,0x2E,0xEF,0xAC,0x36,0x94,0x8F,0xF0, - 0x92,0xB4,0xCA,0x1A,0x53,0x8E,0x12,0x26,0x48,0xC4,0xA8,0x25,0x19,0x96,0x19,0x11, - 0xA2,0xA2,0x48,0xEB,0x8C,0x12,0x59,0x7F,0xCE,0xFC,0x4B,0xC9,0x19,0x10,0x61,0x2B, - 0xB3,0xA6,0x6B,0xB4,0xBA,0x68,0xB9,0x22,0x58,0xE4,0x82,0x27, -}; - -/* This is the cert the ssl server returns to us. */ -/* subject:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ -/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority */ -static unsigned char comodo_ev_certificate[1554]={ - 0x30,0x82,0x06,0x0E,0x30,0x82,0x03,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x06, - 0xA7,0x43,0x80,0xD4,0xEB,0xFE,0xD4,0x35,0xB5,0xA3,0xF7,0xE1,0x6A,0xBD,0xD8,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x30,0x81, - 0x85,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, - 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, - 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, - 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, - 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, - 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x2B,0x30,0x29,0x06,0x03,0x55, - 0x04,0x03,0x13,0x22,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x43, - 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74, - 0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x31,0x32,0x30,0x32,0x31,0x32, - 0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x37,0x30,0x32,0x31,0x31,0x32, - 0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13, - 0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72,0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73, - 0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61, - 0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11, - 0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43,0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65, - 0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F, - 0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20, - 0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72, - 0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, - 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0x95,0x56,0xDE,0x54, - 0xB4,0xDF,0xD5,0x02,0x49,0x7B,0xD1,0x5B,0x5C,0xA2,0xB2,0x1E,0x8F,0x9C,0x2B,0x62, - 0x4C,0x2B,0x8D,0x12,0x28,0xF3,0x1A,0x95,0xA3,0xC6,0x10,0xFD,0x29,0xDE,0xE1,0x9F, - 0x0B,0x38,0x40,0x93,0xD1,0xEF,0x6E,0x95,0x10,0xFC,0xE1,0x90,0x17,0x77,0x2C,0xEE, - 0x75,0x3E,0x7B,0x63,0xEC,0x61,0x92,0x6E,0x4F,0x3B,0xAB,0x80,0x49,0x6B,0xDF,0x00, - 0xEA,0x03,0x00,0x7F,0x2F,0x75,0xD5,0x28,0x2F,0xEC,0x56,0x67,0x8F,0x80,0x83,0xA3, - 0xBD,0xDC,0x03,0x99,0x93,0x8B,0x94,0x91,0x56,0x5B,0xA1,0xB8,0x6A,0x3A,0x3F,0x06, - 0xBD,0x0E,0x92,0xCC,0x60,0x9C,0xFD,0xB5,0xE0,0x9F,0x66,0x30,0x5F,0xDB,0xE6,0x94, - 0xF0,0x95,0x6A,0xAF,0xC8,0x8A,0xAF,0x80,0xD9,0xE6,0x88,0x39,0x01,0x7C,0x1C,0xC0, - 0xC5,0x2A,0xF7,0x7B,0x95,0xA0,0xF2,0x76,0xAB,0x6D,0x9B,0x72,0x39,0x30,0xEB,0xD1, - 0x57,0x55,0x01,0x9D,0x58,0x11,0x9D,0x7C,0x6D,0x84,0x8F,0x49,0xE8,0x9D,0x09,0xFC, - 0x3C,0xFD,0x0A,0x4A,0x76,0x14,0x21,0x5C,0x16,0x73,0x40,0x23,0x19,0x74,0xC3,0xBA, - 0x58,0x0A,0xA6,0x96,0x2E,0xDE,0x36,0xE5,0x9F,0xD0,0xC2,0xF0,0xE1,0xE0,0xC1,0x62, - 0xE3,0xC2,0x18,0x45,0x19,0x51,0xAA,0x17,0x1E,0xE8,0x23,0x75,0xD4,0xC8,0xD0,0x96, - 0x13,0xFF,0xC7,0x24,0xD1,0x8C,0x0B,0x27,0xAE,0x9E,0x7A,0xDC,0x3A,0x61,0x63,0x60, - 0x88,0x97,0x2D,0x5D,0x05,0x0B,0xE5,0x3B,0xEB,0xAE,0xCE,0x3A,0x47,0x73,0x76,0xA8, - 0xFA,0x2C,0xDD,0xC0,0x87,0x17,0xE9,0xAC,0x30,0x99,0xF8,0x1F,0x02,0x03,0x01,0x00, - 0x01,0xA3,0x82,0x01,0x69,0x30,0x82,0x01,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, - 0x04,0x18,0x30,0x16,0x80,0x14,0xBB,0xAF,0x7E,0x02,0x3D,0xFA,0xA6,0xF1,0x3C,0x84, - 0x8E,0xAD,0xEE,0x38,0x98,0xEC,0xD9,0x32,0x32,0xD4,0x30,0x1D,0x06,0x03,0x55,0x1D, - 0x0E,0x04,0x16,0x04,0x14,0x39,0xDA,0xFF,0xCA,0x28,0x14,0x8A,0xA8,0x74,0x13,0x08, - 0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13, - 0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3E,0x06, - 0x03,0x55,0x1D,0x20,0x04,0x37,0x30,0x35,0x30,0x33,0x06,0x04,0x55,0x1D,0x20,0x00, - 0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1D, - 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65,0x63,0x75,0x72,0x65,0x2E,0x63, - 0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x4C,0x06, - 0x03,0x55,0x1D,0x1F,0x04,0x45,0x30,0x43,0x30,0x41,0xA0,0x3F,0xA0,0x3D,0x86,0x3B, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x63,0x6F,0x6D,0x6F,0x64, - 0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53, - 0x41,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x41,0x75, - 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2E,0x63,0x72,0x6C,0x30,0x71,0x06,0x08,0x2B, - 0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3B,0x06,0x08,0x2B, - 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, - 0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D, - 0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x41,0x64,0x64,0x54,0x72,0x75, - 0x73,0x74,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, - 0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x30,0x0D, - 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x03,0x82,0x02, - 0x01,0x00,0x44,0x42,0x9D,0x41,0x51,0x2B,0x48,0x88,0x5D,0x97,0x9B,0x79,0x5E,0x11, - 0x01,0x4A,0x52,0x19,0x7B,0x41,0x2C,0xC7,0x89,0x3C,0xD0,0x72,0xDC,0x85,0xFA,0x58, - 0xAF,0xD5,0x25,0xE4,0x13,0xF8,0x58,0x65,0x67,0x9F,0x0D,0xFF,0x57,0x8B,0xA9,0x85, - 0x5E,0xCA,0xA6,0x4B,0xB0,0xA7,0xB2,0x2D,0xE0,0x8C,0x22,0xCD,0xFB,0xFF,0x79,0xA4, - 0x8C,0x2B,0x8D,0xFE,0x02,0x3D,0x24,0xDE,0xA9,0x5D,0x5F,0xE4,0x0F,0x47,0xD0,0xDB, - 0x66,0x25,0x3E,0x87,0x47,0x0C,0xAE,0x22,0xC5,0x50,0x22,0x84,0xD7,0xED,0x4A,0x59, - 0x1A,0xF6,0x93,0xA5,0x93,0xB0,0xE0,0x1B,0x81,0xF2,0x56,0xC4,0xC8,0x10,0x53,0xE4, - 0xD4,0x76,0xB1,0xD1,0x5B,0x69,0x4B,0x77,0xB2,0xE0,0x4F,0xC4,0x84,0xE7,0xD4,0xA0, - 0x50,0xEE,0x3C,0xFA,0x44,0xFC,0xD0,0x57,0xB9,0xE1,0x28,0x53,0xFD,0x53,0xCD,0xDC, - 0xB9,0x1F,0x7A,0x40,0xBD,0x30,0x3F,0xD8,0x6C,0xD2,0xF3,0xE7,0x07,0x9F,0x1F,0x22, - 0xB5,0xEA,0x22,0x71,0xCB,0x2A,0xF0,0x56,0x7C,0xFE,0xAC,0xA8,0xD1,0x06,0x0F,0x14, - 0x14,0x52,0x4C,0xFE,0x64,0x2B,0x0C,0x69,0x2A,0xB8,0x0D,0x50,0x6E,0x3E,0x04,0x07, - 0xBF,0x7A,0x20,0x8B,0xF8,0xEE,0x65,0x09,0xE1,0xC7,0x49,0x08,0x32,0x3D,0x0D,0x28, - 0x7E,0x49,0x1D,0xB7,0x4A,0xEF,0x02,0xE7,0x0D,0x80,0x17,0xC8,0x5C,0xE0,0x61,0x62, - 0xCB,0xEC,0xB3,0x60,0x79,0x25,0xDA,0x1A,0x65,0x73,0x9C,0x38,0x10,0xA0,0x26,0x3A, - 0xB0,0xC8,0x16,0x7D,0x93,0x31,0x22,0xEE,0x74,0x0B,0x88,0xC0,0x5C,0x89,0x41,0x00, - 0x28,0xA9,0x47,0x31,0xDF,0x7D,0x49,0x45,0x9A,0xF5,0xE6,0xA7,0x45,0x1A,0xD2,0x8E, - 0x13,0x10,0xDF,0x83,0xAF,0x9B,0x0D,0xAD,0x7E,0x7E,0x9D,0x35,0x50,0x34,0x04,0xCE, - 0xE9,0x20,0xD6,0x9E,0xDB,0x9D,0xD4,0xA8,0xDA,0x64,0xB4,0xD1,0x2F,0x59,0x2E,0x5E, - 0xA2,0x36,0x61,0xD4,0x24,0xA0,0x82,0x33,0x33,0x8A,0xA1,0xD1,0x6C,0xEF,0x61,0x68, - 0xA3,0xE5,0xD2,0x56,0xAD,0xC5,0xFD,0x5E,0x62,0xEB,0x15,0xA8,0x74,0x12,0x4C,0x2F, - 0x31,0x8C,0xE9,0xC1,0xDF,0x10,0x4B,0x01,0xEA,0xF6,0x54,0x1B,0xCD,0x7F,0x3B,0xBD, - 0x5C,0x9F,0xC1,0xDB,0xCF,0x01,0xCA,0xF2,0xBA,0x60,0x12,0x21,0x31,0xED,0xA9,0x64, - 0xB8,0xB2,0x49,0x58,0x17,0x6D,0x5A,0xD7,0xCD,0x8C,0x6D,0xBE,0x9E,0x7F,0xE2,0x02, - 0x58,0xA7,0xDB,0xC3,0x2D,0x58,0xF6,0x74,0x06,0x6A,0x9A,0xF6,0x61,0xF9,0xF6,0x00, - 0xB6,0x69,0xD8,0x3A,0x8B,0x31,0x59,0xDD,0x91,0xE6,0x7C,0x27,0x23,0x87,0xDD,0x03, - 0x0F,0x8F,0x2A,0x8C,0x1E,0x83,0x01,0x4E,0x01,0x61,0x0C,0x52,0x73,0x6D,0xFC,0x08, - 0xA2,0xB9,0x2A,0x66,0xE4,0x76,0x4D,0x31,0xA0,0x56,0x9B,0xD9,0x53,0x8D,0xA2,0xB6, - 0x8F,0x02,0xC8,0xE6,0x3A,0xA6,0x04,0xD1,0x48,0xFB,0xC3,0x4A,0x02,0x76,0xFD,0x2F, - 0xD2,0xBC,0x13,0xB6,0xE8,0x6D,0x34,0x24,0xFA,0x9D,0x29,0x8A,0xC7,0xA1,0x2B,0x14, - 0xF1,0x96,0x00,0x73,0xB9,0x13,0xE9,0xC0,0xB9,0x3A,0x47,0x56,0x02,0x71,0x80,0x27, - 0xA4,0xBC,0x25,0xB6,0xE9,0xBD,0xE4,0xE9,0x98,0x74,0x16,0xF1,0x37,0x84,0x81,0x07, - 0xB4,0x82, -}; - -/* This is the cert we get when we get the url in the AIA extension of the ovh leaf. */ -/* subject:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ -/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority */ -static unsigned char comodo_aia_certificate[1554]={ - 0x30,0x82,0x06,0x0E,0x30,0x82,0x03,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x06, - 0xA7,0x43,0x80,0xD4,0xEB,0xFE,0xD4,0x35,0xB5,0xA3,0xF7,0xE1,0x6A,0xBD,0xD8,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x30,0x81, - 0x85,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, - 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, - 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, - 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, - 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, - 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x2B,0x30,0x29,0x06,0x03,0x55, - 0x04,0x03,0x13,0x22,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x43, - 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74, - 0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x31,0x32,0x30,0x32,0x31,0x32, - 0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x37,0x30,0x32,0x31,0x31,0x32, - 0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13, - 0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72,0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73, - 0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61, - 0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11, - 0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43,0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65, - 0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F, - 0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20, - 0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72, - 0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, - 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0x95,0x56,0xDE,0x54, - 0xB4,0xDF,0xD5,0x02,0x49,0x7B,0xD1,0x5B,0x5C,0xA2,0xB2,0x1E,0x8F,0x9C,0x2B,0x62, - 0x4C,0x2B,0x8D,0x12,0x28,0xF3,0x1A,0x95,0xA3,0xC6,0x10,0xFD,0x29,0xDE,0xE1,0x9F, - 0x0B,0x38,0x40,0x93,0xD1,0xEF,0x6E,0x95,0x10,0xFC,0xE1,0x90,0x17,0x77,0x2C,0xEE, - 0x75,0x3E,0x7B,0x63,0xEC,0x61,0x92,0x6E,0x4F,0x3B,0xAB,0x80,0x49,0x6B,0xDF,0x00, - 0xEA,0x03,0x00,0x7F,0x2F,0x75,0xD5,0x28,0x2F,0xEC,0x56,0x67,0x8F,0x80,0x83,0xA3, - 0xBD,0xDC,0x03,0x99,0x93,0x8B,0x94,0x91,0x56,0x5B,0xA1,0xB8,0x6A,0x3A,0x3F,0x06, - 0xBD,0x0E,0x92,0xCC,0x60,0x9C,0xFD,0xB5,0xE0,0x9F,0x66,0x30,0x5F,0xDB,0xE6,0x94, - 0xF0,0x95,0x6A,0xAF,0xC8,0x8A,0xAF,0x80,0xD9,0xE6,0x88,0x39,0x01,0x7C,0x1C,0xC0, - 0xC5,0x2A,0xF7,0x7B,0x95,0xA0,0xF2,0x76,0xAB,0x6D,0x9B,0x72,0x39,0x30,0xEB,0xD1, - 0x57,0x55,0x01,0x9D,0x58,0x11,0x9D,0x7C,0x6D,0x84,0x8F,0x49,0xE8,0x9D,0x09,0xFC, - 0x3C,0xFD,0x0A,0x4A,0x76,0x14,0x21,0x5C,0x16,0x73,0x40,0x23,0x19,0x74,0xC3,0xBA, - 0x58,0x0A,0xA6,0x96,0x2E,0xDE,0x36,0xE5,0x9F,0xD0,0xC2,0xF0,0xE1,0xE0,0xC1,0x62, - 0xE3,0xC2,0x18,0x45,0x19,0x51,0xAA,0x17,0x1E,0xE8,0x23,0x75,0xD4,0xC8,0xD0,0x96, - 0x13,0xFF,0xC7,0x24,0xD1,0x8C,0x0B,0x27,0xAE,0x9E,0x7A,0xDC,0x3A,0x61,0x63,0x60, - 0x88,0x97,0x2D,0x5D,0x05,0x0B,0xE5,0x3B,0xEB,0xAE,0xCE,0x3A,0x47,0x73,0x76,0xA8, - 0xFA,0x2C,0xDD,0xC0,0x87,0x17,0xE9,0xAC,0x30,0x99,0xF8,0x1F,0x02,0x03,0x01,0x00, - 0x01,0xA3,0x82,0x01,0x69,0x30,0x82,0x01,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, - 0x04,0x18,0x30,0x16,0x80,0x14,0xBB,0xAF,0x7E,0x02,0x3D,0xFA,0xA6,0xF1,0x3C,0x84, - 0x8E,0xAD,0xEE,0x38,0x98,0xEC,0xD9,0x32,0x32,0xD4,0x30,0x1D,0x06,0x03,0x55,0x1D, - 0x0E,0x04,0x16,0x04,0x14,0x39,0xDA,0xFF,0xCA,0x28,0x14,0x8A,0xA8,0x74,0x13,0x08, - 0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13, - 0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3E,0x06, - 0x03,0x55,0x1D,0x20,0x04,0x37,0x30,0x35,0x30,0x33,0x06,0x04,0x55,0x1D,0x20,0x00, - 0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1D, - 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65,0x63,0x75,0x72,0x65,0x2E,0x63, - 0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x4C,0x06, - 0x03,0x55,0x1D,0x1F,0x04,0x45,0x30,0x43,0x30,0x41,0xA0,0x3F,0xA0,0x3D,0x86,0x3B, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x63,0x6F,0x6D,0x6F,0x64, - 0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53, - 0x41,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x41,0x75, - 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2E,0x63,0x72,0x6C,0x30,0x71,0x06,0x08,0x2B, - 0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3B,0x06,0x08,0x2B, - 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, - 0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D, - 0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x41,0x64,0x64,0x54,0x72,0x75, - 0x73,0x74,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, - 0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x30,0x0D, - 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x03,0x82,0x02, - 0x01,0x00,0x44,0x42,0x9D,0x41,0x51,0x2B,0x48,0x88,0x5D,0x97,0x9B,0x79,0x5E,0x11, - 0x01,0x4A,0x52,0x19,0x7B,0x41,0x2C,0xC7,0x89,0x3C,0xD0,0x72,0xDC,0x85,0xFA,0x58, - 0xAF,0xD5,0x25,0xE4,0x13,0xF8,0x58,0x65,0x67,0x9F,0x0D,0xFF,0x57,0x8B,0xA9,0x85, - 0x5E,0xCA,0xA6,0x4B,0xB0,0xA7,0xB2,0x2D,0xE0,0x8C,0x22,0xCD,0xFB,0xFF,0x79,0xA4, - 0x8C,0x2B,0x8D,0xFE,0x02,0x3D,0x24,0xDE,0xA9,0x5D,0x5F,0xE4,0x0F,0x47,0xD0,0xDB, - 0x66,0x25,0x3E,0x87,0x47,0x0C,0xAE,0x22,0xC5,0x50,0x22,0x84,0xD7,0xED,0x4A,0x59, - 0x1A,0xF6,0x93,0xA5,0x93,0xB0,0xE0,0x1B,0x81,0xF2,0x56,0xC4,0xC8,0x10,0x53,0xE4, - 0xD4,0x76,0xB1,0xD1,0x5B,0x69,0x4B,0x77,0xB2,0xE0,0x4F,0xC4,0x84,0xE7,0xD4,0xA0, - 0x50,0xEE,0x3C,0xFA,0x44,0xFC,0xD0,0x57,0xB9,0xE1,0x28,0x53,0xFD,0x53,0xCD,0xDC, - 0xB9,0x1F,0x7A,0x40,0xBD,0x30,0x3F,0xD8,0x6C,0xD2,0xF3,0xE7,0x07,0x9F,0x1F,0x22, - 0xB5,0xEA,0x22,0x71,0xCB,0x2A,0xF0,0x56,0x7C,0xFE,0xAC,0xA8,0xD1,0x06,0x0F,0x14, - 0x14,0x52,0x4C,0xFE,0x64,0x2B,0x0C,0x69,0x2A,0xB8,0x0D,0x50,0x6E,0x3E,0x04,0x07, - 0xBF,0x7A,0x20,0x8B,0xF8,0xEE,0x65,0x09,0xE1,0xC7,0x49,0x08,0x32,0x3D,0x0D,0x28, - 0x7E,0x49,0x1D,0xB7,0x4A,0xEF,0x02,0xE7,0x0D,0x80,0x17,0xC8,0x5C,0xE0,0x61,0x62, - 0xCB,0xEC,0xB3,0x60,0x79,0x25,0xDA,0x1A,0x65,0x73,0x9C,0x38,0x10,0xA0,0x26,0x3A, - 0xB0,0xC8,0x16,0x7D,0x93,0x31,0x22,0xEE,0x74,0x0B,0x88,0xC0,0x5C,0x89,0x41,0x00, - 0x28,0xA9,0x47,0x31,0xDF,0x7D,0x49,0x45,0x9A,0xF5,0xE6,0xA7,0x45,0x1A,0xD2,0x8E, - 0x13,0x10,0xDF,0x83,0xAF,0x9B,0x0D,0xAD,0x7E,0x7E,0x9D,0x35,0x50,0x34,0x04,0xCE, - 0xE9,0x20,0xD6,0x9E,0xDB,0x9D,0xD4,0xA8,0xDA,0x64,0xB4,0xD1,0x2F,0x59,0x2E,0x5E, - 0xA2,0x36,0x61,0xD4,0x24,0xA0,0x82,0x33,0x33,0x8A,0xA1,0xD1,0x6C,0xEF,0x61,0x68, - 0xA3,0xE5,0xD2,0x56,0xAD,0xC5,0xFD,0x5E,0x62,0xEB,0x15,0xA8,0x74,0x12,0x4C,0x2F, - 0x31,0x8C,0xE9,0xC1,0xDF,0x10,0x4B,0x01,0xEA,0xF6,0x54,0x1B,0xCD,0x7F,0x3B,0xBD, - 0x5C,0x9F,0xC1,0xDB,0xCF,0x01,0xCA,0xF2,0xBA,0x60,0x12,0x21,0x31,0xED,0xA9,0x64, - 0xB8,0xB2,0x49,0x58,0x17,0x6D,0x5A,0xD7,0xCD,0x8C,0x6D,0xBE,0x9E,0x7F,0xE2,0x02, - 0x58,0xA7,0xDB,0xC3,0x2D,0x58,0xF6,0x74,0x06,0x6A,0x9A,0xF6,0x61,0xF9,0xF6,0x00, - 0xB6,0x69,0xD8,0x3A,0x8B,0x31,0x59,0xDD,0x91,0xE6,0x7C,0x27,0x23,0x87,0xDD,0x03, - 0x0F,0x8F,0x2A,0x8C,0x1E,0x83,0x01,0x4E,0x01,0x61,0x0C,0x52,0x73,0x6D,0xFC,0x08, - 0xA2,0xB9,0x2A,0x66,0xE4,0x76,0x4D,0x31,0xA0,0x56,0x9B,0xD9,0x53,0x8D,0xA2,0xB6, - 0x8F,0x02,0xC8,0xE6,0x3A,0xA6,0x04,0xD1,0x48,0xFB,0xC3,0x4A,0x02,0x76,0xFD,0x2F, - 0xD2,0xBC,0x13,0xB6,0xE8,0x6D,0x34,0x24,0xFA,0x9D,0x29,0x8A,0xC7,0xA1,0x2B,0x14, - 0xF1,0x96,0x00,0x73,0xB9,0x13,0xE9,0xC0,0xB9,0x3A,0x47,0x56,0x02,0x71,0x80,0x27, - 0xA4,0xBC,0x25,0xB6,0xE9,0xBD,0xE4,0xE9,0x98,0x74,0x16,0xF1,0x37,0x84,0x81,0x07, - 0xB4,0x82, -}; - -static unsigned char valid_ist_certificate[] = { - 0x30,0x82,0x08,0x51,0x30,0x82,0x07,0x39,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x3A, - 0xFC,0x35,0x65,0x26,0x40,0x12,0xAF,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04, - 0x03,0x13,0x13,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20, - 0x32,0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13, - 0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, - 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x38, - 0x30,0x37,0x31,0x36,0x32,0x32,0x31,0x31,0x30,0x38,0x5A,0x17,0x0D,0x32,0x30,0x30, - 0x38,0x31,0x34,0x32,0x32,0x31,0x31,0x30,0x38,0x5A,0x30,0x79,0x31,0x18,0x30,0x16, - 0x06,0x03,0x55,0x04,0x03,0x0C,0x0F,0x76,0x61,0x6C,0x69,0x64,0x2E,0x61,0x70,0x70, - 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C, - 0x1D,0x6D,0x61,0x6E,0x61,0x67,0x65,0x6D,0x65,0x6E,0x74,0x3A,0x69,0x64,0x6D,0x73, - 0x2E,0x67,0x72,0x6F,0x75,0x70,0x2E,0x31,0x32,0x30,0x38,0x39,0x32,0x30,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61, - 0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, - 0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, - 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, - 0x0A,0x02,0x82,0x01,0x01,0x00,0xC7,0x5F,0xAC,0x4A,0xAC,0x71,0xFC,0xF1,0x80,0x8D, - 0x57,0xA1,0xDC,0x3B,0x48,0x4F,0x02,0x83,0xBA,0xE0,0x57,0x36,0xAB,0x53,0xB5,0x14, - 0x47,0x8F,0x87,0x24,0xA6,0x7A,0x40,0x5C,0xC3,0x28,0x6E,0x29,0x6D,0x54,0x35,0x89, - 0x79,0xA9,0x12,0xF3,0xD7,0x0A,0x4E,0xBE,0xC7,0xFB,0x75,0xF3,0x1B,0x92,0x6D,0x3F, - 0x7B,0xCC,0x72,0x63,0xF5,0xE8,0x57,0xC8,0xD2,0x7A,0x36,0x98,0x6E,0x61,0x0F,0x48, - 0xD1,0xC3,0x37,0xA4,0xB9,0x94,0x1C,0x66,0x18,0x75,0x97,0x34,0xED,0xFA,0x96,0x00, - 0x24,0x1A,0x8D,0x2E,0xFB,0x98,0x48,0x85,0xA5,0x73,0x9E,0xED,0x7D,0x8E,0x3C,0xCF, - 0xED,0xE9,0xE1,0x5F,0x1C,0x36,0xFF,0x20,0x2D,0x62,0x5C,0x0E,0x3D,0xCC,0x6E,0x3D, - 0xDB,0xF8,0x5A,0x8A,0x5A,0x2A,0x75,0xDC,0x09,0xC4,0x21,0x45,0x55,0x04,0xE3,0xEC, - 0x20,0xF0,0x5E,0xE3,0xC7,0x1A,0xD3,0x16,0x78,0x07,0xF1,0x65,0xF3,0xAD,0xB5,0x68, - 0x4B,0x0E,0x5D,0xA9,0x37,0xEA,0x58,0xAA,0x19,0x1F,0xF4,0xB4,0xF3,0x01,0xB0,0xE0, - 0xDC,0x25,0x4D,0x8A,0x2E,0xB1,0xC4,0xD3,0xE6,0x05,0x9E,0x23,0x8B,0x1E,0x8B,0xD0, - 0x14,0xA1,0x7E,0xC7,0x98,0xF1,0x68,0x9C,0x2D,0x10,0xDE,0xF9,0x79,0x14,0x3E,0x98, - 0x73,0x19,0x94,0x4B,0x4A,0xF7,0x52,0xDA,0x4D,0x98,0x26,0xAC,0xB2,0x76,0x1A,0x71, - 0xB5,0xFA,0x0D,0xE8,0x93,0xEB,0x92,0xF8,0x77,0x82,0xE5,0xE9,0xD4,0x07,0x8C,0xFD, - 0x20,0x8D,0xA0,0x25,0xD2,0x8A,0x6F,0xE2,0x33,0xA7,0x24,0x56,0x14,0x30,0x29,0x9D, - 0x6B,0xAB,0x2A,0x33,0xF9,0xD3,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x04,0xF2,0x30, - 0x82,0x04,0xEE,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, - 0x00,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xD8,0x7A, - 0x94,0x44,0x7C,0x90,0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C,0x01,0x44,0x03,0x86,0xD6, - 0x2A,0x29,0x30,0x7E,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x72, - 0x30,0x70,0x30,0x34,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x28, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x65,0x72,0x74,0x73,0x2E,0x61,0x70,0x70, - 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74,0x63, - 0x61,0x32,0x67,0x31,0x2E,0x64,0x65,0x72,0x30,0x38,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x30,0x01,0x86,0x2C,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, - 0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70, - 0x30,0x33,0x2D,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74,0x63,0x61,0x32,0x67,0x31, - 0x32,0x30,0x30,0x43,0x06,0x03,0x55,0x1D,0x11,0x04,0x3C,0x30,0x3A,0x82,0x0F,0x76, - 0x61,0x6C,0x69,0x64,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x82,0x13, - 0x76,0x61,0x6C,0x69,0x64,0x2D,0x75,0x61,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, - 0x63,0x6F,0x6D,0x82,0x12,0x76,0x61,0x6C,0x69,0x64,0x2D,0x71,0x61,0x2E,0x61,0x70, - 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x81,0xFF,0x06,0x03,0x55,0x1D,0x20,0x04, - 0x81,0xF7,0x30,0x81,0xF4,0x30,0x81,0xF1,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63, - 0x64,0x05,0x0B,0x04,0x30,0x81,0xE2,0x30,0x81,0xA4,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x02,0x02,0x30,0x81,0x97,0x0C,0x81,0x94,0x52,0x65,0x6C,0x69,0x61,0x6E, - 0x63,0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69, - 0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61, - 0x72,0x74,0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65, - 0x70,0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x61,0x6E,0x79,0x20,0x61,0x70, - 0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61, - 0x6E,0x64,0x20,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66, - 0x20,0x75,0x73,0x65,0x20,0x61,0x6E,0x64,0x2F,0x6F,0x72,0x20,0x63,0x65,0x72,0x74, - 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69, - 0x63,0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x39, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x2D,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, - 0x2F,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x61,0x75,0x74,0x68, - 0x6F,0x72,0x69,0x74,0x79,0x2F,0x72,0x70,0x61,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25, - 0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x37,0x06,0x03,0x55,0x1D,0x1F,0x04, - 0x30,0x30,0x2E,0x30,0x2C,0xA0,0x2A,0xA0,0x28,0x86,0x26,0x68,0x74,0x74,0x70,0x3A, - 0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, - 0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74,0x63,0x61,0x32,0x67,0x31,0x2E,0x63,0x72, - 0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x55,0xF7,0x8E,0xC8, - 0x40,0x19,0x7D,0x8B,0x19,0x80,0xA5,0xF5,0xC6,0x44,0x75,0x8A,0x04,0x1E,0x7D,0x48, - 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0, - 0x30,0x82,0x02,0x6D,0x06,0x0A,0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02, - 0x04,0x82,0x02,0x5D,0x04,0x82,0x02,0x59,0x02,0x57,0x00,0x75,0x00,0xBB,0xD9,0xDF, - 0xBC,0x1F,0x8A,0x71,0xB5,0x93,0x94,0x23,0x97,0xAA,0x92,0x7B,0x47,0x38,0x57,0x95, - 0x0A,0xAB,0x52,0xE8,0x1A,0x90,0x96,0x64,0x36,0x8E,0x1E,0xD1,0x85,0x00,0x00,0x01, - 0x64,0xA5,0x2E,0xD8,0xFD,0x00,0x00,0x04,0x03,0x00,0x46,0x30,0x44,0x02,0x20,0x3E, - 0xD8,0xAB,0x26,0x35,0xFC,0xAC,0xE8,0x97,0xE8,0x84,0x28,0x73,0x0D,0xFB,0x6F,0x7B, - 0x02,0xF6,0x8E,0xB8,0xD1,0xAC,0xF3,0x9C,0xDF,0x37,0x2E,0x42,0x53,0x6B,0x3A,0x02, - 0x20,0x73,0x9A,0xED,0x05,0x2C,0x5C,0xDD,0x5A,0x60,0x2D,0xF9,0xB3,0x5C,0x7B,0xB3, - 0x95,0x0F,0xF1,0x21,0xD3,0xB5,0x1C,0x40,0xBC,0x50,0x79,0xE2,0xF3,0x19,0x89,0xAC, - 0xE7,0x00,0x75,0x00,0x56,0x14,0x06,0x9A,0x2F,0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD, - 0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC,0x99,0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55, - 0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x64,0xA5,0x2E,0xD9,0xA9,0x00,0x00,0x04,0x03, - 0x00,0x46,0x30,0x44,0x02,0x20,0x2E,0x5B,0x93,0xD3,0xCA,0x9A,0x1E,0x80,0xC3,0x50, - 0x1C,0xC1,0x37,0x6B,0x11,0x76,0x34,0xE8,0xE3,0xC7,0x8D,0x17,0xD0,0x4D,0x2E,0xA7, - 0xD9,0x98,0x6E,0x15,0x3A,0xC3,0x02,0x20,0x18,0x2B,0xD6,0x7A,0x11,0x46,0xC0,0xE1, - 0x99,0xDA,0x51,0x9C,0xBA,0xC5,0xC3,0x4C,0x3F,0x9A,0xB2,0xD1,0xDA,0xB7,0x6B,0x69, - 0x33,0x81,0x23,0x46,0x6F,0x54,0xFF,0x3F,0x00,0x76,0x00,0xEE,0x4B,0xBD,0xB7,0x75, - 0xCE,0x60,0xBA,0xE1,0x42,0x69,0x1F,0xAB,0xE1,0x9E,0x66,0xA3,0x0F,0x7E,0x5F,0xB0, - 0x72,0xD8,0x83,0x00,0xC4,0x7B,0x89,0x7A,0xA8,0xFD,0xCB,0x00,0x00,0x01,0x64,0xA5, - 0x2E,0xD9,0x25,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x5E,0x30,0x51, - 0x55,0x80,0x59,0xEA,0x60,0x45,0x10,0x9D,0x8E,0x61,0x07,0x34,0xD4,0xC2,0x08,0x46, - 0xEB,0xAC,0x4A,0xC3,0x72,0xC6,0x04,0x8E,0xF4,0x5D,0xF6,0xAF,0x51,0x02,0x21,0x00, - 0xC0,0x20,0xF0,0x01,0x1F,0x74,0xD4,0x33,0x24,0xE3,0x70,0xB3,0x80,0x47,0xE9,0x8A, - 0xB6,0x47,0xE4,0x65,0xA4,0x98,0x8D,0x6A,0xD8,0x75,0xE4,0xFE,0xC7,0x7A,0x89,0x5E, - 0x00,0x77,0x00,0x55,0x81,0xD4,0xC2,0x16,0x90,0x36,0x01,0x4A,0xEA,0x0B,0x9B,0x57, - 0x3C,0x53,0xF0,0xC0,0xE4,0x38,0x78,0x70,0x25,0x08,0x17,0x2F,0xA3,0xAA,0x1D,0x07, - 0x13,0xD3,0x0C,0x00,0x00,0x01,0x64,0xA5,0x2E,0xD9,0x74,0x00,0x00,0x04,0x03,0x00, - 0x48,0x30,0x46,0x02,0x21,0x00,0x94,0x79,0x39,0x0B,0x5F,0x59,0x89,0x4D,0xD4,0x09, - 0x28,0xB4,0xE1,0x07,0xC0,0x58,0xDC,0xA3,0x86,0x07,0x68,0x29,0x02,0xDA,0x86,0xE6, - 0x70,0xBE,0x32,0xB7,0xC6,0x33,0x02,0x21,0x00,0xA6,0x72,0x28,0x8B,0xC9,0x61,0xC4, - 0xFB,0x53,0x98,0x8F,0x99,0x3F,0x92,0x7E,0x06,0x21,0x10,0xA1,0x58,0x1D,0x28,0x44, - 0x80,0x29,0x91,0xC2,0xE6,0xBB,0xCE,0xCC,0x0E,0x00,0x76,0x00,0x87,0x75,0xBF,0xE7, - 0x59,0x7C,0xF8,0x8C,0x43,0x99,0x5F,0xBD,0xF3,0x6E,0xFF,0x56,0x8D,0x47,0x56,0x36, - 0xFF,0x4A,0xB5,0x60,0xC1,0xB4,0xEA,0xFF,0x5E,0xA0,0x83,0x0F,0x00,0x00,0x01,0x64, - 0xA5,0x2E,0xD9,0x12,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x37,0x9C, - 0x18,0xFC,0x24,0x63,0xAD,0x19,0xD6,0xA2,0x82,0xD9,0x47,0x82,0xAE,0x94,0x66,0x97, - 0xE4,0x73,0xCC,0x36,0x40,0x8A,0x6F,0xA5,0xAA,0x3C,0x99,0x92,0x8D,0x8F,0x02,0x21, - 0x00,0xF4,0x44,0x4A,0x8D,0x3A,0x18,0x31,0xDA,0xF5,0xDD,0xF4,0x37,0x4F,0xB3,0x1D, - 0xF6,0x15,0xBD,0x8B,0xF5,0x75,0x53,0x12,0x35,0xE5,0xD5,0x4D,0x08,0x0E,0xA7,0xC2, - 0x69,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, - 0x03,0x82,0x01,0x01,0x00,0x8F,0x46,0xED,0x04,0x6F,0xED,0xF7,0xAA,0xB9,0xE3,0x29, - 0xF7,0x4A,0x9F,0x69,0xEB,0xB2,0x61,0xD0,0x37,0x68,0x8F,0xC8,0xCF,0xB2,0x4F,0x1F, - 0x02,0x3E,0xF3,0x78,0x38,0x67,0xDB,0xD1,0xFA,0x60,0x16,0x70,0xDD,0xB7,0x44,0x12, - 0x54,0x0A,0x8C,0x3E,0xEC,0xF2,0xE9,0xBC,0x78,0x11,0x8D,0x7F,0x44,0x16,0xF0,0x87, - 0xD6,0xD8,0xA2,0x65,0xBC,0x11,0x32,0x4A,0xED,0xA9,0xF9,0xD7,0xB6,0xF7,0x9B,0x0F, - 0xFF,0x82,0x06,0x12,0x04,0x77,0xB9,0x13,0x08,0xAB,0x98,0x5D,0x07,0x04,0x7C,0xDC, - 0x43,0x1E,0x86,0x16,0x8C,0xF7,0xB2,0x67,0x42,0x65,0x43,0x40,0x9B,0x1F,0xC6,0x97, - 0x18,0x41,0xCF,0x2F,0xA9,0xC8,0x4D,0x57,0x4E,0x84,0x28,0x0F,0xC9,0x3A,0xEF,0xB6, - 0x3D,0x9C,0xE9,0x96,0x12,0xFA,0xF2,0x35,0xA0,0xF1,0xDB,0x9D,0x0A,0x65,0x23,0xBB, - 0xC9,0x38,0xCC,0x39,0x7E,0x6B,0x17,0x80,0x48,0xF1,0xAC,0xF3,0x12,0x33,0x7B,0xBE, - 0x5E,0x7B,0xC4,0x8D,0xC6,0xB9,0x9B,0x85,0x0A,0x8A,0x52,0x4F,0x5E,0xC7,0x1F,0x12, - 0xDB,0xA5,0xBA,0x33,0x9E,0xA2,0x3A,0x9E,0x11,0x82,0x4E,0x42,0x0E,0x3F,0x82,0xDF, - 0x36,0x91,0xF7,0x24,0xB6,0xFC,0x6D,0x00,0x19,0xF2,0xD0,0x31,0x70,0x1F,0xED,0xE6, - 0x37,0xED,0x1D,0xB3,0xDB,0x06,0x01,0x90,0x0E,0x95,0x9B,0xD6,0x34,0x5F,0xFA,0xE6, - 0xD1,0x34,0xA6,0xD9,0x61,0x63,0x3E,0x2D,0x59,0x7B,0xD4,0xA5,0x9E,0x3F,0xFE,0xFE, - 0x58,0xC9,0x60,0xAE,0xA4,0xC2,0xCB,0xA6,0x50,0x9D,0x50,0xDB,0x38,0x80,0x2F,0xC9, - 0x2A,0xC5,0xEF,0x98,0xCF, -}; - -static unsigned char revoked_ist_certificate[1515]={ - 0x30,0x82,0x05,0xE7,0x30,0x82,0x04,0xCF,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x7F, - 0x00,0xCE,0x8A,0xD6,0x3F,0x5B,0x34,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04, - 0x03,0x13,0x13,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20, - 0x32,0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13, - 0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, - 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x34, - 0x31,0x31,0x32,0x38,0x31,0x35,0x30,0x36,0x31,0x34,0x5A,0x17,0x0D,0x31,0x36,0x31, - 0x32,0x32,0x37,0x31,0x35,0x30,0x36,0x31,0x34,0x5A,0x30,0x81,0xAB,0x31,0x4B,0x30, - 0x49,0x06,0x03,0x55,0x04,0x03,0x0C,0x42,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x2E, - 0x67,0x65,0x6F,0x74,0x72,0x75,0x73,0x74,0x2D,0x67,0x6C,0x6F,0x62,0x61,0x6C,0x2D, - 0x63,0x61,0x2E,0x74,0x65,0x73,0x74,0x2D,0x70,0x61,0x67,0x65,0x73,0x2E,0x63,0x65, - 0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x6D,0x61,0x6E,0x61,0x67,0x65,0x72, - 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x25,0x30,0x23,0x06,0x03, - 0x55,0x04,0x0B,0x0C,0x1C,0x6D,0x61,0x6E,0x61,0x67,0x65,0x6D,0x65,0x6E,0x74,0x3A, - 0x69,0x64,0x6D,0x73,0x2E,0x67,0x72,0x6F,0x75,0x70,0x2E,0x31,0x37,0x36,0x33,0x39, - 0x39,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, - 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00, - 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xA9,0xD7,0xE0,0x65,0x48,0x36,0x8A, - 0x4B,0x6C,0xBB,0x16,0xAF,0xFD,0x09,0xA5,0x9C,0x30,0xDA,0xC5,0x9B,0x3D,0xD6,0xB4, - 0x8E,0x6B,0xC2,0xF4,0xBF,0x30,0xA7,0xCC,0xF7,0xA1,0x23,0x58,0xA0,0x16,0xE8,0x31, - 0x5F,0xE7,0xD2,0x21,0x3D,0x24,0x3D,0xF4,0x1E,0x82,0x46,0x45,0xA0,0xB8,0x2E,0xD7, - 0xB6,0x86,0xD3,0x2A,0xBC,0x93,0x74,0x44,0xAB,0x1C,0x9F,0x86,0xBF,0x19,0xCE,0xA4, - 0xD0,0xC9,0xB9,0x65,0x84,0x89,0x87,0xDE,0x77,0xDC,0xAE,0x85,0xA9,0xDE,0x5A,0xCF, - 0xAF,0x46,0x80,0x45,0x72,0x68,0x87,0x55,0x5B,0x4D,0x49,0xE2,0x7B,0x25,0x31,0x22, - 0x00,0x87,0xAB,0x72,0xEB,0x9A,0x2D,0x81,0x35,0x0E,0x76,0x82,0x5C,0x99,0x10,0xFB, - 0xD6,0x3F,0x29,0xE8,0xFD,0x2E,0xAD,0xF6,0xF8,0xCF,0xC1,0x99,0x5F,0xDA,0xC1,0xB3, - 0x90,0x70,0xA5,0x4B,0x23,0x4D,0xD6,0x1D,0xC9,0x73,0x27,0xD1,0xAE,0x38,0xA3,0xD0, - 0x71,0x92,0xFF,0x89,0xA8,0xE5,0x51,0x3E,0x2F,0xB6,0xB4,0x02,0x20,0x54,0x62,0xA0, - 0x69,0x6D,0xB6,0x10,0x8D,0xB7,0x13,0x2A,0x94,0x4E,0xED,0x73,0x8C,0x78,0x39,0xF6, - 0x04,0xC0,0xF8,0x7A,0x75,0x2D,0x1E,0x82,0x7E,0x55,0x7B,0xE7,0xA7,0xFA,0x6E,0xB1, - 0x53,0x81,0x75,0xB6,0x19,0xD8,0xD2,0xD3,0x8E,0x30,0x95,0x0D,0xD8,0xC9,0xBA,0x3F, - 0x70,0x23,0xC3,0x7B,0xE2,0x6E,0xA9,0xA8,0x91,0x69,0x89,0x8D,0xEA,0x64,0x5D,0x8E, - 0x49,0x43,0x30,0x99,0xBC,0x54,0x97,0xAC,0xEB,0x98,0x09,0x8C,0xE9,0xA7,0xE8,0xDC, - 0xFC,0xE4,0xBE,0x20,0xDA,0xA1,0x88,0xB6,0x99,0x02,0x03,0x01,0x00,0x01,0xA3,0x82, - 0x02,0x55,0x30,0x82,0x02,0x51,0x30,0x48,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x01,0x01,0x04,0x3C,0x30,0x3A,0x30,0x38,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x30,0x01,0x86,0x2C,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E, - 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30,0x34, - 0x2D,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74,0x63,0x61,0x32,0x67,0x31,0x30,0x31, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x75,0x81,0x7F,0xDF,0xDE, - 0x90,0xE2,0xFB,0x67,0xA8,0x04,0xC9,0x82,0xE1,0x2A,0x13,0x08,0x3D,0xCE,0x8E,0x30, - 0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06, - 0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xD8,0x7A,0x94,0x44,0x7C,0x90, - 0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C,0x01,0x44,0x03,0x86,0xD6,0x2A,0x29,0x30,0x81, - 0xFF,0x06,0x03,0x55,0x1D,0x20,0x04,0x81,0xF7,0x30,0x81,0xF4,0x30,0x81,0xF1,0x06, - 0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x05,0x0B,0x04,0x30,0x81,0xE2,0x30,0x81, - 0xA4,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x81,0x97,0x0C,0x81, - 0x94,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69, - 0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x62,0x79, - 0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72,0x74,0x79,0x20,0x61,0x73,0x73,0x75,0x6D, - 0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66, - 0x20,0x61,0x6E,0x79,0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20, - 0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x64,0x69,0x74, - 0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x6E,0x64,0x2F, - 0x6F,0x72,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, - 0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D, - 0x65,0x6E,0x74,0x73,0x2E,0x30,0x39,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02, - 0x01,0x16,0x2D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61,0x70, - 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63, - 0x61,0x74,0x65,0x61,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2F,0x72,0x70,0x61, - 0x30,0x37,0x06,0x03,0x55,0x1D,0x1F,0x04,0x30,0x30,0x2E,0x30,0x2C,0xA0,0x2A,0xA0, - 0x28,0x86,0x26,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61,0x70, - 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74, - 0x63,0x61,0x32,0x67,0x31,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25, - 0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x4D,0x06,0x03,0x55,0x1D,0x11,0x04, - 0x46,0x30,0x44,0x82,0x42,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x2E,0x67,0x65,0x6F, - 0x74,0x72,0x75,0x73,0x74,0x2D,0x67,0x6C,0x6F,0x62,0x61,0x6C,0x2D,0x63,0x61,0x2E, - 0x74,0x65,0x73,0x74,0x2D,0x70,0x61,0x67,0x65,0x73,0x2E,0x63,0x65,0x72,0x74,0x69, - 0x66,0x69,0x63,0x61,0x74,0x65,0x6D,0x61,0x6E,0x61,0x67,0x65,0x72,0x2E,0x61,0x70, - 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xC0,0x5B,0xA6,0xAF,0x2C, - 0x27,0xBA,0x49,0x8D,0x41,0xF6,0xC4,0x02,0xEE,0x9D,0xB1,0x48,0xC3,0x34,0x7B,0xF2, - 0xD2,0x82,0x49,0xA5,0x13,0x5A,0x66,0xAD,0xC9,0x73,0xBF,0x6B,0xC9,0x30,0x86,0xBA, - 0x7A,0xD2,0x9D,0x61,0xFE,0x04,0x07,0x15,0x66,0xC2,0x25,0xF7,0x6C,0x88,0xB1,0x0E, - 0x22,0x11,0xF9,0x26,0xA7,0x4E,0x88,0x96,0x20,0x99,0xA6,0x51,0xEE,0x02,0x96,0xC7, - 0xA4,0xCA,0xD4,0xAB,0xFC,0x5F,0x96,0x16,0x0D,0x8D,0xA0,0xA1,0x17,0x6E,0x77,0x92, - 0xC9,0x64,0xD9,0xA2,0x5A,0x00,0x08,0xA6,0x55,0x73,0x2C,0xDD,0xD3,0x0C,0xA5,0xCA, - 0x68,0x48,0xAE,0xCE,0x5F,0xF2,0x56,0x4A,0x66,0x57,0xB2,0x2D,0xB5,0xC6,0xFF,0x50, - 0xD8,0x36,0x9C,0x31,0x31,0xE8,0xB2,0x07,0xE2,0x7B,0xC0,0xCE,0x72,0xA4,0x60,0x91, - 0xBB,0x84,0xA7,0xA8,0xC0,0x1D,0x42,0xE8,0x1D,0xF5,0xD9,0x6B,0x85,0x67,0x23,0x20, - 0xA6,0xF8,0x0F,0xBA,0x83,0x63,0x49,0xE2,0x79,0x23,0x90,0xFF,0x6B,0xEF,0xFA,0xB4, - 0x04,0xA8,0x99,0x1E,0x5D,0x5A,0xCD,0x8C,0xBC,0x8E,0x30,0x41,0x7E,0xE7,0x4E,0xDB, - 0x6F,0x4E,0xB7,0xBA,0xE0,0x5B,0x31,0xC4,0xD2,0x2D,0xD3,0x5D,0x82,0x95,0x44,0x7D, - 0x11,0x60,0x75,0xCE,0x6D,0x12,0xDA,0x89,0x71,0x23,0x80,0x75,0xC0,0x13,0x67,0x27, - 0xE8,0xE8,0xCA,0xE0,0xE3,0xFC,0x72,0x23,0x98,0xFA,0xF0,0x96,0x05,0x23,0xC9,0x03, - 0xC8,0x29,0xA4,0xB1,0xE5,0x07,0xE6,0xE8,0x09,0x26,0xD1,0x8C,0xAF,0xE0,0x53,0xBB, - 0xB4,0x1E,0x4D,0x5E,0xEA,0x9A,0x1E,0xE9,0x42,0x87,0x9F, -}; - -static unsigned char ist_intermediate_certificate[1092]={ - 0x30,0x82,0x04,0x40,0x30,0x82,0x03,0x28,0xA0,0x03,0x02,0x01,0x02,0x02,0x03,0x02, - 0x3A,0x74,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, - 0x00,0x30,0x42,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, - 0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x0A,0x13,0x0D,0x47,0x65,0x6F,0x54,0x72, - 0x75,0x73,0x74,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04, - 0x03,0x13,0x12,0x47,0x65,0x6F,0x54,0x72,0x75,0x73,0x74,0x20,0x47,0x6C,0x6F,0x62, - 0x61,0x6C,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x36,0x31,0x36,0x31, - 0x35,0x34,0x32,0x30,0x32,0x5A,0x17,0x0D,0x32,0x32,0x30,0x35,0x32,0x30,0x31,0x35, - 0x34,0x32,0x30,0x32,0x5A,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x03, - 0x13,0x13,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20,0x32, - 0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13,0x17, - 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75, - 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, - 0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09, - 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F, - 0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xD0,0x93,0xA1,0x1D,0x47,0x43, - 0x20,0x16,0xB2,0x0B,0x6B,0xEB,0xC3,0xD5,0xB4,0xE8,0xC7,0x98,0xCD,0xF3,0xDE,0xBF, - 0xE8,0x4D,0xE9,0xE3,0x36,0x80,0x07,0xFC,0x45,0x1B,0x6A,0x7C,0x45,0x86,0xAE,0x56, - 0xD3,0xA4,0x09,0x7F,0x61,0x0D,0x6B,0x5D,0x7E,0x52,0x6B,0x7D,0xB4,0xC8,0x39,0xC4, - 0xF4,0x67,0x3A,0xF7,0x83,0xCE,0x19,0x6F,0x86,0x2F,0x7E,0x45,0x7E,0x47,0x1C,0x67, - 0x52,0xCA,0x95,0x05,0x5D,0xE2,0x36,0x51,0x85,0xC0,0xD4,0x67,0x80,0x35,0x6F,0x15, - 0xDD,0x3E,0xFD,0x1D,0xD2,0xFD,0x8F,0x34,0x50,0xD8,0xEC,0x76,0x2A,0xBE,0xE3,0xD3, - 0xDA,0xE4,0xFD,0xC8,0xEB,0x28,0x02,0x96,0x11,0x97,0x17,0x61,0x1C,0xE9,0xC4,0x59, - 0x3B,0x42,0xDC,0x32,0xD1,0x09,0x1D,0xDA,0xA6,0xD1,0x43,0x86,0xFF,0x5E,0xB2,0xBC, - 0x8C,0xCF,0x66,0xDB,0x01,0x8B,0x02,0xAE,0x94,0x48,0xF3,0x38,0x8F,0xFD,0xEA,0x32, - 0xA8,0x08,0xEC,0x86,0x97,0x51,0x94,0x24,0x3E,0x49,0x49,0x96,0x53,0xE8,0x79,0xA1, - 0x40,0x81,0xE9,0x05,0xBB,0x93,0x95,0x51,0xFC,0xE3,0xFD,0x7C,0x11,0x4B,0xF7,0x9E, - 0x08,0xB3,0x15,0x49,0x15,0x07,0xF9,0xD1,0x37,0xA0,0x9B,0x4B,0x32,0xF6,0xB5,0xC4, - 0xDC,0x6A,0xD1,0xFC,0x0A,0xED,0xF6,0xE0,0xC5,0x29,0xA0,0xA8,0x8B,0x71,0xFE,0x0D, - 0x92,0xBC,0xFE,0x54,0x70,0x18,0x0A,0x6D,0xC7,0xED,0x0C,0xFB,0xC9,0x2D,0x06,0xC3, - 0x8C,0x85,0xFC,0xCB,0x86,0x5C,0xD6,0x36,0x8E,0x12,0x8B,0x09,0x7F,0xFB,0x19,0x1A, - 0x38,0xD5,0xF0,0x94,0x30,0x7A,0x0F,0xA6,0x8C,0xF3,0x02,0x03,0x01,0x00,0x01,0xA3, - 0x82,0x01,0x1D,0x30,0x82,0x01,0x19,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18, - 0x30,0x16,0x80,0x14,0xC0,0x7A,0x98,0x68,0x8D,0x89,0xFB,0xAB,0x05,0x64,0x0C,0x11, - 0x7D,0xAA,0x7D,0x65,0xB8,0xCA,0xCC,0x4E,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, - 0x16,0x04,0x14,0xD8,0x7A,0x94,0x44,0x7C,0x90,0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C, - 0x01,0x44,0x03,0x86,0xD6,0x2A,0x29,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, - 0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x0E,0x06,0x03,0x55, - 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x35,0x06,0x03,0x55, - 0x1D,0x1F,0x04,0x2E,0x30,0x2C,0x30,0x2A,0xA0,0x28,0xA0,0x26,0x86,0x24,0x68,0x74, - 0x74,0x70,0x3A,0x2F,0x2F,0x67,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D, - 0x2F,0x63,0x72,0x6C,0x73,0x2F,0x67,0x74,0x67,0x6C,0x6F,0x62,0x61,0x6C,0x2E,0x63, - 0x72,0x6C,0x30,0x2E,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x22, - 0x30,0x20,0x30,0x1E,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x12, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x67,0x2E,0x73,0x79,0x6D,0x63,0x64,0x2E,0x63, - 0x6F,0x6D,0x30,0x4C,0x06,0x03,0x55,0x1D,0x20,0x04,0x45,0x30,0x43,0x30,0x41,0x06, - 0x0A,0x60,0x86,0x48,0x01,0x86,0xF8,0x45,0x01,0x07,0x36,0x30,0x33,0x30,0x31,0x06, - 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x25,0x68,0x74,0x74,0x70,0x3A, - 0x2F,0x2F,0x77,0x77,0x77,0x2E,0x67,0x65,0x6F,0x74,0x72,0x75,0x73,0x74,0x2E,0x63, - 0x6F,0x6D,0x2F,0x72,0x65,0x73,0x6F,0x75,0x72,0x63,0x65,0x73,0x2F,0x63,0x70,0x73, - 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, - 0x82,0x01,0x01,0x00,0x16,0x47,0x73,0x6F,0x85,0xA2,0x62,0xE1,0xE7,0x2A,0x76,0xBB, - 0x89,0x95,0x42,0x26,0x97,0xBC,0x4A,0xAC,0xAC,0x70,0x53,0x3A,0x3F,0x31,0x83,0x3D, - 0x3C,0x1C,0xAB,0x9A,0xE2,0xB1,0x5D,0x1C,0x76,0x1A,0xA0,0x3C,0x0C,0x72,0x57,0xBE, - 0xD3,0x9E,0x50,0xE0,0xC8,0x99,0xD6,0x58,0xD7,0x02,0xEA,0xCE,0x0D,0x29,0x54,0x7C, - 0xCD,0xF5,0xC2,0xC6,0x90,0x29,0x55,0xA3,0x6F,0x14,0xA8,0x0B,0x42,0x0D,0x3A,0x98, - 0x6D,0x06,0x78,0x9E,0xF0,0x6A,0xA3,0x1D,0x02,0x0A,0xA2,0x28,0xA4,0x8D,0xC2,0x81, - 0x46,0x3E,0x6D,0x67,0xDA,0xDE,0x3F,0xFE,0x85,0x0E,0x42,0x2A,0x12,0xDE,0xB5,0xB7, - 0xFB,0xB8,0x1B,0xA7,0x96,0xEC,0x77,0x9F,0xEC,0xD4,0x53,0x95,0x7A,0xFF,0x07,0xF4, - 0xF2,0x0A,0x14,0xC0,0x51,0x52,0xB1,0xD6,0x8E,0x50,0x0B,0x1A,0x99,0x5C,0xBC,0x0B, - 0xC9,0xBD,0xED,0xED,0xF8,0x5E,0xC1,0x56,0xDB,0x4D,0x7E,0x23,0xA4,0x11,0xA1,0x2C, - 0xD4,0x1B,0x05,0x9A,0xE4,0x1B,0x52,0xF6,0x7C,0x38,0x99,0x05,0x4B,0xBA,0x72,0x8D, - 0x42,0x89,0x60,0x04,0x66,0x2A,0xF4,0xFD,0x68,0xD7,0x6B,0xF7,0x99,0x41,0x28,0xD6, - 0x6C,0x24,0xAB,0xE6,0x25,0x53,0x2E,0xC8,0x82,0x99,0xE2,0xA2,0x8F,0x23,0xBE,0x30, - 0x83,0xB1,0x27,0x8B,0xFA,0x68,0x7F,0x01,0x49,0xE8,0xC6,0x98,0x6B,0x10,0x2E,0x98, - 0x5E,0x8A,0xD7,0xCA,0x4B,0xB1,0xC7,0xC9,0x58,0x9A,0xD0,0x36,0xDB,0x96,0x95,0xEC, - 0xB6,0x81,0xE4,0xF2,0xCD,0x6F,0x1B,0x79,0x87,0x4C,0x10,0x3C,0x89,0xE4,0x4D,0xFA, - 0x54,0xDC,0xAA,0xA6, -}; - -unsigned char ocsp_smime_leaf_certificate[1338]={ - 0x30,0x82,0x05,0x36,0x30,0x82,0x04,0x1E,0xA0,0x03,0x02,0x01,0x02,0x02,0x0D,0x14, - 0x00,0x01,0x00,0x02,0x9C,0xE1,0xB9,0xE0,0x7C,0xD1,0x7B,0xEC,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x7C,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03, - 0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E, - 0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04, - 0x0B,0x13,0x1C,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65, - 0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20,0x43,0x41,0x31, - 0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1F,0x54,0x43,0x20,0x54,0x72,0x75, - 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31, - 0x20,0x4C,0x31,0x20,0x43,0x41,0x20,0x49,0x58,0x30,0x1E,0x17,0x0D,0x31,0x30,0x31, - 0x31,0x31,0x32,0x30,0x36,0x33,0x36,0x34,0x35,0x5A,0x17,0x0D,0x31,0x31,0x31,0x31, - 0x31,0x33,0x30,0x36,0x33,0x36,0x34,0x35,0x5A,0x30,0x24,0x31,0x0B,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04, - 0x03,0x13,0x0C,0x51,0x75,0x69,0x6E,0x6E,0x20,0x54,0x61,0x79,0x6C,0x6F,0x72,0x30, - 0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, - 0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00, - 0xC1,0x11,0xAA,0x04,0xCF,0x04,0xA0,0x07,0xF3,0x43,0x2A,0xB2,0x27,0x1A,0x13,0x35, - 0x97,0x9A,0xBA,0x34,0xE5,0x84,0xF3,0xD5,0xE5,0xD9,0xAB,0x23,0x8D,0xB4,0x7E,0x68, - 0x5C,0xF2,0x9A,0xF1,0x08,0x9B,0x04,0x34,0xC1,0x09,0x14,0x68,0xD8,0x9C,0xC1,0x6C, - 0x27,0xF5,0x92,0x54,0xAF,0x66,0x65,0xF1,0x50,0xAA,0x7E,0xE3,0xFC,0xC1,0xB0,0x3E, - 0xEF,0xAA,0x86,0x58,0x4F,0xE7,0x86,0x0A,0x74,0xA6,0x97,0xBD,0x7D,0xF6,0xCE,0xA6, - 0x8B,0xF7,0xC0,0x90,0x6E,0x50,0x69,0x36,0x65,0x82,0x0F,0x65,0xA7,0x2C,0x16,0xFA, - 0x6C,0xCA,0x54,0x45,0x7C,0x06,0x20,0x72,0xF0,0x00,0x7B,0xD7,0x17,0xCD,0x94,0x64, - 0x6A,0xB7,0x28,0xF3,0x62,0xB1,0x29,0xAE,0x0C,0x8A,0x2F,0x3C,0x06,0x89,0xE8,0x81, - 0x77,0xAD,0x1F,0x65,0xED,0x6F,0x51,0x64,0x65,0x68,0x76,0xD8,0xEE,0xEC,0xA6,0x28, - 0xA9,0x1C,0x4F,0x98,0x4A,0x6D,0xD0,0xC8,0x5C,0x59,0x17,0x9B,0xF8,0x6D,0xF5,0x93, - 0xD3,0x4C,0x2A,0x37,0x80,0x65,0xB4,0x34,0xBA,0x64,0x2F,0xA1,0x8E,0x1C,0x6A,0x88, - 0x7C,0xA3,0xDB,0xDD,0x00,0x9B,0x78,0x51,0x7B,0xA6,0x8D,0xDD,0x43,0x9B,0xB2,0x2E, - 0x4B,0x1E,0xB3,0x34,0x37,0x3F,0x63,0x08,0x8C,0xC8,0xCF,0xD0,0xB0,0x8C,0xBF,0x8F, - 0xA7,0x49,0xBD,0x48,0x1D,0xB5,0x1E,0x6A,0x42,0x48,0x16,0x9A,0x7C,0xD3,0x55,0x6B, - 0xFF,0xD6,0xBA,0x70,0xF3,0x5F,0x1F,0x57,0x16,0xE0,0x1C,0xF1,0x73,0x22,0xD9,0x33, - 0xA7,0x20,0xE8,0xED,0x52,0x2A,0xE9,0x6F,0xCF,0xFB,0x76,0xAC,0xB8,0x5D,0x9B,0xAB, - 0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x02,0x0D,0x30,0x82,0x02,0x09,0x30,0x81,0xA5, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x81,0x98,0x30,0x81,0x95, - 0x30,0x51,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x45,0x68,0x74, - 0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65, - 0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x65,0x72,0x74,0x73,0x65,0x72,0x76, - 0x69,0x63,0x65,0x73,0x2F,0x63,0x61,0x63,0x65,0x72,0x74,0x73,0x2F,0x74,0x63,0x5F, - 0x63,0x6C,0x61,0x73,0x73,0x31,0x5F,0x4C,0x31,0x5F,0x43,0x41,0x5F,0x49,0x58,0x2E, - 0x63,0x72,0x74,0x30,0x40,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86, - 0x34,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x69,0x78,0x2E, - 0x74,0x63,0x63,0x6C,0x61,0x73,0x73,0x31,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65, - 0x72,0x73,0x61,0x6C,0x2D,0x69,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2E,0x64,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, - 0x80,0x14,0xE9,0xB8,0x28,0x1D,0x46,0xCF,0xFC,0xCD,0xF8,0x4E,0x9B,0xC5,0xEE,0x4B, - 0x60,0xEB,0xD8,0x3B,0x3F,0xD1,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, - 0x04,0x02,0x30,0x00,0x30,0x4A,0x06,0x03,0x55,0x1D,0x20,0x04,0x43,0x30,0x41,0x30, - 0x3F,0x06,0x09,0x2A,0x82,0x14,0x00,0x2C,0x01,0x01,0x01,0x01,0x30,0x32,0x30,0x30, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x24,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2E,0x64,0x65,0x2F,0x67,0x75,0x69,0x64,0x65,0x6C,0x69,0x6E,0x65,0x73, - 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x04,0xF0, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xF8,0x4D,0x7F,0xDE,0xFA, - 0x21,0x2E,0xAF,0x96,0xBB,0xAA,0x9B,0x22,0x56,0x80,0xF0,0x8E,0xD4,0x6A,0x52,0x30, - 0x62,0x06,0x03,0x55,0x1D,0x1F,0x04,0x5B,0x30,0x59,0x30,0x57,0xA0,0x55,0xA0,0x53, - 0x86,0x51,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x69,0x78,0x2E, - 0x74,0x63,0x63,0x6C,0x61,0x73,0x73,0x31,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65, - 0x72,0x73,0x61,0x6C,0x2D,0x69,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x72,0x6C,0x2F,0x76,0x32,0x2F,0x74,0x63,0x5F, - 0x43,0x6C,0x61,0x73,0x73,0x31,0x5F,0x4C,0x31,0x5F,0x43,0x41,0x5F,0x49,0x58,0x2E, - 0x63,0x72,0x6C,0x30,0x33,0x06,0x03,0x55,0x1D,0x25,0x04,0x2C,0x30,0x2A,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x03,0x04,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x07,0x06,0x0A,0x2B,0x06, - 0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02,0x30,0x1C,0x06,0x03,0x55,0x1D,0x11,0x04, - 0x15,0x30,0x13,0x81,0x11,0x71,0x74,0x61,0x79,0x6C,0x6F,0x72,0x40,0x61,0x70,0x70, - 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x0D,0xCF,0x33,0xAB,0x3D,0xD3, - 0xD2,0x06,0x2C,0x20,0x3C,0xEC,0x0C,0xE4,0xA5,0x19,0x86,0xB3,0xA7,0xA9,0xA6,0xE9, - 0xDC,0xB4,0x35,0xBB,0x0D,0x67,0xD5,0xBD,0x5F,0x93,0xD9,0x2E,0xA0,0x05,0x2A,0xED, - 0xAE,0x41,0xD9,0xEE,0x30,0xA8,0x82,0x50,0xD0,0x4B,0x04,0x6B,0x37,0xAE,0xC0,0x10, - 0x89,0x05,0x68,0x82,0x91,0x2B,0x5B,0xE2,0x7D,0xA6,0x87,0xF7,0x26,0x96,0xBA,0x2A, - 0x52,0x03,0x97,0xF6,0x2E,0x0D,0x81,0x65,0x24,0x10,0xD5,0x8C,0xB3,0xCD,0x19,0x58, - 0xAF,0x3A,0x3D,0x2F,0x10,0x30,0x79,0x6A,0xD6,0x08,0x8F,0x8B,0x9D,0x1D,0xF8,0x19, - 0xE4,0x24,0x2B,0xE0,0x7F,0x73,0xE1,0x50,0x9C,0x53,0xE1,0x46,0xC7,0xA7,0xBD,0x71, - 0xCD,0xFF,0x39,0xA0,0x50,0xA5,0xA8,0xD9,0x50,0x39,0x6C,0x36,0x1C,0x13,0x89,0x8A, - 0x0D,0x9D,0x06,0x1B,0xAA,0x59,0x40,0xC1,0xAF,0xED,0x66,0x31,0xB8,0xA0,0x9F,0xCF, - 0xA6,0x8A,0x2E,0xC2,0x1A,0x4B,0xDB,0x62,0x15,0x6E,0x10,0x2F,0x82,0x3C,0xF8,0xA2, - 0x18,0x63,0xCC,0x67,0x13,0x42,0x07,0x43,0xDB,0x20,0x13,0xC7,0xAC,0xCE,0xCB,0xEA, - 0x7E,0x53,0xA6,0x01,0x81,0xB2,0x6E,0x92,0x2B,0x0C,0xF9,0x01,0x2C,0x11,0xC9,0x00, - 0x10,0x58,0x64,0x56,0x91,0xAC,0xAA,0xF6,0xE0,0x73,0xC7,0x59,0xEC,0xCE,0x51,0x7E, - 0xAD,0x9F,0x04,0xA4,0x38,0x74,0x65,0xD0,0x23,0xBD,0x6E,0xDF,0x64,0x79,0xE2,0xA3, - 0x37,0x19,0x2F,0x8C,0x41,0x8B,0x5F,0x6D,0x84,0x61,0x54,0xD1,0x26,0x18,0x70,0xAD, - 0xE5,0xF4,0xCD,0x59,0xED,0x9E,0xE0,0xC9,0x9F,0xD3, -}; - -unsigned char ocsp_smime_CA_certificate[1500]={ - 0x30,0x82,0x05,0xD8,0x30,0x82,0x04,0xC0,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x06, - 0xE8,0x00,0x01,0x00,0x02,0x4A,0x96,0x2D,0x24,0x0C,0xFE,0xC5,0xC9,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x79,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, - 0x6E,0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x1B,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74, - 0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31, - 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75, - 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73, - 0x61,0x6C,0x20,0x43,0x41,0x20,0x49,0x30,0x1E,0x17,0x0D,0x30,0x39,0x31,0x31,0x30, - 0x33,0x31,0x34,0x30,0x38,0x31,0x39,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x33,0x31, - 0x32,0x31,0x35,0x39,0x35,0x39,0x5A,0x30,0x7C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20, - 0x47,0x6D,0x62,0x48,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C,0x54, - 0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x43,0x6C, - 0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20,0x43,0x41,0x31,0x28,0x30,0x26,0x06, - 0x03,0x55,0x04,0x03,0x13,0x1F,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, - 0x6E,0x74,0x65,0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20, - 0x43,0x41,0x20,0x49,0x58,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, - 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, - 0x0A,0x02,0x82,0x01,0x01,0x00,0xBB,0xE6,0x90,0x6E,0xCF,0x62,0xE9,0xE9,0x0B,0xAA, - 0xB6,0x10,0xD5,0x47,0xE5,0x7C,0x5D,0x2B,0x27,0x71,0x9A,0x68,0xCD,0x55,0x6D,0xE4, - 0xA2,0xEF,0xE4,0xFE,0xF2,0x7A,0x63,0x11,0xC2,0x57,0x8A,0xC8,0x7D,0xCF,0x8E,0x66, - 0x1F,0x65,0x45,0x4B,0xEB,0x80,0x62,0x69,0xBD,0x46,0x8E,0x8B,0xC5,0x6E,0x5A,0x95, - 0x18,0x2A,0xDE,0xA7,0xF1,0x1F,0x75,0x1A,0x27,0xAB,0x6D,0x32,0x53,0xE3,0xFB,0x4D, - 0x58,0x62,0x2C,0xFF,0x19,0xE5,0xC7,0xA0,0x0D,0x9A,0x2D,0x21,0x88,0x59,0x84,0xCD, - 0x1D,0xF1,0xC3,0xC8,0x8A,0x3E,0xB0,0xE5,0xDE,0x08,0x24,0xCF,0xFC,0x40,0x2C,0xBA, - 0x41,0x23,0x94,0xBB,0x80,0x12,0x89,0x35,0x48,0xB6,0x86,0x04,0xE0,0x01,0x4F,0x8C, - 0xBA,0xA9,0x98,0xFC,0x1C,0x89,0xED,0x1F,0x8A,0xA1,0xC7,0x86,0x98,0x26,0x1E,0x72, - 0x65,0x6B,0xFE,0xCF,0x65,0xD9,0x0C,0x64,0x4B,0x1A,0x09,0xF5,0x43,0x11,0x60,0x66, - 0x26,0xE3,0x33,0x56,0x9A,0xC9,0x3D,0x3E,0x34,0x6A,0x78,0xC6,0xE5,0x50,0x4B,0xC8, - 0xCD,0x88,0xE4,0x39,0x6C,0x50,0x26,0x9E,0x40,0x2C,0xB6,0x3B,0x7C,0x37,0xB2,0xA7, - 0xF5,0xDD,0xDC,0xB3,0x51,0xCB,0xF4,0xDC,0x82,0x02,0xB8,0xD7,0x3A,0xDE,0xDA,0x30, - 0x5C,0x0D,0xF5,0x42,0xDD,0x13,0x69,0x53,0x54,0xE9,0x80,0x26,0x42,0x33,0x1E,0xA5, - 0xD7,0xCC,0x6E,0xCA,0x66,0x09,0x9F,0x86,0xF0,0x3D,0xBE,0xC6,0x8A,0x61,0x10,0xF3, - 0xD1,0xFF,0x5B,0xE4,0xB2,0xDB,0x2D,0xB2,0x65,0x0C,0xA9,0x7D,0x17,0xAC,0xBA,0x27, - 0x4D,0x42,0x5C,0xCE,0x09,0x4F,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x02,0x59,0x30, - 0x82,0x02,0x55,0x30,0x81,0x9A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, - 0x04,0x81,0x8D,0x30,0x81,0x8A,0x30,0x52,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x30,0x02,0x86,0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74, - 0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x65, - 0x72,0x74,0x73,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x2F,0x63,0x61,0x63,0x65,0x72, - 0x74,0x73,0x2F,0x74,0x63,0x5F,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x5F, - 0x72,0x6F,0x6F,0x74,0x5F,0x49,0x2E,0x63,0x72,0x74,0x30,0x34,0x06,0x08,0x2B,0x06, - 0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x28,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F, - 0x63,0x73,0x70,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x2D, - 0x49,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65, - 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x92,0xA4,0x75, - 0x2C,0xA4,0x9E,0xBE,0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75, - 0x73,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01, - 0x01,0xFF,0x02,0x01,0x00,0x30,0x52,0x06,0x03,0x55,0x1D,0x20,0x04,0x4B,0x30,0x49, - 0x30,0x06,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x3F,0x06,0x09,0x2A,0x82,0x14,0x00, - 0x2C,0x01,0x01,0x01,0x01,0x30,0x32,0x30,0x30,0x06,0x08,0x2B,0x06,0x01,0x05,0x05, - 0x07,0x02,0x01,0x16,0x24,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E, - 0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x67, - 0x75,0x69,0x64,0x65,0x6C,0x69,0x6E,0x65,0x73,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, - 0x04,0x16,0x04,0x14,0xE9,0xB8,0x28,0x1D,0x46,0xCF,0xFC,0xCD,0xF8,0x4E,0x9B,0xC5, - 0xEE,0x4B,0x60,0xEB,0xD8,0x3B,0x3F,0xD1,0x30,0x81,0xFD,0x06,0x03,0x55,0x1D,0x1F, - 0x04,0x81,0xF5,0x30,0x81,0xF2,0x30,0x81,0xEF,0xA0,0x81,0xEC,0xA0,0x81,0xE9,0x86, - 0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x74,0x63,0x75,0x6E, - 0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x2D,0x49,0x2E,0x74,0x72,0x75,0x73,0x74,0x63, - 0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x72,0x6C,0x2F,0x76,0x32,0x2F, - 0x74,0x63,0x5F,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x5F,0x72,0x6F,0x6F, - 0x74,0x5F,0x49,0x2E,0x63,0x72,0x6C,0x86,0x81,0x9E,0x6C,0x64,0x61,0x70,0x3A,0x2F, - 0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72, - 0x2E,0x64,0x65,0x2F,0x43,0x4E,0x3D,0x54,0x43,0x25,0x32,0x30,0x54,0x72,0x75,0x73, - 0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x25,0x32,0x30,0x55,0x6E,0x69,0x76,0x65,0x72, - 0x73,0x61,0x6C,0x25,0x32,0x30,0x43,0x41,0x25,0x32,0x30,0x49,0x2C,0x4F,0x3D,0x54, - 0x43,0x25,0x32,0x30,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x25, - 0x32,0x30,0x47,0x6D,0x62,0x48,0x2C,0x4F,0x55,0x3D,0x72,0x6F,0x6F,0x74,0x63,0x65, - 0x72,0x74,0x73,0x2C,0x44,0x43,0x3D,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2C,0x44,0x43,0x3D,0x64,0x65,0x3F,0x63,0x65,0x72,0x74,0x69,0x66,0x69, - 0x63,0x61,0x74,0x65,0x52,0x65,0x76,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x4C,0x69, - 0x73,0x74,0x3F,0x62,0x61,0x73,0x65,0x3F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x39,0xC8,0xC4,0x9B, - 0xEE,0xBE,0x98,0xEE,0x48,0x72,0x6F,0x8D,0xE7,0x71,0xB6,0x0E,0x90,0x8C,0xD3,0xB2, - 0xC1,0x15,0x21,0xA8,0x46,0x90,0x68,0x5F,0x4A,0x04,0xF1,0x3A,0xC9,0x68,0x84,0x21, - 0xD8,0xA5,0xE6,0x04,0x75,0x5D,0x9F,0xD2,0xD4,0xF2,0x4B,0x77,0x43,0x32,0xDC,0x95, - 0xCB,0x60,0xBF,0x02,0x55,0xD0,0xAC,0x1C,0xB0,0xC5,0x14,0x97,0x9B,0x65,0x0A,0xC3, - 0x0F,0xA5,0x1D,0xEC,0xD8,0x49,0x39,0x95,0xB5,0xA9,0xBE,0xFA,0xF4,0x1E,0xAB,0x56, - 0xE7,0xA6,0xE5,0x01,0x08,0x88,0x35,0x5F,0x67,0x05,0xDD,0x44,0x24,0x50,0x12,0x22, - 0x44,0x63,0x79,0xF1,0x9B,0x57,0x69,0xCE,0xAB,0xD6,0x33,0x51,0x4F,0x8D,0xF0,0x70, - 0x3B,0x8E,0xAD,0x51,0x3A,0x17,0x7F,0x35,0x96,0x6B,0x68,0x68,0x63,0xB6,0x1C,0x0A, - 0xC9,0xF8,0xDF,0x1D,0x5E,0xCF,0x2B,0x11,0xA5,0x63,0xED,0xCC,0xD0,0xC6,0xD3,0x20, - 0x6F,0xAA,0xFC,0x68,0x48,0x7E,0x6D,0x1E,0xB8,0x3A,0x45,0xAA,0x12,0x86,0xF3,0xC7, - 0xBD,0x00,0xB5,0xEB,0xFE,0xEA,0x12,0x9F,0x73,0x33,0x78,0xE7,0x28,0x39,0x68,0xD3, - 0xA5,0x6D,0xDA,0x76,0xD1,0x4E,0xE1,0x55,0x95,0x80,0xA6,0xE0,0x1B,0xB8,0xCD,0xAC, - 0x56,0xEF,0x45,0x59,0x47,0x98,0x52,0xDB,0x3A,0x6E,0x26,0xB2,0x31,0x39,0x69,0x75, - 0xB1,0x2E,0x24,0xF0,0xA4,0x9D,0x97,0x88,0x5E,0x33,0x29,0xC6,0xB5,0xBC,0x07,0x40, - 0x3A,0x0C,0x3D,0xBA,0xCF,0x74,0x8C,0x4B,0x4E,0x7A,0x21,0xFA,0x1B,0x38,0xCD,0xC4, - 0x43,0x2F,0x6F,0xB4,0xDF,0x78,0xEE,0x99,0x92,0xE7,0x3A,0x1C, -}; - -unsigned char ocsp_smime_root_certificate[993]={ - 0x30,0x82,0x03,0xDD,0x30,0x82,0x02,0xC5,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x1D, - 0xA2,0x00,0x01,0x00,0x02,0xEC,0xB7,0x60,0x80,0x78,0x8D,0xB6,0x06,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x79,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, - 0x6E,0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x1B,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74, - 0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31, - 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75, - 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73, - 0x61,0x6C,0x20,0x43,0x41,0x20,0x49,0x30,0x1E,0x17,0x0D,0x30,0x36,0x30,0x33,0x32, - 0x32,0x31,0x35,0x35,0x34,0x32,0x38,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x33,0x31, - 0x32,0x32,0x35,0x39,0x35,0x39,0x5A,0x30,0x79,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20, - 0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x0B,0x13,0x1B,0x54, - 0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E, - 0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03, - 0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E, - 0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41, - 0x20,0x49,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82, - 0x01,0x01,0x00,0xA4,0x77,0x23,0x96,0x44,0xAF,0x90,0xF4,0x31,0xA7,0x10,0xF4,0x26, - 0x87,0x9C,0xF3,0x38,0xD9,0x0F,0x5E,0xDE,0xCF,0x41,0xE8,0x31,0xAD,0xC6,0x74,0x91, - 0x24,0x96,0x78,0x1E,0x09,0xA0,0x9B,0x9A,0x95,0x4A,0x4A,0xF5,0x62,0x7C,0x02,0xA8, - 0xCA,0xAC,0xFB,0x5A,0x04,0x76,0x39,0xDE,0x5F,0xF1,0xF9,0xB3,0xBF,0xF3,0x03,0x58, - 0x55,0xD2,0xAA,0xB7,0xE3,0x04,0x22,0xD1,0xF8,0x94,0xDA,0x22,0x08,0x00,0x8D,0xD3, - 0x7C,0x26,0x5D,0xCC,0x77,0x79,0xE7,0x2C,0x78,0x39,0xA8,0x26,0x73,0x0E,0xA2,0x5D, - 0x25,0x69,0x85,0x4F,0x55,0x0E,0x9A,0xEF,0xC6,0xB9,0x44,0xE1,0x57,0x3D,0xDF,0x1F, - 0x54,0x22,0xE5,0x6F,0x65,0xAA,0x33,0x84,0x3A,0xF3,0xCE,0x7A,0xBE,0x55,0x97,0xAE, - 0x8D,0x12,0x0F,0x14,0x33,0xE2,0x50,0x70,0xC3,0x49,0x87,0x13,0xBC,0x51,0xDE,0xD7, - 0x98,0x12,0x5A,0xEF,0x3A,0x83,0x33,0x92,0x06,0x75,0x8B,0x92,0x7C,0x12,0x68,0x7B, - 0x70,0x6A,0x0F,0xB5,0x9B,0xB6,0x77,0x5B,0x48,0x59,0x9D,0xE4,0xEF,0x5A,0xAD,0xF3, - 0xC1,0x9E,0xD4,0xD7,0x45,0x4E,0xCA,0x56,0x34,0x21,0xBC,0x3E,0x17,0x5B,0x6F,0x77, - 0x0C,0x48,0x01,0x43,0x29,0xB0,0xDD,0x3F,0x96,0x6E,0xE6,0x95,0xAA,0x0C,0xC0,0x20, - 0xB6,0xFD,0x3E,0x36,0x27,0x9C,0xE3,0x5C,0xCF,0x4E,0x81,0xDC,0x19,0xBB,0x91,0x90, - 0x7D,0xEC,0xE6,0x97,0x04,0x1E,0x93,0xCC,0x22,0x49,0xD7,0x97,0x86,0xB6,0x13,0x0A, - 0x3C,0x43,0x23,0x77,0x7E,0xF0,0xDC,0xE6,0xCD,0x24,0x1F,0x3B,0x83,0x9B,0x34,0x3A, - 0x83,0x34,0xE3,0x02,0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x1F,0x06,0x03, - 0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x92,0xA4,0x75,0x2C,0xA4,0x9E,0xBE, - 0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75,0x73,0x30,0x0F,0x06, - 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E, - 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x1D, - 0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x92,0xA4,0x75,0x2C,0xA4,0x9E,0xBE, - 0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75,0x73,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01, - 0x00,0x28,0xD2,0xE0,0x86,0xD5,0xE6,0xF8,0x7B,0xF0,0x97,0xDC,0x22,0x6B,0x3B,0x95, - 0x14,0x56,0x0F,0x11,0x30,0xA5,0x9A,0x4F,0x3A,0xB0,0x3A,0xE0,0x06,0xCB,0x65,0xF5, - 0xED,0xC6,0x97,0x27,0xFE,0x25,0xF2,0x57,0xE6,0x5E,0x95,0x8C,0x3E,0x64,0x60,0x15, - 0x5A,0x7F,0x2F,0x0D,0x01,0xC5,0xB1,0x60,0xFD,0x45,0x35,0xCF,0xF0,0xB2,0xBF,0x06, - 0xD9,0xEF,0x5A,0xBE,0xB3,0x62,0x21,0xB4,0xD7,0xAB,0x35,0x7C,0x53,0x3E,0xA6,0x27, - 0xF1,0xA1,0x2D,0xDA,0x1A,0x23,0x9D,0xCC,0xDD,0xEC,0x3C,0x2D,0x9E,0x27,0x34,0x5D, - 0x0F,0xC2,0x36,0x79,0xBC,0xC9,0x4A,0x62,0x2D,0xED,0x6B,0xD9,0x7D,0x41,0x43,0x7C, - 0xB6,0xAA,0xCA,0xED,0x61,0xB1,0x37,0x82,0x15,0x09,0x1A,0x8A,0x16,0x30,0xD8,0xEC, - 0xC9,0xD6,0x47,0x72,0x78,0x4B,0x10,0x46,0x14,0x8E,0x5F,0x0E,0xAF,0xEC,0xC7,0x2F, - 0xAB,0x10,0xD7,0xB6,0xF1,0x6E,0xEC,0x86,0xB2,0xC2,0xE8,0x0D,0x92,0x73,0xDC,0xA2, - 0xF4,0x0F,0x3A,0xBF,0x61,0x23,0x10,0x89,0x9C,0x48,0x40,0x6E,0x70,0x00,0xB3,0xD3, - 0xBA,0x37,0x44,0x58,0x11,0x7A,0x02,0x6A,0x88,0xF0,0x37,0x34,0xF0,0x19,0xE9,0xAC, - 0xD4,0x65,0x73,0xF6,0x69,0x8C,0x64,0x94,0x3A,0x79,0x85,0x29,0xB0,0x16,0x2B,0x0C, - 0x82,0x3F,0x06,0x9C,0xC7,0xFD,0x10,0x2B,0x9E,0x0F,0x2C,0xB6,0x9E,0xE3,0x15,0xBF, - 0xD9,0x36,0x1C,0xBA,0x25,0x1A,0x52,0x3D,0x1A,0xEC,0x22,0x0C,0x1C,0xE0,0xA4,0xA2, - 0x3D,0xF0,0xE8,0x39,0xCF,0x81,0xC0,0x7B,0xED,0x5D,0x1F,0x6F,0xC5,0xD0,0x0B,0xD7, - 0x98, -}; - -/* subject:/C=US/ST=California/L=Walnut Creek/O=Lucas Garron/CN=revoked.badssl.com */ -/* issuer :/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA */ -uint8_t _probablyRevokedLeaf[]={ - 0x30,0x82,0x06,0xA1,0x30,0x82,0x05,0x89,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x01, - 0xAF,0x1E,0xFB,0xDD,0x5E,0xAE,0x09,0x52,0x32,0x0B,0x24,0xFE,0x6B,0x55,0x68,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x4D, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x03,0x13,0x1E,0x44, - 0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x20,0x53,0x48,0x41,0x32,0x20,0x53,0x65,0x63, - 0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,0x30,0x1E,0x17, - 0x0D,0x31,0x36,0x30,0x39,0x30,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D, - 0x31,0x39,0x30,0x39,0x31,0x31,0x31,0x32,0x30,0x30,0x30,0x30,0x5A,0x30,0x6D,0x31, - 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, - 0x06,0x03,0x55,0x04,0x08,0x13,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69, - 0x61,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x07,0x13,0x0C,0x57,0x61,0x6C,0x6E, - 0x75,0x74,0x20,0x43,0x72,0x65,0x65,0x6B,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04, - 0x0A,0x13,0x0C,0x4C,0x75,0x63,0x61,0x73,0x20,0x47,0x61,0x72,0x72,0x6F,0x6E,0x31, - 0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x13,0x12,0x72,0x65,0x76,0x6F,0x6B,0x65, - 0x64,0x2E,0x62,0x61,0x64,0x73,0x73,0x6C,0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01,0x22, - 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03, - 0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC7,0x31,0x65, - 0xE4,0x55,0xCF,0x69,0x90,0x9F,0x6E,0x1F,0xD8,0x6A,0x13,0x7E,0x74,0xBF,0x13,0x3A, - 0x54,0x64,0x0F,0x74,0x24,0x3D,0xDC,0x60,0xB8,0xA7,0x45,0x01,0xB7,0xC8,0x6A,0x03, - 0xAC,0x64,0x4A,0x65,0xF0,0x7C,0x81,0x81,0x83,0x0A,0xD9,0xDD,0x31,0x20,0x82,0x48, - 0xA6,0x33,0x63,0xEE,0x2B,0x74,0xEA,0xB4,0xE6,0xC7,0x1C,0xB2,0x5E,0xE4,0x28,0x3A, - 0x7A,0x3D,0x20,0x19,0x03,0xB7,0x15,0x3F,0x4F,0xC9,0x26,0xEC,0xB7,0xCB,0xBF,0x48, - 0x6E,0x5F,0x34,0x70,0x56,0xC4,0x86,0xC7,0xE3,0x52,0x9A,0x21,0x33,0x2F,0x10,0x13, - 0xF3,0x25,0x0C,0x1E,0x94,0x35,0x2E,0xE8,0xD0,0xD1,0xB5,0xA0,0x77,0x40,0x91,0x2E, - 0xE9,0xBA,0xF8,0xFF,0x4E,0xF5,0xFB,0xF2,0x7A,0x04,0xA7,0xE6,0xC6,0xCE,0x3F,0x0F, - 0x10,0x18,0x32,0xC8,0x06,0xBC,0x15,0xB3,0xBE,0x69,0xAC,0x75,0x7D,0x42,0xA0,0x8C, - 0x2E,0xC3,0xAC,0xE1,0x20,0x4F,0x1E,0x36,0x9C,0x9A,0x2E,0xA2,0xFD,0x79,0x80,0xB6, - 0x62,0xF8,0xC0,0xB2,0x03,0xA9,0x29,0x50,0xCC,0xD5,0x25,0x8A,0x33,0x5E,0xE0,0x78, - 0x13,0x18,0xC0,0x80,0x17,0x09,0x95,0xBD,0xA2,0xFE,0x92,0x15,0x07,0x20,0x7A,0x81, - 0xCE,0xDB,0x0E,0x81,0x29,0x89,0xD4,0xC8,0xEC,0xB3,0xB3,0x79,0x0E,0xF2,0xCE,0x25, - 0xE7,0xEE,0xBE,0x21,0x7D,0xAF,0x0C,0x13,0x94,0x29,0xDE,0x35,0x9A,0x1E,0xD8,0x84, - 0x18,0x5A,0x5C,0x1A,0x94,0x82,0xCE,0x9A,0x61,0xD6,0x9D,0xEC,0xF8,0xEE,0xAD,0x3F, - 0x09,0x5B,0x73,0xEC,0xA2,0x9B,0xFA,0xDC,0x62,0xF1,0x58,0x1F,0x7D,0x02,0x03,0x01, - 0x00,0x01,0xA3,0x82,0x03,0x5B,0x30,0x82,0x03,0x57,0x30,0x1F,0x06,0x03,0x55,0x1D, - 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x0F,0x80,0x61,0x1C,0x82,0x31,0x61,0xD5,0x2F, - 0x28,0xE7,0x8D,0x46,0x38,0xB4,0x2C,0xE1,0xC6,0xD9,0xE2,0x30,0x1D,0x06,0x03,0x55, - 0x1D,0x0E,0x04,0x16,0x04,0x14,0xF4,0x48,0x7D,0x07,0x45,0x1A,0x32,0x07,0x90,0x91, - 0xAC,0x05,0xB8,0x9F,0xA9,0x11,0xF0,0x7E,0x11,0x36,0x30,0x1D,0x06,0x03,0x55,0x1D, - 0x11,0x04,0x16,0x30,0x14,0x82,0x12,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x2E,0x62, - 0x61,0x64,0x73,0x73,0x6C,0x2E,0x63,0x6F,0x6D,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25, - 0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x6B,0x06,0x03,0x55,0x1D,0x1F,0x04, - 0x64,0x30,0x62,0x30,0x2F,0xA0,0x2D,0xA0,0x2B,0x86,0x29,0x68,0x74,0x74,0x70,0x3A, - 0x2F,0x2F,0x63,0x72,0x6C,0x33,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E, - 0x63,0x6F,0x6D,0x2F,0x73,0x73,0x63,0x61,0x2D,0x73,0x68,0x61,0x32,0x2D,0x67,0x35, - 0x2E,0x63,0x72,0x6C,0x30,0x2F,0xA0,0x2D,0xA0,0x2B,0x86,0x29,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x34,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74, - 0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x73,0x63,0x61,0x2D,0x73,0x68,0x61,0x32,0x2D,0x67, - 0x35,0x2E,0x63,0x72,0x6C,0x30,0x4C,0x06,0x03,0x55,0x1D,0x20,0x04,0x45,0x30,0x43, - 0x30,0x37,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xFD,0x6C,0x01,0x01,0x30,0x2A,0x30, - 0x28,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74, - 0x70,0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72, - 0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x08,0x06,0x06,0x67,0x81,0x0C, - 0x01,0x02,0x03,0x30,0x7C,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04, - 0x70,0x30,0x6E,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86, - 0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69,0x67, - 0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x46,0x06,0x08,0x2B,0x06,0x01, - 0x05,0x05,0x07,0x30,0x02,0x86,0x3A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x61, - 0x63,0x65,0x72,0x74,0x73,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63, - 0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x53,0x48,0x41,0x32,0x53, - 0x65,0x63,0x75,0x72,0x65,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72, - 0x74,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, - 0x82,0x01,0x7E,0x06,0x0A,0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02,0x04, - 0x82,0x01,0x6E,0x04,0x82,0x01,0x6A,0x01,0x68,0x00,0x75,0x00,0xA4,0xB9,0x09,0x90, - 0xB4,0x18,0x58,0x14,0x87,0xBB,0x13,0xA2,0xCC,0x67,0x70,0x0A,0x3C,0x35,0x98,0x04, - 0xF9,0x1B,0xDF,0xB8,0xE3,0x77,0xCD,0x0E,0xC8,0x0D,0xDC,0x10,0x00,0x00,0x01,0x56, - 0xEC,0xA1,0x37,0xDA,0x00,0x00,0x04,0x03,0x00,0x46,0x30,0x44,0x02,0x20,0x3F,0x6C, - 0xA8,0xF5,0xC4,0x7C,0x01,0x4C,0xC3,0x5A,0x28,0x27,0x50,0x47,0x63,0xD9,0xAC,0xE1, - 0xBE,0x2D,0xBF,0x87,0x78,0xCB,0x3A,0x80,0x97,0x24,0x74,0xCD,0x16,0xF7,0x02,0x20, - 0x71,0xFF,0x93,0xA2,0xB5,0x54,0x7E,0x7F,0x53,0x45,0x7F,0x59,0x5A,0x60,0x18,0x21, - 0x5C,0xAB,0x7D,0x1F,0x08,0xB2,0x54,0xA0,0xB3,0xC4,0x88,0xA5,0x83,0xD2,0x63,0x55, - 0x00,0x77,0x00,0x68,0xF6,0x98,0xF8,0x1F,0x64,0x82,0xBE,0x3A,0x8C,0xEE,0xB9,0x28, - 0x1D,0x4C,0xFC,0x71,0x51,0x5D,0x67,0x93,0xD4,0x44,0xD1,0x0A,0x67,0xAC,0xBB,0x4F, - 0x4F,0xFB,0xC4,0x00,0x00,0x01,0x56,0xEC,0xA1,0x37,0xA1,0x00,0x00,0x04,0x03,0x00, - 0x48,0x30,0x46,0x02,0x21,0x00,0xFE,0x59,0x97,0x22,0x4C,0x6C,0x0F,0x39,0x05,0xD9, - 0xE4,0xCA,0x7E,0x3B,0xD3,0xB3,0x47,0x1B,0x61,0x72,0xB6,0x3A,0x4F,0xD6,0xF2,0xA3, - 0x57,0x49,0x48,0x4F,0x6A,0x6D,0x02,0x21,0x00,0x8F,0x14,0x1B,0x3C,0x1B,0x89,0xA3, - 0x1D,0x70,0xEC,0xD4,0xD7,0x11,0xBC,0xF9,0x0B,0x3C,0x60,0xAC,0x8C,0x84,0x73,0x24, - 0x6B,0x0E,0x37,0x6E,0x53,0x7F,0x9D,0x7F,0x34,0x00,0x76,0x00,0x56,0x14,0x06,0x9A, - 0x2F,0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC, - 0x99,0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x56, - 0xEC,0xA1,0x38,0x7F,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x0E,0xBF, - 0x53,0x59,0x17,0x0C,0xEC,0x66,0x0C,0x5E,0x87,0xBB,0x8F,0x5F,0xB6,0x76,0x86,0xF2, - 0x5C,0xFC,0xBC,0xA8,0xB9,0xC0,0xDF,0xBC,0x1A,0x3B,0xEE,0x11,0xF2,0xD0,0x02,0x21, - 0x00,0x87,0x25,0x39,0xE4,0x32,0x99,0x48,0xCA,0x20,0x1B,0x13,0x96,0x1D,0xC3,0x2C, - 0x98,0x6B,0x1B,0xC0,0xCC,0xE5,0x67,0x22,0xBD,0x92,0x14,0xE9,0x68,0xCD,0x95,0x82, - 0x32,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, - 0x03,0x82,0x01,0x01,0x00,0x5A,0xA0,0x49,0x88,0xAD,0x60,0x1F,0x08,0x53,0x4C,0xD9, - 0xB8,0xDC,0xF5,0x40,0x41,0xAD,0xEF,0xC8,0x7B,0x01,0x3B,0x13,0x70,0x44,0x99,0xF6, - 0x5C,0x23,0x46,0xF7,0x3A,0xC8,0x7D,0xC9,0x21,0xAD,0x3A,0x49,0x45,0x82,0x1E,0x5D, - 0x3B,0x1E,0x9B,0x6A,0x0A,0x3E,0x61,0x2D,0xF6,0xB1,0x99,0x74,0x2F,0x91,0xF9,0xD5, - 0xF1,0x9F,0xAE,0x74,0x26,0x8B,0x3C,0xA7,0x8C,0xBE,0x28,0xFE,0xAC,0x3B,0x70,0xAE, - 0x08,0x56,0x71,0xAC,0x55,0x7C,0x40,0x89,0x02,0x2D,0x61,0x2A,0xFD,0x54,0x72,0xBF, - 0x1A,0x5C,0x70,0x19,0x90,0x15,0xA4,0x76,0xA0,0x7F,0x56,0x1C,0xC1,0xF0,0x8D,0x5E, - 0x99,0x3D,0x83,0x41,0x54,0x68,0xE5,0x62,0xC1,0x5A,0xA2,0x64,0x8C,0x01,0x64,0x7A, - 0x23,0xB9,0x3F,0xBF,0x22,0xCF,0x1F,0xC0,0x47,0x80,0x1F,0x94,0xD5,0xF2,0x30,0x84, - 0xFB,0x07,0x02,0xFA,0x5B,0xA0,0xBA,0x09,0x04,0x98,0x4E,0xF3,0x25,0x56,0x4C,0xC4, - 0x7E,0xE0,0x27,0xD8,0xE8,0x32,0x8F,0xB3,0x3C,0x5A,0x92,0x4B,0xC0,0x77,0x2D,0xB0, - 0xE5,0xAE,0x1F,0xAF,0x1D,0x7F,0x21,0x9C,0x65,0x26,0xBE,0x0C,0xBA,0xE8,0x0D,0xC1, - 0xD2,0x67,0xB4,0xB9,0x33,0xD1,0x4A,0xEE,0xFC,0xB8,0xAF,0x03,0x5B,0xC8,0x3E,0xBC, - 0xFA,0x09,0x9D,0x04,0xCE,0x3E,0xA6,0xB5,0xC4,0x74,0x3B,0x31,0x7A,0xF3,0x2C,0x42, - 0xB3,0xC7,0x73,0xDB,0xAA,0x75,0x2E,0x8D,0x8A,0x9E,0x79,0x33,0xBE,0xD7,0xB6,0x14, - 0x9B,0x26,0xAB,0x7B,0x9E,0x14,0xB3,0x55,0xE6,0x4B,0xBB,0x86,0x94,0x11,0x74,0x02, - 0x35,0xB4,0x52,0x70,0x9B, -}; - -/* subject:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA */ -uint8_t _digiCertSha2SubCA[] ={ - 0x30,0x82,0x04,0x94,0x30,0x82,0x03,0x7C,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x01, - 0xFD,0xA3,0xEB,0x6E,0xCA,0x75,0xC8,0x88,0x43,0x8B,0x72,0x4B,0xCF,0xBC,0x91,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x61, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x13,0x17,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, - 0x41,0x30,0x1E,0x17,0x0D,0x31,0x33,0x30,0x33,0x30,0x38,0x31,0x32,0x30,0x30,0x30, - 0x30,0x5A,0x17,0x0D,0x32,0x33,0x30,0x33,0x30,0x38,0x31,0x32,0x30,0x30,0x30,0x30, - 0x5A,0x30,0x4D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, - 0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43, - 0x65,0x72,0x74,0x20,0x49,0x6E,0x63,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x03, - 0x13,0x1E,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x20,0x53,0x48,0x41,0x32,0x20, - 0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41, - 0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, - 0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, - 0x00,0xDC,0xAE,0x58,0x90,0x4D,0xC1,0xC4,0x30,0x15,0x90,0x35,0x5B,0x6E,0x3C,0x82, - 0x15,0xF5,0x2C,0x5C,0xBD,0xE3,0xDB,0xFF,0x71,0x43,0xFA,0x64,0x25,0x80,0xD4,0xEE, - 0x18,0xA2,0x4D,0xF0,0x66,0xD0,0x0A,0x73,0x6E,0x11,0x98,0x36,0x17,0x64,0xAF,0x37, - 0x9D,0xFD,0xFA,0x41,0x84,0xAF,0xC7,0xAF,0x8C,0xFE,0x1A,0x73,0x4D,0xCF,0x33,0x97, - 0x90,0xA2,0x96,0x87,0x53,0x83,0x2B,0xB9,0xA6,0x75,0x48,0x2D,0x1D,0x56,0x37,0x7B, - 0xDA,0x31,0x32,0x1A,0xD7,0xAC,0xAB,0x06,0xF4,0xAA,0x5D,0x4B,0xB7,0x47,0x46,0xDD, - 0x2A,0x93,0xC3,0x90,0x2E,0x79,0x80,0x80,0xEF,0x13,0x04,0x6A,0x14,0x3B,0xB5,0x9B, - 0x92,0xBE,0xC2,0x07,0x65,0x4E,0xFC,0xDA,0xFC,0xFF,0x7A,0xAE,0xDC,0x5C,0x7E,0x55, - 0x31,0x0C,0xE8,0x39,0x07,0xA4,0xD7,0xBE,0x2F,0xD3,0x0B,0x6A,0xD2,0xB1,0xDF,0x5F, - 0xFE,0x57,0x74,0x53,0x3B,0x35,0x80,0xDD,0xAE,0x8E,0x44,0x98,0xB3,0x9F,0x0E,0xD3, - 0xDA,0xE0,0xD7,0xF4,0x6B,0x29,0xAB,0x44,0xA7,0x4B,0x58,0x84,0x6D,0x92,0x4B,0x81, - 0xC3,0xDA,0x73,0x8B,0x12,0x97,0x48,0x90,0x04,0x45,0x75,0x1A,0xDD,0x37,0x31,0x97, - 0x92,0xE8,0xCD,0x54,0x0D,0x3B,0xE4,0xC1,0x3F,0x39,0x5E,0x2E,0xB8,0xF3,0x5C,0x7E, - 0x10,0x8E,0x86,0x41,0x00,0x8D,0x45,0x66,0x47,0xB0,0xA1,0x65,0xCE,0xA0,0xAA,0x29, - 0x09,0x4E,0xF3,0x97,0xEB,0xE8,0x2E,0xAB,0x0F,0x72,0xA7,0x30,0x0E,0xFA,0xC7,0xF4, - 0xFD,0x14,0x77,0xC3,0xA4,0x5B,0x28,0x57,0xC2,0xB3,0xF9,0x82,0xFD,0xB7,0x45,0x58, - 0x9B,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x5A,0x30,0x82,0x01,0x56,0x30,0x12, - 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02, - 0x01,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02, - 0x01,0x86,0x30,0x34,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28, - 0x30,0x26,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69,0x67,0x69, - 0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x7B,0x06,0x03,0x55,0x1D,0x1F,0x04, - 0x74,0x30,0x72,0x30,0x37,0xA0,0x35,0xA0,0x33,0x86,0x31,0x68,0x74,0x74,0x70,0x3A, - 0x2F,0x2F,0x63,0x72,0x6C,0x33,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E, - 0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x47,0x6C,0x6F,0x62, - 0x61,0x6C,0x52,0x6F,0x6F,0x74,0x43,0x41,0x2E,0x63,0x72,0x6C,0x30,0x37,0xA0,0x35, - 0xA0,0x33,0x86,0x31,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x34,0x2E, - 0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67, - 0x69,0x43,0x65,0x72,0x74,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x52,0x6F,0x6F,0x74,0x43, - 0x41,0x2E,0x63,0x72,0x6C,0x30,0x3D,0x06,0x03,0x55,0x1D,0x20,0x04,0x36,0x30,0x34, - 0x30,0x32,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x2A,0x30,0x28,0x06,0x08,0x2B,0x06, - 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F, - 0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D, - 0x2F,0x43,0x50,0x53,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x0F, - 0x80,0x61,0x1C,0x82,0x31,0x61,0xD5,0x2F,0x28,0xE7,0x8D,0x46,0x38,0xB4,0x2C,0xE1, - 0xC6,0xD9,0xE2,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, - 0x03,0xDE,0x50,0x35,0x56,0xD1,0x4C,0xBB,0x66,0xF0,0xA3,0xE2,0x1B,0x1B,0xC3,0x97, - 0xB2,0x3D,0xD1,0x55,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, - 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x23,0x3E,0xDF,0x4B,0xD2,0x31,0x42,0xA5, - 0xB6,0x7E,0x42,0x5C,0x1A,0x44,0xCC,0x69,0xD1,0x68,0xB4,0x5D,0x4B,0xE0,0x04,0x21, - 0x6C,0x4B,0xE2,0x6D,0xCC,0xB1,0xE0,0x97,0x8F,0xA6,0x53,0x09,0xCD,0xAA,0x2A,0x65, - 0xE5,0x39,0x4F,0x1E,0x83,0xA5,0x6E,0x5C,0x98,0xA2,0x24,0x26,0xE6,0xFB,0xA1,0xED, - 0x93,0xC7,0x2E,0x02,0xC6,0x4D,0x4A,0xBF,0xB0,0x42,0xDF,0x78,0xDA,0xB3,0xA8,0xF9, - 0x6D,0xFF,0x21,0x85,0x53,0x36,0x60,0x4C,0x76,0xCE,0xEC,0x38,0xDC,0xD6,0x51,0x80, - 0xF0,0xC5,0xD6,0xE5,0xD4,0x4D,0x27,0x64,0xAB,0x9B,0xC7,0x3E,0x71,0xFB,0x48,0x97, - 0xB8,0x33,0x6D,0xC9,0x13,0x07,0xEE,0x96,0xA2,0x1B,0x18,0x15,0xF6,0x5C,0x4C,0x40, - 0xED,0xB3,0xC2,0xEC,0xFF,0x71,0xC1,0xE3,0x47,0xFF,0xD4,0xB9,0x00,0xB4,0x37,0x42, - 0xDA,0x20,0xC9,0xEA,0x6E,0x8A,0xEE,0x14,0x06,0xAE,0x7D,0xA2,0x59,0x98,0x88,0xA8, - 0x1B,0x6F,0x2D,0xF4,0xF2,0xC9,0x14,0x5F,0x26,0xCF,0x2C,0x8D,0x7E,0xED,0x37,0xC0, - 0xA9,0xD5,0x39,0xB9,0x82,0xBF,0x19,0x0C,0xEA,0x34,0xAF,0x00,0x21,0x68,0xF8,0xAD, - 0x73,0xE2,0xC9,0x32,0xDA,0x38,0x25,0x0B,0x55,0xD3,0x9A,0x1D,0xF0,0x68,0x86,0xED, - 0x2E,0x41,0x34,0xEF,0x7C,0xA5,0x50,0x1D,0xBF,0x3A,0xF9,0xD3,0xC1,0x08,0x0C,0xE6, - 0xED,0x1E,0x8A,0x58,0x25,0xE4,0xB8,0x77,0xAD,0x2D,0x6E,0xF5,0x52,0xDD,0xB4,0x74, - 0x8F,0xAB,0x49,0x2E,0x9D,0x3B,0x93,0x34,0x28,0x1F,0x78,0xCE,0x94,0xEA,0xC7,0xBD, - 0xD3,0xC9,0x6D,0x1C,0xDE,0x5C,0x32,0xF3, -}; - -/* subject:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA */ -uint8_t _digiCertGlobalRoot[] ={ - 0x30,0x82,0x03,0xAF,0x30,0x82,0x02,0x97,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x08, - 0x3B,0xE0,0x56,0x90,0x42,0x46,0xB1,0xA1,0x75,0x6A,0xC9,0x59,0x91,0xC7,0x4A,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x61, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x13,0x17,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, - 0x41,0x30,0x1E,0x17,0x0D,0x30,0x36,0x31,0x31,0x31,0x30,0x30,0x30,0x30,0x30,0x30, - 0x30,0x5A,0x17,0x0D,0x33,0x31,0x31,0x31,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30, - 0x5A,0x30,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, - 0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43, - 0x65,0x72,0x74,0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B, - 0x13,0x10,0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63, - 0x6F,0x6D,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x13,0x17,0x44,0x69,0x67, - 0x69,0x43,0x65,0x72,0x74,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F,0x6F, - 0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A, - 0x02,0x82,0x01,0x01,0x00,0xE2,0x3B,0xE1,0x11,0x72,0xDE,0xA8,0xA4,0xD3,0xA3,0x57, - 0xAA,0x50,0xA2,0x8F,0x0B,0x77,0x90,0xC9,0xA2,0xA5,0xEE,0x12,0xCE,0x96,0x5B,0x01, - 0x09,0x20,0xCC,0x01,0x93,0xA7,0x4E,0x30,0xB7,0x53,0xF7,0x43,0xC4,0x69,0x00,0x57, - 0x9D,0xE2,0x8D,0x22,0xDD,0x87,0x06,0x40,0x00,0x81,0x09,0xCE,0xCE,0x1B,0x83,0xBF, - 0xDF,0xCD,0x3B,0x71,0x46,0xE2,0xD6,0x66,0xC7,0x05,0xB3,0x76,0x27,0x16,0x8F,0x7B, - 0x9E,0x1E,0x95,0x7D,0xEE,0xB7,0x48,0xA3,0x08,0xDA,0xD6,0xAF,0x7A,0x0C,0x39,0x06, - 0x65,0x7F,0x4A,0x5D,0x1F,0xBC,0x17,0xF8,0xAB,0xBE,0xEE,0x28,0xD7,0x74,0x7F,0x7A, - 0x78,0x99,0x59,0x85,0x68,0x6E,0x5C,0x23,0x32,0x4B,0xBF,0x4E,0xC0,0xE8,0x5A,0x6D, - 0xE3,0x70,0xBF,0x77,0x10,0xBF,0xFC,0x01,0xF6,0x85,0xD9,0xA8,0x44,0x10,0x58,0x32, - 0xA9,0x75,0x18,0xD5,0xD1,0xA2,0xBE,0x47,0xE2,0x27,0x6A,0xF4,0x9A,0x33,0xF8,0x49, - 0x08,0x60,0x8B,0xD4,0x5F,0xB4,0x3A,0x84,0xBF,0xA1,0xAA,0x4A,0x4C,0x7D,0x3E,0xCF, - 0x4F,0x5F,0x6C,0x76,0x5E,0xA0,0x4B,0x37,0x91,0x9E,0xDC,0x22,0xE6,0x6D,0xCE,0x14, - 0x1A,0x8E,0x6A,0xCB,0xFE,0xCD,0xB3,0x14,0x64,0x17,0xC7,0x5B,0x29,0x9E,0x32,0xBF, - 0xF2,0xEE,0xFA,0xD3,0x0B,0x42,0xD4,0xAB,0xB7,0x41,0x32,0xDA,0x0C,0xD4,0xEF,0xF8, - 0x81,0xD5,0xBB,0x8D,0x58,0x3F,0xB5,0x1B,0xE8,0x49,0x28,0xA2,0x70,0xDA,0x31,0x04, - 0xDD,0xF7,0xB2,0x16,0xF2,0x4C,0x0A,0x4E,0x07,0xA8,0xED,0x4A,0x3D,0x5E,0xB5,0x7F, - 0xA3,0x90,0xC3,0xAF,0x27,0x02,0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x0E, - 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x0F, - 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30, - 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x03,0xDE,0x50,0x35,0x56,0xD1, - 0x4C,0xBB,0x66,0xF0,0xA3,0xE2,0x1B,0x1B,0xC3,0x97,0xB2,0x3D,0xD1,0x55,0x30,0x1F, - 0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x03,0xDE,0x50,0x35,0x56, - 0xD1,0x4C,0xBB,0x66,0xF0,0xA3,0xE2,0x1B,0x1B,0xC3,0x97,0xB2,0x3D,0xD1,0x55,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82, - 0x01,0x01,0x00,0xCB,0x9C,0x37,0xAA,0x48,0x13,0x12,0x0A,0xFA,0xDD,0x44,0x9C,0x4F, - 0x52,0xB0,0xF4,0xDF,0xAE,0x04,0xF5,0x79,0x79,0x08,0xA3,0x24,0x18,0xFC,0x4B,0x2B, - 0x84,0xC0,0x2D,0xB9,0xD5,0xC7,0xFE,0xF4,0xC1,0x1F,0x58,0xCB,0xB8,0x6D,0x9C,0x7A, - 0x74,0xE7,0x98,0x29,0xAB,0x11,0xB5,0xE3,0x70,0xA0,0xA1,0xCD,0x4C,0x88,0x99,0x93, - 0x8C,0x91,0x70,0xE2,0xAB,0x0F,0x1C,0xBE,0x93,0xA9,0xFF,0x63,0xD5,0xE4,0x07,0x60, - 0xD3,0xA3,0xBF,0x9D,0x5B,0x09,0xF1,0xD5,0x8E,0xE3,0x53,0xF4,0x8E,0x63,0xFA,0x3F, - 0xA7,0xDB,0xB4,0x66,0xDF,0x62,0x66,0xD6,0xD1,0x6E,0x41,0x8D,0xF2,0x2D,0xB5,0xEA, - 0x77,0x4A,0x9F,0x9D,0x58,0xE2,0x2B,0x59,0xC0,0x40,0x23,0xED,0x2D,0x28,0x82,0x45, - 0x3E,0x79,0x54,0x92,0x26,0x98,0xE0,0x80,0x48,0xA8,0x37,0xEF,0xF0,0xD6,0x79,0x60, - 0x16,0xDE,0xAC,0xE8,0x0E,0xCD,0x6E,0xAC,0x44,0x17,0x38,0x2F,0x49,0xDA,0xE1,0x45, - 0x3E,0x2A,0xB9,0x36,0x53,0xCF,0x3A,0x50,0x06,0xF7,0x2E,0xE8,0xC4,0x57,0x49,0x6C, - 0x61,0x21,0x18,0xD5,0x04,0xAD,0x78,0x3C,0x2C,0x3A,0x80,0x6B,0xA7,0xEB,0xAF,0x15, - 0x14,0xE9,0xD8,0x89,0xC1,0xB9,0x38,0x6C,0xE2,0x91,0x6C,0x8A,0xFF,0x64,0xB9,0x77, - 0x25,0x57,0x30,0xC0,0x1B,0x24,0xA3,0xE1,0xDC,0xE9,0xDF,0x47,0x7C,0xB5,0xB4,0x24, - 0x08,0x05,0x30,0xEC,0x2D,0xBD,0x0B,0xBF,0x45,0xBF,0x50,0xB9,0xA9,0xF3,0xEB,0x98, - 0x01,0x12,0xAD,0xC8,0x88,0xC6,0x98,0x34,0x5F,0x8D,0x0A,0x3C,0xC6,0xE9,0xD5,0x95, - 0x95,0x6D,0xDE, -}; - -uint8_t _digicertOCSPResponse[] = { - 0x30,0x82,0x01,0xe6,0x0a,0x01,0x00,0xa0,0x82,0x01,0xdf,0x30,0x82,0x01,0xdb,0x06,0x09,0x2b,0x06,0x01, - 0x05,0x05,0x07,0x30,0x01,0x01,0x04,0x82,0x01,0xcc,0x30,0x82,0x01,0xc8,0x30,0x81,0xb1,0xa2,0x16,0x04, - 0x14,0x0f,0x80,0x61,0x1c,0x82,0x31,0x61,0xd5,0x2f,0x28,0xe7,0x8d,0x46,0x38,0xb4,0x2c,0xe1,0xc6,0xd9, - 0xe2,0x18,0x0f,0x32,0x30,0x31,0x38,0x30,0x34,0x32,0x35,0x31,0x37,0x34,0x37,0x34,0x33,0x5a,0x30,0x81, - 0x85,0x30,0x81,0x82,0x30,0x49,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0x10, - 0x5f,0xa6,0x7a,0x80,0x08,0x9d,0xb5,0x27,0x9f,0x35,0xce,0x83,0x0b,0x43,0x88,0x9e,0xa3,0xc7,0x0d,0x04, - 0x14,0x0f,0x80,0x61,0x1c,0x82,0x31,0x61,0xd5,0x2f,0x28,0xe7,0x8d,0x46,0x38,0xb4,0x2c,0xe1,0xc6,0xd9, - 0xe2,0x02,0x10,0x01,0xaf,0x1e,0xfb,0xdd,0x5e,0xae,0x09,0x52,0x32,0x0b,0x24,0xfe,0x6b,0x55,0x68,0xa1, - 0x11,0x18,0x0f,0x32,0x30,0x31,0x36,0x30,0x39,0x30,0x32,0x32,0x31,0x32,0x38,0x34,0x38,0x5a,0x18,0x0f, - 0x32,0x30,0x31,0x38,0x30,0x34,0x32,0x35,0x31,0x37,0x34,0x37,0x34,0x33,0x5a,0xa0,0x11,0x18,0x0f,0x32, - 0x30,0x31,0x38,0x30,0x35,0x30,0x32,0x31,0x37,0x30,0x32,0x34,0x33,0x5a,0x30,0x0d,0x06,0x09,0x2a,0x86, - 0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x9c,0x3d,0xb9,0xc6,0xfd,0x97, - 0x21,0xb0,0x04,0xc1,0x62,0x4b,0xc7,0x74,0x7a,0x37,0x01,0xa6,0x22,0xb2,0xd2,0xce,0xbb,0xd4,0x67,0xcd, - 0xda,0x66,0xb6,0x53,0xbc,0x81,0xd4,0x09,0x9c,0xa0,0x3e,0x95,0x6d,0x90,0x0a,0xe6,0x39,0x24,0xb0,0x42, - 0x17,0xc1,0x02,0x62,0x57,0xc8,0x04,0x07,0x66,0x1f,0xc4,0x75,0x75,0xe6,0x82,0x7e,0xd3,0x28,0x46,0xde, - 0xaa,0xb8,0xd7,0x2d,0xd5,0x17,0x70,0xb7,0xbf,0xd6,0xcc,0xa3,0x14,0xe9,0x5f,0x9d,0x40,0xf2,0x5f,0x29, - 0xb2,0xde,0x8a,0x9f,0x02,0x79,0x2a,0xe9,0xa0,0xc0,0x0f,0xb1,0xc3,0xf8,0xaa,0xb1,0x9d,0xaf,0x15,0x78, - 0xf1,0x98,0x6c,0xd2,0xf2,0x1f,0x8d,0x75,0xd4,0xb6,0x91,0xc4,0xb8,0x13,0x18,0xd2,0x30,0xa1,0xb1,0x1e, - 0x81,0x1a,0xef,0x2a,0x42,0x52,0x2a,0xd4,0xec,0xc5,0x8a,0x87,0x9c,0x7b,0x38,0x81,0xf9,0x6e,0xfe,0x60, - 0x3d,0xc7,0xfe,0x77,0x64,0x99,0x3d,0x1c,0xf5,0x92,0xe9,0xe5,0x45,0xf3,0x7e,0x98,0x74,0xfa,0x5a,0xd9, - 0xf4,0x79,0xf3,0xf7,0x6c,0x99,0xce,0x52,0x47,0xc0,0x4a,0x87,0x20,0xed,0x3b,0x76,0x2a,0x58,0x3f,0x8b, - 0xb3,0xcb,0x9f,0xd4,0x11,0x26,0xc4,0x43,0xce,0xd1,0x6f,0x48,0xe4,0xd0,0x2f,0xa1,0x95,0x5a,0xb9,0x93, - 0x25,0xf9,0xd4,0x1a,0xe9,0x75,0x7d,0xcf,0xfb,0xc5,0xa5,0x78,0x98,0x68,0xfb,0x12,0xbd,0x53,0xdc,0x98, - 0x1d,0xd6,0xc7,0xa1,0x28,0x3f,0x5b,0x82,0x39,0x18,0x85,0xfd,0x91,0x8f,0x80,0xa2,0x30,0xd9,0xee,0xc4, - 0x23,0x48,0x3c,0x50,0x18,0x7e,0xc7,0x1d,0xc1,0x5a -}; - -uint8_t _caissuer_https[] = { - 0x30,0x82,0x04,0x68,0x30,0x82,0x03,0x50,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x7A, - 0x22,0xA1,0x88,0x18,0x9E,0x75,0x77,0xE6,0xEF,0x7E,0xC0,0x33,0x8E,0xE8,0x90,0xE8, - 0x7B,0xC4,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, - 0x00,0x30,0x81,0x81,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, - 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, - 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C, - 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03, - 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, - 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, - 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x15, - 0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x0C,0x0C,0x54,0x65,0x73,0x74,0x20,0x52,0x6F, - 0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x38,0x30,0x34,0x32,0x38,0x32, - 0x30,0x32,0x31,0x34,0x31,0x5A,0x17,0x0D,0x31,0x39,0x30,0x34,0x32,0x38,0x32,0x30, - 0x32,0x31,0x34,0x31,0x5A,0x30,0x81,0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, - 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A, - 0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03, - 0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65, - 0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69, - 0x6E,0x67,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x48,0x54,0x54, - 0x50,0x53,0x20,0x43,0x41,0x49,0x73,0x73,0x75,0x65,0x72,0x20,0x54,0x65,0x73,0x74, - 0x20,0x43,0x65,0x72,0x74,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, - 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, - 0x0A,0x02,0x82,0x01,0x01,0x00,0xC1,0x68,0xC2,0x47,0x1E,0x07,0x82,0x66,0x47,0xC9, - 0x5C,0x22,0xDD,0x8B,0x93,0x6A,0xA7,0x22,0x00,0xB8,0xDA,0x8C,0x3C,0x52,0xA7,0x47, - 0x73,0xBB,0x7A,0xD7,0x8C,0x1E,0xAE,0xDA,0x34,0x25,0x4E,0xEB,0x1F,0x33,0x0B,0x8A, - 0xC7,0x6D,0x2A,0x93,0xDB,0x0D,0xD0,0x47,0x85,0x9C,0x14,0xD5,0x23,0xE3,0xE4,0x94, - 0xE0,0x17,0x9F,0x56,0x64,0x8E,0xE0,0x08,0xE9,0x1B,0x4C,0x7C,0x77,0xF9,0x35,0x74, - 0x52,0x43,0x90,0x13,0xFA,0x51,0x9A,0xA2,0x93,0x47,0x94,0xE7,0xBD,0x07,0xE5,0xFB, - 0x67,0x8B,0xF0,0xE2,0x0C,0x97,0xFD,0x29,0x51,0xBD,0x85,0x6C,0xBE,0x36,0xFD,0xDD, - 0xCC,0x99,0x4D,0x68,0x37,0x96,0xB2,0x20,0x85,0x55,0xA5,0x99,0xA4,0x7E,0xD7,0x19, - 0x06,0x15,0x20,0x10,0x50,0x51,0x2E,0x74,0x5C,0x43,0x49,0x94,0x6B,0x0E,0x9E,0xFB, - 0xDF,0xB2,0xEB,0xD9,0x28,0xA8,0xF1,0x25,0x49,0xC8,0xFE,0x3B,0xE1,0x45,0x95,0x47, - 0xD1,0x53,0xCD,0x34,0x9A,0x6F,0xC4,0x3F,0x63,0xC2,0x60,0xC6,0x40,0xBB,0xF7,0x20, - 0x8A,0xB8,0xB7,0xD7,0xC2,0xBB,0x48,0x24,0x64,0xA2,0x4A,0xE4,0x2A,0x17,0x68,0xE2, - 0xAC,0x47,0x2D,0xCC,0xBD,0xB7,0xCE,0x73,0xDF,0x96,0x8C,0x12,0x56,0xE3,0x29,0xE3, - 0x4D,0xB4,0x55,0x28,0xAB,0x28,0x24,0x45,0x7F,0x55,0x66,0xCD,0x46,0x29,0x89,0x58, - 0xFF,0xA6,0xD1,0x67,0xAC,0x50,0xEE,0x55,0x6D,0x6A,0x2A,0xCF,0xD6,0x09,0xE9,0xDA, - 0x22,0xB0,0xAF,0x90,0xD7,0x02,0xB2,0xCE,0x5F,0x09,0x96,0x5E,0x88,0xAE,0xB5,0xB6, - 0xA1,0xC3,0x9D,0x1A,0x2F,0x2D,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xCA,0x30,0x81, - 0xC7,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, - 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30, - 0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x03,0x01,0x30,0x16,0x06,0x03,0x55,0x1D,0x11,0x04,0x0F,0x30,0x0D,0x82, - 0x0B,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03, - 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xDF,0xC7,0x68,0x26,0x64,0x95,0x5D,0x73,0x36, - 0x84,0xE8,0xE3,0x1D,0xC8,0x28,0x5E,0xA8,0x27,0x73,0x8C,0x30,0x1F,0x06,0x03,0x55, - 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xB5,0xA9,0x53,0x08,0x10,0x38,0x1A,0xA5, - 0xB3,0x84,0xC9,0xEE,0xC4,0xAB,0x0F,0xB8,0x5F,0x68,0x10,0xA2,0x30,0x3A,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x2E,0x30,0x2C,0x30,0x2A,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A, - 0x2F,0x2F,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65, - 0x73,0x74,0x43,0x41,0x2E,0x64,0x65,0x72,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xC4,0x48,0xDF,0x5E, - 0x73,0xD1,0x43,0x28,0x7D,0x69,0x71,0x32,0x1F,0xCC,0x1A,0xEB,0x5B,0x98,0x9D,0xCE, - 0xFF,0xCA,0x16,0xA9,0x96,0xE7,0x4D,0xC4,0xAE,0x53,0xE2,0x5D,0xDB,0xDA,0x40,0x80, - 0xE5,0xFB,0xF3,0xD7,0x21,0x9A,0x77,0x1D,0x67,0xFC,0x04,0x62,0x18,0xFF,0x10,0x59, - 0xF4,0xDD,0xF4,0xC6,0x8F,0xB4,0xEF,0x9F,0x05,0xA6,0xF1,0xCB,0x44,0x24,0x02,0x19, - 0x75,0xF9,0x3C,0x28,0x8A,0xAA,0x57,0x6B,0xFF,0x64,0xFF,0xD7,0xE2,0x62,0x67,0x70, - 0x20,0x4D,0xAE,0xD2,0x67,0xED,0x92,0xA4,0xFA,0x8A,0xC3,0x24,0x9C,0x2F,0x4D,0x2C, - 0xA9,0xA5,0x92,0x5E,0x5C,0x6F,0xDB,0xAB,0x96,0xA6,0xB1,0x5B,0xF1,0x8D,0x97,0x08, - 0xBC,0x5B,0x27,0xD5,0x9E,0x2D,0xF0,0x49,0x68,0xA6,0x92,0x00,0x13,0xAD,0x60,0x9E, - 0x78,0x72,0xC2,0x18,0xB8,0xE5,0x9D,0x72,0xA5,0x87,0x61,0xA8,0x95,0x8A,0x2B,0xB2, - 0xCC,0xCA,0x7F,0x1E,0x1E,0xC5,0xFB,0x5A,0x0C,0x77,0x17,0xB0,0xBE,0x7B,0x5A,0x50, - 0x05,0x32,0x40,0x98,0x3A,0x8B,0x22,0x3F,0x3B,0xA5,0xA8,0xA9,0x59,0x3B,0x55,0x92, - 0xD1,0x8A,0x34,0x73,0xA6,0xD6,0x5D,0x5E,0x85,0x59,0x00,0xD5,0x55,0x94,0x80,0xC1, - 0xB9,0xF1,0xCA,0x2B,0xC5,0x96,0xEE,0x49,0x6A,0x2C,0xDD,0x62,0x98,0xB3,0x74,0x09, - 0x09,0xDE,0x3D,0x59,0x5B,0x21,0x76,0x6E,0x27,0x66,0xED,0x7B,0x74,0x7F,0xE7,0xA9, - 0xAE,0xEB,0x40,0x83,0xB9,0xBC,0xE6,0x0C,0x1E,0x53,0xB2,0xEA,0x79,0xC4,0xA9,0x30, - 0x2B,0x1F,0xC4,0x34,0x82,0x3E,0xFC,0x1E,0x2D,0x66,0x75,0xD0, -}; - -#endif /* _SECURITY_SI_23_SECTRUST_OCSP_H_ */ diff --git a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c b/OSX/sec/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c deleted file mode 100644 index 97a500a5..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. - */ - -#include -#include - -#include - -#include "shared_regressions.h" - -static void tests(void) -{ - SecPolicyRef sslPolicy = SecPolicyCreateSSL(false, 0); - - /* Run the tests. */ - runCertificateTestForDirectory(sslPolicy, CFSTR("DigicertMalaysia"), NULL); - - CFReleaseSafe(sslPolicy); -} - -int si_24_sectrust_digicert_malaysia(int argc, char *const *argv) -{ - plan_tests(2); - - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-diginotar.c b/OSX/sec/Security/Regressions/secitem/si-24-sectrust-diginotar.c deleted file mode 100644 index 4f363710..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-diginotar.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. - */ - -#include -#include - -#include - -#include "shared_regressions.h" - -static void tests(void) -{ - SecPolicyRef sslPolicy = SecPolicyCreateSSL(false, 0); - - /* Run the tests. */ - runCertificateTestForDirectory(sslPolicy, CFSTR("DigiNotar"), NULL); - runCertificateTestForDirectory(sslPolicy, CFSTR("DigiNotar-Entrust"), NULL); - runCertificateTestForDirectory(sslPolicy, CFSTR("DigiNotar-ok"), NULL); - - CFReleaseSafe(sslPolicy); -} - -int si_24_sectrust_diginotar(int argc, char *const *argv) -{ - plan_tests(25); - - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-itms.c b/OSX/sec/Security/Regressions/secitem/si-24-sectrust-itms.c deleted file mode 100644 index 5b4fe130..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-itms.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2007-2010,2012,2014 Apple Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "shared_regressions.h" - -static const UInt8 sITunesStoreRootCertificate[] = -{ - 0x30, 0x82, 0x04, 0x65, 0x30, 0x82, 0x03, 0x4d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, - 0xcb, 0x06, 0xa3, 0x3b, 0x30, 0xc3, 0x24, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x7e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x15, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, - 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, - 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x52, 0x6f, 0x6f, - 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, - 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, - 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x31, 0x30, 0x30, - 0x39, 0x31, 0x37, 0x35, 0x31, 0x33, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x32, 0x31, 0x30, 0x30, 0x32, - 0x31, 0x37, 0x35, 0x31, 0x33, 0x30, 0x5a, 0x30, 0x7e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x15, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, - 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, - 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x52, 0x6f, 0x6f, - 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, - 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, - 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, - 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa9, 0x78, 0xc0, 0xaf, 0x1a, 0x96, 0x59, 0xad, - 0xf8, 0x3c, 0x16, 0xe1, 0xfc, 0xc4, 0x7a, 0xaf, 0xf0, 0x80, 0xed, 0x7f, 0x3a, 0xff, 0xf2, 0x2a, - 0xb6, 0xf3, 0x1a, 0xdd, 0xbd, 0x14, 0xb1, 0x5d, 0x9d, 0x66, 0xaf, 0xc7, 0xaf, 0x2b, 0x26, 0x78, - 0x9c, 0xb8, 0x0b, 0x41, 0x9c, 0xdc, 0x17, 0xf1, 0x40, 0x18, 0x09, 0xa1, 0x0a, 0xbc, 0x01, 0x9a, - 0x0c, 0xbe, 0x89, 0xdb, 0x9d, 0x34, 0xc7, 0x52, 0x8a, 0xf2, 0xbf, 0x35, 0x2b, 0x24, 0x04, 0xb0, - 0x0c, 0x9d, 0x41, 0x7d, 0x63, 0xe3, 0xad, 0xcf, 0x8b, 0x34, 0xbf, 0x5c, 0x42, 0x82, 0x9b, 0x78, - 0x7f, 0x00, 0x10, 0x88, 0xd9, 0xfd, 0xf8, 0xbf, 0x63, 0x2c, 0x91, 0x87, 0x03, 0xda, 0xbc, 0xc6, - 0x71, 0x2b, 0x9a, 0x21, 0x30, 0x95, 0xd6, 0x88, 0xe8, 0xbd, 0x0a, 0x74, 0xa4, 0xa6, 0x39, 0xd0, - 0x61, 0xd3, 0xb6, 0xe0, 0x2b, 0x1e, 0xe4, 0x78, 0x5c, 0x70, 0x32, 0x66, 0x97, 0x34, 0xa9, 0x79, - 0xfc, 0x96, 0xaf, 0x4b, 0x8a, 0xd5, 0x12, 0x07, 0x8c, 0x1c, 0xf6, 0x3e, 0x5f, 0xdc, 0x8f, 0x92, - 0x10, 0xe8, 0x7e, 0xa0, 0x14, 0x1e, 0x61, 0x28, 0xfa, 0xcc, 0xcf, 0x3c, 0xdb, 0x2b, 0xe3, 0xe9, - 0x44, 0x4a, 0x9d, 0x5f, 0x92, 0x3d, 0xa3, 0xfd, 0x1a, 0x63, 0xb4, 0xbb, 0xab, 0x67, 0x45, 0xc6, - 0x4d, 0x84, 0x4a, 0xaa, 0x33, 0xe4, 0xde, 0xd3, 0x04, 0x92, 0xbf, 0xf7, 0x00, 0x48, 0x76, 0xc6, - 0x4e, 0x17, 0xea, 0x70, 0xdb, 0x09, 0xbc, 0x22, 0x07, 0x7b, 0x97, 0x49, 0xe5, 0x29, 0xa7, 0x1a, - 0x04, 0xd2, 0x0d, 0x0e, 0x73, 0xf1, 0x49, 0x43, 0x34, 0x35, 0x61, 0xe5, 0x67, 0xdf, 0x3c, 0x58, - 0x42, 0x51, 0xfb, 0xc3, 0xa4, 0x15, 0x6d, 0x39, 0x6b, 0x2a, 0x22, 0xde, 0xdd, 0xe2, 0x36, 0x5b, - 0xd7, 0x37, 0x53, 0x96, 0x9d, 0x3a, 0x9f, 0x4b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe5, - 0x30, 0x81, 0xe2, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb0, 0xda, - 0xe1, 0x7f, 0xa8, 0x8b, 0x4a, 0x6a, 0x81, 0x5d, 0x0c, 0xa1, 0x84, 0x56, 0x46, 0x1e, 0x6a, 0xef, - 0xe5, 0xcf, 0x30, 0x81, 0xb2, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xaa, 0x30, 0x81, 0xa7, - 0x80, 0x14, 0xb0, 0xda, 0xe1, 0x7f, 0xa8, 0x8b, 0x4a, 0x6a, 0x81, 0x5d, 0x0c, 0xa1, 0x84, 0x56, - 0x46, 0x1e, 0x6a, 0xef, 0xe5, 0xcf, 0xa1, 0x81, 0x83, 0xa4, 0x81, 0x80, 0x30, 0x7e, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, - 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x11, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, - 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, - 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x82, 0x09, 0x00, 0xcb, - 0x06, 0xa3, 0x3b, 0x30, 0xc3, 0x24, 0x03, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0xcc, 0xfb, 0x34, 0x4e, 0xec, 0x27, - 0x05, 0xf9, 0x10, 0xc9, 0xdf, 0x8e, 0x22, 0x21, 0x94, 0x70, 0xe9, 0x74, 0x64, 0x11, 0xce, 0x07, - 0x91, 0xc2, 0x58, 0x0d, 0xff, 0x51, 0x6d, 0x97, 0x64, 0x32, 0x1a, 0x1c, 0xdf, 0x4a, 0x93, 0xdb, - 0x94, 0x62, 0x14, 0xcb, 0x00, 0x13, 0x37, 0x98, 0x0e, 0x3d, 0x96, 0x19, 0x5f, 0x44, 0xc9, 0x11, - 0xd2, 0xc9, 0x8c, 0xa3, 0x19, 0x2f, 0x88, 0x4f, 0x5f, 0x3c, 0x46, 0x56, 0xe2, 0xbd, 0x78, 0x4f, - 0xfe, 0x8e, 0x39, 0xb5, 0xed, 0x37, 0x3e, 0xfb, 0xf6, 0xae, 0x56, 0x2c, 0x49, 0x37, 0x4a, 0x94, - 0x05, 0x4b, 0x8f, 0x67, 0xdb, 0xe6, 0x24, 0xa6, 0x75, 0xae, 0xc8, 0xa2, 0x26, 0x87, 0x70, 0xb8, - 0x1d, 0xc2, 0xfc, 0x8d, 0xff, 0x41, 0x23, 0x8a, 0x01, 0x8a, 0xc3, 0x78, 0x5a, 0x61, 0x4a, 0xed, - 0x48, 0x96, 0xb5, 0x82, 0xa7, 0xaa, 0x2e, 0xb5, 0xed, 0xdd, 0xf4, 0xe6, 0xb5, 0xa1, 0x27, 0x3b, - 0xda, 0xf9, 0x18, 0x26, 0x7e, 0x8e, 0xec, 0xef, 0xe1, 0x00, 0x7d, 0x3d, 0xf7, 0x3d, 0x01, 0x68, - 0x14, 0x92, 0xfc, 0x9c, 0xbb, 0x0a, 0xa1, 0xc3, 0x60, 0x31, 0x16, 0x08, 0x9b, 0xef, 0x4d, 0xaf, - 0x46, 0xc7, 0xcc, 0x4e, 0x05, 0x34, 0xa8, 0x44, 0xb2, 0x85, 0x03, 0x67, 0x6c, 0x31, 0xae, 0xa3, - 0x18, 0xb5, 0x5f, 0x75, 0xae, 0xe0, 0x5a, 0xbf, 0x64, 0x32, 0x2b, 0x28, 0x99, 0x24, 0xcd, 0x01, - 0x34, 0xc2, 0xfc, 0xf1, 0x88, 0xba, 0x8c, 0x9b, 0x90, 0x85, 0x56, 0x6d, 0xaf, 0xd5, 0x2e, 0x88, - 0x12, 0x61, 0x7c, 0x76, 0x33, 0x6b, 0xc4, 0xf7, 0x31, 0x77, 0xe4, 0x02, 0xb7, 0x9e, 0x9c, 0x8c, - 0xbe, 0x04, 0x2e, 0x51, 0xa3, 0x04, 0x4c, 0xcd, 0xe2, 0x71, 0x5e, 0x36, 0xfb, 0xf1, 0x68, 0xf0, - 0xad, 0x37, 0x80, 0x98, 0x26, 0xc0, 0xef, 0x9b, 0x3c -}; - -static const unsigned char url_bag[] = -"" -"" -"" -"" -" signaturePXlOzELnbcmmd6zbfl/CfXhx4lUKpH7exmCIMQXbwLzGCEjy2g1ekpMopSZZ+OeizHJDPrgfMf3mzhPsagguGNVan8Y335wF0iT5zh4dR/POso9mj1HOvoU5JmqjVXpNVWoflfkIyHZUiQafXitKda7DWXOrNpP92LplPtBzLIg=" -" certs" -" " -" MIIDRjCCAi6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADB+MRMwEQYDVQQKEwpBcHBsZSBJbmMuMRUwEwYDVQQLEwxpVHVuZXMgU3RvcmUxGjAYBgNVBAMTEWlUdW5lcyBTdG9yZSBSb290MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAGA1UEBxMJQ3VwZXJ0aW5vMB4XDTExMDYwNjIyMTkxOFoXDTEzMDYwNTIyMTkxOFowgYExEzARBgNVBAoTCkFwcGxlIEluYy4xFTATBgNVBAsTDGlUdW5lcyBTdG9yZTEdMBsGA1UEAxMUaVR1bmVzIFN0b3JlIFVSTCBCYWcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlDdXBlcnRpbm8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALucax5drB+v1stVZDaqk/kyW1zcZ9Va8lKAXzsDXpkt4gvzhSJX1bQ3Z6qNMhbVT1nvkDHONGsnCyqOkRfI6Py19gRAoQO3XtfAqrZ5Sh7Spxsznm8GCUBBNRtSUzYa+StvwOWiXdPX3D9X5dZTetatpsLL5t5FeedaAW7Baan7AgMBAAGjTzBNMB0GA1UdDgQWBBTI704/Bfpw+vAHyPMVdbk/gT3xpjAfBgNVHSMEGDAWgBSw2uF/qItKaoFdDKGEVkYeau/lzzALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEFBQADggEBAIF7O5xNidy+EE3/skB0Erwy0358vboeowqkSPYzYaNWhK2UCyUiERN61hkaZFFIDqjchND3h7y67kJDCyGviRzRlFiMAEb56rKFzAwlT5w1btOoQjbKgl5MnqYIC9GtUWKC5gH4Qx6lgmIR90qQ/7gEykivZ/IkIvYpXHCYvOStEPqN//u1oiAAVmJpmMN1MHCrhJeZebtMu8zgS9i1rv/e+YaxQJcdJ5COg0GD8i5RI3VCCWqRGl3aGvLx5TzzetnQlRvglnfzsSuXR7gB6oENnOjPGnarccN1qdwPCd8lw+hxfzG8/2LWLUooH2tWXC1Qi9dU9yxCgjgTwzmol3I=" -" " -" bagPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlIENvbXB1dGVyLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q+CiAgPGtleT50aW1lc3RhbXA8L2tleT48ZGF0ZT4yMDExLTA3LTIyVDE0OjIyOjE4WjwvZGF0ZT4KICA8a2V5PnN0b3JlRnJvbnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evc3RvcmVGcm9udDwvc3RyaW5nPgogIDxrZXk+bmV3VXNlclN0b3JlRnJvbnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvZmlyc3RMYXVuY2g8L3N0cmluZz4KICA8a2V5Pm5ld0lQb2RVc2VyU3RvcmVGcm9udDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9uZXdJUG9kVXNlcj9uZXdJUG9kVXNlcj10cnVlPC9zdHJpbmc+CiAgPGtleT5uZXdQaG9uZVVzZXI8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvcGhvbmVMYW5kaW5nUGFnZTwvc3RyaW5nPgogIDxrZXk+c2VhcmNoPC9rZXk+PHN0cmluZz5odHRwOi8vYXguc2VhcmNoLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlNlYXJjaC53b2Evd2Evc2VhcmNoPC9zdHJpbmc+CiAgPGtleT5hZHZhbmNlZFNlYXJjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2gud29hL3dhL2FkdmFuY2VkU2VhcmNoPC9zdHJpbmc+CiAgPGtleT5zZWFyY2hIaW50czwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2hIaW50cy53b2Evd2EvaGludHM8L3N0cmluZz4KICA8a2V5PnBhcmVudGFsQWR2aXNvcnk8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvcGFyZW50YWxBZHZpc29yeTwvc3RyaW5nPgogIDxrZXk+YnJvd3NlPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2Jyb3dzZTwvc3RyaW5nPgogIDxrZXk+dmlld0FsYnVtPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdBbGJ1bTwvc3RyaW5nPgogIDxrZXk+dmlld0Jvb2s8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0Jvb2s8L3N0cmluZz4KICA8a2V5PnZpZXdBcnRpc3Q8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0FydGlzdDwvc3RyaW5nPgogIDxrZXk+dmlld0NvbXBvc2VyPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdDb21wb3Nlcjwvc3RyaW5nPgogIDxrZXk+dmlld0dlbnJlPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdHZW5yZTwvc3RyaW5nPgogIDxrZXk+dmlld1BvZGNhc3Q8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1BvZGNhc3Q8L3N0cmluZz4KICA8a2V5PnZpZXdQdWJsaXNoZWRQbGF5bGlzdDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3UHVibGlzaGVkUGxheWxpc3Q8L3N0cmluZz4KICA8a2V5PnZpZXdWaWRlbzwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VmlkZW88L3N0cmluZz4KICA8a2V5PmFwcHM8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0FwcHNNYWluPC9zdHJpbmc+CiAgPGtleT5hdWRpb2Jvb2tzPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdBdWRpb2Jvb2tzTWFpbjwvc3RyaW5nPgogIDxrZXk+aXR1bmVzLXU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0dlbnJlP2lkPTQwMDAwMDAwPC9zdHJpbmc+CiAgPGtleT5tb3ZpZXM8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld01vdmllc01haW48L3N0cmluZz4KICA8a2V5Pm11c2ljPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdNdXNpY01haW48L3N0cmluZz4KICA8a2V5PnBvZGNhc3RzPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdQb2RjYXN0RGlyZWN0b3J5PC9zdHJpbmc+CiAgPGtleT5yaW5ndG9uZXM8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1Jpbmd0b25lczwvc3RyaW5nPgogIDxrZXk+dHYtc2hvd3M8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1RWU2hvd3NNYWluPC9zdHJpbmc+CiAgPGtleT5leHRlcm5hbFVSTFNlYXJjaEtleTwva2V5PjxzdHJpbmc+aXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogIDxrZXk+ZXh0ZXJuYWxVUkxSZXBsYWNlS2V5PC9rZXk+PHN0cmluZz5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgPGtleT5zb25nTWV0YURhdGE8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evc29uZ01ldGFEYXRhPC9zdHJpbmc+CiAgPGtleT5zZWxlY3RlZEl0ZW1zUGFnZTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9zZWxlY3RlZEl0ZW1zUGFnZTwvc3RyaW5nPgogIDxrZXk+c3dpc2gtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdSb29tP2ZjSWQ9Mjk3NDgwODcyJmFtcDtpZD0zNzwvc3RyaW5nPgogIDxrZXk+dXBsb2FkUHVibGlzaGVkUGxheWxpc3Q8L2tleT48c3RyaW5nPmh0dHA6Ly9jLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkNvbm5lY3Rpb25zLndvYS93YS9jcmVhdGVJTWl4P3M9MTQzNDQxPC9zdHJpbmc+CiAgPGtleT5taW5pLXN0b3JlPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL21pbmlzdG9yZVJldGlyZWQ8L3N0cmluZz4KICA8a2V5Pm1pbmktc3RvcmUtZmllbGRzPC9rZXk+PHN0cmluZz48L3N0cmluZz4KICA8a2V5Pm1pbmktc3RvcmUtbWF0Y2g8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvbWluaXN0b3JlUmV0aXJlZDwvc3RyaW5nPgogIDxrZXk+bWluaS1zdG9yZS1tYXRjaC1maWVsZHM8L2tleT48c3RyaW5nPjwvc3RyaW5nPgogIDxrZXk+bWluaS1zdG9yZS13ZWxjb21lPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL21pbmlzdG9yZVJldGlyZWQ8L3N0cmluZz4KICA8a2V5Pm1heFB1Ymxpc2hlZFBsYXlsaXN0SXRlbXM8L2tleT48aW50ZWdlcj4xMDA8L2ludGVnZXI+CiAgPGtleT5hdmFpbGFibGUtcmluZ3RvbmVzPC9rZXk+PHN0cmluZz5odHRwOi8vbXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aUGVyc29uYWxpemVyLndvYS93YS9hdmFpbGFibGVSaW5ndG9uZXM8L3N0cmluZz4KICA8a2V5PmFib3V0LXJpbmd0b25lczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9SaW5ndG9uZUxlYXJuTW9yZVBhZ2U8L3N0cmluZz4KICA8a2V5PnJpbmd0b25lLWluZm8tZmllbGRzLWxpc3Q8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPmlkLHMsZHNpZDwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5jb3Zlci1hcnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9jb3ZlckFydE1hdGNoPC9zdHJpbmc+CiAgPGtleT5jb3Zlci1hcnQtbWF0Y2g8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9jb3ZlckFydE1hdGNoPC9zdHJpbmc+CiAgPGtleT5jb3Zlci1hcnQtZmllbGRzPC9rZXk+PHN0cmluZz5hLHA8L3N0cmluZz4KICA8a2V5PmNvdmVyLWFydC1jZC1maWVsZHM8L2tleT48c3RyaW5nPmNkZGI8L3N0cmluZz4KICA8a2V5PmNvdmVyLWFydC1tYXRjaC1maWVsZHM8L2tleT48c3RyaW5nPmNkZGItdHVpZCxjZGRiLGFuLGFhbixwbjwvc3RyaW5nPgogIDxrZXk+Y292ZXItYXJ0LWZpZWxkcy1saXN0PC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5hLHA8L3N0cmluZz4KICAgIDxzdHJpbmc+aWQsY2RkYi10dWlkLGNkZGIsYW4sYWFuLHBuPC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PmNvdmVyLWFydC11c2VyPC9rZXk+PHN0cmluZz5odHRwOi8vbXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aUGVyc29uYWxpemVyLndvYS93YS9jb3ZlckFydFVzZXI8L3N0cmluZz4KICA8a2V5Pm1hdGNoVVJMczwva2V5PgogIDxhcnJheT4KICAgIDxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vPC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHA6Ly9zZWFyY2guaXR1bmVzLmFwcGxlLmNvbS88L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cDovL2J1eS5pdHVuZXMuYXBwbGUuY29tLzwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5saWJyYXJ5LWxpbms8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9saWJyYXJ5TGluazwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS1saW5rLWZpZWxkcy1saXN0PC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5pZCxhLHAsZyxjZGRiLXR1aWQsYW4sY24sZ24sa2luZCxuLHBuLHBvZGNhc3QtdXJsPC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PmxpYnJhcnlMaW5rPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd2EvbGlicmFyeUxpbms8L3N0cmluZz4KICA8a2V5Pm1heENvbXB1dGVyczwva2V5PjxzdHJpbmc+NTwvc3RyaW5nPgogIDxrZXk+dHJ1c3RlZERvbWFpbnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPmFsYmVydC1zby5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+YWIyLXNvLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5hbGJlcnQuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPmJ1eWlwaG9uZS5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+MmdhY3RpdmF0aW9uLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4qLmlwcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+d3d3LmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz50cmFpbGVycy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+cGhvYm9zLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4uaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4ubXpzdGF0aWMuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+bWV0cmljcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+c2VjdXJlLm1lLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4uYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQ8L3N0cmluZz4KICAgIDxzdHJpbmc+c3VwcG9ydC5tYWMuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPi5pdHVuZXMuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0dW5lcy5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+ZGVpbW9zLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5kZWltb3MyLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5kZWltb3MzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5pbmRpZ28wMS5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+aW5kaWdvLWVkZ2UuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPm53ay11bmJyaWNrMy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+bXpzdXBwb3J0LmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5zdG9yZXByZXZpZXcuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPi5jb3JwLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4uYXNpYS5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+LmV1cm8uYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPmFpdXN3LmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5zb2Z0ZGVwb3QuZmlsZW1ha2VyLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5pc3RkZXYxLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5pc3R3ZWJkZXYxLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4ucnRsY2RuLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5pc3R3ZWIuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+ZHNpZC1kb21haW5zPC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5idXkuaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4qLWJ1eS5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPnN1Lml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+YXguc3UuaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5teS5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPnNlLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+bXlhcHAuaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz51c2VycHViLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+Yy5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPnNjLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+ZHUuaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5zaWRlYmFyLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+YXguc2lkZWJhci5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPiotaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4qLWl0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cGx1cy1pbmZvPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2lUdW5lc1BsdXNMZWFybk1vcmVQYWdlPC9zdHJpbmc+CiAgPGtleT5oZC1pbmZvPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL0hEVFZMZWFybk1vcmVQYWdlPC9zdHJpbmc+CiAgPGtleT5hcHBsZXR2LXJlbGF0ZWQtY29udGVudC11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9teS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpQZXJzb25hbGl6ZXIud29hL3dhL3JlbGF0ZWRJdGVtc1NoZWxmPC9zdHJpbmc+CiAgPGtleT5hcHBsZXR2LXlvdXR1YmUtYXV0aC11cmw8L2tleT48c3RyaW5nPmh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vPC9zdHJpbmc+CiAgPGtleT5hcHBsZXR2LXlvdXR1YmUtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vZ2RhdGEueW91dHViZS5jb20vPC9zdHJpbmc+CiAgPGtleT5hdmFpbGFibGUtc3RvcmVmcm9udHM8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvYXZhaWxhYmxlU3RvcmVGcm9udHM8L3N0cmluZz4KICA8a2V5PmFwcGxldHYtdmlldy10b3AtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdUb3A8L3N0cmluZz4KICA8a2V5PmFwcGxldHYtdXNlLXBlcnNvbmFsaXplZC1tZW51LWNvbnRlbnQ8L2tleT48c3RyaW5nPk5PPC9zdHJpbmc+CiAgPGtleT5HaG9zdHJpZGVyPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICA8a2V5Pml0dW5lcy1wcmVzZW50cy1kaXJlY3RvcnktdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd3MvUlNTL2RpcmVjdG9yeTwvc3RyaW5nPgogIDxrZXk+cDItdG9wLXRlbjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VG9wVGVuc0xpc3Q8L3N0cmluZz4KICA8a2V5PnAyLXNlcnZpY2UtdGVybXMtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vd3d3LmFwcGxlLmNvbS9sZWdhbC9pdHVuZXMvd3cvPC9zdHJpbmc+CiAgPGtleT5tb2JpbGUtY29ubmVjdGlvbi10eXBlLWFsbG93czwva2V5PgogIDxkaWN0PgogICAgPGtleT4zRzwva2V5PgogICAgPGRpY3Q+CiAgICAgIDxrZXk+ZUJvb2stc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5lQm9vay1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+ZUJvb2stc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWVib29rPC9zdHJpbmc+CiAgICAgIDxrZXk+cDItbXVzaWMtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5tdXNpYy1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+cDItc3RvcmUtc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWFsbDwvc3RyaW5nPgogICAgICA8a2V5PnAyLXN0b3JlLW5zLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1hbGxXaXRoUmluZ3RvbmU8L3N0cmluZz4KICAgICAgPGtleT5wMi1wb2RjYXN0cy1lbmFibGVkPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5wb2RjYXN0LWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4yMDk3MTUyMDwvaW50ZWdlcj4KICAgICAgPGtleT5wMi1tdXNpYy1zZWFyY2gtcGFyYW1ldGVyczwva2V5PjxzdHJpbmc+bWVkaWE9bXVzaWNBbmRQb2RjYXN0PC9zdHJpbmc+CiAgICAgIDxrZXk+cDItc29mdHdhcmUtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5zb2Z0d2FyZS1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+dmlkZW8tZG93bmxvYWQtc2l6ZS1saW1pdC1pbi1ieXRlczwva2V5PjxpbnRlZ2VyPjIwOTcxNTIwPC9pbnRlZ2VyPgogICAgPC9kaWN0PgogICAgPGtleT4yRzwva2V5PgogICAgPGRpY3Q+CiAgICAgIDxrZXk+ZUJvb2stc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5lQm9vay1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+ZUJvb2stc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWVib29rPC9zdHJpbmc+CiAgICAgIDxrZXk+cDItbXVzaWMtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5tdXNpYy1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+cDItc3RvcmUtc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWFsbDwvc3RyaW5nPgogICAgICA8a2V5PnAyLXN0b3JlLW5zLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1hbGxXaXRoUmluZ3RvbmU8L3N0cmluZz4KICAgICAgPGtleT5wMi1wb2RjYXN0cy1lbmFibGVkPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5wb2RjYXN0LWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4yMDk3MTUyMDwvaW50ZWdlcj4KICAgICAgPGtleT5wMi1tdXNpYy1zZWFyY2gtcGFyYW1ldGVyczwva2V5PjxzdHJpbmc+bWVkaWE9bXVzaWNBbmRQb2RjYXN0PC9zdHJpbmc+CiAgICAgIDxrZXk+cDItc29mdHdhcmUtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5zb2Z0d2FyZS1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+dmlkZW8tZG93bmxvYWQtc2l6ZS1saW1pdC1pbi1ieXRlczwva2V5PjxpbnRlZ2VyPjIwOTcxNTIwPC9pbnRlZ2VyPgogICAgPC9kaWN0PgogICAgPGtleT5XaUZpPC9rZXk+CiAgICA8ZGljdD4KICAgICAgPGtleT5lQm9vay1zdG9yZS1hdmFpbGFibGU8L2tleT48c3RyaW5nPllFUzwvc3RyaW5nPgogICAgICA8a2V5PmVCb29rLWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4wPC9pbnRlZ2VyPgogICAgICA8a2V5PmVCb29rLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1lYm9vazwvc3RyaW5nPgogICAgICA8a2V5PnAyLW11c2ljLXN0b3JlLWF2YWlsYWJsZTwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgICAgIDxrZXk+bXVzaWMtZG93bmxvYWQtc2l6ZS1saW1pdC1pbi1ieXRlczwva2V5PjxpbnRlZ2VyPjA8L2ludGVnZXI+CiAgICAgIDxrZXk+cDItc3RvcmUtc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWFsbDwvc3RyaW5nPgogICAgICA8a2V5PnAyLXN0b3JlLW5zLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1hbGxXaXRoUmluZ3RvbmU8L3N0cmluZz4KICAgICAgPGtleT5wMi1wb2RjYXN0cy1lbmFibGVkPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5wb2RjYXN0LWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4wPC9pbnRlZ2VyPgogICAgICA8a2V5PnAyLW11c2ljLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1tdXNpY0FuZFBvZGNhc3Q8L3N0cmluZz4KICAgICAgPGtleT5wMi1zb2Z0d2FyZS1zdG9yZS1hdmFpbGFibGU8L2tleT48c3RyaW5nPllFUzwvc3RyaW5nPgogICAgICA8a2V5PnNvZnR3YXJlLWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4wPC9pbnRlZ2VyPgogICAgICA8a2V5PnZpZGVvLWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4wPC9pbnRlZ2VyPgogICAgPC9kaWN0PgogIDwvZGljdD4KICA8a2V5PnAyLW11c2ljLXNlYXJjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2gud29hL3dhL3NlYXJjaDwvc3RyaW5nPgogIDxrZXk+cDItbXVzaWMtc2VhcmNoSGludHM8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zZWFyY2guaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU2VhcmNoSGludHMud29hL3dhL2hpbnRzPC9zdHJpbmc+CiAgPGtleT5wMi1ib29rLXNlYXJjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2gud29hL3dhL3NlYXJjaD9tZWRpYT1lYm9vazwvc3RyaW5nPgogIDxrZXk+cDItYm9vay1zZWFyY2hIaW50czwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2hIaW50cy53b2Evd2EvaGludHM/bWVkaWE9ZWJvb2s8L3N0cmluZz4KICA8a2V5Pm1vYmlsZS10YWItYmFyczwva2V5PgogIDxkaWN0PgogICAgPGtleT5XaUZpLU11c2ljPC9rZXk+CiAgICA8ZGljdD4KICAgICAgPGtleT52ZXJzaW9uPC9rZXk+PHN0cmluZz4zMy0xNDM0NDE8L3N0cmluZz4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvZm9vdGVyU2VjdGlvbnM/YXBwPXdpZmk8L3N0cmluZz4KICAgIDwvZGljdD4KICAgIDxrZXk+U29mdHdhcmU8L2tleT4KICAgIDxkaWN0PgogICAgICA8a2V5PnZlcnNpb248L2tleT48c3RyaW5nPjEyLTE0MzQ0MTwvc3RyaW5nPgogICAgICA8a2V5PnVybDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9mb290ZXJTZWN0aW9ucz9hcHA9YXBwPC9zdHJpbmc+CiAgICA8L2RpY3Q+CiAgICA8a2V5PmVCb29rczwva2V5PgogICAgPGRpY3Q+CiAgICAgIDxrZXk+dmVyc2lvbjwva2V5PjxzdHJpbmc+Ny0xNDM0NDE8L3N0cmluZz4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvZm9vdGVyU2VjdGlvbnM/YXBwPWVCb29rczwvc3RyaW5nPgogICAgPC9kaWN0PgogIDwvZGljdD4KICA8a2V5PnAyLWxhdW5jaC1ob3N0LXN1ZmZpeC13aGl0ZWxpc3Q8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPi5hcHBsZS5jb208L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLW1vYmlsZXN0b3JlLWhvc3QtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPigoYnV5fG15fHNlYXJjaHxjKVwuKT9pdHVuZXNcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICA8c3RyaW5nPnBob2Jvc1wuYXBwbGVcLmNvbSQ8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLW1vYmlsZXN0b3JlLXBhdGgtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9tenN0b3JlLndvYS93YS8oc3RvcmVmcm9udHx2aWV3dG9wdGVuc2xpc3R8dmlld3RvcGZpZnR5fHZpZXd0b3B8dmlld2F1ZGlvYm9va3x2aWV3Z3JvdXBpbmd8dmlld2dlbnJlfHZpZXdwbGF5bGlzdHNwYWdlfHZpZXdyb29tfHZpZXdhbGJ1bXx2aWV3cG9kY2FzdHx2aWV3bWl4fHN0b3JlZnJvbnRzfHZpZXdjb250ZW50c3VzZXJyZXZpZXdzfHZpZXdldWxhfHZpZXd0dnNob3d8dmlld3R2c2Vhc29ufHZpZXdtb3ZpZXx2aWV3dmlkZW98Zm9vdGVyc2VjdGlvbnN8bGlicmFyeWxpbmt8dmlld2ZlYXR1cmV8dmlld2FydGlzdCk8L3N0cmluZz4KICAgIDxzdHJpbmc+Xi93ZWJvYmplY3RzL216c2VhcmNoLndvYS93YS8oc2VhcmNofGFkdmFuY2Vkc2VhcmNoKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXooZmFzdCk/ZmluYW5jZS53b2Evd2EvKGNvbS5hcHBsZS5qaW5nbGUuYXBwLmZpbmFuY2UuZGlyZWN0YWN0aW9uLyk/KHJlZGVlbWxhbmRpbmdwYWdlfGZyZWVwcm9kdWN0Y29kZXdpemFyZHxjaGVja2ZvcnByZW9yZGVyc3xzaG93ZGlhbG9nZm9ycmVkZWVtfGJ1eW9uZWdldG9uZXxjaGVja2ZvcnB1cmNoYXNlc2F1dGh8YXJ0aXN0Y29ubmVjdHxyZWpvaW5hcnRpc3Rjb25uZWN0fG9wdGludG9jb25uZWN0aW9uc3xyZWpvaW5vcHRpbnRvY29ubmVjdGlvbnN8b3B0aW50b3BpbmcpPC9zdHJpbmc+CiAgICA8c3RyaW5nPl4vKFthLXpdW2Etel0vKT8oYWxidW18YXJ0aXN0fGF1ZGlvYm9va3xhdWRpb2Jvb2tzfGF1dGhvcnxib29rfGJyb3dzZXxjYXRlZ29yeXxjZWxlYnJpdHktcGxheWxpc3RzfGNoYXJ0c3xjb2xsYWJvcmF0aW9ufGNvbGxlY3Rpb258Y29sbGVjdGlvbnN8Y29tcG9zZXJ8Y3VzdG9tZXItcmV2aWV3c3xkaXJlY3Rvcnxlc3NlbnRpYWx8ZXNzZW50aWFsc3xmYXF8Z2VucmV8aW1peHxpbWl4ZXN8bW92aWV8bW92aWUtcmVudGFsc3xtb3ZpZXN8bXVzaWN8bXVzaWMtdmlkZW98cGxheWxpc3R8cG9kY2FzdHxwb2RjYXN0c3xwcmVvcmRlcnxwcm9tb3Rpb258cmV2aWV3fHJldmlld3N8c3RvcmV8c3R1ZGlvfHR2LXNlYXNvbnx0di1zaG93fHR2LXNob3dzfHZpZGVvfGl0dW5lcy11fGluc3RpdHV0aW9ufG9wdGludG9jb25uZWN0aW9uc3xvcHRpbnRvcGluZykoL3xcP3wkKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpjb250ZW50bGluay53b2Evd2EvbGluayhcP3wkKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpjb25uZWN0aW9ucy53b2Evd2EvPC9zdHJpbmc+CiAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9tenVzZXJwdWJsaXNoaW5nLndvYS93YS8obWFuYWdlYXJ0aXN0YWxlcnRzKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpwZXJzb25hbGl6ZXIud29hL3dhLyhteWFsZXJ0cyk8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLWFwcHN0b3JlLWhvc3QtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPigoYnV5fG15fHNlYXJjaHxjKVwuKT9pdHVuZXNcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICA8c3RyaW5nPnBob2Jvc1wuYXBwbGVcLmNvbSQ8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLWFwcHN0b3JlLXBhdGgtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPlsmYW1wOz9dKG10PTh8bWVkaWE9c29mdHdhcmUpKCZhbXA7fCQpPC9zdHJpbmc+CiAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9tenNvZnR3YXJldXBkYXRlLndvYS93YS8oYXZhaWxhYmxlc29mdHdhcmV1cGRhdGVzKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHZpZXdzb2Z0d2FyZXxwYW5kYXN0b3JlZnJvbnR8dmlld2ZlYXR1cmVkc29mdHdhcmVjYXRlZ29yaWVzKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpmaW5hbmNlLndvYS93YS8oY29tLmFwcGxlLmppbmdsZS5hcHAuZmluYW5jZS5kaXJlY3RhY3Rpb24vKT8odmVyaWZ5YWNjb3VudGVtYWlsKTwvc3RyaW5nPgogICAgPHN0cmluZz5eLyhbYS16XVthLXpdLyk/KGFwcHxhcHBzLXN0b3JlfGRldmVsb3BlcikoL3xcP3wkKTwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5wMi1sYXVuY2gtZWJvb2tzdG9yZS1ob3N0LXBhdHRlcm5zPC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz4oKGJ1eXxteXxzZWFyY2h8YylcLik/aXR1bmVzXC5hcHBsZVwuY29tJDwvc3RyaW5nPgogICAgPHN0cmluZz5waG9ib3NcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PnAyLWxhdW5jaC1lYm9va3N0b3JlLXBhdGgtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPlsmYW1wOz9dKG10PTExfG1lZGlhPWVib29rKSgmYW1wO3wkKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHZpZXdib29rKTwvc3RyaW5nPgogICAgPHN0cmluZz5eLyhbYS16XVthLXpdLyk/KGJvb2spKC98XD98JCk8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLWFwcGxlLXN0b3JlLWhvc3QtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPl4oc3RvcmV8cmVzZXJ2ZSlbLl1hcHBsZVsuXWNvbSQ8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLWFwcGxlLXN0b3JlLXBhdGgtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPl4vKFteL10rLyk/eGMvPC9zdHJpbmc+CiAgICA8c3RyaW5nPl5bXj9dKi9yZXNlcnZlcHJvZHVjdChcP3wkKTwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5wMi11cmwtcmVzb2x1dGlvbjwva2V5PgogIDxhcnJheT4KICAgIDxkaWN0PgogICAgICA8a2V5PnAyLXVybC1zZWN0aW9uLW5hbWU8L2tleT48c3RyaW5nPkVCb29rczwvc3RyaW5nPgogICAgICA8a2V5Pmhvc3Qtc3VmZml4LXdoaXRlbGlzdDwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz4uYXBwbGUuY29tPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+aG9zdC1wYXR0ZXJuczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz4oKGJ1eXxteXxzZWFyY2h8YylcLik/aXR1bmVzXC5hcHBsZVwuY29tJDwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+cGhvYm9zXC5hcHBsZVwuY29tJDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnBhdGgtcGF0dGVybnM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+WyZhbXA7P10obXQ9MTF8bWVkaWE9ZWJvb2spKCZhbXA7fCQpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHZpZXdib29rKTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+Xi8oW2Etel1bYS16XS8pPyhib29rKSgvfFw/fCQpPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+c2NoZW1lLW1hcHBpbmc8L2tleT4KICAgICAgPGRpY3Q+CiAgICAgICAgPGtleT5odHRwPC9rZXk+PHN0cmluZz5pdG1zLWJvb2s8L3N0cmluZz4KICAgICAgICA8a2V5Pmh0dHBzPC9rZXk+PHN0cmluZz5pdG1zLWJvb2tzPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgIDwvZGljdD4KICAgIDxkaWN0PgogICAgICA8a2V5PnAyLXVybC1zZWN0aW9uLW5hbWU8L2tleT48c3RyaW5nPk1vYmlsZVNvZnR3YXJlQXBwbGljYXRpb25zPC9zdHJpbmc+CiAgICAgIDxrZXk+aG9zdC1zdWZmaXgtd2hpdGVsaXN0PC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPi5hcHBsZS5jb208L3N0cmluZz4KICAgICAgPC9hcnJheT4KICAgICAgPGtleT5ob3N0LXBhdHRlcm5zPC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPigoYnV5fG15fHNlYXJjaHxjKVwuKT9pdHVuZXNcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5waG9ib3NcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+cGF0aC1wYXR0ZXJuczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5bJmFtcDs/XShtdD04fG1lZGlhPXNvZnR3YXJlKSgmYW1wO3wkKTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+Xi93ZWJvYmplY3RzL216c29mdHdhcmV1cGRhdGUud29hL3dhLyhhdmFpbGFibGVzb2Z0d2FyZXVwZGF0ZXMpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHZpZXdzb2Z0d2FyZXxwYW5kYXN0b3JlZnJvbnR8dmlld2ZlYXR1cmVkc29mdHdhcmVjYXRlZ29yaWVzKTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+Xi93ZWJvYmplY3RzL216ZmluYW5jZS53b2Evd2EvKGNvbS5hcHBsZS5qaW5nbGUuYXBwLmZpbmFuY2UuZGlyZWN0YWN0aW9uLyk/KHZlcmlmeWFjY291bnRlbWFpbCk8L3N0cmluZz4KICAgICAgICA8c3RyaW5nPl4vKFthLXpdW2Etel0vKT8oYXBwfGFwcHMtc3RvcmV8ZGV2ZWxvcGVyKSgvfFw/fCQpPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+c2NoZW1lLW1hcHBpbmc8L2tleT4KICAgICAgPGRpY3Q+CiAgICAgICAgPGtleT5odHRwPC9rZXk+PHN0cmluZz5pdG1zLWFwcHM8L3N0cmluZz4KICAgICAgICA8a2V5Pmh0dHBzPC9rZXk+PHN0cmluZz5pdG1zLWFwcHNzPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgIDwvZGljdD4KICAgIDxkaWN0PgogICAgICA8a2V5PnAyLXVybC1zZWN0aW9uLW5hbWU8L2tleT48c3RyaW5nPk11c2ljPC9zdHJpbmc+CiAgICAgIDxrZXk+aG9zdC1zdWZmaXgtd2hpdGVsaXN0PC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPi5hcHBsZS5jb208L3N0cmluZz4KICAgICAgPC9hcnJheT4KICAgICAgPGtleT5ob3N0LXBhdHRlcm5zPC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPigoYnV5fG15fHNlYXJjaHxjKVwuKT9pdHVuZXNcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5waG9ib3NcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+cGF0aC1wYXR0ZXJuczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHN0b3JlZnJvbnR8dmlld3RvcHRlbnNsaXN0fHZpZXd0b3BmaWZ0eXx2aWV3dG9wfHZpZXdhdWRpb2Jvb2t8dmlld2dyb3VwaW5nfHZpZXdnZW5yZXx2aWV3cGxheWxpc3RzcGFnZXx2aWV3cm9vbXx2aWV3YWxidW18dmlld3BvZGNhc3R8dmlld21peHxzdG9yZWZyb250c3x2aWV3Y29udGVudHN1c2VycmV2aWV3c3x2aWV3ZXVsYXx2aWV3dHZzaG93fHZpZXd0dnNlYXNvbnx2aWV3bW92aWV8dmlld3ZpZGVvfGZvb3RlcnNlY3Rpb25zfGxpYnJhcnlsaW5rfHZpZXdmZWF0dXJlfHZpZXdhcnRpc3QpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzZWFyY2gud29hL3dhLyhzZWFyY2h8YWR2YW5jZWRzZWFyY2gpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXooZmFzdCk/ZmluYW5jZS53b2Evd2EvKGNvbS5hcHBsZS5qaW5nbGUuYXBwLmZpbmFuY2UuZGlyZWN0YWN0aW9uLyk/KHJlZGVlbWxhbmRpbmdwYWdlfGZyZWVwcm9kdWN0Y29kZXdpemFyZHxjaGVja2ZvcnByZW9yZGVyc3xzaG93ZGlhbG9nZm9ycmVkZWVtfGJ1eW9uZWdldG9uZXxjaGVja2ZvcnB1cmNoYXNlc2F1dGh8YXJ0aXN0Y29ubmVjdHxyZWpvaW5hcnRpc3Rjb25uZWN0fG9wdGludG9jb25uZWN0aW9uc3xyZWpvaW5vcHRpbnRvY29ubmVjdGlvbnN8b3B0aW50b3BpbmcpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eLyhbYS16XVthLXpdLyk/KGFsYnVtfGFydGlzdHxhdWRpb2Jvb2t8YXVkaW9ib29rc3xhdXRob3J8Ym9va3xicm93c2V8Y2F0ZWdvcnl8Y2VsZWJyaXR5LXBsYXlsaXN0c3xjaGFydHN8Y29sbGFib3JhdGlvbnxjb2xsZWN0aW9ufGNvbGxlY3Rpb25zfGNvbXBvc2VyfGN1c3RvbWVyLXJldmlld3N8ZGlyZWN0b3J8ZXNzZW50aWFsfGVzc2VudGlhbHN8ZmFxfGdlbnJlfGltaXh8aW1peGVzfG1vdmllfG1vdmllLXJlbnRhbHN8bW92aWVzfG11c2ljfG11c2ljLXZpZGVvfHBsYXlsaXN0fHBvZGNhc3R8cG9kY2FzdHN8cHJlb3JkZXJ8cHJvbW90aW9ufHJldmlld3xyZXZpZXdzfHN0b3JlfHN0dWRpb3x0di1zZWFzb258dHYtc2hvd3x0di1zaG93c3x2aWRlb3xpdHVuZXMtdXxpbnN0aXR1dGlvbnxvcHRpbnRvY29ubmVjdGlvbnN8b3B0aW50b3BpbmcpKC98XD98JCk8L3N0cmluZz4KICAgICAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9temNvbnRlbnRsaW5rLndvYS93YS9saW5rKFw/fCQpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpjb25uZWN0aW9ucy53b2Evd2EvPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXp1c2VycHVibGlzaGluZy53b2Evd2EvKG1hbmFnZWFydGlzdGFsZXJ0cyk8L3N0cmluZz4KICAgICAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9tenBlcnNvbmFsaXplci53b2Evd2EvKG15YWxlcnRzKTwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnNjaGVtZS1tYXBwaW5nPC9rZXk+CiAgICAgIDxkaWN0PgogICAgICAgIDxrZXk+aHR0cDwva2V5PjxzdHJpbmc+aXRtczwvc3RyaW5nPgogICAgICAgIDxrZXk+aHR0cHM8L2tleT48c3RyaW5nPml0bXNzPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgIDwvZGljdD4KICA8L2FycmF5PgogIDxrZXk+cDItbXVzaWMtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICA8a2V5PnAyLXNvZnR3YXJlLXN0b3JlLWF2YWlsYWJsZTwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5wMi1wYW5kYS1zdG9yZWZyb250PC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3BhbmRhU3RvcmVGcm9udDwvc3RyaW5nPgogIDxrZXk+cDItcGFuZGEtZ2VucmVzPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdGZWF0dXJlZFNvZnR3YXJlQ2F0ZWdvcmllczwvc3RyaW5nPgogIDxrZXk+cDItcGFuZGEtdG9wLWNoYXJ0czwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VG9wP2dlbnJlSWQ9MzY8L3N0cmluZz4KICA8a2V5PnAyLXBhbmRhLXRvcC1maWZ0eTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VG9wRmlmdHk/Z2VucmVJZD0zNjwvc3RyaW5nPgogIDxrZXk+cDItcGFuZGEtdXBkYXRlczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3UGFuZGFVcGRhdGVzPC9zdHJpbmc+CiAgPGtleT5wMi1wYW5kYS1zZWFyY2g8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zZWFyY2guaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU2VhcmNoLndvYS93YS9zZWFyY2g/bWVkaWE9c29mdHdhcmU8L3N0cmluZz4KICA8a2V5PnAyLXBhbmRhLXNlYXJjaEhpbnRzPC9rZXk+PHN0cmluZz5odHRwOi8vYXguc2VhcmNoLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlNlYXJjaEhpbnRzLndvYS93YS9oaW50cz9tZWRpYT1zb2Z0d2FyZTwvc3RyaW5nPgogIDxrZXk+YXZhaWxhYmxlLXNvZnR3YXJlLXVwZGF0ZXM8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zdS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTb2Z0d2FyZVVwZGF0ZS53b2Evd2EvYXZhaWxhYmxlU29mdHdhcmVVcGRhdGVzPC9zdHJpbmc+CiAgPGtleT5hdmFpbGFibGUtc29mdHdhcmUtdXBkYXRlcy1odG1sPC9rZXk+PHN0cmluZz5odHRwOi8vYXguc3UuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU29mdHdhcmVVcGRhdGUud29hL3dhL3ZpZXdTb2Z0d2FyZVVwZGF0ZXM8L3N0cmluZz4KICA8a2V5PmF2YWlsYWJsZS1zb2Z0d2FyZS1jaGVjay1vbi1sYXVuY2g8L2tleT48c3RyaW5nPllFUzwvc3RyaW5nPgogIDxrZXk+YXZhaWxhYmxlLXNvZnR3YXJlLXVwZGF0ZXMtcmVsb2FkLWZyZXF1ZW5jeTwva2V5PjxpbnRlZ2VyPjg0PC9pbnRlZ2VyPgogIDxrZXk+YXZhaWxhYmxlLXNvZnR3YXJlLXVwZGF0ZXMtY29tcHJlc3MtcmVxdWVzdDwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5wMi1hcHBsaWNhdGlvbi11c2VyLXJldmlldy1pbmZvPC9rZXk+PHN0cmluZz5odHRwczovL3VzZXJwdWIuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aVXNlclB1Ymxpc2hpbmcud29hL3dhL3VzZXJSZXZpZXdJbmZvP3R5cGU9UHVycGxlK1NvZnR3YXJlJmFtcDthbXA7ZGlzcGxheWFibGUta2luZD0xMTwvc3RyaW5nPgogIDxrZXk+cDItY2FwYWJpbGl0aWVzLWRpYWxvZzwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9jYXBhYmlsaXRpZXNEaWFsb2c8L3N0cmluZz4KICA8a2V5PnAyLWFjY2Vzc29yeS1yb29tPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdBY2Nlc3NvcnlSb29tPC9zdHJpbmc+CiAgPGtleT5wMi1wcm9kdWN0LW9mZmVyczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9mZXRjaFNvZnR3YXJlQWRkT25zPC9zdHJpbmc+CiAgPGtleT5wMi1wcm9kdWN0LW9mZmVycy1iYXRjaC1saW1pdDwva2V5PjxpbnRlZ2VyPjEwMDwvaW50ZWdlcj4KICA8a2V5PnAyLWFwcC1nZW5pdXMtc3RhdGlzdGljczwva2V5PgogIDxkaWN0PgogICAgPGtleT5hbGxvd2VkLWNvbm5lY3Rpb24tdHlwZXM8L2tleT4KICAgIDxkaWN0PgogICAgICA8a2V5PjNHPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT4yRzwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgICAgIDxrZXk+V2lGaTwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgICA8L2RpY3Q+CiAgICA8a2V5PnVybDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9nZW5pdXMuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL1VDQXBwQ2hhbm5lbC53b2Evd2EvYXBwU3RhdHM8L3N0cmluZz4KICAgIDxrZXk+cG9zdC1pbnRlcnZhbDwva2V5PjxpbnRlZ2VyPjE0NDAwPC9pbnRlZ2VyPgogICAgPGtleT5zZW5kLWRhdGEtdXNhZ2U8L2tleT48c3RyaW5nPk5PPC9zdHJpbmc+CiAgPC9kaWN0PgogIDxrZXk+Y2xpZW50LWNhY2hlLWRlZmluaXRpb25zPC9rZXk+CiAgPGRpY3Q+CiAgICA8a2V5PmNhY2hlczwva2V5PgogICAgPGFycmF5PgogICAgICA8ZGljdD4KICAgICAgICA8a2V5PnR5cGU8L2tleT48c3RyaW5nPmNsaWVudC1jYWNoZS1kZWZpbml0aW9uPC9zdHJpbmc+CiAgICAgICAgPGtleT5tZW1vcnktc2l6ZTwva2V5PjxpbnRlZ2VyPjE1NzI4NjQ8L2ludGVnZXI+CiAgICAgICAgPGtleT5kaXNrLXNpemU8L2tleT48aW50ZWdlcj4xNTcyODY0PC9pbnRlZ2VyPgogICAgICAgIDxrZXk+cGVyc2lzdGVudC1pZDwva2V5PjxzdHJpbmc+QjNDQnNjcmlwdENhY2hlPC9zdHJpbmc+CiAgICAgICAgPGtleT5jbGllbnRzPC9rZXk+CiAgICAgICAgPGFycmF5PgogICAgICAgICAgPHN0cmluZz5Tb2Z0d2FyZTwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5lQm9va3M8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+V2lGaS1NdXNpYzwvc3RyaW5nPgogICAgICAgIDwvYXJyYXk+CiAgICAgICAgPGtleT5maWxlLWV4dGVuc2lvbnM8L2tleT4KICAgICAgICA8YXJyYXk+CiAgICAgICAgICA8c3RyaW5nPmNzczwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5jc3N6PC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPmpzPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPmpzejwvc3RyaW5nPgogICAgICAgIDwvYXJyYXk+CiAgICAgIDwvZGljdD4KICAgICAgPGRpY3Q+CiAgICAgICAgPGtleT50eXBlPC9rZXk+PHN0cmluZz5jbGllbnQtY2FjaGUtZGVmaW5pdGlvbjwvc3RyaW5nPgogICAgICAgIDxrZXk+bWVtb3J5LXNpemU8L2tleT48aW50ZWdlcj4yMDk3MTUyPC9pbnRlZ2VyPgogICAgICAgIDxrZXk+ZGlzay1zaXplPC9rZXk+PGludGVnZXI+MjA5NzE1MjwvaW50ZWdlcj4KICAgICAgICA8a2V5PnBlcnNpc3RlbnQtaWQ8L2tleT48c3RyaW5nPkIzQ0JpbWFnZUNhY2hlPC9zdHJpbmc+CiAgICAgICAgPGtleT5jbGllbnRzPC9rZXk+CiAgICAgICAgPGFycmF5PgogICAgICAgICAgPHN0cmluZz5Tb2Z0d2FyZTwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5lQm9va3M8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+V2lGaS1NdXNpYzwvc3RyaW5nPgogICAgICAgIDwvYXJyYXk+CiAgICAgICAgPGtleT51cmwtcGF0dGVybnM8L2tleT4KICAgICAgICA8YXJyYXk+CiAgICAgICAgICA8c3RyaW5nPnNwcml0ZXMtazItc3RvcmVmcm9udC5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX2JsdWVfcHJlc3NlZC5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX2JsdWUucG5nPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPm1pZGRsZV9ncmF5X3ByZXNzZWQucG5nPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPm1pZGRsZV9ncmF5LnBuZzwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5taWRkbGVfZ3JlZW5fcHJlc3NlZC5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX2dyZWVuLnBuZzwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5taWRkbGVfZGFya2dyYXlfcHJlc3NlZC5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX3NpbHZlcl9wcmVzc2VkLnBuZzwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5hY3Rpb24tYnV0dG9uLWJnLnBuZzwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5hY3Rpb24tYnV0dG9uLWJnLXByZXNzZWQucG5nPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPm1pZGRsZV9kYXJrZ3JheS5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX3NpbHZlci5wbmc8L3N0cmluZz4KICAgICAgICA8L2FycmF5PgogICAgICA8L2RpY3Q+CiAgICAgIDxkaWN0PgogICAgICAgIDxrZXk+dHlwZTwva2V5PjxzdHJpbmc+Y2xpZW50LWNhY2hlLWRlZmluaXRpb248L3N0cmluZz4KICAgICAgICA8a2V5Pm1lbW9yeS1zaXplPC9rZXk+PGludGVnZXI+MjA5NzE1MjwvaW50ZWdlcj4KICAgICAgICA8a2V5PnBlcnNpc3RlbnQtaWQ8L2tleT48c3RyaW5nPkIzQ0JtaXNjQ2FjaGU8L3N0cmluZz4KICAgICAgICA8a2V5PmNsaWVudHM8L2tleT4KICAgICAgICA8YXJyYXk+CiAgICAgICAgICA8c3RyaW5nPlNvZnR3YXJlPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPmVCb29rczwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5XaUZpLU11c2ljPC9zdHJpbmc+CiAgICAgICAgPC9hcnJheT4KICAgICAgPC9kaWN0PgogICAgPC9hcnJheT4KICA8L2RpY3Q+CiAgPGtleT5wbGF0Zm9ybS1ncmFkaWVudHM8L2tleT4KICA8ZGljdD4KICAgIDxrZXk+ZUJvb2tzPC9rZXk+CiAgICA8ZGljdD4KICAgICAgPGtleT5wYWdlPC9rZXk+CiAgICAgIDxkaWN0PgogICAgICAgIDxrZXk+dG9wLWNvbG9yPC9rZXk+PHN0cmluZz5yZ2IoMjExLDIxNSwyMTgpPC9zdHJpbmc+CiAgICAgICAgPGtleT5ib3R0b20tY29sb3I8L2tleT48c3RyaW5nPnJnYigyMTEsMjE1LDIxOCk8L3N0cmluZz4KICAgICAgPC9kaWN0PgogICAgPC9kaWN0PgogIDwvZGljdD4KICA8a2V5PnZpZXctbW9iaWxlLXNvZnR3YXJlLXVwZGF0ZXM8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zdS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTb2Z0d2FyZVVwZGF0ZS53b2Evd2Evdmlld0FsbEF2YWlsYWJsZVNvZnR3YXJlVXBkYXRlczwvc3RyaW5nPgogIDxrZXk+bm93LXBsYXlpbmctdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL25vd1BsYXlpbmc8L3N0cmluZz4KICA8a2V5Pm5vdy1wbGF5aW5nLW5ldHdvcmstZGV0ZWN0LXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9ub3dQbGF5aW5nPC9zdHJpbmc+CiAgPGtleT5hZGFtaWQtbG9va3VwLXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9hZGFtSWRMb29rdXA8L3N0cmluZz4KICA8a2V5PnJlbnRhbC1yZWNvbW1lbmRhdGlvbnM8L2tleT48c3RyaW5nPmh0dHA6Ly9teS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpQZXJzb25hbGl6ZXIud29hL3dhL3JlbnRhbFJlY29tbWVuZGF0aW9uczwvc3RyaW5nPgogIDxrZXk+cmVudGFsLW1haW48L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1JlbnRhbE1haW48L3N0cmluZz4KICA8a2V5PnR2LXJlbnRhbC1tYWluPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdUdlJlbnRhbE1haW4/cz0xNDM0NDE8L3N0cmluZz4KICA8a2V5PnZpZXdUVlNlYXNvbjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VFZTZWFzb248L3N0cmluZz4KICA8a2V5PnZpZXdUVlNob3c8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1RWU2hvdzwvc3RyaW5nPgogIDxrZXk+dmlld01vdmllPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdNb3ZpZTwvc3RyaW5nPgogIDxrZXk+dmlld0dhbWU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0dhbWU8L3N0cmluZz4KICA8a2V5PnZpZXdQcmVvcmRlcjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3UHJlb3JkZXI8L3N0cmluZz4KICA8a2V5Pm5pa2UtcGx1cy1sYW5kaW5nLXBhZ2U8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0N1c3RvbVBhZ2U/bmFtZT1wYWdlTmlrZTwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtYWNjZXB0aW5nLXJlcXVlc3RzPC9rZXk+PHN0cmluZz5odHRwczovL2dlbml1cy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvVUNHb3Zlcm5vci53b2Evd2EvbGlicmFyeVVwZGF0ZUFjY2VwdGluZ1JlcXVlc3RzPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1yZXF1ZXN0PC9rZXk+PHN0cmluZz5odHRwczovL2dlbml1cy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvVUNHb3Zlcm5vci53b2Evd2EvcmVxdWVzdExpYnJhcnlVcGRhdGU8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLWNoZWNrPC9rZXk+PHN0cmluZz5odHRwczovL2dlbml1cy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvVUNHb3Zlcm5vci53b2Evd2EvY2hlY2tVcGRhdGVQcm9jZXNzaW5nU3RhdHVzPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1tZWRpYS10eXBlczwva2V5PjxzdHJpbmc+Ym9vayxmZWF0dXJlLW1vdmllLG11c2ljLXZpZGVvLHBvZGNhc3QtZmVlZCxwb2RjYXN0LWVwaXNvZGUsc29uZyx0di1lcGlzb2RlPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1maWVsZHM8L2tleT48c3RyaW5nPmFkZGVkLWRhdGUsYWxidW0tcmF0aW5nLGFsYnVtLXJhdGluZy1jb21wdXRlZCxhcnRpc3QtaWQsYXJ0aXN0LW5hbWUsY2RkYi1maW5nZXJwcmludCxjZGRiLWZpbmdlcnByaW50LW5vdC1hdmFpbCxjZGRiLW1lZGlhLWlkLGNkZGItbXVpZCxjZGRiLXRvYyxjZGRiLXR1aWQsY2RkYi10dWlkLXRhZyxjb21wb3Nlci1uYW1lLGR1cmF0aW9uLGVpZCxlcGlzb2RlLWlkLGVwaXNvZGUtbnVtYmVyLGV4Y2x1ZGUtZnJvbS1zaHVmZmxlLGZlZWQtdXJsLGZpbGVuYW1lLGdlbml1cy1wbGF5LWNvdW50LGdlbnJlLW5hbWUsZ3JhbmRwYXJlbnQtZGlyLGl0ZW0tY2hlY2tlZCxpdGVtLWlkLGl0ZW0tbmFtZSxraW5kLGxhY2tzLWNvdmVyLWFydCxsYXN0LXBsYXllZC1kYXRlLGxhc3Qtc2tpcHBlZC1kYXRlLGxvbmctZGVzY3JpcHRpb24sbWF0Y2gtaWQscGFyZW50LWRpcixwZXJzaXN0ZW50LWlkLHBsYXktY291bnQscGxheWxpc3QtaWQscGxheWxpc3QtbmFtZSxwb2RjYXN0LWNhdGVnb3J5LHBvZGNhc3QtZ3VpZCxwb2RjYXN0LWlkLHByb3RlY3RlZCxyZW50YWwsc2Vhc29uLW51bWJlcixzaG93LHNraXAtY291bnQsdHJhY2stbnVtYmVyLHRyYWNrLWNvdW50LHVzZXItcmF0aW5nLHVzZXItcmF0aW5nLWNvbXB1dGVkLHZhbGlkLWZpZWxkcyx5ZWFyPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1jb3JyZWxhdGlvbi1maWVsZHM8L2tleT48c3RyaW5nPmFkZGVkLWRhdGUsYWxidW0tcmF0aW5nLGFsYnVtLXJhdGluZy1jb21wdXRlZCxsYXN0LXBsYXllZC1kYXRlLGxhc3Qtc2tpcHBlZC1kYXRlLHBsYXktY291bnQsc2tpcC1jb3VudCx1c2VyLXJhdGluZyx1c2VyLXJhdGluZy1jb21wdXRlZDwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtbWF0Y2hpbmctZmllbGRzPC9rZXk+PHN0cmluZz5hcnRpc3QtbmFtZSxjZGRiLWZpbmdlcnByaW50LGNkZGItZmluZ2VycHJpbnQtbm90LWF2YWlsLCBjZGRiLW1lZGlhLWlkLGNkZGItbXVpZCxjZGRiLXRvYyxjZGRiLXR1aWQsY2RkYi10dWlkLXRhZyxjb21wb3Nlci1uYW1lLGR1cmF0aW9uLGVpZCxmaWxlbmFtZSxnZW5yZS1uYW1lLGdyYW5kcGFyZW50LWRpcixpdGVtLWNoZWNrZWQsaXRlbS1pZCxpdGVtLW5hbWUsa2luZCxtYXRjaC1pZCxwYXJlbnQtZGlyLHBlcnNpc3RlbnQtaWQscGxheWxpc3QtbmFtZSxwcm90ZWN0ZWQsdHJhY2stbnVtYmVyLHRyYWNrLWNvdW50LHllYXI8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLW1pbmltdW0tZmllbGRzPC9rZXk+PHN0cmluZz5hcnRpc3QtbmFtZSxjZGRiLWZpbmdlcnByaW50LGNkZGItZmluZ2VycHJpbnQtbm90LWF2YWlsLCBjZGRiLW1lZGlhLWlkLGNkZGItbXVpZCxjZGRiLXRvYyxjZGRiLXR1aWQsY2RkYi10dWlkLXRhZyxjb21wb3Nlci1uYW1lLGR1cmF0aW9uLGVpZCxmaWxlbmFtZSxnZW5yZS1uYW1lLGdyYW5kcGFyZW50LWRpcixpdGVtLWNoZWNrZWQsaXRlbS1pZCxpdGVtLW5hbWUsa2luZCxtYXRjaC1pZCxwYXJlbnQtZGlyLHBlcnNpc3RlbnQtaWQscGxheWxpc3QtbmFtZSxwcm90ZWN0ZWQsdHJhY2stbnVtYmVyLHRyYWNrLWNvdW50LHllYXI8L3N0cmluZz4KICA8a2V5PnVjLXNlcnZlci1kaXNhYmxlZDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNFcnJvcj9lcnJvcj1zZXJ2ZXJEaXNhYmxlZDwvc3RyaW5nPgogIDxrZXk+dWMtc2VydmVyLW5vdC1hY2NlcHRpbmctc2lnbnVwczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNFcnJvcj9lcnJvcj1zZXJ2ZXJOb3RBY2NlcHRpbmdTaWdudXBzPC9zdHJpbmc+CiAgPGtleT51Yy1nb3Zlcm5vci1lcnJvcjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNQcm9ncmVzcz9zdGF0ZT1lcnJvciZhbXA7c3RlcD0yPC9zdHJpbmc+CiAgPGtleT51Yy1wcm9ncmVzcy1zdG9wcGVkPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc1Byb2dyZXNzP3N0YXRlPXN0b3BwZWQ8L3N0cmluZz4KICA8a2V5PnVjLXN0ZXAtb25lPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc1Byb2dyZXNzP3N0ZXA9MTwvc3RyaW5nPgogIDxrZXk+dWMtc3RlcC10d28tc2VydmVyLXByb2Nlc3Npbmc8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RhdGU9c2VydmVycHJvY2Vzc2luZyZhbXA7c3RlcD0yPC9zdHJpbmc+CiAgPGtleT51Yy1zdGVwLXR3by11cGxvYWQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RhdGU9dXBsb2FkJmFtcDtzdGVwPTI8L3N0cmluZz4KICA8a2V5PnVjLXN0ZXAtdGhyZWU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RlcD0zPC9zdHJpbmc+CiAgPGtleT51Yy1zdWNjZXNzLXBhZ2U8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zSG93VG8/c3RhdGU9c3VjY2Vzczwvc3RyaW5nPgogIDxrZXk+dWMtaG93LXRvLXBhZ2U8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zSG93VG88L3N0cmluZz4KICA8a2V5Pmdlbml1cy1vcHQtb3V0PC9rZXk+PHN0cmluZz5odHRwczovL2dlbml1cy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvVUNHb3Zlcm5vci53b2Evd2Evb3B0T3V0TGlicmFyeTwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtc2VydmVyLWRpc2FibGVkPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc0Vycm9yP2Vycm9yPXNlcnZlckRpc2FibGVkPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1zZXJ2ZXItbm90LWFjY2VwdGluZy1zaWdudXBzPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc0Vycm9yP2Vycm9yPXNlcnZlck5vdEFjY2VwdGluZ1NpZ251cHM8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLWdvdmVybm9yLWVycm9yPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc1Byb2dyZXNzP3N0YXRlPWVycm9yJmFtcDtzdGVwPTI8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLXN0b3BwZWQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RhdGU9c3RvcHBlZDwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtc3RlcC1vbmU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RlcD0xPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1zdGVwLXR3by1zZXJ2ZXItcHJvY2Vzc2luZzwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNQcm9ncmVzcz9zdGF0ZT1zZXJ2ZXJwcm9jZXNzaW5nJmFtcDtzdGVwPTI8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLXN0ZXAtdHdvLXVwbG9hZDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNQcm9ncmVzcz9zdGF0ZT11cGxvYWQmYW1wO3N0ZXA9Mjwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtc3RlcC10aHJlZTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNQcm9ncmVzcz9zdGVwPTM8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLXN1Y2Nlc3MtcGFnZTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNIb3dUbz9zdGF0ZT1zdWNjZXNzPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1ob3ctdG8tcGFnZTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNIb3dUbzwvc3RyaW5nPgogIDxrZXk+c2lkZWJhci1mYWxsYmFjazwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9zaWRlYmFyRGVmYXVsdDwvc3RyaW5nPgogIDxrZXk+c2lkZWJhci10aW1lb3V0PC9rZXk+PGludGVnZXI+NTwvaW50ZWdlcj4KICA8a2V5PnNpZGViYXItd2VsY29tZTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNpZGViYXIuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU2lkZWJhci53b2Evd2Evc2lkZWJhcldlbGNvbWU8L3N0cmluZz4KICA8a2V5PnNpZGViYXItbWF0Y2gtcnVsZXM8L2tleT4KICA8YXJyYXk+CiAgICA8ZGljdD4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9zaWRlYmFyTWF0Y2g8L3N0cmluZz4KICAgICAgPGtleT5vcHRpb25hbC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+cDwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+YTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+a2luZDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnJlcXVpcmVkLWZpZWxkczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5pZDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgPC9kaWN0PgogICAgPGRpY3Q+CiAgICAgIDxrZXk+dXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd2Evc2lkZWJhck1hdGNoPC9zdHJpbmc+CiAgICAgIDxrZXk+b3B0aW9uYWwtZmllbGRzPC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPmtpbmQ8L3N0cmluZz4KICAgICAgPC9hcnJheT4KICAgICAgPGtleT5yZXF1aXJlZC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+Y2RkYi10dWlkPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICA8L2RpY3Q+CiAgICA8ZGljdD4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9zaWRlYmFyTWF0Y2g8L3N0cmluZz4KICAgICAgPGtleT5vcHRpb25hbC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+dG51bTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+a2luZDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnJlcXVpcmVkLWZpZWxkczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5jZGRiPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICA8L2RpY3Q+CiAgICA8ZGljdD4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9zaWRlYmFyTWF0Y2g8L3N0cmluZz4KICAgICAgPGtleT5vcHRpb25hbC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+YW48L3N0cmluZz4KICAgICAgICA8c3RyaW5nPmduPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5wbjwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+a2luZDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnJlcXVpcmVkLWZpZWxkczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5uPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICA8L2RpY3Q+CiAgICA8ZGljdD4KICAgICAgPGtleT5vcHRpb25hbC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+ZHA8L3N0cmluZz4KICAgICAgICA8c3RyaW5nPmtpbmQ8L3N0cmluZz4KICAgICAgPC9hcnJheT4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zaWRlYmFyLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlNpZGViYXIud29hL3dhL3NpZGViYXI8L3N0cmluZz4KICAgIDwvZGljdD4KICA8L2FycmF5PgogIDxrZXk+c2lkZWJhci1kaXN0aW5ndWlzaGVkLXBsYXlsaXN0czwva2V5PgogIDxkaWN0PgogICAgPGtleT4yPC9rZXk+CiAgICA8ZGljdD4KICAgIDwvZGljdD4KICAgIDxrZXk+Mzwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5PjQ8L2tleT4KICAgIDxkaWN0PgogICAgPC9kaWN0PgogICAgPGtleT4yNjwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5Pjc8L2tleT4KICAgIDxkaWN0PgogICAgPC9kaWN0PgogICAgPGtleT4xOTwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5PjIwPC9rZXk+CiAgICA8ZGljdD4KICAgIDwvZGljdD4KICA8L2RpY3Q+CiAgPGtleT5zaWRlYmFyLWZhbGxiYWNrMjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9zaWRlYmFyRGVmYXVsdDwvc3RyaW5nPgogIDxrZXk+c2lkZWJhci10aW1lb3V0Mjwva2V5PjxpbnRlZ2VyPjA8L2ludGVnZXI+CiAgPGtleT5zaWRlYmFyLWRpc3Rpbmd1aXNoZWQtcGxheWxpc3RzMjwva2V5PgogIDxkaWN0PgogICAgPGtleT4xOTwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5PjQ8L2tleT4KICAgIDxkaWN0PgogICAgPC9kaWN0PgogICAgPGtleT4yNjwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5PjIwPC9rZXk+CiAgICA8ZGljdD4KICAgIDwvZGljdD4KICA8L2RpY3Q+CiAgPGtleT5wb2RjYXN0LWdldC1lcGlzb2RlPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9tZXRyaWNzL3BvZGNhc3QvZ2V0RXBpc29kZTwvc3RyaW5nPgogIDxrZXk+cG9kY2FzdC1wbGF5LWVwaXNvZGU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL21ldHJpY3MvcG9kY2FzdC9wbGF5RXBpc29kZTwvc3RyaW5nPgogIDxrZXk+ZG93bmxvYWQtc3BlZWR0ZXN0LXBvc3QtcmVzdWx0cy11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL3VwbG9hZC9kaWFnL2F0di88L3N0cmluZz4KICA8a2V5PmRvd25sb2FkLXNwZWVkdGVzdC11cmxzPC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5odHRwOi8vYTU2OC5waG9ib3MuYXBwbGUuY29tL3VzL3IxMDAwLzAwMC9EaWFnL3Rlc3RfOE1CLm00dj9uby1zdG9yZT10cnVlPC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHA6Ly9hNTY4LnBob2Jvcy5hcHBsZS5jb20vdXMvcjEwMDAvMDAwL0RpYWcvdGVzdF84TUIubTR2PC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHA6Ly9hNTY4LnBob2Jvcy5hcHBsZS5jb20vdXMvcjEwMDAvMDAwL0RpYWcvdGVzdF84TUIubTR2PC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PmRvd25sb2FkLW1vdmllLXNwZWVkdGVzdC11cmxzPC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5odHRwOi8vYTEudi5waG9ib3MuYXBwbGUuY29tL3VzL3IxMDAwLzAwMC9EaWFnL1NURU1faGQubTR2P25vLXN0b3JlPXRydWU8L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cDovL2ExLnYucGhvYm9zLmFwcGxlLmNvbS91cy9yMTAwMC8wMDAvRGlhZy9TVEVNX2hkLm00djwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwOi8vYTEudi5waG9ib3MuYXBwbGUuY29tL3VzL3IxMDAwLzAwMC9EaWFnL1NURU1faGQubTR2PC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PnRndDwva2V5PjxzdHJpbmc+MTwvc3RyaW5nPgogIDxrZXk+ZW5kLW9mLWJvb2stdXBzZWxsLWVuYWJsZWQ8L2tleT48c3RyaW5nPllFUzwvc3RyaW5nPgogIDxrZXk+ZW5kLW9mLXBpY3R1cmUtYm9vay11cHNlbGwtZW5hYmxlZDwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5ib29rLXVwc2VsbDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9ib29rVXBzZWxsPC9zdHJpbmc+CiAgPGtleT5ib29rLWxpYnJhcnktdGl0bGU8L2tleT48c3RyaW5nPkxpYnJhcnk8L3N0cmluZz4KICA8a2V5Pmlib29rczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3U29mdHdhcmU/aWQ9MzY0NzA5MTkzPC9zdHJpbmc+CiAgPGtleT5maW4tcG9zdHM8L2tleT48c3RyaW5nPjE8L3N0cmluZz4KICA8a2V5PnRpbWVCZXR3ZWVuSG9tZVNoYXJpbmdDb3B5QXBwcm92YWxzPC9rZXk+PGludGVnZXI+ODY0MDA8L2ludGVnZXI+CiAgPGtleT5wMi1wYW5kYS1hcHBSZWNvbW1lbmRhdGlvbnM8L2tleT48c3RyaW5nPmh0dHA6Ly9teWFwcC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpBcHBQZXJzb25hbGl6ZXIud29hL3dhL2FwcFJlY29tbWVuZGF0aW9ucz9tdD04PC9zdHJpbmc+CiAgPGtleT5hZGtpdC1wcm9kdWN0LXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9hZGtpdFByb2R1Y3Q8L3N0cmluZz4KICA8a2V5PmNyb3NzLW1lcmNoYW5kaXNpbmctdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdDcm9zc01lcmNoYW5kaXNpbmc8L3N0cmluZz4KICA8a2V5Pmdob3N0LXJpZGluZy10aGUtd2hpcDwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5uZXRmbGl4LXRvcC1zaGVsZjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vbmV0ZmxpeC1nZW5lcmljLXNoZWxmLnhtbDwvc3RyaW5nPgogIDxrZXk+Z2hvc3QtcmlkaW5nLXRoZS13aGlwMjwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5jb25uZWN0aW9ucy11cmwtcHJlZml4ZXM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPmh0dHA6Ly9jLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cHM6Ly9jLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cDovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpVc2VyUHJvZmlsZS53b2E8L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aVXNlclByb2ZpbGUud29hPC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHA6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evb3B0SW50b0Nvbm5lY3Rpb25zPC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL29wdEludG9Db25uZWN0aW9uczwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3Jlam9pbk9wdEludG9Db25uZWN0aW9uczwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9yZWpvaW5PcHRJbnRvQ29ubmVjdGlvbnM8L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cDovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9zb2NpYWxPcHRPdXQ8L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evc29jaWFsT3B0T3V0PC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PmNvbm5lY3Rpb25zLW1haW48L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvY29ubmVjdGlvbnNIb21lP3M9MTQzNDQxPC9zdHJpbmc+CiAgPGtleT5wMi1zb2NpYWwtbGluazwva2V5PgogIDxkaWN0PgogICAgPGtleT5saWtlLXVybDwva2V5PjxzdHJpbmc+aHR0cHM6Ly91c2VycHViLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlVzZXJQdWJsaXNoaW5nLndvYS93YS9yYXRlP2NkPXQmYW1wO3I9LTImYW1wO3BsaXN0PXQ8L3N0cmluZz4KICAgIDxrZXk+cG9zdC11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9jLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkNvbm5lY3Rpb25zLndvYS93YS92aWV3RHZQb3N0U2hlZXQ/cz0xNDM0NDE8L3N0cmluZz4KICAgIDxrZXk+aGlzdG9yeS11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9teS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpQZXJzb25hbGl6ZXIud29hL3dhL3NvY2lhbEhpc3Rvcnk/cz0xNDM0NDE8L3N0cmluZz4KICA8L2RpY3Q+CiAgPGtleT5waW5nLW1hdGNoPC9rZXk+PHN0cmluZz5odHRwOi8vYy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpDb25uZWN0aW9ucy53b2Evd2EvcGluZ01hdGNoP3M9MTQzNDQxPC9zdHJpbmc+CiAgPGtleT5waW5nLW1hdGNoLWZpZWxkcy1saXN0PC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5pZCxhLHAsZyxjZGRiLXR1aWQsYW4sY24sZ24sa2luZCxuLHBuPC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PnBpbmctYWN0aW9uPC9rZXk+PHN0cmluZz5odHRwOi8vYy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpDb25uZWN0aW9ucy53b2Evd2EvcGluZ0FjdGlvbj9zPTE0MzQ0MTwvc3RyaW5nPgogIDxrZXk+ZGEtc29vbjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vc3RhdGljL3BhZ2VzL2FwcF9zdG9yZV9jb21pbmdfc29vbi5odG1sPC9zdHJpbmc+CiAgPGtleT51c2VyeHAtdXJsPC9rZXk+PHN0cmluZz5odHRwczovL21ldHJpY3MubXpzdGF0aWMuY29tLzwvc3RyaW5nPgogIDxrZXk+dXNlcnhwLXB1bnQtcmF0aW88L2tleT48aW50ZWdlcj4xMDAwPC9pbnRlZ2VyPgogIDxrZXk+bW9iaWxlLXVybC1oYW5kbGVyczwva2V5PgogIDxhcnJheT4KICAgIDxzdHJpbmc+aHR0cDwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwczwvc3RyaW5nPgogICAgPHN0cmluZz5pdG1zPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0bXNzPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0bXMtYXBwczwvc3RyaW5nPgogICAgPHN0cmluZz5pdG1zLWFwcHNzPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0bXMtYm9va3M8L3N0cmluZz4KICAgIDxzdHJpbmc+aXRtcy1ib29rc3M8L3N0cmluZz4KICAgIDxzdHJpbmc+bWFpbHRvPC9zdHJpbmc+CiAgICA8c3RyaW5nPmxpdmVuYXRpb248L3N0cmluZz4KICAgIDxzdHJpbmc+cHJlZnM8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+ZHQtcHVyY2hhc2VzLXBhZ2U8L2tleT48c3RyaW5nPmh0dHBzOi8vc2UuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmVFbGVtZW50cy53b2Evd2EvcHVyY2hhc2VzP3M9MTQzNDQxPC9zdHJpbmc+CiAgPGtleT5taW50LW9mZmVyczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcHJlc2VudE9mZmVyczwvc3RyaW5nPgogIDxrZXk+cGVyc29uYWxpemVkLWJ1eS1idXR0b25zPC9rZXk+CiAgPGRpY3Q+CiAgICA8a2V5PmVCb29rPC9rZXk+PHN0cmluZz5odHRwczovL3NlLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlRWxlbWVudHMud29hL3dhL2J1eUJ1dHRvbk1ldGFEYXRhP3BsaXN0UGFnZT10cnVlJmFtcDtzPTE0MzQ0MTwvc3RyaW5nPgogICAgPGtleT5zb2Z0d2FyZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9zZS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZUVsZW1lbnRzLndvYS93YS9idXlCdXR0b25NZXRhRGF0YT9wbGlzdFBhZ2U9dHJ1ZSZhbXA7cz0xNDM0NDE8L3N0cmluZz4KICA8L2RpY3Q+CiAgPGtleT5hdXRoZW50aWNhdGVBY2NvdW50PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9hdXRoZW50aWNhdGU8L3N0cmluZz4KICA8a2V5PmlQaG9uZUFjdGl2YXRpb248L2tleT48c3RyaW5nPmh0dHBzOi8vYWxiZXJ0LmFwcGxlLmNvbS9XZWJPYmplY3RzL0FMVW5icmljay53b2Evd2EvZGV2aWNlQWN0aXZhdGlvbjwvc3RyaW5nPgogIDxrZXk+ZGV2aWNlLWFjdGl2YXRpb248L2tleT48c3RyaW5nPmh0dHBzOi8vYWxiZXJ0LmFwcGxlLmNvbS9XZWJPYmplY3RzL0FMVW5icmljay53b2Evd2EvZGV2aWNlQWN0aXZhdGlvbjwvc3RyaW5nPgogIDxrZXk+Y2hlY2tVbmJyaWNrSGVhbHRoPC9rZXk+PHN0cmluZz5odHRwczovL2FsYmVydC5hcHBsZS5jb20vV2ViT2JqZWN0cy9BTFVuYnJpY2sud29hL3dhL0FMQWN0aXZhdGlvbk1vbml0b3IvY2hlY2tVbmJyaWNrSGVhbHRoPC9zdHJpbmc+CiAgPGtleT5hdXRob3JpemVNYWNoaW5lPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9hdXRob3JpemVNYWNoaW5lPC9zdHJpbmc+CiAgPGtleT5idXlQcm9kdWN0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpCdXkud29hL3dhL2J1eVByb2R1Y3Q8L3N0cmluZz4KICA8a2V5PmJ1eUNhcnQ8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2J1eUNhcnQ8L3N0cmluZz4KICA8a2V5PmRlYXV0aG9yaXplTWFjaGluZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvZGVhdXRob3JpemVNYWNoaW5lPC9zdHJpbmc+CiAgPGtleT5tYWNoaW5lQXV0aG9yaXphdGlvbkluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL21hY2hpbmVBdXRob3JpemF0aW9uSW5mbzwvc3RyaW5nPgogIDxrZXk+bW9kaWZ5QWNjb3VudDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYWNjb3VudFN1bW1hcnk8L3N0cmluZz4KICA8a2V5PnBlbmRpbmdTb25nczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcGVuZGluZ1NvbmdzPC9zdHJpbmc+CiAgPGtleT5zaWdudXA8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3NpZ251cFdpemFyZDwvc3RyaW5nPgogIDxrZXk+c29uZ0Rvd25sb2FkRG9uZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmFzdEZpbmFuY2Uud29hL3dhL3NvbmdEb3dubG9hZERvbmU8L3N0cmluZz4KICA8a2V5PmZvcmdvdHRlblBhc3N3b3JkPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9pRm9yZ290PC9zdHJpbmc+CiAgPGtleT5teUluZm88L2tleT48c3RyaW5nPmh0dHA6Ly9teWluZm8uY29ycC5hcHBsZS5jb20vPC9zdHJpbmc+CiAgPGtleT5ub0FPTEFjY291bnRzPC9rZXk+PGZhbHNlLz4KICA8a2V5Pm1pbnQtYWNjb3VudDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYWNjb3VudFN1bW1hcnk8L3N0cmluZz4KICA8a2V5Pm1pbnQtYWNjb3VudC1mcmFnbWVudDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYWNjb3VudFN1bW1hcnlGcmFnbWVudDwvc3RyaW5nPgogIDxrZXk+bG9nb3V0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9sb2dvdXQ8L3N0cmluZz4KICA8a2V5PmFkZFRvQ2FydDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYWRkVG9DYXJ0PC9zdHJpbmc+CiAgPGtleT5yZW1vdmVGcm9tQ2FydDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVtb3ZlRnJvbUNhcnQ8L3N0cmluZz4KICA8a2V5PnNob3BwaW5nQ2FydDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evc2hvcHBpbmdDYXJ0PC9zdHJpbmc+CiAgPGtleT5iY1VSTHM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPmh0dHA6Ly8uaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwOi8vd3d3LmF0ZG10LmNvbTwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5yZXBvcnRQb2RjYXN0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9yZXBvcnRQb2RjYXN0PC9zdHJpbmc+CiAgPGtleT5jaGVjay1kb3dubG9hZC1xdWV1ZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvY2hlY2tEb3dubG9hZFF1ZXVlPC9zdHJpbmc+CiAgPGtleT5zZXQtYXV0by1kb3dubG9hZDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evc2V0QXV0b0Rvd25sb2FkPC9zdHJpbmc+CiAgPGtleT5uZXctaXBvZC11c2VyPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9pUG9kUmVnaXN0cmF0aW9uPC9zdHJpbmc+CiAgPGtleT5uZXctaXBvZC11c2VyLTI8L2tleT48c3RyaW5nPmh0dHBzOi8vc2VjdXJlLm1lLmNvbS9zaWdudXAvaXR1bmVzPC9zdHJpbmc+CiAgPGtleT5uZXctdHYtdXNlcjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaVRWUmVnaXN0cmF0aW9uPC9zdHJpbmc+CiAgPGtleT5tZDUtbWlzbWF0Y2g8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL21kNU1pc21hdGNoPC9zdHJpbmc+CiAgPGtleT5yZXBvcnQtZXJyb3I8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3JlcG9ydEVycm9yRnJvbUNsaWVudDwvc3RyaW5nPgogIDxrZXk+dXBkYXRlQXNzZXQ8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3VwZGF0ZUFzc2V0PC9zdHJpbmc+CiAgPGtleT5jcmVhdGUtdG9rZW48L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NyZWF0ZVRva2VuPC9zdHJpbmc+CiAgPGtleT5jcmVhdGUtc2Vzc2lvbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvY3JlYXRlU2Vzc2lvbjwvc3RyaW5nPgogIDxrZXk+ZGlnaXRhbC1jb3B5PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9kaWdpdGFsQ29weVdpemFyZDwvc3RyaW5nPgogIDxrZXk+cDItcmVkZW1wdGlvbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcDJSZWRlZW1Db2RlPC9zdHJpbmc+CiAgPGtleT5wMi1oZWFkbGVzcy1yZWRlbXB0aW9uPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9wMkhlYWRsZXNzUmVkZWVtQ29kZTwvc3RyaW5nPgogIDxrZXk+cDItcmVkZWVtLXNlcnZpY2UtdGVybXMtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vd3d3LmFwcGxlLmNvbS9sZWdhbC9pdHVuZXMvd3cvPC9zdHJpbmc+CiAgPGtleT5wZW5kaW5nQXBwczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcGVuZGluZ0FwcHM8L3N0cmluZz4KICA8a2V5PmNoZWNrQXBwUXVldWU8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NoZWNrQXBwRG93bmxvYWRRdWV1ZTwvc3RyaW5nPgogIDxrZXk+bWFya2V0aW5nLWFjdGlvbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evdmlld01hcmtldGluZ1BhZ2U8L3N0cmluZz4KICA8a2V5Pm1hcmtldGluZy1hY3Rpb24tMjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9zZWN1cmUubWUuY29tL2l0dW5lc3NpZ251cDwvc3RyaW5nPgogIDxrZXk+Z2lmdFBsYXlsaXN0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9naWZ0U29uZ3NXaXphcmQ8L3N0cmluZz4KICA8a2V5PmdpdmUtcGxheWxpc3Q8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2dpZnRTb25nc1dpemFyZDwvc3RyaW5nPgogIDxrZXk+bmV3VG91Y2hVc2VyPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS90b3VjaExhbmRpbmdQYWdlP2lzRGV2aWNlU2VsZWN0ZWQ9dHJ1ZTwvc3RyaW5nPgogIDxrZXk+cmVudGFsLWNoZWNraW48L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NoZWNraW5SZW50YWw8L3N0cmluZz4KICA8a2V5PnJlbnRhbC1hY2stY2hlY2tpbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvY2hlY2tpbkFja1JlbnRhbDwvc3RyaW5nPgogIDxrZXk+cmVudGFsLWNoZWNrb3V0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jaGVja291dFJlbnRhbDwvc3RyaW5nPgogIDxrZXk+Z2V0LW5pa2l0YS1kcGluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2lQb2RUcmFuc2Zlcjwvc3RyaW5nPgogIDxrZXk+YXBwLXJlY2VpcHQtY3JlYXRlPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jcmVhdGVBcHBSZWNlaXB0PC9zdHJpbmc+CiAgPGtleT5jcmVhdGUtcmluZ3RvbmU8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NyZWF0ZVJpbmd0b25lPC9zdHJpbmc+CiAgPGtleT5yaW5ndG9uZS1pbmZvPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9pc1Jpbmd0b25lYWJsZTwvc3RyaW5nPgogIDxrZXk+cDItY29uY2Vybi1saXN0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9wMkdldFJlcG9ydEFDb25jZXJuTGlzdDwvc3RyaW5nPgogIDxrZXk+cDItcmVwb3J0LWNvbmNlcm48L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3AyUmVwb3J0QVByb2JsZW08L3N0cmluZz4KICA8a2V5Pmdlbml1cy13ZWxjb21lPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS91c2VyQ29sbGVjdGlvbnNXZWxjb21lPC9zdHJpbmc+CiAgPGtleT5wMi1jaGVjay1wcmUtb3JkZXItcXVldWU8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2dldFByZW9yZGVyUXVldWVDb3VudDwvc3RyaW5nPgogIDxrZXk+cDItcHJlLW9yZGVyLXF1ZXVlPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9nZXRQcmVvcmRlclF1ZXVlPC9zdHJpbmc+CiAgPGtleT5wMi1vcmRlci1wcmUtb3JkZXI8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL29yZGVyUHJlb3JkZXI8L3N0cmluZz4KICA8a2V5PnAyLWNhbmNlbC1wcmUtb3JkZXI8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NhbmNlbFByZW9yZGVyPC9zdHJpbmc+CiAgPGtleT5wMi1wcm9kdWN0LW9mZmVyPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9vZmZlckF2YWlsYWJpbGl0eUFuZEluZm9EaWFsb2c8L3N0cmluZz4KICA8a2V5PnAyLWluLWFwcC1idXk8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkJ1eS53b2Evd2EvaW5BcHBCdXk8L3N0cmluZz4KICA8a2V5PnAyLWluLWFwcC1jaGVjay1kb3dubG9hZC1xdWV1ZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaW5BcHBDaGVja0Rvd25sb2FkUXVldWU8L3N0cmluZz4KICA8a2V5PnAyLWluLWFwcC1wZW5kaW5nLXRyYW5zYWN0aW9uczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaW5BcHBQZW5kaW5nVHJhbnNhY3Rpb25zPC9zdHJpbmc+CiAgPGtleT5wMi1pbi1hcHAtY2hlY2stcmVjdXJyaW5nLWRvd25sb2FkLXF1ZXVlPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9pbkFwcENoZWNrUmVjdXJyaW5nRG93bmxvYWRRdWV1ZTwvc3RyaW5nPgogIDxrZXk+cDItaW4tYXBwLXJlY3VycmluZy10cmFuc2FjdGlvbnM8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2luQXBwUmVjdXJyaW5nVHJhbnNhY3Rpb25zPC9zdHJpbmc+CiAgPGtleT5wMi1pbi1hcHAtdHJhbnNhY3Rpb24tZG9uZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaW5BcHBUcmFuc2FjdGlvbkRvbmU8L3N0cmluZz4KICA8a2V5PnAyLWluLWFwcC1yZWdyYW50LXB1cmNoYXNlLWhpc3Rvcnk8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2luQXBwUmVncmFudFB1cmNoYXNlSGlzdG9yeTwvc3RyaW5nPgogIDxrZXk+Z2V0U2hhcmVJZGVudGlmaWVyczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aSG9tZVNoYXJpbmcud29hL3dhL2dldFNoYXJlSWRlbnRpZmllcnM8L3N0cmluZz4KICA8a2V5PmFwcHJvdmVDb250ZW50VHJhbnNmZXI8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkhvbWVTaGFyaW5nLndvYS93YS9hcHByb3ZlQ29udGVudFRyYW5zZmVyPC9zdHJpbmc+CiAgPGtleT5wZW5kaW5nQm9va3M8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3BlbmRpbmdCb29rczwvc3RyaW5nPgogIDxrZXk+Y2hlY2tCb29rUXVldWU8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NoZWNrRUJvb2tEb3dubG9hZFF1ZXVlPC9zdHJpbmc+CiAgPGtleT5rdnMtZ2V0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpCb29ra2VlcGVyLndvYS93YS9nZXQ8L3N0cmluZz4KICA8a2V5Pmt2cy1nZXRhbGw8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkJvb2trZWVwZXIud29hL3dhL2dldEFsbDwvc3RyaW5nPgogIDxrZXk+a3ZzLXB1dDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aQm9va2tlZXBlci53b2Evd2EvcHV0PC9zdHJpbmc+CiAgPGtleT5rdnMtcHV0YWxsPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpCb29ra2VlcGVyLndvYS93YS9wdXRBbGw8L3N0cmluZz4KICA8a2V5PmdldC1wbGF5LWluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2dldFBsYXlJbmZvPC9zdHJpbmc+CiAgPGtleT5wdXNoLW5vdGlmaWNhdGlvbnM8L2tleT4KICA8ZGljdD4KICAgIDxrZXk+cmVnaXN0ZXItc3VjY2Vzczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVnaXN0ZXJTdWNjZXNzPC9zdHJpbmc+CiAgICA8a2V5PmVudmlyb25tZW50PC9rZXk+PHN0cmluZz5wcm9kdWN0aW9uPC9zdHJpbmc+CiAgPC9kaWN0PgogIDxrZXk+YXV0b21hdGljLWRvd25sb2FkczI8L2tleT4KICA8ZGljdD4KICAgIDxrZXk+ZG93bmxvYWRzLXVybDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvZ2V0QXV0b0Rvd25sb2FkUXVldWU8L3N0cmluZz4KICAgIDxrZXk+cmVnaXN0ZXItbWVkaWEtdHlwZXM8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3JlZ2lzdGVyTWVkaWFUeXBlczwvc3RyaW5nPgogICAgPGtleT5jb25maWd1cmF0aW9uczwva2V5PgogICAgPGFycmF5PgogICAgICA8ZGljdD4KICAgICAgICA8a2V5Pm1lZGlhLXR5cGVzPC9rZXk+CiAgICAgICAgPGFycmF5PgogICAgICAgICAgPHN0cmluZz5zb25nPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPm11c2ljLXZpZGVvPC9zdHJpbmc+CiAgICAgICAgPC9hcnJheT4KICAgICAgICA8a2V5PmNhbm9uaWNhbC1uYW1lPC9rZXk+PHN0cmluZz5BVVRPX0RPV05MT0FEX01VU0lDPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgICAgPGRpY3Q+CiAgICAgICAgPGtleT5tZWRpYS10eXBlczwva2V5PgogICAgICAgIDxhcnJheT4KICAgICAgICAgIDxzdHJpbmc+c29mdHdhcmU8L3N0cmluZz4KICAgICAgICA8L2FycmF5PgogICAgICAgIDxrZXk+Y2Fub25pY2FsLW5hbWU8L2tleT48c3RyaW5nPkFVVE9fRE9XTkxPQURfQVBQUzwvc3RyaW5nPgogICAgICA8L2RpY3Q+CiAgICAgIDxkaWN0PgogICAgICAgIDxrZXk+bWVkaWEtdHlwZXM8L2tleT4KICAgICAgICA8YXJyYXk+CiAgICAgICAgICA8c3RyaW5nPmVib29rPC9zdHJpbmc+CiAgICAgICAgPC9hcnJheT4KICAgICAgICA8a2V5PmNhbm9uaWNhbC1uYW1lPC9rZXk+PHN0cmluZz5BVVRPX0RPV05MT0FEX0JPT0tTPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgIDwvYXJyYXk+CiAgPC9kaWN0PgogIDxrZXk+ZW5hYmxlZC1tZWRpYS10eXBlczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvZW5hYmxlZE1lZGlhVHlwZXM8L3N0cmluZz4KICA8a2V5PnAyLWNvbnRlbnQtcmVzdG9yZTwva2V5PgogIDxkaWN0PgogICAgPGtleT5nemlwPC9rZXk+PGZhbHNlLz4KICAgIDxrZXk+bWF4LWl0ZW0tY291bnQ8L2tleT48aW50ZWdlcj41MDwvaW50ZWdlcj4KICAgIDxrZXk+dXJsPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jb250ZW50UmVzdG9yZTwvc3RyaW5nPgogICAgPGtleT5hbGxvd2VkLWtpbmRzPC9rZXk+CiAgICA8YXJyYXk+CiAgICAgIDxzdHJpbmc+c29uZzwvc3RyaW5nPgogICAgICA8c3RyaW5nPm11c2ljLXZpZGVvPC9zdHJpbmc+CiAgICAgIDxzdHJpbmc+c29mdHdhcmU8L3N0cmluZz4KICAgICAgPHN0cmluZz5lYm9vazwvc3RyaW5nPgogICAgPC9hcnJheT4KICA8L2RpY3Q+CiAgPGtleT5wcmVmbGlnaHQtbG9va3VwPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9nZXRQcmVmbGlnaHQ8L3N0cmluZz4KICA8a2V5PmJ1bmRsZS1vd25zLWNoZWNrPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9vd25zQ2hlY2s8L3N0cmluZz4KICA8a2V5PnJlY292ZXJ5LWJ1eTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVjb3ZlcnlCdXk8L3N0cmluZz4KICA8a2V5PmFkb3B0LXByb2R1Y3Q8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2Fkb3B0UHJvZHVjdDwvc3RyaW5nPgo8L2RpY3Q+CjwvcGxpc3Q+Cg==" -"" -"" -; - -/* Test basic add delete update copy matching stuff. */ -static void tests(void) -{ - SecTrustRef trust; - SecCertificateRef leaf, root; - SecPolicyRef policy; - CFDataRef urlBagData; - CFDictionaryRef urlBagDict; - - isnt(urlBagData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, url_bag, sizeof(url_bag), kCFAllocatorNull), NULL, - "load url bag"); - isnt(urlBagDict = CFPropertyListCreateWithData(kCFAllocatorDefault, urlBagData, kCFPropertyListImmutable, NULL, NULL), NULL, - "parse url bag"); - CFReleaseSafe(urlBagData); - CFArrayRef certs_data = CFDictionaryGetValue(urlBagDict, CFSTR("certs")); - CFDataRef cert_data = CFArrayGetValueAtIndex(certs_data, 0); - isnt(leaf = SecCertificateCreateWithData(kCFAllocatorDefault, cert_data), NULL, "create leaf"); - isnt(root = SecCertificateCreateWithBytes(kCFAllocatorDefault, sITunesStoreRootCertificate, sizeof(sITunesStoreRootCertificate)), NULL, "create root"); - - CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **)&leaf, 1, NULL); - CFArrayRef anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&root, 1, NULL); - CFDataRef signature = CFDictionaryGetValue(urlBagDict, CFSTR("signature")); - CFDataRef bag = CFDictionaryGetValue(urlBagDict, CFSTR("bag")); - unsigned char sha1_hash[CC_SHA1_DIGEST_LENGTH]; - CFDataRef sha1Data = NULL; - CCDigest(kCCDigestSHA1, CFDataGetBytePtr(bag), CFDataGetLength(bag), sha1_hash); - sha1Data = CFDataCreate(NULL, sha1_hash, sizeof(sha1_hash)); - - isnt(policy = SecPolicyCreateiTunesStoreURLBag(), NULL, "create policy instance"); - - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for leaf"); - ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set iTMS anchor for evaluation"); - - /* it'll have just expired */ - CFDateRef date = CFDateCreateForGregorianZuluMoment(NULL, 2008, 11, 7, 22, 0, 0); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - CFReleaseSafe(date); - - SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - is(SecTrustGetCertificateCount(trust), 2, "cert count is 2"); - SecKeyRef pub_key_leaf; - isnt(pub_key_leaf = SecTrustCopyPublicKey(trust), NULL, "get leaf pub key"); - if (!pub_key_leaf) { goto errOut; } - CFErrorRef error = NULL; - ok(SecKeyVerifySignature(pub_key_leaf, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, sha1Data, signature, &error), - "verify signature on bag"); - CFReleaseNull(error); - -errOut: - CFReleaseSafe(sha1Data); - CFReleaseSafe(pub_key_leaf); - CFReleaseSafe(urlBagDict); - CFReleaseSafe(certs); - CFReleaseSafe(anchors); - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(leaf); - CFReleaseSafe(root); -} - -int si_24_sectrust_itms(int argc, char *const *argv) -{ - plan_tests(13); - - - tests(); -#ifdef NO_SERVER -# if NDEBUG -# else -# endif -#else -#endif - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-passbook.c b/OSX/sec/Security/Regressions/secitem/si-24-sectrust-passbook.c deleted file mode 100644 index b0d361ba..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-passbook.c +++ /dev/null @@ -1,709 +0,0 @@ -/* - * Copyright (c) 2011-2015 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "shared_regressions.h" - -static const unsigned char _USAirwaysCorrect_signature[] = { - 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, - 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x80, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00, 0x00, - 0xa0, 0x82, 0x0a, 0x1c, 0x30, 0x82, 0x04, 0x23, 0x30, 0x82, 0x03, 0x0b, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x19, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, - 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, - 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x32, 0x31, - 0x34, 0x31, 0x38, 0x35, 0x36, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x36, - 0x30, 0x32, 0x31, 0x34, 0x31, 0x38, 0x35, 0x36, 0x33, 0x35, 0x5a, 0x30, - 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, - 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x23, 0x41, - 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, - 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, - 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x31, 0x44, - 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, 0x41, 0x70, 0x70, - 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, 0x64, 0x65, - 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x20, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, - 0x02, 0x82, 0x01, 0x01, 0x00, 0xca, 0x38, 0x54, 0xa6, 0xcb, 0x56, 0xaa, - 0xc8, 0x24, 0x39, 0x48, 0xe9, 0x8c, 0xee, 0xec, 0x5f, 0xb8, 0x7f, 0x26, - 0x91, 0xbc, 0x34, 0x53, 0x7a, 0xce, 0x7c, 0x63, 0x80, 0x61, 0x77, 0x64, - 0x5e, 0xa5, 0x07, 0x23, 0xb6, 0x39, 0xfe, 0x50, 0x2d, 0x15, 0x56, 0x58, - 0x70, 0x2d, 0x7e, 0xc4, 0x6e, 0xc1, 0x4a, 0x85, 0x3e, 0x2f, 0xf0, 0xde, - 0x84, 0x1a, 0xa1, 0x57, 0xc9, 0xaf, 0x7b, 0x18, 0xff, 0x6a, 0xfa, 0x15, - 0x12, 0x49, 0x15, 0x08, 0x19, 0xac, 0xaa, 0xdb, 0x2a, 0x32, 0xed, 0x96, - 0x63, 0x68, 0x52, 0x15, 0x3d, 0x8c, 0x8a, 0xec, 0xbf, 0x6b, 0x18, 0x95, - 0xe0, 0x03, 0xac, 0x01, 0x7d, 0x97, 0x05, 0x67, 0xce, 0x0e, 0x85, 0x95, - 0x37, 0x6a, 0xed, 0x09, 0xb6, 0xae, 0x67, 0xcd, 0x51, 0x64, 0x9f, 0xc6, - 0x5c, 0xd1, 0xbc, 0x57, 0x6e, 0x67, 0x35, 0x80, 0x76, 0x36, 0xa4, 0x87, - 0x81, 0x6e, 0x38, 0x8f, 0xd8, 0x2b, 0x15, 0x4e, 0x7b, 0x25, 0xd8, 0x5a, - 0xbf, 0x4e, 0x83, 0xc1, 0x8d, 0xd2, 0x93, 0xd5, 0x1a, 0x71, 0xb5, 0x60, - 0x9c, 0x9d, 0x33, 0x4e, 0x55, 0xf9, 0x12, 0x58, 0x0c, 0x86, 0xb8, 0x16, - 0x0d, 0xc1, 0xe5, 0x77, 0x45, 0x8d, 0x50, 0x48, 0xba, 0x2b, 0x2d, 0xe4, - 0x94, 0x85, 0xe1, 0xe8, 0xc4, 0x9d, 0xc6, 0x68, 0xa5, 0xb0, 0xa3, 0xfc, - 0x67, 0x7e, 0x70, 0xba, 0x02, 0x59, 0x4b, 0x77, 0x42, 0x91, 0x39, 0xb9, - 0xf5, 0xcd, 0xe1, 0x4c, 0xef, 0xc0, 0x3b, 0x48, 0x8c, 0xa6, 0xe5, 0x21, - 0x5d, 0xfd, 0x6a, 0x6a, 0xbb, 0xa7, 0x16, 0x35, 0x60, 0xd2, 0xe6, 0xad, - 0xf3, 0x46, 0x29, 0xc9, 0xe8, 0xc3, 0x8b, 0xe9, 0x79, 0xc0, 0x6a, 0x61, - 0x67, 0x15, 0xb2, 0xf0, 0xfd, 0xe5, 0x68, 0xbc, 0x62, 0x5f, 0x6e, 0xcf, - 0x99, 0xdd, 0xef, 0x1b, 0x63, 0xfe, 0x92, 0x65, 0xab, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x81, 0xae, 0x30, 0x81, 0xab, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0x88, 0x27, 0x17, 0x09, 0xa9, 0xb6, 0x18, 0x60, - 0x8b, 0xec, 0xeb, 0xba, 0xf6, 0x47, 0x59, 0xc5, 0x52, 0x54, 0xa3, 0xb7, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, - 0x14, 0x2b, 0xd0, 0x69, 0x47, 0x94, 0x76, 0x09, 0xfe, 0xf4, 0x6b, 0x8d, - 0x2e, 0x40, 0xa6, 0xf7, 0x47, 0x4d, 0x7f, 0x08, 0x5e, 0x30, 0x36, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, - 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, - 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x72, 0x6f, 0x6f, - 0x74, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x63, 0x64, 0x06, 0x02, 0x01, 0x04, 0x02, 0x05, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xda, 0x32, 0x00, 0x96, 0xc5, - 0x54, 0x94, 0xd3, 0x3b, 0x82, 0x37, 0x66, 0x7d, 0x2e, 0x68, 0xd5, 0xc3, - 0xc6, 0xb8, 0xcb, 0x26, 0x8c, 0x48, 0x90, 0xcf, 0x13, 0x24, 0x6a, 0x46, - 0x8e, 0x63, 0xd4, 0xf0, 0xd0, 0x13, 0x06, 0xdd, 0xd8, 0xc4, 0xc1, 0x37, - 0x15, 0xf2, 0x33, 0x13, 0x39, 0x26, 0x2d, 0xce, 0x2e, 0x55, 0x40, 0xe3, - 0x0b, 0x03, 0xaf, 0xfa, 0x12, 0xc2, 0xe7, 0x0d, 0x21, 0xb8, 0xd5, 0x80, - 0xcf, 0xac, 0x28, 0x2f, 0xce, 0x2d, 0xb3, 0x4e, 0xaf, 0x86, 0x19, 0x04, - 0xc6, 0xe9, 0x50, 0xdd, 0x4c, 0x29, 0x47, 0x10, 0x23, 0xfc, 0x6c, 0xbb, - 0x1b, 0x98, 0x6b, 0x48, 0x89, 0xe1, 0x5b, 0x9d, 0xde, 0x46, 0xdb, 0x35, - 0x85, 0x35, 0xef, 0x3e, 0xd0, 0xe2, 0x58, 0x4b, 0x38, 0xf4, 0xed, 0x75, - 0x5a, 0x1f, 0x5c, 0x70, 0x1d, 0x56, 0x39, 0x12, 0xe5, 0xe1, 0x0d, 0x11, - 0xe4, 0x89, 0x25, 0x06, 0xbd, 0xd5, 0xb4, 0x15, 0x8e, 0x5e, 0xd0, 0x59, - 0x97, 0x90, 0xe9, 0x4b, 0x81, 0xe2, 0xdf, 0x18, 0xaf, 0x44, 0x74, 0x1e, - 0x19, 0xa0, 0x3a, 0x47, 0xcc, 0x91, 0x1d, 0x3a, 0xeb, 0x23, 0x5a, 0xfe, - 0xa5, 0x2d, 0x97, 0xf7, 0x7b, 0xbb, 0xd6, 0x87, 0x46, 0x42, 0x85, 0xeb, - 0x52, 0x3d, 0x26, 0xb2, 0x63, 0xa8, 0xb4, 0xb1, 0xca, 0x8f, 0xf4, 0xcc, - 0xe2, 0xb3, 0xc8, 0x47, 0xe0, 0xbf, 0x9a, 0x59, 0x83, 0xfa, 0xda, 0x98, - 0x53, 0x2a, 0x82, 0xf5, 0x7c, 0x65, 0x2e, 0x95, 0xd9, 0x33, 0x5d, 0xf5, - 0xed, 0x65, 0xcc, 0x31, 0x37, 0xc5, 0x5a, 0x04, 0xe8, 0x6b, 0xe1, 0xe7, - 0x88, 0x03, 0x4a, 0x75, 0x9e, 0x9b, 0x28, 0xcb, 0x4a, 0x40, 0x88, 0x65, - 0x43, 0x75, 0xdd, 0xcb, 0x3a, 0x25, 0x23, 0xc5, 0x9e, 0x57, 0xf8, 0x2e, - 0xce, 0xd2, 0xa9, 0x92, 0x5e, 0x73, 0x2e, 0x2f, 0x25, 0x75, 0x15, 0x30, - 0x82, 0x05, 0xf1, 0x30, 0x82, 0x04, 0xd9, 0xa0, 0x03, 0x02, 0x01, 0x02, - 0x02, 0x08, 0x29, 0xd6, 0x12, 0x53, 0x17, 0x20, 0x2d, 0x6a, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, - 0x63, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, - 0x23, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, - 0x77, 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, - 0x65, 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, 0x41, - 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, - 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, - 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, - 0x17, 0x0d, 0x31, 0x32, 0x30, 0x35, 0x33, 0x30, 0x32, 0x33, 0x32, 0x30, - 0x31, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x35, 0x33, 0x30, 0x32, - 0x33, 0x32, 0x30, 0x31, 0x30, 0x5a, 0x30, 0x81, 0x9b, 0x31, 0x26, 0x30, - 0x24, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, - 0x01, 0x0c, 0x16, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, - 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, - 0x6e, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x24, - 0x50, 0x61, 0x73, 0x73, 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, 0x49, 0x44, - 0x3a, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, - 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, 0x6e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0a, 0x41, - 0x31, 0x42, 0x32, 0x43, 0x33, 0x44, 0x34, 0x45, 0x35, 0x31, 0x20, 0x30, - 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x17, 0x41, 0x70, 0x70, 0x6c, - 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x55, - 0x73, 0x65, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, - 0x02, 0x82, 0x01, 0x01, 0x00, 0xbb, 0x6c, 0x6c, 0xd4, 0xcd, 0x0b, 0xd9, - 0x47, 0x49, 0xe1, 0xa3, 0xfe, 0x73, 0xe0, 0x15, 0xa6, 0x2e, 0x35, 0xc8, - 0xb7, 0xcd, 0xab, 0x5e, 0xd3, 0x87, 0x8a, 0x94, 0x8f, 0x4d, 0x94, 0x52, - 0x72, 0x27, 0x57, 0xb8, 0xf5, 0xa8, 0xe2, 0xf2, 0xb0, 0x46, 0xad, 0xb9, - 0x30, 0x9b, 0x6a, 0xd7, 0x0a, 0xff, 0x0e, 0x5e, 0x78, 0x4c, 0x97, 0x17, - 0x16, 0xa7, 0x03, 0xe1, 0x13, 0xe7, 0x97, 0x72, 0x24, 0xc8, 0x7f, 0x80, - 0x91, 0xd2, 0x45, 0xa3, 0xf8, 0x21, 0xce, 0x2d, 0xfa, 0xe4, 0x3a, 0x5e, - 0x04, 0x30, 0xe9, 0x48, 0xca, 0x32, 0xce, 0x52, 0x4c, 0xcf, 0x14, 0xf9, - 0x04, 0x58, 0x30, 0x4a, 0xf8, 0x49, 0xbb, 0x39, 0x18, 0x5c, 0x4b, 0x28, - 0x9e, 0x14, 0x16, 0x23, 0x73, 0x6e, 0x0d, 0xcd, 0xcd, 0xef, 0x98, 0xe7, - 0x90, 0x04, 0x0e, 0x4a, 0xc8, 0x16, 0x22, 0x76, 0x68, 0xc6, 0xdf, 0x5d, - 0x20, 0xa7, 0x49, 0x2e, 0x55, 0x9e, 0x50, 0x31, 0x56, 0x50, 0x29, 0xf9, - 0x56, 0x09, 0x38, 0x32, 0x25, 0x1b, 0x3a, 0x1c, 0x97, 0x3e, 0x04, 0xee, - 0x69, 0x3c, 0x68, 0x44, 0x54, 0x51, 0x27, 0x75, 0x70, 0xa2, 0x33, 0x86, - 0x7a, 0x9d, 0x71, 0xc0, 0x18, 0x2e, 0x37, 0xb5, 0x47, 0x8d, 0xbe, 0x57, - 0xb6, 0xaa, 0xda, 0x1d, 0xe8, 0x78, 0x23, 0x66, 0xc8, 0x6c, 0xe3, 0x7e, - 0xfd, 0xde, 0x6b, 0x70, 0x2f, 0x76, 0x1d, 0xa6, 0x2b, 0x97, 0xee, 0xad, - 0x5b, 0x8b, 0x8e, 0x00, 0x87, 0x27, 0xdf, 0x16, 0x54, 0x08, 0x97, 0x18, - 0x23, 0x31, 0x2c, 0xf5, 0x9d, 0x41, 0xd5, 0xbb, 0x60, 0x23, 0x92, 0x3d, - 0xcc, 0x9e, 0x2d, 0xff, 0xa5, 0x8b, 0xe0, 0xf9, 0x65, 0xdc, 0x94, 0x58, - 0xb0, 0x9d, 0x73, 0x05, 0x05, 0x21, 0xa1, 0xb3, 0x37, 0xa4, 0x8f, 0x5d, - 0xda, 0xce, 0x9c, 0xf6, 0x63, 0x9b, 0x6b, 0x9f, 0x77, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3a, 0x30, 0x82, 0x02, 0x36, 0x30, 0x3d, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x31, - 0x30, 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x30, 0x01, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, - 0x63, 0x73, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2d, 0x77, 0x77, 0x64, 0x72, 0x30, - 0x33, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x9b, 0xc2, 0x61, 0x59, 0x72, 0x23, 0xb6, 0x5f, 0x91, 0x0f, 0x04, 0x87, - 0x92, 0xf9, 0xa4, 0xf3, 0x6b, 0xe9, 0xbe, 0xab, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x88, 0x27, 0x17, 0x09, - 0xa9, 0xb6, 0x18, 0x60, 0x8b, 0xec, 0xeb, 0xba, 0xf6, 0x47, 0x59, 0xc5, - 0x52, 0x54, 0xa3, 0xb7, 0x30, 0x82, 0x01, 0x0f, 0x06, 0x03, 0x55, 0x1d, - 0x20, 0x04, 0x82, 0x01, 0x06, 0x30, 0x82, 0x01, 0x02, 0x30, 0x81, 0xff, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, - 0x81, 0xf1, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, - 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x30, 0x81, 0xc3, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x81, - 0xb6, 0x0c, 0x81, 0xb3, 0x52, 0x65, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, - 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x62, 0x79, 0x20, - 0x61, 0x6e, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x79, 0x20, 0x61, 0x73, - 0x73, 0x75, 0x6d, 0x65, 0x73, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x74, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x62, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, - 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, - 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, - 0x20, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, - 0x69, 0x63, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x2e, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x29, - 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x61, 0x70, 0x70, - 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x77, 0x64, 0x72, 0x63, - 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, - 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x1d, - 0x25, 0x04, 0x17, 0x30, 0x15, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, - 0x04, 0x0e, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, - 0x64, 0x06, 0x03, 0x02, 0x04, 0x02, 0x05, 0x00, 0x30, 0x26, 0x06, 0x0a, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, 0x01, 0x10, 0x04, 0x18, - 0x0c, 0x16, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, - 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, 0x6e, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x9b, 0xef, 0x1e, 0xff, - 0xee, 0xd5, 0xfd, 0x71, 0x1a, 0xf5, 0x17, 0xfe, 0x05, 0xba, 0x30, 0xfc, - 0xbd, 0x6d, 0x01, 0xb0, 0x0b, 0x78, 0x41, 0x4b, 0x76, 0x71, 0xd1, 0x8c, - 0xf0, 0xcd, 0xed, 0xd9, 0xaa, 0xec, 0xad, 0x1d, 0x4a, 0x2d, 0xcc, 0x00, - 0x11, 0x5b, 0x1d, 0xd9, 0xef, 0x08, 0xa2, 0x3d, 0xea, 0xe9, 0xbd, 0x35, - 0x0b, 0x1c, 0x9f, 0xe7, 0xeb, 0xc9, 0xc9, 0xea, 0x99, 0xcc, 0x77, 0x27, - 0xb9, 0x01, 0x09, 0x72, 0x40, 0xba, 0xd4, 0x26, 0x54, 0x8f, 0x30, 0x84, - 0x7e, 0x03, 0x65, 0xda, 0x08, 0xb2, 0x92, 0xee, 0x61, 0x4e, 0x5f, 0x00, - 0x39, 0x48, 0x2d, 0x99, 0x83, 0xb5, 0xc4, 0x33, 0xb2, 0xf7, 0x62, 0xcf, - 0x6a, 0xbf, 0xbb, 0xb8, 0x40, 0x70, 0xbf, 0x11, 0xff, 0x7f, 0xc1, 0xc1, - 0x8d, 0x1d, 0x67, 0x6c, 0x87, 0x02, 0xe2, 0x93, 0x17, 0x16, 0xc3, 0xec, - 0x5e, 0x97, 0xe4, 0xdd, 0x12, 0xcc, 0xb2, 0xdd, 0x91, 0x51, 0xa8, 0x32, - 0x25, 0x6d, 0xf7, 0x55, 0xb7, 0x4a, 0x8e, 0x6b, 0x90, 0xcb, 0x0f, 0x4c, - 0x93, 0x87, 0x2a, 0xd9, 0x31, 0xb8, 0x1a, 0x16, 0x12, 0xbb, 0x6e, 0xfc, - 0xb0, 0xae, 0xfb, 0x93, 0x76, 0x63, 0x37, 0xb7, 0x36, 0x13, 0x11, 0xc5, - 0x53, 0x45, 0xe0, 0x0d, 0xff, 0xaf, 0x05, 0x5f, 0x67, 0x51, 0xe1, 0x54, - 0x29, 0xa2, 0x1a, 0x7c, 0x61, 0xe0, 0xc2, 0xcd, 0xac, 0xbe, 0xee, 0xa6, - 0x4a, 0xdc, 0x92, 0x95, 0x48, 0x41, 0x2f, 0x37, 0xc0, 0x64, 0x05, 0xaa, - 0x4f, 0x05, 0xee, 0xe0, 0x3f, 0xa0, 0x9f, 0x43, 0x6c, 0xcc, 0xd5, 0x97, - 0x64, 0x6d, 0x15, 0x5b, 0xb6, 0xcd, 0x2a, 0xbc, 0x18, 0xde, 0xc7, 0x94, - 0x80, 0x2d, 0x2b, 0x81, 0x14, 0xfc, 0x48, 0xf7, 0xdf, 0xce, 0x94, 0xb3, - 0xfd, 0xf5, 0x7e, 0x42, 0x4d, 0x33, 0x58, 0x4d, 0x7a, 0x62, 0x2e, 0x61, - 0x31, 0x82, 0x02, 0x2a, 0x30, 0x82, 0x02, 0x26, 0x02, 0x01, 0x01, 0x30, - 0x81, 0xa3, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x0c, 0x23, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, - 0x64, 0x77, 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, - 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x02, - 0x08, 0x29, 0xd6, 0x12, 0x53, 0x17, 0x20, 0x2d, 0x6a, 0x30, 0x09, 0x06, - 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0xa0, 0x5d, 0x30, 0x18, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, - 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, - 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, - 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37, 0x32, - 0x31, 0x32, 0x31, 0x35, 0x30, 0x5a, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0x97, - 0xab, 0x93, 0x47, 0x94, 0xc1, 0xdf, 0x9b, 0xf4, 0x8e, 0xf9, 0xec, 0x96, - 0x77, 0xf9, 0x35, 0x15, 0xe1, 0x75, 0x58, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x01, 0x00, 0x33, 0xdd, 0xcb, 0xf1, 0xa1, 0x74, 0xc2, 0xad, 0x44, 0xcd, - 0x49, 0x95, 0xad, 0xd4, 0xd5, 0xaf, 0x37, 0x98, 0x5e, 0x1b, 0x0e, 0xf7, - 0x49, 0xc5, 0x3a, 0x01, 0x99, 0x7e, 0xc2, 0x3b, 0x4f, 0x37, 0xd0, 0x8e, - 0x31, 0x7f, 0xcd, 0x7d, 0x9f, 0xfd, 0xb9, 0x6a, 0x8e, 0x43, 0xcf, 0xc0, - 0x94, 0xda, 0x2b, 0x1b, 0x98, 0x28, 0x0a, 0x34, 0x39, 0x1c, 0x3d, 0xf1, - 0x86, 0xad, 0x02, 0x7e, 0xdb, 0x02, 0x9b, 0xfc, 0x4a, 0x2e, 0x10, 0x82, - 0x50, 0xfe, 0x61, 0x18, 0xc4, 0x6f, 0x45, 0x30, 0x66, 0x7a, 0x44, 0x70, - 0x0d, 0x4c, 0x47, 0x04, 0xb4, 0x09, 0x02, 0x12, 0xa8, 0x61, 0x3c, 0xf7, - 0x24, 0x7c, 0xb3, 0xa8, 0x5b, 0xde, 0xe4, 0xa4, 0x5d, 0x98, 0x9e, 0x72, - 0x0a, 0xea, 0x36, 0x5c, 0xfa, 0xe1, 0x80, 0xd6, 0x93, 0xa2, 0xbc, 0x09, - 0x9c, 0xd6, 0xf9, 0x05, 0x53, 0x88, 0xe5, 0x24, 0x9f, 0x8f, 0x5e, 0x2f, - 0xfd, 0x2c, 0x9c, 0xd6, 0x69, 0xad, 0x22, 0x54, 0xa7, 0xc5, 0x27, 0x2f, - 0x35, 0x77, 0xda, 0x0e, 0x49, 0xd0, 0x0a, 0x75, 0xaa, 0x5e, 0x6e, 0xad, - 0xe9, 0x20, 0xff, 0xf8, 0x5a, 0x40, 0x03, 0xe4, 0x36, 0xf1, 0x88, 0x1a, - 0xf3, 0x81, 0xc6, 0xd7, 0x70, 0xc8, 0xa9, 0xd2, 0x93, 0x51, 0x81, 0x49, - 0xf0, 0xe2, 0xef, 0xdb, 0xbd, 0x1a, 0x33, 0xf8, 0x2e, 0xa4, 0xb7, 0x21, - 0x14, 0x57, 0x98, 0x0e, 0xab, 0xbd, 0xa4, 0xd7, 0xec, 0xfc, 0x7a, 0x8d, - 0xdd, 0xcc, 0xec, 0x22, 0x13, 0x8d, 0xa9, 0x43, 0x68, 0xda, 0x5f, 0x78, - 0xe1, 0x21, 0xeb, 0xb1, 0x25, 0xb5, 0x4f, 0x99, 0x29, 0x7d, 0xf1, 0x9c, - 0x11, 0x2a, 0xa6, 0xdf, 0x9c, 0xd3, 0x33, 0xdb, 0xff, 0xb4, 0xcb, 0x40, - 0x77, 0x4d, 0xa5, 0x5c, 0x9b, 0x6f, 0x11, 0xad, 0x98, 0x17, 0x3b, 0xdd, - 0x16, 0xad, 0x5e, 0x4f, 0xcb, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const unsigned char _USAirwaysWrongTeamID_signature[] = { - 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, - 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x80, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00, 0x00, - 0xa0, 0x82, 0x0a, 0x1c, 0x30, 0x82, 0x04, 0x23, 0x30, 0x82, 0x03, 0x0b, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x19, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, - 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, - 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x32, 0x31, - 0x34, 0x31, 0x38, 0x35, 0x36, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x36, - 0x30, 0x32, 0x31, 0x34, 0x31, 0x38, 0x35, 0x36, 0x33, 0x35, 0x5a, 0x30, - 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, - 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x23, 0x41, - 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, - 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, - 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x31, 0x44, - 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, 0x41, 0x70, 0x70, - 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, 0x64, 0x65, - 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x20, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, - 0x02, 0x82, 0x01, 0x01, 0x00, 0xca, 0x38, 0x54, 0xa6, 0xcb, 0x56, 0xaa, - 0xc8, 0x24, 0x39, 0x48, 0xe9, 0x8c, 0xee, 0xec, 0x5f, 0xb8, 0x7f, 0x26, - 0x91, 0xbc, 0x34, 0x53, 0x7a, 0xce, 0x7c, 0x63, 0x80, 0x61, 0x77, 0x64, - 0x5e, 0xa5, 0x07, 0x23, 0xb6, 0x39, 0xfe, 0x50, 0x2d, 0x15, 0x56, 0x58, - 0x70, 0x2d, 0x7e, 0xc4, 0x6e, 0xc1, 0x4a, 0x85, 0x3e, 0x2f, 0xf0, 0xde, - 0x84, 0x1a, 0xa1, 0x57, 0xc9, 0xaf, 0x7b, 0x18, 0xff, 0x6a, 0xfa, 0x15, - 0x12, 0x49, 0x15, 0x08, 0x19, 0xac, 0xaa, 0xdb, 0x2a, 0x32, 0xed, 0x96, - 0x63, 0x68, 0x52, 0x15, 0x3d, 0x8c, 0x8a, 0xec, 0xbf, 0x6b, 0x18, 0x95, - 0xe0, 0x03, 0xac, 0x01, 0x7d, 0x97, 0x05, 0x67, 0xce, 0x0e, 0x85, 0x95, - 0x37, 0x6a, 0xed, 0x09, 0xb6, 0xae, 0x67, 0xcd, 0x51, 0x64, 0x9f, 0xc6, - 0x5c, 0xd1, 0xbc, 0x57, 0x6e, 0x67, 0x35, 0x80, 0x76, 0x36, 0xa4, 0x87, - 0x81, 0x6e, 0x38, 0x8f, 0xd8, 0x2b, 0x15, 0x4e, 0x7b, 0x25, 0xd8, 0x5a, - 0xbf, 0x4e, 0x83, 0xc1, 0x8d, 0xd2, 0x93, 0xd5, 0x1a, 0x71, 0xb5, 0x60, - 0x9c, 0x9d, 0x33, 0x4e, 0x55, 0xf9, 0x12, 0x58, 0x0c, 0x86, 0xb8, 0x16, - 0x0d, 0xc1, 0xe5, 0x77, 0x45, 0x8d, 0x50, 0x48, 0xba, 0x2b, 0x2d, 0xe4, - 0x94, 0x85, 0xe1, 0xe8, 0xc4, 0x9d, 0xc6, 0x68, 0xa5, 0xb0, 0xa3, 0xfc, - 0x67, 0x7e, 0x70, 0xba, 0x02, 0x59, 0x4b, 0x77, 0x42, 0x91, 0x39, 0xb9, - 0xf5, 0xcd, 0xe1, 0x4c, 0xef, 0xc0, 0x3b, 0x48, 0x8c, 0xa6, 0xe5, 0x21, - 0x5d, 0xfd, 0x6a, 0x6a, 0xbb, 0xa7, 0x16, 0x35, 0x60, 0xd2, 0xe6, 0xad, - 0xf3, 0x46, 0x29, 0xc9, 0xe8, 0xc3, 0x8b, 0xe9, 0x79, 0xc0, 0x6a, 0x61, - 0x67, 0x15, 0xb2, 0xf0, 0xfd, 0xe5, 0x68, 0xbc, 0x62, 0x5f, 0x6e, 0xcf, - 0x99, 0xdd, 0xef, 0x1b, 0x63, 0xfe, 0x92, 0x65, 0xab, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x81, 0xae, 0x30, 0x81, 0xab, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0x88, 0x27, 0x17, 0x09, 0xa9, 0xb6, 0x18, 0x60, - 0x8b, 0xec, 0xeb, 0xba, 0xf6, 0x47, 0x59, 0xc5, 0x52, 0x54, 0xa3, 0xb7, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, - 0x14, 0x2b, 0xd0, 0x69, 0x47, 0x94, 0x76, 0x09, 0xfe, 0xf4, 0x6b, 0x8d, - 0x2e, 0x40, 0xa6, 0xf7, 0x47, 0x4d, 0x7f, 0x08, 0x5e, 0x30, 0x36, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, - 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, - 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x72, 0x6f, 0x6f, - 0x74, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x63, 0x64, 0x06, 0x02, 0x01, 0x04, 0x02, 0x05, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xda, 0x32, 0x00, 0x96, 0xc5, - 0x54, 0x94, 0xd3, 0x3b, 0x82, 0x37, 0x66, 0x7d, 0x2e, 0x68, 0xd5, 0xc3, - 0xc6, 0xb8, 0xcb, 0x26, 0x8c, 0x48, 0x90, 0xcf, 0x13, 0x24, 0x6a, 0x46, - 0x8e, 0x63, 0xd4, 0xf0, 0xd0, 0x13, 0x06, 0xdd, 0xd8, 0xc4, 0xc1, 0x37, - 0x15, 0xf2, 0x33, 0x13, 0x39, 0x26, 0x2d, 0xce, 0x2e, 0x55, 0x40, 0xe3, - 0x0b, 0x03, 0xaf, 0xfa, 0x12, 0xc2, 0xe7, 0x0d, 0x21, 0xb8, 0xd5, 0x80, - 0xcf, 0xac, 0x28, 0x2f, 0xce, 0x2d, 0xb3, 0x4e, 0xaf, 0x86, 0x19, 0x04, - 0xc6, 0xe9, 0x50, 0xdd, 0x4c, 0x29, 0x47, 0x10, 0x23, 0xfc, 0x6c, 0xbb, - 0x1b, 0x98, 0x6b, 0x48, 0x89, 0xe1, 0x5b, 0x9d, 0xde, 0x46, 0xdb, 0x35, - 0x85, 0x35, 0xef, 0x3e, 0xd0, 0xe2, 0x58, 0x4b, 0x38, 0xf4, 0xed, 0x75, - 0x5a, 0x1f, 0x5c, 0x70, 0x1d, 0x56, 0x39, 0x12, 0xe5, 0xe1, 0x0d, 0x11, - 0xe4, 0x89, 0x25, 0x06, 0xbd, 0xd5, 0xb4, 0x15, 0x8e, 0x5e, 0xd0, 0x59, - 0x97, 0x90, 0xe9, 0x4b, 0x81, 0xe2, 0xdf, 0x18, 0xaf, 0x44, 0x74, 0x1e, - 0x19, 0xa0, 0x3a, 0x47, 0xcc, 0x91, 0x1d, 0x3a, 0xeb, 0x23, 0x5a, 0xfe, - 0xa5, 0x2d, 0x97, 0xf7, 0x7b, 0xbb, 0xd6, 0x87, 0x46, 0x42, 0x85, 0xeb, - 0x52, 0x3d, 0x26, 0xb2, 0x63, 0xa8, 0xb4, 0xb1, 0xca, 0x8f, 0xf4, 0xcc, - 0xe2, 0xb3, 0xc8, 0x47, 0xe0, 0xbf, 0x9a, 0x59, 0x83, 0xfa, 0xda, 0x98, - 0x53, 0x2a, 0x82, 0xf5, 0x7c, 0x65, 0x2e, 0x95, 0xd9, 0x33, 0x5d, 0xf5, - 0xed, 0x65, 0xcc, 0x31, 0x37, 0xc5, 0x5a, 0x04, 0xe8, 0x6b, 0xe1, 0xe7, - 0x88, 0x03, 0x4a, 0x75, 0x9e, 0x9b, 0x28, 0xcb, 0x4a, 0x40, 0x88, 0x65, - 0x43, 0x75, 0xdd, 0xcb, 0x3a, 0x25, 0x23, 0xc5, 0x9e, 0x57, 0xf8, 0x2e, - 0xce, 0xd2, 0xa9, 0x92, 0x5e, 0x73, 0x2e, 0x2f, 0x25, 0x75, 0x15, 0x30, - 0x82, 0x05, 0xf1, 0x30, 0x82, 0x04, 0xd9, 0xa0, 0x03, 0x02, 0x01, 0x02, - 0x02, 0x08, 0x29, 0xd6, 0x12, 0x53, 0x17, 0x20, 0x2d, 0x6a, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, - 0x63, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, - 0x23, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, - 0x77, 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, - 0x65, 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, 0x41, - 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, - 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, - 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, - 0x17, 0x0d, 0x31, 0x32, 0x30, 0x35, 0x33, 0x30, 0x32, 0x33, 0x32, 0x30, - 0x31, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x35, 0x33, 0x30, 0x32, - 0x33, 0x32, 0x30, 0x31, 0x30, 0x5a, 0x30, 0x81, 0x9b, 0x31, 0x26, 0x30, - 0x24, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, - 0x01, 0x0c, 0x16, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, - 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, - 0x6e, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x24, - 0x50, 0x61, 0x73, 0x73, 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, 0x49, 0x44, - 0x3a, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, - 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, 0x6e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0a, 0x41, - 0x31, 0x42, 0x32, 0x43, 0x33, 0x44, 0x34, 0x45, 0x35, 0x31, 0x20, 0x30, - 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x17, 0x41, 0x70, 0x70, 0x6c, - 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x55, - 0x73, 0x65, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, - 0x02, 0x82, 0x01, 0x01, 0x00, 0xbb, 0x6c, 0x6c, 0xd4, 0xcd, 0x0b, 0xd9, - 0x47, 0x49, 0xe1, 0xa3, 0xfe, 0x73, 0xe0, 0x15, 0xa6, 0x2e, 0x35, 0xc8, - 0xb7, 0xcd, 0xab, 0x5e, 0xd3, 0x87, 0x8a, 0x94, 0x8f, 0x4d, 0x94, 0x52, - 0x72, 0x27, 0x57, 0xb8, 0xf5, 0xa8, 0xe2, 0xf2, 0xb0, 0x46, 0xad, 0xb9, - 0x30, 0x9b, 0x6a, 0xd7, 0x0a, 0xff, 0x0e, 0x5e, 0x78, 0x4c, 0x97, 0x17, - 0x16, 0xa7, 0x03, 0xe1, 0x13, 0xe7, 0x97, 0x72, 0x24, 0xc8, 0x7f, 0x80, - 0x91, 0xd2, 0x45, 0xa3, 0xf8, 0x21, 0xce, 0x2d, 0xfa, 0xe4, 0x3a, 0x5e, - 0x04, 0x30, 0xe9, 0x48, 0xca, 0x32, 0xce, 0x52, 0x4c, 0xcf, 0x14, 0xf9, - 0x04, 0x58, 0x30, 0x4a, 0xf8, 0x49, 0xbb, 0x39, 0x18, 0x5c, 0x4b, 0x28, - 0x9e, 0x14, 0x16, 0x23, 0x73, 0x6e, 0x0d, 0xcd, 0xcd, 0xef, 0x98, 0xe7, - 0x90, 0x04, 0x0e, 0x4a, 0xc8, 0x16, 0x22, 0x76, 0x68, 0xc6, 0xdf, 0x5d, - 0x20, 0xa7, 0x49, 0x2e, 0x55, 0x9e, 0x50, 0x31, 0x56, 0x50, 0x29, 0xf9, - 0x56, 0x09, 0x38, 0x32, 0x25, 0x1b, 0x3a, 0x1c, 0x97, 0x3e, 0x04, 0xee, - 0x69, 0x3c, 0x68, 0x44, 0x54, 0x51, 0x27, 0x75, 0x70, 0xa2, 0x33, 0x86, - 0x7a, 0x9d, 0x71, 0xc0, 0x18, 0x2e, 0x37, 0xb5, 0x47, 0x8d, 0xbe, 0x57, - 0xb6, 0xaa, 0xda, 0x1d, 0xe8, 0x78, 0x23, 0x66, 0xc8, 0x6c, 0xe3, 0x7e, - 0xfd, 0xde, 0x6b, 0x70, 0x2f, 0x76, 0x1d, 0xa6, 0x2b, 0x97, 0xee, 0xad, - 0x5b, 0x8b, 0x8e, 0x00, 0x87, 0x27, 0xdf, 0x16, 0x54, 0x08, 0x97, 0x18, - 0x23, 0x31, 0x2c, 0xf5, 0x9d, 0x41, 0xd5, 0xbb, 0x60, 0x23, 0x92, 0x3d, - 0xcc, 0x9e, 0x2d, 0xff, 0xa5, 0x8b, 0xe0, 0xf9, 0x65, 0xdc, 0x94, 0x58, - 0xb0, 0x9d, 0x73, 0x05, 0x05, 0x21, 0xa1, 0xb3, 0x37, 0xa4, 0x8f, 0x5d, - 0xda, 0xce, 0x9c, 0xf6, 0x63, 0x9b, 0x6b, 0x9f, 0x77, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3a, 0x30, 0x82, 0x02, 0x36, 0x30, 0x3d, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x31, - 0x30, 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x30, 0x01, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, - 0x63, 0x73, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2d, 0x77, 0x77, 0x64, 0x72, 0x30, - 0x33, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x9b, 0xc2, 0x61, 0x59, 0x72, 0x23, 0xb6, 0x5f, 0x91, 0x0f, 0x04, 0x87, - 0x92, 0xf9, 0xa4, 0xf3, 0x6b, 0xe9, 0xbe, 0xab, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x88, 0x27, 0x17, 0x09, - 0xa9, 0xb6, 0x18, 0x60, 0x8b, 0xec, 0xeb, 0xba, 0xf6, 0x47, 0x59, 0xc5, - 0x52, 0x54, 0xa3, 0xb7, 0x30, 0x82, 0x01, 0x0f, 0x06, 0x03, 0x55, 0x1d, - 0x20, 0x04, 0x82, 0x01, 0x06, 0x30, 0x82, 0x01, 0x02, 0x30, 0x81, 0xff, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, - 0x81, 0xf1, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, - 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x30, 0x81, 0xc3, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x81, - 0xb6, 0x0c, 0x81, 0xb3, 0x52, 0x65, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, - 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x62, 0x79, 0x20, - 0x61, 0x6e, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x79, 0x20, 0x61, 0x73, - 0x73, 0x75, 0x6d, 0x65, 0x73, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x74, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x62, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, - 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, - 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, - 0x20, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, - 0x69, 0x63, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x2e, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x29, - 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x61, 0x70, 0x70, - 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x77, 0x64, 0x72, 0x63, - 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, - 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x1d, - 0x25, 0x04, 0x17, 0x30, 0x15, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, - 0x04, 0x0e, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, - 0x64, 0x06, 0x03, 0x02, 0x04, 0x02, 0x05, 0x00, 0x30, 0x26, 0x06, 0x0a, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, 0x01, 0x10, 0x04, 0x18, - 0x0c, 0x16, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, - 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, 0x6e, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x9b, 0xef, 0x1e, 0xff, - 0xee, 0xd5, 0xfd, 0x71, 0x1a, 0xf5, 0x17, 0xfe, 0x05, 0xba, 0x30, 0xfc, - 0xbd, 0x6d, 0x01, 0xb0, 0x0b, 0x78, 0x41, 0x4b, 0x76, 0x71, 0xd1, 0x8c, - 0xf0, 0xcd, 0xed, 0xd9, 0xaa, 0xec, 0xad, 0x1d, 0x4a, 0x2d, 0xcc, 0x00, - 0x11, 0x5b, 0x1d, 0xd9, 0xef, 0x08, 0xa2, 0x3d, 0xea, 0xe9, 0xbd, 0x35, - 0x0b, 0x1c, 0x9f, 0xe7, 0xeb, 0xc9, 0xc9, 0xea, 0x99, 0xcc, 0x77, 0x27, - 0xb9, 0x01, 0x09, 0x72, 0x40, 0xba, 0xd4, 0x26, 0x54, 0x8f, 0x30, 0x84, - 0x7e, 0x03, 0x65, 0xda, 0x08, 0xb2, 0x92, 0xee, 0x61, 0x4e, 0x5f, 0x00, - 0x39, 0x48, 0x2d, 0x99, 0x83, 0xb5, 0xc4, 0x33, 0xb2, 0xf7, 0x62, 0xcf, - 0x6a, 0xbf, 0xbb, 0xb8, 0x40, 0x70, 0xbf, 0x11, 0xff, 0x7f, 0xc1, 0xc1, - 0x8d, 0x1d, 0x67, 0x6c, 0x87, 0x02, 0xe2, 0x93, 0x17, 0x16, 0xc3, 0xec, - 0x5e, 0x97, 0xe4, 0xdd, 0x12, 0xcc, 0xb2, 0xdd, 0x91, 0x51, 0xa8, 0x32, - 0x25, 0x6d, 0xf7, 0x55, 0xb7, 0x4a, 0x8e, 0x6b, 0x90, 0xcb, 0x0f, 0x4c, - 0x93, 0x87, 0x2a, 0xd9, 0x31, 0xb8, 0x1a, 0x16, 0x12, 0xbb, 0x6e, 0xfc, - 0xb0, 0xae, 0xfb, 0x93, 0x76, 0x63, 0x37, 0xb7, 0x36, 0x13, 0x11, 0xc5, - 0x53, 0x45, 0xe0, 0x0d, 0xff, 0xaf, 0x05, 0x5f, 0x67, 0x51, 0xe1, 0x54, - 0x29, 0xa2, 0x1a, 0x7c, 0x61, 0xe0, 0xc2, 0xcd, 0xac, 0xbe, 0xee, 0xa6, - 0x4a, 0xdc, 0x92, 0x95, 0x48, 0x41, 0x2f, 0x37, 0xc0, 0x64, 0x05, 0xaa, - 0x4f, 0x05, 0xee, 0xe0, 0x3f, 0xa0, 0x9f, 0x43, 0x6c, 0xcc, 0xd5, 0x97, - 0x64, 0x6d, 0x15, 0x5b, 0xb6, 0xcd, 0x2a, 0xbc, 0x18, 0xde, 0xc7, 0x94, - 0x80, 0x2d, 0x2b, 0x81, 0x14, 0xfc, 0x48, 0xf7, 0xdf, 0xce, 0x94, 0xb3, - 0xfd, 0xf5, 0x7e, 0x42, 0x4d, 0x33, 0x58, 0x4d, 0x7a, 0x62, 0x2e, 0x61, - 0x31, 0x82, 0x02, 0x2a, 0x30, 0x82, 0x02, 0x26, 0x02, 0x01, 0x01, 0x30, - 0x81, 0xa3, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x0c, 0x23, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, - 0x64, 0x77, 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, - 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x02, - 0x08, 0x29, 0xd6, 0x12, 0x53, 0x17, 0x20, 0x2d, 0x6a, 0x30, 0x09, 0x06, - 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0xa0, 0x5d, 0x30, 0x18, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, - 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, - 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, - 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37, 0x32, - 0x31, 0x32, 0x33, 0x30, 0x35, 0x5a, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0x3e, - 0xa0, 0x0a, 0xb8, 0x8c, 0x99, 0x95, 0xbc, 0x08, 0x28, 0xfc, 0x76, 0x6c, - 0xcc, 0xb7, 0x75, 0x57, 0x82, 0x6f, 0x81, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x01, 0x00, 0x1a, 0x4c, 0x93, 0x84, 0xe5, 0x8a, 0x68, 0x26, 0x7f, 0xb2, - 0xf7, 0xa4, 0x69, 0x66, 0x3a, 0xfa, 0xad, 0x77, 0x30, 0xa7, 0x21, 0xa7, - 0xbb, 0x01, 0x17, 0xb4, 0x88, 0x4a, 0x58, 0x37, 0x2b, 0xf5, 0x92, 0x79, - 0xce, 0xb2, 0x89, 0xbb, 0xb3, 0x52, 0x80, 0xa3, 0x10, 0x6f, 0x58, 0xcb, - 0x03, 0x80, 0xb9, 0x32, 0x12, 0x76, 0xe6, 0x79, 0xc1, 0xcc, 0x3c, 0x7b, - 0xf6, 0x69, 0x31, 0x9a, 0xe1, 0x59, 0xd4, 0x15, 0x8a, 0x1d, 0xbd, 0xb0, - 0xc9, 0xc3, 0xe7, 0x55, 0x24, 0xcc, 0x42, 0x5c, 0x01, 0x1d, 0xd7, 0x1b, - 0x3a, 0x6e, 0x26, 0xda, 0x56, 0xd1, 0xaf, 0x44, 0x2c, 0x41, 0x6f, 0x26, - 0x36, 0xb0, 0x2d, 0x43, 0x04, 0xb8, 0x05, 0xd1, 0xe3, 0xe4, 0xa0, 0x9d, - 0x98, 0x5b, 0x52, 0x7d, 0xd2, 0x8b, 0x78, 0x27, 0x1f, 0x8e, 0xd0, 0xb0, - 0x09, 0x8a, 0x7d, 0x09, 0xd9, 0xc2, 0x7b, 0x09, 0x1e, 0xd8, 0x92, 0x1f, - 0x3f, 0x0f, 0x52, 0x10, 0x13, 0x9c, 0x0a, 0x4c, 0x9d, 0x4e, 0x55, 0x32, - 0x67, 0xc0, 0x46, 0x64, 0x8c, 0x89, 0x77, 0x6a, 0x6a, 0x60, 0xe2, 0x4d, - 0xb2, 0x9e, 0x4d, 0x18, 0xc9, 0x77, 0x74, 0xf1, 0x41, 0xf5, 0xb7, 0xfa, - 0x4b, 0x0f, 0xb7, 0x51, 0xf4, 0x59, 0x4d, 0xfa, 0x7a, 0x07, 0xba, 0xab, - 0xd5, 0x90, 0xa6, 0xbd, 0x61, 0x05, 0xde, 0x8b, 0x46, 0xbf, 0x8b, 0x5a, - 0xf8, 0xbf, 0xd8, 0x6c, 0x87, 0x0e, 0xc0, 0xfd, 0xc4, 0x63, 0xdd, 0xd9, - 0xb1, 0x52, 0xca, 0x64, 0x68, 0x87, 0xab, 0x27, 0x41, 0x41, 0xb8, 0x02, - 0xa2, 0xb7, 0xde, 0xda, 0x84, 0x15, 0x0e, 0xc6, 0x49, 0x5d, 0xd2, 0xc9, - 0xf1, 0x4a, 0x44, 0xa4, 0x1a, 0xf8, 0x5f, 0x70, 0x52, 0x67, 0xb3, 0x6f, - 0x59, 0x9a, 0x9a, 0xea, 0x1d, 0xfa, 0x6e, 0x06, 0xf3, 0xdc, 0x60, 0x28, - 0x97, 0xc3, 0x78, 0x04, 0x17, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const unsigned char _USAirwaysCorrect_manifest_json[] = { - 0x7b, 0x0a, 0x20, 0x20, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x40, 0x32, 0x78, - 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x38, 0x31, 0x38, - 0x64, 0x32, 0x37, 0x64, 0x33, 0x65, 0x66, 0x61, 0x39, 0x35, 0x37, 0x31, - 0x62, 0x61, 0x30, 0x66, 0x66, 0x31, 0x65, 0x36, 0x32, 0x34, 0x33, 0x62, - 0x30, 0x39, 0x34, 0x35, 0x62, 0x63, 0x63, 0x36, 0x39, 0x33, 0x65, 0x62, - 0x37, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x2e, - 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x62, 0x65, 0x64, 0x66, - 0x30, 0x30, 0x61, 0x61, 0x62, 0x32, 0x32, 0x31, 0x61, 0x63, 0x37, 0x31, - 0x64, 0x33, 0x66, 0x66, 0x65, 0x64, 0x64, 0x33, 0x32, 0x63, 0x33, 0x63, - 0x64, 0x36, 0x63, 0x32, 0x35, 0x30, 0x33, 0x32, 0x62, 0x61, 0x34, 0x30, - 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x6a, - 0x73, 0x6f, 0x6e, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x61, 0x65, 0x33, 0x38, - 0x39, 0x35, 0x39, 0x36, 0x30, 0x62, 0x34, 0x64, 0x61, 0x31, 0x65, 0x64, - 0x35, 0x38, 0x33, 0x66, 0x64, 0x37, 0x31, 0x66, 0x66, 0x32, 0x36, 0x31, - 0x36, 0x65, 0x34, 0x39, 0x65, 0x36, 0x34, 0x64, 0x36, 0x36, 0x65, 0x66, - 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x6c, 0x6f, 0x67, 0x6f, 0x2e, 0x70, - 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x39, 0x30, 0x62, 0x63, 0x62, - 0x39, 0x34, 0x62, 0x62, 0x30, 0x66, 0x31, 0x30, 0x33, 0x66, 0x36, 0x63, - 0x32, 0x63, 0x32, 0x36, 0x35, 0x35, 0x33, 0x36, 0x66, 0x65, 0x61, 0x63, - 0x37, 0x61, 0x38, 0x38, 0x33, 0x36, 0x37, 0x30, 0x34, 0x34, 0x33, 0x22, - 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x2e, 0x44, 0x53, 0x5f, 0x53, 0x74, 0x6f, - 0x72, 0x65, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x64, 0x66, 0x32, 0x66, 0x62, - 0x65, 0x62, 0x31, 0x34, 0x30, 0x30, 0x61, 0x63, 0x64, 0x61, 0x30, 0x39, - 0x30, 0x39, 0x61, 0x33, 0x32, 0x63, 0x31, 0x63, 0x66, 0x36, 0x62, 0x66, - 0x34, 0x39, 0x32, 0x66, 0x31, 0x31, 0x32, 0x31, 0x65, 0x30, 0x37, 0x22, - 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x6c, 0x6f, 0x67, 0x6f, 0x40, 0x32, 0x78, - 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x39, 0x30, 0x62, - 0x63, 0x62, 0x39, 0x34, 0x62, 0x62, 0x30, 0x66, 0x31, 0x30, 0x33, 0x66, - 0x36, 0x63, 0x32, 0x63, 0x32, 0x36, 0x35, 0x35, 0x33, 0x36, 0x66, 0x65, - 0x61, 0x63, 0x37, 0x61, 0x38, 0x38, 0x33, 0x36, 0x37, 0x30, 0x34, 0x34, - 0x33, 0x22, 0x0a, 0x7d -}; - -unsigned char _USAirwaysWrongTeamID_manifest_json[] = { - 0x7b, 0x0a, 0x20, 0x20, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x40, 0x32, 0x78, - 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x38, 0x31, 0x38, - 0x64, 0x32, 0x37, 0x64, 0x33, 0x65, 0x66, 0x61, 0x39, 0x35, 0x37, 0x31, - 0x62, 0x61, 0x30, 0x66, 0x66, 0x31, 0x65, 0x36, 0x32, 0x34, 0x33, 0x62, - 0x30, 0x39, 0x34, 0x35, 0x62, 0x63, 0x63, 0x36, 0x39, 0x33, 0x65, 0x62, - 0x37, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x2e, - 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x62, 0x65, 0x64, 0x66, - 0x30, 0x30, 0x61, 0x61, 0x62, 0x32, 0x32, 0x31, 0x61, 0x63, 0x37, 0x31, - 0x64, 0x33, 0x66, 0x66, 0x65, 0x64, 0x64, 0x33, 0x32, 0x63, 0x33, 0x63, - 0x64, 0x36, 0x63, 0x32, 0x35, 0x30, 0x33, 0x32, 0x62, 0x61, 0x34, 0x30, - 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x6a, - 0x73, 0x6f, 0x6e, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x32, 0x61, 0x35, 0x66, - 0x38, 0x66, 0x34, 0x37, 0x66, 0x34, 0x61, 0x33, 0x38, 0x37, 0x35, 0x35, - 0x36, 0x62, 0x31, 0x65, 0x61, 0x30, 0x65, 0x64, 0x64, 0x36, 0x39, 0x65, - 0x64, 0x31, 0x64, 0x62, 0x61, 0x39, 0x37, 0x39, 0x64, 0x32, 0x66, 0x33, - 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x6c, 0x6f, 0x67, 0x6f, 0x2e, 0x70, - 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x39, 0x30, 0x62, 0x63, 0x62, - 0x39, 0x34, 0x62, 0x62, 0x30, 0x66, 0x31, 0x30, 0x33, 0x66, 0x36, 0x63, - 0x32, 0x63, 0x32, 0x36, 0x35, 0x35, 0x33, 0x36, 0x66, 0x65, 0x61, 0x63, - 0x37, 0x61, 0x38, 0x38, 0x33, 0x36, 0x37, 0x30, 0x34, 0x34, 0x33, 0x22, - 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x2e, 0x44, 0x53, 0x5f, 0x53, 0x74, 0x6f, - 0x72, 0x65, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x64, 0x66, 0x32, 0x66, 0x62, - 0x65, 0x62, 0x31, 0x34, 0x30, 0x30, 0x61, 0x63, 0x64, 0x61, 0x30, 0x39, - 0x30, 0x39, 0x61, 0x33, 0x32, 0x63, 0x31, 0x63, 0x66, 0x36, 0x62, 0x66, - 0x34, 0x39, 0x32, 0x66, 0x31, 0x31, 0x32, 0x31, 0x65, 0x30, 0x37, 0x22, - 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x6c, 0x6f, 0x67, 0x6f, 0x40, 0x32, 0x78, - 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x39, 0x30, 0x62, - 0x63, 0x62, 0x39, 0x34, 0x62, 0x62, 0x30, 0x66, 0x31, 0x30, 0x33, 0x66, - 0x36, 0x63, 0x32, 0x63, 0x32, 0x36, 0x35, 0x35, 0x33, 0x36, 0x66, 0x65, - 0x61, 0x63, 0x37, 0x61, 0x38, 0x38, 0x33, 0x36, 0x37, 0x30, 0x34, 0x34, - 0x33, 0x22, 0x0a, 0x7d -}; - - -static void test_sig_verification(void) -{ - SecPolicyRef policy; - - CFDataRef goodSig = CFDataCreate(NULL, (const UInt8*) _USAirwaysCorrect_signature, - sizeof(_USAirwaysCorrect_signature)); - CFDataRef goodManifest = CFDataCreate(NULL, (const UInt8*) _USAirwaysCorrect_manifest_json, - sizeof(_USAirwaysCorrect_manifest_json)); - CFDataRef badSig = CFDataCreate(NULL, (const UInt8*) _USAirwaysWrongTeamID_signature, - sizeof(_USAirwaysWrongTeamID_signature)); - CFDataRef badManifest = CFDataCreate(NULL, (const UInt8*) _USAirwaysWrongTeamID_manifest_json, - sizeof(_USAirwaysWrongTeamID_manifest_json)); - - /* - OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents, - SecPolicyRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates, - CFDataRef *attached_contents, CFDictionaryRef *message_attributes) - */ - - /* Case 1: verify signature with good values */ - isnt(policy = SecPolicyCreatePassbookCardSigner(CFSTR("pass.com.apple.cardman"), CFSTR("A1B2C3D4E5")), - NULL, "create policy"); - ok_status(SecCMSVerifySignedData(goodSig, goodManifest, policy, NULL, NULL, NULL, NULL), "verify signed data 1"); - CFReleaseNull(policy); - CFRelease(goodManifest); - CFRelease(goodSig); - policy = NULL; - - /* Case 2: verify signature with bad values */ - isnt(policy = SecPolicyCreatePassbookCardSigner(CFSTR("pass.com.apple.cardman"), CFSTR("IAMBOGUS")), - NULL, "create policy"); - isnt(SecCMSVerifySignedData(badSig, badManifest, policy, NULL, NULL, NULL, NULL), errSecSuccess, "verify signed data 2"); - CFReleaseNull(policy); - policy = NULL; - - - /* Case 3: get trust reference back from SecCMSVerifySignedData and verify it ourselves */ - SecTrustRef trust = NULL; - SecTrustResultType trustResult; - isnt(policy = SecPolicyCreatePassbookCardSigner(CFSTR("pass.com.apple.cardman"), CFSTR("IAMBOGUS")), - NULL, "create policy"); - ok_status(SecCMSVerifySignedData(badSig, badManifest, policy, &trust, NULL, NULL, NULL), "verify signed data 3"); - isnt(trust, NULL, "get trust"); - if (!trust) { goto errOut; } - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - ok(trustResult == kSecTrustResultRecoverableTrustFailure, "recoverable trustResult expected (ok)"); - -errOut: - CFReleaseNull(trust); - CFReleaseNull(policy); - CFRelease(badManifest); - CFRelease(badSig); - trust = NULL; -} - -int si_24_sectrust_passbook(int argc, char *const *argv) -{ - plan_tests(9); - - test_sig_verification(); - - return 0; -} diff --git a/OSX/libsecurity_keychain/regressions/si-20-sectrust-provisioning.h b/OSX/sec/Security/Regressions/secitem/si-26-cms-apple-signed-samples.h similarity index 99% rename from OSX/libsecurity_keychain/regressions/si-20-sectrust-provisioning.h rename to OSX/sec/Security/Regressions/secitem/si-26-cms-apple-signed-samples.h index 4af0ea43..ec0d9fe7 100644 --- a/OSX/libsecurity_keychain/regressions/si-20-sectrust-provisioning.h +++ b/OSX/sec/Security/Regressions/secitem/si-26-cms-apple-signed-samples.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,6 +21,9 @@ * @APPLE_LICENSE_HEADER_END@ */ +#ifndef _SECURITY_SI_26_CMS_APPLE_SIGNED_SAMPLES_H_ +#define _SECURITY_SI_26_CMS_APPLE_SIGNED_SAMPLES_H_ + static unsigned char _TestProvisioningProfile[7993] = { 0x30, 0x82, 0x1f, 0x35, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x1f, 0x26, 0x30, 0x82, 0x1f, 0x22, 0x02, @@ -690,3 +693,5 @@ static unsigned char _TestProvisioningProfile[7993] = { 0x4c, 0xd3, 0xf0, 0xab, 0x3e, 0x95, 0xe7, 0x1b, 0xc7, 0x49, 0x9a, 0xc3, 0x8b }; + +#endif /* _SECURITY_SI_26_CMS_APPLE_SIGNED_SAMPLES_H_ */ diff --git a/OSX/sec/Security/Regressions/secitem/si-26-cms-apple-signed-samples.m b/OSX/sec/Security/Regressions/secitem/si-26-cms-apple-signed-samples.m new file mode 100644 index 00000000..065df916 --- /dev/null +++ b/OSX/sec/Security/Regressions/secitem/si-26-cms-apple-signed-samples.m @@ -0,0 +1,50 @@ +// +// si-26-cms-apple-signed-samples.m +// SharedRegressions +// +// + +#import +#include +#include +#include +#include +#include + +#include "shared_regressions.h" +#include "si-26-cms-apple-signed-samples.h" + +static void tests(void) +{ + SecPolicyRef policy = NULL; + + /* Create Mac Provisioning Profile policy instance. */ + isnt(policy = SecPolicyCreateOSXProvisioningProfileSigning(), NULL, "create policy"); + + /* Verify signed content with this policy. */ + CMSDecoderRef decoder = NULL; + CMSSignerStatus signerStatus = kCMSSignerInvalidIndex; + OSStatus verifyResult = 0; + ok_status(CMSDecoderCreate(&decoder), + "create decoder"); + ok_status(CMSDecoderUpdateMessage(decoder, _TestProvisioningProfile, sizeof(_TestProvisioningProfile)), + "update message"); + ok_status(CMSDecoderFinalizeMessage(decoder), + "finalize message"); + ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, true, &signerStatus, NULL, &verifyResult), + "copy signer status"); + is(signerStatus, kCMSSignerValid, "signer status valid"); + is(verifyResult, errSecSuccess, "verify result valid"); + + CFReleaseSafe(decoder); + CFReleaseSafe(policy); +} + +int si_26_cms_apple_signed_samples(int argc, char *const *argv) +{ + plan_tests(7); + + tests(); + + return 0; +} diff --git a/OSX/sec/Security/Regressions/secitem/si-26-sectrust-copyproperties.c b/OSX/sec/Security/Regressions/secitem/si-26-sectrust-copyproperties.c deleted file mode 100644 index 9119beb2..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-26-sectrust-copyproperties.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Copyright (c) 2007,2009-2010,2012 Apple Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "shared_regressions.h" - -/* subject:/CN=iPhone Developer: Katherine Kojima/OU=Core OS Plus Others/O=Core OS Plus Others/C=usa */ -/* issuer :/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority */ -unsigned char codesigning_certificate[1415]={ -0x30,0x82,0x05,0x83,0x30,0x82,0x04,0x6B,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x70, -0xA9,0x16,0x20,0x02,0xA2,0xD4,0x50,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, -0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x96,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, -0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, -0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x2C,0x30,0x2A,0x06, -0x03,0x55,0x04,0x0B,0x0C,0x23,0x41,0x70,0x70,0x6C,0x65,0x20,0x57,0x6F,0x72,0x6C, -0x64,0x77,0x69,0x64,0x65,0x20,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x20, -0x52,0x65,0x6C,0x61,0x74,0x69,0x6F,0x6E,0x73,0x31,0x44,0x30,0x42,0x06,0x03,0x55, -0x04,0x03,0x0C,0x3B,0x41,0x70,0x70,0x6C,0x65,0x20,0x57,0x6F,0x72,0x6C,0x64,0x77, -0x69,0x64,0x65,0x20,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x20,0x52,0x65, -0x6C,0x61,0x74,0x69,0x6F,0x6E,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, -0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30, -0x1E,0x17,0x0D,0x30,0x38,0x30,0x33,0x32,0x36,0x31,0x37,0x30,0x37,0x34,0x36,0x5A, -0x17,0x0D,0x30,0x38,0x30,0x39,0x32,0x34,0x31,0x37,0x30,0x37,0x34,0x36,0x5A,0x30, -0x77,0x31,0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x0C,0x22,0x69,0x50,0x68,0x6F, -0x6E,0x65,0x20,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x3A,0x20,0x4B,0x61, -0x74,0x68,0x65,0x72,0x69,0x6E,0x65,0x20,0x4B,0x6F,0x6A,0x69,0x6D,0x61,0x31,0x1C, -0x30,0x1A,0x06,0x03,0x55,0x04,0x0B,0x0C,0x13,0x43,0x6F,0x72,0x65,0x20,0x4F,0x53, -0x20,0x50,0x6C,0x75,0x73,0x20,0x4F,0x74,0x68,0x65,0x72,0x73,0x31,0x1C,0x30,0x1A, -0x06,0x03,0x55,0x04,0x0A,0x0C,0x13,0x43,0x6F,0x72,0x65,0x20,0x4F,0x53,0x20,0x50, -0x6C,0x75,0x73,0x20,0x4F,0x74,0x68,0x65,0x72,0x73,0x31,0x0C,0x30,0x0A,0x06,0x03, -0x55,0x04,0x06,0x13,0x03,0x75,0x73,0x61,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, -0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00, -0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xD4,0x2B,0xF2,0x10,0x71,0x0B,0xBB, -0x3D,0xA0,0x1A,0x32,0x41,0xBC,0xA9,0x55,0xF4,0xFB,0x6C,0x9C,0xB5,0x32,0x52,0x10, -0x7E,0x41,0xF4,0x2C,0x18,0x3A,0x4F,0x32,0x9D,0xA3,0x64,0x28,0xDD,0x94,0xD0,0xB8, -0x3F,0xF9,0x7C,0x62,0xE6,0xF5,0xF1,0x16,0x0D,0x7F,0xBA,0xEC,0xBF,0xD9,0x95,0xD4, -0x7A,0xD7,0x4D,0x32,0x0F,0xCD,0x6D,0xBC,0xF3,0x10,0xDE,0xE8,0x5D,0xA1,0xDA,0x98, -0x8F,0x6C,0x75,0xF7,0x7B,0xBE,0x33,0x43,0xBD,0x95,0xFA,0x35,0xD6,0x77,0x81,0x68, -0x02,0x9C,0x41,0x99,0x0B,0x53,0x5F,0x58,0xF3,0x85,0x4C,0xAB,0x06,0xC2,0xC0,0xC4, -0xD8,0x68,0x64,0xE3,0x14,0x5F,0x62,0x75,0xD5,0x66,0x9B,0xEE,0x4A,0x49,0xBA,0xC7, -0x7B,0xD1,0xE6,0x96,0x9D,0xE5,0xEF,0x99,0x0E,0x87,0xEC,0xE3,0xA4,0x54,0x3E,0x19, -0xBB,0x87,0x53,0x9C,0x3C,0x6A,0x94,0x6B,0x22,0x1A,0x01,0xAF,0x21,0xD5,0xDA,0xB0, -0x92,0xE0,0x70,0x61,0xDD,0xC1,0x37,0x60,0x1F,0xC3,0xB0,0xFC,0xB3,0x00,0x4A,0x56, -0x9D,0x70,0xC3,0xDE,0x66,0xD0,0xEF,0x39,0x88,0x48,0xBD,0x6D,0xA6,0xB2,0x2C,0x0A, -0x78,0xCE,0x05,0x62,0x9B,0xE9,0x18,0x4E,0x59,0xC8,0xDC,0xD3,0xDF,0xB6,0x77,0xB5, -0xA3,0xDA,0x62,0x15,0x9A,0x50,0x1E,0x28,0x55,0x70,0xC2,0xB7,0x97,0x63,0x00,0x1E, -0x0E,0x3A,0x8B,0xA6,0x13,0xE5,0xE0,0xD6,0xE6,0xFA,0x61,0xDE,0x5F,0x30,0x72,0xAA, -0xE4,0xBA,0x21,0x74,0x63,0x4A,0xF2,0x18,0x4C,0x99,0x8D,0x75,0x27,0x91,0xF9,0xD4, -0x08,0xAE,0xB6,0xDA,0x69,0x33,0x06,0x7F,0x17,0x02,0x03,0x01,0x00,0x01,0xA3,0x82, -0x01,0xF1,0x30,0x82,0x01,0xED,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, -0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, -0x03,0x02,0x07,0x80,0x30,0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01,0xFF,0x04,0x0C, -0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x1D,0x06,0x03, -0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x6A,0x6D,0x56,0xC6,0xA5,0x0E,0xC2,0x97,0xF7, -0x17,0x48,0xBE,0xA0,0x07,0xFF,0x77,0xE9,0xEF,0xB2,0xED,0x30,0x1F,0x06,0x03,0x55, -0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x88,0x27,0x17,0x09,0xA9,0xB6,0x18,0x60, -0x8B,0xEC,0xEB,0xBA,0xF6,0x47,0x59,0xC5,0x52,0x54,0xA3,0xB7,0x30,0x82,0x01,0x0F, -0x06,0x03,0x55,0x1D,0x20,0x04,0x82,0x01,0x06,0x30,0x82,0x01,0x02,0x30,0x81,0xFF, -0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF1,0x30,0x81, -0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x81,0xB6,0x0C,0x81, -0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69, -0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x62,0x79, -0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72,0x74,0x79,0x20,0x61,0x73,0x73,0x75,0x6D, -0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66, -0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65,0x6E,0x20,0x61,0x70,0x70,0x6C,0x69,0x63, -0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61,0x6E,0x64,0x61,0x72,0x64,0x20,0x74,0x65, -0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F, -0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x2C,0x20,0x63,0x65,0x72,0x74,0x69, -0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70,0x6F,0x6C,0x69,0x63,0x79,0x20,0x61,0x6E, -0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20, -0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65, -0x6E,0x74,0x73,0x2E,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01, -0x16,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61,0x70,0x70, -0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x63,0x61,0x2F,0x30, -0x4D,0x06,0x03,0x55,0x1D,0x1F,0x04,0x46,0x30,0x44,0x30,0x42,0xA0,0x40,0xA0,0x3E, -0x86,0x3C,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x64,0x65,0x76,0x65,0x6C,0x6F,0x70, -0x65,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x65,0x72, -0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x61,0x75,0x74,0x68,0x6F,0x72, -0x69,0x74,0x79,0x2F,0x77,0x77,0x64,0x72,0x63,0x61,0x2E,0x63,0x72,0x6C,0x30,0x13, -0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x01,0x02,0x01,0x01,0xFF,0x04, -0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, -0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xA1,0x1D,0x8C,0xB9,0x21,0x59,0xC8,0xC0,0x08, -0x25,0x97,0x78,0x0D,0x04,0x14,0x85,0xA8,0xFC,0xC3,0xB1,0x7E,0x72,0x45,0x4C,0x96, -0x82,0x90,0x73,0x68,0x24,0x65,0x11,0x0F,0xB8,0x0D,0xB8,0xE4,0x46,0xD5,0x61,0x01, -0x64,0xB8,0x51,0xF8,0xAE,0xE7,0xCF,0xF2,0x7A,0x93,0x78,0xC7,0x9A,0xD3,0xF4,0xF8, -0x04,0xDB,0xF1,0x4A,0xDB,0x05,0x98,0x2F,0xF3,0x39,0x37,0xB0,0x2B,0x49,0x9A,0x82, -0x36,0x63,0xF4,0xB3,0x70,0x75,0x43,0xE3,0xF1,0xBD,0xB5,0x68,0x0C,0xB3,0x7E,0xA3, -0xB3,0x29,0x55,0xD2,0x34,0xD8,0x13,0xB5,0x87,0xD3,0xCE,0xEB,0x26,0xE5,0xCB,0x1F, -0xF1,0xE1,0x89,0x7A,0xB0,0x39,0xB2,0x2E,0x88,0x76,0xE9,0x68,0x69,0x4E,0x90,0xB4, -0x7C,0x42,0x7A,0x2C,0xDF,0x33,0xCF,0x2F,0xBD,0x38,0x3A,0xCC,0xB3,0xC7,0x47,0x9C, -0xC4,0x87,0xCE,0x1A,0x1E,0xF4,0xBB,0xC9,0x97,0x35,0x1C,0x65,0xC2,0xF0,0x2F,0x98, -0x50,0x96,0xA6,0x6C,0xF5,0x1B,0x45,0xE6,0x48,0xBE,0x17,0xFB,0xF6,0x61,0x3E,0x94, -0xF3,0x49,0x57,0xB5,0x54,0x5F,0xE1,0x92,0x30,0xF9,0xC6,0xB7,0x21,0xE0,0x30,0x64, -0x83,0xE7,0x49,0x97,0x8D,0xDC,0xE5,0x9D,0x89,0xA9,0x14,0x2E,0xEF,0x21,0x00,0xBA, -0x13,0x63,0xF4,0xCD,0x2F,0x61,0x17,0x58,0xAB,0xD3,0xA8,0x06,0x54,0x5F,0x60,0xB3, -0xBE,0xED,0xE8,0xF8,0xA4,0x29,0x2F,0xE1,0x4A,0x0E,0xB1,0xFE,0xCE,0x73,0x14,0x9A, -0x3A,0x95,0xFC,0xC8,0xB6,0x53,0xBC,0xBF,0x3A,0xB0,0xAE,0x80,0x76,0xF5,0x57,0x47, -0xD2,0x1C,0x08,0x19,0x22,0xF2,0x6D, -}; - -/* subject:/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority */ -/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA */ -unsigned char wwdr_intermediate_cert[1063]={ -0x30,0x82,0x04,0x23,0x30,0x82,0x03,0x0B,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x19, -0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30, -0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, -0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, -0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70, -0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, -0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06, -0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74, -0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x38,0x30,0x32,0x31,0x34,0x31,0x38,0x35, -0x36,0x33,0x35,0x5A,0x17,0x0D,0x31,0x36,0x30,0x32,0x31,0x34,0x31,0x38,0x35,0x36, -0x33,0x35,0x5A,0x30,0x81,0x96,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, -0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, -0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04, -0x0B,0x0C,0x23,0x41,0x70,0x70,0x6C,0x65,0x20,0x57,0x6F,0x72,0x6C,0x64,0x77,0x69, -0x64,0x65,0x20,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x20,0x52,0x65,0x6C, -0x61,0x74,0x69,0x6F,0x6E,0x73,0x31,0x44,0x30,0x42,0x06,0x03,0x55,0x04,0x03,0x0C, -0x3B,0x41,0x70,0x70,0x6C,0x65,0x20,0x57,0x6F,0x72,0x6C,0x64,0x77,0x69,0x64,0x65, -0x20,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x20,0x52,0x65,0x6C,0x61,0x74, -0x69,0x6F,0x6E,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, -0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x82,0x01,0x22, -0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03, -0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xCA,0x38,0x54, -0xA6,0xCB,0x56,0xAA,0xC8,0x24,0x39,0x48,0xE9,0x8C,0xEE,0xEC,0x5F,0xB8,0x7F,0x26, -0x91,0xBC,0x34,0x53,0x7A,0xCE,0x7C,0x63,0x80,0x61,0x77,0x64,0x5E,0xA5,0x07,0x23, -0xB6,0x39,0xFE,0x50,0x2D,0x15,0x56,0x58,0x70,0x2D,0x7E,0xC4,0x6E,0xC1,0x4A,0x85, -0x3E,0x2F,0xF0,0xDE,0x84,0x1A,0xA1,0x57,0xC9,0xAF,0x7B,0x18,0xFF,0x6A,0xFA,0x15, -0x12,0x49,0x15,0x08,0x19,0xAC,0xAA,0xDB,0x2A,0x32,0xED,0x96,0x63,0x68,0x52,0x15, -0x3D,0x8C,0x8A,0xEC,0xBF,0x6B,0x18,0x95,0xE0,0x03,0xAC,0x01,0x7D,0x97,0x05,0x67, -0xCE,0x0E,0x85,0x95,0x37,0x6A,0xED,0x09,0xB6,0xAE,0x67,0xCD,0x51,0x64,0x9F,0xC6, -0x5C,0xD1,0xBC,0x57,0x6E,0x67,0x35,0x80,0x76,0x36,0xA4,0x87,0x81,0x6E,0x38,0x8F, -0xD8,0x2B,0x15,0x4E,0x7B,0x25,0xD8,0x5A,0xBF,0x4E,0x83,0xC1,0x8D,0xD2,0x93,0xD5, -0x1A,0x71,0xB5,0x60,0x9C,0x9D,0x33,0x4E,0x55,0xF9,0x12,0x58,0x0C,0x86,0xB8,0x16, -0x0D,0xC1,0xE5,0x77,0x45,0x8D,0x50,0x48,0xBA,0x2B,0x2D,0xE4,0x94,0x85,0xE1,0xE8, -0xC4,0x9D,0xC6,0x68,0xA5,0xB0,0xA3,0xFC,0x67,0x7E,0x70,0xBA,0x02,0x59,0x4B,0x77, -0x42,0x91,0x39,0xB9,0xF5,0xCD,0xE1,0x4C,0xEF,0xC0,0x3B,0x48,0x8C,0xA6,0xE5,0x21, -0x5D,0xFD,0x6A,0x6A,0xBB,0xA7,0x16,0x35,0x60,0xD2,0xE6,0xAD,0xF3,0x46,0x29,0xC9, -0xE8,0xC3,0x8B,0xE9,0x79,0xC0,0x6A,0x61,0x67,0x15,0xB2,0xF0,0xFD,0xE5,0x68,0xBC, -0x62,0x5F,0x6E,0xCF,0x99,0xDD,0xEF,0x1B,0x63,0xFE,0x92,0x65,0xAB,0x02,0x03,0x01, -0x00,0x01,0xA3,0x81,0xAE,0x30,0x81,0xAB,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, -0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01, -0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, -0x04,0x16,0x04,0x14,0x88,0x27,0x17,0x09,0xA9,0xB6,0x18,0x60,0x8B,0xEC,0xEB,0xBA, -0xF6,0x47,0x59,0xC5,0x52,0x54,0xA3,0xB7,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04, -0x18,0x30,0x16,0x80,0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D, -0x2E,0x40,0xA6,0xF7,0x47,0x4D,0x7F,0x08,0x5E,0x30,0x36,0x06,0x03,0x55,0x1D,0x1F, -0x04,0x2F,0x30,0x2D,0x30,0x2B,0xA0,0x29,0xA0,0x27,0x86,0x25,0x68,0x74,0x74,0x70, -0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, -0x2F,0x61,0x70,0x70,0x6C,0x65,0x63,0x61,0x2F,0x72,0x6F,0x6F,0x74,0x2E,0x63,0x72, -0x6C,0x30,0x10,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x02,0x01,0x04, -0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, -0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xDA,0x32,0x00,0x96,0xC5,0x54,0x94,0xD3,0x3B, -0x82,0x37,0x66,0x7D,0x2E,0x68,0xD5,0xC3,0xC6,0xB8,0xCB,0x26,0x8C,0x48,0x90,0xCF, -0x13,0x24,0x6A,0x46,0x8E,0x63,0xD4,0xF0,0xD0,0x13,0x06,0xDD,0xD8,0xC4,0xC1,0x37, -0x15,0xF2,0x33,0x13,0x39,0x26,0x2D,0xCE,0x2E,0x55,0x40,0xE3,0x0B,0x03,0xAF,0xFA, -0x12,0xC2,0xE7,0x0D,0x21,0xB8,0xD5,0x80,0xCF,0xAC,0x28,0x2F,0xCE,0x2D,0xB3,0x4E, -0xAF,0x86,0x19,0x04,0xC6,0xE9,0x50,0xDD,0x4C,0x29,0x47,0x10,0x23,0xFC,0x6C,0xBB, -0x1B,0x98,0x6B,0x48,0x89,0xE1,0x5B,0x9D,0xDE,0x46,0xDB,0x35,0x85,0x35,0xEF,0x3E, -0xD0,0xE2,0x58,0x4B,0x38,0xF4,0xED,0x75,0x5A,0x1F,0x5C,0x70,0x1D,0x56,0x39,0x12, -0xE5,0xE1,0x0D,0x11,0xE4,0x89,0x25,0x06,0xBD,0xD5,0xB4,0x15,0x8E,0x5E,0xD0,0x59, -0x97,0x90,0xE9,0x4B,0x81,0xE2,0xDF,0x18,0xAF,0x44,0x74,0x1E,0x19,0xA0,0x3A,0x47, -0xCC,0x91,0x1D,0x3A,0xEB,0x23,0x5A,0xFE,0xA5,0x2D,0x97,0xF7,0x7B,0xBB,0xD6,0x87, -0x46,0x42,0x85,0xEB,0x52,0x3D,0x26,0xB2,0x63,0xA8,0xB4,0xB1,0xCA,0x8F,0xF4,0xCC, -0xE2,0xB3,0xC8,0x47,0xE0,0xBF,0x9A,0x59,0x83,0xFA,0xDA,0x98,0x53,0x2A,0x82,0xF5, -0x7C,0x65,0x2E,0x95,0xD9,0x33,0x5D,0xF5,0xED,0x65,0xCC,0x31,0x37,0xC5,0x5A,0x04, -0xE8,0x6B,0xE1,0xE7,0x88,0x03,0x4A,0x75,0x9E,0x9B,0x28,0xCB,0x4A,0x40,0x88,0x65, -0x43,0x75,0xDD,0xCB,0x3A,0x25,0x23,0xC5,0x9E,0x57,0xF8,0x2E,0xCE,0xD2,0xA9,0x92, -0x5E,0x73,0x2E,0x2F,0x25,0x75,0x15, -}; - -/* TODO: Use the shared version of this function in print_cert.c. */ -#if !TARGET_OS_IPHONE -__unused -#endif -static void print_line(CFStringRef line) { - UInt8 buf[256]; - CFRange range = { .location = 0 }; - range.length = CFStringGetLength(line); - while (range.length > 0) { - CFIndex bytesUsed = 0; - CFIndex converted = CFStringGetBytes(line, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed); - fwrite(buf, 1, bytesUsed, stdout); - range.length -= converted; - range.location += converted; - } - fputc('\n', stdout); -} - -#if !TARGET_OS_IPHONE -__unused -#endif -static void printPlist(CFArrayRef plist, CFIndex indent, CFIndex maxWidth) { - CFIndex count = CFArrayGetCount(plist); - CFIndex ix; - for (ix = 0; ix < count ; ++ix) { - CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist, - ix); - CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyType); - CFStringRef label = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyLabel); - CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyLocalizedLabel); - CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop, - kSecPropertyKeyValue); - - bool isSection = CFEqual(pType, kSecPropertyTypeSection); - CFMutableStringRef line = CFStringCreateMutable(NULL, 0); - CFIndex jx = 0; - for (jx = 0; jx < indent; ++jx) { - CFStringAppend(line, CFSTR(" ")); - } - if (llabel) { - CFStringAppend(line, llabel); - if (!isSection) { - for (jx = CFStringGetLength(llabel) + indent * 4; - jx < maxWidth; ++jx) { - CFStringAppend(line, CFSTR(" ")); - } - CFStringAppend(line, CFSTR(" : ")); - } - } - if (CFEqual(pType, kSecPropertyTypeWarning)) { - CFStringAppend(line, CFSTR("*WARNING* ")); - CFStringAppend(line, (CFStringRef)value); - } else if (CFEqual(pType, kSecPropertyTypeError)) { - CFStringAppend(line, CFSTR("*ERROR* ")); - CFStringAppend(line, (CFStringRef)value); - } else if (CFEqual(pType, kSecPropertyTypeSuccess)) { - CFStringAppend(line, CFSTR("*OK* ")); - CFStringAppend(line, (CFStringRef)value); - } else if (CFEqual(pType, kSecPropertyTypeTitle)) { - CFStringAppend(line, CFSTR("*")); - CFStringAppend(line, (CFStringRef)value); - CFStringAppend(line, CFSTR("*")); - } else if (CFEqual(pType, kSecPropertyTypeSection)) { - } else if (CFEqual(pType, kSecPropertyTypeData)) { - CFDataRef data = (CFDataRef)value; - CFIndex length = CFDataGetLength(data); - if (length > 20) - CFStringAppendFormat(line, NULL, CFSTR("[%" PRIdCFIndex " bytes] "), length); - const UInt8 *bytes = CFDataGetBytePtr(data); - for (jx = 0; jx < length; ++jx) { - if (jx == 0) - CFStringAppendFormat(line, NULL, CFSTR("%02X"), bytes[jx]); - else if (jx < 15 || length <= 20) - CFStringAppendFormat(line, NULL, CFSTR(" %02X"), - bytes[jx]); - else { - CFStringAppend(line, CFSTR(" ...")); - break; - } - } - } else if (CFEqual(pType, kSecPropertyTypeString)) { - CFStringAppend(line, (CFStringRef)value); - } else if (CFEqual(pType, kSecPropertyTypeDate)) { - CFLocaleRef lc = CFLocaleCopyCurrent(); - CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, - kCFDateFormatterFullStyle, kCFDateFormatterFullStyle); - //CFTimeZoneRef tz = CFTimeZoneCreateWithName(NULL, CFSTR("GMT"), false); - //CFDateFormatterSetProperty(df, kCFDateFormatterTimeZone, tz); - //CFRelease(tz); - CFDateRef date = (CFDateRef)value; - CFStringRef ds = CFDateFormatterCreateStringWithDate(NULL, df, - date); - CFStringAppend(line, ds); - CFRelease(ds); - CFRelease(df); - CFRelease(lc); - } else if (CFEqual(pType, kSecPropertyTypeURL)) { - CFURLRef url = (CFURLRef)value; - CFStringAppend(line, CFSTR("<")); - CFStringAppend(line, CFURLGetString(url)); - CFStringAppend(line, CFSTR(">")); - } else { - CFStringAppendFormat(line, NULL, CFSTR("*unknown type %@* = %@"), - pType, value); - } - - if (!isSection || label) - print_line(line); - CFRelease(line); - if (isSection) { - printPlist((CFArrayRef)value, indent + 1, maxWidth); - } - } -} - -#if !TARGET_OS_IPHONE -__unused -#endif -static CFIndex maxLabelWidth(CFArrayRef plist, CFIndex indent) { - CFIndex count = CFArrayGetCount(plist); - CFIndex ix; - CFIndex maxWidth = 0; - for (ix = 0; ix < count ; ++ix) { - CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist, - ix); - CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyType); - CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyLocalizedLabel); - CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop, - kSecPropertyKeyValue); - - if (CFEqual(pType, kSecPropertyTypeSection)) { - CFIndex width = maxLabelWidth((CFArrayRef)value, indent + 1); - if (width > maxWidth) - maxWidth = width; - } else if (llabel) { - CFIndex width = indent * 4 + CFStringGetLength(llabel); - if (width > maxWidth) - maxWidth = width; - } - } - - return maxWidth; -} - -#if !TARGET_OS_IPHONE -__unused -#endif -static void print_plist(CFArrayRef plist) { - if (plist) - printPlist(plist, 0, maxLabelWidth(plist, 0)); - else - printf("NULL plist\n"); -} - -#if !TARGET_OS_IPHONE -__unused -#endif -static void print_cert(SecCertificateRef cert, bool verbose) { - CFArrayRef plist; - if (verbose) - plist = SecCertificateCopyProperties(cert); - else { - CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); - plist = SecCertificateCopySummaryProperties(cert, now); - } - - CFStringRef subject = SecCertificateCopySubjectString(cert); - if (subject) { - print_line(subject); - CFRelease(subject); - } else { - print_line(CFSTR("no subject")); - } - - print_plist(plist); - CFRelease(plist); -} - -static void tests(void) -{ - SecTrustRef trust; - SecCertificateRef leaf, wwdr_intermediate; - SecPolicyRef policy; - - isnt(wwdr_intermediate = SecCertificateCreateWithBytes(kCFAllocatorDefault, - wwdr_intermediate_cert, sizeof(wwdr_intermediate_cert)), NULL, "create WWDR intermediate"); - isnt(leaf = SecCertificateCreateWithBytes(kCFAllocatorDefault, - codesigning_certificate, sizeof(codesigning_certificate)), NULL, "create leaf"); - - const void *vcerts[] = { leaf, wwdr_intermediate }; - CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, vcerts, 2, NULL); - - isnt(policy = SecPolicyCreateiPhoneProfileApplicationSigning(), NULL, - "create iPhoneProfileApplicationSigning policy instance"); - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for leaf"); - CFDateRef verifyDate = CFDateCreate(kCFAllocatorDefault, 228244066); - ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set verify date"); - CFReleaseNull(verifyDate); - SecTrustResultType trustResult; - CFArrayRef properties = NULL; - properties = SecTrustCopyProperties(trust); -#if TARGET_OS_IPHONE - // Note: OS X will trigger the evaluation in order to return the properties. - is(properties, NULL, "no properties returned before eval"); -#endif - CFReleaseNull(properties); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); - properties = SecTrustCopyProperties(trust); - -#if TARGET_OS_IPHONE - if (properties) { - print_plist(properties); - print_cert(leaf, true); - print_cert(wwdr_intermediate, false); - } -#endif - CFReleaseNull(properties); - // verify wrapper functions are available - properties = SecCertificateCopyProperties(leaf); - isnt(properties, NULL, "leaf properties returned"); - CFReleaseNull(properties); - // Xcode doesn't have a SDK for 10.15.1 so we need to work around this. - // rdar://problem/55890533 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" - properties = SecCertificateCopyLocalizedProperties(leaf, true); -#pragma clang diagnostic pop - isnt(properties, NULL, "localized leaf properties returned"); - CFReleaseNull(properties); - - CFReleaseNull(trust); - CFReleaseNull(wwdr_intermediate); - CFReleaseNull(leaf); - CFReleaseNull(certs); - CFReleaseNull(policy); - CFReleaseNull(trust); -} - -int si_26_sectrust_copyproperties(int argc, char *const *argv) -{ -#if TARGET_OS_IPHONE - plan_tests(10); -#else - // - plan_tests(9); -#endif - - - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-27-cms-parse.m b/OSX/sec/Security/Regressions/secitem/si-27-cms-parse.m new file mode 100644 index 00000000..4a69bb29 --- /dev/null +++ b/OSX/sec/Security/Regressions/secitem/si-27-cms-parse.m @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "shared_regressions.h" + +#import +#import + +#include +#include + +const NSString *kSecTestCMSParseFailureResources = @"si-27-cms-parse/ParseFailureCMS"; +const NSString *kSecTestCMSParseSuccessResources = @"si-27-cms-parse/ParseSuccessCMS"; + + +static void test_cms_parse_success(void) { + NSArray*cmsURLs = [[NSBundle mainBundle] URLsForResourcesWithExtension:@".der" subdirectory:(NSString *)kSecTestCMSParseSuccessResources]; + if ([cmsURLs count] > 0) { + [cmsURLs enumerateObjectsUsingBlock:^(NSURL * _Nonnull url, NSUInteger __unused idx, BOOL * __unused _Nonnull stop) { + SecCmsMessageRef cmsg = NULL; + NSData *cmsData = [NSData dataWithContentsOfURL:url]; + SecAsn1Item encoded_message = { [cmsData length], (uint8_t*)[cmsData bytes] }; + ok_status(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), "Failed to parse CMS: %@", url); + if (cmsg) SecCmsMessageDestroy(cmsg); + }]; + } +} + +static void test_cms_parse_failure(void) { + NSArray*cmsURLs = [[NSBundle mainBundle] URLsForResourcesWithExtension:@".der" subdirectory:(NSString *)kSecTestCMSParseFailureResources]; + if ([cmsURLs count] > 0) { + [cmsURLs enumerateObjectsUsingBlock:^(NSURL * _Nonnull url, NSUInteger __unused idx, BOOL * __unused _Nonnull stop) { + SecCmsMessageRef cmsg = NULL; + NSData *cmsData = [NSData dataWithContentsOfURL:url]; + SecAsn1Item encoded_message = { [cmsData length], (uint8_t*)[cmsData bytes] }; + isnt(errSecSuccess, SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), + "Successfully parsed bad CMS: %@", url); + if (cmsg) SecCmsMessageDestroy(cmsg); + }]; + } +} + +int si_27_cms_parse(int argc, char *const *argv) +{ + int num_tests = 1; + NSArray*cmsURLs = [[NSBundle mainBundle] URLsForResourcesWithExtension:@".der" subdirectory:(NSString *)kSecTestCMSParseFailureResources]; + num_tests += [cmsURLs count]; + cmsURLs = [[NSBundle mainBundle] URLsForResourcesWithExtension:@".der" subdirectory:(NSString *)kSecTestCMSParseSuccessResources]; + num_tests += [cmsURLs count]; + + plan_tests(num_tests); + isnt(num_tests, 1, "no tests run!"); + + test_cms_parse_success(); + test_cms_parse_failure(); + + return 0; +} diff --git a/OSX/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c b/OSX/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c index a5e11478..499880ed 100644 --- a/OSX/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c +++ b/OSX/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c @@ -101,6 +101,9 @@ static void tests(void) "populate keychain"); free(keychain_name); + is(sqlite3_close_v2(db), SQLITE_OK, + "Should be able to close db");; + SecKeychainDbReset(NULL); int v_eighty = 80; @@ -131,7 +134,7 @@ static void tests(void) int si_30_keychain_upgrade(int argc, char *const *argv) { - plan_tests(8); + plan_tests(9); tests(); diff --git a/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.h b/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.h deleted file mode 100644 index f66bb236..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2017-2018 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _SECURITY_SI_32_SECTRUST_PINNING_REQUIRED_H_ -#define _SECURITY_SI_32_SECTRUST_PINNING_REQUIRED_H_ - -/* subject:/CN=profile.ess.apple.com/O=Apple Inc./ST=California/C=US */ -/* issuer :/CN=Test Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ -uint8_t _ids_test[]={ - 0x30,0x82,0x04,0x76,0x30,0x82,0x03,0x5E,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x24, - 0x1F,0x1C,0x82,0xF4,0x25,0x42,0xB4,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x72,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04, - 0x03,0x0C,0x23,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x65, - 0x72,0x76,0x65,0x72,0x20,0x41,0x75,0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74, - 0x69,0x6F,0x6E,0x20,0x43,0x41,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x0C, - 0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, - 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x38, - 0x30,0x38,0x30,0x37,0x30,0x31,0x30,0x35,0x33,0x37,0x5A,0x17,0x0D,0x31,0x39,0x30, - 0x39,0x30,0x36,0x30,0x31,0x30,0x35,0x33,0x37,0x5A,0x30,0x57,0x31,0x1E,0x30,0x1C, - 0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x70,0x72,0x6F,0x66,0x69,0x6C,0x65,0x2E,0x65, - 0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x13,0x30,0x11, - 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, - 0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, - 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, - 0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, - 0x82,0x01,0x01,0x00,0xDA,0xEE,0xCE,0x4F,0x0A,0x31,0xF5,0x6A,0x6C,0xD8,0xD8,0xF9, - 0x1E,0x4D,0x85,0x38,0x17,0x42,0x45,0xBA,0xF2,0x8C,0x16,0xC2,0xEC,0x29,0x84,0x88, - 0xC2,0xC2,0x45,0xCB,0x79,0xF6,0x7F,0x89,0x65,0x3D,0x98,0xED,0xE7,0x21,0xA8,0xAB, - 0x4C,0xE2,0x75,0x7C,0x5B,0x26,0x00,0xC4,0x4C,0x81,0xE4,0xFF,0xA4,0xBB,0xA6,0x0F, - 0x80,0x9D,0xD9,0xD5,0xA3,0xD2,0x5C,0xA1,0x25,0xE1,0x9F,0xB5,0x53,0xF3,0x31,0x3B, - 0xCB,0x55,0xC2,0x75,0xFB,0xC7,0x3B,0x3C,0x07,0x6B,0x29,0xAF,0x43,0x90,0x1E,0x9B, - 0xC3,0x47,0x0C,0x09,0xDF,0x07,0x9C,0xA8,0x12,0x3E,0x9E,0xFE,0x29,0xE7,0x11,0x06, - 0xA1,0x1D,0x8C,0xEA,0x99,0x73,0xD5,0x13,0x66,0x51,0x0D,0x3D,0x6B,0x67,0x38,0x68, - 0x04,0x40,0xE8,0x1E,0x50,0x56,0x59,0x77,0x5A,0xF3,0x12,0xAC,0x2B,0x93,0xF8,0xBC, - 0x87,0xA6,0x70,0x3F,0xB8,0x8F,0xE2,0xEC,0x38,0x5F,0xB4,0x73,0xE6,0x95,0x38,0xD1, - 0x31,0x16,0xFE,0xFF,0x77,0x01,0xD2,0xD0,0x2F,0xF4,0xF7,0x3A,0x21,0x5B,0xA8,0x36, - 0xC4,0xE4,0x58,0x26,0x3D,0x6F,0xFF,0xA0,0x39,0x45,0x83,0xCB,0x66,0xF5,0x4C,0xC6, - 0x43,0x67,0x1C,0x58,0x72,0x5B,0xCC,0xAA,0x15,0x91,0x4D,0xE6,0x24,0xF6,0x18,0xFE, - 0xF5,0xEF,0x75,0xB4,0x5B,0xF1,0x86,0x2F,0x67,0x0A,0x5B,0x7D,0x8E,0x22,0x1B,0x2F, - 0xFA,0xE2,0xB1,0x41,0x37,0x4D,0x26,0xD6,0x9B,0x13,0x66,0x5F,0xE5,0xCD,0x4B,0xC9, - 0x91,0x62,0xF9,0x98,0x8E,0x7F,0xB6,0x6F,0x7A,0xFF,0x95,0xF1,0x0B,0x1C,0x1F,0xFB, - 0xD1,0x49,0xB7,0xFD,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x29,0x30,0x82,0x01, - 0x25,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, - 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xA8,0xCA,0x7A,0x9B, - 0xA8,0x37,0x71,0x9E,0x3D,0xEC,0x5A,0xAB,0x66,0x2E,0xDC,0xD7,0x14,0x3D,0x7B,0xF2, - 0x30,0x52,0x06,0x03,0x55,0x1D,0x11,0x04,0x4B,0x30,0x49,0x82,0x18,0x6F,0x70,0x65, - 0x6E,0x6D,0x61,0x72,0x6B,0x65,0x74,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C, - 0x65,0x2E,0x63,0x6F,0x6D,0x82,0x16,0x69,0x64,0x65,0x6E,0x74,0x69,0x74,0x79,0x2E, - 0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x82,0x15,0x70, - 0x72,0x6F,0x66,0x69,0x6C,0x65,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65, - 0x2E,0x63,0x6F,0x6D,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06, - 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x49,0x06,0x03,0x55,0x1D,0x1F, - 0x04,0x42,0x30,0x40,0x30,0x3E,0xA0,0x3C,0xA0,0x3A,0x86,0x38,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E, - 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65,0x73,0x74,0x61,0x70, - 0x70,0x6C,0x65,0x73,0x65,0x72,0x76,0x65,0x72,0x61,0x75,0x74,0x68,0x63,0x61,0x31, - 0x2E,0x63,0x72,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x3F, - 0x0C,0x0D,0xC7,0x17,0x81,0x02,0x61,0x50,0x18,0xFC,0xAF,0xBD,0xA0,0xA8,0x4E,0x78, - 0xA7,0xFB,0xF1,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, - 0x02,0x05,0xA0,0x30,0x11,0x06,0x0B,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x1B, - 0x04,0x02,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x53,0x88,0x1A,0x2C,0x60,0xFB, - 0x15,0x08,0x83,0x06,0xE4,0xF7,0x23,0x38,0x50,0xA6,0xD3,0xA7,0xBD,0x06,0xB4,0xAF, - 0x87,0x4F,0x13,0xC6,0x1B,0x79,0x2C,0x80,0x30,0x7E,0x23,0x0D,0x4E,0x6A,0xC3,0x9B, - 0xF8,0x73,0x1E,0x7B,0xD7,0x14,0xB0,0x5F,0xA8,0xEC,0xB4,0x0D,0xBD,0x3B,0x40,0x87, - 0x9A,0x4D,0x1D,0x2D,0x8F,0x00,0xCE,0x72,0xDE,0xAF,0x2E,0x73,0x82,0x54,0xBA,0x0E, - 0x3A,0xC2,0xAB,0x7C,0x09,0xE8,0xBE,0x0B,0x26,0x0F,0xC3,0x80,0xCD,0x9C,0x85,0x09, - 0xA3,0xD3,0xB5,0xCE,0x7D,0x63,0xB3,0x33,0x32,0x06,0xD9,0xAE,0xA9,0x7D,0x1E,0x2F, - 0xF9,0x1B,0x60,0x3F,0x1F,0xFA,0x57,0x17,0xC6,0x5A,0x28,0x44,0x24,0x36,0xF4,0x77, - 0xE6,0x91,0x7D,0xED,0x45,0x28,0x59,0x3E,0xA1,0x03,0x3E,0x45,0x3F,0x41,0x8E,0x62, - 0x0A,0x21,0xD8,0x47,0xED,0xFA,0x53,0x4F,0x07,0x7D,0xF6,0xFC,0xE1,0x98,0xC0,0x0C, - 0xAA,0x68,0xD2,0xB7,0xCD,0x7D,0xF5,0x55,0xD7,0x56,0x55,0x78,0x56,0x80,0x8A,0x30, - 0x89,0x30,0x2C,0xA9,0x8A,0x71,0xD1,0x4E,0x05,0x4A,0x5E,0xDB,0x23,0x2F,0xC9,0xA1, - 0x45,0xF9,0xF1,0x16,0xE1,0x72,0xA5,0xD7,0xB1,0x32,0xB3,0x90,0x4B,0xF8,0x72,0xD6, - 0xF3,0x65,0x84,0x0F,0xB6,0x23,0x41,0x4D,0xE3,0xDD,0xC0,0x5B,0xB7,0xF8,0x1C,0xF2, - 0x1F,0xB5,0x5D,0xD0,0xFB,0xB9,0x7D,0x0D,0x34,0xC4,0x61,0x42,0x8E,0xD4,0xED,0x4C, - 0xA4,0x83,0x9C,0x8D,0xBA,0xE3,0x49,0x45,0x07,0xE4,0x0E,0x0E,0x01,0x10,0x93,0xCF, - 0x49,0x39,0x4C,0x1C,0x0A,0x88,0xC3,0x2E,0x7C,0x64, -}; - -/* subject:/CN=Test Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ -/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Test Apple Root CA */ -uint8_t _TestAppleServerAuth[]={ - 0x30,0x82,0x04,0x0F,0x30,0x82,0x02,0xF7,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x4B, - 0x28,0xA9,0x3B,0x57,0x8B,0xF6,0x26,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x67,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, - 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, - 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, - 0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69, - 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, - 0x74,0x79,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x54,0x65,0x73, - 0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30, - 0x1E,0x17,0x0D,0x31,0x35,0x30,0x36,0x30,0x38,0x30,0x37,0x35,0x38,0x34,0x35,0x5A, - 0x17,0x0D,0x32,0x39,0x30,0x33,0x30,0x38,0x30,0x31,0x35,0x33,0x30,0x34,0x5A,0x30, - 0x72,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04,0x03,0x0C,0x23,0x54,0x65,0x73,0x74, - 0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x41,0x75, - 0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x43,0x41,0x31, - 0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69,0x66, - 0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74, - 0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, - 0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, - 0x82,0x01,0x01,0x00,0xC5,0x7B,0x3F,0x48,0xD3,0x62,0x93,0x93,0x7C,0x0C,0x37,0x69, - 0xDB,0x28,0x05,0x40,0x12,0xD7,0x1F,0x0A,0xB8,0xC3,0xBA,0x24,0x39,0x22,0xDC,0x39, - 0x42,0x1F,0xFD,0x93,0x45,0x3C,0x23,0x0B,0x3E,0xB4,0x96,0xA6,0x55,0x59,0xBA,0xC4, - 0x99,0xE7,0x8A,0x5F,0x8F,0xAE,0x66,0xA7,0x28,0xE2,0x9E,0x68,0xD9,0xEC,0x52,0x67, - 0xFE,0xDD,0xBE,0x59,0xB4,0xAD,0x97,0x63,0x64,0xB0,0x08,0x3C,0xBB,0x6E,0xD1,0x29, - 0xD8,0x58,0xA1,0x99,0x6C,0x2F,0x2F,0xB3,0xF5,0x5C,0x59,0xCA,0xA1,0xE6,0x67,0x44, - 0x3C,0x13,0xB4,0xAE,0x0D,0x00,0xC7,0x53,0xB7,0xF5,0x61,0x58,0xD5,0xC8,0x42,0xFC, - 0xE2,0xFD,0xD5,0x39,0x18,0x80,0xE2,0x72,0xBC,0xF8,0xC3,0x9F,0xCB,0xD8,0x2F,0x83, - 0x40,0x9A,0x3E,0x55,0x5E,0x61,0xA9,0xC4,0x81,0x14,0x2B,0x7B,0x19,0x15,0xAD,0x84, - 0x5E,0x80,0xA8,0x67,0x79,0x05,0x16,0x48,0x5C,0xAE,0x1A,0x2B,0x59,0x9F,0xAA,0x62, - 0x0B,0x2F,0x57,0xCD,0xE8,0xA8,0x5D,0x38,0xAD,0x7C,0x90,0x79,0x50,0xAC,0x4D,0x13, - 0xA4,0xA7,0xF3,0x73,0xED,0xD6,0x93,0x45,0xDD,0xA8,0xC6,0xFE,0x03,0x28,0x4D,0x58, - 0xC1,0x8B,0xC1,0x03,0x0E,0xE7,0xDF,0x78,0xDD,0x21,0xC6,0x6D,0x1E,0xA0,0x38,0xD7, - 0xA7,0xD7,0x04,0x8C,0x7F,0xCA,0x15,0xEA,0x88,0xE9,0xAE,0x8D,0x46,0xE0,0x87,0x94, - 0x3E,0x8F,0x53,0x11,0x88,0x23,0x99,0x7B,0x9D,0xD8,0x69,0x1A,0x22,0xAE,0xB5,0x18, - 0xA5,0x9F,0xEA,0x71,0x31,0x0B,0x27,0x93,0x85,0x1D,0xF7,0xA0,0xC3,0x82,0x0A,0x3F, - 0xEE,0xD2,0xD4,0xEF,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xB3,0x30,0x81,0xB0,0x30, - 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xA8,0xCA,0x7A,0x9B,0xA8,0x37, - 0x71,0x9E,0x3D,0xEC,0x5A,0xAB,0x66,0x2E,0xDC,0xD7,0x14,0x3D,0x7B,0xF2,0x30,0x0F, - 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30, - 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x59,0xB8,0x2B,0x94, - 0x3A,0x1B,0xBA,0xF1,0x00,0xAE,0xEE,0x50,0x52,0x23,0x33,0xC9,0x59,0xC3,0x54,0x98, - 0x30,0x3B,0x06,0x03,0x55,0x1D,0x1F,0x04,0x34,0x30,0x32,0x30,0x30,0xA0,0x2E,0xA0, - 0x2C,0x86,0x2A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61, - 0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, - 0x2F,0x74,0x65,0x73,0x74,0x72,0x6F,0x6F,0x74,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06, - 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x10,0x06, - 0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x02,0x0C,0x04,0x02,0x05,0x00,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, - 0x01,0x01,0x00,0x11,0x24,0x61,0x2B,0x7C,0x5E,0x67,0x29,0x94,0x14,0x19,0x16,0xD5, - 0xD4,0x7A,0xEE,0x53,0x1A,0x64,0xA2,0x6A,0x2B,0x04,0xE6,0x2C,0xA1,0x08,0xBA,0xCA, - 0x81,0xF5,0x28,0x2A,0xCE,0xD5,0x6B,0x52,0xAC,0xE7,0xBD,0xB3,0x23,0xB9,0x67,0x2C, - 0xC7,0x9E,0x61,0xA1,0xD9,0x6C,0x3F,0x4F,0x55,0xD4,0x75,0xAF,0x44,0xAD,0xF8,0xCE, - 0x58,0xA7,0x2E,0xF8,0x6A,0xF0,0x76,0x51,0x31,0x75,0x4C,0xCA,0xF6,0xC3,0x59,0xC7, - 0xE6,0xAE,0x4A,0x20,0x4E,0x5F,0xB9,0xAB,0x1C,0xB6,0x36,0x25,0x60,0x02,0x32,0x47, - 0x7D,0xA0,0xE2,0x36,0xB3,0x3B,0x40,0x20,0x9E,0x38,0x40,0x1C,0x7E,0x83,0x35,0x9C, - 0x9D,0x8B,0xD1,0xF9,0xEA,0xD4,0xF2,0x83,0xE0,0x30,0xEA,0xC3,0xEE,0x3D,0x76,0x98, - 0x9E,0x0A,0x07,0xB5,0xB6,0xFC,0x38,0x32,0xF6,0x41,0xEF,0x8E,0x25,0x2C,0xE3,0xC7, - 0xA7,0xAD,0x88,0x77,0x4D,0x10,0x1D,0x67,0x50,0x64,0xB0,0x02,0x04,0x2C,0xEA,0x4C, - 0x81,0x33,0xBE,0xF3,0xCD,0x43,0x63,0x97,0x44,0xDF,0xBB,0xC6,0xE2,0x37,0x32,0xF1, - 0xE4,0x19,0x1F,0xF5,0xAE,0xDA,0x05,0xC4,0x0B,0xFA,0x30,0xCA,0x77,0x78,0x65,0xD6, - 0x4F,0x2D,0xFE,0x63,0xD3,0x4C,0x3D,0xA9,0x0E,0xC4,0x0F,0xD6,0xCC,0x2A,0x2D,0x06, - 0x9B,0xDE,0x94,0xF6,0x22,0x2E,0x89,0xCB,0x68,0x4E,0xDE,0x79,0xE5,0x83,0xDE,0x64, - 0x63,0xE9,0x77,0x88,0xF1,0x57,0xF2,0x5C,0xB4,0x77,0x3A,0xC8,0x1F,0x6D,0x80,0x4C, - 0x8B,0x68,0xA5,0xFA,0xAD,0x1F,0x5C,0x8C,0x50,0x27,0xED,0xF7,0x43,0x68,0xAD,0x34, - 0x5E,0xF6,0x74, -}; - -/* subject:/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Test Apple Root CA */ -/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Test Apple Root CA */ -uint8_t _TestAppleRootCA[]={ - 0x30,0x82,0x04,0xCC,0x30,0x82,0x03,0xB4,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x3D, - 0x00,0x4B,0x90,0x3E,0xDE,0xE0,0xD0,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x67,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, - 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, - 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, - 0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69, - 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, - 0x74,0x79,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x54,0x65,0x73, - 0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30, - 0x1E,0x17,0x0D,0x31,0x35,0x30,0x34,0x32,0x32,0x30,0x32,0x31,0x35,0x34,0x38,0x5A, - 0x17,0x0D,0x33,0x35,0x30,0x32,0x30,0x39,0x32,0x31,0x34,0x30,0x33,0x36,0x5A,0x30, - 0x67,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70, - 0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, - 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x1B,0x30,0x19,0x06, - 0x03,0x55,0x04,0x03,0x0C,0x12,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65, - 0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00, - 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC7,0xD1,0x43,0x53,0x7F,0x0D,0x88, - 0x6B,0xE6,0xB1,0x67,0x9D,0xEE,0x67,0xB6,0xE7,0x77,0x12,0x81,0xC4,0xDF,0x24,0x6B, - 0x7A,0x75,0x24,0xF7,0x01,0x09,0xCE,0x34,0x92,0xF5,0x38,0x08,0x42,0x7E,0xEC,0x9D, - 0xF2,0x5D,0x38,0x91,0xB4,0x93,0x98,0x35,0x11,0x3C,0x98,0x00,0x77,0xD9,0xD7,0xF3, - 0x4A,0xF8,0xF0,0xBC,0xEB,0x97,0x5D,0x4B,0x61,0x2E,0xFB,0xC5,0xCC,0x68,0xB7,0x6D, - 0x69,0x10,0xCC,0xA5,0x61,0x78,0xA8,0x81,0x02,0x9E,0xE7,0x63,0xC5,0xFF,0x29,0x22, - 0x82,0x68,0xAA,0xAA,0x0E,0xFB,0xA9,0xD8,0x16,0x73,0x25,0xBF,0x9D,0x08,0x62,0x2F, - 0x78,0x04,0xF6,0xF6,0x44,0x07,0x37,0x6E,0x99,0x1B,0x93,0xD8,0x7F,0xEE,0x72,0xDE, - 0xE8,0x32,0xF6,0x6D,0x78,0x04,0xA0,0xA8,0x21,0x26,0x8A,0x32,0xE3,0xB1,0x65,0x85, - 0xA1,0x7B,0x1A,0xA9,0x02,0xB2,0xBB,0xEE,0xDD,0xDD,0x8F,0x41,0x49,0xC8,0x3F,0xDC, - 0x1E,0xDF,0x21,0xA3,0x95,0x99,0xBB,0xFC,0x29,0xBA,0x40,0x43,0xB9,0x1C,0xCD,0xC9, - 0x21,0x45,0x73,0xAD,0xFF,0xFD,0xA2,0x6C,0x5C,0x3B,0x1C,0x37,0x91,0x34,0x8E,0x5C, - 0xD3,0xD5,0x03,0x58,0x28,0xC7,0xF2,0x76,0x6F,0x11,0xC0,0xB5,0xBD,0x7E,0xEF,0x23, - 0xB3,0x3D,0xB8,0xBD,0x38,0x66,0x8C,0xF2,0x78,0x95,0xC1,0x8B,0x32,0x65,0x3A,0x9B, - 0x49,0x1A,0x5C,0x41,0x3C,0xC6,0x85,0x50,0xEC,0x85,0xF0,0x59,0x17,0x81,0xE8,0x96, - 0xE8,0x6A,0xCC,0xB3,0xC7,0x46,0xBF,0x81,0x48,0xD1,0x09,0x1B,0xBC,0x73,0x1E,0xD7, - 0xE8,0x27,0xA8,0x49,0x48,0xA2,0x1C,0x41,0x1D,0x02,0x03,0x01,0x00,0x01,0xA3,0x82, - 0x01,0x7A,0x30,0x82,0x01,0x76,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, - 0x14,0x59,0xB8,0x2B,0x94,0x3A,0x1B,0xBA,0xF1,0x00,0xAE,0xEE,0x50,0x52,0x23,0x33, - 0xC9,0x59,0xC3,0x54,0x98,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, - 0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, - 0x16,0x80,0x14,0x59,0xB8,0x2B,0x94,0x3A,0x1B,0xBA,0xF1,0x00,0xAE,0xEE,0x50,0x52, - 0x23,0x33,0xC9,0x59,0xC3,0x54,0x98,0x30,0x82,0x01,0x11,0x06,0x03,0x55,0x1D,0x20, - 0x04,0x82,0x01,0x08,0x30,0x82,0x01,0x04,0x30,0x82,0x01,0x00,0x06,0x09,0x2A,0x86, - 0x48,0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF2,0x30,0x2A,0x06,0x08,0x2B,0x06, - 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F, - 0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70, - 0x70,0x6C,0x65,0x63,0x61,0x2F,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05, - 0x07,0x02,0x02,0x30,0x81,0xB6,0x0C,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63, - 0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66, - 0x69,0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72, - 0x74,0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70, - 0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65, - 0x6E,0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61, - 0x6E,0x64,0x61,0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20, - 0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73, - 0x65,0x2C,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70, - 0x6F,0x6C,0x69,0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66, - 0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65, - 0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x0E,0x06,0x03, - 0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00, - 0x10,0x5E,0x6C,0x69,0xFC,0xA6,0x0F,0xE2,0x09,0xD5,0x94,0x90,0xA6,0x7C,0x22,0xDC, - 0xEE,0xB0,0x8F,0x24,0x22,0x4F,0xB3,0x67,0xDB,0x32,0xB0,0xD6,0x24,0x87,0xE6,0xF3, - 0xEA,0x9E,0xD0,0x95,0x75,0xAA,0xA7,0x08,0xFF,0xB0,0x35,0xD7,0x1F,0xA3,0xBF,0x89, - 0x55,0x0C,0x1C,0xA4,0xD0,0xF8,0x00,0x17,0x44,0x94,0x36,0x63,0x3B,0x83,0xFE,0x4E, - 0xE5,0xB3,0xEC,0x7B,0x7D,0xCE,0xFE,0xA9,0x54,0xED,0xBB,0x12,0xA6,0x72,0x2B,0xB3, - 0x48,0x00,0xC7,0x8E,0xF5,0x5B,0x68,0xC9,0x24,0x22,0x7F,0xA1,0x4D,0xFC,0x54,0xD9, - 0xD0,0x5D,0x82,0x53,0x71,0x29,0x66,0xCF,0x0F,0x6D,0x32,0xA6,0x3F,0xAE,0x54,0x27, - 0xC2,0x8C,0x12,0x4C,0xF0,0xD6,0xC1,0x80,0x75,0xC3,0x33,0x19,0xD1,0x8B,0x58,0xE6, - 0x00,0x69,0x76,0xE7,0xE5,0x3D,0x47,0xF9,0xC0,0x9C,0xE7,0x19,0x1E,0x95,0xBC,0x52, - 0x15,0xCE,0x94,0xF8,0x30,0x14,0x0B,0x39,0x0E,0x8B,0xAF,0x29,0x30,0x56,0xAF,0x5A, - 0x28,0xAC,0xE1,0x0F,0x51,0x76,0x76,0x9A,0xE7,0xB9,0x7D,0xA3,0x30,0xE8,0xE3,0x71, - 0x15,0xE8,0xBF,0x0D,0x4F,0x12,0x9B,0x65,0xAB,0xEF,0xA4,0xE9,0x42,0xF0,0xD2,0x4D, - 0x20,0x55,0x29,0x88,0x58,0x5C,0x82,0x67,0x63,0x20,0x50,0xC6,0xCA,0x04,0xE8,0xBC, - 0x3D,0x93,0x06,0x21,0xB2,0xC0,0xBF,0x53,0x1E,0xE1,0x8B,0x48,0xA9,0xB9,0xD7,0xE6, - 0x5F,0x4E,0x5A,0x2F,0x43,0xAC,0x35,0xBD,0x26,0x60,0x2F,0x01,0xD5,0x86,0x6B,0x64, - 0xFA,0x67,0x05,0x44,0x55,0x83,0x5B,0x93,0x9C,0x7C,0xA7,0x26,0x4E,0x02,0x2B,0x48, -}; - - -#endif /* _SECURITY_SI_32_SECTRUST_PINNING_REQUIRED_H_ */ diff --git a/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.m b/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.m deleted file mode 100644 index 4e44d314..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.m +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2017-2018 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#import - -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -#include "si-32-sectrust-pinning-required.h" - - -static NSArray *certs = nil; -static NSArray *root = nil; -static NSDate *verifyDate = nil; - -static void setup_globals(void) { - SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _ids_test, sizeof(_ids_test)); - SecCertificateRef intermediate = SecCertificateCreateWithBytes(NULL, _TestAppleServerAuth, sizeof(_TestAppleServerAuth)); - SecCertificateRef rootcert = SecCertificateCreateWithBytes(NULL, _TestAppleRootCA, sizeof(_TestAppleRootCA)); - - certs = @[(__bridge id)leaf,(__bridge id)intermediate]; - root = @[(__bridge id)rootcert]; - verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:560000000.0]; //September 30, 2018 at 4:33:20 AM PDT - - CFReleaseNull(leaf); - CFReleaseNull(intermediate); - CFReleaseNull(rootcert); -} - -static SecTrustResultType test_with_policy_exception(SecPolicyRef CF_CONSUMED policy, bool set_exception) -{ - SecTrustRef trust = NULL; - SecTrustResultType trustResult = kSecTrustResultInvalid; - - require_noerr_quiet(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), cleanup); - require_noerr_quiet(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)root), cleanup); - require_noerr_quiet(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), cleanup); - if (set_exception) { - SecTrustSetPinningException(trust); - } - require_noerr_quiet(SecTrustEvaluate(trust, &trustResult), cleanup); - -cleanup: - CFReleaseNull(policy); - CFReleaseNull(trust); - return trustResult; -} - -static SecTrustResultType test_with_policy(SecPolicyRef CF_CONSUMED policy) { - return test_with_policy_exception(policy, false); -} - - -/* Technically, this feature works by reading the info plist of the caller. We'll fake it here by - * setting the policy option for requiring pinning. */ -static void tests(void) -{ - SecPolicyRef policy = NULL; - - policy = SecPolicyCreateSSL(true, CFSTR("openmarket.ess.apple.com")); - SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); - is(test_with_policy(policy), kSecTrustResultRecoverableTrustFailure, "Unpinned connection succeeeded when pinning required"); - - policy = SecPolicyCreateAppleIDSServiceContext(CFSTR("openmarket.ess.apple.com"), NULL); - SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); - is(test_with_policy(policy), kSecTrustResultUnspecified, "Policy pinned connection failed when pinning required"); - - policy = SecPolicyCreateSSL(true, CFSTR("profile.ess.apple.com")); - SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); - is(test_with_policy(policy), kSecTrustResultUnspecified, "Systemwide hostname pinned connection failed when pinning required"); - - NSDictionary *policy_properties = @{ - (__bridge NSString *)kSecPolicyName : @"openmarket.ess.apple.com", - (__bridge NSString *)kSecPolicyPolicyName : @"IDS", - }; - policy = SecPolicyCreateWithProperties(kSecPolicyAppleSSL, (__bridge CFDictionaryRef)policy_properties); - SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); - is(test_with_policy(policy), kSecTrustResultUnspecified, "Systemwide policy name pinned connection failed when pinning required"); - - policy = SecPolicyCreateSSL(true, CFSTR("openmarket.ess.apple.com")); - SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); - is(test_with_policy_exception(policy, true), kSecTrustResultUnspecified, "Unpinned connection failed when pinning exception set"); - - /* can I write an effective test for charles?? */ -} - -int si_32_sectrust_pinning_required(int argc, char *const *argv) -{ - plan_tests(5); - setup_globals(); - tests(); - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-34-cms-timestamp.m b/OSX/sec/Security/Regressions/secitem/si-34-cms-timestamp.m index af261c72..d06ddf5b 100644 --- a/OSX/sec/Security/Regressions/secitem/si-34-cms-timestamp.m +++ b/OSX/sec/Security/Regressions/secitem/si-34-cms-timestamp.m @@ -174,18 +174,16 @@ exit: CFReleaseNull(identity); } -static int ping_host(char *host_name){ - +static int ping_host(char *host_name) { struct sockaddr_in pin; struct hostent *nlp_host; + struct in_addr addr; int sd; - int port; - int retries = 5; + int port = 80; + int retries = 5; // tries 5 times then gived up + char **h_addr_list = NULL; - port=80; - - //tries 5 times then give up - while ((nlp_host=gethostbyname(host_name))==0 && retries--){ + while ((nlp_host=gethostbyname(host_name)) == 0 && retries--) { printf("Resolve Error! (%s) %d\n", host_name, h_errno); sleep(1); } @@ -196,20 +194,23 @@ static int ping_host(char *host_name){ bzero(&pin,sizeof(pin)); pin.sin_family=AF_INET; pin.sin_addr.s_addr=htonl(INADDR_ANY); - pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; + h_addr_list = malloc(nlp_host->h_length * sizeof(char *)); + memcpy(h_addr_list, nlp_host->h_addr_list, nlp_host->h_length * sizeof(char *)); + memcpy(&addr, h_addr_list[0], sizeof(struct in_addr)); + pin.sin_addr.s_addr=addr.s_addr; pin.sin_port=htons(port); sd=socket(AF_INET,SOCK_STREAM,0); - if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){ + if (connect(sd,(struct sockaddr*)&pin,sizeof(pin)) == -1) { printf("connect error! (%s) %d\n", host_name, errno); close(sd); + free(h_addr_list); return 0; } - else{ - close(sd); - return 1; - } + close(sd); + free(h_addr_list); + return 1; } int si_34_cms_timestamp(int argc, char * const *argv) { diff --git a/OSX/sec/Security/Regressions/secitem/si-66-smime.c b/OSX/sec/Security/Regressions/secitem/si-66-smime.c index 0ad24d90..6e61e2db 100644 --- a/OSX/sec/Security/Regressions/secitem/si-66-smime.c +++ b/OSX/sec/Security/Regressions/secitem/si-66-smime.c @@ -1805,6 +1805,79 @@ unsigned char __9148843_bin[] = { }; unsigned int __9148843_bin_len = 4326; +/* subject:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root */ +/* issuer :/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root */ +const uint8_t __9148843_root[] = { + 0x30,0x82,0x04,0x36,0x30,0x82,0x03,0x1E,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x01, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30, + 0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x53,0x45,0x31,0x14, + 0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x41,0x64,0x64,0x54,0x72,0x75,0x73, + 0x74,0x20,0x41,0x42,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C, + 0x20,0x54,0x54,0x50,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x22,0x30,0x20, + 0x06,0x03,0x55,0x04,0x03,0x13,0x19,0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x20, + 0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x43,0x41,0x20,0x52,0x6F,0x6F,0x74, + 0x30,0x1E,0x17,0x0D,0x30,0x30,0x30,0x35,0x33,0x30,0x31,0x30,0x34,0x38,0x33,0x38, + 0x5A,0x17,0x0D,0x32,0x30,0x30,0x35,0x33,0x30,0x31,0x30,0x34,0x38,0x33,0x38,0x5A, + 0x30,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x53,0x45,0x31, + 0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x41,0x64,0x64,0x54,0x72,0x75, + 0x73,0x74,0x20,0x41,0x42,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D, + 0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61, + 0x6C,0x20,0x54,0x54,0x50,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x22,0x30, + 0x20,0x06,0x03,0x55,0x04,0x03,0x13,0x19,0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74, + 0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x43,0x41,0x20,0x52,0x6F,0x6F, + 0x74,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, + 0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01, + 0x01,0x00,0xB7,0xF7,0x1A,0x33,0xE6,0xF2,0x00,0x04,0x2D,0x39,0xE0,0x4E,0x5B,0xED, + 0x1F,0xBC,0x6C,0x0F,0xCD,0xB5,0xFA,0x23,0xB6,0xCE,0xDE,0x9B,0x11,0x33,0x97,0xA4, + 0x29,0x4C,0x7D,0x93,0x9F,0xBD,0x4A,0xBC,0x93,0xED,0x03,0x1A,0xE3,0x8F,0xCF,0xE5, + 0x6D,0x50,0x5A,0xD6,0x97,0x29,0x94,0x5A,0x80,0xB0,0x49,0x7A,0xDB,0x2E,0x95,0xFD, + 0xB8,0xCA,0xBF,0x37,0x38,0x2D,0x1E,0x3E,0x91,0x41,0xAD,0x70,0x56,0xC7,0xF0,0x4F, + 0x3F,0xE8,0x32,0x9E,0x74,0xCA,0xC8,0x90,0x54,0xE9,0xC6,0x5F,0x0F,0x78,0x9D,0x9A, + 0x40,0x3C,0x0E,0xAC,0x61,0xAA,0x5E,0x14,0x8F,0x9E,0x87,0xA1,0x6A,0x50,0xDC,0xD7, + 0x9A,0x4E,0xAF,0x05,0xB3,0xA6,0x71,0x94,0x9C,0x71,0xB3,0x50,0x60,0x0A,0xC7,0x13, + 0x9D,0x38,0x07,0x86,0x02,0xA8,0xE9,0xA8,0x69,0x26,0x18,0x90,0xAB,0x4C,0xB0,0x4F, + 0x23,0xAB,0x3A,0x4F,0x84,0xD8,0xDF,0xCE,0x9F,0xE1,0x69,0x6F,0xBB,0xD7,0x42,0xD7, + 0x6B,0x44,0xE4,0xC7,0xAD,0xEE,0x6D,0x41,0x5F,0x72,0x5A,0x71,0x08,0x37,0xB3,0x79, + 0x65,0xA4,0x59,0xA0,0x94,0x37,0xF7,0x00,0x2F,0x0D,0xC2,0x92,0x72,0xDA,0xD0,0x38, + 0x72,0xDB,0x14,0xA8,0x45,0xC4,0x5D,0x2A,0x7D,0xB7,0xB4,0xD6,0xC4,0xEE,0xAC,0xCD, + 0x13,0x44,0xB7,0xC9,0x2B,0xDD,0x43,0x00,0x25,0xFA,0x61,0xB9,0x69,0x6A,0x58,0x23, + 0x11,0xB7,0xA7,0x33,0x8F,0x56,0x75,0x59,0xF5,0xCD,0x29,0xD7,0x46,0xB7,0x0A,0x2B, + 0x65,0xB6,0xD3,0x42,0x6F,0x15,0xB2,0xB8,0x7B,0xFB,0xEF,0xE9,0x5D,0x53,0xD5,0x34, + 0x5A,0x27,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xDC,0x30,0x81,0xD9,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xAD,0xBD,0x98,0x7A,0x34,0xB4,0x26,0xF7, + 0xFA,0xC4,0x26,0x54,0xEF,0x03,0xBD,0xE0,0x24,0xCB,0x54,0x1A,0x30,0x0B,0x06,0x03, + 0x55,0x1D,0x0F,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13, + 0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x81,0x99,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x81,0x91,0x30,0x81,0x8E,0x80,0x14,0xAD,0xBD,0x98,0x7A,0x34,0xB4, + 0x26,0xF7,0xFA,0xC4,0x26,0x54,0xEF,0x03,0xBD,0xE0,0x24,0xCB,0x54,0x1A,0xA1,0x73, + 0xA4,0x71,0x30,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x53, + 0x45,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x41,0x64,0x64,0x54, + 0x72,0x75,0x73,0x74,0x20,0x41,0x42,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x13,0x1D,0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x20,0x45,0x78,0x74,0x65,0x72, + 0x6E,0x61,0x6C,0x20,0x54,0x54,0x50,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31, + 0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x03,0x13,0x19,0x41,0x64,0x64,0x54,0x72,0x75, + 0x73,0x74,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x43,0x41,0x20,0x52, + 0x6F,0x6F,0x74,0x82,0x01,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xB0,0x9B,0xE0,0x85,0x25,0xC2, + 0xD6,0x23,0xE2,0x0F,0x96,0x06,0x92,0x9D,0x41,0x98,0x9C,0xD9,0x84,0x79,0x81,0xD9, + 0x1E,0x5B,0x14,0x07,0x23,0x36,0x65,0x8F,0xB0,0xD8,0x77,0xBB,0xAC,0x41,0x6C,0x47, + 0x60,0x83,0x51,0xB0,0xF9,0x32,0x3D,0xE7,0xFC,0xF6,0x26,0x13,0xC7,0x80,0x16,0xA5, + 0xBF,0x5A,0xFC,0x87,0xCF,0x78,0x79,0x89,0x21,0x9A,0xE2,0x4C,0x07,0x0A,0x86,0x35, + 0xBC,0xF2,0xDE,0x51,0xC4,0xD2,0x96,0xB7,0xDC,0x7E,0x4E,0xEE,0x70,0xFD,0x1C,0x39, + 0xEB,0x0C,0x02,0x51,0x14,0x2D,0x8E,0xBD,0x16,0xE0,0xC1,0xDF,0x46,0x75,0xE7,0x24, + 0xAD,0xEC,0xF4,0x42,0xB4,0x85,0x93,0x70,0x10,0x67,0xBA,0x9D,0x06,0x35,0x4A,0x18, + 0xD3,0x2B,0x7A,0xCC,0x51,0x42,0xA1,0x7A,0x63,0xD1,0xE6,0xBB,0xA1,0xC5,0x2B,0xC2, + 0x36,0xBE,0x13,0x0D,0xE6,0xBD,0x63,0x7E,0x79,0x7B,0xA7,0x09,0x0D,0x40,0xAB,0x6A, + 0xDD,0x8F,0x8A,0xC3,0xF6,0xF6,0x8C,0x1A,0x42,0x05,0x51,0xD4,0x45,0xF5,0x9F,0xA7, + 0x62,0x21,0x68,0x15,0x20,0x43,0x3C,0x99,0xE7,0x7C,0xBD,0x24,0xD8,0xA9,0x91,0x17, + 0x73,0x88,0x3F,0x56,0x1B,0x31,0x38,0x18,0xB4,0x71,0x0F,0x9A,0xCD,0xC8,0x0E,0x9E, + 0x8E,0x2E,0x1B,0xE1,0x8C,0x98,0x83,0xCB,0x1F,0x31,0xF1,0x44,0x4C,0xC6,0x04,0x73, + 0x49,0x76,0x60,0x0F,0xC7,0xF8,0xBD,0x17,0x80,0x6B,0x2E,0xE9,0xCC,0x4C,0x0E,0x5A, + 0x9A,0x79,0x0F,0x20,0x0A,0x2E,0xD5,0x9E,0x63,0x26,0x1E,0x55,0x92,0x94,0xD8,0x82, + 0x17,0x5A,0x7B,0xD0,0xBC,0xC7,0x8F,0x4E,0x86,0x04, +}; + unsigned char __9639569_bin[] = { 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x02, 0x31, 0x82, 0x02, 0x60, @@ -2627,13 +2700,18 @@ static void tests(void) __9148843_txt, __9148843_txt_len, kCFAllocatorNull); ok_status(SecCMSVerifySignedData(sig, eml, policy, &trust, NULL, NULL, NULL), "validate message, not signer"); - // set date to Thu, 17 Mar 2011 00:59:48 +0000 + // SecCMS sets date to Thu, 17 Mar 2011 00:59:48 +0000 + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, __9148843_root, sizeof(__9148843_root)); + CFArrayRef anchor = CFArrayCreate(NULL, (const void **)&root, 1, &kCFTypeArrayCallBacks); + ok_status(SecTrustSetAnchorCertificates(trust, anchor)); ok_status(SecTrustEvaluate(trust, &result), "validate signer"); is_status(result, kSecTrustResultUnspecified, "valid"); CFReleaseNull(eml); CFReleaseNull(sig); CFReleaseNull(policy); CFReleaseNull(trust); + CFReleaseNull(root); + CFReleaseNull(anchor); CFDataRef msg = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, __9639569_bin, __9639569_bin_len, kCFAllocatorNull); CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0); diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist.c b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist.c deleted file mode 100644 index e263aff7..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "si-67-sectrust-blocklist/Global Trustee.cer.h" -#include "si-67-sectrust-blocklist/login.yahoo.com.1.cer.h" -#include "si-67-sectrust-blocklist/UTN-USERFirst-Hardware.cer.h" -#include "si-67-sectrust-blocklist/login.yahoo.com.2.cer.h" -#include "si-67-sectrust-blocklist/addons.mozilla.org.cer.h" -#include "si-67-sectrust-blocklist/login.yahoo.com.cer.h" -#include "si-67-sectrust-blocklist/login.live.com.cer.h" -#include "si-67-sectrust-blocklist/mail.google.com.cer.h" -#include "si-67-sectrust-blocklist/login.skype.com.cer.h" -#include "si-67-sectrust-blocklist/www.google.com.cer.h" - -#include "shared_regressions.h" - -static void validate_one_cert(uint8_t *data, size_t len, int chain_length, SecTrustResultType trust_result) -{ - SecTrustRef trust; - SecCertificateRef cert; - SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); - CFArrayRef certs; - - isnt(cert = SecCertificateCreateWithBytes(NULL, data, len), - NULL, "create cert"); - certs = CFArrayCreate(NULL, (const void **)&cert, 1, NULL); - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "create trust with single cert"); - //CFDateRef date = CFDateCreate(NULL, 1301008576); - //ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - //CFRelease(date); - - SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is(SecTrustGetCertificateCount(trust), chain_length, "cert count"); - is_status(trustResult, trust_result, "correct trustResult"); - CFRelease(trust); - CFRelease(policy); - CFRelease(certs); - CFRelease(cert); -} - -static void tests(void) -{ - validate_one_cert(Global_Trustee_cer, sizeof(Global_Trustee_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_yahoo_com_1_cer, sizeof(login_yahoo_com_1_cer), 2, kSecTrustResultFatalTrustFailure); - /* this is the root, which isn't ok for ssl and fails here, but at the - same time it proves that kSecTrustResultFatalTrustFailure isn't - returned for policy failures that aren't blocklisting */ - validate_one_cert(login_yahoo_com_2_cer, sizeof(login_yahoo_com_2_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(addons_mozilla_org_cer, sizeof(addons_mozilla_org_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_yahoo_com_cer, sizeof(login_yahoo_com_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_live_com_cer, sizeof(login_live_com_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(mail_google_com_cer, sizeof(mail_google_com_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_skype_com_cer, sizeof(login_skype_com_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(www_google_com_cer, sizeof(www_google_com_cer), 2, kSecTrustResultFatalTrustFailure); -} - -static int ping_host(char *host_name){ - - struct sockaddr_in pin; - struct hostent *nlp_host; - int sd; - int port; - int retries = 5; - - port=80; - - while ((nlp_host=gethostbyname(host_name))==0 && retries--){ - printf("Resolve Error! (%s) %d\n", host_name, h_errno); - sleep(1); - } - - if(nlp_host==0) - return 0; - - bzero(&pin,sizeof(pin)); - pin.sin_family=AF_INET; - pin.sin_addr.s_addr=htonl(INADDR_ANY); - pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; - pin.sin_port=htons(port); - - sd=socket(AF_INET,SOCK_STREAM,0); - - if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){ - printf("connect error! (%s) %d\n", host_name, errno); - close(sd); - return 0; - } - else{ - close(sd); - return 1; - } -} - -int si_67_sectrust_blocklist(int argc, char *const *argv) -{ - char *hosts[] = { - "EVSecure-ocsp.verisign.com", - "EVIntl-ocsp.verisign.com", - "EVIntl-aia.verisign.com", - "ocsp.comodoca.com", - "crt.comodoca.com", - }; - - unsigned host_cnt = 0; - - plan_tests(45); - - for (host_cnt = 0; host_cnt < sizeof(hosts)/sizeof(hosts[0]); host_cnt ++) - if(ping_host(hosts[host_cnt]) == 0){ - printf("Accessing specific server (%s) failed, check the network!\n", hosts[host_cnt]); - return 0; - } - - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/Global Trustee.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/Global Trustee.cer.h deleted file mode 100644 index 4253e078..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/Global Trustee.cer.h +++ /dev/null @@ -1,150 +0,0 @@ -unsigned char Global_Trustee_cer[] = { - 0x30, 0x82, 0x06, 0xdd, 0x30, 0x82, 0x05, 0xc5, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xd8, 0xf3, 0x5f, 0x4e, 0xb7, 0x87, 0x2b, 0x2d, - 0xab, 0x06, 0x92, 0xe3, 0x15, 0x38, 0x2f, 0xb0, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xe3, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x0e, 0x30, 0x0c, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x05, 0x54, 0x61, 0x6d, 0x70, 0x61, 0x31, - 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, 0x53, 0x65, - 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, 0x31, 0x30, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x47, - 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, - 0x65, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0e, - 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, - 0x65, 0x65, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, - 0x1f, 0x48, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, - 0x54, 0x49, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, - 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, - 0x6e, 0x75, 0x6d, 0x53, 0x53, 0x4c, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x0e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, - 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x30, 0x82, 0x02, 0x22, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, - 0x82, 0x02, 0x01, 0x00, 0xd9, 0x74, 0xf2, 0xaa, 0x41, 0x1d, 0xdf, 0xf5, - 0xc2, 0x16, 0x43, 0x49, 0x5c, 0x29, 0xbf, 0xb6, 0x89, 0x74, 0x29, 0xbc, - 0x9c, 0x8d, 0x0c, 0x46, 0x4f, 0x59, 0x7e, 0xb2, 0x41, 0x17, 0x66, 0x34, - 0x0c, 0x65, 0x89, 0xe1, 0x6c, 0x25, 0xe3, 0x86, 0x0a, 0x9e, 0x22, 0x45, - 0x22, 0x8c, 0xdd, 0x9d, 0xe6, 0xa3, 0x95, 0xde, 0xdc, 0x88, 0x02, 0x55, - 0x5c, 0xe3, 0x5b, 0x91, 0x75, 0xeb, 0x26, 0x69, 0x63, 0xb9, 0x2e, 0xc6, - 0xca, 0x2e, 0x27, 0xdf, 0x88, 0xba, 0x02, 0x20, 0x6e, 0xfe, 0xb9, 0x0b, - 0x29, 0xd7, 0xa7, 0xd6, 0xd7, 0x48, 0x1a, 0x1c, 0xce, 0xdd, 0x1f, 0xa9, - 0x27, 0x0e, 0x62, 0x4f, 0xa1, 0x96, 0x1e, 0xdd, 0x54, 0x3a, 0x34, 0x63, - 0x4a, 0x76, 0xf5, 0x77, 0x7d, 0x59, 0x67, 0xd8, 0x10, 0xd4, 0xb5, 0x0f, - 0x3a, 0x43, 0x22, 0x98, 0xdb, 0xf4, 0x09, 0xc4, 0x0a, 0x70, 0xce, 0xdd, - 0x90, 0xd4, 0x2f, 0xef, 0x74, 0x13, 0xc3, 0xcd, 0xc2, 0x89, 0x39, 0x62, - 0x15, 0x9d, 0xe6, 0x74, 0xa8, 0xe8, 0x9b, 0xf0, 0x63, 0x6e, 0x9c, 0x89, - 0xb6, 0x0e, 0xad, 0x9b, 0xf7, 0xcc, 0x82, 0xe8, 0xe8, 0x2d, 0xb8, 0x0b, - 0xda, 0x22, 0xec, 0x49, 0x85, 0x07, 0x88, 0x99, 0x98, 0x3f, 0xf4, 0x74, - 0xa9, 0x09, 0xf7, 0x81, 0x7c, 0x97, 0x0b, 0x59, 0x99, 0x18, 0x72, 0x8b, - 0xdb, 0x94, 0x82, 0x2b, 0xa7, 0xe8, 0xaa, 0x6b, 0x97, 0xbf, 0x88, 0x7e, - 0x75, 0xb0, 0x8b, 0x45, 0x45, 0x0c, 0xc7, 0xa8, 0x09, 0xea, 0x1b, 0x41, - 0x58, 0x30, 0x3b, 0x5f, 0x78, 0x65, 0x15, 0x34, 0xd2, 0xe4, 0x3c, 0x34, - 0x0d, 0x1d, 0xd8, 0x64, 0x3c, 0x8a, 0xa5, 0x56, 0x49, 0x99, 0x28, 0x2d, - 0x4b, 0xf2, 0xcf, 0xcd, 0xd9, 0x6e, 0x49, 0x64, 0x9b, 0xa9, 0x79, 0x90, - 0x77, 0x55, 0xa9, 0x08, 0x1b, 0xad, 0x1a, 0x74, 0x9e, 0xe0, 0x03, 0x93, - 0x0a, 0x09, 0xb7, 0xad, 0xa7, 0xb4, 0x5c, 0xef, 0x83, 0x6c, 0xb7, 0x9a, - 0xb4, 0xc6, 0x68, 0x40, 0x80, 0x1d, 0x42, 0xd1, 0x6e, 0x79, 0x9b, 0xa9, - 0x19, 0x21, 0x9a, 0x9c, 0xf9, 0x86, 0x2d, 0x00, 0xd1, 0x34, 0xfe, 0xe0, - 0xb6, 0xf9, 0x55, 0xb6, 0xf5, 0x26, 0xc5, 0x95, 0x16, 0xa5, 0x7c, 0x73, - 0x9f, 0x0a, 0x29, 0x89, 0xac, 0x3a, 0x98, 0xf7, 0x9b, 0x74, 0x67, 0xb7, - 0x90, 0xb7, 0x5d, 0x09, 0x23, 0x6a, 0x6a, 0xed, 0x2c, 0x10, 0xee, 0x53, - 0x0a, 0x10, 0xf0, 0x16, 0x1f, 0x57, 0xb3, 0xb1, 0x0d, 0x79, 0x91, 0x19, - 0xb0, 0xeb, 0xcd, 0x30, 0x3f, 0xa0, 0x14, 0x5f, 0xb3, 0xc6, 0xfd, 0x5c, - 0x33, 0xa7, 0xb0, 0xff, 0x98, 0xb0, 0x55, 0x8c, 0xb9, 0xa5, 0xf2, 0x6f, - 0x47, 0x24, 0x49, 0x21, 0x69, 0xcc, 0x42, 0xa2, 0x51, 0x00, 0x40, 0x85, - 0x8c, 0x82, 0x82, 0xab, 0x32, 0xa5, 0xcb, 0x9a, 0xdc, 0xd0, 0xd9, 0x18, - 0x0d, 0xdf, 0x19, 0xf4, 0xaf, 0x83, 0x0d, 0xc1, 0x3e, 0x31, 0xdb, 0x24, - 0x48, 0xb6, 0x75, 0x80, 0xa1, 0xe1, 0xc9, 0x77, 0x64, 0x1e, 0xa7, 0xe5, - 0x8b, 0x7f, 0x15, 0x4d, 0x4b, 0xa7, 0xc2, 0xd0, 0xed, 0x79, 0x95, 0x5e, - 0x91, 0x31, 0xec, 0x18, 0xff, 0x4e, 0x9f, 0x48, 0x14, 0xea, 0x75, 0xba, - 0x21, 0xce, 0x29, 0x76, 0xe9, 0x1f, 0x4e, 0x51, 0x87, 0x2e, 0xb3, 0xcc, - 0x04, 0x60, 0xba, 0x23, 0x1f, 0x1f, 0x65, 0xb2, 0x0a, 0xb8, 0xd5, 0x6e, - 0x8f, 0x4b, 0x42, 0x89, 0x47, 0xa9, 0x81, 0x90, 0x5b, 0x2b, 0xb2, 0xb6, - 0xae, 0xe6, 0xa0, 0x70, 0x7b, 0x78, 0x90, 0x0a, 0x7a, 0xc5, 0xe5, 0xe7, - 0xc5, 0xfb, 0x0a, 0xf6, 0x2f, 0x69, 0x8c, 0x8c, 0x1f, 0x57, 0xe0, 0x06, - 0x99, 0xff, 0x11, 0xd5, 0x52, 0x32, 0x20, 0x97, 0x27, 0x98, 0xee, 0x65, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xd4, 0x30, 0x82, 0x01, - 0xd0, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, - 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, 0x43, 0x95, 0x5d, - 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, 0x45, 0x30, 0x1d, - 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, 0xc3, 0xde, - 0x1a, 0x43, 0xed, 0x41, 0x97, 0xa9, 0x8f, 0x29, 0x78, 0x9c, 0x03, 0xb9, - 0xac, 0x40, 0x42, 0x00, 0xac, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, - 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c, 0x06, - 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, - 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, 0x03, 0x55, 0x1d, - 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, 0x2b, 0x06, 0x01, - 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, 0x30, 0x2b, 0x30, - 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, - 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63, - 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, 0x03, 0x55, 0x1d, - 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, 0xa0, 0x34, 0x86, - 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, - 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, 0x86, 0x30, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, - 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x55, 0x54, 0x4e, - 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, - 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, - 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, - 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, 0x64, 0x64, 0x54, - 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41, - 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, - 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, - 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x19, 0x06, 0x03, 0x55, 0x1d, - 0x11, 0x04, 0x12, 0x30, 0x10, 0x82, 0x0e, 0x67, 0x6c, 0x6f, 0x62, 0x61, - 0x6c, 0x20, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x03, 0x82, 0x01, 0x01, 0x00, 0x8f, 0xba, 0x75, 0xba, 0x39, 0xd4, 0x26, - 0xd3, 0x70, 0x0f, 0xc4, 0xb3, 0x02, 0xa7, 0xc5, 0x12, 0x23, 0x71, 0xc9, - 0xfe, 0x63, 0xe9, 0xa3, 0x62, 0x78, 0x24, 0x44, 0x4f, 0xd4, 0xb9, 0x11, - 0x3e, 0x1f, 0xc7, 0x28, 0xe7, 0x55, 0x6b, 0xee, 0xf4, 0xe1, 0x00, 0x91, - 0x86, 0x8a, 0xc9, 0x09, 0x6b, 0x9f, 0x2e, 0xa4, 0x45, 0x39, 0xd1, 0x61, - 0x62, 0x5e, 0x93, 0xa5, 0x05, 0x45, 0x78, 0x9f, 0x60, 0x12, 0x2c, 0xf4, - 0x6c, 0x65, 0x65, 0x0d, 0xcc, 0x46, 0x34, 0x8b, 0x28, 0xba, 0xa0, 0xc6, - 0xf4, 0x99, 0x71, 0x64, 0xf3, 0x22, 0x76, 0xac, 0x4f, 0xf3, 0x62, 0xc9, - 0xa7, 0x33, 0x5a, 0x07, 0x1f, 0x3d, 0xc9, 0x86, 0x80, 0xdc, 0xdb, 0x04, - 0x2f, 0x87, 0x27, 0xe8, 0xbf, 0x48, 0x44, 0x81, 0xc0, 0xf0, 0x49, 0x23, - 0x6e, 0x1f, 0xe5, 0xe4, 0x03, 0x86, 0x24, 0x13, 0xa2, 0x85, 0x62, 0x7c, - 0x58, 0x04, 0xca, 0xe6, 0x8d, 0x13, 0x72, 0x0a, 0xba, 0x56, 0x44, 0xa2, - 0x0f, 0xbc, 0xfb, 0xa0, 0x3d, 0x0d, 0x2a, 0x7f, 0xfb, 0x9e, 0xa9, 0x09, - 0x3d, 0xb7, 0x5a, 0xd4, 0x8a, 0x8d, 0xe1, 0x25, 0xe8, 0xa4, 0x09, 0x84, - 0x70, 0xad, 0x12, 0x44, 0xb9, 0xcf, 0xb9, 0x33, 0x7a, 0xba, 0x5c, 0xe6, - 0x4b, 0xa6, 0xbb, 0x05, 0x06, 0x98, 0xff, 0xf2, 0x98, 0x52, 0x7b, 0x77, - 0x80, 0x27, 0x4a, 0xd9, 0xe2, 0xfa, 0xb9, 0x52, 0xd4, 0xfb, 0xfb, 0xe6, - 0xd6, 0x2d, 0x9e, 0x8f, 0xc1, 0x15, 0x44, 0x8d, 0x9b, 0x74, 0x2f, 0xee, - 0x94, 0x5a, 0x4e, 0xd3, 0xc4, 0x8b, 0x8a, 0xac, 0x43, 0x9d, 0x73, 0xf6, - 0xae, 0x0c, 0x87, 0x89, 0xad, 0x87, 0xc9, 0xc9, 0xc7, 0xdd, 0xba, 0x14, - 0x60, 0x7a, 0xf8, 0xb5, 0x35, 0x9d, 0xc2, 0x8d, 0xc6, 0x96, 0x81, 0x0d, - 0xa9, 0x52, 0x8a, 0x29, 0x40, 0x04, 0xe9, 0x19, 0xb4 -}; -unsigned int Global_Trustee_cer_len = 1761; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/UTN-USERFirst-Hardware.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/UTN-USERFirst-Hardware.cer.h deleted file mode 100644 index 320e0e37..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/UTN-USERFirst-Hardware.cer.h +++ /dev/null @@ -1,99 +0,0 @@ -unsigned char UTN_USERFirst_Hardware_cer[] = { - 0x30, 0x82, 0x04, 0x74, 0x30, 0x82, 0x03, 0x5c, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x44, 0xbe, 0x0c, 0x8b, 0x50, 0x00, 0x24, 0xb4, 0x11, - 0xd3, 0x36, 0x2a, 0xfe, 0x65, 0x0a, 0xfd, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, - 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, - 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, - 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, - 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, - 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, - 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, - 0x39, 0x39, 0x30, 0x37, 0x30, 0x39, 0x31, 0x38, 0x31, 0x30, 0x34, 0x32, - 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x37, 0x30, 0x39, 0x31, 0x38, 0x31, - 0x39, 0x32, 0x32, 0x5a, 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, - 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, - 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, - 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, - 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb1, - 0xf7, 0xc3, 0x38, 0x3f, 0xb4, 0xa8, 0x7f, 0xcf, 0x39, 0x82, 0x51, 0x67, - 0xd0, 0x6d, 0x9f, 0xd2, 0xff, 0x58, 0xf3, 0xe7, 0x9f, 0x2b, 0xec, 0x0d, - 0x89, 0x54, 0x99, 0xb9, 0x38, 0x99, 0x16, 0xf7, 0xe0, 0x21, 0x79, 0x48, - 0xc2, 0xbb, 0x61, 0x74, 0x12, 0x96, 0x1d, 0x3c, 0x6a, 0x72, 0xd5, 0x3c, - 0x10, 0x67, 0x3a, 0x39, 0xed, 0x2b, 0x13, 0xcd, 0x66, 0xeb, 0x95, 0x09, - 0x33, 0xa4, 0x6c, 0x97, 0xb1, 0xe8, 0xc6, 0xec, 0xc1, 0x75, 0x79, 0x9c, - 0x46, 0x5e, 0x8d, 0xab, 0xd0, 0x6a, 0xfd, 0xb9, 0x2a, 0x55, 0x17, 0x10, - 0x54, 0xb3, 0x19, 0xf0, 0x9a, 0xf6, 0xf1, 0xb1, 0x5d, 0xb6, 0xa7, 0x6d, - 0xfb, 0xe0, 0x71, 0x17, 0x6b, 0xa2, 0x88, 0xfb, 0x00, 0xdf, 0xfe, 0x1a, - 0x31, 0x77, 0x0c, 0x9a, 0x01, 0x7a, 0xb1, 0x32, 0xe3, 0x2b, 0x01, 0x07, - 0x38, 0x6e, 0xc3, 0xa5, 0x5e, 0x23, 0xbc, 0x45, 0x9b, 0x7b, 0x50, 0xc1, - 0xc9, 0x30, 0x8f, 0xdb, 0xe5, 0x2b, 0x7a, 0xd3, 0x5b, 0xfb, 0x33, 0x40, - 0x1e, 0xa0, 0xd5, 0x98, 0x17, 0xbc, 0x8b, 0x87, 0xc3, 0x89, 0xd3, 0x5d, - 0xa0, 0x8e, 0xb2, 0xaa, 0xaa, 0xf6, 0x8e, 0x69, 0x88, 0x06, 0xc5, 0xfa, - 0x89, 0x21, 0xf3, 0x08, 0x9d, 0x69, 0x2e, 0x09, 0x33, 0x9b, 0x29, 0x0d, - 0x46, 0x0f, 0x8c, 0xcc, 0x49, 0x34, 0xb0, 0x69, 0x51, 0xbd, 0xf9, 0x06, - 0xcd, 0x68, 0xad, 0x66, 0x4c, 0xbc, 0x3e, 0xac, 0x61, 0xbd, 0x0a, 0x88, - 0x0e, 0xc8, 0xdf, 0x3d, 0xee, 0x7c, 0x04, 0x4c, 0x9d, 0x0a, 0x5e, 0x6b, - 0x91, 0xd6, 0xee, 0xc7, 0xed, 0x28, 0x8d, 0xab, 0x4d, 0x87, 0x89, 0x73, - 0xd0, 0x6e, 0xa4, 0xd0, 0x1e, 0x16, 0x8b, 0x14, 0xe1, 0x76, 0x44, 0x03, - 0x7f, 0x63, 0xac, 0xe4, 0xcd, 0x49, 0x9c, 0xc5, 0x92, 0xf4, 0xab, 0x32, - 0xa1, 0x48, 0x5b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xb9, 0x30, - 0x81, 0xb6, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, - 0x02, 0x01, 0xc6, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, - 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, - 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, - 0x28, 0x98, 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, - 0xd2, 0xc3, 0x45, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x3d, - 0x30, 0x3b, 0x30, 0x39, 0xa0, 0x37, 0xa0, 0x35, 0x86, 0x33, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, - 0x6c, 0x30, 0x31, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x2a, 0x30, 0x28, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x05, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x03, 0x06, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x03, 0x07, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, - 0x47, 0x19, 0x0f, 0xde, 0x74, 0xc6, 0x99, 0x97, 0xaf, 0xfc, 0xad, 0x28, - 0x5e, 0x75, 0x8e, 0xeb, 0x2d, 0x67, 0xee, 0x4e, 0x7b, 0x2b, 0xd7, 0x0c, - 0xff, 0xf6, 0xde, 0xcb, 0x55, 0xa2, 0x0a, 0xe1, 0x4c, 0x54, 0x65, 0x93, - 0x60, 0x6b, 0x9f, 0x12, 0x9c, 0xad, 0x5e, 0x83, 0x2c, 0xeb, 0x5a, 0xae, - 0xc0, 0xe4, 0x2d, 0xf4, 0x00, 0x63, 0x1d, 0xb8, 0xc0, 0x6c, 0xf2, 0xcf, - 0x49, 0xbb, 0x4d, 0x93, 0x6f, 0x06, 0xa6, 0x0a, 0x22, 0xb2, 0x49, 0x62, - 0x08, 0x4e, 0xff, 0xc8, 0xc8, 0x14, 0xb2, 0x88, 0x16, 0x5d, 0xe7, 0x01, - 0xe4, 0x12, 0x95, 0xe5, 0x45, 0x34, 0xb3, 0x8b, 0x69, 0xbd, 0xcf, 0xb4, - 0x85, 0x8f, 0x75, 0x51, 0x9e, 0x7d, 0x3a, 0x38, 0x3a, 0x14, 0x48, 0x12, - 0xc6, 0xfb, 0xa7, 0x3b, 0x1a, 0x8d, 0x0d, 0x82, 0x40, 0x07, 0xe8, 0x04, - 0x08, 0x90, 0xa1, 0x89, 0xcb, 0x19, 0x50, 0xdf, 0xca, 0x1c, 0x01, 0xbc, - 0x1d, 0x04, 0x19, 0x7b, 0x10, 0x76, 0x97, 0x3b, 0xee, 0x90, 0x90, 0xca, - 0xc4, 0x0e, 0x1f, 0x16, 0x6e, 0x75, 0xef, 0x33, 0xf8, 0xd3, 0x6f, 0x5b, - 0x1e, 0x96, 0xe3, 0xe0, 0x74, 0x77, 0x74, 0x7b, 0x8a, 0xa2, 0x6e, 0x2d, - 0xdd, 0x76, 0xd6, 0x39, 0x30, 0x82, 0xf0, 0xab, 0x9c, 0x52, 0xf2, 0x2a, - 0xc7, 0xaf, 0x49, 0x5e, 0x7e, 0xc7, 0x68, 0xe5, 0x82, 0x81, 0xc8, 0x6a, - 0x27, 0xf9, 0x27, 0x88, 0x2a, 0xd5, 0x58, 0x50, 0x95, 0x1f, 0xf0, 0x3b, - 0x1c, 0x57, 0xbb, 0x7d, 0x14, 0x39, 0x62, 0x2b, 0x9a, 0xc9, 0x94, 0x92, - 0x2a, 0xa3, 0x22, 0x0c, 0xff, 0x89, 0x26, 0x7d, 0x5f, 0x23, 0x2b, 0x47, - 0xd7, 0x15, 0x1d, 0xa9, 0x6a, 0x9e, 0x51, 0x0d, 0x2a, 0x51, 0x9e, 0x81, - 0xf9, 0xd4, 0x3b, 0x5e, 0x70, 0x12, 0x7f, 0x10, 0x32, 0x9c, 0x1e, 0xbb, - 0x9d, 0xf8, 0x66, 0xa8 -}; -unsigned int UTN_USERFirst_Hardware_cer_len = 1144; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/addons.mozilla.org.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/addons.mozilla.org.cer.h deleted file mode 100644 index ae288d3f..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/addons.mozilla.org.cer.h +++ /dev/null @@ -1,131 +0,0 @@ -unsigned char addons_mozilla_org_cer[] = { - 0x30, 0x82, 0x05, 0xf8, 0x30, 0x82, 0x04, 0xe0, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0x92, 0x39, 0xd5, 0x34, 0x8f, 0x40, 0xd1, 0x69, - 0x5a, 0x74, 0x54, 0x70, 0xe1, 0xf2, 0x3f, 0x43, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xe2, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, - 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x2e, 0x6d, 0x6f, 0x7a, 0x69, 0x6c, - 0x6c, 0x61, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, - 0x01, 0x01, 0x00, 0xab, 0xc6, 0x6d, 0x36, 0xf3, 0x15, 0x73, 0x78, 0x83, - 0x73, 0xce, 0x74, 0x85, 0xd5, 0xae, 0xec, 0xb2, 0xf0, 0xe0, 0x24, 0x1f, - 0x13, 0x83, 0xb8, 0x20, 0xac, 0xbb, 0x9a, 0xfe, 0x88, 0xbb, 0xab, 0xa1, - 0x1d, 0x0b, 0x1f, 0x45, 0x00, 0xaa, 0x49, 0xb7, 0x35, 0x37, 0x0c, 0x6a, - 0xef, 0x47, 0x4c, 0xb9, 0xd1, 0xbe, 0xe3, 0x57, 0x12, 0x04, 0x8d, 0x92, - 0xc7, 0xb6, 0xec, 0x01, 0xbc, 0xb6, 0xda, 0xc7, 0x81, 0x38, 0x20, 0xad, - 0x72, 0x85, 0xe6, 0x0e, 0xfc, 0x81, 0x6c, 0x07, 0xad, 0x68, 0x76, 0x38, - 0xc5, 0x44, 0xd7, 0xcc, 0xc6, 0x4a, 0xc5, 0x97, 0x3e, 0x64, 0xf4, 0x51, - 0xe6, 0xf0, 0x7e, 0xb2, 0xec, 0x56, 0xf7, 0x25, 0x82, 0x4d, 0x49, 0x98, - 0xcb, 0x16, 0x98, 0xdd, 0x23, 0xf1, 0x89, 0x91, 0xd1, 0x17, 0x97, 0x40, - 0x99, 0x26, 0xd6, 0xe2, 0xa2, 0x2b, 0x5e, 0xdf, 0xbd, 0x89, 0xf2, 0x1b, - 0x1a, 0x53, 0x2d, 0xcc, 0x50, 0x41, 0x7a, 0xd0, 0x3d, 0x2a, 0x0c, 0x55, - 0x70, 0x14, 0x01, 0xe9, 0x58, 0x49, 0x10, 0x7a, 0x0b, 0x93, 0x82, 0x8b, - 0xe1, 0x1e, 0xed, 0x3a, 0x80, 0x10, 0x82, 0xce, 0x96, 0x8a, 0x34, 0xf0, - 0xcc, 0xd7, 0xd3, 0xb9, 0xb4, 0x50, 0x87, 0x55, 0x54, 0x09, 0xb8, 0x9d, - 0x42, 0x28, 0x55, 0x00, 0xe5, 0x8c, 0x35, 0x54, 0xbf, 0xdd, 0x25, 0x91, - 0x46, 0xb7, 0x0d, 0xe5, 0x5d, 0x83, 0xa8, 0xe5, 0x8b, 0xfb, 0x84, 0xe4, - 0x3c, 0xae, 0x76, 0xda, 0xc4, 0x43, 0x2b, 0x5b, 0x74, 0x0b, 0xf8, 0xbe, - 0x5d, 0x68, 0xf1, 0x78, 0x5b, 0xb5, 0xce, 0x7d, 0xf1, 0x5d, 0x99, 0x40, - 0xda, 0xca, 0xee, 0x38, 0x81, 0x50, 0xbe, 0x98, 0xa1, 0x6c, 0xb8, 0x24, - 0xad, 0xf3, 0xaf, 0x8c, 0x0f, 0xd7, 0x11, 0x28, 0x2c, 0x84, 0x18, 0x4c, - 0x7d, 0xb5, 0xd9, 0x8f, 0x30, 0xb5, 0x1b, 0x02, 0x03, 0x01, 0x00, 0x01, - 0xa3, 0x82, 0x01, 0xf0, 0x30, 0x82, 0x01, 0xec, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, - 0x26, 0x1b, 0x28, 0x98, 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, - 0x9d, 0x4b, 0xd2, 0xc3, 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xdd, 0x80, 0xd2, 0x54, 0x3d, 0xf7, 0x4c, 0x70, - 0xca, 0xa3, 0xb0, 0xdd, 0x34, 0x7a, 0x32, 0xe4, 0xe8, 0x3b, 0x5a, 0x3b, - 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, - 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, - 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, - 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, - 0x02, 0x30, 0x46, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, - 0x30, 0x3b, 0x06, 0x0c, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, - 0x02, 0x01, 0x03, 0x04, 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, - 0x73, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, - 0x53, 0x30, 0x7b, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, - 0x30, 0x38, 0xa0, 0x36, 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, - 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, - 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, - 0xa0, 0x34, 0xa0, 0x32, 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, - 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, - 0x6e, 0x65, 0x74, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, - 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x55, 0x54, 0x4e, 0x41, 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, - 0x24, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, - 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, - 0x6d, 0x30, 0x35, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x2e, 0x30, 0x2c, - 0x82, 0x12, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x2e, 0x6d, 0x6f, 0x7a, - 0x69, 0x6c, 0x6c, 0x61, 0x2e, 0x6f, 0x72, 0x67, 0x82, 0x16, 0x77, 0x77, - 0x77, 0x2e, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x2e, 0x6d, 0x6f, 0x7a, - 0x69, 0x6c, 0x6c, 0x61, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x01, 0x00, 0x33, 0x3b, 0x63, 0x15, 0xfc, 0xb1, 0xec, 0x14, - 0x2c, 0x93, 0xdd, 0x75, 0x94, 0xde, 0x81, 0x5a, 0xd9, 0x4e, 0x99, 0xbe, - 0xfb, 0x4a, 0xa4, 0x39, 0x55, 0x4d, 0xa1, 0x40, 0x7a, 0xde, 0x13, 0x2a, - 0x87, 0xa9, 0x37, 0xcf, 0xe8, 0xd5, 0xfb, 0xad, 0xd1, 0x7b, 0x6d, 0x6f, - 0x8c, 0x20, 0x87, 0x82, 0x54, 0xe6, 0x57, 0x49, 0xbc, 0x20, 0x28, 0x84, - 0xcd, 0xd6, 0x01, 0xd9, 0x93, 0x8b, 0x17, 0x6e, 0x23, 0x66, 0xe5, 0x84, - 0xc8, 0x80, 0x3f, 0xc6, 0xa1, 0x70, 0x80, 0xe4, 0xec, 0x4d, 0x1d, 0xf9, - 0xfc, 0x91, 0x5a, 0x73, 0x62, 0x29, 0x9a, 0xf7, 0x20, 0x1c, 0x61, 0xe0, - 0x8b, 0x39, 0x9f, 0xca, 0xbc, 0x7e, 0x8d, 0xdd, 0xbc, 0xd9, 0xb1, 0xe3, - 0x9f, 0x9e, 0xdf, 0x15, 0x53, 0x91, 0x21, 0x52, 0x0b, 0xd9, 0x1a, 0x23, - 0x0f, 0x66, 0x36, 0xdb, 0xac, 0x93, 0x96, 0x4a, 0xa3, 0xa5, 0x22, 0xcf, - 0x29, 0xf7, 0xa2, 0x99, 0xa8, 0xf6, 0xb6, 0xd9, 0x40, 0xae, 0xd9, 0x7e, - 0xb6, 0xf6, 0x58, 0x2e, 0x9b, 0xac, 0x36, 0xca, 0x64, 0x8f, 0x65, 0x52, - 0xdc, 0x86, 0x9c, 0x82, 0xab, 0x6e, 0x50, 0x4b, 0xda, 0x5f, 0xfa, 0x05, - 0x00, 0x88, 0x30, 0x0e, 0xde, 0x8d, 0x56, 0xbf, 0x81, 0x47, 0x8d, 0x3d, - 0x06, 0xe2, 0xb2, 0x62, 0x92, 0x67, 0x8f, 0x9e, 0xc8, 0x9a, 0xb2, 0xe5, - 0x06, 0xb8, 0x70, 0x24, 0xb8, 0x77, 0x7c, 0x23, 0x0a, 0x38, 0xc3, 0x79, - 0x08, 0xd8, 0xb1, 0x51, 0x9d, 0xac, 0x95, 0x11, 0xc7, 0x40, 0x17, 0x9e, - 0xa3, 0x1c, 0x8f, 0xf2, 0x11, 0xa7, 0x68, 0x27, 0xda, 0x49, 0x05, 0x84, - 0x18, 0x7c, 0x58, 0x2d, 0x01, 0x67, 0x5c, 0xe5, 0x9f, 0xa1, 0x29, 0xbb, - 0x4a, 0x39, 0x45, 0x2f, 0xbf, 0x11, 0xaa, 0x79, 0xa2, 0xed, 0xb4, 0xd4, - 0xb5, 0x65, 0x43, 0xb7, 0x93, 0x46, 0x8a, 0xd3 -}; -unsigned int addons_mozilla_org_cer_len = 1532; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.live.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.live.com.cer.h deleted file mode 100644 index fb39259f..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.live.com.cer.h +++ /dev/null @@ -1,130 +0,0 @@ -unsigned char login_live_com_cer[] = { - 0x30, 0x82, 0x05, 0xec, 0x30, 0x82, 0x04, 0xd4, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xb0, 0xb7, 0x13, 0x3e, 0xd0, 0x96, 0xf9, 0xb5, - 0x6f, 0xae, 0x91, 0xc8, 0x74, 0xbd, 0x3a, 0xc0, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xde, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, - 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xf3, - 0xfc, 0x2b, 0x2f, 0xef, 0xe1, 0xad, 0x59, 0xf0, 0x42, 0x3c, 0xc2, 0xf1, - 0x82, 0xbf, 0x2c, 0x41, 0x93, 0xd1, 0xf6, 0x98, 0x33, 0x95, 0x4c, 0xbc, - 0x62, 0xf1, 0x95, 0x58, 0x08, 0xb6, 0xe9, 0x7b, 0x77, 0x48, 0xb0, 0xd3, - 0xdc, 0x17, 0x3f, 0xbc, 0x6e, 0xe6, 0xec, 0x1e, 0xec, 0x8d, 0x17, 0xfe, - 0x1c, 0x24, 0xc6, 0x3e, 0x67, 0x3d, 0x92, 0x95, 0xa2, 0x30, 0xc0, 0xa7, - 0x57, 0x20, 0xcf, 0x70, 0x88, 0x97, 0x4a, 0x05, 0x93, 0x79, 0x93, 0x42, - 0x97, 0x2f, 0x3e, 0xff, 0xc4, 0x14, 0x14, 0x28, 0xa2, 0x13, 0x36, 0xb4, - 0xf8, 0xee, 0xbe, 0x1d, 0xbc, 0x78, 0x5d, 0x61, 0x93, 0x5f, 0xeb, 0x88, - 0xd7, 0xd1, 0xe4, 0x2b, 0x9a, 0xcd, 0x58, 0xe2, 0x07, 0x45, 0x9f, 0x4f, - 0xb8, 0xb9, 0x40, 0x6a, 0x33, 0x2c, 0x5b, 0x21, 0x03, 0x5a, 0x4a, 0x94, - 0xf2, 0x7a, 0x97, 0x59, 0x1b, 0xa8, 0xb5, 0x42, 0xd8, 0x83, 0x00, 0xaa, - 0x34, 0xcc, 0xa7, 0x76, 0xd0, 0x47, 0x03, 0x5f, 0x05, 0xaf, 0x3b, 0xe1, - 0xb9, 0xa1, 0x34, 0x25, 0xb7, 0x6c, 0x5f, 0x9a, 0x30, 0x84, 0x98, 0xc2, - 0xc2, 0xd7, 0xf2, 0xb8, 0x42, 0x4a, 0x10, 0x55, 0xbd, 0xfa, 0x53, 0x81, - 0x5d, 0x8d, 0x68, 0x66, 0x45, 0x2c, 0x52, 0x7e, 0xe5, 0xc4, 0x04, 0xc3, - 0x54, 0xe7, 0xc3, 0x39, 0xda, 0x7a, 0x4a, 0xc5, 0xb9, 0x98, 0x82, 0x20, - 0xe1, 0x2c, 0x60, 0x57, 0xbf, 0xba, 0xf2, 0x46, 0x00, 0xbc, 0x5f, 0x3a, - 0xdc, 0xe3, 0x33, 0x97, 0xf8, 0x4a, 0x98, 0xb9, 0xec, 0x33, 0x4f, 0x2d, - 0x60, 0x6c, 0x15, 0x92, 0xa6, 0x81, 0x4a, 0x0b, 0xe9, 0xec, 0x76, 0x70, - 0x34, 0x31, 0x17, 0x70, 0xe6, 0x70, 0x4b, 0x8e, 0x8b, 0xd3, 0x75, 0xcb, - 0x78, 0x49, 0xab, 0x66, 0x9b, 0x86, 0x9f, 0x8f, 0xa9, 0xc4, 0x01, 0xe8, - 0xca, 0x1b, 0xe7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xe8, - 0x30, 0x82, 0x01, 0xe4, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0xd4, 0x64, 0xf6, 0xa9, 0xe8, 0xa5, 0x7e, 0xd7, 0xbf, 0x63, 0x52, 0x03, - 0x83, 0x53, 0xdb, 0xc5, 0x41, 0x8d, 0xea, 0x80, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x2d, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x26, 0x30, 0x24, 0x82, 0x0e, 0x6c, 0x6f, - 0x67, 0x69, 0x6e, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x82, 0x12, 0x77, 0x77, 0x77, 0x2e, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, - 0x6c, 0x69, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x01, 0x00, 0x54, 0xe3, 0xa4, 0x9a, 0x24, 0xd2, 0xf3, 0x1d, - 0x42, 0xad, 0x1b, 0xf0, 0x1e, 0xab, 0xfb, 0xda, 0xd5, 0xaa, 0xe9, 0xcf, - 0x5a, 0xb3, 0x1e, 0x57, 0x7b, 0x31, 0xf2, 0x6e, 0x57, 0x4b, 0x31, 0xaf, - 0x33, 0xbb, 0xb6, 0x0d, 0x15, 0xc7, 0x5e, 0x59, 0x01, 0xce, 0x44, 0xb5, - 0xb7, 0xbf, 0x09, 0xc9, 0xd5, 0xdc, 0x69, 0x84, 0xe9, 0xc5, 0x1a, 0xb7, - 0xf0, 0x3e, 0xd4, 0xc0, 0x24, 0xbd, 0x29, 0x5f, 0xb4, 0xe9, 0xd6, 0x58, - 0xeb, 0x45, 0x11, 0x89, 0x34, 0x34, 0xd3, 0x11, 0xeb, 0x34, 0xce, 0x2a, - 0x4f, 0x00, 0x3d, 0xf6, 0x72, 0xef, 0x69, 0x66, 0xc0, 0x9f, 0x9a, 0xac, - 0x7e, 0x70, 0x50, 0xac, 0x55, 0x47, 0xda, 0xbe, 0x43, 0x5b, 0xec, 0x8b, - 0xc8, 0xc5, 0x23, 0x84, 0xc9, 0x9f, 0xb6, 0x52, 0x08, 0xcf, 0x91, 0x1b, - 0x2f, 0x80, 0x69, 0xe6, 0x34, 0x33, 0xe6, 0xb3, 0x9f, 0xa4, 0xe5, 0x0d, - 0x9a, 0x15, 0xf9, 0x57, 0xfc, 0x0b, 0xa9, 0x41, 0x0b, 0xf5, 0xff, 0x58, - 0x41, 0x92, 0x22, 0x27, 0x66, 0x12, 0x06, 0xc7, 0x2a, 0xd8, 0x59, 0xa7, - 0xc6, 0xdf, 0x44, 0x12, 0x4f, 0xc0, 0xa8, 0x7f, 0xa7, 0x41, 0xc8, 0xc8, - 0x69, 0xff, 0xba, 0x05, 0x2e, 0x97, 0xad, 0x3b, 0xd0, 0xeb, 0xf3, 0x15, - 0x6d, 0x7e, 0x1b, 0xe5, 0xba, 0xdd, 0x34, 0xbe, 0x22, 0x11, 0xec, 0x68, - 0x98, 0x33, 0x81, 0x02, 0x6a, 0x0b, 0x13, 0x55, 0x79, 0x31, 0x75, 0x4e, - 0x3a, 0xc8, 0xb6, 0x13, 0xbd, 0x97, 0x6f, 0x37, 0x0a, 0x0b, 0x2d, 0x88, - 0x0e, 0xde, 0x67, 0x90, 0xc2, 0xb3, 0xca, 0x20, 0xca, 0x9a, 0x51, 0xf4, - 0x64, 0x3e, 0xdb, 0xf4, 0x2e, 0x45, 0xf2, 0xc7, 0x47, 0x17, 0xa8, 0xf4, - 0xfa, 0x90, 0x5a, 0x7f, 0x80, 0xa6, 0x82, 0xac, 0xe4, 0x6c, 0x81, 0x46, - 0xbb, 0x52, 0x85, 0x20, 0x24, 0xf8, 0x80, 0xea -}; -unsigned int login_live_com_cer_len = 1520; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.skype.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.skype.com.cer.h deleted file mode 100644 index 0ffd13ab..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.skype.com.cer.h +++ /dev/null @@ -1,130 +0,0 @@ -unsigned char login_skype_com_cer[] = { - 0x30, 0x82, 0x05, 0xef, 0x30, 0x82, 0x04, 0xd7, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xe9, 0x02, 0x8b, 0x95, 0x78, 0xe4, 0x15, 0xdc, - 0x1a, 0x71, 0x0a, 0x2b, 0x88, 0x15, 0x44, 0x47, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, - 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x73, 0x6b, 0x79, 0x70, 0x65, 0x2e, - 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, - 0xb0, 0x78, 0x99, 0x86, 0x0e, 0xa2, 0x73, 0x23, 0xd4, 0x5a, 0xc3, 0x49, - 0xeb, 0xb1, 0x36, 0x8c, 0x7c, 0xca, 0x84, 0xae, 0x3c, 0xaf, 0x38, 0x88, - 0x28, 0x99, 0x8d, 0x2d, 0x58, 0x13, 0xb1, 0x97, 0x78, 0x3e, 0x52, 0x20, - 0x67, 0xac, 0x5b, 0x73, 0x98, 0x6c, 0x32, 0x55, 0xc9, 0x70, 0xd1, 0xd9, - 0xaa, 0x15, 0xe8, 0x2e, 0x26, 0x85, 0x81, 0xbc, 0x56, 0xe4, 0xbc, 0x80, - 0x63, 0xdb, 0x4e, 0xd7, 0xf5, 0x02, 0xbe, 0x51, 0x63, 0x1e, 0x3c, 0xdb, - 0xdf, 0xd7, 0x00, 0x5d, 0x5a, 0xb9, 0xe5, 0x7b, 0x6a, 0xea, 0x38, 0x20, - 0xb2, 0x3b, 0xb6, 0xee, 0x75, 0x54, 0x84, 0xf9, 0xa6, 0xca, 0x38, 0x70, - 0xdd, 0xbf, 0xb0, 0xff, 0xa5, 0x85, 0x5d, 0xb4, 0x41, 0xfe, 0xdd, 0x3d, - 0xd9, 0x2a, 0xe1, 0x30, 0x43, 0x1a, 0x98, 0x79, 0x93, 0xa0, 0x5f, 0xe0, - 0x67, 0x6c, 0x95, 0xfa, 0x3e, 0x7a, 0xae, 0x71, 0x7b, 0xe3, 0x6d, 0x88, - 0x42, 0x3f, 0x25, 0xd4, 0xee, 0xbe, 0x68, 0x68, 0xac, 0xad, 0xac, 0x60, - 0xe0, 0x20, 0xa3, 0x39, 0x83, 0xb9, 0x5b, 0x28, 0xa3, 0x93, 0x6d, 0xa1, - 0xbd, 0x76, 0x0a, 0xe3, 0xeb, 0xae, 0x87, 0x27, 0x0e, 0x54, 0x8f, 0xb4, - 0x48, 0x0c, 0x9a, 0x54, 0xf4, 0x5d, 0x8e, 0x37, 0x50, 0xdc, 0x5e, 0xa4, - 0x8b, 0x6b, 0x4b, 0xdc, 0xa6, 0xf3, 0x34, 0xbe, 0x77, 0x59, 0x22, 0x88, - 0xff, 0x19, 0x2b, 0x6d, 0x76, 0x64, 0x73, 0xda, 0x0c, 0x87, 0x07, 0x2b, - 0x9a, 0x37, 0x3a, 0xd0, 0xe2, 0x8c, 0xf6, 0x36, 0x32, 0x6b, 0x9a, 0x79, - 0xcc, 0xd2, 0x3b, 0x93, 0x6f, 0x1a, 0x4d, 0x6c, 0xe6, 0xc1, 0x9d, 0x40, - 0xac, 0x2d, 0x74, 0xc3, 0xbe, 0xea, 0x5c, 0x73, 0x65, 0x01, 0x29, 0xb1, - 0x2a, 0xbf, 0x70, 0x59, 0xc1, 0xce, 0xc6, 0xc3, 0xa2, 0xc8, 0x45, 0x5f, - 0xba, 0x67, 0x3d, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, - 0xea, 0x30, 0x82, 0x01, 0xe6, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, - 0x98, 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, - 0xc3, 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0xd5, 0x8e, 0x5a, 0x51, 0x13, 0xb4, 0x29, 0x0d, 0x31, 0xb6, 0x1c, - 0x8d, 0x3e, 0x51, 0x51, 0x31, 0x0a, 0x33, 0xaa, 0x81, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, - 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, - 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, - 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, - 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, - 0x0c, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, - 0x04, 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, - 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, - 0x64, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, - 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, - 0x36, 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, - 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, - 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, - 0x32, 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, - 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, - 0x63, 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, - 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, - 0x41, 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, - 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x2f, - 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x28, 0x30, 0x26, 0x82, 0x0f, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x73, 0x6b, 0x79, 0x70, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x82, 0x13, 0x77, 0x77, 0x77, 0x2e, 0x6c, 0x6f, 0x67, 0x69, - 0x6e, 0x2e, 0x73, 0x6b, 0x79, 0x70, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x08, 0xf2, 0x81, 0x75, 0x91, - 0xbb, 0xce, 0x12, 0x04, 0x18, 0xc2, 0x4d, 0x5a, 0xfb, 0x46, 0x90, 0x0a, - 0x54, 0x44, 0xf4, 0xf2, 0xdd, 0x07, 0x81, 0xf0, 0x1f, 0xa6, 0x7a, 0x6f, - 0x9f, 0xcf, 0xb8, 0x0e, 0x2c, 0x4f, 0x9c, 0xc4, 0x9a, 0xf5, 0xa8, 0xf6, - 0xba, 0xa4, 0xc9, 0x7a, 0x5d, 0xb1, 0xe2, 0x5a, 0xca, 0x3c, 0xfa, 0x60, - 0xa8, 0x68, 0x3e, 0xcb, 0xba, 0x2d, 0xe2, 0xcd, 0xd6, 0xb6, 0xe4, 0x92, - 0x3c, 0x69, 0xad, 0x57, 0xea, 0xa8, 0x2f, 0x38, 0x10, 0x84, 0x72, 0xe5, - 0x68, 0x71, 0xed, 0xbe, 0xeb, 0x6e, 0x18, 0xef, 0x63, 0x7a, 0xbe, 0xe7, - 0x24, 0xff, 0xc0, 0x63, 0xfd, 0x58, 0x3b, 0x4c, 0x81, 0x92, 0xd8, 0x29, - 0xab, 0x8e, 0x35, 0x5d, 0xd7, 0xd3, 0x09, 0x6b, 0x85, 0xd3, 0xd5, 0x73, - 0x05, 0x44, 0xe2, 0xe5, 0xbb, 0x83, 0x53, 0x10, 0xcb, 0xf2, 0xcf, 0xb7, - 0x6e, 0xe1, 0x69, 0xb7, 0xa1, 0x92, 0x64, 0xc5, 0xcf, 0xcd, 0x82, 0xbb, - 0x36, 0xa0, 0x38, 0xad, 0xd7, 0x24, 0xdf, 0x53, 0xfc, 0x3f, 0x62, 0xb7, - 0xb7, 0xd5, 0xc7, 0x57, 0xe3, 0x93, 0x31, 0x70, 0x8e, 0x24, 0x89, 0x86, - 0xca, 0x63, 0x2b, 0x39, 0xba, 0x5d, 0xd9, 0x6a, 0x60, 0xec, 0xa1, 0x4e, - 0x8a, 0xfe, 0x53, 0xf8, 0x5e, 0x92, 0xdf, 0x2f, 0x5c, 0x26, 0x17, 0x6d, - 0x03, 0x7d, 0x02, 0x0f, 0x0f, 0xaa, 0x43, 0x67, 0x6d, 0xb0, 0x62, 0xbf, - 0x7e, 0x53, 0xdd, 0xcc, 0xec, 0x78, 0x73, 0x95, 0xe5, 0xa5, 0xf6, 0x00, - 0xa3, 0x04, 0xfd, 0x3f, 0x04, 0x2a, 0xb3, 0x98, 0xc5, 0xb7, 0x03, 0x1c, - 0xdb, 0xc9, 0x50, 0xab, 0xb0, 0x05, 0x1d, 0x1e, 0xbe, 0x56, 0xb4, 0xcf, - 0x3e, 0x42, 0x13, 0x94, 0x9e, 0xf9, 0xe7, 0x01, 0x81, 0xa5, 0x78, 0x6f, - 0x0c, 0x7a, 0x76, 0xac, 0x05, 0x86, 0xec, 0xac, 0xc2, 0x11, 0xac -}; -unsigned int login_skype_com_cer_len = 1523; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.1.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.1.cer.h deleted file mode 100644 index 5c1a3ee2..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.1.cer.h +++ /dev/null @@ -1,129 +0,0 @@ -unsigned char login_yahoo_com_1_cer[] = { - 0x30, 0x82, 0x05, 0xd9, 0x30, 0x82, 0x04, 0xc1, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x39, 0x2a, 0x43, 0x4f, 0x0e, 0x07, 0xdf, 0x1f, 0x8a, - 0xa3, 0x05, 0xde, 0x34, 0xe0, 0xc2, 0x29, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, - 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, - 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, - 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, - 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, - 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, - 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, 0x35, - 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, - 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, 0x37, - 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x46, - 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, 0x53, - 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, 0x31, - 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, - 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, 0x65, - 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, 0x26, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, - 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, 0x4c, - 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, - 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa1, - 0xa4, 0x05, 0x3d, 0xed, 0x85, 0x45, 0x93, 0x8a, 0x18, 0x4d, 0xc6, 0x03, - 0x00, 0x57, 0xe2, 0x40, 0x77, 0xf0, 0x1c, 0xeb, 0xd0, 0x19, 0xdf, 0x22, - 0x5d, 0x08, 0x7f, 0xd1, 0x07, 0x3c, 0x41, 0x89, 0x46, 0x17, 0xa3, 0x09, - 0xfa, 0xfc, 0xf8, 0xa9, 0x04, 0xd1, 0x96, 0x8f, 0xab, 0xd7, 0x4f, 0x3c, - 0xf9, 0xad, 0x18, 0xa9, 0x74, 0x81, 0xc4, 0x57, 0x0a, 0x3a, 0x26, 0x16, - 0xce, 0x62, 0x3e, 0xbc, 0x3f, 0x6c, 0x21, 0xee, 0x93, 0x8d, 0xcb, 0x0d, - 0xa0, 0x1f, 0x9a, 0x96, 0xd0, 0x8f, 0xad, 0xf5, 0x93, 0x93, 0x82, 0xee, - 0x72, 0x0c, 0xa1, 0x75, 0x15, 0xa3, 0x7b, 0x84, 0x56, 0xb8, 0xad, 0xff, - 0x52, 0x11, 0x71, 0x84, 0xbc, 0x3a, 0x30, 0x0b, 0x7e, 0x98, 0xa8, 0xe1, - 0xa8, 0x3f, 0x37, 0x52, 0xd0, 0xf1, 0x7c, 0x6f, 0x90, 0xd8, 0x45, 0x0a, - 0xac, 0x39, 0x72, 0x6a, 0x61, 0xd5, 0xbb, 0xc3, 0x8c, 0xf9, 0xc2, 0xcc, - 0xdf, 0xfd, 0x3a, 0x71, 0xb9, 0xaf, 0xbc, 0xdc, 0x3a, 0xdc, 0x0c, 0xb6, - 0xb1, 0xd2, 0xd1, 0x89, 0xbb, 0x41, 0xb6, 0xf2, 0xde, 0x57, 0xd5, 0x15, - 0xdf, 0xfc, 0xfd, 0xe2, 0x31, 0xc5, 0xdf, 0xca, 0xc1, 0xd8, 0x8f, 0x2c, - 0xbf, 0xf0, 0x0e, 0x5b, 0x71, 0xe0, 0x34, 0x71, 0xc3, 0xc5, 0x4d, 0x7d, - 0x7a, 0xd4, 0xfa, 0xed, 0x30, 0x4b, 0x2f, 0xea, 0xb6, 0x2e, 0x9e, 0x93, - 0x3c, 0xe2, 0x3a, 0xf8, 0x42, 0xa2, 0x1a, 0xee, 0xdc, 0xdf, 0xcd, 0x0f, - 0xa9, 0xf6, 0x79, 0x84, 0x1a, 0x8e, 0x6c, 0x02, 0xb6, 0x86, 0xe5, 0xbf, - 0x51, 0x6a, 0x66, 0xf8, 0xf3, 0x9c, 0xd3, 0x59, 0x0c, 0x7b, 0xa5, 0x99, - 0x78, 0xcd, 0x7c, 0x99, 0xfa, 0xc6, 0x96, 0x47, 0xd8, 0x32, 0xd4, 0x74, - 0x76, 0x0e, 0x77, 0x4b, 0x20, 0x74, 0xa4, 0xb7, 0x89, 0x75, 0x92, 0x4a, - 0xb4, 0x5b, 0x55, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xd5, - 0x30, 0x82, 0x01, 0xd1, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x86, 0x49, 0x45, 0xfc, 0x33, 0x19, 0x33, 0xd4, 0x04, 0xed, 0x27, 0x61, - 0xee, 0xe8, 0x01, 0xc9, 0x0c, 0x7f, 0x2f, 0x7e, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1a, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x13, 0x30, 0x11, 0x82, 0x0f, 0x6c, 0x6f, - 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, 0x6f, - 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x57, 0x62, 0xe1, - 0x77, 0xeb, 0xfc, 0x1f, 0xbf, 0x88, 0x53, 0xaf, 0x58, 0xd3, 0xd4, 0xd6, - 0x6d, 0x67, 0x30, 0x17, 0x40, 0xbe, 0xe0, 0x1f, 0x64, 0xde, 0x87, 0x15, - 0xcc, 0xe0, 0xa4, 0x56, 0xa9, 0xd1, 0x9f, 0xf9, 0x01, 0xfe, 0x02, 0xb1, - 0xb1, 0xea, 0xe2, 0x5f, 0xee, 0x71, 0x16, 0x31, 0xf9, 0x08, 0xd5, 0xc2, - 0xd7, 0x9a, 0x9b, 0xb2, 0x5a, 0x38, 0xd7, 0xa9, 0x7f, 0xe9, 0x87, 0x6b, - 0x31, 0xf9, 0x0b, 0xac, 0xd9, 0xfd, 0x50, 0x71, 0xe0, 0xdb, 0x82, 0x92, - 0x0f, 0x81, 0x9c, 0x8d, 0x77, 0xe9, 0xeb, 0x2e, 0xea, 0xd4, 0x23, 0x41, - 0x87, 0xec, 0x2d, 0xb2, 0x78, 0xb3, 0x8e, 0xb1, 0x67, 0xd2, 0xee, 0x71, - 0x03, 0x08, 0x12, 0x99, 0xb3, 0x02, 0x29, 0x6f, 0xde, 0x8b, 0xde, 0xc1, - 0xa9, 0x03, 0x0a, 0x5a, 0x33, 0x1c, 0x3d, 0x11, 0x03, 0xc6, 0x48, 0x0c, - 0x98, 0x9c, 0x15, 0x2e, 0xd9, 0xa6, 0x85, 0x52, 0xe7, 0x05, 0x8a, 0xae, - 0x30, 0x23, 0xeb, 0xed, 0x28, 0x6c, 0x60, 0xe9, 0x2d, 0x7f, 0x8f, 0x47, - 0x8b, 0x2f, 0xd0, 0xdc, 0xe6, 0xbb, 0x0f, 0x7e, 0x5f, 0xf2, 0x48, 0x81, - 0x8e, 0x50, 0x04, 0x63, 0xb1, 0x51, 0x80, 0x75, 0x9a, 0xa9, 0xb6, 0x10, - 0x1c, 0x10, 0x5f, 0x6f, 0x18, 0x6f, 0xe0, 0x0e, 0x96, 0x45, 0xce, 0xee, - 0xf1, 0xb5, 0x20, 0xdb, 0xef, 0xda, 0x6e, 0xc8, 0x95, 0xe3, 0xf6, 0x45, - 0xfd, 0xca, 0xfc, 0xa5, 0x5f, 0x49, 0x6d, 0x06, 0x1e, 0xd2, 0xde, 0x61, - 0x3d, 0x15, 0x7d, 0x37, 0xe5, 0x1c, 0x35, 0x8e, 0x06, 0xc2, 0x6b, 0xf7, - 0xb4, 0xa8, 0x28, 0x2c, 0x31, 0xcb, 0xaa, 0xb4, 0xa7, 0x97, 0x4f, 0x9d, - 0x8a, 0xf6, 0xaf, 0x7e, 0x37, 0xb9, 0x7b, 0x3d, 0xdf, 0x92, 0x66, 0x8b, - 0x8f, 0x4e, 0x9d, 0xc6, 0x36, 0xe7, 0x5c, 0xa6, 0xab, 0x12, 0x0f, 0xd6, - 0xcf -}; -unsigned int login_yahoo_com_1_cer_len = 1501; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.2.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.2.cer.h deleted file mode 100644 index 107dd15a..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.2.cer.h +++ /dev/null @@ -1,129 +0,0 @@ -unsigned char login_yahoo_com_2_cer[] = { - 0x30, 0x82, 0x05, 0xd9, 0x30, 0x82, 0x04, 0xc1, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x3e, 0x75, 0xce, 0xd4, 0x6b, 0x69, 0x30, 0x21, 0x21, - 0x88, 0x30, 0xae, 0x86, 0xa8, 0x2a, 0x71, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, - 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, - 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, - 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, - 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, - 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, - 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, 0x35, - 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, - 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, 0x37, - 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x46, - 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, 0x53, - 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, 0x31, - 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, - 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, 0x65, - 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, 0x26, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, - 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, 0x4c, - 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, - 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa1, - 0xa4, 0x05, 0x3d, 0xed, 0x85, 0x45, 0x93, 0x8a, 0x18, 0x4d, 0xc6, 0x03, - 0x00, 0x57, 0xe2, 0x40, 0x77, 0xf0, 0x1c, 0xeb, 0xd0, 0x19, 0xdf, 0x22, - 0x5d, 0x08, 0x7f, 0xd1, 0x07, 0x3c, 0x41, 0x89, 0x46, 0x17, 0xa3, 0x09, - 0xfa, 0xfc, 0xf8, 0xa9, 0x04, 0xd1, 0x96, 0x8f, 0xab, 0xd7, 0x4f, 0x3c, - 0xf9, 0xad, 0x18, 0xa9, 0x74, 0x81, 0xc4, 0x57, 0x0a, 0x3a, 0x26, 0x16, - 0xce, 0x62, 0x3e, 0xbc, 0x3f, 0x6c, 0x21, 0xee, 0x93, 0x8d, 0xcb, 0x0d, - 0xa0, 0x1f, 0x9a, 0x96, 0xd0, 0x8f, 0xad, 0xf5, 0x93, 0x93, 0x82, 0xee, - 0x72, 0x0c, 0xa1, 0x75, 0x15, 0xa3, 0x7b, 0x84, 0x56, 0xb8, 0xad, 0xff, - 0x52, 0x11, 0x71, 0x84, 0xbc, 0x3a, 0x30, 0x0b, 0x7e, 0x98, 0xa8, 0xe1, - 0xa8, 0x3f, 0x37, 0x52, 0xd0, 0xf1, 0x7c, 0x6f, 0x90, 0xd8, 0x45, 0x0a, - 0xac, 0x39, 0x72, 0x6a, 0x61, 0xd5, 0xbb, 0xc3, 0x8c, 0xf9, 0xc2, 0xcc, - 0xdf, 0xfd, 0x3a, 0x71, 0xb9, 0xaf, 0xbc, 0xdc, 0x3a, 0xdc, 0x0c, 0xb6, - 0xb1, 0xd2, 0xd1, 0x89, 0xbb, 0x41, 0xb6, 0xf2, 0xde, 0x57, 0xd5, 0x15, - 0xdf, 0xfc, 0xfd, 0xe2, 0x31, 0xc5, 0xdf, 0xca, 0xc1, 0xd8, 0x8f, 0x2c, - 0xbf, 0xf0, 0x0e, 0x5b, 0x71, 0xe0, 0x34, 0x71, 0xc3, 0xc5, 0x4d, 0x7d, - 0x7a, 0xd4, 0xfa, 0xed, 0x30, 0x4b, 0x2f, 0xea, 0xb6, 0x2e, 0x9e, 0x93, - 0x3c, 0xe2, 0x3a, 0xf8, 0x42, 0xa2, 0x1a, 0xee, 0xdc, 0xdf, 0xcd, 0x0f, - 0xa9, 0xf6, 0x79, 0x84, 0x1a, 0x8e, 0x6c, 0x02, 0xb6, 0x86, 0xe5, 0xbf, - 0x51, 0x6a, 0x66, 0xf8, 0xf3, 0x9c, 0xd3, 0x59, 0x0c, 0x7b, 0xa5, 0x99, - 0x78, 0xcd, 0x7c, 0x99, 0xfa, 0xc6, 0x96, 0x47, 0xd8, 0x32, 0xd4, 0x74, - 0x76, 0x0e, 0x77, 0x4b, 0x20, 0x74, 0xa4, 0xb7, 0x89, 0x75, 0x92, 0x4a, - 0xb4, 0x5b, 0x55, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xd5, - 0x30, 0x82, 0x01, 0xd1, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x86, 0x49, 0x45, 0xfc, 0x33, 0x19, 0x33, 0xd4, 0x04, 0xed, 0x27, 0x61, - 0xee, 0xe8, 0x01, 0xc9, 0x0c, 0x7f, 0x2f, 0x7e, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1a, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x13, 0x30, 0x11, 0x82, 0x0f, 0x6c, 0x6f, - 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, 0x6f, - 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x53, 0x69, 0x98, - 0x8e, 0x28, 0x4e, 0x9c, 0x2b, 0x5b, 0x1d, 0xcc, 0x6b, 0x77, 0x28, 0x3d, - 0xbb, 0xfa, 0xa5, 0x4e, 0x7e, 0x56, 0x29, 0xa4, 0xea, 0x10, 0xe2, 0xf4, - 0xe6, 0x2d, 0x06, 0xd1, 0x84, 0xdb, 0x23, 0xce, 0x97, 0xf3, 0x68, 0xb6, - 0x0f, 0x3a, 0xde, 0x15, 0x0b, 0x24, 0x1d, 0x91, 0xe3, 0x6c, 0x2e, 0x30, - 0xb7, 0xe9, 0x70, 0xb0, 0xc3, 0x46, 0x80, 0xf0, 0xd3, 0xb1, 0x51, 0xbf, - 0x4f, 0xd6, 0x78, 0xa0, 0xfc, 0xac, 0xc6, 0xcf, 0x31, 0x04, 0x63, 0xe2, - 0x34, 0x55, 0x05, 0x4a, 0x3d, 0xf6, 0x30, 0xba, 0xf3, 0x33, 0xe5, 0xba, - 0xd2, 0x96, 0xf3, 0xd5, 0xb1, 0xb6, 0x93, 0x89, 0x1a, 0xa4, 0x68, 0xbe, - 0x7e, 0xed, 0x63, 0xb4, 0x1a, 0x48, 0xc0, 0x53, 0xe4, 0xa3, 0xf0, 0x39, - 0x0c, 0x32, 0x92, 0xc7, 0x43, 0x0d, 0x1a, 0x71, 0xed, 0xd0, 0x46, 0x93, - 0xbf, 0x93, 0x62, 0x6c, 0x33, 0x4b, 0xcd, 0x36, 0x0d, 0x69, 0x5e, 0xbb, - 0x6c, 0x96, 0x99, 0x21, 0x69, 0xc4, 0x4b, 0x67, 0x72, 0xdb, 0x6c, 0x6a, - 0xb8, 0xf7, 0x68, 0xed, 0xc5, 0x8f, 0xad, 0x63, 0x65, 0x95, 0x0a, 0x4c, - 0xe0, 0xf9, 0x0f, 0x7e, 0x37, 0x3d, 0xaa, 0xd4, 0x93, 0xba, 0x67, 0x09, - 0xc3, 0xa5, 0xa4, 0x0d, 0x03, 0x5a, 0x6d, 0xd5, 0x0b, 0xfe, 0xf0, 0x40, - 0x14, 0xb4, 0xf6, 0xb8, 0x69, 0x7c, 0x6d, 0xc2, 0x32, 0x4b, 0x9f, 0xb5, - 0x1a, 0xe7, 0x46, 0xae, 0x4c, 0x5a, 0x2b, 0xaa, 0x7a, 0x5e, 0x90, 0x57, - 0x95, 0xfa, 0xdb, 0x66, 0x02, 0x20, 0x1e, 0x6a, 0x69, 0x66, 0x15, 0x9c, - 0xc2, 0xb6, 0xf5, 0xbc, 0x50, 0xb5, 0xfd, 0x45, 0xc7, 0x1f, 0x68, 0xb4, - 0x47, 0x59, 0xac, 0xc4, 0x1b, 0x28, 0x93, 0x4e, 0x52, 0x53, 0x12, 0x03, - 0x58, 0x4b, 0x71, 0x83, 0x9f, 0x66, 0xe6, 0xac, 0x79, 0x48, 0xfe, 0xfe, - 0x47 -}; -unsigned int login_yahoo_com_2_cer_len = 1501; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.cer.h deleted file mode 100644 index 4f5ba040..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.cer.h +++ /dev/null @@ -1,130 +0,0 @@ -unsigned char login_yahoo_com_cer[] = { - 0x30, 0x82, 0x05, 0xef, 0x30, 0x82, 0x04, 0xd7, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xd7, 0x55, 0x8f, 0xda, 0xf5, 0xf1, 0x10, 0x5b, - 0xb2, 0x13, 0x28, 0x2b, 0x70, 0x77, 0x29, 0xa3, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, - 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, - 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, - 0xa1, 0xa4, 0x05, 0x3d, 0xed, 0x85, 0x45, 0x93, 0x8a, 0x18, 0x4d, 0xc6, - 0x03, 0x00, 0x57, 0xe2, 0x40, 0x77, 0xf0, 0x1c, 0xeb, 0xd0, 0x19, 0xdf, - 0x22, 0x5d, 0x08, 0x7f, 0xd1, 0x07, 0x3c, 0x41, 0x89, 0x46, 0x17, 0xa3, - 0x09, 0xfa, 0xfc, 0xf8, 0xa9, 0x04, 0xd1, 0x96, 0x8f, 0xab, 0xd7, 0x4f, - 0x3c, 0xf9, 0xad, 0x18, 0xa9, 0x74, 0x81, 0xc4, 0x57, 0x0a, 0x3a, 0x26, - 0x16, 0xce, 0x62, 0x3e, 0xbc, 0x3f, 0x6c, 0x21, 0xee, 0x93, 0x8d, 0xcb, - 0x0d, 0xa0, 0x1f, 0x9a, 0x96, 0xd0, 0x8f, 0xad, 0xf5, 0x93, 0x93, 0x82, - 0xee, 0x72, 0x0c, 0xa1, 0x75, 0x15, 0xa3, 0x7b, 0x84, 0x56, 0xb8, 0xad, - 0xff, 0x52, 0x11, 0x71, 0x84, 0xbc, 0x3a, 0x30, 0x0b, 0x7e, 0x98, 0xa8, - 0xe1, 0xa8, 0x3f, 0x37, 0x52, 0xd0, 0xf1, 0x7c, 0x6f, 0x90, 0xd8, 0x45, - 0x0a, 0xac, 0x39, 0x72, 0x6a, 0x61, 0xd5, 0xbb, 0xc3, 0x8c, 0xf9, 0xc2, - 0xcc, 0xdf, 0xfd, 0x3a, 0x71, 0xb9, 0xaf, 0xbc, 0xdc, 0x3a, 0xdc, 0x0c, - 0xb6, 0xb1, 0xd2, 0xd1, 0x89, 0xbb, 0x41, 0xb6, 0xf2, 0xde, 0x57, 0xd5, - 0x15, 0xdf, 0xfc, 0xfd, 0xe2, 0x31, 0xc5, 0xdf, 0xca, 0xc1, 0xd8, 0x8f, - 0x2c, 0xbf, 0xf0, 0x0e, 0x5b, 0x71, 0xe0, 0x34, 0x71, 0xc3, 0xc5, 0x4d, - 0x7d, 0x7a, 0xd4, 0xfa, 0xed, 0x30, 0x4b, 0x2f, 0xea, 0xb6, 0x2e, 0x9e, - 0x93, 0x3c, 0xe2, 0x3a, 0xf8, 0x42, 0xa2, 0x1a, 0xee, 0xdc, 0xdf, 0xcd, - 0x0f, 0xa9, 0xf6, 0x79, 0x84, 0x1a, 0x8e, 0x6c, 0x02, 0xb6, 0x86, 0xe5, - 0xbf, 0x51, 0x6a, 0x66, 0xf8, 0xf3, 0x9c, 0xd3, 0x59, 0x0c, 0x7b, 0xa5, - 0x99, 0x78, 0xcd, 0x7c, 0x99, 0xfa, 0xc6, 0x96, 0x47, 0xd8, 0x32, 0xd4, - 0x74, 0x76, 0x0e, 0x77, 0x4b, 0x20, 0x74, 0xa4, 0xb7, 0x89, 0x75, 0x92, - 0x4a, 0xb4, 0x5b, 0x55, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, - 0xea, 0x30, 0x82, 0x01, 0xe6, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, - 0x98, 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, - 0xc3, 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0x86, 0x49, 0x45, 0xfc, 0x33, 0x19, 0x33, 0xd4, 0x04, 0xed, 0x27, - 0x61, 0xee, 0xe8, 0x01, 0xc9, 0x0c, 0x7f, 0x2f, 0x7e, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, - 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, - 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, - 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, - 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, - 0x0c, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, - 0x04, 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, - 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, - 0x64, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, - 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, - 0x36, 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, - 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, - 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, - 0x32, 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, - 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, - 0x63, 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, - 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, - 0x41, 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, - 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x2f, - 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x28, 0x30, 0x26, 0x82, 0x0f, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, - 0x6f, 0x6d, 0x82, 0x13, 0x77, 0x77, 0x77, 0x2e, 0x6c, 0x6f, 0x67, 0x69, - 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x3d, 0x57, 0xc9, 0x48, 0x24, - 0x5c, 0xee, 0x64, 0x81, 0xf5, 0xae, 0xbe, 0x55, 0x29, 0x16, 0xff, 0x2a, - 0x2f, 0x84, 0xed, 0xd9, 0xf8, 0xa3, 0x03, 0xc8, 0x30, 0x66, 0xbb, 0xc8, - 0xd4, 0x81, 0x2d, 0x21, 0xf7, 0x08, 0xf7, 0xac, 0x96, 0x42, 0x9a, 0x41, - 0x75, 0x7a, 0xba, 0x5d, 0x10, 0x23, 0xcb, 0x92, 0x42, 0x61, 0xfa, 0x8a, - 0xda, 0x6d, 0x65, 0x34, 0x19, 0xe5, 0xa9, 0xd6, 0x2d, 0x13, 0x78, 0xd7, - 0x81, 0x44, 0x92, 0xa9, 0x6e, 0x80, 0x63, 0x15, 0xcb, 0xfe, 0x35, 0x1f, - 0x02, 0xd1, 0x8a, 0x14, 0xb0, 0xa8, 0xcc, 0x94, 0x20, 0x3b, 0xa8, 0x1a, - 0xf0, 0x5d, 0x36, 0x50, 0xdb, 0x0d, 0xae, 0xe9, 0x64, 0xe4, 0xf6, 0x8d, - 0x69, 0x7d, 0x30, 0xc8, 0x14, 0x17, 0x00, 0x4a, 0xe5, 0xa6, 0x35, 0xfb, - 0x7d, 0x0d, 0x22, 0x9d, 0x79, 0x76, 0x52, 0x2c, 0xbc, 0x97, 0x06, 0x88, - 0x9a, 0x15, 0xf4, 0x73, 0xe6, 0xf1, 0xf5, 0x98, 0xa5, 0xcd, 0x07, 0x44, - 0x91, 0xb8, 0xa7, 0x68, 0x67, 0x45, 0xd2, 0x72, 0x11, 0x60, 0xe2, 0x71, - 0xb7, 0x50, 0x55, 0xe2, 0x8a, 0xa9, 0x0d, 0xd6, 0x92, 0xee, 0x04, 0x2a, - 0x8b, 0x30, 0xa0, 0xa2, 0x05, 0x46, 0x34, 0x6d, 0x92, 0xc6, 0x3b, 0xaa, - 0x4d, 0xa0, 0xd0, 0xab, 0x01, 0x19, 0x0a, 0x32, 0xb7, 0xe8, 0xe3, 0xcf, - 0xf1, 0xd2, 0x97, 0x49, 0x7b, 0xac, 0xa4, 0x97, 0xf7, 0xf0, 0x57, 0xae, - 0x63, 0x77, 0x9a, 0x7f, 0x96, 0xda, 0x4d, 0xfd, 0xbe, 0xdc, 0x07, 0x36, - 0xe3, 0x25, 0xbd, 0x89, 0x79, 0x8e, 0x29, 0x12, 0x13, 0x8b, 0x88, 0x07, - 0xfb, 0x6b, 0xdb, 0xa4, 0xcd, 0xb3, 0x2d, 0x27, 0xe9, 0xd4, 0xca, 0x60, - 0xd7, 0x85, 0x53, 0xfb, 0x74, 0xc6, 0x5c, 0x35, 0x8c, 0x70, 0x1f, 0xf9, - 0xb2, 0xb7, 0x92, 0x27, 0x20, 0xc7, 0x94, 0xd5, 0x67, 0x14, 0x30 -}; -unsigned int login_yahoo_com_cer_len = 1523; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/mail.google.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/mail.google.com.cer.h deleted file mode 100644 index 21f5c081..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/mail.google.com.cer.h +++ /dev/null @@ -1,130 +0,0 @@ -unsigned char mail_google_com_cer[] = { - 0x30, 0x82, 0x05, 0xee, 0x30, 0x82, 0x04, 0xd6, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x04, 0x7e, 0xcb, 0xe9, 0xfc, 0xa5, 0x5f, 0x7b, 0xd0, - 0x9e, 0xae, 0x36, 0xe1, 0x0c, 0xae, 0x1e, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, - 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, - 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, - 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, - 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, - 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, - 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, 0x35, - 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, - 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, 0x37, - 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x46, - 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, 0x53, - 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, 0x31, - 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, - 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, 0x65, - 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, 0x26, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, - 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, 0x4c, - 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x6d, - 0x61, 0x69, 0x6c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb0, - 0x73, 0xf0, 0xf2, 0x04, 0xee, 0xc2, 0xa2, 0x46, 0xca, 0x34, 0x2a, 0xaa, - 0xbb, 0x60, 0x23, 0xd1, 0x11, 0x76, 0x1f, 0x1f, 0x3a, 0xd0, 0x65, 0x83, - 0x4e, 0x9a, 0x45, 0xa8, 0x43, 0x70, 0x85, 0x76, 0xf0, 0x1f, 0x87, 0x00, - 0x02, 0x1f, 0x6e, 0x3b, 0x17, 0x17, 0xc4, 0xb5, 0xe9, 0x19, 0x46, 0xa2, - 0x92, 0x25, 0x8d, 0x62, 0x2a, 0xb4, 0x63, 0x30, 0x1f, 0xb9, 0x85, 0xf8, - 0x35, 0xe1, 0x16, 0x5a, 0x76, 0x49, 0xcc, 0x50, 0x48, 0x53, 0x39, 0x59, - 0x89, 0xd6, 0x84, 0x02, 0xfb, 0x9a, 0xec, 0x1b, 0xc7, 0x51, 0xd5, 0x76, - 0x95, 0x90, 0xd4, 0x3a, 0x2a, 0xb8, 0xa6, 0xde, 0x02, 0x4d, 0x06, 0xfb, - 0xcd, 0xed, 0xa5, 0x46, 0x41, 0x5f, 0x55, 0x74, 0xe5, 0xec, 0x7e, 0x40, - 0xdc, 0x50, 0x9c, 0xb5, 0xe4, 0x35, 0x5d, 0x1e, 0x68, 0x20, 0xf8, 0xe9, - 0xde, 0xa3, 0x6a, 0x28, 0xbf, 0x41, 0xd2, 0xa1, 0xb3, 0xe2, 0x25, 0x8d, - 0x0c, 0x1b, 0xca, 0x3d, 0x93, 0x0c, 0x18, 0xae, 0xdf, 0xc5, 0xbc, 0xfd, - 0xbc, 0x82, 0xba, 0x68, 0x00, 0xd7, 0x16, 0x32, 0x71, 0x9f, 0x65, 0xb5, - 0x11, 0xda, 0x68, 0x59, 0xd0, 0xa6, 0x57, 0x64, 0x1b, 0xc9, 0xfe, 0x98, - 0xe5, 0xf5, 0xa5, 0x65, 0xea, 0xe1, 0xdb, 0xee, 0xf4, 0xb3, 0x9d, 0xb3, - 0x8e, 0xea, 0x87, 0xae, 0x16, 0xd2, 0x1e, 0xa0, 0x7c, 0x7c, 0x69, 0x3f, - 0x29, 0x16, 0x85, 0x01, 0x53, 0xa7, 0x6c, 0xf1, 0x60, 0xab, 0xdd, 0xa2, - 0xfc, 0x25, 0x47, 0xd4, 0x32, 0xd1, 0x12, 0xdd, 0xf7, 0x48, 0x12, 0xe0, - 0xfc, 0x9c, 0xa2, 0x77, 0x98, 0xe9, 0x89, 0x99, 0xb8, 0xf8, 0x38, 0xf1, - 0x8c, 0x06, 0xc2, 0x7a, 0x23, 0x36, 0x6d, 0x9b, 0x9d, 0xcd, 0x30, 0xc8, - 0xc7, 0x34, 0x17, 0x1e, 0xbb, 0x7d, 0x42, 0xc8, 0xab, 0xe7, 0x15, 0x16, - 0xf6, 0x73, 0xb5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xea, - 0x30, 0x82, 0x01, 0xe6, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x18, 0x2a, 0xa2, 0xc8, 0xd4, 0x7a, 0x3f, 0x7b, 0xad, 0x04, 0x8b, 0xbd, - 0x6f, 0x9e, 0x10, 0x46, 0x13, 0x78, 0x71, 0x9d, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x2f, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x28, 0x30, 0x26, 0x82, 0x0f, 0x6d, 0x61, - 0x69, 0x6c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x82, 0x13, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x61, 0x69, 0x6c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x67, 0x06, 0x08, 0x0a, 0x27, 0xc5, - 0x93, 0x6e, 0x02, 0xf2, 0xde, 0x17, 0x3f, 0xd0, 0xd3, 0x1b, 0x7c, 0xff, - 0xb5, 0xcd, 0x7a, 0xc7, 0x77, 0xc7, 0xbe, 0xdf, 0x12, 0xca, 0x19, 0xde, - 0xb0, 0x13, 0x57, 0x0c, 0x03, 0x91, 0xc4, 0x79, 0x52, 0xcf, 0x7f, 0xb7, - 0x5e, 0x55, 0x20, 0x84, 0x49, 0xdd, 0xf5, 0xd0, 0x29, 0x2f, 0x0e, 0x04, - 0xda, 0x59, 0x9e, 0x0e, 0x13, 0x9f, 0xf4, 0xc0, 0x32, 0x9b, 0xff, 0xa1, - 0x11, 0x24, 0x2a, 0x97, 0xa3, 0xf2, 0x3f, 0x3d, 0x2a, 0x6b, 0xa8, 0xad, - 0x8c, 0x19, 0x75, 0x95, 0x0e, 0x1d, 0x25, 0xfd, 0x4f, 0xc4, 0x7a, 0x15, - 0xc3, 0x1d, 0xc7, 0x13, 0x40, 0xc8, 0x0d, 0xbe, 0x97, 0x60, 0x72, 0xa6, - 0xfe, 0x25, 0xbe, 0x8f, 0xec, 0xd5, 0xa6, 0x86, 0xc3, 0x21, 0x5c, 0x59, - 0x52, 0xd9, 0x6a, 0x0b, 0x5c, 0x9f, 0x4b, 0xde, 0xb5, 0xf9, 0xec, 0xe2, - 0xf4, 0xc5, 0xcc, 0x62, 0x53, 0x76, 0x89, 0x65, 0xe4, 0x29, 0xda, 0xb7, - 0xbf, 0x96, 0xe0, 0x60, 0x8d, 0x0d, 0xb7, 0x09, 0x55, 0xd6, 0x40, 0x55, - 0x1d, 0xc1, 0xf2, 0x96, 0x21, 0x75, 0xaf, 0x89, 0x86, 0x1f, 0x5d, 0x81, - 0x97, 0x29, 0x28, 0x1e, 0x29, 0xd7, 0x96, 0xc1, 0x20, 0x03, 0x32, 0x7b, - 0x00, 0x3b, 0x6a, 0x37, 0x17, 0x5a, 0xa3, 0xb3, 0x1a, 0x6f, 0x32, 0x3b, - 0x6e, 0xf1, 0xa3, 0x5d, 0xab, 0xab, 0xcc, 0x2a, 0xcb, 0x30, 0x0c, 0x1f, - 0x35, 0x23, 0x8b, 0x69, 0x44, 0x5c, 0xea, 0xac, 0x28, 0x60, 0xed, 0xab, - 0x6b, 0x63, 0x9e, 0xf6, 0x92, 0xbc, 0xbd, 0x9a, 0x5a, 0x26, 0x4c, 0xc5, - 0x98, 0xb8, 0x0e, 0x19, 0x3e, 0xfc, 0x05, 0x31, 0xe3, 0x16, 0xd9, 0xfd, - 0x90, 0x05, 0x03, 0x86, 0xc6, 0x57, 0x01, 0x1f, 0x7f, 0x78, 0xa0, 0xcf, - 0x33, 0x6a, 0xaa, 0x66, 0x6b, 0x22, 0xd0, 0xa7, 0x49, 0x23 -}; -unsigned int mail_google_com_cer_len = 1522; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/www.google.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/www.google.com.cer.h deleted file mode 100644 index 0754b97f..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/www.google.com.cer.h +++ /dev/null @@ -1,129 +0,0 @@ -unsigned char www_google_com_cer[] = { - 0x30, 0x82, 0x05, 0xe4, 0x30, 0x82, 0x04, 0xcc, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xf5, 0xc8, 0x6a, 0xf3, 0x61, 0x62, 0xf1, 0x3a, - 0x64, 0xf5, 0x4f, 0x6d, 0xc9, 0x58, 0x7c, 0x06, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xde, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, - 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb0, - 0x73, 0xf0, 0xf2, 0x04, 0xee, 0xc2, 0xa2, 0x46, 0xca, 0x34, 0x2a, 0xaa, - 0xbb, 0x60, 0x23, 0xd1, 0x11, 0x76, 0x1f, 0x1f, 0x3a, 0xd0, 0x65, 0x83, - 0x4e, 0x9a, 0x45, 0xa8, 0x43, 0x70, 0x85, 0x76, 0xf0, 0x1f, 0x87, 0x00, - 0x02, 0x1f, 0x6e, 0x3b, 0x17, 0x17, 0xc4, 0xb5, 0xe9, 0x19, 0x46, 0xa2, - 0x92, 0x25, 0x8d, 0x62, 0x2a, 0xb4, 0x63, 0x30, 0x1f, 0xb9, 0x85, 0xf8, - 0x35, 0xe1, 0x16, 0x5a, 0x76, 0x49, 0xcc, 0x50, 0x48, 0x53, 0x39, 0x59, - 0x89, 0xd6, 0x84, 0x02, 0xfb, 0x9a, 0xec, 0x1b, 0xc7, 0x51, 0xd5, 0x76, - 0x95, 0x90, 0xd4, 0x3a, 0x2a, 0xb8, 0xa6, 0xde, 0x02, 0x4d, 0x06, 0xfb, - 0xcd, 0xed, 0xa5, 0x46, 0x41, 0x5f, 0x55, 0x74, 0xe5, 0xec, 0x7e, 0x40, - 0xdc, 0x50, 0x9c, 0xb5, 0xe4, 0x35, 0x5d, 0x1e, 0x68, 0x20, 0xf8, 0xe9, - 0xde, 0xa3, 0x6a, 0x28, 0xbf, 0x41, 0xd2, 0xa1, 0xb3, 0xe2, 0x25, 0x8d, - 0x0c, 0x1b, 0xca, 0x3d, 0x93, 0x0c, 0x18, 0xae, 0xdf, 0xc5, 0xbc, 0xfd, - 0xbc, 0x82, 0xba, 0x68, 0x00, 0xd7, 0x16, 0x32, 0x71, 0x9f, 0x65, 0xb5, - 0x11, 0xda, 0x68, 0x59, 0xd0, 0xa6, 0x57, 0x64, 0x1b, 0xc9, 0xfe, 0x98, - 0xe5, 0xf5, 0xa5, 0x65, 0xea, 0xe1, 0xdb, 0xee, 0xf4, 0xb3, 0x9d, 0xb3, - 0x8e, 0xea, 0x87, 0xae, 0x16, 0xd2, 0x1e, 0xa0, 0x7c, 0x7c, 0x69, 0x3f, - 0x29, 0x16, 0x85, 0x01, 0x53, 0xa7, 0x6c, 0xf1, 0x60, 0xab, 0xdd, 0xa2, - 0xfc, 0x25, 0x47, 0xd4, 0x32, 0xd1, 0x12, 0xdd, 0xf7, 0x48, 0x12, 0xe0, - 0xfc, 0x9c, 0xa2, 0x77, 0x98, 0xe9, 0x89, 0x99, 0xb8, 0xf8, 0x38, 0xf1, - 0x8c, 0x06, 0xc2, 0x7a, 0x23, 0x36, 0x6d, 0x9b, 0x9d, 0xcd, 0x30, 0xc8, - 0xc7, 0x34, 0x17, 0x1e, 0xbb, 0x7d, 0x42, 0xc8, 0xab, 0xe7, 0x15, 0x16, - 0xf6, 0x73, 0xb5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xe0, - 0x30, 0x82, 0x01, 0xdc, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x18, 0x2a, 0xa2, 0xc8, 0xd4, 0x7a, 0x3f, 0x7b, 0xad, 0x04, 0x8b, 0xbd, - 0x6f, 0x9e, 0x10, 0x46, 0x13, 0x78, 0x71, 0x9d, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x25, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x1e, 0x30, 0x1c, 0x82, 0x0e, 0x77, 0x77, - 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x82, 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x71, 0xc0, 0x99, 0x3f, - 0x5e, 0xf6, 0xbd, 0x33, 0xff, 0x9e, 0x16, 0xcb, 0xa8, 0xbf, 0xdd, 0x70, - 0xf9, 0xd2, 0x53, 0x3b, 0x36, 0xae, 0xc9, 0x17, 0xc8, 0xae, 0x5e, 0x4d, - 0xdd, 0x62, 0xf7, 0xb7, 0xd3, 0x3e, 0x77, 0xa3, 0xfe, 0xc0, 0x7b, 0x32, - 0xb5, 0xc9, 0x94, 0x05, 0x52, 0x50, 0xf2, 0x5f, 0x3d, 0x79, 0x84, 0x49, - 0x4f, 0x5d, 0x6c, 0xb0, 0xd7, 0x59, 0xbd, 0xd4, 0x6c, 0x88, 0xfa, 0xfc, - 0xc5, 0x65, 0x86, 0xeb, 0x28, 0x52, 0xa2, 0x42, 0xf6, 0x7c, 0xbc, 0x6a, - 0xc7, 0x07, 0x2e, 0x25, 0xd1, 0x90, 0x62, 0x20, 0xc6, 0x8d, 0x51, 0xc2, - 0x2c, 0x45, 0x39, 0x4e, 0x03, 0xda, 0xf7, 0x18, 0xe8, 0xcc, 0x0a, 0x3a, - 0xd9, 0x45, 0xd8, 0x6c, 0x6e, 0x34, 0x8b, 0x62, 0x9c, 0x4e, 0x15, 0xf9, - 0x43, 0xee, 0xe5, 0x97, 0xc0, 0x3f, 0xad, 0x35, 0x13, 0xc5, 0x2b, 0x06, - 0xc7, 0x41, 0xfd, 0xe2, 0xf7, 0x7e, 0x45, 0xad, 0x9b, 0xd1, 0xe1, 0x66, - 0xed, 0xf8, 0x7a, 0x4b, 0x94, 0x39, 0x7a, 0x2f, 0xeb, 0xe8, 0x3f, 0x43, - 0xd8, 0x35, 0xd6, 0x56, 0xfa, 0x74, 0xe7, 0x6d, 0xe6, 0xed, 0xac, 0x65, - 0x84, 0xfe, 0xd0, 0x4d, 0x06, 0x12, 0xde, 0xda, 0x59, 0x00, 0x3c, 0x09, - 0x5c, 0xcf, 0x88, 0x4b, 0xe8, 0x3d, 0xb4, 0x15, 0x21, 0x92, 0xcc, 0x6d, - 0xa6, 0x51, 0xe2, 0x8e, 0x97, 0xf1, 0xf4, 0x82, 0x46, 0xcb, 0xc4, 0x53, - 0x5e, 0xda, 0x5c, 0x9d, 0x65, 0x92, 0x01, 0x65, 0x89, 0x00, 0xe5, 0xb6, - 0x99, 0xff, 0x26, 0x40, 0xf1, 0x2f, 0x19, 0x31, 0x08, 0x1a, 0xb1, 0x67, - 0x55, 0x86, 0x0d, 0xae, 0x35, 0x33, 0x86, 0xbc, 0x97, 0x48, 0x92, 0xd7, - 0x96, 0x60, 0xf8, 0xce, 0xfc, 0x96, 0xeb, 0x87, 0xc4, 0x73, 0xcc, 0x94, - 0x9b, 0x58, 0x5b, 0xf3, 0x7a, 0xa4, 0x27, 0x13, 0xd6, 0x4f, 0xf4, 0x69 -}; -unsigned int www_google_com_cer_len = 1512; diff --git a/OSX/sec/Security/Regressions/secitem/si-70-sectrust-unified.c b/OSX/sec/Security/Regressions/secitem/si-70-sectrust-unified.c deleted file mode 100644 index fce8b222..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-70-sectrust-unified.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2013-2014 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -// -// si-70-sectrust-unified.c -// regressions -// -// -// -#include -#include -#include -#include -#include - -#include "shared_regressions.h" -#include - -/* This is a minimal test case to ensure that the functionality of - * TLF: SecTrust Unification is present - * and working. Needs to be expanded and split up into separate - * test case files in the future. - */ - -/* SecPolicy: new in 7.0 */ -//CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) -//OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef policies) /* (this was SPI in 6.0) */ -//SecPolicyRef SecPolicyCreateRevocation(CFIndex revocationFlags) -//SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, CFDictionaryRef properties) - -/* SecTrust new in 7.0 */ -//OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies) -//OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, Boolean allowFetch) -//OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, Boolean *allowFetch) -//OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchors) -//CFDictionaryRef SecTrustCopyResult(SecTrustRef trust) -//OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData) - - -/* subject:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com */ -/* issuer :/C=US/O=Google Trust Services/CN=Google Internet Authority G3 */ -const uint8_t google_cert[]={ - 0x30,0x82,0x03,0xC7,0x30,0x82,0x02,0xAF,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x55, - 0x81,0x47,0xC4,0x26,0x8C,0x3F,0xC2,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x54,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, - 0x06,0x13,0x02,0x55,0x53,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x0A,0x13,0x15, - 0x47,0x6F,0x6F,0x67,0x6C,0x65,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x72, - 0x76,0x69,0x63,0x65,0x73,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x03,0x13,0x1C, - 0x47,0x6F,0x6F,0x67,0x6C,0x65,0x20,0x49,0x6E,0x74,0x65,0x72,0x6E,0x65,0x74,0x20, - 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x47,0x33,0x30,0x1E,0x17,0x0D, - 0x31,0x38,0x30,0x35,0x30,0x38,0x31,0x34,0x34,0x37,0x34,0x33,0x5A,0x17,0x0D,0x31, - 0x38,0x30,0x37,0x33,0x31,0x31,0x33,0x32,0x37,0x30,0x30,0x5A,0x30,0x68,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, - 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, - 0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x07,0x0C,0x0D,0x4D,0x6F,0x75,0x6E,0x74, - 0x61,0x69,0x6E,0x20,0x56,0x69,0x65,0x77,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x0A,0x0C,0x0A,0x47,0x6F,0x6F,0x67,0x6C,0x65,0x20,0x4C,0x4C,0x43,0x31,0x17,0x30, - 0x15,0x06,0x03,0x55,0x04,0x03,0x0C,0x0E,0x77,0x77,0x77,0x2E,0x67,0x6F,0x6F,0x67, - 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE, - 0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00, - 0x04,0xDD,0x10,0xCB,0x4F,0xB1,0x49,0xF9,0xE8,0xC2,0x8E,0xB5,0xB9,0xC3,0x7D,0xCC, - 0x9D,0x94,0x3A,0x91,0x19,0x7C,0xA9,0xB3,0x78,0x81,0x21,0x01,0xC0,0x76,0x12,0xA9, - 0x84,0x65,0xDF,0xD3,0xE2,0x51,0xFF,0x17,0x9F,0x69,0x0F,0x0B,0xFA,0x04,0x0D,0xBA, - 0x35,0xBB,0xE8,0x1F,0x14,0x66,0xB7,0xC7,0xD7,0xFC,0xEB,0x10,0xD6,0xCD,0x79,0x8A, - 0x22,0xA3,0x82,0x01,0x52,0x30,0x82,0x01,0x4E,0x30,0x13,0x06,0x03,0x55,0x1D,0x25, - 0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x0E, - 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x19, - 0x06,0x03,0x55,0x1D,0x11,0x04,0x12,0x30,0x10,0x82,0x0E,0x77,0x77,0x77,0x2E,0x67, - 0x6F,0x6F,0x67,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x68,0x06,0x08,0x2B,0x06,0x01, - 0x05,0x05,0x07,0x01,0x01,0x04,0x5C,0x30,0x5A,0x30,0x2D,0x06,0x08,0x2B,0x06,0x01, - 0x05,0x05,0x07,0x30,0x02,0x86,0x21,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x70,0x6B, - 0x69,0x2E,0x67,0x6F,0x6F,0x67,0x2F,0x67,0x73,0x72,0x32,0x2F,0x47,0x54,0x53,0x47, - 0x49,0x41,0x47,0x33,0x2E,0x63,0x72,0x74,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x30,0x01,0x86,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, - 0x70,0x2E,0x70,0x6B,0x69,0x2E,0x67,0x6F,0x6F,0x67,0x2F,0x47,0x54,0x53,0x47,0x49, - 0x41,0x47,0x33,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x2B,0x53, - 0xE0,0x79,0xD4,0xFD,0xA4,0xD4,0xDF,0x18,0x6B,0xDD,0x80,0x4D,0x11,0x35,0xC7,0xB2, - 0x41,0xCC,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00, - 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x77,0xC2,0xB8, - 0x50,0x9A,0x67,0x76,0x76,0xB1,0x2D,0xC2,0x86,0xD0,0x83,0xA0,0x7E,0xA6,0x7E,0xBA, - 0x4B,0x30,0x21,0x06,0x03,0x55,0x1D,0x20,0x04,0x1A,0x30,0x18,0x30,0x0C,0x06,0x0A, - 0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x05,0x03,0x30,0x08,0x06,0x06,0x67,0x81, - 0x0C,0x01,0x02,0x02,0x30,0x31,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2A,0x30,0x28,0x30, - 0x26,0xA0,0x24,0xA0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72, - 0x6C,0x2E,0x70,0x6B,0x69,0x2E,0x67,0x6F,0x6F,0x67,0x2F,0x47,0x54,0x53,0x47,0x49, - 0x41,0x47,0x33,0x2E,0x63,0x72,0x6C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6E,0x85,0x02,0xC0,0xF0, - 0x15,0xBF,0xAF,0x4F,0x29,0x73,0x19,0x87,0x7F,0x30,0xB3,0x24,0xD1,0xEE,0xA7,0xDC, - 0x90,0x44,0x30,0xC1,0xA0,0x84,0x65,0x52,0x26,0xE6,0xAD,0x0D,0xCA,0x43,0xEE,0xB6, - 0x6B,0x37,0x9D,0xFF,0x97,0x80,0x09,0x85,0x58,0x46,0xEC,0xFF,0xF2,0x42,0x6A,0xBB, - 0xE6,0xA3,0xB4,0x9B,0x26,0x26,0xA8,0x53,0xA9,0xB9,0x95,0xB6,0x42,0x06,0x94,0xED, - 0x31,0xC5,0x33,0xF7,0x91,0x6A,0x90,0x4B,0xD2,0x8A,0x45,0xAE,0x3A,0xA0,0x10,0x27, - 0xAE,0xF4,0x9A,0xC9,0x5E,0x63,0x20,0xAD,0xF2,0xCB,0xDC,0x74,0xA8,0x83,0x32,0x56, - 0x6D,0xAA,0x6C,0xCA,0xBC,0xCC,0x71,0x23,0xD4,0xAC,0xA9,0xAE,0xEA,0x04,0xD6,0x75, - 0xE7,0xBF,0x18,0xC7,0x9C,0xCC,0x7B,0xE6,0x81,0x62,0xC6,0xFA,0x17,0xA8,0x82,0x2F, - 0xCC,0xE9,0xAC,0xEF,0x81,0xCC,0xAE,0x1A,0x1C,0x79,0x35,0x7B,0x54,0xFE,0x06,0x57, - 0x2F,0x58,0xD0,0x7C,0x4E,0x5A,0x75,0xAE,0xCC,0x31,0xD6,0x20,0xA6,0xB1,0xDA,0x39, - 0x9E,0x46,0x5B,0x15,0x76,0xF2,0x3E,0x2C,0xB1,0x5E,0xBF,0x7F,0x29,0xE3,0xBE,0xC6, - 0xF3,0xE5,0xEB,0xD5,0x91,0x48,0x84,0x41,0x7B,0xB6,0x3B,0x83,0xC6,0xCE,0x1B,0xE2, - 0x88,0x44,0x91,0x89,0x72,0x27,0xF9,0xD2,0x72,0x33,0xCF,0xC3,0xB2,0x52,0x38,0x65, - 0x17,0x14,0x00,0x4E,0x36,0x1C,0xC2,0xAD,0xBF,0x7F,0x3A,0x18,0xF7,0x52,0xFA,0x3B, - 0x86,0x18,0xF3,0x24,0x97,0xF7,0x35,0x58,0x48,0x0D,0x7D,0x93,0x18,0xA7,0x14,0x52, - 0x1A,0x19,0x9D,0xDB,0xD5,0xCC,0xA3,0xC5,0x48,0x6D,0x8A, -}; - -/* subject:/C=US/O=Google Trust Services/CN=Google Internet Authority G3 */ -/* issuer :/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign */ -const uint8_t _GIAG3[]={ - 0x30,0x82,0x04,0x5C,0x30,0x82,0x03,0x44,0xA0,0x03,0x02,0x01,0x02,0x02,0x0D,0x01, - 0xE3,0xA9,0x30,0x1C,0xFC,0x72,0x06,0x38,0x3F,0x9A,0x53,0x1D,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x4C,0x31,0x20,0x30, - 0x1E,0x06,0x03,0x55,0x04,0x0B,0x13,0x17,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69, - 0x67,0x6E,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x52,0x32,0x31, - 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C, - 0x53,0x69,0x67,0x6E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0A,0x47, - 0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x30,0x1E,0x17,0x0D,0x31,0x37,0x30, - 0x36,0x31,0x35,0x30,0x30,0x30,0x30,0x34,0x32,0x5A,0x17,0x0D,0x32,0x31,0x31,0x32, - 0x31,0x35,0x30,0x30,0x30,0x30,0x34,0x32,0x5A,0x30,0x54,0x31,0x0B,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04, - 0x0A,0x13,0x15,0x47,0x6F,0x6F,0x67,0x6C,0x65,0x20,0x54,0x72,0x75,0x73,0x74,0x20, - 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04, - 0x03,0x13,0x1C,0x47,0x6F,0x6F,0x67,0x6C,0x65,0x20,0x49,0x6E,0x74,0x65,0x72,0x6E, - 0x65,0x74,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x47,0x33,0x30, - 0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, - 0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00, - 0xCA,0x52,0x4B,0xEA,0x1E,0xFF,0xCE,0x24,0x6B,0xA8,0xDA,0x72,0x18,0x68,0xD5,0x56, - 0x5D,0x0E,0x48,0x5A,0x2D,0x35,0x09,0x76,0x5A,0xCF,0xA4,0xC8,0x1C,0xB1,0xA9,0xFE, - 0x53,0x89,0xFB,0xAD,0x34,0xFF,0x88,0x5B,0x9F,0xBB,0xE7,0xE8,0x00,0x01,0xDC,0x35, - 0x73,0x75,0x03,0xAD,0xB3,0xB1,0xB9,0xA4,0x7D,0x2B,0x26,0x79,0xCE,0x15,0x40,0x0A, - 0xEF,0x51,0xB8,0x9F,0x32,0x8C,0x7C,0x70,0x86,0x52,0x4B,0x16,0xFE,0x6A,0x27,0x6B, - 0xE6,0x36,0x7A,0x62,0x50,0xD8,0xDF,0x9A,0x89,0xCC,0x09,0x29,0xEB,0x4F,0x29,0x14, - 0x88,0x80,0x0B,0x8F,0x38,0x1E,0x80,0x6A,0x18,0x7C,0x1D,0xBD,0x97,0x3B,0x78,0x7D, - 0x45,0x49,0x36,0x4F,0x41,0xCD,0xA2,0xE0,0x76,0x57,0x3C,0x68,0x31,0x79,0x64,0xC9, - 0x6E,0xD7,0x51,0x1E,0x66,0xC3,0xA2,0x64,0x2C,0x79,0xC0,0xE7,0x65,0xC3,0x56,0x84, - 0x53,0x5A,0x43,0x6D,0xCB,0x9A,0x02,0x20,0xD2,0xEF,0x1A,0x69,0xD1,0xB0,0x9D,0x73, - 0xA2,0xE0,0x2A,0x60,0x65,0x50,0x31,0xCF,0xFB,0xB3,0x2F,0xBF,0x11,0x88,0x40,0x2E, - 0xB5,0x49,0x10,0x0F,0x0A,0x6E,0xDC,0x97,0xFA,0xBF,0x2C,0x9F,0x05,0x39,0x0B,0x58, - 0x54,0xAF,0x06,0x96,0xE8,0xC5,0x8E,0x01,0x16,0xBC,0xA8,0x1A,0x4D,0x41,0xC5,0x93, - 0x91,0xA2,0x1E,0xA1,0x8B,0xF2,0xFE,0xC1,0x88,0x24,0x49,0xA3,0x47,0x4B,0xC5,0x13, - 0x01,0xDD,0xA7,0x57,0x12,0x69,0x62,0x2B,0xEB,0xFE,0x20,0xEF,0x69,0xFB,0x3A,0xA5, - 0xF0,0x7E,0x29,0xEE,0xED,0x96,0x16,0xF7,0xB1,0x1F,0xA0,0xE4,0x90,0x25,0xE0,0x33, - 0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x33,0x30,0x82,0x01,0x2F,0x30,0x0E,0x06, - 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x1D,0x06, - 0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x12,0x06,0x03, - 0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x77,0xC2,0xB8,0x50,0x9A, - 0x67,0x76,0x76,0xB1,0x2D,0xC2,0x86,0xD0,0x83,0xA0,0x7E,0xA6,0x7E,0xBA,0x4B,0x30, - 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x9B,0xE2,0x07,0x57, - 0x67,0x1C,0x1E,0xC0,0x6A,0x06,0xDE,0x59,0xB4,0x9A,0x2D,0xDF,0xDC,0x19,0x86,0x2E, - 0x30,0x35,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x29,0x30,0x27, - 0x30,0x25,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x19,0x68,0x74, - 0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x70,0x6B,0x69,0x2E,0x67,0x6F, - 0x6F,0x67,0x2F,0x67,0x73,0x72,0x32,0x30,0x32,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2B, - 0x30,0x29,0x30,0x27,0xA0,0x25,0xA0,0x23,0x86,0x21,0x68,0x74,0x74,0x70,0x3A,0x2F, - 0x2F,0x63,0x72,0x6C,0x2E,0x70,0x6B,0x69,0x2E,0x67,0x6F,0x6F,0x67,0x2F,0x67,0x73, - 0x72,0x32,0x2F,0x67,0x73,0x72,0x32,0x2E,0x63,0x72,0x6C,0x30,0x3F,0x06,0x03,0x55, - 0x1D,0x20,0x04,0x38,0x30,0x36,0x30,0x34,0x06,0x06,0x67,0x81,0x0C,0x01,0x02,0x02, - 0x30,0x2A,0x30,0x28,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C, - 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x70,0x6B,0x69,0x2E,0x67,0x6F,0x6F,0x67, - 0x2F,0x72,0x65,0x70,0x6F,0x73,0x69,0x74,0x6F,0x72,0x79,0x2F,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00, - 0x1C,0xB7,0x89,0x96,0xE4,0x53,0xED,0xBB,0xEC,0xDB,0xA8,0x32,0x01,0x9F,0x2C,0xA3, - 0xCD,0x6D,0xAD,0x42,0x12,0x77,0xB3,0xB8,0xE6,0xC9,0x03,0x52,0x60,0x20,0x7B,0x57, - 0x27,0xC6,0x11,0xB5,0x3F,0x67,0x0D,0x99,0x2C,0x5B,0x5A,0xCA,0x22,0x0A,0xDD,0x9E, - 0xBB,0x1F,0x4B,0x48,0x3F,0x8F,0x02,0x3D,0x8B,0x21,0x84,0x45,0x1D,0x6D,0xF5,0xFF, - 0xAC,0x68,0x89,0xCD,0x64,0xE2,0xD6,0xD6,0x5E,0x40,0xC2,0x8E,0x2A,0xF7,0xEF,0x14, - 0xD3,0x36,0xA4,0x40,0x30,0xF5,0x32,0x15,0x15,0x92,0x76,0xFB,0x7E,0x9E,0x53,0xEA, - 0xC2,0x76,0xFC,0x39,0xAD,0x88,0xFE,0x66,0x92,0x26,0xE9,0x1C,0xC4,0x38,0xCD,0x49, - 0xFA,0x43,0x87,0xF0,0x5D,0xD6,0x56,0x4D,0x81,0xD7,0x7F,0xF1,0xC2,0xDD,0xB0,0x4D, - 0xFE,0xC3,0x2A,0x6E,0x7C,0x9F,0x6E,0x5C,0xED,0x62,0x42,0x99,0xE1,0xF7,0x36,0xEE, - 0x14,0x8C,0x2C,0x20,0xE3,0x46,0x97,0x5A,0x77,0x03,0xC0,0xA0,0xC6,0x4A,0x88,0xFD, - 0x40,0x22,0x87,0x72,0x5A,0x18,0xEA,0x9C,0xA5,0xC7,0x5A,0x08,0x8C,0xE4,0x05,0xA4, - 0x7D,0xB9,0x84,0x35,0x5F,0x89,0x36,0x56,0x0E,0x40,0x3D,0x12,0xE8,0xBB,0x35,0x72, - 0xED,0xAF,0x08,0x56,0x4E,0xB0,0xBB,0x2E,0xA9,0x9B,0xE4,0xFB,0x1D,0x3E,0x0B,0x63, - 0xC8,0x9B,0x4B,0x91,0x44,0x66,0x57,0xC0,0x14,0xB4,0x96,0xF0,0xDC,0x2C,0x57,0x3F, - 0x52,0x04,0xAD,0x95,0xAA,0x7D,0x4D,0xD0,0xF2,0x0C,0x9F,0x9C,0x40,0xE8,0xD6,0x55, - 0x73,0xBA,0x3C,0xDF,0x90,0xCB,0x00,0x5B,0x21,0x11,0x67,0xC2,0xED,0x32,0x1E,0xDE, -}; - - -static void tests(void) -{ - SecTrustResultType trustResult; - SecTrustRef trust = NULL; - SecPolicyRef policy = NULL; - CFArrayRef certs = NULL; - CFDateRef date = NULL; - - const void *cert_google; - isnt(cert_google = SecCertificateCreateWithBytes(NULL, google_cert, - sizeof(google_cert)), NULL, "create cert_google"); - certs = CFArrayCreate(NULL, &cert_google, 1, NULL); - - bool server = true; - policy = SecPolicyCreateSSL(server, CFSTR("www2.google.com")); // deliberate hostname mismatch - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "create trust for ssl server www2.google.com"); - CFReleaseSafe(certs); - date = CFDateCreate(NULL, 548800000.0); /* May 23, 2018" */ - ok_status(SecTrustSetVerifyDate(trust, date), "set trust date to May 23, 2018"); - - /* This test uses a root which is no longer in our trust store, - * so we need explicitly set it as a trusted anchor - */ - SecCertificateRef _anchor; - isnt(_anchor = SecCertificateCreateWithBytes(NULL, _GIAG3, sizeof(_GIAG3)), - NULL, "create root"); - const void *v_roots[] = { _anchor }; - CFArrayRef _anchors; - isnt(_anchors = CFArrayCreate(NULL, v_roots, array_size(v_roots), NULL), - NULL, "create anchors"); - SecTrustSetAnchorCertificates(trust, _anchors); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate google trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, - "trust is kSecTrustResultRecoverableTrustFailure (hostname mismatch)"); - - /* Test SecPolicyCreateRevocation */ - { - /* FIXME need to do more than just call the function, but it's a start */ - SecPolicyRef revocation = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); - isnt(revocation, NULL, "create revocation policy"); - CFReleaseSafe(revocation); - } - - /* Test SecTrustCopyPolicies */ - { - CFArrayRef policies = NULL; - ok_status(SecTrustCopyPolicies(trust, &policies), "copy policies"); - is((policies && (CFArrayGetCount(policies) > 0)), true, "non-empty policies"); - CFReleaseSafe(policies); - } - - /* Test SecTrustSetNetworkFetchAllowed */ - { - Boolean curAllow, allow; - ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); - allow = !curAllow; /* flip it and see if the setting sticks */ - ok_status(SecTrustSetNetworkFetchAllowed(trust, allow)); - ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); - is((allow == curAllow), true, "network fetch toggle"); - - /* ensure trust with revocation policy returns the correct status */ - SecPolicyRef revocation = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); - ok_status(SecTrustSetPolicies(trust, revocation)); - ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); - is(curAllow, true, "network fetch set for revocation policy"); - - SecPolicyRef basic = SecPolicyCreateBasicX509(); - CFMutableArrayRef policies = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(policies, basic); - CFArrayAppendValue(policies, revocation); - ok_status(SecTrustSetPolicies(trust, policies)); - ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); - is(curAllow, true, "network fetch set for basic+revocation policy"); - CFReleaseNull(revocation); - CFReleaseNull(basic); - CFReleaseNull(policies); - - revocation = SecPolicyCreateRevocation(kSecRevocationNetworkAccessDisabled); - ok_status(SecTrustSetPolicies(trust, revocation)); - ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); - is(curAllow, false, "network fetch not set for revocation policy"); - CFReleaseNull(revocation); - } - - /* Test setting OCSP response data */ - { - CFDataRef resp = (CFDataRef) CFDataCreateMutable(NULL, 0); - /* FIXME: use actual OCSPResponse DER blob */ - CFDataIncreaseLength((CFMutableDataRef)resp, 64); /* arbitrary length, zero-filled data */ - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnonnull" - // NULL passed as 'trust' newly generates a warning, we need to suppress it in order to compile - is_status(SecTrustSetOCSPResponse(NULL, resp), errSecParam, "SecTrustSetOCSPResponse param 1 check OK"); -#pragma clang diagnostic pop - is_status(SecTrustSetOCSPResponse(trust, NULL), errSecSuccess, "SecTrustSetOCSPResponse param 2 check OK"); - is_status(SecTrustSetOCSPResponse(trust, resp), errSecSuccess, "SecTrustSetOCSPResponse OK"); - CFReleaseSafe(resp); - } - - /* Test creation of a policy via SecPolicyCreateWithProperties */ - CFReleaseNull(policy); - { - const void *keys[] = { kSecPolicyName, kSecPolicyClient }; - const void *values[] = { CFSTR("www.google.com"), kCFBooleanFalse }; - CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, - array_size(keys), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - policy = SecPolicyCreateWithProperties(kSecPolicyAppleSSL, properties); - isnt(policy, NULL, "SecPolicyCreateWithProperties"); - CFReleaseSafe(properties); - } - if (!policy) { goto errOut; } - - /* Test introspection of a policy's properties via SecPolicyCopyProperties */ - { - CFDictionaryRef properties = NULL; - isnt(properties = SecPolicyCopyProperties(policy), NULL, "copy policy properties"); - CFTypeRef value = NULL; - is(CFDictionaryGetValueIfPresent(properties, kSecPolicyName, (const void **)&value) && - kCFCompareEqualTo == CFStringCompare((CFStringRef)value, CFSTR("www.google.com"), 0), - true, "has policy name"); - is(CFDictionaryGetValueIfPresent(properties, kSecPolicyOid, (const void **)&value) && - CFEqual(value, kSecPolicyAppleSSL) , true, "has SSL policy"); - CFReleaseSafe(properties); - } - /* Test setting new policy on a trust via SecTrustSetPolicies */ - ok_status(SecTrustSetPolicies(trust, policy)); - /* Evaluation should now succeed, since our new policy has the correct hostname */ - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate google trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - - /* Make sure we can get the results */ - { - CFDictionaryRef results = NULL; - SecTrustResultType anotherResult = kSecTrustResultInvalid; - ok_status(SecTrustGetTrustResult(trust, &anotherResult), "get trust result"); - is_status(trustResult, anotherResult, "trust is kSecTrustResultUnspecified"); - - isnt(results = SecTrustCopyResult(trust), NULL, "copy trust results"); - CFReleaseSafe(results); - } - -errOut: - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(date); - CFReleaseSafe(cert_google); - - CFReleaseSafe(_anchor); - CFReleaseSafe(_anchors); -} - -int si_70_sectrust_unified(int argc, char *const *argv) -{ - plan_tests(36); - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c b/OSX/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c deleted file mode 100644 index bc8c78f2..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -//#if defined(NO_SERVER) && NO_SERVER == 1 - -__unused static const uint8_t kDemoContentSigningCert[] = { - 0x30, 0x82, 0x04, 0x1a, 0x30, 0x82, 0x03, 0x02, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x47, - 0x62, 0x58, 0xaa, 0x2c, 0xdd, 0x90, 0xc1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x87, 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0c, 0x32, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x20, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, - 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x30, 0x34, 0x32, 0x31, 0x34, 0x37, 0x31, 0x37, - 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x36, 0x30, 0x33, 0x32, 0x31, 0x34, 0x37, 0x31, 0x37, 0x5a, - 0x30, 0x53, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x14, 0x44, 0x65, 0x6d, - 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, - 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, 0x65, - 0x20, 0x4f, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, - 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xaf, 0x2a, 0xac, 0x4b, 0x91, 0x1e, 0x4d, 0x9f, 0x1d, 0x23, - 0xf3, 0xff, 0x1c, 0xbe, 0x87, 0xbe, 0x3e, 0x2a, 0x0f, 0x35, 0xf4, 0xad, 0x80, 0x01, 0xc3, 0xf6, - 0x6b, 0x12, 0xc4, 0xfa, 0x0f, 0xf5, 0xbc, 0xc0, 0x79, 0x76, 0xad, 0x77, 0xb1, 0x8d, 0xdc, 0xe7, - 0xa0, 0x8a, 0xe0, 0x6a, 0xa3, 0xdb, 0x24, 0xb6, 0x0b, 0xa5, 0x29, 0x13, 0xe0, 0xd4, 0x96, 0xc7, - 0x1e, 0xee, 0x9b, 0x56, 0x63, 0xdd, 0xab, 0x9b, 0x4e, 0x7d, 0x09, 0xa7, 0x3f, 0xf9, 0xec, 0x96, - 0xcb, 0x88, 0x62, 0x91, 0xfe, 0xb8, 0x10, 0xe4, 0x40, 0x10, 0xb5, 0x34, 0x8a, 0x8e, 0x9a, 0x28, - 0x16, 0xc3, 0x8e, 0x06, 0xda, 0x32, 0x04, 0x64, 0x60, 0x3b, 0xae, 0x70, 0x24, 0xb0, 0xcc, 0x6c, - 0x76, 0x69, 0xb3, 0x52, 0x8f, 0x9c, 0x7a, 0xfb, 0x68, 0x55, 0x88, 0x2f, 0xd8, 0x18, 0xe0, 0x51, - 0x43, 0xdb, 0x91, 0x9f, 0x10, 0xcf, 0xd8, 0x93, 0x6e, 0x5d, 0xef, 0x90, 0xac, 0x47, 0x56, 0xf7, - 0x32, 0xd3, 0xf0, 0xb4, 0x9d, 0x68, 0x94, 0xdd, 0x4f, 0xf9, 0x5a, 0xb4, 0x9a, 0x81, 0xf8, 0xef, - 0xae, 0xd8, 0x27, 0x4d, 0xec, 0xc5, 0x7d, 0xc2, 0xfe, 0x80, 0x23, 0x4d, 0x13, 0xc9, 0x90, 0x5a, - 0x91, 0x86, 0x30, 0x42, 0x7d, 0x38, 0xda, 0x17, 0xa8, 0x46, 0x3e, 0x76, 0x8c, 0xca, 0x5e, 0x20, - 0x1d, 0x3b, 0x85, 0xda, 0x87, 0x9d, 0xf1, 0xc7, 0x1d, 0x3c, 0x13, 0x4a, 0x56, 0xd4, 0x23, 0x52, - 0x96, 0x6b, 0xb8, 0x99, 0x79, 0x03, 0x88, 0xbd, 0xf0, 0xf2, 0x28, 0x79, 0x1b, 0xe7, 0x8e, 0xfc, - 0xd0, 0x30, 0xf3, 0x0b, 0x3e, 0x15, 0xff, 0x20, 0x5c, 0x42, 0x67, 0x7e, 0x0e, 0x52, 0x86, 0x50, - 0xa0, 0x36, 0xb8, 0xc3, 0xee, 0x3d, 0xd8, 0xd6, 0x77, 0x15, 0xb7, 0x8f, 0xed, 0xf6, 0x42, 0xe4, - 0xfc, 0x52, 0xf6, 0x45, 0x67, 0x41, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xbc, 0x30, 0x81, - 0xb9, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x32, 0x30, - 0x30, 0x30, 0x2e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x22, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x34, 0x2d, 0x61, 0x73, 0x69, 0x30, - 0x32, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x55, 0xac, 0xda, 0x4b, - 0xad, 0xf1, 0xe8, 0xe4, 0x2f, 0x72, 0xc2, 0x02, 0x2b, 0xaa, 0x01, 0x23, 0x9c, 0x96, 0x86, 0xdb, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, - 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x12, 0x75, 0x7c, 0x47, 0x92, - 0xfd, 0x83, 0xe3, 0xbe, 0x2e, 0xfc, 0x59, 0x7f, 0x67, 0x43, 0x81, 0x35, 0x10, 0x45, 0xec, 0x30, - 0x19, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x0f, 0x30, 0x0d, 0x30, 0x0b, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x0c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, - 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x27, 0x50, - 0xf8, 0x85, 0xe0, 0x6a, 0xf6, 0x74, 0x26, 0xcb, 0x5a, 0x23, 0xef, 0xd8, 0x32, 0xa0, 0x87, 0xf0, - 0x01, 0x29, 0x1c, 0x64, 0x84, 0x9e, 0xc6, 0x3b, 0xd7, 0x9e, 0x40, 0x8b, 0x0a, 0x8c, 0x9d, 0xd5, - 0x9b, 0x77, 0xc6, 0x5c, 0xe6, 0x52, 0xfb, 0x5b, 0x41, 0x2b, 0xbb, 0x8c, 0x24, 0xd5, 0xaf, 0xa1, - 0xab, 0x2b, 0xda, 0x3e, 0x11, 0x6b, 0x51, 0xe5, 0xc8, 0xb9, 0xf7, 0x1b, 0x0c, 0x89, 0x6e, 0x29, - 0x1a, 0x88, 0x24, 0xf9, 0x03, 0x2d, 0x46, 0x14, 0x07, 0xff, 0x3f, 0xd2, 0x2b, 0x87, 0x9b, 0xdb, - 0x5c, 0x06, 0x4a, 0x20, 0x4d, 0xf6, 0x33, 0xb1, 0x06, 0x93, 0x87, 0x27, 0x5c, 0x93, 0xca, 0xf6, - 0x81, 0x79, 0x71, 0x82, 0x1b, 0x88, 0x1d, 0x5a, 0x67, 0xc6, 0x2c, 0xd7, 0x68, 0x69, 0xbb, 0x07, - 0x1d, 0x12, 0xae, 0x78, 0x4c, 0xfa, 0x4e, 0xc5, 0x80, 0x5c, 0x2d, 0xd4, 0xb0, 0xcf, 0x71, 0x64, - 0x9e, 0xf8, 0xf3, 0x99, 0xd4, 0xd9, 0xdb, 0xbf, 0xd7, 0xb8, 0x97, 0x24, 0x3f, 0x34, 0x19, 0x52, - 0x73, 0xac, 0xca, 0x31, 0xac, 0x0d, 0xb5, 0x72, 0x11, 0x2d, 0x03, 0x7b, 0xce, 0xf6, 0x1e, 0x84, - 0x09, 0x3b, 0x47, 0xa0, 0x6a, 0xd6, 0x54, 0x60, 0x6d, 0x76, 0x6d, 0x02, 0xbb, 0xa8, 0x69, 0xa8, - 0x58, 0xb5, 0xe2, 0x34, 0xdb, 0x8d, 0xb2, 0x96, 0x17, 0x47, 0x6d, 0xbc, 0xe9, 0xc6, 0xc9, 0xae, - 0xc0, 0x54, 0xcf, 0x98, 0xc9, 0xea, 0x92, 0x69, 0x7f, 0x92, 0x82, 0x19, 0x63, 0x45, 0x5b, 0xeb, - 0x85, 0x0b, 0xaa, 0x7e, 0x4a, 0x77, 0xb4, 0xf9, 0x45, 0xe8, 0x0e, 0x1e, 0x1f, 0xab, 0x1c, 0x86, - 0x59, 0xa8, 0x82, 0x1e, 0x73, 0x86, 0x44, 0xfc, 0x67, 0x2a, 0x71, 0xeb, 0xb9, 0x9e, 0xd0, 0x28, - 0xd7, 0xb1, 0xef, 0xa3, 0x8c, 0x0d, 0x18, 0xd4, 0x8c, 0x1c, 0xb3, 0x0e, 0xba, 0x30 -}; - -__unused static const uint8_t kTestDemoContentSigningCert[] = { - 0x30, 0x82, 0x04, 0x20, 0x30, 0x82, 0x03, 0x08, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x75, - 0x93, 0x8a, 0xaa, 0xe6, 0x6e, 0x3c, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x87, 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0c, 0x32, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x20, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, - 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x30, 0x34, 0x30, 0x30, 0x30, 0x32, 0x35, 0x32, - 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x36, 0x30, 0x33, 0x30, 0x30, 0x30, 0x32, 0x35, 0x32, 0x5a, - 0x30, 0x58, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x54, 0x65, 0x73, - 0x74, 0x20, 0x44, 0x65, 0x6d, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x53, - 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, - 0x07, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x4f, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xac, 0xc5, 0x87, 0x0d, 0x3b, - 0x14, 0xba, 0x87, 0x63, 0x3d, 0xc9, 0x8d, 0xc1, 0x3a, 0xa9, 0x71, 0x14, 0x30, 0x6b, 0x64, 0x58, - 0x35, 0xb2, 0xff, 0xcf, 0xe1, 0xe1, 0x5c, 0xa8, 0x5d, 0x99, 0xed, 0x11, 0x53, 0xf5, 0x6f, 0x92, - 0x39, 0x28, 0x5a, 0x0f, 0x76, 0x86, 0x40, 0x44, 0x6a, 0x7b, 0x23, 0x05, 0x50, 0xfd, 0x1b, 0x29, - 0xd9, 0x83, 0xfe, 0x0b, 0x65, 0xc6, 0x35, 0x8c, 0x69, 0x4e, 0x93, 0xa3, 0x32, 0x74, 0x18, 0xd4, - 0x06, 0xaf, 0xe5, 0x74, 0xb9, 0x63, 0x89, 0x41, 0x25, 0x2f, 0x15, 0xb6, 0x71, 0x45, 0x02, 0x5e, - 0x71, 0x11, 0xec, 0xea, 0xb8, 0x3a, 0x3d, 0xf2, 0x87, 0x2b, 0x71, 0xb8, 0x7e, 0xc8, 0xc7, 0x06, - 0x12, 0x87, 0x21, 0x61, 0x2f, 0xeb, 0x33, 0x44, 0xe1, 0x3e, 0xa7, 0x77, 0x6a, 0xfe, 0x5d, 0xee, - 0x4c, 0x77, 0x57, 0x74, 0xf7, 0x64, 0x2b, 0x6f, 0x12, 0x1b, 0x0e, 0xec, 0x49, 0x41, 0x81, 0x93, - 0x6b, 0xf9, 0x3b, 0x4e, 0x83, 0x53, 0xd7, 0x05, 0xe0, 0x29, 0x78, 0xf2, 0xd3, 0xe5, 0x81, 0x6f, - 0x47, 0xd1, 0xc8, 0xae, 0xb3, 0x22, 0xa9, 0x29, 0x61, 0xe2, 0x36, 0x26, 0xb9, 0x0d, 0x9d, 0x23, - 0x90, 0x45, 0x8b, 0x42, 0xbc, 0x8b, 0x60, 0xd5, 0xd2, 0x56, 0xc6, 0x09, 0xfd, 0x45, 0xff, 0x8c, - 0x54, 0x69, 0x74, 0x81, 0x90, 0x7a, 0x31, 0x6f, 0xf0, 0x16, 0x4c, 0xef, 0x1c, 0xa9, 0x97, 0xc9, - 0x4e, 0xfe, 0x7d, 0x87, 0x7a, 0x47, 0x3f, 0xa5, 0xc8, 0x20, 0xd3, 0x4a, 0xe2, 0xf3, 0xf6, 0x3a, - 0xf1, 0xef, 0x24, 0x5e, 0x35, 0xc8, 0xdf, 0x7b, 0x12, 0xda, 0xcc, 0xef, 0xbb, 0xf2, 0xfa, 0x28, - 0xf6, 0x38, 0x57, 0xcf, 0x41, 0xd6, 0x43, 0x21, 0x62, 0xc6, 0xa3, 0x3f, 0xf5, 0xd1, 0x86, 0x41, - 0x42, 0xb6, 0x69, 0xca, 0xb0, 0x8a, 0xba, 0xba, 0xbe, 0x97, 0x85, 0x02, 0x03, 0x01, 0x00, 0x01, - 0xa3, 0x81, 0xbd, 0x30, 0x81, 0xba, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x32, 0x30, 0x30, 0x30, 0x2e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x30, 0x01, 0x86, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, - 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x34, - 0x2d, 0x61, 0x73, 0x69, 0x30, 0x33, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0x0a, 0x8f, 0x13, 0x24, 0x0d, 0xc4, 0xe4, 0xe7, 0x97, 0x65, 0x35, 0xc8, 0x19, 0x91, 0x38, - 0x28, 0xce, 0x9b, 0x50, 0xdb, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, - 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, - 0x12, 0x75, 0x7c, 0x47, 0x92, 0xfd, 0x83, 0xe3, 0xbe, 0x2e, 0xfc, 0x59, 0x7f, 0x67, 0x43, 0x81, - 0x35, 0x10, 0x45, 0xec, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x10, - 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x0c, 0x01, - 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x01, 0x00, 0x59, 0x19, 0xdd, 0x6c, 0xf5, 0xb6, 0xf9, 0x93, 0x69, 0xe5, 0xcd, 0x64, - 0x5c, 0x4c, 0xaa, 0xd8, 0x86, 0x44, 0x6b, 0xca, 0x48, 0x6f, 0x2b, 0x15, 0x8f, 0xef, 0x1a, 0x5c, - 0xc9, 0xb2, 0x5b, 0x51, 0xee, 0xae, 0xf8, 0xeb, 0x7e, 0x05, 0x4a, 0xa1, 0x27, 0xd3, 0x15, 0x41, - 0xa1, 0x2c, 0x7e, 0x81, 0x96, 0xa8, 0xba, 0x8d, 0x1c, 0xc0, 0x0a, 0xce, 0xfd, 0x4b, 0xbc, 0x56, - 0x80, 0xe8, 0xf1, 0x04, 0x05, 0xd9, 0x17, 0x3d, 0x29, 0x6d, 0x99, 0xf5, 0xcc, 0x3a, 0x80, 0x7c, - 0x03, 0xb0, 0x8a, 0x4e, 0x2c, 0xdb, 0x24, 0x42, 0xa7, 0xa6, 0x8b, 0x2e, 0xff, 0x9c, 0xec, 0xce, - 0xe0, 0x0f, 0xd3, 0x5c, 0x0a, 0xed, 0x35, 0x14, 0xd0, 0x33, 0x76, 0xe0, 0x46, 0x09, 0x35, 0x54, - 0x40, 0x9b, 0x56, 0x8a, 0x45, 0x17, 0xa7, 0x50, 0x95, 0x5c, 0x9f, 0x5e, 0x95, 0x26, 0x89, 0xfe, - 0x79, 0xc6, 0x01, 0x3b, 0xf9, 0x64, 0x83, 0x28, 0x2b, 0x2d, 0x24, 0xbd, 0xb8, 0x4a, 0xca, 0x9a, - 0xba, 0x59, 0x5f, 0x72, 0xdd, 0x90, 0xcc, 0x4c, 0xed, 0x49, 0xf6, 0x11, 0x10, 0x7c, 0x34, 0x86, - 0x3f, 0x3e, 0x9a, 0xc0, 0xe6, 0xda, 0xf0, 0x6d, 0xb0, 0xd2, 0xf0, 0x46, 0x1e, 0x33, 0x53, 0x4a, - 0x5c, 0xd3, 0xdc, 0x9b, 0x74, 0x3d, 0x3e, 0x85, 0x9c, 0x19, 0xca, 0xb5, 0x26, 0xd5, 0xda, 0x22, - 0x7d, 0x52, 0xe6, 0x8c, 0x95, 0xd8, 0x30, 0x61, 0xf5, 0x3e, 0x05, 0x40, 0xe5, 0xd0, 0xcb, 0x91, - 0x28, 0x17, 0x4c, 0xf3, 0xf8, 0x06, 0x4c, 0x71, 0x80, 0xe0, 0x7c, 0x11, 0x7b, 0x00, 0xed, 0xe6, - 0x93, 0x8c, 0x12, 0x9e, 0xcc, 0x65, 0x5a, 0xb6, 0x61, 0x21, 0xe0, 0x0f, 0x3a, 0x8e, 0xcf, 0x12, - 0xea, 0x16, 0xbb, 0x91, 0x7e, 0x6c, 0x11, 0xb2, 0x29, 0x8a, 0x41, 0x46, 0xc3, 0xae, 0xd9, 0xf7, - 0x15, 0xe8, 0xaa, 0x86 -}; - -__unused static const uint8_t kMobileIntermediate[] = { - 0x30, 0x82, 0x04, 0x13, 0x30, 0x82, 0x02, 0xfb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x60, - 0x25, 0x4e, 0x56, 0x81, 0x16, 0xcf, 0xf1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x41, 0x70, 0x70, - 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, - 0x30, 0x39, 0x31, 0x33, 0x32, 0x32, 0x33, 0x35, 0x33, 0x37, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, - 0x39, 0x31, 0x33, 0x32, 0x32, 0x33, 0x35, 0x33, 0x37, 0x5a, 0x30, 0x81, 0x87, 0x31, 0x3b, 0x30, - 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x32, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, - 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, - 0x02, 0x82, 0x01, 0x01, 0x00, 0x9e, 0x48, 0xf6, 0x8f, 0xab, 0x1b, 0x89, 0xa5, 0x9f, 0x34, 0x47, - 0xb6, 0x38, 0x30, 0xa7, 0xb0, 0x62, 0xa4, 0x99, 0x84, 0x2a, 0x74, 0x4b, 0x47, 0x5b, 0x66, 0x35, - 0x69, 0xfe, 0x97, 0x01, 0x64, 0x18, 0x9d, 0x0a, 0xf8, 0xd7, 0x33, 0x2a, 0x64, 0xd8, 0xbc, 0x03, - 0x4f, 0xcd, 0x4d, 0x80, 0x90, 0xd2, 0xc3, 0xc5, 0xd1, 0x8c, 0xc1, 0x73, 0xf6, 0x5a, 0x50, 0x70, - 0xcd, 0xe0, 0x94, 0x35, 0x82, 0xc4, 0x59, 0xca, 0xba, 0xa9, 0x94, 0xbd, 0x88, 0x36, 0x7a, 0x32, - 0xdf, 0x08, 0x29, 0xe0, 0x9c, 0x19, 0x1c, 0x68, 0x02, 0x60, 0x87, 0xfc, 0x2e, 0x8a, 0x3c, 0x37, - 0x4d, 0x7c, 0x81, 0xbb, 0x6c, 0x6f, 0x72, 0x45, 0xf5, 0xb3, 0x96, 0x66, 0x5e, 0xab, 0x97, 0x54, - 0x50, 0x03, 0xc0, 0x41, 0xfc, 0xb5, 0xa8, 0xf7, 0x78, 0xde, 0x4c, 0x9a, 0x67, 0xf4, 0x4d, 0x27, - 0x54, 0x9e, 0xc8, 0x75, 0xea, 0x8c, 0x76, 0xc1, 0xb5, 0x79, 0xe3, 0x60, 0xce, 0x98, 0x21, 0x38, - 0x7b, 0x9a, 0x53, 0xe8, 0x57, 0x69, 0x13, 0xf0, 0xf0, 0x86, 0x91, 0x2e, 0xad, 0x75, 0xb9, 0x53, - 0x4a, 0x30, 0xf6, 0x6d, 0x96, 0x8e, 0x5e, 0xe7, 0xe9, 0xa5, 0x16, 0xe7, 0xb4, 0x5b, 0xe7, 0xe9, - 0x6e, 0x4f, 0xe7, 0x38, 0xda, 0x53, 0x39, 0x60, 0x0e, 0xfd, 0xd0, 0x0b, 0x19, 0x52, 0x5d, 0x79, - 0x3a, 0x5d, 0x7b, 0x0d, 0x19, 0x91, 0x72, 0x94, 0x0e, 0x03, 0xa6, 0x14, 0xca, 0xdd, 0x7a, 0x27, - 0xed, 0x22, 0x21, 0xeb, 0x67, 0x01, 0xc0, 0x98, 0x4f, 0xf7, 0x78, 0x81, 0x34, 0xfb, 0x08, 0x48, - 0xb6, 0xec, 0xa4, 0xdb, 0x60, 0xd3, 0x9d, 0xa7, 0x46, 0x6c, 0x50, 0xa6, 0x14, 0x4a, 0x30, 0xee, - 0x77, 0x87, 0x64, 0xb6, 0xb2, 0xb4, 0x92, 0xfc, 0x45, 0xb3, 0x80, 0x59, 0xbd, 0x85, 0x9c, 0x2f, - 0xd1, 0xd7, 0x59, 0xe3, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa6, 0x30, 0x81, 0xa3, - 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x12, 0x75, 0x7c, 0x47, 0x92, - 0xfd, 0x83, 0xe3, 0xbe, 0x2e, 0xfc, 0x59, 0x7f, 0x67, 0x43, 0x81, 0x35, 0x10, 0x45, 0xec, 0x30, - 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x2b, 0xd0, 0x69, - 0x47, 0x94, 0x76, 0x09, 0xfe, 0xf4, 0x6b, 0x8d, 0x2e, 0x40, 0xa6, 0xf7, 0x47, 0x4d, 0x7f, 0x08, - 0x5e, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x27, 0x30, 0x25, 0x30, 0x23, 0xa0, 0x21, - 0xa0, 0x1f, 0x86, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x61, - 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x63, 0x72, - 0x6c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, - 0x06, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, 0x02, 0x0a, 0x04, - 0x02, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x3d, 0x38, 0x8a, 0x96, 0x9b, 0xc7, 0x94, 0x97, - 0x3d, 0x3e, 0x5b, 0x1f, 0x09, 0x43, 0xe1, 0x1a, 0x6e, 0x6a, 0x4d, 0xd6, 0x38, 0xbb, 0x8a, 0x6d, - 0x00, 0xc9, 0x93, 0xdc, 0x3e, 0xa2, 0xc3, 0x2a, 0x97, 0xc1, 0x4f, 0x07, 0xa0, 0xa3, 0x14, 0x6c, - 0xd9, 0x0b, 0x9a, 0xcd, 0xb1, 0xcf, 0x7c, 0xc0, 0x67, 0x75, 0x12, 0xee, 0x2e, 0xb0, 0x28, 0x17, - 0x18, 0x7e, 0x73, 0x3d, 0xb4, 0x04, 0x91, 0x39, 0x7c, 0x37, 0xfb, 0xbd, 0x34, 0x01, 0xa0, 0xde, - 0x77, 0xa7, 0x5b, 0xb6, 0x47, 0x8e, 0x73, 0x3a, 0x8f, 0x7b, 0x63, 0x58, 0xc4, 0xa3, 0x6d, 0x19, - 0x4d, 0x9d, 0x9e, 0xd6, 0x3e, 0xbe, 0x18, 0x53, 0xe9, 0x30, 0x4d, 0xd2, 0xad, 0xef, 0x4b, 0xf6, - 0xa4, 0x84, 0xcf, 0x25, 0xfc, 0xea, 0x0d, 0x33, 0x58, 0x51, 0x00, 0xe2, 0x4b, 0xfe, 0x74, 0xd9, - 0x47, 0x13, 0x9e, 0xa7, 0xd7, 0x37, 0x6a, 0xea, 0x27, 0x0c, 0x6c, 0x7e, 0x8a, 0x93, 0xee, 0x60, - 0x10, 0x30, 0x1b, 0xf5, 0x59, 0x2a, 0x14, 0x4f, 0xd8, 0x7f, 0xe7, 0xb0, 0xe6, 0x3d, 0xfe, 0x72, - 0xe0, 0xc8, 0x52, 0x21, 0x15, 0x37, 0x18, 0x59, 0xd4, 0x7c, 0x5c, 0x8d, 0x55, 0x0b, 0x9b, 0xfb, - 0x3a, 0x75, 0x0f, 0xf6, 0x06, 0x29, 0xb6, 0xc2, 0x7f, 0x8d, 0x95, 0xce, 0x68, 0x77, 0x73, 0xae, - 0xde, 0x81, 0xfa, 0xce, 0x09, 0x72, 0xb1, 0x6c, 0xce, 0xe4, 0x94, 0x9e, 0x85, 0xf8, 0xdc, 0xba, - 0xc4, 0x5f, 0x77, 0xe9, 0x9e, 0x03, 0x99, 0x34, 0x8d, 0xcc, 0xdc, 0x9f, 0x56, 0x98, 0xed, 0x28, - 0xed, 0x06, 0x56, 0x80, 0xea, 0x52, 0x3a, 0x95, 0xc4, 0x64, 0x8f, 0x0c, 0xd9, 0x57, 0xbd, 0xc2, - 0xa9, 0x8d, 0xa0, 0x3a, 0xe2, 0x6c, 0x5a, 0x2a, 0x7b, 0xda, 0xf6, 0x81, 0x1a, 0x03, 0x17, 0x6b, - 0x0c, 0x0c, 0xda, 0xbd, 0x8e, 0x23, 0x06 - -}; - -// Escrow Service Key F98EB04C6AA62F4022709406305387C61415DDD770A24039C1415F24BF918803 -static const uint8_t kEscrowLeafCert[] = { - 0x30, 0x82, 0x04, 0x07, 0x30, 0x82, 0x02, 0xef, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x00, - 0x9b, 0x6e, 0xef, 0x8d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x0b, 0x05, 0x00, 0x30, 0x79, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x03, - 0x31, 0x30, 0x30, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, - 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1f, 0x30, - 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x45, 0x73, 0x63, 0x72, 0x6f, 0x77, 0x20, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, - 0x17, 0x0d, 0x31, 0x33, 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x38, 0x5a, 0x17, - 0x0d, 0x31, 0x35, 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x38, 0x5a, 0x30, 0x81, - 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x43, 0x41, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, - 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x03, 0x45, 0x54, 0x53, 0x31, 0x5c, - 0x30, 0x5a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x53, 0x45, 0x73, 0x63, 0x72, 0x6f, 0x77, 0x20, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x39, 0x42, 0x36, 0x45, - 0x45, 0x46, 0x38, 0x44, 0x37, 0x42, 0x33, 0x43, 0x34, 0x39, 0x31, 0x32, 0x46, 0x35, 0x35, 0x35, - 0x32, 0x32, 0x32, 0x32, 0x42, 0x42, 0x34, 0x31, 0x44, 0x38, 0x34, 0x43, 0x43, 0x31, 0x39, 0x43, - 0x33, 0x35, 0x37, 0x37, 0x32, 0x35, 0x41, 0x36, 0x43, 0x35, 0x46, 0x34, 0x45, 0x35, 0x43, 0x43, - 0x36, 0x30, 0x37, 0x41, 0x32, 0x44, 0x37, 0x32, 0x31, 0x35, 0x41, 0x43, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc5, 0xc7, 0x51, - 0xf1, 0x3f, 0x9a, 0x5d, 0xd7, 0xc1, 0x03, 0x42, 0x30, 0x84, 0xdb, 0xbc, 0x6c, 0x00, 0x6c, 0xcc, - 0x57, 0x97, 0xaf, 0xfe, 0x9e, 0xa0, 0x06, 0x9f, 0xe8, 0xa9, 0x59, 0xe1, 0xf8, 0xed, 0x23, 0x05, - 0x57, 0xe3, 0xd8, 0xdf, 0xf8, 0x31, 0x80, 0x8b, 0x31, 0x08, 0x2a, 0xc3, 0x7b, 0x16, 0xba, 0x27, - 0x84, 0x4e, 0xbb, 0x55, 0x5b, 0xd2, 0xda, 0x2d, 0xea, 0xda, 0x5c, 0xf0, 0x21, 0x58, 0x63, 0x74, - 0xa9, 0x90, 0x99, 0xbe, 0x87, 0x19, 0x7d, 0x87, 0xfc, 0xcb, 0xb6, 0xc9, 0x39, 0x51, 0x6a, 0xa7, - 0x81, 0x05, 0x50, 0x2d, 0xa2, 0x10, 0x6d, 0x58, 0xa5, 0x62, 0x29, 0x53, 0xce, 0xa6, 0x53, 0xad, - 0x3f, 0x50, 0xda, 0x1a, 0x1e, 0x2c, 0xe3, 0xae, 0x24, 0x88, 0xa5, 0x4c, 0xa3, 0x3a, 0xe1, 0xc6, - 0xa9, 0xcf, 0xb5, 0x53, 0x30, 0xbf, 0x7b, 0xea, 0x77, 0x21, 0x24, 0xfd, 0x91, 0x4c, 0x6f, 0x60, - 0x9f, 0x78, 0xf9, 0xed, 0x84, 0xe5, 0xee, 0xab, 0x07, 0xc5, 0x34, 0xa9, 0xe2, 0x0a, 0xf5, 0xf5, - 0xfa, 0x66, 0x75, 0xc8, 0x3e, 0x9c, 0xdd, 0xea, 0x60, 0xf0, 0x83, 0x03, 0x19, 0x08, 0xa4, 0x85, - 0xb0, 0xf3, 0xb1, 0xf1, 0x7a, 0x3d, 0xb4, 0xc8, 0xdd, 0x25, 0x5a, 0x1b, 0xf5, 0xa0, 0x78, 0xf9, - 0xbb, 0x08, 0x27, 0x6f, 0xa9, 0xf9, 0x17, 0xe8, 0xcb, 0x01, 0xa3, 0x5a, 0xd0, 0x67, 0xfb, 0xb7, - 0xef, 0xb7, 0x5c, 0x20, 0x94, 0x17, 0x5d, 0x46, 0xbd, 0xd2, 0xfe, 0xb6, 0x68, 0x88, 0x9f, 0xa6, - 0x0b, 0x97, 0x0f, 0x2e, 0x10, 0x23, 0x52, 0x9e, 0x69, 0x8b, 0xf4, 0x80, 0x83, 0x0e, 0x5b, 0x04, - 0xfc, 0x4e, 0xa1, 0x32, 0x44, 0x8a, 0x63, 0x3e, 0x3b, 0x0b, 0x70, 0x15, 0xd4, 0x17, 0xc1, 0xbe, - 0xbb, 0x01, 0x37, 0xe8, 0xfb, 0x58, 0x8b, 0x3d, 0xec, 0xc4, 0x47, 0x82, 0xe5, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x73, 0x30, 0x71, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, - 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, - 0x03, 0x02, 0x05, 0x20, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, - 0x34, 0x54, 0x7b, 0x16, 0x2a, 0x38, 0x22, 0xd5, 0x79, 0x7b, 0xbf, 0x5c, 0x62, 0x16, 0x59, 0xc5, - 0x53, 0x9f, 0xac, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, - 0xfd, 0x78, 0x96, 0x53, 0x80, 0xd6, 0xf6, 0xdc, 0xa6, 0xc3, 0x59, 0x06, 0x38, 0xed, 0x79, 0x3e, - 0x8f, 0x50, 0x1b, 0x50, 0x30, 0x11, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, - 0x17, 0x01, 0x04, 0x03, 0x02, 0x01, 0x0a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x41, 0x68, 0xd9, 0xd5, - 0xb5, 0xbe, 0x2d, 0xa1, 0xe7, 0x52, 0x28, 0x2c, 0x4f, 0xe7, 0x43, 0x39, 0x4d, 0x1f, 0xeb, 0x09, - 0xd9, 0xc7, 0xca, 0x6f, 0x63, 0x60, 0x7f, 0x7c, 0xb5, 0x7c, 0x5e, 0x4b, 0xab, 0xd5, 0x8b, 0x34, - 0x5b, 0x50, 0xda, 0x3e, 0x37, 0xa8, 0x26, 0xf5, 0xdb, 0x76, 0xc4, 0x4a, 0x48, 0x09, 0xcf, 0x04, - 0x0a, 0x17, 0x6c, 0x8d, 0x3c, 0x6e, 0x1e, 0x41, 0xfc, 0xef, 0x45, 0xbd, 0x72, 0x59, 0x5e, 0x10, - 0x61, 0x4e, 0xad, 0x0e, 0xe4, 0x76, 0x3c, 0xf7, 0x87, 0xef, 0x54, 0xdd, 0x61, 0xe9, 0x91, 0x0f, - 0x7e, 0x52, 0xd6, 0x9e, 0x02, 0xd7, 0xb6, 0xcc, 0xa4, 0x9e, 0x7d, 0xba, 0x5f, 0xb4, 0x40, 0xc9, - 0xe6, 0x95, 0x61, 0xae, 0xb9, 0x89, 0xba, 0x25, 0x1b, 0xb6, 0xde, 0x08, 0x7f, 0x88, 0xef, 0x7c, - 0x59, 0x4d, 0x73, 0xc7, 0xf5, 0x07, 0x94, 0x13, 0x7b, 0xfc, 0x9f, 0x75, 0x0d, 0x1a, 0x69, 0xf0, - 0x51, 0x36, 0x1e, 0x46, 0x76, 0xc8, 0x27, 0x4e, 0x65, 0x58, 0x66, 0x41, 0x5e, 0x9d, 0xfe, 0xf1, - 0x10, 0xd5, 0x3c, 0x5b, 0xea, 0xcd, 0x96, 0x37, 0x4d, 0x76, 0x88, 0x60, 0xfb, 0x3f, 0xb2, 0x7a, - 0x00, 0xb4, 0xe0, 0xb6, 0xb9, 0x76, 0x6e, 0x02, 0xb6, 0xf7, 0x8d, 0x8b, 0x3a, 0x5c, 0xde, 0x4e, - 0xb9, 0xa4, 0x05, 0xc6, 0x14, 0xa6, 0x3f, 0x6c, 0xbd, 0xfd, 0xee, 0x0b, 0xf5, 0x5c, 0x27, 0x56, - 0xc5, 0x48, 0x55, 0x78, 0x72, 0xdc, 0xca, 0x95, 0xb7, 0x02, 0xb2, 0xdc, 0x4e, 0xbd, 0xe2, 0x78, - 0x87, 0xcc, 0xb5, 0xb0, 0x7c, 0x22, 0x52, 0xc1, 0xb0, 0x5a, 0x09, 0x9d, 0xb6, 0xbe, 0xe7, 0x4b, - 0xa2, 0x0e, 0x20, 0x43, 0x28, 0x77, 0x88, 0x1f, 0xd6, 0xa4, 0xb9, 0x56, 0xd0, 0xd0, 0xa6, 0x0f, - 0xa3, 0xef, 0x2e, 0xb7, 0x1d, 0x40, 0x61, 0xf8, 0xb9, 0x17, 0x4c, -}; - -static const uint8_t kPCSEscrowLeafCert[] = { - 0x30,0x82,0x04,0x0E,0x30,0x82,0x02,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x5B, - 0x57,0x9E,0xA2,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, - 0x05,0x00,0x30,0x7D,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31, - 0x30,0x30,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, - 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, - 0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41, - 0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, - 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x23,0x30,0x21, - 0x06,0x03,0x55,0x04,0x03,0x13,0x1A,0x45,0x66,0x66,0x61,0x63,0x65,0x61,0x62,0x6C, - 0x65,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, - 0x41,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x37,0x32,0x39,0x30,0x30,0x31,0x31,0x34, - 0x33,0x5A,0x17,0x0D,0x31,0x36,0x30,0x37,0x32,0x39,0x30,0x30,0x31,0x31,0x34,0x33, - 0x5A,0x30,0x81,0x9F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, - 0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x43,0x41,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x0B,0x13,0x03,0x45,0x54, - 0x53,0x31,0x60,0x30,0x5E,0x06,0x03,0x55,0x04,0x03,0x13,0x57,0x45,0x66,0x66,0x61, - 0x63,0x65,0x61,0x62,0x6C,0x65,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x20,0x4B, - 0x65,0x79,0x20,0x35,0x42,0x35,0x37,0x39,0x45,0x41,0x32,0x36,0x34,0x41,0x39,0x36, - 0x36,0x39,0x37,0x42,0x41,0x38,0x31,0x33,0x34,0x35,0x34,0x44,0x32,0x45,0x38,0x43, - 0x46,0x37,0x44,0x42,0x31,0x34,0x30,0x33,0x37,0x43,0x30,0x43,0x45,0x44,0x32,0x34, - 0x33,0x43,0x42,0x37,0x46,0x45,0x33,0x31,0x33,0x38,0x33,0x42,0x34,0x35,0x38,0x34, - 0x33,0x30,0x42,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, - 0x82,0x01,0x01,0x00,0xAD,0xAD,0x92,0x86,0x08,0xFF,0x27,0xF1,0xCC,0xB6,0x57,0x41, - 0xC9,0x1F,0x05,0xC2,0xC7,0xC5,0xFB,0x8C,0xE3,0xEE,0xBC,0xE0,0x07,0xA4,0x58,0xE0, - 0x9E,0x81,0x19,0xF9,0x81,0xDF,0xD6,0x1B,0x65,0x23,0x0E,0xAC,0x2A,0xB6,0x3F,0x32, - 0x66,0xBF,0x9E,0xF4,0x0D,0xEA,0xE8,0xE9,0x5E,0xCF,0xB6,0x84,0x61,0x03,0x26,0x92, - 0xC5,0xAC,0xB2,0x54,0xE0,0x5B,0x22,0x88,0xFB,0x9B,0x6F,0xEF,0xFE,0xC1,0x40,0x27, - 0xF3,0x35,0xF2,0xC4,0x4C,0xB1,0xB4,0x57,0x2D,0xE7,0xF0,0x26,0xC0,0xE8,0x5F,0x02, - 0x13,0x33,0x53,0x5F,0xC8,0x5B,0x6B,0x14,0x5B,0x37,0x2F,0x24,0xD6,0x39,0x0C,0x7C, - 0x0D,0x8E,0x4A,0x73,0x33,0xAF,0xA1,0x78,0x6F,0xE0,0xD8,0x42,0x40,0x33,0x58,0x12, - 0x76,0xFF,0xF2,0x1E,0xAE,0x0B,0x80,0x3F,0x63,0x52,0xED,0xCA,0x33,0x3A,0x8B,0x19, - 0x37,0xFF,0xAC,0xFF,0x4D,0xBF,0xD1,0x9D,0x55,0xD1,0x2A,0x17,0x28,0x0E,0x6B,0xC8, - 0x12,0xBF,0x79,0x22,0x6B,0x8F,0x3C,0x3B,0x5C,0xC7,0x66,0xA8,0x9C,0x65,0x68,0xB4, - 0x4B,0x37,0xCE,0xC9,0x2A,0x7E,0x36,0x6A,0x7A,0x76,0x5D,0x47,0x26,0xDE,0x70,0xC8, - 0xE5,0x6B,0xA1,0xC5,0xC8,0xBC,0xCF,0xD2,0x78,0xAF,0xDE,0x9A,0xF4,0x49,0xC7,0xFC, - 0x78,0xF2,0x37,0xC1,0xD1,0x40,0xFA,0x30,0x4C,0x96,0xC2,0x16,0xEC,0xEB,0xE0,0x33, - 0x94,0xE1,0x83,0xE8,0xF9,0xD6,0x58,0xEE,0xEE,0x7D,0x49,0x38,0xC7,0xD6,0x15,0xE6, - 0x00,0x7F,0x40,0x37,0x03,0x3F,0xF3,0x5F,0x38,0x63,0x93,0x87,0xF1,0xE2,0xB7,0x8C, - 0xFF,0x21,0x68,0x7B,0x02,0x03,0x01,0x00,0x01,0xA3,0x73,0x30,0x71,0x30,0x0C,0x06, - 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55, - 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0x20,0x30,0x1D,0x06,0x03,0x55, - 0x1D,0x0E,0x04,0x16,0x04,0x14,0x3F,0x94,0xA6,0xB9,0xB6,0xAE,0x43,0xDA,0x66,0xF3, - 0xD3,0x38,0xF0,0xD0,0x96,0x59,0x79,0x1B,0x0A,0xC1,0x30,0x1F,0x06,0x03,0x55,0x1D, - 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x64,0x0B,0xE4,0x72,0x73,0x5C,0x54,0xB2,0x58, - 0x59,0xAE,0x42,0xDF,0x2B,0xB7,0xBA,0xB9,0xEB,0x86,0xAE,0x30,0x11,0x06,0x0A,0x2A, - 0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x17,0x01,0x04,0x03,0x02,0x01,0x0A,0x30,0x0D, - 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01, - 0x01,0x00,0x83,0x4B,0x3D,0x4E,0xE0,0x17,0xB5,0x95,0xAE,0x90,0xA4,0xE0,0x41,0x01, - 0x5B,0x1A,0x1D,0x69,0x83,0xA9,0xA0,0xD8,0x58,0xCD,0x57,0xB8,0x8B,0x1D,0x00,0xD2, - 0xB4,0x27,0x65,0x34,0x83,0xAD,0x5B,0xCF,0xA8,0x2F,0xFC,0x6C,0x08,0x1B,0x2B,0x12, - 0x93,0xE5,0x68,0xE3,0x85,0xFA,0x87,0x28,0x31,0x7E,0x18,0xA9,0xB9,0xEF,0xF4,0xE3, - 0x1C,0x24,0x83,0xE6,0x01,0xDA,0x56,0x49,0x52,0xA1,0xBC,0x56,0xE4,0xFC,0xA6,0xAF, - 0xC7,0x8D,0xD8,0x41,0xD3,0xA8,0x10,0x99,0x0F,0xEE,0x93,0xF1,0x58,0x4C,0x43,0x8B, - 0x31,0xF8,0xA8,0x04,0xFD,0x88,0x7E,0x0C,0x0C,0xA6,0xB9,0x3C,0xEC,0x9B,0xCD,0x99, - 0xF5,0x38,0x35,0x76,0x63,0xBC,0x23,0x9A,0x8F,0xA3,0x0B,0xE2,0x8E,0x55,0xEF,0x71, - 0xD8,0x87,0xA8,0x62,0x2B,0x35,0x32,0x24,0x6C,0xEE,0x95,0x5C,0x74,0xB2,0x1B,0x8F, - 0xEF,0x4C,0x45,0x03,0x0B,0x35,0x97,0x7D,0x43,0x7F,0x1D,0x3E,0xB9,0xE9,0x9D,0xF1, - 0x96,0x3B,0x91,0xA6,0xDF,0x52,0x00,0xB3,0xC5,0xDC,0xD3,0x29,0xAC,0x17,0xE1,0x73, - 0xA9,0x15,0x14,0xBD,0x1E,0x4F,0x9F,0x09,0xF8,0x84,0xF8,0xB6,0x9C,0xFD,0xCD,0x09, - 0x6D,0xDD,0x39,0xC7,0x15,0x58,0x86,0xE8,0x6B,0x47,0x4F,0x5D,0x84,0x29,0x56,0x81, - 0xF1,0x7C,0x09,0xA5,0x50,0x5C,0x4B,0xD9,0xFF,0xDF,0xA5,0xA9,0x6E,0xFF,0x14,0x9F, - 0xE4,0x4C,0xE7,0xAA,0x83,0xEA,0x30,0xB4,0x0D,0x8D,0xF7,0x36,0x4B,0x8D,0x38,0xDC, - 0xF5,0xA9,0xCF,0x3F,0x85,0x6A,0xC3,0x7A,0x53,0x86,0x18,0x5D,0x4B,0x93,0x1A,0x0E, - 0x50,0x5D, -}; - - -#if 0 -static inline void test_mobile(void) -{ - SecCertificateRef aCert = NULL; - SecCertificateRef intermediateCert = NULL; - SecCertificateRef rootCert = NULL; - SecTrustResultType trustResult = kSecTrustResultUnspecified; - SecPolicyRef policy = NULL; - CFArrayRef certs = NULL; - SecTrustRef trust = NULL; - - isnt(aCert = SecCertificateCreateWithBytes(NULL, kDemoContentSigningCert, sizeof(kDemoContentSigningCert)), - NULL, "create aCert from kDemoContentSigningCert"); - - isnt(intermediateCert = SecCertificateCreateWithBytes(NULL, kMobileIntermediate, sizeof(kMobileIntermediate)), - NULL, "create intermediate from kMobileIntermediate"); - - SecCertificateRef refs[] = {aCert, intermediateCert}; - certs = CFArrayCreate(NULL, (const void **)refs, 2, NULL); - - isnt(policy = SecPolicyCreateMobileStoreSigner(), - NULL, "create mobile policy"); - - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "create trust for mobile store test cert"); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate mobile store trust"); - - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultRecoverableTrustFailure"); - - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(aCert); - - isnt(aCert = SecCertificateCreateWithBytes(NULL, kTestDemoContentSigningCert, sizeof(kTestDemoContentSigningCert)), - NULL, "create aCert from kDemoContentSigningCert"); - - isnt(policy = SecPolicyCreateTestMobileStoreSigner(), - NULL, "create Test mobile policy"); - - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "create trust for mobile store test cert"); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate test mobile store trust"); - - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultRecoverableTrustFailure"); - - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(aCert); - CFReleaseSafe(certs); - CFReleaseSafe(intermediateCert); - CFReleaseSafe(rootCert); - -} -#endif // 0 - -static void test_escrow_with_anchor_roots(CFArrayRef anchors) -{ - SecCertificateRef escrowLeafCert = NULL; - SecTrustResultType trustResult = kSecTrustResultUnspecified; - SecPolicyRef policy = NULL; - CFArrayRef certs = NULL; - SecTrustRef trust = NULL; - - isnt(escrowLeafCert = SecCertificateCreateWithBytes(NULL, kEscrowLeafCert, sizeof(kEscrowLeafCert)), - NULL, "could not create aCert from kEscrowLeafCert"); - - certs = CFArrayCreate(NULL, (const void **)&escrowLeafCert, 1, NULL); - - isnt(policy = SecPolicyCreateWithProperties(kSecPolicyAppleEscrowService, NULL), - NULL, "could not create Escrow policy for GM Escrow Leaf cert"); - - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "could not create trust for escrow service test GM Escrow Leaf cert"); - - SecTrustSetAnchorCertificates(trust, anchors); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate escrow service trust for GM Escrow Leaf cert"); - - is_status(trustResult, kSecTrustResultUnspecified, - "trust is not kSecTrustResultUnspecified for GM Escrow Leaf cert"); - - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(certs); - CFReleaseSafe(escrowLeafCert); - -} - -static void test_pcs_escrow_with_anchor_roots(CFArrayRef anchors) -{ - SecCertificateRef leafCert = NULL; - SecTrustResultType trustResult = kSecTrustResultUnspecified; - SecPolicyRef policy = NULL; - CFArrayRef certs = NULL; - CFDateRef date = NULL; - SecTrustRef trust = NULL; - OSStatus status; - - isnt(leafCert = SecCertificateCreateWithBytes(NULL, kPCSEscrowLeafCert, sizeof(kPCSEscrowLeafCert)), - NULL, "could not create leafCert from kPCSEscrowLeafCert"); - - certs = CFArrayCreate(NULL, (const void **)&leafCert, 1, NULL); - - isnt(policy = SecPolicyCreateWithProperties(kSecPolicyApplePCSEscrowService, NULL), - NULL, "could not create PCS Escrow policy for GM PCS Escrow Leaf cert"); - - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "could not create trust for PCS escrow service test GM PCS Escrow Leaf cert"); - - /* Set explicit verify date: Mar 18 2016. */ - isnt(date = CFDateCreate(NULL, 480000000.0), NULL, "create verify date"); - status = (date) ? SecTrustSetVerifyDate(trust, date) : errSecParam; - ok_status(status, "set date"); - - SecTrustSetAnchorCertificates(trust, anchors); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate PCS escrow service trust for GM PCS Escrow Leaf cert"); - - is_status(trustResult, kSecTrustResultUnspecified, - "trust is not kSecTrustResultUnspecified for GM PCS Escrow Leaf cert"); - - CFReleaseSafe(date); - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(certs); - CFReleaseSafe(leafCert); - -} -static inline void test_escrow() -{ - CFArrayRef anchors = NULL; - isnt(anchors = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot), NULL, "unable to get production anchors"); - test_escrow_with_anchor_roots(anchors); - CFReleaseSafe(anchors); -} - -static inline void test_pcs_escrow() -{ - CFArrayRef anchors = NULL; - isnt(anchors = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot), NULL, "unable to get production PCS roots"); - test_pcs_escrow_with_anchor_roots(anchors); - CFReleaseSafe(anchors); -} - -static inline void test_escrow_roots() -{ - CFArrayRef baselineRoots = NULL; - isnt(baselineRoots = SecCertificateCopyEscrowRoots(kSecCertificateBaselineEscrowRoot), NULL, "unable to get baseline roots"); - ok(baselineRoots && CFArrayGetCount(baselineRoots) > 0, "baseline roots array empty"); - CFReleaseSafe(baselineRoots); - - CFArrayRef productionRoots = NULL; - isnt(productionRoots = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot), NULL, "unable to get production roots"); - ok(productionRoots && CFArrayGetCount(productionRoots) > 0, "production roots array empty"); - CFReleaseSafe(productionRoots); - - CFArrayRef baselinePCSRoots = NULL; - isnt(baselinePCSRoots = SecCertificateCopyEscrowRoots(kSecCertificateBaselinePCSEscrowRoot), NULL, "unable to get baseline PCS roots"); - ok(baselinePCSRoots && CFArrayGetCount(baselinePCSRoots) > 0, "baseline PCS roots array empty"); - CFReleaseSafe(baselinePCSRoots); - - CFArrayRef productionPCSRoots = NULL; - isnt(productionPCSRoots = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot), NULL, "unable to get production PCS roots"); - ok(productionPCSRoots && CFArrayGetCount(productionPCSRoots) > 0, "production PCS roots array empty"); - CFReleaseSafe(productionPCSRoots); -} - -static void tests(void) -{ - test_escrow(); - test_pcs_escrow(); - test_escrow_roots(); -} - -//#endif /* defined(NO_SERVER) && NO_SERVER == 1 */ - -int si_71_mobile_store_policy(int argc, char *const *argv) -{ -//#if defined(NO_SERVER) && NO_SERVER == 1 - - plan_tests(22); - - tests(); - -//#endif - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c b/OSX/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c deleted file mode 100644 index 006dc95c..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c +++ /dev/null @@ -1,1007 +0,0 @@ -/* - * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -static const UInt8 kSignedPList[] = { - 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, - 0x80, 0x02, 0x01, 0x01, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x36, 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, - 0xd1, 0x01, 0x02, 0x53, 0x66, 0x6f, 0x6f, 0x53, 0x62, 0x61, 0x72, 0x08, 0x0b, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x80, 0x30, 0x82, 0x07, 0xab, 0x30, 0x82, 0x05, 0x93, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x08, 0x04, 0x2e, 0x97, 0xbb, 0x62, 0x84, 0xd9, 0x1c, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, - 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, - 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, - 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, - 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, - 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x35, 0x30, 0x30, 0x30, - 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x36, 0x32, 0x31, 0x30, 0x30, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x30, 0x59, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x4f, 0x53, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, - 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, - 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xad, - 0xef, 0x52, 0xc8, 0xda, 0x8e, 0x3c, 0xcc, 0x06, 0xcf, 0xfc, 0xed, 0xdb, 0x92, 0xb3, 0xa8, 0xe0, - 0x3b, 0x14, 0x40, 0x34, 0xad, 0x91, 0xf3, 0xbe, 0x1a, 0x00, 0xbb, 0x06, 0xa2, 0xd7, 0x24, 0x6f, - 0xd5, 0xd3, 0xdf, 0xd9, 0xff, 0x0b, 0x4d, 0x6d, 0xc5, 0xdd, 0x7a, 0x37, 0xfa, 0x08, 0x49, 0x0e, - 0x36, 0x5e, 0xab, 0x83, 0x8d, 0xeb, 0x83, 0x00, 0xf9, 0xaa, 0xe4, 0x88, 0x09, 0x87, 0x05, 0x6b, - 0x01, 0x6e, 0x49, 0x54, 0xa1, 0x3b, 0x5c, 0xfc, 0x2b, 0x0f, 0x1f, 0xa9, 0x7c, 0xc1, 0xc5, 0xe1, - 0x32, 0xd7, 0x86, 0x49, 0x80, 0x0f, 0xf8, 0xe3, 0x3b, 0xa3, 0x12, 0x06, 0x5d, 0xf4, 0x43, 0xc0, - 0xb2, 0xc7, 0xcf, 0xb4, 0x14, 0x2c, 0x50, 0x70, 0x57, 0xb9, 0xb2, 0xe7, 0x72, 0x9a, 0x9f, 0x45, - 0x0b, 0x0d, 0xe5, 0xab, 0x3e, 0x23, 0x91, 0xe0, 0x88, 0x84, 0x3a, 0xec, 0xaa, 0x80, 0xab, 0x37, - 0xa3, 0x0c, 0x63, 0x99, 0x1c, 0xde, 0x1b, 0x29, 0x95, 0x4b, 0xff, 0xcd, 0x92, 0x10, 0xa3, 0x50, - 0x93, 0x89, 0x4f, 0xdc, 0x30, 0x0d, 0x29, 0x2a, 0x80, 0x04, 0x32, 0xb3, 0xb9, 0xa7, 0x79, 0x5f, - 0x18, 0xce, 0xc1, 0x90, 0xe6, 0xd6, 0x0c, 0xeb, 0x91, 0x27, 0x6f, 0x17, 0xd2, 0x93, 0xda, 0xa1, - 0xa8, 0x3f, 0x20, 0xe9, 0xeb, 0x54, 0x37, 0xd7, 0x54, 0xfd, 0x44, 0xa2, 0x8d, 0xa4, 0x30, 0x6e, - 0xbf, 0xd0, 0xbd, 0xc4, 0x7d, 0x93, 0xeb, 0xf6, 0xfa, 0x1e, 0xc1, 0xd5, 0xee, 0xfe, 0xb7, 0x56, - 0x51, 0xb3, 0x0b, 0x3f, 0xf4, 0xb1, 0x77, 0x75, 0xaf, 0x10, 0x14, 0x98, 0x74, 0x41, 0x40, 0xdb, - 0xe4, 0x6b, 0x3f, 0x49, 0xce, 0xb8, 0x80, 0x20, 0x72, 0x92, 0xcb, 0x63, 0x63, 0x44, 0x4e, 0xe8, - 0xe4, 0xde, 0xe9, 0xc3, 0x0a, 0x75, 0xd8, 0xbf, 0xc5, 0x8e, 0xcb, 0xcf, 0xec, 0x65, 0x49, 0x56, - 0xa1, 0x9f, 0xb6, 0x39, 0x53, 0x69, 0xb4, 0x04, 0xe8, 0xd0, 0x28, 0xc6, 0x69, 0xde, 0xdb, 0x30, - 0xa7, 0xb0, 0xbf, 0x6f, 0xfe, 0x7b, 0x45, 0x87, 0x07, 0xf0, 0x85, 0x34, 0x71, 0xca, 0xe5, 0x07, - 0x61, 0xce, 0x53, 0xf3, 0xd6, 0x69, 0x70, 0x5a, 0x4b, 0x7e, 0xda, 0x9b, 0x77, 0x17, 0x65, 0x6c, - 0x4d, 0xd5, 0x59, 0x00, 0x6f, 0x47, 0x65, 0x30, 0x98, 0xd9, 0x7b, 0xa7, 0x51, 0x8b, 0x47, 0x7d, - 0x8f, 0x5a, 0x91, 0x72, 0xe4, 0x86, 0x4f, 0xb0, 0xb4, 0x12, 0x42, 0x55, 0x95, 0x59, 0xa3, 0xc6, - 0xdf, 0xba, 0x20, 0x0e, 0x5d, 0x0f, 0x6a, 0x6a, 0xc2, 0x08, 0x93, 0x9f, 0x0e, 0x8b, 0x61, 0x20, - 0x9e, 0x2b, 0x64, 0x26, 0x15, 0x52, 0x9b, 0xef, 0x34, 0x7c, 0x12, 0xa4, 0xe4, 0xf7, 0xfc, 0x9a, - 0xa6, 0xe6, 0xe9, 0x6f, 0xfc, 0xbb, 0x16, 0xc4, 0x0f, 0x0b, 0xac, 0x84, 0x9d, 0xc8, 0xe9, 0x98, - 0xe1, 0xf4, 0x35, 0xfb, 0x97, 0x63, 0x14, 0x6c, 0x15, 0x51, 0x51, 0x5b, 0xc8, 0x64, 0x25, 0x46, - 0x44, 0x6d, 0xbd, 0x17, 0xdd, 0x17, 0x4d, 0x34, 0x77, 0xa8, 0x6d, 0x4b, 0x97, 0x4b, 0x77, 0xf5, - 0x77, 0x07, 0x1b, 0x93, 0x18, 0xf3, 0x44, 0x4e, 0x79, 0xe2, 0xfc, 0x96, 0x76, 0x5e, 0x69, 0x85, - 0xf6, 0xb6, 0x97, 0xbb, 0xb0, 0x41, 0x1f, 0x03, 0x8b, 0xcb, 0xc0, 0xa9, 0x10, 0x67, 0x8f, 0x6f, - 0x67, 0xab, 0xb0, 0xbd, 0x1f, 0xc7, 0x11, 0xfd, 0xb8, 0x29, 0x47, 0x41, 0xd4, 0x34, 0x0f, 0x5b, - 0x9d, 0x64, 0xfb, 0x8f, 0x5f, 0x37, 0xd1, 0x9a, 0x4a, 0x2d, 0x62, 0xd1, 0x74, 0x2e, 0x6b, 0x7f, - 0xdf, 0xb3, 0xea, 0x5f, 0xfa, 0x63, 0xd4, 0x4f, 0xb3, 0x89, 0x76, 0x67, 0x36, 0x71, 0xcd, 0xaf, - 0xd7, 0x9c, 0x95, 0xa8, 0xce, 0xee, 0x29, 0x25, 0xb1, 0x2a, 0xac, 0x99, 0x10, 0x9b, 0x03, 0x02, - 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x49, 0x30, 0x82, 0x02, 0x45, 0x30, 0x1d, 0x06, 0x03, - 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xcd, 0xbf, 0x6f, 0x14, 0xff, 0x8b, 0xb7, 0xf7, 0x29, - 0xcd, 0xa4, 0x8c, 0xc1, 0xb1, 0x30, 0x92, 0x37, 0x8b, 0xd4, 0xef, 0x30, 0x0c, 0x06, 0x03, 0x55, - 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35, 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, - 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xe3, 0x06, 0x03, - 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0xd3, 0x30, 0x82, - 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, - 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, - 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, - 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, - 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, - 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, - 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, - 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, - 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, - 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, - 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, - 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, - 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, - 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, - 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, - 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, - 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, - 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, - 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, - 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, - 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, - 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, - 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, - 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, - 0x0d, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, - 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, - 0x03, 0x82, 0x02, 0x01, 0x00, 0xc3, 0xd1, 0x52, 0x94, 0x51, 0xa7, 0x6d, 0xe9, 0xf8, 0x1a, 0xba, - 0x15, 0x2c, 0x38, 0x6b, 0xd6, 0xba, 0xcf, 0x12, 0x20, 0x1d, 0x46, 0xef, 0x99, 0x48, 0x95, 0x9d, - 0x1e, 0x49, 0x1b, 0xe7, 0x95, 0xde, 0x73, 0x28, 0xc1, 0x90, 0xfe, 0xeb, 0x39, 0xe1, 0xa8, 0xa8, - 0x5c, 0x4e, 0x71, 0x03, 0x1b, 0x22, 0x37, 0x07, 0xed, 0x24, 0xa4, 0xee, 0x5d, 0x0a, 0xf8, 0x04, - 0xf8, 0xba, 0x34, 0x50, 0xc0, 0x49, 0xd7, 0xa4, 0x4f, 0xdd, 0x06, 0x81, 0x33, 0x3a, 0x69, 0x4e, - 0x43, 0x85, 0x15, 0xde, 0x05, 0x37, 0xf5, 0xb3, 0xd5, 0x68, 0x4c, 0x30, 0x6a, 0x52, 0x35, 0x6a, - 0xb0, 0x2b, 0x8e, 0xe1, 0xde, 0xa6, 0xd2, 0xfc, 0xe2, 0x9f, 0xdc, 0x95, 0x65, 0x13, 0x45, 0x91, - 0xc1, 0x7b, 0xff, 0x90, 0x6a, 0x4c, 0xd3, 0x20, 0x5c, 0x1b, 0x99, 0xea, 0x82, 0xec, 0xfd, 0x0b, - 0x89, 0x25, 0x6c, 0x31, 0x3d, 0xa8, 0x52, 0xba, 0x8e, 0xdf, 0x20, 0xcb, 0x5f, 0x00, 0xf8, 0x6b, - 0xf2, 0x63, 0x5d, 0x2a, 0x55, 0xc6, 0xee, 0x34, 0xa4, 0x86, 0xab, 0x47, 0x89, 0xcd, 0xb6, 0xaa, - 0xe0, 0x5c, 0x9a, 0x57, 0x7d, 0x3e, 0xaa, 0x8b, 0x74, 0xfc, 0x94, 0xc7, 0x9d, 0x0e, 0xa2, 0x92, - 0xa9, 0xc5, 0xdd, 0x71, 0x53, 0x54, 0x38, 0xb0, 0x22, 0x88, 0xdc, 0x46, 0xcd, 0x45, 0xc7, 0x33, - 0xc7, 0x2f, 0xed, 0x5f, 0x4d, 0x05, 0x9d, 0xba, 0x2e, 0xf7, 0xa4, 0xb5, 0xfa, 0x79, 0x11, 0x41, - 0xd1, 0x1b, 0x50, 0xab, 0xef, 0xdf, 0xa8, 0x5c, 0x28, 0xc7, 0x8e, 0x86, 0xa2, 0x85, 0x8a, 0x90, - 0xf4, 0xda, 0x71, 0x1f, 0xff, 0x7f, 0x02, 0x4c, 0x24, 0x95, 0x0d, 0x31, 0xa3, 0x8b, 0x62, 0xae, - 0x45, 0xe2, 0x44, 0x6c, 0x01, 0x1d, 0xdc, 0x67, 0xbe, 0xfb, 0x16, 0x4f, 0x4c, 0xf0, 0x81, 0xa8, - 0xbd, 0xe1, 0x29, 0x6f, 0x1c, 0xff, 0xa4, 0x82, 0x96, 0xa3, 0x67, 0xad, 0xa6, 0x99, 0xd6, 0x29, - 0x02, 0x7f, 0xfc, 0xe3, 0x8d, 0xe3, 0x0d, 0x17, 0x91, 0x84, 0xcf, 0x4b, 0x05, 0xdd, 0x29, 0x96, - 0xb4, 0x58, 0x56, 0x9b, 0x65, 0x17, 0xdd, 0x16, 0x1f, 0xf8, 0x59, 0x8d, 0xfb, 0xa0, 0xb0, 0xc7, - 0x0b, 0x74, 0x64, 0xef, 0x8c, 0xcb, 0xba, 0x10, 0x48, 0x37, 0x28, 0xc9, 0x7f, 0x17, 0xac, 0x5f, - 0x04, 0xa0, 0x50, 0x6d, 0x18, 0x5f, 0x23, 0xe3, 0x9c, 0xb6, 0xe0, 0x6c, 0xc0, 0xe1, 0x5e, 0xba, - 0x8f, 0x70, 0xf1, 0xca, 0xc5, 0x97, 0x95, 0xf7, 0x4c, 0xdd, 0x6c, 0x8c, 0xbb, 0x4d, 0x68, 0x18, - 0x59, 0xb3, 0x1b, 0x6f, 0x81, 0xe7, 0xd8, 0x44, 0xdc, 0x6e, 0x84, 0xce, 0x5b, 0x0c, 0x66, 0xef, - 0xc4, 0x72, 0x00, 0xf2, 0x5a, 0xef, 0x82, 0x63, 0x18, 0xf7, 0xd3, 0xb8, 0x25, 0xc4, 0x91, 0x80, - 0x04, 0x54, 0x61, 0x5b, 0xf5, 0xe2, 0xda, 0xfb, 0x1d, 0xd4, 0x19, 0x99, 0x18, 0xbd, 0x9a, 0x1e, - 0x96, 0xe9, 0x1c, 0xd5, 0xd0, 0x06, 0xf5, 0x37, 0x91, 0x3b, 0x4d, 0xa5, 0x2a, 0xda, 0x3c, 0xcd, - 0xa6, 0xda, 0x53, 0xb8, 0x4a, 0x1e, 0xb9, 0x51, 0xed, 0xc3, 0x47, 0xc6, 0xfa, 0xdc, 0x2e, 0xb3, - 0xdd, 0x63, 0x65, 0xba, 0x17, 0xdb, 0x65, 0x8b, 0x63, 0x77, 0x31, 0x6d, 0xd9, 0xb7, 0x18, 0x33, - 0x91, 0xa1, 0x1f, 0xed, 0x0d, 0x49, 0x7f, 0x29, 0xd6, 0xd4, 0xf6, 0x12, 0x0f, 0xb2, 0x0c, 0xc9, - 0x0f, 0x61, 0xb1, 0x48, 0x58, 0x52, 0xac, 0x80, 0x92, 0xb4, 0x2d, 0x4c, 0xa8, 0x94, 0xf6, 0x99, - 0xc8, 0xb7, 0x1a, 0x7f, 0x3a, 0x52, 0x49, 0x9f, 0x44, 0xff, 0x0d, 0x38, 0x27, 0x3f, 0xad, 0xf6, - 0xa4, 0x8f, 0xd9, 0x4b, 0x30, 0x6f, 0xe0, 0xb8, 0x20, 0x94, 0x82, 0x4c, 0x96, 0xea, 0x27, 0x28, - 0x61, 0x1a, 0x41, 0x6d, 0xd4, 0x30, 0x82, 0x07, 0xca, 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, - 0x01, 0x02, 0x02, 0x08, 0x4e, 0xa1, 0x31, 0xe7, 0xca, 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, - 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, - 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, - 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, - 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, - 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, - 0x33, 0x39, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x36, 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, - 0x39, 0x5a, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, - 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, - 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, - 0x0c, 0x6f, 0x45, 0xb4, 0x04, 0x59, 0x24, 0xcb, 0x70, 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, - 0x87, 0x61, 0xb3, 0xd3, 0xfc, 0xbe, 0xb6, 0x05, 0x3c, 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, - 0x87, 0x07, 0xcf, 0x20, 0xbe, 0xaa, 0xeb, 0x24, 0xc5, 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, - 0xea, 0xb4, 0x5d, 0x3b, 0x29, 0x6c, 0xba, 0x4d, 0x15, 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, - 0x0d, 0x1d, 0xf7, 0x66, 0x77, 0xa2, 0x96, 0x56, 0xed, 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, - 0x32, 0x9c, 0xa9, 0xfd, 0xbf, 0xb8, 0x34, 0x6f, 0x57, 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, - 0xe9, 0x0f, 0x3c, 0xed, 0x4f, 0x31, 0x87, 0x05, 0xa4, 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, - 0xca, 0xd3, 0xf9, 0xd6, 0xaa, 0xaa, 0x88, 0x57, 0x66, 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, - 0x3d, 0x1d, 0xbc, 0x82, 0x6e, 0x81, 0xe9, 0x19, 0xf5, 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, - 0x88, 0xba, 0x51, 0xe7, 0x3a, 0xa0, 0x77, 0x2d, 0xe6, 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, - 0xf8, 0xa7, 0x79, 0x51, 0x2d, 0xe6, 0xc2, 0xee, 0xd2, 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, - 0x37, 0x12, 0xeb, 0x63, 0x99, 0x3d, 0xf3, 0x21, 0xbe, 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, - 0x0c, 0x4b, 0x43, 0x0c, 0x05, 0x6a, 0x6b, 0x8f, 0x05, 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, - 0xa7, 0x75, 0x63, 0x85, 0xe3, 0xa5, 0x5c, 0xc0, 0xd6, 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, - 0x6b, 0x4e, 0x99, 0x74, 0x7d, 0xd2, 0x69, 0x9f, 0xa8, 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, - 0x7e, 0x4a, 0x7a, 0x8a, 0xeb, 0x7c, 0xcd, 0x43, 0x9e, 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, - 0xe7, 0xfb, 0xa0, 0x43, 0xb3, 0xd7, 0x15, 0x28, 0x8a, 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, - 0x1b, 0x37, 0x33, 0x76, 0xc4, 0x58, 0xb9, 0x2d, 0x89, 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, - 0xa6, 0x07, 0x79, 0x11, 0x7d, 0x26, 0xd2, 0x85, 0x22, 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, - 0x18, 0xf3, 0xaa, 0x05, 0xce, 0x87, 0x99, 0xde, 0x76, 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, - 0x51, 0xa0, 0xc9, 0x70, 0xfc, 0xb9, 0x22, 0xfe, 0xd2, 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, - 0x53, 0xfd, 0xa1, 0xe6, 0xff, 0x8e, 0xd6, 0xde, 0x9e, 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, - 0xb2, 0x34, 0x8a, 0x1d, 0xf7, 0x9e, 0xa0, 0xbb, 0xf4, 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, - 0x92, 0x0d, 0xc9, 0x94, 0x7f, 0x24, 0xb9, 0x9f, 0xda, 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, - 0x3a, 0x70, 0x63, 0x3b, 0x22, 0x42, 0x14, 0xd0, 0xf9, 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, - 0x41, 0x20, 0x0d, 0x7e, 0x70, 0xd7, 0x88, 0x36, 0xa2, 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, - 0x9c, 0x5f, 0x4d, 0x3e, 0x4f, 0x83, 0x79, 0x06, 0x73, 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, - 0xce, 0x93, 0x5c, 0x68, 0xbf, 0x5a, 0xe6, 0x4c, 0x23, 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, - 0x1b, 0x64, 0x39, 0x64, 0xb7, 0xd2, 0x1d, 0xd0, 0x2d, 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, - 0x38, 0xb3, 0xf9, 0x5a, 0xee, 0x0e, 0x1d, 0xb6, 0xf9, 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, - 0x1a, 0x4b, 0x5a, 0xaf, 0x62, 0xb5, 0xd3, 0xef, 0x37, 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, - 0xa6, 0x46, 0x7b, 0x38, 0x63, 0x62, 0x3c, 0x18, 0x7d, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, - 0x82, 0x02, 0x3c, 0x30, 0x82, 0x02, 0x38, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, - 0x04, 0x14, 0x35, 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, - 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, - 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, - 0x30, 0x16, 0x80, 0x14, 0x35, 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, - 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, - 0x20, 0x04, 0x82, 0x01, 0xca, 0x30, 0x82, 0x01, 0xc6, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, - 0x01, 0x66, 0x00, 0x52, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, - 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, - 0x00, 0x73, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, - 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, - 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, - 0x00, 0x74, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, - 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, - 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, - 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, - 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, - 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, - 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, - 0x00, 0x72, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, - 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, - 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, - 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, - 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, - 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, - 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, - 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, - 0x00, 0x70, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, - 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, - 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x02, 0x01, 0x16, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, - 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, - 0x02, 0x01, 0x00, 0x6f, 0x8a, 0xb7, 0x35, 0x73, 0x5a, 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, - 0x17, 0x52, 0x1c, 0x70, 0xf0, 0xe0, 0x53, 0xb4, 0x16, 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, - 0x0e, 0xa6, 0x17, 0x86, 0x52, 0xc6, 0x70, 0x73, 0xf3, 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, - 0x0b, 0x85, 0xc9, 0xb9, 0xcf, 0x15, 0x91, 0x05, 0x2e, 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, - 0xf7, 0xe2, 0xd7, 0xf4, 0x60, 0xd2, 0xfc, 0x1d, 0xbf, 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, - 0x92, 0xef, 0xa4, 0x05, 0x34, 0x97, 0x57, 0x97, 0x56, 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, - 0x0e, 0x77, 0x85, 0xf1, 0x37, 0xc6, 0x19, 0x8b, 0x23, 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, - 0x78, 0xc5, 0xe6, 0x77, 0xfe, 0x72, 0x5f, 0xb2, 0x2c, 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, - 0xd9, 0x78, 0x20, 0xae, 0xbd, 0x75, 0x61, 0x6a, 0xaa, 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, - 0x91, 0x5c, 0x0a, 0x85, 0xc9, 0x59, 0x7d, 0x4e, 0x89, 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, - 0x1e, 0x62, 0x1e, 0xb9, 0x62, 0x2c, 0x34, 0x49, 0x15, 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, - 0x01, 0xc0, 0xda, 0x48, 0x44, 0xd4, 0x8b, 0xd3, 0x17, 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, - 0xaa, 0x14, 0x22, 0xa1, 0x38, 0x09, 0x0b, 0xb7, 0x0c, 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, - 0x07, 0xb4, 0x1b, 0xb3, 0x4a, 0xab, 0xae, 0xf6, 0xe7, 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, - 0xf9, 0x30, 0x28, 0x61, 0x92, 0x52, 0x58, 0x10, 0x15, 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, - 0x67, 0xc4, 0xb4, 0xcf, 0xe6, 0xf9, 0x46, 0x68, 0xe2, 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, - 0x9a, 0x45, 0x70, 0x3c, 0xf2, 0xdf, 0x29, 0x20, 0x9e, 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, - 0x4b, 0xae, 0x1a, 0x2f, 0x53, 0x03, 0x9a, 0xfd, 0x68, 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, - 0x3c, 0x1b, 0x47, 0x43, 0x19, 0x81, 0x0e, 0x0a, 0xbb, 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, - 0xb7, 0x9c, 0xe1, 0xf9, 0xeb, 0x37, 0xb0, 0x11, 0x20, 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, - 0xaf, 0x63, 0xed, 0x6a, 0x63, 0x1f, 0x1e, 0x61, 0x62, 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, - 0xd7, 0xba, 0x4f, 0xf2, 0x61, 0x26, 0x29, 0x99, 0xea, 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, - 0x5c, 0xe7, 0x86, 0x1d, 0xef, 0xf4, 0x6f, 0x3b, 0x6c, 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, - 0x9d, 0x0f, 0xdc, 0xcc, 0x0e, 0x7b, 0xf8, 0xc4, 0xee, 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, - 0xc8, 0x18, 0x4d, 0xa1, 0xe4, 0x40, 0x2c, 0xe9, 0x13, 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, - 0x93, 0x66, 0x56, 0x35, 0x5c, 0xc1, 0x38, 0x7d, 0xa1, 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, - 0xb6, 0x37, 0x19, 0x61, 0x81, 0x40, 0xba, 0xd7, 0x07, 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, - 0x8a, 0x2b, 0x99, 0x5a, 0x17, 0x3f, 0x9f, 0xcf, 0x86, 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, - 0x2d, 0x52, 0xce, 0x87, 0x10, 0x0f, 0x25, 0xc2, 0x1e, 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, - 0xd1, 0x65, 0xa8, 0xb4, 0xf6, 0xa5, 0x71, 0xad, 0x45, 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, - 0x96, 0x5a, 0x5d, 0x69, 0xfa, 0xdb, 0x13, 0x39, 0xb8, 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, - 0x6d, 0x39, 0xff, 0x26, 0xce, 0x2c, 0xa8, 0x5a, 0x7e, 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, - 0x48, 0xd3, 0xf8, 0x00, 0x00, 0x31, 0x82, 0x03, 0x28, 0x30, 0x82, 0x03, 0x24, 0x02, 0x01, 0x01, - 0x30, 0x81, 0x91, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, - 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, - 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x02, 0x08, 0x04, 0x2e, 0x97, 0xbb, - 0x62, 0x84, 0xd9, 0x1c, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x01, 0x05, 0x00, 0xa0, 0x69, 0x30, 0x18, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x03, 0x31, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, - 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, - 0x31, 0x33, 0x30, 0x36, 0x32, 0x35, 0x30, 0x30, 0x33, 0x39, 0x33, 0x33, 0x5a, 0x30, 0x2f, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x40, 0xe5, - 0x7f, 0xba, 0xdb, 0xb7, 0xe8, 0x35, 0xa0, 0x59, 0xd4, 0xa0, 0x57, 0x5c, 0x60, 0x53, 0x98, 0x48, - 0xda, 0x3b, 0x79, 0xf4, 0x73, 0x63, 0xd7, 0x90, 0xf0, 0x10, 0x2b, 0x71, 0x6e, 0x36, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, - 0x00, 0x6a, 0x51, 0xe7, 0xdc, 0x34, 0x87, 0x3c, 0x45, 0xd1, 0xeb, 0x6d, 0x20, 0x26, 0xcd, 0x53, - 0x01, 0x82, 0x71, 0x25, 0x73, 0xce, 0xe3, 0x9f, 0xfb, 0xca, 0x4c, 0x89, 0x01, 0x96, 0x6a, 0x1c, - 0x02, 0x57, 0xb1, 0xd1, 0x99, 0x43, 0x29, 0x4e, 0xfc, 0xf3, 0x30, 0x9e, 0xbc, 0x7e, 0xc4, 0x04, - 0xa3, 0x5d, 0x1a, 0x3c, 0x54, 0xc2, 0xba, 0x38, 0xdc, 0x8d, 0x12, 0xaf, 0xb4, 0x12, 0xe4, 0xeb, - 0x8a, 0x03, 0xb0, 0xc7, 0xaa, 0x72, 0xf4, 0x8b, 0x87, 0xd0, 0x0e, 0xd7, 0x9f, 0x45, 0xcb, 0xa5, - 0x0f, 0x4c, 0x60, 0x2b, 0xe5, 0xf7, 0xe8, 0xf1, 0x0a, 0xc0, 0x29, 0x0f, 0xe0, 0xa7, 0x0a, 0xc0, - 0x4b, 0xd9, 0x16, 0x04, 0xde, 0x4d, 0xc1, 0x5c, 0xbd, 0xad, 0x84, 0xb3, 0x8e, 0x72, 0x7d, 0xcc, - 0x73, 0x77, 0xe9, 0xeb, 0x3a, 0x36, 0xbc, 0xbd, 0x58, 0x0b, 0x97, 0x12, 0xd2, 0x9c, 0x3b, 0xd1, - 0x32, 0x2d, 0xbd, 0xe7, 0x40, 0xc8, 0x4c, 0x82, 0xbb, 0xe4, 0x49, 0xbc, 0x64, 0x50, 0xe3, 0x8b, - 0xba, 0xa2, 0xac, 0x31, 0xdb, 0xcd, 0x57, 0x79, 0xeb, 0x91, 0x87, 0xc7, 0x52, 0x70, 0xfe, 0xaa, - 0xd0, 0x7d, 0xd2, 0x78, 0x48, 0x77, 0xbc, 0xd9, 0xa7, 0x2b, 0x01, 0x20, 0x36, 0xd0, 0x99, 0x61, - 0x90, 0xfc, 0xb2, 0x8a, 0xfd, 0x02, 0xad, 0x60, 0xb6, 0x89, 0x82, 0xca, 0x8a, 0xc3, 0x6f, 0xd7, - 0x91, 0xb1, 0x4c, 0x25, 0x6a, 0x00, 0x59, 0xaa, 0x2c, 0xa0, 0xfc, 0x8b, 0x54, 0x64, 0xbd, 0x04, - 0x46, 0x8f, 0x7c, 0x1d, 0x53, 0xd4, 0x57, 0x9c, 0x06, 0x1f, 0xd8, 0x8e, 0x8b, 0x79, 0x0a, 0xe6, - 0xf5, 0xf3, 0xab, 0x10, 0x8c, 0xe1, 0x65, 0xd7, 0x0f, 0xf1, 0x9f, 0xe3, 0xf7, 0xd1, 0xca, 0xb2, - 0x6d, 0xcb, 0x6b, 0x50, 0x94, 0x1f, 0x1f, 0x4d, 0x55, 0xd1, 0xcb, 0x99, 0x86, 0xfe, 0xa4, 0xe5, - 0x05, 0x6c, 0x09, 0x54, 0x3a, 0xc7, 0x1c, 0x6e, 0xa5, 0x9c, 0x49, 0x69, 0xbb, 0xc3, 0x24, 0x8c, - 0x94, 0xf6, 0x67, 0xbd, 0x7b, 0xe9, 0x71, 0x31, 0x14, 0xcf, 0xf3, 0xf4, 0xdc, 0xd9, 0xdf, 0x99, - 0x31, 0x3d, 0x6f, 0xda, 0xba, 0x7c, 0x62, 0xbd, 0x2c, 0x01, 0x2c, 0x03, 0xa5, 0xfb, 0x22, 0xac, - 0x55, 0x60, 0x89, 0xe4, 0xf2, 0xb4, 0xb7, 0xed, 0x18, 0x9d, 0xa5, 0xe9, 0x55, 0xe6, 0xef, 0xbb, - 0x79, 0xe6, 0xf9, 0xd0, 0xf0, 0x62, 0x71, 0x30, 0x12, 0xdf, 0xde, 0x15, 0x42, 0x46, 0x2c, 0x5a, - 0x81, 0x6f, 0x3c, 0x38, 0x7f, 0x75, 0x00, 0x95, 0x68, 0xea, 0x43, 0x1c, 0x6a, 0xf9, 0x81, 0xde, - 0xb5, 0x0c, 0x0e, 0x50, 0xb5, 0x67, 0x9a, 0xea, 0x37, 0x6d, 0x9d, 0xd3, 0xd0, 0x69, 0x89, 0x5c, - 0x51, 0x27, 0x37, 0x10, 0x6f, 0x6e, 0x13, 0xdb, 0xb8, 0xb8, 0xe9, 0xd0, 0x84, 0x12, 0xf2, 0x3d, - 0x71, 0xc9, 0x7c, 0xe6, 0x9a, 0x1c, 0x50, 0xee, 0x43, 0x25, 0xff, 0x0b, 0x31, 0x88, 0x5b, 0xfa, - 0xc9, 0x84, 0x31, 0xb8, 0x6f, 0x67, 0x37, 0x7f, 0xa5, 0x0c, 0xaf, 0x15, 0x2a, 0x15, 0x04, 0xbd, - 0x1c, 0x76, 0xcb, 0x34, 0xb2, 0x38, 0x77, 0x2f, 0x1a, 0x09, 0x8b, 0x01, 0x44, 0xf5, 0x5f, 0x47, - 0x40, 0x64, 0x2a, 0x21, 0x4a, 0x88, 0xa2, 0xdd, 0xe6, 0xc5, 0xc4, 0x9d, 0xfd, 0x7c, 0x3d, 0xe3, - 0x1a, 0x79, 0x30, 0x90, 0xda, 0x17, 0x4d, 0x92, 0x86, 0xe6, 0xf7, 0x19, 0x93, 0x58, 0x1f, 0x21, - 0x16, 0x60, 0x01, 0x6a, 0xbb, 0x69, 0xc4, 0xfd, 0x29, 0xfc, 0xac, 0x04, 0xcb, 0x97, 0x7b, 0x47, - 0x51, 0xf6, 0x29, 0xca, 0x48, 0x52, 0x02, 0xb6, 0x27, 0x1c, 0xf2, 0x96, 0x06, 0x48, 0x23, 0x9d, - 0xf6, 0x93, 0xda, 0x5d, 0x83, 0x61, 0x2b, 0xbd, 0x52, 0x0c, 0x4d, 0x89, 0xf3, 0x2f, 0xa2, 0x67, - 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const UInt8 kSignedManifestData[] = { - 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, - 0x80, 0x02, 0x01, 0x01, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x82, 0x01, 0xeb, 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, - 0x30, 0x30, 0xd8, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, - 0x0e, 0x0f, 0x10, 0x5d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x5d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x5f, - 0x10, 0x0f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x64, 0x61, 0x74, - 0x61, 0x5d, 0x45, 0x56, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x5f, - 0x10, 0x14, 0x47, 0x72, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, - 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x10, 0x12, 0x41, 0x73, 0x73, 0x65, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x10, 0x0f, 0x63, 0x65, - 0x72, 0x74, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x10, 0x19, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x45, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x77, 0xfc, 0xe6, 0x2c, 0x4f, 0x10, - 0x20, 0x08, 0x89, 0x3f, 0xe7, 0x83, 0xdf, 0x07, 0x61, 0xaf, 0x65, 0x58, 0x66, 0xce, 0x74, 0xb5, - 0x46, 0x56, 0xc2, 0x03, 0x35, 0x4a, 0xd4, 0x88, 0xa7, 0x32, 0x6e, 0xdd, 0xcb, 0xb9, 0xb5, 0x21, - 0x6c, 0x4f, 0x10, 0x20, 0x2e, 0xa3, 0x40, 0x44, 0x60, 0xdb, 0x4f, 0x51, 0x3c, 0x06, 0x27, 0x4e, - 0x00, 0x7b, 0x25, 0x35, 0x13, 0x9a, 0x61, 0xc4, 0xa8, 0x0a, 0xaa, 0xcd, 0x70, 0xe7, 0x75, 0x7e, - 0x4d, 0x52, 0xbb, 0x24, 0x4f, 0x10, 0x20, 0x41, 0x11, 0x04, 0x71, 0xcb, 0x9b, 0xfb, 0xaf, 0xcf, - 0x6f, 0x1d, 0xee, 0x8e, 0x14, 0x3c, 0x1d, 0x39, 0x64, 0x68, 0xc8, 0x48, 0xb1, 0xee, 0x8a, 0xd1, - 0x05, 0x62, 0x40, 0x4f, 0x79, 0x22, 0x30, 0x4f, 0x10, 0x20, 0xa5, 0x0a, 0x89, 0x37, 0xf0, 0xa8, - 0x87, 0x2b, 0xcc, 0x33, 0xc1, 0x5a, 0xe6, 0xd3, 0x01, 0x43, 0x83, 0x50, 0x8d, 0x49, 0x84, 0x96, - 0x22, 0xaf, 0x3e, 0x26, 0x10, 0x78, 0x8a, 0x3a, 0x0c, 0x78, 0x4f, 0x10, 0x20, 0x6c, 0xcb, 0x07, - 0xc1, 0x68, 0x6f, 0xf9, 0xa3, 0x0c, 0x12, 0xd7, 0xb8, 0xe2, 0x51, 0x3d, 0xe2, 0xd5, 0x43, 0xeb, - 0xb5, 0x6d, 0x80, 0x6d, 0x8c, 0xca, 0x17, 0xd5, 0x31, 0x1a, 0x65, 0x48, 0x15, 0x4f, 0x10, 0x20, - 0xa6, 0x4c, 0x19, 0xd2, 0xb8, 0xe4, 0xbf, 0x59, 0x9a, 0x68, 0xe5, 0x34, 0x08, 0xc3, 0x61, 0x91, - 0xf9, 0x06, 0xf1, 0x16, 0x02, 0x1c, 0xfd, 0xaf, 0x46, 0xfb, 0xad, 0xc7, 0xb4, 0x57, 0x1d, 0x54, - 0x4f, 0x10, 0x20, 0x94, 0x47, 0xd4, 0x5d, 0xaf, 0x6a, 0x4f, 0xba, 0xc4, 0xe8, 0x6b, 0x10, 0x32, - 0x2a, 0x37, 0x90, 0x3c, 0x5a, 0x5b, 0x9f, 0x33, 0x48, 0x59, 0xd3, 0x1d, 0xf5, 0x57, 0x90, 0xde, - 0xb3, 0x5b, 0xf6, 0x00, 0x08, 0x00, 0x19, 0x00, 0x27, 0x00, 0x35, 0x00, 0x47, 0x00, 0x55, 0x00, - 0x6c, 0x00, 0x81, 0x00, 0x93, 0x00, 0xaf, 0x00, 0xb4, 0x00, 0xd7, 0x00, 0xfa, 0x01, 0x1d, 0x01, - 0x40, 0x01, 0x63, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x80, 0x30, 0x82, 0x07, - 0xab, 0x30, 0x82, 0x05, 0x93, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x04, 0x2e, 0x97, 0xbb, - 0x62, 0x84, 0xd9, 0x1c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x0b, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, - 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, - 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, - 0x30, 0x36, 0x32, 0x35, 0x30, 0x30, 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, - 0x36, 0x32, 0x31, 0x30, 0x30, 0x30, 0x39, 0x33, 0x38, 0x5a, 0x30, 0x59, 0x31, 0x23, 0x30, 0x21, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, - 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, - 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, 0x65, - 0x20, 0x4f, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, - 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xad, 0xef, 0x52, 0xc8, 0xda, 0x8e, 0x3c, 0xcc, 0x06, 0xcf, - 0xfc, 0xed, 0xdb, 0x92, 0xb3, 0xa8, 0xe0, 0x3b, 0x14, 0x40, 0x34, 0xad, 0x91, 0xf3, 0xbe, 0x1a, - 0x00, 0xbb, 0x06, 0xa2, 0xd7, 0x24, 0x6f, 0xd5, 0xd3, 0xdf, 0xd9, 0xff, 0x0b, 0x4d, 0x6d, 0xc5, - 0xdd, 0x7a, 0x37, 0xfa, 0x08, 0x49, 0x0e, 0x36, 0x5e, 0xab, 0x83, 0x8d, 0xeb, 0x83, 0x00, 0xf9, - 0xaa, 0xe4, 0x88, 0x09, 0x87, 0x05, 0x6b, 0x01, 0x6e, 0x49, 0x54, 0xa1, 0x3b, 0x5c, 0xfc, 0x2b, - 0x0f, 0x1f, 0xa9, 0x7c, 0xc1, 0xc5, 0xe1, 0x32, 0xd7, 0x86, 0x49, 0x80, 0x0f, 0xf8, 0xe3, 0x3b, - 0xa3, 0x12, 0x06, 0x5d, 0xf4, 0x43, 0xc0, 0xb2, 0xc7, 0xcf, 0xb4, 0x14, 0x2c, 0x50, 0x70, 0x57, - 0xb9, 0xb2, 0xe7, 0x72, 0x9a, 0x9f, 0x45, 0x0b, 0x0d, 0xe5, 0xab, 0x3e, 0x23, 0x91, 0xe0, 0x88, - 0x84, 0x3a, 0xec, 0xaa, 0x80, 0xab, 0x37, 0xa3, 0x0c, 0x63, 0x99, 0x1c, 0xde, 0x1b, 0x29, 0x95, - 0x4b, 0xff, 0xcd, 0x92, 0x10, 0xa3, 0x50, 0x93, 0x89, 0x4f, 0xdc, 0x30, 0x0d, 0x29, 0x2a, 0x80, - 0x04, 0x32, 0xb3, 0xb9, 0xa7, 0x79, 0x5f, 0x18, 0xce, 0xc1, 0x90, 0xe6, 0xd6, 0x0c, 0xeb, 0x91, - 0x27, 0x6f, 0x17, 0xd2, 0x93, 0xda, 0xa1, 0xa8, 0x3f, 0x20, 0xe9, 0xeb, 0x54, 0x37, 0xd7, 0x54, - 0xfd, 0x44, 0xa2, 0x8d, 0xa4, 0x30, 0x6e, 0xbf, 0xd0, 0xbd, 0xc4, 0x7d, 0x93, 0xeb, 0xf6, 0xfa, - 0x1e, 0xc1, 0xd5, 0xee, 0xfe, 0xb7, 0x56, 0x51, 0xb3, 0x0b, 0x3f, 0xf4, 0xb1, 0x77, 0x75, 0xaf, - 0x10, 0x14, 0x98, 0x74, 0x41, 0x40, 0xdb, 0xe4, 0x6b, 0x3f, 0x49, 0xce, 0xb8, 0x80, 0x20, 0x72, - 0x92, 0xcb, 0x63, 0x63, 0x44, 0x4e, 0xe8, 0xe4, 0xde, 0xe9, 0xc3, 0x0a, 0x75, 0xd8, 0xbf, 0xc5, - 0x8e, 0xcb, 0xcf, 0xec, 0x65, 0x49, 0x56, 0xa1, 0x9f, 0xb6, 0x39, 0x53, 0x69, 0xb4, 0x04, 0xe8, - 0xd0, 0x28, 0xc6, 0x69, 0xde, 0xdb, 0x30, 0xa7, 0xb0, 0xbf, 0x6f, 0xfe, 0x7b, 0x45, 0x87, 0x07, - 0xf0, 0x85, 0x34, 0x71, 0xca, 0xe5, 0x07, 0x61, 0xce, 0x53, 0xf3, 0xd6, 0x69, 0x70, 0x5a, 0x4b, - 0x7e, 0xda, 0x9b, 0x77, 0x17, 0x65, 0x6c, 0x4d, 0xd5, 0x59, 0x00, 0x6f, 0x47, 0x65, 0x30, 0x98, - 0xd9, 0x7b, 0xa7, 0x51, 0x8b, 0x47, 0x7d, 0x8f, 0x5a, 0x91, 0x72, 0xe4, 0x86, 0x4f, 0xb0, 0xb4, - 0x12, 0x42, 0x55, 0x95, 0x59, 0xa3, 0xc6, 0xdf, 0xba, 0x20, 0x0e, 0x5d, 0x0f, 0x6a, 0x6a, 0xc2, - 0x08, 0x93, 0x9f, 0x0e, 0x8b, 0x61, 0x20, 0x9e, 0x2b, 0x64, 0x26, 0x15, 0x52, 0x9b, 0xef, 0x34, - 0x7c, 0x12, 0xa4, 0xe4, 0xf7, 0xfc, 0x9a, 0xa6, 0xe6, 0xe9, 0x6f, 0xfc, 0xbb, 0x16, 0xc4, 0x0f, - 0x0b, 0xac, 0x84, 0x9d, 0xc8, 0xe9, 0x98, 0xe1, 0xf4, 0x35, 0xfb, 0x97, 0x63, 0x14, 0x6c, 0x15, - 0x51, 0x51, 0x5b, 0xc8, 0x64, 0x25, 0x46, 0x44, 0x6d, 0xbd, 0x17, 0xdd, 0x17, 0x4d, 0x34, 0x77, - 0xa8, 0x6d, 0x4b, 0x97, 0x4b, 0x77, 0xf5, 0x77, 0x07, 0x1b, 0x93, 0x18, 0xf3, 0x44, 0x4e, 0x79, - 0xe2, 0xfc, 0x96, 0x76, 0x5e, 0x69, 0x85, 0xf6, 0xb6, 0x97, 0xbb, 0xb0, 0x41, 0x1f, 0x03, 0x8b, - 0xcb, 0xc0, 0xa9, 0x10, 0x67, 0x8f, 0x6f, 0x67, 0xab, 0xb0, 0xbd, 0x1f, 0xc7, 0x11, 0xfd, 0xb8, - 0x29, 0x47, 0x41, 0xd4, 0x34, 0x0f, 0x5b, 0x9d, 0x64, 0xfb, 0x8f, 0x5f, 0x37, 0xd1, 0x9a, 0x4a, - 0x2d, 0x62, 0xd1, 0x74, 0x2e, 0x6b, 0x7f, 0xdf, 0xb3, 0xea, 0x5f, 0xfa, 0x63, 0xd4, 0x4f, 0xb3, - 0x89, 0x76, 0x67, 0x36, 0x71, 0xcd, 0xaf, 0xd7, 0x9c, 0x95, 0xa8, 0xce, 0xee, 0x29, 0x25, 0xb1, - 0x2a, 0xac, 0x99, 0x10, 0x9b, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x49, 0x30, - 0x82, 0x02, 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xcd, 0xbf, - 0x6f, 0x14, 0xff, 0x8b, 0xb7, 0xf7, 0x29, 0xcd, 0xa4, 0x8c, 0xc1, 0xb1, 0x30, 0x92, 0x37, 0x8b, - 0xd4, 0xef, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35, 0x07, 0x82, - 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, - 0x1c, 0x30, 0x82, 0x01, 0xe3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x82, 0x01, - 0xd7, 0x30, 0x82, 0x01, 0xd3, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x63, 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, - 0x00, 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, - 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, - 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, - 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, - 0x00, 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, - 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, - 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, - 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, - 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, - 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, - 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, - 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, - 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, - 0x00, 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, - 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, - 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, - 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, - 0x00, 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, - 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, - 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, - 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, - 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, - 0x00, 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, - 0x16, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, - 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x0b, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x0d, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, - 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0xc3, 0xd1, 0x52, 0x94, - 0x51, 0xa7, 0x6d, 0xe9, 0xf8, 0x1a, 0xba, 0x15, 0x2c, 0x38, 0x6b, 0xd6, 0xba, 0xcf, 0x12, 0x20, - 0x1d, 0x46, 0xef, 0x99, 0x48, 0x95, 0x9d, 0x1e, 0x49, 0x1b, 0xe7, 0x95, 0xde, 0x73, 0x28, 0xc1, - 0x90, 0xfe, 0xeb, 0x39, 0xe1, 0xa8, 0xa8, 0x5c, 0x4e, 0x71, 0x03, 0x1b, 0x22, 0x37, 0x07, 0xed, - 0x24, 0xa4, 0xee, 0x5d, 0x0a, 0xf8, 0x04, 0xf8, 0xba, 0x34, 0x50, 0xc0, 0x49, 0xd7, 0xa4, 0x4f, - 0xdd, 0x06, 0x81, 0x33, 0x3a, 0x69, 0x4e, 0x43, 0x85, 0x15, 0xde, 0x05, 0x37, 0xf5, 0xb3, 0xd5, - 0x68, 0x4c, 0x30, 0x6a, 0x52, 0x35, 0x6a, 0xb0, 0x2b, 0x8e, 0xe1, 0xde, 0xa6, 0xd2, 0xfc, 0xe2, - 0x9f, 0xdc, 0x95, 0x65, 0x13, 0x45, 0x91, 0xc1, 0x7b, 0xff, 0x90, 0x6a, 0x4c, 0xd3, 0x20, 0x5c, - 0x1b, 0x99, 0xea, 0x82, 0xec, 0xfd, 0x0b, 0x89, 0x25, 0x6c, 0x31, 0x3d, 0xa8, 0x52, 0xba, 0x8e, - 0xdf, 0x20, 0xcb, 0x5f, 0x00, 0xf8, 0x6b, 0xf2, 0x63, 0x5d, 0x2a, 0x55, 0xc6, 0xee, 0x34, 0xa4, - 0x86, 0xab, 0x47, 0x89, 0xcd, 0xb6, 0xaa, 0xe0, 0x5c, 0x9a, 0x57, 0x7d, 0x3e, 0xaa, 0x8b, 0x74, - 0xfc, 0x94, 0xc7, 0x9d, 0x0e, 0xa2, 0x92, 0xa9, 0xc5, 0xdd, 0x71, 0x53, 0x54, 0x38, 0xb0, 0x22, - 0x88, 0xdc, 0x46, 0xcd, 0x45, 0xc7, 0x33, 0xc7, 0x2f, 0xed, 0x5f, 0x4d, 0x05, 0x9d, 0xba, 0x2e, - 0xf7, 0xa4, 0xb5, 0xfa, 0x79, 0x11, 0x41, 0xd1, 0x1b, 0x50, 0xab, 0xef, 0xdf, 0xa8, 0x5c, 0x28, - 0xc7, 0x8e, 0x86, 0xa2, 0x85, 0x8a, 0x90, 0xf4, 0xda, 0x71, 0x1f, 0xff, 0x7f, 0x02, 0x4c, 0x24, - 0x95, 0x0d, 0x31, 0xa3, 0x8b, 0x62, 0xae, 0x45, 0xe2, 0x44, 0x6c, 0x01, 0x1d, 0xdc, 0x67, 0xbe, - 0xfb, 0x16, 0x4f, 0x4c, 0xf0, 0x81, 0xa8, 0xbd, 0xe1, 0x29, 0x6f, 0x1c, 0xff, 0xa4, 0x82, 0x96, - 0xa3, 0x67, 0xad, 0xa6, 0x99, 0xd6, 0x29, 0x02, 0x7f, 0xfc, 0xe3, 0x8d, 0xe3, 0x0d, 0x17, 0x91, - 0x84, 0xcf, 0x4b, 0x05, 0xdd, 0x29, 0x96, 0xb4, 0x58, 0x56, 0x9b, 0x65, 0x17, 0xdd, 0x16, 0x1f, - 0xf8, 0x59, 0x8d, 0xfb, 0xa0, 0xb0, 0xc7, 0x0b, 0x74, 0x64, 0xef, 0x8c, 0xcb, 0xba, 0x10, 0x48, - 0x37, 0x28, 0xc9, 0x7f, 0x17, 0xac, 0x5f, 0x04, 0xa0, 0x50, 0x6d, 0x18, 0x5f, 0x23, 0xe3, 0x9c, - 0xb6, 0xe0, 0x6c, 0xc0, 0xe1, 0x5e, 0xba, 0x8f, 0x70, 0xf1, 0xca, 0xc5, 0x97, 0x95, 0xf7, 0x4c, - 0xdd, 0x6c, 0x8c, 0xbb, 0x4d, 0x68, 0x18, 0x59, 0xb3, 0x1b, 0x6f, 0x81, 0xe7, 0xd8, 0x44, 0xdc, - 0x6e, 0x84, 0xce, 0x5b, 0x0c, 0x66, 0xef, 0xc4, 0x72, 0x00, 0xf2, 0x5a, 0xef, 0x82, 0x63, 0x18, - 0xf7, 0xd3, 0xb8, 0x25, 0xc4, 0x91, 0x80, 0x04, 0x54, 0x61, 0x5b, 0xf5, 0xe2, 0xda, 0xfb, 0x1d, - 0xd4, 0x19, 0x99, 0x18, 0xbd, 0x9a, 0x1e, 0x96, 0xe9, 0x1c, 0xd5, 0xd0, 0x06, 0xf5, 0x37, 0x91, - 0x3b, 0x4d, 0xa5, 0x2a, 0xda, 0x3c, 0xcd, 0xa6, 0xda, 0x53, 0xb8, 0x4a, 0x1e, 0xb9, 0x51, 0xed, - 0xc3, 0x47, 0xc6, 0xfa, 0xdc, 0x2e, 0xb3, 0xdd, 0x63, 0x65, 0xba, 0x17, 0xdb, 0x65, 0x8b, 0x63, - 0x77, 0x31, 0x6d, 0xd9, 0xb7, 0x18, 0x33, 0x91, 0xa1, 0x1f, 0xed, 0x0d, 0x49, 0x7f, 0x29, 0xd6, - 0xd4, 0xf6, 0x12, 0x0f, 0xb2, 0x0c, 0xc9, 0x0f, 0x61, 0xb1, 0x48, 0x58, 0x52, 0xac, 0x80, 0x92, - 0xb4, 0x2d, 0x4c, 0xa8, 0x94, 0xf6, 0x99, 0xc8, 0xb7, 0x1a, 0x7f, 0x3a, 0x52, 0x49, 0x9f, 0x44, - 0xff, 0x0d, 0x38, 0x27, 0x3f, 0xad, 0xf6, 0xa4, 0x8f, 0xd9, 0x4b, 0x30, 0x6f, 0xe0, 0xb8, 0x20, - 0x94, 0x82, 0x4c, 0x96, 0xea, 0x27, 0x28, 0x61, 0x1a, 0x41, 0x6d, 0xd4, 0x30, 0x82, 0x07, 0xca, - 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e, 0xa1, 0x31, 0xe7, 0xca, - 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, - 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, - 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, - 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x36, - 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, - 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, - 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, - 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, 0x0c, 0x6f, 0x45, 0xb4, 0x04, 0x59, 0x24, 0xcb, 0x70, - 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, 0x87, 0x61, 0xb3, 0xd3, 0xfc, 0xbe, 0xb6, 0x05, 0x3c, - 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, 0x87, 0x07, 0xcf, 0x20, 0xbe, 0xaa, 0xeb, 0x24, 0xc5, - 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, 0xea, 0xb4, 0x5d, 0x3b, 0x29, 0x6c, 0xba, 0x4d, 0x15, - 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, 0x0d, 0x1d, 0xf7, 0x66, 0x77, 0xa2, 0x96, 0x56, 0xed, - 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, 0x32, 0x9c, 0xa9, 0xfd, 0xbf, 0xb8, 0x34, 0x6f, 0x57, - 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, 0xe9, 0x0f, 0x3c, 0xed, 0x4f, 0x31, 0x87, 0x05, 0xa4, - 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, 0xca, 0xd3, 0xf9, 0xd6, 0xaa, 0xaa, 0x88, 0x57, 0x66, - 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, 0x3d, 0x1d, 0xbc, 0x82, 0x6e, 0x81, 0xe9, 0x19, 0xf5, - 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, 0x88, 0xba, 0x51, 0xe7, 0x3a, 0xa0, 0x77, 0x2d, 0xe6, - 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, 0xf8, 0xa7, 0x79, 0x51, 0x2d, 0xe6, 0xc2, 0xee, 0xd2, - 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, 0x37, 0x12, 0xeb, 0x63, 0x99, 0x3d, 0xf3, 0x21, 0xbe, - 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, 0x0c, 0x4b, 0x43, 0x0c, 0x05, 0x6a, 0x6b, 0x8f, 0x05, - 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, 0xa7, 0x75, 0x63, 0x85, 0xe3, 0xa5, 0x5c, 0xc0, 0xd6, - 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, 0x6b, 0x4e, 0x99, 0x74, 0x7d, 0xd2, 0x69, 0x9f, 0xa8, - 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, 0x7e, 0x4a, 0x7a, 0x8a, 0xeb, 0x7c, 0xcd, 0x43, 0x9e, - 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, 0xe7, 0xfb, 0xa0, 0x43, 0xb3, 0xd7, 0x15, 0x28, 0x8a, - 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, 0x1b, 0x37, 0x33, 0x76, 0xc4, 0x58, 0xb9, 0x2d, 0x89, - 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, 0xa6, 0x07, 0x79, 0x11, 0x7d, 0x26, 0xd2, 0x85, 0x22, - 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, 0x18, 0xf3, 0xaa, 0x05, 0xce, 0x87, 0x99, 0xde, 0x76, - 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, 0x51, 0xa0, 0xc9, 0x70, 0xfc, 0xb9, 0x22, 0xfe, 0xd2, - 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, 0x53, 0xfd, 0xa1, 0xe6, 0xff, 0x8e, 0xd6, 0xde, 0x9e, - 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, 0xb2, 0x34, 0x8a, 0x1d, 0xf7, 0x9e, 0xa0, 0xbb, 0xf4, - 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, 0x92, 0x0d, 0xc9, 0x94, 0x7f, 0x24, 0xb9, 0x9f, 0xda, - 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, 0x3a, 0x70, 0x63, 0x3b, 0x22, 0x42, 0x14, 0xd0, 0xf9, - 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, 0x41, 0x20, 0x0d, 0x7e, 0x70, 0xd7, 0x88, 0x36, 0xa2, - 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, 0x9c, 0x5f, 0x4d, 0x3e, 0x4f, 0x83, 0x79, 0x06, 0x73, - 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, 0xce, 0x93, 0x5c, 0x68, 0xbf, 0x5a, 0xe6, 0x4c, 0x23, - 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, 0x1b, 0x64, 0x39, 0x64, 0xb7, 0xd2, 0x1d, 0xd0, 0x2d, - 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, 0x38, 0xb3, 0xf9, 0x5a, 0xee, 0x0e, 0x1d, 0xb6, 0xf9, - 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, 0x1a, 0x4b, 0x5a, 0xaf, 0x62, 0xb5, 0xd3, 0xef, 0x37, - 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, 0xa6, 0x46, 0x7b, 0x38, 0x63, 0x62, 0x3c, 0x18, 0x7d, - 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3c, 0x30, 0x82, 0x02, 0x38, 0x30, 0x1d, - 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x35, 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, - 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, 0x0f, 0x06, - 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, - 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35, 0x07, 0x82, 0xfe, 0x0e, - 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, - 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0xca, 0x30, 0x82, 0x01, 0xc6, - 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, - 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, - 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00, 0x65, 0x00, 0x6c, 0x00, - 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, - 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, - 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, - 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, - 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, - 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, - 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x70, 0x00, - 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, - 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, - 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x20, 0x00, - 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, - 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, - 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, - 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, - 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, - 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, - 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2e, 0x30, - 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x29, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, - 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x6f, 0x8a, 0xb7, 0x35, 0x73, 0x5a, - 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, 0x17, 0x52, 0x1c, 0x70, 0xf0, 0xe0, 0x53, 0xb4, 0x16, - 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, 0x0e, 0xa6, 0x17, 0x86, 0x52, 0xc6, 0x70, 0x73, 0xf3, - 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, 0x0b, 0x85, 0xc9, 0xb9, 0xcf, 0x15, 0x91, 0x05, 0x2e, - 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, 0xf7, 0xe2, 0xd7, 0xf4, 0x60, 0xd2, 0xfc, 0x1d, 0xbf, - 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, 0x92, 0xef, 0xa4, 0x05, 0x34, 0x97, 0x57, 0x97, 0x56, - 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, 0x0e, 0x77, 0x85, 0xf1, 0x37, 0xc6, 0x19, 0x8b, 0x23, - 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, 0x78, 0xc5, 0xe6, 0x77, 0xfe, 0x72, 0x5f, 0xb2, 0x2c, - 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, 0xd9, 0x78, 0x20, 0xae, 0xbd, 0x75, 0x61, 0x6a, 0xaa, - 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, 0x91, 0x5c, 0x0a, 0x85, 0xc9, 0x59, 0x7d, 0x4e, 0x89, - 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, 0x1e, 0x62, 0x1e, 0xb9, 0x62, 0x2c, 0x34, 0x49, 0x15, - 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, 0x01, 0xc0, 0xda, 0x48, 0x44, 0xd4, 0x8b, 0xd3, 0x17, - 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, 0xaa, 0x14, 0x22, 0xa1, 0x38, 0x09, 0x0b, 0xb7, 0x0c, - 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, 0x07, 0xb4, 0x1b, 0xb3, 0x4a, 0xab, 0xae, 0xf6, 0xe7, - 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, 0xf9, 0x30, 0x28, 0x61, 0x92, 0x52, 0x58, 0x10, 0x15, - 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, 0x67, 0xc4, 0xb4, 0xcf, 0xe6, 0xf9, 0x46, 0x68, 0xe2, - 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, 0x9a, 0x45, 0x70, 0x3c, 0xf2, 0xdf, 0x29, 0x20, 0x9e, - 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, 0x4b, 0xae, 0x1a, 0x2f, 0x53, 0x03, 0x9a, 0xfd, 0x68, - 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, 0x3c, 0x1b, 0x47, 0x43, 0x19, 0x81, 0x0e, 0x0a, 0xbb, - 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, 0xb7, 0x9c, 0xe1, 0xf9, 0xeb, 0x37, 0xb0, 0x11, 0x20, - 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, 0xaf, 0x63, 0xed, 0x6a, 0x63, 0x1f, 0x1e, 0x61, 0x62, - 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, 0xd7, 0xba, 0x4f, 0xf2, 0x61, 0x26, 0x29, 0x99, 0xea, - 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, 0x5c, 0xe7, 0x86, 0x1d, 0xef, 0xf4, 0x6f, 0x3b, 0x6c, - 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, 0x9d, 0x0f, 0xdc, 0xcc, 0x0e, 0x7b, 0xf8, 0xc4, 0xee, - 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, 0xc8, 0x18, 0x4d, 0xa1, 0xe4, 0x40, 0x2c, 0xe9, 0x13, - 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, 0x93, 0x66, 0x56, 0x35, 0x5c, 0xc1, 0x38, 0x7d, 0xa1, - 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, 0xb6, 0x37, 0x19, 0x61, 0x81, 0x40, 0xba, 0xd7, 0x07, - 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, 0x8a, 0x2b, 0x99, 0x5a, 0x17, 0x3f, 0x9f, 0xcf, 0x86, - 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, 0x2d, 0x52, 0xce, 0x87, 0x10, 0x0f, 0x25, 0xc2, 0x1e, - 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, 0xd1, 0x65, 0xa8, 0xb4, 0xf6, 0xa5, 0x71, 0xad, 0x45, - 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, 0x96, 0x5a, 0x5d, 0x69, 0xfa, 0xdb, 0x13, 0x39, 0xb8, - 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, 0x6d, 0x39, 0xff, 0x26, 0xce, 0x2c, 0xa8, 0x5a, 0x7e, - 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, 0x48, 0xd3, 0xf8, 0x00, 0x00, 0x31, 0x82, 0x03, 0x28, - 0x30, 0x82, 0x03, 0x24, 0x02, 0x01, 0x01, 0x30, 0x81, 0x91, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, - 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, - 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, - 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, - 0x53, 0x02, 0x08, 0x04, 0x2e, 0x97, 0xbb, 0x62, 0x84, 0xd9, 0x1c, 0x30, 0x0d, 0x06, 0x09, 0x60, - 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x69, 0x30, 0x18, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x38, 0x31, 0x37, 0x35, - 0x35, 0x32, 0x34, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, - 0x04, 0x31, 0x22, 0x04, 0x20, 0x7f, 0xe5, 0xca, 0xfa, 0x9e, 0x7f, 0xd9, 0x3b, 0xec, 0x98, 0x25, - 0x4f, 0x65, 0x73, 0x30, 0x1f, 0x7a, 0xe3, 0x51, 0xd3, 0xa4, 0xa9, 0x18, 0x7e, 0xeb, 0x6f, 0xdb, - 0x13, 0xcb, 0x2f, 0x82, 0x4b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0x5e, 0xc2, 0x3f, 0x3d, 0x74, 0x0e, 0x23, 0x44, - 0xec, 0x4f, 0x51, 0x96, 0x08, 0x28, 0x05, 0xe1, 0x2e, 0xd6, 0xba, 0x3a, 0x51, 0xf4, 0x46, 0xff, - 0x2c, 0x96, 0x4a, 0x05, 0xa0, 0xa1, 0x89, 0xc8, 0x8d, 0x28, 0xb8, 0x1d, 0xc2, 0xc7, 0xa3, 0x6e, - 0x43, 0x9b, 0xa0, 0xe8, 0xcb, 0x3a, 0x5e, 0xa7, 0xa7, 0xe7, 0x34, 0x93, 0xc9, 0x31, 0xf7, 0xde, - 0x92, 0x55, 0x95, 0x22, 0x96, 0xdf, 0xbb, 0x6e, 0xb3, 0xb1, 0x8c, 0x20, 0x9f, 0x6f, 0x20, 0x85, - 0xae, 0x3a, 0x48, 0x69, 0xfe, 0x5d, 0xd9, 0xf0, 0xe9, 0xd1, 0x86, 0x74, 0xc8, 0x13, 0x58, 0x27, - 0xc6, 0xb5, 0x00, 0x76, 0xa3, 0x75, 0x01, 0x53, 0xfe, 0x8f, 0x7d, 0xe4, 0x69, 0x51, 0x3b, 0x19, - 0x4b, 0xef, 0x34, 0x6e, 0x33, 0xf1, 0x03, 0x4d, 0xfc, 0x08, 0xd9, 0xe3, 0x47, 0x19, 0x83, 0x83, - 0xb9, 0xa1, 0x83, 0x14, 0x5a, 0x70, 0x4f, 0xf7, 0x72, 0x2c, 0x00, 0x04, 0xce, 0x3f, 0x5d, 0xf2, - 0xd3, 0xd8, 0x03, 0x7d, 0xe6, 0xb7, 0xf3, 0xe5, 0x88, 0x44, 0x91, 0x3e, 0x2f, 0x15, 0x51, 0x36, - 0xbd, 0x16, 0xcb, 0x96, 0xc0, 0xda, 0x33, 0xa5, 0x82, 0x07, 0xc0, 0x6f, 0x20, 0x81, 0x0a, 0x5a, - 0x14, 0xc9, 0x35, 0xe3, 0xf7, 0x08, 0x7a, 0x10, 0x80, 0x66, 0x08, 0xa5, 0x88, 0x22, 0xf6, 0xab, - 0x37, 0xbc, 0xc0, 0x75, 0x2c, 0xca, 0xed, 0x5b, 0x83, 0x0c, 0x4b, 0xed, 0x11, 0x05, 0xb1, 0xf9, - 0x91, 0x2b, 0x2a, 0x3e, 0x0f, 0xa7, 0x1e, 0xfe, 0x68, 0xb9, 0x88, 0x02, 0x0b, 0x51, 0xf2, 0x38, - 0x3c, 0xc1, 0xb7, 0x56, 0x57, 0x20, 0x7b, 0xcf, 0xfa, 0x19, 0x85, 0x1f, 0x64, 0x2f, 0x55, 0xb8, - 0xde, 0x80, 0xee, 0x04, 0x99, 0xa9, 0x53, 0x42, 0x15, 0x27, 0x27, 0x22, 0x2e, 0xae, 0xee, 0x98, - 0x17, 0x3e, 0xd6, 0xcf, 0xc7, 0x1c, 0x8c, 0x1a, 0xb9, 0x6a, 0x0c, 0x34, 0xe7, 0xb2, 0x4f, 0xa3, - 0x25, 0xbc, 0xe6, 0x12, 0xae, 0x51, 0xe8, 0xa3, 0x25, 0x6f, 0xc7, 0x10, 0x3e, 0xcf, 0x74, 0x7c, - 0x97, 0x4a, 0x4d, 0xaf, 0xa2, 0x60, 0x9c, 0x99, 0xc7, 0x2a, 0x17, 0x86, 0x13, 0x7b, 0xc6, 0xde, - 0xf1, 0x72, 0xdd, 0x7d, 0x4a, 0x61, 0xce, 0x08, 0xb1, 0x04, 0x6e, 0xcf, 0xc0, 0x50, 0xfd, 0xe9, - 0x80, 0x04, 0xed, 0xb9, 0xbf, 0xc6, 0xcd, 0xa1, 0xad, 0xe7, 0x34, 0x8f, 0x31, 0xb2, 0x6e, 0x25, - 0xba, 0x54, 0x22, 0x23, 0x19, 0x06, 0xe6, 0xea, 0xe7, 0x06, 0x9f, 0x64, 0x44, 0x39, 0x71, 0xc1, - 0xaa, 0xa6, 0xa4, 0xef, 0xaa, 0xdb, 0x6b, 0x9e, 0xce, 0x29, 0x97, 0x55, 0x2f, 0x06, 0x5c, 0x6c, - 0x10, 0xe6, 0xa5, 0x8c, 0x30, 0xf6, 0x81, 0x65, 0xee, 0x74, 0xb3, 0x40, 0xaa, 0x3b, 0x70, 0xcb, - 0x80, 0x50, 0x22, 0x01, 0x0d, 0x12, 0x11, 0x72, 0x6d, 0x10, 0x54, 0x6e, 0xa4, 0x9e, 0x5e, 0xcd, - 0xcc, 0xa0, 0x30, 0xf8, 0x61, 0xab, 0x36, 0x4a, 0x3a, 0xf0, 0x5a, 0xe3, 0xf5, 0x38, 0x70, 0x05, - 0xdd, 0x04, 0x2e, 0x2b, 0x3a, 0xf8, 0x9a, 0x39, 0x48, 0x5f, 0x3f, 0xc6, 0x60, 0xaf, 0x9e, 0xca, - 0x47, 0xb9, 0xfa, 0xb0, 0x1e, 0x45, 0x56, 0x47, 0xe0, 0xf1, 0x00, 0x47, 0x60, 0xb0, 0xca, 0x06, - 0xef, 0xe8, 0xe9, 0x3b, 0xcd, 0x61, 0x8f, 0xc3, 0x14, 0xbc, 0x61, 0x9b, 0x08, 0x4e, 0xf5, 0x4a, - 0xf9, 0x9a, 0x35, 0x5f, 0x84, 0x97, 0x43, 0x24, 0x62, 0x60, 0xd2, 0xa7, 0xd7, 0xe6, 0x10, 0xe7, - 0xf1, 0xe4, 0xd0, 0x96, 0x1f, 0x7c, 0x93, 0xbc, 0x3a, 0x28, 0x59, 0x10, 0x3e, 0x32, 0x71, 0xa4, - 0x9f, 0xab, 0xf6, 0x30, 0x07, 0xca, 0x7e, 0xcd, 0x35, 0xdb, 0xc1, 0xa2, 0x99, 0x8e, 0x7f, 0x85, - 0xba, 0x92, 0xf6, 0x76, 0x99, 0xa3, 0xbc, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const UInt8 kApplePKISettingsRootCACert[] = { - 0x30, 0x82, 0x07, 0xca, 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e, - 0xa1, 0x31, 0xe7, 0xca, 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d, - 0x34, 0x33, 0x30, 0x36, 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x30, 0x81, 0x84, - 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, - 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, - 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, - 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, - 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, 0x0c, 0x6f, 0x45, 0xb4, 0x04, - 0x59, 0x24, 0xcb, 0x70, 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, 0x87, 0x61, 0xb3, 0xd3, 0xfc, - 0xbe, 0xb6, 0x05, 0x3c, 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, 0x87, 0x07, 0xcf, 0x20, 0xbe, - 0xaa, 0xeb, 0x24, 0xc5, 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, 0xea, 0xb4, 0x5d, 0x3b, 0x29, - 0x6c, 0xba, 0x4d, 0x15, 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, 0x0d, 0x1d, 0xf7, 0x66, 0x77, - 0xa2, 0x96, 0x56, 0xed, 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, 0x32, 0x9c, 0xa9, 0xfd, 0xbf, - 0xb8, 0x34, 0x6f, 0x57, 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, 0xe9, 0x0f, 0x3c, 0xed, 0x4f, - 0x31, 0x87, 0x05, 0xa4, 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, 0xca, 0xd3, 0xf9, 0xd6, 0xaa, - 0xaa, 0x88, 0x57, 0x66, 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, 0x3d, 0x1d, 0xbc, 0x82, 0x6e, - 0x81, 0xe9, 0x19, 0xf5, 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, 0x88, 0xba, 0x51, 0xe7, 0x3a, - 0xa0, 0x77, 0x2d, 0xe6, 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, 0xf8, 0xa7, 0x79, 0x51, 0x2d, - 0xe6, 0xc2, 0xee, 0xd2, 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, 0x37, 0x12, 0xeb, 0x63, 0x99, - 0x3d, 0xf3, 0x21, 0xbe, 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, 0x0c, 0x4b, 0x43, 0x0c, 0x05, - 0x6a, 0x6b, 0x8f, 0x05, 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, 0xa7, 0x75, 0x63, 0x85, 0xe3, - 0xa5, 0x5c, 0xc0, 0xd6, 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, 0x6b, 0x4e, 0x99, 0x74, 0x7d, - 0xd2, 0x69, 0x9f, 0xa8, 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, 0x7e, 0x4a, 0x7a, 0x8a, 0xeb, - 0x7c, 0xcd, 0x43, 0x9e, 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, 0xe7, 0xfb, 0xa0, 0x43, 0xb3, - 0xd7, 0x15, 0x28, 0x8a, 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, 0x1b, 0x37, 0x33, 0x76, 0xc4, - 0x58, 0xb9, 0x2d, 0x89, 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, 0xa6, 0x07, 0x79, 0x11, 0x7d, - 0x26, 0xd2, 0x85, 0x22, 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, 0x18, 0xf3, 0xaa, 0x05, 0xce, - 0x87, 0x99, 0xde, 0x76, 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, 0x51, 0xa0, 0xc9, 0x70, 0xfc, - 0xb9, 0x22, 0xfe, 0xd2, 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, 0x53, 0xfd, 0xa1, 0xe6, 0xff, - 0x8e, 0xd6, 0xde, 0x9e, 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, 0xb2, 0x34, 0x8a, 0x1d, 0xf7, - 0x9e, 0xa0, 0xbb, 0xf4, 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, 0x92, 0x0d, 0xc9, 0x94, 0x7f, - 0x24, 0xb9, 0x9f, 0xda, 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, 0x3a, 0x70, 0x63, 0x3b, 0x22, - 0x42, 0x14, 0xd0, 0xf9, 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, 0x41, 0x20, 0x0d, 0x7e, 0x70, - 0xd7, 0x88, 0x36, 0xa2, 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, 0x9c, 0x5f, 0x4d, 0x3e, 0x4f, - 0x83, 0x79, 0x06, 0x73, 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, 0xce, 0x93, 0x5c, 0x68, 0xbf, - 0x5a, 0xe6, 0x4c, 0x23, 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, 0x1b, 0x64, 0x39, 0x64, 0xb7, - 0xd2, 0x1d, 0xd0, 0x2d, 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, 0x38, 0xb3, 0xf9, 0x5a, 0xee, - 0x0e, 0x1d, 0xb6, 0xf9, 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, 0x1a, 0x4b, 0x5a, 0xaf, 0x62, - 0xb5, 0xd3, 0xef, 0x37, 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, 0xa6, 0x46, 0x7b, 0x38, 0x63, - 0x62, 0x3c, 0x18, 0x7d, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3c, 0x30, 0x82, - 0x02, 0x38, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x35, 0x07, 0x82, - 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, - 0x1c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, - 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35, - 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, - 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0xca, - 0x30, 0x82, 0x01, 0xc6, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, - 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00, - 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, - 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, - 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, - 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00, - 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, - 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00, - 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, - 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, - 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, - 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, - 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, - 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, - 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, - 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, - 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, - 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00, - 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, - 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, - 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, - 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, - 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, - 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, - 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, - 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x6f, 0x8a, - 0xb7, 0x35, 0x73, 0x5a, 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, 0x17, 0x52, 0x1c, 0x70, 0xf0, - 0xe0, 0x53, 0xb4, 0x16, 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, 0x0e, 0xa6, 0x17, 0x86, 0x52, - 0xc6, 0x70, 0x73, 0xf3, 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, 0x0b, 0x85, 0xc9, 0xb9, 0xcf, - 0x15, 0x91, 0x05, 0x2e, 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, 0xf7, 0xe2, 0xd7, 0xf4, 0x60, - 0xd2, 0xfc, 0x1d, 0xbf, 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, 0x92, 0xef, 0xa4, 0x05, 0x34, - 0x97, 0x57, 0x97, 0x56, 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, 0x0e, 0x77, 0x85, 0xf1, 0x37, - 0xc6, 0x19, 0x8b, 0x23, 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, 0x78, 0xc5, 0xe6, 0x77, 0xfe, - 0x72, 0x5f, 0xb2, 0x2c, 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, 0xd9, 0x78, 0x20, 0xae, 0xbd, - 0x75, 0x61, 0x6a, 0xaa, 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, 0x91, 0x5c, 0x0a, 0x85, 0xc9, - 0x59, 0x7d, 0x4e, 0x89, 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, 0x1e, 0x62, 0x1e, 0xb9, 0x62, - 0x2c, 0x34, 0x49, 0x15, 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, 0x01, 0xc0, 0xda, 0x48, 0x44, - 0xd4, 0x8b, 0xd3, 0x17, 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, 0xaa, 0x14, 0x22, 0xa1, 0x38, - 0x09, 0x0b, 0xb7, 0x0c, 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, 0x07, 0xb4, 0x1b, 0xb3, 0x4a, - 0xab, 0xae, 0xf6, 0xe7, 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, 0xf9, 0x30, 0x28, 0x61, 0x92, - 0x52, 0x58, 0x10, 0x15, 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, 0x67, 0xc4, 0xb4, 0xcf, 0xe6, - 0xf9, 0x46, 0x68, 0xe2, 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, 0x9a, 0x45, 0x70, 0x3c, 0xf2, - 0xdf, 0x29, 0x20, 0x9e, 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, 0x4b, 0xae, 0x1a, 0x2f, 0x53, - 0x03, 0x9a, 0xfd, 0x68, 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, 0x3c, 0x1b, 0x47, 0x43, 0x19, - 0x81, 0x0e, 0x0a, 0xbb, 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, 0xb7, 0x9c, 0xe1, 0xf9, 0xeb, - 0x37, 0xb0, 0x11, 0x20, 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, 0xaf, 0x63, 0xed, 0x6a, 0x63, - 0x1f, 0x1e, 0x61, 0x62, 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, 0xd7, 0xba, 0x4f, 0xf2, 0x61, - 0x26, 0x29, 0x99, 0xea, 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, 0x5c, 0xe7, 0x86, 0x1d, 0xef, - 0xf4, 0x6f, 0x3b, 0x6c, 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, 0x9d, 0x0f, 0xdc, 0xcc, 0x0e, - 0x7b, 0xf8, 0xc4, 0xee, 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, 0xc8, 0x18, 0x4d, 0xa1, 0xe4, - 0x40, 0x2c, 0xe9, 0x13, 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, 0x93, 0x66, 0x56, 0x35, 0x5c, - 0xc1, 0x38, 0x7d, 0xa1, 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, 0xb6, 0x37, 0x19, 0x61, 0x81, - 0x40, 0xba, 0xd7, 0x07, 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, 0x8a, 0x2b, 0x99, 0x5a, 0x17, - 0x3f, 0x9f, 0xcf, 0x86, 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, 0x2d, 0x52, 0xce, 0x87, 0x10, - 0x0f, 0x25, 0xc2, 0x1e, 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, 0xd1, 0x65, 0xa8, 0xb4, 0xf6, - 0xa5, 0x71, 0xad, 0x45, 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, 0x96, 0x5a, 0x5d, 0x69, 0xfa, - 0xdb, 0x13, 0x39, 0xb8, 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, 0x6d, 0x39, 0xff, 0x26, 0xce, - 0x2c, 0xa8, 0x5a, 0x7e, 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, 0x48, 0xd3, 0xf8 -}; - -static const UInt8 kBasePList[] = { - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd1, 0x01, 0x02, 0x53, 0x66, 0x6f, 0x6f, 0x53, - 0x62, 0x61, 0x72, 0x08, 0x0b, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x13 -}; - -static const UInt8 kBaseManifestData[] = { - 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, - 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, - 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0a, 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, - 0x20, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x22, 0x2d, - 0x2f, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2f, 0x2f, 0x44, 0x54, 0x44, 0x20, 0x50, 0x4c, 0x49, - 0x53, 0x54, 0x20, 0x31, 0x2e, 0x30, 0x2f, 0x2f, 0x45, 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x44, 0x54, 0x44, 0x73, 0x2f, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x4c, - 0x69, 0x73, 0x74, 0x2d, 0x31, 0x2e, 0x30, 0x2e, 0x64, 0x74, 0x64, 0x22, 0x3e, 0x0a, 0x3c, 0x70, - 0x6c, 0x69, 0x73, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, - 0x30, 0x22, 0x3e, 0x0a, 0x3c, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x0a, 0x09, 0x3c, 0x6b, 0x65, 0x79, - 0x3e, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x45, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, - 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x6c, 0x45, 0x66, 0x55, 0x58, 0x61, - 0x39, 0x71, 0x54, 0x37, 0x72, 0x45, 0x36, 0x47, 0x73, 0x51, 0x4d, 0x69, 0x6f, 0x33, 0x6b, 0x44, - 0x78, 0x61, 0x57, 0x35, 0x38, 0x7a, 0x53, 0x46, 0x6e, 0x54, 0x48, 0x66, 0x56, 0x58, 0x6b, 0x4e, - 0x36, 0x7a, 0x57, 0x2f, 0x59, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, - 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, - 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x62, 0x4d, 0x73, 0x48, 0x77, 0x57, 0x68, 0x76, - 0x2b, 0x61, 0x4d, 0x4d, 0x45, 0x74, 0x65, 0x34, 0x34, 0x6c, 0x45, 0x39, 0x34, 0x74, 0x56, 0x44, - 0x36, 0x37, 0x56, 0x74, 0x67, 0x47, 0x32, 0x4d, 0x79, 0x68, 0x66, 0x56, 0x4d, 0x52, 0x70, 0x6c, - 0x53, 0x42, 0x55, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x3c, - 0x6b, 0x65, 0x79, 0x3e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x2e, 0x70, 0x6c, 0x69, 0x73, - 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, - 0x09, 0x43, 0x49, 0x6b, 0x2f, 0x35, 0x34, 0x50, 0x66, 0x42, 0x32, 0x47, 0x76, 0x5a, 0x56, 0x68, - 0x6d, 0x7a, 0x6e, 0x53, 0x31, 0x52, 0x6c, 0x62, 0x43, 0x41, 0x7a, 0x56, 0x4b, 0x31, 0x49, 0x69, - 0x6e, 0x4d, 0x6d, 0x37, 0x64, 0x79, 0x37, 0x6d, 0x31, 0x49, 0x57, 0x77, 0x3d, 0x0a, 0x09, 0x3c, - 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x45, 0x56, 0x52, - 0x6f, 0x6f, 0x74, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, - 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x51, 0x52, 0x45, 0x45, 0x63, 0x63, - 0x75, 0x62, 0x2b, 0x36, 0x2f, 0x50, 0x62, 0x78, 0x33, 0x75, 0x6a, 0x68, 0x51, 0x38, 0x48, 0x54, - 0x6c, 0x6b, 0x61, 0x4d, 0x68, 0x49, 0x73, 0x65, 0x36, 0x4b, 0x30, 0x51, 0x56, 0x69, 0x51, 0x45, - 0x39, 0x35, 0x49, 0x6a, 0x41, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, - 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x47, 0x72, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x64, - 0x4b, 0x65, 0x79, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, - 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x70, 0x51, 0x71, 0x4a, 0x4e, 0x2f, - 0x43, 0x6f, 0x68, 0x79, 0x76, 0x4d, 0x4d, 0x38, 0x46, 0x61, 0x35, 0x74, 0x4d, 0x42, 0x51, 0x34, - 0x4e, 0x51, 0x6a, 0x55, 0x6d, 0x45, 0x6c, 0x69, 0x4b, 0x76, 0x50, 0x69, 0x59, 0x51, 0x65, 0x49, - 0x6f, 0x36, 0x44, 0x48, 0x67, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, - 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x65, 0x72, 0x3e, 0x32, 0x30, 0x31, 0x33, 0x30, 0x36, 0x32, 0x37, 0x30, 0x30, 0x3c, 0x2f, - 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x3e, 0x0a, 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x63, - 0x65, 0x72, 0x74, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x3c, 0x2f, - 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x70, 0x6b, - 0x77, 0x5a, 0x30, 0x72, 0x6a, 0x6b, 0x76, 0x31, 0x6d, 0x61, 0x61, 0x4f, 0x55, 0x30, 0x43, 0x4d, - 0x4e, 0x68, 0x6b, 0x66, 0x6b, 0x47, 0x38, 0x52, 0x59, 0x43, 0x48, 0x50, 0x32, 0x76, 0x52, 0x76, - 0x75, 0x74, 0x78, 0x37, 0x52, 0x58, 0x48, 0x56, 0x51, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, - 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x63, 0x65, 0x72, 0x74, 0x73, 0x54, - 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, - 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x4c, 0x71, 0x4e, 0x41, 0x52, 0x47, 0x44, - 0x62, 0x54, 0x31, 0x45, 0x38, 0x42, 0x69, 0x64, 0x4f, 0x41, 0x48, 0x73, 0x6c, 0x4e, 0x52, 0x4f, - 0x61, 0x59, 0x63, 0x53, 0x6f, 0x43, 0x71, 0x72, 0x4e, 0x63, 0x4f, 0x64, 0x31, 0x66, 0x6b, 0x31, - 0x53, 0x75, 0x79, 0x51, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x3c, - 0x2f, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x0a, 0x3c, 0x2f, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3e, 0x0a -}; -static void test_OTA_PKI() -{ - CFDataRef signed_plist_data = NULL; - isnt(signed_plist_data = CFDataCreate(kCFAllocatorDefault, kSignedPList, sizeof(kSignedPList)), - NULL, "create CMS signed message from kSignedPList"); - - SecPolicyRef policy = NULL; - SecTrustRef trustRef = NULL; - CFDataRef payload = NULL; - isnt(policy = SecPolicyCreateOTAPKISigner(), NULL, "create the OTAPKISigner policy"); - ok_status(SecCMSVerifyCopyDataAndAttributes(signed_plist_data, NULL, policy, &trustRef, &payload, NULL)); - isnt(payload, NULL, "payload from the CMS message (plist)"); - isnt(trustRef, NULL, "trustRef from the CMS message (plist)"); - - CFDataRef apple_pki_settings_root_certificate_authority_cert_data = NULL; - isnt(apple_pki_settings_root_certificate_authority_cert_data = CFDataCreate(kCFAllocatorDefault, kApplePKISettingsRootCACert, sizeof(kApplePKISettingsRootCACert)), - NULL, "Get the Apple PKI Settings Root Certification Authority Cert Data"); - - SecCertificateRef apple_pki_settings_root_certificate_authority_cert = NULL; - isnt(apple_pki_settings_root_certificate_authority_cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, - kApplePKISettingsRootCACert, sizeof(kApplePKISettingsRootCACert)), - NULL, "Get the Apple PKI Settings Root Certification Authority Cert"); - - CFArrayRef anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&apple_pki_settings_root_certificate_authority_cert, 1, &kCFTypeArrayCallBacks); - CFReleaseNull(apple_pki_settings_root_certificate_authority_cert); - apple_pki_settings_root_certificate_authority_cert = NULL; - - SecTrustSetAnchorCertificates(trustRef, anchors); - - SecTrustResultType trust_result = kSecTrustResultRecoverableTrustFailure; - - ok_status(SecTrustEvaluate(trustRef, &trust_result), "Evaluate trust of the CMS message (plist)"); - - is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultRecoverableTrustFailure (plist)"); - - CFPropertyListFormat plist_format; - CFErrorRef error = NULL; - CFPropertyListRef propertyRef = NULL; - isnt(propertyRef = CFPropertyListCreateWithData(kCFAllocatorDefault, payload, 0, &plist_format, &error), - NULL, "create Plist object from the payload"); - is(error, NULL, "error returned from CFPropertyListCreateWithData (payload plist)"); - - CFDataRef base_plist_data = NULL; - isnt(base_plist_data = CFDataCreate(kCFAllocatorDefault, kBasePList, sizeof(kBasePList)), - NULL, "create base plist data object"); - - CFPropertyListRef base_propertyRef = NULL; - isnt(base_propertyRef = CFPropertyListCreateWithData(kCFAllocatorDefault, base_plist_data, 0, &plist_format, &error), - NULL, "create base Plist object from the payload"); - is(error, NULL, "error returned from CFPropertyListCreateWithData (base plist)"); - - ok(CFEqual(base_propertyRef, propertyRef)); - - CFReleaseSafe(signed_plist_data); - - CFReleaseSafe(trustRef); - CFReleaseSafe(payload); - CFReleaseSafe(propertyRef); - CFReleaseSafe(base_plist_data); - CFReleaseSafe(base_propertyRef); - - // Now do this same test with a 'real' manifest file - CFDataRef signed_manifest_data = NULL; - isnt(signed_manifest_data = CFDataCreate(kCFAllocatorDefault, kSignedManifestData, sizeof(kSignedManifestData)), - NULL, "create CMS signed message from kSignedManifestData"); - - trustRef = NULL; - payload = NULL; - - ok_status(SecCMSVerifyCopyDataAndAttributes(signed_manifest_data, NULL, policy, &trustRef, &payload, NULL)); - CFReleaseSafe(signed_manifest_data); - isnt(payload, NULL, "payload from the CMS message (manifest)"); - isnt(trustRef, NULL, "trustRef from the CMS message (manifest)"); - SecTrustSetAnchorCertificates(trustRef, anchors); - trust_result = kSecTrustResultRecoverableTrustFailure; - - ok_status(SecTrustEvaluate(trustRef, &trust_result), "Evaluate trust of the CMS message (plist)"); - - is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultRecoverableTrustFailure (plist)"); - - CFPropertyListRef manifestRef = NULL; - - isnt(manifestRef = CFPropertyListCreateWithData(kCFAllocatorDefault, payload, 0, &plist_format, &error), - NULL, "create manifest plist object from the payload"); - is(error, NULL, "error returned from CFPropertyListCreateWithData (manifest plist)"); - - CFDataRef base_manifest_data = NULL; - isnt(base_manifest_data = CFDataCreate(kCFAllocatorDefault, kBaseManifestData, sizeof(kBaseManifestData)), - NULL, "create base manifest data object"); - - CFPropertyListRef base_manifestRef = NULL; - isnt(base_manifestRef = CFPropertyListCreateWithData(kCFAllocatorDefault, base_manifest_data, 0, &plist_format, &error), - NULL, "create base manifest object from the payload"); - is(error, NULL, "error returned from CFPropertyListCreateWithData (manifest plist)"); - - ok(CFEqual(base_manifestRef, manifestRef)); - - CFReleaseSafe(policy); - CFReleaseSafe(trustRef); - CFReleaseSafe(payload); - CFReleaseSafe(manifestRef); - CFReleaseSafe(base_manifest_data); - CFReleaseSafe(base_manifestRef); - CFReleaseSafe(anchors); - CFReleaseSafe(apple_pki_settings_root_certificate_authority_cert_data); - -} - -static void tests(void) -{ - test_OTA_PKI(); -} - -int si_74_OTA_PKI_Signer(int argc, char *const *argv) -{ - -//#if defined(NO_SERVER) && NO_SERVER == 1 - plan_tests(27); - - tests(); -//#endif - - return 0; -} - diff --git a/OSX/sec/Security/Regressions/secitem/si-82-token-ag.c b/OSX/sec/Security/Regressions/secitem/si-82-token-ag.c index 1863bf1f..0ec84b4c 100644 --- a/OSX/sec/Security/Regressions/secitem/si-82-token-ag.c +++ b/OSX/sec/Security/Regressions/secitem/si-82-token-ag.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "Security_regressions.h" @@ -20,7 +21,11 @@ static void tests(void) { CFDictionaryAddValue(dict, kSecAttrAccessGroup, kSecAttrAccessGroupToken); is_status(SecItemAdd(dict, NULL), errSecMissingEntitlement); - is_status(SecItemCopyMatching(dict, NULL), errSecItemNotFound); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + is_status(SecItemCopyMatching(dict, NULL), errSecItemNotFound); + } else { + is_status(SecItemCopyMatching(dict, NULL), errSecMissingEntitlement); + } CFRelease(dict); } diff --git a/OSX/sec/Security/Regressions/secitem/si-83-seccertificate-sighashalg.c b/OSX/sec/Security/Regressions/secitem/si-83-seccertificate-sighashalg.c deleted file mode 100644 index bbbf794b..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-83-seccertificate-sighashalg.c +++ /dev/null @@ -1,642 +0,0 @@ -/* - * si-83-seccertificate-sighashalg.c - * Security - * - * Copyright (c) 2015 Apple Inc. All Rights Reserved. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -/* prototypes */ -int si_83_seccertificate_sighashalg(int argc, char *const *argv); - -/* test certs */ -static const UInt8 RSA_MD2[]={ - 0x30,0x82,0x02,0x3D,0x30,0x82,0x01,0xA6,0x02,0x11,0x00,0xCD,0xBA,0x7F,0x56,0xF0, - 0xDF,0xE4,0xBC,0x54,0xFE,0x22,0xAC,0xB3,0x72,0xAA,0x55,0x30,0x0D,0x06,0x09,0x2A, - 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02,0x05,0x00,0x30,0x5F,0x31,0x0B,0x30,0x09, - 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55, - 0x04,0x0A,0x13,0x0E,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x2C,0x20,0x49,0x6E, - 0x63,0x2E,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,0x0B,0x13,0x2E,0x43,0x6C,0x61, - 0x73,0x73,0x20,0x31,0x20,0x50,0x75,0x62,0x6C,0x69,0x63,0x20,0x50,0x72,0x69,0x6D, - 0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, - 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x39, - 0x36,0x30,0x31,0x32,0x39,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x38, - 0x30,0x38,0x30,0x31,0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x5F,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03, - 0x55,0x04,0x0A,0x13,0x0E,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x2C,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,0x0B,0x13,0x2E,0x43,0x6C, - 0x61,0x73,0x73,0x20,0x31,0x20,0x50,0x75,0x62,0x6C,0x69,0x63,0x20,0x50,0x72,0x69, - 0x6D,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, - 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x81,0x9F,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81, - 0x8D,0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xE5,0x19,0xBF,0x6D,0xA3,0x56,0x61, - 0x2D,0x99,0x48,0x71,0xF6,0x67,0xDE,0xB9,0x8D,0xEB,0xB7,0x9E,0x86,0x80,0x0A,0x91, - 0x0E,0xFA,0x38,0x25,0xAF,0x46,0x88,0x82,0xE5,0x73,0xA8,0xA0,0x9B,0x24,0x5D,0x0D, - 0x1F,0xCC,0x65,0x6E,0x0C,0xB0,0xD0,0x56,0x84,0x18,0x87,0x9A,0x06,0x9B,0x10,0xA1, - 0x73,0xDF,0xB4,0x58,0x39,0x6B,0x6E,0xC1,0xF6,0x15,0xD5,0xA8,0xA8,0x3F,0xAA,0x12, - 0x06,0x8D,0x31,0xAC,0x7F,0xB0,0x34,0xD7,0x8F,0x34,0x67,0x88,0x09,0xCD,0x14,0x11, - 0xE2,0x4E,0x45,0x56,0x69,0x1F,0x78,0x02,0x80,0xDA,0xDC,0x47,0x91,0x29,0xBB,0x36, - 0xC9,0x63,0x5C,0xC5,0xE0,0xD7,0x2D,0x87,0x7B,0xA1,0xB7,0x32,0xB0,0x7B,0x30,0xBA, - 0x2A,0x2F,0x31,0xAA,0xEE,0xA3,0x67,0xDA,0xDB,0x02,0x03,0x01,0x00,0x01,0x30,0x0D, - 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02,0x05,0x00,0x03,0x81,0x81, - 0x00,0x4C,0x3F,0xB8,0x8B,0xC6,0x68,0xDF,0xEE,0x43,0x33,0x0E,0x5D,0xE9,0xA6,0xCB, - 0x07,0x84,0x4D,0x7A,0x33,0xFF,0x92,0x1B,0xF4,0x36,0xAD,0xD8,0x95,0x22,0x36,0x68, - 0x11,0x6C,0x7C,0x42,0xCC,0xF3,0x9C,0x2E,0xC4,0x07,0x3F,0x14,0xB0,0x0F,0x4F,0xFF, - 0x90,0x92,0x76,0xF9,0xE2,0xBC,0x4A,0xE9,0x8F,0xCD,0xA0,0x80,0x0A,0xF7,0xC5,0x29, - 0xF1,0x82,0x22,0x5D,0xB8,0xB1,0xDD,0x81,0x23,0xA3,0x7B,0x25,0x15,0x46,0x30,0x79, - 0x16,0xF8,0xEA,0x05,0x4B,0x94,0x7F,0x1D,0xC2,0x1C,0xC8,0xE3,0xB7,0xF4,0x10,0x40, - 0x3C,0x13,0xC3,0x5F,0x1F,0x53,0xE8,0x48,0xE4,0x86,0xB4,0x7B,0xA1,0x35,0xB0,0x7B, - 0x25,0xBA,0xB8,0xD3,0x8E,0xAB,0x3F,0x38,0x9D,0x00,0x34,0x00,0x98,0xF3,0xD1,0x71, - 0x94, -}; - -static const UInt8 RSA_MD5[]={ - 0x30,0x82,0x02,0x5A,0x30,0x82,0x01,0xC3,0x02,0x02,0x01,0xA5,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,0x05,0x00,0x30,0x75,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x18,0x30,0x16,0x06,0x03, - 0x55,0x04,0x0A,0x13,0x0F,0x47,0x54,0x45,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61, - 0x74,0x69,0x6F,0x6E,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x0B,0x13,0x1E,0x47, - 0x54,0x45,0x20,0x43,0x79,0x62,0x65,0x72,0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x6F, - 0x6C,0x75,0x74,0x69,0x6F,0x6E,0x73,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x23,0x30, - 0x21,0x06,0x03,0x55,0x04,0x03,0x13,0x1A,0x47,0x54,0x45,0x20,0x43,0x79,0x62,0x65, - 0x72,0x54,0x72,0x75,0x73,0x74,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F, - 0x6F,0x74,0x30,0x1E,0x17,0x0D,0x39,0x38,0x30,0x38,0x31,0x33,0x30,0x30,0x32,0x39, - 0x30,0x30,0x5A,0x17,0x0D,0x31,0x38,0x30,0x38,0x31,0x33,0x32,0x33,0x35,0x39,0x30, - 0x30,0x5A,0x30,0x75,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, - 0x53,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04,0x0A,0x13,0x0F,0x47,0x54,0x45,0x20, - 0x43,0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x69,0x6F,0x6E,0x31,0x27,0x30,0x25,0x06, - 0x03,0x55,0x04,0x0B,0x13,0x1E,0x47,0x54,0x45,0x20,0x43,0x79,0x62,0x65,0x72,0x54, - 0x72,0x75,0x73,0x74,0x20,0x53,0x6F,0x6C,0x75,0x74,0x69,0x6F,0x6E,0x73,0x2C,0x20, - 0x49,0x6E,0x63,0x2E,0x31,0x23,0x30,0x21,0x06,0x03,0x55,0x04,0x03,0x13,0x1A,0x47, - 0x54,0x45,0x20,0x43,0x79,0x62,0x65,0x72,0x54,0x72,0x75,0x73,0x74,0x20,0x47,0x6C, - 0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F,0x6F,0x74,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30, - 0x81,0x89,0x02,0x81,0x81,0x00,0x95,0x0F,0xA0,0xB6,0xF0,0x50,0x9C,0xE8,0x7A,0xC7, - 0x88,0xCD,0xDD,0x17,0x0E,0x2E,0xB0,0x94,0xD0,0x1B,0x3D,0x0E,0xF6,0x94,0xC0,0x8A, - 0x94,0xC7,0x06,0xC8,0x90,0x97,0xC8,0xB8,0x64,0x1A,0x7A,0x7E,0x6C,0x3C,0x53,0xE1, - 0x37,0x28,0x73,0x60,0x7F,0xB2,0x97,0x53,0x07,0x9F,0x53,0xF9,0x6D,0x58,0x94,0xD2, - 0xAF,0x8D,0x6D,0x88,0x67,0x80,0xE6,0xED,0xB2,0x95,0xCF,0x72,0x31,0xCA,0xA5,0x1C, - 0x72,0xBA,0x5C,0x02,0xE7,0x64,0x42,0xE7,0xF9,0xA9,0x2C,0xD6,0x3A,0x0D,0xAC,0x8D, - 0x42,0xAA,0x24,0x01,0x39,0xE6,0x9C,0x3F,0x01,0x85,0x57,0x0D,0x58,0x87,0x45,0xF8, - 0xD3,0x85,0xAA,0x93,0x69,0x26,0x85,0x70,0x48,0x80,0x3F,0x12,0x15,0xC7,0x79,0xB4, - 0x1F,0x05,0x2F,0x3B,0x62,0x99,0x02,0x03,0x01,0x00,0x01,0x30,0x0D,0x06,0x09,0x2A, - 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,0x05,0x00,0x03,0x81,0x81,0x00,0x6D,0xEB, - 0x1B,0x09,0xE9,0x5E,0xD9,0x51,0xDB,0x67,0x22,0x61,0xA4,0x2A,0x3C,0x48,0x77,0xE3, - 0xA0,0x7C,0xA6,0xDE,0x73,0xA2,0x14,0x03,0x85,0x3D,0xFB,0xAB,0x0E,0x30,0xC5,0x83, - 0x16,0x33,0x81,0x13,0x08,0x9E,0x7B,0x34,0x4E,0xDF,0x40,0xC8,0x74,0xD7,0xB9,0x7D, - 0xDC,0xF4,0x76,0x55,0x7D,0x9B,0x63,0x54,0x18,0xE9,0xF0,0xEA,0xF3,0x5C,0xB1,0xD9, - 0x8B,0x42,0x1E,0xB9,0xC0,0x95,0x4E,0xBA,0xFA,0xD5,0xE2,0x7C,0xF5,0x68,0x61,0xBF, - 0x8E,0xEC,0x05,0x97,0x5F,0x5B,0xB0,0xD7,0xA3,0x85,0x34,0xC4,0x24,0xA7,0x0D,0x0F, - 0x95,0x93,0xEF,0xCB,0x94,0xD8,0x9E,0x1F,0x9D,0x5C,0x85,0x6D,0xC7,0xAA,0xAE,0x4F, - 0x1F,0x22,0xB5,0xCD,0x95,0xAD,0xBA,0xA7,0xCC,0xF9,0xAB,0x0B,0x7A,0x7F, -}; - -static const UInt8 RSA_SHA1[]={ - 0x30,0x82,0x04,0xBB,0x30,0x82,0x03,0xA3,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x02, - 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30, - 0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70, - 0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, - 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06, - 0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74, - 0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x36,0x30,0x34,0x32,0x35,0x32,0x31,0x34, - 0x30,0x33,0x36,0x5A,0x17,0x0D,0x33,0x35,0x30,0x32,0x30,0x39,0x32,0x31,0x34,0x30, - 0x33,0x36,0x5A,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, - 0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70, - 0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, - 0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, - 0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, - 0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20, - 0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A, - 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30, - 0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xE4,0x91,0xA9,0x09,0x1F,0x91,0xDB,0x1E, - 0x47,0x50,0xEB,0x05,0xED,0x5E,0x79,0x84,0x2D,0xEB,0x36,0xA2,0x57,0x4C,0x55,0xEC, - 0x8B,0x19,0x89,0xDE,0xF9,0x4B,0x6C,0xF5,0x07,0xAB,0x22,0x30,0x02,0xE8,0x18,0x3E, - 0xF8,0x50,0x09,0xD3,0x7F,0x41,0xA8,0x98,0xF9,0xD1,0xCA,0x66,0x9C,0x24,0x6B,0x11, - 0xD0,0xA3,0xBB,0xE4,0x1B,0x2A,0xC3,0x1F,0x95,0x9E,0x7A,0x0C,0xA4,0x47,0x8B,0x5B, - 0xD4,0x16,0x37,0x33,0xCB,0xC4,0x0F,0x4D,0xCE,0x14,0x69,0xD1,0xC9,0x19,0x72,0xF5, - 0x5D,0x0E,0xD5,0x7F,0x5F,0x9B,0xF2,0x25,0x03,0xBA,0x55,0x8F,0x4D,0x5D,0x0D,0xF1, - 0x64,0x35,0x23,0x15,0x4B,0x15,0x59,0x1D,0xB3,0x94,0xF7,0xF6,0x9C,0x9E,0xCF,0x50, - 0xBA,0xC1,0x58,0x50,0x67,0x8F,0x08,0xB4,0x20,0xF7,0xCB,0xAC,0x2C,0x20,0x6F,0x70, - 0xB6,0x3F,0x01,0x30,0x8C,0xB7,0x43,0xCF,0x0F,0x9D,0x3D,0xF3,0x2B,0x49,0x28,0x1A, - 0xC8,0xFE,0xCE,0xB5,0xB9,0x0E,0xD9,0x5E,0x1C,0xD6,0xCB,0x3D,0xB5,0x3A,0xAD,0xF4, - 0x0F,0x0E,0x00,0x92,0x0B,0xB1,0x21,0x16,0x2E,0x74,0xD5,0x3C,0x0D,0xDB,0x62,0x16, - 0xAB,0xA3,0x71,0x92,0x47,0x53,0x55,0xC1,0xAF,0x2F,0x41,0xB3,0xF8,0xFB,0xE3,0x70, - 0xCD,0xE6,0xA3,0x4C,0x45,0x7E,0x1F,0x4C,0x6B,0x50,0x96,0x41,0x89,0xC4,0x74,0x62, - 0x0B,0x10,0x83,0x41,0x87,0x33,0x8A,0x81,0xB1,0x30,0x58,0xEC,0x5A,0x04,0x32,0x8C, - 0x68,0xB3,0x8F,0x1D,0xDE,0x65,0x73,0xFF,0x67,0x5E,0x65,0xBC,0x49,0xD8,0x76,0x9F, - 0x33,0x14,0x65,0xA1,0x77,0x94,0xC9,0x2D,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01, - 0x7A,0x30,0x82,0x01,0x76,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, - 0x04,0x03,0x02,0x01,0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, - 0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, - 0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6,0xF7, - 0x47,0x4D,0x7F,0x08,0x5E,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, - 0x80,0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6, - 0xF7,0x47,0x4D,0x7F,0x08,0x5E,0x30,0x82,0x01,0x11,0x06,0x03,0x55,0x1D,0x20,0x04, - 0x82,0x01,0x08,0x30,0x82,0x01,0x04,0x30,0x82,0x01,0x00,0x06,0x09,0x2A,0x86,0x48, - 0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF2,0x30,0x2A,0x06,0x08,0x2B,0x06,0x01, - 0x05,0x05,0x07,0x02,0x01,0x16,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77, - 0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70, - 0x6C,0x65,0x63,0x61,0x2F,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x02,0x02,0x30,0x81,0xB6,0x1A,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65, - 0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69, - 0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72,0x74, - 0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74, - 0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65,0x6E, - 0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61,0x6E, - 0x64,0x61,0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20,0x63, - 0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65, - 0x2C,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70,0x6F, - 0x6C,0x69,0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69, - 0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20, - 0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x0D,0x06,0x09,0x2A, - 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x5C, - 0x36,0x99,0x4C,0x2D,0x78,0xB7,0xED,0x8C,0x9B,0xDC,0xF3,0x77,0x9B,0xF2,0x76,0xD2, - 0x77,0x30,0x4F,0xC1,0x1F,0x85,0x83,0x85,0x1B,0x99,0x3D,0x47,0x37,0xF2,0xA9,0x9B, - 0x40,0x8E,0x2C,0xD4,0xB1,0x90,0x12,0xD8,0xBE,0xF4,0x73,0x9B,0xEE,0xD2,0x64,0x0F, - 0xCB,0x79,0x4F,0x34,0xD8,0xA2,0x3E,0xF9,0x78,0xFF,0x6B,0xC8,0x07,0xEC,0x7D,0x39, - 0x83,0x8B,0x53,0x20,0xD3,0x38,0xC4,0xB1,0xBF,0x9A,0x4F,0x0A,0x6B,0xFF,0x2B,0xFC, - 0x59,0xA7,0x05,0x09,0x7C,0x17,0x40,0x56,0x11,0x1E,0x74,0xD3,0xB7,0x8B,0x23,0x3B, - 0x47,0xA3,0xD5,0x6F,0x24,0xE2,0xEB,0xD1,0xB7,0x70,0xDF,0x0F,0x45,0xE1,0x27,0xCA, - 0xF1,0x6D,0x78,0xED,0xE7,0xB5,0x17,0x17,0xA8,0xDC,0x7E,0x22,0x35,0xCA,0x25,0xD5, - 0xD9,0x0F,0xD6,0x6B,0xD4,0xA2,0x24,0x23,0x11,0xF7,0xA1,0xAC,0x8F,0x73,0x81,0x60, - 0xC6,0x1B,0x5B,0x09,0x2F,0x92,0xB2,0xF8,0x44,0x48,0xF0,0x60,0x38,0x9E,0x15,0xF5, - 0x3D,0x26,0x67,0x20,0x8A,0x33,0x6A,0xF7,0x0D,0x82,0xCF,0xDE,0xEB,0xA3,0x2F,0xF9, - 0x53,0x6A,0x5B,0x64,0xC0,0x63,0x33,0x77,0xF7,0x3A,0x07,0x2C,0x56,0xEB,0xDA,0x0F, - 0x21,0x0E,0xDA,0xBA,0x73,0x19,0x4F,0xB5,0xD9,0x36,0x7F,0xC1,0x87,0x55,0xD9,0xA7, - 0x99,0xB9,0x32,0x42,0xFB,0xD8,0xD5,0x71,0x9E,0x7E,0xA1,0x52,0xB7,0x1B,0xBD,0x93, - 0x42,0x24,0x12,0x2A,0xC7,0x0F,0x1D,0xB6,0x4D,0x9C,0x5E,0x63,0xC8,0x4B,0x80,0x17, - 0x50,0xAA,0x8A,0xD5,0xDA,0xE4,0xFC,0xD0,0x09,0x07,0x37,0xB0,0x75,0x75,0x21, -}; - -static const UInt8 RSA_SHA256[]={ - 0x30,0x82,0x03,0x5F,0x30,0x82,0x02,0x47,0xA0,0x03,0x02,0x01,0x02,0x02,0x0B,0x04, - 0x00,0x00,0x00,0x00,0x01,0x21,0x58,0x53,0x08,0xA2,0x30,0x0D,0x06,0x09,0x2A,0x86, - 0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x4C,0x31,0x20,0x30,0x1E,0x06, - 0x03,0x55,0x04,0x0B,0x13,0x17,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E, - 0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x52,0x33,0x31,0x13,0x30, - 0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69, - 0x67,0x6E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F, - 0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x30,0x1E,0x17,0x0D,0x30,0x39,0x30,0x33,0x31, - 0x38,0x31,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x39,0x30,0x33,0x31,0x38, - 0x31,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x4C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x17,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x20,0x52, - 0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x52,0x33,0x31,0x13,0x30,0x11,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E, - 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61, - 0x6C,0x53,0x69,0x67,0x6E,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, - 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, - 0x0A,0x02,0x82,0x01,0x01,0x00,0xCC,0x25,0x76,0x90,0x79,0x06,0x78,0x22,0x16,0xF5, - 0xC0,0x83,0xB6,0x84,0xCA,0x28,0x9E,0xFD,0x05,0x76,0x11,0xC5,0xAD,0x88,0x72,0xFC, - 0x46,0x02,0x43,0xC7,0xB2,0x8A,0x9D,0x04,0x5F,0x24,0xCB,0x2E,0x4B,0xE1,0x60,0x82, - 0x46,0xE1,0x52,0xAB,0x0C,0x81,0x47,0x70,0x6C,0xDD,0x64,0xD1,0xEB,0xF5,0x2C,0xA3, - 0x0F,0x82,0x3D,0x0C,0x2B,0xAE,0x97,0xD7,0xB6,0x14,0x86,0x10,0x79,0xBB,0x3B,0x13, - 0x80,0x77,0x8C,0x08,0xE1,0x49,0xD2,0x6A,0x62,0x2F,0x1F,0x5E,0xFA,0x96,0x68,0xDF, - 0x89,0x27,0x95,0x38,0x9F,0x06,0xD7,0x3E,0xC9,0xCB,0x26,0x59,0x0D,0x73,0xDE,0xB0, - 0xC8,0xE9,0x26,0x0E,0x83,0x15,0xC6,0xEF,0x5B,0x8B,0xD2,0x04,0x60,0xCA,0x49,0xA6, - 0x28,0xF6,0x69,0x3B,0xF6,0xCB,0xC8,0x28,0x91,0xE5,0x9D,0x8A,0x61,0x57,0x37,0xAC, - 0x74,0x14,0xDC,0x74,0xE0,0x3A,0xEE,0x72,0x2F,0x2E,0x9C,0xFB,0xD0,0xBB,0xBF,0xF5, - 0x3D,0x00,0xE1,0x06,0x33,0xE8,0x82,0x2B,0xAE,0x53,0xA6,0x3A,0x16,0x73,0x8C,0xDD, - 0x41,0x0E,0x20,0x3A,0xC0,0xB4,0xA7,0xA1,0xE9,0xB2,0x4F,0x90,0x2E,0x32,0x60,0xE9, - 0x57,0xCB,0xB9,0x04,0x92,0x68,0x68,0xE5,0x38,0x26,0x60,0x75,0xB2,0x9F,0x77,0xFF, - 0x91,0x14,0xEF,0xAE,0x20,0x49,0xFC,0xAD,0x40,0x15,0x48,0xD1,0x02,0x31,0x61,0x19, - 0x5E,0xB8,0x97,0xEF,0xAD,0x77,0xB7,0x64,0x9A,0x7A,0xBF,0x5F,0xC1,0x13,0xEF,0x9B, - 0x62,0xFB,0x0D,0x6C,0xE0,0x54,0x69,0x16,0xA9,0x03,0xDA,0x6E,0xE9,0x83,0x93,0x71, - 0x76,0xC6,0x69,0x85,0x82,0x17,0x02,0x03,0x01,0x00,0x01,0xA3,0x42,0x30,0x40,0x30, - 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30, - 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x8F,0xF0,0x4B,0x7F,0xA8, - 0x2E,0x45,0x24,0xAE,0x4D,0x50,0xFA,0x63,0x9A,0x8B,0xDE,0xE2,0xDD,0x1B,0xBC,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, - 0x01,0x01,0x00,0x4B,0x40,0xDB,0xC0,0x50,0xAA,0xFE,0xC8,0x0C,0xEF,0xF7,0x96,0x54, - 0x45,0x49,0xBB,0x96,0x00,0x09,0x41,0xAC,0xB3,0x13,0x86,0x86,0x28,0x07,0x33,0xCA, - 0x6B,0xE6,0x74,0xB9,0xBA,0x00,0x2D,0xAE,0xA4,0x0A,0xD3,0xF5,0xF1,0xF1,0x0F,0x8A, - 0xBF,0x73,0x67,0x4A,0x83,0xC7,0x44,0x7B,0x78,0xE0,0xAF,0x6E,0x6C,0x6F,0x03,0x29, - 0x8E,0x33,0x39,0x45,0xC3,0x8E,0xE4,0xB9,0x57,0x6C,0xAA,0xFC,0x12,0x96,0xEC,0x53, - 0xC6,0x2D,0xE4,0x24,0x6C,0xB9,0x94,0x63,0xFB,0xDC,0x53,0x68,0x67,0x56,0x3E,0x83, - 0xB8,0xCF,0x35,0x21,0xC3,0xC9,0x68,0xFE,0xCE,0xDA,0xC2,0x53,0xAA,0xCC,0x90,0x8A, - 0xE9,0xF0,0x5D,0x46,0x8C,0x95,0xDD,0x7A,0x58,0x28,0x1A,0x2F,0x1D,0xDE,0xCD,0x00, - 0x37,0x41,0x8F,0xED,0x44,0x6D,0xD7,0x53,0x28,0x97,0x7E,0xF3,0x67,0x04,0x1E,0x15, - 0xD7,0x8A,0x96,0xB4,0xD3,0xDE,0x4C,0x27,0xA4,0x4C,0x1B,0x73,0x73,0x76,0xF4,0x17, - 0x99,0xC2,0x1F,0x7A,0x0E,0xE3,0x2D,0x08,0xAD,0x0A,0x1C,0x2C,0xFF,0x3C,0xAB,0x55, - 0x0E,0x0F,0x91,0x7E,0x36,0xEB,0xC3,0x57,0x49,0xBE,0xE1,0x2E,0x2D,0x7C,0x60,0x8B, - 0xC3,0x41,0x51,0x13,0x23,0x9D,0xCE,0xF7,0x32,0x6B,0x94,0x01,0xA8,0x99,0xE7,0x2C, - 0x33,0x1F,0x3A,0x3B,0x25,0xD2,0x86,0x40,0xCE,0x3B,0x2C,0x86,0x78,0xC9,0x61,0x2F, - 0x14,0xBA,0xEE,0xDB,0x55,0x6F,0xDF,0x84,0xEE,0x05,0x09,0x4D,0xBD,0x28,0xD8,0x72, - 0xCE,0xD3,0x62,0x50,0x65,0x1E,0xEB,0x92,0x97,0x83,0x31,0xD9,0xB3,0xB5,0xCA,0x47, - 0x58,0x3F,0x5F, -}; - -static const UInt8 RSA_SHA512[]={ - 0x30,0x82,0x05,0xD3,0x30,0x82,0x03,0xBB,0xA0,0x03,0x02,0x01,0x02,0x02,0x15,0x00, - 0xB8,0x59,0x14,0x71,0x3F,0x57,0xDF,0x8F,0x31,0xC0,0x33,0x3D,0xD2,0xD6,0x19,0x7A, - 0x23,0x17,0xB4,0xEB,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, - 0x0D,0x05,0x00,0x30,0x81,0x80,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, - 0x02,0x50,0x4C,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0A,0x13,0x19,0x55,0x6E, - 0x69,0x7A,0x65,0x74,0x6F,0x20,0x54,0x65,0x63,0x68,0x6E,0x6F,0x6C,0x6F,0x67,0x69, - 0x65,0x73,0x20,0x53,0x2E,0x41,0x2E,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x0B, - 0x13,0x1E,0x43,0x65,0x72,0x74,0x75,0x6D,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69, - 0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79, - 0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x03,0x13,0x1B,0x43,0x65,0x72,0x74,0x75, - 0x6D,0x20,0x54,0x72,0x75,0x73,0x74,0x65,0x64,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72, - 0x6B,0x20,0x43,0x41,0x20,0x32,0x30,0x1E,0x17,0x0D,0x31,0x31,0x31,0x30,0x30,0x36, - 0x30,0x38,0x33,0x39,0x35,0x36,0x5A,0x17,0x0D,0x34,0x36,0x31,0x30,0x30,0x36,0x30, - 0x38,0x33,0x39,0x35,0x36,0x5A,0x30,0x81,0x80,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x50,0x4C,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x19,0x55,0x6E,0x69,0x7A,0x65,0x74,0x6F,0x20,0x54,0x65,0x63,0x68,0x6E,0x6F,0x6C, - 0x6F,0x67,0x69,0x65,0x73,0x20,0x53,0x2E,0x41,0x2E,0x31,0x27,0x30,0x25,0x06,0x03, - 0x55,0x04,0x0B,0x13,0x1E,0x43,0x65,0x72,0x74,0x75,0x6D,0x20,0x43,0x65,0x72,0x74, - 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72, - 0x69,0x74,0x79,0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x03,0x13,0x1B,0x43,0x65, - 0x72,0x74,0x75,0x6D,0x20,0x54,0x72,0x75,0x73,0x74,0x65,0x64,0x20,0x4E,0x65,0x74, - 0x77,0x6F,0x72,0x6B,0x20,0x43,0x41,0x20,0x32,0x30,0x82,0x02,0x22,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x02,0x0F, - 0x00,0x30,0x82,0x02,0x0A,0x02,0x82,0x02,0x01,0x00,0xBD,0xF9,0x78,0xF8,0xE6,0xD5, - 0x80,0x0C,0x64,0x9D,0x86,0x1B,0x96,0x64,0x67,0x3F,0x22,0x3A,0x1E,0x75,0x01,0x7D, - 0xEF,0xFB,0x5C,0x67,0x8C,0xC9,0xCC,0x5C,0x6B,0xA9,0x91,0xE6,0xB9,0x42,0xE5,0x20, - 0x4B,0x9B,0xDA,0x9B,0x7B,0xB9,0x99,0x5D,0xD9,0x9B,0x80,0x4B,0xD7,0x84,0x40,0x2B, - 0x27,0xD3,0xE8,0xBA,0x30,0xBB,0x3E,0x09,0x1A,0xA7,0x49,0x95,0xEF,0x2B,0x40,0x24, - 0xC2,0x97,0xC7,0xA7,0xEE,0x9B,0x25,0xEF,0xA8,0x0A,0x00,0x97,0x85,0x5A,0xAA,0x9D, - 0xDC,0x29,0xC9,0xE2,0x35,0x07,0xEB,0x70,0x4D,0x4A,0xD6,0xC1,0xB3,0x56,0xB8,0xA1, - 0x41,0x38,0x9B,0xD1,0xFB,0x31,0x7F,0x8F,0xE0,0x5F,0xE1,0xB1,0x3F,0x0F,0x8E,0x16, - 0x49,0x60,0xD7,0x06,0x8D,0x18,0xF9,0xAA,0x26,0x10,0xAB,0x2A,0xD3,0xD0,0xD1,0x67, - 0x8D,0x1B,0x46,0xBE,0x47,0x30,0xD5,0x2E,0x72,0xD1,0xC5,0x63,0xDA,0xE7,0x63,0x79, - 0x44,0x7E,0x4B,0x63,0x24,0x89,0x86,0x2E,0x34,0x3F,0x29,0x4C,0x52,0x8B,0x2A,0xA7, - 0xC0,0xE2,0x91,0x28,0x89,0xB9,0xC0,0x5B,0xF9,0x1D,0xD9,0xE7,0x27,0xAD,0xFF,0x9A, - 0x02,0x97,0xC1,0xC6,0x50,0x92,0x9B,0x02,0x2C,0xBD,0xA9,0xB9,0x34,0x59,0x0A,0xBF, - 0x84,0x4A,0xFF,0xDF,0xFE,0xB3,0x9F,0xEB,0xD9,0x9E,0xE0,0x98,0x23,0xEC,0xA6,0x6B, - 0x77,0x16,0x2A,0xDB,0xCC,0xAD,0x3B,0x1C,0xA4,0x87,0xDC,0x46,0x73,0x5E,0x19,0x62, - 0x68,0x45,0x57,0xE4,0x90,0x82,0x42,0xBB,0x42,0xD6,0xF0,0x61,0xE0,0xC1,0xA3,0x3D, - 0x66,0xA3,0x5D,0xF4,0x18,0xEE,0x88,0xC9,0x8D,0x17,0x45,0x29,0x99,0x32,0x75,0x02, - 0x31,0xEE,0x29,0x26,0xC8,0x6B,0x02,0xE6,0xB5,0x62,0x45,0x7F,0x37,0x15,0x5A,0x23, - 0x68,0x89,0xD4,0x3E,0xDE,0x4E,0x27,0xB0,0xF0,0x40,0x0C,0xBC,0x4D,0x17,0xCB,0x4D, - 0xA2,0xB3,0x1E,0xD0,0x06,0x5A,0xDD,0xF6,0x93,0xCF,0x57,0x75,0x99,0xF5,0xFA,0x86, - 0x1A,0x67,0x78,0xB3,0xBF,0x96,0xFE,0x34,0xDC,0xBD,0xE7,0x52,0x56,0xE5,0xB3,0xE5, - 0x75,0x7B,0xD7,0x41,0x91,0x05,0xDC,0x5D,0x69,0xE3,0x95,0x0D,0x43,0xB9,0xFC,0x83, - 0x96,0x39,0x95,0x7B,0x6C,0x80,0x5A,0x4F,0x13,0x72,0xC6,0xD7,0x7D,0x29,0x7A,0x44, - 0xBA,0x52,0xA4,0x2A,0xD5,0x41,0x46,0x09,0x20,0xFE,0x22,0xA0,0xB6,0x5B,0x30,0x8D, - 0xBC,0x89,0x0C,0xD5,0xD7,0x70,0xF8,0x87,0x52,0xFD,0xDA,0xEF,0xAC,0x51,0x2E,0x07, - 0xB3,0x4E,0xFE,0xD0,0x09,0xDA,0x70,0xEF,0x98,0xFA,0x56,0xE6,0x6D,0xDB,0xB5,0x57, - 0x4B,0xDC,0xE5,0x2C,0x25,0x15,0xC8,0x9E,0x2E,0x78,0x4E,0xF8,0xDA,0x9C,0x9E,0x86, - 0x2C,0xCA,0x57,0xF3,0x1A,0xE5,0xC8,0x92,0x8B,0x1A,0x82,0x96,0x7A,0xC3,0xBC,0x50, - 0x12,0x69,0xD8,0x0E,0x5A,0x46,0x8B,0x3A,0xEB,0x26,0xFA,0x23,0xC9,0xB6,0xB0,0x81, - 0xBE,0x42,0x00,0xA4,0xF8,0xD6,0xFE,0x30,0x2E,0xC7,0xD2,0x46,0xF6,0xE5,0x8E,0x75, - 0xFD,0xF2,0xCC,0xB9,0xD0,0x87,0x5B,0xCC,0x06,0x10,0x60,0xBB,0x83,0x35,0xB7,0x5E, - 0x67,0xDE,0x47,0xEC,0x99,0x48,0xF1,0xA4,0xA1,0x15,0xFE,0xAD,0x8C,0x62,0x8E,0x39, - 0x55,0x4F,0x39,0x16,0xB9,0xB1,0x63,0x9D,0xFF,0xB7,0x02,0x03,0x01,0x00,0x01,0xA3, - 0x42,0x30,0x40,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30, - 0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xB6, - 0xA1,0x54,0x39,0x02,0xC3,0xA0,0x3F,0x8E,0x8A,0xBC,0xFA,0xD4,0xF8,0x1C,0xA6,0xD1, - 0x3A,0x0E,0xFD,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, - 0x02,0x01,0x06,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0D, - 0x05,0x00,0x03,0x82,0x02,0x01,0x00,0x9D,0x53,0xC2,0x81,0x25,0xDC,0x35,0x2C,0xAE, - 0x0A,0xDD,0x5A,0x9B,0x46,0x30,0x56,0xBB,0xD4,0xB4,0x6C,0x4B,0x86,0xE6,0x0A,0xA5, - 0xD2,0x92,0x8A,0x9A,0x8D,0xDC,0x8F,0xB4,0xEE,0x76,0xF4,0x03,0xCB,0xEB,0x9B,0x01, - 0x78,0xAB,0x2A,0x6B,0xB5,0xBA,0x23,0x4E,0x31,0x7C,0xB5,0x2C,0xDD,0x2D,0x69,0x67, - 0x33,0x6E,0x63,0x5D,0x39,0x18,0x12,0xF8,0xA0,0x28,0x53,0x44,0x87,0xAB,0x6A,0xC4, - 0x92,0x96,0x1F,0x2A,0xA2,0x1C,0xBA,0x9D,0xDD,0x27,0xFB,0x52,0x4D,0xB0,0x8F,0x5A, - 0xE8,0xED,0x8D,0xC3,0x68,0xE3,0x92,0xA0,0x26,0x0C,0x87,0x90,0xB0,0x03,0xEA,0x6A, - 0x65,0x28,0x08,0xC4,0x46,0x78,0xE0,0x5B,0xBA,0x0E,0xF0,0x33,0xDC,0x27,0xB6,0x7E, - 0x88,0x3D,0xBD,0x92,0xA4,0x96,0x7E,0x41,0xA8,0x80,0x08,0x7B,0xD6,0x36,0x12,0xBC, - 0x10,0x15,0x9B,0x24,0xBC,0xAB,0xAD,0x7D,0x11,0x89,0x2F,0x31,0xED,0xF8,0xD2,0xCF, - 0x53,0x8E,0xEB,0xB4,0x53,0xA7,0xE7,0x04,0xCA,0x2F,0xA6,0x22,0xC4,0x11,0xDC,0xEB, - 0x98,0xC9,0x22,0x5D,0x41,0x6A,0xDC,0x0A,0x52,0x04,0x5B,0xBC,0x2E,0xA0,0x7D,0xC7, - 0xB6,0x92,0xBB,0x24,0xA0,0xF3,0x37,0xD1,0x2B,0x43,0xA8,0xCC,0xF1,0x68,0x78,0x1A, - 0x7E,0x6F,0x63,0x90,0x7B,0x9F,0x74,0xC8,0x6B,0xD9,0x0B,0x55,0xF6,0x79,0x03,0x3D, - 0x83,0xC7,0x41,0x40,0x92,0xFB,0x76,0x0B,0x37,0x25,0x17,0x3C,0xAF,0x3E,0xFA,0x3C, - 0x5C,0x1B,0x86,0xF9,0x4A,0x0C,0x3F,0x8A,0xC4,0x5E,0x0E,0x98,0xF1,0xAD,0xEE,0xCF, - 0xE0,0xFD,0x21,0x35,0xC7,0x33,0x61,0xCC,0xA2,0x37,0x18,0x43,0x7C,0x33,0xE9,0xAE, - 0x76,0x82,0x82,0x07,0x45,0x48,0x3B,0xC9,0x67,0x6E,0xAD,0xA3,0x85,0xE8,0x96,0x56, - 0xCF,0xBC,0xBB,0xFA,0xAB,0xCB,0xB7,0x57,0x27,0x8D,0x1A,0x2F,0x99,0xF3,0x23,0x33, - 0x34,0x8E,0xCA,0x53,0x63,0xD3,0x57,0x34,0x50,0x4F,0xCF,0x49,0xC1,0x05,0xBA,0xC5, - 0xA8,0x87,0x7B,0xE3,0x86,0x8F,0xFB,0x43,0xA2,0x12,0xE9,0xAC,0x51,0xEC,0x04,0x76, - 0x4C,0xF0,0xFA,0x8F,0xB9,0x31,0x13,0xE9,0x08,0xB7,0x24,0x09,0xF9,0xA0,0xB7,0x07, - 0x36,0x58,0x57,0xCF,0xC4,0xBB,0x7E,0x49,0x66,0x95,0x35,0x04,0xB6,0x77,0x35,0xB8, - 0xA9,0x53,0x29,0x5F,0x92,0x85,0xF8,0x52,0xC4,0x5A,0x4E,0xFD,0x06,0x61,0x39,0xFB, - 0x7D,0xD0,0x76,0x47,0x92,0xCC,0xEC,0x2B,0xBD,0x84,0x6E,0xE6,0x9B,0x45,0xC1,0x7D, - 0x62,0xB1,0x53,0x2D,0x9E,0x75,0xA0,0xE7,0xC9,0x28,0x50,0xD7,0xE5,0xBC,0xA8,0xAA, - 0x07,0x78,0x6A,0xB9,0x74,0xB4,0x60,0xF3,0x84,0x8D,0x03,0xDC,0xAE,0x91,0xDA,0x74, - 0x44,0x0D,0x7B,0x42,0xA9,0x77,0xD6,0x2B,0x7C,0xA1,0xC6,0x6C,0x13,0x53,0x22,0xA9, - 0x12,0x9A,0xA5,0xF9,0x4F,0x28,0x45,0x35,0xB0,0x97,0x4F,0x46,0x65,0x85,0xC5,0xF4, - 0xFD,0x62,0xA2,0xA2,0x6A,0xFC,0x34,0x30,0x06,0x7E,0xDF,0x0C,0xE0,0x73,0x81,0x96, - 0xC9,0x44,0x2A,0xDE,0x1F,0x82,0xEC,0x6C,0x72,0x57,0xAD,0x29,0x64,0xA4,0xF1,0xC6, - 0x29,0x8E,0x35,0x60,0x53,0xCE,0x6B,0xD9,0x02,0xBE,0x39,0x30,0x75,0xE0,0xF7,0x5C, - 0x63,0x6A,0xF0,0x40,0xC1,0x2C,0x8D, -}; - -static const UInt8 ECDSA_SHA1[]={ - 0x30,0x82,0x02,0x40,0x30,0x82,0x01,0xE7,0xA0,0x03,0x02,0x01,0x02,0x02,0x02,0x04, - 0x19,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x30,0x81,0x9B,0x31, - 0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B,0x13,0x0B,0x53,0x41,0x4D,0x50,0x4C,0x45, - 0x20,0x4F,0x4E,0x4C,0x59,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0A,0x13,0x0E, - 0x43,0x65,0x72,0x74,0x69,0x63,0x6F,0x6D,0x20,0x43,0x6F,0x72,0x70,0x2E,0x31,0x10, - 0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x54,0x6F,0x72,0x6F,0x6E,0x74,0x6F, - 0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x04,0x13,0x07,0x4F,0x6E,0x74,0x61,0x72, - 0x69,0x6F,0x31,0x39,0x30,0x37,0x06,0x03,0x55,0x04,0x03,0x13,0x30,0x74,0x6C,0x73, - 0x2E,0x73,0x65,0x63,0x67,0x2E,0x6F,0x72,0x67,0x20,0x45,0x43,0x43,0x20,0x73,0x65, - 0x63,0x70,0x32,0x35,0x36,0x72,0x31,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, - 0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x36, - 0x30,0x35,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x35,0x30, - 0x35,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x81,0x8B,0x31,0x14,0x30, - 0x12,0x06,0x03,0x55,0x04,0x0B,0x13,0x0B,0x53,0x41,0x4D,0x50,0x4C,0x45,0x20,0x4F, - 0x4E,0x4C,0x59,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0A,0x13,0x0E,0x43,0x65, - 0x72,0x74,0x69,0x63,0x6F,0x6D,0x20,0x43,0x6F,0x72,0x70,0x2E,0x31,0x10,0x30,0x0E, - 0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x54,0x6F,0x72,0x6F,0x6E,0x74,0x6F,0x31,0x10, - 0x30,0x0E,0x06,0x03,0x55,0x04,0x04,0x13,0x07,0x4F,0x6E,0x74,0x61,0x72,0x69,0x6F, - 0x31,0x36,0x30,0x34,0x06,0x03,0x55,0x04,0x03,0x13,0x2D,0x74,0x6C,0x73,0x2E,0x73, - 0x65,0x63,0x67,0x2E,0x6F,0x72,0x67,0x20,0x45,0x43,0x43,0x20,0x73,0x65,0x63,0x70, - 0x32,0x35,0x36,0x72,0x31,0x20,0x43,0x6C,0x69,0x65,0x6E,0x74,0x20,0x43,0x65,0x72, - 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86, - 0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03, - 0x42,0x00,0x04,0x36,0x48,0x98,0xF8,0xB3,0xD0,0xC4,0x2E,0xCA,0x99,0x3D,0x14,0xBB, - 0x14,0x24,0xF5,0x89,0x82,0x36,0xE3,0x34,0xB2,0xF5,0x35,0x07,0xD0,0xA8,0xDE,0x14, - 0x84,0xD7,0x78,0xA4,0x62,0x01,0x77,0xEA,0xBD,0xA9,0xA3,0x9F,0x8B,0x48,0x5F,0x3C, - 0x7A,0xA1,0x96,0x40,0xD1,0x2C,0xB6,0xDD,0xEA,0x21,0xF8,0xED,0x29,0x70,0x44,0x80, - 0x49,0x2E,0x77,0xA3,0x2A,0x30,0x28,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, - 0xFF,0x04,0x04,0x03,0x02,0x03,0x88,0x30,0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01, - 0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30, - 0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x03,0x48,0x00,0x30,0x45,0x02, - 0x20,0x45,0xA2,0x99,0x2C,0xE0,0x08,0xB2,0xEE,0x09,0xCD,0x1D,0x51,0x42,0x60,0x3F, - 0x56,0x4D,0x2D,0xA1,0x7D,0xAB,0xD0,0xF5,0x6D,0xF7,0xF0,0xE2,0x23,0x33,0xBC,0xBD, - 0xB3,0x02,0x21,0x00,0xCD,0xFB,0x57,0x1C,0x3A,0x32,0xD1,0xBC,0x67,0xBB,0x0F,0x1D, - 0x12,0xEB,0x63,0x12,0x1F,0x50,0x37,0x67,0x77,0x66,0x2B,0xE1,0x37,0xD4,0x8F,0xDD, - 0xE0,0xAA,0xE4,0x22, -}; - -static const UInt8 ECDSA_SHA256[] = { - 0x30,0x82,0x01,0xE1,0x30,0x82,0x01,0x87,0xA0,0x03,0x02,0x01,0x02,0x02,0x11,0x2A, - 0x38,0xA4,0x1C,0x96,0x0A,0x04,0xDE,0x42,0xB2,0x28,0xA5,0x0B,0xE8,0x34,0x98,0x02, - 0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x50,0x31,0x24, - 0x30,0x22,0x06,0x03,0x55,0x04,0x0B,0x13,0x1B,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53, - 0x69,0x67,0x6E,0x20,0x45,0x43,0x43,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20, - 0x2D,0x20,0x52,0x34,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x47, - 0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x31,0x13,0x30,0x11,0x06,0x03,0x55, - 0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x30,0x1E, - 0x17,0x0D,0x31,0x32,0x31,0x31,0x31,0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17, - 0x0D,0x33,0x38,0x30,0x31,0x31,0x39,0x30,0x33,0x31,0x34,0x30,0x37,0x5A,0x30,0x50, - 0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x0B,0x13,0x1B,0x47,0x6C,0x6F,0x62,0x61, - 0x6C,0x53,0x69,0x67,0x6E,0x20,0x45,0x43,0x43,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, - 0x41,0x20,0x2D,0x20,0x52,0x34,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x31,0x13,0x30,0x11,0x06, - 0x03,0x55,0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E, - 0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A, - 0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xB8,0xC6,0x79,0xD3,0x8F, - 0x6C,0x25,0x0E,0x9F,0x2E,0x39,0x19,0x1C,0x03,0xA4,0xAE,0x9A,0xE5,0x39,0x07,0x09, - 0x16,0xCA,0x63,0xB1,0xB9,0x86,0xF8,0x8A,0x57,0xC1,0x57,0xCE,0x42,0xFA,0x73,0xA1, - 0xF7,0x65,0x42,0xFF,0x1E,0xC1,0x00,0xB2,0x6E,0x73,0x0E,0xFF,0xC7,0x21,0xE5,0x18, - 0xA4,0xAA,0xD9,0x71,0x3F,0xA8,0xD4,0xB9,0xCE,0x8C,0x1D,0xA3,0x42,0x30,0x40,0x30, - 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30, - 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x54,0xB0,0x7B,0xAD,0x45, - 0xB8,0xE2,0x40,0x7F,0xFB,0x0A,0x6E,0xFB,0xBE,0x33,0xC9,0x3C,0xA3,0x84,0xD5,0x30, - 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45, - 0x02,0x21,0x00,0xDC,0x92,0xA1,0xA0,0x13,0xA6,0xCF,0x03,0xB0,0xE6,0xC4,0x21,0x97, - 0x90,0xFA,0x14,0x57,0x2D,0x03,0xEC,0xEE,0x3C,0xD3,0x6E,0xCA,0xA8,0x6C,0x76,0xBC, - 0xA2,0xDE,0xBB,0x02,0x20,0x27,0xA8,0x85,0x27,0x35,0x9B,0x56,0xC6,0xA3,0xF2,0x47, - 0xD2,0xB7,0x6E,0x1B,0x02,0x00,0x17,0xAA,0x67,0xA6,0x15,0x91,0xDE,0xFA,0x94,0xEC, - 0x7B,0x0B,0xF8,0x9F,0x84, -}; - -static const UInt8 ECDSA_SHA384[] = { - 0x30,0x82,0x02,0x43,0x30,0x82,0x01,0xC9,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x2D, - 0xC5,0xFC,0x88,0xD2,0xC5,0x4B,0x95,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, - 0x04,0x03,0x03,0x30,0x67,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12, - 0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20, - 0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70, - 0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, - 0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03, - 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, - 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D, - 0x31,0x34,0x30,0x34,0x33,0x30,0x31,0x38,0x31,0x39,0x30,0x36,0x5A,0x17,0x0D,0x33, - 0x39,0x30,0x34,0x33,0x30,0x31,0x38,0x31,0x39,0x30,0x36,0x5A,0x30,0x67,0x31,0x1B, - 0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x41,0x70,0x70,0x6C,0x65,0x20,0x52, - 0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x47,0x33,0x31,0x26,0x30,0x24,0x06, - 0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74, - 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72, - 0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, - 0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, - 0x06,0x13,0x02,0x55,0x53,0x30,0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, - 0x02,0x01,0x06,0x05,0x2B,0x81,0x04,0x00,0x22,0x03,0x62,0x00,0x04,0x98,0xE9,0x2F, - 0x3D,0x40,0x72,0xA4,0xED,0x93,0x22,0x72,0x81,0x13,0x1C,0xDD,0x10,0x95,0xF1,0xC5, - 0xA3,0x4E,0x71,0xDC,0x14,0x16,0xD9,0x0E,0xE5,0xA6,0x05,0x2A,0x77,0x64,0x7B,0x5F, - 0x4E,0x38,0xD3,0xBB,0x1C,0x44,0xB5,0x7F,0xF5,0x1F,0xB6,0x32,0x62,0x5D,0xC9,0xE9, - 0x84,0x5B,0x4F,0x30,0x4F,0x11,0x5A,0x00,0xFD,0x58,0x58,0x0C,0xA5,0xF5,0x0F,0x2C, - 0x4D,0x07,0x47,0x13,0x75,0xDA,0x97,0x97,0x97,0x6F,0x31,0x5C,0xED,0x2B,0x9D,0x7B, - 0x20,0x3B,0xD8,0xB9,0x54,0xD9,0x5E,0x99,0xA4,0x3A,0x51,0x0A,0x31,0xA3,0x42,0x30, - 0x40,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xBB,0xB0,0xDE,0xA1, - 0x58,0x33,0x88,0x9A,0xA4,0x8A,0x99,0xDE,0xBE,0xBD,0xEB,0xAF,0xDA,0xCB,0x24,0xAB, - 0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01, - 0xFF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01, - 0x06,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x68,0x00, - 0x30,0x65,0x02,0x31,0x00,0x83,0xE9,0xC1,0xC4,0x16,0x5E,0x1A,0x5D,0x34,0x18,0xD9, - 0xED,0xEF,0xF4,0x6C,0x0E,0x00,0x46,0x4B,0xB8,0xDF,0xB2,0x46,0x11,0xC5,0x0F,0xFD, - 0xE6,0x7A,0x8C,0xA1,0xA6,0x6B,0xCE,0xC2,0x03,0xD4,0x9C,0xF5,0x93,0xC6,0x74,0xB8, - 0x6A,0xDF,0xAA,0x23,0x15,0x02,0x30,0x6D,0x66,0x8A,0x10,0xCA,0xD4,0x0D,0xD4,0x4F, - 0xCD,0x8D,0x43,0x3E,0xB4,0x8A,0x63,0xA5,0x33,0x6E,0xE3,0x6D,0xDA,0x17,0xB7,0x64, - 0x1F,0xC8,0x53,0x26,0xF9,0x88,0x62,0x74,0x39,0x0B,0x17,0x5B,0xCB,0x51,0xA8,0x0C, - 0xE8,0x18,0x03,0xE7,0xA2,0xB2,0x28, -}; - -static const UInt8 DSA_SHA1[] = { - 0x30,0x82,0x02,0x1E,0x30,0x82,0x01,0xDD,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x02, - 0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x38,0x04,0x03,0x30,0x3F,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1F,0x30,0x1D,0x06,0x03, - 0x55,0x04,0x0A,0x13,0x16,0x54,0x65,0x73,0x74,0x20,0x43,0x65,0x72,0x74,0x69,0x66, - 0x69,0x63,0x61,0x74,0x65,0x73,0x20,0x32,0x30,0x31,0x31,0x31,0x0F,0x30,0x0D,0x06, - 0x03,0x55,0x04,0x03,0x13,0x06,0x44,0x53,0x41,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, - 0x31,0x30,0x30,0x31,0x30,0x31,0x30,0x38,0x33,0x30,0x30,0x30,0x5A,0x17,0x0D,0x33, - 0x30,0x31,0x32,0x33,0x31,0x30,0x38,0x33,0x30,0x30,0x30,0x5A,0x30,0x54,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1F,0x30,0x1D,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x16,0x54,0x65,0x73,0x74,0x20,0x43,0x65,0x72,0x74,0x69, - 0x66,0x69,0x63,0x61,0x74,0x65,0x73,0x20,0x32,0x30,0x31,0x31,0x31,0x24,0x30,0x22, - 0x06,0x03,0x55,0x04,0x03,0x13,0x1B,0x44,0x53,0x41,0x20,0x50,0x61,0x72,0x61,0x6D, - 0x65,0x74,0x65,0x72,0x73,0x20,0x49,0x6E,0x68,0x65,0x72,0x69,0x74,0x65,0x64,0x20, - 0x43,0x41,0x30,0x81,0x92,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x38,0x04,0x01, - 0x03,0x81,0x84,0x00,0x02,0x81,0x80,0x74,0x2F,0x4F,0x75,0xD0,0x81,0x57,0x23,0x6F, - 0x2D,0x66,0x63,0x90,0xD1,0x42,0x20,0xCB,0x43,0x9F,0x4E,0xE2,0xF5,0x3A,0x14,0xD2, - 0xD8,0xC7,0xEA,0xDD,0xF3,0xB2,0x1E,0x81,0x9A,0x61,0x10,0x40,0x09,0xB2,0x7A,0x51, - 0xF3,0x66,0xF9,0x36,0x23,0x70,0x54,0xE8,0xE9,0x66,0x7A,0x94,0xA5,0xB1,0xF4,0x1B, - 0x31,0x18,0x56,0x5D,0xBF,0x8A,0x19,0x16,0x47,0x91,0x60,0xAA,0xF9,0x8D,0x45,0x5C, - 0x02,0x4B,0x7F,0x67,0xB3,0x02,0xF6,0x8F,0x6D,0x14,0xB9,0xCD,0x64,0x90,0xDD,0x0C, - 0x88,0xC7,0xC4,0x4B,0x12,0xD1,0xB8,0xBE,0x32,0xA0,0x9F,0xB9,0x4A,0x84,0x33,0xC3, - 0xAB,0xB6,0x42,0x4B,0x4B,0x32,0xED,0x29,0x3D,0x07,0xF8,0x07,0x7E,0xA2,0xF7,0xD8, - 0xA2,0x56,0x53,0x71,0x2A,0x53,0x7B,0xA3,0x7C,0x30,0x7A,0x30,0x1F,0x06,0x03,0x55, - 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x8F,0x90,0xC6,0x8C,0x74,0xE8,0x7B,0x0C, - 0xC8,0x59,0xC7,0x7D,0x3C,0x5B,0x54,0x59,0x60,0x25,0x0B,0xB1,0x30,0x1D,0x06,0x03, - 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x65,0x81,0x9F,0x70,0x3A,0x8C,0xAD,0xF6,0x43, - 0x1D,0xC8,0xE7,0x8F,0x55,0x8E,0xE8,0x4B,0xDB,0x87,0xE2,0x30,0x0E,0x06,0x03,0x55, - 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x17,0x06,0x03,0x55, - 0x1D,0x20,0x04,0x10,0x30,0x0E,0x30,0x0C,0x06,0x0A,0x60,0x86,0x48,0x01,0x65,0x03, - 0x02,0x01,0x30,0x01,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05, - 0x30,0x03,0x01,0x01,0xFF,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x38,0x04,0x03, - 0x03,0x30,0x00,0x30,0x2D,0x02,0x14,0x47,0xF0,0x98,0xC9,0xBB,0x05,0xA9,0x82,0xC5, - 0x11,0x2B,0x7A,0x5F,0xC9,0x11,0xE5,0x83,0x90,0xB7,0xD9,0x02,0x15,0x00,0x93,0xE1, - 0x0B,0xBE,0xAD,0x25,0x08,0x00,0x07,0x88,0x70,0xDF,0xC3,0x59,0x4F,0x22,0x9C,0xEA, - 0xD4,0x0F, -}; - -static const UInt8 RSAPSS_SHA256[] = { - 0x30,0x82,0x04,0x51,0x30,0x82,0x03,0x05,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x7B, - 0x20,0x9C,0x9D,0xDF,0x9C,0xED,0x93,0x43,0x73,0x51,0x0D,0x1B,0xD2,0x8A,0xDC,0x30, - 0x41,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0A,0x30,0x34,0xA0,0x0F, - 0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xA1, - 0x1C,0x30,0x1A,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x08,0x30,0x0D, - 0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xA2,0x03,0x02, - 0x01,0x20,0x30,0x31,0x31,0x2F,0x30,0x2D,0x06,0x03,0x55,0x04,0x03,0x13,0x26,0x54, - 0x75,0x63,0x73,0x6F,0x6E,0x20,0x55,0x6E,0x69,0x66,0x69,0x65,0x64,0x20,0x53,0x63, - 0x68,0x6F,0x6F,0x6C,0x20,0x44,0x69,0x73,0x74,0x72,0x69,0x63,0x74,0x20,0x52,0x6F, - 0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x39,0x30,0x32,0x30, - 0x37,0x31,0x36,0x32,0x39,0x5A,0x17,0x0D,0x33,0x34,0x30,0x39,0x30,0x32,0x30,0x37, - 0x32,0x38,0x33,0x33,0x5A,0x30,0x31,0x31,0x2F,0x30,0x2D,0x06,0x03,0x55,0x04,0x03, - 0x13,0x26,0x54,0x75,0x63,0x73,0x6F,0x6E,0x20,0x55,0x6E,0x69,0x66,0x69,0x65,0x64, - 0x20,0x53,0x63,0x68,0x6F,0x6F,0x6C,0x20,0x44,0x69,0x73,0x74,0x72,0x69,0x63,0x74, - 0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00, - 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC7,0x5F,0x0B,0x3D,0x69,0x0B,0x4F, - 0x05,0x0A,0xD9,0x2F,0xFC,0x06,0xD7,0x7E,0x16,0xD2,0x36,0x9E,0x97,0x24,0x4A,0x1B, - 0xCE,0x8E,0x39,0xE6,0x4E,0x2F,0xF3,0x42,0x52,0x61,0x35,0x5F,0x97,0xD5,0x3C,0x06, - 0x85,0x2E,0x39,0xD2,0xE9,0x4D,0x5C,0xEA,0xB9,0xE7,0x04,0x22,0x40,0xE1,0x30,0x61, - 0xD6,0xCC,0x4C,0x0F,0x3B,0xE5,0x25,0x3B,0x21,0x33,0xB7,0x5F,0xA6,0x33,0xC0,0x08, - 0x18,0xD9,0x4A,0xF7,0xC8,0x1C,0xEE,0x16,0xF5,0x7C,0xB1,0xBF,0x9A,0x01,0x7E,0x21, - 0x9F,0x0A,0xD7,0xAC,0x63,0xBA,0xA8,0x9B,0x21,0x64,0x6F,0x2B,0x42,0xFA,0x97,0x8B, - 0xCC,0xF9,0x04,0x91,0x79,0xE1,0xB9,0xFA,0xC2,0xBD,0x2F,0x54,0x02,0x67,0xB1,0xDF, - 0xB8,0x78,0x76,0x06,0x2B,0xC4,0x2E,0xBA,0x62,0xDB,0x70,0x49,0x59,0x8A,0x64,0xD0, - 0x71,0xCC,0x60,0x1F,0xC4,0x89,0xE7,0xE2,0x95,0x05,0x39,0x88,0x43,0x21,0x45,0xAE, - 0x80,0x72,0x2C,0xF6,0x70,0xE1,0xA6,0x65,0x52,0x4F,0x67,0x18,0x7C,0x80,0x4F,0xD3, - 0xE1,0x6C,0x39,0xAB,0x58,0x6F,0x4A,0x7B,0xB1,0xFB,0x21,0xF5,0xF6,0x26,0xCB,0x15, - 0x22,0xEF,0x63,0x1E,0x0E,0xBF,0x92,0xB2,0x3D,0x52,0x79,0xBC,0xE9,0xFE,0x62,0x18, - 0x83,0x0A,0x1D,0x97,0xF0,0x8E,0xE9,0x11,0x77,0x8F,0xDF,0xE5,0x0B,0xB8,0x0D,0xDB, - 0x6B,0x27,0x21,0xE0,0x12,0xB9,0xF4,0xB5,0xA2,0xD9,0x80,0xF4,0x64,0x66,0x5C,0x61, - 0xB6,0x16,0xC8,0x21,0x8B,0xDC,0x66,0x4F,0xEE,0x22,0x7F,0x07,0xA8,0x19,0x05,0x9E, - 0x83,0x0F,0x1E,0xC1,0x93,0x58,0x6C,0xEF,0xB3,0x02,0x03,0x01,0x00,0x01,0xA3,0x81, - 0xFC,0x30,0x81,0xF9,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04,0x04,0x03,0x02,0x01, - 0x86,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01, - 0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xFC,0xEE,0x66, - 0x3B,0xB0,0xC7,0xD4,0x6F,0x68,0x37,0xBA,0x99,0x27,0x73,0xEE,0x4F,0x8D,0x9B,0xE3, - 0xF4,0x30,0x10,0x06,0x09,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x15,0x01,0x04,0x03, - 0x02,0x01,0x01,0x30,0x81,0x82,0x06,0x03,0x55,0x1D,0x20,0x04,0x7B,0x30,0x79,0x30, - 0x77,0x06,0x08,0x2A,0x03,0x04,0x8B,0x2F,0x43,0x59,0x05,0x30,0x6B,0x30,0x3A,0x06, - 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x2E,0x1E,0x2C,0x00,0x4C,0x00, - 0x65,0x00,0x67,0x00,0x61,0x00,0x6C,0x00,0x20,0x00,0x50,0x00,0x6F,0x00,0x6C,0x00, - 0x69,0x00,0x63,0x00,0x79,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x61,0x00,0x74,0x00, - 0x65,0x00,0x6D,0x00,0x65,0x00,0x6E,0x00,0x74,0x30,0x2D,0x06,0x08,0x2B,0x06,0x01, - 0x05,0x05,0x07,0x02,0x01,0x16,0x21,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72, - 0x6C,0x2E,0x74,0x75,0x73,0x64,0x31,0x2E,0x6F,0x72,0x67,0x2F,0x70,0x6B,0x69,0x2F, - 0x63,0x70,0x73,0x2E,0x74,0x78,0x74,0x00,0x30,0x23,0x06,0x09,0x2B,0x06,0x01,0x04, - 0x01,0x82,0x37,0x15,0x02,0x04,0x16,0x04,0x14,0x10,0xF3,0x7D,0x95,0x8D,0xB7,0x2F, - 0x44,0x17,0xD7,0xED,0x56,0xC3,0x7E,0x64,0xAA,0x4F,0xEF,0x26,0xEA,0x30,0x41,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0A,0x30,0x34,0xA0,0x0F,0x30,0x0D, - 0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xA1,0x1C,0x30, - 0x1A,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x08,0x30,0x0D,0x06,0x09, - 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xA2,0x03,0x02,0x01,0x20, - 0x03,0x82,0x01,0x01,0x00,0x03,0x1F,0xF8,0x3C,0x15,0x37,0xA7,0xBB,0xB1,0x6A,0x27, - 0xDB,0x27,0x7F,0xF8,0x23,0xAD,0x51,0xEE,0x87,0x61,0xC8,0xAB,0x56,0x83,0x1C,0x11, - 0xA9,0xAC,0x79,0xB4,0x7E,0x2E,0x33,0x3F,0xBD,0x98,0x7B,0xE4,0x28,0xAB,0xB1,0xCB, - 0x00,0xEE,0xB3,0x2D,0x6B,0x8D,0x15,0xAD,0x4B,0x51,0x29,0xFE,0x05,0xE6,0x5C,0x1C, - 0xBA,0x70,0xAF,0x30,0x13,0x2C,0xAE,0xDD,0x8D,0x95,0xF5,0x56,0x13,0x2B,0x43,0x07, - 0x0F,0xC3,0xCB,0xDA,0x2B,0x46,0x44,0x8E,0x12,0xE3,0x9E,0x14,0xE2,0x5E,0x74,0x07, - 0x0C,0x92,0xDE,0x99,0x45,0x37,0x51,0xFB,0xDB,0x75,0xFE,0x16,0x37,0x58,0x05,0xB3, - 0xDE,0x3E,0xD1,0x77,0x57,0x6A,0x56,0xF1,0xF6,0xC1,0x9F,0xA8,0x93,0xCF,0xA8,0x67, - 0x32,0xE1,0xDB,0x65,0x12,0x39,0x76,0x91,0xB7,0x85,0xDD,0xF0,0x30,0xEF,0x6E,0x68, - 0x41,0xCD,0x72,0x0B,0x8D,0x85,0x50,0x26,0xC1,0x0B,0x93,0x2B,0x9F,0x07,0x44,0x57, - 0x84,0x55,0x3F,0x28,0x75,0x05,0x12,0x04,0x58,0x27,0x24,0x5D,0x21,0x68,0xB5,0xF4, - 0xB9,0xFA,0xE6,0xC1,0xCB,0x99,0x7C,0x85,0x45,0x01,0xFE,0x43,0x8C,0xCA,0x9E,0x44, - 0x32,0x46,0x23,0xFC,0xBD,0x2D,0xCA,0x19,0xF8,0xDB,0x1C,0x9F,0x85,0x3D,0x7C,0xAA, - 0xCC,0x42,0x16,0x4D,0x61,0x7D,0xA1,0x67,0xD5,0xC0,0x25,0x62,0xDB,0xE2,0x61,0xB0, - 0xDD,0xB6,0xD6,0x07,0x03,0x1B,0xD0,0x0E,0xB2,0xBA,0xC2,0xBF,0x24,0x7C,0x2B,0x82, - 0xEB,0xEE,0xB0,0x29,0xE5,0x8E,0xDD,0x55,0xF6,0x3B,0x5E,0x46,0x0D,0xCE,0x55,0xEA, - 0x70,0x2F,0xFF,0xF8,0x74, -}; - -static void test_signature_hash_algorithm() -{ - SecCertificateRef cert=NULL; - SecSignatureHashAlgorithm alg=0; - - isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_MD2, sizeof(RSA_MD2)), - NULL, "create RSA_MD2"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmMD2, "expected kSecSignatureHashAlgorithmMD2 (got %d)", (int)alg); - CFReleaseNull(cert); - - isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_MD5, sizeof(RSA_MD5)), - NULL, "create RSA_MD5"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmMD5, "expected kSecSignatureHashAlgorithmMD5 (got %d)", (int)alg); - CFReleaseNull(cert); - - isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_SHA1, sizeof(RSA_SHA1)), - NULL, "create RSA_SHA1"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmSHA1, "expected kSecSignatureHashAlgorithmSHA1 (got %d)", (int)alg); - CFReleaseNull(cert); - - isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_SHA256, sizeof(RSA_SHA256)), - NULL, "create RSA_SHA256"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmSHA256, "expected kSecSignatureHashAlgorithmSHA256 (got %d)", (int)alg); - CFReleaseNull(cert); - - isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_SHA512, sizeof(RSA_SHA512)), - NULL, "create RSA_SHA512"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmSHA512, "expected kSecSignatureHashAlgorithmSHA512 (got %d)", (int)alg); - CFReleaseNull(cert); - - isnt(cert = SecCertificateCreateWithBytes(NULL, DSA_SHA1, sizeof(DSA_SHA1)), - NULL, "create DSA_SHA1"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmSHA1, "expected kSecSignatureHashAlgorithmSHA1 (got %d)", (int)alg); - CFReleaseNull(cert); - - isnt(cert = SecCertificateCreateWithBytes(NULL, ECDSA_SHA1, sizeof(ECDSA_SHA1)), - NULL, "create ECDSA_SHA1"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmSHA1, "expected kSecSignatureHashAlgorithmSHA1 (got %d)", (int)alg); - CFReleaseNull(cert); - - isnt(cert = SecCertificateCreateWithBytes(NULL, ECDSA_SHA256, sizeof(ECDSA_SHA256)), - NULL, "create ECDSA_SHA256"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmSHA256, "expected kSecSignatureHashAlgorithmSHA256 (got %d)", (int)alg); - CFReleaseNull(cert); - - isnt(cert = SecCertificateCreateWithBytes(NULL, ECDSA_SHA384, sizeof(ECDSA_SHA384)), - NULL, "create ECDSA_SHA384"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmSHA384, "expected kSecSignatureHashAlgorithmSHA384 (got %d)", (int)alg); - CFReleaseNull(cert); - - /* %%% RSAPSS is not yet supported; change this test when it is. */ - isnt(cert = SecCertificateCreateWithBytes(NULL, RSAPSS_SHA256, sizeof(RSAPSS_SHA256)), - NULL, "create RSAPSS_SHA256"); - alg = SecCertificateGetSignatureHashAlgorithm(cert); - ok(alg == kSecSignatureHashAlgorithmUnknown, "expected kSecSignatureHashAlgorithmUnknown (got %d)", (int)alg); - CFReleaseNull(cert); - -} - -static void tests(void) -{ - test_signature_hash_algorithm(); -} - -int si_83_seccertificate_sighashalg(int argc, char *const *argv) -{ - plan_tests(20); - - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-84-sectrust-allowlist.m b/OSX/sec/Security/Regressions/secitem/si-84-sectrust-allowlist.m deleted file mode 100644 index ab4ed0e9..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-84-sectrust-allowlist.m +++ /dev/null @@ -1,490 +0,0 @@ -/* - * si-84-sectrust-allowlist.c - * Security - * - * Copyright (c) 2015-2017 Apple Inc. All Rights Reserved. - */ - -#include -#import -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -#include "si-84-sectrust-allowlist/cnnic_certs.h" -#include "si-84-sectrust-allowlist/wosign_certs.h" -#include "si-84-sectrust-allowlist/date_testing_certs.h" - -/* Define this symbol for testing updated allowlist workaround. */ -#define RADAR_32792206 1 - - -static SecCertificateRef createCertFromStaticData(const UInt8 *certData, CFIndex certLength) -{ - SecCertificateRef cert = NULL; - CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, certData, certLength, kCFAllocatorNull); - if (data) { - cert = SecCertificateCreateWithData(NULL, data); - CFRelease(data); - } - return cert; -} - -static void TestLeafOnAllowList() -{ - SecCertificateRef certs[4]; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFDateRef date = NULL; - CFArrayRef certArray = NULL; - CFArrayRef anchorsArray = NULL; - - isnt(certs[0] = createCertFromStaticData(leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)), - NULL, "allowlist: create leaf cert"); - isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)), - NULL, "allowlist: create intermediate ca 1"); - isnt(certs[2] = createCertFromStaticData(ca2_Cert, sizeof(ca2_Cert)), - NULL, "allowlist: create intermediate ca 2"); - isnt(certs[3] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), - NULL, "allowlist: create root"); - - isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 4, &kCFTypeArrayCallBacks), - NULL, "allowlist: create cert array"); - - /* create a trust reference with ssl policy */ - isnt(policy = SecPolicyCreateSSL(true, CFSTR("telegram.im")), NULL, "allowlist: create policy"); - ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "allowlist: create trust"); - - /* set evaluate date: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "allowlist: create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "allowlist: set verify date"); - - /* use a known root CA at this point in time to anchor the chain */ - isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[3], 1, &kCFTypeArrayCallBacks), - NULL, "allowlist: create anchors array"); - ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "allowlist: set anchors"); - - SecTrustResultType trustResult = kSecTrustResultInvalid; - ok_status(SecTrustEvaluate(trust, &trustResult), "allowlist: evaluate"); - -#if 0 - /* expected result is kSecTrustResultUnspecified since cert is on allow list and its issuer chains to a trusted root */ - ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", - (int)trustResult); -#else - #if RADAR_32792206 - /* this certificate was on the allow list prior to v5, and list hasn't yet updated. */ - if (trustResult == kSecTrustResultUnspecified) { - trustResult = kSecTrustResultRecoverableTrustFailure; - } - #endif - /* this certificate is no longer on the allow list: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - - /* clean up */ - for(CFIndex idx=0; idx < 4; idx++) { - if (certs[idx]) { CFRelease(certs[idx]); } - } - if (policy) { CFRelease(policy); } - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - if (certArray) { CFRelease(certArray); } - if (anchorsArray) { CFRelease(anchorsArray); } -} - -static void TestLeafNotOnAllowList() -{ - SecCertificateRef certs[4]; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFDateRef date = NULL; - CFArrayRef certArray = NULL; - CFArrayRef anchorsArray = NULL; - - isnt(certs[0] = createCertFromStaticData(leafNotOnAllowList_Cert, sizeof(leafNotOnAllowList_Cert)), - NULL, "!allowlist: create leaf cert"); - isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)), - NULL, "!allowlist: create intermediate ca 1"); - isnt(certs[2] = createCertFromStaticData(ca2_Cert, sizeof(ca2_Cert)), - NULL, "!allowlist: create intermediate ca 2"); - isnt(certs[3] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), - NULL, "!allowlist: create root"); - - isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 4, &kCFTypeArrayCallBacks), - NULL, "!allowlist: create cert array"); - - /* create a trust reference with basic policy */ - isnt(policy = SecPolicyCreateBasicX509(), NULL, "!allowlist: create policy"); - ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "!allowlist: create trust"); - - /* set evaluate date: September 7, 2016 at 9:00:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495000000.0), NULL, "!allowlist: create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "!allowlist: set verify date"); - - /* use a known root CA at this point in time to anchor the chain */ - isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[3], 1, &kCFTypeArrayCallBacks), - NULL, "allowlist: create anchors array"); - ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "!allowlist: set anchors"); - - SecTrustResultType trustResult = kSecTrustResultInvalid; - ok_status(SecTrustEvaluate(trust, &trustResult), "!allowlist: evaluate"); - - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); - - /* clean up */ - for(CFIndex idx=0; idx < 4; idx++) { - if (certs[idx]) { CFRelease(certs[idx]); } - } - if (policy) { CFRelease(policy); } - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - if (certArray) { CFRelease(certArray); } - if (anchorsArray) { CFRelease(anchorsArray); } -} - -static void TestAllowListForRootCA(void) -{ - SecCertificateRef test0[2] = {NULL,NULL}; - SecCertificateRef test1[2] = {NULL,NULL}; - SecCertificateRef test1e[2] = {NULL,NULL}; - SecCertificateRef test2[2] = {NULL,NULL}; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFDateRef date = NULL; - SecTrustResultType trustResult; - - isnt(test0[0] = createCertFromStaticData(cert0, sizeof(cert0)), - NULL, "create first leaf"); - isnt(test1[0] = createCertFromStaticData(cert1, sizeof(cert1)), - NULL, "create second leaf"); - isnt(test1e[0] = createCertFromStaticData(cert1_expired, sizeof(cert1_expired)), - NULL, "create second leaf (expired)"); - isnt(test2[0] = createCertFromStaticData(cert2, sizeof(cert2)), - NULL, "create third leaf"); - - isnt(test0[1] = createCertFromStaticData(intermediate0, sizeof(intermediate0)), - NULL, "create intermediate"); - isnt(test1[1] = createCertFromStaticData(intermediate1, sizeof(intermediate1)), - NULL, "create intermediate"); - isnt(test1e[1] = createCertFromStaticData(intermediate1, sizeof(intermediate1)), - NULL, "create intermediate"); - isnt(test2[1] = createCertFromStaticData(intermediate2, sizeof(intermediate2)), - NULL, "create intermediate"); - - CFArrayRef certs0 = CFArrayCreate(kCFAllocatorDefault, (const void **)test0, 2, &kCFTypeArrayCallBacks); - CFArrayRef certs1 = CFArrayCreate(kCFAllocatorDefault, (const void **)test1, 2, &kCFTypeArrayCallBacks); - CFArrayRef certs1e = CFArrayCreate(kCFAllocatorDefault, (const void **)test1e, 2, &kCFTypeArrayCallBacks); - CFArrayRef certs2 = CFArrayCreate(kCFAllocatorDefault, (const void **)test2, 2, &kCFTypeArrayCallBacks); - - /* - * Allowlisted certificates issued by untrusted root CA. - */ - isnt(policy = SecPolicyCreateBasicX509(), NULL, "create policy"); - ok_status(SecTrustCreateWithCertificates(certs0, policy, &trust), "create trust"); - /* set evaluate date within validity range: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set verify date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - /* successful trust result expected since this is on the allow list */ - ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", - (int)trustResult); -#else - #if RADAR_32792206 - /* this certificate was on the allow list prior to v5, and list hasn't yet updated. */ - if (trustResult == kSecTrustResultUnspecified) { - trustResult = kSecTrustResultRecoverableTrustFailure; - } - #endif - /* this certificate is no longer on the allow list: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - - ok_status(SecTrustCreateWithCertificates(certs1, policy, &trust), "create trust"); - /* set evaluate date within validity range: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set verify date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - /* Note: this certificate has expired and was removed from the allowlist, - so we currently expect a revoked trust failure despite the verify date. */ - ok(trustResult == kSecTrustResultFatalTrustFailure, "trustResult 6 expected (got %d)", - (int)trustResult); -#else - /* there is no longer an allowlist: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - - ok_status(SecTrustCreateWithCertificates(certs2, policy, &trust), "create trust"); - /* set evaluate date within validity range: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set verify date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - /* successful trust result expected since this is on the allow list */ - ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", - (int)trustResult); -#else - #if RADAR_32792206 - /* this certificate was on the allow list prior to v5, and list hasn't yet updated. */ - if (trustResult == kSecTrustResultUnspecified) { - trustResult = kSecTrustResultRecoverableTrustFailure; - } - #endif - /* this certificate is no longer on the allow list: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - - /* - * Same certificate, on allow list but past expiration. Expect to fail. - */ - if (date) { CFRelease(date); } - isnt(date = CFDateCreate(NULL, 667680000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set date to far future so certs are expired"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - ok(trustResult == kSecTrustResultRecoverableTrustFailure, "trustResult 5 expected (got %d)", - (int)trustResult); -#else - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - - /* - * Expired certificate not on allow list. Expect to fail. - */ - ok_status(SecTrustCreateWithCertificates(certs1e, policy, &trust), "create trust"); - /* set evaluate date within validity range: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set verify date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - /* Note: because this certificate is not on the allow list, and the allow list is complete, - we now expect it to be treated as revoked regardless of expiration status. */ - ok(trustResult == kSecTrustResultFatalTrustFailure, "trustResult 6 expected (got %d)", - (int)trustResult); -#else - /* there is no longer an allowlist: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - - - /* Clean up. */ - if (policy) { CFRelease(policy); } - if (certs0) { CFRelease(certs0); } - if (certs1) { CFRelease(certs1); } - if (certs1e) { CFRelease(certs1e); } - if (certs2) { CFRelease(certs2); } - - if (test0[0]) { CFRelease(test0[0]); } - if (test0[1]) { CFRelease(test0[1]); } - if (test1[0]) { CFRelease(test1[0]); } - if (test1[1]) { CFRelease(test1[1]); } - if (test1e[0]) { CFRelease(test1e[0]); } - if (test1e[1]) { CFRelease(test1e[1]); } - if (test2[0]) { CFRelease(test2[0]); } - if (test2[1]) { CFRelease(test2[1]); } -} - -static void TestDateBasedAllowListForRootCA(void) { - SecCertificateRef root = NULL, beforeInt = NULL, afterInt = NULL, - beforeLeaf = NULL, afterLeaf = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - NSArray *anchors = nil, *certs = nil; - NSDate *verifyDate = nil; - SecTrustResultType trustResult = kSecTrustResultInvalid; - - require(root = SecCertificateCreateWithBytes(NULL, _datetest_root, sizeof(_datetest_root)), out); - require(beforeInt = SecCertificateCreateWithBytes(NULL, _datetest_before_int, sizeof(_datetest_before_int)), out); - require(afterInt = SecCertificateCreateWithBytes(NULL, _datetest_after_int, sizeof(_datetest_after_int)), out); - require(beforeLeaf = SecCertificateCreateWithBytes(NULL, _datetest_before_leaf, sizeof(_datetest_before_leaf)), out); - require(afterLeaf = SecCertificateCreateWithBytes(NULL, _datetest_after_leaf, sizeof(_datetest_after_leaf)), out); - - anchors = @[(__bridge id)root]; - require(policy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com")), out); - verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:504000000.0]; /* 21 Dec 2016 */ - - /* Leaf issued before cutoff should pass */ - certs = @[(__bridge id)beforeLeaf, (__bridge id)beforeInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* Leaf issued after cutoff should fail */ - certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* Intermediate issued after cutoff should fail (even for leaf issued before) */ - certs = @[(__bridge id)beforeLeaf, (__bridge id)afterInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued after cutoff succeeded evaluation"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* Intermediate issued after cutoff should fail */ - certs = @[(__bridge id)afterLeaf, (__bridge id)afterInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued before cutoff succeeded evaluation"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* Leaf issued before cutoff should choose acceptable path */ - certs = @[(__bridge id)beforeLeaf, (__bridge id) afterInt, (__bridge id)beforeInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation (multi-path)"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* No good path for leaf issued after cutoff */ - certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt, (__bridge id)afterInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation (multi-path)"); - -out: - CFReleaseNull(root); - CFReleaseNull(beforeInt); - CFReleaseNull(afterInt); - CFReleaseNull(beforeLeaf); - CFReleaseNull(afterLeaf); - CFReleaseNull(policy); - CFReleaseNull(trust); -} - -static void TestLeafOnAllowListOtherFailures(void) -{ - SecCertificateRef certs[4]; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - NSArray *anchors = nil, *certArray = nil; - NSDate *verifyDate = nil; - SecTrustResultType trustResult = kSecTrustResultInvalid; - - memset(certs, 0, 4 * sizeof(SecCertificateRef)); - - require(certs[0] = SecCertificateCreateWithBytes(NULL, leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)), out); - require(certs[1] = SecCertificateCreateWithBytes(NULL, ca1_Cert, sizeof(ca1_Cert)), out); - require(certs[2] = SecCertificateCreateWithBytes(NULL, ca2_Cert, sizeof(ca2_Cert)), out); - require(certs[3] = SecCertificateCreateWithBytes(NULL, root_Cert, sizeof(root_Cert)), out); - - anchors = @[(__bridge id)certs[3]]; - certArray = @[(__bridge id)certs[0], (__bridge id)certs[1], (__bridge id)certs[2], (__bridge id)certs[3]]; - verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:495405000.0]; - - /* Mismatched hostname, should fail */ - require(policy = SecPolicyCreateSSL(true, (__bridge CFStringRef)@"wrong.hostname.com"), out); - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certArray, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, - "hostname failure with cert on allow list succeeded evaluation"); - CFReleaseNull(policy); - trustResult = kSecTrustResultInvalid; - - /* Wrong EKU, should fail */ - require(policy = SecPolicyCreateCodeSigning(), out); - require_noerr(SecTrustSetPolicies(trust, policy), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, - "EKU failure with cert on allow list succeeded evaluation"); - CFReleaseNull(policy); - trustResult = kSecTrustResultInvalid; - - /* Apple pinning policy, should fail */ - require(policy = SecPolicyCreateAppleSSLPinned((__bridge CFStringRef)@"aPolicy", - (__bridge CFStringRef)@"telegram.im", NULL, - (__bridge CFStringRef)@"1.2.840.113635.100.6.27.12"), out); - require_noerr(SecTrustSetPolicies(trust, policy), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, - "Apple pinning policy with cert on allow list succeeded evaluation"); - - out: - CFReleaseNull(certs[0]); - CFReleaseNull(certs[1]); - CFReleaseNull(certs[2]); - CFReleaseNull(certs[3]); - CFReleaseNull(policy); - CFReleaseNull(trust); -} - -static void tests(void) -{ - TestAllowListForRootCA(); - TestLeafOnAllowList(); - TestLeafNotOnAllowList(); - TestDateBasedAllowListForRootCA(); - TestLeafOnAllowListOtherFailures(); -} - -int si_84_sectrust_allowlist(int argc, char *const *argv) -{ - plan_tests(68); - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c b/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c index 6aed79c3..285e7ff3 100644 --- a/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c +++ b/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c @@ -368,7 +368,7 @@ static void sign_tests(SecIdentityRef identity, bool isRSA) { is(sign_please(identity, SEC_OID_SHA1, false, (isRSA) ? rsa_sha1 : NULL, (isRSA) ? sizeof(rsa_sha1) : 0), errSecSuccess, "Signed with SHA-1"); - is(sign_please(identity, SEC_OID_SHA256, false, (isRSA) ? rsa_sha256 : NULL, + is(sign_please(identity, SEC_OID_SHA256, false, (isRSA) ? new_sig_alg_rsa_sha256 : NULL, (isRSA) ? sizeof(rsa_sha256) : 0), errSecSuccess, "Signed with SHA-256"); is(sign_please(identity, SEC_OID_SHA384, false, NULL, 0), errSecSuccess, "Signed with SHA-384"); diff --git a/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h b/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h index 371b8f69..c7ad36b9 100644 --- a/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h +++ b/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h @@ -465,7 +465,7 @@ unsigned char rsa_sha1[] = { 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, - 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, + 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x29, 0xbb, 0xc2, 0xc1, 0x17, 0xb9, 0x7d, 0x8b, 0x43, 0xc6, 0x25, 0xad, 0xf1, 0xae, 0xb6, 0x26, 0x78, 0x9c, 0x92, 0x47, 0x77, 0xf8, 0xac, 0x53, 0xca, 0x17, 0x58, 0x4a, 0x8d, 0x66, 0x44, 0x99, 0x14, 0x3f, 0x63, 0x98, 0x3a, 0x7c, 0xe6, 0x65, 0xf0, 0x2a, 0x5e, 0x49, 0xbe, 0xdd, 0x40, 0x6e, 0x21, 0x43, 0xe1, 0xb9, 0x13, 0xa8, 0x31, 0xbf, 0x12, 0xb2, 0x78, 0x97, @@ -565,6 +565,89 @@ unsigned char rsa_sha256[] = { 0x45, 0xc2, 0x99, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +unsigned char new_sig_alg_rsa_sha256[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x80, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, + 0x41, 0x69, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0x82, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, + 0x00, 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, + 0x53, 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, + 0x34, 0x30, 0x30, 0x31, 0x38, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x38, + 0x32, 0x39, 0x5a, 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, + 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, + 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, + 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x9b, 0xcb, 0x6c, 0x77, 0xb7, 0xd1, 0x05, 0xa0, 0xae, 0x86, 0x20, 0x45, 0xd3, + 0xf4, 0x24, 0x8d, 0x25, 0x34, 0x31, 0xa9, 0xe2, 0x10, 0x36, 0xf5, 0x0a, 0x0b, 0x90, 0x4a, 0xa5, 0x6b, 0x5c, 0x16, 0xcd, + 0xb0, 0x72, 0xe9, 0xa9, 0x80, 0x5f, 0x6d, 0xb2, 0x4d, 0xd9, 0x58, 0x16, 0x9f, 0x68, 0x81, 0x9a, 0x6b, 0xeb, 0xd5, 0x4b, + 0xf7, 0x7d, 0x59, 0xe9, 0x46, 0x2b, 0x5b, 0x8f, 0xe4, 0xec, 0xab, 0x5c, 0x07, 0x74, 0xa2, 0x0e, 0x59, 0xbb, 0xfc, 0xd3, + 0xcf, 0xf7, 0x21, 0x88, 0x6c, 0x88, 0xd9, 0x6b, 0xa3, 0xa3, 0x4e, 0x5b, 0xd1, 0x1c, 0xfb, 0x04, 0xf5, 0xb2, 0x12, 0x0e, + 0x54, 0x59, 0x4d, 0xce, 0x0a, 0xe0, 0x26, 0x24, 0x06, 0xeb, 0xc8, 0xa2, 0xc6, 0x41, 0x28, 0xf9, 0x79, 0xe4, 0xb1, 0x4e, + 0x00, 0x6f, 0x6e, 0xf8, 0x96, 0x9e, 0x45, 0x28, 0x70, 0xec, 0xc7, 0xdc, 0xa2, 0xdd, 0x92, 0xab, 0xdd, 0x6f, 0xd8, 0x57, + 0xba, 0xcc, 0x29, 0xbe, 0xb7, 0x00, 0x1e, 0x8d, 0x13, 0x3f, 0x47, 0x34, 0x3c, 0xd0, 0xc6, 0xc8, 0x17, 0xdf, 0x74, 0x8a, + 0xb1, 0xc3, 0x68, 0xd5, 0xba, 0x76, 0x60, 0x55, 0x5f, 0x8d, 0xfa, 0xbd, 0xe7, 0x11, 0x9e, 0x59, 0x96, 0xe5, 0x93, 0x70, + 0xad, 0x41, 0xfb, 0x61, 0x46, 0x70, 0xc4, 0x05, 0x12, 0x23, 0x23, 0xc0, 0x9d, 0xc8, 0xc5, 0xf5, 0x96, 0xe5, 0x48, 0x10, + 0x86, 0x8a, 0x1e, 0x3b, 0x83, 0xd1, 0x47, 0x3a, 0x27, 0x00, 0x71, 0x10, 0xa3, 0x52, 0xba, 0xae, 0x01, 0x43, 0x87, 0x9c, + 0x6a, 0x1b, 0xea, 0x1a, 0x44, 0x4f, 0x4a, 0xac, 0xd4, 0x82, 0x55, 0xee, 0x1f, 0x25, 0x9c, 0x55, 0xca, 0xd2, 0xd0, 0x3a, + 0x0b, 0x70, 0x90, 0x60, 0x49, 0x47, 0x02, 0xfd, 0x89, 0x2c, 0x9a, 0x26, 0x36, 0x34, 0x8f, 0x24, 0x39, 0x8c, 0xe9, 0xa2, + 0x52, 0x8f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, + 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4c, 0xed, 0x5b, 0xaf, 0x13, 0x16, 0x5d, 0xe2, 0xdd, 0x5c, 0x48, 0x1c, + 0xd5, 0x6e, 0x8b, 0x04, 0x51, 0xd6, 0x38, 0x80, 0xfd, 0x52, 0x4a, 0x34, 0xdc, 0x13, 0x35, 0x6e, 0x64, 0x39, 0x39, 0x39, + 0x09, 0xa7, 0x6c, 0x2d, 0x39, 0xf2, 0x04, 0x21, 0xe3, 0xea, 0x8f, 0xf8, 0xbe, 0x46, 0x0e, 0x20, 0x82, 0xd0, 0xc5, 0x60, + 0xbf, 0x57, 0x6f, 0xd8, 0x29, 0xb4, 0x66, 0xdb, 0xbf, 0x92, 0xc9, 0xdc, 0x90, 0x97, 0x0f, 0x2f, 0x59, 0xa0, 0x13, 0xf3, + 0xa4, 0xca, 0xde, 0x3f, 0x80, 0x2a, 0x99, 0xb4, 0xee, 0x71, 0xc3, 0x56, 0x71, 0x51, 0x37, 0x55, 0xa1, 0x60, 0x89, 0xab, + 0x94, 0x0e, 0xb9, 0x70, 0xa5, 0x55, 0xf3, 0x1a, 0x87, 0xa4, 0x41, 0x4c, 0x45, 0xba, 0xb6, 0x56, 0xd6, 0x45, 0x56, 0x12, + 0x60, 0xe5, 0x91, 0xec, 0xf7, 0xbe, 0x39, 0xa4, 0x80, 0x08, 0x9f, 0xea, 0x17, 0x12, 0x0e, 0xa6, 0xe6, 0xef, 0x09, 0xf7, + 0x61, 0x51, 0x57, 0x73, 0xe3, 0x57, 0x88, 0xd7, 0xf8, 0x5f, 0xaf, 0x5d, 0xaf, 0x88, 0x32, 0xb4, 0x09, 0x3e, 0x7c, 0x25, + 0x77, 0x35, 0xe9, 0x3e, 0x6e, 0x0a, 0xb9, 0xb4, 0xa3, 0x06, 0x07, 0x0f, 0x7e, 0x93, 0x26, 0x16, 0x38, 0x1e, 0x4e, 0x72, + 0xaf, 0x06, 0x44, 0x1e, 0x8d, 0x96, 0xa6, 0x15, 0x9c, 0x82, 0x6d, 0x71, 0x99, 0x84, 0x8d, 0x12, 0x46, 0xf2, 0xbb, 0xa7, + 0x63, 0x7a, 0x32, 0xda, 0xa9, 0xde, 0xb6, 0x34, 0x14, 0xfb, 0x07, 0x0c, 0xab, 0x3b, 0x0a, 0xa1, 0x8b, 0xda, 0x15, 0xb3, + 0x63, 0xf3, 0x5c, 0x45, 0x2f, 0x0b, 0x6e, 0xc7, 0x27, 0x72, 0xc1, 0x37, 0x56, 0x30, 0xe3, 0x26, 0xbb, 0x19, 0x4f, 0x91, + 0xa1, 0xd0, 0x30, 0x29, 0x5b, 0x79, 0x79, 0x5c, 0xe6, 0x4f, 0xed, 0xcf, 0x81, 0xb2, 0x50, 0x35, 0x96, 0x23, 0xb2, 0x9f, + 0xca, 0x3f, 0xb5, 0x54, 0x31, 0x82, 0x01, 0xdc, 0x30, 0x82, 0x01, 0xd8, 0x02, 0x01, 0x01, 0x30, 0x81, 0xb0, 0x30, 0x81, + 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0b, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xc9, 0x25, 0xbe, 0xb8, 0xf2, 0x2c, 0x7f, 0xc8, 0x3a, 0xc3, 0xc2, 0x4b, + 0xac, 0x54, 0xcf, 0xa6, 0x75, 0xaa, 0xeb, 0x40, 0x68, 0xee, 0xe2, 0xb1, 0xa8, 0x70, 0x9e, 0xe9, 0x8b, 0xf1, 0x0a, 0x85, + 0x88, 0x40, 0xef, 0xb8, 0xa5, 0x04, 0x87, 0x63, 0x03, 0xf5, 0x41, 0x81, 0x29, 0x42, 0x7f, 0x31, 0x8f, 0x5b, 0xde, 0xe8, + 0x15, 0xc1, 0xa3, 0x45, 0xf1, 0xbc, 0xff, 0x81, 0x58, 0xbd, 0xac, 0x4c, 0xa5, 0xb3, 0x30, 0x9a, 0xb8, 0x9e, 0x69, 0x10, + 0xad, 0x44, 0x7b, 0x93, 0x28, 0xba, 0xca, 0x6f, 0x2e, 0xf8, 0x1b, 0x03, 0xc2, 0x0a, 0x4a, 0x06, 0x32, 0x4d, 0x30, 0x50, + 0xb7, 0x9c, 0x57, 0x4d, 0x4b, 0x6c, 0x34, 0x53, 0xd8, 0xf5, 0xca, 0x91, 0xa5, 0xdf, 0xa6, 0x67, 0x0a, 0x2e, 0x02, 0x47, + 0x1c, 0x1c, 0xd6, 0x2b, 0xe2, 0x85, 0xc1, 0xda, 0x79, 0xa2, 0xe2, 0x1e, 0xf8, 0x5e, 0xf9, 0x76, 0x55, 0xaf, 0x61, 0xaf, + 0xde, 0x0a, 0x7b, 0xeb, 0xa1, 0xa8, 0xc6, 0xef, 0x76, 0x2f, 0x50, 0xd1, 0x0a, 0xce, 0xdb, 0x14, 0xc3, 0x13, 0x72, 0xe5, + 0x26, 0x67, 0x90, 0x19, 0x15, 0x7b, 0x79, 0x05, 0xeb, 0x20, 0xb3, 0x5a, 0x4e, 0x78, 0xae, 0x2d, 0x9c, 0xd1, 0x31, 0xfd, + 0x2e, 0xcb, 0x84, 0xb9, 0x67, 0xea, 0xaf, 0xb3, 0xc2, 0x5f, 0xf5, 0xcd, 0x7b, 0x66, 0x3f, 0xdf, 0xf7, 0xe7, 0x76, 0x46, + 0x57, 0xd9, 0xee, 0x4b, 0xb2, 0xc8, 0x7b, 0xf9, 0x88, 0xab, 0x8e, 0xca, 0xfc, 0x39, 0xd1, 0x8e, 0x1c, 0xba, 0x3e, 0x63, + 0xb7, 0xe8, 0x0e, 0x2f, 0xde, 0x6b, 0x76, 0x81, 0xbf, 0x78, 0x26, 0x0c, 0xa0, 0x2c, 0x35, 0x21, 0xde, 0xb4, 0x45, 0x0a, + 0x84, 0xea, 0x68, 0xa5, 0x37, 0xe8, 0x4a, 0xbc, 0xa6, 0xcf, 0x24, 0x85, 0x46, 0x33, 0x9e, 0xd9, 0xba, 0x58, 0x75, 0xd7, + 0x45, 0xc2, 0x99, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + /* * MARK: RSA-signed messages (with attributes) */ @@ -726,7 +809,7 @@ unsigned char rsa_sha1_attr[] = { 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x38, 0x31, 0x33, 0x32, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0xef, 0x53, 0x0b, 0xfa, 0xcf, 0x34, 0x18, 0xb3, 0x30, 0xff, 0xf8, 0x9e, 0x09, 0xb3, 0xb6, 0x21, 0xd6, 0x83, 0xb9, 0xe9, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x52, 0xbd, 0xa1, 0x0a, 0x41, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x52, 0xbd, 0xa1, 0x0a, 0x41, 0xce, 0xc1, 0xe8, 0xe8, 0x2f, 0x2e, 0x1f, 0x73, 0xd1, 0x2f, 0x2e, 0x53, 0x53, 0x21, 0xec, 0x88, 0x30, 0x6a, 0x9d, 0x58, 0x64, 0x95, 0xef, 0xf2, 0x20, 0x55, 0xb0, 0x15, 0x64, 0x02, 0x1d, 0xf9, 0x44, 0xdd, 0xcb, 0x7a, 0x9c, 0x50, 0x10, 0xea, 0xfa, 0x6f, 0x07, 0x64, 0xaf, 0x30, 0x6e, 0xe2, 0xc1, 0x34, 0x55, 0xd0, 0x6a, 0x6e, 0xe1, 0x09, 0x91, 0xb7, 0xe3, 0x7b, @@ -814,7 +897,7 @@ unsigned char rsa_sha256_attr[] = { 0x31, 0x33, 0x32, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x33, 0x1f, 0x3a, 0xc4, 0x95, 0x97, 0x64, 0x1c, 0x99, 0x9b, 0x37, 0xc8, 0xf2, 0xba, 0xd0, 0xb4, 0x38, 0xa5, 0x9c, 0x3a, 0xa3, 0x78, 0xf9, 0xfb, 0x66, 0x28, 0x4e, 0x6a, 0x90, 0xcc, 0x0e, 0x4c, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xae, 0x6d, 0xa9, 0xa7, 0xee, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xae, 0x6d, 0xa9, 0xa7, 0xee, 0x0c, 0x94, 0x1b, 0xf3, 0x93, 0x40, 0x43, 0x11, 0x41, 0x20, 0x11, 0x60, 0xd9, 0x4e, 0xb6, 0x2d, 0x3e, 0x98, 0xfe, 0x06, 0xd2, 0xc4, 0xe4, 0x0a, 0x66, 0xdc, 0xbb, 0xbd, 0x4d, 0x8e, 0xcb, 0xe1, 0x87, 0x39, 0x3f, 0xb3, 0x4b, 0xf8, 0xe7, 0x18, 0x6f, 0x39, 0xad, 0x01, 0xd4, 0xe8, 0x85, 0x8c, 0x84, 0x96, 0x2c, 0x3a, 0xd4, 0xcf, 0x3c, 0xe5, 0x05, 0xdd, 0xc7, 0xc0, diff --git a/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c b/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c index 44b57a7d..3abf319c 100644 --- a/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c +++ b/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c @@ -411,8 +411,8 @@ static bool merge_der_in_to_data(const void *der1, size_t der1_len, const void * CFPropertyListRef dict1 = NULL; CFPropertyListRef dict2 = NULL; - der_decode_plist(NULL, kCFPropertyListImmutable, &dict1, NULL, der1, der1 + der1_len); - der_decode_plist(NULL, kCFPropertyListImmutable, &dict2, NULL, der2, der2 + der2_len); + der_decode_plist(NULL, &dict1, NULL, der1, der1 + der1_len); + der_decode_plist(NULL, &dict2, NULL, der2, der2 + der2_len); if (dict1 && dict2) { CFMutableDictionaryRef result_dict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict1); CFDictionaryForEach(dict2, ^(const void *key, const void *value) { @@ -463,7 +463,7 @@ static int aks_crypt_acl(CFTypeRef operation, keybag_handle_t keybag, require_action_string(der, out, aks_return = kAKSReturnError, "aks_ref_key_decrypt failed"); CFPropertyListRef decoded_data = NULL; - der_decode_plist(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_data, NULL, der, der + der_len); + der_decode_plist(kCFAllocatorDefault, &decoded_data, NULL, der, der + der_len); require_action_string(decoded_data, out, aks_return = kAKSReturnError, "der_decode_plist failed"); if (CFGetTypeID(decoded_data) == CFDataGetTypeID()) { CFDataSetLength(dest, 0); diff --git a/OSX/sec/Security/Regressions/vmdh/vmdh-41-example.c b/OSX/sec/Security/Regressions/vmdh/vmdh-41-example.c index 089c59ee..fed52229 100644 --- a/OSX/sec/Security/Regressions/vmdh/vmdh-41-example.c +++ b/OSX/sec/Security/Regressions/vmdh/vmdh-41-example.c @@ -19,16 +19,14 @@ //these are copies of SecDH_gp() and SecDH_priv() static inline ccdh_gp_t vmdh_gp(struct vmdh *dh) { - return (ccdh_gp_t)dh; + return (ccdh_gp_t)dh; } static inline ccdh_full_ctx_t vmdh_priv(struct vmdh *dh) { ccdh_gp_t gp = vmdh_gp(dh); cc_size s = ccn_sizeof_n(ccdh_gp_n(gp)); - ccdh_full_ctx_t priv = (ccdh_full_ctx_t)((char *) dh + ccdh_gp_size(s)); - - return priv; + return (ccdh_full_ctx_t)cc_pad_align((uintptr_t)dh + ccdh_gp_size(s)); } static uint32_t param_g = 5; diff --git a/OSX/sec/Security/Regressions/vmdh/vmdh-42-example2.c b/OSX/sec/Security/Regressions/vmdh/vmdh-42-example2.c index 3c79e75e..ded731c7 100644 --- a/OSX/sec/Security/Regressions/vmdh/vmdh-42-example2.c +++ b/OSX/sec/Security/Regressions/vmdh/vmdh-42-example2.c @@ -19,16 +19,14 @@ //these are copies of SecDH_gp() and SecDH_priv() static inline ccdh_gp_t vmdh_gp(struct vmdh *dh) { - return (ccdh_gp_t)dh; + return (ccdh_gp_t)dh; } static inline ccdh_full_ctx_t vmdh_priv(struct vmdh *dh) { ccdh_gp_t gp = vmdh_gp(dh); cc_size s = ccn_sizeof_n(ccdh_gp_n(gp)); - ccdh_full_ctx_t priv = (ccdh_full_ctx_t)((char *) dh + ccdh_gp_size(s)); - - return priv; + return (ccdh_full_ctx_t)cc_pad_align((uintptr_t)dh + ccdh_gp_size(s)); } static uint32_t param_g = 5; diff --git a/OSX/sec/Security/SecAccessControl.m b/OSX/sec/Security/SecAccessControl.m index 849426be..e9ef95c6 100644 --- a/OSX/sec/Security/SecAccessControl.m +++ b/OSX/sec/Security/SecAccessControl.m @@ -52,11 +52,23 @@ static void dumpValue(id value, NSMutableString *target, NSString *separator) { if (value == nil) { // Do nothing. } else if (CFGetTypeID((__bridge CFTypeRef)value) == CFBooleanGetTypeID()) { - [target appendString:[value boolValue] ? @"true" : @"false"]; + NSNumber *boolValue = value; + [target appendString:boolValue.boolValue ? @"true" : @"false"]; } else if ([value isKindOfClass:NSNumber.class]) { - [target appendString:[value string]]; + NSNumber *numberValue = value; + [target appendString:numberValue.stringValue]; } else if ([value isKindOfClass:NSString.class]) { [target appendString:value]; + } else if ([value isKindOfClass:NSData.class]) { + NSData *dataValue = value; + const uint8_t *dataBuffer = dataValue.bytes; + NSUInteger dumpLength = dataValue.length > 64 ? 64 : dataValue.length; + for (NSUInteger i = 0; i < dumpLength; i++) { + [target appendFormat:@"%02X", (unsigned)dataBuffer[i]]; + } + if (dumpLength < dataValue.length) { + [target appendFormat:@"...(%db)", (int)dataValue.length]; + } } else if ([value isKindOfClass:NSDictionary.class]) { [value enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { [target appendString:separator]; @@ -466,7 +478,7 @@ SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFD CFPropertyListRef plist; const uint8_t *der = CFDataGetBytePtr(data); const uint8_t *der_end = der + CFDataGetLength(data); - require_quiet(der = der_decode_plist(0, kCFPropertyListMutableContainers, &plist, error, der, der_end), errOut); + require_quiet(der = der_decode_plist(0, &plist, error, der, der_end), errOut); if (der != der_end) { SecError(errSecDecode, error, CFSTR("trailing garbage at end of SecAccessControl data")); goto errOut; diff --git a/OSX/sec/Security/SecBase64.c b/OSX/sec/Security/SecBase64.c index b92d8dba..1c67bb98 100644 --- a/OSX/sec/Security/SecBase64.c +++ b/OSX/sec/Security/SecBase64.c @@ -43,7 +43,7 @@ #include "SecBase64.h" -#include +#include #include #include diff --git a/OSX/sec/Security/SecCTKKey.m b/OSX/sec/Security/SecCTKKey.m index 5ebebb06..fd0a9a6f 100644 --- a/OSX/sec/Security/SecCTKKey.m +++ b/OSX/sec/Security/SecCTKKey.m @@ -36,6 +36,7 @@ #include #include #include +#include #include "OSX/sec/Security/SecItemShim.h" #include "SecECKey.h" @@ -321,7 +322,7 @@ static Boolean SecCTKKeySetParameter(SecKeyRef key, CFStringRef name, CFProperty if (CFEqual(name, kSecUseAuthenticationContext)) { // Preprocess LAContext to ACMRef value. if (value != NULL) { - require_quiet(acm_reference = SecItemAttributesCopyPreparedAuthContext(value, error), out); + require_quiet(acm_reference = LACopyACMContext(value, error), out); value = acm_reference; } name = kSecUseCredentialReference; @@ -352,6 +353,13 @@ out: return TRUE; } +static Boolean SecCTKKeyIsEqual(SecKeyRef key1, SecKeyRef key2) { + SecCTKKeyData *kd1 = key1->key; + SecCTKKeyData *kd2 = key2->key; + + return CFEqual(kd1->token_id, kd2->token_id) && CFEqual(kd1->object_id, kd2->object_id); +} + static SecKeyDescriptor kSecCTKKeyDescriptor = { .version = kSecKeyDescriptorVersion, .name = "CTKKey", @@ -364,6 +372,7 @@ static SecKeyDescriptor kSecCTKKeyDescriptor = { .getAlgorithmID = SecCTKGetAlgorithmID, .copyPublic = SecCTKKeyCopyPublicOctets, .copyOperationResult = SecCTKKeyCopyOperationResult, + .isEqual = SecCTKKeyIsEqual, .createDuplicate = SecCTKKeyCreateDuplicate, .setParameter = SecCTKKeySetParameter, }; @@ -400,14 +409,6 @@ SecKeyRef SecKeyCreateCTKKey(CFAllocatorRef allocator, CFDictionaryRef refAttrib CFDictionarySetValue(SecCFDictionaryCOWGetMutable(&kd->attributes), kSecAttrIsPrivate, kCFBooleanTrue); } - // Convert some attributes which are stored as numbers in iOS keychain but a lot of code counts that the values - // are actually strings as specified by kSecAttrXxx constants. - static const CFStringRef *numericAttributes[] = { - &kSecAttrKeyType, - &kSecAttrKeyClass, - NULL, - }; - CFMutableDictionaryRef attrs = NULL; if (kd->token == NULL) { require_quiet(kd->token = SecCTKKeyCopyToken(key, error), out); @@ -431,6 +432,14 @@ SecKeyRef SecKeyCreateCTKKey(CFAllocatorRef allocator, CFDictionaryRef refAttrib require_quiet(kd->token != NULL && kd->object_id != NULL, out); } + // Convert some attributes which are stored as numbers in iOS keychain but a lot of code counts that the values + // are actually strings as specified by kSecAttrXxx constants. + static const CFStringRef *numericAttributes[] = { + &kSecAttrKeyType, + &kSecAttrKeyClass, + NULL, + }; + for (const CFStringRef **attrName = &numericAttributes[0]; *attrName != NULL; attrName++) { CFTypeRef value = CFDictionaryGetValue(kd->attributes.dictionary, **attrName); if (value != NULL && CFGetTypeID(value) == CFNumberGetTypeID()) { @@ -444,6 +453,11 @@ SecKeyRef SecKeyCreateCTKKey(CFAllocatorRef allocator, CFDictionaryRef refAttrib } } } + + // Sanitize some important attributes. + CFDictionarySetValue(SecCFDictionaryCOWGetMutable(&kd->attributes), kSecClass, kSecClassKey); + CFDictionarySetValue(SecCFDictionaryCOWGetMutable(&kd->attributes), kSecAttrKeyClass, kSecAttrKeyClassPrivate); + result = (SecKeyRef)CFRetain(key); out: @@ -522,7 +536,17 @@ SecKeyRef SecKeyCopyAttestationKey(SecKeyAttestationKeyType keyType, CFErrorRef static const uint8_t uikProposedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'u', 'i', 'k', 'p' }; static const uint8_t casdObjectIDBytes[] = { 0x04, 27, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 'c', 'e', 'l', 'e', 'm', 't', 'o', 'k', 'e', 'n', '.', 'c', 'a', 's', 'd' }; - + + // [[TKTLVBERRecord alloc] initWithPropertyList:[@"com.apple.setoken.oikc" dataUsingEncoding:NSUTF8StringEncoding]].data + static const uint8_t oikCommittedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'o', 'i', 'k', 'c' }; + // [[TKTLVBERRecord alloc] initWithPropertyList:[@"com.apple.setoken.oikp" dataUsingEncoding:NSUTF8StringEncoding]].data + static const uint8_t oikProposedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'o', 'i', 'k', 'p' }; + + // [[TKTLVBERRecord alloc] initWithPropertyList:[@"com.apple.setoken.dakc" dataUsingEncoding:NSUTF8StringEncoding]].data + static const uint8_t dakCommittedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'd', 'a', 'k', 'c' }; + // [[TKTLVBERRecord alloc] initWithPropertyList:[@"com.apple.setoken.dakp" dataUsingEncoding:NSUTF8StringEncoding]].data + static const uint8_t dakProposedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'd', 'a', 'k', 'p' }; + CFStringRef token = kSecAttrTokenIDAppleKeyStore; switch (keyType) { @@ -542,6 +566,18 @@ SecKeyRef SecKeyCopyAttestationKey(SecKeyAttestationKeyType keyType, CFErrorRef object_id = CFDataCreate(kCFAllocatorDefault, casdObjectIDBytes, sizeof(casdObjectIDBytes)); token = kSecAttrTokenIDSecureElement; break; + case kSecKeyAttestationKeyTypeOIKCommitted: + object_id = CFDataCreate(kCFAllocatorDefault, oikCommittedObjectIDBytes, sizeof(uikCommittedObjectIDBytes)); + break; + case kSecKeyAttestationKeyTypeOIKProposed: + object_id = CFDataCreate(kCFAllocatorDefault, oikProposedObjectIDBytes, sizeof(uikProposedObjectIDBytes)); + break; + case kSecKeyAttestationKeyTypeDAKCommitted: + object_id = CFDataCreate(kCFAllocatorDefault, dakCommittedObjectIDBytes, sizeof(uikCommittedObjectIDBytes)); + break; + case kSecKeyAttestationKeyTypeDAKProposed: + object_id = CFDataCreate(kCFAllocatorDefault, dakProposedObjectIDBytes, sizeof(uikProposedObjectIDBytes)); + break; default: SecError(errSecParam, error, CFSTR("unexpected attestation key type %d"), (int)keyType); goto out; @@ -638,10 +674,6 @@ Boolean SecKeyControlLifetime(SecKeyRef key, SecKeyControlLifetimeType type, CFE }, NULL); } -#if TKTOKEN_CLIENT_INTERFACE_VERSION < 5 -#define kTKTokenCreateAttributeTestMode "testmode" -#endif - void SecCTKKeySetTestMode(CFStringRef tokenID, CFTypeRef enable) { CFErrorRef error = NULL; CFDictionaryRef options = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecAttrTokenID, tokenID, @kTKTokenCreateAttributeTestMode, enable, nil); diff --git a/OSX/sec/Security/SecCertificate.c b/OSX/sec/Security/SecCertificate.c index 269b4388..d9571455 100644 --- a/OSX/sec/Security/SecCertificate.c +++ b/OSX/sec/Security/SecCertificate.c @@ -71,9 +71,8 @@ #include "AppleiPhoneDeviceCACertificates.h" #include #include -#ifdef DARLING -#include -#endif +#include "AppleExternalRootCertificates.h" +#include #pragma clang diagnostic ignored "-Wformat=2" @@ -88,6 +87,14 @@ #define IPv4ADDRLEN 4 // 4 octets #define IPv6ADDRLEN 16 // 16 octets +#define MAX_EXTENSIONS 10000 +#define MAX_ATTRIBUTE_TYPE_AND_VALUES 1024 +#define MAX_CRL_DPS 1024 +#define MAX_CERTIFICATE_POLICIES 8192 +#define MAX_POLICY_MAPPINGS 8192 +#define MAX_EKUS 8192 +#define MAX_AIAS 1024 + typedef struct SecCertificateExtension { DERItem extnID; bool critical; @@ -303,8 +310,6 @@ static CFHashCode SecCertificateHash(CFTypeRef cf) { return (hashCode + der_length + sig_length); } -#if 1 - /************************************************************************/ /************************* General Name Parsing *************************/ /************************************************************************/ @@ -393,159 +398,15 @@ OSStatus SecCertificateParseGeneralNames(const DERItem *generalNames, void *cont DERDecodedInfo generalNamesContent; DERReturn drtn = DERDecodeItem(generalNames, &generalNamesContent); require_noerr_quiet(drtn, badDER); + // GeneralNames ::= SEQUENCE SIZE (1..MAX) require_quiet(generalNamesContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + require_quiet(generalNamesContent.content.length > 0, badDER); // not defining a max due to use of large number of SANs return parseGeneralNamesContent(&generalNamesContent.content, context, callback); badDER: return errSecInvalidCertificate; } -#else - -/* - GeneralName ::= CHOICE { - otherName [0] OtherName, - rfc822Name [1] IA5String, - dNSName [2] IA5String, - x400Address [3] ORAddress, - directoryName [4] Name, - ediPartyName [5] EDIPartyName, - uniformResourceIdentifier [6] IA5String, - iPAddress [7] OCTET STRING, - registeredID [8] OBJECT IDENTIFIER} - - EDIPartyName ::= SEQUENCE { - nameAssigner [0] DirectoryString OPTIONAL, - partyName [1] DirectoryString } - */ -static OSStatus parseGeneralNameContentProperty(DERTag tag, - const DERItem *generalNameContent, SecCEGeneralName *generalName) { - switch (tag) { - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0: - generalName->nameType = GNT_OtherName; - generalName->berEncoded = true; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | 1: - /* IA5String. */ - generalName->nameType = GNT_RFC822Name; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | 2: - /* IA5String. */ - generalName->nameType = GNT_DNSName; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3: - generalName->nameType = GNT_X400Address; - generalName->berEncoded = true; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 4: - generalName->nameType = GNT_DirectoryName; - generalName->berEncoded = true; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 5: - generalName->nameType = GNT_EdiPartyName; - generalName->berEncoded = true; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 6: - { - /* Technically I don't think this is valid, but there are certs out - in the wild that use a constructed IA5String. In particular the - VeriSign Time Stamping Authority CA.cer does this. */ - DERDecodedInfo decoded; - require_noerr(DERDecodeItem(generalNameContent, &decoded), badDER); - require(decoded.tag == ASN1_IA5_STRING, badDER); - generalName->nameType = GNT_URI; - generalName->berEncoded = false; - generalName->name = decoded.content; - break; - } - case ASN1_CONTEXT_SPECIFIC | 6: - generalName->nameType = GNT_URI; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | 7: - /* @@@ This is the IP Address as an OCTECT STRING. For IPv4 it's - 8 octects, addr/mask for ipv6 it's 32. */ - generalName->nameType = GNT_IPAddress; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | 8: - /* name is the content of an OID. */ - generalName->nameType = GNT_RegisteredID; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - default: - goto badDER; - break; - } - return errSecSuccess; -badDER: - return errSecInvalidCertificate; -} - -/* - GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - */ -static OSStatus parseGeneralNamesContent(const DERItem *generalNamesContent, - CFIndex *count, SecCEGeneralName **name) { - SecCEGeneralName *generalNames = NULL; - DERSequence gnSeq; - DERReturn drtn = DERDecodeSeqContentInit(generalNamesContent, &gnSeq); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo generalNameContent; - CFIndex generalNamesCount = 0; - while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == - DR_Success) { - ++generalNamesCount; - } - require_quiet(drtn == DR_EndOfSequence, badDER); - - require(generalNames = calloc(generalNamesCount, sizeof(SecCEGeneralName)), - badDER); - DERDecodeSeqContentInit(generalNamesContent, &gnSeq); - CFIndex ix = 0; - while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == - DR_Success) { - if (!parseGeneralNameContentProperty(generalNameContent.tag, - &generalNameContent.content, &generalNames[ix])) { - goto badDER; - } - ++ix; - } - *count = generalNamesCount; - *name = generalNames; - return errSecSuccess; - -badDER: - if (generalNames) - free(generalNames); - return errSecInvalidCertificate; -} - -static OSStatus parseGeneralNames(const DERItem *generalNames, - CFIndex *count, SecCEGeneralName **name) { - DERDecodedInfo generalNamesContent; - DERReturn drtn = DERDecodeItem(generalNames, &generalNamesContent); - require_noerr_quiet(drtn, badDER); - require_quiet(generalNamesContent.tag == ASN1_CONSTR_SEQUENCE, - badDER); - parseGeneralNamesContent(&generalNamesContent.content, count, name); - return errSecSuccess; -badDER: - return errSecInvalidCertificate; -} -#endif - /************************************************************************/ /************************** X.509 Name Parsing **************************/ /************************************************************************/ @@ -582,25 +443,30 @@ badDER: } static OSStatus parseX501NameContent(const DERItem *x501NameContent, void *context, - parseX501NameCallback callback, bool localized) { - DERSequence derSeq; - DERReturn drtn = DERDecodeSeqContentInit(x501NameContent, &derSeq); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo currDecoded; - while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { - require_quiet(currDecoded.tag == ASN1_CONSTR_SET, badDER); - OSStatus status = parseRDNContent(&currDecoded.content, context, - callback, localized); - if (status) { - return status; - } - } - require_quiet(drtn == DR_EndOfSequence, badDER); + parseX501NameCallback callback, bool localized) { + DERSequence derSeq; + DERReturn drtn = DERDecodeSeqContentInit(x501NameContent, &derSeq); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo currDecoded; + int atv_count = 0; + while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { + /* RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue */ + require_quiet(currDecoded.tag == ASN1_CONSTR_SET, badDER); + require_quiet(currDecoded.content.length > 0, badDER); + OSStatus status = parseRDNContent(&currDecoded.content, context, + callback, localized); + if (status) { + return status; + } + atv_count++; + require_quiet(atv_count < MAX_ATTRIBUTE_TYPE_AND_VALUES, badDER); + } + require_quiet(drtn == DR_EndOfSequence, badDER); - return errSecSuccess; + return errSecSuccess; badDER: - return errSecInvalidCertificate; + return errSecInvalidCertificate; } static OSStatus parseX501Name(const DERItem *x501Name, void *context, @@ -679,11 +545,23 @@ static bool SecCEPPrivateKeyUsagePeriod(SecCertificateRef certificate, return true; } +static OSStatus verifySubjectAltGeneralName(void *context, SecCEGeneralNameType type, + const DERItem *value) { + // Nothing to do for now + return errSecSuccess; +} + static bool SecCEPSubjectAltName(SecCertificateRef certificate, const SecCertificateExtension *extn) { secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + // Make sure that the SAN is parse-able + require_noerr_quiet(SecCertificateParseGeneralNames(&extn->extnValue, NULL, verifySubjectAltGeneralName), badDER); certificate->_subjectAltName = extn; return true; +badDER: + certificate->_subjectAltName = NULL; + secwarning("Invalid SubjectAltName Extension"); + return false; } static bool SecCEPIssuerAltName(SecCertificateRef certificate, @@ -852,7 +730,9 @@ static bool SecCEPCrlDistributionPoints(SecCertificateRef certificate, DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &crlDPSeq); require_noerr_quiet(drtn, badDER); require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + require_quiet(crlDPSeq.nextItem != crlDPSeq.end, badDER); DERDecodedInfo dpContent; + int crldp_count = 0; while ((drtn = DERDecodeSeqNext(&crlDPSeq, &dpContent)) == DR_Success) { require_quiet(dpContent.tag == ASN1_CONSTR_SEQUENCE, badDER); DERDistributionPoint dp; @@ -882,6 +762,8 @@ static bool SecCEPCrlDistributionPoints(SecCertificateRef certificate, appendCRLDPFromGeneralNames); require_noerr_quiet(drtn, badDER); } + crldp_count++; + require_quiet(crldp_count < MAX_CRL_DPS, badDER); } require_quiet(drtn == DR_EndOfSequence, badDER); return true; @@ -904,8 +786,6 @@ badDER: policyQualifierId PolicyQualifierId, qualifier ANY DEFINED BY policyQualifierId } */ -/* maximum number of policies of 8192 seems more than adequate */ -#define MAX_CERTIFICATE_POLICIES 8192 static bool SecCEPCertificatePolicies(SecCertificateRef certificate, const SecCertificateExtension *extn) { secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); @@ -923,14 +803,14 @@ static bool SecCEPCertificatePolicies(SecCertificateRef certificate, policy_count++; } require_quiet(drtn == DR_EndOfSequence, badDER); - require_quiet(policies = (SecCEPolicyInformation *)malloc(sizeof(SecCEPolicyInformation) - * (policy_count > 0 ? policy_count : 1)), + require_quiet(policy_count > 0, badDER); + require_quiet(policies = (SecCEPolicyInformation *)malloc(sizeof(SecCEPolicyInformation) * policy_count), badDER); drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &piSeq); require_noerr_quiet(drtn, badDER); DERSize policy_ix = 0; - while ((policy_ix < (policy_count > 0 ? policy_count : 1)) && - (drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { + while ((policy_ix < policy_count) && + (DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { DERPolicyInformation pi; drtn = DERParseSequenceContent(&piContent.content, DERNumPolicyInformationItemSpecs, @@ -960,7 +840,6 @@ badDER: issuerDomainPolicy CertPolicyId, subjectDomainPolicy CertPolicyId } */ -#define MAX_POLICY_MAPPINGS 8192 static bool SecCEPPolicyMappings(SecCertificateRef certificate, const SecCertificateExtension *extn) { secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); @@ -978,14 +857,14 @@ static bool SecCEPPolicyMappings(SecCertificateRef certificate, mapping_count++; } require_quiet(drtn == DR_EndOfSequence, badDER); - require_quiet(mappings = (SecCEPolicyMapping *)malloc(sizeof(SecCEPolicyMapping) - * (mapping_count > 0 ? mapping_count : 1)), + require_quiet(mapping_count > 0, badDER); // PolicyMappings ::= SEQUENCE SIZE (1..MAX) + require_quiet(mappings = (SecCEPolicyMapping *)malloc(sizeof(SecCEPolicyMapping) * mapping_count), badDER); drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &pmSeq); require_noerr_quiet(drtn, badDER); DERSize mapping_ix = 0; - while ((mapping_ix < (mapping_count > 0 ? mapping_count : 1)) && - (drtn = DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { + while ((mapping_ix < mapping_count) && + (DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { require_quiet(pmContent.tag == ASN1_CONSTR_SEQUENCE, badDER); DERPolicyMapping pm; drtn = DERParseSequenceContent(&pmContent.content, @@ -1006,7 +885,7 @@ badDER: free(mappings); } certificate->_policyMappings.present = false; - secwarning("Invalid CertificatePolicies Extension"); + secwarning("Invalid PolicyMappings Extension"); return false; } @@ -1088,9 +967,13 @@ static bool SecCEPExtendedKeyUsage(SecCertificateRef certificate, DERTag ekuTag; DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &ekuTag, &ekuSeq); require_quiet((drtn == DR_Success) && (ekuTag == ASN1_CONSTR_SEQUENCE), badDER); + require_quiet(ekuSeq.nextItem != ekuSeq.end, badDER); // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId DERDecodedInfo ekuContent; + int eku_count = 0; while ((drtn = DERDecodeSeqNext(&ekuSeq, &ekuContent)) == DR_Success) { require_quiet(ekuContent.tag == ASN1_OBJECT_ID, badDER); + eku_count++; + require_quiet(eku_count < MAX_EKUS, badDER); } require_quiet(drtn == DR_EndOfSequence, badDER); return true; @@ -1147,7 +1030,9 @@ static bool SecCEPAuthorityInfoAccess(SecCertificateRef certificate, DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &adSeq); require_noerr_quiet(drtn, badDER); require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + require_quiet(adSeq.nextItem != adSeq.end, badDER); DERDecodedInfo adContent; + int aia_count = 0; while ((drtn = DERDecodeSeqNext(&adSeq, &adContent)) == DR_Success) { require_quiet(adContent.tag == ASN1_CONSTR_SEQUENCE, badDER); DERAccessDescription ad; @@ -1156,6 +1041,8 @@ static bool SecCEPAuthorityInfoAccess(SecCertificateRef certificate, DERAccessDescriptionItemSpecs, &ad, sizeof(ad)); require_noerr_quiet(drtn, badDER); + aia_count++; + require_quiet(aia_count < MAX_AIAS, badDER); CFMutableArrayRef *urls; if (DEROidCompare(&ad.accessMethod, &oidAdOCSP)) urls = &certificate->_ocspResponders; @@ -1362,13 +1249,28 @@ static bool isAppleExtensionOID(const DERItem *extnID) static const uint8_t appleComponentExtensionArc[8] = { 0x2a,0x86,0x48,0x86,0xf7,0x63,0x64,0x0b }; static const uint8_t appleSigningExtensionArc[8] = { 0x2a,0x86,0x48,0x86,0xf7,0x63,0x64,0x0c }; static const uint8_t appleEncryptionExtensionArc[8] = { 0x2a,0x86,0x48,0x86,0xf7,0x63,0x64,0x0d }; - if (!extnID && !extnID->data && extnID->length <= sizeof(appleExtensionArc)) { + static const uint8_t appleExternalEncryptionExtensionArc[8] = { 0x2a,0x86,0x48,0x86,0xf7,0x63,0x64,0x0f }; + if (!extnID || !extnID->data || (extnID->length <= sizeof(appleExtensionArc))) { return false; } return (!memcmp(extnID->data, appleExtensionArc, sizeof(appleExtensionArc)) || !memcmp(extnID->data, appleComponentExtensionArc, sizeof(appleComponentExtensionArc)) || !memcmp(extnID->data, appleSigningExtensionArc, sizeof(appleSigningExtensionArc)) || - !memcmp(extnID->data, appleEncryptionExtensionArc, sizeof(appleEncryptionExtensionArc))); + !memcmp(extnID->data, appleEncryptionExtensionArc, sizeof(appleEncryptionExtensionArc)) || + !memcmp(extnID->data, appleExternalEncryptionExtensionArc, sizeof(appleExternalEncryptionExtensionArc))); +} + +static bool isCCCExtensionOID(const DERItem *extnID) +{ + static const uint8_t cccVehicleCA[] = { 0x2B,0x06,0x01,0x04,0x01,0x82,0xC4,0x69,0x05,0x09 }; + static const uint8_t cccIntermediateCA[] = { 0x2B,0x06,0x01,0x04,0x01,0x82,0xC4,0x69,0x05,0x08 }; + static const uint8_t cccVehicle[] = { 0x2B,0x06,0x01,0x04,0x01,0x82,0xC4,0x69,0x05,0x01 }; + if (!extnID || !extnID->data || (extnID->length != sizeof(cccVehicleCA))) { + return false; + } + return (!memcmp(extnID->data, cccVehicleCA, sizeof(cccVehicleCA)) || + !memcmp(extnID->data, cccIntermediateCA, sizeof(cccIntermediateCA)) || + !memcmp(extnID->data, cccVehicle, sizeof(cccVehicle))); } /* Given the contents of an X.501 Name return the contents of a normalized @@ -1742,11 +1644,7 @@ static bool SecCertificateParse(SecCertificateRef certificate) /* sequence we're given: encoded DERSubjPubKeyInfo */ DERSubjPubKeyInfo pubKeyInfo; -#ifdef DARLING - drtn = DERParseSequence(&tbsCert.subjectPubKey, -#else drtn = DERParseSequenceContent(&tbsCert.subjectPubKey, -#endif DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, &pubKeyInfo, sizeof(pubKeyInfo)); require_noerr_quiet(drtn, badCert); @@ -1812,9 +1710,10 @@ static bool SecCertificateParse(SecCertificateRef certificate) extensionCount++; } require_quiet(drtn == DR_EndOfSequence, badCert); + require_quiet(extensionCount > 0, badCert); // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension /* Put some upper limit on the number of extensions allowed. */ - require_quiet(extensionCount < 10000, badCert); + require_quiet(extensionCount < MAX_EXTENSIONS, badCert); certificate->_extensionCount = extensionCount; certificate->_extensions = malloc(sizeof(SecCertificateExtension) * (extensionCount > 0 ? extensionCount : 1)); require_quiet(certificate->_extensions, badCert); @@ -1848,7 +1747,7 @@ static bool SecCertificateParse(SecCertificateRef certificate) } require_quiet(parseResult || !certificate->_extensions[ix].critical, badCert); } else if (certificate->_extensions[ix].critical) { - if (isAppleExtensionOID(&extn.extnID)) { + if (isAppleExtensionOID(&extn.extnID) || isCCCExtensionOID(&extn.extnID)) { continue; } secdebug("cert", "Found unknown critical extension"); @@ -3002,7 +2901,7 @@ static void appendSerialNumberProperty(CFMutableArrayRef parent, CFStringRef lab static void appendBitStringContentNames(CFMutableArrayRef properties, CFStringRef label, const DERItem *bitStringContent, - const CFStringRef *names, CFIndex namesCount, + const __nonnull CFStringRef *names, CFIndex namesCount, bool localized) { DERSize len = bitStringContent->length - 1; require_quiet(len == 1 || len == 2, badDER); @@ -3033,7 +2932,7 @@ static void appendBitStringContentNames(CFMutableArrayRef properties, string = s; } else { string = localizedName; - CFRetain(string); + CFRetainSafe(string); } } mask >>= 1; @@ -3050,7 +2949,7 @@ badDER: static void appendBitStringNames(CFMutableArrayRef properties, CFStringRef label, const DERItem *bitString, - const CFStringRef *names, CFIndex namesCount, + const __nonnull CFStringRef *names, CFIndex namesCount, bool localized) { DERDecodedInfo bitStringContent; DERReturn drtn = DERDecodeItem(bitString, &bitStringContent); @@ -4423,10 +4322,20 @@ CFDataRef SecCertificateCopySerialNumberData( return certificate->_serialNumber; } +#if TARGET_OS_OSX && TARGET_CPU_ARM64 +/* force this implementation to be _SecCertificateCopySerialNumber on arm64 macOS. + note: the legacy function in SecCertificate.cpp is now _SecCertificateCopySerialNumber$LEGACYMAC + when both TARGET_OS_OSX and TARGET_CPU_ARM64 are true. + */ +extern CFDataRef SecCertificateCopySerialNumber_ios(SecCertificateRef certificate) __asm("_SecCertificateCopySerialNumber"); +CFDataRef SecCertificateCopySerialNumber_ios(SecCertificateRef certificate) { + return SecCertificateCopySerialNumberData(certificate, NULL); +} +#endif + #if !TARGET_OS_OSX -/* On iOS, the SecCertificateCopySerialNumber API takes one argument. */ -CFDataRef SecCertificateCopySerialNumber( - SecCertificateRef certificate) { +CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate) +{ return SecCertificateCopySerialNumberData(certificate, NULL); } #endif @@ -4647,52 +4556,13 @@ CFDataRef SecFrameworkCopyIPAddressData(CFStringRef string) { return data; } -static OSStatus appendIPAddressesFromGeneralNames(void *context, - SecCEGeneralNameType gnType, const DERItem *generalName) { - CFMutableArrayRef ipAddresses = (CFMutableArrayRef)context; - if (gnType == GNT_IPAddress) { - CFStringRef string = copyIPAddressContentDescription( - kCFAllocatorDefault, generalName); - if (string) { - CFArrayAppendValue(ipAddresses, string); - CFRelease(string); - } else { - return errSecInvalidCertificate; - } - } - return errSecSuccess; -} - -CFArrayRef SecCertificateCopyIPAddresses(SecCertificateRef certificate) { - /* These can only exist in the subject alt name. */ - if (!certificate->_subjectAltName) - return NULL; - - CFMutableArrayRef ipAddresses = CFArrayCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeArrayCallBacks); - OSStatus status = SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, - ipAddresses, appendIPAddressesFromGeneralNames); - if (status || CFArrayGetCount(ipAddresses) == 0) { - CFRelease(ipAddresses); - ipAddresses = NULL; - } - return ipAddresses; -} - -static OSStatus appendIPAddressesFromX501Name(void *context, const DERItem *type, - const DERItem *value, CFIndex rdnIX, - bool localized) { - CFMutableArrayRef addrs = (CFMutableArrayRef)context; - if (DEROidCompare(type, &oidCommonName)) { - CFStringRef string = copyDERThingDescription(kCFAllocatorDefault, - value, true, localized); - if (string) { - CFDataRef data = NULL; - if (convertIPAddress(string, &data)) { - CFArrayAppendValue(addrs, data); - CFReleaseNull(data); - } - CFRelease(string); +static OSStatus appendIPAddressesFromGeneralNames(void *context, SecCEGeneralNameType gnType, const DERItem *generalName) { + CFMutableArrayRef ipAddresses = (CFMutableArrayRef)context; + if (gnType == GNT_IPAddress) { + if (generalName->length == IPv4ADDRLEN || generalName->length == IPv6ADDRLEN) { + CFDataRef address = CFDataCreate(NULL, generalName->data, generalName->length); + CFArrayAppendValue(ipAddresses, address); + CFReleaseNull(address); } else { return errSecInvalidCertificate; } @@ -4700,16 +4570,45 @@ static OSStatus appendIPAddressesFromX501Name(void *context, const DERItem *type return errSecSuccess; } -CFArrayRef SecCertificateCopyIPAddressesFromSubject(SecCertificateRef certificate) { - CFMutableArrayRef addrs = CFArrayCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeArrayCallBacks); - OSStatus status = parseX501NameContent(&certificate->_subject, addrs, - appendIPAddressesFromX501Name, true); - if (status || CFArrayGetCount(addrs) == 0) { - CFReleaseNull(addrs); +CFArrayRef SecCertificateCopyIPAddresses(SecCertificateRef certificate) { + CFArrayRef ipAddresses = SecCertificateCopyIPAddressDatas(certificate); + if (!ipAddresses) { return NULL; } - return addrs; + + // Convert data IP addresses to strings + __block CFMutableArrayRef result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayForEach(ipAddresses, ^(const void *value) { + CFDataRef address = (CFDataRef)value; + DERItem der_address = { (unsigned char *)CFDataGetBytePtr(address), CFDataGetLength(address) }; + CFStringRef string = copyIPAddressContentDescription(NULL, &der_address); + if (string) { + CFArrayAppendValue(result, string); + CFRelease(string); + } + }); + CFReleaseNull(ipAddresses); + if (CFArrayGetCount(result) == 0) { + CFReleaseNull(result); + } + + return result; +} + +CFArrayRef SecCertificateCopyIPAddressDatas(SecCertificateRef certificate) { + /* These can only exist in the subject alt name. */ + if (!certificate->_subjectAltName) + return NULL; + + CFMutableArrayRef ipAddresses = CFArrayCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeArrayCallBacks); + OSStatus status = SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, + ipAddresses, appendIPAddressesFromGeneralNames); + if (status || CFArrayGetCount(ipAddresses) == 0) { + CFRelease(ipAddresses); + ipAddresses = NULL; + } + return ipAddresses; } static OSStatus appendDNSNamesFromGeneralNames(void *context, SecCEGeneralNameType gnType, @@ -4834,21 +4733,12 @@ static OSStatus appendDNSNamesFromX501Name(void *context, const DERItem *type, return errSecSuccess; } -CFArrayRef SecCertificateCopyDNSNamesFromSubject(SecCertificateRef certificate) { - CFMutableArrayRef dnsNames = CFArrayCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeArrayCallBacks); - OSStatus status = parseX501NameContent(&certificate->_subject, dnsNames, - appendDNSNamesFromX501Name, true); - if (status || CFArrayGetCount(dnsNames) == 0) { - CFReleaseNull(dnsNames); - return NULL; - } - - /* appendDNSNamesFromX501Name allows IP addresses, we don't want those for this function */ +static CF_RETURNS_RETAINED CFArrayRef filterIPAddresses(CFArrayRef CF_CONSUMED dnsNames) +{ __block CFMutableArrayRef result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFArrayForEach(dnsNames, ^(const void *value) { CFStringRef name = (CFStringRef)value; - if (!convertIPAddress(name, NULL)) { + if (!SecFrameworkIsIPAddress(name)) { CFArrayAppendValue(result, name); } }); @@ -4863,50 +4753,56 @@ CFArrayRef SecCertificateCopyDNSNamesFromSubject(SecCertificateRef certificate) CFArrayRef SecCertificateCopyDNSNamesFromSAN(SecCertificateRef certificate) { CFMutableArrayRef dnsNames = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - OSStatus status = errSecSuccess; if (certificate->_subjectAltName) { - status = SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, - dnsNames, appendDNSNamesFromGeneralNames); + if (SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, + dnsNames, appendDNSNamesFromGeneralNames) != errSecSuccess) { + CFReleaseNull(dnsNames); + return NULL; + } } - if (status || CFArrayGetCount(dnsNames) == 0) { - CFReleaseNull(dnsNames); - } - return dnsNames; + /* appendDNSNamesFromGeneralNames allows IP addresses, we don't want those for this function */ + return filterIPAddresses(dnsNames); } /* Not everything returned by this function is going to be a proper DNS name, we also return the certificates common name entries from the subject, - assuming they look like dns names as specified in RFC 1035. */ + assuming they look like dns names as specified in RFC 1035. + + To preserve bug for bug compatibility, we can't use SecCertificateCopyDNSNamesFromSAN + because that function filters out IP Addresses. This function is Private, but + SecCertificateCopyValues uses it and that's Public. */ CFArrayRef SecCertificateCopyDNSNames(SecCertificateRef certificate) { - /* These can exist in the subject alt name or in the subject. */ - CFArrayRef sanNames = SecCertificateCopyDNSNamesFromSAN(certificate); - if (sanNames && CFArrayGetCount(sanNames) > 0) { - return sanNames; + /* RFC 2818 section 3.1. Server Identity + [...] + If a subjectAltName extension of type dNSName is present, that MUST + be used as the identity. Otherwise, the (most specific) Common Name + field in the Subject field of the certificate MUST be used. Although + the use of the Common Name is existing practice, it is deprecated and + Certification Authorities are encouraged to use the dNSName instead. + [...] + + This implies that if we found 1 or more DNSNames in the + subjectAltName, we should not use the Common Name of the subject as + a DNSName. + */ + + /* return SAN DNS names if they exist */ + if (certificate->_subjectAltName) { + CFMutableArrayRef sanNames = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + OSStatus status = SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, + sanNames, appendDNSNamesFromGeneralNames); + if (status == errSecSuccess && sanNames && CFArrayGetCount(sanNames) > 0) { + return sanNames; + } + CFReleaseNull(sanNames); } - CFReleaseNull(sanNames); - /* RFC 2818 section 3.1. Server Identity - [...] - If a subjectAltName extension of type dNSName is present, that MUST - be used as the identity. Otherwise, the (most specific) Common Name - field in the Subject field of the certificate MUST be used. Although - the use of the Common Name is existing practice, it is deprecated and - Certification Authorities are encouraged to use the dNSName instead. - [...] - - This implies that if we found 1 or more DNSNames in the - subjectAltName, we should not use the Common Name of the subject as - a DNSName. - */ - - /* To preserve bug for bug compatibility, we can't use SecCertificateCopyDNSNamesFromSubject - * because that function filters out IP Addresses. This function is Private, but - * SecCertificateCopyValues uses it and that's Public. */ + /* fall back to return DNS names in the Common Name */ CFMutableArrayRef dnsNames = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); OSStatus status = parseX501NameContent(&certificate->_subject, dnsNames, - appendDNSNamesFromX501Name, true); + appendDNSNamesFromX501Name, true); if (status || CFArrayGetCount(dnsNames) == 0) { CFReleaseNull(dnsNames); } @@ -5127,6 +5023,37 @@ CFArrayRef SecCertificateCopyCountry(SecCertificateRef certificate) { return countries; } +typedef struct { + DERItem *attributeOID; + CFStringRef *result; +} ATV_Context; + +static OSStatus copyAttributeValueFromX501Name(void *context, const DERItem *type, const DERItem *value, CFIndex rdnIX, bool localized) { + ATV_Context *ctx = (ATV_Context *)context; + if (DEROidCompare(type, ctx->attributeOID)) { + CFStringRef string = copyDERThingDescription(kCFAllocatorDefault, value, true, localized); + if (string) { + CFAssignRetained(*ctx->result, string); + } else { + return errSecInvalidCertificate; + } + } + return errSecSuccess; +} + +CFStringRef SecCertificateCopySubjectAttributeValue(SecCertificateRef cert, DERItem *attributeOID) { + CFStringRef result = NULL; + ATV_Context context = { + .attributeOID = attributeOID, + .result = &result, + }; + OSStatus status = parseX501NameContent(&cert->_subject, &context, copyAttributeValueFromX501Name, false); + if (status) { + CFReleaseNull(result); + } + return result; +} + const SecCEBasicConstraints * SecCertificateGetBasicConstraints(SecCertificateRef certificate) { if (certificate->_basicConstraints.present) @@ -5383,11 +5310,15 @@ const DERItem *SecCertificateGetPublicKeyData(SecCertificateRef certificate) { } #if TARGET_OS_OSX -/* There is already a SecCertificateCopyPublicKey with different args on OS X, - so we will refer to this one internally as SecCertificateCopyPublicKey_ios. +#if TARGET_CPU_ARM64 +/* force this implementation to be _SecCertificateCopyPublicKey on arm64 macOS. + note: the legacy function in SecCertificate.cpp is now _SecCertificateCopyPublicKey$LEGACYMAC + when both TARGET_OS_OSX and TARGET_CPU_ARM64 are true. */ +extern __nullable SecKeyRef SecCertificateCopyPublicKey_ios(SecCertificateRef certificate) __asm("_SecCertificateCopyPublicKey"); +#endif /* TARGET_CPU_ARM64 */ __nullable SecKeyRef SecCertificateCopyPublicKey_ios(SecCertificateRef certificate) -#else +#else /* !TARGET_OS_OSX */ __nullable SecKeyRef SecCertificateCopyPublicKey(SecCertificateRef certificate) #endif { @@ -6126,8 +6057,10 @@ static void check_for_marker(const void *key, const void *value, void *context) CFDataRef key_data = SecCertificateCreateOidDataFromString(NULL, key_string); - if (!isData(key_data)) + if (!isData(key_data)) { + CFReleaseNull(key_data); return; + } if (cert_contains_marker_extension_value(search_ctx->certificate, key_data, value_ref)) search_ctx->found = true; @@ -6709,71 +6642,76 @@ SEC_CONST_DECL (kSecSignatureDigestAlgorithmSHA256, "SignatureDigestSHA256"); SEC_CONST_DECL (kSecSignatureDigestAlgorithmSHA384, "SignatureDigestSHA284"); SEC_CONST_DECL (kSecSignatureDigestAlgorithmSHA512, "SignatureDigestSHA512"); +SecSignatureHashAlgorithm SecSignatureHashAlgorithmForAlgorithmOid(const DERItem *algOid) +{ + SecSignatureHashAlgorithm result = kSecSignatureHashAlgorithmUnknown; + while (algOid) { + if (!algOid->data || !algOid->length) { + break; + } + /* classify the signature algorithm OID into one of our known types */ + if (DEROidCompare(algOid, &oidSha512Ecdsa) || + DEROidCompare(algOid, &oidSha512Rsa) || + DEROidCompare(algOid, &oidSha512)) { + result = kSecSignatureHashAlgorithmSHA512; + break; + } + if (DEROidCompare(algOid, &oidSha384Ecdsa) || + DEROidCompare(algOid, &oidSha384Rsa) || + DEROidCompare(algOid, &oidSha384)) { + result = kSecSignatureHashAlgorithmSHA384; + break; + } + if (DEROidCompare(algOid, &oidSha256Ecdsa) || + DEROidCompare(algOid, &oidSha256Rsa) || + DEROidCompare(algOid, &oidSha256)) { + result = kSecSignatureHashAlgorithmSHA256; + break; + } + if (DEROidCompare(algOid, &oidSha224Ecdsa) || + DEROidCompare(algOid, &oidSha224Rsa) || + DEROidCompare(algOid, &oidSha224)) { + result = kSecSignatureHashAlgorithmSHA224; + break; + } + if (DEROidCompare(algOid, &oidSha1Ecdsa) || + DEROidCompare(algOid, &oidSha1Rsa) || + DEROidCompare(algOid, &oidSha1Dsa) || + DEROidCompare(algOid, &oidSha1DsaOIW) || + DEROidCompare(algOid, &oidSha1DsaCommonOIW) || + DEROidCompare(algOid, &oidSha1RsaOIW) || + DEROidCompare(algOid, &oidSha1Fee) || + DEROidCompare(algOid, &oidSha1)) { + result = kSecSignatureHashAlgorithmSHA1; + break; + } + if (DEROidCompare(algOid, &oidMd5Rsa) || + DEROidCompare(algOid, &oidMd5Fee) || + DEROidCompare(algOid, &oidMd5)) { + result = kSecSignatureHashAlgorithmMD5; + break; + } + if (DEROidCompare(algOid, &oidMd4Rsa) || + DEROidCompare(algOid, &oidMd4)) { + result = kSecSignatureHashAlgorithmMD4; + break; + } + if (DEROidCompare(algOid, &oidMd2Rsa) || + DEROidCompare(algOid, &oidMd2)) { + result = kSecSignatureHashAlgorithmMD2; + break; + } + break; + } + + return result; +} + SecSignatureHashAlgorithm SecCertificateGetSignatureHashAlgorithm(SecCertificateRef certificate) { - SecSignatureHashAlgorithm result = kSecSignatureHashAlgorithmUnknown; DERAlgorithmId *algId = (certificate) ? &certificate->_tbsSigAlg : NULL; const DERItem *algOid = (algId) ? &algId->oid : NULL; - while (algOid) { - if (!algOid->data || !algOid->length) { - break; - } - /* classify the signature algorithm OID into one of our known types */ - if (DEROidCompare(algOid, &oidSha512Ecdsa) || - DEROidCompare(algOid, &oidSha512Rsa) || - DEROidCompare(algOid, &oidSha512)) { - result = kSecSignatureHashAlgorithmSHA512; - break; - } - if (DEROidCompare(algOid, &oidSha384Ecdsa) || - DEROidCompare(algOid, &oidSha384Rsa) || - DEROidCompare(algOid, &oidSha384)) { - result = kSecSignatureHashAlgorithmSHA384; - break; - } - if (DEROidCompare(algOid, &oidSha256Ecdsa) || - DEROidCompare(algOid, &oidSha256Rsa) || - DEROidCompare(algOid, &oidSha256)) { - result = kSecSignatureHashAlgorithmSHA256; - break; - } - if (DEROidCompare(algOid, &oidSha224Ecdsa) || - DEROidCompare(algOid, &oidSha224Rsa) || - DEROidCompare(algOid, &oidSha224)) { - result = kSecSignatureHashAlgorithmSHA224; - break; - } - if (DEROidCompare(algOid, &oidSha1Ecdsa) || - DEROidCompare(algOid, &oidSha1Rsa) || - DEROidCompare(algOid, &oidSha1Dsa) || - DEROidCompare(algOid, &oidSha1DsaOIW) || - DEROidCompare(algOid, &oidSha1DsaCommonOIW) || - DEROidCompare(algOid, &oidSha1RsaOIW) || - DEROidCompare(algOid, &oidSha1Fee) || - DEROidCompare(algOid, &oidSha1)) { - result = kSecSignatureHashAlgorithmSHA1; - break; - } - if (DEROidCompare(algOid, &oidMd5Rsa) || - DEROidCompare(algOid, &oidMd5Fee) || - DEROidCompare(algOid, &oidMd5)) { - result = kSecSignatureHashAlgorithmMD5; - break; - } - if (DEROidCompare(algOid, &oidMd4Rsa) || - DEROidCompare(algOid, &oidMd4)) { - result = kSecSignatureHashAlgorithmMD4; - break; - } - if (DEROidCompare(algOid, &oidMd2Rsa) || - DEROidCompare(algOid, &oidMd2)) { - result = kSecSignatureHashAlgorithmMD2; - break; - } - break; - } - - return result; + return SecSignatureHashAlgorithmForAlgorithmOid(algOid); } CFArrayRef SecCertificateCopyiPhoneDeviceCAChain(void) { @@ -6827,3 +6765,25 @@ CFIndex SecCertificateGetUnparseableKnownExtension(SecCertificateRef certificate } return certificate->_unparseableKnownExtensionIndex; } + +CFArrayRef SecCertificateCopyAppleExternalRoots(void) { + CFMutableArrayRef result = NULL; + SecCertificateRef appleExternalECRoot = NULL, testAppleExternalECRoot = NULL; + + require_quiet(appleExternalECRoot = SecCertificateCreateWithBytes(NULL, _AppleExternalECRootCA, sizeof(_AppleExternalECRootCA)), + errOut); + require_quiet(testAppleExternalECRoot = SecCertificateCreateWithBytes(NULL, _TestAppleExternalECRootCA, + sizeof(_TestAppleExternalECRootCA)), + errOut); + + require_quiet(result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), errOut); + CFArrayAppendValue(result, appleExternalECRoot); + if (SecIsInternalRelease()) { + CFArrayAppendValue(result, testAppleExternalECRoot); + } + +errOut: + CFReleaseNull(appleExternalECRoot); + CFReleaseNull(testAppleExternalECRoot); + return result; +} diff --git a/OSX/sec/Security/SecCertificateInternal.h b/OSX/sec/Security/SecCertificateInternal.h index 46ea84a5..048050e6 100644 --- a/OSX/sec/Security/SecCertificateInternal.h +++ b/OSX/sec/Security/SecCertificateInternal.h @@ -90,6 +90,8 @@ typedef struct { __BEGIN_DECLS +SecSignatureHashAlgorithm SecSignatureHashAlgorithmForAlgorithmOid(const DERItem *algOid); + CFDataRef SecCertificateGetAuthorityKeyID(SecCertificateRef certificate); CFDataRef SecCertificateGetSubjectKeyID(SecCertificateRef certificate); @@ -245,11 +247,9 @@ bool SecCertificateIsOidString(CFStringRef oid); DERItem *SecCertificateGetExtensionValue(SecCertificateRef certificate, CFTypeRef oid); -CFArrayRef SecCertificateCopyDNSNamesFromSubject(SecCertificateRef certificate); -CFArrayRef SecCertificateCopyIPAddressesFromSubject(SecCertificateRef certificate); CFArrayRef SecCertificateCopyRFC822NamesFromSubject(SecCertificateRef certificate); - CFArrayRef SecCertificateCopyDNSNamesFromSAN(SecCertificateRef certificate); +CFArrayRef SecCertificateCopyIPAddressDatas(SecCertificateRef certificate); CFIndex SecCertificateGetUnparseableKnownExtension(SecCertificateRef certificate); diff --git a/OSX/sec/Security/SecCertificateRequest.c b/OSX/sec/Security/SecCertificateRequest.c index dad68a9e..0d19b393 100644 --- a/OSX/sec/Security/SecCertificateRequest.c +++ b/OSX/sec/Security/SecCertificateRequest.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2008-2009,2012-2017 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2008-2009,2012-2020 Apple Inc. All Rights Reserved. + * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * */ @@ -111,7 +111,7 @@ static uint8_t * mod128_oid_encoding_ptr(uint8_t *ptr, uint32_t src, bool final) { if (src > 128) ptr = mod128_oid_encoding_ptr(ptr, src / 128, false); - + unsigned char octet = src % 128; if (!final) octet |= 128; @@ -170,16 +170,16 @@ Consider using IA5String for email address static inline bool printable_string(CFStringRef string) { bool result = true; - - CFCharacterSetRef printable_charset = + + CFCharacterSetRef printable_charset = CFCharacterSetCreateWithCharactersInString(kCFAllocatorDefault, CFSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789 '()+,-./:=?")); - CFCharacterSetRef not_printable_charset = + CFCharacterSetRef not_printable_charset = CFCharacterSetCreateInvertedSet(kCFAllocatorDefault, printable_charset); CFRange found; - if (CFStringFindCharacterFromSet(string, not_printable_charset, + if (CFStringFindCharacterFromSet(string, not_printable_charset, CFRangeMake(0, CFStringGetLength(string)), 0, &found)) result = false; @@ -189,7 +189,7 @@ static inline bool printable_string(CFStringRef string) return result; } -static bool make_nss_atv(PRArenaPool *poolp, +static bool make_nss_atv(PRArenaPool *poolp, CFTypeRef oid, const void * value, const unsigned char type_in, NSS_ATV *nss_atv) { size_t length = 0; @@ -210,7 +210,7 @@ static bool make_nss_atv(PRArenaPool *poolp, else { if (!type || type == SecASN1PrintableString) { if (!printable_string(value)) - type = SEC_ASN1_IA5_STRING; + type = SEC_ASN1_UTF8_STRING; else type = SEC_ASN1_PRINTABLE_STRING; } @@ -245,8 +245,8 @@ static bool make_nss_atv(PRArenaPool *poolp, /* will remain valid for the duration of the operation, still maybe copy into pool */ oid_length = CFDataGetLength(oid); oid_data = (uint8_t *)CFDataGetBytePtr(oid); - } - NSS_ATV stage_nss_atv = { { oid_length, oid_data }, + } + NSS_ATV stage_nss_atv = { { oid_length, oid_data }, { { length, (uint8_t*)buffer }, type } }; *nss_atv = stage_nss_atv; return true; @@ -270,7 +270,7 @@ static NSS_RDN **make_subject(PRArenaPool *poolp, CFArrayRef subject) for (atv_ix = 0; atv_ix < atv_count; atv_ix++) { rdns[rdn_ix].atvs[atv_ix] = &atvs[atv_ix]; CFArrayRef atv = CFArrayGetValueAtIndex(rdn, atv_ix); - if ((CFArrayGetCount(atv) != 2) + if ((CFArrayGetCount(atv) != 2) || !make_nss_atv(poolp, CFArrayGetValueAtIndex(atv, 0), CFArrayGetValueAtIndex(atv, 1), 0, &atvs[atv_ix])) return NULL; @@ -302,7 +302,7 @@ static void make_general_names(const void *key, const void *value, void *context } require(entry_count > 0, out); - + require(key,out); require(CFGetTypeID(key) == CFStringGetTypeID(), out); @@ -312,7 +312,7 @@ static void make_general_names(const void *key, const void *value, void *context capacity *= 2; else capacity = 10; - + void * new_array = PORT_ArenaZNewArray(gn->poolp, SecAsn1Item, capacity); if (gn->names) memcpy(new_array, gn->names, gn->capacity); @@ -389,7 +389,7 @@ static void make_general_names(const void *key, const void *value, void *context } else goto out; - + if (gn_values) { for (entry_ix = 0; entry_ix < entry_count; entry_ix++) { CFTypeRef entry_value = CFArrayGetValueAtIndex(gn_values, entry_ix); @@ -419,7 +419,7 @@ out: static SecAsn1Item make_subjectAltName_extension(PRArenaPool *poolp, CFDictionaryRef subjectAltNames) { SecAsn1Item subjectAltExt = {}; - + struct make_general_names_context context = { poolp, NULL, 0 }; CFDictionaryApplyFunction(subjectAltNames, make_general_names, &context); @@ -498,7 +498,7 @@ extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters) if (basic_contraints_num) { NSS_BasicConstraints basic_contraints = { asn1_true, {} }; uint8_t path_len; - + int basic_contraints_path_len = 0; require(CFNumberGetValue(basic_contraints_num, kCFNumberIntType, &basic_contraints_path_len), out); if (basic_contraints_path_len >= 0 && basic_contraints_path_len < 256) { @@ -506,12 +506,12 @@ extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters) basic_contraints.pathLenConstraint.Length = sizeof(path_len); basic_contraints.pathLenConstraint.Data = &path_len; } - + csr_extension[num_extensions].extnId.Data = oidBasicConstraints.data; csr_extension[num_extensions].extnId.Length = oidBasicConstraints.length; csr_extension[num_extensions].critical = asn1_true; - - SEC_ASN1EncodeItem(poolp, &csr_extension[num_extensions].value, &basic_contraints, + + SEC_ASN1EncodeItem(poolp, &csr_extension[num_extensions].value, &basic_contraints, kSecAsn1BasicConstraintsTemplate); require(num_extensions++ < max_extensions, out); } @@ -532,7 +532,7 @@ extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters) int key_usage_value; require(CFNumberGetValue(key_usage_requested, kCFNumberIntType, &key_usage_value), out); if (key_usage_value > 0) { - uint32_t key_usage_value_be = 0, key_usage_mask = 1<<31; + uint32_t key_usage_value_be = 0, key_usage_mask = (uint32_t)0x80000000; // 1L<<31 uint32_t key_usage_value_max_bitlen = 9, key_usage_value_bitlen = 0; while(key_usage_value_max_bitlen) { if (key_usage_value & 1) { @@ -544,7 +544,7 @@ extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters) key_usage_mask >>= 1; } - SecAsn1Item key_usage_input = { key_usage_value_bitlen, + SecAsn1Item key_usage_input = { key_usage_value_bitlen, ((uint8_t*)&key_usage_value_be) + 3 - (key_usage_value_bitlen >> 3) }; SEC_ASN1EncodeItem(poolp, &key_usage_asn1_value, &key_usage_input, kSecAsn1BitStringTemplate); @@ -603,14 +603,14 @@ NSS_Attribute **nss_attributes_from_parameters_dict(PRArenaPool *poolp, CFDictio whenever possible. If internationalization issues make this impossible, the UTF8String alternative SHOULD be used. PKCS #9- attribute processing systems MUST be able to recognize and process - all string types in DirectoryString values. - + all string types in DirectoryString values. + Upperbound of 255 defined for all PKCS#9 attributes. - + pkcs-9 OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9} pkcs-9-at-challengePassword OBJECT IDENTIFIER ::= {pkcs-9 7} - + */ if (!parameters) return NULL; @@ -631,11 +631,11 @@ NSS_Attribute **nss_attributes_from_parameters_dict(PRArenaPool *poolp, CFDictio if (!printable_string(challenge)) utf8 = true; - SecAsn1Item *challenge_password_value = PORT_ArenaZNewArray(poolp, SecAsn1Item, 1); + SecAsn1Item *challenge_password_value = PORT_ArenaZNewArray(poolp, SecAsn1Item, 1); SecAsn1Item challenge_password_raw = { strlen(buffer), (uint8_t*)buffer }; - SEC_ASN1EncodeItem(poolp, challenge_password_value, &challenge_password_raw, + SEC_ASN1EncodeItem(poolp, challenge_password_value, &challenge_password_raw, utf8 ? kSecAsn1UTF8StringTemplate : kSecAsn1PrintableStringTemplate); - SecAsn1Item **challenge_password_values = PORT_ArenaZNewArray(poolp, SecAsn1Item *, 2); + SecAsn1Item **challenge_password_values = PORT_ArenaZNewArray(poolp, SecAsn1Item *, 2); challenge_password_values[0] = challenge_password_value; challenge_password_attr.attrType.Length = sizeof(pkcs9ChallengePassword); challenge_password_attr.attrType.Data = (uint8_t*)&pkcs9ChallengePassword; @@ -656,7 +656,7 @@ NSS_Attribute **nss_attributes_from_parameters_dict(PRArenaPool *poolp, CFDictio extensions_requested_attr.attrValue = extensions_requested_values; num_attrs++; } - + NSS_Attribute **attributes_ptr = PORT_ArenaZNewArray(poolp, NSS_Attribute *, num_attrs + 1); NSS_Attribute *attributes = PORT_ArenaZNewArray(poolp, NSS_Attribute, num_attrs); if (challenge_password_attr.attrType.Length) { @@ -783,7 +783,7 @@ static CF_RETURNS_RETAINED CFDataRef make_signature (void *data_pointer, size_t return signature; } -CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, +CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey) { if (subject == NULL || *subject == NULL) { @@ -796,12 +796,13 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, SecKeyRef realPublicKey = NULL; /* We calculate this from the private key rather than * trusting the caller to give us the right one. */ PRArenaPool *poolp = PORT_NewArena(1024); - - if (!poolp) - return NULL; - NSSCertRequest certReq; - memset(&certReq, 0, sizeof(certReq)); + if (!poolp) { + return NULL; + } + + NSSCertRequest certReq; + memset(&certReq, 0, sizeof(certReq)); /* version */ unsigned char version = 0; @@ -831,7 +832,7 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, rdnps[rdn_num] = &rdns[rdn_num]; rdn_num++; for (one_atv = *one_rdn; one_atv->oid; one_atv++) { - if (!make_nss_atv(poolp, one_atv->oid, one_atv->value, + if (!make_nss_atv(poolp, one_atv->oid, one_atv->value, one_atv->type, &atvs[atv_num])) goto out; atvps[atv_num] = &atvs[atv_num]; @@ -841,7 +842,7 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, } rdnps[rdn_num] = NULL; certReq.reqInfo.subject.rdns = rdnps; - + /* public key info */ realPublicKey = SecKeyCopyPublicKey(privateKey); if (!realPublicKey) { @@ -852,7 +853,7 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, require_quiet(realPublicKey, out); publicKeyData = make_public_key(realPublicKey, &certReq.reqInfo.subjectPublicKeyInfo, &allocated_parameters); require_quiet(publicKeyData, out); - + certReq.reqInfo.attributes = nss_attributes_from_parameters_dict(poolp, parameters); SecCmsArraySortByDER((void **)certReq.reqInfo.attributes, kSecAsn1AttributeTemplate, NULL); @@ -869,13 +870,13 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, require_quiet(signature, out); certReq.signature.Data = (uint8_t *)CFDataGetBytePtr(signature); certReq.signature.Length = 8 * CFDataGetLength(signature); - + /* encode csr */ SecAsn1Item cert_request = {}; - require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, + require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, kSecAsn1CertRequestTemplate), out); csr = CFDataCreate(kCFAllocatorDefault, cert_request.Data, cert_request.Length); - + out: if (allocated_parameters) { free(certReq.reqInfo.subjectPublicKeyInfo.algorithm.parameters.Data); @@ -892,7 +893,7 @@ out: return csr; } -CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, +CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey) { CFDataRef csr = NULL; @@ -901,12 +902,13 @@ CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, SecKeyRef realPublicKey = NULL; /* We calculate this from the private key rather than * trusting the caller to give us the right one. */ bool allocated_parameters = false; - - if (!poolp) - return NULL; - NSSCertRequest certReq; - memset(&certReq, 0, sizeof(certReq)); + if (!poolp) { + return NULL; + } + + NSSCertRequest certReq; + memset(&certReq, 0, sizeof(certReq)); /* version */ unsigned char version = 0; @@ -915,7 +917,7 @@ CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, /* subject */ certReq.reqInfo.subject.rdns = make_subject(poolp, (CFArrayRef)subject); - + /* public key info */ realPublicKey = SecKeyCopyPublicKey(privateKey); if (!realPublicKey) { @@ -926,7 +928,7 @@ CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, require_quiet(realPublicKey, out); publicKeyData = make_public_key(realPublicKey, &certReq.reqInfo.subjectPublicKeyInfo, &allocated_parameters); require_quiet(publicKeyData, out); - + certReq.reqInfo.attributes = nss_attributes_from_parameters_dict(poolp, parameters); SecCmsArraySortByDER((void **)certReq.reqInfo.attributes, kSecAsn1AttributeTemplate, NULL); @@ -943,13 +945,13 @@ CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, require_quiet(signature, out); certReq.signature.Data = (uint8_t *)CFDataGetBytePtr(signature); certReq.signature.Length = 8 * CFDataGetLength(signature); - + /* encode csr */ SecAsn1Item cert_request = {}; - require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, + require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, kSecAsn1CertRequestTemplate), out); csr = CFDataCreate(kCFAllocatorDefault, cert_request.Data, cert_request.Length); - + out: if (allocated_parameters) { free(certReq.reqInfo.subjectPublicKeyInfo.algorithm.parameters.Data); @@ -1057,9 +1059,9 @@ bool SecVerifyCertificateRequest(CFDataRef csr, SecKeyRef *publicKey, undecodedCertReq.certRequestBlob.Length, kCFAllocatorNull); require_quiet(alg && signature && data, out); require_quiet(SecKeyVerifySignature(candidatePublicKey, alg, data, signature, NULL), out); - + SecAsn1Item subject_item = { 0 }, extensions_item = { 0 }, challenge_item = { 0 }; - require_quiet(SEC_ASN1EncodeItem(poolp, &subject_item, + require_quiet(SEC_ASN1EncodeItem(poolp, &subject_item, &decodedCertReq.reqInfo.subject, kSecAsn1NameTemplate), out); if (*decodedCertReq.reqInfo.attributes) { @@ -1074,7 +1076,7 @@ bool SecVerifyCertificateRequest(CFDataRef csr, SecKeyRef *publicKey, extensions_item = *attr->attrValue[0]; } } - + if (subject && subject_item.Length) *subject = CFDataCreate(kCFAllocatorDefault, subject_item.Data, subject_item.Length); if (extensions && extensions_item.Length) @@ -1105,19 +1107,19 @@ out: return valid; } -#define HIDIGIT(v) (((v) / 10) + '0') -#define LODIGIT(v) (((v) % 10) + '0') +#define HIDIGIT(v) (((v) / 10) + '0') +#define LODIGIT(v) (((v) % 10) + '0') static OSStatus DER_CFDateToUTCTime(PRArenaPool *poolp, CFAbsoluteTime date, SecAsn1Item * utcTime) { unsigned char *d; - + utcTime->Length = 13; utcTime->Data = d = PORT_ArenaAlloc(poolp, 13); if (!utcTime->Data) return SECFailure; - + __block int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; __block bool result; SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) { @@ -1125,15 +1127,15 @@ DER_CFDateToUTCTime(PRArenaPool *poolp, CFAbsoluteTime date, SecAsn1Item * utcTi }); if (!result) return SECFailure; - + /* UTC time does not handle the years before 1950 */ if (year < 1950) return SECFailure; - + /* remove the century since it's added to the year by the CFAbsoluteTimeGetGregorianDate routine, but is not needed for UTC time */ year %= 100; - + d[0] = HIDIGIT(year); d[1] = LODIGIT(year); d[2] = HIDIGIT(month); @@ -1151,7 +1153,7 @@ DER_CFDateToUTCTime(PRArenaPool *poolp, CFAbsoluteTime date, SecAsn1Item * utcTi } SecCertificateRef -SecGenerateSelfSignedCertificate(CFArrayRef subject, CFDictionaryRef parameters, +SecGenerateSelfSignedCertificate(CFArrayRef subject, CFDictionaryRef parameters, SecKeyRef __unused publicKey, SecKeyRef privateKey) { SecCertificateRef cert = NULL; @@ -1276,7 +1278,7 @@ SecIdentitySignCertificateWithAlgorithm(SecIdentityRef issuer, CFDataRef serialn require_noerr(SecIdentityCopyCertificate(issuer, &issuer_cert), out); CFDataRef issuer_name = SecCertificateCopySubjectSequence(issuer_cert); SecAsn1Item issuer_item = { CFDataGetLength(issuer_name), (uint8_t*)CFDataGetBytePtr(issuer_name) }; - require_noerr_action_quiet(SEC_ASN1DecodeItem(poolp, &cert_tmpl.tbs.issuer.rdns, + require_noerr_action_quiet(SEC_ASN1DecodeItem(poolp, &cert_tmpl.tbs.issuer.rdns, kSecAsn1NameTemplate, &issuer_item), out, CFReleaseNull(issuer_name)); CFReleaseNull(issuer_name); diff --git a/OSX/sec/Security/SecDH.c b/OSX/sec/Security/SecDH.c index 0f5689e0..ecd60a52 100644 --- a/OSX/sec/Security/SecDH.c +++ b/OSX/sec/Security/SecDH.c @@ -53,33 +53,28 @@ static inline ccdh_gp_t SecDH_gp(SecDHContext dh) { - return (ccdh_gp_t)dh; + return (ccdh_gp_t)dh; } static inline ccdh_full_ctx_t SecDH_priv(SecDHContext dh) { ccdh_gp_t gp = SecDH_gp(dh); cc_size s = ccn_sizeof_n(ccdh_gp_n(gp)); - ccdh_full_ctx_t priv = (ccdh_full_ctx_t)((char *) dh + ccdh_gp_size(s)); - - return priv; + return (ccdh_full_ctx_t)cc_pad_align((uintptr_t)dh + ccdh_gp_size(s)); } size_t SecDHGetMaxKeyLength(SecDHContext dh) { ccdh_gp_t gp = SecDH_gp(dh); - cc_size s = ccn_sizeof_n(ccdh_gp_n(gp)); - - return s; + return ccn_sizeof_n(ccdh_gp_n(gp)); } - static inline size_t SecDH_context_size(size_t p_len) { - cc_size n = ccn_nof_size(p_len); - cc_size real_p_len = ccn_sizeof_n(n); - size_t context_size = ccdh_gp_size(real_p_len)+ccdh_full_ctx_size(real_p_len); - return context_size; + cc_size real_p_len = ccn_sizeof_size(p_len); + + // Add padding to allow proper alignment of the ccdh_full_ctx. + return ccdh_gp_size(real_p_len) + (CC_MAX_ALIGNMENT - 1) + ccdh_full_ctx_size(real_p_len); } /* Shared static functions. */ @@ -210,7 +205,7 @@ OSStatus SecDHCreateFromParameters(const uint8_t *params, } cc_size n = ccn_nof_size(decodedParams.p.length); cc_size p_len = ccn_sizeof_n(n); - size_t context_size = ccdh_gp_size(p_len)+ccdh_full_ctx_size(p_len); + size_t context_size = SecDH_context_size(p_len); void *context = malloc(context_size); if(context==NULL) return errSecAllocate; diff --git a/OSX/sec/Security/SecECKey.m b/OSX/sec/Security/SecECKey.m index 4e9b26d6..5b343f6b 100644 --- a/OSX/sec/Security/SecECKey.m +++ b/OSX/sec/Security/SecECKey.m @@ -96,6 +96,10 @@ static ccoid_t ccoid_secp224r1 = CC_EC_OID_SECP224R1; static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1; static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1; +// OID_CERTICOM is wrong +static ccoid_t ccoid_libder_secp384r1 = ((unsigned char *)"\x06\x04\x2B\x84\x00\x22"); +static ccoid_t ccoid_libder_secp521r1 = ((unsigned char *)"\x06\x04\x2B\x84\x00\x23"); + static ccec_const_cp_t ccec_cp_for_oid(const unsigned char *oid) { if (oid!=NULL) { @@ -105,9 +109,9 @@ static ccec_const_cp_t ccec_cp_for_oid(const unsigned char *oid) return ccec_cp_256(); } else if (ccoid_equal(oid, ccoid_secp224r1)) { return ccec_cp_224(); - } else if (ccoid_equal(oid, ccoid_secp384r1)) { + } else if (ccoid_equal(oid, ccoid_secp384r1) || ccoid_equal(oid, ccoid_libder_secp384r1)) { return ccec_cp_384(); - } else if (ccoid_equal(oid, ccoid_secp521r1)) { + } else if (ccoid_equal(oid, ccoid_secp521r1) || ccoid_equal(oid, ccoid_libder_secp521r1)) { return ccec_cp_521(); } } @@ -128,10 +132,11 @@ static OSStatus SecECPublicKeyInit(SecKeyRef key, break; } - ccec_const_cp_t cp = getCPForPublicSize(derKey->keyLength); + require_action_quiet(derKey->parameters && derKey->parametersLength > 2 && + derKey->parameters[1] <= derKey->parametersLength - 2, errOut, err = errSecDecode); + ccec_const_cp_t cp = ccec_cp_for_oid(derKey->parameters); require_action_quiet(cp, errOut, err = errSecDecode); - /* TODO: Parse and use real params from passed in derKey->algId.params */ err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey) ? errSecDecode : errSecSuccess); break; diff --git a/OSX/sec/Security/SecExports.exp-in b/OSX/sec/Security/SecExports.exp-in index 7067b56d..116367dd 100644 --- a/OSX/sec/Security/SecExports.exp-in +++ b/OSX/sec/Security/SecExports.exp-in @@ -71,7 +71,6 @@ __P_DO_EXPORT_##ISPUBLIC(NAME) #if TARGET_OS_OSX _kSecPolicyAppleiChat #endif -_kSecPolicyAppleIDValidationRecordSigningPolicy _kSecPolicyMacAppStoreReceipt _kSecPolicyNameAppleAIDCService _kSecPolicyNameAppleAMPService @@ -87,9 +86,11 @@ _kSecPolicyNameAppleIDSService _kSecPolicyNameAppleMapsService _kSecPolicyNameAppleMMCSService _kSecPolicyNameAppleParsecService +_kSecPolicyNameApplePushCertPortal _kSecPolicyNameApplePPQService _kSecPolicyNameApplePushService _kSecPolicyNameAppleSiriService +_kSecPolicyNameAppleUpdatesService _kSecPolicyNameEAPClient _kSecPolicyNameEAPServer _kSecPolicyNameIPSecClient @@ -137,6 +138,9 @@ _kSecPolicyKU_NonRepudiation #endif _SecDNSIsTLD +_CreateCFDataFromBase64CFString +_parseNSPinnedDomains +_SecPolicyReconcilePinningRequiredIfInfoSpecified #undef POLICYCHECKMACRO #define __PC_DO_EXPORT_(NAME) @@ -148,15 +152,16 @@ _SecPolicyCheckCertSubjectCountry _SecPolicyCopyProperties _SecPolicyCreateiAPSWAuthWithExpiration +_SecPolicyCreateSSLWithKeyUsage _SecPolicyCreateWithProperties _SecPolicyGetName _SecPolicyGetOidString _SecPolicyGetTypeID _SecPolicySetName _SecPolicySetOptionsValue +_SecPolicySetSHA256Pins #if TARGET_OS_OSX _SecPolicyCopy -_SecPolicyCopyAll _SecPolicyCreateAppleTimeStampingAndRevocationPolicies _SecPolicyCreateItemImplInstance _SecPolicyCreateWithOID @@ -204,6 +209,8 @@ _kSecTrustExtendedValidation _kSecTrustInfoCertificateTransparencyKey _kSecTrustInfoCompanyNameKey _kSecTrustInfoExtendedValidationKey +_kSecTrustInfoResultNotBefore +_kSecTrustInfoResultNotAfter _kSecTrustInfoRevocationKey _kSecTrustInfoRevocationValidUntilKey _kSecTrustOrganizationName @@ -221,6 +228,7 @@ _SecTrustCopyFailureDescription _SecTrustCopyFilteredDetails _SecTrustCopyInfo _SecTrustCopyInputCertificates +_SecTrustCopyKey _SecTrustCopyPolicies _SecTrustCopyProperties _SecTrustCopyPublicKey @@ -266,6 +274,7 @@ _SecTrustSetPolicies _SecTrustSetSignedCertificateTimestamps _SecTrustSetTrustedLogs _SecTrustSetVerifyDate +_SecTrustTriggerValidUpdate #if TARGET_OS_OSX _SecTrustCopyAnchorCertificates _SecTrustCopyExtendedResult @@ -291,15 +300,18 @@ _SecTrustSettingsCopyCertificatesForUserAdminDomains _SecTrustSettingsCopyModificationDate _SecTrustSettingsCopyQualifiedCerts _SecTrustSettingsCopyTrustSettings +_SecTrustSettingsCopyTrustSettings_Cached _SecTrustSettingsCopyUnrestrictedRoots _SecTrustSettingsCreateExternalRepresentation _SecTrustSettingsEvaluateCert _SecTrustSettingsImportExternalRepresentation +_SecTrustSettingsPurgeCache _SecTrustSettingsPurgeUserAdminCertsCache _SecTrustSettingsRemoveTrustSettings _SecTrustSettingsSetTrustSettings _SecTrustSettingsSetTrustSettingsExternal _SecTrustSettingsSetTrustedCertificateForSSLHost +_SecTrustSettingsUserAdminDomainsContain _SecTrustedApplicationCopyData _SecTrustedApplicationCopyExternalRepresentation _SecTrustedApplicationCopyRequirement @@ -317,7 +329,6 @@ _SecTrustedApplicationValidateWithPath #endif -#if TARGET_OS_IPHONE _SecTrustStoreContains _SecTrustStoreCopyAll _SecTrustStoreCopyUsageConstraints @@ -328,13 +339,21 @@ _SecTrustStoreRemoveCertificate _SecTrustStoreSetTrustSettings _SecTrustGetExceptionResetCount _SecTrustIncrementExceptionResetCount -#endif +_SecTrustStoreSetCARevocationAdditions +_SecTrustStoreCopyCARevocationAdditions _SecTrustStoreSetCTExceptions _SecTrustStoreCopyCTExceptions +_SecTrustStoreSetTransparentConnectionPins +_SecTrustStoreCopyTransparentConnectionPins +_kSecCARevocationAdditionsKey +_kSecCARevocationHashAlgorithmKey +_kSecCARevocationSPKIHashKey _kSecCTExceptionsCAsKey _kSecCTExceptionsDomainsKey _kSecCTExceptionsHashAlgorithmKey _kSecCTExceptionsSPKIHashKey +_kSecTrustStoreHashAlgorithmKey +_kSecTrustStoreSPKIHashKey // // Identity @@ -343,6 +362,9 @@ _kSecCTExceptionsSPKIHashKey _SecIdentityCopyCertificate _SecIdentityCopyPrivateKey _SecIdentityCreate +#if TARGET_OS_OSX +_SecIdentityDeleteApplicationPreferenceItems +#endif _SecIdentityGetTypeID @@ -354,6 +376,7 @@ _kSecCertificateDetailSHA1Digest _kSecCertificateEscrowFileName _kSecCertificateProductionEscrowKey _kSecCertificateProductionPCSEscrowKey +_SecCertificateCopyAppleExternalRoots _SecCertificateCopyAttributeDictionary _SecCertificateCopyCommonName _SecCertificateCopyCommonNames @@ -363,7 +386,6 @@ _SecCertificateCopyCountry _SecCertificateCopyCTLogForKeyID _SecCertificateCopyDNSNames _SecCertificateCopyDNSNamesFromSAN -_SecCertificateCopyDNSNamesFromSubject _SecCertificateCopyData _SecCertificateCopyEmailAddresses _SecCertificateCopyEscrowRoots @@ -371,8 +393,8 @@ _SecCertificateCopyExtendedKeyUsage _SecCertificateCopyExtensionValue _SecCertificateCopyiAPAuthCapabilities _SecCertificateCopyiAPSWAuthCapabilities +_SecCertificateCopyIPAddressDatas _SecCertificateCopyIPAddresses -_SecCertificateCopyIPAddressesFromSubject _SecCertificateCopyiPhoneDeviceCAChain _SecCertificateCopyIssuerSHA1Digest _SecCertificateCopyIssuerSequence @@ -390,13 +412,20 @@ _SecCertificateCopyOrganizationalUnit _SecCertificateCopyPrecertTBS _SecCertificateCopyProperties _SecCertificateCopyPublicKey +#if TARGET_OS_OSX && TARGET_CPU_ARM64 +_SecCertificateCopyPublicKey$LEGACYMAC +#endif _SecCertificateCopyPublicKeySHA1Digest _SecCertificateCopyRFC822Names _SecCertificateCopyRFC822NamesFromSubject _SecCertificateCopySerialNumber _SecCertificateCopySerialNumberData +#if TARGET_OS_OSX && TARGET_CPU_ARM64 +_SecCertificateCopySerialNumber$LEGACYMAC +#endif _SecCertificateCopySHA256Digest _SecCertificateCopySignedCertificateTimestamps +_SecCertificateCopySubjectAttributeValue _SecCertificateCopySubjectPublicKeyInfoSHA1Digest _SecCertificateCopySubjectPublicKeyInfoSHA256Digest _SecCertificateCopySubjectSequence @@ -461,6 +490,7 @@ _SecCertificateShow _SecCertificateVersion _SecDistinguishedNameCopyNormalizedContent _SecDistinguishedNameCopyNormalizedSequence +_SecSignatureHashAlgorithmForAlgorithmOid _SecCertificateArrayCopyXPCArray _SecCertificateAppendToXPCArray @@ -503,16 +533,6 @@ _SecCertificateSetPreference _SecCertificateSetPreferred #endif -// -// CertificateBundle -// - -#if TARGET_OS_OSX -_SecCertifcateBundleExport -_SecCertificateBundleExport -_SecCertificateBundleImport -#endif /* TARGET_OS_OSX */ - #if TARGET_OS_IPHONE // // SCEP @@ -560,7 +580,6 @@ _SecGenerateCertificateRequestSubject // _SecOTRPacketTypeString -_SecOTRSEndSession _SecOTRSPrecalculateKeys _SecOTRSessionCreateRemote _SecOTRSessionProcessPacketRemote @@ -620,6 +639,7 @@ _AES_CTR_IV0_Transform _SecOTRSessionIsSessionInAwaitingState _SecOTRFullIdentityCreateFromSecKeyRef +_SecOTRFullIdentityCreateFromSecKeyRefSOS _SecOTRSIsForKeys _SecOTRPublicIdentityCreateFromSecKeyRef _SecOTRSAppendRestartPacket @@ -1525,6 +1545,13 @@ _kSecAttrPCSPlaintextPublicKey _kSecAttrPCSPlaintextPublicIdentity _kSecAttrSHA1 +_kSecDataInetExtraNotes +_kSecDataInetExtraHistory +_kSecDataInetExtraClientDefined0 +_kSecDataInetExtraClientDefined1 +_kSecDataInetExtraClientDefined2 +_kSecDataInetExtraClientDefined3 + #include "keychain/SecureObjectSync/SOSViews.exp-in" _kSecClass @@ -1565,15 +1592,13 @@ _kSecReturnPersistentRef _kSecReturnRef _SecItemAdd _SecItemCertificateExists -_SecItemCopyDisplayNames _SecItemCopyMatching _SecItemCopyParentCertificates_ios _SecItemDelete -#if TARGET_OS_IPHONE _SecItemDeleteAll -#endif _SecItemUpdateWithError _SecItemUpdate +_SecItemPersistKeychainWritesAtHighPerformanceCost __SecItemAddAndNotifyOnSync _SecItemSetCurrentItemAcrossAllDevices _SecItemFetchCurrentItemAcrossAllDevices @@ -1594,18 +1619,18 @@ __SecKeychainWriteBackupToFileDescriptor __SecKeychainCopyKeybagUUIDFromFileDescriptor _SecItemBackupWithRegisteredBackups +_SecItemBackupWithRegisteredViewBackup _SecItemBackupSetConfirmedManifest _SecItemBackupRestore _SecBackupKeybagAdd _SecBackupKeybagDelete -_SecItemBackupCopyMatching _SecItemBackupCreateManifest _SecItemBackupWithChanges _SecBackupKeybagAdd _SecBackupKeybagDelete __SecKeychainRollKeys -#if TARGET_OS_IPHONE +#if TARGET_OS_IPHONE || TARGET_OS_OSX || TARGET_OS_MACCATALYST _SecAddSharedWebCredential _SecRequestSharedWebCredential @@ -1619,7 +1644,7 @@ __SecSecuritydCopyWhoAmI __SecSyncBubbleTransfer __SecSystemKeychainTransfer __SecSyncDeleteUserViews -_SecItemUpdateTokenItems +_SecItemUpdateTokenItemsForAccessGroups _SecItemDeleteAllWithAccessGroups _SecTokenItemValueCopy @@ -1646,6 +1671,7 @@ _SecCopyDecryptedForServer _sSecDERErrorDomain _der_sizeof_plist _der_encode_plist +_der_encode_plist_repair _der_decode_plist _CFPropertyListCreateDERData _CFPropertyListCreateWithDERData @@ -1745,10 +1771,9 @@ _sec_protocol_options_access_handle _sec_protocol_metadata_access_handle _sec_protocol_metadata_get_server_name _sec_protocol_options_set_output_handler_access_block -_sec_protocol_options_set_tls_SIKE503_exchange_enabled -_sec_protocol_options_set_tls_HRSS_exchange_enabled _sec_protocol_options_set_eddsa_enabled _sec_protocol_options_set_tls_grease_enabled +_sec_protocol_options_set_allow_unknown_alpn_protos _sec_protocol_options_set_tls_delegated_credentials_enabled _sec_protocol_options_set_tls_ticket_request_count _sec_protocol_options_set_local_certificates @@ -1762,6 +1787,8 @@ _sec_protocol_options_set_quic_transport_parameters _sec_protocol_options_set_session_state _sec_protocol_options_set_session_update_block _sec_protocol_options_add_tls_application_protocol +_sec_protocol_options_add_transport_specific_application_protocol +_sec_protocol_options_copy_transport_specific_application_protocol _sec_protocol_options_append_tls_ciphersuite _sec_protocol_options_append_tls_ciphersuite_group _sec_protocol_options_add_tls_ciphersuite @@ -1788,6 +1815,9 @@ _sec_protocol_options_set_tls_is_fallback_attempt _sec_protocol_options_set_verify_block _sec_protocol_options_set_tls_diffie_hellman_parameters _sec_protocol_options_set_peer_authentication_required +_sec_protocol_options_set_peer_authentication_optional +_sec_protocol_options_set_enable_encrypted_client_hello +_sec_protocol_options_get_enable_encrypted_client_hello _sec_protocol_options_set_experiment_identifier _sec_protocol_metadata_get_experiment_identifier _sec_protocol_options_create_config @@ -1812,6 +1842,7 @@ _sec_protocol_configuration_tls_required_for_address _sec_protocol_configuration_builder_create _sec_protocol_configuration_create_with_builder _sec_protocol_options_set_tls_encryption_secret_update_block +_sec_protocol_options_set_tls_encryption_level_update_block _sec_protocol_options_append_tls_key_exchange_group _sec_protocol_options_append_tls_key_exchange_group_set _sec_protocol_options_add_tls_key_exchange_group @@ -1828,6 +1859,11 @@ _sec_protocol_metadata_access_pre_shared_keys _sec_protocol_metadata_copy_connection_id _sec_protocol_options_set_pre_shared_key_selection_block _sec_protocol_helper_ciphersuite_group_to_ciphersuite_list +_sec_protocol_helper_ciphersuite_group_contains_ciphersuite +_sec_protocol_helper_ciphersuite_minimum_TLS_version +_sec_protocol_helper_ciphersuite_maximum_TLS_version +_sec_protocol_helper_get_ciphersuite_name +_sec_protocol_options_set_tls_block_length_padding _sec_release _sec_retain _sec_trust_copy_ref @@ -1852,7 +1888,3 @@ _sec_experiment_set_sampling_disabled _SSLCiphersuiteGroupToCiphersuiteList _SSLCiphersuiteMaximumTLSVersion _SSLCiphersuiteMinimumTLSVersion - -#if __OBJC2__ && (TARGET_OS_IPHONE || (TARGET_OS_OSX && __x86_64__)) -_OBJC_CLASS_$_SFSignInAnalytics -#endif //__OBJC2__ && IPHONE || OSX diff --git a/OSX/sec/Security/SecFramework.c b/OSX/sec/Security/SecFramework.c index b054999d..909ec7f9 100644 --- a/OSX/sec/Security/SecFramework.c +++ b/OSX/sec/Security/SecFramework.c @@ -32,18 +32,8 @@ #endif #include "SecFramework.h" -#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include /* Security.framework's bundle id. */ #if TARGET_OS_IPHONE @@ -64,19 +54,3 @@ CFStringRef SecFrameworkCopyLocalizedString(CFStringRef key, return CFRetainSafe(key); } - -CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName, - CFStringRef resourceType, CFStringRef subDirName) { - CFURLRef url = NULL; - CFBundleRef bundle = SecFrameworkGetBundle(); - if (bundle) { - url = CFBundleCopyResourceURL(bundle, resourceName, - resourceType, subDirName); - if (!url) { - secwarning("resource: %@.%@ in %@ not found", resourceName, - resourceType, subDirName); - } - } - - return url; -} diff --git a/OSX/sec/Security/SecFramework.h b/OSX/sec/Security/SecFramework.h index 29c74c60..a1c35eff 100644 --- a/OSX/sec/Security/SecFramework.h +++ b/OSX/sec/Security/SecFramework.h @@ -43,9 +43,6 @@ __BEGIN_DECLS CFStringRef SecFrameworkCopyLocalizedString(CFStringRef key, CFStringRef tableName); -CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName, - CFStringRef resourceType, CFStringRef subDirName); - /* Return the SHA1 digest of a chunk of data as newly allocated CFDataRef. */ CFDataRef SecSHA1DigestCreate(CFAllocatorRef allocator, const UInt8 *data, CFIndex length); diff --git a/OSX/sec/Security/SecFrameworkStrings.h b/OSX/sec/Security/SecFrameworkStrings.h index 9404603c..9708ca21 100644 --- a/OSX/sec/Security/SecFrameworkStrings.h +++ b/OSX/sec/Security/SecFrameworkStrings.h @@ -271,6 +271,7 @@ __BEGIN_DECLS #define SEC_TRUST_ERROR_WeakKeySize SecStringWithDefaultValue("Certificate is using a broken key size", "Trust", 0, "Certificate is using a broken key size", "Error for weak keys") #define SEC_TRUST_ERROR_WeakSignature SecStringWithDefaultValue("Certificate is using a broken signature algorithm", "Trust", 0, "Certificate is using a broken signature algorithm", "Error for weak signatures") #define SEC_TRUST_ERROR_KeyUsage SecStringWithDefaultValue("Key usage does not match certificate usage", "Trust", 0, "Key usage does not match certificate usage", "Error for key usage mismatch") +#define SEC_TRUST_ERROR_KeyUsageReportOnly SecStringWithDefaultValue("Key usage does not match certificate usage", "Trust", 0, "Key usage does not match certificate usage", "Error for key usage mismatch") #define SEC_TRUST_ERROR_ExtendedKeyUsage SecStringWithDefaultValue("Extended key usage does not match certificate usage", "Trust", 0, "Extended key usage does not match certificate usage", "Error for extended key usage mismatch") #define SEC_TRUST_ERROR_SubjectCommonName SecStringWithDefaultValue("Common Name does not match expected name", "Trust", 0, "Common Name does not match expected name", "Error for subject common name mismatch") #define SEC_TRUST_ERROR_SubjectCommonNamePrefix SecStringWithDefaultValue("Common Name does not match expected name", "Trust", 0, "Common Name does not match expected name", "Error for subject common name prefix mismatch") @@ -284,17 +285,19 @@ __BEGIN_DECLS #define SEC_TRUST_ERROR_LeafMarkersProdAndQA SecStringWithDefaultValue("Missing project-specific extension OID", "Trust", 0, "Missing project-specific extension OID", "Error for leaf marker OID allowing prod or QA") #define SEC_TRUST_ERROR_BlackListedLeaf SecStringWithDefaultValue("Certificate is blocked", "Trust", 0, "Certificate is blocked", "Error for blocklisted certificates") #define SEC_TRUST_ERROR_GrayListedLeaf SecStringWithDefaultValue("Certificate is listed as untrusted", "Trust", 0, "Certificate is listed as untrusted", "Error for graylisted certificates") +#define SEC_TRUST_ERROR_LeafSPKISHA256 SecStringWithDefaultValue("Public key does not match pinned value", "Trust", 0, "Public key does not match pinned value", "Error for leaf public key pin") +#define SEC_TRUST_ERROR_NotCA SecStringWithDefaultValue("Leaf certificate is a CA", "Trust", 0, "Leaf certificate is a CA", "Error for leaf CA") #define SEC_TRUST_ERROR_IssuerCommonName SecStringWithDefaultValue("Common Name does not match expected name", "Trust", 0, "Common Name does not match expected name", "Error for issuer common name mismatch") #define SEC_TRUST_ERROR_BasicConstraints SecStringWithDefaultValue("Basic constraints are required but missing", "Trust", 0, "Basic constraints are required but missing", "Error for missing basic constraints") #define SEC_TRUST_ERROR_BasicConstraintsCA SecStringWithDefaultValue("Non-CA certificate used as a CA", "Trust", 0, "Non-CA certificate used as a CA", "Error for CA basic constraints") #define SEC_TRUST_ERROR_BasicConstraintsPathLen SecStringWithDefaultValue("Chain exceeded constrained path length", "Trust", 0, "Chain exceeded constrained path length", "Error for path length basic constraints") #define SEC_TRUST_ERROR_IntermediateSPKISHA256 SecStringWithDefaultValue("Public key does not match pinned value", "Trust", 0, "Public key does not match pinned value", "Error for intermediate public key pin") +#define SEC_TRUST_ERROR_CAspkiSHA256 SecStringWithDefaultValue("Public key does not match pinned value", "Trust", 0, "Public key does not match pinned value", "Error for CA public key pin") #define SEC_TRUST_ERROR_IntermediateEKU SecStringWithDefaultValue("Extended key usage does not match pinned value", "Trust", 0, "Extended key usage does not match pinned value", "Error for intermediate extended key usage pin") #define SEC_TRUST_ERROR_IntermediateMarkerOid SecStringWithDefaultValue("Missing issuer-specific extension OID", "Trust", 0, "Missing issuer-specific extension OID", "Error for intermediate marker OID") #define SEC_TRUST_ERROR_IntermediateMarkerOidWithoutValueCheck SecStringWithDefaultValue("Missing issuer-specific extension OID", "Trust", 0, "Missing issuer-specific extension OID", "Error for intermediate marker OID") #define SEC_TRUST_ERROR_IntermediateOrganization SecStringWithDefaultValue("Organization does not match expected name", "Trust", 0, "Organization does not match expected name", "Error for issuer organization mismatch") #define SEC_TRUST_ERROR_IntermediateCountry SecStringWithDefaultValue("Country or Region does not match expected name", "Trust", 0, "Country or Region does not match expected name", "Error for issuer country mismatch") -#define SEC_TRUST_ERROR_AnchorSHA1 SecStringWithDefaultValue("Anchor does not match pinned fingerprint", "Trust", 0, "Anchor does not match pinned fingerprint", "Error for anchor SHA-1 fingerprint pin") #define SEC_TRUST_ERROR_AnchorSHA256 SecStringWithDefaultValue("Anchor does not match pinned fingerprint", "Trust", 0, "Anchor does not match pinned fingerprint", "Error for anchor SHA-256 fingerprint pin") #define SEC_TRUST_ERROR_AnchorTrusted SecStringWithDefaultValue("Root is not trusted", "Trust", 0, "Root is not trusted", "Error for untrusted root") #define SEC_TRUST_ERROR_MissingIntermediate SecStringWithDefaultValue("Unable to build chain to root (possible missing intermediate)", "Trust", 0, "Unable to build chain to root (possible missing intermediate)", "Error for missing intermediates") @@ -329,6 +332,7 @@ __BEGIN_DECLS #define SEC_TRUST_ERROR_ValidityPeriodMaximums SecStringWithDefaultValue("Certificate exceeds maximum temporal validity period", "Trust", 0, "Certificate exceeds maximum temporal validity period", "Error for certificates that exceed the system's maximum temporal validity") #define SEC_TRUST_ERROR_ServerAuthEKU SecStringWithDefaultValue("Extended key usage does not match certificate usage", "Trust", 0, "Extended key usage does not match certificate usage", "Error for extended key usage mismatch") #define SEC_TRUST_ERROR_UnparseableExtension SecStringWithDefaultValue("Unable to parse known extension", "Trust", 0, "Unable to parse known extension", "Error for unparseable known extensions") +#define SEC_TRUST_ERROR_NonTlsCTRequired SecStringWithDefaultValue("Certificate Transparency validation required but missing", "Trust", 0, "Certificate Transparency validation required but missing", "Error for missing Certificate Transparency validation") __END_DECLS diff --git a/OSX/sec/Security/SecItem.c b/OSX/sec/Security/SecItem.c index b526d632..4f325ec9 100644 --- a/OSX/sec/Security/SecItem.c +++ b/OSX/sec/Security/SecItem.c @@ -70,12 +70,12 @@ #include #include #include -#include -#include +#include #include #include #include #include +#include #include #include "keychain/SecureObjectSync/SOSInternal.h" @@ -95,10 +95,11 @@ #include #include -#include #include +#include "SecItemRateLimit.h" + /* * See corresponding definition in SecDbKeychainItemV7. This is the unserialized * maximum, so the daemon's limit is not exactly the same. @@ -219,6 +220,9 @@ static OSStatus osstatus_for_ctk_error(CFIndex ctkError) { return errSecUserCanceled; case kTKErrorCodeCorruptedData: return errSecDecode; + case kTKErrorCodeTokenNotFound: + case kTKErrorCodeObjectNotFound: + return errSecItemNotFound; default: return errSecInternal; } @@ -458,15 +462,6 @@ SecItemCreateFromAttributeDictionary(CFDictionaryRef refAttributes) { return ref; } -#if !TARGET_OS_OSX -OSStatus -SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames) -{ - // @@@ TBI - return -1 /* errSecUnimplemented */; -} -#endif // TARGET_OS_OSX - typedef OSStatus (*secitem_operation)(CFDictionaryRef attributes, CFTypeRef *result); static bool explode_identity(CFDictionaryRef attributes, secitem_operation operation, @@ -540,7 +535,7 @@ static bool explode_identity(CFDictionaryRef attributes, secitem_operation opera if (result) { if (!status) { /* result is a persistent ref to a cert */ - sqlite_int64 rowid; + sqlite_int64 rowid = -1; CFDictionaryRef tokenAttrs = NULL; if (_SecItemParsePersistentRef(result, NULL, &rowid, &tokenAttrs)) { *return_result = _SecItemCreatePersistentRef(kSecClassIdentity, rowid, tokenAttrs); @@ -671,20 +666,31 @@ static void infer_cert_label(SecCFDictionaryCOW *attributes) } } -static CFDataRef CreateTokenPersistentRefData(CFTypeRef class, CFDictionaryRef attributes) -{ +static CFDataRef CreateTokenPersistentRefData(CFTypeRef class, CFDictionaryRef attributes) { CFDataRef tokenPersistentRef = NULL; - CFStringRef tokenId = CFDictionaryGetValue(attributes, kSecAttrTokenID); + CFStringRef tokenID = NULL; + CFDataRef tokenData = NULL; + CFDataRef oid = NULL; CFDictionaryRef itemValue = NULL; - if (CFEqual(class, kSecClassIdentity)) { - itemValue = SecTokenItemValueCopy(CFDictionaryGetValue(attributes, kSecAttrIdentityCertificateData), NULL); + + oid = CFDictionaryGetValue(attributes, kSecAttrTokenOID); + if (oid != NULL) { + require_quiet(tokenID = CFCast(CFString, CFDictionaryGetValue(attributes, kSecAttrTokenID)), out); } else { - itemValue = SecTokenItemValueCopy(CFDictionaryGetValue(attributes, kSecValueData), NULL); + // Identities are identified by their contained certificate, so we need to get tokenID and OID from certificate, + // not from the key. + if (CFEqual(class, kSecClassIdentity) && oid == NULL) { + require_quiet(tokenID = CFCast(CFString, CFDictionaryGetValue(attributes, kSecAttrIdentityCertificateTokenID)), out); + require_quiet(tokenData = CFCast(CFData, CFDictionaryGetValue(attributes, kSecAttrIdentityCertificateData)), out); + } else { + require_quiet(tokenID = CFCast(CFString, CFDictionaryGetValue(attributes, kSecAttrTokenID)), out); + require_quiet(tokenData = CFCast(CFData, CFDictionaryGetValue(attributes, kSecValueData)), out); + } + require_quiet(itemValue = SecTokenItemValueCopy(tokenData, NULL), out); + require_quiet(oid = CFDictionaryGetValue(itemValue, kSecTokenValueObjectIDKey), out); + require_quiet(CFCast(CFData, oid) != NULL, out); } - require(itemValue, out); - CFDataRef oid = CFDictionaryGetValue(itemValue, kSecTokenValueObjectIDKey); - require(oid, out); - CFArrayRef array = CFArrayCreateForCFTypes(kCFAllocatorDefault, class, tokenId, oid, NULL); + CFArrayRef array = CFArrayCreateForCFTypes(kCFAllocatorDefault, class, tokenID, oid, NULL); tokenPersistentRef = CFPropertyListCreateDERData(kCFAllocatorDefault, array, NULL); CFRelease(array); out: @@ -698,9 +704,12 @@ static const uint8_t tk_persistent_ref_id[] = {'t', 'k', 'p', 'r'}; CFDataRef _SecItemCreatePersistentRef(CFTypeRef class, sqlite_int64 rowid, CFDictionaryRef attributes) { CFDataRef result = NULL; - if (attributes && CFDictionaryContainsKey(attributes, CFEqual(class, kSecClassIdentity) ? kSecAttrIdentityCertificateTokenID : kSecAttrTokenID)) { - CFDataRef tokenPersistentRef = CreateTokenPersistentRefData(class, attributes); - require(tokenPersistentRef, out); + CFDataRef tokenPersistentRef = NULL; + if (attributes != NULL) { + tokenPersistentRef = CreateTokenPersistentRefData(class, attributes); + } + + if (tokenPersistentRef != NULL) { CFMutableDataRef tmpData = CFDataCreateMutable(kCFAllocatorDefault, sizeof(tk_persistent_ref_id) + CFDataGetLength(tokenPersistentRef)); CFDataAppendBytes(tmpData, tk_persistent_ref_id, sizeof(tk_persistent_ref_id)); CFDataAppend(tmpData, tokenPersistentRef); @@ -744,7 +753,7 @@ static bool ParseTokenPersistentRefData(CFDataRef persistent_ref, CFStringRef *r CFPropertyListRef pl = NULL; const uint8_t *der = CFDataGetBytePtr(persistent_ref) + sizeof(tk_persistent_ref_id); const uint8_t *der_end = der + (CFDataGetLength(persistent_ref) - sizeof(tk_persistent_ref_id)); - require_quiet(der = der_decode_plist(0, kCFPropertyListImmutable, &pl, NULL, der, der_end), out); + require_quiet(der = der_decode_plist(0, &pl, NULL, der, der_end), out); require_quiet(der == der_end, out); require_quiet(CFGetTypeID(pl) == CFArrayGetTypeID(), out); require_quiet(CFArrayGetCount(pl) == 3, out); @@ -824,16 +833,23 @@ static CFDataRef SecTokenItemValueCreate(CFDataRef oid, CFDataRef access_control } CFDictionaryRef SecTokenItemValueCopy(CFDataRef db_value, CFErrorRef *error) { - CFPropertyListRef plist = NULL; + CFPropertyListRef plist = NULL, result = NULL; + require_quiet(CFCastWithError(CFData, db_value, error), out); const uint8_t *der = CFDataGetBytePtr(db_value); const uint8_t *der_end = der + CFDataGetLength(db_value); - require_quiet(der = der_decode_plist(0, kCFPropertyListImmutable, &plist, error, der, der_end), out); + require_quiet(der = der_decode_plist(0, &plist, error, der, der_end), out); require_action_quiet(der == der_end, out, SecError(errSecDecode, error, CFSTR("trailing garbage at end of token data field"))); - require_action_quiet(CFDictionaryGetValue(plist, kSecTokenValueObjectIDKey) != NULL, out, + CFTypeRef value = CFDictionaryGetValue(plist, kSecTokenValueObjectIDKey); + require_action_quiet(CFCast(CFData, value) != NULL, out, SecError(errSecInternal, error, CFSTR("token based item data does not have OID"))); - + value = CFDictionaryGetValue(plist, kSecTokenValueAccessControlKey); + require_quiet(value == NULL || CFCastWithError(CFData, value, error), out); + value = CFDictionaryGetValue(plist, kSecTokenValueDataKey); + require_quiet(value == NULL || CFCastWithError(CFData, value, error), out); + result = CFRetainSafe(plist); out: - return plist; + CFReleaseNull(plist); + return result; } TKTokenRef SecTokenCreate(CFStringRef token_id, SecCFDictionaryCOW *auth_params, CFErrorRef *error) { @@ -894,6 +910,7 @@ static bool SecTokenItemCreateFromAttributes(CFDictionaryRef attributes, CFDicti CFMutableDictionaryRef attrs = CFDictionaryCreateMutableCopy(NULL, 0, attributes); CFTypeRef token_id = CFDictionaryGetValue(attributes, kSecAttrTokenID); if (token_id != NULL && object_id != NULL) { + require_quiet(CFCastWithError(CFString, token_id, error), out); if (CFRetainSafe(token) == NULL) { require_quiet(token = SecTokenCreate(token_id, &auth_params, error), out); } @@ -946,9 +963,11 @@ static bool SecItemResultCopyPrepared(CFTypeRef raw_result, TKTokenRef token, if (token == NULL) { if (CFGetTypeID(raw_result) == CFDictionaryGetTypeID()) { token_id = CFDictionaryGetValue(raw_result, kSecAttrTokenID); + require_quiet(token_id == NULL || CFCastWithError(CFString, token_id, error) != NULL, out); token_item = (token_id != NULL); cert_token_id = CFDictionaryGetValue(raw_result, kSecAttrIdentityCertificateTokenID); + require_quiet(cert_token_id == NULL || CFCastWithError(CFString, cert_token_id, error) != NULL, out); cert_token_item = (cert_token_id != NULL); } } else { @@ -975,8 +994,11 @@ static bool SecItemResultCopyPrepared(CFTypeRef raw_result, TKTokenRef token, CFDictionaryRef parsed_value = NULL; require_quiet(parsed_value = SecTokenItemValueCopy(value, error), out); object_id = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueObjectIDKey)); + require_quiet(object_id == NULL || CFCastWithError(CFData, object_id, error) != NULL, out); ac_data = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueAccessControlKey)); + require_quiet(ac_data == NULL || CFCastWithError(CFData, ac_data, error) != NULL, out); object_value = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueDataKey)); + require_quiet(object_value == NULL || CFCastWithError(CFData, object_value, error) != NULL, out); CFRelease(parsed_value); if ((wants_data || wants_ref) && object_value == NULL) { // Retrieve value directly from the token. @@ -1044,7 +1066,9 @@ static bool SecItemResultCopyPrepared(CFTypeRef raw_result, TKTokenRef token, CFDictionaryRef parsed_value; require_quiet(parsed_value = SecTokenItemValueCopy(data, error), out); cert_data = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueDataKey)); + require_quiet(cert_data == NULL || CFCastWithError(CFData, cert_data, error) != NULL, out); cert_object_id = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueObjectIDKey)); + require_quiet(cert_object_id == NULL || CFCastWithError(CFData, cert_object_id, error) != NULL, out); CFRelease(parsed_value); if (cert_data == NULL) { // Retrieve value directly from the token. @@ -1110,7 +1134,7 @@ out: } bool SecItemResultProcess(CFDictionaryRef query, CFDictionaryRef auth_params, TKTokenRef token, - CFTypeRef raw_result, CFTypeRef *result, CFErrorRef *error) { + CFTypeRef raw_result, CFTypeRef *result, CFErrorRef *error) { bool ok = false; require_action_quiet(raw_result != NULL, out, ok = true); require_action_quiet(result != NULL, out, ok = true); @@ -1120,9 +1144,16 @@ bool SecItemResultProcess(CFDictionaryRef query, CFDictionaryRef auth_params, TK *result = CFArrayCreateMutableForCFTypes(NULL); for (i = 0; i < count; i++) { CFTypeRef ref; - require_quiet(SecItemResultCopyPrepared(CFArrayGetValueAtIndex(raw_result, i), - token, query, auth_params, &ref, error), out); - if (ref != NULL) { + CFErrorRef localError = NULL; + bool prepared = SecItemResultCopyPrepared(CFArrayGetValueAtIndex(raw_result, i), + token, query, auth_params, &ref, &localError); + if (!prepared) { + // TokenNotFound or TokenObjectNotFound will just not insert failing item into resulting array, other errors abort processing. + require_action_quiet(localError != NULL && CFEqual(CFErrorGetDomain(localError), CFSTR(kTKErrorDomain)) && + (CFErrorGetCode(localError) == kTKErrorCodeTokenNotFound || CFErrorGetCode(localError) == kTKErrorCodeObjectNotFound), out, + CFErrorPropagate(localError, error)); + CFReleaseNull(localError); + } else if (ref != NULL) { CFArrayAppendValue((CFMutableArrayRef)*result, ref); CFRelease(ref); } @@ -1137,27 +1168,9 @@ out: return ok; } -CFDataRef SecItemAttributesCopyPreparedAuthContext(CFTypeRef la_context, CFErrorRef *error) { - void *la_lib = NULL; - CFDataRef acm_context = NULL; - require_action_quiet(la_lib = dlopen("/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication", RTLD_LAZY), out, - SecError(errSecInternal, error, CFSTR("failed to open LocalAuthentication.framework"))); - LAFunctionCopyExternalizedContext fnCopyExternalizedContext = NULL; - require_action_quiet(fnCopyExternalizedContext = dlsym(la_lib, "LACopyExternalizedContext"), out, - SecError(errSecInternal, error, CFSTR("failed to obtain LACopyExternalizedContext"))); - require_action_quiet(acm_context = fnCopyExternalizedContext(la_context), out, - SecError(errSecInternal, error, CFSTR("failed to get ACM handle from LAContext"))); -out: - if (la_lib != NULL) { - dlclose(la_lib); - } - return acm_context; -} - static bool SecItemAttributesPrepare(SecCFDictionaryCOW *attrs, bool forQuery, CFErrorRef *error) { bool ok = false; CFDataRef ac_data = NULL, acm_context = NULL; - void *la_lib = NULL; // If a ref was specified we get its attribute dictionary and parse it. CFTypeRef value = CFDictionaryGetValue(attrs->dictionary, kSecValueRef); @@ -1199,7 +1212,7 @@ static bool SecItemAttributesPrepare(SecCFDictionaryCOW *attrs, bool forQuery, C if (la_context) { require_action_quiet(!CFDictionaryContainsKey(attrs->dictionary, kSecUseCredentialReference), out, SecError(errSecParam, error, CFSTR("kSecUseAuthenticationContext cannot be used together with kSecUseCredentialReference"))); - require_quiet(acm_context = SecItemAttributesCopyPreparedAuthContext(la_context, error), out); + require_quiet(acm_context = LACopyACMContext(la_context, error), out); CFDictionaryRemoveValue(SecCFDictionaryCOWGetMutable(attrs), kSecUseAuthenticationContext); CFDictionarySetValue(SecCFDictionaryCOWGetMutable(attrs), kSecUseCredentialReference, acm_context); } @@ -1227,7 +1240,9 @@ static bool SecItemAttributesPrepare(SecCFDictionaryCOW *attrs, bool forQuery, C value = CFDictionaryGetValue(attrs->dictionary, kSecAttrIssuer); if (value) { /* convert DN to canonical issuer, if value is DN (top level sequence) */ - const DERItem name = { (unsigned char *)CFDataGetBytePtr(value), CFDataGetLength(value) }; + CFDataRef issuer; + require_quiet(issuer = CFCastWithError(CFData, value, error), out); + const DERItem name = { (unsigned char *)CFDataGetBytePtr(issuer), CFDataGetLength(issuer) }; DERDecodedInfo content; if (DERDecodeItem(&name, &content) == DR_Success && content.tag == ASN1_CONSTR_SEQUENCE) { CFDataRef canonical_issuer = createNormalizedX501Name(kCFAllocatorDefault, &content.content); @@ -1246,9 +1261,6 @@ static bool SecItemAttributesPrepare(SecCFDictionaryCOW *attrs, bool forQuery, C ok = true; out: - if (la_lib != NULL) { - dlclose(la_lib); - } CFReleaseSafe(ac_data); CFReleaseSafe(acm_context); return ok; @@ -1475,17 +1487,33 @@ bool SecItemAuthDoQuery(SecCFDictionaryCOW *query, SecCFDictionaryCOW *attribute // Prepare connection to target token if it is present. CFStringRef token_id = CFDictionaryGetValue(query->dictionary, kSecAttrTokenID); - if (secItemOperation != SecItemCopyMatching && token_id != NULL) { - require_quiet(CFAssignRetained(token, SecTokenCreate(token_id, &auth_params, error)), out); + require_quiet(token_id == NULL || CFCastWithError(CFString, token_id, error) != NULL, out); + if (secItemOperation != SecItemCopyMatching && token_id != NULL && !cf_bool_value(CFDictionaryGetValue(query->dictionary, kSecUseTokenRawItems))) { + CFErrorRef localError = NULL; + CFAssignRetained(token, SecTokenCreate(token_id, &auth_params, &localError)); + if (token == NULL) { + require_action_quiet(secItemOperation == SecItemDelete && + CFEqual(CFErrorGetDomain(localError), CFSTR(kTKErrorDomain)) && + CFErrorGetCode(localError) == kTKErrorCodeTokenNotFound, + out, CFErrorPropagate(localError, error)); + + // In case that token cannot be found and deletion is required, just continue and delete item from keychain only. + CFReleaseNull(localError); + } } CFDictionaryRef attrs = (attributes != NULL) ? attributes->dictionary : NULL; - if(!perform(token, query->dictionary, attrs, auth_params.dictionary, error)) { - require_quiet((result = SecItemCreatePairsFromError(error, ac_pairs)) == kSecItemAuthResultOK, out); + if(perform(token, query->dictionary, attrs, auth_params.dictionary, error)) { + result = kSecItemAuthResultOK; + if(error && *error) { + // SecItemAuthDoQuery perform() sometimes returns success and fills in error parameter + secdebug("SecItemAuthDoQuery", "perform() succeded but returned an error: %@", *error); + CFReleaseNull(*error); + } + } else { + result = SecItemCreatePairsFromError(error, ac_pairs); } - result = kSecItemAuthResultOK; - out: return result; }, NULL); @@ -1533,16 +1561,21 @@ static bool dict_to_error_request(enum SecXPCOperation op, CFDictionaryRef query }, NULL); } -static bool cfstring_array_to_error_request(enum SecXPCOperation op, CFStringRef string, CFArrayRef attributes, __unused SecurityClient *client, CFErrorRef *error) +static bool cfstring_array_array_to_error_request(enum SecXPCOperation op, CFStringRef string, CFArrayRef groups, CFArrayRef items, __unused SecurityClient *client, CFErrorRef *error) { return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { if (string) { if (!SecXPCDictionarySetString(message, kSecXPCKeyString, string, error)) return false; } + + if (groups) { + if (!SecXPCDictionarySetPList(message, kSecXPCKeyArray, groups, error)) + return false; + } - if (attributes) { - if (!SecXPCDictionarySetPList(message, kSecXPCKeyQuery, attributes, error)) + if (items) { + if (!SecXPCDictionarySetPList(message, kSecXPCKeyQuery, items, error)) return false; } @@ -1682,6 +1715,16 @@ out: return ok; } +static void countReadOnlyAPICall() { + if (!isReadOnlyAPIRateWithinLimits()) { + } +} + +static void countModifyingAPICall() { + if (!isModifyingAPIRateWithinLimits()) { + } +} + OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) { __block SecCFDictionaryCOW attrs = { attributes }; OSStatus status; @@ -1698,8 +1741,10 @@ OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) { if (token == NULL) { CFTypeRef raw_result = NULL; logUnreasonableDataLength(attributes); - if (!SECURITYD_XPC(sec_item_add, cftype_client_to_bool_cftype_error_request, attributes, SecSecurityClientGet(), &raw_result, error)) + countModifyingAPICall(); + if (!SECURITYD_XPC(sec_item_add, cftype_client_to_bool_cftype_error_request, attributes, SecSecurityClientGet(), &raw_result, error)) { return false; + } bool ok = SecItemResultProcess(attributes, auth_params, token, raw_result, result, error); CFReleaseSafe(raw_result); @@ -1740,8 +1785,10 @@ OSStatus SecItemCopyMatching(CFDictionaryRef inQuery, CFTypeRef *result) { status = SecOSStatusWith(^bool(CFErrorRef *error) { return SecItemAuthDoQuery(&query, NULL, SecItemCopyMatching, error, ^bool(TKTokenRef token, CFDictionaryRef query, CFDictionaryRef attributes, CFDictionaryRef auth_params, CFErrorRef *error) { CFTypeRef raw_result = NULL; - if (!SECURITYD_XPC(sec_item_copy_matching, cftype_client_to_bool_cftype_error_request, query, SecSecurityClientGet(), &raw_result, error)) + countReadOnlyAPICall(); + if (!SECURITYD_XPC(sec_item_copy_matching, cftype_client_to_bool_cftype_error_request, query, SecSecurityClientGet(), &raw_result, error)) { return false; + } // We intentionally pass NULL as token argument, because we want to be able to decide about token on which the item lives // on per-record basis, not wholesale. Logic inside SecItemResultCopyPrepared will open proper token according @@ -1883,6 +1930,7 @@ SecItemUpdateWithError(CFDictionaryRef inQuery, goto errOut; result = SecItemAuthDoQuery(&query, &attributesToUpdate, SecItemUpdate, error, ^bool(TKTokenRef token, CFDictionaryRef query, CFDictionaryRef attributes, CFDictionaryRef auth_params, CFErrorRef *error) { + countModifyingAPICall(); if (token == NULL) { return SecItemRawUpdate(query, attributes, error); } else { @@ -1937,6 +1985,7 @@ OSStatus SecItemDelete(CFDictionaryRef inQuery) { status = SecOSStatusWith(^bool(CFErrorRef *error) { return SecItemAuthDoQuery(&query, NULL, SecItemDelete, error, ^bool(TKTokenRef token, CFDictionaryRef query, CFDictionaryRef attributes, CFDictionaryRef auth_params, CFErrorRef *error) { + countModifyingAPICall(); if (token == NULL) { return SECURITYD_XPC(sec_item_delete, dict_client_to_error_request, query, SecSecurityClientGet(), error); } else { @@ -1945,8 +1994,14 @@ OSStatus SecItemDelete(CFDictionaryRef inQuery) { // Delete item from the token. CFDataRef object_id = CFDictionaryGetValue(object_data, kSecTokenValueObjectIDKey); - require_action_quiet(TKTokenDeleteObject(token, object_id, error), out, - SecTokenProcessError(kAKSKeyOpDelete, token, object_id, error)); + CFErrorRef localError = NULL; + if (!TKTokenDeleteObject(token, object_id, &localError)) { + // Check whether object was not found; in this case, ignore the error. + require_action_quiet(CFEqual(CFErrorGetDomain(localError), CFSTR(kTKErrorDomain)) && + CFErrorGetCode(localError) == kTKErrorCodeObjectNotFound, out, + (CFErrorPropagate(localError, error), SecTokenProcessError(kAKSKeyOpDelete, token, object_id, error))); + CFReleaseNull(localError); + } // Delete the item from the keychain. require_quiet(SECURITYD_XPC(sec_item_delete, dict_client_to_error_request, item_query, @@ -1982,75 +2037,50 @@ SecItemDeleteAll(void) }); } -#if 0 -static bool -agrps_client_to_error_request(enum SecXPCOperation op, CFArrayRef agrps, __unused SecurityClient *client, CFErrorRef *error) -{ - return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - return SecXPCDictionarySetPList(message, kSecXPCKeyAccessGroups, agrps, error); - }, NULL); -} -#endif - bool SecItemDeleteAllWithAccessGroups(CFArrayRef accessGroups, CFErrorRef *error) { -#if 0 - os_activity_t activity = os_activity_create("SecItemDeleteAllWithAccessGroups", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); - os_activity_scope(activity); - os_release(activity); - - return SECURITYD_XPC(sec_delete_items_with_access_groups, agrps_client_to_error_request, accessGroups, - SecSecurityClientGet(), error); -#else return true; -#endif } OSStatus -#if SECITEM_SHIM_OSX -SecItemUpdateTokenItems_ios(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes) -#else -SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes) -#endif +SecItemUpdateTokenItemsForAccessGroups(CFTypeRef tokenID, CFArrayRef accessGroups, CFArrayRef tokenItemsAttributes) { OSStatus status; - os_activity_t activity = os_activity_create("SecItemUpdateTokenItems_ios", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_t activity = os_activity_create("SecItemUpdateTokenItemsForAccessGroups", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); os_activity_scope(activity); os_release(activity); status = SecOSStatusWith(^bool(CFErrorRef *error) { - CFArrayRef tmpArrayRef = tokenItemsAttributes; + bool ok = false; + CFMutableArrayRef tokenItemsForServer = NULL; if (tokenItemsAttributes) { - CFMutableArrayRef tokenItems = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + tokenItemsForServer = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); for (CFIndex i = 0; i < CFArrayGetCount(tokenItemsAttributes); ++i) { CFDictionaryRef itemAttributes = CFArrayGetValueAtIndex(tokenItemsAttributes, i); CFTypeRef accessControl = CFDictionaryGetValue(itemAttributes, kSecAttrAccessControl); CFTypeRef tokenOID = CFDictionaryGetValue(itemAttributes, kSecAttrTokenOID); CFTypeRef valueData = CFDictionaryGetValue(itemAttributes, kSecValueData); if (tokenOID != NULL && accessControl != NULL && CFDataGetTypeID() == CFGetTypeID(accessControl)) { - CFDataRef data = SecTokenItemValueCreate(tokenOID, accessControl, valueData, error); - if (!data) { - CFRelease(tokenItems); - return false; - } - + CFDataRef data; + require_quiet(data = SecTokenItemValueCreate(tokenOID, accessControl, valueData, error), out); CFMutableDictionaryRef attributes = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, itemAttributes); CFDictionarySetValue(attributes, kSecValueData, data); CFDictionarySetValue(attributes, kSecAttrTokenID, tokenID); CFDictionaryRemoveValue(attributes, kSecAttrAccessControl); CFDictionaryRemoveValue(attributes, kSecAttrTokenOID); - CFArrayAppendValue(tokenItems, attributes); - CFRelease(attributes); - CFRelease(data); + CFArrayAppendValue(tokenItemsForServer, attributes); + CFReleaseNull(attributes); + CFReleaseNull(data); + } else { + CFArrayAppendValue(tokenItemsForServer, itemAttributes); } - else - CFArrayAppendValue(tokenItems, itemAttributes); } - - tmpArrayRef = tokenItems; } - return SECURITYD_XPC(sec_item_update_token_items, cfstring_array_to_error_request, tokenID, tmpArrayRef, SecSecurityClientGet(), error); + ok = SECURITYD_XPC(sec_item_update_token_items_for_access_groups, cfstring_array_array_to_error_request, tokenID, accessGroups, tokenItemsForServer, SecSecurityClientGet(), error); + out: + CFReleaseNull(tokenItemsForServer); + return ok; }); return status; diff --git a/OSX/sec/Security/SecItem.m b/OSX/sec/Security/SecItem.m index faa47c88..f1ac3adf 100644 --- a/OSX/sec/Security/SecItem.m +++ b/OSX/sec/Security/SecItem.m @@ -30,6 +30,7 @@ #include #include #include +#import #include @@ -52,7 +53,7 @@ OSStatus _SecItemAddAndNotifyOnSync(CFDictionaryRef attributes, CFTypeRef * CF_R __block CFTypeRef raw_result = NULL; __block CFErrorRef raw_error = NULL; - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { syncCallback(false, (__bridge CFErrorRef)error); }); if (rpc == NULL) { @@ -103,7 +104,7 @@ void SecItemSetCurrentItemAcrossAllDevices(CFStringRef accessGroup, os_activity_scope(activity); @autoreleasepool { - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { complete((__bridge CFErrorRef) error); }); [rpc secItemSetCurrentItemAcrossAllDevices:(__bridge NSData*)newCurrentItemReference @@ -129,7 +130,7 @@ void SecItemFetchCurrentItemAcrossAllDevices(CFStringRef accessGroup, os_activity_scope(activity); @autoreleasepool { - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { complete(NULL, (__bridge CFErrorRef) error); }); [rpc secItemFetchCurrentItemAcrossAllDevices:(__bridge NSString*)accessGroup @@ -147,7 +148,7 @@ void _SecItemFetchDigests(NSString *itemClass, NSString *accessGroup, void (^com os_activity_t activity = os_activity_create("_SecItemFetchDigests", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); os_activity_scope(activity); - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { complete(NULL, error); }); [rpc secItemDigest:itemClass accessGroup:accessGroup complete:complete]; @@ -167,7 +168,7 @@ void _SecKeychainDeleteMultiUser(NSString *musr, void (^complete)(bool, NSError uuid_t musrUUID; [uuid getUUIDBytes:musrUUID]; - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { complete(false, error); }); [rpc secKeychainDeleteMultiuser:[NSData dataWithBytes:musrUUID length:sizeof(uuid_t)] complete:^(bool status, NSError *error) { @@ -179,9 +180,61 @@ void SecItemVerifyBackupIntegrity(BOOL lightweight, void(^completion)(NSDictionary* results, NSError* error)) { @autoreleasepool { - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(true, ^(NSError *error) { completion(@{@"summary" : @"XPC Error"}, error); }); [rpc secItemVerifyBackupIntegrity:lightweight completion:completion]; } } + +OSStatus SecItemDeleteKeychainItemsForAppClip(CFStringRef applicationIdentifier) +{ + __block OSStatus status = errSecInternal; + @autoreleasepool { + id rpc = SecuritydXPCProxyObject(true, ^(NSError *error) { + secerror("xpc: failure to obtain XPC proxy object for app clip deletion, %@", error); + }); + [rpc secItemDeleteForAppClipApplicationIdentifier:(__bridge NSString*)applicationIdentifier + completion:^(OSStatus xpcStatus) { + // Other errors turn into errSecInternal for caller + secnotice("xpc", "app clip deletion result: %i", (int)xpcStatus); + if (xpcStatus == errSecMissingEntitlement || xpcStatus == errSecSuccess) { + status = xpcStatus; + } + }]; + } + return status; +} + +OSStatus SecItemPersistKeychainWritesAtHighPerformanceCost(CFErrorRef* error) +{ + os_activity_t activity = os_activity_create("SecItemPersistKeychainWritesAtHighPerformanceCost", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_scope(activity); + + __block OSStatus status = errSecInternal; + __block CFErrorRef activityError = NULL; + @autoreleasepool { + secnotice("xpc", "This process is requesting a expensive full keychain database checkpoint"); + id rpc = SecuritydXPCProxyObject(true, ^(NSError *error) { + secerror("xpc: failure to obtain XPC proxy object for Item Persistence, %@", error); + activityError = (CFErrorRef)CFBridgingRetain(error); + }); + [rpc secItemPersistKeychainWritesAtHighPerformanceCost:^(OSStatus xpcStatus, + NSError* xpcError) { + if(xpcStatus != errSecSuccess) { + secerror("xpc: Failed to persist keychain writes: %d %@", (int)xpcStatus, xpcError); + activityError = (CFErrorRef)CFBridgingRetain(xpcError); + } else { + secnotice("xpc", "Successfully persisted keychain data to disk"); + } + status = xpcStatus; + }]; + } + if(activityError) { + if(error) { + *error = CFRetainSafe(activityError); + } + CFReleaseNull(activityError); + } + return status; +} diff --git a/OSX/sec/Security/SecItemBackup.c b/OSX/sec/Security/SecItemBackup.c index 614e40d8..9581cb8b 100644 --- a/OSX/sec/Security/SecItemBackup.c +++ b/OSX/sec/Security/SecItemBackup.c @@ -124,6 +124,17 @@ static bool string_string_data_data_data_to_bool_error_request(enum SecXPCOperat }); } +static CFStringRef string_to_string_error_request(enum SecXPCOperation op, CFStringRef viewName, CFErrorRef *error) +{ + __block CFStringRef result = NULL; + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + return SecXPCDictionarySetString(message, kSecXPCKeyString, viewName, error); + }, ^bool(xpc_object_t response, CFErrorRef *error) { + return result = SecXPCDictionaryCopyString(response, kSecXPCKeyResult, error); + }); + return result; +} + static CFArrayRef to_array_error_request(enum SecXPCOperation op, CFErrorRef *error) { __block CFArrayRef result = NULL; @@ -346,6 +357,25 @@ bool SecItemBackupWithRegisteredBackups(CFErrorRef *error, void(^backup)(CFStrin return true; } +static CFStringRef SecItemBackupViewAndCopyBackupPeerID(CFStringRef viewName, CFErrorRef *error) +{ + __block CFStringRef result; + os_activity_initiate("SecItemBackupViewAndCopyBackupPeerID", OS_ACTIVITY_FLAG_DEFAULT, ^{ + result = SECURITYD_XPC(sec_item_backup_ensure_copy_view, string_to_string_error_request, viewName, error); + }); + return result; +} + +bool SecItemBackupWithRegisteredViewBackup(CFStringRef viewName, CFErrorRef *error) { + CFStringRef backupName = SecItemBackupViewAndCopyBackupPeerID(viewName, error); + if(backupName == NULL) { + return false; + } + CFReleaseNull(backupName); + return true; +} + + static bool SecItemBackupDoResetEventBody(const uint8_t *der, const uint8_t *der_end, CFErrorRef *error, void (^handleEvent)(SecBackupEventType et, CFTypeRef key, CFTypeRef item)) { size_t sequence_len; const uint8_t *sequence_body = ccder_decode_len(&sequence_len, der, der_end); @@ -377,7 +407,7 @@ static bool SecItemBackupDoResetEventBody(const uint8_t *der, const uint8_t *der static bool SecItemBackupDoAddEvent(const uint8_t *der, const uint8_t *der_end, CFErrorRef *error, void (^handleEvent)(SecBackupEventType et, CFTypeRef key, CFTypeRef item)) { CFDictionaryRef eventDict = NULL; - const uint8_t *der_end_of_dict = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &eventDict, error, der, der_end); + const uint8_t *der_end_of_dict = der_decode_dictionary(kCFAllocatorDefault, &eventDict, error, der, der_end); if (der_end_of_dict && der_end_of_dict != der_end) { // Can't ever happen! SecError(errSecDecode, error, CFSTR("trailing junk after add")); @@ -589,11 +619,6 @@ void SecItemBackupRestore(CFStringRef backupName, CFStringRef peerID, CFDataRef CFReleaseSafe(localError); } -CFDictionaryRef SecItemBackupCopyMatching(CFDataRef keybag, CFDataRef secret, CFDictionaryRef backup, CFDictionaryRef query, CFErrorRef *error) { - SecError(errSecUnimplemented, error, CFSTR("SecItemBackupCopyMatching unimplemented")); - return NULL; -} - bool SecBackupKeybagAdd(CFDataRef passcode, CFDataRef *identifier, CFURLRef *pathinfo, CFErrorRef *error) { __block bool result = false; os_activity_initiate("_SecServerBackupKeybagAdd", OS_ACTIVITY_FLAG_DEFAULT, ^{ diff --git a/OSX/sec/Security/SecItemBackup.h b/OSX/sec/Security/SecItemBackup.h index b6b73679..c6047c6d 100644 --- a/OSX/sec/Security/SecItemBackup.h +++ b/OSX/sec/Security/SecItemBackup.h @@ -54,6 +54,8 @@ typedef enum SecBackupEventType { bool SecItemBackupWithRegisteredBackups(CFErrorRef *error, void(^backup)(CFStringRef backupName)); +bool SecItemBackupWithRegisteredViewBackup(CFStringRef viewName, CFErrorRef *error); + /*! @function SecItemBackupWithChanges @abstract Tell securityd which keybag (via a persistent ref) to use to backup @@ -85,24 +87,6 @@ bool SecItemBackupSetConfirmedManifest(CFStringRef backupName, CFDataRef keybagD @discussion CloudServices iterates over all the backups, calling this for each backup with peer infos matching the chosen device. */ void SecItemBackupRestore(CFStringRef backupName, CFStringRef peerID, CFDataRef keybag, CFDataRef secret, CFTypeRef backup, void (^completion)(CFErrorRef error)); -/*! - @function SecItemBackupCopyMatching - @abstract Query the contents of a backup dictionary. - @param keybag The bag protecting the backup data. - @param secret Credential to unlock keybag. - @param backup Dictionary returned from SecItemBackupDataSource. - @param query A dictionary containing an item class specification and - optional attributes for controlling the search. See the "Keychain - Search Attributes" section of SecItemCopyMatching for a description of - currently defined search attributes. - @result CFTypeRef reference to the found item(s). The - exact type of the result is based on the search attributes supplied - in the query. Returns NULL and sets *error if there is a failure. - @discussion This allows clients to "restore" a backup and fetch an item from - it without restoring the backup to the keychain, and in particular without - even having a writable keychain around, such as when running in the restore OS. */ -CFDictionaryRef SecItemBackupCopyMatching(CFDataRef keybag, CFDataRef secret, CFDictionaryRef backup, CFDictionaryRef query, CFErrorRef *error); - // Utility function to compute a confirmed manifest from a v0 backup dictionary. CFDataRef SecItemBackupCreateManifest(CFDictionaryRef backup, CFErrorRef *error); diff --git a/OSX/sec/Security/SecItemConstants.c b/OSX/sec/Security/SecItemConstants.c index 38904fe6..a5fd1aa8 100644 --- a/OSX/sec/Security/SecItemConstants.c +++ b/OSX/sec/Security/SecItemConstants.c @@ -120,6 +120,13 @@ SEC_CONST_DECL (kSecAttrPCSPlaintextServiceIdentifier, "pcss"); SEC_CONST_DECL (kSecAttrPCSPlaintextPublicKey, "pcsk"); SEC_CONST_DECL (kSecAttrPCSPlaintextPublicIdentity, "pcsi"); +SEC_CONST_DECL (kSecDataInetExtraNotes, "binn"); +SEC_CONST_DECL (kSecDataInetExtraHistory, "bini"); +SEC_CONST_DECL (kSecDataInetExtraClientDefined0, "bin0"); +SEC_CONST_DECL (kSecDataInetExtraClientDefined1, "bin1"); +SEC_CONST_DECL (kSecDataInetExtraClientDefined2, "bin2"); +SEC_CONST_DECL (kSecDataInetExtraClientDefined3, "bin3"); + /* Predefined access groups constants */ SEC_CONST_DECL (kSecAttrAccessGroupToken, "com.apple.token"); diff --git a/OSX/sec/Security/SecItemInternal.h b/OSX/sec/Security/SecItemInternal.h index c3b02279..33b184f1 100644 --- a/OSX/sec/Security/SecItemInternal.h +++ b/OSX/sec/Security/SecItemInternal.h @@ -101,12 +101,15 @@ TKTokenRef SecTokenCreate(CFStringRef token_id, SecCFDictionaryCOW *auth_params, CFDictionaryRef SecTokenItemValueCopy(CFDataRef db_value, CFErrorRef *error); -CFDataRef SecItemAttributesCopyPreparedAuthContext(CFTypeRef la_context, CFErrorRef *error); - CFArrayRef SecItemCopyParentCertificates_ios(CFDataRef normalizedIssuer, CFArrayRef accessGroups, CFErrorRef *error); bool SecItemCertificateExists(CFDataRef normalizedIssuer, CFDataRef serialNumber, CFArrayRef accessGroups, CFErrorRef *error); +/*! + @constant kSecAttrAppClipItem Boolean attribute indicating whether the origin of this item is an App Clip client +*/ +static const CFStringRef kSecAttrAppClipItem = CFSTR("clip"); + __END_DECLS #endif /* !_SECURITY_SECITEMINTERNAL_H_ */ diff --git a/OSX/sec/Security/SecItemRateLimit.h b/OSX/sec/Security/SecItemRateLimit.h new file mode 100644 index 00000000..b5503a8a --- /dev/null +++ b/OSX/sec/Security/SecItemRateLimit.h @@ -0,0 +1,9 @@ +#ifndef SECITEMRATELIMIT_H_ +#define SECITEMRATELIMIT_H_ + +#include + +bool isReadOnlyAPIRateWithinLimits(void); +bool isModifyingAPIRateWithinLimits(void); + +#endif // SECITEMRATELIMIT_H_ diff --git a/OSX/sec/Security/SecItemRateLimit.m b/OSX/sec/Security/SecItemRateLimit.m new file mode 100644 index 00000000..c18f9edf --- /dev/null +++ b/OSX/sec/Security/SecItemRateLimit.m @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import "SecItemRateLimit.h" +#import "SecItemRateLimit_tests.h" + +#import +#import +#import "ipc/securityd_client.h" + +#import +#import + +// Dressed-down version of RateLimiter which directly computes the rate of one bucket and resets when it runs out of tokens + +// Broken out so the test-only reset method can reinit this +static SecItemRateLimit* ratelimit; + +@implementation SecItemRateLimit { + bool _forceEnabled; + dispatch_queue_t _dataQueue; +} + ++ (instancetype)instance { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + ratelimit = [SecItemRateLimit new]; + }); + return ratelimit; +} + +- (instancetype)init { + if (self = [super init]) { + _roCapacity = 25; // allow burst of this size + _roRate = 3.0; // allow sustained rate of this many per second + _rwCapacity = 25; + _rwRate = 1.0; + _roBucket = nil; + _rwBucket = nil; + _forceEnabled = false; + _limitMultiplier = 5.0; // Multiply capacity and rate by this much after exceeding limit + _dataQueue = dispatch_queue_create("com.apple.keychain.secitemratelimit.dataqueue", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + } + + return self; +} + +- (bool)isEnabled { + return _forceEnabled || [self shouldCountAPICalls]; +} + +- (void)forceEnabled:(bool)force { + _forceEnabled = force; + secnotice("secitemratelimit", "%sorcing SIRL to be enabled (effective: %i)", force ? "F" : "Not f", [self isEnabled]); +} + +- (bool)isReadOnlyAPICallWithinLimits { + if (![self consumeTokenFromBucket:false]) { + secnotice("secitemratelimit", "Readonly API rate exceeded"); + return false; + } else { + return true; + } +} + +- (bool)isModifyingAPICallWithinLimits { + if (![self consumeTokenFromBucket:true]) { + secnotice("secitemratelimit", "Modifying API rate exceeded"); + return false; + } else { + return true; + } +} + +- (bool)consumeTokenFromBucket:(bool)readwrite { + if (![self shouldCountAPICalls] && !_forceEnabled) { + return true; + } + + __block bool ok = false; + dispatch_sync(_dataQueue, ^{ + int* capacity = readwrite ? &_rwCapacity : &_roCapacity; + double* rate = readwrite ? &_rwRate : &_roRate; + NSDate* __strong* bucket = readwrite ? &_rwBucket : &_roBucket; + + NSDate* now = [NSDate now]; + NSDate* fullBucket = [now dateByAddingTimeInterval:-(*capacity * (1.0 / *rate))]; + // bucket has more tokens than a 'full' bucket? This prevents occasional-but-bursty activity slipping through + if (!*bucket || [*bucket timeIntervalSinceDate: fullBucket] < 0) { + *bucket = fullBucket; + } + + *bucket = [*bucket dateByAddingTimeInterval:1.0 / *rate]; + ok = [*bucket timeIntervalSinceDate:now] <= 0; + + // Get a new bucket next time so we only complain every now and then + if (!ok) { + *bucket = nil; + *capacity *= _limitMultiplier; + *rate *= _limitMultiplier; + } + }); + + return ok; +} + +- (bool)shouldCountAPICalls { + static bool shouldCount = false; + static dispatch_once_t shouldCountToken; + dispatch_once(&shouldCountToken, ^{ + if (!SecIsInternalRelease()) { + secnotice("secitemratelimit", "Not internal release, disabling SIRL"); + return; + } + + // gSecurityd is the XPC elision mechanism for testing; don't want simcrashes during tests + if (gSecurityd != nil) { + secnotice("secitemratelimit", "gSecurityd non-nil, disabling SIRL for testing"); + return; + } + + if (!os_feature_enabled(Security, SecItemRateLimiting)) { + secnotice("secitemratelimit", "SIRL disabled via feature flag"); + return; + } + + SecTaskRef task = SecTaskCreateFromSelf(NULL); + NSMutableArray* exempt = [NSMutableArray arrayWithArray:@[@"com.apple.pcsstatus", @"com.apple.protectedcloudstorage.protectedcloudkeysyncing", @"com.apple.cloudd", @"com.apple.pcsctl"]]; + CFStringRef identifier = NULL; + require_action_quiet(task, cleanup, secerror("secitemratelimit: unable to get task from self, disabling SIRL")); + + // If not a valid or debugged platform binary, don't count + uint32_t flags = SecTaskGetCodeSignStatus(task); + require_action_quiet((flags & (CS_VALID | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) == (CS_VALID | CS_PLATFORM_BINARY) || + (flags & (CS_DEBUGGED | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) == (CS_DEBUGGED | CS_PLATFORM_BINARY), + cleanup, secnotice("secitemratelimit", "Not valid/debugged platform binary, disabling SIRL")); + + // Some processes have legitimate need to query or modify a large number of items + identifier = SecTaskCopySigningIdentifier(task, NULL); + require_action_quiet(identifier, cleanup, secerror("secitemratelimit: unable to get signing identifier, disabling SIRL")); +#if TARGET_OS_OSX + [exempt addObjectsFromArray:@[@"com.apple.keychainaccess", @"com.apple.Safari"]]; +#elif TARGET_OS_IOS + [exempt addObjectsFromArray:@[@"com.apple.mobilesafari", @"com.apple.Preferences"]]; +#endif + if ([exempt containsObject:(__bridge NSString*)identifier]) { + secnotice("secitemratelimit", "%@ exempt from SIRL", identifier); + goto cleanup; + } + + secnotice("secitemratelimit", "valid/debugged platform binary %@ on internal release, enabling SIRL", identifier); + shouldCount = true; + +cleanup: + CFReleaseNull(task); + CFReleaseNull(identifier); + }); + return shouldCount; +} + +// Testing ++ (instancetype)getStaticRateLimit { + return [SecItemRateLimit instance]; +} + +// Testing and super thread-UNsafe. Caveat emptor. ++ (void)resetStaticRateLimit { + ratelimit = [SecItemRateLimit new]; +} + +@end + +bool isReadOnlyAPIRateWithinLimits(void) { + return [[SecItemRateLimit instance] isReadOnlyAPICallWithinLimits]; +} + +bool isModifyingAPIRateWithinLimits(void) { + return [[SecItemRateLimit instance] isModifyingAPICallWithinLimits]; +} diff --git a/OSX/sec/Security/SecItemRateLimit_tests.h b/OSX/sec/Security/SecItemRateLimit_tests.h new file mode 100644 index 00000000..c79c9472 --- /dev/null +++ b/OSX/sec/Security/SecItemRateLimit_tests.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef SecItemRateLimit_tests_h +#define SecItemRateLimit_tests_h + +#import "SecItemRateLimit.h" +#import + +// Broken out into header for testing convenience. +// If you need this, why? +@interface SecItemRateLimit : NSObject + +@property (nonatomic, readonly) int roCapacity; +@property (nonatomic, readonly) double roRate; +@property (nonatomic, readonly) int rwCapacity; +@property (nonatomic, readonly) double rwRate; +@property (nonatomic, readonly) double limitMultiplier; + +@property (nonatomic, readonly) NSDate* roBucket; +@property (nonatomic, readonly) NSDate* rwBucket; + +- (bool)shouldCountAPICalls; +- (bool)isEnabled; +- (void)forceEnabled:(bool)force; + ++ (instancetype)getStaticRateLimit; ++ (void)resetStaticRateLimit; + +@end + +#endif /* SecItemRateLimit_tests_h */ diff --git a/OSX/sec/Security/SecItemShim.h b/OSX/sec/Security/SecItemShim.h index 02b89f36..862dd996 100644 --- a/OSX/sec/Security/SecItemShim.h +++ b/OSX/sec/Security/SecItemShim.h @@ -47,7 +47,6 @@ OSStatus SecItemAdd_ios(CFDictionaryRef attributes, CFTypeRef *result); OSStatus SecItemCopyMatching_ios(CFDictionaryRef query, CFTypeRef *result); OSStatus SecItemUpdate_ios(CFDictionaryRef query, CFDictionaryRef attributesToUpdate); OSStatus SecItemDelete_ios(CFDictionaryRef query); -OSStatus SecItemUpdateTokenItems_ios(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes); OSStatus SecKeyGeneratePair_ios(CFDictionaryRef parameters, SecKeyRef *publicKey, SecKeyRef *privateKey); SecKeyRef SecKeyCreateRandomKey_ios(CFDictionaryRef parameters, CFErrorRef *error); @@ -58,7 +57,6 @@ SecKeyRef SecKeyCreateRandomKey_ios(CFDictionaryRef parameters, CFErrorRef *erro #define SecItemCopyMatching SecItemCopyMatching_ios #define SecItemUpdate SecItemUpdate_ios #define SecItemDelete SecItemDelete_ios -#define SecItemUpdateTokenItems SecItemUpdateTokenItems_ios #define SecKeyGeneratePair SecKeyGeneratePair_ios #define SecKeyCreateRandomKey SecKeyCreateRandomKey_ios diff --git a/OSX/sec/Security/SecKey.m b/OSX/sec/Security/SecKey.m index 218f1a9b..723a8bb7 100644 --- a/OSX/sec/Security/SecKey.m +++ b/OSX/sec/Security/SecKey.m @@ -60,6 +60,8 @@ #include /* For error codes. */ #include +#include +#include #include #include @@ -689,7 +691,7 @@ out: return status; } -static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding(SecKeyRef key, SecPadding padding) { +static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding(SecKeyRef key, SecPadding padding, size_t digestSize) { switch (SecKeyGetAlgorithmId(key)) { case kSecRSAAlgorithmID: { switch (padding) { @@ -715,6 +717,22 @@ static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding(SecKeyRef key, SecP switch (padding) { case kSecPaddingSigRaw: return kSecKeyAlgorithmECDSASignatureRFC4754; + case kSecPaddingPKCS1: { + // If digest has known size of some hash function, explicitly encode that hash type in the algorithm. + if (digestSize == ccsha1_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA1; + } else if (digestSize == ccsha224_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA224; + } else if (digestSize == ccsha256_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA256; + } else if (digestSize == ccsha384_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA384; + } else if (digestSize == ccsha512_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA512; + } + + // Fall through to common case, no break here. + } default: // Although it is not very logical, previous SecECKey implementation really considered // anything else than SigRaw (incl. None!) as PKCS1 (i.e. x962), so we keep the behaviour @@ -727,7 +745,7 @@ static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding(SecKeyRef key, SecP } #if TARGET_OS_OSX -static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding_macOS(SecKeyRef key, SecPadding padding) { +static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding_macOS(SecKeyRef key, SecPadding padding, size_t digestSize) { switch (SecKeyGetAlgorithmId(key)) { case kSecRSAAlgorithmID: { // On CSSM-based implementation, these functions actually did hash its input, @@ -755,6 +773,22 @@ static SecKeyAlgorithm SecKeyGetSignatureAlgorithmForPadding_macOS(SecKeyRef key switch (padding) { case kSecPaddingSigRaw: return kSecKeyAlgorithmECDSASignatureRFC4754; + case kSecPaddingPKCS1: { + // If digest has known size of some hash function, explicitly encode that hash type in the algorithm. + if (digestSize == ccsha1_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA1; + } else if (digestSize == ccsha224_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA224; + } else if (digestSize == ccsha256_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA256; + } else if (digestSize == ccsha384_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA384; + } else if (digestSize == ccsha512_di()->output_size) { + return kSecKeyAlgorithmECDSASignatureDigestX962SHA512; + } + + // Fall through to common case, no break here. + } default: // Although it is not very logical, previous SecECKey implementation really considered // anything else than SigRaw (incl. None!) as PKCS1 (i.e. x962), so we keep the behaviour @@ -775,7 +809,7 @@ OSStatus SecKeyRawSign( size_t dataToSignLen, /* length of dataToSign */ uint8_t *sig, /* signature, RETURNED */ size_t *sigLen) { /* IN/OUT */ - SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding(key, padding); + SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding(key, padding, dataToSignLen); if (algorithm == NULL) { return errSecParam; } @@ -793,7 +827,7 @@ OSStatus SecKeyRawSign_macOS( size_t dataToSignLen, /* length of dataToSign */ uint8_t *sig, /* signature, RETURNED */ size_t *sigLen) { /* IN/OUT */ - SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding_macOS(key, padding); + SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding_macOS(key, padding, dataToSignLen); if (algorithm == NULL) { return errSecParam; } @@ -812,7 +846,7 @@ OSStatus SecKeyRawVerify( size_t signedDataLen, /* length of dataToSign */ const uint8_t *sig, /* signature */ size_t sigLen) { /* length of signature */ - SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding(key, padding); + SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding(key, padding, signedDataLen); if (algorithm == NULL) { return errSecParam; } @@ -832,7 +866,7 @@ OSStatus SecKeyRawVerify_macOS( size_t signedDataLen, /* length of dataToSign */ const uint8_t *sig, /* signature */ size_t sigLen) { /* length of signature */ - SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding_macOS(key, padding); + SecKeyAlgorithm algorithm = SecKeyGetSignatureAlgorithmForPadding_macOS(key, padding, signedDataLen); if (algorithm == NULL) { return errSecParam; } @@ -1199,7 +1233,7 @@ OSStatus SecKeyCopyPersistentRef(SecKeyRef key, CFDataRef* persistentRef) if (!persistentRef) { secerror("SecKeyCopyPersistentRef: Need a persistentRef pointer for this to work"); return errSecParam; - } + } CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecReturnPersistentRef, kCFBooleanTrue, diff --git a/OSX/sec/Security/SecKeyAdaptors.m b/OSX/sec/Security/SecKeyAdaptors.m index 07a8b98b..3e0868cf 100644 --- a/OSX/sec/Security/SecKeyAdaptors.m +++ b/OSX/sec/Security/SecKeyAdaptors.m @@ -716,12 +716,12 @@ static CFTypeRef SecKeyECDHCopyX963Result(SecKeyOperationContext *context, const CFMutableDataRef kdfResult = CFDataCreateMutableWithScratch(kCFAllocatorDefault, requestedSize); int err = ccansikdf_x963(di, CFDataGetLength(sharedSecret), CFDataGetBytePtr(sharedSecret), sharedInfoLength, sharedInfo, requestedSize, CFDataGetMutableBytePtr(kdfResult)); - require_noerr_action_quiet(err, out, (CFReleaseNull(result), + require_noerr_action_quiet(err, out, (CFReleaseNull(kdfResult), SecError(errSecParam, error, CFSTR("ECDHKeyExchange wrong input (%d)"), err))); CFAssignRetained(result, kdfResult); } else { // In test-only mode, propagate result (YES/NO) of underlying operation. - result = CFRetainAssign(result, sharedSecret); + CFRetainAssign(result, sharedSecret); } out: CFReleaseNull(sharedSecret); @@ -949,8 +949,11 @@ out: static CFDataRef SecKeyECIESDecryptAESGCMCopyResult(CFDataRef keyExchangeResult, CFDataRef inData, CFDictionaryRef inParams, CFErrorRef *error) { CFDataRef result = NULL; - CFMutableDataRef plaintext = CFDataCreateMutableWithScratch(kCFAllocatorDefault, CFDataGetLength(inData) - kSecKeyIESTagLength); - CFMutableDataRef tag = CFDataCreateMutableWithScratch(SecCFAllocatorZeroize(), kSecKeyIESTagLength); + CFMutableDataRef plaintext = NULL; + CFMutableDataRef tag = NULL; + require_action_quiet(CFDataGetLength(inData) >= kSecKeyIESTagLength, out, SecError(errSecParam, error, CFSTR("ECIES: Input data too short"))); + plaintext = CFDataCreateMutableWithScratch(kCFAllocatorDefault, CFDataGetLength(inData) - kSecKeyIESTagLength); + tag = CFDataCreateMutableWithScratch(SecCFAllocatorZeroize(), kSecKeyIESTagLength); CFDataGetBytes(inData, CFRangeMake(CFDataGetLength(inData) - kSecKeyIESTagLength, kSecKeyIESTagLength), CFDataGetMutableBytePtr(tag)); CFIndex aesKeySize = CFDataGetLength(keyExchangeResult) - sizeof(kSecKeyIESIV); diff --git a/OSX/sec/Security/SecKeyProxy.m b/OSX/sec/Security/SecKeyProxy.m index 94855948..b5a0e980 100644 --- a/OSX/sec/Security/SecKeyProxy.m +++ b/OSX/sec/Security/SecKeyProxy.m @@ -136,7 +136,11 @@ @implementation SecKeyProxy - (instancetype)initWithKey:(SecKeyRef)key certificate:(nullable NSData *)certificate { if (self = [super init]) { - _key = CFBridgingRelease(CFRetain(key)); + if (key != nil) { + _key = CFBridgingRelease(CFRetainSafe(key)); + } else { + _key = nil; + } _certificate = certificate; _listener = [NSXPCListener anonymousListener]; _listener.delegate = self; diff --git a/OSX/utilities/SecADWrapper.h b/OSX/sec/Security/SecKnownFilePaths.h similarity index 68% rename from OSX/utilities/SecADWrapper.h rename to OSX/sec/Security/SecKnownFilePaths.h index 3ea457f0..f1cd8051 100644 --- a/OSX/utilities/SecADWrapper.h +++ b/OSX/sec/Security/SecKnownFilePaths.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,15 +21,15 @@ * @APPLE_LICENSE_HEADER_END@ */ -#ifndef SecADWrapper_h -#define SecADWrapper_h +#ifndef SecKnownFilePaths_h +#define SecKnownFilePaths_h -#include #include -extern void SecADClearScalarKey(CFStringRef key); -extern void SecADSetValueForScalarKey(CFStringRef key, int64_t value); -extern void SecADAddValueForScalarKey(CFStringRef key, int64_t value); -extern void SecADClientPushValueForDistributionKey(CFStringRef key, int64_t value); +CFURLRef SecCopyHomeURL(void); +CFURLRef SecCopyBaseFilesURL(bool system); -#endif /* SecADWrapper_h */ +void SecSetCustomHomeURL(CFURLRef url); +void SecSetCustomHomeURLString(CFStringRef home_path); + +#endif /* SecKnownFilePaths_h */ diff --git a/OSX/sec/Security/SecOTR.h b/OSX/sec/Security/SecOTR.h index 743320a2..d79b0ebe 100644 --- a/OSX/sec/Security/SecOTR.h +++ b/OSX/sec/Security/SecOTR.h @@ -56,8 +56,13 @@ typedef struct _SecOTRPublicIdentity* SecOTRPublicIdentityRef; * Full identity functions */ SecOTRFullIdentityRef SecOTRFullIdentityCreate(CFAllocatorRef allocator, CFErrorRef *error); - + +// This variant is used by MessageProtection that doesn't use persistent references anymore. SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRef(CFAllocatorRef allocator, SecKeyRef privateKey, + CFErrorRef *error); + +// This variant is used by SOS, and still relies on privateKey having a persistent reference. +SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRefSOS(CFAllocatorRef allocator, SecKeyRef privateKey, CFErrorRef *error); SecOTRFullIdentityRef SecOTRFullIdentityCreateFromData(CFAllocatorRef allocator, CFDataRef serializedData, CFErrorRef *error); diff --git a/OSX/sec/Security/SecOTRDHKey.c b/OSX/sec/Security/SecOTRDHKey.c index 221274d7..492eef0e 100644 --- a/OSX/sec/Security/SecOTRDHKey.c +++ b/OSX/sec/Security/SecOTRDHKey.c @@ -31,8 +31,7 @@ #include #include #include - -#include +#include #define kECKeySize 256 @@ -177,7 +176,7 @@ fail: OSStatus SecFDHKNewKey(SecOTRFullDHKeyRef fullKey) { - struct ccrng_state *rng=ccDRBGGetRngState(); + struct ccrng_state *rng=ccrng(NULL); // We need compact keys, maybe we should be using // ccecdh_generate_key or ccechd_generate_compact_key, but for now ecdh are fine for compact use IFF we don't diff --git a/OSX/sec/Security/SecOTRFullIdentity.c b/OSX/sec/Security/SecOTRFullIdentity.c index 877863eb..c38b51ca 100644 --- a/OSX/sec/Security/SecOTRFullIdentity.c +++ b/OSX/sec/Security/SecOTRFullIdentity.c @@ -186,7 +186,7 @@ errOut: SecOTRFullIdentityRef SecOTRFullIdentityCreate(CFAllocatorRef allocator, CFErrorRef *error) { SecKeyRef signingKey = SecOTRCreateSigningKey(allocator); - SecOTRFullIdentityRef newID = SecOTRFullIdentityCreateFromSecKeyRef(allocator, signingKey, error); + SecOTRFullIdentityRef newID = SecOTRFullIdentityCreateFromSecKeyRefSOS(allocator, signingKey, error); CFReleaseNull(signingKey); return newID; @@ -298,7 +298,8 @@ OSStatus SecOTRFIInitFromV2Bytes(SecOTRFullIdentityRef newID, CFAllocatorRef all --*size; require_noerr_quiet(status = SecOTRFICreateKeysFromReadPersistentRefAndPublicKey(bytes, size, &newID->publicSigningKey, &newID->privateSigningKey, &newID->privateKeyPersistentRef, &CreateECPublicKeyFrom), fail); - + newID->isMessageProtectionKey = false; + return status; fail: @@ -309,6 +310,49 @@ fail: return status; } +static +OSStatus SecOTRFIInitFromV3Bytes(SecOTRFullIdentityRef newID, CFAllocatorRef allocator, + const uint8_t **bytes,size_t *size) { + OSStatus status = errSecInvalidData; + require_action(**bytes == 3, fail, status = errSecParam); + ++*bytes; + --*size; + + uint16_t dataSize; + require_noerr_quiet(readSize(bytes, size, &dataSize), fail); + + int32_t keysz32 = 256; + CFNumberRef ksizeNumber = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFDataRef keyBytes = CFDataCreate(allocator, *bytes, dataSize); + + CFDictionaryRef dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrKeySizeInBits, ksizeNumber, + kSecAttrIsPermanent, kCFBooleanFalse, NULL); + + CFErrorRef error; + SecKeyRef key = SecKeyCreateWithData(keyBytes, dict, &error); + + CFReleaseSafe(dict); + CFReleaseSafe(keyBytes); + CFReleaseSafe(ksizeNumber); + + if (key == NULL) { + CFRelease(error); + return errSecInvalidData; + } + + newID->privateKeyPersistentRef = NULL; + newID->isMessageProtectionKey = true; + newID->privateSigningKey = key; + newID->publicSigningKey = SecKeyCopyPublicKey(newID->privateSigningKey); + status = errSecSuccess; + +fail: + return status; +} + // TODO: Probably move to SecKey static CFDataRef SecKeyCreatePersistentRef(SecKeyRef theKey, CFErrorRef *error) { CFDataRef persistentRef = NULL; @@ -320,13 +364,27 @@ static CFDataRef SecKeyCreatePersistentRef(SecKeyRef theKey, CFErrorRef *error) SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRef(CFAllocatorRef allocator, SecKeyRef privateKey, CFErrorRef *error) { - // TODO - make sure this is an appropriate key type - SecOTRFullIdentityRef newID = CFTypeAllocate(SecOTRFullIdentity, struct _SecOTRFullIdentity, allocator); - CFRetainAssign(newID->privateSigningKey, privateKey); - require_action(newID->publicSigningKey = SecKeyCreatePublicFromPrivate(privateKey), fail, - SecError(errSecInternalComponent, error, CFSTR("Failed to extract public key from private key"))); + // TODO - make sure this is an appropriate key type + SecOTRFullIdentityRef newID = CFTypeAllocate(SecOTRFullIdentity, struct _SecOTRFullIdentity, allocator); + CFRetainAssign(newID->privateSigningKey, privateKey); + require_action(newID->publicSigningKey = SecKeyCreatePublicFromPrivate(privateKey), fail, + SecError(errSecInternalComponent, error, CFSTR("Failed to extract public key from private key"))); + // MessageProtection keys are no longer having persistent references. + newID->privateKeyPersistentRef = NULL; + newID->isMessageProtectionKey = true; + + require(SecOTRFICachePublicHash(newID, error), fail); + return newID; + fail: + CFReleaseNull(newID); + return NULL; +} + +SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRefSOS(CFAllocatorRef allocator, SecKeyRef privateKey, + CFErrorRef *error) { + SecOTRFullIdentityRef newID = SecOTRFullIdentityCreateFromSecKeyRef(allocator, privateKey, error); require(newID->privateKeyPersistentRef = SecKeyCreatePersistentRef(privateKey, error), fail); - require(SecOTRFICachePublicHash(newID, error), fail); + newID->isMessageProtectionKey = false; return newID; fail: CFReleaseNull(newID); @@ -347,6 +405,9 @@ SecOTRFullIdentityRef SecOTRFullIdentityCreateFromBytes(CFAllocatorRef allocator case 2: require_noerr_action_quiet(status = SecOTRFIInitFromV2Bytes(newID, allocator, bytes, size), fail, SecError(status, error, CFSTR("failed to decode v2 otr session: %d"), (int)status)); break; + case 3: + require_noerr_action_quiet(status = SecOTRFIInitFromV3Bytes(newID, allocator, bytes, size), fail, SecError(status, error, CFSTR("failed to decode v3 otr session: %d"), (int)status)); + break; case 0: // Version 0 was used in seeds of 5.0, transition from those seeds unsupported - keys were in exported data. default: SecError(errSecParam, error, CFSTR("unknown otr session version %hhu"), **bytes); @@ -432,6 +493,23 @@ bool SecOTRFIPurgeAllFromKeychain(CFErrorRef *error) } } +static OSStatus SecOTRFIAppendV3Serialization(SecOTRFullIdentityRef fullID, CFMutableDataRef serializeInto) +{ + const uint8_t version = 3; + CFIndex start = CFDataGetLength(serializeInto); + CFDataAppendBytes(serializeInto, &version, sizeof(version)); + CFErrorRef error = nil; + CFDataRef privKeyBytes = SecKeyCopyExternalRepresentation(fullID->privateSigningKey, &error); + require(privKeyBytes != nil, fail); + appendSizeAndData(privKeyBytes, serializeInto); + CFReleaseSafe(privKeyBytes); + return errSecSuccess; + +fail: + CFDataSetLength(serializeInto, start); + + return errSecParam; +} static OSStatus SecOTRFIAppendV2Serialization(SecOTRFullIdentityRef fullID, CFMutableDataRef serializeInto) { @@ -452,7 +530,13 @@ fail: bool SecOTRFIAppendSerialization(SecOTRFullIdentityRef fullID, CFMutableDataRef serializeInto, CFErrorRef *error) { - OSStatus status = SecOTRFIAppendV2Serialization(fullID, serializeInto); + OSStatus status = errSecParam; + if (fullID->isMessageProtectionKey) { + status = SecOTRFIAppendV3Serialization(fullID, serializeInto); + } else { + status = SecOTRFIAppendV2Serialization(fullID, serializeInto); + } + if (errSecSuccess == status) { return true; } else { diff --git a/OSX/sec/Security/SecOTRIdentityPriv.h b/OSX/sec/Security/SecOTRIdentityPriv.h index 8ce081c9..61b288ea 100644 --- a/OSX/sec/Security/SecOTRIdentityPriv.h +++ b/OSX/sec/Security/SecOTRIdentityPriv.h @@ -52,7 +52,8 @@ struct _SecOTRFullIdentity { SecKeyRef publicSigningKey; SecKeyRef privateSigningKey; CFDataRef privateKeyPersistentRef; - + + bool isMessageProtectionKey; uint8_t publicIDHash[kMPIDHashSize]; }; diff --git a/OSX/sec/Security/SecOTRPacketData.h b/OSX/sec/Security/SecOTRPacketData.h index 81dc4409..fc84f8c4 100644 --- a/OSX/sec/Security/SecOTRPacketData.h +++ b/OSX/sec/Security/SecOTRPacketData.h @@ -39,80 +39,84 @@ #include +#include + __BEGIN_DECLS -static CC_NONNULL((1,2)) -OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected); +CF_ASSUME_NONNULL_BEGIN -static CC_NONNULL((1,2)) -OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected); +static +OSStatus ReadAndVerifyByte(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint8_t expected); -static CC_NONNULL((1,2)) -OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected); +static +OSStatus ReadAndVerifyShort(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint16_t expected); -static CC_NONNULL((1,2,3,4)) -OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size, - const uint8_t **dataBytes, size_t *dataSize); -static CC_NONNULL((1,2,3,4)) -OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size, - const uint8_t **mpiBytes, size_t *mpiSize); +static +OSStatus ReadAndVerifyMessageType(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, OTRMessageType expected); + +static +OSStatus SizeAndSkipDATA(const uint8_t *_Nonnull *_Nonnull bytes, size_t *size, + const uint8_t *_Nonnull *_Nonnull dataBytes, size_t *dataSize); +static +OSStatus SizeAndSkipMPI(const uint8_t *_Nonnull *_Nonnull bytes, size_t *size, + const uint8_t *_Nonnull *_Nonnull mpiBytes, size_t *mpiSize); -static CC_NONNULL((1,2,3)) -OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value); +static +OSStatus ReadLongLongCompact(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint64_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value); +static +OSStatus ReadLongLong(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint64_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value); +static +OSStatus ReadLong(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint32_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value); +static +OSStatus ReadShort(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint16_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value); +static +OSStatus ReadByte(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint8_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type); +static +OSStatus ReadMessageType(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, OTRMessageType* type); -static CC_NONNULL((1,2,4)) -OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x); +static +OSStatus ReadMPI(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x); -static CC_NONNULL((1,2,3,4)) -OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data); +static +OSStatus ReadDATA(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data); -static CC_NONNULL((1,2,3)) -OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId); +static +OSStatus CreatePublicKey(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, _Nonnull SecOTRPublicIdentityRef *_Nonnull publicId); -static CC_NONNULL((1,2,3)) -CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr); +static +CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef _Nullable allocator, const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr); -static CC_NONNULL((1)) +static void AppendLongLongCompact(CFMutableDataRef appendTo, uint64_t value); -static CC_NONNULL((1)) +static void AppendLongLong(CFMutableDataRef appendTo, uint64_t value); -static CC_NONNULL((1)) +static void AppendLong(CFMutableDataRef appendTo, uint32_t value); -static CC_NONNULL((1)) +static void AppendShort(CFMutableDataRef appendTo, uint16_t value); -static CC_NONNULL((1)) +static void AppendByte(CFMutableDataRef appendTo, uint8_t type); -static CC_NONNULL((1)) +static void AppendMessageType(CFMutableDataRef appendTo, OTRMessageType type); -static CC_NONNULL((1,3)) +static void AppendMPI(CFMutableDataRef appendTo, cc_size n, const cc_unit *x); -static CC_NONNULL((1,3)) +static void AppendDATA(CFMutableDataRef appendTo, size_t size, const uint8_t*data); -static CC_NONNULL((1,2)) +static void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId); @@ -122,7 +126,7 @@ void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId static uint16_t kCurrentOTRVersion = 0x2; -static inline OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value) +static inline OSStatus ReadLongLong(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint64_t* value) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -146,7 +150,7 @@ fail: return errSecParam; } -static inline OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value) +static inline OSStatus ReadLongLongCompact(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint64_t* value) { bool moreBytes = true; @@ -172,7 +176,7 @@ fail: return !moreBytes ? errSecSuccess : errSecDecode; } -static inline OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value) +static inline OSStatus ReadLong(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint32_t* value) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -192,7 +196,7 @@ fail: return errSecParam; } -static inline OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value) +static inline OSStatus ReadShort(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint16_t* value) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -210,7 +214,7 @@ fail: return errSecParam; } -static inline OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value) +static inline OSStatus ReadByte(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint8_t* value) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -227,7 +231,7 @@ fail: return errSecParam; } -static inline OSStatus ReadByteAsBool(const uint8_t**bytesPtr, size_t*sizePtr, bool* value) +static inline OSStatus ReadByteAsBool(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, bool* value) { uint8_t byte = 0; @@ -239,7 +243,7 @@ static inline OSStatus ReadByteAsBool(const uint8_t**bytesPtr, size_t*sizePtr, b return result; } -static inline OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type) +static inline OSStatus ReadMessageType(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, OTRMessageType* type) { OSStatus result = errSecParam; uint8_t value; @@ -252,7 +256,7 @@ fail: return result; } -static inline OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x) +static inline OSStatus ReadMPI(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -276,7 +280,7 @@ fail: } -static inline OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data) +static inline OSStatus ReadDATA(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -301,7 +305,7 @@ fail: } -static inline OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId) +static inline OSStatus CreatePublicKey(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, _Nonnull SecOTRPublicIdentityRef *_Nonnull publicId) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -336,7 +340,7 @@ fail: } -static inline CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr) +static inline CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef _Nullable allocator, const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr) { CFMutableDataRef result = NULL; uint32_t sizeInStream; @@ -359,7 +363,7 @@ exit: // // Parse and verify functions // -static inline OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected) +static inline OSStatus ReadAndVerifyByte(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint8_t expected) { uint8_t found; OSStatus result = ReadByte(bytes, size, &found); @@ -369,7 +373,7 @@ exit: return result; } -static inline OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected) +static inline OSStatus ReadAndVerifyShort(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint16_t expected) { uint16_t found; OSStatus result = ReadShort(bytes, size, &found); @@ -379,7 +383,7 @@ exit: return result; } -static inline OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected) +static inline OSStatus ReadAndVerifyMessageType(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, OTRMessageType expected) { OTRMessageType found; OSStatus result = ReadMessageType(bytes, size, &found); @@ -389,12 +393,12 @@ exit: return result; } -static inline OSStatus ReadAndVerifyVersion(const uint8_t**bytes, size_t*size) +static inline OSStatus ReadAndVerifyVersion(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size) { return ReadAndVerifyShort(bytes, size, kCurrentOTRVersion); } -static inline OSStatus ReadAndVerifyHeader(const uint8_t**bytes, size_t*size, OTRMessageType expected) +static inline OSStatus ReadAndVerifyHeader(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, OTRMessageType expected) { OSStatus result = ReadAndVerifyVersion(bytes, size); require_noerr_quiet(result, exit); @@ -406,7 +410,7 @@ exit: return result; } -static inline OSStatus ReadHeader(const uint8_t**bytes, size_t*size, OTRMessageType *messageType) +static inline OSStatus ReadHeader(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, OTRMessageType *messageType) { OSStatus result = ReadAndVerifyVersion(bytes, size); require_noerr_quiet(result, exit); @@ -418,8 +422,8 @@ exit: return result; } -static inline OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size, - const uint8_t **dataBytes, size_t *dataSize) +static inline OSStatus SizeAndSkipDATA(const uint8_t *_Nonnull *_Nonnull bytes, size_t *size, + const uint8_t *_Nonnull *_Nonnull dataBytes, size_t *dataSize) { OSStatus result; uint32_t sizeRead; @@ -436,8 +440,8 @@ exit: return result; } -static inline OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size, - const uint8_t **mpiBytes, size_t *mpiSize) +static inline OSStatus SizeAndSkipMPI(const uint8_t *_Nonnull *_Nonnull bytes, size_t *size, + const uint8_t *_Nonnull *_Nonnull mpiBytes, size_t *mpiSize) { // MPIs looke like data for skipping. return SizeAndSkipDATA(bytes, size, mpiBytes, mpiSize); @@ -550,6 +554,8 @@ static inline void AppendHeader(CFMutableDataRef appendTo, OTRMessageType type) AppendMessageType(appendTo, type); } +CF_ASSUME_NONNULL_END + __END_DECLS #endif diff --git a/OSX/sec/Security/SecOTRPublicIdentity.c b/OSX/sec/Security/SecOTRPublicIdentity.c index b0f666db..37cc0faa 100644 --- a/OSX/sec/Security/SecOTRPublicIdentity.c +++ b/OSX/sec/Security/SecOTRPublicIdentity.c @@ -186,6 +186,7 @@ SecOTRPublicIdentityRef SecOTRPublicIdentityCreateFromBytes(CFAllocatorRef alloc const uint8_t* fullSequenceEnd = *bytes + *size; const uint8_t* keyData = ccder_decode_sequence_tl(&fullSequenceEnd, *bytes, fullSequenceEnd); + require(keyData != NULL, fail); size_t fullSize = (size_t)(fullSequenceEnd - *bytes); size_t keyDataSize; diff --git a/OSX/sec/Security/SecOTRSession.c b/OSX/sec/Security/SecOTRSession.c index 7e4ec347..de5ad666 100644 --- a/OSX/sec/Security/SecOTRSession.c +++ b/OSX/sec/Security/SecOTRSession.c @@ -1359,12 +1359,6 @@ abort: } -OSStatus SecOTRSEndSession(SecOTRSessionRef session, - CFMutableDataRef messageToSend) -{ - return errSecUnimplemented; -} - static CFDataRef data_to_data_error_request(enum SecXPCOperation op, CFDataRef publicPeerId, CFErrorRef *error) { __block CFDataRef result = NULL; securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { diff --git a/OSX/sec/Security/SecOTRSession.h b/OSX/sec/Security/SecOTRSession.h index 652a8000..05ac05d7 100644 --- a/OSX/sec/Security/SecOTRSession.h +++ b/OSX/sec/Security/SecOTRSession.h @@ -80,10 +80,6 @@ OSStatus SecOTRSProcessPacket(SecOTRSessionRef session, CFDataRef incomingPacket, CFMutableDataRef negotiationResponse); -OSStatus SecOTRSEndSession(SecOTRSessionRef session, - CFMutableDataRef messageToSend); - - bool SecOTRSIsForKeys(SecOTRSessionRef session, SecKeyRef myPublic, SecKeyRef theirPublic); bool SecOTRSGetIsReadyForMessages(SecOTRSessionRef session); bool SecOTRSGetIsIdle(SecOTRSessionRef session); diff --git a/OSX/sec/Security/SecPolicy.c b/OSX/sec/Security/SecPolicy.c index 09c09273..bad54204 100644 --- a/OSX/sec/Security/SecPolicy.c +++ b/OSX/sec/Security/SecPolicy.c @@ -44,12 +44,13 @@ #include #include #include -#ifdef DARLING -#include -#endif +#include +#include #include +#include + #undef POLICYCHECKMACRO #define POLICYCHECKMACRO(NAME, TRUSTRESULT, SUBTYPE, LEAFCHECK, PATHCHECK, LEAFONLY, CSSMERR, OSSTATUS) \ const CFStringRef kSecPolicyCheck##NAME = CFSTR(#NAME); @@ -78,7 +79,6 @@ const CFStringRef kSecPolicyApple##NAME = CFSTR("1.2.840.113635.100.1."#OID); #include "SecPolicy.list" //Some naming exceptions SEC_CONST_DECL(kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19") -SEC_CONST_DECL(kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113635.100.1.30"); SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid"); SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); @@ -135,48 +135,10 @@ SEC_CONST_DECL (kSecPolicyNameAppleParsecService, "Parsec"); SEC_CONST_DECL (kSecPolicyNameAppleAMPService, "AMP"); SEC_CONST_DECL (kSecPolicyNameAppleSiriService, "Siri"); SEC_CONST_DECL (kSecPolicyNameAppleHomeAppClipUploadService, "HomeAppClipUploadService"); +SEC_CONST_DECL (kSecPolicyNameAppleUpdatesService, "Updates"); +SEC_CONST_DECL (kSecPolicyNameApplePushCertPortal, "PushCertPortal"); -#define kSecPolicySHA1Size 20 -#define kSecPolicySHA256Size 32 -__unused const UInt8 kAppleCASHA1[kSecPolicySHA1Size] = { - 0x61, 0x1E, 0x5B, 0x66, 0x2C, 0x59, 0x3A, 0x08, 0xFF, 0x58, - 0xD1, 0x4A, 0xE2, 0x24, 0x52, 0xD1, 0x98, 0xDF, 0x6C, 0x60 -}; - -__unused static const UInt8 kAppleTESTCASHA1[kSecPolicySHA1Size] = { - 0xbc, 0x30, 0x55, 0xc8, 0xc8, 0xd3, 0x48, 0x3f, 0xf4, 0x8d, - 0xfe, 0x3d, 0x51, 0x75, 0x31, 0xc9, 0xf4, 0xd7, 0x4a, 0xf7 -}; - -static const UInt8 kITMSCASHA1[kSecPolicySHA1Size] = { - 0x1D, 0x33, 0x42, 0x46, 0x8B, 0x10, 0xBD, 0xE6, 0x45, 0xCE, - 0x44, 0x6E, 0xBB, 0xE8, 0xF5, 0x03, 0x5D, 0xF8, 0x32, 0x22 -}; - -static const UInt8 kFactoryDeviceCASHA1[kSecPolicySHA1Size] = { - 0xef, 0x68, 0x73, 0x17, 0xa4, 0xf8, 0xf9, 0x4b, 0x7b, 0x21, - 0xe2, 0x2f, 0x09, 0x8f, 0xfd, 0x6a, 0xae, 0xc0, 0x0d, 0x63 -}; - -static const UInt8 kApplePKISettingsAuthority[kSecPolicySHA1Size] = { - 0x1D, 0x0C, 0xBA, 0xAD, 0x17, 0xFD, 0x7E, 0x9E, 0x9F, 0xF1, - 0xC9, 0xA2, 0x66, 0x79, 0x60, 0x00, 0x8B, 0xAE, 0x70, 0xB8 -}; - -static const UInt8 kAppleTestPKISettingsAuthority[kSecPolicySHA1Size] = { - 0xDB, 0xBA, 0x25, 0x0B, 0xD8, 0x62, 0x71, 0x87, 0x54, 0x7E, - 0xD7, 0xEF, 0x11, 0x94, 0x7E, 0x82, 0xE6, 0xD8, 0x1C, 0x9A -}; - -static const UInt8 kTestAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = { - 0x62, 0x0A, 0xED, 0x83, 0xD2, 0x97, 0x4A, 0x77, 0x56, 0x33, - 0x83, 0xBE, 0xDB, 0xF9, 0xA1, 0xBD, 0x5F, 0xFE, 0x55, 0x7B -}; - -__unused static const UInt8 kAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = { - 0xB5, 0x2C, 0xB0, 0x2F, 0xD5, 0x67, 0xE0, 0x35, 0x9F, 0xE8, - 0xFA, 0x4D, 0x4C, 0x41, 0x03, 0x79, 0x70, 0xFE, 0x01, 0xB0 -}; +#define kSecPolicySHA256Size CC_SHA256_DIGEST_LENGTH // MARK: - // MARK: SecPolicy @@ -255,7 +217,7 @@ errOut: return result; } -#ifdef TARGET_OS_OSX +#if TARGET_OS_OSX static void set_ku_from_properties(SecPolicyRef policy, CFDictionaryRef properties); #endif @@ -391,11 +353,18 @@ SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, policy = SecPolicyCreateAppleBasicAttestationUser(rootDigest); } else if (CFEqual(policyIdentifier, kSecPolicyAppleComponentCertificate)) { policy = SecPolicyCreateAppleComponentCertificate(rootDigest); + } else if (CFEqual(policyIdentifier, kSecPolicyAppleAggregateMetricTransparency)) { + policy = SecPolicyCreateAggregateMetricTransparency(!client); + } else if (CFEqual(policyIdentifier, kSecPolicyAppleAggregateMetricEncryption)) { + policy = SecPolicyCreateAggregateMetricEncryption(!client); + } else if (CFEqual(policyIdentifier, kSecPolicyApplePayModelSigning)) { + policy = SecPolicyCreateApplePayModelSigning(true); } /* For a couple of common patterns we use the macro, but some of the - * policies are deprecated, so we need to ignore the warning. */ + * policies are deprecated (or not yet available), so we need to ignore the warning. */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wunguarded-availability" #define _P_OPTION_ #define _P_OPTION_N name #define _P_PROPERTIES_(NAME, IN_NAME, FUNCTION) @@ -415,7 +384,7 @@ _P_PROPERTIES_##IN_PROPERTIES(NAME, IN_NAME, FUNCTION) return NULL; } -#ifdef TARGET_OS_OSX +#if TARGET_OS_OSX set_ku_from_properties(policy, properties); #endif @@ -618,7 +587,7 @@ OSStatus SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properti } } -#ifdef TARGET_OS_OSX +#if TARGET_OS_OSX set_ku_from_properties(policyRef, properties); #endif CFRelease(oid); @@ -974,7 +943,17 @@ static void add_ku(CFMutableDictionaryRef options, SecKeyUsage keyUsage) { } } -#ifdef TARGET_OS_OSX +static void add_ku_report(CFMutableDictionaryRef options, SecKeyUsage keyUsage) { + SInt32 dku = keyUsage; + CFNumberRef ku = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, + &dku); + if (ku) { + add_element(options, kSecPolicyCheckKeyUsageReportOnly, ku); + CFRelease(ku); + } +} + +#if TARGET_OS_OSX static void set_ku_from_properties(SecPolicyRef policy, CFDictionaryRef properties) { if (!policy || !properties) { return; @@ -1227,29 +1206,13 @@ errOut: return result; } -static bool SecPolicyAddAnchorSHA1Options(CFMutableDictionaryRef options, - const UInt8 anchorSha1[kSecPolicySHA1Size]) -{ - bool success = false; - CFDataRef anchorData = NULL; - - require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha1, kSecPolicySHA1Size), errOut); - add_element(options, kSecPolicyCheckAnchorSHA1, anchorData); - - success = true; - -errOut: - CFReleaseSafe(anchorData); - return success; -} - static bool SecPolicyAddAnchorSHA256Options(CFMutableDictionaryRef options, - const UInt8 anchorSha1[kSecPolicySHA256Size]) + const UInt8 anchorSha256[kSecPolicySHA256Size]) { bool success = false; CFDataRef anchorData = NULL; - require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha1, kSecPolicySHA256Size), errOut); + require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha256, kSecPolicySHA256Size), errOut); add_element(options, kSecPolicyCheckAnchorSHA256, anchorData); success = true; @@ -1325,18 +1288,251 @@ static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef options, CFStr return true; } +CFDataRef CreateCFDataFromBase64CFString(CFStringRef base64string) +{ + __block CFDataRef cfData = NULL; + + require_quiet(base64string, errOut); + + CFStringPerformWithCStringAndLength(base64string, ^(const char *base64string_buf, size_t base64string_buf_length) { + void *data = NULL; + + require_quiet(base64string_buf != NULL, errOut); + require_quiet(base64string_buf_length != 0, errOut); + + size_t expected_data_length = SecBase64Decode(base64string_buf, base64string_buf_length, NULL, 0); + require_quiet(expected_data_length != 0, errOut); + + data = malloc(expected_data_length); + require(data != NULL, errOut); + + size_t actual_data_length = SecBase64Decode(base64string_buf, base64string_buf_length, data, expected_data_length); + require_quiet(actual_data_length != 0, errOut); + + cfData = CFDataCreate(kCFAllocatorDefault, (const uint8_t *)data, actual_data_length); + + errOut: + free(data); + return; + }); + +errOut: + return cfData; +} + +static CFStringRef CopyParentDomainNameFromHostName(CFStringRef hostName) +{ + CFStringRef parentDomainName = NULL; + + require_quiet(hostName, errOut); + + CFIndex hostNameLength = CFStringGetLength(hostName); + require_quiet(hostNameLength != 0, errOut); + + CFRange nextLabel = CFStringFind(hostName, CFSTR("."), 0); + require_quiet(nextLabel.location != kCFNotFound && nextLabel.location < (hostNameLength - 1), errOut); + + CFRange parentDomainNameRange = CFRangeMake(nextLabel.location + 1, hostNameLength - nextLabel.location - 1); + parentDomainName = CFStringCreateWithSubstring(NULL, hostName, parentDomainNameRange); + +errOut: + return parentDomainName; +} + +CFArrayRef parseNSPinnedDomains(CFDictionaryRef nsPinnedDomainsDict, CFStringRef hostName, CFStringRef nsPinnedIdentityType) +{ + CFMutableArrayRef targetSPKISHA256 = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + + __block bool hostNamePinned = false; + + // Strip the trailing dot if any. + CFIndex hostNameLength = CFStringGetLength(hostName); + if (hostNameLength > 0 && '.' == CFStringGetCharacterAtIndex(hostName, hostNameLength - 1)) { + hostName = CFStringCreateWithSubstring(NULL, hostName, CFRangeMake(0, hostNameLength - 1)); + require_quiet(hostName, errOut); + } else { + CFRetainSafe(hostName); + } + + CFDictionaryForEach(nsPinnedDomainsDict, ^(const void *key, const void *value) { + CFStringRef parentDomainName = NULL; + + require_quiet(isString(key), errOutNSPinnedDomainsDict); + require_quiet(isDictionary(value), errOutNSPinnedDomainsDict); + + // Match one of the pinned domains to the current endpoint's hostname. + CFStringRef domainName = (CFStringRef)key; + bool hostNameMatched = (CFStringCompare(domainName, hostName, kCFCompareCaseInsensitive) == kCFCompareEqualTo); + + // Match one of the pinned domains to the current endpoint's parent domain if allowed. + if (hostNameMatched == false) { + CFTypeRef nsIncludesSubdomains = CFDictionaryGetValue(value, CFSTR("NSIncludesSubdomains")); + require_quiet(nsIncludesSubdomains == kCFBooleanTrue, errOutNSPinnedDomainsDict); + + parentDomainName = CopyParentDomainNameFromHostName(hostName); + require_quiet(parentDomainName != NULL, errOutNSPinnedDomainsDict); + + hostNameMatched = (CFStringCompare(domainName, parentDomainName, kCFCompareCaseInsensitive) == kCFCompareEqualTo); + } + require_quiet(hostNameMatched, errOutNSPinnedDomainsDict); + + CFTypeRef nsPinnedIdentities = CFDictionaryGetValue(value, nsPinnedIdentityType); + require_quiet(nsPinnedIdentities, errOutNSPinnedDomainsDict); + hostNamePinned = true; + + require_quiet(isArray(nsPinnedIdentities), errOutNSPinnedDomainsDict); + CFArrayForEach(nsPinnedIdentities, ^(const void *v) { + CFDataRef spkiSHA256 = NULL; + + require_quiet(isDictionary(v), errOutNSPinnedIdentities); + + CFTypeRef spkiSHA256base64 = CFDictionaryGetValue(v, CFSTR("SPKI-SHA256-BASE64")); + require_quiet(isString(spkiSHA256base64), errOutNSPinnedIdentities); + + spkiSHA256 = CreateCFDataFromBase64CFString(spkiSHA256base64); + require_quiet(spkiSHA256, errOutNSPinnedIdentities); + + CFArrayAppendValue(targetSPKISHA256, spkiSHA256); + + errOutNSPinnedIdentities: + CFReleaseSafe(spkiSHA256); + }); + + errOutNSPinnedDomainsDict: + CFReleaseSafe(parentDomainName); + return; + }); + +errOut: + CFReleaseSafe(hostName); + if (hostNamePinned == false) { + CFReleaseNull(targetSPKISHA256); + } + return targetSPKISHA256; +} + +static CFArrayRef getNSPinnedIdentitiesForHostName(CFStringRef hostName, CFStringRef nsPinnedIdentityType) +{ + CFMutableArrayRef targetSPKISHA256 = NULL; + + static CFDictionaryRef nsPinnedDomainsDict = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + CFBundleRef bundle = CFBundleGetMainBundle(); + require(bundle, initializationIncomplete); + + CFTypeRef nsAppTransportSecurityDict = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("NSAppTransportSecurity")); + require_quiet(isDictionary(nsAppTransportSecurityDict), initializationIncomplete); + + nsPinnedDomainsDict = CFDictionaryGetValue(nsAppTransportSecurityDict, CFSTR("NSPinnedDomains")); + require(isDictionary(nsPinnedDomainsDict), initializationIncomplete); + return; + + initializationIncomplete: + nsPinnedDomainsDict = NULL; + }); + // To proceed, this or a previous call must have found NSPinnedDomains in the info dictionary. + require_quiet(nsPinnedDomainsDict, errOut); + + targetSPKISHA256 = (CFMutableArrayRef)parseNSPinnedDomains(nsPinnedDomainsDict, hostName, nsPinnedIdentityType); + + // Return NULL if the hostname (or its parent domain name) is not among the pinned domains. + // Otherwise return an array of zero or more SPKI SHA256 identities. +errOut: + return targetSPKISHA256; +} + +static void SecPolicyAddATSpinningIfInfoSpecified(CFMutableDictionaryRef options) +{ + CFStringRef hostname = CFDictionaryGetValue(options, kSecPolicyCheckSSLHostname); + require_quiet(isString(hostname), errOut); + + CFArrayRef leafSPKISHA256 = getNSPinnedIdentitiesForHostName(hostname, CFSTR("NSPinnedLeafIdentities")); + if (leafSPKISHA256) { + add_element(options, kSecPolicyCheckLeafSPKISHA256, leafSPKISHA256); + } + + CFArrayRef caSPKISHA256 = getNSPinnedIdentitiesForHostName(hostname, CFSTR("NSPinnedCAIdentities")); + if (caSPKISHA256) { + add_element(options, kSecPolicyCheckCAspkiSHA256, caSPKISHA256); + } + +errOut: + return; +} + +void SecPolicyReconcilePinningRequiredIfInfoSpecified(CFMutableDictionaryRef options) +{ + bool hasPinningRequiredKey = false; + CFArrayRef leafSPKISHA256 = NULL; + CFArrayRef caSPKISHA256 = NULL; + + hasPinningRequiredKey = CFDictionaryContainsKey(options, kSecPolicyCheckPinningRequired); + require_quiet(hasPinningRequiredKey, errOut); + + // A non-NULL, empty, leafSPKISHA256 array allows all leaves and thus excludes this hostname from pinning. + leafSPKISHA256 = CFDictionaryGetValue(options, kSecPolicyCheckLeafSPKISHA256); + caSPKISHA256 = CFDictionaryGetValue(options, kSecPolicyCheckCAspkiSHA256); + if (isArray(leafSPKISHA256) && CFArrayGetCount(leafSPKISHA256) == 0 && + isArray(caSPKISHA256) && CFArrayGetCount(caSPKISHA256) == 0) { + CFDictionaryRemoveValue(options, kSecPolicyCheckPinningRequired); + } + + // kSecPolicyCheckPinningRequired and (kSecPolicyCheckLeafSPKISHA256, kSecPolicyCheckCAspkiSHA256) are mutually exclusive. + CFDictionaryRemoveValue(options, kSecPolicyCheckLeafSPKISHA256); + CFDictionaryRemoveValue(options, kSecPolicyCheckCAspkiSHA256); + +errOut: + return; +} + static bool SecPolicyAddPinningRequiredIfInfoSpecified(CFMutableDictionaryRef options) { - CFBundleRef bundle = CFBundleGetMainBundle(); - if (bundle) { - CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("SecTrustPinningRequired")); - if (isBoolean(value) && CFBooleanGetValue(value)) { - add_element(options, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + static bool result = false; + static bool hasPinningRequiredKey = false; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + CFBundleRef bundle = CFBundleGetMainBundle(); + if (bundle) { + CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("SecTrustPinningRequired")); + if (isBoolean(value) && CFBooleanGetValue(value)) { + hasPinningRequiredKey = true; + } + result = true; } - } else { - return false; + }); + if (result && hasPinningRequiredKey) { + add_element(options, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + } + return result; +} + +void SecPolicySetSHA256Pins(SecPolicyRef policy, CFArrayRef _Nullable leafSPKISHA256, CFArrayRef _Nullable caSPKISHA256) +{ + if (!policy) { + return; + } + CFMutableDictionaryRef options = (CFMutableDictionaryRef) policy->_options; + if (!options) { + options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!options) return; + policy->_options = options; + } + + if (leafSPKISHA256) { + CFDictionaryRemoveValue(options, kSecPolicyCheckLeafSPKISHA256); + add_element(options, kSecPolicyCheckLeafSPKISHA256, leafSPKISHA256); + } else { + CFDictionaryRemoveValue(options, kSecPolicyCheckLeafSPKISHA256); + } + + if (caSPKISHA256) { + CFDictionaryRemoveValue(options, kSecPolicyCheckCAspkiSHA256); + add_element(options, kSecPolicyCheckCAspkiSHA256, caSPKISHA256); + } else { + CFDictionaryRemoveValue(options, kSecPolicyCheckCAspkiSHA256); } - return true; } // @@ -1360,7 +1556,7 @@ errOut: return (SecPolicyRef _Nonnull)result; } -SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) { +SecPolicyRef SecPolicyCreateSSLWithKeyUsage(Boolean server, CFStringRef hostname, uint32_t keyUsage) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; @@ -1380,6 +1576,8 @@ SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) { require_quiet(SecPolicyRemoveWeakHashOptions(options), errOut); require_quiet(SecPolicyAddStrongKeySizeOptions(options), errOut); require_quiet(SecPolicyAddPinningRequiredIfInfoSpecified(options), errOut); + SecPolicyAddATSpinningIfInfoSpecified(options); + SecPolicyReconcilePinningRequiredIfInfoSpecified(options); CFDictionaryAddValue(options, kSecPolicyCheckValidityPeriodMaximums, kCFBooleanTrue); CFDictionaryAddValue(options, kSecPolicyCheckServerAuthEKU, kCFBooleanTrue); // enforces stricter EKU rules than set_ssl_ekus below for certain anchor types #if !TARGET_OS_BRIDGE @@ -1387,6 +1585,10 @@ SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) { #endif } + if (keyUsage) { + add_ku_report(options, keyUsage); + } + set_ssl_ekus(options, server); require(result = SecPolicyCreate(kSecPolicyAppleSSL, @@ -1398,6 +1600,10 @@ errOut: return (SecPolicyRef _Nonnull)result; } +SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) { + return SecPolicyCreateSSLWithKeyUsage(server, hostname, kSecKeyUsageUnspecified); +} + SecPolicyRef SecPolicyCreateLegacySSL(Boolean server, CFStringRef hostname) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; @@ -1417,6 +1623,8 @@ SecPolicyRef SecPolicyCreateLegacySSL(Boolean server, CFStringRef hostname) { if (server) { // fewer requirements than the standard SSL policy require_quiet(SecPolicyAddPinningRequiredIfInfoSpecified(options), errOut); + SecPolicyAddATSpinningIfInfoSpecified(options); + SecPolicyReconcilePinningRequiredIfInfoSpecified(options); CFDictionaryAddValue(options, kSecPolicyCheckValidityPeriodMaximums, kCFBooleanTrue); #if !TARGET_OS_BRIDGE CFDictionaryAddValue(options, kSecPolicyCheckSystemTrustedCTRequired, kCFBooleanTrue); @@ -1513,7 +1721,7 @@ fail: SecPolicyRef SecPolicyCreateAppleSSLPinned(CFStringRef policyName, CFStringRef hostname, CFStringRef intermediateMarkerOID, CFStringRef leafMarkerOID) { - CFMutableDictionaryRef options = NULL, appleAnchorOptions = NULL; + CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; if (!policyName || !hostname || !leafMarkerOID) { @@ -1578,7 +1786,6 @@ SecPolicyRef SecPolicyCreateAppleSSLPinned(CFStringRef policyName, CFStringRef h errOut: CFReleaseSafe(options); - CFReleaseSafe(appleAnchorOptions); return result; } @@ -1653,6 +1860,13 @@ errOut: return result; } +/* subject:/C=US/O=Apple Inc./OU=Apple iPhone/CN=[TEST] Apple iPhone Device CA */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=[TEST] Apple iPhone Certification Authority */ +const uint8_t kFactoryDeviceCASHA256[CC_SHA256_DIGEST_LENGTH] = { + 0x7b, 0x8e, 0xc8, 0x78, 0xff, 0x3a, 0xcf, 0x61, 0xdd, 0xe6, 0x53, 0x77, 0x2b, 0xe7, 0x32, 0xc5, + 0x97, 0xf4, 0x6b, 0x9c, 0xa6, 0x00, 0xc5, 0x2c, 0xc1, 0x25, 0x85, 0x02, 0x03, 0x06, 0x97, 0x96 +}; + SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; @@ -1662,16 +1876,9 @@ SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void) { SecPolicyAddBasicCertOptions(options); -#if 0 - CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage, - kCFBooleanTrue); - CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage, - kCFBooleanTrue); -#endif - /* Basic X.509 policy with the additional requirements that the chain is anchored at the factory device certificate issuer. */ - require(SecPolicyAddAnchorSHA1Options(options, kFactoryDeviceCASHA1), errOut); + require(SecPolicyAddAnchorSHA256Options(options, kFactoryDeviceCASHA256), errOut); require(result = SecPolicyCreate(kSecPolicyAppleFactoryDeviceCertificate, kSecPolicyNameFactoryDeviceCertificate, options), @@ -1710,6 +1917,13 @@ errOut: return result; } +/* subject:/O=Apple Inc./OU=iTunes Store/CN=iTunes Store Root/C=US/ST=California/L=Cupertino */ +/* issuer :/O=Apple Inc./OU=iTunes Store/CN=iTunes Store Root/C=US/ST=California/L=Cupertino */ +const uint8_t kITMS_CA_SHA256[CC_SHA256_DIGEST_LENGTH] = { + 0xa1, 0xdc, 0x36, 0x23, 0x84, 0xb4, 0xba, 0x0f, 0xaf, 0xea, 0x2a, 0xd4, 0xac, 0xc4, 0x86, 0x8f, + 0xfb, 0xae, 0x57, 0x21, 0x4d, 0x20, 0x88, 0xc8, 0x82, 0xe7, 0x65, 0x13, 0x47, 0xab, 0x81, 0xd7 +}; + SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; @@ -1726,7 +1940,7 @@ SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void) { CFSTR("iTunes Store URL Bag")); require(SecPolicyAddChainLengthOptions(options, 2), errOut); - require(SecPolicyAddAnchorSHA1Options(options, kITMSCASHA1), errOut); + require(SecPolicyAddAnchorSHA256Options(options, kITMS_CA_SHA256), errOut); require(result = SecPolicyCreate(kSecPolicyAppleiTunesStoreURLBag, kSecPolicyNameiTunesStoreURLBag, options), errOut); @@ -2093,6 +2307,10 @@ SecPolicyRef SecPolicyCreateOCSPSigner(void) { /* Require id-kp-OCSPSigning extendedKeyUsage to be present, not optional. */ add_eku(options, &oidExtendedKeyUsageOCSPSigning); + /* Check for digitalSignature KU and CA:FALSE. See */ + add_ku(options, kSecKeyUsageDigitalSignature); + CFDictionarySetValue(options, kSecPolicyCheckNotCA, kCFBooleanTrue); + require(result = SecPolicyCreate(kSecPolicyAppleOCSPSigner, kSecPolicyNameOCSPSigner, options), errOut); @@ -2175,7 +2393,6 @@ SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email) { if (smimeUsage & kSecSignSMIMEUsage) { add_ku(options, kSecKeyUsageUnspecified); add_ku(options, kSecKeyUsageDigitalSignature); - add_ku(options, kSecKeyUsageNonRepudiation); } if (smimeUsage & kSecKeyEncryptSMIMEUsage) { add_ku(options, kSecKeyUsageKeyEncipherment); @@ -2183,31 +2400,18 @@ SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email) { if (smimeUsage & kSecDataEncryptSMIMEUsage) { add_ku(options, kSecKeyUsageDataEncipherment); } - if (smimeUsage & kSecKeyExchangeDecryptSMIMEUsage) { - add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageDecipherOnly); - } - if (smimeUsage & kSecKeyExchangeEncryptSMIMEUsage) { - add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly); - } - if (smimeUsage & kSecKeyExchangeBothSMIMEUsage) { - add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly | kSecKeyUsageDecipherOnly); + if (smimeUsage & kSecKeyExchangeDecryptSMIMEUsage || + smimeUsage & kSecKeyExchangeEncryptSMIMEUsage || + smimeUsage & kSecKeyExchangeBothSMIMEUsage) { + /* */ + add_ku(options, kSecKeyUsageKeyAgreement); } if (email) { CFDictionaryAddValue(options, kSecPolicyCheckEmail, email); } - /* RFC 3850 paragraph 4.4.4 - - If the extended key usage extension is present in the certificate - then interpersonal message S/MIME receiving agents MUST check that it - contains either the emailProtection or the anyExtendedKeyUsage OID as - defined in [KEYM]. S/MIME uses other than interpersonal messaging - MAY require the explicit presence of the extended key usage extension - or other OIDs to be present in the extension or both. - */ add_eku(options, NULL); /* eku extension is optional */ - add_eku(options, &oidAnyExtendedKeyUsage); add_eku(options, &oidExtendedKeyUsageEmailProtection); #if !TARGET_OS_IPHONE @@ -2657,7 +2861,8 @@ errOut: return result; } -static SecPolicyRef CreateConfigurationProfileSigner(bool forTest) { +SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void) +{ SecPolicyRef result = NULL; CFMutableDictionaryRef options = NULL; require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, @@ -2671,14 +2876,20 @@ static SecPolicyRef CreateConfigurationProfileSigner(bool forTest) { require(SecPolicyAddChainLengthOptions(options, 3), errOut); // Require the profile signing EKU - const DERItem* pOID = (forTest) ? &oidAppleExtendedKeyUsageQAProfileSigning :&oidAppleExtendedKeyUsageProfileSigning; - add_eku(options, pOID); + add_eku(options, &oidAppleExtendedKeyUsageProfileSigning); + + CFStringRef releaseType = MGCopyAnswer(kMGQReleaseType, NULL); + if (releaseType != NULL) { + // all non-GM variants (beta, carrier, internal, etc) allow the QA signer as well + add_eku(options, &oidAppleExtendedKeyUsageQAProfileSigning); + } + CFReleaseNull(releaseType); // Require the Apple Application Integration CA marker OID add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.3")); - require(result = SecPolicyCreate((forTest) ? kSecPolicyAppleQAProfileSigner: kSecPolicyAppleProfileSigner, - (forTest) ? kSecPolicyNameQAProfileSigner : kSecPolicyNameProfileSigner, + require(result = SecPolicyCreate(kSecPolicyAppleProfileSigner, + kSecPolicyNameProfileSigner, options), errOut); errOut: @@ -2686,19 +2897,9 @@ errOut: return result; } -SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void) -{ - return CreateConfigurationProfileSigner(false); -} - - SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void) { - if (SecIsInternalRelease()) { - return CreateConfigurationProfileSigner(true); - } else { - return CreateConfigurationProfileSigner(false); - } + return SecPolicyCreateConfigurationProfileSigner(); } SecPolicyRef SecPolicyCreateOSXProvisioningProfileSigning(void) @@ -2732,54 +2933,6 @@ errOut: return result; } - -SecPolicyRef SecPolicyCreateOTAPKISigner(void) -{ - SecPolicyRef result = NULL; - CFMutableDictionaryRef options = NULL; - require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks), errOut); - SecPolicyAddBasicX509Options(options); - - SecPolicyAddAnchorSHA1Options(options, kApplePKISettingsAuthority); - require(SecPolicyAddChainLengthOptions(options, 2), errOut); - - require(result = SecPolicyCreate(kSecPolicyAppleOTAPKISigner, - kSecPolicyNameOTAPKISigner, options), errOut); - -errOut: - CFReleaseSafe(options); - return result; - -} - - -SecPolicyRef SecPolicyCreateTestOTAPKISigner(void) -{ - /* Guard against use on production devices */ - if (!SecIsInternalRelease()) { - return SecPolicyCreateOTAPKISigner(); - } - - SecPolicyRef result = NULL; - CFMutableDictionaryRef options = NULL; - require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks), errOut); - SecPolicyAddBasicX509Options(options); - - SecPolicyAddAnchorSHA1Options(options, kAppleTestPKISettingsAuthority); - require(SecPolicyAddChainLengthOptions(options, 2), errOut); - - require(result = SecPolicyCreate(kSecPolicyAppleTestOTAPKISigner, - kSecPolicyNameTestOTAPKISigner, options), errOut); - -errOut: - CFReleaseSafe(options); - return result; -} - /*! @function SecPolicyCreateAppleSMPEncryption @abstract Check for intermediate certificate 'Apple System Integration CA - G3' by name, @@ -2823,6 +2976,13 @@ errOut: return result; } +/* subject:/CN=Test Apple Root CA - ECC/OU=Certification Authority/O=Apple Inc./C=US */ +/* issuer :/CN=Test Apple Root CA - ECC/OU=Certification Authority/O=Apple Inc./C=US */ +const uint8_t kTestAppleRootCA_ECC_SHA256[CC_SHA256_DIGEST_LENGTH] = { + 0xe8, 0x6a, 0xd6, 0x5c, 0x74, 0x60, 0x21, 0x14, 0x47, 0xc6, 0x6a, 0xd7, 0x5f, 0xf8, 0x06, 0x7b, + 0xec, 0xb5, 0x52, 0x7e, 0x4e, 0xa1, 0xac, 0x48, 0xcf, 0x3c, 0x53, 0x8f, 0x4d, 0x2b, 0x20, 0xa9 +}; + /*! @function SecPolicyCreateTestAppleSMPEncryption @abstract Check for intermediate certificate 'Test Apple System Integration CA - ECC' by name, @@ -2838,7 +2998,7 @@ SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void) &kCFTypeDictionaryValueCallBacks), errOut); SecPolicyAddBasicCertOptions(options); - SecPolicyAddAnchorSHA1Options(options, kTestAppleRootCA_ECC_SHA1); + SecPolicyAddAnchorSHA256Options(options, kTestAppleRootCA_ECC_SHA256); require(SecPolicyAddChainLengthOptions(options, 3), errOut); CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, @@ -2916,7 +3076,6 @@ SecPolicyCreateAppleServerAuthCommon(CFStringRef hostname, const DERItem *leafMarkerOID, const DERItem *UATLeafMarkerOID) { - CFMutableDictionaryRef appleAnchorOptions = NULL; CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; CFDataRef oid = NULL, uatoid = NULL; @@ -2979,7 +3138,6 @@ SecPolicyCreateAppleServerAuthCommon(CFStringRef hostname, require(result, errOut); errOut: - CFReleaseSafe(appleAnchorOptions); CFReleaseSafe(options); CFReleaseSafe(oid); CFReleaseSafe(uatoid); @@ -2992,12 +3150,10 @@ errOut: */ SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname) { - SecPolicyRef result = SecPolicyCreateSSL(true, hostname); - - SecPolicySetOid(result, kSecPolicyAppleIDSService); - SecPolicySetName(result, kSecPolicyNameAppleIDSBag); - - return result; + return SecPolicyCreateAppleServerAuthCommon(hostname, NULL, kSecPolicyAppleIDSService, + kSecPolicyNameAppleIDSBag, + &oidAppleCertExtAppleServerAuthenticationIDSProd, + &oidAppleCertExtAppleServerAuthenticationIDSProdQA); } /*! @@ -3476,7 +3632,6 @@ errOut: } SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) { - CFMutableDictionaryRef appleAnchorOptions = NULL; CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; CFDataRef oid = NULL; @@ -3514,7 +3669,6 @@ SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) { require(result, errOut); errOut: - CFReleaseSafe(appleAnchorOptions); CFReleaseSafe(options); CFReleaseSafe(oid); return result; @@ -3564,8 +3718,6 @@ errOut: /* This one is special because the intermediate has no marker OID */ SecPolicyRef SecPolicyCreateAppleSoftwareSigning(void) { CFMutableDictionaryRef options = NULL; - CFDictionaryRef keySizes = NULL; - CFNumberRef rsaSize = NULL, ecSize = NULL; SecPolicyRef result = NULL; require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, @@ -3601,9 +3753,6 @@ SecPolicyRef SecPolicyCreateAppleSoftwareSigning(void) { errOut: CFReleaseSafe(options); - CFReleaseSafe(keySizes); - CFReleaseSafe(rsaSize); - CFReleaseSafe(ecSize); return result; } @@ -3666,9 +3815,6 @@ errOut: SecPolicyRef SecPolicyCreateAppleWarsaw(void) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; -#if TARGET_OS_BRIDGE - CFMutableDictionaryRef appleAnchorOptions = NULL; -#endif require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, @@ -3783,9 +3929,6 @@ errOut: SecPolicyRef SecPolicyCreateMobileSoftwareUpdate(void) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; -#if TARGET_OS_BRIDGE - CFMutableDictionaryRef appleAnchorOptions = NULL; -#endif require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); @@ -4117,3 +4260,387 @@ errOut: CFReleaseNull(options); return result; } + +SecPolicyRef SecPolicyCreateAlisha(void) { + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + CFDictionaryRef keySizes = NULL; + CFNumberRef ecSize = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + /* Alisha certs don't expire */ + SecPolicyAddBasicCertOptions(options); + + /* RSA key sizes are disallowed. EC key sizes are P-256 or larger. */ + require(ecSize = CFNumberCreateWithCFIndex(NULL, 256), errOut); + require(keySizes = CFDictionaryCreate(NULL, (const void**)&kSecAttrKeyTypeEC, + (const void**)&ecSize, 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + add_element(options, kSecPolicyCheckKeySize, keySizes); + + /* Check for weak hashes */ + require(SecPolicyRemoveWeakHashOptions(options), errOut); + + require(result = SecPolicyCreate(kSecPolicyAppleAlisha, + kSecPolicyNameAlisha, options), errOut); +errOut: + CFReleaseNull(options); + CFReleaseNull(keySizes); + CFReleaseNull(ecSize); + return result; +} + +SecPolicyRef SecPolicyCreateMeasuredBootPolicySigning(void) { + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + /* No expiration check. */ + SecPolicyAddBasicCertOptions(options); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Corporate Signing subCA */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.24.17")); + + /* Measured Boot Policy Signing Leaf OID */ + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.6.26.6.1")); + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + require(result = SecPolicyCreate(kSecPolicyAppleMeasuredBootPolicySigning, + kSecPolicyNameMeasuredBootPolicySigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +/* subject:/CN=Apple External EC Root/O=Apple Inc./C=US */ +/* SKID: 3F:A4:C0:94:20:70:CB:3B:DD:A8:54:E6:14:1E:29:CC:4D:14:38:53 */ +/* Not Before: Jan 23 00:46:48 2020 GMT, Not After : Jan 18 00:00:00 2045 GMT */ +/* Signature Algorithm: ecdsa-with-SHA384 */ +const uint8_t AppleExternalECRoot_SHA256[kSecPolicySHA256Size] = { + 0x72, 0x56, 0x6e, 0x6f, 0x66, 0x30, 0x0c, 0xfd, 0x24, 0xe5, 0xe6, 0x85, 0xa2, 0xf1, 0x5a, 0x74, + 0x9d, 0xe0, 0x4b, 0xb0, 0x38, 0x50, 0x77, 0x91, 0x96, 0x63, 0x6e, 0x07, 0x23, 0x0f, 0x91, 0x1e +}; +/* subject:/CN=Test Apple External EC Root/O=Apple Inc./C=US */ +/* SKID: 07:6B:07:47:33:E4:96:B4:FC:6F:FA:32:2C:8E:BE:70:C2:8F:80:3C */ +/* Not Before: Nov 5 18:00:46 2019 GMT, Not After : Oct 29 18:00:46 2044 GMT */ +/* Signature Algorithm: ecdsa-with-SHA384 */ +const uint8_t TestAppleExternalECRoot_SHA256[kSecPolicySHA256Size] = { + 0xf3, 0x98, 0x39, 0xdc, 0x6a, 0x64, 0xf6, 0xe3, 0xa0, 0xdc, 0x97, 0xd7, 0x83, 0x61, 0x6b, 0x84, + 0x9f, 0xdf, 0xa1, 0x70, 0x54, 0x59, 0xae, 0x96, 0x0f, 0x41, 0xe1, 0x16, 0xa3, 0xb4, 0x8b, 0xb5 +}; +SecPolicyRef SecPolicyCreateApplePayQRCodeEncryption(void) { + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + /* Check expiration */ + SecPolicyAddBasicX509Options(options); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Apple External EC CA 1 - G1 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.22")); + + /* ApplePay QR Code Encryption */ + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.13.3")); + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + require(SecPolicyAddAnchorSHA256Options(options, AppleExternalECRoot_SHA256),errOut); + if (SecIsInternalRelease()) { + require(SecPolicyAddAnchorSHA256Options(options, TestAppleExternalECRoot_SHA256),errOut); + } + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + require(result = SecPolicyCreate(kSecPolicyApplePayQRCodeEncryption, + kSecPolicyNamePayQRCodeEncryption, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +SecPolicyRef SecPolicyCreateApplePayQRCodeSigning(void) { + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + /* Check expiration */ + SecPolicyAddBasicX509Options(options); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Apple External EC CA 1 - G1 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.22")); + + /* ApplePay QR Code Signing */ + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.12.12")); + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + require(SecPolicyAddAnchorSHA256Options(options, AppleExternalECRoot_SHA256),errOut); + if (SecIsInternalRelease()) { + require(SecPolicyAddAnchorSHA256Options(options, TestAppleExternalECRoot_SHA256),errOut); + } + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + require(result = SecPolicyCreate(kSecPolicyApplePayQRCodeSigning, + kSecPolicyNamePayQRCodeSigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +SecPolicyRef SecPolicyCreateAppleAccessoryUpdateSigning(void) { + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + /* No expiration check */ + SecPolicyAddBasicCertOptions(options); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Apple Anchor */ + require_quiet(SecPolicyAddAppleAnchorOptions(options, kSecPolicyNameAccessoryUpdateSigning), errOut); + + /* Apple External EC CA 1 - G1 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.17")); + + /* Accessory Manufacturer Firmware Signing Prod */ + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.12.9")); + if (isCFPreferenceInSecurityDomain(CFSTR("AllowAccessoryUpdateSigningBeta"))) { + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.12.10")); // ProdQA + } + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + require(result = SecPolicyCreate(kSecPolicyAppleAccessoryUpdateSigning, + kSecPolicyNameAccessoryUpdateSigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateEscrowServiceIdKeySigning(void) +{ + SecPolicyRef result = NULL; + CFMutableDictionaryRef options = NULL; + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + // X509, ignoring date validity + SecPolicyAddBasicCertOptions(options); + + add_ku(options, kSecKeyUsageDigitalSignature); + + CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName, + CFSTR("Escrow Service ID Key")); + + /* Exactly 2 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 2), errOut); + + require(result = SecPolicyCreate(kSecPolicyAppleEscrowServiceIdKeySigning, + kSecPolicyNameEscrowServiceIdKeySigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreatePCSEscrowServiceIdKeySigning(void) +{ + SecPolicyRef result = NULL; + CFMutableDictionaryRef options = NULL; + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + SecPolicyAddBasicX509Options(options); + add_ku(options, kSecKeyUsageDigitalSignature); + + CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonName, + CFSTR("Effaceable Service ID Key")); + + /* Exactly 2 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 2), errOut); + + require(result = SecPolicyCreate(kSecPolicyApplePCSEscrowServiceIdKeySigning, + kSecPolicyNamePCSEscrowServiceIdKeySigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +SecPolicyRef SecPolicyCreateAggregateMetricTransparency(bool facilitator) +{ + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + SecPolicyAddBasicX509Options(options); + + /* Anchored to the Apple Roots */ + require(SecPolicyAddAppleAnchorOptions(options, kSecPolicyNameAggregateMetricTransparency), errOut); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Intermediate marker OID matches AAICA 6 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.26")); + + /* Leaf marker OID matches expected OID for either Facilitator or Partner */ + if (facilitator) { + add_element(options, kSecPolicyCheckLeafMarkerOidWithoutValueCheck, CFSTR("1.2.840.113635.100.12.17")); + } else { + add_element(options, kSecPolicyCheckLeafMarkerOidWithoutValueCheck, CFSTR("1.2.840.113635.100.12.18")); + } + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + /* Require CT */ + if (!SecIsInternalRelease() || !isCFPreferenceInSecurityDomain(CFSTR("disableAggregateMetricsCTCheck"))) { + add_element(options, kSecPolicyCheckCTRequired, kCFBooleanTrue); + } + + /* Check for weak hashes */ + // require(SecPolicyRemoveWeakHashOptions(options), errOut); // the current WWDR CA cert is signed with SHA1 + require(result = SecPolicyCreate(kSecPolicyAppleAggregateMetricTransparency, + kSecPolicyNameAggregateMetricTransparency, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +SecPolicyRef SecPolicyCreateAggregateMetricEncryption(bool facilitator) +{ + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + SecPolicyAddBasicX509Options(options); + + /* Anchored to the Apple Roots */ + require(SecPolicyAddAppleAnchorOptions(options, kSecPolicyNameAggregateMetricEncryption), errOut); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Intermediate marker OID matches AAICA 6 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.26")); + + /* Leaf marker OID matches expected OID for either Facilitator or Partner */ + if (facilitator) { + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.15.2")); + } else { + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.15.3")); + } + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + /* Require CT */ + if (!SecIsInternalRelease() || !isCFPreferenceInSecurityDomain(CFSTR("disableAggregateMetricsCTCheck"))) { + add_element(options, kSecPolicyCheckNonTlsCTRequired, kCFBooleanTrue); + } + + require(result = SecPolicyCreate(kSecPolicyAppleAggregateMetricEncryption, + kSecPolicyNameAggregateMetricEncryption, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +SecPolicyRef SecPolicyCreateApplePayModelSigning(bool checkExpiration) { + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + if (checkExpiration) { + SecPolicyAddBasicX509Options(options); + } else { + SecPolicyAddBasicCertOptions(options); + } + + /* Anchored to the Apple Roots */ + require(SecPolicyAddAppleAnchorOptions(options, kSecPolicyNamePayModelSigning), errOut); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Intermediate marker OID is Apple System Integration CA 4 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.17")); + + /* Leaf marker OID for ApplePay Model Signing */ + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.12.20")); + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + require(result = SecPolicyCreate(kSecPolicyApplePayModelSigning, + kSecPolicyNamePayModelSigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} diff --git a/OSX/sec/Security/SecPolicy.list b/OSX/sec/Security/SecPolicy.list index 6dfb4452..e3255661 100644 --- a/OSX/sec/Security/SecPolicy.list +++ b/OSX/sec/Security/SecPolicy.list @@ -35,8 +35,6 @@ POLICYMACRO(EscrowService, 24, E, AppleEscrowService, POLICYMACRO(ProfileSigner, 25, E, AppleProfileSigner, , Y, ConfigurationProfileSigner) POLICYMACRO(QAProfileSigner, 26, E, AppleQAProfileSigner, , Y, QAConfigurationProfileSigner) POLICYMACRO(TestMobileStore, 27, E, AppleTestMobileStore, , Y, TestMobileStoreSigner) -POLICYMACRO(OTAPKISigner, 28, E, AppleOTAPKIAssetSigner, , Y, OTAPKISigner) -POLICYMACRO(TestOTAPKISigner, 29, E, AppleTestOTAPKIAssetSigner, , Y, TestOTAPKISigner) POLICYMACRO(IDValidationRecordSigning, 30, E, AppleIDValidationRecordSigningPolicy, , Y, AppleIDValidationRecordSigningPolicy) POLICYMACRO(SMPEncryption, 31, E, AppleSMPEncryption, , Y, AppleSMPEncryption) POLICYMACRO(TestSMPEncryption, 32, E, AppleTestSMPEncryption, , Y, TestAppleSMPEncryption) @@ -99,3 +97,13 @@ POLICYMACRO(FDRProvisioning, 91, , FDRProvisioning, POLICYMACRO(ComponentCertificate, 92, E, Component, , , AppleComponentCertificate) POLICYMACRO(KeyTransparency, 93, E, KT, N, Y, AppleKeyTransparency) POLICYMACRO(LegacySSL, 94, E, legacySSL, , , LegacySSL) +POLICYMACRO(Alisha, 95, E, Alisha, , Y, Alisha) +POLICYMACRO(MeasuredBootPolicySigning, 96, E, MeasuredBootPolicySigning, , Y, MeasuredBootPolicySigning) +POLICYMACRO(PayQRCodeEncryption, 97, E, ApplePayQRCodeEncryption, , Y, ApplePayQRCodeEncryption) +POLICYMACRO(PayQRCodeSigning, 98, E, ApplePayQRCodeSigning, , Y, ApplePayQRCodeSigning) +POLICYMACRO(AccessoryUpdateSigning, 99, E, AccessoryUpdateSigning, , Y, AppleAccessoryUpdateSigning) +POLICYMACRO(EscrowServiceIdKeySigning, 100, E, AppleEscrowServiceIdKeySigning, , Y, EscrowServiceIdKeySigning) +POLICYMACRO(PCSEscrowServiceIdKeySigning, 101, E, ApplePCSEscrowServiceIdKeySigning, , Y, PCSEscrowServiceIdKeySigning) +POLICYMACRO(AggregateMetricTransparency, 102, E, AggregateMetricTransparency, , , AggregateMetricTransparency) +POLICYMACRO(AggregateMetricEncryption, 103, E, AggregateMetricEncryption, , , AggregateMetricEncryption) +POLICYMACRO(PayModelSigning, 104, E, ApplePayModelSigning, , , ApplePayModelSigning) diff --git a/OSX/sec/Security/SecPolicyChecks.list b/OSX/sec/Security/SecPolicyChecks.list index 18072c46..2a82bbef 100644 --- a/OSX/sec/Security/SecPolicyChecks.list +++ b/OSX/sec/Security/SecPolicyChecks.list @@ -23,7 +23,7 @@ POLICYCHECKMACRO(TemporalValidity, R, E, L, A, O, 0x8001210A, errS POLICYCHECKMACRO(WeakKeySize, F, S, L, A, O, 0x80012115, errSecUnsupportedKeySize) //CSSMERR_TP_INVALID_CERTIFICATE POLICYCHECKMACRO(WeakSignature, F, H, L, A, O, 0x80010955, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_INVALID_DIGEST_ALGORITHM POLICYCHECKMACRO(KeyUsage, R, U, L, , O, 0x80012406, errSecInvalidKeyUsageForPolicy) //CSSMERR_APPLETP_INVALID_KEY_USAGE -POLICYCHECKMACRO(ExtendedKeyUsage, R, U, L, , O, 0x80012407, errSecInvalidExtendedKeyUsage) //CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +POLICYCHECKMACRO(ExtendedKeyUsage, R, U, L, A, O, 0x80012407, errSecInvalidExtendedKeyUsage) //CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE POLICYCHECKMACRO(SubjectCommonName, R, P, L, , O, 0x8001243B, errSecInvalidSubjectName) //CSSMERR_APPLETP_IDENTIFIER_MISSING POLICYCHECKMACRO(SubjectCommonNamePrefix, R, P, L, , O, 0x8001243B, errSecInvalidSubjectName) //CSSMERR_APPLETP_IDENTIFIER_MISSING POLICYCHECKMACRO(SubjectCommonNameTEST, R, P, L, , O, 0x8001243B, errSecInvalidSubjectName) //CSSMERR_APPLETP_IDENTIFIER_MISSING @@ -36,6 +36,9 @@ POLICYCHECKMACRO(LeafMarkerOidWithoutValueCheck, R, P, L, , O, 0x80012439, errS POLICYCHECKMACRO(LeafMarkersProdAndQA, R, P, L, , O, 0x80012439, errSecMissingRequiredExtension) //CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION POLICYCHECKMACRO(BlackListedLeaf, F, B, L, , , 0x8001210C, errSecCertificateRevoked) //CSSMERR_TP_CERT_REVOKED POLICYCHECKMACRO(GrayListedLeaf, R, T, L, , , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED +POLICYCHECKMACRO(LeafSPKISHA256, R, P, L, , , 0x8001243D, errSSLATSCertificateTrustViolation) //CSSMERR_APPLETP_LEAF_PIN_MISMATCH +POLICYCHECKMACRO(NotCA, R, C, L, , O, 0x80012116, errSecCertificateIsCA) // CSSMERR_TP_INVALID_CERT_AUTHORITY +POLICYCHECKMACRO(KeyUsageReportOnly, R, U, L, , , 0x80012406, errSecInvalidKeyUsageForPolicy) //CSSMERR_APPLETP_INVALID_KEY_USAGE /******************************************************** *********** Unverified Intermediate Checks ************* @@ -54,11 +57,11 @@ POLICYCHECKMACRO(IntermediateCountry, R, P, , A, , 0x800124 /******************************************************** ************** Unverified Anchor Checks **************** ********************************************************/ -POLICYCHECKMACRO(AnchorSHA1, R, P, , A, , 0x8001243C, errSecInvalidRoot) //CSSMERR_APPLETP_CA_PIN_MISMATCH POLICYCHECKMACRO(AnchorSHA256, R, P, , A, , 0x8001243C, errSecInvalidRoot) //CSSMERR_APPLETP_CA_PIN_MISMATCH POLICYCHECKMACRO(AnchorTrusted, R, T, , , , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED POLICYCHECKMACRO(MissingIntermediate, R, T, , , , 0x8001212A, errSecCreateChainFailed) //CSSMERR_TP_NOT_TRUSTED POLICYCHECKMACRO(AnchorApple, R, P, , A, , 0x8001243C, errSecInvalidRoot) //CSSMERR_APPLETP_CA_PIN_MISMATCH +POLICYCHECKMACRO(CAspkiSHA256, R, P, , A, , 0x8001243C, errSSLATSCertificateTrustViolation) //CSSMERR_APPLETP_CA_PIN_MISMATCH /******************************************************** *********** Unverified Certificate Checks ************** @@ -66,7 +69,7 @@ POLICYCHECKMACRO(AnchorApple, R, P, , A, , 0x8001243C, errS POLICYCHECKMACRO(NonEmptySubject, R, C, , A, O, 0x80012437, errSecInvalidSubjectName) //CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT POLICYCHECKMACRO(IdLinkage, R, C, , A, , 0x80012404, errSecInvalidIDLinkage) //CSSMERR_APPLETP_INVALID_AUTHORITY_ID POLICYCHECKMACRO(KeySize, R, P, , A, O, 0x80010918, errSecUnsupportedKeySize) //CSSMERR_CSP_UNSUPPORTED_KEY_SIZE -POLICYCHECKMACRO(SignatureHashAlgorithms, R, P, , A, O, 0x80010913, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_ALGID_MISMATCH +POLICYCHECKMACRO(SignatureHashAlgorithms, R, H, , A, O, 0x80010913, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_ALGID_MISMATCH POLICYCHECKMACRO(CertificatePolicy, R, P, , A, O, 0x80012439, errSecInvalidPolicyIdentifiers) //CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION POLICYCHECKMACRO(ValidRoot, R, E, , , , 0x8001210A, errSecCertificateExpired) //CSSMERR_TP_CERT_EXPIRED @@ -81,18 +84,19 @@ POLICYCHECKMACRO(PolicyConstraints, R, C, , , , 0x80012115, errS POLICYCHECKMACRO(GrayListedKey, R, T, , , , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED POLICYCHECKMACRO(BlackListedKey, F, B, , , , 0x8001210C, errSecCertificateRevoked) //CSSMERR_TP_CERT_REVOKED POLICYCHECKMACRO(UsageConstraints, D, D, , , , 0x80012436, errSecTrustSettingDeny) //CSSMERR_APPLETP_TRUST_SETTING_DENY -POLICYCHECKMACRO(SystemTrustedWeakHash, R, C, , A, , 0x80010955, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_INVALID_DIGEST_ALGORITHM -POLICYCHECKMACRO(SystemTrustedWeakKey, R, C, , A, , 0x80010918, errSecUnsupportedKeySize) //CSSMERR_CSP_UNSUPPORTED_KEY_SIZE +POLICYCHECKMACRO(SystemTrustedWeakHash, R, H, , A, , 0x80010955, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_INVALID_DIGEST_ALGORITHM +POLICYCHECKMACRO(SystemTrustedWeakKey, R, S, , A, , 0x80010918, errSecUnsupportedKeySize) //CSSMERR_CSP_UNSUPPORTED_KEY_SIZE POLICYCHECKMACRO(PinningRequired, R, P, L, , , 0x8001243C, errSecInvalidRoot) //CSSMERR_APPLETP_CA_PIN_MISMATCH POLICYCHECKMACRO(Revocation, F, V, L, , , 0x8001210C, errSecCertificateRevoked) //CSSMERR_TP_CERT_REVOKED POLICYCHECKMACRO(RevocationResponseRequired, R, P, L, , , 0x80012423, errSecIncompleteCertRevocationCheck) //CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK -POLICYCHECKMACRO(CTRequired, R, T, , , , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED +POLICYCHECKMACRO(CTRequired, R, T, , A, , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED POLICYCHECKMACRO(SystemTrustedCTRequired, R, C, , A, , 0x80012114, errSecVerifyActionFailed) //CSSMERR_TP_VERIFY_ACTION_FAILED POLICYCHECKMACRO(IssuerPolicyConstraints, F, B, , , , 0x80012120, errSecCertificatePolicyNotAllowed) //CSSMERR_TP_INVALID_POLICY_IDENTIFIERS POLICYCHECKMACRO(IssuerNameConstraints, F, B, , , , 0x8001211F, errSecCertificateNameNotAllowed) //CSSMERR_TP_INVALID_NAME POLICYCHECKMACRO(ValidityPeriodMaximums, R, C, , A, , 0x8001210D, errSecCertificateValidityPeriodTooLong) //CSSMERR_TP_CERT_SUSPENDED POLICYCHECKMACRO(ServerAuthEKU, R, U, , A, , 0x80012407, errSecInvalidExtendedKeyUsage) //CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE POLICYCHECKMACRO(UnparseableExtension, R, C, , , O, 0x80012410, errSecUnknownCertExtension) //CSSMERR_APPLETP_UNKNOWN_CERT_EXTEN +POLICYCHECKMACRO(NonTlsCTRequired, R, T, , A, , 0x80012114, errSecVerifyActionFailed) //CSSMERR_TP_VERIFY_ACTION_FAILED /******************************************************** ******************* Feature Toggles ********************* diff --git a/OSX/sec/Security/SecPolicyLeafCallbacks.c b/OSX/sec/Security/SecPolicyLeafCallbacks.c index d7562db8..36d614e4 100644 --- a/OSX/sec/Security/SecPolicyLeafCallbacks.c +++ b/OSX/sec/Security/SecPolicyLeafCallbacks.c @@ -62,6 +62,10 @@ static bool keyusage_allows(SecKeyUsage keyUsage, CFTypeRef xku) { SInt32 dku; CFNumberGetValue((CFNumberRef)xku, kCFNumberSInt32Type, &dku); SecKeyUsage ku = (SecKeyUsage)dku; + /* kSecKeyUsageUnspecified is a special sentinel for allowing a missing KU extension */ + if (ku == kSecKeyUsageUnspecified) { + return (keyUsage == ku); + } return (keyUsage & ku) == ku; } @@ -303,15 +307,13 @@ bool SecPolicyCheckCertSSLHostname(SecCertificateRef cert, CFTypeRef pvcValue) { obtained by SecCertificateCopyIPAddresses. Comparisons must always use the canonical data representation of the address, since string notation may omit zeros, etc. */ - CFArrayRef ipAddresses = SecCertificateCopyIPAddresses(cert); + CFArrayRef ipAddresses = SecCertificateCopyIPAddressDatas(cert); CFIndex ix, count = (ipAddresses) ? CFArrayGetCount(ipAddresses) : 0; for (ix = 0; ix < count && !dnsMatch; ++ix) { - CFStringRef ipAddress = (CFStringRef)CFArrayGetValueAtIndex(ipAddresses, ix); - CFDataRef addrData = SecFrameworkCopyIPAddressData(ipAddress); - if (CFEqualSafe(hostIPData, addrData)) { + CFDataRef ipAddress = (CFDataRef)CFArrayGetValueAtIndex(ipAddresses, ix); + if (CFEqualSafe(hostIPData, ipAddress)) { dnsMatch = true; } - CFReleaseSafe(addrData); } CFReleaseSafe(ipAddresses); CFReleaseSafe(hostIPData); @@ -693,6 +695,13 @@ bool SecPolicyCheckCertUnparseableExtension(SecCertificateRef cert, CFTypeRef pv return true; } +bool SecPolicyCheckCertNotCA(SecCertificateRef cert, CFTypeRef pvcValue) { + if (SecCertificateIsCA(cert)) { + return false; + } + return true; +} + /* * MARK: SecLeafPVC functions */ diff --git a/OSX/sec/Security/SecRSAKey.c b/OSX/sec/Security/SecRSAKey.c index fb8f2c51..66f9f239 100644 --- a/OSX/sec/Security/SecRSAKey.c +++ b/OSX/sec/Security/SecRSAKey.c @@ -607,12 +607,13 @@ static CFDataRef SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_ful { const size_t result_size = ccrsa_export_priv_size(fullkey); - CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size); + CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size); - if (pkcs1 == NULL) + if (pkcs1 == NULL) { return NULL; + } - CFDataSetLength(pkcs1, result_size); + CFDataSetLength(pkcs1, result_size); uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1); diff --git a/OSX/sec/Security/SecRecoveryKey.m b/OSX/sec/Security/SecRecoveryKey.m index ecf9ddc1..5f400e02 100644 --- a/OSX/sec/Security/SecRecoveryKey.m +++ b/OSX/sec/Security/SecRecoveryKey.m @@ -9,9 +9,9 @@ #import #import #import +#import #import -#import #import @@ -20,9 +20,7 @@ #if !TARGET_OS_BRIDGE #include -#ifndef DARLING #include -#endif #define PATH_FOR_APPLEIDAUTHSUPPORTFRAMEWORK "/System/Library/PrivateFrameworks/AppleIDAuthSupport.framework/AppleIDAuthSupport" #endif @@ -303,7 +301,7 @@ RKBackupCreateECKey(SecRecoveryKey *rk, bool returnFullkey) status = ccec_generate_key_deterministic(cp, CFDataGetLength(derivedSecret), CFDataGetBytePtr(derivedSecret), - ccDRBGGetRngState(), + ccrng(NULL), CCEC_GENKEY_DETERMINISTIC_COMPACT, fullKey); require_noerr(status, fail); diff --git a/OSX/sec/Security/SecServerEncryptionSupport.c b/OSX/sec/Security/SecServerEncryptionSupport.c index 507a181b..e43f0f6b 100644 --- a/OSX/sec/Security/SecServerEncryptionSupport.c +++ b/OSX/sec/Security/SecServerEncryptionSupport.c @@ -327,11 +327,7 @@ CFDataRef SecCopyDecryptedForServer(SecKeyRef serverFullKey, CFDataRef blob, CFE CFDataRef SecCopyEncryptedToServer(SecTrustRef trustedEvaluation, CFDataRef dataToEncrypt, CFErrorRef *error) { CFDataRef result = NULL; -#if TARGET_OS_OSX - SecKeyRef trustKey = SecTrustCopyPublicKey_ios(trustedEvaluation); -#else - SecKeyRef trustKey = SecTrustCopyPublicKey(trustedEvaluation); -#endif + SecKeyRef trustKey = SecTrustCopyKey(trustedEvaluation); require_action_quiet(trustKey, fail, SecError(errSecInteractionNotAllowed, error, CFSTR("Failed to get key out of trust ref, was it evaluated?"))); diff --git a/OSX/sec/Security/SecSharedCredential.c b/OSX/sec/Security/SecSharedCredential.c index b9ec9bf6..f77c9af2 100644 --- a/OSX/sec/Security/SecSharedCredential.c +++ b/OSX/sec/Security/SecSharedCredential.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2014-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -36,9 +36,29 @@ /* forward declarations */ OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFStringRef password, CFErrorRef *error); OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, CFErrorRef *error); +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST +OSStatus SecCopySharedWebCredentialSyncUsingAuthSvcs(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, CFErrorRef *error); +#endif #if SHAREDWEBCREDENTIALS +// OSX now has SWC enabled, but cannot link SharedWebCredentials framework: rdar://59958701 +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + +OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, + CFStringRef account, + CFStringRef password, + CFErrorRef *error) +{ + OSStatus status = errSecUnimplemented; + if (error) { + SecError(status, error, CFSTR("SecAddSharedWebCredentialSync not supported on this platform")); + } + return status; +} + +#else + OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFStringRef password, @@ -59,7 +79,7 @@ OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, } status = SecOSStatusWith(^bool (CFErrorRef *error) { CFTypeRef raw_result = NULL; - bool xpc_result; + bool xpc_result = false; bool internal_spi = false; // TODO: support this for SecurityDevTests if(internal_spi && gSecurityd && gSecurityd->sec_add_shared_web_credential) { xpc_result = gSecurityd->sec_add_shared_web_credential(args, NULL, NULL, NULL, SecAccessGroupsGetCurrent(), &raw_result, error); @@ -84,6 +104,7 @@ OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, return status; } +#endif /* !TARGET_OS_OSX || !TARGET_OS_MACCATALYST */ #endif /* SHAREDWEBCREDENTIALS */ void SecAddSharedWebCredential(CFStringRef fqdn, @@ -147,6 +168,23 @@ void SecAddSharedWebCredential(CFStringRef fqdn, } #if SHAREDWEBCREDENTIALS + +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + +OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, + CFStringRef account, + CFArrayRef *credentials, + CFErrorRef *error) +{ + OSStatus status = errSecUnimplemented; + if (error) { + SecError(status, error, CFSTR("SecCopySharedWebCredentialSync not supported on this platform")); + } + return status; +} + +#else + OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, @@ -164,7 +202,7 @@ OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, } status = SecOSStatusWith(^bool (CFErrorRef *error) { CFTypeRef raw_result = NULL; - bool xpc_result; + bool xpc_result = false; bool internal_spi = false; // TODO: support this for SecurityDevTests if(internal_spi && gSecurityd && gSecurityd->sec_copy_shared_web_credential) { xpc_result = gSecurityd->sec_copy_shared_web_credential(args, NULL, NULL, NULL, SecAccessGroupsGetCurrent(), &raw_result, error); @@ -192,6 +230,7 @@ OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, return status; } +#endif /* !TARGET_OS_OSX || !TARGET_OS_MACCATALYST */ #endif /* SHAREDWEBCREDENTIALS */ void SecRequestSharedWebCredential(CFStringRef fqdn, @@ -227,7 +266,11 @@ void SecRequestSharedWebCredential(CFStringRef fqdn, __block CFStringRef accountStr = CFRetainSafe(account); dispatch_async(dst_queue, ^{ +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + OSStatus status = SecCopySharedWebCredentialSyncUsingAuthSvcs(serverStr, accountStr, &result, &error); +#else OSStatus status = SecCopySharedWebCredentialSync(serverStr, accountStr, &result, &error); +#endif CFReleaseSafe(serverStr); CFReleaseSafe(accountStr); @@ -250,7 +293,7 @@ void SecRequestSharedWebCredential(CFStringRef fqdn, } CFReleaseSafe(error); }); -#endif +#endif /* SHAREDWEBCREDENTIALS */ } diff --git a/OSX/sec/Security/SecSharedCredential.m b/OSX/sec/Security/SecSharedCredential.m new file mode 100644 index 00000000..4fd5f188 --- /dev/null +++ b/OSX/sec/Security/SecSharedCredential.m @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * SecSharedCredential.m - Retrieve shared credentials with AuthenticationServices. + * + */ + +#include +#include +#include +#include +#include "SecItemInternal.h" +#include + +#import +#import + +// Forward declaration of the primary function implemented in this file +OSStatus SecCopySharedWebCredentialSyncUsingAuthSvcs(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, CFErrorRef *error); + +// Classes we will load dynamically +static Class kASAuthorizationClass = NULL; +static Class kASAuthorizationControllerClass = NULL; +static Class kASAuthorizationPasswordProviderClass = NULL; +static Class kASPasswordCredentialClass = NULL; +static Class kUIApplicationClass = NULL; +static Class kNSApplicationClass = NULL; + +static void loadAuthenticationServices(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + const char *path = "/System/Library/Frameworks/AuthenticationServices.framework/AuthenticationServices"; + if ( [NSProcessInfo processInfo].macCatalystApp == YES ) { + path = "/System/iOSSupport/System/Library/Frameworks/AuthenticationServices.framework/AuthenticationServices"; + } + void* lib_handle = dlopen(path, RTLD_LAZY); + if (lib_handle != NULL) { + kASAuthorizationClass = NSClassFromString(@"ASAuthorization"); + kASAuthorizationControllerClass = NSClassFromString(@"ASAuthorizationController"); + kASAuthorizationPasswordProviderClass = NSClassFromString(@"ASAuthorizationPasswordProvider"); + kASPasswordCredentialClass = NSClassFromString(@"ASPasswordCredential"); + } + }); +} + +static void loadUIKit(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + const char *path = "/System/Library/Frameworks/UIKit.framework/UIKit"; + if ( [NSProcessInfo processInfo].macCatalystApp == YES ) { + path = "/System/Library/iOSSupport/System/Library/Frameworks/UIKit.framework/UIKit"; + } + void* lib_handle = dlopen(path, RTLD_LAZY); + if (lib_handle != NULL) { + kUIApplicationClass = NSClassFromString(@"UIApplication"); + } + }); +} + +static void loadAppKit(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + const char *path = "/System/Library/Frameworks/AppKit.framework/AppKit"; + void* lib_handle = dlopen(path, RTLD_LAZY); + if (lib_handle != NULL) { + kNSApplicationClass = NSClassFromString(@"NSApplication"); + } + }); +} + +static Class ASAuthorizationClass() { + loadAuthenticationServices(); + return kASAuthorizationClass; +} + +static Class ASAuthorizationControllerClass() { + loadAuthenticationServices(); + return kASAuthorizationControllerClass; +} + +static Class ASAuthorizationPasswordProviderClass() { + loadAuthenticationServices(); + return kASAuthorizationPasswordProviderClass; +} + +static Class ASPasswordCredentialClass() { + loadAuthenticationServices(); + return kASPasswordCredentialClass; +} + +static Class UIApplicationClass() { + loadUIKit(); + return kUIApplicationClass; +} + +static Class NSApplicationClass() { + loadAppKit(); + return kNSApplicationClass; +} + +@interface SharedCredentialController : NSObject + + +-(ASPasswordCredential *)passwordCredential; + +@end + +@implementation SharedCredentialController { + ASAuthorizationPasswordProvider *_provider; + ASAuthorizationController *_controller; + ASPasswordCredential *_passwordCredential; + dispatch_semaphore_t _semaphore; + NSError *_error; + OSStatus _result; +} + +- (void)dealloc { + // Don't want any further callbacks since we are going away + _controller.delegate = nil; + _controller.presentationContextProvider = nil; +} + +- (void)_requestCredential { + if (!_provider) { + _provider = [[ASAuthorizationPasswordProviderClass() alloc] init]; + } + if (!_controller) { + _controller = [[ASAuthorizationControllerClass() alloc] initWithAuthorizationRequests:@[ [_provider createRequest] ]]; + } + _controller.delegate = self; + _controller.presentationContextProvider = self; + _semaphore = dispatch_semaphore_create(0); + _result = errSecItemNotFound; + _error = nil; + + [_controller performRequests]; +} + +- (ASPasswordCredential *)passwordCredential { + if (_passwordCredential) { + return _passwordCredential; + } + BOOL shouldRequest = YES; // ( [NSProcessInfo processInfo].macCatalystApp == YES ); + if (shouldRequest) { + [self _requestCredential]; + // wait synchronously until user picks a credential or cancels + dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER); + } else { + // unable to return a shared credential: + _result = errSecItemNotFound; + _error = [[NSError alloc] initWithDomain:NSOSStatusErrorDomain code:_result userInfo:NULL]; + } + return _passwordCredential; +} + +- (NSError *)error { + return _error; +} + +- (OSStatus)result { + return _result; +} + +- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization { + secinfo("swcagent", "SWC received didCompleteWithAuthorization"); + ASPasswordCredential *passwordCredential = authorization.credential; + if (![passwordCredential isKindOfClass:[ASPasswordCredentialClass() class]]) { + _passwordCredential = nil; + _result = errSecItemNotFound; + } else { + _passwordCredential = passwordCredential; + _result = errSecSuccess; + } + dispatch_semaphore_signal(_semaphore); +} + +- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error { + secinfo("swcagent", "SWC received didCompleteWithError"); + _passwordCredential = nil; + _error = error; + _result = errSecItemNotFound; + dispatch_semaphore_signal(_semaphore); +} + +- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller +{ + ASPresentationAnchor anchorWindow = nil; +#if TARGET_OS_OSX + if ( [NSProcessInfo processInfo].macCatalystApp == NO ) { + anchorWindow = [[NSApplicationClass() sharedApplication] keyWindow]; + } +#endif + if (!anchorWindow) { + anchorWindow = [[UIApplicationClass() sharedApplication] keyWindow]; + } + return anchorWindow; +} + +@end + +OSStatus SecCopySharedWebCredentialSyncUsingAuthSvcs(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, CFErrorRef *error) { + SharedCredentialController *controller = [[SharedCredentialController alloc] init]; + ASPasswordCredential *passwordCredential = [controller passwordCredential]; + OSStatus status = [controller result]; + NSArray *returnedCredentials = @[]; + if (status != errSecSuccess) { + secinfo("swcagent", "SecCopySharedWebCredentialSyncUsingAuthSvcs received result %d", (int)status); + if (error) { + *error = (CFErrorRef)CFBridgingRetain([controller error]); + } + } else if (passwordCredential) { + // Use the .user and .password of the passwordCredential to satisfy the SWC interface. + NSDictionary *credential = @{ + (id)kSecAttrServer : (__bridge NSString*)fqdn, + (id)kSecAttrAccount : passwordCredential.user, + (id)kSecSharedPassword : passwordCredential.password, + }; + returnedCredentials = @[ credential ]; + } else { + secinfo("swcagent", "SecCopySharedWebCredentialSyncUsingAuthSvcs found no credential"); + status = errSecItemNotFound; + } + if (credentials) { + *credentials = (CFArrayRef)CFBridgingRetain(returnedCredentials); + } + return status; +} diff --git a/OSX/sec/Security/SecTrust.c b/OSX/sec/Security/SecTrust.c index d64de6dd..ee5aea2c 100644 --- a/OSX/sec/Security/SecTrust.c +++ b/OSX/sec/Security/SecTrust.c @@ -73,9 +73,7 @@ SEC_CONST_DECL (kSecCertificateDetailSHA1Digest, "SHA1Digest"); SEC_CONST_DECL (kSecCertificateDetailStatusCodes, "StatusCodes"); -#if TARGET_OS_IPHONE SEC_CONST_DECL (kSecCertificateExceptionResetCount, "ExceptionResetCount"); -#endif SEC_CONST_DECL (kSecTrustInfoExtendedValidationKey, "ExtendedValidation"); SEC_CONST_DECL (kSecTrustInfoCompanyNameKey, "CompanyName"); @@ -83,6 +81,10 @@ SEC_CONST_DECL (kSecTrustInfoRevocationKey, "Revocation"); SEC_CONST_DECL (kSecTrustInfoRevocationValidUntilKey, "RevocationValidUntil"); SEC_CONST_DECL (kSecTrustInfoCertificateTransparencyKey, "CertificateTransparency"); +/* This is the "real" trust validity date which includes all inputs. */ +SEC_CONST_DECL (kSecTrustInfoResultNotBefore, "TrustResultNotBefore"); +SEC_CONST_DECL (kSecTrustInfoResultNotAfter, "TrustResultNotAfter"); + /* Public trust result constants */ SEC_CONST_DECL (kSecTrustEvaluationDate, "TrustEvaluationDate"); SEC_CONST_DECL (kSecTrustExtendedValidation, "TrustExtendedValidation"); @@ -90,11 +92,14 @@ SEC_CONST_DECL (kSecTrustOrganizationName, "Organization"); SEC_CONST_DECL (kSecTrustResultValue, "TrustResultValue"); SEC_CONST_DECL (kSecTrustRevocationChecked, "TrustRevocationChecked"); SEC_CONST_DECL (kSecTrustRevocationReason, "TrustRevocationReason"); -SEC_CONST_DECL (kSecTrustRevocationValidUntilDate, "TrustExpirationDate"); SEC_CONST_DECL (kSecTrustResultDetails, "TrustResultDetails"); SEC_CONST_DECL (kSecTrustCertificateTransparency, "TrustCertificateTransparency"); SEC_CONST_DECL (kSecTrustCertificateTransparencyWhiteList, "TrustCertificateTransparencyWhiteList"); +/* This value is actually incorrect as this constant only refers to the revocation expiration + * not the trust expiration. But it's API. */ +SEC_CONST_DECL (kSecTrustRevocationValidUntilDate, "TrustExpirationDate"); + #pragma mark - #pragma mark SecTrust @@ -1834,15 +1839,7 @@ CFStringRef SecTrustCopyFailureDescription(SecTrustRef trust) { return reason; } -#if TARGET_OS_OSX -/* On OS X we need SecTrustCopyPublicKey to give us a CDSA-based SecKeyRef, - so we will refer to this one internally as SecTrustCopyPublicKey_ios, - and call it from SecTrustCopyPublicKey. - */ -SecKeyRef SecTrustCopyPublicKey_ios(SecTrustRef trust) -#else -SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) -#endif +SecKeyRef SecTrustCopyKey(SecTrustRef trust) { if (!trust) { return NULL; @@ -1870,7 +1867,20 @@ SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) } }); } - return publicKey; + return publicKey; +} + +#if TARGET_OS_OSX +/* On OS X we need SecTrustCopyPublicKey to give us a CDSA-based SecKeyRef, + so we will refer to this one internally as SecTrustCopyPublicKey_ios, + and call it from SecTrustCopyPublicKey. + */ +SecKeyRef SecTrustCopyPublicKey_ios(SecTrustRef trust) +#else +SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) +#endif +{ + return SecTrustCopyKey(trust); } CFIndex SecTrustGetCertificateCount(SecTrustRef trust) { @@ -1940,7 +1950,9 @@ CFDataRef SecTrustCopyExceptions(SecTrustRef trust) { trust->_exceptions = NULL; } }); - SecTrustSetNeedsEvaluation(trust); + if (oldExceptions) { + SecTrustSetNeedsEvaluation(trust); + } /* Create the new exceptions based on an unfiltered eval. */ __block CFArrayRef details = NULL; @@ -1950,13 +1962,11 @@ CFDataRef SecTrustCopyExceptions(SecTrustRef trust) { }); CFIndex pathLength = details ? CFArrayGetCount(details) : 0; CFMutableArrayRef exceptions = CFArrayCreateMutable(kCFAllocatorDefault, pathLength, &kCFTypeArrayCallBacks); -#if TARGET_OS_IPHONE /* Fetch the current exceptions epoch and tag each exception with it. */ CFErrorRef exceptionResetCountError = NULL; uint64_t exceptionResetCount = SecTrustGetExceptionResetCount(&exceptionResetCountError); secinfo("trust", "The current exceptions epoch is %llu. (%{public}s)", exceptionResetCount, exceptionResetCountError ? "Error" : "OK"); CFNumberRef exceptionResetCountRef = CFNumberCreate(NULL, kCFNumberSInt64Type, &exceptionResetCount); -#endif CFIndex ix; for (ix = 0; ix < pathLength; ++ix) { CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix); @@ -1967,11 +1977,9 @@ CFDataRef SecTrustCopyExceptions(SecTrustRef trust) { SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix); CFDataRef digest = SecCertificateGetSHA1Digest(certificate); CFDictionaryAddValue(exception, kSecCertificateDetailSHA1Digest, digest); -#if TARGET_OS_IPHONE if (exceptionResetCount && !exceptionResetCountError && exceptionResetCountRef) { CFDictionaryAddValue(exception, kSecCertificateExceptionResetCount, exceptionResetCountRef); } -#endif } else { /* Add empty exception dictionaries for non leaf certs which have no exceptions to save space. */ exception = (CFMutableDictionaryRef)CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, @@ -2004,13 +2012,11 @@ CFDataRef SecTrustCopyExceptions(SecTrustRef trust) { exceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL); CFRelease(exceptions); CFReleaseSafe(details); -#if TARGET_OS_IPHONE CFReleaseSafe(exceptionResetCountRef); -#endif + CFReleaseSafe(exceptionResetCountError); return encodedExceptions; } -#if TARGET_OS_IPHONE static bool SecTrustExceptionsValidForThisEpoch(CFArrayRef exceptions) { if (!exceptions) { return false; @@ -2023,6 +2029,7 @@ static bool SecTrustExceptionsValidForThisEpoch(CFArrayRef exceptions) { /* Fail closed: if we were unable to get the current exceptions epoch consider the exceptions invalid. */ if (currentExceptionResetCountError) { secerror("Failed to get the current exceptions epoch."); + CFReleaseNull(currentExceptionResetCountError); return false; } /* If this is the first epoch ever there is no point in checking whether any exceptions belong in the past. */ @@ -2050,7 +2057,6 @@ static bool SecTrustExceptionsValidForThisEpoch(CFArrayRef exceptions) { secinfo("trust", "Exceptions are valid for the current exceptions epoch. (%llu)", currentExceptionResetCount); return true; } -#endif bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions) { if (!trust) { @@ -2077,11 +2083,7 @@ bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions) { SecTrustSetNeedsEvaluation(trust); /* If there is a valid exception entry for our current leaf we're golden. */ -#if TARGET_OS_IPHONE if (SecTrustGetExceptionForCertificateAtIndex(trust, 0) && SecTrustExceptionsValidForThisEpoch(exceptions)) { -#else - if (SecTrustGetExceptionForCertificateAtIndex(trust, 0)) { -#endif return true; } @@ -2222,7 +2224,6 @@ static void applyDetailProperty(const void *_key, const void *_value, } else if (CFEqual(key, kSecPolicyCheckCriticalExtensions)) { tf->unknownCritExtn = true; } else if (CFEqual(key, kSecPolicyCheckAnchorTrusted) - || CFEqual(key, kSecPolicyCheckAnchorSHA1) || CFEqual(key, kSecPolicyCheckAnchorSHA256) || CFEqual(key, kSecPolicyCheckAnchorApple)) { tf->untrustedAnchor = true; @@ -2576,6 +2577,18 @@ CFDictionaryRef SecTrustOTASecExperimentCopyAsset(CFErrorRef *error) { return result; } +bool SecTrustTriggerValidUpdate(CFErrorRef *error) { + do_if_registered(sec_valid_update, error); + + os_activity_t activity = os_activity_create("SecTrustTriggerValidUpdate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_scope(activity); + + uint64_t num = do_ota_pki_op(kSecXPCOpValidUpdate, error); + + os_release(activity); + return num; +} + bool SecTrustReportTLSAnalytics(CFStringRef eventName, xpc_object_t eventAttributes, CFErrorRef *error) { if (!eventName || !eventAttributes) { return false; @@ -2678,6 +2691,12 @@ OSStatus SecTrustEvaluateLeafOnly(SecTrustRef trust, SecTrustResultType *result) trustResult = kSecTrustResultUnspecified; } + /* Set trust result validity dates. This is a short window based on verifyTime. */ + CFAbsoluteTime resultNotBefore = SecTrustGetVerifyTime(trust); + CFAbsoluteTime resultNotAfter = resultNotBefore + TRUST_TIME_LEEWAY; + CFDateRef notBeforeDate = CFDateCreate(NULL, resultNotBefore); + CFDateRef notAfterDate = CFDateCreate(NULL, resultNotAfter); + /* Set other result context information */ dispatch_sync(trust->_trustQueue, ^{ trust->_trustResult = trustResult; @@ -2687,6 +2706,8 @@ OSStatus SecTrustEvaluateLeafOnly(SecTrustRef trust, SecTrustResultType *result) &kCFTypeDictionaryValueCallBacks); CFMutableArrayRef leafCert = CFArrayCreateMutableCopy(NULL, 1, trust->_certificates); trust->_chain = leafCert; + if (notBeforeDate) { CFDictionarySetValue(trust->_info, kSecTrustInfoResultNotBefore, notBeforeDate); } + if (notAfterDate) { CFDictionarySetValue(trust->_info, kSecTrustInfoResultNotAfter, notAfterDate); } }); SecLeafPVCDelete(&pvc); @@ -2703,6 +2724,8 @@ OSStatus SecTrustEvaluateLeafOnly(SecTrustRef trust, SecTrustResultType *result) } CFReleaseSafe(policies); + CFReleaseSafe(notBeforeDate); + CFReleaseSafe(notAfterDate); return status; } @@ -2933,7 +2956,6 @@ out: return trust; } -#if TARGET_OS_IPHONE static uint64_t to_uint_error_request(enum SecXPCOperation op, CFErrorRef *error) { __block uint64_t result = 0; @@ -2985,4 +3007,3 @@ OSStatus SecTrustIncrementExceptionResetCount(CFErrorRef *error) { return status; } -#endif diff --git a/OSX/sec/Security/SecTrustInternal.h b/OSX/sec/Security/SecTrustInternal.h index 4921bdd9..8d11e5fc 100644 --- a/OSX/sec/Security/SecTrustInternal.h +++ b/OSX/sec/Security/SecTrustInternal.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2015-2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2015-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -44,6 +44,7 @@ __BEGIN_DECLS #define kSecTrustTrustedLogsKey "trustedLogs" #define kSecTrustVerifyDateKey "verifyDate" #define kSecTrustExceptionsKey "exceptions" +#define kSecTrustRevocationAdditionsKey "revocationCheck" /* args_out keys. */ #define kSecTrustDetailsKey "details" diff --git a/OSX/sec/Security/SecTrustStatusCodes.c b/OSX/sec/Security/SecTrustStatusCodes.c index 20ad72f6..7ecba136 100644 --- a/OSX/sec/Security/SecTrustStatusCodes.c +++ b/OSX/sec/Security/SecTrustStatusCodes.c @@ -32,14 +32,6 @@ #include #include #include -#ifdef DARLING -// if i had to guess, i'd say Apple changed up libDER when they stopped releasing it and now -// their "private" OIDs are included in the regular `libDER/oids.h` header -// -// if this error keeps popping up, i'll stop manually including `libDER/oidsPriv.h` and instead patch -// `libDER/oids.h` to include `libDER/oidsPriv.h` -#include -#endif struct resultmap_entry_s { const CFStringRef checkstr; diff --git a/OSX/sec/Security/SecTrustStore.c b/OSX/sec/Security/SecTrustStore.c index 32f84c3b..79449ccc 100644 --- a/OSX/sec/Security/SecTrustStore.c +++ b/OSX/sec/Security/SecTrustStore.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007-2018 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2007-2020 Apple Inc. All Rights Reserved. + * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,11 +17,11 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ -/* +/* * SecTrustStore.c - CertificateSource API to a system root certificate store */ #include @@ -47,13 +47,23 @@ #include "SecTrustInternal.h" static CFStringRef kSecTrustStoreUserName = CFSTR("user"); +static CFStringRef kSecTrustStoreAdminName = CFSTR("admin"); +static CFStringRef kSecTrustStoreSystemName = CFSTR("system"); SecTrustStoreRef SecTrustStoreForDomain(SecTrustStoreDomain domain) { - CFStringRef domainName; - if (domain == kSecTrustStoreDomainUser) { - domainName = kSecTrustStoreUserName; - } else { - return NULL; + CFStringRef domainName = NULL; + switch (domain) { + case kSecTrustStoreDomainUser: + domainName = kSecTrustStoreUserName; + break; + case kSecTrustStoreDomainAdmin: + domainName = kSecTrustStoreAdminName; + break; + case kSecTrustStoreDomainSystem: + domainName = kSecTrustStoreSystemName; + break; + default: + return NULL; } if (gTrustd) { @@ -63,21 +73,30 @@ SecTrustStoreRef SecTrustStoreForDomain(SecTrustStoreDomain domain) { } } -static bool string_data_to_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFDataRef digest, CFErrorRef *error) +static bool SecXPCDictionarySetCertificate(xpc_object_t message, const char *key, SecCertificateRef certificate, CFErrorRef *error) { + if (certificate) { + xpc_dictionary_set_data(message, key, SecCertificateGetBytePtr(certificate), + SecCertificateGetLength(certificate)); + return true; + } + return SecError(errSecParam, error, CFSTR("NULL certificate")); +} + +static bool string_cert_to_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef cert, CFErrorRef *error) { return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) { return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) && - SecXPCDictionarySetData(message, kSecXPCKeyDigest, digest, blockError); + SecXPCDictionarySetCertificate(message, kSecXPCKeyCertificate, cert, blockError); }, NULL); } -static bool string_data_to_bool_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFDataRef digest, bool *result, CFErrorRef *error) +static bool string_cert_to_bool_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef cert, bool *result, CFErrorRef *error) { os_activity_t activity = os_activity_create("SecTrustStoreContains", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); os_activity_scope(activity); bool status = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) { return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) && - SecXPCDictionarySetData(message, kSecXPCKeyDigest, digest, error); + SecXPCDictionarySetCertificate(message, kSecXPCKeyCertificate, cert, blockError); }, ^bool(xpc_object_t response, CFErrorRef *blockError) { if (result) *result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); @@ -89,31 +108,17 @@ static bool string_data_to_bool_bool_error(enum SecXPCOperation op, SecTrustStor Boolean SecTrustStoreContains(SecTrustStoreRef ts, SecCertificateRef certificate) { - CFDataRef digest; bool ok = false; __block bool contains = false; - - require(ts, errOut); - require(digest = SecCertificateGetSHA1Digest(certificate), errOut); - - + require(ts, errOut); ok = (SecOSStatusWith(^bool (CFErrorRef *error) { - return TRUSTD_XPC(sec_trust_store_contains, string_data_to_bool_bool_error, ts, digest, &contains, error); + return TRUSTD_XPC(sec_trust_store_contains, string_cert_to_bool_bool_error, ts, certificate, &contains, error); }) == errSecSuccess); - + errOut: return ok && contains; } -static bool SecXPCDictionarySetCertificate(xpc_object_t message, const char *key, SecCertificateRef certificate, CFErrorRef *error) { - if (certificate) { - xpc_dictionary_set_data(message, key, SecCertificateGetBytePtr(certificate), - SecCertificateGetLength(certificate)); - return true; - } - return SecError(errSecParam, error, CFSTR("NULL certificate")); -} - static bool string_cert_cftype_to_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef certificate, CFTypeRef trustSettingsDictOrArray, CFErrorRef *error) { @@ -206,7 +211,7 @@ OSStatus SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, Boolean isSelfSigned = false; require_noerr_quiet(result = SecCertificateIsSelfSigned(certificate, &isSelfSigned), out); require_noerr_quiet(result = validateTrustSettings(isSelfSigned, trustSettingsDictOrArray, &validatedTrustSettings), out); - + os_activity_initiate("SecTrustStoreSetTrustSettings", OS_ACTIVITY_FLAG_DEFAULT, ^{ result = SecOSStatusWith(^bool (CFErrorRef *error) { return TRUSTD_XPC(sec_trust_store_set_trust_settings, string_cert_cftype_to_error, ts, certificate, validatedTrustSettings, error); @@ -221,17 +226,14 @@ out: OSStatus SecTrustStoreRemoveCertificate(SecTrustStoreRef ts, SecCertificateRef certificate) { - CFDataRef digest; __block OSStatus status = errSecParam; os_activity_t activity = os_activity_create("SecTrustStoreRemoveCertificate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); os_activity_scope(activity); require(ts, errOut); - require(digest = SecCertificateGetSHA1Digest(certificate), errOut); - require(gTrustd || ts == (SecTrustStoreRef)kSecTrustStoreUserName, errOut); - + status = SecOSStatusWith(^bool (CFErrorRef *error) { - return TRUSTD_XPC(sec_trust_store_remove_certificate, string_data_to_bool_error, ts, digest, error); + return TRUSTD_XPC(sec_trust_store_remove_certificate, string_cert_to_bool_error, ts, certificate, error); }); errOut: @@ -262,12 +264,12 @@ OSStatus SecTrustStoreGetSettingsAssetVersionNumber(SecTrustSettingsAssetVersion if (NULL == p_settings_asset_version_number) { return errSecParam; } - + OSStatus status = errSecSuccess; CFErrorRef error = nil; uint64_t versionNumber = SecTrustGetAssetVersionNumber(&error); *p_settings_asset_version_number = (SecTrustSettingsAssetVersionNumber)versionNumber; - + if (error) { status = (OSStatus)CFErrorGetCode(error); } @@ -308,11 +310,11 @@ errOut: return status; } -static bool string_data_to_array_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFDataRef digest, CFArrayRef *usageConstraints, CFErrorRef *error) +static bool string_cert_to_array_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef cert, CFArrayRef *usageConstraints, CFErrorRef *error) { return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *blockError) { return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, blockError) && - SecXPCDictionarySetData(message, kSecXPCKeyDigest, digest, blockError); + SecXPCDictionarySetCertificate(message, kSecXPCKeyCertificate, cert, blockError); }, ^bool(xpc_object_t response, CFErrorRef *blockError) { return SecXPCDictionaryCopyArrayOptional(response, kSecXPCKeyResult, usageConstraints, blockError); }); @@ -320,7 +322,6 @@ static bool string_data_to_array_error(enum SecXPCOperation op, SecTrustStoreRef OSStatus SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, SecCertificateRef certificate, CFArrayRef *usageConstraints) { - CFDataRef digest; __block CFArrayRef results = NULL; OSStatus status = errSecParam; @@ -328,11 +329,10 @@ OSStatus SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, SecCertificateRe os_activity_scope(activity); require(ts, errOut); require(certificate, errOut); - require(digest = SecCertificateGetSHA1Digest(certificate), errOut); require(usageConstraints, errOut); status = SecOSStatusWith(^bool (CFErrorRef *error) { - return TRUSTD_XPC(sec_trust_store_copy_usage_constraints, string_data_to_array_error, ts, digest, &results, error); + return TRUSTD_XPC(sec_trust_store_copy_usage_constraints, string_cert_to_array_error, ts, certificate, &results, error); }); *usageConstraints = results; @@ -344,12 +344,15 @@ errOut: #define do_if_registered(sdp, ...) if (gTrustd && gTrustd->sdp) { return gTrustd->sdp(__VA_ARGS__); } +const CFStringRef kSecTrustStoreSPKIHashKey = CFSTR("SubjectPublicKeyInfoHash"); +const CFStringRef kSecTrustStoreHashAlgorithmKey = CFSTR("HashAlgorithm"); + /* MARK: CT Enforcement Exceptions */ const CFStringRef kSecCTExceptionsCAsKey = CFSTR("DisabledForCAs"); const CFStringRef kSecCTExceptionsDomainsKey = CFSTR("DisabledForDomains"); -const CFStringRef kSecCTExceptionsHashAlgorithmKey = CFSTR("HashAlgorithm"); -const CFStringRef kSecCTExceptionsSPKIHashKey = CFSTR("SubjectPublicKeyInfoHash"); +const CFStringRef kSecCTExceptionsHashAlgorithmKey = kSecTrustStoreHashAlgorithmKey; +const CFStringRef kSecCTExceptionsSPKIHashKey = kSecTrustStoreSPKIHashKey; bool SecTrustStoreSetCTExceptions(CFStringRef applicationIdentifier, CFDictionaryRef exceptions, CFErrorRef *error) { #if !TARGET_OS_BRIDGE @@ -404,3 +407,129 @@ CFDictionaryRef SecTrustStoreCopyCTExceptions(CFStringRef applicationIdentifier, return NULL; #endif // TARGET_OS_BRIDGE } + +/* MARK: CA Revocation Additions */ + +/* Specify explicit additions to the list of known CAs for which revocation will be checked. + * Input: dictionary with following key and value: + * Key = kSecCARevocationAdditionsKey; Value = Array of dictionaries + * For revocation checking to be enabled for certificates issued by a CA, the CA must be specified as a + * dictionary entry containing the hash of the subjectPublicKeyInfo that appears in the CA certificate: + * Key = kSecCARevocationHashAlgorithmKey; Value = String. Currently, must be ”sha256”. + * Key = kSecCARevocationSPKIHashKey; Value = Data. Created by applying the specified hash algorithm + * to the DER encoding of the certificate's subjectPublicKeyInfo. +*/ + +const CFStringRef kSecCARevocationAdditionsKey = CFSTR("EnabledForCAs"); +const CFStringRef kSecCARevocationHashAlgorithmKey = kSecTrustStoreHashAlgorithmKey; +const CFStringRef kSecCARevocationSPKIHashKey = kSecTrustStoreSPKIHashKey; + +bool SecTrustStoreSetCARevocationAdditions(CFStringRef applicationIdentifier, CFDictionaryRef additions, CFErrorRef *error) { +#if !TARGET_OS_BRIDGE + if (applicationIdentifier && gTrustd && gTrustd->sec_trust_store_set_ca_revocation_additions) { + return gTrustd->sec_trust_store_set_ca_revocation_additions(applicationIdentifier, additions, error); + } else if (gTrustd && gTrustd->sec_trust_store_set_ca_revocation_additions) { + /* When calling from the TrustTests, we need to pass the appID for the tests. Ordinarily, + * this is done by trustd using the client's entitlements. */ + return gTrustd->sec_trust_store_set_ca_revocation_additions(CFSTR("com.apple.trusttests"), additions, error); + } + + os_activity_t activity = os_activity_create("SecTrustStoreSetCARevocationAdditions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_scope(activity); + + __block bool result = false; + securityd_send_sync_and_do(kSecXPCOpSetCARevocationAdditions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) { + SecXPCDictionarySetPListOptional(message, kSecTrustRevocationAdditionsKey, additions, block_error); + SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error); + return true; + }, ^bool(xpc_object_t response, CFErrorRef *block_error) { + result = SecXPCDictionaryGetBool(response, kSecXPCKeyResult, block_error); + return true; + }); + + os_release(activity); + return result; +#else // TARGET_OS_BRIDGE + return SecError(errSecReadOnly, error, CFSTR("SecTrustStoreSetCARevocationAdditions not supported on bridgeOS")); +#endif // TARGET_OS_BRIDGE +} + +CFDictionaryRef SecTrustStoreCopyCARevocationAdditions(CFStringRef applicationIdentifier, CFErrorRef *error) { +#if !TARGET_OS_BRIDGE + do_if_registered(sec_trust_store_copy_ca_revocation_additions, applicationIdentifier, error); + + os_activity_t activity = os_activity_create("SecTrustStoreCopyCARevocationAdditions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_scope(activity); + + __block CFDictionaryRef result = NULL; + securityd_send_sync_and_do(kSecXPCOpCopyCARevocationAdditions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) { + SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error); + return true; + }, ^bool(xpc_object_t response, CFErrorRef *block_error) { + (void)SecXPCDictionaryCopyDictionaryOptional(response, kSecTrustRevocationAdditionsKey, &result, block_error); + return true; + }); + + os_release(activity); + return result; +#else // TARGET_OS_BRIDGE + SecError(errSecReadOnly, error, CFSTR("SecTrustStoreCopyCARevocationAdditions not supported on bridgeOS")); + return NULL; +#endif // TARGET_OS_BRIDGE +} + +/* MARK: Transparent Connection Pins */ + +bool SecTrustStoreSetTransparentConnectionPins(CFStringRef applicationIdentifier, CFArrayRef pins, CFErrorRef *error) { +#if !TARGET_OS_BRIDGE + if (applicationIdentifier && gTrustd && gTrustd->sec_trust_store_set_transparent_connection_pins) { + return gTrustd->sec_trust_store_set_transparent_connection_pins(applicationIdentifier, pins, error); + } else if (gTrustd && gTrustd->sec_trust_store_set_transparent_connection_pins) { + /* When calling from the TrustTests, we need to pass the appID for the tests. Ordinarily, + * this is done by trustd using the client's entitlements. */ + return gTrustd->sec_trust_store_set_transparent_connection_pins(CFSTR("com.apple.trusttests"), pins, error); + } + + os_activity_t activity = os_activity_create("SecTrustStoreSetTransparentConnectionPins", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_scope(activity); + + __block bool result = false; + securityd_send_sync_and_do(kSecXPCOpSetTransparentConnectionPins, error, ^bool(xpc_object_t message, CFErrorRef *block_error) { + SecXPCDictionarySetPListOptional(message, kSecTrustAnchorsKey, pins, block_error); + SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error); + return true; + }, ^bool(xpc_object_t response, CFErrorRef *block_error) { + result = SecXPCDictionaryGetBool(response, kSecXPCKeyResult, block_error); + return true; + }); + + os_release(activity); + return result; +#else // TARGET_OS_BRIDGE + return SecError(errSecReadOnly, error, CFSTR("SecTrustStoreSetTransparentConnectionPins not supported on bridgeOS")); +#endif // TARGET_OS_BRIDGE +} + +CF_RETURNS_RETAINED CFArrayRef SecTrustStoreCopyTransparentConnectionPins(CFStringRef applicationIdentifier, CFErrorRef *error) { +#if !TARGET_OS_BRIDGE + do_if_registered(sec_trust_store_copy_transparent_connection_pins, applicationIdentifier, error); + + os_activity_t activity = os_activity_create("SecTrustStoreCopyTransparentConnectionPins", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_scope(activity); + + __block CFArrayRef result = NULL; + securityd_send_sync_and_do(kSecXPCOpCopyTransparentConnectionPins, error, ^bool(xpc_object_t message, CFErrorRef *block_error) { + SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error); + return true; + }, ^bool(xpc_object_t response, CFErrorRef *block_error) { + (void)SecXPCDictionaryCopyArrayOptional(response, kSecTrustAnchorsKey, &result, block_error); + return true; + }); + + os_release(activity); + return result; +#else // TARGET_OS_BRIDGE + SecError(errSecReadOnly, error, CFSTR("SecTrustStoreCopyTransparentConnectionPins not supported on bridgeOS")); + return NULL; +#endif // TARGET_OS_BRIDGE +} diff --git a/OSX/sec/Security/SecTrustStore.h b/OSX/sec/Security/SecTrustStore.h index 1458137b..58a049c7 100644 --- a/OSX/sec/Security/SecTrustStore.h +++ b/OSX/sec/Security/SecTrustStore.h @@ -39,6 +39,7 @@ typedef struct __SecTrustStore *SecTrustStoreRef; enum { kSecTrustStoreDomainSystem = 1, kSecTrustStoreDomainUser = 2, + kSecTrustStoreDomainAdmin = 3, }; typedef uint32_t SecTrustStoreDomain; diff --git a/OSX/sec/Security/SecuritydXPC.c b/OSX/sec/Security/SecuritydXPC.c index 696d1f2c..ff7d5d0f 100644 --- a/OSX/sec/Security/SecuritydXPC.c +++ b/OSX/sec/Security/SecuritydXPC.c @@ -101,8 +101,6 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("OTASecExperimentGetAsset"); case kSecXPCOpAcceptApplicants: return CFSTR("AcceptApplicants"); - case kSecXPCOpApplyToARing: - return CFSTR("ApplyToARing"); case kSecXPCOpBailFromCircle: return CFSTR("BailFromCircle"); case kSecXPCOpCanAuthenticate: @@ -115,8 +113,6 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("CopyEngineState"); case kSecXPCOpCopyGenerationPeerInfo: return CFSTR("CopyGenerationPeerInfo"); - case kSecXPCOpCopyIncompatibilityInfo: - return CFSTR("CopyIncompatibilityInfo"); case kSecXPCOpCopyMyPeerInfo: return CFSTR("CopyMyPeerInfo"); case kSecXPCOpCopyNotValidPeerPeerInfo: @@ -131,10 +127,6 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("CopyViewUnawarePeerInfo"); case kSecXPCOpDeviceInCircle: return CFSTR("DeviceInCircle"); - case kSecXPCOpEnableRing: - return CFSTR("EnableRing"); - case kSecXPCOpGetAllTheRings: - return CFSTR("GetAllTheRings"); case kSecXPCOpGetLastDepartureReason: return CFSTR("GetLastDepartureReason"); case kSecXPCOpLoggedOutOfAccount: @@ -151,30 +143,16 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("RejectApplicants"); case kSecXPCOpRemoveThisDeviceFromCircle: return CFSTR("RemoveThisDeviceFromCircle"); - case kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics: - return CFSTR("RemoveThisDeviceFromCircleWithAnalytics"); case kSecXPCOpRemovePeersFromCircle: return CFSTR("RemovePeersFromCircle"); - case kSecXPCOpRemovePeersFromCircleWithAnalytics: - return CFSTR("RemovePeersFromCircleWithAnalytics"); - case kSecXPCOpRequestEnsureFreshParameters: - return CFSTR("RequestEnsureFreshParameters"); case kSecXPCOpRequestToJoin: return CFSTR("RequestToJoin"); - case kSecXPCOpRequestToJoinWithAnalytics: - return CFSTR("RequestToJoinWithAnalytics"); case kSecXPCOpRequestToJoinAfterRestore: return CFSTR("RequestToJoinAfterRestore"); - case kSecXPCOpRequestToJoinAfterRestoreWithAnalytics: - return CFSTR("RequestToJoinAfterRestoreWithAnalytics"); case kSecXPCOpResetToEmpty: return CFSTR("ResetToEmpty"); - case kSecXPCOpResetToEmptyWithAnalytics: - return CFSTR("ResetToEmptyWithAnalytics"); case kSecXPCOpResetToOffering: return CFSTR("ResetToOffering"); - case kSecXPCOpRingStatus: - return CFSTR("RingStatus"); case kSecXPCOpRollKeys: return CFSTR("RollKeys"); case kSecXPCOpSetBagForAllSlices: @@ -187,16 +165,12 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("SetUserCredentials"); case kSecXPCOpSetUserCredentialsAndDSID: return CFSTR("SetUserCredentialsAndDSID"); - case kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics: - return CFSTR("SetUserCredentialsAndDSIDWithAnalytics"); case kSecXPCOpTryUserCredentials: return CFSTR("TryUserCredentials"); case kSecXPCOpValidateUserPublic: return CFSTR("ValidateUserPublic"); case kSecXPCOpView: return CFSTR("View"); - case kSecXPCOpWithdrawlFromARing: - return CFSTR("WithdrawlFromARing"); case sec_add_shared_web_credential_id: return CFSTR("add_shared_web_credential"); case sec_copy_shared_web_credential_id: @@ -209,6 +183,8 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("add"); case sec_item_backup_copy_names_id: return CFSTR("backup_copy_names"); + case sec_item_backup_ensure_copy_view_id: + return CFSTR("backup_register_view"); case sec_item_backup_handoff_fd_id: return CFSTR("backup_handoff_fd"); case sec_item_backup_restore_id: @@ -259,25 +235,11 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("ocsp_cache_flush"); case soscc_EnsurePeerRegistration_id: return CFSTR("EnsurePeerRegistration"); - case kSecXPCOpSetEscrowRecord: - return CFSTR("SetEscrowRecord"); - case kSecXPCOpGetEscrowRecord: - return CFSTR("GetEscrowRecord"); case kSecXPCOpWhoAmI: return CFSTR("WhoAmI"); case kSecXPCOpTransmogrifyToSyncBubble: return CFSTR("TransmogrifyToSyncBubble"); - case kSecXPCOpWrapToBackupSliceKeyBagForView: - return CFSTR("WrapToBackupSliceKeyBagForView"); - case kSecXPCOpCopyAccountData: - return CFSTR("CopyAccountDataFromKeychain"); - case kSecXPCOpDeleteAccountData: - return CFSTR("DeleteAccountDataFromKeychain"); - case kSecXPCOpCopyEngineData: - return CFSTR("CopyEngineDataFromKeychain"); - case kSecXPCOpDeleteEngineData: - return CFSTR("DeleteEngineDataFromKeychain"); - case sec_item_update_token_items_id: + case sec_item_update_token_items_for_access_groups_id: return CFSTR("UpdateTokenItems"); case sec_delete_items_with_access_groups_id: return CFSTR("sec_delete_items_with_access_groups_id"); @@ -287,8 +249,6 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("RegisterRecoveryPublicKey"); case kSecXPCOpGetRecoveryPublicKey: return CFSTR("GetRecoveryPublicKey"); - case kSecXPCOpCopyBackupInformation: - return CFSTR("CopyBackupInformation"); case kSecXPCOpMessageFromPeerIsPending: return CFSTR("MessageFromPeerIsPending"); case kSecXPCOpSendToPeerIsPending: @@ -313,22 +273,38 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("GetExceptionResetCount"); case sec_trust_increment_exception_reset_count_id: return CFSTR("IncrementExceptionResetCount"); + case kSecXPCOpSetCARevocationAdditions: + return CFSTR("SetCARevocationAdditions"); + case kSecXPCOpCopyCARevocationAdditions: + return CFSTR("CopyCARevocationAdditions"); + case kSecXPCOpValidUpdate: + return CFSTR("ValidUpdate"); + case kSecXPCOpSetTransparentConnectionPins: + return CFSTR("SetTransparentConnectionPins"); + case kSecXPCOpCopyTransparentConnectionPins: + return CFSTR("CopyTransparentConnectionPins"); default: return CFSTR("Unknown xpc operation"); } } bool SecXPCDictionarySetPList(xpc_object_t message, const char *key, CFTypeRef object, CFErrorRef *error) +{ + return SecXPCDictionarySetPListWithRepair(message, key, object, false, error); +} + +bool SecXPCDictionarySetPListWithRepair(xpc_object_t message, const char *key, CFTypeRef object, bool repair, CFErrorRef *error) { if (!object) return SecError(errSecParam, error, CFSTR("object for key %s is NULL"), key); size_t size = der_sizeof_plist(object, error); - if (!size) + if (!size) { return false; + } uint8_t *der = malloc(size); uint8_t *der_end = der + size; - uint8_t *der_start = der_encode_plist(object, error, der, der_end); + uint8_t *der_start = der_encode_plist_repair(object, error, repair, der, der_end); if (!der_start) { free(der); return false; @@ -522,10 +498,16 @@ CFTypeRef SecXPCDictionaryCopyPList(xpc_object_t message, const char *key, CFErr const uint8_t *der_end = der + size; /* use the sensitive allocator so that the dictionary is zeroized upon deallocation */ - const uint8_t *decode_end = der_decode_plist(SecCFAllocatorZeroize(), kCFPropertyListImmutable, + const uint8_t *decode_end = der_decode_plist(SecCFAllocatorZeroize(), &cfobject, error, der, der_end); if (decode_end != der_end) { - SecError(errSecParam, error, CFSTR("trailing garbage after der decoded object for key %s"), key); + CFStringRef description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("trailing garbage after der decoded object for key %s"), key); + SecError(errSecParam, error, CFSTR("%@"), description); + if (error) { // The no-error case is handled in SecError directly + secerror("xpc: %@", *error); + } + __security_simulatecrash(description, __sec_exception_code_CorruptItem); + CFReleaseNull(description); CFReleaseNull(cfobject); } diff --git a/OSX/sec/Security/SecuritydXPC.h b/OSX/sec/Security/SecuritydXPC.h index da93c9fa..92d6df73 100644 --- a/OSX/sec/Security/SecuritydXPC.h +++ b/OSX/sec/Security/SecuritydXPC.h @@ -35,6 +35,7 @@ bool SecXPCDictionarySetDataOptional(xpc_object_t message, const char *key, CFDa bool SecXPCDictionarySetBool(xpc_object_t message, const char *key, bool value, CFErrorRef *error); bool SecXPCDictionarySetPList(xpc_object_t message, const char *key, CFTypeRef object, CFErrorRef *error); +bool SecXPCDictionarySetPListWithRepair(xpc_object_t message, const char *key, CFTypeRef object, bool repair, CFErrorRef *error); bool SecXPCDictionarySetPListOptional(xpc_object_t message, const char *key, CFTypeRef object, CFErrorRef *error); bool SecXPCDictionarySetString(xpc_object_t message, const char *key, CFStringRef string, CFErrorRef *error); diff --git a/OSX/sec/Security/ios_tapi_hacks.h b/OSX/sec/Security/ios_tapi_hacks.h index 92e3c930..e068beeb 100644 --- a/OSX/sec/Security/ios_tapi_hacks.h +++ b/OSX/sec/Security/ios_tapi_hacks.h @@ -76,6 +76,9 @@ bool securityd_message_no_error(xpc_object_t message, CFErrorRef *error); void SecAccessGroupsSetCurrent(CFArrayRef accessGroups); CFArrayRef SecAccessGroupsGetCurrent(void); +void SecSecurityClientRegularToAppClip(void); +void SecSecurityClientAppClipToRegular(void); +void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier); #include extern os_log_t secLogObjForScope(const char *scope); diff --git a/OSX/sec/Security/p12pbegen.c b/OSX/sec/Security/p12pbegen.c index 17abc062..3f33e888 100644 --- a/OSX/sec/Security/p12pbegen.c +++ b/OSX/sec/Security/p12pbegen.c @@ -31,6 +31,8 @@ #include "p12pbegen.h" +#include + static uint8_t *concatenate_to_blocksize(const uint8_t *data, size_t data_length, size_t blocksize, size_t *blocklength) { diff --git a/OSX/sec/SharedWebCredential/swcagent.m b/OSX/sec/SharedWebCredential/swcagent.m index 6c873d22..bdf13306 100644 --- a/OSX/sec/SharedWebCredential/swcagent.m +++ b/OSX/sec/SharedWebCredential/swcagent.m @@ -47,7 +47,7 @@ #include #endif -#if TARGET_OS_IPHONE && !TARGET_OS_WATCH +#if TARGET_OS_IPHONE && !TARGET_OS_WATCH && !TARGET_OS_TV #include #include @@ -85,7 +85,7 @@ typedef WBSAutoFillDataClasses (*WBUAutoFillGetEnabledDataClasses_f)(void); #import #import #import -#import +#import #endif static NSString *swca_string_table = @"SharedWebCredentials"; diff --git a/OSX/sec/ipc/SecdWatchdog.m b/OSX/sec/ipc/SecdWatchdog.m index 68863de2..56fba152 100644 --- a/OSX/sec/ipc/SecdWatchdog.m +++ b/OSX/sec/ipc/SecdWatchdog.m @@ -21,7 +21,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#import "SecdWatchdog.h" +#import "ipc/SecdWatchdog.h" #include "utilities/debugging.h" #include #import diff --git a/OSX/sec/ipc/client.c b/OSX/sec/ipc/client.c index 5dd78112..4ff36ed9 100644 --- a/OSX/sec/ipc/client.c +++ b/OSX/sec/ipc/client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2009,2012-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2012-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -69,27 +70,33 @@ struct trustd *gTrustd; /* Hardcoded Access Groups for the server itself */ static CFArrayRef SecServerCopyAccessGroups(void) { - return CFArrayCreateForCFTypes(kCFAllocatorDefault, + CFArrayRef accessGroups = CFArrayCreateForCFTypes(kCFAllocatorDefault, #if NO_SERVER - CFSTR("test"), - CFSTR("apple"), - CFSTR("lockdown-identities"), - CFSTR("123456.test.group"), - CFSTR("123456.test.group2"), - CFSTR("com.apple.cfnetwork"), - CFSTR("com.apple.bluetooth"), + CFSTR("test"), + CFSTR("apple"), + CFSTR("lockdown-identities"), + CFSTR("123456.test.group"), + CFSTR("123456.test.group2"), + CFSTR("com.apple.cfnetwork"), + CFSTR("com.apple.bluetooth"), #endif - CFSTR("sync"), - CFSTR("com.apple.security.sos"), - CFSTR("com.apple.security.ckks"), - CFSTR("com.apple.security.octagon"), - CFSTR("com.apple.security.egoIdentities"), - CFSTR("com.apple.security.sos-usercredential"), - CFSTR("com.apple.sbd"), - CFSTR("com.apple.lakitu"), - CFSTR("com.apple.security.securityd"), - kSecAttrAccessGroupToken, - NULL); + CFSTR("sync"), + CFSTR("com.apple.security.sos"), + CFSTR("com.apple.security.ckks"), + CFSTR("com.apple.security.octagon"), + CFSTR("com.apple.security.egoIdentities"), + CFSTR("com.apple.security.sos-usercredential"), + CFSTR("com.apple.sbd"), + CFSTR("com.apple.lakitu"), + CFSTR("com.apple.security.securityd"), + NULL); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + CFMutableArrayRef mutableGroups = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, accessGroups); + CFArrayAppendValue(mutableGroups, kSecAttrAccessGroupToken); + CFAssignRetained(accessGroups, mutableGroups); + } + + return accessGroups; } static SecurityClient gClient; @@ -137,6 +144,8 @@ SecSecurityClientGet(void) gClient.activeUser = 501; gClient.musr = NULL; #endif + gClient.applicationIdentifier = NULL; + gClient.isAppClip = false; }); return &gClient; } @@ -150,8 +159,30 @@ CFArrayRef SecAccessGroupsGetCurrent(void) { // Only for testing. void SecAccessGroupsSetCurrent(CFArrayRef accessGroups) { // Not thread safe at all, but OK because it is meant to be used only by tests. - CFReleaseNull(gClient.accessGroups); - gClient.accessGroups = CFRetainSafe(accessGroups); + SecurityClient* client = SecSecurityClientGet(); + CFReleaseNull(client->accessGroups); + client->accessGroups = CFRetainSafe(accessGroups); +} + +// Testing +void SecSecurityClientRegularToAppClip(void) { + SecurityClient* client = SecSecurityClientGet(); + client->isAppClip = true; +} + +// Testing +void SecSecurityClientAppClipToRegular(void) { + SecurityClient* client = SecSecurityClientGet(); + client->isAppClip = false; +} + +// Testing +void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier) { + SecurityClient* client = SecSecurityClientGet(); + CFReleaseNull(client->applicationIdentifier); + if (identifier) { + client->applicationIdentifier = CFRetain(identifier); + } } #if !TARGET_OS_IPHONE @@ -227,6 +258,11 @@ static bool is_trust_operation(enum SecXPCOperation op) { case kSecXPCOpCopyCTExceptions: case sec_trust_get_exception_reset_count_id: case sec_trust_increment_exception_reset_count_id: + case kSecXPCOpSetCARevocationAdditions: + case kSecXPCOpCopyCARevocationAdditions: + case kSecXPCOpValidUpdate: + case kSecXPCOpSetTransparentConnectionPins: + case kSecXPCOpCopyTransparentConnectionPins: return true; default: break; diff --git a/OSX/sec/ipc/client_endpoint.m b/OSX/sec/ipc/client_endpoint.m index b9957cc7..e9d8975c 100644 --- a/OSX/sec/ipc/client_endpoint.m +++ b/OSX/sec/ipc/client_endpoint.m @@ -26,6 +26,7 @@ #import #import #import +#import #include @@ -59,37 +60,7 @@ ofReply:0]; #if OCTAGON - static NSMutableSet *errClasses; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - // By finding classes by strings at runtime, we'll only get the CloudKit helpers if you link CloudKit - // Plus, we don't have to weak-link cloudkit from Security.framework - - errClasses = [[NSMutableSet alloc] init]; - char *classes[] = { - "NSError", - "NSArray", - "NSString", - "NSNumber", - "NSData", - "NSDate", - "CKReference", - "CKAsset", - "CLLocation", - "CKPackage", - "CKArchivedAnchoredPackage", - "CKPrettyError", - "CKRecordID", - "NSURL", - }; - - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) { - [errClasses addObject:cls]; - } - } - }); + NSSet *errClasses = [SecXPCHelper safeErrorClasses]; @try { [rpcCallbackInterface setClasses:errClasses forSelector:@selector(callCallback:error:) argumentIndex:1 ofReply:NO]; @@ -97,14 +68,6 @@ [interface setClasses:errClasses forSelector:@selector(SecItemAddAndNotifyOnSync: syncCallback: complete:) argumentIndex:2 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(secItemFetchCurrentItemAcrossAllDevices: - identifier: - viewHint: - fetchCloudValue: - complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(secItemDigest: - accessGroup: - complete:) argumentIndex:1 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(secItemSetCurrentItemAcrossAllDevices: newCurrentItemHash: accessGroup: @@ -113,12 +76,21 @@ oldCurrentItemReference: oldCurrentItemHash: complete:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(secItemFetchCurrentItemAcrossAllDevices: + identifier: + viewHint: + fetchCloudValue: + complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(secItemDigest: + accessGroup: + complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(secKeychainDeleteMultiuser:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(secItemVerifyBackupIntegrity:completion:) argumentIndex:1 ofReply:YES]; + } @catch(NSException* e) { secerror("Could not configure SecuritydXPCProtocol: %@", e); -#if DEBUG @throw e; -#endif // DEBUG } #endif // OCTAGON } @@ -139,7 +111,7 @@ } @end -id SecuritydXPCProxyObject(void (^rpcErrorHandler)(NSError *)) +id SecuritydXPCProxyObject(bool synchronous, void (^rpcErrorHandler)(NSError *)) { if (gSecurityd && gSecurityd->secd_xpc_server) { return (__bridge id)gSecurityd->secd_xpc_server; @@ -156,7 +128,11 @@ id SecuritydXPCProxyObject(void (^rpcErrorHandler)(NSError rpcErrorHandler([NSError errorWithDomain:@"securityd" code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Could not create SecuritydXPCClient" }]); return NULL; } else { - return [rpc.connection remoteObjectProxyWithErrorHandler: rpcErrorHandler]; + if (synchronous) { + return [rpc.connection synchronousRemoteObjectProxyWithErrorHandler:rpcErrorHandler]; + } else { + return [rpc.connection remoteObjectProxyWithErrorHandler:rpcErrorHandler]; + } } } diff --git a/OSX/sec/ipc/com.apple.secd.plist b/OSX/sec/ipc/com.apple.secd.plist index 59392e17..3f2b01a0 100644 --- a/OSX/sec/ipc/com.apple.secd.plist +++ b/OSX/sec/ipc/com.apple.secd.plist @@ -55,6 +55,22 @@ Interval 86400 + com.apple.securityd.entropyhealth + + Priority + Utility + Interval + 86400 + + com.apple.securityd.prng + + Priority + Maintenance + Interval + 3600 + RequiresClassC + + diff --git a/OSX/sec/ipc/com.apple.securityd.plist b/OSX/sec/ipc/com.apple.securityd.plist index e75b5e1b..9fd326fa 100644 --- a/OSX/sec/ipc/com.apple.securityd.plist +++ b/OSX/sec/ipc/com.apple.securityd.plist @@ -67,6 +67,22 @@ NetworkTransferDirection Bidirectional + com.apple.securityd.entropyhealth + + Priority + Utility + Interval + 86400 + + com.apple.securityd.prng + + Priority + Maintenance + Interval + 3600 + RequiresClassC + + com.apple.notifyd.matching diff --git a/OSX/sec/ipc/securityd_client.h b/OSX/sec/ipc/securityd_client.h index afbd42d6..acab23a6 100644 --- a/OSX/sec/ipc/securityd_client.h +++ b/OSX/sec/ipc/securityd_client.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -182,6 +182,7 @@ enum SecXPCOperation { sec_keychain_backup_syncable_id, sec_keychain_restore_syncable_id, sec_item_backup_copy_names_id, + sec_item_backup_ensure_copy_view_id, sec_item_backup_handoff_fd_id, sec_item_backup_set_confirmed_manifest_id, sec_item_backup_restore_id, @@ -203,12 +204,6 @@ enum SecXPCOperation { sec_set_xpc_log_settings_id, sec_set_circle_log_settings_id, soscc_EnsurePeerRegistration_id, - kSecXPCOpRequestEnsureFreshParameters, - kSecXPCOpGetAllTheRings, - kSecXPCOpApplyToARing, - kSecXPCOpWithdrawlFromARing, - kSecXPCOpEnableRing, - kSecXPCOpRingStatus, kSecXPCOpRequestDeviceID, kSecXPCOpSetDeviceID, kSecXPCOpHandleIDSMessage, @@ -222,24 +217,18 @@ enum SecXPCOperation { kSecXPCOpTryUserCredentials, kSecXPCOpSetUserCredentials, kSecXPCOpSetUserCredentialsAndDSID, - kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics, kSecXPCOpCanAuthenticate, kSecXPCOpPurgeUserCredentials, kSecXPCOpDeviceInCircle, kSecXPCOpRequestToJoin, - kSecXPCOpRequestToJoinWithAnalytics, kSecXPCOpRequestToJoinAfterRestore, - kSecXPCOpRequestToJoinAfterRestoreWithAnalytics, kSecXPCOpResetToOffering, kSecXPCOpResetToEmpty, - kSecXPCOpResetToEmptyWithAnalytics, kSecXPCOpView, kSecXPCOpViewSet, - kSecXPCOpViewSetWithAnalytics, kSecXPCOpRemoveThisDeviceFromCircle, - kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics, kSecXPCOpRemovePeersFromCircle, - kSecXPCOpRemovePeersFromCircleWithAnalytics, + kSecXPCOpLoggedIntoAccount, kSecXPCOpLoggedOutOfAccount, kSecXPCOpBailFromCircle, kSecXPCOpAcceptApplicants, @@ -253,7 +242,6 @@ enum SecXPCOperation { kSecXPCOpCopyGenerationPeerInfo, kSecXPCOpGetLastDepartureReason, kSecXPCOpSetLastDepartureReason, - kSecXPCOpCopyIncompatibilityInfo, kSecXPCOpCopyRetirementPeerInfo, kSecXPCOpCopyViewUnawarePeerInfo, kSecXPCOpCopyEngineState, @@ -262,39 +250,26 @@ enum SecXPCOperation { kSecXPCOpSetNewPublicBackupKey, kSecXPCOpSetBagForAllSlices, kSecXPCOpWaitForInitialSync, - kSecXPCOpWaitForInitialSyncWithAnalytics, - kSecXPCOpCopyYetToSyncViews, - kSecXPCOpSetEscrowRecord, - kSecXPCOpGetEscrowRecord, kSecXPCOpCheckPeerAvailability, - kSecXPCOpCopyAccountData, - kSecXPCOpDeleteAccountData, - kSecXPCOpCopyEngineData, - kSecXPCOpDeleteEngineData, kSecXPCOpCopyApplication, kSecXPCOpCopyCircleJoiningBlob, kSecXPCOpJoinWithCircleJoiningBlob, kSecXPCOpKVSKeyCleanup, - kSecXPCOpPopulateKVS, kSecXPCOpAccountHasPublicKey, - kSecXPCOpAccountIsNew, kSecXPCOpClearKVSPeerMessage, kSecXPCOpRegisterRecoveryPublicKey, kSecXPCOpGetRecoveryPublicKey, - kSecXPCOpCopyBackupInformation, kSecXPCOpCopyInitialSyncBlob, /* after this is free for all */ kSecXPCOpWhoAmI, kSecXPCOpTransmogrifyToSyncBubble, kSecXPCOpTransmogrifyToSystemKeychain, - kSecXPCOpWrapToBackupSliceKeyBagForView, - sec_item_update_token_items_id, + sec_item_update_token_items_for_access_groups_id, kSecXPCOpDeleteUserView, sec_trust_store_copy_all_id, sec_trust_store_copy_usage_constraints_id, sec_ocsp_cache_flush_id, sec_delete_items_with_access_groups_id, - kSecXPCOpIsThisDeviceLastBackup, sec_keychain_backup_keybag_uuid_id, kSecXPCOpPeersHaveViewsEnabled, kSecXPCOpProcessSyncWithPeers, @@ -313,6 +288,11 @@ enum SecXPCOperation { kSecXPCOpOTASecExperimentGetNewAsset, sec_trust_get_exception_reset_count_id, sec_trust_increment_exception_reset_count_id, + kSecXPCOpSetCARevocationAdditions, + kSecXPCOpCopyCARevocationAdditions, + kSecXPCOpValidUpdate, + kSecXPCOpSetTransparentConnectionPins, + kSecXPCOpCopyTransparentConnectionPins }; @@ -332,6 +312,8 @@ typedef struct SecurityClient { bool inMultiUser; int activeUser; #endif + bool isAppClip; + CFStringRef applicationIdentifier; } SecurityClient; @@ -353,7 +335,7 @@ struct securityd { CFDataRef (*sec_keychain_backup)(SecurityClient *client, CFDataRef keybag, CFDataRef passcode, bool emcs, CFErrorRef* error); bool (*sec_keychain_restore)(CFDataRef backup, SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); bool (*sec_roll_keys)(bool force, CFErrorRef* error); - bool (*sec_item_update_token_items)(CFStringRef tokenID, CFArrayRef query, SecurityClient *client, CFErrorRef* error); + bool (*sec_item_update_token_items_for_access_groups)(CFStringRef tokenID, CFArrayRef accessGroups, CFArrayRef tokenItems, SecurityClient *client, CFErrorRef* error); bool (*sec_delete_items_with_access_groups)(CFArrayRef bundleIDs, SecurityClient *client, CFErrorRef *error); /* SHAREDWEBCREDENTIALS */ bool (*sec_add_shared_web_credential)(CFDictionaryRef attributes, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); @@ -362,6 +344,7 @@ struct securityd { CFDictionaryRef (*sec_keychain_backup_syncable)(CFDictionaryRef backup_in, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); bool (*sec_keychain_restore_syncable)(CFDictionaryRef backup, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); CFArrayRef (*sec_item_backup_copy_names)(CFErrorRef *error); + CFStringRef (*sec_item_backup_ensure_copy_view)(CFStringRef viewName, CFErrorRef *error); int (*sec_item_backup_handoff_fd)(CFStringRef backupName, CFErrorRef *error); bool (*sec_item_backup_set_confirmed_manifest)(CFStringRef backupName, CFDataRef keybagDigest, CFDataRef manifest, CFErrorRef *error); bool (*sec_item_backup_restore)(CFStringRef backupName, CFStringRef peerID, CFDataRef keybag, CFDataRef secret, CFDataRef backup, CFErrorRef *error); @@ -370,34 +353,22 @@ struct securityd { bool (*soscc_TryUserCredentials)(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); bool (*soscc_SetUserCredentials)(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); bool (*soscc_SetUserCredentialsAndDSID)(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); - bool (*soscc_SetUserCredentialsAndDSIDWithAnalytics)(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error); bool (*soscc_CanAuthenticate)(CFErrorRef *error); bool (*soscc_PurgeUserCredentials)(CFErrorRef *error); SOSCCStatus (*soscc_ThisDeviceIsInCircle)(CFErrorRef* error); bool (*soscc_RequestToJoinCircle)(CFErrorRef* error); - bool (*soscc_RequestToJoinCircleWithAnalytics)(CFDataRef parentEvent, CFErrorRef* error); bool (*soscc_RequestToJoinCircleAfterRestore)(CFErrorRef* error); - bool (*soscc_RequestToJoinCircleAfterRestoreWithAnalytics)(CFDataRef parentEvent, CFErrorRef* error); - bool (*soscc_RequestEnsureFreshParameters)(CFErrorRef* error); - CFStringRef (*soscc_GetAllTheRings)(CFErrorRef *error); - bool (*soscc_ApplyToARing)(CFStringRef ringName, CFErrorRef* error); - bool (*soscc_WithdrawlFromARing)(CFStringRef ringName, CFErrorRef* error); - bool (*soscc_EnableRing)(CFStringRef ringName, CFErrorRef* error); - SOSRingStatus (*soscc_RingStatus)(CFStringRef ringName, CFErrorRef* error); bool (*soscc_SetToNew)(CFErrorRef *error); bool (*soscc_ResetToOffering)(CFErrorRef* error); bool (*soscc_ResetToEmpty)(CFErrorRef* error); - bool (*soscc_ResetToEmptyWithAnalytics)(CFDataRef parentEvent, CFErrorRef* error); SOSViewResultCode (*soscc_View)(CFStringRef view, SOSViewActionCode action, CFErrorRef *error); bool (*soscc_ViewSet)(CFSetRef enabledViews, CFSetRef disabledViews); - bool (*soscc_ViewSetWithAnalytics)(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent); bool (*soscc_RegisterSingleRecoverySecret)(CFDataRef backupSlice, bool forV0Only, CFErrorRef *error); bool (*soscc_RegisterRecoveryPublicKey)(CFDataRef recovery_key, CFErrorRef *error); CFDataRef (*soscc_CopyRecoveryPublicKey)(CFErrorRef *error); bool (*soscc_RemoveThisDeviceFromCircle)(CFErrorRef* error); - bool (*soscc_RemoveThisDeviceFromCircleWithAnalytics)(CFDataRef parentEvent, CFErrorRef* error); bool (*soscc_RemovePeersFromCircle)(CFArrayRef peers, CFErrorRef* error); - bool (*soscc_RemovePeersFromCircleWithAnalytics)(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error); + bool (*soscc_LoggedIntoAccount)(CFErrorRef* error); bool (*soscc_LoggedOutOfAccount)(CFErrorRef* error); bool (*soscc_BailFromCircle)(uint64_t limit_in_seconds, CFErrorRef* error); bool (*soscc_AcceptApplicants)(CFArrayRef applicants, CFErrorRef* error); @@ -414,7 +385,6 @@ struct securityd { // Not sure why these are below the last entry in the enum order above, but they are: CFArrayRef (*soscc_CopyPeerInfo)(CFErrorRef* error); CFArrayRef (*soscc_CopyConcurringPeerInfo)(CFErrorRef* error); - CFStringRef (*soscc_CopyIncompatibilityInfo)(CFErrorRef* error); enum DepartureReason (*soscc_GetLastDepartureReason)(CFErrorRef* error); bool (*soscc_SetLastDepartureReason)(enum DepartureReason, CFErrorRef* error); CFSetRef (*soscc_ProcessSyncWithPeers)(CFSetRef peerIDs, CFSetRef backupPeerIDs, CFErrorRef* error); @@ -426,26 +396,13 @@ struct securityd { bool (*sec_set_circle_log_settings)(CFTypeRef type, CFErrorRef* error); SOSPeerInfoRef (*soscc_CopyMyPeerInfo)(CFErrorRef*); bool (*soscc_WaitForInitialSync)(CFErrorRef*); - bool (*soscc_WaitForInitialSyncWithAnalytics)(CFDataRef parentEvent, CFErrorRef *error); - CFArrayRef (*soscc_CopyYetToSyncViewsList)(CFErrorRef*); - bool (*soscc_SetEscrowRecords)(CFStringRef escrow_label, uint64_t tries, CFErrorRef *error); - CFDictionaryRef (*soscc_CopyEscrowRecords)(CFErrorRef *error); - CFDictionaryRef (*soscc_CopyBackupInformation)(CFErrorRef *error); bool (*soscc_PeerAvailability)(CFErrorRef *error); - bool (*sosbskb_WrapToBackupSliceKeyBagForView)(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error); - CFDataRef (*soscc_CopyAccountState)(CFErrorRef *error); - bool (*soscc_DeleteAccountState)(CFErrorRef *error); - CFDataRef (*soscc_CopyEngineData)(CFErrorRef *error); - bool (*soscc_DeleteEngineState)(CFErrorRef *error); SOSPeerInfoRef (*soscc_CopyApplicant)(CFErrorRef *error); CFDataRef (*soscc_CopyCircleJoiningBlob)(SOSPeerInfoRef applicant, CFErrorRef *error); CFDataRef (*soscc_CopyInitialSyncData)(SOSInitialSyncFlags flags, CFErrorRef *error); bool (*soscc_JoinWithCircleJoiningBlob)(CFDataRef joiningBlob, PiggyBackProtocolVersion version, CFErrorRef *error); bool (*soscc_SOSCCCleanupKVSKeys)(CFErrorRef *error); - bool (*soscc_SOSCCTestPopulateKVSWithBadKeys)(CFErrorRef *error); bool (*soscc_AccountHasPublicKey)(CFErrorRef *error); - bool (*soscc_AccountIsNew)(CFErrorRef *error); - bool (*soscc_IsThisDeviceLastBackup)(CFErrorRef *error); bool (*soscc_requestSyncWithPeerOverKVS)(CFStringRef peerID, CFDataRef message, CFErrorRef *error); CFBooleanRef (*soscc_SOSCCPeersHaveViewsEnabled)(CFArrayRef views, CFErrorRef *error); bool (*socc_clearPeerMessageKeyInKVS)(CFStringRef peerID, CFErrorRef *error); @@ -460,9 +417,9 @@ extern struct securityd *gSecurityd; struct trustd { SecTrustStoreRef (*sec_trust_store_for_domain)(CFStringRef domainName, CFErrorRef* error); - bool (*sec_trust_store_contains)(SecTrustStoreRef ts, CFDataRef digest, bool *contains, CFErrorRef* error); + bool (*sec_trust_store_contains)(SecTrustStoreRef ts, SecCertificateRef certificate, bool *contains, CFErrorRef* error); bool (*sec_trust_store_set_trust_settings)(SecTrustStoreRef ts, SecCertificateRef certificate, CFTypeRef trustSettingsDictOrArray, CFErrorRef* error); - bool (*sec_trust_store_remove_certificate)(SecTrustStoreRef ts, CFDataRef digest, CFErrorRef* error); + bool (*sec_trust_store_remove_certificate)(SecTrustStoreRef ts, SecCertificateRef certificate, CFErrorRef* error); bool (*sec_truststore_remove_all)(SecTrustStoreRef ts, CFErrorRef* error); SecTrustResultType (*sec_trust_evaluate)(CFArrayRef certificates, CFArrayRef anchors, bool anchorsOnly, bool keychainsAllowed, CFArrayRef policies, CFArrayRef responses, CFArrayRef SCTs, CFArrayRef trustedLogs, CFAbsoluteTime verifyTime, __unused CFArrayRef accessGroups, CFArrayRef exceptions, CFArrayRef *details, CFDictionaryRef *info, CFArrayRef *chain, CFErrorRef *error); uint64_t (*sec_ota_pki_trust_store_version)(CFErrorRef* error); @@ -474,15 +431,18 @@ struct trustd { CFDictionaryRef (*sec_ota_pki_copy_trusted_ct_logs)(CFErrorRef *error); CFDictionaryRef (*sec_ota_pki_copy_ct_log_for_keyid)(CFDataRef keyID, CFErrorRef *error); bool (*sec_trust_store_copy_all)(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error); - bool (*sec_trust_store_copy_usage_constraints)(SecTrustStoreRef ts, CFDataRef digest, CFArrayRef *usageConstraints, CFErrorRef *error); + bool (*sec_trust_store_copy_usage_constraints)(SecTrustStoreRef ts, SecCertificateRef certificate, CFArrayRef *usageConstraints, CFErrorRef *error); bool (*sec_ocsp_cache_flush)(CFErrorRef *error); bool (*sec_networking_analytics_report)(CFStringRef event_name, xpc_object_t tls_analytics_attributes, CFErrorRef *error); bool (*sec_trust_store_set_ct_exceptions)(CFStringRef appID, CFDictionaryRef exceptions, CFErrorRef *error); CFDictionaryRef (*sec_trust_store_copy_ct_exceptions)(CFStringRef appID, CFErrorRef *error); -#if TARGET_OS_IPHONE bool (*sec_trust_increment_exception_reset_count)(CFErrorRef *error); uint64_t (*sec_trust_get_exception_reset_count)(CFErrorRef *error); -#endif + bool (*sec_trust_store_set_ca_revocation_additions)(CFStringRef appID, CFDictionaryRef additions, CFErrorRef *error); + CFDictionaryRef (*sec_trust_store_copy_ca_revocation_additions)(CFStringRef appID, CFErrorRef *error); + bool (*sec_valid_update)(CFErrorRef *error); + bool (*sec_trust_store_set_transparent_connection_pins)(CFStringRef appID, CFArrayRef exceptions, CFErrorRef *error); + CFArrayRef (*sec_trust_store_copy_transparent_connection_pins)(CFStringRef appID, CFErrorRef *error); }; extern struct trustd *gTrustd; @@ -572,11 +532,19 @@ typedef void (^SecBoolNSErrorCallback) (bool, NSError*); - (void)secItemVerifyBackupIntegrity:(BOOL)lightweight completion:(void (^)(NSDictionary* resultsPerKeyclass, NSError* error))completion; +// Delete all items from the keychain where agrp==identifier and clip==1. Requires App Clip deletion entitlement. +- (void)secItemDeleteForAppClipApplicationIdentifier:(NSString*)identifier + completion:(void (^)(OSStatus status))completion; + +// Ask the keychain to durably persist its database to disk, at whatever guarantees the existing filesystem provides. +// On Apple hardware with an APFS-formatted physical disk, this should succeed. On any sort of network home folder, no guarantee is provided. +// This is an expensive operation. +- (void)secItemPersistKeychainWritesAtHighPerformanceCost:(void (^)(OSStatus status, NSError* error))completion; @end // Call this to receive a proxy object conforming to SecuritydXPCProtocol that you can call methods on. // It's probably a remote object for securityd/secd, but it might be in-process if you've configured it that way. -id SecuritydXPCProxyObject(void (^rpcErrorHandler)(NSError *)); +id SecuritydXPCProxyObject(bool synchronous, void (^rpcErrorHandler)(NSError *)); // Set up a local securityxpcserver: after this call, all securitydxpc calls will be handled in-process instead of actually transferring to securityd id SecCreateLocalSecuritydXPCServer(void) NS_RETURNS_RETAINED; diff --git a/OSX/sec/ipc/server.c b/OSX/sec/ipc/server.c index 917ac3e6..8460832c 100644 --- a/OSX/sec/ipc/server.c +++ b/OSX/sec/ipc/server.c @@ -21,7 +21,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#if TARGET_DARWINOS +#if defined(TARGET_DARWINOS) && TARGET_DARWINOS #undef OCTAGON #undef SECUREOBJECTSYNC #undef SHAREDWEBCREDENTIALS @@ -30,6 +30,7 @@ #include #include +#include #include "keychain/SecureObjectSync/SOSPeerInfoDER.h" #include #include @@ -58,8 +59,10 @@ #include "trust/trustd/SecTrustStoreServer.h" #include "keychain/securityd/iCloudTrace.h" #include "keychain/securityd/spi.h" +#include #include #include +#include #include #include #include @@ -118,6 +121,51 @@ #include "util.h" +static void refresh_prng(void) +{ + aks_ref_key_t ref = NULL; + + int fd = open("/dev/random", O_WRONLY); + if (fd == -1) { + secerror("failed to open /dev/random (%d)", errno); + goto out; + } + + /* create class F ref-key, and use its public key as an entropy source */ + int err = aks_ref_key_create(bad_keybag_handle, key_class_f, key_type_asym_ec_p256, NULL, 0, &ref); + if (err != kAKSReturnSuccess) { + secerror("failed to create refkey (%d)", err); + goto out; + } + + size_t pub_key_len = 0; + const uint8_t *pub_key = aks_ref_key_get_public_key(ref, &pub_key_len); + if (pub_key_len > ccec_export_pub_size_cp(ccec_cp_256())) { + secerror("invalid pub key (%zu)", pub_key_len); + goto out; + } + + while (pub_key_len > 0) { + ssize_t n = write(fd, pub_key, pub_key_len); + if (n == -1) { + secerror("failed to write /dev/random (%d)", errno); + goto out; + } + + pub_key += n; + pub_key_len -= n; + } + + out: + if (ref) { + aks_ref_key_free(&ref); + } + + if (fd >= 0) { + close(fd); + } +} + #if SECUREOBJECTSYNC CF_RETURNS_RETAINED @@ -191,7 +239,7 @@ static CFDataRef SecXPCDictionaryCopyCFDataRef(xpc_object_t message, const char CFDataRef retval = NULL; const uint8_t *bytes = NULL; size_t len = 0; - + bytes = xpc_dictionary_get_data(message, key, &len); require_action_quiet(bytes, errOut, SOSCreateError(kSOSErrorBadKey, CFSTR("missing CFDataRef info"), NULL, error)); retval = CFDataCreate(NULL, bytes, len); @@ -208,7 +256,7 @@ static CFSetRef CreateCFSetRefFromXPCObject(xpc_object_t xpcSetDER, CFErrorRef* const uint8_t* der = xpc_data_get_bytes_ptr(xpcSetDER); const uint8_t* der_end = der + xpc_data_get_length(xpcSetDER); - der = der_decode_set(kCFAllocatorDefault, kCFPropertyListMutableContainersAndLeaves, &retval, error, der, der_end); + der = der_decode_set(kCFAllocatorDefault, &retval, error, der, der_end); if (der != der_end) { SecError(errSecDecode, error, CFSTR("trailing garbage at end of SecAccessControl data")); goto errOut; @@ -341,6 +389,8 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, .allowSyncBubbleKeychain = false, .isNetworkExtension = false, .canAccessNetworkExtensionAccessGroups = false, + .applicationIdentifier = NULL, + .isAppClip = false, }; secdebug("serverxpc", "entering"); @@ -383,6 +433,16 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFDictionaryGetValue(query, kSecAttrPCSPlaintextPublicIdentity)) { entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateCKKSPlaintextFields, &error); } + if(entitlementsCorrect && + (CFDictionaryGetValue(query, kSecDataInetExtraNotes) || + CFDictionaryGetValue(query, kSecDataInetExtraHistory) || + CFDictionaryGetValue(query, kSecDataInetExtraClientDefined0) || + CFDictionaryGetValue(query, kSecDataInetExtraClientDefined1) || + CFDictionaryGetValue(query, kSecDataInetExtraClientDefined2) || + CFDictionaryGetValue(query, kSecDataInetExtraClientDefined3))) { + entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateInetExpansionFields, &error); + } + if (entitlementsCorrect && CFDictionaryGetValue(query, kSecAttrSysBound)) { entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateSysBound, &error); } @@ -406,7 +466,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, if (query) { CFTypeRef result = NULL; if (_SecItemCopyMatching(query, &client, &result, &error) && result) { - SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + SecXPCDictionarySetPListWithRepair(replyMessage, kSecXPCKeyResult, result, true, &error); CFReleaseNull(result); } CFReleaseNull(query); @@ -429,6 +489,15 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFDictionaryGetValue(attributesToUpdate, kSecAttrPCSPlaintextPublicIdentity)) { entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateCKKSPlaintextFields, &error); } + if(entitlementsCorrect && + (CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraNotes) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraHistory) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined0) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined1) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined2) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined3))) { + entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateInetExpansionFields, &error); + } if (entitlementsCorrect && CFDictionaryGetValue(query, kSecAttrSysBound)) { entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateSysBound, &error); } @@ -456,17 +525,20 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } break; } - case sec_item_update_token_items_id: + case sec_item_update_token_items_for_access_groups_id: { - if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) { + if (EntitlementAbsentOrFalse(sec_item_update_token_items_for_access_groups_id, client.task, kSecEntitlementKeychainDeny, &error) && + EntitlementPresentAndTrue(sec_item_update_token_items_for_access_groups_id, client.task, kSecEntitlementUpdateTokenItems, &error)) { CFStringRef tokenID = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error); - CFArrayRef attributes = SecXPCDictionaryCopyArray(event, kSecXPCKeyQuery, &error); + CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyArray, &error); + CFArrayRef tokenItems = SecXPCDictionaryCopyArray(event, kSecXPCKeyQuery, &error); if (tokenID) { - bool result = _SecItemUpdateTokenItems(tokenID, attributes, &client, &error); + bool result = _SecItemUpdateTokenItemsForAccessGroups(tokenID, accessGroups, tokenItems, &client, &error); xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); } CFReleaseNull(tokenID); - CFReleaseNull(attributes); + CFReleaseNull(accessGroups); + CFReleaseNull(tokenItems); } break; } @@ -642,6 +714,18 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } break; } + case sec_item_backup_ensure_copy_view_id: + { + if(EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) { + CFStringRef viewName = NULL; + if (SecXPCDictionaryCopyStringOptional(event, kSecXPCKeyString, &viewName, &error)) { + CFStringRef name = SecServerItemBackupEnsureCopyView(viewName, &error); + SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, name, &error); + CFReleaseNull(name); + } + } + break; + } case sec_item_backup_handoff_fd_id: { if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) { @@ -833,19 +917,6 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, }); } break; - case kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server(label, password, dsid, parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetUserCredentialsAndDSID_Server(label, password, dsid, &error)); - } - CFReleaseNull(parentEvent); - }); - } - break; case kSecXPCOpView: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { with_view_and_action(event, ^(CFStringRef view, uint64_t actionCode) { @@ -854,18 +925,13 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, }); } break; - case kSecXPCOpViewSet: // FALLTHROUGH - case kSecXPCOpViewSetWithAnalytics: + case kSecXPCOpViewSet: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { CFSetRef enabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyEnabledViewsKey); CFSetRef disabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyDisabledViewsKey); - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error)){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSetWithAnalytics_Server(enabledViews, disabledViews, parentEvent)); - } + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSet_Server(enabledViews, disabledViews)); CFReleaseNull(enabledViews); CFReleaseNull(disabledViews); - CFReleaseNull(parentEvent); } break; case kSecXPCOpCanAuthenticate: @@ -892,89 +958,19 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCRequestToJoinCircle_Server(&error)); } break; - case kSecXPCOpRequestToJoinWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleWithAnalytics_Server(parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircle_Server(&error)); - } - CFReleaseNull(parentEvent); - } - break; case kSecXPCOpAccountHasPublicKey: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCAccountHasPublicKey_Server(&error)); } break; - case kSecXPCOpAccountIsNew: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCAccountIsNew_Server(&error)); - } - break; + case kSecXPCOpRequestToJoinAfterRestore: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleAfterRestore_Server(&error)); } break; - case kSecXPCOpRequestToJoinAfterRestoreWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleAfterRestore_Server(&error)); - } - CFReleaseNull(parentEvent); - } - break; - case kSecXPCOpRequestEnsureFreshParameters: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCRequestEnsureFreshParameters_Server(&error)); - } - break; - case kSecXPCOpGetAllTheRings: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFStringRef ringDescriptions = SOSCCGetAllTheRings_Server(&error); - xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(ringDescriptions); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary); - xpc_release(xpc_dictionary); - CFReleaseNull(ringDescriptions); - } - break; - case kSecXPCOpApplyToARing: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCApplyToARing_Server(ringName, &error)); - CFReleaseNull(ringName); - } - break; - case kSecXPCOpWithdrawlFromARing: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWithdrawlFromARing_Server(ringName, &error)); - CFReleaseNull(ringName); - } - break; - case kSecXPCOpRingStatus: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRingStatus_Server(ringName, &error)); - CFReleaseNull(ringName); - } - break; - case kSecXPCOpEnableRing: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCEnableRing_Server(ringName, &error)); - CFReleaseNull(ringName); - } - break; case kSecXPCOpRequestDeviceID: case kSecXPCOpSetDeviceID: case kSecXPCOpHandleIDSMessage: @@ -1003,33 +999,12 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCResetToEmpty_Server(&error)); } break; - case kSecXPCOpResetToEmptyWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCResetToEmptyWithAnalytics_Server(parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCResetToEmpty_Server(&error)); - } - } - break; case kSecXPCOpRemoveThisDeviceFromCircle: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemoveThisDeviceFromCircle_Server(&error)); } break; - case kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server(parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemoveThisDeviceFromCircle_Server(&error)); - } - CFReleaseNull(parentEvent); - } - break; case kSecXPCOpRemovePeersFromCircle: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfoArray, &error); @@ -1038,33 +1013,19 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFReleaseNull(applicants); } break; - case kSecXPCOpRemovePeersFromCircleWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfoArray, &error); - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemovePeersFromCircleWithAnalytics_Server(applicants, parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemovePeersFromCircle_Server(applicants, &error)); + case kSecXPCOpLoggedIntoAccount: + if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { + SOSCCNotifyLoggedIntoAccount_Server(); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + true); } - CFReleaseNull(parentEvent); - CFReleaseNull(applicants); - } - break; + break; case kSecXPCOpLoggedOutOfAccount: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCLoggedOutOfAccount_Server(&error)); } break; - case kSecXPCOpBailFromCircle: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - // 0 is valid; ok for this parameter to be unset or incorrect type. Note: kSecXPCLimitInMinutes is actually seconds, not minutes - uint64_t limit_in_seconds = xpc_dictionary_get_uint64(event, kSecXPCLimitInMinutes); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCBailFromCircle_Server(limit_in_seconds, &error)); - } - break; case kSecXPCOpAcceptApplicants: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfoArray); @@ -1191,61 +1152,17 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, &error); } break; - case kSecXPCOpCopyAccountData: - { - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - xpc_object_t xpc_account_object = NULL; - CFDataRef accountData = SOSCCCopyAccountState_Server(&error); - if(accountData) - xpc_account_object = _CFXPCCreateXPCObjectFromCFObject(accountData); - - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_account_object); - CFReleaseNull(accountData); - } - break; - } - case kSecXPCOpDeleteAccountData: - { - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - bool status = SOSCCDeleteAccountState_Server(&error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status); - } - break; - } - case kSecXPCOpCopyEngineData: - { - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - - xpc_object_t xpc_engine_object = NULL; - CFDataRef engineData = SOSCCCopyEngineData_Server(&error); - if(engineData) - xpc_engine_object = _CFXPCCreateXPCObjectFromCFObject(engineData); - - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_engine_object); - CFReleaseNull(engineData); - - } - break; - } - case kSecXPCOpDeleteEngineData: - { - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - bool status = SOSCCDeleteEngineState_Server(&error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status); - } - break; - } case kSecXPCOpCopyEngineState: { - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFArrayRef array = SOSCCCopyEngineState_Server(&error); - CFDataRef derData = NULL; + if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { + CFArrayRef array = SOSCCCopyEngineState_Server(&error); + CFDataRef derData = NULL; - require_quiet(array, done); - derData = CFPropertyListCreateDERData(kCFAllocatorDefault, array, &error); + require_quiet(array, done); + derData = CFPropertyListCreateDERData(kCFAllocatorDefault, array, &error); - require_quiet(derData, done); - xpc_dictionary_set_data(replyMessage, kSecXPCKeyResult, CFDataGetBytePtr(derData), CFDataGetLength(derData)); + require_quiet(derData, done); + xpc_dictionary_set_data(replyMessage, kSecXPCKeyResult, CFDataGetBytePtr(derData),CFDataGetLength(derData)); done: CFReleaseNull(derData); CFReleaseNull(array); @@ -1253,10 +1170,10 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } break; case kSecXPCOpCopyPeerPeerInfo: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult, - SOSCCCopyPeerPeerInfo_Server(&error), - &error); + if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { + xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult, + SOSCCCopyPeerPeerInfo_Server(&error), + &error); } break; case kSecXPCOpCopyConcurringPeerPeerInfo: @@ -1320,13 +1237,6 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCProcessEnsurePeerRegistration_Server(&error)); } break; - case kSecXPCOpCopyIncompatibilityInfo: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFStringRef iis = SOSCCCopyIncompatibilityInfo_Server(&error); - SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, iis, &error); - CFReleaseSafe(iis); - } - break; case kSecXPCOpRollKeys: { // false is valid, so it's safe for this parameter to be unset or incorrect type @@ -1341,71 +1251,6 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCWaitForInitialSync_Server(&error)); } break; - - case kSecXPCOpWaitForInitialSyncWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWaitForInitialSyncWithAnalytics_Server(parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWaitForInitialSync_Server(&error)); - } - CFReleaseNull(parentEvent); - } - break; - case kSecXPCOpCopyYetToSyncViews: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFArrayRef array = SOSCCCopyYetToSyncViewsList_Server(&error); - if (array) { - xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); - xpc_release(xpc_array); - } - CFReleaseNull(array); - } - break; - case kSecXPCOpSetEscrowRecord: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFStringRef escrow_label = SecXPCDictionaryCopyString(event, kSecXPCKeyEscrowLabel, &error); // NULL checked below - uint64_t tries = xpc_dictionary_get_int64(event, kSecXPCKeyTriesLabel); // 0 is acceptable; safe for this parameter to be unset or incorrect type - - if (escrow_label != NULL) { - bool result = SOSCCSetEscrowRecord_Server(escrow_label, tries, &error); - if (result) { - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); - } - CFReleaseNull(escrow_label); - } - } - break; - case kSecXPCOpGetEscrowRecord: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDictionaryRef record = SOSCCCopyEscrowRecord_Server(&error); - if (record) { - xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(record); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary); - xpc_release(xpc_dictionary); - } - CFReleaseNull(record); - } - break; - case kSecXPCOpCopyBackupInformation: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDictionaryRef record = SOSCCCopyBackupInformation_Server(&error); - if (record) { - xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(record); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary); - xpc_release(xpc_dictionary); - } - CFReleaseNull(record); - } - break; - - case kSecXPCOpIsThisDeviceLastBackup: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error)); - } - break; case kSecXPCOpPeersHaveViewsEnabled: { CFArrayRef viewSet = SecXPCDictionaryCopyArray(event, kSecXPCKeyArray, &error); @@ -1475,34 +1320,6 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } } break; - case kSecXPCOpWrapToBackupSliceKeyBagForView: - { - CFStringRef viewname = SecXPCDictionaryCopyString(event, kSecXPCKeyViewName, &error); - if(viewname) { - CFDataRef plaintext = SecXPCDictionaryCopyData(event, kSecXPCData, &error); - if (plaintext) { - CFDataRef ciphertext = NULL; - CFDataRef bskbEncoded = NULL; - - bool result = SOSWrapToBackupSliceKeyBagForView_Server(viewname, plaintext, &ciphertext, &bskbEncoded, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); - - if(!error && result) { - if(ciphertext) { - xpc_dictionary_set_data(replyMessage, kSecXPCData, CFDataGetBytePtr(ciphertext), CFDataGetLength(ciphertext)); - } - if(bskbEncoded) { - xpc_dictionary_set_data(replyMessage, kSecXPCKeyKeybag, CFDataGetBytePtr(bskbEncoded), CFDataGetLength(bskbEncoded)); - } - } - CFReleaseSafe(ciphertext); - CFReleaseSafe(bskbEncoded); - } - CFReleaseSafe(plaintext); - } - CFReleaseNull(viewname); - } - break; case kSecXPCOpCopyApplication: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) { SOSPeerInfoRef peerInfo = SOSCCCopyApplication_Server(&error); @@ -1558,16 +1375,9 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } } break; - case kSecXPCOpKVSKeyCleanup: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - bool retval = SOSCCCleanupKVSKeys_Server(&error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval); - } - break; - case kSecXPCOpPopulateKVS: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - bool retval = SOSCCTestPopulateKVSWithBadKeys_Server(&error); + bool retval = SOSCCCleanupKVSKeys_Server(&error); xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval); } break; @@ -1695,12 +1505,14 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_connection_send_message(connection, replyMessage); xpc_release(replyMessage); } - if (xpcError) + if (xpcError) { xpc_release(xpcError); + } CFReleaseSafe(error); CFReleaseSafe(client.accessGroups); CFReleaseSafe(client.musr); CFReleaseSafe(client.task); + CFReleaseNull(client.applicationIdentifier); CFReleaseSafe(domains); CFReleaseSafe(clientAuditToken); } @@ -1737,6 +1549,20 @@ static void securityd_xpc_init(const char *service_name) }); #endif + xpc_activity_register("com.apple.securityd.entropyhealth", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { + xpc_activity_state_t activityState = xpc_activity_get_state(activity); + if (activityState == XPC_ACTIVITY_STATE_RUN) { + SecCoreAnalyticsSendKernEntropyHealth(); + } + }); + + xpc_activity_register("com.apple.securityd.prng", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { + xpc_activity_state_t state = xpc_activity_get_state(activity); + if (state == XPC_ACTIVITY_STATE_RUN) { + refresh_prng(); + } + }); + #if OCTAGON && !TARGET_OS_BRIDGE // Kick off reporting tasks. if (os_variant_has_internal_diagnostics("com.apple.security") && !os_variant_is_recovery("securityd")) { @@ -1748,7 +1574,7 @@ static void securityd_xpc_init(const char *service_name) // 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_BRIDGE static void securityd_soscc_lock_hack() { dispatch_queue_t soscc_lock_queue = dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT); int soscc_tok; @@ -1838,22 +1664,29 @@ int main(int argc, char *argv[]) }); #endif + signal(SIGTERM, SIG_IGN); + static dispatch_source_t termSource; + termSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)); + dispatch_source_set_event_handler(termSource, ^{ + secnotice("signal", "SIGTERM, exiting when clean ✌️"); + xpc_transaction_exit_clean(); + }); + dispatch_activate(termSource); + #if TARGET_OS_OSX #define SECD_PROFILE_NAME "com.apple.secd" const char *homedir = homedirPath(); - if (homedir == NULL) + if (homedir == NULL) { errx(1, "failed to get home directory for secd"); + } char *errorbuf = NULL; - const char *sandbox_params[] = { - "_HOME", homedir, - NULL - }; - int32_t rc; - - rc = sandbox_init_with_parameters(SECD_PROFILE_NAME, SANDBOX_NAMED, sandbox_params, &errorbuf); - if (rc) - err(1, "Failed to process in a sandbox: %d %s", rc, errorbuf); + const char *sandbox_params[] = {"_HOME", homedir, NULL}; + int32_t rc = sandbox_init_with_parameters(SECD_PROFILE_NAME, SANDBOX_NAMED, sandbox_params, &errorbuf); + if (rc) { + errx(1, "Failed to instantiate sandbox: %d %s", rc, errorbuf); + /* errx will quit the process */ + } #endif /* TARGET_OS_OSX */ const char *serviceName = kSecuritydXPCServiceName; @@ -1870,11 +1703,12 @@ int main(int argc, char *argv[]) securityd_init_server(); securityd_xpc_init(serviceName); - SecCreateSecuritydXPCServer(); + #if SECUREOBJECTSYNC SOSControlServerInitialize(); #endif + #if OCTAGON CKKSControlServerInitialize(); OctagonControlServerInitialize(); @@ -1882,7 +1716,7 @@ int main(int argc, char *argv[]) #endif // 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_BRIDGE securityd_soscc_lock_hack(); #endif diff --git a/OSX/sec/ipc/server_endpoint.m b/OSX/sec/ipc/server_endpoint.m index 8db291ac..50607d9e 100644 --- a/OSX/sec/ipc/server_endpoint.m +++ b/OSX/sec/ipc/server_endpoint.m @@ -75,6 +75,8 @@ self->_client.inMultiUser = existingClient->inMultiUser; self->_client.activeUser = existingClient->activeUser; #endif + self->_client.applicationIdentifier = CFRetainSafe(existingClient->applicationIdentifier); + self->_client.isAppClip = existingClient->isAppClip; } return self; } @@ -88,6 +90,7 @@ CFReleaseNull(self->_client.task); CFReleaseNull(self->_client.accessGroups); CFReleaseNull(self->_client.musr); + CFReleaseNull(self->_client.applicationIdentifier); } @end diff --git a/OSX/sec/ipc/server_entitlement_helpers.c b/OSX/sec/ipc/server_entitlement_helpers.c index 3dd4c584..f5fbfa98 100644 --- a/OSX/sec/ipc/server_entitlement_helpers.c +++ b/OSX/sec/ipc/server_entitlement_helpers.c @@ -29,10 +29,12 @@ #include #include "ipc/securityd_client.h" #include +#include "sectask/SystemEntitlements.h" #include #include "utilities/SecCFRelease.h" #include "utilities/SecCFWrappers.h" #include "utilities/debugging.h" +#include CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task, CFStringRef entitlement) @@ -70,8 +72,14 @@ CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task, } CFStringRef SecTaskCopyApplicationIdentifier(SecTaskRef task) { - return SecTaskCopyStringForEntitlement(task, - kSecEntitlementApplicationIdentifier); + // Catalyst apps may have the iOS style application identifier. + CFStringRef result = SecTaskCopyStringForEntitlement(task, + kSecEntitlementBasicApplicationIdentifier); + if (!result) { + result = SecTaskCopyStringForEntitlement(task, + kSecEntitlementAppleApplicationIdentifier); + } + return result; } #if TARGET_OS_IOS @@ -85,6 +93,8 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) { CFMutableArrayRef groups = NULL; + bool onDemandInstallable = SecTaskGetBooleanValueForEntitlement(task, kSystemEntitlementOnDemandInstallCapable); + CFArrayRef keychainAccessGroups, appleSecurityApplicationGroups; CFStringRef appID; CFArrayRef associatedAppIDs; @@ -92,7 +102,7 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) keychainAccessGroups = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementKeychainAccessGroups); appleSecurityApplicationGroups = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementAppleSecurityApplicationGroups); appID = SecTaskCopyApplicationIdentifier(task); - // Marzipan apps (may?) have this entitlement. + // Catalyst apps (may?) have this entitlement. associatedAppIDs = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementAssociatedApplicationIdentifier); groups = CFArrayCreateMutableForCFTypes(NULL); @@ -118,14 +128,19 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) CFArrayAppendValue(groups, appID); } if (appleSecurityApplicationGroups) { - CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, CFArrayGetCount(appleSecurityApplicationGroups))); + if (onDemandInstallable) { + // This is perfectly legal for other functionality but not for keychain use + secnotice("entitlements", "Ignoring \"%@\" because client is API-restricted", kSecEntitlementAppleSecurityApplicationGroups); + } else { + CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, CFArrayGetCount(appleSecurityApplicationGroups))); + } } } else { // Try to provide some hopefully helpful diagnostics for common failure cases. if (CFArrayGetCount(groups) == 0) { if (appID) { secwarning("Entitlement %@=%@ is ignored because of invalid application signature or incorrect provisioning profile", - kSecEntitlementApplicationIdentifier, appID); + kSecEntitlementApplicationIdentifier, appID); } if (appleSecurityApplicationGroups) { secwarning("Entitlement %@=%@ is ignored because of invalid application signature or incorrect provisioning profile", @@ -134,6 +149,21 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) } } + // Do not allow to explicitly specify com.apple.token if token support is not allowed by feature flags. + CFIndex index = CFArrayGetFirstIndexOfValue(groups, CFRangeMake(0, CFArrayGetCount(groups)), kSecAttrAccessGroupToken); + if (index != kCFNotFound) { + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + // Make sure that com.apple.token is last one. This is because it is always read-only group and therefore updating keychain + // operations without explicitly set kSecAttrAccessGroup attribute would always fail. + CFArrayRemoveValueAtIndex(groups, index); + CFArrayAppendValue(groups, kSecAttrAccessGroupToken); + } else { + secwarning("Keychain access group com.apple.token ignored, feature not available"); + CFArrayRemoveValueAtIndex(groups, index); + } + } + +#if TARGET_OS_OSX /* * We would like to add implicit token access group always, but we avoid doing that in case that application * clearly intended to use non-smartcard functionality of keychain but messed up signing or provisioning. In this case, @@ -142,8 +172,12 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) */ bool entitlementsFailure = (CFArrayGetCount(groups) == 0 && appID != NULL); if (!entitlementsFailure) { - CFArrayAppendValue(groups, kSecAttrAccessGroupToken); + bool addTokenGroup = os_feature_enabled(CryptoTokenKit, UseTokens); + if (addTokenGroup && !CFArrayContainsValue(groups, CFRangeMake(0, CFArrayGetCount(groups)), kSecAttrAccessGroupToken)) { + CFArrayAppendValue(groups, kSecAttrAccessGroupToken); + } } +#endif CFReleaseNull(associatedAppIDs); CFReleaseNull(appID); diff --git a/OSX/sec/ipc/server_security_helpers.h b/OSX/sec/ipc/server_security_helpers.h index 9986b7cb..8d878b21 100644 --- a/OSX/sec/ipc/server_security_helpers.h +++ b/OSX/sec/ipc/server_security_helpers.h @@ -34,6 +34,20 @@ void SecCreateSecuritydXPCServer(void); bool fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t auditToken); CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task); + +/*! + @function SecTaskIsEligiblePlatformBinary + @abstract Determine whether task belongs to valid platform binary and optionally has one of the allowed identifiers. + @param task The client task to be evaluated. + @param identifiers Optional array of codesigning identifiers of allowed callers. Pass NULL to permit any platform binary. + @result Client satisfies the criteria or not. + */ +bool SecTaskIsEligiblePlatformBinary(SecTaskRef task, CFArrayRef identifiers); + +// Testing support void SecAccessGroupsSetCurrent(CFArrayRef accessGroups); +void SecSecurityClientRegularToAppClip(void); +void SecSecurityClientAppClipToRegular(void); +void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier); #endif /* server_security_helpers_h */ diff --git a/OSX/sec/ipc/server_security_helpers.m b/OSX/sec/ipc/server_security_helpers.m index cd7f0e15..b6351c6b 100644 --- a/OSX/sec/ipc/server_security_helpers.m +++ b/OSX/sec/ipc/server_security_helpers.m @@ -30,6 +30,9 @@ #include #include "ipc/securityd_client.h" #include +#include "sectask/SystemEntitlements.h" +#include +#include #include #include "utilities/SecCFRelease.h" #include "utilities/SecCFWrappers.h" @@ -66,6 +69,35 @@ device_is_multiuser(void) } #endif /* HAVE_MOBILE_KEYBAG_SUPPORT && TARGET_OS_IOS */ +static bool sanityCheckClientAccessGroups(SecurityClient* client) { + if (!client->accessGroups) { + return true; + } + + CFRange range = { 0, CFArrayGetCount(client->accessGroups) }; + if (!CFArrayContainsValue(client->accessGroups, range, CFSTR("*"))) { + return true; + } + + CFMutableArrayRef allowedIdentifiers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); +#if TARGET_OS_OSX + CFArrayAppendValue(allowedIdentifiers, CFSTR("com.apple.keychainaccess")); + CFArrayAppendValue(allowedIdentifiers, CFSTR("com.apple.KeychainMigrator")); +#endif + if (SecIsInternalRelease()) { +#if TARGET_OS_OSX + CFArrayAppendValue(allowedIdentifiers, CFSTR("com.apple.security2")); +#else + CFArrayAppendValue(allowedIdentifiers, CFSTR("com.apple.security")); +#endif + } + + bool answer = SecTaskIsEligiblePlatformBinary(client->task, allowedIdentifiers); + CFReleaseNull(allowedIdentifiers); + + return answer; +} + bool fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t auditToken) { if(!client) { @@ -77,8 +109,7 @@ fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t aud client->uid = uid; client->musr = NULL; -#if TARGET_OS_IOS -#if HAVE_MOBILE_KEYBAG_SUPPORT +#if TARGET_OS_IOS && HAVE_MOBILE_KEYBAG_SUPPORT if (device_is_multiuser()) { CFErrorRef error = NULL; @@ -108,15 +139,23 @@ fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t aud client->keybag = KEYBAG_DEVICE; } } else -#endif +#endif /* TARGET_OS_IOS && HAVE_MOBILE_KEYBAG_SUPPORT */ +#if TARGET_OS_IOS || TARGET_OS_TV /* - * If the client application is a enterprise app according to usermanager, switch - * to the per enterprise slice of keychain. + * iOS supports Enterprise Data Separation. + * tvOS supports guest users. + * Use the appropriate musr values for either. */ { UMUserPersona * persona = [[UMUserManager sharedManager] currentPersona]; - if (persona && persona.userPersonaType == UMUserPersonaTypeEnterprise) { - secinfo("serverxpc", "securityd client: enterprise user"); + if (persona && +#if TARGET_OS_IOS + persona.userPersonaType == UMUserPersonaTypeEnterprise +#elif TARGET_OS_TV + persona.userPersonaType == UMUserPersonaTypeGuest +#endif + ) { + secinfo("serverxpc", "securityd client: persona user %@", persona.userPersonaNickName); uuid_t uuid; if (uuid_parse([persona.userPersonaUniqueString UTF8String], uuid) != 0) { @@ -125,11 +164,15 @@ fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t aud client->musr = CFDataCreate(NULL, uuid, sizeof(uuid_t)); } } -#endif /* TARGET_OS_IOS */ +#endif /* TARGET_OS_IOS || TARGET_OS_TV */ client->task = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken); - client->accessGroups = SecTaskCopyAccessGroups(client->task); + client->applicationIdentifier = SecTaskCopyApplicationIdentifier(client->task); + client->isAppClip = SecTaskGetBooleanValueForEntitlement(client->task, kSystemEntitlementOnDemandInstallCapable); + if (client->isAppClip) { + secinfo("serverxpc", "securityd client: app clip (API restricted)"); + } #if TARGET_OS_IPHONE client->allowSystemKeychain = SecTaskGetBooleanValueForEntitlement(client->task, kSecEntitlementPrivateSystemKeychain); @@ -141,7 +184,71 @@ fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t aud client->allowSyncBubbleKeychain = SecTaskGetBooleanValueForEntitlement(client->task, kSecEntitlementPrivateKeychainSyncBubble); } #endif + if (!sanityCheckClientAccessGroups(client)) { + CFReleaseNull(client->task); + CFReleaseNull(client->accessGroups); + CFReleaseNull(client->musr); + CFReleaseNull(client->applicationIdentifier); + return false; + } } return true; } +// Stolen and adapted from securityd_service +bool SecTaskIsEligiblePlatformBinary(SecTaskRef task, CFArrayRef identifiers) { +#if (DEBUG || RC_BUILDIT_YES) + secnotice("serverxpc", "Accepting client because debug"); + return true; +#else + + if (task == NULL) { + secerror("serverxpc: Client task is null, cannot verify platformness"); + return false; + } + + uint32_t flags = SecTaskGetCodeSignStatus(task); + /* check if valid and platform binary, but not platform path */ + + if ((flags & (CS_VALID | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) != (CS_VALID | CS_PLATFORM_BINARY)) { + if (SecIsInternalRelease()) { + if ((flags & (CS_DEBUGGED | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) != (CS_DEBUGGED | CS_PLATFORM_BINARY)) { + secerror("serverxpc: client is not a platform binary: 0x%08x", flags); + return false; + } + } else { + secerror("serverxpc: client is not a platform binary: 0x%08x", flags); + return false; + } + } + + CFStringRef signingIdentifier = SecTaskCopySigningIdentifier(task, NULL); + if (identifiers) { + if (signingIdentifier == NULL) { + secerror("serverxpc: client has no codesign identifier"); + return false; + } + + __block bool result = false; + CFArrayForEach(identifiers, ^(const void *value) { + if (CFEqual(value, signingIdentifier)) { + result = true; + } + }); + + if (result == true) { + secinfo("serverxpc", "client %@ is eligible platform binary", signingIdentifier); + } else { + secerror("serverxpc: client %@ is not eligible", signingIdentifier); + } + + CFReleaseNull(signingIdentifier); + return result; + } + + secinfo("serverxpc", "Client %@ is valid platform binary", signingIdentifier); + CFReleaseNull(signingIdentifier); + return true; + +#endif +} diff --git a/OSX/sec/ipc/server_xpc.m b/OSX/sec/ipc/server_xpc.m index 27413305..5c83e2c6 100644 --- a/OSX/sec/ipc/server_xpc.m +++ b/OSX/sec/ipc/server_xpc.m @@ -28,7 +28,7 @@ #include #include -#if TARGET_DARWINOS +#if defined(TARGET_DARWINOS) && TARGET_DARWINOS #undef OCTAGON #undef SECUREOBJECTSYNC #undef SHAREDWEBCREDENTIALS @@ -107,6 +107,20 @@ } } + if(attributes[(id)kSecDataInetExtraNotes] || + attributes[(id)kSecDataInetExtraHistory] || + attributes[(id)kSecDataInetExtraClientDefined0] || + attributes[(id)kSecDataInetExtraClientDefined1] || + attributes[(id)kSecDataInetExtraClientDefined2] || + attributes[(id)kSecDataInetExtraClientDefined3]) { + if(![self clientHasBooleanEntitlement:(__bridge NSString*)kSecEntitlementPrivateInetExpansionFields]) { + SecError(errSecMissingEntitlement, &cferror, CFSTR("SecItemAddAndNotifyOnSync: %@ does not have entitlement %@"), _client.task, kSecEntitlementPrivateInetExpansionFields); + complete(NULL, NULL, (__bridge NSError*) cferror); + CFReleaseNull(cferror); + return; + } + } + CFTypeRef cfresult = NULL; NSMutableDictionary* callbackQuery = [attributes mutableCopy]; @@ -363,7 +377,7 @@ (__bridge NSString *)kSecAttrSynchronizable : (__bridge NSString *)kSecAttrSynchronizableAny, }; - Query *q = query_create_with_limit((__bridge CFDictionaryRef)attributes, _client.musr, 0, &cferror); + Query *q = query_create_with_limit((__bridge CFDictionaryRef)attributes, _client.musr, 0, &(_client), &cferror); if (q == NULL) { SecError(errSecParam, &cferror, CFSTR("failed to build query: %@"), _client.task); complete(NULL, (__bridge NSError*) cferror); @@ -425,4 +439,42 @@ [[SecDbBackupManager manager] verifyBackupIntegrity:lightweight completion:completion]; } + +- (void)secItemDeleteForAppClipApplicationIdentifier:(NSString*)identifier + completion:(void (^)(OSStatus))completion +{ + if (![self clientHasBooleanEntitlement:(__bridge NSString*)kSecEntitlementPrivateAppClipDeletion]) { + completion(errSecMissingEntitlement); + return; + } + + completion(SecServerDeleteForAppClipApplicationIdentifier((__bridge CFStringRef)identifier)); +} + + +- (void)secItemPersistKeychainWritesAtHighPerformanceCost:(void (^)(OSStatus status, NSError* error))completion +{ + if (![self clientHasBooleanEntitlement:(__bridge NSString*)kSecEntitlementPrivatePerformanceImpactingAPI]) { + completion(errSecMissingEntitlement, [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecMissingEntitlement userInfo:nil]); + return; + } + + __block CFErrorRef cferror = NULL; + secnotice("item", "Performing keychain database checkpoint"); + + bool status = kc_with_dbt(true, &cferror, ^bool(SecDbConnectionRef dbt) { + return SecDbCheckpoint(dbt, &cferror); + }); + + if(!status) { + secerror("item: keychain database checkpoint failed: %@", cferror); + } else { + secnotice("item", "Keychain database checkpoint succeeded"); + } + + completion(status ? errSecSuccess : errSecInternal, (__bridge NSError*)cferror); + + CFReleaseNull(cferror); +} + @end diff --git a/OSX/sec/os_log/com.apple.security.ckks.plist b/OSX/sec/os_log/com.apple.security.ckks.plist new file mode 100644 index 00000000..b164d1b6 --- /dev/null +++ b/OSX/sec/os_log/com.apple.security.ckks.plist @@ -0,0 +1,37 @@ + + + + + DEFAULT-OPTIONS + + Default-Privacy-Setting + Public + Enabled + True + Persist + Default + Enable-Oversize-Messages + + TTL + Default + Development + + Enabled + True + Persist + Default + TTL + Default + + Debug + + Enabled + True + Persist + True + TTL + 2 + + + + diff --git a/OSX/sec/os_log/com.apple.securityd.plist b/OSX/sec/os_log/com.apple.securityd.plist index 87da5a3d..a293e2d7 100644 --- a/OSX/sec/os_log/com.apple.securityd.plist +++ b/OSX/sec/os_log/com.apple.securityd.plist @@ -80,5 +80,25 @@ 30 + itemDelete + + Default-Privacy-Setting + Public + Enabled + True + Persist + True + TTL + 10d + Development + + Enabled + True + Persist + True + TTL + 10d + + diff --git a/OSX/sectests/SecurityTests-Entitlements.plist b/OSX/sectests/SecurityTests-Entitlements.plist index 35eb8339..9dc36dce 100644 --- a/OSX/sectests/SecurityTests-Entitlements.plist +++ b/OSX/sectests/SecurityTests-Entitlements.plist @@ -33,5 +33,11 @@ 123456.test.group 123456.test.group2 + com.apple.private.AuthorizationServices + + com.apple.trust-settings.admin + + com.apple.private.security.storage.Keychains + diff --git a/OSX/sectests/testlist.h b/OSX/sectests/testlist.h index 44ebadc5..e637efee 100644 --- a/OSX/sectests/testlist.h +++ b/OSX/sectests/testlist.h @@ -5,6 +5,5 @@ /* Don't prevent multiple inclusion of this file. */ #include #include -#include #include diff --git a/OSX/shared_regressions/append_log_to_plist.py b/OSX/shared_regressions/append_log_to_plist.py old mode 100644 new mode 100755 diff --git a/OSX/shared_regressions/shared_regressions.h b/OSX/shared_regressions/shared_regressions.h index 534f8cd5..bcc61d2b 100644 --- a/OSX/shared_regressions/shared_regressions.h +++ b/OSX/shared_regressions/shared_regressions.h @@ -8,23 +8,10 @@ */ #include -ONE_TEST(si_21_sectrust_asr) -ONE_TEST(si_22_sectrust_iap) -#if !TARGET_OS_WATCH -ONE_TEST(si_23_sectrust_ocsp) -#else -DISABLED_ONE_TEST(si_23_sectrust_ocsp) -#endif -ONE_TEST(si_24_sectrust_itms) -ONE_TEST(si_24_sectrust_diginotar) -ONE_TEST(si_24_sectrust_digicert_malaysia) -ONE_TEST(si_24_sectrust_passbook) ONE_TEST(si_25_cms_skid) -ONE_TEST(si_26_sectrust_copyproperties) -ONE_TEST(si_27_sectrust_exceptions) -ONE_TEST(si_28_sectrustsettings) +ONE_TEST(si_26_cms_apple_signed_samples) +ONE_TEST(si_27_cms_parse) ONE_TEST(si_29_cms_chain_mode) -ONE_TEST(si_32_sectrust_pinning_required) ONE_TEST(si_34_cms_timestamp) ONE_TEST(si_35_cms_expiration_time) ONE_TEST(si_44_seckey_gen) @@ -42,19 +29,7 @@ ONE_TEST(si_62_csr) ONE_TEST(si_64_ossl_cms) ONE_TEST(si_65_cms_cert_policy) ONE_TEST(si_66_smime) -#if !TARGET_OS_WATCH -ONE_TEST(si_67_sectrust_blocklist) -ONE_TEST(si_84_sectrust_allowlist) -#else -DISABLED_ONE_TEST(si_67_sectrust_blocklist) -DISABLED_ONE_TEST(si_84_sectrust_allowlist) -#endif ONE_TEST(si_68_secmatchissuer) -ONE_TEST(si_70_sectrust_unified) -ONE_TEST(si_71_mobile_store_policy) -ONE_TEST(si_74_OTA_PKI_Signer) -ONE_TEST(si_83_seccertificate_sighashalg) -ONE_TEST(si_88_sectrust_valid) ONE_TEST(si_89_cms_hash_agility) ONE_TEST(rk_01_recoverykey) diff --git a/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_SAN_seq_length.cer b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_SAN_seq_length.cer new file mode 100644 index 00000000..787be236 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_SAN_seq_length.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_general_name_type.cer b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_general_name_type.cer new file mode 100644 index 00000000..8805ba18 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_general_name_type.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/san_zero_length_sequence.cer b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/san_zero_length_sequence.cer new file mode 100644 index 00000000..b6249ec4 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/san_zero_length_sequence.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_aia.cer b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_aia.cer new file mode 100644 index 00000000..a83546f1 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_aia.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_certificate_policies.cer b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_certificate_policies.cer new file mode 100644 index 00000000..9cb2c1f7 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_certificate_policies.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_crldps.cer b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_crldps.cer new file mode 100644 index 00000000..ed0b660c Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_crldps.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/KeyFailureCerts/parse_fail_explicit_paramaters.cer b/OSX/shared_regressions/si-18-certificate-parse/KeyFailureCerts/parse_fail_explicit_paramaters.cer new file mode 100644 index 00000000..f9c53045 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/KeyFailureCerts/parse_fail_explicit_paramaters.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/rdn_short_length.cer b/OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/rdn_short_length.cer new file mode 100644 index 00000000..9c0f93b3 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/rdn_short_length.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/zero_length_rdn.cer b/OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/zero_length_rdn.cer new file mode 100644 index 00000000..e4194b77 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/zero_length_rdn.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_critical_policy_mappings.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_critical_policy_mappings.cer new file mode 100644 index 00000000..a696bd72 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_critical_policy_mappings.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_ekus.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_ekus.cer new file mode 100644 index 00000000..7b839ce3 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_ekus.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_extensions.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_extensions.cer new file mode 100644 index 00000000..96ed5c67 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_extensions.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_general_subtrees.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_general_subtrees.cer new file mode 100644 index 00000000..5d76d031 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_general_subtrees.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_constructed_uri_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_constructed_uri_name.cer new file mode 100644 index 00000000..bab809ee Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_constructed_uri_name.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_directory_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_directory_name.cer new file mode 100644 index 00000000..e755cecd Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_directory_name.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_dns_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_dns_name.cer new file mode 100644 index 00000000..3e60bc97 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_dns_name.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_edi_party_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_edi_party_name.cer new file mode 100644 index 00000000..0020d4c8 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_edi_party_name.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_ip_address.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_ip_address.cer new file mode 100644 index 00000000..64eff2a1 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_ip_address.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_other_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_other_name.cer new file mode 100644 index 00000000..124c48e2 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_other_name.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_registered_id.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_registered_id.cer new file mode 100644 index 00000000..44163a71 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_registered_id.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_rfc822_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_rfc822_name.cer new file mode 100644 index 00000000..6eaaa8ef Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_rfc822_name.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_uri_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_uri_name.cer new file mode 100644 index 00000000..77a69f7a Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_uri_name.cer differ diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_x400_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_x400_name.cer new file mode 100644 index 00000000..c84a8d94 Binary files /dev/null and b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_x400_name.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/AAACertificateServices.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/AAACertificateServices.cer new file mode 100644 index 00000000..5c715fae Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/AAACertificateServices.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/ApplePublicServerRSA12-G1.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/ApplePublicServerRSA12-G1.cer new file mode 100644 index 00000000..3b7788be Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/ApplePublicServerRSA12-G1.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/GoogleInternetAuthorityG3.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/GoogleInternetAuthorityG3.cer deleted file mode 100644 index ffb1a0ff..00000000 Binary files a/OSX/shared_regressions/si-20-sectrust-policies-data/GoogleInternetAuthorityG3.cer and /dev/null differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/GoogleTrustServicesCA101.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/GoogleTrustServicesCA101.cer new file mode 100644 index 00000000..29c5c22e Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/GoogleTrustServicesCA101.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomainsParsingTest.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomainsParsingTest.plist new file mode 100644 index 00000000..8dd22192 --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomainsParsingTest.plist @@ -0,0 +1,100 @@ + + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_ca + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedCAIdentities + + NSPinnedCAIdentitiesCount + 1 + NSIncludesSubdomains + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_leaf + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedLeafIdentitiesCount + 2 + NSPinnedCAIdentities + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_leaf_and_ca + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedLeafIdentitiesCount + 1 + NSPinnedCAIdentities + + NSPinnedCAIdentitiesCount + 2 + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_without_spki + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedCAIdentities + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_with_empty_spki + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedLeafIdentitiesCount + 0 + NSPinnedCAIdentities + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_with_invalid_spki + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedLeafIdentitiesCount + 0 + NSPinnedCAIdentities + + NSPinnedCAIdentitiesCount + 0 + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_ca.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_ca.plist new file mode 100644 index 00000000..edac4c79 --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_ca.plist @@ -0,0 +1,24 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSIncludesSubdomains + + NSPinnedCAIdentities + + + SPKI-SHA256-BASE64 + r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E= + + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf.plist new file mode 100644 index 00000000..4cab23ad --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf.plist @@ -0,0 +1,26 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSPinnedLeafIdentities + + + SPKI-SHA256-BASE64 + i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI= + + + SPKI-SHA256-BASE64 + i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI= + + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf_and_ca.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf_and_ca.plist new file mode 100644 index 00000000..9a8c5551 --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf_and_ca.plist @@ -0,0 +1,33 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSPinnedCAIdentities + + + SPKI-SHA256-BASE64 + 5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w= + + + SPKI-SHA256-BASE64 + r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E= + + + NSPinnedLeafIdentities + + + SPKI-SHA256-BASE64 + i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI= + + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_empty_spki.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_empty_spki.plist new file mode 100644 index 00000000..a974f8be --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_empty_spki.plist @@ -0,0 +1,18 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSPinnedLeafIdentities + + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_invalid_spki.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_invalid_spki.plist new file mode 100644 index 00000000..187c60d7 --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_invalid_spki.plist @@ -0,0 +1,21 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSPinnedCAIdentities + + r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E= + + NSPinnedLeafIdentities + i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI= + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_without_spki.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_without_spki.plist new file mode 100644 index 00000000..81657f67 --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_without_spki.plist @@ -0,0 +1,15 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/OCSP_TestCA.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/OCSP_TestCA.cer new file mode 100644 index 00000000..9df4ea97 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/OCSP_TestCA.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist index 2f480cf6..6e642d73 100644 --- a/OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist @@ -1088,7 +1088,7 @@ CertDirectory si-20-sectrust-policies-data MajorTestName - iPhoneProfileSigning + iPhoneProfileApplicationSigning MinorTestName PositiveTest Policies @@ -2317,13 +2317,13 @@ Leaf googleapis Intermediates - GoogleInternetAuthorityG3 + GoogleTrustServicesCA101 Anchors GlobalSignRootCAR2 ExpectedResult 4 VerifyDate - 2018-04-14T19:00:00Z + 2019-11-14T20:00:00Z CertDirectory @@ -2515,7 +2515,7 @@ Properties SecPolicyName - openmarket.ess.apple.com + init.ess.apple.com Leaf @@ -2529,7 +2529,7 @@ ChainLength 3 VerifyDate - 2019-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2537,7 +2537,7 @@ MajorTestName Systemwide-Baseline MinorTestName - IDS-IST + IDS-PublicTrust Policies PolicyIdentifier @@ -2545,21 +2545,21 @@ Properties SecPolicyName - static.ess.apple.com + pds-init.ess.apple.com Leaf - ids_ist_static + ids_init_public Intermediates - AppleISTCA2G1 + ApplePublicServerRSA12-G1 Anchors - GeoTrustGlobalCA + AAACertificateServices ExpectedResult 4 ChainLength 3 VerifyDate - 2017-12-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2589,7 +2589,7 @@ ChainLength 3 VerifyDate - 2019-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2635,7 +2635,7 @@ Properties SecPolicyName - openmarket.ess.apple.com + init.ess.apple.com SecPolicyPolicyName IDS @@ -2651,11 +2651,13 @@ ChainLength 3 VerifyDate - 2019-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory si-20-sectrust-policies-data + BridgeOSDisable + MajorTestName Systemwide-PolicyName MinorTestName @@ -2667,21 +2669,21 @@ Properties SecPolicyName - static.ess.apple.com + pds-init.ess.apple.com SecPolicyPolicyName IDS Leaf - ids_ist_static + ids_init_public Intermediates - AppleISTCA2G1 + ApplePublicServerRSA12-G1 Anchors - GeoTrustGlobalCA + AAACertificateServices ExpectedResult 5 VerifyDate - 2017-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2713,7 +2715,7 @@ ChainLength 3 VerifyDate - 2019-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2791,19 +2793,19 @@ Properties SecPolicyName - static.ess.apple.com + init.ess.apple.com Leaf - ids_ist_static + ids_test Intermediates - AppleISTCA2G1 + TestAppleServerAuthentication Anchors - GeoTrustGlobalCA + TestAppleRootCA ExpectedResult 4 VerifyDate - 2017-04-08T20:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2858,6 +2860,38 @@ VerifyDate 2017-02-20T21:00:00Z + + CertDirectory + si-20-sectrust-policies-data + BridgeOSDisable + + MajorTestName + Systemwide-Both + MinorTestName + Precedence + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + identity.ess.apple.com + SecPolicyPolicyName + APN + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + VerifyDate + 2020-09-15T00:00:00Z + CertDirectory si-20-sectrust-policies-data @@ -3164,13 +3198,13 @@ Leaf googleapis Intermediates - GoogleInternetAuthorityG3 + GoogleTrustServicesCA101 Anchors GlobalSignRootCAR2 ExpectedResult 5 VerifyDate - 2018-04-14T19:00:00Z + 2019-11-14T20:00:00Z CertDirectory @@ -3192,13 +3226,13 @@ Leaf googleapis Intermediates - GoogleInternetAuthorityG3 + GoogleTrustServicesCA101 Anchors GlobalSignRootCAR2 ExpectedResult 4 VerifyDate - 2018-04-14T19:00:00Z + 2019-11-14T20:00:00Z CertDirectory @@ -3588,5 +3622,558 @@ ChainLength 3 + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + iPhoneProfileApplicationSigning + MinorTestName + PositiveTest + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.55 + + Leaf + test_iphone_distribution + Intermediates + TestAppleWWDR-G3 + Anchors + TestAppleRootCA + VerifyDate + 2020-03-01T20:00:00Z + ExpectedResult + 4 + ChainLength + 3 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + OCSP + MinorTestName + PositiveTest + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.66 + + Leaf + ocsp_responder + Anchors + OCSP_TestCA + VerifyDate + 2020-08-01T20:00:00Z + ExpectedResult + 4 + ChainLength + 2 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + OCSP + MinorTestName + NegativeTest-SubCA + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.66 + + Leaf + ocsp_subca + Anchors + OCSP_TestCA + VerifyDate + 2020-08-01T20:00:00Z + ExpectedResult + 5 + ChainLength + 2 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + OCSP + MinorTestName + NegativeTest-MissingEKU + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.66 + + Leaf + ocsp_missing_eku + Anchors + OCSP_TestCA + VerifyDate + 2020-08-01T20:00:00Z + ExpectedResult + 5 + ChainLength + 2 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + OCSP + MinorTestName + NegativeTest-MissingKU + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.66 + + Leaf + ocsp_missing_ku + Anchors + OCSP_TestCA + VerifyDate + 2020-08-01T20:00:00Z + ExpectedResult + 5 + ChainLength + 2 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckLeafSPKISHA256 + MinorTestName + leaf-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + +GxzfmXKLWfWePjBrbCey6zjhsMU/KtGFQExWAnFJeQ= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 4 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckLeafSPKISHA256 + MinorTestName + leaf-empty + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckLeafSPKISHA256 + MinorTestName + leaf-bad + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + intermediate-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + Yc/8PBtv5TPVDELtY0SUFd5zObsSVVzm7WbLz5eIpQM= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 4 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + intermediate-empty + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + CAspkiSHA256 + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + intermediate-bad + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + root-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + pmuYhKz98VG4gaGpUvi3y7CEl5+yJNGQ8/ARWg4FVnw= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 4 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + leaf-good-intermediate-good-root-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + +GxzfmXKLWfWePjBrbCey6zjhsMU/KtGFQExWAnFJeQ= + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + Yc/8PBtv5TPVDELtY0SUFd5zObsSVVzm7WbLz5eIpQM= + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + pmuYhKz98VG4gaGpUvi3y7CEl5+yJNGQ8/ARWg4FVnw= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 4 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + leaf-bad-intermediate-good-root-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + Yc/8PBtv5TPVDELtY0SUFd5zObsSVVzm7WbLz5eIpQM= + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + pmuYhKz98VG4gaGpUvi3y7CEl5+yJNGQ8/ARWg4FVnw= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + DemoContentSigning + MinorTestName + PositiveTest + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.23 + + Leaf + demo_content + Intermediates + AppleSystemIntegration2CA + Anchors + AppleRootCA + VerifyDate + 2017-02-18T00:19:45Z + ExpectedResult + 4 + ChainLength + 3 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + DemoContentSigning + MinorTestName + PositiveTest + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.23 + + Leaf + test_demo_content + Intermediates + AppleSystemIntegration2CA + Anchors + AppleRootCA + VerifyDate + 2017-02-18T00:19:45Z + ExpectedResult + 5 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + TestDemoContentSigning + MinorTestName + PositiveTest + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.27 + + Leaf + test_demo_content + Intermediates + AppleSystemIntegration2CA + Anchors + AppleRootCA + VerifyDate + 2017-02-18T00:19:45Z + ExpectedResult + 4 + ChainLength + 3 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + MacProvisioningProfile + MinorTestName + PositiveTest + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.40 + + Leaf + mac_provisioning_profile + Intermediates + AppleWWDR + Anchors + AppleRootCA + VerifyDate + 2015-09-01T00:19:45Z + ExpectedResult + 4 + ChainLength + 3 + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleWWDR-G3.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleWWDR-G3.cer new file mode 100644 index 00000000..212690f3 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleWWDR-G3.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/demo_content.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/demo_content.cer new file mode 100644 index 00000000..a99864c8 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/demo_content.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/googleapis.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/googleapis.cer index 14b15dc8..a3d82d6b 100644 Binary files a/OSX/shared_regressions/si-20-sectrust-policies-data/googleapis.cer and b/OSX/shared_regressions/si-20-sectrust-policies-data/googleapis.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/ids_init_public.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/ids_init_public.cer new file mode 100644 index 00000000..5cc09d67 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/ids_init_public.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/ids_test.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/ids_test.cer index c489eff1..d2fed0a4 100644 Binary files a/OSX/shared_regressions/si-20-sectrust-policies-data/ids_test.cer and b/OSX/shared_regressions/si-20-sectrust-policies-data/ids_test.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/mac_provisioning_profile.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/mac_provisioning_profile.cer new file mode 100644 index 00000000..4396f1b4 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/mac_provisioning_profile.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_eku.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_eku.cer new file mode 100644 index 00000000..e60f5cb2 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_eku.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_ku.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_ku.cer new file mode 100644 index 00000000..edadfed5 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_ku.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_responder.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_responder.cer new file mode 100644 index 00000000..582b1a08 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_responder.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_subca.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_subca.cer new file mode 100644 index 00000000..60b13d8d Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_subca.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/test_demo_content.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/test_demo_content.cer new file mode 100644 index 00000000..c219c652 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/test_demo_content.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/test_iPh0ne_distribution.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/test_iPh0ne_distribution.cer new file mode 100644 index 00000000..11967153 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/test_iPh0ne_distribution.cer differ diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/test_iphone_distribution.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/test_iphone_distribution.cer new file mode 100644 index 00000000..11967153 Binary files /dev/null and b/OSX/shared_regressions/si-20-sectrust-policies-data/test_iphone_distribution.cer differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_1.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_1.ber.der new file mode 100644 index 00000000..b9a358db Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_1.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_10.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_10.ber.der new file mode 100644 index 00000000..b480ecf8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_10.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_11.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_11.ber.der new file mode 100644 index 00000000..458131ec Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_11.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_12.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_12.ber.der new file mode 100644 index 00000000..a337950e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_12.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_13.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_13.ber.der new file mode 100644 index 00000000..69fb062a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_13.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_14.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_14.ber.der new file mode 100644 index 00000000..1054c895 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_14.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_15.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_15.ber.der new file mode 100644 index 00000000..b94dc39c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_15.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_16.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_16.ber.der new file mode 100644 index 00000000..2ac10552 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_16.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_17.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_17.ber.der new file mode 100644 index 00000000..1977d0a8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_17.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_18.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_18.ber.der new file mode 100644 index 00000000..0b6ff4c6 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_18.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_19.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_19.ber.der new file mode 100644 index 00000000..5ed715af Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_19.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_2.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_2.ber.der new file mode 100644 index 00000000..f61c432d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_2.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_20.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_20.ber.der new file mode 100644 index 00000000..29fe350f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_20.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_21.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_21.ber.der new file mode 100644 index 00000000..33121fdb Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_21.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_22.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_22.ber.der new file mode 100644 index 00000000..6ed11805 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_22.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_23.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_23.ber.der new file mode 100644 index 00000000..615819b4 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_23.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_24.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_24.ber.der new file mode 100644 index 00000000..6f29e9dc Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_24.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_25.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_25.ber.der new file mode 100644 index 00000000..3ca9237f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_25.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_26.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_26.ber.der new file mode 100644 index 00000000..9abcafbc Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_26.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_27.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_27.ber.der new file mode 100644 index 00000000..890264cd Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_27.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_28.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_28.ber.der new file mode 100644 index 00000000..054d5737 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_28.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_29.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_29.ber.der new file mode 100644 index 00000000..fe91e653 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_29.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_3.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_3.ber.der new file mode 100644 index 00000000..a5d529d3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_3.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_30.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_30.ber.der new file mode 100644 index 00000000..9fee10c1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_30.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_31.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_31.ber.der new file mode 100644 index 00000000..79a56663 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_31.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_32.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_32.ber.der new file mode 100644 index 00000000..ef7990e1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_32.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_33.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_33.ber.der new file mode 100644 index 00000000..f5ac274c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_33.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_34.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_34.ber.der new file mode 100644 index 00000000..773802bd Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_34.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_35.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_35.ber.der new file mode 100644 index 00000000..8ae6b212 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_35.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_4.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_4.ber.der new file mode 100644 index 00000000..d594bbb7 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_4.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_42.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_42.ber.der new file mode 100644 index 00000000..2353478c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_42.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_43.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_43.ber.der new file mode 100644 index 00000000..c208373b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_43.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_44.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_44.ber.der new file mode 100644 index 00000000..e783671c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_44.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_45.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_45.ber.der new file mode 100644 index 00000000..47265970 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_45.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_46.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_46.ber.der new file mode 100644 index 00000000..ba3e5173 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_46.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_47.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_47.ber.der new file mode 100644 index 00000000..1277f5d6 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_47.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_48.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_48.ber.der new file mode 100644 index 00000000..f82c45ff Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_48.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_49.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_49.ber.der new file mode 100644 index 00000000..a25e47bd Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_49.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_5.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_5.ber.der new file mode 100644 index 00000000..eb0601bf Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_5.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_50.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_50.ber.der new file mode 100644 index 00000000..c1e788f9 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_50.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_51.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_51.ber.der new file mode 100644 index 00000000..0faf6a83 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_51.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_52.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_52.ber.der new file mode 100644 index 00000000..03230ba9 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_52.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_53.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_53.ber.der new file mode 100644 index 00000000..41ca712a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_53.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_54.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_54.ber.der new file mode 100644 index 00000000..02995d22 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_54.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_55.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_55.ber.der new file mode 100644 index 00000000..572a4447 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_55.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_56.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_56.ber.der new file mode 100644 index 00000000..74371837 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_56.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_57.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_57.ber.der new file mode 100644 index 00000000..f86e7a58 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_57.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_58.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_58.ber.der new file mode 100644 index 00000000..5fd5ef92 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_58.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_59.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_59.ber.der new file mode 100644 index 00000000..ee13721d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_59.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_6.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_6.ber.der new file mode 100644 index 00000000..fdacf280 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_6.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_7.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_7.ber.der new file mode 100644 index 00000000..8c2fed06 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_7.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_8.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_8.ber.der new file mode 100644 index 00000000..e14543f8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_8.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_9.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_9.ber.der new file mode 100644 index 00000000..93f18133 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_length_fail_9.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_1.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_1.ber.der new file mode 100644 index 00000000..a4208a61 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_1.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_10.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_10.ber.der new file mode 100644 index 00000000..9db48710 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_10.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_12.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_12.ber.der new file mode 100644 index 00000000..206dbfd1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_12.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_13.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_13.ber.der new file mode 100644 index 00000000..0b8397bf Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_13.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_14.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_14.ber.der new file mode 100644 index 00000000..622388df Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_14.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_16.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_16.ber.der new file mode 100644 index 00000000..a8eed839 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_16.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_17.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_17.ber.der new file mode 100644 index 00000000..9990470d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_17.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_18.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_18.ber.der new file mode 100644 index 00000000..feadeb52 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_18.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_2.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_2.ber.der new file mode 100644 index 00000000..8d00829d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_2.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_20.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_20.ber.der new file mode 100644 index 00000000..d53cfb35 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_20.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_21.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_21.ber.der new file mode 100644 index 00000000..4816c535 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_21.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_23.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_23.ber.der new file mode 100644 index 00000000..006f4b44 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_23.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_24.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_24.ber.der new file mode 100644 index 00000000..bfa2b28f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_24.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_3.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_3.ber.der new file mode 100644 index 00000000..302b4a99 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_3.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_4.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_4.ber.der new file mode 100644 index 00000000..9472520a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_4.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_48.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_48.ber.der new file mode 100644 index 00000000..b90a2d17 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_48.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_49.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_49.ber.der new file mode 100644 index 00000000..1bb57ba0 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_49.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_5.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_5.ber.der new file mode 100644 index 00000000..7df7fd35 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_5.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_50.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_50.ber.der new file mode 100644 index 00000000..6cdee676 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_50.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_51.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_51.ber.der new file mode 100644 index 00000000..b362d49f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_51.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_6.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_6.ber.der new file mode 100644 index 00000000..c3ecd75c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_6.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_7.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_7.ber.der new file mode 100644 index 00000000..61473bf8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_7.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_8.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_8.ber.der new file mode 100644 index 00000000..dc9dee8f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_8.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_9.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_9.ber.der new file mode 100644 index 00000000..905d6a5f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_ber_tag_fail_9.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_long_TaggedType.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_long_TaggedType.der new file mode 100644 index 00000000..39a7d767 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_long_TaggedType.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_long_octet.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_long_octet.der new file mode 100644 index 00000000..4de21b68 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_long_octet.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_short_TaggedType.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_short_TaggedType.der new file mode 100644 index 00000000..fcc44b33 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_short_TaggedType.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_short_octet.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_short_octet.der new file mode 100644 index 00000000..9b0ef1cb Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_too_short_octet.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_wrong_Tag.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_wrong_Tag.der new file mode 100644 index 00000000..0b9ef00f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_wrong_Tag.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_wrong_TaggedType.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_wrong_TaggedType.der new file mode 100644 index 00000000..f00ed75e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_definite_wrong_TaggedType.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_eoc_fail_1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_eoc_fail_1.der new file mode 100644 index 00000000..251f671c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_eoc_fail_1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_eoc_fail_2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_eoc_fail_2.der new file mode 100644 index 00000000..56adf342 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_eoc_fail_2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_eoc_fail_3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_eoc_fail_3.der new file mode 100644 index 00000000..9256d94f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_eoc_fail_3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_too_long_octet.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_too_long_octet.der new file mode 100644 index 00000000..9e7954c8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_too_long_octet.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_too_short_octet.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_too_short_octet.der new file mode 100644 index 00000000..8cbd8337 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_too_short_octet.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_wrong_TaggedType.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_wrong_TaggedType.der new file mode 100644 index 00000000..400fe18c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_wrong_TaggedType.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_wrong_cons_octet.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_wrong_cons_octet.der new file mode 100644 index 00000000..ce3a9e52 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_wrong_cons_octet.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_wrong_octet.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_wrong_octet.der new file mode 100644 index 00000000..12e7d6da Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_content_indefinite_wrong_octet.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_1.der new file mode 100644 index 00000000..da4563d2 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_10.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_10.der new file mode 100644 index 00000000..2da0e4fd Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_10.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_11.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_11.der new file mode 100644 index 00000000..2dad877e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_11.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_12.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_12.der new file mode 100644 index 00000000..283aac61 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_12.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_13.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_13.der new file mode 100644 index 00000000..8ebc0f11 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_13.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_14.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_14.der new file mode 100644 index 00000000..df5fc04d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_14.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_15.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_15.der new file mode 100644 index 00000000..b6547ab5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_15.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_16.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_16.der new file mode 100644 index 00000000..6c2a00b1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_16.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_17.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_17.der new file mode 100644 index 00000000..2d870d3b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_17.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_18.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_18.der new file mode 100644 index 00000000..6ff1faac Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_18.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_19.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_19.der new file mode 100644 index 00000000..a39f5680 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_19.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_2.der new file mode 100644 index 00000000..05bfcbc3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_20.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_20.der new file mode 100644 index 00000000..4324e939 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_20.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_21.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_21.der new file mode 100644 index 00000000..4a2891e9 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_21.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_22.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_22.der new file mode 100644 index 00000000..3e52ac8d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_22.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_23.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_23.der new file mode 100644 index 00000000..96409d7f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_23.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_24.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_24.der new file mode 100644 index 00000000..a2ebc820 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_24.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_25.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_25.der new file mode 100644 index 00000000..18a837f4 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_25.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_26.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_26.der new file mode 100644 index 00000000..43b8d710 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_26.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_27.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_27.der new file mode 100644 index 00000000..95e07344 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_27.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_28.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_28.der new file mode 100644 index 00000000..5c677f9f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_28.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_29.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_29.der new file mode 100644 index 00000000..094b7a94 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_29.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_3!.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_3!.der new file mode 100644 index 00000000..deeadd88 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_3!.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_3.der new file mode 100644 index 00000000..27901008 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_30.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_30.der new file mode 100644 index 00000000..37508c56 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_30.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_31.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_31.der new file mode 100644 index 00000000..d31fd210 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_31.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_32.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_32.der new file mode 100644 index 00000000..94c94656 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_32.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_33.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_33.der new file mode 100644 index 00000000..c7e39374 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_33.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_34.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_34.der new file mode 100644 index 00000000..a169c112 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_34.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_35.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_35.der new file mode 100644 index 00000000..08260679 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_35.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_36.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_36.der new file mode 100644 index 00000000..e637e6c0 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_36.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_37.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_37.der new file mode 100644 index 00000000..bed6068f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_37.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_38.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_38.der new file mode 100644 index 00000000..0b22de92 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_38.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_39.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_39.der new file mode 100644 index 00000000..c75c85d5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_39.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_4.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_4.der new file mode 100644 index 00000000..8be5fb7b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_4.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_40.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_40.der new file mode 100644 index 00000000..fb574c9c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_40.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_41.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_41.der new file mode 100644 index 00000000..94bb59e2 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_41.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_42.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_42.der new file mode 100644 index 00000000..c12d4cdd Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_42.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_43.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_43.der new file mode 100644 index 00000000..3db7813b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_43.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_44.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_44.der new file mode 100644 index 00000000..9d0500ae Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_44.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_45.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_45.der new file mode 100644 index 00000000..4c32efea Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_45.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_46.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_46.der new file mode 100644 index 00000000..25283c08 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_46.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_47.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_47.der new file mode 100644 index 00000000..d6d85df2 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_47.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_48.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_48.der new file mode 100644 index 00000000..9e9c034e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_48.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_49.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_49.der new file mode 100644 index 00000000..ac94539b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_49.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_5.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_5.der new file mode 100644 index 00000000..a7a5f502 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_5.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_50.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_50.der new file mode 100644 index 00000000..92e247c8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_50.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_51.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_51.der new file mode 100644 index 00000000..9938f5f5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_51.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_52.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_52.der new file mode 100644 index 00000000..ef7f0c66 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_52.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_53.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_53.der new file mode 100644 index 00000000..ed9875cb Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_53.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_54.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_54.der new file mode 100644 index 00000000..c4c14e85 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_54.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_55.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_55.der new file mode 100644 index 00000000..2f0f9a47 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_55.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_56.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_56.der new file mode 100644 index 00000000..d32c1f28 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_56.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_57.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_57.der new file mode 100644 index 00000000..2ec511a8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_57.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_6.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_6.der new file mode 100644 index 00000000..1bbdfe74 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_6.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_7.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_7.der new file mode 100644 index 00000000..a6f4615f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_7.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_8.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_8.der new file mode 100644 index 00000000..f9706a59 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_8.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_9.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_9.der new file mode 100644 index 00000000..1bd529da Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_length_fail_9.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_1.der new file mode 100644 index 00000000..0a4b36cb Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_10.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_10.der new file mode 100644 index 00000000..3748dedc Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_10.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_12.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_12.der new file mode 100644 index 00000000..a48f01e4 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_12.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_13.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_13.der new file mode 100644 index 00000000..76fbb7d2 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_13.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_14.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_14.der new file mode 100644 index 00000000..1940d22a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_14.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_15.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_15.der new file mode 100644 index 00000000..38ded8f1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_15.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_16.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_16.der new file mode 100644 index 00000000..651d6f5e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_16.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_17.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_17.der new file mode 100644 index 00000000..37368f8f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_17.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_18.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_18.der new file mode 100644 index 00000000..564150ec Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_18.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_19.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_19.der new file mode 100644 index 00000000..d0ff853b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_19.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_2.der new file mode 100644 index 00000000..1f3255e2 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_20.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_20.der new file mode 100644 index 00000000..9c8e34a5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_20.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_21.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_21.der new file mode 100644 index 00000000..17aae1f1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_21.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_22.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_22.der new file mode 100644 index 00000000..1b6fa700 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_22.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_3.der new file mode 100644 index 00000000..b6295621 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_4.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_4.der new file mode 100644 index 00000000..db57c99f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_4.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_5.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_5.der new file mode 100644 index 00000000..658c6bac Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_5.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_6.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_6.der new file mode 100644 index 00000000..34be3106 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_6.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_7.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_7.der new file mode 100644 index 00000000..c1af0bf8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_7.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_8.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_8.der new file mode 100644 index 00000000..a39f5680 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_8.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_9.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_9.der new file mode 100644 index 00000000..4324e939 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attached_der_tag_fail_9.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_1.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_1.ber.der new file mode 100644 index 00000000..36eb42d5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_1.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_10.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_10.ber.der new file mode 100644 index 00000000..dbbec430 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_10.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_12.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_12.ber.der new file mode 100644 index 00000000..3c656f07 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_12.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_13.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_13.ber.der new file mode 100644 index 00000000..45d17b9f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_13.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_14.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_14.ber.der new file mode 100644 index 00000000..3df5f984 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_14.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_15.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_15.ber.der new file mode 100644 index 00000000..8ceb4a85 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_15.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_16.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_16.ber.der new file mode 100644 index 00000000..7fa4b5d4 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_16.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_17.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_17.ber.der new file mode 100644 index 00000000..e0bb0de3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_17.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_18.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_18.ber.der new file mode 100644 index 00000000..77bdaca9 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_18.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_19.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_19.ber.der new file mode 100644 index 00000000..5d737468 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_19.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_2.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_2.ber.der new file mode 100644 index 00000000..823fc444 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_2.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_20.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_20.ber.der new file mode 100644 index 00000000..7e2260a5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_20.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_21.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_21.ber.der new file mode 100644 index 00000000..ed8f4181 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_21.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_22.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_22.ber.der new file mode 100644 index 00000000..7d3806a8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_22.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_23.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_23.ber.der new file mode 100644 index 00000000..75af8ced Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_23.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_24.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_24.ber.der new file mode 100644 index 00000000..5eda32a6 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_24.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_25.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_25.ber.der new file mode 100644 index 00000000..536cf754 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_25.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_26.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_26.ber.der new file mode 100644 index 00000000..b8b8def6 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_26.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_27.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_27.ber.der new file mode 100644 index 00000000..2a2d7b66 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_27.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_3.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_3.ber.der new file mode 100644 index 00000000..afda6b2c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_3.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_4.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_4.ber.der new file mode 100644 index 00000000..7d6df66b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_4.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_5.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_5.ber.der new file mode 100644 index 00000000..b7fad495 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_5.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_6.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_6.ber.der new file mode 100644 index 00000000..363ae8b8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_6.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_7.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_7.ber.der new file mode 100644 index 00000000..b7a7123c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_7.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_8.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_8.ber.der new file mode 100644 index 00000000..b05e2d90 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_8.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_9.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_9.ber.der new file mode 100644 index 00000000..4071da3d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_length_fail_9.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_10.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_10.ber.der new file mode 100644 index 00000000..86bc448c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_10.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_11.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_11.ber.der new file mode 100644 index 00000000..7ac45185 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_11.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_12.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_12.ber.der new file mode 100644 index 00000000..9607907c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_12.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_13.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_13.ber.der new file mode 100644 index 00000000..05419c4b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_13.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_14.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_14.ber.der new file mode 100644 index 00000000..282363b1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_14.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_2.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_2.ber.der new file mode 100644 index 00000000..bee8b4d3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_2.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_3.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_3.ber.der new file mode 100644 index 00000000..a275d6a7 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_3.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_4.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_4.ber.der new file mode 100644 index 00000000..6d9954aa Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_4.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_6.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_6.ber.der new file mode 100644 index 00000000..a4f24b33 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_6.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_7.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_7.ber.der new file mode 100644 index 00000000..afea4d57 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_7.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_8.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_8.ber.der new file mode 100644 index 00000000..ae6c3c4c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/attrs_ber_tag_fail_8.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_attached_data_bad_len.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_attached_data_bad_len.der new file mode 100644 index 00000000..90b20fa3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_attached_data_bad_len.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eat_ber_recursion.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eat_ber_recursion.der new file mode 100644 index 00000000..4978ef49 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eat_ber_recursion.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_0.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_0.der new file mode 100644 index 00000000..3cae184e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_0.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_1.der new file mode 100644 index 00000000..7267c941 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_2.der new file mode 100644 index 00000000..43f21b4f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_3.der new file mode 100644 index 00000000..ea3f9ca2 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_4.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_4.der new file mode 100644 index 00000000..a7aa1008 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_eoc_fail_4.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_indefinite_certs_bad_eoc.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_indefinite_certs_bad_eoc.der new file mode 100644 index 00000000..208df372 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_indefinite_certs_bad_eoc.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_indefinite_signer_info_bad_eoc.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_indefinite_signer_info_bad_eoc.der new file mode 100644 index 00000000..fe17eb37 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_indefinite_signer_info_bad_eoc.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_length_fail_1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_length_fail_1.der new file mode 100644 index 00000000..d1c655b5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_length_fail_1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_length_fail_2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_length_fail_2.der new file mode 100644 index 00000000..9018ced3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_length_fail_2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error1.der new file mode 100644 index 00000000..2996a245 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error2.der new file mode 100644 index 00000000..fb304c3d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error3.der new file mode 100644 index 00000000..c1f87223 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error4.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error4.der new file mode 100644 index 00000000..3179e016 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_length_error4.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_tag_error1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_tag_error1.der new file mode 100644 index 00000000..4b8be5ed Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_tag_error1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_tag_error2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_tag_error2.der new file mode 100644 index 00000000..4f794bdc Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_tag_error2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_tag_error3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_tag_error3.der new file mode 100644 index 00000000..fe5145a7 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/ber_sigd_tag_error3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/cinfo_envd.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/cinfo_envd.der new file mode 100644 index 00000000..a3b9e35a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/cinfo_envd.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error1.der new file mode 100644 index 00000000..2a844e87 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error1.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error10.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error10.der new file mode 100644 index 00000000..499abcac --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error10.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error11.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error11.der new file mode 100644 index 00000000..dd4d53bf --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error11.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error12.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error12.der new file mode 100644 index 00000000..37b0a042 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error12.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error14.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error14.der new file mode 100644 index 00000000..6a7fc9a2 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error14.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error2.der new file mode 100644 index 00000000..cfc32ddf --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error2.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error3.der new file mode 100644 index 00000000..278206c0 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error3.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error4.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error4.der new file mode 100644 index 00000000..c02a0897 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error4.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error5.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error5.der new file mode 100644 index 00000000..0d1a9904 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error5.der @@ -0,0 +1,2 @@ +0*H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error6.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error6.der new file mode 100644 index 00000000..181eef67 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error6.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error7.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error7.der new file mode 100644 index 00000000..89a87ce0 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error7.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error8.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error8.der new file mode 100644 index 00000000..8db4dc70 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error8.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error9.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error9.der new file mode 100644 index 00000000..65764434 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_length_error9.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error1.der new file mode 100644 index 00000000..167529a0 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error1.der @@ -0,0 +1,2 @@ +1 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error2.der new file mode 100644 index 00000000..80fdb18b --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error2.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error3.der new file mode 100644 index 00000000..bad747e9 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error3.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error4.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error4.der new file mode 100644 index 00000000..6738e7ff --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/data_tag_error4.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_1.der new file mode 100644 index 00000000..92374769 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_10.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_10.der new file mode 100644 index 00000000..5457b1e3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_10.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_11.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_11.der new file mode 100644 index 00000000..0567325a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_11.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_12.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_12.der new file mode 100644 index 00000000..73581204 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_12.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_13.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_13.der new file mode 100644 index 00000000..0d35f18e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_13.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_14.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_14.der new file mode 100644 index 00000000..7d63d37f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_14.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_15.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_15.der new file mode 100644 index 00000000..424fdf11 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_15.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_16.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_16.der new file mode 100644 index 00000000..cd09c138 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_16.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_17.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_17.der new file mode 100644 index 00000000..ecfa996d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_17.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_18.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_18.der new file mode 100644 index 00000000..1396d288 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_18.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_19.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_19.der new file mode 100644 index 00000000..fe4e07aa Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_19.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_2.der new file mode 100644 index 00000000..9edb95dd Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_20.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_20.der new file mode 100644 index 00000000..c346a97e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_20.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_25.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_25.der new file mode 100644 index 00000000..6dc826b6 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_25.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_26.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_26.der new file mode 100644 index 00000000..ba833965 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_26.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_27.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_27.der new file mode 100644 index 00000000..8f8bf553 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_27.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_28.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_28.der new file mode 100644 index 00000000..da675018 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_28.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_29.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_29.der new file mode 100644 index 00000000..ad9d92d2 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_29.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_3.der new file mode 100644 index 00000000..6a2419e6 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_30.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_30.der new file mode 100644 index 00000000..51750330 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_30.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_31.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_31.der new file mode 100644 index 00000000..67480fc2 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_31.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_32.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_32.der new file mode 100644 index 00000000..16ea819c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_32.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_33.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_33.der new file mode 100644 index 00000000..11d74460 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_33.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_34.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_34.der new file mode 100644 index 00000000..422d70c6 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_34.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_35.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_35.der new file mode 100644 index 00000000..64dd86c6 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_35.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_36.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_36.der new file mode 100644 index 00000000..c1ebaec7 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_36.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_37.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_37.der new file mode 100644 index 00000000..cca33dd0 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_37.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_38.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_38.der new file mode 100644 index 00000000..57701833 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_38.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_39.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_39.der new file mode 100644 index 00000000..a8a6dfd5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_39.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_4.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_4.der new file mode 100644 index 00000000..f01e9946 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_4.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_40.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_40.der new file mode 100644 index 00000000..7075078f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_40.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_41.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_41.der new file mode 100644 index 00000000..d7467286 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_41.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_42.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_42.der new file mode 100644 index 00000000..1b4dbc1e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_42.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_43.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_43.der new file mode 100644 index 00000000..3e2dcfbe Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_43.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_44.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_44.der new file mode 100644 index 00000000..abdf4e0a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_44.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_45.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_45.der new file mode 100644 index 00000000..959a73f8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_45.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_5.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_5.der new file mode 100644 index 00000000..f1f3fe6e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_5.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_50.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_50.der new file mode 100644 index 00000000..ffcbed02 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_50.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_51.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_51.der new file mode 100644 index 00000000..2a6f9c28 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_51.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_52.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_52.der new file mode 100644 index 00000000..7234a396 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_52.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_53.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_53.der new file mode 100644 index 00000000..33c91eb4 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_53.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_54.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_54.der new file mode 100644 index 00000000..423c2a3f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_54.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_55.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_55.der new file mode 100644 index 00000000..871e9c4e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_55.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_56.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_56.der new file mode 100644 index 00000000..9ce208e6 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_56.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_57.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_57.der new file mode 100644 index 00000000..90892e16 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_57.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_58.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_58.der new file mode 100644 index 00000000..5b44a987 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_58.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_59.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_59.der new file mode 100644 index 00000000..ef5bb8f3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_59.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_6.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_6.der new file mode 100644 index 00000000..8a0dbcbc Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_6.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_60.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_60.der new file mode 100644 index 00000000..90e7adfb Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_60.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_61.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_61.der new file mode 100644 index 00000000..388d16ee Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_61.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_62.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_62.der new file mode 100644 index 00000000..cdd8d50e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_62.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_63.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_63.der new file mode 100644 index 00000000..7557b616 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_63.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_7.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_7.der new file mode 100644 index 00000000..9d2c57e7 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_7.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_8.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_8.der new file mode 100644 index 00000000..65c37304 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_8.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_9.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_9.der new file mode 100644 index 00000000..3b43c4fd Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_length_fail_9.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_1.der new file mode 100644 index 00000000..35ca2ac5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_10.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_10.der new file mode 100644 index 00000000..b1251947 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_10.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_11.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_11.der new file mode 100644 index 00000000..e156fe5a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_11.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_12.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_12.der new file mode 100644 index 00000000..be050a6d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_12.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_13.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_13.der new file mode 100644 index 00000000..8017afc1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_13.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_14.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_14.der new file mode 100644 index 00000000..5276ae7b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_14.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_17.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_17.der new file mode 100644 index 00000000..28b3c0c9 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_17.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_18.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_18.der new file mode 100644 index 00000000..3d686ad9 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_18.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_19.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_19.der new file mode 100644 index 00000000..12e45925 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_19.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_2.der new file mode 100644 index 00000000..d5f7fda8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_20.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_20.der new file mode 100644 index 00000000..abdcb65a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_20.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_22.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_22.der new file mode 100644 index 00000000..51e91b40 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_22.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_3.der new file mode 100644 index 00000000..daa7678a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_4.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_4.der new file mode 100644 index 00000000..4286c305 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_4.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_5.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_5.der new file mode 100644 index 00000000..2efeed4e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_5.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_6.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_6.der new file mode 100644 index 00000000..c462efd3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_6.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_9.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_9.der new file mode 100644 index 00000000..bab4e962 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/der_tag_fail_9.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/not_enough_data_one.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/not_enough_data_one.der new file mode 100644 index 00000000..ed14d786 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/not_enough_data_one.der @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/not_enough_data_three.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/not_enough_data_three.der new file mode 100644 index 00000000..013d46f1 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/not_enough_data_three.der @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/not_enough_data_two.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/not_enough_data_two.der new file mode 100644 index 00000000..daf83bb8 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/not_enough_data_two.der @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/rdar_76758936_test_case.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/rdar_76758936_test_case.der new file mode 100644 index 00000000..eb873f45 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/rdar_76758936_test_case.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error1.der new file mode 100644 index 00000000..d6616b4b Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error10.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error10.der new file mode 100644 index 00000000..aac84f75 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error10.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error2.der new file mode 100644 index 00000000..456d69ae Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error3.der new file mode 100644 index 00000000..55a46102 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error4.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error4.der new file mode 100644 index 00000000..66d68851 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error4.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error5.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error5.der new file mode 100644 index 00000000..e1a3e800 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error5.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error6.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error6.der new file mode 100644 index 00000000..7f352c1d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error6.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error7.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error7.der new file mode 100644 index 00000000..35a9cb46 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error7.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error8.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error8.der new file mode 100644 index 00000000..2ac23109 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error8.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error9.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error9.der new file mode 100644 index 00000000..5143f199 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_length_error9.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_tag_error1.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_tag_error1.der new file mode 100644 index 00000000..db380b58 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_tag_error1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_tag_error2.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_tag_error2.der new file mode 100644 index 00000000..8028315e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_tag_error2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_tag_error3.der b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_tag_error3.der new file mode 100644 index 00000000..e460c725 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseFailureCMS/sigd_tag_error3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/algId_any_params.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/algId_any_params.der new file mode 100644 index 00000000..9ad14da8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/algId_any_params.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/ber_attached_data.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/ber_attached_data.der new file mode 100644 index 00000000..6579120d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/ber_attached_data.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/ber_indefinite_certs.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/ber_indefinite_certs.der new file mode 100644 index 00000000..5f726da5 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/ber_indefinite_certs.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/ber_indefinite_signer_info.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/ber_indefinite_signer_info.der new file mode 100644 index 00000000..c1b9b96d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/ber_indefinite_signer_info.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo0.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo0.der new file mode 100644 index 00000000..26d35155 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo0.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo1.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo1.der new file mode 100644 index 00000000..1abcbc6e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo2.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo2.der new file mode 100644 index 00000000..8f2fcb78 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo3.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo3.der new file mode 100644 index 00000000..8f2fcb78 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo4.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo4.der new file mode 100644 index 00000000..b9118243 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo4.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo5.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo5.der new file mode 100644 index 00000000..979bc2dd Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo5.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_certs_only.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_certs_only.der new file mode 100644 index 00000000..afef4908 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_certs_only.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_data.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_data.der new file mode 100644 index 00000000..26d35155 --- /dev/null +++ b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_data.der @@ -0,0 +1,2 @@ +0 *H 5r,>}Vo˘[ÁrSKH42p5/ KP`U.ucO@/ok99c/4edz"Xr-O"Jzv{/s qJec”ʎ +Q)޿ʵBW<>6FR\ \ No newline at end of file diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_data_attached.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_data_attached.der new file mode 100644 index 00000000..1abcbc6e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_data_attached.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_definite_length.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_definite_length.der new file mode 100644 index 00000000..6723e236 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_definite_length.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_no_certs_v1.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_no_certs_v1.der new file mode 100644 index 00000000..64a6eb74 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_no_certs_v1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_no_certs_v3.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_no_certs_v3.der new file mode 100644 index 00000000..316cff1f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_no_certs_v3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sha256.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sha256.der new file mode 100644 index 00000000..7dcdbcec Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sha256.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sha256_attached.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sha256_attached.der new file mode 100644 index 00000000..ef640d22 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sha256_attached.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sha256_attrs.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sha256_attrs.der new file mode 100644 index 00000000..59ec93dc Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sha256_attrs.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sigd.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sigd.der new file mode 100644 index 00000000..b9118243 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/cinfo_sigd_sigd.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/config_profile.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/config_profile.der new file mode 100644 index 00000000..52c335d1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/config_profile.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/dev_id_signature.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/dev_id_signature.der new file mode 100644 index 00000000..aa4edb65 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/dev_id_signature.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/empty_bitstring.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/empty_bitstring.der new file mode 100644 index 00000000..f3e2632d Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/empty_bitstring.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/encapsulated_missing_attrs.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/encapsulated_missing_attrs.der new file mode 100644 index 00000000..22b564a8 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/encapsulated_missing_attrs.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/fake_crlset_entry.ber.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/fake_crlset_entry.ber.der new file mode 100644 index 00000000..2c755ad4 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/fake_crlset_entry.ber.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/md5_attr_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/md5_attr_signed.der new file mode 100644 index 00000000..c0009aa0 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/md5_attr_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/md5_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/md5_signed.der new file mode 100644 index 00000000..3d8c6276 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/md5_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/multiple_signers.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/multiple_signers.der new file mode 100644 index 00000000..2d689a47 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/multiple_signers.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_attr_ec.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_attr_ec.der new file mode 100644 index 00000000..3d7cba03 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_attr_ec.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_attr_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_attr_signed.der new file mode 100644 index 00000000..0b0010be Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_attr_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_signed.der new file mode 100644 index 00000000..d6e5de2a Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_signed_ec.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_signed_ec.der new file mode 100644 index 00000000..1031f32f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha1_signed_ec.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_attr_ec.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_attr_ec.der new file mode 100644 index 00000000..d47212fd Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_attr_ec.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_attr_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_attr_signed.der new file mode 100644 index 00000000..bc6d9b2f Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_attr_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_signed.der new file mode 100644 index 00000000..8e6218f7 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_signed_ec.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_signed_ec.der new file mode 100644 index 00000000..9a414281 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha256_signed_ec.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_attr_ec.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_attr_ec.der new file mode 100644 index 00000000..215dceda Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_attr_ec.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_attr_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_attr_signed.der new file mode 100644 index 00000000..6c1d3815 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_attr_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_signed.der new file mode 100644 index 00000000..234411b3 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_signed_ec.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_signed_ec.der new file mode 100644 index 00000000..d32979ba Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha384_signed_ec.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_attr_ec.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_attr_ec.der new file mode 100644 index 00000000..e27e8793 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_attr_ec.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_attr_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_attr_signed.der new file mode 100644 index 00000000..e0248bdb Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_attr_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_signed.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_signed.der new file mode 100644 index 00000000..7ac510e9 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_signed.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_signed_ec.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_signed_ec.der new file mode 100644 index 00000000..53230e18 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sha512_signed_ec.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd1.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd1.der new file mode 100644 index 00000000..c2fed708 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd1.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd2.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd2.der new file mode 100644 index 00000000..cdf63bf2 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd2.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd3.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd3.der new file mode 100644 index 00000000..88df29c1 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd3.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd4.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd4.der new file mode 100644 index 00000000..d6329d43 Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd4.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd5.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd5.der new file mode 100644 index 00000000..37675e4e Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd5.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd6.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd6.der new file mode 100644 index 00000000..38fa048c Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd6.der differ diff --git a/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd7.der b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd7.der new file mode 100644 index 00000000..26ec50ab Binary files /dev/null and b/OSX/shared_regressions/si-27-cms-parse/ParseSuccessCMS/sigd7.der differ diff --git a/OSX/shared_regressions/si-44-seckey-aks.m b/OSX/shared_regressions/si-44-seckey-aks.m index 048929d5..cd8a2a46 100644 --- a/OSX/shared_regressions/si-44-seckey-aks.m +++ b/OSX/shared_regressions/si-44-seckey-aks.m @@ -8,17 +8,13 @@ #import #import #import -#if !TARGET_OS_OSX #import "MobileGestalt.h" -#else -#import -#endif #import "shared_regressions.h" -static id generateKey(id keyType, CFStringRef protection, BOOL noACL) { +static id generateKey(id keyType, CFStringRef protection, BOOL withACL) { id accessControl; - if (noACL) { + if (!withACL) { accessControl = CFBridgingRelease(SecAccessControlCreate(kCFAllocatorDefault, NULL)); SecAccessControlSetProtection((__bridge SecAccessControlRef)accessControl, protection, NULL); } else { @@ -41,9 +37,9 @@ static void secKeySepTest(BOOL testPKA) { } else { keyTypes = @[(id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeyTypeSecureEnclaveAttestation]; } - BOOL noACL = YES; + BOOL withACL = NO; for (id keyType in keyTypes) { - id privateKey = generateKey((id)keyType, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, (noACL = !noACL)); + id privateKey = generateKey((id)keyType, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, (withACL = !withACL)); ok(privateKey, "failed to create key '%@'", keyType); id publicKey = (__bridge_transfer id)SecKeyCopyPublicKey((SecKeyRef)privateKey); @@ -92,16 +88,13 @@ static void secKeySepTest(BOOL testPKA) { } } -static void attestationTest(CFStringRef protection, BOOL noACL) { +static void attestationTest(CFStringRef protection, BOOL withACL) { NSError *error; - id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection, noACL); - id uik = generateKey((id)kSecAttrKeyTypeSecureEnclaveAttestation, protection, noACL); + id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection, withACL); + id uik = generateKey((id)kSecAttrKeyTypeSecureEnclaveAttestation, protection, withACL); id sik = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeSIK, (void *)&error)); ok(sik != nil, "get SIK key: %@", error); - id pubSIK = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sik)); - ok(pubSIK != nil, "get SIK pubkey"); - error = nil; NSData *attSIKPlain = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)uik, (void *)&error)); ok(attSIKPlain != nil, "SIK attesting UIK, no nonce: %@", error); @@ -120,70 +113,82 @@ static void attestationTest(CFStringRef protection, BOOL noACL) { ok(SecKeySetParameter((__bridge SecKeyRef)uik, kSecKeyParameterSETokenAttestationNonce, (__bridge CFPropertyListRef)nonce, (void *)&error), "Set nonce to UIK: %@", error); NSData *attUIKNonce = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)uik, (__bridge SecKeyRef)privKey, (void *)&error)); ok(attUIKNonce != nil, "SIK attesting UIK, with nonce: %@", error); +} + +static void sysKeyAttestationTest(CFStringRef protection, BOOL withACL, const char *name, SecKeyAttestationKeyType committed, SecKeyAttestationKeyType proposed, BOOL canAttest) { + NSError *error; + id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection, withACL); + id sik = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeSIK, (void *)&error)); + ok(sik != nil, "get SIK key: %@", error); + + id pubSIK = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sik)); + ok(pubSIK != nil, "get SIK pubkey"); + + id sysKeyC = CFBridgingRelease(SecKeyCopyAttestationKey(committed, (void *)&error)); + if (sysKeyC == nil) { + diag("skipping attestation test, platform does not support key %s-committed", name); + return; + } error = nil; - id sysUikC = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeUIKCommitted, (void *)&error)); - if (sysUikC == nil) { - // Platform does not support system UIK, so just fake test rounds to avoid testplan counting failures. - for (int i = 0; i < 19; i++) { - ok(true); - } - } else { - ok(sysUikC != nil, "get UIK-committed key, error: %@", error); + id sysKeyP = CFBridgingRelease(SecKeyCopyAttestationKey(proposed, (void *)&error)); + ok(sysKeyP != nil, "unable to get proposed key, but successfully got committed key"); + + if (canAttest) { error = nil; - id sysUikP = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeUIKProposed, (void *)&error)); - ok(sysUikP != nil, "get UIK-proposed key: %@", error); + NSData *attSysKeyC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyC, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyC != nil, "%s-committed attesting privKey: %@", name, error); error = nil; - NSData *attUIKC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKC != nil, "Sys-UIK-committed attesting privKey: %@", error); - - error = nil; - NSData *attUIKP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKP != nil, "Sys-UIK-proposed attesting privKey: %@", error); - - id pubUIKP = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikP)); - ok(pubUIKP != nil, "Sys-UIK-proposed copy public key"); - id pubUIKC = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikC)); - ok(pubUIKC != nil, "Sys-UIK-proposed copy public key"); - - BOOL res = SecKeyControlLifetime((__bridge SecKeyRef)sysUikC, kSecKeyControlLifetimeTypeBump, (void *)&error); - ok(res, "bumping sys-uik: %@", error); - - error = nil; - NSData *attUIKCN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKCN != nil, "Sys-UIK-committed attesting privKey: %@", error); - - error = nil; - NSData *attUIKPN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKPN != nil, "Sys-UIK-proposed attesting privKey: %@", error); - - id pubUIKPN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikP)); - ok(pubUIKPN != nil, "Sys-UIK-proposed copy public key"); - ok(![pubUIKPN isEqual:pubUIKC], "Sys-UIK proposed and committed differ after bump"); - - res = SecKeyControlLifetime((__bridge SecKeyRef)sysUikP, kSecKeyControlLifetimeTypeCommit, (void *)&error); - ok(res, "committing sys-uik: %@", error); - - error = nil; - NSData *attUIKCNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKCNN != nil, "Sys-UIK-committed attesting privKey: %@", error); - - error = nil; - NSData *attUIKPNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKPNN != nil, "Sys-UIK-proposed attesting privKey: %@", error); - - id pubUIKCN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikC)); - ok(pubUIKCN != nil, "Sys-UIK-committed copy public key"); - ok([pubUIKPN isEqual:pubUIKCN], "Sys-UIK proposed and committed same after commit"); - - // Attest system-UIK with SIK - NSData *attSIKUIKP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysUikP, (void *)&error)); - ok(attSIKUIKP != nil, "SIK attesting Sys-UIK-proposed, error: %@", error); - - NSData *attSIKUIKC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysUikC, (void *)&error)); - ok(attSIKUIKC != nil, "SIK attesting Sys-UIK-committed, error: %@", error); + NSData *attSysKeyP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyP, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyP != nil, "%s-proposed attesting privKey: %@", name, error); } + + id pubSysKeyP = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysKeyP)); + ok(pubSysKeyP != nil, "%s-proposed copy public key", name); + id pubSysKeyC = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysKeyC)); + ok(pubSysKeyC != nil, "%s-committed copy public key", name); + + BOOL res = SecKeyControlLifetime((__bridge SecKeyRef)sysKeyC, kSecKeyControlLifetimeTypeBump, (void *)&error); + ok(res, "bumping %s: %@", name, error); + + if (canAttest) { + error = nil; + NSData *attSysKeyCN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyC, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyCN != nil, "%s-committed attesting privKey: %@", name, error); + + error = nil; + NSData *attSysKeyPN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyP, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyPN != nil, "%s-proposed attesting privKey: %@", name, error); + } + + id pubSysKeyPN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysKeyP)); + ok(pubSysKeyPN != nil, "%s-proposed copy public key", name); + ok(![pubSysKeyPN isEqual:pubSysKeyC], "%s proposed and committed differ after bump", name); + + res = SecKeyControlLifetime((__bridge SecKeyRef)sysKeyP, kSecKeyControlLifetimeTypeCommit, (void *)&error); + ok(res, "committing %s: %@", name, error); + + if (canAttest) { + error = nil; + NSData *attSysKeyCNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyC, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyCNN != nil, "%s-committed attesting privKey: %@", name, error); + + error = nil; + NSData *attSysKeyPNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyP, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyPNN != nil, "%s-proposed attesting privKey: %@", name, error); + } + + id pubSysKeyCN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysKeyC)); + ok(pubSysKeyCN != nil, "%s-committed copy public key", name); + ok([pubSysKeyPN isEqual:pubSysKeyCN], "%s proposed and committed same after commit", name); + + // Attest system key with SIK + NSData *attSIKSysKeyP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysKeyP, (void *)&error)); + ok(attSIKSysKeyP != nil, "SIK attesting %s-proposed, error: %@", name, error); + + NSData *attSIKSysKeyC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysKeyC, (void *)&error)); + ok(attSIKSysKeyC != nil, "SIK attesting %s-committed, error: %@", name, error); } static void keyFromBlobTest(void) { @@ -410,35 +415,128 @@ static void rewrapTest(void) { ok([decrypted isEqualToData:message], "Decrypted data differs: %@ vs %@", decrypted, message); } +static void keychainTest(void) { + id accessControl = CFBridgingRelease(SecAccessControlCreateWithFlags(NULL, kSecAttrAccessibleWhenUnlocked, kSecAccessControlPrivateKeyUsage, NULL)); + NSDictionary *keyAttributes = @{ (id)kSecAttrTokenID : (id)kSecAttrTokenIDAppleKeyStore, + (id)kSecAttrKeyType : (id)kSecAttrKeyTypeECSECPrimeRandom, + (id)kSecPrivateKeyAttrs : @{ + (id)kSecAttrAccessControl : accessControl, + (id)kSecAttrIsPermanent : @YES, + (id)kSecAttrLabel : @"si_44_seckey_aks_1", + }, + }; + NSError *error; + id key = (__bridge_transfer id)SecKeyCreateRandomKey((CFDictionaryRef)keyAttributes, (void *)&error); + ok(key, "failed to create random key %@", error); + id pubKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)key)); + ok(pubKey, "failed to get public key from SEP key"); + key = nil; + + NSDictionary *query = @{ + (id)kSecReturnRef: @YES, + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"si_44_seckey_aks_1", + }; + OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (void *)&key); + is(status, errSecSuccess, "getting SEP key from keychain failed"); + + NSError *err; + NSData *data = [@"message" dataUsingEncoding:NSUTF8StringEncoding]; + NSData *sig = CFBridgingRelease(SecKeyCreateSignature((SecKeyRef)key, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (CFDataRef)data, (void *)&err)); + ok(sig, "failed to create signature: %@", err); + ok(SecKeyVerifySignature((SecKeyRef)pubKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (CFDataRef)data, (CFDataRef)sig, (void *)&err), "failed to verify signature: %@", err); + + status = SecItemDelete((CFDictionaryRef)query); + is(status, errSecSuccess, "deleting SEP key from keychain failed"); + + status = SecItemCopyMatching((CFDictionaryRef)query, (void *)&key); + is(status, errSecItemNotFound, "SEP key was not deleted from keychain"); +} + +static void secAccessControlDescriptionTest(void) { + NSError *error; + NSObject *ac = CFBridgingRelease(SecAccessControlCreate(kCFAllocatorDefault, (void *)&error)); + ok(ac, "failed to create ac: %@", error); + ok(SecAccessControlSetProtection((__bridge SecAccessControlRef)ac, kSecAttrAccessibleWhenUnlocked, (void *)&error), "failed to set protection: %@", error); + + NSString *desc = ac.description; + ok([desc isEqualToString:@""], "unexpected desc: %@", desc); + + SecAccessControlSetConstraints((__bridge SecAccessControlRef)ac, (__bridge CFDictionaryRef)@{}); + desc = ac.description; + ok([desc isEqualToString:@""], "unexpected desc: %@", desc); + + SecAccessControlSetConstraints((__bridge SecAccessControlRef)ac, (__bridge CFDictionaryRef)@{@"od": (__bridge id)kCFBooleanTrue}); + desc = ac.description; + ok([desc isEqualToString:@""], "unexpected desc: %@", desc); + + SecAccessControlSetConstraints((__bridge SecAccessControlRef)ac, (__bridge CFDictionaryRef)@{@"od": (__bridge id)kCFBooleanTrue, @"oe": (__bridge id)kCFBooleanFalse}); + desc = ac.description; + ok([desc isEqualToString:@""], "unexpected desc: %@", desc); + + SecAccessControlSetConstraints((__bridge SecAccessControlRef)ac, (__bridge CFDictionaryRef)@{@"od": @"huh"}); + desc = ac.description; + ok([desc isEqualToString:@""], "unexpected desc: %@", desc); + + SecAccessControlSetConstraints((__bridge SecAccessControlRef)ac, (__bridge CFDictionaryRef)@{@"od": @2}); + desc = ac.description; + ok([desc isEqualToString:@""], "unexpected desc: %@", desc); + + NSData *shortData = [NSData dataWithBytes:"\x01\x02\x03" length:3]; + SecAccessControlSetConstraints((__bridge SecAccessControlRef)ac, (__bridge CFDictionaryRef)@{@"od": shortData}); + desc = ac.description; + ok([desc isEqualToString:@""], "unexpected desc: %@", desc); + + NSData *longData = [NSMutableData dataWithLength:128]; + SecAccessControlSetConstraints((__bridge SecAccessControlRef)ac, (__bridge CFDictionaryRef)@{@"od": longData}); + desc = ac.description; + ok([desc isEqualToString:@""], "unexpected desc: %@", desc); + + SecAccessControlSetConstraints((__bridge SecAccessControlRef)ac, (__bridge CFDictionaryRef)@{@"od": @{@"kofn": @2}}); + desc = ac.description; + ok([desc isEqualToString:@""], "unexpected desc: %@", desc); +} + int si_44_seckey_aks(int argc, char *const *argv) { @autoreleasepool { - BOOL testPKA = YES; -#if !TARGET_OS_OSX - NSNumber *hasPKA = (__bridge_transfer id)MGCopyAnswer(kMGQHasPKA, NULL); - if(![hasPKA isKindOfClass:NSNumber.class] || ![hasPKA boolValue]) { - testPKA = NO; - } -#else - if (remote_device_copy_unique_of_type(REMOTE_DEVICE_TYPE_EOS) == nil && remote_device_copy_unique_of_type(REMOTE_DEVICE_TYPE_BRIDGE_COPROC) == nil) { + NSNumber *hasSEP = CFBridgingRelease(MGCopyAnswer(kMGQHasSEP, NULL)); + if (!hasSEP.boolValue) { // macOS without SEP cannot run attestations at all. plan_tests(1); ok(true); return 0; } - testPKA = NO; + NSNumber *hasPKA = CFBridgingRelease(MGCopyAnswer(kMGQHasPKA, NULL)); + plan_tests(hasPKA.boolValue ? 207 : 113); + + secAccessControlDescriptionTest(); + secKeySepTest(hasPKA.boolValue); + + attestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, YES); + attestationTest(kSecAttrAccessibleUntilReboot, NO); + + sysKeyAttestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, YES, "SysUIK", kSecKeyAttestationKeyTypeUIKCommitted, kSecKeyAttestationKeyTypeUIKProposed, YES); + sysKeyAttestationTest(kSecAttrAccessibleUntilReboot, NO, "SysUIK", kSecKeyAttestationKeyTypeUIKCommitted, kSecKeyAttestationKeyTypeUIKProposed, YES); + + // OIK is too weird to be usable directly, just skip is testing for now. +#if 0 + sysKeyAttestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, YES, "OIK", kSecKeyAttestationKeyTypeOIKCommitted, kSecKeyAttestationKeyTypeOIKProposed, NO); + sysKeyAttestationTest(kSecAttrAccessibleUntilReboot, NO, "OIK", kSecKeyAttestationKeyTypeOIKCommitted, kSecKeyAttestationKeyTypeOIKProposed, NO); #endif - plan_tests(testPKA ? 102 : 87); - secKeySepTest(testPKA); - attestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, NO); - attestationTest(kSecAttrAccessibleUntilReboot, YES); + sysKeyAttestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, YES, "DAK", kSecKeyAttestationKeyTypeDAKCommitted, kSecKeyAttestationKeyTypeDAKProposed, YES); + sysKeyAttestationTest(kSecAttrAccessibleUntilReboot, NO, "DAK", kSecKeyAttestationKeyTypeDAKCommitted, kSecKeyAttestationKeyTypeDAKProposed, YES); + keyFromBlobTest(); + keychainTest(); - // Put SEP keys into test-keybag mode. Available only when running in direct-mode, not with extension. - SecKeySetParameter(NULL, kSecAttrTokenIDAppleKeyStore, kCFBooleanTrue, NULL); - rewrapTest(); - SecKeySetParameter(NULL, kSecAttrTokenIDAppleKeyStore, kCFBooleanFalse, NULL); + if (hasPKA.boolValue) { + // Put SEP keys into test-keybag mode. Available only when running in direct-mode, not with extension. + SecKeySetParameter(NULL, kSecAttrTokenIDAppleKeyStore, kCFBooleanTrue, NULL); + rewrapTest(); + SecKeySetParameter(NULL, kSecAttrTokenIDAppleKeyStore, kCFBooleanFalse, NULL); + } return 0; } diff --git a/OSX/shared_regressions/si-44-seckey-proxy.m b/OSX/shared_regressions/si-44-seckey-proxy.m index c0aa33aa..648dfeae 100644 --- a/OSX/shared_regressions/si-44-seckey-proxy.m +++ b/OSX/shared_regressions/si-44-seckey-proxy.m @@ -54,11 +54,12 @@ static void test_key_proxy_connect() { // Create new proxy and invalidate it (idempotent, so we try invalidate multiple times). keyProxy = [[SecKeyProxy alloc] initWithKey:(SecKeyRef)serverKey]; + endpoint = keyProxy.endpoint; [keyProxy invalidate]; [keyProxy invalidate]; - secondKey = [SecKeyProxy createKeyFromEndpoint:keyProxy.endpoint error:&error]; + secondKey = [SecKeyProxy createKeyFromEndpoint:endpoint error:&error]; is(secondKey, NULL, "connection to invalidated proxy should be refused."); - + // Invalidate connected proxy, make sure that remote key does not work as expected. keyProxy = [[SecKeyProxy alloc] initWithKey:(SecKeyRef)serverKey]; secondKey = [SecKeyProxy createKeyFromEndpoint:keyProxy.endpoint error:&error]; diff --git a/OSX/shared_regressions/si-82-sectrust-ct-data/CTlogs.plist b/OSX/shared_regressions/si-82-sectrust-ct-data/CTlogs.plist index 1abc8574..283e8721 100644 --- a/OSX/shared_regressions/si-82-sectrust-ct-data/CTlogs.plist +++ b/OSX/shared_regressions/si-82-sectrust-ct-data/CTlogs.plist @@ -146,5 +146,21 @@ operator sugar + + description + butter + key + MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDH3+ICRtk2yzuDVqQqfzEZjTolXEJE231xMfH5WqbsbgKMWzVLb6N53Tu0HE1BrEGLRys0l9+a5FFNPu9ZD8+g== + operator + butter + + + description + salt + key + MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGGqtoLdUmLWG4HztrrF1ywuXPPsp59pOgyWtSKabhDJOi8xyTtf8WMxCGl6LyKg+jl5QnT9MRpT5P3BkNfrljg== + operator + salt + diff --git a/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_one_year_2_scts_after.cer b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_one_year_2_scts_after.cer new file mode 100644 index 00000000..a9030248 Binary files /dev/null and b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_one_year_2_scts_after.cer differ diff --git a/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_one_year_2_scts_before.cer b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_one_year_2_scts_before.cer new file mode 100644 index 00000000..23169319 Binary files /dev/null and b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_one_year_2_scts_before.cer differ diff --git a/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_one_year_3_scts_after.cer b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_one_year_3_scts_after.cer new file mode 100644 index 00000000..bbaefb60 Binary files /dev/null and b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_one_year_3_scts_after.cer differ diff --git a/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_root.cer b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_root.cer new file mode 100644 index 00000000..bb220c01 Binary files /dev/null and b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_root.cer differ diff --git a/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_six_months_1_sct.cer b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_six_months_1_sct.cer new file mode 100644 index 00000000..0e25cf87 Binary files /dev/null and b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_six_months_1_sct.cer differ diff --git a/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_six_months_2_scts.cer b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_six_months_2_scts.cer new file mode 100644 index 00000000..85ffc8c9 Binary files /dev/null and b/OSX/shared_regressions/si-82-sectrust-ct-data/policyv2_six_months_2_scts.cer differ diff --git a/OSX/shared_regressions/si-88-sectrust-valid.m b/OSX/shared_regressions/si-88-sectrust-valid.m deleted file mode 100644 index 28b593aa..00000000 --- a/OSX/shared_regressions/si-88-sectrust-valid.m +++ /dev/null @@ -1,308 +0,0 @@ -/* - * si-88-sectrust-valid.m - * Security - * - * Copyright (c) 2017-2019 Apple Inc. All Rights Reserved. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -enum { - kBasicPolicy = 0, - kSSLServerPolicy = 1, -}; - -/* number of tests in the test_valid_trust function */ -#define TVT_COUNT 8 - -static void test_valid_trust(SecCertificateRef leaf, SecCertificateRef ca, SecCertificateRef subca, - CFArrayRef anchors, CFDateRef date, CFIndex policyID, - SecTrustResultType expected, const char *test_name) -{ - CFArrayRef policies=NULL; - SecPolicyRef policy=NULL; - SecTrustRef trust=NULL; - SecTrustResultType trustResult; - CFMutableArrayRef certs=NULL; - - printf("Starting %s\n", test_name); - isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array"); - if (certs) { - if (leaf) { - CFArrayAppendValue(certs, leaf); - } - if (ca) { - CFArrayAppendValue(certs, ca); - } - if (subca) { - CFArrayAppendValue(certs, subca); - } - } - - if (policyID == kSSLServerPolicy) { - isnt(policy = SecPolicyCreateSSL(true, NULL), NULL, "create ssl policy"); - } else { - isnt(policy = SecPolicyCreateBasicX509(), NULL, "create basic policy"); - } - isnt(policies = CFArrayCreate(kCFAllocatorDefault, (const void **)&policy, 1, &kCFTypeArrayCallBacks), NULL, "create policies"); - ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); - - assert(trust); // silence analyzer - ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - ok(trustResult == expected, "trustResult %d expected (got %d)", - (int)expected, (int)trustResult); - - CFReleaseSafe(certs); - CFReleaseSafe(policy); - CFReleaseSafe(policies); - CFReleaseSafe(trust); -} - -#import -SecCertificateRef SecCertificateCreateWithPEM(CFAllocatorRef allocator, CFDataRef pem_certificate); - -static SecCertificateRef SecCertificateCreateFromResource(NSString *name) -{ - NSString *resources = @"si-88-sectrust-valid-data"; - NSString *extension = @"pem"; - - NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:extension subdirectory:resources]; - if (!url) { - printf("No URL for resource \"%s.pem\"\n", [name UTF8String]); - return NULL; - } - - NSData *certData = [NSData dataWithContentsOfURL:url]; - if (!certData) { - printf("No cert data for resource \"%s.pem\"\n", [name UTF8String]); - return NULL; - } - - return SecCertificateCreateWithPEM(kCFAllocatorDefault, (__bridge CFDataRef)certData); -} - -/* number of tests in date_constraints_tests function, plus calls to test_valid_trust */ -#define DC_COUNT (12+(TVT_COUNT*6)) - -static void date_constraints_tests() -{ - SecCertificateRef ca_na=NULL, ca_nb=NULL, root=NULL; - SecCertificateRef leaf_na_ok1=NULL, leaf_na_ok2=NULL; - SecCertificateRef leaf_nb_ok1=NULL, leaf_nb_ok2=NULL, leaf_nb_revoked1=NULL; - - isnt(ca_na = SecCertificateCreateFromResource(@"ca-na"), NULL, "create ca-na cert"); - isnt(ca_nb = SecCertificateCreateFromResource(@"ca-nb"), NULL, "create ca-nb cert"); - isnt(root = SecCertificateCreateFromResource(@"root"), NULL, "create root cert"); - isnt(leaf_na_ok1 = SecCertificateCreateFromResource(@"leaf-na-ok1"), NULL, "create leaf-na-ok1 cert"); - isnt(leaf_na_ok2 = SecCertificateCreateFromResource(@"leaf-na-ok2"), NULL, "create leaf-na-ok2 cert"); - isnt(leaf_nb_ok1 = SecCertificateCreateFromResource(@"leaf-nb-ok1"), NULL, "create leaf-nb-ok1 cert"); - isnt(leaf_nb_ok2 = SecCertificateCreateFromResource(@"leaf-nb-ok2"), NULL, "create leaf-nb-ok2 cert"); - isnt(leaf_nb_revoked1 = SecCertificateCreateFromResource(@"leaf-nb-revoked1"), NULL, "create leaf-nb-revoked1 cert"); - - CFMutableArrayRef anchors=NULL; - isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array"); - if (anchors && root) { - CFArrayAppendValue(anchors, root); - } - CFCalendarRef cal = NULL; - CFAbsoluteTime at; - CFDateRef date_20180102 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info - - isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar"); - ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 1, 2), "create verify absolute time 20180102"); - isnt(date_20180102 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180102"); - - /* Case 0: leaf_na_ok1 (not revoked) */ - /* -- OK: cert issued 2017-10-20, before the CA not-after date of 2017-10-21 */ - /* test cert has no SCT, but is expected to be OK since we now only apply the CT restriction for SSL. */ - test_valid_trust(leaf_na_ok1, ca_na, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultUnspecified, - "leaf_na_ok1 basic"); - - /* Case 1: leaf_na_ok1 (not revoked) */ - /* -- BAD: since a not-after date now requires CT (for SSL) and the test cert has no SCT, this is fatal. */ - test_valid_trust(leaf_na_ok1, ca_na, NULL, anchors, date_20180102, - kSSLServerPolicy, kSecTrustResultFatalTrustFailure, - "leaf_na_ok1 ssl"); - - /* Case 2: leaf_na_ok2 (revoked) */ - /* -- BAD: cert issued 2017-10-26, after the CA not-after date of 2017-10-21 */ - test_valid_trust(leaf_na_ok2, ca_na, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_na_ok2 basic"); - - /* Case 3: leaf_nb_ok1 (revoked) */ - /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */ - test_valid_trust(leaf_nb_ok1, ca_nb, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_nb_ok1 basic"); - - /* Case 4: leaf_nb_ok2 (not revoked) */ - /* -- OK: cert issued 2017-10-26, after the CA not-before date of 2017-10-22 */ - test_valid_trust(leaf_nb_ok2, ca_nb, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultUnspecified, - "leaf_nb_ok2 basic"); - - /* Case 5: leaf_nb_revoked1 (revoked) */ - /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */ - test_valid_trust(leaf_nb_revoked1, ca_nb, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_nb_revoked1 basic"); - - CFReleaseSafe(ca_na); - CFReleaseSafe(ca_nb); - CFReleaseSafe(leaf_na_ok1); - CFReleaseSafe(leaf_na_ok2); - CFReleaseSafe(leaf_nb_ok1); - CFReleaseSafe(leaf_nb_ok2); - CFReleaseSafe(leaf_nb_revoked1); - CFReleaseSafe(root); - CFReleaseSafe(anchors); - CFReleaseSafe(cal); - CFReleaseSafe(date_20180102); -} - -/* number of tests in known_intermediate_tests function, plus calls to test_valid_trust */ -#define KI_COUNT (10+(TVT_COUNT*3)) - -static void known_intermediate_tests() -{ - SecCertificateRef ca_ki=NULL, root=NULL; - SecCertificateRef leaf_ki_ok1=NULL, leaf_ki_revoked1=NULL; - SecCertificateRef leaf_unknown=NULL, ca_unknown=NULL; - - isnt(ca_ki = SecCertificateCreateFromResource(@"ca-ki"), NULL, "create ca-ki cert"); - isnt(root = SecCertificateCreateFromResource(@"root"), NULL, "create root cert"); - isnt(leaf_ki_ok1 = SecCertificateCreateFromResource(@"leaf-ki-ok1"), NULL, "create leaf-ki-ok1 cert"); - isnt(leaf_ki_revoked1 = SecCertificateCreateFromResource(@"leaf-ki-revoked1"), NULL, "create leaf-ki-revoked1 cert"); - isnt(ca_unknown = SecCertificateCreateFromResource(@"ca-unknown"), NULL, "create ca-unknown cert"); - isnt(leaf_unknown = SecCertificateCreateFromResource(@"leaf-unknown"), NULL, "create leaf-unknown cert"); - - CFMutableArrayRef anchors=NULL; - isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array"); - if (anchors && root) { - CFArrayAppendValue(anchors, root); - } - CFCalendarRef cal = NULL; - CFAbsoluteTime at; - CFDateRef date_20180310 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info - - isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar"); - ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 3, 10), "create verify absolute time 20180310"); - isnt(date_20180310 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180310"); - - /* Case 1: leaf_ki_ok1 */ - /* -- OK: cert issued by a known intermediate */ - test_valid_trust(leaf_ki_ok1, ca_ki, NULL, anchors, date_20180310, - kBasicPolicy, kSecTrustResultUnspecified, - "leaf_ki_ok1"); - - /* Case 2: leaf_ki_revoked1 */ - /* -- BAD: CA specifies known-only+complete serial blocklist; this cert is on the blocklist. */ - test_valid_trust(leaf_ki_revoked1, ca_ki, NULL, anchors, date_20180310, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_ki_revoked1"); - - /* Case 3: leaf_unknown */ - /* -- BAD: ca_unknown issued from ca_ki, but is not a known intermediate. - * ca_ki has a path len of 0 which would normally result in kSecTrustResultRecoverableTrustFailure; - * however, since known-intermediates is asserted for ca_ki (non-overridable), we expect a fatal failure. */ - test_valid_trust(leaf_unknown, ca_unknown, ca_ki, anchors, date_20180310, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_unknown test"); - - CFReleaseSafe(ca_ki); - CFReleaseSafe(leaf_ki_ok1); - CFReleaseSafe(leaf_ki_revoked1); - CFReleaseSafe(ca_unknown); - CFReleaseSafe(leaf_unknown); - CFReleaseSafe(root); - CFReleaseSafe(anchors); - CFReleaseSafe(cal); - CFReleaseSafe(date_20180310); -} - -static int ping_host(char *host_name) -{ - struct sockaddr_in pin; - struct hostent *nlp_host; - int sd = 0; - int port = 80; - int retries = 5; // we try 5 times, then give up - - while ((nlp_host=gethostbyname(host_name))==0 && retries--) { - printf("Resolve Error! (%s) %d\n", host_name, h_errno); - sleep(1); - } - if (nlp_host==0) { - return 0; - } - - bzero(&pin,sizeof(pin)); - pin.sin_family=AF_INET; - pin.sin_addr.s_addr=htonl(INADDR_ANY); - pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; - pin.sin_port=htons(port); - - sd=socket(AF_INET,SOCK_STREAM,0); - - if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1) { - printf("connect error! (%s) %d\n", host_name, errno); - close(sd); - return 0; - } - close(sd); - return 1; -} - -static int preflight_network() -{ - char *hosts[] = { - "EVSecure-ocsp.verisign.com", - "EVIntl-ocsp.verisign.com", - "EVIntl-aia.verisign.com", - "ocsp.comodoca.com", - "crt.comodoca.com", - "ocsp.entrust.net", - "ocsp.digicert.com", - }; - - for (unsigned host_cnt = 0; host_cnt < sizeof(hosts)/sizeof(hosts[0]); host_cnt ++) { - if (!ping_host(hosts[host_cnt])) { - printf("Accessing specific server (%s) failed, check the network!\n", hosts[host_cnt]); - return 0; - } - } - return 1; -} - -int si_88_sectrust_valid(int argc, char *const *argv) -{ - plan_tests(DC_COUNT+KI_COUNT); - - if (!preflight_network()) { - return 0; - } - - date_constraints_tests(); - known_intermediate_tests(); - - return 0; -} diff --git a/OSX/utilities/Regressions/su-10-cfstring-der.c b/OSX/utilities/Regressions/su-10-cfstring-der.c index 98176101..3a9031e1 100644 --- a/OSX/utilities/Regressions/su-10-cfstring-der.c +++ b/OSX/utilities/Regressions/su-10-cfstring-der.c @@ -63,7 +63,7 @@ static void one_test(const struct test_case * thisCase) CFStringRef decoded = NULL; - const uint8_t* decode_end = der_decode_string(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_string(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end); @@ -77,7 +77,7 @@ static void one_test(const struct test_case * thisCase) CFTypeRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end); diff --git a/OSX/utilities/Regressions/su-11-cfdata-der.c b/OSX/utilities/Regressions/su-11-cfdata-der.c index ceeeddf9..fb50b629 100644 --- a/OSX/utilities/Regressions/su-11-cfdata-der.c +++ b/OSX/utilities/Regressions/su-11-cfdata-der.c @@ -120,14 +120,14 @@ static void one_test(const struct test_case * thisCase) #endif CFDataRef decoded = NULL; - const uint8_t* decode_end = der_decode_data(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_data(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end); ok((decoded != NULL) && CFEqual(decoded, start)); CFTypeRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end); diff --git a/OSX/utilities/Regressions/su-12-cfboolean-der.c b/OSX/utilities/Regressions/su-12-cfboolean-der.c index ed6fe783..5a4ae67a 100644 --- a/OSX/utilities/Regressions/su-12-cfboolean-der.c +++ b/OSX/utilities/Regressions/su-12-cfboolean-der.c @@ -61,14 +61,14 @@ static void one_test(CFBooleanRef value, size_t der_size, const uint8_t *expecte #endif CFBooleanRef decoded = NULL; - const uint8_t* decode_end = der_decode_boolean(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_boolean(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end); ok((decoded != NULL) && CFEqual(decoded, value)); CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end); diff --git a/OSX/utilities/Regressions/su-13-cfnumber-der.c b/OSX/utilities/Regressions/su-13-cfnumber-der.c index 8eb5d038..6b6b1738 100644 --- a/OSX/utilities/Regressions/su-13-cfnumber-der.c +++ b/OSX/utilities/Regressions/su-13-cfnumber-der.c @@ -82,7 +82,7 @@ static void one_test(const struct test_case * thisCase) CFNumberRef decoded = NULL; - const uint8_t* decode_end = der_decode_number(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_number(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); @@ -90,7 +90,7 @@ static void one_test(const struct test_case * thisCase) CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); diff --git a/OSX/utilities/Regressions/su-14-cfarray-der.c b/OSX/utilities/Regressions/su-14-cfarray-der.c index 5627a9db..14076282 100644 --- a/OSX/utilities/Regressions/su-14-cfarray-der.c +++ b/OSX/utilities/Regressions/su-14-cfarray-der.c @@ -83,7 +83,7 @@ static void one_test(const struct test_case * thisCase) CFArrayRef decoded = NULL; - const uint8_t* decode_end = der_decode_array(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_array(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); @@ -91,7 +91,7 @@ static void one_test(const struct test_case * thisCase) CFTypeRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); diff --git a/OSX/utilities/Regressions/su-15-cfdictionary-der.c b/OSX/utilities/Regressions/su-15-cfdictionary-der.c index 945bf3fe..9f9c3515 100644 --- a/OSX/utilities/Regressions/su-15-cfdictionary-der.c +++ b/OSX/utilities/Regressions/su-15-cfdictionary-der.c @@ -83,7 +83,7 @@ static void test_dictionary(CFDictionaryRef testValue, size_t expected_size, con CFDictionaryRef decoded = NULL; - const uint8_t* decode_end = der_decode_dictionary(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_dictionary(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); @@ -91,7 +91,7 @@ static void test_dictionary(CFDictionaryRef testValue, size_t expected_size, con CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); diff --git a/OSX/utilities/Regressions/su-16-cfdate-der.c b/OSX/utilities/Regressions/su-16-cfdate-der.c index df3d05fc..8b781a73 100644 --- a/OSX/utilities/Regressions/su-16-cfdate-der.c +++ b/OSX/utilities/Regressions/su-16-cfdate-der.c @@ -114,6 +114,7 @@ static bool ok_date_equals(int testnumber, CFDateRef decoded, CFDateRef expected } } +#if 0 static CFCalendarRef sZuluCalendar = NULL; static CFCalendarRef SecCFCalendarGetZulu() { @@ -170,10 +171,12 @@ static bool parallelizeZulu(bool useSharedZuluCalendar, void(^action)(CFCalendar dispatch_release(dgroup); return !stop; } +#endif // We expect this to fail until this is fixed: // CFCalendarDecomposeAbsoluteTime is not thread safe // +#if 0 static void testWithUnguardedZuluCalendar() { const bool useSharedZuluCalendar = true; __block bool success = true; @@ -217,6 +220,7 @@ static void testDoWithZulu() { ok(success,"unexpected result from CFCalendarDecomposeAbsoluteTime"); } +#endif #define kTestsPerTestCase 12 static void one_test(const struct test_case * thisCase, int testnumber) @@ -246,7 +250,7 @@ static void one_test(const struct test_case * thisCase, int testnumber) CFReleaseNull(error); CFDateRef decoded = NULL; - const uint8_t* decode_end = der_decode_date(NULL, kCFPropertyListMutableContainers, + const uint8_t* decode_end = der_decode_date(NULL, &decoded, &error, encoded, buffer_end); ok(error == NULL, "[%d] der_decode_date failed: %@", testnumber, error); CFReleaseNull(error); @@ -256,7 +260,7 @@ static void one_test(const struct test_case * thisCase, int testnumber) CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainers, + decode_end = der_decode_plist(NULL, &decoded_type, &error, encoded, buffer_end); ok(error == NULL, "[%d] der_decode_plist failed: %@", testnumber, error); CFReleaseNull(error); diff --git a/OSX/utilities/Regressions/su-17-cfset-der.c b/OSX/utilities/Regressions/su-17-cfset-der.c index eff6f588..845b5b15 100644 --- a/OSX/utilities/Regressions/su-17-cfset-der.c +++ b/OSX/utilities/Regressions/su-17-cfset-der.c @@ -86,7 +86,7 @@ static void test_set(CFSetRef testValue, size_t expected_size, const uint8_t* ex CFSetRef decoded = NULL; - const uint8_t* decode_end = der_decode_set(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_set(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); @@ -94,7 +94,7 @@ static void test_set(CFSetRef testValue, size_t expected_size, const uint8_t* ex CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); diff --git a/OSX/utilities/Regressions/su-40-secdb.c b/OSX/utilities/Regressions/su-40-secdb.c index 5c3c4d13..90d2c0c9 100644 --- a/OSX/utilities/Regressions/su-40-secdb.c +++ b/OSX/utilities/Regressions/su-40-secdb.c @@ -24,6 +24,7 @@ #include #include +#include #include @@ -71,25 +72,25 @@ static void count_connections(SecDbRef db) { dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_async(group, queue, ^{ - cmp_ok(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), <=, kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters); + cmp_ok(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), <=, kSecDbMaxWriters, "max writers is %zu", kSecDbMaxWriters); TODO: { todo("can't guarantee all threads used"); - is(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters); + is(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), kSecDbMaxWriters, "max writers is %zu", kSecDbMaxWriters); } }); dispatch_group_async(group, queue, ^{ - cmp_ok(count_func(db, "readers", &max_conn_count, SecDbPerformRead), <=, kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders); + cmp_ok(count_func(db, "readers", &max_conn_count, SecDbPerformRead), <=, kSecDbMaxReaders, "max readers is %zu", kSecDbMaxReaders); TODO: { todo("can't guarantee all threads used"); - is(count_func(db, "readers", &max_conn_count, SecDbPerformRead), kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders); + is(count_func(db, "readers", &max_conn_count, SecDbPerformRead), kSecDbMaxReaders, "max readers is %zu", kSecDbMaxReaders); } }); dispatch_group_wait(group, DISPATCH_TIME_FOREVER); dispatch_release(group); - cmp_ok(max_conn_count, <=, kSecDbMaxIdleHandles, "max idle connection count is %d", kSecDbMaxIdleHandles); + cmp_ok(max_conn_count, <=, kSecDbMaxIdleHandles, "max idle connection count is %zu", kSecDbMaxIdleHandles); TODO: { todo("can't guarantee all threads idle"); - is(max_conn_count, kSecDbMaxIdleHandles, "max idle connection count is %d", kSecDbMaxIdleHandles); + is(max_conn_count, kSecDbMaxIdleHandles, "max idle connection count is %zu", kSecDbMaxIdleHandles); } } diff --git a/OSX/utilities/Regressions/su-41-secdb-stress.c b/OSX/utilities/Regressions/su-41-secdb-stress.c index b7f9c5bf..52c8b838 100644 --- a/OSX/utilities/Regressions/su-41-secdb-stress.c +++ b/OSX/utilities/Regressions/su-41-secdb-stress.c @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -31,7 +32,7 @@ #include "utilities_regressions.h" #include -#define kTestCount 3418 +#define kTestCount 3422 // God I love magic numbers // Queue to protect counters and test_ok invocations static dispatch_queue_t count_queue; @@ -187,7 +188,7 @@ static void tests(void) CFReleaseNull(tid); const char *home_var = getenv("HOME"); - CFStringRef dbName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s/Library/Keychains/su-41-sqldb-stress.db"), home_var ? home_var : ""); + CFStringRef dbName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s/Library/Keychains/su-41-secdb-stress.db"), home_var ? home_var : "/var/tmp"); CFStringPerformWithCString(dbName, ^(const char *path) { unlink(path); }); SecDbRef db = SecDbCreate(dbName, 0600, true, true, true, true, kSecDbMaxIdleHandles, @@ -244,14 +245,18 @@ static void tests(void) dispatch_release_null(count_queue); - cmp_ok(max_idle, >=, kSecDbMaxIdleHandles - 1, "max idle at least %d", kSecDbMaxIdleHandles - 1); - cmp_ok(max_writers, >=, kSecDbMaxWriters - 1, "max writers at least %d", kSecDbMaxWriters - 1); - cmp_ok(max_readers, >=, kSecDbMaxReaders - 1, "max readers at least %d", kSecDbMaxReaders - 1); + cmp_ok(SecDbIdleConnectionCount(db), >=, kSecDbMaxIdleHandles - 1, "cur idle at least %lu", kSecDbMaxIdleHandles - 1); + cmp_ok(SecDbIdleConnectionCount(db), <=, kSecDbMaxIdleHandles, "cur idle at most %lu", kSecDbMaxIdleHandles); + cmp_ok(max_idle, <=, kSecDbMaxIdleHandles, "max idle at most %lu", kSecDbMaxIdleHandles - 1); + cmp_ok(max_writers, >=, kSecDbMaxWriters - 1, "max writers at least %lu", kSecDbMaxWriters - 1); + cmp_ok(max_readers, >=, kSecDbMaxReaders - 1, "max readers at least %lu", kSecDbMaxReaders - 1); + cmp_ok(max_writers, <=, kSecDbMaxWriters, "max writers at most %lu", kSecDbMaxWriters); + cmp_ok(max_readers, <=, kSecDbMaxReaders, "max readers at most %lu", kSecDbMaxReaders); TODO: { todo("race conditions make us not always hit the limits reliably."); - is(max_idle, kSecDbMaxIdleHandles, "max idle connection count is %d", kSecDbMaxIdleHandles); - is(max_writers, kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters); - is(max_readers, kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders); + is(max_idle, kSecDbMaxIdleHandles, "max idle connection count is %zu", kSecDbMaxIdleHandles); + is(max_writers, kSecDbMaxWriters, "max writers is %zu", kSecDbMaxWriters); + is(max_readers, kSecDbMaxReaders, "max readers is %zu", kSecDbMaxReaders); } CFReleaseSafe(dbName); diff --git a/OSX/utilities/SecADWrapper.c b/OSX/utilities/SecADWrapper.c deleted file mode 100644 index 7d6aba8f..00000000 --- a/OSX/utilities/SecADWrapper.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include "SecADWrapper.h" - -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR -#include - -static typeof(ADClientAddValueForScalarKey) *soft_ADClientAddValueForScalarKey = NULL; -static typeof(ADClientClearScalarKey) *soft_ADClientClearScalarKey = NULL; -static typeof(ADClientSetValueForScalarKey) *soft_ADClientSetValueForScalarKey = NULL; -static typeof(ADClientPushValueForDistributionKey) *soft_ADClientPushValueForDistributionKey = NULL; - -static bool -setup(void) -{ - static dispatch_once_t onceToken; - static CFBundleRef bundle = NULL; - dispatch_once(&onceToken, ^{ - - CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework"), kCFURLPOSIXPathStyle, true); - if (url == NULL) - return; - - bundle = CFBundleCreate(kCFAllocatorDefault, url); - CFRelease(url); - if (bundle == NULL) - return; - - soft_ADClientClearScalarKey = CFBundleGetFunctionPointerForName(bundle, CFSTR("ADClientClearScalarKey")); - soft_ADClientSetValueForScalarKey = CFBundleGetFunctionPointerForName(bundle, CFSTR("ADClientSetValueForScalarKey")); - soft_ADClientAddValueForScalarKey = CFBundleGetFunctionPointerForName(bundle, CFSTR("ADClientAddValueForScalarKey")); - soft_ADClientPushValueForDistributionKey = CFBundleGetFunctionPointerForName(bundle, CFSTR("ADClientPushValueForDistributionKey")); - - if (soft_ADClientClearScalarKey == NULL || - soft_ADClientSetValueForScalarKey == NULL || - soft_ADClientAddValueForScalarKey == NULL || - soft_ADClientPushValueForDistributionKey == NULL) - { - CFRelease(bundle); - bundle = NULL; - } - }); - return bundle != NULL; -} -#endif - -void -SecADClearScalarKey(CFStringRef key) -{ -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (setup()) - soft_ADClientClearScalarKey(key); -#endif -} - -void -SecADSetValueForScalarKey(CFStringRef key, int64_t value) -{ -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (setup()) - soft_ADClientSetValueForScalarKey(key, value); -#endif -} -void -SecADAddValueForScalarKey(CFStringRef key, int64_t value) -{ -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (setup()) - soft_ADClientAddValueForScalarKey(key, value); -#endif -} - -void -SecADClientPushValueForDistributionKey(CFStringRef key, int64_t value) -{ -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (setup()) - soft_ADClientPushValueForDistributionKey(key, value); -#endif -} - diff --git a/OSX/utilities/SecBuffer.c b/OSX/utilities/SecBuffer.c index 49715789..e3a7c89f 100644 --- a/OSX/utilities/SecBuffer.c +++ b/OSX/utilities/SecBuffer.c @@ -29,9 +29,9 @@ void PerformWithBuffer(size_t size, void (^operation)(size_t size, uint8_t *buff } void PerformWithBufferAndClear(size_t size, void (^operation)(size_t size, uint8_t *buffer)) { - PerformWithBuffer(size, ^(size_t size, uint8_t *buffer) { - operation(size, buffer); + PerformWithBuffer(size, ^(size_t buf_size, uint8_t *buffer) { + operation(buf_size, buffer); - bzero(buffer, size); + bzero(buffer, buf_size); }); } diff --git a/OSX/utilities/SecCFCCWrappers.c b/OSX/utilities/SecCFCCWrappers.c index 588b9de2..dc815dfd 100644 --- a/OSX/utilities/SecCFCCWrappers.c +++ b/OSX/utilities/SecCFCCWrappers.c @@ -24,6 +24,8 @@ #include +#include + CFDataRef CFDataCreateDigestWithBytes(CFAllocatorRef allocator, const struct ccdigest_info *di, size_t len, const void *data, CFErrorRef *error) { CFMutableDataRef digest = CFDataCreateMutable(allocator, di->output_size); diff --git a/OSX/utilities/SecCFError.c b/OSX/utilities/SecCFError.c index 39caa712..fd428b29 100644 --- a/OSX/utilities/SecCFError.c +++ b/OSX/utilities/SecCFError.c @@ -26,7 +26,8 @@ #include #include #include - +#include "keychain/SecureObjectSync/SOSInternal.h" +#include // // OSStatus values we magically know @@ -69,66 +70,26 @@ bool SecCheckErrno(int result, CFErrorRef *error, CFStringRef format, ...) { return false; } -bool SecPOSIXError(int error, CFErrorRef *cferror, CFStringRef format, ...) -{ - if (error == 0) return true; - if (error) { - va_list args; - CFIndex code = error; - CFErrorRef previousError = *cferror; - - *cferror = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecErrnoDomain, previousError, cferror, NULL, format, args); - va_end(args); - } - return false; -} - -bool SecCoreCryptoError(int error, CFErrorRef *cferror, CFStringRef format, ...) -{ - if (error == 0) return true; - if (error) { - va_list args; - CFIndex code = error; - CFErrorRef previousError = *cferror; - - *cferror = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecCoreCryptoDomain, previousError, cferror, NULL, format, args); - va_end(args); - } - return false; -} - - -bool SecNotifyError(uint32_t result, CFErrorRef *error, CFStringRef format, ...) { - if (result == NOTIFY_STATUS_OK) return true; - if (error) { - va_list args; - CFIndex code = result; - CFErrorRef previousError = *error; - - *error = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecNotifyDomain, previousError, error, NULL, format, args); - va_end(args); - } - return false; -} - bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...) { - if (status == 0) return true; - if (error) { - va_list args; - CFIndex code = status; - CFErrorRef previousError = *error; - - *error = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecErrorDomain, previousError, error, NULL, format, args); - va_end(args); + if (status == 0) { + return true; } + + CFErrorRef localError = NULL; + va_list args; + CFIndex code = status; + va_start(args, format); + SecCFCreateErrorWithFormatAndArguments(code, kSecErrorDomain, error ? *error : NULL, &localError, NULL, format, args); + va_end(args); + + if (error) { + *error = localError; // Existing *error is consumed by SecCFCreateErrorWithFormatAndArguments + } else { + // This happens a bunch in our codebase, so this log can only really exist in debug builds + secdebug("secerror", "Error, but no out-parameter for error: %@", localError); + CFReleaseNull(localError); + } + return false; } @@ -175,6 +136,57 @@ bool SecCFCreateErrorWithFormat(CFIndex errorCode, CFStringRef domain, CFErrorRe return result; } +static bool SecCFErrorIsEqual(CFIndex errorCode, CFStringRef domain, CFStringRef description, CFErrorRef previousError) +{ + bool isEqual = false; + bool equalDescriptions = false; + + if (previousError == NULL) { + return false; + } + + CFDictionaryRef previousUserInfo = CFErrorCopyUserInfo(previousError); + CFStringRef previousDescription = CFDictionaryGetValue(previousUserInfo, kCFErrorDescriptionKey); + if (previousDescription) { + equalDescriptions = CFStringCompare(description, previousDescription, 0) == kCFCompareEqualTo ? true : false; + } + + CFReleaseNull(previousUserInfo); + bool equalCodes = errorCode == CFErrorGetCode(previousError); + + CFErrorDomain previousDomain = CFErrorGetDomain(previousError); + bool equalDomains = CFStringCompare(domain, previousDomain, 0) == kCFCompareEqualTo ? true : false; + + isEqual = equalCodes && equalDomains && equalDescriptions; + return isEqual; +} + +#define CAP_LIMIT 200 +static bool SecCFErrorShouldCapNestedError(CFErrorRef previousError, long *newCount) +{ + bool shouldCap = false; + + if (previousError) { + CFDictionaryRef userInfo = CFErrorCopyUserInfo(previousError); + if (userInfo && CFDictionaryContainsKey(userInfo, kSOSCountKey) == true) { + CFNumberRef previousCount = CFDictionaryGetValue(userInfo, kSOSCountKey); + if (previousCount) { + long previousLong = 0; + CFNumberGetValue(previousCount, kCFNumberLongType, &previousLong); + if (SecErrorIsNestedErrorCappingEnabled() && previousLong >= CAP_LIMIT) { + shouldCap = true; + } else { + *newCount = previousLong+1; + } + } + } + CFReleaseNull(userInfo); + } else { + *newCount = 0; + } + return shouldCap; +} + // Also consumes whatever newError points to bool SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode, CFStringRef domain, CF_CONSUMED CFErrorRef previousError, CFErrorRef *newError, @@ -182,35 +194,57 @@ bool SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode, CFStringRef domai { if (newError && !(*newError)) { CFStringRef formattedString = CFStringCreateWithFormatAndArguments(NULL, formatoptions, format, args); - - const void* keys[2] = { kCFErrorDescriptionKey, kCFErrorUnderlyingErrorKey}; - const void* values[2] = { formattedString, previousError }; - const CFIndex numEntriesToUse = (previousError != NULL) ? 2 : 1; - // Prepare to release whatever we replaced, as long as they didn't tell us to do so via previousError - // In a sane world, this function wouldn't have a previousError argument, since it should always release what it's replacing, - // but changing all callsites is a huge change - CFErrorRef replacing = ((*newError) == previousError) ? NULL : *newError; + long newDepthCount = 0; + CFNumberRef newCount = NULL; - *newError = CFErrorCreateWithUserInfoKeysAndValues(kCFAllocatorDefault, domain, errorCode, - keys, values, numEntriesToUse); + if (SecCFErrorIsEqual(errorCode, domain, formattedString, previousError) == true) { + secdebug("error_thee_well", "SecCFCreateErrorWithFormatAndArguments previous Error: %@ is equal to the new incoming error: domain: %@, error code: %ld, description: %@", previousError, domain, (long)errorCode, formattedString); + *newError = CFRetainSafe(previousError); + CFReleaseNull(previousError); + CFReleaseNull(formattedString); + return false; + } else if (SecCFErrorShouldCapNestedError(previousError, &newDepthCount) == true) { + secdebug("error_thee_well", "SecCFCreateErrorWithFormatAndArguments reached nested error limit, returning previous error: %@", previousError); + *newError = CFRetainSafe(previousError); + CFReleaseNull(previousError); + CFReleaseNull(formattedString); + return false; + } else { + newCount = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongType, &newDepthCount); + } - CFReleaseNull(formattedString); - if (previousError) + CFMutableDictionaryRef newUserInfo = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + if (previousError) { + CFDictionaryAddValue(newUserInfo, kCFErrorUnderlyingErrorKey, previousError); + } + if (newCount) { + CFDictionaryAddValue(newUserInfo, kSOSCountKey, newCount); + } + if (formattedString) { + CFDictionaryAddValue(newUserInfo, kCFErrorDescriptionKey, formattedString); + } + + *newError = CFErrorCreate(kCFAllocatorDefault, domain, errorCode, newUserInfo); + + if (previousError) { secdebug("error_thee_well", "encapsulated %@ with new error: %@", previousError, *newError); - - CFReleaseNull(replacing); + } + CFReleaseNull(newCount); + CFReleaseNull(formattedString); + CFReleaseNull(newUserInfo); CFReleaseNull(previousError); } else { if (previousError && newError && (previousError != *newError)) { secdebug("error_thee_well", "dropping %@", previousError); - CFRelease(previousError); + CFReleaseNull(previousError); } } - if (newError) + if (newError) { secdebug("error_thee_well", "SecError: %@", *newError); - + } return false; } diff --git a/OSX/utilities/SecCFError.h b/OSX/utilities/SecCFError.h index 3d6121ee..853e150a 100644 --- a/OSX/utilities/SecCFError.h +++ b/OSX/utilities/SecCFError.h @@ -47,21 +47,6 @@ bool SecCheckErrno(int result, CFErrorRef *error, CFStringRef format, ...) bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...) CF_FORMAT_FUNCTION(3, 4); -// Direct checking of POSIX errors. -bool SecPOSIXError(int error, CFErrorRef *cferror, CFStringRef format, ...) - CF_FORMAT_FUNCTION(3, 4); - -// CoreCrypto error -#define kSecCoreCryptoDomain CFSTR("kSecCoreCryptoDomain") -bool SecCoreCryptoError(int error, CFErrorRef *cferror, CFStringRef format, ...) - CF_FORMAT_FUNCTION(3, 4); - -// Notification -#define kSecNotifyDomain CFSTR("kSecNotifyDomain") -bool SecNotifyError(uint32_t result, CFErrorRef *error, CFStringRef format, ...) - CF_FORMAT_FUNCTION(3, 4); - - // requirement error, typically parameters bool SecRequirementError(bool requirement, CFErrorRef *error, CFStringRef format, ...) CF_FORMAT_FUNCTION(3, 4); @@ -95,7 +80,9 @@ static inline bool asArrayOptional(CFTypeRef cfType, CFArrayRef *array, CFErrorR if (array) *array = (CFArrayRef)cfType; return true; } - SecError(-50, error, CFSTR("object %@ is not an array"), cfType); + if(error) { + SecError(-50, error, CFSTR("object %@ is not an array"), cfType); + } return false; } @@ -104,16 +91,9 @@ static inline bool asDataOptional(CFTypeRef cfType, CFDataRef *data, CFErrorRef if (data) *data = (CFDataRef)cfType; return true; } - SecError(-50, error, CFSTR("object %@ is not an data"), cfType); - return false; -} - -static inline bool asSetOptional(CFTypeRef cfType, CFSetRef *set, CFErrorRef *error) { - if (!cfType || CFGetTypeID(cfType) == CFSetGetTypeID()) { - if (set) *set = (CFSetRef)cfType; - return true; + if(error) { + SecError(-50, error, CFSTR("object %@ is not an data"), cfType); } - SecError(-50, error, CFSTR("object %@ is not a set"), cfType); return false; } @@ -121,63 +101,23 @@ static inline bool asSetOptional(CFTypeRef cfType, CFSetRef *set, CFErrorRef *er // MARK: Required value type casting // -// -// MARK: Required value type casting -// - -static inline CFArrayRef copyIfArray(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFArrayGetTypeID()) - return (CFArrayRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not an array"), cfType); - return NULL; -} - -static inline CFBooleanRef copyIfBoolean(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID()) - return (CFBooleanRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not an boolean"), cfType); - return NULL; -} - static inline CFDataRef copyIfData(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDataGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFDataGetTypeID()) { return (CFDataRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a data"), cfType); - return NULL; -} - -static inline CFDateRef copyIfDate(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDateGetTypeID()) - return (CFDateRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a date"), cfType); - return NULL; -} - -static inline CFDictionaryRef copyIfDictionary(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID()) - return (CFDictionaryRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a dictionary"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a data"), cfType); + } return NULL; } static inline CFSetRef copyIfSet(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFSetGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFSetGetTypeID()) { return (CFSetRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a set"), cfType); - return NULL; -} - -static inline CFStringRef copyIfString(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFStringGetTypeID()) - return (CFStringRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a string"), cfType); - return NULL; -} - -static inline CFUUIDRef copyIfUUID(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFUUIDGetTypeID()) - return (CFUUIDRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a UUID"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a set"), cfType); + } return NULL; } @@ -185,58 +125,72 @@ static inline CFUUIDRef copyIfUUID(CFTypeRef cfType, CFErrorRef *error) { // MARK: Analyzer confusing asXxx casting // static inline CFArrayRef asArray(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFArrayGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFArrayGetTypeID()) { return (CFArrayRef)cfType; - SecError(-50, error, CFSTR("object %@ is not an array"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not an array"), cfType); + } return NULL; } static inline CFBooleanRef asBoolean(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID()) { return (CFBooleanRef)cfType; - SecError(-50, error, CFSTR("object %@ is not an boolean"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not an boolean"), cfType); + } return NULL; } static inline CFDataRef asData(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDataGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFDataGetTypeID()) { return (CFDataRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a data"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a data"), cfType); + } return NULL; } static inline CFDateRef asDate(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDateGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFDateGetTypeID()) { return (CFDateRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a date"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a date"), cfType); + } return NULL; } static inline CFDictionaryRef asDictionary(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID()) { return (CFDictionaryRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a dictionary"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a dictionary"), cfType); + } return NULL; } static inline CFSetRef asSet(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFSetGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFSetGetTypeID()) { return (CFSetRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a set"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a set"), cfType); + } return NULL; } static inline CFStringRef asString(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFStringGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFStringGetTypeID()) { return (CFStringRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a string"), cfType); - return NULL; -} - -static inline CFUUIDRef asUUID(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFUUIDGetTypeID()) - return (CFUUIDRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a UUID"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a string"), cfType); + } return NULL; } diff --git a/OSX/utilities/SecCFWrappers.h b/OSX/utilities/SecCFWrappers.h index f1efbf3f..979adda6 100644 --- a/OSX/utilities/SecCFWrappers.h +++ b/OSX/utilities/SecCFWrappers.h @@ -34,7 +34,7 @@ #include -#include +#include "utilities/simulatecrash_assert.h" #include #include #include @@ -223,6 +223,15 @@ static inline bool isNull(CFTypeRef cfType) { return cfType && CFGetTypeID(cfType) == CFNullGetTypeID(); } +// Usage: void foo(CFTypeRef value) { CFDataRef data = CFCast(CFData, value); } +#define CFCast(type, value) \ + ({ __typeof__(value) _v = (value); (_v != NULL) && CFGetTypeID(_v) == type ## GetTypeID() ? (type ## Ref)_v : NULL; }) + +#define CFCastWithError(type, value, error) \ + ({ __typeof__(value) _v = (value); (_v != NULL) && CFGetTypeID(_v) == type ## GetTypeID() ? \ + (type ## Ref)_v : \ + (SecError(errSecParam, error, CFSTR("Unexpected type")), NULL); }) + // // MARK CFEqual Helpers // @@ -360,7 +369,9 @@ static inline const uint8_t* CFDataGetPastEndPtr(CFDataRef theData) { return CFDataGetBytePtr(theData) + CFDataGetLength(theData); } -static inline CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right) +// This function compare DER data object, which take into account the length +// of the data objects when doing the comparsion which item is "before" or "after" +static inline CFComparisonResult CFDataCompareDERData(CFDataRef left, CFDataRef right) { const size_t left_size = CFDataGetLength(left); const size_t right_size = CFDataGetLength(right); @@ -376,6 +387,10 @@ static inline CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right) return kCFCompareEqualTo; } +static inline __deprecated_msg("please use CFEqual or CFDataCompareDERData") CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right) { + return CFDataCompareDERData(left, right); +} + static inline CFDataRef CFDataCreateWithHash(CFAllocatorRef allocator, const struct ccdigest_info *di, const uint8_t *buffer, const uint8_t length) { CFMutableDataRef result = CFDataCreateMutableWithScratch(allocator, di->output_size); @@ -521,13 +536,13 @@ static inline CFStringRef CFStringCreateTruncatedCopy(CFStringRef s, CFIndex len // static inline -const void *SecCFRetainForCollection(CFAllocatorRef allocator, const void *value) +const void *SecCFRetainForCollection(CFAllocatorRef __unused allocator, const void *value) { return CFRetain(value); } static inline -void SecCFReleaseForCollection(CFAllocatorRef allocator, const void *value) +void SecCFReleaseForCollection(CFAllocatorRef __unused allocator, const void *value) { CFRelease(value); } @@ -1006,7 +1021,8 @@ static inline CFDateRef CFDateCreateForGregorianMoment(CFAllocatorRef allocator, return CFDateCreate(allocator, CFAbsoluteTimeForGregorianMoment(tz, year, month, day, hour, minute, second)); } -static inline CFDateRef CFDateCreateForGregorianDay(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second) +static inline CFDateRef CFDateCreateForGregorianDay(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, + int __unused hour, int __unused minute, int __unused second) { return CFDateCreate(allocator, CFAbsoluteTimeForGregorianDay(tz, year, month, day)); } diff --git a/OSX/utilities/SecCoreAnalytics.h b/OSX/utilities/SecCoreAnalytics.h index 244ffd28..f9608865 100644 --- a/OSX/utilities/SecCoreAnalytics.h +++ b/OSX/utilities/SecCoreAnalytics.h @@ -21,12 +21,19 @@ * @APPLE_LICENSE_HEADER_END@ */ -#import +#include + +void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value); +void SecCoreAnalyticsSendKernEntropyHealth(void); #if __OBJC__ +#import + NS_ASSUME_NONNULL_BEGIN +extern NSString* const SecCoreAnalyticsValue; + @interface SecCoreAnalytics : NSObject + (void)sendEvent:(NSString*) eventName event:(NSDictionary *)event; diff --git a/OSX/utilities/SecCoreAnalytics.m b/OSX/utilities/SecCoreAnalytics.m index 3e41cf17..c427e454 100644 --- a/OSX/utilities/SecCoreAnalytics.m +++ b/OSX/utilities/SecCoreAnalytics.m @@ -25,10 +25,89 @@ #import #import #import +#import + +NSString* const SecCoreAnalyticsValue = @"value"; + + +void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value) +{ + [SecCoreAnalytics sendEvent:(__bridge NSString*)eventName + event:@{ + SecCoreAnalyticsValue: [NSNumber numberWithLong:value], + }]; +} + +void SecCoreAnalyticsSendKernEntropyHealth() +{ + size_t sz_int = sizeof(int); + size_t sz_uint = sizeof(unsigned int); + size_t sz_tv = sizeof(struct timeval); + + int startup_done; + unsigned int adaptive_proportion_failure_count = 0; + unsigned int adaptive_proportion_max_observation_count = 0; + unsigned int adaptive_proportion_reset_count = 0; + unsigned int repetition_failure_count = 0; + unsigned int repetition_max_observation_count = 0; + unsigned int repetition_reset_count = 0; + + int rv = sysctlbyname("kern.entropy.health.startup_done", &startup_done, &sz_int, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.adaptive_proportion_test.failure_count", &adaptive_proportion_failure_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.adaptive_proportion_test.max_observation_count", &adaptive_proportion_max_observation_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.adaptive_proportion_test.reset_count", &adaptive_proportion_reset_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.repetition_count_test.failure_count", &repetition_failure_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.repetition_count_test.max_observation_count", &repetition_max_observation_count, &sz_uint, NULL, 0); + rv |= sysctlbyname("kern.entropy.health.repetition_count_test.reset_count", &repetition_reset_count, &sz_uint, NULL, 0); + + // Round up to next power of two. + if (adaptive_proportion_reset_count > 0) { + adaptive_proportion_reset_count = + 1U << (sizeof(unsigned int) * 8 - __builtin_clz(adaptive_proportion_reset_count)); + } + + // Round up to next power of two. + if (repetition_reset_count > 0) { + repetition_reset_count = + 1U << (sizeof(unsigned int) * 8 - __builtin_clz(repetition_reset_count)); + } + + // Default to not submitting uptime, except on failure. + int uptime = -1; + + if (adaptive_proportion_failure_count > 0 || repetition_failure_count > 0) { + time_t now; + time(&now); + + struct timeval boottime; + int mib[2] = { CTL_KERN, KERN_BOOTTIME }; + rv |= sysctl(mib, 2, &boottime, &sz_tv, NULL, 0); + + // Submit uptime in minutes. + uptime = (int)((now - boottime.tv_sec) / 60); + } + + if (rv) { + return; + } + + [SecCoreAnalytics sendEventLazy:@"com.apple.kern.entropyHealth" builder:^NSDictionary * _Nonnull{ + return @{ + @"uptime" : @(uptime), + @"startup_done" : @(startup_done), + @"adaptive_proportion_failure_count" : @(adaptive_proportion_failure_count), + @"adaptive_proportion_max_observation_count" : @(adaptive_proportion_max_observation_count), + @"adaptive_proportion_reset_count" : @(adaptive_proportion_reset_count), + @"repetition_failure_count" : @(repetition_failure_count), + @"repetition_max_observation_count" : @(repetition_max_observation_count), + @"repetition_reset_count" : @(repetition_reset_count) + }; + }]; +} @implementation SecCoreAnalytics -SOFT_LINK_FRAMEWORK_SAFE(PrivateFrameworks, CoreAnalytics); +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CoreAnalytics); SOFT_LINK_FUNCTION(CoreAnalytics, AnalyticsSendEvent, soft_AnalyticsSendEvent, \ void, (NSString* eventName, NSDictionary* eventPayload),(eventName, eventPayload)); diff --git a/OSX/utilities/SecDb.c b/OSX/utilities/SecDb.c index 729520a4..54ad9327 100644 --- a/OSX/utilities/SecDb.c +++ b/OSX/utilities/SecDb.c @@ -23,6 +23,7 @@ #include "SecDb.h" +#include "SecDbInternal.h" #include "debugging.h" #include @@ -87,9 +88,14 @@ struct __OpaqueSecDb { CFStringRef db_path; dispatch_queue_t queue; dispatch_queue_t commitQueue; - CFMutableArrayRef connections; - dispatch_semaphore_t write_semaphore; - dispatch_semaphore_t read_semaphore; + + CFMutableArrayRef idleWriteConnections; // up to kSecDbMaxWriters of them (currently 1, requires locking change for >1) + CFMutableArrayRef idleReadConnections; // up to kSecDbMaxReaders of them + pthread_mutex_t writeMutex; + pthread_mutexattr_t writeMutexAttrs; + // TODO: Replace after we have rdar://problem/60961964 + dispatch_semaphore_t readSemaphore; + bool didFirstOpen; bool (^opened)(SecDbRef db, SecDbConnectionRef dbconn, bool didCreate, bool *callMeAgainForNextConnection, CFErrorRef *error); bool callOpenedHandlerForNextConnection; @@ -200,7 +206,7 @@ static CFStringRef SecDbCopyFormatDescription(CFTypeRef value, CFDictionaryRef formatOptions) { SecDbRef db = (SecDbRef)value; - return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), db->db_path, db->connections); + return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), db->db_path, db->idleReadConnections); } @@ -208,8 +214,13 @@ static void SecDbDestroy(CFTypeRef value) { SecDbRef db = (SecDbRef)value; - CFReleaseNull(db->connections); + CFReleaseNull(db->db_path); + dispatch_sync(db->queue, ^{ + CFReleaseNull(db->idleWriteConnections); + CFReleaseNull(db->idleReadConnections); + }); + if (db->queue) { dispatch_release(db->queue); db->queue = NULL; @@ -218,14 +229,14 @@ SecDbDestroy(CFTypeRef value) dispatch_release(db->commitQueue); db->commitQueue = NULL; } - if (db->read_semaphore) { - dispatch_release(db->read_semaphore); - db->read_semaphore = NULL; - } - if (db->write_semaphore) { - dispatch_release(db->write_semaphore); - db->write_semaphore = NULL; + + pthread_mutex_destroy(&(db->writeMutex)); + + if (db->readSemaphore) { + dispatch_release(db->readSemaphore); + db->readSemaphore = NULL; } + if (db->opened) { Block_release(db->opened); db->opened = NULL; @@ -252,9 +263,23 @@ SecDbCreate(CFStringRef dbName, mode_t mode, bool readWrite, bool allowRepair, b db->commitQueue = dispatch_queue_create(cqNameStr, DISPATCH_QUEUE_CONCURRENT); }); CFReleaseNull(commitQueueStr); - db->read_semaphore = dispatch_semaphore_create(kSecDbMaxReaders); - db->write_semaphore = dispatch_semaphore_create(kSecDbMaxWriters); - db->connections = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + db->readSemaphore = dispatch_semaphore_create(kSecDbMaxReaders); + + bool mutexAttrSuccess = (0 == pthread_mutexattr_init(&(db->writeMutexAttrs))); + if(mutexAttrSuccess) { + mutexAttrSuccess = (0 == pthread_mutexattr_setpolicy_np(&(db->writeMutexAttrs), PTHREAD_MUTEX_POLICY_FAIRSHARE_NP)); + } + + if(!mutexAttrSuccess) { + seccritical("SecDb: SecDbCreate failed to create attributes for the write mutex; fairness properties are no longer present"); + } + + if (pthread_mutex_init(&(db->writeMutex), (mutexAttrSuccess ? &(db->writeMutexAttrs) : NULL)) != 0) { + seccritical("SecDb: SecDbCreate failed to init the write mutex, this will end badly"); + } + + db->idleWriteConnections = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + db->idleReadConnections = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); db->opened = opened ? Block_copy(opened) : NULL; if (getenv("__OSINSTALL_ENVIRONMENT") != NULL) { // TODO: Move this code out of this layer @@ -280,13 +305,15 @@ CFIndex SecDbIdleConnectionCount(SecDbRef db) { __block CFIndex count = 0; dispatch_sync(db->queue, ^{ - count = CFArrayGetCount(db->connections); + count = CFArrayGetCount(db->idleReadConnections); + count += CFArrayGetCount(db->idleWriteConnections); }); return count; } void SecDbAddNotifyPhaseBlock(SecDbRef db, SecDBNotifyBlock notifyPhase) { +#if !TARGET_OS_BRIDGE // SecDbNotifyPhase seems to mostly be called on the db's commitQueue, and not the db's queue. Therefore, protect the array with that queue. dispatch_sync(db->commitQueue, ^{ SecDBNotifyBlock block = Block_copy(notifyPhase); /* Force the block off the stack */ @@ -296,9 +323,11 @@ void SecDbAddNotifyPhaseBlock(SecDbRef db, SecDBNotifyBlock notifyPhase) CFArrayAppendValue(db->notifyPhase, block); Block_release(block); }); +#endif } static void SecDbNotifyPhase(SecDbConnectionRef dbconn, SecDbTransactionPhase phase) { +#if !TARGET_OS_BRIDGE if (CFArrayGetCount(dbconn->changes)) { CFArrayRef changes = dbconn->changes; dbconn->changes = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); @@ -310,6 +339,7 @@ static void SecDbNotifyPhase(SecDbConnectionRef dbconn, SecDbTransactionPhase ph } CFReleaseSafe(changes); } +#endif } static void SecDbOnNotify(SecDbConnectionRef dbconn, void (^perform)(void)) { @@ -781,11 +811,10 @@ bool SecDbStep(SecDbConnectionRef dbconn, sqlite3_stmt *stmt, CFErrorRef *error, bool SecDbCheckpoint(SecDbConnectionRef dbconn, CFErrorRef *error) { - return SecDbConnectionCheckCode(dbconn, sqlite3_wal_checkpoint(dbconn->handle, NULL), error, CFSTR("wal_checkpoint")); -} - -static bool SecDbFileControl(SecDbConnectionRef dbconn, int op, void *arg, CFErrorRef *error) { - return SecDbConnectionCheckCode(dbconn, sqlite3_file_control(dbconn->handle, NULL, op, arg), error, CFSTR("file_control")); + return SecDbConnectionCheckCode(dbconn, + sqlite3_wal_checkpoint_v2(dbconn->handle, NULL, SQLITE_CHECKPOINT_FULL, NULL, NULL), + error, + CFSTR("wal_checkpoint(FULL)")); } static sqlite3 *_SecDbOpenV2(const char *path, @@ -986,19 +1015,24 @@ SecDbProfileMask(void) static int SecDbTraceV2(unsigned mask, void *ctx, void *p, void *x) { SecDbConnectionRef dbconn __unused = ctx; + +#if SECDB_DEBUGGING const char *trace = "unknown"; + char *tofree = NULL; if (mask == SQLITE_TRACE_PROFILE) trace = sqlite3_sql(p); else if (mask == SQLITE_TRACE_STMT) { trace = sqlite3_sql(p); } else if (mask == SQLITE_TRACE_ROW) { - trace = sqlite3_expanded_sql(p); + trace = tofree = sqlite3_expanded_sql(p); } -#if SECDB_DEBUGGING secinfo("#SecDB", "#SecDB %{public}s", trace); + + sqlite3_free(tofree); #endif + return 0; } @@ -1015,7 +1049,12 @@ static bool SecDbOpenHandle(SecDbConnectionRef dbconn, bool *created, CFErrorRef } CFStringPerformWithCString(dbconn->db->db_path, ^(const char *db_path) { - int flags = (dbconn->db->readWrite) ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY; +#if TARGET_OS_IPHONE + int flags = SQLITE_OPEN_FILEPROTECTION_NONE; +#else + int flags = 0; +#endif + flags |= (dbconn->db->readWrite) ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY; ok = created && SecDbOpenV2(dbconn, db_path, flags, NULL); if (!ok) { ok = true; @@ -1036,7 +1075,11 @@ static bool SecDbOpenHandle(SecDbConnectionRef dbconn, bool *created, CFErrorRef } // if the enclosing directory is ok, try to create the database. // this forces us to open it read-write, so we'll need to be the owner here. - ok = ok && SecDbOpenV2(dbconn, db_path, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, error); + flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; +#if TARGET_OS_IPHONE + flags |= SQLITE_OPEN_FILEPROTECTION_NONE; +#endif + ok = ok && SecDbOpenV2(dbconn, db_path, flags, error); if (ok) { chmod(db_path, dbconn->db->mode); // default: 0600 (S_IRUSR | S_IWUSR) if (created) @@ -1089,21 +1132,36 @@ static void SecDbConectionSetReadOnly(SecDbConnectionRef dbconn, bool readOnly) dbconn->readOnly = readOnly; } -/* Read only connections go to the end of the queue, writeable connections - go to the start of the queue. */ SecDbConnectionRef SecDbConnectionAcquire(SecDbRef db, bool readOnly, CFErrorRef *error) { SecDbConnectionRef dbconn = NULL; SecDbConnectionAcquireRefMigrationSafe(db, readOnly, &dbconn, error); return dbconn; } +static void SecDbConnectionConsumeResource(SecDbRef db, bool readOnly) { + if (readOnly) { + dispatch_semaphore_wait(db->readSemaphore, DISPATCH_TIME_FOREVER); + } else { + pthread_mutex_lock(&(db->writeMutex)); + } +} + +static void SecDbConnectionMakeResourceAvailable(SecDbRef db, bool readOnly) { + if (readOnly) { + dispatch_semaphore_signal(db->readSemaphore); + } else { + pthread_mutex_unlock(&(db->writeMutex)); + } +} + bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbConnectionRef* dbconnRef, CFErrorRef *error) { CFRetain(db); #if SECDB_DEBUGGING secinfo("dbconn", "acquire %s connection", readOnly ? "ro" : "rw"); #endif - dispatch_semaphore_wait(readOnly ? db->read_semaphore : db->write_semaphore, DISPATCH_TIME_FOREVER); + SecDbConnectionConsumeResource(db, readOnly); + __block SecDbConnectionRef dbconn = NULL; __block bool ok = true; __block bool ranOpenedHandler = false; @@ -1140,29 +1198,23 @@ bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbCon if (ok) { db->didFirstOpen = ok = SecDbDidCreateFirstConnection(dbconn, didCreate, error); ranOpenedHandler = true; - } - if (!ok) + SecDbConectionSetReadOnly(dbconn, readOnly); // first connection always created "rw", so set to real value + } else { CFReleaseNull(dbconn); + } } else { /* Try to get one from the cache */ - CFIndex count = CFArrayGetCount(db->connections); - while (count && !dbconn) { - CFIndex ix = readOnly ? count - 1 : 0; - if (assignDbConn((SecDbConnectionRef)CFArrayGetValueAtIndex(db->connections, ix))) + CFMutableArrayRef cache = readOnly ? db->idleReadConnections : db->idleWriteConnections; + if (CFArrayGetCount(cache) && !dbconn) { + if (assignDbConn((SecDbConnectionRef)CFArrayGetValueAtIndex(cache, 0))) { CFRetainSafe(dbconn); - else - secerror("got NULL dbconn at index: %" PRIdCFIndex " skipping", ix); - CFArrayRemoveValueAtIndex(db->connections, ix); + } + CFArrayRemoveValueAtIndex(cache, 0); } } }); - if (dbconn) { - /* Make sure the connection we found has the right access */ - if (SecDbConnectionIsReadOnly(dbconn) != readOnly) { - SecDbConectionSetReadOnly(dbconn, readOnly); - } - } else if (ok) { + if (ok && !dbconn) { /* Nothing found in cache, create a new connection */ bool created = false; if (assignDbConn(SecDbConnectionCreate(db, readOnly, error)) && !SecDbOpenHandle(dbconn, &created, error)) { @@ -1170,7 +1222,6 @@ bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbCon } } - if (dbconn && !ranOpenedHandler && dbconn->db->opened) { dispatch_sync(db->queue, ^{ if (dbconn->db->callOpenedHandlerForNextConnection) { @@ -1189,8 +1240,8 @@ bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbCon } if (!dbconn) { - // If acquire fails we need to signal the semaphore again. - dispatch_semaphore_signal(readOnly ? db->read_semaphore : db->write_semaphore); + // Caller doesn't get (to use) a connection so the backing synchronization primitive is available again + SecDbConnectionMakeResourceAvailable(db, readOnly); CFRelease(db); } @@ -1199,33 +1250,38 @@ bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbCon void SecDbConnectionRelease(SecDbConnectionRef dbconn) { if (!dbconn) { - secerror("called with NULL dbconn"); + secerror("SecDbConnectionRelease called with NULL dbconn"); return; } SecDbRef db = dbconn->db; #if SECDB_DEBUGGING secinfo("dbconn", "release %@", dbconn); #endif + + bool readOnly = SecDbConnectionIsReadOnly(dbconn); dispatch_sync(db->queue, ^{ - bool readOnly = SecDbConnectionIsReadOnly(dbconn); if (dbconn->hasIOFailure) { // Something wrong on the file layer (e.g. revoked file descriptor for networked home) - // so we don't trust our existing connections anymore. - CFArrayRemoveAllValues(db->connections); + secwarning("SecDbConnectionRelease: IO failure reported in connection, throwing away currently idle caches"); + // Any other checked-out connections are beyond our grasp. If they did not have IO failures they'll come back, + // otherwise this branch gets taken more than once and gradually those connections die off + CFArrayRemoveAllValues(db->idleWriteConnections); + CFArrayRemoveAllValues(db->idleReadConnections); } else { - CFIndex count = CFArrayGetCount(db->connections); - // Add back possible writable dbconn to the pool. - CFArrayInsertValueAtIndex(db->connections, readOnly ? count : 0, dbconn); - // Remove the last (probably read-only) dbconn from the pool. - if (count >= db->maxIdleHandles) { - CFArrayRemoveValueAtIndex(db->connections, count); + CFMutableArrayRef cache = readOnly ? db->idleReadConnections : db->idleWriteConnections; + CFIndex count = CFArrayGetCount(cache); + if ((unsigned long)count < (readOnly ? kSecDbMaxReaders : kSecDbMaxWriters)) { + CFArrayAppendValue(cache, dbconn); + } else { + secerror("dbconn: did not expect to run out of room in the %s cache when releasing connection", readOnly ? "ro" : "rw"); } } - // Signal after we have put the connection back in the pool of connections - dispatch_semaphore_signal(readOnly ? db->read_semaphore : db->write_semaphore); - CFRelease(dbconn); - CFRelease(db); }); + + // Signal after we have put the connection back in the pool of connections + SecDbConnectionMakeResourceAvailable(db, readOnly); + CFRelease(dbconn); + CFRelease(db); } void SecDbReleaseAllConnections(SecDbRef db) { @@ -1235,9 +1291,31 @@ void SecDbReleaseAllConnections(SecDbRef db) { return; } dispatch_sync(db->queue, ^{ - CFArrayRemoveAllValues(db->connections); - dispatch_semaphore_signal(db->write_semaphore); - dispatch_semaphore_signal(db->read_semaphore); + CFArrayRemoveAllValues(db->idleReadConnections); + CFArrayRemoveAllValues(db->idleWriteConnections); + }); +} + +static void onQueueSecDbForceCloseForCache(CFMutableArrayRef cache) { + CFArrayForEach(cache, ^(const void* ptr) { + SecDbConnectionRef connection = (SecDbConnectionRef)ptr; + + // this pointer is claimed to be nonretained + connection->db = NULL; + + if(connection->handle) { + sqlite3_close(connection->handle); + connection->handle = NULL; + } + }); + CFArrayRemoveAllValues(cache); +} + +// Please make sure you want to do this. Any use of the outstanding connections to this DB will cause a crash. +void SecDbForceClose(SecDbRef db) { + dispatch_sync(db->queue, ^{ + onQueueSecDbForceCloseForCache(db->idleReadConnections); + onQueueSecDbForceCloseForCache(db->idleWriteConnections); }); } diff --git a/OSX/utilities/SecDb.h b/OSX/utilities/SecDb.h index b3c90402..9316e3e8 100644 --- a/OSX/utilities/SecDb.h +++ b/OSX/utilities/SecDb.h @@ -36,14 +36,6 @@ typedef struct __OpaqueSecDbConnection *SecDbConnectionRef; typedef struct __OpaqueSecDbStatement *SecDbStatementRef; struct SOSDigestVector; -// MARK: Configuration values, not used by clients directly. -// TODO: Move this section to a private header -enum { - kSecDbMaxReaders = 4, - kSecDbMaxWriters = 1, - kSecDbMaxIdleHandles = 3, -}; - // MARK: SecDbTransactionType enum { kSecDbNoneTransactionType = 0, @@ -125,6 +117,8 @@ bool SecDbPerformWrite(SecDbRef db, CFErrorRef *error, void (^perform)(SecDbConn CFIndex SecDbIdleConnectionCount(SecDbRef db); void SecDbReleaseAllConnections(SecDbRef db); +void SecDbForceClose(SecDbRef db); + CFStringRef SecDbGetPath(SecDbRef db); // MARK: - diff --git a/OSX/utilities/SecDbInternal.h b/OSX/utilities/SecDbInternal.h new file mode 100644 index 00000000..15a5ef20 --- /dev/null +++ b/OSX/utilities/SecDbInternal.h @@ -0,0 +1,14 @@ +#ifndef SecDbInternal_h +#define SecDbInternal_h + +#include "SecDb.h" + +static const size_t kSecDbMaxReaders = 5; + +// Do not increase this without changing lock types in SecDb +static const size_t kSecDbMaxWriters = 1; + +// maxreaders + maxwriters +static const size_t kSecDbMaxIdleHandles = 6; + +#endif /* SecDbInternal_h */ diff --git a/OSX/utilities/SecFileLocations.c b/OSX/utilities/SecFileLocations.c index db1281eb..14c54d90 100644 --- a/OSX/utilities/SecFileLocations.c +++ b/OSX/utilities/SecFileLocations.c @@ -46,37 +46,8 @@ #include #include "SecFileLocations.h" +#include "OSX/sec/Security/SecKnownFilePaths.h" -static CFURLRef sCustomHomeURL = NULL; - -CFURLRef SecCopyHomeURL(void) -{ - // This returns a CFURLRef so that it can be passed as the second parameter - // to CFURLCreateCopyAppendingPathComponent - - CFURLRef homeURL = sCustomHomeURL; - if (homeURL) { - CFRetain(homeURL); - } else { -#ifdef DARLING - // ported from an older version of Security - // - // i'm not sure how Apple is convincing the compiler that CFCopyHomeDirectoryURL is available on macOS - // because there's nothing new in the public headers to indicate that the function has suddenly become - // available on macOS, nor is there any indication in the Xcode build files that this code is being - // compiled for Catalyst for macOS - // - // maybe they're just not using compiler availability warnings/errors - // - // either way, this should work fine and provide the same behavior as Apple's code - homeURL = CFCopyHomeDirectoryURLForUser(NULL); -#else - homeURL = CFCopyHomeDirectoryURL(); -#endif - } - - return homeURL; -} #if TARGET_OS_OSX static const char * get_host_uuid() @@ -145,41 +116,22 @@ done: } #endif /* TARGET_OS_OSX */ -static CFURLRef SecCopyBaseFilesURL(bool system) -{ - CFURLRef baseURL = sCustomHomeURL; - if (baseURL) { - CFRetain(baseURL); - } else { -#if TARGET_OS_OSX - if (system) { - baseURL = CFURLCreateWithFileSystemPath(NULL, CFSTR("/"), kCFURLPOSIXPathStyle, true); - } else { - baseURL = SecCopyHomeURL(); - } -#elif TARGET_OS_SIMULATOR - baseURL = SecCopyHomeURL(); -#else - baseURL = CFURLCreateWithFileSystemPath(NULL, CFSTR("/"), kCFURLPOSIXPathStyle, true); -#endif - } - return baseURL; -} - -static CFURLRef SecCopyURLForFileInBaseDirectory(bool system, CFStringRef directoryPath, CFStringRef fileName) +CFURLRef SecCopyURLForFileInBaseDirectory(bool system, CFStringRef directoryPath, CFStringRef fileName) { CFURLRef fileURL = NULL; CFStringRef suffix = NULL; CFURLRef homeURL = SecCopyBaseFilesURL(system); - if (fileName) + if (fileName) { suffix = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@/%@"), directoryPath, fileName); - else - if (directoryPath) + } else if (directoryPath) { suffix = CFStringCreateCopy(kCFAllocatorDefault, directoryPath); + } - if (homeURL && suffix) - fileURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, homeURL, suffix, false); + bool isDirectory = !fileName; + if (homeURL && suffix) { + fileURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, homeURL, suffix, isDirectory); + } CFReleaseSafe(suffix); CFReleaseSafe(homeURL); return fileURL; @@ -274,12 +226,12 @@ CFURLRef SecCopyURLForFileInManagedPreferencesDirectory(CFStringRef fileName) return resultURL; } -CFURLRef SecCopyURLForFileInRevocationInfoDirectory(CFStringRef fileName) +CFURLRef SecCopyURLForFileInProtectedDirectory(CFStringRef fileName) { - return SecCopyURLForFileInBaseDirectory(true, CFSTR("Library/Keychains/crls/"), fileName); + return SecCopyURLForFileInBaseDirectory(true, CFSTR("private/var/protected/"), fileName); } -static void WithPathInDirectory(CFURLRef fileURL, void(^operation)(const char *utf8String)) +void WithPathInDirectory(CFURLRef fileURL, void(^operation)(const char *utf8String)) { /* Ownership of fileURL is taken by this function and so we release it. */ if (fileURL) { @@ -291,11 +243,6 @@ static void WithPathInDirectory(CFURLRef fileURL, void(^operation)(const char *u } } -void WithPathInRevocationInfoDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)) -{ - WithPathInDirectory(SecCopyURLForFileInRevocationInfoDirectory(fileName), operation); -} - void WithPathInKeychainDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)) { WithPathInDirectory(SecCopyURLForFileInKeychainDirectory(fileName), operation); @@ -306,28 +253,19 @@ void WithPathInUserCacheDirectory(CFStringRef fileName, void(^operation)(const c WithPathInDirectory(SecCopyURLForFileInUserCacheDirectory(fileName), operation); } -void SetCustomHomeURL(CFURLRef url) +void WithPathInProtectedDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)) { - sCustomHomeURL = CFRetainSafe(url); -} - - -void SetCustomHomeURLString(CFStringRef home_path) -{ - CFReleaseNull(sCustomHomeURL); - if (home_path) { - sCustomHomeURL = CFURLCreateWithFileSystemPath(NULL, home_path, kCFURLPOSIXPathStyle, true); - } + WithPathInDirectory(SecCopyURLForFileInProtectedDirectory(fileName), operation); } void SetCustomHomePath(const char* path) { if (path) { CFStringRef path_cf = CFStringCreateWithCStringNoCopy(NULL, path, kCFStringEncodingUTF8, kCFAllocatorNull); - SetCustomHomeURLString(path_cf); + SecSetCustomHomeURLString(path_cf); CFReleaseSafe(path_cf); } else { - SetCustomHomeURLString(NULL); + SecSetCustomHomeURLString(NULL); } } diff --git a/OSX/utilities/SecFileLocations.h b/OSX/utilities/SecFileLocations.h index 09dcd233..fcbe42eb 100644 --- a/OSX/utilities/SecFileLocations.h +++ b/OSX/utilities/SecFileLocations.h @@ -34,20 +34,22 @@ __BEGIN_DECLS +CFURLRef SecCopyURLForFileInBaseDirectory(bool system, CFStringRef directoryPath, CFStringRef fileName) CF_RETURNS_RETAINED; CFURLRef SecCopyURLForFileInKeychainDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; CFURLRef SecCopyURLForFileInSystemKeychainDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; CFURLRef SecCopyURLForFileInUserCacheDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; CFURLRef SecCopyURLForFileInPreferencesDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; CFURLRef SecCopyURLForFileInManagedPreferencesDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; -CFURLRef SecCopyURLForFileInRevocationInfoDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; +CFURLRef SecCopyURLForFileInProtectedDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; +void WithPathInDirectory(CFURLRef fileURL, void(^operation)(const char *utf8String)); void WithPathInKeychainDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); -void WithPathInRevocationInfoDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); void WithPathInUserCacheDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); +void WithPathInProtectedDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); void SetCustomHomePath(const char* path); -void SetCustomHomeURLString(CFStringRef path); -void SetCustomHomeURL(CFURLRef url); +void SecSetCustomHomeURLString(CFStringRef path); +void SecSetCustomHomeURL(CFURLRef url); CFURLRef SecCopyHomeURL(void) CF_RETURNS_RETAINED; diff --git a/OSX/utilities/SecKnownFilePaths.m b/OSX/utilities/SecKnownFilePaths.m new file mode 100644 index 00000000..e22c546d --- /dev/null +++ b/OSX/utilities/SecKnownFilePaths.m @@ -0,0 +1,57 @@ + +#import +#import "SecKnownFilePaths.h" +#import "OSX/utilities/SecCFRelease.h" + +// This file is separate from SecFileLocation.c because it has a global variable. +// We need exactly one of those per address space, so it needs to live in the Security framework. +static CFURLRef sCustomHomeURL = NULL; + +CFURLRef SecCopyHomeURL(void) +{ + // This returns a CFURLRef so that it can be passed as the second parameter + // to CFURLCreateCopyAppendingPathComponent + + CFURLRef homeURL = sCustomHomeURL; + if (homeURL) { + CFRetain(homeURL); + } else { + homeURL = CFCopyHomeDirectoryURL(); + } + + return homeURL; +} + +CFURLRef SecCopyBaseFilesURL(bool system) +{ + CFURLRef baseURL = sCustomHomeURL; + if (baseURL) { + CFRetain(baseURL); + } else { +#if TARGET_OS_OSX + if (system) { + baseURL = CFURLCreateWithFileSystemPath(NULL, CFSTR("/"), kCFURLPOSIXPathStyle, true); + } else { + baseURL = SecCopyHomeURL(); + } +#elif TARGET_OS_SIMULATOR + baseURL = SecCopyHomeURL(); +#else + baseURL = CFURLCreateWithFileSystemPath(NULL, CFSTR("/"), kCFURLPOSIXPathStyle, true); +#endif + } + return baseURL; +} + +void SecSetCustomHomeURL(CFURLRef url) +{ + sCustomHomeURL = CFRetainSafe(url); +} + +void SecSetCustomHomeURLString(CFStringRef home_path) +{ + CFReleaseNull(sCustomHomeURL); + if (home_path) { + sCustomHomeURL = CFURLCreateWithFileSystemPath(NULL, home_path, kCFURLPOSIXPathStyle, true); + } +} diff --git a/OSX/utilities/SecXPCError.c b/OSX/utilities/SecXPCError.c index 47e9266f..83b6f6b8 100644 --- a/OSX/utilities/SecXPCError.c +++ b/OSX/utilities/SecXPCError.c @@ -56,7 +56,7 @@ CFErrorRef SecCreateCFErrorWithXPCObject(xpc_object_t xpc_error) const uint8_t *der = xpc_dictionary_get_data(xpc_error, kUserInfoKey, &size); if (der) { const uint8_t *der_end = der + size; - der = der_decode_plist(kCFAllocatorDefault, kCFPropertyListImmutable, + der = der_decode_plist(kCFAllocatorDefault, &user_info, NULL, der, der_end); if (der != der_end) CFReleaseNull(user_info); diff --git a/OSX/utilities/SecXPCHelper.h b/OSX/utilities/SecXPCHelper.h index 905eca6d..019b49a1 100644 --- a/OSX/utilities/SecXPCHelper.h +++ b/OSX/utilities/SecXPCHelper.h @@ -12,13 +12,13 @@ NS_ASSUME_NONNULL_BEGIN @interface SecXPCHelper : NSObject + (NSSet *)safeErrorClasses; -+ (NSError *)cleanseErrorForXPC:(NSError * _Nullable)error; ++ (NSError * _Nullable)cleanseErrorForXPC:(NSError * _Nullable)error; /* * Some NSError objects contain non-NSSecureCoding-compliant userInfo. * When in doubt, use cleanseErrorForXPC: before encodedDataFromError: */ -+ (NSError *)errorFromEncodedData:(NSData *)data; ++ (NSError * _Nullable)errorFromEncodedData:(NSData *)data; + (NSData *)encodedDataFromError:(NSError *)error; @end diff --git a/OSX/utilities/SecXPCHelper.m b/OSX/utilities/SecXPCHelper.m index d9d80e09..73e3cf32 100644 --- a/OSX/utilities/SecXPCHelper.m +++ b/OSX/utilities/SecXPCHelper.m @@ -35,6 +35,32 @@ return errorClasses; } ++ (NSSet *)safeCKErrorPrimitiveClasses +{ + static NSMutableSet *errorClasses = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + errorClasses = [NSMutableSet set]; + char *classes[] = { + "CKArchivedAnchoredPackage", + "CKAsset", + "CKPackage", + "CKRecordID", + "CKReference", + "CLLocation", + }; + + for (unsigned n = 0; n < sizeof(classes) / sizeof(classes[0]); n++) { + Class class = objc_getClass(classes[n]); + if (class) { + [errorClasses addObject:class]; + } + } + }); + + return errorClasses; +} + + (NSSet *)safeErrorCollectionClasses { static NSMutableSet *errorClasses = nil; @@ -47,6 +73,7 @@ "NSError", "NSOrderedSet", "NSSet", + "NSURLError", }; for (unsigned n = 0; n < sizeof(classes) / sizeof(classes[0]); n++) { @@ -69,6 +96,9 @@ for (Class class in [SecXPCHelper safeErrorPrimitiveClasses]) { [errorClasses addObject:class]; } + for (Class class in [SecXPCHelper safeCKErrorPrimitiveClasses]) { + [errorClasses addObject:class]; + } for (Class class in [SecXPCHelper safeErrorCollectionClasses]) { [errorClasses addObject:class]; } @@ -143,7 +173,7 @@ return NSStringFromClass([object class]); } -+ (NSError *)cleanseErrorForXPC:(NSError * _Nullable)error ++ (NSError * _Nullable)cleanseErrorForXPC:(NSError * _Nullable)error { if (!error) { return nil; @@ -155,7 +185,7 @@ static NSString *kArchiveKeyError = @"error"; -+ (NSError *)errorFromEncodedData:(NSData *)data ++ (NSError * _Nullable)errorFromEncodedData:(NSData *)data { NSKeyedUnarchiver *unarchiver = nil; NSError *error = nil; diff --git a/OSX/utilities/SecXPCUtils.h b/OSX/utilities/SecXPCUtils.h new file mode 100644 index 00000000..46b9b355 --- /dev/null +++ b/OSX/utilities/SecXPCUtils.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* C interfaces to Foundation XPC utilities */ +#ifndef _UTILITIES_SECXPCUTILS_H_ +#define _UTILITIES_SECXPCUTILS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +CF_ASSUME_NONNULL_BEGIN + +/* SecXPCClientCanEditPreferenceOwnership identifies whether the calling + process has a keychain-access-groups entitlement of "*", which provides + a hint to the caller that its role is one which edits item ownership. + This hint is advisory only and is not used to grant access. +*/ +Boolean SecXPCClientCanEditPreferenceOwnership(void); + +/* SecXPCCopyClientApplicationIdentifier is designed only to return a + string which identifies the calling application. In the case where + there is no current XPC connection, the check is performed in-process. + As such, this identifier is advisory only and should not be used as + a security boundary. +*/ +CFStringRef SecXPCCopyClientApplicationIdentifier(void); + +CF_ASSUME_NONNULL_END + +#ifdef __cplusplus +} +#endif + +#endif /* _UTILITIES_SECXPCUTILS_H_ */ diff --git a/OSX/utilities/SecXPCUtils.m b/OSX/utilities/SecXPCUtils.m new file mode 100644 index 00000000..0f03905e --- /dev/null +++ b/OSX/utilities/SecXPCUtils.m @@ -0,0 +1,143 @@ +// +// SecXPCUtils.m +// Security +// + +#import +#import +#import +#import +#import +#import +#import +#import +#import "SecXPCUtils.h" + +@interface SecXPCUtils : NSObject ++ (BOOL)clientCanEditPreferenceOwnership; ++ (CFStringRef)copyApplicationIdentifier; +@end + +@implementation SecXPCUtils + +// IMPORTANT: These methods are designed to identify the calling process +// for applications which do not rely solely on that identification as a +// security boundary. When there is no NSXPCConnection, the SecTask check +// is made by the calling process on itself. As such, these identifiers can +// only be considered advisory. + ++ (BOOL)clientCanEditPreferenceOwnership +{ + NSXPCConnection* connection = [NSXPCConnection currentConnection]; + if (connection) { + NSArray *accessGroups = [connection valueForEntitlement:(__bridge NSString*)kSecEntitlementKeychainAccessGroups]; + if (accessGroups && [accessGroups isMemberOfClass:[NSArray class]] && [accessGroups containsObject:@"*"]) { + return YES; + } + } else { + SecTaskRef task = SecTaskCreateFromSelf(NULL); + if (task) { + CFTypeRef entitlementValue = SecTaskCopyValueForEntitlement(task, + kSecEntitlementKeychainAccessGroups, NULL); + CFRelease(task); + if (entitlementValue) { + BOOL result = NO; + if (CFGetTypeID(entitlementValue) == CFArrayGetTypeID() && + [(__bridge NSArray*)entitlementValue containsObject:@"*"]) { + result = YES; + } + CFRelease(entitlementValue); + return result; + } + } + } + return NO; +} + ++ (CFStringRef)copySigningIdentifier:(NSXPCConnection*)connection +{ + CFStringRef result = NULL; + SecTaskRef task = NULL; + if (connection) { + task = SecTaskCreateWithAuditToken(NULL, [connection auditToken]); + } else { + task = SecTaskCreateFromSelf(NULL); + } + if (task) { + result = SecTaskCopySigningIdentifier(task, NULL); + CFRelease(task); + } + return result; +} + ++ (CFStringRef)copyApplicationIdentifierFromSelf +{ + CFStringRef result = NULL; + SecTaskRef task = SecTaskCreateFromSelf(NULL); + if (task) { + CFTypeRef entitlementValue = SecTaskCopyValueForEntitlement(task, + kSecEntitlementBasicApplicationIdentifier, NULL); + if (!entitlementValue) { + entitlementValue = SecTaskCopyValueForEntitlement(task, + kSecEntitlementAppleApplicationIdentifier, NULL); + } + CFRelease(task); + if (entitlementValue) { + if (CFGetTypeID(entitlementValue) == CFStringGetTypeID()) { + result = entitlementValue; + } else { + CFRelease(entitlementValue); + } + } + } + if (!result) { + result = [SecXPCUtils copySigningIdentifier:nil]; + } + return result; +} + ++ (CFStringRef)copyApplicationIdentifierFromConnection:(NSXPCConnection*)connection +{ + CFStringRef result = NULL; + NSString* identifier = [connection valueForEntitlement:(__bridge NSString*)kSecEntitlementBasicApplicationIdentifier]; + if (!identifier) { + identifier = [connection valueForEntitlement:(__bridge NSString*)kSecEntitlementAppleApplicationIdentifier]; + } + if (identifier && [identifier isMemberOfClass:[NSString class]]) { + result = CFStringCreateCopy(NULL, (__bridge CFStringRef)identifier); + } + if (!result) { + result = [SecXPCUtils copySigningIdentifier:connection]; + } + return result; +} + ++ (CFStringRef)copyApplicationIdentifier +{ + NSXPCConnection* connection = [NSXPCConnection currentConnection]; + if (connection) { + return [SecXPCUtils copyApplicationIdentifierFromConnection:connection]; + } + return [SecXPCUtils copyApplicationIdentifierFromSelf]; +} + +@end + +Boolean SecXPCClientCanEditPreferenceOwnership(void) { + Boolean result = false; + @autoreleasepool { + if ([SecXPCUtils clientCanEditPreferenceOwnership] == YES) { + result = true; + } + } + return result; +} + +CFStringRef SecXPCCopyClientApplicationIdentifier(void) +{ + CFStringRef appIdStr = NULL; + @autoreleasepool { + appIdStr = [SecXPCUtils copyApplicationIdentifier]; + } + return appIdStr; +} diff --git a/OSX/utilities/debugging.c b/OSX/utilities/debugging.c index 14695726..b0bd2ce1 100644 --- a/OSX/utilities/debugging.c +++ b/OSX/utilities/debugging.c @@ -215,13 +215,6 @@ static int string_to_log_level(CFStringRef string) { return -1; } -static void CFSetAppendValues(CFSetRef set, CFMutableArrayRef appendTo) -{ - CFSetForEach(set, ^(const void *value) { - CFArrayAppendValue(appendTo, value); - }); -} - static CFMutableArrayRef CFSetOfCFObjectsCopyValues(CFSetRef setOfCFs) { CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); @@ -401,18 +394,6 @@ void __security_debug_init(void) { } - - -static char *copyScopeStr(CFStringRef scope, char *alternative) { - char *scopeStr = NULL; - if(scope) { - scopeStr = CFStringToCString(scope); - } else { - scopeStr = strdup("noScope"); - } - return scopeStr; -} - os_log_t secLogObjForCFScope(CFStringRef scope) { diff --git a/OSX/utilities/debugging.h b/OSX/utilities/debugging.h index 52769f19..caa2b9c2 100644 --- a/OSX/utilities/debugging.h +++ b/OSX/utilities/debugging.h @@ -144,6 +144,9 @@ void __security_stackshotreport(CFStringRef reason, uint32_t code); #define __sec_exception_code_SQLiteBusy __sec_exception_code(10) #define __sec_exception_code_CorruptDb(rc) __sec_exception_code(11|((rc)<<8)) #define __sec_exception_code_Watchdog __sec_exception_code(12) +#define __sec_exception_code_BadStash __sec_exception_code(13) +#define __sec_exception_code_UnexpectedState __sec_exception_code(14) +#define __sec_exception_code_RateLimit __sec_exception_code(15) /* For testing only, turns off/on simulated crashes, when turning on, returns number of simulated crashes which were not reported since last turned off. */ diff --git a/OSX/utilities/der_array.c b/OSX/utilities/der_array.c index 95eaf95e..9a01f021 100644 --- a/OSX/utilities/der_array.c +++ b/OSX/utilities/der_array.c @@ -32,21 +32,26 @@ #include -const uint8_t* der_decode_array(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_array(CFAllocatorRef allocator, CFArrayRef* array, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } CFMutableArrayRef result = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); const uint8_t *elements_end; const uint8_t *current_element = ccder_decode_sequence_tl(&elements_end, der, der_end); + if (!current_element) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("tag/length decode failed"), NULL, error); + } while (current_element != NULL && current_element < elements_end) { CFPropertyListRef element = NULL; - current_element = der_decode_plist(allocator, mutability, &element, error, current_element, elements_end); + current_element = der_decode_plist(allocator, &element, error, current_element, elements_end); if (current_element) { CFArrayAppendValue(result, element); CFReleaseNull(element); @@ -78,14 +83,22 @@ size_t der_sizeof_array(CFArrayRef data, CFErrorRef *error) uint8_t* der_encode_array(CFArrayRef array, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) +{ + return der_encode_array_repair(array, error, false, der, der_end); +} + +uint8_t* der_encode_array_repair(CFArrayRef array, CFErrorRef *error, + bool repair, + const uint8_t *der, uint8_t *der_end) { uint8_t* original_der_end = der_end; for(CFIndex position = CFArrayGetCount(array) - 1; position >= 0; --position) { - der_end = der_encode_plist(CFArrayGetValueAtIndex(array, position), error, der, der_end); + der_end = der_encode_plist_repair(CFArrayGetValueAtIndex(array, position), error, repair, der, der_end); } - - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, der_end); + + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, der_end), + error); } diff --git a/OSX/utilities/der_boolean.c b/OSX/utilities/der_boolean.c index 986c3132..0ab42b49 100644 --- a/OSX/utilities/der_boolean.c +++ b/OSX/utilities/der_boolean.c @@ -32,12 +32,14 @@ #include -const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFBooleanRef* boolean, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); @@ -64,7 +66,8 @@ uint8_t* der_encode_boolean(CFBooleanRef boolean, CFErrorRef *error, { uint8_t value = CFBooleanGetValue(boolean); - return ccder_encode_tl(CCDER_BOOLEAN, 1, der, - ccder_encode_body(1, &value, der, der_end)); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_BOOLEAN, 1, der, + ccder_encode_body(1, &value, der, der_end)), + error); } diff --git a/OSX/utilities/der_data.c b/OSX/utilities/der_data.c index b29ddfe0..83bdcec6 100644 --- a/OSX/utilities/der_data.c +++ b/OSX/utilities/der_data.c @@ -32,40 +32,14 @@ #include -const uint8_t* der_decode_data_mutable(CFAllocatorRef allocator, CFOptionFlags mutability, - CFMutableDataRef* data, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); - - if (NULL == payload || (ssize_t) (der_end - payload) < (ssize_t) payload_size) { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding"), NULL, error); - return NULL; - } - - *data = CFDataCreateMutable(allocator, 0); - - if (NULL == *data) { - SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create data"), NULL, error); - return NULL; - } - - CFDataAppendBytes(*data, payload, payload_size); - - return payload + payload_size; -} - - -const uint8_t* der_decode_data(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_data(CFAllocatorRef allocator, CFDataRef* data, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); @@ -97,7 +71,8 @@ uint8_t* der_encode_data(CFDataRef data, CFErrorRef *error, { const CFIndex data_length = CFDataGetLength(data); - return ccder_encode_tl(CCDER_OCTET_STRING, data_length, der, - ccder_encode_body(data_length, CFDataGetBytePtr(data), der, der_end)); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_OCTET_STRING, data_length, der, + ccder_encode_body(data_length, CFDataGetBytePtr(data), der, der_end)), + error); } diff --git a/OSX/utilities/der_date.c b/OSX/utilities/der_date.c index 0bdde9cc..d930f660 100644 --- a/OSX/utilities/der_date.c +++ b/OSX/utilities/der_date.c @@ -39,13 +39,26 @@ /* Cumulative number of days in the year for months up to month i. */ static int mdays[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; +static bool validateDateComponents(int year, int month, int day, int hour, int minute, int second, int *is_leap_year, CFErrorRef* error) +{ + int leapyear = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) ? 1 : 0; + if (is_leap_year) { + *is_leap_year = leapyear; + } + if (month < 1 || month > 12 || day < 1 || day > 31 || hour >= 24 || minute >= 60 || second > 61 + || (month == 2 && day > mdays[month] - mdays[month - 1] + leapyear) + || (month != 2 && day > mdays[month] - mdays[month - 1])) + { + SecError(kSecDERErrorUnknownEncoding, error, CFSTR("Invalid date: %i, %i, %i, %i, %i, %i, %i"), year, month, day, hour, minute, second, leapyear); + return false; + } + + return true; +} + static CFAbsoluteTime SecGregorianDateGetAbsoluteTime(int year, int month, int day, int hour, int minute, int second, CFTimeInterval timeZoneOffset, CFErrorRef *error) { - int is_leap_year = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) ? 1 : 0; - if (month < 1 || month > 12 || day < 1 || day > 31 || hour >= 24 || minute >= 60 || second >= 60.0 - || (month == 2 && day > mdays[month] - mdays[month - 1] + is_leap_year) - || (month != 2 && day > mdays[month] - mdays[month - 1])) { - /* Invalid date. */ - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Invalid date."), 0, error); + int is_leap_year = 0; + if (!validateDateComponents(year, month, day, hour, minute, second, &is_leap_year, error)) { return NULL_TIME; } @@ -72,8 +85,10 @@ static bool SecAbsoluteTimeGetGregorianDate(CFTimeInterval at, int *year, int *m SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) { result = CFCalendarDecomposeAbsoluteTime(zuluCalendar, at, "yMdHms", year, month, day, hour, minute, second); }); - if (!result) + if (!result) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Failed to encode date."), 0, error); + } + return result; } @@ -144,9 +159,11 @@ static const uint8_t *der_decode_decimal_fraction(double *fraction, CFErrorRef * value += (ch - '0'); } } - if (der >= der_end) + if (der >= der_end) { + SecCFDERCreateError(kSecDERErrorOverflow, + CFSTR("overflow"), 0, error); der = NULL; - else if (last == '0') { + } else if (last == '0') { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("fraction ends in 0"), 0, error); der = NULL; @@ -205,14 +222,6 @@ static const uint8_t* der_decode_commontime_body(CFAbsoluteTime *at, CFErrorRef CFTimeInterval timeZoneOffset = der_decode_timezone_offset(&der, der_end, error); -#if 0 - secinfo("dateparse", - "date %.*s year: %04d%02d%02d%02d%02d%02d%+05g", - length, bytes, g.year, g.month, - g.day, g.hour, g.minute, g.second, - timeZoneOffset / 60); -#endif - if (der) { if (der != der_end) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, @@ -257,12 +266,14 @@ const uint8_t* der_decode_universaltime_body(CFAbsoluteTime *at, CFErrorRef *err return der_decode_commontime_body(at, error, year, der, der_end); } -const uint8_t* der_decode_date(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_date(CFAllocatorRef allocator, CFDateRef* date, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } der = ccder_decode_constructed_tl(CCDER_GENERALIZED_TIME, &der_end, der, der_end); CFAbsoluteTime at = 0; @@ -373,13 +384,38 @@ static uint8_t *ccder_encode_nanoseconds(CFAbsoluteTime at, const uint8_t *der, return der_end; } -/* Encode generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) +{ + return der_encode_generalizedtime_body_repair(at, error, false, der, der_end); +} + +/* Encode generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ +uint8_t* der_encode_generalizedtime_body_repair(CFAbsoluteTime at, CFErrorRef *error, bool repair, + const uint8_t *der, uint8_t *der_end) { int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; - if (!SecAbsoluteTimeGetGregorianDate(at, &year, &month, &day, &hour, &minute, &second, error)) + if (!SecAbsoluteTimeGetGregorianDate(at, &year, &month, &day, &hour, &minute, &second, error)) { + secerror("der: unable to encode date: %@", error ? *error : NULL); return NULL; + } + + // Without repair flag, do not let validation change result so we do not change existing behavior + CFErrorRef localError = NULL; + if (!validateDateComponents(year, month, day, hour, minute, second, 0, &localError)) { + CFStringRef desc = CFErrorCopyDescription(localError); + __security_simulatecrash(desc, __sec_exception_code_CorruptItem); + CFReleaseNull(desc); + secerror("der: invalid date: %@; %s", localError, repair ? "setting default value" : "continuing"); + CFReleaseNull(localError); + if (repair) { + year = 2001; + month = 1; + day = 1; + // I don't think this is required but I don't want any funny business with exactly midnight in any timezone + minute = 1; + } + } uint8_t * result = ccder_encode_decimal_quad(year, der, ccder_encode_decimal_pair(month, der, @@ -387,17 +423,18 @@ uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, ccder_encode_decimal_pair(hour, der, ccder_encode_decimal_pair(minute, der, ccder_encode_decimal_pair(second, der, - ccder_encode_nanoseconds(at, der, + ccder_encode_nanoseconds(at, der, // Uses original "at" even after repair because DER length calculations depend on its exact value ccder_encode_byte('Z', der, der_end)))))))); - return result; + return SecCCDEREncodeHandleResult(result, error); } uint8_t* der_encode_generalizedtime(CFAbsoluteTime at, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { - return ccder_encode_constructed_tl(CCDER_GENERALIZED_TIME, der_end, der, - der_encode_generalizedtime_body(at, error, der, der_end)); + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_GENERALIZED_TIME, der_end, der, + der_encode_generalizedtime_body(at, error, der, der_end)), + error); } @@ -407,3 +444,11 @@ uint8_t* der_encode_date(CFDateRef date, CFErrorRef *error, return der_encode_generalizedtime(CFDateGetAbsoluteTime(date), error, der, der_end); } + +uint8_t* der_encode_date_repair(CFDateRef date, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end) +{ + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_GENERALIZED_TIME, der_end, der, + der_encode_generalizedtime_body_repair(CFDateGetAbsoluteTime(date), error, repair, der, der_end)), + error); +} diff --git a/OSX/utilities/der_date.h b/OSX/utilities/der_date.h index 327ea7de..a92871b6 100644 --- a/OSX/utilities/der_date.h +++ b/OSX/utilities/der_date.h @@ -39,5 +39,7 @@ uint8_t* der_encode_generalizedtime(CFAbsoluteTime at, CFErrorRef *error, size_t der_sizeof_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error); uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); +uint8_t* der_encode_generalizedtime_body_repair(CFAbsoluteTime at, CFErrorRef *error, bool repair, + const uint8_t *der, uint8_t *der_end); #endif /* _UTILITIES_DER_DATE_H_ */ diff --git a/OSX/utilities/der_dictionary.c b/OSX/utilities/der_dictionary.c index bb002953..2d921d3f 100644 --- a/OSX/utilities/der_dictionary.c +++ b/OSX/utilities/der_dictionary.c @@ -32,7 +32,7 @@ #include #include -static const uint8_t* der_decode_key_value(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_key_value(CFAllocatorRef allocator, CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { @@ -48,8 +48,8 @@ static const uint8_t* der_decode_key_value(CFAllocatorRef allocator, CFOptionFla CFTypeRef valueObject = NULL; - payload = der_decode_plist(allocator, mutability, &keyObject, error, payload, payload_end); - payload = der_decode_plist(allocator, mutability, &valueObject, error, payload, payload_end); + payload = der_decode_plist(allocator, &keyObject, error, payload, payload_end); + payload = der_decode_plist(allocator, &valueObject, error, payload, payload_end); if (payload != NULL) { *key = keyObject; @@ -61,12 +61,14 @@ static const uint8_t* der_decode_key_value(CFAllocatorRef allocator, CFOptionFla return payload; } -const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFDictionaryRef* dictionary, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } const uint8_t *payload_end = 0; const uint8_t *payload = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SET, &payload_end, der, der_end); @@ -89,7 +91,7 @@ const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFOptionFlags mut CFTypeRef key = NULL; CFTypeRef value = NULL; - payload = der_decode_key_value(allocator, mutability, &key, &value, error, payload, payload_end); + payload = der_decode_key_value(allocator, &key, &value, error, payload, payload_end); if (payload) { CFDictionaryAddValue(dict, key, value); @@ -120,10 +122,12 @@ struct size_context { static size_t der_sizeof_key_value(CFTypeRef key, CFTypeRef value, CFErrorRef *error) { size_t key_size = der_sizeof_plist(key, error); if (key_size == 0) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return 0; } size_t value_size = der_sizeof_plist(value, error); if (value_size == 0) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return 0; } return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, key_size + value_size); @@ -161,15 +165,18 @@ size_t der_sizeof_dictionary(CFDictionaryRef dict, CFErrorRef *error) } static uint8_t* der_encode_key_value(CFPropertyListRef key, CFPropertyListRef value, CFErrorRef *error, + bool repair, const uint8_t* der, uint8_t *der_end) { - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - der_encode_plist(key, error, der, - der_encode_plist(value, error, der, der_end))); + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + der_encode_plist_repair(key, error, repair, der, + der_encode_plist_repair(value, error, repair, der, der_end))), + error); } struct encode_context { bool success; + bool repair_contents; CFErrorRef * error; CFMutableArrayRef list; CFAllocatorRef allocator; @@ -192,7 +199,7 @@ static void add_sequence_to_array(const void *key_void, const void *value_void, uint8_t* const encode_begin = CFDataGetMutableBytePtr(encoded_kv); uint8_t* encode_end = encode_begin + der_size; - encode_end = der_encode_key_value(key, value, context->error, encode_begin, encode_end); + encode_end = der_encode_key_value(key, value, context->error, context->repair_contents, encode_begin, encode_end); if (encode_end != NULL) { CFDataDeleteBytes(encoded_kv, CFRangeMake(0, (encode_end - encode_begin))); @@ -206,18 +213,24 @@ static void add_sequence_to_array(const void *key_void, const void *value_void, } } -static CFComparisonResult cfdata_compare_contents(const void *val1, const void *val2, void *context __unused) +static CFComparisonResult cfdata_compare_der_contents(const void *val1, const void *val2, void *context __unused) { - return CFDataCompare((CFDataRef) val1, (CFDataRef) val2); + return CFDataCompareDERData((CFDataRef) val1, (CFDataRef) val2); } uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) +{ + return der_encode_dictionary_repair(dictionary, error, false, der, der_end); +} + +uint8_t* der_encode_dictionary_repair(CFDictionaryRef dictionary, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end) { CFMutableArrayRef elements = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - struct encode_context context = { .success = true, .error = error, .list = elements }; + struct encode_context context = { .success = true, .error = error, .list = elements, .repair_contents = repair }; CFDictionaryApplyFunction(dictionary, add_sequence_to_array, &context); if (!context.success) { @@ -227,7 +240,7 @@ uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error, CFRange allOfThem = CFRangeMake(0, CFArrayGetCount(elements)); - CFArraySortValues(elements, allOfThem, cfdata_compare_contents, NULL); + CFArraySortValues(elements, allOfThem, cfdata_compare_der_contents, NULL); uint8_t* original_der_end = der_end; @@ -239,6 +252,7 @@ uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error, CFReleaseNull(elements); - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SET, original_der_end, der, der_end); + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SET, original_der_end, der, der_end), + error); } diff --git a/OSX/utilities/der_null.c b/OSX/utilities/der_null.c index b462a031..de3c0bf6 100644 --- a/OSX/utilities/der_null.c +++ b/OSX/utilities/der_null.c @@ -32,12 +32,14 @@ #include -const uint8_t* der_decode_null(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_null(CFAllocatorRef allocator, CFNullRef* nul, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_NULL, &payload_size, der, der_end); @@ -62,5 +64,6 @@ size_t der_sizeof_null(CFNullRef data __unused, CFErrorRef *error) uint8_t* der_encode_null(CFNullRef boolean __unused, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { - return ccder_encode_tl(CCDER_NULL, 0, der, der_end); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_NULL, 0, der, der_end), + error); } diff --git a/OSX/utilities/der_number.c b/OSX/utilities/der_number.c index 29560a71..c47ce8a2 100644 --- a/OSX/utilities/der_number.c +++ b/OSX/utilities/der_number.c @@ -33,12 +33,14 @@ #include -const uint8_t* der_decode_number(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_number(CFAllocatorRef allocator, CFNumberRef* number, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_INTEGER, &payload_size, der, der_end); @@ -50,7 +52,6 @@ const uint8_t* der_decode_number(CFAllocatorRef allocator, CFOptionFlags mutabil if (payload_size > sizeof(long long)) { SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Number too large"), NULL, error); return NULL; - } long long value = 0; @@ -107,8 +108,10 @@ static inline size_t bytes_when_encoded(long long value) size_t der_sizeof_number(CFNumberRef data, CFErrorRef *error) { long long value; - if (!CFNumberGetValue(data, kCFNumberLongLongType, &value)) + if (!CFNumberGetValue(data, kCFNumberLongLongType, &value)) { + SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Unable to get number from data"), NULL, error); return 0; + } return ccder_sizeof(CCDER_INTEGER, bytes_when_encoded(value)); } @@ -117,13 +120,17 @@ uint8_t* der_encode_number(CFNumberRef number, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { long long value; - if (!CFNumberGetValue(number, kCFNumberLongLongType, &value)) + if (!CFNumberGetValue(number, kCFNumberLongLongType, &value)) { + SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Unable to get number from data"), NULL, error); return NULL; + } size_t first_byte_to_include = bytes_when_encoded(value); - if (!der_end || (ssize_t) (der_end - der) < (ssize_t) first_byte_to_include) + if (!der_end || (ssize_t) (der_end - der) < (ssize_t) first_byte_to_include) { + SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Unknown size"), NULL, error); return NULL; + } // Put the bytes we should include on the end. for(size_t bytes_included = 0; bytes_included < first_byte_to_include; ++bytes_included) @@ -133,6 +140,7 @@ uint8_t* der_encode_number(CFNumberRef number, CFErrorRef *error, value >>= 8; } - return ccder_encode_tl(CCDER_INTEGER, first_byte_to_include, der, der_end); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_INTEGER, first_byte_to_include, der, der_end), + error); } diff --git a/OSX/utilities/der_plist.c b/OSX/utilities/der_plist.c index e053c3f4..5e9c0c87 100644 --- a/OSX/utilities/der_plist.c +++ b/OSX/utilities/der_plist.c @@ -31,6 +31,8 @@ #include #include +#include "utilities/simulatecrash_assert.h" + // // der..CFPropertyList // @@ -48,35 +50,40 @@ // // -const uint8_t* der_decode_plist(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_plist(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) -{ if (NULL == der) - return NULL; +{ + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); + return NULL; + } ccder_tag tag; - if (NULL == ccder_decode_tag(&tag, der, der_end)) + if (NULL == ccder_decode_tag(&tag, der, der_end)) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("invalid tag"), NULL, error); return NULL; + } switch (tag) { case CCDER_NULL: - return der_decode_null(allocator, mutability, (CFNullRef*)pl, error, der, der_end); + return der_decode_null(allocator, (CFNullRef*)pl, error, der, der_end); case CCDER_BOOLEAN: - return der_decode_boolean(allocator, mutability, (CFBooleanRef*)pl, error, der, der_end); + return der_decode_boolean(allocator, (CFBooleanRef*)pl, error, der, der_end); case CCDER_OCTET_STRING: - return der_decode_data(allocator, mutability, (CFDataRef*)pl, error, der, der_end); + return der_decode_data(allocator, (CFDataRef*)pl, error, der, der_end); case CCDER_GENERALIZED_TIME: - return der_decode_date(allocator, mutability, (CFDateRef*)pl, error, der, der_end); + return der_decode_date(allocator, (CFDateRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_SEQUENCE: - return der_decode_array(allocator, mutability, (CFArrayRef*)pl, error, der, der_end); + return der_decode_array(allocator, (CFArrayRef*)pl, error, der, der_end); case CCDER_UTF8_STRING: - return der_decode_string(allocator, mutability, (CFStringRef*)pl, error, der, der_end); + return der_decode_string(allocator, (CFStringRef*)pl, error, der, der_end); case CCDER_INTEGER: - return der_decode_number(allocator, mutability, (CFNumberRef*)pl, error, der, der_end); + return der_decode_number(allocator, (CFNumberRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_SET: - return der_decode_dictionary(allocator, mutability, (CFDictionaryRef*)pl, error, der, der_end); + return der_decode_dictionary(allocator, (CFDictionaryRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_CFSET: - return der_decode_set(allocator, mutability, (CFSetRef*)pl, error, der, der_end); + return der_decode_set(allocator, (CFSetRef*)pl, error, der, der_end); default: SecCFDERCreateError(kSecDERErrorUnsupportedDERType, CFSTR("Unsupported DER Type"), NULL, error); return NULL; @@ -109,17 +116,22 @@ size_t der_sizeof_plist(CFPropertyListRef pl, CFErrorRef *error) return der_sizeof_string((CFStringRef) pl, error); else if (CFNumberGetTypeID() == dataType) return der_sizeof_number((CFNumberRef) pl, error); - if (CFNullGetTypeID() == dataType) - return der_sizeof_null((CFNullRef) pl, error); - else { + else if (CFNullGetTypeID() == dataType) + return der_sizeof_null((CFNullRef) pl, error); + else { SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Unsupported CFType"), NULL, error); return 0; } } - uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) +{ + return der_encode_plist_repair(pl, error, false, der, der_end); +} + +uint8_t* der_encode_plist_repair(CFPropertyListRef pl, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end) { if (!pl) { SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Null CFType"), NULL, error); @@ -129,23 +141,23 @@ uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error, CFTypeID dataType = CFGetTypeID(pl); if (CFArrayGetTypeID() == dataType) - return der_encode_array((CFArrayRef) pl, error, der, der_end); + return der_encode_array_repair((CFArrayRef) pl, error, repair, der, der_end); else if (CFBooleanGetTypeID() == dataType) return der_encode_boolean((CFBooleanRef) pl, error, der, der_end); else if (CFDataGetTypeID() == dataType) return der_encode_data((CFDataRef) pl, error, der, der_end); else if (CFDateGetTypeID() == dataType) - return der_encode_date((CFDateRef) pl, error, der, der_end); + return der_encode_date_repair((CFDateRef) pl, error, repair, der, der_end); else if (CFDictionaryGetTypeID() == dataType) - return der_encode_dictionary((CFDictionaryRef) pl, error, der, der_end); + return der_encode_dictionary_repair((CFDictionaryRef) pl, error, repair, der, der_end); else if (CFSetGetTypeID() == dataType) - return der_encode_set((CFSetRef) pl, error, der, der_end); + return der_encode_set_repair((CFSetRef) pl, error, repair, der, der_end); else if (CFStringGetTypeID() == dataType) return der_encode_string((CFStringRef) pl, error, der, der_end); else if (CFNumberGetTypeID() == dataType) return der_encode_number((CFNumberRef) pl, error, der, der_end); - else if (CFNullGetTypeID() == dataType) - return der_encode_null((CFNullRef) pl, error, der, der_end); + else if (CFNullGetTypeID() == dataType) + return der_encode_null((CFNullRef) pl, error, der, der_end); else { SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Unsupported CFType"), NULL, error); return NULL; @@ -174,7 +186,7 @@ CFPropertyListRef CFPropertyListCreateWithDERData(CFAllocatorRef allocator, CFDa CFPropertyListRef plist = NULL; const uint8_t *der = CFDataGetBytePtr(data); const uint8_t *der_end = der + CFDataGetLength(data); - der = der_decode_plist(0, kCFPropertyListMutableContainers, &plist, error, der, der_end); + der = der_decode_plist(0, &plist, error, der, der_end); if (der && der != der_end) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("trailing garbage after plist item"), NULL, error); CFReleaseNull(plist); diff --git a/OSX/utilities/der_plist.h b/OSX/utilities/der_plist.h index 36629478..109e082f 100644 --- a/OSX/utilities/der_plist.h +++ b/OSX/utilities/der_plist.h @@ -40,6 +40,9 @@ static const CFIndex kSecDERErrorUnsupportedDERType = -2; static const CFIndex kSecDERErrorAllocationFailure = -3; static const CFIndex kSecDERErrorUnsupportedNumberType = -4; static const CFIndex kSecDERErrorUnsupportedCFObject = -5; +static const CFIndex kSecDERErrorNullInput = -6; +static const CFIndex kSecDERErrorCCDEREncode = -7; +static const CFIndex kSecDERErrorOverflow = -8; extern CFStringRef sSecDERErrorDomain; @@ -55,7 +58,11 @@ size_t der_sizeof_plist(CFPropertyListRef pl, CFErrorRef *error); uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_plist(CFAllocatorRef pl, CFOptionFlags mutability, +// When allowed to repair, if certain objects (right now only Dates) do not validate, set them to recognizable defaults +uint8_t* der_encode_plist_repair(CFPropertyListRef pl, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end); + +const uint8_t* der_decode_plist(CFAllocatorRef pl, CFPropertyListRef* cf, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); diff --git a/OSX/utilities/der_plist_internal.c b/OSX/utilities/der_plist_internal.c index 017834f1..5b1041b4 100644 --- a/OSX/utilities/der_plist_internal.c +++ b/OSX/utilities/der_plist_internal.c @@ -25,6 +25,15 @@ #include "utilities/der_plist_internal.h" #include "utilities/SecCFError.h" #include "utilities/SecCFRelease.h" +#include "utilities/der_plist.h" #include CFStringRef sSecDERErrorDomain = CFSTR("com.apple.security.cfder.error"); + +uint8_t * SecCCDEREncodeHandleResult(uint8_t *der, CFErrorRef *newError) +{ + if (!der) { + SecCFDERCreateError(kSecDERErrorCCDEREncode, CFSTR("ccder failed to encode"), NULL, newError); + } + return der; +} diff --git a/OSX/utilities/der_plist_internal.h b/OSX/utilities/der_plist_internal.h index 6b334d8e..cd9bf587 100644 --- a/OSX/utilities/der_plist_internal.h +++ b/OSX/utilities/der_plist_internal.h @@ -32,14 +32,19 @@ #define SecCFDERCreateError(errorCode, descriptionString, previousError, newError) \ SecCFCreateErrorWithFormat(errorCode, sSecDERErrorDomain, previousError, newError, NULL, descriptionString) +uint8_t * SecCCDEREncodeHandleResult(uint8_t *der, CFErrorRef *newError); + // CFArray <-> DER size_t der_sizeof_array(CFArrayRef array, CFErrorRef *error); uint8_t* der_encode_array(CFArrayRef array, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); +uint8_t* der_encode_array_repair(CFArrayRef array, CFErrorRef *error, + bool repair, + const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_array(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_array(CFAllocatorRef allocator, CFArrayRef* array, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -49,7 +54,7 @@ size_t der_sizeof_null(CFNullRef nul, CFErrorRef *error); uint8_t* der_encode_null(CFNullRef nul, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_null(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_null(CFAllocatorRef allocator, CFNullRef *nul, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -60,7 +65,7 @@ size_t der_sizeof_boolean(CFBooleanRef boolean, CFErrorRef *error); uint8_t* der_encode_boolean(CFBooleanRef boolean, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFBooleanRef* boolean, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -70,22 +75,20 @@ size_t der_sizeof_data(CFDataRef data, CFErrorRef *error); uint8_t* der_encode_data(CFDataRef data, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_data(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_data(CFAllocatorRef allocator, CFDataRef* data, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); -const uint8_t* der_decode_data_mutable(CFAllocatorRef allocator, CFOptionFlags mutability, - CFMutableDataRef* data, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end); - - // CFDate <-> DER size_t der_sizeof_date(CFDateRef date, CFErrorRef *error); uint8_t* der_encode_date(CFDateRef date, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_date(CFAllocatorRef allocator, CFOptionFlags mutability, +uint8_t* der_encode_date_repair(CFDateRef date, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end); + +const uint8_t* der_decode_date(CFAllocatorRef allocator, CFDateRef* date, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -95,8 +98,10 @@ size_t der_sizeof_dictionary(CFDictionaryRef dictionary, CFErrorRef *error); uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); +uint8_t* der_encode_dictionary_repair(CFDictionaryRef dictionary, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFDictionaryRef* dictionary, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -107,7 +112,7 @@ size_t der_sizeof_number(CFNumberRef number, CFErrorRef *error); uint8_t* der_encode_number(CFNumberRef number, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_number(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_number(CFAllocatorRef allocator, CFNumberRef* number, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -117,7 +122,7 @@ size_t der_sizeof_string(CFStringRef string, CFErrorRef *error); uint8_t* der_encode_string(CFStringRef string, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_string(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_string(CFAllocatorRef allocator, CFStringRef* string, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -126,8 +131,10 @@ size_t der_sizeof_set(CFSetRef dict, CFErrorRef *error); uint8_t* der_encode_set(CFSetRef set, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); +uint8_t* der_encode_set_repair(CFSetRef set, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_set(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_set(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); diff --git a/OSX/utilities/der_set.c b/OSX/utilities/der_set.c index 8bf2a895..386ecf83 100644 --- a/OSX/utilities/der_set.c +++ b/OSX/utilities/der_set.c @@ -33,12 +33,14 @@ #include #include -const uint8_t* der_decode_set(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_set(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } const uint8_t *payload_end = 0; const uint8_t *payload = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_CFSET, &payload_end, der, der_end); @@ -60,7 +62,7 @@ const uint8_t* der_decode_set(CFAllocatorRef allocator, CFOptionFlags mutability while (payload != NULL && payload < payload_end) { CFTypeRef value = NULL; - payload = der_decode_plist(allocator, mutability, &value, error, payload, payload_end); + payload = der_decode_plist(allocator, &value, error, payload, payload_end); if (payload) { CFSetAddValue(theSet, value); @@ -116,6 +118,7 @@ size_t der_sizeof_set(CFSetRef dict, CFErrorRef *error) struct encode_context { bool success; + bool repair_contents; CFErrorRef * error; CFMutableArrayRef list; CFAllocatorRef allocator; @@ -135,7 +138,7 @@ static void add_sequence_to_array(const void *value_void, void *context_void) uint8_t* const encode_begin = CFDataGetMutableBytePtr(value); uint8_t *encode_end = encode_begin + der_size; - encode_end = der_encode_plist(value_void, context->error, encode_begin, encode_end); + encode_end = der_encode_plist_repair(value_void, context->error, context->repair_contents, encode_begin, encode_end); if (encode_end != NULL) { CFDataDeleteBytes(value, CFRangeMake(0, (encode_end - encode_begin))); @@ -148,18 +151,24 @@ static void add_sequence_to_array(const void *value_void, void *context_void) } } -static CFComparisonResult cfdata_compare_contents(const void *val1, const void *val2, void *context __unused) +static CFComparisonResult cfdata_compare_der_contents(const void *val1, const void *val2, void *context __unused) { - return CFDataCompare((CFDataRef) val1, (CFDataRef) val2); + return CFDataCompareDERData((CFDataRef) val1, (CFDataRef) val2); } uint8_t* der_encode_set(CFSetRef set, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) +{ + return der_encode_set_repair(set, error, false, der, der_end); +} + +uint8_t* der_encode_set_repair(CFSetRef set, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end) { CFMutableArrayRef elements = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - - struct encode_context context = { .success = true, .error = error, .list = elements }; + + struct encode_context context = { .success = true, .error = error, .list = elements, .repair_contents = repair }; CFSetApplyFunction(set, add_sequence_to_array, &context); if (!context.success) { @@ -169,7 +178,7 @@ uint8_t* der_encode_set(CFSetRef set, CFErrorRef *error, CFRange allOfThem = CFRangeMake(0, CFArrayGetCount(elements)); - CFArraySortValues(elements, allOfThem, cfdata_compare_contents, NULL); + CFArraySortValues(elements, allOfThem, cfdata_compare_der_contents, NULL); uint8_t* original_der_end = der_end; @@ -181,6 +190,7 @@ uint8_t* der_encode_set(CFSetRef set, CFErrorRef *error, CFReleaseNull(elements); - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_CFSET, original_der_end, der, der_end); + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_CONSTRUCTED_CFSET, original_der_end, der, der_end), + error); } diff --git a/OSX/utilities/der_set.h b/OSX/utilities/der_set.h index d02dfd01..bd8329bb 100644 --- a/OSX/utilities/der_set.h +++ b/OSX/utilities/der_set.h @@ -14,7 +14,7 @@ #include // If you provide a set in *set, we will add elements to it and return the union. -const uint8_t* der_decode_set(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_set(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); diff --git a/OSX/utilities/der_string.c b/OSX/utilities/der_string.c index 2f0c5dc0..972a1206 100644 --- a/OSX/utilities/der_string.c +++ b/OSX/utilities/der_string.c @@ -32,12 +32,14 @@ #include -const uint8_t* der_decode_string(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_string(CFAllocatorRef allocator, CFStringRef* string, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_UTF8_STRING, &payload_size, der, der_end); @@ -73,9 +75,10 @@ size_t der_sizeof_string(CFStringRef str, CFErrorRef *error) uint8_t* der_encode_string(CFStringRef string, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { - // Obey the NULL allowed rules. - if (!der_end) + if (NULL == der_end) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } const CFIndex str_length = CFStringGetLength(string); @@ -88,7 +91,8 @@ uint8_t* der_encode_string(CFStringRef string, CFErrorRef *error, return NULL; } - return ccder_encode_tl(CCDER_UTF8_STRING, bytes_used, der, - ccder_encode_body(bytes_used, buffer, der, der_end)); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_UTF8_STRING, bytes_used, der, + ccder_encode_body(bytes_used, buffer, der, der_end)), + error); } diff --git a/OSX/utilities/entitlements.c b/OSX/utilities/entitlements.c new file mode 100644 index 00000000..bffbe6fb --- /dev/null +++ b/OSX/utilities/entitlements.c @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2020 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +#include "entitlements.h" + +/// Moves the entitlement value from the original entitlement into the target entitlement. +static void transferEntitlement(CFMutableDictionaryRef entitlements, CFStringRef originalEntitlement, CFStringRef targetEntitlement) +{ + CFTypeRef value = (CFStringRef)CFDictionaryGetValue(entitlements, originalEntitlement); + CFDictionaryAddValue(entitlements, targetEntitlement, value); +} + +/// Determines if an entitlement needs fixup, which means it has a value for the original entitlement and no value for the +/// target entitlement. +static bool entitlementNeedsFixup(CFDictionaryRef entitlements, CFStringRef originalEntitlement, CFStringRef targetEntitlement) +{ + // Entitlements only need fixup on macOS running on Apple Silicon, so just always fall through to the default case otherwise. +#if TARGET_OS_OSX && TARGET_CPU_ARM64 + CFTypeRef originalValue = (CFStringRef)CFDictionaryGetValue(entitlements, originalEntitlement); + CFTypeRef newValue = (CFStringRef)CFDictionaryGetValue(entitlements, targetEntitlement); + if (originalValue != NULL && newValue == NULL) { + return true; + } +#endif + return false; +} + +bool needsCatalystEntitlementFixup(CFDictionaryRef entitlements) +{ + return entitlementNeedsFixup(entitlements, CFSTR("application-identifier"), CFSTR("com.apple.application-identifier")) || + entitlementNeedsFixup(entitlements, CFSTR("aps-environment"), CFSTR("com.apple.developer.aps-environment")); +} + +bool updateCatalystEntitlements(CFMutableDictionaryRef entitlements) +{ + bool updated = false; + if (entitlementNeedsFixup(entitlements, CFSTR("application-identifier"), CFSTR("com.apple.application-identifier"))) { + transferEntitlement(entitlements, CFSTR("application-identifier"), CFSTR("com.apple.application-identifier")); + updated = true; + } + if (entitlementNeedsFixup(entitlements, CFSTR("aps-environment"), CFSTR("com.apple.developer.aps-environment"))) { + transferEntitlement(entitlements, CFSTR("aps-environment"), CFSTR("com.apple.developer.aps-environment")); + updated = true; + } + return updated; +} diff --git a/OSX/utilities/entitlements.h b/OSX/utilities/entitlements.h new file mode 100644 index 00000000..427f0bc6 --- /dev/null +++ b/OSX/utilities/entitlements.h @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2020 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +#ifndef _utilities_entitlements_h +#define _utilities_entitlements_h + +#include +#include + +__BEGIN_DECLS + +/// Checks an entitlement dictionary to determine if any Catalyst-related entitlements need to be updated. +bool needsCatalystEntitlementFixup(CFDictionaryRef entitlements); + +/// Modifies an entitlements dictionary to add the necessary Catalyst-related entitlements based on pre-existing entitlements. +/// Returns whether the entitlements were modified. +bool updateCatalystEntitlements(CFMutableDictionaryRef entitlements); + +__END_DECLS + +#endif /* _utilities_entitlements_h */ diff --git a/OSX/utilities/simulate_crash.m b/OSX/utilities/simulate_crash.m index 197dfe35..0a41470c 100644 --- a/OSX/utilities/simulate_crash.m +++ b/OSX/utilities/simulate_crash.m @@ -11,7 +11,7 @@ #import #import -SOFT_LINK_FRAMEWORK_SAFE(PrivateFrameworks, CrashReporterSupport); +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CrashReporterSupport); SOFT_LINK_FUNCTION(CrashReporterSupport, SimulateCrash, soft_SimulateCrash, \ BOOL, (pid_t pid, mach_exception_data_type_t exceptionCode, NSString *description), diff --git a/OSX/utilities/simulatecrash_assert.h b/OSX/utilities/simulatecrash_assert.h new file mode 100644 index 00000000..33d13b37 --- /dev/null +++ b/OSX/utilities/simulatecrash_assert.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SECURITY_UTILITIES_SIMULATECRASH_ASSERT_H_ +#define _SECURITY_UTILITIES_SIMULATECRASH_ASSERT_H_ + +#if !defined(NDEBUG) || !defined(__OBJC__) + #include +#else // NDEBUG && __OBJC__ + #include "debugging.h" + #undef assert + #define assert(expr) { \ + if (!(expr)) { \ + __security_simulatecrash(CFSTR("Execution has encountered an unexpected state"), __sec_exception_code_UnexpectedState); \ + } \ + } +#endif // NDEBUG && __OBJC__ + +#endif /* _SECURITY_UTILITIES_SIMULATECRASH_ASSERT_H_ */ diff --git a/RegressionTests/PreprocessPlist.sh b/RegressionTests/PreprocessPlist.sh old mode 100644 new mode 100755 diff --git a/RegressionTests/Security.plist b/RegressionTests/Security.plist index e08137ea..79b5a486 100644 --- a/RegressionTests/Security.plist +++ b/RegressionTests/Security.plist @@ -46,6 +46,8 @@ Disabled BATS_UTD_Disabled_keychainnetworkextensionsharing_1 + MayRunConcurrently + TestName @@ -56,6 +58,8 @@ Disabled BATS_UTD_Disabled_keychainnetworkextensionsharing_2 + MayRunConcurrently + TestName @@ -66,6 +70,8 @@ Disabled BATS_UTD_Disabled_keychainnetworkextensionsharing_3 + MayRunConcurrently + TestName @@ -119,29 +125,33 @@ TestName - KeychainSecd_macOS + KeychainSecd ShowSubtestResults Command - BATS_XCTEST_CMD - /AppleInternal/XCTests/com.apple.security/secdxctests_mac.xctest + /AppleInternal/CoreOS/tests/Security/KeychainEntitledTestRunner + -t + secdxctests Disabled - BATS_UTD_Disabled_KeychainSecd_macOS + BATS_UTD_Disabled_KeychainSecdXCTests TestName - KeychainSecd_iOS + SecDbBackupTests + WorkingDirectory + /AppleInternal/XCTests/com.apple.security/ ShowSubtestResults Command - BATS_XCTEST_CMD - /AppleInternal/XCTests/com.apple.security/secdxctests_ios.xctest + /AppleInternal/CoreOS/tests/Security/KeychainEntitledTestRunner + -t + SecDbBackupTests Disabled - BATS_UTD_Disabled_KeychainSecd_iOS + BATS_UTD_Disabled_KeychainSecDbBackupTests TestName @@ -156,6 +166,55 @@ Disabled BATS_UTD_Disabled_SecurityUtiltitesTests + + TestName + SecCodeAPITest + Command + + /AppleInternal/CoreOS/tests/Security/secseccodeapitest + + Disabled + BATS_UTD_Disabled_SecCodeAPITest + ShowSubtestResults + + + + TestName + SecStaticCodeAPITest + Command + + /AppleInternal/CoreOS/tests/Security/secsecstaticcodeapitest + + Disabled + BATS_UTD_Disabled_SecStaticCodeAPITest + ShowSubtestResults + + + + TestName + SecStaticCodeAPITestUnsigned + Command + + /AppleInternal/CoreOS/tests/Security/unsigned_secstaticcodeapitest.sh + + Disabled + BATS_UTD_Disabled_SecStaticCodeAPITestUnsigned + ShowSubtestResults + + + + TestName + SecLegacyCodeRegressions + ShowSubtestResults + + Command + + BATS_XCTEST_CMD + /AppleInternal/XCTests/com.apple.security/SecLegacyCodeRegressions.xctest + + Disabled + BATS_UTD_Disabled_SecLegacyCodeRegressions + diff --git a/RegressionTests/bats_utd_plist.h b/RegressionTests/bats_utd_plist.h index e8549e96..179fe8ed 100644 --- a/RegressionTests/bats_utd_plist.h +++ b/RegressionTests/bats_utd_plist.h @@ -45,6 +45,12 @@ #define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _TRUE_ #define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ #define BATS_UTD_Disabled_security_sysdiagnose _TRUE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _TRUE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _TRUE_ +#define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITestUnsigned _TRUE_ +#define BATS_UTD_Disabled_SecLegacyCodeRegressions _TRUE_ #elif TARGET_OS_OSX /* For MacOS, we disable the iOS only tests. */ @@ -61,6 +67,54 @@ #define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _FALSE_ #define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ #define BATS_UTD_Disabled_security_sysdiagnose _FALSE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _FALSE_ +#define BATS_UTD_Disabled_SecCodeAPITest _FALSE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _FALSE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITestUnsigned _FALSE_ +#define BATS_UTD_Disabled_SecLegacyCodeRegressions _FALSE_ + +#elif TARGET_OS_WATCH +#define BATS_UTD_Disabled_AuthorizationTest _TRUE_ +#define BATS_UTD_Disabled_EduModeTest _FALSE_ +#define BATS_UTD_Disabled_KCPairingTest _FALSE_ +#define BATS_UTD_Disabled_KeychainAnalyticsTests _FALSE_ +#define BATS_UTD_Disabled_KeychainMockAKSTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecd_iOS _FALSE_ +#define BATS_UTD_Disabled_KeychainSecd_macOS _TRUE_ +#define BATS_UTD_Disabled_SecurityUtiltitesTests _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_1 _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_2 _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _FALSE_ +#define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ +#define BATS_UTD_Disabled_security_sysdiagnose _FALSE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _TRUE_ +#define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITestUnsigned _TRUE_ +#define BATS_UTD_Disabled_SecLegacyCodeRegressions _TRUE_ + +#elif TARGET_OS_TV +#define BATS_UTD_Disabled_AuthorizationTest _TRUE_ +#define BATS_UTD_Disabled_EduModeTest _FALSE_ +#define BATS_UTD_Disabled_KCPairingTest _FALSE_ +#define BATS_UTD_Disabled_KeychainAnalyticsTests _FALSE_ +#define BATS_UTD_Disabled_KeychainMockAKSTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecd_iOS _FALSE_ +#define BATS_UTD_Disabled_KeychainSecd_macOS _TRUE_ +#define BATS_UTD_Disabled_SecurityUtiltitesTests _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_1 _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_2 _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _FALSE_ +#define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ +#define BATS_UTD_Disabled_security_sysdiagnose _FALSE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _TRUE_ +#define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITestUnsigned _TRUE_ +#define BATS_UTD_Disabled_SecLegacyCodeRegressions _TRUE_ #else /* By default, assume iOS platforms. We disable the MacOS only tests. */ @@ -77,5 +131,11 @@ #define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _FALSE_ #define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ #define BATS_UTD_Disabled_security_sysdiagnose _FALSE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _FALSE_ +#define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITest _TRUE_ +#define BATS_UTD_Disabled_SecStaticCodeAPITestUnsigned _TRUE_ +#define BATS_UTD_Disabled_SecLegacyCodeRegressions _TRUE_ #endif diff --git a/RegressionTests/codesigning_api_tests/codesigning_tests_shared.h b/RegressionTests/codesigning_api_tests/codesigning_tests_shared.h new file mode 100644 index 00000000..85fef653 --- /dev/null +++ b/RegressionTests/codesigning_api_tests/codesigning_tests_shared.h @@ -0,0 +1,64 @@ +// +// codesigning_tests_shared.h +// Security +// +// Copyright 2021 Apple Inc. All rights reserved. +// + +// +// BATS test token helpers +// +#define TEST_START(name) \ + do { \ + printf("==================================================\n"); \ + printf("[TEST] %s\n", name); \ + printf("==================================================\n"); \ + } while(0) + +#define TEST_CASE(cond, name) \ + do { \ + printf("[BEGIN] %s\n", (name)); \ + if ((cond)) \ + printf("[PASS] %s\n", (name)); \ + else \ + printf("[FAIL] %s\n", (name)); \ + } while (0) + +#define TEST_CASE_EXPR(cond) TEST_CASE(cond, #cond) + +#define TEST_CASE_JUMP(cond, block, name) \ + do { \ + printf("[BEGIN] %s\n", (name)); \ + if ((cond)) \ + printf("[PASS] %s\n", (name)); \ + else {\ + printf("[FAIL] %s\n", (name)); \ + goto block; \ + } \ + } while (0) + +#define TEST_CASE_EXPR_JUMP(cond, block) TEST_CASE_JUMP(cond, block, #cond) + +#define TEST_CASE_BLOCK(name, block) \ + do { \ + printf("[BEGIN] %s\n", (name)); \ + if (block()) \ + printf("[PASS] %s\n", (name)); \ + else \ + printf("[FAIL] %s\n", (name)); \ + } while (0) + +#define TEST_BEGIN printf("[BEGIN] %s\n", __FUNCTION__); +#define TEST_PASS printf("[PASS] %s\n", __FUNCTION__); +#define TEST_FAIL printf("[FAIL] %s\n", __FUNCTION__); + +#define TEST_RESULT(cond) \ + (cond) ? TEST_PASS : TEST_FAIL + +// +// Common output helpers +// +#define INFO(fmt, ...) \ +({ \ + NSLog(fmt, ##__VA_ARGS__); \ +}) diff --git a/RegressionTests/codesigning_api_tests/seccode.c b/RegressionTests/codesigning_api_tests/seccode.c new file mode 100644 index 00000000..2d470853 --- /dev/null +++ b/RegressionTests/codesigning_api_tests/seccode.c @@ -0,0 +1,280 @@ +// +// seccode.c +// secseccodeapitest +// +#include "authd_private.h" + +#include +#include +#include +#include +#include + +#define BEGIN() \ +({ \ + fprintf(stdout, "[BEGIN] %s\n", __FUNCTION__); \ +}) + +#define INFO(fmt, ...) \ +({ \ + fprintf(stdout, fmt "\n", ##__VA_ARGS__); \ +}) + +#define PASS(fmt, ...) \ +({ \ + fprintf(stdout, "[PASS] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define FAIL(fmt, ...) \ +({ \ + fprintf(stdout, "[FAIL] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define SAFE_RELEASE(x) \ +({ \ + if (x) { \ + CFRelease(x); \ + x = NULL; \ + } \ +}) + +enum xpcConnectionStates { + kXPCConnectionStateNotCancelled = 0, + kXPCConnectionStateCancelled, + kXPCConnectionStateOkayToExit, + kXPCConnectionStateServerNotAvailable, +}; + +static int +_validatePathFromSecCode(SecCodeRef processRef, const char *path) +{ + int ret = -1; + OSStatus status; + SecStaticCodeRef staticProcessRef = NULL; + CFURLRef pathURL = NULL; + CFStringRef pathString = NULL; + + /* Get the StaticCodeRef for this SecCodeRef */ + status = SecCodeCopyStaticCode(processRef, kSecCSDefaultFlags, &staticProcessRef); + require_noerr_action(status, exit, ret = -1); + + INFO("Successfully created a SecStaticCodeRef"); + + /* Copy the path of requested service */ + status = SecCodeCopyPath(staticProcessRef, kSecCSDefaultFlags, &pathURL); + require_noerr_action(status, exit, ret = -1); + + INFO("Successfully created a CFURLRef"); + + /* Get the CFStringRef from the CFURLRef */ + pathString = CFURLGetString(pathURL); + require_action(pathString, exit, ret = -1); + + INFO("Successfully created a CFStingRef"); + + if (!strncmp(path, CFStringGetCStringPtr(pathString, kCFStringEncodingUTF8), strlen(path))) { + INFO("Successfully confirmed the location of requested service"); + ret = 0; + } else { + INFO("Location of service incorrect: %s", CFStringGetCStringPtr(pathString, kCFStringEncodingUTF8)); + ret = -1; + } + +exit: + SAFE_RELEASE(pathURL); + SAFE_RELEASE(staticProcessRef); + + return ret; +} + +static int +CheckCreateWithXPCMessage(void) +{ + BEGIN(); + + int ret; + OSStatus status; + xpc_connection_t connection = NULL; + xpc_object_t message = NULL, reply = NULL; + SecCodeRef processRef = NULL; + volatile static int xpcState = kXPCConnectionStateNotCancelled; + + connection = xpc_connection_create(SECURITY_AUTH_NAME, NULL); + if (NULL == connection) { + FAIL("Unable to create an XPC connection with %s", SECURITY_AUTH_NAME); + return -1; + } + + INFO("XPC Connection with %s created", SECURITY_AUTH_NAME); + + xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { + if (xpc_get_type(event) == XPC_TYPE_ERROR && event == XPC_ERROR_CONNECTION_INVALID) { + if (OSAtomicCompareAndSwapInt(kXPCConnectionStateCancelled, kXPCConnectionStateOkayToExit, &xpcState)) { + INFO("XPC Connection Cancelled"); + } else { + xpcState = kXPCConnectionStateServerNotAvailable; + FAIL("Authorization server not available"); + } + } + }); + + xpc_connection_resume(connection); + + INFO("XPC Connection resumed"); + + /* Create an empty dictionary */ + message = xpc_dictionary_create(NULL, NULL, 0); + + /* + * Set _type to something invalid. This is done because authd will simply + * return an "invalid type" for this case, which means no state changes in + * the authd daemon. + */ + xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_RIGHT_PROPERTIES+512); + + /* Send object and wait for response */ + reply = xpc_connection_send_message_with_reply_sync(connection, message); + xpc_release(message); + + INFO("XPC Message received"); + + /* Create a SecCode using the XPC Message */ + status = SecCodeCreateWithXPCMessage(reply, kSecCSDefaultFlags, &processRef); + if (status) { + FAIL("Unable to create a SecCodeRef from message reply [%d]", status); + xpc_release(reply); + return -1; + } + xpc_release(reply); + + INFO("Successfully created a SecCodeRef"); + + const char *authdLocation = "file:///System/Library/Frameworks/Security.framework/Versions/A/XPCServices/authd.xpc/"; + if (_validatePathFromSecCode(processRef, authdLocation)) { + FAIL("Unable to verify authd location"); + ret = -1; + } else { + PASS("authd location successfully verified"); + ret = 0; + } + + SAFE_RELEASE(processRef); + + // Potential race condition in getting an actual XPC_TYPE_ERROR vs getting + // a connection cancelled. We are okay with this since this is extremely unlikely... + if (OSAtomicCompareAndSwapInt(kXPCConnectionStateNotCancelled, kXPCConnectionStateCancelled, &xpcState)) { + xpc_connection_cancel(connection); + } + + while (xpcState != kXPCConnectionStateOkayToExit) { + if (xpcState == kXPCConnectionStateServerNotAvailable) { + break; + } + usleep(1000 * 1); + } + + return ret; +} + +static int +CheckCreateWithXPCMessage_invalidXPCObject(void) +{ + BEGIN(); + + OSStatus status; + xpc_object_t invalidObject = NULL; + SecCodeRef processRef = NULL; + + /* Create an NULL object */ + invalidObject = xpc_null_create(); + + INFO("Created a NULL object"); + + /* Try and acquire a SecCodeRef through the NULL object -- should fail with errSecCSInvalidObjectRef */ + status = SecCodeCreateWithXPCMessage(invalidObject, kSecCSDefaultFlags, &processRef); + if (status != errSecCSInvalidObjectRef) { + FAIL("Return code unexpected [%d]", status); + return -1; + } + + PASS("Got expected return code"); + return 0; +} + +static int +CheckCreateWithXPCMessage_NULLConnectionInObject(void) +{ + BEGIN(); + + OSStatus status; + xpc_object_t emptyDictionary = NULL; + SecCodeRef processRef = NULL; + + /* Create an empty dictionary object */ + emptyDictionary = xpc_dictionary_create_empty(); + + INFO("Created an empty dictionary object"); + + /* Try and acquire a SecCodeRef through the empty dictionary -- should fail with errSecCSInvalidObjectRef */ + status = SecCodeCreateWithXPCMessage(emptyDictionary, kSecCSDefaultFlags, &processRef); + if (status != errSecCSInvalidObjectRef) { + FAIL("Return code unexpected [%d]", status); + return -1; + } + + PASS("Got expected return code"); + return 0; +} + +static int +CheckValidateWithNoNetwork(void) +{ + BEGIN(); + + OSStatus status; + SecCodeRef processRef = NULL; + + status = SecCodeCopySelf(kSecCSDefaultFlags, &processRef); + if (status) { + FAIL("Return code unexpected [%d]", status); + return -1; + } + + status = SecCodeCheckValidity(processRef, kSecCSNoNetworkAccess, NULL); + if (status == errSecCSInvalidFlags) { + FAIL("SecCodeCheckValidity did not accept kSecCSNoNetworkAccess"); + return -1; + } else if (status) { + FAIL("Return code unexpected [%d]", status); + return -1; + } + + PASS("Flag was accepted for validation call."); + return 0; +} + +int main(void) +{ + fprintf(stdout, "[TEST] secseccodeapitest\n"); + + int i; + int (*testList[])(void) = { + CheckCreateWithXPCMessage, + CheckCreateWithXPCMessage_invalidXPCObject, + CheckCreateWithXPCMessage_NULLConnectionInObject, + CheckValidateWithNoNetwork, + }; + const int numberOfTests = sizeof(testList) / sizeof(*testList); + int testResults[numberOfTests] = {0}; + + for (i = 0; i < numberOfTests; i++) { + testResults[i] = testList[i](); + } + + fprintf(stdout, "[SUMMARY]\n"); + for (i = 0; i < numberOfTests; i++) { + fprintf(stdout, "%d. %s\n", i+1, testResults[i] == 0 ? "Passed" : "Failed"); + } + + return 0; +} diff --git a/RegressionTests/codesigning_api_tests/secstaticcode.cpp b/RegressionTests/codesigning_api_tests/secstaticcode.cpp new file mode 100644 index 00000000..e522a667 --- /dev/null +++ b/RegressionTests/codesigning_api_tests/secstaticcode.cpp @@ -0,0 +1,884 @@ +// +// secstaticcode.cpp +// secsecstaticcodeapitest +// +#include +#include +#include +#include + +#include "StaticCode.h" + +#include +#include +#include +#include +#include + +#include "secstaticcode.h" + +using namespace CodeSigning; + +#define BEGIN() \ +({ \ + fprintf(stdout, "[BEGIN] %s\n", __FUNCTION__); \ +}) + +#define INFO(fmt, ...) \ +({ \ + fprintf(stdout, fmt "\n", ##__VA_ARGS__); \ +}) + +#define PASS(fmt, ...) \ +({ \ + fprintf(stdout, "[PASS] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define FAIL(fmt, ...) \ +({ \ + fprintf(stdout, "[FAIL] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define SAFE_RELEASE(x) \ +({ \ + if (x) { \ + CFRelease(x); \ + x = NULL; \ + } \ +}) + +#define kCommandRedirectOutputToDevNULL " >/dev/null 2>&1" +#define BUILD_COMMAND(x) x kCommandRedirectOutputToDevNULL + +#define kFAT32DiskImageFileDirectory "/tmp" +#define kFAT32DiskImageFileName "Security_SecStaticCodeAPITest.dmg" +#define kFAT32DiskImageFilePath kFAT32DiskImageFileDirectory "/" kFAT32DiskImageFileName + +#define kFAT32DiskImageVolumeDirectory "/Volumes" +#define kFAT32DiskImageVolumeName "SEC_TEST" +#define kFAT32DiskImageVolumePath kFAT32DiskImageVolumeDirectory "/" kFAT32DiskImageVolumeName + +#define kApplicationsPath "/Applications" +#define kSafariBundleName "Safari.app" +#define kSafariBundleOnSystemPath kApplicationsPath "/" kSafariBundleName +#define kSafariBundleOnVolumePath kFAT32DiskImageVolumePath "/" kSafariBundleName + +static void +_cleanUpFAT32DiskImage(void) +{ + // Delete disk image. + const char *command = BUILD_COMMAND("rm -rf " kFAT32DiskImageFilePath); + system(command); + + // Detach volume. + command = BUILD_COMMAND("hdiutil detach " kFAT32DiskImageVolumePath); + system(command); +} + +static int +_createFAT32DiskImage(void) +{ + const char *command = BUILD_COMMAND("hdiutil create -fs FAT32 -size 256m -volname " kFAT32DiskImageVolumeName " " kFAT32DiskImageFilePath); + return system(command); +} + +static int +_attachFAT32DiskImage(void) +{ + const char *command = BUILD_COMMAND("hdiutil attach " kFAT32DiskImageFilePath); + return system(command); +} + +static int +_copySafariBundleToVolume(void) +{ + const char *command = BUILD_COMMAND("cp -R " kSafariBundleOnSystemPath " " kSafariBundleOnVolumePath); + return system(command); +} + +static int +_confirmValidationPolicy(const char *path) +{ + int ret = -1; + OSStatus status = 0; + CFRef stringPath; + CFRef url; + CFRef codeRef; + SecCSFlags createFlags = kSecCSDefaultFlags; + SecCSFlags validateFlags = kSecCSDefaultFlags | kSecCSStrictValidateStructure; + + require(path, done); + + stringPath.take(CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)path, strlen(path), kCFStringEncodingASCII, false)); + require(stringPath, done); + + url.take(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, stringPath, kCFURLPOSIXPathStyle, false)); + require(url, done); + + status = SecStaticCodeCreateWithPath(url, createFlags, &codeRef.aref()); + require_noerr(status, done); + require(codeRef, done); + + // Validate binary without kSecCSSkipXattrFiles. Expectation is this should fail. + status = SecStaticCodeCheckValidity(codeRef, validateFlags, NULL); + if (!status) { + INFO("%s validated without kSecCSSkipXattrFiles flag", path); + goto done; + } + + // Create codeRef again to clear state. + status = SecStaticCodeCreateWithPath(url, createFlags, &codeRef.aref()); + require_noerr(status, done); + require(codeRef, done); + + // Validate binary with kSecCSSkipXattrFiles. Expectation is this should pass. + validateFlags |= kSecCSSkipXattrFiles; + status = SecStaticCodeCheckValidity(codeRef, validateFlags, NULL); + if (status) { + INFO("%s is not valid even with kSecCSSkipXattrFiles flag", path); + goto done; + } + + // Complete. + ret = 0; + +done: + return ret; +} + +static int +CheckCheckValidity_kSecCSSkipXattrFiles(void) +{ + const char *xattrName = NULL; + uint32_t xattrValue = 0; + const char *safariBinary = NULL; + const char *safariCodeResources = NULL; + + BEGIN(); + + int ret = -1; + + // Create FAT32 disk image. + if (_createFAT32DiskImage()) { + FAIL("_createFAT32DiskImage error"); + goto done; + } + INFO("Created " kFAT32DiskImageFilePath); + + // Attach disk image to the system. + if (_attachFAT32DiskImage()) { + FAIL("_attachFAT32DiskImage error"); + goto done; + } + INFO("Attached " kFAT32DiskImageFilePath " as " kFAT32DiskImageVolumePath); + + // Copy Safari.app to the attached volume. + if (_copySafariBundleToVolume()) { + FAIL("_copySafariBundleToVolume error"); + goto done; + } + INFO("Copied " kSafariBundleOnSystemPath " to " kSafariBundleOnVolumePath); + + // Write "com.apple.dummy" xattr to Safari. + xattrName = "com.apple.dummy"; + xattrValue = 0; + + safariBinary = kSafariBundleOnVolumePath "/Contents/MacOS/Safari"; + if (setxattr(safariBinary, xattrName, &xattrValue, sizeof(xattrValue), 0, 0)) { + FAIL("%s setxattr error: %d [%s]", safariBinary, errno, strerror(errno)); + goto done; + } + INFO("Wrote xattr \'%s\' to %s", xattrName, safariBinary); + + safariCodeResources = kSafariBundleOnVolumePath "/Contents/_CodeSignature/CodeResources"; + if (setxattr(safariCodeResources, xattrName, &xattrValue, sizeof(xattrValue), 0, 0)) { + FAIL("%s setxattr error: %d [%s]", safariCodeResources, errno, strerror(errno)); + goto done; + } + INFO("Wrote xattr \'%s\' to %s", xattrName, safariCodeResources); + + // Validate Safari.app with and without kSecCSSkipXattrFiles flag. + if (_confirmValidationPolicy(kSafariBundleOnVolumePath)) { + FAIL("%s _confirmValidationPolicy error", kSafariBundleOnVolumePath); + goto done; + } + INFO("Validation policy on %s confirmed", kSafariBundleOnVolumePath); + + PASS("Completed validation policy check with kSecCSSkipXattrFiles"); + ret = 0; + +done: + _cleanUpFAT32DiskImage(); + return ret; +} + +static int +CheckAppleProcessNetworkDefault(void) +{ + int ret = -1; + CFRef url; + CFRef codeRef; + OSStatus status = 0; + SecPointer code; + + BEGIN(); + + url.take(CFURLCreateWithString(NULL, CFSTR("/Applications/Safari.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode: %d", status); + goto done; + } + + code = SecStaticCode::requiredStatic(codeRef); + if (code->validationCannotUseNetwork()) { + PASS("apple process cannot use network by default"); + ret = 0; + } else { + FAIL("apple process can use network by default"); + } +done: + return ret; +} + +static int +CheckAppleProcessCanUseNetworkWithFlag(void) +{ + int ret = -1; + CFRef url; + CFRef codeRef; + OSStatus status = 0; + SecPointer code; + + BEGIN(); + + url.take(CFURLCreateWithString(NULL, CFSTR("/Applications/Safari.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode: %d", status); + goto done; + } + + status = SecStaticCodeCheckValidity(codeRef, kSecCSAllowNetworkAccess | kSecCSBasicValidateOnly, NULL); + if (status) { + FAIL("Failed to perform basic validation: %d", status); + goto done; + } + + code = SecStaticCode::requiredStatic(codeRef); + if (code->validationCannotUseNetwork()) { + FAIL("apple process cannot use network with kSecCSAllowNetworkAccess flag"); + } else { + PASS("apple process can use network with kSecCSAllowNetworkAccess flag"); + ret = 0; + } + +done: + return ret; +} + +static int +CheckAppleProcessCanDenyNetworkWithFlag(void) +{ + int ret = -1; + CFRef url; + CFRef codeRef; + OSStatus status = 0; + SecPointer code; + + BEGIN(); + + url.take(CFURLCreateWithString(NULL, CFSTR("/Applications/Safari.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode: %d", status); + goto done; + } + + status = SecStaticCodeCheckValidity(codeRef, kSecCSNoNetworkAccess | kSecCSBasicValidateOnly, NULL); + if (status) { + FAIL("Failed to perform basic validation: %d", status); + goto done; + } + + code = SecStaticCode::requiredStatic(codeRef); + if (code->validationCannotUseNetwork()) { + PASS("apple process cannot use network with kSecCSNoNetworkAccess flag"); + ret = 0; + } else { + FAIL("apple process can use network with kSecCSNoNetworkAccess flag"); + } + +done: + return ret; +} + +static int +Check_SecStaticCodeEnableOnlineNotarizationCheck(void) +{ + int ret = -1; + CFRef url; + CFRef codeRef; + OSStatus status = 0; + SecPointer code; + + BEGIN(); + + url.take(CFURLCreateWithString(NULL, CFSTR("/usr/libexec/syspolicyd"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode: %d", status); + goto done; + } + + code = SecStaticCode::requiredStatic(codeRef); + if (!code) { + FAIL("Unable to get get SecStaticCode"); + goto done; + } + + if (isFlagSet(code->getFlags(), kSecCSForceOnlineNotarizationCheck)) { + FAIL("Default object has notarization flag without asking for it"); + goto done; + } + + status = SecStaticCodeEnableOnlineNotarizationCheck(codeRef, true); + if (status) { + FAIL("Call to SecStaticCodeEnableOnlineNotarizationCheck(true) failed: %d", status); + goto done; + } + + if (!isFlagSet(code->getFlags(), kSecCSForceOnlineNotarizationCheck)) { + FAIL("SecStaticCodeEnableOnlineNotarizationCheck did not set notarization flag"); + goto done; + } + + status = SecStaticCodeEnableOnlineNotarizationCheck(codeRef, false); + if (status) { + FAIL("Call to SecStaticCodeEnableOnlineNotarizationCheck(false) failed: %d", status); + goto done; + } + + if (isFlagSet(code->getFlags(), kSecCSForceOnlineNotarizationCheck)) { + FAIL("SecStaticCodeEnableOnlineNotarizationCheck did not clear notarization flag"); + goto done; + } + + PASS("SecStaticCodeEnableOnlineNotarizationCheck can control notarization behavior"); + ret = 0; + +done: + return ret; +} + +/// Modify the binary at the provided path by overwriting a few bytes in the executable pages (beyond the header). +static void +modifyBinaryPage(const char *path) +{ + UnixPlusPlus::AutoFileDesc fd = UnixPlusPlus::AutoFileDesc(); + fd.open(path, O_RDWR); + + Universal uv = Universal(fd); + Universal::Architectures architectures; + uv.architectures(architectures); + + for (Universal::Architectures::const_iterator arch = architectures.begin(); arch != architectures.end(); ++arch) { + unique_ptr slice(uv.architecture(*arch)); + // Skip ahead to about 3 pages into the slice to skip past the header. + size_t location = slice->offset() + (3 * 0x400); + INFO("modifying binary at offset: %lx", location); + lseek(fd, location, SEEK_SET); + const char *data = "ERROR"; + write(fd, data, strlen(data)); + } +} + +static int +CheckSingleResourceValidationAPI(void) +{ + int ret = -1; + CFRef url; + CFRef codeRef; + OSStatus status = 0; + SecPointer code; + CFErrorRef error = NULL; + + BEGIN(); + + url.take(CFURLCreateWithString(NULL, CFSTR("/Applications/Safari.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode: %d", status); + goto done; + } + + // Check it returns an error for a non-nested item. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/Applications/test"), kSecCSDefaultFlags, &error); + if (status != errSecParam) { + FAIL("Failed to reject non-nested path with errSecParam: %d", status); + goto done; + } + + // Check it returns an error for a perfect prefix match. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/Applications/Safari.app"), kSecCSDefaultFlags, &error); + if (status != errSecParam) { + FAIL("Failed to reject exact path match with errSecParam: %d", status); + goto done; + } + + // Check it can validate a basic file as a resource. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/Applications/Safari.app/Contents/Resources/BuiltInBookmarks_ca.plist"), kSecCSDefaultFlags, &error); + if (status != errSecSuccess) { + FAIL("Failed to succeed validation for a basic file: %d", status); + goto done; + } + + // Check it can validate the main executable file. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/Applications/Safari.app/Contents/MacOS/Safari"), kSecCSDefaultFlags, &error); + if (status != errSecSuccess) { + FAIL("Failed to succeed validation for the main executable: %d", status); + goto done; + } + + // Check that it fails to validate a non-resource file. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/Applications/Safari.app/Contents/Info.plist"), kSecCSDefaultFlags, &error); + if (status != errSecSuccess) { + FAIL("Failed to validate Info.plist: %d", status); + goto done; + } + + // Check that it can validate a specific sub-bundle directly. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/Applications/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc"), kSecCSDefaultFlags, &error); + if (status != errSecSuccess) { + FAIL("Failed to succeed validation of nested code: %d", status); + goto done; + } + + // Check that it can validate a specific resource within a sub-bundle. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/Applications/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/Resources/WebContentProcess.nib"), kSecCSDefaultFlags, &error); + if (status != errSecSuccess) { + FAIL("Failed to succeed validation of nested code: %d", status); + goto done; + } + + // Check it can validate the main executable file of a nested bundle. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/Applications/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Safari"), kSecCSDefaultFlags, &error); + if (status != errSecSuccess) { + FAIL("Failed to succeed validation for the main executable: %d", status); + goto done; + } + + system("rm -rf /tmp/Safari.app"); + system("cp -R /Applications/Safari.app /tmp/"); + + // Create new SecStaticCode object referencing app in temp location. + url.take(CFURLCreateWithString(NULL, CFSTR("/tmp/Safari.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode on temporary app: %d", status); + goto done; + } + + // Check it cannot verify a file within an omission hole in the main bundle itself. + system("cp /usr/bin/ditto /tmp/Safari.app/Contents/.DS_Store"); + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/tmp/Safari.app/Contents/.DS_Store"), kSecCSDefaultFlags, &error); + if (status != errSecCSResourcesNotSealed) { + FAIL("Failed to reject binary within an omission hole: %d", status); + goto done; + } + system("rm /Applications/Safari.app/Contents/.DS_Store"); + + // Verify that if a file is modified, the resource is no longer valid. + system("echo 'hello' >> /tmp/Safari.app/Contents/Resources/BuiltInBookmarks_ca.plist"); + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/tmp/Safari.app/Contents/Resources/BuiltInBookmarks_ca.plist"), kSecCSDefaultFlags, &error); + if (status != errSecCSBadResource) { + FAIL("Failed to reject validation of a modified resource file: %d", status); + goto done; + } + system("cp /Applications/Safari.app/Contents/Resources/BuiltInBookmarks_ca.plist /tmp/Safari.app/Contents/Resources/BuiltInBookmarks_ca.plist"); + + // Verify that if a nested bundle doesn't pass basic validation, its resources cannot be valid. + system("echo 'hello' >> /tmp/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/Info.plist"); + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/tmp/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/Resources/WebContentProcess.nib"), kSecCSDefaultFlags, &error); + if (status != errSecCSInfoPlistFailed) { + FAIL("Failed to succeed validation of nested code: %d", status); + goto done; + } + system("cp /Applications/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/Info.plist /tmp/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/Info.plist"); + + // Verify that if a nested bundle has its resource modified, its noticed during default validation. + modifyBinaryPage("/tmp/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Safari"); + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/tmp/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Safari"), kSecCSDefaultFlags, &error); + if (status != errSecCSSignatureFailed) { + FAIL("Failed to detect tampering in main executable: %d", status); + goto done; + } + + // And confirm that validating it by the bundle itself behaves the same. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/tmp/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc"), kSecCSDefaultFlags, &error); + if (status != errSecCSSignatureFailed) { + FAIL("Failed to detect tampering in main executable (bundle): %d", status); + goto done; + } + + // Verify that if a nested bundle has its resource modified and the 'fast validation' flag is used, its not noticed during resource validation. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/tmp/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Safari"), kSecCSFastExecutableValidation, &error); + if (status != errSecSuccess) { + FAIL("Failed to allow tampered executable with fast validation: %d", status); + goto done; + } + + // And confirm that validating it by the bundle itself behaves the same. + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/tmp/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc"), kSecCSFastExecutableValidation, &error); + if (status != errSecSuccess) { + FAIL("Failed to allow tampered executable with fast validation (bundle): %d", status); + goto done; + } + system("cp /Applications/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Safari /tmp/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Safari"); + + PASS("All SecStaticCodeValidateResourceWithErrors passed"); + ret = 0; + +done: + system("rm -rf /tmp/Safari.app"); + return ret; +} + +static int +CheckSingleResourceValidationAPIPolicy(void) +{ + int ret = -1; + CFRef url; + CFRef codeRef; + OSStatus status = 0; + SecPointer code; + CFErrorRef error = NULL; + + BEGIN(); + + url.take(CFURLCreateWithString(NULL, CFSTR("/System/Applications/Calculator.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode: %d", status); + goto done; + } + + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/System/Applications/Calculator.app/Contents/Resources/Speakable.plist"), kSecCSDefaultFlags, &error); + if (status != errSecSuccess) { + FAIL("Failed to validate app in ARV: %d", status); + goto done; + } + + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/System/Applications/Calculator.app/Contents/Resources/Speakable.plist"), kSecCSSkipRootVolumeExceptions, &error); + if (status != errSecCSResourcesNotSealed) { + FAIL("Failed to reject app in ARV with kSecCSSkipRootVolumeExceptions: %d", status); + goto done; + } + + url.take(CFURLCreateWithString(NULL, CFSTR("/AppleInternal/Applications/CatalogInspector.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create apple internal SecStaticCode: %d", status); + goto done; + } + + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/AppleInternal/Applications/CatalogInspector.app/Contents/Resources/pkg.tiff"), kSecCSDefaultFlags, &error); + if (status != errSecSuccess) { + FAIL("Failed to validate apple internal app resource: %d", status); + goto done; + } + + status = SecStaticCodeValidateResourceWithErrors(codeRef, CFTempURL("/AppleInternal/Applications/CatalogInspector.app/Contents/Resources/pkg.tiff"), kSecCSSkipRootVolumeExceptions, &error); + if (status != errSecCSResourcesNotSealed) { + FAIL("Failed to reject apple internal app with kSecCSSkipRootVolumeExceptions: %d", status); + goto done; + } + + PASS("All SecStaticCodeValidateResourceWithErrors passed"); + ret = 0; + +done: + return ret; +} + +static int +CheckPathHelpers(void) +{ + int ret = -1; + string remaining; + bool stopped = false; + __block int currentIndex = 0; + __block bool failed = false; + + static const char *expectedResults[] = { + "/Applications/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/Resources", + "/Applications/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents", + "/Applications/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc", + "/Applications/Safari.app/Contents/XPCServices", + "/Applications/Safari.app/Contents", + "/Applications/Safari.app", + "/Applications", + }; + + BEGIN(); + + if (isPathPrefix("", "")) { + FAIL("invalid empty prefixes were not rejected"); + goto done; + } + + if (isPathPrefix("/Applications", "/Applications")) { + FAIL("matching prefix was not rejected"); + goto done; + } + + if (isPathPrefix("/somewhere", "/something")) { + FAIL("invalid prefix was not rejected"); + goto done; + } + + if (isPathPrefix("/Applications/Safari.app", "/Applications/Safari.application")) { + FAIL("prefix not on a directory boundary was not rejected"); + goto done; + } + + if (!isPathPrefix("/Applications/Safari.app", "/Applications/Safari.app/Contents")) { + FAIL("proper prefix was not detected"); + goto done; + } + + if (!isPathPrefix("/Applications/Safari.app/", "/Applications/Safari.app/Contents")) { + FAIL("proper prefix was not detected"); + goto done; + } + + remaining = pathRemaining("", ""); + if (remaining != "") { + FAIL("empty arguments are handled incorrectly: %s", remaining.c_str()); + goto done; + } + + remaining = pathRemaining("/something", "/"); + if (remaining != "something") { + FAIL("empty prefix path is handled incorrectly: %s", remaining.c_str()); + goto done; + } + + remaining = pathRemaining("/Applications/Safari.app/Contents/Info.plist", "/Applications/Safari.app"); + if (remaining != "Contents/Info.plist") { + FAIL("simple resource path remaining was wrong: %s", remaining.c_str()); + goto done; + } + + remaining = pathRemaining("/Applications/Safari.app/Contents/Info.plist", "/Applications/Safari.app/"); + if (remaining != "Contents/Info.plist") { + FAIL("prefix path with trailing slash is not handled properly: %s", remaining.c_str()); + goto done; + } + + remaining = pathRemaining("Resources/", "Resources/"); + if (remaining != "") { + FAIL("exact paths with trailing slash is not handled properly: %s", remaining.c_str()); + goto done; + } + + remaining = pathRemaining("Resources/a", "Resources/a"); + if (remaining != "") { + FAIL("exact paths don't produce empty remaining path: %s", remaining.c_str()); + goto done; + } + + remaining = pathRemaining("full", "prefix-is-longer"); + if (remaining != "") { + FAIL("shorter full path doesn't produce empty remaining path: %s", remaining.c_str()); + goto done; + } + + stopped = iterateLargestSubpaths("/Applications/Safari.app/Contents/XPCServices/com.apple.WebKit.WebContent.Safari.xpc/Contents/Resources/WebContentProcess.nib", ^bool(string p) { + if ((p != expectedResults[currentIndex]) || (currentIndex > 6)) { + FAIL("unexpected result: %d, %s", currentIndex, p.c_str()); + failed = true; + return false; + } else { + currentIndex += 1; + return true; + } + }); + if (failed) { + goto done; + } + failed = false; + + stopped = iterateLargestSubpaths("WebContentProcess.nib", ^bool(string p) { + FAIL("unexpected call to block on empty iteration: %s", p.c_str()); + return true; + }); + if (stopped) { + FAIL("iterate reported stopped when it wasn't"); + goto done; + } else if (failed) { + goto done; + } + + PASS("All path helper tests succeeded."); + ret = 0; + +done: + return ret; +} + +static int +CheckValidityWithRevocationTraversal(void) +{ + int ret = -1; + CFRef url; + CFRef codeRef; + OSStatus status = 0; + SecPointer code; + + BEGIN(); + + url.take(CFURLCreateWithString(NULL, CFSTR("/Applications/Safari.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode: %d", status); + goto done; + } + + status = SecStaticCodeCheckValidity(codeRef, kSecCSEnforceRevocationChecks, NULL); + if (status) { + FAIL("Unable to validate Safari with kSecCSEnforceRevocationChecks: %d", status); + goto done; + } + + PASS("SecStaticCodeCheckValidity with kSecCSEnforceRevocationChecks works"); + ret = 0; + +done: + return ret; +} + +static int +CheckUnsignedProcessNetworkByDefault(void) +{ + int ret = -1; + CFRef url; + CFRef codeRef; + OSStatus status = 0; + SecPointer code; + + BEGIN(); + + url.take(CFURLCreateWithString(NULL, CFSTR("/Applications/Safari.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode: %d", status); + goto done; + } + + code = SecStaticCode::requiredStatic(codeRef); + if (code->validationCannotUseNetwork()) { + FAIL("unsigned process does not use network by default"); + } else { + PASS("unsigned process uses network by default"); + ret = 0; + } + +done: + return ret; +} + +static int +CheckUnsignedProcessCanDenyNetworkWithFlag(void) +{ + int ret = -1; + CFRef url; + CFRef codeRef; + OSStatus status = 0; + SecPointer code; + + BEGIN(); + + url.take(CFURLCreateWithString(NULL, CFSTR("/Applications/Safari.app"), NULL)); + status = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &codeRef.aref()); + if (status) { + FAIL("Failed to create SecStaticCode: %d", status); + goto done; + } + + status = SecStaticCodeCheckValidity(codeRef, kSecCSNoNetworkAccess | kSecCSBasicValidateOnly, NULL); + if (status) { + FAIL("Failed to perform basic validation: %d", status); + goto done; + } + + code = SecStaticCode::requiredStatic(codeRef); + if (code->validationCannotUseNetwork()) { + PASS("unsigned process can block network with kSecCSNoNetworkAccess flag"); + ret = 0; + } else { + FAIL("unsigned process can block network with kSecCSNoNetworkAccess flag"); + } + +done: + return ret; +} + +static int runTests(int (*testList[])(void), int testCount) +{ + fprintf(stdout, "[TEST] secsecstaticcodeapitest\n"); + + int *testResults = (int *)malloc(sizeof(int) * testCount); + + for (int i = 0; i < testCount; i++) { + testResults[i] = testList[i](); + } + + fprintf(stdout, "[SUMMARY]\n"); + for (int i = 0; i < testCount; i++) { + fprintf(stdout, "%d. %s\n", i+1, testResults[i] == 0 ? "Passed" : "Failed"); + } + + free(testResults); + return 0; +} + +int main(int argc, const char *argv[]) +{ + static int (*signedTestList[])(void) = { + CheckCheckValidity_kSecCSSkipXattrFiles, + CheckAppleProcessNetworkDefault, + CheckAppleProcessCanUseNetworkWithFlag, + CheckAppleProcessCanDenyNetworkWithFlag, + Check_SecStaticCodeEnableOnlineNotarizationCheck, + CheckSingleResourceValidationAPI, + CheckSingleResourceValidationAPIPolicy, + CheckPathHelpers, + CheckValidityWithRevocationTraversal, + }; + + static int (*unsignedTestList[])(void) = { + CheckUnsignedProcessNetworkByDefault, + CheckUnsignedProcessCanDenyNetworkWithFlag, + }; + + const int numberOfSignedTests = sizeof(signedTestList) / sizeof(*signedTestList); + const int numberOfUnsignedTests = sizeof(unsignedTestList) / sizeof(*unsignedTestList); + + bool runUnsignedTests = false; + if (argc == 2) { + if (strcmp(argv[1], "unsigned") == 0) { + INFO("Running unsigned variant of tests"); + runUnsignedTests = true; + } else { + INFO("Running integration tests with content root: %s", argv[1]); + return run_integration_tests(argv[1]); + } + } + + if (runUnsignedTests) { + return runTests(unsignedTestList, numberOfUnsignedTests); + } else { + return runTests(signedTestList, numberOfSignedTests); + } +} diff --git a/RegressionTests/codesigning_api_tests/secstaticcode.h b/RegressionTests/codesigning_api_tests/secstaticcode.h new file mode 100644 index 00000000..0cc936a8 --- /dev/null +++ b/RegressionTests/codesigning_api_tests/secstaticcode.h @@ -0,0 +1,12 @@ +// +// secstaticcode.h +// Security +// +// Copyright 2021 Apple Inc. All rights reserved. +// +#include + +__BEGIN_DECLS +/// Integration test hook. +int run_integration_tests(const char *root); +__END_DECLS diff --git a/RegressionTests/codesigning_api_tests/secstaticcode_integration.m b/RegressionTests/codesigning_api_tests/secstaticcode_integration.m new file mode 100644 index 00000000..1ce7dd7f --- /dev/null +++ b/RegressionTests/codesigning_api_tests/secstaticcode_integration.m @@ -0,0 +1,59 @@ +// +// secstaticcode_integration.m +// secsecstaticcodeapitest +// +// Copyright 2021 Apple Inc. All rights reserved. +// +#import +#import +#import + +#import "secstaticcode.h" +#import "codesigning_tests_shared.h" + +static void +RevokedBinaryTraversalTest(NSURL *contentRoot) +{ + NSDictionary *gTestPaths = @{ + // This resource file has a bad signature that will fail validation, but not in a fatal way. + @"traversal/KV-badsig.app": @(errSecSuccess), + // These are all hiding revoked binaries in various places for different types of discovery. + @"traversal/KV-badfile.app": @(CSSMERR_TP_CERT_REVOKED), + @"traversal/KV-badlink.app": @(CSSMERR_TP_CERT_REVOKED), + @"traversal/KV-badspot.app": @(CSSMERR_TP_CERT_REVOKED), + }; + + TEST_START("kSecCSEnforceRevocationChecks finds revoked binaries inside bundles"); + + for (NSString *path in gTestPaths.allKeys) { + SecStaticCodeRef codeRef = NULL; + OSStatus status; + + NSNumber *expected = gTestPaths[path]; + INFO(@"Test case: %@, %@", path, expected); + + NSURL *url = [contentRoot URLByAppendingPathComponent:path]; + status = SecStaticCodeCreateWithPath((__bridge CFURLRef)url, kSecCSDefaultFlags, &codeRef); + TEST_CASE_EXPR_JUMP(status == errSecSuccess, lb_next); + + status = SecStaticCodeCheckValidity(codeRef, kSecCSEnforceRevocationChecks, NULL); + INFO(@"validation result: %d", status); + TEST_CASE(status == expected.integerValue, "validation succeeds with expected result"); + +lb_next: + if (codeRef) { + CFRelease(codeRef); + } + } + return; +} + +int +run_integration_tests(const char *root) +{ + NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:root]]; + NSLog(@"Running integration test with content root: %@", url); + + RevokedBinaryTraversalTest(url); + return 0; +} diff --git a/RegressionTests/codesigning_api_tests/unsigned_secstaticcodeapitest.sh b/RegressionTests/codesigning_api_tests/unsigned_secstaticcodeapitest.sh new file mode 100755 index 00000000..90af2498 --- /dev/null +++ b/RegressionTests/codesigning_api_tests/unsigned_secstaticcodeapitest.sh @@ -0,0 +1,5 @@ +#!/bin/sh +rm /tmp/secsecstaticcodeapitest_unsigned +cp /AppleInternal/CoreOS/tests/Security/secsecstaticcodeapitest /tmp/secsecstaticcodeapitest_unsigned +codesign -s - -f /tmp/secsecstaticcodeapitest_unsigned +/tmp/secsecstaticcodeapitest_unsigned unsigned diff --git a/RegressionTests/secitemnotifications/secitemnotifications.m b/RegressionTests/secitemnotifications/secitemnotifications.m index 14986bd6..94e961a3 100644 --- a/RegressionTests/secitemnotifications/secitemnotifications.m +++ b/RegressionTests/secitemnotifications/secitemnotifications.m @@ -1,6 +1,25 @@ -// -// Copyright 2016 Apple. All rights reserved. -// +/* + * Copyright (c) 2016,2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ /* * This is to fool os services to not provide the Keychain manager @@ -14,6 +33,7 @@ #include #include #include +#import int main(int argc, const char ** argv) @@ -32,8 +52,9 @@ main(int argc, const char ** argv) (id)kSecAttrAccessible : (id)kSecAttrAccessibleAfterFirstUnlock, }; status = SecItemDelete((__bridge CFDictionaryRef)query); - if (status != errSecSuccess && status != errSecItemNotFound) + if (status != errSecSuccess && status != errSecItemNotFound) { errx(1, "cleanup item: %d", (int)status); + } notify_register_dispatch("com.apple.security.view-change.PCS", &token, queue, ^(int __unused token2) { printf("got notification\n"); @@ -45,13 +66,22 @@ main(int argc, const char ** argv) */ status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); - if (status != errSecSuccess) + if (status != errSecSuccess) { errx(1, "add item: %d", (int)status); + } sleep(3); - if (!got_notification) +// Bridge explicitly disables notify phase, no PCS, octagon or sos on this platform +#if !TARGET_OS_BRIDGE + if (!got_notification) { errx(1, "failed to get notification on add"); + } +#else + if (got_notification) { + errx(1, "received unexpected notification on add"); + } +#endif got_notification = false; /* @@ -59,13 +89,21 @@ main(int argc, const char ** argv) */ status = SecItemDelete((__bridge CFDictionaryRef)query); - if (status != errSecSuccess) + if (status != errSecSuccess) { errx(1, "cleanup2 item: %d", (int)status); + } sleep(3); - if (!got_notification) +#if !TARGET_OS_BRIDGE + if (!got_notification) { errx(1, "failed to get notification on delete"); + } +#else + if (got_notification) { + errx(1, "received unexpected notification on delete"); + } +#endif return 0; } diff --git a/RegressionTests/secitemstresstest/secitemstresstest.m b/RegressionTests/secitemstresstest/secitemstresstest.m index 122a78bd..dea0cee5 100644 --- a/RegressionTests/secitemstresstest/secitemstresstest.m +++ b/RegressionTests/secitemstresstest/secitemstresstest.m @@ -43,8 +43,9 @@ Cleanup(void) (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue, }; status = SecItemDelete((__bridge CFDictionaryRef)query); - if (status != errSecSuccess || status == errSecItemNotFound) + if (status != errSecSuccess) { printf("cleanup ag1: %d\n", (int)status); + } query = @{ (id)kSecClass : (id)kSecClassGenericPassword, @@ -52,8 +53,9 @@ Cleanup(void) (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue, }; status = SecItemDelete((__bridge CFDictionaryRef)query); - if (status != errSecSuccess || status != errSecItemNotFound) + if (status != errSecSuccess) { printf("cleanup ag2: %d\n", (int)status); + } } static void diff --git a/Security.exp-in b/Security.exp-in index 26ea5d7e..0530d5d7 100644 --- a/Security.exp-in +++ b/Security.exp-in @@ -332,7 +332,6 @@ SEC_EXP_CLASS(CKKSControl) SEC_EXP_CLASS(SecuritydXPCClient) #if __OBJC2__ -SEC_EXP_CLASS(SFSignInAnalytics) SEC_EXP_CLASS(SecXPCHelper) SEC_EXP_CLASS(OTClique) SEC_EXP_CLASS(OTConfigurationContext) @@ -347,6 +346,7 @@ __OctagonSignpostLogSystem _OTCliqueStatusToString _OTCliqueStatusFromString +_OTCDPStatusToString _OTCliqueCDPContextTypeNone _OTCliqueCDPContextTypeSignIn @@ -355,6 +355,7 @@ _OTCliqueCDPContextTypeFinishPasscodeChange _OTCliqueCDPContextTypeRecoveryKeyGenerate _OTCliqueCDPContextTypeRecoveryKeyNew _OTCliqueCDPContextTypeUpdatePasscode +_OTCliqueCDPContextTypeConfirmPasscodeCyrus _OTSetupControlProtocol _OTDefaultContext @@ -364,19 +365,13 @@ _OTProtocolPiggybacking _OTDefaultsDomain _OTDefaultsOctagonEnable _OTTrustStatusChangeNotification - -_OctagonEventAttributeZoneName -_OctagonEventAttributeFailureReason -_OctagonEventAttributeTimeSinceLastPostedFollowUp +_OTEscrowRecordPrefix _SecEscrowRequestHavePrecord _SecEscrowRequestPendingPasscode _SecEscrowRequestPendingCertificate -_OTCKContainerName -_CuttlefishTrustZone _CuttlefishErrorDomain -_TrustedPeersHelperErrorDomain _CuttlefishErrorRetryAfterKey _OctagonPlatformSupportsSOS @@ -391,6 +386,14 @@ _OctagonAuthoritativeTrustIsEnabled _OctagonAuthoritativeTrustSetIsEnabled _OctagonIsSOSFeatureEnabled _OctagonSetSOSFeatureEnabled +_OctagonIsOptimizationEnabled +_OctagonSetOptimizationEnabled +_OctagonSetEscrowRecordFetchEnabled +_OctagonIsEscrowRecordFetchEnabled +_SecKVSOnCloudKitIsEnabled +_SecKVSOnCloudKitSetOverrideIsEnabled +_SecErrorIsNestedErrorCappingEnabled +_SecErrorSetOverrideNestedErrorCappingIsEnabled SEC_EXP_CLASS(OTJoiningConfiguration) SEC_EXP_CLASS(OTControl) @@ -399,6 +402,9 @@ SEC_EXP_CLASS(SecuritydXPCClient) _SecAccessGroupsGetCurrent _SecAccessGroupsSetCurrent _SecSecurityClientGet +_SecSecurityClientRegularToAppClip +_SecSecurityClientAppClipToRegular +_SecSecurityClientSetApplicationIdentifier _securityd_create_message _securityd_message_with_reply_sync _securityd_message_no_error @@ -414,7 +420,6 @@ __SecSetSecuritydTargetUID _SecDERItemCopyOIDDecimalRepresentation _SecDigestCreate -_SecFrameworkCopyResourceURL _SecCopyErrorMessageString _SecFrameworkCopyIPAddressData @@ -535,11 +540,14 @@ _AuthorizationExecuteWithPrivilegesExternalFormInternal _AuthorizationFree _AuthorizationFreeItemSet _AuthorizationMakeExternalForm -_AuthorizationPreauthorizeCredentials _AuthorizationRightGet _AuthorizationRightRemove _AuthorizationRightSet _AuthorizationEnableSmartCard +_AuthorizationCopyPreloginUserDatabase +_AuthorizationCopyPreloginPreferencesValue +_AuthorizationCopyRightProperties +_AuthorizationHandlePreloginOverride _SessionCreate _SessionGetInfo _SessionSetDistinguishedUser @@ -912,14 +920,10 @@ _SecDigestGetData _SecFDERecoveryUnwrapCRSKWithPrivKey _SecFDERecoveryWrapCRSKWithPubKey _SecGenericPasswordCreate -_SecIdentityAddPreferenceItem -_SecIdentityCompare -_SecIdentityCopyFromPreferenceItem _SecIdentityCopyPreference _SecIdentityCopyPreferred _SecIdentityCopySystemIdentity _SecIdentityCreateWithCertificate -_SecIdentityFindPreferenceItem _SecIdentitySearchCopyNext _SecIdentitySearchCreate _SecIdentitySearchCreateWithAttributes @@ -928,11 +932,10 @@ _SecIdentitySearchGetTypeID _SecIdentitySetPreference _SecIdentitySetPreferred _SecIdentitySetSystemIdentity -_SecIdentityUpdatePreferenceItem _SecInferLabelFromX509Name _SecItemAdd_ios _SecItemCopyMatching_ios -_SecItemUpdateTokenItems_ios +_SecItemUpdateTokenItemsForAccessGroups _SecKeyGeneratePair_ios @@ -941,7 +944,6 @@ _SecItemParentCachePurge _SecItemCopyStoredCertificate _SecItemCreateFromAttributeDictionary_osx -_SecItemDeleteAll _SecItemDelete_ios _SecItemExport _SecItemImport @@ -949,7 +951,6 @@ _SecItemUpdate_ios _SecKeychainAddCallback _SecKeychainAddDBToKeychainList _SecKeychainAddGenericPassword -_SecKeychainAddIToolsPassword _SecKeychainAddInternetPassword _SecKeychainAttemptMigrationWithMasterKey _SecKeychainAttributeInfoForItemID @@ -1033,7 +1034,6 @@ _SecKeychainLogout _SecKeychainMDSInstall _SecKeychainMakeFromFullPath _SecKeychainOpen -_SecKeychainOpenWithGuid _SecKeychainRecodeKeychain _SecKeychainRemoveCallback _SecKeychainRemoveDBFromKeychainList @@ -1588,6 +1588,7 @@ _SecCodeCopyHost _SecCodeCopyGuestWithAttributes _SecCodeCreateWithAuditToken _SecCodeCreateWithPID +_SecCodeCreateWithXPCMessage _SecCodeCheckValidity _SecCodeCheckValidityWithErrors _SecCodeCopyPath @@ -1609,6 +1610,8 @@ _SecStaticCodeCheckValidityWithErrors _SecStaticCodeSetCallback _SecStaticCodeSetValidationConditions _SecStaticCodeCancelValidation +_SecStaticCodeEnableOnlineNotarizationCheck +_SecStaticCodeValidateResourceWithErrors _SecRequirementGetTypeID _SecRequirementCreateWithData _SecRequirementCreateWithResource @@ -1698,6 +1701,7 @@ _kSecCodeInfoDiskRepVersionMin _kSecCodeInfoDiskRepVersionSDK _kSecCodeInfoResourceDirectory _kSecCodeInfoNotarizationDate +_kSecCodeInfoSignatureVersion _kSecGuestAttributeCanonical _kSecGuestAttributeDynamicCode _kSecGuestAttributeDynamicCodeInfoPlist @@ -1818,6 +1822,11 @@ _SecRequirementGetTypeID _SecStaticCodeCheckValidity _SecStaticCodeCreateWithPath _SecStaticCodeGetTypeID +_SecStaticCodeSetCallback +_SecStaticCodeSetValidationConditions +_SecStaticCodeCancelValidation +_SecStaticCodeEnableOnlineNotarizationCheck +_SecStaticCodeValidateResourceWithErrors _kSecCFErrorArchitecture _kSecCFErrorGuestAttributes _kSecCFErrorInfoPlist @@ -1829,6 +1838,7 @@ _kSecCFErrorResourceSideband _kSecCodeAttributeArchitecture _kSecCodeAttributeBundleVersion _kSecCodeAttributeSubarchitecture +_kSecCodeDirectoryFlagTable _kSecCodeInfoCMS _kSecCodeInfoCMSDigest _kSecCodeInfoCMSDigestHashType @@ -1855,6 +1865,7 @@ _kSecCodeInfoPlatformIdentifier _kSecCodeInfoRequirementData _kSecCodeInfoRequirements _kSecCodeInfoResourceDirectory +_kSecCodeInfoSignatureVersion _kSecCodeInfoSource _kSecCodeInfoStatus _kSecCodeInfoTimestamp @@ -1871,13 +1882,6 @@ _kSecGuestAttributeSubarchitecture #endif // TARGET_OS_IPHONE -#if TARGET_OS_OSX -//breadcrumb -_SecBreadcrumbCreateFromPassword -_SecBreadcrumbCopyPassword -_SecBreadcrumbCreateNewEncryptedKey -#endif // TARGET_OS_OSX - // // libDER OIDs // @@ -2008,6 +2012,7 @@ _SecTranslocateAppLaunchCheckin _SecTranslocateURLShouldRunTranslocated _SecTranslocateIsTranslocatedURL _SecTranslocateCreateOriginalPathForURL +_SecTranslocateCreateGeneric #endif // TARGET_OS_OSX #if TARGET_OS_OSX @@ -2086,7 +2091,9 @@ _OBJC_CLASS_$_SFAnalyticsMultiSampler _OBJC_CLASS_$_SFAnalyticsSampler _OBJC_CLASS_$_SFAnalyticsSQLiteStore _OBJC_CLASS_$_SecCoreAnalytics -_OBJC_METACLASS_$_SFSignInAnalytics +_SecCoreAnalyticsValue +_SecCoreAnalyticsSendValue +_SecCoreAnalyticsSendKernEntropyHealth _SFAnalyticsMaxEventsToReport _SFSQLiteJournalSuffixes _SFAnalyticsSamplerIntervalOncePerReport @@ -2100,6 +2107,7 @@ _SFAnalyticsColumnHardFailureCount _SFAnalyticsColumnSoftFailureCount _SFAnalyticsColumnSampleValue _SFAnalyticsColumnSampleName +_SFAnalyticsPostTime _SFAnalyticsEventTime _SFAnalyticsEventType _SFAnalyticsEventTypeErrorEvent @@ -2114,6 +2122,7 @@ _SFAnalyticsAttributeErrorUnderlyingChain _SFAnalyticsAttributeLastUploadTime _SFAnalyticsTopicCloudServices _SFAnalyticsTopicKeySync +_SFAnalyticsTopicNetworking _SFAnalyticsTopicTransparency _SFAnalyticsTopicTrust _SFAnalyticsErrorDomain @@ -2130,12 +2139,15 @@ _CKDKVSPerfCounterSynchronizeFailures _OBJC_CLASS_$_LocalKeychainAnalytics _LKAEventUpgrade +_LKAEventStash +_LKAEventStashLoad #endif // __OBJC2__ _LKAReportKeychainUpgradeOutcome _LKAReportKeychainUpgradeOutcomeWithError _LKABackupReportStart _LKABackupReportEnd +_LKAForceClose // // Padding @@ -2166,9 +2178,13 @@ _SecCreateXPCObjectWithCFError _SecItemVerifyBackupIntegrity -#ifdef DARLING -// Apple stopped exporting these (I guess they replaced them in their updated CFNetwork source), -// but we still need them for our CFNetwork -_cuDec64 -_cuEnc64 -#endif +_SecItemDeleteKeychainItemsForAppClip + +// +// File URL Overriding support +// +_SecCopyHomeURL +_SecCopyBaseFilesURL + +_SecSetCustomHomeURL +_SecSetCustomHomeURLString diff --git a/Security.xcodeproj/project.pbxproj b/Security.xcodeproj/project.pbxproj index 63d915ed..d2469708 100644 --- a/Security.xcodeproj/project.pbxproj +++ b/Security.xcodeproj/project.pbxproj @@ -13,7 +13,9 @@ buildPhases = ( ); dependencies = ( + 6C2045F82424BC4400F9461D /* PBXTargetDependency */, 47C2F1902059CBFC0062DE30 /* PBXTargetDependency */, + DCE27861245B81BD00381FE8 /* PBXTargetDependency */, D469C4E5218BECCE008AC1FC /* PBXTargetDependency */, 0C78CCE51FCC97E7008B4B24 /* PBXTargetDependency */, EB27FF261E40716D00EC9E3A /* PBXTargetDependency */, @@ -52,16 +54,29 @@ EB6A6FBD1B90F9170045DC68 /* PBXTargetDependency */, DC647C46208A85C900D0F9F8 /* PBXTargetDependency */, D4F56BAB217FCAF600FCA6B7 /* PBXTargetDependency */, + 0C65BB4F23C3F3270063D2B7 /* PBXTargetDependency */, ); name = Security_frameworks_ios; productName = kernel; }; + 0CA378E123876DD100090B7E /* reset_account */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 0CA378E323876DD100090B7E /* Build configuration list for PBXAggregateTarget "reset_account" */; + buildPhases = ( + 0CA378E623876DEC00090B7E /* CopyFiles */, + ); + dependencies = ( + ); + name = reset_account; + productName = codesigning_DTrace; + }; 4C541F840F250BF500E508AE /* Security_executables_ios */ = { isa = PBXAggregateTarget; buildConfigurationList = 4C541FA30F250C8C00E508AE /* Build configuration list for PBXAggregateTarget "Security_executables_ios" */; buildPhases = ( ); dependencies = ( + 5AAE383623D261CF0025CF9E /* PBXTargetDependency */, EB74CC232207E99700F1BBAD /* PBXTargetDependency */, 47C2F18C2059CBEA0062DE30 /* PBXTargetDependency */, 4771D982209A76B100BA9772 /* PBXTargetDependency */, @@ -166,8 +181,9 @@ buildPhases = ( ); dependencies = ( + 0CCC22D223F39A7500E1FCD0 /* PBXTargetDependency */, + 6CF33CA62387156600D1E75D /* PBXTargetDependency */, EB694E87223AB79400F02C1C /* PBXTargetDependency */, - D4E0E9762224DE9100A802E0 /* PBXTargetDependency */, D4E0E9702224DE8200A802E0 /* PBXTargetDependency */, D4E0E9722224DE8200A802E0 /* PBXTargetDependency */, D4E0E9742224DE8200A802E0 /* PBXTargetDependency */, @@ -197,8 +213,9 @@ buildPhases = ( ); dependencies = ( + 0CCC22D423F39A7C00E1FCD0 /* PBXTargetDependency */, + 6CF33CA82387157200D1E75D /* PBXTargetDependency */, EB694E72223AB78E00F02C1C /* PBXTargetDependency */, - D4E0E9AC2224DFEB00A802E0 /* PBXTargetDependency */, D4E0E9A62224DFDD00A802E0 /* PBXTargetDependency */, D4E0E9A82224DFDD00A802E0 /* PBXTargetDependency */, D4E0E9AA2224DFDD00A802E0 /* PBXTargetDependency */, @@ -275,6 +292,7 @@ buildPhases = ( ); dependencies = ( + D445C1F2258C147A0019858E /* PBXTargetDependency */, D4A763E52224BE170063B2B9 /* PBXTargetDependency */, D4A763D12224BCDE0063B2B9 /* PBXTargetDependency */, D4A763CF2224BCD10063B2B9 /* PBXTargetDependency */, @@ -348,6 +366,7 @@ D4F56B9D217FCA7E00FCA6B7 /* PBXTargetDependency */, D4F56B9F217FCA8600FCA6B7 /* PBXTargetDependency */, D4F56BB72181380600FCA6B7 /* PBXTargetDependency */, + 0C2B36C523C42EC800000718 /* PBXTargetDependency */, ); name = Security_frameworks_tvos; productName = Security_frameworks_tvos; @@ -361,6 +380,7 @@ D4F56BA7217FCAB000FCA6B7 /* PBXTargetDependency */, D4F56BA5217FCAAA00FCA6B7 /* PBXTargetDependency */, D4F56BBB2181387600FCA6B7 /* PBXTargetDependency */, + 0C2B36C323C42EBC00000718 /* PBXTargetDependency */, ); name = Security_frameworks_watchos; productName = Security_frameworks_watchos; @@ -371,6 +391,7 @@ buildPhases = ( ); dependencies = ( + 0CA378EB23876E1000090B7E /* PBXTargetDependency */, D4E0E9BC2224E15500A802E0 /* PBXTargetDependency */, D45D8F5C2224D9F100D6C124 /* PBXTargetDependency */, D45D8F5A2224D8A100D6C124 /* PBXTargetDependency */, @@ -389,6 +410,7 @@ buildPhases = ( ); dependencies = ( + 0CA378E923876E0900090B7E /* PBXTargetDependency */, D4EB53C9223C4AB5009101F8 /* PBXTargetDependency */, D4E0E9BE2224E15E00A802E0 /* PBXTargetDependency */, D45D8F902224DC9900D6C124 /* PBXTargetDependency */, @@ -608,6 +630,10 @@ buildPhases = ( ); dependencies = ( + 3E4D531F2531185D00B124B3 /* PBXTargetDependency */, + 0CCC22D023F39A6A00E1FCD0 /* PBXTargetDependency */, + 6CC638FE2266AE0A00E5DB0B /* PBXTargetDependency */, + 6CC639002266AE0A00E5DB0B /* PBXTargetDependency */, EB694E8B223AB7A200F02C1C /* PBXTargetDependency */, EB694DD0223A087700F02C1C /* PBXTargetDependency */, EB694DC82239E5F200F02C1C /* PBXTargetDependency */, @@ -626,8 +652,6 @@ D4A763E32224BDF90063B2B9 /* PBXTargetDependency */, D4A763E12224BDED0063B2B9 /* PBXTargetDependency */, D4A763DF2224BDDC0063B2B9 /* PBXTargetDependency */, - D4A763DD2224BDCC0063B2B9 /* PBXTargetDependency */, - D4A763DB2224BDAB0063B2B9 /* PBXTargetDependency */, D4A763D92224BD990063B2B9 /* PBXTargetDependency */, D4A763D52224BD6F0063B2B9 /* PBXTargetDependency */, D4A763D32224BD640063B2B9 /* PBXTargetDependency */, @@ -639,9 +663,11 @@ D477EE7B21ED48C000C9AAFF /* PBXTargetDependency */, D477EE7D21ED48CB00C9AAFF /* PBXTargetDependency */, D477EE7F21ED48D500C9AAFF /* PBXTargetDependency */, - D477EE8321ED48E800C9AAFF /* PBXTargetDependency */, D477EE8121ED48DF00C9AAFF /* PBXTargetDependency */, EBB8521022F793A200424FD0 /* PBXTargetDependency */, + 6C61D3E8242A29BA008AB9BB /* PBXTargetDependency */, + 3E88361D24F08F5400E9F4D6 /* PBXTargetDependency */, + EBAFDD6F2551D0550034B78D /* PBXTargetDependency */, ); name = Security_tests_osx; productName = Security_test_macos; @@ -652,13 +678,14 @@ buildPhases = ( ); dependencies = ( + 0CCC22CE23F39A6300E1FCD0 /* PBXTargetDependency */, + 6C2D797522C06CEF00C3CE32 /* PBXTargetDependency */, + 6C2D797322C06CEB00C3CE32 /* PBXTargetDependency */, EB694E89223AB79B00F02C1C /* PBXTargetDependency */, EB694DCE223A086C00F02C1C /* PBXTargetDependency */, EB694DC42239E5A200F02C1C /* PBXTargetDependency */, - D4E0E97A2224DEE600A802E0 /* PBXTargetDependency */, D45D8F882224DC3F00D6C124 /* PBXTargetDependency */, D45D8F862224DBF800D6C124 /* PBXTargetDependency */, - D45D8F842224DBEF00D6C124 /* PBXTargetDependency */, D45D8F822224DBE300D6C124 /* PBXTargetDependency */, D45D8F7E2224DBD900D6C124 /* PBXTargetDependency */, D45D8F7C2224DBC600D6C124 /* PBXTargetDependency */, @@ -679,7 +706,6 @@ EB58A0621E74C8E4009C10D7 /* PBXTargetDependency */, EB10557D1E14DFB60003C309 /* PBXTargetDependency */, BE9C38D31EB11605007E2AE1 /* PBXTargetDependency */, - 47D991D020407F7E0078CAE2 /* PBXTargetDependency */, EBB8521222F793AC00424FD0 /* PBXTargetDependency */, ); name = Security_tests_ios; @@ -695,6 +721,7 @@ DC647C44208A85BE00D0F9F8 /* PBXTargetDependency */, DC58C4431D77C1F8003C25A4 /* PBXTargetDependency */, D4F56BB32181306900FCA6B7 /* PBXTargetDependency */, + 0C65BB4D23C3F31B0063D2B7 /* PBXTargetDependency */, ); name = Security_frameworks_osx; productName = Security_frameworks_macos; @@ -716,6 +743,7 @@ buildPhases = ( ); dependencies = ( + 6C7BE2EA23C3DD9C003BB2CA /* PBXTargetDependency */, 47455B24205B3E2F008FE980 /* PBXTargetDependency */, D41257F71E941E9600781F23 /* PBXTargetDependency */, ); @@ -758,13 +786,14 @@ 091B39732063B67700ECAB6F /* RemoteServiceDiscovery.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 091B396D2063B64A00ECAB6F /* RemoteServiceDiscovery.framework */; }; 0940F6F82151316500C06F18 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3A1D78F228002223DE /* libACM.a */; }; 0940F6F92151316600C06F18 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3A1D78F228002223DE /* libACM.a */; }; - 096C647020AB1BC700D7B7D5 /* KeychainEntitlementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */; }; - 09BFE35C20A32E0E008511E9 /* KeychainEntitlementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */; }; + 097CE59F246966A100958AF8 /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; 09CB49701F2F64E300C8E4DE /* si-44-seckey-fv.m in Sources */ = {isa = PBXBuildFile; fileRef = 09CB496A1F2F64AF00C8E4DE /* si-44-seckey-fv.m */; }; 09EF431B21A5A8CC0066CF20 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; }; 0C00FC86217A980100C8BF00 /* OTLocalCuttlefishReset.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.m */; }; + 0C0203E623A857C1005D0A68 /* OTEscrowRecord.proto in Sources */ = {isa = PBXBuildFile; fileRef = 0C0203E023A8564E005D0A68 /* OTEscrowRecord.proto */; }; 0C0582C620D9CA4800D7BD7A /* OTClique.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CDBCD8620AD03FB007F8EA7 /* OTClique.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0C0582CC20D9CA4900D7BD7A /* OTClique.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CDBCD8620AD03FB007F8EA7 /* OTClique.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C0821EF2559D4D8006DAD6A /* secd-231-v0Peers.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C081F532559D181006DAD6A /* secd-231-v0Peers.m */; }; 0C0BDB32175685B000BC1A7E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C0BDB31175685B000BC1A7E /* main.m */; }; 0C0BDB881756A51000BC1A7E /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; 0C0BDB8D1756A66100BC1A7E /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; @@ -773,13 +802,18 @@ 0C0BDB931756A8C900BC1A7E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; 0C0C4F86216FB73C00C14C61 /* EscrowKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0C4F83216FB55600C14C61 /* EscrowKeys.swift */; }; 0C0C4F87216FB73F00C14C61 /* BottledPeer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0C4F84216FB56B00C14C61 /* BottledPeer.swift */; }; + 0C0CB73923AD714D0020C6BF /* Container_EscrowRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */; }; + 0C0CB73A23AD715A0020C6BF /* Container_EscrowRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */; }; + 0C0CB73B23AD71650020C6BF /* Container_EscrowRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */; }; 0C0CECA41DA45ED700C22FBC /* recovery_key.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C0CEC9E1DA45EA200C22FBC /* recovery_key.m */; }; + 0C0D920C23BFEAB30070A68C /* OTCDPRecoveryInformation.proto in Sources */ = {isa = PBXBuildFile; fileRef = 0C0D920523BFEA740070A68C /* OTCDPRecoveryInformation.proto */; }; 0C0DA5CE1FE1EAB9003BD3BB /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; 0C0DA5CF1FE1F1C5003BD3BB /* OTControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0D1FCB452300580909 /* OTControlProtocol.m */; }; 0C0DA5D01FE1F1F3003BD3BB /* CKKSControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF7A8A21F0450EB00CABE89 /* CKKSControlProtocol.m */; }; 0C0E60DA20D033E400E654F2 /* OTControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0E1FCB452400580909 /* OTControl.m */; }; 0C0E60E020D033E400E654F2 /* OTControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0E1FCB452400580909 /* OTControl.m */; }; 0C12B1F12138D31600BE0A98 /* OTClientStateMachine.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C12B1F02138D31600BE0A98 /* OTClientStateMachine.m */; }; + 0C147A2823F39CD10034F08B /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; 0C16371C1FD116B300210823 /* MockCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502E61E0214C800BC0587 /* MockCloudKit.m */; }; 0C1637271FD2065400210823 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; 0C1637291FD2066A00210823 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; @@ -789,6 +823,8 @@ 0C1B8BB72233244F0094D5DA /* OTVouchWithRecoveryKeyOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C1B8BB52233241E0094D5DA /* OTVouchWithRecoveryKeyOperation.m */; }; 0C29BF222323288C003C807E /* OTDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = EBCE06E521C6E26000FB1493 /* OTDefines.m */; }; 0C29BF2523232897003C807E /* OTDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = EBCE06E521C6E26000FB1493 /* OTDefines.m */; }; + 0C2B32A423C4000F00A97B18 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + 0C2B32A523C4001900A97B18 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; 0C2BCBAF1D06401F00ED7A2F /* ioSock.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65809C79E0600D27A3F /* ioSock.c */; }; 0C2BCBB01D06401F00ED7A2F /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65A09C79E0600D27A3F /* sslAppUtils.cpp */; }; 0C2BCBB41D06401F00ED7A2F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; @@ -801,50 +837,72 @@ 0C2BCBCF1D0648EF00ED7A2F /* dtlsEchoServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C2BCBA61D063F7D00ED7A2F /* dtlsEchoServer.c */; }; 0C2F337220DD64930031A92D /* OTRamping.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F337120DD647D0031A92D /* OTRamping.m */; }; 0C2F337320DD64940031A92D /* OTRamping.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F337120DD647D0031A92D /* OTRamping.m */; }; + 0C3810F123EF6FC4002D7E19 /* OctagonTrust.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */; }; 0C38AA92212B2D1900C90A1D /* OTEpochOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C4F4DE121153659007F7E20 /* OTEpochOperation.h */; }; 0C38AA96212B2D1E00C90A1D /* OTClientVoucherOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC8A9002123AA3B005D7F6A /* OTClientVoucherOperation.h */; }; 0C38AA98212B2D2300C90A1D /* OTJoinWithVoucherOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */; }; 0C3BB3582188E18C0018FC14 /* OTPrivateKey+SF.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3BB3522188E18A0018FC14 /* OTPrivateKey+SF.m */; }; 0C3BB35A2188E18C0018FC14 /* OTAuthenticatedCiphertext+SF.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3BB3542188E18B0018FC14 /* OTAuthenticatedCiphertext+SF.m */; }; 0C3C00731EF3636500AB19FE /* secd-155-otr-negotiation-monitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C00721EF3636300AB19FE /* secd-155-otr-negotiation-monitor.m */; }; + 0C3C47C624902D960084B951 /* OTSupportOctagonMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C47C024902D450084B951 /* OTSupportOctagonMessage.m */; }; + 0C3C47C724902D960084B951 /* OTSupportSOSMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C47C324902D460084B951 /* OTSupportSOSMessage.m */; }; + 0C3C47C824902DA50084B951 /* OTSupportSOSMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C47C324902D460084B951 /* OTSupportSOSMessage.m */; }; + 0C3C47C924902DA50084B951 /* OTSupportOctagonMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C47C024902D450084B951 /* OTSupportOctagonMessage.m */; }; + 0C3DF8C824789C3C009CF03A /* Container_Peers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3DF8C524789C04009CF03A /* Container_Peers.swift */; }; + 0C3DF8C924789D06009CF03A /* Container_Peers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3DF8C524789C04009CF03A /* Container_Peers.swift */; }; + 0C3DF8CA24789D0A009CF03A /* Container_Peers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3DF8C524789C04009CF03A /* Container_Peers.swift */; }; 0C3E316B21372FA50093C04B /* OctagonPairingTests+ProximitySetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C6604812134DD5D00BFBBB8 /* OctagonPairingTests+ProximitySetup.swift */; }; + 0C468FE123C7D487006F4582 /* OTEscrowRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FDE23C7D471006F4582 /* OTEscrowRecord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FE223C7D487006F4582 /* OTEscrowRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */; }; + 0C468FE323C7D487006F4582 /* OTEscrowRecordMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FDA23C7D41D006F4582 /* OTEscrowRecordMetadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FE423C7D487006F4582 /* OTEscrowRecordMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */; }; + 0C468FE523C7D487006F4582 /* OTEscrowRecordMetadataClientMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FDB23C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FE623C7D487006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */; }; + 0C468FEF23C7D4D5006F4582 /* OTCDPRecoveryInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FEA23C7D4C8006F4582 /* OTCDPRecoveryInformation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FF023C7D4D5006F4582 /* OTCDPRecoveryInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEE23C7D4CA006F4582 /* OTCDPRecoveryInformation.m */; }; + 0C468FF123C7D4D5006F4582 /* OTEscrowAuthenticationInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FE823C7D4C8006F4582 /* OTEscrowAuthenticationInformation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FF223C7D4D5006F4582 /* OTEscrowAuthenticationInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEC23C7D4C9006F4582 /* OTEscrowAuthenticationInformation.m */; }; + 0C468FF323C7D4D5006F4582 /* OTICDPRecordContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FE723C7D4C7006F4582 /* OTICDPRecordContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FF423C7D4D5006F4582 /* OTICDPRecordContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FED23C7D4C9006F4582 /* OTICDPRecordContext.m */; }; + 0C468FF523C7D4D5006F4582 /* OTICDPRecordSilentContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FE923C7D4C8006F4582 /* OTICDPRecordSilentContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FF623C7D4D5006F4582 /* OTICDPRecordSilentContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEB23C7D4C9006F4582 /* OTICDPRecordSilentContext.m */; }; + 0C468FF723C7D4E3006F4582 /* OTEscrowRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */; }; + 0C468FF823C7D4E3006F4582 /* OTEscrowRecordMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */; }; + 0C468FF923C7D4E3006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */; }; + 0C468FFA23C7D4EF006F4582 /* OTEscrowRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */; }; + 0C468FFB23C7D4EF006F4582 /* OTEscrowRecordMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */; }; + 0C468FFC23C7D4EF006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */; }; + 0C468FFD23C7D4F9006F4582 /* OTEscrowRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */; }; + 0C468FFE23C7D4F9006F4582 /* OTEscrowRecordMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */; }; + 0C468FFF23C7D4F9006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */; }; 0C46A5712034C6BA00F17112 /* OTControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0E1FCB452400580909 /* OTControl.m */; }; 0C48990B1E0E0FF300C6CF70 /* SOSTransportCircleCK.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C48990A1E0E0FF300C6CF70 /* SOSTransportCircleCK.h */; }; 0C4899121E0E105D00C6CF70 /* SOSTransportCircleCK.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C4899111E0E105D00C6CF70 /* SOSTransportCircleCK.m */; }; 0C4899231E0F386900C6CF70 /* SOSAccountTrustClassic.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C4899221E0F386900C6CF70 /* SOSAccountTrustClassic.h */; }; 0C48B380202E438100A0E1AA /* CloudKitKeychainSyncingMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC08D1C31E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m */; }; - 0C4C547620E1A0B400BA61BA /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C4C548020E1A53D00BA61BA /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; 0C4CDE6F22922E550050C499 /* OctagonTests+RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C4CDE6D22922E360050C499 /* OctagonTests+RecoveryKey.swift */; }; - 0C4D96A621F24E5700617E60 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C4D96A721F25F2C00617E60 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; 0C4F4DE221153E9E007F7E20 /* OTEpochOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C4F4DDA211535E8007F7E20 /* OTEpochOperation.m */; }; 0C5258BA21BB062F00B32C96 /* FakeSOSControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C5258B821BB05C100B32C96 /* FakeSOSControl.m */; }; 0C5258BB21BB128000B32C96 /* FakeSOSControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C5258B821BB05C100B32C96 /* FakeSOSControl.m */; }; 0C5258BD21BB137900B32C96 /* FakeSOSControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C5258BC21BB137800B32C96 /* FakeSOSControl.h */; }; - 0C5663EC20BE2DF30035F362 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; - 0C5663EF20BE2E220035F362 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; + 0C570B7923F3A015001FEB3B /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0C570B7B23F3A09A001FEB3B /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0C570B7C23F3A0E3001FEB3B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + 0C570B8123F3A1EC001FEB3B /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; 0C5824A52286002D009E8C15 /* OctagonTests+HealthCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C5824A322860001009E8C15 /* OctagonTests+HealthCheck.swift */; }; 0C5960641FB2E2070095BA29 /* libprequelite.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */; settings = {ATTRIBUTES = (Weak, ); }; }; 0C5960811FB369C50095BA29 /* CKKSHealTLKSharesOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBF2F841F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.m */; }; 0C61F1F62194FC79009566D4 /* OTPrivateKey+SF.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3BB3522188E18A0018FC14 /* OTPrivateKey+SF.m */; }; 0C61F1F92194FC82009566D4 /* OTAuthenticatedCiphertext+SF.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3BB3542188E18B0018FC14 /* OTAuthenticatedCiphertext+SF.m */; }; + 0C64C0802485B2EF00D84A5D /* OTPreloadOctagonKeysOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C64C07C2485A53000D84A5D /* OTPreloadOctagonKeysOperation.m */; }; 0C66046A2134983900BFBBB8 /* OTEstablishOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C6604692134983900BFBBB8 /* OTEstablishOperation.m */; }; 0C66047E2134CA5600BFBBB8 /* OTDeviceInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C66047B2134C88C00BFBBB8 /* OTDeviceInformation.m */; }; - 0C6C0FCB21F1415B00CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FCF21F1457600CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD021F145F600CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD121F1465500CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD221F146E700CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD321F1494C00CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD621F14D3900CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C78826F20132069002B7475 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; - 0C78827520132074002B7475 /* SFSignInAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */; }; 0C78F1CC16A5E1BF00654E08 /* sectask-10-sectask.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CA16A5E1BF00654E08 /* sectask-10-sectask.c */; }; 0C78F1CD16A5E1BF00654E08 /* sectask-10-sectask.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CA16A5E1BF00654E08 /* sectask-10-sectask.c */; }; 0C78F1CE16A5E1BF00654E08 /* sectask_ipc.defs in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CB16A5E1BF00654E08 /* sectask_ipc.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; }; 0C78F1CF16A5E1BF00654E08 /* sectask_ipc.defs in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CB16A5E1BF00654E08 /* sectask_ipc.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; }; 0C78F1D016A5E3EB00654E08 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; + 0C79213D23C3F6E100193389 /* OctagonTrust.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD743B723C3ED7E00FA0EC5 /* OctagonTrust.m */; }; 0C7A8BBF21714CDC00F4C480 /* OTJoiningConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8FD549214AECD70098E3FB /* OTJoiningConfiguration.m */; }; 0C7A8BC021714D0E00F4C480 /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 0C84D8341FCF43AF00B822E3 /* OTControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0D1FCB452300580909 /* OTControlProtocol.m */; }; @@ -880,13 +938,12 @@ 0C8884042154C4EA0053224D /* OTJoiningConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8FD549214AECD70098E3FB /* OTJoiningConfiguration.m */; }; 0C8FD52521483EF20098E3FB /* OT.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CCCC7C820261D310024405E /* OT.m */; }; 0C97867D235A77230040A867 /* com.apple.security.signposts.plist in Copy System logging profile */ = {isa = PBXBuildFile; fileRef = 0C97867C235A76E70040A867 /* com.apple.security.signposts.plist */; }; - 0C98122821ACCC9300784441 /* OTClique.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F336A20DD643B0031A92D /* OTClique.m */; }; - 0C9AEEAF20783FBB00BF6237 /* SFSignInAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */; }; - 0C9AEEBB20783FF900BF6237 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - 0C9AEEBE207843D000BF6237 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; - 0C9FB40720D872A600864612 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C9FB40920D8735500864612 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; + 0C9A54B6250C286100FF007B /* OctagonTrustTests+Errors.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9A54B4250C27F100FF007B /* OctagonTrustTests+Errors.m */; }; + 0C9F65AD23E3AD2E00B1A2C5 /* OTEscrowTranslation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C9F65AC23E3ACF700B1A2C5 /* OTEscrowTranslation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C9F65AE23E3AD3200B1A2C5 /* OTEscrowTranslation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9F65AA23E3ACF700B1A2C5 /* OTEscrowTranslation.m */; }; + 0CA1D0B923E9034600021038 /* OctagonTests+EscrowTestVectors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA1D0B223E9023100021038 /* OctagonTests+EscrowTestVectors.swift */; }; 0CA2282F2187A5CA00A1C56C /* BottledPeer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0C4F84216FB56B00C14C61 /* BottledPeer.swift */; }; + 0CA378E723876DFC00090B7E /* reset_ick_account in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0C7382F023863AD5004F98CB /* reset_ick_account */; }; 0CA4B4722171410200B17169 /* EscrowKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0C4F83216FB55600C14C61 /* EscrowKeys.swift */; }; 0CA4EBF3202B8D9C002B1D96 /* CloudKitKeychainSyncingTestsBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CA4EBF2202B8D1D002B1D96 /* CloudKitKeychainSyncingTestsBase.m */; }; 0CA4EBF4202B8DBE002B1D96 /* CloudKitKeychainSyncingTestsBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CA4EBF2202B8D1D002B1D96 /* CloudKitKeychainSyncingTestsBase.m */; }; @@ -899,7 +956,6 @@ 0CAD1E591E1C5CBD00537693 /* secd-52-offering-gencount-reset.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C4F1D8085D800865A7C /* secd-52-offering-gencount-reset.m */; }; 0CAD1E5A1E1C5CD100537693 /* secd-71-engine-save.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C641D8085D800865A7C /* secd-71-engine-save.m */; }; 0CAD1E5D1E1C5CF900537693 /* secd-80-views-alwayson.m in Sources */ = {isa = PBXBuildFile; fileRef = 7281E08B1DFD0A380021E1B7 /* secd-80-views-alwayson.m */; }; - 0CAD1E5E1E1C5D0600537693 /* secd-95-escrow-persistence.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C741D8085D800865A7C /* secd-95-escrow-persistence.m */; }; 0CADDF0721545CF100DF8B06 /* OctagonPairingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CADDF0421545C8E00DF8B06 /* OctagonPairingTests.swift */; }; 0CB50A0D20AA486800FE4675 /* SOSAccountTrustClassic+Expansion.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE760471E12F2F200B4381E /* SOSAccountTrustClassic+Expansion.m */; }; 0CB50A0E20AA4C2F00FE4675 /* SOSAccountTrustClassic+Circle.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE760491E12F30200B4381E /* SOSAccountTrustClassic+Circle.m */; }; @@ -915,28 +971,59 @@ 0CB5C678218B803C0044F730 /* OTPrivateKey+SF.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3BB3522188E18A0018FC14 /* OTPrivateKey+SF.m */; }; 0CB72D9D21E42FCF00D8BC9B /* OTApplicantToSponsorRound2M1.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9AE28E214054F6003BFDB5 /* OTApplicantToSponsorRound2M1.m */; }; 0CB72D9E21E42FCF00D8BC9B /* OTPairingMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9AE2A2214055CF003BFDB5 /* OTPairingMessage.m */; }; - 0CB72D9F21E42FCF00D8BC9B /* OTSOSMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE9C98A21B8891A006BDD80 /* OTSOSMessage.m */; }; 0CB72DA021E42FCF00D8BC9B /* OTSponsorToApplicantRound1M2.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9AE28D214054F6003BFDB5 /* OTSponsorToApplicantRound1M2.m */; }; 0CB72DA121E42FCF00D8BC9B /* OTSponsorToApplicantRound2M2.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9AE290214054F7003BFDB5 /* OTSponsorToApplicantRound2M2.m */; }; 0CB8DC9A2194B14C0021A7C8 /* OTVouchWithBottleOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CB8DC992194B1440021A7C8 /* OTVouchWithBottleOperation.m */; }; 0CB9754F2023A8F5008D6B48 /* CloudKitMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC222CA71E08A7D900B09171 /* CloudKitMockXCTest.m */; }; 0CBA047D214C4E4D005B3A2F /* OctagonPairingTests+ProxMultiClients.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBA047C214C4E4D005B3A2F /* OctagonPairingTests+ProxMultiClients.swift */; }; - 0CBD55B31FE883F200A8CE21 /* SFBehavior.m in Sources */ = {isa = PBXBuildFile; fileRef = EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */; }; 0CBEF3432242CA0600015691 /* TestsObjcTranslation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CBEF3412242C9AE00015691 /* TestsObjcTranslation.m */; }; - 0CBFEACA200FCD2D009A60E9 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; - 0CBFEACB200FCD2D009A60E9 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; - 0CBFEACC200FCD33009A60E9 /* SFSignInAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0CBFEACD200FCD33009A60E9 /* SFSignInAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0CBF883D23AAD9F100652EDD /* OctagonTests+EscrowRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBF883A23AAD9DC00652EDD /* OctagonTests+EscrowRecords.swift */; }; 0CC319241DA46FBF005D42EA /* ProtectedCloudStorage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43DB542E1BB1F85B0083C3F1 /* ProtectedCloudStorage.framework */; }; - 0CC3771320A222BC00B58D2D /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; 0CC593F02299B9AA006C34B5 /* SecInternalRelease.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC761D8C68CF00070CB0 /* SecInternalRelease.c */; }; 0CC593F62299EC3D006C34B5 /* OTDeviceInformationAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC19484B21812EC5007C2260 /* OTDeviceInformationAdapter.m */; }; 0CC593F92299EE06006C34B5 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; 0CC8A8FE2123A9F6005D7F6A /* OTClientVoucherOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CC8A8FA2123A9EB005D7F6A /* OTClientVoucherOperation.m */; }; 0CC8A9032123AF06005D7F6A /* OTJoinWithVoucherOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */; }; + 0CC9403023F39E84004B71AA /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0CCC21FC23F33DA900E1FCD0 /* OTICDPRecordContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FED23C7D4C9006F4582 /* OTICDPRecordContext.m */; }; + 0CCC21FD23F33DCE00E1FCD0 /* OTCDPRecoveryInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEE23C7D4CA006F4582 /* OTCDPRecoveryInformation.m */; }; + 0CCC21FE23F33DD400E1FCD0 /* OTEscrowAuthenticationInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEC23C7D4C9006F4582 /* OTEscrowAuthenticationInformation.m */; }; + 0CCC21FF23F3577A00E1FCD0 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; + 0CCC22A023F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CCC229F23F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m */; }; + 0CCC22A423F374EB00E1FCD0 /* OctagonTrust.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */; }; + 0CCC22A523F3763C00E1FCD0 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; + 0CCC22A623F3868400E1FCD0 /* OTControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0E1FCB452400580909 /* OTControl.m */; }; + 0CCC22A823F38AD600E1FCD0 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; + 0CCC22A923F38AFD00E1FCD0 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; + 0CCC22AE23F38B2D00E1FCD0 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + 0CCC22B223F38B5B00E1FCD0 /* libsqlite3.0.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22B123F38B5B00E1FCD0 /* libsqlite3.0.tbd */; }; + 0CCC22B323F38B6D00E1FCD0 /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; + 0CCC22B623F38BCD00E1FCD0 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; }; + 0CCC22B723F38BF500E1FCD0 /* CloudKitMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC222CA71E08A7D900B09171 /* CloudKitMockXCTest.m */; }; + 0CCC22B823F38C0E00E1FCD0 /* MockCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502E61E0214C800BC0587 /* MockCloudKit.m */; }; + 0CCC22B923F38C3000E1FCD0 /* CKKSMockSOSPresentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA9BC06221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.m */; }; + 0CCC22BB23F38C8800E1FCD0 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; + 0CCC22BC23F38D3500E1FCD0 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; + 0CCC22BD23F38D4B00E1FCD0 /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EB49B2DC202DF251003F34A0 /* libbsm.tbd */; }; + 0CCC22BE23F38D7C00E1FCD0 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; + 0CCC22BF23F38D8E00E1FCD0 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; + 0CCC22C023F38DA100E1FCD0 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; + 0CCC22C123F38DC100E1FCD0 /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; + 0CCC22C723F3904D00E1FCD0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 0CCC22C823F390E400E1FCD0 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47D1838B1FB3827700CFCD89 /* OCMock.framework */; }; + 0CCC22C923F3932600E1FCD0 /* CloudKitKeychainSyncingTestsBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CA4EBF2202B8D1D002B1D96 /* CloudKitKeychainSyncingTestsBase.m */; }; + 0CCC22CA23F3933000E1FCD0 /* CloudKitKeychainSyncingMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC08D1C31E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m */; }; + 0CCC22D623F39B2E00E1FCD0 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0CCC22D723F39B7200E1FCD0 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0CCC22D823F39BCA00E1FCD0 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; 0CCDE7171EEB08220021A946 /* secd-156-timers.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CCDE7161EEB08220021A946 /* secd-156-timers.m */; }; 0CD3D519224048A800024755 /* OTSetRecoveryKeyOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD3D5152240479600024755 /* OTSetRecoveryKeyOperation.m */; }; + 0CD5040523F39DEA0036C279 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; 0CD5797A21498F8200C43496 /* OctagonPairingTests+Piggybacking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD5797721498F7700C43496 /* OctagonPairingTests+Piggybacking.swift */; }; + 0CD743AA23C3EC8000FA0EC5 /* OctagonTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CD743A823C3EC8000FA0EC5 /* OctagonTrust.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0CD743AF23C3ECEB00FA0EC5 /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C441E2537CC007F95E5 /* ProtocolBuffer.framework */; }; + 0CD743BB23C3EF1D00FA0EC5 /* OTClique+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CD743BA23C3EF0D00FA0EC5 /* OTClique+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0CD743BC23C3EF1E00FA0EC5 /* OTClique+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CD743BA23C3EF0D00FA0EC5 /* OTClique+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0CD8CB051ECA50780076F37F /* SOSPeerOTRTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */; }; 0CD8CB0B1ECA50920076F37F /* SOSPeerOTRTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */; }; 0CD9E34323592DD7002995DE /* OctagonSignPosts.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CD9E33E235928D1002995DE /* OctagonSignPosts.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -944,7 +1031,6 @@ 0CD9E34523592EA6002995DE /* OctagonSignPosts.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD9E340235928E9002995DE /* OctagonSignPosts.m */; }; 0CD9E34623592EA7002995DE /* OctagonSignPosts.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD9E340235928E9002995DE /* OctagonSignPosts.m */; }; 0CDD6F79226E83F6009094C2 /* OTTriggerEscrowUpdateOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CDD6F76226E62AD009094C2 /* OTTriggerEscrowUpdateOperation.m */; }; - 0CE079F41FEA15B20040A3F1 /* SFBehavior.m in Sources */ = {isa = PBXBuildFile; fileRef = EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */; }; 0CE15E2C222DF63600B7EAA4 /* RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E2A222DF63500B7EAA4 /* RecoveryKey.swift */; }; 0CE15E2D222DF63600B7EAA4 /* RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E2A222DF63500B7EAA4 /* RecoveryKey.swift */; }; 0CE15E2F222DF63600B7EAA4 /* RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E2A222DF63500B7EAA4 /* RecoveryKey.swift */; }; @@ -959,7 +1045,6 @@ 0CE15E43222DF6A800B7EAA4 /* Recovery.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E3C222DF6A700B7EAA4 /* Recovery.m */; }; 0CE15E44222DF6A800B7EAA4 /* Recovery.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E3C222DF6A700B7EAA4 /* Recovery.m */; }; 0CE15E46222DF6A800B7EAA4 /* Recovery.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E3C222DF6A700B7EAA4 /* Recovery.m */; }; - 0CE751AF20ACC497002B2832 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; 0CE760501E1301DC00B4381E /* SOSAccountTrustClassic+Expansion.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CE7604F1E1301DC00B4381E /* SOSAccountTrustClassic+Expansion.h */; }; 0CE760521E1314F700B4381E /* SOSAccountTrustClassic+Identity.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CE760511E1314F700B4381E /* SOSAccountTrustClassic+Identity.h */; }; 0CE760541E13155100B4381E /* SOSAccountTrustClassic+Circle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CE760531E13155100B4381E /* SOSAccountTrustClassic+Circle.h */; }; @@ -969,7 +1054,7 @@ 0CE887D22299A8CF0082D120 /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; 0CE887D32299A9090082D120 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 0CE887D52299A9C70082D120 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; - 0CF406522072E422003D6A7F /* SFSignInAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */; }; + 0CE902352395D0A3005E3F8C /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 0CF70BD9218BED1000EC3515 /* CuttlefishExtensionWorkaround.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF70BD6218BECF500EC3515 /* CuttlefishExtensionWorkaround.swift */; }; 0CF70BDA218BEFAE00EC3515 /* CuttlefishExtensionWorkaround.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF70BD6218BECF500EC3515 /* CuttlefishExtensionWorkaround.swift */; }; 0CF70BDB218BEFF000EC3515 /* CuttlefishExtensionWorkaround.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF70BD6218BECF500EC3515 /* CuttlefishExtensionWorkaround.swift */; }; @@ -995,7 +1080,6 @@ 1B5EAADD2252ABCD008D27E7 /* OTFetchViewsOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B5EAADB2252ABCC008D27E7 /* OTFetchViewsOperation.m */; }; 1B8341B92239AD3A002BF18A /* TPPBPolicyKeyViewMapping.proto in Sources */ = {isa = PBXBuildFile; fileRef = 1B8341B72239AD39002BF18A /* TPPBPolicyKeyViewMapping.proto */; }; 1B8D2D96226E1FA500C94238 /* SetValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E2A222DF63500B7EAA5 /* SetValueTransformer.swift */; }; - 1B916CD0223FFF25006657FD /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C441E2537CC007F95E5 /* ProtocolBuffer.framework */; }; 1B995259226681FA00A2D6CD /* PolicyReporter.h in Sources */ = {isa = PBXBuildFile; fileRef = 1B995256226681ED00A2D6CD /* PolicyReporter.h */; }; 1B99525A226681FA00A2D6CD /* PolicyReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B995258226681EE00A2D6CD /* PolicyReporter.m */; }; 1BB1CAB7232C05BD001D0C71 /* CuttlefishXPCWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BB1CAB4232C05BB001D0C71 /* CuttlefishXPCWrapper.m */; }; @@ -1077,7 +1161,6 @@ 3DD1FF9F201FC5410086D049 /* STLegacyTests+sslciphers.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1FE81201AA5100086D049 /* STLegacyTests+sslciphers.m */; }; 3DD1FFA0201FC5450086D049 /* STLegacyTests+tls12.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1FE7D201AA50E0086D049 /* STLegacyTests+tls12.m */; }; 3DD1FFA1201FC5660086D049 /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCA451D8B82CD00070CB0 /* ssl-utils.c */; }; - 3DD1FFA2201FC5800086D049 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; 3DD1FFA3201FC5870086D049 /* libDiagnosticMessagesClient.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41D36701EB14D87007FA978 /* libDiagnosticMessagesClient.tbd */; }; 3DD1FFA4201FC58F0086D049 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 3DD1FFA5201FC59D0086D049 /* libsecurity_ssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BC9CF1D8B824700070CB0 /* libsecurity_ssl.a */; }; @@ -1104,13 +1187,17 @@ 3DD1FFC6201FDB1D0086D049 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; 3DD1FFC8201FDB1D0086D049 /* libsecurity_ssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BC9CF1D8B824700070CB0 /* libsecurity_ssl.a */; }; 3DD1FFC9201FDB1D0086D049 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; - 3DD1FFCB201FDB1D0086D049 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; 3DD1FFD1201FDC460086D049 /* STLegacyTests+clientauth41.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1FE78201AA50C0086D049 /* STLegacyTests+clientauth41.m */; }; 3DD1FFD5201FF7860086D049 /* SecureTransport_iosTests.plist in Copy Plist */ = {isa = PBXBuildFile; fileRef = 3DD1FE86201AA5120086D049 /* SecureTransport_iosTests.plist */; }; 3DD1FFD7201FF7B10086D049 /* SecureTransport_macosTests.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3DD1FE79201AA50D0086D049 /* SecureTransport_macosTests.plist */; }; 3DD2589F20478CF900F5DA78 /* STLegacyTests+session.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2589820478CCE00F5DA78 /* STLegacyTests+session.m */; }; 3DD258A020478CFA00F5DA78 /* STLegacyTests+session.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2589820478CCE00F5DA78 /* STLegacyTests+session.m */; }; 3DD258AC2051F10300F5DA78 /* STLegacyTests+sni.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1FE7F201AA50F0086D049 /* STLegacyTests+sni.m */; }; + 3E4D49B72531170600B124B3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; + 3E4D49B82531170600B124B3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 3E4D508F253117DD00B124B3 /* secstaticcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3E4D508E253117DD00B124B3 /* secstaticcode.cpp */; }; + 3E88360D24F068EF00E9F4D6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 3E88361B24F08DA100E9F4D6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; 433E519E1B66D5F600482618 /* AppSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 433E519D1B66D5F600482618 /* AppSupport.framework */; }; 4381603A1B4DCE8F00C54D58 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; 4381603B1B4DCEFF00C54D58 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; @@ -1246,7 +1333,6 @@ 4718AE92205B39C40068EC3F /* CKKSSIV.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D541E2826DB0089CF55 /* CKKSSIV.m */; }; 4718AE96205B39C40068EC3F /* CKKSZoneChangeFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = DC9082C31EA0276000D0C1C5 /* CKKSZoneChangeFetcher.m */; }; 4718AE97205B39C40068EC3F /* CKKSCondition.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFE1C331F17ECE5007640C8 /* CKKSCondition.m */; }; - 4718AE98205B39C40068EC3F /* CKKSZone.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D961E3014250089CF55 /* CKKSZone.m */; }; 4718AE99205B39C40068EC3F /* SFKeychainServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 47FF17251FD60ACA00875565 /* SFKeychainServer.m */; }; 4718AE9B205B39C40068EC3F /* swcagent_client.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78EA01D80860C00865A7C /* swcagent_client.c */; }; 4718AE9E205B39C40068EC3F /* SecDbKeychainSerializedAKSWrappedKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 47922D371FAA7C040008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.h */; }; @@ -1326,7 +1412,6 @@ 4727FBC91F991E5A0003AE36 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 4727FBCD1F991F660003AE36 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBCC1F991F660003AE36 /* libsqlite3.dylib */; }; 4727FBCE1F991F820003AE36 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBCF1F991F820003AE36 /* SecurityFoundation.framework */; }; - 4727FBD11F991F990003AE36 /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD01F991F990003AE36 /* libMobileGestalt.dylib */; }; 4727FBD31F9920290003AE36 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD21F9920290003AE36 /* CloudKit.framework */; }; 4727FBD51F9920510003AE36 /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD41F9920510003AE36 /* ProtocolBuffer.framework */; }; 4727FBD61F9920960003AE36 /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; @@ -1351,7 +1436,6 @@ 475F37201EE8F23900248FB5 /* SFAnalytics.plist in Resources */ = {isa = PBXBuildFile; fileRef = 475F371F1EE8F23900248FB5 /* SFAnalytics.plist */; }; 475F37211EE8F23900248FB5 /* SFAnalytics.plist in Resources */ = {isa = PBXBuildFile; fileRef = 475F371F1EE8F23900248FB5 /* SFAnalytics.plist */; }; 4764E9272059D866005497C9 /* KeychainModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 470D966B1FCDE4BA0065FE90 /* KeychainModel.xcdatamodeld */; }; - 4764E92D2059D8BF005497C9 /* KeychainModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 470D966B1FCDE4BA0065FE90 /* KeychainModel.xcdatamodeld */; }; 476541651F339F6300413F65 /* SecdWatchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = 476541631F339F6300413F65 /* SecdWatchdog.h */; }; 476541701F33B59300413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541711F33B59500413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; @@ -1359,8 +1443,6 @@ 476541A11F33EDA500413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541A21F33EDAD00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541A31F33EDCC00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; - 476541A41F33EDED00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; - 476541A51F33EE1E00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541A61F33EE2700413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541A71F33EE3F00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 47702B181E5E58E600B29577 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40B6A881E2B5F9900CD6EE5 /* Foundation.framework */; }; @@ -1374,47 +1456,13 @@ 4771D9A0209B7C2700BA9772 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4771D99F209B7C2600BA9772 /* Security.framework */; }; 4771D9A2209B7C3900BA9772 /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4771D9A1209B7C3900BA9772 /* Accounts.framework */; }; 477A1F5220320E4A00ACD81D /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 477A1F4C20320E4900ACD81D /* Accounts.framework */; }; - 477A1F5320320E5100ACD81D /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF4C19C171E0EA600877419 /* Accounts.framework */; }; 477A1FE4203763A500ACD81D /* KeychainAPITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 477A1FE1203763A500ACD81D /* KeychainAPITests.m */; }; - 477A1FE5203763A500ACD81D /* KeychainAPITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 477A1FE1203763A500ACD81D /* KeychainAPITests.m */; }; 477A1FED2037A0E000ACD81D /* KeychainXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */; }; - 477A1FEE2037A0E000ACD81D /* KeychainXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */; }; 478014541FBF577000C4043D /* si-44-seckey-proxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 09A3B9DF1F8271A200C5C324 /* si-44-seckey-proxy.m */; }; 4780146A1FBF5BD600C4043D /* SecKeyProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 09E9991F1F7D76550018DF67 /* SecKeyProxy.m */; }; 478014701FBF5BD800C4043D /* SecKeyProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 09E9991F1F7D76550018DF67 /* SecKeyProxy.m */; }; 478014791FBF5D2000C4043D /* SecKeyProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 09A3B9D71F8267BB00C5C324 /* SecKeyProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4780147F1FBF5D2100C4043D /* SecKeyProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 09A3B9D71F8267BB00C5C324 /* SecKeyProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 478D42761FD72A8100CAB645 /* server_xpc.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB2214A1E8B0861001598BC /* server_xpc.m */; }; - 478D42771FD72A8100CAB645 /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; - 478D42781FD72A8100CAB645 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; - 478D42791FD72A8100CAB645 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; - 478D427A1FD72A8100CAB645 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; - 478D427B1FD72A8100CAB645 /* KeychainCryptoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4727FBB91F9918590003AE36 /* KeychainCryptoTests.m */; }; - 478D427C1FD72A8100CAB645 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; - 478D427F1FD72A8100CAB645 /* libprequelite.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 472339611FD7155C00CB6A72 /* libprequelite.dylib */; }; - 478D42801FD72A8100CAB645 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47D1838B1FB3827700CFCD89 /* OCMock.framework */; }; - 478D42811FD72A8100CAB645 /* libregressionBase.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCBFD1D8C648C00070CB0 /* libregressionBase.a */; }; - 478D42821FD72A8100CAB645 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE81F9921D00003AE36 /* libACM.a */; }; - 478D42831FD72A8100CAB645 /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE61F9921890003AE36 /* ApplePushService.framework */; }; - 478D42841FD72A8100CAB645 /* SharedWebCredentials.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE41F99217A0003AE36 /* SharedWebCredentials.framework */; }; - 478D42851FD72A8100CAB645 /* MobileKeyBag.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE21F9921660003AE36 /* MobileKeyBag.framework */; }; - 478D42861FD72A8100CAB645 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE01F99212F0003AE36 /* IOKit.framework */; }; - 478D42871FD72A8100CAB645 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBDE1F99211D0003AE36 /* libaks.a */; }; - 478D42881FD72A8100CAB645 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBDC1F9920F10003AE36 /* libaks_acl.a */; }; - 478D42891FD72A8100CAB645 /* WirelessDiagnostics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBDA1F9920CB0003AE36 /* WirelessDiagnostics.framework */; }; - 478D428A1FD72A8100CAB645 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD81F9920BB0003AE36 /* SystemConfiguration.framework */; }; - 478D428B1FD72A8100CAB645 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - 478D428C1FD72A8100CAB645 /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; - 478D428D1FD72A8100CAB645 /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD41F9920510003AE36 /* ProtocolBuffer.framework */; }; - 478D428E1FD72A8100CAB645 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD21F9920290003AE36 /* CloudKit.framework */; }; - 478D42901FD72A8100CAB645 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBCF1F991F820003AE36 /* SecurityFoundation.framework */; }; - 478D42911FD72A8100CAB645 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBCC1F991F660003AE36 /* libsqlite3.dylib */; }; - 478D42931FD72A8100CAB645 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; - 478D42951FD72A8100CAB645 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; - 478D42961FD72A8100CAB645 /* libsecdRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52EDB11D80D58400B0A59C /* libsecdRegressions.a */; }; - 478D42971FD72A8100CAB645 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBC41F991C460003AE36 /* Foundation.framework */; }; - 478D429E1FD72C4800CAB645 /* CrashReporterSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E9391D7F3DF200AFB96E /* CrashReporterSupport.framework */; }; - 478D429F1FD72C8400CAB645 /* AppleSystemInfo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3F1D78F2FF002223DE /* AppleSystemInfo.framework */; }; 479108B71EE879F9008CEFA0 /* CKKSAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 479108B51EE879F9008CEFA0 /* CKKSAnalytics.h */; }; 4791B4652118BBFF00977C3F /* OTControlProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8BBF0C1FCB452200580909 /* OTControlProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4791B46B2118BC0000977C3F /* OTControlProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8BBF0C1FCB452200580909 /* OTControlProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -1428,7 +1476,6 @@ 47922D541FAA7E060008F7E0 /* SecDbKeychainSerializedItemV7.h in Headers */ = {isa = PBXBuildFile; fileRef = 47922D501FAA7DF60008F7E0 /* SecDbKeychainSerializedItemV7.h */; }; 47922D561FAA7E0D0008F7E0 /* SecDbKeychainSerializedItemV7.m in Sources */ = {isa = PBXBuildFile; fileRef = 47922D511FAA7DF70008F7E0 /* SecDbKeychainSerializedItemV7.m */; }; 479231E82065B31300B2718C /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; - 479231EE2065B32200B2718C /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; 479231EF2065C52200B2718C /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; 479231F02065C52D00B2718C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; 479DA1721EBBA8D10065C98F /* CKKSManifest.m in Sources */ = {isa = PBXBuildFile; fileRef = 47CEED1F1E60DE900044EAB4 /* CKKSManifest.m */; }; @@ -1437,7 +1484,6 @@ 47A05B181FDB5DBC00D0816E /* SFKeychainControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 47A05B101FDB5A8B00D0816E /* SFKeychainControl.h */; }; 47A0ABA81E6F7B24001B388C /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 474B5FBF1E662E21007546F8 /* SecurityFoundation.framework */; }; 47A91562201A43BA00FF8F46 /* SecSharedCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = BE061FE01899ECEE00C739F6 /* SecSharedCredential.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 47B011991F17D78D0030B49F /* SFSQLiteStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BF1F152EB10082882F /* SFSQLiteStatement.m */; }; 47B90C901F350966006500BC /* CrashReporterSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E9391D7F3DF200AFB96E /* CrashReporterSupport.framework */; }; 47C2F1762059A2300062DE30 /* libprequelite.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */; }; 47C2F1842059CB680062DE30 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBC41F991C460003AE36 /* Foundation.framework */; }; @@ -1459,19 +1505,15 @@ 482FE5642177C6850031C11E /* libprequelite.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */; }; 482FE5652177C6D90031C11E /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF4C19C171E0EA600877419 /* Accounts.framework */; }; 482FE5662177C6E40031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; - 482FE5672177C7260031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; - 482FE5682177C73C0031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 482FE5692177C7670031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; - 482FE56A2177C7980031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 482FE56C2177CEEF0031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 482FE56D2177CF150031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 482FE56E2177CF340031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 482FE56B2177C7AE0031C11E /* AuthKit.framework */; }; 482FE56F2177CF520031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 483E798F1DC87605005C0008 /* secd-67-prefixedKeyIDs.m in Sources */ = {isa = PBXBuildFile; fileRef = 483E79891DC875F2005C0008 /* secd-67-prefixedKeyIDs.m */; }; + 487A65F4245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m in Sources */ = {isa = PBXBuildFile; fileRef = 487A65F3245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m */; }; 48AC7B73232B1DA600F02B6F /* SOSIntervalEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 48AC7B71232B1A7000F02B6F /* SOSIntervalEvent.m */; }; 48CC589F1DA5FF2700EBD9DB /* secd-66-account-recovery.m in Sources */ = {isa = PBXBuildFile; fileRef = 48CC58971DA5FF0B00EBD9DB /* secd-66-account-recovery.m */; }; - 48E617211DBEC6BA0098EAAD /* SOSBackupInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 48E6171A1DBEC40D0098EAAD /* SOSBackupInformation.m */; }; - 48E617221DBEC6C60098EAAD /* SOSBackupInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = 48E6171B1DBEC40D0098EAAD /* SOSBackupInformation.h */; }; 48FE669620E6E69D00FAEF17 /* SOSAuthKitHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 48FE668F20E6E69B00FAEF17 /* SOSAuthKitHelpers.m */; }; 48FE669720E6E69D00FAEF17 /* SOSAuthKitHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 48FE669520E6E69C00FAEF17 /* SOSAuthKitHelpers.h */; }; 4AF7000115AFB73800B9D400 /* SecOTRMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFF715AFB73800B9D400 /* SecOTRMath.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -1496,93 +1538,11 @@ 4C32C1260A4976BF002891BD /* SecTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8FD03E099D5C91006867B6 /* SecTrust.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4C32C1990A497A0C002891BD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; 4C32C1A60A497A21002891BD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; - 4C3CECF31416E25C00947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */; }; - 4C3CECF41416E2EC00947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; - 4C3CECF51416E2FA00947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; - 4C3CECF61416E31A00947741 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; - 4C3CECF81416E33500947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; - 4C3CECF91416E34F00947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; - 4C3CECFB1416E34F00947741 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; - 4C3CECFC1416E34F00947741 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; - 4C3CECFD1416E35400947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; - 4C3CECFE1416E35400947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; - 4C3CECFF1416E35400947741 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; - 4C3CED001416E35400947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; - 4C3CED011416E35400947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; - 4C3CED031416E35400947741 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; - 4C3CED041416E35400947741 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; - 4C3CED051416E35A00947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; 4C3DD6B0179755560093F9D8 /* NSDate+TimeIntervalDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C3DD6AF179755560093F9D8 /* NSDate+TimeIntervalDescription.m */; }; 4C3DD6BD179760280093F9D8 /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; 4C4296320BB0A68200491999 /* SecTrustSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C4296300BB0A68200491999 /* SecTrustSettings.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4C47FA9320A51DC900384CB6 /* AppleFSCompression.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C47FA8D20A51DC700384CB6 /* AppleFSCompression.framework */; }; 4C47FA9420A51DD800384CB6 /* AppleFSCompression.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C47FA8D20A51DC700384CB6 /* AppleFSCompression.framework */; }; - 4C50AD0C1410679000EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - 4C50AD0D1410679000EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - 4C50AD0E1410679000EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - 4C50AD0F1410679000EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - 4C50AD101410679000EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - 4C50AD111410679000EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - 4C50AD121410679000EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - 4C50AD131410679000EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - 4C50AD141410679000EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - 4C50AD151410679000EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; - 4C50AD181410679900EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - 4C50AD191410679900EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - 4C50AD1A1410679900EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - 4C50AD1B1410679900EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - 4C50AD1C1410679900EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - 4C50AD1D1410679900EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - 4C50AD1E1410679900EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - 4C50AD1F1410679900EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - 4C50AD201410679900EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - 4C50AD211410679900EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; - 4C50AD221410679900EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */; }; - 4C50AD23141067A100EE92DE /* DigiNotarCA2007RootCertificate.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */; }; - 4C50AD24141067A100EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - 4C50AD25141067A100EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - 4C50AD26141067A100EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - 4C50AD27141067A100EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - 4C50AD28141067A100EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - 4C50AD29141067A100EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - 4C50AD2A141067A100EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - 4C50AD2B141067A100EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - 4C50AD2C141067A100EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - 4C50AD2D141067A100EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; - 4C50AD30141068C100EE92DE /* Expectations.plist in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD2F1410689300EE92DE /* Expectations.plist */; }; - 4C50AD3914106A4E00EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - 4C50AD3A14106A4E00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - 4C50AD3B14106A4E00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - 4C50AD3C14106A4E00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - 4C50AD3D14106A4E00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - 4C50AD3E14106A4E00EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - 4C50AD3F14106A4E00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - 4C50AD4014106A4E00EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - 4C50AD4114106A4E00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - 4C50AD4214106A4E00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; - 4C50AD4614106A5000EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - 4C50AD4714106A5000EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - 4C50AD4814106A5000EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - 4C50AD4914106A5000EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - 4C50AD4A14106A5000EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - 4C50AD4B14106A5000EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - 4C50AD4C14106A5000EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - 4C50AD4D14106A5000EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - 4C50AD4E14106A5000EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - 4C50AD4F14106A5000EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; - 4C50AD5014106A5000EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */; }; - 4C50AD5114106A5400EE92DE /* Expectations.plist in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD2F1410689300EE92DE /* Expectations.plist */; }; - 4C50AD5214106A5400EE92DE /* DigiNotarCA2007RootCertificate.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */; }; - 4C50AD5314106A5400EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - 4C50AD5414106A5400EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - 4C50AD5514106A5400EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - 4C50AD5614106A5400EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - 4C50AD5714106A5400EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - 4C50AD5814106A5400EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - 4C50AD5914106A5400EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - 4C50AD5A14106A5400EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - 4C50AD5B14106A5400EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - 4C50AD5C14106A5400EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; 4C52D0B516EFC61E0079966E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; 4C52D0BA16EFC61E0079966E /* CircleJoinRequested.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C52D0B916EFC61E0079966E /* CircleJoinRequested.m */; }; 4C52D0E716EFCCA20079966E /* Applicant.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C52D0E316EFCCA20079966E /* Applicant.m */; }; @@ -1603,33 +1563,10 @@ 4C7391790B01745000C4CBFA /* vmdh.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7391770B01745000C4CBFA /* vmdh.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4C7416040F1D71A2008E0E4D /* SecSCEP.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7416020F1D71A2008E0E4D /* SecSCEP.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4C7608B30AC34A8100980096 /* SecCertificatePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7608B10AC34A8100980096 /* SecCertificatePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4C7913251799A5CC00A9633E /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C7913241799A5CB00A9633E /* MobileCoreServices.framework */; }; 4C7CE5700DC7DC6600AE53FC /* SecEntitlements.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7CE56E0DC7DB0A00AE53FC /* SecEntitlements.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4C84DA551720698900AEE225 /* AppleAccount.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C84DA541720698900AEE225 /* AppleAccount.framework */; }; 4C87F3A80D611C26000E7104 /* SecTrustPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C87F3A70D611C26000E7104 /* SecTrustPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4C8A38C917B93DF10001B4C0 /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; - 4C8B91C61416EB8B00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - 4C8B91C71416EBA400A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - 4C8B91C81416EBB500A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - 4C8B91C91416ED7E00A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; - 4C8B91CA1416ED7E00A254E2 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; - 4C8B91CB1416ED7E00A254E2 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; - 4C8B91CC1416ED7E00A254E2 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; - 4C8B91CD1416ED7E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; - 4C8B91CF1416ED7E00A254E2 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; - 4C8B91D01416ED7E00A254E2 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; - 4C8B91D11416ED7E00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - 4C8B91D21416ED8E00A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; - 4C8B91D31416ED8E00A254E2 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; - 4C8B91D41416ED8E00A254E2 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; - 4C8B91D51416ED8E00A254E2 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; - 4C8B91D61416ED8E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; - 4C8B91D81416ED8E00A254E2 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; - 4C8B91D91416ED8E00A254E2 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; - 4C8B91DA1416ED8E00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - 4C8B91DB1416ED9400A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; - 4C8B91E31416ED9400A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - 4C8B91E41416ED9A00A254E2 /* DigiNotar_Root_CA_G2-RootCertificate.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */; }; 4C999BA60AB5F0BB0010451D /* NtlmGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C999BA20AB5F0BB0010451D /* NtlmGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4C999BA80AB5F0BB0010451D /* ntlmBlobPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C999BA40AB5F0BB0010451D /* ntlmBlobPriv.h */; }; 4C9DE9E31181AC8300CF5C27 /* sslEcdsa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9DE9E21181AC8300CF5C27 /* sslEcdsa.cpp */; }; @@ -1668,6 +1605,7 @@ 52A23EDD161DEC3F00E271E0 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52A23EDB161DEC3700E271E0 /* Default-568h@2x.png */; }; 52D82BDF16A621F70078DFE5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; 52D82BEE16A622370078DFE5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; + 52DA3C7123C7E63600FEEDFF /* KCTLKRequestTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DA3C6F23C7E63500FEEDFF /* KCTLKRequestTest.m */; }; 5328C0521738903F00708984 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; 533B5D4F177CD63100995334 /* SpringBoardServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52222CC0167BDAE100EDD09C /* SpringBoardServices.framework */; }; 5346480217331E1200FE9172 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; @@ -1678,18 +1616,12 @@ 5A04BAF822973E7F001848A0 /* OTFollowup.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A04BAF722973E43001848A0 /* OTFollowup.m */; }; 5A04BAFA22976A15001848A0 /* OTClique.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F336A20DD643B0031A92D /* OTClique.m */; }; 5A04BAFB22976A16001848A0 /* OTClique.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F336A20DD643B0031A92D /* OTClique.m */; }; - 5A04BB0222982733001848A0 /* OTFollowupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A04BAF922973EA9001848A0 /* OTFollowupTests.m */; }; 5A04BB1922986717001848A0 /* SecXPCHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A04BB182298670C001848A0 /* SecXPCHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5A04BB1A22986717001848A0 /* SecXPCHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A04BB182298670C001848A0 /* SecXPCHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5A06118E229ED5EB006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; 5A061191229ED6DB006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; - 5A061192229ED6E5006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; - 5A061193229ED6E6006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; 5A061194229ED6E7006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; - 5A061196229ED6E8006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; 5A061197229ED6EB006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; - 5A061198229ED8F3006AF14A /* NSDate+SFAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A061190229ED60C006AF14A /* NSDate+SFAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 5A061199229ED8F4006AF14A /* NSDate+SFAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A061190229ED60C006AF14A /* NSDate+SFAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5A0F84A522AEAF5B0097AEEA /* NSDate+SFAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A1A1C2122A71D2A00CB8D1D /* NSDate+SFAnalyticsTests.m */; }; 5A43A083225FA39C005450E4 /* SecProtocolHelperTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A43A07F225FA38D005450E4 /* SecProtocolHelperTest.m */; }; 5A43A084225FA3A5005450E4 /* SecProtocolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = AA44E0B3202E3451001EA371 /* SecProtocolTest.m */; }; @@ -1753,16 +1685,30 @@ 5F00F9592306147A00B832E0 /* SecImportExport.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E551D8085FC00865A7C /* SecImportExport.c */; }; 5F00F95B230614AC00B832E0 /* SecImportExportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F00F95A230614A200B832E0 /* SecImportExportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5F00F95C230614AD00B832E0 /* SecImportExportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F00F95A230614A200B832E0 /* SecImportExportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5F4C22002489C6AB00F0C425 /* simulatecrash_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F4C21FE2489C68900F0C425 /* simulatecrash_assert.h */; }; + 5F4C22012489C6AC00F0C425 /* simulatecrash_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F4C21FE2489C68900F0C425 /* simulatecrash_assert.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F84950222DFB505008B3EFB /* SecTrustExceptionResetCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F8494FF22DFB502008B3EFB /* SecTrustExceptionResetCount.m */; }; 6C02134E21F7ED25009D5C80 /* SecDbBackupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C02134D21F7ED16009D5C80 /* SecDbBackupTests.m */; }; - 6C02135021F7EF07009D5C80 /* SecDbBackupTests.plist in Copy BATS Test Discovery Plist */ = {isa = PBXBuildFile; fileRef = 6C02134C21F7ED16009D5C80 /* SecDbBackupTests.plist */; }; + 6C06CB902408602900025303 /* SecItemInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEDF7370F3A6CFB0027C4FE /* SecItemInternal.h */; }; + 6C06CB912408602A00025303 /* SecItemInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEDF7370F3A6CFB0027C4FE /* SecItemInternal.h */; }; 6C1260FD1F7DA42D001B2EEC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; 6C13AE471F8E9F5F00F047E3 /* supd.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69517E1F758E1000F68F91 /* supd.m */; }; 6C13AE481F8E9FC800F047E3 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 6C1520D41DCCF71400C85C6D /* secd.8 in Install man8 page */ = {isa = PBXBuildFile; fileRef = 6C1520CD1DCCF57A00C85C6D /* secd.8 */; }; + 6C16258723C4FFEC0086A0FF /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; + 6C16258823C5001C0086A0FF /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; 6C1F93111DD5E41A00585608 /* libDiagnosticMessagesClient.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3C1D78F25C002223DE /* libDiagnosticMessagesClient.dylib */; }; + 6C2045F12424BAC900F9461D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C99786D242362EC008C498D /* main.m */; }; + 6C2045F22424BACE00F9461D /* KeychainStasher.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C99786B242362EC008C498D /* KeychainStasher.m */; }; + 6C2045F42424BBCD00F9461D /* com.apple.security.KeychainStasher.sb in Install Sandbox Profile */ = {isa = PBXBuildFile; fileRef = 6C48D10F2423A3C0004AF950 /* com.apple.security.KeychainStasher.sb */; }; + 6C2045F52424BBDD00F9461D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C997879242364E5008C498D /* Foundation.framework */; }; + 6C2045FB2424BCD600F9461D /* com.apple.security.KeychainStasher.plist in Install LaunchAgent plist */ = {isa = PBXBuildFile; fileRef = 6C2045F92424BCB800F9461D /* com.apple.security.KeychainStasher.plist */; }; + 6C2138C4225183FE007DEDD3 /* SecDbKeychainSerializedMetadataKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */; }; + 6C220088244F075E000A4557 /* SecItemRateLimit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C513A38244F007B00207D5E /* SecItemRateLimit.m */; }; + 6C22008A244F0760000A4557 /* SecItemRateLimit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C513A38244F007B00207D5E /* SecItemRateLimit.m */; }; 6C23F02F227A3A28009F6756 /* com.apple.securityd.sb in Install Sandbox Profile */ = {isa = PBXBuildFile; fileRef = 6C23F02C227A39E9009F6756 /* com.apple.securityd.sb */; }; - 6C32BB9920EAE6B00042DF59 /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; }; + 6C2D463D24C88AA10015C3C9 /* LegacyAPICounts.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */; }; + 6C2D463E24C88AA60015C3C9 /* LegacyAPICounts.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */; }; 6C32D36420F2C23100ACAB2C /* TPPBPolicyRedaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C70D8DE20EBDFD700AB6FAF /* TPPBPolicyRedaction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6C32D36520F2C23D00ACAB2C /* TPPBPolicyDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C0C807420EAF81900334E33 /* TPPBPolicyDocument.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6C32D36620F2C23D00ACAB2C /* TPPBPolicyCategoriesByView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C0C809620EB024800334E33 /* TPPBPolicyCategoriesByView.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -1818,19 +1764,61 @@ 6C4AEF97218A12810012C5DA /* SecDbKeychainMetadataKeyStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF93218A124B0012C5DA /* SecDbKeychainMetadataKeyStore.m */; }; 6C4AEFA0218A189A0012C5DA /* SecAKSObjCWrappers.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF9D218A16F80012C5DA /* SecAKSObjCWrappers.m */; }; 6C4AEFA1218A189B0012C5DA /* SecAKSObjCWrappers.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF9D218A16F80012C5DA /* SecAKSObjCWrappers.m */; }; - 6C4F98252075833E00A3C5AB /* OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 6C53A44D206AB1EF000FA611 /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; }; 6C540C3922289A3B0032B5BC /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC4A76A92212698B006F2D8F /* CloudServices.framework */; }; 6C588D7F1EAA14AA00D7E322 /* RateLimiterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C588D791EAA149F00D7E322 /* RateLimiterTests.m */; }; 6C588D801EAA20AB00D7E322 /* RateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CC7F5B31E9F99EE0014AE63 /* RateLimiter.m */; }; 6C5B36BA1E2F9B95008AD443 /* WirelessDiagnostics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C3D1E2537C6007F95E5 /* WirelessDiagnostics.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 6C5B36C01E2F9BEA008AD443 /* WirelessDiagnostics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C3D1E2537C6007F95E5 /* WirelessDiagnostics.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 6C5D62A6221B6E3F00AF79DC /* secdxctests-entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6C5D62A5221B6E3F00AF79DC /* secdxctests-entitlements.plist */; }; + 6C61D3E9242A2C14008AB9BB /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; + 6C6AF17A221A06790091CE0A /* SecDbKeychainSerializedMetadataKey.proto in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF178221A03930091CE0A /* SecDbKeychainSerializedMetadataKey.proto */; }; + 6C6AF17F221A07090091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */; }; + 6C6AF180221A070A0091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */; }; + 6C6AF181221A070C0091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */; }; + 6C6AF182221A07230091CE0A /* SecDbKeychainSerializedMetadataKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */; }; + 6C6AF183221A07240091CE0A /* SecDbKeychainSerializedMetadataKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */; }; + 6C6B3AC623F1A820002827C2 /* KeychainEntitlementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */; }; + 6C6B3ADF23F1B3E0002827C2 /* KeychainAppClipTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C84E3C723ECBC84003C9710 /* KeychainAppClipTests.m */; }; 6C7094CC2239D21E00C5DAC6 /* SecDbBackupManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF8B218A0A400012C5DA /* SecDbBackupManager.m */; }; 6C73F48A2006B839003D5D63 /* SOSAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C7BB0032006B4EE004D1B6B /* SOSAnalytics.m */; }; 6C73F48B2006B83A003D5D63 /* SOSAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C7BB0032006B4EE004D1B6B /* SOSAnalytics.m */; }; 6C73F48D2006B83E003D5D63 /* SOSAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C7BB0032006B4EE004D1B6B /* SOSAnalytics.m */; }; 6C73F48F2006B910003D5D63 /* SOSAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C7BB0042006B4EF004D1B6B /* SOSAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6C73F4902006B911003D5D63 /* SOSAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C7BB0042006B4EF004D1B6B /* SOSAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 6C75560624212B4400025D78 /* keychainstasherinterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C755603242121F000025D78 /* keychainstasherinterface.m */; }; + 6C7BE2B823C3DD64003BB2CA /* SecurityTool.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA981D80CC2A00B0A59C /* SecurityTool.c */; }; + 6C7BE2B923C3DD64003BB2CA /* scep.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E231D8085FC00865A7C /* scep.c */; }; + 6C7BE2BA23C3DD64003BB2CA /* trust_update.m in Sources */ = {isa = PBXBuildFile; fileRef = D453C38A1FEC669300DE349B /* trust_update.m */; }; + 6C7BE2BB23C3DD64003BB2CA /* keychain_backup.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E211D8085FC00865A7C /* keychain_backup.c */; }; + 6C7BE2BC23C3DD64003BB2CA /* whoami.m in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA911D80CC2A00B0A59C /* whoami.m */; }; + 6C7BE2BE23C3DD64003BB2CA /* KeychainCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 473337831FDB29A200E19F30 /* KeychainCheck.m */; }; + 6C7BE2BF23C3DD64003BB2CA /* log_control.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1D1D8085FC00865A7C /* log_control.c */; }; + 6C7BE2C023C3DD64003BB2CA /* not_on_this_platorm.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCDB41D8C6A5B00070CB0 /* not_on_this_platorm.c */; }; + 6C7BE2C123C3DD64003BB2CA /* keychain_util.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1A1D8085FC00865A7C /* keychain_util.c */; }; + 6C7BE2C223C3DD64003BB2CA /* security_tool_commands.c in Sources */ = {isa = PBXBuildFile; fileRef = E7104A0B169E171900DB0045 /* security_tool_commands.c */; }; + 6C7BE2C323C3DD64003BB2CA /* codesign.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1E1D8085FC00865A7C /* codesign.c */; }; + 6C7BE2C523C3DD64003BB2CA /* NSFileHandle+Formatting.m in Sources */ = {isa = PBXBuildFile; fileRef = E78A9AD91D34959200006B5B /* NSFileHandle+Formatting.m */; }; + 6C7BE2C623C3DD64003BB2CA /* keychain_find.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E201D8085FC00865A7C /* keychain_find.m */; }; + 6C7BE2C723C3DD64003BB2CA /* readline.c in Sources */ = {isa = PBXBuildFile; fileRef = DC65E7BE1D8CBB1500152EF0 /* readline.c */; }; + 6C7BE2C823C3DD64003BB2CA /* add_internet_password.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1C1D8085FC00865A7C /* add_internet_password.c */; }; + 6C7BE2C923C3DD64003BB2CA /* digest_calc.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA8F1D80CC2A00B0A59C /* digest_calc.c */; }; + 6C7BE2CA23C3DD64003BB2CA /* leaks.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA931D80CC2A00B0A59C /* leaks.c */; }; + 6C7BE2CB23C3DD64003BB2CA /* show_certificates.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E251D8085FC00865A7C /* show_certificates.c */; }; + 6C7BE2CC23C3DD64003BB2CA /* spc.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E261D8085FC00865A7C /* spc.c */; }; + 6C7BE2CD23C3DD64003BB2CA /* verify_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E191D8085FC00865A7C /* verify_cert.c */; }; + 6C7BE2CE23C3DD64003BB2CA /* ct_exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = D4A3A596217A85CB00F0A8DA /* ct_exceptions.m */; }; + 6C7BE2CF23C3DD64003BB2CA /* keychain_add.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1F1D8085FC00865A7C /* keychain_add.c */; }; + 6C7BE2D023C3DD64003BB2CA /* pkcs12_util.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E221D8085FC00865A7C /* pkcs12_util.c */; }; + 6C7BE2D123C3DD64003BB2CA /* print_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA951D80CC2A00B0A59C /* print_cert.c */; }; + 6C7BE2D423C3DD64003BB2CA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; + 6C7BE2D723C3DD64003BB2CA /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; + 6C7BE2D823C3DD64003BB2CA /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + 6C7BE2D923C3DD64003BB2CA /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E43C48C1B00D07000E5ECB2 /* CoreFoundation.framework */; }; + 6C7BE2DC23C3DD64003BB2CA /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; }; + 6C7BE2DD23C3DD64003BB2CA /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; + 6C7BE2E023C3DD64003BB2CA /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 6C7BE2E323C3DD64003BB2CA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 6C7BE2EB23C3DDC3003BB2CA /* libsecurityd_bridge.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4718AEE2205B39C40068EC3F /* libsecurityd_bridge.a */; }; 6C7FD5DF1F87FA42002C2285 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; 6C814A4C2050B4B600CB391B /* LocalKeychainAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C814A4A2050B4B600CB391B /* LocalKeychainAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6C814A4D2050B4B600CB391B /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; }; @@ -1848,73 +1836,30 @@ 6C8CC3B61E2F98C2009025C5 /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C441E2537CC007F95E5 /* ProtocolBuffer.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 6C8CE6C11FA248DA0032ADF0 /* SFAnalyticsActivityTracker+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C8CE6BB1FA248B50032ADF0 /* SFAnalyticsActivityTracker+Internal.h */; }; 6C8CE6C21FA248DB0032ADF0 /* SFAnalyticsActivityTracker+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C8CE6BB1FA248B50032ADF0 /* SFAnalyticsActivityTracker+Internal.h */; }; - 6C8FF4B3224C1A8D00E5C812 /* TrustedPeers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BEF88C281EAFFC3F00357577 /* TrustedPeers.framework */; }; + 6C912AA0227A3E9600671FC6 /* CheckV12DevEnabled.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF83218A09210012C5DA /* CheckV12DevEnabled.m */; }; + 6C912AA1227A3E9700671FC6 /* CheckV12DevEnabled.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF83218A09210012C5DA /* CheckV12DevEnabled.m */; }; + 6C963284242A279B00C53CE2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C963283242A279B00C53CE2 /* main.m */; }; + 6C96328A242A284C00C53CE2 /* MobileKeyBag.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FC30AB1332DE9000802946 /* MobileKeyBag.framework */; }; + 6C97434824D1C8CB00A2025C /* LegacyAPICounts.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */; }; + 6C97434A24D1C8DE00A2025C /* LegacyAPICounts.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */; }; 6C9791C821C20CFF0074C609 /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; 6C9791C921C2EAB60074C609 /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; - 6C9791CA21C2EAB70074C609 /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; 6C9791CB21C325C30074C609 /* SecDbBackupRecoverySet.proto in Sources */ = {isa = PBXBuildFile; fileRef = 6CB6CC022198D4BC0080AD6F /* SecDbBackupRecoverySet.proto */; }; - 6C98083E1E788AEB00E70590 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; - 6C98084A1E788AEB00E70590 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; - 6C98084D1E788AEB00E70590 /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; - 6C98084E1E788AEB00E70590 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - 6C98084F1E788AEB00E70590 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; - 6C9808501E788AEB00E70590 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; - 6C9808511E788AEB00E70590 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; - 6C9808521E788AEB00E70590 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; - 6C9808531E788AEB00E70590 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; - 6C9808541E788AEB00E70590 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; }; - 6C9808551E788AEB00E70590 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; - 6C9808561E788AEB00E70590 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3A1D78F228002223DE /* libACM.a */; }; - 6C9808571E788AEB00E70590 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; }; - 6C9808581E788AEB00E70590 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; - 6C9808591E788AEB00E70590 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; }; - 6C98085A1E788AEB00E70590 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; }; - 6C98085B1E788AEB00E70590 /* libsqlite3.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC27B57D1DDFC24500599261 /* libsqlite3.0.dylib */; }; - 6C98085C1E788AEB00E70590 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; }; - 6C98087A1E788AFD00E70590 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; - 6C9808861E788AFD00E70590 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; - 6C9808891E788AFD00E70590 /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; - 6C98088A1E788AFD00E70590 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - 6C98088B1E788AFD00E70590 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; - 6C98088C1E788AFD00E70590 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; - 6C98088D1E788AFD00E70590 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; - 6C98088E1E788AFD00E70590 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; - 6C98088F1E788AFD00E70590 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; - 6C9808901E788AFD00E70590 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; }; - 6C9808911E788AFD00E70590 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; - 6C9808921E788AFD00E70590 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3A1D78F228002223DE /* libACM.a */; }; - 6C9808931E788AFD00E70590 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; }; - 6C9808941E788AFD00E70590 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; - 6C9808951E788AFD00E70590 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; }; - 6C9808961E788AFD00E70590 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; }; - 6C9808971E788AFD00E70590 /* libsqlite3.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC27B57D1DDFC24500599261 /* libsqlite3.0.dylib */; }; - 6C9808981E788AFD00E70590 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; }; - 6C9808A51E788CD100E70590 /* CKKSCloudKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CCDF7911E3C2D69003F2555 /* CKKSCloudKitTests.m */; }; - 6C9808A61E788CD200E70590 /* CKKSCloudKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CCDF7911E3C2D69003F2555 /* CKKSCloudKitTests.m */; }; 6C9AA7A11F7C1D9000D08296 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C9AA7A01F7C1D9000D08296 /* main.m */; }; 6C9AA7A51F7C6F7F00D08296 /* SecArgParse.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5BCC461E5380EA00649140 /* SecArgParse.c */; }; 6CA837642210CA8A002770F1 /* kc-45-change-password.c in Sources */ = {isa = PBXBuildFile; fileRef = 6CA837612210C5E7002770F1 /* kc-45-change-password.c */; }; - 6CAA8CDD1F82EDEF007B6E03 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; - 6CAA8CEE1F83E417007B6E03 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; - 6CAA8CEF1F83E65D007B6E03 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; - 6CAA8CF01F83E65E007B6E03 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; - 6CAA8CF61F83E79D007B6E03 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; - 6CAA8CF71F83E79E007B6E03 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; - 6CAA8CF81F83E7A9007B6E03 /* SFAnalyticsSQLiteStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */; }; - 6CAA8CF91F83E7AA007B6E03 /* SFAnalyticsSQLiteStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */; }; + 6CA9690A24ACC2D100C08B5E /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 6CAA8CFC1F83E7EA007B6E03 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; 6CAA8CFD1F83E7EB007B6E03 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; 6CAA8CFE1F83E800007B6E03 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; 6CAA8CFF1F83E800007B6E03 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; - 6CAA8D0D1F83EC57007B6E03 /* SFSQLiteStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BF1F152EB10082882F /* SFSQLiteStatement.m */; }; - 6CAA8D131F83ECD4007B6E03 /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; - 6CAA8D141F83ECD5007B6E03 /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; 6CAA8D271F843002007B6E03 /* supd.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69517E1F758E1000F68F91 /* supd.m */; }; 6CAA8D351F84306C007B6E03 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6951801F758E1000F68F91 /* main.m */; }; 6CAA8D371F843196007B6E03 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; 6CAA8D3A1F8431A7007B6E03 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 6CAA8D3B1F8431AE007B6E03 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40B6A881E2B5F9900CD6EE5 /* Foundation.framework */; }; 6CAB39C71E521BEA00566A79 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 6CB0C5F824ACDB5300479FB4 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; 6CB420A52051FDD500FF2D44 /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; }; 6CB420AB2051FDE000FF2D44 /* LocalKeychainAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C814A4A2050B4B600CB391B /* LocalKeychainAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CB5F47B1E402E6700DBF3F0 /* KeychainEntitledTestRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CB5F47A1E402E5700DBF3F0 /* KeychainEntitledTestRunner.m */; }; @@ -1927,8 +1872,6 @@ 6CBF65401FA1480C00A68667 /* SFAnalyticsActivityTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CBF65371FA147E500A68667 /* SFAnalyticsActivityTracker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CBF65411FA1481100A68667 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; 6CBF65421FA2255800A68667 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; - 6CBF65431FA2257100A68667 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; - 6CBF65441FA2257200A68667 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; 6CC1859E1E24E8EB009657D8 /* CKKSRateLimiter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CC185971E24E87D009657D8 /* CKKSRateLimiter.h */; }; 6CC1859F1E24E8EB009657D8 /* CKKSRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CC185981E24E87D009657D8 /* CKKSRateLimiter.m */; }; 6CC952481FB4CB2C0051A823 /* SFAnalytics+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CC952421FB4C5CA0051A823 /* SFAnalytics+Internal.h */; }; @@ -1936,10 +1879,10 @@ 6CCDF78C1E3C26BC003F2555 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CCDF78B1E3C26BC003F2555 /* XCTest.framework */; }; 6CCDF78D1E3C26C2003F2555 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40B6A881E2B5F9900CD6EE5 /* Foundation.framework */; }; 6CD1DBED21F9281D00D158FB /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; + 6CD224E623949132001B70FD /* SecDbBackupTestsBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6579FC2394878700701C8B /* SecDbBackupTestsBase.m */; }; + 6CD8412C23F5D871003DDF34 /* KeychainBackupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CD8412B23F5D871003DDF34 /* KeychainBackupTests.m */; }; 6CDB5FF51FA78D1A00410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; 6CDB5FF61FA78D1B00410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; - 6CDB5FF81FA78D2300410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; - 6CDB5FF91FA78D2400410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; 6CDB5FFA1FA78D2500410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; 6CDB5FFB1FA78D2C00410924 /* SFAnalyticsMultiSampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CDB5FF41FA78CB500410924 /* SFAnalyticsMultiSampler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CDB5FFC1FA78D2D00410924 /* SFAnalyticsMultiSampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CDB5FF41FA78CB500410924 /* SFAnalyticsMultiSampler.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -1947,12 +1890,9 @@ 6CDB60111FA9386200410924 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; 6CDB601A1FA93A1800410924 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CB96BB41F966E0C00E11457 /* libsqlite3.tbd */; }; 6CDB601B1FA93A2000410924 /* libprequelite.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CFDC4561F907E1D00646DBB /* libprequelite.tbd */; }; - 6CDF8DEF1F96495600140B54 /* SFAnalyticsSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */; }; - 6CDF8DF01F96495700140B54 /* SFAnalyticsSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */; }; 6CDF8DF21F9649AB00140B54 /* SFAnalyticsSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */; }; 6CDF8DF31F9649C000140B54 /* SFAnalyticsSQLiteStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */; }; 6CDF8DF41F9649C000140B54 /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; - 6CE22D701E49206600974785 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CE22D6F1E49206600974785 /* UIKit.framework */; }; 6CE3654B1FA100D00012F6AB /* SFAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 4723C9DA1F1540CE0082882F /* SFAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CE3654C1FA100D10012F6AB /* SFAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 4723C9DA1F1540CE0082882F /* SFAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CE3654D1FA100E50012F6AB /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; @@ -1970,9 +1910,6 @@ 6CF4A0B81E45488B00ECD7B5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0B71E45488B00ECD7B5 /* AppDelegate.m */; }; 6CF4A0BB1E45488B00ECD7B5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0BA1E45488B00ECD7B5 /* main.m */; }; 6CF4A0BE1E45488B00ECD7B5 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0BD1E45488B00ECD7B5 /* ViewController.m */; }; - 6CF4A0E41E4549F200ECD7B5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0E31E4549F200ECD7B5 /* main.m */; }; - 6CF4A0E71E4549F300ECD7B5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0E61E4549F300ECD7B5 /* AppDelegate.m */; }; - 6CF4A0EA1E4549F300ECD7B5 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0E91E4549F300ECD7B5 /* ViewController.m */; }; 7200D76F177B9999009BB396 /* ManagedConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72C3EC2D1705F24E0040C87C /* ManagedConfiguration.framework */; }; 7281E0871DFD01800021E1B7 /* SOSAccountGetSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7281E0861DFD015A0021E1B7 /* SOSAccountGetSet.m */; }; 7281E08D1DFD0B520021E1B7 /* XPCNotificationDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = E7C787331DD0FED50087FC34 /* XPCNotificationDispatcher.m */; }; @@ -1993,22 +1930,35 @@ 7913B2080D172B3900601FE9 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; 791766DE0DD0162C00F3B974 /* SecCertificateRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 791766DD0DD0162C00F3B974 /* SecCertificateRequest.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7940D4130C3ACF9000FDB5D8 /* SecDH.h in Headers */ = {isa = PBXBuildFile; fileRef = 7940D4110C3ACF9000FDB5D8 /* SecDH.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 7947431A146213DC00D638A3 /* Invalid-www.cybersecurity.my.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */; }; - 7947431B146213EF00D638A3 /* Invalid-www.cybersecurity.my.crt in Copy DigicertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */; }; - 7947431D1462151400D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in Copy DigicertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */; }; - 7947431E1462151E00D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */; }; 795CA9CE0D38435E00BAE6A2 /* p12pbegen.h in Headers */ = {isa = PBXBuildFile; fileRef = 795CA9CC0D38435E00BAE6A2 /* p12pbegen.h */; }; - 79679E29146202A800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */; }; - 79679E2A146202A800CF997F /* Invalid-webmail.jaring.my.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */; }; - 79679E2C146202CB00CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in Copy DigicertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */; }; - 79679E2D146202CB00CF997F /* Invalid-webmail.jaring.my.crt in Copy DigicertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */; }; 79EF5B6E0D3D6A31009F5270 /* SecImportExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5B6C0D3D6A31009F5270 /* SecImportExport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 79EF5B730D3D6AFE009F5270 /* p12import.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5B720D3D6AFE009F5270 /* p12import.h */; }; 8E02FA6B1107BE460043545E /* pbkdf2.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E02FA691107BE460043545E /* pbkdf2.h */; settings = {ATTRIBUTES = (Private, ); }; }; 8ED6F6CA110904E300D2B368 /* SecPBKDF.h in Headers */ = {isa = PBXBuildFile; fileRef = 8ED6F6C8110904E300D2B368 /* SecPBKDF.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A640B71D25CB75820098A4A4 /* libxar.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789201D7799A100B50D50 /* libxar.dylib */; }; + A640B71F25CB8A030098A4A4 /* secstaticcode_integration.m in Sources */ = {isa = PBXBuildFile; fileRef = A640B71E25CB8A030098A4A4 /* secstaticcode_integration.m */; }; + A640B72425CB99EB0098A4A4 /* seccode.c in Sources */ = {isa = PBXBuildFile; fileRef = 3E88361324F0699F00E9F4D6 /* seccode.c */; }; A690B033208A75D1002FB775 /* notarization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A6B1BA78207BD9D400F1E099 /* notarization.cpp */; }; + A695615C2580A0F500BDF83F /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A695615A2580A0F500BDF83F /* libsecurity_codesigning.a */; }; + A695623C2580AB7900BDF83F /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A695623B2580AB7800BDF83F /* libsecurity_utilities.a */; }; + A695623D2580AB7E00BDF83F /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EB49B2DC202DF251003F34A0 /* libbsm.tbd */; }; + A695631D2580AB8A00BDF83F /* libsecurity_cdsa_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A695631C2580AB8A00BDF83F /* libsecurity_cdsa_utilities.a */; }; + A69563FC2580ABA200BDF83F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CB96BB41F966E0C00E11457 /* libsqlite3.tbd */; }; + A69564DB2580ABAC00BDF83F /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + A69565BB2580ABBC00BDF83F /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A69565BA2580ABBC00BDF83F /* libDER.a */; }; + A69565BC2580ABD900BDF83F /* AppleFSCompression.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C47FA8D20A51DC700384CB6 /* AppleFSCompression.framework */; }; + A695677D2581B47F00BDF83F /* unsigned_secstaticcodeapitest.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = A695677A2581B46000BDF83F /* unsigned_secstaticcodeapitest.sh */; }; A6B1BA81207BD9EC00F1E099 /* notarization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A6B1BA78207BD9D400F1E099 /* notarization.cpp */; }; A6B1BA82207BDCB200F1E099 /* notarization.h in Headers */ = {isa = PBXBuildFile; fileRef = A6B1BA79207BD9D400F1E099 /* notarization.h */; }; + A6BC648824897C5E00A21CD7 /* CSCommonPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787441D7790A500B50D50 /* CSCommonPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A6BC6491248B0AB400A21CD7 /* SecStaticCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17874C1D7790A500B50D50 /* SecStaticCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A6BF3B3623EB95F0009AF079 /* entitlements.h in Headers */ = {isa = PBXBuildFile; fileRef = A6BF3B3123EB94A7009AF079 /* entitlements.h */; }; + A6C737B923F37A480009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737BA23F37A4B0009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737BB23F37AB00009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737BD23F37AB20009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737C023F37AB90009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737C123F37AC00009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; AA0DA47A21E818AB009F1C74 /* builtins.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = AA0DA47921E8189E009F1C74 /* builtins.json */; }; AA0DA47B21E818AB009F1C74 /* example1.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = AA0DA47821E8189D009F1C74 /* example1.json */; }; AA0DA47D21E818D2009F1C74 /* builtins.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = AA0DA47921E8189E009F1C74 /* builtins.json */; }; @@ -2044,12 +1994,14 @@ BE197F5B1911723E00BA91D1 /* SpringBoardUIServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE197F5A1911723E00BA91D1 /* SpringBoardUIServices.framework */; }; BE197F5C1911724900BA91D1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE411314471B000DE34E /* UIKit.framework */; }; BE197F5E191173A800BA91D1 /* SWCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE197F5D191173A800BA91D1 /* SWCViewController.m */; }; - BE197F61191173F200BA91D1 /* entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = BE197F60191173F200BA91D1 /* entitlements.plist */; }; BE22FBC61EE0E8AB00893431 /* Monkey.m in Sources */ = {isa = PBXBuildFile; fileRef = BE22FBC51EE0E8AB00893431 /* Monkey.m */; }; BE22FBCE1EE1E26600893431 /* Keychain.m in Sources */ = {isa = PBXBuildFile; fileRef = BE22FBCD1EE1E26600893431 /* Keychain.m */; }; BE22FBD11EE2084100893431 /* Config.m in Sources */ = {isa = PBXBuildFile; fileRef = BE22FBD01EE2084100893431 /* Config.m */; }; BE22FC041EE3584400893431 /* mark.m in Sources */ = {isa = PBXBuildFile; fileRef = BE22FBFC1EE23D9100893431 /* mark.m */; }; BE25C41618B83491003320E0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + BE26081825620B1A0057C489 /* SecXPCUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = BE26081625620B190057C489 /* SecXPCUtils.m */; }; + BE2609D425620B2C0057C489 /* SecXPCUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = BE2609D325620B2C0057C489 /* SecXPCUtils.h */; }; + BE2609D525620B2C0057C489 /* SecXPCUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = BE2609D325620B2C0057C489 /* SecXPCUtils.h */; }; BE405EE21DC2F10E00E227B1 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; }; BE405EE31DC2F11E00E227B1 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; }; BE442BAE18B7FDB800F24DAE /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; @@ -2066,7 +2018,6 @@ BE536019209BB76B0027E25A /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA311DEE768000D0F733 /* CloudKit.framework */; }; BE53601A209BB7F80027E25A /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; BE53601B209BB8390027E25A /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - BE53601C209BB8970027E25A /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; BE53602D209BBF630027E25A /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; BE536030209BC1FD0027E25A /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; BE536031209BC2F90027E25A /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; @@ -2075,8 +2026,10 @@ BE536034209BC3C40027E25A /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; BE55C77C2044D0C90045863D /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE55C77B2044D0C90045863D /* Client.swift */; }; BE55C77E2044D7E60045863D /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE55C77D2044D7E60045863D /* main.swift */; }; + BE57B1182509E1000045B7FD /* ca_revocation_additions.m in Sources */ = {isa = PBXBuildFile; fileRef = BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */; }; + BE57B1192509E1000045B7FD /* ca_revocation_additions.m in Sources */ = {isa = PBXBuildFile; fileRef = BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */; }; + BE57B11A2509E1000045B7FD /* ca_revocation_additions.m in Sources */ = {isa = PBXBuildFile; fileRef = BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */; }; BE61F5AF1EB0060C00556CCF /* TrustedPeers.h in Headers */ = {isa = PBXBuildFile; fileRef = BEF88C641EB0005F00357577 /* TrustedPeers.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BE6215BE1DB6E69100961E15 /* si-84-sectrust-allowlist.m in Sources */ = {isa = PBXBuildFile; fileRef = BE6215BD1DB6E69100961E15 /* si-84-sectrust-allowlist.m */; }; BE64A7FA22AF006F001209F3 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 474B5FBF1E662E21007546F8 /* SecurityFoundation.framework */; }; BE64A7FC22AF008D001209F3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D848541C6C1D9C0025BB44 /* Foundation.framework */; }; BE64A80022AF010B001209F3 /* trusted_cert_ssl.m in Sources */ = {isa = PBXBuildFile; fileRef = BE64A7FE22AF010A001209F3 /* trusted_cert_ssl.m */; }; @@ -2085,12 +2038,11 @@ BE72782B209D27C800F0DA77 /* TPKeyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BE72782A209D27C800F0DA77 /* TPKeyTests.m */; }; BE72782C209D2C1400F0DA77 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; BE759DCB1917E38D00801E02 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE451314471B000DE34E /* CoreGraphics.framework */; }; + BE7B8E132415579900E1CF4F /* SecSharedCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = BE7B8E112415579800E1CF4F /* SecSharedCredential.m */; }; + BE7B8E142415579900E1CF4F /* SecSharedCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = BE7B8E112415579800E1CF4F /* SecSharedCredential.m */; }; + BE7B8E152415580D00E1CF4F /* SecSharedCredential.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E8C1D8085FC00865A7C /* SecSharedCredential.c */; }; BE8ABDD81DC2DD9100EC2D58 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; }; BE92249E204F203C0052E828 /* TrustedPeersHelper.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = BE92249C204F203C0052E828 /* TrustedPeersHelper.xcdatamodeld */; }; - BE9B8B4A202BB4A20081EF87 /* si-88-sectrust-valid.m in Sources */ = {isa = PBXBuildFile; fileRef = BE9B8B49202BB4A10081EF87 /* si-88-sectrust-valid.m */; }; - BE9B8B4B202BB4D10081EF87 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */; }; - BE9B8B4C202BB4E30081EF87 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */; }; - BE9B8B4D202BB4F30081EF87 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */; }; BE9F4F8C2072D881004A52C2 /* Cuttlefish.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F4F8B2072D881004A52C2 /* Cuttlefish.pb.swift */; }; BE9F8D10206C099800B53D16 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F8D0F206C099800B53D16 /* Container.swift */; }; BE9F8D12206C121400B53D16 /* Decrypter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F8D11206C121400B53D16 /* Decrypter.swift */; }; @@ -2100,7 +2052,7 @@ BEAA0046202B785000E51F45 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; BEB0B06E1FE9E81D007E6A83 /* TPPBPeerDynamicInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089CF1FA3BA01001ACC20 /* TPPBPeerDynamicInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; BEB0B06F1FE9E850007E6A83 /* TPPBPeerPermanentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089DD1FA40B93001ACC20 /* TPPBPeerPermanentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BEB0B0701FE9E8F6007E6A83 /* TPPBPeerStableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089D41FA3BA04001ACC20 /* TPPBPeerStableInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BEB0B0701FE9E8F6007E6A83 /* TPPBPeerStableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089D41FA3BA04001ACC20 /* TPPBPeerStableInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; BEB0B0711FE9E936007E6A83 /* TPPBPolicySecret.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089D31FA3BA03001ACC20 /* TPPBPolicySecret.h */; settings = {ATTRIBUTES = (Private, ); }; }; BEB49F30206E98D0008DA7F4 /* TPECPublicKeyFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB49F29206E98CD008DA7F4 /* TPECPublicKeyFactory.h */; settings = {ATTRIBUTES = (Private, ); }; }; BEB49F31206E98D0008DA7F4 /* TPECPublicKeyFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = BEB49F2F206E98CE008DA7F4 /* TPECPublicKeyFactory.m */; }; @@ -2124,9 +2076,10 @@ BECFA43B20F91CE500B11002 /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C441E2537CC007F95E5 /* ProtocolBuffer.framework */; }; BECFA43D20F9493000B11002 /* Policy.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECFA43C20F9493000B11002 /* Policy.swift */; }; BECFA43E20F9493000B11002 /* Policy.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECFA43C20F9493000B11002 /* Policy.swift */; }; - BECFA44320FD0A4B00B11002 /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; }; BECFA45920FEB90900B11002 /* Policy.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECFA43C20F9493000B11002 /* Policy.swift */; }; BECFA46420FFB87500B11002 /* TPKey.m in Sources */ = {isa = PBXBuildFile; fileRef = BECFA46320FFB87400B11002 /* TPKey.m */; }; + BED07AAC2542A2CC00FED203 /* CARevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BED078F82542A2BF00FED203 /* CARevocationTests.m */; }; + BED07B862542A2CE00FED203 /* CARevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BED078F82542A2BF00FED203 /* CARevocationTests.m */; }; BED208D81EDF950E00753952 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; BED208D91EDF950E00753952 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; BED208E81EDF974500753952 /* manifeststresstest.m in Sources */ = {isa = PBXBuildFile; fileRef = BED208E71EDF971600753952 /* manifeststresstest.m */; }; @@ -2137,6 +2090,7 @@ BED987E020991B1100607A5F /* TrustedPeersHelper.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = BE92249C204F203C0052E828 /* TrustedPeersHelper.xcdatamodeld */; }; BED987E120991B9B00607A5F /* Decrypter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F8D11206C121400B53D16 /* Decrypter.swift */; }; BED987E320991C4D00607A5F /* MockCuttlefish.swift in Sources */ = {isa = PBXBuildFile; fileRef = BED987E220991C4D00607A5F /* MockCuttlefish.swift */; }; + BEE2954325818E0400CD1294 /* si-40-identity-tests.m in Sources */ = {isa = PBXBuildFile; fileRef = BEE2954125818E0300CD1294 /* si-40-identity-tests.m */; }; BEE523D91DACAA2500DD0AA3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789221D7799A600B50D50 /* libz.dylib */; }; BEE523DC1DACAA9200DD0AA3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789221D7799A600B50D50 /* libz.dylib */; }; BEEB47D91EA189F5004AA5C6 /* SecTrustStatusCodes.c in Sources */ = {isa = PBXBuildFile; fileRef = BEEB47D71EA189F5004AA5C6 /* SecTrustStatusCodes.c */; }; @@ -2183,11 +2137,15 @@ CD9F2AFA1DF249CF00AD3577 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; CDB9FCAB179CD098000AAD66 /* Info.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = CDB9FCA9179CC757000AAD66 /* Info.plist */; }; CDDE9BD11729ABFA0013B0E8 /* SecPasswordGenerate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDE9BC31729AB910013B0E8 /* SecPasswordGenerate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D401443725789030008BAE33 /* TrustURLSessionCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D401443625789030008BAE33 /* TrustURLSessionCache.m */; }; D401E8B420A26F1F00CD8BB4 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; }; D4056A1A22712A650026E24E /* SSLPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4056A1922712A650026E24E /* SSLPolicyTests.m */; }; D4056A1B22712A650026E24E /* SSLPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4056A1922712A650026E24E /* SSLPolicyTests.m */; }; D4056A1F22712D750026E24E /* ssl-policy-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4056A1D22712D740026E24E /* ssl-policy-certs */; }; D4056A2022712D750026E24E /* ssl-policy-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4056A1D22712D740026E24E /* ssl-policy-certs */; }; + D40724E725310F3B0084D96B /* PinningDbTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D407225A25310BC20084D96B /* PinningDbTests.m */; }; + D40725C225310F3D0084D96B /* PinningDbTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D407225A25310BC20084D96B /* PinningDbTests.m */; }; + D407292A2531387F0084D96B /* TestTrustdInitialization-data in Resources */ = {isa = PBXBuildFile; fileRef = D4072929253138730084D96B /* TestTrustdInitialization-data */; }; D40881EF2175731E00180E81 /* SecTrust.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E901D8085FC00865A7C /* SecTrust.c */; }; D40881F02175732600180E81 /* SecTrustStore.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E971D8085FC00865A7C /* SecTrustStore.c */; }; D40881F12175732E00180E81 /* SecCertificate.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E381D8085FC00865A7C /* SecCertificate.c */; }; @@ -2214,7 +2172,6 @@ D40B6A991E2B68A400CD6EE5 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; }; D40B6A9A1E2B68E800CD6EE5 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; D40B6A9B1E2B690E00CD6EE5 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E9A1D8085FC00865A7C /* SecuritydXPC.c */; }; - D40B6A9D1E2B6A2700CD6EE5 /* login.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E8271D7A4F0E00AFB96E /* login.framework */; }; D40B6A9E1E2B6A6F00CD6EE5 /* libtrustd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D4ADA3191E2B41670031CEA3 /* libtrustd.a */; }; D40B7CA021605BF800AC9A75 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; settings = {ATTRIBUTES = (Required, ); }; }; D4119E78202BDF490048587B /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; @@ -2230,9 +2187,17 @@ D41257E21E94138600781F23 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E43C48C1B00D07000E5ECB2 /* CoreFoundation.framework */; }; D41257EF1E941E4E00781F23 /* com.apple.trustd.plist in Copy LaunchDaemon */ = {isa = PBXBuildFile; fileRef = D41257EE1E941DA800781F23 /* com.apple.trustd.plist */; }; D41258011E94230400781F23 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + D41321822549E49B0062995A /* DigicertMalaysia in Resources */ = {isa = PBXBuildFile; fileRef = D41321802549E49A0062995A /* DigicertMalaysia */; }; + D413225D2549E4AF0062995A /* DigicertMalaysia in Resources */ = {isa = PBXBuildFile; fileRef = D41321802549E49A0062995A /* DigicertMalaysia */; }; + D41324132549E55C0062995A /* DigiNotar in Resources */ = {isa = PBXBuildFile; fileRef = D41324122549E55B0062995A /* DigiNotar */; }; + D41324EE2549E56F0062995A /* DigiNotar in Resources */ = {isa = PBXBuildFile; fileRef = D41324122549E55B0062995A /* DigiNotar */; }; D418CC701E690CAD00330A44 /* MobileAsset.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7273402816CAFB3C0096622A /* MobileAsset.framework */; }; D418CC711E690CBC00330A44 /* MobileAsset.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7273402816CAFB3C0096622A /* MobileAsset.framework */; }; D41D36711EB14D87007FA978 /* libDiagnosticMessagesClient.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41D36701EB14D87007FA978 /* libDiagnosticMessagesClient.tbd */; }; + D423114323725F9F000E470A /* SMIMEPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D423114223725F9F000E470A /* SMIMEPolicyTests.m */; }; + D423114423725F9F000E470A /* SMIMEPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D423114223725F9F000E470A /* SMIMEPolicyTests.m */; }; + D4231148237261F8000E470A /* SMIMEPolicyTests-data in Resources */ = {isa = PBXBuildFile; fileRef = D4231147237261F7000E470A /* SMIMEPolicyTests-data */; }; + D4231149237261F8000E470A /* SMIMEPolicyTests-data in Resources */ = {isa = PBXBuildFile; fileRef = D4231147237261F7000E470A /* SMIMEPolicyTests-data */; }; D425EC1D1DD3C3CF00DE5DEC /* SecInternalRelease.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC761D8C68CF00070CB0 /* SecInternalRelease.c */; }; D425EC231DD3FFF200DE5DEC /* SecInternalRelease.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC761D8C68CF00070CB0 /* SecInternalRelease.c */; }; D4267BD123440F8900B54678 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; @@ -2251,6 +2216,11 @@ D42C839E21159170008D3D83 /* CMSDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D42C8390211590BC008D3D83 /* CMSDecoder.cpp */; }; D42C839F211593D8008D3D83 /* libsecurity_cms.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D42C839821159146008D3D83 /* libsecurity_cms.a */; }; D42CDC351DC12FE90090E2C9 /* si-66-smime.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DEB1D8085FC00865A7C /* si-66-smime.c */; }; + D43534FE2525033E002E72F7 /* trustdFileLocations.h in Headers */ = {isa = PBXBuildFile; fileRef = D43534FC2525033E002E72F7 /* trustdFileLocations.h */; }; + D43534FF2525033E002E72F7 /* trustdFileLocations.m in Sources */ = {isa = PBXBuildFile; fileRef = D43534FD2525033E002E72F7 /* trustdFileLocations.m */; }; + D43539E42526BE5B002E72F7 /* trust_config.m in Sources */ = {isa = PBXBuildFile; fileRef = D43538302526BB01002E72F7 /* trust_config.m */; }; + D4353ABE2526BE5C002E72F7 /* trust_config.m in Sources */ = {isa = PBXBuildFile; fileRef = D43538302526BB01002E72F7 /* trust_config.m */; }; + D4353ABF2526BE5D002E72F7 /* trust_config.m in Sources */ = {isa = PBXBuildFile; fileRef = D43538302526BB01002E72F7 /* trust_config.m */; }; D437185F211671A500EA350A /* cms-01-basic.c in Sources */ = {isa = PBXBuildFile; fileRef = D437185C211671A300EA350A /* cms-01-basic.c */; }; D4371860211671A500EA350A /* smime-cms-test.c in Sources */ = {isa = PBXBuildFile; fileRef = D437185D211671A400EA350A /* smime-cms-test.c */; }; D4371861211671A500EA350A /* cms-01-basic.h in Headers */ = {isa = PBXBuildFile; fileRef = D437185E211671A400EA350A /* cms-01-basic.h */; }; @@ -2329,6 +2299,11 @@ D442830022D68564001746B3 /* TrustEvaluationTestHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = D44282FE22D68556001746B3 /* TrustEvaluationTestHelpers.m */; }; D4428B342122604300EB8448 /* SecFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0B906C0ACCBD240077CD03 /* SecFramework.h */; settings = {ATTRIBUTES = (Private, ); }; }; D4428B36212262F800EB8448 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; + D445B853258C10E50019858E /* trustdFileHelper.8 in Install man8 page */ = {isa = PBXBuildFile; fileRef = D445B692258C08B10019858E /* trustdFileHelper.8 */; }; + D445BA13258C11230019858E /* com.apple.trustdFileHelper.sb in Copy Sandbox */ = {isa = PBXBuildFile; fileRef = D445B772258C08CC0019858E /* com.apple.trustdFileHelper.sb */; }; + D445BAF4258C114F0019858E /* com.apple.trustdFileHelper.plist in Copy LaunchDaemon Files */ = {isa = PBXBuildFile; fileRef = D445B691258C088B0019858E /* com.apple.trustdFileHelper.plist */; }; + D445C2D2258C14AB0019858E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + D445C2D3258C14BC0019858E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; D447C4101D3094740082FC1D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; D44D1F6F2115899C00E76E1A /* CMSUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = D4CF6E762115886D0014647E /* CMSUtils.c */; }; D44D1F70211589AC00E76E1A /* CMSDecoder.c in Sources */ = {isa = PBXBuildFile; fileRef = D4CF6E68211588680014647E /* CMSDecoder.c */; }; @@ -2385,10 +2360,7 @@ D458C512214E20850043D982 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D458C511214E20840043D982 /* XCTest.framework */; }; D458C515214E286C0043D982 /* PolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D458C513214E27620043D982 /* PolicyTests.m */; }; D458C516214E286D0043D982 /* PolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D458C513214E27620043D982 /* PolicyTests.m */; }; - D458C517214E2C690043D982 /* si-20-sectrust-policies-data in Resources */ = {isa = PBXBuildFile; fileRef = D4EC94FA1CEA482D0083E753 /* si-20-sectrust-policies-data */; }; - D458C51A214E2CC80043D982 /* si-20-sectrust-policies-data in Resources */ = {isa = PBXBuildFile; fileRef = D4EC94FA1CEA482D0083E753 /* si-20-sectrust-policies-data */; }; D458C51C214E2DEB0043D982 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D458C4C5214E1A400043D982 /* Assets.xcassets */; }; - D458C51D214E2DEB0043D982 /* Base.lproj in Resources */ = {isa = PBXBuildFile; fileRef = D458C4C7214E1A400043D982 /* Base.lproj */; }; D458C51F214E2E0C0043D982 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D458C51E214E2E0C0043D982 /* Main.storyboard */; }; D458C520214E33260043D982 /* ECTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5766214E195300A32C01 /* ECTests.m */; }; D458C521214E33260043D982 /* ECTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5766214E195300A32C01 /* ECTests.m */; }; @@ -2396,7 +2368,14 @@ D458C523214E33380043D982 /* KeySizeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5768214E195400A32C01 /* KeySizeTests.m */; }; D458C524214E33430043D982 /* VerifyDateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5764214E195200A32C01 /* VerifyDateTests.m */; }; D458C525214E33440043D982 /* VerifyDateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5764214E195200A32C01 /* VerifyDateTests.m */; }; + D458DAC32375FEA300E5890E /* TrustSettingsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D458DAC22375FEA300E5890E /* TrustSettingsTests.m */; }; + D458DAC42375FEA300E5890E /* TrustSettingsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D458DAC22375FEA300E5890E /* TrustSettingsTests.m */; }; D45917E41DC13E6700752D25 /* SecCertificateRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E3E1D8085FC00865A7C /* SecCertificateRequest.c */; }; + D4593EFF24C131180069F577 /* SecTrustStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C1B442C0BB9CAF900461B82 /* SecTrustStore.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D4610637258C2E1D0099E390 /* trustdFileLocations.m in Sources */ = {isa = PBXBuildFile; fileRef = D43534FD2525033E002E72F7 /* trustdFileLocations.m */; }; + D4610717258C2E230099E390 /* SecFileLocations.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC6D1D8C68CF00070CB0 /* SecFileLocations.c */; }; + D46108D7258C2E510099E390 /* SecCFWrappers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC471D8C68CF00070CB0 /* SecCFWrappers.c */; }; + D4610A96258C2F350099E390 /* SecBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC3E1D8C68CF00070CB0 /* SecBuffer.c */; }; D46246971F9AE2E400D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246911F9AE2E400D63882 /* libDER.a */; }; D46246A31F9AE59E00D63882 /* oids.h in Headers */ = {isa = PBXBuildFile; fileRef = D46246A21F9AE49E00D63882 /* oids.h */; settings = {ATTRIBUTES = (Private, ); }; }; D46246A81F9AE64000D63882 /* oids.h in Headers */ = {isa = PBXBuildFile; fileRef = D46246A21F9AE49E00D63882 /* oids.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -2408,8 +2387,6 @@ D46246B91F9AE79000D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; D46246BA1F9AE7A000D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; D46246BB1F9AE7B300D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; - D46246BC1F9AE82B00D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; - D46246BD1F9AE83600D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; D46246BE1F9AE86400D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; D46246C91F9AEA5300D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246C31F9AEA5200D63882 /* libDER.a */; }; D46246D41F9AEAE300D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246CE1F9AEAE300D63882 /* libDER.a */; }; @@ -2437,6 +2414,23 @@ D4707A2D2114C1E8005BCFDA /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = D4707A2B2114B31A005BCFDA /* SecCmsContentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; D4707A2F2114C315005BCFDA /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D4707A2E2114C30A005BCFDA /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; D4707A302114C316005BCFDA /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D4707A2E2114C30A005BCFDA /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D477CB5C237B6E0E00C02355 /* PersonalizationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */; }; + D477CB5D237B6E0E00C02355 /* PersonalizationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */; }; + D477CB6A237CBA2C00C02355 /* TrustDaemonTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */; }; + D477CB6B237CBA2C00C02355 /* TrustDaemonTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */; }; + D477CB78237E482800C02355 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = D477CB76237E453C00C02355 /* si-88-sectrust-valid-data */; }; + D477CB79237E484300C02355 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = D477CB76237E453C00C02355 /* si-88-sectrust-valid-data */; }; + D477CB7B237E4BD700C02355 /* ExceptionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB7A237E4BD700C02355 /* ExceptionTests.m */; }; + D477CB7C237E4BD700C02355 /* ExceptionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB7A237E4BD700C02355 /* ExceptionTests.m */; }; + D477CB82237F692400C02355 /* RevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB81237F692400C02355 /* RevocationTests.m */; }; + D477CB83237F692400C02355 /* RevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB81237F692400C02355 /* RevocationTests.m */; }; + D477CB87237F8B2F00C02355 /* CAIssuerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB86237F8B2F00C02355 /* CAIssuerTests.m */; }; + D477CB88237F8B2F00C02355 /* CAIssuerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB86237F8B2F00C02355 /* CAIssuerTests.m */; }; + D477CB8B237F8DBC00C02355 /* AllowlistBlocklistTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB8A237F8DBB00C02355 /* AllowlistBlocklistTests.m */; }; + D477CB8C237F8DBC00C02355 /* AllowlistBlocklistTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB8A237F8DBB00C02355 /* AllowlistBlocklistTests.m */; }; + D477CB8F237F975500C02355 /* ValidTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB8E237F975500C02355 /* ValidTests.m */; }; + D477CB90237F975500C02355 /* ValidTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB8E237F975500C02355 /* ValidTests.m */; }; + D478A4572532762E00283EB9 /* TestTrustdInitialization-data in Resources */ = {isa = PBXBuildFile; fileRef = D4072929253138730084D96B /* TestTrustdInitialization-data */; }; D479F6E21F980FAB00388D28 /* Trust.strings in Resources */ = {isa = PBXBuildFile; fileRef = D479F6DF1F980F8F00388D28 /* Trust.strings */; }; D479F6E31F981FD600388D28 /* OID.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C198F1F0ACDB4BF00AAB142 /* OID.strings */; }; D479F6E41F981FD600388D28 /* Certificate.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C198F1D0ACDB4BF00AAB142 /* Certificate.strings */; }; @@ -2450,6 +2444,7 @@ D47AB2D12356B2FE005A3801 /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D47AB2CA2356AD72005A3801 /* Network.framework */; }; D47AB2D22356B325005A3801 /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D47AB2CA2356AD72005A3801 /* Network.framework */; }; D47AB2D62357955F005A3801 /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D47AB2CA2356AD72005A3801 /* Network.framework */; }; + D47C457A255244AD00460750 /* CertificateTransparency.m in Sources */ = {isa = PBXBuildFile; fileRef = D47C4579255244AD00460750 /* CertificateTransparency.m */; }; D47CA65D1EB036450038E2BB /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D47CA65C1EB036450038E2BB /* libMobileGestalt.dylib */; }; D47DCCB523427C7D00B80E37 /* md.m in Sources */ = {isa = PBXBuildFile; fileRef = D47DCCB423427C7D00B80E37 /* md.m */; }; D47E69401E92F75D002C8CF6 /* si-61-pkcs12.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DD91D8085FC00865A7C /* si-61-pkcs12.c */; }; @@ -2473,8 +2468,14 @@ D491116F209559510066A1E4 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; D49111702095595B0066A1E4 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; D4911172209559630066A1E4 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - D4911173209559630066A1E4 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; D4961BC42079424200F16DA7 /* TrustURLSessionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D4961BBD2079423300F16DA7 /* TrustURLSessionDelegate.m */; }; + D4981B8F24F723EA004B033B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + D49A370C23877ECC0065719F /* OCSPCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370B23877ECC0065719F /* OCSPCacheTests.m */; }; + D49A370D23877ECC0065719F /* OCSPCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370B23877ECC0065719F /* OCSPCacheTests.m */; }; + D49BD0742476F67700FC7E1C /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; + D49BD0762476F74B00FC7E1C /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; + D49BD0772476F7C000FC7E1C /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; + D49BD07824770E2D00FC7E1C /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; D4A0F8C2211E6A2F00443CA1 /* si-82-sectrust-ct-data in Resources */ = {isa = PBXBuildFile; fileRef = D4A0F8C1211E6A2F00443CA1 /* si-82-sectrust-ct-data */; }; D4A0F8C7211E6A5800443CA1 /* TrustFrameworkTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D4A0F8C4211E6A5700443CA1 /* TrustFrameworkTestCase.m */; }; D4A0F8C8211E6A5800443CA1 /* CertificateInterfaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4A0F8C6211E6A5700443CA1 /* CertificateInterfaceTests.m */; }; @@ -2525,7 +2526,6 @@ D4B68C66211A8186009FED69 /* trustd_spi.h in Headers */ = {isa = PBXBuildFile; fileRef = D4B68C64211A8186009FED69 /* trustd_spi.h */; }; D4B68C68211A827C009FED69 /* trustd_spi.c in Sources */ = {isa = PBXBuildFile; fileRef = D4B68C65211A8186009FED69 /* trustd_spi.c */; }; D4B6D57C2069D8450099FBEF /* si-34-cms-timestamp.m in Sources */ = {isa = PBXBuildFile; fileRef = D4B6D57B2069D8450099FBEF /* si-34-cms-timestamp.m */; }; - D4B858671D370D9A003B2D95 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4B858661D370D9A003B2D95 /* MobileCoreServices.framework */; }; D4BD5E83228A6823001650A7 /* util.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BC6F79621C9955D005ED67A /* util.m */; }; D4BD5E85228A6854001650A7 /* util.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BC6F79621C9955D005ED67A /* util.m */; }; D4BD5E86228A6855001650A7 /* util.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BC6F79621C9955D005ED67A /* util.m */; }; @@ -2535,11 +2535,25 @@ D4BEECE81E93094500F76D1A /* trustd.c in Sources */ = {isa = PBXBuildFile; fileRef = D4BEECE61E93093A00F76D1A /* trustd.c */; }; D4C263CE1F95300F001317EA /* SecErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = D4C263CC1F952F6C001317EA /* SecErrorMessages.strings */; }; D4C263CF1F953019001317EA /* SecDebugErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = D4C263C81F952E64001317EA /* SecDebugErrorMessages.strings */; }; + D4C573C4255B6A1800AB5D78 /* si-26-cms-apple-signed-samples.m in Sources */ = {isa = PBXBuildFile; fileRef = D4C573C3255B6A1800AB5D78 /* si-26-cms-apple-signed-samples.m */; }; + D4C57B76255B74A400AB5D78 /* PolicyInterfaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4C578E6255B746600AB5D78 /* PolicyInterfaceTests.m */; }; + D4C57C51255B74A600AB5D78 /* PolicyInterfaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4C578E6255B746600AB5D78 /* PolicyInterfaceTests.m */; }; D4C6C5CD1FB3B423007EA57E /* libarchive.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4C6C5CB1FB3B3CC007EA57E /* libarchive.tbd */; }; D4C6C5CF1FB3B44D007EA57E /* libarchive.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4C6C5CE1FB3B44C007EA57E /* libarchive.2.dylib */; }; D4C6C5D01FB3B45E007EA57E /* libarchive.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4C6C5CE1FB3B44C007EA57E /* libarchive.2.dylib */; }; D4C7CD661E71E92D00139817 /* MobileAsset.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7273402816CAFB3C0096622A /* MobileAsset.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - D4CFAA7E1E660BB3004746AA /* si-32-sectrust-pinning-required.m in Sources */ = {isa = PBXBuildFile; fileRef = D4CFAA7D1E660BB3004746AA /* si-32-sectrust-pinning-required.m */; }; + D4C88D88262E5DB20006FFB1 /* si-27-cms-parse.m in Sources */ = {isa = PBXBuildFile; fileRef = D4C88D87262E5DB20006FFB1 /* si-27-cms-parse.m */; }; + D4C88D8B262E66420006FFB1 /* si-27-cms-parse in Resources */ = {isa = PBXBuildFile; fileRef = D4C88D8A262E660A0006FFB1 /* si-27-cms-parse */; }; + D4C88D8C262E666B0006FFB1 /* si-27-cms-parse in Resources */ = {isa = PBXBuildFile; fileRef = D4C88D8A262E660A0006FFB1 /* si-27-cms-parse */; }; + D4C88D8D262E667C0006FFB1 /* si-27-cms-parse in Resources */ = {isa = PBXBuildFile; fileRef = D4C88D8A262E660A0006FFB1 /* si-27-cms-parse */; }; + D4C88D8E262E67D90006FFB1 /* si-20-sectrust-policies-data in Resources */ = {isa = PBXBuildFile; fileRef = D458C51B214E2CFF0043D982 /* si-20-sectrust-policies-data */; }; + D4C88D8F262E67DF0006FFB1 /* si-87-sectrust-name-constraints in Resources */ = {isa = PBXBuildFile; fileRef = D4056A1E22712D750026E24E /* si-87-sectrust-name-constraints */; }; + D4C88D90262E67F30006FFB1 /* si-20-sectrust-policies-data in Resources */ = {isa = PBXBuildFile; fileRef = D458C51B214E2CFF0043D982 /* si-20-sectrust-policies-data */; }; + D4C88D91262E67F80006FFB1 /* si-87-sectrust-name-constraints in Resources */ = {isa = PBXBuildFile; fileRef = D4056A1E22712D750026E24E /* si-87-sectrust-name-constraints */; }; + D4D1CBB425AD0AAF0068595B /* CertificateServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D1CBB325AD0AAF0068595B /* CertificateServerTests.m */; }; + D4D1CBB525AD0AAF0068595B /* CertificateServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D1CBB325AD0AAF0068595B /* CertificateServerTests.m */; }; + D4D1CF3125AD37260068595B /* TrustServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D1CF3025AD37260068595B /* TrustServerTests.m */; }; + D4D1CF3225AD37260068595B /* TrustServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D1CF3025AD37260068595B /* TrustServerTests.m */; }; D4D1FDC721163F6A003538E2 /* SecCmsBase.h in Headers */ = {isa = PBXBuildFile; fileRef = D4707A1F2113AB65005BCFDA /* SecCmsBase.h */; }; D4D1FDC821163F6A003538E2 /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = D4707A2B2114B31A005BCFDA /* SecCmsContentInfo.h */; }; D4D1FDC921163F6A003538E2 /* SecCmsDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = D4707A252113E9B6005BCFDA /* SecCmsDecoder.h */; }; @@ -2560,34 +2574,64 @@ D4D1FDE4211660F4003538E2 /* cms-trust-settings-test.h in Headers */ = {isa = PBXBuildFile; fileRef = D42C83A321159569008D3D83 /* cms-trust-settings-test.h */; }; D4D1FDE521166135003538E2 /* libsecurity_cms_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D4D1FDDC21165F8B003538E2 /* libsecurity_cms_regressions.a */; }; D4D718351E04A721000AE7A6 /* spbkdf-01-hmac-sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = D4D718341E04A721000AE7A6 /* spbkdf-01-hmac-sha256.c */; }; - D4D886E91CEBDD2A00DC7583 /* nist-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4D886E81CEBDD2A00DC7583 /* nist-certs */; }; - D4D886EA1CEBDE0800DC7583 /* nist-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4D886E81CEBDD2A00DC7583 /* nist-certs */; }; D4D92DA522788FEB0009A7CF /* NISTTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D92DA422788FEB0009A7CF /* NISTTests.m */; }; D4D92DA622788FEB0009A7CF /* NISTTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D92DA422788FEB0009A7CF /* NISTTests.m */; }; D4D92DA8227890500009A7CF /* nist-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4D92DA72278904F0009A7CF /* nist-certs */; }; D4D92DA9227890500009A7CF /* nist-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4D92DA72278904F0009A7CF /* nist-certs */; }; + D4E6D8592404EAD40074CB26 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246911F9AE2E400D63882 /* libDER.a */; }; D4EA5CF822B225D100883439 /* LoggingServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4EA5CF622B225C000883439 /* LoggingServerTests.m */; }; D4EA5CF922B225D100883439 /* LoggingServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4EA5CF622B225C000883439 /* LoggingServerTests.m */; }; D4EF32172156B025000A31A5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; D4EF32182156DDEB000A31A5 /* TrustSettingsInterfaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D458C4BE214E19FA0043D982 /* TrustSettingsInterfaceTests.m */; }; D4EF3221215F0F7F000A31A5 /* SecTrustStoreServer.m in Sources */ = {isa = PBXBuildFile; fileRef = D4EF321E215F0F76000A31A5 /* SecTrustStoreServer.m */; }; D4F56B95217FC93500FCA6B7 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + D4FA5BD9259D0FCB00EDB660 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D4FA5BD8259D0FCB00EDB660 /* main.m */; }; + D4FA6039259D109B00EDB660 /* trustdFileHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = D445B5B0258C08790019858E /* trustdFileHelper.m */; }; + D4FA62D8259D16D800EDB660 /* trustdFileHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = D445B5B0258C08790019858E /* trustdFileHelper.m */; }; + D4FA63BC259D568F00EDB660 /* trustdFileLocations.m in Sources */ = {isa = PBXBuildFile; fileRef = D43534FD2525033E002E72F7 /* trustdFileLocations.m */; }; + D4FA657B259D5B9C00EDB660 /* trustdFileLocations.m in Sources */ = {isa = PBXBuildFile; fileRef = D43534FD2525033E002E72F7 /* trustdFileLocations.m */; }; + D4FA657C259D5B9C00EDB660 /* trustdFileHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = D445B5B0258C08790019858E /* trustdFileHelper.m */; }; D4FD421C217D789C002B7EE2 /* NameConstraintsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4FD421B217D7891002B7EE2 /* NameConstraintsTests.m */; }; D4FD421D217D789C002B7EE2 /* NameConstraintsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4FD421B217D7891002B7EE2 /* NameConstraintsTests.m */; }; D4FD4220217D7B2E002B7EE2 /* PathScoringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4FD421F217D7B27002B7EE2 /* PathScoringTests.m */; }; D4FD4221217D7B2E002B7EE2 /* PathScoringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4FD421F217D7B27002B7EE2 /* PathScoringTests.m */; }; D4FD4224217D7BE4002B7EE2 /* libarchive.2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4FD4223217D7BE3002B7EE2 /* libarchive.2.tbd */; }; D4FD4225217D7BEE002B7EE2 /* libarchive.2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4FD4223217D7BE3002B7EE2 /* libarchive.2.tbd */; }; - D4FD4226217D7C41002B7EE2 /* si-87-sectrust-name-constraints in Resources */ = {isa = PBXBuildFile; fileRef = D4C6C5C71FB2AD3F007EA57E /* si-87-sectrust-name-constraints */; }; - D4FD4227217D7C4F002B7EE2 /* si-87-sectrust-name-constraints in Resources */ = {isa = PBXBuildFile; fileRef = D4C6C5C71FB2AD3F007EA57E /* si-87-sectrust-name-constraints */; }; DA20716222E9367500E209E4 /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; DA2C402E2189302F005F1CC3 /* mach_notify.defs in Sources */ = {isa = PBXBuildFile; fileRef = DA2C402D2189302E005F1CC3 /* mach_notify.defs */; settings = {ATTRIBUTES = (Server, ); }; }; + DA2F591823A32BC100C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F591E23A986A300C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592123A9874800C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592523A99E8400C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592623A99EC900C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592723A99F2900C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592823A99F6300C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; DA30D6851DF8CA4100EC6B43 /* KeychainSyncAccountUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30D6841DF8CA4100EC6B43 /* KeychainSyncAccountUpdater.m */; }; DA31CB212319DC8F0039F1CC /* TPStringTable.m in Sources */ = {isa = PBXBuildFile; fileRef = DA700FC82310C0E00051A7DE /* TPStringTable.m */; }; + DA3862A723A9CD2E001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862A923AAD1FD001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862AA23AAD959001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862AB23AAE3A8001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862AC23AAE3D3001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862AE23AAE65E001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; DA3AD86A2319AA5D0049AFD6 /* TPStringTableTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3AD8682319AA310049AFD6 /* TPStringTableTests.m */; }; DA41FE1A2241AF4600838FB3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DA41FE192241AF3E00838FB3 /* main.m */; }; DA41FE1B2241AF8200838FB3 /* IDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD744683195A00BB00FB01C0 /* IDS.framework */; }; DA45865C2245AEDB0073F993 /* OTPairingService.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4586592245AEDA0073F993 /* OTPairingService.m */; }; + DA53FC3923A9BA68002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC3C23A9BDD5002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC3D23A9BF28002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC3E23A9C180002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC3F23A9C26F002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4023A9C351002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4123A9C3CE002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4223A9C442002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4423A9C779002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4523A9C801002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4623A9CB13002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4723A9CBAA002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4823A9CC16002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4923A9CC8D002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; DA5B871C2065A8440093F083 /* SecAutorelease.h in Headers */ = {isa = PBXBuildFile; fileRef = DA5B871A2065A8410093F083 /* SecAutorelease.h */; }; DA5B871D2065A8440093F083 /* SecAutorelease.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5B871B2065A8430093F083 /* SecAutorelease.m */; }; DA6AA1651FE88AFB004565B0 /* CKKSControlServer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6AA15E1FE88AF9004565B0 /* CKKSControlServer.m */; }; @@ -2648,12 +2692,12 @@ DC00ABF11D821FC400513D74 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; DC00ABF21D821FC800513D74 /* libSOSRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52EC681D80D0C400B0A59C /* libSOSRegressions.a */; }; DC00ABF31D821FCD00513D74 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - DC00C91D20B3B79600628BEB /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; DC00C92020B3B7CC00628BEB /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246911F9AE2E400D63882 /* libDER.a */; }; DC00C92320B3B80500628BEB /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EB49B2DC202DF251003F34A0 /* libbsm.tbd */; }; DC00C92420B3B82600628BEB /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; DC00C93420B48B4100628BEB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; DC00C93520B48BA800628BEB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + DC03592D235FCCD500F14883 /* KCInitialMessageData.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A47FFB5228F5E9000F781B8 /* KCInitialMessageData.m */; }; DC047081218BB21E0078BDAA /* OTCuttlefishAccountStateHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = DC04707F218BB21E0078BDAA /* OTCuttlefishAccountStateHolder.h */; }; DC047082218BB21E0078BDAA /* OTCuttlefishAccountStateHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = DC047080218BB21E0078BDAA /* OTCuttlefishAccountStateHolder.m */; }; DC047087218BCEF20078BDAA /* OTOperationDependencies.h in Headers */ = {isa = PBXBuildFile; fileRef = DC047085218BCEF20078BDAA /* OTOperationDependencies.h */; }; @@ -2662,7 +2706,8 @@ DC05037A21409A4100A8EDB7 /* OCMockUmbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = DC05037821409A4100A8EDB7 /* OCMockUmbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; DC05038121409A6100A8EDB7 /* OCMock.framework in Embed OCMock */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; DC05038221409B3400A8EDB7 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; }; - DC066DF02102563300694EAF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; + DC061A71246213660026ADB3 /* CKKSLocalResetOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC061A70246211DE0026ADB3 /* CKKSLocalResetOperation.m */; }; + DC061A722462136F0026ADB3 /* CKKSOperationDependencies.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3412E6245780BA008ABD0A /* CKKSOperationDependencies.m */; }; DC07090422936DB2002711B9 /* OctagonTests+ErrorHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC07090222936BCC002711B9 /* OctagonTests+ErrorHandling.swift */; }; DC08D1C41E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC08D1C31E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m */; }; DC08D1CC1E64FCC5006237DA /* CKKSSOSTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DC08D1CB1E64FCC5006237DA /* CKKSSOSTests.m */; }; @@ -3145,7 +3190,6 @@ DC0BCDA51D8C6A1F00070CB0 /* iOSforOSX-SecRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC6A1D8C68CF00070CB0 /* iOSforOSX-SecRandom.c */; }; DC0BCDA61D8C6A1F00070CB0 /* SecDb.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC6B1D8C68CF00070CB0 /* SecDb.c */; }; DC0BCDA71D8C6A1F00070CB0 /* SecDb.h in Headers */ = {isa = PBXBuildFile; fileRef = DC0BCC6C1D8C68CF00070CB0 /* SecDb.h */; }; - DC0BCDA81D8C6A1F00070CB0 /* SecFileLocations.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC6D1D8C68CF00070CB0 /* SecFileLocations.c */; }; DC0BCDA91D8C6A1F00070CB0 /* SecFileLocations.h in Headers */ = {isa = PBXBuildFile; fileRef = DC0BCC6E1D8C68CF00070CB0 /* SecFileLocations.h */; }; DC0BCDAA1D8C6A1F00070CB0 /* SecXPCError.h in Headers */ = {isa = PBXBuildFile; fileRef = DC0BCC6F1D8C68CF00070CB0 /* SecXPCError.h */; }; DC0BCDAB1D8C6A1F00070CB0 /* SecXPCError.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC701D8C68CF00070CB0 /* SecXPCError.c */; }; @@ -3160,6 +3204,11 @@ DC0BD4F621BB0610006B9154 /* CKKSKeychainBackedKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DC0BD4F021BB05F2006B9154 /* CKKSKeychainBackedKey.m */; }; DC0C343821FA7DEB00417D04 /* SecEscrowRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = DC90A4C021F27680001300EB /* SecEscrowRequest.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC0C343A21FA7DEB00417D04 /* SecEscrowRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = DC90A4C021F27680001300EB /* SecEscrowRequest.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DC0D16012363A1D6007F0951 /* OTSetCDPBitOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC0D15FF2363A1D6007F0951 /* OTSetCDPBitOperation.h */; }; + DC0D16022363A1D6007F0951 /* OTSetCDPBitOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC0D16002363A1D6007F0951 /* OTSetCDPBitOperation.m */; }; + DC0D16062363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC0D16042363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.h */; }; + DC0D16072363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC0D16052363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.m */; }; + DC0DE87123750340006E2EAE /* OTPairingMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9AE2A2214055CF003BFDB5 /* OTPairingMessage.m */; }; DC0EF8F2208697C600AB9E95 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC0EF8F1208697C600AB9E95 /* main.swift */; }; DC0FA6B02291F63F00FE01C4 /* OctagonPendingFlag.h in Headers */ = {isa = PBXBuildFile; fileRef = DC0FA6AE2291F63F00FE01C4 /* OctagonPendingFlag.h */; }; DC0FA6B12291F63F00FE01C4 /* OctagonPendingFlag.m in Sources */ = {isa = PBXBuildFile; fileRef = DC0FA6AF2291F63F00FE01C4 /* OctagonPendingFlag.m */; }; @@ -3171,6 +3220,7 @@ DC14478A1F5764C600236DB4 /* CKKSResultOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1447881F5764C600236DB4 /* CKKSResultOperation.h */; }; DC14478C1F5764C600236DB4 /* CKKSResultOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC1447891F5764C600236DB4 /* CKKSResultOperation.m */; }; DC1447961F5766D200236DB4 /* NSOperationCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1447941F5766D200236DB4 /* NSOperationCategories.h */; }; + DC14C4C223AAACED007F673F /* Container_BottledPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC3A9B2523A9D6120073ED06 /* Container_BottledPeers.swift */; }; DC15F7661E67A6F6003B9A40 /* CKKSHealKeyHierarchyOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC15F7641E67A6F6003B9A40 /* CKKSHealKeyHierarchyOperation.h */; }; DC15F7681E67A6F6003B9A40 /* CKKSHealKeyHierarchyOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC15F7651E67A6F6003B9A40 /* CKKSHealKeyHierarchyOperation.m */; }; DC15F79C1E68EAD5003B9A40 /* CKKSTests+API.m in Sources */ = {isa = PBXBuildFile; fileRef = DC15F79B1E68EAD5003B9A40 /* CKKSTests+API.m */; }; @@ -3258,7 +3308,6 @@ DC1787261D778FDE00B50D50 /* SecManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787241D778FDE00B50D50 /* SecManifest.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787271D778FDE00B50D50 /* SecureDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787251D778FDE00B50D50 /* SecureDownloadInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787351D77903700B50D50 /* SecAccessPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787281D77903700B50D50 /* SecAccessPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - DC1787361D77903700B50D50 /* SecCertificateBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787291D77903700B50D50 /* SecCertificateBundle.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787371D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17872A1D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787381D77903700B50D50 /* SecIdentitySearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17872B1D77903700B50D50 /* SecIdentitySearchPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787391D77903700B50D50 /* SecKeychainItemExtendedAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17872C1D77903700B50D50 /* SecKeychainItemExtendedAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -3289,7 +3338,6 @@ DC1787701D77911D00B50D50 /* osKeyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787671D77911D00B50D50 /* osKeyTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787711D77911D00B50D50 /* secasn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787681D77911D00B50D50 /* secasn1t.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787721D77911D00B50D50 /* X509Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787691D77911D00B50D50 /* X509Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - DC1787741D77915500B50D50 /* SecBreadcrumb.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787731D77915500B50D50 /* SecBreadcrumb.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787751D77916000B50D50 /* SecAccessControlPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 443381DA18A3D81400215606 /* SecAccessControlPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787761D77916600B50D50 /* SecCFAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = D47F514B1C3B812500A7CEFE /* SecCFAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787771D77916A00B50D50 /* SecDH.h in Headers */ = {isa = PBXBuildFile; fileRef = 7940D4110C3ACF9000FDB5D8 /* SecDH.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -3319,7 +3367,6 @@ DC1789281D779A0F00B50D50 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; }; DC1789291D779A2800B50D50 /* libctkclient_sep.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDD1AA0A45C0021AA26 /* libctkclient_sep.a */; }; DC17892A1D779A3200B50D50 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; }; - DC1789A21D779DF400B50D50 /* SecBreadcrumb.c in Sources */ = {isa = PBXBuildFile; fileRef = DC1789A01D779DEE00B50D50 /* SecBreadcrumb.c */; }; DC1789A51D779E3B00B50D50 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC1789A41D779E3B00B50D50 /* dummy.cpp */; }; DC1789E91D77A0F300B50D50 /* CloudKeychain.strings in Resources */ = {isa = PBXBuildFile; fileRef = 53C0E1F1177FAC2C00F8A018 /* CloudKeychain.strings */; }; DC178A1F1D77A1E700B50D50 /* cssm.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = DC178A0E1D77A1E700B50D50 /* cssm.mdsinfo */; }; @@ -3342,7 +3389,6 @@ DC178A421D77A1F600B50D50 /* FDEPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = DC178A311D77A1F500B50D50 /* FDEPrefs.plist */; }; DC178A431D77A1F600B50D50 /* SecDebugErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC178A321D77A1F500B50D50 /* SecDebugErrorMessages.strings */; }; DC178A441D77A1F600B50D50 /* SecErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC178A331D77A1F500B50D50 /* SecErrorMessages.strings */; }; - DC178A451D77A1F600B50D50 /* framework.sb in Resources */ = {isa = PBXBuildFile; fileRef = DC178A351D77A1F500B50D50 /* framework.sb */; }; DC178A471D77A1F600B50D50 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC178A381D77A1F500B50D50 /* InfoPlist.strings */; }; DC178A481D77A1F600B50D50 /* TimeStampingPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = DC178A3A1D77A1F500B50D50 /* TimeStampingPrefs.plist */; }; DC178A491D77A1F600B50D50 /* authorization.dfr.prompts.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC178A3B1D77A1F500B50D50 /* authorization.dfr.prompts.strings */; }; @@ -3365,12 +3411,6 @@ DC222C361E02419B00B09171 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; DC222C8A1E089BAE00B09171 /* CKKSSQLTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DC222C891E089BAE00B09171 /* CKKSSQLTests.m */; }; DC222CA81E08A7D900B09171 /* CloudKitMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC222CA71E08A7D900B09171 /* CloudKitMockXCTest.m */; }; - DC2353291ECA658300D7C1BE /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; - DC23532F1ECA658400D7C1BE /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; - DC2353301ECA658900D7C1BE /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; - DC2353311ECA658B00D7C1BE /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; - DC2353321ECA659000D7C1BE /* server_xpc.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB2214A1E8B0861001598BC /* server_xpc.m */; }; - DC2353331ECA659000D7C1BE /* server_xpc.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB2214A1E8B0861001598BC /* server_xpc.m */; }; DC25B3AC233C2EBC00CB1409 /* CloudKitCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = DC94BCC91F10448600E07CEB /* CloudKitCategories.m */; }; DC26666A21CAC32700F19960 /* OTControlCLI.m in Sources */ = {isa = PBXBuildFile; fileRef = DC26666921CAC32700F19960 /* OTControlCLI.m */; }; DC26666C21CAC97000F19960 /* OTControlCLI.m in Sources */ = {isa = PBXBuildFile; fileRef = DC26666921CAC32700F19960 /* OTControlCLI.m */; }; @@ -3398,9 +3438,6 @@ DC2C5F511F0D935300FEBDA7 /* CKKSControlProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF7A89F1F04502300CABE89 /* CKKSControlProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC2C5F5D1F0EB97E00FEBDA7 /* CKKSNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = DC2C5F5A1F0EB97E00FEBDA7 /* CKKSNotifier.h */; }; DC2C5F601F0EB97E00FEBDA7 /* CKKSNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = DC2C5F5B1F0EB97E00FEBDA7 /* CKKSNotifier.m */; }; - DC2D438F1F0EEC2A0005D382 /* MockCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502E61E0214C800BC0587 /* MockCloudKit.m */; }; - DC2D43951F0EEC300005D382 /* MockCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502E61E0214C800BC0587 /* MockCloudKit.m */; }; - DC2FA71120E5770400DB7518 /* OTClique.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F336A20DD643B0031A92D /* OTClique.m */; }; DC2FA72520E57AB500DB7518 /* SOSPeerInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D631D8085F200865A7C /* SOSPeerInfo.m */; }; DC2FA72A20E57BFD00DB7518 /* SOSAccountTrust.m in Sources */ = {isa = PBXBuildFile; fileRef = CD31F8601DCD4C1400414B46 /* SOSAccountTrust.m */; }; DC2FA72B20E57C1000DB7518 /* SOSAccountTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = CD31F8611DCD4C1400414B46 /* SOSAccountTrust.h */; }; @@ -3408,6 +3445,8 @@ DC311E7A2124B8EF002F5EAE /* aks_real_witness.h in Headers */ = {isa = PBXBuildFile; fileRef = DC311E782124B8EF002F5EAE /* aks_real_witness.h */; }; DC311E7B2124B8EF002F5EAE /* aks_real_witness.c in Sources */ = {isa = PBXBuildFile; fileRef = DC311E792124B8EF002F5EAE /* aks_real_witness.c */; }; DC337B1F1EA04E2100B3A1F0 /* SecBase64.h in Headers */ = {isa = PBXBuildFile; fileRef = 18351B8F14CB65870097860E /* SecBase64.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DC33D7BD2374FD0500A68155 /* OTSponsorToApplicantRound1M2.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9AE28D214054F6003BFDB5 /* OTSponsorToApplicantRound1M2.m */; }; + DC33D7BE2374FD0A00A68155 /* OTSponsorToApplicantRound2M2.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9AE290214054F7003BFDB5 /* OTSponsorToApplicantRound2M2.m */; }; DC340C54208E828F004D7EEC /* TrustedPeers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BEF88C281EAFFC3F00357577 /* TrustedPeers.framework */; }; DC3502B81E0208BE00BC0587 /* CKKSTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502B71E0208BE00BC0587 /* CKKSTests.m */; }; DC3502C51E020D5100BC0587 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; @@ -3455,6 +3494,8 @@ DC3A81D61D99D57F000C7419 /* libcoretls.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CFC029B1D41650700E6283B /* libcoretls.dylib */; }; DC3A81D71D99D58A000C7419 /* libcoretls_cfhelpers.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3A81D41D99D567000C7419 /* libcoretls_cfhelpers.dylib */; }; DC3A81EC1D99F568000C7419 /* libcoretls.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CFC029B1D41650700E6283B /* libcoretls.dylib */; }; + DC3A9B2723A9D8BD0073ED06 /* Container_BottledPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC3A9B2523A9D6120073ED06 /* Container_BottledPeers.swift */; }; + DC3A9B2823A9D8C40073ED06 /* Container_BottledPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC3A9B2523A9D6120073ED06 /* Container_BottledPeers.swift */; }; DC3AA2782097DF70007CA68A /* readline.c in Sources */ = {isa = PBXBuildFile; fileRef = DC65E7BE1D8CBB1500152EF0 /* readline.c */; }; DC3AA2792097DF71007CA68A /* readline.c in Sources */ = {isa = PBXBuildFile; fileRef = DC65E7BE1D8CBB1500152EF0 /* readline.c */; }; DC3AA27A2097DF84007CA68A /* not_on_this_platorm.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCDB41D8C6A5B00070CB0 /* not_on_this_platorm.c */; }; @@ -3510,7 +3551,6 @@ DC3D748C1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3D748A1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.h */; }; DC3D748E1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3D748B1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.m */; }; DC3E18C82125015300073D80 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; - DC3E18EB2125FB8700073D80 /* libaks_mock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC36895E21235F42003A3735 /* libaks_mock.a */; }; DC4268F61E82036F002B7110 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; DC4268FC1E820370002B7110 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; DC4268FE1E820371002B7110 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; @@ -3527,19 +3567,19 @@ DC4269101E82FD9F002B7110 /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; DC4269111E82FDA0002B7110 /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; DC4269121E82FDA1002B7110 /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; + DC4415B423610BF40087981C /* OctagonTests+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4415B323610BF40087981C /* OctagonTests+Account.swift */; }; DC45D43D22EB619D00CEB6B7 /* OctagonStateMachineObservers.h in Headers */ = {isa = PBXBuildFile; fileRef = DC45D43B22EB619D00CEB6B7 /* OctagonStateMachineObservers.h */; }; DC45D43E22EB619D00CEB6B7 /* OctagonStateMachineObservers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC45D43C22EB619D00CEB6B7 /* OctagonStateMachineObservers.m */; }; + DC4A73C5235E69D800DB1E6E /* OTApplicantToSponsorRound2M1.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9AE28E214054F6003BFDB5 /* OTApplicantToSponsorRound2M1.m */; }; DC4A76A02212676D006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; DC4A76A3221267D4006F2D8F /* EscrowRequestServerHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4A76A2221267D4006F2D8F /* EscrowRequestServerHelpers.m */; }; DC4A76A5221268A6006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; DC4A76A62212691F006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; - DC4A76A72212694F006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; - DC4A76A822126959006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; - DC4A76AA22126993006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; DC4A76AB221269B8006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC4A76A92212698B006F2D8F /* CloudServices.framework */; }; DC4A76AC221269E4006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; DC4A76AD22126A17006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; DC4A76AE22126C49006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; + DC4CD9842372294E00EF55FC /* OctagonTests+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4CD9822372294D00EF55FC /* OctagonTests+Helpers.swift */; }; DC4DB1501E24692100CD6769 /* CKKSKey.h in Headers */ = {isa = PBXBuildFile; fileRef = DC4DB14E1E24692100CD6769 /* CKKSKey.h */; }; DC4DB1521E24692100CD6769 /* CKKSKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4DB14F1E24692100CD6769 /* CKKSKey.m */; }; DC4DB15F1E2590B100CD6769 /* CKKSAESSIVEncryptionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4DB15E1E2590B100CD6769 /* CKKSAESSIVEncryptionTests.m */; }; @@ -3624,7 +3664,6 @@ DC52EC381D80CFDB00B0A59C /* secToolFileIO.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D931D8085F200865A7C /* secToolFileIO.c */; }; DC52EC391D80CFDF00B0A59C /* secViewDisplay.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D9E1D8085F200865A7C /* secViewDisplay.c */; }; DC52EC3A1D80CFE400B0A59C /* keychain_log.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D9B1D8085F200865A7C /* keychain_log.m */; }; - DC52EC3B1D80CFE900B0A59C /* syncbackup.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D9D1D8085F200865A7C /* syncbackup.m */; }; DC52EC4E1D80D01F00B0A59C /* swcagent_client.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78EA01D80860C00865A7C /* swcagent_client.c */; }; DC52EC4F1D80D02400B0A59C /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E9A1D8085FC00865A7C /* SecuritydXPC.c */; }; DC52EC5D1D80D06300B0A59C /* SecLogging.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E651D8085FC00865A7C /* SecLogging.c */; }; @@ -3636,7 +3675,6 @@ DC52EC731D80D12E00B0A59C /* sc-20-keynames.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CFD1D8085F200865A7C /* sc-20-keynames.m */; }; DC52EC741D80D13500B0A59C /* SOSTestDataSource.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D0C1D8085F200865A7C /* SOSTestDataSource.c */; }; DC52EC751D80D13B00B0A59C /* sc-42-circlegencount.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D021D8085F200865A7C /* sc-42-circlegencount.c */; }; - DC52EC761D80D13F00B0A59C /* sc-150-ring.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D061D8085F200865A7C /* sc-150-ring.m */; }; DC52EC771D80D14400B0A59C /* sc-130-resignationticket.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D041D8085F200865A7C /* sc-130-resignationticket.c */; }; DC52EC781D80D14800B0A59C /* SOSRegressionUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D0A1D8085F200865A7C /* SOSRegressionUtilities.m */; }; DC52EC791D80D14D00B0A59C /* sc-45-digestvector.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D031D8085F200865A7C /* sc-45-digestvector.c */; }; @@ -3685,7 +3723,6 @@ DC52ECE81D80D2FA00B0A59C /* pbkdf2-00-hmac-sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DA41D8085FC00865A7C /* pbkdf2-00-hmac-sha1.c */; }; DC52ECE91D80D2FA00B0A59C /* spbkdf-00-hmac-sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DA51D8085FC00865A7C /* spbkdf-00-hmac-sha1.c */; }; DC52ECEA1D80D30900B0A59C /* so_01_serverencryption.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E171D8085FC00865A7C /* so_01_serverencryption.c */; }; - DC52ED9E1D80D4ED00B0A59C /* secd-95-escrow-persistence.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C741D8085D800865A7C /* secd-95-escrow-persistence.m */; }; DC52ED9F1D80D4F200B0A59C /* SOSTransportTestTransports.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C7C1D8085D800865A7C /* SOSTransportTestTransports.m */; }; DC52EDA01D80D4F700B0A59C /* sd-10-policytree.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C3D1D8085D800865A7C /* sd-10-policytree.m */; }; DC52EDB51D80D5C500B0A59C /* secd-03-corrupted-items.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C391D8085D800865A7C /* secd-03-corrupted-items.m */; }; @@ -3715,7 +3752,7 @@ DC52EDD21D80D5C500B0A59C /* secd-58-password-change.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C561D8085D800865A7C /* secd-58-password-change.m */; }; DC52EDD31D80D5C500B0A59C /* secd-59-account-cleanup.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C571D8085D800865A7C /* secd-59-account-cleanup.m */; }; DC52EDD41D80D5C500B0A59C /* secd-60-account-cloud-identity.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C581D8085D800865A7C /* secd-60-account-cloud-identity.m */; }; - DC52EDD51D80D5C500B0A59C /* secd60-account-cloud-exposure.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C591D8085D800865A7C /* secd60-account-cloud-exposure.m */; }; + DC52EDD51D80D5C500B0A59C /* secd-60-account-cloud-exposure.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C591D8085D800865A7C /* secd-60-account-cloud-exposure.m */; }; DC52EDD61D80D5C500B0A59C /* secd-61-account-leave-not-in-kansas-anymore.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C5A1D8085D800865A7C /* secd-61-account-leave-not-in-kansas-anymore.m */; }; DC52EDD71D80D5C500B0A59C /* secd-62-account-backup.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C5B1D8085D800865A7C /* secd-62-account-backup.m */; }; DC52EDD91D80D5C500B0A59C /* secd-63-account-resurrection.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C5D1D8085D800865A7C /* secd-63-account-resurrection.m */; }; @@ -3737,31 +3774,16 @@ DC52EDF11D80D5C600B0A59C /* secd-100-initialsync.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C751D8085D800865A7C /* secd-100-initialsync.m */; }; DC52EDF21D80D5C600B0A59C /* secd-130-other-peer-views.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C761D8085D800865A7C /* secd-130-other-peer-views.m */; }; DC52EDF41D80D5C600B0A59C /* secd-200-logstate.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C781D8085D800865A7C /* secd-200-logstate.m */; }; - DC52EDF51D80D62E00B0A59C /* SecdTestKeychainUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C7A1D8085D800865A7C /* SecdTestKeychainUtilities.c */; }; + DC52EDF51D80D62E00B0A59C /* SecdTestKeychainUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C7A1D8085D800865A7C /* SecdTestKeychainUtilities.m */; }; DC52EDF61D80D62E00B0A59C /* SOSTransportTestTransports.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C7C1D8085D800865A7C /* SOSTransportTestTransports.m */; }; DC52EDF71D80D65700B0A59C /* si-90-emcs.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E0D1D8085FC00865A7C /* si-90-emcs.m */; }; DC52EDF81D80D65C00B0A59C /* SOSTestDevice.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D0E1D8085F200865A7C /* SOSTestDevice.c */; }; DC52EDF91D80D66000B0A59C /* SOSTestDataSource.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D0C1D8085F200865A7C /* SOSTestDataSource.c */; }; DC52EDFA1D80D66600B0A59C /* SOSRegressionUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D0A1D8085F200865A7C /* SOSRegressionUtilities.m */; }; - DC52EE441D80D71900B0A59C /* si-21-sectrust-asr.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DBD1D8085FC00865A7C /* si-21-sectrust-asr.c */; }; - DC52EE451D80D71900B0A59C /* si-22-sectrust-iap.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DBE1D8085FC00865A7C /* si-22-sectrust-iap.c */; }; - DC52EE471D80D71900B0A59C /* si-23-sectrust-ocsp.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC01D8085FC00865A7C /* si-23-sectrust-ocsp.c */; }; - DC52EE481D80D71900B0A59C /* si-24-sectrust-digicert-malaysia.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC11D8085FC00865A7C /* si-24-sectrust-digicert-malaysia.c */; }; - DC52EE491D80D71900B0A59C /* si-24-sectrust-diginotar.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC21D8085FC00865A7C /* si-24-sectrust-diginotar.c */; }; - DC52EE4A1D80D71900B0A59C /* si-24-sectrust-itms.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC31D8085FC00865A7C /* si-24-sectrust-itms.c */; }; - DC52EE4C1D80D71900B0A59C /* si-24-sectrust-passbook.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC51D8085FC00865A7C /* si-24-sectrust-passbook.c */; }; - DC52EE4D1D80D71900B0A59C /* si-26-sectrust-copyproperties.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC61D8085FC00865A7C /* si-26-sectrust-copyproperties.c */; }; - DC52EE4E1D80D71900B0A59C /* si-27-sectrust-exceptions.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC71D8085FC00865A7C /* si-27-sectrust-exceptions.c */; }; - DC52EE4F1D80D71900B0A59C /* si-28-sectrustsettings.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC81D8085FC00865A7C /* si-28-sectrustsettings.m */; }; DC52EE531D80D73800B0A59C /* si-44-seckey-gen.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DD31D8085FC00865A7C /* si-44-seckey-gen.m */; }; DC52EE541D80D73800B0A59C /* si-44-seckey-rsa.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DD41D8085FC00865A7C /* si-44-seckey-rsa.m */; }; DC52EE551D80D73800B0A59C /* si-44-seckey-ec.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DD51D8085FC00865A7C /* si-44-seckey-ec.m */; }; DC52EE561D80D73800B0A59C /* si-44-seckey-ies.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DD61D8085FC00865A7C /* si-44-seckey-ies.m */; }; - DC52EE571D80D73800B0A59C /* si-67-sectrust-blocklist.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DF71D8085FC00865A7C /* si-67-sectrust-blocklist.c */; }; - DC52EE581D80D73800B0A59C /* si-70-sectrust-unified.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DFA1D8085FC00865A7C /* si-70-sectrust-unified.c */; }; - DC52EE5A1D80D73800B0A59C /* si-83-seccertificate-sighashalg.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E061D8085FC00865A7C /* si-83-seccertificate-sighashalg.c */; }; - DC52EE601D80D79900B0A59C /* si-74-OTAPKISigner.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DFE1D8085FC00865A7C /* si-74-OTAPKISigner.c */; }; - DC52EE611D80D79E00B0A59C /* si-71-mobile-store-policy.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DFB1D8085FC00865A7C /* si-71-mobile-store-policy.c */; }; DC52EE6F1D80D83F00B0A59C /* SecPasswordGenerate.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E7A1D8085FC00865A7C /* SecPasswordGenerate.c */; }; DC52EE701D80D84700B0A59C /* SecItemConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E5C1D8085FC00865A7C /* SecItemConstants.c */; }; DC52EE711D80D85F00B0A59C /* SecECKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E491D8085FC00865A7C /* SecECKey.m */; }; @@ -3878,7 +3900,6 @@ DC5AC0C21D83538D00CF422C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789241D7799CD00B50D50 /* CoreFoundation.framework */; }; DC5AC0C41D8353BB00CF422C /* System.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5AC0C31D8353B900CF422C /* System.framework */; }; DC5AC0C51D8353C200CF422C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; - DC5AC0C71D8353C800CF422C /* PCSC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5AC0C61D8353C800CF422C /* PCSC.framework */; }; DC5AC0C91D8353D100CF422C /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789181D77998C00B50D50 /* libbsm.dylib */; }; DC5AC0CE1D83542B00CF422C /* libsecurity_tokend_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5AC0CD1D83542700CF422C /* libsecurity_tokend_client.a */; }; DC5AC0D31D83544D00CF422C /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC17891E1D77999D00B50D50 /* libsqlite3.dylib */; }; @@ -3901,7 +3922,6 @@ DC5AC0E61D8354CA00CF422C /* tokendatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABF9B1D83511A00CF422C /* tokendatabase.cpp */; }; DC5AC0E71D8354CA00CF422C /* tokenkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABF9D1D83511A00CF422C /* tokenkey.cpp */; }; DC5AC0E81D8354CA00CF422C /* tokenaccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABF9F1D83511A00CF422C /* tokenaccess.cpp */; }; - DC5AC0E91D8354CA00CF422C /* pcscmonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABFA31D83511A00CF422C /* pcscmonitor.cpp */; }; DC5AC0EA1D8354CA00CF422C /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABFA51D83511A00CF422C /* reader.cpp */; }; DC5AC0EB1D8354CA00CF422C /* token.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABFA71D83511A00CF422C /* token.cpp */; }; DC5AC0EC1D8354CA00CF422C /* tokend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABFA91D83511A00CF422C /* tokend.cpp */; }; @@ -3982,13 +4002,10 @@ DC5F35AE1EE0F27C00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; DC5F35AF1EE0F27C00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; DC5F35B01EE0F27C00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; - DC5F35B11EE0F28B00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; - DC5F35B21EE0F28C00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; DC5F65AE2225C22C0051E9FA /* CKKSProvideKeySetOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC5F65AC2225C22C0051E9FA /* CKKSProvideKeySetOperation.h */; }; DC5F65AF2225C22C0051E9FA /* CKKSProvideKeySetOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC5F65AD2225C22C0051E9FA /* CKKSProvideKeySetOperation.m */; }; DC5F65B12225CD720051E9FA /* CKKSProvideKeySetOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC5F65AD2225C22C0051E9FA /* CKKSProvideKeySetOperation.m */; }; DC60132E2147220600863C1A /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; - DC6013312147220F00863C1A /* libaks_mock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC36895E21235F42003A3735 /* libaks_mock.a */; }; DC6013392147227800863C1A /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; DC6063B221B09AB200069B82 /* KCJoiningRequestCircleSession.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6063B121B09AB200069B82 /* KCJoiningRequestCircleSession.m */; }; DC610A181D78F129002223DE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C0BDB31175685B000BC1A7E /* main.m */; }; @@ -4018,7 +4035,6 @@ DC62DC6D22A87137000D2D5D /* CKKSTests+MultiZone.m in Sources */ = {isa = PBXBuildFile; fileRef = DC62DC6B22A87128000D2D5D /* CKKSTests+MultiZone.m */; }; DC63D70820B3931100D088AD /* libxar.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DC63D70220B3930700D088AD /* libxar.tbd */; }; DC6593D11ED8DAB900C19462 /* CKKSTests+CurrentPointerAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6593C91ED8DA9200C19462 /* CKKSTests+CurrentPointerAPI.m */; }; - DC65E7231D8CB28900152EF0 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; DC65E7241D8CB29E00152EF0 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; DC65E7271D8CB2EC00152EF0 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; DC65E72A1D8CB2FC00152EF0 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; @@ -4077,6 +4093,7 @@ DC6D2C931DD2836500BE372D /* CKKSOutgoingQueueEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = DC9B7AE61DCBF651004E9385 /* CKKSOutgoingQueueEntry.h */; }; DC6DE899213076C000C6B56D /* OTSOSUpgradeOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC6DE897213076C000C6B56D /* OTSOSUpgradeOperation.h */; }; DC6DE89C213076C000C6B56D /* OTSOSUpgradeOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6DE898213076C000C6B56D /* OTSOSUpgradeOperation.m */; }; + DC6E02162405DE3900C61335 /* OTModifyUserControllableViewStatusOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6E02132405DDC400C61335 /* OTModifyUserControllableViewStatusOperation.m */; }; DC71D85C1D94CCD40065FB93 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; DC71D8F51D959F150065FB93 /* com.apple.securityd.plist in Copy Logging Files */ = {isa = PBXBuildFile; fileRef = DCE4E80D1D7A4E3A00AFB96E /* com.apple.securityd.plist */; }; DC725030229600C000493D88 /* OctagonTests+Reset.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC72502D229600A800493D88 /* OctagonTests+Reset.swift */; }; @@ -4104,9 +4121,6 @@ DC74799D22272344001E0E8C /* CKKSSIV.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D541E2826DB0089CF55 /* CKKSSIV.m */; }; DC74799E22272358001E0E8C /* CKKSSerializedKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DC9FD3261F858D3E00C8AAC8 /* CKKSSerializedKey.m */; }; DC752F1721C1B48400216089 /* SOSPiggyback.m in Sources */ = {isa = PBXBuildFile; fileRef = EB75B4941E75A44100E469CC /* SOSPiggyback.m */; }; - DC752F1921C1B69C00216089 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; - DC752F1A21C1B6A700216089 /* SFSQLiteStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BF1F152EB10082882F /* SFSQLiteStatement.m */; }; - DC752F1F21C1B98000216089 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; DC754C722228B57C00A39C8E /* TrustedPeersHelperProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = DC754C712228B57B00A39C8E /* TrustedPeersHelperProtocol.m */; }; DC754C742228B59000A39C8E /* TrustedPeersHelperProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = DC754C712228B57B00A39C8E /* TrustedPeersHelperProtocol.m */; }; DC762A9E1E57A86A00B03A2C /* CKKSRecordHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = DC762A9C1E57A86A00B03A2C /* CKKSRecordHolder.h */; }; @@ -4114,6 +4128,7 @@ DC797E1A1DD3F9A400CC9E42 /* CKKSSQLDatabaseObject.m in Sources */ = {isa = PBXBuildFile; fileRef = DC797E131DD3F88300CC9E42 /* CKKSSQLDatabaseObject.m */; }; DC7A17ED1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC7A17EB1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.h */; }; DC7A17EF1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC7A17EC1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.m */; }; + DC7F6A7D233D7FAC00DF5769 /* OctagonTests+ForwardCompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC7F6A7C233D7FAC00DF5769 /* OctagonTests+ForwardCompatibility.swift */; }; DC7F79B622EA4ED4001FB69A /* OctagonTests+CKKS.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC7F79B522EA4ED4001FB69A /* OctagonTests+CKKS.swift */; }; DC7F79BA22EA5C73001FB69A /* OTLocalCKKSResetOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC7F79B822EA5C72001FB69A /* OTLocalCKKSResetOperation.h */; }; DC7F79BB22EA5C73001FB69A /* OTLocalCKKSResetOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC7F79B922EA5C72001FB69A /* OTLocalCKKSResetOperation.m */; }; @@ -4138,8 +4153,14 @@ DC8506B52097F1FD00C712EC /* whoami.m in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA911D80CC2A00B0A59C /* whoami.m */; }; DC8506B62097F39100C712EC /* libSOSCommands.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52EC341D80CFB200B0A59C /* libSOSCommands.a */; }; DC85687E2284E7860088D3EF /* OctagonTestMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC85687C2284E7850088D3EF /* OctagonTestMocks.swift */; }; + DC86122C2408AC190092E93B /* CKKSTests+ItemSyncChoice.m in Sources */ = {isa = PBXBuildFile; fileRef = DC86122B2408AC190092E93B /* CKKSTests+ItemSyncChoice.m */; }; DC8757F4218D2003000E65F1 /* OTRemovePeersOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC8757F2218D2003000E65F1 /* OTRemovePeersOperation.h */; }; DC8757F5218D2003000E65F1 /* OTRemovePeersOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC8757F3218D2003000E65F1 /* OTRemovePeersOperation.m */; }; + DC880F68243D4CC00059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; + DC880F69243D4CE50059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; + DC880F6A243D4D640059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; + DC880F6B243D4D730059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; + DC880F6C243D4DC00059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; DC8834521D8A21AA00CE0ACA /* SecAsn1Coder.c in Sources */ = {isa = PBXBuildFile; fileRef = DC88340A1D8A21AA00CE0ACA /* SecAsn1Coder.c */; }; DC8834541D8A21AA00CE0ACA /* SecAsn1Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = DC88340C1D8A21AA00CE0ACA /* SecAsn1Templates.c */; }; DC8834571D8A21AA00CE0ACA /* certExtensionTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = DC88340F1D8A21AA00CE0ACA /* certExtensionTemplates.c */; }; @@ -4164,6 +4185,8 @@ DC8834931D8A21AB00CE0ACA /* oidsattr.c in Sources */ = {isa = PBXBuildFile; fileRef = DC88344B1D8A21AA00CE0ACA /* oidsattr.c */; }; DC8834961D8A21AB00CE0ACA /* oidsocsp.c in Sources */ = {isa = PBXBuildFile; fileRef = DC88344E1D8A21AA00CE0ACA /* oidsocsp.c */; }; DC88466B22373A5E00738068 /* TPPBDictionaryMatchingRule.proto in Sources */ = {isa = PBXBuildFile; fileRef = DC88466922373A4000738068 /* TPPBDictionaryMatchingRule.proto */; }; + DC89608D2395C75600D339D9 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC89608C2395C75500D339D9 /* CoreServices.framework */; }; + DC89608E2395C76300D339D9 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC89608C2395C75500D339D9 /* CoreServices.framework */; }; DC8D238D2064649400E163C8 /* CKKSAPSHandlingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DC8D238C2064649400E163C8 /* CKKSAPSHandlingTests.m */; }; DC8DF6DC212F8A7C007B3FE8 /* OTSOSAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB9475C2127562100ED9272 /* OTSOSAdapter.m */; }; DC8DF6DF212F8A7D007B3FE8 /* OTSOSAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB9475C2127562100ED9272 /* OTSOSAdapter.m */; }; @@ -4178,12 +4201,9 @@ DC926F081F33F7D30012A315 /* SecCodeHost.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD067981D8CDF7E007602F1 /* SecCodeHost.h */; settings = {ATTRIBUTES = (Public, ); }; }; DC926F091F33FA8D0012A315 /* CKKSControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF7A8A21F0450EB00CABE89 /* CKKSControlProtocol.m */; }; DC926F0A1F33FA8E0012A315 /* CKKSControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF7A8A21F0450EB00CABE89 /* CKKSControlProtocol.m */; }; - DC93C4C5214713C5008F8362 /* libaks_mock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC36895E21235F42003A3735 /* libaks_mock.a */; }; - DC93C4CA214713E5008F8362 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; - DC93C4CB214713ED008F8362 /* libaks_mock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC36895E21235F42003A3735 /* libaks_mock.a */; }; - DC93C4D021471FD8008F8362 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; DC93F02922387A010072720A /* OTSOSUpdatePreapprovalsOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC93F02722387A010072720A /* OTSOSUpdatePreapprovalsOperation.h */; }; DC93F02A22387A010072720A /* OTSOSUpdatePreapprovalsOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC93F02822387A010072720A /* OTSOSUpdatePreapprovalsOperation.m */; }; + DC947E8524638320005B8669 /* CKKSCheckKeyHierarchyOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC947E832463831F005B8669 /* CKKSCheckKeyHierarchyOperation.m */; }; DC94BCCA1F10448600E07CEB /* CloudKitCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = DC94BCC81F10448600E07CEB /* CloudKitCategories.h */; }; DC94BCCC1F10448600E07CEB /* CloudKitCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = DC94BCC91F10448600E07CEB /* CloudKitCategories.m */; }; DC96053F1ECA2D6400AF9BDA /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = 107226D00D91DB32003CF14F /* SecTask.c */; }; @@ -4192,6 +4212,9 @@ DC963E821D95EC1C008A153E /* libsecurity_codesigning.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = DCD068CB1D8CDFFE007602F1 /* libsecurity_codesigning.plist */; }; DC963E841D95EC31008A153E /* libsecurity_codesigning.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = DCD068CC1D8CDFFE007602F1 /* libsecurity_codesigning.txt */; }; DC963EC61D95F646008A153E /* der_plist.h in Headers */ = {isa = PBXBuildFile; fileRef = 524492931AFD6D480043695A /* der_plist.h */; }; + DC9978B82404AA3200A5EE2F /* Container_UserSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */; }; + DC9978B92404AA3200A5EE2F /* Container_UserSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */; }; + DC9978BB2404B26900A5EE2F /* Container_UserSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */; }; DC99B86B20EACA470065B73B /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; DC99B86C20EACA470065B73B /* FakeCuttlefish.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA8557F20B5DC7D00D5AD11 /* FakeCuttlefish.swift */; }; DC99B86D20EACA470065B73B /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; @@ -4219,7 +4242,6 @@ DC99B88A20EACA470065B73B /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; DC99B88B20EACA470065B73B /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; DC9A2C5F1EB3F557008FAC27 /* CKKSTests+Coalesce.m in Sources */ = {isa = PBXBuildFile; fileRef = DC9A2C5E1EB3F556008FAC27 /* CKKSTests+Coalesce.m */; }; - DC9A2C7F1EB40A76008FAC27 /* OCMock.framework in Embed OCMock */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; DC9C06692149DFE400C6F7B8 /* OTAuthKitAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = DC9C06672149DFE400C6F7B8 /* OTAuthKitAdapter.h */; }; DC9C066B2149DFE400C6F7B8 /* OTAuthKitAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC9C06682149DFE400C6F7B8 /* OTAuthKitAdapter.m */; }; DC9C066D2149E33D00C6F7B8 /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; @@ -4242,12 +4264,18 @@ DCA4D1FF1E552DD50056214F /* CKKSCurrentKeyPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA4D1F41E5520550056214F /* CKKSCurrentKeyPointer.m */; }; DCA4D2151E5684220056214F /* CKKSReencryptOutgoingItemsOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCA4D2131E5684220056214F /* CKKSReencryptOutgoingItemsOperation.h */; }; DCA4D2171E5684220056214F /* CKKSReencryptOutgoingItemsOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA4D2141E5684220056214F /* CKKSReencryptOutgoingItemsOperation.m */; }; + DCA72AE12530D3BD00CCB062 /* CKKSKeychainViewState.h in Headers */ = {isa = PBXBuildFile; fileRef = DCA72ADF2530D3BD00CCB062 /* CKKSKeychainViewState.h */; }; + DCA72AE22530D3BD00CCB062 /* CKKSKeychainViewState.h in Headers */ = {isa = PBXBuildFile; fileRef = DCA72ADF2530D3BD00CCB062 /* CKKSKeychainViewState.h */; }; + DCA72AE42530D3BD00CCB062 /* CKKSKeychainViewState.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA72AE02530D3BD00CCB062 /* CKKSKeychainViewState.m */; }; + DCA72AE52530D3BD00CCB062 /* CKKSKeychainViewState.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA72AE02530D3BD00CCB062 /* CKKSKeychainViewState.m */; }; + DCA7F7EF23A44AA200927989 /* OctagonPolicyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA7F7EE23A44AA200927989 /* OctagonPolicyTests.swift */; }; DCA85B931E8D97E400BA7241 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; DCA85B941E8D97E400BA7241 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; DCA85B971E8D980200BA7241 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; DCA85B981E8D980A00BA7241 /* client_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC844AEC1E81F315007AAB71 /* client_endpoint.m */; }; DCA85B991E8D980B00BA7241 /* client_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC844AEC1E81F315007AAB71 /* client_endpoint.m */; }; DCA85B9B1E8D981200BA7241 /* client_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC844AEC1E81F315007AAB71 /* client_endpoint.m */; }; + DCA992AD2400BB99007959AF /* TPPBAncientEpoch.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373A820D810DA00DBDF5B /* TPPBAncientEpoch.proto */; }; DCA9BC02221B721E00B4EB26 /* CKKSCloudKitClassDependencies.h in Headers */ = {isa = PBXBuildFile; fileRef = DCA9BC00221B721D00B4EB26 /* CKKSCloudKitClassDependencies.h */; }; DCA9BC03221B721E00B4EB26 /* CKKSCloudKitClassDependencies.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA9BC01221B721E00B4EB26 /* CKKSCloudKitClassDependencies.m */; }; DCA9BC07221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA9BC06221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.m */; }; @@ -4259,6 +4287,10 @@ DCA9D84821FFEE9800B27421 /* EscrowRequestXPCProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA9D84521FFE7CF00B27421 /* EscrowRequestXPCProtocol.m */; }; DCA9D84D21FFF04700B27421 /* EscrowRequestServer.h in Headers */ = {isa = PBXBuildFile; fileRef = DCA9D84B21FFF04600B27421 /* EscrowRequestServer.h */; }; DCA9D84E21FFF04700B27421 /* EscrowRequestServer.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA9D84C21FFF04700B27421 /* EscrowRequestServer.m */; }; + DCAA209A23AAF8F600DCB594 /* Container_RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */; }; + DCAA209B23AAF8FD00DCB594 /* Container_RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */; }; + DCAA209C23AAF93700DCB594 /* Container_RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */; }; + DCAAF3362493F9C600D4EB55 /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EAFA4CD1EF16059002DC188 /* LocalAuthentication.framework */; }; DCAB14271E40039600C81511 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; DCAB17CE21FFF75B00E1DFCF /* MockSynchronousEscrowServer.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAB17CC21FFF6C400E1DFCF /* MockSynchronousEscrowServer.m */; }; DCAB17D12200D26900E1DFCF /* SecEscrowPendingRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = DCAB17CF2200D26700E1DFCF /* SecEscrowPendingRecord.h */; }; @@ -4457,7 +4489,6 @@ DCB342FB1D8A32A20054D16E /* SecBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342441D8A32A20054D16E /* SecBase.cpp */; }; DCB342FC1D8A32A20054D16E /* SecBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB342451D8A32A20054D16E /* SecBridge.h */; }; DCB342FD1D8A32A20054D16E /* SecCertificate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342461D8A32A20054D16E /* SecCertificate.cpp */; }; - DCB342FE1D8A32A20054D16E /* SecCertificateBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342471D8A32A20054D16E /* SecCertificateBundle.cpp */; }; DCB343001D8A32A20054D16E /* SecIdentity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342491D8A32A20054D16E /* SecIdentity.cpp */; }; DCB343011D8A32A20054D16E /* SecIdentitySearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB3424A1D8A32A20054D16E /* SecIdentitySearch.cpp */; }; DCB343021D8A32A20054D16E /* SecItemConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = DCB3424B1D8A32A20054D16E /* SecItemConstants.c */; }; @@ -4508,7 +4539,6 @@ DCB3435A1D8A32A20054D16E /* PolicyCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB342A51D8A32A20054D16E /* PolicyCursor.h */; }; DCB3435B1D8A32A20054D16E /* SecCFTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342A61D8A32A20054D16E /* SecCFTypes.cpp */; }; DCB3435C1D8A32A20054D16E /* SecCFTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB342A71D8A32A20054D16E /* SecCFTypes.h */; }; - DCB3435D1D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342A81D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp */; }; DCB3435E1D8A32A20054D16E /* StorageManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342AA1D8A32A20054D16E /* StorageManager.cpp */; }; DCB3435F1D8A32A20054D16E /* Trust.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342AB1D8A32A20054D16E /* Trust.cpp */; }; DCB343601D8A32A20054D16E /* Trust.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB342AC1D8A32A20054D16E /* Trust.h */; }; @@ -4623,9 +4653,7 @@ DCB344A01D8A35270054D16E /* kc-40-seckey.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB3446B1D8A35270054D16E /* kc-40-seckey.m */; }; DCB344A11D8A35270054D16E /* kc-41-sececkey.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB3446C1D8A35270054D16E /* kc-41-sececkey.m */; }; DCB344A21D8A35270054D16E /* kc-43-seckey-interop.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB3446D1D8A35270054D16E /* kc-43-seckey-interop.m */; }; - DCB344A31D8A35270054D16E /* kc-42-trust-revocation.c in Sources */ = {isa = PBXBuildFile; fileRef = DCB3446E1D8A35270054D16E /* kc-42-trust-revocation.c */; }; - DCB344A41D8A35270054D16E /* si-20-sectrust-provisioning.c in Sources */ = {isa = PBXBuildFile; fileRef = DCB3446F1D8A35270054D16E /* si-20-sectrust-provisioning.c */; }; - DCB344A51D8A35270054D16E /* si-20-sectrust-provisioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB344701D8A35270054D16E /* si-20-sectrust-provisioning.h */; }; + DCB344A41D8A35270054D16E /* si-20-certificate-copy-values.c in Sources */ = {isa = PBXBuildFile; fileRef = DCB3446F1D8A35270054D16E /* si-20-certificate-copy-values.c */; }; DCB344A61D8A35270054D16E /* si-33-keychain-backup.c in Sources */ = {isa = PBXBuildFile; fileRef = DCB344711D8A35270054D16E /* si-33-keychain-backup.c */; }; DCB344A71D8A35270054D16E /* si-34-one-true-keychain.c in Sources */ = {isa = PBXBuildFile; fileRef = DCB344721D8A35270054D16E /* si-34-one-true-keychain.c */; }; DCB41DF1216C2DBB00F219E0 /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; @@ -4635,13 +4663,9 @@ DCB4584C2240396E00115F8C /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; DCB468DF20EC25FF00BA7E5B /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE55C77B2044D0C90045863D /* Client.swift */; }; DCB468E520EC262C00BA7E5B /* ContainerMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F8D18206C4AD300B53D16 /* ContainerMap.swift */; }; - DCB515DE1ED3CF86001F1152 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; - DCB515DF1ED3CF95001F1152 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; - DCB515E01ED3D111001F1152 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; - DCB515E11ED3D11A001F1152 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; - DCB515E21ED3D134001F1152 /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = 107226D00D91DB32003CF14F /* SecTask.c */; }; - DCB515E31ED3D135001F1152 /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = 107226D00D91DB32003CF14F /* SecTask.c */; }; - DCB515E41ED3D15A001F1152 /* client_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC844AEC1E81F315007AAB71 /* client_endpoint.m */; }; + DCB55175247F48290009A859 /* CKKSDeleteCKZoneOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB55173247F48290009A859 /* CKKSDeleteCKZoneOperation.h */; }; + DCB55176247F48290009A859 /* CKKSDeleteCKZoneOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB55174247F48290009A859 /* CKKSDeleteCKZoneOperation.m */; }; + DCB55177247F483D0009A859 /* CKKSCreateCKZoneOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB5516B247F3DB50009A859 /* CKKSCreateCKZoneOperation.m */; }; DCB5D93B1E4A9A3400BE22AB /* CKKSSynchronizeOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB5D9391E4A9A3400BE22AB /* CKKSSynchronizeOperation.h */; }; DCB5D93D1E4A9A3400BE22AB /* CKKSSynchronizeOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB5D93A1E4A9A3400BE22AB /* CKKSSynchronizeOperation.m */; }; DCB7D8C31D8E181B00867385 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD06AB01D8E0D53007602F1 /* libsecurity_utilities.a */; }; @@ -4653,6 +4677,7 @@ DCB9475621274A1900ED9272 /* TPHObjcTranslation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB9475421274A1900ED9272 /* TPHObjcTranslation.m */; }; DCB9475821274F9D00ED9272 /* TPHObjcTranslation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB9475421274A1900ED9272 /* TPHObjcTranslation.m */; }; DCB9475A2127534C00ED9272 /* OctagonTests+SOSUpgrade.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB947592127534C00ED9272 /* OctagonTests+SOSUpgrade.swift */; }; + DCBA6F2924105399009A5187 /* CKKSTests+ForwardCompatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBA6F2824105399009A5187 /* CKKSTests+ForwardCompatibility.m */; }; DCBB8AC41D80DD95007ED154 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; DCBDB3B71E57C82300B61300 /* CKKSKeychainView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBDB3B11E57C67500B61300 /* CKKSKeychainView.m */; }; DCBDB3BB1E57CA7A00B61300 /* CKKSViewManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DCBDB3B91E57CA7A00B61300 /* CKKSViewManager.h */; }; @@ -4667,7 +4692,6 @@ DCBF4ABA21FFC82100539F0A /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; DCBF4ABB21FFC82100539F0A /* SecFramework.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E4F1D8085FC00865A7C /* SecFramework.c */; }; DCBF4ABE21FFC82100539F0A /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; - DCBF4AC121FFC82100539F0A /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; DCBF4AC221FFC82100539F0A /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; DCBF4AC321FFC82100539F0A /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF4C19C171E0EA600877419 /* Accounts.framework */; }; DCBF4AC421FFC82100539F0A /* AppleAccount.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C84DA541720698900AEE225 /* AppleAccount.framework */; }; @@ -4693,6 +4717,8 @@ DCBF4AE521FFC9B300539F0A /* SecEscrowRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBF4AE321FFC9A800539F0A /* SecEscrowRequestTests.m */; }; DCBFF832222611A200C5C044 /* OTFetchCKKSKeysOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCBFF830222611A200C5C044 /* OTFetchCKKSKeysOperation.h */; }; DCBFF833222611A200C5C044 /* OTFetchCKKSKeysOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBFF831222611A200C5C044 /* OTFetchCKKSKeysOperation.m */; }; + DCC03FA423FF521100A4DA3F /* TPSyncingPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC03FA223FF521100A4DA3F /* TPSyncingPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DCC03FA523FF521100A4DA3F /* TPSyncingPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC03FA323FF521100A4DA3F /* TPSyncingPolicy.m */; }; DCC093791D80B02100F984E4 /* SecOnOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC78E671D8085FC00865A7C /* SecOnOSX.h */; }; DCC0937A1D80B07200F984E4 /* SecOTRSessionPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFFC15AFB73800B9D400 /* SecOTRSessionPriv.h */; }; DCC0937B1D80B07B00F984E4 /* SecOTRSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFFB15AFB73800B9D400 /* SecOTRSession.h */; }; @@ -4703,7 +4729,8 @@ DCC093801D80B0B700F984E4 /* SecCFAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = D47F514B1C3B812500A7CEFE /* SecCFAllocator.h */; }; DCC19518214C53FD00C9E0B6 /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; DCC1951C214C668A00C9E0B6 /* AppleAccount.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C84DA541720698900AEE225 /* AppleAccount.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - DCC19F711EB9151B00B7D70F /* KeychainCKKS.plist in Copy BATS Test Discovery Plist */ = {isa = PBXBuildFile; fileRef = 6CB5F4781E402E5700DBF3F0 /* KeychainCKKS.plist */; }; + DCC40B112383786D00402CB9 /* CKKSStates.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC40B0F2383786D00402CB9 /* CKKSStates.h */; }; + DCC40B122383786D00402CB9 /* CKKSStates.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC40B102383786D00402CB9 /* CKKSStates.m */; }; DCC51C99209B7C1500A40387 /* print_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA951D80CC2A00B0A59C /* print_cert.c */; }; DCC54181225C05180095D926 /* OTUploadNewCKKSTLKsOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */; }; DCC54182225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */; }; @@ -4774,7 +4801,11 @@ DCC78EE51D808B2100865A7C /* SecBase64.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E351D8085FC00865A7C /* SecBase64.c */; }; DCC78EE61D808B2A00865A7C /* SecAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E301D8085FC00865A7C /* SecAccessControl.m */; }; DCC78EE71D808B2F00865A7C /* secViewDisplay.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D9E1D8085F200865A7C /* secViewDisplay.c */; }; - DCCA5E841E539EE7009EE93D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCCA5E831E539EE7009EE93D /* AppKit.framework */; }; + DCC8856E2548E9FB004B0DB4 /* SecKnownFilePaths.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC8856D2548E9FB004B0DB4 /* SecKnownFilePaths.m */; }; + DCC8856F2548E9FB004B0DB4 /* SecKnownFilePaths.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC8856D2548E9FB004B0DB4 /* SecKnownFilePaths.m */; }; + DCC887252548EB3B004B0DB4 /* SecKnownFilePaths.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC887242548EB3B004B0DB4 /* SecKnownFilePaths.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DCC887262548EB3B004B0DB4 /* SecKnownFilePaths.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC887242548EB3B004B0DB4 /* SecKnownFilePaths.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DCC888DB2548EC2B004B0DB4 /* SecFileLocations.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC6D1D8C68CF00070CB0 /* SecFileLocations.c */; }; DCCBFA1E1DBA95CD001DD54D /* kc-20-item-delete-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = DCCBFA1D1DBA95CD001DD54D /* kc-20-item-delete-stress.c */; }; DCCBFA391DBAE445001DD54D /* SecInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6416F00BB357D5001C83FD /* SecInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; DCCD33C91E3FE95900AA4AD1 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; @@ -5192,6 +5223,10 @@ DCD66DE21D8205FB00DB1393 /* SecOTRPublicIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E741D8085FC00865A7C /* SecOTRPublicIdentity.c */; }; DCD66DE31D8205FB00DB1393 /* SecOTRSession.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E751D8085FC00865A7C /* SecOTRSession.c */; }; DCD66DE41D8205FB00DB1393 /* SecOTRSessionAKE.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E771D8085FC00865A7C /* SecOTRSessionAKE.c */; }; + DCD689DF255A0AF600C2A1BA /* OctagonStateMachineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD689DD255A0AE300C2A1BA /* OctagonStateMachineTests.swift */; }; + DCD68B9D255A149300C2A1BA /* CKKSMockLockStateProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD68B9C255A149300C2A1BA /* CKKSMockLockStateProvider.m */; }; + DCD68B9E255A149300C2A1BA /* CKKSMockLockStateProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD68B9C255A149300C2A1BA /* CKKSMockLockStateProvider.m */; }; + DCD68F18255A1C1400C2A1BA /* CKKSMockLockStateProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD68B9C255A149300C2A1BA /* CKKSMockLockStateProvider.m */; }; DCD6C4B21EC5302500414FEE /* CKKSNearFutureScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD6C4B01EC5302400414FEE /* CKKSNearFutureScheduler.h */; }; DCD6C4B41EC5302500414FEE /* CKKSNearFutureScheduler.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD6C4B11EC5302500414FEE /* CKKSNearFutureScheduler.m */; }; DCD6C4B71EC5319600414FEE /* CKKSNearFutureSchedulerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD6C4B61EC5319600414FEE /* CKKSNearFutureSchedulerTests.m */; }; @@ -5265,6 +5300,8 @@ DCD8A20A1E09FB5900E4FA0A /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; settings = {ATTRIBUTES = (Weak, ); }; }; DCD8A20B1E09FB5A00E4FA0A /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; DCD8A20C1E09FB6600E4FA0A /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; + DCDACB5924A3F38E0054080C /* com.apple.security.ckks.plist in Copy Logging Files */ = {isa = PBXBuildFile; fileRef = DCDACB5724A3F1AA0054080C /* com.apple.security.ckks.plist */; }; + DCDACB5A24A3F39A0054080C /* com.apple.security.ckks.plist in Copy Logging Files */ = {isa = PBXBuildFile; fileRef = DCDACB5724A3F1AA0054080C /* com.apple.security.ckks.plist */; }; DCDB296C1FD8820400B5D242 /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; DCDB296E1FD8821400B5D242 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; DCDB29701FD8821800B5D242 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; @@ -5273,9 +5310,6 @@ DCDB29791FD8844C00B5D242 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; DCDB297A1FD8845600B5D242 /* client_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC844AEC1E81F315007AAB71 /* client_endpoint.m */; }; DCDB297B1FD8847100B5D242 /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = 107226D00D91DB32003CF14F /* SecTask.c */; }; - DCDB297C1FD8848A00B5D242 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; - DCDB297D1FD8849A00B5D242 /* SFSQLiteStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BF1F152EB10082882F /* SFSQLiteStatement.m */; }; - DCDB297E1FD8849D00B5D242 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; DCDCC7E31D9B54EE006487E8 /* secd-202-recoverykey.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDCC7DD1D9B54DF006487E8 /* secd-202-recoverykey.m */; }; DCDCC7E51D9B5526006487E8 /* SOSAccountSync.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDCC7E41D9B551C006487E8 /* SOSAccountSync.m */; }; DCDCC8331D9B6A00006487E8 /* libcoretls.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CFC029B1D41650700E6283B /* libcoretls.dylib */; }; @@ -5285,7 +5319,7 @@ DCDCCB391DF25D18006E840E /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA311DEE768000D0F733 /* CloudKit.framework */; }; DCDCCB3A1DF25D1D006E840E /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA231DEE36FE00D0F733 /* ApplePushService.framework */; }; DCDCCB3B1DF25D69006E840E /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA311DEE768000D0F733 /* CloudKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - DCDCCB3C1DF25D74006E840E /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA231DEE36FE00D0F733 /* ApplePushService.framework */; }; + DCDCCB3C1DF25D74006E840E /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA231DEE36FE00D0F733 /* ApplePushService.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; DCDCCB3E1DF25DA0006E840E /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA231DEE36FE00D0F733 /* ApplePushService.framework */; }; DCDCCB8F1DF7B8D4006E840E /* CKKSItem.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDCCB8D1DF7B8D4006E840E /* CKKSItem.h */; }; DCDCCB901DF7B8D4006E840E /* CKKSItem.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDCCB8E1DF7B8D4006E840E /* CKKSItem.m */; }; @@ -5300,7 +5334,6 @@ DCE0774321ADD635002662FD /* TPPBPeerDynamicInfo.proto in Sources */ = {isa = PBXBuildFile; fileRef = BE7089CB1FA3B19A001ACC20 /* TPPBPeerDynamicInfo.proto */; }; DCE0774621ADD638002662FD /* TPPBDisposition.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC3739B20CF2AA200DBDF5B /* TPPBDisposition.proto */; }; DCE0774721ADD63A002662FD /* TPPBDispositionEntry.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373C120D8224A00DBDF5B /* TPPBDispositionEntry.proto */; }; - DCE0774821ADD63C002662FD /* TPPBAncientEpoch.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373A820D810DA00DBDF5B /* TPPBAncientEpoch.proto */; }; DCE0774921ADD63E002662FD /* TPPBPolicyProhibits.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373A620D810D800DBDF5B /* TPPBPolicyProhibits.proto */; }; DCE0774A21ADD640002662FD /* TPPBUnknownMachineID.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373A720D810D900DBDF5B /* TPPBUnknownMachineID.proto */; }; DCE0774B21ADD642002662FD /* TPPBPeerStableInfo.proto in Sources */ = {isa = PBXBuildFile; fileRef = BE7089CC1FA3B332001ACC20 /* TPPBPeerStableInfo.proto */; }; @@ -5342,6 +5375,7 @@ DCE278DF1ED789EF0083B485 /* CKKSCurrentItemPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE278DC1ED789EF0083B485 /* CKKSCurrentItemPointer.m */; }; DCE278E81ED7A5B40083B485 /* CKKSUpdateCurrentItemPointerOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCE278E61ED7A5B40083B485 /* CKKSUpdateCurrentItemPointerOperation.h */; }; DCE278EA1ED7A5B40083B485 /* CKKSUpdateCurrentItemPointerOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE278E71ED7A5B40083B485 /* CKKSUpdateCurrentItemPointerOperation.m */; }; + DCE405C523A04A7F00C4343B /* OctagonTests+CKKSConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCE405C423A04A7F00C4343B /* OctagonTests+CKKSConfiguration.swift */; }; DCE4E6921D7A37FA00AFB96E /* security_tool_commands.c in Sources */ = {isa = PBXBuildFile; fileRef = E7104A0B169E171900DB0045 /* security_tool_commands.c */; }; DCE4E6931D7A37FA00AFB96E /* NSFileHandle+Formatting.m in Sources */ = {isa = PBXBuildFile; fileRef = E78A9AD91D34959200006B5B /* NSFileHandle+Formatting.m */; }; DCE4E6961D7A37FA00AFB96E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E43C48C1B00D07000E5ECB2 /* CoreFoundation.framework */; }; @@ -5357,69 +5391,10 @@ DCE4E7541D7A43B500AFB96E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; DCE4E75E1D7A43B500AFB96E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E43C48C1B00D07000E5ECB2 /* CoreFoundation.framework */; }; DCE4E7681D7A43B500AFB96E /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; - DCE4E76D1D7A43B500AFB96E /* nist-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4D886E81CEBDD2A00DC7583 /* nist-certs */; }; - DCE4E7721D7A43B500AFB96E /* Invalid-asterisk.google.com.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - DCE4E7731D7A43B500AFB96E /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - DCE4E7741D7A43B500AFB96E /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - DCE4E7751D7A43B500AFB96E /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - DCE4E7761D7A43B500AFB96E /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - DCE4E7771D7A43B500AFB96E /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - DCE4E7781D7A43B500AFB96E /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - DCE4E7791D7A43B500AFB96E /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - DCE4E77A1D7A43B500AFB96E /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - DCE4E77B1D7A43B500AFB96E /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; - DCE4E77C1D7A43B500AFB96E /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; - DCE4E77D1D7A43B500AFB96E /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; - DCE4E77E1D7A43B500AFB96E /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; - DCE4E77F1D7A43B500AFB96E /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; - DCE4E7801D7A43B500AFB96E /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; - DCE4E7811D7A43B500AFB96E /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; - DCE4E7821D7A43B500AFB96E /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; - DCE4E7831D7A43B500AFB96E /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - DCE4E7851D7A43B500AFB96E /* Invalid-asterisk.google.com.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - DCE4E7861D7A43B500AFB96E /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - DCE4E7871D7A43B500AFB96E /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - DCE4E7881D7A43B500AFB96E /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - DCE4E7891D7A43B500AFB96E /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - DCE4E78A1D7A43B500AFB96E /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - DCE4E78B1D7A43B500AFB96E /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - DCE4E78C1D7A43B500AFB96E /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - DCE4E78D1D7A43B500AFB96E /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - DCE4E78E1D7A43B500AFB96E /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; - DCE4E78F1D7A43B500AFB96E /* diginotar.root.ca-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */; }; - DCE4E7901D7A43B500AFB96E /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; - DCE4E7911D7A43B500AFB96E /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; - DCE4E7921D7A43B500AFB96E /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; - DCE4E7931D7A43B500AFB96E /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; - DCE4E7941D7A43B500AFB96E /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; - DCE4E7951D7A43B500AFB96E /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; - DCE4E7961D7A43B500AFB96E /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; - DCE4E7971D7A43B500AFB96E /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - DCE4E7991D7A43B500AFB96E /* DigiNotarCA2007RootCertificate.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */; }; - DCE4E79A1D7A43B500AFB96E /* DigiNotar_Root_CA_G2-RootCertificate.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */; }; - DCE4E79B1D7A43B500AFB96E /* Invalid-asterisk.google.com.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - DCE4E79C1D7A43B500AFB96E /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - DCE4E79D1D7A43B500AFB96E /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - DCE4E79E1D7A43B500AFB96E /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - DCE4E79F1D7A43B500AFB96E /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - DCE4E7A01D7A43B500AFB96E /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - DCE4E7A11D7A43B500AFB96E /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - DCE4E7A21D7A43B500AFB96E /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - DCE4E7A31D7A43B500AFB96E /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - DCE4E7A41D7A43B500AFB96E /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; - DCE4E7A51D7A43B500AFB96E /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; - DCE4E7A61D7A43B500AFB96E /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - DCE4E7A71D7A43B500AFB96E /* Expectations.plist in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = 4C50AD2F1410689300EE92DE /* Expectations.plist */; }; - DCE4E7A91D7A43B500AFB96E /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */; }; - DCE4E7AA1D7A43B500AFB96E /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */; }; - DCE4E7AB1D7A43B500AFB96E /* Invalid-webmail.jaring.my.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */; }; - DCE4E7AC1D7A43B500AFB96E /* Invalid-www.cybersecurity.my.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */; }; DCE4E7B51D7A43FF00AFB96E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE4E6D71D7A420D00AFB96E /* main.m */; }; - DCE4E7B61D7A440A00AFB96E /* bc-10-knife-on-bread.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE4E6D41D7A41E400AFB96E /* bc-10-knife-on-bread.m */; }; DCE4E7BF1D7A463400AFB96E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; DCE4E7C11D7A463E00AFB96E /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; DCE4E7C61D7A468300AFB96E /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EB2CA4D81D2C28C800AB770F /* libaks.a */; }; - DCE4E7DF1D7A4B4C00AFB96E /* bc-10-knife-on-bread.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE4E6D41D7A41E400AFB96E /* bc-10-knife-on-bread.m */; }; DCE4E7E21D7A4B7F00AFB96E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = DCE4E7E11D7A4B7F00AFB96E /* main.c */; }; DCE4E7E41D7A4B8F00AFB96E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D848541C6C1D9C0025BB44 /* Foundation.framework */; }; DCE4E7E71D7A4B9C00AFB96E /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789261D7799D300B50D50 /* IOKit.framework */; }; @@ -5509,7 +5484,6 @@ DCEA5D571E2826DB0089CF55 /* CKKSSIV.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D541E2826DB0089CF55 /* CKKSSIV.m */; }; DCEA5D851E2F14810089CF55 /* OctagonAPSReceiver.h in Headers */ = {isa = PBXBuildFile; fileRef = DCEA5D831E2F14810089CF55 /* OctagonAPSReceiver.h */; }; DCEA5D871E2F14810089CF55 /* OctagonAPSReceiver.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D841E2F14810089CF55 /* OctagonAPSReceiver.m */; }; - DCEA5D971E3015830089CF55 /* CKKSZone.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D961E3014250089CF55 /* CKKSZone.m */; }; DCEDE3511D80B0FA00C3826E /* secd-71-engine-save-sample1.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC78C651D8085D800865A7C /* secd-71-engine-save-sample1.h */; }; DCEDE3901D80B10100C3826E /* SecOTRIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFF615AFB73800B9D400 /* SecOTRIdentityPriv.h */; }; DCEDE3911D80B10800C3826E /* SecCTKKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC78E451D8085FC00865A7C /* SecCTKKeyPriv.h */; }; @@ -5518,6 +5492,8 @@ DCEDE3941D80B11800C3826E /* SecPasswordGenerate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDE9BC31729AB910013B0E8 /* SecPasswordGenerate.h */; }; DCEDE3961D80B12600C3826E /* SecTrustInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC78E921D8085FC00865A7C /* SecTrustInternal.h */; }; DCEE1E861D93427400DC0EB7 /* com.apple.securityd.plist in Resources */ = {isa = PBXBuildFile; fileRef = DCE4E80D1D7A4E3A00AFB96E /* com.apple.securityd.plist */; }; + DCF0C435256347BB007D5A6A /* CKKSMemoryKeyCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF0C432256347B7007D5A6A /* CKKSMemoryKeyCache.m */; }; + DCF0C436256347BB007D5A6A /* CKKSMemoryKeyCache.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF0C434256347B8007D5A6A /* CKKSMemoryKeyCache.h */; }; DCF12673218A757A000124C6 /* OTLeaveCliqueOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF12671218A7579000124C6 /* OTLeaveCliqueOperation.h */; }; DCF12674218A757A000124C6 /* OTLeaveCliqueOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF12672218A757A000124C6 /* OTLeaveCliqueOperation.m */; }; DCF216DE21ADD5F90029CCC1 /* CKKSSerializedKey.proto in Sources */ = {isa = PBXBuildFile; fileRef = DC4D49D81F857728007AF2B8 /* CKKSSerializedKey.proto */; }; @@ -5843,7 +5819,6 @@ DCF94A7C222D9F2400C01744 /* OctagonCKKSPeerAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF94A7A222D9F2400C01744 /* OctagonCKKSPeerAdapter.m */; }; DCFABF8E20081E2F001128B5 /* CKKSDeviceStateUploadTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFABF8D20081E2F001128B5 /* CKKSDeviceStateUploadTests.m */; }; DCFAEDCF1D999859005187E4 /* SOSAccountGhost.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFAEDC81D999851005187E4 /* SOSAccountGhost.m */; }; - DCFAEDD21D99991F005187E4 /* secd-668-ghosts.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFAEDD11D9998DD005187E4 /* secd-668-ghosts.m */; }; DCFAEDD61D99A47A005187E4 /* secd-36-ks-encrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFAEDD51D99A464005187E4 /* secd-36-ks-encrypt.m */; }; DCFAEDD71D99A4AB005187E4 /* secd-154-engine-backoff.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C771D8085D800865A7C /* secd-154-engine-backoff.m */; }; DCFB12C51E95A4C000510F5F /* CKKSAccountStateTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = DCFB12C31E95A4C000510F5F /* CKKSAccountStateTracker.h */; }; @@ -5933,7 +5908,6 @@ E7F482961C74FDF800390FDB /* KCJoiningSession.h in Headers */ = {isa = PBXBuildFile; fileRef = E7F480131C7397CE00390FDB /* KCJoiningSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; E7F482A11C7543E500390FDB /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; E7F482A31C7544E600390FDB /* libctkclient_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7F482A21C7544E600390FDB /* libctkclient_test.a */; }; - E7F482A61C75453900390FDB /* libcoreauthd_test_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7F482A51C75453900390FDB /* libcoreauthd_test_client.a */; }; E7F482AA1C7554FB00390FDB /* NSError+KCCreationHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = E7F482A91C7554F500390FDB /* NSError+KCCreationHelpers.m */; }; E7F482AC1C7558F700390FDB /* KCJoiningAcceptSession.m in Sources */ = {isa = PBXBuildFile; fileRef = E7F482AB1C7558F700390FDB /* KCJoiningAcceptSession.m */; }; E7F482E61C7640D300390FDB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; @@ -5950,34 +5924,7 @@ EB0E1ADA2357627F002B6037 /* CKKSPBFileStorageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EB0E1AD723576273002B6037 /* CKKSPBFileStorageTests.m */; }; EB0E1B912358FAC6002B6037 /* SOSAccountConfiguration.proto in Sources */ = {isa = PBXBuildFile; fileRef = EB0E1AC72352A81E002B6037 /* SOSAccountConfiguration.proto */; }; EB0E1B942358FAF3002B6037 /* SOSAccountConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = EB0E1B932358FADE002B6037 /* SOSAccountConfiguration.m */; }; - EB0F4A2C22F7D3DC009E855B /* OCMock.framework in Embedd OCMock */ = {isa = PBXBuildFile; fileRef = 47D1838B1FB3827700CFCD89 /* OCMock.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; EB1055791E14DF570003C309 /* SecCertificateFuzzer.c in Sources */ = {isa = PBXBuildFile; fileRef = EB10556B1E14DC0F0003C309 /* SecCertificateFuzzer.c */; }; - EB1055831E14E1F90003C309 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */; }; - EB1055841E14E1F90003C309 /* Invalid-www.cybersecurity.my.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */; }; - EB1055851E14E1F90003C309 /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */; }; - EB1055861E14E1F90003C309 /* Invalid-webmail.jaring.my.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */; }; - EB1055871E14E2060003C309 /* DigiNotar_Root_CA_G2-RootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */; }; - EB1055881E14E2060003C309 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; - EB1055891E14E2060003C309 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; - EB10558A1E14E2060003C309 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; - EB10558B1E14E2060003C309 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; - EB10558C1E14E2060003C309 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; - EB10558D1E14E2060003C309 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEF1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */; }; - EB10558E1E14E2060003C309 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; - EB10558F1E14E2060003C309 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; - EB1055901E14E2060003C309 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; - EB1055921E14E2060003C309 /* DigiNotarCA2007RootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */; }; - EB1055931E14E2060003C309 /* Invalid-asterisk.google.com.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; - EB1055941E14E2060003C309 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; - EB1055951E14E2060003C309 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; - EB1055961E14E2060003C309 /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; - EB1055971E14E2060003C309 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; - EB1055981E14E2060003C309 /* diginotar-public-ca-2025-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; - EB1055991E14E2060003C309 /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; - EB10559A1E14E2060003C309 /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; - EB10559B1E14E2060003C309 /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; - EB10559C1E14E2060003C309 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; - EB10559D1E14E2060003C309 /* diginotar.root.ca-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */; }; EB10559E1E14E39D0003C309 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E43C48C1B00D07000E5ECB2 /* CoreFoundation.framework */; }; EB10559F1E14E3A80003C309 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; EB108F261E6CE4D2003B0456 /* KCPairingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = EB413B7E1E663A8300592085 /* KCPairingTest.m */; }; @@ -6023,8 +5970,6 @@ EB49B2C2202DF002003F34A0 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246911F9AE2E400D63882 /* libDER.a */; }; EB49B2C7202DF0E9003F34A0 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; EB49B2CD202DF0F9003F34A0 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; - EB49B2D0202DF14D003F34A0 /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; - EB49B2D1202DF15F003F34A0 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; EB49B2D2202DF17D003F34A0 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; EB49B2D3202DF1AC003F34A0 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; EB49B2D5202DF1D8003F34A0 /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = 107226D00D91DB32003CF14F /* SecTask.c */; }; @@ -6035,15 +5980,12 @@ EB49B2DD202DF259003F34A0 /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EB49B2DC202DF251003F34A0 /* libbsm.tbd */; }; EB49B2E0202DF5D7003F34A0 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; EB49B308202FF421003F34A0 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47D1838B1FB3827700CFCD89 /* OCMock.framework */; }; - EB4B6E201DC0682A00AFC494 /* SecADWrapper.c in Sources */ = {isa = PBXBuildFile; fileRef = EBF3749A1DC064200065D840 /* SecADWrapper.c */; }; - EB4B6E261DC0683600AFC494 /* SecADWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = EBF3749B1DC064200065D840 /* SecADWrapper.h */; }; EB4E0CDB1FF36A9700CDCACC /* CKKSReachabilityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = EB4E0CD51FF36A1900CDCACC /* CKKSReachabilityTracker.m */; }; EB58A0511E74BF07009C10D7 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; EB59D6731E95F01600997EAC /* libcompression.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EB59D66B1E95EF2900997EAC /* libcompression.dylib */; }; EB5E3BCC2003C67A00F1631B /* SecSignpost.h in Headers */ = {isa = PBXBuildFile; fileRef = EB5E3BC62003C66300F1631B /* SecSignpost.h */; settings = {ATTRIBUTES = (Private, ); }; }; EB5E3BCD2003C67B00F1631B /* SecSignpost.h in Headers */ = {isa = PBXBuildFile; fileRef = EB5E3BC62003C66300F1631B /* SecSignpost.h */; settings = {ATTRIBUTES = (Private, ); }; }; EB627A73233E339200F32437 /* MockAKSOptionalParameters.proto in Sources */ = {isa = PBXBuildFile; fileRef = EB627A6F233E323600F32437 /* MockAKSOptionalParameters.proto */; }; - EB627A79233E375A00F32437 /* MockAKSOptionalParameters.proto in Sources */ = {isa = PBXBuildFile; fileRef = EB627A6F233E323600F32437 /* MockAKSOptionalParameters.proto */; }; EB627A7E233E3C1300F32437 /* MockAKSOptionalParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = EB627A77233E342B00F32437 /* MockAKSOptionalParameters.m */; }; EB627A7F233E3C1600F32437 /* MockAKSRefKey.m in Sources */ = {isa = PBXBuildFile; fileRef = EB627A75233E342800F32437 /* MockAKSRefKey.m */; }; EB6667C7204CD69F000B404F /* testPlistDER.m in Sources */ = {isa = PBXBuildFile; fileRef = EB6667BE204CD65E000B404F /* testPlistDER.m */; }; @@ -6106,13 +6048,10 @@ EB75B48C1E75407C00E469CC /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; EB75B48D1E75408900E469CC /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; EB75B48F1E75409A00E469CC /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; - EB75B4901E7540AA00E469CC /* libctkclient_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDC1AA0A45C0021AA26 /* libctkclient_test.a */; }; - EB75B4911E7540BF00E469CC /* libcoreauthd_test_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E8B53A41AA0B8A600345E7B /* libcoreauthd_test_client.a */; }; EB75B4951E75A44100E469CC /* SOSPiggyback.h in Headers */ = {isa = PBXBuildFile; fileRef = EB75B4931E75A44100E469CC /* SOSPiggyback.h */; }; EB76B7591DCB0CA200C43FBC /* CloudKeychainProxy.8 in Install man8 page */ = {isa = PBXBuildFile; fileRef = DC24B5851DA432E900330B48 /* CloudKeychainProxy.8 */; }; EB7732C221963B0500FCF513 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; EB7732D921963BA500FCF513 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EB80DE57219600CF005B10FA /* libz.dylib */; }; - EB7732DB21963BC100FCF513 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; EB78D3F91E600E93009AFE05 /* SOSCloudCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D891D8085F200865A7C /* SOSCloudCircle.m */; }; EB7AE6F81E86DACC00B80B15 /* SecPLWrappers.m in Sources */ = {isa = PBXBuildFile; fileRef = EB7AE6F61E86D55400B80B15 /* SecPLWrappers.m */; }; EB7AE6F91E86DAD200B80B15 /* SecPLWrappers.h in Headers */ = {isa = PBXBuildFile; fileRef = EB7AE6F71E86D55400B80B15 /* SecPLWrappers.h */; }; @@ -6180,11 +6119,7 @@ EB8908BA21F1957300F0DDDB /* SecAKSObjCWrappers.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF9D218A16F80012C5DA /* SecAKSObjCWrappers.m */; }; EB8908BE21F2181600F0DDDB /* SFKeychainControlManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 473337781FDAFBCC00E19F30 /* SFKeychainControlManager.m */; }; EB8A9381233C900D0015A794 /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; - EB973651234E8F4B00518B2B /* CKKSPBFileStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = EB97364F234E8F4A00518B2B /* CKKSPBFileStorage.h */; }; - EB973652234E8F4B00518B2B /* CKKSPBFileStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = EB973650234E8F4B00518B2B /* CKKSPBFileStorage.m */; }; EB9795B522FE9256002BDBFB /* SecItemTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EB6D1D5322FE8D3000205E83 /* SecItemTests.m */; }; - EB9B283321C7755700173DC2 /* OTDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8BBE971FC9DA5A00580909 /* OTDefines.h */; settings = {ATTRIBUTES = (Private, ); }; }; - EB9B283421C7755800173DC2 /* OTDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8BBE971FC9DA5A00580909 /* OTDefines.h */; settings = {ATTRIBUTES = (Private, ); }; }; EB9B285721C77C8D00173DC2 /* OTDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = EBCE06E521C6E26000FB1493 /* OTDefines.m */; }; EB9B285821C77C8D00173DC2 /* OTDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = EBCE06E521C6E26000FB1493 /* OTDefines.m */; }; EB9C02481E8A15B40040D3C6 /* secd-37-pairing-initial-sync.m in Sources */ = {isa = PBXBuildFile; fileRef = EB9C02421E8A112A0040D3C6 /* secd-37-pairing-initial-sync.m */; }; @@ -6194,6 +6129,10 @@ EBA9AA811CE30E58004E2B68 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; EBA9AA821CE30E58004E2B68 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; EBA9AA871CE30E6F004E2B68 /* secitemnotifications.m in Sources */ = {isa = PBXBuildFile; fileRef = EBA9AA7C1CE30CE7004E2B68 /* secitemnotifications.m */; }; + EBAFC9AF2551C2700034B78D /* legacyCodeRegressions.mm in Sources */ = {isa = PBXBuildFile; fileRef = EBAFC9AE2551C2700034B78D /* legacyCodeRegressions.mm */; }; + EBAFD2592551CDA40034B78D /* libsecurity_cdsa_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCB341821D8A2B860054D16E /* libsecurity_cdsa_utilities.a */; }; + EBAFD25A2551CDA40034B78D /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD06AB01D8E0D53007602F1 /* libsecurity_utilities.a */; }; + EBAFDBB92551CFD20034B78D /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; EBB02A6A2220649F007241CB /* KeychainSettingsCKKSViews.plist in Resources */ = {isa = PBXBuildFile; fileRef = EBB02A56221FF362007241CB /* KeychainSettingsCKKSViews.plist */; }; EBB02A702220ED26007241CB /* CKKSLaunchSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = EBB02A6D2220ED16007241CB /* CKKSLaunchSequence.m */; }; EBB0315822223AAF007241CB /* CKKSLaunchSequenceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EBB03155222237A7007241CB /* CKKSLaunchSequenceTests.m */; }; @@ -6209,12 +6148,6 @@ EBB852D022F7A13D00424FD0 /* SecInternalRelease.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC761D8C68CF00070CB0 /* SecInternalRelease.c */; }; EBC1024422EBF93E0083D356 /* CKKSTests+LockStateTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = EBC1023022EBF8AC0083D356 /* CKKSTests+LockStateTracker.m */; }; EBC15B1D1DB432F800126882 /* com.apple.secd.sb in Copy Sandbox profile */ = {isa = PBXBuildFile; fileRef = EBC15B1B1DB4306C00126882 /* com.apple.secd.sb */; }; - EBC73F2020993F8600AE3350 /* SFAnalyticsSQLiteStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */; }; - EBC73F2720993FC900AE3350 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; - EBC73F2820993FDA00AE3350 /* SFAnalyticsSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */; }; - EBC73F29209966AF00AE3350 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; - EBC73F2A20996AD400AE3350 /* SFSQLiteStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BF1F152EB10082882F /* SFSQLiteStatement.m */; }; - EBC73F2B2099785900AE3350 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; EBCC31B1228CF0FD000AF5D9 /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; EBCF73F71CE45F9C00BED7CA /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; EBCF73F81CE45F9C00BED7CA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; @@ -6223,7 +6156,6 @@ EBD531772198AF19003A57E6 /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF4C19C171E0EA600877419 /* Accounts.framework */; }; EBDAA7E920EC4838003EA6E5 /* SecurityLocalKeychain.plist in Install BATS plist */ = {isa = PBXBuildFile; fileRef = EBDAA7E320EC46CF003EA6E5 /* SecurityLocalKeychain.plist */; }; EBDAF15D21C75FF200EAE89F /* NSXPCConnectionMock.h in Headers */ = {isa = PBXBuildFile; fileRef = EBDAF15B21C75FF200EAE89F /* NSXPCConnectionMock.h */; }; - EBDCC001233DD3E000806566 /* MockAKSRefKey.proto in Sources */ = {isa = PBXBuildFile; fileRef = EBDCBFFE233DD31700806566 /* MockAKSRefKey.proto */; }; EBDCC002233DD45700806566 /* MockAKSRefKey.proto in Sources */ = {isa = PBXBuildFile; fileRef = EBDCBFFE233DD31700806566 /* MockAKSRefKey.proto */; }; EBDE5E0E22BA3DE900A229C8 /* CKKSMockOctagonAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = EBDE5DFA22BA3D5D00A229C8 /* CKKSMockOctagonAdapter.m */; }; EBDE5E0F22BA3DEA00A229C8 /* CKKSMockOctagonAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = EBDE5DFA22BA3D5D00A229C8 /* CKKSMockOctagonAdapter.m */; }; @@ -6257,13 +6189,21 @@ F667EC611E96E9E700203D5C /* authdtests.m in Sources */ = {isa = PBXBuildFile; fileRef = F6A0971F1E953ABD00B1E7D6 /* authdtests.m */; }; F667EC621E96EAD200203D5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F667EC551E96E94800203D5C /* main.m */; }; F667EC631E96EDC500203D5C /* libregressionBase.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCBFD1D8C648C00070CB0 /* libregressionBase.a */; }; + F67B93C3254707E10076CA99 /* fvunlock.m in Sources */ = {isa = PBXBuildFile; fileRef = F67B93C1254707E00076CA99 /* fvunlock.m */; }; + F67B93C525470D7E0076CA99 /* fvunlock.h in Headers */ = {isa = PBXBuildFile; fileRef = F67B93C425470D7D0076CA99 /* fvunlock.h */; }; + F67B93C72547301F0076CA99 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + F681C3AB2386B8C30083F22C /* PreloginUserDb.m in Sources */ = {isa = PBXBuildFile; fileRef = F681C3A82386B8B40083F22C /* PreloginUserDb.m */; }; F682C1D41F4486F700F1B029 /* libctkloginhelper.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F682C1CE1F4486F600F1B029 /* libctkloginhelper.a */; }; F6AF96681E646CAF00917214 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; }; + F6B1B48B24144B5F00CB3E3F /* libctkloginhelperlite.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B1B48924144B5E00CB3E3F /* libctkloginhelperlite.a */; }; F6EEF76F21675E8000FB7F79 /* AuthorizationTrampolinePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D600702166551800F9F7C9 /* AuthorizationTrampolinePriv.h */; }; F6EEF77521675EF000FB7F79 /* AuthorizationTrampolinePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D600702166551800F9F7C9 /* AuthorizationTrampolinePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F6F4105324AC622F00369037 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EB2CA4D81D2C28C800AB770F /* libaks.a */; }; F964772C1E5832540019E4EB /* SecCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD0678E1D8CDF7E007602F1 /* SecCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; F9F77E98223C2F9A00E5CBF6 /* requirement.c in Sources */ = {isa = PBXBuildFile; fileRef = F9F77E96223C2F7B00E5CBF6 /* requirement.c */; }; F9F77E99223C2F9A00E5CBF6 /* requirement.h in Headers */ = {isa = PBXBuildFile; fileRef = F9F77E97223C2F7C00E5CBF6 /* requirement.h */; }; + FC63722F237B5D1C00973738 /* SecItemServer+SWC.m in Sources */ = {isa = PBXBuildFile; fileRef = FC63722A237B5CF900973738 /* SecItemServer+SWC.m */; }; + FC637231237B5D2200973738 /* SecItemServer+SWC.m in Sources */ = {isa = PBXBuildFile; fileRef = FC63722A237B5CF900973738 /* SecItemServer+SWC.m */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ @@ -6277,10 +6217,9 @@ ); isEditable = 1; outputFiles = ( - "$(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).exp", + "$(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).$(CURRENT_ARCH).exp", ); - runOncePerArchitecture = 0; - script = "#!/bin/sh\n\nfor file in ${HEADER_SEARCH_PATHS[@]} ; do\nHEADER_SEARCH_OPTIONS=\"${HEADER_SEARCH_OPTIONS} -I${file}\"\ndone\n\nfor prep in ${GCC_PREPROCESSOR_DEFINITIONS[@]} ; do\nPREPROCESSOR=\"${PREPROCESSOR} -D${prep}\"\ndone\n\nxcrun clang -E -Xpreprocessor -P -x objective-c ${HEADER_SEARCH_OPTIONS} ${OTHER_INPUT_FILE_FLAGS} ${PREPROCESSOR} ${INPUT_FILE_PATH} -o \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.exp\"\n"; + script = "#!/bin/sh\n\nfor file in ${HEADER_SEARCH_PATHS[@]} ; do\nHEADER_SEARCH_OPTIONS=\"${HEADER_SEARCH_OPTIONS} -I${file}\"\ndone\n\nfor prep in ${GCC_PREPROCESSOR_DEFINITIONS[@]} ; do\nPREPROCESSOR=\"${PREPROCESSOR} -D${prep}\"\ndone\n\nxcrun clang -E -Xpreprocessor -P -x objective-c -arch ${CURRENT_ARCH} ${HEADER_SEARCH_OPTIONS} ${OTHER_INPUT_FILE_FLAGS} ${PREPROCESSOR} ${INPUT_FILE_PATH} -o \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.${CURRENT_ARCH}.exp\"\n"; }; DCF216DD21ADD5D10029CCC1 /* PBXBuildRule */ = { isa = PBXBuildRule; @@ -6329,6 +6268,20 @@ remoteGlobalIDString = DC0BCC211D8C684F00070CB0; remoteInfo = utilities; }; + 0C2B36C223C42EBC00000718 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CD743A523C3EC8000FA0EC5; + remoteInfo = Clique; + }; + 0C2B36C423C42EC800000718 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CD743A523C3EC8000FA0EC5; + remoteInfo = Clique; + }; 0C2BCBBB1D0640B200ED7A2F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6343,19 +6296,19 @@ remoteGlobalIDString = 0C2BCBBD1D0648D100ED7A2F; remoteInfo = dtlsEchoServer; }; - 0C3E2EA82073F5C400F5B95B /* PBXContainerItemProxy */ = { + 0C65BB4C23C3F31B0063D2B7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 4C32C0AE0A4975F6002891BD; - remoteInfo = Security_ios; + remoteGlobalIDString = 0CD743A523C3EC8000FA0EC5; + remoteInfo = Clique; }; - 0C5663ED20BE2E1A0035F362 /* PBXContainerItemProxy */ = { + 0C65BB4E23C3F3270063D2B7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DC0BCC211D8C684F00070CB0; - remoteInfo = utilities; + remoteGlobalIDString = 0CD743A523C3EC8000FA0EC5; + remoteInfo = Clique; }; 0C78CCE41FCC97E7008B4B24 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -6371,6 +6324,20 @@ remoteGlobalIDString = 0C8BBEFD1FCB446400580909; remoteInfo = otctl; }; + 0C7EB14C23F3D13C0089097B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; + remoteInfo = aks_support; + }; + 0C7EB14E23F3D1480089097B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC0BCC211D8C684F00070CB0; + remoteInfo = utilities; + }; 0C85DFD91FB38BB6000343A7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6406,12 +6373,19 @@ remoteGlobalIDString = DCC78EA81D8088E200865A7C; remoteInfo = security; }; - 0C9AEEB920783FE000BF6237 /* PBXContainerItemProxy */ = { + 0CA378E823876E0900090B7E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DC1789031D77980500B50D50; - remoteInfo = Security_osx; + remoteGlobalIDString = 0CA378E123876DD100090B7E; + remoteInfo = reset_account; + }; + 0CA378EA23876E1000090B7E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CA378E123876DD100090B7E; + remoteInfo = reset_account; }; 0CC593F72299EDFC006C34B5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -6420,6 +6394,48 @@ remoteGlobalIDString = DC52E7731D80BC8000B0A59C; remoteInfo = libsecurityd_ios; }; + 0CCC22AA23F38B0600E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; + remoteInfo = SecureObjectSyncServer; + }; + 0CCC22AC23F38B0E00E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC52E7731D80BC8000B0A59C; + remoteInfo = libsecurityd_ios; + }; + 0CCC22CD23F39A6300E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCC220023F357EE00E1FCD0; + remoteInfo = OctagonTrustTests; + }; + 0CCC22CF23F39A6A00E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCC220023F357EE00E1FCD0; + remoteInfo = OctagonTrustTests; + }; + 0CCC22D123F39A7500E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCC220023F357EE00E1FCD0; + remoteInfo = OctagonTrustTests; + }; + 0CCC22D323F39A7C00E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCC220023F357EE00E1FCD0; + remoteInfo = OctagonTrustTests; + }; 0CF0920F219649DB002B0AEE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6476,6 +6492,20 @@ remoteGlobalIDString = DC0BCC211D8C684F00070CB0; remoteInfo = utilities; }; + 3E4D531E2531185D00B124B3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3E4D49B32531170600B124B3; + remoteInfo = secsecstaticcodeapitest; + }; + 3E88361C24F08F5400E9F4D6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3E88360824F068EF00E9F4D6; + remoteInfo = secseccodeapitest; + }; 438169E61B4EE4B300C54D58 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6539,27 +6569,6 @@ remoteGlobalIDString = 4771D971209A755800BA9772; remoteInfo = KeychainDataclassOwner; }; - 478D426E1FD72A8100CAB645 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52EDA61D80D58400B0A59C; - remoteInfo = secdRegressions; - }; - 478D42701FD72A8100CAB645 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC0BCBD91D8C648C00070CB0; - remoteInfo = regressionBase; - }; - 478D42741FD72A8100CAB645 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCC78EA81D8088E200865A7C; - remoteInfo = security; - }; 47A6FC69206B461700BD6C54 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6567,13 +6576,6 @@ remoteGlobalIDString = DC52E7731D80BC8000B0A59C; remoteInfo = libsecurityd_ios; }; - 47A6FC6B206B462400BD6C54 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E7731D80BC8000B0A59C; - remoteInfo = libsecurityd_ios; - }; 47C2F18B2059CBEA0062DE30 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6609,13 +6611,6 @@ remoteGlobalIDString = DC1789031D77980500B50D50; remoteInfo = Security_osx; }; - 47D991CF20407F7E0078CAE2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4727FBB61F9918580003AE36; - remoteInfo = secdxctests_ios; - }; 47DE88CD1FA7AD6200DD3254 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6665,6 +6660,62 @@ remoteGlobalIDString = 5346480017331E1100FE9172; remoteInfo = KeychainSyncAccountNotification; }; + 5AAE383523D261CF0025CF9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5A442F81233C330F00918373; + remoteInfo = experimentTool; + }; + 6C14CA0323C4F6830097B572 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4718AE2E205B39C40068EC3F; + remoteInfo = libsecurityd_bridge; + }; + 6C16258023C4FFC40086A0FF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D4ADA3181E2B41670031CEA3; + remoteInfo = libtrustd; + }; + 6C16258323C4FFD40086A0FF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; + remoteInfo = SecureObjectSyncFramework; + }; + 6C16258523C4FFD40086A0FF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; + remoteInfo = SecureObjectSyncServer; + }; + 6C2045F72424BC4400F9461D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6C2045E92424BA7E00F9461D; + remoteInfo = KeychainStasher; + }; + 6C2D797222C06CEB00C3CE32 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6C39234421F13E4D00D018AD; + remoteInfo = SecDbBackupTests; + }; + 6C2D797422C06CEF00C3CE32 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4727FBB61F9918580003AE36; + remoteInfo = secdxctests; + }; 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6672,96 +6723,33 @@ remoteGlobalIDString = EB9C1DAE1BDFD4DE00F89272; remoteInfo = SecurityBatsTests; }; - 6C8FF4B5224C1A9800E5C812 /* PBXContainerItemProxy */ = { + 6C61D3E7242A29BA008AB9BB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = BEF88C271EAFFC3F00357577; - remoteInfo = TrustedPeers; + remoteGlobalIDString = 6C963280242A279B00C53CE2; + remoteInfo = stashtester; }; - 6C9808301E788AEB00E70590 /* PBXContainerItemProxy */ = { + 6C7BE2AB23C3DD64003BB2CA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DC8834011D8A218F00CE0ACA; - remoteInfo = ASN1_not_installed; + remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; + remoteInfo = aks_support; }; - 6C9808321E788AEB00E70590 /* PBXContainerItemProxy */ = { + 6C7BE2AD23C3DD64003BB2CA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; remoteGlobalIDString = DC0BCC211D8C684F00070CB0; remoteInfo = utilities; }; - 6C9808361E788AEB00E70590 /* PBXContainerItemProxy */ = { + 6C7BE2E923C3DD9C003BB2CA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; - remoteInfo = SecureObjectSyncFramework; - }; - 6C9808381E788AEB00E70590 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; - remoteInfo = SecureObjectSyncServer; - }; - 6C98083A1E788AEB00E70590 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCC78EA81D8088E200865A7C; - remoteInfo = security; - }; - 6C98086C1E788AFD00E70590 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC8834011D8A218F00CE0ACA; - remoteInfo = ASN1_not_installed; - }; - 6C98086E1E788AFD00E70590 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC0BCC211D8C684F00070CB0; - remoteInfo = utilities; - }; - 6C9808721E788AFD00E70590 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; - remoteInfo = SecureObjectSyncFramework; - }; - 6C9808741E788AFD00E70590 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; - remoteInfo = SecureObjectSyncServer; - }; - 6C9808761E788AFD00E70590 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCC78EA81D8088E200865A7C; - remoteInfo = security; - }; - 6C98089F1E788B9400E70590 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6CF4A0B31E45488B00ECD7B5; - remoteInfo = KeychainEntitledTestApp_mac; - }; - 6C9808A31E788CB100E70590 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6CF4A0DF1E4549F200ECD7B5; - remoteInfo = KeychainEntitledTestApp_ios; + remoteGlobalIDString = 6C7BE2A923C3DD64003BB2CA; + remoteInfo = securitytool_bridge; }; 6C9A49B11FAB647D00239D58 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -6770,6 +6758,13 @@ remoteGlobalIDString = DC0BCC211D8C684F00070CB0; remoteInfo = utilities; }; + 6CA9690C24ACC5C100C08B5E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC0BCC211D8C684F00070CB0; + remoteInfo = utilities; + }; 6CAA8D3C1F8431BC007B6E03 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6784,6 +6779,76 @@ remoteGlobalIDString = 6CAA8D1F1F842FB3007B6E03; remoteInfo = supd; }; + 6CC638E6226695B900E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; + remoteInfo = SecureObjectSyncServer; + }; + 6CC638E8226695B900E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; + remoteInfo = SecureObjectSyncFramework; + }; + 6CC638EA226695C300E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; + remoteInfo = SecureObjectSyncServer; + }; + 6CC638EC226695C300E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; + remoteInfo = SecureObjectSyncFramework; + }; + 6CC638FD2266AE0A00E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4727FBB61F9918580003AE36; + remoteInfo = secdxctests; + }; + 6CC638FF2266AE0A00E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6C39234421F13E4D00D018AD; + remoteInfo = SecDbBackupTests; + }; + 6CE2AEAA22B2C1BE00C96AE7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6CF4A0B31E45488B00ECD7B5; + remoteInfo = "KeychainEntitledTestApp-mac"; + }; + 6CE2AEAC22B2C1C300C96AE7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6CF4A0B31E45488B00ECD7B5; + remoteInfo = "KeychainEntitledTestApp-mac"; + }; + 6CF33CA52387156600D1E75D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4727FBB61F9918580003AE36; + remoteInfo = secdxctests; + }; + 6CF33CA72387157200D1E75D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4727FBB61F9918580003AE36; + remoteInfo = secdxctests; + }; 873C14B121540FED003C9C00 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6826,6 +6891,13 @@ remoteGlobalIDString = 5346480017331E1100FE9172; remoteInfo = KeychainSyncAccountNotification; }; + A695605F2580540F00BDF83F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCD067561D8CDCF3007602F1; + remoteInfo = codesigning_DTrace; + }; ACBAF6FD1E941E090007BA2F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6973,6 +7045,13 @@ remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; remoteInfo = aks_support; }; + D445C1F1258C147A0019858E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D445B30B258C07FC0019858E; + remoteInfo = trustdFileHelper; + }; D453A4A62122236D00850A26 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7176,13 +7255,6 @@ remoteGlobalIDString = 6CCDF7831E3C25FA003F2555; remoteInfo = KeychainEntitledTestRunner; }; - D45D8F832224DBEF00D6C124 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6C9808681E788AFD00E70590; - remoteInfo = CKKSCloudKitTests_ios; - }; D45D8F852224DBF800D6C124 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7330,13 +7402,6 @@ remoteGlobalIDString = BEF88C2F1EAFFC3F00357577; remoteInfo = TrustedPeersTests; }; - D477EE8221ED48E800C9AAFF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 478D426C1FD72A8100CAB645; - remoteInfo = secdxctests_mac; - }; D4794E6A21222E72007C6725 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7379,20 +7444,6 @@ remoteGlobalIDString = DC3502B41E0208BE00BC0587; remoteInfo = CKKSTests; }; - D4A763DA2224BDAB0063B2B9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6C98082C1E788AEB00E70590; - remoteInfo = CKKSCloudKitTests_mac; - }; - D4A763DC2224BDCC0063B2B9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6CF4A0B31E45488B00ECD7B5; - remoteInfo = KeychainEntitledTestApp_mac; - }; D4A763DE2224BDDC0063B2B9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7666,20 +7717,6 @@ remoteGlobalIDString = 47702B2D1E5F492C00B29577; remoteInfo = seckeychainnetworkextensionunauthorizedaccesstest; }; - D4E0E9752224DE9100A802E0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4727FBB61F9918580003AE36; - remoteInfo = secdxctests_ios; - }; - D4E0E9792224DEE600A802E0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6CF4A0DF1E4549F200ECD7B5; - remoteInfo = KeychainEntitledTestApp_ios; - }; D4E0E97B2224DF0300A802E0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7841,13 +7878,6 @@ remoteGlobalIDString = 47702B2D1E5F492C00B29577; remoteInfo = seckeychainnetworkextensionunauthorizedaccesstest; }; - D4E0E9AB2224DFEB00A802E0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4727FBB61F9918580003AE36; - remoteInfo = secdxctests_ios; - }; D4E0E9AD2224E00600A802E0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -8681,27 +8711,6 @@ remoteGlobalIDString = DC52E7731D80BC8000B0A59C; remoteInfo = libsecurityd_ios; }; - DC34CD2C20326C2C00302481 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; - remoteInfo = SecureObjectSyncServer; - }; - DC34CD3320326C3100302481 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; - remoteInfo = SecureObjectSyncFramework; - }; - DC34CD3520326C3B00302481 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC0BCC211D8C684F00070CB0; - remoteInfo = utilities; - }; DC3502C31E020D4D00BC0587 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -8968,13 +8977,6 @@ remoteGlobalIDString = BEAA0040202B728B00E51F45; remoteInfo = Security_executables_Swift; }; - DC65E7211D8CB27900152EF0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC0BCC211D8C684F00070CB0; - remoteInfo = iOSutilities; - }; DC65E7251D8CB2E100152EF0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -9220,13 +9222,6 @@ remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; remoteInfo = aks_support; }; - DC69A5862165298500512BD6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; - remoteInfo = aks_support; - }; DC6BC2731D90D07800DD57B3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -9332,20 +9327,6 @@ remoteGlobalIDString = DC8834011D8A218F00CE0ACA; remoteInfo = ASN1_not_installed; }; - DC93C4C8214713DC008F8362 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E7731D80BC8000B0A59C; - remoteInfo = libsecurityd_ios; - }; - DC93C4CC21471401008F8362 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E7731D80BC8000B0A59C; - remoteInfo = libsecurityd_ios; - }; DC99B85D20EACA470065B73B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -9696,20 +9677,6 @@ remoteGlobalIDString = DCD66DC41D8205C400DB1393; remoteInfo = libSecOtrOSX; }; - DCD6BF5321E919610015F7A8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; - remoteInfo = aks_support; - }; - DCD6BF5521E9196E0015F7A8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; - remoteInfo = aks_support; - }; DCD6BF5721E919820015F7A8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -9843,6 +9810,13 @@ remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; remoteInfo = aks_support; }; + DCE27860245B81BD00381FE8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4771D971209A755800BA9772; + remoteInfo = KeychainDataclassOwner; + }; DCE4E8D71D7F37F200AFB96E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -10228,6 +10202,13 @@ remoteGlobalIDString = EBA9AA7D1CE30E58004E2B68; remoteInfo = secitemnotifications; }; + EBAFDD6E2551D0550034B78D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EBAFC9AB2551C26F0034B78D; + remoteInfo = SecLegacyCodeRegressions; + }; EBB8520F22F793A200424FD0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -10277,20 +10258,6 @@ remoteGlobalIDString = DC0BC5501D8B6D2D00070CB0; remoteInfo = XPCKeychainSandboxCheck; }; - EBD7DF8021FF475B0089F2DF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; - remoteInfo = SecureObjectSyncServer; - }; - EBD7DF8221FF475B0089F2DF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; - remoteInfo = SecureObjectSyncFramework; - }; EBF374811DC058B60065D840 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -10385,25 +10352,15 @@ name = "Copy System logging profile"; runOnlyForDeploymentPostprocessing = 1; }; - 0C9AEEB320783FBB00BF6237 /* Embed OCMock */ = { + 0CA378E623876DEC00090B7E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; + buildActionMask = 8; + dstPath = /usr/local/bin; + dstSubfolderSpec = 0; files = ( + 0CA378E723876DFC00090B7E /* reset_ick_account in CopyFiles */, ); - name = "Embed OCMock"; - runOnlyForDeploymentPostprocessing = 0; - }; - 0CF4064A2072E3E3003D6A7F /* Embed OCMock */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed OCMock"; - runOnlyForDeploymentPostprocessing = 0; + runOnlyForDeploymentPostprocessing = 1; }; 3D58394821890FFB000ACA44 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -10499,175 +10456,12 @@ dstPath = /System/Library/Preferences/Logging/Subsystems; dstSubfolderSpec = 0; files = ( + DCDACB5A24A3F39A0054080C /* com.apple.security.ckks.plist in Copy Logging Files */, DC71D8F51D959F150065FB93 /* com.apple.securityd.plist in Copy Logging Files */, ); name = "Copy Logging Files"; runOnlyForDeploymentPostprocessing = 1; }; - 4C50AD081410673800EE92DE /* Copy DigiNotar Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = DigiNotar; - dstSubfolderSpec = 7; - files = ( - 4C50AD0C1410679000EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar Resources */, - 4C50AD0D1410679000EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar Resources */, - 4C50AD0E1410679000EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar Resources */, - 4C50AD0F1410679000EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar Resources */, - 4C50AD101410679000EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar Resources */, - 4C50AD111410679000EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar Resources */, - 4C50AD121410679000EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar Resources */, - 4C50AD131410679000EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar Resources */, - 4C50AD141410679000EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar Resources */, - 4C50AD151410679000EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar Resources */, - 4C8B91C91416ED7E00A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar Resources */, - 4C8B91CA1416ED7E00A254E2 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar Resources */, - 4C8B91CB1416ED7E00A254E2 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar Resources */, - 4C8B91CC1416ED7E00A254E2 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar Resources */, - 4C8B91CD1416ED7E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar Resources */, - 4C8B91CF1416ED7E00A254E2 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar Resources */, - 4C8B91D01416ED7E00A254E2 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar Resources */, - 4C8B91D11416ED7E00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar Resources */, - ); - name = "Copy DigiNotar Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; - 4C50AD091410675400EE92DE /* Copy DigiNotar-Entrust Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "DigiNotar-Entrust"; - dstSubfolderSpec = 7; - files = ( - 4C50AD181410679900EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD191410679900EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD1A1410679900EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD1B1410679900EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD1C1410679900EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD1D1410679900EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD1E1410679900EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD1F1410679900EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD201410679900EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD211410679900EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD221410679900EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C8B91D21416ED8E00A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-Entrust Resources */, - 4C8B91D31416ED8E00A254E2 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C8B91D41416ED8E00A254E2 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar-Entrust Resources */, - 4C8B91D51416ED8E00A254E2 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C8B91D61416ED8E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar-Entrust Resources */, - 4C8B91D81416ED8E00A254E2 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C8B91D91416ED8E00A254E2 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C8B91DA1416ED8E00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-Entrust Resources */, - ); - name = "Copy DigiNotar-Entrust Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; - 4C50AD0A1410676300EE92DE /* Copy DigiNotar-ok Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "DigiNotar-ok"; - dstSubfolderSpec = 7; - files = ( - 4C50AD23141067A100EE92DE /* DigiNotarCA2007RootCertificate.crt in Copy DigiNotar-ok Resources */, - 4C8B91E41416ED9A00A254E2 /* DigiNotar_Root_CA_G2-RootCertificate.crt in Copy DigiNotar-ok Resources */, - 4C50AD24141067A100EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar-ok Resources */, - 4C50AD25141067A100EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-ok Resources */, - 4C50AD26141067A100EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-ok Resources */, - 4C50AD27141067A100EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-ok Resources */, - 4C50AD28141067A100EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-ok Resources */, - 4C50AD29141067A100EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-ok Resources */, - 4C50AD2A141067A100EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-ok Resources */, - 4C50AD2B141067A100EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-ok Resources */, - 4C50AD2C141067A100EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-ok Resources */, - 4C50AD2D141067A100EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-ok Resources */, - 4C8B91DB1416ED9400A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-ok Resources */, - 4C8B91E31416ED9400A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-ok Resources */, - 4C50AD30141068C100EE92DE /* Expectations.plist in Copy DigiNotar-ok Resources */, - ); - name = "Copy DigiNotar-ok Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; - 4C50AD3414106A2900EE92DE /* Copy DigiNotar Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = DigiNotar; - dstSubfolderSpec = 7; - files = ( - 4C50AD3914106A4E00EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar Resources */, - 4C50AD3A14106A4E00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar Resources */, - 4C50AD3B14106A4E00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar Resources */, - 4C50AD3C14106A4E00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar Resources */, - 4C50AD3D14106A4E00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar Resources */, - 4C50AD3E14106A4E00EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar Resources */, - 4C50AD3F14106A4E00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar Resources */, - 4C50AD4014106A4E00EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar Resources */, - 4C50AD4114106A4E00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar Resources */, - 4C50AD4214106A4E00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar Resources */, - 4C3CECF41416E2EC00947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar Resources */, - 4C3CECF51416E2FA00947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar Resources */, - 4C3CECF61416E31A00947741 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar Resources */, - 4C3CECF81416E33500947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar Resources */, - 4C3CECF91416E34F00947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar Resources */, - 4C3CECFB1416E34F00947741 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar Resources */, - 4C3CECFC1416E34F00947741 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar Resources */, - 4C8B91C81416EBB500A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar Resources */, - ); - name = "Copy DigiNotar Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; - 4C50AD3514106A2B00EE92DE /* Copy DigiNotar-Entrust Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "DigiNotar-Entrust"; - dstSubfolderSpec = 7; - files = ( - 4C8B91C61416EB8B00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4614106A5000EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4714106A5000EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4814106A5000EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4914106A5000EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4A14106A5000EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4B14106A5000EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4C14106A5000EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4D14106A5000EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4E14106A5000EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD4F14106A5000EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C50AD5014106A5000EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C3CECFD1416E35400947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-Entrust Resources */, - 4C3CECFE1416E35400947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C3CECFF1416E35400947741 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar-Entrust Resources */, - 4C3CED001416E35400947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C3CED011416E35400947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar-Entrust Resources */, - 4C3CED031416E35400947741 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar-Entrust Resources */, - 4C3CED041416E35400947741 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar-Entrust Resources */, - ); - name = "Copy DigiNotar-Entrust Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; - 4C50AD3614106A2C00EE92DE /* Copy DigiNotar-ok Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "DigiNotar-ok"; - dstSubfolderSpec = 7; - files = ( - 4C50AD5114106A5400EE92DE /* Expectations.plist in Copy DigiNotar-ok Resources */, - 4C50AD5214106A5400EE92DE /* DigiNotarCA2007RootCertificate.crt in Copy DigiNotar-ok Resources */, - 4C3CECF31416E25C00947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt in Copy DigiNotar-ok Resources */, - 4C50AD5314106A5400EE92DE /* Invalid-asterisk.google.com.crt in Copy DigiNotar-ok Resources */, - 4C50AD5414106A5400EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-ok Resources */, - 4C50AD5514106A5400EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-ok Resources */, - 4C50AD5614106A5400EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-ok Resources */, - 4C50AD5714106A5400EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-ok Resources */, - 4C50AD5814106A5400EE92DE /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-ok Resources */, - 4C50AD5914106A5400EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-ok Resources */, - 4C50AD5A14106A5400EE92DE /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-ok Resources */, - 4C50AD5B14106A5400EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-ok Resources */, - 4C50AD5C14106A5400EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-ok Resources */, - 4C3CED051416E35A00947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-ok Resources */, - 4C8B91C71416EBA400A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-ok Resources */, - ); - name = "Copy DigiNotar-ok Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; 4C52D0B216EFC61E0079966E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -10699,6 +10493,28 @@ name = "Install man8 page"; runOnlyForDeploymentPostprocessing = 1; }; + 6C2045F32424BBB900F9461D /* Install Sandbox Profile */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/Sandbox/Profiles; + dstSubfolderSpec = 0; + files = ( + 6C2045F42424BBCD00F9461D /* com.apple.security.KeychainStasher.sb in Install Sandbox Profile */, + ); + name = "Install Sandbox Profile"; + runOnlyForDeploymentPostprocessing = 1; + }; + 6C2045FA2424BCC300F9461D /* Install LaunchAgent plist */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/LaunchAgents; + dstSubfolderSpec = 0; + files = ( + 6C2045FB2424BCD600F9461D /* com.apple.security.KeychainStasher.plist in Install LaunchAgent plist */, + ); + name = "Install LaunchAgent plist"; + runOnlyForDeploymentPostprocessing = 1; + }; 6C23F02E227A39FD009F6756 /* Install Sandbox Profile */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -10710,27 +10526,6 @@ name = "Install Sandbox Profile"; runOnlyForDeploymentPostprocessing = 1; }; - 6C4F981E2075831300A3C5AB /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 6C4F98252075833E00A3C5AB /* OCMock.framework in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6C7E8F1F21F7BE64008A2D56 /* Copy BATS Test Discovery Plist */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /AppleInternal/CoreOS/BATS/unit_tests; - dstSubfolderSpec = 0; - files = ( - 6C02135021F7EF07009D5C80 /* SecDbBackupTests.plist in Copy BATS Test Discovery Plist */, - ); - name = "Copy BATS Test Discovery Plist"; - runOnlyForDeploymentPostprocessing = 1; - }; 6C9AA79C1F7C1D8F00D08296 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -10751,34 +10546,6 @@ name = "Copy Manpage"; runOnlyForDeploymentPostprocessing = 1; }; - 79679E231462023800CF997F /* Copy DigiCertMalaysia Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = DigicertMalaysia; - dstSubfolderSpec = 7; - files = ( - 79679E29146202A800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in Copy DigiCertMalaysia Resources */, - 7947431E1462151E00D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in Copy DigiCertMalaysia Resources */, - 79679E2A146202A800CF997F /* Invalid-webmail.jaring.my.crt in Copy DigiCertMalaysia Resources */, - 7947431A146213DC00D638A3 /* Invalid-www.cybersecurity.my.crt in Copy DigiCertMalaysia Resources */, - ); - name = "Copy DigiCertMalaysia Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; - 79679E2B146202BC00CF997F /* Copy DigicertMalaysia Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = DigicertMalaysia; - dstSubfolderSpec = 7; - files = ( - 79679E2C146202CB00CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in Copy DigicertMalaysia Resources */, - 7947431D1462151400D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in Copy DigicertMalaysia Resources */, - 79679E2D146202CB00CF997F /* Invalid-webmail.jaring.my.crt in Copy DigicertMalaysia Resources */, - 7947431B146213EF00D638A3 /* Invalid-www.cybersecurity.my.crt in Copy DigicertMalaysia Resources */, - ); - name = "Copy DigicertMalaysia Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; 79863B6C0CADCE4300818B0D /* launchd plist */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -10790,6 +10557,16 @@ name = "launchd plist"; runOnlyForDeploymentPostprocessing = 1; }; + A695677C2581B46E00BDF83F /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /AppleInternal/CoreOS/tests/Security; + dstSubfolderSpec = 0; + files = ( + A695677D2581B47F00BDF83F /* unsigned_secstaticcodeapitest.sh in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; AA0DA47C21E818C1009F1C74 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -10885,6 +10662,39 @@ name = "Copy Open Source Licenses"; runOnlyForDeploymentPostprocessing = 1; }; + D445B30A258C07FC0019858E /* Install man8 page */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man8; + dstSubfolderSpec = 0; + files = ( + D445B853258C10E50019858E /* trustdFileHelper.8 in Install man8 page */, + ); + name = "Install man8 page"; + runOnlyForDeploymentPostprocessing = 1; + }; + D445BA12258C110A0019858E /* Copy Sandbox */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/Sandbox/Profiles; + dstSubfolderSpec = 0; + files = ( + D445BA13258C11230019858E /* com.apple.trustdFileHelper.sb in Copy Sandbox */, + ); + name = "Copy Sandbox"; + runOnlyForDeploymentPostprocessing = 1; + }; + D445BAF3258C11370019858E /* Copy LaunchDaemon Files */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/LaunchDaemons; + dstSubfolderSpec = 0; + files = ( + D445BAF4258C114F0019858E /* com.apple.trustdFileHelper.plist in Copy LaunchDaemon Files */, + ); + name = "Copy LaunchDaemon Files"; + runOnlyForDeploymentPostprocessing = 1; + }; D4ADA3111E2B209C0031CEA3 /* Install man8 page */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -11015,17 +10825,6 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - DC7162D41EB4154D000D2BB5 /* Copy BATS Test Discovery Plist */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /AppleInternal/CoreOS/BATS/unit_tests; - dstSubfolderSpec = 0; - files = ( - DCC19F711EB9151B00B7D70F /* KeychainCKKS.plist in Copy BATS Test Discovery Plist */, - ); - name = "Copy BATS Test Discovery Plist"; - runOnlyForDeploymentPostprocessing = 1; - }; DC7FC44F21EE9175003C39B8 /* Install Security FeatureFlags plist */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -11077,17 +10876,6 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - DC9A2C791EB40A64008FAC27 /* Embed OCMock */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - DC9A2C7F1EB40A76008FAC27 /* OCMock.framework in Embed OCMock */, - ); - name = "Embed OCMock"; - runOnlyForDeploymentPostprocessing = 0; - }; DCD0676D1D8CDEC1007602F1 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -11133,102 +10921,6 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - DCE4E7711D7A43B500AFB96E /* Copy DigiNotar Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = DigiNotar; - dstSubfolderSpec = 7; - files = ( - DCE4E7721D7A43B500AFB96E /* Invalid-asterisk.google.com.crt in Copy DigiNotar Resources */, - DCE4E7731D7A43B500AFB96E /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar Resources */, - DCE4E7741D7A43B500AFB96E /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar Resources */, - DCE4E7751D7A43B500AFB96E /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar Resources */, - DCE4E7761D7A43B500AFB96E /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar Resources */, - DCE4E7771D7A43B500AFB96E /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar Resources */, - DCE4E7781D7A43B500AFB96E /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar Resources */, - DCE4E7791D7A43B500AFB96E /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar Resources */, - DCE4E77A1D7A43B500AFB96E /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar Resources */, - DCE4E77B1D7A43B500AFB96E /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar Resources */, - DCE4E77C1D7A43B500AFB96E /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar Resources */, - DCE4E77D1D7A43B500AFB96E /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar Resources */, - DCE4E77E1D7A43B500AFB96E /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar Resources */, - DCE4E77F1D7A43B500AFB96E /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar Resources */, - DCE4E7801D7A43B500AFB96E /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar Resources */, - DCE4E7811D7A43B500AFB96E /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar Resources */, - DCE4E7821D7A43B500AFB96E /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar Resources */, - DCE4E7831D7A43B500AFB96E /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar Resources */, - ); - name = "Copy DigiNotar Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; - DCE4E7841D7A43B500AFB96E /* Copy DigiNotar-Entrust Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "DigiNotar-Entrust"; - dstSubfolderSpec = 7; - files = ( - DCE4E7851D7A43B500AFB96E /* Invalid-asterisk.google.com.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7861D7A43B500AFB96E /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7871D7A43B500AFB96E /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7881D7A43B500AFB96E /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7891D7A43B500AFB96E /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-Entrust Resources */, - DCE4E78A1D7A43B500AFB96E /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E78B1D7A43B500AFB96E /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E78C1D7A43B500AFB96E /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E78D1D7A43B500AFB96E /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E78E1D7A43B500AFB96E /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E78F1D7A43B500AFB96E /* diginotar.root.ca-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7901D7A43B500AFB96E /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7911D7A43B500AFB96E /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7921D7A43B500AFB96E /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7931D7A43B500AFB96E /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7941D7A43B500AFB96E /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7951D7A43B500AFB96E /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7961D7A43B500AFB96E /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar-Entrust Resources */, - DCE4E7971D7A43B500AFB96E /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-Entrust Resources */, - ); - name = "Copy DigiNotar-Entrust Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; - DCE4E7981D7A43B500AFB96E /* Copy DigiNotar-ok Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "DigiNotar-ok"; - dstSubfolderSpec = 7; - files = ( - DCE4E7991D7A43B500AFB96E /* DigiNotarCA2007RootCertificate.crt in Copy DigiNotar-ok Resources */, - DCE4E79A1D7A43B500AFB96E /* DigiNotar_Root_CA_G2-RootCertificate.crt in Copy DigiNotar-ok Resources */, - DCE4E79B1D7A43B500AFB96E /* Invalid-asterisk.google.com.crt in Copy DigiNotar-ok Resources */, - DCE4E79C1D7A43B500AFB96E /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-ok Resources */, - DCE4E79D1D7A43B500AFB96E /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-ok Resources */, - DCE4E79E1D7A43B500AFB96E /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-ok Resources */, - DCE4E79F1D7A43B500AFB96E /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-ok Resources */, - DCE4E7A01D7A43B500AFB96E /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-ok Resources */, - DCE4E7A11D7A43B500AFB96E /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-ok Resources */, - DCE4E7A21D7A43B500AFB96E /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-ok Resources */, - DCE4E7A31D7A43B500AFB96E /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-ok Resources */, - DCE4E7A41D7A43B500AFB96E /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-ok Resources */, - DCE4E7A51D7A43B500AFB96E /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-ok Resources */, - DCE4E7A61D7A43B500AFB96E /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-ok Resources */, - DCE4E7A71D7A43B500AFB96E /* Expectations.plist in Copy DigiNotar-ok Resources */, - ); - name = "Copy DigiNotar-ok Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; - DCE4E7A81D7A43B500AFB96E /* Copy DigiCertMalaysia Resources */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = DigicertMalaysia; - dstSubfolderSpec = 7; - files = ( - DCE4E7A91D7A43B500AFB96E /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in Copy DigiCertMalaysia Resources */, - DCE4E7AA1D7A43B500AFB96E /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in Copy DigiCertMalaysia Resources */, - DCE4E7AB1D7A43B500AFB96E /* Invalid-webmail.jaring.my.crt in Copy DigiCertMalaysia Resources */, - DCE4E7AC1D7A43B500AFB96E /* Invalid-www.cybersecurity.my.crt in Copy DigiCertMalaysia Resources */, - ); - name = "Copy DigiCertMalaysia Resources"; - runOnlyForDeploymentPostprocessing = 0; - }; DCE4E7F41D7A4DA800AFB96E /* Copy LaunchAgents files */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -11246,6 +10938,7 @@ dstPath = /System/Library/Preferences/Logging/Subsystems; dstSubfolderSpec = 0; files = ( + DCDACB5924A3F38E0054080C /* com.apple.security.ckks.plist in Copy Logging Files */, DCE4E80E1D7A4E3B00AFB96E /* com.apple.securityd.plist in Copy Logging Files */, ); name = "Copy Logging Files"; @@ -11393,49 +11086,12 @@ name = "Install BATS Tests"; runOnlyForDeploymentPostprocessing = 1; }; - EB0F4A2B22F7D3BD009E855B /* Embedd OCMock */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - EB0F4A2C22F7D3DC009E855B /* OCMock.framework in Embedd OCMock */, - ); - name = "Embedd OCMock"; - runOnlyForDeploymentPostprocessing = 0; - }; EB1055801E14DFE40003C309 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; dstPath = "$(SECURITY_FUZZER_BASE_DIR)/data/$(TARGET_NAME)"; dstSubfolderSpec = 0; files = ( - EB1055831E14E1F90003C309 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in CopyFiles */, - EB1055841E14E1F90003C309 /* Invalid-www.cybersecurity.my.crt in CopyFiles */, - EB1055851E14E1F90003C309 /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in CopyFiles */, - EB1055861E14E1F90003C309 /* Invalid-webmail.jaring.my.crt in CopyFiles */, - EB1055871E14E2060003C309 /* DigiNotar_Root_CA_G2-RootCertificate.crt in CopyFiles */, - EB1055881E14E2060003C309 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */, - EB1055891E14E2060003C309 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */, - EB10558A1E14E2060003C309 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */, - EB10558B1E14E2060003C309 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */, - EB10558C1E14E2060003C309 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */, - EB10558D1E14E2060003C309 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */, - EB10558E1E14E2060003C309 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */, - EB10558F1E14E2060003C309 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */, - EB1055901E14E2060003C309 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */, - EB1055921E14E2060003C309 /* DigiNotarCA2007RootCertificate.crt in CopyFiles */, - EB1055931E14E2060003C309 /* Invalid-asterisk.google.com.crt in CopyFiles */, - EB1055941E14E2060003C309 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */, - EB1055951E14E2060003C309 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */, - EB1055961E14E2060003C309 /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */, - EB1055971E14E2060003C309 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */, - EB1055981E14E2060003C309 /* diginotar-public-ca-2025-Cert.crt in CopyFiles */, - EB1055991E14E2060003C309 /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */, - EB10559A1E14E2060003C309 /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */, - EB10559B1E14E2060003C309 /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */, - EB10559C1E14E2060003C309 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */, - EB10559D1E14E2060003C309 /* diginotar.root.ca-entrust-secure-server-Cert.crt in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; @@ -11600,16 +11256,18 @@ 09E9991F1F7D76550018DF67 /* SecKeyProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecKeyProxy.m; sourceTree = ""; }; 0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTLocalCuttlefishReset.m; sourceTree = ""; }; 0C00FC85217A972E00C8BF00 /* OTLocalCuttlefishReset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTLocalCuttlefishReset.h; sourceTree = ""; }; + 0C0203E023A8564E005D0A68 /* OTEscrowRecord.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; name = OTEscrowRecord.proto; path = proto/OTEscrowRecord.proto; sourceTree = ""; }; + 0C081F532559D181006DAD6A /* secd-231-v0Peers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-231-v0Peers.m"; sourceTree = ""; }; 0C0BDB2F175685B000BC1A7E /* secdtests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secdtests; sourceTree = BUILT_PRODUCTS_DIR; }; 0C0BDB31175685B000BC1A7E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 0C0BDB441756868B00BC1A7E /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist.h; sourceTree = ""; }; 0C0C4F83216FB55600C14C61 /* EscrowKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EscrowKeys.swift; sourceTree = ""; }; 0C0C4F84216FB56B00C14C61 /* BottledPeer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottledPeer.swift; sourceTree = ""; }; - 0C0C88771CCEC5BD00617D1B /* si-82-sectrust-ct-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-82-sectrust-ct-data"; path = "../OSX/shared_regressions/si-82-sectrust-ct-data"; sourceTree = ""; }; + 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_EscrowRecords.swift; sourceTree = ""; }; 0C0CEC9D1DA45EA200C22FBC /* recovery_key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = recovery_key.h; sourceTree = ""; }; 0C0CEC9E1DA45EA200C22FBC /* recovery_key.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = recovery_key.m; sourceTree = ""; }; + 0C0D920523BFEA740070A68C /* OTCDPRecoveryInformation.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; name = OTCDPRecoveryInformation.proto; path = proto/OTCDPRecoveryInformation.proto; sourceTree = ""; }; 0C0F76DD21399AF40074EDDF /* OTPairingMessage.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = OTPairingMessage.proto; sourceTree = ""; }; - 0C108C4B208A677100E8CF70 /* SFSignInAnalytics+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFSignInAnalytics+Internal.h"; sourceTree = ""; }; 0C12B1F02138D31600BE0A98 /* OTClientStateMachine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTClientStateMachine.m; sourceTree = ""; }; 0C12B1F52138D32F00BE0A98 /* OTClientStateMachine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTClientStateMachine.h; sourceTree = ""; }; 0C1B8BB3223323710094D5DA /* OTVouchWithRecoveryKeyOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTVouchWithRecoveryKeyOperation.h; sourceTree = ""; }; @@ -11629,6 +11287,26 @@ 0C3BB3562188E18B0018FC14 /* OTPrivateKey+SF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OTPrivateKey+SF.h"; path = "keychain/TrustedPeersHelper/categories/OTPrivateKey+SF.h"; sourceTree = SOURCE_ROOT; }; 0C3BB3572188E18C0018FC14 /* OTAuthenticatedCiphertext+SF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OTAuthenticatedCiphertext+SF.h"; path = "keychain/TrustedPeersHelper/categories/OTAuthenticatedCiphertext+SF.h"; sourceTree = SOURCE_ROOT; }; 0C3C00721EF3636300AB19FE /* secd-155-otr-negotiation-monitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-155-otr-negotiation-monitor.m"; sourceTree = ""; }; + 0C3C47C024902D450084B951 /* OTSupportOctagonMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSupportOctagonMessage.m; sourceTree = ""; }; + 0C3C47C224902D460084B951 /* OTSupportSOSMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSupportSOSMessage.h; sourceTree = ""; }; + 0C3C47C324902D460084B951 /* OTSupportSOSMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSupportSOSMessage.m; sourceTree = ""; }; + 0C3C47C424902D470084B951 /* OTSupportOctagonMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSupportOctagonMessage.h; sourceTree = ""; }; + 0C3C47C524902D470084B951 /* OTGlobalEnums.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTGlobalEnums.h; sourceTree = ""; }; + 0C3DF8C524789C04009CF03A /* Container_Peers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_Peers.swift; sourceTree = ""; }; + 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowRecordMetadata.m; path = proto/generated_source/OTEscrowRecordMetadata.m; sourceTree = ""; }; + 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowRecordMetadataClientMetadata.m; path = proto/generated_source/OTEscrowRecordMetadataClientMetadata.m; sourceTree = ""; }; + 0C468FDA23C7D41D006F4582 /* OTEscrowRecordMetadata.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowRecordMetadata.h; path = proto/generated_source/OTEscrowRecordMetadata.h; sourceTree = ""; }; + 0C468FDB23C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowRecordMetadataClientMetadata.h; path = proto/generated_source/OTEscrowRecordMetadataClientMetadata.h; sourceTree = ""; }; + 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowRecord.m; path = proto/generated_source/OTEscrowRecord.m; sourceTree = ""; }; + 0C468FDE23C7D471006F4582 /* OTEscrowRecord.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowRecord.h; path = proto/generated_source/OTEscrowRecord.h; sourceTree = ""; }; + 0C468FE723C7D4C7006F4582 /* OTICDPRecordContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTICDPRecordContext.h; path = proto/generated_source/OTICDPRecordContext.h; sourceTree = ""; }; + 0C468FE823C7D4C8006F4582 /* OTEscrowAuthenticationInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowAuthenticationInformation.h; path = proto/generated_source/OTEscrowAuthenticationInformation.h; sourceTree = ""; }; + 0C468FE923C7D4C8006F4582 /* OTICDPRecordSilentContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTICDPRecordSilentContext.h; path = proto/generated_source/OTICDPRecordSilentContext.h; sourceTree = ""; }; + 0C468FEA23C7D4C8006F4582 /* OTCDPRecoveryInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTCDPRecoveryInformation.h; path = proto/generated_source/OTCDPRecoveryInformation.h; sourceTree = ""; }; + 0C468FEB23C7D4C9006F4582 /* OTICDPRecordSilentContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTICDPRecordSilentContext.m; path = proto/generated_source/OTICDPRecordSilentContext.m; sourceTree = ""; }; + 0C468FEC23C7D4C9006F4582 /* OTEscrowAuthenticationInformation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowAuthenticationInformation.m; path = proto/generated_source/OTEscrowAuthenticationInformation.m; sourceTree = ""; }; + 0C468FED23C7D4C9006F4582 /* OTICDPRecordContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTICDPRecordContext.m; path = proto/generated_source/OTICDPRecordContext.m; sourceTree = ""; }; + 0C468FEE23C7D4CA006F4582 /* OTCDPRecoveryInformation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTCDPRecoveryInformation.m; path = proto/generated_source/OTCDPRecoveryInformation.m; sourceTree = ""; }; 0C48990A1E0E0FF300C6CF70 /* SOSTransportCircleCK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportCircleCK.h; sourceTree = ""; }; 0C4899111E0E105D00C6CF70 /* SOSTransportCircleCK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSTransportCircleCK.m; sourceTree = ""; }; 0C48991B1E0F384700C6CF70 /* SOSAccountTrustClassic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SOSAccountTrustClassic.m; path = SecureObjectSync/SOSAccountTrustClassic.m; sourceTree = ""; }; @@ -11639,6 +11317,8 @@ 0C5258B821BB05C100B32C96 /* FakeSOSControl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FakeSOSControl.m; path = Tests/FakeSOSControl.m; sourceTree = ""; }; 0C5258BC21BB137800B32C96 /* FakeSOSControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FakeSOSControl.h; path = Tests/FakeSOSControl.h; sourceTree = ""; }; 0C5824A322860001009E8C15 /* OctagonTests+HealthCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+HealthCheck.swift"; sourceTree = ""; }; + 0C64C07C2485A53000D84A5D /* OTPreloadOctagonKeysOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTPreloadOctagonKeysOperation.m; sourceTree = ""; }; + 0C64C07F2485A54100D84A5D /* OTPreloadOctagonKeysOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTPreloadOctagonKeysOperation.h; sourceTree = ""; }; 0C6604692134983900BFBBB8 /* OTEstablishOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTEstablishOperation.m; sourceTree = ""; }; 0C66046E2134985100BFBBB8 /* OTEstablishOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTEstablishOperation.h; sourceTree = ""; }; 0C6604782134C86500BFBBB8 /* OTDeviceInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTDeviceInformation.h; sourceTree = ""; }; @@ -11647,6 +11327,7 @@ 0C664AB2175926B20092D3D9 /* secdtests-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "secdtests-entitlements.plist"; sourceTree = ""; }; 0C6C2B682258211800C53C96 /* AppleAccount.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppleAccount.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/PrivateFrameworks/AppleAccount.framework; sourceTree = DEVELOPER_DIR; }; 0C6C2B6C2258295D00C53C96 /* UIKitCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKitCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/PrivateFrameworks/UIKitCore.framework; sourceTree = DEVELOPER_DIR; }; + 0C7382F023863AD5004F98CB /* reset_ick_account */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = reset_ick_account; sourceTree = ""; }; 0C75AC642141F18D0073A2F9 /* KeychainCircle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = KeychainCircle.framework; path = System/Library/PrivateFrameworks/KeychainCircle.framework; sourceTree = SDKROOT; }; 0C78F1C916A5E13400654E08 /* sectask_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sectask_regressions.h; sourceTree = ""; }; 0C78F1CA16A5E1BF00654E08 /* sectask-10-sectask.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sectask-10-sectask.c"; sourceTree = ""; }; @@ -11670,6 +11351,8 @@ 0C8FD546214AEC650098E3FB /* OTJoiningConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTJoiningConfiguration.h; sourceTree = ""; }; 0C8FD549214AECD70098E3FB /* OTJoiningConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTJoiningConfiguration.m; sourceTree = ""; }; 0C97867C235A76E70040A867 /* com.apple.security.signposts.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.signposts.plist; sourceTree = ""; }; + 0C9A54B4250C27F100FF007B /* OctagonTrustTests+Errors.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OctagonTrustTests+Errors.m"; sourceTree = ""; }; + 0C9A54B7250C290800FF007B /* OctagonTrustTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonTrustTests.h; sourceTree = ""; }; 0C9AE289214054F4003BFDB5 /* OTSponsorToApplicantRound1M2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSponsorToApplicantRound1M2.h; sourceTree = ""; }; 0C9AE28A214054F5003BFDB5 /* OTSponsorToApplicantRound2M2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSponsorToApplicantRound2M2.h; sourceTree = ""; }; 0C9AE28B214054F5003BFDB5 /* OTApplicantToSponsorRound2M1.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTApplicantToSponsorRound2M1.h; sourceTree = ""; }; @@ -11678,8 +11361,9 @@ 0C9AE290214054F7003BFDB5 /* OTSponsorToApplicantRound2M2.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSponsorToApplicantRound2M2.m; sourceTree = ""; }; 0C9AE2A1214055CE003BFDB5 /* OTPairingMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTPairingMessage.h; sourceTree = ""; }; 0C9AE2A2214055CF003BFDB5 /* OTPairingMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTPairingMessage.m; sourceTree = ""; }; - 0C9AEEB720783FBB00BF6237 /* SignInAnalyticsTests_osx.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SignInAnalyticsTests_osx.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C9FB40120D8729A00864612 /* CoreCDP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreCDP.framework; path = System/Library/PrivateFrameworks/CoreCDP.framework; sourceTree = SDKROOT; }; + 0C9F65AA23E3ACF700B1A2C5 /* OTEscrowTranslation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTEscrowTranslation.m; sourceTree = ""; }; + 0C9F65AC23E3ACF700B1A2C5 /* OTEscrowTranslation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTEscrowTranslation.h; sourceTree = ""; }; + 0CA1D0B223E9023100021038 /* OctagonTests+EscrowTestVectors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+EscrowTestVectors.swift"; sourceTree = ""; }; 0CA4EBF1202B8D1C002B1D96 /* CloudKitKeychainSyncingTestsBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudKitKeychainSyncingTestsBase.h; sourceTree = ""; }; 0CA4EBF2202B8D1D002B1D96 /* CloudKitKeychainSyncingTestsBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudKitKeychainSyncingTestsBase.m; sourceTree = ""; }; 0CA702082280D5600085AC54 /* OTCheckHealthOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTCheckHealthOperation.m; sourceTree = ""; }; @@ -11706,16 +11390,29 @@ 0CBA047C214C4E4D005B3A2F /* OctagonPairingTests+ProxMultiClients.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonPairingTests+ProxMultiClients.swift"; sourceTree = ""; }; 0CBEF3412242C9AE00015691 /* TestsObjcTranslation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestsObjcTranslation.m; sourceTree = ""; }; 0CBEF3422242C9BE00015691 /* TestsObjcTranslation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestsObjcTranslation.h; sourceTree = ""; }; + 0CBF883A23AAD9DC00652EDD /* OctagonTests+EscrowRecords.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+EscrowRecords.swift"; sourceTree = ""; }; 0CC8A8FA2123A9EB005D7F6A /* OTClientVoucherOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTClientVoucherOperation.m; sourceTree = ""; }; 0CC8A9002123AA3B005D7F6A /* OTClientVoucherOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTClientVoucherOperation.h; sourceTree = ""; }; 0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTJoinWithVoucherOperation.m; sourceTree = ""; }; 0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTJoinWithVoucherOperation.h; sourceTree = ""; }; + 0CCC227923F357EE00E1FCD0 /* OctagonTrustTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OctagonTrustTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CCC229223F35D4300E1FCD0 /* OctagonTrustTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "OctagonTrustTests-Info.plist"; sourceTree = ""; }; + 0CCC229F23F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OctagonTrustTests-EscrowRecords.m"; sourceTree = ""; }; + 0CCC22A323F36DD300E1FCD0 /* OctagonTrustTests-EscrowTestVectors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OctagonTrustTests-EscrowTestVectors.h"; sourceTree = ""; }; + 0CCC22B123F38B5B00E1FCD0 /* libsqlite3.0.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; }; + 0CCC22CC23F395A100E1FCD0 /* OctagonTrustEscrowRecoverer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonTrustEscrowRecoverer.h; sourceTree = ""; }; + 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreCDP.framework; path = System/Library/PrivateFrameworks/CoreCDP.framework; sourceTree = SDKROOT; }; 0CCCC7C720261D050024405E /* OT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OT.h; sourceTree = ""; }; 0CCCC7C820261D310024405E /* OT.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OT.m; sourceTree = ""; }; 0CCDE7161EEB08220021A946 /* secd-156-timers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-156-timers.m"; sourceTree = ""; }; 0CD3D5152240479600024755 /* OTSetRecoveryKeyOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSetRecoveryKeyOperation.m; sourceTree = ""; }; 0CD3D518224047B400024755 /* OTSetRecoveryKeyOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSetRecoveryKeyOperation.h; sourceTree = ""; }; 0CD5797721498F7700C43496 /* OctagonPairingTests+Piggybacking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonPairingTests+Piggybacking.swift"; sourceTree = ""; }; + 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OctagonTrust.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CD743A823C3EC8000FA0EC5 /* OctagonTrust.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonTrust.h; sourceTree = ""; }; + 0CD743A923C3EC8000FA0EC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0CD743B723C3ED7E00FA0EC5 /* OctagonTrust.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OctagonTrust.m; sourceTree = ""; }; + 0CD743BA23C3EF0D00FA0EC5 /* OTClique+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OTClique+Private.h"; sourceTree = ""; }; 0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSPeerOTRTimer.m; sourceTree = ""; }; 0CD8CB0C1ECA50D10076F37F /* SOSPeerOTRTimer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerOTRTimer.h; sourceTree = ""; }; 0CD8D654207D6E65005CDBE8 /* SFAnalytics+Signin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFAnalytics+Signin.h"; sourceTree = ""; }; @@ -11741,14 +11438,10 @@ 0CE760531E13155100B4381E /* SOSAccountTrustClassic+Circle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SOSAccountTrustClassic+Circle.h"; path = "SecureObjectSync/SOSAccountTrustClassic+Circle.h"; sourceTree = ""; }; 0CE760551E1316E900B4381E /* SOSAccountTrustClassic+Retirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SOSAccountTrustClassic+Retirement.h"; path = "SecureObjectSync/SOSAccountTrustClassic+Retirement.h"; sourceTree = ""; }; 0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libprequelite.tbd; path = usr/lib/libprequelite.tbd; sourceTree = SDKROOT; }; - 0CE9C98921B88919006BDD80 /* OTSOSMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OTSOSMessage.h; sourceTree = ""; }; - 0CE9C98A21B8891A006BDD80 /* OTSOSMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OTSOSMessage.m; sourceTree = ""; }; - 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFSignInAnalytics.m; sourceTree = ""; }; - 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFSignInAnalytics.h; sourceTree = ""; }; - 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFSignInAnalyticsTests.m; sourceTree = ""; }; 0CF405FC2072E352003D6A7F /* SFTMTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SFTMTests-Info.plist"; sourceTree = ""; }; - 0CF406502072E3E3003D6A7F /* SignInAnalyticsTests_ios.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SignInAnalyticsTests_ios.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 0CF70BD6218BECF500EC3515 /* CuttlefishExtensionWorkaround.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CuttlefishExtensionWorkaround.swift; sourceTree = ""; }; + 0CF7613D23F24B5D00A3C3AD /* KeychainCircle.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = KeychainCircle.modulemap; path = Modules/KeychainCircle.modulemap; sourceTree = ""; }; + 0CF7613F23F24B5E00A3C3AD /* OctagonTrust.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = OctagonTrust.modulemap; path = Modules/OctagonTrust.modulemap; sourceTree = ""; }; 0CFC029B1D41650700E6283B /* libcoretls.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcoretls.dylib; path = usr/lib/libcoretls.dylib; sourceTree = SDKROOT; }; 107226D00D91DB32003CF14F /* SecTask.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecTask.c; sourceTree = ""; }; 107226D10D91DB32003CF14F /* SecTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTask.h; path = sectask/SecTask.h; sourceTree = ""; }; @@ -11781,6 +11474,8 @@ 2281820D17B4686C0067C9C9 /* BackgroundTaskAgent.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BackgroundTaskAgent.framework; path = System/Library/PrivateFrameworks/BackgroundTaskAgent.framework; sourceTree = SDKROOT; }; 24CBF8731E9D4E4500F09F0E /* kc-44-secrecoverypassword.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-44-secrecoverypassword.c"; path = "regressions/kc-44-secrecoverypassword.c"; sourceTree = ""; }; 3D58394D21890FFB000ACA44 /* SecExperimentTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecExperimentTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3DC5BD58241830D50039ABF4 /* SecureTransportTests_macos.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = SecureTransportTests_macos.xctestplan; path = OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan; sourceTree = ""; }; + 3DC5BD59241845100039ABF4 /* SecureTransportTests_ios.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = SecureTransportTests_ios.xctestplan; path = OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan; sourceTree = ""; }; 3DD1FE78201AA50C0086D049 /* STLegacyTests+clientauth41.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "STLegacyTests+clientauth41.m"; sourceTree = ""; }; 3DD1FE79201AA50D0086D049 /* SecureTransport_macosTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SecureTransport_macosTests.plist; sourceTree = ""; }; 3DD1FE7A201AA50D0086D049 /* STLegacyTests-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "STLegacyTests-Entitlements.plist"; sourceTree = ""; }; @@ -11807,6 +11502,10 @@ 3DD1FFA9201FC5C30086D049 /* libcoretls_cfhelpers.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcoretls_cfhelpers.tbd; path = usr/lib/libcoretls_cfhelpers.tbd; sourceTree = SDKROOT; }; 3DD1FFD0201FDB1D0086D049 /* SecureTransport_ios_tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecureTransport_ios_tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3DD2589820478CCE00F5DA78 /* STLegacyTests+session.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "STLegacyTests+session.m"; sourceTree = ""; }; + 3E4D49BC2531170600B124B3 /* secsecstaticcodeapitest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secsecstaticcodeapitest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E4D508E253117DD00B124B3 /* secstaticcode.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = secstaticcode.cpp; path = codesigning_api_tests/secstaticcode.cpp; sourceTree = ""; }; + 3E88361124F068EF00E9F4D6 /* secseccodeapitest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secseccodeapitest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E88361324F0699F00E9F4D6 /* seccode.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = seccode.c; path = codesigning_api_tests/seccode.c; sourceTree = ""; }; 433E519D1B66D5F600482618 /* AppSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppSupport.framework; path = System/Library/PrivateFrameworks/AppSupport.framework; sourceTree = SDKROOT; }; 4381690C1B4EDCBD00C54D58 /* SOSCCAuthPlugin.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SOSCCAuthPlugin.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 4381690F1B4EDCBD00C54D58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -11841,7 +11540,7 @@ 4723C9D11F1531970082882F /* CKKSLoggerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSLoggerTests.m; sourceTree = ""; }; 4723C9DA1F1540CE0082882F /* SFAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalytics.h; sourceTree = ""; }; 4723C9DB1F1540CE0082882F /* SFAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalytics.m; sourceTree = ""; }; - 4727FBB71F9918580003AE36 /* secdxctests_ios.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = secdxctests_ios.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4727FBB71F9918580003AE36 /* secdxctests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = secdxctests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 4727FBB91F9918590003AE36 /* KeychainCryptoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainCryptoTests.m; sourceTree = ""; }; 4727FBBB1F9918590003AE36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4727FBC41F991C460003AE36 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; @@ -11860,7 +11559,6 @@ 4727FBE41F99217A0003AE36 /* SharedWebCredentials.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SharedWebCredentials.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.Internal.sdk/System/Library/PrivateFrameworks/SharedWebCredentials.framework; sourceTree = DEVELOPER_DIR; }; 4727FBE61F9921890003AE36 /* ApplePushService.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplePushService.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.Internal.sdk/System/Library/PrivateFrameworks/ApplePushService.framework; sourceTree = DEVELOPER_DIR; }; 4727FBE81F9921D00003AE36 /* libACM.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libACM.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.Internal.sdk/usr/local/lib/libACM.a; sourceTree = DEVELOPER_DIR; }; - 472E184F20D9A20D00ECE7C9 /* libcoreauthd_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcoreauthd_client.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/local/lib/libcoreauthd_client.a; sourceTree = DEVELOPER_DIR; }; 473337771FDAFBCC00E19F30 /* SFKeychainControlManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFKeychainControlManager.h; sourceTree = ""; }; 473337781FDAFBCC00E19F30 /* SFKeychainControlManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFKeychainControlManager.m; sourceTree = ""; }; 473337821FDB29A200E19F30 /* KeychainCheck.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainCheck.h; sourceTree = ""; }; @@ -11882,7 +11580,6 @@ 475EDCF520D98BCF009D2409 /* libACM.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libACM.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/local/lib/libACM.a; sourceTree = DEVELOPER_DIR; }; 475EDCF720D98BF6009D2409 /* CoreCDP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreCDP.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/PrivateFrameworks/CoreCDP.framework; sourceTree = DEVELOPER_DIR; }; 475EDCF920D98C0D009D2409 /* CryptoTokenKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CryptoTokenKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/PrivateFrameworks/CryptoTokenKit.framework; sourceTree = DEVELOPER_DIR; }; - 475EDCFB20D98C3C009D2409 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/libDER.a; sourceTree = SDKROOT; }; 475EDCFD20D98C53009D2409 /* libaks.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/local/lib/libaks.a; sourceTree = DEVELOPER_DIR; }; 475EDCFF20D98C64009D2409 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; }; 475EDD0120D98C81009D2409 /* libaks_acl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks_acl.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/local/lib/libaks_acl.a; sourceTree = DEVELOPER_DIR; }; @@ -11911,7 +11608,6 @@ 477A1FE1203763A500ACD81D /* KeychainAPITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainAPITests.m; sourceTree = ""; }; 477A1FEB2037A0E000ACD81D /* KeychainXCTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainXCTest.h; sourceTree = ""; }; 477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainXCTest.m; sourceTree = ""; }; - 478D429C1FD72A8100CAB645 /* secdxctests_mac.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = secdxctests_mac.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 479108B51EE879F9008CEFA0 /* CKKSAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSAnalytics.h; sourceTree = ""; }; 479108B61EE879F9008CEFA0 /* CKKSAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSAnalytics.m; sourceTree = ""; }; 47922D171FAA65120008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecDbKeychainSerializedAKSWrappedKey.proto; sourceTree = ""; }; @@ -11950,13 +11646,12 @@ 48776C7C1DA5BB5F00CC09B9 /* SOSRingRecovery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSRingRecovery.m; sourceTree = ""; }; 48776C7D1DA5BB5F00CC09B9 /* SOSRingRecovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSRingRecovery.h; sourceTree = ""; }; 48776C801DA5BC0E00CC09B9 /* SOSAccountRecovery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAccountRecovery.m; sourceTree = ""; }; + 487A65F3245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-68-fullPeerInfoIntegrity.m"; sourceTree = ""; }; 48AC7B5C232B1A1700F02B6F /* SOSIntervalEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSIntervalEvent.h; sourceTree = ""; }; 48AC7B71232B1A7000F02B6F /* SOSIntervalEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSIntervalEvent.m; sourceTree = ""; }; 48C2F9321E4BCFC30093D70C /* accountCirclesViewsPrint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = accountCirclesViewsPrint.m; sourceTree = ""; }; 48C2F9331E4BCFC30093D70C /* accountCirclesViewsPrint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = accountCirclesViewsPrint.h; sourceTree = ""; }; 48CC58971DA5FF0B00EBD9DB /* secd-66-account-recovery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-66-account-recovery.m"; sourceTree = ""; }; - 48E6171A1DBEC40D0098EAAD /* SOSBackupInformation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSBackupInformation.m; sourceTree = ""; }; - 48E6171B1DBEC40D0098EAAD /* SOSBackupInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSBackupInformation.h; sourceTree = ""; }; 48FE668F20E6E69B00FAEF17 /* SOSAuthKitHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAuthKitHelpers.m; sourceTree = ""; }; 48FE669520E6E69C00FAEF17 /* SOSAuthKitHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSAuthKitHelpers.h; sourceTree = ""; }; 4AF7FFF315AFB73800B9D400 /* SecOTR.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTR.h; sourceTree = ""; }; @@ -11980,15 +11675,6 @@ 4C2F81D40BF121D2003C4F77 /* SecRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRandom.h; path = base/SecRandom.h; sourceTree = ""; }; 4C32C0AF0A4975F6002891BD /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4C35DC37094F9120002917C4 /* Security-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Security-Info.plist"; sourceTree = ""; }; - 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-CertiID_Enterprise_Certificate_Authority.crt"; sourceTree = ""; }; - 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt"; sourceTree = ""; }; - 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-diginotarpkioverheidcaoverheid.crt"; sourceTree = ""; }; - 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt"; sourceTree = ""; }; - 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt; sourceTree = ""; }; - 4C3CECEF1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = Ministerie_van_Defensie_Certificatie_Autoriteit.crt; sourceTree = ""; }; - 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "staatdernederlandenorganisatieca-g2-Cert.crt"; sourceTree = ""; }; - 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "staatdernederlandenoverheidca-Cert.crt"; sourceTree = ""; }; - 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "DigiNotar_Root_CA_G2-RootCertificate.crt"; sourceTree = ""; }; 4C3DD6AE179755560093F9D8 /* NSDate+TimeIntervalDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+TimeIntervalDescription.h"; sourceTree = ""; }; 4C3DD6AF179755560093F9D8 /* NSDate+TimeIntervalDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+TimeIntervalDescription.m"; sourceTree = ""; }; 4C4296300BB0A68200491999 /* SecTrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustSettings.h; path = trust/headers/SecTrustSettings.h; sourceTree = ""; }; @@ -11997,19 +11683,6 @@ 4C4CB7100DDA44900026B660 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; 4C4CE9070AF81ED80056B01D /* TODO */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = TODO; sourceTree = ""; }; 4C4CE9120AF81F0E0056B01D /* README */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README; sourceTree = ""; }; - 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DigiNotarCA2007RootCertificate.crt; sourceTree = ""; }; - 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-asterisk.google.com.crt"; sourceTree = ""; }; - 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt"; sourceTree = ""; }; - 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-webmail.terneuzen.nl-diginotar-services.crt"; sourceTree = ""; }; - 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-www.maestre.com-diginotal.extended.validation.crt"; sourceTree = ""; }; - 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt"; sourceTree = ""; }; - 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar-public-ca-2025-Cert.crt"; sourceTree = ""; }; - 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar-services-1024-entrust-secure-server-Cert.crt"; sourceTree = ""; }; - 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar-services-diginotar-root-Cert.crt"; sourceTree = ""; }; - 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar.cyberca-gte.global.root-Cert.crt"; sourceTree = ""; }; - 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar.extended.validation-diginotar.root.ca-Cert.crt"; sourceTree = ""; }; - 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar.root.ca-entrust-secure-server-Cert.crt"; sourceTree = ""; }; - 4C50AD2F1410689300EE92DE /* Expectations.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expectations.plist; sourceTree = ""; }; 4C52D0B416EFC61E0079966E /* CircleJoinRequested */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CircleJoinRequested; sourceTree = BUILT_PRODUCTS_DIR; }; 4C52D0B916EFC61E0079966E /* CircleJoinRequested.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CircleJoinRequested.m; sourceTree = ""; }; 4C52D0BD16EFC61E0079966E /* Readme.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Readme.txt; sourceTree = ""; }; @@ -12035,7 +11708,6 @@ 4C84DA6217207E8D00AEE225 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; 4C87F3A70D611C26000E7104 /* SecTrustPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustPriv.h; path = trust/headers/SecTrustPriv.h; sourceTree = ""; }; 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudServices.framework; path = System/Library/PrivateFrameworks/CloudServices.framework; sourceTree = SDKROOT; }; - 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-webmail.portofamsterdam.nl.crt"; sourceTree = ""; }; 4C8E99C20FC601D50072EB4C /* SecFrameworkStrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecFrameworkStrings.h; sourceTree = ""; }; 4C8FD03D099D5C91006867B6 /* SecCertificate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SecCertificate.h; path = trust/headers/SecCertificate.h; sourceTree = ""; }; 4C8FD03E099D5C91006867B6 /* SecTrust.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SecTrust.h; path = trust/headers/SecTrust.h; sourceTree = ""; }; @@ -12090,6 +11762,7 @@ 52AA92881E662A4A004301A6 /* SecBackupKeybagEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecBackupKeybagEntry.m; sourceTree = ""; }; 52D82BD316A5EADA0078DFE5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 52D82BDE16A621F70078DFE5 /* CloudKeychainProxy.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CloudKeychainProxy.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + 52DA3C6F23C7E63500FEEDFF /* KCTLKRequestTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KCTLKRequestTest.m; path = Tests/KCTLKRequestTest.m; sourceTree = ""; }; 5346480117331E1200FE9172 /* KeychainSyncAccountNotification.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeychainSyncAccountNotification.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 5346480517331E1200FE9172 /* KeychainSyncAccountNotification-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KeychainSyncAccountNotification-Info.plist"; sourceTree = ""; }; 5346480717331E1200FE9172 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -12099,7 +11772,6 @@ 53C0E1F2177FAC2C00F8A018 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = en.lproj/CloudKeychain.strings; sourceTree = ""; }; 5A04BAF622973E43001848A0 /* OTFollowup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OTFollowup.h; sourceTree = ""; }; 5A04BAF722973E43001848A0 /* OTFollowup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OTFollowup.m; sourceTree = ""; }; - 5A04BAF922973EA9001848A0 /* OTFollowupTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OTFollowupTests.m; path = keychain/ot/tests/OTFollowupTests.m; sourceTree = SOURCE_ROOT; }; 5A04BB14229866F7001848A0 /* SecXPCHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecXPCHelper.m; sourceTree = ""; }; 5A04BB182298670C001848A0 /* SecXPCHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecXPCHelper.h; sourceTree = ""; }; 5A04BB22229872CB001848A0 /* SecXPCHelperTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecXPCHelperTests.m; sourceTree = ""; }; @@ -12142,9 +11814,10 @@ 5EBE247A1B00CCAE0007DB0E /* secacltests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secacltests; sourceTree = BUILT_PRODUCTS_DIR; }; 5EBE247C1B00CCAE0007DB0E /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 5F00F95A230614A200B832E0 /* SecImportExportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecImportExportPriv.h; path = keychain/headers/SecImportExportPriv.h; sourceTree = ""; }; + 5F4C21FE2489C68900F0C425 /* simulatecrash_assert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = simulatecrash_assert.h; sourceTree = ""; }; 5F8494FF22DFB502008B3EFB /* SecTrustExceptionResetCount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecTrustExceptionResetCount.m; sourceTree = ""; }; 617570BA22C2D19E00EFBA37 /* Security.macOS.private.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = Security.macOS.private.modulemap; path = Modules/Security.macOS.private.modulemap; sourceTree = ""; }; - 6C02134C21F7ED16009D5C80 /* SecDbBackupTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = SecDbBackupTests.plist; path = tests/SecDbBackupTests/SecDbBackupTests.plist; sourceTree = SOURCE_ROOT; }; + 61BDC97E242932A100A2ABD8 /* SecTranslocateEnumUtils.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateEnumUtils.hpp; sourceTree = ""; }; 6C02134D21F7ED16009D5C80 /* SecDbBackupTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SecDbBackupTests.m; path = tests/SecDbBackupTests/SecDbBackupTests.m; sourceTree = SOURCE_ROOT; }; 6C02134F21F7ED45009D5C80 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = Info.plist; path = tests/SecDbBackupTests/Info.plist; sourceTree = SOURCE_ROOT; }; 6C0B0C3D1E2537C6007F95E5 /* WirelessDiagnostics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WirelessDiagnostics.framework; path = System/Library/PrivateFrameworks/WirelessDiagnostics.framework; sourceTree = SDKROOT; }; @@ -12164,11 +11837,17 @@ 6C1260FA1F7D631D001B2EEC /* securityuploadd-ios.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "securityuploadd-ios.plist"; sourceTree = ""; }; 6C1520CD1DCCF57A00C85C6D /* secd.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = secd.8; sourceTree = ""; }; 6C1A29FC1F882788002312D8 /* SFAnalyticsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsTests.m; sourceTree = ""; }; - 6C2008EF220BB4B500674B3A /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = ""; }; + 6C2008EF220BB4B500674B3A /* SecDbBackupTests-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SecDbBackupTests-Entitlements.plist"; sourceTree = ""; }; + 6C2045EA2424BA7E00F9461D /* KeychainStasher */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = KeychainStasher; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C2045F92424BCB800F9461D /* com.apple.security.KeychainStasher.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.KeychainStasher.plist; sourceTree = ""; }; 6C23F02C227A39E9009F6756 /* com.apple.securityd.sb */ = {isa = PBXFileReference; lastKnownFileType = text; name = com.apple.securityd.sb; path = securityd/etc/com.apple.securityd.sb; sourceTree = SOURCE_ROOT; }; + 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LegacyAPICounts.h; sourceTree = ""; }; + 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LegacyAPICounts.m; sourceTree = ""; }; 6C34462F1E24F6BE00F9522B /* CKKSRateLimiterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSRateLimiterTests.m; sourceTree = ""; }; 6C39237921F13E4D00D018AD /* SecDbBackupTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecDbBackupTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6C4605B81F882B9B001421B6 /* KeychainAnalyticsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeychainAnalyticsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C48D10D2423A2F3004AF950 /* KeychainStasher.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = KeychainStasher.entitlements; sourceTree = ""; }; + 6C48D10F2423A3C0004AF950 /* com.apple.security.KeychainStasher.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.security.KeychainStasher.sb; sourceTree = ""; }; 6C4AEF82218A09210012C5DA /* CheckV12DevEnabled.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckV12DevEnabled.h; sourceTree = ""; }; 6C4AEF83218A09210012C5DA /* CheckV12DevEnabled.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CheckV12DevEnabled.m; sourceTree = ""; }; 6C4AEF8A218A0A400012C5DA /* SecDbBackupManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbBackupManager.h; sourceTree = ""; }; @@ -12177,10 +11856,15 @@ 6C4AEF93218A124B0012C5DA /* SecDbKeychainMetadataKeyStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecDbKeychainMetadataKeyStore.m; sourceTree = ""; }; 6C4AEF9C218A16F80012C5DA /* SecAKSObjCWrappers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAKSObjCWrappers.h; sourceTree = ""; }; 6C4AEF9D218A16F80012C5DA /* SecAKSObjCWrappers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecAKSObjCWrappers.m; sourceTree = ""; }; + 6C513A37244F007B00207D5E /* SecItemRateLimit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemRateLimit.h; sourceTree = ""; }; + 6C513A38244F007B00207D5E /* SecItemRateLimit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecItemRateLimit.m; sourceTree = ""; }; 6C5232D41E3C183F00330DB1 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/CloudKit.framework; sourceTree = DEVELOPER_DIR; }; + 6C54BE0C23F41497004716CB /* SystemEntitlements.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SystemEntitlements.h; sourceTree = ""; }; 6C588D791EAA149F00D7E322 /* RateLimiterTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RateLimiterTests.m; sourceTree = ""; }; 6C5B101B1F91613E009B091E /* supdctl-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "supdctl-Entitlements.plist"; sourceTree = ""; }; 6C5B10211F9164F5009B091E /* securityuploadd.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = securityuploadd.8; sourceTree = ""; }; + 6C5D62A5221B6E3F00AF79DC /* secdxctests-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "secdxctests-entitlements.plist"; sourceTree = ""; }; + 6C6579FC2394878700701C8B /* SecDbBackupTestsBase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecDbBackupTestsBase.m; sourceTree = ""; }; 6C69517C1F758E1000F68F91 /* supdProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = supdProtocol.h; sourceTree = ""; }; 6C69517D1F758E1000F68F91 /* supd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = supd.h; sourceTree = ""; }; 6C69517E1F758E1000F68F91 /* supd.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = supd.m; sourceTree = ""; }; @@ -12189,16 +11873,23 @@ 6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsSQLiteStore.m; sourceTree = ""; }; 6C69518E1F75A7DC00F68F91 /* SFAnalyticsSQLiteStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsSQLiteStore.h; sourceTree = ""; }; 6C69518F1F75A8C100F68F91 /* SFAnalyticsDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsDefines.h; sourceTree = ""; }; + 6C6AF178221A03930091CE0A /* SecDbKeychainSerializedMetadataKey.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecDbKeychainSerializedMetadataKey.proto; sourceTree = ""; }; + 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbKeychainSerializedMetadataKey.h; sourceTree = ""; }; + 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecDbKeychainSerializedMetadataKey.m; sourceTree = ""; }; 6C70D8D420EB02B700AB6FAF /* TPPBPolicyCategoriesByView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPBPolicyCategoriesByView.m; sourceTree = ""; }; 6C70D8D520EBDE4500AB6FAF /* TPPBPolicyRedaction.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = TPPBPolicyRedaction.proto; sourceTree = ""; }; 6C70D8DD20EBDFD600AB6FAF /* TPPBPolicyRedaction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPBPolicyRedaction.m; sourceTree = ""; }; 6C70D8DE20EBDFD700AB6FAF /* TPPBPolicyRedaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPBPolicyRedaction.h; sourceTree = ""; }; + 6C755603242121F000025D78 /* keychainstasherinterface.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = keychainstasherinterface.m; sourceTree = ""; }; + 6C755604242121F000025D78 /* keychainstasherinterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keychainstasherinterface.h; sourceTree = ""; }; 6C758CB01F8826100075BD78 /* SupdTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SupdTests.m; sourceTree = ""; }; 6C758CB21F8826100075BD78 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6C7BB0032006B4EE004D1B6B /* SOSAnalytics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SOSAnalytics.m; path = Analytics/Clients/SOSAnalytics.m; sourceTree = SOURCE_ROOT; }; 6C7BB0042006B4EF004D1B6B /* SOSAnalytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSAnalytics.h; path = Analytics/Clients/SOSAnalytics.h; sourceTree = SOURCE_ROOT; }; + 6C7BE2E723C3DD64003BB2CA /* securitytool_bridge */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = securitytool_bridge; sourceTree = BUILT_PRODUCTS_DIR; }; 6C814A4A2050B4B600CB391B /* LocalKeychainAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalKeychainAnalytics.h; sourceTree = ""; }; 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocalKeychainAnalytics.m; sourceTree = ""; }; + 6C84E3C723ECBC84003C9710 /* KeychainAppClipTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainAppClipTests.m; sourceTree = ""; }; 6C860C741F4F63AD004100A1 /* SOSEnsureBackup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSEnsureBackup.h; sourceTree = ""; }; 6C860C7A1F4F63DB004100A1 /* SOSEnsureBackup.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSEnsureBackup.m; sourceTree = ""; }; 6C880FBE21C334FB00D38D66 /* SecDbBackupBagIdentity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbBackupBagIdentity.h; sourceTree = ""; }; @@ -12213,17 +11904,24 @@ 6C880FC721C334FE00D38D66 /* SecDbBackupRecoverySet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbBackupRecoverySet.h; sourceTree = ""; }; 6C8CE6BB1FA248B50032ADF0 /* SFAnalyticsActivityTracker+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFAnalyticsActivityTracker+Internal.h"; sourceTree = ""; }; 6C8CE6C31FA24A670032ADF0 /* SFAnalyticsSampler+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFAnalyticsSampler+Internal.h"; sourceTree = ""; }; + 6C915BE3242E14BC00DBDAFB /* SecDbInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbInternal.h; sourceTree = ""; }; + 6C963281242A279B00C53CE2 /* stashtester */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = stashtester; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C963283242A279B00C53CE2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6C963289242A27F300C53CE2 /* stashtester.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = stashtester.entitlements; sourceTree = ""; }; 6C9791C421C17D060074C609 /* SecDbBackupManager_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbBackupManager_Internal.h; sourceTree = ""; }; - 6C9808611E788AEB00E70590 /* CKKSCloudKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CKKSCloudKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 6C98089D1E788AFD00E70590 /* CKKSCloudKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CKKSCloudKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C997869242362EC008C498D /* KeychainStasherProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainStasherProtocol.h; sourceTree = ""; }; + 6C99786A242362EC008C498D /* KeychainStasher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainStasher.h; sourceTree = ""; }; + 6C99786B242362EC008C498D /* KeychainStasher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainStasher.m; sourceTree = ""; }; + 6C99786D242362EC008C498D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6C99786F242362EC008C498D /* KeychainStasher-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KeychainStasher-Info.plist"; sourceTree = ""; }; + 6C997879242364E5008C498D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.16.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 6C99787C242364FB008C498D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.16.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; 6C9AA79E1F7C1D8F00D08296 /* supdctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = supdctl; sourceTree = BUILT_PRODUCTS_DIR; }; 6C9AA7A01F7C1D9000D08296 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 6CA2B9431E9F9F5700C43444 /* RateLimiter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RateLimiter.h; sourceTree = ""; }; 6CA837612210C5E7002770F1 /* kc-45-change-password.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "kc-45-change-password.c"; path = "regressions/kc-45-change-password.c"; sourceTree = ""; }; 6CAA8D201F842FB3007B6E03 /* securityuploadd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = securityuploadd; sourceTree = BUILT_PRODUCTS_DIR; }; - 6CB5F4751E4025AB00DBF3F0 /* CKKSCloudKitTestsInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = CKKSCloudKitTestsInfo.plist; sourceTree = ""; }; - 6CB5F4781E402E5700DBF3F0 /* KeychainCKKS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = KeychainCKKS.plist; path = testrunner/KeychainCKKS.plist; sourceTree = ""; }; - 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "KeychainEntitledTestRunner-Entitlements.plist"; sourceTree = ""; }; + 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = KeychainEntitledTestRunner.entitlements; sourceTree = ""; }; 6CB5F47A1E402E5700DBF3F0 /* KeychainEntitledTestRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeychainEntitledTestRunner.m; sourceTree = ""; }; 6CB6CC022198D4BC0080AD6F /* SecDbBackupRecoverySet.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecDbBackupRecoverySet.proto; sourceTree = ""; }; 6CB96BB41F966E0C00E11457 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; @@ -12235,7 +11933,8 @@ 6CC952421FB4C5CA0051A823 /* SFAnalytics+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SFAnalytics+Internal.h"; sourceTree = ""; }; 6CCDF7841E3C25FA003F2555 /* KeychainEntitledTestRunner */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = KeychainEntitledTestRunner; sourceTree = BUILT_PRODUCTS_DIR; }; 6CCDF78B1E3C26BC003F2555 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/MacOSX.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 6CCDF7911E3C2D69003F2555 /* CKKSCloudKitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSCloudKitTests.m; sourceTree = ""; }; + 6CD224E7239493E8001B70FD /* SecDbBackupTestsBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbBackupTestsBase.h; sourceTree = ""; }; + 6CD8412B23F5D871003DDF34 /* KeychainBackupTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainBackupTests.m; sourceTree = ""; }; 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsMultiSampler.m; sourceTree = ""; }; 6CDB5FF31FA78CB500410924 /* SFAnalyticsMultiSampler+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SFAnalyticsMultiSampler+Internal.h"; sourceTree = ""; }; 6CDB5FF41FA78CB500410924 /* SFAnalyticsMultiSampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsMultiSampler.h; sourceTree = ""; }; @@ -12243,6 +11942,9 @@ 6CDF8DE51F95562B00140B54 /* SFAnalyticsSampler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsSampler.h; sourceTree = ""; }; 6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsSampler.m; sourceTree = ""; }; 6CE22D6F1E49206600974785 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.Internal.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 6CF1B5C5245077E400FD8CC4 /* SecItemRateLimit_tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemRateLimit_tests.h; sourceTree = ""; }; + 6CF33CA2238714C900D1E75D /* bats_utd_plist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bats_utd_plist.h; sourceTree = ""; }; + 6CF33CA4238714C900D1E75D /* PreprocessPlist.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = PreprocessPlist.sh; sourceTree = ""; }; 6CF4A0B41E45488B00ECD7B5 /* KeychainEntitledTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KeychainEntitledTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6CF4A0B61E45488B00ECD7B5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 6CF4A0B71E45488B00ECD7B5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -12250,15 +11952,7 @@ 6CF4A0BC1E45488B00ECD7B5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 6CF4A0BD1E45488B00ECD7B5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 6CF4A0BF1E45488B00ECD7B5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 6CF4A0C41E45488B00ECD7B5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6CF4A0E01E4549F200ECD7B5 /* KeychainEntitledTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KeychainEntitledTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6CF4A0E31E4549F200ECD7B5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6CF4A0E51E4549F200ECD7B5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6CF4A0E61E4549F300ECD7B5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6CF4A0E81E4549F300ECD7B5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - 6CF4A0E91E4549F300ECD7B5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; - 6CF4A0EE1E4549F300ECD7B5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 6CF4A0F31E4549F300ECD7B5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6CF4A0C41E45488B00ECD7B5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 6CFDC4561F907E1D00646DBB /* libprequelite.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libprequelite.tbd; path = usr/lib/libprequelite.tbd; sourceTree = SDKROOT; }; 7221843E1EC6782A004C7BED /* sec_action.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sec_action.c; sourceTree = ""; }; 7221843F1EC6782A004C7BED /* sec_action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sec_action.h; sourceTree = ""; }; @@ -12280,19 +11974,25 @@ 7913B2110D172B3900601FE9 /* sslServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sslServer; sourceTree = BUILT_PRODUCTS_DIR; }; 791766DD0DD0162C00F3B974 /* SecCertificateRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateRequest.h; path = trust/headers/SecCertificateRequest.h; sourceTree = ""; }; 7940D4110C3ACF9000FDB5D8 /* SecDH.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecDH.h; sourceTree = ""; }; - 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-www.cybersecurity.my.crt"; sourceTree = ""; }; - 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Digisign-Server-ID-Enrich-GTETrust-Cert.crt"; sourceTree = ""; }; 795CA9CC0D38435E00BAE6A2 /* p12pbegen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p12pbegen.h; sourceTree = ""; }; - 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Digisign-Server-ID-Enrich-Entrust-Cert.crt"; sourceTree = ""; }; - 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-webmail.jaring.my.crt"; sourceTree = ""; }; 79EF5B6C0D3D6A31009F5270 /* SecImportExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecImportExport.h; path = keychain/headers/SecImportExport.h; sourceTree = ""; }; 79EF5B720D3D6AFE009F5270 /* p12import.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p12import.h; sourceTree = ""; }; 8E02FA691107BE460043545E /* pbkdf2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pbkdf2.h; sourceTree = ""; }; 8E64DB4C1C17CD3F0076C9DF /* com.apple.security.cloudkeychainproxy3.ios.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.security.cloudkeychainproxy3.ios.plist; path = KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.ios.plist; sourceTree = ""; }; 8E64DB4D1C17CD400076C9DF /* com.apple.security.cloudkeychainproxy3.osx.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.security.cloudkeychainproxy3.osx.plist; path = KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist; sourceTree = ""; }; 8ED6F6C8110904E300D2B368 /* SecPBKDF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPBKDF.h; sourceTree = ""; }; + A640B71E25CB8A030098A4A4 /* secstaticcode_integration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = secstaticcode_integration.m; path = codesigning_api_tests/secstaticcode_integration.m; sourceTree = ""; }; + A640B72525CB9A5C0098A4A4 /* secstaticcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = secstaticcode.h; path = codesigning_api_tests/secstaticcode.h; sourceTree = ""; }; + A640B72625CB9B3B0098A4A4 /* codesigning_tests_shared.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = codesigning_tests_shared.h; path = codesigning_api_tests/codesigning_tests_shared.h; sourceTree = ""; }; + A695615A2580A0F500BDF83F /* libsecurity_codesigning.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_codesigning.a; path = usr/local/lib/libsecurity_codesigning.a; sourceTree = SDKROOT; }; + A695623B2580AB7800BDF83F /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = usr/local/lib/libsecurity_utilities.a; sourceTree = SDKROOT; }; + A695631C2580AB8A00BDF83F /* libsecurity_cdsa_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_cdsa_utilities.a; path = usr/local/lib/libsecurity_cdsa_utilities.a; sourceTree = SDKROOT; }; + A69565BA2580ABBC00BDF83F /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/libDER.a; sourceTree = SDKROOT; }; + A695677A2581B46000BDF83F /* unsigned_secstaticcodeapitest.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = unsigned_secstaticcodeapitest.sh; path = codesigning_api_tests/unsigned_secstaticcodeapitest.sh; sourceTree = ""; }; A6B1BA78207BD9D400F1E099 /* notarization.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = notarization.cpp; sourceTree = ""; }; A6B1BA79207BD9D400F1E099 /* notarization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = notarization.h; sourceTree = ""; }; + A6BF3B3123EB94A7009AF079 /* entitlements.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = entitlements.h; sourceTree = ""; }; + A6BF3B3223EB94A7009AF079 /* entitlements.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = entitlements.c; sourceTree = ""; }; AA0DA47821E8189D009F1C74 /* example1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = example1.json; path = protocol/test_data/example1.json; sourceTree = ""; }; AA0DA47921E8189E009F1C74 /* builtins.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = builtins.json; path = protocol/test_data/builtins.json; sourceTree = ""; }; AA44E0B3202E3451001EA371 /* SecProtocolTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SecProtocolTest.m; path = protocol/SecProtocolTest.m; sourceTree = ""; }; @@ -12329,6 +12029,8 @@ BE22FBD01EE2084100893431 /* Config.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Config.m; path = manifeststresstest/Config.m; sourceTree = ""; }; BE22FBFC1EE23D9100893431 /* mark.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = mark.m; path = manifeststresstest/mark.m; sourceTree = ""; }; BE22FC031EE23DA600893431 /* mark.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = mark.h; path = manifeststresstest/mark.h; sourceTree = ""; }; + BE26081625620B190057C489 /* SecXPCUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecXPCUtils.m; sourceTree = ""; }; + BE2609D325620B2C0057C489 /* SecXPCUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecXPCUtils.h; sourceTree = ""; }; BE442BC118B7FDB800F24DAE /* swcagent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = swcagent; sourceTree = BUILT_PRODUCTS_DIR; }; BE4AC9A118B7FFAD00B84964 /* swcagent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = swcagent.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; BE4AC9AD18B7FFC800B84964 /* com.apple.security.swcagent.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.swcagent.plist; sourceTree = ""; }; @@ -12338,7 +12040,7 @@ BE55C77A2044D0C80045863D /* TrustedPeersHelper-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TrustedPeersHelper-Bridging-Header.h"; sourceTree = ""; }; BE55C77B2044D0C90045863D /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; BE55C77D2044D7E60045863D /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; - BE6215BD1DB6E69100961E15 /* si-84-sectrust-allowlist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-84-sectrust-allowlist.m"; sourceTree = ""; }; + BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ca_revocation_additions.m; sourceTree = ""; }; BE64A7FD22AF0109001209F3 /* trusted_cert_ssl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trusted_cert_ssl.h; sourceTree = ""; }; BE64A7FE22AF010A001209F3 /* trusted_cert_ssl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = trusted_cert_ssl.m; sourceTree = ""; }; BE7089911F9AA027001ACC20 /* TPPBVoucher.proto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.protobuf; path = TPPBVoucher.proto; sourceTree = ""; }; @@ -12357,11 +12059,9 @@ BE7089DD1FA40B93001ACC20 /* TPPBPeerPermanentInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPBPeerPermanentInfo.h; sourceTree = ""; }; BE7089DE1FA40B95001ACC20 /* TPPBPeerPermanentInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPBPeerPermanentInfo.m; sourceTree = ""; }; BE72782A209D27C800F0DA77 /* TPKeyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPKeyTests.m; sourceTree = ""; }; - BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = framework_requiring_modern_objc_runtime.xcconfig; path = xcconfig/framework_requiring_modern_objc_runtime.xcconfig; sourceTree = ""; }; + BE7B8E112415579800E1CF4F /* SecSharedCredential.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecSharedCredential.m; sourceTree = ""; }; BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; BE92249D204F203C0052E828 /* TrustedPeersHelper.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = TrustedPeersHelper.xcdatamodel; sourceTree = ""; }; - BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "si-88-sectrust-valid-data"; sourceTree = ""; }; - BE9B8B49202BB4A10081EF87 /* si-88-sectrust-valid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "si-88-sectrust-valid.m"; path = "OSX/shared_regressions/si-88-sectrust-valid.m"; sourceTree = SOURCE_ROOT; }; BE9F4F8B2072D881004A52C2 /* Cuttlefish.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cuttlefish.pb.swift; sourceTree = ""; }; BE9F8D0F206C099800B53D16 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; BE9F8D11206C121400B53D16 /* Decrypter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Decrypter.swift; sourceTree = ""; }; @@ -12401,6 +12101,8 @@ BECFA43C20F9493000B11002 /* Policy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Policy.swift; sourceTree = ""; }; BECFA46320FFB87400B11002 /* TPKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPKey.m; sourceTree = ""; }; BED01530206F050F0027A2B4 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = trust/README.txt; sourceTree = ""; }; + BED0781D2542A2B300FED203 /* CARevocationTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CARevocationTests_data.h; path = tests/TrustTests/EvaluationTests/CARevocationTests_data.h; sourceTree = ""; }; + BED078F82542A2BF00FED203 /* CARevocationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CARevocationTests.m; path = tests/TrustTests/EvaluationTests/CARevocationTests.m; sourceTree = ""; }; BED208DD1EDF950E00753952 /* manifeststresstest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = manifeststresstest; sourceTree = BUILT_PRODUCTS_DIR; }; BED208E61EDF971600753952 /* manifeststresstest.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; name = manifeststresstest.entitlements; path = manifeststresstest/manifeststresstest.entitlements; sourceTree = ""; }; BED208E71EDF971600753952 /* manifeststresstest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = manifeststresstest.m; path = manifeststresstest/manifeststresstest.m; sourceTree = ""; }; @@ -12408,6 +12110,8 @@ BED987D52099145300607A5F /* TrustedPeersHelperUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedPeersHelperUnitTests.swift; sourceTree = ""; }; BED987D72099145300607A5F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BED987E220991C4D00607A5F /* MockCuttlefish.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCuttlefish.swift; sourceTree = ""; }; + BEE2953F25818E0300CD1294 /* si-40-identity-tests_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "si-40-identity-tests_data.h"; path = "regressions/si-40-identity-tests_data.h"; sourceTree = ""; }; + BEE2954125818E0300CD1294 /* si-40-identity-tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "si-40-identity-tests.m"; path = "regressions/si-40-identity-tests.m"; sourceTree = ""; }; BEEB47D71EA189F5004AA5C6 /* SecTrustStatusCodes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecTrustStatusCodes.c; sourceTree = ""; }; BEEB47D81EA189F5004AA5C6 /* SecTrustStatusCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTrustStatusCodes.h; sourceTree = ""; }; BEF88C281EAFFC3F00357577 /* TrustedPeers.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TrustedPeers.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -12458,10 +12162,15 @@ CDA43D251DFCA0790038E038 /* AggregateDictionary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AggregateDictionary.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.Internal.sdk/System/Library/PrivateFrameworks/AggregateDictionary.framework; sourceTree = DEVELOPER_DIR; }; CDB9FCA9179CC757000AAD66 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; CDDE9BC31729AB910013B0E8 /* SecPasswordGenerate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPasswordGenerate.h; sourceTree = ""; }; + D401443625789030008BAE33 /* TrustURLSessionCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TrustURLSessionCache.m; sourceTree = ""; }; + D401451725789075008BAE33 /* TrustURLSessionCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TrustURLSessionCache.h; sourceTree = ""; }; D4056A1922712A650026E24E /* SSLPolicyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SSLPolicyTests.m; path = tests/TrustTests/EvaluationTests/SSLPolicyTests.m; sourceTree = ""; }; D4056A1C22712AD80026E24E /* SSLPolicyTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SSLPolicyTests_data.h; path = tests/TrustTests/EvaluationTests/SSLPolicyTests_data.h; sourceTree = ""; }; D4056A1D22712D740026E24E /* ssl-policy-certs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "ssl-policy-certs"; path = "SecurityTests/ssl-policy-certs"; sourceTree = ""; }; D4056A1E22712D750026E24E /* si-87-sectrust-name-constraints */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-87-sectrust-name-constraints"; path = "SecurityTests/si-87-sectrust-name-constraints"; sourceTree = ""; }; + D407217A252FE5FD0084D96B /* PolicyTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PolicyTests_data.h; path = tests/TrustTests/EvaluationTests/PolicyTests_data.h; sourceTree = ""; }; + D407225A25310BC20084D96B /* PinningDbTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PinningDbTests.m; path = tests/TrustTests/DaemonTests/PinningDbTests.m; sourceTree = ""; }; + D4072929253138730084D96B /* TestTrustdInitialization-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "TestTrustdInitialization-data"; path = "tests/TrustTests/TestData/TestTrustdInitialization-data"; sourceTree = ""; }; D40B6A871E2B5F9900CD6EE5 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; D40B6A881E2B5F9900CD6EE5 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; D41149A01E7C935D00C078C7 /* AppleiPhoneDeviceCACertificates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleiPhoneDeviceCACertificates.h; sourceTree = ""; }; @@ -12473,7 +12182,11 @@ D41257EC1E941CF200781F23 /* trustd.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = trustd.8; sourceTree = ""; }; D41257ED1E941D5B00781F23 /* SecTrustOSXEntryPoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustOSXEntryPoints.h; path = trust/trustd/macOS/SecTrustOSXEntryPoints.h; sourceTree = SOURCE_ROOT; }; D41257EE1E941DA800781F23 /* com.apple.trustd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.trustd.plist; sourceTree = ""; }; + D41321802549E49A0062995A /* DigicertMalaysia */ = {isa = PBXFileReference; lastKnownFileType = folder; name = DigicertMalaysia; path = SecurityTests/DigicertMalaysia; sourceTree = ""; }; + D41324122549E55B0062995A /* DigiNotar */ = {isa = PBXFileReference; lastKnownFileType = folder; name = DigiNotar; path = SecurityTests/DigiNotar; sourceTree = ""; }; D41D36701EB14D87007FA978 /* libDiagnosticMessagesClient.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libDiagnosticMessagesClient.tbd; path = usr/lib/libDiagnosticMessagesClient.tbd; sourceTree = SDKROOT; }; + D423114223725F9F000E470A /* SMIMEPolicyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SMIMEPolicyTests.m; path = tests/TrustTests/EvaluationTests/SMIMEPolicyTests.m; sourceTree = ""; }; + D4231147237261F7000E470A /* SMIMEPolicyTests-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "SMIMEPolicyTests-data"; path = "tests/TrustTests/TestData/SMIMEPolicyTests-data"; sourceTree = ""; }; D42C838721158B3F008D3D83 /* cmsreclist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cmsreclist.h; path = libsecurity_smime/lib/cmsreclist.h; sourceTree = SOURCE_ROOT; }; D42C838821158B40008D3D83 /* SecAsn1Item.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SecAsn1Item.c; path = libsecurity_smime/lib/SecAsn1Item.c; sourceTree = SOURCE_ROOT; }; D42C8390211590BC008D3D83 /* CMSDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CMSDecoder.cpp; path = OSX/libsecurity_cms/lib/CMSDecoder.cpp; sourceTree = ""; }; @@ -12485,6 +12198,11 @@ D42C83A221159569008D3D83 /* cms-trust-settings-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "cms-trust-settings-test.c"; path = "OSX/libsecurity_cms/regressions/cms-trust-settings-test.c"; sourceTree = ""; }; D42C83A321159569008D3D83 /* cms-trust-settings-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cms-trust-settings-test.h"; path = "OSX/libsecurity_cms/regressions/cms-trust-settings-test.h"; sourceTree = ""; }; D42C83A621163866008D3D83 /* cert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cert.h; path = libsecurity_smime/lib/cert.h; sourceTree = SOURCE_ROOT; }; + D42D044124733BEA004E7AA2 /* com.apple.securityuploadd.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.securityuploadd.sb; sourceTree = ""; }; + D42F6FF0256EEE18004ED354 /* SecTrustExceptionResetCount.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustExceptionResetCount.h; sourceTree = ""; }; + D43534FC2525033E002E72F7 /* trustdFileLocations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = trustdFileLocations.h; sourceTree = ""; }; + D43534FD2525033E002E72F7 /* trustdFileLocations.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = trustdFileLocations.m; sourceTree = ""; }; + D43538302526BB01002E72F7 /* trust_config.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = trust_config.m; sourceTree = ""; }; D437185C211671A300EA350A /* cms-01-basic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "cms-01-basic.c"; path = "OSX/libsecurity_smime/regressions/cms-01-basic.c"; sourceTree = ""; }; D437185D211671A400EA350A /* smime-cms-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "smime-cms-test.c"; path = "OSX/libsecurity_smime/regressions/smime-cms-test.c"; sourceTree = ""; }; D437185E211671A400EA350A /* cms-01-basic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cms-01-basic.h"; path = "OSX/libsecurity_smime/regressions/cms-01-basic.h"; sourceTree = ""; }; @@ -12577,6 +12295,12 @@ D44282FE22D68556001746B3 /* TrustEvaluationTestHelpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustEvaluationTestHelpers.m; path = tests/TrustTests/TrustEvaluationTestHelpers.m; sourceTree = ""; }; D442AD62215ADA250050B50F /* AppleCorporateRootCA2.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = AppleCorporateRootCA2.cer; sourceTree = ""; }; D442AD68215ADA250050B50F /* AppleCorporateRootCA.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = AppleCorporateRootCA.cer; sourceTree = ""; }; + D445B30C258C07FC0019858E /* trustdFileHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = trustdFileHelper; sourceTree = BUILT_PRODUCTS_DIR; }; + D445B5B0258C08790019858E /* trustdFileHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = trustdFileHelper.m; sourceTree = ""; }; + D445B691258C088B0019858E /* com.apple.trustdFileHelper.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.trustdFileHelper.plist; sourceTree = ""; }; + D445B692258C08B10019858E /* trustdFileHelper.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = trustdFileHelper.8; sourceTree = ""; }; + D445B772258C08CC0019858E /* com.apple.trustdFileHelper.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.trustdFileHelper.sb; sourceTree = ""; }; + D445B773258C0F8D0019858E /* entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; D44D08B420AB890E0023C439 /* Security.apinotes */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Security.apinotes; path = base/Security.apinotes; sourceTree = ""; }; D44D1F662115893000E76E1A /* libCMS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCMS.a; sourceTree = BUILT_PRODUCTS_DIR; }; D44D1F8321158AAB00E76E1A /* plhash.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = plhash.h; path = libsecurity_smime/lib/plhash.h; sourceTree = SOURCE_ROOT; }; @@ -12606,7 +12330,6 @@ D458C4C0214E19FB0043D982 /* TrustInterfaceTests_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrustInterfaceTests_data.h; path = tests/TrustTests/FrameworkTests/TrustInterfaceTests_data.h; sourceTree = ""; }; D458C4C5214E1A400043D982 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = tests/TrustTests/TestRunners/Assets.xcassets; sourceTree = ""; }; D458C4C6214E1A400043D982 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = tests/TrustTests/TestRunners/main.m; sourceTree = ""; }; - D458C4C7214E1A400043D982 /* Base.lproj */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Base.lproj; path = tests/TrustTests/TestRunners/Base.lproj; sourceTree = ""; }; D458C4C8214E1A410043D982 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = tests/TrustTests/TestRunners/AppDelegate.h; sourceTree = ""; }; D458C4C9214E1A410043D982 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ViewController.h; path = tests/TrustTests/TestRunners/ViewController.h; sourceTree = ""; }; D458C4CA214E1A420043D982 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = tests/TrustTests/TestRunners/AppDelegate.m; sourceTree = ""; }; @@ -12622,13 +12345,14 @@ D458C513214E27620043D982 /* PolicyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PolicyTests.m; path = tests/TrustTests/EvaluationTests/PolicyTests.m; sourceTree = ""; }; D458C51B214E2CFF0043D982 /* si-20-sectrust-policies-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-20-sectrust-policies-data"; path = "OSX/shared_regressions/si-20-sectrust-policies-data"; sourceTree = ""; }; D458C51E214E2E0C0043D982 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Main.storyboard; path = tests/TrustTests/TestRunners/Main.storyboard; sourceTree = ""; }; + D458DAC22375FEA300E5890E /* TrustSettingsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustSettingsTests.m; path = tests/TrustTests/EvaluationTests/TrustSettingsTests.m; sourceTree = ""; }; + D458DAC52375FEE900E5890E /* TrustSettingsTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TrustSettingsTests_data.h; path = tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h; sourceTree = ""; }; D46246911F9AE2E400D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; D46246A21F9AE49E00D63882 /* oids.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oids.h; path = trust/headers/oids.h; sourceTree = ""; }; D46246A91F9AE6C900D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; D46246AF1F9AE73F00D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; D46246C31F9AEA5200D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; D46246CE1F9AEAE300D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; - D46513072097954B005D93FE /* si-23-sectrust-ocsp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "si-23-sectrust-ocsp.h"; sourceTree = ""; }; D47079F221128C46005BCFDA /* SecCMS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecCMS.h; path = CMS/SecCMS.h; sourceTree = ""; }; D47079F9211355B3005BCFDA /* CMSEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMSEncoder.h; path = CMS/CMSEncoder.h; sourceTree = ""; }; D4707A0521136E69005BCFDA /* TrustTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TrustTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -12640,11 +12364,27 @@ D4707A282113ECA0005BCFDA /* SecCmsMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsMessage.h; path = CMS/SecCmsMessage.h; sourceTree = ""; }; D4707A2B2114B31A005BCFDA /* SecCmsContentInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsContentInfo.h; path = CMS/SecCmsContentInfo.h; sourceTree = ""; }; D4707A2E2114C30A005BCFDA /* SecCmsDigestContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDigestContext.h; path = CMS/SecCmsDigestContext.h; sourceTree = ""; }; + D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PersonalizationTests.m; path = tests/TrustTests/DaemonTests/PersonalizationTests.m; sourceTree = ""; }; + D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustDaemonTestCase.m; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.m; sourceTree = ""; }; + D477CB6D237CBACD00C02355 /* TrustDaemonTestCase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TrustDaemonTestCase.h; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.h; sourceTree = ""; }; + D477CB76237E453C00C02355 /* si-88-sectrust-valid-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-88-sectrust-valid-data"; path = "SecurityTests/si-88-sectrust-valid-data"; sourceTree = ""; }; + D477CB7A237E4BD700C02355 /* ExceptionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ExceptionTests.m; path = tests/TrustTests/EvaluationTests/ExceptionTests.m; sourceTree = ""; }; + D477CB7D237F321400C02355 /* ExceptionTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ExceptionTests_data.h; path = tests/TrustTests/EvaluationTests/ExceptionTests_data.h; sourceTree = ""; }; + D477CB81237F692400C02355 /* RevocationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RevocationTests.m; path = tests/TrustTests/EvaluationTests/RevocationTests.m; sourceTree = ""; }; + D477CB85237F6A0700C02355 /* RevocationTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RevocationTests_data.h; path = tests/TrustTests/EvaluationTests/RevocationTests_data.h; sourceTree = ""; }; + D477CB86237F8B2F00C02355 /* CAIssuerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CAIssuerTests.m; path = tests/TrustTests/EvaluationTests/CAIssuerTests.m; sourceTree = ""; }; + D477CB89237F8CB300C02355 /* CAIssuerTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CAIssuerTests_data.h; path = tests/TrustTests/EvaluationTests/CAIssuerTests_data.h; sourceTree = ""; }; + D477CB8A237F8DBB00C02355 /* AllowlistBlocklistTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AllowlistBlocklistTests.m; path = tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m; sourceTree = ""; }; + D477CB8D237F8EB200C02355 /* AllowlistBlocklistTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AllowlistBlocklistTests_data.h; path = tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h; sourceTree = ""; }; + D477CB8E237F975500C02355 /* ValidTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ValidTests.m; path = tests/TrustTests/EvaluationTests/ValidTests.m; sourceTree = ""; }; D479F6E01F980F8F00388D28 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = en.lproj/Trust.strings; sourceTree = ""; }; + D47A085B2486EC1A000F2C49 /* AppleExternalRootCertificates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleExternalRootCertificates.h; sourceTree = ""; }; + D47A55892466100A0039285D /* MSUDataAccessor.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MSUDataAccessor.framework; path = System/Library/PrivateFrameworks/MSUDataAccessor.framework; sourceTree = SDKROOT; }; D47AB2CA2356AD72005A3801 /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; }; + D47C4579255244AD00460750 /* CertificateTransparency.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CertificateTransparency.m; sourceTree = ""; }; + D47C4730255246FC00460750 /* CertificateTransparency.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CertificateTransparency.h; sourceTree = ""; }; D47C56AB1DCA831C00E18518 /* lib_ios_x64.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = lib_ios_x64.xcconfig; path = xcconfig/lib_ios_x64.xcconfig; sourceTree = ""; }; D47C56AF1DCA841D00E18518 /* lib_ios_x64_shim.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = lib_ios_x64_shim.xcconfig; path = xcconfig/lib_ios_x64_shim.xcconfig; sourceTree = ""; }; - D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = all_arches.xcconfig; path = xcconfig/all_arches.xcconfig; sourceTree = ""; }; D47CA65C1EB036450038E2BB /* libMobileGestalt.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMobileGestalt.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.Internal.sdk/usr/lib/libMobileGestalt.dylib; sourceTree = DEVELOPER_DIR; }; D47DCCB423427C7D00B80E37 /* md.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = md.m; sourceTree = ""; }; D47DCCB723427C8D00B80E37 /* md.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = md.h; sourceTree = ""; }; @@ -12655,6 +12395,7 @@ D4911167209558900066A1E4 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; D4961BBD2079423300F16DA7 /* TrustURLSessionDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TrustURLSessionDelegate.m; sourceTree = ""; }; D4961BC52079426000F16DA7 /* TrustURLSessionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TrustURLSessionDelegate.h; sourceTree = ""; }; + D49A370B23877ECC0065719F /* OCSPCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OCSPCacheTests.m; path = tests/TrustTests/DaemonTests/OCSPCacheTests.m; sourceTree = ""; }; D4A0F8BA211E69CB00443CA1 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = tests/TrustTests/Info.plist; sourceTree = ""; }; D4A0F8BB211E69CB00443CA1 /* TestMacroConversions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestMacroConversions.h; path = tests/TrustTests/TestMacroConversions.h; sourceTree = ""; }; D4A0F8C1211E6A2F00443CA1 /* si-82-sectrust-ct-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-82-sectrust-ct-data"; path = "OSX/shared_regressions/si-82-sectrust-ct-data"; sourceTree = ""; }; @@ -12669,7 +12410,6 @@ D4A7DD7320A26CF900F51F3F /* AuthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AuthKit.framework; path = System/Library/PrivateFrameworks/AuthKit.framework; sourceTree = SDKROOT; }; D4AA0D9922FB959600D77FA4 /* si-29-cms-chain-mode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-29-cms-chain-mode.m"; sourceTree = ""; }; D4AA0D9C22FB962300D77FA4 /* si-29-cms-chain-mode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "si-29-cms-chain-mode.h"; sourceTree = ""; }; - D4AA64831E97270300D317ED /* si-18-certificate-parse */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-18-certificate-parse"; path = "OSX/shared_regressions/si-18-certificate-parse"; sourceTree = SOURCE_ROOT; }; D4AC5764214E195200A32C01 /* VerifyDateTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = VerifyDateTests.m; path = tests/TrustTests/EvaluationTests/VerifyDateTests.m; sourceTree = ""; }; D4AC5765214E195300A32C01 /* VerifyDateTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VerifyDateTests_data.h; path = tests/TrustTests/EvaluationTests/VerifyDateTests_data.h; sourceTree = ""; }; D4AC5766214E195300A32C01 /* ECTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ECTests.m; path = tests/TrustTests/EvaluationTests/ECTests.m; sourceTree = ""; }; @@ -12693,14 +12433,18 @@ D4B6D57B2069D8450099FBEF /* si-34-cms-timestamp.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-34-cms-timestamp.m"; sourceTree = ""; }; D4B6D5822069D85B0099FBEF /* si-34-cms-timestamp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "si-34-cms-timestamp.h"; sourceTree = ""; }; D4B858661D370D9A003B2D95 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.Internal.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; }; + D4BA4FD22388687A000B9E64 /* OCSPCacheTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OCSPCacheTests_data.h; path = tests/TrustTests/DaemonTests/OCSPCacheTests_data.h; sourceTree = ""; }; D4BEECE61E93093A00F76D1A /* trustd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = trustd.c; sourceTree = ""; }; D4C263C51F8FF2A9001317EA /* generateErrStrings.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = generateErrStrings.pl; path = OSX/lib/generateErrStrings.pl; sourceTree = ""; usesTabs = 1; }; D4C263C81F952E64001317EA /* SecDebugErrorMessages.strings */ = {isa = PBXFileReference; explicitFileType = text.plist.strings; fileEncoding = 10; name = SecDebugErrorMessages.strings; path = derived_src/SecDebugErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; D4C263CD1F952F6C001317EA /* SecErrorMessages.strings */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = SecErrorMessages.strings; path = derived_src/en.lproj/SecErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; - D4C6C5C71FB2AD3F007EA57E /* si-87-sectrust-name-constraints */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "si-87-sectrust-name-constraints"; sourceTree = ""; }; + D4C573C3255B6A1800AB5D78 /* si-26-cms-apple-signed-samples.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-26-cms-apple-signed-samples.m"; sourceTree = ""; }; + D4C5749F255B6AA600AB5D78 /* si-26-cms-apple-signed-samples.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "si-26-cms-apple-signed-samples.h"; sourceTree = ""; }; + D4C578E6255B746600AB5D78 /* PolicyInterfaceTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PolicyInterfaceTests.m; path = tests/TrustTests/FrameworkTests/PolicyInterfaceTests.m; sourceTree = ""; }; D4C6C5CB1FB3B3CC007EA57E /* libarchive.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libarchive.tbd; path = usr/lib/libarchive.tbd; sourceTree = SDKROOT; }; D4C6C5CE1FB3B44C007EA57E /* libarchive.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libarchive.2.dylib; path = /usr/lib/libarchive.2.dylib; sourceTree = SDKROOT; }; - D4C8A1511E66709800CD6DF1 /* si-32-sectrust-pinning-required.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "si-32-sectrust-pinning-required.h"; sourceTree = ""; }; + D4C88D87262E5DB20006FFB1 /* si-27-cms-parse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-27-cms-parse.m"; sourceTree = ""; }; + D4C88D8A262E660A0006FFB1 /* si-27-cms-parse */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "si-27-cms-parse"; path = "OSX/shared_regressions/si-27-cms-parse"; sourceTree = SOURCE_ROOT; }; D4CF6E63211588660014647E /* SecSMIME.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecSMIME.h; path = libsecurity_smime/lib/SecSMIME.h; sourceTree = SOURCE_ROOT; }; D4CF6E64211588670014647E /* cmspriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cmspriv.h; path = libsecurity_smime/lib/cmspriv.h; sourceTree = SOURCE_ROOT; }; D4CF6E65211588670014647E /* cmspubkey.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = cmspubkey.c; path = libsecurity_smime/lib/cmspubkey.c; sourceTree = SOURCE_ROOT; }; @@ -12729,18 +12473,20 @@ D4CF6E7D2115886F0014647E /* cmsenvdata.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = cmsenvdata.c; path = libsecurity_smime/lib/cmsenvdata.c; sourceTree = SOURCE_ROOT; }; D4CF6E7F211588700014647E /* cmsrecinfo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = cmsrecinfo.c; path = libsecurity_smime/lib/cmsrecinfo.c; sourceTree = SOURCE_ROOT; }; D4CF6E81211588710014647E /* SecAsn1Item.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecAsn1Item.h; path = libsecurity_smime/lib/SecAsn1Item.h; sourceTree = SOURCE_ROOT; }; - D4CFAA7D1E660BB3004746AA /* si-32-sectrust-pinning-required.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-32-sectrust-pinning-required.m"; sourceTree = ""; }; + D4D1CBB325AD0AAF0068595B /* CertificateServerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CertificateServerTests.m; path = tests/TrustTests/DaemonTests/CertificateServerTests.m; sourceTree = ""; }; + D4D1CC9525AD0ACD0068595B /* CertificateServerTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CertificateServerTests_data.h; path = tests/TrustTests/DaemonTests/CertificateServerTests_data.h; sourceTree = ""; }; + D4D1CF3025AD37260068595B /* TrustServerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustServerTests.m; path = tests/TrustTests/DaemonTests/TrustServerTests.m; sourceTree = ""; }; + D4D1D1D125AFDA3D0068595B /* TrustServerTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TrustServerTests_data.h; path = tests/TrustTests/DaemonTests/TrustServerTests_data.h; sourceTree = ""; }; D4D1FDDC21165F8B003538E2 /* libsecurity_cms_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_cms_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; D4D718341E04A721000AE7A6 /* spbkdf-01-hmac-sha256.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "spbkdf-01-hmac-sha256.c"; sourceTree = ""; }; - D4D886BE1CEB9F3B00DC7583 /* ssl-policy-certs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "ssl-policy-certs"; sourceTree = ""; }; - D4D886E81CEBDD2A00DC7583 /* nist-certs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "nist-certs"; sourceTree = ""; }; D4D92DA32277E6D10009A7CF /* PathParseTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PathParseTests_data.h; path = tests/TrustTests/EvaluationTests/PathParseTests_data.h; sourceTree = ""; }; D4D92DA422788FEB0009A7CF /* NISTTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = NISTTests.m; path = tests/TrustTests/EvaluationTests/NISTTests.m; sourceTree = ""; }; D4D92DA72278904F0009A7CF /* nist-certs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "nist-certs"; path = "SecurityTests/nist-certs"; sourceTree = ""; }; D4EA5CF622B225C000883439 /* LoggingServerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LoggingServerTests.m; path = tests/TrustTests/DaemonTests/LoggingServerTests.m; sourceTree = ""; }; - D4EC94FA1CEA482D0083E753 /* si-20-sectrust-policies-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-20-sectrust-policies-data"; path = "../OSX/shared_regressions/si-20-sectrust-policies-data"; sourceTree = ""; }; D4EF321E215F0F76000A31A5 /* SecTrustStoreServer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecTrustStoreServer.m; sourceTree = ""; }; D4EF3222215F102F000A31A5 /* CTTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CTTests_data.h; path = tests/TrustTests/EvaluationTests/CTTests_data.h; sourceTree = ""; }; + D4FA5BD8259D0FCB00EDB660 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + D4FA61F8259D10E700EDB660 /* trustdFileHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = trustdFileHelper.h; sourceTree = ""; }; D4FC521C1EC3E05B00E99785 /* smime_attr_emails.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = smime_attr_emails.h; sourceTree = ""; }; D4FD421B217D7891002B7EE2 /* NameConstraintsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = NameConstraintsTests.m; path = tests/TrustTests/EvaluationTests/NameConstraintsTests.m; sourceTree = ""; }; D4FD421E217D78BB002B7EE2 /* NameConstraintsTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NameConstraintsTests_data.h; path = tests/TrustTests/EvaluationTests/NameConstraintsTests_data.h; sourceTree = ""; }; @@ -12748,6 +12494,7 @@ D4FD4222217D7B48002B7EE2 /* PathScoringTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PathScoringTests_data.h; path = tests/TrustTests/EvaluationTests/PathScoringTests_data.h; sourceTree = ""; }; D4FD4223217D7BE3002B7EE2 /* libarchive.2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libarchive.2.tbd; path = usr/lib/libarchive.2.tbd; sourceTree = SDKROOT; }; DA2C402D2189302E005F1CC3 /* mach_notify.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = mach_notify.defs; sourceTree = ""; }; + DA2F591523A32BB400C30285 /* SoftLinking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SoftLinking.framework; path = System/Library/PrivateFrameworks/SoftLinking.framework; sourceTree = SDKROOT; }; DA30D6761DF8C8FB00EC6B43 /* KeychainSyncAccountUpdater.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeychainSyncAccountUpdater.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; DA30D6781DF8C8FB00EC6B43 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DA30D6831DF8CA4100EC6B43 /* KeychainSyncAccountUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeychainSyncAccountUpdater.h; sourceTree = ""; }; @@ -12792,6 +12539,8 @@ DC05037621409A4000A8EDB7 /* OCMockUmbrella.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OCMockUmbrella.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DC05037821409A4100A8EDB7 /* OCMockUmbrella.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OCMockUmbrella.h; sourceTree = ""; }; DC05037921409A4100A8EDB7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DC061A6E246211DD0026ADB3 /* CKKSLocalResetOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSLocalResetOperation.h; sourceTree = ""; }; + DC061A70246211DE0026ADB3 /* CKKSLocalResetOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSLocalResetOperation.m; sourceTree = ""; }; DC07090222936BCC002711B9 /* OctagonTests+ErrorHandling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+ErrorHandling.swift"; sourceTree = ""; }; DC08D1C21E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudKitKeychainSyncingMockXCTest.h; sourceTree = ""; }; DC08D1C31E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudKitKeychainSyncingMockXCTest.m; sourceTree = ""; }; @@ -13172,23 +12921,23 @@ DC0BCABE1D8B85BC00070CB0 /* SecTransformValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransformValidator.h; sourceTree = ""; }; DC0BCABF1D8B85BC00070CB0 /* SecReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecReadTransform.h; sourceTree = ""; }; DC0BCB081D8B894F00070CB0 /* libsecurity_translocate.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_translocate.a; sourceTree = BUILT_PRODUCTS_DIR; }; - DC0BCB0A1D8B898100070CB0 /* SecTranslocateClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateClient.cpp; sourceTree = ""; }; + DC0BCB0A1D8B898100070CB0 /* SecTranslocateClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateClient.cpp; sourceTree = ""; usesTabs = 0; }; DC0BCB0B1D8B898100070CB0 /* SecTranslocateClient.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateClient.hpp; sourceTree = ""; }; - DC0BCB0C1D8B898100070CB0 /* SecTranslocateXPCServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateXPCServer.cpp; sourceTree = ""; }; + DC0BCB0C1D8B898100070CB0 /* SecTranslocateXPCServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateXPCServer.cpp; sourceTree = ""; usesTabs = 0; }; DC0BCB0D1D8B898100070CB0 /* SecTranslocateXPCServer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateXPCServer.hpp; sourceTree = ""; }; DC0BCB0E1D8B898100070CB0 /* SecTranslocateInterface.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateInterface.hpp; sourceTree = ""; }; DC0BCB0F1D8B898100070CB0 /* SecTranslocateDANotification.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateDANotification.cpp; sourceTree = ""; }; DC0BCB101D8B898100070CB0 /* SecTranslocateDANotification.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateDANotification.hpp; sourceTree = ""; }; DC0BCB111D8B898100070CB0 /* SecTranslocateLSNotification.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateLSNotification.cpp; sourceTree = ""; }; DC0BCB121D8B898100070CB0 /* SecTranslocateLSNotification.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateLSNotification.hpp; sourceTree = ""; }; - DC0BCB131D8B898100070CB0 /* SecTranslocateShared.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateShared.hpp; sourceTree = ""; }; - DC0BCB141D8B898100070CB0 /* SecTranslocateShared.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateShared.cpp; sourceTree = ""; }; + DC0BCB131D8B898100070CB0 /* SecTranslocateShared.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateShared.hpp; sourceTree = ""; usesTabs = 0; }; + DC0BCB141D8B898100070CB0 /* SecTranslocateShared.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateShared.cpp; sourceTree = ""; usesTabs = 0; }; DC0BCB151D8B898100070CB0 /* SecTranslocateServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateServer.cpp; sourceTree = ""; }; DC0BCB161D8B898100070CB0 /* SecTranslocateServer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateServer.hpp; sourceTree = ""; }; DC0BCB171D8B898100070CB0 /* SecTranslocate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTranslocate.h; sourceTree = ""; }; - DC0BCB181D8B898100070CB0 /* SecTranslocate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocate.cpp; sourceTree = ""; }; + DC0BCB181D8B898100070CB0 /* SecTranslocate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocate.cpp; sourceTree = ""; usesTabs = 0; }; DC0BCB191D8B898100070CB0 /* SecTranslocateUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateUtilities.cpp; sourceTree = ""; }; - DC0BCB1A1D8B898100070CB0 /* SecTranslocateUtilities.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateUtilities.hpp; sourceTree = ""; }; + DC0BCB1A1D8B898100070CB0 /* SecTranslocateUtilities.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateUtilities.hpp; sourceTree = ""; usesTabs = 0; }; DC0BCB1B1D8B898100070CB0 /* SecTranslocateInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTranslocateInterface.cpp; sourceTree = ""; }; DC0BCBFD1D8C648C00070CB0 /* libregressionBase.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libregressionBase.a; sourceTree = BUILT_PRODUCTS_DIR; }; DC0BCBFE1D8C64B500070CB0 /* test-00-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "test-00-test.c"; path = "OSX/regressions/test/test-00-test.c"; sourceTree = ""; }; @@ -13280,6 +13029,10 @@ DC0BCDB41D8C6A5B00070CB0 /* not_on_this_platorm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = not_on_this_platorm.c; sourceTree = ""; }; DC0BD4EF21BB05F2006B9154 /* CKKSKeychainBackedKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSKeychainBackedKey.h; sourceTree = ""; }; DC0BD4F021BB05F2006B9154 /* CKKSKeychainBackedKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSKeychainBackedKey.m; sourceTree = ""; }; + DC0D15FF2363A1D6007F0951 /* OTSetCDPBitOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSetCDPBitOperation.h; sourceTree = ""; }; + DC0D16002363A1D6007F0951 /* OTSetCDPBitOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSetCDPBitOperation.m; sourceTree = ""; }; + DC0D16042363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTDetermineCDPBitStatusOperation.h; sourceTree = ""; }; + DC0D16052363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTDetermineCDPBitStatusOperation.m; sourceTree = ""; }; DC0EF8EF208697C600AB9E95 /* tpctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tpctl; sourceTree = BUILT_PRODUCTS_DIR; }; DC0EF8F1208697C600AB9E95 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; DC0FA6AE2291F63F00FE01C4 /* OctagonPendingFlag.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonPendingFlag.h; sourceTree = ""; }; @@ -13362,7 +13115,6 @@ DC1787241D778FDE00B50D50 /* SecManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecManifest.h; path = OSX/libsecurity_manifest/lib/SecManifest.h; sourceTree = ""; }; DC1787251D778FDE00B50D50 /* SecureDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureDownloadInternal.h; path = OSX/libsecurity_manifest/lib/SecureDownloadInternal.h; sourceTree = ""; }; DC1787281D77903700B50D50 /* SecAccessPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAccessPriv.h; path = OSX/libsecurity_keychain/lib/SecAccessPriv.h; sourceTree = ""; }; - DC1787291D77903700B50D50 /* SecCertificateBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateBundle.h; path = OSX/libsecurity_keychain/lib/SecCertificateBundle.h; sourceTree = ""; }; DC17872A1D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecFDERecoveryAsymmetricCrypto.h; path = OSX/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h; sourceTree = ""; }; DC17872B1D77903700B50D50 /* SecIdentitySearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearchPriv.h; path = OSX/libsecurity_keychain/lib/SecIdentitySearchPriv.h; sourceTree = ""; }; DC17872C1D77903700B50D50 /* SecKeychainItemExtendedAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainItemExtendedAttributes.h; path = OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h; sourceTree = ""; }; @@ -13393,7 +13145,6 @@ DC1787671D77911D00B50D50 /* osKeyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = osKeyTemplates.h; path = OSX/libsecurity_asn1/lib/osKeyTemplates.h; sourceTree = ""; }; DC1787681D77911D00B50D50 /* secasn1t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = secasn1t.h; path = OSX/libsecurity_asn1/lib/secasn1t.h; sourceTree = ""; }; DC1787691D77911D00B50D50 /* X509Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = X509Templates.h; path = OSX/libsecurity_asn1/lib/X509Templates.h; sourceTree = ""; }; - DC1787731D77915500B50D50 /* SecBreadcrumb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecBreadcrumb.h; path = OSX/Breadcrumb/SecBreadcrumb.h; sourceTree = SOURCE_ROOT; }; DC1789041D77980500B50D50 /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DC1789121D7798B300B50D50 /* libDiagnosticMessagesClient.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libDiagnosticMessagesClient.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/lib/libDiagnosticMessagesClient.dylib; sourceTree = DEVELOPER_DIR; }; DC1789141D77997F00B50D50 /* libOpenScriptingUtil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libOpenScriptingUtil.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/lib/libOpenScriptingUtil.dylib; sourceTree = DEVELOPER_DIR; }; @@ -13404,7 +13155,6 @@ DC1789221D7799A600B50D50 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; }; DC1789241D7799CD00B50D50 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; DC1789261D7799D300B50D50 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; }; - DC1789A01D779DEE00B50D50 /* SecBreadcrumb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SecBreadcrumb.c; path = OSX/Breadcrumb/SecBreadcrumb.c; sourceTree = ""; }; DC1789A41D779E3B00B50D50 /* dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dummy.cpp; path = OSX/lib/dummy.cpp; sourceTree = ""; }; DC178A0E1D77A1E700B50D50 /* cssm.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cssm.mdsinfo; path = OSX/libsecurity_cssm/mds/cssm.mdsinfo; sourceTree = ""; }; DC178A0F1D77A1E700B50D50 /* csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_capabilities.mdsinfo; path = OSX/libsecurity_apple_csp/mds/csp_capabilities.mdsinfo; sourceTree = ""; }; @@ -13426,7 +13176,6 @@ DC178A311D77A1F500B50D50 /* FDEPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = FDEPrefs.plist; path = OSX/lib/FDEPrefs.plist; sourceTree = ""; }; DC178A321D77A1F500B50D50 /* SecDebugErrorMessages.strings */ = {isa = PBXFileReference; explicitFileType = text.plist.strings; fileEncoding = 10; name = SecDebugErrorMessages.strings; path = derived_src/SecDebugErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; DC178A341D77A1F500B50D50 /* SecErrorMessages.strings */ = {isa = PBXFileReference; explicitFileType = text.plist.strings; fileEncoding = 10; name = SecErrorMessages.strings; path = derived_src/en.lproj/SecErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; - DC178A351D77A1F500B50D50 /* framework.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = framework.sb; path = OSX/lib/framework.sb; sourceTree = ""; }; DC178A391D77A1F500B50D50 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = OSX/lib/en.lproj/InfoPlist.strings; sourceTree = ""; }; DC178A3A1D77A1F500B50D50 /* TimeStampingPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = TimeStampingPrefs.plist; path = OSX/lib/TimeStampingPrefs.plist; sourceTree = ""; }; DC178A3C1D77A1F500B50D50 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = OSX/lib/en.lproj/authorization.dfr.prompts.strings; sourceTree = ""; }; @@ -13472,7 +13221,6 @@ DC24B5681DA326B900330B48 /* rule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rule.h; path = OSX/authd/rule.h; sourceTree = ""; }; DC24B5691DA326B900330B48 /* server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = server.h; path = OSX/authd/server.h; sourceTree = ""; }; DC24B56A1DA326B900330B48 /* session.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = session.h; path = OSX/authd/session.h; sourceTree = ""; }; - DC24B5701DA3274000330B48 /* breadcrumb_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = breadcrumb_regressions.h; path = OSX/Breadcrumb/breadcrumb_regressions.h; sourceTree = ""; }; DC24B5711DA327A800330B48 /* KDAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KDAppDelegate.h; path = OSX/Keychain/KDAppDelegate.h; sourceTree = SOURCE_ROOT; }; DC24B5721DA327A800330B48 /* KDCirclePeer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KDCirclePeer.h; path = OSX/Keychain/KDCirclePeer.h; sourceTree = SOURCE_ROOT; }; DC24B5731DA327A800330B48 /* KDSecCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KDSecCircle.h; path = OSX/Keychain/KDSecCircle.h; sourceTree = SOURCE_ROOT; }; @@ -13507,6 +13255,8 @@ DC311E782124B8EF002F5EAE /* aks_real_witness.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = aks_real_witness.h; sourceTree = ""; }; DC311E792124B8EF002F5EAE /* aks_real_witness.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = aks_real_witness.c; sourceTree = ""; }; DC340C53208E7BAE004D7EEC /* swift_binary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = swift_binary.xcconfig; path = xcconfig/swift_binary.xcconfig; sourceTree = ""; }; + DC3412E5245780B9008ABD0A /* CKKSOperationDependencies.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSOperationDependencies.h; sourceTree = ""; }; + DC3412E6245780BA008ABD0A /* CKKSOperationDependencies.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSOperationDependencies.m; sourceTree = ""; }; DC3502B51E0208BE00BC0587 /* CKKSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CKKSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DC3502B71E0208BE00BC0587 /* CKKSTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSTests.m; sourceTree = ""; }; DC3502B91E0208BE00BC0587 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -13528,6 +13278,7 @@ DC3A4B601D91EAC500E46D4A /* com.apple.CodeSigningHelper.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.CodeSigningHelper.sb; sourceTree = ""; }; DC3A4B621D91EAC500E46D4A /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; usesTabs = 1; }; DC3A81D41D99D567000C7419 /* libcoretls_cfhelpers.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcoretls_cfhelpers.dylib; path = usr/lib/libcoretls_cfhelpers.dylib; sourceTree = SDKROOT; }; + DC3A9B2523A9D6120073ED06 /* Container_BottledPeers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_BottledPeers.swift; sourceTree = ""; }; DC3AA27C2097DF94007CA68A /* security_tool_commands_table.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = security_tool_commands_table.h; sourceTree = ""; }; DC3AF52A2229E6C0006577E8 /* CKKSListenerCollection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSListenerCollection.h; sourceTree = ""; }; DC3AF52B2229E6C0006577E8 /* CKKSListenerCollection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSListenerCollection.m; sourceTree = ""; }; @@ -13537,11 +13288,13 @@ DC4269031E82EDAC002B7110 /* SecItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecItem.m; sourceTree = ""; }; DC4269061E82FBDF002B7110 /* server_security_helpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = server_security_helpers.m; sourceTree = ""; }; DC4269071E82FBDF002B7110 /* server_security_helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = server_security_helpers.h; sourceTree = ""; }; + DC4415B323610BF40087981C /* OctagonTests+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+Account.swift"; sourceTree = ""; }; DC45D43B22EB619D00CEB6B7 /* OctagonStateMachineObservers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonStateMachineObservers.h; sourceTree = ""; }; DC45D43C22EB619D00CEB6B7 /* OctagonStateMachineObservers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OctagonStateMachineObservers.m; sourceTree = ""; }; DC4A76A2221267D4006F2D8F /* EscrowRequestServerHelpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EscrowRequestServerHelpers.m; sourceTree = ""; }; DC4A76A4221267FB006F2D8F /* EscrowRequestServerHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EscrowRequestServerHelpers.h; sourceTree = ""; }; DC4A76A92212698B006F2D8F /* CloudServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/PrivateFrameworks/CloudServices.framework; sourceTree = DEVELOPER_DIR; }; + DC4CD9822372294D00EF55FC /* OctagonTests+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OctagonTests+Helpers.swift"; sourceTree = ""; }; DC4D49D81F857728007AF2B8 /* CKKSSerializedKey.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = CKKSSerializedKey.proto; sourceTree = ""; }; DC4DB14E1E24692100CD6769 /* CKKSKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSKey.h; sourceTree = ""; }; DC4DB14F1E24692100CD6769 /* CKKSKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSKey.m; sourceTree = ""; }; @@ -13827,6 +13580,8 @@ DC6ACC401E81DF9400125DC5 /* server_endpoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = server_endpoint.m; sourceTree = ""; }; DC6DE897213076C000C6B56D /* OTSOSUpgradeOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSOSUpgradeOperation.h; sourceTree = ""; }; DC6DE898213076C000C6B56D /* OTSOSUpgradeOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSOSUpgradeOperation.m; sourceTree = ""; }; + DC6E02122405DDC300C61335 /* OTModifyUserControllableViewStatusOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTModifyUserControllableViewStatusOperation.h; sourceTree = ""; }; + DC6E02132405DDC400C61335 /* OTModifyUserControllableViewStatusOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTModifyUserControllableViewStatusOperation.m; sourceTree = ""; }; DC7181062089172F00B2CB13 /* TrustedPeersHelper-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TrustedPeersHelper-entitlements.plist"; sourceTree = ""; }; DC71D8DD1D94CF3C0065FB93 /* lib_ios_shim.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = lib_ios_shim.xcconfig; path = xcconfig/lib_ios_shim.xcconfig; sourceTree = ""; }; DC72502D229600A800493D88 /* OctagonTests+Reset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+Reset.swift"; sourceTree = ""; }; @@ -13853,6 +13608,7 @@ DC7EB920211E17E500516452 /* OTAccountMetadataClassC+KeychainSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OTAccountMetadataClassC+KeychainSupport.h"; sourceTree = ""; }; DC7EB921211E17E500516452 /* OTAccountMetadataClassC+KeychainSupport.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OTAccountMetadataClassC+KeychainSupport.m"; sourceTree = ""; }; DC7EB928211E20DF00516452 /* OctagonDataPersistenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OctagonDataPersistenceTests.swift; sourceTree = ""; }; + DC7F6A7C233D7FAC00DF5769 /* OctagonTests+ForwardCompatibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+ForwardCompatibility.swift"; sourceTree = ""; }; DC7F79B522EA4ED4001FB69A /* OctagonTests+CKKS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+CKKS.swift"; sourceTree = ""; }; DC7F79B822EA5C72001FB69A /* OTLocalCKKSResetOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTLocalCKKSResetOperation.h; sourceTree = ""; }; DC7F79B922EA5C72001FB69A /* OTLocalCKKSResetOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTLocalCKKSResetOperation.m; sourceTree = ""; }; @@ -13861,8 +13617,10 @@ DC844AEC1E81F315007AAB71 /* client_endpoint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = client_endpoint.m; sourceTree = ""; }; DC85687C2284E7850088D3EF /* OctagonTestMocks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OctagonTestMocks.swift; sourceTree = ""; }; DC85687F2284E79C0088D3EF /* OctagonEscrowRecoverer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OctagonEscrowRecoverer.h; sourceTree = ""; }; + DC86122B2408AC190092E93B /* CKKSTests+ItemSyncChoice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+ItemSyncChoice.m"; sourceTree = ""; }; DC8757F2218D2003000E65F1 /* OTRemovePeersOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTRemovePeersOperation.h; sourceTree = ""; }; DC8757F3218D2003000E65F1 /* OTRemovePeersOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTRemovePeersOperation.m; sourceTree = ""; }; + DC880F67243D4CC00059806D /* CKKSLogging.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSLogging.m; sourceTree = ""; }; DC8834081D8A218F00CE0ACA /* libASN1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libASN1.a; sourceTree = BUILT_PRODUCTS_DIR; }; DC88340A1D8A21AA00CE0ACA /* SecAsn1Coder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAsn1Coder.c; sourceTree = ""; }; DC88340C1D8A21AA00CE0ACA /* SecAsn1Templates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAsn1Templates.c; sourceTree = ""; }; @@ -13924,6 +13682,7 @@ DC88466C2237407500738068 /* TPDictionaryMatchingRuleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPDictionaryMatchingRuleTests.m; sourceTree = ""; }; DC88467F2237431400738068 /* TPDictionaryMatchingRules.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TPDictionaryMatchingRules.h; sourceTree = ""; }; DC8846802237431400738068 /* TPDictionaryMatchingRules.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPDictionaryMatchingRules.m; sourceTree = ""; }; + DC89608C2395C75500D339D9 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; DC8D238C2064649400E163C8 /* CKKSAPSHandlingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSAPSHandlingTests.m; sourceTree = ""; }; DC8E04901D7F6780006D80EB /* lib_ios.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = lib_ios.xcconfig; path = xcconfig/lib_ios.xcconfig; sourceTree = ""; }; DC9061B822B02BA30071474D /* TPTypes.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPTypes.m; sourceTree = ""; }; @@ -13934,9 +13693,12 @@ DC90A4C621F279D4001300EB /* SecEscrowPendingRecord.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecEscrowPendingRecord.proto; sourceTree = ""; }; DC93F02722387A010072720A /* OTSOSUpdatePreapprovalsOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSOSUpdatePreapprovalsOperation.h; sourceTree = ""; }; DC93F02822387A010072720A /* OTSOSUpdatePreapprovalsOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSOSUpdatePreapprovalsOperation.m; sourceTree = ""; }; + DC947E812463831E005B8669 /* CKKSCheckKeyHierarchyOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSCheckKeyHierarchyOperation.h; sourceTree = ""; }; + DC947E832463831F005B8669 /* CKKSCheckKeyHierarchyOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSCheckKeyHierarchyOperation.m; sourceTree = ""; }; DC94BCC81F10448600E07CEB /* CloudKitCategories.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CloudKitCategories.h; sourceTree = ""; }; DC94BCC91F10448600E07CEB /* CloudKitCategories.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CloudKitCategories.m; sourceTree = ""; }; DC976C581E3AC5E50012A6DD /* PlatformFeatures.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = PlatformFeatures.xcconfig; path = xcconfig/PlatformFeatures.xcconfig; sourceTree = ""; }; + DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_UserSync.swift; sourceTree = ""; }; DC99B89220EACA470065B73B /* OctagonTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OctagonTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DC99B89320EACA480065B73B /* OctagonTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "OctagonTests-Info.plist"; sourceTree = ""; }; DC9A2C5E1EB3F556008FAC27 /* CKKSTests+Coalesce.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+Coalesce.m"; sourceTree = ""; }; @@ -13960,6 +13722,9 @@ DCA4D1F41E5520550056214F /* CKKSCurrentKeyPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSCurrentKeyPointer.m; sourceTree = ""; }; DCA4D2131E5684220056214F /* CKKSReencryptOutgoingItemsOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSReencryptOutgoingItemsOperation.h; sourceTree = ""; }; DCA4D2141E5684220056214F /* CKKSReencryptOutgoingItemsOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSReencryptOutgoingItemsOperation.m; sourceTree = ""; }; + DCA72ADF2530D3BD00CCB062 /* CKKSKeychainViewState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSKeychainViewState.h; sourceTree = ""; }; + DCA72AE02530D3BD00CCB062 /* CKKSKeychainViewState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSKeychainViewState.m; sourceTree = ""; }; + DCA7F7EE23A44AA200927989 /* OctagonPolicyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OctagonPolicyTests.swift; sourceTree = ""; }; DCA9BC00221B721D00B4EB26 /* CKKSCloudKitClassDependencies.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSCloudKitClassDependencies.h; sourceTree = ""; }; DCA9BC01221B721E00B4EB26 /* CKKSCloudKitClassDependencies.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSCloudKitClassDependencies.m; sourceTree = ""; }; DCA9BC05221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSMockSOSPresentAdapter.h; sourceTree = ""; }; @@ -13971,6 +13736,7 @@ DCA9D84521FFE7CF00B27421 /* EscrowRequestXPCProtocol.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EscrowRequestXPCProtocol.m; sourceTree = ""; }; DCA9D84B21FFF04600B27421 /* EscrowRequestServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EscrowRequestServer.h; sourceTree = ""; }; DCA9D84C21FFF04700B27421 /* EscrowRequestServer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EscrowRequestServer.m; sourceTree = ""; }; + DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_RecoveryKey.swift; sourceTree = ""; }; DCAB17CB21FFF6C400E1DFCF /* MockSynchronousEscrowServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockSynchronousEscrowServer.h; sourceTree = ""; }; DCAB17CC21FFF6C400E1DFCF /* MockSynchronousEscrowServer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockSynchronousEscrowServer.m; sourceTree = ""; }; DCAB17CF2200D26700E1DFCF /* SecEscrowPendingRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEscrowPendingRecord.h; sourceTree = ""; }; @@ -14166,7 +13932,6 @@ DCB342441D8A32A20054D16E /* SecBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecBase.cpp; sourceTree = ""; }; DCB342451D8A32A20054D16E /* SecBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecBridge.h; sourceTree = ""; }; DCB342461D8A32A20054D16E /* SecCertificate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificate.cpp; sourceTree = ""; }; - DCB342471D8A32A20054D16E /* SecCertificateBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificateBundle.cpp; sourceTree = ""; }; DCB342491D8A32A20054D16E /* SecIdentity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentity.cpp; sourceTree = ""; }; DCB3424A1D8A32A20054D16E /* SecIdentitySearch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentitySearch.cpp; sourceTree = ""; }; DCB3424B1D8A32A20054D16E /* SecItemConstants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecItemConstants.c; sourceTree = ""; }; @@ -14217,7 +13982,6 @@ DCB342A51D8A32A20054D16E /* PolicyCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolicyCursor.h; sourceTree = ""; }; DCB342A61D8A32A20054D16E /* SecCFTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCFTypes.cpp; sourceTree = ""; }; DCB342A71D8A32A20054D16E /* SecCFTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCFTypes.h; sourceTree = ""; }; - DCB342A81D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainAddIToolsPassword.cpp; sourceTree = ""; }; DCB342AA1D8A32A20054D16E /* StorageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = StorageManager.cpp; sourceTree = ""; }; DCB342AB1D8A32A20054D16E /* Trust.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Trust.cpp; sourceTree = ""; }; DCB342AC1D8A32A20054D16E /* Trust.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Trust.h; sourceTree = ""; }; @@ -14332,12 +14096,14 @@ DCB3446B1D8A35270054D16E /* kc-40-seckey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-40-seckey.m"; path = "regressions/kc-40-seckey.m"; sourceTree = ""; }; DCB3446C1D8A35270054D16E /* kc-41-sececkey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-41-sececkey.m"; path = "regressions/kc-41-sececkey.m"; sourceTree = ""; }; DCB3446D1D8A35270054D16E /* kc-43-seckey-interop.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-43-seckey-interop.m"; path = "regressions/kc-43-seckey-interop.m"; sourceTree = ""; }; - DCB3446E1D8A35270054D16E /* kc-42-trust-revocation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-42-trust-revocation.c"; path = "regressions/kc-42-trust-revocation.c"; sourceTree = ""; }; - DCB3446F1D8A35270054D16E /* si-20-sectrust-provisioning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "si-20-sectrust-provisioning.c"; path = "regressions/si-20-sectrust-provisioning.c"; sourceTree = ""; }; - DCB344701D8A35270054D16E /* si-20-sectrust-provisioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "si-20-sectrust-provisioning.h"; path = "regressions/si-20-sectrust-provisioning.h"; sourceTree = ""; }; + DCB3446F1D8A35270054D16E /* si-20-certificate-copy-values.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "si-20-certificate-copy-values.c"; path = "regressions/si-20-certificate-copy-values.c"; sourceTree = ""; }; DCB344711D8A35270054D16E /* si-33-keychain-backup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "si-33-keychain-backup.c"; path = "regressions/si-33-keychain-backup.c"; sourceTree = ""; }; DCB344721D8A35270054D16E /* si-34-one-true-keychain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "si-34-one-true-keychain.c"; path = "regressions/si-34-one-true-keychain.c"; sourceTree = ""; }; DCB41DF9216C3F8A00F219E0 /* tpctl-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "tpctl-entitlements.plist"; sourceTree = ""; }; + DCB5516A247F3DB50009A859 /* CKKSCreateCKZoneOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSCreateCKZoneOperation.h; sourceTree = ""; }; + DCB5516B247F3DB50009A859 /* CKKSCreateCKZoneOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSCreateCKZoneOperation.m; sourceTree = ""; }; + DCB55173247F48290009A859 /* CKKSDeleteCKZoneOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSDeleteCKZoneOperation.h; sourceTree = ""; }; + DCB55174247F48290009A859 /* CKKSDeleteCKZoneOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSDeleteCKZoneOperation.m; sourceTree = ""; }; DCB5D9391E4A9A3400BE22AB /* CKKSSynchronizeOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSSynchronizeOperation.h; sourceTree = ""; }; DCB5D93A1E4A9A3400BE22AB /* CKKSSynchronizeOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSSynchronizeOperation.m; sourceTree = ""; }; DCB946AD22FCB88400BE4490 /* OTDetermineHSA2AccountStatusOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTDetermineHSA2AccountStatusOperation.h; sourceTree = ""; }; @@ -14347,6 +14113,8 @@ DCB947592127534C00ED9272 /* OctagonTests+SOSUpgrade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+SOSUpgrade.swift"; sourceTree = ""; }; DCB9475B2127562100ED9272 /* OTSOSAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSOSAdapter.h; sourceTree = ""; }; DCB9475C2127562100ED9272 /* OTSOSAdapter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSOSAdapter.m; sourceTree = ""; }; + DCBA6F2824105399009A5187 /* CKKSTests+ForwardCompatibility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+ForwardCompatibility.m"; sourceTree = ""; }; + DCBDA460245A39A300B0938B /* com.apple.TrustedPeersHelper.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.TrustedPeersHelper.sb; sourceTree = ""; }; DCBDB3B01E57C67500B61300 /* CKKSKeychainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSKeychainView.h; sourceTree = ""; }; DCBDB3B11E57C67500B61300 /* CKKSKeychainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSKeychainView.m; sourceTree = ""; }; DCBDB3B91E57CA7A00B61300 /* CKKSViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSViewManager.h; sourceTree = ""; }; @@ -14358,8 +14126,12 @@ DCBF4AE321FFC9A800539F0A /* SecEscrowRequestTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecEscrowRequestTests.m; sourceTree = ""; }; DCBFF830222611A200C5C044 /* OTFetchCKKSKeysOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTFetchCKKSKeysOperation.h; sourceTree = ""; }; DCBFF831222611A200C5C044 /* OTFetchCKKSKeysOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTFetchCKKSKeysOperation.m; sourceTree = ""; }; + DCC03FA223FF521100A4DA3F /* TPSyncingPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TPSyncingPolicy.h; sourceTree = ""; }; + DCC03FA323FF521100A4DA3F /* TPSyncingPolicy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPSyncingPolicy.m; sourceTree = ""; }; DCC0800D1CFF7903005C35C8 /* CSSMOID.exp-in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "CSSMOID.exp-in"; sourceTree = ""; }; DCC1849220EEEC4400F3B26C /* security_framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = security_framework.xcconfig; path = xcconfig/security_framework.xcconfig; sourceTree = ""; }; + DCC40B0F2383786D00402CB9 /* CKKSStates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSStates.h; sourceTree = ""; }; + DCC40B102383786D00402CB9 /* CKKSStates.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSStates.m; sourceTree = ""; }; DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTUploadNewCKKSTLKsOperation.h; sourceTree = ""; }; DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTUploadNewCKKSTLKsOperation.m; sourceTree = ""; }; DCC5860220BF8A98005C7269 /* SecBase.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecBase.c; sourceTree = ""; }; @@ -14402,7 +14174,7 @@ DCC78C561D8085D800865A7C /* secd-58-password-change.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-58-password-change.m"; sourceTree = ""; }; DCC78C571D8085D800865A7C /* secd-59-account-cleanup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-59-account-cleanup.m"; sourceTree = ""; }; DCC78C581D8085D800865A7C /* secd-60-account-cloud-identity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-60-account-cloud-identity.m"; sourceTree = ""; }; - DCC78C591D8085D800865A7C /* secd60-account-cloud-exposure.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd60-account-cloud-exposure.m"; sourceTree = ""; }; + DCC78C591D8085D800865A7C /* secd-60-account-cloud-exposure.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-60-account-cloud-exposure.m"; sourceTree = ""; }; DCC78C5A1D8085D800865A7C /* secd-61-account-leave-not-in-kansas-anymore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-61-account-leave-not-in-kansas-anymore.m"; sourceTree = ""; }; DCC78C5B1D8085D800865A7C /* secd-62-account-backup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-62-account-backup.m"; sourceTree = ""; }; DCC78C5D1D8085D800865A7C /* secd-63-account-resurrection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-63-account-resurrection.m"; sourceTree = ""; }; @@ -14424,13 +14196,12 @@ DCC78C701D8085D800865A7C /* secd-83-item-match-valid-on-date.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-83-item-match-valid-on-date.m"; sourceTree = ""; }; DCC78C711D8085D800865A7C /* secd-83-item-match-trusted.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-83-item-match-trusted.m"; sourceTree = ""; }; DCC78C721D8085D800865A7C /* secd-83-item-match.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "secd-83-item-match.h"; sourceTree = ""; }; - DCC78C741D8085D800865A7C /* secd-95-escrow-persistence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-95-escrow-persistence.m"; sourceTree = ""; }; DCC78C751D8085D800865A7C /* secd-100-initialsync.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-100-initialsync.m"; sourceTree = ""; }; DCC78C761D8085D800865A7C /* secd-130-other-peer-views.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-130-other-peer-views.m"; sourceTree = ""; }; DCC78C771D8085D800865A7C /* secd-154-engine-backoff.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-154-engine-backoff.m"; sourceTree = ""; }; DCC78C781D8085D800865A7C /* secd-200-logstate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-200-logstate.m"; sourceTree = ""; }; DCC78C791D8085D800865A7C /* SOSAccountTesting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSAccountTesting.h; sourceTree = ""; }; - DCC78C7A1D8085D800865A7C /* SecdTestKeychainUtilities.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecdTestKeychainUtilities.c; sourceTree = ""; }; + DCC78C7A1D8085D800865A7C /* SecdTestKeychainUtilities.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecdTestKeychainUtilities.m; sourceTree = ""; }; DCC78C7B1D8085D800865A7C /* SecdTestKeychainUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecdTestKeychainUtilities.h; sourceTree = ""; }; DCC78C7C1D8085D800865A7C /* SOSTransportTestTransports.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSTransportTestTransports.m; sourceTree = ""; }; DCC78C7D1D8085D800865A7C /* SOSTransportTestTransports.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportTestTransports.h; sourceTree = ""; }; @@ -14474,7 +14245,6 @@ DCC78D021D8085F200865A7C /* sc-42-circlegencount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-42-circlegencount.c"; sourceTree = ""; }; DCC78D031D8085F200865A7C /* sc-45-digestvector.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-45-digestvector.c"; sourceTree = ""; }; DCC78D041D8085F200865A7C /* sc-130-resignationticket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-130-resignationticket.c"; sourceTree = ""; }; - DCC78D061D8085F200865A7C /* sc-150-ring.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "sc-150-ring.m"; sourceTree = ""; }; DCC78D071D8085F200865A7C /* sc-150-backupkeyderivation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-150-backupkeyderivation.c"; sourceTree = ""; }; DCC78D081D8085F200865A7C /* sc-153-backupslicekeybag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-153-backupslicekeybag.c"; sourceTree = ""; }; DCC78D091D8085F200865A7C /* SOSCircle_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCircle_regressions.h; sourceTree = ""; }; @@ -14605,8 +14375,6 @@ DCC78D991D8085F200865A7C /* keychain_sync_test.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = keychain_sync_test.m; sourceTree = ""; }; DCC78D9A1D8085F200865A7C /* keychain_log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_log.h; sourceTree = ""; }; DCC78D9B1D8085F200865A7C /* keychain_log.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = keychain_log.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - DCC78D9C1D8085F200865A7C /* syncbackup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = syncbackup.h; sourceTree = ""; }; - DCC78D9D1D8085F200865A7C /* syncbackup.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = syncbackup.m; sourceTree = ""; }; DCC78D9E1D8085F200865A7C /* secViewDisplay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = secViewDisplay.c; sourceTree = ""; }; DCC78D9F1D8085F200865A7C /* secViewDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = secViewDisplay.h; sourceTree = ""; }; DCC78DA21D8085FC00865A7C /* Security_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Security_regressions.h; path = Regressions/Security_regressions.h; sourceTree = ""; }; @@ -14629,18 +14397,6 @@ DCC78DB51D8085FC00865A7C /* si-14-dateparse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-14-dateparse.c"; sourceTree = ""; }; DCC78DB61D8085FC00865A7C /* si-15-delete-access-group.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-15-delete-access-group.m"; sourceTree = ""; }; DCC78DB91D8085FC00865A7C /* si-17-item-system-bluetooth.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-17-item-system-bluetooth.m"; sourceTree = ""; }; - DCC78DBD1D8085FC00865A7C /* si-21-sectrust-asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-21-sectrust-asr.c"; sourceTree = ""; }; - DCC78DBE1D8085FC00865A7C /* si-22-sectrust-iap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-22-sectrust-iap.c"; sourceTree = ""; }; - DCC78DBF1D8085FC00865A7C /* si-22-sectrust-iap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-22-sectrust-iap.h"; sourceTree = ""; }; - DCC78DC01D8085FC00865A7C /* si-23-sectrust-ocsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-23-sectrust-ocsp.c"; sourceTree = ""; }; - DCC78DC11D8085FC00865A7C /* si-24-sectrust-digicert-malaysia.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-digicert-malaysia.c"; sourceTree = ""; }; - DCC78DC21D8085FC00865A7C /* si-24-sectrust-diginotar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-diginotar.c"; sourceTree = ""; }; - DCC78DC31D8085FC00865A7C /* si-24-sectrust-itms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-itms.c"; sourceTree = ""; }; - DCC78DC51D8085FC00865A7C /* si-24-sectrust-passbook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-passbook.c"; sourceTree = ""; }; - DCC78DC61D8085FC00865A7C /* si-26-sectrust-copyproperties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-26-sectrust-copyproperties.c"; sourceTree = ""; }; - DCC78DC71D8085FC00865A7C /* si-27-sectrust-exceptions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-27-sectrust-exceptions.c"; sourceTree = ""; }; - DCC78DC81D8085FC00865A7C /* si-28-sectrustsettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-28-sectrustsettings.m"; sourceTree = ""; }; - DCC78DC91D8085FC00865A7C /* si-28-sectrustsettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-28-sectrustsettings.h"; sourceTree = ""; }; DCC78DCA1D8085FC00865A7C /* si-30-keychain-upgrade.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-30-keychain-upgrade.c"; sourceTree = ""; }; DCC78DCB1D8085FC00865A7C /* si-31-keychain-bad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-bad.c"; sourceTree = ""; }; DCC78DCC1D8085FC00865A7C /* si-31-keychain-unreadable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-unreadable.c"; sourceTree = ""; }; @@ -14672,30 +14428,15 @@ DCC78DE81D8085FC00865A7C /* si-65-cms-cert-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-65-cms-cert-policy.c"; sourceTree = ""; }; DCC78DE91D8085FC00865A7C /* signed-receipt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "signed-receipt.h"; sourceTree = ""; }; DCC78DEB1D8085FC00865A7C /* si-66-smime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-66-smime.c"; sourceTree = ""; }; - DCC78DEC1D8085FC00865A7C /* Global Trustee.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Global Trustee.cer.h"; sourceTree = ""; }; - DCC78DED1D8085FC00865A7C /* UTN-USERFirst-Hardware.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UTN-USERFirst-Hardware.cer.h"; sourceTree = ""; }; - DCC78DEE1D8085FC00865A7C /* addons.mozilla.org.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = addons.mozilla.org.cer.h; sourceTree = ""; }; - DCC78DEF1D8085FC00865A7C /* login.live.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.live.com.cer.h; sourceTree = ""; }; - DCC78DF01D8085FC00865A7C /* login.skype.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.skype.com.cer.h; sourceTree = ""; }; - DCC78DF11D8085FC00865A7C /* login.yahoo.com.1.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.1.cer.h; sourceTree = ""; }; - DCC78DF21D8085FC00865A7C /* login.yahoo.com.2.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.2.cer.h; sourceTree = ""; }; - DCC78DF31D8085FC00865A7C /* login.yahoo.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.cer.h; sourceTree = ""; }; - DCC78DF41D8085FC00865A7C /* mail.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mail.google.com.cer.h; sourceTree = ""; }; - DCC78DF51D8085FC00865A7C /* www.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = www.google.com.cer.h; sourceTree = ""; }; - DCC78DF71D8085FC00865A7C /* si-67-sectrust-blocklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-67-sectrust-blocklist.c"; sourceTree = ""; }; DCC78DF81D8085FC00865A7C /* si-68-secmatchissuer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-68-secmatchissuer.c"; sourceTree = ""; }; DCC78DF91D8085FC00865A7C /* si-69-keydesc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-69-keydesc.c"; sourceTree = ""; }; - DCC78DFA1D8085FC00865A7C /* si-70-sectrust-unified.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-70-sectrust-unified.c"; sourceTree = ""; }; - DCC78DFB1D8085FC00865A7C /* si-71-mobile-store-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-71-mobile-store-policy.c"; sourceTree = ""; }; DCC78DFC1D8085FC00865A7C /* si-72-syncableitems.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-72-syncableitems.c"; sourceTree = ""; }; DCC78DFD1D8085FC00865A7C /* si-73-secpasswordgenerate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-73-secpasswordgenerate.c"; sourceTree = ""; }; - DCC78DFE1D8085FC00865A7C /* si-74-OTAPKISigner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-74-OTAPKISigner.c"; sourceTree = ""; }; DCC78DFF1D8085FC00865A7C /* si-76-shared-credentials.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-76-shared-credentials.c"; sourceTree = ""; }; DCC78E001D8085FC00865A7C /* si_77_SecAccessControl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = si_77_SecAccessControl.c; sourceTree = ""; }; DCC78E011D8085FC00865A7C /* si-78-query-attrs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-78-query-attrs.c"; sourceTree = ""; }; DCC78E021D8085FC00865A7C /* si-80-empty-data.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "si-80-empty-data.c"; sourceTree = ""; }; DCC78E051D8085FC00865A7C /* si-82-token-ag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-82-token-ag.c"; sourceTree = ""; }; - DCC78E061D8085FC00865A7C /* si-83-seccertificate-sighashalg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-83-seccertificate-sighashalg.c"; sourceTree = ""; }; DCC78E0B1D8085FC00865A7C /* si-89-cms-hash-agility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-89-cms-hash-agility.m"; sourceTree = ""; }; DCC78E0D1D8085FC00865A7C /* si-90-emcs.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-90-emcs.m"; sourceTree = ""; }; DCC78E0E1D8085FC00865A7C /* si-95-cms-basic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-95-cms-basic.c"; sourceTree = ""; }; @@ -14778,6 +14519,8 @@ DCC78EA01D80860C00865A7C /* swcagent_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = swcagent_client.c; sourceTree = ""; }; DCC78EA11D80860C00865A7C /* swcagent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = swcagent.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; DCC78EA91D8088E200865A7C /* libsecurity.a */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsecurity.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DCC8856D2548E9FB004B0DB4 /* SecKnownFilePaths.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecKnownFilePaths.m; sourceTree = ""; }; + DCC887242548EB3B004B0DB4 /* SecKnownFilePaths.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecKnownFilePaths.h; path = OSX/sec/Security/SecKnownFilePaths.h; sourceTree = ""; }; DCCA5E831E539EE7009EE93D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; DCCBFA1D1DBA95CD001DD54D /* kc-20-item-delete-stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-20-item-delete-stress.c"; path = "regressions/kc-20-item-delete-stress.c"; sourceTree = ""; }; DCCD88E61E42622200F5AA71 /* CKKSGroupOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSGroupOperation.h; sourceTree = ""; }; @@ -15075,8 +14818,8 @@ DCD06B001D8E0D7D007602F1 /* muscle++.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "muscle++.cpp"; sourceTree = ""; }; DCD06B011D8E0D7D007602F1 /* pcsc++.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "pcsc++.h"; sourceTree = ""; }; DCD06B021D8E0D7D007602F1 /* pcsc++.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "pcsc++.cpp"; sourceTree = ""; }; - DCD06B051D8E0D7D007602F1 /* unix++.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "unix++.h"; sourceTree = ""; }; - DCD06B061D8E0D7D007602F1 /* unix++.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "unix++.cpp"; sourceTree = ""; }; + DCD06B051D8E0D7D007602F1 /* unix++.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "unix++.h"; sourceTree = ""; usesTabs = 0; }; + DCD06B061D8E0D7D007602F1 /* unix++.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "unix++.cpp"; sourceTree = ""; usesTabs = 0; }; DCD06B071D8E0D7D007602F1 /* unixchild.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unixchild.h; sourceTree = ""; }; DCD06B081D8E0D7D007602F1 /* unixchild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = unixchild.cpp; sourceTree = ""; }; DCD06B0C1D8E0D7D007602F1 /* mach++.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mach++.h"; sourceTree = ""; }; @@ -15117,6 +14860,9 @@ DCD662F41E329B6800188186 /* CKKSNewTLKOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSNewTLKOperation.m; sourceTree = ""; }; DCD66D731D8204A700DB1393 /* libSecTrustOSX.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libSecTrustOSX.a; sourceTree = BUILT_PRODUCTS_DIR; }; DCD66DDB1D8205C400DB1393 /* libSecOtrOSX.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libSecOtrOSX.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DCD689DD255A0AE300C2A1BA /* OctagonStateMachineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OctagonStateMachineTests.swift; sourceTree = ""; }; + DCD68B9C255A149300C2A1BA /* CKKSMockLockStateProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSMockLockStateProvider.m; sourceTree = ""; }; + DCD68C7D255A14C900C2A1BA /* CKKSMockLockStateProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSMockLockStateProvider.h; sourceTree = ""; }; DCD6C4B01EC5302400414FEE /* CKKSNearFutureScheduler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSNearFutureScheduler.h; sourceTree = ""; }; DCD6C4B11EC5302500414FEE /* CKKSNearFutureScheduler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSNearFutureScheduler.m; sourceTree = ""; }; DCD6C4B61EC5319600414FEE /* CKKSNearFutureSchedulerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSNearFutureSchedulerTests.m; sourceTree = ""; }; @@ -15124,6 +14870,7 @@ DCD7DD9D22B868C200161396 /* TPPBDispositionDuplicateMachineID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPBDispositionDuplicateMachineID.h; sourceTree = ""; }; DCD7EE9B1F4F51D9007D9804 /* ios_tapi_hacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ios_tapi_hacks.h; sourceTree = ""; }; DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecureObjectSyncFramework.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DCDACB5724A3F1AA0054080C /* com.apple.security.ckks.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.ckks.plist; sourceTree = ""; }; DCDCC7DD1D9B54DF006487E8 /* secd-202-recoverykey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-202-recoverykey.m"; sourceTree = ""; }; DCDCC7E41D9B551C006487E8 /* SOSAccountSync.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAccountSync.m; sourceTree = ""; }; DCDCCB8D1DF7B8D4006E840E /* CKKSItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSItem.h; sourceTree = ""; }; @@ -15135,12 +14882,11 @@ DCE278DC1ED789EF0083B485 /* CKKSCurrentItemPointer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSCurrentItemPointer.m; sourceTree = ""; }; DCE278E61ED7A5B40083B485 /* CKKSUpdateCurrentItemPointerOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSUpdateCurrentItemPointerOperation.h; sourceTree = ""; }; DCE278E71ED7A5B40083B485 /* CKKSUpdateCurrentItemPointerOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSUpdateCurrentItemPointerOperation.m; sourceTree = ""; }; + DCE405C423A04A7F00C4343B /* OctagonTests+CKKSConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+CKKSConfiguration.swift"; sourceTree = ""; }; DCE4E6A41D7A37FA00AFB96E /* security2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = security2; sourceTree = BUILT_PRODUCTS_DIR; }; DCE4E6A71D7A38C000AFB96E /* security2.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = security2.1; sourceTree = ""; }; - DCE4E6D41D7A41E400AFB96E /* bc-10-knife-on-bread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "bc-10-knife-on-bread.m"; path = "OSX/Breadcrumb/bc-10-knife-on-bread.m"; sourceTree = ""; }; DCE4E6D71D7A420D00AFB96E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = OSX/SecurityTestsOSX/main.m; sourceTree = ""; }; DCE4E6E71D7A427200AFB96E /* SecurityFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/SecurityFoundation.framework; sourceTree = DEVELOPER_DIR; }; - DCE4E72E1D7A436300AFB96E /* si-82-sectrust-ct-logs.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "si-82-sectrust-ct-logs.plist"; path = "OSX/shared_regressions/si-82-sectrust-ct-logs.plist"; sourceTree = SOURCE_ROOT; }; DCE4E7B21D7A43B500AFB96E /* SecurityTestsOSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SecurityTestsOSX.app; sourceTree = BUILT_PRODUCTS_DIR; }; DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityFoundation.framework; path = System/Library/Frameworks/SecurityFoundation.framework; sourceTree = SDKROOT; }; DCE4E7CC1D7A4AED00AFB96E /* sectests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sectests; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -15205,14 +14951,13 @@ DCE772642290712F005862B4 /* OctagonCheckTrustStateOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonCheckTrustStateOperation.h; sourceTree = ""; }; DCE772652290712F005862B4 /* OctagonCheckTrustStateOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OctagonCheckTrustStateOperation.m; sourceTree = ""; }; DCE7F2081F21726500DDB0F7 /* OctagonAPSReceiverTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OctagonAPSReceiverTests.m; sourceTree = ""; }; - DCEA0FF6213F1E6F0054A328 /* Octagon.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Octagon.plist; sourceTree = ""; }; DCEA5D531E2826DB0089CF55 /* CKKSSIV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSSIV.h; sourceTree = ""; }; DCEA5D541E2826DB0089CF55 /* CKKSSIV.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSSIV.m; sourceTree = ""; }; DCEA5D831E2F14810089CF55 /* OctagonAPSReceiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OctagonAPSReceiver.h; sourceTree = ""; }; DCEA5D841E2F14810089CF55 /* OctagonAPSReceiver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OctagonAPSReceiver.m; sourceTree = ""; }; - DCEA5D951E3014250089CF55 /* CKKSZone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSZone.h; sourceTree = ""; }; - DCEA5D961E3014250089CF55 /* CKKSZone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSZone.m; sourceTree = ""; }; DCEE1E851D93424D00DC0EB7 /* com.apple.securityd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.securityd.plist; path = OSX/sec/ipc/com.apple.securityd.plist; sourceTree = SOURCE_ROOT; }; + DCF0C432256347B7007D5A6A /* CKKSMemoryKeyCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSMemoryKeyCache.m; sourceTree = ""; }; + DCF0C434256347B8007D5A6A /* CKKSMemoryKeyCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSMemoryKeyCache.h; sourceTree = ""; }; DCF12671218A7579000124C6 /* OTLeaveCliqueOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTLeaveCliqueOperation.h; sourceTree = ""; }; DCF12672218A757A000124C6 /* OTLeaveCliqueOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTLeaveCliqueOperation.m; sourceTree = ""; }; DCF158C52064895C00B87B6D /* OctagonAPSReceiverTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonAPSReceiverTests.h; sourceTree = ""; }; @@ -15550,7 +15295,6 @@ DCFABF8D20081E2F001128B5 /* CKKSDeviceStateUploadTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSDeviceStateUploadTests.m; sourceTree = ""; }; DCFAEDC81D999851005187E4 /* SOSAccountGhost.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAccountGhost.m; sourceTree = ""; }; DCFAEDC91D999851005187E4 /* SOSAccountGhost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSAccountGhost.h; sourceTree = ""; }; - DCFAEDD11D9998DD005187E4 /* secd-668-ghosts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-668-ghosts.m"; sourceTree = ""; }; DCFAEDD51D99A464005187E4 /* secd-36-ks-encrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-36-ks-encrypt.m"; sourceTree = ""; }; DCFB12C31E95A4C000510F5F /* CKKSAccountStateTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSAccountStateTracker.h; sourceTree = ""; }; DCFB12C41E95A4C000510F5F /* CKKSAccountStateTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSAccountStateTracker.m; sourceTree = ""; }; @@ -15646,7 +15390,6 @@ E7F4809D1C74E86D00390FDB /* KCAESGCMTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KCAESGCMTest.m; path = Tests/KCAESGCMTest.m; sourceTree = ""; }; E7F4826F1C74FDD100390FDB /* KCJoiningSessionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KCJoiningSessionTest.m; path = Tests/KCJoiningSessionTest.m; sourceTree = ""; }; E7F482A21C7544E600390FDB /* libctkclient_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkclient_test.a; path = ../../../../../usr/local/lib/libctkclient_test.a; sourceTree = ""; }; - E7F482A51C75453900390FDB /* libcoreauthd_test_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcoreauthd_test_client.a; path = ../../../../../usr/local/lib/libcoreauthd_test_client.a; sourceTree = ""; }; E7F482A91C7554F500390FDB /* NSError+KCCreationHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+KCCreationHelpers.m"; sourceTree = ""; }; E7F482AB1C7558F700390FDB /* KCJoiningAcceptSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KCJoiningAcceptSession.m; sourceTree = ""; }; E7FC30AB1332DE9000802946 /* MobileKeyBag.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileKeyBag.framework; path = System/Library/PrivateFrameworks/MobileKeyBag.framework; sourceTree = SDKROOT; }; @@ -15705,6 +15448,10 @@ EB433A1E1CC3242C00A7EACE /* secitemstresstest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = secitemstresstest.m; path = secitemstresstest/secitemstresstest.m; sourceTree = ""; }; EB433A281CC3243600A7EACE /* secitemstresstest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secitemstresstest; sourceTree = BUILT_PRODUCTS_DIR; }; EB433A2D1CC325E900A7EACE /* secitemstresstest.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = secitemstresstest.entitlements; path = secitemstresstest/secitemstresstest.entitlements; sourceTree = ""; }; + EB45ED2E24749DE9008A1F6F /* gen_test_plist.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gen_test_plist.py; path = tests/TrustTests/gen_test_plist.py; sourceTree = ""; }; + EB45ED3024749E63008A1F6F /* gen_test_plist.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gen_test_plist.py; sourceTree = ""; }; + EB45ED3124749ECC008A1F6F /* OTTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "OTTests-Info.plist"; sourceTree = ""; }; + EB45ED3224749ECC008A1F6F /* gen_test_plist.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gen_test_plist.py; sourceTree = ""; }; EB48C19E1E573EDC00EC5E57 /* sos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sos.m; sourceTree = ""; }; EB490153211C0026001E6D6A /* UserManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserManagement.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/PrivateFrameworks/UserManagement.framework; sourceTree = DEVELOPER_DIR; }; EB49B2AE202D877F003F34A0 /* secdmockaks.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = secdmockaks.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -15783,8 +15530,6 @@ EB8021411D3D90BB008540C4 /* Security.iOS.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = Security.iOS.modulemap; path = Modules/Security.iOS.modulemap; sourceTree = ""; }; EB8021421D3D90BB008540C4 /* Security.macOS.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = Security.macOS.modulemap; path = Modules/Security.macOS.modulemap; sourceTree = ""; }; EB80DE57219600CF005B10FA /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; }; - EB82A2A41FAFF26900CA64A9 /* SFBehavior.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFBehavior.h; sourceTree = ""; }; - EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFBehavior.m; sourceTree = ""; }; EB89088621F17D3C00F0DDDB /* recovery_securityd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = recovery_securityd; sourceTree = BUILT_PRODUCTS_DIR; }; EB8908BB21F20E0200F0DDDB /* com.apple.recovery_securityd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.recovery_securityd.plist; sourceTree = ""; }; EB89111020E3C15D00DE533F /* UserManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserManagement.framework; path = System/Library/PrivateFrameworks/UserManagement.framework; sourceTree = SDKROOT; }; @@ -15799,6 +15544,9 @@ EBA9AA7C1CE30CE7004E2B68 /* secitemnotifications.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = secitemnotifications.m; path = secitemnotifications/secitemnotifications.m; sourceTree = ""; }; EBA9AA861CE30E58004E2B68 /* secitemnotifications */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secitemnotifications; sourceTree = BUILT_PRODUCTS_DIR; }; EBAC4A512189743D00FBEC43 /* rio.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rio.yml; sourceTree = ""; }; + EBAFC9AC2551C2700034B78D /* SecLegacyCodeRegressions.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecLegacyCodeRegressions.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + EBAFC9AE2551C2700034B78D /* legacyCodeRegressions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = legacyCodeRegressions.mm; sourceTree = ""; }; + EBAFC9B02551C2700034B78D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; EBB02A56221FF362007241CB /* KeychainSettingsCKKSViews.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = KeychainSettingsCKKSViews.plist; sourceTree = ""; }; EBB02A6C2220ED16007241CB /* CKKSLaunchSequence.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSLaunchSequence.h; sourceTree = ""; }; EBB02A6D2220ED16007241CB /* CKKSLaunchSequence.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSLaunchSequence.m; sourceTree = ""; }; @@ -15811,7 +15559,6 @@ EBB8521A22F7943700424FD0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; EBC1023022EBF8AC0083D356 /* CKKSTests+LockStateTracker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+LockStateTracker.m"; sourceTree = ""; }; EBC15B1B1DB4306C00126882 /* com.apple.secd.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.secd.sb; sourceTree = ""; }; - EBC73F4A209A0BEF00AE3350 /* install-test-framework.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "install-test-framework.sh"; path = "xcscripts/install-test-framework.sh"; sourceTree = ""; }; EBCE06E521C6E26000FB1493 /* OTDefines.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTDefines.m; sourceTree = ""; }; EBCF01001DF501310055AF97 /* swcagent-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "swcagent-entitlements.plist"; sourceTree = ""; }; EBCF73F11CE45F8600BED7CA /* secitemfunctionality.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = secitemfunctionality.entitlements; path = secitemfunctionality/secitemfunctionality.entitlements; sourceTree = ""; }; @@ -15836,21 +15583,27 @@ EBF374721DC055580065D840 /* security-sysdiagnose */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "security-sysdiagnose"; sourceTree = BUILT_PRODUCTS_DIR; }; EBF374741DC055590065D840 /* security-sysdiagnose.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "security-sysdiagnose.m"; sourceTree = ""; }; EBF3747F1DC057FE0065D840 /* security-sysdiagnose.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = "security-sysdiagnose.1"; sourceTree = ""; }; - EBF3749A1DC064200065D840 /* SecADWrapper.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecADWrapper.c; sourceTree = ""; }; - EBF3749B1DC064200065D840 /* SecADWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecADWrapper.h; sourceTree = ""; }; EBF9AE171F536D0300FECBF7 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Version.xcconfig; path = xcconfig/Version.xcconfig; sourceTree = ""; }; F619D71D1ED70BB0005B5F46 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = OSX/authorizationdump/main.m; sourceTree = ""; }; F621D07F1ED6DCE7000EA569 /* authorizationdump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = authorizationdump; sourceTree = BUILT_PRODUCTS_DIR; }; F667EC551E96E94800203D5C /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = OSX/authd/tests/main.m; sourceTree = ""; }; F667EC601E96E9B100203D5C /* authdtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = authdtest; sourceTree = BUILT_PRODUCTS_DIR; }; + F67B93C1254707E00076CA99 /* fvunlock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = fvunlock.m; sourceTree = ""; }; + F67B93C425470D7D0076CA99 /* fvunlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fvunlock.h; sourceTree = ""; }; + F681C3A82386B8B40083F22C /* PreloginUserDb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PreloginUserDb.m; path = OSX/authd/PreloginUserDb.m; sourceTree = ""; }; + F681C3AA2386B8B40083F22C /* PreloginUserDb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreloginUserDb.h; path = OSX/authd/PreloginUserDb.h; sourceTree = ""; }; F682C1CE1F4486F600F1B029 /* libctkloginhelper.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkloginhelper.a; path = usr/local/lib/libctkloginhelper.a; sourceTree = SDKROOT; }; + F68D5B65254C065500020852 /* securitytool-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "securitytool-entitlements.plist"; sourceTree = ""; }; F6A0971E1E953A1500B1E7D6 /* authdtestlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = authdtestlist.h; path = OSX/authd/tests/authdtestlist.h; sourceTree = ""; }; F6A0971F1E953ABD00B1E7D6 /* authdtests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = authdtests.m; path = OSX/authd/tests/authdtests.m; sourceTree = ""; }; F6A3CB0D1E7062BA00E7821F /* authd-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "authd-Entitlements.plist"; path = "OSX/authd/authd-Entitlements.plist"; sourceTree = ""; }; + F6B1B48924144B5E00CB3E3F /* libctkloginhelperlite.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkloginhelperlite.a; path = usr/local/lib/libctkloginhelperlite.a; sourceTree = SDKROOT; }; F6D600702166551800F9F7C9 /* AuthorizationTrampolinePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationTrampolinePriv.h; path = OSX/libsecurity_authorization/lib/AuthorizationTrampolinePriv.h; sourceTree = ""; }; F9B458272183E01100F6BCEB /* SignatureEditing.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = SignatureEditing.sh; path = OSX/codesign_tests/SignatureEditing.sh; sourceTree = ""; }; F9F77E96223C2F7B00E5CBF6 /* requirement.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = requirement.c; sourceTree = ""; }; F9F77E97223C2F7C00E5CBF6 /* requirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = requirement.h; sourceTree = ""; }; + FC637229237B5CF800973738 /* SecItemServer+SWC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SecItemServer+SWC.h"; sourceTree = ""; }; + FC63722A237B5CF900973738 /* SecItemServer+SWC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SecItemServer+SWC.m"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -15889,6 +15642,7 @@ 0C0BDB881756A51000BC1A7E /* libsqlite3.dylib in Frameworks */, BE8ABDD81DC2DD9100EC2D58 /* libz.dylib in Frameworks */, 4469FBFF1AA0A4820021AA26 /* libctkclient_test.a in Frameworks */, + DA53FC4523A9C801002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -15947,24 +15701,38 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0C3810F123EF6FC4002D7E19 /* OctagonTrust.framework in Frameworks */, 0C84D83D1FCF449700B822E3 /* Security.framework in Frameworks */, + 0CE902352395D0A3005E3F8C /* AuthKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 0C9AEEB020783FBB00BF6237 /* Frameworks */ = { + 0CCC226123F357EE00E1FCD0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C9AEEBB20783FF900BF6237 /* Security.framework in Frameworks */, + 0CCC22B323F38B6D00E1FCD0 /* AuthKit.framework in Frameworks */, + 0CCC22B623F38BCD00E1FCD0 /* CoreData.framework in Frameworks */, + 0CCC22C723F3904D00E1FCD0 /* Foundation.framework in Frameworks */, + 0C570B7C23F3A0E3001FEB3B /* IOKit.framework in Frameworks */, + 0CCC22C823F390E400E1FCD0 /* OCMock.framework in Frameworks */, + 0CCC22A423F374EB00E1FCD0 /* OctagonTrust.framework in Frameworks */, + 0CCC22AE23F38B2D00E1FCD0 /* SystemConfiguration.framework in Frameworks */, + 0CCC22A923F38AFD00E1FCD0 /* libSecureObjectSyncServer.a in Frameworks */, + 0CCC22A823F38AD600E1FCD0 /* libsecurityd_ios.a in Frameworks */, + 0CCC22A523F3763C00E1FCD0 /* libutilities.a in Frameworks */, + 0CCC22BD23F38D4B00E1FCD0 /* libbsm.tbd in Frameworks */, + 0CCC22BC23F38D3500E1FCD0 /* libz.tbd in Frameworks */, + 0CCC22B223F38B5B00E1FCD0 /* libsqlite3.0.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 0CF406342072E3E3003D6A7F /* Frameworks */ = { + 0CD743A323C3EC8000FA0EC5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C5663EF20BE2E220035F362 /* libutilities.a in Frameworks */, - 0C9AEEBE207843D000BF6237 /* Security.framework in Frameworks */, + 0CCC21FF23F3577A00E1FCD0 /* Security.framework in Frameworks */, + 0CD743AF23C3ECEB00FA0EC5 /* ProtocolBuffer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -15995,7 +15763,6 @@ 3DD1FFA5201FC59D0086D049 /* libsecurity_ssl.a in Frameworks */, 3DD1FFA4201FC58F0086D049 /* libutilities.a in Frameworks */, 3DD1FFA3201FC5870086D049 /* libDiagnosticMessagesClient.tbd in Frameworks */, - 3DD1FFA2201FC5800086D049 /* SecurityFoundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16010,7 +15777,33 @@ 3DD1FFC6201FDB1D0086D049 /* Foundation.framework in Frameworks */, 3DD1FFC8201FDB1D0086D049 /* libsecurity_ssl.a in Frameworks */, 3DD1FFC9201FDB1D0086D049 /* libutilities.a in Frameworks */, - 3DD1FFCB201FDB1D0086D049 /* SecurityFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E4D49B62531170600B124B3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A69565BC2580ABD900BDF83F /* AppleFSCompression.framework in Frameworks */, + A69565BB2580ABBC00BDF83F /* libDER.a in Frameworks */, + A69564DB2580ABAC00BDF83F /* IOKit.framework in Frameworks */, + A69563FC2580ABA200BDF83F /* libsqlite3.tbd in Frameworks */, + A695631D2580AB8A00BDF83F /* libsecurity_cdsa_utilities.a in Frameworks */, + A695623D2580AB7E00BDF83F /* libbsm.tbd in Frameworks */, + A695623C2580AB7900BDF83F /* libsecurity_utilities.a in Frameworks */, + A695615C2580A0F500BDF83F /* libsecurity_codesigning.a in Frameworks */, + 3E4D49B72531170600B124B3 /* Security.framework in Frameworks */, + 3E4D49B82531170600B124B3 /* Foundation.framework in Frameworks */, + A640B71D25CB75820098A4A4 /* libxar.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E88360B24F068EF00E9F4D6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E88361B24F08DA100E9F4D6 /* Security.framework in Frameworks */, + 3E88360D24F068EF00E9F4D6 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16022,6 +15815,7 @@ 438169E41B4EE13B00C54D58 /* Accounts.framework in Frameworks */, 438169E51B4EE14D00C54D58 /* Security.framework in Frameworks */, 4381690D1B4EDCBD00C54D58 /* Foundation.framework in Frameworks */, + DA2F592723A99F2900C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16052,6 +15846,7 @@ 4718AE23205B39620068EC3F /* IOKit.framework in Frameworks */, 4718AE24205B39620068EC3F /* libaks_acl.a in Frameworks */, 4718AE25205B39620068EC3F /* libsqlite3.dylib in Frameworks */, + DA2F592523A99E8400C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16087,12 +15882,12 @@ 4727FBD51F9920510003AE36 /* ProtocolBuffer.framework in Frameworks */, D4911172209559630066A1E4 /* CoreData.framework in Frameworks */, 4727FBD31F9920290003AE36 /* CloudKit.framework in Frameworks */, - 4727FBD11F991F990003AE36 /* libMobileGestalt.dylib in Frameworks */, 4727FBCE1F991F820003AE36 /* SecurityFoundation.framework in Frameworks */, 4727FBCD1F991F660003AE36 /* libsqlite3.dylib in Frameworks */, 4727FBC91F991E5A0003AE36 /* libutilities.a in Frameworks */, 4727FBC61F991DE90003AE36 /* libsecdRegressions.a in Frameworks */, 4727FBC51F991C470003AE36 /* Foundation.framework in Frameworks */, + DA53FC3E23A9C180002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16122,45 +15917,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 478D427D1FD72A8100CAB645 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - DC4A76AA22126993006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FD221F146E700CD5B9E /* CoreCDP.framework in Frameworks */, - EB7732DB21963BC100FCF513 /* libz.tbd in Frameworks */, - 482FE56A2177C7980031C11E /* AuthKit.framework in Frameworks */, - 479231EE2065B32200B2718C /* libsecurityd_ios.a in Frameworks */, - 477A1F5320320E5100ACD81D /* Accounts.framework in Frameworks */, - 478D429F1FD72C8400CAB645 /* AppleSystemInfo.framework in Frameworks */, - 478D429E1FD72C4800CAB645 /* CrashReporterSupport.framework in Frameworks */, - 478D427F1FD72A8100CAB645 /* libprequelite.dylib in Frameworks */, - 478D42801FD72A8100CAB645 /* OCMock.framework in Frameworks */, - 478D42811FD72A8100CAB645 /* libregressionBase.a in Frameworks */, - 478D42821FD72A8100CAB645 /* libACM.a in Frameworks */, - D4911173209559630066A1E4 /* CoreData.framework in Frameworks */, - 478D42831FD72A8100CAB645 /* ApplePushService.framework in Frameworks */, - 478D42841FD72A8100CAB645 /* SharedWebCredentials.framework in Frameworks */, - 478D42851FD72A8100CAB645 /* MobileKeyBag.framework in Frameworks */, - 478D42861FD72A8100CAB645 /* IOKit.framework in Frameworks */, - 478D42871FD72A8100CAB645 /* libaks.a in Frameworks */, - 478D42881FD72A8100CAB645 /* libaks_acl.a in Frameworks */, - 478D42891FD72A8100CAB645 /* WirelessDiagnostics.framework in Frameworks */, - 478D428A1FD72A8100CAB645 /* SystemConfiguration.framework in Frameworks */, - 478D428B1FD72A8100CAB645 /* libSecureObjectSyncServer.a in Frameworks */, - 478D428C1FD72A8100CAB645 /* libSecureObjectSyncFramework.a in Frameworks */, - 478D428D1FD72A8100CAB645 /* ProtocolBuffer.framework in Frameworks */, - 478D428E1FD72A8100CAB645 /* CloudKit.framework in Frameworks */, - DC066DF02102563300694EAF /* Security.framework in Frameworks */, - 478D42901FD72A8100CAB645 /* SecurityFoundation.framework in Frameworks */, - 478D42911FD72A8100CAB645 /* libsqlite3.dylib in Frameworks */, - 478D42931FD72A8100CAB645 /* libutilities.a in Frameworks */, - 478D42951FD72A8100CAB645 /* libsecurity.a in Frameworks */, - 478D42961FD72A8100CAB645 /* libsecdRegressions.a in Frameworks */, - 478D42971FD72A8100CAB645 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 47C2F1802059CB680062DE30 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -16204,6 +15960,7 @@ 438166ED1B4ECF9400C54D58 /* CoreFoundation.framework in Frameworks */, 4CAF67AC0F3A70220064A534 /* IOKit.framework in Frameworks */, 0940F6F82151316500C06F18 /* libACM.a in Frameworks */, + 0C2B32A523C4001900A97B18 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16211,15 +15968,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C9FB40720D872A600864612 /* CoreCDP.framework in Frameworks */, + 0CCC22D623F39B2E00E1FCD0 /* CoreCDP.framework in Frameworks */, 43DB54551BB1F8920083C3F1 /* ProtectedCloudStorage.framework in Frameworks */, 4C8A38C917B93DF10001B4C0 /* CloudServices.framework in Frameworks */, - 4C7913251799A5CC00A9633E /* MobileCoreServices.framework in Frameworks */, 4381603B1B4DCEFF00C54D58 /* AggregateDictionary.framework in Frameworks */, 4C3DD6BD179760280093F9D8 /* libMobileGestalt.dylib in Frameworks */, 533B5D4F177CD63100995334 /* SpringBoardServices.framework in Frameworks */, 7200D76F177B9999009BB396 /* ManagedConfiguration.framework in Frameworks */, 433E519E1B66D5F600482618 /* AppSupport.framework in Frameworks */, + DC89608D2395C75600D339D9 /* CoreServices.framework in Frameworks */, 4C84DA551720698900AEE225 /* AppleAccount.framework in Frameworks */, 4CF4C19D171E0EA600877419 /* Accounts.framework in Frameworks */, 438168C41B4ED43800C54D58 /* CoreFoundation.framework in Frameworks */, @@ -16234,9 +15991,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0CC9403023F39E84004B71AA /* CoreCDP.framework in Frameworks */, D47AB2D12356B2FE005A3801 /* Network.framework in Frameworks */, DC4A76AD22126A17006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FD621F14D3900CD5B9E /* CoreCDP.framework in Frameworks */, EB80DE5B219600FC005B10FA /* libz.tbd in Frameworks */, 482FE56F2177CF520031C11E /* AuthKit.framework in Frameworks */, D4C6C5CF1FB3B44D007EA57E /* libarchive.2.dylib in Frameworks */, @@ -16269,6 +16026,7 @@ 4C711D6D13AFCD0900FE865D /* Security.framework in Frameworks */, D418CC701E690CAD00330A44 /* MobileAsset.framework in Frameworks */, E71F3E4216EA6A6300FAF9B4 /* SystemConfiguration.framework in Frameworks */, + DA3862AA23AAD959001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16295,11 +16053,11 @@ DC4A76A5221268A6006F2D8F /* CloudServices.framework in Frameworks */, EB7732C221963B0500FCF513 /* libz.tbd in Frameworks */, 482FE56C2177CEEF0031C11E /* AuthKit.framework in Frameworks */, - 0C9FB40920D8735500864612 /* CoreCDP.framework in Frameworks */, 47D13F631E8447FB0063B6E2 /* SecurityFoundation.framework in Frameworks */, EBE9019A1C22852C007308C6 /* AggregateDictionary.framework in Frameworks */, 438168BB1B4ED42300C54D58 /* CoreFoundation.framework in Frameworks */, DC00AB8E1D821D4900513D74 /* libSOSCommands.a in Frameworks */, + 0CCC22D723F39B7200E1FCD0 /* CoreCDP.framework in Frameworks */, 5296CB4F1655B92F009912AF /* libMobileGestalt.dylib in Frameworks */, 4432B0B71A014987000958DC /* libaks_acl.a in Frameworks */, DC65E7361D8CB35E00152EF0 /* libutilities.a in Frameworks */, @@ -16330,6 +16088,7 @@ 52D82BEE16A622370078DFE5 /* Security.framework in Frameworks */, 52D82BDF16A621F70078DFE5 /* Foundation.framework in Frameworks */, E72D462B175FBF3E00F70B9B /* IOKit.framework in Frameworks */, + DA53FC3D23A9BF28002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16366,7 +16125,6 @@ buildActionMask = 2147483647; files = ( DC4A76A02212676D006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FCB21F1415B00CD5B9E /* CoreCDP.framework in Frameworks */, EB80DE5D21960C0A005B10FA /* libz.tbd in Frameworks */, 482FE5662177C6E40031C11E /* AuthKit.framework in Frameworks */, 482FE5652177C6D90031C11E /* Accounts.framework in Frameworks */, @@ -16386,6 +16144,17 @@ 5E43C48D1B00D07000E5ECB2 /* CoreFoundation.framework in Frameworks */, 5E43C4961B00D3B500E5ECB2 /* IOKit.framework in Frameworks */, 5E43C49A1B00D4D800E5ECB2 /* Security.framework in Frameworks */, + DA53FC4623A9CB13002D5EA9 /* SoftLinking.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6C2045E72424BA7E00F9461D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6CB0C5F824ACDB5300479FB4 /* Security.framework in Frameworks */, + 6CA9690A24ACC2D100C08B5E /* libutilities.a in Frameworks */, + 6C2045F52424BBDD00F9461D /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16393,7 +16162,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6C8FF4B3224C1A8D00E5C812 /* TrustedPeers.framework in Frameworks */, 6C540C3922289A3B0032B5BC /* CloudServices.framework in Frameworks */, 6C39235B21F13E4D00D018AD /* libz.dylib in Frameworks */, 6C39235C21F13E4D00D018AD /* AuthKit.framework in Frameworks */, @@ -16419,6 +16187,7 @@ 6C39237221F13E4D00D018AD /* libutilities.a in Frameworks */, 6C39237321F13E4D00D018AD /* libsecdRegressions.a in Frameworks */, 6C39237421F13E4D00D018AD /* Foundation.framework in Frameworks */, + DA53FC3F23A9C26F002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16435,70 +16204,34 @@ D4119E882032A8FA0048587B /* OCMock.framework in Frameworks */, 6C13AE481F8E9FC800F047E3 /* libutilities.a in Frameworks */, 6C4605A51F882B9B001421B6 /* Foundation.framework in Frameworks */, + DA53FC4123A9C3CE002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 6C9808481E788AEB00E70590 /* Frameworks */ = { + 6C7BE2D223C3DD64003BB2CA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DC4A76A822126959006F2D8F /* CloudServices.framework in Frameworks */, - 0C4D96A721F25F2C00617E60 /* CoreCDP.framework in Frameworks */, - 482FE5672177C7260031C11E /* AuthKit.framework in Frameworks */, - 6CAA8CDD1F82EDEF007B6E03 /* Security.framework in Frameworks */, - D46246BC1F9AE82B00D63882 /* libDER.a in Frameworks */, - 6C98084A1E788AEB00E70590 /* libASN1.a in Frameworks */, - 6C98084D1E788AEB00E70590 /* libSecureObjectSyncFramework.a in Frameworks */, - 6C98084E1E788AEB00E70590 /* libSecureObjectSyncServer.a in Frameworks */, - DC93C4C5214713C5008F8362 /* libaks_mock.a in Frameworks */, - DC93C4D021471FD8008F8362 /* libsecurityd_ios.a in Frameworks */, - 6C98084F1E788AEB00E70590 /* libsecurity.a in Frameworks */, - 6C9808501E788AEB00E70590 /* libutilities.a in Frameworks */, - 6C9808511E788AEB00E70590 /* CFNetwork.framework in Frameworks */, - 6C9808521E788AEB00E70590 /* Foundation.framework in Frameworks */, - 6C9808531E788AEB00E70590 /* IOKit.framework in Frameworks */, - 6C9808541E788AEB00E70590 /* OCMock.framework in Frameworks */, - DCB515DE1ED3CF86001F1152 /* SecurityFoundation.framework in Frameworks */, - 6C9808551E788AEB00E70590 /* SystemConfiguration.framework in Frameworks */, - 6C9808561E788AEB00E70590 /* libACM.a in Frameworks */, - 6C9808571E788AEB00E70590 /* libaks_acl.a in Frameworks */, - 6C9808581E788AEB00E70590 /* libbsm.dylib in Frameworks */, - 6C9808591E788AEB00E70590 /* libcoreauthd_client.a in Frameworks */, - 6C98085A1E788AEB00E70590 /* libctkclient_sep.a in Frameworks */, - 6C98085B1E788AEB00E70590 /* libsqlite3.0.dylib in Frameworks */, - 6C98085C1E788AEB00E70590 /* libz.dylib in Frameworks */, + 6C16258823C5001C0086A0FF /* libSecureObjectSyncServer.a in Frameworks */, + 6C16258723C4FFEC0086A0FF /* libMobileGestalt.tbd in Frameworks */, + 6C7BE2EB23C3DDC3003BB2CA /* libsecurityd_bridge.a in Frameworks */, + 6C7BE2D423C3DD64003BB2CA /* libz.tbd in Frameworks */, + 6C7BE2D723C3DD64003BB2CA /* SecurityFoundation.framework in Frameworks */, + 6C7BE2D823C3DD64003BB2CA /* AggregateDictionary.framework in Frameworks */, + 6C7BE2D923C3DD64003BB2CA /* CoreFoundation.framework in Frameworks */, + 6C7BE2DC23C3DD64003BB2CA /* libaks_acl.a in Frameworks */, + 6C7BE2DD23C3DD64003BB2CA /* libutilities.a in Frameworks */, + 6C7BE2E023C3DD64003BB2CA /* Security.framework in Frameworks */, + 6C7BE2E323C3DD64003BB2CA /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 6C9808841E788AFD00E70590 /* Frameworks */ = { + 6C96327E242A279B00C53CE2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DC4A76A72212694F006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FD021F145F600CD5B9E /* CoreCDP.framework in Frameworks */, - 482FE5682177C73C0031C11E /* AuthKit.framework in Frameworks */, - 6CAA8CEE1F83E417007B6E03 /* Security.framework in Frameworks */, - D46246BD1F9AE83600D63882 /* libDER.a in Frameworks */, - 6C9808861E788AFD00E70590 /* libASN1.a in Frameworks */, - 6C9808891E788AFD00E70590 /* libSecureObjectSyncFramework.a in Frameworks */, - 6C98088A1E788AFD00E70590 /* libSecureObjectSyncServer.a in Frameworks */, - DC93C4CB214713ED008F8362 /* libaks_mock.a in Frameworks */, - DC93C4CA214713E5008F8362 /* libsecurityd_ios.a in Frameworks */, - 6C98088B1E788AFD00E70590 /* libsecurity.a in Frameworks */, - 6C98088C1E788AFD00E70590 /* libutilities.a in Frameworks */, - 6C98088D1E788AFD00E70590 /* CFNetwork.framework in Frameworks */, - 6C98088E1E788AFD00E70590 /* Foundation.framework in Frameworks */, - 6C98088F1E788AFD00E70590 /* IOKit.framework in Frameworks */, - 6C9808901E788AFD00E70590 /* OCMock.framework in Frameworks */, - DCB515DF1ED3CF95001F1152 /* SecurityFoundation.framework in Frameworks */, - 6C9808911E788AFD00E70590 /* SystemConfiguration.framework in Frameworks */, - 6C9808921E788AFD00E70590 /* libACM.a in Frameworks */, - 6C9808931E788AFD00E70590 /* libaks_acl.a in Frameworks */, - 6C9808941E788AFD00E70590 /* libbsm.dylib in Frameworks */, - 6C9808951E788AFD00E70590 /* libcoreauthd_client.a in Frameworks */, - 6C9808961E788AFD00E70590 /* libctkclient_sep.a in Frameworks */, - 6C9808971E788AFD00E70590 /* libsqlite3.0.dylib in Frameworks */, - 6C9808981E788AFD00E70590 /* libz.dylib in Frameworks */, + 6C61D3E9242A2C14008AB9BB /* Security.framework in Frameworks */, + 6C96328A242A284C00C53CE2 /* MobileKeyBag.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16537,19 +16270,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DCCA5E841E539EE7009EE93D /* AppKit.framework in Frameworks */, 6CAB39C71E521BEA00566A79 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 6CF4A0DD1E4549F200ECD7B5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6CE22D701E49206600974785 /* UIKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 790851B40CA9859F0083CC4D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -16569,6 +16293,7 @@ E71F3E3116EA69A900FAF9B4 /* SystemConfiguration.framework in Frameworks */, 4CAF66190F3A6FCD0064A534 /* IOKit.framework in Frameworks */, 4C2215220F3A612C00835155 /* libsqlite3.dylib in Frameworks */, + 0C2B32A423C4000F00A97B18 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16619,12 +16344,12 @@ DC00AB9A1D821D8800513D74 /* libSWCAgent.a in Frameworks */, DCD22D981D8CCF78001C9B81 /* libutilities.a in Frameworks */, BE442BB318B7FDB800F24DAE /* Security.framework in Frameworks */, + DC89608E2395C76300D339D9 /* CoreServices.framework in Frameworks */, BE442BB418B7FDB800F24DAE /* SystemConfiguration.framework in Frameworks */, BE442BB618B7FDB800F24DAE /* CFNetwork.framework in Frameworks */, BE25C41618B83491003320E0 /* Foundation.framework in Frameworks */, BE442BB718B7FDB800F24DAE /* IOKit.framework in Frameworks */, 438168C61B4ED43F00C54D58 /* CoreFoundation.framework in Frameworks */, - D4B858671D370D9A003B2D95 /* MobileCoreServices.framework in Frameworks */, BE442BB818B7FDB800F24DAE /* libsqlite3.dylib in Frameworks */, BE442BB918B7FDB800F24DAE /* libbsm.dylib in Frameworks */, ); @@ -16639,6 +16364,7 @@ D401E8B420A26F1F00CD8BB4 /* CoreData.framework in Frameworks */, DC340C54208E828F004D7EEC /* TrustedPeers.framework in Frameworks */, BE9F8D15206C2E0200B53D16 /* libutilities.a in Frameworks */, + DA53FC4923A9CC8D002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16668,7 +16394,6 @@ DC00C92320B3B80500628BEB /* libbsm.tbd in Frameworks */, DC00C92420B3B82600628BEB /* libz.tbd in Frameworks */, DC00C92020B3B7CC00628BEB /* libDER.a in Frameworks */, - DC6013312147220F00863C1A /* libaks_mock.a in Frameworks */, DC60132E2147220600863C1A /* libsecurityd_ios.a in Frameworks */, BE53602D209BBF630027E25A /* libMobileGestalt.tbd in Frameworks */, DC9C06712149E6B900C6F7B8 /* AuthKit.framework in Frameworks */, @@ -16677,10 +16402,9 @@ BED987DF209918A500607A5F /* SecurityFoundation.framework in Frameworks */, BED987D82099145300607A5F /* TrustedPeers.framework in Frameworks */, DC00C93520B48BA800628BEB /* IOKit.framework in Frameworks */, - DC00C91D20B3B79600628BEB /* libsecurity.a in Frameworks */, - BE53601C209BB8970027E25A /* libSecureObjectSyncFramework.a in Frameworks */, BE53601B209BB8390027E25A /* libSecureObjectSyncServer.a in Frameworks */, BE53601A209BB7F80027E25A /* libutilities.a in Frameworks */, + DA3862A723A9CD2E001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16697,7 +16421,6 @@ files = ( DC730E2922401F5E0051DD48 /* ProtocolBuffer.framework in Frameworks */, DC730E2522401E310051DD48 /* TrustedPeers.framework in Frameworks */, - 1B916CD0223FFF25006657FD /* ProtocolBuffer.framework in Frameworks */, BE72782C209D2C1400F0DA77 /* SecurityFoundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -16717,6 +16440,7 @@ D41257E21E94138600781F23 /* CoreFoundation.framework in Frameworks */, D41257D01E9410A300781F23 /* Foundation.framework in Frameworks */, D450686A1E948D2200FA7675 /* Security.framework in Frameworks */, + DA53FC3C23A9BDD5002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16727,6 +16451,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D445B309258C07FC0019858E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D445C2D3258C14BC0019858E /* Security.framework in Frameworks */, + D445C2D2258C14AB0019858E /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D44D1F642115893000E76E1A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -16738,6 +16471,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D49BD0762476F74B00FC7E1C /* libMobileGestalt.tbd in Frameworks */, D4FD4225217D7BEE002B7EE2 /* libarchive.2.tbd in Frameworks */, D453A4B22122236D00850A26 /* libz.tbd in Frameworks */, D453A4B32122236D00850A26 /* libsqlite3.tbd in Frameworks */, @@ -16752,6 +16486,7 @@ D453A4B92122236D00850A26 /* Foundation.framework in Frameworks */, D453A4BA2122236D00850A26 /* IOKit.framework in Frameworks */, D40B7CA021605BF800AC9A75 /* OCMock.framework in Frameworks */, + DA3862AB23AAE3A8001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16770,6 +16505,7 @@ files = ( D458C512214E20850043D982 /* XCTest.framework in Frameworks */, D458C507214E20540043D982 /* Foundation.framework in Frameworks */, + DA2F592623A99EC900C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16777,6 +16513,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D49BD0742476F67700FC7E1C /* libMobileGestalt.tbd in Frameworks */, D4FD4224217D7BE4002B7EE2 /* libarchive.2.tbd in Frameworks */, D4B68C62211A80CE009FED69 /* libz.tbd in Frameworks */, D4B68C5F211A80B1009FED69 /* libsqlite3.tbd in Frameworks */, @@ -16789,6 +16526,7 @@ D4B68C60211A80BC009FED69 /* CoreFoundation.framework in Frameworks */, D4B68C61211A80C4009FED69 /* Foundation.framework in Frameworks */, D4B68C63211A80DA009FED69 /* IOKit.framework in Frameworks */, + DA53FC4723A9CBAA002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17034,8 +16772,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D49BD0772476F7C000FC7E1C /* libMobileGestalt.tbd in Frameworks */, 4C47FA9420A51DD800384CB6 /* AppleFSCompression.framework in Frameworks */, DCD22D4B1D8CBF54001C9B81 /* libASN1.a in Frameworks */, + F6B1B48B24144B5F00CB3E3F /* libctkloginhelperlite.a in Frameworks */, DC00AB6F1D821C3400513D74 /* libSecItemShimOSX.a in Frameworks */, DC00AB701D821C3800513D74 /* libSecOtrOSX.a in Frameworks */, DC00AB6B1D821C1A00513D74 /* libSecTrustOSX.a in Frameworks */, @@ -17085,6 +16825,7 @@ DC1789251D7799CD00B50D50 /* CoreFoundation.framework in Frameworks */, DC1789271D7799D400B50D50 /* IOKit.framework in Frameworks */, 0940F6F92151316600C06F18 /* libACM.a in Frameworks */, + DA2F591823A32BC100C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17100,7 +16841,6 @@ buildActionMask = 2147483647; files = ( DCF465742201155000BA6EEA /* CloudServices.framework in Frameworks */, - 0C6C0FD121F1465500CD5B9E /* CoreCDP.framework in Frameworks */, DC391FAE21C1903E00772585 /* libutilities.a in Frameworks */, EBD531772198AF19003A57E6 /* Accounts.framework in Frameworks */, EBD531762198AF0B003A57E6 /* AppleAccount.framework in Frameworks */, @@ -17119,6 +16859,7 @@ DC222C361E02419B00B09171 /* libbsm.dylib in Frameworks */, DC3502CA1E020DC100BC0587 /* libsqlite3.0.dylib in Frameworks */, DC222C321E0240D300B09171 /* libz.dylib in Frameworks */, + DA53FC4023A9C351002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17234,6 +16975,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + DC5ABE181D832F2200CF422C /* Security.framework in Frameworks */, + F67B93C72547301F0076CA99 /* IOKit.framework in Frameworks */, DC5ABE191D832F2700CF422C /* CoreFoundation.framework in Frameworks */, BE64A7FA22AF006F001209F3 /* SecurityFoundation.framework in Frameworks */, DC5ABE181D832F2200CF422C /* Security.framework in Frameworks */, @@ -17269,9 +17012,9 @@ DC5AC0C91D8353D100CF422C /* libbsm.dylib in Frameworks */, DCD22D701D8CC733001C9B81 /* libutilities.a in Frameworks */, DC63D70820B3931100D088AD /* libxar.tbd in Frameworks */, - DC5AC0C71D8353C800CF422C /* PCSC.framework in Frameworks */, DC5AC0C51D8353C200CF422C /* Security.framework in Frameworks */, DC5AC0C41D8353BB00CF422C /* System.framework in Frameworks */, + D4E6D8592404EAD40074CB26 /* libDER.a in Frameworks */, DC5AC0C21D83538D00CF422C /* CoreFoundation.framework in Frameworks */, DC5AC0C11D83538800CF422C /* IOKit.framework in Frameworks */, ); @@ -17281,9 +17024,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0C570B8123F3A1EC001FEB3B /* CoreCDP.framework in Frameworks */, D47AB2D62357955F005A3801 /* Network.framework in Frameworks */, DCF46573220114F000BA6EEA /* CloudServices.framework in Frameworks */, - 0C4D96A621F24E5700617E60 /* CoreCDP.framework in Frameworks */, EB80DE56219600C6005B10FA /* libz.tbd in Frameworks */, DC9C066F2149E36900C6F7B8 /* AuthKit.framework in Frameworks */, 47C2F1762059A2300062DE30 /* libprequelite.tbd in Frameworks */, @@ -17292,6 +17035,7 @@ 474B5FC81E662E79007546F8 /* SecurityFoundation.framework in Frameworks */, D43B88721E72298500F86F19 /* MobileAsset.framework in Frameworks */, DC4EA5961E70A237008840B4 /* libsecurity.a in Frameworks */, + D49BD07824770E2D00FC7E1C /* libMobileGestalt.tbd in Frameworks */, 6C5B36BA1E2F9B95008AD443 /* WirelessDiagnostics.framework in Frameworks */, DC610A3D1D78F25C002223DE /* libDiagnosticMessagesClient.dylib in Frameworks */, DC610A3B1D78F234002223DE /* libACM.a in Frameworks */, @@ -17323,6 +17067,7 @@ DCD22D6B1D8CC685001C9B81 /* AppleSystemInfo.framework in Frameworks */, DC610A291D78F129002223DE /* IOKit.framework in Frameworks */, DC610A271D78F129002223DE /* Security.framework in Frameworks */, + DA3862AE23AAE65E001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17375,6 +17120,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0CD5040523F39DEA0036C279 /* CoreCDP.framework in Frameworks */, DCF465762201162800BA6EEA /* CloudServices.framework in Frameworks */, DC3E18C82125015300073D80 /* libsecurityd_ios.a in Frameworks */, DCCFB14E212394EC003D2DA2 /* libaks_mock.a in Frameworks */, @@ -17392,6 +17138,7 @@ DC99B88920EACA470065B73B /* libSecureObjectSyncServer.a in Frameworks */, DC99B88A20EACA470065B73B /* libutilities.a in Frameworks */, DC99B88B20EACA470065B73B /* libASN1.a in Frameworks */, + DA3862A923AAD1FD001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17441,7 +17188,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DCBF4AC121FFC82100539F0A /* CoreCDP.framework in Frameworks */, DCBF4AC221FFC82100539F0A /* libutilities.a in Frameworks */, DCBF4AC321FFC82100539F0A /* Accounts.framework in Frameworks */, DCBF4AC421FFC82100539F0A /* AppleAccount.framework in Frameworks */, @@ -17540,12 +17286,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0C570B7B23F3A09A001FEB3B /* CoreCDP.framework in Frameworks */, DC4A76AE22126C49006F2D8F /* CloudServices.framework in Frameworks */, EB80DE38219600A8005B10FA /* libz.tbd in Frameworks */, 482FE5642177C6850031C11E /* libprequelite.tbd in Frameworks */, 482FE5632177C5E80031C11E /* Accounts.framework in Frameworks */, 482FE5602177C5DA0031C11E /* AuthKit.framework in Frameworks */, - 0C4C548020E1A53D00BA61BA /* CoreCDP.framework in Frameworks */, 6C1F93111DD5E41A00585608 /* libDiagnosticMessagesClient.dylib in Frameworks */, DCE4E6AE1D7A3C6A00AFB96E /* AppleSystemInfo.framework in Frameworks */, DCE4E6AD1D7A3B9700AFB96E /* libaks.a in Frameworks */, @@ -17575,6 +17321,7 @@ files = ( D47AB2D02356B2F6005A3801 /* Network.framework in Frameworks */, 09EF431B21A5A8CC0066CF20 /* libaks_acl.a in Frameworks */, + 097CE59F246966A100958AF8 /* libMobileGestalt.dylib in Frameworks */, D4C6C5CD1FB3B423007EA57E /* libarchive.tbd in Frameworks */, D46246B71F9AE76500D63882 /* libDER.a in Frameworks */, DC3A81EC1D99F568000C7419 /* libcoretls.dylib in Frameworks */, @@ -17652,6 +17399,7 @@ DCD504C320CB293700F37D26 /* Security.framework in Frameworks */, DC4DB16A1E26E9F900CD6769 /* ProtocolBuffer.framework in Frameworks */, DCE4E82C1D7A56FF00AFB96E /* AppleSystemInfo.framework in Frameworks */, + DA53FC3923A9BA68002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17666,13 +17414,14 @@ D40B6A9E1E2B6A6F00CD6EE5 /* libtrustd.a in Frameworks */, D40B6A931E2B67E500CD6EE5 /* libutilities.a in Frameworks */, D40B6A831E2B5F5B00CD6EE5 /* libASN1.a in Frameworks */, - D40B6A9D1E2B6A2700CD6EE5 /* login.framework in Frameworks */, + D4981B8F24F723EA004B033B /* IOKit.framework in Frameworks */, D4ADA3311E2B43450031CEA3 /* CFNetwork.framework in Frameworks */, D47AB2CC2356AD7C005A3801 /* Network.framework in Frameworks */, D4ADA3301E2B433B0031CEA3 /* Security.framework in Frameworks */, D4ADA32E1E2B43220031CEA3 /* CoreFoundation.framework in Frameworks */, D4ADA32F1E2B43220031CEA3 /* Foundation.framework in Frameworks */, D4C7CD661E71E92D00139817 /* MobileAsset.framework in Frameworks */, + DA2F592123A9874800C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17683,11 +17432,13 @@ 5E01F5B1227C859200BC884C /* Foundation.framework in Frameworks */, DCE4E8C91D7F356500AFB96E /* libsqlite3.dylib in Frameworks */, DCE4E8C81D7F355F00AFB96E /* libbsm.dylib in Frameworks */, + F6F4105324AC622F00369037 /* libaks.a in Frameworks */, DCE4E8C71D7F355900AFB96E /* Security.framework in Frameworks */, DCE4E8C61D7F354700AFB96E /* CoreFoundation.framework in Frameworks */, DCE4E8C51D7F354300AFB96E /* IOKit.framework in Frameworks */, F6AF96681E646CAF00917214 /* libcoreauthd_client.a in Frameworks */, F682C1D41F4486F700F1B029 /* libctkloginhelper.a in Frameworks */, + DA2F591E23A986A300C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17706,7 +17457,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C4C547620E1A0B400BA61BA /* CoreCDP.framework in Frameworks */, + 0C570B7923F3A015001FEB3B /* CoreCDP.framework in Frameworks */, CD112FC51DDA31AD00C77A07 /* Accounts.framework in Frameworks */, 0CC319241DA46FBF005D42EA /* ProtectedCloudStorage.framework in Frameworks */, DCE4E9401D7F3E4D00AFB96E /* Security.framework in Frameworks */, @@ -17802,9 +17553,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0C147A2823F39CD10034F08B /* CoreCDP.framework in Frameworks */, D47AB2CF2356B2ED005A3801 /* Network.framework in Frameworks */, DC4A76A62212691F006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FCF21F1457600CD5B9E /* CoreCDP.framework in Frameworks */, EB80DE5C2196010F005B10FA /* libz.tbd in Frameworks */, 482FE56D2177CF150031C11E /* AuthKit.framework in Frameworks */, D4C6C5D01FB3B45E007EA57E /* libarchive.2.dylib in Frameworks */, @@ -17837,6 +17588,7 @@ E71F3E4116EA6A5100FAF9B4 /* SystemConfiguration.framework in Frameworks */, D418CC711E690CBC00330A44 /* MobileAsset.framework in Frameworks */, 0CFC029C1D41650700E6283B /* libcoretls.dylib in Frameworks */, + DA53FC4423A9C779002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17867,7 +17619,6 @@ files = ( 5A47FFBE228F6D1B00F781B8 /* ProtocolBuffer.framework in Frameworks */, EB59D6731E95F01600997EAC /* libcompression.dylib in Frameworks */, - DC65E7231D8CB28900152EF0 /* libutilities.a in Frameworks */, D4F56B95217FC93500FCA6B7 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -17886,7 +17637,6 @@ DCD22D531D8CC0EF001C9B81 /* libASN1.a in Frameworks */, E7F482A11C7543E500390FDB /* libsqlite3.dylib in Frameworks */, E7F482A31C7544E600390FDB /* libctkclient_test.a in Frameworks */, - E7F482A61C75453900390FDB /* libcoreauthd_test_client.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17920,8 +17670,6 @@ EB75B48C1E75407C00E469CC /* libutilities.a in Frameworks */, EB75B48D1E75408900E469CC /* libASN1.a in Frameworks */, EB75B48F1E75409A00E469CC /* libsqlite3.dylib in Frameworks */, - EB75B4901E7540AA00E469CC /* libctkclient_test.a in Frameworks */, - EB75B4911E7540BF00E469CC /* libcoreauthd_test_client.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17966,14 +17714,14 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + DCAAF3362493F9C600D4EB55 /* LocalAuthentication.framework in Frameworks */, + 0CCC22D823F39BCA00E1FCD0 /* CoreCDP.framework in Frameworks */, DC4A76AC221269E4006F2D8F /* CloudServices.framework in Frameworks */, EB49B2BB202D8894003F34A0 /* libsecurityd_ios.a in Frameworks */, - DC3E18EB2125FB8700073D80 /* libaks_mock.a in Frameworks */, EB49B2DD202DF259003F34A0 /* libbsm.tbd in Frameworks */, EB80DE59219600DF005B10FA /* libz.tbd in Frameworks */, EB49B2C2202DF002003F34A0 /* libDER.a in Frameworks */, 482FE5692177C7670031C11E /* AuthKit.framework in Frameworks */, - 0C6C0FD321F1494C00CD5B9E /* CoreCDP.framework in Frameworks */, EB49B2BE202DEF29003F34A0 /* libSecureObjectSyncServer.a in Frameworks */, EB49B2C1202DEF8D003F34A0 /* libASN1.a in Frameworks */, EB49B2C0202DEF7D003F34A0 /* libutilities.a in Frameworks */, @@ -17982,6 +17730,7 @@ EB49B2CD202DF0F9003F34A0 /* SystemConfiguration.framework in Frameworks */, EB49B2C7202DF0E9003F34A0 /* IOKit.framework in Frameworks */, EB49B2BC202DEF14003F34A0 /* libsqlite3.tbd in Frameworks */, + DA53FC4223A9C442002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17999,6 +17748,7 @@ EB6952B1223B75C300F02C1C /* CoreData.framework in Frameworks */, EB6952B2223B75C300F02C1C /* SystemConfiguration.framework in Frameworks */, EB6952B3223B75C300F02C1C /* libsqlite3.dylib in Frameworks */, + DA2F592823A99F6300C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18024,6 +17774,7 @@ EB89087921F17D3C00F0DDDB /* Security.framework in Frameworks */, EB89087B21F17D3C00F0DDDB /* SystemConfiguration.framework in Frameworks */, EB89087E21F17D3C00F0DDDB /* libsqlite3.dylib in Frameworks */, + DA3862AC23AAE3D3001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18044,6 +17795,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + EBAFC9A92551C26F0034B78D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EBAFDBB92551CFD20034B78D /* libutilities.a in Frameworks */, + EBAFD2592551CDA40034B78D /* libsecurity_cdsa_utilities.a in Frameworks */, + EBAFD25A2551CDA40034B78D /* libsecurity_utilities.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; EBB839A21E29665D00853BAC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -18059,6 +17820,7 @@ EBB8521D22F7948B00424FD0 /* libutilities.a in Frameworks */, EBB8521B22F7945600424FD0 /* XCTest.framework in Frameworks */, EBB852CF22F7A05600424FD0 /* OCMock.framework in Frameworks */, + DA53FC4823A9CC16002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18102,6 +17864,37 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0C0203DE23A855B8005D0A68 /* proto */ = { + isa = PBXGroup; + children = ( + 0C0203E023A8564E005D0A68 /* OTEscrowRecord.proto */, + 0C0D920523BFEA740070A68C /* OTCDPRecoveryInformation.proto */, + 0C0203E523A85780005D0A68 /* generated_source */, + ); + name = proto; + sourceTree = ""; + }; + 0C0203E523A85780005D0A68 /* generated_source */ = { + isa = PBXGroup; + children = ( + 0C468FEA23C7D4C8006F4582 /* OTCDPRecoveryInformation.h */, + 0C468FEE23C7D4CA006F4582 /* OTCDPRecoveryInformation.m */, + 0C468FE823C7D4C8006F4582 /* OTEscrowAuthenticationInformation.h */, + 0C468FEC23C7D4C9006F4582 /* OTEscrowAuthenticationInformation.m */, + 0C468FDE23C7D471006F4582 /* OTEscrowRecord.h */, + 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */, + 0C468FDA23C7D41D006F4582 /* OTEscrowRecordMetadata.h */, + 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */, + 0C468FDB23C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.h */, + 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */, + 0C468FE723C7D4C7006F4582 /* OTICDPRecordContext.h */, + 0C468FED23C7D4C9006F4582 /* OTICDPRecordContext.m */, + 0C468FE923C7D4C8006F4582 /* OTICDPRecordSilentContext.h */, + 0C468FEB23C7D4C9006F4582 /* OTICDPRecordSilentContext.m */, + ); + name = generated_source; + sourceTree = ""; + }; 0C0BDB30175685B000BC1A7E /* secdtests */ = { isa = PBXGroup; children = ( @@ -18142,14 +17935,12 @@ path = Categories; sourceTree = ""; }; - 0C4C546C20E19CF200BA61BA /* Recovered References */ = { + 0C7382E52386379E004F98CB /* ResetCloudKeychainAccount */ = { isa = PBXGroup; children = ( - 0C9FB40120D8729A00864612 /* CoreCDP.framework */, - DCD067E71D8CDF7E007602F1 /* SecCodeHostLib.h */, - DCD067E81D8CDF7E007602F1 /* SecCodeHostLib.c */, + 0C7382F023863AD5004F98CB /* reset_ick_account */, ); - name = "Recovered References"; + path = ResetCloudKeychainAccount; sourceTree = ""; }; 0C78F1C816A5E13400654E08 /* regressions */ = { @@ -18162,16 +17953,7 @@ path = regressions; sourceTree = ""; }; - 0C7CEA391FE9CE3900125C79 /* behavior */ = { - isa = PBXGroup; - children = ( - EB82A2A41FAFF26900CA64A9 /* SFBehavior.h */, - EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */, - ); - path = behavior; - sourceTree = ""; - }; - 0C8BBE831FC9DA1700580909 /* Octagon Trust */ = { + 0C8BBE831FC9DA1700580909 /* OT */ = { isa = PBXGroup; children = ( DCD33D7D220B9D98000A390B /* State Machine Machinery */, @@ -18213,7 +17995,7 @@ BE34059B1FD71BA700933DAC /* Protocol Buffers */, 0C8BBEB11FC9DCAC00580909 /* tests */, ); - name = "Octagon Trust"; + name = OT; path = ot; sourceTree = ""; }; @@ -18221,6 +18003,8 @@ isa = PBXGroup; children = ( DC99B89720EAD4D20065B73B /* Octagon */, + EB45ED3124749ECC008A1F6F /* OTTests-Info.plist */, + EB45ED3224749ECC008A1F6F /* gen_test_plist.py */, ); path = tests; sourceTree = ""; @@ -18272,6 +18056,40 @@ path = generated_source; sourceTree = ""; }; + 0CCC227B23F3586F00E1FCD0 /* ot-tests */ = { + isa = PBXGroup; + children = ( + 0CCC229223F35D4300E1FCD0 /* OctagonTrustTests-Info.plist */, + 0C9A54B7250C290800FF007B /* OctagonTrustTests.h */, + 0CCC229F23F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m */, + 0CCC22A323F36DD300E1FCD0 /* OctagonTrustTests-EscrowTestVectors.h */, + 0C9A54B4250C27F100FF007B /* OctagonTrustTests+Errors.m */, + ); + path = "ot-tests"; + sourceTree = ""; + }; + 0CCC22CB23F3958B00E1FCD0 /* categories */ = { + isa = PBXGroup; + children = ( + 0CCC22CC23F395A100E1FCD0 /* OctagonTrustEscrowRecoverer.h */, + ); + path = categories; + sourceTree = ""; + }; + 0CD743A723C3EC8000FA0EC5 /* OctagonTrust */ = { + isa = PBXGroup; + children = ( + 0C9F65AC23E3ACF700B1A2C5 /* OTEscrowTranslation.h */, + 0C9F65AA23E3ACF700B1A2C5 /* OTEscrowTranslation.m */, + 0CD743A823C3EC8000FA0EC5 /* OctagonTrust.h */, + 0CD743B723C3ED7E00FA0EC5 /* OctagonTrust.m */, + 0CD743A923C3EC8000FA0EC5 /* Info.plist */, + 0CCC22CB23F3958B00E1FCD0 /* categories */, + 0CCC227B23F3586F00E1FCD0 /* ot-tests */, + ); + path = OctagonTrust; + sourceTree = ""; + }; 0CE15E29222DF5FF00B7EAA4 /* RecoveryKey */ = { isa = PBXGroup; children = ( @@ -18287,9 +18105,6 @@ 0CF405FB2072E351003D6A7F /* Resources */, 0CD9E33E235928D1002995DE /* OctagonSignPosts.h */, 0CD9E340235928E9002995DE /* OctagonSignPosts.m */, - 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */, - 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */, - 0C108C4B208A677100E8CF70 /* SFSignInAnalytics+Internal.h */, 0CF405F32072E295003D6A7F /* tests */, ); path = SigninMetrics; @@ -18298,7 +18113,6 @@ 0CF405F32072E295003D6A7F /* tests */ = { isa = PBXGroup; children = ( - 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */, ); path = tests; sourceTree = ""; @@ -18318,6 +18132,7 @@ 0C78F1C816A5E13400654E08 /* regressions */, 107226D00D91DB32003CF14F /* SecTask.c */, 4C7CE56E0DC7DB0A00AE53FC /* SecEntitlements.h */, + 6C54BE0C23F41497004716CB /* SystemEntitlements.h */, ); name = sectask; path = ../../../sectask; @@ -18425,6 +18240,7 @@ 4727FBB81F9918590003AE36 /* secdxctests */ = { isa = PBXGroup; children = ( + 6CD8412B23F5D871003DDF34 /* KeychainBackupTests.m */, 477A1FEB2037A0E000ACD81D /* KeychainXCTest.h */, 477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */, 4727FBB91F9918590003AE36 /* KeychainCryptoTests.m */, @@ -18432,7 +18248,9 @@ 47B503C5203B97A000722164 /* SFCredentialStoreTests.m */, 477A1FE1203763A500ACD81D /* KeychainAPITests.m */, 09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */, + 6C84E3C723ECBC84003C9710 /* KeychainAppClipTests.m */, 4727FBBB1F9918590003AE36 /* Info.plist */, + 6C5D62A5221B6E3F00AF79DC /* secdxctests-entitlements.plist */, ); path = secdxctests; sourceTree = ""; @@ -18502,6 +18320,7 @@ 47922D171FAA65120008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.proto */, 47922D201FAA75FF0008F7E0 /* SecDbKeychainSerializedMetadata.proto */, 47922D2C1FAA77970008F7E0 /* SecDbKeychainSerializedSecretData.proto */, + 6C6AF178221A03930091CE0A /* SecDbKeychainSerializedMetadataKey.proto */, ); path = "SecDbKeychainV7-protobufs"; sourceTree = ""; @@ -18510,6 +18329,7 @@ isa = PBXGroup; children = ( DCE4E80D1D7A4E3A00AFB96E /* com.apple.securityd.plist */, + DCDACB5724A3F1AA0054080C /* com.apple.security.ckks.plist */, EB3FB9B7231C12A800DF52EA /* com.apple.security.trustedpeers.plist */, 48284A041D1DB06E00C76CB7 /* README_os_log_prefs.txt */, ); @@ -18535,6 +18355,8 @@ 4C35DB67094F906D002917C4 = { isa = PBXGroup; children = ( + 3DC5BD58241830D50039ABF4 /* SecureTransportTests_macos.xctestplan */, + 3DC5BD59241845100039ABF4 /* SecureTransportTests_ios.xctestplan */, DC6D2C941DD3B20400BE372D /* keychain */, DC5AC2021D83668700CF422C /* Security.framework */, DC5AC1FD1D83647300CF422C /* SecureObjectSync */, @@ -18545,7 +18367,6 @@ DC0BC4E51D8B6AA600070CB0 /* applications */, DC5AC2011D83663C00CF422C /* tests */, EB2CA5311D2C30CD00AB770F /* xcconfig */, - EBC73F44209A0BB200AE3350 /* xcscripts */, EBF374731DC055590065D840 /* security-sysdiagnose */, DC7FC44121EE6F4E003C39B8 /* featureflags */, E7FCBE401314471B000DE34E /* Frameworks */, @@ -18555,7 +18376,6 @@ 4CAB97FD1114CC5300EFB38D /* README.keychain */, 4C4CE9070AF81ED80056B01D /* TODO */, EBAC4A512189743D00FBEC43 /* rio.yml */, - 0C4C546C20E19CF200BA61BA /* Recovered References */, ); sourceTree = ""; }; @@ -18675,7 +18495,6 @@ D4ADA3191E2B41670031CEA3 /* libtrustd.a */, 6CCDF7841E3C25FA003F2555 /* KeychainEntitledTestRunner */, 6CF4A0B41E45488B00ECD7B5 /* KeychainEntitledTestApp.app */, - 6CF4A0E01E4549F200ECD7B5 /* KeychainEntitledTestApp.app */, EB27FF111E402CD300EC9E3A /* ckksctl */, 470415CF1E5E14B5001F3D95 /* seckeychainnetworkextensionstest */, 47702B1E1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */, @@ -18683,8 +18502,6 @@ EB108F411E6CE4D2003B0456 /* KCPairingTests.xctest */, F667EC601E96E9B100203D5C /* authdtest */, D41257CF1E9410A300781F23 /* trustd */, - 6C9808611E788AEB00E70590 /* CKKSCloudKitTests.xctest */, - 6C98089D1E788AFD00E70590 /* CKKSCloudKitTests.xctest */, ACBAF6DD1E9417F40007BA2F /* libsecurity_transform_regressions.a */, BEF88C281EAFFC3F00357577 /* TrustedPeers.framework */, BEF88C301EAFFC3F00357577 /* TrustedPeersTests.xctest */, @@ -18692,7 +18509,7 @@ BED208DD1EDF950E00753952 /* manifeststresstest */, 47C51B841EEA657D0032D9E5 /* SecurityUnitTests.xctest */, EB2D54AA1F02A45E00E46890 /* secatomicfile */, - 4727FBB71F9918580003AE36 /* secdxctests_ios.xctest */, + 4727FBB71F9918580003AE36 /* secdxctests.xctest */, 0C85E0031FB38BB6000343A7 /* OTTests.xctest */, 6C9AA79E1F7C1D8F00D08296 /* supdctl */, 6CAA8D201F842FB3007B6E03 /* securityuploadd */, @@ -18701,13 +18518,10 @@ 3DD1FF4D201C07F30086D049 /* SecureTransport_macos_tests.xctest */, 3DD1FFD0201FDB1D0086D049 /* SecureTransport_ios_tests.xctest */, BEAA002B202A832500E51F45 /* TrustedPeersHelper.xpc */, - 478D429C1FD72A8100CAB645 /* secdxctests_mac.xctest */, EB49B2AE202D877F003F34A0 /* secdmockaks.xctest */, 47C2F1832059CB680062DE30 /* KeychainResources.bundle */, 4718AE2D205B39620068EC3F /* securityd */, 4718AEE2205B39C40068EC3F /* libsecurityd_bridge.a */, - 0CF406502072E3E3003D6A7F /* SignInAnalyticsTests_ios.xctest */, - 0C9AEEB720783FBB00BF6237 /* SignInAnalyticsTests_osx.xctest */, DAE40BCE20CF3E47002D5674 /* secitemcanarytest */, DC0EF8EF208697C600AB9E95 /* tpctl */, BED987D32099145300607A5F /* TrustedPeersHelperUnitTests.xctest */, @@ -18738,40 +18552,19 @@ DA41FE0E2241ADC000838FB3 /* otpaird */, EBB851EC22F7912400424FD0 /* SecurityUtilitiesTests.xctest */, 5A442F90233C330F00918373 /* experimentTool */, + 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */, + 6C7BE2E723C3DD64003BB2CA /* securitytool_bridge */, + 0CCC227923F357EE00E1FCD0 /* OctagonTrustTests.xctest */, + 6C2045EA2424BA7E00F9461D /* KeychainStasher */, + 6C963281242A279B00C53CE2 /* stashtester */, + 3E88361124F068EF00E9F4D6 /* secseccodeapitest */, + 3E4D49BC2531170600B124B3 /* secsecstaticcodeapitest */, + EBAFC9AC2551C2700034B78D /* SecLegacyCodeRegressions.xctest */, + D445B30C258C07FC0019858E /* trustdFileHelper */, ); name = Products; sourceTree = ""; }; - 4C50ACFB1410671D00EE92DE /* DigiNotar */ = { - isa = PBXGroup; - children = ( - 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */, - 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */, - 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */, - 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */, - 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */, - 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */, - 4C3CECEF1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */, - 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */, - 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */, - 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */, - 4C50AD2F1410689300EE92DE /* Expectations.plist */, - 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */, - 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */, - 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */, - 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */, - 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */, - 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */, - 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */, - 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */, - 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */, - 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */, - 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */, - 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */, - ); - path = DigiNotar; - sourceTree = ""; - }; 4C52D0B616EFC61E0079966E /* CircleJoinRequested */ = { isa = PBXGroup; children = ( @@ -18855,6 +18648,7 @@ 4C6416F00BB357D5001C83FD /* SecInternal.h */, 4CF0484A0A5D988F00268236 /* SecItem.h */, 4CF0487F0A5F016300268236 /* SecItemPriv.h */, + DCC887242548EB3B004B0DB4 /* SecKnownFilePaths.h */, 4C7072840AC9EA4E007CC205 /* SecKey.h */, 4C7072D30AC9ED5A007CC205 /* SecKeyPriv.h */, 09A3B9D71F8267BB00C5C324 /* SecKeyProxy.h */, @@ -19028,6 +18822,17 @@ path = secacltests; sourceTree = ""; }; + 6C0535F422B7043B0064BA50 /* TestHostBinaries */ = { + isa = PBXGroup; + children = ( + 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner.entitlements */, + 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp */, + 6CB5F4771E402D6D00DBF3F0 /* KeychainEntitledTestRunner */, + ); + name = TestHostBinaries; + path = tests/TestHostBinaries; + sourceTree = ""; + }; 6C34464D1E2534C200F9522B /* analytics */ = { isa = PBXGroup; children = ( @@ -19051,6 +18856,14 @@ path = analytics; sourceTree = ""; }; + 6C534E0422C3E52600D4781F /* Discovery Plists */ = { + isa = PBXGroup; + children = ( + ); + name = "Discovery Plists"; + path = "tests/Discovery Plists"; + sourceTree = ""; + }; 6C69517B1F758E1000F68F91 /* supd */ = { isa = PBXGroup; children = ( @@ -19064,6 +18877,7 @@ 6C1260F21F7D5F25001B2EEC /* securityuploadd-osx.plist */, 6C5B10211F9164F5009B091E /* securityuploadd.8 */, 6CDB600E1FA92C1700410924 /* securityuploadd-Entitlements.plist */, + D42D044124733BEA004E7AA2 /* com.apple.securityuploadd.sb */, ); path = supd; sourceTree = ""; @@ -19093,10 +18907,11 @@ 6C7E8F1D21F7BD1C008A2D56 /* SecDbBackupTests */ = { isa = PBXGroup; children = ( - 6C2008EF220BB4B500674B3A /* Entitlements.plist */, - 6C02134F21F7ED45009D5C80 /* Info.plist */, + 6C6579FC2394878700701C8B /* SecDbBackupTestsBase.m */, + 6CD224E7239493E8001B70FD /* SecDbBackupTestsBase.h */, 6C02134D21F7ED16009D5C80 /* SecDbBackupTests.m */, - 6C02134C21F7ED16009D5C80 /* SecDbBackupTests.plist */, + 6C02134F21F7ED45009D5C80 /* Info.plist */, + 6C2008EF220BB4B500674B3A /* SecDbBackupTests-Entitlements.plist */, ); name = SecDbBackupTests; path = tests/SecDbBackupTests; @@ -19119,6 +18934,31 @@ path = generated_source; sourceTree = ""; }; + 6C963282242A279B00C53CE2 /* stashtester */ = { + isa = PBXGroup; + children = ( + 6C963283242A279B00C53CE2 /* main.m */, + 6C963289242A27F300C53CE2 /* stashtester.entitlements */, + ); + name = stashtester; + path = tests/stashtester; + sourceTree = ""; + }; + 6C997868242362EC008C498D /* KeychainStasher */ = { + isa = PBXGroup; + children = ( + 6C997869242362EC008C498D /* KeychainStasherProtocol.h */, + 6C99786A242362EC008C498D /* KeychainStasher.h */, + 6C99786B242362EC008C498D /* KeychainStasher.m */, + 6C99786D242362EC008C498D /* main.m */, + 6C99786F242362EC008C498D /* KeychainStasher-Info.plist */, + 6C48D10D2423A2F3004AF950 /* KeychainStasher.entitlements */, + 6C48D10F2423A3C0004AF950 /* com.apple.security.KeychainStasher.sb */, + 6C2045F92424BCB800F9461D /* com.apple.security.KeychainStasher.plist */, + ); + path = KeychainStasher; + sourceTree = ""; + }; 6C9AA79F1F7C1D9000D08296 /* supdctl */ = { isa = PBXGroup; children = ( @@ -19128,13 +18968,12 @@ path = supdctl; sourceTree = ""; }; - 6CB5F4771E402D6D00DBF3F0 /* testrunner */ = { + 6CB5F4771E402D6D00DBF3F0 /* KeychainEntitledTestRunner */ = { isa = PBXGroup; children = ( - 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner-Entitlements.plist */, 6CB5F47A1E402E5700DBF3F0 /* KeychainEntitledTestRunner.m */, ); - path = testrunner; + path = KeychainEntitledTestRunner; sourceTree = ""; }; 6CB6CBFE2198D40B0080AD6F /* SecDbBackupManager-protobufs */ = { @@ -19146,7 +18985,7 @@ path = "SecDbBackupManager-protobufs"; sourceTree = ""; }; - 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */ = { + 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp */ = { isa = PBXGroup; children = ( 6CF4A0B61E45488B00ECD7B5 /* AppDelegate.h */, @@ -19157,8 +18996,7 @@ 6CF4A0C41E45488B00ECD7B5 /* Info.plist */, 6CF4A0B91E45488B00ECD7B5 /* Supporting Files */, ); - name = KeychainEntitledTestApp_mac; - path = ../../../KeychainEntitledTestApp_mac; + path = KeychainEntitledTestApp; sourceTree = ""; }; 6CF4A0B91E45488B00ECD7B5 /* Supporting Files */ = { @@ -19169,29 +19007,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 6CF4A0E11E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */ = { - isa = PBXGroup; - children = ( - 6CF4A0E51E4549F200ECD7B5 /* AppDelegate.h */, - 6CF4A0E61E4549F300ECD7B5 /* AppDelegate.m */, - 6CF4A0E81E4549F300ECD7B5 /* ViewController.h */, - 6CF4A0E91E4549F300ECD7B5 /* ViewController.m */, - 6CF4A0EE1E4549F300ECD7B5 /* Assets.xcassets */, - 6CF4A0F31E4549F300ECD7B5 /* Info.plist */, - 6CF4A0E21E4549F200ECD7B5 /* Supporting Files */, - ); - name = KeychainEntitledTestApp_ios; - path = ../../../KeychainEntitledTestApp_ios; - sourceTree = ""; - }; - 6CF4A0E21E4549F200ECD7B5 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6CF4A0E31E4549F200ECD7B5 /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; 7908507E0CA87CF00083CC4D /* ipc */ = { isa = PBXGroup; children = ( @@ -19214,15 +19029,17 @@ path = ../ipc; sourceTree = ""; }; - 79679E241462028800CF997F /* DigicertMalaysia */ = { + A640B72225CB99600098A4A4 /* codesigning_api_tests */ = { isa = PBXGroup; children = ( - 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */, - 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */, - 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */, - 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */, + A640B72625CB9B3B0098A4A4 /* codesigning_tests_shared.h */, + 3E88361324F0699F00E9F4D6 /* seccode.c */, + A640B72525CB9A5C0098A4A4 /* secstaticcode.h */, + 3E4D508E253117DD00B124B3 /* secstaticcode.cpp */, + A640B71E25CB8A030098A4A4 /* secstaticcode_integration.m */, + A695677A2581B46000BDF83F /* unsigned_secstaticcodeapitest.sh */, ); - path = DigicertMalaysia; + name = codesigning_api_tests; sourceTree = ""; }; AA0DA47721E81885009F1C74 /* test_data */ = { @@ -19292,14 +19109,17 @@ BE3405A21FD71CDE00933DAC /* generated */ = { isa = PBXGroup; children = ( + 0C3C47C524902D470084B951 /* OTGlobalEnums.h */, + 0C3C47C424902D470084B951 /* OTSupportOctagonMessage.h */, + 0C3C47C024902D450084B951 /* OTSupportOctagonMessage.m */, + 0C3C47C224902D460084B951 /* OTSupportSOSMessage.h */, + 0C3C47C324902D460084B951 /* OTSupportSOSMessage.m */, 0C89BDA121554DD3003F3CC0 /* OTAccountMetadataClassC.h */, 0C89BDA021554DD2003F3CC0 /* OTAccountMetadataClassC.m */, 0C9AE28B214054F5003BFDB5 /* OTApplicantToSponsorRound2M1.h */, 0C9AE28E214054F6003BFDB5 /* OTApplicantToSponsorRound2M1.m */, 0C9AE2A1214055CE003BFDB5 /* OTPairingMessage.h */, 0C9AE2A2214055CF003BFDB5 /* OTPairingMessage.m */, - 0CE9C98921B88919006BDD80 /* OTSOSMessage.h */, - 0CE9C98A21B8891A006BDD80 /* OTSOSMessage.m */, 0C9AE289214054F4003BFDB5 /* OTSponsorToApplicantRound1M2.h */, 0C9AE28D214054F6003BFDB5 /* OTSponsorToApplicantRound1M2.m */, 0C9AE28A214054F5003BFDB5 /* OTSponsorToApplicantRound2M2.h */, @@ -19373,8 +19193,8 @@ BEAA002C202A832500E51F45 /* TrustedPeersHelper */ = { isa = PBXGroup; children = ( - 0CE15E29222DF5FF00B7EAA4 /* RecoveryKey */, DCB0C28F222F5DF80083AECB /* CuttlefishErrors.swift */, + 0CE15E29222DF5FF00B7EAA4 /* RecoveryKey */, 0C3BB3312187EC4D0018FC14 /* Categories */, 0C0C4F80216FB53A00C14C61 /* BottledPeer */, BE9F4F852072D834004A52C2 /* Cuttlefish Client */, @@ -19383,7 +19203,12 @@ DC754C712228B57B00A39C8E /* TrustedPeersHelperProtocol.m */, BE55C77B2044D0C90045863D /* Client.swift */, BE9F8D0F206C099800B53D16 /* Container.swift */, + DC3A9B2523A9D6120073ED06 /* Container_BottledPeers.swift */, + 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */, DCAD8F8422C43EAD007C3872 /* Container_MachineIDs.swift */, + 0C3DF8C524789C04009CF03A /* Container_Peers.swift */, + DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */, + DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */, BE9F8D18206C4AD300B53D16 /* ContainerMap.swift */, BE9F8D11206C121400B53D16 /* Decrypter.swift */, BECFA43C20F9493000B11002 /* Policy.swift */, @@ -19398,6 +19223,7 @@ 0CB582BA218915010040C5F2 /* proto */, DC391FA521C04D1500772585 /* OctagonPeerKeys.swift */, DCF6320421C074F30030CCC0 /* CuttlefishAPIHelpers.swift */, + DCBDA460245A39A300B0938B /* com.apple.TrustedPeersHelper.sb */, ); path = TrustedPeersHelper; sourceTree = ""; @@ -19469,6 +19295,8 @@ BEF88C5B1EB0005E00357577 /* TPPolicy.m */, BEF88C5C1EB0005E00357577 /* TPPolicyDocument.h */, BEF88C5D1EB0005E00357577 /* TPPolicyDocument.m */, + DCC03FA223FF521100A4DA3F /* TPSyncingPolicy.h */, + DCC03FA323FF521100A4DA3F /* TPSyncingPolicy.m */, BEF88C5E1EB0005E00357577 /* TPKey.h */, BECFA46320FFB87400B11002 /* TPKey.m */, BEF88C5F1EB0005E00357577 /* TPTypes.h */, @@ -19616,6 +19444,20 @@ name = docs; sourceTree = ""; }; + D445B307258C041E0019858E /* trustdFileHelper */ = { + isa = PBXGroup; + children = ( + D445B5B0258C08790019858E /* trustdFileHelper.m */, + D4FA61F8259D10E700EDB660 /* trustdFileHelper.h */, + D4FA5BD8259D0FCB00EDB660 /* main.m */, + D445B691258C088B0019858E /* com.apple.trustdFileHelper.plist */, + D445B692258C08B10019858E /* trustdFileHelper.8 */, + D445B772258C08CC0019858E /* com.apple.trustdFileHelper.sb */, + D445B773258C0F8D0019858E /* entitlements.plist */, + ); + path = trustdFileHelper; + sourceTree = ""; + }; D458C4DC214E1A4B0043D982 /* TestRunners */ = { isa = PBXGroup; children = ( @@ -19623,7 +19465,6 @@ D458C4CA214E1A420043D982 /* AppDelegate.m */, D458C4C8214E1A410043D982 /* AppDelegate.h */, D458C4C5214E1A400043D982 /* Assets.xcassets */, - D458C4C7214E1A400043D982 /* Base.lproj */, D458C4CC214E1A420043D982 /* Info.plist */, D458C4C6214E1A400043D982 /* main.m */, D458C4CB214E1A420043D982 /* trusttests_entitlements.plist */, @@ -19646,6 +19487,7 @@ D4A0F8BB211E69CB00443CA1 /* TestMacroConversions.h */, D44282FE22D68556001746B3 /* TrustEvaluationTestHelpers.m */, D4A7946D22D7DD6E00D1B2B7 /* TrustEvaluationTestHelpers.h */, + EB45ED2E24749DE9008A1F6F /* gen_test_plist.py */, ); name = TrustTests; sourceTree = ""; @@ -19653,7 +19495,17 @@ D4A0F8BD211E69D500443CA1 /* DaemonTests */ = { isa = PBXGroup; children = ( + D4D1CBB325AD0AAF0068595B /* CertificateServerTests.m */, + D4D1CC9525AD0ACD0068595B /* CertificateServerTests_data.h */, D4EA5CF622B225C000883439 /* LoggingServerTests.m */, + D49A370B23877ECC0065719F /* OCSPCacheTests.m */, + D4BA4FD22388687A000B9E64 /* OCSPCacheTests_data.h */, + D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */, + D407225A25310BC20084D96B /* PinningDbTests.m */, + D4D1CF3025AD37260068595B /* TrustServerTests.m */, + D4D1D1D125AFDA3D0068595B /* TrustServerTests_data.h */, + D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */, + D477CB6D237CBACD00C02355 /* TrustDaemonTestCase.h */, ); name = DaemonTests; sourceTree = ""; @@ -19661,12 +19513,20 @@ D4A0F8BE211E69DF00443CA1 /* EvaluationTests */ = { isa = PBXGroup; children = ( + D477CB8A237F8DBB00C02355 /* AllowlistBlocklistTests.m */, + D477CB8D237F8EB200C02355 /* AllowlistBlocklistTests_data.h */, + D477CB86237F8B2F00C02355 /* CAIssuerTests.m */, + D477CB89237F8CB300C02355 /* CAIssuerTests_data.h */, D458C4AA214E198D0043D982 /* CTTests.m */, D4EF3222215F102F000A31A5 /* CTTests_data.h */, + BED078F82542A2BF00FED203 /* CARevocationTests.m */, + BED0781D2542A2B300FED203 /* CARevocationTests_data.h */, D4AC5766214E195300A32C01 /* ECTests.m */, D4AC5767214E195300A32C01 /* ECTests_data.h */, D458C4AE214E198E0043D982 /* EvaluationBasicTests_data.h */, D458C4AF214E198E0043D982 /* EvaluationBasicTests.m */, + D477CB7A237E4BD700C02355 /* ExceptionTests.m */, + D477CB7D237F321400C02355 /* ExceptionTests_data.h */, D458C4B5214E19AE0043D982 /* iAPTests.m */, D458C4AD214E198E0043D982 /* iAPTests_data.h */, D4AC5768214E195400A32C01 /* KeySizeTests.m */, @@ -19679,10 +19539,17 @@ D4FD421F217D7B27002B7EE2 /* PathScoringTests.m */, D4FD4222217D7B48002B7EE2 /* PathScoringTests_data.h */, D458C513214E27620043D982 /* PolicyTests.m */, + D407217A252FE5FD0084D96B /* PolicyTests_data.h */, + D477CB81237F692400C02355 /* RevocationTests.m */, + D477CB85237F6A0700C02355 /* RevocationTests_data.h */, D458C4B7214E19AF0043D982 /* SignatureAlgorithmTests.m */, D458C4B6214E19AE0043D982 /* SignatureAlgorithmTests_data.h */, + D423114223725F9F000E470A /* SMIMEPolicyTests.m */, D4056A1922712A650026E24E /* SSLPolicyTests.m */, D4056A1C22712AD80026E24E /* SSLPolicyTests_data.h */, + D458DAC22375FEA300E5890E /* TrustSettingsTests.m */, + D458DAC52375FEE900E5890E /* TrustSettingsTests_data.h */, + D477CB8E237F975500C02355 /* ValidTests.m */, D4AC5764214E195200A32C01 /* VerifyDateTests.m */, D4AC5765214E195300A32C01 /* VerifyDateTests_data.h */, D4A0F8CB211E6A8200443CA1 /* TrustEvaluationTestCase.h */, @@ -19697,6 +19564,7 @@ D4A0F8C6211E6A5700443CA1 /* CertificateInterfaceTests.m */, D4A0F8C3211E6A5600443CA1 /* CertificateInterfaceTests_data.h */, D4AC8BE721320AD0006E9871 /* CertificateParseTests.m */, + D4C578E6255B746600AB5D78 /* PolicyInterfaceTests.m */, D458C4BF214E19FB0043D982 /* TrustInterfaceTests.m */, D458C4C0214E19FB0043D982 /* TrustInterfaceTests_data.h */, D458C4BE214E19FA0043D982 /* TrustSettingsInterfaceTests.m */, @@ -19709,12 +19577,17 @@ D4A0F8C0211E69F500443CA1 /* TestData */ = { isa = PBXGroup; children = ( + D41324122549E55B0062995A /* DigiNotar */, + D41321802549E49A0062995A /* DigicertMalaysia */, + D4072929253138730084D96B /* TestTrustdInitialization-data */, + D4231147237261F7000E470A /* SMIMEPolicyTests-data */, D4B2966822DBFDB100DCF250 /* TestCopyProperties_ios-data */, D4D92DA72278904F0009A7CF /* nist-certs */, D4AC8BED2132127A006E9871 /* si-18-certificate-parse */, D458C51B214E2CFF0043D982 /* si-20-sectrust-policies-data */, D4A0F8C1211E6A2F00443CA1 /* si-82-sectrust-ct-data */, D4056A1E22712D750026E24E /* si-87-sectrust-name-constraints */, + D477CB76237E453C00C02355 /* si-88-sectrust-valid-data */, D4056A1D22712D740026E24E /* ssl-policy-certs */, ); name = TestData; @@ -20345,7 +20218,6 @@ isa = PBXGroup; children = ( DC0BC9DB1D8B827200070CB0 /* CipherSuite.h */, - DC0BC9DC1D8B827200070CB0 /* SecureTransport.h */, ); name = "Public Headers"; path = ../Security; @@ -20355,6 +20227,7 @@ isa = PBXGroup; children = ( DC0BC9DE1D8B827200070CB0 /* sslTypes.h */, + DC0BC9DC1D8B827200070CB0 /* SecureTransport.h */, DC0BC9DF1D8B827200070CB0 /* SecureTransportPriv.h */, ); name = "Private Headers"; @@ -20595,6 +20468,7 @@ DC0BCB191D8B898100070CB0 /* SecTranslocateUtilities.cpp */, DC0BCB1A1D8B898100070CB0 /* SecTranslocateUtilities.hpp */, DC0BCB1B1D8B898100070CB0 /* SecTranslocateInterface.cpp */, + 61BDC97E242932A100A2ABD8 /* SecTranslocateEnumUtils.hpp */, ); path = lib; sourceTree = ""; @@ -20627,8 +20501,6 @@ DC0BCC3B1D8C68CF00070CB0 /* iCloudKeychainTrace.h */, EB3FBBF42320629400DF52EA /* SecABC.h */, EB3FBBF52320629400DF52EA /* SecABC.m */, - EBF3749A1DC064200065D840 /* SecADWrapper.c */, - EBF3749B1DC064200065D840 /* SecADWrapper.h */, DC0BCC3C1D8C68CF00070CB0 /* SecAKSWrappers.c */, DC0BCC3D1D8C68CF00070CB0 /* SecAKSWrappers.h */, DA5B871A2065A8410093F083 /* SecAutorelease.h */, @@ -20648,12 +20520,15 @@ DC0BCC4A1D8C68CF00070CB0 /* SecCFError.h */, DC0BCC4B1D8C68CF00070CB0 /* SecDispatchRelease.h */, DC0BCC4C1D8C68CF00070CB0 /* SecIOFormat.h */, + DCC8856D2548E9FB004B0DB4 /* SecKnownFilePaths.m */, EB71CF6322E8238000DA3D0E /* SecTapToRadar.h */, EB71CF6422E8238000DA3D0E /* SecTapToRadar.m */, E78CCDC61E737F6700C1CFAA /* SecNSAdditions.m */, E78CCDCD1E737F8100C1CFAA /* SecNSAdditions.h */, 5A04BB182298670C001848A0 /* SecXPCHelper.h */, 5A04BB14229866F7001848A0 /* SecXPCHelper.m */, + BE2609D325620B2C0057C489 /* SecXPCUtils.h */, + BE26081625620B190057C489 /* SecXPCUtils.m */, DC0BCC4D1D8C68CF00070CB0 /* SecTrace.c */, DC0BCC4E1D8C68CF00070CB0 /* SecTrace.h */, EB7AE6F61E86D55400B80B15 /* SecPLWrappers.m */, @@ -20662,6 +20537,7 @@ DC0BCC521D8C68CF00070CB0 /* debugging.c */, DC0BCC531D8C68CF00070CB0 /* debugging.h */, DC0BCC541D8C68CF00070CB0 /* debugging_test.h */, + 5F4C21FE2489C68900F0C425 /* simulatecrash_assert.h */, DC0BCC551D8C68CF00070CB0 /* der_array.c */, DC0BCC561D8C68CF00070CB0 /* der_boolean.c */, DC0BCC571D8C68CF00070CB0 /* der_null.c */, @@ -20677,6 +20553,8 @@ DC0BCC611D8C68CF00070CB0 /* der_set.c */, DC0BCC621D8C68CF00070CB0 /* der_set.h */, DC0BCC631D8C68CF00070CB0 /* der_string.c */, + A6BF3B3123EB94A7009AF079 /* entitlements.h */, + A6BF3B3223EB94A7009AF079 /* entitlements.c */, DC0BCC641D8C68CF00070CB0 /* fileIo.c */, DC0BCC651D8C68CF00070CB0 /* fileIo.h */, 7221843E1EC6782A004C7BED /* sec_action.c */, @@ -20690,6 +20568,7 @@ E7C787311DD0FED50087FC34 /* NSURL+SOSPlistStore.m */, DC0BCC6B1D8C68CF00070CB0 /* SecDb.c */, DC0BCC6C1D8C68CF00070CB0 /* SecDb.h */, + 6C915BE3242E14BC00DBDAFB /* SecDbInternal.h */, DC0BCC6D1D8C68CF00070CB0 /* SecFileLocations.c */, DC0BCC6E1D8C68CF00070CB0 /* SecFileLocations.h */, DC0BCC6F1D8C68CF00070CB0 /* SecXPCError.h */, @@ -20713,6 +20592,7 @@ children = ( DCC78E281D8085FC00865A7C /* AppleBaselineEscrowCertificates.h */, D41149A01E7C935D00C078C7 /* AppleiPhoneDeviceCACertificates.h */, + D47A085B2486EC1A000F2C49 /* AppleExternalRootCertificates.h */, DCC78E301D8085FC00865A7C /* SecAccessControl.m */, 443381DA18A3D81400215606 /* SecAccessControlPriv.h */, DCC78E351D8085FC00865A7C /* SecBase64.c */, @@ -20741,6 +20621,9 @@ DC4269031E82EDAC002B7110 /* SecItem.m */, DCC78E5A1D8085FC00865A7C /* SecItemBackup.c */, 4CE7EA561AEAE8D60067F5BD /* SecItemBackup.h */, + 6C513A37244F007B00207D5E /* SecItemRateLimit.h */, + 6CF1B5C5245077E400FD8CC4 /* SecItemRateLimit_tests.h */, + 6C513A38244F007B00207D5E /* SecItemRateLimit.m */, 52AA92881E662A4A004301A6 /* SecBackupKeybagEntry.m */, 52AA92871E662A4A004301A6 /* SecBackupKeybagEntry.h */, DCC78E5C1D8085FC00865A7C /* SecItemConstants.c */, @@ -20789,6 +20672,7 @@ DCC78E8A1D8085FC00865A7C /* SecServerEncryptionSupport.c */, E7676DB519411DF300498DD4 /* SecServerEncryptionSupport.h */, DCC78E8C1D8085FC00865A7C /* SecSharedCredential.c */, + BE7B8E112415579800E1CF4F /* SecSharedCredential.m */, DCC78E8E1D8085FC00865A7C /* SecSignatureVerificationSupport.c */, DCC78E8F1D8085FC00865A7C /* SecSignatureVerificationSupport.h */, DCC78E901D8085FC00865A7C /* SecTrust.c */, @@ -20890,21 +20774,9 @@ name = headers; sourceTree = ""; }; - DC17899F1D779DD600B50D50 /* SecBreadcrumb */ = { - isa = PBXGroup; - children = ( - DC1787731D77915500B50D50 /* SecBreadcrumb.h */, - DC1789A01D779DEE00B50D50 /* SecBreadcrumb.c */, - DC24B5701DA3274000330B48 /* breadcrumb_regressions.h */, - DCE4E6D41D7A41E400AFB96E /* bc-10-knife-on-bread.m */, - ); - name = SecBreadcrumb; - sourceTree = ""; - }; DC1789A31D779E2400B50D50 /* Security.framework macOS */ = { isa = PBXGroup; children = ( - DC17899F1D779DD600B50D50 /* SecBreadcrumb */, DCF783091D88B4B500E694BB /* apple_csp */, DCF785E61D88B96800E694BB /* apple_cspdl */, DCF787341D88C84300E694BB /* apple_file_dl */, @@ -20946,7 +20818,6 @@ D4C263C51F8FF2A9001317EA /* generateErrStrings.pl */, DC178A321D77A1F500B50D50 /* SecDebugErrorMessages.strings */, DC178A331D77A1F500B50D50 /* SecErrorMessages.strings */, - DC178A351D77A1F500B50D50 /* framework.sb */, DC178A381D77A1F500B50D50 /* InfoPlist.strings */, DC178A3A1D77A1F500B50D50 /* TimeStampingPrefs.plist */, DC178A3B1D77A1F500B50D50 /* authorization.dfr.prompts.strings */, @@ -21033,6 +20904,8 @@ DC15F79B1E68EAD5003B9A40 /* CKKSTests+API.m */, DC6593C91ED8DA9200C19462 /* CKKSTests+CurrentPointerAPI.m */, DC9A2C5E1EB3F556008FAC27 /* CKKSTests+Coalesce.m */, + DC86122B2408AC190092E93B /* CKKSTests+ItemSyncChoice.m */, + DCBA6F2824105399009A5187 /* CKKSTests+ForwardCompatibility.m */, DC62DC6E22A8721C000D2D5D /* CKKSTests+MultiZone.h */, DC62DC6B22A87128000D2D5D /* CKKSTests+MultiZone.m */, EBC1023022EBF8AC0083D356 /* CKKSTests+LockStateTracker.m */, @@ -21050,6 +20923,8 @@ DCA9BC06221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.m */, EBDE5DF922BA3D5D00A229C8 /* CKKSMockOctagonAdapter.h */, EBDE5DFA22BA3D5D00A229C8 /* CKKSMockOctagonAdapter.m */, + DCD68C7D255A14C900C2A1BA /* CKKSMockLockStateProvider.h */, + DCD68B9C255A149300C2A1BA /* CKKSMockLockStateProvider.m */, 6C34462F1E24F6BE00F9522B /* CKKSRateLimiterTests.m */, DCD6C4B61EC5319600414FEE /* CKKSNearFutureSchedulerTests.m */, DCFE1C3C1F17EFB5007640C8 /* CKKSConditionTests.m */, @@ -21067,6 +20942,7 @@ DCE7F2081F21726500DDB0F7 /* OctagonAPSReceiverTests.m */, DC9C95951F748D0B000D19E5 /* CKKSServerValidationRecoveryTests.m */, EB0E1AD723576273002B6037 /* CKKSPBFileStorageTests.m */, + EB45ED3024749E63008A1F6F /* gen_test_plist.py */, ); name = "Tests (Local)"; path = tests; @@ -21090,8 +20966,10 @@ DC8506A42097E8CF00C712EC /* iOS Resources */, DCC78E1C1D8085FC00865A7C /* add_internet_password.c */, DC52EA8E1D80CC2A00B0A59C /* builtin_commands.h */, + BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */, DCC78E1E1D8085FC00865A7C /* codesign.c */, D4A3A596217A85CB00F0A8DA /* ct_exceptions.m */, + D43538302526BB01002E72F7 /* trust_config.m */, DC52EA8F1D80CC2A00B0A59C /* digest_calc.c */, DCC78E1F1D8085FC00865A7C /* keychain_add.c */, DCC78E211D8085FC00865A7C /* keychain_backup.c */, @@ -21186,6 +21064,8 @@ DC5ABDBE1D832D5800CF422C /* Source */ = { isa = PBXGroup; children = ( + F67B93C425470D7D0076CA99 /* fvunlock.h */, + F67B93C1254707E00076CA99 /* fvunlock.m */, F9F77E96223C2F7B00E5CBF6 /* requirement.c */, F9F77E97223C2F7C00E5CBF6 /* requirement.h */, DC5ABD781D832D5800CF422C /* srCdsaUtils.cpp */, @@ -21260,6 +21140,7 @@ DC5ABDBB1D832D5800CF422C /* smartcards.m */, DC5ABDBC1D832D5800CF422C /* translocate.c */, DC5ABDBD1D832D5800CF422C /* translocate.h */, + F68D5B65254C065500020852 /* securitytool-entitlements.plist */, ); name = Source; sourceTree = ""; @@ -21459,6 +21340,8 @@ DC5ABFD11D83511A00CF422C /* notifications.cpp */, DC5ABFD21D83511A00CF422C /* SharedMemoryServer.h */, DC5ABFD31D83511A00CF422C /* SharedMemoryServer.cpp */, + 6C755604242121F000025D78 /* keychainstasherinterface.h */, + 6C755603242121F000025D78 /* keychainstasherinterface.m */, ); name = Support; sourceTree = ""; @@ -21591,26 +21474,30 @@ DC5AC2011D83663C00CF422C /* tests */ = { isa = PBXGroup; children = ( - EBDAF14021C75FC800EAE89F /* SharedMocks */, - DC05037721409A4100A8EDB7 /* OCMockUmbrella */, F667EC541E96E8C800203D5C /* authdtests */, - EB1055641E14DB370003C309 /* secfuzzer */, - DC0BCBD81D8C646700070CB0 /* regressionBase */, - DC0BCCB81D8C68F000070CB0 /* utilitiesRegressions */, - DC0BC5CD1D8B72FE00070CB0 /* test-checkpw */, - DC610AB81D7910E5002223DE /* gk_reset_check */, DC610A4E1D78F702002223DE /* codesign_tests */, - 5EBE247B1B00CCAE0007DB0E /* secacltests */, - DCE4E7E01D7A4B6D00AFB96E /* sectests */, - 0C0BDB30175685B000BC1A7E /* secdtests */, - E710C74A1331946500F85568 /* SecurityTests */, - EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */, - 4CE5A55609C7970A00D27A3F /* sslViewer */, + 6C534E0422C3E52600D4781F /* Discovery Plists */, 0C2BCBA41D063F7D00ED7A2F /* dtlsEcho */, - 4727FBB81F9918590003AE36 /* secdxctests */, - EB49B2AF202D8780003F34A0 /* secdmockaks */, + DC610AB81D7910E5002223DE /* gk_reset_check */, + EBAFC9A62551C1B50034B78D /* SecLegacyCodeRegressions */, + DC05037721409A4100A8EDB7 /* OCMockUmbrella */, + DC0BCBD81D8C646700070CB0 /* regressionBase */, + EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */, + 5EBE247B1B00CCAE0007DB0E /* secacltests */, 6C7E8F1D21F7BD1C008A2D56 /* SecDbBackupTests */, + EB49B2AF202D8780003F34A0 /* secdmockaks */, + 0C0BDB30175685B000BC1A7E /* secdtests */, + 4727FBB81F9918590003AE36 /* secdxctests */, + EB1055641E14DB370003C309 /* secfuzzer */, + DCE4E7E01D7A4B6D00AFB96E /* sectests */, + E710C74A1331946500F85568 /* SecurityTests */, + EBDAF14021C75FC800EAE89F /* SharedMocks */, + 4CE5A55609C7970A00D27A3F /* sslViewer */, + 6C963282242A279B00C53CE2 /* stashtester */, + DC0BC5CD1D8B72FE00070CB0 /* test-checkpw */, + 6C0535F422B7043B0064BA50 /* TestHostBinaries */, D4A0F8B9211E69A800443CA1 /* TrustTests */, + DC0BCCB81D8C68F000070CB0 /* utilitiesRegressions */, ); name = tests; sourceTree = ""; @@ -21681,11 +21568,13 @@ isa = PBXGroup; children = ( 0CDBCD8620AD03FB007F8EA7 /* OTClique.h */, + 0CD743BA23C3EF0D00FA0EC5 /* OTClique+Private.h */, 0C2F336A20DD643B0031A92D /* OTClique.m */, 0C8BBF0B1FCB452200580909 /* OTControl.h */, 0C8BBF0E1FCB452400580909 /* OTControl.m */, EB10A3E320356E2000E84270 /* OTConstants.h */, EB10A3E420356E2000E84270 /* OTConstants.m */, + 0C0203DE23A855B8005D0A68 /* proto */, ); name = Framework; sourceTree = ""; @@ -21800,15 +21689,16 @@ isa = PBXGroup; children = ( 6C34464D1E2534C200F9522B /* analytics */, - 0C7CEA391FE9CE3900125C79 /* behavior */, DCAE1DCF2073FCA400B4F687 /* categories */, EB27FF051E402C3C00EC9E3A /* ckksctl */, + 0CD743A723C3EC8000FA0EC5 /* OctagonTrust */, DC9B7AD31DCBF336004E9385 /* CloudKit Syncing */, 470D96651FCDE45C0065FE90 /* CoreDataKeychain */, 4771D974209A755800BA9772 /* KeychainDataclassOwner */, 47C2F1852059CB680062DE30 /* KeychainResources */, EB74CC182207E48000F1BBAD /* KeychainSettings */, - 0C8BBE831FC9DA1700580909 /* Octagon Trust */, + 6C997868242362EC008C498D /* KeychainStasher */, + 0C8BBE831FC9DA1700580909 /* OT */, 0C8BBEF61FCB402900580909 /* otctl */, DA41FDFC2241A7CD00838FB3 /* otpaird */, DC90A4BD21F275EC001300EB /* escrowrequest */, @@ -21822,6 +21712,7 @@ BEF88C451EAFFFED00357577 /* TrustedPeers */, BEAA002C202A832500E51F45 /* TrustedPeersHelper */, BED987D42099145300607A5F /* TrustedPeersHelperUnitTests */, + 0C7382E52386379E004F98CB /* ResetCloudKeychainAccount */, ); path = keychain; sourceTree = ""; @@ -21929,14 +21820,6 @@ path = OSX/libsecurity_asn1/lib; sourceTree = ""; }; - DC88467E223742CA00738068 /* View Matching */ = { - isa = PBXGroup; - children = ( - ); - name = "View Matching"; - path = view_matching; - sourceTree = ""; - }; DC90A4BD21F275EC001300EB /* escrowrequest */ = { isa = PBXGroup; children = ( @@ -21973,28 +21856,34 @@ DC99B89720EAD4D20065B73B /* Octagon */ = { isa = PBXGroup; children = ( - DCC0A4C52152C4AB000AF654 /* Pairing */, - DC27C3C820EADD8200F7839C /* OctagonTests-BridgingHeader.h */, + DCD689DD255A0AE300C2A1BA /* OctagonStateMachineTests.swift */, + DC7EB928211E20DF00516452 /* OctagonDataPersistenceTests.swift */, DC85687C2284E7850088D3EF /* OctagonTestMocks.swift */, + DC27C3C820EADD8200F7839C /* OctagonTests-BridgingHeader.h */, + DC99B89320EACA480065B73B /* OctagonTests-Info.plist */, DC27C3C020EAD9C300F7839C /* OctagonTests.swift */, + DC4415B323610BF40087981C /* OctagonTests+Account.swift */, DC7F79B522EA4ED4001FB69A /* OctagonTests+CKKS.swift */, + DCE405C423A04A7F00C4343B /* OctagonTests+CKKSConfiguration.swift */, + DC5BEACC2217509A001681F0 /* OctagonTests+CloudKitAccount.swift */, DC5F2BBD2310B941001ADA5D /* OctagonTests+CoreFollowUp.swift */, DC2819B822F8F6FE007829F5 /* OctagonTests+DeviceList.swift */, - 0C4CDE6D22922E360050C499 /* OctagonTests+RecoveryKey.swift */, DC07090222936BCC002711B9 /* OctagonTests+ErrorHandling.swift */, + 0CBF883A23AAD9DC00652EDD /* OctagonTests+EscrowRecords.swift */, DCDF03112284E34B008055BA /* OctagonTests+EscrowRecovery.swift */, - DC5BEACC2217509A001681F0 /* OctagonTests+CloudKitAccount.swift */, + DC7F6A7C233D7FAC00DF5769 /* OctagonTests+ForwardCompatibility.swift */, 0C5824A322860001009E8C15 /* OctagonTests+HealthCheck.swift */, + DC4CD9822372294D00EF55FC /* OctagonTests+Helpers.swift */, + 0C4CDE6D22922E360050C499 /* OctagonTests+RecoveryKey.swift */, DC72502D229600A800493D88 /* OctagonTests+Reset.swift */, - DCB947592127534C00ED9272 /* OctagonTests+SOSUpgrade.swift */, 0C87D3E2229368A7007853B5 /* OctagonTests+SOS.swift */, - DC7EB928211E20DF00516452 /* OctagonDataPersistenceTests.swift */, - DC99B89320EACA480065B73B /* OctagonTests-Info.plist */, - DCEA0FF6213F1E6F0054A328 /* Octagon.plist */, - 5A04BAF922973EA9001848A0 /* OTFollowupTests.m */, + DCB947592127534C00ED9272 /* OctagonTests+SOSUpgrade.swift */, + 0CA1D0B223E9023100021038 /* OctagonTests+EscrowTestVectors.swift */, DCFF82702162834C00D54B02 /* OctagonTestsXPCConnections.swift */, + DCC0A4C52152C4AB000AF654 /* Pairing */, 0CBEF3422242C9BE00015691 /* TestsObjcTranslation.h */, 0CBEF3412242C9AE00015691 /* TestsObjcTranslation.m */, + DCA7F7EE23A44AA200927989 /* OctagonPolicyTests.swift */, ); name = Octagon; path = octagon; @@ -22003,16 +21892,17 @@ DC9B7AD31DCBF336004E9385 /* CloudKit Syncing */ = { isa = PBXGroup; children = ( - DC88467E223742CA00738068 /* View Matching */, DC9FD3161F857FF800C8AAC8 /* Protocol Buffers */, DCD662F21E3294DE00188186 /* CloudKit Support */, DCFE1C311F17ECC3007640C8 /* dispatch Support */, DCD662EB1E32946000188186 /* Sync Objects */, DCD662F11E32946E00188186 /* Operations */, DC3502B61E0208BE00BC0587 /* Tests (Local) */, - DCA4D2121E5651950056214F /* Tests (Live CloudKit) */, DC1ED8C21DD5538C002BDCFA /* CKKS.h */, DC1ED8C51DD55476002BDCFA /* CKKS.m */, + DC880F67243D4CC00059806D /* CKKSLogging.m */, + DCC40B0F2383786D00402CB9 /* CKKSStates.h */, + DCC40B102383786D00402CB9 /* CKKSStates.m */, DC391F9921BF2F4B00772585 /* CKKSConstants.m */, DCF7A89F1F04502300CABE89 /* CKKSControlProtocol.h */, DCF7A8A21F0450EB00CABE89 /* CKKSControlProtocol.m */, @@ -22028,6 +21918,8 @@ DC1E5AB523063A4E00918162 /* CKKSPeerProvider.m */, DC1ED8C01DD51890002BDCFA /* CKKSItemEncrypter.h */, DC1ED8BA1DD51883002BDCFA /* CKKSItemEncrypter.m */, + DCF0C434256347B8007D5A6A /* CKKSMemoryKeyCache.h */, + DCF0C432256347B7007D5A6A /* CKKSMemoryKeyCache.m */, 6CC185971E24E87D009657D8 /* CKKSRateLimiter.h */, 6CC185981E24E87D009657D8 /* CKKSRateLimiter.m */, EB97364F234E8F4A00518B2B /* CKKSPBFileStorage.h */, @@ -22040,6 +21932,8 @@ DA6AA15E1FE88AF9004565B0 /* CKKSControlServer.m */, 479108B51EE879F9008CEFA0 /* CKKSAnalytics.h */, 479108B61EE879F9008CEFA0 /* CKKSAnalytics.m */, + DCA72ADF2530D3BD00CCB062 /* CKKSKeychainViewState.h */, + DCA72AE02530D3BD00CCB062 /* CKKSKeychainViewState.m */, ); name = "CloudKit Syncing"; path = ckks; @@ -22065,20 +21959,6 @@ path = generated_source; sourceTree = ""; }; - DCA4D2121E5651950056214F /* Tests (Live CloudKit) */ = { - isa = PBXGroup; - children = ( - 6CB5F4781E402E5700DBF3F0 /* KeychainCKKS.plist */, - 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */, - 6CF4A0E11E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */, - 6CB5F4771E402D6D00DBF3F0 /* testrunner */, - 6CCDF7911E3C2D69003F2555 /* CKKSCloudKitTests.m */, - 6CB5F4751E4025AB00DBF3F0 /* CKKSCloudKitTestsInfo.plist */, - ); - name = "Tests (Live CloudKit)"; - path = tests; - sourceTree = ""; - }; DCA4D2191E569FFE0056214F /* Helpers */ = { isa = PBXGroup; children = ( @@ -22086,6 +21966,8 @@ EB4E0CD51FF36A1900CDCACC /* CKKSReachabilityTracker.m */, DC207EB61ED4EAB600D46873 /* CKKSLockStateTracker.h */, DC207EB71ED4EAB600D46873 /* CKKSLockStateTracker.m */, + DC3412E5245780B9008ABD0A /* CKKSOperationDependencies.h */, + DC3412E6245780BA008ABD0A /* CKKSOperationDependencies.m */, DCCD88E61E42622200F5AA71 /* CKKSGroupOperation.h */, DCCD88E71E42622200F5AA71 /* CKKSGroupOperation.m */, DC1447881F5764C600236DB4 /* CKKSResultOperation.h */, @@ -22385,7 +22267,6 @@ DCB344731D8A35270054D16E /* regressions */, DCB342F81D8A32A20054D16E /* lib */, DC1787281D77903700B50D50 /* SecAccessPriv.h */, - DC1787291D77903700B50D50 /* SecCertificateBundle.h */, DC17872A1D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h */, DC17872B1D77903700B50D50 /* SecIdentitySearchPriv.h */, DC17872C1D77903700B50D50 /* SecKeychainItemExtendedAttributes.h */, @@ -22418,7 +22299,6 @@ DCB342441D8A32A20054D16E /* SecBase.cpp */, DCB342451D8A32A20054D16E /* SecBridge.h */, DCB342461D8A32A20054D16E /* SecCertificate.cpp */, - DCB342471D8A32A20054D16E /* SecCertificateBundle.cpp */, DCB342491D8A32A20054D16E /* SecIdentity.cpp */, DCB3424A1D8A32A20054D16E /* SecIdentitySearch.cpp */, DCB3424B1D8A32A20054D16E /* SecItemConstants.c */, @@ -22434,6 +22314,8 @@ DCB342551D8A32A20054D16E /* SecTrust.cpp */, DCB342561D8A32A20054D16E /* SecTrustedApplication.cpp */, DCB342571D8A32A20054D16E /* SecTrustSettings.cpp */, + 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */, + 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */, ); name = "API Bridge"; sourceTree = ""; @@ -22476,7 +22358,6 @@ DCB342A51D8A32A20054D16E /* PolicyCursor.h */, DCB342A61D8A32A20054D16E /* SecCFTypes.cpp */, DCB342A71D8A32A20054D16E /* SecCFTypes.h */, - DCB342A81D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp */, DCB342AA1D8A32A20054D16E /* StorageManager.cpp */, DCB342AB1D8A32A20054D16E /* Trust.cpp */, DCB342AC1D8A32A20054D16E /* Trust.h */, @@ -22625,13 +22506,13 @@ DCB3446B1D8A35270054D16E /* kc-40-seckey.m */, DCB3446C1D8A35270054D16E /* kc-41-sececkey.m */, DCB3446D1D8A35270054D16E /* kc-43-seckey-interop.m */, - DCB3446E1D8A35270054D16E /* kc-42-trust-revocation.c */, 24CBF8731E9D4E4500F09F0E /* kc-44-secrecoverypassword.c */, 6CA837612210C5E7002770F1 /* kc-45-change-password.c */, - DCB3446F1D8A35270054D16E /* si-20-sectrust-provisioning.c */, - DCB344701D8A35270054D16E /* si-20-sectrust-provisioning.h */, + DCB3446F1D8A35270054D16E /* si-20-certificate-copy-values.c */, DCB344711D8A35270054D16E /* si-33-keychain-backup.c */, DCB344721D8A35270054D16E /* si-34-one-true-keychain.c */, + BEE2953F25818E0300CD1294 /* si-40-identity-tests_data.h */, + BEE2954125818E0300CD1294 /* si-40-identity-tests.m */, DCCBFA1D1DBA95CD001DD54D /* kc-20-item-delete-stress.c */, ); name = regressions; @@ -22654,60 +22535,68 @@ children = ( 1BB1CAB6232C05BC001D0C71 /* CuttlefishXPCWrapper.h */, 1BB1CAB4232C05BB001D0C71 /* CuttlefishXPCWrapper.m */, - DCB946AD22FCB88400BE4490 /* OTDetermineHSA2AccountStatusOperation.h */, - DCB946AE22FCB88500BE4490 /* OTDetermineHSA2AccountStatusOperation.m */, DCE772642290712F005862B4 /* OctagonCheckTrustStateOperation.h */, DCE772652290712F005862B4 /* OctagonCheckTrustStateOperation.m */, - DC047085218BCEF20078BDAA /* OTOperationDependencies.h */, - DC047086218BCEF20078BDAA /* OTOperationDependencies.m */, - 1B5EAAD92252ABCC008D27E7 /* OTFetchViewsOperation.h */, - 1B5EAADB2252ABCC008D27E7 /* OTFetchViewsOperation.m */, + 0CA7020B2280D99D0085AC54 /* OTCheckHealthOperation.h */, + 0CA702082280D5600085AC54 /* OTCheckHealthOperation.m */, + 0CC8A9002123AA3B005D7F6A /* OTClientVoucherOperation.h */, + 0CC8A8FA2123A9EB005D7F6A /* OTClientVoucherOperation.m */, + DC0D16042363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.h */, + DC0D16052363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.m */, + DCB946AD22FCB88400BE4490 /* OTDetermineHSA2AccountStatusOperation.h */, + DCB946AE22FCB88500BE4490 /* OTDetermineHSA2AccountStatusOperation.m */, + 0C87D3DA229326CB007853B5 /* OTEnsureOctagonKeyConsistency.h */, + 0C87D3D6229326A2007853B5 /* OTEnsureOctagonKeyConsistency.m */, + 0C64C07F2485A54100D84A5D /* OTPreloadOctagonKeysOperation.h */, + 0C64C07C2485A53000D84A5D /* OTPreloadOctagonKeysOperation.m */, + 0C4F4DE121153659007F7E20 /* OTEpochOperation.h */, + 0C4F4DDA211535E8007F7E20 /* OTEpochOperation.m */, + 0C66046E2134985100BFBBB8 /* OTEstablishOperation.h */, + 0C6604692134983900BFBBB8 /* OTEstablishOperation.m */, DCBFF830222611A200C5C044 /* OTFetchCKKSKeysOperation.h */, DCBFF831222611A200C5C044 /* OTFetchCKKSKeysOperation.m */, + 1B5EAAD92252ABCC008D27E7 /* OTFetchViewsOperation.h */, + 1B5EAADB2252ABCC008D27E7 /* OTFetchViewsOperation.m */, + 0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */, + 0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */, DCF12671218A7579000124C6 /* OTLeaveCliqueOperation.h */, DCF12672218A757A000124C6 /* OTLeaveCliqueOperation.m */, + DC7F79B822EA5C72001FB69A /* OTLocalCKKSResetOperation.h */, + DC7F79B922EA5C72001FB69A /* OTLocalCKKSResetOperation.m */, + 0C00FC85217A972E00C8BF00 /* OTLocalCuttlefishReset.h */, + 0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.m */, + DC6E02122405DDC300C61335 /* OTModifyUserControllableViewStatusOperation.h */, + DC6E02132405DDC400C61335 /* OTModifyUserControllableViewStatusOperation.m */, + DC047085218BCEF20078BDAA /* OTOperationDependencies.h */, + DC047086218BCEF20078BDAA /* OTOperationDependencies.m */, + DCC67E2B20DDC07900A70A31 /* OTPrepareOperation.h */, + DCC67E2C20DDC07900A70A31 /* OTPrepareOperation.m */, + DC8757F2218D2003000E65F1 /* OTRemovePeersOperation.h */, + DC8757F3218D2003000E65F1 /* OTRemovePeersOperation.m */, + DC7250352296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.h */, + DC7250362296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.m */, + DCFF82722162876400D54B02 /* OTResetOperation.h */, + DCFF82732162876400D54B02 /* OTResetOperation.m */, + DC0D15FF2363A1D6007F0951 /* OTSetCDPBitOperation.h */, + DC0D16002363A1D6007F0951 /* OTSetCDPBitOperation.m */, + 0CD3D518224047B400024755 /* OTSetRecoveryKeyOperation.h */, + 0CD3D5152240479600024755 /* OTSetRecoveryKeyOperation.m */, + DC93F02722387A010072720A /* OTSOSUpdatePreapprovalsOperation.h */, + DC93F02822387A010072720A /* OTSOSUpdatePreapprovalsOperation.m */, + DC6DE897213076C000C6B56D /* OTSOSUpgradeOperation.h */, + DC6DE898213076C000C6B56D /* OTSOSUpgradeOperation.m */, + 0CDD6F78226E62BC009094C2 /* OTTriggerEscrowUpdateOperation.h */, + 0CDD6F76226E62AD009094C2 /* OTTriggerEscrowUpdateOperation.m */, DC221BA92267E2A60068DBCF /* OTUpdateTPHOperation.h */, DC221BAA2267E2A60068DBCF /* OTUpdateTPHOperation.m */, DCF46C2C214B1E0700319A93 /* OTUpdateTrustedDeviceListOperation.h */, DCF46C2D214B1E0700319A93 /* OTUpdateTrustedDeviceListOperation.m */, - DC6DE897213076C000C6B56D /* OTSOSUpgradeOperation.h */, - DC6DE898213076C000C6B56D /* OTSOSUpgradeOperation.m */, - DC93F02722387A010072720A /* OTSOSUpdatePreapprovalsOperation.h */, - DC93F02822387A010072720A /* OTSOSUpdatePreapprovalsOperation.m */, - DCC67E2B20DDC07900A70A31 /* OTPrepareOperation.h */, - DCC67E2C20DDC07900A70A31 /* OTPrepareOperation.m */, - 0C4F4DE121153659007F7E20 /* OTEpochOperation.h */, - 0C4F4DDA211535E8007F7E20 /* OTEpochOperation.m */, - 0CC8A9002123AA3B005D7F6A /* OTClientVoucherOperation.h */, - 0CC8A8FA2123A9EB005D7F6A /* OTClientVoucherOperation.m */, - 0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */, - 0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */, - 0C66046E2134985100BFBBB8 /* OTEstablishOperation.h */, - 0C6604692134983900BFBBB8 /* OTEstablishOperation.m */, - DCFF82722162876400D54B02 /* OTResetOperation.h */, - DCFF82732162876400D54B02 /* OTResetOperation.m */, - 0C00FC85217A972E00C8BF00 /* OTLocalCuttlefishReset.h */, - 0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.m */, - DC7F79B822EA5C72001FB69A /* OTLocalCKKSResetOperation.h */, - DC7F79B922EA5C72001FB69A /* OTLocalCKKSResetOperation.m */, - DC8757F2218D2003000E65F1 /* OTRemovePeersOperation.h */, - DC8757F3218D2003000E65F1 /* OTRemovePeersOperation.m */, DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */, DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */, - DC7250352296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.h */, - DC7250362296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.m */, 0CB8DC962194B1300021A7C8 /* OTVouchWithBottleOperation.h */, 0CB8DC992194B1440021A7C8 /* OTVouchWithBottleOperation.m */, 0C1B8BB3223323710094D5DA /* OTVouchWithRecoveryKeyOperation.h */, 0C1B8BB52233241E0094D5DA /* OTVouchWithRecoveryKeyOperation.m */, - 0CD3D518224047B400024755 /* OTSetRecoveryKeyOperation.h */, - 0CD3D5152240479600024755 /* OTSetRecoveryKeyOperation.m */, - 0CDD6F78226E62BC009094C2 /* OTTriggerEscrowUpdateOperation.h */, - 0CDD6F76226E62AD009094C2 /* OTTriggerEscrowUpdateOperation.m */, - 0CA7020B2280D99D0085AC54 /* OTCheckHealthOperation.h */, - 0CA702082280D5600085AC54 /* OTCheckHealthOperation.m */, - 0C87D3DA229326CB007853B5 /* OTEnsureOctagonKeyConsistency.h */, - 0C87D3D6229326A2007853B5 /* OTEnsureOctagonKeyConsistency.m */, ); name = Operations; sourceTree = ""; @@ -22751,7 +22640,7 @@ DCC78C561D8085D800865A7C /* secd-58-password-change.m */, DCC78C571D8085D800865A7C /* secd-59-account-cleanup.m */, DCC78C581D8085D800865A7C /* secd-60-account-cloud-identity.m */, - DCC78C591D8085D800865A7C /* secd60-account-cloud-exposure.m */, + DCC78C591D8085D800865A7C /* secd-60-account-cloud-exposure.m */, DCC78C5A1D8085D800865A7C /* secd-61-account-leave-not-in-kansas-anymore.m */, DCC78C5B1D8085D800865A7C /* secd-62-account-backup.m */, DCC78C5D1D8085D800865A7C /* secd-63-account-resurrection.m */, @@ -22759,6 +22648,7 @@ DCC78C5F1D8085D800865A7C /* secd-64-circlereset.m */, 48CC58971DA5FF0B00EBD9DB /* secd-66-account-recovery.m */, 483E79891DC875F2005C0008 /* secd-67-prefixedKeyIDs.m */, + 487A65F3245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m */, DCC78C601D8085D800865A7C /* secd-70-engine.m */, DCC78C611D8085D800865A7C /* secd-70-engine-corrupt.m */, DCC78C621D8085D800865A7C /* secd-70-engine-smash.m */, @@ -22776,7 +22666,6 @@ DCC78C701D8085D800865A7C /* secd-83-item-match-valid-on-date.m */, DCC78C711D8085D800865A7C /* secd-83-item-match-trusted.m */, DCC78C721D8085D800865A7C /* secd-83-item-match.h */, - DCC78C741D8085D800865A7C /* secd-95-escrow-persistence.m */, DCC78C751D8085D800865A7C /* secd-100-initialsync.m */, DCC78C761D8085D800865A7C /* secd-130-other-peer-views.m */, DCC78C771D8085D800865A7C /* secd-154-engine-backoff.m */, @@ -22787,9 +22676,9 @@ DCDCC7DD1D9B54DF006487E8 /* secd-202-recoverykey.m */, 7281E08E1DFD0D810021E1B7 /* secd-210-keyinterest.m */, 522B28081E64B48E002B5638 /* secd-230-keybagtable.m */, - DCFAEDD11D9998DD005187E4 /* secd-668-ghosts.m */, + 0C081F532559D181006DAD6A /* secd-231-v0Peers.m */, DCC78C791D8085D800865A7C /* SOSAccountTesting.h */, - DCC78C7A1D8085D800865A7C /* SecdTestKeychainUtilities.c */, + DCC78C7A1D8085D800865A7C /* SecdTestKeychainUtilities.m */, DCC78C7B1D8085D800865A7C /* SecdTestKeychainUtilities.h */, DCC78C7C1D8085D800865A7C /* SOSTransportTestTransports.m */, DCC78C7D1D8085D800865A7C /* SOSTransportTestTransports.h */, @@ -22824,6 +22713,8 @@ DCC78C991D8085D800865A7C /* SecItemSchema.h */, DCC78C9A1D8085D800865A7C /* SecItemServer.c */, DCC78C9B1D8085D800865A7C /* SecItemServer.h */, + FC637229237B5CF800973738 /* SecItemServer+SWC.h */, + FC63722A237B5CF900973738 /* SecItemServer+SWC.m */, DCC78C9C1D8085D800865A7C /* SecItemBackupServer.c */, DCC78C9D1D8085D800865A7C /* SecItemBackupServer.h */, DCC78C9E1D8085D800865A7C /* SecKeybagSupport.c */, @@ -22883,7 +22774,6 @@ DCC78D021D8085F200865A7C /* sc-42-circlegencount.c */, DCC78D031D8085F200865A7C /* sc-45-digestvector.c */, DCC78D041D8085F200865A7C /* sc-130-resignationticket.c */, - DCC78D061D8085F200865A7C /* sc-150-ring.m */, DCC78D071D8085F200865A7C /* sc-150-backupkeyderivation.c */, DCC78D081D8085F200865A7C /* sc-153-backupslicekeybag.c */, DCC78D091D8085F200865A7C /* SOSCircle_regressions.h */, @@ -22930,8 +22820,6 @@ DCC78D2A1D8085F200865A7C /* SOSBackupSliceKeyBag.h */, 48776C731DA5BB4200CC09B9 /* SOSRecoveryKeyBag.m */, 48776C741DA5BB4200CC09B9 /* SOSRecoveryKeyBag.h */, - 48E6171A1DBEC40D0098EAAD /* SOSBackupInformation.m */, - 48E6171B1DBEC40D0098EAAD /* SOSBackupInformation.h */, DCC78D2B1D8085F200865A7C /* SOSUserKeygen.m */, DCC78D2C1D8085F200865A7C /* SOSUserKeygen.h */, 485B64081DC16E8300B771B9 /* SOSKeyedPubKeyIdentifier.c */, @@ -23113,8 +23001,6 @@ DCC78D9B1D8085F200865A7C /* keychain_log.m */, 0C0CEC9D1DA45EA200C22FBC /* recovery_key.h */, 0C0CEC9E1DA45EA200C22FBC /* recovery_key.m */, - DCC78D9D1D8085F200865A7C /* syncbackup.m */, - DCC78D9C1D8085F200865A7C /* syncbackup.h */, DCC78D9E1D8085F200865A7C /* secViewDisplay.c */, DCC78D9F1D8085F200865A7C /* secViewDisplay.h */, 48C2F9321E4BCFC30093D70C /* accountCirclesViewsPrint.m */, @@ -23181,23 +23067,6 @@ path = "si-66-smime"; sourceTree = ""; }; - DCC78DF61D8085FC00865A7C /* si-67-sectrust-blocklist */ = { - isa = PBXGroup; - children = ( - DCC78DEC1D8085FC00865A7C /* Global Trustee.cer.h */, - DCC78DED1D8085FC00865A7C /* UTN-USERFirst-Hardware.cer.h */, - DCC78DEE1D8085FC00865A7C /* addons.mozilla.org.cer.h */, - DCC78DEF1D8085FC00865A7C /* login.live.com.cer.h */, - DCC78DF01D8085FC00865A7C /* login.skype.com.cer.h */, - DCC78DF11D8085FC00865A7C /* login.yahoo.com.1.cer.h */, - DCC78DF21D8085FC00865A7C /* login.yahoo.com.2.cer.h */, - DCC78DF31D8085FC00865A7C /* login.yahoo.com.cer.h */, - DCC78DF41D8085FC00865A7C /* mail.google.com.cer.h */, - DCC78DF51D8085FC00865A7C /* www.google.com.cer.h */, - ); - path = "si-67-sectrust-blocklist"; - sourceTree = ""; - }; DCC78E121D8085FC00865A7C /* secitem */ = { isa = PBXGroup; children = ( @@ -23210,28 +23079,16 @@ DCC78DB51D8085FC00865A7C /* si-14-dateparse.c */, DCC78DB61D8085FC00865A7C /* si-15-delete-access-group.m */, DCC78DB91D8085FC00865A7C /* si-17-item-system-bluetooth.m */, - DCC78DBD1D8085FC00865A7C /* si-21-sectrust-asr.c */, - DCC78DBE1D8085FC00865A7C /* si-22-sectrust-iap.c */, - DCC78DBF1D8085FC00865A7C /* si-22-sectrust-iap.h */, - DCC78DC01D8085FC00865A7C /* si-23-sectrust-ocsp.c */, - D46513072097954B005D93FE /* si-23-sectrust-ocsp.h */, - DCC78DC11D8085FC00865A7C /* si-24-sectrust-digicert-malaysia.c */, - DCC78DC21D8085FC00865A7C /* si-24-sectrust-diginotar.c */, - DCC78DC31D8085FC00865A7C /* si-24-sectrust-itms.c */, - DCC78DC51D8085FC00865A7C /* si-24-sectrust-passbook.c */, DC0B62261D90973900D43BCB /* si-25-cms-skid.h */, DC0B62271D90973900D43BCB /* si-25-cms-skid.m */, - DCC78DC61D8085FC00865A7C /* si-26-sectrust-copyproperties.c */, - DCC78DC71D8085FC00865A7C /* si-27-sectrust-exceptions.c */, - DCC78DC81D8085FC00865A7C /* si-28-sectrustsettings.m */, - DCC78DC91D8085FC00865A7C /* si-28-sectrustsettings.h */, + D4C573C3255B6A1800AB5D78 /* si-26-cms-apple-signed-samples.m */, + D4C5749F255B6AA600AB5D78 /* si-26-cms-apple-signed-samples.h */, + D4C88D87262E5DB20006FFB1 /* si-27-cms-parse.m */, D4AA0D9922FB959600D77FA4 /* si-29-cms-chain-mode.m */, D4AA0D9C22FB962300D77FA4 /* si-29-cms-chain-mode.h */, DCC78DCA1D8085FC00865A7C /* si-30-keychain-upgrade.c */, DCC78DCB1D8085FC00865A7C /* si-31-keychain-bad.c */, DCC78DCC1D8085FC00865A7C /* si-31-keychain-unreadable.c */, - D4CFAA7D1E660BB3004746AA /* si-32-sectrust-pinning-required.m */, - D4C8A1511E66709800CD6DF1 /* si-32-sectrust-pinning-required.h */, DCC78DCD1D8085FC00865A7C /* si-33-keychain-backup.c */, D4B6D57B2069D8450099FBEF /* si-34-cms-timestamp.m */, D4B6D5822069D85B0099FBEF /* si-34-cms-timestamp.h */, @@ -23262,23 +23119,15 @@ DCC78DE81D8085FC00865A7C /* si-65-cms-cert-policy.c */, DCC78DEA1D8085FC00865A7C /* si-66-smime */, DCC78DEB1D8085FC00865A7C /* si-66-smime.c */, - DCC78DF61D8085FC00865A7C /* si-67-sectrust-blocklist */, - DCC78DF71D8085FC00865A7C /* si-67-sectrust-blocklist.c */, DCC78DF81D8085FC00865A7C /* si-68-secmatchissuer.c */, DCC78DF91D8085FC00865A7C /* si-69-keydesc.c */, - DCC78DFA1D8085FC00865A7C /* si-70-sectrust-unified.c */, - DCC78DFB1D8085FC00865A7C /* si-71-mobile-store-policy.c */, DCC78DFC1D8085FC00865A7C /* si-72-syncableitems.c */, DCC78DFD1D8085FC00865A7C /* si-73-secpasswordgenerate.c */, - DCC78DFE1D8085FC00865A7C /* si-74-OTAPKISigner.c */, DCC78DFF1D8085FC00865A7C /* si-76-shared-credentials.c */, DCC78E001D8085FC00865A7C /* si_77_SecAccessControl.c */, DCC78E011D8085FC00865A7C /* si-78-query-attrs.c */, DCC78E021D8085FC00865A7C /* si-80-empty-data.c */, DCC78E051D8085FC00865A7C /* si-82-token-ag.c */, - DCC78E061D8085FC00865A7C /* si-83-seccertificate-sighashalg.c */, - BE6215BD1DB6E69100961E15 /* si-84-sectrust-allowlist.m */, - BE9B8B49202BB4A10081EF87 /* si-88-sectrust-valid.m */, DCC78E0B1D8085FC00865A7C /* si-89-cms-hash-agility.m */, DCC78E0D1D8085FC00865A7C /* si-90-emcs.m */, DCC78E0E1D8085FC00865A7C /* si-95-cms-basic.c */, @@ -23972,6 +23821,12 @@ isa = PBXGroup; children = ( DCA4D2191E569FFE0056214F /* Helpers */, + DC947E812463831E005B8669 /* CKKSCheckKeyHierarchyOperation.h */, + DC947E832463831F005B8669 /* CKKSCheckKeyHierarchyOperation.m */, + DCB5516A247F3DB50009A859 /* CKKSCreateCKZoneOperation.h */, + DCB5516B247F3DB50009A859 /* CKKSCreateCKZoneOperation.m */, + DCB55173247F48290009A859 /* CKKSDeleteCKZoneOperation.h */, + DCB55174247F48290009A859 /* CKKSDeleteCKZoneOperation.m */, DC5BB4F01E0C86800010F836 /* CKKSIncomingQueueOperation.h */, DC5BB4F11E0C86800010F836 /* CKKSIncomingQueueOperation.m */, DC5BB4FC1E0C98320010F836 /* CKKSOutgoingQueueOperation.h */, @@ -23982,6 +23837,8 @@ DCD662F41E329B6800188186 /* CKKSNewTLKOperation.m */, DCBF2F831F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.h */, DCBF2F841F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.m */, + DC061A6E246211DD0026ADB3 /* CKKSLocalResetOperation.h */, + DC061A70246211DE0026ADB3 /* CKKSLocalResetOperation.m */, DC7A17EB1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.h */, DC7A17EC1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.m */, DC5F65AC2225C22C0051E9FA /* CKKSProvideKeySetOperation.h */, @@ -24014,8 +23871,6 @@ DC222CA91E08C57400B09171 /* CloudKitDependencies.h */, DCEA5D831E2F14810089CF55 /* OctagonAPSReceiver.h */, DCEA5D841E2F14810089CF55 /* OctagonAPSReceiver.m */, - DCEA5D951E3014250089CF55 /* CKKSZone.h */, - DCEA5D961E3014250089CF55 /* CKKSZone.m */, DC18F76D1E43E116006B8B43 /* CKKSFetchAllRecordZoneChangesOperation.h */, DC18F76E1E43E116006B8B43 /* CKKSFetchAllRecordZoneChangesOperation.m */, DCFB12C31E95A4C000510F5F /* CKKSAccountStateTracker.h */, @@ -24032,23 +23887,23 @@ isa = PBXGroup; children = ( BE7089991F9AAF57001ACC20 /* generated */, - BE7089911F9AA027001ACC20 /* TPPBVoucher.proto */, - BE7089CB1FA3B19A001ACC20 /* TPPBPeerDynamicInfo.proto */, + BEC373A820D810DA00DBDF5B /* TPPBAncientEpoch.proto */, + DC88466922373A4000738068 /* TPPBDictionaryMatchingRule.proto */, BEC3739B20CF2AA200DBDF5B /* TPPBDisposition.proto */, BEC373C120D8224A00DBDF5B /* TPPBDispositionEntry.proto */, - BEC373A820D810DA00DBDF5B /* TPPBAncientEpoch.proto */, - BEC373A620D810D800DBDF5B /* TPPBPolicyProhibits.proto */, - BEC373A720D810D900DBDF5B /* TPPBUnknownMachineID.proto */, - BE7089CC1FA3B332001ACC20 /* TPPBPeerStableInfo.proto */, + BE7089CB1FA3B19A001ACC20 /* TPPBPeerDynamicInfo.proto */, BE7089DB1FA407E4001ACC20 /* TPPBPeerPermanentInfo.proto */, - BE7089D91FA3F0AF001ACC20 /* TPPBPolicySecret.proto */, + BE7089CC1FA3B332001ACC20 /* TPPBPeerStableInfo.proto */, 6C0C807D20EAF86100334E33 /* TPPBPolicyDocument.proto */, 6C0C807F20EAFB9600334E33 /* TPPBPolicyCategoriesByView.proto */, 6C0C808020EAFB9600334E33 /* TPPBPolicyModelToCategory.proto */, 6C0C808320EAFD7A00334E33 /* TPPBPolicyIntroducersByCategory.proto */, - 6C70D8D520EBDE4500AB6FAF /* TPPBPolicyRedaction.proto */, 1B8341B72239AD39002BF18A /* TPPBPolicyKeyViewMapping.proto */, - DC88466922373A4000738068 /* TPPBDictionaryMatchingRule.proto */, + BEC373A620D810D800DBDF5B /* TPPBPolicyProhibits.proto */, + 6C70D8D520EBDE4500AB6FAF /* TPPBPolicyRedaction.proto */, + BE7089D91FA3F0AF001ACC20 /* TPPBPolicySecret.proto */, + BEC373A720D810D900DBDF5B /* TPPBUnknownMachineID.proto */, + BE7089911F9AA027001ACC20 /* TPPBVoucher.proto */, ); path = proto; sourceTree = ""; @@ -24056,6 +23911,8 @@ DCE0777C21ADE96C002662FD /* generated */ = { isa = PBXGroup; children = ( + 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */, + 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */, 47922D501FAA7DF60008F7E0 /* SecDbKeychainSerializedItemV7.h */, 47922D511FAA7DF70008F7E0 /* SecDbKeychainSerializedItemV7.m */, 47922D371FAA7C040008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.h */, @@ -24097,6 +23954,8 @@ D4B68C65211A8186009FED69 /* trustd_spi.c */, D47DCCB423427C7D00B80E37 /* md.m */, D47DCCB723427C8D00B80E37 /* md.h */, + D47C4579255244AD00460750 /* CertificateTransparency.m */, + D47C4730255246FC00460750 /* CertificateTransparency.h */, D43DBED71E99D17100C04AEA /* nameconstraints.c */, D43DBED81E99D17100C04AEA /* nameconstraints.h */, D43DBED91E99D17100C04AEA /* OTATrustUtilities.m */, @@ -24130,6 +23989,7 @@ D43DBEF31E99D17300C04AEA /* SecRevocationServer.c */, D43DBEF41E99D17300C04AEA /* SecRevocationServer.h */, 5F8494FF22DFB502008B3EFB /* SecTrustExceptionResetCount.m */, + D42F6FF0256EEE18004ED354 /* SecTrustExceptionResetCount.h */, D43DBEF51E99D17300C04AEA /* SecTrustLoggingServer.m */, D43DBEF61E99D17300C04AEA /* SecTrustLoggingServer.h */, D43DBEF71E99D17300C04AEA /* SecTrustServer.c */, @@ -24137,9 +23997,14 @@ D43DBEF91E99D17300C04AEA /* SecTrustStoreServer.c */, D4EF321E215F0F76000A31A5 /* SecTrustStoreServer.m */, D43DBEFA1E99D17300C04AEA /* SecTrustStoreServer.h */, + D43534FC2525033E002E72F7 /* trustdFileLocations.h */, + D43534FD2525033E002E72F7 /* trustdFileLocations.m */, + D401443625789030008BAE33 /* TrustURLSessionCache.m */, + D401451725789075008BAE33 /* TrustURLSessionCache.h */, D4961BBD2079423300F16DA7 /* TrustURLSessionDelegate.m */, D4961BC52079426000F16DA7 /* TrustURLSessionDelegate.h */, D4ADA30E1E2B1E650031CEA3 /* trustd-Info.plist */, + D445B307258C041E0019858E /* trustdFileHelper */, DCE4E85E1D7A585300AFB96E /* macOS */, DCE4E85D1D7A584D00AFB96E /* iOS */, ); @@ -24189,6 +24054,7 @@ DC24B5641DA326B900330B48 /* Info.plist */, DC24B5651DA326B900330B48 /* mechanism.h */, DC24B5661DA326B900330B48 /* object.h */, + F681C3AA2386B8B40083F22C /* PreloginUserDb.h */, DC24B5671DA326B900330B48 /* process.h */, DC24B5681DA326B900330B48 /* rule.h */, DC24B5691DA326B900330B48 /* server.h */, @@ -24207,6 +24073,7 @@ DCE4E8AB1D7F353900AFB96E /* main.c */, DCE4E8AC1D7F353900AFB96E /* mechanism.c */, DCE4E8AD1D7F353900AFB96E /* object.c */, + F681C3A82386B8B40083F22C /* PreloginUserDb.m */, DCE4E8AE1D7F353900AFB96E /* process.c */, DCE4E8AF1D7F353900AFB96E /* rule.c */, DCE4E8B01D7F353900AFB96E /* server.c */, @@ -24989,16 +24856,7 @@ DCE4E6D61D7A420100AFB96E /* SecurityTestsOSX */, 4CC92ABA15A3B3D900C6D578 /* testlist.h */, 4CC92B1B15A3BF2F00C6D578 /* testmain.c */, - D4D886E81CEBDD2A00DC7583 /* nist-certs */, - D4D886BE1CEB9F3B00DC7583 /* ssl-policy-certs */, - D4AA64831E97270300D317ED /* si-18-certificate-parse */, - D4EC94FA1CEA482D0083E753 /* si-20-sectrust-policies-data */, - 0C0C88771CCEC5BD00617D1B /* si-82-sectrust-ct-data */, - DCE4E72E1D7A436300AFB96E /* si-82-sectrust-ct-logs.plist */, - D4C6C5C71FB2AD3F007EA57E /* si-87-sectrust-name-constraints */, - BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */, - 4C50ACFB1410671D00EE92DE /* DigiNotar */, - 79679E241462028800CF997F /* DigicertMalaysia */, + D4C88D8A262E660A0006FFB1 /* si-27-cms-parse */, E710C74B1331946500F85568 /* Supporting Files */, 0CB321F01464A95F00587CD3 /* CreateCerts.sh */, ); @@ -25110,6 +24968,7 @@ E7D848031C6BEFAB0025BB44 /* Tests */ = { isa = PBXGroup; children = ( + 52DA3C6F23C7E63500FEEDFF /* KCTLKRequestTest.m */, E7CFF7221C8660A000E3484E /* KeychainCircle.plist */, E7D848061C6BEFFA0025BB44 /* Info.plist */, E7D848041C6BEFC10025BB44 /* KCSRPTests.m */, @@ -25127,6 +24986,18 @@ E7FCBE401314471B000DE34E /* Frameworks */ = { isa = PBXGroup; children = ( + A69565BA2580ABBC00BDF83F /* libDER.a */, + A695631C2580AB8A00BDF83F /* libsecurity_cdsa_utilities.a */, + A695623B2580AB7800BDF83F /* libsecurity_utilities.a */, + A695615A2580A0F500BDF83F /* libsecurity_codesigning.a */, + D47A55892466100A0039285D /* MSUDataAccessor.framework */, + 6C99787C242364FB008C498D /* CoreFoundation.framework */, + 6C997879242364E5008C498D /* Foundation.framework */, + F6B1B48924144B5E00CB3E3F /* libctkloginhelperlite.a */, + 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */, + 0CCC22B123F38B5B00E1FCD0 /* libsqlite3.0.tbd */, + DA2F591523A32BB400C30285 /* SoftLinking.framework */, + DC89608C2395C75500D339D9 /* CoreServices.framework */, BEC6A9142331992800080069 /* Network.framework */, D47AB2CA2356AD72005A3801 /* Network.framework */, 0C6C2B6C2258295D00C53C96 /* UIKitCore.framework */, @@ -25143,14 +25014,12 @@ 0C75AC642141F18D0073A2F9 /* KeychainCircle.framework */, D4B68C5C211A7D98009FED69 /* libDER.a */, EB490153211C0026001E6D6A /* UserManagement.framework */, - 472E184F20D9A20D00ECE7C9 /* libcoreauthd_client.a */, 475EDD0720D9A031009D2409 /* LocalAuthenticationPrivateUI.framework */, 475EDD0520D98CE2009D2409 /* LocalAuthentication.framework */, 475EDD0320D98CD0009D2409 /* libctkclient.a */, 475EDD0120D98C81009D2409 /* libaks_acl.a */, 475EDCFF20D98C64009D2409 /* IOKit.framework */, 475EDCFD20D98C53009D2409 /* libaks.a */, - 475EDCFB20D98C3C009D2409 /* libDER.a */, 475EDCF920D98C0D009D2409 /* CryptoTokenKit.framework */, 475EDCF720D98BF6009D2409 /* CoreCDP.framework */, 475EDCF520D98BCF009D2409 /* libACM.a */, @@ -25286,7 +25155,6 @@ EB2CA4D81D2C28C800AB770F /* libaks.a */, 4432AF8C1A01472C000958DC /* libaks_acl.a */, DC1789181D77998C00B50D50 /* libbsm.dylib */, - E7F482A51C75453900390FDB /* libcoreauthd_test_client.a */, 0CFC029B1D41650700E6283B /* libcoretls.dylib */, E7F482A21C7544E600390FDB /* libctkclient_test.a */, EBE54D771BE33227000C4856 /* libmis.dylib */, @@ -25351,14 +25219,12 @@ DC5225091E402D8B0021640A /* PlatformLibraries.xcconfig */, DC976C581E3AC5E50012A6DD /* PlatformFeatures.xcconfig */, EB2CA5561D2C30F700AB770F /* Security.xcconfig */, - D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */, DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */, DC8E04901D7F6780006D80EB /* lib_ios.xcconfig */, DC71D8DD1D94CF3C0065FB93 /* lib_ios_shim.xcconfig */, D47C56AB1DCA831C00E18518 /* lib_ios_x64.xcconfig */, D47C56AF1DCA841D00E18518 /* lib_ios_x64_shim.xcconfig */, DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */, - BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */, EBF9AE171F536D0300FECBF7 /* Version.xcconfig */, DC340C53208E7BAE004D7EEC /* swift_binary.xcconfig */, DCC1849220EEEC4400F3B26C /* security_framework.xcconfig */, @@ -25474,6 +25340,8 @@ EB80211C1D3D9044008540C4 /* Modules */ = { isa = PBXGroup; children = ( + 0CF7613D23F24B5D00A3C3AD /* KeychainCircle.modulemap */, + 0CF7613F23F24B5E00A3C3AD /* OctagonTrust.modulemap */, EB8021411D3D90BB008540C4 /* Security.iOS.modulemap */, EB8021421D3D90BB008540C4 /* Security.macOS.modulemap */, 617570BA22C2D19E00EFBA37 /* Security.macOS.private.modulemap */, @@ -25492,6 +25360,9 @@ EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */ = { isa = PBXGroup; children = ( + A640B72225CB99600098A4A4 /* codesigning_api_tests */, + 6CF33CA2238714C900D1E75D /* bats_utd_plist.h */, + 6CF33CA4238714C900D1E75D /* PreprocessPlist.sh */, EB9C1DAD1BDFD49400F89272 /* Security.plist */, EBDAA7E320EC46CF003EA6E5 /* SecurityLocalKeychain.plist */, EBE202752092913500B48020 /* SecurityInduceLowDisk.plist */, @@ -25521,6 +25392,16 @@ name = secitemnotifications; sourceTree = ""; }; + EBAFC9A62551C1B50034B78D /* SecLegacyCodeRegressions */ = { + isa = PBXGroup; + children = ( + EBAFC9AE2551C2700034B78D /* legacyCodeRegressions.mm */, + EBAFC9B02551C2700034B78D /* Info.plist */, + ); + name = SecLegacyCodeRegressions; + path = tests/SecLegacyCodeRegressions; + sourceTree = ""; + }; EBB0314122223786007241CB /* Tests */ = { isa = PBXGroup; children = ( @@ -25529,14 +25410,6 @@ path = Tests; sourceTree = ""; }; - EBC73F44209A0BB200AE3350 /* xcscripts */ = { - isa = PBXGroup; - children = ( - EBC73F4A209A0BEF00AE3350 /* install-test-framework.sh */, - ); - name = xcscripts; - sourceTree = ""; - }; EBCF73CC1CE45F3F00BED7CA /* secitemfunctionality */ = { isa = PBXGroup; children = ( @@ -25586,6 +25459,22 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 0CD743A123C3EC8000FA0EC5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C468FE323C7D487006F4582 /* OTEscrowRecordMetadata.h in Headers */, + 0C468FF523C7D4D5006F4582 /* OTICDPRecordSilentContext.h in Headers */, + 0CD743AA23C3EC8000FA0EC5 /* OctagonTrust.h in Headers */, + 0C468FF323C7D4D5006F4582 /* OTICDPRecordContext.h in Headers */, + 0C468FE523C7D487006F4582 /* OTEscrowRecordMetadataClientMetadata.h in Headers */, + 0C468FEF23C7D4D5006F4582 /* OTCDPRecoveryInformation.h in Headers */, + 0C468FE123C7D487006F4582 /* OTEscrowRecord.h in Headers */, + 0C468FF123C7D4D5006F4582 /* OTEscrowAuthenticationInformation.h in Headers */, + 0C9F65AD23E3AD2E00B1A2C5 /* OTEscrowTranslation.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 225394B01E3080A600D3CD9B /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -25611,6 +25500,7 @@ 4718AEA0205B39C40068EC3F /* CKKSScanLocalItemsOperation.h in Headers */, 4718AEA1205B39C40068EC3F /* CKKSNotifier.h in Headers */, 4718AEA2205B39C40068EC3F /* CKKSGroupOperation.h in Headers */, + DCA72AE22530D3BD00CCB062 /* CKKSKeychainViewState.h in Headers */, 4718AEA3205B39C40068EC3F /* CKKSRateLimiter.h in Headers */, 4718AEA4205B39C40068EC3F /* SecDbKeychainSerializedItemV7.h in Headers */, 4718AEA6205B39C40068EC3F /* CKKSResultOperation.h in Headers */, @@ -25631,6 +25521,7 @@ 4718AEB5205B39C40068EC3F /* CloudKitCategories.h in Headers */, 4718AEB6205B39C40068EC3F /* CKKSDeviceStateEntry.h in Headers */, 4718AEB8205B39C40068EC3F /* CKKSAccountStateTracker.h in Headers */, + 6C6AF183221A07240091CE0A /* SecDbKeychainSerializedMetadataKey.h in Headers */, 4718AEB9205B39C40068EC3F /* CKKSZoneStateEntry.h in Headers */, DC5A01E921BB428500D87AB9 /* CKKSTLKShare.h in Headers */, 4718AEBA205B39C40068EC3F /* CKKSTLKShareRecord.h in Headers */, @@ -25677,7 +25568,6 @@ 4C32C1240A4976BF002891BD /* SecBase.h in Headers */, 4C32C1250A4976BF002891BD /* SecCertificate.h in Headers */, 4C32C1260A4976BF002891BD /* SecTrust.h in Headers */, - EB973651234E8F4B00518B2B /* CKKSPBFileStorage.h in Headers */, 4CF0484C0A5D988F00268236 /* SecItem.h in Headers */, 6CE3654F1FA100F10012F6AB /* SFAnalyticsDefines.h in Headers */, D4707A292113EF68005BCFDA /* SecCmsMessage.h in Headers */, @@ -25699,13 +25589,14 @@ DC3C73541D837B1900F6A832 /* SOSCloudCircle.h in Headers */, 524492941AFD6D480043695A /* der_plist.h in Headers */, DC3C73531D837AF800F6A832 /* SOSPeerInfo.h in Headers */, - 5A061198229ED8F3006AF14A /* NSDate+SFAnalytics.h in Headers */, D47079F321128C74005BCFDA /* SecCMS.h in Headers */, + A6BC648824897C5E00A21CD7 /* CSCommonPriv.h in Headers */, 4C12828D0BB4957D00985BB0 /* SecTrustSettingsPriv.h in Headers */, DCD45355209A5B260086CBFC /* si-cms-signing-identity-p12.h in Headers */, 1BE85ED5235CEC250051E1D8 /* sslDeprecated.h in Headers */, CDDE9BD11729ABFA0013B0E8 /* SecPasswordGenerate.h in Headers */, 4C7072860AC9EA4F007CC205 /* SecKey.h in Headers */, + 0CD743BB23C3EF1D00FA0EC5 /* OTClique+Private.h in Headers */, D4B3B1CC2115150D00A43409 /* SecCmsDigestedData.h in Headers */, 476541651F339F6300413F65 /* SecdWatchdog.h in Headers */, D47079FB211355C9005BCFDA /* CMSEncoder.h in Headers */, @@ -25714,10 +25605,10 @@ DCD7EE981F4F4DE9007D9804 /* SecBase64.h in Headers */, 4791B4652118BBFF00977C3F /* OTControlProtocol.h in Headers */, 4C7073CA0ACB2BAD007CC205 /* SecRSAKey.h in Headers */, + A6BC6491248B0AB400A21CD7 /* SecStaticCodePriv.h in Headers */, EB6928C51D9C9C6E00062A18 /* SecRecoveryKey.h in Headers */, 4C0B906E0ACCBD240077CD03 /* SecFramework.h in Headers */, EBF252222155E910000204D6 /* OTJoiningConfiguration.h in Headers */, - EB9B283321C7755700173DC2 /* OTDefines.h in Headers */, 4C7391790B01745000C4CBFA /* vmdh.h in Headers */, 6CDB5FFB1FA78D2C00410924 /* SFAnalyticsMultiSampler.h in Headers */, 4C64E01C0B8FBC71009B306C /* SecIdentity.h in Headers */, @@ -25752,6 +25643,7 @@ DC0C343821FA7DEB00417D04 /* SecEscrowRequest.h in Headers */, 4CE7EA791AEAF39C0067F5BD /* SecItemBackup.h in Headers */, 222F23A01DAC1603007ACB90 /* SecTaskPriv.h in Headers */, + DCC887252548EB3B004B0DB4 /* SecKnownFilePaths.h in Headers */, DC3C7AB51D838C1300F6A832 /* SecAsn1Templates.h in Headers */, 6CE365511FA100FE0012F6AB /* SFAnalyticsSampler.h in Headers */, 79EF5B6E0D3D6A31009F5270 /* SecImportExport.h in Headers */, @@ -25792,9 +25684,11 @@ DC3C7AB31D838BC300F6A832 /* CipherSuite.h in Headers */, 6C814A4C2050B4B600CB391B /* LocalKeychainAnalytics.h in Headers */, 4AF7000415AFB73800B9D400 /* SecOTRPackets.h in Headers */, + BE2609D425620B2C0057C489 /* SecXPCUtils.h in Headers */, 6C8CE6C11FA248DA0032ADF0 /* SFAnalyticsActivityTracker+Internal.h in Headers */, D4707A262113EBC1005BCFDA /* SecCmsDecoder.h in Headers */, DC3C7ABA1D838C9F00F6A832 /* sslTypes.h in Headers */, + 6C06CB902408602900025303 /* SecItemInternal.h in Headers */, 6CE3654B1FA100D00012F6AB /* SFAnalytics.h in Headers */, 5A442FA6233C34FE00918373 /* SecExperimentInternal.h in Headers */, 4AF7000515AFB73800B9D400 /* SecOTRSession.h in Headers */, @@ -25822,7 +25716,6 @@ 22A23B3D1E3AAC9800C41830 /* SecStaticCode.h in Headers */, 22A23B3E1E3AAC9800C41830 /* SecRequirement.h in Headers */, DC9C95BE1F79DC5F000D19E5 /* CKKSControl.h in Headers */, - 0CBFEACC200FCD33009A60E9 /* SFSignInAnalytics.h in Headers */, DC3C7AB61D838C2D00F6A832 /* SecAsn1Types.h in Headers */, 1B2BD397235E050E009A8624 /* Security-tapi.h in Headers */, D43D8B2D20AB8A54005BEEC4 /* Security.apinotes in Headers */, @@ -25861,6 +25754,7 @@ BEC373CB20D822DA00DBDF5B /* TPPBDispositionEntry.h in Headers */, BEF88C7F1EB000BE00357577 /* TPModel.h in Headers */, BE61F5AF1EB0060C00556CCF /* TrustedPeers.h in Headers */, + DCC03FA423FF521100A4DA3F /* TPSyncingPolicy.h in Headers */, BEF88C891EB000BE00357577 /* TPPolicy.h in Headers */, BEF88C871EB000BE00357577 /* TPPeerStableInfo.h in Headers */, BEF88C7B1EB000BE00357577 /* TPDecrypter.h in Headers */, @@ -25941,6 +25835,7 @@ buildActionMask = 2147483647; files = ( D43761661EB2996C00954447 /* SecRevocationNetworking.h in Headers */, + D43534FE2525033E002E72F7 /* trustdFileLocations.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -26065,6 +25960,7 @@ DC0BC7CF1D8B7B7F00070CB0 /* cssmconfig.h in Headers */, DC0BC7DB1D8B7B7F00070CB0 /* oidsbase.h in Headers */, DC0BC7D51D8B7B7F00070CB0 /* cssmspi.h in Headers */, + 6C97434824D1C8CB00A2025C /* LegacyAPICounts.h in Headers */, DC0BC7D01D8B7B7F00070CB0 /* cssmcspi.h in Headers */, DC0BC7AD1D8B773000070CB0 /* modload_static.h in Headers */, DC0BC7D21D8B7B7F00070CB0 /* cssmerr.h in Headers */, @@ -26334,8 +26230,8 @@ DC0BCDB21D8C6A1F00070CB0 /* SecInternalReleasePriv.h in Headers */, DC0BCD831D8C6A1E00070CB0 /* SecCFWrappers.h in Headers */, DC0BCDB01D8C6A1F00070CB0 /* SecAppleAnchorPriv.h in Headers */, + 5F4C22002489C6AB00F0C425 /* simulatecrash_assert.h in Headers */, B61577EC1F201562004A3930 /* SecPaddingConfigurationsPriv.h in Headers */, - EB4B6E261DC0683600AFC494 /* SecADWrapper.h in Headers */, DC36895921235F2A003A3735 /* SecAKSWrappers.h in Headers */, DC0BCDAA1D8C6A1F00070CB0 /* SecXPCError.h in Headers */, 72CDF5131EC679A4002D233B /* sec_action.h in Headers */, @@ -26398,13 +26294,11 @@ DC2671071F3E8A0900816EED /* SecECKey.h in Headers */, DC17877C1D77919500B50D50 /* SecBasePriv.h in Headers */, 5F00F95C230614AD00B832E0 /* SecImportExportPriv.h in Headers */, - DC1787741D77915500B50D50 /* SecBreadcrumb.h in Headers */, 6CB420AB2051FDE000FF2D44 /* LocalKeychainAnalytics.h in Headers */, 1BE85ED0235CEB620051E1D8 /* cms-tapi.h in Headers */, DC1787761D77916600B50D50 /* SecCFAllocator.h in Headers */, DC0C343A21FA7DEB00417D04 /* SecEscrowRequest.h in Headers */, DC17859F1D778C8D00B50D50 /* SecCertificate.h in Headers */, - DC1787361D77903700B50D50 /* SecCertificateBundle.h in Headers */, DC1785501D778ACD00B50D50 /* SecCertificateOIDs.h in Headers */, DC1787821D7791BE00B50D50 /* SecCertificatePriv.h in Headers */, 5A6D1B9E20810EF40057CAC8 /* SecProtocolTypes.h in Headers */, @@ -26416,7 +26310,6 @@ DC1787511D7790A500B50D50 /* SecCodePriv.h in Headers */, DC1787521D7790A500B50D50 /* SecCodeSigner.h in Headers */, DC1785301D778A0100B50D50 /* SecCustomTransform.h in Headers */, - 0CBFEACD200FCD33009A60E9 /* SFSignInAnalytics.h in Headers */, 5A442FA8233C34FF00918373 /* SecExperimentInternal.h in Headers */, DC1787771D77916A00B50D50 /* SecDH.h in Headers */, DC1785311D778A0100B50D50 /* SecDecodeTransform.h in Headers */, @@ -26441,7 +26334,6 @@ DC1787781D77917100B50D50 /* SecItemBackup.h in Headers */, DC17877F1D7791A800B50D50 /* SecItemPriv.h in Headers */, DC17859D1D778C8000B50D50 /* SecKey.h in Headers */, - EB9B283421C7755800173DC2 /* OTDefines.h in Headers */, 6CC952481FB4CB2C0051A823 /* SFAnalytics+Internal.h in Headers */, DC1787801D7791AD00B50D50 /* SecKeyPriv.h in Headers */, DC1785521D778ACD00B50D50 /* SecKeychain.h in Headers */, @@ -26456,6 +26348,7 @@ DCA9D84221FFE62A00B27421 /* EscrowRequestXPCProtocol.h in Headers */, DC1786F91D778F2500B50D50 /* SecNullTransform.h in Headers */, DC17873D1D77903700B50D50 /* SecPassword.h in Headers */, + 6C06CB912408602A00025303 /* SecItemInternal.h in Headers */, DC1787791D77917700B50D50 /* SecPasswordGenerate.h in Headers */, 1BE85ED6235CEC250051E1D8 /* sslDeprecated.h in Headers */, F6EEF77521675EF000FB7F79 /* AuthorizationTrampolinePriv.h in Headers */, @@ -26473,6 +26366,7 @@ DC1785351D778A0100B50D50 /* SecReadTransform.h in Headers */, DC17873F1D77903700B50D50 /* SecRecoveryPassword.h in Headers */, 6CE3654C1FA100D10012F6AB /* SFAnalytics.h in Headers */, + D4593EFF24C131180069F577 /* SecTrustStore.h in Headers */, DC17858B1D778B8000B50D50 /* SecRequirement.h in Headers */, DC1787551D7790A500B50D50 /* SecRequirementPriv.h in Headers */, DC17877A1D77917D00B50D50 /* SecServerEncryptionSupport.h in Headers */, @@ -26485,6 +26379,7 @@ DC1785381D778A0100B50D50 /* SecTransformReadTransform.h in Headers */, DC1786F41D778EF800B50D50 /* SecTranslocate.h in Headers */, D43718BC211683F100EA350A /* tsaSupport.h in Headers */, + BE2609D525620B2C0057C489 /* SecXPCUtils.h in Headers */, DC1785A01D778C9400B50D50 /* SecTrust.h in Headers */, DC1787841D7791C900B50D50 /* SecTrustPriv.h in Headers */, 6CDB5FFC1FA78D2D00410924 /* SFAnalyticsMultiSampler.h in Headers */, @@ -26557,7 +26452,6 @@ D4B3B1D921151BBF00A43409 /* SecCmsSignedData.h in Headers */, DC17857E1D778B4A00B50D50 /* oidscrl.h in Headers */, DC1787701D77911D00B50D50 /* osKeyTemplates.h in Headers */, - 5A061199229ED8F4006AF14A /* NSDate+SFAnalytics.h in Headers */, D4707A302114C316005BCFDA /* SecCmsDigestContext.h in Headers */, DC2C5F511F0D935300FEBDA7 /* CKKSControlProtocol.h in Headers */, AA7C71B72185429900EB314F /* SecProtocolTypesPriv.h in Headers */, @@ -26568,10 +26462,12 @@ 4723C9CB1F152ECF0082882F /* SFSQLiteStatement.h in Headers */, 6CE365501FA100F20012F6AB /* SFAnalyticsDefines.h in Headers */, 6CE365521FA100FF0012F6AB /* SFAnalyticsSampler.h in Headers */, + DCC887262548EB3B004B0DB4 /* SecKnownFilePaths.h in Headers */, D43D8B2C20AB8A48005BEEC4 /* Security.apinotes in Headers */, 4723C9C31F152EB60082882F /* SFObjCType.h in Headers */, DCB3323C1F46833E00178C30 /* SecLogging.h in Headers */, DC9C95BD1F79DC5A000D19E5 /* CKKSControl.h in Headers */, + 0CD743BC23C3EF1E00FA0EC5 /* OTClique+Private.h in Headers */, DC3C73561D837B9B00F6A832 /* SOSPeerInfoPriv.h in Headers */, EB6928C61D9C9C6F00062A18 /* SecRecoveryKey.h in Headers */, D4B3B1D0211516A100A43409 /* SecCmsEncryptedData.h in Headers */, @@ -26603,7 +26499,9 @@ DC0FA6B02291F63F00FE01C4 /* OctagonPendingFlag.h in Headers */, 47922D421FAA7C240008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.h in Headers */, DCFE1C341F17ECE5007640C8 /* CKKSCondition.h in Headers */, + DCB55175247F48290009A859 /* CKKSDeleteCKZoneOperation.h in Headers */, DC1E5AB623063A4E00918162 /* CKKSPeerProvider.h in Headers */, + DCF0C436256347BB007D5A6A /* CKKSMemoryKeyCache.h in Headers */, DC047081218BB21E0078BDAA /* OTCuttlefishAccountStateHolder.h in Headers */, DC1DA65E1E4554620094CE7F /* CKKSScanLocalItemsOperation.h in Headers */, DC2C5F5D1F0EB97E00FEBDA7 /* CKKSNotifier.h in Headers */, @@ -26634,6 +26532,7 @@ DC7A17ED1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.h in Headers */, DC52E7E31D80BDA600B0A59C /* SecDbQuery.h in Headers */, 470D96711FCDE55B0065FE90 /* SecCDKeychain.h in Headers */, + DCC40B112383786D00402CB9 /* CKKSStates.h in Headers */, DC378B2D1DEF9DF000A3DAFA /* CKKSMirrorEntry.h in Headers */, DC94BCCA1F10448600E07CEB /* CloudKitCategories.h in Headers */, DCC67E2D20DDC07900A70A31 /* OTPrepareOperation.h in Headers */, @@ -26656,6 +26555,7 @@ DC9082C61EA027DB00D0C1C5 /* CKKSZoneChangeFetcher.h in Headers */, DC614C5122A9BDB500E16ADA /* CKKSZoneModifier.h in Headers */, DCA4D2151E5684220056214F /* CKKSReencryptOutgoingItemsOperation.h in Headers */, + DC0D16012363A1D6007F0951 /* OTSetCDPBitOperation.h in Headers */, 0C38AA96212B2D1E00C90A1D /* OTClientVoucherOperation.h in Headers */, DC378B3C1DF0CA7200A3DAFA /* CKKSIncomingQueueEntry.h in Headers */, DC5F65AE2225C22C0051E9FA /* CKKSProvideKeySetOperation.h in Headers */, @@ -26664,6 +26564,7 @@ DC52E7E61D80BE7B00B0A59C /* SecItemDb.h in Headers */, DCF12673218A757A000124C6 /* OTLeaveCliqueOperation.h in Headers */, DCAD9B441F8D939C00C5E2AE /* CKKSFixups.h in Headers */, + DC0D16062363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.h in Headers */, DC9C95B41F79CFD1000D19E5 /* CKKSControl.h in Headers */, DC52E7EA1D80BE9500B0A59C /* SecItemSchema.h in Headers */, DC7F79BA22EA5C73001FB69A /* OTLocalCKKSResetOperation.h in Headers */, @@ -26676,6 +26577,7 @@ DCD662F51E329B6800188186 /* CKKSNewTLKOperation.h in Headers */, DC52E7EB1D80BE9B00B0A59C /* iCloudTrace.h in Headers */, DCF7A8A01F04502400CABE89 /* CKKSControlProtocol.h in Headers */, + DCA72AE12530D3BD00CCB062 /* CKKSKeychainViewState.h in Headers */, 47FF17261FD60ACA00875565 /* SFKeychainServer.h in Headers */, DC6D2C931DD2836500BE372D /* CKKSOutgoingQueueEntry.h in Headers */, DC15F7661E67A6F6003B9A40 /* CKKSHealKeyHierarchyOperation.h in Headers */, @@ -26685,6 +26587,7 @@ DCBF2F851F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.h in Headers */, DCE278E81ED7A5B40083B485 /* CKKSUpdateCurrentItemPointerOperation.h in Headers */, DCEA5D851E2F14810089CF55 /* OctagonAPSReceiver.h in Headers */, + 6C6AF182221A07230091CE0A /* SecDbKeychainSerializedMetadataKey.h in Headers */, DC1447961F5766D200236DB4 /* NSOperationCategories.h in Headers */, DC4DB1501E24692100CD6769 /* CKKSKey.h in Headers */, DCE278DD1ED789EF0083B485 /* CKKSCurrentItemPointer.h in Headers */, @@ -26729,7 +26632,6 @@ DC52E9161D80C41A00B0A59C /* SOSPeerInfoInternal.h in Headers */, DC3C735A1D837C0000F6A832 /* SOSPeerInfoPriv.h in Headers */, DC52E91A1D80C43500B0A59C /* SOSRing.h in Headers */, - 48E617221DBEC6C60098EAAD /* SOSBackupInformation.h in Headers */, CD198F971DE27B9E00F6FB83 /* SOSAccountPriv.h in Headers */, DC52E9231D80C47100B0A59C /* SOSTransportCircleKVS.h in Headers */, DC52E92C1D80C4AF00B0A59C /* SOSTransportKeyParameter.h in Headers */, @@ -26791,7 +26693,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 0C78827520132074002B7475 /* SFSignInAnalytics.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -26832,6 +26733,7 @@ DC5ABDFC1D832E8300CF422C /* keychain_delete.h in Headers */, DC5ABDFD1D832E8300CF422C /* keychain_export.h in Headers */, DC5ABDFE1D832E8300CF422C /* keychain_find.h in Headers */, + F67B93C525470D7E0076CA99 /* fvunlock.h in Headers */, DC5ABDFF1D832E8300CF422C /* keychain_import.h in Headers */, DC5ABE001D832E8300CF422C /* keychain_list.h in Headers */, DC5ABE011D832E8300CF422C /* keychain_lock.h in Headers */, @@ -27092,6 +26994,7 @@ DCB3439C1D8A32A20054D16E /* SecImportExportOpenSSH.h in Headers */, DCB343A61D8A32A20054D16E /* SecPkcs8Templates.h in Headers */, DCB343461D8A32A20054D16E /* ExtendedAttribute.h in Headers */, + 6C2D463E24C88AA60015C3C9 /* LegacyAPICounts.h in Headers */, DCB343601D8A32A20054D16E /* Trust.h in Headers */, DCB3437B1D8A32A20054D16E /* PrimaryKey.h in Headers */, DCB343911D8A32A20054D16E /* TokenLogin.h in Headers */, @@ -27118,7 +27021,6 @@ DCB344781D8A35270054D16E /* kc-identity-helpers.h in Headers */, DCB344791D8A35270054D16E /* kc-keychain-file-helpers.h in Headers */, DCB344741D8A35270054D16E /* keychain_regressions.h in Headers */, - DCB344A51D8A35270054D16E /* si-20-sectrust-provisioning.h in Headers */, DCB344771D8A35270054D16E /* kc-key-helpers.h in Headers */, DCB3449D1D8A35270054D16E /* kc-30-xara-upgrade-helpers.h in Headers */, DCB3449F1D8A35270054D16E /* kc-30-xara-key-helpers.h in Headers */, @@ -27310,6 +27212,7 @@ DCD06B491D8E0D7D007602F1 /* blob.h in Headers */, DCD06B911D8E0D7D007602F1 /* unix++.h in Headers */, DCD06B9D1D8E0D7D007602F1 /* macho++.h in Headers */, + 5F4C22012489C6AC00F0C425 /* simulatecrash_assert.h in Headers */, DCD06BAA1D8E0D7D007602F1 /* cfmunge.h in Headers */, DCD06B6A1D8E0D7D007602F1 /* seccfobject.h in Headers */, DC2670F21F3E6EC500816EED /* debugging.h in Headers */, @@ -27334,6 +27237,7 @@ DCD06B841D8E0D7D007602F1 /* utility_config.h in Headers */, DCD06B8D1D8E0D7D007602F1 /* pcsc++.h in Headers */, DCD06B9B1D8E0D7D007602F1 /* cfmach++.h in Headers */, + A6BF3B3623EB95F0009AF079 /* entitlements.h in Headers */, DCD06B441D8E0D7D007602F1 /* crc.h in Headers */, DCD06B6D1D8E0D7D007602F1 /* simpleprefs.h in Headers */, DCD06B8B1D8E0D7D007602F1 /* muscle++.h in Headers */, @@ -27911,42 +27815,43 @@ productReference = 0C8BBF081FCB446400580909 /* otctl */; productType = "com.apple.product-type.tool"; }; - 0C9AEEAB20783FBB00BF6237 /* SignInAnalyticsTests_osx */ = { + 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 0C9AEEB420783FBB00BF6237 /* Build configuration list for PBXNativeTarget "SignInAnalyticsTests_osx" */; + buildConfigurationList = 0CCC227623F357EE00E1FCD0 /* Build configuration list for PBXNativeTarget "OctagonTrustTests" */; buildPhases = ( - 0C9AEEAE20783FBB00BF6237 /* Sources */, - 0C9AEEB020783FBB00BF6237 /* Frameworks */, - 0C9AEEB320783FBB00BF6237 /* Embed OCMock */, + 0CCC220B23F357EE00E1FCD0 /* Sources */, + 0CCC226123F357EE00E1FCD0 /* Frameworks */, + 0CCC227423F357EE00E1FCD0 /* Resources */, ); buildRules = ( ); dependencies = ( - 0C9AEEBA20783FE000BF6237 /* PBXTargetDependency */, + 0C7EB14F23F3D1480089097B /* PBXTargetDependency */, + 0C7EB14D23F3D13C0089097B /* PBXTargetDependency */, + 0CCC22AD23F38B0E00E1FCD0 /* PBXTargetDependency */, + 0CCC22AB23F38B0600E1FCD0 /* PBXTargetDependency */, ); - name = SignInAnalyticsTests_osx; - productName = CKKSTests; - productReference = 0C9AEEB720783FBB00BF6237 /* SignInAnalyticsTests_osx.xctest */; + name = OctagonTrustTests; + productName = TrustedPeersHelperUnitTests; + productReference = 0CCC227923F357EE00E1FCD0 /* OctagonTrustTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 0CF406042072E3E3003D6A7F /* SignInAnalyticsTests_ios */ = { + 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */ = { isa = PBXNativeTarget; - buildConfigurationList = 0CF4064D2072E3E3003D6A7F /* Build configuration list for PBXNativeTarget "SignInAnalyticsTests_ios" */; + buildConfigurationList = 0CD743AB23C3EC8000FA0EC5 /* Build configuration list for PBXNativeTarget "OctagonTrust" */; buildPhases = ( - 0CF406112072E3E3003D6A7F /* Sources */, - 0CF406342072E3E3003D6A7F /* Frameworks */, - 0CF4064A2072E3E3003D6A7F /* Embed OCMock */, + 0CD743A123C3EC8000FA0EC5 /* Headers */, + 0CD743A223C3EC8000FA0EC5 /* Sources */, + 0CD743A323C3EC8000FA0EC5 /* Frameworks */, ); buildRules = ( ); dependencies = ( - 0C5663EE20BE2E1A0035F362 /* PBXTargetDependency */, - 0C3E2EA92073F5C400F5B95B /* PBXTargetDependency */, ); - name = SignInAnalyticsTests_ios; - productName = CKKSTests; - productReference = 0CF406502072E3E3003D6A7F /* SignInAnalyticsTests_ios.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; + name = OctagonTrust; + productName = Clique; + productReference = 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */; + productType = "com.apple.product-type.framework"; }; 225394AC1E3080A600D3CD9B /* security_codesigning_ios */ = { isa = PBXNativeTarget; @@ -28025,6 +27930,40 @@ productReference = 3DD1FFD0201FDB1D0086D049 /* SecureTransport_ios_tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 3E4D49B32531170600B124B3 /* secsecstaticcodeapitest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E4D49B92531170600B124B3 /* Build configuration list for PBXNativeTarget "secsecstaticcodeapitest" */; + buildPhases = ( + 3E4D49B42531170600B124B3 /* Sources */, + 3E4D49B62531170600B124B3 /* Frameworks */, + A695677C2581B46E00BDF83F /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + A69560602580540F00BDF83F /* PBXTargetDependency */, + ); + name = secsecstaticcodeapitest; + productName = secbackupntest; + productReference = 3E4D49BC2531170600B124B3 /* secsecstaticcodeapitest */; + productType = "com.apple.product-type.tool"; + }; + 3E88360824F068EF00E9F4D6 /* secseccodeapitest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E88360E24F068EF00E9F4D6 /* Build configuration list for PBXNativeTarget "secseccodeapitest" */; + buildPhases = ( + 3E88360924F068EF00E9F4D6 /* Sources */, + 3E88360B24F068EF00E9F4D6 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = secseccodeapitest; + productName = secbackupntest; + productReference = 3E88361124F068EF00E9F4D6 /* secseccodeapitest */; + productType = "com.apple.product-type.tool"; + }; 4381690B1B4EDCBD00C54D58 /* SOSCCAuthPlugin */ = { isa = PBXNativeTarget; buildConfigurationList = 438169381B4EDCBD00C54D58 /* Build configuration list for PBXNativeTarget "SOSCCAuthPlugin" */; @@ -28102,29 +28041,29 @@ productReference = 4718AEE2205B39C40068EC3F /* libsecurityd_bridge.a */; productType = "com.apple.product-type.library.static"; }; - 4727FBB61F9918580003AE36 /* secdxctests_ios */ = { + 4727FBB61F9918580003AE36 /* secdxctests */ = { isa = PBXNativeTarget; - buildConfigurationList = 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests_ios" */; + buildConfigurationList = 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests" */; buildPhases = ( 4727FBB31F9918580003AE36 /* Sources */, 4727FBB41F9918580003AE36 /* Frameworks */, - 090585D120AEF9FE00BB7490 /* Install OCMock framework */, ); buildRules = ( ); dependencies = ( + 6CE2AEAB22B2C1BE00C96AE7 /* PBXTargetDependency */, + 6CC638EB226695C300E5DB0B /* PBXTargetDependency */, + 6CC638ED226695C300E5DB0B /* PBXTargetDependency */, D4BFFD692227B30700163B4B /* PBXTargetDependency */, EB74CBD622077CC600F1BBAD /* PBXTargetDependency */, - EBD7DF8121FF475B0089F2DF /* PBXTargetDependency */, - EBD7DF8321FF475B0089F2DF /* PBXTargetDependency */, 47A6FC6A206B461700BD6C54 /* PBXTargetDependency */, 47DE88D91FA7ADBB00DD3254 /* PBXTargetDependency */, 47DE88D71FA7ADAC00DD3254 /* PBXTargetDependency */, 47DE88CE1FA7AD6200DD3254 /* PBXTargetDependency */, ); - name = secdxctests_ios; + name = secdxctests; productName = secdxctests; - productReference = 4727FBB71F9918580003AE36 /* secdxctests_ios.xctest */; + productReference = 4727FBB71F9918580003AE36 /* secdxctests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 47702B1D1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */ = { @@ -28178,31 +28117,6 @@ productReference = 4771D972209A755800BA9772 /* KeychainDataclassOwner.bundle */; productType = "com.apple.product-type.bundle"; }; - 478D426C1FD72A8100CAB645 /* secdxctests_mac */ = { - isa = PBXNativeTarget; - buildConfigurationList = 478D42991FD72A8100CAB645 /* Build configuration list for PBXNativeTarget "secdxctests_mac" */; - buildPhases = ( - 478D42751FD72A8100CAB645 /* Sources */, - 478D427D1FD72A8100CAB645 /* Frameworks */, - 090585D020AEF9D300BB7490 /* Install OCMock framework */, - ); - buildRules = ( - ); - dependencies = ( - DC69A5872165298500512BD6 /* PBXTargetDependency */, - 47A6FC6C206B462400BD6C54 /* PBXTargetDependency */, - DC34CD3620326C3B00302481 /* PBXTargetDependency */, - DC34CD3420326C3100302481 /* PBXTargetDependency */, - DC34CD2D20326C2C00302481 /* PBXTargetDependency */, - 478D426D1FD72A8100CAB645 /* PBXTargetDependency */, - 478D426F1FD72A8100CAB645 /* PBXTargetDependency */, - 478D42731FD72A8100CAB645 /* PBXTargetDependency */, - ); - name = secdxctests_mac; - productName = secdxctests; - productReference = 478D429C1FD72A8100CAB645 /* secdxctests_mac.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; 47C2F1822059CB680062DE30 /* KeychainResources */ = { isa = PBXNativeTarget; buildConfigurationList = 47C2F1872059CB690062DE30 /* Build configuration list for PBXNativeTarget "KeychainResources" */; @@ -28296,10 +28210,6 @@ 4C711D6313AFCD0900FE865D /* Sources */, 4C711D6513AFCD0900FE865D /* Frameworks */, 4C711D7213AFCD0900FE865D /* Resources */, - 4C50AD3414106A2900EE92DE /* Copy DigiNotar Resources */, - 4C50AD3514106A2B00EE92DE /* Copy DigiNotar-Entrust Resources */, - 4C50AD3614106A2C00EE92DE /* Copy DigiNotar-ok Resources */, - 79679E2B146202BC00CF997F /* Copy DigicertMalaysia Resources */, ); buildRules = ( ); @@ -28473,24 +28383,43 @@ productReference = 5EBE247A1B00CCAE0007DB0E /* secacltests */; productType = "com.apple.product-type.tool"; }; + 6C2045E92424BA7E00F9461D /* KeychainStasher */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6C2045EE2424BA7F00F9461D /* Build configuration list for PBXNativeTarget "KeychainStasher" */; + buildPhases = ( + 6C2045E62424BA7E00F9461D /* Sources */, + 6C2045E72424BA7E00F9461D /* Frameworks */, + 6C2045F32424BBB900F9461D /* Install Sandbox Profile */, + 6C2045FA2424BCC300F9461D /* Install LaunchAgent plist */, + ); + buildRules = ( + ); + dependencies = ( + 6CA9690D24ACC5C100C08B5E /* PBXTargetDependency */, + ); + name = KeychainStasher; + productName = KeychainStasher; + productReference = 6C2045EA2424BA7E00F9461D /* KeychainStasher */; + productType = "com.apple.product-type.tool"; + }; 6C39234421F13E4D00D018AD /* SecDbBackupTests */ = { isa = PBXNativeTarget; buildConfigurationList = 6C39237621F13E4D00D018AD /* Build configuration list for PBXNativeTarget "SecDbBackupTests" */; buildPhases = ( 6C39234D21F13E4D00D018AD /* Sources */, 6C39235A21F13E4D00D018AD /* Frameworks */, - 6C7E8F1F21F7BE64008A2D56 /* Copy BATS Test Discovery Plist */, - 6C7E8F2121F7BE7F008A2D56 /* Chown BATS Test Discovery Plist */, ); buildRules = ( ); dependencies = ( - 6C8FF4B6224C1A9800E5C812 /* PBXTargetDependency */, + 6CC638E7226695B900E5DB0B /* PBXTargetDependency */, + 6CC638E9226695B900E5DB0B /* PBXTargetDependency */, D4BFFD622227578900163B4B /* PBXTargetDependency */, D4BFFD602227576E00163B4B /* PBXTargetDependency */, D4BFFD5E2227575C00163B4B /* PBXTargetDependency */, D4BFFD5C2227574C00163B4B /* PBXTargetDependency */, D4BFFD592227574200163B4B /* PBXTargetDependency */, + 6CE2AEAD22B2C1C300C96AE7 /* PBXTargetDependency */, ); name = SecDbBackupTests; productName = secdxctests; @@ -28503,7 +28432,6 @@ buildPhases = ( 6C46057A1F882B9B001421B6 /* Sources */, 6C46059B1F882B9B001421B6 /* Frameworks */, - 6C4F981E2075831300A3C5AB /* CopyFiles */, ); buildRules = ( ); @@ -28515,55 +28443,43 @@ productReference = 6C4605B81F882B9B001421B6 /* KeychainAnalyticsTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 6C98082C1E788AEB00E70590 /* CKKSCloudKitTests_mac */ = { + 6C7BE2A923C3DD64003BB2CA /* securitytool_bridge */ = { isa = PBXNativeTarget; - buildConfigurationList = 6C98085E1E788AEB00E70590 /* Build configuration list for PBXNativeTarget "CKKSCloudKitTests_mac" */; + buildConfigurationList = 6C7BE2E423C3DD64003BB2CA /* Build configuration list for PBXNativeTarget "securitytool_bridge" */; buildPhases = ( - 6C98083D1E788AEB00E70590 /* Sources */, - 6C9808481E788AEB00E70590 /* Frameworks */, - 6C98085D1E788AEB00E70590 /* Resources */, + 6C7BE2B623C3DD64003BB2CA /* Sources */, + 6C7BE2D223C3DD64003BB2CA /* Frameworks */, ); buildRules = ( ); dependencies = ( - DCD6BF5421E919610015F7A8 /* PBXTargetDependency */, - DC93C4C9214713DC008F8362 /* PBXTargetDependency */, - 6C98082F1E788AEB00E70590 /* PBXTargetDependency */, - 6C9808311E788AEB00E70590 /* PBXTargetDependency */, - 6C9808351E788AEB00E70590 /* PBXTargetDependency */, - 6C9808371E788AEB00E70590 /* PBXTargetDependency */, - 6C9808391E788AEB00E70590 /* PBXTargetDependency */, - 6C9808A01E788B9400E70590 /* PBXTargetDependency */, + 6C16258423C4FFD40086A0FF /* PBXTargetDependency */, + 6C16258623C4FFD40086A0FF /* PBXTargetDependency */, + 6C16258123C4FFC40086A0FF /* PBXTargetDependency */, + 6C14CA0423C4F6830097B572 /* PBXTargetDependency */, + 6C7BE2AA23C3DD64003BB2CA /* PBXTargetDependency */, + 6C7BE2AC23C3DD64003BB2CA /* PBXTargetDependency */, ); - name = CKKSCloudKitTests_mac; - productName = CKKSTests; - productReference = 6C9808611E788AEB00E70590 /* CKKSCloudKitTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; + name = securitytool_bridge; + productName = security; + productReference = 6C7BE2E723C3DD64003BB2CA /* securitytool_bridge */; + productType = "com.apple.product-type.tool"; }; - 6C9808681E788AFD00E70590 /* CKKSCloudKitTests_ios */ = { + 6C963280242A279B00C53CE2 /* stashtester */ = { isa = PBXNativeTarget; - buildConfigurationList = 6C98089A1E788AFD00E70590 /* Build configuration list for PBXNativeTarget "CKKSCloudKitTests_ios" */; + buildConfigurationList = 6C963288242A279B00C53CE2 /* Build configuration list for PBXNativeTarget "stashtester" */; buildPhases = ( - 6C9808791E788AFD00E70590 /* Sources */, - 6C9808841E788AFD00E70590 /* Frameworks */, - 6C9808991E788AFD00E70590 /* Resources */, + 6C96327D242A279B00C53CE2 /* Sources */, + 6C96327E242A279B00C53CE2 /* Frameworks */, ); buildRules = ( ); dependencies = ( - DCD6BF5621E9196E0015F7A8 /* PBXTargetDependency */, - DC93C4CD21471401008F8362 /* PBXTargetDependency */, - 6C9808A41E788CB100E70590 /* PBXTargetDependency */, - 6C98086B1E788AFD00E70590 /* PBXTargetDependency */, - 6C98086D1E788AFD00E70590 /* PBXTargetDependency */, - 6C9808711E788AFD00E70590 /* PBXTargetDependency */, - 6C9808731E788AFD00E70590 /* PBXTargetDependency */, - 6C9808751E788AFD00E70590 /* PBXTargetDependency */, ); - name = CKKSCloudKitTests_ios; - productName = CKKSTests; - productReference = 6C98089D1E788AFD00E70590 /* CKKSCloudKitTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; + name = stashtester; + productName = stashtester; + productReference = 6C963281242A279B00C53CE2 /* stashtester */; + productType = "com.apple.product-type.tool"; }; 6C9AA79D1F7C1D8F00D08296 /* supdctl */ = { isa = PBXNativeTarget; @@ -28590,6 +28506,7 @@ 6CAA8D1D1F842FB3007B6E03 /* Frameworks */, 6CAA8D1E1F842FB3007B6E03 /* Copy Manpage */, 6CAA8D361F84317F007B6E03 /* Install launchd plist */, + D42D044424734050004E7AA2 /* Install sandbox profile for macOS */, ); buildRules = ( ); @@ -28617,9 +28534,9 @@ productReference = 6CCDF7841E3C25FA003F2555 /* KeychainEntitledTestRunner */; productType = "com.apple.product-type.tool"; }; - 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */ = { + 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp */ = { isa = PBXNativeTarget; - buildConfigurationList = 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp_mac" */; + buildConfigurationList = 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp" */; buildPhases = ( 6CF4A0B01E45488B00ECD7B5 /* Sources */, 6CF4A0B11E45488B00ECD7B5 /* Frameworks */, @@ -28629,28 +28546,11 @@ ); dependencies = ( ); - name = KeychainEntitledTestApp_mac; + name = KeychainEntitledTestApp; productName = KeychainEntitledTestApp_mac; productReference = 6CF4A0B41E45488B00ECD7B5 /* KeychainEntitledTestApp.app */; productType = "com.apple.product-type.application"; }; - 6CF4A0DF1E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6CF4A0F41E4549F300ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp_ios" */; - buildPhases = ( - 6CF4A0DC1E4549F200ECD7B5 /* Sources */, - 6CF4A0DD1E4549F200ECD7B5 /* Frameworks */, - 6CF4A0DE1E4549F200ECD7B5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = KeychainEntitledTestApp_ios; - productName = KeychainEntitledTestApp_ios; - productReference = 6CF4A0E01E4549F200ECD7B5 /* KeychainEntitledTestApp.app */; - productType = "com.apple.product-type.application"; - }; 790851B50CA9859F0083CC4D /* securityd_ios */ = { isa = PBXNativeTarget; buildConfigurationList = 790851C90CA985C10083CC4D /* Build configuration list for PBXNativeTarget "securityd_ios" */; @@ -28759,6 +28659,7 @@ BEAA0029202A832500E51F45 /* Resources */, BEAA0028202A832500E51F45 /* Frameworks */, EB3FB9A3231C125400DF52EA /* Copy Logging Files */, + DC2C884D245B4B3E0040CBEB /* Copy Sandbox Profile (macOS only) */, ); buildRules = ( ); @@ -28871,6 +28772,7 @@ D41257CC1E9410A300781F23 /* Frameworks */, D41257CD1E9410A300781F23 /* Copy LaunchDaemon */, D442AD70215C39100050B50F /* Install Apple Corporate Roots */, + D404E2CB255CA5AA0040190B /* Create DataVault Directories */, ); buildRules = ( ); @@ -28902,6 +28804,25 @@ productReference = D42C839821159146008D3D83 /* libsecurity_cms.a */; productType = "com.apple.product-type.library.static"; }; + D445B30B258C07FC0019858E /* trustdFileHelper */ = { + isa = PBXNativeTarget; + buildConfigurationList = D445B310258C07FD0019858E /* Build configuration list for PBXNativeTarget "trustdFileHelper" */; + buildPhases = ( + D445B308258C07FC0019858E /* Sources */, + D445B309258C07FC0019858E /* Frameworks */, + D445B30A258C07FC0019858E /* Install man8 page */, + D445BA12258C110A0019858E /* Copy Sandbox */, + D445BAF3258C11370019858E /* Copy LaunchDaemon Files */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = trustdFileHelper; + productName = trustdFileHelper; + productReference = D445B30C258C07FC0019858E /* trustdFileHelper */; + productType = "com.apple.product-type.tool"; + }; D44D1F652115893000E76E1A /* CMS */ = { isa = PBXNativeTarget; buildConfigurationList = D44D1F6E2115893000E76E1A /* Build configuration list for PBXNativeTarget "CMS" */; @@ -28981,6 +28902,7 @@ D4707A0221136E69005BCFDA /* Frameworks */, D4707A0321136E69005BCFDA /* Resources */, D4428B432122718400EB8448 /* Generate BATS Plist */, + D428337D24E1D0B10068B2F5 /* Remove Name Constraints Resources from watchOS */, ); buildRules = ( ); @@ -29613,8 +29535,6 @@ buildPhases = ( DC3502B11E0208BE00BC0587 /* Sources */, DC3502B21E0208BE00BC0587 /* Frameworks */, - DC9A2C791EB40A64008FAC27 /* Embed OCMock */, - DC7162D41EB4154D000D2BB5 /* Copy BATS Test Discovery Plist */, DC7162D61EB4157D000D2BB5 /* ShellScript */, ); buildRules = ( @@ -30396,10 +30316,6 @@ DCE4E74C1D7A43B500AFB96E /* Sources */, DCE4E7501D7A43B500AFB96E /* Frameworks */, DCE4E76B1D7A43B500AFB96E /* Resources */, - DCE4E7711D7A43B500AFB96E /* Copy DigiNotar Resources */, - DCE4E7841D7A43B500AFB96E /* Copy DigiNotar-Entrust Resources */, - DCE4E7981D7A43B500AFB96E /* Copy DigiNotar-ok Resources */, - DCE4E7A81D7A43B500AFB96E /* Copy DigiCertMalaysia Resources */, ); buildRules = ( ); @@ -30475,6 +30391,8 @@ DCE4E8541D7A57AE00AFB96E /* Copy LaunchDaemon Files */, BEB463AD1E64F3C1008EB77E /* Copy Sandbox */, D4ADA3111E2B209C0031CEA3 /* Install man8 page */, + D459364124BFBA700066FB43 /* Install Apple Corporate Roots */, + D404E2CC255CA89D0040190B /* Create DataVault Directories */, ); buildRules = ( ); @@ -30748,10 +30666,6 @@ E710C73E1331946400F85568 /* Sources */, E710C73F1331946400F85568 /* Frameworks */, E710C7401331946400F85568 /* Resources */, - 4C50AD081410673800EE92DE /* Copy DigiNotar Resources */, - 4C50AD091410675400EE92DE /* Copy DigiNotar-Entrust Resources */, - 4C50AD0A1410676300EE92DE /* Copy DigiNotar-ok Resources */, - 79679E231462023800CF997F /* Copy DigiCertMalaysia Resources */, ); buildRules = ( ); @@ -30806,7 +30720,6 @@ buildRules = ( ); dependencies = ( - DC65E7221D8CB27900152EF0 /* PBXTargetDependency */, ); name = KeychainCircle; productName = KeychainCircle; @@ -30959,7 +30872,6 @@ buildPhases = ( EB49B2AA202D877F003F34A0 /* Sources */, EB49B2AB202D877F003F34A0 /* Frameworks */, - EBC73F4B209A0C3400AE3350 /* Install OCMock framework */, ); buildRules = ( ); @@ -31070,6 +30982,23 @@ productReference = EBA9AA861CE30E58004E2B68 /* secitemnotifications */; productType = "com.apple.product-type.tool"; }; + EBAFC9AB2551C26F0034B78D /* SecLegacyCodeRegressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = EBAFC9B32551C2710034B78D /* Build configuration list for PBXNativeTarget "SecLegacyCodeRegressions" */; + buildPhases = ( + EBAFC9A82551C26F0034B78D /* Sources */, + EBAFC9A92551C26F0034B78D /* Frameworks */, + EBAFC9AA2551C26F0034B78D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SecLegacyCodeRegressions; + productName = legacyCodeRegressions; + productReference = EBAFC9AC2551C2700034B78D /* SecLegacyCodeRegressions.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; EBB839A41E29665D00853BAC /* secfuzzer */ = { isa = PBXNativeTarget; buildConfigurationList = EBB839A91E29665E00853BAC /* Build configuration list for PBXNativeTarget "secfuzzer" */; @@ -31093,7 +31022,6 @@ buildPhases = ( EBB851E822F7912400424FD0 /* Sources */, EBB851E922F7912400424FD0 /* Frameworks */, - EB0F4A2B22F7D3BD009E855B /* Embedd OCMock */, ); buildRules = ( ); @@ -31180,9 +31108,12 @@ 4C35DB69094F906D002917C4 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1000; - LastUpgradeCheck = 1000; + LastSwiftUpdateCheck = 1200; + LastUpgradeCheck = 1200; TargetAttributes = { + 0CD743A523C3EC8000FA0EC5 = { + CreatedOnToolsVersion = 12.0; + }; 4381690B1B4EDCBD00C54D58 = { CreatedOnToolsVersion = 7.0; }; @@ -31206,9 +31137,6 @@ CreatedOnToolsVersion = 10.0; ProvisioningStyle = Automatic; }; - 478D426C1FD72A8100CAB645 = { - ProvisioningStyle = Automatic; - }; 47C2F1822059CB680062DE30 = { CreatedOnToolsVersion = 10.0; ProvisioningStyle = Automatic; @@ -31222,14 +31150,14 @@ 5EBE24791B00CCAE0007DB0E = { CreatedOnToolsVersion = 7.0; }; + 6C2045E92424BA7E00F9461D = { + CreatedOnToolsVersion = 12.0; + }; 6C39234421F13E4D00D018AD = { - ProvisioningStyle = Manual; + ProvisioningStyle = Automatic; }; - 6C98082C1E788AEB00E70590 = { - TestTargetID = 6CF4A0B31E45488B00ECD7B5; - }; - 6C9808681E788AFD00E70590 = { - TestTargetID = 6CF4A0DF1E4549F200ECD7B5; + 6C963280242A279B00C53CE2 = { + CreatedOnToolsVersion = 12.0; }; 6C9AA79D1F7C1D8F00D08296 = { CreatedOnToolsVersion = 9.0; @@ -31247,10 +31175,6 @@ CreatedOnToolsVersion = 8.3; ProvisioningStyle = Automatic; }; - 6CF4A0DF1E4549F200ECD7B5 = { - CreatedOnToolsVersion = 8.3; - ProvisioningStyle = Automatic; - }; BEAA002A202A832500E51F45 = { CreatedOnToolsVersion = 9.3; LastSwiftMigration = 0930; @@ -31287,6 +31211,9 @@ CreatedOnToolsVersion = 10.0; ProvisioningStyle = Automatic; }; + D445B30B258C07FC0019858E = { + CreatedOnToolsVersion = 12.4; + }; D44D1F652115893000E76E1A = { CreatedOnToolsVersion = 10.0; ProvisioningStyle = Automatic; @@ -31485,6 +31412,7 @@ }; DCF216D621ADD5B10029CCC1 = { CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1200; ProvisioningStyle = Automatic; }; DCF7889C1D88CB5200E694BB = { @@ -31553,6 +31481,9 @@ EB9C1DAE1BDFD4DE00F89272 = { CreatedOnToolsVersion = 7.1; }; + EBAFC9AB2551C26F0034B78D = { + CreatedOnToolsVersion = 12.0; + }; EBB839A41E29665D00853BAC = { CreatedOnToolsVersion = 8.3; ProvisioningStyle = Automatic; @@ -31568,15 +31499,14 @@ }; buildConfigurationList = 4C35DB6A094F906D002917C4 /* Build configuration list for PBXProject "Security" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, - Japanese, - French, - German, en, Base, + de, + fr, + ja, ); mainGroup = 4C35DB67094F906D002917C4; productRefGroup = 4C35DC36094F9120002917C4 /* Products */; @@ -31628,6 +31558,7 @@ DC1789031D77980500B50D50 /* Security_osx */, E7D847C41C6BE9710025BB44 /* KeychainCircle */, BEF88C271EAFFC3F00357577 /* TrustedPeers */, + 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */, DC8E04911D7F6CED006D80EB /* ======= Daemons ========= */, DCE4E8931D7F34F600AFB96E /* authd */, DCE4E7F51D7A4DA800AFB96E /* secd */, @@ -31644,6 +31575,8 @@ DC0BC5631D8B6E3D00070CB0 /* XPCTimeStampingService */, BEAA002A202A832500E51F45 /* TrustedPeersHelper */, DA41FE0D2241ADC000838FB3 /* otpaird */, + 6C2045E92424BA7E00F9461D /* KeychainStasher */, + D445B30B258C07FC0019858E /* trustdFileHelper */, DC8E04B11D7F6EC9006D80EB /* ======= Libraries ========= */, DCDA5E4F2124B9C5009B11B2 /* aks_support */, DC36895D21235F42003A3735 /* aks_mock */, @@ -31708,6 +31641,7 @@ DC0067921D87876F005AF8DB /* securityd_server_macos */, DC0067C51D878898005AF8DB /* securityd_ucspc */, DC8E04951D7F6D80006D80EB /* ========= CLI =========== */, + 6C7BE2A923C3DD64003BB2CA /* securitytool_bridge */, 4CB740A20A47567C00D641BB /* securitytool_ios */, DC5ABDC41D832DAB00CF422C /* securitytool_macos */, DCE4E68A1D7A37FA00AFB96E /* security2tool_macos */, @@ -31733,9 +31667,8 @@ DCE4E7311D7A43B500AFB96E /* SecurityTestsOSX */, DC3502B41E0208BE00BC0587 /* CKKSTests */, 0C85DFD11FB38BB6000343A7 /* OTTests */, + 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */, DC99B85B20EACA470065B73B /* OctagonTests */, - 0CF406042072E3E3003D6A7F /* SignInAnalyticsTests_ios */, - 0C9AEEAB20783FBB00BF6237 /* SignInAnalyticsTests_osx */, DC610AAD1D7910C3002223DE /* gk_reset_check_macos */, DC610A551D78F9D2002223DE /* codesign_tests_macos */, DC610A461D78F48F002223DE /* SecTaskTest_macos */, @@ -31751,6 +31684,8 @@ EB433A201CC3243600A7EACE /* secitemstresstest */, EBA9AA7D1CE30E58004E2B68 /* secitemnotifications */, DAE40BC520CF3E46002D5674 /* secitemcanarytest */, + 3E88360824F068EF00E9F4D6 /* secseccodeapitest */, + 3E4D49B32531170600B124B3 /* secsecstaticcodeapitest */, DCE4E7CB1D7A4AED00AFB96E /* sectests_macos */, 470415CE1E5E14B5001F3D95 /* seckeychainnetworkextensionstest */, 47702B1D1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */, @@ -31763,15 +31698,11 @@ 4CE5A54C09C796E100D27A3F /* sslViewer */, DC0BC5C51D8B72E700070CB0 /* test-checkpw */, DC0BC5D51D8B73B000070CB0 /* perf-checkpw */, - 6C98082C1E788AEB00E70590 /* CKKSCloudKitTests_mac */, - 6C9808681E788AFD00E70590 /* CKKSCloudKitTests_ios */, - 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */, - 6CF4A0DF1E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */, + 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp */, 6CCDF7831E3C25FA003F2555 /* KeychainEntitledTestRunner */, 6C46056B1F882B9B001421B6 /* KeychainAnalyticsTests */, 47C51B831EEA657D0032D9E5 /* SecurityUnitTests */, - 4727FBB61F9918580003AE36 /* secdxctests_ios */, - 478D426C1FD72A8100CAB645 /* secdxctests_mac */, + 4727FBB61F9918580003AE36 /* secdxctests */, EB49B2AD202D877F003F34A0 /* secdmockaks */, 6C39234421F13E4D00D018AD /* SecDbBackupTests */, 3DD1FEF5201C07F30086D049 /* SecureTransportTests_macos */, @@ -31783,6 +31714,8 @@ D458C4E0214E1DE00043D982 /* TrustTestsRunner_ios */, D4707A0421136E69005BCFDA /* TrustTests_ios */, D453A4A42122236D00850A26 /* TrustTests_macos */, + 6C963280242A279B00C53CE2 /* stashtester */, + EBAFC9AB2551C26F0034B78D /* SecLegacyCodeRegressions */, DC5AC1351D835D9700CF422C /* ===== Source Gen ===== */, DC008B451D90CE53004002A3 /* securityd_macos_mig */, DC6BC26C1D90CFEF00DD57B3 /* securityd_macos_startup */, @@ -31825,6 +31758,7 @@ EB7E90F12193F90700B1FA21 /* Build C2 Metrics */, 3D58392D21890FFB000ACA44 /* SecExperimentTests */, 5A442F81233C330F00918373 /* experimentTool */, + 0CA378E123876DD100090B7E /* reset_account */, ); }; /* End PBXProject section */ @@ -31861,6 +31795,13 @@ /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ + 0CCC227423F357EE00E1FCD0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4381690A1B4EDCBD00C54D58 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -31896,6 +31837,7 @@ 4C198F220ACDB4BF00AAB142 /* Certificate.strings in Resources */, 4C198F230ACDB4BF00AAB142 /* OID.strings in Resources */, D479F6E21F980FAB00388D28 /* Trust.strings in Resources */, + 6C5D62A6221B6E3F00AF79DC /* secdxctests-entitlements.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -31903,9 +31845,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4C88D8D262E667C0006FFB1 /* si-27-cms-parse in Resources */, 52A23EDD161DEC3F00E271E0 /* Default-568h@2x.png in Resources */, - D4D886E91CEBDD2A00DC7583 /* nist-certs in Resources */, - BE9B8B4B202BB4D10081EF87 /* si-88-sectrust-valid-data in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -31925,20 +31866,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6C98085D1E788AEB00E70590 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6C9808991E788AFD00E70590 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 6CF4A0B21E45488B00ECD7B5 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -31946,18 +31873,10 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6CF4A0DE1E4549F200ECD7B5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; BE197F2419116FD100BA91D1 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - BE197F61191173F200BA91D1 /* entitlements.plist in Resources */, BE197F2C19116FD100BA91D1 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -31994,13 +31913,18 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4C88D91262E67F80006FFB1 /* si-87-sectrust-name-constraints in Resources */, + D4C88D90262E67F30006FFB1 /* si-20-sectrust-policies-data in Resources */, + D41324132549E55C0062995A /* DigiNotar in Resources */, + D413225D2549E4AF0062995A /* DigicertMalaysia in Resources */, + D478A4572532762E00283EB9 /* TestTrustdInitialization-data in Resources */, D4B2966B22DBFDD300DCF250 /* TestCopyProperties_ios-data in Resources */, D4D92DA9227890500009A7CF /* nist-certs in Resources */, + D4231149237261F8000E470A /* SMIMEPolicyTests-data in Resources */, D4056A2022712D750026E24E /* ssl-policy-certs in Resources */, D4AC8BEF213212A7006E9871 /* si-18-certificate-parse in Resources */, - D458C51A214E2CC80043D982 /* si-20-sectrust-policies-data in Resources */, D453A4BC2122236D00850A26 /* si-82-sectrust-ct-data in Resources */, - D4FD4226217D7C41002B7EE2 /* si-87-sectrust-name-constraints in Resources */, + D477CB79237E484300C02355 /* si-88-sectrust-valid-data in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32010,7 +31934,6 @@ files = ( D458C51F214E2E0C0043D982 /* Main.storyboard in Resources */, D458C51C214E2DEB0043D982 /* Assets.xcassets in Resources */, - D458C51D214E2DEB0043D982 /* Base.lproj in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32018,13 +31941,18 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4C88D8F262E67DF0006FFB1 /* si-87-sectrust-name-constraints in Resources */, + D4C88D8E262E67D90006FFB1 /* si-20-sectrust-policies-data in Resources */, + D41324EE2549E56F0062995A /* DigiNotar in Resources */, + D41321822549E49B0062995A /* DigicertMalaysia in Resources */, D4B2966A22DBFDC700DCF250 /* TestCopyProperties_ios-data in Resources */, D4D92DA8227890500009A7CF /* nist-certs in Resources */, + D4231148237261F8000E470A /* SMIMEPolicyTests-data in Resources */, D4056A1F22712D750026E24E /* ssl-policy-certs in Resources */, D4AC8BEE21321291006E9871 /* si-18-certificate-parse in Resources */, - D458C517214E2C690043D982 /* si-20-sectrust-policies-data in Resources */, + D407292A2531387F0084D96B /* TestTrustdInitialization-data in Resources */, D4A0F8C2211E6A2F00443CA1 /* si-82-sectrust-ct-data in Resources */, - D4FD4227217D7C4F002B7EE2 /* si-87-sectrust-name-constraints in Resources */, + D477CB78237E482800C02355 /* si-88-sectrust-valid-data in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32064,7 +31992,6 @@ DC178A471D77A1F600B50D50 /* InfoPlist.strings in Resources */, DC178A241D77A1E700B50D50 /* cspdl_common.mdsinfo in Resources */, DC178A2B1D77A1E700B50D50 /* cl_primary.mdsinfo in Resources */, - DC178A451D77A1F600B50D50 /* framework.sb in Resources */, DC178A2D1D77A1E700B50D50 /* tp_policyOids.mdsinfo in Resources */, DC178A231D77A1E700B50D50 /* csp_primary.mdsinfo in Resources */, DC178A251D77A1E700B50D50 /* cspdl_csp_capabilities.mdsinfo in Resources */, @@ -32118,16 +32045,13 @@ DC99B88E20EACA470065B73B /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; - files = ( - ); runOnlyForDeploymentPostprocessing = 0; }; DCE4E76B1D7A43B500AFB96E /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - DCE4E76D1D7A43B500AFB96E /* nist-certs in Resources */, - BE9B8B4D202BB4F30081EF87 /* si-88-sectrust-valid-data in Resources */, + D4C88D8C262E666B0006FFB1 /* si-27-cms-parse in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32171,9 +32095,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4C88D8B262E66420006FFB1 /* si-27-cms-parse in Resources */, 52A23EDC161DEC3800E271E0 /* Default-568h@2x.png in Resources */, - D4D886EA1CEBDE0800DC7583 /* nist-certs in Resources */, - BE9B8B4C202BB4E30081EF87 /* si-88-sectrust-valid-data in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32215,37 +32138,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + EBAFC9AA2551C26F0034B78D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 090585D020AEF9D300BB7490 /* Install OCMock framework */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 8; - files = ( - ); - inputPaths = ( - ); - name = "Install OCMock framework"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 1; - shellPath = /bin/sh; - shellScript = "sh xcscripts/install-test-framework.sh OCMock.framework\n"; - }; - 090585D120AEF9FE00BB7490 /* Install OCMock framework */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 8; - files = ( - ); - inputPaths = ( - ); - name = "Install OCMock framework"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 1; - shellPath = /bin/sh; - shellScript = "sh xcscripts/install-test-framework.sh OCMock.framework\n"; - }; 0C85DFFF1FB38BB6000343A7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; @@ -32285,24 +32187,6 @@ shellPath = /bin/sh; shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist"; }; - 6C7E8F2121F7BE7F008A2D56 /* Chown BATS Test Discovery Plist */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 8; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = "Chown BATS Test Discovery Plist"; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 1; - shellPath = /bin/sh; - shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\n chown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n"; - }; 6CAA8D361F84317F007B6E03 /* Install launchd plist */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; @@ -32334,6 +32218,80 @@ shellPath = /bin/sh; shellScript = "PLIST_FILE_NAME=com.apple.security.cloudkeychainproxy3\nFILE_TO_COPY=${PROJECT_DIR}/KVSKeychainSyncingProxy/${PLIST_FILE_NAME}.ios.plist\n\nif [ ${PLATFORM_NAME} = \"macosx\" ]\nthen\nFILE_TO_COPY=${PROJECT_DIR}/KVSKeychainSyncingProxy/${PLIST_FILE_NAME}.osx.plist\nfi\n\ncp ${FILE_TO_COPY} ${INSTALL_ROOT}/${INSTALL_DAEMON_AGENT_DIR}/${PLIST_FILE_NAME}.plist\n"; }; + D404E2CB255CA5AA0040190B /* Create DataVault Directories */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Create DataVault Directories"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "DATA_VAULT_DIR=${DSTROOT}/private/var/protected\nTRUSTD_PUBLIC_DIR=${DATA_VAULT_DIR}/trustd\nTRUSTD_PRIVATE_DIR=${TRUSTD_PUBLIC_DIR}/private\n\nmkdir -p ${DATA_VAULT_DIR}\nchown -f root:wheel ${DATA_VAULT_DIR}\nchmod 755 ${DATA_VAULT_DIR}\n\n# TRUSTD_PUBLIC_DIR is owned by _trustd (uid 282)\nmkdir -p ${TRUSTD_PUBLIC_DIR}\nchown -f 282:wheel ${TRUSTD_PUBLIC_DIR}\nchmod 755 ${TRUSTD_PUBLIC_DIR}\n"; + }; + D404E2CC255CA89D0040190B /* Create DataVault Directories */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Create DataVault Directories"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "DATA_VAULT_DIR=${DSTROOT}/private/var/protected\nTRUSTD_PUBLIC_DIR=${DATA_VAULT_DIR}/trustd\nTRUSTD_PRIVATE_DIR=${TRUSTD_PUBLIC_DIR}/private\n\nmkdir -p ${DATA_VAULT_DIR}\nchown -f root:wheel ${DATA_VAULT_DIR}\nchmod 755 ${DATA_VAULT_DIR}\n\n# TRUSTD_PUBLIC_DIR is owned by _trustd (uid 282)\nmkdir -p ${TRUSTD_PUBLIC_DIR}\nchown -f 282:wheel ${TRUSTD_PUBLIC_DIR}\nchmod 755 ${TRUSTD_PUBLIC_DIR}\n\n# Note: PRIVATE_TRUSTD_DIR is intentionally installed world-writeable so any\n# user instance of trustd may write to it. This is only permissible because\n# access to this directory is restricted by entitlement.\nmkdir -p ${TRUSTD_PRIVATE_DIR}\nchown -f root:wheel ${TRUSTD_PRIVATE_DIR}\nchmod 777 ${TRUSTD_PRIVATE_DIR}\n"; + }; + D428337D24E1D0B10068B2F5 /* Remove Name Constraints Resources from watchOS */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Remove Name Constraints Resources from watchOS"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "# see \nif [ \"${PLATFORM_NAME}\" == \"watchos\" ]; then\n rm -rf \"$DSTROOT/AppleInternal/XCTests/com.apple.security/TrustTests.xctest/si-87-sectrust-name-constraints\"\nfi\n"; + }; + D42D044424734050004E7AA2 /* Install sandbox profile for macOS */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/supd/com.apple.securityuploadd.sb", + ); + name = "Install sandbox profile for macOS"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DSTROOT)/System/Library/Sandbox/Profiles/com.apple.securityuploadd.sb", + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "if [ \"${PLATFORM_NAME}\" == \"macosx\" ]; then\n mkdir /System/Library/Sandbox/Profiles\n cp \"$SRCROOT/supd/com.apple.securityuploadd.sb\" \"$DSTROOT/System/Library/Sandbox/Profiles/com.apple.securityuploadd.sb\"\nfi\n"; + }; D4428B432122718400EB8448 /* Generate BATS Plist */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; @@ -32392,6 +32350,28 @@ shellPath = /bin/sh; shellScript = "ditto ${SRCROOT}/trust/trustd/iOS/AppleCorporateRootCA.cer ${DSTROOT}/AppleInternal/Library/Security/\nditto ${SRCROOT}/trust/trustd/iOS/AppleCorporateRootCA2.cer ${DSTROOT}/AppleInternal/Library/Security/\nchown -R root:wheel ${DSTROOT}/AppleInternal/Library/Security/\n"; }; + D459364124BFBA700066FB43 /* Install Apple Corporate Roots */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/trust/trustd/iOS/AppleCorporateRootCA.cer", + "$(SRCROOT)/trust/trustd/iOS/AppleCorporateRootCA2.cer", + ); + name = "Install Apple Corporate Roots"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DSTROOT)/AppleInternal/Library/Security/AppleCorporateRootCA.cer", + "$(DSTROOT)/AppleInternal/Library/Security/AppleCorporateRootCA2.cer", + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "ditto ${SRCROOT}/trust/trustd/iOS/AppleCorporateRootCA.cer ${DSTROOT}/AppleInternal/Library/Security/\nditto ${SRCROOT}/trust/trustd/iOS/AppleCorporateRootCA2.cer ${DSTROOT}/AppleInternal/Library/Security/\nchown -R root:wheel ${DSTROOT}/AppleInternal/Library/Security/\n\n"; + }; D4C263C41F8FEAA8001317EA /* Run Script Generate Error Strings */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -32519,6 +32499,25 @@ shellPath = /bin/sh; shellScript = "if [ ! -h ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/XPCServices ]; then\n ln -s Versions/Current/XPCServices ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/XPCServices\nfi\n\nexit 0\n"; }; + DC2C884D245B4B3E0040CBEB /* Copy Sandbox Profile (macOS only) */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb", + ); + name = "Copy Sandbox Profile (macOS only)"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "if [ \"$PLATFORM_FAMILY_NAME\" = \"macOS\" ]; then\n mkdir -p ${INSTALL_ROOT}/System/Library/Sandbox/Profiles/\n cp ${SRCROOT}/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb ${INSTALL_ROOT}/System/Library/Sandbox/Profiles/\nfi\n"; + }; DC58C4381D77BE5E003C25A4 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -32610,7 +32609,7 @@ ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n"; + shellScript = "CKKSTESTS_DIR=${SRCROOT}/keychain/ckks/tests\npython ${CKKSTESTS_DIR}/gen_test_plist.py ${CKKSTESTS_DIR} ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/KeychainCKKS.plist\n\n[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n"; }; DC82FFE61D90D3F60085674B /* security_utilities DTrace */ = { isa = PBXShellScriptBuildPhase; @@ -32832,20 +32831,6 @@ shellScript = "${SRCROOT}/RegressionTests/PreprocessPlist.sh ${SRCROOT}/RegressionTests/Security.plist ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/Security.plist\n\n[ \"$(whoami)\" == \"root\" ] || exit 0\nchown root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n"; showEnvVarsInLog = 0; }; - EBC73F4B209A0C3400AE3350 /* Install OCMock framework */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 8; - files = ( - ); - inputPaths = ( - ); - name = "Install OCMock framework"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 1; - shellPath = /bin/sh; - shellScript = "sh xcscripts/install-test-framework.sh OCMock.framework\n"; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -32895,24 +32880,19 @@ 0CB9754F2023A8F5008D6B48 /* CloudKitMockXCTest.m in Sources */, 0C0DA5D01FE1F1F3003BD3BB /* CKKSControlProtocol.m in Sources */, 0C16371C1FD116B300210823 /* MockCloudKit.m in Sources */, - 6C53A44D206AB1EF000FA611 /* LocalKeychainAnalytics.m in Sources */, 0C0DA5CF1FE1F1C5003BD3BB /* OTControlProtocol.m in Sources */, DCDB296C1FD8820400B5D242 /* SFAnalytics.m in Sources */, 6C73F48D2006B83E003D5D63 /* SOSAnalytics.m in Sources */, DC5B391820C08B39005B09F6 /* SecFramework.c in Sources */, DCDB296E1FD8821400B5D242 /* SFAnalyticsActivityTracker.m in Sources */, DCDB29701FD8821800B5D242 /* SFAnalyticsMultiSampler.m in Sources */, - DC2FA71120E5770400DB7518 /* OTClique.m in Sources */, DCDB29741FD8822200B5D242 /* SFAnalyticsSQLiteStore.m in Sources */, 0C46A5712034C6BA00F17112 /* OTControl.m in Sources */, DCDB29721FD8821D00B5D242 /* SFAnalyticsSampler.m in Sources */, - DCDB297E1FD8849D00B5D242 /* SFObjCType.m in Sources */, 5A061197229ED6EB006AF14A /* NSDate+SFAnalytics.m in Sources */, - DCDB297C1FD8848A00B5D242 /* SFSQLite.m in Sources */, + A6C737BD23F37AB20009C930 /* entitlements.c in Sources */, 0CA4EBF4202B8DBE002B1D96 /* CloudKitKeychainSyncingTestsBase.m in Sources */, - DCDB297D1FD8849A00B5D242 /* SFSQLiteStatement.m in Sources */, DCDB297B1FD8847100B5D242 /* SecTask.c in Sources */, - 0CE751AF20ACC497002B2832 /* SFSignInAnalytics.m in Sources */, 0C1637291FD2066A00210823 /* SecdWatchdog.m in Sources */, DCDB29791FD8844C00B5D242 /* client.c in Sources */, DCDB297A1FD8845600B5D242 /* client_endpoint.m in Sources */, @@ -32936,20 +32916,40 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 0C9AEEAE20783FBB00BF6237 /* Sources */ = { + 0CCC220B23F357EE00E1FCD0 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0C9AEEAF20783FBB00BF6237 /* SFSignInAnalyticsTests.m in Sources */, + 0CCC22A623F3868400E1FCD0 /* OTControl.m in Sources */, + 0CCC22CA23F3933000E1FCD0 /* CloudKitKeychainSyncingMockXCTest.m in Sources */, + 0CCC22C023F38DA100E1FCD0 /* SecdWatchdog.m in Sources */, + 0CCC22B723F38BF500E1FCD0 /* CloudKitMockXCTest.m in Sources */, + 0CCC22BB23F38C8800E1FCD0 /* server_entitlement_helpers.c in Sources */, + 0CCC22C123F38DC100E1FCD0 /* server_security_helpers.m in Sources */, + 0CCC22C923F3932600E1FCD0 /* CloudKitKeychainSyncingTestsBase.m in Sources */, + 0CCC22BF23F38D8E00E1FCD0 /* server_endpoint.m in Sources */, + 0CCC22B823F38C0E00E1FCD0 /* MockCloudKit.m in Sources */, + 0CCC22BE23F38D7C00E1FCD0 /* spi.c in Sources */, + 0CCC22B923F38C3000E1FCD0 /* CKKSMockSOSPresentAdapter.m in Sources */, + 0C9A54B6250C286100FF007B /* OctagonTrustTests+Errors.m in Sources */, + 0CCC22A023F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m in Sources */, + DCD68F18255A1C1400C2A1BA /* CKKSMockLockStateProvider.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 0CF406112072E3E3003D6A7F /* Sources */ = { + 0CD743A223C3EC8000FA0EC5 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0C5663EC20BE2DF30035F362 /* SFSignInAnalytics.m in Sources */, - 0CF406522072E422003D6A7F /* SFSignInAnalyticsTests.m in Sources */, + 0C468FF623C7D4D5006F4582 /* OTICDPRecordSilentContext.m in Sources */, + 0C468FF223C7D4D5006F4582 /* OTEscrowAuthenticationInformation.m in Sources */, + 0C468FE423C7D487006F4582 /* OTEscrowRecordMetadata.m in Sources */, + 0C9F65AE23E3AD3200B1A2C5 /* OTEscrowTranslation.m in Sources */, + 0C468FE623C7D487006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */, + 0C79213D23C3F6E100193389 /* OctagonTrust.m in Sources */, + 0C468FF023C7D4D5006F4582 /* OTCDPRecoveryInformation.m in Sources */, + 0C468FE223C7D487006F4582 /* OTEscrowRecord.m in Sources */, + 0C468FF423C7D4D5006F4582 /* OTICDPRecordContext.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32984,6 +32984,7 @@ 225394CA1E3082D500D3CD9B /* macho++.cpp in Sources */, 225394CB1E30831D00D3CD9B /* machorep.cpp in Sources */, 225394CC1E30832A00D3CD9B /* sigblob.cpp in Sources */, + A6C737B923F37A480009C930 /* entitlements.c in Sources */, 225394CD1E30833400D3CD9B /* resources.cpp in Sources */, 225394CE1E30833F00D3CD9B /* cfmunge.cpp in Sources */, 225394CF1E30835700D3CD9B /* csutilities.cpp in Sources */, @@ -33056,6 +33057,23 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3E4D49B42531170600B124B3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A640B71F25CB8A030098A4A4 /* secstaticcode_integration.m in Sources */, + 3E4D508F253117DD00B124B3 /* secstaticcode.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E88360924F068EF00E9F4D6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A640B72425CB99EB0098A4A4 /* seccode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 438169081B4EDCBD00C54D58 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -33105,6 +33123,7 @@ 4718AE44205B39C40068EC3F /* SFKeychainControlManager.m in Sources */, DC3AF52F2229E770006577E8 /* CKKSListenerCollection.m in Sources */, 0C29BF2523232897003C807E /* OTDefines.m in Sources */, + 6C6AF17F221A07090091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */, 4718AE46205B39C40068EC3F /* CKKSIncomingQueueOperation.m in Sources */, 4718AE47205B39C40068EC3F /* CKKSOutgoingQueueOperation.m in Sources */, 4718AE48205B39C40068EC3F /* CKKSZoneStateEntry.m in Sources */, @@ -33112,10 +33131,12 @@ 4718AE4B205B39C40068EC3F /* CKKSHealKeyHierarchyOperation.m in Sources */, 4718AE4C205B39C40068EC3F /* CKKSCurrentItemPointer.m in Sources */, 6C4AEF97218A12810012C5DA /* SecDbKeychainMetadataKeyStore.m in Sources */, + DCA72AE52530D3BD00CCB062 /* CKKSKeychainViewState.m in Sources */, EB0E1ACD2353A704002B6037 /* CKKSRateLimiter.m in Sources */, 4718AE4D205B39C40068EC3F /* CKKSLocalSynchronizeOperation.m in Sources */, 4718AE4E205B39C40068EC3F /* OTManager.m in Sources */, 4718AE50205B39C40068EC3F /* CKKSCurrentKeyPointer.m in Sources */, + DC880F69243D4CE50059806D /* CKKSLogging.m in Sources */, 4718AE51205B39C40068EC3F /* CKKSControlServer.m in Sources */, 4718AE52205B39C40068EC3F /* CKKSUpdateDeviceStateOperation.m in Sources */, 4718AE53205B39C40068EC3F /* SecDbKeychainSerializedMetadata.m in Sources */, @@ -33168,6 +33189,7 @@ 6C4AEF89218A09E80012C5DA /* CheckV12DevEnabled.m in Sources */, 4718AE81205B39C40068EC3F /* SecDbKeychainSerializedSecretData.m in Sources */, 4718AE82205B39C40068EC3F /* CKKSKeychainView.m in Sources */, + FC637231237B5D2200973738 /* SecItemServer+SWC.m in Sources */, 4718AE83205B39C40068EC3F /* SecuritydXPC.c in Sources */, 4718AE84205B39C40068EC3F /* SecDbKeychainSerializedItemV7.m in Sources */, 4718AE86205B39C40068EC3F /* CKKSProcessReceivedKeysOperation.m in Sources */, @@ -33187,7 +33209,6 @@ 4718AE96205B39C40068EC3F /* CKKSZoneChangeFetcher.m in Sources */, 4718AE97205B39C40068EC3F /* CKKSCondition.m in Sources */, EB0E1ACE2353A704002B6037 /* CKKSPBFileStorage.m in Sources */, - 4718AE98205B39C40068EC3F /* CKKSZone.m in Sources */, 4718AE99205B39C40068EC3F /* SFKeychainServer.m in Sources */, 4718AE9B205B39C40068EC3F /* swcagent_client.c in Sources */, DC5A01EB21BB428500D87AB9 /* CKKSTLKShare.m in Sources */, @@ -33205,12 +33226,15 @@ 477A1FED2037A0E000ACD81D /* KeychainXCTest.m in Sources */, 4727FBEB1F99227F0003AE36 /* spi.c in Sources */, 4727FBEC1F99235B0003AE36 /* SecdWatchdog.m in Sources */, + 6CD8412C23F5D871003DDF34 /* KeychainBackupTests.m in Sources */, 4764E9272059D866005497C9 /* KeychainModel.xcdatamodeld in Sources */, + 6C6B3ADF23F1B3E0002827C2 /* KeychainAppClipTests.m in Sources */, 4727FBBA1F9918590003AE36 /* KeychainCryptoTests.m in Sources */, 6C9791C921C2EAB60074C609 /* NSError+UsefulConstructors.m in Sources */, + 6C912AA1227A3E9700671FC6 /* CheckV12DevEnabled.m in Sources */, 477A1FE4203763A500ACD81D /* KeychainAPITests.m in Sources */, 4727FBED1F99249A0003AE36 /* server_endpoint.m in Sources */, - 096C647020AB1BC700D7B7D5 /* KeychainEntitlementsTest.m in Sources */, + 6C6B3AC623F1A820002827C2 /* KeychainEntitlementsTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -33239,25 +33263,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 478D42751FD72A8100CAB645 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 478D42761FD72A8100CAB645 /* server_xpc.m in Sources */, - 4764E92D2059D8BF005497C9 /* KeychainModel.xcdatamodeld in Sources */, - 478D42771FD72A8100CAB645 /* server_security_helpers.m in Sources */, - 478D42781FD72A8100CAB645 /* server_entitlement_helpers.c in Sources */, - 477A1FEE2037A0E000ACD81D /* KeychainXCTest.m in Sources */, - 09BFE35C20A32E0E008511E9 /* KeychainEntitlementsTest.m in Sources */, - 478D42791FD72A8100CAB645 /* spi.c in Sources */, - 478D427A1FD72A8100CAB645 /* SecdWatchdog.m in Sources */, - 6C9791CA21C2EAB70074C609 /* NSError+UsefulConstructors.m in Sources */, - 478D427B1FD72A8100CAB645 /* KeychainCryptoTests.m in Sources */, - 477A1FE5203763A500ACD81D /* KeychainAPITests.m in Sources */, - 478D427C1FD72A8100CAB645 /* server_endpoint.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 47C2F17F2059CB680062DE30 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -33281,10 +33286,8 @@ files = ( 6CAA8CFF1F83E800007B6E03 /* SFSQLite.m in Sources */, 6CDB5FF61FA78D1B00410924 /* SFAnalyticsMultiSampler.m in Sources */, - 0CBFEACB200FCD2D009A60E9 /* SFSignInAnalytics.m in Sources */, 5A06118E229ED5EB006AF14A /* NSDate+SFAnalytics.m in Sources */, 0C8884012154C4E80053224D /* OTJoiningConfiguration.m in Sources */, - 0CBD55B31FE883F200A8CE21 /* SFBehavior.m in Sources */, 6C814A4D2050B4B600CB391B /* LocalKeychainAnalytics.m in Sources */, 220179E91E3BF03200EFB6F3 /* dummy.cpp in Sources */, 5A442FA9233C351000918373 /* SecExperiment.m in Sources */, @@ -33294,6 +33297,7 @@ DCC5860020BF8A7E005C7269 /* SecFramework.c in Sources */, DCA85B931E8D97E400BA7241 /* client.c in Sources */, DCA9D84621FFE7CF00B27421 /* EscrowRequestXPCProtocol.m in Sources */, + DCC8856E2548E9FB004B0DB4 /* SecKnownFilePaths.m in Sources */, 6CBF653A1FA147E500A68667 /* SFAnalyticsActivityTracker.m in Sources */, DC9C95BF1F79DC88000D19E5 /* CKKSControl.m in Sources */, EB10A3E620356E2000E84270 /* OTConstants.m in Sources */, @@ -33315,7 +33319,6 @@ 6CE365531FA101080012F6AB /* SFAnalyticsSampler.m in Sources */, AA9FD59C2152AFD70045A07A /* SecProtocolConfiguration.m in Sources */, 6C73F48A2006B839003D5D63 /* SOSAnalytics.m in Sources */, - EB973652234E8F4B00518B2B /* CKKSPBFileStorage.m in Sources */, 5A04BAFA22976A15001848A0 /* OTClique.m in Sources */, 6CE365571FA1017D0012F6AB /* SFAnalyticsSQLiteStore.m in Sources */, EB9B285721C77C8D00173DC2 /* OTDefines.m in Sources */, @@ -33379,6 +33382,8 @@ DC3AA2862097E22A007CA68A /* codesign.c in Sources */, DC8506AC2097EEBA00C712EC /* sos.m in Sources */, E78A9ADA1D34959200006B5B /* NSFileHandle+Formatting.m in Sources */, + D4353ABE2526BE5C002E72F7 /* trust_config.m in Sources */, + BE57B1192509E1000045B7FD /* ca_revocation_additions.m in Sources */, DC3AA28A2097E23B007CA68A /* keychain_find.m in Sources */, DC3AA2782097DF70007CA68A /* readline.c in Sources */, DC3AA2812097E216007CA68A /* add_internet_password.c in Sources */, @@ -33460,10 +33465,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 6C2045E62424BA7E00F9461D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6C2045F12424BAC900F9461D /* main.m in Sources */, + 6C2045F22424BACE00F9461D /* KeychainStasher.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 6C39234D21F13E4D00D018AD /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6CD224E623949132001B70FD /* SecDbBackupTestsBase.m in Sources */, + 6C912AA0227A3E9600671FC6 /* CheckV12DevEnabled.m in Sources */, 6C39237B21F13EB400D018AD /* SecDbBackupManager.m in Sources */, 6C39237C21F13EB400D018AD /* SecDbBackupBag.m in Sources */, 6C39237D21F13EB400D018AD /* SecDbBackupBagIdentity.m in Sources */, @@ -33486,6 +33502,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4FA657B259D5B9C00EDB660 /* trustdFileLocations.m in Sources */, + D4FA657C259D5B9C00EDB660 /* trustdFileHelper.m in Sources */, 6CB96BB21F966DA400E11457 /* SFSQLite.m in Sources */, 6CB96BB31F966DA400E11457 /* SFSQLiteStatement.m in Sources */, 6CBF65421FA2255800A68667 /* SFAnalyticsActivityTracker.m in Sources */, @@ -33504,56 +33522,44 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6C98083D1E788AEB00E70590 /* Sources */ = { + 6C7BE2B623C3DD64003BB2CA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6CBF65431FA2257100A68667 /* SFAnalyticsActivityTracker.m in Sources */, - 6CAA8CF71F83E79E007B6E03 /* SFSQLite.m in Sources */, - 476541A41F33EDED00413F65 /* SecdWatchdog.m in Sources */, - 47B011991F17D78D0030B49F /* SFSQLiteStatement.m in Sources */, - DC2D438F1F0EEC2A0005D382 /* MockCloudKit.m in Sources */, - 6CDF8DEF1F96495600140B54 /* SFAnalyticsSampler.m in Sources */, - DCB515E21ED3D134001F1152 /* SecTask.c in Sources */, - DCB515E11ED3D11A001F1152 /* client.c in Sources */, - 6C9808A61E788CD200E70590 /* CKKSCloudKitTests.m in Sources */, - 6C98083E1E788AEB00E70590 /* spi.c in Sources */, - 5A061192229ED6E5006AF14A /* NSDate+SFAnalytics.m in Sources */, - DC2353301ECA658900D7C1BE /* server_security_helpers.m in Sources */, - 6CAA8CF01F83E65E007B6E03 /* SFObjCType.m in Sources */, - 6CAA8D131F83ECD4007B6E03 /* SFAnalytics.m in Sources */, - DC2353321ECA659000D7C1BE /* server_xpc.m in Sources */, - 6CDB5FF91FA78D2400410924 /* SFAnalyticsMultiSampler.m in Sources */, - DC5F35B11EE0F28B00900966 /* server_entitlement_helpers.c in Sources */, - DC2353291ECA658300D7C1BE /* server_endpoint.m in Sources */, - 6CAA8CF91F83E7AA007B6E03 /* SFAnalyticsSQLiteStore.m in Sources */, + 6C7BE2B823C3DD64003BB2CA /* SecurityTool.c in Sources */, + 6C7BE2B923C3DD64003BB2CA /* scep.c in Sources */, + 6C7BE2BA23C3DD64003BB2CA /* trust_update.m in Sources */, + 6C7BE2BB23C3DD64003BB2CA /* keychain_backup.c in Sources */, + 6C7BE2BC23C3DD64003BB2CA /* whoami.m in Sources */, + 6C7BE2BE23C3DD64003BB2CA /* KeychainCheck.m in Sources */, + 6C7BE2BF23C3DD64003BB2CA /* log_control.c in Sources */, + 6C7BE2C023C3DD64003BB2CA /* not_on_this_platorm.c in Sources */, + 6C7BE2C123C3DD64003BB2CA /* keychain_util.c in Sources */, + 6C7BE2C223C3DD64003BB2CA /* security_tool_commands.c in Sources */, + 6C7BE2C323C3DD64003BB2CA /* codesign.c in Sources */, + 6C7BE2C523C3DD64003BB2CA /* NSFileHandle+Formatting.m in Sources */, + 6C7BE2C623C3DD64003BB2CA /* keychain_find.m in Sources */, + 6C7BE2C723C3DD64003BB2CA /* readline.c in Sources */, + 6C7BE2C823C3DD64003BB2CA /* add_internet_password.c in Sources */, + 6C7BE2C923C3DD64003BB2CA /* digest_calc.c in Sources */, + 6C7BE2CA23C3DD64003BB2CA /* leaks.c in Sources */, + 6C7BE2CB23C3DD64003BB2CA /* show_certificates.c in Sources */, + 6C7BE2CC23C3DD64003BB2CA /* spc.c in Sources */, + 6C7BE2CD23C3DD64003BB2CA /* verify_cert.c in Sources */, + D43539E42526BE5B002E72F7 /* trust_config.m in Sources */, + 6C7BE2CE23C3DD64003BB2CA /* ct_exceptions.m in Sources */, + BE57B1182509E1000045B7FD /* ca_revocation_additions.m in Sources */, + 6C7BE2CF23C3DD64003BB2CA /* keychain_add.c in Sources */, + 6C7BE2D023C3DD64003BB2CA /* pkcs12_util.c in Sources */, + 6C7BE2D123C3DD64003BB2CA /* print_cert.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 6C9808791E788AFD00E70590 /* Sources */ = { + 6C96327D242A279B00C53CE2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6CAA8CF61F83E79D007B6E03 /* SFSQLite.m in Sources */, - 6CDB5FF81FA78D2300410924 /* SFAnalyticsMultiSampler.m in Sources */, - 5A061193229ED6E6006AF14A /* NSDate+SFAnalytics.m in Sources */, - 476541A51F33EE1E00413F65 /* SecdWatchdog.m in Sources */, - DC2D43951F0EEC300005D382 /* MockCloudKit.m in Sources */, - 6CAA8CF81F83E7A9007B6E03 /* SFAnalyticsSQLiteStore.m in Sources */, - 6C9808A51E788CD100E70590 /* CKKSCloudKitTests.m in Sources */, - 6CBF65441FA2257200A68667 /* SFAnalyticsActivityTracker.m in Sources */, - DCB515E31ED3D135001F1152 /* SecTask.c in Sources */, - 6CAA8CEF1F83E65D007B6E03 /* SFObjCType.m in Sources */, - DCB515E01ED3D111001F1152 /* client.c in Sources */, - DCB515E41ED3D15A001F1152 /* client_endpoint.m in Sources */, - 6CAA8D141F83ECD5007B6E03 /* SFAnalytics.m in Sources */, - 6C98087A1E788AFD00E70590 /* spi.c in Sources */, - 6CAA8D0D1F83EC57007B6E03 /* SFSQLiteStatement.m in Sources */, - DC5F35B21EE0F28C00900966 /* server_entitlement_helpers.c in Sources */, - DC2353311ECA658B00D7C1BE /* server_security_helpers.m in Sources */, - DC2353331ECA659000D7C1BE /* server_xpc.m in Sources */, - DC23532F1ECA658400D7C1BE /* server_endpoint.m in Sources */, - 6CDF8DF01F96495700140B54 /* SFAnalyticsSampler.m in Sources */, + 6C963284242A279B00C53CE2 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -33572,6 +33578,8 @@ files = ( 6CAA8D351F84306C007B6E03 /* main.m in Sources */, 6CAA8D271F843002007B6E03 /* supd.m in Sources */, + D4FA62D8259D16D800EDB660 /* trustdFileHelper.m in Sources */, + D4FA63BC259D568F00EDB660 /* trustdFileLocations.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -33594,16 +33602,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6CF4A0DC1E4549F200ECD7B5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6CF4A0EA1E4549F300ECD7B5 /* ViewController.m in Sources */, - 6CF4A0E71E4549F300ECD7B5 /* AppDelegate.m in Sources */, - 6CF4A0E41E4549F200ECD7B5 /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 790851B30CA9859F0083CC4D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -33662,6 +33660,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0C468FF823C7D4E3006F4582 /* OTEscrowRecordMetadata.m in Sources */, 0CE15E2F222DF63600B7EAA5 /* SetValueTransformer.swift in Sources */, 0CE15E2C222DF63600B7EAA4 /* RecoveryKey.swift in Sources */, 0CE15E43222DF6A800B7EAA4 /* Recovery.m in Sources */, @@ -33670,15 +33669,19 @@ DC391F8D21BF244000772585 /* CKKSSIV.m in Sources */, 0CE15E30222DF63600B7EAA4 /* RecoverKeySet.swift in Sources */, 0C3BB3582188E18C0018FC14 /* OTPrivateKey+SF.m in Sources */, + 0C468FF723C7D4E3006F4582 /* OTEscrowRecord.m in Sources */, BECFA43D20F9493000B11002 /* Policy.swift in Sources */, 0CB582D1218920090040C5F2 /* OTAuthenticatedCiphertext.m in Sources */, 0CF70BD9218BED1000EC3515 /* CuttlefishExtensionWorkaround.swift in Sources */, DC754C742228B59000A39C8E /* TrustedPeersHelperProtocol.m in Sources */, + DC3A9B2823A9D8C40073ED06 /* Container_BottledPeers.swift in Sources */, DC391FA621C04D1500772585 /* OctagonPeerKeys.swift in Sources */, DCF6320521C074F30030CCC0 /* CuttlefishAPIHelpers.swift in Sources */, DC391F8C21BF222B00772585 /* CKKSTLKShare.m in Sources */, + DCAA209C23AAF93700DCB594 /* Container_RecoveryKey.swift in Sources */, BE9F8D19206C4AD300B53D16 /* ContainerMap.swift in Sources */, BE9F4F8C2072D881004A52C2 /* Cuttlefish.pb.swift in Sources */, + DC9978B82404AA3200A5EE2F /* Container_UserSync.swift in Sources */, DC391F9D21BF2F8100772585 /* CKKSConstants.m in Sources */, BE9F8D10206C099800B53D16 /* Container.swift in Sources */, 0CB582D3218920090040C5F2 /* OTPrivateKey.m in Sources */, @@ -33688,13 +33691,17 @@ DCAD8F8622C43EC1007C3872 /* Container_MachineIDs.swift in Sources */, DCB0C295222F5EF60083AECB /* CuttlefishErrors.swift in Sources */, 0CB582D021891FF40040C5F2 /* OTBottle.m in Sources */, + DC880F6B243D4D730059806D /* CKKSLogging.m in Sources */, 0C0C4F86216FB73C00C14C61 /* EscrowKeys.swift in Sources */, DCB9475621274A1900ED9272 /* TPHObjcTranslation.m in Sources */, 0C3BB35A2188E18C0018FC14 /* OTAuthenticatedCiphertext+SF.m in Sources */, + 0C468FF923C7D4E3006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */, + 0C0CB73923AD714D0020C6BF /* Container_EscrowRecords.swift in Sources */, 0CE15E3E222DF6A800B7EAA4 /* OTRecovery.m in Sources */, DC391F8E21BF274600772585 /* CKKSPeer.m in Sources */, DC391F8A21BF222500772585 /* CKKSKeychainBackedKey.m in Sources */, 0C0C4F87216FB73F00C14C61 /* BottledPeer.swift in Sources */, + 0C3DF8C824789C3C009CF03A /* Container_Peers.swift in Sources */, 0CB582D2218920090040C5F2 /* OTBottleContents.m in Sources */, DC391F8F21BF284D00772585 /* CKKSSerializedKey.m in Sources */, BEC0A96420B362EC00DBD772 /* Utils.swift in Sources */, @@ -33732,37 +33739,45 @@ 0CA4B4722171410200B17169 /* EscrowKeys.swift in Sources */, BE536030209BC1FD0027E25A /* spi.c in Sources */, BEA8558120B5DC7D00D5AD11 /* FakeCuttlefish.swift in Sources */, + DC9978BB2404B26900A5EE2F /* Container_UserSync.swift in Sources */, 0CB5C678218B803C0044F730 /* OTPrivateKey+SF.m in Sources */, DC05035E214083B200A8EDB7 /* TPHObjcTranslation.m in Sources */, 0CE15E41222DF6A800B7EAA4 /* OTRecovery.m in Sources */, BE536031209BC2F90027E25A /* SecdWatchdog.m in Sources */, 0CB582C82189157F0040C5F2 /* OTAuthenticatedCiphertext.m in Sources */, + 0C468FFC23C7D4EF006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */, BED987E320991C4D00607A5F /* MockCuttlefish.swift in Sources */, BEC373D020D87B4D00DBDF5B /* SecFramework.c in Sources */, 0CB582CA2189157F0040C5F2 /* OTBottleContents.m in Sources */, + 0C3DF8C924789D06009CF03A /* Container_Peers.swift in Sources */, BE536032209BC3250027E25A /* server_endpoint.m in Sources */, BE536034209BC3C40027E25A /* server_security_helpers.m in Sources */, BECFA43E20F9493000B11002 /* Policy.swift in Sources */, 0CA2282F2187A5CA00A1C56C /* BottledPeer.swift in Sources */, + DC880F6A243D4D640059806D /* CKKSLogging.m in Sources */, DC747993222720C8001E0E8C /* MockCloudKit.m in Sources */, 0CB5C677218B803C0044F730 /* OTAuthenticatedCiphertext+SF.m in Sources */, BE727824209CBCA800F0DA77 /* Cuttlefish.pb.swift in Sources */, BED987E120991B9B00607A5F /* Decrypter.swift in Sources */, DC391FA721C04D6800772585 /* OctagonPeerKeys.swift in Sources */, BE536033209BC3B30027E25A /* server_entitlement_helpers.c in Sources */, + DCAA209B23AAF8FD00DCB594 /* Container_RecoveryKey.swift in Sources */, BED987E020991B1100607A5F /* TrustedPeersHelper.xcdatamodeld in Sources */, + 0C468FFA23C7D4EF006F4582 /* OTEscrowRecord.m in Sources */, BED987D62099145300607A5F /* TrustedPeersHelperUnitTests.swift in Sources */, BE4C6AB820CAF4F700EAD6BE /* ContainerSync.swift in Sources */, 0CE15E46222DF6A800B7EAA4 /* Recovery.m in Sources */, 0CE15E33222DF63600B7EAA4 /* RecoverKeySet.swift in Sources */, 0CE15E2F222DF63600B7EAA4 /* RecoveryKey.swift in Sources */, + 0C468FFB23C7D4EF006F4582 /* OTEscrowRecordMetadata.m in Sources */, DCF6320721C075210030CCC0 /* CuttlefishAPIHelpers.swift in Sources */, + 0C0CB73B23AD71650020C6BF /* Container_EscrowRecords.swift in Sources */, BED987DE2099156B00607A5F /* Container.swift in Sources */, DCB0C292222F5E1D0083AECB /* CuttlefishErrors.swift in Sources */, - BECFA44320FD0A4B00B11002 /* LocalKeychainAnalytics.m in Sources */, DCAD8F8922C43EDB007C3872 /* Container_MachineIDs.swift in Sources */, 0CF70BDA218BEFAE00EC3515 /* CuttlefishExtensionWorkaround.swift in Sources */, DCD24DEC228C9A480052604C /* SetValueTransformer.swift in Sources */, + DC14C4C223AAACED007F673F /* Container_BottledPeers.swift in Sources */, BEC0A96520B362EC00DBD772 /* Utils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -33804,6 +33819,7 @@ DCE0776A21ADD71C002662FD /* TPPBPeerDynamicInfo.m in Sources */, DCE0776C21ADD71C002662FD /* TPPBPolicySecret.m in Sources */, DCE0776E21ADD71C002662FD /* TPPBPeerStableInfo.m in Sources */, + DCC03FA523FF521100A4DA3F /* TPSyncingPolicy.m in Sources */, DCE0777021ADD71C002662FD /* TPPBVoucher.m in Sources */, DCE0777221ADD71C002662FD /* TPPBPolicyDocument.m in Sources */, DCE0777421ADD71C002662FD /* TPPBPolicyCategoriesByView.m in Sources */, @@ -33886,6 +33902,19 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D445B308258C07FC0019858E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D4610A96258C2F350099E390 /* SecBuffer.c in Sources */, + D46108D7258C2E510099E390 /* SecCFWrappers.c in Sources */, + D4610717258C2E230099E390 /* SecFileLocations.c in Sources */, + D4610637258C2E1D0099E390 /* trustdFileLocations.m in Sources */, + D4FA5BD9259D0FCB00EDB660 /* main.m in Sources */, + D4FA6039259D109B00EDB660 /* trustdFileHelper.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D44D1F632115893000E76E1A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -33924,20 +33953,28 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D477CB83237F692400C02355 /* RevocationTests.m in Sources */, D40881F5217573C900180E81 /* SecTrustStatusCodes.c in Sources */, D4FD421D217D789C002B7EE2 /* NameConstraintsTests.m in Sources */, D4FD4221217D7B2E002B7EE2 /* PathScoringTests.m in Sources */, + D477CB88237F8B2F00C02355 /* CAIssuerTests.m in Sources */, D40881F42175738C00180E81 /* SecPolicyLeafCallbacks.c in Sources */, D40881F32175733F00180E81 /* SecPolicy.c in Sources */, + D40724E725310F3B0084D96B /* PinningDbTests.m in Sources */, + D477CB7C237E4BD700C02355 /* ExceptionTests.m in Sources */, D40881F22175733500180E81 /* SecSignatureVerificationSupport.c in Sources */, D40881F12175732E00180E81 /* SecCertificate.c in Sources */, D40881F02175732600180E81 /* SecTrustStore.c in Sources */, + D477CB90237F975500C02355 /* ValidTests.m in Sources */, D40881EF2175731E00180E81 /* SecTrust.c in Sources */, D458C523214E33380043D982 /* KeySizeTests.m in Sources */, + D477CB8C237F8DBC00C02355 /* AllowlistBlocklistTests.m in Sources */, D458C4BD214E19AF0043D982 /* SignatureAlgorithmTests.m in Sources */, + D477CB6B237CBA2C00C02355 /* TrustDaemonTestCase.m in Sources */, D458C4B1214E198F0043D982 /* CTTests.m in Sources */, D458C4B9214E19AF0043D982 /* PathParseTests.m in Sources */, D458C516214E286D0043D982 /* PolicyTests.m in Sources */, + D4D1CF3225AD37260068595B /* TrustServerTests.m in Sources */, D458C524214E33430043D982 /* VerifyDateTests.m in Sources */, D458C4B3214E198F0043D982 /* EvaluationBasicTests.m in Sources */, D458C521214E33260043D982 /* ECTests.m in Sources */, @@ -33947,11 +33984,18 @@ D442830022D68564001746B3 /* TrustEvaluationTestHelpers.m in Sources */, D453A4AB2122236D00850A26 /* TrustEvaluationTestCase.m in Sources */, D453A4AD2122236D00850A26 /* TrustFrameworkTestCase.m in Sources */, + D49A370D23877ECC0065719F /* OCSPCacheTests.m in Sources */, D4EA5CF922B225D100883439 /* LoggingServerTests.m in Sources */, + D458DAC42375FEA300E5890E /* TrustSettingsTests.m in Sources */, D4056A1B22712A650026E24E /* SSLPolicyTests.m in Sources */, D458C4C4214E19FC0043D982 /* TrustInterfaceTests.m in Sources */, D453A4AF2122236D00850A26 /* CertificateInterfaceTests.m in Sources */, D458C4C2214E19FC0043D982 /* TrustSettingsInterfaceTests.m in Sources */, + D423114423725F9F000E470A /* SMIMEPolicyTests.m in Sources */, + D4D1CBB525AD0AAF0068595B /* CertificateServerTests.m in Sources */, + D477CB5D237B6E0E00C02355 /* PersonalizationTests.m in Sources */, + D4C57B76255B74A400AB5D78 /* PolicyInterfaceTests.m in Sources */, + BED07B862542A2CE00FED203 /* CARevocationTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -33977,8 +34021,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D477CB6A237CBA2C00C02355 /* TrustDaemonTestCase.m in Sources */, + D49A370C23877ECC0065719F /* OCSPCacheTests.m in Sources */, D40881FA217573F800180E81 /* SecPolicy.c in Sources */, + D477CB8B237F8DBC00C02355 /* AllowlistBlocklistTests.m in Sources */, D40881FB217573F800180E81 /* SecPolicyLeafCallbacks.c in Sources */, + D4D1CBB425AD0AAF0068595B /* CertificateServerTests.m in Sources */, + D4C57C51255B74A600AB5D78 /* PolicyInterfaceTests.m in Sources */, D40881F9217573EF00180E81 /* SecSignatureVerificationSupport.c in Sources */, D40881F8217573E700180E81 /* SecCertificate.c in Sources */, D40881F7217573E000180E81 /* SecTrustStore.c in Sources */, @@ -33991,17 +34040,27 @@ D4FD4220217D7B2E002B7EE2 /* PathScoringTests.m in Sources */, D458C4BC214E19AF0043D982 /* SignatureAlgorithmTests.m in Sources */, D4FD421C217D789C002B7EE2 /* NameConstraintsTests.m in Sources */, + D477CB5C237B6E0E00C02355 /* PersonalizationTests.m in Sources */, D4A0F8CC211E6A8300443CA1 /* TrustEvaluationTestCase.m in Sources */, + D40725C225310F3D0084D96B /* PinningDbTests.m in Sources */, + D477CB87237F8B2F00C02355 /* CAIssuerTests.m in Sources */, D4A0F8C7211E6A5800443CA1 /* TrustFrameworkTestCase.m in Sources */, D458C4C3214E19FC0043D982 /* TrustInterfaceTests.m in Sources */, D4AC8BE821320AD0006E9871 /* CertificateParseTests.m in Sources */, D4A0F8C8211E6A5800443CA1 /* CertificateInterfaceTests.m in Sources */, + D423114323725F9F000E470A /* SMIMEPolicyTests.m in Sources */, D458C4B0214E198F0043D982 /* CTTests.m in Sources */, + D477CB8F237F975500C02355 /* ValidTests.m in Sources */, D458C4B2214E198F0043D982 /* EvaluationBasicTests.m in Sources */, + D477CB82237F692400C02355 /* RevocationTests.m in Sources */, + BED07AAC2542A2CC00FED203 /* CARevocationTests.m in Sources */, D458C4BA214E19AF0043D982 /* iAPTests.m in Sources */, D458C4B8214E19AF0043D982 /* PathParseTests.m in Sources */, D458C525214E33440043D982 /* VerifyDateTests.m in Sources */, D458C515214E286C0043D982 /* PolicyTests.m in Sources */, + D4D1CF3125AD37260068595B /* TrustServerTests.m in Sources */, + D458DAC32375FEA300E5890E /* TrustSettingsTests.m in Sources */, + D477CB7B237E4BD700C02355 /* ExceptionTests.m in Sources */, D4EF32182156DDEB000A31A5 /* TrustSettingsInterfaceTests.m in Sources */, D44282FF22D68564001746B3 /* TrustEvaluationTestHelpers.m in Sources */, ); @@ -34013,8 +34072,10 @@ files = ( D43DBEFC1E99D1CA00C04AEA /* nameconstraints.c in Sources */, D43DBEFD1E99D1CA00C04AEA /* OTATrustUtilities.m in Sources */, + D43534FF2525033E002E72F7 /* trustdFileLocations.m in Sources */, D43DBEFE1E99D1CA00C04AEA /* personalization.c in Sources */, D43DBEFF1E99D1CA00C04AEA /* policytree.c in Sources */, + D401443725789030008BAE33 /* TrustURLSessionCache.m in Sources */, D43DBF001E99D1CA00C04AEA /* SecCAIssuerCache.c in Sources */, D43DBF011E99D1CA00C04AEA /* SecCAIssuerRequest.m in Sources */, D43DBF021E99D1CA00C04AEA /* SecCertificateServer.c in Sources */, @@ -34022,6 +34083,7 @@ 5F84950222DFB505008B3EFB /* SecTrustExceptionResetCount.m in Sources */, D43DBF041E99D1CA00C04AEA /* SecOCSPCache.c in Sources */, D43DBF051E99D1CA00C04AEA /* SecOCSPRequest.c in Sources */, + D47C457A255244AD00460750 /* CertificateTransparency.m in Sources */, D4B68C68211A827C009FED69 /* trustd_spi.c in Sources */, D43761671EB2996C00954447 /* SecRevocationNetworking.m in Sources */, D4EF3221215F0F7F000A31A5 /* SecTrustStoreServer.m in Sources */, @@ -34205,6 +34267,7 @@ DC0BC7A21D8B773000070CB0 /* cssmcontext.cpp in Sources */, DC0BC7B21D8B773000070CB0 /* oidsalg.c in Sources */, DC0BC7AA1D8B773000070CB0 /* modload_plugin.cpp in Sources */, + 6C97434A24D1C8DE00A2025C /* LegacyAPICounts.m in Sources */, DC0BC7B41D8B773000070CB0 /* oidscrl.cpp in Sources */, DC0BC79B1D8B773000070CB0 /* attachfactory.cpp in Sources */, DC0BC7A51D8B773000070CB0 /* cssmmds.cpp in Sources */, @@ -34432,12 +34495,11 @@ DC0BCD961D8C6A1E00070CB0 /* der_dictionary.c in Sources */, DC0BCD751D8C6A1E00070CB0 /* iCloudKeychainTrace.c in Sources */, DC0BCD821D8C6A1E00070CB0 /* SecCFWrappers.c in Sources */, - EB4B6E201DC0682A00AFC494 /* SecADWrapper.c in Sources */, DC0BCD941D8C6A1E00070CB0 /* der_date.c in Sources */, DC0BCD9F1D8C6A1F00070CB0 /* fileIo.c in Sources */, - DC0BCDA81D8C6A1F00070CB0 /* SecFileLocations.c in Sources */, DC0BCDA61D8C6A1F00070CB0 /* SecDb.c in Sources */, EB7AE6F81E86DACC00B80B15 /* SecPLWrappers.m in Sources */, + BE26081825620B1A0057C489 /* SecXPCUtils.m in Sources */, DC0BCD7B1D8C6A1E00070CB0 /* SecCoreCrypto.c in Sources */, DC0BCDAF1D8C6A1F00070CB0 /* SecAppleAnchor.c in Sources */, DC0BCDA41D8C6A1F00070CB0 /* iOSforOSX-SecAttr.c in Sources */, @@ -34461,6 +34523,7 @@ DC0BCD9C1D8C6A1F00070CB0 /* der_set.c in Sources */, DC36895821235F23003A3735 /* SecAKSWrappers.c in Sources */, EBB8528122F79F6E00424FD0 /* SecXPCHelper.m in Sources */, + DCC888DB2548EC2B004B0DB4 /* SecFileLocations.c in Sources */, DC0BCDAC1D8C6A1F00070CB0 /* simulate_crash.m in Sources */, DC0BCD791D8C6A1E00070CB0 /* SecBuffer.c in Sources */, DC0BCDAB1D8C6A1F00070CB0 /* SecXPCError.c in Sources */, @@ -34501,6 +34564,7 @@ DC74799A222722BC001E0E8C /* CKKSKeychainBackedKey.m in Sources */, DC747999222722B2001E0E8C /* CKKSConstants.m in Sources */, DC7479982227229D001E0E8C /* CKKSTLKShare.m in Sources */, + DC880F6C243D4DC00059806D /* CKKSLogging.m in Sources */, DC0EF8F2208697C600AB9E95 /* main.swift in Sources */, EB7ECF9623467FB400CE2D3C /* Cuttlefish.pb.swift in Sources */, DCD48BFE20BF3D83009A3224 /* tpctl-objc.m in Sources */, @@ -34513,6 +34577,7 @@ buildActionMask = 2147483647; files = ( DC2B757621F2A270003C9356 /* SecEscrowRequest.m in Sources */, + BE7B8E142415579900E1CF4F /* SecSharedCredential.m in Sources */, 0C84D8381FCF43BF00B822E3 /* OTControlProtocol.m in Sources */, DCC585FF20BF8A7E005C7269 /* SecFramework.c in Sources */, DCA85B991E8D980B00BA7241 /* client_endpoint.m in Sources */, @@ -34522,7 +34587,6 @@ 6CDB5FF51FA78D1A00410924 /* SFAnalyticsMultiSampler.m in Sources */, DCA85B941E8D97E400BA7241 /* client.c in Sources */, DCDF0A4F1D81D76F007AF174 /* Security.exp-in in Sources */, - 0CBFEACA200FCD2D009A60E9 /* SFSignInAnalytics.m in Sources */, DC1789A51D779E3B00B50D50 /* dummy.cpp in Sources */, 5A061191229ED6DB006AF14A /* NSDate+SFAnalytics.m in Sources */, EB9B285821C77C8D00173DC2 /* OTDefines.m in Sources */, @@ -34534,6 +34598,8 @@ 6CAA8CFE1F83E800007B6E03 /* SFSQLite.m in Sources */, DC9C95C01F79DC89000D19E5 /* CKKSControl.m in Sources */, 5AF594001FA0EE5300A5C1EC /* SecProtocol.c in Sources */, + DCC8856F2548E9FB004B0DB4 /* SecKnownFilePaths.m in Sources */, + BE7B8E152415580D00E1CF4F /* SecSharedCredential.c in Sources */, 5A442FAA233C351100918373 /* SecExperiment.m in Sources */, 0C8884042154C4EA0053224D /* OTJoiningConfiguration.m in Sources */, 0C0E60E020D033E400E654F2 /* OTControl.m in Sources */, @@ -34544,9 +34610,7 @@ 6CE3654D1FA100E50012F6AB /* SFAnalytics.m in Sources */, 5A7E037A22272E0E003DB3A0 /* SecProtocolHelper.m in Sources */, 6CAA8CFD1F83E7EB007B6E03 /* SFObjCType.m in Sources */, - DC1789A21D779DF400B50D50 /* SecBreadcrumb.c in Sources */, 78ADC62C1FA0FACE001EB8B6 /* SecProtocolTypes.m in Sources */, - 0CE079F41FEA15B20040A3F1 /* SFBehavior.m in Sources */, 6CBF65411FA1481100A68667 /* SFAnalyticsActivityTracker.m in Sources */, 0CD9E34623592EA7002995DE /* OctagonSignPosts.m in Sources */, ); @@ -34574,7 +34638,6 @@ DC3502E71E0214C800BC0587 /* MockCloudKit.m in Sources */, DC6593D11ED8DAB900C19462 /* CKKSTests+CurrentPointerAPI.m in Sources */, DCAD9B491F8D95F200C5E2AE /* CloudKitKeychainSyncingFixupTests.m in Sources */, - DC752F1A21C1B6A700216089 /* SFSQLiteStatement.m in Sources */, 0CA4EBF3202B8D9C002B1D96 /* CloudKitKeychainSyncingTestsBase.m in Sources */, DC9A2C5F1EB3F557008FAC27 /* CKKSTests+Coalesce.m in Sources */, DC222C8A1E089BAE00B09171 /* CKKSSQLTests.m in Sources */, @@ -34583,32 +34646,33 @@ DCBF2F7D1F90084D00ED0CA4 /* CKKSTLKSharingTests.m in Sources */, DC62DC6D22A87137000D2D5D /* CKKSTests+MultiZone.m in Sources */, DCFABF8E20081E2F001128B5 /* CKKSDeviceStateUploadTests.m in Sources */, + DCD68B9D255A149300C2A1BA /* CKKSMockLockStateProvider.m in Sources */, DC3502B81E0208BE00BC0587 /* CKKSTests.m in Sources */, 6C3446301E24F6BE00F9522B /* CKKSRateLimiterTests.m in Sources */, DCE7F2091F21726500DDB0F7 /* OctagonAPSReceiverTests.m in Sources */, DC96053F1ECA2D6400AF9BDA /* SecTask.c in Sources */, DC08D1CC1E64FCC5006237DA /* CKKSSOSTests.m in Sources */, - 0C98122821ACCC9300784441 /* OTClique.m in Sources */, DC222CA81E08A7D900B09171 /* CloudKitMockXCTest.m in Sources */, EBB0315822223AAF007241CB /* CKKSLaunchSequenceTests.m in Sources */, - DC752F1F21C1B98000216089 /* SFObjCType.m in Sources */, DC9C98C722E264F30021E29F /* CKKSFetchTests.m in Sources */, EB0E1ADA2357627F002B6037 /* CKKSPBFileStorageTests.m in Sources */, DC9C75161E4BCE1800F1CA0D /* CKKSOperationTests.m in Sources */, + DC86122C2408AC190092E93B /* CKKSTests+ItemSyncChoice.m in Sources */, DC8D238D2064649400E163C8 /* CKKSAPSHandlingTests.m in Sources */, EBC1024422EBF93E0083D356 /* CKKSTests+LockStateTracker.m in Sources */, DCB221561E8B08BF001598BC /* server_xpc.m in Sources */, DCA9BC07221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.m in Sources */, DC42690F1E82FD9C002B7110 /* server_security_helpers.m in Sources */, DC4268FE1E820371002B7110 /* server_endpoint.m in Sources */, - DC752F1921C1B69C00216089 /* SFSQLite.m in Sources */, DCFE1C3D1F17EFB5007640C8 /* CKKSConditionTests.m in Sources */, + DCBA6F2924105399009A5187 /* CKKSTests+ForwardCompatibility.m in Sources */, DCCD33C91E3FE95900AA4AD1 /* spi.c in Sources */, DC5B391720C08B38005B09F6 /* SecFramework.c in Sources */, DC9C95971F748D0B000D19E5 /* CKKSServerValidationRecoveryTests.m in Sources */, DC7341FE1F84642C00AB9BDF /* CKKSTLKSharingEncryptionTests.m in Sources */, DC5F35AC1EE0F27900900966 /* server_entitlement_helpers.c in Sources */, DAEE055C1FAD3FC700DF27F3 /* AutoreleaseTest.c in Sources */, + A6C737BB23F37AB00009C930 /* entitlements.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -34636,6 +34700,7 @@ buildActionMask = 2147483647; files = ( 1BB1CAB7232C05BD001D0C71 /* CuttlefishXPCWrapper.m in Sources */, + DC6E02162405DE3900C61335 /* OTModifyUserControllableViewStatusOperation.m in Sources */, 1BB1CAB8232C05BD001D0C71 /* CuttlefishXPCWrapper.h in Sources */, DCE0778021ADEC4B002662FD /* CKKSSerializedKey.m in Sources */, DCE0777F21ADEC07002662FD /* OTAccountMetadataClassC.m in Sources */, @@ -34644,6 +34709,7 @@ 0C00FC86217A980100C8BF00 /* OTLocalCuttlefishReset.m in Sources */, DCAE1DDD2073FDCC00B4F687 /* NSError+UsefulConstructors.m in Sources */, 6C4AEF88218A09E70012C5DA /* CheckV12DevEnabled.m in Sources */, + DCC40B122383786D00402CB9 /* CKKSStates.m in Sources */, DC797E1A1DD3F9A400CC9E42 /* CKKSSQLDatabaseObject.m in Sources */, 6CC1859F1E24E8EB009657D8 /* CKKSRateLimiter.m in Sources */, DCD33D7C220B99CC000A390B /* EscrowRequestController.m in Sources */, @@ -34660,7 +34726,9 @@ DC54DD0F1EA7D9E700108E92 /* CKKSManifestLeafRecord.m in Sources */, DCDCCB901DF7B8D4006E840E /* CKKSItem.m in Sources */, DC1ED8C11DD5197E002BDCFA /* CKKSItemEncrypter.m in Sources */, + DCB55176247F48290009A859 /* CKKSDeleteCKZoneOperation.m in Sources */, 0CDD6F79226E83F6009094C2 /* OTTriggerEscrowUpdateOperation.m in Sources */, + DC0D16072363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.m in Sources */, DC6D2C921DD2835A00BE372D /* CKKSOutgoingQueueEntry.m in Sources */, DC378B3D1DF0CA7200A3DAFA /* CKKSIncomingQueueEntry.m in Sources */, 6C880FCB21C3351400D38D66 /* SecDbBackupMetadataClassKey.m in Sources */, @@ -34678,15 +34746,18 @@ 6C880FC821C3351400D38D66 /* SecDbBackupBag.m in Sources */, 0C87D3D9229326AA007853B5 /* OTEnsureOctagonKeyConsistency.m in Sources */, 6C588D801EAA20AB00D7E322 /* RateLimiter.m in Sources */, + DCB55177247F483D0009A859 /* CKKSCreateCKZoneOperation.m in Sources */, DC8DF6DC212F8A7C007B3FE8 /* OTSOSAdapter.m in Sources */, 0C66046A2134983900BFBBB8 /* OTEstablishOperation.m in Sources */, DC15F7681E67A6F6003B9A40 /* CKKSHealKeyHierarchyOperation.m in Sources */, DCE278DF1ED789EF0083B485 /* CKKSCurrentItemPointer.m in Sources */, + DC061A722462136F0026ADB3 /* CKKSOperationDependencies.m in Sources */, DC3D748E1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.m in Sources */, DCC67E2F20DDC07900A70A31 /* OTPrepareOperation.m in Sources */, DCB41DFC216D5E5B00F219E0 /* OTAccountMetadataClassC+KeychainSupport.m in Sources */, 6C880FCC21C3351400D38D66 /* SecDbBackupRecoverySet.m in Sources */, DCA4D1FF1E552DD50056214F /* CKKSCurrentKeyPointer.m in Sources */, + DC0D16022363A1D6007F0951 /* OTSetCDPBitOperation.m in Sources */, EB7E91212194849900B1FA21 /* SECC2MPMetric.m in Sources */, DA6AA1651FE88AFB004565B0 /* CKKSControlServer.m in Sources */, DCFE1C531F1825F7007640C8 /* CKKSUpdateDeviceStateOperation.m in Sources */, @@ -34706,14 +34777,17 @@ DC762AA01E57A86A00B03A2C /* CKKSRecordHolder.m in Sources */, DC52E7DF1D80BD8700B0A59C /* SOSChangeTracker.c in Sources */, DCD33D94220CFF8A000A390B /* EscrowRequestPerformEscrowEnrollOperation.m in Sources */, + DC947E8524638320005B8669 /* CKKSCheckKeyHierarchyOperation.m in Sources */, DC1DA6681E4555D80094CE7F /* CKKSScanLocalItemsOperation.m in Sources */, 0CC8A9032123AF06005D7F6A /* OTJoinWithVoucherOperation.m in Sources */, + DC061A71246213660026ADB3 /* CKKSLocalResetOperation.m in Sources */, DC18F7711E43E116006B8B43 /* CKKSFetchAllRecordZoneChangesOperation.m in Sources */, DC45D43E22EB619D00CEB6B7 /* OctagonStateMachineObservers.m in Sources */, DC2C5F601F0EB97E00FEBDA7 /* CKKSNotifier.m in Sources */, DC7250382296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.m in Sources */, DC221BAC2267E2A70068DBCF /* OTUpdateTPHOperation.m in Sources */, DC93F02A22387A010072720A /* OTSOSUpdatePreapprovalsOperation.m in Sources */, + DC880F68243D4CC00059806D /* CKKSLogging.m in Sources */, 6C4AEF90218A0C170012C5DA /* SecDbBackupManager.m in Sources */, DC5060ED20E2D88300925005 /* OTCuttlefishContext.m in Sources */, DC0FA6B12291F63F00FE01C4 /* OctagonPendingFlag.m in Sources */, @@ -34738,6 +34812,7 @@ DC52E7CB1D80BCD800B0A59C /* SecItemBackupServer.c in Sources */, 0C2F337220DD64930031A92D /* OTRamping.m in Sources */, DCF12674218A757A000124C6 /* OTLeaveCliqueOperation.m in Sources */, + FC63722F237B5D1C00973738 /* SecItemServer+SWC.m in Sources */, DC52E7CD1D80BCE700B0A59C /* SecItemDataSource.c in Sources */, 0C8FD52521483EF20098E3FB /* OT.m in Sources */, DC9C066B2149DFE400C6F7B8 /* OTAuthKitAdapter.m in Sources */, @@ -34770,9 +34845,11 @@ DCB946B022FCB88500BE4490 /* OTDetermineHSA2AccountStatusOperation.m in Sources */, DCE772672290712F005862B4 /* OctagonCheckTrustStateOperation.m in Sources */, 5A04BAF822973E7F001848A0 /* OTFollowup.m in Sources */, + DCF0C435256347BB007D5A6A /* CKKSMemoryKeyCache.m in Sources */, DCB837321ED5045000015C07 /* CKKSLockStateTracker.m in Sources */, EB80DE162195EDA4005B10FA /* SecC2DeviceInfo.m in Sources */, 47922D4C1FAA7C4A0008F7E0 /* SecDbKeychainSerializedSecretData.m in Sources */, + 6C6AF180221A070A0091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */, DCBDB3B71E57C82300B61300 /* CKKSKeychainView.m in Sources */, DC52E7D61D80BD2800B0A59C /* SecuritydXPC.c in Sources */, 0C4F4DE221153E9E007F7E20 /* OTEpochOperation.m in Sources */, @@ -34780,6 +34857,7 @@ EB0E1ACB2353A702002B6037 /* CKKSPBFileStorage.m in Sources */, DC7A17EF1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.m in Sources */, DC7341F51F8447AB00AB9BDF /* CKKSTLKShareRecord.m in Sources */, + DCA72AE42530D3BD00CCB062 /* CKKSKeychainViewState.m in Sources */, 0C5960811FB369C50095BA29 /* CKKSHealTLKSharesOperation.m in Sources */, DCD33D81220B9DC8000A390B /* OctagonStateMachineHelpers.m in Sources */, DCA4D2171E5684220056214F /* CKKSReencryptOutgoingItemsOperation.m in Sources */, @@ -34800,7 +34878,7 @@ 6C4AEF96218A127F0012C5DA /* SecDbKeychainMetadataKeyStore.m in Sources */, DCFE1C361F17ECE5007640C8 /* CKKSCondition.m in Sources */, EB7E91172194847A00B1FA21 /* SecEventMetric.m in Sources */, - DCEA5D971E3015830089CF55 /* CKKSZone.m in Sources */, + 0C64C0802485B2EF00D84A5D /* OTPreloadOctagonKeysOperation.m in Sources */, DCAB17D22200D26900E1DFCF /* SecEscrowPendingRecord.m in Sources */, DC047082218BB21E0078BDAA /* OTCuttlefishAccountStateHolder.m in Sources */, DC047088218BCEF20078BDAA /* OTOperationDependencies.m in Sources */, @@ -34820,7 +34898,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 48E617211DBEC6BA0098EAAD /* SOSBackupInformation.m in Sources */, DC52E8F11D80C34000B0A59C /* SOSAccount.m in Sources */, DC52E8F31D80C34000B0A59C /* SOSAccountBackup.m in Sources */, DCB332591F478C3C00178C30 /* SOSUserKeygen.m in Sources */, @@ -34888,7 +34965,6 @@ files = ( DCD7EE841F4E46F9007D9804 /* accountCirclesViewsPrint.m in Sources */, 0C0CECA41DA45ED700C22FBC /* recovery_key.m in Sources */, - DC52EC3B1D80CFE900B0A59C /* syncbackup.m in Sources */, DC52EC3A1D80CFE400B0A59C /* keychain_log.m in Sources */, DC52EC391D80CFDF00B0A59C /* secViewDisplay.c in Sources */, DC52EC381D80CFDB00B0A59C /* secToolFileIO.c in Sources */, @@ -34923,7 +34999,6 @@ DC52EC791D80D14D00B0A59C /* sc-45-digestvector.c in Sources */, DC52EC781D80D14800B0A59C /* SOSRegressionUtilities.m in Sources */, DC52EC771D80D14400B0A59C /* sc-130-resignationticket.c in Sources */, - DC52EC761D80D13F00B0A59C /* sc-150-ring.m in Sources */, DC52EC751D80D13B00B0A59C /* sc-42-circlegencount.c in Sources */, DC52EC741D80D13500B0A59C /* SOSTestDataSource.c in Sources */, DC52EC731D80D12E00B0A59C /* sc-20-keynames.m in Sources */, @@ -34992,7 +35067,6 @@ files = ( DC52EDA01D80D4F700B0A59C /* sd-10-policytree.m in Sources */, DC52ED9F1D80D4F200B0A59C /* SOSTransportTestTransports.m in Sources */, - DC52ED9E1D80D4ED00B0A59C /* secd-95-escrow-persistence.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -35011,10 +35085,9 @@ DC52EDF71D80D65700B0A59C /* si-90-emcs.m in Sources */, 483E798F1DC87605005C0008 /* secd-67-prefixedKeyIDs.m in Sources */, 48CC589F1DA5FF2700EBD9DB /* secd-66-account-recovery.m in Sources */, - DC52EDF51D80D62E00B0A59C /* SecdTestKeychainUtilities.c in Sources */, + DC52EDF51D80D62E00B0A59C /* SecdTestKeychainUtilities.m in Sources */, DC52EDF61D80D62E00B0A59C /* SOSTransportTestTransports.m in Sources */, EB9C02481E8A15B40040D3C6 /* secd-37-pairing-initial-sync.m in Sources */, - 0CAD1E5E1E1C5D0600537693 /* secd-95-escrow-persistence.m in Sources */, DC52EDB51D80D5C500B0A59C /* secd-03-corrupted-items.m in Sources */, 0CAD1E5D1E1C5CF900537693 /* secd-80-views-alwayson.m in Sources */, DC52EDB61D80D5C500B0A59C /* secd-04-corrupted-items.m in Sources */, @@ -35023,7 +35096,6 @@ DC52EDBC1D80D5C500B0A59C /* secd-02-upgrade-while-locked.m in Sources */, DC52EDBD1D80D5C500B0A59C /* secd-20-keychain_upgrade.m in Sources */, DC52EDBE1D80D5C500B0A59C /* secd-21-transmogrify.m in Sources */, - DCFAEDD21D99991F005187E4 /* secd-668-ghosts.m in Sources */, DC52EDBF1D80D5C500B0A59C /* secd-30-keychain-upgrade.m in Sources */, DC52EDC11D80D5C500B0A59C /* secd-31-keychain-unreadable.m in Sources */, 0CCDE7171EEB08220021A946 /* secd-156-timers.m in Sources */, @@ -35049,14 +35121,14 @@ DC52EDD31D80D5C500B0A59C /* secd-59-account-cleanup.m in Sources */, EB351540211A79E30097A87C /* secd-33-keychain-backup.m in Sources */, DC52EDD41D80D5C500B0A59C /* secd-60-account-cloud-identity.m in Sources */, - DC52EDD51D80D5C500B0A59C /* secd60-account-cloud-exposure.m in Sources */, + DC52EDD51D80D5C500B0A59C /* secd-60-account-cloud-exposure.m in Sources */, DC52EDD61D80D5C500B0A59C /* secd-61-account-leave-not-in-kansas-anymore.m in Sources */, - 0C78826F20132069002B7475 /* SFSignInAnalytics.m in Sources */, DC52EDD71D80D5C500B0A59C /* secd-62-account-backup.m in Sources */, DC52EDD91D80D5C500B0A59C /* secd-63-account-resurrection.m in Sources */, DC52EDDA1D80D5C500B0A59C /* secd-65-account-retirement-reset.m in Sources */, DCDCC7E31D9B54EE006487E8 /* secd-202-recoverykey.m in Sources */, DC52EDDB1D80D5C500B0A59C /* secd-64-circlereset.m in Sources */, + 0C0821EF2559D4D8006DAD6A /* secd-231-v0Peers.m in Sources */, DC52EDDC1D80D5C500B0A59C /* secd-70-engine.m in Sources */, 0C3C00731EF3636500AB19FE /* secd-155-otr-negotiation-monitor.m in Sources */, 7281E08F1DFD0DBB0021E1B7 /* secd-210-keyinterest.m in Sources */, @@ -35067,6 +35139,7 @@ DC52EDDF1D80D5C500B0A59C /* secd-70-otr-remote.m in Sources */, DC52EDE21D80D5C500B0A59C /* secd-74-engine-beer-servers.m in Sources */, 7281E0901DFD0E0A0021E1B7 /* CKDKVSProxy.m in Sources */, + 487A65F4245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m in Sources */, DC52EDE31D80D5C500B0A59C /* secd-75-engine-views.m in Sources */, DC52EDE61D80D5C500B0A59C /* secd-80-views-basic.m in Sources */, DC52EDE81D80D5C500B0A59C /* secd-81-item-acl-stress.m in Sources */, @@ -35085,46 +35158,30 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DC52EE611D80D79E00B0A59C /* si-71-mobile-store-policy.c in Sources */, - DC52EE601D80D79900B0A59C /* si-74-OTAPKISigner.c in Sources */, D4AD87701E452CE000CA1B7F /* si-68-secmatchissuer.c in Sources */, + D4C88D88262E5DB20006FFB1 /* si-27-cms-parse.m in Sources */, EB6928CA1D9C9E1800062A18 /* rk_01_recoverykey.m in Sources */, D42CDC351DC12FE90090E2C9 /* si-66-smime.c in Sources */, B61577F41F20513C004A3930 /* padding-00-mmcs.c in Sources */, DC0B62291D90974600D43BCB /* si-25-cms-skid.m in Sources */, 09CB49701F2F64E300C8E4DE /* si-44-seckey-fv.m in Sources */, D48BD18D206C45F00075DDC9 /* si-89-cms-hash-agility.m in Sources */, - BE6215BE1DB6E69100961E15 /* si-84-sectrust-allowlist.m in Sources */, D4B6D57C2069D8450099FBEF /* si-34-cms-timestamp.m in Sources */, D4096E031ED5F21C000AC459 /* si-65-cms-cert-policy.c in Sources */, - DC52EE441D80D71900B0A59C /* si-21-sectrust-asr.c in Sources */, D4AA0D9A22FB959600D77FA4 /* si-29-cms-chain-mode.m in Sources */, - DC52EE451D80D71900B0A59C /* si-22-sectrust-iap.c in Sources */, - DC52EE471D80D71900B0A59C /* si-23-sectrust-ocsp.c in Sources */, D48E4E241E42F0620011B4BA /* si-62-csr.m in Sources */, - DC52EE481D80D71900B0A59C /* si-24-sectrust-digicert-malaysia.c in Sources */, - DC52EE491D80D71900B0A59C /* si-24-sectrust-diginotar.c in Sources */, - DC52EE4A1D80D71900B0A59C /* si-24-sectrust-itms.c in Sources */, + D4C573C4255B6A1800AB5D78 /* si-26-cms-apple-signed-samples.m in Sources */, DCE2341820A3D4B8009766A3 /* si-cms-hash-agility-data.c in Sources */, - DC52EE4C1D80D71900B0A59C /* si-24-sectrust-passbook.c in Sources */, - DC52EE4D1D80D71900B0A59C /* si-26-sectrust-copyproperties.c in Sources */, 5E7793751E5F025A0074A2D1 /* si-44-seckey-aks.m in Sources */, - DC52EE4E1D80D71900B0A59C /* si-27-sectrust-exceptions.c in Sources */, - DC52EE4F1D80D71900B0A59C /* si-28-sectrustsettings.m in Sources */, DC52EE531D80D73800B0A59C /* si-44-seckey-gen.m in Sources */, DC52EE541D80D73800B0A59C /* si-44-seckey-rsa.m in Sources */, DC52EE551D80D73800B0A59C /* si-44-seckey-ec.m in Sources */, D4096E011ED5F0B5000AC459 /* si-60-cms.c in Sources */, - D4CFAA7E1E660BB3004746AA /* si-32-sectrust-pinning-required.m in Sources */, - BE9B8B4A202BB4A20081EF87 /* si-88-sectrust-valid.m in Sources */, D48BD194206C47530075DDC9 /* si-35-cms-expiration-time.m in Sources */, DC52EE561D80D73800B0A59C /* si-44-seckey-ies.m in Sources */, - DC52EE571D80D73800B0A59C /* si-67-sectrust-blocklist.c in Sources */, D4096E021ED5F207000AC459 /* si-64-ossl-cms.c in Sources */, 478014541FBF577000C4043D /* si-44-seckey-proxy.m in Sources */, DCD45357209A5BA10086CBFC /* si-cms-signing-identity-p12.c in Sources */, - DC52EE581D80D73800B0A59C /* si-70-sectrust-unified.c in Sources */, - DC52EE5A1D80D73800B0A59C /* si-83-seccertificate-sighashalg.c in Sources */, D47E69401E92F75D002C8CF6 /* si-61-pkcs12.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -35151,6 +35208,7 @@ DC52EE721D80D86400B0A59C /* SecuritydXPC.c in Sources */, DC52EE711D80D85F00B0A59C /* SecECKey.m in Sources */, DC52EE701D80D84700B0A59C /* SecItemConstants.c in Sources */, + 6C22008A244F0760000A4557 /* SecItemRateLimit.m in Sources */, DC52EE6F1D80D83F00B0A59C /* SecPasswordGenerate.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -35202,6 +35260,7 @@ DC5ABDEA1D832E4000CF422C /* authz.c in Sources */, DC5ABDEB1D832E4000CF422C /* verify_cert.c in Sources */, BE64A80022AF010B001209F3 /* trusted_cert_ssl.m in Sources */, + F67B93C3254707E10076CA99 /* fvunlock.m in Sources */, DC5ABDEC1D832E4000CF422C /* access_utils.c in Sources */, DC5ABDED1D832E4000CF422C /* translocate.c in Sources */, ); @@ -35214,6 +35273,7 @@ DC5AC1031D83552000CF422C /* selfServer.cpp in Sources */, DC5AC1041D83552000CF422C /* selfUser.cpp in Sources */, DC5AC0D81D8354CA00CF422C /* main.cpp in Sources */, + 6C75560624212B4400025D78 /* keychainstasherinterface.m in Sources */, DC5AC0D91D8354CA00CF422C /* connection.cpp in Sources */, DC5AC0DA1D8354CA00CF422C /* database.cpp in Sources */, DC5AC0DB1D8354CA00CF422C /* key.cpp in Sources */, @@ -35231,7 +35291,6 @@ DC5AC0E61D8354CA00CF422C /* tokendatabase.cpp in Sources */, DC5AC0E71D8354CA00CF422C /* tokenkey.cpp in Sources */, DC5AC0E81D8354CA00CF422C /* tokenaccess.cpp in Sources */, - DC5AC0E91D8354CA00CF422C /* pcscmonitor.cpp in Sources */, DC5AC0EA1D8354CA00CF422C /* reader.cpp in Sources */, DC5AC0EB1D8354CA00CF422C /* token.cpp in Sources */, DC5AC0EC1D8354CA00CF422C /* tokend.cpp in Sources */, @@ -35358,20 +35417,29 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DCE405C523A04A7F00C4343B /* OctagonTests+CKKSConfiguration.swift in Sources */, 1B8D2D96226E1FA500C94238 /* SetValueTransformer.swift in Sources */, + 0CCC21FC23F33DA900E1FCD0 /* OTICDPRecordContext.m in Sources */, DC5F2BBE2310B941001ADA5D /* OctagonTests+CoreFollowUp.swift in Sources */, DCB468E520EC262C00BA7E5B /* ContainerMap.swift in Sources */, + 0CA1D0B923E9034600021038 /* OctagonTests+EscrowTestVectors.swift in Sources */, 0C4CDE6F22922E550050C499 /* OctagonTests+RecoveryKey.swift in Sources */, EBDE5E0F22BA3DEA00A229C8 /* CKKSMockOctagonAdapter.m in Sources */, DCB468DF20EC25FF00BA7E5B /* Client.swift in Sources */, 0C5824A52286002D009E8C15 /* OctagonTests+HealthCheck.swift in Sources */, + 0C468FFD23C7D4F9006F4582 /* OTEscrowRecord.m in Sources */, DC27C3CE20EAFE9C00F7839C /* CloudKitMockXCTest.m in Sources */, DCB9475821274F9D00ED9272 /* TPHObjcTranslation.m in Sources */, DC27C3CB20EADF3500F7839C /* CloudKitKeychainSyncingMockXCTest.m in Sources */, 0C87D3E4229368BD007853B5 /* OctagonTests+SOS.swift in Sources */, DC27C3C920EADEE700F7839C /* MockCloudKit.m in Sources */, + 0CCC21FD23F33DCE00E1FCD0 /* OTCDPRecoveryInformation.m in Sources */, 0CF70BE0218CF26600EC3515 /* BottledPeer.swift in Sources */, DC99B86B20EACA470065B73B /* spi.c in Sources */, + DC4CD9842372294E00EF55FC /* OctagonTests+Helpers.swift in Sources */, + 0C3C47C924902DA50084B951 /* OTSupportOctagonMessage.m in Sources */, + DCAA209A23AAF8F600DCB594 /* Container_RecoveryKey.swift in Sources */, + DCA7F7EF23A44AA200927989 /* OctagonPolicyTests.swift in Sources */, DCDF03122284E34B008055BA /* OctagonTests+EscrowRecovery.swift in Sources */, DCFF82712162834D00D54B02 /* OctagonTestsXPCConnections.swift in Sources */, DC5BEACD2217509A001681F0 /* OctagonTests+CloudKitAccount.swift in Sources */, @@ -35379,46 +35447,63 @@ DC07090422936DB2002711B9 /* OctagonTests+ErrorHandling.swift in Sources */, DC99B86C20EACA470065B73B /* FakeCuttlefish.swift in Sources */, 0CBEF3432242CA0600015691 /* TestsObjcTranslation.m in Sources */, - 5A04BB0222982733001848A0 /* OTFollowupTests.m in Sources */, + 0C468FFE23C7D4F9006F4582 /* OTEscrowRecordMetadata.m in Sources */, DCB24B45221B901700BE73FE /* CKKSMockSOSPresentAdapter.m in Sources */, + DC33D7BE2374FD0A00A68155 /* OTSponsorToApplicantRound2M2.m in Sources */, 0CE15E31222DF63600B7EAA4 /* RecoverKeySet.swift in Sources */, + 0C3C47C824902DA50084B951 /* OTSupportSOSMessage.m in Sources */, + 0C468FFF23C7D4F9006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */, 0CADDF0721545CF100DF8B06 /* OctagonPairingTests.swift in Sources */, DC99B86D20EACA470065B73B /* SecdWatchdog.m in Sources */, DC26666C21CAC97000F19960 /* OTControlCLI.m in Sources */, DC99B86E20EACA470065B73B /* MockCuttlefish.swift in Sources */, 0CF70BE3218CF2AA00EC3515 /* OTBottle.m in Sources */, DC27C3CA20EADF1700F7839C /* CloudKitKeychainSyncingTestsBase.m in Sources */, + 0C3DF8CA24789D0A009CF03A /* Container_Peers.swift in Sources */, 0CF70BE4218CF2AA00EC3515 /* OTBottleContents.m in Sources */, 0C61F1F92194FC82009566D4 /* OTAuthenticatedCiphertext+SF.m in Sources */, DCB0C291222F5E130083AECB /* CuttlefishErrors.swift in Sources */, DC99B86F20EACA470065B73B /* SecFramework.c in Sources */, + 0CBF883D23AAD9F100652EDD /* OctagonTests+EscrowRecords.swift in Sources */, 0C5258BB21BB128000B32C96 /* FakeSOSControl.m in Sources */, + DC3A9B2723A9D8BD0073ED06 /* Container_BottledPeers.swift in Sources */, DC99B87020EACA470065B73B /* server_endpoint.m in Sources */, 0CD5797A21498F8200C43496 /* OctagonPairingTests+Piggybacking.swift in Sources */, + DC4A73C5235E69D800DB1E6E /* OTApplicantToSponsorRound2M1.m in Sources */, DCAD8F8722C43ECA007C3872 /* Container_MachineIDs.swift in Sources */, + DC03592D235FCCD500F14883 /* KCInitialMessageData.m in Sources */, DC99B87120EACA470065B73B /* server_security_helpers.m in Sources */, 0CF70BE1218CF27600EC3515 /* EscrowKeys.swift in Sources */, DC7F79B622EA4ED4001FB69A /* OctagonTests+CKKS.swift in Sources */, 0CBA047D214C4E4D005B3A2F /* OctagonPairingTests+ProxMultiClients.swift in Sources */, DCF6320821C09DCE0030CCC0 /* CuttlefishAPIHelpers.swift in Sources */, 0CE15E44222DF6A800B7EAA4 /* Recovery.m in Sources */, + DC4415B423610BF40087981C /* OctagonTests+Account.swift in Sources */, DC725030229600C000493D88 /* OctagonTests+Reset.swift in Sources */, 0C3E316B21372FA50093C04B /* OctagonPairingTests+ProximitySetup.swift in Sources */, DC2819B922F8F6FE007829F5 /* OctagonTests+DeviceList.swift in Sources */, 0CF70BE5218CF2AA00EC3515 /* OTPrivateKey.m in Sources */, + DCD68B9E255A149300C2A1BA /* CKKSMockLockStateProvider.m in Sources */, BECFA45920FEB90900B11002 /* Policy.swift in Sources */, DC99B87220EACA470065B73B /* Cuttlefish.pb.swift in Sources */, 0CF70BE2218CF2AA00EC3515 /* OTAuthenticatedCiphertext.m in Sources */, DCB41E01216D5FE500F219E0 /* OctagonDataPersistenceTests.swift in Sources */, DC85687E2284E7860088D3EF /* OctagonTestMocks.swift in Sources */, + DC0DE87123750340006E2EAE /* OTPairingMessage.m in Sources */, + DCD689DF255A0AF600C2A1BA /* OctagonStateMachineTests.swift in Sources */, DC99B87320EACA470065B73B /* Decrypter.swift in Sources */, DC99B87420EACA470065B73B /* server_entitlement_helpers.c in Sources */, DC99B87520EACA470065B73B /* TrustedPeersHelper.xcdatamodeld in Sources */, + DC9978B92404AA3200A5EE2F /* Container_UserSync.swift in Sources */, 0CE15E2D222DF63600B7EAA4 /* RecoveryKey.swift in Sources */, DC27C3C120EAD9C300F7839C /* OctagonTests.swift in Sources */, 0CE15E3F222DF6A800B7EAA4 /* OTRecovery.m in Sources */, + 0C0CB73A23AD715A0020C6BF /* Container_EscrowRecords.swift in Sources */, DCB9475A2127534C00ED9272 /* OctagonTests+SOSUpgrade.swift in Sources */, + DC7F6A7D233D7FAC00DF5769 /* OctagonTests+ForwardCompatibility.swift in Sources */, DC99B87720EACA470065B73B /* ContainerSync.swift in Sources */, + DC33D7BD2374FD0500A68155 /* OTSponsorToApplicantRound1M2.m in Sources */, + 0CCC21FE23F33DD400E1FCD0 /* OTEscrowAuthenticationInformation.m in Sources */, 0C61F1F62194FC79009566D4 /* OTPrivateKey+SF.m in Sources */, DC391FA821C04DAE00772585 /* OctagonPeerKeys.swift in Sources */, DC99B87820EACA470065B73B /* Container.swift in Sources */, @@ -35538,6 +35623,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6C2D463D24C88AA10015C3C9 /* LegacyAPICounts.m in Sources */, DCB3433D1D8A32A20054D16E /* ACL.cpp in Sources */, DCB3433B1D8A32A20054D16E /* Access.cpp in Sources */, DCB3436A1D8A32A20054D16E /* CCallbackMgr.cp in Sources */, @@ -35564,7 +35650,6 @@ DCB342FB1D8A32A20054D16E /* SecBase.cpp in Sources */, DCB3435B1D8A32A20054D16E /* SecCFTypes.cpp in Sources */, DCB342FD1D8A32A20054D16E /* SecCertificate.cpp in Sources */, - DCB342FE1D8A32A20054D16E /* SecCertificateBundle.cpp in Sources */, DCB343921D8A32A20054D16E /* SecExport.cpp in Sources */, DCB343931D8A32A20054D16E /* SecExternalRep.cpp in Sources */, DCB343371D8A32A20054D16E /* SecFDERecoveryAsymmetricCrypto.cpp in Sources */, @@ -35582,7 +35667,6 @@ DCB343021D8A32A20054D16E /* SecItemConstants.c in Sources */, DCB343041D8A32A20054D16E /* SecKey.cpp in Sources */, DCB343051D8A32A20054D16E /* SecKeychain.cpp in Sources */, - DCB3435D1D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp in Sources */, DCB343061D8A32A20054D16E /* SecKeychainItem.cpp in Sources */, DCB343071D8A32A20054D16E /* SecKeychainItemExtendedAttributes.cpp in Sources */, DCB343081D8A32A20054D16E /* SecKeychainSearch.cpp in Sources */, @@ -35659,11 +35743,11 @@ DCB3449B1D8A35270054D16E /* kc-30-xara.c in Sources */, DCB344A01D8A35270054D16E /* kc-40-seckey.m in Sources */, DCB344A11D8A35270054D16E /* kc-41-sececkey.m in Sources */, - DCB344A31D8A35270054D16E /* kc-42-trust-revocation.c in Sources */, DCB344A21D8A35270054D16E /* kc-43-seckey-interop.m in Sources */, - DCB344A41D8A35270054D16E /* si-20-sectrust-provisioning.c in Sources */, + DCB344A41D8A35270054D16E /* si-20-certificate-copy-values.c in Sources */, DCB344A61D8A35270054D16E /* si-33-keychain-backup.c in Sources */, DCB344A71D8A35270054D16E /* si-34-one-true-keychain.c in Sources */, + BEE2954325818E0400CD1294 /* si-40-identity-tests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -35682,6 +35766,7 @@ DCAB17CE21FFF75B00E1DFCF /* MockSynchronousEscrowServer.m in Sources */, DCBF4ABB21FFC82100539F0A /* SecFramework.c in Sources */, DCBF4ABE21FFC82100539F0A /* server_entitlement_helpers.c in Sources */, + A6C737C123F37AC00009C930 /* entitlements.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -35697,6 +35782,7 @@ DCC78EE41D808B1B00865A7C /* SecCFAllocator.c in Sources */, DCC78EE31D808B1300865A7C /* SecCMS.c in Sources */, BEEB47D91EA189F5004AA5C6 /* SecTrustStatusCodes.c in Sources */, + 6C220088244F075E000A4557 /* SecItemRateLimit.m in Sources */, DCC78EE21D808B0E00865A7C /* SecCTKKey.m in Sources */, DCC78EE11D808B0900865A7C /* SecCertificate.c in Sources */, DC4269041E82EDAC002B7110 /* SecItem.m in Sources */, @@ -35780,6 +35866,7 @@ DCD068201D8CDF7E007602F1 /* SecRequirement.cpp in Sources */, DCD0681D1D8CDF7E007602F1 /* SecStaticCode.cpp in Sources */, 1F631C5622387FFE005920D8 /* legacydevid.cpp in Sources */, + A6C737BA23F37A4B0009C930 /* entitlements.c in Sources */, DCD0682C1D8CDF7E007602F1 /* StaticCode.cpp in Sources */, DCD0693D1D8CDFFF007602F1 /* String.cpp in Sources */, DCD0693E1D8CDFFF007602F1 /* Token.cpp in Sources */, @@ -35993,6 +36080,8 @@ DC3AA2852097E22A007CA68A /* codesign.c in Sources */, DC8506AD2097EEBC00C712EC /* sos.m in Sources */, DCE4E6931D7A37FA00AFB96E /* NSFileHandle+Formatting.m in Sources */, + D4353ABF2526BE5D002E72F7 /* trust_config.m in Sources */, + BE57B11A2509E1000045B7FD /* ca_revocation_additions.m in Sources */, DC3AA2892097E23A007CA68A /* keychain_find.m in Sources */, DC3AA2792097DF71007CA68A /* readline.c in Sources */, DC3AA2822097E218007CA68A /* add_internet_password.c in Sources */, @@ -36013,7 +36102,6 @@ buildActionMask = 2147483647; files = ( DCE4E7B51D7A43FF00AFB96E /* main.m in Sources */, - DCE4E7B61D7A440A00AFB96E /* bc-10-knife-on-bread.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -36022,7 +36110,6 @@ buildActionMask = 2147483647; files = ( DCE4E7E21D7A4B7F00AFB96E /* main.c in Sources */, - DCE4E7DF1D7A4B4C00AFB96E /* bc-10-knife-on-bread.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -36064,6 +36151,7 @@ DCE4E8C31D7F353900AFB96E /* session.c in Sources */, DCE4E8BC1D7F353900AFB96E /* engine.c in Sources */, DCE4E8C41D7F353900AFB96E /* connection.c in Sources */, + F681C3AB2386B8C30083F22C /* PreloginUserDb.m in Sources */, DCE4E8C11D7F353900AFB96E /* rule.c in Sources */, DCE4E8C01D7F353900AFB96E /* process.c in Sources */, DCE4E8B31D7F353900AFB96E /* agent.c in Sources */, @@ -36111,18 +36199,21 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0C0203E623A857C1005D0A68 /* OTEscrowRecord.proto in Sources */, + BE7B8E132415579900E1CF4F /* SecSharedCredential.m in Sources */, EBDCC002233DD45700806566 /* MockAKSRefKey.proto in Sources */, 0CE15E39222DF67800B7EAA4 /* OTRecovery.proto in Sources */, + 6C6AF17A221A06790091CE0A /* SecDbKeychainSerializedMetadataKey.proto in Sources */, DCE0775621ADD665002662FD /* OTPrivateKey.proto in Sources */, DCE0775321ADD65E002662FD /* OTAuthenticatedCiphertext.proto in Sources */, DCE0775521ADD663002662FD /* OTBottleContents.proto in Sources */, DCE0775421ADD661002662FD /* OTBottle.proto in Sources */, DCF216DE21ADD5F90029CCC1 /* CKKSSerializedKey.proto in Sources */, + DCA992AD2400BB99007959AF /* TPPBAncientEpoch.proto in Sources */, DCF216DF21ADD5FB0029CCC1 /* OTPairingMessage.proto in Sources */, DCF216E121ADD6060029CCC1 /* TPPBVoucher.proto in Sources */, DCF216E021ADD5FD0029CCC1 /* OTAccountMetadataClassC.proto in Sources */, DCE0774721ADD63A002662FD /* TPPBDispositionEntry.proto in Sources */, - DCE0774821ADD63C002662FD /* TPPBAncientEpoch.proto in Sources */, DCE0774621ADD638002662FD /* TPPBDisposition.proto in Sources */, DCE0774921ADD63E002662FD /* TPPBPolicyProhibits.proto in Sources */, DCE0774A21ADD640002662FD /* TPPBUnknownMachineID.proto in Sources */, @@ -36134,6 +36225,7 @@ 5A47FFB3228F5E5500F781B8 /* KCInitialMessageData.proto in Sources */, DCE0775021ADD655002662FD /* TPPBPolicyModelToCategory.proto in Sources */, DCE0775121ADD658002662FD /* TPPBPolicyIntroducersByCategory.proto in Sources */, + 0C0D920C23BFEAB30070A68C /* OTCDPRecoveryInformation.proto in Sources */, DCE0774F21ADD651002662FD /* TPPBPolicyCategoriesByView.proto in Sources */, DC88466B22373A5E00738068 /* TPPBDictionaryMatchingRule.proto in Sources */, DCE0775221ADD65A002662FD /* TPPBPolicyRedaction.proto in Sources */, @@ -36422,10 +36514,10 @@ files = ( EB413B801E663AEB00592085 /* PairingChannel.m in Sources */, 0CB72D9E21E42FCF00D8BC9B /* OTPairingMessage.m in Sources */, + 0C3C47C624902D960084B951 /* OTSupportOctagonMessage.m in Sources */, 0CB72DA121E42FCF00D8BC9B /* OTSponsorToApplicantRound2M2.m in Sources */, E7F480151C73980D00390FDB /* KCJoiningRequestSecretSession.m in Sources */, E7F480331C73FC4C00390FDB /* KCAESGCMDuplexSession.m in Sources */, - 0CB72D9F21E42FCF00D8BC9B /* OTSOSMessage.m in Sources */, DC6063B221B09AB200069B82 /* KCJoiningRequestCircleSession.m in Sources */, E794BB001C7598F900339A0F /* KCJoiningMessages.m in Sources */, 5A47FFB9228F5F2A00F781B8 /* KCInitialMessageData.m in Sources */, @@ -36435,6 +36527,7 @@ E7F482AC1C7558F700390FDB /* KCJoiningAcceptSession.m in Sources */, E71454F01C741E0800B5B20B /* KCError.m in Sources */, E772FD471CC15EFA00D63E41 /* NSData+SecRandom.m in Sources */, + 0C3C47C724902D960084B951 /* OTSupportSOSMessage.m in Sources */, 0CB72D9D21E42FCF00D8BC9B /* OTApplicantToSponsorRound2M1.m in Sources */, E7F482AA1C7554FB00390FDB /* NSError+KCCreationHelpers.m in Sources */, E75C0E831C6FC31D00E6953B /* KCSRPContext.m in Sources */, @@ -36448,6 +36541,7 @@ E7F4809C1C74E85200390FDB /* KCDerTest.m in Sources */, E7D848051C6BEFCD0025BB44 /* KCSRPTests.m in Sources */, E7F4809E1C74E86D00390FDB /* KCAESGCMTest.m in Sources */, + 52DA3C7123C7E63600FEEDFF /* KCTLKRequestTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -36513,31 +36607,19 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6C32BB9920EAE6B00042DF59 /* LocalKeychainAnalytics.m in Sources */, EB1E069D211E16260088F0B1 /* mockaksxcbase.m in Sources */, - 0CC3771320A222BC00B58D2D /* SFSignInAnalytics.m in Sources */, EB49B2DB202DF20F003F34A0 /* spi.c in Sources */, EB49B2D7202DF1F7003F34A0 /* server_endpoint.m in Sources */, - EBC73F2020993F8600AE3350 /* SFAnalyticsSQLiteStore.m in Sources */, - EBC73F2720993FC900AE3350 /* SFAnalyticsMultiSampler.m in Sources */, EB49B2D8202DF1F7003F34A0 /* server_xpc.m in Sources */, EB49B2D9202DF1F7003F34A0 /* server_security_helpers.m in Sources */, - EBC73F2B2099785900AE3350 /* SFObjCType.m in Sources */, 480ADDB22155A0CE00318FC6 /* SOSAnalytics.m in Sources */, - EB627A79233E375A00F32437 /* MockAKSOptionalParameters.proto in Sources */, + A6C737C023F37AB90009C930 /* entitlements.c in Sources */, EB49B2E0202DF5D7003F34A0 /* server_entitlement_helpers.c in Sources */, - 5A061196229ED6E8006AF14A /* NSDate+SFAnalytics.m in Sources */, - EBC73F2A20996AD400AE3350 /* SFSQLiteStatement.m in Sources */, EB6667C7204CD69F000B404F /* testPlistDER.m in Sources */, - EBC73F29209966AF00AE3350 /* SFSQLite.m in Sources */, EB49B2D5202DF1D8003F34A0 /* SecTask.c in Sources */, EB49B2D3202DF1AC003F34A0 /* SecdWatchdog.m in Sources */, EB49B2B1202D8780003F34A0 /* mockaksKeychain.m in Sources */, EB1E069F211E17C00088F0B1 /* mockaksWatchDog.m in Sources */, - EB49B2D1202DF15F003F34A0 /* SFAnalyticsActivityTracker.m in Sources */, - EB49B2D0202DF14D003F34A0 /* SFAnalytics.m in Sources */, - EBC73F2820993FDA00AE3350 /* SFAnalyticsSampler.m in Sources */, - EBDCC001233DD3E000806566 /* MockAKSRefKey.proto in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -36568,6 +36650,7 @@ EB6952A4223B75C300F02C1C /* server_xpc.m in Sources */, EB6952A5223B75C300F02C1C /* SecDbKeychainSerializedItemV7.m in Sources */, EB6952A6223B75C300F02C1C /* SecDbQuery.c in Sources */, + 6C2138C4225183FE007DEDD3 /* SecDbKeychainSerializedMetadataKey.m in Sources */, EB6952A7223B75C300F02C1C /* SecuritydXPC.c in Sources */, EB6952A8223B75C300F02C1C /* server_endpoint.m in Sources */, EB6952A9223B75C300F02C1C /* SecDbKeychainItemV7.m in Sources */, @@ -36607,6 +36690,7 @@ EB89086C21F17D3C00F0DDDB /* server_security_helpers.m in Sources */, EB8908B021F18D7B00F0DDDB /* SecDbKeychainSerializedMetadata.m in Sources */, EB89086D21F17D3C00F0DDDB /* server_xpc.m in Sources */, + 6C6AF181221A070C0091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */, EB8908B221F18E1400F0DDDB /* SecDbKeychainSerializedItemV7.m in Sources */, EB8908A821F1886100F0DDDB /* SecDbQuery.c in Sources */, EB8908AD21F18CEF00F0DDDB /* SecuritydXPC.c in Sources */, @@ -36631,6 +36715,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + EBAFC9A82551C26F0034B78D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EBAFC9AF2551C2700034B78D /* legacyCodeRegressions.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; EBB839A11E29665D00853BAC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -36695,6 +36787,16 @@ target = DC0BCC211D8C684F00070CB0 /* utilities */; targetProxy = 0C10C93B1DD548BD000602A8 /* PBXContainerItemProxy */; }; + 0C2B36C323C42EBC00000718 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */; + targetProxy = 0C2B36C223C42EBC00000718 /* PBXContainerItemProxy */; + }; + 0C2B36C523C42EC800000718 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */; + targetProxy = 0C2B36C423C42EC800000718 /* PBXContainerItemProxy */; + }; 0C2BCBBC1D0640B200ED7A2F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 0C2BCBA81D06401F00ED7A2F /* dtlsEchoClient */; @@ -36705,15 +36807,15 @@ target = 0C2BCBBD1D0648D100ED7A2F /* dtlsEchoServer */; targetProxy = 0C2BCBD01D0648FA00ED7A2F /* PBXContainerItemProxy */; }; - 0C3E2EA92073F5C400F5B95B /* PBXTargetDependency */ = { + 0C65BB4D23C3F31B0063D2B7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 4C32C0AE0A4975F6002891BD /* Security_ios */; - targetProxy = 0C3E2EA82073F5C400F5B95B /* PBXContainerItemProxy */; + target = 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */; + targetProxy = 0C65BB4C23C3F31B0063D2B7 /* PBXContainerItemProxy */; }; - 0C5663EE20BE2E1A0035F362 /* PBXTargetDependency */ = { + 0C65BB4F23C3F3270063D2B7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DC0BCC211D8C684F00070CB0 /* utilities */; - targetProxy = 0C5663ED20BE2E1A0035F362 /* PBXContainerItemProxy */; + target = 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */; + targetProxy = 0C65BB4E23C3F3270063D2B7 /* PBXContainerItemProxy */; }; 0C78CCE51FCC97E7008B4B24 /* PBXTargetDependency */ = { isa = PBXTargetDependency; @@ -36725,6 +36827,16 @@ target = 0C8BBEFD1FCB446400580909 /* otctl */; targetProxy = 0C78CCE61FCC97F1008B4B24 /* PBXContainerItemProxy */; }; + 0C7EB14D23F3D13C0089097B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; + targetProxy = 0C7EB14C23F3D13C0089097B /* PBXContainerItemProxy */; + }; + 0C7EB14F23F3D1480089097B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC0BCC211D8C684F00070CB0 /* utilities */; + targetProxy = 0C7EB14E23F3D1480089097B /* PBXContainerItemProxy */; + }; 0C85DFD81FB38BB6000343A7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC8834011D8A218F00CE0ACA /* ASN1 */; @@ -36750,16 +36862,51 @@ target = DCC78EA81D8088E200865A7C /* security */; targetProxy = 0C85DFE11FB38BB6000343A7 /* PBXContainerItemProxy */; }; - 0C9AEEBA20783FE000BF6237 /* PBXTargetDependency */ = { + 0CA378E923876E0900090B7E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DC1789031D77980500B50D50 /* Security_osx */; - targetProxy = 0C9AEEB920783FE000BF6237 /* PBXContainerItemProxy */; + target = 0CA378E123876DD100090B7E /* reset_account */; + targetProxy = 0CA378E823876E0900090B7E /* PBXContainerItemProxy */; + }; + 0CA378EB23876E1000090B7E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CA378E123876DD100090B7E /* reset_account */; + targetProxy = 0CA378EA23876E1000090B7E /* PBXContainerItemProxy */; }; 0CC593F82299EDFC006C34B5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; targetProxy = 0CC593F72299EDFC006C34B5 /* PBXContainerItemProxy */; }; + 0CCC22AB23F38B0600E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; + targetProxy = 0CCC22AA23F38B0600E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22AD23F38B0E00E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; + targetProxy = 0CCC22AC23F38B0E00E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22CE23F39A6300E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */; + targetProxy = 0CCC22CD23F39A6300E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22D023F39A6A00E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */; + targetProxy = 0CCC22CF23F39A6A00E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22D223F39A7500E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */; + targetProxy = 0CCC22D123F39A7500E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22D423F39A7C00E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */; + targetProxy = 0CCC22D323F39A7C00E1FCD0 /* PBXContainerItemProxy */; + }; 0CF09210219649DB002B0AEE /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 5346480017331E1100FE9172 /* KeychainSyncAccountNotification */; @@ -36800,6 +36947,16 @@ target = DC0BCC211D8C684F00070CB0 /* utilities */; targetProxy = 3DD258A1204B7DA800F5DA78 /* PBXContainerItemProxy */; }; + 3E4D531F2531185D00B124B3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3E4D49B32531170600B124B3 /* secsecstaticcodeapitest */; + targetProxy = 3E4D531E2531185D00B124B3 /* PBXContainerItemProxy */; + }; + 3E88361D24F08F5400E9F4D6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3E88360824F068EF00E9F4D6 /* secseccodeapitest */; + targetProxy = 3E88361C24F08F5400E9F4D6 /* PBXContainerItemProxy */; + }; 438169E71B4EE4B300C54D58 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4381690B1B4EDCBD00C54D58 /* SOSCCAuthPlugin */; @@ -36845,31 +37002,11 @@ target = 4771D971209A755800BA9772 /* KeychainDataclassOwner */; targetProxy = 4771D981209A76B100BA9772 /* PBXContainerItemProxy */; }; - 478D426D1FD72A8100CAB645 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52EDA61D80D58400B0A59C /* secdRegressions */; - targetProxy = 478D426E1FD72A8100CAB645 /* PBXContainerItemProxy */; - }; - 478D426F1FD72A8100CAB645 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC0BCBD91D8C648C00070CB0 /* regressionBase */; - targetProxy = 478D42701FD72A8100CAB645 /* PBXContainerItemProxy */; - }; - 478D42731FD72A8100CAB645 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCC78EA81D8088E200865A7C /* security */; - targetProxy = 478D42741FD72A8100CAB645 /* PBXContainerItemProxy */; - }; 47A6FC6A206B461700BD6C54 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; targetProxy = 47A6FC69206B461700BD6C54 /* PBXContainerItemProxy */; }; - 47A6FC6C206B462400BD6C54 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; - targetProxy = 47A6FC6B206B462400BD6C54 /* PBXContainerItemProxy */; - }; 47C2F18C2059CBEA0062DE30 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 47C2F1822059CB680062DE30 /* KeychainResources */; @@ -36895,11 +37032,6 @@ target = DC1789031D77980500B50D50 /* Security_osx */; targetProxy = 47C51B8A1EEA657D0032D9E5 /* PBXContainerItemProxy */; }; - 47D991D020407F7E0078CAE2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4727FBB61F9918580003AE36 /* secdxctests_ios */; - targetProxy = 47D991CF20407F7E0078CAE2 /* PBXContainerItemProxy */; - }; 47DE88CE1FA7AD6200DD3254 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DCC78EA81D8088E200865A7C /* security */; @@ -36935,81 +37067,81 @@ target = 5346480017331E1100FE9172 /* KeychainSyncAccountNotification */; targetProxy = 5346481A17331ED800FE9172 /* PBXContainerItemProxy */; }; + 5AAE383623D261CF0025CF9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5A442F81233C330F00918373 /* experimentTool */; + targetProxy = 5AAE383523D261CF0025CF9E /* PBXContainerItemProxy */; + }; + 6C14CA0423C4F6830097B572 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4718AE2E205B39C40068EC3F /* libsecurityd_bridge */; + targetProxy = 6C14CA0323C4F6830097B572 /* PBXContainerItemProxy */; + }; + 6C16258123C4FFC40086A0FF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D4ADA3181E2B41670031CEA3 /* libtrustd */; + targetProxy = 6C16258023C4FFC40086A0FF /* PBXContainerItemProxy */; + }; + 6C16258423C4FFD40086A0FF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; + targetProxy = 6C16258323C4FFD40086A0FF /* PBXContainerItemProxy */; + }; + 6C16258623C4FFD40086A0FF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; + targetProxy = 6C16258523C4FFD40086A0FF /* PBXContainerItemProxy */; + }; + 6C2045F82424BC4400F9461D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6C2045E92424BA7E00F9461D /* KeychainStasher */; + targetProxy = 6C2045F72424BC4400F9461D /* PBXContainerItemProxy */; + }; + 6C2D797322C06CEB00C3CE32 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6C39234421F13E4D00D018AD /* SecDbBackupTests */; + targetProxy = 6C2D797222C06CEB00C3CE32 /* PBXContainerItemProxy */; + }; + 6C2D797522C06CEF00C3CE32 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4727FBB61F9918580003AE36 /* secdxctests */; + targetProxy = 6C2D797422C06CEF00C3CE32 /* PBXContainerItemProxy */; + }; 6C4AA1AA2228B640006FA945 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */; targetProxy = 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */; }; - 6C8FF4B6224C1A9800E5C812 /* PBXTargetDependency */ = { + 6C61D3E8242A29BA008AB9BB /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = BEF88C271EAFFC3F00357577 /* TrustedPeers */; - targetProxy = 6C8FF4B5224C1A9800E5C812 /* PBXContainerItemProxy */; + target = 6C963280242A279B00C53CE2 /* stashtester */; + targetProxy = 6C61D3E7242A29BA008AB9BB /* PBXContainerItemProxy */; }; - 6C98082F1E788AEB00E70590 /* PBXTargetDependency */ = { + 6C7BE2AA23C3DD64003BB2CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DC8834011D8A218F00CE0ACA /* ASN1 */; - targetProxy = 6C9808301E788AEB00E70590 /* PBXContainerItemProxy */; + target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; + targetProxy = 6C7BE2AB23C3DD64003BB2CA /* PBXContainerItemProxy */; }; - 6C9808311E788AEB00E70590 /* PBXTargetDependency */ = { + 6C7BE2AC23C3DD64003BB2CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC0BCC211D8C684F00070CB0 /* utilities */; - targetProxy = 6C9808321E788AEB00E70590 /* PBXContainerItemProxy */; + targetProxy = 6C7BE2AD23C3DD64003BB2CA /* PBXContainerItemProxy */; }; - 6C9808351E788AEB00E70590 /* PBXTargetDependency */ = { + 6C7BE2EA23C3DD9C003BB2CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; - targetProxy = 6C9808361E788AEB00E70590 /* PBXContainerItemProxy */; - }; - 6C9808371E788AEB00E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; - targetProxy = 6C9808381E788AEB00E70590 /* PBXContainerItemProxy */; - }; - 6C9808391E788AEB00E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCC78EA81D8088E200865A7C /* security */; - targetProxy = 6C98083A1E788AEB00E70590 /* PBXContainerItemProxy */; - }; - 6C98086B1E788AFD00E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC8834011D8A218F00CE0ACA /* ASN1 */; - targetProxy = 6C98086C1E788AFD00E70590 /* PBXContainerItemProxy */; - }; - 6C98086D1E788AFD00E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC0BCC211D8C684F00070CB0 /* utilities */; - targetProxy = 6C98086E1E788AFD00E70590 /* PBXContainerItemProxy */; - }; - 6C9808711E788AFD00E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; - targetProxy = 6C9808721E788AFD00E70590 /* PBXContainerItemProxy */; - }; - 6C9808731E788AFD00E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; - targetProxy = 6C9808741E788AFD00E70590 /* PBXContainerItemProxy */; - }; - 6C9808751E788AFD00E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCC78EA81D8088E200865A7C /* security */; - targetProxy = 6C9808761E788AFD00E70590 /* PBXContainerItemProxy */; - }; - 6C9808A01E788B9400E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */; - targetProxy = 6C98089F1E788B9400E70590 /* PBXContainerItemProxy */; - }; - 6C9808A41E788CB100E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6CF4A0DF1E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */; - targetProxy = 6C9808A31E788CB100E70590 /* PBXContainerItemProxy */; + target = 6C7BE2A923C3DD64003BB2CA /* securitytool_bridge */; + targetProxy = 6C7BE2E923C3DD9C003BB2CA /* PBXContainerItemProxy */; }; 6C9A49B21FAB647D00239D58 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC0BCC211D8C684F00070CB0 /* utilities */; targetProxy = 6C9A49B11FAB647D00239D58 /* PBXContainerItemProxy */; }; + 6CA9690D24ACC5C100C08B5E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC0BCC211D8C684F00070CB0 /* utilities */; + targetProxy = 6CA9690C24ACC5C100C08B5E /* PBXContainerItemProxy */; + }; 6CAA8D3D1F8431BC007B6E03 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 6CAA8D1F1F842FB3007B6E03 /* securityuploadd */; @@ -37020,6 +37152,56 @@ target = 6CAA8D1F1F842FB3007B6E03 /* securityuploadd */; targetProxy = 6CAA8D3E1F8431C9007B6E03 /* PBXContainerItemProxy */; }; + 6CC638E7226695B900E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; + targetProxy = 6CC638E6226695B900E5DB0B /* PBXContainerItemProxy */; + }; + 6CC638E9226695B900E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; + targetProxy = 6CC638E8226695B900E5DB0B /* PBXContainerItemProxy */; + }; + 6CC638EB226695C300E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; + targetProxy = 6CC638EA226695C300E5DB0B /* PBXContainerItemProxy */; + }; + 6CC638ED226695C300E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; + targetProxy = 6CC638EC226695C300E5DB0B /* PBXContainerItemProxy */; + }; + 6CC638FE2266AE0A00E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4727FBB61F9918580003AE36 /* secdxctests */; + targetProxy = 6CC638FD2266AE0A00E5DB0B /* PBXContainerItemProxy */; + }; + 6CC639002266AE0A00E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6C39234421F13E4D00D018AD /* SecDbBackupTests */; + targetProxy = 6CC638FF2266AE0A00E5DB0B /* PBXContainerItemProxy */; + }; + 6CE2AEAB22B2C1BE00C96AE7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp */; + targetProxy = 6CE2AEAA22B2C1BE00C96AE7 /* PBXContainerItemProxy */; + }; + 6CE2AEAD22B2C1C300C96AE7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp */; + targetProxy = 6CE2AEAC22B2C1C300C96AE7 /* PBXContainerItemProxy */; + }; + 6CF33CA62387156600D1E75D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4727FBB61F9918580003AE36 /* secdxctests */; + targetProxy = 6CF33CA52387156600D1E75D /* PBXContainerItemProxy */; + }; + 6CF33CA82387157200D1E75D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4727FBB61F9918580003AE36 /* secdxctests */; + targetProxy = 6CF33CA72387157200D1E75D /* PBXContainerItemProxy */; + }; 873C14B221540FED003C9C00 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC0BCC211D8C684F00070CB0 /* utilities */; @@ -37050,6 +37232,11 @@ target = 5346480017331E1100FE9172 /* KeychainSyncAccountNotification */; targetProxy = 87EDC3B12141BBD5007B0E64 /* PBXContainerItemProxy */; }; + A69560602580540F00BDF83F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCD067561D8CDCF3007602F1 /* codesigning_DTrace */; + targetProxy = A695605F2580540F00BDF83F /* PBXContainerItemProxy */; + }; ACBAF6FE1E941E090007BA2F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = ACBAF6991E9417F40007BA2F /* security_transform_regressions */; @@ -37155,6 +37342,11 @@ target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; targetProxy = D437C33021EBF8A000DD1E06 /* PBXContainerItemProxy */; }; + D445C1F2258C147A0019858E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D445B30B258C07FC0019858E /* trustdFileHelper */; + targetProxy = D445C1F1258C147A0019858E /* PBXContainerItemProxy */; + }; D453A4A52122236D00850A26 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = D4ADA3181E2B41670031CEA3 /* libtrustd */; @@ -37300,11 +37492,6 @@ target = 6CCDF7831E3C25FA003F2555 /* KeychainEntitledTestRunner */; targetProxy = D45D8F812224DBE300D6C124 /* PBXContainerItemProxy */; }; - D45D8F842224DBEF00D6C124 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6C9808681E788AFD00E70590 /* CKKSCloudKitTests_ios */; - targetProxy = D45D8F832224DBEF00D6C124 /* PBXContainerItemProxy */; - }; D45D8F862224DBF800D6C124 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC3502B41E0208BE00BC0587 /* CKKSTests */; @@ -37410,11 +37597,6 @@ target = BEF88C2F1EAFFC3F00357577 /* TrustedPeersTests */; targetProxy = D477EE8021ED48DF00C9AAFF /* PBXContainerItemProxy */; }; - D477EE8321ED48E800C9AAFF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 478D426C1FD72A8100CAB645 /* secdxctests_mac */; - targetProxy = D477EE8221ED48E800C9AAFF /* PBXContainerItemProxy */; - }; D4794E6B21222E72007C6725 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC8834011D8A218F00CE0ACA /* ASN1 */; @@ -37445,16 +37627,6 @@ target = DC3502B41E0208BE00BC0587 /* CKKSTests */; targetProxy = D4A763D82224BD990063B2B9 /* PBXContainerItemProxy */; }; - D4A763DB2224BDAB0063B2B9 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6C98082C1E788AEB00E70590 /* CKKSCloudKitTests_mac */; - targetProxy = D4A763DA2224BDAB0063B2B9 /* PBXContainerItemProxy */; - }; - D4A763DD2224BDCC0063B2B9 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */; - targetProxy = D4A763DC2224BDCC0063B2B9 /* PBXContainerItemProxy */; - }; D4A763DF2224BDDC0063B2B9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */; @@ -37650,16 +37822,6 @@ target = 47702B2D1E5F492C00B29577 /* seckeychainnetworkextensionunauthorizedaccesstest */; targetProxy = D4E0E9732224DE8200A802E0 /* PBXContainerItemProxy */; }; - D4E0E9762224DE9100A802E0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4727FBB61F9918580003AE36 /* secdxctests_ios */; - targetProxy = D4E0E9752224DE9100A802E0 /* PBXContainerItemProxy */; - }; - D4E0E97A2224DEE600A802E0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6CF4A0DF1E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */; - targetProxy = D4E0E9792224DEE600A802E0 /* PBXContainerItemProxy */; - }; D4E0E97C2224DF0300A802E0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4CB740A20A47567C00D641BB /* securitytool_ios */; @@ -37775,11 +37937,6 @@ target = 47702B2D1E5F492C00B29577 /* seckeychainnetworkextensionunauthorizedaccesstest */; targetProxy = D4E0E9A92224DFDD00A802E0 /* PBXContainerItemProxy */; }; - D4E0E9AC2224DFEB00A802E0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4727FBB61F9918580003AE36 /* secdxctests_ios */; - targetProxy = D4E0E9AB2224DFEB00A802E0 /* PBXContainerItemProxy */; - }; D4E0E9AE2224E00600A802E0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4CB740A20A47567C00D641BB /* securitytool_ios */; @@ -38375,21 +38532,6 @@ target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; targetProxy = DC311E662124A9D2002F5EAE /* PBXContainerItemProxy */; }; - DC34CD2D20326C2C00302481 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; - targetProxy = DC34CD2C20326C2C00302481 /* PBXContainerItemProxy */; - }; - DC34CD3420326C3100302481 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; - targetProxy = DC34CD3320326C3100302481 /* PBXContainerItemProxy */; - }; - DC34CD3620326C3B00302481 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC0BCC211D8C684F00070CB0 /* utilities */; - targetProxy = DC34CD3520326C3B00302481 /* PBXContainerItemProxy */; - }; DC3502C41E020D4D00BC0587 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC8834011D8A218F00CE0ACA /* ASN1 */; @@ -38560,11 +38702,6 @@ target = BEAA0040202B728B00E51F45 /* Security_executables_Swift */; targetProxy = DC647C49208A865200D0F9F8 /* PBXContainerItemProxy */; }; - DC65E7221D8CB27900152EF0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC0BCC211D8C684F00070CB0 /* utilities */; - targetProxy = DC65E7211D8CB27900152EF0 /* PBXContainerItemProxy */; - }; DC65E7261D8CB2E100152EF0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC0BCC211D8C684F00070CB0 /* utilities */; @@ -38740,11 +38877,6 @@ target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; targetProxy = DC69A5822165295F00512BD6 /* PBXContainerItemProxy */; }; - DC69A5872165298500512BD6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; - targetProxy = DC69A5862165298500512BD6 /* PBXContainerItemProxy */; - }; DC6BC2741D90D07800DD57B3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC6BC26C1D90CFEF00DD57B3 /* securityd_macos_startup */; @@ -38820,16 +38952,6 @@ target = DC8834011D8A218F00CE0ACA /* ASN1 */; targetProxy = DC89998A1E410DBF00E6E604 /* PBXContainerItemProxy */; }; - DC93C4C9214713DC008F8362 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; - targetProxy = DC93C4C8214713DC008F8362 /* PBXContainerItemProxy */; - }; - DC93C4CD21471401008F8362 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; - targetProxy = DC93C4CC21471401008F8362 /* PBXContainerItemProxy */; - }; DC99B85C20EACA470065B73B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC8834011D8A218F00CE0ACA /* ASN1 */; @@ -39080,16 +39202,6 @@ target = DCD66DC41D8205C400DB1393 /* SecOtrOSX */; targetProxy = DCD66DE51D82061F00DB1393 /* PBXContainerItemProxy */; }; - DCD6BF5421E919610015F7A8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; - targetProxy = DCD6BF5321E919610015F7A8 /* PBXContainerItemProxy */; - }; - DCD6BF5621E9196E0015F7A8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; - targetProxy = DCD6BF5521E9196E0015F7A8 /* PBXContainerItemProxy */; - }; DCD6BF5821E919820015F7A8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; @@ -39185,6 +39297,11 @@ target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; targetProxy = DCDA5E632124BCA9009B11B2 /* PBXContainerItemProxy */; }; + DCE27861245B81BD00381FE8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4771D971209A755800BA9772 /* KeychainDataclassOwner */; + targetProxy = DCE27860245B81BD00381FE8 /* PBXContainerItemProxy */; + }; DCE4E8D81D7F37F200AFB96E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DCE4E8931D7F34F600AFB96E /* authd */; @@ -39460,6 +39577,11 @@ target = EBA9AA7D1CE30E58004E2B68 /* secitemnotifications */; targetProxy = EBA9AA881CE3E76C004E2B68 /* PBXContainerItemProxy */; }; + EBAFDD6F2551D0550034B78D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EBAFC9AB2551C26F0034B78D /* SecLegacyCodeRegressions */; + targetProxy = EBAFDD6E2551D0550034B78D /* PBXContainerItemProxy */; + }; EBB8521022F793A200424FD0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = EBB851EB22F7912400424FD0 /* SecurityUtilitiesTests */; @@ -39495,16 +39617,6 @@ target = DC0BC5501D8B6D2D00070CB0 /* XPCKeychainSandboxCheck */; targetProxy = EBD31B411E0A18A600FBE9FA /* PBXContainerItemProxy */; }; - EBD7DF8121FF475B0089F2DF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; - targetProxy = EBD7DF8021FF475B0089F2DF /* PBXContainerItemProxy */; - }; - EBD7DF8321FF475B0089F2DF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; - targetProxy = EBD7DF8221FF475B0089F2DF /* PBXContainerItemProxy */; - }; EBF374821DC058B60065D840 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = EBF374711DC055580065D840 /* security-sysdiagnose */; @@ -39712,10 +39824,6 @@ buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = "secdtests/secdtests-entitlements.plist"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "LIBTRUSTD=1", - "$(inherited)", - ); GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( @@ -39736,6 +39844,7 @@ "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = secdtests; STRIP_STYLE = debugging; @@ -39747,10 +39856,6 @@ buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = "secdtests/secdtests-entitlements.plist"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "LIBTRUSTD=1", - "$(inherited)", - ); GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( @@ -39771,6 +39876,7 @@ "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = secdtests; STRIP_STYLE = debugging; @@ -40015,16 +40121,15 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "keychain/otctl/otctl-Entitlements.plist"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -40035,207 +40140,59 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "keychain/otctl/otctl-Entitlements.plist"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; - 0C9AEEB520783FBB00BF6237 /* Debug */ = { + 0CA378E423876DD100090B7E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = "keychain/Signin Metrics/Resources/SFTMTests-Info.plist"; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests; PRODUCT_NAME = "$(TARGET_NAME)"; - USE_XCTRUNNER = YES; }; name = Debug; }; - 0C9AEEB620783FBB00BF6237 /* Release */ = { + 0CA378E523876DD100090B7E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = "keychain/Signin Metrics/Resources/SFTMTests-Info.plist"; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests; PRODUCT_NAME = "$(TARGET_NAME)"; - USE_XCTRUNNER = YES; - VALIDATE_PRODUCT = YES; }; name = Release; }; - 0CF4064E2072E3E3003D6A7F /* Debug */ = { + 0CCC227723F357EE00E1FCD0 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 725D438D212CAA3B007B49E4 /* xcconfig/swift_binary_shim.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/../../AppleInternal/Library/Frameworks", + ); GCC_PREPROCESSOR_DEFINITIONS = ( "NO_SERVER=1", + "DEBUG=1", "$(inherited)", ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = "keychain/Signin Metrics/Resources/SFTMTests-Info.plist"; + INFOPLIST_FILE = "keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist"; INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + "$(SDKROOT)/usr/local/lib/security_libDER", ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", "$(OTHER_LDFLAGS_PROTOBUF)", "$(OTHER_LDFLAGS_MOBILEGESTALT)", @@ -40243,90 +40200,57 @@ "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", "$(OTHER_LDFLAGS_APS)", "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", "$(OTHER_LDFLAGS_PREQUELITE)", "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", "-ObjC", - "$(OTHER_LDFLAGS_CrashReporterSupport)", "$(OTHER_LDFLAGS_CORECDP)", "$(OTHER_LDFLAGS_IMCORE)", + "$(OTHER_LDFLAGS_FOR_SECURITYD)", "$(OTHER_LDFLAGS_ACCOUNTS)", + "-framework", + Security, + "$(OTHER_LDFLAGS_UserManagement)", + "$(OTHER_LDFLAGS_CLOUDSERVICES)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests; + OTHER_SWIFT_FLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.OctagonTrustTests; PRODUCT_NAME = "$(TARGET_NAME)"; - USE_XCTRUNNER = YES; + SKIP_INSTALL = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_INTERFACE_HEADER_NAME = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = ""; }; name = Debug; }; - 0CF4064F2072E3E3003D6A7F /* Release */ = { + 0CCC227823F357EE00E1FCD0 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 725D438D212CAA3B007B49E4 /* xcconfig/swift_binary_shim.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/../../AppleInternal/Library/Frameworks", + ); GCC_PREPROCESSOR_DEFINITIONS = ( "NO_SERVER=1", + "NDEBUG=1", "$(inherited)", ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = "keychain/Signin Metrics/Resources/SFTMTests-Info.plist"; + INFOPLIST_FILE = "keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist"; INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + "$(SDKROOT)/usr/local/lib/security_libDER", ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", "$(OTHER_LDFLAGS_PROTOBUF)", "$(OTHER_LDFLAGS_MOBILEGESTALT)", @@ -40339,14 +40263,114 @@ "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", "-ObjC", - "$(OTHER_LDFLAGS_CrashReporterSupport)", + "$(OTHER_LDFLAGS_CORECDP)", "$(OTHER_LDFLAGS_IMCORE)", + "$(OTHER_LDFLAGS_FOR_SECURITYD)", "$(OTHER_LDFLAGS_ACCOUNTS)", + "-framework", + Security, + "$(OTHER_LDFLAGS_UserManagement)", + "$(OTHER_LDFLAGS_CLOUDSERVICES)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests; + OTHER_SWIFT_FLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.OctagonTrustTests; PRODUCT_NAME = "$(TARGET_NAME)"; - USE_XCTRUNNER = YES; + SKIP_INSTALL = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_INTERFACE_HEADER_NAME = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = ""; + }; + name = Release; + }; + 0CD743AC23C3EC8000FA0EC5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "$(INSTALL_PATH)"; + EXPORTED_SYMBOLS_FILE = ""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INFOPLIST_FILE = keychain/OctagonTrust/Info.plist; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ""; + MODULEMAP_FILE = Modules/OctagonTrust.modulemap; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = ( + "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)", + "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.octagontrust; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx.internal; + SKIP_INSTALL = NO; + TAPI_VERIFY_MODE = ErrorsAndWarnings; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 0CD743AD23C3EC8000FA0EC5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "$(INSTALL_PATH)"; + ENABLE_NS_ASSERTIONS = NO; + EXPORTED_SYMBOLS_FILE = ""; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INFOPLIST_FILE = keychain/OctagonTrust/Info.plist; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ""; + MODULEMAP_FILE = Modules/OctagonTrust.modulemap; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = ( + "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)", + "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.octagontrust; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx.internal; + SKIP_INSTALL = NO; + TAPI_VERIFY_MODE = ErrorsAndWarnings; + TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; @@ -40365,7 +40389,6 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -40390,9 +40413,7 @@ "-Wglobal-constructors", "-Wmost", "-Wno-four-char-constants", - "-Wno-unknown-pragmas", "$(inherited)", - "-Wno-error=c++11-narrowing", ); }; name = Debug; @@ -40412,7 +40433,6 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -40437,9 +40457,7 @@ "-Wglobal-constructors", "-Wmost", "-Wno-four-char-constants", - "-Wno-unknown-pragmas", "$(inherited)", - "-Wno-error=c++11-narrowing", ); }; name = Release; @@ -40616,7 +40634,7 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "-"; GCC_PREPROCESSOR_DEFINITIONS = ( "NO_SERVER=1", "$(inherited)", @@ -40624,6 +40642,7 @@ GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; + GENERATE_INFOPLIST_FILE = YES; HEADER_SEARCH_PATHS = ( "$(PROJECT_DIR)", "$(HEADER_SYMLINKS)", @@ -40656,7 +40675,7 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "-"; GCC_PREPROCESSOR_DEFINITIONS = ( "NO_SERVER=1", "$(inherited)", @@ -40664,6 +40683,7 @@ GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; + GENERATE_INFOPLIST_FILE = YES; HEADER_SEARCH_PATHS = ( "$(PROJECT_DIR)", "$(HEADER_SYMLINKS)", @@ -40689,6 +40709,144 @@ }; name = Release; }; + 3E4D49BA2531170600B124B3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = ""; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; + USER_HEADER_SEARCH_PATHS = "${BUILT_PRODUCTS_DIR}/cstemp"; + }; + name = Debug; + }; + 3E4D49BB2531170600B124B3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; + USER_HEADER_SEARCH_PATHS = "${BUILT_PRODUCTS_DIR}/cstemp"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3E88360F24F068EF00E9F4D6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = ""; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; + }; + name = Debug; + }; + 3E88361024F068EF00E9F4D6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; 438169101B4EDCBD00C54D58 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -40719,13 +40877,11 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionstest/seckeychainnetworkextensionstest.entitlements; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; @@ -40741,14 +40897,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionstest/seckeychainnetworkextensionstest.entitlements; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; MTL_ENABLE_DEBUG_INFO = NO; @@ -40806,10 +40960,7 @@ ); PRODUCT_NAME = securityd; STRIP_STYLE = debugging; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -40862,10 +41013,7 @@ ); PRODUCT_NAME = securityd; STRIP_STYLE = debugging; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -40925,12 +41073,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -40948,10 +41094,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ( @@ -40959,6 +41102,11 @@ "$(OTHER_LDFLAGS_AKS_ACL_LIBRARY)", "$(OTHER_LDFLAGS_UserManagement)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", + "$(OTHER_LDFLAGS_COREANALYTICS)", + "$(OTHER_LDFLAGS_MOBILEGESTALT)", + "$(OTHER_LDFLAGS_ACCOUNTS)", + "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", + "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", "$(OTHER_LDFLAGS_CORECDP)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", ); @@ -40974,12 +41122,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -40997,10 +41143,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ( @@ -41008,6 +41151,11 @@ "$(OTHER_LDFLAGS_AKS_ACL_LIBRARY)", "$(OTHER_LDFLAGS_UserManagement)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", + "$(OTHER_LDFLAGS_COREANALYTICS)", + "$(OTHER_LDFLAGS_MOBILEGESTALT)", + "$(OTHER_LDFLAGS_ACCOUNTS)", + "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", + "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", "$(OTHER_LDFLAGS_CORECDP)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", ); @@ -41024,13 +41172,11 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionsystemdaemontest/seckeychainnetworkextensionsystemdaemontest.entitlements; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; @@ -41046,14 +41192,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionsystemdaemontest/seckeychainnetworkextensionsystemdaemontest.entitlements; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; MTL_ENABLE_DEBUG_INFO = NO; @@ -41068,13 +41212,11 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionunauthorizedaccesstest/seckeychainnetworkextensionunauthorizedaccesstest.entitlements; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; @@ -41090,14 +41232,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionunauthorizedaccesstest/seckeychainnetworkextensionunauthorizedaccesstest.entitlements; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; MTL_ENABLE_DEBUG_INFO = NO; @@ -41109,34 +41249,20 @@ 4771D976209A755800BA9772 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = keychain/KeychainDataclassOwner/Info.plist; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Accounts/DataclassOwners"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = com.apple.KeychainDataclassOwner; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos.internal; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,6"; WRAPPER_EXTENSION = bundle; }; name = Debug; @@ -41144,24 +41270,13 @@ 4771D977209A755800BA9772 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_STYLE = Automatic; ENABLE_NS_ASSERTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = keychain/KeychainDataclassOwner/Info.plist; @@ -41169,115 +41284,18 @@ MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = com.apple.KeychainDataclassOwner; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos.internal; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,6"; VALIDATE_PRODUCT = YES; WRAPPER_EXTENSION = bundle; }; name = Release; }; - 478D429A1FD72A8100CAB645 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_MODULES = NO; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_STRICT_PROTOTYPES = NO; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "secdtests/secdtests-entitlements.plist"; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = dwarf; - GCC_DYNAMIC_NO_PIC = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = secdxctests/Info.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_AKS_ACL_LIBRARY)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.secdxctests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 478D429B1FD72A8100CAB645 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_MODULES = NO; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_STRICT_PROTOTYPES = NO; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "secdtests/secdtests-entitlements.plist"; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - ENABLE_NS_ASSERTIONS = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = secdxctests/Info.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_AKS_ACL_LIBRARY)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.secdxctests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; 47C2F1882059CB690062DE30 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; @@ -41310,7 +41328,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; @@ -41343,7 +41360,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -41376,7 +41392,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -41407,7 +41422,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -41418,7 +41432,6 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = CircleJoinRequested/entitlements.plist; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -41461,7 +41474,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -41473,7 +41485,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = CircleJoinRequested/entitlements.plist; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_UNDECLARED_SELECTOR = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -41549,6 +41560,7 @@ "$(OTHER_LDFLAGS_SECUREKEYVAULT)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = SecurityDevTests; @@ -41591,6 +41603,7 @@ "$(OTHER_LDFLAGS_SECUREKEYVAULT)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = SecurityDevTests; @@ -41657,7 +41670,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -41670,7 +41682,6 @@ COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; @@ -41702,7 +41713,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -41715,7 +41725,6 @@ COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES = ""; HEADER_SEARCH_PATHS = ( @@ -41743,7 +41752,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_ARC = YES; @@ -41756,7 +41764,6 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch"; @@ -41781,7 +41788,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_ARC = YES; @@ -41795,7 +41801,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch"; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -41816,12 +41821,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "experiment/tool/experimentTool-Entitlements.plist"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; @@ -41836,14 +41839,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "experiment/tool/experimentTool-Entitlements.plist"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = NO; @@ -41855,7 +41856,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -41869,7 +41869,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -41893,7 +41892,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -41908,7 +41906,6 @@ COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -41996,7 +41993,7 @@ }; name = Release; }; - 6C39237721F13E4D00D018AD /* Debug */ = { + 6C2045EF2424BA7F00F9461D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -42004,21 +42001,77 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/KeychainStasher/KeychainStasher.entitlements"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INFOPLIST_FILE = "$(SRCROOT)/keychain/KeychainStasher/KeychainStasher-Info.plist"; + INSTALL_PATH = /usr/libexec; + MACOSX_DEPLOYMENT_TARGET = 10.16; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainStasher; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + }; + name = Debug; + }; + 6C2045F02424BA7F00F9461D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/KeychainStasher/KeychainStasher.entitlements"; + CODE_SIGN_STYLE = Automatic; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INFOPLIST_FILE = "$(SRCROOT)/keychain/KeychainStasher/KeychainStasher-Info.plist"; + INSTALL_PATH = /usr/libexec; + MACOSX_DEPLOYMENT_TARGET = 10.16; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainStasher; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + }; + name = Release; + }; + 6C39237721F13E4D00D018AD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = NO; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_STRICT_PROTOTYPES = NO; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = tests/SecDbBackupTests/Entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_ENTITLEMENTS = "tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist"; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = ""; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; @@ -42046,8 +42099,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.secdbbackuptests; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - USES_XCTRUNNER = YES; + REEXPORTED_LIBRARY_PATHS = ""; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Debug; }; @@ -42057,23 +42110,18 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_STRICT_PROTOTYPES = NO; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = tests/SecDbBackupTests/Entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_ENTITLEMENTS = "tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist"; COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = ""; ENABLE_NS_ASSERTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; @@ -42101,8 +42149,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.secdbbackuptests; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - USES_XCTRUNNER = YES; + REEXPORTED_LIBRARY_PATHS = ""; + TEST_BUILD_STYLE = _APPLEINTERNAL; VALIDATE_PRODUCT = YES; }; name = Release; @@ -42115,17 +42163,13 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INFOPLIST_FILE = "$(SRCROOT)/supd/Tests/Info.plist"; INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ( @@ -42153,17 +42197,13 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INFOPLIST_FILE = "$(SRCROOT)/supd/Tests/Info.plist"; INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ( @@ -42184,264 +42224,120 @@ }; name = Release; }; - 6C98085F1E788AEB00E70590 /* Debug */ = { + 6C7BE2E523C3DD64003BB2CA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "NO_LIBTRUSTD=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_ENTITLEMENTS = SecurityTool/sharedTool/iOS/entitlements.plist; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = keychain/ckks/tests/CKKSCloudKitTestsInfo.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; + GCC_WARN_SHADOW = NO; + INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", + "-lsqlite3", "-framework", - CrashReporterSupport, - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", + CFNetwork, + "-framework", + IOKit, + "$(OTHER_LDFLAGS_ACM_LIBRARY)", + "$(OTHER_LDFLAGS_PROTOBUF)", + "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", + "$(OTHER_LDFLAGS_SECURITYFOUNDATION)", + "$(OTHER_LDFLAGS_AKS_LIBRARY)", + "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSCloudKitTests; - PRODUCT_NAME = CKKSCloudKitTests; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeychainEntitledTestApp_mac.app/Contents/MacOS/KeychainEntitledTestApp_mac"; + PRODUCT_NAME = "$(TARGET_NAME)"; + REEXPORTED_LIBRARY_PATHS = ""; + STRIP_STYLE = debugging; }; name = Debug; }; - 6C9808601E788AEB00E70590 /* Release */ = { + 6C7BE2E623C3DD64003BB2CA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "NO_LIBTRUSTD=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_ENTITLEMENTS = SecurityTool/sharedTool/iOS/entitlements.plist; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = keychain/ckks/tests/CKKSCloudKitTestsInfo.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = NO; + GCC_WARN_SHADOW = NO; + INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "$(OTHER_LDFLAGS_ACM_LIBRARY)", "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(OTHER_LDFLAGS_SECURITYFOUNDATION)", "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSCloudKitTests; - PRODUCT_NAME = CKKSCloudKitTests; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeychainEntitledTestApp_mac.app/Contents/MacOS/KeychainEntitledTestApp_mac"; - VALIDATE_PRODUCT = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + REEXPORTED_LIBRARY_PATHS = ""; + STRIP_STYLE = debugging; }; name = Release; }; - 6C98089B1E788AFD00E70590 /* Debug */ = { + 6C963285242A279B00C53CE2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "NO_LIBTRUSTD=1", - "$(inherited)", - ); + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/stashtester/stashtester.entitlements"; + CODE_SIGN_STYLE = Manual; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = keychain/ckks/tests/CKKSCloudKitTestsInfo.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSCloudKitTests; - PRODUCT_NAME = CKKSCloudKitTests; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeychainEntitledTestApp_ios.app/KeychainEntitledTestApp_ios"; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MACOSX_DEPLOYMENT_TARGET = 10.16; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx.internal; }; name = Debug; }; - 6C98089C1E788AFD00E70590 /* Release */ = { + 6C963286242A279B00C53CE2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "NO_LIBTRUSTD=1", - "$(inherited)", - ); + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/stashtester/stashtester.entitlements"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = keychain/ckks/tests/CKKSCloudKitTestsInfo.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MACOSX_DEPLOYMENT_TARGET = 10.16; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSCloudKitTests; - PRODUCT_NAME = CKKSCloudKitTests; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeychainEntitledTestApp_ios.app/KeychainEntitledTestApp_ios"; - VALIDATE_PRODUCT = YES; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx.internal; }; name = Release; }; @@ -42451,7 +42347,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -42476,7 +42371,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -42502,7 +42396,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -42537,7 +42430,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -42573,29 +42465,23 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements"; DEBUG_INFORMATION_FORMAT = dwarf; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(PLATFORM_DIR)/Developer/AppleInternal/Library/Frameworks", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; LD_RUNPATH_SEARCH_PATHS = ( /Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Debug; }; @@ -42605,29 +42491,23 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(PLATFORM_DIR)/Developer/AppleInternal/Library/Frameworks", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; LD_RUNPATH_SEARCH_PATHS = ( /Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Release; }; @@ -42638,26 +42518,26 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements"; COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = KeychainEntitledTestApp_mac/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + INFOPLIST_FILE = "$(SOURCE_ROOT)/tests/TestHostBinaries/KeychainEntitledTestApp/Info.plist"; + INFOPLIST_PREPROCESS = YES; + INSTALL_PATH = /AppleInternal/Applications; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); MTL_ENABLE_DEBUG_INFO = YES; OTHER_CODE_SIGN_FLAGS = "--deep"; - PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.KeychainEntitledTestApp-mac"; + OTHER_LDFLAGS = "$(OTHER_LDFLAGS_AppFrameworks)"; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainEntitledTestApp; PRODUCT_NAME = KeychainEntitledTestApp; }; name = Debug; @@ -42669,92 +42549,28 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = KeychainEntitledTestApp_mac/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + INSTALL_PATH = /AppleInternal/Applications; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); MTL_ENABLE_DEBUG_INFO = NO; OTHER_CODE_SIGN_FLAGS = "--deep"; - PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.KeychainEntitledTestApp-mac"; + OTHER_LDFLAGS = "$(OTHER_LDFLAGS_AppFrameworks)"; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainEntitledTestApp; PRODUCT_NAME = KeychainEntitledTestApp; }; name = Release; }; - 6CF4A0F51E4549F300ECD7B5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; - DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - INFOPLIST_FILE = KeychainEntitledTestApp_ios/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_CODE_SIGN_FLAGS = "--deep"; - PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.KeychainEntitledTestApp-ios"; - PRODUCT_NAME = KeychainEntitledTestApp; - VALIDATE_PRODUCT = NO; - }; - name = Debug; - }; - 6CF4A0F61E4549F300ECD7B5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; - COPY_PHASE_STRIP = NO; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - INFOPLIST_FILE = KeychainEntitledTestApp_ios/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_CODE_SIGN_FLAGS = "--deep"; - PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.KeychainEntitledTestApp-ios"; - PRODUCT_NAME = KeychainEntitledTestApp; - VALIDATE_PRODUCT = NO; - }; - name = Release; - }; 7913B20D0D172B3900601FE9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -42810,6 +42626,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = DCC1849220EEEC4400F3B26C /* security_framework.xcconfig */; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; @@ -42841,6 +42658,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = DCC1849220EEEC4400F3B26C /* security_framework.xcconfig */; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; @@ -43013,10 +42831,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -43064,10 +42879,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -43091,7 +42903,6 @@ buildSettings = { APPLY_RULES_IN_COPY_FILES = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_STATIC_ANALYZER_MODE = shallow; @@ -43109,6 +42920,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -43122,7 +42934,6 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; EXCLUDED_INSTALLSRC_SUBDIRECTORY_PATTERNS = "$(SRCROOT)/sslViewer/ecc-secp256r1-client.pfx"; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -43130,7 +42941,7 @@ "$(inherited)", ); GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; @@ -43152,9 +42963,10 @@ HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES = NO; INSTALL_DAEMON_AGENT_DIR = "$(SYSTEM_LIBRARY_DIR)/LaunchDaemons"; "INSTALL_DAEMON_AGENT_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/LaunchAgents"; - LLVM_LTO = YES_THIN; + LLVM_LTO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; + RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx.internal; SECURITY_FRAMEWORK_RESOURCES_DIR = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/"; "SECURITY_FRAMEWORK_RESOURCES_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; @@ -43163,7 +42975,7 @@ SERVICETYPE_USER_OR_SYSTEM = System; "SERVICETYPE_USER_OR_SYSTEM[sdk=macosx*]" = User; STRIP_INSTALLED_PRODUCT = NO; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchos macosx appletvos appletvsimulator watchsimulator"; + SUPPORTED_PLATFORMS = "bridgeos iphoneos iphonesimulator macosx appletvos appletvsimulator watchos watchsimulator"; SUPPORTS_TEXT_BASED_API = YES; Sim_Name = ""; "Sim_Name[sdk=embeddedsimulator*][arch=*]" = _sim; @@ -43178,7 +42990,6 @@ buildSettings = { APPLY_RULES_IN_COPY_FILES = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_STATIC_ANALYZER_MODE = shallow; @@ -43196,6 +43007,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -43208,7 +43020,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; EXCLUDED_INSTALLSRC_SUBDIRECTORY_PATTERNS = "$(SRCROOT)/sslViewer/ecc-secp256r1-client.pfx"; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = s; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -43216,7 +43027,7 @@ "$(inherited)", ); GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; @@ -43240,6 +43051,7 @@ "INSTALL_DAEMON_AGENT_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/LaunchAgents"; LLVM_LTO = YES; OTHER_LDFLAGS = ""; + RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx.internal; SECURITY_FRAMEWORK_RESOURCES_DIR = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/"; "SECURITY_FRAMEWORK_RESOURCES_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; @@ -43247,7 +43059,7 @@ "SECURITY_FRAMEWORK_XPCSERVICES_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/XPCServices"; SERVICETYPE_USER_OR_SYSTEM = System; "SERVICETYPE_USER_OR_SYSTEM[sdk=macosx*]" = User; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchos macosx appletvos appletvsimulator watchsimulator"; + SUPPORTED_PLATFORMS = "bridgeos iphoneos iphonesimulator macosx appletvos appletvsimulator watchos watchsimulator"; SUPPORTS_TEXT_BASED_API = YES; SWIFT_COMPILATION_MODE = wholemodule; Sim_Name = ""; @@ -43262,10 +43074,7 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_SUSPICIOUS_MOVES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( COM_APPLE_SECURITY_SANE_INCLUDES, "$(inherited)", @@ -43281,10 +43090,7 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_SUSPICIOUS_MOVES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( COM_APPLE_SECURITY_SANE_INCLUDES, "$(inherited)", @@ -43303,7 +43109,6 @@ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; AXLE_ENABLE_DEBUG_INFO = YES; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_ASSIGN_ENUM = YES; @@ -43318,7 +43123,6 @@ CODE_SIGN_ENTITLEMENTS = "$(TARGET_NAME)/entitlements.plist"; "CODE_SIGN_IDENTITY[sdk=embedded*]" = "-"; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(TARGET_NAME)/$(TARGET_NAME)-Prefix.pch"; @@ -43327,7 +43131,7 @@ "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_ABOUT_MISSING_NEWLINE = NO; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -43352,7 +43156,6 @@ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; AXLE_ENABLE_DEBUG_INFO = NO; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_ASSIGN_ENUM = YES; @@ -43368,10 +43171,9 @@ "CODE_SIGN_IDENTITY[sdk=embedded*]" = "-"; COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(TARGET_NAME)/$(TARGET_NAME)-Prefix.pch"; - GCC_WARN_ABOUT_MISSING_NEWLINE = NO; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -43508,7 +43310,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -43519,7 +43320,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -43608,7 +43408,6 @@ "$(SDKROOT)/usr/local/lib/security_libDER", ); OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", "$(OTHER_LDFLAGS_PROTOBUF)", "$(OTHER_LDFLAGS_MOBILEGESTALT)", @@ -43628,6 +43427,7 @@ "$(OTHER_LDFLAGS_FOR_SECURITYD)", "-framework", Security, + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustedPeersHelperUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -43659,7 +43459,6 @@ "$(SDKROOT)/usr/local/lib/security_libDER", ); OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", "$(OTHER_LDFLAGS_PROTOBUF)", "$(OTHER_LDFLAGS_MOBILEGESTALT)", @@ -43679,6 +43478,7 @@ "$(OTHER_LDFLAGS_FOR_SECURITYD)", "-framework", Security, + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustedPeersHelperUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -43690,7 +43490,6 @@ }; BEF88C391EAFFC4000357577 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -43713,19 +43512,18 @@ "$(OTHER_LDFLAGS_AKS_LIBRARY)", "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)", "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)", - "$(OTHER_LDFLAGS_UPWARD_SECURITY)", "$(OTHER_LDFLAGS_UPWARD_SECURITYFOUNDATION)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustedPeers; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + TAPI_VERIFY_MODE = Pedantic; VERSION_INFO_PREFIX = ""; }; name = Debug; }; BEF88C3A1EAFFC4000357577 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -43748,12 +43546,12 @@ "$(OTHER_LDFLAGS_AKS_LIBRARY)", "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)", "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)", - "$(OTHER_LDFLAGS_UPWARD_SECURITY)", "$(OTHER_LDFLAGS_UPWARD_SECURITYFOUNDATION)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustedPeers; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + TAPI_VERIFY_MODE = Pedantic; VERSION_INFO_PREFIX = ""; }; name = Release; @@ -43804,6 +43602,7 @@ OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = trustd; STRIP_STYLE = debugging; @@ -43829,6 +43628,7 @@ OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = trustd; STRIP_STYLE = debugging; @@ -43872,7 +43672,6 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -43895,7 +43694,6 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -43909,6 +43707,54 @@ }; name = Release; }; + D445B311258C07FD0019858E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_ENTITLEMENTS = trust/trustd/trustdFileHelper/entitlements.plist; + GCC_DYNAMIC_NO_PIC = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INSTALL_PATH = /usr/libexec; + LLVM_LTO = NO; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D445B312258C07FD0019858E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_ENTITLEMENTS = trust/trustd/trustdFileHelper/entitlements.plist; + ENABLE_NS_ASSERTIONS = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INSTALL_PATH = /usr/libexec; + LLVM_LTO = NO; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; D44D1F672115893000E76E1A /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = DC8E04901D7F6780006D80EB /* lib_ios.xcconfig */; @@ -43950,17 +43796,14 @@ INSTALL_PATH = /AppleInternal/XCTests/com.apple.security/; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests; PRODUCT_NAME = TrustTests; @@ -43990,17 +43833,14 @@ INSTALL_PATH = /AppleInternal/XCTests/com.apple.security/; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests; PRODUCT_NAME = TrustTests; @@ -44015,10 +43855,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -44031,6 +43869,8 @@ LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", + /Developer/Library/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -44048,10 +43888,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -44063,6 +43901,8 @@ LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", + /Developer/Library/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; @@ -44079,34 +43919,29 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = tests/TrustTests/TestRunners/trusttests_entitlements.plist; CODE_SIGN_STYLE = Automatic; DEBUG_INFORMATION_FORMAT = dwarf; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(PLATFORM_DIR)/Developer/AppleInternal/Library/Frameworks", - ); + ENABLE_TESTING_SEARCH_PATHS = YES; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = tests/TrustTests/TestRunners/Info.plist; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; LD_RUNPATH_SEARCH_PATHS = ( /Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Debug; }; @@ -44116,33 +43951,28 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = tests/TrustTests/TestRunners/trusttests_entitlements.plist; CODE_SIGN_STYLE = Automatic; ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(PLATFORM_DIR)/Developer/AppleInternal/Library/Frameworks", - ); + ENABLE_TESTING_SEARCH_PATHS = YES; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = tests/TrustTests/TestRunners/Info.plist; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; LD_RUNPATH_SEARCH_PATHS = ( /Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; + TEST_BUILD_STYLE = _APPLEINTERNAL; VALIDATE_PRODUCT = YES; }; name = Release; @@ -44165,11 +43995,7 @@ INSTALL_PATH = /AppleInternal/XCTests/com.apple.security/; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -44177,6 +44003,7 @@ "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_OCMOCK)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests; PRODUCT_NAME = TrustTests; @@ -44201,11 +44028,7 @@ INSTALL_PATH = /AppleInternal/XCTests/com.apple.security/; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; @@ -44213,6 +44036,7 @@ "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_OCMOCK)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests; PRODUCT_NAME = TrustTests; @@ -44422,7 +44246,6 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -44441,7 +44264,6 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -44696,7 +44518,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -44712,7 +44533,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -44734,7 +44554,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -44751,7 +44570,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -44769,7 +44587,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; @@ -44784,7 +44601,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; @@ -44799,7 +44615,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; @@ -44814,7 +44629,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; @@ -44845,7 +44659,6 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -44861,7 +44674,7 @@ FRAMEWORK_VERSION = A; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = OCMockUmbrella/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/BATS/unit_tests/Frameworks; + INSTALL_PATH = /AppleInternal/XCTests/com.apple.security/Frameworks; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -44884,7 +44697,6 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -44900,7 +44712,7 @@ FRAMEWORK_VERSION = A; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = OCMockUmbrella/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/BATS/unit_tests/Frameworks; + INSTALL_PATH = /AppleInternal/XCTests/com.apple.security/Frameworks; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -44922,7 +44734,6 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -44951,7 +44762,6 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -44982,7 +44792,6 @@ CLANG_ENABLE_OBJC_ARC = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -45012,7 +44821,6 @@ CLANG_ENABLE_OBJC_ARC = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -45038,7 +44846,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -45052,7 +44859,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -45066,7 +44872,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -45079,7 +44884,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -45093,7 +44897,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -45113,7 +44916,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -45132,7 +44934,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -45152,7 +44953,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -45169,7 +44969,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -45180,7 +44979,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -45192,7 +44990,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -45209,7 +45006,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -45226,7 +45022,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; HEADER_SEARCH_PATHS = ( @@ -45243,7 +45038,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; HEADER_SEARCH_PATHS = ( @@ -45260,7 +45054,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -45273,7 +45066,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -45286,10 +45078,9 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -45300,10 +45091,9 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -45314,7 +45104,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -45327,7 +45116,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -45340,7 +45128,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; @@ -45355,7 +45142,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; @@ -45370,7 +45156,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -45383,7 +45168,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -45396,7 +45180,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -45409,7 +45192,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -45419,7 +45201,6 @@ }; DC0BC9CD1D8B824700070CB0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_ENUM_CONVERSION = NO; @@ -45444,7 +45225,6 @@ }; DC0BC9CE1D8B824700070CB0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_ENUM_CONVERSION = NO; @@ -45480,7 +45260,6 @@ SKIP_INSTALL = YES; WARNING_CFLAGS = ( "$(inherited)", - "-Wno-int-to-void-pointer-cast", "-Wno-sign-compare", ); }; @@ -45499,7 +45278,6 @@ SKIP_INSTALL = YES; WARNING_CFLAGS = ( "$(inherited)", - "-Wno-int-to-void-pointer-cast", "-Wno-sign-compare", ); }; @@ -45510,10 +45288,8 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_SUSPICIOUS_MOVES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( COM_APPLE_SECURITY_SANE_INCLUDES, "$(inherited)", @@ -45529,10 +45305,8 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_SUSPICIOUS_MOVES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( COM_APPLE_SECURITY_SANE_INCLUDES, "$(inherited)", @@ -45548,7 +45322,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -45561,7 +45334,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -45619,7 +45391,6 @@ }; DC0BCC341D8C684F00070CB0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -45638,21 +45409,17 @@ GCC_WARN_SHADOW = NO; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; STRIP_INSTALLED_PRODUCT = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-unused-function", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; DC0BCC351D8C684F00070CB0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -45671,15 +45438,12 @@ GCC_WARN_SHADOW = NO; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; STRIP_INSTALLED_PRODUCT = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-unused-function", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -45700,14 +45464,13 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; WARNING_CFLAGS = ( "$(inherited)", "-Wno-sign-compare", - "-Wno-unused-function", ); }; name = Debug; @@ -45729,14 +45492,13 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; WARNING_CFLAGS = ( "$(inherited)", "-Wno-sign-compare", - "-Wno-unused-function", ); }; name = Release; @@ -45752,7 +45514,6 @@ CLANG_WARN_COMMA = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -45790,7 +45551,6 @@ CLANG_WARN_COMMA = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -45825,7 +45585,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -45872,7 +45631,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -45918,7 +45676,6 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -45938,7 +45695,6 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -45970,18 +45726,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ( @@ -46005,6 +45750,8 @@ "-framework", Security, "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "-framework", + TrustedPeers, ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -46031,18 +45778,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ( @@ -46066,6 +45802,8 @@ "-framework", Security, "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "-framework", + TrustedPeers, ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -46080,7 +45818,6 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -46101,7 +45838,6 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -46120,7 +45856,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -46149,7 +45884,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -46698,7 +46432,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -46735,7 +46468,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -46768,18 +46500,17 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++98"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = "SecurityTool/macOS/securitytool-entitlements.plist"; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; @@ -46805,18 +46536,17 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++98"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = "SecurityTool/macOS/securitytool-entitlements.plist"; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -46844,7 +46574,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; @@ -46872,10 +46601,7 @@ INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = YES; ORDER_FILE = securityd/src/securityd.order; - OTHER_CPLUSPLUSFLAGS = ( - "$(OTHER_CFLAGS)", - "-Wno-deprecated-register", - ); + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; PRODUCT_NAME = securityd; SUPPORTED_PLATFORMS = macosx; }; @@ -46889,7 +46615,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; @@ -46917,10 +46642,7 @@ INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = NO; ORDER_FILE = securityd/src/securityd.order; - OTHER_CPLUSPLUSFLAGS = ( - "$(OTHER_CFLAGS)", - "-Wno-deprecated-register", - ); + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; PRODUCT_NAME = securityd; SUPPORTED_PLATFORMS = macosx; }; @@ -46931,13 +46653,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -46949,7 +46669,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -46973,13 +46692,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -46992,7 +46709,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47009,10 +46725,6 @@ buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = keychain/securityd/entitlements.plist; - GCC_PREPROCESSOR_DEFINITIONS = ( - "LIBTRUSTD=1", - "$(inherited)", - ); GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( @@ -47022,6 +46734,8 @@ "$(OTHER_LDFLAGS_IMCORE)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = secdtests; STRIP_STYLE = debugging; @@ -47033,10 +46747,6 @@ buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = keychain/securityd/entitlements.plist; - GCC_PREPROCESSOR_DEFINITIONS = ( - "LIBTRUSTD=1", - "$(inherited)", - ); GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( @@ -47046,6 +46756,8 @@ "$(OTHER_LDFLAGS_IMCORE)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = secdtests; STRIP_STYLE = debugging; @@ -47062,7 +46774,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47094,7 +46805,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47126,7 +46836,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47156,7 +46865,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47187,7 +46895,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47218,7 +46925,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47261,7 +46967,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; @@ -47277,7 +46982,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; @@ -47350,7 +47054,6 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -47373,7 +47076,6 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -47424,7 +47126,6 @@ }; DC8834061D8A218F00CE0ACA /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_MODULES = NO; @@ -47445,7 +47146,6 @@ }; DC8834071D8A218F00CE0ACA /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_MODULES = NO; @@ -47469,13 +47169,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47487,7 +47185,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47511,13 +47208,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47530,7 +47225,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47547,13 +47241,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47565,7 +47257,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47589,13 +47280,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47608,7 +47297,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47625,13 +47313,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47643,7 +47329,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47667,13 +47352,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47686,7 +47369,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47703,13 +47385,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47721,7 +47401,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47745,13 +47424,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47764,7 +47441,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47781,13 +47457,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47799,7 +47473,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47823,13 +47496,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47842,7 +47513,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47859,13 +47529,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47877,7 +47545,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47901,13 +47568,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47920,7 +47585,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47937,13 +47601,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47955,7 +47617,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47979,13 +47640,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -47998,7 +47657,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -48015,13 +47673,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -48033,7 +47689,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -48057,13 +47712,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -48076,7 +47729,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -48093,13 +47745,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -48111,7 +47761,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -48135,13 +47784,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -48154,7 +47801,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -48179,11 +47825,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -48234,11 +47876,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -48280,7 +47918,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -48293,7 +47930,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -48306,7 +47942,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -48320,7 +47955,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -48334,7 +47968,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -48347,7 +47980,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -48360,7 +47992,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -48373,7 +48004,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -48386,16 +48016,12 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-switch", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -48404,16 +48030,12 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-switch", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -48423,7 +48045,6 @@ buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; @@ -48438,7 +48059,6 @@ buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; @@ -48464,11 +48084,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ( @@ -48516,11 +48132,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ( @@ -48632,7 +48244,7 @@ APPLY_RULES_IN_COPY_FILES = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_ENUM_CONVERSION = NO; + CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; HEADER_SEARCH_PATHS = ( @@ -48644,10 +48256,7 @@ MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=c++11-narrowing", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -48658,7 +48267,7 @@ APPLY_RULES_IN_COPY_FILES = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_ENUM_CONVERSION = NO; + CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; HEADER_SEARCH_PATHS = ( @@ -48670,10 +48279,7 @@ MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=c++11-narrowing", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -48696,13 +48302,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -48714,7 +48318,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -48738,13 +48341,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -48757,7 +48358,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -48774,7 +48374,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -48788,7 +48387,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -48802,7 +48400,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -48816,7 +48413,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -48840,6 +48436,8 @@ "-lsqlite3", "-framework", CFNetwork, + "-framework", + Security, ); "OTHER_LDFLAGS[sdk=embedded][arch=*]" = ( "-lsqlite3", @@ -48868,7 +48466,11 @@ "$(inherited)", ); INSTALL_PATH = /usr/local/bin; - OTHER_LDFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Security, + "$(inherited)", + ); "OTHER_LDFLAGS[sdk=embedded]" = ( "-lsqlite3", "-framework", @@ -48930,7 +48532,6 @@ WARNING_CFLAGS = ( "$(inherited)", "-Wno-sign-compare", - "-Wno-deprecated-register", ); }; name = Debug; @@ -48961,7 +48562,6 @@ WARNING_CFLAGS = ( "$(inherited)", "-Wno-sign-compare", - "-Wno-deprecated-register", ); }; name = Release; @@ -49240,7 +48840,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49271,7 +48870,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49304,7 +48902,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49341,10 +48938,7 @@ "$(OTHER_LDFLAGS_FOR_SECURITYD)", ); PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -49358,7 +48952,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49396,10 +48989,7 @@ "$(OTHER_LDFLAGS_FOR_SECURITYD)", ); PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -49413,7 +49003,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49434,16 +49023,14 @@ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; INSTALL_PATH = /usr/libexec; MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = trustd; - WARNING_CFLAGS = ( - "-Wextra", - "-Wno-unused-parameter", - "-Wno-missing-field-initializers", - "-Wno-error=deprecated-declarations", + OTHER_LDFLAGS = ( + "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); + PRODUCT_NAME = trustd; }; name = Debug; }; @@ -49457,7 +49044,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49479,16 +49065,14 @@ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; INSTALL_PATH = /usr/libexec; MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = trustd; - WARNING_CFLAGS = ( - "-Wextra", - "-Wno-unused-parameter", - "-Wno-missing-field-initializers", - "-Wno-error=deprecated-declarations", + OTHER_LDFLAGS = ( + "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); + PRODUCT_NAME = trustd; }; name = Release; }; @@ -49499,7 +49083,6 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49516,7 +49099,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNINITIALIZED_AUTOS = YES; INFOPLIST_FILE = OSX/authd/Info.plist; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; MTL_ENABLE_DEBUG_INFO = YES; @@ -49532,7 +49115,6 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49550,7 +49132,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNINITIALIZED_AUTOS = YES; INFOPLIST_FILE = OSX/authd/Info.plist; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; MTL_ENABLE_DEBUG_INFO = NO; @@ -49569,7 +49151,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49617,7 +49198,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49661,7 +49241,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49705,7 +49284,6 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49744,17 +49322,25 @@ buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; EXECUTABLE_PREFIX = lib; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -49763,17 +49349,24 @@ buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; EXECUTABLE_PREFIX = lib; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -49782,13 +49375,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49800,7 +49391,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -49824,13 +49414,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -49843,7 +49431,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -49861,7 +49448,6 @@ buildSettings = { APPLY_RULES_IN_COPY_FILES = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_STRICT_PROTOTYPES = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -49885,7 +49471,6 @@ buildSettings = { APPLY_RULES_IN_COPY_FILES = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_STRICT_PROTOTYPES = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -49908,7 +49493,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -49932,7 +49516,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -49956,7 +49539,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -49969,7 +49551,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -49982,7 +49563,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -49995,7 +49575,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -50008,7 +49587,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -50021,7 +49599,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -50035,18 +49612,15 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -50069,11 +49643,9 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -50082,7 +49654,6 @@ COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -50099,7 +49670,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = YES; @@ -50112,7 +49682,6 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; MTL_ENABLE_DEBUG_INFO = NO; @@ -50126,11 +49695,9 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -50168,11 +49735,9 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -50210,11 +49775,9 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -50245,11 +49808,9 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -50280,11 +49841,9 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -50324,11 +49883,9 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -50406,6 +49963,7 @@ "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -50457,6 +50015,7 @@ "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -50523,13 +50082,11 @@ E7B01BF0166594AB000485F1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -50575,13 +50132,11 @@ E7B01BF1166594AB000485F1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PRECOMPILE_PREFIX_HEADER = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -50638,7 +50193,6 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50657,7 +50211,6 @@ DYLIB_CURRENT_VERSION = 1; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_VERSION = A; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -50674,7 +50227,6 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_MOBILEGESTALT)", "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)", "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)", ); @@ -50684,7 +50236,7 @@ TAPI_VERIFY_MODE = ErrorsOnly; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; - WARNING_CFLAGS = "-Wno-objc-designated-initializers"; + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -50692,7 +50244,6 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50712,7 +50263,6 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_VERSION = A; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -50724,7 +50274,6 @@ MODULEMAP_FILE = Modules/KeychainCircle.modulemap; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_MOBILEGESTALT)", "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)", "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)", ); @@ -50742,7 +50291,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50757,7 +50305,6 @@ COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -50819,7 +50366,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50836,7 +50382,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -50895,7 +50440,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50911,7 +50455,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -50952,7 +50495,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50969,7 +50511,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -51005,13 +50546,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -51023,7 +50562,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -51047,13 +50585,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -51066,7 +50602,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -51083,9 +50618,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; COPY_PHASE_STRIP = NO; @@ -51093,7 +50626,6 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; @@ -51110,9 +50642,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; COPY_PHASE_STRIP = NO; @@ -51120,7 +50650,6 @@ DYLIB_CURRENT_VERSION = 1; ENABLE_NS_ASSERTIONS = NO; EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = "$(SECURITY_FUZZER_BASE_DIR)/lib"; @@ -51136,7 +50665,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51151,7 +50679,6 @@ COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; @@ -51206,6 +50733,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainCircle.KeychainCircleTests; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_TEXT_BASED_API = YES; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Debug; }; @@ -51214,7 +50742,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51231,7 +50758,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -51283,6 +50809,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainCircle.KeychainCircleTests; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_TEXT_BASED_API = YES; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Release; }; @@ -51292,12 +50819,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "keychain/ckksctl/ckksctl-Entitlements.plist"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; @@ -51312,14 +50837,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "keychain/ckksctl/ckksctl-Entitlements.plist"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = NO; @@ -51331,7 +50854,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51346,7 +50868,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -51386,7 +50907,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51402,7 +50922,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -51438,7 +50957,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51454,7 +50972,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -51495,7 +51012,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51512,7 +51028,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -51547,7 +51062,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51563,7 +51077,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -51603,7 +51116,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51620,7 +51132,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -51658,7 +51169,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; @@ -51684,10 +51194,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ( @@ -51706,6 +51213,7 @@ "-framework", Security, "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.Security.secdmockaks; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -51720,7 +51228,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; @@ -51746,10 +51253,7 @@ INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", ); MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ( @@ -51768,6 +51272,7 @@ "-framework", Security, "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.Security.secdmockaks; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -51810,10 +51315,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = YES; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -51852,10 +51354,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = YES; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -51879,10 +51378,8 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -51916,10 +51413,8 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -51995,10 +51490,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = YES; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -52034,10 +51526,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = YES; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -52045,7 +51534,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52060,7 +51548,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -52100,7 +51587,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52116,7 +51602,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -52165,7 +51650,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52181,7 +51665,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -52221,7 +51704,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52238,7 +51720,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -52269,6 +51750,74 @@ }; name = Release; }; + EBAFC9B42551C2710034B78D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INFOPLIST_FILE = tests/SecLegacyCodeRegressions/Info.plist; + INSTALL_PATH = /AppleInternal/XCTests/com.apple.security/; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = ( + "-framework", + Security, + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.apple.legacyCodeRegressions; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + EBAFC9B52551C2710034B78D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INFOPLIST_FILE = tests/SecLegacyCodeRegressions/Info.plist; + INSTALL_PATH = /AppleInternal/XCTests/com.apple.security/; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = ( + "-framework", + Security, + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.apple.legacyCodeRegressions; + PRODUCT_NAME = "$(TARGET_NAME)"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; EBB696031BE1F9DE00715F16 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -52284,12 +51833,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = "$(SECURITY_FUZZER_BASE_DIR)"; @@ -52303,13 +51850,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = "$(SECURITY_FUZZER_BASE_DIR)"; MTL_ENABLE_DEBUG_INFO = NO; @@ -52327,7 +51872,15 @@ DEBUG_INFORMATION_FORMAT = dwarf; INFOPLIST_FILE = OSX/utilities/test/Info.plist; INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = "$(OCMOCK_RUNTIME_SEARCH_PATH)"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-framework", + Security, + ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SecurityUtilitiesTests; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = NO; @@ -52344,7 +51897,15 @@ ENABLE_NS_ASSERTIONS = NO; INFOPLIST_FILE = OSX/utilities/test/Info.plist; INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = "$(OCMOCK_RUNTIME_SEARCH_PATH)"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "$(LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA)", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-framework", + Security, + ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SecurityUtilitiesTests; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = NO; @@ -52357,7 +51918,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52373,7 +51933,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -52414,7 +51973,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52431,7 +51989,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -52467,15 +52024,12 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "security-sysdiagnose/security-sysdiagnose.entitlements.plist"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/libexec; @@ -52489,17 +52043,14 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "security-sysdiagnose/security-sysdiagnose.entitlements.plist"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/libexec; MTL_ENABLE_DEBUG_INFO = NO; @@ -52512,12 +52063,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++98"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; @@ -52549,12 +52098,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++98"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; @@ -52586,12 +52133,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; @@ -52607,13 +52152,11 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; MTL_ENABLE_DEBUG_INFO = NO; @@ -52697,20 +52240,29 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0C9AEEB420783FBB00BF6237 /* Build configuration list for PBXNativeTarget "SignInAnalyticsTests_osx" */ = { + 0CA378E323876DD100090B7E /* Build configuration list for PBXAggregateTarget "reset_account" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0C9AEEB520783FBB00BF6237 /* Debug */, - 0C9AEEB620783FBB00BF6237 /* Release */, + 0CA378E423876DD100090B7E /* Debug */, + 0CA378E523876DD100090B7E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0CF4064D2072E3E3003D6A7F /* Build configuration list for PBXNativeTarget "SignInAnalyticsTests_ios" */ = { + 0CCC227623F357EE00E1FCD0 /* Build configuration list for PBXNativeTarget "OctagonTrustTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0CF4064E2072E3E3003D6A7F /* Debug */, - 0CF4064F2072E3E3003D6A7F /* Release */, + 0CCC227723F357EE00E1FCD0 /* Debug */, + 0CCC227823F357EE00E1FCD0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CD743AB23C3EC8000FA0EC5 /* Build configuration list for PBXNativeTarget "OctagonTrust" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CD743AC23C3EC8000FA0EC5 /* Debug */, + 0CD743AD23C3EC8000FA0EC5 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -52751,6 +52303,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 3E4D49B92531170600B124B3 /* Build configuration list for PBXNativeTarget "secsecstaticcodeapitest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E4D49BA2531170600B124B3 /* Debug */, + 3E4D49BB2531170600B124B3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3E88360E24F068EF00E9F4D6 /* Build configuration list for PBXNativeTarget "secseccodeapitest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E88360F24F068EF00E9F4D6 /* Debug */, + 3E88361024F068EF00E9F4D6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 438169381B4EDCBD00C54D58 /* Build configuration list for PBXNativeTarget "SOSCCAuthPlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -52787,7 +52357,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests_ios" */ = { + 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests" */ = { isa = XCConfigurationList; buildConfigurations = ( 4727FBBC1F9918590003AE36 /* Debug */, @@ -52823,15 +52393,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 478D42991FD72A8100CAB645 /* Build configuration list for PBXNativeTarget "secdxctests_mac" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 478D429A1FD72A8100CAB645 /* Debug */, - 478D429B1FD72A8100CAB645 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 47C2F1872059CB690062DE30 /* Build configuration list for PBXNativeTarget "KeychainResources" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -52976,6 +52537,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 6C2045EE2424BA7F00F9461D /* Build configuration list for PBXNativeTarget "KeychainStasher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6C2045EF2424BA7F00F9461D /* Debug */, + 6C2045F02424BA7F00F9461D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 6C39237621F13E4D00D018AD /* Build configuration list for PBXNativeTarget "SecDbBackupTests" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -52994,20 +52564,20 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6C98085E1E788AEB00E70590 /* Build configuration list for PBXNativeTarget "CKKSCloudKitTests_mac" */ = { + 6C7BE2E423C3DD64003BB2CA /* Build configuration list for PBXNativeTarget "securitytool_bridge" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6C98085F1E788AEB00E70590 /* Debug */, - 6C9808601E788AEB00E70590 /* Release */, + 6C7BE2E523C3DD64003BB2CA /* Debug */, + 6C7BE2E623C3DD64003BB2CA /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6C98089A1E788AFD00E70590 /* Build configuration list for PBXNativeTarget "CKKSCloudKitTests_ios" */ = { + 6C963288242A279B00C53CE2 /* Build configuration list for PBXNativeTarget "stashtester" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6C98089B1E788AFD00E70590 /* Debug */, - 6C98089C1E788AFD00E70590 /* Release */, + 6C963285242A279B00C53CE2 /* Debug */, + 6C963286242A279B00C53CE2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -53039,7 +52609,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp_mac" */ = { + 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 6CF4A0C51E45488B00ECD7B5 /* Debug */, @@ -53048,15 +52618,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6CF4A0F41E4549F300ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp_ios" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6CF4A0F51E4549F300ECD7B5 /* Debug */, - 6CF4A0F61E4549F300ECD7B5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 790851C90CA985C10083CC4D /* Build configuration list for PBXNativeTarget "securityd_ios" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -53201,6 +52762,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D445B310258C07FD0019858E /* Build configuration list for PBXNativeTarget "trustdFileHelper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D445B311258C07FD0019858E /* Debug */, + D445B312258C07FD0019858E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D44D1F6E2115893000E76E1A /* Build configuration list for PBXNativeTarget "CMS" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -54705,6 +54275,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + EBAFC9B32551C2710034B78D /* Build configuration list for PBXNativeTarget "SecLegacyCodeRegressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EBAFC9B42551C2710034B78D /* Debug */, + EBAFC9B52551C2710034B78D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; EBB839A91E29665E00853BAC /* Build configuration list for PBXNativeTarget "secfuzzer" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Security.xcodeproj/xcshareddata/xcschemes/CKKSTests.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/CKKSTests.xcscheme index c30a62b4..ac6fde2d 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/CKKSTests.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/CKKSTests.xcscheme @@ -1,6 +1,6 @@ + + @@ -50,8 +53,6 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/SecureTransportTests_macos.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/SecureTransportTests_macos.xcscheme new file mode 100644 index 00000000..f2cae49c --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/SecureTransportTests_macos.xcscheme @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_ios.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_ios.xcscheme index 3fbabf06..eca0a91a 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_ios.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_ios.xcscheme @@ -1,6 +1,6 @@ + buildForAnalyzing = "YES"> + onlyGenerateCoverageForSpecifiedTargets = "YES"> - - - - - - + allowLocationSimulation = "YES" + internalIOSLaunchStyle = "0"> - - - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_macos.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_macos.xcscheme index 42212060..d829f6b1 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_macos.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_macos.xcscheme @@ -1,6 +1,6 @@ + onlyGenerateCoverageForSpecifiedTargets = "YES"> - - - - - - - - + shouldUseLaunchSchemeArgsEnv = "YES" + codeCoverageEnabled = "YES"> @@ -40,17 +40,6 @@ - - - - - - - - - - - - @@ -71,16 +62,6 @@ ReferencedContainer = "container:Security.xcodeproj"> - - - - + allowLocationSimulation = "YES" + internalIOSLaunchStyle = "0"> @@ -242,48 +224,16 @@ argument = "si_17_item_system_bluetooth" isEnabled = "NO"> - - - - - - - - - - - - - - - - - - @@ -386,10 +332,6 @@ argument = "si_66_smime" isEnabled = "NO"> - - @@ -398,14 +340,6 @@ argument = "si_69_keydesc" isEnabled = "NO"> - - - - @@ -414,10 +348,6 @@ argument = "si_73_secpasswordgenerate" isEnabled = "NO"> - - @@ -430,18 +360,6 @@ argument = "si_80_empty_data" isEnabled = "NO"> - - - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/ios - Release.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/ios - Release.xcscheme index 11eaea1e..caacd3f4 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/ios - Release.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/ios - Release.xcscheme @@ -1,6 +1,6 @@ - - - - @@ -201,39 +192,11 @@ isEnabled = "NO"> - - - - - - - - - - - - - - - - @@ -324,10 +283,6 @@ argument = "si_66_smime" isEnabled = "NO"> - - @@ -336,14 +291,6 @@ argument = "si_69_keydesc" isEnabled = "NO"> - - - - @@ -352,10 +299,6 @@ argument = "si_73_secpasswordgenerate" isEnabled = "NO"> - - @@ -372,22 +315,6 @@ argument = "si-81-item-acl-stress" isEnabled = "NO"> - - - - - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/ios - secdtests.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/ios - secdtests.xcscheme index d1fcb4cf..15062dd9 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/ios - secdtests.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/ios - secdtests.xcscheme @@ -1,6 +1,6 @@ - - - - - - - - + + + + - - - - @@ -67,16 +72,6 @@ ReferencedContainer = "container:Security.xcodeproj"> - - - - + + + + + + + + + + @@ -263,10 +282,6 @@ argument = "smime_cms_test" isEnabled = "NO"> - - @@ -275,62 +290,22 @@ argument = "kc_41_sececkey" isEnabled = "NO"> - - - - - - - - - - - - - - - - - - - - @@ -339,6 +314,10 @@ argument = "si_35_cms_expiration_time" isEnabled = "NO"> + + @@ -391,34 +370,6 @@ argument = "si_68_secmatchissuer" isEnabled = "NO"> - - - - - - - - - - - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme index 30a0789a..efb0ae22 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme @@ -1,6 +1,6 @@ - - - - @@ -212,6 +203,10 @@ argument = "secd_61_account_leave_not_in_kansas_anymore" isEnabled = "NO"> + + @@ -224,6 +219,10 @@ argument = "secd_71_engine_save" isEnabled = "NO"> + + @@ -288,11 +287,27 @@ argument = "secd_230_keybagtable" isEnabled = "NO"> + + + + + + + + - - - - - - - - - - - - 123456.test.group 123456.test.group2 com.apple.bluetooth + com.apple.token com.apple.developer.associated-domains webcredentials:localhost + com.apple.private.security.storage.Keychains + diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_Root.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_Root.cer new file mode 100644 index 00000000..70cd9625 Binary files /dev/null and b/SecurityTests/ssl-policy-certs/subCA_EKU_Root.cer differ diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_ca.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_ca.cer new file mode 100644 index 00000000..f32740db Binary files /dev/null and b/SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_ca.cer differ diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_leaf.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_leaf.cer new file mode 100644 index 00000000..bdb982a1 Binary files /dev/null and b/SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_leaf.cer differ diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_ca.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_ca.cer new file mode 100644 index 00000000..c2236694 Binary files /dev/null and b/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_ca.cer differ diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_leaf.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_leaf.cer new file mode 100644 index 00000000..b5763b8a Binary files /dev/null and b/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_leaf.cer differ diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_smime_ca.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_smime_ca.cer new file mode 100644 index 00000000..7342c2f7 Binary files /dev/null and b/SecurityTests/ssl-policy-certs/subCA_EKU_smime_ca.cer differ diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_smime_leaf.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_smime_leaf.cer new file mode 100644 index 00000000..0a1651ca Binary files /dev/null and b/SecurityTests/ssl-policy-certs/subCA_EKU_smime_leaf.cer differ diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_ca.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_ca.cer new file mode 100644 index 00000000..58ed701e Binary files /dev/null and b/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_ca.cer differ diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_leaf.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_leaf.cer new file mode 100644 index 00000000..8531402b Binary files /dev/null and b/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_leaf.cer differ diff --git a/SecurityTool/macOS/authz.c b/SecurityTool/macOS/authz.c index 00208dd4..de5579f7 100644 --- a/SecurityTool/macOS/authz.c +++ b/SecurityTool/macOS/authz.c @@ -678,10 +678,11 @@ authorize(int argc, char * const *argv) retval = (status ? -1 : 0); bail: - if (rights) + if (rights) { free(rights); - - return retval; + } + + return retval; } diff --git a/SecurityTool/macOS/cmsutil.c b/SecurityTool/macOS/cmsutil.c index 1d06dfa6..bfcecedf 100644 --- a/SecurityTool/macOS/cmsutil.c +++ b/SecurityTool/macOS/cmsutil.c @@ -63,7 +63,7 @@ #include #include #include -#include +#include #include #include diff --git a/SecurityTool/macOS/createFVMaster.c b/SecurityTool/macOS/createFVMaster.c index 34e55fec..9965ce02 100644 --- a/SecurityTool/macOS/createFVMaster.c +++ b/SecurityTool/macOS/createFVMaster.c @@ -45,7 +45,7 @@ #include "srCdsaUtils.h" -#include +#include const char * const _masterKeychainName = "FileVaultMaster.keychain"; const char * const _masterKeychainPath = "./FileVaultMaster"; @@ -101,8 +101,11 @@ OSStatus makeMasterPassword(const char *fvmkcName, const char *masterPasswordPas OSStatus status = SecKeychainCreate(fvmkcName, (UInt32) strlen(masterPasswordPassword), masterPasswordPassword, false, initialAccess, keychainRef); if (status!=noErr) { - if (status==errSecDuplicateKeychain || status==CSSMERR_DL_DATASTORE_ALREADY_EXISTS) + if (status==errSecDuplicateKeychain || status==CSSMERR_DL_DATASTORE_ALREADY_EXISTS) { sec_error("The keychain file %s already exists", fvmkcName); + } else if (status != errSecSuccess) { + sec_error("Could not create keychain file %s: %s", fvmkcName, sec_errstr(status)); + } return status; } @@ -199,18 +202,24 @@ OSStatus createPair(CFStringRef hostName,CFStringRef userName,SecKeychainRef key // cleanup xit: - if (certRef) + if (certRef) { CFRelease(certRef); - if (certData.Data) + } + if (certData.Data) { free(certData.Data); - if (hostStr) - free(hostStr); - if (userStr) - free(userStr); - if (tpHand) - CSSM_ModuleDetach(tpHand); - if (clHand) - CSSM_ModuleDetach(clHand); + } + if (hostStr) { + free(hostStr); + } + if (userStr) { + free(userStr); + } + if (tpHand) { + CSSM_ModuleDetach(tpHand); + } + if (clHand) { + CSSM_ModuleDetach(clHand); + } if (pubKey) { CSSM_FreeKey(cspHand, @@ -707,8 +716,9 @@ keychain_createMFV(int argc, char * const *argv) return SHOW_USAGE_MESSAGE; keychainName = (argc == 1)?*argv:_masterKeychainName; - if (!keychainName || *keychainName == '\0') + if (!keychainName || *keychainName == '\0') { return -1; + } if (!password && !do_prompt) { diff --git a/SecurityTool/macOS/db_commands.cpp b/SecurityTool/macOS/db_commands.cpp index 381501f9..89655f69 100644 --- a/SecurityTool/macOS/db_commands.cpp +++ b/SecurityTool/macOS/db_commands.cpp @@ -43,7 +43,7 @@ do_db_create(const CSSM_GUID guid, const char *dbname, Boolean do_openparams, Bo try { CSSM_APPLEDL_OPEN_PARAMETERS openParameters = { sizeof(CSSM_APPLEDL_OPEN_PARAMETERS), - (do_version_0_params ? 0 : CSSM_APPLEDL_OPEN_PARAMETERS_VERSION) }; + (do_version_0_params ? 0u : CSSM_APPLEDL_OPEN_PARAMETERS_VERSION) }; Cssm cssm; Module module(guid, cssm); DL dl(module); diff --git a/SecurityTool/macOS/fvunlock.h b/SecurityTool/macOS/fvunlock.h new file mode 100644 index 00000000..b1fa44b2 --- /dev/null +++ b/SecurityTool/macOS/fvunlock.h @@ -0,0 +1,10 @@ +// +// fvunlock.h +// SecurityTool + +#ifndef fvunlock_h +#define fvunlock_h + +int fvunlock(int argc, char * const *argv); + +#endif diff --git a/SecurityTool/macOS/fvunlock.m b/SecurityTool/macOS/fvunlock.m new file mode 100644 index 00000000..a387bd8e --- /dev/null +++ b/SecurityTool/macOS/fvunlock.m @@ -0,0 +1,228 @@ +// +// fvunlock.m +// SecurityTool + +#import + +#import "fvunlock.h" +#import "security_tool.h" +#import "Security/AuthorizationPriv.h" +#import +#import +#import +#import + +#if TARGET_OS_OSX && TARGET_CPU_ARM64 + +SOFT_LINK_FRAMEWORK(Frameworks, LocalAuthentication) +SOFT_LINK_CLASS(LocalAuthentication, LAContext) + +NSUUID *currentRecoveryVolumeUUID(void); + +static Boolean isInFVUnlock() +{ + return YES; + // temporary solution until we find a better way + // return getenv("__OSINSTALL_ENVIRONMENT") != NULL; +} + +#define kEFISystemVolumeUUIDVariableName "SystemVolumeUUID" +NSUUID *currentRecoveryVolumeUUID() +{ + NSData *data; + NSString * const LANVRAMNamespaceStartupManager = @"5EEB160F-45FB-4CE9-B4E3-610359ABF6F8"; + + NSString *key = [NSString stringWithFormat:@"%@:%@", LANVRAMNamespaceStartupManager, @kEFISystemVolumeUUIDVariableName]; + + io_registry_entry_t match = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options"); + if (match) { + CFTypeRef entry = IORegistryEntryCreateCFProperty(match, (__bridge CFStringRef)key, kCFAllocatorDefault, 0); + IOObjectRelease(match); + + if (entry) + { + if (CFGetTypeID(entry) == CFDataGetTypeID()) + data = CFBridgingRelease(entry); + else + CFRelease(entry); + } + } + + if (data) { + return [[NSUUID alloc] initWithUUIDBytes:data.bytes]; + } else { + return nil; + } +} + +static Boolean verifyUser() +{ + // first check if policy was already satisfied + __block Boolean verified = NO; + dispatch_semaphore_t ds = dispatch_semaphore_create(0); + LAContext *ctx = [[getLAContextClass() alloc] init]; + [ctx evaluatePolicy:LAPolicyUserAuthenticationWithPasscodeRecovery options:@{ @(LAOptionNotInteractive) : @YES } reply:^(NSDictionary *result, NSError *error) { + if (result) { + verified = YES; + } + dispatch_semaphore_signal(ds); + }]; + dispatch_semaphore_wait(ds, DISPATCH_TIME_FOREVER); + if (verified) { + // user was already authenticated, no need to prompt + return YES; + } + + // we need to prompt for the credentials + char buf[50]; + printf("Enter admin's username: "); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + // no input + os_log_error(OS_LOG_DEFAULT, "Unable to acquire username"); + return NO; + } + char *temp = getpass("Password: "); + NSString *username = [[NSString stringWithUTF8String:buf] stringByReplacingOccurrencesOfString:@"\n" withString:@""]; + NSString *password = [NSString stringWithUTF8String:temp]; + + if (username.length == 0 || password.length == 0) { + // no credentials + os_log_error(OS_LOG_DEFAULT, "Unable to get the credentials"); + return NO; + } + + // get the user GUID + CFArrayRef usersCf; + OSStatus status = AuthorizationCopyPreloginUserDatabase(NULL, 0, &usersCf); + if (status) { + // cannot get AIR + os_log_error(OS_LOG_DEFAULT, "AIR failed with error %d", status); + return NO; + } + NSArray *users = CFBridgingRelease(usersCf); + Boolean found = NO; + for (NSDictionary *record in users) { + if (![username isEqualToString:record[@PLUDB_USERNAME]]) { + continue; + } + if (![record[@PLUDB_ADMIN] isEqual:@YES]) { + // admins only + continue; + } + found = YES; + NSString *userGuid = record[@PLUDB_GUID]; + if (userGuid) { + ctx = [[getLAContextClass() alloc] init]; + NSDictionary *cred = @{ + @kLACredentialKeyUserGuid : userGuid, + @kLACredentialKeyPassword : password, + }; + NSError *error; + NSData *credData = [NSKeyedArchiver archivedDataWithRootObject:cred requiringSecureCoding:YES error:&error]; + if (credData == nil) { + os_log_error(OS_LOG_DEFAULT, "NSKeyedArchiver failed with error %{public}@", error); + continue; // try another user + } + + if ([ctx setCredential:credData type:LACredentialTypeRecoveryData error:&error]) { + return YES; // user was verified + } + } + } + + os_log_error(OS_LOG_DEFAULT, "Unable to verify user (found %d)", found); + return NO; +} + +static int enforcementWorker(const char operation, NSUUID *volumeUuid) +{ + // first ensure we are in a Recovery + if (!isInFVUnlock()) { + fprintf(stderr, "This command is available only when booted to Recovery\n"); + return -1; + } + + // then authenticate user + if (!verifyUser()) { + fprintf(stderr, "Unable to verify an administrator\n"); + return -3; + } + + // then call authd + Boolean enabled = false; + OSStatus retval = AuthorizationHandlePreloginOverride(volumeUuid.UUIDString.UTF8String, operation, &enabled); + switch (operation) { + case kAuthorizationOverrideOperationSet: + if (retval != noErr) { + fprintf(stderr, "Error %d when trying to set the SmartCard enforcement override\n", retval); + } else { + fprintf(stdout, "SmartCard enforcement is temporarily turned off for the next boot\n"); + } + break; + case kAuthorizationOverrideOperationReset: + if (retval != noErr) { + fprintf(stderr, "Error %d when trying to reset the SmartCard enforcement override\n", retval); + } else { + fprintf(stdout, "SmartCard enforcement override was reset\n"); + } + break; + case kAuthorizationOverrideOperationQuery: + if (retval != noErr) { + fprintf(stderr, "Error %d when trying to get the SmartCard enforcement state\n", retval); + } else { + fprintf(stdout, "SmartCard enforcement is%s temporarily turned off for the next boot\n", enabled ? "" : " not"); + } + break; + default: + fprintf(stderr, "Unsupported operation\n"); + break; + } + + return retval; +} + +static int skipScEnforcement(int argc, char * const *argv) +{ + NSUUID *systemVolumeUuid = [[NSUUID UUID] initWithUUIDString:[[NSString alloc] initWithUTF8String:argv[1]]]; + if (!systemVolumeUuid) { + fprintf(stderr, "System volume UUID %s was not recognized\n", argv[1]); + return -4; + } + // look if system volume exists at all + CFArrayRef cfUsers; + OSStatus status = AuthorizationCopyPreloginUserDatabase(argv[1], 0, &cfUsers); + NSArray *users = CFBridgingRelease(cfUsers); + if (status) { + fprintf(stderr, "System volume error\n"); + return -5; + } + if (users.count == 0) { + fprintf(stderr, "System volume with UUID %s is not supported\n", argv[1]); + return -6; + } + + if (!strcmp("set", argv[2])) { + return enforcementWorker(kAuthorizationOverrideOperationSet, systemVolumeUuid); + } else if (!strcmp("reset", argv[2])) { + return enforcementWorker(kAuthorizationOverrideOperationReset, systemVolumeUuid); + } else if (!strcmp("status", argv[2])) { + return enforcementWorker(kAuthorizationOverrideOperationQuery, systemVolumeUuid); + } + + return SHOW_USAGE_MESSAGE; +} + +int fvunlock(int argc, char * const *argv) { + int result = SHOW_USAGE_MESSAGE; + require_quiet(argc > 3, out); // three arguments needed + @autoreleasepool { + if (!strcmp("skip-sc-enforcement", argv[1])) { + result = skipScEnforcement(argc - 1, argv + 1); + } + } + +out: + return result; +} + +#endif diff --git a/SecurityTool/macOS/identity_find.m b/SecurityTool/macOS/identity_find.m index 1b3e562f..932361ed 100644 --- a/SecurityTool/macOS/identity_find.m +++ b/SecurityTool/macOS/identity_find.m @@ -391,7 +391,7 @@ do_identity_search_with_policy(CFTypeRef keychainOrArray, safe_CFRelease(&idStr); safe_CFRelease(&policy); - safe_CFRelease(policySearch); + safe_CFRelease(&policySearch); } static void diff --git a/SecurityTool/macOS/key_create.c b/SecurityTool/macOS/key_create.c index e14f64d2..8e5688f7 100644 --- a/SecurityTool/macOS/key_create.c +++ b/SecurityTool/macOS/key_create.c @@ -163,11 +163,13 @@ parse_time(const char *time, CFAbsoluteTime *ptime) sec_error("%s is not a valid date", time); result = 1; } - if (formatter) + if (formatter) { CFRelease(formatter); - if (time_string) + } + if (time_string) { CFRelease(time_string); - return result; + } + return result; } int diff --git a/SecurityTool/macOS/keychain_add.c b/SecurityTool/macOS/keychain_add.c index 506ea3a0..cd5dc33e 100644 --- a/SecurityTool/macOS/keychain_add.c +++ b/SecurityTool/macOS/keychain_add.c @@ -764,14 +764,17 @@ keychain_add_generic_password(int argc, char * const *argv) update_item); cleanup: - if (mustFreePasswordData) + if (mustFreePasswordData) { free(passwordData); - if (trusted_list) - CFRelease(trusted_list); - if (access) - CFRelease(access); + } + if (trusted_list) { + CFRelease(trusted_list); + } + if (access) { + CFRelease(access); + } - return result; + return result; } int @@ -976,12 +979,15 @@ keychain_add_internet_password(int argc, char * const *argv) update_item); cleanup: - if (mustFreePasswordData) + if (mustFreePasswordData) { free(passwordData); - if (trusted_list) - CFRelease(trusted_list); - if (access) - CFRelease(access); + } + if (trusted_list) { + CFRelease(trusted_list); + } + if (access) { + CFRelease(access); + } return result; } diff --git a/SecurityTool/macOS/keychain_import.c b/SecurityTool/macOS/keychain_import.c index d27b211b..61e1401d 100644 --- a/SecurityTool/macOS/keychain_import.c +++ b/SecurityTool/macOS/keychain_import.c @@ -416,12 +416,14 @@ keychain_import(int argc, char * const *argv) if(kcName) { kcRef = keychain_open(kcName); if(kcRef == NULL) { - return 1; + result = 1; + goto cleanup; } } else { OSStatus status = SecKeychainCopyDefault(&kcRef); if (status != noErr || kcRef == NULL) { - return 1; + result = 1; + goto cleanup; } } if(readFileSizet(inFile, &inFileData, &inFileLen)) { diff --git a/SecurityTool/macOS/keychain_lock.c b/SecurityTool/macOS/keychain_lock.c index 20a8d549..3cb1670d 100644 --- a/SecurityTool/macOS/keychain_lock.c +++ b/SecurityTool/macOS/keychain_lock.c @@ -39,10 +39,11 @@ static int do_lock_all(void) { OSStatus result = SecKeychainLockAll(); - if (result) + if (result) { sec_perror("SecKeychainLockAll", result); + } - return result; + return result; } static int diff --git a/SecurityTool/macOS/keychain_utilities.c b/SecurityTool/macOS/keychain_utilities.c index bee380fc..ff8dd7eb 100644 --- a/SecurityTool/macOS/keychain_utilities.c +++ b/SecurityTool/macOS/keychain_utilities.c @@ -507,8 +507,9 @@ print_keychain_item_attributes(FILE *stream, SecKeychainItemRef item, Boolean sh fputs("version: ", stream); result = print_keychain_version(stream, keychain); fputc('\n', stream); - if (result) + if (result) { goto loser; + } /* First find out the item class. */ status = SecKeychainItemCopyAttributesAndData(item, NULL, &itemClass, NULL, NULL, NULL); @@ -903,7 +904,7 @@ fromHex(const char *hexDigits, CSSM_DATA *data) CFDataRef CF_RETURNS_RETAINED cfFromHex(CFStringRef hex) { // behavior is undefined if you pass in a non-hex string. Don't do that. - char* chex; + char* chex = NULL; size_t len; GetCStringFromCFString(hex, &chex, &len); @@ -916,6 +917,7 @@ cfFromHex(CFStringRef hex) { CFDataIncreaseLength(bin, bytes); if(!bin || (size_t) CFDataGetLength(bin) != bytes) { + free(chex); CFReleaseNull(bin); return NULL; } @@ -925,6 +927,7 @@ cfFromHex(CFStringRef hex) { data[i] = (uint8)(hexValue(chex[2*i]) << 4 | hexValue(chex[2*i+1])); } + free(chex); return bin; } diff --git a/SecurityTool/macOS/readline.c b/SecurityTool/macOS/readline.c index a6ef891a..3976cc6a 100644 --- a/SecurityTool/macOS/readline.c +++ b/SecurityTool/macOS/readline.c @@ -140,10 +140,12 @@ read_file(const char *name, CSSM_DATA *outData) return result; loser: - if (fd != -1) + if (fd != -1) { close(fd); - if (buffer) - free(buffer); + } + if (buffer) { + free(buffer); + } return result; } diff --git a/SecurityTool/macOS/requirement.c b/SecurityTool/macOS/requirement.c index 0215b80e..abb7fec7 100644 --- a/SecurityTool/macOS/requirement.c +++ b/SecurityTool/macOS/requirement.c @@ -62,6 +62,7 @@ int requirement_evaluate(int argc, char * const *argv) fprintf(stderr, "parsing requirement failed (%d): %s\n", status, errorStr); free(errorStr); + CFReleaseSafe(errorDesc); err = 1; } @@ -82,7 +83,7 @@ int requirement_evaluate(int argc, char * const *argv) } CFArrayAppendValue(certs, cert); - CFRelease(cert); + CFReleaseSafe(cert); } // Evaluate! diff --git a/SecurityTool/macOS/security.c b/SecurityTool/macOS/security.c index 6aba03ed..69b65338 100644 --- a/SecurityTool/macOS/security.c +++ b/SecurityTool/macOS/security.c @@ -58,6 +58,7 @@ #include "smartcards.h" #include "translocate.h" #include "requirement.h" +#include "fvunlock.h" #include #include @@ -745,7 +746,16 @@ const command commands[] = " [ ...]\n" "Evaluates the given requirement string against the given cert chain.", "Evaluate a requirement against a cert chain." }, - +#if TARGET_OS_OSX && TARGET_CPU_ARM64 + { "filevault" , fvunlock, + "skip-sc-enforcement \n" + " data volume UUID can by obtained by running diskutil apfs list" + " operation is one of the following:" + " set Sets SmartCard enforcement to be skipped for the next boot\n" + " reset Resets any SmartCard overrides\n" + " status Tells the current state of the SmartCard overrides\n", + "Handles FileVault specific settings and overrides."}, +#endif {} }; diff --git a/SecurityTool/macOS/securitytool-entitlements.plist b/SecurityTool/macOS/securitytool-entitlements.plist new file mode 100644 index 00000000..5827ec9e --- /dev/null +++ b/SecurityTool/macOS/securitytool-entitlements.plist @@ -0,0 +1,8 @@ + + + + + com.apple.authorization.smartcard.override + + + diff --git a/SecurityTool/macOS/trusted_cert_ssl.m b/SecurityTool/macOS/trusted_cert_ssl.m index 24ee1bf8..18effdf6 100644 --- a/SecurityTool/macOS/trusted_cert_ssl.m +++ b/SecurityTool/macOS/trusted_cert_ssl.m @@ -109,14 +109,16 @@ - (id)initWithURLString:(const char *)urlstr verbose:(int)level { - _url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%s", urlstr]]; - _udp = NO; - _finished = NO; - _verbose = level; - _error = nil; - _trust = NULL; - _queue = dispatch_get_main_queue(); - _connection = [self createConnection]; + if ((self = [super init])) { + _url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%s", urlstr]]; + _udp = NO; + _finished = NO; + _verbose = level; + _error = nil; + _trust = NULL; + _queue = dispatch_get_main_queue(); + _connection = [self createConnection]; + } return self; } diff --git a/SecurityTool/sharedTool/KeychainCheck.m b/SecurityTool/sharedTool/KeychainCheck.m index 724082bd..1eb76c7d 100644 --- a/SecurityTool/sharedTool/KeychainCheck.m +++ b/SecurityTool/sharedTool/KeychainCheck.m @@ -137,15 +137,9 @@ int verify_backup_integrity(int argc, char * const *argv) { } NSLog(@"Running backup integrity validation in %@ mode", lightweight ? @"lightweight" : @"default"); - dispatch_semaphore_t sema = dispatch_semaphore_create(0); SecItemVerifyBackupIntegrity(lightweight, ^(NSDictionary* results, NSError *error) { NSLog(@"%@", results); - dispatch_semaphore_signal(sema); }); - if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 30))) { - NSLog(@"Timed out waiting for backup integrity validation"); - } - return 0; } diff --git a/SecurityTool/sharedTool/SecurityCommands.h b/SecurityTool/sharedTool/SecurityCommands.h index 1792878a..fd44d8a4 100644 --- a/SecurityTool/sharedTool/SecurityCommands.h +++ b/SecurityTool/sharedTool/SecurityCommands.h @@ -41,9 +41,11 @@ SECURITY_COMMAND("item", keychain_item, "SAC object for deleting item added by default\n", "Manipulate keychain items.") +#if !TARGET_OS_BRIDGE SECURITY_COMMAND("policy-dryrun", policy_dryrun, "", "Try to evaluate policy old/new.") +#endif SECURITY_COMMAND("keychain-item-digest", keychain_item_digest, "itemClass keychainAccessGroup\n" @@ -223,3 +225,59 @@ SECURITY_COMMAND("show-ct-exceptions", show_ct_exceptions, " -c Output certificate exceptions (as SPKI hash).\n" " Default is both domains and certs.\n", "Display exceptions for Certificate Transparency enforcement in json.") + +SECURITY_COMMAND("add-ca-revocation-checking", add_ca_revocation_checking, + "[options]\n" + " -c cert Cert for which revocation checking should be enabled.\n" + " Specify a CA cert to enable checking for all its issued certs.\n" + " Can be specified multiple times.\n" + " -p plist plist containing entries to enable explicit revocation checking.\n" + " Resets existing entries, if present.\n" + " Overrides -c\n" + " For detailed specification, see SecTrustSettingsPriv.h.\n" + " -r which Resets cert entries for \"cert\" or \"all\".\n" + " Overrides -c and -p\n", + "Specify additional CA certs for which revocation checking is enabled") + +SECURITY_COMMAND("show-ca-revocation-checking", show_ca_revocation_checking, + "[options]\n" + " -a Output all combined CA revocation checking additions.\n" + " -i identifier Output CA revocation additions for specified identifier.\n" + " Default is the additions for this tool. Overridden by -a.\n" + " -c Output CA revocation additions (as certificate SPKI hash).\n", + "Display CA revocation checking additions in json.") + +SECURITY_COMMAND("add-trust-config", add_trust_config, + "-t [options]\n" + " -t configurationType Config type to add, one of:\n" + " \"ct-exceptions\",\n" + " \"ca-revocation-checking\",\n" + " \"transparent-connection-pins\"\n" + " -d domain For \"ct-exceptions\" only, domain to add.\n" + " Can be specified multiple times.\n" + " -c cert Cert for which specified configuration type should be enabled.\n" + " Can be specified multiple times.\n" + " -p plist plist containing entries to enable specified configuration type.\n" + " Resets existing entries, if present.\n" + " Overrides -c and -d \n" + " For detailed specification, see SecTrustSettingsPriv.h.\n" + " -r which Reset configuration for \"domain\" (for ct-exceptions only),\n" + " \"cert\", or\n" + " \"all\".\n" + " Overrides -d, -c, and -p\n", + "Set trust evaluation configuration") + +SECURITY_COMMAND("show-trust-config", show_trust_config, + "-t [options]\n" + " -t configurationType Config type to add, one of:\n" + " \"ct-exceptions\",\n" + " \"ca-revocation-checking\",\n" + " \"transparent-connection-pins\"\n" + " -a Output all combined configuration.\n" + " -i identifier Output configuration for specified identifier.\n" + " Default is configuration for this tool. Overridden by -a.\n" + " -d For \"ct-exceptions\" only, output domain exceptions.\n" + " Default is both domains and certs.\n" + " -c Output certificate exceptions (as SPKI hash).\n" + " Default is both domains and certs.\n", + "Display trust evaluation configuration in json.") diff --git a/SecurityTool/sharedTool/add_internet_password.c b/SecurityTool/sharedTool/add_internet_password.c index 1a8f54d8..7599c9c5 100644 --- a/SecurityTool/sharedTool/add_internet_password.c +++ b/SecurityTool/sharedTool/add_internet_password.c @@ -93,14 +93,16 @@ do_addinternetpassword(const char *keychainName, const char *serverName, /* @@@ For performance reasons we could choose to make the dictionaries CFRetain callback a no op and let the dictionary deal with the releasing. */ - for (; ix-- > 0;) + for (; ix-- > 0;) { CFRelease(values[ix]); + } result = SecItemAdd(attributes, NULL); - if (attributes) + if (attributes) { CFRelease(attributes); - + } + if (result) { sec_perror("SecItemAdd", result); diff --git a/SecurityTool/sharedTool/builtin_commands.h b/SecurityTool/sharedTool/builtin_commands.h index 8e57592a..79783228 100644 --- a/SecurityTool/sharedTool/builtin_commands.h +++ b/SecurityTool/sharedTool/builtin_commands.h @@ -23,6 +23,7 @@ #include "SecurityTool/sharedTool/security_tool_commands.h" +#include SECURITY_COMMAND("help", help, "[command ...]", @@ -40,6 +41,7 @@ SECURITY_COMMAND("whoami", command_whoami, "", "Ask securityd who you are.") +#if !TARGET_OS_BRIDGE SECURITY_COMMAND("sos-stats", command_sos_stats, "", "SOS for performance numbers.") @@ -60,6 +62,7 @@ SECURITY_COMMAND("watchdog", command_watchdog, " check-period \n" " graceful-exit-time \n", "Show current watchdog parameters or set an individual parameter") +#endif SECURITY_COMMAND("keychain-check", command_keychain_check, "", diff --git a/SecurityTool/sharedTool/ca_revocation_additions.m b/SecurityTool/sharedTool/ca_revocation_additions.m new file mode 100644 index 00000000..b725ac49 --- /dev/null +++ b/SecurityTool/sharedTool/ca_revocation_additions.m @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * ca_revocation_additions.m + */ + +#import +#include +#include +#include +#include + +#include "SecurityCommands.h" + +NSString* secToolAppID = @"com.apple.security"; + +static int addCertFile(const char *fileName, NSMutableArray *array) { + SecCertificateRef certRef = NULL; + NSData *data = NULL; + unsigned char *buf = NULL; + size_t numBytes; + int rtn = 0; + + if (readFileSizet(fileName, &buf, &numBytes)) { + rtn = -1; + goto errOut; + } + + data = [NSData dataWithBytes:buf length:numBytes]; + certRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data); + if (!certRef) { + certRef = SecCertificateCreateWithPEM(NULL, (__bridge CFDataRef)data); + if (!certRef) { + rtn = -1; + goto errOut; + } + } + + [array addObject:(__bridge id)certRef]; + +errOut: + /* Cleanup */ + free(buf); + CFReleaseNull(certRef); + return rtn; +} + +static int returnCFError(CFErrorRef CF_CONSUMED error) { + CFStringRef errorString = CFErrorCopyDescription(error); + CFStringPerformWithCString(errorString, ^(const char *utf8Str) { + fprintf(stderr, "Failed to copy CA revocation additions: %s\n", utf8Str); + }); + CFIndex errCode = CFErrorGetCode(error); + CFReleaseNull(error); + return (int)errCode; +} + +static int resetRevocationAdditions(bool resetCerts) { + bool result = false; + CFErrorRef error = NULL; + if (resetCerts) { + NSDictionary *resetCertsDict = @{ (__bridge NSString*)kSecCARevocationAdditionsKey: @[] }; + result = SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)resetCertsDict, &error); + } + if (!result) { + return returnCFError(error); + } + return 0; +} + +static int addRevocationAdditions(CFStringRef key, NSArray *newAdditions) { + CFErrorRef error = NULL; + NSDictionary *currentAdditions = CFBridgingRelease(SecTrustStoreCopyCARevocationAdditions((__bridge CFStringRef)secToolAppID, &error)); + if (!currentAdditions && error) { + return returnCFError(error); + } + + NSMutableArray *additionsForKey = nil; + if (currentAdditions && currentAdditions[(__bridge NSString*)key]) { + additionsForKey = [currentAdditions[(__bridge NSString*)key] mutableCopy]; + [additionsForKey addObjectsFromArray:newAdditions]; + } else { + additionsForKey = [newAdditions copy]; + } + + NSDictionary *newAdditionsDict = @{ (__bridge NSString*)key: additionsForKey }; + bool result = SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)newAdditionsDict, &error); + if (!result) { + return returnCFError(error); + } + + return 0; +} + +int add_ca_revocation_checking(int argc, char * const *argv) { + int arg; + + bool resetCerts = false; + + NSMutableArray *certs = [NSMutableArray array]; + NSDictionary *plist = nil; + + /* parse args */ + if (argc == 1) { + return SHOW_USAGE_MESSAGE; + } + + while ((arg = getopt(argc, argv, "c:r:p:")) != -1) { + switch(arg) { + case 'c': + if (addCertFile(optarg, certs)) { + fprintf(stderr, "Failed to read cert file\n"); + return 1; + } + break; + case 'r': + if (!strcmp(optarg, "all")) { + resetCerts = true; + } else if (!strcmp(optarg, "cert")) { + resetCerts = true; + } else { + return SHOW_USAGE_MESSAGE; + } + break; + case 'p': + plist = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]]; + break; + case '?': + default: + return SHOW_USAGE_MESSAGE; + } + } + + /* handle reset operation */ + if (resetCerts) { + return resetRevocationAdditions(resetCerts); + } + + /* set plist */ + if (plist) { + CFErrorRef error = NULL; + bool result = SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)plist, &error); + if (!result) { + return returnCFError(error); + } else { + return 0; + } + } + + /* add certs */ + int status = 0; + if ([certs count]) { + NSMutableArray*valuesForCAsKey = [NSMutableArray arrayWithCapacity:[certs count]]; + [certs enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + SecCertificateRef cert = (__bridge SecCertificateRef)obj; + NSData* hash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(cert)); + NSDictionary *value = @{ (__bridge NSString*)kSecCARevocationHashAlgorithmKey:@"sha256", + (__bridge NSString*)kSecCARevocationSPKIHashKey:hash }; + [valuesForCAsKey addObject:value]; + }]; + status = addRevocationAdditions(kSecCARevocationAdditionsKey, valuesForCAsKey); + } + if (status != 0) { + fprintf(stderr, "failed to add cert revocation additions\n"); + return status; + } + + return 0; +} + +static int printRevocationAdditions(CFStringRef key, NSDictionary *allAdditions) { + if (!allAdditions || !allAdditions[(__bridge NSString*)key] || + [allAdditions[(__bridge NSString*)key] count] == 0) { + CFStringPerformWithCString(key, ^(const char *utf8Str) { + fprintf(stdout, "No revocation additions for %s\n", utf8Str); + }); + return 0; + } + + NSArray *additionsForKey = allAdditions[(__bridge NSString*)key]; + NSMutableString *additionsString = [NSMutableString stringWithFormat:@"\t%@ : [",key]; + [additionsForKey enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[NSString class]]) { + if (idx == 0) { + [additionsString appendFormat:@"\"%@\"",obj]; + } else { + [additionsString appendFormat:@", \"%@\"", obj]; + } + } else if ([obj isKindOfClass:[NSDictionary class]]) { + if (idx == 0) { + [additionsString appendString:@"\n\t "]; + } else { + [additionsString appendString:@"\t "]; + } + [additionsString appendFormat:@"\"%@:", obj[(__bridge NSString*)kSecCARevocationHashAlgorithmKey]]; + NSString *hashHex = CFBridgingRelease(CFDataCopyHexString((__bridge CFDataRef)obj[(__bridge NSString*)kSecCARevocationSPKIHashKey])); + [additionsString appendString:hashHex]; + if ([additionsForKey count] == idx + 1) { // last entry + [additionsString appendString:@"\"\n"]; + } else { + [additionsString appendString:@"\",\n"]; + } + } + }]; + [additionsString appendString:@"]\n"]; + CFStringPerformWithCString((__bridge CFStringRef)additionsString, ^(const char *utf8Str) { + fprintf(stdout, "\n%s\n", utf8Str); + }); + + return 0; +} + +int show_ca_revocation_checking(int argc, char * const *argv) { + int arg; + bool allAdditions = false; + NSString *identifier = nil; + bool certAdditions = false; + + /* parse args */ + while ((arg = getopt(argc, argv, "ai:c")) != -1) { + switch(arg) { + case 'a': + allAdditions = true; + break; + case 'i': + identifier = [NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]; + break; + case 'c': + certAdditions = true; + break; + case '?': + default: + return SHOW_USAGE_MESSAGE; + } + } + + if (allAdditions) { + identifier = nil; + fprintf(stdout, "Showing revocation additions for all apps\n"); + } else if (!identifier) { + identifier = secToolAppID; + } + + if (identifier) { + CFStringPerformWithCString((__bridge CFStringRef)identifier, ^(const char *utf8Str) { + fprintf(stdout, "Showing revocation additions for %s\n", utf8Str); + }); + } + + CFErrorRef error = NULL; + NSDictionary *results = CFBridgingRelease(SecTrustStoreCopyCARevocationAdditions((__bridge CFStringRef)identifier, &error)); + + /* Copy failed, return error */ + if (!results && error) { + return returnCFError(error); + } + + /* print cert revocation additions */ + int status = 0; + if (certAdditions) { + status = printRevocationAdditions(kSecCARevocationAdditionsKey, results); + } + if (status != 0) { + fprintf(stderr, "failed to print revocation additions\n"); + return status; + } + + + return 0; +} diff --git a/SecurityTool/sharedTool/iOS/entitlements.plist b/SecurityTool/sharedTool/iOS/entitlements.plist index ecb877f8..8cdb7c53 100644 --- a/SecurityTool/sharedTool/iOS/entitlements.plist +++ b/SecurityTool/sharedTool/iOS/entitlements.plist @@ -17,6 +17,8 @@ com.apple.security com.apple.private.keychain.keychaincontrol + com.apple.private.keychain.inet_expansion_fields + com.apple.developer.icloud-services CloudKit diff --git a/SecurityTool/sharedTool/macOS/entitlements.plist b/SecurityTool/sharedTool/macOS/entitlements.plist index dc75012f..461763d5 100644 --- a/SecurityTool/sharedTool/macOS/entitlements.plist +++ b/SecurityTool/sharedTool/macOS/entitlements.plist @@ -12,6 +12,8 @@ com.apple.private.keychain.keychaincontrol + com.apple.private.keychain.inet_expansion_fields + com.apple.private.syncbubble-keychain com.apple.private.system-keychain diff --git a/SecurityTool/sharedTool/policy_dryrun.m b/SecurityTool/sharedTool/policy_dryrun.m index dc1668ec..ff46b5a8 100644 --- a/SecurityTool/sharedTool/policy_dryrun.m +++ b/SecurityTool/sharedTool/policy_dryrun.m @@ -158,11 +158,11 @@ static void reportStats(unsigned expected_mismatches, unsigned real_mismatches, int policy_dryrun(int argc, char * const *argv) { @autoreleasepool { NSError* error = nil; - // From Swift.policy, policy v5 + // From Swift.policy, policy v7 - TPPolicyDocument *tpd = [TPPolicyDocument policyDocWithHash:@"SHA256:O/ECQlWhvNlLmlDNh2+nal/yekUC87bXpV3k+6kznSo=" + TPPolicyDocument *tpd = [TPPolicyDocument policyDocWithHash:@"SHA256:dL8Qujqzprhp6FdH5GzNMtPlnZtLWMwfiiF7aykr8WU=" data:[[NSData alloc] initWithBase64EncodedString: - @"CAUSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGhsKDEFwcGxpY2F0aW9ucxIEZnVsbBIFd2F0Y2gaHwoQU2VjdXJlT2JqZWN0U3luYxIEZnVsbBIFd2F0Y2gaHAoNRGV2aWNlUGFpcmluZxIEZnVsbBIFd2F0Y2gaGgoLQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoGhUKBkhlYWx0aBIEZnVsbBIFd2F0Y2gaLQoTTGltaXRlZFBlZXJzQWxsb3dlZBIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxokChVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2USBGZ1bGwSBXdhdGNoGhcKCEFwcGxlUGF5EgRmdWxsEgV3YXRjaBoZCgpBdXRvVW5sb2NrEgRmdWxsEgV3YXRjaBoWCgdNYW5hdGVlEgRmdWxsEgV3YXRjaBoYCglQYXNzd29yZHMSBGZ1bGwSBXdhdGNoGhUKBkVuZ3JhbRIEZnVsbBIFd2F0Y2gaHgoEV2lGaRIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxoTCgRIb21lEgRmdWxsEgV3YXRjaCIbCgVhdWRpbxIEZnVsbBIFd2F0Y2gSBWF1ZGlvIhMKBGZ1bGwSBGZ1bGwSBXdhdGNoIhUKAnR2EgRmdWxsEgV3YXRjaBICdHYiFAoFd2F0Y2gSBGZ1bGwSBXdhdGNoMiIKFgAEIhICBHZ3aHQKCl5BcHBsZVBheSQSCEFwcGxlUGF5MiYKGAAEIhQCBHZ3aHQKDF5BdXRvVW5sb2NrJBIKQXV0b1VubG9jazIeChQABCIQAgR2d2h0CgheRW5ncmFtJBIGRW5ncmFtMh4KFAAEIhACBHZ3aHQKCF5IZWFsdGgkEgZIZWFsdGgyGgoSAAQiDgIEdndodAoGXkhvbWUkEgRIb21lMiAKFQAEIhECBHZ3aHQKCV5NYW5hdGVlJBIHTWFuYXRlZTI4CiEABCIdAgR2d2h0ChVeTGltaXRlZFBlZXJzQWxsb3dlZCQSE0xpbWl0ZWRQZWVyc0FsbG93ZWQyXQpQAAISHgAEIhoCBHZ3aHQKEl5Db250aW51aXR5VW5sb2NrJBIVAAQiEQIEdndodAoJXkhvbWVLaXQkEhUABCIRAgR2d2h0CgleQXBwbGVUViQSCU5vdFN5bmNlZDIrChsABCIXAgRhZ3JwCg9eWzAtOUEtWl17MTB9XC4SDEFwcGxpY2F0aW9uczLFAQqwAQACEjQAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAobAAQiFwIEYWdycAoPXmNvbS5hcHBsZS5zYmQkEj0AAQoTAAQiDwIFY2xhc3MKBl5rZXlzJAokAAQiIAIEYWdycAoYXmNvbS5hcHBsZS5zZWN1cml0eS5zb3MkEhkABCIVAgR2d2h0Cg1eQmFja3VwQmFnVjAkEhwABCIYAgR2d2h0ChBeaUNsb3VkSWRlbnRpdHkkEhBTZWN1cmVPYmplY3RTeW5jMmMKWwACEhIABCIOAgR2d2h0CgZeV2lGaSQSQwABChMABCIPAgVjbGFzcwoGXmdlbnAkChMABCIPAgRhZ3JwCgdeYXBwbGUkChUABCIRAgRzdmNlCgleQWlyUG9ydCQSBFdpRmkynQMKgwMAAhIYAAQiFAIEdndodAoMXlBDUy1CYWNrdXAkEhoABCIWAgR2d2h0Cg5eUENTLUNsb3VkS2l0JBIYAAQiFAIEdndodAoMXlBDUy1Fc2Nyb3ckEhUABCIRAgR2d2h0CgleUENTLUZERSQSGgAEIhYCBHZ3aHQKDl5QQ1MtRmVsZHNwYXIkEhoABCIWAgR2d2h0Cg5eUENTLU1haWxEcm9wJBIaAAQiFgIEdndodAoOXlBDUy1NYWlsZHJvcCQSGwAEIhcCBHZ3aHQKD15QQ1MtTWFzdGVyS2V5JBIXAAQiEwIEdndodAoLXlBDUy1Ob3RlcyQSGAAEIhQCBHZ3aHQKDF5QQ1MtUGhvdG9zJBIZAAQiFQIEdndodAoNXlBDUy1TaGFyaW5nJBIeAAQiGgIEdndodAoSXlBDUy1pQ2xvdWRCYWNrdXAkEh0ABCIZAgR2d2h0ChFeUENTLWlDbG91ZERyaXZlJBIaAAQiFgIEdndodAoOXlBDUy1pTWVzc2FnZSQSFVByb3RlY3RlZENsb3VkU3RvcmFnZTI6CisABCInAgRhZ3JwCh9eY29tLmFwcGxlLnNhZmFyaS5jcmVkaXQtY2FyZHMkEgtDcmVkaXRDYXJkczIuCiEABCIdAgRhZ3JwChVeY29tLmFwcGxlLmNmbmV0d29yayQSCVBhc3N3b3JkczJtClwAAhIeAAQiGgIEdndodAoSXkFjY2Vzc29yeVBhaXJpbmckEhoABCIWAgR2d2h0Cg5eTmFub1JlZ2lzdHJ5JBIcAAQiGAIEdndodAoQXldhdGNoTWlncmF0aW9uJBINRGV2aWNlUGFpcmluZzIOCgIABhIIQmFja3N0b3A=" options:0]]; + @"CAcSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGh4KBEhvbWUSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aJAoVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlEgRmdWxsEgV3YXRjaBoYCglQYXNzd29yZHMSBGZ1bGwSBXdhdGNoGh8KEFNlY3VyZU9iamVjdFN5bmMSBGZ1bGwSBXdhdGNoGh4KBFdpRmkSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aGgoLQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoGhcKCEFwcGxlUGF5EgRmdWxsEgV3YXRjaBoVCgZIZWFsdGgSBGZ1bGwSBXdhdGNoGhkKCkF1dG9VbmxvY2sSBGZ1bGwSBXdhdGNoGi0KE0xpbWl0ZWRQZWVyc0FsbG93ZWQSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aHAoNRGV2aWNlUGFpcmluZxIEZnVsbBIFd2F0Y2gaFgoHTWFuYXRlZRIEZnVsbBIFd2F0Y2gaFQoGRW5ncmFtEgRmdWxsEgV3YXRjaBoXCghCYWNrc3RvcBIEZnVsbBIFd2F0Y2gaGwoMQXBwbGljYXRpb25zEgRmdWxsEgV3YXRjaCITCgRmdWxsEgRmdWxsEgV3YXRjaCIVCgJ0dhIEZnVsbBIFd2F0Y2gSAnR2IhQKBXdhdGNoEgRmdWxsEgV3YXRjaCIbCgVhdWRpbxIEZnVsbBIFd2F0Y2gSBWF1ZGlvMiIKFgAEIhICBHZ3aHQKCl5BcHBsZVBheSQSCEFwcGxlUGF5MiYKGAAEIhQCBHZ3aHQKDF5BdXRvVW5sb2NrJBIKQXV0b1VubG9jazIeChQABCIQAgR2d2h0CgheRW5ncmFtJBIGRW5ncmFtMh4KFAAEIhACBHZ3aHQKCF5IZWFsdGgkEgZIZWFsdGgyGgoSAAQiDgIEdndodAoGXkhvbWUkEgRIb21lMiAKFQAEIhECBHZ3aHQKCV5NYW5hdGVlJBIHTWFuYXRlZTI4CiEABCIdAgR2d2h0ChVeTGltaXRlZFBlZXJzQWxsb3dlZCQSE0xpbWl0ZWRQZWVyc0FsbG93ZWQyXQpQAAISHgAEIhoCBHZ3aHQKEl5Db250aW51aXR5VW5sb2NrJBIVAAQiEQIEdndodAoJXkhvbWVLaXQkEhUABCIRAgR2d2h0CgleQXBwbGVUViQSCU5vdFN5bmNlZDIrChsABCIXAgRhZ3JwCg9eWzAtOUEtWl17MTB9XC4SDEFwcGxpY2F0aW9uczLKAQq1AQACEjYAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAodAAQiGQIEYWdycAoRXmNvbVwuYXBwbGVcLnNiZCQSQAABChMABCIPAgVjbGFzcwoGXmtleXMkCicABCIjAgRhZ3JwChteY29tXC5hcHBsZVwuc2VjdXJpdHlcLnNvcyQSGQAEIhUCBHZ3aHQKDV5CYWNrdXBCYWdWMCQSHAAEIhgCBHZ3aHQKEF5pQ2xvdWRJZGVudGl0eSQSEFNlY3VyZU9iamVjdFN5bmMyYwpbAAISEgAEIg4CBHZ3aHQKBl5XaUZpJBJDAAEKEwAEIg8CBWNsYXNzCgZeZ2VucCQKEwAEIg8CBGFncnAKB15hcHBsZSQKFQAEIhECBHN2Y2UKCV5BaXJQb3J0JBIEV2lGaTKdAwqDAwACEhgABCIUAgR2d2h0CgxeUENTLUJhY2t1cCQSGgAEIhYCBHZ3aHQKDl5QQ1MtQ2xvdWRLaXQkEhgABCIUAgR2d2h0CgxeUENTLUVzY3JvdyQSFQAEIhECBHZ3aHQKCV5QQ1MtRkRFJBIaAAQiFgIEdndodAoOXlBDUy1GZWxkc3BhciQSGgAEIhYCBHZ3aHQKDl5QQ1MtTWFpbERyb3AkEhoABCIWAgR2d2h0Cg5eUENTLU1haWxkcm9wJBIbAAQiFwIEdndodAoPXlBDUy1NYXN0ZXJLZXkkEhcABCITAgR2d2h0CgteUENTLU5vdGVzJBIYAAQiFAIEdndodAoMXlBDUy1QaG90b3MkEhkABCIVAgR2d2h0Cg1eUENTLVNoYXJpbmckEh4ABCIaAgR2d2h0ChJeUENTLWlDbG91ZEJhY2t1cCQSHQAEIhkCBHZ3aHQKEV5QQ1MtaUNsb3VkRHJpdmUkEhoABCIWAgR2d2h0Cg5eUENTLWlNZXNzYWdlJBIVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlMj0KLgAEIioCBGFncnAKIl5jb21cLmFwcGxlXC5zYWZhcmlcLmNyZWRpdC1jYXJkcyQSC0NyZWRpdENhcmRzMjAKIwAEIh8CBGFncnAKF15jb21cLmFwcGxlXC5jZm5ldHdvcmskEglQYXNzd29yZHMybQpcAAISHgAEIhoCBHZ3aHQKEl5BY2Nlc3NvcnlQYWlyaW5nJBIaAAQiFgIEdndodAoOXk5hbm9SZWdpc3RyeSQSHAAEIhgCBHZ3aHQKEF5XYXRjaE1pZ3JhdGlvbiQSDURldmljZVBhaXJpbmcyDgoCAAYSCEJhY2tzdG9w" options:0]]; TPPolicy *policy = [tpd policyWithSecrets:@{} decrypter:nil error:&error]; if (error != nil) { NSLog(@"policy error: %@", error); @@ -172,6 +172,15 @@ int policy_dryrun(int argc, char * const *argv) { NSLog(@"policy is nil"); return 1; } + + TPSyncingPolicy* syncingPolicy = [policy syncingPolicyForModel:@"iPhone" + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_UNKNOWN + error:&error]; + if(syncingPolicy == nil || error != nil) { + NSLog(@"syncing policy is nil: %@", error); + return 1; + } + unsigned real_mismatches = 0; unsigned expected_mismatches = 0; NSMutableArray* reportedMismatches = [[NSMutableArray alloc] init]; @@ -219,7 +228,7 @@ int policy_dryrun(int argc, char * const *argv) { NSMutableDictionary* mutA = [a mutableCopy]; mutA[(id)kSecClass] = (id)itemClass; - NSString* newView = [policy mapKeyToView:mutA]; + NSString* newView = [syncingPolicy mapDictionaryToView:mutA]; if (newView != nil) { NSLog(@"new: %@", newView); } diff --git a/SecurityTool/sharedTool/scep.c b/SecurityTool/sharedTool/scep.c index 304c9270..39e2f744 100644 --- a/SecurityTool/sharedTool/scep.c +++ b/SecurityTool/sharedTool/scep.c @@ -441,30 +441,44 @@ extern int command_scep(int argc, char * const *argv) (void) scep_signing_certificate; // Silence analyzer -#if 0 +/* GetCACaps capabilities advertised by SCEP server: - +--------------------+----------------------------------------------+ - | Keyword | Description | - +--------------------+----------------------------------------------+ - | "GetNextCACert" | CA Supports the GetNextCACert message. | - | "POSTPKIOperation" | PKIOPeration messages may be sent via HTTP | - | | POST. | - | "Renewal" | Clients may use current certificate and key | - | | to authenticate an enrollment request for a | - | | new certificate. | - | "SHA-512" | CA Supports the SHA-512 hashing algorithm in | - | | signatures and fingerprints. | - | "SHA-256" | CA Supports the SHA-256 hashing algorithm in | - | | signatures and fingerprints. | - | "SHA-1" | CA Supports the SHA-1 hashing algorithm in | - | | signatures and fingerprints. | - | "DES3" | CA Supports triple-DES for encryption. | - +--------------------+----------------------------------------------+ -#endif + +--------------------+----------------------------------------------+ + | Keyword | Description | + +--------------------+----------------------------------------------+ + | "AES" | CA supports the AES128-CBC encryption | + | | algorithm. | + | | | + | "DES3" | CA supports the triple DES-CBC encryption | + | | algorithm. | + | | | + | "GetNextCACert" | CA supports the GetNextCACert | + | | message. | + | | | + | "POSTPKIOperation" | CA supports PKIOPeration messages sent | + | | via HTTP POST. | + | | | + | "Renewal" | CA supports the Renewal CA operation. | + | | | + | "SHA-1" | CA supports the SHA-1 hashing algorithm. | + | | | + | "SHA-256" | CA supports the SHA-256 hashing algorithm. | + | | | + | "SHA-512" | CA supports the SHA-512 hashing algorithm. | + | | | + | "SCEPStandard" | CA supports all mandatory-to-implement | + | | sections of the SCEP standard. This keyword | + | | implies "AES", | + | | "POSTPKIOperation", and "SHA-256", as well | + | | as the provisions of | + | | Section 2.9. | + +--------------------+----------------------------------------------+ +*/ bool scep_can_use_post = false; - bool scep_use_3des = false; + bool scep_can_use_3des = false; + bool scep_can_use_aes = false; bool scep_can_use_sha1 = false; bool scep_can_use_sha512 = false; bool scep_can_use_sha256 = false; @@ -496,21 +510,14 @@ extern int command_scep(int argc, char * const *argv) CFRange caps_length = CFRangeMake(0, CFArrayGetCount(caps)); scep_can_use_post = CFArrayContainsValue(caps, caps_length, CFSTR("POSTPKIOperation")); - scep_use_3des = CFArrayContainsValue(caps, caps_length, CFSTR("DES3")); + scep_can_use_3des = CFArrayContainsValue(caps, caps_length, CFSTR("DES3")); + scep_can_use_aes = CFArrayContainsValue(caps, caps_length, CFSTR("AES")); scep_can_use_sha1 = CFArrayContainsValue(caps, caps_length, CFSTR("SHA-1")); scep_can_use_sha256 = CFArrayContainsValue(caps, caps_length, CFSTR("SHA-256")); scep_can_use_sha512 = CFArrayContainsValue(caps, caps_length, CFSTR("SHA-512")); - - // We probably inteded these to be the values and not override them below.. - // but for now to quiet the analyzer we reference them here. see scep.c, command_scep assumes 3des and sha1 - (void) scep_use_3des; - (void) scep_can_use_sha1; CFRelease(caps); } - scep_use_3des = true; - scep_can_use_sha1 = true; - csr_parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (scep_key_usage) @@ -520,11 +527,14 @@ extern int command_scep(int argc, char * const *argv) else fprintf(stderr, "No SCEP challenge provided, hope that's ok.\n"); - if (!scep_use_3des) { - CFDictionarySetValue(csr_parameters, kSecCMSBulkEncryptionAlgorithm, kSecCMSEncryptionAlgorithmDESCBC); - fprintf(stderr, "SCEP server does not support 3DES, falling back to DES. You should reconfigure your server.\n"); + // set encryption algorithm for CMS + if (scep_can_use_aes) { + CFDictionarySetValue(csr_parameters, kSecCMSBulkEncryptionAlgorithm, kSecCMSEncryptionAlgorithmAESCBC); + } else if (!scep_can_use_3des) { + fprintf(stderr, "SCEP server does not support 3DES -- using it anyway. You must reconfigure your server.\n"); } + // set hash algorithmn for CMS if (scep_can_use_sha512) { CFDictionarySetValue(csr_parameters, kSecCMSSignHashAlgorithm, kSecCMSHashingAlgorithmSHA512); } else if (scep_can_use_sha256) { @@ -532,7 +542,7 @@ extern int command_scep(int argc, char * const *argv) } else if (scep_can_use_sha1) { CFDictionarySetValue(csr_parameters, kSecCMSSignHashAlgorithm, kSecCMSHashingAlgorithmSHA1); } else { - fprintf(stderr, "SCEP server does not support SHA-1. You must reconfigure your server.\n"); + fprintf(stderr, "SCEP server does not support SHA-1 -- using it anyway. You must reconfigure your server.\n"); } if (scep_subject_alt_name) { diff --git a/SecurityTool/sharedTool/security_tool_commands.h b/SecurityTool/sharedTool/security_tool_commands.h index 90fca292..1d834211 100644 --- a/SecurityTool/sharedTool/security_tool_commands.h +++ b/SecurityTool/sharedTool/security_tool_commands.h @@ -21,6 +21,8 @@ * @APPLE_LICENSE_HEADER_END@ */ +#include + #define SHOW_USAGE_MESSAGE 2 // This is included to make SECURITY_COMMAND macros result in declarations of diff --git a/SecurityTool/sharedTool/sos.m b/SecurityTool/sharedTool/sos.m index e52156b7..e6684469 100644 --- a/SecurityTool/sharedTool/sos.m +++ b/SecurityTool/sharedTool/sos.m @@ -185,6 +185,8 @@ command_sos_control(__unused int argc, __unused char * const * argv) bool gbtriggered = false; bool circleHash = false; bool triggerRingUpdate = false; + bool iCloudIdentityStatus = false; + bool removeV0Peers = false; static struct option long_options[] = { @@ -200,10 +202,12 @@ command_sos_control(__unused int argc, __unused char * const * argv) {"ghostbustByAge", optional_argument, NULL, 'A'}, {"ghostbustInfo", optional_argument, NULL, 'G'}, {"ghostbustTriggered", optional_argument, NULL, 'T'}, + {"icloudIdentityStatus", optional_argument, NULL, 'i'}, + {"removeV0Peers", optional_argument, NULL, 'V'}, {0, 0, 0, 0} }; - while ((ch = getopt_long(argc, argv, "as:AB:GHIMRST", long_options, &option_index)) != -1) { + while ((ch = getopt_long(argc, argv, "as:AB:GHIMRSTiV", long_options, &option_index)) != -1) { switch (ch) { case 'a': { assertStashAccountKey = true; @@ -259,6 +263,12 @@ command_sos_control(__unused int argc, __unused char * const * argv) case 'H': circleHash = true; break; + case 'i': + iCloudIdentityStatus = true; + break; + case 'V': + removeV0Peers = true; + break; case '?': default: { @@ -354,8 +364,27 @@ command_sos_control(__unused int argc, __unused char * const * argv) } }]; - } else { + } else if (iCloudIdentityStatus) { + [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) { + printControlFailureMessage(error); + }] iCloudIdentityStatus:^(NSData *json, NSError *error) { + if (json) { + printf("iCloudIdentityStatus:\n%s\n", [[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding] UTF8String]); + } else { + printf("%s", [[NSString stringWithFormat:@"failed to get iCloudIdentityStatus: %@\n", error] UTF8String]); + } + }]; + } else if (removeV0Peers) { + [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) { + printControlFailureMessage(error); + }] removeV0Peers:^(bool removedV0Peer, NSError *error) { + printf("removed v0 peers:%d\n", removedV0Peer); + if (error) { + printf("%s", [[NSString stringWithFormat:@"failed to remove V0 Peers: %@\n", error] UTF8String]); + } + }]; + } else { [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) { printControlFailureMessage(error); }] userPublicKey:^(BOOL trusted, NSData *spki, NSError *error) { diff --git a/SecurityTool/sharedTool/sub_commands.h b/SecurityTool/sharedTool/sub_commands.h index de949106..e6d5b1c4 100644 --- a/SecurityTool/sharedTool/sub_commands.h +++ b/SecurityTool/sharedTool/sub_commands.h @@ -26,8 +26,10 @@ // This file can't be once, it gets included multiple times to get definitions and declarations. #include "SecurityTool/sharedTool/SecurityCommands.h" + +#if !TARGET_OS_BRIDGE #include "keychain/SecureObjectSync/Tool/keychain_sync.h" #include "keychain/SecureObjectSync/Tool/keychain_sync_test.h" #include "keychain/SecureObjectSync/Tool/keychain_log.h" -#include "keychain/SecureObjectSync/Tool/syncbackup.h" #include "keychain/SecureObjectSync/Tool/recovery_key.h" +#endif diff --git a/SecurityTool/sharedTool/trust_config.m b/SecurityTool/sharedTool/trust_config.m new file mode 100644 index 00000000..b5debbb8 --- /dev/null +++ b/SecurityTool/sharedTool/trust_config.m @@ -0,0 +1,624 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * trust_config.m + */ + +#import +#include +#include +#include +#include + +#include "SecurityCommands.h" + +NSString* toolApplicationID = @"com.apple.security"; + +typedef enum { + TrustConfigurationUnknown = 0, + TrustConfigurationCTExceptions = 1, + TrustConfigurationCARevocationAdditions = 2, + TrustConfigurationTransparentConnectionPins = 3, +} TrustConfigurationType; + +static TrustConfigurationType trustConfigurationTypeForOptarg(NSString *optarg) +{ + if ([optarg isEqualToString:@"ct-exceptions"]) { + return TrustConfigurationCTExceptions; + } else if ([optarg isEqualToString:@"ca-revocation-checking"]) { + return TrustConfigurationCARevocationAdditions; + } else if ([optarg isEqualToString:@"transparent-connection-pins"]) { + return TrustConfigurationTransparentConnectionPins; + } + return TrustConfigurationUnknown; +} + +static char *stringForTrustConfigurationType(TrustConfigurationType type) +{ + switch (type) { + case TrustConfigurationCTExceptions: + return "ct-exceptions"; + case TrustConfigurationCARevocationAdditions: + return "ca-revocation-checking"; + case TrustConfigurationTransparentConnectionPins: + return "transparent-connection-pins"; + default: + return "unknown configuration type"; + } +} + +static int addCertFile(const char *fileName, NSMutableArray *array) { + SecCertificateRef certRef = NULL; + NSData *data = NULL; + unsigned char *buf = NULL; + size_t numBytes; + int rtn = 0; + + if (readFileSizet(fileName, &buf, &numBytes)) { + rtn = -1; + goto errOut; + } + + data = [NSData dataWithBytes:buf length:numBytes]; + certRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data); + if (!certRef) { + certRef = SecCertificateCreateWithPEM(NULL, (__bridge CFDataRef)data); + if (!certRef) { + rtn = -1; + goto errOut; + } + } + + [array addObject:(__bridge id)certRef]; + +errOut: + /* Cleanup */ + free(buf); + CFReleaseNull(certRef); + return rtn; +} + +static int returnCFError(TrustConfigurationType type,CFErrorRef CF_CONSUMED error) { + CFStringRef errorString = CFErrorCopyDescription(error); + CFStringPerformWithCString(errorString, ^(const char *utf8Str) { + fprintf(stderr, "Trust Configuration error for %s: %s\n", stringForTrustConfigurationType(type), utf8Str); + }); + CFIndex errCode = CFErrorGetCode(error); + CFReleaseNull(error); + return (int)errCode; +} + +static int resetConfig(TrustConfigurationType type, bool resetCerts, bool resetDomains) { + bool result = false; + CFErrorRef error = NULL; + switch(type) { + case TrustConfigurationCTExceptions: + if (resetCerts) { + NSDictionary *resetCertsDict = @{ (__bridge NSString*)kSecCTExceptionsCAsKey: @[] }; + result = SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)resetCertsDict, &error); + } + if (!error && resetDomains) { + NSDictionary *resetDomainsDict = @{ (__bridge NSString*)kSecCTExceptionsDomainsKey : @[] }; + result = SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)resetDomainsDict, &error); + } + break; + case TrustConfigurationCARevocationAdditions: { + NSDictionary *resetCertsDict = @{ (__bridge NSString*)kSecCARevocationAdditionsKey: @[] }; + result = SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)resetCertsDict, &error); + break; + } + case TrustConfigurationTransparentConnectionPins: + result = SecTrustStoreSetTransparentConnectionPins(NULL, NULL, &error); + break; + default: + fprintf(stderr, "Unknown trust configuration type\n"); + } + + if (!result) { + return returnCFError(type, error); + } + return 0; +} + +static int setConfigPlist(TrustConfigurationType type, id plist) { + CFErrorRef error = NULL; + bool result = false; + switch(type) { + case TrustConfigurationCTExceptions: + if (![plist isKindOfClass:[NSDictionary class]]) { + fprintf(stderr, "Plist should be a dictionary type for %s\n", + stringForTrustConfigurationType(type)); + return -1; + } + result = SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)plist, &error); + break; + case TrustConfigurationCARevocationAdditions: + if (![plist isKindOfClass:[NSDictionary class]]) { + fprintf(stderr, "Plist should be a dictionary type for %s\n", + stringForTrustConfigurationType(type)); + return -1; + } + result = SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)plist, &error); + break; + case TrustConfigurationTransparentConnectionPins: + if (![plist isKindOfClass:[NSArray class]]) { + fprintf(stderr, "Plist should be a array type for %s\n", + stringForTrustConfigurationType(type)); + return -1; + } + result = SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)plist, &error); + break; + default: + fprintf(stderr, "Unknown trust configuration type\n"); + } + + if (!result) { + return returnCFError(type, error); + } + return 0; +} + +static int addDictionaryConfig(TrustConfigurationType type, bool certsValues, NSArray *values) { + CFErrorRef error = NULL; + NSDictionary *currentConfig = NULL; + NSString *key = @"unknown"; + switch (type) { + case TrustConfigurationCTExceptions: + currentConfig = CFBridgingRelease(SecTrustStoreCopyCTExceptions((__bridge CFStringRef)toolApplicationID, &error)); + key = certsValues ? (__bridge NSString *)kSecCTExceptionsCAsKey : + (__bridge NSString *)kSecCTExceptionsDomainsKey; + break; + case TrustConfigurationCARevocationAdditions: + currentConfig = CFBridgingRelease(SecTrustStoreCopyCARevocationAdditions((__bridge CFStringRef)toolApplicationID, &error)); + key = (__bridge NSString *)kSecCARevocationAdditionsKey; + break; + default: + fprintf(stderr, "Unknown trust configuration type\n"); + return SHOW_USAGE_MESSAGE; + } + if (!currentConfig && error) { + return returnCFError(type, error); + } + + NSMutableArray *configForKey = nil; + if (currentConfig && currentConfig[key]) { + configForKey = [currentConfig[key] mutableCopy]; + [configForKey addObjectsFromArray:values]; + } else { + configForKey = [values copy]; + } + + NSDictionary *newConfigDict = @{key: configForKey }; + bool result = false; + switch (type) { + case TrustConfigurationCTExceptions: + result = SecTrustStoreSetCTExceptions(NULL, (__bridge CFDictionaryRef)newConfigDict, &error); + break; + case TrustConfigurationCARevocationAdditions: + result = SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)newConfigDict, &error); + break; + default: + fprintf(stderr, "Unknown trust configuration type\n"); + return SHOW_USAGE_MESSAGE; + } + + if (!result) { + return returnCFError(type, error); + } + + return 0; +} + +static int addArrayConfig(TrustConfigurationType type, NSArray *values) { + CFErrorRef error = NULL; + NSArray *currentConfig = NULL; + switch (type) { + case TrustConfigurationTransparentConnectionPins: + currentConfig = CFBridgingRelease(SecTrustStoreCopyTransparentConnectionPins((__bridge CFStringRef)toolApplicationID, &error)); + break; + default: + fprintf(stderr, "Unknown trust configuration type\n"); + return SHOW_USAGE_MESSAGE; + } + if (!currentConfig && error) { + return returnCFError(type, error); + } + + NSMutableArray *newConfig = nil; + if (currentConfig) { + newConfig = [currentConfig mutableCopy]; + [newConfig addObjectsFromArray:values]; + } else { + newConfig = [values copy]; + } + + bool result = false; + switch (type) { + case TrustConfigurationTransparentConnectionPins: + result = SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)newConfig, &error); + break; + default: + fprintf(stderr, "Unknown trust configuration type\n"); + return SHOW_USAGE_MESSAGE; + } + + if (!result) { + return returnCFError(type, error); + } + + return 0; +} + +static int addDomains(TrustConfigurationType type, NSArray *domains) { + int status = ERR_SUCCESS; + if ([domains count]) { + status = addDictionaryConfig(type, false, domains); + } + if (status != 0) { + fprintf(stderr, "failed to add domain configuration\n"); + } + return status; +} + +static int addCerts(TrustConfigurationType type, NSArray *certs) { + int status = ERR_SUCCESS; + if ([certs count]) { + NSMutableArray*valuesForCAsKey = [NSMutableArray arrayWithCapacity:[certs count]]; + [certs enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + SecCertificateRef cert = (__bridge SecCertificateRef)obj; + NSData* hash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(cert)); + NSDictionary *value = @{ (__bridge NSString*)kSecTrustStoreHashAlgorithmKey:@"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey:hash }; + [valuesForCAsKey addObject:value]; + }]; + switch(type) { + case TrustConfigurationCTExceptions: + case TrustConfigurationCARevocationAdditions: + status = addDictionaryConfig(type, true, valuesForCAsKey); + break; + case TrustConfigurationTransparentConnectionPins: + status = addArrayConfig(type, valuesForCAsKey); + break; + default: + fprintf(stderr, "Unknown trust configuration type\n"); + return SHOW_USAGE_MESSAGE; + } + + } + if (status != 0) { + fprintf(stderr, "failed to add cert configuration\n"); + } + return status; +} + +int add_trust_config(int argc, char * const *argv) { + int arg; + + bool resetDomains = false; + bool resetCerts = false; + TrustConfigurationType type = TrustConfigurationUnknown; + + NSMutableArray *domains = [NSMutableArray array]; + NSMutableArray *certs = [NSMutableArray array]; + id plist = nil; + + /* parse args */ + if (argc == 2) { + return SHOW_USAGE_MESSAGE; + } + + while ((arg = getopt(argc, argv, "t:d:c:r:p:")) != -1) { + switch(arg) { + case 't': + type = trustConfigurationTypeForOptarg([NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]); + break; + case 'd': { + NSString *domain = [NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]; + [domains addObject:domain]; + break; + } + case 'c': + if (addCertFile(optarg, certs)) { + fprintf(stderr, "Failed to read cert file\n"); + return 1; + } + break; + case 'r': + if (!strcmp(optarg, "all")) { + resetDomains = true; + resetCerts = true; + } else if (!strcmp(optarg, "domain")) { + resetDomains = true; + } else if (!strcmp(optarg, "cert")) { + resetCerts = true; + } else { + return SHOW_USAGE_MESSAGE; + } + break; + case 'p': + plist = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]]; + if (!plist) { + plist = [NSArray arrayWithContentsOfFile:[NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]]; + } + break; + case '?': + default: + return SHOW_USAGE_MESSAGE; + } + } + + if (type == TrustConfigurationUnknown) { + fprintf(stderr, "Unknown trust configuration type\n"); + return SHOW_USAGE_MESSAGE; + } + + if ((domains.count > 0 || (resetDomains && !resetCerts)) && (type != TrustConfigurationCTExceptions)) { + fprintf(stderr, "-d and domain resets not supported by %s configuration type\n", + stringForTrustConfigurationType(type)); + return SHOW_USAGE_MESSAGE; + } + + /* handle reset operation */ + if (resetCerts || resetDomains) { + return resetConfig(type, resetCerts, resetDomains); + } + + /* set plist */ + if (plist) { + return setConfigPlist(type, plist); + } + + /* add domains */ + int status = addDomains(type, domains); + if (status != 0) { + return status; + } + + /* add certs */ + return addCerts(type, certs); +} + +static int printArrayConfig(TrustConfigurationType type, NSArray *configArray) { + if (!configArray || [configArray count] == 0) { + fprintf(stdout, "No configuration for %s\n", stringForTrustConfigurationType(type)); + return 0; + } + + NSMutableString *resultString = [NSMutableString stringWithFormat:@"["]; + [configArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[NSString class]]) { + if (idx == 0) { + [resultString appendFormat:@"\"%@\"",obj]; + } else { + [resultString appendFormat:@", \"%@\"", obj]; + } + } else if ([obj isKindOfClass:[NSDictionary class]]) { + if (idx == 0) { + [resultString appendString:@"\n\t "]; + } else { + [resultString appendString:@"\t "]; + } + [resultString appendFormat:@"\"%@:", obj[(__bridge NSString*)kSecTrustStoreHashAlgorithmKey]]; + NSString *hashHex = CFBridgingRelease(CFDataCopyHexString((__bridge CFDataRef)obj[(__bridge NSString*)kSecTrustStoreSPKIHashKey])); + [resultString appendString:hashHex]; + if ([configArray count] == idx + 1) { // last entry + [resultString appendString:@"\"\n"]; + } else { + [resultString appendString:@"\",\n"]; + } + } + }]; + [resultString appendString:@"]\n"]; + CFStringPerformWithCString((__bridge CFStringRef)resultString, ^(const char *utf8Str) { + fprintf(stdout, "\n%s\n", utf8Str); + }); + + return 0; +} + +static int printDictionaryConfig(TrustConfigurationType type, CFStringRef key, NSDictionary *allConfig) { + if (!allConfig || !allConfig[(__bridge NSString*)key] || + [allConfig[(__bridge NSString*)key] count] == 0) { + CFStringPerformWithCString(key, ^(const char *utf8Str) { + fprintf(stdout, "No configuration for %s\n", utf8Str); + }); + return 0; + } + + NSArray *exceptionsForKey = allConfig[(__bridge NSString*)key]; + NSMutableString *exceptionsString = [NSMutableString stringWithFormat:@"\t%@ : [",key]; + [exceptionsForKey enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[NSString class]]) { + if (idx == 0) { + [exceptionsString appendFormat:@"\"%@\"",obj]; + } else { + [exceptionsString appendFormat:@", \"%@\"", obj]; + } + } else if ([obj isKindOfClass:[NSDictionary class]]) { + if (idx == 0) { + [exceptionsString appendString:@"\n\t "]; + } else { + [exceptionsString appendString:@"\t "]; + } + [exceptionsString appendFormat:@"\"%@:", obj[(__bridge NSString*)kSecTrustStoreHashAlgorithmKey]]; + NSString *hashHex = CFBridgingRelease(CFDataCopyHexString((__bridge CFDataRef)obj[(__bridge NSString*)kSecTrustStoreSPKIHashKey])); + [exceptionsString appendString:hashHex]; + if ([exceptionsForKey count] == idx + 1) { // last entry + [exceptionsString appendString:@"\"\n"]; + } else { + [exceptionsString appendString:@"\",\n"]; + } + } + }]; + [exceptionsString appendString:@"\t]\n"]; + CFStringPerformWithCString((__bridge CFStringRef)exceptionsString, ^(const char *utf8Str) { + fprintf(stdout, "\n%s\n", utf8Str); + }); + + return 0; +} + +static int printDomainConfig(TrustConfigurationType type, id config) { + if (type != TrustConfigurationCTExceptions) { + fprintf(stderr, "Unknown trust configuration type\n"); + return SHOW_USAGE_MESSAGE; + } + int status = printDictionaryConfig(type, kSecCTExceptionsDomainsKey, config); + if (status != 0) { + fprintf(stderr, "failed to print domain config\n"); + } + return status; +} + +static int printCertConfig(TrustConfigurationType type, id config) { + switch (type) { + case TrustConfigurationCTExceptions: + if (config && ![config isKindOfClass:[NSDictionary class]]) { + fprintf(stderr, "Internal error: configuration should be a dictionary type for %s\n", + stringForTrustConfigurationType(type)); + return -1; + } + return printDictionaryConfig(type, kSecCTExceptionsCAsKey, config); + case TrustConfigurationCARevocationAdditions: + if (config && ![config isKindOfClass:[NSDictionary class]]) { + fprintf(stderr, "Internal error: configuration should be a dictionary type for %s\n", + stringForTrustConfigurationType(type)); + return -1; + } + return printDictionaryConfig(type, kSecCARevocationAdditionsKey, config); + case TrustConfigurationTransparentConnectionPins: + if (config && ![config isKindOfClass:[NSArray class]]) { + fprintf(stderr, "Internal error: configuration should be a array type for %s\n", + stringForTrustConfigurationType(type)); + return -1; + } + return printArrayConfig(type, config); + default: + fprintf(stderr, "Unknown trust configuration type\n"); + return SHOW_USAGE_MESSAGE; + } +} + +static id getConfig(TrustConfigurationType type, NSString *identifier, CFErrorRef *error) { + id results = NULL; + switch(type) { + case TrustConfigurationCTExceptions: + results = CFBridgingRelease(SecTrustStoreCopyCTExceptions((__bridge CFStringRef)identifier, error)); + break; + case TrustConfigurationCARevocationAdditions: + results = CFBridgingRelease(SecTrustStoreCopyCARevocationAdditions((__bridge CFStringRef)identifier, error)); + break; + case TrustConfigurationTransparentConnectionPins: + results = CFBridgingRelease(SecTrustStoreCopyTransparentConnectionPins((__bridge CFStringRef)identifier, error)); + break; + default: + fprintf(stderr, "Unknown trust configuration type\n"); + } + return results; +} + +int show_trust_config(int argc, char * const *argv) { + int arg; + bool allConfig = false; + NSString *identifier = nil; + bool domainConfig = false; + bool certConfig = false; + TrustConfigurationType type = TrustConfigurationUnknown; + + /* parse args */ + while ((arg = getopt(argc, argv, "t:ai:dc")) != -1) { + switch(arg) { + case 't': + type = trustConfigurationTypeForOptarg([NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]); + break; + case 'a': + allConfig = true; + break; + case 'i': + identifier = [NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]; + break; + case 'd': + domainConfig = true; + break; + case 'c': + certConfig = true; + break; + case '?': + default: + return SHOW_USAGE_MESSAGE; + } + } + + if (type == TrustConfigurationUnknown) { + fprintf(stderr, "Unknown trust configuration type\n"); + return SHOW_USAGE_MESSAGE; + } + + if (!domainConfig && !certConfig) { + /* Nothing specified, show cert config and domain config if it exists*/ + certConfig = true; + domainConfig = (type == TrustConfigurationCTExceptions) ? true : false; + } + + if (!certConfig && (type != TrustConfigurationCTExceptions)) { + fprintf(stderr, "-d not supported by %s configuration type\n", + stringForTrustConfigurationType(type)); + return SHOW_USAGE_MESSAGE; + } + + if (allConfig) { + identifier = nil; + fprintf(stdout, "Showing %s configuration for all apps\n", stringForTrustConfigurationType(type)); + } else if (!identifier) { + identifier = toolApplicationID; + } + + if (identifier) { + CFStringPerformWithCString((__bridge CFStringRef)identifier, ^(const char *utf8Str) { + fprintf(stdout, "Showing %s configuration for %s\n", stringForTrustConfigurationType(type), utf8Str); + }); + } + + CFErrorRef error = NULL; + id results = getConfig(type, identifier, &error); + + /* Copy failed, return error */ + if (!results && error) { + return returnCFError(type, error); + } + + /* print domain exceptions */ + int status = 0; + if (domainConfig) { + status = printDomainConfig(type, results); + } + if (status != 0) { + return status; + } + + /* print cert exceptions */ + if (certConfig) { + status = printCertConfig(type, results); + } + + return status; +} diff --git a/SecurityTool/sharedTool/trust_update.m b/SecurityTool/sharedTool/trust_update.m index 17323408..8111e2cb 100644 --- a/SecurityTool/sharedTool/trust_update.m +++ b/SecurityTool/sharedTool/trust_update.m @@ -80,6 +80,26 @@ static int check_OTA_sec_experiment_asset(void) { return 0; } +static int check_valid_update(void) { + CFErrorRef error = NULL; + bool result = SecTrustTriggerValidUpdate(&error); + if (!result) { + CFStringRef errorDescription = error ? CFErrorCopyDescription(error) : NULL; + if (errorDescription) { + char *errMsg = CFStringToCString(errorDescription); + fprintf(stdout, "Update failed: %s\n", errMsg ? errMsg : "no error message"); + free(errMsg); + CFRelease(errorDescription); + } else { + fprintf(stdout, "Update failed: no description\n"); + } + CFReleaseNull(error); + } else { + fprintf(stdout, "Updated triggered\n"); + } + return 0; +} + int check_trust_update(int argc, char * const *argv) { int arg; @@ -87,12 +107,14 @@ int check_trust_update(int argc, char * const *argv) { return SHOW_USAGE_MESSAGE; } - while ((arg = getopt(argc, argv, "se")) != -1) { + while ((arg = getopt(argc, argv, "ser")) != -1) { switch(arg) { case 's': return check_OTA_Supplementals_asset(); case 'e': return check_OTA_sec_experiment_asset(); + case 'r': + return check_valid_update(); case '?': default: return SHOW_USAGE_MESSAGE; diff --git a/SharedMocks/NSXPCConnectionMock.m b/SharedMocks/NSXPCConnectionMock.m index f667d23c..89102a49 100644 --- a/SharedMocks/NSXPCConnectionMock.m +++ b/SharedMocks/NSXPCConnectionMock.m @@ -14,8 +14,7 @@ @implementation NSXPCConnectionMock - (instancetype) initWithRealObject:(id)reality { - self = [super init]; - if (self) { + if ((self = [super init])) { _reality = reality; } return self; diff --git a/SharedWebCredentialViewService/Base.lproj/Main_iPad.storyboard b/SharedWebCredentialViewService/Base.lproj/Main_iPad.storyboard old mode 100644 new mode 100755 diff --git a/SharedWebCredentialViewService/Base.lproj/Main_iPhone.storyboard b/SharedWebCredentialViewService/Base.lproj/Main_iPhone.storyboard old mode 100644 new mode 100755 diff --git a/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Info.plist b/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Info.plist old mode 100644 new mode 100755 diff --git a/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Prefix.pch b/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Prefix.pch old mode 100644 new mode 100755 diff --git a/SharedWebCredentialViewService/SWCAppDelegate.h b/SharedWebCredentialViewService/SWCAppDelegate.h old mode 100644 new mode 100755 diff --git a/SharedWebCredentialViewService/SWCAppDelegate.m b/SharedWebCredentialViewService/SWCAppDelegate.m old mode 100644 new mode 100755 diff --git a/SharedWebCredentialViewService/SWCViewController.h b/SharedWebCredentialViewService/SWCViewController.h old mode 100644 new mode 100755 index 3ac3843e..9b047a7d --- a/SharedWebCredentialViewService/SWCViewController.h +++ b/SharedWebCredentialViewService/SWCViewController.h @@ -6,7 +6,9 @@ // #import +#if !TARGET_OS_TV #import +#endif @interface SWCViewController : SBSUIRemoteAlertItemContentViewController diff --git a/SharedWebCredentialViewService/SWCViewController.m b/SharedWebCredentialViewService/SWCViewController.m old mode 100644 new mode 100755 index 25e643ca..23bf5312 --- a/SharedWebCredentialViewService/SWCViewController.m +++ b/SharedWebCredentialViewService/SWCViewController.m @@ -109,7 +109,7 @@ const NSString* SWC_SERVER_KEY = @"srvr"; self.backgroundView = [[UIView alloc] init]; self.backgroundView.backgroundColor = [UIColor systemBackgroundColor]; - self.imageView.image = [UIImage symbolImageNamed:@"checkmark"]; + self.imageView.image = [UIImage systemImageNamed:@"checkmark"]; self.imageView.hidden = YES; } diff --git a/SharedWebCredentialViewService/en.lproj/InfoPlist.strings b/SharedWebCredentialViewService/en.lproj/InfoPlist.strings old mode 100644 new mode 100755 diff --git a/SharedWebCredentialViewService/entitlements.plist b/SharedWebCredentialViewService/entitlements.plist old mode 100644 new mode 100755 index ef81b9b7..7f762505 --- a/SharedWebCredentialViewService/entitlements.plist +++ b/SharedWebCredentialViewService/entitlements.plist @@ -6,5 +6,24 @@ com.apple.private.associated-domains + com.apple.security.iokit-user-client-class + + AGXDevice + AGXDeviceUserClient + AGXSharedUserClient + AGXCommandQueue + IOAccelContext + IOAccelContext2 + IOAccelDevice + IOAccelDevice2 + IOAccelSharedUserClient + IOAccelSharedUserClient2 + IOAccelSubmitter + IOAccelSubmitter2 + IOAVControllerConcreteUserClient + IOMobileFramebufferUserClient + IOSurfaceRootUserClient + RootDomainUserClient + diff --git a/SharedWebCredentialViewService/main.m b/SharedWebCredentialViewService/main.m old mode 100644 new mode 100755 diff --git a/TestPlan.xctestplan b/TestPlan.xctestplan deleted file mode 100644 index 551dd811..00000000 --- a/TestPlan.xctestplan +++ /dev/null @@ -1,18 +0,0 @@ -{ - "configurations" : [ - { - "id" : "E61600EC-4F68-414B-932D-2A0655D233A4", - "name" : "Configuration 1", - "options" : { - - } - } - ], - "defaultOptions" : { - - }, - "testTargets" : [ - - ], - "version" : 1 -} diff --git a/base/SecBase.h b/base/SecBase.h index 6f3a8a61..028df742 100644 --- a/base/SecBase.h +++ b/base/SecBase.h @@ -27,16 +27,10 @@ #include #include #include -#ifdef DARLING - // for unprefixed API_AVAILABLE and friends - #include - // not sure if we're supposed to be including that header in CoreFoundation or in Availability.h, - // but this works for all of Security -#endif // Truth table for following declarations: // -// TARGET_OS_OSX TARGET_OS_OSX TARGET_OS_IPHONE TARGET_OS_IPHONE TARGET_OS_IOSMAC +// TARGET_OS_OSX TARGET_OS_OSX TARGET_OS_IPHONE TARGET_OS_IPHONE TARGET_OS_MACCATALYST // SEC_IOS_ON_OSX SEC_IOS_ON_OSX // ================================================================================================================= // SEC_OS_IPHONE 0 1 1 1 1 @@ -52,12 +46,12 @@ #endif // SEC_IOS_ON_OSX #endif // TARGET_OS_OSX -#if TARGET_OS_IOSMAC +#if TARGET_OS_MACCATALYST #define SEC_OS_IPHONE 1 #define SEC_OS_OSX 0 #define SEC_OS_OSX_INCLUDES 0 -#endif // TARGET_OS_IOSMAC +#endif // TARGET_OS_MACCATALYST #ifndef SEC_OS_IPHONE // block above did not fire; set flags to current platform @@ -77,7 +71,7 @@ #define SEC_DEPRECATED_ATTRIBUTE #endif -#define CSSM_DEPRECATED API_DEPRECATED("CSSM is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) +#define CSSM_DEPRECATED API_DEPRECATED("CSSM is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) __BEGIN_DECLS @@ -145,19 +139,19 @@ typedef struct CF_BRIDGED_TYPE(id) __SecKeychain *SecKeychainRef @typedef SecKeychainItemRef @abstract Contains information about a keychain item. */ -typedef struct CF_BRIDGED_TYPE(id) __SecKeychainItem *SecKeychainItemRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecKeychainItem *SecKeychainItemRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainSearchRef @abstract Contains information about a keychain search. */ -typedef struct CF_BRIDGED_TYPE(id) __SecKeychainSearch *SecKeychainSearchRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecKeychainSearch *SecKeychainSearchRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainAttrType @abstract Represents a keychain attribute type. */ -typedef OSType SecKeychainAttrType API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef OSType SecKeychainAttrType API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @struct SecKeychainAttribute @@ -166,19 +160,19 @@ typedef OSType SecKeychainAttrType API_UNAVAILABLE(ios, watchos, tvos, bridgeos, @field length The length of the buffer pointed to by data. @field data A pointer to the attribute data. */ -struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) SecKeychainAttribute +struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) SecKeychainAttribute { SecKeychainAttrType tag; UInt32 length; void * __nullable data; }; -typedef struct SecKeychainAttribute SecKeychainAttribute API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct SecKeychainAttribute SecKeychainAttribute API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainAttributePtr @abstract Represents a pointer to a keychain attribute structure. */ -typedef SecKeychainAttribute *SecKeychainAttributePtr API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef SecKeychainAttribute *SecKeychainAttributePtr API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainAttributeList @@ -186,30 +180,30 @@ typedef SecKeychainAttribute *SecKeychainAttributePtr API_UNAVAILABLE(ios, watch @field count An unsigned 32-bit integer that represents the number of keychain attributes in the array. @field attr A pointer to the first keychain attribute in the array. */ -struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) SecKeychainAttributeList +struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) SecKeychainAttributeList { UInt32 count; SecKeychainAttribute * __nullable attr; }; -typedef struct SecKeychainAttributeList SecKeychainAttributeList API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct SecKeychainAttributeList SecKeychainAttributeList API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainStatus @abstract Represents the status of a keychain. */ -typedef UInt32 SecKeychainStatus API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef UInt32 SecKeychainStatus API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecTrustedApplicationRef @abstract Contains information about a trusted application. */ -typedef struct CF_BRIDGED_TYPE(id) __SecTrustedApplication *SecTrustedApplicationRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecTrustedApplication *SecTrustedApplicationRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecAccessRef @abstract Contains information about an access. */ -typedef struct CF_BRIDGED_TYPE(id) __SecAccess *SecAccessRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecAccess *SecAccessRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if TARGET_OS_OSX typedef struct __SecAccess OpaqueSecAccessRef; @@ -219,13 +213,13 @@ typedef struct __SecAccess OpaqueSecAccessRef; @typedef SecACLRef @abstract Contains information about an access control list (ACL) entry. */ -typedef struct CF_BRIDGED_TYPE(id) __SecACL *SecACLRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecACL *SecACLRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecPasswordRef @abstract Contains information about a password. */ -typedef struct CF_BRIDGED_TYPE(id) __SecPassword *SecPasswordRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecPassword *SecPasswordRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainAttributeInfo @@ -235,13 +229,13 @@ typedef struct CF_BRIDGED_TYPE(id) __SecPassword *SecPasswordRef API_UNAVAILABLE @field format A pointer to the first CSSM_DB_ATTRIBUTE_FORMAT in the array. @discussion Each tag and format item form a pair. */ -struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) SecKeychainAttributeInfo +struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) SecKeychainAttributeInfo { UInt32 count; UInt32 *tag; UInt32 * __nullable format; }; -typedef struct SecKeychainAttributeInfo SecKeychainAttributeInfo API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct SecKeychainAttributeInfo SecKeychainAttributeInfo API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecCopyErrorMessageString @@ -342,6 +336,7 @@ CF_ENUM(OSStatus) errSecCoreFoundationUnknown = -4960, errSecMissingEntitlement = -34018, /* A required entitlement isn't present. */ + errSecRestrictedAPI = -34020, /* Client is restricted and is not permitted to perform this operation. */ errSecNotAvailable = -25291, /* No keychain is available. You may need to restart your computer. */ errSecReadOnly = -25292, /* This keychain cannot be modified. */ @@ -710,6 +705,7 @@ CF_ENUM(OSStatus) errSecCertificatePolicyNotAllowed = -67899, /* The requested policy is not allowed for this certificate. */ errSecCertificateNameNotAllowed = -67900, /* The requested name is not allowed for this certificate. */ errSecCertificateValidityPeriodTooLong = -67901, /* The validity period in the certificate exceeds the maximum allowed. */ + errSecCertificateIsCA = -67902, /* The verified certificate is a CA rather than an end-entity */ }; @@ -791,6 +787,7 @@ CF_ENUM(OSStatus) @constant errSSLATSLeafCertificateHashAlgorithmViolation ATS violation: peer leaf certificate hash algorithm is not ATS compliant @constant errSSLATSCertificateHashAlgorithmViolation ATS violation: peer certificate hash algorithm is not ATS compliant @constant errSSLATSCertificateTrustViolation ATS violation: peer certificate is not issued by trusted peer + @constant errSSLEarlyDataRejected Early application data rejected by peer */ /* @@ -889,6 +886,9 @@ CF_ENUM(OSStatus) { errSSLATSLeafCertificateHashAlgorithmViolation = -9884, /* ATS violation: peer leaf certificate hash algorithm is not ATS compliant */ errSSLATSCertificateHashAlgorithmViolation = -9885, /* ATS violation: peer certificate hash algorithm is not ATS compliant */ errSSLATSCertificateTrustViolation = -9886, /* ATS violation: peer certificate is not issued by trusted peer */ + + /* early data errors */ + errSSLEarlyDataRejected = -9890, /* Early application data rejected by peer */ }; CF_IMPLICIT_BRIDGING_DISABLED diff --git a/base/SecBasePriv.h b/base/SecBasePriv.h index d2732607..16578154 100644 --- a/base/SecBasePriv.h +++ b/base/SecBasePriv.h @@ -125,7 +125,7 @@ OSStatus SecKeychainErrFromOSStatus(OSStatus osStatus) * This only apply to MacOS where background session exists. */ void _SecSetSecuritydTargetUID(uid_t uid) - API_AVAILABLE(macos(10.13.5)) API_UNAVAILABLE(ios, iosmac, watchos, tvos, bridgeos); + API_AVAILABLE(macos(10.13.5)) API_UNAVAILABLE(ios, macCatalyst, watchos, tvos, bridgeos); diff --git a/base/SecInternal.h b/base/SecInternal.h index 92d8f3a9..aaa000f4 100644 --- a/base/SecInternal.h +++ b/base/SecInternal.h @@ -29,7 +29,7 @@ #ifndef _SECURITY_SECINTERNAL_H_ #define _SECURITY_SECINTERNAL_H_ -#include +#include "utilities/simulatecrash_assert.h" #include #include diff --git a/base/Security.h b/base/Security.h index 7df4ffea..c5c4914c 100644 --- a/base/Security.h +++ b/base/Security.h @@ -114,11 +114,7 @@ #endif /* DER */ -#ifdef DARLING -#include -#else #include -#endif #endif // SEC_OS_OSX diff --git a/cmake/security_lib.cmake b/cmake/security_lib.cmake deleted file mode 100644 index c083b7cd..00000000 --- a/cmake/security_lib.cmake +++ /dev/null @@ -1,126 +0,0 @@ -include(CMakeParseArguments) - -# add_security_library -# Helper function for adding Security libraries -# (because there's a lot of them, and it's easier to configure all necessary options with a single function) -# -# Options: -# FAT -# Build the library for both x86_64 and i386. -# OBJC_ARC -# Enable Objective-C ARC for the library. -# MODERN_OBJC -# Only build the library for targets where the "modern" Objective-C runtime is available -# -# Single-value arguments: -# OUTPUT_NAME -# The filename for the built library. This is combined with PREFIX and SUFFIX to produce the full filename. -# Defaults to the target name. -# PREFIX -# The prefix to add to the library filename. -# Defaults to `lib`. -# SUFFIX -# The suffix to add to the library filename. -# Defaults to `.dylib`. -# C_STANDARD -# The C standard to use when compiling the code. E.g. `gnu99`, `c99`, etc. -# CXX_STANDARD -# The C++ standard to use when compiling the code. E.g. `gnu++11`, `c++1`, etc. -# -# Multi-value arguments: -# SOURCES -# A list of sources to use to build the library. -# Can include any source that `add_darling_static_library` supports. -# LIBRARIES -# A list of libraries to link to. If target names are provided, they are also added as dependencies. -# INCLUDES -# A list of directories to add as private header directories. -# DEFINITIONS -# A list of preprocessor definitions to add as private preprocessor definitions. -# Supports the same syntax as `add_compile_definitions`. -# FLAGS -# A list of flags to pass to the compiler when compiling the library. -# Supports the same syntax as `add_compile_options`. -function(add_security_library name) - cmake_parse_arguments(SECLIB "FAT;OBJC_ARC;MODERN_OBJC" "OUTPUT_NAME;PREFIX;SUFFIX;C_STANDARD;CXX_STANDARD" "SOURCES;LIBRARIES;INCLUDES;DEFINITIONS;FLAGS" ${ARGN}) - - set(STATICLIB_ARG_RUNTIME "") - set(STATICLIB_ARG_FAT "") - - if(SECLIB_FAT) - set(STATICLIB_ARG_FAT "FAT") - endif() - - if(SECLIB_MODERN_OBJC) - set(STATICLIB_ARG_RUNTIME "64BIT_ONLY") - set(STATICLIB_ARG_FAT "") - endif() - - add_darling_static_library(${name} ${STATICLIB_ARG_FAT} ${STATICLIB_ARG_RUNTIME} SOURCES ${SECLIB_SOURCES}) - - if(SECLIB_OBJC_ARC) - target_compile_options(${name} PRIVATE -fobjc-arc) - endif() - - if(DEFINED SECLIB_OUTPUT_NAME) - set_target_properties(${name} PROPERTIES OUTPUT_NAME "${SECLIB_OUTPUT_NAME}") - endif() - - if(DEFINED SECLIB_PREFIX) - set_target_properties(${name} PROPERTIES PREFIX "${SECLIB_PREFIX}") - endif() - - if(DEFINED SECLIB_SUFFIX) - set_target_properties(${name} PROPERTIES SUFFIX "${SECLIB_SUFFIX}") - endif() - - if(SECLIB_C_STANDARD) - set(SECLIB_C_STANDARD_VALID TRUE) - if(SECLIB_C_STANDARD MATCHES "[cC][0-9]+([a-zA-Z])?") - set_property(TARGET ${name} PROPERTY C_EXTENSIONS OFF) - elseif(SECLIB_C_STANDARD MATCHES "([gG][nN][uU])?[0-9]+([a-zA-Z])?") - # the default is to enable extensions - set_property(TARGET ${name} PROPERTY C_EXTENSIONS ON) - else() - set(SECLIB_C_STANDARD_VALID FALSE) - message(WARNING "Unrecognized C standard: ${SECLIB_C_STANDARD}") - endif() - if(SECLIB_C_STANDARD_VALID) - string(REGEX MATCH "[0-9]+" SECLIB_C_STANDARD_VERSION "${SECLIB_C_STANDARD}") - set_property(TARGET ${name} PROPERTY C_STANDARD "${SECLIB_C_STANDARD_VERSION}") - endif() - endif() - - if(SECLIB_CXX_STANDARD) - set(SECLIB_CXX_STANDARD_VALID TRUE) - if(SECLIB_CXX_STANDARD MATCHES "[cC](\\+\\+|[xX][xX])[0-9]+([a-zA-Z])?") - set_property(TARGET ${name} PROPERTY CXX_EXTENSIONS OFF) - elseif(SECLIB_CXX_STANDARD MATCHES "([gG][nN][uU](\\+\\+|[xX][xX]))?[0-9]+([a-zA-Z])?") - # the default is to enable extensions - set_property(TARGET ${name} PROPERTY CXX_EXTENSIONS ON) - else() - set(SECLIB_CXX_STANDARD_VALID FALSE) - message(WARNING "Unrecognized C standard: ${SECLIB_CXX_STANDARD}") - endif() - if(SECLIB_CXX_STANDARD_VALID) - string(REGEX MATCH "[0-9]+" SECLIB_CXX_STANDARD_VERSION "${SECLIB_CXX_STANDARD}") - set_property(TARGET ${name} PROPERTY CXX_STANDARD "${SECLIB_CXX_STANDARD_VERSION}") - endif() - endif() - - if(SECLIB_LIBRARIES) - target_link_libraries(${name} ${SECLIB_LIBRARIES}) - endif() - - if(SECLIB_INCLUDES) - target_include_directories(${name} PRIVATE ${SECLIB_INCLUDES}) - endif() - - if(SECLIB_DEFINITIONS) - target_compile_definitions(${name} PRIVATE ${SECLIB_DEFINITIONS}) - endif() - - if (SECLIB_FLAGS) - target_compile_options(${name} PRIVATE ${SECLIB_FLAGS}) - endif() -endfunction() diff --git a/cmake/security_xcconfigs.cmake b/cmake/security_xcconfigs.cmake deleted file mode 100644 index ba3530dc..00000000 --- a/cmake/security_xcconfigs.cmake +++ /dev/null @@ -1,38 +0,0 @@ -# some Xcode `.xcconfig` files translated into CMake functions - -include(security_lib) -include(CMakeParseArguments) - -function(add_macos_legacy_lib name) - add_security_library(${name} - FAT - INCLUDES - ${SECURITY_PROJECT_DIR}/OSX/libsecurity_cssm/lib - ${SECURITY_PROJECT_DIR}/OSX/include - ${SECURITY_PROJECT_DIR}/OSX/utilities/src - ${SECURITY_PROJECT_DIR}/OSX/libsecurity_apple_csp/open_ssl - ${SECURITY_PROJECT_DIR}/OSX/lib${name}/lib - ${ARGN} - ) -endfunction() - -function(add_lib_ios name) - add_security_library(${name} - FAT - C_STANDARD gnu99 - INCLUDES - ${SECURITY_PROJECT_DIR}/OSX/libsecurity_smime - #$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers - DEFINITIONS - SEC_IOS_ON_OSX=1 - ${ARGN} - ) -endfunction() - -function(add_lib_ios_shim name) - add_lib_ios(${name} - DEFINITIONS - SECITEM_SHIM_OSX=1 - ${ARGN} - ) -endfunction() diff --git a/codesign_wrapper/check_entitlements.c b/codesign_wrapper/check_entitlements.c index 0ab4da76..68633e06 100644 --- a/codesign_wrapper/check_entitlements.c +++ b/codesign_wrapper/check_entitlements.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/cssm/cssmapple.h b/cssm/cssmapple.h index 456174f9..8fcb7582 100644 --- a/cssm/cssmapple.h +++ b/cssm/cssmapple.h @@ -570,6 +570,8 @@ enum CSSMERR_APPLETP_IDENTIFIER_MISSING = -2147408837, /* Certificate authority pinning mismatch */ CSSMERR_APPLETP_CA_PIN_MISMATCH = -2147408836, + /* Leaf pinning mismatch */ + CSSMERR_APPLETP_LEAF_PIN_MISMATCH = -2147408835, }; /* Apple .mac TP private error codes. */ @@ -605,7 +607,7 @@ enum enum { - CSSM_APPLEDL_OPEN_PARAMETERS_VERSION = 1 + CSSM_APPLEDL_OPEN_PARAMETERS_VERSION = 1u }; enum cssm_appledl_open_parameters_mask diff --git a/derived_src/KeySchema.cpp b/derived_src/KeySchema.cpp deleted file mode 100644 index 0cb875f9..00000000 --- a/derived_src/KeySchema.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Generated by m4 from KeySchema.m4 please do not edit this file. - */ - -#include -#include - -namespace KeySchema { - -// Key attributes -const CSSM_DB_SCHEMA_ATTRIBUTE_INFO KeySchemaAttributeList[] = -{ - { kSecKeyKeyClass, (char*) (char*) "KeyClass", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyPrintName, (char*) (char*) "PrintName", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecKeyAlias, (char*) (char*) "Alias", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecKeyPermanent, (char*) (char*) "Permanent", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyPrivate, (char*) (char*) "Private", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyModifiable, (char*) (char*) "Modifiable", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyLabel, (char*) (char*) "Label", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecKeyApplicationTag, (char*) (char*) "ApplicationTag", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecKeyKeyCreator, (char*) (char*) "KeyCreator", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecKeyKeyType, (char*) (char*) "KeyType", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyKeySizeInBits, (char*) (char*) "KeySizeInBits", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyEffectiveKeySize, (char*) (char*) "EffectiveKeySize", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyStartDate, (char*) (char*) "StartDate", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecKeyEndDate, (char*) (char*) "EndDate", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecKeySensitive, (char*) (char*) "Sensitive", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyAlwaysSensitive, (char*) (char*) "AlwaysSensitive", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyExtractable, (char*) (char*) "Extractable", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyNeverExtractable, (char*) (char*) "NeverExtractable", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyEncrypt, (char*) (char*) "Encrypt", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyDecrypt, (char*) (char*) "Decrypt", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyDerive, (char*) (char*) "Derive", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeySign, (char*) (char*) "Sign", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyVerify, (char*) (char*) "Verify", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeySignRecover, (char*) (char*) "SignRecover", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyVerifyRecover, (char*) (char*) "VerifyRecover", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyWrap, (char*) (char*) "Wrap", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecKeyUnwrap, (char*) (char*) "Unwrap", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, -}; - -const uint32 KeySchemaAttributeCount = sizeof(KeySchemaAttributeList) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO); - -// Key indices -const CSSM_DB_SCHEMA_INDEX_INFO KeySchemaIndexList[] = -{ - // Unique (primary) index - { kSecKeyLabel, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyApplicationTag, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyKeyCreator, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyKeyType, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyKeySizeInBits, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyEffectiveKeySize, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyStartDate, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyEndDate, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - - // Secondary indices - { kSecKeyLabel, 1, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyEncrypt, 2, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyDecrypt, 3, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyDerive, 4, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeySign, 5, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyVerify, 6, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeySignRecover, 7, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyVerifyRecover, 8, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyWrap, 9, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecKeyUnwrap, 10, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, -}; - -const uint32 KeySchemaIndexCount = sizeof(KeySchemaIndexList) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO); - -const CSSM_DB_ATTRIBUTE_INFO KeyClass = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "KeyClass"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO PrintName = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "PrintName"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO Alias = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Alias"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO Permanent = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Permanent"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Private = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Private"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Modifiable = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Modifiable"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Label = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Label"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO ApplicationTag = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "ApplicationTag"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO KeyCreator = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "KeyCreator"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO KeyType = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "KeyType"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO KeySizeInBits = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "KeySizeInBits"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO EffectiveKeySize = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "EffectiveKeySize"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO StartDate = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "StartDate"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO EndDate = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "EndDate"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO Sensitive = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Sensitive"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO AlwaysSensitive = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "AlwaysSensitive"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Extractable = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Extractable"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO NeverExtractable = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "NeverExtractable"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Encrypt = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Encrypt"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Decrypt = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Decrypt"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Derive = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Derive"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Sign = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Sign"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Verify = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Verify"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO SignRecover = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "SignRecover"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO VerifyRecover = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "VerifyRecover"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Wrap = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Wrap"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO Unwrap = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Unwrap"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - - -} // end namespace KeySchema diff --git a/derived_src/Schema.cpp b/derived_src/Schema.cpp deleted file mode 100644 index 2ed0b557..00000000 --- a/derived_src/Schema.cpp +++ /dev/null @@ -1,1383 +0,0 @@ -/* - * Generated by m4 from Schema.m4 please do not edit this file. - */ - -#include - -#include -#include -#include -#include -#include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-const-variable" - -namespace Security { - -namespace KeychainCore { - -namespace Schema { - -// Meta attributes -const CSSM_DB_ATTRIBUTE_INFO RelationID = - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "RelationID"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }; - -const CSSM_DB_ATTRIBUTE_INFO RelationName = - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "RelationName"}, - CSSM_DB_ATTRIBUTE_FORMAT_STRING - }; - -const CSSM_DB_ATTRIBUTE_INFO AttributeID = - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "AttributeID"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }; - -const CSSM_DB_ATTRIBUTE_INFO AttributeNameFormat = - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "AttributeNameFormat"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }; - -const CSSM_DB_ATTRIBUTE_INFO AttributeName = - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "AttributeName"}, - CSSM_DB_ATTRIBUTE_FORMAT_STRING - }; - -const CSSM_DB_ATTRIBUTE_INFO AttributeNameID = - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "AttributeNameID"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }; - -const CSSM_DB_ATTRIBUTE_INFO AttributeFormat = - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "AttributeFormat"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }; - -const CSSM_DB_ATTRIBUTE_INFO IndexType = - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "IndexType"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }; - - -// Generic password attributes -static const CSSM_DB_ATTRIBUTE_INFO GenericAttributes[] = -{ - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCreationDateItemAttr<<32|kSecCreationDateItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecModDateItemAttr<<32|kSecModDateItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecDescriptionItemAttr<<32|kSecDescriptionItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCommentItemAttr<<32|kSecCommentItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCreatorItemAttr<<32|kSecCreatorItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecTypeItemAttr<<32|kSecTypeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecScriptCodeItemAttr<<32|kSecScriptCodeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "PrintName"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Alias"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecInvisibleItemAttr<<32|kSecInvisibleItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecNegativeItemAttr<<32|kSecNegativeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCustomIconItemAttr<<32|kSecCustomIconItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecProtectedDataItemAttr<<32|kSecProtectedDataItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAccountItemAttr<<32|kSecAccountItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecServiceItemAttr<<32|kSecServiceItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecGenericItemAttr<<32|kSecGenericItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, -}; - -// Appleshare password attributes -static const CSSM_DB_ATTRIBUTE_INFO AppleshareAttributes[] = -{ - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCreationDateItemAttr<<32|kSecCreationDateItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecModDateItemAttr<<32|kSecModDateItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecDescriptionItemAttr<<32|kSecDescriptionItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCommentItemAttr<<32|kSecCommentItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCreatorItemAttr<<32|kSecCreatorItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecTypeItemAttr<<32|kSecTypeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecScriptCodeItemAttr<<32|kSecScriptCodeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "PrintName"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Alias"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecInvisibleItemAttr<<32|kSecInvisibleItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecNegativeItemAttr<<32|kSecNegativeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCustomIconItemAttr<<32|kSecCustomIconItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecProtectedDataItemAttr<<32|kSecProtectedDataItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAccountItemAttr<<32|kSecAccountItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecVolumeItemAttr<<32|kSecVolumeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecServerItemAttr<<32|kSecServerItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecProtocolItemAttr<<32|kSecProtocolItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAddressItemAttr<<32|kSecAddressItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecSignatureItemAttr<<32|kSecSignatureItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, -}; - -// Internet password attributes -static const CSSM_DB_ATTRIBUTE_INFO InternetAttributes[] = -{ - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCreationDateItemAttr<<32|kSecCreationDateItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecModDateItemAttr<<32|kSecModDateItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecDescriptionItemAttr<<32|kSecDescriptionItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCommentItemAttr<<32|kSecCommentItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCreatorItemAttr<<32|kSecCreatorItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecTypeItemAttr<<32|kSecTypeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecScriptCodeItemAttr<<32|kSecScriptCodeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "PrintName"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Alias"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecInvisibleItemAttr<<32|kSecInvisibleItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecNegativeItemAttr<<32|kSecNegativeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecCustomIconItemAttr<<32|kSecCustomIconItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_SINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecProtectedDataItemAttr<<32|kSecProtectedDataItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAccountItemAttr<<32|kSecAccountItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecSecurityDomainItemAttr<<32|kSecSecurityDomainItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecServerItemAttr<<32|kSecServerItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecProtocolItemAttr<<32|kSecProtocolItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAuthenticationTypeItemAttr<<32|kSecAuthenticationTypeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecPortItemAttr<<32|kSecPortItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - }, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecPathItemAttr<<32|kSecPathItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - }, -}; - -#define kGenericCreationDate GenericAttributes[0]; -#define kGenericModDate GenericAttributes[1]; -#define kGenericDescription GenericAttributes[2]; -#define kGenericComment GenericAttributes[3]; -#define kGenericCreator GenericAttributes[4]; -#define kGenericType GenericAttributes[5]; -#define kGenericScriptCode GenericAttributes[6]; -#define kGenericPrintName GenericAttributes[7]; -#define kGenericAlias GenericAttributes[8]; -#define kGenericInvisible GenericAttributes[9]; -#define kGenericNegative GenericAttributes[10]; -#define kGenericCustomIcon GenericAttributes[11]; -#define kGenericProtected GenericAttributes[12]; -#define kGenericAccount GenericAttributes[13]; -#define kGenericService GenericAttributes[14]; -#define kGenericGeneric GenericAttributes[15]; -#define kAppleshareCreationDate AppleshareAttributes[0]; -#define kAppleshareModDate AppleshareAttributes[1]; -#define kAppleshareDescription AppleshareAttributes[2]; -#define kAppleshareComment AppleshareAttributes[3]; -#define kAppleshareCreator AppleshareAttributes[4]; -#define kAppleshareType AppleshareAttributes[5]; -#define kAppleshareScriptCode AppleshareAttributes[6]; -#define kApplesharePrintName AppleshareAttributes[7]; -#define kAppleshareAlias AppleshareAttributes[8]; -#define kAppleshareInvisible AppleshareAttributes[9]; -#define kAppleshareNegative AppleshareAttributes[10]; -#define kAppleshareCustomIcon AppleshareAttributes[11]; -#define kAppleshareProtected AppleshareAttributes[12]; -#define kAppleshareAccount AppleshareAttributes[13]; -#define kAppleshareVolume AppleshareAttributes[14]; -#define kAppleshareServer AppleshareAttributes[15]; -#define kAppleshareProtocol AppleshareAttributes[16]; -#define kAppleshareAddress AppleshareAttributes[17]; -#define kAppleshareSignature AppleshareAttributes[18]; -#define kInternetCreationDate InternetAttributes[0]; -#define kInternetModDate InternetAttributes[1]; -#define kInternetDescription InternetAttributes[2]; -#define kInternetComment InternetAttributes[3]; -#define kInternetCreator InternetAttributes[4]; -#define kInternetType InternetAttributes[5]; -#define kInternetScriptCode InternetAttributes[6]; -#define kInternetPrintName InternetAttributes[7]; -#define kInternetAlias InternetAttributes[8]; -#define kInternetInvisible InternetAttributes[9]; -#define kInternetNegative InternetAttributes[10]; -#define kInternetCustomIcon InternetAttributes[11]; -#define kInternetProtected InternetAttributes[12]; -#define kInternetAccount InternetAttributes[13]; -#define kInternetSecurityDomain InternetAttributes[14]; -#define kInternetServer InternetAttributes[15]; -#define kInternetProtocol InternetAttributes[16]; -#define kInternetAuthType InternetAttributes[17]; -#define kInternetPort InternetAttributes[18]; -#define kInternetPath InternetAttributes[19]; -// X509Certificate attributes -const CSSM_DB_SCHEMA_ATTRIBUTE_INFO X509CertificateSchemaAttributeList[] = -{ - { kSecCertTypeItemAttr, (char*) "CertType", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecCertEncodingItemAttr, (char*) "CertEncoding", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecLabelItemAttr, (char*) "PrintName", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecAlias, (char*) "Alias", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecSubjectItemAttr, (char*) "Subject", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecIssuerItemAttr, (char*) "Issuer", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecSerialNumberItemAttr, (char*) "SerialNumber", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecSubjectKeyIdentifierItemAttr, (char*) "SubjectKeyIdentifier", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecPublicKeyHashItemAttr, (char*) "PublicKeyHash", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, -}; - -const uint32 X509CertificateSchemaAttributeCount = sizeof(X509CertificateSchemaAttributeList) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO); - -// X509Certificate indices -const CSSM_DB_SCHEMA_INDEX_INFO X509CertificateSchemaIndexList[] = -{ - // Unique (primary) index - { kSecCertTypeItemAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecIssuerItemAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecSerialNumberItemAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - - // Secondary indices - { kSecCertTypeItemAttr, 1, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecAlias, 2, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecSubjectItemAttr, 3, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecIssuerItemAttr, 4, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecSerialNumberItemAttr, 5, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecSubjectKeyIdentifierItemAttr, 6, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecPublicKeyHashItemAttr, 7, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, -}; - -const uint32 X509CertificateSchemaIndexCount = sizeof(X509CertificateSchemaIndexList) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO); - -const CSSM_DB_ATTRIBUTE_INFO kX509CertificateCertType = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "CertType"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CertificateCertEncoding = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "CertEncoding"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CertificatePrintName = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "PrintName"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CertificateAlias = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Alias"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CertificateSubject = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Subject"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CertificateIssuer = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Issuer"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CertificateSerialNumber = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "SerialNumber"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CertificateSubjectKeyIdentifier = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "SubjectKeyIdentifier"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CertificatePublicKeyHash = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "PublicKeyHash"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - - -// X509Crl attributes -const CSSM_DB_SCHEMA_ATTRIBUTE_INFO X509CrlSchemaAttributeList[] = -{ - { kSecCrlType, (char*) "CrlType", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecCrlEncodingItemAttr, (char*) "CrlEncoding", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecLabelItemAttr, (char*) "PrintName", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecAlias, (char*) "Alias", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecIssuerItemAttr, (char*) "Issuer", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecThisUpdateItemAttr, (char*) "ThisUpdate", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecNextUpdateItemAttr, (char*) "NextUpdate", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecUriItemAttr, (char*) "URI", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecCrlNumberItemAttr, (char*) "CrlNumber", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecDeltaCrlNumberItemAttr, (char*) "DeltaCrlNumber", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, -}; - -const uint32 X509CrlSchemaAttributeCount = sizeof(X509CrlSchemaAttributeList) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO); - -// X509Crl indices -const CSSM_DB_SCHEMA_INDEX_INFO X509CrlSchemaIndexList[] = -{ - // Unique (primary) index - { kSecCrlType, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecIssuerItemAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecThisUpdateItemAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecNextUpdateItemAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecUriItemAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - - // Secondary indices - { kSecCrlType, 1, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecIssuerItemAttr, 2, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecThisUpdateItemAttr, 3, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecNextUpdateItemAttr, 4, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecUriItemAttr, 5, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecCrlNumberItemAttr, 6, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecDeltaCrlNumberItemAttr, 7, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, -}; - -const uint32 X509CrlSchemaIndexCount = sizeof(X509CrlSchemaIndexList) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO); - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlCrlType = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "CrlType"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlCrlEncoding = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "CrlEncoding"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlPrintName = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "PrintName"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlAlias = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Alias"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlIssuer = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Issuer"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlThisUpdate = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "ThisUpdate"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlNextUpdate = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "NextUpdate"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlURI = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "URI"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlCrlNumber = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "CrlNumber"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO kX509CrlDeltaCrlNumber = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "DeltaCrlNumber"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - - -// UserTrust attributes -const CSSM_DB_SCHEMA_ATTRIBUTE_INFO UserTrustSchemaAttributeList[] = -{ - { kSecTrustCertAttr, (char*) "TrustedCertificate", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecTrustPolicyAttr, (char*) "TrustedPolicy", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecLabelItemAttr, (char*) "PrintName", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, -}; - -const uint32 UserTrustSchemaAttributeCount = sizeof(UserTrustSchemaAttributeList) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO); - -// UserTrust indices -const CSSM_DB_SCHEMA_INDEX_INFO UserTrustSchemaIndexList[] = -{ - // Unique (primary) index - { kSecTrustCertAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecTrustPolicyAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - - // Secondary indices - { kSecTrustCertAttr, 1, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecTrustPolicyAttr, 2, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, -}; - -const uint32 UserTrustSchemaIndexCount = sizeof(UserTrustSchemaIndexList) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO); - -const CSSM_DB_ATTRIBUTE_INFO kUserTrustTrustedCertificate = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "TrustedCertificate"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kUserTrustTrustedPolicy = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "TrustedPolicy"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kUserTrustPrintName = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "PrintName"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - - -// UnlockReferral attributes -const CSSM_DB_SCHEMA_ATTRIBUTE_INFO UnlockReferralSchemaAttributeList[] = -{ - { kSecReferralTypeAttr, (char*) "Type", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecReferralDbNameAttr, (char*) "DbName", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_STRING }, - { kSecReferralDbNetnameAttr, (char*) "DbNetname", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecReferralDbGuidAttr, (char*) "DbGuid", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecReferralDbSSIDAttr, (char*) "DbSSID", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecReferralDbSSTypeAttr, (char*) "DbSSType", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kSecReferralKeyLabelAttr, (char*) "KeyLabel", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecReferralKeyAppTagAttr, (char*) "KeyAppTag", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecLabelItemAttr, (char*) "PrintName", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecAlias, (char*) "Alias", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, -}; - -const uint32 UnlockReferralSchemaAttributeCount = sizeof(UnlockReferralSchemaAttributeList) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO); - -// UnlockReferral indices -const CSSM_DB_SCHEMA_INDEX_INFO UnlockReferralSchemaIndexList[] = -{ - // Unique (primary) index - { kSecReferralTypeAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbNameAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbNetnameAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbGuidAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbSSIDAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbSSTypeAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - - // Secondary indices - { kSecReferralTypeAttr, 1, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbNameAttr, 2, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbNetnameAttr, 3, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbGuidAttr, 4, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbSSIDAttr, 5, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralDbSSTypeAttr, 6, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralKeyLabelAttr, 7, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kSecReferralKeyAppTagAttr, 8, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, -}; - -const uint32 UnlockReferralSchemaIndexCount = sizeof(UnlockReferralSchemaIndexList) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO); - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralType = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Type"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbName = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "DbName"}, - CSSM_DB_ATTRIBUTE_FORMAT_STRING -}; - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbNetname = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "DbNetname"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbGuid = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "DbGuid"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbSSID = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "DbSSID"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralDbSSType = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "DbSSType"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralKeyLabel = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "KeyLabel"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralKeyAppTag = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "KeyAppTag"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralPrintName = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "PrintName"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kUnlockReferralAlias = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "Alias"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - - -// Extended Attribute -// ExtendedAttribute attributes -const CSSM_DB_SCHEMA_ATTRIBUTE_INFO ExtendedAttributeSchemaAttributeList[] = -{ - { kExtendedAttrRecordTypeAttr, (char*) "RecordType", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_UINT32 }, - { kExtendedAttrItemIDAttr, (char*) "ItemID", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kExtendedAttrAttributeNameAttr, (char*) "AttributeName", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, - { kSecModDateItemAttr, (char*) "ModDate", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE }, - { kExtendedAttrAttributeValueAttr, (char*) "AttributeValue", { 0, NULL }, CSSM_DB_ATTRIBUTE_FORMAT_BLOB }, -}; - -const uint32 ExtendedAttributeSchemaAttributeCount = sizeof(ExtendedAttributeSchemaAttributeList) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO); - -// ExtendedAttribute indices -const CSSM_DB_SCHEMA_INDEX_INFO ExtendedAttributeSchemaIndexList[] = -{ - // Unique (primary) index - { kExtendedAttrRecordTypeAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kExtendedAttrItemIDAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kExtendedAttrAttributeNameAttr, 0, CSSM_DB_INDEX_UNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - - // Secondary indices - { kExtendedAttrRecordTypeAttr, 1, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kExtendedAttrItemIDAttr, 2, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, - { kExtendedAttrAttributeNameAttr, 3, CSSM_DB_INDEX_NONUNIQUE, CSSM_DB_INDEX_ON_ATTRIBUTE }, -}; - -const uint32 ExtendedAttributeSchemaIndexCount = sizeof(ExtendedAttributeSchemaIndexList) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO); - -const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeRecordType = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "RecordType"}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 -}; - -const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeItemID = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "ItemID"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeAttributeName = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "AttributeName"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - -const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeModDate = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "ModDate"}, - CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE -}; - -const CSSM_DB_ATTRIBUTE_INFO kExtendedAttributeAttributeValue = -{ - CSSM_DB_ATTRIBUTE_NAME_AS_STRING, - {(char*) "AttributeValue"}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB -}; - - -// Generic password indices -static const CSSM_DB_INDEX_INFO GenericIndices[] = -{ - // Unique (primary) index - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAccountItemAttr<<32|kSecAccountItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecServiceItemAttr<<32|kSecServiceItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - - // Secondary indices - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAccountItemAttr<<32|kSecAccountItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecServiceItemAttr<<32|kSecServiceItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, -}; - -// Appleshare password indices -static const CSSM_DB_INDEX_INFO AppleshareIndices[] = -{ - // Unique (primary) index - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAccountItemAttr<<32|kSecAccountItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecVolumeItemAttr<<32|kSecVolumeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAddressItemAttr<<32|kSecAddressItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecSignatureItemAttr<<32|kSecSignatureItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - - // Secondary indices - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAccountItemAttr<<32|kSecAccountItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecVolumeItemAttr<<32|kSecVolumeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAddressItemAttr<<32|kSecAddressItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecSignatureItemAttr<<32|kSecSignatureItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, -}; - -// Internet password indices -static const CSSM_DB_INDEX_INFO InternetIndices[] = -{ - // Unique (primary) index - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAccountItemAttr<<32|kSecAccountItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecSecurityDomainItemAttr<<32|kSecSecurityDomainItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecServerItemAttr<<32|kSecServerItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecProtocolItemAttr<<32|kSecProtocolItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAuthenticationTypeItemAttr<<32|kSecAuthenticationTypeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecPortItemAttr<<32|kSecPortItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - } - }, - { - CSSM_DB_INDEX_UNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecPathItemAttr<<32|kSecPathItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - - // Secondary indices - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAccountItemAttr<<32|kSecAccountItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecSecurityDomainItemAttr<<32|kSecSecurityDomainItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecServerItemAttr<<32|kSecServerItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecProtocolItemAttr<<32|kSecProtocolItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecAuthenticationTypeItemAttr<<32|kSecAuthenticationTypeItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecPortItemAttr<<32|kSecPortItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_UINT32 - } - }, - { - CSSM_DB_INDEX_NONUNIQUE, - CSSM_DB_INDEX_ON_ATTRIBUTE, - { - CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, - {(char *)((uint64_t)kSecPathItemAttr<<32|kSecPathItemAttr)}, - CSSM_DB_ATTRIBUTE_FORMAT_BLOB - } - }, -}; - - -static const CSSM_DB_RECORD_ATTRIBUTE_INFO Attributes[] = -{ - { - CSSM_DL_DB_RECORD_GENERIC_PASSWORD, - sizeof(GenericAttributes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), - const_cast(GenericAttributes) - }, - { - CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD, - sizeof(AppleshareAttributes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), - const_cast(AppleshareAttributes) - }, - { - CSSM_DL_DB_RECORD_INTERNET_PASSWORD, - sizeof(InternetAttributes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), - const_cast(InternetAttributes) - } -}; - -static const CSSM_DB_RECORD_INDEX_INFO Indices[] = -{ - { - CSSM_DL_DB_RECORD_GENERIC_PASSWORD, - sizeof(GenericIndices) / sizeof(CSSM_DB_INDEX_INFO), - const_cast(GenericIndices) - }, - { - CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD, - sizeof(AppleshareIndices) / sizeof(CSSM_DB_INDEX_INFO), - const_cast(AppleshareIndices) - }, - { - CSSM_DL_DB_RECORD_INTERNET_PASSWORD, - sizeof(InternetIndices) / sizeof(CSSM_DB_INDEX_INFO), - const_cast(InternetIndices) - } -}; - -static const CSSM_DB_PARSING_MODULE_INFO ParseInfos[] = -{ - { - CSSM_DB_RECORDTYPE_APP_DEFINED_START, - { - {0,0,0,{0}}, - {0,0}, - 0, - 0 - } - }, - { - CSSM_DB_RECORDTYPE_APP_DEFINED_START, - { - {0,0,0,{0}}, - {0,0}, - 0, - 0 - } - }, - { - CSSM_DB_RECORDTYPE_APP_DEFINED_START, - { - {0,0,0,{0}}, - {0,0}, - 0, - 0 - } - } -}; - -// -// Public stuff -// -const CSSM_DBINFO DBInfo = -{ - sizeof(Attributes) / sizeof(CSSM_DB_RECORD_ATTRIBUTE_INFO), - const_cast(ParseInfos), - const_cast(Attributes), - const_cast(Indices), - CSSM_TRUE, - NULL, - NULL -}; - -// -// Schema methods -// -CSSM_DB_RECORDTYPE -recordTypeFor(SecItemClass itemClass) -{ - switch (itemClass) - { - case kSecGenericPasswordItemClass: return CSSM_DL_DB_RECORD_GENERIC_PASSWORD; - case kSecInternetPasswordItemClass: return CSSM_DL_DB_RECORD_INTERNET_PASSWORD; - case 'ashp': return CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD; - default: return CSSM_DB_RECORDTYPE(itemClass); - } -} - -SecItemClass -itemClassFor(CSSM_DB_RECORDTYPE recordType) -{ - switch (recordType) - { - case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: return kSecGenericPasswordItemClass; - case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: return kSecInternetPasswordItemClass; - case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: return (SecItemClass) 'ashp'; - default: return SecItemClass(recordType); - } -} - -bool -haveAttributeInfo(SecKeychainAttrType attrType) -{ -switch (attrType) -{ -case kSecCreationDateItemAttr: return true; -case kSecModDateItemAttr: return true; -case kSecDescriptionItemAttr: return true; -case kSecCommentItemAttr: return true; -case kSecCreatorItemAttr: return true; -case kSecTypeItemAttr: return true; -case kSecScriptCodeItemAttr: return true; -case kSecLabelItemAttr: return true; -case kSecAlias: return true; -case kSecInvisibleItemAttr: return true; -case kSecNegativeItemAttr: return true; -case kSecCustomIconItemAttr: return true; -/* Unique Generic password attributes */ -case kSecAccountItemAttr: return true; -case kSecServiceItemAttr: return true; -case kSecGenericItemAttr: return true; -/* Unique Appleshare password attributes */ -case kSecVolumeItemAttr: return true; -case kSecAddressItemAttr: return true; -case kSecSignatureItemAttr: return true; -/* Unique AppleShare and Internet attributes */ -case kSecServerItemAttr: return true; -case kSecProtocolItemAttr: return true; -/* Unique Internet password attributes */ -case kSecSecurityDomainItemAttr: return true; -case kSecAuthenticationTypeItemAttr: return true; -case kSecPortItemAttr: return true; -case kSecPathItemAttr: return true; -/* Unique Certificate attributes */ -case kSecCertTypeItemAttr: return true; -case kSecCertEncodingItemAttr: return true; -case kSecSubjectItemAttr: return true; -case kSecIssuerItemAttr: return true; -case kSecSerialNumberItemAttr: return true; -case kSecSubjectKeyIdentifierItemAttr: return true; -case kSecPublicKeyHashItemAttr: return true; -/* Unique UserTrust attributes */ -case kSecTrustCertAttr: return true; -case kSecTrustPolicyAttr: return true; -/* Unique UnlockReferral attributes */ -case kSecReferralTypeAttr: return true; -case kSecReferralDbNameAttr: return true; -case kSecReferralDbGuidAttr: return true; -case kSecReferralDbSSIDAttr: return true; -case kSecReferralDbSSTypeAttr: return true; -case kSecReferralDbNetnameAttr: return true; -case kSecReferralKeyLabelAttr: return true; -case kSecReferralKeyAppTagAttr: return true; -/* Unique ExtendedAttribute attributes */ -case kExtendedAttrRecordTypeAttr: return true; -case kExtendedAttrItemIDAttr: return true; -case kExtendedAttrAttributeNameAttr: return true; -case kExtendedAttrAttributeValueAttr: return true; -/* ??? */ -case kSecProtectedDataItemAttr: return true; -default: -{ -if (attrType == 7) -{ -return true; -} -else if (attrType == 8) -{ -return true; -} -return false; -} -} -} - -const CSSM_DB_ATTRIBUTE_INFO & -attributeInfo(SecKeychainAttrType attrType) -{ - switch (attrType) - { - case kSecCreationDateItemAttr: return kGenericCreationDate; - case kSecModDateItemAttr: return kGenericModDate; - case kSecDescriptionItemAttr: return kGenericDescription; - case kSecCommentItemAttr: return kGenericComment; - case kSecCreatorItemAttr: return kGenericCreator; - case kSecTypeItemAttr: return kGenericType; - case kSecScriptCodeItemAttr: return kGenericScriptCode; - case kSecLabelItemAttr: return kGenericPrintName; - case kSecAlias: return kGenericAlias; - case kSecInvisibleItemAttr: return kGenericInvisible; - case kSecNegativeItemAttr: return kGenericNegative; - case kSecCustomIconItemAttr: return kGenericCustomIcon; - /* Unique Generic password attributes */ - case kSecAccountItemAttr: return kGenericAccount; - case kSecServiceItemAttr: return kGenericService; - case kSecGenericItemAttr: return kGenericGeneric; - /* Unique Appleshare password attributes */ - case kSecVolumeItemAttr: return kAppleshareVolume; - case kSecAddressItemAttr: return kAppleshareAddress; - case kSecSignatureItemAttr: return kAppleshareSignature; - /* Unique AppleShare and Internet attributes */ - case kSecServerItemAttr: return kAppleshareServer; - case kSecProtocolItemAttr: return kAppleshareProtocol; - /* Unique Internet password attributes */ - case kSecSecurityDomainItemAttr: return kInternetSecurityDomain; - case kSecAuthenticationTypeItemAttr: return kInternetAuthType; - case kSecPortItemAttr: return kInternetPort; - case kSecPathItemAttr: return kInternetPath; - /* Unique Certificate attributes */ - case kSecCertTypeItemAttr: return kX509CertificateCertType; - case kSecCertEncodingItemAttr: return kX509CertificateCertEncoding; - case kSecSubjectItemAttr: return kX509CertificateSubject; - case kSecIssuerItemAttr: return kX509CertificateIssuer; - case kSecSerialNumberItemAttr: return kX509CertificateSerialNumber; - case kSecSubjectKeyIdentifierItemAttr: return kX509CertificateSubjectKeyIdentifier; - case kSecPublicKeyHashItemAttr: return kX509CertificatePublicKeyHash; - /* Unique UserTrust attributes */ - case kSecTrustCertAttr: return kUserTrustTrustedCertificate; - case kSecTrustPolicyAttr: return kUserTrustTrustedPolicy; - /* Unique UnlockReferral attributes */ - case kSecReferralTypeAttr: return kUnlockReferralType; - case kSecReferralDbNameAttr: return kUnlockReferralDbName; - case kSecReferralDbGuidAttr: return kUnlockReferralDbGuid; - case kSecReferralDbSSIDAttr: return kUnlockReferralDbSSID; - case kSecReferralDbSSTypeAttr: return kUnlockReferralDbSSType; - case kSecReferralDbNetnameAttr: return kUnlockReferralDbNetname; - case kSecReferralKeyLabelAttr: return kUnlockReferralKeyLabel; - case kSecReferralKeyAppTagAttr: return kUnlockReferralKeyAppTag; - /* Unique ExtendedAttribute attributes */ - case kExtendedAttrRecordTypeAttr: return kExtendedAttributeRecordType; - case kExtendedAttrItemIDAttr: return kExtendedAttributeItemID; - case kExtendedAttrAttributeNameAttr: return kExtendedAttributeAttributeName; - case kExtendedAttrAttributeValueAttr: return kExtendedAttributeAttributeValue; - /* ??? */ - case kSecProtectedDataItemAttr: return kGenericProtected; - default: - { - if (attrType == 7) - { - return kGenericPrintName; - } - else if (attrType == 8) - { - return kGenericAlias; - } - MacOSError::throwMe(errSecNoSuchAttr); - } - } -} - -} // end namespace Schema - -} // end namespace KeychainCore - -} // end namespace Security - -#pragma clang diagnostic pop diff --git a/derived_src/cssmexports.gen b/derived_src/cssmexports.gen deleted file mode 100644 index 846877b1..00000000 --- a/derived_src/cssmexports.gen +++ /dev/null @@ -1,634 +0,0 @@ -_CSSMOID_SupportedApplicationContext -_CSSMOID_CrlReason -_CSSMOID_APPLE_TP_ESCROW_SERVICE -_CSSMOID_X9_62_C_TwoCurve -_CSSMOID_CountryName -_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_STORE -_CSSMOID_TimeStamping -_CSSMOID_secp256r1 -_CSSMOID_UniqueIdentifier -_CSSMOID_InvalidityDate -_CSSMOID_PrivateKeyUsagePeriod -_CSSMOID_CollectiveTelexNumber -_CSSMOID_sect131r2 -_CSSMOID_APPLE_EKU_CODE_SIGNING -_CSSM_CL_CrlRemoveCert -_CSSM_DecryptData -_CSSMOID_APPLE_EXTENSION_APPLEID_SHARING -_CSSMOID_InhibitAnyPolicy -_CSSMOID_PhysicalDeliveryOfficeName -_CSSMOID_PDA_DATE_OF_BIRTH -_CSSMOID_CrossCertificatePair -_CSSMOID_UnstructuredAddress -_CSSMOID_secp128r1 -_CSSM_CSP_CreateRandomGenContext -_CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING -_CSSMOID_X509V2CRLExtensionCritical -_CSSMOID_MD5 -_CSSM_CL_CrlGetNextFieldValue -_CSSMOID_X509V3CertificateExtensionCritical -_CSSM_GetModuleGUIDFromHandle -_CSSM_SignDataUpdate -_CSSMOID_X509V2CRLExtensionId -_CSSMOID_SHA256WithRSA -_CSSMOID_PolicyConstraints -_CSSMOID_PKCS12_keyBag -_CSSMOID_X509V1SubjectPublicKeyAlgorithm -_CSSMOID_RegisteredAddress -_CSSMOID_ANSI_MQV2 -_CSSMOID_PKCS12_crlBag -_CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION -_CSSMOID_DOTMAC_CERT_EMAIL_ENCRYPT -_CSSM_DecryptDataUpdate -_CSSMOID_TEST_MOBILE_STORE_SIGNING_POLICY -_CSSM_CL_CertGetFirstCachedFieldValue -_CSSMOID_MD2 -_CSSM_TP_CertGroupPrune -_CSSM_Introduce -_CSSMOID_DSA -_CSSMOID_APPLE_EXTENSION_ADC_APPLE_SIGNING -_CSSMOID_X509V2CRLTbsCertListStruct -_CSSMOID_APPLE_EKU_SYSTEM_IDENTITY -_CSSMOID_Initials -_CSSMOID_PDA_COUNTRY_RESIDENCE -_CSSM_GenerateKey -_CSSM_CL_CertVerify -_CSSMOID_PKCS5_DIGEST_ALG -_CSSMOID_PDA_GENDER -_CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME -_CSSMOID_X509V3CertificateCStruct -_CSSM_DigestDataClone -_CSSMOID_ECDSA_WithSHA256 -_CSSM_CL_IsCertInCrl -_CSSMOID_SubjectInfoAccess -_CSSM_CL_CertCache -_CSSMOID_HouseIdentifier -_CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC -_CSSM_VerifyMac -_CSSMOID_OAEP_MGF1 -_CSSMOID_PKIX_OCSP_CRL -_CSSMOID_ANSI_DH_ONE_FLOW_SHA1 -_CSSMOID_SHA224WithRSA -_CSSMOID_X509V2CRLRevokedEntryExtensionId -_CSSM_CSP_CreatePassThroughContext -_CSSMOID_APPLE_X509_BASIC -_CSSMOID_OID_QCS_SYNTAX_V2 -_CSSMOID_FacsimileTelephoneNumber -_CSSM_CL_IsCertInCachedCrl -_CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC -_CSSMOID_secp224r1 -_CSSM_CL_CertGetAllTemplateFields -_CSSMOID_IssuerAltName -_CSSMOID_APPLE_CERT_POLICY -_CSSM_DL_DbDelete -_CSSMOID_SubjectPicture -_CSSMOID_DOTMAC_CERT_EXTENSION -_CSSMOID_ProtocolInformation -_CSSMOID_APPLE_FEED -_CSSMOID_X509V2CRLSignedCrlStruct -_CSSM_CSP_GetLoginAcl -_CSSMOID_X509V1IssuerNameStd -_CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC -_CSSMOID_DSA_CMS -_CSSM_TP_TupleGroupToCertGroup -_CSSMOID_secp128r2 -_CSSM_DL_DbOpen -_CSSMOID_APPLEID_SHARING_CERT_POLICY -_CSSM_TP_CertGroupConstruct -_CSSMOID_sect571r1 -_CSSM_CL_CrlGetAllFields -_CSSMOID_PDA_PLACE_OF_BIRTH -_CSSMOID_X509V1SignatureStruct -_CSSMOID_APPLE_EKU_ICHAT_SIGNING -_CSSMOID_ECDSA_WithSHA1 -_CSSMOID_sect131r1 -_CSSM_TP_CertReclaimKey -_CSSMOID_APPLE_EXTENSION_AAI_INTERMEDIATE -_CSSM_Init -_CSSM_TP_ReceiveConfirmation -_CSSMOID_sect233r1 -_CSSMOID_GivenName -_CSSMOID_X509V3CertificateExtensionsStruct -_CSSM_GetKeyAcl -_CSSM_GenerateKeyP -_CSSM_RetrieveUniqueId -_CSSM_DecryptDataFinal -_CSSMOID_PKCS5_pbeWithMD5AndDES -_CSSMOID_TelexTerminalIdentifier -_CSSM_DecryptDataInit -_CSSM_DecryptDataP -_CSSMOID_CollectiveTelexTerminalIdentifier -_CSSM_CSP_ChangeLoginAcl -_CSSM_GenerateKeyPair -_CSSMOID_APPLE_TP_SMIME -_CSSM_DL_GetDbNames -_CSSMOID_APPLE_TP_ICHAT -_CSSM_GetContextAttribute -_CSSMOID_X9_62 -_CSSMOID_DOTMAC_CERT_POLICY -_CSSMOID_PKIX_OCSP_NOCHECK -_CSSM_DeriveKey -_CSSMOID_CollectivePostalCode -_CSSMOID_X509V3CertificateNumberOfExtensions -_CSSMOID_QT_UNOTICE -_CSSMOID_ServerAuth -_CSSMOID_UserPassword -_CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE -_CSSMOID_CommonName -_CSSMOID_PKCS3 -_CSSMOID_APPLE_TP_TEST_MOBILE_STORE -_CSSMOID_ClientAuth -_CSSMOID_CACertificate -_CSSMOID_X509V1CRLRevokedEntrySerialNumber -_CSSMOID_X509V1IssuerNameLDAP -_CSSM_UnwrapKey -_CSSMOID_X509V2CRLRevokedEntrySingleExtensionStruct -_CSSMOID_DNQualifier -_CSSMOID_SHA1WithRSA_OIW -_CSSMOID_ANSI_DH_HYBRID_ONEFLOW -_CSSM_CL_CrlCache -_CSSM_CL_CrlVerify -_CSSMOID_KERBv5_PKINIT_KP_CLIENT_AUTH -_CSSM_TP_CrlSign -_CSSMOID_ExtendedCertificateAttributes -_CSSM_DL_DataGetNext -_CSSMOID_UseExemptions -_CSSMOID_Surname -_CSSM_CSP_ObtainPrivateKeyFromPublicKey -_CSSMOID_ANSI_DH_EPHEM_SHA1 -_CSSMOID_BiometricInfo -_CSSMOID_ANSI_MQV1 -_CSSMOID_EnhancedSearchGuide -_CSSMOID_DeltaCrlIndicator -_CSSMOID_DSA_JDK -_CSSMOID_KnowledgeInformation -_CSSM_DL_ChangeDbOwner -_CSSMOID_NameConstraints -_CSSM_CL_CrlAbortQuery -_CSSMOID_UnstructuredName -_CSSMOID_UniqueMember -_CSSMOID_X509V1SerialNumber -_CSSMOID_SeeAlso -_CSSMOID_secp192r1 -_CSSMOID_X509V3SignedCertificateCStruct -_CSSMOID_DestinationIndicator -_CSSMOID_PKCS9_Id_Ct_TSTInfo -_CSSM_TP_CertGroupVerify -_CSSMOID_CollectiveOrganizationName -_CSSMOID_X509V2CRLAllExtensionsStruct -_CSSMOID_X9_62_FieldType -_CSSMOID_sect239k1 -_CSSM_EncryptDataInitP -_CSSM_Terminate -_CSSMOID_X509V3CertificateExtensionCStruct -_CSSMOID_APPLE_EKU_PROFILE_SIGNING -_CSSMOID_PKIX_OCSP -_CSSM_VerifyData -_CSSMOID_X509V2CRLSignedCrlCStruct -_CSSMOID_ADC_CERT_POLICY -_CSSMOID_DOTMAC_CERT_REQ_VALUE_IS_PENDING -_CSSM_DL_DestroyRelation -_CSSMOID_PKCS12_shroudedKeyBag -_CSSMOID_APPLE_FEE_MD5 -_CSSMOID_sect163k1 -_CSSMOID_X509V1Signature -_CSSMOID_KERBv5_PKINIT_KP_KDC -_CSSM_CL_CrlGetFirstFieldValue -_CSSMOID_APPLE_TP_LOCAL_CERT_GEN -_CSSM_VerifyMacInit -_CSSMOID_ANSI_DH_HYBRID2 -_CSSM_DigestData -_CSSMOID_X509V1SubjectNameLDAP -_CSSMOID_MicrosoftSGC -_CSSMOID_PKCS9_FriendlyName -_CSSM_FreeContext -_CSSM_WrapKey -_CSSMOID_PKCS9_X509Crl -_CSSMOID_X509V2CRLRevokedEntrySingleExtensionCStruct -_CSSM_VerifyMacUpdate -_CSSM_AC_AuthCompute -_CSSMOID_PKCS5_RC5_CBC -_CSSM_CL_CrlDescribeFormat -_CSSMOID_APPLE_EKU_CODE_SIGNING_DEV -_CSSMOID_DOTMAC_CERT_REQ_VALUE_ASYNC -_CSSM_TP_CertRemoveFromCrlTemplate -_CSSMOID_PKCS12_secretBag -_CSSMOID_CerticomEllCurve -_CSSMOID_ECDSA_WithSHA384 -_CSSMOID_SubjectSignatureBitmap -_CSSMOID_APPLE_EKU_RESOURCE_SIGNING -_CSSMOID_SerialNumber -_CSSMOID_APPLE_FEE_SHA1 -_CSSMOID_TelephoneNumber -_CSSMOID_SHA1WithDSA -_CSSM_DL_DataModify -_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_LIST -_CSSMOID_AliasedEntryName -_CSSMOID_APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING -_CSSM_CL_PassThrough -_CSSMOID_UserID -_CSSMOID_X509V3Certificate -_CSSMOID_PKIX_OCSP_BASIC -_CSSMOID_ECDSA_WithSHA224 -_CSSMOID_APPLE_TP_PKINIT_SERVER -_CSSM_CSP_GetOperationalStatistics -_CSSMOID_secp160k1 -_CSSMOID_sect193r2 -_CSSMOID_ANSI_DH_STATIC -_CSSMOID_MD5WithRSA -_CSSM_CL_CrlVerifyWithKey -_CSSMOID_sect283r1 -_CSSMOID_AuthorityInfoAccess -_CSSM_DL_ChangeDbAcl -_CSSMOID_PKCS5_pbeWithSHA1AndDES -_CSSMOID_EmailProtection -_CSSMOID_SHA1WithDSA_JDK -_CSSMOID_StateProvinceName -_CSSM_QuerySize -_CSSMOID_DH -_CSSMOID_sect409k1 -_CSSM_DL_DbClose -_CSSMOID_SigningTime -_CSSMOID_APPLE_EXTENSION_SERVER_AUTHENTICATION -_CSSMOID_IssuingDistributionPoints -_CSSMOID_secp384r1 -_CSSMOID_PKCS9_X509Certificate -_CSSM_CL_CertGroupToSignedBundle -_CSSMOID_LocalityName -_CSSMOID_CertificateRevocationList -_CSSMOID_APPLE_EXTENSION -_CSSM_CSP_CreateSignatureContext -_CSSMOID_PreferredDeliveryMethod -_CSSM_CL_CrlGetFirstCachedFieldValue -_CSSMOID_APPLE_TP_REVOCATION_CRL -_CSSMOID_QC_Statements -_CSSMOID_APPLE_ECDSA -_CSSM_DL_CreateRelation -_CSSMOID_PKCS5_PBKDF2 -_CSSMOID_ANSI_DH_HYBRID2_SHA1 -_CSSMOID_APPLEID_CERT_POLICY -_CSSMOID_APPLE_EXTENSION_APPLEID_INTERMEDIATE -_CSSM_DL_DataInsert -_CSSMOID_SHA1WithRSA -_CSSM_SignDataInit -_CSSMOID_PKCS9_CrlTypes -_CSSMOID_MOBILE_STORE_SIGNING_POLICY -_CSSMOID_SHA384 -_CSSMOID_X9_62_PrimeCurve -_CSSMOID_PKCS9_LocalKeyId -_CSSM_ModuleAttach -_CSSMOID_sect193r1 -_CSSM_DigestDataFinal -_CSSMOID_APPLE_EKU_QA_PROFILE_SIGNING -_CSSMOID_ExtendedUseCodeSigning -_CSSM_GetTimeValue -_CSSMOID_ECDSA_WithSHA512 -_CSSMOID_X509V1IssuerName -_CSSM_VerifyDataFinal -_CSSM_DL_FreeNameList -_CSSMOID_X509V1CRLRevokedEntryRevocationDate -_CSSM_TP_FormSubmit -_CSSM_CL_CertGetAllFields -_CSSMOID_MD2WithRSA -_CSSMOID_X509V1CRLNextUpdate -_CSSMOID_X509V1SubjectPublicKey -_CSSMOID_SHA512WithRSA -_CSSMOID_X509V1CRLIssuerNameCStruct -_CSSMOID_KERBv5_PKINIT_DH_KEY_DATA -_CSSMOID_PKCS7_EncryptedData -_CSSMOID_X509V1SubjectPublicKeyCStruct -_CSSMOID_RSAWithOAEP -_CSSMOID_APPLE_TP_REVOCATION_OCSP -_CSSM_ModuleUnload -_CSSMOID_PKCS5_PBMAC1 -_CSSMOID_X509V2CRLRevokedEntryExtensionCritical -_CSSM_CL_CertSign -_CSSMOID_AD_CA_REPOSITORY -_CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES -_CSSM_TP_CertGetAllTemplateFields -_CSSMOID_PKCS5_PBES2 -_CSSM_WrapKeyP -_CSSMOID_PKIX_OCSP_ARCHIVE_CUTOFF -_CSSMOID_OrganizationalUnitName -_CSSMOID_SearchGuide -_CSSMOID_NetscapeCertSequence -_CSSMOID_CollectiveFacsimileTelephoneNumber -_CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC -_CSSMOID_APPLE_EXTENSION_APPLE_SIGNING -_CSSMOID_X509V1CRLNumberOfRevokedCertEntries -_CSSMOID_APPLE_TP_EAP -_CSSM_DL_Authenticate -_CSSM_CL_CrlGetAllCachedRecordFields -_CSSMOID_ANSI_DH_HYBRID1 -_CSSM_CL_CertGetKeyInfo -_CSSMOID_TelexNumber -_CSSMOID_APPLE_TP_IP_SEC -_CSSMOID_SHA512 -_CSSM_TP_PassThrough -_CSSMOID_PKCS7_DigestedData -_CSSMOID_CollectivePostOfficeBox -_CSSM_TP_CrlCreateTemplate -_CSSMOID_ANSI_DH_ONE_FLOW -_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_FETCH -_CSSM_FreeKey -_CSSMOID_secp160r1 -_CSSMOID_KERBv5_PKINIT_AUTH_DATA -_CSSMOID_AD_TIME_STAMPING -_CSSMOID_DOTMAC_CERT_IDENTITY -_CSSMOID_Owner -_CSSMOID_ExtendedKeyUsage -_CSSMOID_ANSI_DH_PUB_NUMBER -_CSSMOID_SHA384WithRSA -_CSSMOID_PKCS5_DES_EDE3_CBC -_CSSMOID_X509V1SubjectName -_CSSMOID_PKCS7_EncryptedPrivateKeyInfo -_CSSMOID_APPLE_FEE -_CSSM_EncryptDataUpdate -_CSSMOID_SubjectEmailAddress -_CSSMOID_PKIX_OCSP_RESPONSE -_CSSMOID_DOTMAC_CERT_REQ -_CSSMOID_X509V1CRLRevokedCertificatesStruct -_CSSMOID_InternationalISDNNumber -_CSSMOID_GenerationQualifier -_CSSMOID_secp192k1 -_CSSMOID_APPLE_TP_PROFILE_SIGNING -_CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT -_CSSMOID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE -_CSSMOID_Name -_CSSMOID_Member -_CSSMOID_PKCS5_pbeWithMD2AndDES -_CSSM_DL_DataGetFirst -_CSSMOID_DOTMAC_CERT_EMAIL_SIGN -_CSSM_DL_GetDbAcl -_CSSM_EncryptData -_CSSMOID_X509V3CertificateExtensionType -_CSSMOID_SHA1WithDSA_CMS -_CSSMOID_APPLE_TP_CSR_GEN -_CSSMOID_DOTMAC_CERT -_CSSMOID_X509V1SubjectNameCStruct -_CSSM_TP_SubmitCredRequest -_CSSMOID_StreetAddress -_CSSM_DL_PassThrough -_CSSMOID_APPLE_EXTENSION_ADC_DEV_SIGNING -_CSSMOID_X509V1SignatureAlgorithmTBS -_CSSMOID_MACAPPSTORE_RECEIPT_CERT_POLICY -_CSSMOID_NetscapeSGC -_CSSMOID_APPLE_ISIGN -_CSSMOID_ContentType -_CSSM_CL_CertGetNextFieldValue -_CSSMOID_X509V2CRLTbsCertListCStruct -_CSSM_CL_CertAbortQuery -_CSSMOID_X509V1CertificateSubjectUniqueId -_CSSM_ModuleDetach -_CSSMOID_sect163r1 -_CSSMOID_ecPublicKey -_CSSMOID_PostOfficeBox -_CSSM_CSP_Login -_CSSMOID_APPLE_EXTENSION_CODE_SIGNING -_CSSM_QueryKeySizeInBits -_CSSMOID_APPLE_TP_SW_UPDATE_SIGNING -_CSSMOID_ObjectClass -_CSSM_CSP_CreateSymmetricContext -_CSSMOID_X9_62_EllCurve -_CSSMOID_APPLE_EXTENSION_ESCROW_SERVICE -_CSSMOID_APPLE_TP_RESOURCE_SIGN -_CSSMOID_ECDSA_WithSpecified -_CSSMOID_AD_OCSP -_CSSMOID_MD4 -_CSSMOID_X509V3SignedCertificate -_CSSMOID_DES_CBC -_CSSMOID_CollectiveOrganizationalUnitName -_CSSMOID_CollectivePhysicalDeliveryOfficeName -_CSSM_CL_CertVerifyWithKey -_CSSMOID_APPLE_ASC -_CSSMOID_secp160r2 -_CSSM_GenerateRandom -_CSSMOID_X509V1CRLRevokedEntryCStruct -_CSSMOID_APPLE_TP_MOBILE_STORE -_CSSMOID_Description -_CSSMOID_SHA1 -_CSSMOID_CollectiveTelephoneNumber -_CSSM_GetPrivilege -_CSSM_DL_DbCreate -_CSSMOID_X509V1CRLThisUpdate -_CSSMOID_APPLE_EXTENSION_MACAPPSTORE_RECEIPT -_CSSMOID_ETSI_QCS_QC_LIMIT_VALUE -_CSSMOID_OCSPSigning -_CSSM_CL_CertCreateTemplate -_CSSMOID_X509V1CRLRevokedCertificatesCStruct -_CSSM_VerifyDevice -_CSSM_ChangeKeyOwner -_CSSMOID_CrlDistributionPoints -_CSSMOID_X509V2CRLSingleExtensionCStruct -_CSSM_TP_CertSign -_CSSMOID_X509V1Version -_CSSM_EncryptDataInit -_CSSMOID_PKCS7_SignedData -_CSSM_TP_RetrieveCredResult -_CSSMOID_PKCS5_HMAC_SHA1 -_CSSM_EncryptDataP -_CSSMOID_PKCS5_pbeWithSHA1AndRC2 -_CSSM_TP_ConfirmCredResult -_CSSM_TP_ApplyCrlToDb -_CSSM_CL_CrlAbortCache -_CSSMOID_X509V1SubjectPublicKeyAlgorithmParameters -_CSSM_CL_CrlSetFields -_CSSMOID_PKCS12_safeContentsBag -_CSSMOID_ChallengePassword -_CSSMOID_QT_CPS -_CSSMOID_APPLE_TP_TIMESTAMPING -_CSSMOID_X509V2CRLRevokedEntryExtensionType -_CSSMOID_sect409r1 -_CSSMOID_X509V1SignatureCStruct -_CSSM_CSP_CreateMacContext -_CSSM_CL_CrlGetNextCachedFieldValue -_CSSMOID_CounterSignature -_CSSMOID_CollectiveStateProvinceName -_CSSM_EncryptDataFinal -_CSSMOID_NetscapeCertType -_CSSM_GetContext -_CSSM_CSP_Logout -_CSSM_DeleteContextAttributes -_CSSM_TP_CertGroupToTupleGroup -_CSSMOID_BusinessCategory -_CSSMOID_Certicom -_CSSMOID_APPLE_FEEDEXP -_CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4 -_CSSM_DL_GetDbNameFromHandle -_CSSMOID_sect163r2 -_CSSM_DeleteContext -_CSSMOID_sect283k1 -_CSSM_ListAttachedModuleManagers -_CSSM_CSP_ChangeLoginOwner -_CSSMOID_PostalCode -_CSSMOID_X509V3CertificateExtensionStruct -_CSSMOID_APPLE_EXTENSION_DEVELOPER_AUTHENTICATION -_CSSM_GetKeyOwner -_CSSMOID_X509V1ValidityNotBefore -_CSSM_CSP_CreateDeriveKeyContext -_CSSMOID_ETSI_QCS_QC_COMPLIANCE -_CSSMOID_APPLE_EKU_PASSBOOK_SIGNING -_CSSMOID_AuthorityKeyIdentifier -_CSSMOID_ANSI_DH_HYBRID1_SHA1 -_CSSM_UpdateContextAttributes -_CSSMOID_PKCS7_SignedAndEnvelopedData -_CSSMOID_X509V1IssuerNameCStruct -_CSSMOID_X9_62_SigType -_CSSM_CL_CrlAddCert -_CSSMOID_MessageDigest -_CSSMOID_RSA -_CSSMOID_X509V3CertificateExtensionValue -_CSSMOID_ETSI_QCS_QC_SSCD -_CSSM_TP_FormRequest -_CSSM_CL_CertGroupFromVerifiedBundle -_CSSMOID_X509V1CRLIssuerNameLDAP -_CSSMOID_X509V2CRLExtensionType -_CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD -_CSSMOID_APPLE_TP_APPLEID_SHARING -_CSSMOID_APPLE_EXTENSION_PASSBOOK_SIGNING -_CSSMOID_PKCS12_certBag -_CSSMOID_SubjectDirectoryAttributes -_CSSMOID_X509V2CRLRevokedEntryAllExtensionsStruct -_CSSM_SetPrivilege -_CSSMOID_SubjectAltName -_CSSMOID_ANSI_MQV2_SHA1 -_CSSMOID_X509V1SubjectNameStd -_CSSMOID_sect113r2 -_CSSM_ChangeKeyAcl -_CSSMOID_PKCS7_EnvelopedData -_CSSM_DL_GetDbOwner -_CSSMOID_PostalAddress -_CSSMOID_KERBv5_PKINIT_RKEY_DATA -_CSSM_CL_FreeFieldValue -_CSSMOID_CertIssuer -_CSSMOID_AuthorityRevocationList -_CSSMOID_SubjectKeyIdentifier -_CSSM_SignDataFinal -_CSSMOID_APPLE_EXTENSION_INTERMEDIATE_MARKER -_CSSM_CL_FreeFields -_CSSMOID_MACAPPSTORE_CERT_POLICY -_CSSMOID_KeyUsage -_CSSMOID_PKCS7_Data -_CSSMOID_PKCS7_DataWithAttributes -_CSSMOID_CollectivePostalAddress -_CSSMOID_PKCS9_SdsiCertificate -_CSSMOID_APPLE_TP_REVOCATION -_CSSMOID_AD_CA_ISSUERS -_CSSMOID_DOTMAC_CERT_REQ_VALUE_RENEW -_CSSMOID_MD4WithRSA -_CSSM_GenerateMacFinal -_CSSMOID_X509V1SignatureAlgorithmParameters -_CSSMOID_IssuingDistributionPoint -_CSSMOID_CollectiveStreetAddress -_CSSM_CL_CertGetFirstFieldValue -_CSSMOID_CertificatePolicies -_CSSMOID_X509V3CertificateExtensionsCStruct -_CSSMOID_secp112r1 -_CSSM_GenerateMacInit -_CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME -_CSSMOID_APPLE_TP_CODE_SIGN -_CSSMOID_APPLE_EXTENSION_WWDR_INTERMEDIATE -_CSSMOID_OAEP_ID_PSPECIFIED -_CSSM_DL_DataGetFromUniqueRecordId -_CSSMOID_DistinguishedName -_CSSMOID_EKU_IPSec -_CSSMOID_APPLE_TP_CODE_SIGNING -_CSSMOID_X9_62_PubKeyType -_CSSMOID_DomainComponent -_CSSM_GenerateAlgorithmParams -_CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN -_CSSM_GenerateKeyPairP -_CSSMOID_CollectiveInternationalISDNNumber -_CSSM_DecryptDataInitP -_CSSM_ModuleLoad -_CSSM_SetContext -_CSSMOID_APPLE_TP_SSL -_CSSMOID_OrganizationName -_CSSMOID_PKCS9_TimeStampToken -_CSSMOID_secp256k1 -_CSSMOID_X509V3CertificateExtensionId -_CSSM_DL_DataAbortQuery -_CSSMOID_X_121Address -_CSSM_TP_CertCreateTemplate -_CSSM_TP_CertRevoke -_CSSM_DL_DataDelete -_CSSMOID_PKCS5_RC2_CBC -_CSSMOID_PKIX_OCSP_SERVICE_LOCATOR -_CSSMOID_PKIX_OCSP_NONCE -_CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT -_CSSM_CL_CrlCreateTemplate -_CSSMOID_PKCS5_pbeWithMD2AndRC2 -_CSSMOID_ANSI_DH_STATIC_SHA1 -_CSSM_AC_PassThrough -_CSSM_CSP_PassThrough -_CSSMOID_PKCS5_pbeWithMD5AndRC2 -_CSSMOID_APPLE_TP_PASSBOOK_SIGNING -_CSSMOID_CSSMKeyStruct -_CSSMOID_BasicConstraints -_CSSM_SignData -_CSSMOID_X509V2CRLVersion -_CSSMOID_X509V1CertificateIssuerUniqueId -_CSSM_UnwrapKeyP -_CSSMOID_SHA224 -_CSSM_CSP_CreateDigestContext -_CSSM_DL_FreeUniqueRecord -_CSSMOID_HoldInstructionCode -_CSSMOID_X509V1CRLRevokedEntryStruct -_CSSMOID_X509V2CRLRevokedEntryNumberOfExtensions -_CSSMOID_X509V1ValidityNotAfter -_CSSMOID_sect113r1 -_CSSM_CSP_GetLoginOwner -_CSSMOID_X509V2CRLRevokedEntryAllExtensionsCStruct -_CSSMOID_X509V1SignatureAlgorithm -_CSSMOID_secp521r1 -_CSSMOID_X509V2CRLSingleExtensionStruct -_CSSMOID_APPLE_EXTENSION_ITMS_INTERMEDIATE -_CSSMOID_PDA_COUNTRY_CITIZEN -_CSSMOID_PolicyMappings -_CSSM_GenerateMac -_CSSM_CL_CrlSign -_CSSMOID_ANSI_MQV1_SHA1 -_CSSMOID_X509V2CRLRevokedEntryExtensionValue -_CSSM_GetSubserviceUIDFromHandle -_CSSMOID_ANSI_DH_EPHEM -_CSSM_VerifyDataInit -_CSSMOID_X509V2CRLNumberOfExtensions -_CSSMOID_APPLE_TP_QA_PROFILE_SIGNING -_CSSMOID_PKCS9_CertTypes -_CSSM_CL_CertGetNextCachedFieldValue -_CSSM_TP_CrlVerify -_CSSM_VerifyMacFinal -_CSSM_DigestDataInit -_CSSMOID_PresentationAddress -_CSSMOID_APPLE_TP_PKINIT_CLIENT -_CSSMOID_DOTMAC_CERT_REQ_IDENTITY -_CSSM_CSP_CreateKeyGenContext -_CSSM_CL_CertAbortCache -_CSSM_GenerateMacUpdate -_CSSMOID_SHA256 -_CSSM_TP_CertReclaimAbort -_CSSMOID_secp224k1 -_CSSMOID_ExtendedKeyUsageAny -_CSSMOID_UserCertificate -_CSSMOID_OID_QCS_SYNTAX_V1 -_CSSM_RetrieveCounter -_CSSMOID_APPLE_TP_PACKAGE_SIGNING -_CSSM_GetAPIMemoryFunctions -_CSSM_DigestDataUpdate -_CSSM_CSP_CreateAsymmetricContext -_CSSMOID_X509V1CRLIssuerStruct -_CSSMOID_EmailAddress -_CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4 -_CSSMOID_RoleOccupant -_CSSMOID_CrlNumber -_CSSM_CL_CertDescribeFormat -_CSSMOID_sect233k1 -_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE -_CSSMOID_secp112r2 -_CSSMOID_ETSI_QCS_QC_RETENTION -_CSSMOID_Title -_CSSM_VerifyDataUpdate -_CSSM_Unintroduce -_CSSMOID_X509V2CRLAllExtensionsCStruct -_CSSMOID_sect571k1 -_CSSMOID_PKCS5_ENCRYPT_ALG diff --git a/derived_src/funcnames.gen b/derived_src/funcnames.gen deleted file mode 100644 index f0989d3d..00000000 --- a/derived_src/funcnames.gen +++ /dev/null @@ -1,163 +0,0 @@ -// -// Standard plugin name tables -// This file was automatically generated. Do not edit on penalty of futility! -// -extern const char *const CLNameTable[] = { - "CertCreateTemplate", - "CertGetAllTemplateFields", - "CertSign", - "CertVerify", - "CertVerifyWithKey", - "CertGetFirstFieldValue", - "CertGetNextFieldValue", - "CertAbortQuery", - "CertGetKeyInfo", - "CertGetAllFields", - "FreeFields", - "FreeFieldValue", - "CertCache", - "CertGetFirstCachedFieldValue", - "CertGetNextCachedFieldValue", - "CertAbortCache", - "CertGroupToSignedBundle", - "CertGroupFromVerifiedBundle", - "CertDescribeFormat", - "CrlCreateTemplate", - "CrlSetFields", - "CrlAddCert", - "CrlRemoveCert", - "CrlSign", - "CrlVerify", - "CrlVerifyWithKey", - "IsCertInCrl", - "CrlGetFirstFieldValue", - "CrlGetNextFieldValue", - "CrlAbortQuery", - "CrlGetAllFields", - "CrlCache", - "IsCertInCachedCrl", - "CrlGetFirstCachedFieldValue", - "CrlGetNextCachedFieldValue", - "CrlGetAllCachedRecordFields", - "CrlAbortCache", - "CrlDescribeFormat", - "PassThrough", -}; - -extern const char *const DLNameTable[] = { - "DbOpen", - "DbClose", - "DbCreate", - "DbDelete", - "CreateRelation", - "DestroyRelation", - "Authenticate", - "GetDbAcl", - "ChangeDbAcl", - "GetDbOwner", - "ChangeDbOwner", - "GetDbNames", - "GetDbNameFromHandle", - "FreeNameList", - "DataInsert", - "DataDelete", - "DataModify", - "DataGetFirst", - "DataGetNext", - "DataAbortQuery", - "DataGetFromUniqueRecordId", - "FreeUniqueRecord", - "PassThrough", -}; - -extern const char *const CSPNameTable[] = { - "EventNotify", - "QuerySize", - "SignData", - "SignDataInit", - "SignDataUpdate", - "SignDataFinal", - "VerifyData", - "VerifyDataInit", - "VerifyDataUpdate", - "VerifyDataFinal", - "DigestData", - "DigestDataInit", - "DigestDataUpdate", - "DigestDataClone", - "DigestDataFinal", - "GenerateMac", - "GenerateMacInit", - "GenerateMacUpdate", - "GenerateMacFinal", - "VerifyMac", - "VerifyMacInit", - "VerifyMacUpdate", - "VerifyMacFinal", - "EncryptData", - "EncryptDataInit", - "EncryptDataUpdate", - "EncryptDataFinal", - "DecryptData", - "DecryptDataInit", - "DecryptDataUpdate", - "DecryptDataFinal", - "QueryKeySizeInBits", - "GenerateKey", - "GenerateKeyPair", - "GenerateRandom", - "GenerateAlgorithmParams", - "WrapKey", - "UnwrapKey", - "DeriveKey", - "FreeKey", - "PassThrough", - "Login", - "Logout", - "ChangeLoginAcl", - "ObtainPrivateKeyFromPublicKey", - "RetrieveUniqueId", - "RetrieveCounter", - "VerifyDevice", - "GetTimeValue", - "GetOperationalStatistics", - "GetLoginAcl", - "GetKeyAcl", - "ChangeKeyAcl", - "GetKeyOwner", - "ChangeKeyOwner", - "GetLoginOwner", - "ChangeLoginOwner", -}; - -extern const char *const TPNameTable[] = { - "SubmitCredRequest", - "RetrieveCredResult", - "ConfirmCredResult", - "ReceiveConfirmation", - "CertReclaimKey", - "CertReclaimAbort", - "FormRequest", - "FormSubmit", - "CertGroupVerify", - "CertCreateTemplate", - "CertGetAllTemplateFields", - "CertSign", - "CrlVerify", - "CrlCreateTemplate", - "CertRevoke", - "CertRemoveFromCrlTemplate", - "CrlSign", - "ApplyCrlToDb", - "CertGroupConstruct", - "CertGroupPrune", - "CertGroupToTupleGroup", - "TupleGroupToCertGroup", - "PassThrough", -}; - -extern const char *const ACNameTable[] = { - "AuthCompute", - "PassThrough", -}; - diff --git a/derived_src/generator.rpt b/derived_src/generator.rpt deleted file mode 100644 index 445e1d8f..00000000 --- a/derived_src/generator.rpt +++ /dev/null @@ -1,33 +0,0 @@ -CSSM_CSP_CreateAsymmetricContext not in cssmcspi.h -CSSM_CSP_CreateDeriveKeyContext not in cssmcspi.h -CSSM_CSP_CreateDigestContext not in cssmcspi.h -CSSM_CSP_CreateKeyGenContext not in cssmcspi.h -CSSM_CSP_CreateMacContext not in cssmcspi.h -CSSM_CSP_CreatePassThroughContext not in cssmcspi.h -CSSM_CSP_CreateRandomGenContext not in cssmcspi.h -CSSM_CSP_CreateSignatureContext not in cssmcspi.h -CSSM_CSP_CreateSymmetricContext not in cssmcspi.h -CSSM_DeleteContext not in cssmcspi.h -CSSM_DeleteContextAttributes not in cssmcspi.h -CSSM_DigestDataClone has custom implementation -CSSM_FreeContext has no module type -CSSM_GenerateAlgorithmParams has custom implementation -CSSM_GetAPIMemoryFunctions has no module type -CSSM_GetContext not in cssmcspi.h -CSSM_GetContextAttribute has no module type -CSSM_GetModuleGUIDFromHandle has no module type -CSSM_GetPrivilege has no module type -CSSM_GetSubserviceUIDFromHandle has no module type -CSSM_Init has no module type -CSSM_Introduce has no module type -CSSM_ListAttachedModuleManagers has no module type -CSSM_ModuleAttach has no module type -CSSM_ModuleDetach has no module type -CSSM_ModuleLoad has no module type -CSSM_ModuleUnload has no module type -CSSM_QueryKeySizeInBits has custom implementation -CSSM_SetContext not in cssmcspi.h -CSSM_SetPrivilege has no module type -CSSM_Terminate has no module type -CSSM_Unintroduce has no module type -CSSM_UpdateContextAttributes not in cssmcspi.h diff --git a/derived_src/transition.gen b/derived_src/transition.gen deleted file mode 100644 index 036f6686..00000000 --- a/derived_src/transition.gen +++ /dev/null @@ -1,2510 +0,0 @@ -// -// This file was automatically generated. Do not edit on penalty of futility! -// -CSSM_RETURN CSSMAPI -CSSM_AC_AuthCompute (CSSM_AC_HANDLE ACHandle, - const CSSM_TUPLEGROUP *BaseAuthorizations, - const CSSM_TUPLEGROUP *Credentials, - uint32 NumberOfRequestors, - const CSSM_LIST *Requestors, - const CSSM_LIST *RequestedAuthorizationPeriod, - const CSSM_LIST *RequestedAuthorization, - CSSM_TUPLEGROUP_PTR AuthorizationResult) -{ - BEGIN_API - ACAttachment &attachment = enterAttachment(ACHandle); - TransitLock _(attachment); - return attachment.downcalls.AuthCompute(ACHandle, - BaseAuthorizations, - Credentials, - NumberOfRequestors, - Requestors, - RequestedAuthorizationPeriod, - RequestedAuthorization, - AuthorizationResult); - END_API(AC) -} - -CSSM_RETURN CSSMAPI -CSSM_AC_PassThrough (CSSM_AC_HANDLE ACHandle, - CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DL_DB_LIST *DBList, - uint32 PassThroughId, - const void *InputParams, - void **OutputParams) -{ - BEGIN_API - ACAttachment &attachment = enterAttachment(ACHandle); - TransitLock _(attachment); - return attachment.downcalls.PassThrough(ACHandle, - TPHandle, - CLHandle, - CCHandle, - DBList, - PassThroughId, - InputParams, - OutputParams); - END_API(AC) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertAbortCache (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE CertHandle) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertAbortCache(CLHandle, - CertHandle); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertAbortQuery (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE ResultsHandle) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertAbortQuery(CLHandle, - ResultsHandle); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertCache (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Cert, - CSSM_HANDLE_PTR CertHandle) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertCache(CLHandle, - Cert, - CertHandle); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertCreateTemplate (CSSM_CL_HANDLE CLHandle, - uint32 NumberOfFields, - const CSSM_FIELD *CertFields, - CSSM_DATA_PTR CertTemplate) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertCreateTemplate(CLHandle, - NumberOfFields, - CertFields, - CertTemplate); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertDescribeFormat (CSSM_CL_HANDLE CLHandle, - uint32 *NumberOfFields, - CSSM_OID_PTR *OidList) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertDescribeFormat(CLHandle, - NumberOfFields, - OidList); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertGetAllFields (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Cert, - uint32 *NumberOfFields, - CSSM_FIELD_PTR *CertFields) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGetAllFields(CLHandle, - Cert, - NumberOfFields, - CertFields); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertGetAllTemplateFields (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *CertTemplate, - uint32 *NumberOfFields, - CSSM_FIELD_PTR *CertFields) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGetAllTemplateFields(CLHandle, - CertTemplate, - NumberOfFields, - CertFields); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertGetFirstCachedFieldValue (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE CertHandle, - const CSSM_OID *CertField, - CSSM_HANDLE_PTR ResultsHandle, - uint32 *NumberOfMatchedFields, - CSSM_DATA_PTR *Value) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGetFirstCachedFieldValue(CLHandle, - CertHandle, - CertField, - ResultsHandle, - NumberOfMatchedFields, - Value); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertGetFirstFieldValue (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Cert, - const CSSM_OID *CertField, - CSSM_HANDLE_PTR ResultsHandle, - uint32 *NumberOfMatchedFields, - CSSM_DATA_PTR *Value) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGetFirstFieldValue(CLHandle, - Cert, - CertField, - ResultsHandle, - NumberOfMatchedFields, - Value); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertGetKeyInfo (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Cert, - CSSM_KEY_PTR *Key) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGetKeyInfo(CLHandle, - Cert, - Key); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertGetNextCachedFieldValue (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE ResultsHandle, - CSSM_DATA_PTR *Value) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGetNextCachedFieldValue(CLHandle, - ResultsHandle, - Value); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertGetNextFieldValue (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE ResultsHandle, - CSSM_DATA_PTR *Value) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGetNextFieldValue(CLHandle, - ResultsHandle, - Value); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertGroupFromVerifiedBundle (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_CERT_BUNDLE *CertBundle, - const CSSM_DATA *SignerCert, - CSSM_CERTGROUP_PTR *CertGroup) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGroupFromVerifiedBundle(CLHandle, - CCHandle, - CertBundle, - SignerCert, - CertGroup); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertGroupToSignedBundle (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_CERTGROUP *CertGroupToBundle, - const CSSM_CERT_BUNDLE_HEADER *BundleInfo, - CSSM_DATA_PTR SignedBundle) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGroupToSignedBundle(CLHandle, - CCHandle, - CertGroupToBundle, - BundleInfo, - SignedBundle); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertSign (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *CertTemplate, - const CSSM_FIELD *SignScope, - uint32 ScopeSize, - CSSM_DATA_PTR SignedCert) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertSign(CLHandle, - CCHandle, - CertTemplate, - SignScope, - ScopeSize, - SignedCert); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertVerify (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *CertToBeVerified, - const CSSM_DATA *SignerCert, - const CSSM_FIELD *VerifyScope, - uint32 ScopeSize) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertVerify(CLHandle, - CCHandle, - CertToBeVerified, - SignerCert, - VerifyScope, - ScopeSize); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CertVerifyWithKey (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *CertToBeVerified) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CertVerifyWithKey(CLHandle, - CCHandle, - CertToBeVerified); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlAbortCache (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE CrlHandle) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlAbortCache(CLHandle, - CrlHandle); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlAbortQuery (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE ResultsHandle) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlAbortQuery(CLHandle, - ResultsHandle); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlAddCert (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *Cert, - uint32 NumberOfFields, - const CSSM_FIELD *CrlEntryFields, - const CSSM_DATA *OldCrl, - CSSM_DATA_PTR NewCrl) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlAddCert(CLHandle, - CCHandle, - Cert, - NumberOfFields, - CrlEntryFields, - OldCrl, - NewCrl); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlCache (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Crl, - CSSM_HANDLE_PTR CrlHandle) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlCache(CLHandle, - Crl, - CrlHandle); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlCreateTemplate (CSSM_CL_HANDLE CLHandle, - uint32 NumberOfFields, - const CSSM_FIELD *CrlTemplate, - CSSM_DATA_PTR NewCrl) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlCreateTemplate(CLHandle, - NumberOfFields, - CrlTemplate, - NewCrl); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlDescribeFormat (CSSM_CL_HANDLE CLHandle, - uint32 *NumberOfFields, - CSSM_OID_PTR *OidList) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlDescribeFormat(CLHandle, - NumberOfFields, - OidList); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlGetAllCachedRecordFields (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE CrlHandle, - const CSSM_DATA *CrlRecordIndex, - uint32 *NumberOfFields, - CSSM_FIELD_PTR *CrlFields) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlGetAllCachedRecordFields(CLHandle, - CrlHandle, - CrlRecordIndex, - NumberOfFields, - CrlFields); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlGetAllFields (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Crl, - uint32 *NumberOfCrlFields, - CSSM_FIELD_PTR *CrlFields) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlGetAllFields(CLHandle, - Crl, - NumberOfCrlFields, - CrlFields); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlGetFirstCachedFieldValue (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE CrlHandle, - const CSSM_DATA *CrlRecordIndex, - const CSSM_OID *CrlField, - CSSM_HANDLE_PTR ResultsHandle, - uint32 *NumberOfMatchedFields, - CSSM_DATA_PTR *Value) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlGetFirstCachedFieldValue(CLHandle, - CrlHandle, - CrlRecordIndex, - CrlField, - ResultsHandle, - NumberOfMatchedFields, - Value); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlGetFirstFieldValue (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Crl, - const CSSM_OID *CrlField, - CSSM_HANDLE_PTR ResultsHandle, - uint32 *NumberOfMatchedFields, - CSSM_DATA_PTR *Value) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlGetFirstFieldValue(CLHandle, - Crl, - CrlField, - ResultsHandle, - NumberOfMatchedFields, - Value); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlGetNextCachedFieldValue (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE ResultsHandle, - CSSM_DATA_PTR *Value) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlGetNextCachedFieldValue(CLHandle, - ResultsHandle, - Value); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlGetNextFieldValue (CSSM_CL_HANDLE CLHandle, - CSSM_HANDLE ResultsHandle, - CSSM_DATA_PTR *Value) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlGetNextFieldValue(CLHandle, - ResultsHandle, - Value); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlRemoveCert (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Cert, - const CSSM_DATA *OldCrl, - CSSM_DATA_PTR NewCrl) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlRemoveCert(CLHandle, - Cert, - OldCrl, - NewCrl); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlSetFields (CSSM_CL_HANDLE CLHandle, - uint32 NumberOfFields, - const CSSM_FIELD *CrlTemplate, - const CSSM_DATA *OldCrl, - CSSM_DATA_PTR ModifiedCrl) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlSetFields(CLHandle, - NumberOfFields, - CrlTemplate, - OldCrl, - ModifiedCrl); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlSign (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *UnsignedCrl, - const CSSM_FIELD *SignScope, - uint32 ScopeSize, - CSSM_DATA_PTR SignedCrl) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlSign(CLHandle, - CCHandle, - UnsignedCrl, - SignScope, - ScopeSize, - SignedCrl); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlVerify (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *CrlToBeVerified, - const CSSM_DATA *SignerCert, - const CSSM_FIELD *VerifyScope, - uint32 ScopeSize) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlVerify(CLHandle, - CCHandle, - CrlToBeVerified, - SignerCert, - VerifyScope, - ScopeSize); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_CrlVerifyWithKey (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *CrlToBeVerified) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlVerifyWithKey(CLHandle, - CCHandle, - CrlToBeVerified); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_FreeFieldValue (CSSM_CL_HANDLE CLHandle, - const CSSM_OID *CertOrCrlOid, - CSSM_DATA_PTR Value) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.FreeFieldValue(CLHandle, - CertOrCrlOid, - Value); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_FreeFields (CSSM_CL_HANDLE CLHandle, - uint32 NumberOfFields, - CSSM_FIELD_PTR *Fields) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.FreeFields(CLHandle, - NumberOfFields, - Fields); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_IsCertInCachedCrl (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Cert, - CSSM_HANDLE CrlHandle, - CSSM_BOOL *CertFound, - CSSM_DATA_PTR CrlRecordIndex) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.IsCertInCachedCrl(CLHandle, - Cert, - CrlHandle, - CertFound, - CrlRecordIndex); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_IsCertInCrl (CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *Cert, - const CSSM_DATA *Crl, - CSSM_BOOL *CertFound) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.IsCertInCrl(CLHandle, - Cert, - Crl, - CertFound); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CL_PassThrough (CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - uint32 PassThroughId, - const void *InputParams, - void **OutputParams) -{ - BEGIN_API - CLAttachment &attachment = enterAttachment(CLHandle); - TransitLock _(attachment); - return attachment.downcalls.PassThrough(CLHandle, - CCHandle, - PassThroughId, - InputParams, - OutputParams); - END_API(CL) -} - -CSSM_RETURN CSSMAPI -CSSM_CSP_ChangeLoginAcl (CSSM_CSP_HANDLE CSPHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_ACL_EDIT *AclEdit) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.ChangeLoginAcl(CSPHandle, - AccessCred, - AclEdit); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_CSP_ChangeLoginOwner (CSSM_CSP_HANDLE CSPHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_ACL_OWNER_PROTOTYPE *NewOwner) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.ChangeLoginOwner(CSPHandle, - AccessCred, - NewOwner); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_CSP_GetLoginAcl (CSSM_CSP_HANDLE CSPHandle, - const CSSM_STRING *SelectionTag, - uint32 *NumberOfAclInfos, - CSSM_ACL_ENTRY_INFO_PTR *AclInfos) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.GetLoginAcl(CSPHandle, - SelectionTag, - NumberOfAclInfos, - AclInfos); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_CSP_GetLoginOwner (CSSM_CSP_HANDLE CSPHandle, - CSSM_ACL_OWNER_PROTOTYPE_PTR Owner) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.GetLoginOwner(CSPHandle, - Owner); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_CSP_GetOperationalStatistics (CSSM_CSP_HANDLE CSPHandle, - CSSM_CSP_OPERATIONAL_STATISTICS *Statistics) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.GetOperationalStatistics(CSPHandle, - Statistics); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_CSP_Login (CSSM_CSP_HANDLE CSPHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_DATA *LoginName, - const void *Reserved) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.Login(CSPHandle, - AccessCred, - LoginName, - Reserved); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_CSP_Logout (CSSM_CSP_HANDLE CSPHandle) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.Logout(CSPHandle); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_CSP_ObtainPrivateKeyFromPublicKey (CSSM_CSP_HANDLE CSPHandle, - const CSSM_KEY *PublicKey, - CSSM_KEY_PTR PrivateKey) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.ObtainPrivateKeyFromPublicKey(CSPHandle, - PublicKey, - PrivateKey); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_CSP_PassThrough (CSSM_CC_HANDLE CCHandle, - uint32 PassThroughId, - const void *InData, - void **OutData) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.PassThrough(context.CSPHandle, CCHandle, &context, - PassThroughId, - InData, - OutData); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_ChangeKeyAcl (CSSM_CSP_HANDLE CSPHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_ACL_EDIT *AclEdit, - const CSSM_KEY *Key) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.ChangeKeyAcl(CSPHandle, - AccessCred, - AclEdit, - Key); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_ChangeKeyOwner (CSSM_CSP_HANDLE CSPHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_KEY *Key, - const CSSM_ACL_OWNER_PROTOTYPE *NewOwner) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.ChangeKeyOwner(CSPHandle, - AccessCred, - Key, - NewOwner); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_Authenticate (CSSM_DL_DB_HANDLE DLDBHandle, - CSSM_DB_ACCESS_TYPE AccessRequest, - const CSSM_ACCESS_CREDENTIALS *AccessCred) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.Authenticate(DLDBHandle, - AccessRequest, - AccessCred); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_ChangeDbAcl (CSSM_DL_DB_HANDLE DLDBHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_ACL_EDIT *AclEdit) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.ChangeDbAcl(DLDBHandle, - AccessCred, - AclEdit); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_ChangeDbOwner (CSSM_DL_DB_HANDLE DLDBHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_ACL_OWNER_PROTOTYPE *NewOwner) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.ChangeDbOwner(DLDBHandle, - AccessCred, - NewOwner); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_CreateRelation (CSSM_DL_DB_HANDLE DLDBHandle, - CSSM_DB_RECORDTYPE RelationID, - const char *RelationName, - uint32 NumberOfAttributes, - const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, - uint32 NumberOfIndexes, - const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.CreateRelation(DLDBHandle, - RelationID, - RelationName, - NumberOfAttributes, - pAttributeInfo, - NumberOfIndexes, - pIndexInfo); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DataAbortQuery (CSSM_DL_DB_HANDLE DLDBHandle, - CSSM_HANDLE ResultsHandle) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DataAbortQuery(DLDBHandle, - ResultsHandle); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DataDelete (CSSM_DL_DB_HANDLE DLDBHandle, - const CSSM_DB_UNIQUE_RECORD *UniqueRecordIdentifier) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DataDelete(DLDBHandle, - UniqueRecordIdentifier); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DataGetFirst (CSSM_DL_DB_HANDLE DLDBHandle, - const CSSM_QUERY *Query, - CSSM_HANDLE_PTR ResultsHandle, - CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, - CSSM_DATA_PTR Data, - CSSM_DB_UNIQUE_RECORD_PTR *UniqueId) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DataGetFirst(DLDBHandle, - Query, - ResultsHandle, - Attributes, - Data, - UniqueId); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DataGetFromUniqueRecordId (CSSM_DL_DB_HANDLE DLDBHandle, - const CSSM_DB_UNIQUE_RECORD *UniqueRecord, - CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, - CSSM_DATA_PTR Data) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DataGetFromUniqueRecordId(DLDBHandle, - UniqueRecord, - Attributes, - Data); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DataGetNext (CSSM_DL_DB_HANDLE DLDBHandle, - CSSM_HANDLE ResultsHandle, - CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, - CSSM_DATA_PTR Data, - CSSM_DB_UNIQUE_RECORD_PTR *UniqueId) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DataGetNext(DLDBHandle, - ResultsHandle, - Attributes, - Data, - UniqueId); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DataInsert (CSSM_DL_DB_HANDLE DLDBHandle, - CSSM_DB_RECORDTYPE RecordType, - const CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, - const CSSM_DATA *Data, - CSSM_DB_UNIQUE_RECORD_PTR *UniqueId) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DataInsert(DLDBHandle, - RecordType, - Attributes, - Data, - UniqueId); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DataModify (CSSM_DL_DB_HANDLE DLDBHandle, - CSSM_DB_RECORDTYPE RecordType, - CSSM_DB_UNIQUE_RECORD_PTR UniqueRecordIdentifier, - const CSSM_DB_RECORD_ATTRIBUTE_DATA *AttributesToBeModified, - const CSSM_DATA *DataToBeModified, - CSSM_DB_MODIFY_MODE ModifyMode) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DataModify(DLDBHandle, - RecordType, - UniqueRecordIdentifier, - AttributesToBeModified, - DataToBeModified, - ModifyMode); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DbClose (CSSM_DL_DB_HANDLE DLDBHandle) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DbClose(DLDBHandle); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DbCreate (CSSM_DL_HANDLE DLHandle, - const char *DbName, - const CSSM_NET_ADDRESS *DbLocation, - const CSSM_DBINFO *DBInfo, - CSSM_DB_ACCESS_TYPE AccessRequest, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - const void *OpenParameters, - CSSM_DB_HANDLE *DbHandle) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DbCreate(DLHandle, - DbName, - DbLocation, - DBInfo, - AccessRequest, - CredAndAclEntry, - OpenParameters, - DbHandle); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DbDelete (CSSM_DL_HANDLE DLHandle, - const char *DbName, - const CSSM_NET_ADDRESS *DbLocation, - const CSSM_ACCESS_CREDENTIALS *AccessCred) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DbDelete(DLHandle, - DbName, - DbLocation, - AccessCred); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DbOpen (CSSM_DL_HANDLE DLHandle, - const char *DbName, - const CSSM_NET_ADDRESS *DbLocation, - CSSM_DB_ACCESS_TYPE AccessRequest, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const void *OpenParameters, - CSSM_DB_HANDLE *DbHandle) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DbOpen(DLHandle, - DbName, - DbLocation, - AccessRequest, - AccessCred, - OpenParameters, - DbHandle); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_DestroyRelation (CSSM_DL_DB_HANDLE DLDBHandle, - CSSM_DB_RECORDTYPE RelationID) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.DestroyRelation(DLDBHandle, - RelationID); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_FreeNameList (CSSM_DL_HANDLE DLHandle, - CSSM_NAME_LIST_PTR NameList) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLHandle); - TransitLock _(attachment); - return attachment.downcalls.FreeNameList(DLHandle, - NameList); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_FreeUniqueRecord (CSSM_DL_DB_HANDLE DLDBHandle, - CSSM_DB_UNIQUE_RECORD_PTR UniqueRecord) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.FreeUniqueRecord(DLDBHandle, - UniqueRecord); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_GetDbAcl (CSSM_DL_DB_HANDLE DLDBHandle, - const CSSM_STRING *SelectionTag, - uint32 *NumberOfAclInfos, - CSSM_ACL_ENTRY_INFO_PTR *AclInfos) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.GetDbAcl(DLDBHandle, - SelectionTag, - NumberOfAclInfos, - AclInfos); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_GetDbNameFromHandle (CSSM_DL_DB_HANDLE DLDBHandle, - char **DbName) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.GetDbNameFromHandle(DLDBHandle, - DbName); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_GetDbNames (CSSM_DL_HANDLE DLHandle, - CSSM_NAME_LIST_PTR *NameList) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLHandle); - TransitLock _(attachment); - return attachment.downcalls.GetDbNames(DLHandle, - NameList); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_GetDbOwner (CSSM_DL_DB_HANDLE DLDBHandle, - CSSM_ACL_OWNER_PROTOTYPE_PTR Owner) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.GetDbOwner(DLDBHandle, - Owner); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DL_PassThrough (CSSM_DL_DB_HANDLE DLDBHandle, - uint32 PassThroughId, - const void *InputParams, - void **OutputParams) -{ - BEGIN_API - DLAttachment &attachment = enterAttachment(DLDBHandle.DLHandle); - TransitLock _(attachment); - return attachment.downcalls.PassThrough(DLDBHandle, - PassThroughId, - InputParams, - OutputParams); - END_API(DL) -} - -CSSM_RETURN CSSMAPI -CSSM_DecryptData (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *CipherBufs, - uint32 CipherBufCount, - CSSM_DATA_PTR ClearBufs, - uint32 ClearBufCount, - CSSM_SIZE *bytesDecrypted, - CSSM_DATA_PTR RemData) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DecryptData(context.CSPHandle, CCHandle, &context, - CipherBufs, - CipherBufCount, - ClearBufs, - ClearBufCount, - bytesDecrypted, - RemData, - attachment.module.cssm.getPrivilege()); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DecryptDataFinal (CSSM_CC_HANDLE CCHandle, - CSSM_DATA_PTR RemData) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DecryptDataFinal(context.CSPHandle, CCHandle, - RemData); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DecryptDataInit (CSSM_CC_HANDLE CCHandle) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DecryptDataInit(context.CSPHandle, CCHandle, &context, - attachment.module.cssm.getPrivilege()); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DecryptDataInitP (CSSM_CC_HANDLE CCHandle, - CSSM_PRIVILEGE Privilege) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DecryptDataInit(context.CSPHandle, CCHandle, &context, - Privilege); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DecryptDataP (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *CipherBufs, - uint32 CipherBufCount, - CSSM_DATA_PTR ClearBufs, - uint32 ClearBufCount, - CSSM_SIZE *bytesDecrypted, - CSSM_DATA_PTR RemData, - CSSM_PRIVILEGE Privilege) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DecryptData(context.CSPHandle, CCHandle, &context, - CipherBufs, - CipherBufCount, - ClearBufs, - ClearBufCount, - bytesDecrypted, - RemData, - Privilege); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DecryptDataUpdate (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *CipherBufs, - uint32 CipherBufCount, - CSSM_DATA_PTR ClearBufs, - uint32 ClearBufCount, - CSSM_SIZE *bytesDecrypted) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DecryptDataUpdate(context.CSPHandle, CCHandle, - CipherBufs, - CipherBufCount, - ClearBufs, - ClearBufCount, - bytesDecrypted); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DeriveKey (CSSM_CC_HANDLE CCHandle, - CSSM_DATA_PTR Param, - uint32 KeyUsage, - uint32 KeyAttr, - const CSSM_DATA *KeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CSSM_KEY_PTR DerivedKey) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DeriveKey(context.CSPHandle, CCHandle, &context, - Param, - KeyUsage, - KeyAttr, - KeyLabel, - CredAndAclEntry, - DerivedKey); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DigestData (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount, - CSSM_DATA_PTR Digest) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DigestData(context.CSPHandle, CCHandle, &context, - DataBufs, - DataBufCount, - Digest); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DigestDataFinal (CSSM_CC_HANDLE CCHandle, - CSSM_DATA_PTR Digest) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DigestDataFinal(context.CSPHandle, CCHandle, - Digest); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DigestDataInit (CSSM_CC_HANDLE CCHandle) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DigestDataInit(context.CSPHandle, CCHandle, &context); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_DigestDataUpdate (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.DigestDataUpdate(context.CSPHandle, CCHandle, - DataBufs, - DataBufCount); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_EncryptData (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *ClearBufs, - uint32 ClearBufCount, - CSSM_DATA_PTR CipherBufs, - uint32 CipherBufCount, - CSSM_SIZE *bytesEncrypted, - CSSM_DATA_PTR RemData) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.EncryptData(context.CSPHandle, CCHandle, &context, - ClearBufs, - ClearBufCount, - CipherBufs, - CipherBufCount, - bytesEncrypted, - RemData, - attachment.module.cssm.getPrivilege()); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_EncryptDataFinal (CSSM_CC_HANDLE CCHandle, - CSSM_DATA_PTR RemData) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.EncryptDataFinal(context.CSPHandle, CCHandle, - RemData); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_EncryptDataInit (CSSM_CC_HANDLE CCHandle) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.EncryptDataInit(context.CSPHandle, CCHandle, &context, - attachment.module.cssm.getPrivilege()); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_EncryptDataInitP (CSSM_CC_HANDLE CCHandle, - CSSM_PRIVILEGE Privilege) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.EncryptDataInit(context.CSPHandle, CCHandle, &context, - Privilege); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_EncryptDataP (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *ClearBufs, - uint32 ClearBufCount, - CSSM_DATA_PTR CipherBufs, - uint32 CipherBufCount, - CSSM_SIZE *bytesEncrypted, - CSSM_DATA_PTR RemData, - CSSM_PRIVILEGE Privilege) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.EncryptData(context.CSPHandle, CCHandle, &context, - ClearBufs, - ClearBufCount, - CipherBufs, - CipherBufCount, - bytesEncrypted, - RemData, - Privilege); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_EncryptDataUpdate (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *ClearBufs, - uint32 ClearBufCount, - CSSM_DATA_PTR CipherBufs, - uint32 CipherBufCount, - CSSM_SIZE *bytesEncrypted) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.EncryptDataUpdate(context.CSPHandle, CCHandle, - ClearBufs, - ClearBufCount, - CipherBufs, - CipherBufCount, - bytesEncrypted); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_FreeKey (CSSM_CSP_HANDLE CSPHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - CSSM_KEY_PTR KeyPtr, - CSSM_BOOL Delete) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.FreeKey(CSPHandle, - AccessCred, - KeyPtr, - Delete); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GenerateKey (CSSM_CC_HANDLE CCHandle, - uint32 KeyUsage, - uint32 KeyAttr, - const CSSM_DATA *KeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CSSM_KEY_PTR Key) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.GenerateKey(context.CSPHandle, CCHandle, &context, - KeyUsage, - KeyAttr, - KeyLabel, - CredAndAclEntry, - Key, - attachment.module.cssm.getPrivilege()); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GenerateKeyP (CSSM_CC_HANDLE CCHandle, - uint32 KeyUsage, - uint32 KeyAttr, - const CSSM_DATA *KeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CSSM_KEY_PTR Key, - CSSM_PRIVILEGE Privilege) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.GenerateKey(context.CSPHandle, CCHandle, &context, - KeyUsage, - KeyAttr, - KeyLabel, - CredAndAclEntry, - Key, - Privilege); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GenerateKeyPair (CSSM_CC_HANDLE CCHandle, - uint32 PublicKeyUsage, - uint32 PublicKeyAttr, - const CSSM_DATA *PublicKeyLabel, - CSSM_KEY_PTR PublicKey, - uint32 PrivateKeyUsage, - uint32 PrivateKeyAttr, - const CSSM_DATA *PrivateKeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CSSM_KEY_PTR PrivateKey) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.GenerateKeyPair(context.CSPHandle, CCHandle, &context, - PublicKeyUsage, - PublicKeyAttr, - PublicKeyLabel, - PublicKey, - PrivateKeyUsage, - PrivateKeyAttr, - PrivateKeyLabel, - CredAndAclEntry, - PrivateKey, - attachment.module.cssm.getPrivilege()); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GenerateKeyPairP (CSSM_CC_HANDLE CCHandle, - uint32 PublicKeyUsage, - uint32 PublicKeyAttr, - const CSSM_DATA *PublicKeyLabel, - CSSM_KEY_PTR PublicKey, - uint32 PrivateKeyUsage, - uint32 PrivateKeyAttr, - const CSSM_DATA *PrivateKeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CSSM_KEY_PTR PrivateKey, - CSSM_PRIVILEGE Privilege) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.GenerateKeyPair(context.CSPHandle, CCHandle, &context, - PublicKeyUsage, - PublicKeyAttr, - PublicKeyLabel, - PublicKey, - PrivateKeyUsage, - PrivateKeyAttr, - PrivateKeyLabel, - CredAndAclEntry, - PrivateKey, - Privilege); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GenerateMac (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount, - CSSM_DATA_PTR Mac) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.GenerateMac(context.CSPHandle, CCHandle, &context, - DataBufs, - DataBufCount, - Mac); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GenerateMacFinal (CSSM_CC_HANDLE CCHandle, - CSSM_DATA_PTR Mac) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.GenerateMacFinal(context.CSPHandle, CCHandle, - Mac); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GenerateMacInit (CSSM_CC_HANDLE CCHandle) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.GenerateMacInit(context.CSPHandle, CCHandle, &context); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GenerateMacUpdate (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.GenerateMacUpdate(context.CSPHandle, CCHandle, - DataBufs, - DataBufCount); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GenerateRandom (CSSM_CC_HANDLE CCHandle, - CSSM_DATA_PTR RandomNumber) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.GenerateRandom(context.CSPHandle, CCHandle, &context, - RandomNumber); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GetKeyAcl (CSSM_CSP_HANDLE CSPHandle, - const CSSM_KEY *Key, - const CSSM_STRING *SelectionTag, - uint32 *NumberOfAclInfos, - CSSM_ACL_ENTRY_INFO_PTR *AclInfos) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.GetKeyAcl(CSPHandle, - Key, - SelectionTag, - NumberOfAclInfos, - AclInfos); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GetKeyOwner (CSSM_CSP_HANDLE CSPHandle, - const CSSM_KEY *Key, - CSSM_ACL_OWNER_PROTOTYPE_PTR Owner) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.GetKeyOwner(CSPHandle, - Key, - Owner); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_GetTimeValue (CSSM_CSP_HANDLE CSPHandle, - CSSM_ALGORITHMS TimeAlgorithm, - CSSM_DATA *TimeData) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.GetTimeValue(CSPHandle, - TimeAlgorithm, - TimeData); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_QuerySize (CSSM_CC_HANDLE CCHandle, - CSSM_BOOL Encrypt, - uint32 QuerySizeCount, - CSSM_QUERY_SIZE_DATA_PTR DataBlockSizes) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.QuerySize(context.CSPHandle, CCHandle, &context, - Encrypt, - QuerySizeCount, - DataBlockSizes); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_RetrieveCounter (CSSM_CSP_HANDLE CSPHandle, - CSSM_DATA_PTR Counter) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.RetrieveCounter(CSPHandle, - Counter); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_RetrieveUniqueId (CSSM_CSP_HANDLE CSPHandle, - CSSM_DATA_PTR UniqueID) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.RetrieveUniqueId(CSPHandle, - UniqueID); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_SignData (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount, - CSSM_ALGORITHMS DigestAlgorithm, - CSSM_DATA_PTR Signature) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.SignData(context.CSPHandle, CCHandle, &context, - DataBufs, - DataBufCount, - DigestAlgorithm, - Signature); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_SignDataFinal (CSSM_CC_HANDLE CCHandle, - CSSM_DATA_PTR Signature) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.SignDataFinal(context.CSPHandle, CCHandle, - Signature); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_SignDataInit (CSSM_CC_HANDLE CCHandle) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.SignDataInit(context.CSPHandle, CCHandle, &context); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_SignDataUpdate (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.SignDataUpdate(context.CSPHandle, CCHandle, - DataBufs, - DataBufCount); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_ApplyCrlToDb (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CSP_HANDLE CSPHandle, - const CSSM_ENCODED_CRL *CrlToBeApplied, - const CSSM_CERTGROUP *SignerCertGroup, - const CSSM_TP_VERIFY_CONTEXT *ApplyCrlVerifyContext, - CSSM_TP_VERIFY_CONTEXT_RESULT_PTR ApplyCrlVerifyResult) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.ApplyCrlToDb(TPHandle, - CLHandle, - CSPHandle, - CrlToBeApplied, - SignerCertGroup, - ApplyCrlVerifyContext, - ApplyCrlVerifyResult); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertCreateTemplate (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - uint32 NumberOfFields, - const CSSM_FIELD *CertFields, - CSSM_DATA_PTR CertTemplate) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertCreateTemplate(TPHandle, - CLHandle, - NumberOfFields, - CertFields, - CertTemplate); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertGetAllTemplateFields (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - const CSSM_DATA *CertTemplate, - uint32 *NumberOfFields, - CSSM_FIELD_PTR *CertFields) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGetAllTemplateFields(TPHandle, - CLHandle, - CertTemplate, - NumberOfFields, - CertFields); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertGroupConstruct (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CSP_HANDLE CSPHandle, - const CSSM_DL_DB_LIST *DBList, - const void *ConstructParams, - const CSSM_CERTGROUP *CertGroupFrag, - CSSM_CERTGROUP_PTR *CertGroup) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGroupConstruct(TPHandle, - CLHandle, - CSPHandle, - DBList, - ConstructParams, - CertGroupFrag, - CertGroup); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertGroupPrune (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - const CSSM_DL_DB_LIST *DBList, - const CSSM_CERTGROUP *OrderedCertGroup, - CSSM_CERTGROUP_PTR *PrunedCertGroup) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGroupPrune(TPHandle, - CLHandle, - DBList, - OrderedCertGroup, - PrunedCertGroup); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertGroupToTupleGroup (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - const CSSM_CERTGROUP *CertGroup, - CSSM_TUPLEGROUP_PTR *TupleGroup) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGroupToTupleGroup(TPHandle, - CLHandle, - CertGroup, - TupleGroup); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertGroupVerify (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CSP_HANDLE CSPHandle, - const CSSM_CERTGROUP *CertGroupToBeVerified, - const CSSM_TP_VERIFY_CONTEXT *VerifyContext, - CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertGroupVerify(TPHandle, - CLHandle, - CSPHandle, - CertGroupToBeVerified, - VerifyContext, - VerifyContextResult); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertReclaimAbort (CSSM_TP_HANDLE TPHandle, - CSSM_LONG_HANDLE KeyCacheHandle) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertReclaimAbort(TPHandle, - KeyCacheHandle); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertReclaimKey (CSSM_TP_HANDLE TPHandle, - const CSSM_CERTGROUP *CertGroup, - uint32 CertIndex, - CSSM_LONG_HANDLE KeyCacheHandle, - CSSM_CSP_HANDLE CSPHandle, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertReclaimKey(TPHandle, - CertGroup, - CertIndex, - KeyCacheHandle, - CSPHandle, - CredAndAclEntry); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertRemoveFromCrlTemplate (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CSP_HANDLE CSPHandle, - const CSSM_DATA *OldCrlTemplate, - const CSSM_CERTGROUP *CertGroupToBeRemoved, - const CSSM_CERTGROUP *RevokerCertGroup, - const CSSM_TP_VERIFY_CONTEXT *RevokerVerifyContext, - CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult, - CSSM_DATA_PTR NewCrlTemplate) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertRemoveFromCrlTemplate(TPHandle, - CLHandle, - CSPHandle, - OldCrlTemplate, - CertGroupToBeRemoved, - RevokerCertGroup, - RevokerVerifyContext, - RevokerVerifyResult, - NewCrlTemplate); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertRevoke (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CSP_HANDLE CSPHandle, - const CSSM_DATA *OldCrlTemplate, - const CSSM_CERTGROUP *CertGroupToBeRevoked, - const CSSM_CERTGROUP *RevokerCertGroup, - const CSSM_TP_VERIFY_CONTEXT *RevokerVerifyContext, - CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult, - CSSM_TP_CERTCHANGE_REASON Reason, - CSSM_DATA_PTR NewCrlTemplate) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertRevoke(TPHandle, - CLHandle, - CSPHandle, - OldCrlTemplate, - CertGroupToBeRevoked, - RevokerCertGroup, - RevokerVerifyContext, - RevokerVerifyResult, - Reason, - NewCrlTemplate); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CertSign (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *CertTemplateToBeSigned, - const CSSM_CERTGROUP *SignerCertGroup, - const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, - CSSM_TP_VERIFY_CONTEXT_RESULT_PTR SignerVerifyResult, - CSSM_DATA_PTR SignedCert) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CertSign(TPHandle, - CLHandle, - CCHandle, - CertTemplateToBeSigned, - SignerCertGroup, - SignerVerifyContext, - SignerVerifyResult, - SignedCert); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_ConfirmCredResult (CSSM_TP_HANDLE TPHandle, - const CSSM_DATA *ReferenceIdentifier, - const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, - const CSSM_TP_CONFIRM_RESPONSE *Responses, - const CSSM_TP_AUTHORITY_ID *PreferredAuthority) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.ConfirmCredResult(TPHandle, - ReferenceIdentifier, - CallerAuthCredentials, - Responses, - PreferredAuthority); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CrlCreateTemplate (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - uint32 NumberOfFields, - const CSSM_FIELD *CrlFields, - CSSM_DATA_PTR NewCrlTemplate) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlCreateTemplate(TPHandle, - CLHandle, - NumberOfFields, - CrlFields, - NewCrlTemplate); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CrlSign (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_ENCODED_CRL *CrlToBeSigned, - const CSSM_CERTGROUP *SignerCertGroup, - const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, - CSSM_TP_VERIFY_CONTEXT_RESULT_PTR SignerVerifyResult, - CSSM_DATA_PTR SignedCrl) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlSign(TPHandle, - CLHandle, - CCHandle, - CrlToBeSigned, - SignerCertGroup, - SignerVerifyContext, - SignerVerifyResult, - SignedCrl); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_CrlVerify (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CSP_HANDLE CSPHandle, - const CSSM_ENCODED_CRL *CrlToBeVerified, - const CSSM_CERTGROUP *SignerCertGroup, - const CSSM_TP_VERIFY_CONTEXT *VerifyContext, - CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.CrlVerify(TPHandle, - CLHandle, - CSPHandle, - CrlToBeVerified, - SignerCertGroup, - VerifyContext, - RevokerVerifyResult); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_FormRequest (CSSM_TP_HANDLE TPHandle, - const CSSM_TP_AUTHORITY_ID *PreferredAuthority, - CSSM_TP_FORM_TYPE FormType, - CSSM_DATA_PTR BlankForm) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.FormRequest(TPHandle, - PreferredAuthority, - FormType, - BlankForm); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_FormSubmit (CSSM_TP_HANDLE TPHandle, - CSSM_TP_FORM_TYPE FormType, - const CSSM_DATA *Form, - const CSSM_TP_AUTHORITY_ID *ClearanceAuthority, - const CSSM_TP_AUTHORITY_ID *RepresentedAuthority, - CSSM_ACCESS_CREDENTIALS_PTR Credentials) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.FormSubmit(TPHandle, - FormType, - Form, - ClearanceAuthority, - RepresentedAuthority, - Credentials); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_PassThrough (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - CSSM_CC_HANDLE CCHandle, - const CSSM_DL_DB_LIST *DBList, - uint32 PassThroughId, - const void *InputParams, - void **OutputParams) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.PassThrough(TPHandle, - CLHandle, - CCHandle, - DBList, - PassThroughId, - InputParams, - OutputParams); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_ReceiveConfirmation (CSSM_TP_HANDLE TPHandle, - const CSSM_DATA *ReferenceIdentifier, - CSSM_TP_CONFIRM_RESPONSE_PTR *Responses, - sint32 *ElapsedTime) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.ReceiveConfirmation(TPHandle, - ReferenceIdentifier, - Responses, - ElapsedTime); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_RetrieveCredResult (CSSM_TP_HANDLE TPHandle, - const CSSM_DATA *ReferenceIdentifier, - const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, - sint32 *EstimatedTime, - CSSM_BOOL *ConfirmationRequired, - CSSM_TP_RESULT_SET_PTR *RetrieveOutput) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.RetrieveCredResult(TPHandle, - ReferenceIdentifier, - CallerAuthCredentials, - EstimatedTime, - ConfirmationRequired, - RetrieveOutput); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_SubmitCredRequest (CSSM_TP_HANDLE TPHandle, - const CSSM_TP_AUTHORITY_ID *PreferredAuthority, - CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType, - const CSSM_TP_REQUEST_SET *RequestInput, - const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, - sint32 *EstimatedTime, - CSSM_DATA_PTR ReferenceIdentifier) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.SubmitCredRequest(TPHandle, - PreferredAuthority, - RequestType, - RequestInput, - CallerAuthContext, - EstimatedTime, - ReferenceIdentifier); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_TP_TupleGroupToCertGroup (CSSM_TP_HANDLE TPHandle, - CSSM_CL_HANDLE CLHandle, - const CSSM_TUPLEGROUP *TupleGroup, - CSSM_CERTGROUP_PTR *CertTemplates) -{ - BEGIN_API - TPAttachment &attachment = enterAttachment(TPHandle); - TransitLock _(attachment); - return attachment.downcalls.TupleGroupToCertGroup(TPHandle, - CLHandle, - TupleGroup, - CertTemplates); - END_API(TP) -} - -CSSM_RETURN CSSMAPI -CSSM_UnwrapKey (CSSM_CC_HANDLE CCHandle, - const CSSM_KEY *PublicKey, - const CSSM_WRAP_KEY *WrappedKey, - uint32 KeyUsage, - uint32 KeyAttr, - const CSSM_DATA *KeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CSSM_KEY_PTR UnwrappedKey, - CSSM_DATA_PTR DescriptiveData) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.UnwrapKey(context.CSPHandle, CCHandle, &context, - PublicKey, - WrappedKey, - KeyUsage, - KeyAttr, - KeyLabel, - CredAndAclEntry, - UnwrappedKey, - DescriptiveData, - attachment.module.cssm.getPrivilege()); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_UnwrapKeyP (CSSM_CC_HANDLE CCHandle, - const CSSM_KEY *PublicKey, - const CSSM_WRAP_KEY *WrappedKey, - uint32 KeyUsage, - uint32 KeyAttr, - const CSSM_DATA *KeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CSSM_KEY_PTR UnwrappedKey, - CSSM_DATA_PTR DescriptiveData, - CSSM_PRIVILEGE Privilege) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.UnwrapKey(context.CSPHandle, CCHandle, &context, - PublicKey, - WrappedKey, - KeyUsage, - KeyAttr, - KeyLabel, - CredAndAclEntry, - UnwrappedKey, - DescriptiveData, - Privilege); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_VerifyData (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount, - CSSM_ALGORITHMS DigestAlgorithm, - const CSSM_DATA *Signature) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.VerifyData(context.CSPHandle, CCHandle, &context, - DataBufs, - DataBufCount, - DigestAlgorithm, - Signature); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_VerifyDataFinal (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *Signature) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.VerifyDataFinal(context.CSPHandle, CCHandle, - Signature); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_VerifyDataInit (CSSM_CC_HANDLE CCHandle) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.VerifyDataInit(context.CSPHandle, CCHandle, &context); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_VerifyDataUpdate (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.VerifyDataUpdate(context.CSPHandle, CCHandle, - DataBufs, - DataBufCount); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_VerifyDevice (CSSM_CSP_HANDLE CSPHandle, - const CSSM_DATA *DeviceCert) -{ - BEGIN_API - CSPAttachment &attachment = enterAttachment(CSPHandle); - TransitLock _(attachment); - return attachment.downcalls.VerifyDevice(CSPHandle, - DeviceCert); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_VerifyMac (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount, - const CSSM_DATA *Mac) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.VerifyMac(context.CSPHandle, CCHandle, &context, - DataBufs, - DataBufCount, - Mac); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_VerifyMacFinal (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *Mac) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.VerifyMacFinal(context.CSPHandle, CCHandle, - Mac); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_VerifyMacInit (CSSM_CC_HANDLE CCHandle) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.VerifyMacInit(context.CSPHandle, CCHandle, &context); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_VerifyMacUpdate (CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *DataBufs, - uint32 DataBufCount) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.VerifyMacUpdate(context.CSPHandle, CCHandle, - DataBufs, - DataBufCount); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_WrapKey (CSSM_CC_HANDLE CCHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_KEY *Key, - const CSSM_DATA *DescriptiveData, - CSSM_WRAP_KEY_PTR WrappedKey) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.WrapKey(context.CSPHandle, CCHandle, &context, - AccessCred, - Key, - DescriptiveData, - WrappedKey, - attachment.module.cssm.getPrivilege()); - END_API(CSP) -} - -CSSM_RETURN CSSMAPI -CSSM_WrapKeyP (CSSM_CC_HANDLE CCHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_KEY *Key, - const CSSM_DATA *DescriptiveData, - CSSM_WRAP_KEY_PTR WrappedKey, - CSSM_PRIVILEGE Privilege) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - CSPAttachment &attachment = context.attachment; - TransitLock _(attachment); - return attachment.downcalls.WrapKey(context.CSPHandle, CCHandle, &context, - AccessCred, - Key, - DescriptiveData, - WrappedKey, - Privilege); - END_API(CSP) -} diff --git a/experiment/SecExperiment.m b/experiment/SecExperiment.m index c39ddaa5..f6e82895 100644 --- a/experiment/SecExperiment.m +++ b/experiment/SecExperiment.m @@ -154,11 +154,10 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, return SEC_EXP_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { - return SEC_EXP_NIL_OUT_OF_MEMORY; - } else { + if ((self = [super init])) { self->innerExperiment = [[SecExperiment alloc] initWithName:name]; + } else { + return SEC_EXP_NIL_OUT_OF_MEMORY; } return self; } @@ -169,11 +168,10 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, return SEC_EXP_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { - return SEC_EXP_NIL_OUT_OF_MEMORY; - } else { + if ((self = [super init])) { self->innerExperiment = experiment; + } else { + return SEC_EXP_NIL_OUT_OF_MEMORY; } return self; } @@ -224,11 +222,10 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, return SEC_EXP_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { - return SEC_EXP_NIL_OUT_OF_MEMORY; - } else { + if ((self = [super init])) { self.name = [NSString stringWithUTF8String:name]; + } else { + return SEC_EXP_NIL_OUT_OF_MEMORY; } return self; } @@ -381,10 +378,7 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, return SEC_EXP_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { - return SEC_EXP_NIL_OUT_OF_MEMORY; - } else { + if ((self = [super init])) { // Parse out experiment information from the configuration dictionary self.config = configuration; self.identifier = [configuration objectForKey:SecExperimentConfigurationKeyExperimentIdentifier]; @@ -400,7 +394,10 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, } self.configurationData = [configuration objectForKey:SecExperimentConfigurationKeyConfigurationData]; + } else { + return SEC_EXP_NIL_OUT_OF_MEMORY; } + return self; } diff --git a/experiment/SecExperimentInternal.h b/experiment/SecExperimentInternal.h index e475dcdb..efb4f251 100644 --- a/experiment/SecExperimentInternal.h +++ b/experiment/SecExperimentInternal.h @@ -30,7 +30,7 @@ extern const NSString *SecExperimentConfigurationKeyConfigurationData; @interface SecExperiment : NSObject @property (readonly) NSString *name; -@property (readonly) NSString *identifier; +@property (readonly, nullable) NSString *identifier; @property (readonly) BOOL samplingDisabled; - (instancetype)initWithName:(const char *)name; - (BOOL)experimentIsAllowedForProcess; @@ -50,8 +50,8 @@ extern const NSString *SecExperimentConfigurationKeyConfigurationData; * @abstract * Create an ARC-able `sec_experiment_t` instance wrapping an internal `SecExperiment` object. * - * @param experiment_name - * Name of the experiment. + * @param experiment + * The experiment * * @return a `sec_experiment_t` instance. */ diff --git a/experiment/tool/experimentTool.m b/experiment/tool/experimentTool.m index e08c385d..84aa3f61 100644 --- a/experiment/tool/experimentTool.m +++ b/experiment/tool/experimentTool.m @@ -22,9 +22,9 @@ run_experiment(const char *experiment_name, size_t num_runs, bool sampling_disab for (size_t i = 0; i < num_runs; i++) { (void)sec_experiment_run_with_sampling_disabled(experiment_name, ^bool(const char *identifier, xpc_object_t experiment_config) { runs++; - CFDictionaryRef configuration = (CFDictionaryRef)_CFXPCCreateCFObjectFromXPCObject(experiment_config); + NSDictionary* configuration = (__bridge_transfer NSDictionary*)_CFXPCCreateCFObjectFromXPCObject(experiment_config); if (configuration != NULL) { - [configurations addObject:(__bridge NSDictionary *)configuration]; + [configurations addObject:configuration]; } return true; }, ^(const char * _Nonnull identifier) { @@ -58,6 +58,7 @@ main(int argc, const char *argv[]) while ((arg = getopt(argc, gargv, "e:n:sruh")) != -1) { switch (arg) { case 'e': + free(experiment_name); // Only the last instance of -e counts experiment_name = strdup(optarg); break; case 'n': @@ -77,6 +78,7 @@ main(int argc, const char *argv[]) break; default: fprintf(stderr, "%s: FAILURE: unknown option \"%c\"\n", argv[0], arg); + free(experiment_name); return -1; } } diff --git a/featureflags/Security.plist b/featureflags/Security.plist index 1ffb729d..af1e3285 100644 --- a/featureflags/Security.plist +++ b/featureflags/Security.plist @@ -2,6 +2,16 @@ + SecErrorNestedErrorCapping + + Enabled + + + OctagonEscrowRecordFetch + + Enabled + + EnableSecureObjectSync Enabled @@ -30,7 +40,7 @@ CKKSViewsFromPolicy Enabled - + securitydReportPolicy @@ -42,5 +52,25 @@ Enabled + OctagonOptimization + + Enabled + + + SecItemRateLimiting + + Enabled + + + LegacyAPICounts + + Enabled + + + SecCodeOCSPDefault + + Enabled + + diff --git a/header_symlinks/Security/CKKSControl.h b/header_symlinks/Security/CKKSControl.h deleted file mode 120000 index 637ff3fd..00000000 --- a/header_symlinks/Security/CKKSControl.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/ckks/CKKSControl.h \ No newline at end of file diff --git a/header_symlinks/Security/CKKSControlProtocol.h b/header_symlinks/Security/CKKSControlProtocol.h deleted file mode 120000 index 5ea603db..00000000 --- a/header_symlinks/Security/CKKSControlProtocol.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/ckks/CKKSControlProtocol.h \ No newline at end of file diff --git a/header_symlinks/Security/CMSDecoder.h b/header_symlinks/Security/CMSDecoder.h deleted file mode 120000 index 38a00cfa..00000000 --- a/header_symlinks/Security/CMSDecoder.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/CMSDecoder.h \ No newline at end of file diff --git a/header_symlinks/Security/CMSEncoder.h b/header_symlinks/Security/CMSEncoder.h deleted file mode 120000 index 9837a584..00000000 --- a/header_symlinks/Security/CMSEncoder.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/CMSEncoder.h \ No newline at end of file diff --git a/header_symlinks/Security/CMSPrivate.h b/header_symlinks/Security/CMSPrivate.h deleted file mode 120000 index 2136cb4a..00000000 --- a/header_symlinks/Security/CMSPrivate.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/CMSPrivate.h \ No newline at end of file diff --git a/header_symlinks/Security/CSCommon.h b/header_symlinks/Security/CSCommon.h deleted file mode 120000 index 84797d4e..00000000 --- a/header_symlinks/Security/CSCommon.h +++ /dev/null @@ -1 +0,0 @@ -.././../OSX/libsecurity_codesigning/lib/CSCommon.h \ No newline at end of file diff --git a/header_symlinks/Security/CipherSuite.h b/header_symlinks/Security/CipherSuite.h deleted file mode 120000 index 72a3feb8..00000000 --- a/header_symlinks/Security/CipherSuite.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_ssl/lib/CipherSuite.h \ No newline at end of file diff --git a/header_symlinks/Security/CodeSigning.h b/header_symlinks/Security/CodeSigning.h deleted file mode 120000 index 16f5cdb3..00000000 --- a/header_symlinks/Security/CodeSigning.h +++ /dev/null @@ -1 +0,0 @@ -.././../OSX/libsecurity_codesigning/lib/CodeSigning.h \ No newline at end of file diff --git a/header_symlinks/Security/LocalKeychainAnalytics.h b/header_symlinks/Security/LocalKeychainAnalytics.h deleted file mode 120000 index b93921a2..00000000 --- a/header_symlinks/Security/LocalKeychainAnalytics.h +++ /dev/null @@ -1 +0,0 @@ -../../Analytics/Clients/LocalKeychainAnalytics.h \ No newline at end of file diff --git a/header_symlinks/Security/OTClique.h b/header_symlinks/Security/OTClique.h deleted file mode 120000 index 8b9848bb..00000000 --- a/header_symlinks/Security/OTClique.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/ot/OTClique.h \ No newline at end of file diff --git a/header_symlinks/Security/OTConstants.h b/header_symlinks/Security/OTConstants.h deleted file mode 120000 index 34c048da..00000000 --- a/header_symlinks/Security/OTConstants.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/ot/OTConstants.h \ No newline at end of file diff --git a/header_symlinks/Security/OTControl.h b/header_symlinks/Security/OTControl.h deleted file mode 120000 index 690316c2..00000000 --- a/header_symlinks/Security/OTControl.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/ot/OTControl.h \ No newline at end of file diff --git a/header_symlinks/Security/OTControlProtocol.h b/header_symlinks/Security/OTControlProtocol.h deleted file mode 120000 index ba64a3cd..00000000 --- a/header_symlinks/Security/OTControlProtocol.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/ot/OTControlProtocol.h \ No newline at end of file diff --git a/header_symlinks/Security/OTJoiningConfiguration.h b/header_symlinks/Security/OTJoiningConfiguration.h deleted file mode 120000 index 830036d9..00000000 --- a/header_symlinks/Security/OTJoiningConfiguration.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/ot/OTJoiningConfiguration.h \ No newline at end of file diff --git a/header_symlinks/Security/SFAnalytics.h b/header_symlinks/Security/SFAnalytics.h deleted file mode 120000 index c7a1c3b7..00000000 --- a/header_symlinks/Security/SFAnalytics.h +++ /dev/null @@ -1 +0,0 @@ -../../Analytics/SFAnalytics.h \ No newline at end of file diff --git a/header_symlinks/Security/SFAnalyticsActivityTracker.h b/header_symlinks/Security/SFAnalyticsActivityTracker.h deleted file mode 120000 index c6d8ec8f..00000000 --- a/header_symlinks/Security/SFAnalyticsActivityTracker.h +++ /dev/null @@ -1 +0,0 @@ -../../Analytics/SFAnalyticsActivityTracker.h \ No newline at end of file diff --git a/header_symlinks/Security/SFAnalyticsDefines.h b/header_symlinks/Security/SFAnalyticsDefines.h deleted file mode 120000 index 88ca4fde..00000000 --- a/header_symlinks/Security/SFAnalyticsDefines.h +++ /dev/null @@ -1 +0,0 @@ -../../Analytics/SFAnalyticsDefines.h \ No newline at end of file diff --git a/header_symlinks/Security/SFAnalyticsMultiSampler.h b/header_symlinks/Security/SFAnalyticsMultiSampler.h deleted file mode 120000 index 6f8259b7..00000000 --- a/header_symlinks/Security/SFAnalyticsMultiSampler.h +++ /dev/null @@ -1 +0,0 @@ -../../Analytics/SFAnalyticsMultiSampler.h \ No newline at end of file diff --git a/header_symlinks/Security/SFAnalyticsSQLiteStore.h b/header_symlinks/Security/SFAnalyticsSQLiteStore.h deleted file mode 120000 index 94f163c1..00000000 --- a/header_symlinks/Security/SFAnalyticsSQLiteStore.h +++ /dev/null @@ -1 +0,0 @@ -../../Analytics/SFAnalyticsSQLiteStore.h \ No newline at end of file diff --git a/header_symlinks/Security/SFAnalyticsSampler.h b/header_symlinks/Security/SFAnalyticsSampler.h deleted file mode 120000 index 4302b8ce..00000000 --- a/header_symlinks/Security/SFAnalyticsSampler.h +++ /dev/null @@ -1 +0,0 @@ -../../Analytics/SFAnalyticsSampler.h \ No newline at end of file diff --git a/header_symlinks/Security/SFSQLite.h b/header_symlinks/Security/SFSQLite.h deleted file mode 120000 index 36894567..00000000 --- a/header_symlinks/Security/SFSQLite.h +++ /dev/null @@ -1 +0,0 @@ -../../Analytics/SQLite/SFSQLite.h \ No newline at end of file diff --git a/header_symlinks/Security/SFSignInAnalytics.h b/header_symlinks/Security/SFSignInAnalytics.h deleted file mode 120000 index 7dadfc88..00000000 --- a/header_symlinks/Security/SFSignInAnalytics.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/SigninMetrics/SFSignInAnalytics.h \ No newline at end of file diff --git a/header_symlinks/Security/SOSAnalytics.h b/header_symlinks/Security/SOSAnalytics.h deleted file mode 120000 index 28ba10e4..00000000 --- a/header_symlinks/Security/SOSAnalytics.h +++ /dev/null @@ -1 +0,0 @@ -../../Analytics/Clients/SOSAnalytics.h \ No newline at end of file diff --git a/header_symlinks/Security/SOSControlHelper.h b/header_symlinks/Security/SOSControlHelper.h deleted file mode 120000 index e8720ef5..00000000 --- a/header_symlinks/Security/SOSControlHelper.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/SecureObjectSync/SOSControlHelper.h \ No newline at end of file diff --git a/header_symlinks/Security/SecAccessControl.h b/header_symlinks/Security/SecAccessControl.h deleted file mode 120000 index 67c3571f..00000000 --- a/header_symlinks/Security/SecAccessControl.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecAccessControl.h \ No newline at end of file diff --git a/header_symlinks/Security/SecAccessControlPriv.h b/header_symlinks/Security/SecAccessControlPriv.h deleted file mode 120000 index a6568af9..00000000 --- a/header_symlinks/Security/SecAccessControlPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecAccessControlPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecAsn1Coder.h b/header_symlinks/Security/SecAsn1Coder.h deleted file mode 120000 index 05b5692e..00000000 --- a/header_symlinks/Security/SecAsn1Coder.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_asn1/lib/SecAsn1Coder.h \ No newline at end of file diff --git a/header_symlinks/Security/SecAsn1Templates.h b/header_symlinks/Security/SecAsn1Templates.h deleted file mode 120000 index ce4d426f..00000000 --- a/header_symlinks/Security/SecAsn1Templates.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_asn1/lib/SecAsn1Templates.h \ No newline at end of file diff --git a/header_symlinks/Security/SecAsn1Types.h b/header_symlinks/Security/SecAsn1Types.h deleted file mode 120000 index 8001b9ef..00000000 --- a/header_symlinks/Security/SecAsn1Types.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_asn1/lib/SecAsn1Types.h \ No newline at end of file diff --git a/header_symlinks/Security/SecBase.h b/header_symlinks/Security/SecBase.h deleted file mode 120000 index 870c892e..00000000 --- a/header_symlinks/Security/SecBase.h +++ /dev/null @@ -1 +0,0 @@ -../../base/SecBase.h \ No newline at end of file diff --git a/header_symlinks/Security/SecBase64.h b/header_symlinks/Security/SecBase64.h deleted file mode 120000 index 7f78b9ba..00000000 --- a/header_symlinks/Security/SecBase64.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecBase64.h \ No newline at end of file diff --git a/header_symlinks/Security/SecBasePriv.h b/header_symlinks/Security/SecBasePriv.h deleted file mode 120000 index f54bbe45..00000000 --- a/header_symlinks/Security/SecBasePriv.h +++ /dev/null @@ -1 +0,0 @@ -../../base/SecBasePriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCFAllocator.h b/header_symlinks/Security/SecCFAllocator.h deleted file mode 120000 index f0558729..00000000 --- a/header_symlinks/Security/SecCFAllocator.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecCFAllocator.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCMS.h b/header_symlinks/Security/SecCMS.h deleted file mode 120000 index ace16523..00000000 --- a/header_symlinks/Security/SecCMS.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCMS.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCertificate.h b/header_symlinks/Security/SecCertificate.h deleted file mode 120000 index 69f443c8..00000000 --- a/header_symlinks/Security/SecCertificate.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/SecCertificate.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCertificatePriv.h b/header_symlinks/Security/SecCertificatePriv.h deleted file mode 120000 index 68e61428..00000000 --- a/header_symlinks/Security/SecCertificatePriv.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/SecCertificatePriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCertificateRequest.h b/header_symlinks/Security/SecCertificateRequest.h deleted file mode 120000 index f90bab2c..00000000 --- a/header_symlinks/Security/SecCertificateRequest.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/SecCertificateRequest.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsBase.h b/header_symlinks/Security/SecCmsBase.h deleted file mode 120000 index ebdbbcbd..00000000 --- a/header_symlinks/Security/SecCmsBase.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsBase.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsContentInfo.h b/header_symlinks/Security/SecCmsContentInfo.h deleted file mode 120000 index 70255a1b..00000000 --- a/header_symlinks/Security/SecCmsContentInfo.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsContentInfo.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsDecoder.h b/header_symlinks/Security/SecCmsDecoder.h deleted file mode 120000 index 6d05781a..00000000 --- a/header_symlinks/Security/SecCmsDecoder.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsDecoder.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsDigestContext.h b/header_symlinks/Security/SecCmsDigestContext.h deleted file mode 120000 index 1203762d..00000000 --- a/header_symlinks/Security/SecCmsDigestContext.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsDigestContext.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsDigestedData.h b/header_symlinks/Security/SecCmsDigestedData.h deleted file mode 120000 index 0d59d6f3..00000000 --- a/header_symlinks/Security/SecCmsDigestedData.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsDigestedData.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsEncoder.h b/header_symlinks/Security/SecCmsEncoder.h deleted file mode 120000 index dbf99b43..00000000 --- a/header_symlinks/Security/SecCmsEncoder.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsEncoder.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsEncryptedData.h b/header_symlinks/Security/SecCmsEncryptedData.h deleted file mode 120000 index c883dc36..00000000 --- a/header_symlinks/Security/SecCmsEncryptedData.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsEncryptedData.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsEnvelopedData.h b/header_symlinks/Security/SecCmsEnvelopedData.h deleted file mode 120000 index 9b8242e0..00000000 --- a/header_symlinks/Security/SecCmsEnvelopedData.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsEnvelopedData.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsMessage.h b/header_symlinks/Security/SecCmsMessage.h deleted file mode 120000 index 7a03b42d..00000000 --- a/header_symlinks/Security/SecCmsMessage.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsMessage.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsRecipientInfo.h b/header_symlinks/Security/SecCmsRecipientInfo.h deleted file mode 120000 index 3ccbdc4a..00000000 --- a/header_symlinks/Security/SecCmsRecipientInfo.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsRecipientInfo.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsSignedData.h b/header_symlinks/Security/SecCmsSignedData.h deleted file mode 120000 index 0320a0de..00000000 --- a/header_symlinks/Security/SecCmsSignedData.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsSignedData.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCmsSignerInfo.h b/header_symlinks/Security/SecCmsSignerInfo.h deleted file mode 120000 index 2b141a6e..00000000 --- a/header_symlinks/Security/SecCmsSignerInfo.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecCmsSignerInfo.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCode.h b/header_symlinks/Security/SecCode.h deleted file mode 120000 index 380eac00..00000000 --- a/header_symlinks/Security/SecCode.h +++ /dev/null @@ -1 +0,0 @@ -.././../OSX/libsecurity_codesigning/lib/SecCode.h \ No newline at end of file diff --git a/header_symlinks/Security/SecCodePriv.h b/header_symlinks/Security/SecCodePriv.h deleted file mode 120000 index d88588b9..00000000 --- a/header_symlinks/Security/SecCodePriv.h +++ /dev/null @@ -1 +0,0 @@ -.././../OSX/libsecurity_codesigning/lib/SecCodePriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecDH.h b/header_symlinks/Security/SecDH.h deleted file mode 120000 index 78fcfec4..00000000 --- a/header_symlinks/Security/SecDH.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecDH.h \ No newline at end of file diff --git a/header_symlinks/Security/SecECKey.h b/header_symlinks/Security/SecECKey.h deleted file mode 120000 index 0788c222..00000000 --- a/header_symlinks/Security/SecECKey.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecECKey.h \ No newline at end of file diff --git a/header_symlinks/Security/SecEntitlements.h b/header_symlinks/Security/SecEntitlements.h deleted file mode 120000 index a3e2942e..00000000 --- a/header_symlinks/Security/SecEntitlements.h +++ /dev/null @@ -1 +0,0 @@ -../../sectask/SecEntitlements.h \ No newline at end of file diff --git a/header_symlinks/Security/SecEscrowRequest.h b/header_symlinks/Security/SecEscrowRequest.h deleted file mode 120000 index 877cf5aa..00000000 --- a/header_symlinks/Security/SecEscrowRequest.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/escrowrequest/Framework/SecEscrowRequest.h \ No newline at end of file diff --git a/header_symlinks/Security/SecExperimentPriv.h b/header_symlinks/Security/SecExperimentPriv.h deleted file mode 120000 index 31074005..00000000 --- a/header_symlinks/Security/SecExperimentPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../experiment/SecExperimentPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecFramework.h b/header_symlinks/Security/SecFramework.h deleted file mode 120000 index 9f3334d2..00000000 --- a/header_symlinks/Security/SecFramework.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecFramework.h \ No newline at end of file diff --git a/header_symlinks/Security/SecIdentity.h b/header_symlinks/Security/SecIdentity.h deleted file mode 120000 index dc260732..00000000 --- a/header_symlinks/Security/SecIdentity.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecIdentity.h \ No newline at end of file diff --git a/header_symlinks/Security/SecIdentityPriv.h b/header_symlinks/Security/SecIdentityPriv.h deleted file mode 120000 index beba63ef..00000000 --- a/header_symlinks/Security/SecIdentityPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecIdentityPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecImportExport.h b/header_symlinks/Security/SecImportExport.h deleted file mode 120000 index f717a36c..00000000 --- a/header_symlinks/Security/SecImportExport.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecImportExport.h \ No newline at end of file diff --git a/header_symlinks/Security/SecImportExportPriv.h b/header_symlinks/Security/SecImportExportPriv.h deleted file mode 120000 index dbd175b6..00000000 --- a/header_symlinks/Security/SecImportExportPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecImportExportPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecInternal.h b/header_symlinks/Security/SecInternal.h deleted file mode 120000 index b4075e31..00000000 --- a/header_symlinks/Security/SecInternal.h +++ /dev/null @@ -1 +0,0 @@ -../../base/SecInternal.h \ No newline at end of file diff --git a/header_symlinks/Security/SecInternalReleasePriv.h b/header_symlinks/Security/SecInternalReleasePriv.h deleted file mode 120000 index d0edea3d..00000000 --- a/header_symlinks/Security/SecInternalReleasePriv.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/utilities/SecInternalReleasePriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecItem.h b/header_symlinks/Security/SecItem.h deleted file mode 120000 index 9dc42443..00000000 --- a/header_symlinks/Security/SecItem.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecItem.h \ No newline at end of file diff --git a/header_symlinks/Security/SecItemBackup.h b/header_symlinks/Security/SecItemBackup.h deleted file mode 120000 index 97206628..00000000 --- a/header_symlinks/Security/SecItemBackup.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecItemBackup.h \ No newline at end of file diff --git a/header_symlinks/Security/SecItemPriv.h b/header_symlinks/Security/SecItemPriv.h deleted file mode 120000 index c3c783d4..00000000 --- a/header_symlinks/Security/SecItemPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecItemPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecKey.h b/header_symlinks/Security/SecKey.h deleted file mode 120000 index 01f31ffe..00000000 --- a/header_symlinks/Security/SecKey.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecKey.h \ No newline at end of file diff --git a/header_symlinks/Security/SecKeyPriv.h b/header_symlinks/Security/SecKeyPriv.h deleted file mode 120000 index d15450e9..00000000 --- a/header_symlinks/Security/SecKeyPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecKeyPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecKeyProxy.h b/header_symlinks/Security/SecKeyProxy.h deleted file mode 120000 index 62d5f88d..00000000 --- a/header_symlinks/Security/SecKeyProxy.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecKeyProxy.h \ No newline at end of file diff --git a/header_symlinks/Security/SecLogging.h b/header_symlinks/Security/SecLogging.h deleted file mode 120000 index f9dbf442..00000000 --- a/header_symlinks/Security/SecLogging.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecLogging.h \ No newline at end of file diff --git a/header_symlinks/Security/SecOTR.h b/header_symlinks/Security/SecOTR.h deleted file mode 120000 index e58823ad..00000000 --- a/header_symlinks/Security/SecOTR.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecOTR.h \ No newline at end of file diff --git a/header_symlinks/Security/SecOTRSession.h b/header_symlinks/Security/SecOTRSession.h deleted file mode 120000 index 5a5928e8..00000000 --- a/header_symlinks/Security/SecOTRSession.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecOTRSession.h \ No newline at end of file diff --git a/header_symlinks/Security/SecPaddingConfigurationsPriv.h b/header_symlinks/Security/SecPaddingConfigurationsPriv.h deleted file mode 120000 index d3672167..00000000 --- a/header_symlinks/Security/SecPaddingConfigurationsPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/utilities/SecPaddingConfigurationsPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecPasswordGenerate.h b/header_symlinks/Security/SecPasswordGenerate.h deleted file mode 120000 index 5f59cf7a..00000000 --- a/header_symlinks/Security/SecPasswordGenerate.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecPasswordGenerate.h \ No newline at end of file diff --git a/header_symlinks/Security/SecPolicy.h b/header_symlinks/Security/SecPolicy.h deleted file mode 120000 index 1d58dd4e..00000000 --- a/header_symlinks/Security/SecPolicy.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/SecPolicy.h \ No newline at end of file diff --git a/header_symlinks/Security/SecPolicyPriv.h b/header_symlinks/Security/SecPolicyPriv.h deleted file mode 120000 index 3adc0670..00000000 --- a/header_symlinks/Security/SecPolicyPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/SecPolicyPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecProtocolConfiguration.h b/header_symlinks/Security/SecProtocolConfiguration.h deleted file mode 120000 index 52a493d1..00000000 --- a/header_symlinks/Security/SecProtocolConfiguration.h +++ /dev/null @@ -1 +0,0 @@ -../../protocol/SecProtocolConfiguration.h \ No newline at end of file diff --git a/header_symlinks/Security/SecProtocolInternal.h b/header_symlinks/Security/SecProtocolInternal.h deleted file mode 120000 index 70aab730..00000000 --- a/header_symlinks/Security/SecProtocolInternal.h +++ /dev/null @@ -1 +0,0 @@ -../../protocol/SecProtocolInternal.h \ No newline at end of file diff --git a/header_symlinks/Security/SecProtocolMetadata.h b/header_symlinks/Security/SecProtocolMetadata.h deleted file mode 120000 index 688a4150..00000000 --- a/header_symlinks/Security/SecProtocolMetadata.h +++ /dev/null @@ -1 +0,0 @@ -../../protocol/SecProtocolMetadata.h \ No newline at end of file diff --git a/header_symlinks/Security/SecProtocolObject.h b/header_symlinks/Security/SecProtocolObject.h deleted file mode 120000 index 36a0949d..00000000 --- a/header_symlinks/Security/SecProtocolObject.h +++ /dev/null @@ -1 +0,0 @@ -../../protocol/SecProtocolObject.h \ No newline at end of file diff --git a/header_symlinks/Security/SecProtocolOptions.h b/header_symlinks/Security/SecProtocolOptions.h deleted file mode 120000 index 05eb8879..00000000 --- a/header_symlinks/Security/SecProtocolOptions.h +++ /dev/null @@ -1 +0,0 @@ -../../protocol/SecProtocolOptions.h \ No newline at end of file diff --git a/header_symlinks/Security/SecProtocolPriv.h b/header_symlinks/Security/SecProtocolPriv.h deleted file mode 120000 index d1d24804..00000000 --- a/header_symlinks/Security/SecProtocolPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../protocol/SecProtocolPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecProtocolTypes.h b/header_symlinks/Security/SecProtocolTypes.h deleted file mode 120000 index 72a2050f..00000000 --- a/header_symlinks/Security/SecProtocolTypes.h +++ /dev/null @@ -1 +0,0 @@ -../../protocol/SecProtocolTypes.h \ No newline at end of file diff --git a/header_symlinks/Security/SecProtocolTypesPriv.h b/header_symlinks/Security/SecProtocolTypesPriv.h deleted file mode 120000 index c60242a5..00000000 --- a/header_symlinks/Security/SecProtocolTypesPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../protocol/SecProtocolTypesPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecRandom.h b/header_symlinks/Security/SecRandom.h deleted file mode 120000 index 16f27e92..00000000 --- a/header_symlinks/Security/SecRandom.h +++ /dev/null @@ -1 +0,0 @@ -../../base/SecRandom.h \ No newline at end of file diff --git a/header_symlinks/Security/SecRecoveryKey.h b/header_symlinks/Security/SecRecoveryKey.h deleted file mode 120000 index 216d1978..00000000 --- a/header_symlinks/Security/SecRecoveryKey.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecRecoveryKey.h \ No newline at end of file diff --git a/header_symlinks/Security/SecRequirement.h b/header_symlinks/Security/SecRequirement.h deleted file mode 120000 index 6b9d4a36..00000000 --- a/header_symlinks/Security/SecRequirement.h +++ /dev/null @@ -1 +0,0 @@ -.././../OSX/libsecurity_codesigning/lib/SecRequirement.h \ No newline at end of file diff --git a/header_symlinks/Security/SecSMIME.h b/header_symlinks/Security/SecSMIME.h deleted file mode 120000 index ce44c56c..00000000 --- a/header_symlinks/Security/SecSMIME.h +++ /dev/null @@ -1 +0,0 @@ -../../CMS/SecSMIME.h \ No newline at end of file diff --git a/header_symlinks/Security/SecServerEncryptionSupport.h b/header_symlinks/Security/SecServerEncryptionSupport.h deleted file mode 120000 index 270c2c1c..00000000 --- a/header_symlinks/Security/SecServerEncryptionSupport.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/sec/Security/SecServerEncryptionSupport.h \ No newline at end of file diff --git a/header_symlinks/Security/SecSharedCredential.h b/header_symlinks/Security/SecSharedCredential.h deleted file mode 120000 index b8f75a0b..00000000 --- a/header_symlinks/Security/SecSharedCredential.h +++ /dev/null @@ -1 +0,0 @@ -../../keychain/headers/SecSharedCredential.h \ No newline at end of file diff --git a/header_symlinks/Security/SecSignpost.h b/header_symlinks/Security/SecSignpost.h deleted file mode 120000 index 5ece266c..00000000 --- a/header_symlinks/Security/SecSignpost.h +++ /dev/null @@ -1 +0,0 @@ -../../base/SecSignpost.h \ No newline at end of file diff --git a/header_symlinks/Security/SecStaticCode.h b/header_symlinks/Security/SecStaticCode.h deleted file mode 120000 index 0879cd41..00000000 --- a/header_symlinks/Security/SecStaticCode.h +++ /dev/null @@ -1 +0,0 @@ -.././../OSX/libsecurity_codesigning/lib/SecStaticCode.h \ No newline at end of file diff --git a/header_symlinks/Security/SecTask.h b/header_symlinks/Security/SecTask.h deleted file mode 120000 index 00808c3c..00000000 --- a/header_symlinks/Security/SecTask.h +++ /dev/null @@ -1 +0,0 @@ -../../sectask/SecTask.h \ No newline at end of file diff --git a/header_symlinks/Security/SecTaskPriv.h b/header_symlinks/Security/SecTaskPriv.h deleted file mode 120000 index b62e3a79..00000000 --- a/header_symlinks/Security/SecTaskPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../sectask/SecTaskPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecTrust.h b/header_symlinks/Security/SecTrust.h deleted file mode 120000 index ced22994..00000000 --- a/header_symlinks/Security/SecTrust.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/SecTrust.h \ No newline at end of file diff --git a/header_symlinks/Security/SecTrustPriv.h b/header_symlinks/Security/SecTrustPriv.h deleted file mode 120000 index 54b6ba30..00000000 --- a/header_symlinks/Security/SecTrustPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/SecTrustPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecTrustSettings.h b/header_symlinks/Security/SecTrustSettings.h deleted file mode 120000 index 574e3b2c..00000000 --- a/header_symlinks/Security/SecTrustSettings.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/SecTrustSettings.h \ No newline at end of file diff --git a/header_symlinks/Security/SecTrustSettingsPriv.h b/header_symlinks/Security/SecTrustSettingsPriv.h deleted file mode 120000 index a3dbc9b8..00000000 --- a/header_symlinks/Security/SecTrustSettingsPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/SecTrustSettingsPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/SecXPCError.h b/header_symlinks/Security/SecXPCError.h deleted file mode 120000 index fcb27e20..00000000 --- a/header_symlinks/Security/SecXPCError.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/utilities/SecXPCError.h \ No newline at end of file diff --git a/header_symlinks/Security/SecXPCHelper.h b/header_symlinks/Security/SecXPCHelper.h deleted file mode 120000 index 06cda214..00000000 --- a/header_symlinks/Security/SecXPCHelper.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/utilities/SecXPCHelper.h \ No newline at end of file diff --git a/header_symlinks/Security/SecureObjectSync/SOSBackupSliceKeyBag.h b/header_symlinks/Security/SecureObjectSync/SOSBackupSliceKeyBag.h deleted file mode 120000 index 4cd393ec..00000000 --- a/header_symlinks/Security/SecureObjectSync/SOSBackupSliceKeyBag.h +++ /dev/null @@ -1 +0,0 @@ -../../..//keychain/SecureObjectSync/SOSBackupSliceKeyBag.h \ No newline at end of file diff --git a/header_symlinks/Security/SecureObjectSync/SOSCloudCircle.h b/header_symlinks/Security/SecureObjectSync/SOSCloudCircle.h deleted file mode 120000 index 1ca5caab..00000000 --- a/header_symlinks/Security/SecureObjectSync/SOSCloudCircle.h +++ /dev/null @@ -1 +0,0 @@ -../../..//keychain/SecureObjectSync/SOSCloudCircle.h \ No newline at end of file diff --git a/header_symlinks/Security/SecureObjectSync/SOSCloudCircleInternal.h b/header_symlinks/Security/SecureObjectSync/SOSCloudCircleInternal.h deleted file mode 120000 index 63b05874..00000000 --- a/header_symlinks/Security/SecureObjectSync/SOSCloudCircleInternal.h +++ /dev/null @@ -1 +0,0 @@ -../../..//keychain/SecureObjectSync/SOSCloudCircleInternal.h \ No newline at end of file diff --git a/header_symlinks/Security/SecureObjectSync/SOSPeerInfo.h b/header_symlinks/Security/SecureObjectSync/SOSPeerInfo.h deleted file mode 120000 index 335a6795..00000000 --- a/header_symlinks/Security/SecureObjectSync/SOSPeerInfo.h +++ /dev/null @@ -1 +0,0 @@ -../../..//keychain/SecureObjectSync/SOSPeerInfo.h \ No newline at end of file diff --git a/header_symlinks/Security/SecureObjectSync/SOSTypes.h b/header_symlinks/Security/SecureObjectSync/SOSTypes.h deleted file mode 120000 index 0a5f344e..00000000 --- a/header_symlinks/Security/SecureObjectSync/SOSTypes.h +++ /dev/null @@ -1 +0,0 @@ -../../..//keychain/SecureObjectSync/SOSTypes.h \ No newline at end of file diff --git a/header_symlinks/Security/SecureObjectSync/SOSViews.h b/header_symlinks/Security/SecureObjectSync/SOSViews.h deleted file mode 120000 index c5d2f1e6..00000000 --- a/header_symlinks/Security/SecureObjectSync/SOSViews.h +++ /dev/null @@ -1 +0,0 @@ -../../..//keychain/SecureObjectSync/SOSViews.h \ No newline at end of file diff --git a/header_symlinks/Security/SecureTransport.h b/header_symlinks/Security/SecureTransport.h deleted file mode 120000 index 71df180e..00000000 --- a/header_symlinks/Security/SecureTransport.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_ssl/lib/SecureTransport.h \ No newline at end of file diff --git a/header_symlinks/Security/SecureTransportPriv.h b/header_symlinks/Security/SecureTransportPriv.h deleted file mode 120000 index 6a484ea3..00000000 --- a/header_symlinks/Security/SecureTransportPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_ssl/lib/SecureTransportPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/Security.h b/header_symlinks/Security/Security.h deleted file mode 120000 index dc112cd9..00000000 --- a/header_symlinks/Security/Security.h +++ /dev/null @@ -1 +0,0 @@ -../../base/Security.h \ No newline at end of file diff --git a/header_symlinks/Security/X509Templates.h b/header_symlinks/Security/X509Templates.h deleted file mode 120000 index c42286c9..00000000 --- a/header_symlinks/Security/X509Templates.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_asn1/lib/X509Templates.h \ No newline at end of file diff --git a/header_symlinks/Security/certExtensionTemplates.h b/header_symlinks/Security/certExtensionTemplates.h deleted file mode 120000 index 802263b2..00000000 --- a/header_symlinks/Security/certExtensionTemplates.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_asn1/lib/certExtensionTemplates.h \ No newline at end of file diff --git a/header_symlinks/Security/certextensions.h b/header_symlinks/Security/certextensions.h deleted file mode 120000 index 25e28d69..00000000 --- a/header_symlinks/Security/certextensions.h +++ /dev/null @@ -1 +0,0 @@ -../../cssm/certextensions.h \ No newline at end of file diff --git a/header_symlinks/Security/der_plist.h b/header_symlinks/Security/der_plist.h deleted file mode 120000 index e9508730..00000000 --- a/header_symlinks/Security/der_plist.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/utilities/der_plist.h \ No newline at end of file diff --git a/header_symlinks/Security/nameTemplates.h b/header_symlinks/Security/nameTemplates.h deleted file mode 120000 index 940b141e..00000000 --- a/header_symlinks/Security/nameTemplates.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_asn1/lib/nameTemplates.h \ No newline at end of file diff --git a/header_symlinks/Security/ocspTemplates.h b/header_symlinks/Security/ocspTemplates.h deleted file mode 120000 index 48148182..00000000 --- a/header_symlinks/Security/ocspTemplates.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_asn1/lib/ocspTemplates.h \ No newline at end of file diff --git a/header_symlinks/Security/oids.h b/header_symlinks/Security/oids.h deleted file mode 120000 index 48616d80..00000000 --- a/header_symlinks/Security/oids.h +++ /dev/null @@ -1 +0,0 @@ -../../trust/headers/oids.h \ No newline at end of file diff --git a/header_symlinks/Security/oidsalg.h b/header_symlinks/Security/oidsalg.h deleted file mode 120000 index d0e9c523..00000000 --- a/header_symlinks/Security/oidsalg.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_asn1/lib/oidsalg.h \ No newline at end of file diff --git a/header_symlinks/Security/secasn1t.h b/header_symlinks/Security/secasn1t.h deleted file mode 120000 index a58ccedd..00000000 --- a/header_symlinks/Security/secasn1t.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_asn1/lib/secasn1t.h \ No newline at end of file diff --git a/header_symlinks/Security/sslTypes.h b/header_symlinks/Security/sslTypes.h deleted file mode 120000 index 0436edfb..00000000 --- a/header_symlinks/Security/sslTypes.h +++ /dev/null @@ -1 +0,0 @@ -../../OSX/libsecurity_ssl/lib/sslTypes.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/NtlmGenerator.h b/header_symlinks/iOS/Security/NtlmGenerator.h deleted file mode 120000 index 34872005..00000000 --- a/header_symlinks/iOS/Security/NtlmGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../ntlm/NtlmGenerator.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecCertificateInternal.h b/header_symlinks/iOS/Security/SecCertificateInternal.h deleted file mode 120000 index 8c7f1eaf..00000000 --- a/header_symlinks/iOS/Security/SecCertificateInternal.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecCertificateInternal.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecECKeyPriv.h b/header_symlinks/iOS/Security/SecECKeyPriv.h deleted file mode 120000 index 7da6bb7c..00000000 --- a/header_symlinks/iOS/Security/SecECKeyPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecECKeyPriv.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecEMCSPriv.h b/header_symlinks/iOS/Security/SecEMCSPriv.h deleted file mode 120000 index 84666477..00000000 --- a/header_symlinks/iOS/Security/SecEMCSPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecEMCSPriv.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecOTRDHKey.h b/header_symlinks/iOS/Security/SecOTRDHKey.h deleted file mode 120000 index 0d02e160..00000000 --- a/header_symlinks/iOS/Security/SecOTRDHKey.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecOTRDHKey.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecOTRErrors.h b/header_symlinks/iOS/Security/SecOTRErrors.h deleted file mode 120000 index 842ef0e9..00000000 --- a/header_symlinks/iOS/Security/SecOTRErrors.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecOTRErrors.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecOTRMath.h b/header_symlinks/iOS/Security/SecOTRMath.h deleted file mode 120000 index 7e4b7f36..00000000 --- a/header_symlinks/iOS/Security/SecOTRMath.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecOTRMath.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecOTRPacketData.h b/header_symlinks/iOS/Security/SecOTRPacketData.h deleted file mode 120000 index de04f3d2..00000000 --- a/header_symlinks/iOS/Security/SecOTRPacketData.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecOTRPacketData.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecOTRPackets.h b/header_symlinks/iOS/Security/SecOTRPackets.h deleted file mode 120000 index 2bb570a5..00000000 --- a/header_symlinks/iOS/Security/SecOTRPackets.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecOTRPackets.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecOTRSessionPriv.h b/header_symlinks/iOS/Security/SecOTRSessionPriv.h deleted file mode 120000 index 91639716..00000000 --- a/header_symlinks/iOS/Security/SecOTRSessionPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecOTRSessionPriv.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecPBKDF.h b/header_symlinks/iOS/Security/SecPBKDF.h deleted file mode 120000 index e00a3e26..00000000 --- a/header_symlinks/iOS/Security/SecPBKDF.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecPBKDF.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecRSAKey.h b/header_symlinks/iOS/Security/SecRSAKey.h deleted file mode 120000 index b04fe94e..00000000 --- a/header_symlinks/iOS/Security/SecRSAKey.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecRSAKey.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecSCEP.h b/header_symlinks/iOS/Security/SecSCEP.h deleted file mode 120000 index 49133713..00000000 --- a/header_symlinks/iOS/Security/SecSCEP.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecSCEP.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecTrustStore.h b/header_symlinks/iOS/Security/SecTrustStore.h deleted file mode 120000 index add6d4a0..00000000 --- a/header_symlinks/iOS/Security/SecTrustStore.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/SecTrustStore.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/SecureObjectSync/SOSPeerInfoV2.h b/header_symlinks/iOS/Security/SecureObjectSync/SOSPeerInfoV2.h deleted file mode 120000 index 37fe43fd..00000000 --- a/header_symlinks/iOS/Security/SecureObjectSync/SOSPeerInfoV2.h +++ /dev/null @@ -1 +0,0 @@ -../../../..//keychain/SecureObjectSync/SOSPeerInfoV2.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/oidsocsp.h b/header_symlinks/iOS/Security/oidsocsp.h deleted file mode 120000 index 7870a05c..00000000 --- a/header_symlinks/iOS/Security/oidsocsp.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_asn1/lib/oidsocsp.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/pbkdf2.h b/header_symlinks/iOS/Security/pbkdf2.h deleted file mode 120000 index 72166955..00000000 --- a/header_symlinks/iOS/Security/pbkdf2.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/pbkdf2.h \ No newline at end of file diff --git a/header_symlinks/iOS/Security/vmdh.h b/header_symlinks/iOS/Security/vmdh.h deleted file mode 120000 index ffe6faed..00000000 --- a/header_symlinks/iOS/Security/vmdh.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/sec/Security/vmdh.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/AuthSession.h b/header_symlinks/macOS/Security/AuthSession.h deleted file mode 120000 index 16ad054a..00000000 --- a/header_symlinks/macOS/Security/AuthSession.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_authorization/lib/AuthSession.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/Authorization.h b/header_symlinks/macOS/Security/Authorization.h deleted file mode 120000 index 9d0c637b..00000000 --- a/header_symlinks/macOS/Security/Authorization.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_authorization/lib/Authorization.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/AuthorizationDB.h b/header_symlinks/macOS/Security/AuthorizationDB.h deleted file mode 120000 index 3da362cb..00000000 --- a/header_symlinks/macOS/Security/AuthorizationDB.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_authorization/lib/AuthorizationDB.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/AuthorizationPlugin.h b/header_symlinks/macOS/Security/AuthorizationPlugin.h deleted file mode 120000 index b33d03d5..00000000 --- a/header_symlinks/macOS/Security/AuthorizationPlugin.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_authorization/lib/AuthorizationPlugin.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/AuthorizationPriv.h b/header_symlinks/macOS/Security/AuthorizationPriv.h deleted file mode 120000 index 7a2876e2..00000000 --- a/header_symlinks/macOS/Security/AuthorizationPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_authorization/lib/AuthorizationPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/AuthorizationTags.h b/header_symlinks/macOS/Security/AuthorizationTags.h deleted file mode 120000 index 831de6ac..00000000 --- a/header_symlinks/macOS/Security/AuthorizationTags.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_authorization/lib/AuthorizationTags.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/AuthorizationTagsPriv.h b/header_symlinks/macOS/Security/AuthorizationTagsPriv.h deleted file mode 120000 index 9f73f172..00000000 --- a/header_symlinks/macOS/Security/AuthorizationTagsPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/CSCommonPriv.h b/header_symlinks/macOS/Security/CSCommonPriv.h deleted file mode 120000 index 32e1bd04..00000000 --- a/header_symlinks/macOS/Security/CSCommonPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_codesigning/lib/CSCommonPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecACL.h b/header_symlinks/macOS/Security/SecACL.h deleted file mode 120000 index 1866246f..00000000 --- a/header_symlinks/macOS/Security/SecACL.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecACL.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecAccess.h b/header_symlinks/macOS/Security/SecAccess.h deleted file mode 120000 index 02e1ceea..00000000 --- a/header_symlinks/macOS/Security/SecAccess.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecAccess.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecAccessPriv.h b/header_symlinks/macOS/Security/SecAccessPriv.h deleted file mode 120000 index 4e88e9c3..00000000 --- a/header_symlinks/macOS/Security/SecAccessPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecAccessPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecAssessment.h b/header_symlinks/macOS/Security/SecAssessment.h deleted file mode 120000 index a8e83045..00000000 --- a/header_symlinks/macOS/Security/SecAssessment.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_codesigning/lib/SecAssessment.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecBreadcrumb.h b/header_symlinks/macOS/Security/SecBreadcrumb.h deleted file mode 120000 index 82728e08..00000000 --- a/header_symlinks/macOS/Security/SecBreadcrumb.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/Breadcrumb/SecBreadcrumb.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecCertificateBundle.h b/header_symlinks/macOS/Security/SecCertificateBundle.h deleted file mode 120000 index c9b1b5e6..00000000 --- a/header_symlinks/macOS/Security/SecCertificateBundle.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecCertificateBundle.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecCertificateOIDs.h b/header_symlinks/macOS/Security/SecCertificateOIDs.h deleted file mode 120000 index 141c565e..00000000 --- a/header_symlinks/macOS/Security/SecCertificateOIDs.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecCertificateOIDs.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecCodeHost.h b/header_symlinks/macOS/Security/SecCodeHost.h deleted file mode 120000 index a1da5ee5..00000000 --- a/header_symlinks/macOS/Security/SecCodeHost.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_codesigning/lib/SecCodeHost.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecCodeSigner.h b/header_symlinks/macOS/Security/SecCodeSigner.h deleted file mode 120000 index 732ed129..00000000 --- a/header_symlinks/macOS/Security/SecCodeSigner.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_codesigning/lib/SecCodeSigner.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecCustomTransform.h b/header_symlinks/macOS/Security/SecCustomTransform.h deleted file mode 120000 index b1937117..00000000 --- a/header_symlinks/macOS/Security/SecCustomTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecCustomTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecDecodeTransform.h b/header_symlinks/macOS/Security/SecDecodeTransform.h deleted file mode 120000 index 214334ea..00000000 --- a/header_symlinks/macOS/Security/SecDecodeTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecDecodeTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecDigestTransform.h b/header_symlinks/macOS/Security/SecDigestTransform.h deleted file mode 120000 index 9ef31e82..00000000 --- a/header_symlinks/macOS/Security/SecDigestTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecDigestTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecEncodeTransform.h b/header_symlinks/macOS/Security/SecEncodeTransform.h deleted file mode 120000 index 5405ddd9..00000000 --- a/header_symlinks/macOS/Security/SecEncodeTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecEncodeTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecEncryptTransform.h b/header_symlinks/macOS/Security/SecEncryptTransform.h deleted file mode 120000 index f7b5bf7f..00000000 --- a/header_symlinks/macOS/Security/SecEncryptTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecEncryptTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecExternalSourceTransform.h b/header_symlinks/macOS/Security/SecExternalSourceTransform.h deleted file mode 120000 index 96a1babd..00000000 --- a/header_symlinks/macOS/Security/SecExternalSourceTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecExternalSourceTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecFDERecoveryAsymmetricCrypto.h b/header_symlinks/macOS/Security/SecFDERecoveryAsymmetricCrypto.h deleted file mode 120000 index 6233bf82..00000000 --- a/header_symlinks/macOS/Security/SecFDERecoveryAsymmetricCrypto.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecIdentitySearch.h b/header_symlinks/macOS/Security/SecIdentitySearch.h deleted file mode 120000 index 369e11fe..00000000 --- a/header_symlinks/macOS/Security/SecIdentitySearch.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecIdentitySearch.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecIdentitySearchPriv.h b/header_symlinks/macOS/Security/SecIdentitySearchPriv.h deleted file mode 120000 index 4e2ef247..00000000 --- a/header_symlinks/macOS/Security/SecIdentitySearchPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecIdentitySearchPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecKeychain.h b/header_symlinks/macOS/Security/SecKeychain.h deleted file mode 120000 index fcdcf3a9..00000000 --- a/header_symlinks/macOS/Security/SecKeychain.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecKeychain.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecKeychainItem.h b/header_symlinks/macOS/Security/SecKeychainItem.h deleted file mode 120000 index b271bb2f..00000000 --- a/header_symlinks/macOS/Security/SecKeychainItem.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecKeychainItem.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecKeychainItemExtendedAttributes.h b/header_symlinks/macOS/Security/SecKeychainItemExtendedAttributes.h deleted file mode 120000 index afe97057..00000000 --- a/header_symlinks/macOS/Security/SecKeychainItemExtendedAttributes.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecKeychainItemPriv.h b/header_symlinks/macOS/Security/SecKeychainItemPriv.h deleted file mode 120000 index 23f9c37c..00000000 --- a/header_symlinks/macOS/Security/SecKeychainItemPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecKeychainPriv.h b/header_symlinks/macOS/Security/SecKeychainPriv.h deleted file mode 120000 index f1939925..00000000 --- a/header_symlinks/macOS/Security/SecKeychainPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecKeychainPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecKeychainSearch.h b/header_symlinks/macOS/Security/SecKeychainSearch.h deleted file mode 120000 index 7ca0f284..00000000 --- a/header_symlinks/macOS/Security/SecKeychainSearch.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecKeychainSearch.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecKeychainSearchPriv.h b/header_symlinks/macOS/Security/SecKeychainSearchPriv.h deleted file mode 120000 index f747aff1..00000000 --- a/header_symlinks/macOS/Security/SecKeychainSearchPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecKeychainSearchPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecManifest.h b/header_symlinks/macOS/Security/SecManifest.h deleted file mode 120000 index 598764b2..00000000 --- a/header_symlinks/macOS/Security/SecManifest.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_manifest/lib/SecManifest.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecNullTransform.h b/header_symlinks/macOS/Security/SecNullTransform.h deleted file mode 120000 index bbe5128c..00000000 --- a/header_symlinks/macOS/Security/SecNullTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecNullTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecPassword.h b/header_symlinks/macOS/Security/SecPassword.h deleted file mode 120000 index 03905c20..00000000 --- a/header_symlinks/macOS/Security/SecPassword.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecPassword.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecPolicySearch.h b/header_symlinks/macOS/Security/SecPolicySearch.h deleted file mode 120000 index 32a75d50..00000000 --- a/header_symlinks/macOS/Security/SecPolicySearch.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecPolicySearch.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecRandomP.h b/header_symlinks/macOS/Security/SecRandomP.h deleted file mode 120000 index 00042cbf..00000000 --- a/header_symlinks/macOS/Security/SecRandomP.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecRandomP.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecReadTransform.h b/header_symlinks/macOS/Security/SecReadTransform.h deleted file mode 120000 index 5c20b243..00000000 --- a/header_symlinks/macOS/Security/SecReadTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecReadTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecRecoveryPassword.h b/header_symlinks/macOS/Security/SecRecoveryPassword.h deleted file mode 120000 index 08b37892..00000000 --- a/header_symlinks/macOS/Security/SecRecoveryPassword.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecRecoveryPassword.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecRequirementPriv.h b/header_symlinks/macOS/Security/SecRequirementPriv.h deleted file mode 120000 index 5b4f82f4..00000000 --- a/header_symlinks/macOS/Security/SecRequirementPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_codesigning/lib/SecRequirementPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecSignVerifyTransform.h b/header_symlinks/macOS/Security/SecSignVerifyTransform.h deleted file mode 120000 index d80cf8a2..00000000 --- a/header_symlinks/macOS/Security/SecSignVerifyTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecSignVerifyTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecStaticCodePriv.h b/header_symlinks/macOS/Security/SecStaticCodePriv.h deleted file mode 120000 index 047eb18c..00000000 --- a/header_symlinks/macOS/Security/SecStaticCodePriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_codesigning/lib/SecStaticCodePriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecTransform.h b/header_symlinks/macOS/Security/SecTransform.h deleted file mode 120000 index cc62c624..00000000 --- a/header_symlinks/macOS/Security/SecTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecTransformInternal.h b/header_symlinks/macOS/Security/SecTransformInternal.h deleted file mode 120000 index a8b87b3a..00000000 --- a/header_symlinks/macOS/Security/SecTransformInternal.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecTransformInternal.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecTransformReadTransform.h b/header_symlinks/macOS/Security/SecTransformReadTransform.h deleted file mode 120000 index 7ad3d69e..00000000 --- a/header_symlinks/macOS/Security/SecTransformReadTransform.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_transform/lib/SecTransformReadTransform.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecTranslocate.h b/header_symlinks/macOS/Security/SecTranslocate.h deleted file mode 120000 index ca1de7e3..00000000 --- a/header_symlinks/macOS/Security/SecTranslocate.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_translocate/lib/SecTranslocate.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecTrustedApplication.h b/header_symlinks/macOS/Security/SecTrustedApplication.h deleted file mode 120000 index 14f1174c..00000000 --- a/header_symlinks/macOS/Security/SecTrustedApplication.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecTrustedApplication.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecTrustedApplicationPriv.h b/header_symlinks/macOS/Security/SecTrustedApplicationPriv.h deleted file mode 120000 index 595e9434..00000000 --- a/header_symlinks/macOS/Security/SecTrustedApplicationPriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/SecTrustedApplicationPriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecureDownload.h b/header_symlinks/macOS/Security/SecureDownload.h deleted file mode 120000 index d3f5b437..00000000 --- a/header_symlinks/macOS/Security/SecureDownload.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_manifest/lib/SecureDownload.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecureDownloadInternal.h b/header_symlinks/macOS/Security/SecureDownloadInternal.h deleted file mode 120000 index f55e8567..00000000 --- a/header_symlinks/macOS/Security/SecureDownloadInternal.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_manifest/lib/SecureDownloadInternal.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/TrustSettingsSchema.h b/header_symlinks/macOS/Security/TrustSettingsSchema.h deleted file mode 120000 index 0504f4d7..00000000 --- a/header_symlinks/macOS/Security/TrustSettingsSchema.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_keychain/lib/TrustSettingsSchema.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/asn1Templates.h b/header_symlinks/macOS/Security/asn1Templates.h deleted file mode 120000 index 4a12264f..00000000 --- a/header_symlinks/macOS/Security/asn1Templates.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_asn1/lib/asn1Templates.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/checkpw.h b/header_symlinks/macOS/Security/checkpw.h deleted file mode 120000 index 768a778a..00000000 --- a/header_symlinks/macOS/Security/checkpw.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_checkpw/lib/checkpw.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/csrTemplates.h b/header_symlinks/macOS/Security/csrTemplates.h deleted file mode 120000 index dee1cd85..00000000 --- a/header_symlinks/macOS/Security/csrTemplates.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_asn1/lib/csrTemplates.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssm.h b/header_symlinks/macOS/Security/cssm.h deleted file mode 120000 index 64eb1b61..00000000 --- a/header_symlinks/macOS/Security/cssm.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssm.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmaci.h b/header_symlinks/macOS/Security/cssmaci.h deleted file mode 120000 index 947d7cfb..00000000 --- a/header_symlinks/macOS/Security/cssmaci.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmaci.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmapi.h b/header_symlinks/macOS/Security/cssmapi.h deleted file mode 120000 index fde6a40a..00000000 --- a/header_symlinks/macOS/Security/cssmapi.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmapi.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmapple.h b/header_symlinks/macOS/Security/cssmapple.h deleted file mode 120000 index 0548df9f..00000000 --- a/header_symlinks/macOS/Security/cssmapple.h +++ /dev/null @@ -1 +0,0 @@ -../../../cssm/cssmapple.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmapplePriv.h b/header_symlinks/macOS/Security/cssmapplePriv.h deleted file mode 120000 index 61b480d4..00000000 --- a/header_symlinks/macOS/Security/cssmapplePriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmapplePriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmcli.h b/header_symlinks/macOS/Security/cssmcli.h deleted file mode 120000 index bb586813..00000000 --- a/header_symlinks/macOS/Security/cssmcli.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmcli.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmconfig.h b/header_symlinks/macOS/Security/cssmconfig.h deleted file mode 120000 index 5ecd59ae..00000000 --- a/header_symlinks/macOS/Security/cssmconfig.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmconfig.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmcspi.h b/header_symlinks/macOS/Security/cssmcspi.h deleted file mode 120000 index c4db273b..00000000 --- a/header_symlinks/macOS/Security/cssmcspi.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmcspi.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmdli.h b/header_symlinks/macOS/Security/cssmdli.h deleted file mode 120000 index ebd6c822..00000000 --- a/header_symlinks/macOS/Security/cssmdli.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmdli.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmerr.h b/header_symlinks/macOS/Security/cssmerr.h deleted file mode 120000 index 85d9012b..00000000 --- a/header_symlinks/macOS/Security/cssmerr.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmerr.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmkrapi.h b/header_symlinks/macOS/Security/cssmkrapi.h deleted file mode 120000 index deb5ee11..00000000 --- a/header_symlinks/macOS/Security/cssmkrapi.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmkrapi.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmkrspi.h b/header_symlinks/macOS/Security/cssmkrspi.h deleted file mode 120000 index e4e5d058..00000000 --- a/header_symlinks/macOS/Security/cssmkrspi.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmkrspi.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmspi.h b/header_symlinks/macOS/Security/cssmspi.h deleted file mode 120000 index 0ab6cf91..00000000 --- a/header_symlinks/macOS/Security/cssmspi.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmspi.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmtpi.h b/header_symlinks/macOS/Security/cssmtpi.h deleted file mode 120000 index d63ca095..00000000 --- a/header_symlinks/macOS/Security/cssmtpi.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmtpi.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/cssmtype.h b/header_symlinks/macOS/Security/cssmtype.h deleted file mode 120000 index 90d797f4..00000000 --- a/header_symlinks/macOS/Security/cssmtype.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/cssmtype.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/eisl.h b/header_symlinks/macOS/Security/eisl.h deleted file mode 120000 index a04e4998..00000000 --- a/header_symlinks/macOS/Security/eisl.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/eisl.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/emmspi.h b/header_symlinks/macOS/Security/emmspi.h deleted file mode 120000 index 9f897dde..00000000 --- a/header_symlinks/macOS/Security/emmspi.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/emmspi.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/emmtype.h b/header_symlinks/macOS/Security/emmtype.h deleted file mode 120000 index 843ce525..00000000 --- a/header_symlinks/macOS/Security/emmtype.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/emmtype.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/keyTemplates.h b/header_symlinks/macOS/Security/keyTemplates.h deleted file mode 120000 index e74ec3e6..00000000 --- a/header_symlinks/macOS/Security/keyTemplates.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_asn1/lib/keyTemplates.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/mds.h b/header_symlinks/macOS/Security/mds.h deleted file mode 120000 index 717273bc..00000000 --- a/header_symlinks/macOS/Security/mds.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_mds/lib/mds.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/mds_schema.h b/header_symlinks/macOS/Security/mds_schema.h deleted file mode 120000 index 79714c60..00000000 --- a/header_symlinks/macOS/Security/mds_schema.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_mds/lib/mds_schema.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/mdspriv.h b/header_symlinks/macOS/Security/mdspriv.h deleted file mode 120000 index 53b1778f..00000000 --- a/header_symlinks/macOS/Security/mdspriv.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_mds/lib/mdspriv.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/oidsattr.h b/header_symlinks/macOS/Security/oidsattr.h deleted file mode 120000 index b98dd3af..00000000 --- a/header_symlinks/macOS/Security/oidsattr.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_asn1/lib/oidsattr.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/oidsbase.h b/header_symlinks/macOS/Security/oidsbase.h deleted file mode 120000 index 26fe0d9f..00000000 --- a/header_symlinks/macOS/Security/oidsbase.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/oidsbase.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/oidscert.h b/header_symlinks/macOS/Security/oidscert.h deleted file mode 120000 index 7af27c7b..00000000 --- a/header_symlinks/macOS/Security/oidscert.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/oidscert.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/oidscrl.h b/header_symlinks/macOS/Security/oidscrl.h deleted file mode 120000 index 42cfa36c..00000000 --- a/header_symlinks/macOS/Security/oidscrl.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/oidscrl.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/osKeyTemplates.h b/header_symlinks/macOS/Security/osKeyTemplates.h deleted file mode 120000 index 9e372bcc..00000000 --- a/header_symlinks/macOS/Security/osKeyTemplates.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_asn1/lib/osKeyTemplates.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/tsaSupport.h b/header_symlinks/macOS/Security/tsaSupport.h deleted file mode 120000 index 2659ba1f..00000000 --- a/header_symlinks/macOS/Security/tsaSupport.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_smime/lib/tsaSupport.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/tsaTemplates.h b/header_symlinks/macOS/Security/tsaTemplates.h deleted file mode 120000 index db748ac9..00000000 --- a/header_symlinks/macOS/Security/tsaTemplates.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_smime/lib/tsaTemplates.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/x509defs.h b/header_symlinks/macOS/Security/x509defs.h deleted file mode 120000 index f0286997..00000000 --- a/header_symlinks/macOS/Security/x509defs.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_cssm/lib/x509defs.h \ No newline at end of file diff --git a/header_symlinks/macOS/security_utilities/casts.h b/header_symlinks/macOS/security_utilities/casts.h deleted file mode 120000 index 29d35ad5..00000000 --- a/header_symlinks/macOS/security_utilities/casts.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_utilities/lib/casts.h \ No newline at end of file diff --git a/header_symlinks/macOS/security_utilities/memutils.h b/header_symlinks/macOS/security_utilities/memutils.h deleted file mode 120000 index ebff9b50..00000000 --- a/header_symlinks/macOS/security_utilities/memutils.h +++ /dev/null @@ -1 +0,0 @@ -../../../OSX/libsecurity_utilities/lib/memutils.h \ No newline at end of file diff --git a/keychain/CoreDataKeychain/SecCDKeychain.m b/keychain/CoreDataKeychain/SecCDKeychain.m index 77ac9689..12617744 100644 --- a/keychain/CoreDataKeychain/SecCDKeychain.m +++ b/keychain/CoreDataKeychain/SecCDKeychain.m @@ -302,6 +302,7 @@ SecCDKeychainLookupValueType* const SecCDKeychainLookupValueTypeDate = (SecCDKey - (NSData*)_onQueueGetDatabaseKeyDataWithError:(NSError**)error { + dispatch_assert_queue(_queue); NSData* keyData = nil; NSDictionary* databaseKeyQuery = @{ (id)kSecClass : (id)kSecClassGenericPassword, (id)kSecAttrAccessGroup : @"com.apple.security.securityd", @@ -458,6 +459,7 @@ SecCDKeychainLookupValueType* const SecCDKeychainLookupValueTypeDate = (SecCDKey - (void)_onQueueDropClassAPersistentStore { + dispatch_assert_queue(_queue); for (NSPersistentStore* store in _classAPersistentStores) { NSError* error = nil; if (![_persistentStoreCoordinator removePersistentStore:store error:&error]) { diff --git a/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m b/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m index b79201ec..28dafff8 100644 --- a/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m +++ b/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m @@ -93,19 +93,29 @@ static NSString* const KeychainDataclass = @"KeychainDataclass"; creditCardsQuery[(id)kSecAttrAccessGroup] = @"com.apple.safari.credit-cards"; OSStatus creditCardsResult = SecItemDelete((__bridge CFDictionaryRef)creditCardsQuery); - if (inetResult != errSecSuccess) { + if (inetResult == errSecSuccess) { + secnotice("itemDelete", "deleted synchronizable passwords from table inet"); + } else { secwarning("failed to delete synchronizable passwords from table inet: %d", (int)inetResult); } - if (genpResult != errSecSuccess) { + if (genpResult == errSecSuccess) { + secnotice("itemDelete", "deleted synchronizable passwords from table genp"); + } else { secwarning("failed to delete synchronizable passwords from table genp: %d", (int)genpResult); } - if (certResult != errSecSuccess) { - secwarning("failed to delete synchronizable passwords from table cert: %d", (int)certResult); + if (certResult == errSecSuccess) { + secnotice("itemDelete", "deleted synchronizable certificates from table cert"); + } else { + secwarning("failed to delete synchronizable certificates from table cert: %d", (int)certResult); } - if (keyResult != errSecSuccess) { - secwarning("failed to delete synchronizable passwords from table keys: %d", (int)keyResult); + if (keyResult == errSecSuccess) { + secnotice("itemDelete", "deleted synchronizable keys from table keys"); + } else { + secwarning("failed to delete synchronizable keys from table keys: %d", (int)keyResult); } - if (creditCardsResult != errSecSuccess) { + if (creditCardsResult == errSecSuccess) { + secnotice("itemDelete", "deleted credit cards from table genp"); + } else { secwarning("failed to delete credit cards from table genp: %d", (int)creditCardsResult); } } diff --git a/keychain/KeychainStasher/KeychainStasher-Info.plist b/keychain/KeychainStasher/KeychainStasher-Info.plist new file mode 100644 index 00000000..777a5d4d --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasher-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + KeychainStasher + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/keychain/KeychainStasher/KeychainStasher.entitlements b/keychain/KeychainStasher/KeychainStasher.entitlements new file mode 100644 index 00000000..7a31b992 --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasher.entitlements @@ -0,0 +1,10 @@ + + + + + application-identifier + com.apple.security.KeychainStasher + com.apple.private.keychain.sysbound + + + diff --git a/keychain/KeychainStasher/KeychainStasher.h b/keychain/KeychainStasher/KeychainStasher.h new file mode 100644 index 00000000..c723cebb --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasher.h @@ -0,0 +1,5 @@ +#import +#import "KeychainStasherProtocol.h" + +@interface KeychainStasher : NSObject +@end diff --git a/keychain/KeychainStasher/KeychainStasher.m b/keychain/KeychainStasher/KeychainStasher.m new file mode 100644 index 00000000..efc8cdd4 --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasher.m @@ -0,0 +1,116 @@ +#import + +#import "utilities/debugging.h" +#import +#import "LocalKeychainAnalytics.h" + +#import "KeychainStasher.h" + +NSString* const kApplicationIdentifier = @"com.apple.security.KeychainStasher"; + +@implementation KeychainStasher + +- (NSError*)errorWithStatus:(OSStatus)status message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3) +{ + if (status == errSecSuccess) { + return nil; + } + + NSString* desc; + if (format) { + va_list ap; + va_start(ap, format); + desc = [[NSString alloc] initWithFormat:format arguments:ap]; + va_end(ap); + } + return [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + userInfo:desc ? @{NSLocalizedDescriptionKey : desc} : nil]; +} + +- (NSMutableDictionary*)baseQuery { + return [@{ + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + // Prevents backups in case this ever comes to the Mac, prevents sync + (id)kSecAttrSysBound : @(kSecSecAttrSysBoundPreserveDuringRestore), + // Belt-and-suspenders prohibition on syncing + (id)kSecAttrSynchronizable : @NO, + (id)kSecClass : (id)kSecClassKey, + (id)kSecAttrApplicationLabel : @"loginstash", + // This is the default, but just making sure + (id)kSecAttrAccessGroup : kApplicationIdentifier, + } mutableCopy]; +} + +- (void)stashKey:(NSData*)key withReply:(void (^)(NSError*))reply { + secnotice("stashkey", "Will attempt to stash key"); + if (!key || key.length == 0) { + reply([self errorWithStatus:errSecParam message:@"nil or empty key passed"]); + return; + } + + NSMutableDictionary* query = [self baseQuery]; + query[(id)kSecValueData] = key; + + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); + secnotice("stashkey", "SecItemAdd result: %ld", (long)status); + + if (status == errSecDuplicateItem) { + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStash hardFailure:NO result:[self errorWithStatus:status message:nil]]; + query[(id)kSecValueData] = nil; + NSDictionary* update = @{(id)kSecValueData : key}; + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update); + secnotice("stashkey", "SecItemUpdate result: %ld", (long)status); + } + + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStash hardFailure:YES result:[self errorWithStatus:status message:nil]]; + if (status == errSecSuccess) { + reply(nil); + } else { + reply([self errorWithStatus:status message:@"Stash failed with keychain error"]); + } +} + +- (void)loadKeyWithReply:(void (^)(NSData*, NSError*))reply { + secnotice("KeychainStasher", "Will attempt to retrieve stashed key"); + + NSMutableDictionary* query = [self baseQuery]; + query[(id)kSecReturnData] = @YES; + + CFTypeRef object = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &object); + + if (status != errSecSuccess) { + if (status == errSecItemNotFound) { + reply(nil, [self errorWithStatus:status message:@"No stashed key found"]); + } else { + reply(nil, [self errorWithStatus:status message:@"Keychain error"]); + } + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStashLoad hardFailure:YES result:[self errorWithStatus:status message:nil]]; + return; + } + + NSData* key; + if (!object || CFGetTypeID(object) != CFDataGetTypeID() || !(key = CFBridgingRelease(object))) { + reply(nil, [self errorWithStatus:errSecInternalError + message:@"No or bad object: %d / %lu / %d", + object != NULL, object ? CFGetTypeID(object) : 0, key != nil]); + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStashLoad + hardFailure:YES + result:[self errorWithStatus:errSecInternalError message:nil]]; + return; + } + + // Caller does not need to wait for our delete + reply(key, nil); + + query[(id)kSecReturnData] = nil; + status = SecItemDelete((__bridge CFDictionaryRef)query); + if (status != errSecSuccess) { + seccritical("Unable to delete masterkey after load: %d", (int)status); + } + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStashLoad hardFailure:NO result:[self errorWithStatus:status message:nil]]; +} + +@end diff --git a/keychain/KeychainStasher/KeychainStasherProtocol.h b/keychain/KeychainStasher/KeychainStasherProtocol.h new file mode 100644 index 00000000..c837e325 --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasherProtocol.h @@ -0,0 +1,13 @@ +#ifndef KeychainStasherProtocol_h +#define KeychainStasherProtocol_h + +#import + +@protocol KeychainStasherProtocol + +- (void)stashKey:(NSData*)key withReply:(void (^)(NSError*))reply; +- (void)loadKeyWithReply:( void (^)(NSData*, NSError*))reply; + +@end + +#endif /* KeychainStasherProtocol_h */ diff --git a/keychain/KeychainStasher/com.apple.security.KeychainStasher.plist b/keychain/KeychainStasher/com.apple.security.KeychainStasher.plist new file mode 100644 index 00000000..df467bce --- /dev/null +++ b/keychain/KeychainStasher/com.apple.security.KeychainStasher.plist @@ -0,0 +1,25 @@ + + + + + EnablePressuredExit + + EnableTransactions + + LimitLoadToSessionType + Background + POSIXSpawnType + Adaptive + Label + com.apple.security.KeychainStasher + MachServices + + com.apple.security.KeychainStasher + + + ProgramArguments + + /usr/libexec/KeychainStasher + + + diff --git a/keychain/KeychainStasher/com.apple.security.KeychainStasher.sb b/keychain/KeychainStasher/com.apple.security.KeychainStasher.sb new file mode 100644 index 00000000..5c86637d --- /dev/null +++ b/keychain/KeychainStasher/com.apple.security.KeychainStasher.sb @@ -0,0 +1,22 @@ +(version 1) + +(deny default) +(deny file-map-executable process-info* nvram*) +(deny dynamic-code-generation) + +(import "system.sb") +(import "com.apple.corefoundation.sb") +(corefoundation) + +(allow process-info-dirtycontrol (target self)) + +(allow mach-lookup (global-name "com.apple.securityd.xpc")) + +(allow file-read-metadata) + +(if (param "ANALYTICSDIR") + (allow file-read* file-write* (subpath (param "ANALYTICSDIR")))) + +(allow file-read* (subpath "/usr/libexec")) + +(allow user-preference-read (preference-domain "kCFPreferencesAnyApplication")) diff --git a/keychain/KeychainStasher/main.m b/keychain/KeychainStasher/main.m new file mode 100644 index 00000000..45be5ed2 --- /dev/null +++ b/keychain/KeychainStasher/main.m @@ -0,0 +1,72 @@ +#import +#import +#import +#import +#import + +#import +#import +#import + +#import "KeychainStasher.h" + +NSString* const KeychainStasherMachServiceName = @"com.apple.security.KeychainStasher"; + +@interface ServiceDelegate : NSObject +@end + +@implementation ServiceDelegate + +- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection { + // We should encounter no more than 1 transaction per boot in normal conditions, so get out of everyone's way ASAP + xpc_transaction_exit_clean(); + + NSNumber* value = [newConnection valueForEntitlement:kSecEntitlementPrivateStashService]; + if (value == nil || ![value boolValue]) { + secerror("KeychainStasher: client not entitled, rejecting connection"); + [newConnection invalidate]; + return NO; + } + + newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)]; + newConnection.exportedObject = [KeychainStasher new]; + [newConnection resume]; + return YES; +} + +@end + +int main(int argc, const char *argv[]) +{ + if (geteuid() == 0) { + secerror("KeychainStasher invoked as root, do not want."); + return 1; + } else { + secnotice("KeychainStasher", "Invoked with uid %d", geteuid()); + } + + NSString* analyticsdir = [[(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(nil) URLByAppendingPathComponent:@"Analytics/"] path]; + if (analyticsdir) { + const char* sandbox_parameters[] = {"ANALYTICSDIR", analyticsdir.UTF8String, NULL}; + char* sandbox_error = NULL; + if (0 != sandbox_init_with_parameters("com.apple.security.KeychainStasher", SANDBOX_NAMED, sandbox_parameters, &sandbox_error)) { + secerror("unable to enter sandbox with parameter: %s", sandbox_error); + sandbox_free_error(sandbox_error); + abort(); + } + } else { // If this fails somehow we will go ahead without analytics + char* sandbox_error = NULL; + if (0 != sandbox_init("com.apple.security.KeychainStasher", SANDBOX_NAMED, &sandbox_error)) { + secerror("unable to enter sandbox: %s", sandbox_error); + sandbox_free_error(sandbox_error); + abort(); + } + } + + ServiceDelegate *delegate = [ServiceDelegate new]; + NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:KeychainStasherMachServiceName]; + listener.delegate = delegate; + [listener resume]; + [[NSRunLoop currentRunLoop] run]; + return 0; +} diff --git a/keychain/OctagonTrust/Info.plist b/keychain/OctagonTrust/Info.plist new file mode 100644 index 00000000..9bcb2444 --- /dev/null +++ b/keychain/OctagonTrust/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/keychain/OctagonTrust/OTEscrowTranslation.h b/keychain/OctagonTrust/OTEscrowTranslation.h new file mode 100644 index 00000000..700c2d0a --- /dev/null +++ b/keychain/OctagonTrust/OTEscrowTranslation.h @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2020 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +#ifndef EscrowTranslation_h +#define EscrowTranslation_h +#if __OBJC2__ + +#import +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OTEscrowTranslation : NSObject + +//dictionary to escrow auth ++ (OTEscrowAuthenticationInformation* _Nullable )dictionaryToEscrowAuthenticationInfo:(NSDictionary*)dictionary; + +//escrow auth to dictionary ++ (NSDictionary* _Nullable)escrowAuthenticationInfoToDictionary:(OTEscrowAuthenticationInformation*)escrowAuthInfo; + +//dictionary to escrow record ++ (OTEscrowRecord* _Nullable)dictionaryToEscrowRecord:(NSDictionary*)dictionary; + +//escrow record to dictionary ++ (NSDictionary* _Nullable)escrowRecordToDictionary:(OTEscrowRecord*)escrowRecord; + +//dictionary to icdp record context ++ (OTICDPRecordContext* _Nullable)dictionaryToCDPRecordContext:(NSDictionary*)dictionary; + +//icdp record context to dictionary ++ (NSDictionary* _Nullable)CDPRecordContextToDictionary:(OTICDPRecordContext*)context; + ++ (NSDictionary * _Nullable) metadataToDictionary:(OTEscrowRecordMetadata*)metadata; + ++ (OTEscrowRecordMetadata * _Nullable) dictionaryToMetadata:(NSDictionary*)dictionary; + ++ (BOOL)supportedRestorePath:(OTICDPRecordContext*)cdpContext; + +@end + +NS_ASSUME_NONNULL_END + +#endif + +#endif /* EscrowTranslation_h */ diff --git a/keychain/OctagonTrust/OTEscrowTranslation.m b/keychain/OctagonTrust/OTEscrowTranslation.m new file mode 100644 index 00000000..916ad5ee --- /dev/null +++ b/keychain/OctagonTrust/OTEscrowTranslation.m @@ -0,0 +1,402 @@ +/* +* Copyright (c) 2020 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +#import +#import "OTEscrowTranslation.h" + +#import +#import +#import +#import "keychain/ot/categories/OctagonEscrowRecoverer.h" +#import +#import +#import +#import "keychain/ot/OTClique+Private.h" +#import + +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CloudServices); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" + +SOFT_LINK_CLASS(CloudServices, SecureBackup); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupErrorDomain, NSErrorDomain); + +/* Escrow Authentication Information used for SRP*/ +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationAppleID, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationPassword, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationiCloudEnvironment, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationAuthToken, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationEscrowProxyURL, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupIDMSRecoveryKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupFMiPRecoveryKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupFMiPUUIDKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationDSID, NSString*); + +/* CDP recovery information */ +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUseCachedPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryKeyKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupContainsiCDPDataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupSilentRecoveryAttemptKey, NSString*); + + +/* Escrow Record Fields set by SecureBackup*/ +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupIsEnabledKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesRecoveryKeyKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupLastBackupTimestampKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupLastBackupDateKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupEscrowTrustStatusKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordStatusKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordIDKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPeerInfoDataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPeerInfoSerialNumberKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPeerInfoOSVersionKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAlliCDPRecordsKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordLabelKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupEscrowedSPKIKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBottleIDKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupSerialNumberKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBuildVersionKey, NSString*); + +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesRandomPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesComplexPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesNumericPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupNumericPassphraseLengthKey, NSString*); + +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryRequiresVerificationTokenKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAccountIsHighSecurityKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupSMSTargetInfoKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupMetadataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesMultipleiCSCKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupClientMetadataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBottleValidityKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupEscrowDateKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRemainingAttemptsKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupCoolOffEndKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryStatusKey, NSString*); + +#pragma clang diagnostic pop + +static NSString * const kCliqueSecureBackupTimestampKey = @"com.apple.securebackup.timestamp"; +static NSString * const kCliqueEscrowServiceRecordMetadataKey = @"metadata"; +static NSString * const kCliqueSecureBackupEncodedMetadataKey = @"encodedMetadata"; +static NSString * const kCliqueSecureBackupKeybagDigestKey = @"BackupKeybagDigest"; +static NSString * const kCliqueSecureBackupMetadataTimestampKey = @"SecureBackupMetadataTimestamp"; +static NSString * const kCliqueSecureBackupDeviceColor = @"device_color"; +static NSString * const kCliqueSecureBackupDeviceEnclosureColor = @"device_enclosure_color"; +static NSString * const kCliqueSecureBackupDeviceMID = @"device_mid"; +static NSString * const kCliqueSecureBackupDeviceModel = @"device_model"; +static NSString * const kCliqueSecureBackupDeviceModelClass = @"device_model_class"; +static NSString * const kCliqueSecureBackupDeviceModelVersion = @"device_model_version"; +static NSString * const kCliqueSecureBackupDeviceName = @"device_name"; +static NSString * const kCliqueSecureBackupDevicePlatform = @"device_platform"; +static NSString * const kCliqueSecureBackupSilentAttemptAllowed = @"silentAttemptAllowed"; +static NSString * const kCliqueSecureBackupFederationID = @"FEDERATIONID"; +static NSString * const kCliqueSecureBackupExpectedFederationID = @"EXPECTEDFEDERATIONID"; + +@implementation OTEscrowTranslation + +//dictionary to escrow auth ++ (OTEscrowAuthenticationInformation*) dictionaryToEscrowAuthenticationInfo:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTEscrowAuthenticationInformation* escrowAuthInfo = [[OTEscrowAuthenticationInformation alloc] init]; + escrowAuthInfo.authenticationAppleid = dictionary[getkSecureBackupAuthenticationAppleID()]; + escrowAuthInfo.authenticationAuthToken = dictionary[getkSecureBackupAuthenticationAuthToken()]; + escrowAuthInfo.authenticationDsid = dictionary[getkSecureBackupAuthenticationDSID()]; + escrowAuthInfo.authenticationEscrowproxyUrl = dictionary[getkSecureBackupAuthenticationEscrowProxyURL()]; + escrowAuthInfo.authenticationIcloudEnvironment = dictionary[getkSecureBackupAuthenticationiCloudEnvironment()]; + escrowAuthInfo.authenticationPassword = dictionary[getkSecureBackupAuthenticationPassword()]; + escrowAuthInfo.fmipUuid = dictionary[getkSecureBackupFMiPUUIDKey()]; + escrowAuthInfo.fmipRecovery = [dictionary[getkSecureBackupFMiPRecoveryKey()] boolValue]; + escrowAuthInfo.idmsRecovery = [dictionary[getkSecureBackupIDMSRecoveryKey()] boolValue]; + + return escrowAuthInfo; +} + +//escrow auth to dictionary ++ (NSDictionary*) escrowAuthenticationInfoToDictionary:(OTEscrowAuthenticationInformation*)escrowAuthInfo +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; + if(![escrowAuthInfo.authenticationAppleid isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationAppleID()] = escrowAuthInfo.authenticationAppleid; + } + if(![escrowAuthInfo.authenticationAuthToken isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationAuthToken()] = escrowAuthInfo.authenticationAuthToken; + } + if(![escrowAuthInfo.authenticationDsid isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationDSID()] = escrowAuthInfo.authenticationDsid; + } + if(![escrowAuthInfo.authenticationEscrowproxyUrl isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationEscrowProxyURL()] = escrowAuthInfo.authenticationEscrowproxyUrl; + } + if(![escrowAuthInfo.authenticationIcloudEnvironment isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationiCloudEnvironment()] = escrowAuthInfo.authenticationIcloudEnvironment; + } + if(![escrowAuthInfo.authenticationPassword isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationPassword()] = escrowAuthInfo.authenticationPassword; + } + if(![escrowAuthInfo.fmipUuid isEqualToString:@""]){ + dictionary[getkSecureBackupFMiPUUIDKey()] = escrowAuthInfo.fmipUuid; + } + dictionary[getkSecureBackupFMiPRecoveryKey()] = escrowAuthInfo.fmipRecovery ? @YES : @NO; + dictionary[getkSecureBackupIDMSRecoveryKey()] = escrowAuthInfo.idmsRecovery ? @YES : @NO; + + return dictionary; +} + ++ (OTCDPRecoveryInformation*)dictionaryToCDPRecoveryInformation:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTCDPRecoveryInformation* info = [[OTCDPRecoveryInformation alloc] init]; + info.recoverySecret = dictionary[getkSecureBackupPassphraseKey()]; + info.useCachedSecret = [dictionary[getkSecureBackupUseCachedPassphraseKey()] boolValue]; + info.recoveryKey = dictionary[getkSecureBackupRecoveryKeyKey()]; + info.usePreviouslyCachedRecoveryKey = [dictionary[getkSecureBackupUsesRecoveryKeyKey()] boolValue]; + info.silentRecoveryAttempt = [dictionary[@"SecureBackupSilentRecoveryAttempt"] boolValue]; + info.containsIcdpData =[dictionary[getkSecureBackupContainsiCDPDataKey()] boolValue]; + info.usesMultipleIcsc = [dictionary[getkSecureBackupUsesMultipleiCSCKey()] boolValue]; + return info; +} + ++ (NSDictionary*)cdpRecoveryInformationToDictionary:(OTCDPRecoveryInformation*)info +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; + dictionary[getkSecureBackupPassphraseKey()] = info.recoverySecret; + dictionary[getkSecureBackupUseCachedPassphraseKey()] = info.useCachedSecret ? @YES : @NO; + dictionary[getkSecureBackupRecoveryKeyKey()] = info.recoveryKey; + dictionary[getkSecureBackupUsesRecoveryKeyKey()] = info.usePreviouslyCachedRecoveryKey ? @YES : @NO; + dictionary[@"SecureBackupSilentRecoveryAttempt"] = info.silentRecoveryAttempt ? @YES : @NO; + dictionary[getkSecureBackupContainsiCDPDataKey()] = info.containsIcdpData ? @YES : @NO; + dictionary[getkSecureBackupUsesMultipleiCSCKey()] = info.usesMultipleIcsc ? @YES : @NO; + + return dictionary; +} + ++ (NSDate *)_dateWithSecureBackupDateString:(NSString *)dateString +{ + NSDateFormatter *dateFormatter = [NSDateFormatter new]; + dateFormatter.dateFormat = @"dd-MM-yyyy HH:mm:ss"; + NSDate *ret = [dateFormatter dateFromString:dateString]; + + if (ret) { + return ret; + } + // New date format is GMT + dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; + dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; + return [dateFormatter dateFromString:dateString]; +} + ++ (NSString*)_stringWithSecureBackupDate:(NSDate*) date +{ + NSDateFormatter *dateFormatter = [NSDateFormatter new]; + dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; + dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; + return [dateFormatter stringFromDate: date]; +} + ++ (OTEscrowRecordMetadata *) dictionaryToMetadata:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTEscrowRecordMetadata *metadata = [[OTEscrowRecordMetadata alloc] init]; + + metadata.backupKeybagDigest = dictionary[kCliqueSecureBackupKeybagDigestKey]; + metadata.secureBackupUsesMultipleIcscs = [dictionary[getkSecureBackupUsesMultipleiCSCKey()] boolValue]; + metadata.bottleId = dictionary[getkSecureBackupBottleIDKey()]; + metadata.bottleValidity = dictionary[@"bottleValid"]; + NSDate* secureBackupTimestamp = [OTEscrowTranslation _dateWithSecureBackupDateString: dictionary[kCliqueSecureBackupTimestampKey]]; + + metadata.secureBackupTimestamp = [secureBackupTimestamp timeIntervalSince1970]; + metadata.escrowedSpki = dictionary[getkSecureBackupEscrowedSPKIKey()]; + metadata.peerInfo = dictionary[getkSecureBackupPeerInfoDataKey()]; + metadata.serial = dictionary[getkSecureBackupSerialNumberKey()]; + + NSDictionary* escrowInformationMetadataClientMetadata = dictionary[getkSecureBackupClientMetadataKey()]; + metadata.clientMetadata = [[OTEscrowRecordMetadataClientMetadata alloc] init]; + NSNumber *platform = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDevicePlatform]; + metadata.clientMetadata.devicePlatform = [platform longLongValue]; + + NSDate* secureBackupMetadataTimestamp = [OTEscrowTranslation _dateWithSecureBackupDateString: escrowInformationMetadataClientMetadata[kCliqueSecureBackupMetadataTimestampKey]]; + metadata.clientMetadata.secureBackupMetadataTimestamp = [secureBackupMetadataTimestamp timeIntervalSince1970]; + + NSNumber *passphraseLength = escrowInformationMetadataClientMetadata[getkSecureBackupNumericPassphraseLengthKey()]; + metadata.clientMetadata.secureBackupNumericPassphraseLength = [passphraseLength longLongValue]; + metadata.clientMetadata.secureBackupUsesComplexPassphrase = [escrowInformationMetadataClientMetadata[getkSecureBackupUsesComplexPassphraseKey()] boolValue]; + metadata.clientMetadata.secureBackupUsesNumericPassphrase = [escrowInformationMetadataClientMetadata[getkSecureBackupUsesNumericPassphraseKey()] boolValue]; + metadata.clientMetadata.deviceColor = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceColor]; + metadata.clientMetadata.deviceEnclosureColor = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceEnclosureColor]; + metadata.clientMetadata.deviceMid = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceMID]; + metadata.clientMetadata.deviceModel = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceModel]; + metadata.clientMetadata.deviceModelClass = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceModelClass]; + metadata.clientMetadata.deviceModelVersion = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceModelVersion]; + metadata.clientMetadata.deviceName = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceName]; + + return metadata; +} + +//dictionary to escrow record ++ (OTEscrowRecord*) dictionaryToEscrowRecord:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTEscrowRecord* record = [[OTEscrowRecord alloc] init]; + NSDate* creationDate = dictionary[getkSecureBackupEscrowDateKey()]; + record.creationDate = [creationDate timeIntervalSince1970]; + NSDictionary* escrowInformationMetadata = dictionary[kCliqueEscrowServiceRecordMetadataKey]; + record.escrowInformationMetadata = [OTEscrowTranslation dictionaryToMetadata:escrowInformationMetadata]; + + NSNumber *remainingAttempts = dictionary[getkSecureBackupRemainingAttemptsKey()]; + + record.remainingAttempts = [remainingAttempts longLongValue]; + record.label = dictionary[getkSecureBackupRecordLabelKey()]; + record.recordStatus = [dictionary[getkSecureBackupRecordStatusKey()] isEqualToString:@"valid"] ? OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID : OTEscrowRecord_RecordStatus_RECORD_STATUS_INVALID; + record.silentAttemptAllowed = [dictionary[kCliqueSecureBackupSilentAttemptAllowed] boolValue]; + record.federationId = dictionary[kCliqueSecureBackupFederationID]; + record.expectedFederationId = dictionary[kCliqueSecureBackupExpectedFederationID]; + record.recordId = dictionary[getkSecureBackupRecordIDKey()]; + record.serialNumber = dictionary[getkSecureBackupPeerInfoSerialNumberKey()]; + if(dictionary[getkSecureBackupCoolOffEndKey()]) { + record.coolOffEnd = [dictionary[getkSecureBackupCoolOffEndKey()] longLongValue]; + } + record.recoveryStatus = [dictionary[getkSecureBackupRecoveryStatusKey()] intValue]; + return record; +} + ++ (NSDictionary *) metadataToDictionary:(OTEscrowRecordMetadata*)metadata +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + dictionary[getkSecureBackupClientMetadataKey()] = [NSMutableDictionary dictionary]; + + dictionary[kCliqueSecureBackupKeybagDigestKey] = metadata.backupKeybagDigest; + dictionary[getkSecureBackupUsesMultipleiCSCKey()] = [[NSNumber alloc]initWithUnsignedLongLong:metadata.secureBackupUsesMultipleIcscs]; + dictionary[getkSecureBackupBottleIDKey()] = metadata.bottleId; + dictionary[@"bottleValid"] = metadata.bottleValidity; + dictionary[kCliqueSecureBackupTimestampKey] = [OTEscrowTranslation _stringWithSecureBackupDate: [NSDate dateWithTimeIntervalSince1970: metadata.secureBackupTimestamp]]; + dictionary[getkSecureBackupEscrowedSPKIKey()] = metadata.escrowedSpki; + dictionary[getkSecureBackupPeerInfoDataKey()] = metadata.peerInfo; + dictionary[getkSecureBackupSerialNumberKey()] = metadata.serial; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDevicePlatform] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.devicePlatform]; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupMetadataTimestampKey] = [OTEscrowTranslation _stringWithSecureBackupDate: [NSDate dateWithTimeIntervalSince1970: metadata.clientMetadata.secureBackupMetadataTimestamp]]; + dictionary[getkSecureBackupClientMetadataKey()][getkSecureBackupNumericPassphraseLengthKey()] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.secureBackupNumericPassphraseLength]; + dictionary[getkSecureBackupClientMetadataKey()][getkSecureBackupUsesComplexPassphraseKey()] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.secureBackupUsesComplexPassphrase]; + dictionary[getkSecureBackupClientMetadataKey()][getkSecureBackupUsesNumericPassphraseKey()] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.secureBackupUsesNumericPassphrase]; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceColor] = metadata.clientMetadata.deviceColor; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceEnclosureColor] = metadata.clientMetadata.deviceEnclosureColor; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceMID] = metadata.clientMetadata.deviceMid; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceModel] = metadata.clientMetadata.deviceModel; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceModelClass] = metadata.clientMetadata.deviceModelClass; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceModelVersion] = metadata.clientMetadata.deviceModelVersion; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceName] = metadata.clientMetadata.deviceName; + + return dictionary; +} + +//escrow record to dictionary ++ (NSDictionary*) escrowRecordToDictionary:(OTEscrowRecord*)escrowRecord +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; + dictionary[getkSecureBackupEscrowDateKey()] = [NSDate dateWithTimeIntervalSince1970: escrowRecord.creationDate]; + + dictionary[kCliqueEscrowServiceRecordMetadataKey] = [OTEscrowTranslation metadataToDictionary: escrowRecord.escrowInformationMetadata]; + + dictionary[getkSecureBackupRemainingAttemptsKey()] = [[NSNumber alloc]initWithUnsignedLongLong:escrowRecord.remainingAttempts]; + dictionary[getkSecureBackupRecordLabelKey()] = escrowRecord.label; + dictionary[getkSecureBackupRecordStatusKey()] = escrowRecord.recordStatus == OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID ? @"valid" : @"invalid"; + dictionary[kCliqueSecureBackupSilentAttemptAllowed] = [[NSNumber alloc] initWithUnsignedLongLong: escrowRecord.silentAttemptAllowed]; + dictionary[kCliqueSecureBackupFederationID] = escrowRecord.federationId; + dictionary[kCliqueSecureBackupExpectedFederationID] = escrowRecord.expectedFederationId; + dictionary[getkSecureBackupRecordIDKey()] = escrowRecord.recordId; + dictionary[getkSecureBackupPeerInfoSerialNumberKey()] = escrowRecord.serialNumber; + dictionary[getkSecureBackupCoolOffEndKey()] = @(escrowRecord.coolOffEnd); + dictionary[getkSecureBackupRecoveryStatusKey()] = @(escrowRecord.recoveryStatus); + + return dictionary; +} + ++ (OTICDPRecordContext*)dictionaryToCDPRecordContext:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTICDPRecordContext* context = [[OTICDPRecordContext alloc] init]; + context.authInfo = [OTEscrowTranslation dictionaryToEscrowAuthenticationInfo:dictionary]; + context.cdpInfo = [OTEscrowTranslation dictionaryToCDPRecoveryInformation:dictionary]; + + return context; +} + ++ (NSDictionary*)CDPRecordContextToDictionary:(OTICDPRecordContext*)context +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + + [dictionary addEntriesFromDictionary:[OTEscrowTranslation escrowAuthenticationInfoToDictionary:context.authInfo]]; + [dictionary addEntriesFromDictionary:[OTEscrowTranslation cdpRecoveryInformationToDictionary:context.cdpInfo]]; + + return dictionary; +} + ++ (BOOL)supportedRestorePath:(OTICDPRecordContext *)cdpContext +{ + return (cdpContext.authInfo.idmsRecovery == false + && (cdpContext.authInfo.fmipUuid == nil || [cdpContext.authInfo.fmipUuid isEqualToString:@""]) + && cdpContext.authInfo.fmipRecovery == false + && (cdpContext.cdpInfo.recoveryKey == nil || [cdpContext.cdpInfo.recoveryKey isEqualToString:@""]) + && cdpContext.cdpInfo.usePreviouslyCachedRecoveryKey == false); +} + +@end + diff --git a/keychain/OctagonTrust/OctagonTrust.h b/keychain/OctagonTrust/OctagonTrust.h new file mode 100644 index 00000000..72d31de3 --- /dev/null +++ b/keychain/OctagonTrust/OctagonTrust.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if __OBJC2__ + +#import +#import +#import +#import +#import +#import +#import +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +//! Project version number for OctagonTrust. +FOUNDATION_EXPORT double OctagonTrustVersionNumber; + +//! Project version string for OctagonTrust. +FOUNDATION_EXPORT const unsigned char OctagonTrustVersionString[]; + +extern NSString* OTCKContainerName; + +@interface OTConfigurationContext(Framework) +@property (nonatomic, copy, nullable) OTEscrowAuthenticationInformation* escrowAuth; +@end + +@interface OTClique(Framework) + +/* * + * @abstract Fetch recommended iCDP escrow records + * + * @param data, context containing parameters to setup OTClique + * @param error, error gets filled if something goes horribly wrong + * + * @return array of escrow records that can get a device back into trust + */ ++ (NSArray* _Nullable)fetchEscrowRecords:(OTConfigurationContext*)data error:(NSError**)error; + + +/* * + * @abstract Fetch all iCDP escrow records + * + * @param data, context containing parameters to setup OTClique + * @param error, error gets filled if something goes horribly wrong + * + * @return array of all escrow records (viable and legacy) + */ ++ (NSArray* _Nullable)fetchAllEscrowRecords:(OTConfigurationContext*)data error:(NSError**)error; + +/* * + * @abstract Perform escrow recovery of a particular record (not silent) + * + * @param data, context containing parameters to setup OTClique + * @param cdpContext, context containing parameters used in recovery + * @param escrowRecord, the chosen escrow record to recover from + * @param error, error gets filled if something goes horribly wrong + * + * @return clique, returns a new clique instance + */ ++ (instancetype _Nullable)performEscrowRecovery:(OTConfigurationContext*)data + cdpContext:(OTICDPRecordContext*)cdpContext + escrowRecord:(OTEscrowRecord*)escrowRecord + error:(NSError**)error; + +/* * + * @abstract Perform a silent escrow recovery + * + * @param data, context containing parameters to setup OTClique + * @param cdpContext, context containing parameters used in recovery + * @param allRecords, all fetched escrow records + * @param error, error gets filled if something goes horribly wrong + * @return clique, returns a new clique instance + */ ++ (instancetype _Nullable)performSilentEscrowRecovery:(OTConfigurationContext*)data + cdpContext:(OTICDPRecordContext*)cdpContext + allRecords:(NSArray*)allRecords + error:(NSError**)error; + ++ (BOOL) invalidateEscrowCache:(OTConfigurationContext*)data error:(NSError**)error; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/keychain/OctagonTrust/OctagonTrust.m b/keychain/OctagonTrust/OctagonTrust.m new file mode 100644 index 00000000..8d2aef4b --- /dev/null +++ b/keychain/OctagonTrust/OctagonTrust.m @@ -0,0 +1,659 @@ +/* +* Copyright (c) 2020 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +#if __OBJC2__ + +#import + +#import "OctagonTrust.h" +#import +#import +#import "OTEscrowTranslation.h" + +#import +#import +#import +#import "keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h" +#import "keychain/ot/OTDefines.h" +#import "keychain/ot/OTControl.h" +#import "keychain/ot/OTClique+Private.h" +#import +#include + +SOFT_LINK_FRAMEWORK(PrivateFrameworks, KeychainCircle); +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CloudServices); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +SOFT_LINK_CLASS(CloudServices, SecureBackup); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupErrorDomain, NSErrorDomain); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupiCDPRecordsKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupMetadataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordIDKey, NSString*); + +SOFT_LINK_CONSTANT(CloudServices, kEscrowServiceRecordDataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupKeybagDigestKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBagPasswordKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordLabelKey, NSString*); + +#pragma clang diagnostic pop + +static NSString * const kOTEscrowAuthKey = @"kOTEscrowAuthKey"; +NSString* OTCKContainerName = @"com.apple.security.keychain"; + +@implementation OTConfigurationContext(Framework) + +@dynamic escrowAuth; + +-(void) setEscrowAuth:(id)e +{ + objc_setAssociatedObject(self, (__bridge const void * _Nonnull)(kOTEscrowAuthKey), e, OBJC_ASSOCIATION_ASSIGN); + +} +- (id) escrowAuth +{ + return objc_getAssociatedObject(self, (__bridge const void * _Nonnull)(kOTEscrowAuthKey)); +} + +@end + +@implementation OTClique(Framework) + ++ (NSArray*)filterViableSOSRecords:(NSArray*)nonViable +{ + NSMutableArray* viableSOS = [NSMutableArray array]; + for(OTEscrowRecord* record in nonViable) { + if (record.viabilityStatus == OTEscrowRecord_SOSViability_SOS_VIABLE) { + [viableSOS addObject:record]; + } + } + + return viableSOS; +} + +/* + * desired outcome from filtering on an iOS/macOS platform: + * Escrow Record data validation outcome Outcome of fetch records + Octagon Viable, SOS Viable Record gets recommended, normal Octagon and SOS join + Octagon Viable, SOS Doesn't work Record gets recommended, normal Octagon join, SOS reset + Octagon Doesn't work, SOS Viable Record gets recommended, Octagon reset, normal SOS join + Octagon Doesn't work, SOS Doesn't work no records recommended. Force user to reset all protected data + + * desired outcome from filtering on an watchOS/tvOS/etc: + Escrow Record data validation outcome Outcome of fetch records + Octagon Viable, SOS Viable Record gets recommended, normal Octagon and SOS noop + Octagon Viable, SOS Doesn't work Record gets recommended, normal Octagon join, SOS noop + Octagon Doesn't work, SOS Viable Record gets recommended, Octagon reset, SOS noop + Octagon Doesn't work, SOS Doesn't work no records recommended. Force user to reset all protected data +*/ + ++ (NSArray* _Nullable)filterRecords:(NSArray*)allRecords +{ + NSMutableArray* viable = [NSMutableArray array]; + NSMutableArray* partial = [NSMutableArray array]; + NSMutableArray* nonViable = [NSMutableArray array]; + + for (OTEscrowRecord* record in allRecords) { + if(record.recordViability == OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE && + record.escrowInformationMetadata.bottleId != nil && + [record.escrowInformationMetadata.bottleId length] != 0) { + [viable addObject:record]; + } else if(record.recordViability == OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE && + record.escrowInformationMetadata.bottleId != nil && + [record.escrowInformationMetadata.bottleId length] != 0) { + [partial addObject:record]; + } else { + [nonViable addObject:record]; + } + } + + for(OTEscrowRecord* record in viable) { + secnotice("octagontrust-fetchescrowrecords", "viable record: %@ serial:%@ bottleID:%@ silent allowed:%d", + record.label, + record.escrowInformationMetadata.serial, + record.escrowInformationMetadata.bottleId, + (int)record.silentAttemptAllowed); + } + for(OTEscrowRecord* record in partial) { + secnotice("octagontrust-fetchescrowrecords", "partially viable record: %@ serial:%@ bottleID:%@ silent allowed:%d", + record.label, + record.escrowInformationMetadata.serial, + record.escrowInformationMetadata.bottleId, + (int)record.silentAttemptAllowed); + } + for(OTEscrowRecord* record in nonViable) { + secnotice("octagontrust-fetchescrowrecords", "nonviable record: %@ serial:%@ bottleID:%@ silent allowed:%d", + record.label, + record.escrowInformationMetadata.serial, + record.escrowInformationMetadata.bottleId, + (int)record.silentAttemptAllowed); + } + + if ([viable count] > 0) { + secnotice("octagontrust-fetchescrowrecords", "Returning %d viable records", (int)[viable count]); + return viable; + } + + if ([partial count] > 0) { + secnotice("octagontrust-fetchescrowrecords", "Returning %d partially viable records", (int)[partial count]); + return partial; + } + + if (OctagonPlatformSupportsSOS()) { + NSArray* viableSOSRecords = [self filterViableSOSRecords:nonViable]; + secnotice("octagontrust-fetchescrowrecords", "Returning %d sos viable records", (int)[viableSOSRecords count]); + return viableSOSRecords; + } + + secnotice("octagontrust-fetchescrowrecords", "no viable records!"); + + return nil; +} + ++ (NSArray* _Nullable)fetchAndHandleEscrowRecords:(OTConfigurationContext*)data shouldFilter:(BOOL)shouldFiler error:(NSError**)error +{ + OctagonSignpost signPost = OctagonSignpostBegin(OctagonSignpostNameFetchEscrowRecords); + bool subTaskSuccess = false; + + NSError* localError = nil; + NSArray* escrowRecordDatas = [OTClique fetchEscrowRecordsInternal:data error:&localError]; + if(localError) { + secerror("octagontrust-fetchAndHandleEscrowRecords: failed to fetch escrow records: %@", localError); + if(error){ + *error = localError; + } + OctagonSignpostEnd(signPost, OctagonSignpostNameFetchEscrowRecords, OctagonSignpostNumber1(OctagonSignpostNameFetchEscrowRecords), (int)subTaskSuccess); + return nil; + } + + NSMutableArray* escrowRecords = [NSMutableArray array]; + + for(NSData* recordData in escrowRecordDatas){ + OTEscrowRecord* translated = [[OTEscrowRecord alloc] initWithData:recordData]; + if(translated.escrowInformationMetadata.bottleValidity == nil || [translated.escrowInformationMetadata.bottleValidity isEqualToString:@""]){ + switch(translated.recordViability) { + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE: + translated.escrowInformationMetadata.bottleValidity = @"valid"; + break; + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE: + translated.escrowInformationMetadata.bottleValidity = @"valid"; + break; + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY: + translated.escrowInformationMetadata.bottleValidity = @"invalid"; + break; + } + } + if(translated.recordId == nil || [translated.recordId isEqualToString:@""]){ + translated.recordId = [[translated.label stringByReplacingOccurrencesOfString:OTEscrowRecordPrefix withString:@""] mutableCopy]; + } + if((translated.serialNumber == nil || [translated.serialNumber isEqualToString:@""]) && translated.escrowInformationMetadata.peerInfo != nil && [translated.escrowInformationMetadata.peerInfo length] > 0) { + CFErrorRef cfError = NULL; + SOSPeerInfoRef peer = SOSPeerInfoCreateFromData(kCFAllocatorDefault, &cfError, (__bridge CFDataRef)translated.escrowInformationMetadata.peerInfo); + if(cfError != NULL){ + secnotice("octagontrust-handleEscrowRecords", "failed to create sos peer info: %@", cfError); + } else { + translated.serialNumber = (NSString*)CFBridgingRelease(SOSPeerInfoCopySerialNumber(peer)); + } + } + + [escrowRecords addObject:translated]; + } + subTaskSuccess = true; + OctagonSignpostEnd(signPost, OctagonSignpostNameFetchEscrowRecords, OctagonSignpostNumber1(OctagonSignpostNameFetchEscrowRecords), (int)subTaskSuccess); + + if (shouldFiler == YES) { + return [OTClique filterRecords:escrowRecords]; + } + + return escrowRecords; +} + ++ (NSArray* _Nullable)fetchAllEscrowRecords:(OTConfigurationContext*)data error:(NSError**)error +{ +#if OCTAGON + secnotice("octagontrust-fetchallescrowrecords", "fetching all escrow records for context :%@, altdsid:%@", data.context, data.altDSID); + return [OTClique fetchAndHandleEscrowRecords:data shouldFilter:NO error:error]; +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; +#endif +} + ++ (NSArray* _Nullable)fetchEscrowRecords:(OTConfigurationContext*)data error:(NSError**)error +{ +#if OCTAGON + if (OctagonIsOptimizationEnabled() && OctagonIsEscrowRecordFetchEnabled()) { + secnotice("octagontrust-fetchescrowrecords", "fetching filtered escrow records for context with feature flag enabled:%@, altdsid:%@", data.context, data.altDSID); + return [OTClique fetchAndHandleEscrowRecords:data shouldFilter:YES error:error]; + } else { + if ([OTClique isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return NULL; + } + + OctagonSignpost signPost = OctagonSignpostBegin(OctagonSignpostNameGetAccountInfo); + secnotice("octagontrust-fetchescrowrecords", "fetching escrow records for context with feature flag disabled:%@, altdsid:%@", data.context, data.altDSID); + id sb = data.sbd ?: [[getSecureBackupClass() alloc] init]; + + OTEscrowAuthenticationInformation *escrowAuth = nil; + NSDictionary* escrowAuthDictionary = nil; + if(data.escrowAuth != nil) { + escrowAuth = data.escrowAuth; + escrowAuthDictionary = [OTEscrowTranslation escrowAuthenticationInfoToDictionary:escrowAuth]; + } + NSDictionary* results = nil; + NSError* recoverError = [sb getAccountInfoWithInfo:escrowAuthDictionary results:&results]; + bool subTaskSuccess = false; + if(recoverError || results == nil) { + secerror("octagontrust-fetchescrowrecords: error fetching escrow records: %@", recoverError); + if(error){ + *error = recoverError; + } + OctagonSignpostEnd(signPost, OctagonSignpostNameGetAccountInfo, OctagonSignpostNumber1(OctagonSignpostNameGetAccountInfo), (int)subTaskSuccess); + return nil; + } else { + secnotice("octagontrust-fetchescrowrecords", "recovered accountWithInfo results: %@", results); + NSArray *icdpRecords = results[getkSecureBackupiCDPRecordsKey()]; + secnotice("octagontrust-fetchescrowrecords", "recovered iCDP records: %@", icdpRecords); + + NSMutableArray* records = [NSMutableArray array]; + for (NSDictionary *dictionaryRecord in icdpRecords) { + OTEscrowRecord* otEscrowRecord = [OTEscrowTranslation dictionaryToEscrowRecord:dictionaryRecord]; + [records addObject:otEscrowRecord]; + } + secnotice("octagontrust-fetchescrowrecords", "translated dictionary records to escrow record protos: %@", records); + + subTaskSuccess = true; + OctagonSignpostEnd(signPost, OctagonSignpostNameGetAccountInfo, OctagonSignpostNumber1(OctagonSignpostNameGetAccountInfo), (int)subTaskSuccess); + + return records; + } + } +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; +#endif +} + ++ (OTClique* _Nullable)handleRecoveryResults:(OTConfigurationContext*)data recoveredInformation:(NSDictionary*)recoveredInformation sosViability:(OTEscrowRecord_SOSViability)sosViability performedSilentBurn:(BOOL)performedSilentBurn recoverError:(NSError*)recoverError error:(NSError**)error +{ + if ([self isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } + + OTClique* clique = [[OTClique alloc] initWithContextData:data]; + BOOL resetToOfferingOccured = NO; + + if(recoverError) { + secnotice("octagontrust-handleRecoveryResults", "sbd escrow recovery failed: %@", recoverError); + if(recoverError.code == 40 /* kSecureBackupRestoringLegacyBackupKeychainError */ && [recoverError.domain isEqualToString:getkSecureBackupErrorDomain()]) { + if([OTClique platformSupportsSOS]) { + secnotice("octagontrust-handleRecoveryResults", "Can't restore legacy backup with no keybag. Resetting SOS to offering"); + CFErrorRef resetToOfferingError = NULL; + bool successfulReset = SOSCCResetToOffering(&resetToOfferingError); + resetToOfferingOccured = YES; + if(!successfulReset || resetToOfferingError) { + secerror("octagontrust-handleRecoveryResults: failed to reset to offering:%@", resetToOfferingError); + } else { + secnotice("octagontrust-handleRecoveryResults", "resetting SOS circle successful"); + } + CFReleaseNull(resetToOfferingError); + } else { + secnotice("octagontrust-handleRecoveryResults", "Legacy restore failed on a non-SOS platform"); + } + } else { + if(error) { + *error = recoverError; + } + return nil; + } + } + + NSError* localError = nil; + OTControl* control = nil; + + if (data.otControl) { + control = data.otControl; + } else { + control = [data makeOTControl:&localError]; + } + if (!control) { + secerror("octagontrust-handleRecoveryResults: unable to create otcontrol: %@", localError); + if (error) { + *error = localError; + } + return nil; + } + + // look for OT Bottles + NSString *bottleID = recoveredInformation[@"bottleID"]; + NSString *isValid = recoveredInformation[@"bottleValid"]; + NSData *bottledPeerEntropy = recoveredInformation[@"EscrowServiceEscrowData"][@"BottledPeerEntropy"]; + bool shouldResetOctagon = false; + + if(bottledPeerEntropy && bottleID && [isValid isEqualToString:@"valid"]){ + secnotice("octagontrust-handleRecoveryResults", "recovering from bottle: %@", bottleID); + __block NSError* restoreBottleError = nil; + OctagonSignpost bottleRestoreSignPost = performedSilentBurn ? OctagonSignpostBegin(OctagonSignpostNamePerformOctagonJoinForSilent) : OctagonSignpostBegin(OctagonSignpostNamePerformOctagonJoinForNonSilent); + + //restore bottle! + [control restore:OTCKContainerName + contextID:data.context + bottleSalt:data.altDSID + entropy:bottledPeerEntropy + bottleID:bottleID + reply:^(NSError * _Nullable restoreError) { + if(restoreError) { + secnotice("octagontrust-handleRecoveryResults", "restore bottle errored: %@", restoreError); + } else { + secnotice("octagontrust-handleRecoveryResults", "restoring bottle succeeded"); + } + restoreBottleError = restoreError; + if (performedSilentBurn) { + OctagonSignpostEnd(bottleRestoreSignPost, OctagonSignpostNamePerformOctagonJoinForSilent, OctagonSignpostNumber1(OctagonSignpostNamePerformOctagonJoinForSilent), (int)true); + } else { + OctagonSignpostEnd(bottleRestoreSignPost, OctagonSignpostNamePerformOctagonJoinForNonSilent, OctagonSignpostNumber1(OctagonSignpostNamePerformOctagonJoinForNonSilent), (int)true); + } + }]; + + if(restoreBottleError) { + if(error){ + *error = restoreBottleError; + } + return nil; + } + } else { + shouldResetOctagon = true; + } + + if(shouldResetOctagon) { + secnotice("octagontrust-handleRecoveryResults", "bottle %@ is not valid, resetting octagon", bottleID); + NSError* resetError = nil; + [clique resetAndEstablish:CuttlefishResetReasonNoBottleDuringEscrowRecovery error:&resetError]; + if(resetError) { + secerror("octagontrust-handleRecoveryResults: failed to reset octagon: %@", resetError); + if(error){ + *error = resetError; + } + return nil; + } else{ + secnotice("octagontrust-handleRecoveryResults", "reset octagon succeeded"); + } + } + + // Join SOS circle if platform is supported and we didn't previously reset SOS + if (OctagonPlatformSupportsSOS() && resetToOfferingOccured == NO) { + if (sosViability == OTEscrowRecord_SOSViability_SOS_NOT_VIABLE) { + secnotice("octagontrust-handleRecoveryResults", "Record will not allow device to join SOS. Invoking reset to offering"); + CFErrorRef resetToOfferingError = NULL; + bool successfulReset = SOSCCResetToOffering(&resetToOfferingError); + if(!successfulReset || resetToOfferingError) { + secerror("octagontrust-handleRecoveryResults: failed to reset to offering:%@", resetToOfferingError); + } else { + secnotice("octagontrust-handleRecoveryResults", "resetting SOS circle successful"); + } + CFReleaseNull(resetToOfferingError); + } else { + NSError* joinAfterRestoreError = nil; + secnotice("octagontrust-handleRecoveryResults", "attempting joinAfterRestore"); + BOOL joinAfterRestoreResult = [clique joinAfterRestore:&joinAfterRestoreError]; + if(joinAfterRestoreError || joinAfterRestoreResult == NO) { + secnotice("octagontrust-handleRecoveryResults", "failed to join after restore: %@", joinAfterRestoreError); + } else { + secnotice("octagontrust-handleRecoveryResults", "joinAfterRestore succeeded"); + } + } + } + + + // call SBD to kick off keychain data restore + id sb = data.sbd ?: [[getSecureBackupClass() alloc] init]; + NSError* restoreError = nil; + + NSMutableSet *viewsNotToBeRestored = [NSMutableSet set]; + [viewsNotToBeRestored addObject:@"iCloudIdentity"]; + [viewsNotToBeRestored addObject:@"PCS-MasterKey"]; + [viewsNotToBeRestored addObject:@"KeychainV0"]; + + NSDictionary *escrowRecords = recoveredInformation[getkEscrowServiceRecordDataKey()]; + if (escrowRecords == nil) { + secnotice("octagontrust-handleRecoveryResults", "unable to request keychain restore, record data missing"); + return clique; + } + + + NSData *keybagDigest = escrowRecords[getkSecureBackupKeybagDigestKey()]; + NSData *password = escrowRecords[getkSecureBackupBagPasswordKey()]; + if (keybagDigest == nil || password == nil) { + secnotice("octagontrust-handleRecoveryResults", "unable to request keychain restore, digest or password missing"); + return clique; + } + + BOOL haveBottledPeer = (bottledPeerEntropy && bottleID && [isValid isEqualToString:@"valid"]) || shouldResetOctagon; + [sb restoreKeychainAsyncWithPassword:password + keybagDigest:keybagDigest + haveBottledPeer:haveBottledPeer + viewsNotToBeRestored:viewsNotToBeRestored + error:&restoreError]; + + if (restoreError) { + secerror("octagontrust-handleRecoveryResults: error restoring keychain items: %@", restoreError); + } + + return clique; +} + ++ (instancetype _Nullable)performEscrowRecovery:(OTConfigurationContext*)data + cdpContext:(OTICDPRecordContext*)cdpContext + escrowRecord:(OTEscrowRecord*)escrowRecord + error:(NSError**)error +{ +#if OCTAGON + secnotice("octagontrust-performEscrowRecovery", "performEscrowRecovery invoked for context:%@, altdsid:%@", data.context, data.altDSID); + + if ([self isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } + + OctagonSignpost performEscrowRecoverySignpost = OctagonSignpostBegin(OctagonSignpostNamePerformEscrowRecovery); + bool subTaskSuccess = true; + + id sb = data.sbd ?: [[getSecureBackupClass() alloc] init]; + NSDictionary* recoveredInformation = nil; + NSError* recoverError = nil; + + BOOL supportedRestorePath = [OTEscrowTranslation supportedRestorePath:cdpContext]; + secnotice("octagontrust-performEscrowRecovery", "restore path is supported? %@", supportedRestorePath ? @"YES" : @"NO"); + + if (OctagonIsOptimizationEnabled() && supportedRestorePath) { + secnotice("octagontrust-performEscrowRecovery", "optimization flag turned on"); + OctagonSignpost recoverFromSBDSignPost = OctagonSignpostBegin(OctagonSignpostNameRecoverWithCDPContext); + recoveredInformation = [sb recoverWithCDPContext:cdpContext escrowRecord:escrowRecord error:&recoverError]; + subTaskSuccess = (recoverError == nil) ? true : false; + OctagonSignpostEnd(recoverFromSBDSignPost, OctagonSignpostNameRecoverWithCDPContext, OctagonSignpostNumber1(OctagonSignpostNameRecoverWithCDPContext), (int)subTaskSuccess); + } else { + secnotice("octagontrust-performEscrowRecovery", "optimization flag turned off"); + NSMutableDictionary* sbdRecoveryArguments = [[OTEscrowTranslation CDPRecordContextToDictionary:cdpContext] mutableCopy]; + NSDictionary* metadata = [OTEscrowTranslation metadataToDictionary:escrowRecord.escrowInformationMetadata]; + sbdRecoveryArguments[getkSecureBackupMetadataKey()] = metadata; + sbdRecoveryArguments[getkSecureBackupRecordIDKey()] = escrowRecord.recordId; + secnotice("octagontrust-performEscrowRecovery", "using sbdRecoveryArguments: %@", sbdRecoveryArguments); + + OctagonSignpost recoverFromSBDSignPost = OctagonSignpostBegin(OctagonSignpostNamePerformRecoveryFromSBD); + recoverError = [sb recoverWithInfo:sbdRecoveryArguments results:&recoveredInformation]; + subTaskSuccess = (recoverError == nil) ? true : false; + OctagonSignpostEnd(recoverFromSBDSignPost, OctagonSignpostNamePerformRecoveryFromSBD, OctagonSignpostNumber1(OctagonSignpostNamePerformRecoveryFromSBD), (int)subTaskSuccess); + } + + OTEscrowRecord_SOSViability viableForSOS = escrowRecord.viabilityStatus; + + OTClique* clique = [OTClique handleRecoveryResults:data recoveredInformation:recoveredInformation sosViability:viableForSOS performedSilentBurn:NO recoverError:recoverError error:error]; + + if(recoverError) { + subTaskSuccess = false; + OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNamePerformEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformEscrowRecovery), (int)subTaskSuccess); + } else { + OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNamePerformEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformEscrowRecovery), (int)subTaskSuccess); + } + return clique; + +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; +#endif +} + ++ (OTEscrowRecord* _Nullable) recordMatchingLabel:(NSString*)label allRecords:(NSArray*)allRecords +{ + for(OTEscrowRecord* record in allRecords) { + if ([record.label isEqualToString:label]) { + return record; + } + } + return nil; +} + ++ (instancetype _Nullable)performSilentEscrowRecovery:(OTConfigurationContext*)data + cdpContext:(OTICDPRecordContext*)cdpContext + allRecords:(NSArray*)allRecords + error:(NSError**)error +{ +#if OCTAGON + secnotice("octagontrust-performSilentEscrowRecovery", "performSilentEscrowRecovery invoked for context:%@, altdsid:%@", data.context, data.altDSID); + + if ([self isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } + + OctagonSignpost performSilentEscrowRecoverySignpost = OctagonSignpostBegin(OctagonSignpostNamePerformSilentEscrowRecovery); + bool subTaskSuccess = true; + + id sb = data.sbd ?: [[getSecureBackupClass() alloc] init]; + NSDictionary* recoveredInformation = nil; + NSError* recoverError = nil; + + BOOL supportedRestorePath = [OTEscrowTranslation supportedRestorePath:cdpContext]; + secnotice("octagontrust-performSilentEscrowRecovery", "restore path is supported? %@", supportedRestorePath ? @"YES" : @"NO"); + + if (OctagonIsOptimizationEnabled() && supportedRestorePath) { + secnotice("octagontrust-performSilentEscrowRecovery", "optimization flag turned on"); + OctagonSignpost recoverFromSBDSignPost = OctagonSignpostBegin(OctagonSignpostNameRecoverSilentWithCDPContext); + recoveredInformation = [sb recoverSilentWithCDPContext:cdpContext allRecords:allRecords error:&recoverError]; + subTaskSuccess = (recoverError == nil) ? true : false; + OctagonSignpostEnd(recoverFromSBDSignPost, OctagonSignpostNameRecoverSilentWithCDPContext, OctagonSignpostNumber1(OctagonSignpostNameRecoverSilentWithCDPContext), (int)subTaskSuccess); + } else { + secnotice("octagontrust-performSilentEscrowRecovery", "optimization flag turned off"); + NSDictionary* sbdRecoveryArguments = [OTEscrowTranslation CDPRecordContextToDictionary:cdpContext]; + + OctagonSignpost recoverFromSBDSignPost = OctagonSignpostBegin(OctagonSignpostNamePerformRecoveryFromSBD); + recoverError = [sb recoverWithInfo:sbdRecoveryArguments results:&recoveredInformation]; + subTaskSuccess = (recoverError == nil) ? true : false; + OctagonSignpostEnd(recoverFromSBDSignPost, OctagonSignpostNamePerformRecoveryFromSBD, OctagonSignpostNumber1(OctagonSignpostNamePerformRecoveryFromSBD), (int)subTaskSuccess); + } + + NSString* label = recoveredInformation[getkSecureBackupRecordLabelKey()]; + OTEscrowRecord* chosenRecord = [OTClique recordMatchingLabel:label allRecords:allRecords]; + OTEscrowRecord_SOSViability viableForSOS = chosenRecord ? chosenRecord.viabilityStatus : OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN; + + OTClique *clique = [OTClique handleRecoveryResults:data recoveredInformation:recoveredInformation sosViability:viableForSOS performedSilentBurn:YES recoverError:recoverError error:error]; + + if(recoverError) { + subTaskSuccess = false; + OctagonSignpostEnd(performSilentEscrowRecoverySignpost, OctagonSignpostNamePerformSilentEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformSilentEscrowRecovery), (int)subTaskSuccess); + } else { + OctagonSignpostEnd(performSilentEscrowRecoverySignpost, OctagonSignpostNamePerformSilentEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformSilentEscrowRecovery), (int)subTaskSuccess); + } + + return clique; + +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; +#endif +} + ++ (BOOL) invalidateEscrowCache:(OTConfigurationContext*)configurationContext error:(NSError**)error +{ +#if OCTAGON + secnotice("octagontrust-invalidateEscrowCache", "invalidateEscrowCache invoked for context:%@, altdsid:%@", configurationContext.context, configurationContext.altDSID); + __block NSError* localError = nil; + __block BOOL invalidatedCache = NO; + + OTControl *control = [configurationContext makeOTControl:&localError]; + if (!control) { + secnotice("clique-invalidateEscrowCache", "unable to create otcontrol: %@", localError); + if (error) { + *error = localError; + } + return invalidatedCache; + } + + [control invalidateEscrowCache:OTCKContainerName + contextID:configurationContext.context + reply:^(NSError * _Nullable invalidateError) { + if(invalidateError) { + secnotice("clique-invalidateEscrowCache", "invalidateEscrowCache errored: %@", invalidateError); + } else { + secnotice("clique-invalidateEscrowCache", "invalidateEscrowCache succeeded"); + invalidatedCache = YES; + } + localError = invalidateError; + }]; + + if(error && localError) { + *error = localError; + } + + secnotice("clique-invalidateEscrowCache", "invalidateEscrowCache complete"); + + return invalidatedCache; +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return NO; +#endif +} + +@end + +#endif diff --git a/keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h b/keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h new file mode 100644 index 00000000..1bd22615 --- /dev/null +++ b/keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h @@ -0,0 +1,27 @@ + +#if OCTAGON + +#ifndef OctagonTrustEscrowRecoverer_h +#define OctagonTrustEscrowRecoverer_h + +@protocol OctagonEscrowRecovererPrococol +- (NSError*)recoverWithInfo:(NSDictionary*)info results:(NSDictionary**)results; +- (NSError *)getAccountInfoWithInfo:(NSDictionary *)info results:(NSDictionary**)results; +- (NSError *)disableWithInfo:(NSDictionary *)info; +- (NSDictionary*)recoverWithCDPContext:(OTICDPRecordContext*)cdpContext + escrowRecord:(OTEscrowRecord*)escrowRecord + error:(NSError**)error; +- (NSDictionary*)recoverSilentWithCDPContext:(OTICDPRecordContext*)cdpContext + allRecords:(NSArray*)allRecords + error:(NSError**)error; +- (void)restoreKeychainAsyncWithPassword:password + keybagDigest:(NSData *)keybagDigest + haveBottledPeer:(BOOL)haveBottledPeer + viewsNotToBeRestored:(NSMutableSet *)viewsNotToBeRestored + error:(NSError **)error; + +@end + +#endif /* OctagonTrustEscrowRecoverer_h */ + +#endif // OCTAGON diff --git a/keychain/OctagonTrust/ot-tests/OctagonTrustTests+Errors.m b/keychain/OctagonTrust/ot-tests/OctagonTrustTests+Errors.m new file mode 100644 index 00000000..baf22123 --- /dev/null +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests+Errors.m @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import "OctagonTrustTests.h" + +#if OCTAGON + +NS_ASSUME_NONNULL_BEGIN + + +@implementation OctagonTrustTests (OctagonTrustTestsErrors) +- (void) testDepthCountOnErrors +{ + SecErrorSetOverrideNestedErrorCappingIsEnabled(true); + //previousError == nil case + CFErrorRef errorWithoutPreviousSet = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, &errorWithoutPreviousSet, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) errorWithoutPreviousSet, "errorWithoutPreviousSet should not be nil"); + NSDictionary *userInfo = [(__bridge NSError*)errorWithoutPreviousSet userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + NSNumber *depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + //previousError is set with a depth of 0 + CFErrorRef newError = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, errorWithoutPreviousSet, &newError, NULL, CFSTR("previousError exists!")); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 1, "depth should be 1"); + + //previousError is set with a dpeth of 1 + CFErrorRef secondError = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, newError, &secondError, NULL, CFSTR("using previous error that already has a chain")); + XCTAssertNotNil((__bridge NSError*) secondError, "secondError should not be nil"); + userInfo = [(__bridge NSError*)secondError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 2, "depth should be 2"); +} +- (void) testErrorCap +{ + SecErrorSetOverrideNestedErrorCappingIsEnabled(true); + //previousError == nil case + CFErrorRef previous= NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, &previous, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) previous, "errorWithoutPreviousSet should not be nil"); + NSDictionary *userInfo = [(__bridge NSError*)previous userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + NSNumber *depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + //stay within the cap limit + CFErrorRef newError = NULL; + for(int i = 0; i<200; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("previousError exists %d!"), i); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], i+1, "depth should be i+1"); + previous = newError; + newError = nil; + } + + //now blow the cap limit + previous = NULL; + newError = NULL; + int depthCounter = 0; + + for(int i = 0; i < 500; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("previousError exists %d!"), i); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + if (i >= 201) { + NSDictionary* previousUserInfo = [(__bridge NSError*)previous userInfo]; + NSDictionary* newErrorUserInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertTrue([previousUserInfo isEqualToDictionary:newErrorUserInfo], "newError should equal previous error"); + } + + if (i <= 199) { + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], depthCounter, "depth should be %d", depthCounter); + depthCounter++; + } else { + userInfo = [(__bridge NSError*)newError userInfo]; + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 200, "depth should be 200"); + } + + previous = newError; + newError = nil; + } +} + +- (void) testErrorCapWithFeatureFlagDisable +{ + SecErrorSetOverrideNestedErrorCappingIsEnabled(false); + //previousError == nil case + CFErrorRef previous= NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, &previous, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) previous, "errorWithoutPreviousSet should not be nil"); + NSDictionary *userInfo = [(__bridge NSError*)previous userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + NSNumber *depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + //stay within the cap limit + CFErrorRef newError = NULL; + for(int i = 0; i<200; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("previousError exists %d!"), i); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], i+1, "depth should be i+1"); + previous = newError; + newError = nil; + } + + //now blow the cap limit + previous = NULL; + newError = NULL; + + for(int i = 0; i < 500; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("previousError exists %d!"), i); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], i, "depth should be %d", i); + previous = newError; + newError = nil; + } +} + +- (void) testNestedErrorCreationUsingSameErrorParameters +{ + SecErrorSetOverrideNestedErrorCappingIsEnabled(true); + //previousError == nil case + CFErrorRef previous= NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, &previous, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) previous, "previous should not be nil"); + NSDictionary *userInfo = [(__bridge NSError*)previous userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + NSNumber *depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + //now pass the exact same error + CFErrorRef newError = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + previous = newError; + newError = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("no previous error1")); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 1, "depth should be 1"); + + previous = newError; + newError = NULL; + for(int i = 0; i < 500; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("no previous error1")); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 1, "depth should be 1"); + previous = newError; + newError = nil; + } +} + +@end +NS_ASSUME_NONNULL_END + +#endif diff --git a/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowRecords.m b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowRecords.m new file mode 100644 index 00000000..0f7fb0b3 --- /dev/null +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowRecords.m @@ -0,0 +1,722 @@ +/* +* Copyright (c) 2020 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + + +#import +#import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" +#import +#pragma clang diagnostic pop + +#import +#import "OctagonTrustTests-EscrowTestVectors.h" + +#import "keychain/ot/OTConstants.h" +#import "keychain/ot/OTManager.h" +#import "keychain/ot/OTDefines.h" +#import "keychain/ot/OTClique+Private.h" + +#import "keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h" + +#import + +#import "keychain/ckks/tests/MockCloudKit.h" +#import "keychain/ckks/tests/CKKSMockSOSPresentAdapter.h" +#import "utilities/SecCFError.h" +#import "keychain/categories/NSError+UsefulConstructors.h" + +#import "OctagonTrustTests.h" + +@implementation ProxyXPCConnection + +- (instancetype)initWithInterface:(NSXPCInterface*)interface obj:(id)obj +{ + if(self = [super init]) { + self.obj = obj; + self.serverInterface = interface; + self.listener = [NSXPCListener anonymousListener]; + + self.listener.delegate = self; + [self.listener resume]; + } + + return self; +} + +- (NSXPCConnection*)connection +{ + NSXPCConnection* connection = [[NSXPCConnection alloc] initWithListenerEndpoint:self.listener.endpoint]; + connection.remoteObjectInterface = self.serverInterface; + [connection resume]; + return connection; +} + +- (BOOL)listener:(NSXPCListener*)listener newConnection:(NSXPCConnection*)newConnection { + newConnection.exportedInterface = self.serverInterface; + newConnection.exportedObject = self.obj; + [newConnection resume]; + return true; + } + +@end + +@interface FakeOTControlEntitlementBearer : NSObject +@property NSMutableDictionary* entitlements; +-(instancetype)init; +- (nullable id)valueForEntitlement:(NSString *)entitlement; +@end + +@implementation FakeOTControlEntitlementBearer + +-(instancetype)init +{ + if(self = [super init]) { + self.entitlements = [NSMutableDictionary dictionary]; + self.entitlements[kSecEntitlementPrivateOctagonEscrow] = @YES; + } + return self; +} +-(id)valueForEntitlement:(NSString*)entitlement +{ + return self.entitlements[entitlement]; +} + +@end + +@interface OTMockSecureBackup : NSObject +@property (nonatomic) NSString * bottleID; +@property (nonatomic) NSData* entropy; + +@end + +@implementation OTMockSecureBackup + +-(instancetype) initWithBottleID:(NSString*)b entropy:(NSData*)e { + if(self = [super init]) { + self.bottleID = b; + self.entropy = e; + } + return self; +} + +- (NSError *)disableWithInfo:(NSDictionary *)info { + return nil; +} + +- (NSError *)getAccountInfoWithInfo:(NSDictionary *)info results:(NSDictionary *__autoreleasing *)results { + NSError* localError = nil; + NSData *testVectorData = [accountInfoWithInfoSample dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + *results = testVectorPlist; + + return nil; +} + +- (NSDictionary *)recoverSilentWithCDPContext:(OTICDPRecordContext *)cdpContext allRecords:(NSArray *)allRecords error:(NSError *__autoreleasing *)error { + return nil; +} + +- (NSDictionary *)recoverWithCDPContext:(OTICDPRecordContext *)cdpContext escrowRecord:(OTEscrowRecord *)escrowRecord error:(NSError *__autoreleasing *)error { + return nil; +} + +- (NSError *)recoverWithInfo:(NSDictionary *)info results:(NSDictionary *__autoreleasing *)results { + return nil; +} + +- (void)restoreKeychainAsyncWithPassword:(id)password keybagDigest:(NSData *)keybagDigest haveBottledPeer:(BOOL)haveBottledPeer viewsNotToBeRestored:(NSMutableSet *)viewsNotToBeRestored error:(NSError *__autoreleasing *)error { +} + + +@end + +@implementation OctagonTrustTests + +- (OTEscrowRecord*)createLegacyRecord +{ + OTEscrowRecord *nonViableRecord = [[OTEscrowRecord alloc] init]; + nonViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + nonViableRecord.label = [[NSUUID UUID] UUIDString]; + nonViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + nonViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY; + nonViableRecord.serialNumber = [[NSUUID UUID] UUIDString]; + nonViableRecord.silentAttemptAllowed = 1; + nonViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + nonViableRecord.escrowInformationMetadata.bottleValidity = @"invalid"; + + // It even has a bottleId! Not a useful one, though. + nonViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + return nonViableRecord; +} + +- (OTEscrowRecord*)createLegacyRecordWithSOSNotViable +{ + OTEscrowRecord *nonViableRecord = [[OTEscrowRecord alloc] init]; + nonViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + nonViableRecord.label = [[NSUUID UUID] UUIDString]; + nonViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + nonViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY; + nonViableRecord.viabilityStatus = OTEscrowRecord_SOSViability_SOS_NOT_VIABLE; + nonViableRecord.serialNumber = [[NSUUID UUID] UUIDString]; + nonViableRecord.silentAttemptAllowed = 1; + nonViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + nonViableRecord.escrowInformationMetadata.bottleValidity = @"invalid"; + + // It even has a bottleId! Not a useful one, though. + nonViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + return nonViableRecord; +} + +- (OTEscrowRecord*)createPartialRecord +{ + OTEscrowRecord *partiallyViableRecord = [[OTEscrowRecord alloc] init]; + partiallyViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + partiallyViableRecord.label = [[NSUUID UUID] UUIDString]; + partiallyViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + partiallyViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE; + partiallyViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + partiallyViableRecord.escrowInformationMetadata.bottleValidity = @"valid"; + partiallyViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + + partiallyViableRecord.serialNumber =[[NSUUID UUID] UUIDString]; + partiallyViableRecord.silentAttemptAllowed = 1; + return partiallyViableRecord; +} + +- (OTEscrowRecord*)createOctagonViableSOSViableRecord +{ + OTEscrowRecord *octagonAndSOSViableRecord = [[OTEscrowRecord alloc] init]; + octagonAndSOSViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + octagonAndSOSViableRecord.label = [[NSUUID UUID] UUIDString]; + octagonAndSOSViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + octagonAndSOSViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE; + octagonAndSOSViableRecord.viabilityStatus = OTEscrowRecord_SOSViability_SOS_VIABLE; + + octagonAndSOSViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + octagonAndSOSViableRecord.escrowInformationMetadata.bottleValidity = @"valid"; + octagonAndSOSViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + + octagonAndSOSViableRecord.serialNumber =[[NSUUID UUID] UUIDString]; + octagonAndSOSViableRecord.silentAttemptAllowed = 1; + return octagonAndSOSViableRecord; +} + +- (OTEscrowRecord*)createOctagonNotViableSOSViableRecord +{ + OTEscrowRecord *octagonAndSOSViableRecord = [[OTEscrowRecord alloc] init]; + octagonAndSOSViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + octagonAndSOSViableRecord.label = [[NSUUID UUID] UUIDString]; + octagonAndSOSViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + octagonAndSOSViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY; + octagonAndSOSViableRecord.viabilityStatus = OTEscrowRecord_SOSViability_SOS_VIABLE; + + octagonAndSOSViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + octagonAndSOSViableRecord.escrowInformationMetadata.bottleValidity = @"invalid"; + octagonAndSOSViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + + octagonAndSOSViableRecord.serialNumber =[[NSUUID UUID] UUIDString]; + octagonAndSOSViableRecord.silentAttemptAllowed = 1; + return octagonAndSOSViableRecord; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnOneRecord:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + NSError* localError = nil; + NSData *testVectorData = [accountInfoWithInfoSample dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + + NSArray *testVectorICDPRecords = testVectorPlist[@"SecureBackupAlliCDPRecords"]; + XCTAssertNotNil(testVectorICDPRecords, "should not be nil"); + + NSDictionary *testVectorRecord = testVectorICDPRecords[0]; + + OTEscrowRecord *record = [OTEscrowTranslation dictionaryToEscrowRecord:testVectorRecord]; + + NSArray *records = @[record.data]; + return records; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnMixedRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + NSError* localError = nil; + NSData *testVectorData = [accountInfoWithInfoSample dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + + NSArray *testVectorICDPRecords = testVectorPlist[@"SecureBackupAlliCDPRecords"]; + XCTAssertNotNil(testVectorICDPRecords, "should not be nil"); + + NSDictionary *testVectorRecord = testVectorICDPRecords[0]; + + OTEscrowRecord *record = [OTEscrowTranslation dictionaryToEscrowRecord:testVectorRecord]; + + NSArray *records = @[record.data, [self createLegacyRecord].data, [self createLegacyRecord].data]; + return records; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnPartiallyViableRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createPartialRecord].data, [self createPartialRecord].data]; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnOctagonViableSOSViableRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createOctagonViableSOSViableRecord].data, [self createOctagonViableSOSViableRecord].data]; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnLegacyRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createLegacyRecord].data, [self createLegacyRecord].data]; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnLegacyNonViableSOSRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createLegacyRecordWithSOSNotViable].data, [self createLegacyRecordWithSOSNotViable].data]; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnOctagonNotViableSOSViableRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createOctagonNotViableSOSViableRecord].data, [self createOctagonNotViableSOSViableRecord].data]; +} + +- (void)setUp +{ + [super setUp]; + + FakeOTControlEntitlementBearer *otControlEntitlementBearer = [[FakeOTControlEntitlementBearer alloc]init]; + id otControlEntitlementChecker = [OctagonXPCEntitlementChecker createWithManager:self.injectedOTManager entitlementBearer:otControlEntitlementBearer]; + + NSXPCInterface *interface = OTSetupControlProtocol([NSXPCInterface interfaceWithProtocol:@protocol(OTControlProtocol)]); + self.otXPCProxy = [[ProxyXPCConnection alloc] initWithInterface:interface obj: otControlEntitlementChecker]; + + self.otControl = [[OTControl alloc] initWithConnection:self.otXPCProxy.connection sync: true]; + + self.mockClique = OCMClassMock([OTClique class]); +} + +- (void)testFetchOneViableEscrowRecord +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnOneRecord:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 1, "should only return 1 record"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.label isEqualToString:@"com.apple.icdp.record"], "label should be com.apple.icdp.record"); + XCTAssertTrue([firstRecord.serialNumber isEqualToString:@"C39V209AJ9L5"], "serial number should be C39V209AJ9L5"); + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); +} + +- (void)testFetchTwoPartiallyViableEscrowRecords +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnPartiallyViableRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 2, "should only return 2 records"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE, "record viability should be partial"); + + OTEscrowRecord *secondRecord = escrowRecords[1]; + XCTAssertTrue([secondRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(secondRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE, "record viability should be partial"); +} + +- (void)testFetchViableAndLegacyEscrowRecords +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnMixedRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertEqual(escrowRecords.count, 1, "should only return 1 record"); + XCTAssertNil(localErrror, "error should be nil"); + + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.label isEqualToString:@"com.apple.icdp.record"], "label should be com.apple.icdp.record"); + XCTAssertTrue([firstRecord.serialNumber isEqualToString:@"C39V209AJ9L5"], "serial number should be C39V209AJ9L5"); + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); +} + +- (void)testFetchLegacyEscrowRecords +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnLegacyRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertEqual(escrowRecords.count, 0, "should return zero records"); + XCTAssertNil(localErrror, "error should be nil"); +} + +- (void)testFetchRecordsOctagonViableSOSUnknownViability +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnOneRecord:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 1, "should only return 1 record"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.label isEqualToString:@"com.apple.icdp.record"], "label should be com.apple.icdp.record"); + XCTAssertTrue([firstRecord.serialNumber isEqualToString:@"C39V209AJ9L5"], "serial number should be C39V209AJ9L5"); + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); + XCTAssertEqual(firstRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN, "record SOS viability should be unknown"); +} + +- (void)testFetchRecordsOctagonViableSOSViable +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnOctagonViableSOSViableRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 2, "should only return 2 records"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); + XCTAssertEqual(firstRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE, "record sos viability should be fully viable"); + + OTEscrowRecord *secondRecord = escrowRecords[1]; + XCTAssertTrue([secondRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(secondRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); + XCTAssertEqual(secondRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE, "record sos viability should be fully viable"); +} + +- (void)testFetchRecordsOctagonNotViableSOSViable +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnOctagonNotViableSOSViableRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + if (OctagonPlatformSupportsSOS()) { + XCTAssertEqual(escrowRecords.count, 2, "should only return 2 records"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"invalid"], "bottle validity should be invalid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY, "record viability should be set to legacy"); + XCTAssertEqual(firstRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE, "record sos viability should be fully viable"); + + OTEscrowRecord *secondRecord = escrowRecords[1]; + XCTAssertTrue([secondRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"invalid"], "bottle validity should be invalid"); + XCTAssertEqual(secondRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY, "record viability should be set to legacy"); + XCTAssertEqual(secondRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE, "record sos viability should be fully viable"); + } else { + XCTAssertEqual(escrowRecords.count, 0, "should return 0 records"); + + } +} + +- (void)testFetchRecordsOctagonNotViableSOSNotViable +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnLegacyNonViableSOSRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 0, "should return 0 records"); +} + +- (void)testFetchAllRecords +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnLegacyNonViableSOSRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchAllEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 2, "should return 2 records"); +} + +- (void)testFetchEscrowRecordOptimizationOff +{ + OctagonSetOptimizationEnabled(false); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.sbd = [[OTMockSecureBackup alloc]initWithBottleID:@"" entropy:[NSData data]]; + cliqueContextConfiguration.otControl = self.otControl; + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + XCTAssertNotNil(escrowRecords, "escrow records should not be nil"); + + for (OTEscrowRecord* record in escrowRecords) { + XCTAssertEqual(record.creationDate, 1580440060, "escrow record creation date should be 1580440060"); + XCTAssertNotNil(record.escrowInformationMetadata.backupKeybagDigest, "escrow record backup key bag digest should not be nil"); + XCTAssertTrue([record.label isEqualToString:@"com.apple.icdp.record"], "escrow record label should be com.apple.icdp.record"); + XCTAssertEqual(record.recordStatus, OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID, "escrow record record status should be valid"); + XCTAssertEqual(record.remainingAttempts, 10, "escrow record remaining attempts should be 10"); + XCTAssertEqual(record.silentAttemptAllowed, 1, "escrow record silent attempted allowed should be true"); + XCTAssertTrue([record.serialNumber isEqualToString:@"C39V209AJ9L5"], "escrow record serial number should be equal"); + XCTAssertTrue([record.recordId isEqualToString:@"sNs6voV0N35D/T91SuGmJnGO29"], "escrow record record id should be true"); + XCTAssertEqual(record.silentAttemptAllowed, 1, "escrow record silent attempted allowed should be true"); + + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceColor isEqualToString: @"1"], "escrow record device color should be 1"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceEnclosureColor isEqualToString:@"1"], "escrow record "); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceMid isEqualToString:@"yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X"], "escrow record MID should be yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceModel isEqualToString:@"iPhone 8 Plus"], "escrow record device model should be iPhone 8 Plus"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceModelClass isEqualToString: @"iPhone"], "escrow record model calss should be iPhone"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceModelVersion isEqualToString:@"iPhone10,5"], "escrow record model version should be iPhone10,5"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceName isEqualToString:@"iPhone"], "escrow record device name should be iPhone "); + XCTAssertEqual(record.escrowInformationMetadata.clientMetadata.secureBackupMetadataTimestamp, 1580440060, "escrow record timestamp should be 1580440060"); + XCTAssertEqual(record.escrowInformationMetadata.clientMetadata.secureBackupNumericPassphraseLength, 6, "escrow record passphrase length should be 6"); + XCTAssertEqual(record.escrowInformationMetadata.clientMetadata.secureBackupUsesComplexPassphrase, 1, "escrow record uses complex passphrase should be 1"); + XCTAssertEqual(record.escrowInformationMetadata.clientMetadata.secureBackupUsesNumericPassphrase, 1, "escrow record uses numeric passphrase should be 1"); + XCTAssertNotNil(record.escrowInformationMetadata.escrowedSpki, "escrow record escrowed spki should not be nil"); + XCTAssertNotNil(record.escrowInformationMetadata.peerInfo, "escrow record peer info should be not nil"); + XCTAssertEqual(record.escrowInformationMetadata.secureBackupTimestamp, 1580440060, "escrow record timestamp should be 1580440060"); + XCTAssertEqual(record.escrowInformationMetadata.secureBackupUsesMultipleIcscs, 1, "escrow record uses multiple icscs should be 1"); + + NSData *testVectorData = [accountInfoWithInfoSample dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localErrror]; + + //now translate back to dictionary! + NSDictionary *translatedBackToDictionary = [OTEscrowTranslation escrowRecordToDictionary:record]; + XCTAssertNotNil(translatedBackToDictionary, "should not be nil"); + + NSArray *testVectorICDPRecords = testVectorPlist[@"SecureBackupAlliCDPRecords"]; + XCTAssertNotNil(testVectorICDPRecords, "should not be nil"); + + NSDictionary *testVectorRecord = testVectorICDPRecords[0]; + XCTAssertNotNil(testVectorRecord, "should not be nil"); + XCTAssertTrue([testVectorRecord[@"SecureBackupEscrowDate"] isEqualToDate: translatedBackToDictionary[@"SecureBackupEscrowDate"]], "should be equal"); + XCTAssertTrue([testVectorRecord[@"recordStatus"] isEqualToString:translatedBackToDictionary[@"recordStatus"]], "should be equal"); + XCTAssertTrue([testVectorRecord[@"silentAttemptAllowed"] isEqualToNumber:translatedBackToDictionary[@"silentAttemptAllowed"]], "should be equal"); + + XCTAssertTrue([testVectorRecord[@"peerInfoSerialNumber"] isEqualToString:translatedBackToDictionary[@"peerInfoSerialNumber"]], "should be equal"); + XCTAssertTrue([testVectorRecord[@"recordID"] isEqualToString:translatedBackToDictionary[@"recordID"]], "should be equal"); + + NSDictionary *testVectorMetadata = testVectorRecord[@"metadata"]; + XCTAssertNotNil(testVectorMetadata, "should not be nil"); + + NSDictionary *translatedMetadata = translatedBackToDictionary[@"metadata"]; + XCTAssertNotNil(translatedMetadata, "should not be nil"); + + XCTAssertTrue([testVectorMetadata[@"com.apple.securebackup.timestamp"] isEqualToString: translatedMetadata[@"com.apple.securebackup.timestamp"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"bottleID"] isEqualToString:translatedMetadata[@"bottleID"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"escrowedSPKI"] isEqualToData:translatedMetadata[@"escrowedSPKI"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"SecureBackupUsesMultipleiCSCs"] isEqualToNumber: translatedMetadata[@"SecureBackupUsesMultipleiCSCs"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"peerInfo"] isEqualToData:translatedMetadata[@"peerInfo"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"BackupKeybagDigest"] isEqualToData: translatedMetadata[@"BackupKeybagDigest"]], "should be equal"); + + NSDictionary *testVectorClientMetadata = testVectorMetadata[@"ClientMetadata"]; + XCTAssertNotNil(testVectorClientMetadata, "should not be nil"); + NSDictionary *translatedClientMetadata = translatedMetadata[@"ClientMetadata"]; + XCTAssertNotNil(translatedClientMetadata, "should not be nil"); + XCTAssertTrue([testVectorClientMetadata isEqualToDictionary:translatedClientMetadata], "should be equal"); + } + +} + +- (void)testCDPRecordContextTranslation +{ + NSError* localError = nil; + NSData *testVectorData = [testCDPRemoteRecordContextTestVector dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + XCTAssertNotNil(testVectorPlist, "testVectorPlist should not be nil"); + OTICDPRecordContext *cdpContext = [OTEscrowTranslation dictionaryToCDPRecordContext:testVectorPlist]; + XCTAssertNotNil(cdpContext, "cdpContext should not be nil"); + XCTAssertTrue([cdpContext.authInfo.authenticationAppleid isEqualToString:@"anna.535.paid@icloud.com"], "authenticationAppleid should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationAuthToken isEqualToString:@"EAAbAAAABLwIAAAAAF5PGvkRDmdzLmljbG91ZC5hdXRovQBx359KJvlZTwe1q6BwXvK4gQUYo2WQbKT8UDtn8rcA6FvEYBANaAk1ofWx/bcfB4pcLiXR3Y0kncELCwFCEEpqpZS+klD9AY1oT9zW6VtyOgQTZJ4mfWz103+FoMh8nLJAVpYVfM/UjsiNsLfTX+rUmevfeA=="], "authenticationAuthToken should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationDsid isEqualToString:@"16187698960"], "authenticationDsid should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationEscrowproxyUrl isEqualToString:@"https://p97-escrowproxy.icloud.com:443"], "authenticationEscrowproxyUrl should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationIcloudEnvironment isEqualToString:@"PROD"], "authenticationIcloudEnvironment should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationPassword isEqualToString: @"PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET"], "authenticationPassword should match"); + XCTAssertFalse(cdpContext.authInfo.fmipRecovery, "fmipRecovery should be false"); + XCTAssertFalse(cdpContext.authInfo.idmsRecovery, "idmsRecovery should be false"); + + + XCTAssertTrue(cdpContext.cdpInfo.containsIcdpData, "containsIcdpData should be true"); + XCTAssertFalse(cdpContext.cdpInfo.silentRecoveryAttempt, "silentRecoveryAttempt should be false"); + XCTAssertTrue(cdpContext.cdpInfo.usesMultipleIcsc, "usesMultipleIcsc should match"); + XCTAssertFalse(cdpContext.cdpInfo.useCachedSecret, "useCachedSecret should be false"); + XCTAssertFalse(cdpContext.cdpInfo.usePreviouslyCachedRecoveryKey, "usePreviouslyCachedRecoveryKey should be false"); + XCTAssertNil(cdpContext.cdpInfo.recoveryKey, "recoveryKey should be nil"); + XCTAssertTrue([cdpContext.cdpInfo.recoverySecret isEqualToString:@"333333"], "recoverySecret should be 333333"); + + NSDictionary *translateBack = [OTEscrowTranslation CDPRecordContextToDictionary:cdpContext]; + XCTAssertNotNil(translateBack, "translateBack should not be nil"); + + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationAppleID"]) isEqualToString:@"anna.535.paid@icloud.com"], "SecureBackupAuthenticationAppleID should be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationAuthToken"]) isEqualToString:@"EAAbAAAABLwIAAAAAF5PGvkRDmdzLmljbG91ZC5hdXRovQBx359KJvlZTwe1q6BwXvK4gQUYo2WQbKT8UDtn8rcA6FvEYBANaAk1ofWx/bcfB4pcLiXR3Y0kncELCwFCEEpqpZS+klD9AY1oT9zW6VtyOgQTZJ4mfWz103+FoMh8nLJAVpYVfM/UjsiNsLfTX+rUmevfeA=="], "SecureBackupAuthenticationAuthToken should be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationDSID"]) isEqualToString:@"16187698960"], "SecureBackupAuthenticationDSIDshould be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationEscrowProxyURL"]) isEqualToString:@"https://p97-escrowproxy.icloud.com:443"], "SecureBackupAuthenticationEscrowProxyURL be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationPassword"]) isEqualToString:@"PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET"], "SecureBackupAuthenticationPassword be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationiCloudEnvironment"]) isEqualToString:@"PROD"], "SecureBackupAuthenticationiCloudEnvironment be equal"); + XCTAssertTrue(translateBack[@"SecureBackupContainsiCDPData"], "SecureBackupContainsiCDPData true"); + XCTAssertTrue([translateBack[@"SecureBackupFMiPRecoveryKey"] isEqualToNumber:@NO], "SecureBackupFMiPRecoveryKey is false"); + XCTAssertTrue([translateBack[@"SecureBackupIDMSRecovery"] isEqualToNumber:@NO], "SecureBackupIDMSRecovery false"); + XCTAssertTrue([translateBack[@"SecureBackupPassphrase"] isEqualToString: @"333333"], "SecureBackupPassphrase true"); + XCTAssertTrue([translateBack[@"SecureBackupSilentRecoveryAttempt"] isEqualToNumber:@NO], "SecureBackupSilentRecoveryAttempt false"); + XCTAssertTrue([translateBack[@"SecureBackupUseCachedPassphrase"] isEqualToNumber:@NO], "SecureBackupUseCachedPassphrase false"); + XCTAssertTrue([translateBack[@"SecureBackupUsesMultipleiCSCs"] isEqualToNumber:@YES], "SecureBackupUsesMultipleiCSCs true"); + XCTAssertTrue([translateBack[@"SecureBackupUsesRecoveryKey"] isEqualToNumber:@NO], "SecureBackupUsesRecoveryKey false"); +} + +- (void)testCDPSilentRecordContextTranslation +{ + NSError* localError = nil; + NSData *testVectorData = [CDPRecordContextSilentTestVector dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + XCTAssertNotNil(testVectorPlist, "testVectorPlist should not be nil"); + OTICDPRecordContext *cdpContext = [OTEscrowTranslation dictionaryToCDPRecordContext:testVectorPlist]; + XCTAssertNotNil(cdpContext, "cdpContext should not be nil"); + XCTAssertTrue([cdpContext.authInfo.authenticationAppleid isEqualToString:@"anna.535.paid@icloud.com"], "authenticationAppleid should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationAuthToken isEqualToString:@"EAAbAAAABLwIAAAAAF5PHOERDmdzLmljbG91ZC5hdXRovQDwjwm2kXoklEtO/xeL3YCPlBr7IkVuV26y2BfLco+QhJFm4VhgFZSBFUg5l4g/uV2DG95xadgk0+rWLhyXDGZwHN2V9jju3eo6sRwGVj4g5iBFStuj4unTKylu3iFkNSKtTMXAyBXpn4EiRX+8dwumC2FKkA=="], "authenticationAuthToken should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationDsid isEqualToString:@"16187698960"], "authenticationDsid should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationEscrowproxyUrl isEqualToString:@"https://p97-escrowproxy.icloud.com:443"], "authenticationEscrowproxyUrl should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationIcloudEnvironment isEqualToString:@"PROD"], "authenticationIcloudEnvironment should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationPassword isEqualToString: @"PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET"], "authenticationPassword should match"); + XCTAssertFalse(cdpContext.authInfo.fmipRecovery, "fmipRecovery should be false"); + XCTAssertFalse(cdpContext.authInfo.idmsRecovery, "idmsRecovery should be false"); + + + XCTAssertTrue(cdpContext.cdpInfo.containsIcdpData, "containsIcdpData should be true"); + XCTAssertTrue(cdpContext.cdpInfo.silentRecoveryAttempt, "silentRecoveryAttempt should be true"); + XCTAssertTrue(cdpContext.cdpInfo.usesMultipleIcsc, "usesMultipleIcsc should match"); + XCTAssertFalse(cdpContext.cdpInfo.useCachedSecret, "useCachedSecret should be false"); + XCTAssertFalse(cdpContext.cdpInfo.usePreviouslyCachedRecoveryKey, "usePreviouslyCachedRecoveryKey should be false"); + XCTAssertNil(cdpContext.cdpInfo.recoveryKey, "recoveryKey should be nil"); + XCTAssertTrue([cdpContext.cdpInfo.recoverySecret isEqualToString:@"333333"], "recoverySecret should be 333333"); + + NSDictionary *translateBack = [OTEscrowTranslation CDPRecordContextToDictionary:cdpContext]; + XCTAssertNotNil(translateBack, "translateBack should not be nil"); + + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationAppleID"]) isEqualToString:@"anna.535.paid@icloud.com"], "SecureBackupAuthenticationAppleID should be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationAuthToken"]) isEqualToString:@"EAAbAAAABLwIAAAAAF5PHOERDmdzLmljbG91ZC5hdXRovQDwjwm2kXoklEtO/xeL3YCPlBr7IkVuV26y2BfLco+QhJFm4VhgFZSBFUg5l4g/uV2DG95xadgk0+rWLhyXDGZwHN2V9jju3eo6sRwGVj4g5iBFStuj4unTKylu3iFkNSKtTMXAyBXpn4EiRX+8dwumC2FKkA=="], "SecureBackupAuthenticationAuthToken should be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationDSID"]) isEqualToString:@"16187698960"], "SecureBackupAuthenticationDSIDshould be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationEscrowProxyURL"]) isEqualToString:@"https://p97-escrowproxy.icloud.com:443"], "SecureBackupAuthenticationEscrowProxyURL be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationPassword"]) isEqualToString:@"PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET"], "SecureBackupAuthenticationPassword be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationiCloudEnvironment"]) isEqualToString:@"PROD"], "SecureBackupAuthenticationiCloudEnvironment be equal"); + XCTAssertTrue(translateBack[@"SecureBackupContainsiCDPData"], "SecureBackupContainsiCDPData true"); + XCTAssertTrue([translateBack[@"SecureBackupFMiPRecoveryKey"] isEqualToNumber:@NO], "SecureBackupFMiPRecoveryKey is false"); + XCTAssertTrue([translateBack[@"SecureBackupIDMSRecovery"] isEqualToNumber:@NO], "SecureBackupIDMSRecovery false"); + XCTAssertTrue([translateBack[@"SecureBackupPassphrase"] isEqualToString: @"333333"], "SecureBackupPassphrase true"); + XCTAssertTrue([translateBack[@"SecureBackupSilentRecoveryAttempt"] isEqualToNumber:@YES], "SecureBackupSilentRecoveryAttempt true"); + XCTAssertTrue([translateBack[@"SecureBackupUseCachedPassphrase"] isEqualToNumber:@NO], "SecureBackupUseCachedPassphrase false"); + XCTAssertTrue([translateBack[@"SecureBackupUsesMultipleiCSCs"] isEqualToNumber:@YES], "SecureBackupUsesMultipleiCSCs true"); + XCTAssertTrue([translateBack[@"SecureBackupUsesRecoveryKey"] isEqualToNumber:@NO], "SecureBackupUsesRecoveryKey false"); +} + +@end + diff --git a/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowTestVectors.h b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowTestVectors.h new file mode 100644 index 00000000..aa9ddc7a --- /dev/null +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowTestVectors.h @@ -0,0 +1,415 @@ +/* +* Copyright (c) 2020 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +#if OCTAGON + +NSString *accountInfoWithInfoSample = @"\ +\ +\ +\ + SecureBackupAccountIsHighSecurity\ + \ + SecureBackupAlliCDPRecords\ + \ + \ + SecureBackupEscrowDate\ + 2020-01-31T03:07:40Z\ + SecureBackupRemainingAttempts\ + 10\ + encodedMetadata\ + YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ==\ + label\ + com.apple.icdp.record\ + metadata\ + \ + BackupKeybagDigest\ + \ + yFGtyxY2ZzDt0j/26GkNSmrgVnY=\ + \ + ClientMetadata\ + \ + SecureBackupMetadataTimestamp\ + 2020-01-31 03:07:40\ + SecureBackupNumericPassphraseLength\ + 6\ + SecureBackupUsesComplexPassphrase\ + \ + SecureBackupUsesNumericPassphrase\ + \ + device_color\ + 1\ + device_enclosure_color\ + 1\ + device_mid\ + yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X\ + device_model\ + iPhone 8 Plus\ + device_model_class\ + iPhone\ + device_model_version\ + iPhone10,5\ + device_name\ + iPhone\ + device_platform\ + 1\ + \ + SecureBackupUsesMultipleiCSCs\ + \ + bottleID\ + DD5E3F9F-3702-4789-8ACF-2D28BC86A94C\ + build\ + 18A214\ + com.apple.securebackup.timestamp\ + 2020-01-31 03:07:40\ + escrowedSPKI\ + \ + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC\ + Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b\ + 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj\ + Ug+fyh0c0xABOXt2Kdup7IYTGrzn\ + \ + peerInfo\ + \ + MIIErjGCBGEwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsM\ + D0FwcGxpY2F0aW9uRGF0ZQQYGBYyMDIwMDEzMDIyNDEy\ + Ni4yODAwNTdaMFUMEFB1YmxpY1NpZ25pbmdLZXkEQQTl\ + vn18gJwjGum8v3Chn9Yh5HM/VRLGuq6HAV4KyxlUm+w8\ + uF80+32tY3/l9nKOmU61691beekwSWcfF+mDTGPrMFgM\ + D0FwcGxpY2F0aW9uVXNpZwRFMEMCIGOIXWe83FnflHu+\ + yShdjivfTaPDFHvX+RYNgMy74iSnAh9OHeQzmDchZOi0\ + 81lbhw/9rjEe8wEmozXX126RUOe/MHAMDURldmljZUdl\ + c3RhbHQxXzATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlP\ + U1ZlcnNpb24MBjE4QTIxNDAWDAxDb21wdXRlck5hbWUM\ + BmlQaG9uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJzaW9u\ + AgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEE\ + oLohYY3GpRSv20AT67jLJ1s2dKr+1bT8JoY23QkCeJgj\ + GNb+vutEQhLFjLPsENtNE7+NA7wgac0QAXLDO9H/LbpN\ + UP8DF1Q0NpFX4JiFZqG876jS8HEgR6VOOJzhJzUZMH8M\ + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEDRnS\ + sPQ/mTEl5dmMEYnQYhcm9hiPzBnQ0ghQzb70auYoPbCR\ + xjCoG7MCpbb+4JGM4L74OdbJZJbTtHeZ0JtCbqo93ZyI\ + fULWz131HsOyxowTSSI9yDiPAyXZz6nRnnvnMIIB+AwQ\ + VjJEaWN0aW9uYXJ5RGF0YQSCAeIxggHeMBAMDEVzY3Jv\ + d1JlY29yZAUAMBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw\ + OUFKOUw1MC0MCUJhY2t1cEtleQQgZlnxFs5NJO9YlR/4\ + SDWH+e9rD/+Jf7lWWjMoTW9+n68wYAwMTWFjaGluZUlE\ + S2V5DFB5V25JOHZkTmc2RVdheWVXL0ZQNGNEWlJzZTNM\ + TW44UHhnL3gvc1B6WkpJUzVjczNSS280L3N0T1c0Nm5R\ + OThpTmxwU0hyblIwa2ZzYlIzWDCCARkMBVZpZXdz0YIB\ + DgwHQXBwbGVUVgwHSG9tZUtpdAwHUENTLUZERQwJUENT\ + LU5vdGVzDApQQ1MtQmFja3VwDApQQ1MtRXNjcm93DApQ\ + Q1MtUGhvdG9zDAtCYWNrdXBCYWdWMAwLUENTLVNoYXJp\ + bmcMDE5hbm9SZWdpc3RyeQwMUENTLUNsb3VkS2l0DAxQ\ + Q1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN\ + ZXNzYWdlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1pZ3Jh\ + dGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWRE\ + cml2ZQwQQWNjZXNzb3J5UGFpcmluZwwQQ29udGludWl0\ + eVVubG9jawRHMEUCIES5okyKP4YMZqDjIGRMoLE83SYh\ + zjEyOvGPA0BoF6ViAiEAh6/dd57K+JBWmGXd4v4qGELp\ + vAeSjqcRUfdLtQj4DxI=\ + \ + serial\ + C39V209AJ9L5\ + \ + osVersion\ + 18A214\ + peerInfoSerialNumber\ + C39V209AJ9L5\ + recordID\ + sNs6voV0N35D/T91SuGmJnGO29\ + recordStatus\ + valid\ + silentAttemptAllowed\ + \ + \ + \ + SecureBackupContainsiCloudIdentity\ + \ + SecureBackupEnabled\ + \ + SecureBackupEscrowTrustStatus\ + 0\ + SecureBackupRecoveryRequiresVerificationToken\ + \ + SecureBackupUsesRecoveryKey\ + \ + SecureBackupiCDPRecords\ + \ + \ + SecureBackupEscrowDate\ + 2020-01-31T03:07:40Z\ + SecureBackupRemainingAttempts\ + 10\ + encodedMetadata\ + YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ==\ + label\ + com.apple.icdp.record\ + metadata\ + \ + BackupKeybagDigest\ + \ + yFGtyxY2ZzDt0j/26GkNSmrgVnY=\ + \ + ClientMetadata\ + \ + SecureBackupMetadataTimestamp\ + 2020-01-31 03:07:40\ + SecureBackupNumericPassphraseLength\ + 6\ + SecureBackupUsesComplexPassphrase\ + \ + SecureBackupUsesNumericPassphrase\ + \ + device_color\ + 1\ + device_enclosure_color\ + 1\ + device_mid\ + yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X\ + device_model\ + iPhone 8 Plus\ + device_model_class\ + iPhone\ + device_model_version\ + iPhone10,5\ + device_name\ + iPhone\ + device_platform\ + 1\ + \ + SecureBackupUsesMultipleiCSCs\ + \ + bottleID\ + DD5E3F9F-3702-4789-8ACF-2D28BC86A94C\ + bottleValid\ + valid\ + build\ + 18A214\ + com.apple.securebackup.timestamp\ + 2020-01-31 03:07:40\ + escrowedSPKI\ + \ + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC\ + Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b\ + 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj\ + Ug+fyh0c0xABOXt2Kdup7IYTGrzn\ + \ + peerInfo\ + \ + MIIErjGCBGEwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsM\ + D0FwcGxpY2F0aW9uRGF0ZQQYGBYyMDIwMDEzMDIyNDEy\ + Ni4yODAwNTdaMFUMEFB1YmxpY1NpZ25pbmdLZXkEQQTl\ + vn18gJwjGum8v3Chn9Yh5HM/VRLGuq6HAV4KyxlUm+w8\ + uF80+32tY3/l9nKOmU61691beekwSWcfF+mDTGPrMFgM\ + D0FwcGxpY2F0aW9uVXNpZwRFMEMCIGOIXWe83FnflHu+\ + yShdjivfTaPDFHvX+RYNgMy74iSnAh9OHeQzmDchZOi0\ + 81lbhw/9rjEe8wEmozXX126RUOe/MHAMDURldmljZUdl\ + c3RhbHQxXzATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlP\ + U1ZlcnNpb24MBjE4QTIxNDAWDAxDb21wdXRlck5hbWUM\ + BmlQaG9uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJzaW9u\ + AgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEE\ + oLohYY3GpRSv20AT67jLJ1s2dKr+1bT8JoY23QkCeJgj\ + GNb+vutEQhLFjLPsENtNE7+NA7wgac0QAXLDO9H/LbpN\ + UP8DF1Q0NpFX4JiFZqG876jS8HEgR6VOOJzhJzUZMH8M\ + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEDRnS\ + sPQ/mTEl5dmMEYnQYhcm9hiPzBnQ0ghQzb70auYoPbCR\ + xjCoG7MCpbb+4JGM4L74OdbJZJbTtHeZ0JtCbqo93ZyI\ + fULWz131HsOyxowTSSI9yDiPAyXZz6nRnnvnMIIB+AwQ\ + VjJEaWN0aW9uYXJ5RGF0YQSCAeIxggHeMBAMDEVzY3Jv\ + d1JlY29yZAUAMBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw\ + OUFKOUw1MC0MCUJhY2t1cEtleQQgZlnxFs5NJO9YlR/4\ + SDWH+e9rD/+Jf7lWWjMoTW9+n68wYAwMTWFjaGluZUlE\ + S2V5DFB5V25JOHZkTmc2RVdheWVXL0ZQNGNEWlJzZTNM\ + TW44UHhnL3gvc1B6WkpJUzVjczNSS280L3N0T1c0Nm5R\ + OThpTmxwU0hyblIwa2ZzYlIzWDCCARkMBVZpZXdz0YIB\ + DgwHQXBwbGVUVgwHSG9tZUtpdAwHUENTLUZERQwJUENT\ + LU5vdGVzDApQQ1MtQmFja3VwDApQQ1MtRXNjcm93DApQ\ + Q1MtUGhvdG9zDAtCYWNrdXBCYWdWMAwLUENTLVNoYXJp\ + bmcMDE5hbm9SZWdpc3RyeQwMUENTLUNsb3VkS2l0DAxQ\ + Q1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN\ + ZXNzYWdlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1pZ3Jh\ + dGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWRE\ + cml2ZQwQQWNjZXNzb3J5UGFpcmluZwwQQ29udGludWl0\ + eVVubG9jawRHMEUCIES5okyKP4YMZqDjIGRMoLE83SYh\ + zjEyOvGPA0BoF6ViAiEAh6/dd57K+JBWmGXd4v4qGELp\ + vAeSjqcRUfdLtQj4DxI=\ + \ + serial\ + C39V209AJ9L5\ + \ + osVersion\ + 18A214\ + peerInfoSerialNumber\ + C39V209AJ9L5\ + recordID\ + sNs6voV0N35D/T91SuGmJnGO29\ + recordStatus\ + valid\ + silentAttemptAllowed\ + \ + \ + \ + SecureBackupiCloudDataProtectionEnabled\ + \ +\ +"; + +NSString *testCDPRemoteRecordContextTestVector = @"\ +\ +\ +\ + SecureBackupAuthenticationAppleID\ + anna.535.paid@icloud.com\ + SecureBackupAuthenticationAuthToken\ + EAAbAAAABLwIAAAAAF5PGvkRDmdzLmljbG91ZC5hdXRovQBx359KJvlZTwe1q6BwXvK4gQUYo2WQbKT8UDtn8rcA6FvEYBANaAk1ofWx/bcfB4pcLiXR3Y0kncELCwFCEEpqpZS+klD9AY1oT9zW6VtyOgQTZJ4mfWz103+FoMh8nLJAVpYVfM/UjsiNsLfTX+rUmevfeA==\ + SecureBackupAuthenticationDSID\ + 16187698960\ + SecureBackupAuthenticationEscrowProxyURL\ + https://p97-escrowproxy.icloud.com:443\ + SecureBackupAuthenticationPassword\ + PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET\ + SecureBackupAuthenticationiCloudEnvironment\ + PROD\ + SecureBackupContainsiCDPData\ + \ + SecureBackupMetadata\ + \ + BackupKeybagDigest\ + \ + uZ+vDf1JWIHh+MXIi487iENG2fk=\ + \ + ClientMetadata\ + \ + SecureBackupMetadataTimestamp\ + 2020-02-20 00:38:28\ + SecureBackupNumericPassphraseLength\ + 6\ + SecureBackupUsesComplexPassphrase\ + \ + SecureBackupUsesNumericPassphrase\ + 1\ + device_color\ + 1\ + device_enclosure_color\ + 1\ + device_mid\ + vsoWCkYtidlo3QGgt6jvLDfeTWqKKQwHITeUEuYM7ZoyWI6CRH/ZUqsdg1fT96TyAyxUuYUF3fjRs5b1\ + device_model\ + iPhone 8 Plus\ + device_model_class\ + iPhone\ + device_model_version\ + iPhone10,2\ + device_name\ + One\ + device_platform\ + 1\ + \ + SecureBackupUsesMultipleiCSCs\ + \ + bottleID\ + 0125E97E-B124-4556-881A-A355805EBE47\ + bottleValid\ + valid\ + build\ + 18A230\ + com.apple.securebackup.timestamp\ + 2020-02-20 00:38:28\ + escrowedSPKI\ + \ + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEB48BVh0D++mTSm9ucXC/a5M0CxFm\ + 4QfFktDjGV0Oo3z7xLSBiqxOwvzl1Vt7m45Rbfk4YnyguNan7aDzD1X6S2zU\ + HhJ8nXro1aAn8tnUX6+EGV2v4iScbkeOrWkqQoWw\ + \ + peerInfo\ + \ + MIIEyjGCBHwwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsMD0FwcGxpY2F0aW9u\ + RGF0ZQQYGBYyMDIwMDIyMDAwMzgyMi4yODc3NjNaMFUMEFB1YmxpY1NpZ25p\ + bmdLZXkEQQQCECkiqu2q7lmL+UUs1fzJWfI7ECo+3JsbiKsrXe8yr/JJC96U\ + oOz8qsdqgJOoA9pp4oaLtdGU9gzopNdRxTU8MFsMD0FwcGxpY2F0aW9uVXNp\ + ZwRIMEYCIQCNUy7VzU5erma8k0EgvXdo0YsuSgC9T4c6w3UM30vnSwIhAKsw\ + Sz6mVOEE3cVbv8WFlF88nb54MK51cyfI3pWp3rRlMG0MDURldmljZUdlc3Rh\ + bHQxXDATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlPU1ZlcnNpb24MBjE4QTIz\ + MDATDAxDb21wdXRlck5hbWUMA09uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJz\ + aW9uAgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEErqcLz3k64Qla\ + asOxVOz9q6jNddI5ujH1zFYjhrTzkGvRCjfgTOK6cHbEbZS6/zgpXXXNMhj4\ + jsZR+scCcbv5yvRfyaZiGAIT5KrsnEiTXygR9hYmVdRqrjmk0ZQkgXOPMH8M\ + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEsP2N8X9uVz2lqLgeYCFE\ + 8kRIUduWj7rL0ioejawj10Qj2OqNhUGYZ0xPnnaGd0uSYFiSrMT04KYXPRqZ\ + NoExp4z9Xda9JvJXjqk2wUeo+EL/smGJmgklfcFkAlY8RheCMIICEwwQVjJE\ + aWN0aW9uYXJ5RGF0YQSCAf0xggH5MBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw\ + RUtKOUtUMC0MCUJhY2t1cEtleQQg+5p8h4Sbq3rSHuA6eHvUGHlVKxvMvtSh\ + DsjZD/h9OBAwYAwMTWFjaGluZUlES2V5DFB2c29XQ2tZdGlkbG8zUUdndDZq\ + dkxEZmVUV3FLS1F3SElUZVVFdVlNN1pveVdJNkNSSC9aVXFzZGcxZlQ5NlR5\ + QXl4VXVZVUYzZmpSczViMTCCAUYMBVZpZXdz0YIBOwwEV2lGaQwHQXBwbGVU\ + VgwHSG9tZUtpdAwHUENTLUZERQwJUENTLU5vdGVzDAlQYXNzd29yZHMMClBD\ + Uy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1Yw\ + DAtDcmVkaXRDYXJkcwwLUENTLVNoYXJpbmcMDE5hbm9SZWdpc3RyeQwMUENT\ + LUNsb3VkS2l0DAxQQ1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN\ + ZXNzYWdlDA1PdGhlclN5bmNhYmxlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1p\ + Z3JhdGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWREcml2ZQwQQWNj\ + ZXNzb3J5UGFpcmluZwwQQ29udGludWl0eVVubG9jawRIMEYCIQC9IebK7hYO\ + N4bYG05pbavoyP3uVs2GrBTvaaxhNeO/WgIhAP/M+WSwsqzcUkg5zhT806au\ + Ax7U0AMhq4OkV2yIuQd8\ + \ + serial\ + C39V20EKJ9KT\ + \ + SecureBackupPassphrase\ + 333333\ + SecureBackupUsesMultipleiCSCs\ + \ + recordID\ + nDF7K/s5knTXbH6/+ERe2LPFZR\ +\ +"; + +NSString* CDPRecordContextSilentTestVector = @"\ +\ +\ +\ + SecureBackupAuthenticationAppleID\ + anna.535.paid@icloud.com\ + SecureBackupAuthenticationAuthToken\ + EAAbAAAABLwIAAAAAF5PHOERDmdzLmljbG91ZC5hdXRovQDwjwm2kXoklEtO/xeL3YCPlBr7IkVuV26y2BfLco+QhJFm4VhgFZSBFUg5l4g/uV2DG95xadgk0+rWLhyXDGZwHN2V9jju3eo6sRwGVj4g5iBFStuj4unTKylu3iFkNSKtTMXAyBXpn4EiRX+8dwumC2FKkA==\ + SecureBackupAuthenticationDSID\ + 16187698960\ + SecureBackupAuthenticationEscrowProxyURL\ + https://p97-escrowproxy.icloud.com:443\ + SecureBackupAuthenticationPassword\ + PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET\ + SecureBackupAuthenticationiCloudEnvironment\ + PROD\ + SecureBackupContainsiCDPData\ + \ + SecureBackupPassphrase\ + 333333\ + SecureBackupSilentRecoveryAttempt\ + \ + SecureBackupUsesMultipleiCSCs\ + \ +\ +"; + +#endif + diff --git a/keychain/ckks/tests/CKKSCloudKitTestsInfo.plist b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist similarity index 94% rename from keychain/ckks/tests/CKKSCloudKitTestsInfo.plist rename to keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist index 6c6c23c4..6c40a6cd 100644 --- a/keychain/ckks/tests/CKKSCloudKitTestsInfo.plist +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/keychain/OctagonTrust/ot-tests/OctagonTrustTests.h b/keychain/OctagonTrust/ot-tests/OctagonTrustTests.h new file mode 100644 index 00000000..84ee897c --- /dev/null +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests.h @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2020 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + + +#ifndef OctagonTrustTests_h +#define OctagonTrustTests_h + +#import "keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h" +#import "keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h" +#import "keychain/ot/OTControl.h" +#import "keychain/ot/OTControlProtocol.h" +#import "keychain/ot/OctagonControlServer.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ProxyXPCConnection : NSObject +@property NSXPCListener *listener; +@property (nonatomic) id obj; +@property (nonatomic) NSXPCInterface *serverInterface; +- (instancetype)initWithInterface:(NSXPCInterface*)interface obj:(id)obj; +- (BOOL)listener:(NSXPCListener*)listener newConnection:(NSXPCConnection*)newConnection; +@end + +@interface OctagonTrustTests : CloudKitKeychainSyncingTestsBase +@property (nonatomic) OTControl* otControl; +@property (nonatomic) ProxyXPCConnection* otXPCProxy; +@property (nonatomic) id mockClique; + +@end + + +@interface OctagonTrustTests (OctagonTrustTestsErrors) +@end + +NS_ASSUME_NONNULL_END +#endif /* OctagonTrustTests_h */ diff --git a/keychain/ResetCloudKeychainAccount/reset_ick_account b/keychain/ResetCloudKeychainAccount/reset_ick_account new file mode 100755 index 00000000..ceb378b8 --- /dev/null +++ b/keychain/ResetCloudKeychainAccount/reset_ick_account @@ -0,0 +1,54 @@ +#!/usr/local/bin/python3 + +import sys +from glob import glob +import subprocess +import re +import os +import argparse + +parser = argparse.ArgumentParser(description='Reset your iCloud Keychain account') +parser.add_argument('icloudpassword', help='iCloud password') +parser.add_argument('passcode', help='passcode or password of the local device') +args = vars(parser.parse_args()) + + +iCloudPassword = args['icloudpassword'] +passcode = args['passcode'] + +def set_security_mac_cmd(): + return 'security2' + +def set_security_ios_cmd(): + return 'security' + +def security_cmd_by_platform(): + swVers = subprocess.check_output(["sw_vers"]) + deviceInformation = swVers.decode('utf-8') + if "Mac OS X" in deviceInformation or "macOS" in deviceInformation: + print("using security2 command on macos") + return set_security_mac_cmd() + elif "iPhone OS" in deviceInformation: + print("using security command on ios") + return set_security_ios_cmd() + else: + print("unsupported platform") + sys.exit(1) + +security_cmd = security_cmd_by_platform() + +print("deleting all escrow records") +subprocess.check_output(["stingrayutil", "--deleteAll", "ReallyDeleteAll"]) + +print("resetting SOS") +subprocess.check_output([security_cmd, "sync", "-C"]) +subprocess.check_output([security_cmd, "sync", "-P", "$iCloudPassword"]) +subprocess.check_output([security_cmd, "sync", "-O"]) + +print("resetting octagon") +subprocess.check_output(["otctl", "resetoctagon"]) + +print("creating new escrow record") +subprocess.check_output(["sbdtool", "passcode_request_trigger"]) +subprocess.check_output(["sbdtool", "passcode_request_provide_passcode", "$passcode"]) + diff --git a/keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.c b/keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.c index f2412f5b..fa0acac2 100644 --- a/keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.c +++ b/keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.c @@ -145,7 +145,7 @@ static SOSCloudTransportRef SOSCloudTransportDefaultTransport(void) if (defaultTransport == NULL) { defaultTransport = SOSCloudTransportCreateXPCTransport(); // provide state handler to sysdiagnose and logging - os_state_add_handler(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), kvsStateBlock); + os_state_add_handler(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), kvsStateBlock); } }); return defaultTransport; @@ -490,7 +490,7 @@ static bool SOSCloudTransportHasPendingKey(SOSCloudTransportRef transport, CFStr SecXPCDictionarySetCFObject(xpcmessage, kMessageKeyKey, keyName); dispatch_semaphore_t kvsWait = dispatch_semaphore_create(0); - bool kvsSent = messageToProxy(xpcTransport, xpcmessage, error, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(xpc_object_t reply) { + bool kvsSent = messageToProxy(xpcTransport, xpcmessage, error, dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(xpc_object_t reply) { kvsHasMessage = xpc_dictionary_get_bool(reply, kMessageKeyValue); dispatch_semaphore_signal(kvsWait); }); diff --git a/keychain/SecureObjectSync/CKDSimulatedStore.h b/keychain/SecureObjectSync/CKDSimulatedStore.h index bcdc6f17..37fb187d 100644 --- a/keychain/SecureObjectSync/CKDSimulatedStore.h +++ b/keychain/SecureObjectSync/CKDSimulatedStore.h @@ -25,7 +25,7 @@ - (NSDictionary*) copyAsDictionary; -- (void)pushWrites; +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync; - (BOOL)pullUpdates:(NSError**) failure; - (void)addOneToOutGoing; diff --git a/keychain/SecureObjectSync/CKDSimulatedStore.m b/keychain/SecureObjectSync/CKDSimulatedStore.m index f42bc0cf..ffd82cbc 100644 --- a/keychain/SecureObjectSync/CKDSimulatedStore.m +++ b/keychain/SecureObjectSync/CKDSimulatedStore.m @@ -24,11 +24,10 @@ } - (instancetype)init { - self = [super init]; - - self.proxy = nil; - self.data = [NSMutableDictionary dictionary]; - + if ((self = [super init])) { + self.proxy = nil; + self.data = [NSMutableDictionary dictionary]; + } return self; } @@ -62,7 +61,8 @@ [self.data removeAllObjects]; } -- (void)pushWrites { +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync +{ } - (void)addOneToOutGoing{ diff --git a/keychain/SecureObjectSync/Regressions/CKDSimulatedAccount.m b/keychain/SecureObjectSync/Regressions/CKDSimulatedAccount.m index 311c75e9..a67e6cae 100644 --- a/keychain/SecureObjectSync/Regressions/CKDSimulatedAccount.m +++ b/keychain/SecureObjectSync/Regressions/CKDSimulatedAccount.m @@ -20,8 +20,7 @@ return [[CKDSimulatedAccount alloc] init]; } - (instancetype) init { - self = [super init]; - if (self) { + if ((self = [super init])) { self.keysToNotHandle = [NSMutableSet set]; self.keyChanges = [NSMutableDictionary dictionary]; diff --git a/keychain/SecureObjectSync/Regressions/SOSCircle_regressions.h b/keychain/SecureObjectSync/Regressions/SOSCircle_regressions.h index fb048fd4..3bdeb8b1 100644 --- a/keychain/SecureObjectSync/Regressions/SOSCircle_regressions.h +++ b/keychain/SecureObjectSync/Regressions/SOSCircle_regressions.h @@ -13,7 +13,6 @@ ONE_TEST(sc_42_circlegencount) ONE_TEST(sc_45_digestvector) ONE_TEST(sc_130_resignationticket) -ONE_TEST(sc_150_Ring) ONE_TEST(sc_150_backupkeyderivation) ONE_TEST(sc_153_backupslicekeybag) diff --git a/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.h b/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.h index d4810cc2..d7e2dcc7 100644 --- a/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.h +++ b/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.h @@ -33,10 +33,16 @@ #include #include #include +#include "keychain/SecureObjectSync/SOSPeerInfoPriv.h" #include "keychain/SecureObjectSync/SOSFullPeerInfo.h" +#include "keychain/SecureObjectSync/SOSCircle.h" +#include "keychain/SecureObjectSync/SOSCirclePriv.h" +#include __BEGIN_DECLS +#define SOS_ENABLED (TARGET_OS_OSX || TARGET_OS_IOS) + CFStringRef myMacAddress(void); const char *cfabsoluteTimeToString(CFAbsoluteTime abstime); const char *cfabsoluteTimeToStringLocal(CFAbsoluteTime abstime); @@ -75,6 +81,24 @@ SOSCreateFullPeerInfoFromName(CFStringRef name, SecKeyRef* outOctagonEncryptionKey, CFErrorRef *error); +SOSFullPeerInfoRef SOSTestV0FullPeerInfo(CFStringRef name, SecKeyRef userKey, CFStringRef OSName, SOSPeerInfoDeviceClass devclass); +SOSFullPeerInfoRef SOSTestFullPeerInfo(CFStringRef name, SecKeyRef userKey, CFStringRef OSName, SOSPeerInfoDeviceClass devclass); +SOSCircleRef SOSTestCircle(SecKeyRef userKey, void * firstFpiv, ... ); +SecKeyRef SOSMakeUserKeyForPassword(const char *passwd); +bool SOSPeerValidityCheck(SOSFullPeerInfoRef fpi, SecKeyRef userKey, CFErrorRef *error); + + +static CFStringRef SOSModelFromType(SOSPeerInfoDeviceClass cls) { + switch(cls) { + case SOSPeerInfo_macOS: return CFSTR("Mac Pro"); + case SOSPeerInfo_iOS: return CFSTR("iPhone"); + case SOSPeerInfo_iCloud: return CFSTR("iCloud"); + case SOSPeerInfo_watchOS: return CFSTR("needWatchOSDeviceName"); + case SOSPeerInfo_tvOS: return CFSTR("needTVOSDeviceName"); + default: return CFSTR("GENERICOSTHING"); + } +} + __END_DECLS #endif /* sec_SOSRegressionUtilities_h */ diff --git a/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.m b/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.m index 1d343706..0d20af9b 100644 --- a/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.m +++ b/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.m @@ -37,6 +37,7 @@ #include "keychain/SecureObjectSync/SOSCircle.h" #include "keychain/SecureObjectSync/SOSInternal.h" #include "keychain/SecureObjectSync/SOSPeerInfoInternal.h" +#include "keychain/SecureObjectSync/SOSPeerInfoPriv.h" #include "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h" #include "SOSRegressionUtilities.h" @@ -220,11 +221,12 @@ CFTypeRef testGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t process dispatch_semaphore_signal(waitSemaphore); }; - if (!keysToGet) + if (!keysToGet) { SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock); - else + } else { SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock); - + } + dispatch_semaphore_wait(waitSemaphore, finishTime); if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull { @@ -315,7 +317,10 @@ SOSPeerInfoRef SOSCreatePeerInfoFromName(CFStringRef name, require(gestalt, exit); result = SOSPeerInfoCreate(NULL, gestalt, NULL, *outSigningKey, - *outOctagonSigningKey, *outOctagonEncryptionKey, error); + *outOctagonSigningKey, *outOctagonEncryptionKey, + // Always support CKKS4All for now + true, + error); exit: CFReleaseNull(gestalt); @@ -336,27 +341,35 @@ SOSFullPeerInfoRef SOSCreateFullPeerInfoFromName(CFStringRef name, SecKeyRef publicKey = NULL; CFDictionaryRef gestalt = NULL; - require(outSigningKey, exit); - *outSigningKey = GeneratePermanentFullECKey(256, name, error); - require(*outSigningKey, exit); - - require(outOctagonSigningKey, exit); - *outOctagonSigningKey = GeneratePermanentFullECKey(384, name, error); - require(*outOctagonSigningKey, exit); - - require(outOctagonEncryptionKey, exit); - *outOctagonEncryptionKey = GeneratePermanentFullECKey(384, name, error); - require(*outOctagonEncryptionKey, exit); - gestalt = SOSCreatePeerGestaltFromName(name); require(gestalt, exit); - result = SOSFullPeerInfoCreate(NULL, gestalt, + require(outSigningKey, exit); + *outSigningKey = GeneratePermanentFullECKey(256, name, error); + require(*outSigningKey, exit); + + if(outOctagonSigningKey && outOctagonEncryptionKey) { + require(outOctagonSigningKey, exit); + *outOctagonSigningKey = GeneratePermanentFullECKey(384, name, error); + require(*outOctagonSigningKey, exit); + + require(outOctagonEncryptionKey, exit); + *outOctagonEncryptionKey = GeneratePermanentFullECKey(384, name, error); + require(*outOctagonEncryptionKey, exit); + result = SOSFullPeerInfoCreate(NULL, gestalt, + NULL, + *outSigningKey, + *outOctagonSigningKey, + *outOctagonEncryptionKey, + error); + } else { + result = SOSFullPeerInfoCreate(NULL, gestalt, NULL, *outSigningKey, - *outOctagonSigningKey, - *outOctagonEncryptionKey, + NULL, + NULL, error); + } exit: CFReleaseNull(gestalt); @@ -365,6 +378,90 @@ exit: return result; } +// MARK: ----- Circle/Peer Creators and Authenticators + +SOSFullPeerInfoRef SOSTestV0FullPeerInfo(CFStringRef name, SecKeyRef userKey, CFStringRef OSName, SOSPeerInfoDeviceClass devclass) { + CFErrorRef error = NULL; + SecKeyRef signingKey = NULL; + SecKeyRef octagonSigningKey = NULL; + SecKeyRef octagonEncryptionKey = NULL; + SOSFullPeerInfoRef fpi = SOSCreateFullPeerInfoFromName(name, &signingKey, &octagonSigningKey, &octagonEncryptionKey, NULL); + SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi); + pi->version = 0; + CFMutableDictionaryRef gestalt = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryAddValue(gestalt, kPIUserDefinedDeviceNameKey, name); + if(SOSPeerInfo_unknown != devclass) { + CFDictionaryAddValue(gestalt, kPIDeviceModelNameKey, SOSModelFromType(devclass)); + CFDictionaryAddValue(gestalt, kPIOSVersionKey, OSName); + } + SOSFullPeerInfoUpdateGestalt(fpi, gestalt, NULL); + if(!SOSFullPeerInfoPromoteToApplication(fpi, userKey, &error)) { + CFReleaseNull(fpi); + } + CFReleaseNull(gestalt); + return fpi; +} + +SOSFullPeerInfoRef SOSTestFullPeerInfo(CFStringRef name, SecKeyRef userKey, CFStringRef OSName, SOSPeerInfoDeviceClass devclass) { + CFErrorRef error = NULL; + SecKeyRef signingKey = NULL; + SecKeyRef octagonSigningKey = NULL; + SecKeyRef octagonEncryptionKey = NULL; + SOSFullPeerInfoRef fpi = SOSCreateFullPeerInfoFromName(name, &signingKey, &octagonSigningKey, &octagonEncryptionKey, NULL); + CFMutableDictionaryRef gestalt = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryAddValue(gestalt, kPIUserDefinedDeviceNameKey, name); + if(SOSPeerInfo_unknown != devclass) { + CFDictionaryAddValue(gestalt, kPIDeviceModelNameKey, SOSModelFromType(devclass)); + CFDictionaryAddValue(gestalt, kPIOSVersionKey, OSName); + } + SOSFullPeerInfoUpdateGestalt(fpi, gestalt, NULL); + if(!SOSFullPeerInfoPromoteToApplication(fpi, userKey, &error)) { + CFReleaseNull(fpi); + } + CFReleaseNull(gestalt); + return fpi; +} + +// to use this function the first peer must be valid +SOSCircleRef SOSTestCircle(SecKeyRef userKey, void * firstFpiv, ... ) { + CFErrorRef error = NULL; + SOSFullPeerInfoRef firstFpi = (SOSFullPeerInfoRef) firstFpiv; + SOSCircleRef circle = SOSCircleCreate(kCFAllocatorDefault, CFSTR("oak"), &error); + CFSetAddValue(circle->peers, SOSFullPeerInfoGetPeerInfo(firstFpi)); + + va_list argp; + va_start(argp, firstFpiv); + SOSFullPeerInfoRef fpi = NULL; + while((fpi = va_arg(argp, SOSFullPeerInfoRef)) != NULL) { + CFSetAddValue(circle->peers, SOSFullPeerInfoGetPeerInfo(fpi)); + } + va_end(argp); + + SOSCircleGenerationSign(circle, userKey, firstFpi, &error); + CFReleaseNull(error); + + return circle; +} + +SecKeyRef SOSMakeUserKeyForPassword(const char *passwd) { + CFDataRef password = CFDataCreate(NULL, (uint8_t *) passwd, strlen(passwd)); + CFErrorRef error = NULL; + CFDataRef parameters = SOSUserKeyCreateGenerateParameters(NULL); + SecKeyRef userKey = SOSUserKeygen(password, parameters, &error); + CFReleaseSafe(password); + CFReleaseNull(parameters); + CFReleaseNull(error); + return userKey; +} + +bool SOSPeerValidityCheck(SOSFullPeerInfoRef fpi, SecKeyRef userKey, CFErrorRef *error) { + SecKeyRef pubKey = SecKeyCopyPublicKey(userKey); + bool retval = SOSPeerInfoApplicationVerify(SOSFullPeerInfoGetPeerInfo(fpi), pubKey, error); + CFReleaseNull(pubKey); + return retval; +} + + // MARK: ----- MAC Address ----- /* diff --git a/keychain/SecureObjectSync/Regressions/SOSTestDataSource.c b/keychain/SecureObjectSync/Regressions/SOSTestDataSource.c index e7e2ac8e..e27c713d 100644 --- a/keychain/SecureObjectSync/Regressions/SOSTestDataSource.c +++ b/keychain/SecureObjectSync/Regressions/SOSTestDataSource.c @@ -220,7 +220,7 @@ static SOSObjectRef copyMergedObject(SOSObjectRef object1, SOSObjectRef object2, // Return the item with the smallest digest. CFDataRef digest1 = copyDigest(object1, error); CFDataRef digest2 = copyDigest(object2, error); - if (digest1 && digest2) switch (CFDataCompare(digest1, digest2)) { + if (digest1 && digest2) switch (CFDataCompareDERData(digest1, digest2)) { case kCFCompareGreaterThan: case kCFCompareEqualTo: result = (SOSObjectRef)dict2; diff --git a/keychain/SecureObjectSync/Regressions/SOSTestDevice.c b/keychain/SecureObjectSync/Regressions/SOSTestDevice.c index 85efa2ec..abfe942f 100644 --- a/keychain/SecureObjectSync/Regressions/SOSTestDevice.c +++ b/keychain/SecureObjectSync/Regressions/SOSTestDevice.c @@ -82,6 +82,22 @@ void SOSTestDeviceDestroyEngine(CFMutableDictionaryRef testDevices) { }); } +void SOSTestDeviceForceCloseDatabase(SOSTestDeviceRef testDevice) { + if(testDevice->db) { + SecDbForceClose(testDevice->db); + } +} + +void SOSTestDeviceForceCloseDatabases(CFMutableDictionaryRef testDevices) { + CFArrayRef deviceIDs = (CFArrayRef)CFDictionaryGetValue(testDevices, CFSTR("@devicesIDs")); + + CFArrayForEach(deviceIDs, ^(const void *value) { + CFStringRef sourceID = (CFStringRef)value; + SOSTestDeviceRef td = (SOSTestDeviceRef)CFDictionaryGetValue(testDevices, sourceID); + SOSTestDeviceForceCloseDatabase(td); + }); +} + CFStringRef SOSTestDeviceGetID(SOSTestDeviceRef td) { CFStringRef engineID = NULL; SOSEngineRef engine = SOSDataSourceGetSharedEngine(td->ds, NULL); @@ -507,5 +523,6 @@ void SOSTestDeviceListTestSync(const char *name, const char *test_directive, con SOSTestDeviceListSync(name, test_directive, test_reason, testDevices, pre, post); SOSTestDeviceListInSync(name, test_directive, test_reason, testDevices); SOSTestDeviceDestroyEngine(testDevices); + SOSTestDeviceForceCloseDatabases(testDevices); CFReleaseSafe(testDevices); } diff --git a/keychain/SecureObjectSync/Regressions/SOSTestDevice.h b/keychain/SecureObjectSync/Regressions/SOSTestDevice.h index 600bda7c..ad494e3b 100644 --- a/keychain/SecureObjectSync/Regressions/SOSTestDevice.h +++ b/keychain/SecureObjectSync/Regressions/SOSTestDevice.h @@ -49,6 +49,9 @@ CFSetRef SOSViewsCopyTestV2Default(void); SOSTestDeviceRef SOSTestDeviceSetPeerIDs(SOSTestDeviceRef td, CFArrayRef peerIDs, CFIndex version, CFSetRef defaultViews); void SOSTestDeviceDestroyEngine(CFMutableDictionaryRef testDevices); +void SOSTestDeviceForceCloseDatabase(SOSTestDeviceRef testDevice); +void SOSTestDeviceForceCloseDatabases(CFMutableDictionaryRef testDevices); + SOSTestDeviceRef SOSTestDeviceSetMute(SOSTestDeviceRef td, bool mute); bool SOSTestDeviceIsMute(SOSTestDeviceRef td); diff --git a/keychain/SecureObjectSync/Regressions/sc-130-resignationticket.c b/keychain/SecureObjectSync/Regressions/sc-130-resignationticket.c index 5ad7629b..b0ba179b 100644 --- a/keychain/SecureObjectSync/Regressions/sc-130-resignationticket.c +++ b/keychain/SecureObjectSync/Regressions/sc-130-resignationticket.c @@ -41,6 +41,8 @@ #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + typedef struct piStuff_t { SecKeyRef signingKey; SecKeyRef octagonSigningKey; @@ -150,13 +152,15 @@ static void tests(void) freeSimplePeer(iDrone); } -static int kTestTestCount = 12; +#endif int sc_130_resignationticket(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(12); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-150-backupkeyderivation.c b/keychain/SecureObjectSync/Regressions/sc-150-backupkeyderivation.c index 3120a20a..768fe6ae 100644 --- a/keychain/SecureObjectSync/Regressions/sc-150-backupkeyderivation.c +++ b/keychain/SecureObjectSync/Regressions/sc-150-backupkeyderivation.c @@ -40,6 +40,8 @@ #include "SOSRegressionUtilities.h" #include "keychain/SecureObjectSync/SOSInternal.h" +#if SOS_ENABLED + #if 0 static inline CFMutableDataRef CFDataCreateMutableWithRandom(CFAllocatorRef allocator, CFIndex size) { CFMutableDataRef result = NULL; @@ -68,8 +70,6 @@ static const uint8_t sEntropy2[] = { 0xef, 0xbd, 0x72, 0x57, 0x02, 0xe6, 0xbd, static const uint8_t sEntropy3[] = { 0xea, 0x06, 0x34, 0x93, 0xd7, 0x8b, 0xd6, 0x0d, 0xce, 0x83, 0x00 }; - -#define tests_count (6) static void tests(void) { ccec_const_cp_t cp = SOSGetBackupKeyCurveParameters(); @@ -112,14 +112,16 @@ static void tests(void) CFReleaseNull(entropy2); CFReleaseNull(entropy3); } +#endif -static int kTestTestCount = tests_count; int sc_150_backupkeyderivation(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(6); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-150-ring.m b/keychain/SecureObjectSync/Regressions/sc-150-ring.m deleted file mode 100644 index c547a988..00000000 --- a/keychain/SecureObjectSync/Regressions/sc-150-ring.m +++ /dev/null @@ -1,181 +0,0 @@ -// -// sc-150-ring.c -// sec -// -// Created by Richard Murphy on 3/3/15. -// -// - -#include -/* - * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - - -#include -#include -#include - -#include "keychain/SecureObjectSync/SOSRing.h" -#include "keychain/SecureObjectSync/SOSRingTypes.h" -#include "keychain/SecureObjectSync/SOSRingUtils.h" -#include -#include "keychain/SecureObjectSync/SOSInternal.h" -#include "keychain/SecureObjectSync/SOSUserKeygen.h" - -#include - -#include - -#include -#include - -#include "SOSCircle_regressions.h" -#include "SOSRegressionUtilities.h" - -static SOSFullPeerInfoRef SOSCreateApplicantFullPeerInfoFromName(CFStringRef peerName, - SecKeyRef user_private_key, - SecKeyRef* outSigningKey, - SecKeyRef* outOctagonSigningKey, - SecKeyRef* outOctagonEncryptionKey, - CFErrorRef *error) -{ - SOSFullPeerInfoRef result = NULL; - SOSFullPeerInfoRef fullPeer = SOSCreateFullPeerInfoFromName(peerName, outSigningKey, outOctagonSigningKey, outOctagonEncryptionKey, error); - - if (fullPeer && SOSFullPeerInfoPromoteToApplication(fullPeer, user_private_key, error)) - CFTransferRetained(result, fullPeer); - - CFReleaseNull(fullPeer); - return result; -} - -static int kTestTestCount = 24; -static void tests(void) -{ - - //SecKeyRef publicKey = NULL; - SecKeyRef dev_a_key = NULL; - SecKeyRef dev_b_key = NULL; - SecKeyRef dev_c_key = NULL; - SecKeyRef oct_dev_as_key = NULL; - SecKeyRef oct_dev_aw_key = NULL; - SecKeyRef oct_dev_bs_key = NULL; - SecKeyRef oct_dev_bw_key = NULL; - SecKeyRef oct_dev_cs_key = NULL; - SecKeyRef oct_dev_cw_key = NULL; - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - - ok(cfpassword, "no password"); - - CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error); - ok(parameters, "No parameters!"); - ok(error == NULL, "Error: (%@)", error); - CFReleaseNull(error); - - SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error); - CFReleaseNull(parameters); - - SecKeyRef user_pubkey = SecKeyCreatePublicFromPrivate(user_privkey); - - - SOSFullPeerInfoRef peer_a_full_info = SOSCreateApplicantFullPeerInfoFromName(CFSTR("Peer A"), user_privkey, &dev_a_key, &oct_dev_as_key, &oct_dev_aw_key, NULL); - SOSFullPeerInfoRef peer_b_full_info = SOSCreateApplicantFullPeerInfoFromName(CFSTR("Peer B"), user_privkey, &dev_b_key, &oct_dev_bs_key, &oct_dev_bw_key, NULL); - SOSFullPeerInfoRef peer_c_full_info = SOSCreateApplicantFullPeerInfoFromName(CFSTR("Peer C"), user_privkey, &dev_c_key, &oct_dev_cs_key, &oct_dev_cw_key, NULL); - CFStringRef peerID_a = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(peer_a_full_info)); - CFStringRef peerID_b = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(peer_b_full_info)); - SOSRingRef Ring = SOSRingCreate(CFSTR("TESTRING"), peerID_a, kSOSRingBase, NULL); - - ok(Ring, "Ring creation"); - - - ok(0 == SOSRingCountPeers(Ring), "Zero peers"); - - ok(SOSRingApply(Ring, user_pubkey, peer_a_full_info, NULL)); - ok(SOSRingApply(Ring, user_pubkey, peer_b_full_info, NULL)); - - ok(2 == SOSRingCountPeers(Ring), "Two peers"); - - ok(SOSRingWithdraw(Ring, user_privkey, peer_b_full_info, NULL)); - - ok(1 == SOSRingCountPeers(Ring), "One peer"); - - ok(kSOSRingMember == SOSRingDeviceIsInRing(Ring, peerID_a), "peer_a is in Ring"); - ok(kSOSRingNotInRing == SOSRingDeviceIsInRing(Ring, peerID_b), "peer_b is not in Ring"); - CFStringRef lastmod = SOSRingGetLastModifier(Ring); - ok(CFEqual(lastmod, peerID_b), "peer_b_full_info did last mod"); - - ok(SOSRingResetToEmpty(Ring, peerID_a, NULL), "Reset the circle"); - ok(kSOSRingNotInRing == SOSRingDeviceIsInRing(Ring, peerID_a), "peer_a is not in Ring"); - - ok(SOSRingResetToOffering(Ring, NULL, peer_a_full_info, NULL), "Reset Ring to Offering for PeerA"); - ok(kSOSRingMember == SOSRingDeviceIsInRing(Ring, peerID_a), "peer_a is in Ring"); - ok(kSOSRingNotInRing == SOSRingDeviceIsInRing(Ring, peerID_b), "peer_b is not in Ring"); - - CFDataRef ringDER = SOSRingCopyEncodedData(Ring, NULL); - ok(ringDER, "Successful encoding to DER of Ring"); - SOSRingRef Ring2 = SOSRingCreateFromData(NULL, ringDER); - ok(Ring2, "Successful decoding of DER to Ring"); - - ok(CFEqualSafe(Ring, Ring2), "Compares"); - - ok(SOSRingApply(Ring, user_pubkey, peer_c_full_info, NULL)); - ok(SOSRingApply(Ring, user_pubkey, peer_b_full_info, NULL)); - - CFReleaseNull(ringDER); - CFReleaseNull(Ring2); - ringDER = SOSRingCopyEncodedData(Ring, NULL); - Ring2 = SOSRingCreateFromData(NULL, ringDER); - ok(CFEqualSafe(Ring, Ring2), "Compares"); - - CFReleaseNull(ringDER); - CFReleaseNull(Ring2); - CFReleaseNull(dev_a_key); - CFReleaseNull(dev_b_key); - CFReleaseNull(dev_c_key); - CFReleaseNull(oct_dev_as_key); - CFReleaseNull(oct_dev_aw_key); - CFReleaseNull(oct_dev_bs_key); - CFReleaseNull(oct_dev_bw_key); - CFReleaseNull(oct_dev_cs_key); - CFReleaseNull(oct_dev_cw_key); - CFReleaseNull(cfpassword); - - CFReleaseNull(user_privkey); - CFReleaseNull(user_pubkey); - - CFReleaseNull(peer_a_full_info); - CFReleaseNull(peer_b_full_info); - CFReleaseNull(peer_c_full_info); - CFReleaseNull(Ring); -} - -int sc_150_Ring(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/keychain/SecureObjectSync/Regressions/sc-153-backupslicekeybag.c b/keychain/SecureObjectSync/Regressions/sc-153-backupslicekeybag.c index a1cefeba..28983628 100644 --- a/keychain/SecureObjectSync/Regressions/sc-153-backupslicekeybag.c +++ b/keychain/SecureObjectSync/Regressions/sc-153-backupslicekeybag.c @@ -32,8 +32,10 @@ #include "SOSCircle_regressions.h" #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + #define encode_decode_count 2 -#if !TARGET_OS_SIMULATOR + static CF_RETURNS_RETAINED SOSBackupSliceKeyBagRef EncodeDecode(SOSBackupSliceKeyBagRef bag) { SOSBackupSliceKeyBagRef result = NULL; @@ -54,17 +56,6 @@ static CF_RETURNS_RETAINED SOSBackupSliceKeyBagRef EncodeDecode(SOSBackupSliceKe return result; } -#endif - -#if 0 -static CFDataRef CFDataCreateWithRandom(CFAllocatorRef allocator, size_t size) { - CFMutableDataRef result = CFDataCreateMutableWithScratch(allocator, size); - - SecRandomCopyBytes(kSecRandomDefault, size, CFDataGetMutableBytePtr(result)); - - return result; -} -#endif static const uint8_t sEntropy1[] = { 0xc4, 0xb9, 0xa6, 0x6e, 0xeb, 0x56, 0xa1, 0x5c, 0x1d, 0x30, 0x09, 0x40, @@ -78,12 +69,6 @@ static const uint8_t sEntropy2[] = { 0x3a, 0x91, 0x0d, 0xc1, 0x5f, 0x57, 0x98, 0x44 }; -#if !TARGET_OS_SIMULATOR - #define tests_count (8 + encode_decode_count) -#else - #define tests_count (6) -#endif - static void tests(void) { CFErrorRef localError = NULL; @@ -132,7 +117,6 @@ static void tests(void) SOSBackupSliceKeyBagRef vb2 = NULL; -#if !TARGET_OS_SIMULATOR vb = SOSBackupSliceKeyBagCreate(kCFAllocatorDefault, piSet, &localError); ok(vb != NULL, "Allocation: (%@)", localError); CFReleaseNull(localError); @@ -140,20 +124,6 @@ static void tests(void) vb2 = EncodeDecode(vb); ok(vb2 != NULL, "transcoded"); -#endif -#if 0 - // Have helper functions for new security object that load bags - keybag_handle_t ourHandle = SOSBSKBLoadAndUnlockWithPeerSecret(vb, peer2WithBackup, entropy2, &localError); - ok(ourHandle != bad_keybag_handle, "loaded with peer secret, handle %d (%@)", ourHandle, localError); - CFReleaseNull(localError); - - aks_unload_bag(ourHandle); -#else -TODO:{ - todo("no simulator supprt"); - ok(false); - } -#endif CFReleaseNull(vb); CFReleaseNull(vb2); @@ -172,14 +142,15 @@ TODO:{ CFReleaseNull(entropy1); CFReleaseNull(entropy2); } - -static int kTestTestCount = tests_count; +#endif int sc_153_backupslicekeybag(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(12); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-20-keynames.m b/keychain/SecureObjectSync/Regressions/sc-20-keynames.m index a3722490..ad74dbc8 100644 --- a/keychain/SecureObjectSync/Regressions/sc-20-keynames.m +++ b/keychain/SecureObjectSync/Regressions/sc-20-keynames.m @@ -43,6 +43,8 @@ #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + static int kTestTestCount = 15; static void tests(void) @@ -130,12 +132,15 @@ static void tests(void) CFReleaseNull(retirement_peer_id); } +#endif int sc_20_keynames(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-25-soskeygen.c b/keychain/SecureObjectSync/Regressions/sc-25-soskeygen.c index 42859409..bce07903 100644 --- a/keychain/SecureObjectSync/Regressions/sc-25-soskeygen.c +++ b/keychain/SecureObjectSync/Regressions/sc-25-soskeygen.c @@ -48,6 +48,9 @@ #include "SOSCircle_regressions.h" #include "SOSRegressionUtilities.h" + +#if SOS_ENABLED + #include #include #include @@ -185,7 +188,6 @@ static SecKeyRef SOSOldUserKeygen(CFDataRef password, CFDataRef parameters, CFEr return NULL; } - debugDumpUserParameters(CFSTR("params-keygen"), parameters); const uint8_t *password_bytes = CFDataGetBytePtr(password); @@ -198,7 +200,7 @@ static SecKeyRef SOSOldUserKeygen(CFDataRef password, CFDataRef parameters, CFEr ccec_full_ctx_decl_cp(cp, tmpkey); - secnotice("circleOps", "Generating key for: iterations %zd, keysize %zd: %@", iterations, keysize, parameters); + debugDumpUserParameters(CFSTR("sc_25_soskeygen: Generating key for:"), parameters); if (ccrng_pbkdf2_prng_init(&pbkdf2_prng, maxbytes, password_length, password_bytes, @@ -275,15 +277,15 @@ static void tests(void) { CFReleaseNull(cfpassword); } +#endif + int sc_25_soskeygen(int argc, char *const *argv) { -#if TARGET_OS_WATCH - plan_tests(NKEYS*(4+NPARMS*4)); -#else +#if SOS_ENABLED plan_tests(850); -#endif - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-30-peerinfo.c b/keychain/SecureObjectSync/Regressions/sc-30-peerinfo.c index 66c95929..4efa2918 100644 --- a/keychain/SecureObjectSync/Regressions/sc-30-peerinfo.c +++ b/keychain/SecureObjectSync/Regressions/sc-30-peerinfo.c @@ -46,6 +46,8 @@ #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + #if TARGET_OS_IPHONE #include #endif @@ -152,12 +154,15 @@ static void tests(void) CFReleaseNull(octagonEncryptionKey); CFReleaseNull(fpi); } +#endif int sc_30_peerinfo(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-31-peerinfo-simplefuzz.c b/keychain/SecureObjectSync/Regressions/sc-31-peerinfo-simplefuzz.c index 800a241d..2774cbd9 100644 --- a/keychain/SecureObjectSync/Regressions/sc-31-peerinfo-simplefuzz.c +++ b/keychain/SecureObjectSync/Regressions/sc-31-peerinfo-simplefuzz.c @@ -28,6 +28,7 @@ #include "SOSCircle_regressions.h" #include "SOSRegressionUtilities.h" +#if SOS_ENABLED #if TARGET_OS_IPHONE #include @@ -79,12 +80,15 @@ errOut: CFReleaseNull(octagonEncryptionKey); CFReleaseNull(fpi); } +#endif int sc_31_peerinfo(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests((int)(kTestCount + kTestFuzzerCount)); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-40-circle.c b/keychain/SecureObjectSync/Regressions/sc-40-circle.c index 6f516bd1..a4687f81 100644 --- a/keychain/SecureObjectSync/Regressions/sc-40-circle.c +++ b/keychain/SecureObjectSync/Regressions/sc-40-circle.c @@ -47,6 +47,8 @@ #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + static int kTestGenerationCount = 2; static void test_generation(void) { @@ -182,14 +184,16 @@ static void tests(void) CFReleaseNull(user_privkey); CFReleaseNull(circle); } +#endif int sc_40_circle(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestGenerationCount + kTestTestCount); - test_generation(); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-42-circlegencount.c b/keychain/SecureObjectSync/Regressions/sc-42-circlegencount.c index 7ee15736..f3ba599d 100644 --- a/keychain/SecureObjectSync/Regressions/sc-42-circlegencount.c +++ b/keychain/SecureObjectSync/Regressions/sc-42-circlegencount.c @@ -31,8 +31,7 @@ #include "SOSCircle_regressions.h" #include "SOSRegressionUtilities.h" - -static int kTestTestCount = 7; +#if SOS_ENABLED static void tests(void) { @@ -66,12 +65,15 @@ static void tests(void) CFReleaseNull(circle); } +#endif int sc_42_circlegencount(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(7); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-45-digestvector.c b/keychain/SecureObjectSync/Regressions/sc-45-digestvector.c index 7f86e643..8c177bcc 100644 --- a/keychain/SecureObjectSync/Regressions/sc-45-digestvector.c +++ b/keychain/SecureObjectSync/Regressions/sc-45-digestvector.c @@ -28,8 +28,7 @@ #include #include - -static int kTestTestCount = 15; +#include "SOSRegressionUtilities.h" static void testNullDigestVector(void) { @@ -158,9 +157,11 @@ static void tests(void) int sc_45_digestvector(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(15); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-kvstool.m b/keychain/SecureObjectSync/Regressions/sc-kvstool.m deleted file mode 100644 index 63660dee..00000000 --- a/keychain/SecureObjectSync/Regressions/sc-kvstool.m +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - - -// Run on a device: -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_kvstool -v -- --dump -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_kvstool -v -- --clear -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_kvstool -v -- --putcircle -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_kvstool -v -- --direct --dump -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_kvstool -v -- --direct --putcircle - -#include -#include -#include -#include -#include - -#include "SOSCircle_regressions.h" - -#include - -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "SOSCircle_regressions.h" -#include "CKDLocalKeyValueStore.h" -#include "SOSRegressionUtilities.h" -#include "SOSTestDataSource.h" -#include "SOSTestTransport.h" -#include "SOSCloudKeychainClient.h" - -#import "SOSDirectCloudTransport.h" - -// MARK: ----- Constants ----- - -static CFStringRef circleKey = CFSTR("Circle"); - -// MARK: ----- start of all tests ----- - -static void putCircleInCloud(SOSCircleRef circle, dispatch_queue_t work_queue, dispatch_group_t work_group) -{ - CFErrorRef error = NULL; - CFDataRef newCloudCircleEncoded = SOSCircleCopyEncodedData(circle, kCFAllocatorDefault, &error); - ok(newCloudCircleEncoded, "Encoded as: %@ [%@]", newCloudCircleEncoded, error); - - // Send the circle with our application request back to cloud - testPutObjectInCloud(circleKey, newCloudCircleEncoded, &error, work_group, work_queue); -} - -static void createAndPutInitialCircle(void) -{ - dispatch_queue_t work_queue = dispatch_queue_create("capic", DISPATCH_QUEUE_CONCURRENT); - dispatch_group_t work_group = dispatch_group_create(); - - CFErrorRef error = NULL; - CFStringRef cflabel = CFSTR("TEST_USERKEY"); - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - SOSCCRegisterUserCredentials(cflabel, cfpassword, &error); - - CFErrorRef localError = NULL; - - SOSDataSourceFactoryRef our_data_source_factory = SOSTestDataSourceFactoryCreate(); - SOSDataSourceRef our_data_source = SOSTestDataSourceCreate(); - SOSTestDataSourceFactoryAddDataSource(our_data_source_factory, circleKey, our_data_source); - - CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(CFSTR("Alice")); - - SOSAccountRef our_account = SOSAccountCreate(kCFAllocatorDefault, gestalt, our_data_source_factory, - ^(CFArrayRef keys) - { - pass("SOSAccountKeyInterestBlock"); - }, - ^ bool (CFDictionaryRef keys, CFErrorRef *error) - { - pass("SOSAccountDataUpdateBlock"); - return false; - }, - NULL); - SOSAccountEnsureCircle(our_account, circleKey); - - SOSFullPeerInfoRef our_full_peer_info = SOSAccountGetMyFullPeerInCircleNamed(our_account, circleKey, &error); - SOSPeerInfoRef our_peer_info = SOSFullPeerInfoGetPeerInfo(our_full_peer_info); - CFRetain(our_peer_info); - - SOSCircleRef circle = SOSAccountFindCircle(our_account, circleKey); - CFRetain(circle); - -// SecKeyRef user_privkey = SOSUserGetPrivKey(&localError); - SecKeyRef user_privkey = NULL; // TODO: this will not work - ok(SOSCircleRequestAdmission(circle, user_privkey, our_full_peer_info, &localError), "Requested admission (%@)", our_peer_info); - ok(SOSCircleAcceptRequests(circle, user_privkey, our_full_peer_info, &localError), "Accepted self"); - - putCircleInCloud(circle, work_queue, work_group); - pass("Put circle in cloud: (%@)", circle); - - CFRelease(circle); -} - -static void postCircleChangeNotification() -{ - NSArray *keys = [NSArray arrayWithObjects:(id)circleKey, nil]; - NSDictionary* userInfo = [[NSDictionary alloc] initWithObjectsAndKeys: - keys, NSUbiquitousKeyValueStoreChangedKeysKey, - [NSNumber numberWithInt:NSUbiquitousKeyValueStoreServerChange], NSUbiquitousKeyValueStoreChangeReasonKey, - nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:NULL userInfo:userInfo]; - [userInfo release]; -} - -static void requestSynchronization(dispatch_queue_t processQueue, dispatch_group_t dgroup) -{ - testSynchronize(processQueue, dgroup); -} - -static void displayCircles(CFTypeRef objects) -{ - // SOSCCCopyApplicantPeerInfo doesn't display all info, e.g. in the case where we are not in circle - CFDictionaryForEach(objects, ^(const void *key, const void *value) - { - if (SOSKVSKeyGetKeyType(key) == kCircleKey) - { - CFErrorRef localError = NULL; - if (isData(value)) - { - SOSCircleRef circle = SOSCircleCreateFromData(NULL, (CFDataRef) value, &localError); - pass("circle: %@ %@", key, circle); - CFReleaseSafe(circle); - } - else - pass("non-circle: %@ %@", key, value); - } - }); -} - - -static void dumpCircleInfo() -{ - CFErrorRef error = NULL; - CFArrayRef applicantPeerInfos = NULL; - CFArrayRef peerInfos = NULL; - int idx; - - NSArray *ccmsgs = @[@"Error", @"InCircle", @"NotInCircle", @"RequestPending", @"CircleAbsent"]; - - SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error); - pass("ccstatus: %d, error: %@", ccstatus, error); - idx = ccstatus-kSOSCCError; - if (0<=idx && idx<(int)[ccmsgs count]) - pass("ccstatus: %d (%@)", ccstatus, ccmsgs[idx]); - - // Now look at current applicants - applicantPeerInfos = SOSCCCopyApplicantPeerInfo(&error); - if (applicantPeerInfos) - { - pass("Applicants: %ld, error: %@", (long)CFArrayGetCount(applicantPeerInfos), error); - CFArrayForEach(applicantPeerInfos, ^(const void *value) { - SOSPeerInfoRef peer = (SOSPeerInfoRef)value; - CFStringRef peerName = SOSPeerInfoGetPeerName(peer); - pass("Applicant: %@", peerName); - }); - } - else - pass("No applicants, error: %@", error); - - - peerInfos = SOSCCCopyPeerPeerInfo(&error); - if (peerInfos) - { - pass("Peers: %ld, error: %@", (long)CFArrayGetCount(applicantPeerInfos), error); - CFArrayForEach(peerInfos, ^(const void *value) { - SOSPeerInfoRef peer = (SOSPeerInfoRef)value; - CFStringRef peerName = SOSPeerInfoGetPeerName(peer); - pass("Peer: %@", peerName); - }); - } - else - pass("No peers, error: %@", error); -} - -// define the options table for the command line -static const struct option options[] = -{ - { "verbose", optional_argument, NULL, 'v' }, - { "dump", optional_argument, NULL, 'd' }, - { "clear", optional_argument, NULL, 'C' }, - { "putcircle", optional_argument, NULL, 'p' }, - { "direct", optional_argument, NULL, 'D' }, - { "notify", optional_argument, NULL, 'n' }, - { "sync", optional_argument, NULL, 's' }, - { "info", optional_argument, NULL, 'i' }, - { } -}; - -static int kTestCount = 10; - -static void usage(void) -{ - printf("Usage:\n"); - printf(" --dump [itemName] Dump the contents of the kvs store (through proxy)\n"); - printf(" --clear Clear the contents of the kvs store (through proxy)\n"); - printf(" --putcircle Put a new circle into the kvs store (through proxy)\n"); - printf(" --direct Go directly to KVS (bypass proxy)\n"); - printf(" --notify Post a notification that the circle key has changed\n"); - printf(" --sync Post a notification that the circle key has changed\n"); - printf(" --info Dump info about circle and peer status\n"); -} - -enum kvscommands -{ - kCommandClear = 1, - kCommandDump = 2, - kCommandPutCircle = 3, - kCommandNotify = 4, - kCommandSynchronize = 5, - kCommandInfo = 6, - kCommandHelp -}; - -static int command = kCommandHelp; -static bool useDirect = false; - -static void tests(const char *itemName) -{ - dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL); - dispatch_group_t work_group = dispatch_group_create(); - -#if 0 - if (useDirect) - { - SOSCloudKeychainServerInit(); - } -#endif - SOSCloudKeychainSetCallbackMethodXPC(); // call this first - - pass("Command: %d", command); - switch (command) - { - case kCommandClear: - ok(testClearAll(generalq, work_group), "test Clear All"); - break; - case kCommandDump: - { - CFArrayRef keysToGet = NULL; - if (itemName) - { - CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8); - pass("Retrieving : %@", itemStr); - keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr); - CFReleaseSafe(itemStr); - } - CFTypeRef objects = testGetObjectsFromCloud(keysToGet, generalq, work_group); - CFReleaseSafe(keysToGet); - pass(" : %@", objects); - displayCircles(objects); - } - break; - case kCommandPutCircle: - createAndPutInitialCircle(); - break; - case kCommandNotify: - postCircleChangeNotification(); - break; - case kCommandSynchronize: - requestSynchronization(generalq, work_group); - break; - case kCommandInfo: - dumpCircleInfo(); - break; - default: - case kCommandHelp: - usage(); - break; - } -} - -int sc_kvstool(int argc, char *const *argv) -{ - char *itemName = NULL; -// extern int optind; - extern char *optarg; - int arg, argSlot; - - while (argSlot = -1, (arg = getopt_long(argc, (char * const *)argv, "ivChpdns", options, &argSlot)) != -1) - switch (arg) - { - case 'd': - itemName = (char *)(optarg); - command = kCommandDump; - break; - case 'C': // should set up to call testClearAll - command = kCommandClear; - break; - case 'p': - command = kCommandPutCircle; - break; - case 'n': - command = kCommandNotify; - break; - case 's': - command = kCommandSynchronize; - break; - case 'i': - command = kCommandInfo; - break; - case 'D': - useDirect = true; - printf("Using direct calls to KVS\n"); - break; - default: - secerror("arg: %s", optarg); - break; - } - - plan_tests(kTestCount); - - secerror("Command: %d", command); - printf("Command: %d\n", command); - - tests(itemName); - - return 0; -} diff --git a/keychain/SecureObjectSync/SOSAccount.h b/keychain/SecureObjectSync/SOSAccount.h index a50be3ee..8efa9cbf 100644 --- a/keychain/SecureObjectSync/SOSAccount.h +++ b/keychain/SecureObjectSync/SOSAccount.h @@ -44,6 +44,10 @@ #import "keychain/SecureObjectSync/SOSAccountTransaction.h" #include +extern NSString* const kSOSIdentityStatusCompleteIdentity; +extern NSString* const kSOSIdentityStatusKeyOnly; +extern NSString* const kSOSIdentityStatusPeerOnly; + @class SOSAccount; __BEGIN_DECLS @@ -106,11 +110,8 @@ void SOSTransportEachMessage(SOSAccount* account, CFDictionaryRef updates, CFEr CFStringRef SOSAccountGetSOSCCStatusString(SOSCCStatus status); SOSCCStatus SOSAccountGetSOSCCStatusFromString(CFStringRef status); bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, CFErrorRef* error); -bool SOSAccountJoinCirclesWithAnalytics(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error); bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, CFErrorRef* error); -bool SOSAccountJoinCirclesAfterRestoreWithAnalytics(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error); bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, CFErrorRef* error); -bool SOSAccountRemovePeersFromCircleWithAnalytics(SOSAccount* account, CFArrayRef peers, NSData* parentEvent, CFErrorRef* error); bool SOSAccountBail(SOSAccount* account, uint64_t limit_in_seconds, CFErrorRef* error); bool SOSAccountAcceptApplicants(SOSAccount* account, CFArrayRef applicants, CFErrorRef* error); bool SOSAccountRejectApplicants(SOSAccount* account, CFArrayRef applicants, CFErrorRef* error); @@ -161,6 +162,12 @@ void SOSAccountPeerGotInSync(SOSAccountTransaction* aTxn, CFStringRef peerID, CF bool SOSAccountHandleParametersChange(SOSAccount* account, CFDataRef updates, CFErrorRef *error); +// +// MARK: Local device key access from account object - can call without lock without endangering peerinfo. +// +SecKeyRef SOSAccountCopyDevicePrivateKey(SOSAccount* account, CFErrorRef *error); +SecKeyRef SOSAccountCopyDevicePublicKey(SOSAccount* account, CFErrorRef *error); + // // MARK: Requests for syncing later // @@ -188,11 +195,6 @@ CF_RETURNS_RETAINED CFSetRef SOSAccountCopyBackupPeersAndForceSync(SOSAccountTra bool SOSAccountScanForRetired(SOSAccount* account, SOSCircleRef circle, CFErrorRef *error); CF_RETURNS_RETAINED SOSCircleRef SOSAccountCloneCircleWithRetirement(SOSAccount* account, SOSCircleRef starting_circle, CFErrorRef *error); -// -// MARK: Version incompatibility Functions -// -CFStringRef SOSAccountCopyIncompatibilityInfo(SOSAccount* account, CFErrorRef* error); - // // MARK: Backup functions // @@ -200,18 +202,16 @@ CFStringRef SOSAccountCopyIncompatibilityInfo(SOSAccount* account, CFErrorRef* bool SOSAccountIsBackupRingEmpty(SOSAccount* account, CFStringRef viewName); bool SOSAccountNewBKSBForView(SOSAccount* account, CFStringRef viewName, CFErrorRef *error); -void SOSAccountProcessBackupRings(SOSAccount* account, CFErrorRef *error); +void SOSAccountProcessBackupRings(SOSAccount* account); bool SOSAccountValidateBackupRingForView(SOSAccount* account, CFStringRef viewName, CFErrorRef *error); bool SOSAccountSetBackupPublicKey(SOSAccountTransaction* aTxn, CFDataRef backupKey, CFErrorRef *error); +bool SOSAccountEnsurePeerInfoHasCurrentBackupKey(SOSAccountTransaction *aTxn, CFErrorRef *error); bool SOSAccountRemoveBackupPublickey(SOSAccountTransaction* aTxn, CFErrorRef *error); bool SOSAccountBackupUpdateBackupPublicKey(SOSAccount *account, CFDataRef backupKey); bool SOSAccountSetBSKBagForAllSlices(SOSAccount* account, CFDataRef backupSlice, bool setupV0Only, CFErrorRef *error); CF_RETURNS_RETAINED SOSBackupSliceKeyBagRef SOSAccountBackupSliceKeyBagForView(SOSAccount* account, CFStringRef viewName, CFErrorRef* error); -bool SOSAccountIsLastBackupPeer(SOSAccount* account, CFErrorRef *error); - - // // MARK: Recovery Public Key Functions // @@ -292,8 +292,17 @@ void SOSAccountResetOTRNegotiationCoder(SOSAccount* account, CFStringRef peerid) void SOSAccountTimerFiredSendNextMessage(SOSAccountTransaction* txn, NSString* peerid, NSString* accessGroup); NSArray* SOSAccountGetAllTLKs(void); +NSArray* SOSAccountGetSelectedTLKs(void); + CF_RETURNS_RETAINED CFMutableArrayRef SOSAccountCopyiCloudIdentities(SOSAccount* account); +bool SOSAccountEvaluateKeysAndCircle(SOSAccountTransaction *txn, CFErrorRef *block_error); + +// +// MARK: Remove V0 Peers +bool SOSAccountRemoveV0Clients(SOSAccount *account, CFErrorRef *error); + + __END_DECLS #endif /* !_SOSACCOUNT_H_ */ diff --git a/keychain/SecureObjectSync/SOSAccount.m b/keychain/SecureObjectSync/SOSAccount.m index cd5951a2..30bc2d1a 100644 --- a/keychain/SecureObjectSync/SOSAccount.m +++ b/keychain/SecureObjectSync/SOSAccount.m @@ -59,11 +59,9 @@ #include "keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.h" -#import "SecdWatchdog.h" - +#import "ipc/SecdWatchdog.h" #include #include -#include #include #include @@ -94,6 +92,10 @@ const CFStringRef kOTRConfigVersion = CFSTR("OTRConfigVersion"); NSString* const SecSOSAggdReattemptOTRNegotiation = @"com.apple.security.sos.otrretry"; NSString* const SOSAccountUserDefaultsSuite = @"com.apple.security.sosaccount"; NSString* const SOSAccountLastKVSCleanup = @"lastKVSCleanup"; +NSString* const kSOSIdentityStatusCompleteIdentity = @"completeIdentity"; +NSString* const kSOSIdentityStatusKeyOnly = @"keyOnly"; +NSString* const kSOSIdentityStatusPeerOnly = @"peerOnly"; + const uint64_t max_packet_size_over_idms = 500; @@ -124,6 +126,9 @@ static NSDictionary* SOSStateMap(void); CFReleaseNull(self->_accountKey); CFReleaseNull(self->_accountPrivateKey); CFReleaseNull(self->_previousAccountKey); + CFReleaseNull(self->_peerPublicKey); + CFReleaseNull(self->_octagonSigningFullKeyRef); + CFReleaseNull(self->_octagonEncryptionFullKeyRef); #if OCTAGON [self.performBackups cancel]; [self.performRingUpdates cancel]; @@ -138,16 +143,22 @@ static NSDictionary* SOSStateMap(void); CFRetainAssign(self->_accountKey, key); } +@synthesize accountPrivateKey = _accountPrivateKey; + +- (void) setAccountPrivateKey: (SecKeyRef) key { + CFRetainAssign(self->_accountPrivateKey, key); +} + @synthesize previousAccountKey = _previousAccountKey; - (void) setPreviousAccountKey: (SecKeyRef) key { CFRetainAssign(self->_previousAccountKey, key); } -@synthesize accountPrivateKey = _accountPrivateKey; +@synthesize peerPublicKey = _peerPublicKey; -- (void) setAccountPrivateKey: (SecKeyRef) key { - CFRetainAssign(self->_accountPrivateKey, key); +- (void) setPeerPublicKey: (SecKeyRef) key { + CFRetainAssign(self->_peerPublicKey, key); } // Syntactic sugar getters @@ -187,7 +198,7 @@ static NSDictionary* SOSStateMap(void); -(void)ensureOctagonPeerKeys { #if OCTAGON - CKKSLockStateTracker *tracker = [CKKSViewManager manager].lockStateTracker; + CKKSLockStateTracker *tracker = [CKKSLockStateTracker globalTracker]; if (tracker && tracker.isLocked == false) { [self.trust ensureOctagonPeerKeys:self.circle_transport]; } @@ -196,8 +207,7 @@ static NSDictionary* SOSStateMap(void); -(id) initWithGestalt:(CFDictionaryRef)newGestalt factory:(SOSDataSourceFactoryRef)f { - self = [super init]; - if(self){ + if ((self = [super init])) { self.queue = dispatch_queue_create("Account Queue", DISPATCH_QUEUE_SERIAL); self.gestalt = [[NSDictionary alloc] initWithDictionary:(__bridge NSDictionary * _Nonnull)(newGestalt)]; @@ -224,15 +234,17 @@ static NSDictionary* SOSStateMap(void); self.circle_rings_retirements_need_attention = false; self.engine_peer_state_needs_repair = false; self.key_interests_need_updating = false; + self.need_backup_peers_created_after_backup_key_set = false; self.backup_key =nil; self.deviceID = nil; self.waitForInitialSync_blocks = [NSMutableDictionary dictionary]; self.accountKeyIsTrusted = false; - self.accountKeyDerivationParamters = NULL; + self.accountKeyDerivationParameters = NULL; self.accountKey = NULL; self.previousAccountKey = NULL; + self.peerPublicKey = NULL; self.saveBlock = nil; @@ -240,6 +252,7 @@ static NSDictionary* SOSStateMap(void); [self ensureFactoryCircles]; SOSAccountEnsureUUID(self); + self.accountIsChanging = false; #if OCTAGON [self setupStateMachine]; @@ -294,7 +307,7 @@ static NSDictionary* SOSStateMap(void); - (void)kvsPerformanceCounters:(void(^)(NSDictionary *))reply { /* Need to collect performance counters from all subsystems, not just circle transport, don't have counters yet though */ - SOSCloudKeychainRequestPerfCounters(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) + SOSCloudKeychainRequestPerfCounters(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) { reply((__bridge NSDictionary *)returnedValues); }); @@ -343,7 +356,7 @@ static bool SyncKVSAndWait(CFErrorRef *error) { secnoticeq("fresh", "EFP calling SOSCloudKeychainSynchronizeAndWait"); os_activity_initiate("CloudCircle EFRESH", OS_ACTIVITY_FLAG_DEFAULT, ^(void) { - SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(__unused CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(__unused CFDictionaryRef returnedValues, CFErrorRef sync_error) { secnotice("fresh", "EFP returned, callback error: %@", sync_error); success = (sync_error == NULL); @@ -368,7 +381,7 @@ static bool Flush(CFErrorRef *error) { dispatch_semaphore_t wait_for = dispatch_semaphore_create(0); secnotice("flush", "Starting"); - SOSCloudKeychainFlush(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainFlush(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { success = (sync_error == NULL); if (error) { CFRetainAssign(*error, sync_error); @@ -433,57 +446,63 @@ static bool Flush(CFErrorRef *error) { CFReleaseNull(error); }); } - - (void)stashAccountCredential:(NSData *)credential complete:(void(^)(bool success, NSError *error))complete { - CFErrorRef syncerror = NULL; - if (![self syncWaitAndFlush:&syncerror]) { - complete(NULL, (__bridge NSError *)syncerror); - CFReleaseNull(syncerror); - return; - } + dispatch_sync(SOSCCCredentialQueue(), ^{ + CFErrorRef syncerror = NULL; - sleep(1); // make up for keygen time in password based version - let syncdefaults catch up + if (![self syncWaitAndFlush:&syncerror]) { + complete(NULL, (__bridge NSError *)syncerror); + CFReleaseNull(syncerror); + } else { + __block bool success = false; + sleep(1); // make up for keygen time in password based version - let syncdefaults catch up - [self performTransaction:^(SOSAccountTransaction * _Nonnull txn) { - SecKeyRef accountPrivateKey = NULL; - CFErrorRef error = NULL; - NSDictionary *attributes = @{ - (__bridge id)kSecAttrKeyClass : (__bridge id)kSecAttrKeyClassPrivate, - (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeEC, - }; + [self performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + SecKeyRef accountPrivateKey = NULL; + CFErrorRef error = NULL; + NSDictionary *attributes = @{ + (__bridge id)kSecAttrKeyClass : (__bridge id)kSecAttrKeyClassPrivate, + (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeEC, + }; - accountPrivateKey = SecKeyCreateWithData((__bridge CFDataRef)credential, (__bridge CFDictionaryRef)attributes, &error); - if (accountPrivateKey == NULL) { - complete(false, (__bridge NSError *)error); - secnotice("pairing", "SecKeyCreateWithData failed: %@", error); - CFReleaseNull(error); - return; + accountPrivateKey = SecKeyCreateWithData((__bridge CFDataRef)credential, (__bridge CFDictionaryRef)attributes, &error); + if (accountPrivateKey == NULL) { + complete(false, (__bridge NSError *)error); + secnotice("pairing", "SecKeyCreateWithData failed: %@", error); + CFReleaseNull(error); + return; + } + + if (!SOSAccountTryUserPrivateKey(self, accountPrivateKey, &error)) { + CFReleaseNull(accountPrivateKey); + complete(false, (__bridge NSError *)error); + secnotice("pairing", "SOSAccountTryUserPrivateKey failed: %@", error); + CFReleaseNull(error); + return; + } + + success = true; + secnotice("pairing", "SOSAccountTryUserPrivateKey succeeded"); + + CFReleaseNull(accountPrivateKey); + complete(true, NULL); + }]; + + // This makes getting the private key the same as Asserting the password - we read all the other things + // that we just expressed interest in. + + if(success) { + CFErrorRef localError = NULL; + if (!Flush(&localError)) { + // we're still setup with the private key - just report this. + secnotice("pairing", "failed final flush: %@", localError); + } + CFReleaseNull(localError); + } } - - if (!SOSAccountTryUserPrivateKey(self, accountPrivateKey, &error)) { - CFReleaseNull(accountPrivateKey); - complete(false, (__bridge NSError *)error); - secnotice("pairing", "SOSAccountTryUserPrivateKey failed: %@", error); - CFReleaseNull(error); - return; - } - - secnotice("pairing", "SOSAccountTryUserPrivateKey succeeded"); - - CFReleaseNull(accountPrivateKey); - complete(true, NULL); - }]; - - // This makes getting the private key the same as Asserting the password - we read all the other things - // that we just expressed interest in. - CFErrorRef error = NULL; - if (!Flush(&error)) { - secnotice("pairing", "failed final flush: %@", error ? error : NULL); - return; - } - CFReleaseNull(error); + }); } - (void)myPeerInfo:(void (^)(NSData *, NSError *))complete @@ -624,6 +643,75 @@ static bool Flush(CFErrorRef *error) { complete(json, err); } +- (void) iCloudIdentityStatus_internal: (void(^)(NSDictionary *tableSpid, NSError *error))complete { + CFErrorRef localError = NULL; + NSMutableDictionary *tableSPID = [NSMutableDictionary new]; + + if(![self isInCircle: &localError]) { + complete(tableSPID, (__bridge NSError *)localError); + return; + } + + // Make set of SPIDs for iCloud Identity PeerInfos + NSMutableSet *peerInfoSPIDs = [[NSMutableSet alloc] init]; + SOSCircleForEachiCloudIdentityPeer(self.trust.trustedCircle , ^(SOSPeerInfoRef peer) { + NSString *peerID = CFBridgingRelease(CFStringCreateCopy(kCFAllocatorDefault, SOSPeerInfoGetPeerID(peer))); + if(peerID) { + [ peerInfoSPIDs addObject:peerID]; + } + }); + + // Make set of SPIDs for iCloud Identity Private Keys + NSMutableSet *privateKeySPIDs = [[NSMutableSet alloc] init]; + SOSiCloudIdentityPrivateKeyForEach(^(SecKeyRef privKey) { + CFErrorRef localError = NULL; + CFStringRef keyID = SOSCopyIDOfKey(privKey, &localError); + if(keyID) { + NSString *peerID = CFBridgingRelease(keyID); + [ privateKeySPIDs addObject:peerID]; + } else { + secnotice("iCloudIdentity", "couldn't make ID from key (%@)", localError); + } + CFReleaseNull(localError); + }); + + NSMutableSet *completeIdentity = [peerInfoSPIDs mutableCopy]; + if([peerInfoSPIDs count] > 0 && [privateKeySPIDs count] > 0) { + [ completeIdentity intersectSet:privateKeySPIDs]; + } else { + completeIdentity = nil; + } + + NSMutableSet *keyOnly = [privateKeySPIDs mutableCopy]; + if([peerInfoSPIDs count] > 0 && [keyOnly count] > 0) { + [ keyOnly minusSet: peerInfoSPIDs ]; + } + + NSMutableSet *peerOnly = [peerInfoSPIDs mutableCopy]; + if([peerOnly count] > 0 && [privateKeySPIDs count] > 0) { + [ peerOnly minusSet: privateKeySPIDs ]; + } + + tableSPID[kSOSIdentityStatusCompleteIdentity] = [completeIdentity allObjects]; + tableSPID[kSOSIdentityStatusKeyOnly] = [keyOnly allObjects]; + tableSPID[kSOSIdentityStatusPeerOnly] = [peerOnly allObjects]; + + complete(tableSPID, nil); +} + +- (void)iCloudIdentityStatus: (void (^)(NSData *json, NSError *error))complete { + [self iCloudIdentityStatus_internal:^(NSDictionary *tableSpid, NSError *error) { + NSError *err = nil; + NSData *json = [NSJSONSerialization dataWithJSONObject:tableSpid + options:(NSJSONWritingPrettyPrinted | NSJSONWritingSortedKeys) + error:&err]; + if (!json) { + secnotice("iCloudIdentity", "Error during iCloudIdentityStatus JSONification: %@", err.localizedDescription); + } + complete(json, err); + }]; +} + #else + (SOSAccountGhostBustingOptions) ghostBustGetRampSettings { @@ -660,7 +748,16 @@ static bool Flush(CFErrorRef *error) { return false; } -#endif +- (void)iCloudIdentityStatus:(void (^)(NSData *, NSError *))complete { + complete(nil, nil); +} + + +- (void)iCloudIdentityStatus_internal:(void (^)(NSDictionary *, NSError *))complete { + complete(nil, nil); +} + +#endif // !(TARGET_OS_OSX || TARGET_OS_IOS) - (void)circleJoiningBlob:(NSData *)applicant complete:(void (^)(NSData *blob, NSError *))complete { @@ -803,6 +900,16 @@ static bool Flush(CFErrorRef *error) { } } +- (void)removeV0Peers:(void (^)(bool, NSError *))reply { + [self performTransaction:^(SOSAccountTransaction *txn) { + CFErrorRef localError = NULL; + bool result = SOSAccountRemoveV0Clients(txn.account, &localError); + reply(result, (__bridge NSError *)localError); + CFReleaseNull(localError); + }]; +} + + // // MARK: Save Block // @@ -851,6 +958,17 @@ void SOSAccountAssertDSID(SOSAccount* account, CFStringRef dsid) { } } +SecKeyRef SOSAccountCopyDevicePrivateKey(SOSAccount* account, CFErrorRef *error) { + if(account.peerPublicKey) { + return SecKeyCopyMatchingPrivateKey(account.peerPublicKey, error); + } + return NULL; +} + +SecKeyRef SOSAccountCopyDevicePublicKey(SOSAccount* account, CFErrorRef *error) { + return SecKeyCopyPublicKey(account.peerPublicKey); +} + void SOSAccountPendDisableViewSet(SOSAccount* account, CFSetRef disabledViews) { @@ -989,7 +1107,6 @@ void SOSAccountSetToNew(SOSAccount* a) result = do_keychain_delete_sbd(); (void) result; secdebug("set to new", "result for deleting sbd: %d", result); - a.accountKeyIsTrusted = false; if (a.user_private_timer) { dispatch_source_cancel(a.user_private_timer); @@ -1014,11 +1131,30 @@ void SOSAccountSetToNew(SOSAccount* a) a.circle_transport = NULL; a.kvs_message_transport = nil; + a._password_tmp = nil; + a.circle_rings_retirements_need_attention = true; + a.engine_peer_state_needs_repair = true; + a.key_interests_need_updating = true; + a.need_backup_peers_created_after_backup_key_set = true; + + a.accountKeyIsTrusted = false; + a.accountKeyDerivationParameters = nil; + a.accountPrivateKey = NULL; + a.accountKey = NULL; + a.previousAccountKey = NULL; + a.peerPublicKey = NULL; + a.backup_key = nil; + a.notifyCircleChangeOnExit = true; + a.notifyViewChangeOnExit = true; + a.notifyBackupOnExit = true; + + a.octagonSigningFullKeyRef = NULL; + a.octagonEncryptionFullKeyRef = NULL; a.trust = nil; + // setting a new trust object resets all the rings from this peer's point of view - they're in the SOSAccountTrustClassic dictionary a.trust = [[SOSAccountTrustClassic alloc]initWithRetirees:[NSMutableSet set] fpi:NULL circle:NULL departureCode:kSOSDepartureReasonError peerExpansion:[NSMutableDictionary dictionary]]; - - [a ensureFactoryCircles]; // Does rings too + [a ensureFactoryCircles]; // By resetting our expansion dictionary we've reset our UUID, so we'll be notified properly SOSAccountEnsureUUID(a); @@ -1026,26 +1162,6 @@ void SOSAccountSetToNew(SOSAccount* a) a.key_interests_need_updating = true; } -bool SOSAccountIsNew(SOSAccount* account, CFErrorRef *error){ - bool result = false; - SOSAccountTrustClassic* trust = account.trust; - if(account.accountKeyIsTrusted != false || trust.departureCode != kSOSNeverAppliedToCircle || - CFSetGetCount((__bridge CFSetRef)trust.retirees) != 0) - return result; - - if(trust.retirees != nil) - return result; - if(trust.expansion != nil) - return result; - - if(account.user_private_timer != NULL || account.lock_notification_token != NOTIFY_TOKEN_INVALID) - return result; - - result = true; - - return result; -} - dispatch_queue_t SOSAccountGetQueue(SOSAccount* account) { return account.queue; } @@ -1160,97 +1276,7 @@ void SOSAccountRemoveChangeBlock(SOSAccount* a, SOSAccountCircleMembershipChang void SOSAccountPurgeIdentity(SOSAccount* account) { SOSAccountTrustClassic *trust = account.trust; - SOSFullPeerInfoRef identity = trust.fullPeerInfo; - - if (identity) { - // Purge private key but don't return error if we can't. - CFErrorRef purgeError = NULL; - if (!SOSFullPeerInfoPurgePersistentKey(identity, &purgeError)) { - secwarning("Couldn't purge persistent key for %@ [%@]", identity, purgeError); - } - CFReleaseNull(purgeError); - - trust.fullPeerInfo = nil; - } -} - -bool sosAccountLeaveCircleWithAnalytics(SOSAccount* account, SOSCircleRef circle, NSData* parentData, CFErrorRef* error) { - SOSAccountTrustClassic *trust = account.trust; - SOSFullPeerInfoRef identity = trust.fullPeerInfo; - NSMutableSet* retirees = trust.retirees; - - NSError* localError = nil; - SFSignInAnalytics* parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentData error:&localError]; - - SOSFullPeerInfoRef fpi = identity; - if(!fpi) return false; - - CFErrorRef retiredError = NULL; - - bool retval = false; - - SFSignInAnalytics *promoteToRetiredEvent = [parent newSubTaskForEvent:@"promoteToRetiredEvent"]; - SOSPeerInfoRef retire_peer = SOSFullPeerInfoPromoteToRetiredAndCopy(fpi, &retiredError); - if(retiredError){ - [promoteToRetiredEvent logRecoverableError:(__bridge NSError*)retiredError]; - secerror("SOSFullPeerInfoPromoteToRetiredAndCopy error: %@", retiredError); - if(error){ - *error = retiredError; - }else{ - CFReleaseNull(retiredError); - } - } - [promoteToRetiredEvent stopWithAttributes:nil]; - - if (!retire_peer) { - secerror("Create ticket failed for peer %@: %@", fpi, localError); - } else { - // See if we need to repost the circle we could either be an applicant or a peer already in the circle - if(SOSCircleHasApplicant(circle, retire_peer, NULL)) { - // Remove our application if we have one. - SOSCircleWithdrawRequest(circle, retire_peer, NULL); - } else if (SOSCircleHasPeer(circle, retire_peer, NULL)) { - if (SOSCircleUpdatePeerInfo(circle, retire_peer)) { - CFErrorRef cleanupError = NULL; - SFSignInAnalytics *cleanupEvent = [parent newSubTaskForEvent:@"cleanupAfterPeerEvent"]; - if (![account.trust cleanupAfterPeer:account.kvs_message_transport circleTransport:account.circle_transport seconds:RETIREMENT_FINALIZATION_SECONDS circle:circle cleanupPeer:retire_peer err:&cleanupError]) { - secerror("Error cleanup up after peer (%@): %@", retire_peer, cleanupError); - } - [cleanupEvent stopWithAttributes:nil]; - CFReleaseSafe(cleanupError); - } - } - - // Store the retirement record locally. - CFSetAddValue((__bridge CFMutableSetRef)retirees, retire_peer); - - trust.retirees = retirees; - - // Write retirement to Transport - CFErrorRef postError = NULL; - SFSignInAnalytics *postRestirementEvent = [parent newSubTaskForEvent:@"postRestirementEvent"]; - if(![account.circle_transport postRetirement:SOSCircleGetName(circle) peer:retire_peer err:&postError]){ - [postRestirementEvent logRecoverableError:(__bridge NSError*)postError]; - secwarning("Couldn't post retirement (%@)", postError); - } - [postRestirementEvent stopWithAttributes:nil]; - - SFSignInAnalytics *flushChangesEvent = [parent newSubTaskForEvent:@"flushChangesEvent"]; - - if(![account.circle_transport flushChanges:&postError]){ - [flushChangesEvent logRecoverableError:(__bridge NSError*)postError]; - secwarning("Couldn't flush retirement data (%@)", postError); - } - [flushChangesEvent stopWithAttributes:nil]; - CFReleaseNull(postError); - } - SFSignInAnalytics *purgeIdentityEvent = [parent newSubTaskForEvent:@"purgeIdentityEvent"]; - SOSAccountPurgeIdentity(account); - [purgeIdentityEvent stopWithAttributes:nil]; - retval = true; - - CFReleaseNull(retire_peer); - return retval; + [trust purgeIdentity]; } bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, CFErrorRef* error) { @@ -1258,14 +1284,24 @@ bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, CFErrorRef* SOSFullPeerInfoRef identity = trust.fullPeerInfo; NSMutableSet* retirees = trust.retirees; + NSError* localError = nil; SOSFullPeerInfoRef fpi = identity; if(!fpi) return false; - CFErrorRef localError = NULL; + CFErrorRef retiredError = NULL; bool retval = false; + + SOSPeerInfoRef retire_peer = SOSFullPeerInfoPromoteToRetiredAndCopy(fpi, &retiredError); + if(retiredError){ + secerror("SOSFullPeerInfoPromoteToRetiredAndCopy error: %@", retiredError); + if(error){ + *error = retiredError; + }else{ + CFReleaseNull(retiredError); + } + } - SOSPeerInfoRef retire_peer = SOSFullPeerInfoPromoteToRetiredAndCopy(fpi, &localError); if (!retire_peer) { secerror("Create ticket failed for peer %@: %@", fpi, localError); } else { @@ -1287,15 +1323,20 @@ bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, CFErrorRef* CFSetAddValue((__bridge CFMutableSetRef)retirees, retire_peer); trust.retirees = retirees; - + // Write retirement to Transport CFErrorRef postError = NULL; if(![account.circle_transport postRetirement:SOSCircleGetName(circle) peer:retire_peer err:&postError]){ + secwarning("Couldn't post retirement (%@)", postError); } + + + if(![account.circle_transport flushChanges:&postError]){ secwarning("Couldn't flush retirement data (%@)", postError); } + CFReleaseNull(postError); } @@ -1303,47 +1344,10 @@ bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, CFErrorRef* retval = true; - CFReleaseNull(localError); CFReleaseNull(retire_peer); return retval; } -bool sosAccountLeaveRing(SOSAccount* account, SOSRingRef ring, CFErrorRef* error) { - SOSAccountTrustClassic *trust = account.trust; - SOSFullPeerInfoRef identity = trust.fullPeerInfo; - - SOSFullPeerInfoRef fpi = identity; - if(!fpi) return false; - SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi); - CFStringRef peerID = SOSPeerInfoGetPeerID(pi); - - CFErrorRef localError = NULL; - - bool retval = false; - bool writeRing = false; - bool writePeerInfo = false; - - if(SOSRingHasPeerID(ring, peerID)) { - writePeerInfo = true; - } - - if(writePeerInfo || writeRing) { - SOSRingWithdraw(ring, NULL, fpi, error); - } - - if (writeRing) { - CFDataRef ring_data = SOSRingCopyEncodedData(ring, error); - - if (ring_data) { - [account.circle_transport kvsRingPostRing:SOSRingGetName(ring) ring:ring_data err:NULL]; - } - CFReleaseNull(ring_data); - } - retval = true; - CFReleaseNull(localError); - return retval; -} - bool SOSAccountPostDebugScope(SOSAccount* account, CFTypeRef scope, CFErrorRef *error) { bool result = false; if (account.circle_transport) { @@ -1434,61 +1438,22 @@ bool SOSAccountRemoveIncompleteiCloudIdentities(SOSAccount* account, SOSCircleR // MARK: start backups // - -- (bool)_onQueueEnsureInBackupRings { - __block bool result = false; - __block CFErrorRef error = NULL; - secnotice("backup", "Ensuring in rings"); +// This needs to be called within a transaction. It only processes one view at a time +// this will return true if work was done. +- (bool)_onQueueEnsureInBackupRings: (CFStringRef) viewName { + __block bool workDone = false; dispatch_assert_queue(self.queue); - if(!self.backup_key){ - return true; - } - - if(!SOSBSKBIsGoodBackupPublic((__bridge CFDataRef)self.backup_key, &error)){ - secnotice("backupkey", "account backup key isn't valid: %@", error); - self.backup_key = nil; - CFReleaseNull(error); - return false; - } - - NSData *peerBackupKey = (__bridge_transfer NSData*)SOSPeerInfoCopyBackupKey(self.peerInfo); - if(![peerBackupKey isEqual:self.backup_key]) { - result = SOSAccountUpdatePeerInfo(self, CFSTR("Backup public key"), &error, ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *error) { - return SOSFullPeerInfoUpdateBackupKey(fpi, (__bridge CFDataRef)(self.backup_key), error); - }); - if (!result) { - secnotice("backupkey", "Failed to setup backup public key in peerInfo from account: %@", error); - CFReleaseNull(error); - return result; - } - } - - // It's a good key, we're going with it. Stop backing up the old way. - CFErrorRef localError = NULL; - if (!SOSDeleteV0Keybag(&localError)) { - secerror("Failed to delete v0 keybag: %@", localError); - } - CFReleaseNull(localError); - // Setup backups the new way. - SOSAccountForEachBackupView(self, ^(const void *value) { - CFStringRef viewName = asString(value, NULL); - bool resetRing = SOSAccountValidateBackupRingForView(self, viewName, NULL); - if(resetRing) { - SOSAccountUpdateBackupRing(self, viewName, NULL, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) { - SOSRingRef newRing = SOSAccountCreateBackupRingForView(self, viewName, error); - return newRing; - }); - } - }); - - if (!result) { - secnotice("backupkey", "Failed to setup backup public key: %@", error); + if(SOSAccountValidateBackupRingForView(self, viewName, NULL)) { + workDone = SOSAccountUpdateBackupRing(self, viewName, NULL, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) { + SOSRingRef newRing = SOSAccountCreateBackupRingForView(self, viewName, error); + secnotice("backup", "Reset backup ring %@ %s", viewName, (newRing) ? "success": "failed"); + return newRing; + }); } - CFReleaseNull(error); - return result; + return workDone; } // @@ -1528,20 +1493,14 @@ CFDataRef SOSAccountCopyRecoveryPublicKey(SOSAccountTransaction* txn, CFErrorRef // MARK: Joining // -static bool SOSAccountJoinCircleWithAnalytics(SOSAccountTransaction* aTxn, SecKeyRef user_key, - bool use_cloud_peer, NSData* parentEvent, CFErrorRef* error) { +static bool SOSAccountJoinCircle(SOSAccountTransaction* aTxn, SecKeyRef user_key, bool use_cloud_peer, CFErrorRef* error) { SOSAccount* account = aTxn.account; SOSAccountTrustClassic *trust = account.trust; __block bool result = false; __block SOSFullPeerInfoRef cloud_full_peer = NULL; - SFSignInAnalytics *ensureFullPeerAvailableEvent = nil; - NSError* localError = nil; - SFSignInAnalytics* parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - require_action_quiet(trust.trustedCircle, fail, SOSCreateErrorWithFormat(kSOSErrorPeerNotFound, NULL, error, NULL, CFSTR("Don't have circle when joining???"))); - ensureFullPeerAvailableEvent = [parent newSubTaskForEvent:@"ensureFullPeerAvailableEvent"]; - require_quiet([account.trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)account.gestalt deviceID:(__bridge CFStringRef)account.deviceID backupKey:(__bridge CFDataRef)account.backup_key err:error], fail); - [ensureFullPeerAvailableEvent stopWithAttributes:nil]; + + require_quiet([account.trust ensureFullPeerAvailable: account err:error], fail); SOSFullPeerInfoRef myCirclePeer = trust.fullPeerInfo; if (SOSCircleCountPeers(trust.trustedCircle) == 0 || SOSAccountGhostResultsInReset(account)) { @@ -1553,56 +1512,7 @@ static bool SOSAccountJoinCircleWithAnalytics(SOSAccountTransaction* aTxn, SecKe if (use_cloud_peer) { cloud_full_peer = SOSCircleCopyiCloudFullPeerInfoRef(trust.trustedCircle, NULL); } - SFSignInAnalytics *acceptApplicantEvent = [parent newSubTaskForEvent:@"acceptApplicantEvent"]; - [account.trust modifyCircle:account.circle_transport err:error action:^bool(SOSCircleRef circle) { - result = SOSAccountAddEscrowToPeerInfo(account, myCirclePeer, error); - result &= SOSCircleRequestAdmission(circle, user_key, myCirclePeer, error); - trust.departureCode = kSOSNeverLeftCircle; - if(result && cloud_full_peer) { - CFErrorRef localError = NULL; - CFStringRef cloudid = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(cloud_full_peer)); - require_quiet(cloudid, finish); - require_quiet(SOSCircleHasActivePeerWithID(circle, cloudid, &localError), finish); - require_quiet(SOSCircleAcceptRequest(circle, user_key, cloud_full_peer, SOSFullPeerInfoGetPeerInfo(myCirclePeer), &localError), finish); - finish: - if (localError){ - [acceptApplicantEvent logRecoverableError:(__bridge NSError *)(localError)]; - secerror("Failed to join with cloud identity: %@", localError); - CFReleaseNull(localError); - } - } - return result; - }]; - [acceptApplicantEvent stopWithAttributes:nil]; - if (use_cloud_peer) { - SFSignInAnalytics *updateOutOfDateSyncViewsEvent = [acceptApplicantEvent newSubTaskForEvent:@"updateOutOfDateSyncViewsEvent"]; - SOSAccountUpdateOutOfSyncViews(aTxn, SOSViewsGetAllCurrent()); - [updateOutOfDateSyncViewsEvent stopWithAttributes:nil]; - } - } -fail: - CFReleaseNull(cloud_full_peer); - return result; -} -static bool SOSAccountJoinCircle(SOSAccountTransaction* aTxn, SecKeyRef user_key, - bool use_cloud_peer, CFErrorRef* error) { - SOSAccount* account = aTxn.account; - SOSAccountTrustClassic *trust = account.trust; - __block bool result = false; - __block SOSFullPeerInfoRef cloud_full_peer = NULL; - require_action_quiet(trust.trustedCircle, fail, SOSCreateErrorWithFormat(kSOSErrorPeerNotFound, NULL, error, NULL, CFSTR("Don't have circle when joining???"))); - require_quiet([account.trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)account.gestalt deviceID:(__bridge CFStringRef)account.deviceID backupKey:(__bridge CFDataRef)account.backup_key err:error], fail); - SOSFullPeerInfoRef myCirclePeer = trust.fullPeerInfo; - if (SOSCircleCountPeers(trust.trustedCircle) == 0 || SOSAccountGhostResultsInReset(account)) { - secnotice("resetToOffering", "Resetting circle to offering since there are no peers"); - // this also clears initial sync data - result = [account.trust resetCircleToOffering:aTxn userKey:user_key err:error]; - } else { - SOSAccountInitializeInitialSync(account); - if (use_cloud_peer) { - cloud_full_peer = SOSCircleCopyiCloudFullPeerInfoRef(trust.trustedCircle, NULL); - } [account.trust modifyCircle:account.circle_transport err:error action:^bool(SOSCircleRef circle) { result = SOSAccountAddEscrowToPeerInfo(account, myCirclePeer, error); result &= SOSCircleRequestAdmission(circle, user_key, myCirclePeer, error); @@ -1621,6 +1531,7 @@ static bool SOSAccountJoinCircle(SOSAccountTransaction* aTxn, SecKeyRef user_key } return result; }]; + if (use_cloud_peer) { SOSAccountUpdateOutOfSyncViews(aTxn, SOSViewsGetAllCurrent()); } @@ -1630,7 +1541,7 @@ fail: return result; } -static bool SOSAccountJoinCirclesWithAnalytics_internal(SOSAccountTransaction* aTxn, bool use_cloud_identity, NSData* parentEvent, CFErrorRef* error) { +static bool SOSAccountJoinCircles_internal(SOSAccountTransaction* aTxn, bool use_cloud_identity, CFErrorRef* error) { SOSAccount* account = aTxn.account; SOSAccountTrustClassic *trust = account.trust; bool success = false; @@ -1638,7 +1549,21 @@ static bool SOSAccountJoinCirclesWithAnalytics_internal(SOSAccountTransaction* a SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); require_quiet(user_key, done); // Fail if we don't get one. - require_action_quiet(trust.trustedCircle, done, SOSErrorCreate(kSOSErrorNoCircle, error, NULL, CFSTR("No circle to join"))); + if(!trust.trustedCircle || SOSCircleCountPeers(trust.trustedCircle) == 0 ) { + secnotice("resetToOffering", "Resetting circle to offering because it's empty and we're joining"); + return [account.trust resetCircleToOffering:aTxn userKey:user_key err:error]; + } + + if(SOSCircleHasPeerWithID(trust.trustedCircle, (__bridge CFStringRef)(account.peerID), NULL)) { + // We shouldn't be at this point if we're already in circle. + secnotice("circleops", "attempt to join a circle we're in - continuing."); + return true; // let things above us think we're in circle - because we are. + } + + if(!SOSCircleVerify(trust.trustedCircle, account.accountKey, NULL)) { + secnotice("resetToOffering", "Resetting circle to offering since we are new and it doesn't verify with current userKey"); + return [account.trust resetCircleToOffering:aTxn userKey:user_key err:error]; + } if (trust.fullPeerInfo != NULL) { SOSPeerInfoRef myPeer = trust.peerInfo; @@ -1654,93 +1579,53 @@ static bool SOSAccountJoinCirclesWithAnalytics_internal(SOSAccountTransaction* a } } - success = SOSAccountJoinCircleWithAnalytics(aTxn, user_key, use_cloud_identity, parentEvent, error); - - require_quiet(success, done); - - trust.departureCode = kSOSNeverLeftCircle; - -done: - return success; -} - -static bool SOSAccountJoinCircles_internal(SOSAccountTransaction* aTxn, bool use_cloud_identity, CFErrorRef* error) { - SOSAccount* account = aTxn.account; - SOSAccountTrustClassic *trust = account.trust; - bool success = false; - - SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); - require_quiet(user_key, done); // Fail if we don't get one. - - require_action_quiet(trust.trustedCircle, done, SOSErrorCreate(kSOSErrorNoCircle, error, NULL, CFSTR("No circle to join"))); - - if (trust.fullPeerInfo != NULL) { - SOSPeerInfoRef myPeer = trust.peerInfo; - success = SOSCircleHasPeer(trust.trustedCircle, myPeer, NULL); - require_quiet(!success, done); - - SOSCircleRemoveRejectedPeer(trust.trustedCircle, myPeer, NULL); // If we were rejected we should remove it now. - - if (!SOSCircleHasApplicant(trust.trustedCircle, myPeer, NULL)) { - secerror("Resetting my peer (ID: %@) for circle '%@' during application", SOSPeerInfoGetPeerID(myPeer), SOSCircleGetName(trust.trustedCircle)); - - trust.fullPeerInfo = NULL; - } - } - success = SOSAccountJoinCircle(aTxn, user_key, use_cloud_identity, error); require_quiet(success, done); - + trust.departureCode = kSOSNeverLeftCircle; done: return success; } -bool SOSAccountJoinCirclesWithAnalytics(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error) { - secnotice("circleOps", "Normal path circle join (SOSAccountJoinCirclesWithAnalytics)"); - return SOSAccountJoinCirclesWithAnalytics_internal(aTxn, false, parentEvent, error); -} - bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, CFErrorRef* error) { - secnotice("circleOps", "Normal path circle join (SOSAccountJoinCircles)"); + secnotice("circleOps", "Normal path circle join (SOSAccountJoinCircles)"); return SOSAccountJoinCircles_internal(aTxn, false, error); } bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, CFErrorRef* error) { - secnotice("circleOps", "Joining after restore (SOSAccountJoinCirclesAfterRestore)"); - return SOSAccountJoinCircles_internal(aTxn, true, error); -} - -bool SOSAccountJoinCirclesAfterRestoreWithAnalytics(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error) { secnotice("circleOps", "Joining after restore (SOSAccountJoinCirclesAfterRestore)"); - return SOSAccountJoinCirclesWithAnalytics_internal(aTxn, true, parentEvent, error); + return SOSAccountJoinCircles_internal(aTxn, true, error); } bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, CFErrorRef* error) { bool result = false; CFMutableSetRef peersToRemove = NULL; + + CFStringArrayPerformWithDescription(peers, ^(CFStringRef description) { + secnotice("circleOps", "Attempting to remove peer set %@", description); + }); + SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); - if(!user_key){ + if (!user_key) { secnotice("circleOps", "Can't remove without userKey"); return result; } + SOSFullPeerInfoRef me_full = account.fullPeerInfo; SOSPeerInfoRef me = account.peerInfo; - if(!(me_full && me)) - { + if (!(me_full && me)) { secnotice("circleOps", "Can't remove without being active peer"); SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("Can't remove without being active peer")); return result; } - + result = true; // beyond this point failures would be rolled up in AccountModifyCircle. peersToRemove = CFSetCreateMutableForSOSPeerInfosByIDWithArray(kCFAllocatorDefault, peers); - if(!peersToRemove) - { + if (!peersToRemove) { CFReleaseNull(peersToRemove); secnotice("circleOps", "No peerSet to remove"); return result; @@ -1753,10 +1638,12 @@ bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, CFE result &= [account.trust modifyCircle:account.circle_transport err:error action:^(SOSCircleRef circle) { bool success = false; - if(CFSetGetCount(peersToRemove) != 0) { + if (CFSetGetCount(peersToRemove) != 0) { require_quiet(SOSCircleRemovePeers(circle, user_key, me_full, peersToRemove, error), done); success = SOSAccountGenerationSignatureUpdate(account, error); - } else success = true; + } else { + success = true; + } if (success && leaveCircle) { secnotice("circleOps", "Leaving circle by client request (SOSAccountRemovePeersFromCircle)"); @@ -1767,79 +1654,8 @@ bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, CFE return success; }]; - - if(result) { - CFStringSetPerformWithDescription(peersToRemove, ^(CFStringRef description) { - secnotice("circleOps", "Removed Peers from circle %@", description); - }); - } - CFReleaseNull(peersToRemove); - return result; -} - - -bool SOSAccountRemovePeersFromCircleWithAnalytics(SOSAccount* account, CFArrayRef peers, NSData* parentEvent, CFErrorRef* error) -{ - - NSError* localError = nil; - SFSignInAnalytics* parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - - bool result = false; - CFMutableSetRef peersToRemove = NULL; - SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); - if(!user_key){ - secnotice("circleOps", "Can't remove without userKey"); - return result; - } - SOSFullPeerInfoRef me_full = account.fullPeerInfo; - SOSPeerInfoRef me = account.peerInfo; - if(!(me_full && me)) - { - secnotice("circleOps", "Can't remove without being active peer"); - SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("Can't remove without being active peer")); - return result; - } - - result = true; // beyond this point failures would be rolled up in AccountModifyCircle. - - peersToRemove = CFSetCreateMutableForSOSPeerInfosByIDWithArray(kCFAllocatorDefault, peers); - if(!peersToRemove) - { - CFReleaseNull(peersToRemove); - secnotice("circleOps", "No peerSet to remove"); - return result; - } - - // If we're one of the peers expected to leave - note that and then remove ourselves from the set (different handling). - bool leaveCircle = CFSetContainsValue(peersToRemove, me); - CFSetRemoveValue(peersToRemove, me); - - result &= [account.trust modifyCircle:account.circle_transport err:error action:^(SOSCircleRef circle) { - bool success = false; - - if(CFSetGetCount(peersToRemove) != 0) { - require_quiet(SOSCircleRemovePeers(circle, user_key, me_full, peersToRemove, error), done); - SFSignInAnalytics *generationSignatureUpdateEvent = [parent newSubTaskForEvent:@"generationSignatureUpdateEvent"]; - success = SOSAccountGenerationSignatureUpdate(account, error); - if(error && *error){ - NSError* signatureUpdateError = (__bridge NSError*)*error; - [generationSignatureUpdateEvent logUnrecoverableError:signatureUpdateError]; - } - [generationSignatureUpdateEvent stopWithAttributes:nil]; - } else success = true; - - if (success && leaveCircle) { - secnotice("circleOps", "Leaving circle by client request (SOSAccountRemovePeersFromCircle)"); - success = sosAccountLeaveCircleWithAnalytics(account, circle, parentEvent, error); - } - - done: - return success; - - }]; - - if(result) { + if (result) { CFStringSetPerformWithDescription(peersToRemove, ^(CFStringRef description) { secnotice("circleOps", "Removed Peers from circle %@", description); }); @@ -1850,7 +1666,7 @@ bool SOSAccountRemovePeersFromCircleWithAnalytics(SOSAccount* account, CFArrayR } bool SOSAccountBail(SOSAccount* account, uint64_t limit_in_seconds, CFErrorRef* error) { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_queue_t queue = dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0); dispatch_group_t group = dispatch_group_create(); SOSAccountTrustClassic *trust = account.trust; __block bool result = false; @@ -1870,7 +1686,6 @@ bool SOSAccountBail(SOSAccount* account, uint64_t limit_in_seconds, CFErrorRef* return result; } - // // MARK: Application // @@ -1936,11 +1751,6 @@ bool SOSAccountRejectApplicants(SOSAccount* account, CFArrayRef applicants, CFE return success; } - -CFStringRef SOSAccountCopyIncompatibilityInfo(SOSAccount* account, CFErrorRef* error) { - return CFSTR("We're compatible, go away"); -} - enum DepartureReason SOSAccountGetLastDepartureReason(SOSAccount* account, CFErrorRef* error) { SOSAccountTrustClassic *trust = account.trust; return trust.departureCode; @@ -2028,28 +1838,6 @@ CFTypeRef SOSAccountGetValue(SOSAccount* account, CFStringRef key, CFErrorRef * return (__bridge CFTypeRef)([trust.expansion objectForKey:(__bridge NSString* _Nonnull)(key)]); } -bool SOSAccountAddEscrowRecords(SOSAccount* account, CFStringRef dsid, CFDictionaryRef record, CFErrorRef *error){ - CFMutableDictionaryRef escrowRecords = (CFMutableDictionaryRef)SOSAccountGetValue(account, kSOSEscrowRecord, error); - CFMutableDictionaryRef escrowCopied = NULL; - bool success = false; - - if(isDictionary(escrowRecords) && escrowRecords != NULL) - escrowCopied = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(escrowRecords), escrowRecords); - else - escrowCopied = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - CFDictionaryAddValue(escrowCopied, dsid, record); - SOSAccountSetValue(account, kSOSEscrowRecord, escrowCopied, error); - - if(*error == NULL) - success = true; - - CFReleaseNull(escrowCopied); - - return success; - -} - bool SOSAccountAddEscrowToPeerInfo(SOSAccount* account, SOSFullPeerInfoRef myPeer, CFErrorRef *error){ bool success = false; @@ -2086,7 +1874,7 @@ bool SOSAccountAddEscrowToPeerInfo(SOSAccount* account, SOSFullPeerInfoRef myPe return updated; }]; if(updateRings) { - SOSAccountProcessBackupRings(self, NULL); + SOSAccountProcessBackupRings(self); } } @@ -2163,7 +1951,7 @@ static void SOSAccountWriteLastCleanupTimestampToKVS(SOSAccount* account) dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_queue_t processQueue = dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0); CloudKeychainReplyBlock replyBlock = ^ (CFDictionaryRef returnedValues, CFErrorRef error){ if (error){ @@ -2191,7 +1979,7 @@ bool SOSAccountCleanupAllKVSKeys(SOSAccount* account, CFErrorRef* error) return true; } - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_queue_t processQueue = dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0); NSDictionary *keysAndValues = (__bridge_transfer NSDictionary*)SOSAccountGetObjectsFromCloud(processQueue, error); NSMutableArray *peerIDs = [NSMutableArray array]; @@ -2235,38 +2023,12 @@ bool SOSAccountCleanupAllKVSKeys(SOSAccount* account, CFErrorRef* error) } -bool SOSAccountPopulateKVSWithBadKeys(SOSAccount* account, CFErrorRef* error) { - - NSMutableDictionary *testKeysAndValues = [NSMutableDictionary dictionary]; - [testKeysAndValues setObject:@"deadbeef" forKey:@"-ak|asdfjkl;asdfjk;"]; - [testKeysAndValues setObject:@"foobar" forKey:@"ak|asdfasdfasdf:qwerqwerqwer"]; - [testKeysAndValues setObject:@"oldhistorycircle" forKey:@"poak|asdfasdfasdfasdf"]; - [testKeysAndValues setObject:@"oldhistorycircle" forKey:@"po|asdfasdfasdfasdfasdfasdf"]; - [testKeysAndValues setObject:@"oldhistorycircle" forKey:@"k>KeyParm"]; - - dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); - dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - - CloudKeychainReplyBlock replyBlock = ^ (CFDictionaryRef returnedValues, CFErrorRef error){ - if (error){ - secerror("SOSCloudKeychainPutObjectsInCloud returned error: %@", error); - } - dispatch_semaphore_signal(waitSemaphore); - }; - - SOSCloudKeychainPutObjectsInCloud((__bridge CFDictionaryRef)(testKeysAndValues), processQueue, replyBlock); - dispatch_semaphore_wait(waitSemaphore, finishTime); - - return true; -} - SOSPeerInfoRef SOSAccountCopyApplication(SOSAccount* account, CFErrorRef* error) { SOSPeerInfoRef applicant = NULL; SOSAccountTrustClassic *trust = account.trust; SecKeyRef userKey = SOSAccountGetPrivateCredential(account, error); if(!userKey) return false; - if(![trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)(account.gestalt) deviceID:(__bridge CFStringRef)(account.deviceID) backupKey:(__bridge CFDataRef)(account.backup_key) err:error]) + if(![trust ensureFullPeerAvailable:account err:error]) return applicant; if(!SOSFullPeerInfoPromoteToApplication(trust.fullPeerInfo, userKey, error)) return applicant; @@ -2275,6 +2037,36 @@ SOSPeerInfoRef SOSAccountCopyApplication(SOSAccount* account, CFErrorRef* error return applicant; } +#if OCTAGON +static void +AddStrippedTLKs(NSMutableArray* results, NSArray* tlks, NSMutableSet *seenUUID, bool authoritative) +{ + for(CKKSKeychainBackedKey* tlk in tlks) { + NSError* localerror = nil; + CKKSAESSIVKey* keyBytes = [tlk ensureKeyLoaded:&localerror]; + + if(!keyBytes || localerror) { + secnotice("piggy", "Failed to load TLK %@: %@", tlk, localerror); + continue; + } + + NSMutableDictionary* strippedDown = [@{ + (id)kSecValueData : [keyBytes keyMaterial], + (id)kSecAttrServer : tlk.zoneID.zoneName, + (id)kSecAttrAccount : tlk.uuid, + } mutableCopy]; + + if (authoritative) { + strippedDown[@"auth"] = @YES; + } + + secnotice("piggy", "sending TLK %@", tlk); + + [results addObject:strippedDown]; + [seenUUID addObject:tlk.uuid]; + } +} +#endif static void AddStrippedResults(NSMutableArray *results, NSArray *keychainItems, NSMutableSet *seenUUID, bool authoriative) @@ -2316,34 +2108,32 @@ AddStrippedResults(NSMutableArray *results, NSArray *keychainItems, NSMutableSet } static void -AddViewManagerResults(NSMutableArray *results, NSMutableSet *seenUUID) +AddViewManagerResults(NSMutableArray *results, NSMutableSet *seenUUID, bool selectedTLKsOnly) { #if OCTAGON - CKKSViewManager* manager = [CKKSViewManager manager]; + NSError* localError = nil; + NSArray* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:selectedTLKsOnly error:&localError]; - NSDictionary *items = [manager activeTLKs]; - - for (NSString *view in items) { - NSString *uuid = items[view]; - NSDictionary *query = @{ - (id)kSecClass : (id)kSecClassInternetPassword, - (id)kSecUseDataProtectionKeychain : @YES, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccount : uuid, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecMatchLimit : (id)kSecMatchLimitAll, - (id)kSecReturnAttributes: @YES, - (id)kSecReturnData: @YES, - }; - CFTypeRef result = NULL; - if (SecItemCopyMatching((__bridge CFDictionaryRef)query, &result) == 0) { - AddStrippedResults(results, (__bridge NSArray*)result, seenUUID, true); - } - CFReleaseNull(result); + if(localError) { + secnotice("piggy", "unable to fetch TLKs: %@", localError); + return; } + + AddStrippedTLKs(results, tlks, seenUUID, true); #endif } +NSArray* +SOSAccountGetSelectedTLKs(void) +{ + NSMutableArray* results = [NSMutableArray array]; + NSMutableSet *seenUUID = [NSMutableSet set]; + + AddViewManagerResults(results, seenUUID, true); + + return results; +} + NSArray* SOSAccountGetAllTLKs(void) @@ -2352,8 +2142,8 @@ SOSAccountGetAllTLKs(void) NSMutableArray* results = [NSMutableArray array]; NSMutableSet *seenUUID = [NSMutableSet set]; - // first use the TLK from the view manager - AddViewManagerResults(results, seenUUID); + // first use all TLKs from the view manager + AddViewManagerResults(results, seenUUID, false); //try to grab tlk-piggy items NSDictionary* query = @{ @@ -2638,22 +2428,27 @@ CFDataRef SOSAccountCopyInitialSyncData(SOSAccount* account, SOSInitialSyncFlags NSMutableArray* encodedIdenities = [NSMutableArray array]; NSArray* tlks = nil; - if (flags & kSOSInitialSyncFlagiCloudIdentity) { - CFMutableArrayRef identities = SOSAccountCopyiCloudIdentities(account); - secnotice("piggy", "identities: %@", identities); + if (flags & kSOSInitialSyncFlagTLKsRequestOnly) { + tlks = SOSAccountGetSelectedTLKs(); + } else { + if (flags & kSOSInitialSyncFlagiCloudIdentity) { + CFMutableArrayRef identities = SOSAccountCopyiCloudIdentities(account); + secnotice("piggy", "identities: %@", identities); - CFIndex i, count = CFArrayGetCount(identities); - for (i = 0; i < count; i++) { - SOSPeerInfoRef fpi = (SOSPeerInfoRef)CFArrayGetValueAtIndex(identities, i); - NSData *data = CFBridgingRelease(SOSPeerInfoCopyData(fpi, error)); - if (data) - [encodedIdenities addObject:data]; + CFIndex i, count = CFArrayGetCount(identities); + for (i = 0; i < count; i++) { + SOSPeerInfoRef fpi = (SOSPeerInfoRef)CFArrayGetValueAtIndex(identities, i); + NSData *data = CFBridgingRelease(SOSPeerInfoCopyData(fpi, error)); + if (data) + [encodedIdenities addObject:data]; + } + CFRelease(identities); } - CFRelease(identities); - } - if (flags & kSOSInitialSyncFlagTLKs) { - tlks = SOSAccountGetAllTLKs(); + + if (flags & kSOSInitialSyncFlagTLKs) { + tlks = SOSAccountGetAllTLKs(); + } } return CFBridgingRetain(SOSPiggyCreateInitialSyncData(encodedIdenities, tlks)); @@ -2669,13 +2464,15 @@ static void pbNotice(CFStringRef operation, SOSAccount* account, SOSGenCountRef accountName = CFSTR("Unavailable"); } CFStringRef circleHash = SOSCircleCopyHashString(account.trust.trustedCircle); + CFStringRef genString = SOSGenerationCountCopyDescription(gencount); secnotice("circleOps", "%@: Joining blob for account: %@ for piggyback (V%d) gencount: %@ pubkey: %@ signatureID: %@ starting circle hash: %@", - operation, accountName, version, gencount, pkeyID, sigID, circleHash); + operation, accountName, version, genString, pkeyID, sigID, circleHash); CFReleaseNull(pkeyID); CFReleaseNull(sigID); CFReleaseNull(circleHash); + CFReleaseNull(genString); } CFDataRef SOSAccountCopyCircleJoiningBlob(SOSAccount* account, SOSPeerInfoRef applicant, CFErrorRef *error) { @@ -2804,10 +2601,10 @@ void SOSAccountLogState(SOSAccount* account) { secnotice(ACCOUNTLOGSTATE, "Start"); - secnotice(ACCOUNTLOGSTATE, "ACCOUNT: [keyStatus: %c%c%c hpub %@] [SOSCCStatus: %@]", + secnotice(ACCOUNTLOGSTATE, "ACCOUNT: [keyStatus: %c%c%c hpub %@] [SOSCCStatus: %@] [UID: %d EUID: %d]", boolToChars(hasPubKey, 'U', 'u'), boolToChars(pubTrusted, 'T', 't'), boolToChars(hasPriv, 'I', 'i'), userPubKeyID, - SOSAccountGetSOSCCStatusString(stat) + SOSAccountGetSOSCCStatusString(stat), getuid(), geteuid() ); CFReleaseNull(userPubKeyID); if(trust.trustedCircle) SOSCircleLogState(ACCOUNTLOGSTATE, trust.trustedCircle, account.accountKey, (__bridge CFStringRef)(account.peerID)); @@ -2853,7 +2650,6 @@ void SOSAccountResetOTRNegotiationCoder(SOSAccount* account, CFStringRef peerid) { secnotice("otrtimer", "timer fired!"); CFErrorRef error = NULL; - SecADAddValueForScalarKey((__bridge CFStringRef) SecSOSAggdReattemptOTRNegotiation,1); SOSEngineRef engine = SOSDataSourceFactoryGetEngineForDataSourceName(account.factory, SOSCircleGetName(account.trust.trustedCircle), NULL); SOSEngineWithPeerID(engine, peerid, &error, ^(SOSPeerRef peer, SOSCoderRef coder, SOSDataSourceRef dataSource, SOSTransactionRef txn, bool *forceSaveState) { @@ -2962,7 +2758,7 @@ static NSSet* SOSFlagsSet(void) { + (NSURL *)urlForSOSAccountSettings { - return (__bridge NSURL *)SecCopyURLForFileInKeychainDirectory(CFSTR("SOSAccountSettings.pb")); + return (__bridge_transfer NSURL *)SecCopyURLForFileInKeychainDirectory(CFSTR("SOSAccountSettings.pb")); } @@ -2970,9 +2766,9 @@ static NSSet* SOSFlagsSet(void) { WEAKIFY(self); self.accountConfiguration = [[CKKSPBFileStorage alloc] initWithStoragePath:[[self class] urlForSOSAccountSettings] - storageClass:[SOSAccountConfiguration class]]; + storageClass:[SOSAccountConfiguration class]]; - NSAssert(self.stateMachine == nil, @"cant bootstrap more the once"); + NSAssert(self.stateMachine == nil, @"can't bootstrap more than once"); self.stateMachineQueue = dispatch_queue_create("SOS-statemachine", NULL); @@ -2982,7 +2778,8 @@ static NSSet* SOSFlagsSet(void) { initialState:SOSStateReady queue:self.stateMachineQueue stateEngine:self - lockStateTracker:[CKKSLockStateTracker globalTracker]]; + lockStateTracker:[CKKSLockStateTracker globalTracker] + reachabilityTracker:nil]; self.performBackups = [[CKKSNearFutureScheduler alloc] initWithName:@"performBackups" @@ -2996,9 +2793,9 @@ static NSSet* SOSFlagsSet(void) { }]; self.performRingUpdates = [[CKKSNearFutureScheduler alloc] initWithName:@"performRingUpdates" - initialDelay:5*NSEC_PER_SEC + initialDelay:1*NSEC_PER_SEC expontialBackoff:2.0 - maximumDelay:15*60*NSEC_PER_SEC + maximumDelay:10*NSEC_PER_SEC keepProcessAlive:YES dependencyDescriptionCode:CKKSResultDescriptionNone block:^{ @@ -3062,7 +2859,6 @@ static NSSet* SOSFlagsSet(void) { - (void)triggerRingUpdate { - WEAKIFY(self); dispatch_async(self.stateMachineQueue, ^{ STRONGIFY(self); @@ -3107,21 +2903,62 @@ static NSSet* SOSFlagsSet(void) { errorState:SOSStateError withBlockTakingSelf:^void(OctagonStateTransitionOperation * _Nonnull op) { STRONGIFY(self); + __block bool goodPubKey = false; + __block CFMutableSetRef myBackupViews = NULL; + __block bool changesMade = false; SOSAccountConfiguration *storage = self.accountConfiguration.storage; storage.ringUpdateFlag = NO; [self.accountConfiguration setStorage:storage]; [self performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + if([self accountKeyIsTrusted] && [self isInCircle:NULL]) { + [self _onQueueRecordRetiredPeersInCircle]; + SOSAccountEnsureRecoveryRing(self); + + CFErrorRef error = NULL; + + // if we have a backup key but it isn't good clear it. goodPubKey becomes false. + // if we have nil then we're resetting the pubkey. + goodPubKey = SOSAccountBackupKeyConsistencyCheck(self, &error); + + if(goodPubKey) { + // It's a good key, we're going with it. Stop backing up the old way. + CFErrorRef localError = NULL; + if (!SOSDeleteV0Keybag(&localError)) { + secerror("Failed to delete v0 keybag: %@", localError); + } else { + changesMade = true; + } + CFReleaseNull(localError); + + if (self.peerInfo) { + myBackupViews = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, SOSPeerInfoGetPermittedViews(self.peerInfo)); + } + } + } + }]; + + if(goodPubKey && myBackupViews && !CFSetIsEmpty(myBackupViews)) { + CFSetForEach(myBackupViews, ^(const void *value) { + CFStringRef viewName = asString(value, NULL); + [self performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + if([self _onQueueEnsureInBackupRings: viewName]) { + changesMade = true; + } + }]; + }); + } + CFReleaseNull(myBackupViews); - [self _onQueueRecordRetiredPeersInCircle]; - - SOSAccountEnsureRecoveryRing(self); - [self _onQueueEnsureInBackupRings]; - + // This is where circle and ring flushes happen now. + // If a circle or ring has been Pushed in handleUpdate routines we need them to get out now. + // It isn't just the work up above that can do that push. It could simply be signing + // an existing circle/ring. + [self performTransaction:^(SOSAccountTransaction * _Nonnull txn) { CFErrorRef localError = NULL; if(![self.circle_transport flushChanges:&localError]){ - secerror("flush circle failed %@", localError); + secnotice("circleOps", "flush circles/rings failed %@", localError); } CFReleaseNull(localError); diff --git a/keychain/SecureObjectSync/SOSAccountBackup.m b/keychain/SecureObjectSync/SOSAccountBackup.m index 3a631f1f..7812b32a 100644 --- a/keychain/SecureObjectSync/SOSAccountBackup.m +++ b/keychain/SecureObjectSync/SOSAccountBackup.m @@ -458,13 +458,18 @@ SOSRingRef SOSAccountCreateBackupRingForView(SOSAccount* account, CFStringRef ri return newRing; } -void SOSAccountProcessBackupRings(SOSAccount* account, CFErrorRef *error) { +void SOSAccountProcessBackupRings(SOSAccount* account) { SOSAccountForEachBackupView(account, ^(const void *value) { + CFErrorRef localError = NULL; CFStringRef viewName = (CFStringRef)value; - SOSAccountUpdateBackupRing(account, viewName, error, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) { + SOSAccountUpdateBackupRing(account, viewName, &localError, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) { SOSRingRef newRing = SOSAccountCreateBackupRingForView(account, viewName, error); return newRing; }); + if(localError) { + secnotice("ring", "Error during SOSAccountProcessBackupRings (%@)", localError); + CFReleaseNull(localError); + } }); } @@ -483,8 +488,11 @@ bool SOSAccountValidateBackupRingForView(SOSAccount* account, CFStringRef viewN require_action_quiet(ringName, errOut, CFSTR("No RingName for View")); ring = SOSAccountCopyRingNamed(account, ringName, error); require_quiet(ring, errOut); + recoveryKeyData = SOSAccountCopyRecoveryPublic(kCFAllocatorDefault, account, NULL); currentBSKB = SOSRingCopyBackupSliceKeyBag(ring, NULL); + + // build the list of peer things we need to make sure are there from the circle filteredPeerIDs = CFSetCreateMutableForCFTypes(kCFAllocatorDefault); filteredPeerInfos = CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault); @@ -493,14 +501,16 @@ bool SOSAccountValidateBackupRingForView(SOSAccount* account, CFStringRef viewN CFSetAddValue(filteredPeerInfos, peer); }); + // check the ring to make sure everyone is there ringPeerIDSet = SOSRingCopyPeerIDs(ring); if(!CFEqual(filteredPeerIDs, ringPeerIDSet)) { fixBackupRing = true; } - fixBackupRing &= !currentBSKB || - !SOSBSKBAllPeersBackupKeysAreInKeyBag(currentBSKB, filteredPeerInfos) || - !SOSBSKBHasThisRecoveryKey(currentBSKB, recoveryKeyData); + // now validate the ring BSKB payload has everyone + fixBackupRing &= !(currentBSKB && + SOSBSKBAllPeersBackupKeysAreInKeyBag(currentBSKB, filteredPeerInfos) && + SOSBSKBHasThisRecoveryKey(currentBSKB, recoveryKeyData)); errOut: CFReleaseNull(ringName); @@ -515,18 +525,34 @@ errOut: bool SOSAccountSetBackupPublicKey(SOSAccountTransaction* aTxn, CFDataRef cfBackupKey, CFErrorRef *error) { - SOSAccount* account = aTxn.account; - __block bool result = false; - - account.backup_key = nil; - if(!SOSAccountUpdatePeerInfo(account, CFSTR("Backup public key"), error, ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *error) { - return SOSFullPeerInfoUpdateBackupKey(fpi, cfBackupKey, error); - })){ - return result; + __block SOSAccount* account = aTxn.account; + + if(cfBackupKey != NULL) { + account.backup_key = (NSData*) CFBridgingRelease(CFDataCreateCopy(kCFAllocatorDefault, cfBackupKey)); + } else { + account.backup_key = nil; } - SOSAccountProcessBackupRings(account, NULL); - return true; + + bool result = SOSAccountUpdatePeerInfoAndPush(account, CFSTR("Backup public key"), error, ^bool(SOSPeerInfoRef pi, CFErrorRef *error) { + if (account.backup_key != NULL) { + CFStringRef shortHash = SOSCopyIDOfDataBufferWithLength(cfBackupKey, 8, NULL); + secnotice("backup", "Setting peerInfo backupKey to %@", shortHash); + CFReleaseNull(shortHash); + SOSPeerInfoV2DictionarySetValue(pi, sBackupKeyKey, cfBackupKey); + } else { + secnotice("backup", "Setting peerInfo backupKey to NULL"); + SOSPeerInfoV2DictionaryRemoveValue(pi, sBackupKeyKey); + } + return true; + }); + if(result) { + SOSAccountProcessBackupRings(account); + account.need_backup_peers_created_after_backup_key_set = true; + secnotice("devRecovery", "circle_rings_retirements_need_attention set to true since we got a BackupKey"); + account.circle_rings_retirements_need_attention = true; + } + return result; } @@ -607,6 +633,48 @@ bool SOSAccountRemoveBackupPeers(SOSAccount* account, CFArrayRef peers, CFError } +bool SOSAccountEnsurePeerInfoHasCurrentBackupKey(SOSAccountTransaction *aTxn, CFErrorRef *error) { + bool retval = false; + CFDataRef peerBackupKey = NULL; + SOSAccount* account = aTxn.account; + + require_action_quiet([account isInCircle: nil], errOut, secnotice("backup", "Not currently in circle")); + + peerBackupKey = SOSPeerInfoCopyBackupKey(account.peerInfo); + if(!account.backup_key) { + if(peerBackupKey) { + retval = SOSAccountSetBackupPublicKey(aTxn, NULL, error); + } + } else if(!SOSBSKBIsGoodBackupPublic((__bridge CFDataRef)account.backup_key, error)){ + secnotice("backupkey", "account backup key isn't valid: %@", *error); + retval = SOSAccountSetBackupPublicKey(aTxn, NULL, error); + } else if(!CFEqualSafe(peerBackupKey, (__bridge CFDataRef)(account.backup_key))) { + secnotice("backupkey", "Account backup key and peerinforef backup key don't match. Using account backup key."); + retval = SOSAccountSetBackupPublicKey(aTxn, (__bridge CFDataRef)(account.backup_key), error); + if (!retval) { + secnotice("backupkey", "Failed to setup backup public key in peerInfo from account: %@", *error); + } + } else { + retval = true; + } + +errOut: + CFReleaseNull(peerBackupKey); + return retval; +} + +bool SOSAccountBackupKeyConsistencyCheck(SOSAccount* account, CFErrorRef *error) { + bool retval = false; + if([account isInCircle: nil] && account.backup_key && SOSBSKBIsGoodBackupPublic((__bridge CFDataRef)account.backup_key, error)) { + CFDataRef peerBackupKey = SOSPeerInfoCopyBackupKey(account.peerInfo); + if(CFEqualSafe(peerBackupKey, (__bridge CFDataRef)(account.backup_key))) { + retval = true; + } + CFReleaseNull(peerBackupKey); + } + return retval; +} + SOSBackupSliceKeyBagRef SOSAccountBackupSliceKeyBagForView(SOSAccount* account, CFStringRef viewName, CFErrorRef* error){ CFDataRef backupSliceData = NULL; CFStringRef ringName = NULL; @@ -629,33 +697,3 @@ exit: return bskb; } - -bool SOSAccountIsLastBackupPeer(SOSAccount* account, CFErrorRef *error) { - __block bool retval = false; - SOSPeerInfoRef pi = account.peerInfo; - - if(![account isInCircle:error]) { - return retval; - } - - if(!SOSPeerInfoHasBackupKey(pi)) - return retval; - - SOSCircleRef circle = [account.trust getCircle:error]; - - if(SOSCircleCountValidSyncingPeers(circle, SOSAccountGetTrustedPublicCredential(account, error)) == 1){ - retval = true; - return retval; - } - // We're in a circle with more than 1 ActiveValidPeers - are they in the backups? - SOSAccountForEachBackupView(account, ^(const void *value) { - CFStringRef viewname = (CFStringRef) value; - SOSBackupSliceKeyBagRef keybag = SOSAccountBackupSliceKeyBagForView(account, viewname, error); - require_quiet(keybag, inner_errOut); - retval |= ((SOSBSKBCountPeers(keybag) == 1) && (SOSBSKBPeerIsInKeyBag(keybag, pi))); - inner_errOut: - CFReleaseNull(keybag); - }); - - return retval; -} diff --git a/keychain/SecureObjectSync/SOSAccountCircles.m b/keychain/SecureObjectSync/SOSAccountCircles.m index 26e84b44..192548db 100644 --- a/keychain/SecureObjectSync/SOSAccountCircles.m +++ b/keychain/SecureObjectSync/SOSAccountCircles.m @@ -11,6 +11,8 @@ #import "keychain/SecureObjectSync/SOSTransportCircleCK.h" #import "keychain/SecureObjectSync/SOSAccountTrust.h" #import "keychain/SecureObjectSync/SOSAccountTrustClassic.h" +#import "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h" +#import "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h" #include "SOSCloudKeychainClient.h" @@ -42,3 +44,10 @@ fail: return circle; } +bool SOSAccountEvaluateKeysAndCircle(SOSAccountTransaction *txn, CFErrorRef *error) { + // if the userKey signature on the circle doesn't work with the new userkey + if([txn.account.trust isInCircleOnly:nil]) { + return SOSAccountGenerationSignatureUpdate(txn.account, error); + } + return true; +} diff --git a/keychain/SecureObjectSync/SOSAccountCloudParameters.m b/keychain/SecureObjectSync/SOSAccountCloudParameters.m index 9da7355e..ae1f9b91 100644 --- a/keychain/SecureObjectSync/SOSAccountCloudParameters.m +++ b/keychain/SecureObjectSync/SOSAccountCloudParameters.m @@ -30,14 +30,14 @@ static uint8_t* der_encode_cloud_parameters(SecKeyRef publicKey, CFDataRef param const uint8_t* der_decode_cloud_parameters(CFAllocatorRef allocator, CFIndex algorithmID, SecKeyRef* publicKey, - CFDataRef *parameters, + CFDataRef *pbkdfParams, CFErrorRef* error, const uint8_t* der, const uint8_t* der_end) { const uint8_t *sequence_end; der = ccder_decode_sequence_tl(&sequence_end, der, der_end); der = der_decode_public_bytes(allocator, algorithmID, publicKey, error, der, sequence_end); - der = der_decode_data_or_null(allocator, parameters, error, der, sequence_end); + der = der_decode_data_or_null(allocator, pbkdfParams, error, der, sequence_end); return der; } @@ -46,12 +46,12 @@ const uint8_t* der_decode_cloud_parameters(CFAllocatorRef allocator, bool SOSAccountPublishCloudParameters(SOSAccount* account, CFErrorRef* error){ bool success = false; CFIndex cloud_der_len = der_sizeof_cloud_parameters(account.accountKey, - (__bridge CFDataRef)(account.accountKeyDerivationParamters), + (__bridge CFDataRef)(account.accountKeyDerivationParameters), error); CFMutableDataRef cloudParameters = CFDataCreateMutableWithScratch(kCFAllocatorDefault, cloud_der_len); - if (der_encode_cloud_parameters(account.accountKey, (__bridge CFDataRef)(account.accountKeyDerivationParamters), error, + if (der_encode_cloud_parameters(account.accountKey, (__bridge CFDataRef)(account.accountKeyDerivationParameters), error, CFDataGetMutableBytePtr(cloudParameters), CFDataGetMutablePastEndPtr(cloudParameters)) != NULL) { @@ -75,9 +75,9 @@ bool SOSAccountPublishCloudParameters(SOSAccount* account, CFErrorRef* error){ bool SOSAccountRetrieveCloudParameters(SOSAccount* account, SecKeyRef *newKey, CFDataRef derparms, - CFDataRef *newParameters, CFErrorRef* error) { + CFDataRef *pbkdfParams, CFErrorRef* error) { const uint8_t *parse_end = der_decode_cloud_parameters(kCFAllocatorDefault, kSecECDSAAlgorithmID, - newKey, newParameters, error, + newKey, pbkdfParams, error, CFDataGetBytePtr(derparms), CFDataGetPastEndPtr(derparms)); if (parse_end == CFDataGetPastEndPtr(derparms)) return true; diff --git a/keychain/SecureObjectSync/SOSAccountCredentials.m b/keychain/SecureObjectSync/SOSAccountCredentials.m index a2d80366..4297b789 100644 --- a/keychain/SecureObjectSync/SOSAccountCredentials.m +++ b/keychain/SecureObjectSync/SOSAccountCredentials.m @@ -29,6 +29,7 @@ #include "SOSTransport.h" #import "keychain/SecureObjectSync/SOSAccountTrust.h" #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" +#import "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h" #define kPublicKeyAvailable "com.apple.security.publickeyavailable" // @@ -110,7 +111,9 @@ static void SOSAccountSetTrustedUserPublicKey(SOSAccount* account, bool public_w CFReleaseNull(publicKey); - secnotice("circleOps", "trusting new public key: %@", account.accountKey); + CFStringRef keyid = SOSCopyIDOfKeyWithLength(account.accountKey, 8, NULL); + secnotice("circleOps", "trusting new public key: %@", keyid); + CFReleaseNull(keyid); notify_post(kPublicKeyAvailable); } @@ -126,8 +129,9 @@ void SOSAccountSetUnTrustedUserPublicKey(SOSAccount* account, SecKeyRef publicKe if(!account.previousAccountKey) { account.previousAccountKey = account.accountKey; } - - secnotice("circleOps", "not trusting new public key: %@", account.accountKey); + CFStringRef keyid = SOSCopyIDOfKeyWithLength(account.accountKey, 8, NULL); + secnotice("circleOps", "not trusting new public key: %@", keyid); + CFReleaseNull(keyid); } @@ -204,21 +208,6 @@ CFDataRef SOSAccountGetCachedPassword(SOSAccount* account, CFErrorRef* error) static NSString *SOSUserCredentialAccount = @"SOSUserCredential"; static NSString *SOSUserCredentialAccessGroup = @"com.apple.security.sos-usercredential"; -__unused static void SOSAccountDeleteStashedAccountKey(SOSAccount* account) -{ - NSString *dsid = (__bridge NSString *)SOSAccountGetValue(account, kSOSDSIDKey, NULL); - if (dsid == NULL) - return; - - NSDictionary * attributes = @{ - (__bridge id)kSecClass : (__bridge id)kSecClassInternetPassword, - (__bridge id)kSecAttrAccount : SOSUserCredentialAccount, - (__bridge id)kSecAttrServer : dsid, - (__bridge id)kSecAttrAccessGroup : SOSUserCredentialAccessGroup, - }; - (void)SecItemDelete((__bridge CFDictionaryRef)attributes); -} - void SOSAccountStashAccountKey(SOSAccount* account) { OSStatus status; @@ -324,8 +313,8 @@ static void sosAccountSetTrustedCredentials(SOSAccount* account, CFDataRef user_ static SecKeyRef sosAccountCreateKeyIfPasswordIsCorrect(SOSAccount* account, CFDataRef user_password, CFErrorRef *error) { SecKeyRef user_private = NULL; - require_quiet(account.accountKey && account.accountKeyDerivationParamters, errOut); - user_private = SOSUserKeygen(user_password, (__bridge CFDataRef)(account.accountKeyDerivationParamters), error); + require_quiet(account.accountKey && account.accountKeyDerivationParameters, errOut); + user_private = SOSUserKeygen(user_password, (__bridge CFDataRef)(account.accountKeyDerivationParameters), error); require_quiet(user_private, errOut); require_action_quiet(SOSAccountValidateAccountCredential(account, user_private, error), errOut, CFReleaseNull(user_private)); @@ -336,7 +325,21 @@ errOut: static bool sosAccountValidatePasswordOrFail(SOSAccount* account, CFDataRef user_password, CFErrorRef *error) { SecKeyRef privKey = sosAccountCreateKeyIfPasswordIsCorrect(account, user_password, error); if(!privKey) { - if(account.accountKeyDerivationParamters) debugDumpUserParameters(CFSTR("sosAccountValidatePasswordOrFail"), (__bridge CFDataRef)(account.accountKeyDerivationParamters)); + if(account.accountKeyDerivationParameters) { + SecKeyRef newKey = NULL; + CFDataRef pbkdfParams = NULL; + CFErrorRef localError = NULL; + if(SOSAccountRetrieveCloudParameters(account, &newKey, (__bridge CFDataRef)(account.accountKeyDerivationParameters), &pbkdfParams, &localError)) { + debugDumpUserParameters(CFSTR("sosAccountValidatePasswordOrFail"), pbkdfParams); + } else { + secnotice("circleOps", "Failed to retrieve cloud parameters - %@", localError); + if(error) { + CFTransferRetained(*error, localError); + } + } + CFReleaseNull(newKey); + CFReleaseNull(pbkdfParams); + } SOSCreateError(kSOSErrorWrongPassword, CFSTR("Could not create correct key with password."), NULL, error); return false; } @@ -346,7 +349,7 @@ static bool sosAccountValidatePasswordOrFail(SOSAccount* account, CFDataRef user } void SOSAccountSetParameters(SOSAccount* account, CFDataRef parameters) { - account.accountKeyDerivationParamters = (__bridge NSData *) parameters; + account.accountKeyDerivationParameters = (__bridge NSData *) parameters; } bool SOSAccountValidateAccountCredential(SOSAccount* account, SecKeyRef accountPrivateKey, CFErrorRef *error) @@ -361,7 +364,7 @@ bool SOSAccountValidateAccountCredential(SOSAccount* account, SecKeyRef accountP CFStringRef accountHpub = SOSCopyIDOfKey(account.accountKey, NULL); CFStringRef candidateHpub = SOSCopyIDOfKey(publicCandidate, NULL); SOSCreateErrorWithFormat(kSOSErrorWrongPassword, NULL, &localError, NULL, CFSTR("Password generated pubkey doesn't match - candidate: %@ known: %@"), candidateHpub, accountHpub); - secnotice("circleop", "%@", localError); + secnotice("circleop", "Password generated pubkey doesn't match - candidate: %@ known: %@", candidateHpub, accountHpub); if (error) { *error = localError; localError = NULL; diff --git a/keychain/SecureObjectSync/SOSAccountFullPeerInfo.m b/keychain/SecureObjectSync/SOSAccountFullPeerInfo.m index 834c75d7..100433b1 100644 --- a/keychain/SecureObjectSync/SOSAccountFullPeerInfo.m +++ b/keychain/SecureObjectSync/SOSAccountFullPeerInfo.m @@ -39,15 +39,11 @@ static CFStringRef kicloud_identity_name = CFSTR("Cloud Identity"); SecKeyRef SOSAccountCopyDeviceKey(SOSAccount* account, CFErrorRef *error) { SecKeyRef privateKey = NULL; - SOSFullPeerInfoRef identity = NULL; - - SOSAccountTrustClassic *trust = account.trust; - identity = trust.fullPeerInfo; - require_action_quiet(identity, fail, SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("No identity to get key from"))); - - privateKey = SOSFullPeerInfoCopyDeviceKey(identity, error); - -fail: + if(account.peerPublicKey) { + privateKey = SecKeyCopyMatchingPrivateKey(account.peerPublicKey, error); + } else { + SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("No identity to get key from")); + } return privateKey; } @@ -59,13 +55,13 @@ SOSFullPeerInfoRef CopyCloudKeychainIdentity(SOSPeerInfoRef cloudPeer, CFErrorRe static CF_RETURNS_RETAINED SecKeyRef GeneratePermanentFullECKey_internal(int keySize, CFStringRef name, CFTypeRef accessibility, CFBooleanRef sync, CFErrorRef* error) { SecKeyRef full_key = NULL; - + CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keySize); - + CFDictionaryRef priv_key_attrs = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecAttrIsPermanent, kCFBooleanTrue, NULL); - + CFDictionaryRef keygen_parameters = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecAttrKeyType, kSecAttrKeyTypeEC, kSecAttrKeySizeInBits, key_size_num, @@ -76,19 +72,19 @@ static CF_RETURNS_RETAINED SecKeyRef GeneratePermanentFullECKey_internal(int key kSecAttrSynchronizable, sync, kSecUseTombstones, kCFBooleanTrue, NULL); - + CFReleaseNull(priv_key_attrs); - + CFReleaseNull(key_size_num); OSStatus status = SecKeyGeneratePair(keygen_parameters, NULL, &full_key); CFReleaseNull(keygen_parameters); - + if (status) secerror("status: %ld", (long)status); if (status != errSecSuccess && error != NULL && *error == NULL) { *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, status, NULL); } - + return full_key; } @@ -100,6 +96,69 @@ static CF_RETURNS_RETAINED SecKeyRef GeneratePermanentFullECKeyForCloudIdentity( return GeneratePermanentFullECKey_internal(keySize, name, kSecAttrAccessibleWhenUnlocked, kCFBooleanTrue, error); } +static SecKeyRef sosKeyForLabel(CFStringRef label) { + CFTypeRef queryResult = NULL; + SecKeyRef retval = NULL; + CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecMatchLimit, kSecMatchLimitOne, + kSecClass, kSecClassKey, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrSynchronizable, kSecAttrSynchronizableAny, + kSecAttrAccessGroup, kSOSInternalAccessGroup, + kSecAttrLabel, label, + kSecReturnRef, kCFBooleanTrue, + NULL); + OSStatus stat = SecItemCopyMatching(query, &queryResult); + if(errSecSuccess == stat) { + retval = (SecKeyRef) queryResult; + secnotice("iCloudIdentity", "Got key for label (%@)", label); + } else { + secnotice("iCloudIdentity", "Failed query(%d) for %@", (int) stat, label); + } + CFReleaseNull(query); + return retval; +} + +void SOSiCloudIdentityPrivateKeyForEach(void (^complete)(SecKeyRef privKey)) { + CFTypeRef queryResult = NULL; + CFArrayRef iCloudPrivKeys = NULL; + + CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecMatchLimit, kSecMatchLimitAll, + kSecClass, kSecClassKey, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrSynchronizable, kSecAttrSynchronizableAny, + kSecAttrAccessGroup, kSOSInternalAccessGroup, + kSecReturnAttributes, kCFBooleanTrue, + NULL); + + if((errSecSuccess == SecItemCopyMatching(query, &queryResult)) && (iCloudPrivKeys = asArray(queryResult, NULL))) { + secnotice("iCloudIdentity", "Screening %ld icloud private key candidates", (long)CFArrayGetCount(iCloudPrivKeys)); + CFReleaseNull(query); + } else { + secnotice("iCloudIdentity", "Can't get iCloud Identity private key candidates"); + CFReleaseNull(query); + CFReleaseNull(queryResult); + return; + } + + CFArrayForEach(iCloudPrivKeys, ^(const void *value) { + CFDictionaryRef privKeyDict = (CFDictionaryRef) value; + CFStringRef label = CFDictionaryGetValue(privKeyDict, kSecAttrLabel); + if(!label) { + return; + } + if(CFStringHasPrefix(label, CFSTR("Cloud Identity"))) { + SecKeyRef privKey = sosKeyForLabel(label); + if(privKey) { + complete(privKey); + CFReleaseNull(privKey); + } + } + }); + CFReleaseNull(queryResult); +} + bool SOSAccountHasCircle(SOSAccount* account, CFErrorRef* error) { SOSAccountTrustClassic *trust = account.trust; SOSCircleRef circle = trust.trustedCircle; diff --git a/keychain/SecureObjectSync/SOSAccountGhost.m b/keychain/SecureObjectSync/SOSAccountGhost.m index f8de69c2..6a65ebf5 100644 --- a/keychain/SecureObjectSync/SOSAccountGhost.m +++ b/keychain/SecureObjectSync/SOSAccountGhost.m @@ -18,6 +18,7 @@ #include "keychain/SecureObjectSync/SOSPeerInfoPriv.h" #include "keychain/SecureObjectSync/SOSAuthKitHelpers.h" #import "Analytics/Clients/SOSAnalytics.h" +#import #include "utilities/SecTrace.h" @@ -32,9 +33,9 @@ static bool sosGhostCheckValid(SOSPeerInfoRef pi) { case SOSPeerInfo_iOS: case SOSPeerInfo_tvOS: case SOSPeerInfo_watchOS: - case SOSPeerInfo_macOS: retval = true; break; + case SOSPeerInfo_macOS: // go back and quit killing macos ghosts so people can multi-boot case SOSPeerInfo_iCloud: case SOSPeerInfo_unknown: default: @@ -140,28 +141,27 @@ static NSUInteger SOSGhostBustThinSerialClones(SOSCircleRef circle, NSString *my for(CFIndex i = CFArrayGetCount(sortPeers); i > 0; i--) { SOSPeerInfoRef pi = (SOSPeerInfoRef) CFArrayGetValueAtIndex(sortPeers, i-1); - - if(sosGhostCheckValid(pi)) { + NSString *peerID = (__bridge NSString *)SOSPeerInfoGetPeerID(pi); + + if(![peerID isEqualToString: myPeerID] && sosGhostCheckValid(pi)) { NSString *serial = CFBridgingRelease(SOSPeerInfoV2DictionaryCopyString(pi, sSerialNumberKey)); - NSString *peerID = (__bridge NSString *)SOSPeerInfoGetPeerID(pi); if(serial != nil) { if([latestPeers objectForKey:serial] != nil) { - if(peerID != myPeerID) { - [removals addObject:peerID]; - } else { - secnotice("ghostBust", "There is a more recent peer for this serial number"); - } + secnotice("ghostBust", "There is a more recent peer than %@ for this serial number", SOSPeerInfoGetSPID(pi)); + [removals addObject:peerID]; } else { [latestPeers setObject:peerID forKey:serial]; } } else { - secnotice("ghostBust", "Removing peerID (%@) with no serial number", peerID); + secnotice("ghostBust", "Removing peerID (%@) with no serial number", SOSPeerInfoGetSPID(pi)); [removals addObject:peerID]; } } } - SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); gbcount = [removals count]; + if(gbcount > 0) { + SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); + } CFReleaseNull(sortPeers); return gbcount; } @@ -175,6 +175,42 @@ static void SOSCircleRemoveiCloudIdentities(SOSCircleRef circle) { SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); } +// this is only used to determine if we have a circle that can't accept new peers because of ghosts. +static void SOSCircleRemoveWindowsPeers(SOSCircleRef circle) { + NSMutableSet *removals = [[NSMutableSet alloc] init]; + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + NSString *devType = (__bridge NSString *)SOSPeerInfoGetPeerDeviceType(peer); + if([devType hasPrefix: @"Windows"]) { + NSString *peerID = (__bridge NSString *)SOSPeerInfoGetPeerID(peer); + [removals addObject:peerID]; + } + }); + SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); +} + +static void SOSCircleRemovePeersNotInMidlist(SOSCircleRef circle) { + __block SOSAuthKitHelpers *akh = nil; + + if([SOSAuthKitHelpers accountIsHSA2]) { + [SOSAuthKitHelpers activeMIDs:^(NSSet * _Nullable activeMIDs, NSError * _Nullable error) { + akh = [[SOSAuthKitHelpers alloc] initWithActiveMIDS:activeMIDs]; + }]; + } + + NSMutableSet *removals = [[NSMutableSet alloc] init]; + if(akh) { + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + NSString *mid = CFBridgingRelease(SOSPeerInfoV2DictionaryCopyString(peer, sMachineIDKey)); + if(![akh midIsValidInList:mid]) { + NSString *peerID = (__bridge NSString *)SOSPeerInfoGetPeerID(peer); + [removals addObject:peerID]; + } + }); + SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); + } +} + + bool SOSAccountGhostResultsInReset(SOSAccount* account) { if(!account.peerID || !account.trust.trustedCircle) return false; SOSCircleRef newCircle = SOSCircleCopyCircle(kCFAllocatorDefault, account.trust.trustedCircle, NULL); @@ -182,6 +218,8 @@ bool SOSAccountGhostResultsInReset(SOSAccount* account) { SOSCircleClearMyGhosts(newCircle, account.peerInfo); SOSCircleRemoveRetired(newCircle, NULL); SOSCircleRemoveiCloudIdentities(newCircle); + SOSCircleRemoveWindowsPeers(newCircle); + SOSCircleRemovePeersNotInMidlist(newCircle); int npeers = SOSCircleCountPeers(newCircle); CFReleaseNull(newCircle); return npeers == 0; @@ -200,6 +238,7 @@ static NSUInteger SOSGhostBustThinByMIDList(SOSCircleRef circle, NSString *myPee if(options & SOSGhostBustByMID) { NSString *mid = CFBridgingRelease(SOSPeerInfoV2DictionaryCopyString(peer, sMachineIDKey)); if(![akh midIsValidInList:mid]) { + secnotice("ghostBust", "Removing peerInfo %@ - mid is not in list", SOSPeerInfoGetSPID(peer)); [removals addObject:peerID]; gbmid++; return; @@ -208,6 +247,7 @@ static NSUInteger SOSGhostBustThinByMIDList(SOSCircleRef circle, NSString *myPee if(options & SOSGhostBustBySerialNumber) { NSString *serial = CFBridgingRelease(SOSPeerInfoV2DictionaryCopyString(peer, sSerialNumberKey)); if(![akh serialIsValidInList: serial]) { + secnotice("ghostBust", "Removing peerInfo %@ - serial# is not in list", SOSPeerInfoGetSPID(peer)); [removals addObject:peerID]; gbserial++; return; @@ -222,92 +262,86 @@ static NSUInteger SOSGhostBustThinByMIDList(SOSCircleRef circle, NSString *myPee return [removals count]; } -static bool SOSGhostBustiCloudIdentityPrivateKeys(SOSAccount *account) { - __block bool cleaned = false; - SecKeyRef pubKey = NULL; - CFTypeRef queryResult = NULL; - CFDataRef pubKeyHash = NULL; - CFDictionaryRef query = NULL; - __block int removed = 0; +static NSUInteger SOSGhostBustiCloudIdentityPrivateKeys(SOSAccount *account) { + __block NSUInteger cleaned = 0; - SOSFullPeerInfoRef iCloudIdentity = SOSCircleCopyiCloudFullPeerInfoVerifier(account.trust.trustedCircle, NULL); - require_action_quiet(iCloudIdentity, retOut, secnotice("ghostBust", "No iCloud Identity FPI")); - pubKey = SOSFullPeerInfoCopyPubKey(iCloudIdentity, NULL); - require_action_quiet(pubKey, retOut, secnotice("ghostBust", "Can't get iCloud Identity pubkey")); - pubKeyHash = SecKeyCopyPublicKeyHash(pubKey); - require_action_quiet(pubKeyHash, retOut, secnotice("ghostBust", "Can't get iCloud Identity pubkey hash")); - query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecMatchLimit, kSecMatchLimitAll, - kSecClass, kSecClassKey, - kSecAttrKeyClass, kSecAttrKeyClassPrivate, - kSecAttrSynchronizable, kSecAttrSynchronizableAny, - kSecReturnAttributes, kCFBooleanTrue, - kSecAttrAccessGroup, kSOSInternalAccessGroup, - NULL); - require_action_quiet(errSecSuccess == SecItemCopyMatching(query, &queryResult), retOut, secnotice("ghostBust", "Can't get iCloud Identity private keys")); - require_action_quiet(CFGetTypeID(queryResult) == CFArrayGetTypeID(), retOut, cleaned = true); - CFArrayRef iCloudPrivKeys = queryResult; - secnotice("ghostBust", "Screening %ld icloud private keys", (long)CFArrayGetCount(iCloudPrivKeys)); - CFArrayForEach(iCloudPrivKeys, ^(const void *value) { - CFDictionaryRef privkey = asDictionary(value, NULL); - if(privkey) { - CFDataRef candidate = asData(CFDictionaryGetValue(privkey, kSecAttrApplicationLabel), NULL); - if(candidate && !CFEqual(pubKeyHash, candidate)) { - CFStringRef label = asString(CFDictionaryGetValue(privkey, kSecAttrLabel), NULL); - if(label) { - if(CFStringHasPrefix(label, CFSTR("Cloud Identity"))) { + [ account iCloudIdentityStatus_internal:^(NSDictionary *tableSpid, NSError *error) { + if(!tableSpid) { + secnotice("ghostBust", "Couldn't work on iCloud Identities (%@)", error); + } - CFDictionaryRef delQuery = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecClass, kSecClassKey, - kSecAttrKeyClass, kSecAttrKeyClassPrivate, - kSecAttrSynchronizable, kSecAttrSynchronizableAny, - kSecAttrApplicationLabel, candidate, - NULL); + size_t keysToRemove = [tableSpid[kSOSIdentityStatusKeyOnly] count]; - OSStatus status = SecItemDelete(delQuery); - if(errSecSuccess == status) { - secnotice("ghostBust", "removed %@", label); - removed++; - cleaned = true; - } else { - secnotice("ghostbust", "Search for %@ returned %d", candidate, (int) status); - } - CFReleaseNull(delQuery); - } + if(keysToRemove == 0) { + return; + } + + if([tableSpid[kSOSIdentityStatusCompleteIdentity] count] == 0) { + secnotice("ghostBust", "No iCloud Identity FPI, can't remove iCloudIdentity extra keys"); + return; + } + + for (NSString *pid in tableSpid[kSOSIdentityStatusKeyOnly]) { + CFStringRef fullKeyLabel = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Cloud Identity - '%@'"), pid); + + if(fullKeyLabel) { + CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecClass, kSecClassKey, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrSynchronizable, kSecAttrSynchronizableAny, + kSecUseTombstones, kCFBooleanTrue, + kSecAttrLabel, fullKeyLabel, + NULL); + OSStatus status = SecItemDelete(query); + if(errSecSuccess == status) { + secnotice("ghostBust", "removed %@", pid); + cleaned++; + } else { + secnotice("ghostbust", "Delete for %@ returned %d", pid, (int) status); } + CFReleaseNull(query); + CFReleaseNull(fullKeyLabel); } } - }); - secnotice("ghostBust", "Removed %d icloud private keys", removed); -retOut: - CFReleaseNull(query); - CFReleaseNull(queryResult); - CFReleaseNull(pubKeyHash); - CFReleaseNull(pubKey); - CFReleaseNull(iCloudIdentity); + secnotice("ghostBust", "Removed %zu of %zu deserted icloud private keys", cleaned, keysToRemove); + }]; return cleaned; } bool SOSAccountGhostBustCircle(SOSAccount *account, SOSAuthKitHelpers *akh, SOSAccountGhostBustingOptions options, int mincount) { __block bool result = false; + __block bool actionTaken = false; CFErrorRef localError = NULL; __block NSUInteger nbusted = 9999; NSMutableDictionary *attributes =[NSMutableDictionary new]; + int circleSize = SOSCircleCountPeers(account.trust.trustedCircle); - if ([akh isUseful] && [account isInCircle:nil] && circleSize > mincount) { - if(options & SOSGhostBustiCloudIdentities) { - secnotice("ghostBust", "Callout to cleanup icloud identities"); - result = SOSGhostBustiCloudIdentityPrivateKeys(account); - } else { + if(options & SOSGhostBustiCloudIdentities && [account isInCircle:nil]) { + secnotice("ghostBust", "Callout to cleanup icloud identities"); + nbusted = SOSGhostBustiCloudIdentityPrivateKeys(account); + if(nbusted) { + attributes[@"iCloudPrivKeysBusted"] = @(nbusted); + [[SOSAnalytics logger] logSoftFailureForEventNamed:@"GhostBust" withAttributes:attributes]; + result = true; + } + actionTaken = true; + } + + if(options & (~SOSGhostBustiCloudIdentities)) { + if ([akh isUseful] && [account isInCircle:nil] && circleSize > mincount) { [account.trust modifyCircle:account.circle_transport err:&localError action:^(SOSCircleRef circle) { - nbusted = SOSGhostBustThinByMIDList(circle, account.peerID, akh, options, attributes); - secnotice("ghostbust", "Removed %lu ghosts from circle by midlist && serialNumber", (unsigned long)nbusted); + if((options & SOSGhostBustByMID) || (options & SOSGhostBustBySerialNumber)) { + nbusted = SOSGhostBustThinByMIDList(circle, account.peerID, akh, options, attributes); + secnotice("ghostbust", "Removed %lu ghosts from circle by midlist && serialNumber", (unsigned long)nbusted); + actionTaken = true; + } if(options & SOSGhostBustSerialByAge) { NSUInteger thinBusted = 9999; thinBusted = SOSGhostBustThinSerialClones(circle, account.peerID); nbusted += thinBusted; attributes[@"byAge"] = @(thinBusted); + actionTaken = true; } attributes[@"total"] = @(SecBucket1Significant(nbusted)); attributes[@"startCircleSize"] = @(SecBucket1Significant(circleSize)); @@ -324,17 +358,17 @@ bool SOSAccountGhostBustCircle(SOSAccount *account, SOSAuthKitHelpers *akh, SOSA }]; secnotice("circleOps", "Ghostbusting %@ (%@)", result ? CFSTR("Performed") : CFSTR("Not Performed"), localError); } - } else { - secnotice("circleOps", "Ghostbusting skipped"); } CFReleaseNull(localError); - - if(result) { - [[SOSAnalytics logger] logSoftFailureForEventNamed:@"GhostBust" withAttributes:attributes]; - } else if(nbusted == 0){ - [[SOSAnalytics logger] logSuccessForEventNamed:@"GhostBust"]; - } else { - [[SOSAnalytics logger] logHardFailureForEventNamed:@"GhostBust" withAttributes:nil]; + + if(actionTaken) { + if(result) { + [[SOSAnalytics logger] logSoftFailureForEventNamed:@"GhostBust" withAttributes:attributes]; + } else if(nbusted == 0){ + [[SOSAnalytics logger] logSuccessForEventNamed:@"GhostBust"]; + } else { + [[SOSAnalytics logger] logHardFailureForEventNamed:@"GhostBust" withAttributes:nil]; + } } return result; } diff --git a/keychain/SecureObjectSync/SOSAccountLog.m b/keychain/SecureObjectSync/SOSAccountLog.m index 1eed7078..26d6261f 100644 --- a/keychain/SecureObjectSync/SOSAccountLog.m +++ b/keychain/SecureObjectSync/SOSAccountLog.m @@ -6,7 +6,6 @@ #include "SOSAccountLog.h" #include #include -#include #include #include "SOSAccountPriv.h" #include "SOSViews.h" diff --git a/keychain/SecureObjectSync/SOSAccountPeers.m b/keychain/SecureObjectSync/SOSAccountPeers.m index 474335b3..56b3699f 100644 --- a/keychain/SecureObjectSync/SOSAccountPeers.m +++ b/keychain/SecureObjectSync/SOSAccountPeers.m @@ -125,16 +125,7 @@ CFArrayRef SOSAccountCopyViewUnaware(SOSAccount* account, CFErrorRef *error) { SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { if (!SOSPeerInfoVersionHasV2Data(peer) ) { sosArrayAppendPeerCopy(appendPeersTo, peer); - } else { - CFSetRef peerEnabledViews = SOSPeerInfoCopyEnabledViews(peer); - CFSetRef enabledV0Views = CFSetCreateIntersection(kCFAllocatorDefault, peerEnabledViews, SOSViewsGetV0ViewSet()); - if(CFSetGetCount(enabledV0Views) != 0) { - sosArrayAppendPeerCopy(appendPeersTo, peer); - } - CFReleaseNull(peerEnabledViews); - CFReleaseNull(enabledV0Views); - } - }); + } }); }); } @@ -154,77 +145,6 @@ CFArrayRef SOSAccountCopyPeers(SOSAccount* account, CFErrorRef *error) { }); } -CFDataRef SOSAccountCopyAccountStateFromKeychain(CFErrorRef *error){ - CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFTypeRef result = NULL; - CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); - CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos")); - CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dku")); - CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse); - CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse); - CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue); - - SecItemCopyMatching(query, &result); - - if(!isData(result)){ - SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result); - CFReleaseNull(result); - return NULL; - } - return result; -} - -bool SOSAccountDeleteAccountStateFromKeychain(CFErrorRef *error){ - CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - bool result = false; - CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); - CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos")); - CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dku")); - CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse); - CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse); - - result = SecItemDelete(query); - return result; -} - -CFDataRef SOSAccountCopyEngineStateFromKeychain(CFErrorRef *error){ - CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFTypeRef result = NULL; - CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); - CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("engine-state")); - CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos")); - CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dk")); - CFDictionaryAddValue(query, kSecAttrService, CFSTR("SOSDataSource-ak")); - CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse); - CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse); - CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue); - - SecItemCopyMatching(query, &result); - - if(!isData(result)){ - SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result); - CFReleaseNull(result); - return NULL; - } - return result; -} - -bool SOSAccountDeleteEngineStateFromKeychain(CFErrorRef *error){ - CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - bool result = false; - CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); - CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("engine-state")); - CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos")); - CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dk")); - CFDictionaryAddValue(query, kSecAttrService, CFSTR("SOSDataSource-ak")); - CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse); - CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse); - - result = SecItemDelete(query); - return result; -} - - CFArrayRef SOSAccountCopyActivePeers(SOSAccount* account, CFErrorRef *error) { return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { @@ -288,3 +208,27 @@ CFBooleanRef SOSAccountPeersHaveViewsEnabled(SOSAccount* account, CFArrayRef vie return result; } +bool SOSAccountRemoveV0Clients(SOSAccount *account, CFErrorRef *error) { + CFErrorRef localError = NULL; + + CFArrayRef v0Peers = SOSAccountCopyViewUnaware(account, &localError); + if (error && localError) { + CFTransferRetained(*error, localError); + } + + if (v0Peers == NULL || CFArrayGetCount(v0Peers) == 0) { + CFReleaseNull(localError); + CFReleaseNull(v0Peers); + return true; + } + + bool result = SOSAccountRemovePeersFromCircle(account, v0Peers, &localError); + if (error && localError) { + CFTransferRetained(*error, localError); + } + + CFReleaseNull(localError); + CFReleaseNull(v0Peers); + + return result; +} diff --git a/keychain/SecureObjectSync/SOSAccountPersistence.m b/keychain/SecureObjectSync/SOSAccountPersistence.m index eb4b7a0f..274c921d 100644 --- a/keychain/SecureObjectSync/SOSAccountPersistence.m +++ b/keychain/SecureObjectSync/SOSAccountPersistence.m @@ -24,7 +24,6 @@ #include #include -#include #include #include "SOSViews.h" @@ -65,7 +64,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v6(CFAllocatorRef allocator, { CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p = der_decode_dictionary(kCFAllocatorDefault, &decoded_gestalt, error, *der_p, der_end); if (*der_p == 0) @@ -77,7 +76,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v6(CFAllocatorRef allocator, } SOSAccountTrustClassic *trust = account.trust; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, der_end); + *der_p = der_decode_array(kCFAllocatorDefault, &array, error, *der_p, der_end); uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, der_end); @@ -99,10 +98,10 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v6(CFAllocatorRef allocator, { CFDataRef parms = NULL; *der_p = der_decode_data_or_null(kCFAllocatorDefault, &parms, error, *der_p, der_end); - [account setAccountKeyDerivationParamters:(__bridge_transfer NSData*) parms]; + [account setAccountKeyDerivationParameters:(__bridge_transfer NSData*) parms]; } - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &retiredPeers, error, *der_p, der_end); + *der_p = der_decode_dictionary(kCFAllocatorDefault, (CFDictionaryRef *) &retiredPeers, error, *der_p, der_end); if(*der_p != der_end) { *der_p = NULL; @@ -173,11 +172,11 @@ fail: return result; } -static const uint8_t* der_decode_data_optional(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_data_optional(CFAllocatorRef allocator, CFDataRef* data, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - const uint8_t *dt_end = der_decode_data(allocator, mutability, data, NULL, der, der_end); + const uint8_t *dt_end = der_decode_data(allocator, data, NULL, der, der_end); return dt_end ? dt_end : der; } @@ -192,7 +191,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v7(CFAllocatorRef allocator, { CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p = der_decode_dictionary(kCFAllocatorDefault, &decoded_gestalt, error, *der_p, der_end); if (*der_p == 0) @@ -242,7 +241,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v7(CFAllocatorRef allocator, { CFDataRef parms = NULL; *der_p = der_decode_data_or_null(kCFAllocatorDefault, &parms, error, *der_p, der_end); - account.accountKeyDerivationParamters = (__bridge_transfer NSData*)parms; + account.accountKeyDerivationParameters = (__bridge_transfer NSData*)parms; } { @@ -252,7 +251,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v7(CFAllocatorRef allocator, { CFDataRef bKey = NULL; - *der_p = der_decode_data_optional(kCFAllocatorDefault, kCFPropertyListImmutable, &bKey, error, *der_p, der_end); + *der_p = der_decode_data_optional(kCFAllocatorDefault, &bKey, error, *der_p, der_end); if(bKey != NULL) [account setBackup_key:(__bridge_transfer NSData *)bKey]; } @@ -280,7 +279,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v8(CFAllocatorRef allocator, { CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p = der_decode_dictionary(kCFAllocatorDefault, &decoded_gestalt, error, *der_p, der_end); if (*der_p == 0) { @@ -332,7 +331,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v8(CFAllocatorRef allocator, { CFDataRef parms; *der_p = der_decode_data_or_null(kCFAllocatorDefault, &parms, error, *der_p, der_end); - account.accountKeyDerivationParamters = (__bridge_transfer NSData*)parms; + account.accountKeyDerivationParameters = (__bridge_transfer NSData*)parms; parms = NULL; } @@ -343,16 +342,17 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v8(CFAllocatorRef allocator, } CFDataRef bKey = NULL; - *der_p = der_decode_data_optional(kCFAllocatorDefault, kCFPropertyListImmutable, &bKey, error, *der_p, der_end); - { + *der_p = der_decode_data_optional(kCFAllocatorDefault, &bKey, error, *der_p, der_end); + if(*der_p != der_end) { CFDictionaryRef expansion = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &expansion, error, + *der_p = der_decode_dictionary(kCFAllocatorDefault, &expansion, error, *der_p, der_end); if (*der_p == 0) { + secnotice("persistence", "Error Processing expansion dictionary der - dropping account object"); CFReleaseNull(bKey); CFReleaseNull(expansion); - return NULL; + return result; } if(expansion) { @@ -361,8 +361,12 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v8(CFAllocatorRef allocator, CFReleaseNull(expansion); } if(bKey) { + secnotice("backupKey", "Setting backup key from metadata"); [account setBackup_key:[[NSData alloc] initWithData:(__bridge NSData * _Nonnull)(bKey)]]; + } else { + secnotice("backupKey", "Failed to set backup key from metadata - no key found"); } + CFReleaseNull(bKey); require_action_quiet(*der_p && *der_p == der_end, fail, @@ -440,9 +444,12 @@ static SOSAccount* SOSAccountCreateFromDER(CFAllocatorRef allocator, SOSUnregisterTransportKeyParameter(account.key_transport); SOSUnregisterTransportCircle((SOSCircleStorageTransport*)account.circle_transport); SOSUnregisterTransportMessage(account.kvs_message_transport); - secnotice("account", "No private key associated with my_identity, resetting"); return nil; + } else { + SecKeyRef ppk = SOSFullPeerInfoCopyPubKey(identity, NULL); + account.peerPublicKey = ppk; + CFReleaseNull(ppk); } } diff --git a/keychain/SecureObjectSync/SOSAccountPriv.h b/keychain/SecureObjectSync/SOSAccountPriv.h index 798d1fb1..a1f2bc22 100644 --- a/keychain/SecureObjectSync/SOSAccountPriv.h +++ b/keychain/SecureObjectSync/SOSAccountPriv.h @@ -21,7 +21,6 @@ #include #include -#include #import @@ -97,16 +96,19 @@ typedef void (^SOSAccountSaveBlock)(CFDataRef flattenedAccount, CFErrorRef flatt @property (nonatomic, assign) BOOL circle_rings_retirements_need_attention; @property (nonatomic, assign) BOOL engine_peer_state_needs_repair; @property (nonatomic, assign) BOOL key_interests_need_updating; +@property (nonatomic, assign) BOOL need_backup_peers_created_after_backup_key_set; + @property (nonatomic, retain) NSMutableArray *change_blocks; @property (nonatomic, retain) NSMutableDictionary *waitForInitialSync_blocks; -@property (nonatomic, retain) NSData* accountKeyDerivationParamters; +@property (nonatomic, retain) NSData* accountKeyDerivationParameters; @property (nonatomic, assign) BOOL accountKeyIsTrusted; @property (nonatomic) SecKeyRef accountKey; @property (nonatomic) SecKeyRef previousAccountKey; +@property (nonatomic) SecKeyRef peerPublicKey; @property (copy) SOSAccountSaveBlock saveBlock; @@ -121,8 +123,12 @@ typedef void (^SOSAccountSaveBlock)(CFDataRef flattenedAccount, CFErrorRef flatt @property (nonatomic, assign) BOOL notifyViewChangeOnExit; @property (nonatomic, assign) BOOL notifyBackupOnExit; -@property (nonatomic, retain) NSUserDefaults* settings; +@property (nonatomic, retain) NSUserDefaults* settings; +@property (nonatomic) SecKeyRef octagonSigningFullKeyRef; +@property (nonatomic) SecKeyRef octagonEncryptionFullKeyRef; + +@property (nonatomic, assign) BOOL accountIsChanging; -(id) init NS_UNAVAILABLE; @@ -246,6 +252,8 @@ bool SOSAccountIsAccountIdentity(SOSAccount* account, SOSPeerInfoRef peer_info, bool SOSAccountFullPeerInfoVerify(SOSAccount* account, SecKeyRef privKey, CFErrorRef *error); CF_RETURNS_RETAINED SOSPeerInfoRef GenerateNewCloudIdentityPeerInfo(CFErrorRef *error); +void SOSiCloudIdentityPrivateKeyForEach(void (^complete)(SecKeyRef privKey)); + // Credentials bool SOSAccountHasPublicKey(SOSAccount* account, CFErrorRef* error); bool SOSAccountPublishCloudParameters(SOSAccount* account, CFErrorRef* error); @@ -269,9 +277,7 @@ void SOSAccountSetUserPublicTrustedForTesting(SOSAccount* account); void SOSAccountPurgeIdentity(SOSAccount*); bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, CFErrorRef* error); -bool sosAccountLeaveCircleWithAnalytics(SOSAccount* account, SOSCircleRef circle, NSData* parentData, CFErrorRef* error); -bool sosAccountLeaveRing(SOSAccount* account, SOSRingRef ring, CFErrorRef* error); bool SOSAccountForEachRing(SOSAccount* account, SOSRingRef (^action)(CFStringRef name, SOSRingRef ring)); bool SOSAccountUpdateBackUp(SOSAccount* account, CFStringRef viewname, CFErrorRef *error); void SOSAccountEnsureRecoveryRing(SOSAccount* account); @@ -298,15 +304,12 @@ bool SOSAccountClearValue(SOSAccount* account, CFStringRef key, CFErrorRef *erro CFTypeRef SOSAccountGetValue(SOSAccount* account, CFStringRef key, CFErrorRef *error); bool SOSAccountAddEscrowToPeerInfo(SOSAccount* account, SOSFullPeerInfoRef myPeer, CFErrorRef *error); -bool SOSAccountAddEscrowRecords(SOSAccount* account, CFStringRef dsid, CFDictionaryRef record, CFErrorRef *error); void SOSAccountRemoveRing(SOSAccount* a, CFStringRef ringName); SOSRingRef SOSAccountCopyRingNamed(SOSAccount* a, CFStringRef ringName, CFErrorRef *error); -SOSRingRef SOSAccountRingCreateForName(SOSAccount* a, CFStringRef ringName, CFErrorRef *error); bool SOSAccountUpdateRingFromRemote(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error); bool SOSAccountUpdateRing(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error); bool SOSAccountRemoveBackupPeers(SOSAccount* account, CFArrayRef peerIDs, CFErrorRef *error); -bool SOSAccountResetRing(SOSAccount* account, CFStringRef ringName, CFErrorRef *error); -bool SOSAccountCheckPeerAvailability(SOSAccount* account, CFErrorRef *error); +bool SOSAccountBackupKeyConsistencyCheck(SOSAccount* account, CFErrorRef *error); bool SOSAccountUpdateNamedRing(SOSAccount* account, CFStringRef ringName, CFErrorRef *error, SOSRingRef (^create)(CFStringRef ringName, CFErrorRef *error), SOSRingRef (^copyModified)(SOSRingRef existing, CFErrorRef *error)); @@ -322,12 +325,7 @@ bool SOSAccountUpdateBackupRing(SOSAccount* account, CFStringRef viewName, CFEr // Security tool test/debug functions // bool SOSAccountPostDebugScope(SOSAccount* account, CFTypeRef scope, CFErrorRef *error); -CFDataRef SOSAccountCopyAccountStateFromKeychain(CFErrorRef *error); -bool SOSAccountDeleteAccountStateFromKeychain(CFErrorRef *error); -CFDataRef SOSAccountCopyEngineStateFromKeychain(CFErrorRef *error); -bool SOSAccountDeleteEngineStateFromKeychain(CFErrorRef *error); -bool SOSAccountIsNew(SOSAccount* account, CFErrorRef *error); bool SOSAccountCheckForAlwaysOnViews(SOSAccount* account); // UUID, no setter just getter and ensuring value. void SOSAccountEnsureUUID(SOSAccount* account); @@ -351,7 +349,6 @@ NSArray* SOSAccountSortTLKS(NSArray* tlks); #endif bool SOSAccountCleanupAllKVSKeys(SOSAccount* account, CFErrorRef* error); -bool SOSAccountPopulateKVSWithBadKeys(SOSAccount* account, CFErrorRef* error); @end diff --git a/keychain/SecureObjectSync/SOSAccountRecovery.m b/keychain/SecureObjectSync/SOSAccountRecovery.m index 39d74993..a477f5c4 100644 --- a/keychain/SecureObjectSync/SOSAccountRecovery.m +++ b/keychain/SecureObjectSync/SOSAccountRecovery.m @@ -36,7 +36,6 @@ #include "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h" #include "keychain/SecureObjectSync/SOSInternal.h" -#include "SecADWrapper.h" #include "keychain/SecureObjectSync/SOSRecoveryKeyBag.h" #include "keychain/SecureObjectSync/SOSRingRecovery.h" @@ -139,7 +138,7 @@ bool SOSAccountSetRecoveryKey(SOSAccount* account, CFDataRef pubData, CFErrorRef CFReleaseNull(rkbg); if(SOSPeerInfoHasBackupKey(account.trust.peerInfo)) { - SOSAccountProcessBackupRings(account, error); + SOSAccountProcessBackupRings(account); } account.circle_rings_retirements_need_attention = true; result = true; diff --git a/keychain/SecureObjectSync/SOSAccountRings.m b/keychain/SecureObjectSync/SOSAccountRings.m index 30e18ed5..708940da 100644 --- a/keychain/SecureObjectSync/SOSAccountRings.m +++ b/keychain/SecureObjectSync/SOSAccountRings.m @@ -34,72 +34,12 @@ const CFStringRef kSOSRingOtherSyncable = CFSTR("Ring-OtherSyncable"); const CFStringRef kSOSRingKey = CFSTR("trusted_rings"); -static CFSetRef allCurrentRings(void) { - static dispatch_once_t dot; - static CFMutableSetRef allRings = NULL; - dispatch_once(&dot, ^{ - allRings = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); - CFSetAddValue(allRings, kSOSRingCircleV2); - CFSetAddValue(allRings, kSOSRingKeychainV0); - CFSetAddValue(allRings, kSOSRingPCSHyperion); - CFSetAddValue(allRings, kSOSRingPCSBladerunner); - CFSetAddValue(allRings, kSOSRingPCSLiverpool); - CFSetAddValue(allRings, kSOSRingPCSEscrow); - CFSetAddValue(allRings, kSOSRingPCSPianoMover); - CFSetAddValue(allRings, kSOSRingPCSNotes); - CFSetAddValue(allRings, kSOSRingPCSFeldspar); - CFSetAddValue(allRings, kSOSRingAppleTV); - CFSetAddValue(allRings, kSOSRingHomeKit); - CFSetAddValue(allRings, kSOSRingWifi); - CFSetAddValue(allRings, kSOSRingPasswords); - CFSetAddValue(allRings, kSOSRingCreditCards); - CFSetAddValue(allRings, kSOSRingiCloudIdentity); - CFSetAddValue(allRings, kSOSRingOtherSyncable); - }); - return allRings; -} - typedef struct ringDef_t { CFStringRef name; SOSRingType ringType; bool dropWhenLeaving; } ringDef, *ringDefPtr; -static ringDefPtr getRingDef(CFStringRef ringName) { - static ringDef retval; - - // Defaults - retval.name = ringName; - retval.dropWhenLeaving = true; - retval.ringType = kSOSRingEntropyKeyed; - - - if(CFSetContainsValue(allCurrentRings(), ringName)) { - retval.ringType = kSOSRingBase; - retval.dropWhenLeaving = false; - } else { - retval.ringType = kSOSRingBackup; - retval.dropWhenLeaving = false; - } - return &retval; -} - -__unused static inline void SOSAccountRingForEachRingMatching(SOSAccount* a, void (^action)(SOSRingRef ring), bool (^condition)(SOSRingRef ring)) { - CFSetRef allRings = allCurrentRings(); - CFSetForEach(allRings, ^(const void *value) { - CFStringRef ringName = (CFStringRef) value; - SOSRingRef ring = [a.trust copyRing:ringName err:NULL]; - if (condition(ring)) { - action(ring); - } - CFReleaseNull(ring); - }); -} - - - - - static void SOSAccountSetRings(SOSAccount* a, CFMutableDictionaryRef newrings){ SOSAccountTrustClassic *trust = a.trust; [trust.expansion setObject:(__bridge NSMutableDictionary*)newrings forKey:(__bridge NSString* _Nonnull)(kSOSRingKey)]; @@ -175,15 +115,12 @@ SOSRingRef SOSAccountCopyRingNamed(SOSAccount* a, CFStringRef ringName, CFErrorR return found; } -/* Unused? */ -SOSRingRef SOSAccountRingCreateForName(SOSAccount* a, CFStringRef ringName, CFErrorRef *error) { - ringDefPtr rdef = getRingDef(ringName); - if(!rdef) return NULL; - SOSRingRef retval = SOSRingCreate(rdef->name, (__bridge CFStringRef) a.peerID, rdef->ringType, error); - return retval; -} - bool SOSAccountUpdateRingFromRemote(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error) { + if(account && account.accountIsChanging) { + secnotice("circleOps", "SOSAccountUpdateRingFromRemote called before signing in to new account"); + return true; // we want to drop circle notifications when account is changing + } + require_quiet(SOSAccountHasPublicKey(account, error), errOut); return [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:false err:error]; @@ -203,25 +140,22 @@ errOut: bool SOSAccountUpdateNamedRing(SOSAccount* account, CFStringRef ringName, CFErrorRef *error, SOSRingRef (^create)(CFStringRef ringName, CFErrorRef *error), SOSRingRef (^copyModified)(SOSRingRef existing, CFErrorRef *error)) { + if(![account isInCircle:NULL]) { + return false; + } bool result = false; - SOSRingRef found = [account.trust copyRing:ringName err:error]; - + SOSRingRef found = NULL; SOSRingRef newRing = NULL; + found = [account.trust copyRing:ringName err:error]; if(!found) { found = create(ringName, error); } - require_quiet(found, errOut); - newRing = copyModified(found, error); - CFReleaseNull(found); - - require_quiet(newRing, errOut); - - require_quiet(SOSAccountHasPublicKey(account, error), errOut); - require_quiet(SOSAccountHasCircle(account, error), errOut); - - result = [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error]; - -errOut: + if(found) { + newRing = copyModified(found, error); + if(newRing) { + result = [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error]; + } + } CFReleaseNull(found); CFReleaseNull(newRing); return result; diff --git a/keychain/SecureObjectSync/SOSAccountTransaction.m b/keychain/SecureObjectSync/SOSAccountTransaction.m index 168d096d..64ade897 100644 --- a/keychain/SecureObjectSync/SOSAccountTransaction.m +++ b/keychain/SecureObjectSync/SOSAccountTransaction.m @@ -73,6 +73,10 @@ return circleStatus; } +static inline SOSCCStatus reportAsSOSCCStatus(uint64_t x) { + return (SOSCCStatus) x & CC_MASK; +} + - (void) updateSOSCircleCachedStatus { // clearly invalid, overwritten by cached value in notify_get_state() // if its the second time we are launchded @@ -92,7 +96,7 @@ } return true; }); - secnotice("sosnotify", "initial last circle status is: %llu", (unsigned long long)lastStatus); + secnotice("sosnotify", "initial last circle status is: %d", reportAsSOSCCStatus(lastStatus)); }); uint64_t currentStatus = [self currentTrustBitmask]; @@ -114,8 +118,8 @@ lastStatus = currentStatus; - secnotice("sosnotify", "new last circle status is: %llu (notify: %s)", - (unsigned long long)lastStatus, + secnotice("sosnotify", "new last circle status is: %d (notify: %s)", + reportAsSOSCCStatus(lastStatus), circleStatusChanged ? "yes" : "no"); SOSCachedNotificationOperation(kSOSCCCircleChangedNotification, ^bool(int token, bool gtg) { @@ -198,7 +202,7 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { } self.initialUnsyncedViews = (__bridge_transfer NSMutableSet*)SOSAccountCopyOutstandingViews(self.account); - self.initialKeyParameters = self.account.accountKeyDerivationParamters ? [NSData dataWithData:self.account.accountKeyDerivationParamters] : nil; + self.initialKeyParameters = self.account.accountKeyDerivationParameters ? [NSData dataWithData:self.account.accountKeyDerivationParameters] : nil; SOSPeerInfoRef mpi = self.account.peerInfo; if (mpi) { @@ -206,6 +210,8 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { [self.account ensureOctagonPeerKeys]; } self.peersToRequestSync = nil; + + SOSAccountEnsurePeerInfoHasCurrentBackupKey(self, NULL); if(self.account.key_interests_need_updating) { SOSUpdateKeyInterest(self.account); @@ -238,9 +244,12 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { bool isInCircle = [self.account isInCircle:NULL]; if (isInCircle && self.peersToRequestSync) { - SOSCCRequestSyncWithPeers((__bridge CFSetRef)(self.peersToRequestSync)); + NSMutableSet* worklist = self.peersToRequestSync; + self.peersToRequestSync = nil; + SOSCCRequestSyncWithPeers((__bridge CFSetRef)(worklist)); } - self.peersToRequestSync = nil; + + SOSAccountEnsurePeerInfoHasCurrentBackupKey(self, NULL); if (isInCircle) { SOSAccountEnsureSyncChecking(self.account); @@ -281,7 +290,19 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { #if OCTAGON [self.account triggerRingUpdate]; #endif + // Also, there might be some view set change. Ensure that the engine knows... + notifyEngines = true; } + if(self.account.need_backup_peers_created_after_backup_key_set){ + self.account.need_backup_peers_created_after_backup_key_set = false; + notifyEngines = true; + } + + // Always notify the engines if the view set has changed + CFSetRef currentViews = self.account.peerInfo ? SOSPeerInfoCopyEnabledViews(self.account.peerInfo) : NULL; + BOOL viewSetChanged = !NSIsEqualSafe(self.initialViews, (__bridge NSSet*)currentViews); + CFReleaseNull(currentViews); + notifyEngines |= viewSetChanged; if (notifyEngines) { #if OCTAGON @@ -323,7 +344,7 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { } // This is the logic to detect a new userKey: - bool userKeyChanged = !NSIsEqualSafe(self.initialKeyParameters, self.account.accountKeyDerivationParamters); + bool userKeyChanged = !NSIsEqualSafe(self.initialKeyParameters, self.account.accountKeyDerivationParameters); // This indicates we initiated a password change. bool weInitiatedKeyChange = (self.initialTrusted && diff --git a/keychain/SecureObjectSync/SOSAccountTrust.m b/keychain/SecureObjectSync/SOSAccountTrust.m index 8aafe173..c7303592 100644 --- a/keychain/SecureObjectSync/SOSAccountTrust.m +++ b/keychain/SecureObjectSync/SOSAccountTrust.m @@ -16,9 +16,7 @@ -(id)init { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.retirees = [NSMutableSet set]; self.fullPeerInfo = NULL; self.trustedCircle = NULL; @@ -32,9 +30,7 @@ departureCode:(enum DepartureReason)code peerExpansion:(NSMutableDictionary*)e { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.retirees = r; self.fullPeerInfo = fpi; self.trustedCircle = trusted_circle; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h b/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h index 624badd0..e3815966 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h @@ -20,12 +20,11 @@ -(bool) isInCircleOnly:(CFErrorRef *)error; -(void) forEachCirclePeerExceptMe:(SOSIteratePeerBlock)block; -(bool) leaveCircle:(SOSAccount*)account err:(CFErrorRef*) error; --(bool) leaveCircleWithAccount:(SOSAccount*)account withAnalytics:(NSData*)parentEvent err:(CFErrorRef*) error; +-(bool) leaveCircleWithAccount:(SOSAccount*)account err:(CFErrorRef*) error; -(bool) resetToOffering:(SOSAccountTransaction*) aTxn key:(SecKeyRef)userKey err:(CFErrorRef*) error; -(bool) resetCircleToOffering:(SOSAccountTransaction*) aTxn userKey:(SecKeyRef) user_key err:(CFErrorRef *)error; -(SOSCCStatus) thisDeviceStatusInCircle:(SOSCircleRef) circle peer:(SOSPeerInfoRef) this_peer; -(bool) updateCircle:(SOSCircleStorageTransport*)circleTransport newCircle:(SOSCircleRef) newCircle err:(CFErrorRef*)error; --(bool) updateCircleWithAnalytics:(SOSCircleStorageTransport*)circleTransport newCircle:(SOSCircleRef) newCircle parentEvent:(NSData*)parentEvent err:(CFErrorRef*)error; -(bool) updateCircleFromRemote:(SOSCircleStorageTransport*)circleTransport newCircle:(SOSCircleRef)newCircle err:(CFErrorRef*)error; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.m b/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.m index d118ec54..3507aa1a 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.m +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.m @@ -348,44 +348,44 @@ static bool SOSCircleHasUpdatedPeerInfoWithOctagonKey(SOSCircleRef oldCircle, SO old_circle_key, account.accountKey, me, error); - CFStringRef concStr = NULL; - switch(concstat) { - case kSOSConcordanceTrusted: - circle_action = countersign; - concStr = CFSTR("Trusted"); - break; - case kSOSConcordanceGenOld: - circle_action = userTrustedOldCircle ? revert : ignore; - concStr = CFSTR("Generation Old"); - break; - case kSOSConcordanceBadUserSig: - case kSOSConcordanceBadPeerSig: - circle_action = userTrustedOldCircle ? revert : accept; - concStr = CFSTR("Bad Signature"); - break; - case kSOSConcordanceNoUserSig: - circle_action = userTrustedOldCircle ? revert : accept; - concStr = CFSTR("No User Signature"); - break; - case kSOSConcordanceNoPeerSig: - circle_action = accept; // We might like this one eventually but don't countersign. - concStr = CFSTR("No trusted peer signature"); - secnotice("signing", "##### No trusted peer signature found, accepting hoping for concordance later"); - break; - case kSOSConcordanceNoPeer: - circle_action = leave; - leave_reason = kSOSLeftUntrustedCircle; - concStr = CFSTR("No trusted peer left"); - break; - case kSOSConcordanceNoUserKey: - secerror("##### No User Public Key Available, this shouldn't ever happen!!!"); - abort(); - break; - default: - secerror("##### Bad Error Return from ConcordanceTrust"); - abort(); - break; - } + CFStringRef concStr = NULL; + switch(concstat) { + case kSOSConcordanceTrusted: + circle_action = countersign; + concStr = CFSTR("Trusted"); + break; + case kSOSConcordanceGenOld: + circle_action = userTrustedOldCircle ? revert : ignore; + concStr = CFSTR("Generation Old"); + break; + case kSOSConcordanceBadUserSig: + case kSOSConcordanceBadPeerSig: + circle_action = userTrustedOldCircle ? revert : accept; + concStr = CFSTR("Bad Signature"); + break; + case kSOSConcordanceNoUserSig: + circle_action = userTrustedOldCircle ? revert : accept; + concStr = CFSTR("No User Signature"); + break; + case kSOSConcordanceNoPeerSig: + circle_action = accept; // We might like this one eventually but don't countersign. + concStr = CFSTR("No trusted peer signature"); + secnotice("signing", "##### No trusted peer signature found, accepting hoping for concordance later"); + break; + case kSOSConcordanceNoPeer: + circle_action = leave; + leave_reason = kSOSLeftUntrustedCircle; + concStr = CFSTR("No trusted peer left"); + break; + case kSOSConcordanceNoUserKey: + secerror("##### No User Public Key Available, this shouldn't ever happen!!!"); + abort(); + break; + default: + secerror("##### Bad Error Return from ConcordanceTrust"); + abort(); + break; + } secnotice("signing", "Decided on action [%s] based on concordance state [%@] and [%s] circle. My PeerID is %@", actionstring[circle_action], concStr, userTrustedOldCircle ? "trusted" : "untrusted", myPeerID); @@ -464,8 +464,7 @@ static bool SOSCircleHasUpdatedPeerInfoWithOctagonKey(SOSCircleRef oldCircle, SO && !(SOSCircleCountPeers(oldCircle) == 1 && SOSCircleHasPeer(oldCircle, me, NULL)) // If it was our offering, don't change ID to avoid ghosts && !SOSCircleHasPeer(newCircle, me, NULL) && !SOSCircleHasApplicant(newCircle, me, NULL)) { secnotice("circle", "Purging my peer (ID: %@) for circle '%@'!!!", SOSPeerInfoGetPeerID(me), SOSCircleGetName(oldCircle)); - if (self.fullPeerInfo) - SOSFullPeerInfoPurgePersistentKey(self.fullPeerInfo, NULL); + [self purgeIdentity]; me = NULL; me_full = NULL; } @@ -476,8 +475,7 @@ static bool SOSCircleHasUpdatedPeerInfoWithOctagonKey(SOSCircleRef oldCircle, SO secnotice("circle", "Rejected, Purging my applicant peer (ID: %@) for circle '%@'", SOSPeerInfoGetPeerID(me), SOSCircleGetName(oldCircle)); debugDumpCircle(CFSTR("oldCircle"), oldCircle); debugDumpCircle(CFSTR("newCircle"), newCircle); - if (self.fullPeerInfo) - SOSFullPeerInfoPurgePersistentKey(self.fullPeerInfo, NULL); + [self purgeIdentity]; me = NULL; me_full = NULL; } else { @@ -657,7 +655,7 @@ fail: // rdar://51233857 - don't gensign if there isn't a change in the userKey // also don't rebake the circle to fix the icloud identity if there isn't // a change as that will mess up piggybacking. - if(SOSAccountFullPeerInfoVerify(account, privKey, NULL) && SOSCircleVerify(account.trust.trustedCircle, account.accountKey, NULL)) { + if(account.trust.trustedCircle && SOSAccountFullPeerInfoVerify(account, privKey, NULL) && SOSCircleVerify(account.trust.trustedCircle, account.accountKey, NULL)) { secnotice("updatingGenSignature", "no change to userKey - skipping gensign"); return; } @@ -696,12 +694,12 @@ fail: } } --(bool) leaveCircleWithAccount:(SOSAccount*)account withAnalytics:(NSData*)parentEvent err:(CFErrorRef*) error +-(bool) leaveCircleWithAccount:(SOSAccount*)account err:(CFErrorRef*) error { bool result = true; secnotice("circleOps", "leaveCircleWithAccount: Leaving circle by client request"); result &= [self modifyCircle:account.circle_transport err:error action:^(SOSCircleRef circle) { - return sosAccountLeaveCircleWithAnalytics(account, circle, parentEvent, error); + return sosAccountLeaveCircle(account, circle, error); }]; self.departureCode = kSOSWithdrewMembership; @@ -724,9 +722,8 @@ fail: -(bool) resetToOffering:(SOSAccountTransaction*) aTxn key:(SecKeyRef)userKey err:(CFErrorRef*) error { - SOSFullPeerInfoPurgePersistentKey(self.fullPeerInfo, NULL); - self.fullPeerInfo = nil; - + [self purgeIdentity]; + secnotice("resetToOffering", "Resetting circle to offering by request from client"); return userKey && [self resetCircleToOffering:aTxn userKey:userKey err:error]; @@ -741,7 +738,7 @@ fail: if(![self hasCircle:error]) return result; - if(![self ensureFullPeerAvailable:(__bridge CFDictionaryRef)(account.gestalt) deviceID:(__bridge CFStringRef)(account.deviceID) backupKey:(__bridge CFDataRef)(account.backup_key) err:error]) + if(![self ensureFullPeerAvailable:account err:error]) return result; (void)[self resetAllRings:account err:error]; @@ -807,7 +804,7 @@ void SOSAccountForEachCirclePeerExceptMe(SOSAccount* account, void (^action)(SOS __block SOSFullPeerInfoRef cloud_full_peer = NULL; __block SOSAccount* account = aTxn.account; require_action_quiet(self.trustedCircle, fail, SOSCreateErrorWithFormat(kSOSErrorPeerNotFound, NULL, error, NULL, CFSTR("Don't have circle when joining???"))); - require_quiet([self ensureFullPeerAvailable:(__bridge CFDictionaryRef)account.gestalt deviceID:(__bridge CFStringRef)account.deviceID backupKey:(__bridge CFDataRef)account.backup_key err:error], fail); + require_quiet([self ensureFullPeerAvailable:account err:error], fail); if (SOSCircleCountPeers(self.trustedCircle) == 0 || SOSAccountGhostResultsInReset(account)) { secnotice("resetToOffering", "Resetting circle to offering since there are no peers"); diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h b/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h index 5d716757..e6855c86 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h @@ -21,7 +21,6 @@ -(bool) handleUpdateRing:(SOSAccount*)account prospectiveRing:(SOSRingRef)prospectiveRing transport:(SOSKVSCircleStorageTransport*)circleTransport userPublicKey:(SecKeyRef)userPublic writeUpdate:(bool)writeUpdate err:(CFErrorRef *)error; -(bool) resetRing:(SOSAccount*)account ringName:(CFStringRef) ringName err:(CFErrorRef *)error; -(bool) resetAccountToEmpty:(SOSAccount*)account transport: (SOSCircleStorageTransport*)circleTransport err:(CFErrorRef*) error; --(bool) resetAccountToEmptyWithAnalytics:(SOSAccount*)account transport: (SOSCircleStorageTransport*)circleTransport parentEvent:(NSData*)parentEvent err:(CFErrorRef*) error; -(SOSRingRef) copyRing:(CFStringRef) ringName err:(CFErrorRef *)error; -(CFMutableDictionaryRef) getRings:(CFErrorRef *)error; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.m b/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.m index b6273573..df3b08dd 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.m +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.m @@ -15,7 +15,6 @@ #import "keychain/SecureObjectSync/SOSPeerInfoCollections.h" #import "keychain/SecureObjectSync/SOSTransportCircleKVS.h" #import "keychain/SecureObjectSync/SOSRingRecovery.h" -#import "keychain/SigninMetrics/SFSignInAnalytics.h" @implementation SOSAccountTrustClassic (Expansion) typedef enum { @@ -202,29 +201,12 @@ errOut: } -(bool) resetAccountToEmpty:(SOSAccount*)account transport: (SOSCircleStorageTransport*)circleTransport err:(CFErrorRef*) error -{ - return [self resetAccountToEmptyWithAnalytics:account transport:circleTransport parentEvent:nil err:error ]; -} - --(bool) resetAccountToEmptyWithAnalytics:(SOSAccount*)account transport: (SOSCircleStorageTransport*)circleTransport parentEvent:(NSData*)parentEvent err:(CFErrorRef*) error { __block bool result = true; CFErrorRef resetError = NULL; - NSError* localError = nil; - SFSignInAnalytics* parent = nil; - SFSignInAnalytics *resetAllRingsEvent = nil; - bool doingAnalytics = parentEvent != nil; - - if(doingAnalytics) { - parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - resetAllRingsEvent = [parent newSubTaskForEvent:@"resetAllRingsEvent"]; - } result &= [self resetAllRings:account err:&resetError]; if(resetError){ - if(doingAnalytics) { - [resetAllRingsEvent logRecoverableError:(__bridge NSError*)resetError]; - } secerror("reset all rings error: %@", resetError); if(error){ *error = resetError; @@ -232,29 +214,17 @@ errOut: CFReleaseNull(resetError); } } - if(doingAnalytics) { - [resetAllRingsEvent stopWithAttributes:nil]; - } self.fullPeerInfo = nil; self.departureCode = kSOSWithdrewMembership; secnotice("circleOps", "Reset Rings to empty by client request"); - SFSignInAnalytics *resetCircleToEmptyEvent = nil; - if(doingAnalytics) { - resetCircleToEmptyEvent = [parent newSubTaskForEvent:@"resetCircleToEmptyEvent"]; - } - result &= [self modifyCircle:circleTransport err:error action:^bool(SOSCircleRef circle) { result = SOSCircleResetToEmpty(circle, error); return result; }]; - if(doingAnalytics) { - [resetCircleToEmptyEvent stopWithAttributes:nil]; - } - if (!result) { secerror("error: %@", error ? *error : NULL); } else { @@ -332,6 +302,15 @@ errOut: CFStringRef modifierPeerID = CFStringCreateTruncatedCopy(SOSRingGetLastModifier(prospectiveRing), 8); secnotice("ring", "start:[%s] modifier: %@", localRemote, modifierPeerID); CFReleaseNull(modifierPeerID); + + // don't act on our own echos from KVS (remote ring, our peerID as modifier) + oldRing = [self copyRing:ringName err:NULL]; + if(!localUpdate && CFEqualSafe(peerID, SOSRingGetLastModifier(prospectiveRing)) && CFEqualSafe(oldRing, prospectiveRing)) { + secnotice("ring", "Ceasing ring handling for an echo of our own posted ring"); + success = true; + goto errOut; + } + require_quiet(SOSAccountHasPublicKey(account, error), errOut); require_action_quiet(peerPubKey, errOut, SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("No device public key to work with"), NULL, error)); require_action_quiet(peerPrivKey, errOut, SOSCreateError(kSOSErrorPrivateKeyAbsent, CFSTR("No device private key to work with"), NULL, error)); @@ -347,7 +326,6 @@ errOut: } require_action_quiet(peerActive, errOut, success = true); - oldRing = [self copyRing:ringName err:NULL]; newRing = SOSRingCopyRing(prospectiveRing, NULL); ringAction_t ringAction = ignore; @@ -424,6 +402,7 @@ errOut: // This will take care of modify, but we're always going to do this scan if we get this far CFSetRef ringPeerIDSet = SOSRingCopyPeerIDs(newRing); if(CFSetGetCount(ringPeerIDSet) == 0) { // this is a reset ring + secnotice("ring", "changing state to accept - we have a reset ring"); ringAction = accept; } else { // Get the peerIDs appropriate for the ring @@ -440,6 +419,9 @@ errOut: } if(!CFEqual(filteredPeerIDs, ringPeerIDSet)) { + secnotice("ring", "mismatch between filteredPeerIDs and ringPeerIDSet, fixing ring and gensigning"); + secnotice("ring", "filteredPeerIDs %@", filteredPeerIDs); + secnotice("ring", " ringPeerIDSet %@", ringPeerIDSet); SOSRingSetPeerIDs(newRing, filteredPeerIDs); SOSRingRemoveSignatures(newRing, NULL); ringAction = countersign; @@ -457,14 +439,27 @@ errOut: __block bool fixBSKB = false; CFDataRef recoveryKeyData = SOSAccountCopyRecoveryPublic(kCFAllocatorDefault, account, NULL); SOSBackupSliceKeyBagRef currentBSKB = SOSRingCopyBackupSliceKeyBag(newRing, NULL); + + if(currentBSKB == NULL) { + secnotice("ring", "Backup ring contains no BSKB"); + fixBSKB = true; + } + + if(SOSBSKBAllPeersBackupKeysAreInKeyBag(currentBSKB, filteredPeerInfos) == false) { + secnotice("ring", "BSKB is missing some backup keys"); + fixBSKB = true; + } - fixBSKB = !currentBSKB || - !SOSBSKBAllPeersBackupKeysAreInKeyBag(currentBSKB, filteredPeerInfos) || - !SOSBSKBHasThisRecoveryKey(currentBSKB, recoveryKeyData); + if(SOSBSKBHasThisRecoveryKey(currentBSKB, recoveryKeyData) == false) { + secnotice("ring", "BSKB is missing recovery key"); + fixBSKB = true; + } if(fixBSKB) { CFErrorRef localError = NULL; CFSetRef viewSet = SOSRingGetBackupViewset(newRing, NULL); + secnotice("ring", "Need to fix BSKB - this will prompt a gensign"); + SOSBackupSliceKeyBagRef bskb = NULL; if(recoveryKeyData) { CFMutableDictionaryRef additionalKeys = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); @@ -498,6 +493,7 @@ errOut: } else { CFErrorRef signingError = NULL; if (fpi && SOSRingConcordanceSign(newRing, fpi, &signingError)) { + secnotice("ring", "concordance signed"); ringToPush = newRing; ringAction = accept; } else { @@ -515,10 +511,12 @@ leaveAndAccept: if(ringIsRecovery) { if(!localUpdate) { // processing a remote ring - we accept the new recovery key here if(SOSRingIsEmpty_Internal(newRing)) { // Reset ring will reset the recovery key + secnotice("ring", "Reset ring for recovery from remote peer"); SOSRecoveryKeyBagRef ringRKBG = SOSRecoveryKeyBagCreateForAccount(kCFAllocatorDefault, (__bridge CFTypeRef)account, SOSRKNullKey(), error); SOSAccountSetRecoveryKeyBagEntry(kCFAllocatorDefault, account, ringRKBG, error); CFReleaseNull(ringRKBG); } else { // normal ring recovery key harvest + secnotice("ring", "normal ring recovery key harvest"); SOSRecoveryKeyBagRef ringRKBG = SOSRingCopyRecoveryKeyBag(newRing, NULL); SOSAccountSetRecoveryKeyBagEntry(kCFAllocatorDefault, account, ringRKBG, error); CFReleaseNull(ringRKBG); diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h b/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h index 0bd9cd22..07890687 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h @@ -17,7 +17,7 @@ -(bool) fullPeerInfoVerify:(SecKeyRef) privKey err:(CFErrorRef *)error; -(bool) hasFullPeerInfo:(CFErrorRef*) error; -(SOSFullPeerInfoRef) CopyAccountIdentityPeerInfo CF_RETURNS_RETAINED; --(bool) ensureFullPeerAvailable:(CFDictionaryRef)gestalt deviceID:(CFStringRef)deviceID backupKey:(CFDataRef)backup err:(CFErrorRef *) error; +-(bool) ensureFullPeerAvailable:(SOSAccount*)account err:(CFErrorRef *) error; -(bool) isMyPeerActive:(CFErrorRef*) error; -(void) purgeIdentity; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.m b/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.m index d72bd125..1cca6e06 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.m +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.m @@ -10,6 +10,10 @@ #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h" #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h" #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" +#import +#import +#import +#import #if __OBJC2__ #import "Analytics/Clients/SOSAnalytics.h" #endif // __OBJC2__ @@ -135,6 +139,10 @@ secnotice("circleChange", "Already have Octagon signing key"); CFReleaseNull(self->_cachedOctagonSigningKey); _cachedOctagonSigningKey = SecKeyCopyPublicKey(octagonSigningFullKey); + + // Ensure that the agrp is correct. + SOSCCEnsureAccessGroupOfKey(_cachedOctagonSigningKey, @"sync", (__bridge NSString*)kSOSInternalAccessGroup); + } else if (octagonSigningFullKey == NULL && copyError && ((CFEqualSafe(CFErrorGetDomain(copyError), kCFErrorDomainOSStatus) && CFErrorGetCode(copyError) == errSecItemNotFound) || (CFEqualSafe(CFErrorGetDomain(copyError), kCFErrorDomainOSStatus) && CFErrorGetCode(copyError) == errSecDecode) || @@ -178,6 +186,8 @@ secnotice("circleChange", "Already have Octagon encryption key"); CFReleaseNull(self->_cachedOctagonEncryptionKey); _cachedOctagonEncryptionKey = SecKeyCopyPublicKey(octagonEncryptionFullKey); + + SOSCCEnsureAccessGroupOfKey(_cachedOctagonEncryptionKey, @"sync", (__bridge NSString*)kSOSInternalAccessGroup); } else if (octagonEncryptionFullKey == NULL && copyError && ((CFEqualSafe(CFErrorGetDomain(copyError), kCFErrorDomainOSStatus) && CFErrorGetCode(copyError) == errSecItemNotFound) || (CFEqualSafe(CFErrorGetDomain(copyError), kCFErrorDomainOSStatus) && CFErrorGetCode(copyError) == errSecDecode) || @@ -217,23 +227,44 @@ #endif /* OCTAGON */ } --(bool) ensureFullPeerAvailable:(CFDictionaryRef)gestalt deviceID:(CFStringRef)deviceID backupKey:(CFDataRef)backup err:(CFErrorRef *) error +-(bool) ensureFullPeerAvailable:(SOSAccount*) account err:(CFErrorRef *) error { require_action_quiet(self.trustedCircle, fail, SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("Don't have circle"))); - - if (self.fullPeerInfo == NULL) { + + if (self.fullPeerInfo == NULL || !SOSFullPeerInfoPrivKeyExists(self.fullPeerInfo)) { + if(self.fullPeerInfo) { // fullPeerInfo where privkey is gone + secnotice("circleOps", "FullPeerInfo has no matching private key - resetting FPI and attendant keys"); + CFReleaseNull(self->fullPeerInfo); + if(self->peerInfo) CFReleaseNull(self->peerInfo); + if(self->_cachedOctagonSigningKey) CFReleaseNull(self->_cachedOctagonSigningKey); + if(self->_cachedOctagonEncryptionKey) CFReleaseNull(self->_cachedOctagonEncryptionKey); + } + + SecKeyRef fullKey = NULL; bool skipInitialSync = false; // This will be set if the set of initial sync views is empty NSString* octagonKeyName; - CFStringRef keyName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("ID for %@-%@"), SOSPeerGestaltGetName(gestalt), SOSCircleGetName(self.trustedCircle)); - SecKeyRef full_key = [self randomPermanentFullECKey:256 name:(__bridge NSString *)keyName error:NULL]; + CFStringRef keyName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("ID for %@-%@"), SOSPeerGestaltGetName((__bridge CFDictionaryRef)(account.gestalt)), SOSCircleGetName(self.trustedCircle)); + fullKey = [self randomPermanentFullECKey:256 name:(__bridge NSString *)keyName error:NULL]; octagonKeyName = [@"Octagon Peer Signing " stringByAppendingString:(__bridge NSString*)keyName]; - SecKeyRef octagonSigningFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL]; + + SecKeyRef octagonSigningFullKey = NULL; + if (account.octagonSigningFullKeyRef != NULL) { + octagonSigningFullKey = CFRetainSafe(account.octagonSigningFullKeyRef); + } else { + octagonSigningFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL]; + } octagonKeyName = [@"Octagon Peer Encryption " stringByAppendingString:(__bridge NSString*)keyName]; - SecKeyRef octagonEncryptionFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL]; - if (full_key && octagonSigningFullKey && octagonEncryptionFullKey) { + SecKeyRef octagonEncryptionFullKey = NULL; + if (account.octagonEncryptionFullKeyRef != NULL){ + octagonEncryptionFullKey = CFRetainSafe(account.octagonEncryptionFullKeyRef); + } else { + octagonEncryptionFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL]; + } + + if (fullKey && octagonSigningFullKey && octagonEncryptionFullKey) { CFMutableSetRef initialViews = SOSViewCopyViewSet(kViewSetInitial); CFMutableSetRef initialSyncDoneViews = SOSViewCopyViewSet(kViewSetAlwaysOn); CFSetRef defaultViews = SOSViewCopyViewSet(kViewSetDefault); @@ -250,8 +281,14 @@ // setting fullPeerInfo takes an extra ref, so... self.fullPeerInfo = nil; - SOSFullPeerInfoRef fpi = SOSFullPeerInfoCreateWithViews(kCFAllocatorDefault, gestalt, backup, initialViews, full_key, octagonSigningFullKey, octagonEncryptionFullKey, error); + SOSFullPeerInfoRef fpi = SOSFullPeerInfoCreateWithViews(kCFAllocatorDefault, (__bridge CFDictionaryRef)(account.gestalt), (__bridge CFDataRef)(account.backup_key), initialViews, fullKey, octagonSigningFullKey, octagonEncryptionFullKey, error); self.fullPeerInfo = fpi; + SecKeyRef pubKey = SOSFullPeerInfoCopyPubKey(fpi, NULL); + account.peerPublicKey = pubKey; + CFReleaseNull(pubKey); + if(!account.peerPublicKey) { + secnotice("circleOp", "Failed to copy peer public key for account object"); + } CFReleaseNull(fpi); CFDictionaryRef v2dictionaryTestUpdates = [self getValueFromExpansion:kSOSTestV2Settings err:NULL]; @@ -272,7 +309,7 @@ } - CFReleaseNull(full_key); + CFReleaseNull(fullKey); CFReleaseNull(octagonSigningFullKey); CFReleaseNull(octagonEncryptionFullKey); CFReleaseNull(keyName); @@ -292,7 +329,7 @@ fail: // Purge private key but don't return error if we can't. CFErrorRef purgeError = NULL; if (!SOSFullPeerInfoPurgePersistentKey(self.fullPeerInfo, &purgeError)) { - secwarning("Couldn't purge persistent key for %@ [%@]", self.fullPeerInfo, purgeError); + secwarning("Couldn't purge persistent keys for %@ [%@]", self.fullPeerInfo, purgeError); } CFReleaseNull(purgeError); diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic.h b/keychain/SecureObjectSync/SOSAccountTrustClassic.h index a1a2e237..0188cf36 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic.h +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic.h @@ -32,7 +32,7 @@ //Views -(SOSViewResultCode) updateView:(SOSAccount*)account name:(CFStringRef) viewname code:(SOSViewActionCode) actionCode err:(CFErrorRef *)error; -(SOSViewResultCode) viewStatus:(SOSAccount*)account name:(CFStringRef) viewname err:(CFErrorRef *)error; --(bool) updateViewSetsWithAnalytics:(SOSAccount*)account enabled:(CFSetRef) origEnabledViews disabled:(CFSetRef) origDisabledViews parentEvent:(NSData*)parentEvent; +-(bool) updateViewSets:(SOSAccount*)account enabled:(CFSetRef) origEnabledViews disabled:(CFSetRef) origDisabledViews; -(CFSetRef) copyPeerSetForView:(CFStringRef) viewName; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic.m b/keychain/SecureObjectSync/SOSAccountTrustClassic.m index 10459637..76831260 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic.m +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic.m @@ -36,9 +36,7 @@ extern CFStringRef kSOSAccountDebugScope; -(id)init { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.retirees = [NSMutableSet set]; self.fullPeerInfo = NULL; self.trustedCircle = NULL; @@ -52,9 +50,7 @@ extern CFStringRef kSOSAccountDebugScope; -(id)initWithRetirees:(NSMutableSet*)r fpi:(SOSFullPeerInfoRef)fpi circle:(SOSCircleRef) trusted_circle departureCode:(enum DepartureReason)code peerExpansion:(NSMutableDictionary*)e { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.retirees = [[NSMutableSet alloc] initWithSet:r] ; self.fullPeerInfo = CFRetainSafe(fpi); self.trustedCircle = CFRetainSafe(trusted_circle); @@ -211,21 +207,11 @@ static bool SOSAccountScreenViewListForValidV0(SOSAccount* account, CFMutableSe return retval; } --(bool) updateViewSetsWithAnalytics:(SOSAccount*)account enabled:(CFSetRef) origEnabledViews disabled:(CFSetRef) origDisabledViews parentEvent:(NSData*)parentEvent +-(bool) updateViewSets:(SOSAccount*)account enabled:(CFSetRef) origEnabledViews disabled:(CFSetRef) origDisabledViews { bool retval = false; bool updateCircle = false; SOSPeerInfoRef pi = NULL; - NSError* localError = nil; - SFSignInAnalytics* parent = NULL; - bool doAnalytics = (parentEvent != NULL); - - if(doAnalytics) { - parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - } - - SFSignInAnalytics *hasCompletedInitialSyncEvent = nil; - SFSignInAnalytics *updatePeerInCircleEvent = nil; CFMutableSetRef enabledViews = NULL; CFMutableSetRef disabledViews = NULL; @@ -263,9 +249,7 @@ static bool SOSAccountScreenViewListForValidV0(SOSAccount* account, CFMutableSe require_action_quiet(SOSAccountScreenViewListForValidV0(account, enabledViews, kSOSCCViewEnable), errOut, secnotice("viewChange", "Bad view change (enable) with kSOSViewKeychainV0")); require_action_quiet(SOSAccountScreenViewListForValidV0(account, disabledViews, kSOSCCViewDisable), errOut, secnotice("viewChange", "Bad view change (disable) with kSOSViewKeychainV0")); - if(doAnalytics) { - hasCompletedInitialSyncEvent = [parent newSubTaskForEvent:@"hasCompletedInitialSyncEvent"]; - } + if(SOSAccountHasCompletedInitialSync(account)) { if(enabledViews) updateCircle |= SOSViewSetEnable(pi, enabledViews); if(disabledViews) updateCircle |= SOSViewSetDisable(pi, disabledViews); @@ -276,31 +260,21 @@ static bool SOSAccountScreenViewListForValidV0(SOSAccount* account, CFMutableSe if(disabledViews) SOSAccountPendDisableViewSet(account, disabledViews); retval = true; } - if(doAnalytics) { - [hasCompletedInitialSyncEvent stopWithAttributes:nil]; - } + if(updateCircle) { /* UPDATE FULLPEERINFO VIEWS */ require_quiet(SOSFullPeerInfoUpdateToThisPeer(fpi, pi, NULL), errOut); - if(doAnalytics) { - updatePeerInCircleEvent = [parent newSubTaskForEvent:@"updatePeerInCircleEvent"]; - } + require_quiet([self modifyCircle:account.circle_transport err:NULL action:^(SOSCircleRef circle_to_change) { secnotice("circleChange", "Calling SOSCircleUpdatePeerInfo for views or peerInfo change"); bool updated= SOSCircleUpdatePeerInfo(circle_to_change, self.peerInfo); return updated; }], errOut); - if(doAnalytics) { - [updatePeerInCircleEvent stopWithAttributes:nil]; - } // Make sure we update the engine account.circle_rings_retirements_need_attention = true; } errOut: - if(doAnalytics) { - [updatePeerInCircleEvent stopWithAttributes:nil]; - } CFReleaseNull(enabledViews); CFReleaseNull(disabledViews); CFReleaseNull(pi); @@ -564,7 +538,7 @@ static size_t der_sizeof_data_optional(CFDataRef data) require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account.accountKeyIsTrusted, &failure)), fail); require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account.accountKey, &failure)), fail); require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account.previousAccountKey, &failure)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null((__bridge CFDataRef)account.accountKeyDerivationParamters, &failure)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null((__bridge CFDataRef)account.accountKeyDerivationParameters, &failure)), fail); require_quiet(accumulate_size(&sequence_size, SOSPeerInfoSetGetDEREncodedArraySize((__bridge CFSetRef)self.retirees, &failure)), fail); (void)accumulate_size(&sequence_size, der_sizeof_data_optional((__bridge CFDataRef)(account.backup_key))); require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary((__bridge CFDictionaryRef)(self.expansion), &failure)), fail); @@ -605,7 +579,7 @@ static uint8_t* der_encode_data_optional(CFDataRef data, CFErrorRef *error, ccder_encode_bool(account.accountKeyIsTrusted, der, der_encode_public_bytes(account.accountKey, &failure, der, der_encode_public_bytes(account.previousAccountKey, &failure, der, - der_encode_data_or_null((__bridge CFDataRef)(account.accountKeyDerivationParamters), &failure, der, + der_encode_data_or_null((__bridge CFDataRef)(account.accountKeyDerivationParameters), &failure, der, SOSPeerInfoSetEncodeToArrayDER((__bridge CFSetRef)(self.retirees), &failure, der, der_encode_data_optional((__bridge CFDataRef)account.backup_key, &failure, der, der_encode_dictionary((__bridge CFDictionaryRef)(self.expansion), &failure, der, @@ -717,6 +691,11 @@ static uint8_t* der_encode_data_optional(CFDataRef data, CFErrorRef *error, -(SOSEngineRef) getDataSourceEngine:(SOSDataSourceFactoryRef)factory { + // This is at least a piece of SecItemDataSourceFactoryCopyDataSource; looks like UaF + if(!self.trustedCircle) { + secnotice("engine", "Tried to set dataSourceEngine with no circle"); + return NULL; + } return SOSDataSourceFactoryGetEngineForDataSourceName(factory, SOSCircleGetName(self.trustedCircle), NULL); } diff --git a/keychain/SecureObjectSync/SOSAccountUpdate.m b/keychain/SecureObjectSync/SOSAccountUpdate.m index f24e6713..f4098276 100644 --- a/keychain/SecureObjectSync/SOSAccountUpdate.m +++ b/keychain/SecureObjectSync/SOSAccountUpdate.m @@ -181,7 +181,10 @@ void SOSAccountNotifyEngines(SOSAccount* account) // We add V0 views to everyone if we see a V0 peer, or a peer with the view explicity enabled // V2 peers shouldn't be explicity enabling the uber V0 view, though the seeds did. __block bool addV0Views = SOSAccountSyncingV0(account); - + + bool selfSupportCKKSForAll = SOSPeerInfoSupportsCKKSForAll(myPi); + secnotice("engine-notify", "Self peer(%@) %@ CKKS For All", myPi_id, selfSupportCKKSForAll ? @"supports" : @"doesn't support"); + syncing_peer_metas = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); zombie_peer_metas = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); SOSAccountForEachCirclePeerExceptMe(account, ^(SOSPeerInfoRef peer) { @@ -195,6 +198,12 @@ void SOSAccountNotifyEngines(SOSAccount* account) if(addV0Views) { CFSetAddValue(views, kSOSViewKeychainV0); } + + // If this peer supports CKKS4All, let's sync zero views to it. + if(selfSupportCKKSForAll && SOSPeerInfoSupportsCKKSForAll(peer)) { + secnotice("engine-notify", "Peer %@ supports CKKS For All; ignoring in SOS syncing", SOSPeerInfoGetPeerID(peer)); + CFSetRemoveAllValues(views); + } CFStringSetPerformWithDescription(views, ^(CFStringRef viewsDescription) { secnotice("engine-notify", "Meta: %@: %@", SOSPeerInfoGetPeerID(peer), viewsDescription); @@ -347,6 +356,12 @@ bool SOSAccountHandleCircleMessage(SOSAccount* account, CFStringRef circleName, CFDataRef encodedCircleMessage, CFErrorRef *error) { bool success = false; CFErrorRef localError = NULL; + + if(account && account.accountIsChanging) { + secnotice("circleOps", "SOSAccountHandleCircleMessage called before signing in to new account"); + return true; // we want to drop circle notifications when account is changing + } + SOSCircleRef circle = SOSAccountCreateCircleFrom(circleName, encodedCircleMessage, &localError); if (circle) { success = [account.trust updateCircleFromRemote:account.circle_transport newCircle:circle err:&localError]; @@ -374,14 +389,20 @@ bool SOSAccountHandleCircleMessage(SOSAccount* account, } bool SOSAccountHandleParametersChange(SOSAccount* account, CFDataRef parameters, CFErrorRef *error){ + if(account && account.accountIsChanging) { + secnotice("circleOps", "SOSAccountHandleParametersChange called before signing in to new account"); + return true; // we want to drop parm notifications when account is changing + } SecKeyRef newKey = NULL; - CFDataRef newParameters = NULL; + CFDataRef pbkdfParams = NULL; bool success = false; - if(SOSAccountRetrieveCloudParameters(account, &newKey, parameters, &newParameters, error)) { - debugDumpUserParameters(CFSTR("SOSAccountHandleParametersChange got new user key parameters:"), parameters); - secnotice("circleOps", "SOSAccountHandleParametersChange got new public key: %@", newKey); + if(SOSAccountRetrieveCloudParameters(account, &newKey, parameters, &pbkdfParams, error)) { + debugDumpUserParameters(CFSTR("SOSAccountHandleParametersChange got new user key parameters:"), pbkdfParams); + CFStringRef keyid = SOSCopyIDOfKeyWithLength(newKey, 8, NULL); + secnotice("circleOps", "SOSAccountHandleParametersChange got new public key: %@", keyid); + CFReleaseNull(keyid); if (CFEqualSafe(account.accountKey, newKey)) { secnotice("circleOps", "Got same public key sent our way. Ignoring."); @@ -392,7 +413,7 @@ bool SOSAccountHandleParametersChange(SOSAccount* account, CFDataRef parameters, } else { SOSAccountSetUnTrustedUserPublicKey(account, newKey); CFReleaseNull(newKey); - SOSAccountSetParameters(account, newParameters); + SOSAccountSetParameters(account, pbkdfParams); if(SOSAccountRetryUserCredentials(account)) { secnotice("circleOps", "Successfully used cached password with new parameters"); @@ -410,7 +431,7 @@ bool SOSAccountHandleParametersChange(SOSAccount* account, CFDataRef parameters, } CFReleaseNull(newKey); - CFReleaseNull(newParameters); + CFReleaseNull(pbkdfParams); return success; } diff --git a/keychain/SecureObjectSync/SOSAccountViewSync.m b/keychain/SecureObjectSync/SOSAccountViewSync.m index f619a750..c592b0bd 100644 --- a/keychain/SecureObjectSync/SOSAccountViewSync.m +++ b/keychain/SecureObjectSync/SOSAccountViewSync.m @@ -185,7 +185,7 @@ static bool SOSAccountResolvePendingViewSets(SOSAccount* account, CFErrorRef *er } CFReleaseNull(defaultOn); - bool status = [account.trust updateViewSetsWithAnalytics:account enabled:newPending disabled:pendingDisabled parentEvent: NULL]; + bool status = [account.trust updateViewSets:account enabled:newPending disabled:pendingDisabled]; CFReleaseNull(newPending); if(status){ diff --git a/keychain/SecureObjectSync/SOSAuthKitHelpers.m b/keychain/SecureObjectSync/SOSAuthKitHelpers.m index 03ea585d..36ca8e09 100644 --- a/keychain/SecureObjectSync/SOSAuthKitHelpers.m +++ b/keychain/SecureObjectSync/SOSAuthKitHelpers.m @@ -30,7 +30,6 @@ SOFT_LINK_CLASS(AuthKit, AKAccountManager); SOFT_LINK_CLASS(AuthKit, AKAnisetteProvisioningController); SOFT_LINK_CLASS(AuthKit, AKAppleIDAuthenticationController); SOFT_LINK_CLASS(AuthKit, AKDeviceListRequestContext); -SOFT_LINK_CLASS(Accounts, Accounts); SOFT_LINK_CLASS(Accounts, ACAccountStore); SOFT_LINK_CONSTANT(AuthKit, AKServiceNameiCloud, const NSString *); #pragma clang diagnostic pop @@ -189,29 +188,27 @@ static ACAccount *GetPrimaryAccount(void) { -(id) initWithActiveMIDS: (NSSet *) theMidList { - self = [super init]; - if(!self){ - return nil; - } - NSMutableSet *MmachineIDs = [[NSMutableSet alloc] init]; - NSMutableSet *MserialNumbers = [[NSMutableSet alloc] init]; - _machineIDs = [[NSSet alloc] init]; - _serialNumbers = [[NSSet alloc] init]; + if ((self = [super init])) { + NSMutableSet *MmachineIDs = [[NSMutableSet alloc] init]; + NSMutableSet *MserialNumbers = [[NSMutableSet alloc] init]; + _machineIDs = [[NSSet alloc] init]; + _serialNumbers = [[NSSet alloc] init]; - if(!theMidList) return nil; - _midList = theMidList; + if(!theMidList) return nil; + _midList = theMidList; + + for(SOSTrustedDeviceAttributes *dev in _midList) { + if(dev.machineID) { + [MmachineIDs addObject:dev.machineID]; + } + if(dev.serialNumber) { + [MserialNumbers addObject:dev.serialNumber]; + } - for(SOSTrustedDeviceAttributes *dev in _midList) { - if(dev.machineID) { - [MmachineIDs addObject:dev.machineID]; } - if(dev.serialNumber) { - [MserialNumbers addObject:dev.serialNumber]; - } - + _machineIDs = MmachineIDs; + _serialNumbers = MserialNumbers; } - _machineIDs = MmachineIDs; - _serialNumbers = MserialNumbers; return self; } diff --git a/keychain/SecureObjectSync/SOSBackupInformation.m b/keychain/SecureObjectSync/SOSBackupInformation.m deleted file mode 100644 index 8b9b9177..00000000 --- a/keychain/SecureObjectSync/SOSBackupInformation.m +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -// -// SOSBackupInformation.c -// Security -// - -#include "SOSBackupInformation.h" -#include "SOSAccountPriv.h" -#include -#include - -const CFStringRef kSOSBkpInfoStatus = CFSTR("BkpInfoStatus"); -const CFStringRef kSOSBkpInfoBSKB = CFSTR("BkpInfoBSKB"); -const CFStringRef kSOSBkpInfoRKBG = CFSTR("BkpInfoRKBG"); - -CFDictionaryRef SOSBackupInformation(SOSAccountTransaction* txn, CFErrorRef *error) { - CFNumberRef status = NULL; - int ibkpInfoStatus; - __block bool havebskbcontent = false; - SOSAccount *a = txn.account; - - CFMutableDictionaryRef retval = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - require_action_quiet(txn && a, errOut, ibkpInfoStatus = noTxnorAcct); - require_action_quiet(retval, errOut, ibkpInfoStatus = noAlloc); - require_action_quiet(txn, errOut, ibkpInfoStatus = noTxnorAcct); - - require_action_quiet(a.accountKey && a.accountKeyIsTrusted, errOut, ibkpInfoStatus = noTrustedPubKey); - CFMutableDictionaryRef bskbders = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - SOSAccountForEachRing(a, ^SOSRingRef(CFStringRef name, SOSRingRef ring) { - if(SOSRingGetType(ring) == kSOSRingBackup) { - CFDataRef bskbder = SOSRingGetPayload(ring, NULL); - if(bskbder) CFDictionaryAddValue(bskbders, name, bskbder); - havebskbcontent = true; - } else if(SOSRingGetType(ring) == kSOSRingRecovery) { - CFDataRef rkbgder = SOSRingGetPayload(ring, NULL); - if(rkbgder) CFDictionaryAddValue(retval, kSOSBkpInfoRKBG, rkbgder); - } - return NULL; // we're reporting - never changing the ring - }); - if(havebskbcontent) { - ibkpInfoStatus = noError; - CFDictionaryAddValue(retval, kSOSBkpInfoBSKB, bskbders); - } else { - ibkpInfoStatus = noBSKBs; - } - CFReleaseNull(bskbders); - -errOut: - status = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ibkpInfoStatus); - CFDictionaryAddValue(retval, kSOSBkpInfoStatus, status); - CFReleaseNull(status); - return retval; -} diff --git a/keychain/SecureObjectSync/SOSBackupSliceKeyBag.m b/keychain/SecureObjectSync/SOSBackupSliceKeyBag.m index f41ad4b6..61c7dbee 100644 --- a/keychain/SecureObjectSync/SOSBackupSliceKeyBag.m +++ b/keychain/SecureObjectSync/SOSBackupSliceKeyBag.m @@ -49,7 +49,6 @@ #include #include "SOSKeyedPubKeyIdentifier.h" #include "keychain/SecureObjectSync/SOSInternal.h" -#include "SecADWrapper.h" #include "SecCFAllocator.h" CFStringRef bskbRkbgPrefix = CFSTR("RK"); @@ -131,10 +130,10 @@ const uint8_t* der_decode_BackupSliceKeyBag(CFAllocatorRef allocator, der = ccder_decode_sequence_tl(&sequence_end, der, der_end); require_quiet(sequence_end == der_end, fail); - der = der_decode_data(kCFAllocatorDefault, kCFPropertyListImmutable, &vb->aks_bag, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &vb->aks_bag, error, der, sequence_end); vb->peers = SOSPeerInfoSetCreateFromArrayDER(kCFAllocatorDefault, &kSOSPeerSetCallbacks, error, &der, der_end); - der = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &vb->wrapped_keys, error, der, sequence_end); + der = der_decode_dictionary(kCFAllocatorDefault, &vb->wrapped_keys, error, der, sequence_end); require_quiet(SecRequirementError(der == der_end, error, CFSTR("Extra space in sequence")), fail); @@ -489,17 +488,17 @@ bool SOSBKSBPeerBackupKeyIsInKeyBag(SOSBackupSliceKeyBagRef backupSliceKeyBag, S return result; } -// returns true if all peers in (peers) and only those peers have matching backupKeys in the BSKB bool SOSBSKBAllPeersBackupKeysAreInKeyBag(SOSBackupSliceKeyBagRef backupSliceKeyBag, CFSetRef peers) { - __block bool result = false; + // earlier we had to accept BSKBs listing peers without backup keys for compatibility. For that reason + // this routine will iterate over the peers given and only disqualify the BSKB if it doesn't include the backup key of a peer with one. + __block bool result = true; if(backupSliceKeyBag && peers) { - result = (SOSBSKBCountPeers(backupSliceKeyBag) == CFSetGetCount(peers)); - if(result) { - CFSetForEach(peers, ^(const void *value) { - SOSPeerInfoRef pi = asSOSPeerInfo(value); - result &= pi && SOSBKSBPeerBackupKeyIsInKeyBag(backupSliceKeyBag, pi); - }); - } + CFSetForEach(peers, ^(const void *value) { + SOSPeerInfoRef pi = asSOSPeerInfo(value); + if(pi && SOSPeerInfoHasBackupKey(pi)) { + result &= SOSBKSBPeerBackupKeyIsInKeyBag(backupSliceKeyBag, pi); + } + }); } return result; } @@ -761,6 +760,7 @@ bool SOSBSKBHasThisRecoveryKey(SOSBackupSliceKeyBagRef bskb, CFDataRef backupKey CFReleaseNull(id); return result; } else { - return CFDictionaryGetCount(bskb->wrapped_keys) == SOSBSKBCountPeers(bskb); + // let's not judge ripping out other recovery keys + return true; } } diff --git a/keychain/SecureObjectSync/SOSChangeTracker.h b/keychain/SecureObjectSync/SOSChangeTracker.h index 0b68d4bc..4731c9a8 100644 --- a/keychain/SecureObjectSync/SOSChangeTracker.h +++ b/keychain/SecureObjectSync/SOSChangeTracker.h @@ -31,6 +31,8 @@ #include "keychain/SecureObjectSync/SOSDataSource.h" +#include "utilities/simulatecrash_assert.h" + __BEGIN_DECLS enum { diff --git a/keychain/SecureObjectSync/SOSCircle.c b/keychain/SecureObjectSync/SOSCircle.c index 68d47e37..c697e0f0 100644 --- a/keychain/SecureObjectSync/SOSCircle.c +++ b/keychain/SecureObjectSync/SOSCircle.c @@ -59,7 +59,7 @@ #include #include -#include +#include CFGiblisWithCompareFor(SOSCircle); @@ -581,11 +581,6 @@ static inline bool SOSCircleIsDegenerateReset(SOSCircleRef deGenCircle){ return SOSCircleHasDegenerateGeneration(deGenCircle) && SOSCircleIsEmpty(deGenCircle); } - -__unused static inline bool SOSCircleIsResignOffering(SOSCircleRef circle, SecKeyRef pubkey) { - return SOSCircleCountActiveValidPeers(circle, pubkey) == 1; -} - static inline SOSConcordanceStatus GetSignersStatus(SOSCircleRef signers_circle, SOSCircleRef status_circle, SecKeyRef user_pubKey, SOSPeerInfoRef exclude, CFErrorRef *error) { CFStringRef excluded_id = exclude ? SOSPeerInfoGetPeerID(exclude) : NULL; @@ -831,8 +826,9 @@ static CFStringRef SOSCircleCopyFormatDescription(CFTypeRef aObj, CFDictionaryRe } CFStringRef SOSCircleGetName(SOSCircleRef circle) { - assert(circle); - assert(circle->name); + if(!circle || !circle->name) { + return NULL; + } return circle->name; } @@ -1324,7 +1320,9 @@ void SOSCircleForEachApplicant(SOSCircleRef circle, void (^action)(SOSPeerInfoRe bool SOSCircleHasPeerWithID(SOSCircleRef circle, CFStringRef peerid, CFErrorRef *error) { SOSCircleAssertStable(circle); - + if(!peerid) { + return false; + } SOSPeerInfoRef found = asSOSPeerInfo(CFSetGetValue(circle->peers, peerid)); return found && !isHiddenPeer(found); } @@ -1499,7 +1497,11 @@ bool SOSCircleAcceptPeerFromHSA2(SOSCircleRef circle, SecKeyRef userKey, SOSGenC // Gen sign first, then add signature from our approver - remember gensign removes all existing sigs. res = SOSCircleGenerationSignWithGenCount(circle, userKey, fpi, gencount, error); if (!res) { - secnotice("circleOps", "Failed to regenerate circle with new gen count: %@", error ? *error : NULL); + CFStringRef newGenString = SOSGenerationCountCopyDescription(gencount); + CFStringRef currentGenString = SOSGenerationCountCopyDescription(SOSCircleGetGeneration(circle)); + secnotice("circleOps", "Failed to regenerate circle with new gen count: %@ current gencount: %@ error: %@", newGenString, currentGenString, error ? *error : NULL); + CFReleaseNull(newGenString); + CFReleaseNull(currentGenString); return res; } res = SOSCircleSetSignature(circle, pPubKey, signature, error); diff --git a/keychain/SecureObjectSync/SOSCircleDer.c b/keychain/SecureObjectSync/SOSCircleDer.c index b44e9287..f60ee4ce 100644 --- a/keychain/SecureObjectSync/SOSCircleDer.c +++ b/keychain/SecureObjectSync/SOSCircleDer.c @@ -28,24 +28,9 @@ #include #include #include -#include #include "SOSCircleDer.h" -static const uint8_t* der_decode_mutable_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability, - CFMutableDictionaryRef* dictionary, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - CFDictionaryRef theDict; - const uint8_t* result = der_decode_dictionary(allocator, mutability, &theDict, error, der, der_end); - - if (result != NULL) - *dictionary = (CFMutableDictionaryRef)theDict; - - return result; -} - - SOSCircleRef SOSCircleCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, const uint8_t** der_p, const uint8_t *der_end) { SOSCircleRef cir = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator); @@ -70,15 +55,17 @@ SOSCircleRef SOSCircleCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, require_action_quiet(version == kOnlyCompatibleVersion, fail, SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Bad Circle Version"), NULL, error)); - *der_p = der_decode_string(allocator, 0, &cir->name, error, *der_p, sequence_end); + *der_p = der_decode_string(allocator, &cir->name, error, *der_p, sequence_end); cir->generation = SOSGenCountCreateFromDER(kCFAllocatorDefault, error, der_p, sequence_end); cir->peers = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); cir->applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); cir->rejected_applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); - *der_p = der_decode_mutable_dictionary(allocator, kCFPropertyListMutableContainersAndLeaves, - &cir->signatures, error, *der_p, sequence_end); + CFDictionaryRef tmp = NULL; + *der_p = der_decode_dictionary(allocator, &tmp, error, *der_p, sequence_end); + cir->signatures = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, tmp); + CFReleaseNull(tmp); require_action_quiet(*der_p == sequence_end, fail, SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error)); @@ -192,7 +179,7 @@ const uint8_t* der_decode_data_or_null(CFAllocatorRef allocator, CFDataRef* data const uint8_t* der, const uint8_t* der_end) { CFTypeRef value = NULL; - der = der_decode_plist(allocator, 0, &value, error, der, der_end); + der = der_decode_plist(allocator, &value, error, der, der_end); if (value && CFGetTypeID(value) != CFDataGetTypeID()) { CFReleaseNull(value); } diff --git a/keychain/SecureObjectSync/SOSCirclePriv.h b/keychain/SecureObjectSync/SOSCirclePriv.h index 79852a34..21aa0947 100644 --- a/keychain/SecureObjectSync/SOSCirclePriv.h +++ b/keychain/SecureObjectSync/SOSCirclePriv.h @@ -13,6 +13,8 @@ #include #include "keychain/SecureObjectSync/SOSGenCount.h" +#include + enum { kOnlyCompatibleVersion = 1, // Sometime in the future this name will be improved to reflect history. kAlwaysIncompatibleVersion = UINT64_MAX, diff --git a/keychain/SecureObjectSync/SOSCloudCircle.h b/keychain/SecureObjectSync/SOSCloudCircle.h index 46bbae1e..4026c299 100644 --- a/keychain/SecureObjectSync/SOSCloudCircle.h +++ b/keychain/SecureObjectSync/SOSCloudCircle.h @@ -39,7 +39,6 @@ #include #include -#import __BEGIN_DECLS @@ -72,6 +71,7 @@ enum { typedef CF_OPTIONS(uint32_t, SOSInitialSyncFlags) { kSOSInitialSyncFlagTLKs = (1UL << 0), kSOSInitialSyncFlagiCloudIdentity = (1UL << 1), + kSOSInitialSyncFlagTLKsRequestOnly = (1UL << 2), // Note that this overrides the other two flags, as it's used for aborting the piggybacking session early and returning a very small number of TLKs }; @@ -126,7 +126,6 @@ bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CF */ bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); -bool SOSCCSetUserCredentialsAndDSIDWithAnalytics(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentevent, CFErrorRef *error); /*! @function SOSCCTryUserCredentials @@ -158,15 +157,6 @@ bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_passwor @return if we waited successfully */ bool SOSCCWaitForInitialSync(CFErrorRef* error); -bool SOSCCWaitForInitialSyncWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); - -/*! - @function SOSCCCopyYetToSyncViewsList - @abstract returns views not yet synced - @param error error to fill in if we have one - @return List of view names that we haven't synced yet. - */ -CFArrayRef SOSCCCopyYetToSyncViewsList(CFErrorRef* error); /*! @function SOSCCCanAuthenticate @@ -255,7 +245,6 @@ bool SOSCCIsContinuityUnlockSyncing(void); @discussion Requests to join the user's circle or all the pending circles (other than his) if there are multiple pending circles. */ bool SOSCCRequestToJoinCircle(CFErrorRef* error); -bool SOSCCRequestToJoinCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); /*! @@ -266,15 +255,6 @@ bool SOSCCRequestToJoinCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* er @discussion Uses the cloud identity to get in the circle if it can. If it cannot it falls back on simple application. */ bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error); -bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); - -/*! - @function SOSCCRequestEnsureFreshParameters - @abstract function to help debug problems with EnsureFreshParameters - @param error What went wrong if we tried to refresh parameters - @result true if we successfully retrieved fresh parameters. False if we failed. -*/ -bool SOSCCRequestEnsureFreshParameters(CFErrorRef* error); /*! @function SOSCCAccountSetToNew @@ -299,7 +279,6 @@ bool SOSCCResetToOffering(CFErrorRef* error); @result true if we posted the circle successfully. False if there was an error. */ bool SOSCCResetToEmpty(CFErrorRef* error); -bool SOSCCResetToEmptyWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); /*! @function SOSCCRemoveThisDeviceFromCircle @@ -310,7 +289,6 @@ bool SOSCCResetToEmptyWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); */ bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error); -bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); /*! @function SOSCCRemoveThisDeviceFromCircle @@ -322,14 +300,18 @@ bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFError that we don't have the user credentail (need to prompt for password) */ bool SOSCCRemovePeersFromCircle(CFArrayRef peerList, CFErrorRef* error); -bool SOSCCRemovePeersFromCircleWithAnalytics(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error); /*! - @function SOSCCRemoveThisDeviceFromCircle - @abstract Removes the current device from the circle. - @param error What went wrong trying to remove ourselves. - @result true if we posted the removal. False if there was an error. - @discussion This removes us from the circle. + @function SOSCCLoggedIntoAccount + @param error value set if there are xpc errors. + @abstract Notifies the account object that the device logged into an icloud account + */ +bool SOSCCLoggedIntoAccount(CFErrorRef* error); + +/*! + @function SOSCCLoggedOutOfAccount + @param error value set if there are xpc errors. + @abstract Removes the current device from the circle. Clears the account object */ bool SOSCCLoggedOutOfAccount(CFErrorRef* error); @@ -345,18 +327,6 @@ bool SOSCCLoggedOutOfAccount(CFErrorRef* error); */ bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error); -/*! - @function SOSCCSignedOut - @abstract Attempts to publish a retirement ticket for the current device. - @param immediate If we should remove the device immediately or to leave the circle with best effort. - @param error What went wrong trying to remove ourselves. - @result true if we posted the ticket. False if there was an error. - @discussion This attempts to post a retirement ticket that should - result in other devices removing this device from the circle. It does so - with a 5 second timeout or immediately. - */ -bool SOSCCSignedOut(bool immediate, CFErrorRef* error); - /*! @function SOSCCCopyApplicantPeerInfo @abstract Get the list of peers wishing admittance. @@ -490,14 +460,6 @@ enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error); bool SOSCCSetLastDepartureReason(enum DepartureReason reason, CFErrorRef *error); -/*! - @function SOSCCGetIncompatibilityInfo - @abstract Returns the information (string, hopefully URL) that will lead to an explanation of why you have an incompatible circle. - @param error What went wrong if we returned NULL. - */ -CFStringRef SOSCCCopyIncompatibilityInfo(CFErrorRef *error); - - /* Views @@ -614,7 +576,6 @@ SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode action, CFErrorR */ bool SOSCCViewSet(CFSetRef enabledviews, CFSetRef disabledviews); -bool SOSCCViewSetWithAnalytics(CFSetRef enabledviews, CFSetRef disabledviews, CFDataRef parentEvent); /* Security Attributes for PeerInfos @@ -653,34 +614,6 @@ CFDataRef SOSCopyDeviceBackupPublicKey(CFDataRef entropy, CFErrorRef *error); */ bool SOSCCRegisterSingleRecoverySecret(CFDataRef aks_bag, bool forV0Only, CFErrorRef *error); - -/*! - @function SOSCCIsThisDeviceLastBackup - @param error Why this query can't be accepted. - @result true if this is the last backup device, false otherwise. - */ - -bool SOSCCIsThisDeviceLastBackup(CFErrorRef *error); - -/*! - @function SOSCCSetEscrowRecord - @param escrow_label Account label - @param tries Number of attempts - @param error What went wrong trying to set the escrow label - @result true if we saved the escrow record, false if we had an error - @discussion persist escrow records in the account object or the peer info - */ -bool SOSCCSetEscrowRecord(CFStringRef escrow_label, uint64_t tries, CFErrorRef *error); - -/*! - @function SOSCCCopyEscrowRecord - @param error What went wrong trying to set the escrow label - @result dictionary of the escrow record, false if we had an error, dictionary will be of format: [account label: ], dictionary will contain (ex): "Burned Recovery Attempt Attestation Date" = "[2015-08-19 15:21]"; - "Burned Recovery Attempt Count" = 8; - @discussion for debugging - retrieve the escrow record - */ -CFDictionaryRef SOSCCCopyEscrowRecord(CFErrorRef *error); - /*! @function SOSCCCopyApplication @param error What went wrong getting the applicant peerInfo. diff --git a/keychain/SecureObjectSync/SOSCloudCircle.m b/keychain/SecureObjectSync/SOSCloudCircle.m index d1af2e1a..6cea17ce 100644 --- a/keychain/SecureObjectSync/SOSCloudCircle.m +++ b/keychain/SecureObjectSync/SOSCloudCircle.m @@ -84,8 +84,18 @@ static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *ke return value && (xpc_get_type(value) == type); } +static void setSOSDisabledError(CFErrorRef *error) { + SecCFCreateErrorWithFormat(0, kSOSErrorDomain, NULL, error, NULL, CFSTR("SOS Disabled for this platform")); +} + SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSOSCCError; + } + SOSCCStatus retval = SOSGetCachedCircleStatus(error); if(retval != kSOSNoCachedValue) { secdebug("circleOps", "Retrieved cached circle value %d", retval); @@ -97,6 +107,12 @@ SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error) SOSCCStatus SOSCCThisDeviceIsInCircleNonCached(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSOSCCError; + } + sec_trace_enter_api(NULL); sec_trace_return_api(SOSCCStatus, ^{ SOSCCStatus result = kSOSCCError; @@ -128,79 +144,6 @@ SOSCCStatus SOSCCThisDeviceIsInCircleNonCached(CFErrorRef *error) }, CFSTR("SOSCCStatus=%d")) } -static bool sfsigninanalytics_bool_error_request(enum SecXPCOperation op, CFDataRef parentEvent, CFErrorRef* error) -{ - __block bool result = false; - - secdebug("sosops","enter - operation: %d", op); - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - return SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error); - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - return result; -} - -static bool cfstring_to_error_request(enum SecXPCOperation op, CFStringRef string, CFErrorRef* error) -{ - __block bool result = false; - - secdebug("sosops","enter - operation: %d", op); - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - xpc_object_t xString = _CFXPCCreateXPCObjectFromCFObject(string); - bool success = false; - if (xString){ - xpc_dictionary_set_value(message, kSecXPCKeyString, xString); - success = true; - xString = nil; - } - return success; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - return result; -} - -static SOSRingStatus cfstring_to_uint64_request(enum SecXPCOperation op, CFStringRef string, CFErrorRef* error) -{ - __block bool result = false; - - secdebug("sosops","enter - operation: %d", op); - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - xpc_object_t xString = _CFXPCCreateXPCObjectFromCFObject(string); - bool success = false; - if (xString){ - xpc_dictionary_set_value(message, kSecXPCKeyString, xString); - success = true; - xString = nil; - } - return success; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_int64(response, kSecXPCKeyResult); - return result; - }); - return result; -} - -static CFStringRef simple_cfstring_error_request(enum SecXPCOperation op, CFErrorRef* error) -{ - __block CFStringRef result = NULL; - - secdebug("sosops","enter - operation: %d", op); - securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - const char *c_string = xpc_dictionary_get_string(response, kSecXPCKeyResult); - - if (c_string) { - result = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)c_string, strlen(c_string), kCFStringEncodingUTF8, false); - } - - return c_string != NULL; - }); - return result; -} - static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error) { __block bool result = false; @@ -270,33 +213,6 @@ static CFSetRef cfset_cfset_to_cfset_error_request(enum SecXPCOperation op, CFSe return result; } - -static bool escrow_to_bool_error_request(enum SecXPCOperation op, CFStringRef escrow_label, uint64_t tries, CFErrorRef* error) -{ - __block bool result = false; - - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - - bool success = false; - xpc_object_t xEscrowLabel = _CFXPCCreateXPCObjectFromCFObject(escrow_label); - if (xEscrowLabel){ - xpc_dictionary_set_value(message, kSecXPCKeyEscrowLabel, xEscrowLabel); - success = true; - xEscrowLabel = nil; - } - if(tries){ - xpc_dictionary_set_int64(message, kSecXPCKeyTriesLabel, tries); - success = true; - } - - return success; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - return result; -} - static CF_RETURNS_RETAINED CFArrayRef simple_array_error_request(enum SecXPCOperation op, CFErrorRef* error) { __block CFArrayRef result = NULL; @@ -323,7 +239,7 @@ static CF_RETURNS_RETAINED CFArrayRef der_array_error_request(enum SecXPCOperati if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) { size_t length = 0; const uint8_t* bytes = xpc_dictionary_get_data(response, kSecXPCKeyResult, &length); - der_decode_plist(kCFAllocatorDefault, 0, (CFPropertyListRef*) &result, error, bytes, bytes + length); + der_decode_plist(kCFAllocatorDefault, (CFPropertyListRef*) &result, error, bytes, bytes + length); return result != NULL; })) { @@ -335,28 +251,6 @@ static CF_RETURNS_RETAINED CFArrayRef der_array_error_request(enum SecXPCOperati return result; } -static CFDictionaryRef strings_to_dictionary_error_request(enum SecXPCOperation op, CFErrorRef* error) -{ - __block CFDictionaryRef result = NULL; - - secdebug("sosops","enter - operation: %d", op); - - if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) { - xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult); - if(temp_result) - result = _CFXPCCreateCFObjectFromXPCObject(temp_result); - return result != NULL; - })){ - - if (!isDictionary(result)) { - SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected dictionary, got: %@"), result); - CFReleaseNull(result); - } - - } - return result; -} - static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error) { __block int result = 0; @@ -555,30 +449,12 @@ static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef return result; } -static bool info_array_data_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFDataRef parentEvent, CFErrorRef* error) -{ - __block bool result = false; - - secdebug("sosops", "enter - operation: %d", op); - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error); - xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error); - if (encoded_peers) - xpc_dictionary_set_value(message, kSecXPCKeyPeerInfoArray, encoded_peers); - return encoded_peers != NULL; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - return result; -} - static bool uint64_t_to_bool_error_request(enum SecXPCOperation op, uint64_t number, CFErrorRef* error) { __block bool result = false; - + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number); return true; @@ -586,46 +462,6 @@ static bool uint64_t_to_bool_error_request(enum SecXPCOperation op, result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); return result; }); - - return result; -} - -static bool cfstring_and_cfdata_to_cfdata_cfdata_error_request(enum SecXPCOperation op, CFStringRef viewName, CFDataRef input, CFDataRef* data, CFDataRef* data2, CFErrorRef* error) { - secdebug("sosops", "enter - operation: %d", op); - __block bool result = false; - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - xpc_object_t xviewname = _CFXPCCreateXPCObjectFromCFObject(viewName); - xpc_object_t xinput = _CFXPCCreateXPCObjectFromCFObject(input); - bool success = false; - if (xviewname && xinput){ - xpc_dictionary_set_value(message, kSecXPCKeyViewName, xviewname); - xpc_dictionary_set_value(message, kSecXPCData, xinput); - success = true; - xviewname = nil; - xinput = nil; - } - return success; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - - xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCData); - if ((NULL != temp_result) && data) { - *data = _CFXPCCreateCFObjectFromXPCObject(temp_result); - } - temp_result = xpc_dictionary_get_value(response, kSecXPCKeyKeybag); - if ((NULL != temp_result) && data2) { - *data2 = _CFXPCCreateCFObjectFromXPCObject(temp_result); - } - - return result; - }); - - if (data &&!isData(*data)) { - SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), *data); - } - if (data2 &&!isData(*data2)) { - SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), *data2); - } return result; } @@ -682,6 +518,12 @@ static CFDataRef cfdata_error_request_returns_cfdata(enum SecXPCOperation op, CF bool SOSCCRequestToJoinCircle(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_RequestToJoinCircle, error); @@ -690,18 +532,14 @@ bool SOSCCRequestToJoinCircle(CFErrorRef* error) }, NULL) } -bool SOSCCRequestToJoinCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RequestToJoinCircleWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinWithAnalytics, parentEvent, error); - }, NULL) -} - bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_RequestToJoinCircleAfterRestore, error); @@ -710,18 +548,14 @@ bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error) }, NULL) } -bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RequestToJoinCircleAfterRestoreWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinAfterRestoreWithAnalytics, parentEvent, error); - }, NULL) -} - bool SOSCCAccountHasPublicKey(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_AccountHasPublicKey, error); @@ -731,28 +565,14 @@ bool SOSCCAccountHasPublicKey(CFErrorRef *error) } -bool SOSCCAccountIsNew(CFErrorRef *error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_AccountIsNew, error); - - return simple_bool_error_request(kSecXPCOpAccountIsNew, error); - }, NULL) -} - -bool SOSCCWaitForInitialSyncWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_WaitForInitialSyncWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpWaitForInitialSyncWithAnalytics, parentEvent, error); - }, NULL) -} - bool SOSCCWaitForInitialSync(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_WaitForInitialSync, error); @@ -761,77 +581,14 @@ bool SOSCCWaitForInitialSync(CFErrorRef* error) }, NULL) } -CFArrayRef SOSCCCopyYetToSyncViewsList(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(CFArrayRef, ^{ - do_if_registered(soscc_CopyYetToSyncViewsList, error); - - return simple_array_error_request(kSecXPCOpCopyYetToSyncViews, error); - }, NULL) -} - -bool SOSCCRequestEnsureFreshParameters(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RequestEnsureFreshParameters, error); - - return simple_bool_error_request(kSecXPCOpRequestEnsureFreshParameters, error); - }, NULL) -} - -CFStringRef SOSCCGetAllTheRings(CFErrorRef *error){ - sec_trace_enter_api(NULL); - sec_trace_return_api(CFStringRef, ^{ - do_if_registered(soscc_GetAllTheRings, error); - - - return simple_cfstring_error_request(kSecXPCOpGetAllTheRings, error); - }, NULL) -} -bool SOSCCApplyToARing(CFStringRef ringName, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_ApplyToARing, ringName, error); - - return cfstring_to_error_request(kSecXPCOpApplyToARing, ringName, error); - }, NULL) -} - -bool SOSCCWithdrawlFromARing(CFStringRef ringName, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_WithdrawlFromARing, ringName, error); - - return cfstring_to_error_request(kSecXPCOpWithdrawlFromARing, ringName, error); - }, NULL) -} - -SOSRingStatus SOSCCRingStatus(CFStringRef ringName, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(SOSRingStatus, ^{ - do_if_registered(soscc_RingStatus, ringName, error); - - return cfstring_to_uint64_request(kSecXPCOpRingStatus, ringName, error); - }, CFSTR("SOSCCStatus=%d")) -} - -bool SOSCCEnableRing(CFStringRef ringName, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_EnableRing, ringName, error); - - return cfstring_to_error_request(kSecXPCOpEnableRing, ringName, error); - }, NULL) -} - bool SOSCCAccountSetToNew(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secwarning("SOSCCAccountSetToNew called"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -842,6 +599,12 @@ bool SOSCCAccountSetToNew(CFErrorRef *error) bool SOSCCResetToOffering(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secwarning("SOSCCResetToOffering called"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -853,6 +616,12 @@ bool SOSCCResetToOffering(CFErrorRef* error) bool SOSCCResetToEmpty(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secwarning("SOSCCResetToEmpty called"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -862,18 +631,14 @@ bool SOSCCResetToEmpty(CFErrorRef* error) }, NULL) } -bool SOSCCResetToEmptyWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ - secwarning("SOSCCResetToEmptyWithAnalytics called"); - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_ResetToEmptyWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpResetToEmptyWithAnalytics, parentEvent, error); - }, NULL) -} bool SOSCCRemovePeersFromCircle(CFArrayRef peers, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_RemovePeersFromCircle, peers, error); @@ -882,28 +647,14 @@ bool SOSCCRemovePeersFromCircle(CFArrayRef peers, CFErrorRef* error) }, NULL) } -bool SOSCCRemovePeersFromCircleWithAnalytics(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RemovePeersFromCircleWithAnalytics, peers, parentEvent, error); - - return info_array_data_to_bool_error_request(kSecXPCOpRemovePeersFromCircleWithAnalytics, peers, parentEvent, error); - }, NULL) -} - -bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RemoveThisDeviceFromCircleWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics, parentEvent, error); - }, NULL) -} - bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_RemoveThisDeviceFromCircle, error); @@ -912,8 +663,23 @@ bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error) }, NULL) } +bool SOSCCLoggedIntoAccount(CFErrorRef* error) { + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_LoggedIntoAccount, error); + + return simple_bool_error_request(kSecXPCOpLoggedIntoAccount, error); + }, NULL) +} + bool SOSCCLoggedOutOfAccount(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_LoggedOutOfAccount, error); @@ -924,27 +690,28 @@ bool SOSCCLoggedOutOfAccount(CFErrorRef* error) bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_BailFromCircle, limit_in_seconds, error); - + return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error); }, NULL) } -bool SOSCCSignedOut(bool immediate, CFErrorRef* error) -{ - uint64_t limit = strtoul(optarg, NULL, 10); - - if(immediate) - return SOSCCRemoveThisDeviceFromCircle(error); - else - return SOSCCBailFromCircle_BestEffort(limit, error); - -} - CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyPeerInfo, error); @@ -955,6 +722,12 @@ CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyConcurringPeerInfo, error); @@ -965,6 +738,12 @@ CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyGenerationPeerInfo, error); @@ -975,6 +754,12 @@ CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyApplicantPeerInfo, error); @@ -984,6 +769,12 @@ CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error) } bool SOSCCValidateUserPublic(CFErrorRef* error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_api(bool, ^{ do_if_registered(soscc_ValidateUserPublic, error); @@ -994,6 +785,12 @@ bool SOSCCValidateUserPublic(CFErrorRef* error){ CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyValidPeerPeerInfo, error); @@ -1004,6 +801,12 @@ CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyNotValidPeerPeerInfo, error); @@ -1014,7 +817,13 @@ CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error) { - sec_trace_enter_api(NULL); + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyRetirementPeerInfo, error); @@ -1024,6 +833,12 @@ CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyViewUnawarePeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyViewUnawarePeerInfo, error); @@ -1032,45 +847,14 @@ CFArrayRef SOSCCCopyViewUnawarePeerInfo(CFErrorRef* error) }, CFSTR("return=%@")); } -CFDataRef SOSCCCopyAccountState(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(CFDataRef, ^{ - do_if_registered(soscc_CopyAccountState, error); - - return data_to_error_request(kSecXPCOpCopyAccountData, error); - }, CFSTR("return=%@")); -} - -bool SOSCCDeleteAccountState(CFErrorRef *error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(bool, ^{ - do_if_registered(soscc_DeleteAccountState, error); - return simple_bool_error_request(kSecXPCOpDeleteAccountData, error); - }, NULL); -} -CFDataRef SOSCCCopyEngineData(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(CFDataRef, ^{ - do_if_registered(soscc_CopyEngineData, error); - - return data_to_error_request(kSecXPCOpCopyEngineData, error); - }, CFSTR("return=%@")); -} - -bool SOSCCDeleteEngineState(CFErrorRef *error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(bool, ^{ - do_if_registered(soscc_DeleteEngineState, error); - return simple_bool_error_request(kSecXPCOpDeleteEngineData, error); - }, NULL); -} - SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(SOSPeerInfoRef, ^{ do_if_registered(soscc_CopyMyPeerInfo, error); @@ -1081,6 +865,12 @@ SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error) static CFArrayRef SOSCCCopyEngineState(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyEngineState, error); @@ -1096,6 +886,11 @@ CFStringRef kSOSCCEngineStateCoderKey = CFSTR("CoderDump"); CFStringRef kSOSCCEngineStateManifestHashKey = CFSTR("ManifestHash"); void SOSCCForEachEngineStateAsStringFromArray(CFArrayRef states, void (^block)(CFStringRef oneStateString)) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return; + } + CFArrayForEach(states, ^(const void *value) { CFDictionaryRef dict = asDictionary(value, NULL); @@ -1143,6 +938,12 @@ void SOSCCForEachEngineStateAsStringFromArray(CFArrayRef states, void (^block)(C } bool SOSCCForEachEngineStateAsString(CFErrorRef* error, void (^block)(CFStringRef oneStateString)) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + CFArrayRef states = SOSCCCopyEngineState(error); if (states == NULL) return false; @@ -1157,6 +958,12 @@ bool SOSCCForEachEngineStateAsString(CFErrorRef* error, void (^block)(CFStringRe bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_AcceptApplicants, applicants, error); @@ -1167,7 +974,13 @@ bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error) bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error) { - sec_trace_enter_api(CFSTR("applicants=%@"), applicants); + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + + sec_trace_enter_api(CFSTR("applicants=%@"), applicants); sec_trace_return_bool_api(^{ do_if_registered(soscc_RejectApplicants, applicants, error); @@ -1186,6 +999,12 @@ static CF_RETURNS_RETAINED SOSPeerInfoRef SOSSetNewPublicBackupKey(CFDataRef pub } SOSPeerInfoRef SOSCCCopyMyPeerWithNewDeviceRecoverySecret(CFDataRef secret, CFErrorRef *error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + secnotice("devRecovery", "Enter SOSCCCopyMyPeerWithNewDeviceRecoverySecret()"); CFDataRef publicKeyData = SOSCopyDeviceBackupPublicKey(secret, error); secnotice("devRecovery", "SOSCopyDeviceBackupPublicKey (%@)", publicKeyData); @@ -1196,6 +1015,12 @@ SOSPeerInfoRef SOSCCCopyMyPeerWithNewDeviceRecoverySecret(CFDataRef secret, CFEr } bool SOSCCRegisterSingleRecoverySecret(CFDataRef aks_bag, bool forV0Only, CFErrorRef *error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_RegisterSingleRecoverySecret, aks_bag, forV0Only, error); @@ -1205,7 +1030,13 @@ bool SOSCCRegisterSingleRecoverySecret(CFDataRef aks_bag, bool forV0Only, CFErro bool SOSCCRegisterRecoveryPublicKey(CFDataRef recovery_key, CFErrorRef *error){ - sec_trace_enter_api(NULL); + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ bool retval = false; do_if_registered(soscc_RegisterRecoveryPublicKey, recovery_key, error); @@ -1216,6 +1047,12 @@ bool SOSCCRegisterRecoveryPublicKey(CFDataRef recovery_key, CFErrorRef *error){ } CFDataRef SOSCCCopyRecoveryPublicKey(CFErrorRef *error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFDataRef, ^{ do_if_registered(soscc_CopyRecoveryPublicKey, error); @@ -1244,7 +1081,7 @@ static bool label_and_password_to_bool_error_request(enum SecXPCOperation op, static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperation op, CFStringRef user_label, CFDataRef user_password, - CFStringRef dsid, CFDataRef parentEvent, CFErrorRef* error) + CFStringRef dsid, CFErrorRef* error) { __block bool result = false; @@ -1256,9 +1093,6 @@ static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperati xpc_dictionary_set_string(message, kSecXPCKeyDSID, utr8StrDSID); }); xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password)); - if(parentEvent){ - SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error); - } return true; }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); @@ -1270,12 +1104,24 @@ static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperati bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) { - secnotice("circleOps", "SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials for %@\n", user_label); + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + + secnotice("circleOps", "SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials for %@\n", user_label); return SOSCCSetUserCredentials(user_label, user_password, error); } bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("circleOps", "SOSCCSetUserCredentials for %@\n", user_label); sec_trace_enter_api(CFSTR("user_label=%@"), user_label); sec_trace_return_bool_api(^{ @@ -1287,6 +1133,12 @@ bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CF bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("circleOps", "SOSCCSetUserCredentialsAndDSID for %@\n", user_label); sec_trace_enter_api(CFSTR("user_label=%@"), user_label); sec_trace_return_bool_api(^{ @@ -1301,30 +1153,7 @@ bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_passw if(account_dsid == NULL){ account_dsid = CFSTR(""); } - return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSID, user_label, user_password, account_dsid, nil, error); - out: - return result; - - }, NULL) -} - -bool SOSCCSetUserCredentialsAndDSIDWithAnalytics(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error) -{ - secnotice("circleOps", "SOSCCSetUserCredentialsAndDSIDWithAnalytics for %@\n", user_label); - sec_trace_enter_api(CFSTR("user_label=%@"), user_label); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_SetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, dsid, parentEvent, error); - - bool result = false; - __block CFStringRef account_dsid = dsid; - - require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil"))); - require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil"))); - - if(account_dsid == NULL){ - account_dsid = CFSTR(""); - } - return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, account_dsid, parentEvent, error); + return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSID, user_label, user_password, account_dsid, error); out: return result; @@ -1345,7 +1174,7 @@ static bool SOSCCTryUserCredentialsAndDSID_internal(CFStringRef user_label, CFDa account_dsid = CFSTR(""); } - return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, account_dsid, nil, error); + return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, account_dsid, error); out: return result; @@ -1355,6 +1184,12 @@ static bool SOSCCTryUserCredentialsAndDSID_internal(CFStringRef user_label, CFDa bool SOSCCTryUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("sosops", "SOSCCTryUserCredentialsAndDSID!! %@\n", user_label); require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil"))); require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil"))); @@ -1365,11 +1200,23 @@ out: } bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, NULL, error); } bool SOSCCCanAuthenticate(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_CanAuthenticate, error); @@ -1379,6 +1226,12 @@ bool SOSCCCanAuthenticate(CFErrorRef* error) { } bool SOSCCPurgeUserCredentials(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_PurgeUserCredentials, error); @@ -1388,6 +1241,12 @@ bool SOSCCPurgeUserCredentials(CFErrorRef* error) { } enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSOSDepartureReasonError; + } + sec_trace_enter_api(NULL); sec_trace_return_api(enum DepartureReason, ^{ do_if_registered(soscc_GetLastDepartureReason, error); @@ -1397,6 +1256,12 @@ enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) { } bool SOSCCSetLastDepartureReason(enum DepartureReason reason, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_api(bool, ^{ do_if_registered(soscc_SetLastDepartureReason, reason, error); @@ -1412,16 +1277,13 @@ bool SOSCCSetLastDepartureReason(enum DepartureReason reason, CFErrorRef *error) }, NULL) } -CFStringRef SOSCCCopyIncompatibilityInfo(CFErrorRef* error) { - sec_trace_enter_api(NULL); - sec_trace_return_api(CFStringRef, ^{ - do_if_registered(soscc_CopyIncompatibilityInfo, error); - - return simple_cfstring_error_request(kSecXPCOpCopyIncompatibilityInfo, error); - }, NULL) -} - bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("updates", "enter SOSCCProcessEnsurePeerRegistration"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -1434,6 +1296,12 @@ bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){ CFSetRef /* CFString */ SOSCCProcessSyncWithPeers(CFSetRef peers, CFSetRef backupPeers, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFSetRef, ^{ do_if_registered(soscc_ProcessSyncWithPeers, peers, backupPeers, error); @@ -1445,6 +1313,12 @@ CFSetRef /* CFString */ SOSCCProcessSyncWithPeers(CFSetRef peers, CFSetRef backu SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSyncWithAllPeersOtherFail; + } + sec_trace_enter_api(NULL); sec_trace_return_api(SyncWithAllPeersReason, ^{ do_if_registered(soscc_ProcessSyncWithAllPeers, error); @@ -1512,6 +1386,17 @@ static int64_t name_action_to_code_request(enum SecXPCOperation op, uint16_t err } SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode actionCode, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSOSCCGeneralViewError; + } + + if(SOSVisibleKeychainNotAllowed() && (actionCode == kSOSCCViewEnable) && view && SOSViewsIsV0Subview(view)) { + secnotice("views", "Cannot enable visible keychain views due to profile restrictions"); + return false; + } + if(actionCode == kSOSCCViewQuery) { uint64_t circleStat = SOSGetCachedCircleBitmask(); if(circleStat & CC_STATISVALID) { @@ -1538,6 +1423,16 @@ SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode actionCode, CFEr bool SOSCCViewSet(CFSetRef enabledViews, CFSetRef disabledViews) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + + if(SOSVisibleKeychainNotAllowed() && enabledViews && CFSetGetCount(enabledViews) && SOSViewSetIntersectsV0(enabledViews)) { + secnotice("views", "Cannot enable visible keychain views due to profile restrictions"); + return false; + } + CFErrorRef *error = NULL; __block bool result = false; @@ -1557,27 +1452,6 @@ bool SOSCCViewSet(CFSetRef enabledViews, CFSetRef disabledViews) { }, NULL) } -bool SOSCCViewSetWithAnalytics(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent) { - CFErrorRef *error = NULL; - __block bool result = false; - - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_ViewSetWithAnalytics, enabledViews, disabledViews, parentEvent); - return securityd_send_sync_and_do(kSecXPCOpViewSetWithAnalytics, error, ^bool(xpc_object_t message, CFErrorRef *error) { - xpc_object_t enabledSetXpc = CreateXPCObjectWithCFSetRef(enabledViews, error); - xpc_object_t disabledSetXpc = CreateXPCObjectWithCFSetRef(disabledViews, error); - if (enabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyEnabledViewsKey, enabledSetXpc); - if (disabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyDisabledViewsKey, disabledSetXpc); - if(parentEvent) SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error); - return (enabledSetXpc != NULL) || (disabledSetXpc != NULL) ; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - }, NULL) -} - static CFStringRef copyViewNames(size_t n, CFStringRef *views) { CFMutableStringRef retval = CFStringCreateMutable(kCFAllocatorDefault, 0); CFStringAppend(retval, CFSTR("|")); @@ -1638,77 +1512,72 @@ static bool sosIsViewSetSyncing(size_t n, CFStringRef *views) { } bool SOSCCIsIcloudKeychainSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; // should we lie since CKKS is syncing - or forward? + } + CFStringRef views[] = { kSOSViewWiFi, kSOSViewAutofillPasswords, kSOSViewSafariCreditCards, kSOSViewOtherSyncable }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsSafariSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewAutofillPasswords, kSOSViewSafariCreditCards }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsAppleTVSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewAppleTV }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsHomeKitSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewHomeKit }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsWiFiSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewWiFi }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsContinuityUnlockSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewContinuityUnlock }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } - -bool SOSCCSetEscrowRecord(CFStringRef escrow_label, uint64_t tries, CFErrorRef *error ){ - secnotice("escrow", "enter SOSCCSetEscrowRecord"); - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_SetEscrowRecords, escrow_label, tries, error); - - return escrow_to_bool_error_request(kSecXPCOpSetEscrowRecord, escrow_label, tries, error); - }, NULL) -} - -CFDictionaryRef SOSCCCopyEscrowRecord(CFErrorRef *error){ - secnotice("escrow", "enter SOSCCCopyEscrowRecord"); - sec_trace_enter_api(NULL); - sec_trace_return_api(CFDictionaryRef, ^{ - do_if_registered(soscc_CopyEscrowRecords, error); - - return strings_to_dictionary_error_request(kSecXPCOpGetEscrowRecord, error); - }, CFSTR("return=%@")) - -} - -CFDictionaryRef SOSCCCopyBackupInformation(CFErrorRef *error) { - secnotice("escrow", "enter SOSCCCopyBackupInformation"); - sec_trace_enter_api(NULL); - sec_trace_return_api(CFDictionaryRef, ^{ - do_if_registered(soscc_CopyBackupInformation, error); - return strings_to_dictionary_error_request(kSecXPCOpCopyBackupInformation, error); - }, CFSTR("return=%@")) -} - -bool SOSWrapToBackupSliceKeyBagForView(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error) { - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(sosbskb_WrapToBackupSliceKeyBagForView, viewName, input, output, bskbEncoded, error); - - return cfstring_and_cfdata_to_cfdata_cfdata_error_request(kSecXPCOpWrapToBackupSliceKeyBagForView, viewName, input, output, bskbEncoded, error); - }, NULL) -} - - SOSPeerInfoRef SOSCCCopyApplication(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + secnotice("hsa2PB", "enter SOSCCCopyApplication applicant"); sec_trace_enter_api(NULL); @@ -1719,6 +1588,12 @@ SOSPeerInfoRef SOSCCCopyApplication(CFErrorRef *error) { } bool SOSCCCleanupKVSKeys(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("cleanup-keys", "enter SOSCCCleanupKVSKeys"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -1730,19 +1605,13 @@ bool SOSCCCleanupKVSKeys(CFErrorRef *error) { return false; } -bool SOSCCTestPopulateKVSWithBadKeys(CFErrorRef *error) { - secnotice("cleanup-keys", "enter SOSCCPopulateKVSWithBadKeys"); - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_SOSCCTestPopulateKVSWithBadKeys, error); - - return simple_bool_error_request(kSecXPCOpPopulateKVS, error); - }, NULL) - - return false; -} - CFDataRef SOSCCCopyCircleJoiningBlob(SOSPeerInfoRef applicant, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + secnotice("hsa2PB", "enter SOSCCCopyCircleJoiningBlob approver"); sec_trace_enter_api(NULL); @@ -1757,6 +1626,12 @@ CFDataRef SOSCCCopyCircleJoiningBlob(SOSPeerInfoRef applicant, CFErrorRef *error } CFDataRef SOSCCCopyInitialSyncData(SOSInitialSyncFlags flags, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + secnotice("circleJoin", "enter SOSCCCopyInitialSyncData approver"); sec_trace_enter_api(NULL); @@ -1767,6 +1642,12 @@ CFDataRef SOSCCCopyInitialSyncData(SOSInitialSyncFlags flags, CFErrorRef *error) } bool SOSCCJoinWithCircleJoiningBlob(CFDataRef joiningBlob, PiggyBackProtocolVersion version, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("hsa2PB", "enter SOSCCJoinWithCircleJoiningBlob applicant"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -1776,17 +1657,13 @@ bool SOSCCJoinWithCircleJoiningBlob(CFDataRef joiningBlob, PiggyBackProtocolVers }, NULL) } -bool SOSCCIsThisDeviceLastBackup(CFErrorRef *error) { - secnotice("peer", "enter SOSCCIsThisDeviceLastBackup"); - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_IsThisDeviceLastBackup, error); - - return simple_bool_error_request(kSecXPCOpIsThisDeviceLastBackup, error); - }, NULL) -} - CFBooleanRef SOSCCPeersHaveViewsEnabled(CFArrayRef viewNames, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return FALSE; + } + secnotice("view-enabled", "enter SOSCCPeersHaveViewsEnabled"); sec_trace_enter_api(NULL); sec_trace_return_api(CFBooleanRef, ^{ @@ -1797,6 +1674,12 @@ CFBooleanRef SOSCCPeersHaveViewsEnabled(CFArrayRef viewNames, CFErrorRef *error) } bool SOSCCMessageFromPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("pending-check", "enter SOSCCMessageFromPeerIsPending"); sec_trace_return_bool_api(^{ @@ -1808,6 +1691,12 @@ bool SOSCCMessageFromPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) { } bool SOSCCSendToPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_return_bool_api(^{ do_if_registered(soscc_SOSCCSendToPeerIsPending, peer, error); @@ -1852,6 +1741,12 @@ bool SOSCCSendToPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) { static id SOSCCGetStatusObject(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return nil; + } + if (gSecurityd && gSecurityd->soscc_status) return (__bridge id)gSecurityd->soscc_status(); @@ -1866,6 +1761,11 @@ SOSCCGetStatusObject(CFErrorRef *error) static id SOSCCGetSynchronousStatusObject(CFErrorRef *cferror) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(cferror); + return nil; + } if (gSecurityd && gSecurityd->soscc_status) return (__bridge id)gSecurityd->soscc_status(); diff --git a/keychain/SecureObjectSync/SOSCloudCircleInternal.h b/keychain/SecureObjectSync/SOSCloudCircleInternal.h index 36e5dfbd..9fd07e97 100644 --- a/keychain/SecureObjectSync/SOSCloudCircleInternal.h +++ b/keychain/SecureObjectSync/SOSCloudCircleInternal.h @@ -31,6 +31,24 @@ #include #include +#if TARGET_OS_TV +#define SOS_AVAILABLE false +#elif TARGET_OS_WATCH +#define SOS_AVAILABLE false +#elif TARGET_OS_BRIDGE +#define SOS_AVAILABLE false +#elif TARGET_OS_IOS +#define SOS_AVAILABLE true +#elif TARGET_OS_OSX +#define SOS_AVAILABLE true +#elif TARGET_OS_SIMULATOR +#define SOS_AVAILABLE true +#else +#define SOS_AVAILABLE false +#endif + +#define IF_SOS_DISABLED if(!SOS_AVAILABLE) + __BEGIN_DECLS // Use the kSecAttrViewHint* constants in SecItemPriv.h instead @@ -56,7 +74,6 @@ bool SOSCCPurgeUserCredentials(CFErrorRef* error); CFStringRef SOSCCGetStatusDescription(SOSCCStatus status); CFStringRef SOSCCGetViewResultDescription(SOSViewResultCode vrc); bool SOSCCAccountHasPublicKey(CFErrorRef *error); -bool SOSCCAccountIsNew(CFErrorRef *error); /*! @function SOSCCProcessSyncWithPeers @@ -75,14 +92,6 @@ SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error); bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error); -//Rings -CFStringRef SOSCCGetAllTheRings(CFErrorRef *error); - -bool SOSCCApplyToARing(CFStringRef ringName, CFErrorRef* error); -bool SOSCCWithdrawlFromARing(CFStringRef ringName, CFErrorRef* error); -int SOSCCRingStatus(CFStringRef ringName, CFErrorRef* error); // TODO: this returns SOSRingStatus -bool SOSCCEnableRing(CFStringRef ringName, CFErrorRef* error); - bool SOSCCCleanupKVSKeys(CFErrorRef *error); @@ -93,27 +102,10 @@ bool SOSCCCleanupKVSKeys(CFErrorRef *error); */ SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error); -/*! - @function SOSWrapToBackupSliceKeyBagForView - @abstract Encrypts the given plaintext, and wraps the encryption key to the backup slice keybag for this view - @param viewName The view to wrap to - @param input The plaintext to encrypt - @param output The ciphertext - @param bskbEncoded The encoded backup slice keybag used to wrap the data - @param error What went wrong if we returned false - */ -bool SOSWrapToBackupSliceKeyBagForView(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error); - // // Security Tool calls // -CFDataRef SOSCCCopyAccountState(CFErrorRef* error); -bool SOSCCDeleteAccountState(CFErrorRef *error); -CFDataRef SOSCCCopyEngineData(CFErrorRef* error); -bool SOSCCDeleteEngineState(CFErrorRef *error); CFDataRef SOSCCCopyRecoveryPublicKey(CFErrorRef *error); -CFDictionaryRef SOSCCCopyBackupInformation(CFErrorRef *error); -bool SOSCCTestPopulateKVSWithBadKeys(CFErrorRef *error); CFDataRef SOSCCCopyInitialSyncData(SOSInitialSyncFlags flags, CFErrorRef *error); void SOSCCForEachEngineStateAsStringFromArray(CFArrayRef states, void (^block)(CFStringRef oneStateString)); diff --git a/keychain/SecureObjectSync/SOSCoder.c b/keychain/SecureObjectSync/SOSCoder.c index 109cffae..4172edb3 100644 --- a/keychain/SecureObjectSync/SOSCoder.c +++ b/keychain/SecureObjectSync/SOSCoder.c @@ -48,7 +48,6 @@ #include #include -#include #include "AssertMacros.h" @@ -274,7 +273,7 @@ SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { switch (SOSCoderGetExportedVersion(der, der_end)) { case kCoderAsOTRDataOnly: - der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, der_end); + der = der_decode_data(kCFAllocatorDefault, &otr_data, error, der, der_end); p->waitingForDataPacket = false; break; @@ -285,10 +284,10 @@ SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { require_action_quiet(sequence_end == der_end, fail, SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Extra data in SOS coder"), NULL, error)); - der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &otr_data, error, der, sequence_end); der = ccder_decode_bool(&p->waitingForDataPacket, der, sequence_end); if (der != sequence_end) { // optionally a pending response - der = der_decode_data(kCFAllocatorDefault, 0, &p->pendingResponse, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &p->pendingResponse, error, der, sequence_end); } } break; @@ -307,12 +306,12 @@ SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { goto fail; } - der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &otr_data, error, der, sequence_end); der = ccder_decode_bool(&p->waitingForDataPacket, der, sequence_end); der = ccder_decode_bool(&p->lastReceivedWasOld, der, sequence_end); - der = der_decode_data(kCFAllocatorDefault, 0, &p->hashOfLastReceived, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &p->hashOfLastReceived, error, der, sequence_end); if (der != sequence_end) { // optionally a pending response - der = der_decode_data(kCFAllocatorDefault, 0, &p->pendingResponse, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &p->pendingResponse, error, der, sequence_end); } } break; @@ -356,7 +355,7 @@ SOSCoderRef SOSCoderCreate(SOSPeerInfoRef peerInfo, SOSFullPeerInfoRef myPeerInf privateKey = SOSFullPeerInfoCopyDeviceKey(myPeerInfo, &localError); require_quiet(privateKey, errOut); - myRef = SecOTRFullIdentityCreateFromSecKeyRef(allocator, privateKey, &localError); + myRef = SecOTRFullIdentityCreateFromSecKeyRefSOS(allocator, privateKey, &localError); require_quiet(myRef, errOut); CFReleaseNull(privateKey); @@ -566,7 +565,6 @@ SOSCoderStatus SOSCoderUnwrap(SOSCoderRef coder, CFDataRef codedMessage, CFMutab case errSecDecode: CFStringAppend(action, CFSTR("resending dh")); result = SOSCoderResendDH(coder, error); - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.restartotrnegotiation"), 1); break; default: SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot negotiate session (%ld)"), clientId, (long)ppstatus); @@ -592,7 +590,6 @@ SOSCoderStatus SOSCoderUnwrap(SOSCoderRef coder, CFDataRef codedMessage, CFMutab if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) { CFStringAppend(action, CFSTR("not ready for data; resending DH packet")); - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.restartotrnegotiation"), 1); result = SOSCoderResendDH(coder, error); } else { if (coder->waitingForDataPacket) { diff --git a/keychain/SecureObjectSync/SOSControlHelper.m b/keychain/SecureObjectSync/SOSControlHelper.m index aaf58c28..fa802120 100644 --- a/keychain/SecureObjectSync/SOSControlHelper.m +++ b/keychain/SecureObjectSync/SOSControlHelper.m @@ -24,6 +24,8 @@ #import #import #import +#import +#include #import "keychain/SecureObjectSync/SOSTypes.h" #import "keychain/SecureObjectSync/SOSControlHelper.h" @@ -31,41 +33,38 @@ void _SOSControlSetupInterface(NSXPCInterface *interface) { - static NSMutableSet *errClasses; + NSSet *errClasses = [SecXPCHelper safeErrorClasses]; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - errClasses = [NSMutableSet set]; + @try { + [interface setClasses:errClasses forSelector:@selector(userPublicKey:) argumentIndex:2 ofReply:YES]; - char *classes[] = { - "NSURL", - "NSURLError", - "NSError" - }; + [interface setClasses:errClasses forSelector:@selector(stashedCredentialPublicKey:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(assertStashedAccountCredential:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(validatedStashedAccountCredential:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(stashAccountCredential:complete:) argumentIndex:1 ofReply:YES]; - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) - [errClasses addObject:cls]; - } - }); + [interface setClasses:errClasses forSelector:@selector(ghostBust:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(ghostBustPeriodic:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(ghostBustTriggerTimed:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(ghostBustInfo:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(userPublicKey:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(iCloudIdentityStatus:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(stashedCredentialPublicKey:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(assertStashedAccountCredential:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(stashAccountCredential:complete:) argumentIndex:1 ofReply:YES]; - - [interface setClasses:errClasses forSelector:@selector(myPeerInfo:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(circleHash:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(circleJoiningBlob:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(joinCircleWithBlob:version:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(initialSyncCredentials:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(importInitialSyncCredentials:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(getWatchdogParameters:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(setWatchdogParmeters:complete:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(ghostBust:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(rpcTriggerSync:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(rpcTriggerBackup:complete:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(rpcTriggerRingUpdate:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(myPeerInfo:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(circleHash:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(circleJoiningBlob:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(joinCircleWithBlob:version:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(initialSyncCredentials:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(importInitialSyncCredentials:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcTriggerSync:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(getWatchdogParameters:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(setWatchdogParmeters:complete:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcTriggerBackup:complete:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcTriggerRingUpdate:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(removeV0Peers:) argumentIndex:1 ofReply:YES]; + } + @catch(NSException* e) { + secerror("Could not configure SOSControlHelper: %@", e); + @throw e; + } } diff --git a/keychain/SecureObjectSync/SOSControlServer.m b/keychain/SecureObjectSync/SOSControlServer.m index 5f8a748d..c03e3f43 100644 --- a/keychain/SecureObjectSync/SOSControlServer.m +++ b/keychain/SecureObjectSync/SOSControlServer.m @@ -180,6 +180,10 @@ [self.account ghostBustInfo:complete]; } +- (void)iCloudIdentityStatus: (void (^)(NSData *json, NSError *error))complete { + [self.account iCloudIdentityStatus: complete]; +} + - (void)rpcTriggerBackup:(NSArray* _Nullable)backupPeers complete:(void (^)(NSError *error))complete { [self.account rpcTriggerBackup:backupPeers complete:complete]; @@ -189,14 +193,23 @@ [self.account rpcTriggerRingUpdate:complete]; } +- (void)iCloudIdentityStatus_internal:(void (^)(NSDictionary *, NSError *))complete { + [self.account iCloudIdentityStatus_internal:complete]; +} + +- (void)removeV0Peers:(void (^)(bool, NSError *))reply { + [self.account removeV0Peers:reply]; +} + + + @end @implementation SOSClientRemote - (instancetype)initSOSConnectionWithConnection:(NSXPCConnection *)connection account:(SOSAccount *)account { - self = [super initSOSClientWithAccount:account]; - if (self) { + if ((self = [super initSOSClientWithAccount:account])) { self.connection = connection; } return self; diff --git a/keychain/SecureObjectSync/SOSECWrapUnwrap.c b/keychain/SecureObjectSync/SOSECWrapUnwrap.c index 7aea444d..f013cb8e 100644 --- a/keychain/SecureObjectSync/SOSECWrapUnwrap.c +++ b/keychain/SecureObjectSync/SOSECWrapUnwrap.c @@ -9,11 +9,11 @@ #include -#include #include #include #include -#include +#import +#import #if 0 && defined(CCEC_RFC6637_DEBUG_KEYS) @@ -46,7 +46,7 @@ SOSCopyECWrappedData(ccec_pub_ctx_t ec_ctx, CFDataRef data, CFErrorRef *error) res = ccec_rfc6637_wrap_key(ec_ctx, CFDataGetMutableBytePtr(output), CCEC_RFC6637_COMPACT_KEYS | DEBUGKEYS, kAlgorithmID, CFDataGetLength(data), CFDataGetBytePtr(data), &ccec_rfc6637_dh_curve_p256, &ccec_rfc6637_wrap_sha256_kek_aes128, (const uint8_t *)fingerprint, - ccDevRandomGetRngState()); + ccrng(NULL)); require_noerr_action(res, exit, SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("Wrap failed with %d"), res)); CFTransferRetained(result, output); diff --git a/keychain/SecureObjectSync/SOSEngine.c b/keychain/SecureObjectSync/SOSEngine.c index f2a4a9db..d644bee0 100644 --- a/keychain/SecureObjectSync/SOSEngine.c +++ b/keychain/SecureObjectSync/SOSEngine.c @@ -50,9 +50,8 @@ #include #include #include -#include #include - +#include "utilities/SecCoreAnalytics.h" #include #include @@ -332,6 +331,19 @@ static void SOSEngineForEachBackupPeer_locked(SOSEngineRef engine, void (^with)( CFRelease(peerMapCopy); } +static void SOSEngineForBackupPeer_locked(SOSEngineRef engine, CFStringRef backupPeerID, void (^with)(SOSPeerRef peer)) { + struct SOSEngineWithPeerContext ewp = { .engine = engine, .with = with }; + CFMutableDictionaryRef singleEntryMap = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryRef peerMapCopy = CFDictionaryCreateCopy(NULL, engine->peerMap); + SOSPeerRef peer = (SOSPeerRef)CFDictionaryGetValue(peerMapCopy, backupPeerID); + if(peer != NULL) { + CFDictionaryAddValue(singleEntryMap, backupPeerID, peer); + CFDictionaryApplyFunction(singleEntryMap, SOSEngineWithBackupPeerMapEntry_locked, &ewp); + } + CFRelease(peerMapCopy); + CFRelease(singleEntryMap); +} + // // Manifest cache // @@ -706,7 +718,7 @@ CFMutableDictionaryRef derStateToDictionaryCopy(CFDataRef state, CFErrorRef *err if (state) { const uint8_t *der = CFDataGetBytePtr(state); const uint8_t *der_end = der + CFDataGetLength(state); - ok = der = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *)&stateDict, error, der, der_end); + ok = der = der_decode_dictionary(kCFAllocatorDefault, (CFDictionaryRef *)&stateDict, error, der, der_end); if (der && der != der_end) { ok = SOSErrorCreate(kSOSErrorDecodeFailure, error, NULL, CFSTR("trailing %td bytes at end of state"), der_end - der); } @@ -773,7 +785,7 @@ static bool SOSEngineLoadCoders(SOSEngineRef engine, SOSTransactionRef txn, CFEr secnotice("coder", "Will force peer registration: %s",needPeerRegistration ? "yes" : "no"); if (needPeerRegistration) { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_queue_t queue = dispatch_get_global_queue(SOS_ENGINE_PRIORITY, 0); dispatch_async(queue, ^{ CFErrorRef eprError = NULL; @@ -1202,22 +1214,12 @@ static bool SOSEngineUpdateChanges_locked(SOSEngineRef engine, SOSTransactionRef if (deleted) { bool someoneCares = SOSChangeMapperIngestChange(&cm, false, deleted); if (someoneCares) { -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.delete"), 1); -#endif mappedItemChanged = true; } } if (inserted) { bool someoneCares = SOSChangeMapperIngestChange(&cm, true, inserted); if (someoneCares) { -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (deleted == NULL) { - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.add"), 1); - } else { - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.update"), 1); - } -#endif mappedItemChanged = true; } if (!someoneCares && !isData(inserted) && SecDbItemIsTombstone((SecDbItemRef)inserted) && !CFEqualSafe(SecDbItemGetValue((SecDbItemRef)inserted, &v7utomb, NULL), kCFBooleanTrue)) { @@ -1748,6 +1750,12 @@ static void SOSEngineForEachBackupPeer(SOSEngineRef engine, void (^with)(SOSPeer }); } +static void SOSEngineForBackupPeer(SOSEngineRef engine, CFStringRef backupPeerID, void (^with)(SOSPeerRef peer)) { + SOSEngineDoOnQueue(engine, ^{ + SOSEngineForBackupPeer_locked(engine, backupPeerID, with); + }); +} + static const CFStringRef kSecADSecurityNewItemSyncTimeKey = CFSTR("com.apple.security.secureobjectsync.itemtime.new"); static const CFStringRef kSecADSecurityKnownItemSyncTimeKey = CFSTR("com.apple.security.secureobjectsync.itemtime.known"); @@ -1764,8 +1772,8 @@ static void ReportItemSyncTime(SOSDataSourceRef ds, bool known, SOSObjectRef obj syncTime = now - peerModificationAbsoluteTime; } - SecADClientPushValueForDistributionKey(known ? kSecADSecurityKnownItemSyncTimeKey : kSecADSecurityNewItemSyncTimeKey, - SecBucket2Significant(syncTime)); + SecCoreAnalyticsSendValue(known ? kSecADSecurityKnownItemSyncTimeKey : kSecADSecurityNewItemSyncTimeKey, + SecBucket2Significant(syncTime)); } CFReleaseNull(itemModDate); } @@ -2772,6 +2780,14 @@ CFArrayRef SOSEngineCopyBackupPeerNames(SOSEngineRef engine, CFErrorRef *error) return backupNames; } +CFStringRef SOSEngineEnsureCopyBackupPeerForView(SOSEngineRef engine, CFStringRef backupPeerID, CFErrorRef *error) { + __block CFStringRef backupName = CFSTR(""); + SOSEngineForBackupPeer(engine, backupPeerID, ^(SOSPeerRef peer) { + backupName = CFRetainSafe(SOSPeerGetID(peer)); + }); + return backupName; +} + static CFMutableDictionaryRef SOSEngineCreateStateDictionary(CFStringRef peerID, SOSManifestRef manifest, CFSetRef vns, CFStringRef coderString) { CFNumberRef manifestCount = CFNumberCreateWithCFIndex(kCFAllocatorDefault, SOSManifestGetCount(manifest)); CFDataRef manifestHash = SOSManifestGetDigest(manifest, NULL); diff --git a/keychain/SecureObjectSync/SOSEngine.h b/keychain/SecureObjectSync/SOSEngine.h index ea598b8b..0e508d17 100644 --- a/keychain/SecureObjectSync/SOSEngine.h +++ b/keychain/SecureObjectSync/SOSEngine.h @@ -135,6 +135,7 @@ bool SOSEnginePeerDidConnect(SOSEngineRef engine, CFStringRef peerID, CFErrorRef bool SOSEngineSetPeerConfirmedManifest(SOSEngineRef engine, CFStringRef backupName, CFDataRef keybagDigest, CFDataRef manifestData, CFErrorRef *error); CFArrayRef SOSEngineCopyBackupPeerNames(SOSEngineRef engine, CFErrorRef *error); +CFStringRef SOSEngineEnsureCopyBackupPeerForView(SOSEngineRef engine, CFStringRef backupPeerID, CFErrorRef *error); void logRawMessage(CFDataRef message, bool sending, uint64_t seqno); diff --git a/keychain/SecureObjectSync/SOSExports.exp-in b/keychain/SecureObjectSync/SOSExports.exp-in index 66d25d5e..2e6dcd99 100644 --- a/keychain/SecureObjectSync/SOSExports.exp-in +++ b/keychain/SecureObjectSync/SOSExports.exp-in @@ -10,20 +10,14 @@ _SOSCCAccountGetAccountPrivateCredential _SOSCCAccountGetPublicKey _SOSCCAccountGetKeyCircleGeneration _SOSCCAccountHasPublicKey -_SOSCCAccountIsNew _SOSCCAccountSetToNew _SOSCCBailFromCircle_BestEffort _SOSCCCanAuthenticate -_SOSCCCopyAccountState _SOSCCCopyApplicantPeerInfo _SOSCCCopyApplication -_SOSCCCopyBackupInformation _SOSCCCopyCircleJoiningBlob _SOSCCCopyConcurringPeerPeerInfo -_SOSCCCopyEngineData -_SOSCCCopyEscrowRecord _SOSCCCopyGenerationPeerInfo -_SOSCCCopyIncompatibilityInfo _SOSCCCopyMyPeerInfo _SOSCCCopyMyPeerWithNewDeviceRecoverySecret _SOSCCCopyNotValidPeerPeerInfo @@ -32,11 +26,7 @@ _SOSCCCopyRecoveryPublicKey _SOSCCCopyRetirementPeerInfo _SOSCCCopyValidPeerPeerInfo _SOSCCCopyViewUnawarePeerInfo -_SOSCCCopyYetToSyncViewsList -_SOSCCDeleteAccountState -_SOSCCDeleteEngineState _SOSCCCleanupKVSKeys -_SOSCCTestPopulateKVSWithBadKeys _SOSCCForEachEngineStateAsString _SOSCCForEachEngineStateAsStringFromArray _SOSCCGetLastDepartureReason @@ -49,6 +39,7 @@ _SOSCCIsIcloudKeychainSyncing _SOSCCIsSafariSyncing _SOSCCIsWiFiSyncing _SOSCCJoinWithCircleJoiningBlob +_SOSCCLoggedIntoAccount _SOSCCLoggedOutOfAccount _SOSCCMessageFromPeerIsPending _SOSCCPeersHaveViewsEnabled @@ -61,24 +52,15 @@ _SOSCCRegisterSingleRecoverySecret _SOSCCRegisterUserCredentials _SOSCCRejectApplicants _SOSCCRemovePeersFromCircle -_SOSCCRemovePeersFromCircleWithAnalytics _SOSCCRemoveThisDeviceFromCircle -_SOSCCRemoveThisDeviceFromCircleWithAnalytics -_SOSCCRequestEnsureFreshParameters _SOSCCRequestToJoinCircle -_SOSCCRequestToJoinCircleWithAnalytics _SOSCCRequestToJoinCircleAfterRestore -_SOSCCRequestToJoinCircleAfterRestoreWithAnalytics _SOSCCResetToEmpty -_SOSCCResetToEmptyWithAnalytics _SOSCCResetToOffering _SOSCCSendToPeerIsPending -_SOSCCSetEscrowRecord _SOSCCSetLastDepartureReason _SOSCCSetUserCredentials _SOSCCSetUserCredentialsAndDSID -_SOSCCSetUserCredentialsAndDSIDWithAnalytics -_SOSCCSignedOut _SOSCCThisDeviceIsInCircle _SOSCCThisDeviceIsInCircleNonCached _SOSCCTryUserCredentials @@ -86,9 +68,7 @@ _SOSCCTryUserCredentialsAndDSID _SOSCCValidateUserPublic _SOSCCView _SOSCCViewSet -_SOSCCViewSetWithAnalytics _SOSCCWaitForInitialSync -_SOSCCWaitForInitialSyncWithAnalytics _SOSCCCopyInitialSyncData _kSOSCCEngineStateCoderKey @@ -126,14 +106,12 @@ _SOSPeerInfoCopyBackupKey _SOSPeerInfoCopyDeviceID _SOSPeerInfoCopyEnabledViews _SOSPeerInfoCopyEncodedData -_SOSPeerInfoCopyEscrowRecord _SOSPeerInfoCopyOctagonSigningPublicKey _SOSPeerInfoCopyOctagonEncryptionPublicKey _SOSPeerInfoCopyPeerGestalt _SOSPeerInfoCopyPubKey _SOSPeerInfoCopyTransportType _SOSPeerInfoCopyWithBackupKeyUpdate -_SOSPeerInfoCopyWithEscrowRecordUpdate _SOSPeerInfoCopyWithGestaltUpdate _SOSPeerInfoCopyWithPing _SOSPeerInfoCopyWithReplacedEscrowRecords @@ -156,6 +134,7 @@ _SOSPeerInfoGetClass _SOSPeerInfoGetDEREncodedSize _SOSPeerInfoGetPeerDeviceType _SOSPeerInfoGetPeerID +_SOSPeerInfoGetSPID _SOSPeerInfoGetPeerName _SOSPeerInfoGetPeerProtocolVersion _SOSPeerInfoGetPermittedViews @@ -189,13 +168,6 @@ _SOSFullPeerInfoGetPeerInfo _SOSCircleAcceptPeerFromHSA2 _SOSFullPeerInfoUpdate -_SOSCCGetAllTheRings -_SOSCCApplyToARing -_SOSCCWithdrawlFromARing -_SOSCCRingStatus -_SOSCCEnableRing -_SOSCCIsThisDeviceLastBackup - _SOSCloudKeychainRemoveKeys _SOSCloudTransportSetDefaultTransport @@ -246,7 +218,6 @@ _der_encode_BackupSliceKeyBag _der_sizeof_BackupSliceKeyBag _bskbRkbgPrefix -_SOSWrapToBackupSliceKeyBagForView _SOSBSKBHasRecoveryKey _SOSBSKBHasThisRecoveryKey @@ -273,7 +244,10 @@ _SOSViewsGetV0SubviewSet _SOSViewsGetV0ViewSet _SOSViewsIsV0Subview _SOSViewsQuery +_SOSPeerInfoIsViewPermitted _SOSViewsSetTestViewsSet +_SOSViewSetIntersectsV0 +_SOSPeerInfoV0ViewsEnabled _SOSViewsXlateAction // @@ -415,7 +389,6 @@ _SOSCircleVerifyPeerSignatureExists _SOSCircleWithdrawRequest _debugDumpCircle -_SOSFullPeerInfoAddEscrowRecord _SOSFullPeerInfoCopyDeviceKey _SOSFullPeerInfoCopyEncodedData _SOSFullPeerInfoCopyFullPeerInfo @@ -431,6 +404,7 @@ _SOSFullPeerInfoCreateWithViews _SOSFullPeerInfoEncodeToDER _SOSFullPeerInfoGetDEREncodedSize _SOSFullPeerInfoPing +_SOSFullPeerInfoSetCKKS4AllSupport _SOSFullPeerInfoPrivKeyExists _SOSFullPeerInfoPromoteToRetiredAndCopy _SOSFullPeerInfoPurgePersistentKey @@ -492,6 +466,7 @@ _SOSRingKeyCreateWithName _SOSRingKeyCreateWithRingName _kSOSKVSKeyParametersKey _sCirclePrefix +_sRingPrefix _sDebugInfoPrefix _sRetirementPrefix @@ -513,6 +488,8 @@ _SOSCreateErrorWithFormat _SOSCreateErrorWithFormatAndArguments _SOSDateCreate _SOSErrorCreate +_SOSCCCredentialQueue +_SOSVisibleKeychainNotAllowed _SOSGenerateDeviceBackupFullKey _SOSGetBackupKeyCurveParameters _SOSItemsChangedCopyDescription @@ -522,7 +499,7 @@ _SOSTransportMessageTypeIDSV2 _SOSTransportMessageTypeKVS _kSOSDSIDKey _kSOSNoCachedValue - +_kSOSCountKey _SOSPeerGestaltGetAnswer _SOSPeerGestaltGetName @@ -560,6 +537,7 @@ _sBackupKeyKey _sEscrowRecord _sTransportType _SOSGenerationCountCopyDescription +_sCKKSForAll _kSOSHsaCrKeyDictionary _SOSPeerInfoCopySerialNumber @@ -568,6 +546,8 @@ _SOSPeerInfoPackV2Data _SOSPeerInfoSerialNumberIsSet _SOSPeerInfoSetSerialNumber _SOSPeerInfoSetTestSerialNumber +_SOSPeerInfoSetSupportsCKKSForAll +_SOSPeerInfoSupportsCKKSForAll _SOSPeerInfoSign _SOSPeerInfoUpdateToV2 _SOSPeerInfoV2DictionaryCopyDictionary diff --git a/keychain/SecureObjectSync/SOSFullPeerInfo.h b/keychain/SecureObjectSync/SOSFullPeerInfo.h index 2d265c6e..05e1b1af 100644 --- a/keychain/SecureObjectSync/SOSFullPeerInfo.h +++ b/keychain/SecureObjectSync/SOSFullPeerInfo.h @@ -63,6 +63,7 @@ SecKeyRef SOSFullPeerInfoCopyOctagonPublicSigningKey(SOSFullPeerInfoRef fullPeer SecKeyRef SOSFullPeerInfoCopyOctagonPublicEncryptionKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error); SecKeyRef SOSFullPeerInfoCopyOctagonSigningKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error); SecKeyRef SOSFullPeerInfoCopyOctagonEncryptionKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error); +bool SOSFullPeerInfoSetCKKS4AllSupport(SOSFullPeerInfoRef fullPeerInfo, bool support, CFErrorRef* error); bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef peer, CFErrorRef* error); @@ -80,8 +81,6 @@ bool SOSFullPeerInfoUpdateV2Dictionary(SOSFullPeerInfoRef peer, CFDictionaryRef bool SOSFullPeerInfoUpdateBackupKey(SOSFullPeerInfoRef peer, CFDataRef backupKey, CFErrorRef* error); -bool SOSFullPeerInfoAddEscrowRecord(SOSFullPeerInfoRef peer, CFStringRef dsid, CFDictionaryRef escrowRecord, CFErrorRef* error); - bool SOSFullPeerInfoReplaceEscrowRecords(SOSFullPeerInfoRef peer, CFDictionaryRef escrowRecords, CFErrorRef* error); bool SOSFullPeerInfoUpdateToCurrent(SOSFullPeerInfoRef peer, CFSetRef minimumViews, CFSetRef excludedViews); diff --git a/keychain/SecureObjectSync/SOSFullPeerInfo.m b/keychain/SecureObjectSync/SOSFullPeerInfo.m index 7b2bee13..02cbbe20 100644 --- a/keychain/SecureObjectSync/SOSFullPeerInfo.m +++ b/keychain/SecureObjectSync/SOSFullPeerInfo.m @@ -41,7 +41,6 @@ #include #include -#include #include #include @@ -146,15 +145,17 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateWithViews(CFAllocatorRef allocator, fpi->peer_info = SOSPeerInfoCreateWithTransportAndViews(allocator, gestalt, backupKey, IDSID, transportType, preferIDS, preferIDSFragmentation, preferACKModel, initialViews, - signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, error); + signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, + // All newly-created FullPeerInfos are on software that supports CKKS4All + true, + error); require_quiet(fpi->peer_info, exit); OSStatus status = SecKeyCopyPersistentRef(signingKey, &fpi->key_ref); require_quiet(SecError(status, error, CFSTR("Inflating persistent ref")), exit); - status = SecKeyCopyPersistentRef(octagonPeerSigningKey, &fpi->octagon_peer_signing_key_ref); require_quiet(SecError(status, error, CFSTR("Inflating octagon peer signing persistent ref")), exit); - status = SecKeyCopyPersistentRef(octagonPeerSigningKey, &fpi->octagon_peer_encryption_key_ref); + status = SecKeyCopyPersistentRef(octagonPeerEncryptionKey, &fpi->octagon_peer_encryption_key_ref); require_quiet(SecError(status, error, CFSTR("Inflating octagon peer encryption persistent ref")), exit); CFTransferRetained(result, fpi); @@ -199,6 +200,27 @@ bool SOSFullPeerInfoUpdateOctagonEncryptionKey(SOSFullPeerInfoRef peer, SecKeyRe }); } +bool SOSFullPeerInfoSetCKKS4AllSupport(SOSFullPeerInfoRef fullPeerInfo, bool support, CFErrorRef* error) { + + SOSPeerInfoRef peerInfo = SOSFullPeerInfoGetPeerInfo(fullPeerInfo); + bool supportsCKKS4All = SOSPeerInfoSupportsCKKSForAll(peerInfo); + + if(supportsCKKS4All == support) { + // Early-exit: no change needed + return true; + } + + secnotice("circleChange", "Setting CKKS4All status to '%@'", support ? @"supported" : @"not supported"); + + return SOSFullPeerInfoUpdate(fullPeerInfo, error, ^SOSPeerInfoRef(SOSPeerInfoRef currentPeerInfo, SecKeyRef key, CFErrorRef *blockerror) { + SOSPeerInfoRef newPeerInfo = SOSPeerInfoCopyWithModification(kCFAllocatorDefault, currentPeerInfo, key, blockerror, + ^bool(SOSPeerInfoRef peerToModify, CFErrorRef *innerblockerror) { + SOSPeerInfoSetSupportsCKKSForAll(peerToModify, support); + return true; + }); + return newPeerInfo; + }); +} CFDataRef SOSPeerInfoCopyData(SOSPeerInfoRef pi, CFErrorRef *error) @@ -271,7 +293,7 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErro fpi->peer_info = SOSPeerInfoCreateFromDER(allocator, error, der_p, der_end); require_quiet(fpi->peer_info != NULL, fail); - *der_p = der_decode_data(allocator, kCFPropertyListImmutable, &fpi->key_ref, error, *der_p, sequence_end); + *der_p = der_decode_data(allocator, &fpi->key_ref, error, *der_p, sequence_end); require_quiet(*der_p != NULL, fail); return fpi; @@ -354,13 +376,6 @@ bool SOSFullPeerInfoUpdateBackupKey(SOSFullPeerInfoRef peer, CFDataRef backupKey }); } -bool SOSFullPeerInfoAddEscrowRecord(SOSFullPeerInfoRef peer, CFStringRef dsid, CFDictionaryRef escrowRecord, CFErrorRef* error) -{ - return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) { - return SOSPeerInfoCopyWithEscrowRecordUpdate(kCFAllocatorDefault, peer, dsid, escrowRecord, key, error); - }); -} - bool SOSFullPeerInfoReplaceEscrowRecords(SOSFullPeerInfoRef peer, CFDictionaryRef escrowRecords, CFErrorRef* error) { return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) { @@ -499,12 +514,14 @@ errOut: static SecKeyRef SOSFullPeerInfoCopyMatchingPrivateKey(SOSFullPeerInfoRef fpi, CFErrorRef *error) { SecKeyRef retval = NULL; - SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi, error); - require_quiet(pub, exit); - retval = SecKeyCopyMatchingPrivateKey(pub, error); -exit: - CFReleaseNull(pub); + if(pub) { + retval = SecKeyCopyMatchingPrivateKey(pub, error); + if(!retval) { + secnotice("circleOp", "Failed to find my private key for spid %@", SOSPeerInfoGetSPID(SOSFullPeerInfoGetPeerInfo(fpi))); + } + CFReleaseNull(pub); + } return retval; } diff --git a/keychain/SecureObjectSync/SOSGenCount.c b/keychain/SecureObjectSync/SOSGenCount.c index 5163e901..ef04e2dc 100644 --- a/keychain/SecureObjectSync/SOSGenCount.c +++ b/keychain/SecureObjectSync/SOSGenCount.c @@ -124,7 +124,7 @@ SOSGenCountRef SOSGenerationCreateWithBaseline(SOSGenCountRef reference) { SOSGenCountRef SOSGenCountCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, const uint8_t** der_p, const uint8_t *der_end) { SOSGenCountRef retval = NULL; - *der_p = der_decode_number(allocator, 0, &retval, error, *der_p, der_end); + *der_p = der_decode_number(allocator, &retval, error, *der_p, der_end); if(retval == NULL) retval = SOSGenerationCreate(); return retval; diff --git a/keychain/SecureObjectSync/SOSInternal.h b/keychain/SecureObjectSync/SOSInternal.h index 0460de82..29dc81ae 100644 --- a/keychain/SecureObjectSync/SOSInternal.h +++ b/keychain/SecureObjectSync/SOSInternal.h @@ -39,6 +39,10 @@ __BEGIN_DECLS +#define SOS_ACCOUNT_PRIORITY DISPATCH_QUEUE_PRIORITY_LOW +#define SOS_ENGINE_PRIORITY DISPATCH_QUEUE_PRIORITY_BACKGROUND +#define SOS_TRANSPORT_PRIORITY DISPATCH_QUEUE_PRIORITY_LOW + #define ENABLE_IDS 0 #define kSOSPeerIDLengthMax (26) @@ -82,12 +86,18 @@ enum { kSOSErrorParam = 1045, kSOSErrorNotInCircle = 1046, kSOSErrorKeysNeedAttention = 1047, + kSOSErrorNoAccount = 1048, }; extern const CFStringRef SOSTransportMessageTypeIDSV2; extern const CFStringRef SOSTransportMessageTypeKVS; extern const CFStringRef kSOSDSIDKey; extern const SOSCCStatus kSOSNoCachedValue; +extern const CFStringRef kSOSCountKey; + +dispatch_queue_t SOSCCCredentialQueue(void); + +bool SOSVisibleKeychainNotAllowed(void); // Returns false unless errorCode is 0. bool SOSErrorCreate(CFIndex errorCode, CFErrorRef *error, CFDictionaryRef formatOptions, CFStringRef descriptionString, ...); diff --git a/keychain/SecureObjectSync/SOSInternal.m b/keychain/SecureObjectSync/SOSInternal.m index 35e8c151..d77bf9d0 100644 --- a/keychain/SecureObjectSync/SOSInternal.m +++ b/keychain/SecureObjectSync/SOSInternal.m @@ -47,9 +47,15 @@ #include #include -#include +#include +#include +#include -#include +#if !TARGET_OS_OSX +#import +#import +#import +#endif #include @@ -59,6 +65,7 @@ const CFStringRef kSOSErrorDomain = CFSTR("com.apple.security.sos.error"); const CFStringRef kSOSDSIDKey = CFSTR("AccountDSID"); const CFStringRef SOSTransportMessageTypeIDSV2 = CFSTR("IDS2.0"); const CFStringRef SOSTransportMessageTypeKVS = CFSTR("KVS"); +const CFStringRef kSOSCountKey = CFSTR("numberOfErrorsDeep"); bool SOSErrorCreate(CFIndex errorCode, CFErrorRef *error, CFDictionaryRef formatOptions, CFStringRef format, ...) CF_FORMAT_FUNCTION(4, 5); @@ -256,23 +263,29 @@ bool SOSGenerateDeviceBackupFullKey(ccec_full_ctx_t generatedKey, ccec_const_cp_ { bool result = false; int cc_result = 0; - struct ccrng_pbkdf2_prng_state pbkdf2_prng; - const int kBackupKeyMaxBytes = 1024; // This may be a function of the cp but will be updated when we use a formally deterministic key generation. - cc_result = ccrng_pbkdf2_prng_init(&pbkdf2_prng, kBackupKeyMaxBytes, - CFDataGetLength(entropy), CFDataGetBytePtr(entropy), - sizeof(sBackupKeySalt), sBackupKeySalt, - kBackupKeyIterations); - require_action_quiet(cc_result == 0, exit, SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("pbkdf rng init failed: %d"), cc_result)); +#define drbg_output_size 1024 - cc_result = ccec_compact_generate_key(cp, (struct ccrng_state *) &pbkdf2_prng, generatedKey); - require_action_quiet(cc_result == 0, exit, SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("Generate key failed: %d"), cc_result)); + uint8_t drbg_output[drbg_output_size]; + cc_result = ccpbkdf2_hmac(ccsha256_di(), CFDataGetLength(entropy), CFDataGetBytePtr(entropy), + sizeof(sBackupKeySalt), sBackupKeySalt, + kBackupKeyIterations, + drbg_output_size, drbg_output); + require_action_quiet(cc_result == 0, exit, + SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("ccpbkdf2_hmac failed: %d"), cc_result)); + + cc_result = ccec_generate_key_deterministic(cp, + drbg_output_size, + drbg_output, + ccrng(NULL), + CCEC_GENKEY_DETERMINISTIC_SECBKP, + generatedKey); + require_action_quiet(cc_result == 0, exit, + SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("ccec_generate_key_deterministic failed: %d"), cc_result)); result = true; exit: - bzero(&pbkdf2_prng, sizeof(pbkdf2_prng)); return result; - } CFDataRef SOSCopyDeviceBackupPublicKey(CFDataRef entropy, CFErrorRef *error) @@ -440,3 +453,38 @@ NSDate *SOSCreateRandomDateBetweenNowPlus(NSTimeInterval starting, NSTimeInterva return [[NSDate alloc] initWithTimeIntervalSinceNow:resultInterval]; } + +dispatch_queue_t SOSCCCredentialQueue(void) { + static dispatch_queue_t credQueue = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + credQueue = dispatch_queue_create("com.apple.SOSCredentialsQueue", DISPATCH_QUEUE_SERIAL); + }); + return credQueue; +} + + +#if TARGET_OS_OSX +#define KEYCHAINSYNCDISABLE "DisableKeychainCloudSync" +#define ICLOUDMANAGEDENVIRONMENT "com.apple.icloud.managed" +#else +SOFT_LINK_FRAMEWORK(PrivateFrameworks, ManagedConfiguration) +SOFT_LINK_CLASS(ManagedConfiguration, MCProfileConnection) +#endif + +bool SOSVisibleKeychainNotAllowed(void) { + bool notAllowed = false; + +#if TARGET_OS_OSX + notAllowed = CFPreferencesGetAppBooleanValue(CFSTR(KEYCHAINSYNCDISABLE), CFSTR(ICLOUDMANAGEDENVIRONMENT), NULL); +#else + Class mpc = getMCProfileConnectionClass(); + MCProfileConnection *sharedConnection = [mpc sharedConnection]; + notAllowed = ![sharedConnection isCloudKeychainSyncAllowed]; +#endif + + if(notAllowed) { + secnotice("views", "V0 views disabled by Managed Preferences Profile"); + } + return notAllowed; +} diff --git a/keychain/SecureObjectSync/SOSIntervalEvent.m b/keychain/SecureObjectSync/SOSIntervalEvent.m index 30fda736..f230261b 100644 --- a/keychain/SecureObjectSync/SOSIntervalEvent.m +++ b/keychain/SecureObjectSync/SOSIntervalEvent.m @@ -54,15 +54,16 @@ SOSIntervalEvent fooEvent = [[SOSIntervalEvent alloc] initWithDefaults:account.s } -(id)initWithDefaults:(NSUserDefaults*) defaults dateDescription:(NSString *)dateDescription earliest:(NSTimeInterval) earliest latest: (NSTimeInterval) latest { - if(!self) return nil; - _defaults = defaults; - if(! _defaults) { - _defaults = [[NSUserDefaults alloc] init]; + if ((self = [super init])) { + _defaults = defaults; + if(! _defaults) { + _defaults = [[NSUserDefaults alloc] init]; + } + _dateDescription = dateDescription; + _earliestDate = earliest; + _latestDate = latest; + [self schedule]; } - _dateDescription = dateDescription; - _earliestDate = earliest; - _latestDate = latest; - [self schedule]; return self; } diff --git a/keychain/SecureObjectSync/SOSKVSKeys.h b/keychain/SecureObjectSync/SOSKVSKeys.h index 84afb8c9..dabc69c5 100644 --- a/keychain/SecureObjectSync/SOSKVSKeys.h +++ b/keychain/SecureObjectSync/SOSKVSKeys.h @@ -36,6 +36,7 @@ extern const CFStringRef kSOSKVSWroteLastKeyParams; extern const CFStringRef sCirclePrefix; extern const CFStringRef sRetirementPrefix; extern const CFStringRef sDebugInfoPrefix; +extern const CFStringRef sRingPrefix; SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key); bool SOSKVSKeyParse(SOSKVSKeyType keyType, CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to); diff --git a/keychain/SecureObjectSync/SOSMessage.c b/keychain/SecureObjectSync/SOSMessage.c index 97ab42db..f01b48da 100644 --- a/keychain/SecureObjectSync/SOSMessage.c +++ b/keychain/SecureObjectSync/SOSMessage.c @@ -443,13 +443,13 @@ bool SOSMessageAppendObject(SOSMessageRef message, CFDataRef object, CFErrorRef return true; } -static CC_NONNULL_ALL -size_t ccder_sizeof_bit_string(cc_size n, const cc_unit *s) { +static +size_t ccder_sizeof_bit_string(cc_size n, const cc_unit *_Nonnull s) { return ccder_sizeof(CCDER_BIT_STRING, ccn_sizeof(ccn_bitlen(n, s)) + 1); } -static CC_NONNULL_ALL -uint8_t *ccder_encode_bit_string(cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end) { +static +uint8_t *ccder_encode_bit_string(cc_size n, const cc_unit *_Nonnull s, const uint8_t *_Nonnull der, uint8_t *_Nonnull der_end) { size_t bits = ccn_bitlen(n, s); size_t out_size = ccn_sizeof(bits) + 1; der_end = ccder_encode_body_nocopy(out_size, der, der_end); @@ -467,8 +467,8 @@ size_t der_sizeof_implicit_data(ccder_tag tag, CFDataRef data) { } -static CC_NONNULL((3, 4)) -uint8_t *der_encode_implicit_data(ccder_tag tag, CFDataRef data, const uint8_t *der, uint8_t *der_end) { +static +uint8_t *der_encode_implicit_data(ccder_tag tag, CFDataRef data, const uint8_t *_Nonnull der, uint8_t *_Nonnull der_end) { if (!data) return der_end; return ccder_encode_implicit_raw_octet_string(tag, CFDataGetLength(data), CFDataGetBytePtr(data), der, der_end); @@ -765,8 +765,8 @@ CFDataRef SOSMessageCreateData(SOSMessageRef message, uint64_t sequenceNumber, C // Decode BER length field. Sets *lenp to ccber_indefinite_len if this is an indefinite length encoded object. // Behaves like ccder_decode_len in every other way. -static CC_NONNULL((1, 3)) -const uint8_t *ccber_decode_len(size_t *lenp, const uint8_t *der, const uint8_t *der_end) { +static +const uint8_t *ccber_decode_len(size_t *_Nonnull lenp, const uint8_t *_Nullable der, const uint8_t *_Nonnull der_end) { if (der && der < der_end) { if (*der == 0x80) { der++; @@ -793,8 +793,8 @@ static const uint8_t *der_decode_optional_generalizedtime(CFAbsoluteTime *at, CF return times_end ? times_end : der; } -static CC_NONNULL((2, 4)) -const uint8_t *ccder_decode_implicit_uint64(ccder_tag expected_tag, uint64_t* r, const uint8_t *der, const uint8_t *der_end) { +static +const uint8_t *ccder_decode_implicit_uint64(ccder_tag expected_tag, uint64_t *_Nonnull r, const uint8_t *_Nullable der, const uint8_t *_Nonnull der_end) { size_t len; der = ccder_decode_tl(expected_tag, &len, der, der_end); if (der && len && (*der & 0x80) != 0x80) { @@ -1155,7 +1155,7 @@ bool SOSMessageWithSOSObjects(SOSMessageRef message, SOSDataSourceRef dataSource const uint8_t *der = CFDataGetBytePtr(object); const uint8_t *der_end = der + CFDataGetLength(object); // TODO Remove intermediate plist format - der = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &plist, error, der, der_end); + der = der_decode_dictionary(kCFAllocatorDefault, &plist, error, der, der_end); if (der) { SOSObjectRef peersObject = SOSObjectCreateWithPropertyList(dataSource, plist, error); withObject(peersObject, stop); diff --git a/keychain/SecureObjectSync/SOSPeerInfo.h b/keychain/SecureObjectSync/SOSPeerInfo.h index 25389178..e7c78516 100644 --- a/keychain/SecureObjectSync/SOSPeerInfo.h +++ b/keychain/SecureObjectSync/SOSPeerInfo.h @@ -61,11 +61,15 @@ static inline SOSPeerInfoRef asSOSPeerInfo(CFTypeRef obj) { return isSOSPeerInfo(obj) ? (SOSPeerInfoRef) obj : NULL; } -SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, SecKeyRef signingKey, SecKeyRef octagonSigningKey, SecKeyRef octagonPeerEncryptionKey, CFErrorRef* error); +SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, SecKeyRef signingKey, + SecKeyRef octagonSigningKey, SecKeyRef octagonPeerEncryptionKey, bool supportsCKKS4All, + CFErrorRef* error); SOSPeerInfoRef SOSPeerInfoCreateWithTransportAndViews(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, CFStringRef IDSID, CFStringRef transportType, CFBooleanRef preferIDS, - CFBooleanRef preferFragmentation, CFBooleanRef preferAckModel, CFSetRef enabledViews, SecKeyRef signingKey, SecKeyRef octagonSigningKey, SecKeyRef octagonPeerEncryptionKey, CFErrorRef* error); + CFBooleanRef preferFragmentation, CFBooleanRef preferAckModel, CFSetRef enabledViews, SecKeyRef signingKey, + SecKeyRef octagonSigningKey, SecKeyRef octagonPeerEncryptionKey, bool supportsCKKS4All, + CFErrorRef* error); SOSPeerInfoRef SOSPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error); @@ -77,7 +81,6 @@ bool SOSPeerInfoVersionIsCurrent(SOSPeerInfoRef pi); bool SOSPeerInfoVersionHasV2Data(SOSPeerInfoRef pi); SOSPeerInfoRef SOSPeerInfoCopyWithGestaltUpdate(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error); SOSPeerInfoRef SOSPeerInfoCopyWithBackupKeyUpdate(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFDataRef backupKey, SecKeyRef signingKey, CFErrorRef* error); -SOSPeerInfoRef SOSPeerInfoCopyWithEscrowRecordUpdate(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFStringRef dsid, CFDictionaryRef escrowRecord, SecKeyRef signingKey, CFErrorRef *error); SOSPeerInfoRef SOSPeerInfoCopyWithReplacedEscrowRecords(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFDictionaryRef escrowRecords, SecKeyRef signingKey, CFErrorRef *error); @@ -104,7 +107,6 @@ CF_RETURNS_RETAINED CFDateRef SOSPeerInfoGetApplicationDate(SOSPeerInfoRef pi); // bool SOSPeerInfoHasBackupKey(SOSPeerInfoRef peer); CFDataRef SOSPeerInfoCopyBackupKey(SOSPeerInfoRef peer); -CFMutableDictionaryRef SOSPeerInfoCopyEscrowRecord(SOSPeerInfoRef peer); // // DER Import Export @@ -140,6 +142,8 @@ CFIndex SOSPeerInfoGetPeerProtocolVersion(SOSPeerInfoRef peer); // Stringified ID for this peer, not human readable. CFStringRef SOSPeerInfoGetPeerID(SOSPeerInfoRef peer); +CFStringRef SOSPeerInfoGetSPID(SOSPeerInfoRef pi); + bool SOSPeerInfoPeerIDEqual(SOSPeerInfoRef pi, CFStringRef myPeerID); CFIndex SOSPeerInfoGetVersion(SOSPeerInfoRef peer); @@ -155,7 +159,7 @@ CFTypeRef SOSPeerGestaltGetAnswer(CFDictionaryRef gestalt, CFStringRef question) SecKeyRef SOSPeerInfoCopyPubKey(SOSPeerInfoRef peer, CFErrorRef *error); SecKeyRef SOSPeerInfoCopyOctagonSigningPublicKey(SOSPeerInfoRef peer, CFErrorRef* error); SecKeyRef SOSPeerInfoCopyOctagonEncryptionPublicKey(SOSPeerInfoRef peer, CFErrorRef* error); -void SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octagonSigningKey, +bool SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octagonSigningKey, SecKeyRef octagonEncryptionKey, CFErrorRef *error); CFDataRef SOSPeerInfoGetAutoAcceptInfo(SOSPeerInfoRef peer); @@ -185,6 +189,9 @@ void SOSPeerInfoWithEnabledViewSet(SOSPeerInfoRef pi, void (^operation)(CFSetRef uint64_t SOSViewBitmaskFromSet(CFSetRef views); uint64_t SOSPeerInfoViewBitMask(SOSPeerInfoRef pi); +bool SOSPeerInfoSupportsCKKSForAll(SOSPeerInfoRef peerInfo); +void SOSPeerInfoSetSupportsCKKSForAll(SOSPeerInfoRef peerInfo, bool supports); + bool SOSPeerInfoKVSOnly(SOSPeerInfoRef pi); CFStringRef SOSPeerInfoCopyTransportType(SOSPeerInfoRef peer); CFStringRef SOSPeerInfoCopyDeviceID(SOSPeerInfoRef peer); diff --git a/keychain/SecureObjectSync/SOSPeerInfo.m b/keychain/SecureObjectSync/SOSPeerInfo.m index f75c3321..76937b5b 100644 --- a/keychain/SecureObjectSync/SOSPeerInfo.m +++ b/keychain/SecureObjectSync/SOSPeerInfo.m @@ -37,7 +37,6 @@ #include #include -#include #include #include @@ -98,6 +97,8 @@ CFStringRef sPreferIDSACKModel = CFSTR("PreferIDSAckModel"); CFStringRef sTransportType = CFSTR("TransportType"); CFStringRef sDeviceID = CFSTR("DeviceID"); +CFStringRef sCKKSForAll = CFSTR("CKKS4A"); + const CFStringRef peerIDLengthKey = CFSTR("idLength"); SOSPeerInfoRef SOSPeerInfoAllocate(CFAllocatorRef allocator) { @@ -158,10 +159,9 @@ static bool SOSDescriptionHash(SOSPeerInfoRef peer, const struct ccdigest_info * #define SIGLEN 128 static CFDataRef sosCopySignedHash(SecKeyRef privkey, const struct ccdigest_info *di, uint8_t *hbuf) { - OSStatus stat; size_t siglen = SIGLEN; uint8_t sig[siglen]; - if((stat = SecKeyRawSign(privkey, kSecPaddingNone, hbuf, di->output_size, sig, &siglen)) != 0) { + if(SecKeyRawSign(privkey, kSecPaddingNone, hbuf, di->output_size, sig, &siglen) != 0) { return NULL; } return CFDataCreate(NULL, sig, (CFIndex)siglen); @@ -230,6 +230,7 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, SecKeyRef signingKey, SecKeyRef octagonPeerSigningKey, SecKeyRef octagonPeerEncryptionKey, + bool supportsCKKS4All, CFErrorRef* error, void (^ description_modifier)(CFMutableDictionaryRef description)) { SOSPeerInfoRef pi = CFTypeAllocate(SOSPeerInfo, struct __OpaqueSOSPeerInfo, allocator); @@ -257,6 +258,7 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, goto exit; } + if (octagonPeerSigningKey) { SecKeyRef octagonPeerSigningPublicKey = SecKeyCreatePublicFromPrivate(octagonPeerSigningKey); if (octagonPeerSigningPublicKey == NULL) { @@ -311,6 +313,7 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, description_modifier(pi->description); pi->peerID = SOSCopyIDOfKey(publicKey, error); + pi->spid = CFStringCreateTruncatedCopy(pi->peerID, 8); pi->verifiedAppKeyID = NULL; pi->verifiedResult = false; @@ -328,6 +331,8 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, if (backup_key != NULL) SOSPeerInfoV2DictionarySetValue(pi, sBackupKeyKey, backup_key); SOSPeerInfoV2DictionarySetValue(pi, sViewsKey, enabledViews); + SOSPeerInfoSetSupportsCKKSForAll(pi, supportsCKKS4All); + // ================ V2 Additions End if (!SOSPeerInfoSign(signingKey, pi, error)) { @@ -344,8 +349,14 @@ exit: return pi; } -SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, SecKeyRef signingKey, SecKeyRef octagonPeerSigningKey, SecKeyRef octagonPeerEncryptionKey, CFErrorRef* error) { - return SOSPeerInfoCreate_Internal(allocator, gestalt, backup_key, NULL, NULL, NULL, NULL, NULL, NULL, signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, error, ^(CFMutableDictionaryRef description) {}); +SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, SecKeyRef signingKey, + SecKeyRef octagonPeerSigningKey, + SecKeyRef octagonPeerEncryptionKey, + bool supportsCKKS4All, + CFErrorRef* error) { + return SOSPeerInfoCreate_Internal(allocator, gestalt, backup_key, NULL, NULL, NULL, NULL, NULL, NULL, signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, + supportsCKKS4All, + error, ^(CFMutableDictionaryRef description) {}); } SOSPeerInfoRef SOSPeerInfoCreateWithTransportAndViews(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, @@ -354,14 +365,19 @@ SOSPeerInfoRef SOSPeerInfoCreateWithTransportAndViews(CFAllocatorRef allocator, SecKeyRef signingKey, SecKeyRef octagonPeerSigningKey, SecKeyRef octagonPeerEncryptionKey, + bool supportsCKKS4All, CFErrorRef* error) { - return SOSPeerInfoCreate_Internal(allocator, gestalt, backup_key, IDSID, transportType, preferIDS, preferFragmentation, preferAckModel, enabledViews, signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, error, ^(CFMutableDictionaryRef description) {}); + return SOSPeerInfoCreate_Internal(allocator, gestalt, backup_key, IDSID, transportType, preferIDS, preferFragmentation, preferAckModel, enabledViews, signingKey, + octagonPeerSigningKey, + octagonPeerEncryptionKey, + supportsCKKS4All, + error, ^(CFMutableDictionaryRef description) {}); } SOSPeerInfoRef SOSPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error) { - return SOSPeerInfoCreate_Internal(allocator, gestalt, NULL, NULL, NULL, NULL, NULL, NULL, NULL, signingKey, NULL, NULL, error, ^(CFMutableDictionaryRef description) { + return SOSPeerInfoCreate_Internal(allocator, gestalt, NULL, NULL, NULL, NULL, NULL, NULL, NULL, signingKey, NULL, NULL, false, error, ^(CFMutableDictionaryRef description) { CFDictionarySetValue(description, sCloudIdentityKey, kCFBooleanTrue); }); @@ -377,6 +393,7 @@ SOSPeerInfoRef SOSPeerInfoCreateCopy(CFAllocatorRef allocator, SOSPeerInfoRef to pi->gestalt = CFDictionaryCreateCopy(allocator, toCopy->gestalt); pi->peerID = CFStringCreateCopy(allocator, toCopy->peerID); + pi->spid = CFStringCreateCopy(allocator, toCopy->spid); pi->verifiedAppKeyID = NULL; // The peer resulting from this will need to be re-evaluated for an application signature. pi->verifiedResult = false; @@ -414,10 +431,10 @@ SOSPeerInfoRef SOSPeerInfoCreateCurrentCopy(CFAllocatorRef allocator, SOSPeerInf } -static SOSPeerInfoRef SOSPeerInfoCopyWithModification(CFAllocatorRef allocator, SOSPeerInfoRef original, - SecKeyRef signingKey, CFErrorRef *error, - bool (^modification)(SOSPeerInfoRef peerToModify, CFErrorRef *error)) { - +SOSPeerInfoRef SOSPeerInfoCopyWithModification(CFAllocatorRef allocator, SOSPeerInfoRef original, + SecKeyRef signingKey, CFErrorRef *error, + bool (^modification)(SOSPeerInfoRef peerToModify, CFErrorRef *error)) +{ SOSPeerInfoRef result = NULL; SOSPeerInfoRef copy = SOSPeerInfoCreateCopy(allocator, original, error); @@ -448,44 +465,19 @@ SOSPeerInfoRef SOSPeerInfoCopyWithGestaltUpdate(CFAllocatorRef allocator, SOSPee SOSPeerInfoRef SOSPeerInfoCopyWithBackupKeyUpdate(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFDataRef backupKey, SecKeyRef signingKey, CFErrorRef *error) { return SOSPeerInfoCopyWithModification(allocator, toCopy, signingKey, error, ^bool(SOSPeerInfoRef peerToModify, CFErrorRef *error) { - if (backupKey != NULL) + if (backupKey != NULL) { + CFStringRef shortHash = SOSCopyIDOfDataBufferWithLength(backupKey, 8, NULL); + secnotice("backup", "Setting peerInfo backupKey to %@", shortHash); + CFReleaseNull(shortHash); SOSPeerInfoV2DictionarySetValue(peerToModify, sBackupKeyKey, backupKey); - else + } else { + secnotice("backup", "Setting peerInfo backupKey to NULL"); SOSPeerInfoV2DictionaryRemoveValue(peerToModify, sBackupKeyKey); + } return true; }); } -static CFDictionaryRef SOSPeerInfoUpdateAndCopyRecord(SOSPeerInfoRef peer, CFStringRef dsid, CFDictionaryRef escrowRecord){ - - CFMutableDictionaryRef existingEscrowRecords = SOSPeerInfoCopyEscrowRecord(peer); - - if(escrowRecord == NULL && existingEscrowRecords != NULL) - { - CFDictionaryRemoveValue(existingEscrowRecords, dsid); - return existingEscrowRecords; - } - - if(existingEscrowRecords == NULL) - existingEscrowRecords = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - CFDictionarySetValue(existingEscrowRecords, dsid, escrowRecord); - - return existingEscrowRecords; -} - - -SOSPeerInfoRef SOSPeerInfoCopyWithEscrowRecordUpdate(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFStringRef dsid, CFDictionaryRef escrowRecord, SecKeyRef signingKey, CFErrorRef *error) { - return SOSPeerInfoCopyWithModification(allocator, toCopy, signingKey, error, - ^bool(SOSPeerInfoRef peerToModify, CFErrorRef *error) { - - CFDictionaryRef updatedEscrowRecords = SOSPeerInfoUpdateAndCopyRecord(peerToModify, dsid, escrowRecord); - SOSPeerInfoV2DictionarySetValue(peerToModify, sEscrowRecord, updatedEscrowRecords); - CFReleaseNull(updatedEscrowRecords); - return true; - }); -} - SOSPeerInfoRef SOSPeerInfoCopyWithReplacedEscrowRecords(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFDictionaryRef escrowRecords, SecKeyRef signingKey, CFErrorRef *error) { return SOSPeerInfoCopyWithModification(allocator, toCopy, signingKey, error, ^bool(SOSPeerInfoRef peerToModify, CFErrorRef *error) { @@ -500,10 +492,6 @@ CFDataRef SOSPeerInfoCopyBackupKey(SOSPeerInfoRef peer) { return SOSPeerInfoV2DictionaryCopyData(peer, sBackupKeyKey); } -CFMutableDictionaryRef SOSPeerInfoCopyEscrowRecord(SOSPeerInfoRef peer){ - return SOSPeerInfoV2DictionaryCopyDictionary(peer, sEscrowRecord); -} - bool SOSPeerInfoHasBackupKey(SOSPeerInfoRef peer) { CFDataRef bk = SOSPeerInfoCopyBackupKey(peer); bool success = bk != NULL; @@ -541,6 +529,7 @@ SOSPeerInfoRef SOSPeerInfoCopyWithPing(CFAllocatorRef allocator, SOSPeerInfoRef SecKeyRef pub_key = SOSPeerInfoCopyPubKey(pi, error); require_quiet(pub_key, exit); pi->peerID = SOSCopyIDOfKey(pub_key, error); + pi->spid = CFStringCreateTruncatedCopy(pi->peerID, 8); require_quiet(pi->peerID, exit); require_action_quiet(SOSPeerInfoSign(signingKey, pi, error), exit, CFReleaseNull(pi)); exit: @@ -562,8 +551,9 @@ static void SOSPeerInfoDestroy(CFTypeRef aObj) { CFReleaseNull(pi->signature); CFReleaseNull(pi->gestalt); CFReleaseNull(pi->peerID); - CFReleaseNull(pi->v2Dictionary); + CFReleaseNull(pi->spid); CFReleaseNull(pi->verifiedAppKeyID); + CFReleaseNull(pi->v2Dictionary); pi->verifiedResult = false; } @@ -643,19 +633,19 @@ static CFStringRef copyDescriptionWithFormatOptions(CFTypeRef aObj, CFDictionary bool selfValid = SOSPeerInfoVerify(pi, NULL); bool backingUp = SOSPeerInfoHasBackupKey(pi); bool isKVS = SOSPeerInfoKVSOnly(pi); + bool isCKKSForAll = SOSPeerInfoSupportsCKKSForAll(pi); CFStringRef osVersion = CFDictionaryGetValue(pi->gestalt, kPIOSVersionKey); CFStringRef tmp = SOSPeerInfoV2DictionaryCopyString(pi, sDeviceID); CFStringRef deviceID = CFStringCreateTruncatedCopy(tmp, 8); CFReleaseNull(tmp); CFStringRef serialNum = SOSPeerInfoCopySerialNumber(pi); - CFStringRef peerID = CFStringCreateTruncatedCopy(SOSPeerInfoGetPeerID(pi), 8); // Calculate the truncated length CFStringRef objectPrefix = CFStringCreateWithFormat(kCFAllocatorDefault, formatOptions, CFSTR("PI@%p"), pi); description = CFStringCreateWithFormat(kCFAllocatorDefault, formatOptions, - CFSTR("<%@: [name: %20@] [%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]"), + CFSTR("<%@: [name: %20@] [%c%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]"), objectPrefix, isKnown(SOSPeerInfoGetPeerName(pi)), '-', @@ -665,10 +655,10 @@ static CFStringRef copyDescriptionWithFormatOptions(CFTypeRef aObj, CFDictionary boolToChars(backingUp, 'B', 'b'), boolToChars(isKVS, 'K', 'I'), '-', - isKnown(SOSPeerInfoGetPeerDeviceType(pi)), isKnown(peerID), + boolToChars(isCKKSForAll, 'C', '_'), + isKnown(SOSPeerInfoGetPeerDeviceType(pi)), isKnown(SOSPeerInfoGetSPID(pi)), isKnown(osVersion), isKnown(deviceID), isKnown(serialNum)); - CFReleaseNull(peerID); CFReleaseNull(deviceID); CFReleaseNull(serialNum); CFReleaseNull(objectPrefix); @@ -694,25 +684,25 @@ void SOSPeerInfoLogState(char *category, SOSPeerInfoRef pi, SecKeyRef pubKey, CF bool backingUp = SOSPeerInfoHasBackupKey(pi); bool isMe = CFEqualSafe(SOSPeerInfoGetPeerID(pi), myPID) == true; bool isKVS = SOSPeerInfoKVSOnly(pi); + bool isCKKSForAll = SOSPeerInfoSupportsCKKSForAll(pi); CFStringRef osVersion = CFDictionaryGetValue(pi->gestalt, kPIOSVersionKey); CFStringRef tmp = SOSPeerInfoV2DictionaryCopyString(pi, sDeviceID); CFStringRef deviceID = CFStringCreateTruncatedCopy(tmp, 8); CFReleaseNull(tmp); CFStringRef serialNum = SOSPeerInfoCopySerialNumber(pi); - CFStringRef peerID = CFStringCreateTruncatedCopy(SOSPeerInfoGetPeerID(pi), 8); - secnotice(category, "PI: [name: %-20@] [%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]", isKnown(SOSPeerInfoGetPeerName(pi)), + secnotice(category, "PI: [name: %-20@] [%c%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]", isKnown(SOSPeerInfoGetPeerName(pi)), boolToChars(isMe, 'M', 'm'), boolToChars(appValid, 'A', 'a'), boolToChars(selfValid, 'S', 's'), boolToChars(retired, 'R', 'r'), boolToChars(backingUp, 'B', 'b'), boolToChars(isKVS, 'K', 'I'), + boolToChars(isCKKSForAll, 'C', '_'), sigchr, - isKnown(SOSPeerInfoGetPeerDeviceType(pi)), isKnown(peerID), + isKnown(SOSPeerInfoGetPeerDeviceType(pi)), isKnown(SOSPeerInfoGetSPID(pi)), isKnown(osVersion), isKnown(deviceID), isKnown(serialNum)); - CFReleaseNull(peerID); CFReleaseNull(deviceID); CFReleaseNull(serialNum); } @@ -750,6 +740,10 @@ CFStringRef SOSPeerInfoGetPeerID(SOSPeerInfoRef pi) { return pi ? pi->peerID : NULL; } +CFStringRef SOSPeerInfoGetSPID(SOSPeerInfoRef pi) { + return pi ? pi->spid : NULL; +} + bool SOSPeerInfoPeerIDEqual(SOSPeerInfoRef pi, CFStringRef myPeerID) { return CFEqualSafe(myPeerID, SOSPeerInfoGetPeerID(pi)); } @@ -814,7 +808,7 @@ static CFDataRef sosCreateDate() { static CFDateRef sosCreateCFDate(CFDataRef sosdate) { CFDateRef date; - der_decode_date(NULL, 0, &date, NULL, CFDataGetBytePtr(sosdate), + der_decode_date(NULL, &date, NULL, CFDataGetBytePtr(sosdate), CFDataGetBytePtr(sosdate) + CFDataGetLength(sosdate)); return date; } @@ -1017,9 +1011,10 @@ SOSPeerInfoRef SOSPeerInfoUpgradeSignatures(CFAllocatorRef allocator, SecKeyRef return retval; } -void SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octagonSigningKey, +bool SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octagonSigningKey, SecKeyRef octagonEncryptionKey, CFErrorRef *error) { + bool ret = false; CFDataRef signingPublicKeyBytes = NULL; CFDataRef encryptionPublicKeyBytes = NULL; @@ -1033,9 +1028,13 @@ void SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octa CFDictionarySetValue(peer->description, sOctagonPeerSigningPublicKeyKey, signingPublicKeyBytes); CFDictionarySetValue(peer->description, sOctagonPeerEncryptionPublicKeyKey, encryptionPublicKeyBytes); + ret = true; + fail: CFReleaseNull(signingPublicKeyBytes); CFReleaseNull(encryptionPublicKeyBytes); + + return ret; } diff --git a/keychain/SecureObjectSync/SOSPeerInfoCollections.c b/keychain/SecureObjectSync/SOSPeerInfoCollections.c index f4aa46db..93869b1a 100644 --- a/keychain/SecureObjectSync/SOSPeerInfoCollections.c +++ b/keychain/SecureObjectSync/SOSPeerInfoCollections.c @@ -103,7 +103,9 @@ SOSPeerInfoRef SOSPeerInfoSetFindByID(CFSetRef set, CFStringRef id) { void CFArrayOfSOSPeerInfosSortByID(CFMutableArrayRef peerInfoArray) { - CFArraySortValues(peerInfoArray, CFRangeMake(0, CFArrayGetCount(peerInfoArray)), SOSPeerInfoCompareByID, NULL); + if(peerInfoArray && CFArrayGetCount(peerInfoArray) > 0) { + CFArraySortValues(peerInfoArray, CFRangeMake(0, CFArrayGetCount(peerInfoArray)), SOSPeerInfoCompareByID, NULL); + } } diff --git a/keychain/SecureObjectSync/SOSPeerInfoDER.m b/keychain/SecureObjectSync/SOSPeerInfoDER.m index b71e7f93..a1bc10ff 100644 --- a/keychain/SecureObjectSync/SOSPeerInfoDER.m +++ b/keychain/SecureObjectSync/SOSPeerInfoDER.m @@ -77,8 +77,8 @@ SOSPeerInfoRef SOSPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* er pi->gestalt = NULL; pi->version = 0; // TODO: Encode this in the DER *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - *der_p = der_decode_plist(allocator, kCFPropertyListImmutable, &pl, error, *der_p, sequence_end); - *der_p = der_decode_data(allocator, kCFPropertyListImmutable, &pi->signature, error, *der_p, sequence_end); + *der_p = der_decode_plist(allocator, &pl, error, *der_p, sequence_end); + *der_p = der_decode_data(allocator, &pi->signature, error, *der_p, sequence_end); if (*der_p == NULL || *der_p != sequence_end) { SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Format of Peer Info DER"), NULL, error); @@ -134,7 +134,8 @@ SOSPeerInfoRef SOSPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* er pi->peerID = SOSCopyIDOfKey(pubKey, error); require_quiet(pi->peerID, fail); - + pi->spid = CFStringCreateTruncatedCopy(pi->peerID, 8); + if(pi->version >= 2) SOSPeerInfoExpandV2Data(pi, error); if(!SOSPeerInfoVerify(pi, error)) { diff --git a/keychain/SecureObjectSync/SOSPeerInfoPriv.h b/keychain/SecureObjectSync/SOSPeerInfoPriv.h index c216d2c0..c669ab0a 100644 --- a/keychain/SecureObjectSync/SOSPeerInfoPriv.h +++ b/keychain/SecureObjectSync/SOSPeerInfoPriv.h @@ -22,6 +22,7 @@ struct __OpaqueSOSPeerInfo { // Cached data CFDictionaryRef gestalt; CFStringRef peerID; + CFStringRef spid; CFIndex version; CFStringRef verifiedAppKeyID; bool verifiedResult; @@ -35,6 +36,10 @@ bool SOSPeerInfoSign(SecKeyRef privKey, SOSPeerInfoRef peer, CFErrorRef *error); bool SOSPeerInfoVerify(SOSPeerInfoRef peer, CFErrorRef *error); void SOSPeerInfoSetVersionNumber(SOSPeerInfoRef pi, int version); +SOSPeerInfoRef SOSPeerInfoCopyWithModification(CFAllocatorRef allocator, SOSPeerInfoRef original, + SecKeyRef signingKey, CFErrorRef *error, + bool (^modification)(SOSPeerInfoRef peerToModify, CFErrorRef *error)); + extern const CFStringRef peerIDLengthKey; #endif diff --git a/keychain/SecureObjectSync/SOSPeerInfoV2.h b/keychain/SecureObjectSync/SOSPeerInfoV2.h index d482b248..661699f8 100644 --- a/keychain/SecureObjectSync/SOSPeerInfoV2.h +++ b/keychain/SecureObjectSync/SOSPeerInfoV2.h @@ -30,6 +30,8 @@ extern CFStringRef sRingState; // Dictionary of Ring Membership extern CFStringRef sBackupKeyKey; extern CFStringRef sEscrowRecord; +extern CFStringRef sCKKSForAll; + bool SOSPeerInfoUpdateToV2(SOSPeerInfoRef pi, CFErrorRef *error); void SOSPeerInfoPackV2Data(SOSPeerInfoRef peer); bool SOSPeerInfoExpandV2Data(SOSPeerInfoRef pi, CFErrorRef *error); diff --git a/keychain/SecureObjectSync/SOSPeerInfoV2.m b/keychain/SecureObjectSync/SOSPeerInfoV2.m index 84eec8a6..d3a812fb 100644 --- a/keychain/SecureObjectSync/SOSPeerInfoV2.m +++ b/keychain/SecureObjectSync/SOSPeerInfoV2.m @@ -127,7 +127,7 @@ static CFMutableDictionaryRef SOSCreateDictionaryFromDER(CFDataRef v2Data, CFErr const uint8_t *der_p = CFDataGetBytePtr(v2Data); const uint8_t *der_end = CFDataGetLength(v2Data) + der_p; - der_p = der_decode_plist(NULL, kCFPropertyListImmutable, &pl, error, der_p, der_end); + der_p = der_decode_plist(NULL, &pl, error, der_p, der_end); if (der_p == NULL || der_p != der_end) { SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Format of Dictionary DER"), NULL, error); diff --git a/keychain/SecureObjectSync/SOSPeerOTRTimer.m b/keychain/SecureObjectSync/SOSPeerOTRTimer.m index 5562db28..f2f93a8b 100644 --- a/keychain/SecureObjectSync/SOSPeerOTRTimer.m +++ b/keychain/SecureObjectSync/SOSPeerOTRTimer.m @@ -15,17 +15,12 @@ #include "keychain/SecureObjectSync/SOSPeerOTRTimer.h" #include "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h" -#include #include #include #include #include "keychain/SecureObjectSync/SOSInternal.h" -//AGGD -NSString* const SecSOSAggdMaxRenegotiation = @"com.apple.security.sos.otrrenegotiationmaxretries"; - -__unused static int initialOTRTimeoutValue = 60; //best round trip time in KVS plus extra for good measure static int maxRetryCount = 7; //max number of times to attempt restarting OTR negotiation bool SOSPeerOTRTimerHaveReachedMaxRetryAllowance(SOSAccount* account, NSString* peerid){ @@ -38,7 +33,6 @@ bool SOSPeerOTRTimerHaveReachedMaxRetryAllowance(SOSAccount* account, NSString* if(attempt && [attempt intValue] >= maxRetryCount) { reachedMax = true; - SecADAddValueForScalarKey((__bridge CFStringRef) SecSOSAggdMaxRenegotiation,1); } return reachedMax; } diff --git a/keychain/SecureObjectSync/SOSPeerRateLimiter.m b/keychain/SecureObjectSync/SOSPeerRateLimiter.m index 15d756f9..104efeba 100644 --- a/keychain/SecureObjectSync/SOSPeerRateLimiter.m +++ b/keychain/SecureObjectSync/SOSPeerRateLimiter.m @@ -71,8 +71,7 @@ -(instancetype)initWithPeer:(SOSPeerRef)peer { - self = [super initWithConfig:[self setUpConfigForPeer]]; - if(self){ + if ((self = [super initWithConfig:[self setUpConfigForPeer]])) { self.peerID = (__bridge NSString *)(SOSPeerGetID(peer)); self.accessGroupRateLimitState = [[NSMutableDictionary alloc] init]; self.accessGroupToTimer = [[NSMutableDictionary alloc]init]; @@ -102,8 +101,7 @@ -(instancetype)initWithAccessGroup:(NSString *)accessGroup { - self = [super init]; - if(self){ + if ((self = [super init])) { _accessGroup = accessGroup; } return self; diff --git a/keychain/SecureObjectSync/SOSPiggyback.m b/keychain/SecureObjectSync/SOSPiggyback.m index 0234388f..5780234c 100644 --- a/keychain/SecureObjectSync/SOSPiggyback.m +++ b/keychain/SecureObjectSync/SOSPiggyback.m @@ -262,7 +262,7 @@ SOSPiggyCreateDecodedTLKs(const uint8_t *der, const uint8_t *der_end) CFErrorRef localError = NULL; CFStringRef string = NULL; - choice_der = der_decode_string(NULL, 0, &string, &localError, item_der, end_item_der); + choice_der = der_decode_string(NULL, &string, &localError, item_der, end_item_der); if (choice_der == NULL || string == NULL) { CFReleaseNull(string); secnotice("piggy", "Failed to parse view name"); @@ -365,7 +365,7 @@ SOSPiggyBackBlobCreateFromDER(SOSGenCountRef *retGencount, *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); require_action_quiet(sequence_end != NULL, errOut, SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Blob DER"), (error != NULL) ? *error : NULL, error)); - *der_p = der_decode_number(kCFAllocatorDefault, 0, &gencount, error, *der_p, sequence_end); + *der_p = der_decode_number(kCFAllocatorDefault, &gencount, error, *der_p, sequence_end); *der_p = der_decode_data_or_null(kCFAllocatorDefault, &publicBytes, error, *der_p, sequence_end); *der_p = der_decode_data_or_null(kCFAllocatorDefault, &signature, error, *der_p, sequence_end); diff --git a/keychain/SecureObjectSync/SOSRecoveryKeyBag.m b/keychain/SecureObjectSync/SOSRecoveryKeyBag.m index 5555949b..91abdc17 100644 --- a/keychain/SecureObjectSync/SOSRecoveryKeyBag.m +++ b/keychain/SecureObjectSync/SOSRecoveryKeyBag.m @@ -101,10 +101,10 @@ const uint8_t* der_decode_RecoveryKeyBag(CFAllocatorRef allocator, der = ccder_decode_sequence_tl(&sequence_end, der, der_end); require_quiet(sequence_end == der_end, fail); - der = der_decode_string(kCFAllocatorDefault, kCFPropertyListImmutable, &rb->accountDSID, error, der, sequence_end); + der = der_decode_string(kCFAllocatorDefault, &rb->accountDSID, error, der, sequence_end); rb->generation = SOSGenCountCreateFromDER(kCFAllocatorDefault, error, &der, sequence_end); der = ccder_decode_uint64(&rb->rkbVersion, der, sequence_end); - der = der_decode_data(allocator, kCFPropertyListImmutable, &rb->recoveryKeyBag, error, der, sequence_end); + der = der_decode_data(allocator, &rb->recoveryKeyBag, error, der, sequence_end); require_quiet(SecRequirementError(der == der_end, error, CFSTR("Extra space in sequence")), fail); if (RecoveryKeyBag) CFTransferRetained(*RecoveryKeyBag, rb); diff --git a/keychain/SecureObjectSync/SOSRing.h b/keychain/SecureObjectSync/SOSRing.h index 25dd226b..8c97f793 100644 --- a/keychain/SecureObjectSync/SOSRing.h +++ b/keychain/SecureObjectSync/SOSRing.h @@ -45,10 +45,6 @@ CFTypeID SOSRingGetTypeID(void); SOSRingRef SOSRingCreate(CFStringRef name, CFStringRef myPeerID, SOSRingType type, CFErrorRef *error); bool SOSRingResetToEmpty(SOSRingRef ring, CFStringRef myPeerID, CFErrorRef *error); -bool SOSRingResetToOffering(SOSRingRef ring, __unused SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error); -SOSRingStatus SOSRingDeviceIsInRing(SOSRingRef ring, CFStringRef peerID); -bool SOSRingApply(SOSRingRef ring, SecKeyRef user_pubkey, SOSFullPeerInfoRef requestor, CFErrorRef *error); -bool SOSRingWithdraw(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error); bool SOSRingGenerationSign(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error); bool SOSRingConcordanceSign(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error); SOSConcordanceStatus SOSRingConcordanceTrust(SOSFullPeerInfoRef me, CFSetRef peers, diff --git a/keychain/SecureObjectSync/SOSRingBackup.m b/keychain/SecureObjectSync/SOSRingBackup.m index 26582d44..1c9cba4c 100644 --- a/keychain/SecureObjectSync/SOSRingBackup.m +++ b/keychain/SecureObjectSync/SOSRingBackup.m @@ -24,7 +24,6 @@ #include #include -#include #include "SOSRingUtils.h" #include "SOSRingTypes.h" diff --git a/keychain/SecureObjectSync/SOSRingBasic.m b/keychain/SecureObjectSync/SOSRingBasic.m index 6c0cfa21..e2fea8b8 100644 --- a/keychain/SecureObjectSync/SOSRingBasic.m +++ b/keychain/SecureObjectSync/SOSRingBasic.m @@ -23,7 +23,6 @@ #include #include -#include #include "SOSRingUtils.h" #include "SOSRingTypes.h" diff --git a/keychain/SecureObjectSync/SOSRingConcordanceTrust.c b/keychain/SecureObjectSync/SOSRingConcordanceTrust.c index 2218db14..110aee53 100644 --- a/keychain/SecureObjectSync/SOSRingConcordanceTrust.c +++ b/keychain/SecureObjectSync/SOSRingConcordanceTrust.c @@ -34,7 +34,6 @@ #include #include -#include #include "SOSRing.h" #include "SOSRingUtils.h" diff --git a/keychain/SecureObjectSync/SOSRingDER.c b/keychain/SecureObjectSync/SOSRingDER.c index 66d6f70a..b53f54ad 100644 --- a/keychain/SecureObjectSync/SOSRingDER.c +++ b/keychain/SecureObjectSync/SOSRingDER.c @@ -35,7 +35,6 @@ #include #include -#include #include "SOSRingUtils.h" @@ -79,10 +78,10 @@ SOSRingRef SOSRingCreateFromDER(CFErrorRef* error, const uint8_t** der_p, const require_action_quiet(ring, errOut, secnotice("ring", "Unable to allocate ring")); *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - *der_p = der_decode_dictionary(ALLOCATOR, kCFPropertyListImmutable, &unSignedInformation, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(ALLOCATOR, kCFPropertyListImmutable, &signedInformation, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(ALLOCATOR, kCFPropertyListImmutable, &signatures, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(ALLOCATOR, kCFPropertyListImmutable, &data, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(ALLOCATOR, &unSignedInformation, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(ALLOCATOR, &signedInformation, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(ALLOCATOR, &signatures, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(ALLOCATOR, &data, error, *der_p, sequence_end); require_action_quiet(*der_p, errOut, secnotice("ring", "Unable to decode DER")); require_action_quiet(*der_p == der_end, errOut, secnotice("ring", "Unable to decode DER")); diff --git a/keychain/SecureObjectSync/SOSRingPeerInfoUtils.c b/keychain/SecureObjectSync/SOSRingPeerInfoUtils.c index a141de62..e18ddb0a 100644 --- a/keychain/SecureObjectSync/SOSRingPeerInfoUtils.c +++ b/keychain/SecureObjectSync/SOSRingPeerInfoUtils.c @@ -35,7 +35,6 @@ #include #include -#include #include "SOSRing.h" #include "SOSRingUtils.h" diff --git a/keychain/SecureObjectSync/SOSRingRecovery.m b/keychain/SecureObjectSync/SOSRingRecovery.m index 3a204d68..e513853c 100644 --- a/keychain/SecureObjectSync/SOSRingRecovery.m +++ b/keychain/SecureObjectSync/SOSRingRecovery.m @@ -47,7 +47,6 @@ #include #include -#include #include "SOSRingUtils.h" #include "SOSRingTypes.h" diff --git a/keychain/SecureObjectSync/SOSRingTypes.m b/keychain/SecureObjectSync/SOSRingTypes.m index 6a5ed6be..e7b6e995 100644 --- a/keychain/SecureObjectSync/SOSRingTypes.m +++ b/keychain/SecureObjectSync/SOSRingTypes.m @@ -80,63 +80,6 @@ bool SOSRingResetToEmpty(SOSRingRef ring, CFStringRef myPeerID, CFErrorRef *erro return ringTypes[type]->sosRingResetToEmpty(ring, myPeerID, error); } -bool SOSRingResetToOffering(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { - SOSRingAssertStable(ring); - SOSRingType type = SOSRingGetType(ring); - if(!SOSRingValidType(type)){ - SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); - return false; - } - if(!ringTypes[type]->sosRingResetToOffering){ - SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); - return false; - } - return ringTypes[type]->sosRingResetToOffering(ring, user_privkey, requestor, error); -} - -SOSRingStatus SOSRingDeviceIsInRing(SOSRingRef ring, CFStringRef peerID) { - SOSRingAssertStable(ring); - SOSRingType type = SOSRingGetType(ring); - if(!(SOSRingValidType(type))){ - return kSOSRingError; - } - if(!(ringTypes[type]->sosRingDeviceIsInRing)){ - return kSOSRingError; - } - return ringTypes[type]->sosRingDeviceIsInRing(ring, peerID); -} - -bool SOSRingApply(SOSRingRef ring, SecKeyRef user_pubkey, SOSFullPeerInfoRef fpi, CFErrorRef *error) { - SOSRingAssertStable(ring); - SOSRingType type = SOSRingGetType(ring); - if(!(SOSRingValidType(type))){ - SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); - return false; - } - if(!(ringTypes[type]->sosRingApply)){ - return true; - } - if(!(SOSPeerInfoApplicationVerify(SOSFullPeerInfoGetPeerInfo(fpi), user_pubkey, error))){ - SOSCreateError(kSOSErrorBadSignature, CFSTR("FullPeerInfo fails userkey signature check"), NULL, error); - return false; - } - - return ringTypes[type]->sosRingApply(ring, user_pubkey, fpi, error); -} - -bool SOSRingWithdraw(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { - SOSRingAssertStable(ring); - SOSRingType type = SOSRingGetType(ring); - if(!SOSRingValidType(type)){ - SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error); - return false; - } - if(!ringTypes[type]->sosRingWithdraw) - return true; - - return ringTypes[type]->sosRingWithdraw(ring, user_privkey, requestor, error); -} - bool SOSRingGenerationSign(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { SOSRingAssertStable(ring); SOSRingType type = SOSRingGetType(ring); diff --git a/keychain/SecureObjectSync/SOSRingUtils.c b/keychain/SecureObjectSync/SOSRingUtils.c index bb0d6221..86523787 100644 --- a/keychain/SecureObjectSync/SOSRingUtils.c +++ b/keychain/SecureObjectSync/SOSRingUtils.c @@ -54,7 +54,7 @@ #include #include -#include +#include #include "SOSRing.h" #include "SOSRingUtils.h" @@ -82,12 +82,6 @@ SOSRingRef SOSRingAllocate(void) { return (SOSRingRef) CFTypeAllocate(SOSRing, struct __OpaqueSOSRing, ALLOCATOR); } -__unused static bool addValueToDict(CFMutableDictionaryRef thedict, CFStringRef key, CFTypeRef value) { - if(!value) return false; - CFDictionaryAddValue(thedict, key, value); - return true; -} - static bool setValueInDict(CFMutableDictionaryRef thedict, CFStringRef key, CFTypeRef value) { if(!value) return false; CFDictionarySetValue(thedict, key, value); @@ -736,16 +730,18 @@ static CFStringRef CreateCommaSeparatedPeerIDs(CFSetRef peers) { __block bool addSeparator = false; - CFSetForEachPeerID(peers, ^(CFStringRef peerID) { - if (addSeparator) { - CFStringAppendCString(result, ", ", kCFStringEncodingUTF8); - } - CFStringRef spid = CFStringCreateTruncatedCopy(peerID, 8); - CFStringAppend(result, spid); - CFReleaseNull(spid); + if(peers) { + CFSetForEachPeerID(peers, ^(CFStringRef peerID) { + if (addSeparator) { + CFStringAppendCString(result, ", ", kCFStringEncodingUTF8); + } + CFStringRef spid = CFStringCreateTruncatedCopy(peerID, 8); + CFStringAppend(result, spid); + CFReleaseNull(spid); - addSeparator = true; - }); + addSeparator = true; + }); + } return result; } @@ -768,7 +764,7 @@ CFDictionaryRef SOSRingCopyPeerIDList(SOSRingRef ring) { CFStringRef SOSRingCopySignerList(SOSRingRef ring) { __block bool addSeparator = false; - CFMutableStringRef signers = CFStringCreateMutable(ALLOCATOR, 0); + CFMutableStringRef signers = CFStringCreateMutable(ALLOCATOR, 0); CFDictionaryForEach(ring->signatures, ^(const void *key, const void *value) { CFStringRef peerID = (CFStringRef) key; CFStringRef spid = CFStringCreateTruncatedCopy(peerID, 8); diff --git a/keychain/SecureObjectSync/SOSRingV0.m b/keychain/SecureObjectSync/SOSRingV0.m index 84579836..e070bd93 100644 --- a/keychain/SecureObjectSync/SOSRingV0.m +++ b/keychain/SecureObjectSync/SOSRingV0.m @@ -23,7 +23,6 @@ #include #include -#include #include "SOSRingUtils.h" #include "SOSRingTypes.h" @@ -117,23 +116,6 @@ static bool SOSRingConcordanceSign_V0(SOSRingRef ring, SOSFullPeerInfoRef reques } -__unused static bool SOSRingSetPayload_V0(SOSRingRef ring, SecKeyRef user_privkey, CFDataRef payload, SOSFullPeerInfoRef requestor, CFErrorRef *error) { - CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor)); - SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error); - bool retval = priv && myPeerID && - SOSRingSetLastModifier(ring, myPeerID) && - SOSRingSetPayload_Internal(ring, payload) && - SOSRingGenerationSign_Internal(ring, priv, error); - if(user_privkey) SOSRingConcordanceSign_Internal(ring, user_privkey, error); - CFReleaseNull(priv); - return retval; -} - -__unused static CFDataRef SOSRingGetPayload_V0(SOSRingRef ring, CFErrorRef *error) { - return SOSRingGetPayload_Internal(ring); -} - - ringFuncStruct ringsV0 = { "V0", 1, diff --git a/keychain/SecureObjectSync/SOSTransport.m b/keychain/SecureObjectSync/SOSTransport.m index ce9a8d82..4bdfe17c 100644 --- a/keychain/SecureObjectSync/SOSTransport.m +++ b/keychain/SecureObjectSync/SOSTransport.m @@ -206,7 +206,7 @@ void SOSUpdateKeyInterest(SOSAccount* account) secnotice("key-interests", "Updating interests done: %lu", (unsigned long)itemCount); CFStringRef uuid = SOSAccountCopyUUID(account); - SOSCloudKeychainUpdateKeys(keyDict, uuid, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) { + SOSCloudKeychainUpdateKeys(keyDict, uuid, dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) { if (error) { secerror("Error updating keys: %@", error); account.key_interests_need_updating = true; diff --git a/keychain/SecureObjectSync/SOSTransportCircle.m b/keychain/SecureObjectSync/SOSTransportCircle.m index 49145ab1..d58a85e1 100644 --- a/keychain/SecureObjectSync/SOSTransportCircle.m +++ b/keychain/SecureObjectSync/SOSTransportCircle.m @@ -12,8 +12,7 @@ } -(SOSCircleStorageTransport*) initWithAccount:(SOSAccount*)acct { - self = [super init]; - if(self){ + if ((self = [super init])) { self.account = acct; } return self; diff --git a/keychain/SecureObjectSync/SOSTransportCircleCK.m b/keychain/SecureObjectSync/SOSTransportCircleCK.m index 2e3a4cc5..4e82d116 100644 --- a/keychain/SecureObjectSync/SOSTransportCircleCK.m +++ b/keychain/SecureObjectSync/SOSTransportCircleCK.m @@ -15,8 +15,7 @@ -(id) init { - self = [super init]; - if(self){ + if ((self = [super init])) { SOSRegisterTransportCircle(self); } return self; @@ -24,9 +23,7 @@ -(id) initWithAccount:(SOSAccount*)acct { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.account = acct; } return self; diff --git a/keychain/SecureObjectSync/SOSTransportCircleKVS.m b/keychain/SecureObjectSync/SOSTransportCircleKVS.m index d3237e81..1077f639 100644 --- a/keychain/SecureObjectSync/SOSTransportCircleKVS.m +++ b/keychain/SecureObjectSync/SOSTransportCircleKVS.m @@ -25,8 +25,7 @@ extern CFStringRef kSOSAccountDebugScope; -(id)initWithAccount:(SOSAccount*)acct andCircleName:(NSString*)name { - self = [super init]; - if(self){ + if ((self = [super init])) { self.pending_changes = [NSMutableDictionary dictionary]; self.circleName = [[NSString alloc] initWithString:name]; self.account = acct; @@ -52,7 +51,7 @@ static bool SOSTransportCircleKVSUpdateKVS(NSDictionary *changes, CFErrorRef *er } }; - SOSCloudKeychainPutObjectsInCloud((__bridge CFDictionaryRef)(changes), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); + SOSCloudKeychainPutObjectsInCloud((__bridge CFDictionaryRef)(changes), dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), log_error); return true; } diff --git a/keychain/SecureObjectSync/SOSTransportKeyParameter.m b/keychain/SecureObjectSync/SOSTransportKeyParameter.m index 84b1bf27..25ccd6bb 100644 --- a/keychain/SecureObjectSync/SOSTransportKeyParameter.m +++ b/keychain/SecureObjectSync/SOSTransportKeyParameter.m @@ -35,8 +35,7 @@ -(id) initWithAccount:(SOSAccount*) acct { - self = [super init]; - if(self){ + if ((self = [super init])) { self.account = acct; SOSRegisterTransportKeyParameter(self); } @@ -57,7 +56,7 @@ static bool SOSTransportKeyParameterKVSUpdateKVS(CFDictionaryRef changes, CFErro } }; - SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); + SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), log_error); return true; } diff --git a/keychain/SecureObjectSync/SOSTransportMessage.m b/keychain/SecureObjectSync/SOSTransportMessage.m index 407c5543..1e6b247f 100644 --- a/keychain/SecureObjectSync/SOSTransportMessage.m +++ b/keychain/SecureObjectSync/SOSTransportMessage.m @@ -5,8 +5,8 @@ #include "keychain/SecureObjectSync/SOSEngine.h" #import "keychain/SecureObjectSync/SOSPeerRateLimiter.h" #import "keychain/SecureObjectSync/SOSPeerOTRTimer.h" -#include +#import "utilities/SecCoreAnalytics.h" #include #include #include "keychain/SecureObjectSync/SOSInternal.h" @@ -29,8 +29,7 @@ static const CFStringRef kSecAccessGroupCKKS = CFSTR("com.apple. -(id) initWithAccount:(SOSAccount*)acct andName:(NSString*)name { - self = [super init]; - if(self){ + if ((self = [super init])) { SOSEngineRef e = SOSDataSourceFactoryGetEngineForDataSourceName(acct.factory, (__bridge CFStringRef)name, NULL); engine = e; account = acct; @@ -89,6 +88,12 @@ static const CFStringRef kSecAccessGroupCKKS = CFSTR("com.apple. bool SOSEngineHandleCodedMessage(SOSAccount* account, SOSEngineRef engine, CFStringRef peerID, CFDataRef codedMessage, CFErrorRef*error) { __block bool result = true; __block bool somethingChanged = false; + + if(account && account.accountIsChanging) { + secnotice("engine", "SOSEngineHandleCodedMessage called before signing in to new account"); + return true; // we want to drop sync message notifications when account is changing + } + result &= SOSEngineWithPeerID(engine, peerID, error, ^(SOSPeerRef peer, SOSCoderRef coder, SOSDataSourceRef dataSource, SOSTransactionRef txn, bool *shouldSave) { CFDataRef decodedMessage = NULL; enum SOSCoderUnwrapStatus uwstatus = SOSPeerHandleCoderMessage(peer, coder, peerID, codedMessage, &decodedMessage, shouldSave, error); @@ -188,8 +193,8 @@ bool SOSEngineHandleCodedMessage(SOSAccount* account, SOSEngineRef engine, CFStr secnotice("otrtimer","peerID: %@ current date: %@, stored date: %@", peerid, currentDate, storedDate); secnotice("otrtimer", "rtt: %d", rtt); [self SOSTransportMessageCalculateNextTimer:account rtt:rtt peerid:peerid]; - - SecADClientPushValueForDistributionKey(kSecSOSMessageRTT, rtt); + + [SecCoreAnalytics sendEvent:(__bridge id)kSecSOSMessageRTT event:@{SecCoreAnalyticsValue: [NSNumber numberWithUnsignedInt:rtt]}]; [peerToTimeLastSentDict removeObjectForKey:peerid]; //remove last sent message date SOSAccountSetValue(account, kSOSAccountPeerLastSentTimestamp, (__bridge CFMutableDictionaryRef)peerToTimeLastSentDict, NULL); } diff --git a/keychain/SecureObjectSync/SOSTransportMessageKVS.m b/keychain/SecureObjectSync/SOSTransportMessageKVS.m index 68af1835..5d785ed9 100644 --- a/keychain/SecureObjectSync/SOSTransportMessageKVS.m +++ b/keychain/SecureObjectSync/SOSTransportMessageKVS.m @@ -3,7 +3,6 @@ #import "keychain/SecureObjectSync/SOSTransportMessageKVS.h" #include "keychain/SecureObjectSync/SOSKVSKeys.h" #include -#include #include "keychain/SecureObjectSync/SOSInternal.h" #include #include "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h" @@ -14,9 +13,7 @@ -(id) initWithAccount:(SOSAccount*)acct andName:(NSString*)name { - self = [super init]; - - if (self) { + if ((self = [super init])) { account = acct; circleName = [[NSString alloc]initWithString:name]; SOSEngineRef e = SOSDataSourceFactoryGetEngineForDataSourceName(acct.factory, (__bridge CFStringRef)(circleName), NULL); @@ -83,16 +80,13 @@ fail: } static bool SOSTransportMessageKVSUpdateKVS(SOSMessageKVS* transport, CFDictionaryRef changes, CFErrorRef *error){ - - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.sendkvs"), 1); - CloudKeychainReplyBlock log_error = ^(CFDictionaryRef returnedValues __unused, CFErrorRef block_error) { if (block_error) { secerror("Error putting: %@", block_error); } }; - SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); + SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), log_error); return true; } diff --git a/keychain/SecureObjectSync/SOSTypes.h b/keychain/SecureObjectSync/SOSTypes.h index a9e748ae..12ed9cf5 100644 --- a/keychain/SecureObjectSync/SOSTypes.h +++ b/keychain/SecureObjectSync/SOSTypes.h @@ -116,6 +116,8 @@ typedef NS_OPTIONS(uint32_t, SOSAccountGhostBustingOptions) { - (void)ghostBustPeriodic:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool busted, NSError *error))complete; - (void)ghostBustTriggerTimed:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool ghostBusted, NSError *error))complete; - (void)ghostBustInfo: (void(^)(NSData *json, NSError *error))complete; +- (void)iCloudIdentityStatus_internal: (void(^)(NSDictionary *tableSpid, NSError *error))complete; +- (void)iCloudIdentityStatus: (void (^)(NSData *json, NSError *error))complete; - (void)myPeerInfo:(void (^)(NSData *, NSError *))complete; - (void)circleHash:(void (^)(NSString *, NSError *))complete; @@ -132,6 +134,8 @@ typedef NS_OPTIONS(uint32_t, SOSAccountGhostBustingOptions) { - (void)rpcTriggerBackup:(NSArray*)backupPeers complete:(void (^)(NSError *error))complete; - (void)rpcTriggerRingUpdate:(void (^)(NSError *error))complete; +- (void)removeV0Peers:(void(^)(bool removedV0Peer, NSError *error))reply; + @end #endif diff --git a/keychain/SecureObjectSync/SOSUserKeygen.m b/keychain/SecureObjectSync/SOSUserKeygen.m index 5e466ae7..a8ab22b3 100644 --- a/keychain/SecureObjectSync/SOSUserKeygen.m +++ b/keychain/SecureObjectSync/SOSUserKeygen.m @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -197,8 +196,8 @@ CFDataRef SOSUserKeyCreateGenerateParameters(CFErrorRef *error) { size_t iterations = ITERATIONMIN; size_t keysize = 256; - if(CCRandomCopyBytes(kCCRandomDefault, salt, sizeof(salt)) != kCCSuccess) { - SOSCreateError(kSOSErrorProcessingFailure, CFSTR("CCRandomCopyBytes failed"), NULL, error); + if (SecRandomCopyBytes(NULL, sizeof(salt), salt) != 0) { + SOSCreateError(kSOSErrorProcessingFailure, CFSTR("SecRandomCopyBytes failed"), NULL, error); return NULL; } @@ -213,7 +212,7 @@ CFDataRef SOSUserKeyCreateGenerateParameters(CFErrorRef *error) { CFReleaseNull(result); if (result) { - secnotice("circleOps", "Created new parameters: iterations %zd, keysize %zd: %@", iterations, keysize, result); + debugDumpUserParameters(CFSTR("SOSUserKeyCreateGenerateParameters created new parameters:"), result); } return result; @@ -259,7 +258,7 @@ SecKeyRef SOSUserKeygen(CFDataRef password, CFDataRef parameters, CFErrorRef *er ccec_const_cp_t cp = ccec_get_cp(keysize); ccec_full_ctx_decl_cp(cp, tmpkey); - secnotice("circleOps", "Generating key for: iterations %zd, keysize %zd: %@", iterations, keysize, parameters); + debugDumpUserParameters(CFSTR("SOSUserKeygen generating key for:"), parameters); size_t drbg_output_size=128; uint8_t drbg_output[drbg_output_size]; @@ -297,51 +296,28 @@ void debugDumpUserParameters(CFStringRef message, CFDataRef parameters) CF_RETURNS_RETAINED CFStringRef UserParametersDescription(CFDataRef parameters){ - __block CFStringRef description = NULL; - CFDataRef newParameters = NULL; - SecKeyRef newKey = NULL; - - CFErrorRef error = NULL; - const uint8_t *parse_end = der_decode_cloud_parameters(kCFAllocatorDefault, kSecECDSAAlgorithmID, - &newKey, &newParameters, &error, - CFDataGetBytePtr(parameters), CFDataGetPastEndPtr(parameters)); - - if (parse_end != CFDataGetPastEndPtr(parameters)){ - secdebug("circleOps", "failed to decode cloud parameters"); - CFReleaseNull(newParameters); - CFReleaseNull(newKey); + if(parameters == NULL) { return NULL; } - + __block CFStringRef description = NULL; size_t saltlen = 0; const uint8_t *salt = NULL; - size_t iterations = 0; size_t keysize = 0; - const uint8_t *der = CFDataGetBytePtr(newParameters); - const uint8_t *der_end = der + CFDataGetLength(newParameters); + const uint8_t *der = CFDataGetBytePtr(parameters); + const uint8_t *der_end = der + CFDataGetLength(parameters); der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end); - if (der != NULL) { + if (der != der_end) { secdebug("circleOps", "failed to decode pbkdf2 params"); - CFReleaseNull(newParameters); - CFReleaseNull(newKey); return NULL; } - - CFStringRef userPubKeyID = SOSCopyIDOfKeyWithLength(newKey, 8, NULL); - + BufferPerformWithHexString(salt, 4, ^(CFStringRef saltHex) { // Only dump 4 bytes worth of salthex - CFDataPerformWithHexString(newParameters, ^(CFStringRef parametersHex) { - description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(" "), iterations, keysize, saltHex, userPubKeyID); - }); + description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), iterations, keysize, saltHex); }); - - CFReleaseNull(newParameters); - CFReleaseNull(newKey); - CFReleaseNull(userPubKeyID); - + return description; } diff --git a/keychain/SecureObjectSync/SOSViews.h b/keychain/SecureObjectSync/SOSViews.h index e3692d24..134032ea 100644 --- a/keychain/SecureObjectSync/SOSViews.h +++ b/keychain/SecureObjectSync/SOSViews.h @@ -93,11 +93,10 @@ CFSetRef SOSViewCreateSetFromBitmask(uint64_t bitmask); void SOSViewsSetTestViewsSet(CFSetRef testViewNames); -static inline bool SOSPeerInfoIsViewPermitted(SOSPeerInfoRef peerInfo, CFStringRef viewName) { - SOSViewResultCode viewResult = SOSViewsQuery(peerInfo, viewName, NULL); - - return kSOSCCViewMember == viewResult || kSOSCCViewPending == viewResult || kSOSCCViewNotMember == viewResult; -} +bool SOSViewSetIntersectsV0(CFSetRef theSet); +bool SOSPeerInfoV0ViewsEnabled(SOSPeerInfoRef pi); + +bool SOSPeerInfoIsViewPermitted(SOSPeerInfoRef peerInfo, CFStringRef viewName); const char *SOSViewsXlateAction(SOSViewActionCode action); /* CFSet <-> XPC functions */ diff --git a/keychain/SecureObjectSync/SOSViews.m b/keychain/SecureObjectSync/SOSViews.m index 4098335d..97fe544e 100644 --- a/keychain/SecureObjectSync/SOSViews.m +++ b/keychain/SecureObjectSync/SOSViews.m @@ -306,6 +306,26 @@ CFSetRef SOSViewCreateSetFromBitmask(uint64_t bitmask) { return retval; } +bool SOSPeerInfoSupportsCKKSForAll(SOSPeerInfoRef peerInfo) { + if(!peerInfo) { + return false; + } + + bool ret = false; + CFBooleanRef value = SOSPeerInfoV2DictionaryCopyBoolean(peerInfo, sCKKSForAll); + + if(value) { + ret = CFBooleanGetValue(value) ? true : false; + } + + CFReleaseNull(value); + return ret; +} + +void SOSPeerInfoSetSupportsCKKSForAll(SOSPeerInfoRef peerInfo, bool supports) { + return SOSPeerInfoV2DictionarySetValue(peerInfo, sCKKSForAll, supports ? kCFBooleanTrue : kCFBooleanFalse); +} + const char *SOSViewsXlateAction(SOSViewActionCode action) { switch(action) { case kSOSCCViewEnable: return "kSOSCCViewEnable"; @@ -386,6 +406,9 @@ static void SOSPeerInfoSetViews(SOSPeerInfoRef pi, CFSetRef newviews) { } static bool SOSPeerInfoViewIsValid(SOSPeerInfoRef pi, CFStringRef viewname) { + if(SOSViewsIsV0Subview(viewname) && SOSVisibleKeychainNotAllowed()) { + return false; + } return true; } @@ -479,7 +502,6 @@ errOut: return removed; } - SOSViewResultCode SOSViewsQuery(SOSPeerInfoRef pi, CFStringRef viewname, CFErrorRef *error) { SOSViewResultCode retval = kSOSCCNoSuchView; CFSetRef views = NULL; @@ -510,10 +532,30 @@ fail: return retval; } +bool SOSPeerInfoIsViewPermitted(SOSPeerInfoRef peerInfo, CFStringRef viewName) { + if(SOSViewsIsV0Subview(viewName) && SOSVisibleKeychainNotAllowed()) { + return false; + } + + SOSViewResultCode viewResult = SOSViewsQuery(peerInfo, viewName, NULL); + + return kSOSCCViewMember == viewResult || kSOSCCViewPending == viewResult || kSOSCCViewNotMember == viewResult; +} /* Need XPC way to carry CFSets of views */ +bool SOSViewSetIntersectsV0(CFSetRef theSet) { + return CFSetIntersects(theSet, SOSViewsGetV0ViewSet()); +} - +bool SOSPeerInfoV0ViewsEnabled(SOSPeerInfoRef pi) { + if(!pi) { + return false; + } + CFSetRef piViews = SOSPeerInfoCopyEnabledViews(pi); + bool retval = SOSViewSetIntersectsV0(piViews); + CFReleaseNull(piViews); + return retval; +} xpc_object_t CreateXPCObjectWithCFSetRef(CFSetRef setref, CFErrorRef *error) { xpc_object_t result = NULL; diff --git a/keychain/SecureObjectSync/Tool/accountCirclesViewsPrint.m b/keychain/SecureObjectSync/Tool/accountCirclesViewsPrint.m index 9cdf7d3a..b9d0db31 100644 --- a/keychain/SecureObjectSync/Tool/accountCirclesViewsPrint.m +++ b/keychain/SecureObjectSync/Tool/accountCirclesViewsPrint.m @@ -149,7 +149,8 @@ static void printPeerInfos(char *label, CFStringRef mypeerID, CFArrayRef (^copyP CFStringRef bufstr = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); CFStringRef pid = SOSPeerInfoGetPeerID(peer); CFIndex vers = SOSPeerInfoGetVersion(peer); - printmsg(CFSTR("%@ pid:%@ V%d OS:%@\n"), bufstr, pid, vers, osVersion ?: CFSTR("")); + bool isCKKSForAll = SOSPeerInfoSupportsCKKSForAll(peer); + printmsg(CFSTR("%@ pid:%@ V%d %@ OS:%@\n"), bufstr, pid, vers, isCKKSForAll ? CFSTR("c4a") : CFSTR("SOS"), osVersion ?: CFSTR("")); CFRelease(bufstr); CFReleaseNull(gestalt); diff --git a/keychain/SecureObjectSync/Tool/keychain_sync.h b/keychain/SecureObjectSync/Tool/keychain_sync.h index 141de9d9..6d7d9ec5 100644 --- a/keychain/SecureObjectSync/Tool/keychain_sync.h +++ b/keychain/SecureObjectSync/Tool/keychain_sync.h @@ -35,28 +35,14 @@ SECURITY_COMMAND( "\n" "Account/Circle Management\n" " -a accept all applicants\n" - " -l [reason] sign out of circle + set custom departure reason\n" - " -q sign out of circle\n" " -r reject all applicants\n" - " -E ensure fresh parameters\n" " -b device|all|single Register a backup bag - THIS RESETS BACKUPS!\n" - " -A Apply to a ring\n" - " -B Withdrawl from a ring\n" - " -G Enable Ring\n" - " -F Ring Status\n" - " -I Dump Ring Information\n" " -N (re-)set to new account (USE WITH CARE: device will not leave circle before resetting account!)\n" " -O reset to offering\n" " -R reset circle\n" - " -X [limit] best effort bail from circle in limit seconds\n" " -o list view unaware peers in circle\n" " -0 boot view unaware peers from circle\n" - " -1 grab account state from the keychain\n" - " -2 delete account state from the keychain\n" - " -3 grab engine state from the keychain\n" - " -4 delete engine state from the keychain\n" " -5 cleanup old KVS keys in KVS\n" - " -6 [test]populate KVS with garbage KVS keys\n" "\n" "Circle Tools\n" " --remove-peer SPID Remove a peer identified by the first 8 or more\n" @@ -79,9 +65,7 @@ SECURITY_COMMAND( " wifi|passwords|creditcards|icloudidentity|othersyncable\n" " -L list all known view and their status\n" " -U purge private key material cache\n" - " -V Report View Sync Status on all known clients.\n" - " -Y Report yet to initial sync views\n" - " -H Set escrow record.\n" - " -J Get the escrow record.\n" - " -M Check peer availability.\n", + " -V Report View Sync Status on all known clients.\n", "Keychain Syncing controls." ) + + diff --git a/keychain/SecureObjectSync/Tool/keychain_sync.m b/keychain/SecureObjectSync/Tool/keychain_sync.m index 4d17e4e5..e545b84e 100644 --- a/keychain/SecureObjectSync/Tool/keychain_sync.m +++ b/keychain/SecureObjectSync/Tool/keychain_sync.m @@ -59,7 +59,6 @@ #include "keychain_sync.h" #include "keychain_log.h" -#include "syncbackup.h" #include "secToolFileIO.h" #include "secViewDisplay.h" @@ -329,30 +328,6 @@ static bool clientViewStatus(CFErrorRef *error) { return false; } - -static bool dumpYetToSync(CFErrorRef *error) { - CFArrayRef yetToSyncViews = SOSCCCopyYetToSyncViewsList(error); - - bool hadError = yetToSyncViews; - - if (yetToSyncViews) { - __block CFStringRef separator = CFSTR(""); - - printmsg(CFSTR("Yet to sync views: ["), NULL); - - CFArrayForEach(yetToSyncViews, ^(const void *value) { - if (isString(value)) { - printmsg(CFSTR("%@%@"), separator, value); - - separator = CFSTR(", "); - } - }); - printmsg(CFSTR("]\n"), NULL); - } - - return !hadError; -} - #pragma mark - #pragma mark --remove-peer @@ -468,30 +443,20 @@ keychain_sync(int argc, char * const *argv) " "Account/Circle Management" " -a accept all applicants" - " -l [reason] sign out of circle + set custom departure reason" - " -q sign out of circle" " -r reject all applicants" - " -E ensure fresh parameters" " -b device|all|single Register a backup bag - THIS RESETS BACKUPS!\n" - " -A Apply to a ring\n" - " -B Withdrawl from a ring\n" - " -G Enable Ring\n" - " -F Ring Status\n" - " -I Dump Ring Information\n" " -N (re-)set to new account (USE WITH CARE: device will not leave circle before resetting account!)" " -O reset to offering" " -R reset circle" - " -X [limit] best effort bail from circle in limit seconds" " -o list view unaware peers in circle" " -0 boot view unaware peers from circle" - " -1 grab account state from the keychain" - " -2 delete account state from the keychain" - " -3 grab engine state from the keychain" - " -4 delete engine state from the keychain" " -5 cleanup old KVS keys in KVS" - " -6 [test]populate KVS with garbage KVS keys " + "Circle Tools\n" + " --remove-peer SPID Remove a peer identified by the first 8 or more\n" + " characters of its spid. Specify multiple times to\n" + " remove more than one peer.\n" "Password" " -P [label:]password set password (optionally for a given label) for sync" " -T [label:]password try password (optionally for a given label) for sync" @@ -509,9 +474,6 @@ keychain_sync(int argc, char * const *argv) " -L list all known view and their status" " -U purge private key material cache\n" " -V Report View Sync Status on all known clients.\n" - " -H Set escrow record.\n" - " -J Get the escrow record.\n" - " -M Check peer availability.\n" */ enum { SYNC_REMOVE_PEER, @@ -527,358 +489,170 @@ keychain_sync(int argc, char * const *argv) CFMutableArrayRef peers2remove = NULL; SOSLogSetOutputTo(NULL, NULL); - while ((ch = getopt_long(argc, argv, "ab:deg:hikl:mopq:rSv:w:x:zA:B:MNJCDEF:HG:ILOP:RT:UWX:VY0123456", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "ab:deikmorv:NCDLOP:RT:UWV05", longopts, NULL)) != -1) { switch (ch) { - case 'l': - { - fprintf(outFile, "Signing out of circle\n"); - hadError = !SOSCCSignedOut(true, &error); - if (!hadError) { - errno = 0; - int reason = (int) strtoul(optarg, NULL, 10); - if (errno != 0 || - reason < kSOSDepartureReasonError || - reason >= kSOSNumDepartureReasons) { - fprintf(errFile, "Invalid custom departure reason %s\n", optarg); - } else { - fprintf(outFile, "Setting custom departure reason %d\n", reason); - hadError = !SOSCCSetLastDepartureReason(reason, &error); - notify_post(kSOSCCCircleChangedNotification); - } - } - break; - } - - case 'q': - { - fprintf(outFile, "Signing out of circle\n"); - bool signOutImmediately = false; - if (strcasecmp(optarg, "true") == 0) { - signOutImmediately = true; - } else if (strcasecmp(optarg, "false") == 0) { - signOutImmediately = false; - } else { - fprintf(outFile, "Please provide a \"true\" or \"false\" whether you'd like to leave the circle immediately\n"); - } - hadError = !SOSCCSignedOut(signOutImmediately, &error); - notify_post(kSOSCCCircleChangedNotification); - break; - } - case 'e': - fprintf(outFile, "Turning ON keychain syncing\n"); - hadError = requestToJoinCircle(&error); - break; - - case 'd': - fprintf(outFile, "Turning OFF keychain syncing\n"); - hadError = !SOSCCRemoveThisDeviceFromCircle(&error); - break; - - case 'a': - { - CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL); - if (applicants) { - hadError = !SOSCCAcceptApplicants(applicants, &error); - CFRelease(applicants); - } else { - fprintf(errFile, "No applicants to accept\n"); - } - break; - } - - case 'r': - { - CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL); - if (applicants) { - hadError = !SOSCCRejectApplicants(applicants, &error); - CFRelease(applicants); - } else { - fprintf(errFile, "No applicants to reject\n"); - } - break; - } - - case 'i': - SOSCCDumpCircleInformation(); - SOSCCDumpEngineInformation(); - break; - - case 'k': - notify_post("com.apple.security.cloudkeychain.forceupdate"); - break; - - case 'o': - { - SOSCCDumpViewUnwarePeers(); - break; - } - - case '0': - { - CFArrayRef unawares = SOSCCCopyViewUnawarePeerInfo(&error); - if (unawares) { - hadError = !SOSCCRemovePeersFromCircle(unawares, &error); - } else { - hadError = true; - } - CFReleaseNull(unawares); - break; - } - case '1': - { - CFDataRef accountState = SOSCCCopyAccountState(&error); - if (accountState) { - printmsg(CFSTR(" %@\n"), CFDataCopyHexString(accountState)); - } else { - hadError = true; - } - CFReleaseNull(accountState); - break; - } - case '2': - { - bool status = SOSCCDeleteAccountState(&error); - if (status) { - printmsg(CFSTR("Deleted account from the keychain %d\n"), status); - } else { - hadError = true; - } - break; - } - case '3': - { - CFDataRef engineState = SOSCCCopyEngineData(&error); - if (engineState) { - printmsg(CFSTR(" %@\n"), CFDataCopyHexString(engineState)); - } else { - hadError = true; - } - CFReleaseNull(engineState); - break; - } - case '4': - { - bool status = SOSCCDeleteEngineState(&error); - if (status) { - printmsg(CFSTR("Deleted engine-state from the keychain %d\n"), status); - } else { - hadError = true; - } - break; - } - case '5' : - { - bool result = SOSCCCleanupKVSKeys(&error); - if(result) + case 'a': { - printmsg(CFSTR("Got all the keys from KVS %d\n"), result); - }else { - hadError = true; + CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL); + if (applicants) { + hadError = !SOSCCAcceptApplicants(applicants, &error); + CFRelease(applicants); + } else { + fprintf(errFile, "No applicants to accept\n"); + } + break; } - break; - } - case '6' : - { - bool result = SOSCCTestPopulateKVSWithBadKeys(&error); - if(result) + case 'b': + { + hadError = setBag(optarg, &error); + break; + } + case 'd': + { + fprintf(outFile, "Turning OFF keychain syncing\n"); + hadError = !SOSCCRemoveThisDeviceFromCircle(&error); + break; + } + case 'e': + { + fprintf(outFile, "Turning ON keychain syncing\n"); + hadError = requestToJoinCircle(&error); + break; + } + case 'i': + { + SOSCCDumpCircleInformation(); + SOSCCDumpEngineInformation(); + break; + } + case 'k': + { + notify_post("com.apple.security.cloudkeychain.forceupdate"); + break; + } + case 'm': + { + hadError = !dumpMyPeer(&error); + break; + } + case 'o': + { + SOSCCDumpViewUnwarePeers(); + break; + } + case 'r': + { + CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL); + if (applicants) { + hadError = !SOSCCRejectApplicants(applicants, &error); + CFRelease(applicants); + } else { + fprintf(errFile, "No applicants to reject\n"); + } + break; + } + case 'v': + { + hadError = !viewcmd(optarg, &error); + break; + } + case 'C': + { + hadError = clearAllKVS(&error); + break; + } + case 'D': + { + (void)SOSCCDumpCircleKVSInformation(optarg); + break; + } + case 'L': + { + hadError = !listviewcmd(&error); + break; + } + case 'N': + { + hadError = !SOSCCAccountSetToNew(&error); + if (!hadError) + notify_post(kSOSCCCircleChangedNotification); + break; + } + case 'O': + { + hadError = !SOSCCResetToOffering(&error); + break; + } + case 'P': + { + hadError = setPassword(optarg, &error); + break; + } + case 'R': + { + hadError = !SOSCCResetToEmpty(&error); + break; + } + case 'T': + { + hadError = tryPassword(optarg, &error); + break; + } + case 'U': + { + hadError = !SOSCCPurgeUserCredentials(&error); + break; + } + case 'V': + { + hadError = clientViewStatus(&error); + break; + } + case 'W': + { + hadError = syncAndWait(&error); + break; + } + case '0': + { + CFArrayRef unawares = SOSCCCopyViewUnawarePeerInfo(&error); + if (unawares) { + hadError = !SOSCCRemovePeersFromCircle(unawares, &error); + } else { + hadError = true; + } + CFReleaseNull(unawares); + break; + } + case '5' : + { + bool result = SOSCCCleanupKVSKeys(&error); + if(result) { - printmsg(CFSTR("Populated KVS with garbage %d\n"), result); + printmsg(CFSTR("Got all the keys from KVS %d\n"), result); }else { hadError = true; } break; - } - case 'E': - { - fprintf(outFile, "Ensuring Fresh Parameters\n"); - bool result = SOSCCRequestEnsureFreshParameters(&error); - if (error) { - hadError = true; - break; - } - if (result) { - fprintf(outFile, "Refreshed Parameters Ensured!\n"); - } else { - fprintf(outFile, "Problem trying to ensure fresh parameters\n"); - } - break; - } - case 'A': - { - fprintf(outFile, "Applying to Ring\n"); - CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); - hadError = SOSCCApplyToARing(ringName, &error); - CFReleaseNull(ringName); - break; - } - case 'B': - { - fprintf(outFile, "Withdrawing from Ring\n"); - CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); - hadError = SOSCCWithdrawlFromARing(ringName, &error); - CFReleaseNull(ringName); - break; - } - case 'F': - { - fprintf(outFile, "Status of this device in the Ring\n"); - CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); - hadError = SOSCCRingStatus(ringName, &error); - CFReleaseNull(ringName); - break; - } - case 'G': - { - fprintf(outFile, "Enabling Ring\n"); - CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); - hadError = SOSCCEnableRing(ringName, &error); - CFReleaseNull(ringName); - break; - } - case 'H': - { - fprintf(outFile, "Setting random escrow record\n"); - bool success = SOSCCSetEscrowRecord(CFSTR("label"), 8, &error); - if(success) - hadError = false; - else - hadError = true; - break; - } - case 'J': - { - CFDictionaryRef attempts = SOSCCCopyEscrowRecord(&error); - if(attempts){ - CFDictionaryForEach(attempts, ^(const void *key, const void *value) { - if(isString(key)){ - char *keyString = CFStringToCString(key); - fprintf(outFile, "%s:\n", keyString); - free(keyString); - } - if(isDictionary(value)){ - CFDictionaryForEach(value, ^(const void *key, const void *value) { - if(isString(key)){ - char *keyString = CFStringToCString(key); - fprintf(outFile, "%s: ", keyString); - free(keyString); - } - if(isString(value)){ - char *time = CFStringToCString(value); - fprintf(outFile, "timestamp: %s\n", time); - free(time); - } - else if(isNumber(value)){ - uint64_t tries; - CFNumberGetValue(value, kCFNumberLongLongType, &tries); - fprintf(outFile, "date: %llu\n", tries); - } - }); - } - - }); } - CFReleaseNull(attempts); - hadError = false; - break; - } - case 'I': - { - fprintf(outFile, "Printing all the rings\n"); - CFStringRef ringdescription = SOSCCGetAllTheRings(&error); - if(!ringdescription) - hadError = true; - else - fprintf(outFile, "Rings: %s", CFStringToCString(ringdescription)); - - break; - } - - case 'N': - hadError = !SOSCCAccountSetToNew(&error); - if (!hadError) - notify_post(kSOSCCCircleChangedNotification); - break; - - case 'R': - hadError = !SOSCCResetToEmpty(&error); - break; - - case 'O': - hadError = !SOSCCResetToOffering(&error); - break; - - case 'm': - hadError = !dumpMyPeer(&error); - break; - - case 'C': - hadError = clearAllKVS(&error); - break; - - case 'P': - hadError = setPassword(optarg, &error); - break; - - case 'T': - hadError = tryPassword(optarg, &error); - break; - - case 'X': - { - uint64_t limit = strtoul(optarg, NULL, 10); - hadError = !SOSCCBailFromCircle_BestEffort(limit, &error); - break; - } - - case 'U': - hadError = !SOSCCPurgeUserCredentials(&error); - break; - - case 'D': - (void)SOSCCDumpCircleKVSInformation(optarg); - break; - - case 'W': - hadError = syncAndWait(&error); - break; - - case 'v': - hadError = !viewcmd(optarg, &error); - break; - - case 'V': - hadError = clientViewStatus(&error); - break; - case 'L': - hadError = !listviewcmd(&error); - break; - - case 'b': - hadError = setBag(optarg, &error); - break; - - case 'Y': - hadError = dumpYetToSync(&error); - break; - case 0: - switch (action) { - case SYNC_REMOVE_PEER: { - CFStringRef optstr; - optstr = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); - if (peers2remove == NULL) { - peers2remove = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + case 0: + { + if (action == SYNC_REMOVE_PEER) { + CFStringRef optstr = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); + if (peers2remove == NULL) { + peers2remove = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFArrayAppendValue(peers2remove, optstr); + CFReleaseNull(optstr); + } else { + return SHOW_USAGE_MESSAGE; } - CFArrayAppendValue(peers2remove, optstr); - CFRelease(optstr); break; } + case '?': default: return SHOW_USAGE_MESSAGE; - } - break; - case '?': - default: - return SHOW_USAGE_MESSAGE; + } } if (peers2remove != NULL) { diff --git a/keychain/SecureObjectSync/Tool/recovery_key.m b/keychain/SecureObjectSync/Tool/recovery_key.m index f836de1f..beca9f35 100644 --- a/keychain/SecureObjectSync/Tool/recovery_key.m +++ b/keychain/SecureObjectSync/Tool/recovery_key.m @@ -133,6 +133,7 @@ recovery_key(int argc, char * const *argv) CDPFollowUpContext *context = [CDPFollowUpContext contextForRecoveryKeyRepair]; context.force = true; + secnotice("followup", "Posting a follow up (for SOS) of type recovery key"); [cdpd postFollowUpWithContext:context error:&localError]; if(localError){ printmsg(CFSTR("Request to CoreCDP to follow up failed: %@\n"), localError); diff --git a/keychain/SecureObjectSync/Tool/syncbackup.m b/keychain/SecureObjectSync/Tool/syncbackup.m deleted file mode 100644 index 5216ad19..00000000 --- a/keychain/SecureObjectSync/Tool/syncbackup.m +++ /dev/null @@ -1,146 +0,0 @@ - -/* - * Copyright (c) 2003-2007,2009-2010,2013-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - * - */ - -// -// syncbackup.c -// sec -// -// -// - -#include "syncbackup.h" - - -#include -#include - -#include -#include -#include "keychain/SecureObjectSync/SOSBackupInformation.h" -#include "keychain/SecureObjectSync/SOSRecoveryKeyBag.h" -#include - -#include - -#include "SecurityTool/sharedTool/readline.h" -#include "secToolFileIO.h" - - -static bool dumpBackupInfo(CFErrorRef *error) { - CFReleaseNull(*error); - bool isLast = SOSCCIsThisDeviceLastBackup(error); - - printmsg(CFSTR("This %s the last backup peer.\n"), (isLast) ? "is": "isn't"); - return *error != NULL; -} - -static bool longListing(CFErrorRef *error) { - CFDataRef rkbgder = NULL; - CFDictionaryRef bskbders = NULL; - - CFDictionaryRef backupInfo = SOSCCCopyBackupInformation(error); - SOSRecoveryKeyBagRef rkbg = NULL; - CFNumberRef status = CFDictionaryGetValue(backupInfo, kSOSBkpInfoStatus); - int infoStatus; - CFNumberGetValue(status, kCFNumberIntType, &infoStatus); - - switch(infoStatus) { - case noError: - rkbgder = CFDictionaryGetValue(backupInfo, kSOSBkpInfoRKBG); - bskbders = CFDictionaryGetValue(backupInfo, kSOSBkpInfoBSKB); - break; - case noTxnorAcct: - break; - case noAlloc: - break; - case noTrustedPubKey: - break; - case noBSKBs: - rkbgder = CFDictionaryGetValue(backupInfo, kSOSBkpInfoRKBG); - break; - default: - break; - } - - if(rkbgder) { - rkbg = SOSRecoveryKeyBagCreateFromData(kCFAllocatorDefault, rkbgder, NULL); - printmsg(CFSTR("Recovery Keybag: %@\n"), rkbg); - } - - if(bskbders) { - CFDataRef rkPub = NULL; - if(rkbg) rkPub = SOSRecoveryKeyBagGetKeyData(rkbg, NULL); - CFDictionaryForEach(bskbders, ^(const void *key, const void *value) { - CFDataRef bskbder = asData(value, NULL); - SOSBackupSliceKeyBagRef bskb = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, bskbder, NULL); - if(bskb) { - bool reckeyPresent = (rkPub && SOSBKSBPrefixedKeyIsInKeyBag(bskb, bskbRkbgPrefix, rkPub)); - printmsg(CFSTR("BackupSliceKeybag %@: Recovery Key %s; %@\n"), key, (reckeyPresent) ? "Present": "Absent ", bskb); - CFReleaseNull(bskb); - } - }); - } - CFReleaseNull(backupInfo); - CFReleaseNull(rkbg); - return *error != NULL; -} - - - -int -syncbackup(int argc, char * const *argv) -{ - /* - "Circle Backup Information" - " -i info (current status)" - - */ - SOSLogSetOutputTo(NULL, NULL); - - int ch, result = 0; - CFErrorRef error = NULL; - bool hadError = false; - - while ((ch = getopt(argc, argv, "il")) != -1) - switch (ch) { - - case 'i': - hadError = dumpBackupInfo(&error); - break; - - case 'l': - hadError = longListing(&error); - break; - - case '?': - default: - return SHOW_USAGE_MESSAGE; - } - - if (hadError) - printerr(CFSTR("Error: %@\n"), error); - - return result; -} diff --git a/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.m b/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.m index 0314479a..be89bc72 100644 --- a/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.m +++ b/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.m @@ -50,7 +50,7 @@ } - (BOOL)hasRingUpdateFlag { - return _has.ringUpdateFlag; + return _has.ringUpdateFlag != 0; } - (NSString *)description diff --git a/keychain/SecurityUnitTests/SecItemTests.m b/keychain/SecurityUnitTests/SecItemTests.m index 998dc16b..efcb1e2c 100644 --- a/keychain/SecurityUnitTests/SecItemTests.m +++ b/keychain/SecurityUnitTests/SecItemTests.m @@ -68,7 +68,7 @@ attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"]; XCTAssertNotNil(attrs, "should create genp"); - XCTAssertEqual(attrs[@"OSStatus"], @(errSecDuplicateItem), "should have duplicate item"); + XCTAssertEqual([attrs[@"OSStatus"] integerValue], errSecDuplicateItem, "should have duplicate item"); } @@ -80,7 +80,7 @@ attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"]; XCTAssertNotNil(attrs, "should create genp"); - XCTAssertEqual(attrs[@"OSStatus"], @(errSecDuplicateItem), "should have duplicate item"); + XCTAssertEqual([attrs[@"OSStatus"] integerValue], errSecDuplicateItem, "should have duplicate item"); XCTAssertEqual([self moveGenericPassword:@"delete-me" service:@"delete-me" newAccount:@"delete-me2" newService:@"delete-me2"], diff --git a/keychain/SecurityUnitTests/SecKeyTests.m b/keychain/SecurityUnitTests/SecKeyTests.m index 97348ac5..2b7febdf 100644 --- a/keychain/SecurityUnitTests/SecKeyTests.m +++ b/keychain/SecurityUnitTests/SecKeyTests.m @@ -22,22 +22,78 @@ */ #import +#import @interface SecKeyTests : XCTestCase @end @implementation SecKeyTests -- (void)testSecKeyAttributesCanBeReadWithMatchingStringsAsKeys -{ +- (void)testSecKeyAttributesCanBeReadWithMatchingStringsAsKeys { CFMutableDictionaryRef keyParameters = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(keyParameters, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom); CFDictionarySetValue(keyParameters, kSecAttrKeySizeInBits, (__bridge CFNumberRef)@(384)); CFDictionarySetValue(keyParameters, CFSTR("nleg"), kCFBooleanTrue); SecKeyRef secKey = SecKeyCreateRandomKey(keyParameters, nil); NSDictionary* attributes = (__bridge_transfer NSDictionary*)SecKeyCopyAttributes(secKey); - XCTAssertEqual(attributes[(__bridge NSString*)kSecAttrKeySizeInBits], attributes[@"bsiz"], @"the SecKey attributes dictionary value of 'kSecAttrKeySizeInBits' and 'bsiz' are not the same"); + XCTAssertEqualObjects(attributes[(__bridge NSString*)kSecAttrKeySizeInBits], attributes[@"bsiz"], @"the SecKey attributes dictionary value of 'kSecAttrKeySizeInBits' and 'bsiz' are not the same"); XCTAssertNotNil(attributes[@"bsiz"], @"the SecKey attributes dictionary value for 'bsiz' is nil"); } +- (void)testECIESDecryptBadInputData { + NSData *message = [@"message" dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error; + id privKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)@{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeySizeInBits: @256}, (void *)&error)); + XCTAssertNotNil(privKey, @"key generation failed: %@", error); + id pubKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privKey)); + XCTAssertNotNil(pubKey); + NSData *ciphertext = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)pubKey, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)message, (void *)&error)); + XCTAssertNotNil(ciphertext, @"Encryption failed: %@", error); + NSData *plaintext = CFBridgingRelease(SecKeyCreateDecryptedData((SecKeyRef)privKey, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)ciphertext, (void *)&error)); + XCTAssertEqualObjects(message, plaintext, @"Decryption did not provide original message"); + + // Strip tag from ciphertext + NSData *strippedCiphertext = [ciphertext subdataWithRange:NSMakeRange(0, ciphertext.length - 16)]; + NSData *failedDecrypted = CFBridgingRelease(SecKeyCreateDecryptedData((SecKeyRef)privKey, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)strippedCiphertext, (void *)&error)); + XCTAssertNil(failedDecrypted, @"Decryption of malformed data did not fail"); + XCTAssertEqual(error.code, errSecParam, @"Unexpected error code provided"); +} + +static CFIndex SecTestKeyGetAlgorithmID(SecKeyRef key) { + return kSecECDSAAlgorithmID; +} + +static CFTypeRef SecTestKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm, CFArrayRef allAlgorithms, SecKeyOperationMode mode, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { + if (!CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) { + return kCFNull; + } + + NSArray *algs = (__bridge NSArray *)allAlgorithms; + XCTAssertEqualObjects(algs[0], (__bridge id)kSecKeyAlgorithmECDSASignatureDigestX962SHA256); + return CFRetain(in1); +} + + +static SecKeyDescriptor SecTestKeyDescriptor = { + .version = kSecKeyDescriptorVersion, + .name = "SecTestKey", + .getAlgorithmID = SecTestKeyGetAlgorithmID, + .copyOperationResult = SecTestKeyCopyOperationResult, +}; + +- (void)testLegacyAPIBridging { + NSData *message = [NSMutableData dataWithLength:256 / 8]; + NSError *error; + id privKey = CFBridgingRelease(SecKeyCreate(kCFAllocatorDefault, &SecTestKeyDescriptor, 0, 0, 0)); + CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)@{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeySizeInBits: @256}, (void *)&error)); + XCTAssertNotNil(privKey, @"key generation failed: %@", error); + NSMutableData *signature = [NSMutableData dataWithLength:256]; + size_t sigLength = signature.length; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + OSStatus status = SecKeyRawSign((__bridge SecKeyRef)privKey, kSecPaddingPKCS1, message.bytes, message.length, signature.mutableBytes, &sigLength); +#pragma clang diagnostic pop + XCTAssertEqual(status, errSecSuccess, @"Encryption failed"); +} + @end diff --git a/keychain/SigninMetrics/OctagonSignPosts.h b/keychain/SigninMetrics/OctagonSignPosts.h index 92afe71d..b6a06b8d 100644 --- a/keychain/SigninMetrics/OctagonSignPosts.h +++ b/keychain/SigninMetrics/OctagonSignPosts.h @@ -38,8 +38,16 @@ typedef struct octagon_signpost_s { } OctagonSignpost; #define OctagonSignpostNamePerformEscrowRecovery "OctagonSignpostNamePerformEscrowRecovery" +#define OctagonSignpostNamePerformSilentEscrowRecovery "OctagonSignpostNamePerformSilentEscrowRecovery" #define OctagonSignpostNamePerformRecoveryFromSBD "OctagonSignpostNamePerformRecoveryFromSBD" -#define OctagonSignpostNamePerformBottleRecovery "OctagonSignpostNamePerformBottleRecovery" + +#define OctagonSignpostNameRecoverWithCDPContext "OctagonSignpostNameRecoverWithCDPContext" +#define OctagonSignpostNameRecoverSilentWithCDPContext "OctagonSignpostNameRecoverSilentWithCDPContext" +#define OctagonSignpostNamePerformOctagonJoinForSilent "OctagonSignpostNamePerformOctagonJoinForSilent" +#define OctagonSignpostNamePerformOctagonJoinForNonSilent "OctagonSignpostNamePerformOctagonJoinForNonSilent" + + +#define OctagonSignpostNamePerformOctagonJoin "OctagonSignpostNamePerformOctagonJoin" #define OctagonSignpostNamePerformResetAndEstablishAfterFailedBottle "OctagonSignpostNamePerformResetAndEstablishAfterFailedBottle" #define OctagonSignpostNameFetchEgoPeer "OctagonSignpostNameFetchEgoPeer" #define OctagonSignpostNameEstablish "OctagonSignpostNameEstablish" @@ -61,11 +69,13 @@ typedef struct octagon_signpost_s { #define OctagonSignpostNameRequestToJoinCircle "OctagonSignpostNameRequestToJoinCircle" #define OctagonSignpostNameAccountUserKeyAvailable "OctagonSignpostNameAccountUserKeyAvailable" #define OctagonSignpostNameFindOptimalBottleIDsWithContextData "OctagonSignpostNameFindOptimalBottleIDsWithContextData" +#define OctagonSignpostNameFetchEscrowRecords "OctagonSignpostNameFetchEscrowRecords" #define OctagonSignpostNameFetchEscrowContents "OctagonSignpostNameFetchEscrowContents" #define OctagonSignpostNameSetNewRecoveryKeyWithData "OctagonSignpostNameSetNewRecoveryKeyWithData" #define OctagonSignpostNameRecoverOctagonUsingData "OctagonSignpostNameRecoverOctagonUsingData" #define OctagonSignpostNamePerformedCDPStateMachineRun "OctagonSignpostNamePerformedCDPStateMachineRun" #define OctagonSignpostNameWaitForOctagonUpgrade "OctagonSignpostNameWaitForOctagonUpgrade" +#define OctagonSignpostNameGetAccountInfo "OctagonSignpostNameGetAccountInfo" #define SOSSignpostNameAssertUserCredentialsAndOptionalDSID "SOSSignpostNameAssertUserCredentialsAndOptionalDSID" #define SOSSignpostNameSOSCCTryUserCredentials "SOSSignpostNameSOSCCTryUserCredentials" @@ -128,28 +138,6 @@ extern os_log_t _OctagonSignpostLogSystem(void); extern OctagonSignpost _OctagonSignpostCreate(os_log_t subsystem); extern uint64_t _OctagonSignpostGetNanoseconds(OctagonSignpost signpost); -#ifdef DARLING -// the compiler was being weird with the preprocessor trickery that was happening in Apple's code -// so i had to manually expand parts of it -#define _OctagonSignpostBegin(subsystem, name, something, ...) __extension__({ \ - OctagonSignpost internalSignpost = _OctagonSignpostCreate(subsystem); \ - os_signpost_interval_begin(subsystem, internalSignpost.identifier, name, __VA_ARGS__); \ - os_log(subsystem, "BEGIN [%lld]: " name " " something, internalSignpost.identifier, ##__VA_ARGS__); \ - internalSignpost; \ -}) - -#define _OctagonSignpostEvent(subsystem, signpost, name, something, ...) __extension__({ \ - double interval = ((double)_OctagonSignpostGetNanoseconds(_signpost) / NSEC_PER_SEC); \ - os_signpost_event_emit(subsystem, signpost.identifier, name, __VA_ARGS__); \ - os_log(subsystem, "EVENT [%lld] %fs: " name " " something, signpost.identifier, interval, ##__VA_ARGS__); \ -}) - -#define _OctagonSignpostEnd(subsystem, signpost, name, something, ...) __extension__({ \ - double interval = ((double)_OctagonSignpostGetNanoseconds(signpost) / NSEC_PER_SEC); \ - os_signpost_interval_end(subsystem, signpost.identifier, name, __VA_ARGS__); \ - os_log(subsystem, "END [%lld] %fs: " name " " something, signpost.identifier, interval, ##__VA_ARGS__); \ -}) -#else #define _OctagonSignpostBegin(subsystem, name, ...) __extension__({ \ OctagonSignpost internalSignpost = _OctagonSignpostCreate(subsystem); \ os_signpost_interval_begin(subsystem, internalSignpost.identifier, name, __VA_ARGS__); \ @@ -171,7 +159,6 @@ extern uint64_t _OctagonSignpostGetNanoseconds(OctagonSignpost signpost); #define _OctagonSwizzle1(x, a, ...) a, x, ##__VA_ARGS__ #define _OctagonSwizzle2(x, y, a, ...) a, x, y, ##__VA_ARGS__ -#endif NS_ASSUME_NONNULL_END diff --git a/keychain/SigninMetrics/SFSignInAnalytics.h b/keychain/SigninMetrics/SFSignInAnalytics.h deleted file mode 100644 index 2863a4d3..00000000 --- a/keychain/SigninMetrics/SFSignInAnalytics.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#if __OBJC2__ -#ifndef SignInAnalytics_h -#define SignInAnalytics_h - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface SFSignInAnalytics : NSObject - -@property (readonly) NSString* eventName; -@property (readonly) NSString* category; -@property (readonly) BOOL stopped; - -/* - abstract: creates a new SignInAnalytics object, automatically starts a timer for this task. - uuid: iCloud sign in transaction UUID - category: name of client subsystem. This will be used as the category name when logging - eventName: name of the event we are measuring - */ -- (instancetype _Nullable)initWithSignInUUID:(NSString *)uuid category:(NSString *)category eventName:(NSString*)eventName; -- (instancetype)init NS_UNAVAILABLE; - -/* - abstract: creates a new SignInAnalytics that starts a timer for the subtask. - ideal for fine grained timing of sub events and automatically creates a dependency chain. - eventNmae: name of the event being timed - */ -- (SFSignInAnalytics* _Nullable)newSubTaskForEvent:(NSString*)eventName; - -/* - abstract: call to log when a recoverable error occurs during sign in - error: error that occured during iCloud Sign in - */ -- (void)logRecoverableError:(NSError*)error; - -/* - abstract: call to log when a unrecoverable error occurs during sign in - error: error that occured during iCloud Sign in - */ -- (void)logUnrecoverableError:(NSError*)error; - -/* - abstract: call to cancel the timer object. - */ -- (void)cancel; - -/* - abstract: call to stop a timer and log the time spent. - eventName: subsystem name - attributes: a dictionary containing event attributes - */ -- (void)stopWithAttributes:(NSDictionary* _Nullable)attributes; - -/* - abstract: call to signal iCloud sign in has finished. - */ -- (void)signInCompleted; - -@end -NS_ASSUME_NONNULL_END -#endif /* SignInAnalytics_h */ -#endif diff --git a/keychain/SigninMetrics/SFSignInAnalytics.m b/keychain/SigninMetrics/SFSignInAnalytics.m deleted file mode 100644 index 3b079c97..00000000 --- a/keychain/SigninMetrics/SFSignInAnalytics.m +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#if __OBJC2__ - -#import "SFSignInAnalytics.h" -#import "SFSignInAnalytics+Internal.h" - -#import -#import "Analytics/SFAnalyticsDefines.h" -#import "Analytics/SFAnalyticsSQLiteStore.h" -#import "Analytics/SFAnalytics.h" - -#import -#import -#import -#import "utilities/debugging.h" -#import - -//metrics database location -NSString* signinMetricsDatabase = @"signin_metrics"; - -//defaults write results location -static NSString* const SFSignInAnalyticsDumpLoggedResultsToLocation = @"/tmp/signin_results.txt"; -static NSString* const SFSignInAnalyticsPersistedEventList = @"/tmp/signin_eventlist"; - -//analytics constants -static NSString* const SFSignInAnalyticsAttributeRecoverableError = @"recoverableError"; -static NSString* const SFSignInAnalyticsAttributeErrorDomain = @"errorDomain"; -static NSString* const SFSignInAnalyticsAttributeErrorCode = @"errorCode"; -static NSString* const SFSignInAnalyticsAttributeErrorChain = @"errorChain"; -static NSString* const SFSignInAnalyticsAttributeParentUUID = @"parentUUID"; -static NSString* const SFSignInAnalyticsAttributeMyUUID = @"myUUID"; -static NSString* const SFSignInAnalyticsAttributeSignInUUID = @"signinUUID"; -static NSString* const SFSignInAnalyticsAttributeEventName = @"eventName"; -static NSString* const SFSignInAnalyticsAttributeSubsystemName = @"subsystemName"; -static NSString* const SFSignInAnalyticsAttributeBuiltDependencyChains = @"dependencyChains"; -static NSString* const SFSignInAnalyticsAttributeTrackerTime = @"trackerTime"; - -@implementation SFSIALoggerObject -+ (NSString*)databasePath { - return [SFSIALoggerObject defaultAnalyticsDatabasePath:signinMetricsDatabase]; -} - -+ (instancetype)logger -{ - return [super logger]; -} -@end - - -@interface SFSignInAnalytics () -@property (nonatomic, copy) NSString *signin_uuid; -@property (nonatomic, copy) NSString *my_uuid; -@property (nonatomic, copy) NSString *parent_uuid; -@property (nonatomic, copy) NSString *category; -@property (nonatomic, copy) NSString *eventName; -@property (nonatomic, copy) NSString *persistencePath; - -@property (nonatomic, strong) NSURL *persistedEventPlist; -@property (nonatomic, strong) NSMutableDictionary *eventDependencyList; -@property (nonatomic, strong) NSMutableArray *builtDependencyChains; - -@property (nonatomic) BOOL canceled; -@property (nonatomic) BOOL stopped; - -@property (nonatomic, strong) os_log_t logObject; - -@property (nonatomic, strong) NSNumber *measurement; - -@property (nonatomic, strong) dispatch_queue_t queue; - -@property (nonatomic, strong) SFSignInAnalytics *root; -@property (nonatomic, strong) SFAnalyticsActivityTracker *tracker; - --(os_log_t) newLogForCategoryName:(NSString*) category; --(os_log_t) logForCategoryName:(NSString*) category; - -@end - -static NSMutableDictionary *logObjects; -static const NSString* signInLogSpace = @"com.apple.security.wiiss"; - -@implementation SFSignInAnalytics - -+ (BOOL)supportsSecureCoding { - return YES; -} - --(os_log_t) logForCategoryName:(NSString*) category -{ - return logObjects[category]; -} - --(os_log_t) newLogForCategoryName:(NSString*) category -{ - return os_log_create([signInLogSpace UTF8String], [category UTF8String]); -} - -- (BOOL)writeDependencyList:(NSError**)error -{ - NSError *localError = nil; - if (![NSPropertyListSerialization propertyList: self.root.eventDependencyList isValidForFormat: NSPropertyListXMLFormat_v1_0]){ - os_log_error(self.logObject, "can't save PersistentState as XML"); - return false; - } - - NSData *data = [NSPropertyListSerialization dataWithPropertyList: self.root.eventDependencyList - format: NSPropertyListXMLFormat_v1_0 options: 0 error: &localError]; - if (data == nil){ - os_log_error(self.logObject, "error serializing PersistentState to xml: %@", localError); - return false; - } - - BOOL writeStatus = [data writeToURL:self.root.persistedEventPlist options: NSDataWritingAtomic error: &localError]; - if (!writeStatus){ - os_log_error(self.logObject, "error writing PersistentState to file: %@", localError); - } - if(localError && error){ - *error = localError; - } - - return writeStatus; -} - -- (instancetype)initWithSignInUUID:(NSString *)uuid category:(NSString *)category eventName:(NSString*)eventName -{ - self = [super init]; - if (self) { - _signin_uuid = uuid; - - _my_uuid = uuid; - _parent_uuid = uuid; - _eventName = eventName; - _category = category; - _root = self; - _canceled = NO; - _stopped = NO; - _builtDependencyChains = [NSMutableArray array]; - - if ([self writeResultsToTmp]) { - //make plist file containing uuid parent/child - _persistencePath = [NSString stringWithFormat:@"%@-%@.plist", SFSignInAnalyticsPersistedEventList, eventName]; - _persistedEventPlist = [NSURL fileURLWithPath:_persistencePath isDirectory:NO]; - } - - _eventDependencyList = [NSMutableDictionary dictionary]; - [_eventDependencyList setObject:[NSMutableArray array] forKey:_signin_uuid]; - - _tracker = [[SFSIALoggerObject logger] logSystemMetricsForActivityNamed:eventName withAction:nil]; - [_tracker start]; - - NSError* error = nil; - - if(self.root.persistedEventPlist && ![self writeDependencyList:&error] ){ - os_log(self.logObject, "attempting to write dependency list: %@", error); - } - - _queue = dispatch_queue_create("com.apple.security.SignInAnalytics", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - logObjects = [NSMutableDictionary dictionary]; - }); - @synchronized(logObjects){ - if(category){ - _logObject = [self logForCategoryName:category]; - - if(!_logObject){ - _logObject = [self newLogForCategoryName:category]; - [logObjects setObject:_logObject forKey:category]; - } - } - } - } - return self; -} - --(instancetype) initChildWithSignInUUID:(NSString*)uuid andCategory:(NSString*)category andEventName:(NSString*)eventName -{ - self = [super init]; - if (self) { - _signin_uuid = uuid; - - _my_uuid = uuid; - _parent_uuid = uuid; - _eventName = eventName; - _category = category; - _canceled = NO; - } - return self; -} - -- (void)encodeWithCoder:(NSCoder *)coder { - [coder encodeObject:_signin_uuid forKey:@"UUID"]; - [coder encodeObject:_category forKey:@"category"]; - [coder encodeObject:_parent_uuid forKey:@"parentUUID"]; - [coder encodeObject:_my_uuid forKey:@"myUUID"]; - [coder encodeObject:_measurement forKey:@"measurement"]; - [coder encodeObject:_eventName forKey:@"eventName"]; -} - -- (nullable instancetype)initWithCoder:(NSCoder *)decoder -{ - self = [super init]; - if (self) { - _signin_uuid = [decoder decodeObjectOfClass:[NSString class] forKey:@"UUID"]; - _category = [decoder decodeObjectOfClass:[NSString class] forKey:@"category"]; - _parent_uuid = [decoder decodeObjectOfClass:[NSString class] forKey:@"parentUUID"]; - _my_uuid = [decoder decodeObjectOfClass:[NSString class] forKey:@"myUUID"]; - _measurement = [decoder decodeObjectOfClass:[NSString class] forKey:@"measurement"]; - _eventName = [decoder decodeObjectOfClass:[NSString class] forKey:@"eventName"]; - _queue = dispatch_queue_create("com.apple.security.SignInAnalytics", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - - if(_signin_uuid == nil || - _category == nil || - _parent_uuid == nil){ - [decoder failWithError:[NSError errorWithDomain:@"securityd" code:errSecDecode userInfo:@{NSLocalizedDescriptionKey: @"Failed to decode SignInAnalytics object"}]]; - return nil; - } - } - return self; -} - -- (SFSignInAnalytics*)newSubTaskForEvent:(NSString*)eventName -{ - SFSignInAnalytics *newSubTask = [[SFSignInAnalytics alloc] initChildWithSignInUUID:self.signin_uuid andCategory:self.category andEventName:self.eventName]; - if(newSubTask){ - newSubTask.my_uuid = [NSUUID UUID].UUIDString; - newSubTask.parent_uuid = self.my_uuid; - newSubTask.signin_uuid = self.signin_uuid; - - newSubTask.category = self.category; - newSubTask.eventName = [eventName copy]; - newSubTask.root = self.root; - newSubTask.canceled = NO; - newSubTask.stopped = NO; - - newSubTask.queue = dispatch_queue_create("com.apple.security.SignInAnalytics", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - newSubTask.tracker = [[SFSIALoggerObject logger] logSystemMetricsForActivityNamed:eventName withAction:nil]; - [newSubTask.tracker start]; - - @synchronized(_eventDependencyList){ - NSMutableArray *parentEntry = [newSubTask.root.eventDependencyList objectForKey:newSubTask.parent_uuid]; - - //add new subtask entry to parent event's list - [parentEntry addObject:newSubTask.my_uuid]; - [newSubTask.root.eventDependencyList setObject:parentEntry forKey:newSubTask.parent_uuid]; - - //create new array list for this new subtask incase it has subtasks - [newSubTask.root.eventDependencyList setObject:[NSMutableArray array] forKey:newSubTask.my_uuid]; - NSError* error = nil; - if(self.root.persistedEventPlist && ![newSubTask writeDependencyList:&error] ){ - os_log(self.logObject, "attempting to write dependency list: %@", error); - } - } - } - - return newSubTask; -} - -- (void)logRecoverableError:(NSError*)error -{ - - if (error == nil){ - os_log_error(self.logObject, "attempting to log a nil error for event:%@", self.eventName); - return; - } - - os_log_error(self.logObject, "%@", error); - - NSMutableDictionary* eventAttributes = [NSMutableDictionary dictionary]; - - [eventAttributes setValuesForKeysWithDictionary:@{ - SFSignInAnalyticsAttributeRecoverableError : @(YES), - SFSignInAnalyticsAttributeErrorDomain : error.domain, - SFSignInAnalyticsAttributeErrorCode : @(error.code), - SFSignInAnalyticsAttributeMyUUID : self.my_uuid, - SFSignInAnalyticsAttributeParentUUID : self.parent_uuid, - SFSignInAnalyticsAttributeSignInUUID : self.signin_uuid, - SFSignInAnalyticsAttributeEventName : self.eventName, - SFSignInAnalyticsAttributeSubsystemName : self.category - }]; - - [[SFSIALoggerObject logger] logSoftFailureForEventNamed:self.eventName withAttributes:eventAttributes]; - -} - -- (void)logUnrecoverableError:(NSError*)error -{ - if (error == nil){ - os_log_error(self.logObject, "attempting to log a nil error for event:%@", self.eventName); - return; - } - - os_log_error(self.logObject, "%@", error); - - NSMutableDictionary* eventAttributes = [NSMutableDictionary dictionary]; - - [eventAttributes setValuesForKeysWithDictionary:@{ - SFSignInAnalyticsAttributeRecoverableError : @(NO), - SFSignInAnalyticsAttributeErrorDomain : error.domain, - SFSignInAnalyticsAttributeErrorCode : @(error.code), - SFSignInAnalyticsAttributeMyUUID : self.my_uuid, - SFSignInAnalyticsAttributeParentUUID : self.parent_uuid, - SFSignInAnalyticsAttributeSignInUUID : self.signin_uuid, - SFSignInAnalyticsAttributeEventName : self.eventName, - SFSignInAnalyticsAttributeSubsystemName : self.category - }]; - - [[SFSIALoggerObject logger] logHardFailureForEventNamed:self.eventName withAttributes:eventAttributes]; -} - --(void)cancel -{ - dispatch_sync(self.queue, ^{ - [self.tracker cancel]; - self.canceled = YES; - os_log(self.logObject, "canceled timer for %@", self.eventName); - }); -} - -- (void)stopWithAttributes:(NSDictionary*)attributes -{ - dispatch_sync(self.queue, ^{ - - if(self.canceled || self.stopped){ - return; - } - - self.stopped = YES; - - [self.tracker stop]; - - NSMutableDictionary *mutableAttributes = nil; - - if(attributes){ - mutableAttributes = [NSMutableDictionary dictionaryWithDictionary:attributes]; - } - else{ - mutableAttributes = [NSMutableDictionary dictionary]; - } - mutableAttributes[SFSignInAnalyticsAttributeMyUUID] = self.my_uuid; - mutableAttributes[SFSignInAnalyticsAttributeParentUUID] = self.parent_uuid; - mutableAttributes[SFSignInAnalyticsAttributeSignInUUID] = self.signin_uuid; - mutableAttributes[SFSignInAnalyticsAttributeEventName] = self.eventName; - mutableAttributes[SFSignInAnalyticsAttributeSubsystemName] = self.category; - mutableAttributes[SFSignInAnalyticsAttributeTrackerTime] = self.tracker.measurement; - - [mutableAttributes enumerateKeysAndObjectsUsingBlock:^(NSString* key, id obj, BOOL * stop) { - os_log(self.logObject, "event: %@, %@ : %@", self.eventName, key, obj); - }]; - - [[SFSIALoggerObject logger] logSuccessForEventNamed:self.eventName]; - [[SFSIALoggerObject logger] logSoftFailureForEventNamed:self.eventName withAttributes:mutableAttributes]; - }); -} - --(BOOL) writeResultsToTmp { - - bool shouldWriteResultsToTemp = NO; - CFBooleanRef toTmp = (CFBooleanRef)CFPreferencesCopyValue(CFSTR("DumpResultsToTemp"), - CFSTR("com.apple.security"), - kCFPreferencesAnyUser, kCFPreferencesAnyHost); - if(toTmp && CFGetTypeID(toTmp) == CFBooleanGetTypeID()){ - if(toTmp == kCFBooleanFalse){ - os_log(self.logObject, "writing results to splunk"); - shouldWriteResultsToTemp = NO; - } - if(toTmp == kCFBooleanTrue){ - os_log(self.logObject, "writing results to /tmp"); - shouldWriteResultsToTemp = YES; - } - } - - CFReleaseNull(toTmp); - return shouldWriteResultsToTemp; -} - -- (void)processEventChainForUUID:(NSString*)uuid dependencyChain:(NSString*)dependencyChain -{ - NSString* newChain = dependencyChain; - - NSArray* children = [self.root.eventDependencyList objectForKey:uuid]; - for (NSString* child in children) { - newChain = [NSString stringWithFormat:@"%@, %@", dependencyChain, child]; - [self processEventChainForUUID:child dependencyChain:newChain]; - } - if([children count] == 0){ - [self.root.builtDependencyChains addObject:newChain]; - os_log(self.logObject, "current dependency chain list: %@", newChain); - } -} - -- (void)signInCompleted -{ - //print final - os_log(self.logObject, "sign in complete"); - NSError* error = nil; - - //create dependency chains and log them - [self processEventChainForUUID:self.root.my_uuid dependencyChain:self.root.signin_uuid]; - //write to database - if([self.root.builtDependencyChains count] > 0){ - NSDictionary* eventAttributes = @{SFSignInAnalyticsAttributeBuiltDependencyChains : self.root.builtDependencyChains}; - [[SFSIALoggerObject logger] logSoftFailureForEventNamed:SFSignInAnalyticsAttributeBuiltDependencyChains withAttributes:eventAttributes]; - } - - if([self writeResultsToTmp]){ //writing sign in analytics to /tmp - os_log(self.logObject, "logging to /tmp"); - - NSData* eventData = [NSKeyedArchiver archivedDataWithRootObject:[[SFSIALoggerObject logger].database allEvents] requiringSecureCoding:YES error:&error]; - if(eventData){ - [eventData writeToFile:SFSignInAnalyticsDumpLoggedResultsToLocation options:0 error:&error]; - - if(error){ - os_log_error(self.logObject, "error writing to file [%@], error:%@", SFSignInAnalyticsDumpLoggedResultsToLocation, error); - }else{ - os_log(self.logObject, "successfully wrote sign in analytics to:%@", SFSignInAnalyticsDumpLoggedResultsToLocation); - } - }else{ - os_log_error(self.logObject, "collected no data"); - } - - }else{ //writing to splunk - os_log(self.logObject, "logging to splunk"); - } - - if (self.persistencePath) { - //remove dependency list - BOOL removedPersistedDependencyList = [[NSFileManager defaultManager] removeItemAtPath:self.persistencePath error:&error]; - if(!removedPersistedDependencyList || error){ - os_log(self.logObject, "encountered error when attempting to remove persisted event list: %@", error); - } - } -} - -@end -#endif - diff --git a/keychain/SigninMetrics/tests/SFSignInAnalyticsTests.m b/keychain/SigninMetrics/tests/SFSignInAnalyticsTests.m deleted file mode 100644 index b52d9b4e..00000000 --- a/keychain/SigninMetrics/tests/SFSignInAnalyticsTests.m +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#import -#import "keychain/SigninMetrics/SFSignInAnalytics.h" -#import "keychain/SigninMetrics/SFSignInAnalytics+Internal.h" -#import "keychain/ot/OTDefines.h" -#import "SFAnalytics+Signin.h" -#import - -static NSInteger _testnum; -static NSString* _path; - -@interface SFSignInAnalyticsTester : SFSignInAnalytics --(instancetype)init; -@end - -@implementation SFSignInAnalyticsTester - -+ (NSString*)databasePath { - return _path; -} - --(instancetype)init -{ - self = [super initWithSignInUUID:[NSUUID UUID].UUIDString category:@"CoreCDP" eventName:@"signin"]; - - return self; -} - -@end - - -@interface SignInAnalyticsTests : XCTestCase -@property (nonatomic) SFSignInAnalyticsTester *metric; -@end - -@implementation SignInAnalyticsTests - - -- (void)setUp { - [super setUp]; - _testnum = 0; - self.continueAfterFailure = NO; - _path = [@"/tmp" stringByAppendingFormat:@"/test_%ld.db", (long)++_testnum]; - _metric = [[SFSignInAnalyticsTester alloc] init]; - XCTAssertNotNil(_metric, "SignInAnalyticsTester object should not be nil"); -} - -- (void)tearDown -{ - dispatch_async([SFSIALoggerObject logger].queue, ^{ - [[SFSIALoggerObject logger].database executeSQL:@"delete from all_events"]; - [[SFSIALoggerObject logger].database executeSQL:@"delete from soft_failures"]; - [[SFSIALoggerObject logger].database executeSQL:@"delete from hard_failures"]; - }); - - [[SFSIALoggerObject logger] removeState]; - _metric = nil; - [super tearDown]; -} - -- (void)testStop -{ - sleep(2); - NSDictionary *attributes = @{@"success": @YES, - @"takenFlow" : @"restore", - }; - XCTAssertNotNil(attributes, "attributes dictionary should exist"); - - [_metric stopWithAttributes:attributes]; - - NSArray* results = [[SFSIALoggerObject logger].database allEvents]; - - XCTAssertEqual([results count], 2, @"should have 2 results"); - -} - -- (void)testCancel -{ - [_metric cancel]; -} - -- (void)testLogError -{ - NSError* error = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorBottleID userInfo:@{NSLocalizedDescriptionKey: @"Failed to deserialize bottle peer"}]; - [_metric logRecoverableError:error]; - NSArray* results = [[SFSIALoggerObject logger].database softFailures]; - XCTAssertEqual([results count], 1, @"should have 1 results"); -} - -- (void)testCreateNewSubtask -{ - SFSignInAnalytics* child = [_metric newSubTaskForEvent:@"restore"]; - XCTAssertNotNil(child, "child should be created"); - [[SFSIALoggerObject logger] removeState]; - child = nil; -} - - -- (void)testCreateNewSubtaskAndStop -{ - SFSignInAnalytics* child = [_metric newSubTaskForEvent:@"restore"]; - - sleep(2); - NSDictionary *attributes = @{@"success": @YES, - @"takenFlow" : @"piggyback", - }; - - [child stopWithAttributes:attributes]; - - XCTAssertNotNil(child, "child should be created"); - - NSArray* results = [[SFSIALoggerObject logger].database allEvents]; - - XCTAssertEqual([results count], 2, @"should have 2 results"); - - [[SFSIALoggerObject logger] removeState]; - child = nil; -} - -- (void)testStopAfterCancel -{ - sleep(2); - NSDictionary *attributes = @{@"success": @YES, - @"takenFlow" : @"piggyback", - }; - XCTAssertNotNil(attributes, "attributes dictionary should exist"); - - [_metric cancel]; - - [_metric stopWithAttributes:attributes]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - - XCTAssertEqual([allEvents count], 0, @"should have 0 things logged"); -} - -- (void)testStopAfterStop -{ - sleep(2); - NSDictionary *attributes = @{@"success": @YES, - @"takenFlow" : @"piggyback", - }; - XCTAssertNotNil(attributes, "attributes dictionary should exist"); - - [_metric stopWithAttributes:attributes]; - - [_metric stopWithAttributes:attributes]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - - XCTAssertEqual([allEvents count], 2, @"should have 2 things logged"); -} - --(void)testSignInComplete -{ - NSDictionary* attributes = [NSDictionary dictionary]; - [_metric stopWithAttributes:attributes]; - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array should not be nil"); - XCTAssertTrue(allEvents && [allEvents count] > 0, "array should not be nil and contain an entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - XCTAssertTrue(dependencyEntry && [dependencyEntry count] > 0, "dictionary should not be nil and contain an entry"); - - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - - XCTAssertEqual([chains count], 1, "should be one list"); - - XCTAssertTrue([chains containsObject:_metric.signin_uuid], "should contain 1 uuid"); -} - --(void)testSingleChainDependencyList -{ - SFSignInAnalytics* child1 = [_metric newSubTaskForEvent:@"piggyback"]; - XCTAssertNotNil(child1, "child1 should be created"); - - SFSignInAnalytics* child2 = [child1 newSubTaskForEvent:@"initialsync"]; - XCTAssertNotNil(child2, "child2 should be created"); - - SFSignInAnalytics* child3 = [child2 newSubTaskForEvent:@"backup"]; - XCTAssertNotNil(child3, "child3 should be created"); - - SFSignInAnalytics* child4 = [child3 newSubTaskForEvent:@"processing one ring"]; - XCTAssertNotNil(child4, "child4 should be created"); - - [_metric signInCompleted]; - - NSString *expectedChain = [NSString stringWithFormat:@"%@, %@, %@, %@, %@", child1.signin_uuid, child1.my_uuid, child2.my_uuid, child3.my_uuid, child4.my_uuid]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "should not be nil"); - XCTAssertTrue([allEvents count] > 0, "should be events"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - - XCTAssertEqual([chains count], 1, "should be one list"); - XCTAssertTrue([expectedChain isEqualToString:[chains objectAtIndex:0]], "chains should be the same"); - - child1 = nil; - child2 = nil; - child3 = nil; - child4 = nil; - - child1 = nil; - child2 = nil; - child3 = nil; - child4 = nil; -} - --(void)testMultipleChildrenPerEvent -{ - SFSignInAnalytics* child1 = [_metric newSubTaskForEvent:@"piggyback"]; - XCTAssertNotNil(child1, "child1 should be created"); - - SFSignInAnalytics* child2 = [child1 newSubTaskForEvent:@"initialsync"]; - XCTAssertNotNil(child2, "child2 should be created"); - - SFSignInAnalytics* child3 = [child1 newSubTaskForEvent:@"backup"]; - XCTAssertNotNil(child3, "child3 should be created"); - - SFSignInAnalytics* child4 = [child1 newSubTaskForEvent:@"processing one ring"]; - XCTAssertNotNil(child4, "child4 should be created"); - - SFSignInAnalytics* child5 = [child2 newSubTaskForEvent:@"processing second ring"]; - XCTAssertNotNil(child5, "child5 should be created"); - - SFSignInAnalytics* child6 = [child2 newSubTaskForEvent:@"processing third ring"]; - XCTAssertNotNil(child6, "child6 should be created"); - - SFSignInAnalytics* child7 = [child2 newSubTaskForEvent:@"processing fourth ring"]; - XCTAssertNotNil(child7, "child7 should be created"); - - SFSignInAnalytics* child8 = [child7 newSubTaskForEvent:@"processing fifth ring"]; - XCTAssertNotNil(child8, "child8 should be created"); - - SFSignInAnalytics* child9 = [child7 newSubTaskForEvent:@"processing one ring"]; - XCTAssertNotNil(child9, "child9 should be created"); - - NSString *expectedChain = [NSString stringWithFormat:@"%@, %@, %@, %@", _metric.signin_uuid, child1.my_uuid, child2.my_uuid, child5.my_uuid]; - - NSString *expectedChain1 = [NSString stringWithFormat:@"%@, %@, %@", _metric.signin_uuid, child1.my_uuid, child3.my_uuid]; - - NSString *expectedChain2 = [NSString stringWithFormat:@"%@, %@, %@", _metric.signin_uuid, child1.my_uuid, child4.my_uuid]; - - NSString *expectedChain3 = [NSString stringWithFormat:@"%@, %@, %@, %@", _metric.signin_uuid, child1.my_uuid, child2.my_uuid, child5.my_uuid]; - - NSString *expectedChain4 = [NSString stringWithFormat:@"%@, %@, %@, %@, %@", _metric.signin_uuid, child1.my_uuid, child2.my_uuid, child7.my_uuid, child8.my_uuid]; - - NSString *expectedChain5 = [NSString stringWithFormat:@"%@, %@, %@, %@, %@", _metric.signin_uuid, child1.my_uuid, child2.my_uuid, child7.my_uuid, child9.my_uuid]; - - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertTrue([allEvents count] > 0, "array should not be empty"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - - XCTAssertEqual([chains count], 6, "should be one list"); - - XCTAssertTrue([chains containsObject:expectedChain], "chains should contain expectedChain"); - XCTAssertTrue([chains containsObject:expectedChain1], "chains should contain expectedChain1"); - XCTAssertTrue([chains containsObject:expectedChain2], "chains should contain expectedChain2"); - XCTAssertTrue([chains containsObject:expectedChain3], "chains should contain expectedChain3"); - XCTAssertTrue([chains containsObject:expectedChain4], "chains should contain expectedChain4"); - XCTAssertTrue([chains containsObject:expectedChain5], "chains should contain expectedChain5"); - - [[SFSIALoggerObject logger] removeState]; - - child1 = nil; - child2 = nil; - child3 = nil; - child4 = nil; - child5 = nil; - child6 = nil; - child7 = nil; - child8 = nil; - child9 = nil; - -} - --(void)testSOSCCWaitForInitialSync -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - bool worked = SOSCCWaitForInitialSyncWithAnalytics(parentData, &error); - XCTAssertTrue(worked, "should have worked"); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCRemoveThisDeviceFromCircle -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - bool worked = SOSCCRemoveThisDeviceFromCircleWithAnalytics(parentData, &error); - XCTAssertTrue(worked, "should have worked"); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCRequestToJoinCircle -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - SOSCCRequestToJoinCircleWithAnalytics(parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCRequestToJoinCircleAfterRestore -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - SOSCCRequestToJoinCircleAfterRestoreWithAnalytics(parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCRemovePeersFromCircle -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - NSArray* peers = [NSArray array]; - SOSCCRemovePeersFromCircleWithAnalytics((__bridge CFArrayRef)peers, parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - - --(void)testSOSCCViewSet -{ - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - CFSetRef enabledViews = nil; - CFSetRef disabledViews = nil; - SOSCCViewSetWithAnalytics(enabledViews, disabledViews, parentData); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCSetUserCredentialsAndDSID -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - CFStringRef label = nil; - CFDataRef password = nil; - CFStringRef dsid = nil; - SOSCCSetUserCredentialsAndDSIDWithAnalytics(label, password, dsid, parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCResetToEmpty -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - SOSCCResetToEmptyWithAnalytics(parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - -- (void)testMultipleDBConnections -{ - NSError* error = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorBottleID userInfo:@{NSLocalizedDescriptionKey: @"Failed to deserialize bottle peer"}]; - dispatch_queue_t test_queue = dispatch_queue_create("com.apple.security.signin.tests", DISPATCH_QUEUE_CONCURRENT_WITH_AUTORELEASE_POOL); - - for(int i = 0; i < 1000; i++){ - SFSignInAnalytics *test1 = [_metric newSubTaskForEvent:@"connection1"]; - SFSignInAnalytics *test2 = [_metric newSubTaskForEvent:@"connection2"]; - - dispatch_async(test_queue, ^{ - [test1 logRecoverableError:error]; - }); - dispatch_async(test_queue, ^{ - [test2 stopWithAttributes:nil]; - }); - dispatch_async(test_queue, ^{ - [self->_metric logRecoverableError:error]; - }); - } -} -@end diff --git a/keychain/Trieste/.swiftlint.yml b/keychain/Trieste/.swiftlint.yml new file mode 100644 index 00000000..9ddd0d11 --- /dev/null +++ b/keychain/Trieste/.swiftlint.yml @@ -0,0 +1,3 @@ +disabled_rules: + - force_cast + - force_try diff --git a/keychain/Trieste/OctagonTestHarnessXPCService/SecRemoteDevice.m b/keychain/Trieste/OctagonTestHarnessXPCService/SecRemoteDevice.m index db9d9914..b19065e8 100644 --- a/keychain/Trieste/OctagonTestHarnessXPCService/SecRemoteDevice.m +++ b/keychain/Trieste/OctagonTestHarnessXPCService/SecRemoteDevice.m @@ -67,8 +67,7 @@ - (instancetype)initAsInitiator:(bool)initiator version:(KCPairingChannelContext *)peerVersionContext device:(SecRemoteDevice *)device { - self = [super init]; - if (self) { + if ((self = [super init])) { self.remoteVersionContext = peerVersionContext; self.initiator = initiator; self.device = device; @@ -135,7 +134,7 @@ - (void)sosCircleStatus:(void(^)(SOSCCStatus status, NSError *error))complete { - SOSCloudKeychainFlush(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef __unused returnedValues, CFErrorRef __unused sync_error) { + SOSCloudKeychainFlush(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef __unused returnedValues, CFErrorRef __unused sync_error) { CFErrorRef cferror = NULL; SOSCCStatus status = SOSCCThisDeviceIsInCircle(&cferror); complete(status, (__bridge NSError *)cferror); @@ -145,7 +144,7 @@ - (void)sosCircleStatusNonCached:(void(^)(SOSCCStatus status, NSError *error))complete { - SOSCloudKeychainFlush(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef __unused returnedValues, CFErrorRef __unused sync_error) { + SOSCloudKeychainFlush(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), ^(CFDictionaryRef __unused returnedValues, CFErrorRef __unused sync_error) { CFErrorRef cferror = NULL; SOSCCStatus status = SOSCCThisDeviceIsInCircleNonCached(&cferror); complete(status, (__bridge NSError *)cferror); diff --git a/keychain/Trieste/OctagonTriesteTests/Tests/OctagonTriesteTests/OctagonTests.swift b/keychain/Trieste/OctagonTriesteTests/Tests/OctagonTriesteTests/OctagonTests.swift index a97ab461..b63671b2 100644 --- a/keychain/Trieste/OctagonTriesteTests/Tests/OctagonTriesteTests/OctagonTests.swift +++ b/keychain/Trieste/OctagonTriesteTests/Tests/OctagonTriesteTests/OctagonTests.swift @@ -16,7 +16,6 @@ extension CDAIOSDevice { } final class OctagonTests: CDTTestCase { - let username: String? = nil let password: String? = nil var signedIn: Bool = false @@ -77,7 +76,7 @@ final class OctagonTests: CDTTestCase { } addTeardownBlock { - if (self.signedIn) { + if self.signedIn { do { let listAccounts = try device.executeFile(atPath: "/usr/local/bin/accounts_tool", withArguments: ["--no-confirmation", "deleteAccountsForUsername", self.username!]) XCTAssertEqual(listAccounts.returnCode, 0, "deleteAccountsForUsername") @@ -89,7 +88,7 @@ final class OctagonTests: CDTTestCase { device.relinquish() } - if (self.username != nil) { + if self.username != nil { CDALog(at: .infoLevel, "Signing in to iCloud here \(self.username!)") let listAccounts = try device.executeFile(atPath: "/usr/local/bin/accounts_tool", withArguments: ["listAccounts", "-v"]) @@ -111,7 +110,6 @@ final class OctagonTests: CDTTestCase { } func compareCKKSZone(name zone: String, status1: NSDictionary, status2: NSDictionary) -> Bool { - let zone1 = status1[zone] as! NSDictionary let zone2 = status2[zone] as! NSDictionary @@ -136,7 +134,6 @@ final class OctagonTests: CDTTestCase { } func compareCKKSStatus(c1: NSDictionary, c2: NSDictionary) -> Bool { - let status1 = c1["status"] as! NSDictionary let status2 = c2["status"] as! NSDictionary @@ -150,13 +147,13 @@ final class OctagonTests: CDTTestCase { func sosStatus(_ device: CDAIOSDevice, verbose: Bool = false) throws { let result = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-i"]) - if (verbose) { + if verbose { print("security sync -i\n\(String(data: result.standardOutput, encoding: .utf8)!)\n") } } func ckksStatus(_ device: CDAIOSDevice, verbose: Bool = false) throws -> NSDictionary { let ckks = try device.executeFile(atPath: self.ckksTool, withArguments: ["status", "--json"]) - if (verbose) { + if verbose { print("ckks status\n\(String(data: ckks.standardOutput, encoding: .utf8)!)\n") } @@ -164,8 +161,7 @@ final class OctagonTests: CDTTestCase { } func sosApplication(_ device: CDAIOSDevice, verbose: Bool = false) throws { - if (self.password != nil) { - + if self.password != nil { print("submitting application\n") let password = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-P", self.password!]) @@ -182,8 +178,7 @@ final class OctagonTests: CDTTestCase { } func sosApprove(_ device: CDAIOSDevice, verbose: Bool = false) throws { - if (self.password != nil) { - + if self.password != nil { print("approving applications\n") let password = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-P", self.password!]) @@ -200,7 +195,7 @@ final class OctagonTests: CDTTestCase { } func forceResetSOS(_ device: CDAIOSDevice, resetCKKS: Bool = false) throws { - if (self.password != nil) { + if self.password != nil { _ = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-P", self.password!]) _ = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-R"]) _ = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-C"]) @@ -213,7 +208,7 @@ final class OctagonTests: CDTTestCase { print("sleeping some to allow cdpd, cloudd and friends to catch up \n") sleep(4) - if (resetCKKS) { + if resetCKKS { _ = try device.executeFile(atPath: self.ckksTool, withArguments: ["reset-cloudkit"]) print("sleeps some after ckksctl reset (should be removed)\n") @@ -234,7 +229,7 @@ final class OctagonTests: CDTTestCase { } func test2DeviceSOS() throws { - if (self.password == nil) { + if self.password == nil { print("this test only works with password") return } @@ -272,9 +267,9 @@ final class OctagonTests: CDTTestCase { for i in 0..<2 { CDALog(at: .infoLevel, "Reset \(i)") - octagon.octagonReset("altDSID", complete: { _, error in + octagon.octagonReset("altDSID") { _, error in CDTAssert(error == nil, "Octagon wasn't reset, error was \(String(describing: error))") - }) + } } } diff --git a/keychain/Trieste/OctagonTriesteTests/remake-local-project.sh b/keychain/Trieste/OctagonTriesteTests/remake-local-project.sh old mode 100644 new mode 100755 diff --git a/keychain/TrustedPeersHelper/BottledPeer/BottledPeer.swift b/keychain/TrustedPeersHelper/BottledPeer/BottledPeer.swift index ff8a8929..415e5d4b 100644 --- a/keychain/TrustedPeersHelper/BottledPeer/BottledPeer.swift +++ b/keychain/TrustedPeersHelper/BottledPeer/BottledPeer.swift @@ -25,22 +25,21 @@ import Foundation import SecurityFoundation class BottledPeer: NSObject { + var escrowKeys: EscrowKeys + var secret: Data + var peerID: String + var bottleID: String + var peerKeys: OctagonSelfPeerKeys - public var escrowKeys: EscrowKeys - public var secret: Data - public var peerID: String - public var bottleID: String - public var peerKeys: OctagonSelfPeerKeys + var signatureUsingEscrowKey: Data + var signatureUsingPeerKey: Data + var escrowSigningPublicKey: Data + var escrowSigningSPKI: Data + var peersigningSPKI: Data - public var signatureUsingEscrowKey: Data - public var signatureUsingPeerKey: Data - public var escrowSigningPublicKey: Data - public var escrowSigningSPKI: Data - public var peersigningSPKI: Data + var contents: Data - public var contents: Data - - public class func encryptionOperation() -> (_SFAuthenticatedEncryptionOperation) { + class func encryptionOperation() -> (_SFAuthenticatedEncryptionOperation) { let keySpecifier = _SFAESKeySpecifier.init(bitSize: TPHObjectiveC.aes256BitSize()) return _SFAuthenticatedEncryptionOperation.init(keySpecifier: keySpecifier) } @@ -48,8 +47,7 @@ class BottledPeer: NSObject { // Given a peer's details including private key material, and // the keys generated from the escrow secret, encrypt the peer private keys, // make a bottled peer object and serialize it into data. - public init (peerID: String, bottleID: String, peerSigningKey: _SFECKeyPair, peerEncryptionKey: _SFECKeyPair, bottleSalt: String) throws { - + init (peerID: String, bottleID: String, peerSigningKey: _SFECKeyPair, peerEncryptionKey: _SFECKeyPair, bottleSalt: String) throws { let secret = try BottledPeer.makeMeSomeEntropy(requiredLength: Int(OTMasterSecretLength)) self.secret = secret @@ -130,8 +128,7 @@ class BottledPeer: NSObject { // Deserialize a bottle (data) and decrypt the contents (peer keys) // using the keys generated from the escrow secret, and signatures from signing keys - public init (contents: Data, secret: Data, bottleSalt: String, signatureUsingEscrow: Data, signatureUsingPeerKey: Data) throws { - + init (contents: Data, secret: Data, bottleSalt: String, signatureUsingEscrow: Data, signatureUsingPeerKey: Data) throws { self.secret = secret self.escrowKeys = try EscrowKeys(secret: self.secret, bottleSalt: bottleSalt) @@ -166,7 +163,7 @@ class BottledPeer: NSObject { let ciphertext = _SFAuthenticatedCiphertext.init(ciphertext: ac.ciphertext, authenticationCode: ac.authenticationCode, initializationVector: ac.initializationVector) let clearContentsData = try op.decrypt(ciphertext, with: escrowKeys.symmetricKey) - if clearContentsData.count == 0 { + if clearContentsData.isEmpty { throw Error.OTErrorDecryptionFailure } @@ -210,24 +207,24 @@ class BottledPeer: NSObject { try xso.verify(peerSigned, with: peerPublicKey) } - public func escrowSigningPublicKeyHash() -> String { + func escrowSigningPublicKeyHash() -> String { return TPHObjectiveC.digest(usingSha384: self.escrowSigningPublicKey) } - public class func signingOperation() -> (_SFEC_X962SigningOperation) { + class func signingOperation() -> (_SFEC_X962SigningOperation) { let keySpecifier = _SFECKeySpecifier.init(curve: SFEllipticCurve.nistp384) let digestOperation = _SFSHA384DigestOperation.init() return _SFEC_X962SigningOperation.init(keySpecifier: keySpecifier, digestOperation: digestOperation) } - public class func verifyBottleSignature(data: Data, signature: Data, pubKey: _SFECPublicKey) throws -> (Bool) { + class func verifyBottleSignature(data: Data, signature: Data, pubKey: _SFECPublicKey) throws -> (Bool) { let xso = BottledPeer.signingOperation() let peerSigned = _SFSignedData.init(data: data, signature: signature) try xso.verify(peerSigned, with: pubKey) return true } - public class func makeMeSomeEntropy(requiredLength: Int) throws -> Data { + class func makeMeSomeEntropy(requiredLength: Int) throws -> Data { let bytesPointer = UnsafeMutableRawPointer.allocate(byteCount: requiredLength, alignment: 1) if SecRandomCopyBytes(kSecRandomDefault, requiredLength, bytesPointer) != 0 { @@ -253,7 +250,7 @@ extension BottledPeer { } extension BottledPeer.Error: LocalizedError { - public var errorDescription: String? { + var errorDescription: String? { switch self { case .OTErrorDeserializationFailure: return "Failed to deserialize bottle peer" diff --git a/keychain/TrustedPeersHelper/BottledPeer/EscrowKeys.swift b/keychain/TrustedPeersHelper/BottledPeer/EscrowKeys.swift index 04bb5f27..206463d0 100644 --- a/keychain/TrustedPeersHelper/BottledPeer/EscrowKeys.swift +++ b/keychain/TrustedPeersHelper/BottledPeer/EscrowKeys.swift @@ -28,31 +28,31 @@ let OT_ESCROW_SIGNING_HKDF_SIZE = 56 let OT_ESCROW_ENCRYPTION_HKDF_SIZE = 56 let OT_ESCROW_SYMMETRIC_HKDF_SIZE = 32 -enum escrowKeyType: Int { +enum EscrowKeyType: Int { case kOTEscrowKeySigning = 1 case kOTEscrowKeyEncryption = 2 case kOTEscrowKeySymmetric = 3 } class EscrowKeys: NSObject { - public var encryptionKey: _SFECKeyPair - public var signingKey: _SFECKeyPair - public var symmetricKey: _SFAESKey + var encryptionKey: _SFECKeyPair + var signingKey: _SFECKeyPair + var symmetricKey: _SFAESKey - public var secret: Data - public var bottleSalt: String + var secret: Data + var bottleSalt: String - public init (secret: Data, bottleSalt: String) throws { + init (secret: Data, bottleSalt: String) throws { self.secret = secret self.bottleSalt = bottleSalt - let encryptionKeyData = try EscrowKeys.generateEscrowKey(keyType: escrowKeyType.kOTEscrowKeyEncryption, masterSecret: secret, bottleSalt: bottleSalt) + let encryptionKeyData = try EscrowKeys.generateEscrowKey(keyType: EscrowKeyType.kOTEscrowKeyEncryption, masterSecret: secret, bottleSalt: bottleSalt) self.encryptionKey = _SFECKeyPair.init(secKey: try EscrowKeys.createSecKey(keyData: encryptionKeyData)) - let signingKeyData = try EscrowKeys.generateEscrowKey(keyType: escrowKeyType.kOTEscrowKeySigning, masterSecret: secret, bottleSalt: bottleSalt) + let signingKeyData = try EscrowKeys.generateEscrowKey(keyType: EscrowKeyType.kOTEscrowKeySigning, masterSecret: secret, bottleSalt: bottleSalt) self.signingKey = _SFECKeyPair.init(secKey: try EscrowKeys.createSecKey(keyData: signingKeyData)) - let symmetricKeyData = try EscrowKeys.generateEscrowKey(keyType: escrowKeyType.kOTEscrowKeySymmetric, masterSecret: secret, bottleSalt: bottleSalt) + let symmetricKeyData = try EscrowKeys.generateEscrowKey(keyType: EscrowKeyType.kOTEscrowKeySymmetric, masterSecret: secret, bottleSalt: bottleSalt) let specifier = _SFAESKeySpecifier.init(bitSize: TPHObjectiveC.aes256BitSize()) self.symmetricKey = try _SFAESKey.init(data: symmetricKeyData, specifier: specifier) @@ -62,34 +62,30 @@ class EscrowKeys: NSObject { _ = try EscrowKeys.storeEscrowedSymmetricKey(keyData: self.symmetricKey.keyData, label: escrowSigningPubKeyHash) } - class func generateEscrowKey(keyType: escrowKeyType, masterSecret: Data, bottleSalt: String) throws -> (Data) { + class func generateEscrowKey(keyType: EscrowKeyType, masterSecret: Data, bottleSalt: String) throws -> (Data) { var keyLength: Int var info: Data var derivedKey: Data var finalKey = Data() switch keyType { - case escrowKeyType.kOTEscrowKeySymmetric: + case EscrowKeyType.kOTEscrowKeySymmetric: keyLength = OT_ESCROW_SYMMETRIC_HKDF_SIZE let infoString = Array("Escrow Symmetric Key".utf8) info = Data(bytes: infoString, count: infoString.count) - break - case escrowKeyType.kOTEscrowKeyEncryption: + case EscrowKeyType.kOTEscrowKeyEncryption: keyLength = OT_ESCROW_ENCRYPTION_HKDF_SIZE let infoString = Array("Escrow Encryption Private Key".utf8) info = Data(bytes: infoString, count: infoString.count) - break - case escrowKeyType.kOTEscrowKeySigning: + case EscrowKeyType.kOTEscrowKeySigning: keyLength = OT_ESCROW_SIGNING_HKDF_SIZE let infoString = Array("Escrow Signing Private Key".utf8) info = Data(bytes: infoString, count: infoString.count) - - break } guard let cp = ccec_cp_384() else { @@ -119,13 +115,13 @@ class EscrowKeys: NSObject { throw EscrowKeysError.corecryptoKeyGeneration(corecryptoError: status) } - if(keyType == escrowKeyType.kOTEscrowKeySymmetric) { + if keyType == EscrowKeyType.kOTEscrowKeySymmetric { finalKey = Data(buffer: derivedKeyBytes.bindMemory(to: UInt8.self)) return - } else if(keyType == escrowKeyType.kOTEscrowKeyEncryption || keyType == escrowKeyType.kOTEscrowKeySigning) { + } else if keyType == EscrowKeyType.kOTEscrowKeyEncryption || keyType == EscrowKeyType.kOTEscrowKeySigning { status = ccec_generate_key_deterministic(cp, derivedKeyBytes.count, derivedKeyBytes.bindMemory(to: UInt8.self).baseAddress!, - ccDRBGGetRngState(), + ccrng(nil), UInt32(CCEC_GENKEY_DETERMINISTIC_FIPS), fullKey) @@ -156,7 +152,7 @@ class EscrowKeys: NSObject { return key } - class func setKeyMaterialInKeychain(query: Dictionary) throws -> (Bool) { + class func setKeyMaterialInKeychain(query: [CFString: Any]) throws -> (Bool) { var result = false var results: CFTypeRef? @@ -165,7 +161,7 @@ class EscrowKeys: NSObject { if status == errSecSuccess { result = true } else if status == errSecDuplicateItem { - var updateQuery: Dictionary = query + var updateQuery: [CFString: Any] = query updateQuery[kSecClass] = nil status = SecItemUpdate(query as CFDictionary, updateQuery as CFDictionary) @@ -198,7 +194,6 @@ class EscrowKeys: NSObject { } class func storeEscrowedEncryptionKeyPair(keyData: Data, label: String) throws -> (Bool) { - let query: [CFString: Any] = [ kSecClass: kSecClassKey, kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, @@ -240,8 +235,8 @@ class EscrowKeys: NSObject { return try EscrowKeys.setKeyMaterialInKeychain(query: query) } - class func retrieveEscrowKeysFromKeychain(label: String) throws -> [Dictionary ]? { - var keySet: [Dictionary]? + class func retrieveEscrowKeysFromKeychain(label: String) throws -> [ [CFString: Any]]? { + var keySet: [[CFString: Any]]? let query: [CFString: Any] = [ kSecClass: kSecClassKey, @@ -261,10 +256,10 @@ class EscrowKeys: NSObject { } if result != nil { - if let dictionaryArray = result as? [Dictionary] { + if let dictionaryArray = result as? [[CFString: Any]] { keySet = dictionaryArray } else { - if let dictionary = result as? Dictionary { + if let dictionary = result as? [CFString: Any] { keySet = [dictionary] } else { keySet = nil @@ -287,15 +282,15 @@ class EscrowKeys: NSObject { let keyTypeData = item[kSecAttrApplicationLabel as CFString] as! Data let keyType = String(data: keyTypeData, encoding: .utf8)! - if keyType.range(of: "Symmetric") != nil { + if keyType.contains("Symmetric") { let keyData = item[kSecValueData as CFString] as! Data let specifier = _SFAESKeySpecifier.init(bitSize: TPHObjectiveC.aes256BitSize()) symmetricKey = try _SFAESKey.init(data: keyData, specifier: specifier) - } else if keyType.range(of: "Encryption") != nil { + } else if keyType.contains("Encryption") { let keyData = item[kSecValueData as CFString] as! Data let encryptionSecKey = try EscrowKeys.createSecKey(keyData: keyData) encryptionKey = _SFECKeyPair.init(secKey: encryptionSecKey) - } else if keyType.range(of: "Signing") != nil { + } else if keyType.contains("Signing") { let keyData = item[kSecValueData as CFString] as! Data let signingSecKey = try EscrowKeys.createSecKey(keyData: keyData) signingKey = _SFECKeyPair.init(secKey: signingSecKey) @@ -317,7 +312,7 @@ enum EscrowKeysError: Error { } extension EscrowKeysError: LocalizedError { - public var errorDescription: String? { + var errorDescription: String? { switch self { case .keyGeneration: return "Key generation failed" @@ -334,12 +329,11 @@ extension EscrowKeysError: LocalizedError { } extension EscrowKeysError: CustomNSError { - - public static var errorDomain: String { + static var errorDomain: String { return "com.apple.security.trustedpeers.EscrowKeys" } - public var errorCode: Int { + var errorCode: Int { switch self { case .keyGeneration: return 1 @@ -354,7 +348,7 @@ extension EscrowKeysError: CustomNSError { } } - public var errorUserInfo: [String: Any] { + var errorUserInfo: [String: Any] { var userInfo: [String: Any] = [:] if let desc = self.errorDescription { userInfo[NSLocalizedDescriptionKey] = desc diff --git a/keychain/TrustedPeersHelper/Client.swift b/keychain/TrustedPeersHelper/Client.swift index 0a062b79..ecbdb479 100644 --- a/keychain/TrustedPeersHelper/Client.swift +++ b/keychain/TrustedPeersHelper/Client.swift @@ -23,8 +23,39 @@ import Foundation -class Client: TrustedPeersHelperProtocol { +extension Error { + func sanitizeForClientXPC() -> Error { + let nserror = self as NSError + // CoreData errors might have extra things in them that need removal. + if nserror.domain == NSCocoaErrorDomain { + return nserror.cleanAllButDescription() + } + + // The docs for CKXPCSuitableError say it only returns nil if you pass it nil, but swift can't read those. + guard let ckCleanedError = CKXPCSuitableError(self) else { + return ContainerError.unknownCloudKitError + } + return ckCleanedError + } +} + +extension NSError { + func cleanAllButDescription() -> NSError { + let userInfo: [String: AnyHashable]? + if let description = self.userInfo[NSLocalizedDescriptionKey] as? AnyHashable { + userInfo = [NSLocalizedDescriptionKey: description] + } else { + userInfo = nil + } + + return NSError(domain: self.domain, + code: self.code, + userInfo: userInfo) + } +} + +class Client: TrustedPeersHelperProtocol { let endpoint: NSXPCListenerEndpoint? let containerMap: ContainerMap @@ -39,9 +70,9 @@ class Client: TrustedPeersHelperProtocol { func logComplete(function: String, container: ContainerName, error: Error?) { if let error = error { - os_log("%@ errored for %@: %@", log: tplogDebug, type: .default, function, container.description, error as CVarArg) + os_log("%{public}@ errored for %{public}@: %{public}@", log: tplogDebug, type: .default, function, container.description, error as CVarArg) } else { - os_log("%@ finished for %@", log: tplogDebug, type: .default, function, container.description) + os_log("%{public}@ finished for %{public}@", log: tplogDebug, type: .default, function, container.description) } } @@ -53,15 +84,15 @@ class Client: TrustedPeersHelperProtocol { func dump(withContainer container: String, context: String, reply: @escaping ([AnyHashable: Any]?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Dumping for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Dumping for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.dump { result, error in self.logComplete(function: "Dumping", container: container.name, error: error) - reply(result, CKXPCSuitableError(error)) + reply(result, error?.sanitizeForClientXPC()) } } catch { - os_log("Dumping failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + os_log("Dumping failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, error.sanitizeForClientXPC()) } } @@ -70,15 +101,15 @@ class Client: TrustedPeersHelperProtocol { reply: @escaping (String?, TPPeerPermanentInfo?, TPPeerStableInfo?, TPPeerDynamicInfo?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Dumping peer for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Dumping peer for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.dumpEgoPeer { peerID, perm, stable, dyn, error in self.logComplete(function: "Dumping peer", container: container.name, error: error) - reply(peerID, perm, stable, dyn, CKXPCSuitableError(error)) + reply(peerID, perm, stable, dyn, error?.sanitizeForClientXPC()) } } catch { - os_log("Dumping peer failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, nil, nil, CKXPCSuitableError(error)) + os_log("Dumping peer failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, nil, nil, error.sanitizeForClientXPC()) } } @@ -86,75 +117,81 @@ class Client: TrustedPeersHelperProtocol { do { let containerName = ContainerName(container: container, context: context) let container = try self.containerMap.findOrCreate(name: containerName) - container.trustStatus(reply: reply) + container.trustStatus { egoPeerStatus, error in + reply(egoPeerStatus, error?.sanitizeForClientXPC()) + } } catch { - os_log("Trust status failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) + os_log("Trust status failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) reply(TrustedPeersHelperEgoPeerStatus(egoPeerID: nil, + egoPeerMachineID: nil, status: TPPeerStatus.unknown, viablePeerCountsByModelID: [:], peerCountsByMachineID: [:], isExcluded: false, isLocked: false), - CKXPCSuitableError(error)) + error.sanitizeForClientXPC()) } } func fetchTrustState(withContainer container: String, context: String, reply: @escaping (TrustedPeersHelperPeerState?, [TrustedPeersHelperPeer]?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Fetch Trust State for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Fetch Trust State for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.fetchTrustState(reply: reply) + container.fetchTrustState { peerState, peerList, error in + reply(peerState, peerList, error?.sanitizeForClientXPC()) + } } catch { - os_log("Fetch Trust State failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + os_log("Fetch Trust State failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, error.sanitizeForClientXPC()) } } func reset(withContainer container: String, context: String, resetReason: CuttlefishResetReason, reply: @escaping (Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Resetting for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Resetting for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.reset(resetReason: resetReason) { error in self.logComplete(function: "Resetting", container: container.name, error: error) - reply(CKXPCSuitableError(error)) } + reply(error?.sanitizeForClientXPC()) } } catch { - os_log("Resetting failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + os_log("Resetting failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } } func localReset(withContainer container: String, context: String, reply: @escaping (Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Performing local reset for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Performing local reset for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.localReset { error in self.logComplete(function: "Local reset", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { - os_log("Local reset failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + os_log("Local reset failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } } func setAllowedMachineIDsWithContainer(_ container: String, context: String, allowedMachineIDs: Set, + honorIDMSListChanges: Bool, reply: @escaping (Bool, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Setting allowed machineIDs for %@ to %@", log: tplogDebug, type: .default, containerName.description, allowedMachineIDs) + os_log("Setting allowed machineIDs for %{public}@ to %{public}@", log: tplogDebug, type: .default, containerName.description, allowedMachineIDs) let container = try self.containerMap.findOrCreate(name: containerName) - container.setAllowedMachineIDs(allowedMachineIDs) { differences, error in + container.setAllowedMachineIDs(allowedMachineIDs, honorIDMSListChanges: honorIDMSListChanges) { differences, error in self.logComplete(function: "Setting allowed machineIDs", container: container.name, error: error) - reply(differences, CKXPCSuitableError(error)) + reply(differences, error?.sanitizeForClientXPC()) } } catch { - os_log("Setting allowed machineIDs failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(false, CKXPCSuitableError(error)) + os_log("Setting allowed machineIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(false, error.sanitizeForClientXPC()) } } @@ -164,15 +201,15 @@ class Client: TrustedPeersHelperProtocol { reply: @escaping (Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Adding allowed machineIDs for %@: %@", log: tplogDebug, type: .default, containerName.description, machineIDs) + os_log("Adding allowed machineIDs for %{public}@: %{public}@", log: tplogDebug, type: .default, containerName.description, machineIDs) let container = try self.containerMap.findOrCreate(name: containerName) container.addAllow(machineIDs) { error in self.logComplete(function: "Adding allowed machineIDs", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { - os_log("Adding allowed machineID failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + os_log("Adding allowed machineID failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } } @@ -182,44 +219,44 @@ class Client: TrustedPeersHelperProtocol { reply: @escaping (Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Removing allowed machineIDs for %@: %@", log: tplogDebug, type: .default, containerName.description, machineIDs) + os_log("Removing allowed machineIDs for %{public}@: %{public}@", log: tplogDebug, type: .default, containerName.description, machineIDs) let container = try self.containerMap.findOrCreate(name: containerName) container.removeAllow(machineIDs) { error in self.logComplete(function: "Removing allowed machineIDs", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { - os_log("Removing allowed machineID failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + os_log("Removing allowed machineID failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } } func fetchAllowedMachineIDs(withContainer container: String, context: String, reply: @escaping (Set?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Fetching allowed machineIDs for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Fetching allowed machineIDs for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.fetchAllowedMachineIDs() { mids, error in + container.fetchAllowedMachineIDs { mids, error in self.logComplete(function: "Fetched allowed machineIDs", container: container.name, error: error) - reply(mids, CKXPCSuitableError(error)) + reply(mids, error?.sanitizeForClientXPC()) } } catch { - os_log("Fetching allowed machineIDs failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + os_log("Fetching allowed machineIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, error.sanitizeForClientXPC()) } } func fetchEgoEpoch(withContainer container: String, context: String, reply: @escaping (UInt64, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("retrieving epoch for %@", log: tplogDebug, type: .default, containerName.description) + os_log("retrieving epoch for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.getEgoEpoch { epoch, error in - reply(epoch, CKXPCSuitableError(error)) + reply(epoch, error?.sanitizeForClientXPC()) } } catch { - os_log("Epoch retrieval failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(0, CKXPCSuitableError(error)) + os_log("Epoch retrieval failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(0, error.sanitizeForClientXPC()) } } @@ -231,16 +268,17 @@ class Client: TrustedPeersHelperProtocol { bottleID: String, modelID: String, deviceName: String?, - serialNumber: String, + serialNumber: String?, osVersion: String, - policyVersion: NSNumber?, + policyVersion: TPPolicyVersion?, policySecrets: [String: Data]?, + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus, signingPrivKeyPersistentRef: Data?, encPrivKeyPersistentRef: Data?, - reply: @escaping (String?, Data?, Data?, Data?, Data?, Error?) -> Void) { + reply: @escaping (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Preparing new identity for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Preparing new identity for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.prepare(epoch: epoch, machineID: machineID, @@ -250,16 +288,17 @@ class Client: TrustedPeersHelperProtocol { deviceName: deviceName, serialNumber: serialNumber, osVersion: osVersion, - policyVersion: policyVersion?.uint64Value, + policyVersion: policyVersion, policySecrets: policySecrets, + syncUserControllableViews: syncUserControllableViews, signingPrivateKeyPersistentRef: signingPrivKeyPersistentRef, - encryptionPrivateKeyPersistentRef: encPrivKeyPersistentRef) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encryptionPrivateKeyPersistentRef: encPrivKeyPersistentRef) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, policy, error in self.logComplete(function: "Prepare", container: container.name, error: error) - reply(peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, CKXPCSuitableError(error)) + reply(peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, policy, error?.sanitizeForClientXPC()) } } catch { - os_log("Prepare failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, nil, nil, nil, CKXPCSuitableError(error)) + os_log("Prepare failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, nil, nil, nil, nil, error.sanitizeForClientXPC()) } } @@ -268,19 +307,19 @@ class Client: TrustedPeersHelperProtocol { ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord]?, Error?) -> Void) { + reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Establishing %@", log: tplogDebug, type: .default, containerName.description) + os_log("Establishing %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.establish(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, error in + preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in self.logComplete(function: "Establishing", container: container.name, error: error) - reply(peerID, keyHierarchyRecords, CKXPCSuitableError(error)) } + reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC()) } } catch { - os_log("Establishing failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + os_log("Establishing failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, nil, error.sanitizeForClientXPC()) } } @@ -295,7 +334,7 @@ class Client: TrustedPeersHelperProtocol { reply: @escaping (Data?, Data?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Vouching %@", log: tplogDebug, type: .default, containerName.description) + os_log("Vouching %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.vouch(peerID: peerID, permanentInfo: permanentInfo, @@ -304,27 +343,27 @@ class Client: TrustedPeersHelperProtocol { stableInfoSig: stableInfoSig, ckksKeys: ckksKeys) { voucher, voucherSig, error in self.logComplete(function: "Vouching", container: container.name, error: error) - reply(voucher, voucherSig, CKXPCSuitableError(error)) } + reply(voucher, voucherSig, error?.sanitizeForClientXPC()) } } catch { - os_log("Vouching failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + os_log("Vouching failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, error.sanitizeForClientXPC()) } } func preflightVouchWithBottle(withContainer container: String, context: String, bottleID: String, - reply: @escaping (String?, Error?) -> Void) { + reply: @escaping (String?, TPSyncingPolicy?, Bool, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Preflight Vouch With Bottle %@", log: tplogDebug, type: .default, containerName.description) + os_log("Preflight Vouch With Bottle %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.preflightVouchWithBottle(bottleID: bottleID) { peerID, error in + container.preflightVouchWithBottle(bottleID: bottleID) { peerID, policy, refetched, error in self.logComplete(function: "Preflight Vouch With Bottle", container: container.name, error: error) - reply(peerID, CKXPCSuitableError(error)) } + reply(peerID, policy, refetched, error?.sanitizeForClientXPC()) } } catch { - os_log("Preflighting Vouch With Bottle failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + os_log("Preflighting Vouch With Bottle failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, false, error.sanitizeForClientXPC()) } } @@ -334,17 +373,35 @@ class Client: TrustedPeersHelperProtocol { entropy: Data, bottleSalt: String, tlkShares: [CKKSTLKShare], - reply: @escaping (Data?, Data?, Error?) -> Void) { + reply: @escaping (Data?, Data?, Int64, Int64, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Vouching With Bottle %@", log: tplogDebug, type: .default, containerName.description) + os_log("Vouching With Bottle %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.vouchWithBottle(bottleID: bottleID, entropy: entropy, bottleSalt: bottleSalt, tlkShares: tlkShares) { voucher, voucherSig, error in + container.vouchWithBottle(bottleID: bottleID, entropy: entropy, bottleSalt: bottleSalt, tlkShares: tlkShares) { voucher, voucherSig, uniqueTLKsRecovered, totalTLKSharesRecovered, error in self.logComplete(function: "Vouching With Bottle", container: container.name, error: error) - reply(voucher, voucherSig, CKXPCSuitableError(error)) } + reply(voucher, voucherSig, uniqueTLKsRecovered, totalTLKSharesRecovered, error?.sanitizeForClientXPC()) } } catch { - os_log("Vouching with Bottle failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + os_log("Vouching with Bottle failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, 0, 0, error.sanitizeForClientXPC()) + } + } + + func preflightVouchWithRecoveryKey(withContainer container: String, + context: String, + recoveryKey: String, + salt: String, + reply: @escaping (String?, TPSyncingPolicy?, Error?) -> Void) { + do { + let containerName = ContainerName(container: container, context: context) + os_log("Preflight Vouch With RecoveryKey %{public}@", log: tplogDebug, type: .default, containerName.description) + let container = try self.containerMap.findOrCreate(name: containerName) + container.preflightVouchWithRecoveryKey(recoveryKey: recoveryKey, salt: salt) { rkID, policy, error in + self.logComplete(function: "Preflight Vouch With RecoveryKey", container: container.name, error: error) + reply(rkID, policy, error?.sanitizeForClientXPC()) } + } catch { + os_log("Preflighting Vouch With RecoveryKey failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, error.sanitizeForClientXPC()) } } @@ -356,14 +413,14 @@ class Client: TrustedPeersHelperProtocol { reply: @escaping (Data?, Data?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Vouching With Recovery Key %@", log: tplogDebug, type: .default, containerName.description) + os_log("Vouching With Recovery Key %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.vouchWithRecoveryKey(recoveryKey: recoveryKey, salt: salt, tlkShares: tlkShares) { voucher, voucherSig, error in self.logComplete(function: "Vouching With Recovery Key", container: container.name, error: error) - reply(voucher, voucherSig, CKXPCSuitableError(error)) } + reply(voucher, voucherSig, error?.sanitizeForClientXPC()) } } catch { - os_log("Vouching with Recovery Key failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + os_log("Vouching with Recovery Key failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, error.sanitizeForClientXPC()) } } @@ -373,32 +430,37 @@ class Client: TrustedPeersHelperProtocol { voucherSig: Data, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data], - reply: @escaping (String?, [CKRecord]?, Error?) -> Void) { + preapprovedKeys: [Data]?, + reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Joining %@", log: tplogDebug, type: .default, containerName.description) + os_log("Joining %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.join(voucherData: voucherData, voucherSig: voucherSig, ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, error in reply(peerID, keyHierarchyRecords, CKXPCSuitableError(error)) } + preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in + reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC()) + } } catch { - reply(nil, nil, CKXPCSuitableError(error)) + os_log("Joining failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, nil, error.sanitizeForClientXPC()) } } func preflightPreapprovedJoin(withContainer container: String, context: String, + preapprovedKeys: [Data]?, reply: @escaping (Bool, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Attempting to preflight a preapproved join for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Attempting to preflight a preapproved join for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.preflightPreapprovedJoin { success, error in reply(success, CKXPCSuitableError(error)) } + container.preflightPreapprovedJoin(preapprovedKeys: preapprovedKeys) { success, error in reply(success, error?.sanitizeForClientXPC()) } } catch { - reply(false, CKXPCSuitableError(error)) + os_log("preflightPreapprovedJoin failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(false, error.sanitizeForClientXPC()) } } @@ -406,17 +468,19 @@ class Client: TrustedPeersHelperProtocol { context: String, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data], - reply: @escaping (String?, [CKRecord]?, Error?) -> Void) { + preapprovedKeys: [Data]?, + reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Attempting a preapproved join for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Attempting a preapproved join for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.preapprovedJoin(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, error in reply(peerID, keyHierarchyRecords, CKXPCSuitableError(error)) } + preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in + reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC()) } } catch { - reply(nil, nil, CKXPCSuitableError(error)) + os_log("attemptPreapprovedJoin failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, nil, error.sanitizeForClientXPC()) } } @@ -427,32 +491,53 @@ class Client: TrustedPeersHelperProtocol { osVersion: String?, policyVersion: NSNumber?, policySecrets: [String: Data]?, - reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { + syncUserControllableViews: NSNumber?, + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Updating %@", log: tplogDebug, type: .default, containerName.description) + os_log("Updating %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) + + let syncUserControllableSetting: TPPBPeerStableInfo_UserControllableViewStatus? + if let value = syncUserControllableViews?.int32Value { + switch value { + case TPPBPeerStableInfo_UserControllableViewStatus.ENABLED.rawValue: + syncUserControllableSetting = .ENABLED + case TPPBPeerStableInfo_UserControllableViewStatus.DISABLED.rawValue: + syncUserControllableSetting = .DISABLED + case TPPBPeerStableInfo_UserControllableViewStatus.FOLLOWING.rawValue: + syncUserControllableSetting = .FOLLOWING + default: + throw ContainerError.unknownSyncUserControllableViewsValue(value: value) + } + } else { + syncUserControllableSetting = nil + } + container.update(deviceName: deviceName, serialNumber: serialNumber, osVersion: osVersion, policyVersion: policyVersion?.uint64Value, - policySecrets: policySecrets) { state, error in reply(state, CKXPCSuitableError(error)) } + policySecrets: policySecrets, + syncUserControllableViews: syncUserControllableSetting) { state, policy, error in reply(state, policy, error?.sanitizeForClientXPC()) } } catch { - reply(nil, CKXPCSuitableError(error)) + os_log("update failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, error.sanitizeForClientXPC()) } } func setPreapprovedKeysWithContainer(_ container: String, - context: String, - preapprovedKeys: [Data], - reply: @escaping (Error?) -> Void) { + context: String, + preapprovedKeys: [Data], + reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Updating %@", log: tplogDebug, type: .default, containerName.description) + os_log("setPreapprovedKeysWithContainer %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.set(preapprovedKeys: preapprovedKeys) { error in reply(CKXPCSuitableError(error)) } + container.set(preapprovedKeys: preapprovedKeys) { state, error in reply(state, error?.sanitizeForClientXPC()) } } catch { - reply(CKXPCSuitableError(error)) + os_log("setPreapprovedKeysWithContainer failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, error.sanitizeForClientXPC()) } } @@ -463,13 +548,15 @@ class Client: TrustedPeersHelperProtocol { reply: @escaping ([CKRecord]?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Updating TLKs for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Updating TLKs for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.updateTLKs(ckksKeys: ckksKeys, - tlkShares: tlkShares, - reply: reply) + tlkShares: tlkShares) { records, error in + reply(records, error?.sanitizeForClientXPC()) + } } catch { - reply(nil, CKXPCSuitableError(error)) + os_log("updateTLKs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, error.sanitizeForClientXPC()) } } @@ -478,13 +565,14 @@ class Client: TrustedPeersHelperProtocol { reply: @escaping (Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Departing %@", log: tplogDebug, type: .default, containerName.description) + os_log("Departing %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.departByDistrustingSelf { error in - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { - reply(CKXPCSuitableError(error)) + os_log("departByDistrustingSelf failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } } @@ -494,177 +582,212 @@ class Client: TrustedPeersHelperProtocol { reply: @escaping (Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Distrusting %@ in %@", log: tplogDebug, type: .default, peerIDs, containerName.description) + os_log("Distrusting %{public}@ in %{public}@", log: tplogDebug, type: .default, peerIDs, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.distrust(peerIDs: peerIDs) { error in - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { - reply(CKXPCSuitableError(error)) + os_log("distrustPeerIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } } func fetchViableBottles(withContainer container: String, context: String, reply: @escaping ([String]?, [String]?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("fetchViableBottles in %@", log: tplogDebug, type: .default, containerName.description) + os_log("fetchViableBottles in %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.fetchViableBottles { sortedBottleIDs, partialBottleIDs, error in - reply(sortedBottleIDs, partialBottleIDs, CKXPCSuitableError(error)) + reply(sortedBottleIDs, partialBottleIDs, error?.sanitizeForClientXPC()) } } catch { - reply(nil, nil, CKXPCSuitableError(error)) + os_log("fetchViableBottles failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, error.sanitizeForClientXPC()) + } + } + + func fetchViableEscrowRecords(withContainer container: String, context: String, forceFetch: Bool, reply: @escaping ([Data]?, Error?) -> Void) { + do { + let containerName = ContainerName(container: container, context: context) + os_log("fetchViableEscrowRecords in %@", log: tplogDebug, type: .default, containerName.description) + let container = try self.containerMap.findOrCreate(name: containerName) + container.fetchEscrowRecords(forceFetch: forceFetch) { recordDatas, error in + reply(recordDatas, error?.sanitizeForClientXPC()) + } + } catch { + reply(nil, error.sanitizeForClientXPC()) } } func fetchEscrowContents(withContainer container: String, context: String, reply: @escaping (Data?, String?, Data?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("fetchEscrowContents in %@", log: tplogDebug, type: .default, containerName.description) + os_log("fetchEscrowContents in %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.fetchEscrowContents { entropy, bottleID, signingPublicKey, error in - reply(entropy, bottleID, signingPublicKey, CKXPCSuitableError(error)) + reply(entropy, bottleID, signingPublicKey, error?.sanitizeForClientXPC()) } } catch { - reply(nil, nil, nil, CKXPCSuitableError(error)) + os_log("fetchEscrowContents failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, nil, nil, error.sanitizeForClientXPC()) } } - func fetchPolicy(withContainer container: String, - context: String, - reply: @escaping (TPPolicy?, Error?) -> Void) { + func fetchCurrentPolicy(withContainer container: String, + context: String, + modelIDOverride: String?, + reply: @escaping (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Fetching policy for %@", log: tplogDebug, type: .default, containerName.description) + os_log("Fetching policy+views for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.fetchPolicy { policy, error in - reply(policy, CKXPCSuitableError(error)) + container.fetchCurrentPolicy(modelIDOverride: modelIDOverride) { policy, peersOpinion, error in + reply(policy, peersOpinion, error?.sanitizeForClientXPC()) } } catch { - reply(nil, CKXPCSuitableError(error)) + os_log("fetchCurrentPolicy failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, .UNKNOWN, error.sanitizeForClientXPC()) } } func fetchPolicyDocuments(withContainer container: String, context: String, - keys: [NSNumber: String], - reply: @escaping ([NSNumber: [String]]?, Error?) -> Void) { + versions: Set, + reply: @escaping ([TPPolicyVersion: Data]?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("Fetching policy documents %@ with keys: %@", log: tplogDebug, type: .default, containerName.description, keys) + os_log("Fetching policy documents %{public}@ with versions: %{public}@", log: tplogDebug, type: .default, containerName.description, versions) let container = try self.containerMap.findOrCreate(name: containerName) - container.fetchPolicyDocuments(keys: keys) { entries, error in - reply(entries, CKXPCSuitableError(error)) + container.fetchPolicyDocuments(versions: versions) { entries, error in + reply(entries, error?.sanitizeForClientXPC()) } } catch { - reply(nil, CKXPCSuitableError(error)) + os_log("fetchPolicyDocuments failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, error.sanitizeForClientXPC()) } } func validatePeers(withContainer container: String, context: String, reply: @escaping ([AnyHashable: Any]?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("ValidatePeers for %@", log: tplogDebug, type: .default, containerName.description) + os_log("ValidatePeers for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) let request = ValidatePeersRequest() container.validatePeers(request: request) { result, error in self.logComplete(function: "validatePeers", container: container.name, error: error) - reply(result, CKXPCSuitableError(error)) + reply(result, error?.sanitizeForClientXPC()) } } catch { - os_log("ValidatePeers failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + os_log("ValidatePeers failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, error.sanitizeForClientXPC()) } } - func setRecoveryKeyWithContainer(_ container: String, context: String, recoveryKey: String, salt: String, ckksKeys: [CKKSKeychainBackedKeySet], reply: @escaping (Error?) -> Void) { + func setRecoveryKeyWithContainer(_ container: String, + context: String, + recoveryKey: String, + salt: String, + ckksKeys: [CKKSKeychainBackedKeySet], + reply: @escaping ([CKRecord]?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("SetRecoveryKey for %@", log: tplogDebug, type: .default, containerName.description) + os_log("SetRecoveryKey for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.setRecoveryKey(recoveryKey: recoveryKey, salt: salt, ckksKeys: ckksKeys) { error in + container.setRecoveryKey(recoveryKey: recoveryKey, salt: salt, ckksKeys: ckksKeys) { records, error in self.logComplete(function: "setRecoveryKey", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(records, error?.sanitizeForClientXPC()) } } catch { - os_log("SetRecoveryKey failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + os_log("SetRecoveryKey failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, error.sanitizeForClientXPC()) } } func reportHealth(withContainer container: String, context: String, stateMachineState: String, trustState: String, reply: @escaping (Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("ReportHealth for %@", log: tplogDebug, type: .default, containerName.description) + os_log("ReportHealth for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) let request = ReportHealthRequest.with { $0.stateMachineState = stateMachineState } container.reportHealth(request: request) { error in self.logComplete(function: "reportHealth", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { - os_log("ReportHealth failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + os_log("ReportHealth failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } } func pushHealthInquiry(withContainer container: String, context: String, reply: @escaping (Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("PushHealthInquiry for %@", log: tplogDebug, type: .default, containerName.description) + os_log("PushHealthInquiry for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.pushHealthInquiry { error in self.logComplete(function: "pushHealthInquiry", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { - os_log("PushHealthInquiry failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + os_log("PushHealthInquiry failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } } - func getViewsWithContainer(_ container: String, context: String, inViews: [String], reply: @escaping ([String]?, Error?) -> Void) { + func requestHealthCheck(withContainer container: String, context: String, requiresEscrowCheck: Bool, reply: @escaping (Bool, Bool, Bool, Bool, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) - os_log("GetViews (%@) for %@", log: tplogDebug, type: .default, inViews, containerName.description) + os_log("Health Check! requiring escrow check? %d for %{public}@", log: tplogDebug, type: .default, requiresEscrowCheck, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.getViews(inViews: inViews) { outViews, error in - reply(outViews, CKXPCSuitableError(error)) + container.requestHealthCheck(requiresEscrowCheck: requiresEscrowCheck) { postRepair, postEscrow, postReset, leaveTrust, error in + reply(postRepair, postEscrow, postReset, leaveTrust, error?.sanitizeForClientXPC()) } } catch { - os_log("GetViews failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) - } - } - - func requestHealthCheck(withContainer container: String, context: String, requiresEscrowCheck: Bool, reply: @escaping (Bool, Bool, Bool, Error?) -> Void) { - do { - let containerName = ContainerName(container: container, context: context) - os_log("Health Check! requiring escrow check? %d for %@", log: tplogDebug, type: .default, requiresEscrowCheck, containerName.description) - let container = try self.containerMap.findOrCreate(name: containerName) - container.requestHealthCheck(requiresEscrowCheck: requiresEscrowCheck) { postRepair, postEscrow, postReset, error in - reply(postRepair, postEscrow, postReset, CKXPCSuitableError(error)) - } - } catch { - os_log("Health Check! failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(false, false, false, CKXPCSuitableError(error)) + os_log("Health Check! failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(false, false, false, false, error.sanitizeForClientXPC()) } } func getSupportAppInfo(withContainer container: String, context: String, reply: @escaping (Data?, Error?) -> Void) { - do { + do { let containerName = ContainerName(container: container, context: context) - os_log("getSupportInfo %d for %@", log: tplogDebug, type: .default, containerName.description) + os_log("getSupportAppInfo for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.getSupportAppInfo { info, error in - reply(info, CKXPCSuitableError(error)) + reply(info, error?.sanitizeForClientXPC()) } } catch { - os_log("getSupportInfo failed for (%@, %@): %@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + os_log("getSupportInfo failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(nil, error.sanitizeForClientXPC()) + } + } + func removeEscrowCache(withContainer container: String, context: String, reply: @escaping (Error?) -> Void) { + do { + let containerName = ContainerName(container: container, context: context) + os_log("removeEscrowCache for %{public}@", log: tplogDebug, type: .default, containerName.description) + let container = try self.containerMap.findOrCreate(name: containerName) + container.removeEscrowCache { error in + reply(error?.sanitizeForClientXPC()) + } + } catch { + os_log("removeEscrowCache failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) + } + } + func resetAccountCDPContents(withContainer container: String, context: String, reply: @escaping (Error?) -> Void) { + do { + let containerName = ContainerName(container: container, context: context) + os_log("resetAccountCDPContents for %{public}@", log: tplogDebug, type: .default, containerName.description) + let container = try self.containerMap.findOrCreate(name: containerName) + container.resetCDPAccountData{ error in + reply(error?.sanitizeForClientXPC()) + } + } catch { + os_log("resetAccountCDPContents failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } - } } diff --git a/keychain/TrustedPeersHelper/Container.swift b/keychain/TrustedPeersHelper/Container.swift index fffd68b1..db1f8c7b 100644 --- a/keychain/TrustedPeersHelper/Container.swift +++ b/keychain/TrustedPeersHelper/Container.swift @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2018 - 2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,6 +22,7 @@ */ import CloudKitCode +import CloudKitCodeProtobuf import CoreData import Foundation import os @@ -30,9 +31,14 @@ import SecurityFoundation let tplogDebug = OSLog(subsystem: "com.apple.security.trustedpeers", category: "debug") let tplogTrace = OSLog(subsystem: "com.apple.security.trustedpeers", category: "trace") - let egoIdentitiesAccessGroup = "com.apple.security.egoIdentities" +enum Viability { + case full + case partial + case none +} + extension ResetReason { static func from(cuttlefishResetReason: CuttlefishResetReason) -> ResetReason { switch cuttlefishResetReason { @@ -51,7 +57,7 @@ extension ResetReason { case .testGenerated: return ResetReason.testGenerated @unknown default: - fatalError() + fatalError("unknown reset reason: \(cuttlefishResetReason)") } } } @@ -99,6 +105,10 @@ public enum ContainerError: Error { case failedToStoreSecret(errorCode: Int) case unknownSecurityFoundationError case failedToSerializeData + case unknownInternalError + case unknownSyncUserControllableViewsValue(value: Int32) + case noPeersPreapprovedBySelf + case peerRegisteredButNotStored(String) } extension ContainerError: LocalizedError { @@ -188,12 +198,19 @@ extension ContainerError: LocalizedError { return "SecurityFoundation returned an unknown type" case .failedToSerializeData: return "Failed to encode protobuf data" + case .unknownInternalError: + return "Internal code failed, but didn't return error" + case .unknownSyncUserControllableViewsValue(value: let value): + return "Unknown syncUserControllableViews number: \(value)" + case .noPeersPreapprovedBySelf: + return "No peers preapproved by the local peer" + case .peerRegisteredButNotStored(let s): + return "Peer \(s) not found in database" } } } extension ContainerError: CustomNSError { - public static var errorDomain: String { return "com.apple.security.trustedpeers.container" } @@ -286,6 +303,14 @@ extension ContainerError: CustomNSError { return 43 case .failedToSerializeData: return 44 + case .unknownInternalError: + return 45 + case .unknownSyncUserControllableViewsValue: + return 46 + case .noPeersPreapprovedBySelf: + return 47 + case .peerRegisteredButNotStored: + return 48 } } @@ -321,7 +346,6 @@ internal func traceError(_ error: Error?) -> String { } func saveSecret(_ secret: Data, label: String) throws { - let query: [CFString: Any] = [ kSecClass: kSecClassInternetPassword, kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, @@ -427,14 +451,14 @@ func loadEgoKeyPair(identifier: String, resultHandler: @escaping (_SFECKeyPair?, func loadEgoKeys(peerID: String, resultHandler: @escaping (OctagonSelfPeerKeys?, Error?) -> Void) { loadEgoKeyPair(identifier: signingKeyIdentifier(peerID: peerID)) { signingKey, error in guard let signingKey = signingKey else { - os_log("Unable to load signing key: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + os_log("Unable to load signing key: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") resultHandler(nil, error) return } loadEgoKeyPair(identifier: encryptionKeyIdentifier(peerID: peerID)) { encryptionKey, error in guard let encryptionKey = encryptionKey else { - os_log("Unable to load encryption key: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + os_log("Unable to load encryption key: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") resultHandler(nil, error) return } @@ -540,11 +564,22 @@ func makeTLKShares(ckksTLKs: [CKKSKeychainBackedKey]?, asPeer: CKKSSelfPeer, toP throw error } } - }.compactMap { $0 } + } + .compactMap { $0 } } -func extract(tlkShares: [CKKSTLKShare], peer: CKKSSelfPeer) { - os_log("Attempting to recover %d TLK shares for peer %@", log: tplogDebug, type: .default, tlkShares.count, peer.peerID) +@discardableResult +func extract(tlkShares: [CKKSTLKShare], peer: OctagonSelfPeerKeys, model: TPModel) -> (Int64, Int64) { + os_log("Attempting to recover %d TLK shares for peer %{public}@", log: tplogDebug, type: .default, tlkShares.count, peer.peerID) + + return extract(tlkShares: tlkShares, peer: peer, sponsorPeerID: nil, model: model) +} + +@discardableResult +func extract(tlkShares: [CKKSTLKShare], peer: OctagonSelfPeerKeys, sponsorPeerID: String?, model: TPModel) -> (Int64, Int64) { + var tlksRecovered: Set = Set() + var sharesRecovered: Int64 = 0 + for share in tlkShares { guard share.receiverPeerID == peer.peerID else { os_log("Skipping %@ (wrong peerID)", log: tplogDebug, type: .default, share) @@ -552,18 +587,39 @@ func extract(tlkShares: [CKKSTLKShare], peer: CKKSSelfPeer) { } do { - // TODO: how should we handle peer sets here? + var trustedPeers: [AnyHashable] = [peer] + + if let egoPeer = model.peer(withID: sponsorPeerID ?? peer.peerID) { + egoPeer.trustedPeerIDs.forEach { trustedPeerID in + if let peer = model.peer(withID: trustedPeerID) { + let peerObj = CKKSActualPeer(peerID: trustedPeerID, + encryptionPublicKey: (peer.permanentInfo.encryptionPubKey as! _SFECPublicKey), + signing: (peer.permanentInfo.signingPubKey as! _SFECPublicKey), + viewList: []) + + trustedPeers.append(peerObj) + } else { + os_log("No peer for trusted ID %{public}@", log: tplogDebug, type: .default, trustedPeerID) + } + } + } else { + os_log("No ego peer in model; no trusted peers", log: tplogDebug, type: .default) + } + let key = try share.recoverTLK(peer, - trustedPeers: [peer as! AnyHashable], + trustedPeers: Set(trustedPeers), ckrecord: nil) try key.saveMaterialToKeychain() + tlksRecovered.insert(key.uuid) + sharesRecovered += 1 os_log("Recovered %@ (from %@)", log: tplogDebug, type: .default, key, share) } catch { - os_log("Failed to recover share %@: %@", log: tplogDebug, type: .default, share, error as CVarArg) + os_log("Failed to recover share %@: %{public}@", log: tplogDebug, type: .default, share, error as CVarArg) } } + return (Int64(tlksRecovered.count), sharesRecovered) } struct ContainerState { @@ -571,6 +627,7 @@ struct ContainerState { var peers: [String: TPPeer] = [:] var vouchers: [TPVoucher] = [] var bottles = Set() + var escrowRecords = Set() var recoverySigningKey: Data? var recoveryEncryptionKey: Data? } @@ -581,13 +638,13 @@ internal struct StableChanges { let osVersion: String? let policyVersion: UInt64? let policySecrets: [String: Data]? - let recoverySigningPubKey: Data? - var recoveryEncryptionPubKey: Data? + let setSyncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus? } // CoreData doesn't handle creating an identical model from an identical URL. Help it out. private var nsObjectModels: [URL: NSManagedObjectModel] = [:] private let nsObjectModelsQueue = DispatchQueue(label: "com.apple.security.TrustedPeersHelper.nsObjectModels") + func getOrMakeModel(url: URL) -> NSManagedObjectModel { return nsObjectModelsQueue.sync { if let model = nsObjectModels[url] { @@ -617,6 +674,17 @@ struct ContainerName: Hashable, CustomStringConvertible { } } +extension ContainerMO { + func egoStableInfo() -> TPPeerStableInfo? { + guard let egoStableData = self.egoPeerStableInfo, + let egoStableSig = self.egoPeerStableInfoSig else { + return nil + } + + return TPPeerStableInfo(data: egoStableData, sig: egoStableSig) + } +} + /// This maps to a Cuttlefish service backed by a CloudKit container, /// and a corresponding local Core Data persistent container. /// @@ -639,12 +707,19 @@ class Container: NSObject { // that queue. internal let moc: NSManagedObjectContext + // To facilitate CoreData tear down, we need to keep the PersistentContainer around. + internal let persistentContainer: NSPersistentContainer + // Rather than Container having its own dispatch queue, we use moc's queue // to synchronise access to our own state as well. So the following instance // variables must only be accessed within blocks executed by calling // moc.perform() or moc.performAndWait(). internal var containerMO: ContainerMO internal var model: TPModel + internal var escrowCacheTimeout: TimeInterval + + // Used in tests only. Set when an identity is prepared using a policy version override + internal var policyVersionOverride: TPPolicyVersion? /** Construct a Container. @@ -666,17 +741,17 @@ class Container: NSObject { // Set up Core Data stack let url = Bundle(for: type(of: self)).url(forResource: "TrustedPeersHelper", withExtension: "momd")! let mom = getOrMakeModel(url: url) - let persistentContainer = NSPersistentContainer(name: "TrustedPeersHelper", managedObjectModel: mom) - persistentContainer.persistentStoreDescriptions = [persistentStoreDescription] + self.persistentContainer = NSPersistentContainer(name: "TrustedPeersHelper", managedObjectModel: mom) + self.persistentContainer.persistentStoreDescriptions = [persistentStoreDescription] - persistentContainer.loadPersistentStores { _, error in + self.persistentContainer.loadPersistentStores { _, error in initError = error } if let initError = initError { throw initError } - let moc = persistentContainer.newBackgroundContext() + let moc = self.persistentContainer.newBackgroundContext() moc.mergePolicy = NSMergePolicy.mergeByPropertyStoreTrump moc.performAndWait { @@ -696,6 +771,9 @@ class Container: NSObject { Container.onqueueUpgradeMachineIDSetToModel(container: containerMO!, moc: moc) Container.onqueueUpgradeMachineIDSetToUseStatus(container: containerMO!, moc: moc) + //remove duplicate vouchers on all the peers + Container.onqueueRemoveDuplicateVouchersPerPeer(container: containerMO!, moc: moc) + model = Container.loadModel(from: containerMO!) Container.ensureEgoConsistency(from: containerMO!, model: model!) try moc.save() @@ -713,10 +791,23 @@ class Container: NSObject { self.containerMO = containerMO! self.cuttlefish = cuttlefish self.model = model! - + self.escrowCacheTimeout = 60.0 * 15.0 //15 minutes super.init() } + func deletePersistentStore() throws { + // Call this to entirely destroy the persistent store. + // This container should not be used after this event. + + try self.persistentContainer.persistentStoreDescriptions.forEach { storeDescription in + if let url = storeDescription.url { + try self.moc.persistentStoreCoordinator?.destroyPersistentStore(at: url, + ofType: storeDescription.type, + options: [:]) + } + } + } + // Must be on containerMO's moc queue to call this internal static func loadModel(from containerMO: ContainerMO) -> TPModel { // Populate model from persistent store @@ -736,26 +827,26 @@ class Container: NSObject { do { try model.update(stableInfo, forPeerWithID: permanentInfo.peerID) } catch { - os_log("loadModel unable to update stable info for peer(%@): %@", log: tplogDebug, type: .default, peer, error as CVarArg) + os_log("loadModel unable to update stable info for peer(%{public}@): %{public}@", log: tplogDebug, type: .default, peer, error as CVarArg) } } else { - os_log("loadModel: peer %@ has unparseable stable info", log: tplogDebug, type: .default, permanentInfo.peerID) + os_log("loadModel: peer %{public}@ has unparseable stable info", log: tplogDebug, type: .default, permanentInfo.peerID) } } else { - os_log("loadModel: peer %@ has no stable info", log: tplogDebug, type: .default, permanentInfo.peerID) + os_log("loadModel: peer %{public}@ has no stable info", log: tplogDebug, type: .default, permanentInfo.peerID) } if let data = peer.dynamicInfo, let sig = peer.dynamicInfoSig { if let dynamicInfo = TPPeerDynamicInfo(data: data as Data, sig: sig as Data) { do { try model.update(dynamicInfo, forPeerWithID: permanentInfo.peerID) } catch { - os_log("loadModel unable to update dynamic info for peer(%@): %@", log: tplogDebug, type: .default, peer, error as CVarArg) + os_log("loadModel unable to update dynamic info for peer(%{public}@): %{public}@", log: tplogDebug, type: .default, peer, error as CVarArg) } } else { - os_log("loadModel: peer %@ has unparseable dynamic info", log: tplogDebug, type: .default, permanentInfo.peerID) + os_log("loadModel: peer %{public}@ has unparseable dynamic info", log: tplogDebug, type: .default, permanentInfo.peerID) } } else { - os_log("loadModel: peer %@ has no dynamic info", log: tplogDebug, type: .default, permanentInfo.peerID) + os_log("loadModel: peer %{public}@ has no dynamic info", log: tplogDebug, type: .default, permanentInfo.peerID) } peer.vouchers?.forEach { let v = $0 as! VoucherMO @@ -767,6 +858,23 @@ class Container: NSObject { } } + os_log("loadModel: loaded %{public}d vouchers", log: tplogDebug, type: .default, model.allVouchers().count) + + // Note: the containerMO objects are misnamed; they are key data, and not SPKI. + if let recoveryKeySigningKeyData = containerMO.recoveryKeySigningSPKI, + let recoveryKeyEncyryptionKeyData = containerMO.recoveryKeyEncryptionSPKI { + model.setRecoveryKeys(TPRecoveryKeyPair(signingKeyData: recoveryKeySigningKeyData, encryptionKeyData: recoveryKeyEncyryptionKeyData)) + } else { + // If the ego peer has an RK set, tell the model to use that one + // This is a hack to work around TPH databases which don't have the RK set on the container due to previously running old software + if let egoStableInfo = containerMO.egoStableInfo(), + egoStableInfo.recoverySigningPublicKey.count > 0, + egoStableInfo.recoveryEncryptionPublicKey.count > 0 { + os_log("loadModel: recovery key not set in model, but is set on ego peer", log: tplogDebug, type: .default) + model.setRecoveryKeys(TPRecoveryKeyPair(signingKeyData: egoStableInfo.recoverySigningPublicKey, encryptionKeyData: egoStableInfo.recoveryEncryptionPublicKey)) + } + } + // Register persisted policies (cached from cuttlefish) let policies = containerMO.policies as? Set policies?.forEach { policyMO in @@ -787,10 +895,10 @@ class Container: NSObject { let allowedMachineIDs = Set(knownMachines.filter { $0.status == TPMachineIDStatus.allowed.rawValue }.compactMap { $0.machineID }) let disallowedMachineIDs = Set(knownMachines.filter { $0.status == TPMachineIDStatus.disallowed.rawValue }.compactMap { $0.machineID }) - os_log("loadModel: allowedMachineIDs: %@", log: tplogDebug, type: .default, allowedMachineIDs) - os_log("loadModel: disallowedMachineIDs: %@", log: tplogDebug, type: .default, disallowedMachineIDs) + os_log("loadModel: allowedMachineIDs: %{public}@", log: tplogDebug, type: .default, allowedMachineIDs) + os_log("loadModel: disallowedMachineIDs: %{public}@", log: tplogDebug, type: .default, disallowedMachineIDs) - if allowedMachineIDs.count == 0 { + if allowedMachineIDs.isEmpty { os_log("loadModel: no allowedMachineIDs?", log: tplogDebug, type: .default) } @@ -821,7 +929,6 @@ class Container: NSObject { containerMO.egoPeerStableInfo = modelStableInfo.data containerMO.egoPeerStableInfoSig = modelStableInfo.sig } - } static func dictionaryRepresentation(bottle: BottleMO) -> [String: Any] { @@ -855,8 +962,9 @@ class Container: NSObject { func onQueueDetermineLocalTrustStatus(reply: @escaping (TrustedPeersHelperEgoPeerStatus, Error?) -> Void) { let viablePeerCountsByModelID = self.model.viablePeerCountsByModelID() let peerCountsByMachineID = self.model.peerCountsByMachineID() - if let egoPeerID = self.containerMO.egoPeerID { + let egoPermanentInfo = self.model.peer(withID: egoPeerID)?.permanentInfo + var status = self.model.statusOfPeer(withID: egoPeerID) var isExcluded: Bool = (status == .excluded) @@ -866,7 +974,7 @@ class Container: NSObject { guard returnError == nil else { var isLocked = false if let error = (loadError as NSError?) { - os_log("trust status: Unable to load ego keys: %@", log: tplogDebug, type: .default, error as CVarArg) + os_log("trust status: Unable to load ego keys: %{public}@", log: tplogDebug, type: .default, error as CVarArg) if error.code == errSecItemNotFound && error.domain == NSOSStatusErrorDomain { os_log("trust status: Lost the ego key pair, returning 'excluded' in hopes of fixing up the identity", log: tplogDebug, type: .debug) isExcluded = true @@ -879,6 +987,7 @@ class Container: NSObject { } let egoStatus = TrustedPeersHelperEgoPeerStatus(egoPeerID: egoPeerID, + egoPeerMachineID: egoPermanentInfo?.machineID, status: status, viablePeerCountsByModelID: viablePeerCountsByModelID, peerCountsByMachineID: peerCountsByMachineID, @@ -892,6 +1001,7 @@ class Container: NSObject { guard egoPeerKeys != nil else { os_log("trust status: No error but Ego Peer Keys are nil", log: tplogDebug, type: .default) let egoStatus = TrustedPeersHelperEgoPeerStatus(egoPeerID: egoPeerID, + egoPeerMachineID: egoPermanentInfo?.machineID, status: .excluded, viablePeerCountsByModelID: viablePeerCountsByModelID, peerCountsByMachineID: peerCountsByMachineID, @@ -903,6 +1013,7 @@ class Container: NSObject { } let egoStatus = TrustedPeersHelperEgoPeerStatus(egoPeerID: egoPeerID, + egoPeerMachineID: egoPermanentInfo?.machineID, status: status, viablePeerCountsByModelID: viablePeerCountsByModelID, peerCountsByMachineID: peerCountsByMachineID, @@ -911,12 +1022,12 @@ class Container: NSObject { reply(egoStatus, nil) return } - } else { // With no ego peer ID, either return 'excluded' if there are extant peers, or 'unknown' to signal no peers at all if self.model.allPeerIDs().isEmpty { os_log("No existing peers in account", log: tplogDebug, type: .debug) let egoStatus = TrustedPeersHelperEgoPeerStatus(egoPeerID: nil, + egoPeerMachineID: nil, status: .unknown, viablePeerCountsByModelID: viablePeerCountsByModelID, peerCountsByMachineID: peerCountsByMachineID, @@ -927,6 +1038,7 @@ class Container: NSObject { } else { os_log("Existing peers in account, but we don't have a peer ID. We are excluded.", log: tplogDebug, type: .debug) let egoStatus = TrustedPeersHelperEgoPeerStatus(egoPeerID: nil, + egoPeerMachineID: nil, status: .excluded, viablePeerCountsByModelID: viablePeerCountsByModelID, peerCountsByMachineID: peerCountsByMachineID, @@ -943,7 +1055,7 @@ class Container: NSObject { let reply: (TrustedPeersHelperEgoPeerStatus, Error?) -> Void = { // Suppress logging of successful replies here; it's not that useful let logType: OSLogType = $1 == nil ? .debug : .info - os_log("trustStatus complete: %@ %@", + os_log("trustStatus complete: %{public}@ %{public}@", log: tplogTrace, type: logType, TPPeerStatusToString($0.egoStatus), traceError($1)) self.semaphore.signal() @@ -952,13 +1064,14 @@ class Container: NSObject { self.moc.performAndWait { // Knowledge of your peer status only exists if you know about other peers. If you haven't fetched, fetch. if self.containerMO.changeToken == nil { - self.fetchAndPersistChanges { fetchError in + self.onqueueFetchAndPersistChanges { fetchError in guard fetchError == nil else { if let error = fetchError { - os_log("Unable to fetch changes, trust status is unknown: %@", log: tplogDebug, type: .default, error as CVarArg) + os_log("Unable to fetch changes, trust status is unknown: %{public}@", log: tplogDebug, type: .default, error as CVarArg) } let egoStatus = TrustedPeersHelperEgoPeerStatus(egoPeerID: nil, + egoPeerMachineID: nil, status: .unknown, viablePeerCountsByModelID: [:], peerCountsByMachineID: [:], @@ -980,16 +1093,15 @@ class Container: NSObject { func fetchTrustState(reply: @escaping (TrustedPeersHelperPeerState?, [TrustedPeersHelperPeer]?, Error?) -> Void) { let reply: (TrustedPeersHelperPeerState?, [TrustedPeersHelperPeer]?, Error?) -> Void = { - os_log("fetch trust state complete: %@ %@", + os_log("fetch trust state complete: %{public}@ %{public}@", log: tplogTrace, type: .info, String(reflecting: $0), traceError($2)) reply($0, $1, $2) } self.moc.performAndWait { if let egoPeerID = self.containerMO.egoPeerID, - let egoPermData = self.containerMO.egoPeerPermanentInfo, - let egoPermSig = self.containerMO.egoPeerPermanentInfoSig { - + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig { let keyFactory = TPECPublicKeyFactory() guard let permanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { os_log("fetchTrustState failed to create TPPeerPermanentInfo", log: tplogDebug, type: .error) @@ -998,7 +1110,7 @@ class Container: NSObject { } let isPreapproved = self.model.hasPotentiallyTrustedPeerPreapprovingKey(permanentInfo.signingPubKey.spki()) - os_log("fetchTrustState: ego peer is %@", log: tplogDebug, type: .default, isPreapproved ? "preapproved" : "not yet preapproved") + os_log("fetchTrustState: ego peer is %{public}@", log: tplogDebug, type: .default, isPreapproved ? "preapproved" : "not yet preapproved") let egoStableInfo = self.model.getStableInfoForPeer(withID: egoPeerID) @@ -1015,22 +1127,36 @@ class Container: NSObject { egoPeer.trustedPeerIDs.forEach { trustedPeerID in if let peer = self.model.peer(withID: trustedPeerID) { let peerViews = try? self.model.getViewsForPeer(peer.permanentInfo, - stableInfo: peer.stableInfo, - inViews: Set()) + stableInfo: peer.stableInfo) tphPeers.append(TrustedPeersHelperPeer(peerID: trustedPeerID, signingSPKI: peer.permanentInfo.signingPubKey.spki(), encryptionSPKI: peer.permanentInfo.encryptionPubKey.spki(), viewList: peerViews ?? Set())) } else { - os_log("No peer for trusted ID %@", log: tplogDebug, type: .default, trustedPeerID) + os_log("No peer for trusted ID %{public}@", log: tplogDebug, type: .default, trustedPeerID) + } + } + + if let stableInfo = egoPeer.stableInfo, stableInfo.recoveryEncryptionPublicKey.count > 0, stableInfo.recoverySigningPublicKey.count > 0 { + let recoveryKeyPair = TPRecoveryKeyPair(stableInfo: stableInfo) + + do { + // The RK should have all views. So, claim that it should have all views that this peer has. + let rkViews = try self.model.getViewsForPeer(egoPeer.permanentInfo, + stableInfo: egoPeer.stableInfo) + + tphPeers.append(try RecoveryKey.asPeer(recoveryKeys: recoveryKeyPair, + viewList: rkViews)) + } catch { + os_log("Unable to add RK as a trusted peer: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") } } } else { os_log("No ego peer in model; no trusted peers", log: tplogDebug, type: .default) } - os_log("Returning trust state: %@ %@", log: tplogDebug, type: .default, egoPeerStatus, tphPeers) + os_log("Returning trust state: %{public}@ %@", log: tplogDebug, type: .default, egoPeerStatus, tphPeers) reply(egoPeerStatus, tphPeers, nil) } else { // With no ego peer ID, there are no trusted peers @@ -1042,11 +1168,11 @@ class Container: NSObject { func dump(reply: @escaping ([AnyHashable: Any]?, Error?) -> Void) { let reply: ([AnyHashable: Any]?, Error?) -> Void = { - os_log("dump complete: %@", + os_log("dump complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) reply($0, $1) - } - self.moc.performAndWait { + } + self.moc.performAndWait { var d: [AnyHashable: Any] = [:] if let egoPeerID = self.containerMO.egoPeerID { @@ -1076,17 +1202,18 @@ class Container: NSObject { d["machineIDsDisallowed"] = midList.machineIDs(in: .disallowed).sorted() d["modelRecoverySigningPublicKey"] = self.model.recoverySigningPublicKey() d["modelRecoveryEncryptionPublicKey"] = self.model.recoveryEncryptionPublicKey() + d["registeredPolicyVersions"] = self.model.allRegisteredPolicyVersions().sorted().map { policyVersion in "\(policyVersion.versionNumber), \(policyVersion.policyHash)" } reply(d, nil) } } func dumpEgoPeer(reply: @escaping (String?, TPPeerPermanentInfo?, TPPeerStableInfo?, TPPeerDynamicInfo?, Error?) -> Void) { - let reply: (String?, TPPeerPermanentInfo?, TPPeerStableInfo?, TPPeerDynamicInfo?, Error?) -> Void = { - os_log("dumpEgoPeer complete: %@", log: tplogTrace, type: .info, traceError($4)) - reply($0, $1, $2, $3, $4) - } - self.moc.performAndWait { + let reply: (String?, TPPeerPermanentInfo?, TPPeerStableInfo?, TPPeerDynamicInfo?, Error?) -> Void = { + os_log("dumpEgoPeer complete: %{public}@", log: tplogTrace, type: .info, traceError($4)) + reply($0, $1, $2, $3, $4) + } + self.moc.performAndWait { guard let egoPeerID = self.containerMO.egoPeerID else { reply(nil, nil, nil, nil, ContainerError.noPreparedIdentity) return @@ -1104,15 +1231,14 @@ class Container: NSObject { func validatePeers(request: ValidatePeersRequest, reply: @escaping ([AnyHashable: Any]?, Error?) -> Void) { self.semaphore.wait() let reply: ([AnyHashable: Any]?, Error?) -> Void = { - os_log("validatePeers complete %@", log: tplogTrace, type: .info, traceError($1)) + os_log("validatePeers complete %{public}@", log: tplogTrace, type: .info, traceError($1)) self.semaphore.signal() reply($0, $1) } self.cuttlefish.validatePeers(request) { response, error in - os_log("ValidatePeers(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { - os_log("validatePeers failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + os_log("validatePeers failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, error ?? ContainerError.cloudkitResponseMissing) return } @@ -1125,49 +1251,10 @@ class Container: NSObject { } } - func getViews(inViews: [String], reply: @escaping ([String]?, Error?) -> Void) { - let reply: ([String]?, Error?) -> Void = { - os_log("getViews complete %@", log: tplogTrace, type: .info, traceError($1)) - reply($0, $1) - } - self.moc.performAndWait { - guard let egoPeerID = self.containerMO.egoPeerID, - let egoPermData = self.containerMO.egoPeerPermanentInfo, - let egoPermSig = self.containerMO.egoPeerPermanentInfoSig, - let egoStableData = self.containerMO.egoPeerStableInfo, - let egoStableSig = self.containerMO.egoPeerStableInfoSig - else { - os_log("getViews failed to find ego peer information", log: tplogDebug, type: .error) - reply(nil, ContainerError.noPreparedIdentity) - return - } - guard let stableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { - os_log("getViews failed to create TPPeerStableInfo", log: tplogDebug, type: .error) - reply(nil, ContainerError.invalidStableInfoOrSig) - return - } - - let keyFactory = TPECPublicKeyFactory() - guard let permanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - os_log("getViews failed to create TPPeerPermanentInfo", log: tplogDebug, type: .error) - reply(nil, ContainerError.invalidPermanentInfoOrSig) - return - } - - do { - let views = try self.model.getViewsForPeer(permanentInfo, stableInfo: stableInfo, inViews: Set(inViews)) - reply(Array(views), nil) - } catch { - reply(nil, error) - return - } - } - } - func reset(resetReason: CuttlefishResetReason, reply: @escaping (Error?) -> Void) { self.semaphore.wait() let reply: (Error?) -> Void = { - os_log("reset complete %@", log: tplogTrace, type: .info, traceError($0)) + os_log("reset complete %{public}@", log: tplogTrace, type: .info, traceError($0)) self.semaphore.signal() reply($0) } @@ -1178,9 +1265,8 @@ class Container: NSObject { $0.resetReason = resetReason } self.cuttlefish.reset(request) { response, error in - os_log("Reset(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { - os_log("reset failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + os_log("reset failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(error ?? ContainerError.cloudkitResponseMissing) return } @@ -1196,7 +1282,7 @@ class Container: NSObject { os_log("reset succeded", log: tplogDebug, type: .default) reply(nil) } catch { - os_log("reset persist failed: %@", log: tplogDebug, type: .default, (error as CVarArg)) + os_log("reset persist failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg)) reply(error) } } @@ -1207,7 +1293,7 @@ class Container: NSObject { func localReset(reply: @escaping (Error?) -> Void) { self.semaphore.wait() let reply: (Error?) -> Void = { - os_log("localReset complete %@", log: tplogTrace, type: .info, traceError($0)) + os_log("localReset complete %{public}@", log: tplogTrace, type: .info, traceError($0)) self.semaphore.signal() reply($0) } @@ -1240,26 +1326,27 @@ class Container: NSObject { } } - // policyVersion should only be non-nil for testing, to override prevailingPolicyVersion + // policyVersion should only be non-nil for testing, to override prevailingPolicyVersion.versionNumber func prepare(epoch: UInt64, machineID: String, bottleSalt: String, bottleID: String, modelID: String, deviceName: String?, - serialNumber: String, + serialNumber: String?, osVersion: String, - policyVersion: UInt64?, + policyVersion: TPPolicyVersion?, policySecrets: [String: Data]?, + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus, signingPrivateKeyPersistentRef: Data?, encryptionPrivateKeyPersistentRef: Data?, - reply: @escaping (String?, Data?, Data?, Data?, Data?, Error?) -> Void) { + reply: @escaping (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (String?, Data?, Data?, Data?, Data?, Error?) -> Void = { - os_log("prepare complete peerID: %@ %@", - log: tplogTrace, type: .info, ($0 ?? "NULL") as CVarArg, traceError($5)) + let reply: (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) -> Void = { + os_log("prepare complete peerID: %{public}@ %{public}@", + log: tplogTrace, type: .info, ($0 ?? "NULL") as CVarArg, traceError($6)) self.semaphore.signal() - reply($0, $1, $2, $3, $4, $5) + reply($0, $1, $2, $3, $4, $5, $6) } // Create a new peer identity with random keys, and store the keys in keychain @@ -1270,15 +1357,15 @@ class Container: NSObject { signingKeyPair = try self.loadOrCreateKeyPair(privateKeyPersistentRef: signingPrivateKeyPersistentRef) encryptionKeyPair = try self.loadOrCreateKeyPair(privateKeyPersistentRef: encryptionPrivateKeyPersistentRef) + // Octagon: use epoch transmitted across pairing channel permanentInfo = try TPPeerPermanentInfo(machineID: machineID, modelID: modelID, epoch: 1, signing: signingKeyPair, encryptionKeyPair: encryptionKeyPair, peerIDHashAlgo: TPHashAlgo.SHA256) - } catch { - reply(nil, nil, nil, nil, nil, error) + reply(nil, nil, nil, nil, nil, nil, error) return } @@ -1294,63 +1381,81 @@ class Container: NSObject { _ = try saveSecret(bottle.secret, label: peerID) } catch { - os_log("bottle creation failed: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, nil, nil, nil, error) + os_log("bottle creation failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, nil, nil, nil, nil, error) return } saveEgoKeyPair(signingKeyPair, identifier: signingKeyIdentifier(peerID: peerID)) { success, error in guard success else { - os_log("Unable to save signing key: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity) + os_log("Unable to save signing key: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + reply(nil, nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity) return } saveEgoKeyPair(encryptionKeyPair, identifier: encryptionKeyIdentifier(peerID: peerID)) { success, error in guard success else { - os_log("Unable to save encryption key: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity) + os_log("Unable to save encryption key: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + reply(nil, nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity) return } - // Save the prepared identity as containerMO.egoPeer* and its bottle - self.moc.performAndWait { - do { - let policyVersion = policyVersion ?? prevailingPolicyVersion - let policyDoc = try self.getPolicyDoc(policyVersion) + let actualPolicyVersion = policyVersion ?? prevailingPolicyVersion + self.fetchPolicyDocumentWithSemaphore(version: actualPolicyVersion) { policyDoc, policyFetchError in + guard let policyDoc = policyDoc, policyFetchError == nil else { + os_log("Unable to fetch policy: %{public}@", log: tplogDebug, type: .default, (policyFetchError as CVarArg?) ?? "error missing") + reply(nil, nil, nil, nil, nil, nil, error ?? ContainerError.unknownInternalError) + return + } - let stableInfo = TPPeerStableInfo(clock: 1, - policyVersion: policyDoc.policyVersion, - policyHash: policyDoc.policyHash, - policySecrets: policySecrets, - deviceName: deviceName, - serialNumber: serialNumber, - osVersion: osVersion, - signing: signingKeyPair, - recoverySigningPubKey: nil, - recoveryEncryptionPubKey: nil, - error: nil) + if policyVersion != nil { + self.policyVersionOverride = policyDoc.version + } - self.containerMO.egoPeerID = permanentInfo.peerID - self.containerMO.egoPeerPermanentInfo = permanentInfo.data - self.containerMO.egoPeerPermanentInfoSig = permanentInfo.sig - self.containerMO.egoPeerStableInfo = stableInfo.data - self.containerMO.egoPeerStableInfoSig = stableInfo.sig + // Save the prepared identity as containerMO.egoPeer* and its bottle + self.moc.performAndWait { + do { + // Note: the client chooses for syncUserControllableViews here. + // if they pass in UNKNOWN, we'll fix it later at join time, following the peers we trust. + let syncUserViews = syncUserControllableViews.sanitizeForPlatform(permanentInfo: permanentInfo) - let bottleMO = BottleMO(context: self.moc) - bottleMO.peerID = bottle.peerID - bottleMO.bottleID = bottle.bottleID - bottleMO.escrowedSigningSPKI = bottle.escrowSigningSPKI - bottleMO.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey - bottleMO.signatureUsingPeerKey = bottle.signatureUsingPeerKey - bottleMO.contents = bottle.contents + let useFrozenPolicyVersion = policyDoc.version.versionNumber >= frozenPolicyVersion.versionNumber - self.containerMO.addToBottles(bottleMO) + let stableInfo = try TPPeerStableInfo(clock: 1, + frozenPolicyVersion: useFrozenPolicyVersion ? frozenPolicyVersion : policyDoc.version, + flexiblePolicyVersion: useFrozenPolicyVersion ? policyDoc.version : nil, + policySecrets: policySecrets, + syncUserControllableViews: syncUserViews, + deviceName: deviceName, + serialNumber: serialNumber, + osVersion: osVersion, + signing: signingKeyPair, + recoverySigningPubKey: nil, + recoveryEncryptionPubKey: nil) + self.containerMO.egoPeerID = permanentInfo.peerID + self.containerMO.egoPeerPermanentInfo = permanentInfo.data + self.containerMO.egoPeerPermanentInfoSig = permanentInfo.sig + self.containerMO.egoPeerStableInfo = stableInfo.data + self.containerMO.egoPeerStableInfoSig = stableInfo.sig - try self.moc.save() + let bottleMO = BottleMO(context: self.moc) + bottleMO.peerID = bottle.peerID + bottleMO.bottleID = bottle.bottleID + bottleMO.escrowedSigningSPKI = bottle.escrowSigningSPKI + bottleMO.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey + bottleMO.signatureUsingPeerKey = bottle.signatureUsingPeerKey + bottleMO.contents = bottle.contents - reply(permanentInfo.peerID, permanentInfo.data, permanentInfo.sig, stableInfo.data, stableInfo.sig, nil) - } catch { - reply(nil, nil, nil, nil, nil, error) + self.containerMO.addToBottles(bottleMO) + + let syncingPolicy = try self.syncingPolicyFor(modelID: permanentInfo.modelID, stableInfo: stableInfo) + + try self.moc.save() + + reply(permanentInfo.peerID, permanentInfo.data, permanentInfo.sig, stableInfo.data, stableInfo.sig, syncingPolicy, nil) + } catch { + os_log("Unable to save identity: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, nil, nil, nil, nil, error) + } } } } @@ -1358,7 +1463,7 @@ class Container: NSObject { } func getEgoEpoch(reply: @escaping (UInt64, Error?) -> Void) { let reply: (UInt64, Error?) -> Void = { - os_log("getEgoEpoch complete: %d %@", log: tplogTrace, type: .info, $0, traceError($1)) + os_log("getEgoEpoch complete: %d %{public}@", log: tplogTrace, type: .info, $0, traceError($1)) reply($0, $1) } @@ -1378,20 +1483,21 @@ class Container: NSObject { func establish(ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord], Error?) -> Void) { + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (String?, [CKRecord], Error?) -> Void = { - os_log("establish complete peer: %@ %@", - log: tplogTrace, type: .default, ($0 ?? "NULL") as CVarArg, traceError($2)) + let reply: (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void = { + os_log("establish complete peer: %{public}@ %{public}@", + log: tplogTrace, type: .default, ($0 ?? "NULL") as CVarArg, traceError($3)) self.semaphore.signal() - reply($0, $1, $2) + reply($0, $1, $2, $3) } self.moc.performAndWait { self.onqueueEstablish(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys, - reply: reply) + preapprovedKeys: preapprovedKeys) { peerID, ckrecords, syncingPolicy, error in + reply(peerID, ckrecords, syncingPolicy, error) + } } } @@ -1402,10 +1508,76 @@ class Container: NSObject { ttr.trigger() } + func fetchAfterEstablish(ckksKeys: [CKKSKeychainBackedKeySet], + tlkShares: [CKKSTLKShare], + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { + self.moc.performAndWait { + do { + try self.deleteLocalCloudKitData() + } catch { + os_log("fetchAfterEstablish failed to reset local data: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, [], nil, error) + return + } + self.onqueueFetchAndPersistChanges { error in + guard error == nil else { + os_log("fetchAfterEstablish failed to fetch changes: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + reply(nil, [], nil, error) + return + } + + self.moc.performAndWait { + guard let egoPeerID = self.containerMO.egoPeerID, + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig, + let egoStableData = self.containerMO.egoPeerStableInfo, + let egoStableSig = self.containerMO.egoPeerStableInfoSig + else { + os_log("fetchAfterEstablish: failed to fetch egoPeerID", log: tplogDebug, type: .default) + reply(nil, [], nil, ContainerError.noPreparedIdentity) + return + } + guard self.model.hasPeer(withID: egoPeerID) else { + os_log("fetchAfterEstablish: did not find peer %{public}@ in model", log: tplogDebug, type: .default, egoPeerID) + reply(nil, [], nil, ContainerError.invalidPeerID) + return + } + let keyFactory = TPECPublicKeyFactory() + guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { + reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig) + return + } + guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { + os_log("cannot create TPPeerStableInfo", log: tplogDebug, type: .default) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) + return + } + self.onqueueUpdateTLKs(ckksKeys: ckksKeys, tlkShares: tlkShares) { ckrecords, error in + guard error == nil else { + os_log("fetchAfterEstablish failed to update TLKs: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + reply(nil, [], nil, error) + return + } + + do { + let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID, + stableInfo: selfStableInfo) + os_log("fetchAfterEstablish succeeded", log: tplogDebug, type: .default) + reply(egoPeerID, ckrecords ?? [], syncingPolicy, nil) + } catch { + os_log("fetchAfterEstablish failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg)) + reply(nil, [], nil, error) + } + } + } + } + } + } + func onqueueEstablish(ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord], Error?) -> Void) { + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { // Fetch ego peer identity from local storage. guard let egoPeerID = self.containerMO.egoPeerID, let egoPermData = self.containerMO.egoPeerPermanentInfo, @@ -1413,31 +1585,31 @@ class Container: NSObject { let egoStableData = self.containerMO.egoPeerStableInfo, let egoStableSig = self.containerMO.egoPeerStableInfoSig else { - reply(nil, [], ContainerError.noPreparedIdentity) + reply(nil, [], nil, ContainerError.noPreparedIdentity) return } let keyFactory = TPECPublicKeyFactory() guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - reply(nil, [], ContainerError.invalidPermanentInfoOrSig) + reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig) return } guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { os_log("cannot create TPPeerStableInfo", log: tplogDebug, type: .default) - reply(nil, [], ContainerError.invalidStableInfoOrSig) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) return } guard self.onqueueMachineIDAllowedByIDMS(machineID: selfPermanentInfo.machineID) else { - os_log("establish: self machineID %@ not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID) + os_log("establish: self machineID %{public}@ not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID) self.onqueueTTRUntrusted() - reply(nil, [], ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) + reply(nil, [], nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) return } loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in - guard let egoPeerKeys = egoPeerKeys else { - os_log("Don't have my own peer keys; can't establish: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, [], error) + guard let egoPeerKeys = egoPeerKeys else { + os_log("Don't have my own peer keys; can't establish: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + reply(nil, [], nil, error) return } self.moc.performAndWait { @@ -1449,58 +1621,57 @@ class Container: NSObject { allTLKShares = octagonShares + sosShares } catch { - os_log("Unable to make TLKShares for self: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], error) + os_log("Unable to make TLKShares for self: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, [], nil, error) return } - let dynamicInfo: TPPeerDynamicInfo + let peer: Peer + let newDynamicInfo: TPPeerDynamicInfo do { - dynamicInfo = try self.model.dynamicInfo(forJoiningPeerID: egoPeerID, - peerPermanentInfo: selfPermanentInfo, - peerStableInfo: selfStableInfo, - sponsorID: nil, - preapprovedKeys: preapprovedKeys, - signing: egoPeerKeys.signingKey, - currentMachineIDs: self.onqueueCurrentMIDList()) + (peer, newDynamicInfo) = try self.onqueuePreparePeerForJoining(egoPeerID: egoPeerID, + peerPermanentInfo: selfPermanentInfo, + stableInfo: selfStableInfo, + sponsorID: nil, + preapprovedKeys: preapprovedKeys, + vouchers: [], + egoPeerKeys: egoPeerKeys) - os_log("dynamic info: %@", log: tplogDebug, type: .default, dynamicInfo) + os_log("dynamic info: %{public}@", log: tplogDebug, type: .default, newDynamicInfo) } catch { - reply(nil, [], error) + os_log("Unable to create peer for joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, [], nil, error) return } - let peer = Peer.with { - $0.peerID = egoPeerID - $0.permanentInfoAndSig.peerPermanentInfo = egoPermData - $0.permanentInfoAndSig.sig = egoPermSig - $0.stableInfoAndSig.peerStableInfo = egoStableData - $0.stableInfoAndSig.sig = egoStableSig - $0.dynamicInfoAndSig = SignedPeerDynamicInfo(dynamicInfo) + guard let newPeerStableInfo = peer.stableInfoAndSig.toStableInfo() else { + os_log("Unable to create new peer stable info for joining", log: tplogDebug, type: .default) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) + return } let bottle: Bottle do { bottle = try self.assembleBottle(egoPeerID: egoPeerID) } catch { - reply(nil, [], error) + reply(nil, [], nil, error) return } - os_log("Beginning establish for peer %@", log: tplogDebug, type: .default, egoPeerID) - os_log("Establish permanentInfo: %@", log: tplogDebug, type: .debug, egoPermData.base64EncodedString()) - os_log("Establish permanentInfoSig: %@", log: tplogDebug, type: .debug, egoPermSig.base64EncodedString()) - os_log("Establish stableInfo: %@", log: tplogDebug, type: .debug, egoStableData.base64EncodedString()) - os_log("Establish stableInfoSig: %@", log: tplogDebug, type: .debug, egoStableSig.base64EncodedString()) - os_log("Establish dynamicInfo: %@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.peerDynamicInfo.base64EncodedString()) - os_log("Establish dynamicInfoSig: %@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.sig.base64EncodedString()) + os_log("Beginning establish for peer %{public}@", log: tplogDebug, type: .default, egoPeerID) + os_log("Establish permanentInfo: %{public}@", log: tplogDebug, type: .debug, egoPermData.base64EncodedString()) + os_log("Establish permanentInfoSig: %{public}@", log: tplogDebug, type: .debug, egoPermSig.base64EncodedString()) + os_log("Establish stableInfo: %{public}@", log: tplogDebug, type: .debug, egoStableData.base64EncodedString()) + os_log("Establish stableInfoSig: %{public}@", log: tplogDebug, type: .debug, egoStableSig.base64EncodedString()) + os_log("Establish dynamicInfo: %{public}@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.peerDynamicInfo.base64EncodedString()) + os_log("Establish dynamicInfoSig: %{public}@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.sig.base64EncodedString()) os_log("Establish introducing %d key sets, %d tlk shares", log: tplogDebug, type: .default, viewKeys.count, allTLKShares.count) do { - os_log("Establish bottle: %@", log: tplogDebug, type: .debug, try bottle.serializedData().base64EncodedString()) - os_log("Establish peer: %@", log: tplogDebug, type: .debug, try peer.serializedData().base64EncodedString()) + os_log("Establish bottle: %{public}@", log: tplogDebug, type: .debug, try bottle.serializedData().base64EncodedString()) + os_log("Establish peer: %{public}@", log: tplogDebug, type: .debug, try peer.serializedData().base64EncodedString()) } catch { - os_log("Establish unable to encode bottle/peer: %@", log: tplogDebug, type: .debug, error as CVarArg) + os_log("Establish unable to encode bottle/peer: %{public}@", log: tplogDebug, type: .debug, error as CVarArg) } let request = EstablishRequest.with { @@ -1510,16 +1681,22 @@ class Container: NSObject { $0.tlkShares = allTLKShares } self.cuttlefish.establish(request) { response, error in - os_log("Establish(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") - os_log("Establish: viewKeys: %@", String(describing: viewKeys)) + os_log("Establish: viewKeys: %{public}@", String(describing: viewKeys)) guard let response = response, error == nil else { - os_log("establish failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, [], error ?? ContainerError.cloudkitResponseMissing) - return + switch error { + case CuttlefishErrorMatcher(code: CuttlefishErrorCode.establishFailed): + os_log("establish returned failed, trying fetch", log: tplogDebug, type: .default) + self.fetchAfterEstablish(ckksKeys: ckksKeys, tlkShares: tlkShares, reply: reply) + return + default: + os_log("establish failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, [], nil, error ?? ContainerError.cloudkitResponseMissing) + return + } } do { - os_log("Establish returned changes: %@", log: tplogDebug, type: .default, try response.changes.jsonString()) + os_log("Establish returned changes: %{public}@", log: tplogDebug, type: .default, try response.changes.jsonString()) } catch { os_log("Establish returned changes, but they can't be serialized", log: tplogDebug, type: .default) } @@ -1527,6 +1704,9 @@ class Container: NSObject { let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } do { + let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID, + stableInfo: newPeerStableInfo) + try self.persist(changes: response.changes) guard response.changes.more == false else { @@ -1535,34 +1715,34 @@ class Container: NSObject { self.fetchAndPersistChanges { fetchError in guard fetchError == nil else { // This is an odd error condition: we might be able to fetch again and be in a good state... - os_log("fetch-after-establish failed: %@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "no error") - reply(nil, keyHierarchyRecords, fetchError) + os_log("fetch-after-establish failed: %{public}@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "no error") + reply(nil, keyHierarchyRecords, nil, fetchError) return } os_log("fetch-after-establish succeeded", log: tplogDebug, type: .default) - reply(egoPeerID, keyHierarchyRecords, nil) + reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil) } return } os_log("establish succeeded", log: tplogDebug, type: .default) - reply(egoPeerID, keyHierarchyRecords, nil) + reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil) } catch { - os_log("establish handling failed: %@", log: tplogDebug, type: .default, (error as CVarArg)) - reply(nil, keyHierarchyRecords, error) + os_log("establish handling failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg)) + reply(nil, keyHierarchyRecords, nil, error) } } } } } - func setRecoveryKey(recoveryKey: String, salt: String, ckksKeys: [CKKSKeychainBackedKeySet], reply: @escaping (Error?) -> Void) { + func setRecoveryKey(recoveryKey: String, salt: String, ckksKeys: [CKKSKeychainBackedKeySet], reply: @escaping ([CKRecord]?, Error?) -> Void) { self.semaphore.wait() - let reply: (Error?) -> Void = { - os_log("setRecoveryKey complete: %@", log: tplogTrace, type: .info, traceError($0)) + let reply: ([CKRecord]?, Error?) -> Void = { + os_log("setRecoveryKey complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) self.semaphore.signal() - reply($0) + reply($0, $1) } os_log("beginning a setRecoveryKey", log: tplogDebug, type: .default) @@ -1570,7 +1750,7 @@ class Container: NSObject { self.moc.performAndWait { guard let egoPeerID = self.containerMO.egoPeerID else { os_log("no prepared identity, cannot set recovery key", log: tplogDebug, type: .default) - reply(ContainerError.noPreparedIdentity) + reply(nil, ContainerError.noPreparedIdentity) return } @@ -1578,53 +1758,53 @@ class Container: NSObject { do { recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) } catch { - os_log("failed to create recovery keys: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(ContainerError.failedToCreateRecoveryKey) + os_log("failed to create recovery keys: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, ContainerError.failedToCreateRecoveryKey) return } let signingPublicKey: Data = recoveryKeys.peerKeys.signingVerificationKey.keyData let encryptionPublicKey: Data = recoveryKeys.peerKeys.encryptionVerificationKey.keyData - os_log("setRecoveryKey signingPubKey: %@", log: tplogDebug, type: .debug, signingPublicKey.base64EncodedString()) - os_log("setRecoveryKey encryptionPubKey: %@", log: tplogDebug, type: .debug, encryptionPublicKey.base64EncodedString()) + os_log("setRecoveryKey signingPubKey: %@", log: tplogDebug, type: .default, signingPublicKey.base64EncodedString()) + os_log("setRecoveryKey encryptionPubKey: %@", log: tplogDebug, type: .default, encryptionPublicKey.base64EncodedString()) guard let stableInfoData = self.containerMO.egoPeerStableInfo else { os_log("stableInfo does not exist", log: tplogDebug, type: .default) - reply(ContainerError.nonMember) + reply(nil, ContainerError.nonMember) return } guard let stableInfoSig = self.containerMO.egoPeerStableInfoSig else { os_log("stableInfoSig does not exist", log: tplogDebug, type: .default) - reply(ContainerError.nonMember) + reply(nil, ContainerError.nonMember) return } guard let permInfoData = self.containerMO.egoPeerPermanentInfo else { os_log("permanentInfo does not exist", log: tplogDebug, type: .default) - reply(ContainerError.nonMember) + reply(nil, ContainerError.nonMember) return } guard let permInfoSig = self.containerMO.egoPeerPermanentInfoSig else { os_log("permInfoSig does not exist", log: tplogDebug, type: .default) - reply(ContainerError.nonMember) + reply(nil, ContainerError.nonMember) return } guard let stableInfo = TPPeerStableInfo(data: stableInfoData, sig: stableInfoSig) else { os_log("cannot create TPPeerStableInfo", log: tplogDebug, type: .default) - reply(ContainerError.invalidStableInfoOrSig) + reply(nil, ContainerError.invalidStableInfoOrSig) return } let keyFactory = TPECPublicKeyFactory() guard let permanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: permInfoData, sig: permInfoSig, keyFactory: keyFactory) else { os_log("cannot create TPPeerPermanentInfo", log: tplogDebug, type: .default) - reply(ContainerError.invalidStableInfoOrSig) + reply(nil, ContainerError.invalidStableInfoOrSig) return } loadEgoKeyPair(identifier: signingKeyIdentifier(peerID: egoPeerID)) { signingKeyPair, error in guard let signingKeyPair = signingKeyPair else { - os_log("handle: no signing key pair: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(error) + os_log("handle: no signing key pair: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, error) return } self.moc.performAndWait { @@ -1634,20 +1814,20 @@ class Container: NSObject { toPeer: recoveryKeys.peerKeys, epoch: Int(permanentInfo.epoch)) - let policyVersion = stableInfo.policyVersion - let policyDoc = try self.getPolicyDoc(policyVersion) + let policyVersion = stableInfo.bestPolicyVersion() + let policyDoc = try self.getPolicyDoc(policyVersion.versionNumber) - let updatedStableInfo = TPPeerStableInfo(clock: stableInfo.clock + 1, - policyVersion: policyDoc.policyVersion, - policyHash: policyDoc.policyHash, - policySecrets: stableInfo.policySecrets, - deviceName: stableInfo.deviceName, - serialNumber: stableInfo.serialNumber, - osVersion: stableInfo.osVersion, - signing: signingKeyPair, - recoverySigningPubKey: signingPublicKey, - recoveryEncryptionPubKey: encryptionPublicKey, - error: nil) + let updatedStableInfo = try TPPeerStableInfo(clock: stableInfo.clock + 1, + frozenPolicyVersion: frozenPolicyVersion, + flexiblePolicyVersion: policyDoc.version, + policySecrets: stableInfo.policySecrets, + syncUserControllableViews: stableInfo.syncUserControllableViews, + deviceName: stableInfo.deviceName, + serialNumber: stableInfo.serialNumber, + osVersion: stableInfo.osVersion, + signing: signingKeyPair, + recoverySigningPubKey: signingPublicKey, + recoveryEncryptionPubKey: encryptionPublicKey) let signedStableInfo = SignedPeerStableInfo(updatedStableInfo) let request = SetRecoveryKeyRequest.with { @@ -1660,10 +1840,9 @@ class Container: NSObject { } self.cuttlefish.setRecoveryKey(request) { response, error in - os_log("SetRecoveryKey(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { - os_log("setRecoveryKey failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(error ?? ContainerError.cloudkitResponseMissing) + os_log("setRecoveryKey failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, error ?? ContainerError.cloudkitResponseMissing) return } @@ -1674,320 +1853,167 @@ class Container: NSObject { try self.onQueuePersist(changes: response.changes) os_log("setRecoveryKey succeeded", log: tplogDebug, type: .default) - reply(nil) + + let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } + reply(keyHierarchyRecords, nil) } catch { - os_log("setRecoveryKey handling failed: %@", log: tplogDebug, type: .default, (error as CVarArg)) - reply(error) + os_log("setRecoveryKey handling failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg)) + reply(nil, error) } } } } catch { - reply(error) + reply(nil, error) } } } } } - func currentSetContainerBottleID(bottleMOs: Set, bottleID: String) -> (Bool) { - let bmos = bottleMOs.filter { - $0.bottleID == bottleID - } - return !bmos.isEmpty - } - - func onqueueFindBottle(bottleID: String, reply: @escaping (BottleMO?, Error?) -> Void) { - - var bmo: BottleMO? - var bottles: Set = [] - var shouldPerformFetch = false - - if let containerBottles = self.containerMO.bottles as? Set { - if self.currentSetContainerBottleID(bottleMOs: containerBottles, bottleID: bottleID) == false { - shouldPerformFetch = true - } else { - bottles = containerBottles - } - } else { - shouldPerformFetch = true - } - - if shouldPerformFetch == true { - self.fetchViableBottlesWithSemaphore { _, _, error in - guard error == nil else { - os_log("fetchViableBottles failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, error) - return - } - - guard let newBottles = self.containerMO.bottles as? Set else { - os_log("no bottles on container: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, ContainerError.noBottlesPresent) - return - } - - guard self.currentSetContainerBottleID(bottleMOs: newBottles, bottleID: bottleID) == true else { - reply(nil, ContainerError.noBottlesForEscrowRecordID) - return - } - - os_log("onqueueFindBottle found bottle: %@", log: tplogDebug, type: .default, newBottles) - - bottles = newBottles.filter { - $0.bottleID == bottleID - } - if bottles.count > 1 { - reply(nil, ContainerError.tooManyBottlesForPeer) - return - } - bmo = bottles.removeFirst() - reply(bmo, nil) - } - } else { - var filteredBottles = bottles.filter { - $0.bottleID == bottleID - } - if filteredBottles.count > 1 { - reply(nil, ContainerError.tooManyBottlesForPeer) - return - } - bmo = filteredBottles.removeFirst() - reply(bmo, nil) - } - } - - func onqueueRecoverBottle(managedBottle: BottleMO, entropy: Data, bottleSalt: String) throws -> BottledPeer { - guard let bottledContents = managedBottle.contents else { - throw ContainerError.bottleDoesNotContainContents - } - guard let signatureUsingEscrowKey = managedBottle.signatureUsingEscrowKey else { - throw ContainerError.bottleDoesNotContainEscrowKeySignature - } - - guard let signatureUsingPeerKey = managedBottle.signatureUsingPeerKey else { - throw ContainerError.bottleDoesNotContainerPeerKeySignature - } - guard let sponsorPeerID = managedBottle.peerID else { - throw ContainerError.bottleDoesNotContainPeerID - } - - //verify bottle signature using peer - do { - guard let sponsorPeer = self.model.peer(withID: sponsorPeerID) else { - os_log("recover bottle: Unable to find peer that created the bottle", log: tplogDebug, type: .default) - throw ContainerError.bottleCreatingPeerNotFound - } - guard let signingKey: _SFECPublicKey = sponsorPeer.permanentInfo.signingPubKey as? _SFECPublicKey else { - os_log("recover bottle: Unable to create a sponsor public key", log: tplogDebug, type: .default) - throw ContainerError.signatureVerificationFailed - } - - _ = try BottledPeer.verifyBottleSignature(data: bottledContents, signature: signatureUsingPeerKey, pubKey: signingKey) - } catch { - os_log("Verification of bottled signature failed: %@", log: tplogDebug, type: .default, error as CVarArg) - throw ContainerError.failedToCreateBottledPeer - } - - do { - return try BottledPeer(contents: bottledContents, - secret: entropy, - bottleSalt: bottleSalt, - signatureUsingEscrow: signatureUsingEscrowKey, - signatureUsingPeerKey: signatureUsingPeerKey) - } catch { - os_log("Creation of Bottled Peer failed with bottle salt: %@,\nAttempting with empty bottle salt", bottleSalt) - - do { - return try BottledPeer(contents: bottledContents, - secret: entropy, - bottleSalt: "", - signatureUsingEscrow: signatureUsingEscrowKey, - signatureUsingPeerKey: signatureUsingPeerKey) - } catch { - os_log("Creation of Bottled Peer failed: %@", log: tplogDebug, type: .default, error as CVarArg) - throw ContainerError.failedToCreateBottledPeer - } - } - } - - func preflightVouchWithBottle(bottleID: String, - reply: @escaping (String?, Error?) -> Void) { - self.semaphore.wait() - let reply: (String?, Error?) -> Void = { - os_log("preflightVouchWithBottle complete: %@", - log: tplogTrace, type: .info, traceError($1)) - self.semaphore.signal() - reply($0, $1) - } - - self.moc.performAndWait { - self.onqueueFindBottle(bottleID: bottleID) { bottleMO, error in - guard let bottleMO = bottleMO else { - os_log("preflightVouchWithBottle found no bottle: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, error) - return - } - - reply(bottleMO.peerID, nil) - } - } - } - func vouchWithBottle(bottleID: String, entropy: Data, bottleSalt: String, tlkShares: [CKKSTLKShare], - reply: @escaping (Data?, Data?, Error?) -> Void) { + reply: @escaping (Data?, Data?, Int64, Int64, Error?) -> Void) { self.semaphore.wait() - let reply: (Data?, Data?, Error?) -> Void = { - os_log("vouchWithBottle complete: %@", - log: tplogTrace, type: .info, traceError($2)) + let reply: (Data?, Data?, Int64, Int64, Error?) -> Void = { + os_log("vouchWithBottle complete: %{public}@", + log: tplogTrace, type: .info, traceError($4)) self.semaphore.signal() - reply($0, $1, $2) + reply($0, $1, $2, $3, $4) } - self.fetchAndPersistChanges { error in - guard error == nil else { - os_log("vouchWithBottle unable to fetch changes: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, nil, error) + // A preflight should have been successful before calling this function. So, we can assume that all required data is stored locally. + + self.moc.performAndWait { + let bmo: BottleMO + + do { + (bmo, _, _) = try self.onMOCQueuePerformPreflight(bottleID: bottleID) + } catch { + os_log("vouchWithBottle failed preflight: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") + reply(nil, nil, 0, 0, error) return } - self.onqueueFindBottle(bottleID: bottleID) { returnedBMO, error in - self.moc.performAndWait { - guard error == nil else { - os_log("vouchWithBottle unable to find bottle for escrow record id: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, nil, error) - return - } + guard let bottledContents = bmo.contents else { + reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainContents) + return + } + guard let signatureUsingEscrowKey = bmo.signatureUsingEscrowKey else { + reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainEscrowKeySignature) + return + } - guard let bmo: BottleMO = returnedBMO else { - os_log("vouchWithBottle bottle is nil: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, nil, error) - return - } + guard let signatureUsingPeerKey = bmo.signatureUsingPeerKey else { + reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainerPeerKeySignature) + return + } + guard let sponsorPeerID = bmo.peerID else { + reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainPeerID) + return + } - guard let bottledContents = bmo.contents else { - reply(nil, nil, ContainerError.bottleDoesNotContainContents) - return - } - guard let signatureUsingEscrowKey = bmo.signatureUsingEscrowKey else { - reply(nil, nil, ContainerError.bottleDoesNotContainEscrowKeySignature) - return - } + //verify bottle signature using peer + do { + guard let sponsorPeer = self.model.peer(withID: sponsorPeerID) else { + os_log("vouchWithBottle: Unable to find peer that created the bottle", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.bottleCreatingPeerNotFound) + return + } + guard let signingKey: _SFECPublicKey = sponsorPeer.permanentInfo.signingPubKey as? _SFECPublicKey else { + os_log("vouchWithBottle: Unable to create a sponsor public key", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.signatureVerificationFailed) + return + } - guard let signatureUsingPeerKey = bmo.signatureUsingPeerKey else { - reply(nil, nil, ContainerError.bottleDoesNotContainerPeerKeySignature) - return - } - guard let sponsorPeerID = bmo.peerID else { - reply(nil, nil, ContainerError.bottleDoesNotContainPeerID) - return - } + _ = try BottledPeer.verifyBottleSignature(data: bottledContents, signature: signatureUsingPeerKey, pubKey: signingKey) + } catch { + os_log("vouchWithBottle: Verification of bottled signature failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, 0, 0, ContainerError.failedToCreateBottledPeer) + return + } - //verify bottle signature using peer - do { - guard let sponsorPeer = self.model.peer(withID: sponsorPeerID) else { - os_log("vouchWithBottle: Unable to find peer that created the bottle", log: tplogDebug, type: .default) - reply(nil, nil, ContainerError.bottleCreatingPeerNotFound) - return - } - guard let signingKey: _SFECPublicKey = sponsorPeer.permanentInfo.signingPubKey as? _SFECPublicKey else { - os_log("vouchWithBottle: Unable to create a sponsor public key", log: tplogDebug, type: .default) - reply(nil, nil, ContainerError.signatureVerificationFailed) - return - } + //create bottled peer + let bottledPeer: BottledPeer + do { + bottledPeer = try BottledPeer(contents: bottledContents, + secret: entropy, + bottleSalt: bottleSalt, + signatureUsingEscrow: signatureUsingEscrowKey, + signatureUsingPeerKey: signatureUsingPeerKey) + } catch { + os_log("Creation of Bottled Peer failed with bottle salt: %@,\nAttempting with empty bottle salt", bottleSalt) - _ = try BottledPeer.verifyBottleSignature(data: bottledContents, signature: signatureUsingPeerKey, pubKey: signingKey) - } catch { - os_log("vouchWithBottle: Verification of bottled signature failed: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, ContainerError.failedToCreateBottledPeer) - return - } + do { + bottledPeer = try BottledPeer(contents: bottledContents, + secret: entropy, + bottleSalt: "", + signatureUsingEscrow: signatureUsingEscrowKey, + signatureUsingPeerKey: signatureUsingPeerKey) + } catch { + os_log("Creation of Bottled Peer failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, 0, 0, ContainerError.failedToCreateBottledPeer) + return + } + } - //create bottled peer - let bottledPeer: BottledPeer - do { - bottledPeer = try BottledPeer(contents: bottledContents, - secret: entropy, - bottleSalt: bottleSalt, - signatureUsingEscrow: signatureUsingEscrowKey, - signatureUsingPeerKey: signatureUsingPeerKey) - } catch { - os_log("Creation of Bottled Peer failed with bottle salt: %@,\nAttempting with empty bottle salt", bottleSalt) + os_log("Have a bottle for peer %{public}@", log: tplogDebug, type: .default, bottledPeer.peerID) - do { - bottledPeer = try BottledPeer(contents: bottledContents, - secret: entropy, - bottleSalt: "", - signatureUsingEscrow: signatureUsingEscrowKey, - signatureUsingPeerKey: signatureUsingPeerKey) - } catch { + // Extract any TLKs we have been given + let (uniqueTLKsRecovered, totalSharesRecovered) = extract(tlkShares: tlkShares, peer: bottledPeer.peerKeys, model: self.model) - os_log("Creation of Bottled Peer failed: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, ContainerError.failedToCreateBottledPeer) - return - } - } + self.moc.performAndWait { + // I must have an ego identity in order to vouch using bottle + guard let egoPeerID = self.containerMO.egoPeerID else { + os_log("As a nonmember, can't vouch for someone else", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + guard let permanentInfo = self.containerMO.egoPeerPermanentInfo else { + os_log("permanentInfo does not exist", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + guard let permanentInfoSig = self.containerMO.egoPeerPermanentInfoSig else { + os_log("permanentInfoSig does not exist", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + guard let stableInfo = self.containerMO.egoPeerStableInfo else { + os_log("stableInfo does not exist", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + guard let stableInfoSig = self.containerMO.egoPeerStableInfoSig else { + os_log("stableInfoSig does not exist", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + let keyFactory = TPECPublicKeyFactory() + guard let beneficiaryPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: permanentInfo, sig: permanentInfoSig, keyFactory: keyFactory) else { + os_log("Invalid permenent info or signature; can't vouch for them", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.invalidPermanentInfoOrSig) + return + } + guard let beneficiaryStableInfo = TPPeerStableInfo(data: stableInfo, sig: stableInfoSig) else { + os_log("Invalid stableinfo or signature; van't vouch for them", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.invalidStableInfoOrSig) + return + } - os_log("Have a bottle for peer %@", log: tplogDebug, type: .default, bottledPeer.peerID) - - // Extract any TLKs we have been given - extract(tlkShares: tlkShares, peer: bottledPeer.peerKeys) - - self.moc.performAndWait { - // I must have an ego identity in order to vouch using bottle - guard let egoPeerID = self.containerMO.egoPeerID else { - os_log("As a nonmember, can't vouch for someone else", log: tplogDebug, type: .default) - reply(nil, nil, ContainerError.nonMember) - return - } - guard let permanentInfo = self.containerMO.egoPeerPermanentInfo else { - os_log("permanentInfo does not exist", log: tplogDebug, type: .default) - reply(nil, nil, ContainerError.nonMember) - return - } - guard let permanentInfoSig = self.containerMO.egoPeerPermanentInfoSig else { - os_log("permanentInfoSig does not exist", log: tplogDebug, type: .default) - reply(nil, nil, ContainerError.nonMember) - return - } - guard let stableInfo = self.containerMO.egoPeerStableInfo else { - os_log("stableInfo does not exist", log: tplogDebug, type: .default) - reply(nil, nil, ContainerError.nonMember) - return - } - guard let stableInfoSig = self.containerMO.egoPeerStableInfoSig else { - os_log("stableInfoSig does not exist", log: tplogDebug, type: .default) - reply(nil, nil, ContainerError.nonMember) - return - } - let keyFactory = TPECPublicKeyFactory() - guard let beneficiaryPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: permanentInfo, sig: permanentInfoSig, keyFactory: keyFactory) else { - os_log("Invalid permenent info or signature; can't vouch for them", log: tplogDebug, type: .default) - reply(nil, nil, ContainerError.invalidPermanentInfoOrSig) - return - } - guard let beneficiaryStableInfo = TPPeerStableInfo(data: stableInfo, sig: stableInfoSig) else { - os_log("Invalid stableinfo or signature; van't vouch for them", log: tplogDebug, type: .default) - reply(nil, nil, ContainerError.invalidStableInfoOrSig) - return - } - - do { - let voucher = try self.model.createVoucher(forCandidate: beneficiaryPermanentInfo, - stableInfo: beneficiaryStableInfo, - withSponsorID: sponsorPeerID, - reason: TPVoucherReason.restore, - signing: bottledPeer.peerKeys.signingKey) - reply(voucher.data, voucher.sig, nil) - return - } catch { - os_log("Error creating voucher: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, error) - return - } - } + do { + let voucher = try self.model.createVoucher(forCandidate: beneficiaryPermanentInfo, + stableInfo: beneficiaryStableInfo, + withSponsorID: sponsorPeerID, + reason: TPVoucherReason.restore, + signing: bottledPeer.peerKeys.signingKey) + reply(voucher.data, voucher.sig, uniqueTLKsRecovered, totalSharesRecovered, nil) + return + } catch { + os_log("Error creating voucher with bottle: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, 0, 0, error) + return } } } @@ -1999,7 +2025,7 @@ class Container: NSObject { reply: @escaping (Data?, Data?, Error?) -> Void) { self.semaphore.wait() let reply: (Data?, Data?, Error?) -> Void = { - os_log("vouchWithRecoveryKey complete: %@", + os_log("vouchWithRecoveryKey complete: %{public}@", log: tplogTrace, type: .info, traceError($2)) self.semaphore.signal() reply($0, $1, $2) @@ -2051,18 +2077,16 @@ class Container: NSObject { do { recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) } catch { - os_log("failed to create recovery keys: %@", log: tplogDebug, type: .default, error as CVarArg) + os_log("failed to create recovery keys: %{public}@", log: tplogDebug, type: .default, error as CVarArg) reply(nil, nil, ContainerError.failedToCreateRecoveryKey) return } - extract(tlkShares: tlkShares, peer: recoveryKeys.peerKeys) - let signingPublicKey: Data = recoveryKeys.peerKeys.signingKey.publicKey.keyData let encryptionPublicKey: Data = recoveryKeys.peerKeys.encryptionKey.publicKey.keyData - os_log("vouchWithRecoveryKey signingPubKey: %@", log: tplogDebug, type: .debug, signingPublicKey.base64EncodedString()) - os_log("vouchWithRecoveryKey encryptionPubKey: %@", log: tplogDebug, type: .debug, encryptionPublicKey.base64EncodedString()) + os_log("vouchWithRecoveryKey signingPubKey: %@", log: tplogDebug, type: .default, signingPublicKey.base64EncodedString()) + os_log("vouchWithRecoveryKey encryptionPubKey: %@", log: tplogDebug, type: .default, encryptionPublicKey.base64EncodedString()) guard self.model.isRecoveryKeyEnrolled() else { os_log("Recovery Key is not enrolled", log: tplogDebug, type: .default) @@ -2071,12 +2095,16 @@ class Container: NSObject { } //find matching peer containing recovery keys - guard let sponsorPeerID = self.model.peerIDThatTrustsRecoveryKeys(TPRecoveryKeyPair(signingSPKI: signingPublicKey, encryptionSPKI: encryptionPublicKey)) else { + guard let sponsorPeerID = self.model.peerIDThatTrustsRecoveryKeys(TPRecoveryKeyPair(signingKeyData: signingPublicKey, encryptionKeyData: encryptionPublicKey)) else { os_log("Untrusted recovery key set", log: tplogDebug, type: .default) reply(nil, nil, ContainerError.untrustedRecoveryKeys) return } + // We're going to end up trusting every peer that the sponsor peer trusts. + // We might as well trust all TLKShares from those peers at this point. + extract(tlkShares: tlkShares, peer: recoveryKeys.peerKeys, sponsorPeerID: sponsorPeerID, model: self.model) + do { let voucher = try self.model.createVoucher(forCandidate: beneficiaryPermanentInfo, stableInfo: beneficiaryStableInfo, @@ -2086,7 +2114,7 @@ class Container: NSObject { reply(voucher.data, voucher.sig, nil) return } catch { - os_log("Error creating voucher using recovery key set: %@", log: tplogDebug, type: .default, error as CVarArg) + os_log("Error creating voucher using recovery key set: %{public}@", log: tplogDebug, type: .default, error as CVarArg) reply(nil, nil, error) return } @@ -2102,7 +2130,7 @@ class Container: NSObject { reply: @escaping (Data?, Data?, Error?) -> Void) { self.semaphore.wait() let reply: (Data?, Data?, Error?) -> Void = { - os_log("vouch complete: %@", log: tplogTrace, type: .info, traceError($2)) + os_log("vouch complete: %{public}@", log: tplogTrace, type: .info, traceError($2)) self.semaphore.signal() reply($0, $1, $2) } @@ -2138,65 +2166,79 @@ class Container: NSObject { loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in guard let egoPeerKeys = egoPeerKeys else { - os_log("Don't have my own keys: can't vouch for %@: %@", log: tplogDebug, type: .default, beneficiaryPermanentInfo, (error as CVarArg?) ?? "no error") + os_log("Don't have my own keys: can't vouch for %{public}@(%{public}@): %{public}@", log: tplogDebug, type: .default, peerID, beneficiaryPermanentInfo, (error as CVarArg?) ?? "no error") reply(nil, nil, error) return } - self.moc.performAndWait { - let voucher: TPVoucher - do { - voucher = try self.model.createVoucher(forCandidate: beneficiaryPermanentInfo, - stableInfo: beneficiaryStableInfo, - withSponsorID: egoPeerID, - reason: TPVoucherReason.secureChannel, - signing: egoPeerKeys.signingKey) - } catch { - os_log("Error creating voucher: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, error) + self.fetchPolicyDocumentsWithSemaphore(versions: Set([beneficiaryStableInfo.bestPolicyVersion()])) { _, policyFetchError in + guard policyFetchError == nil else { + os_log("Unknown policy for beneficiary: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, nil, policyFetchError) return } - // And generate and upload any tlkShares - // Note that this might not be the whole list: Octagon: Limited Peers - let tlkShares: [TLKShare] - do { - // Note: we only want to send up TLKs for uploaded ckks zones - let ckksTLKs = ckksKeys.filter { !$0.newUpload }.map { $0.tlk } + self.moc.performAndWait { + let voucher: TPVoucher + do { + voucher = try self.model.createVoucher(forCandidate: beneficiaryPermanentInfo, + stableInfo: beneficiaryStableInfo, + withSponsorID: egoPeerID, + reason: TPVoucherReason.secureChannel, + signing: egoPeerKeys.signingKey) + } catch { + os_log("Error creating voucher: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, error) + return + } - tlkShares = try makeTLKShares(ckksTLKs: ckksTLKs, - asPeer: egoPeerKeys, - toPeer: beneficiaryPermanentInfo, - epoch: Int(selfPermanentInfo.epoch)) - } catch { - os_log("Unable to make TLKShares for beneficiary %@: %@", log: tplogDebug, type: .default, beneficiaryPermanentInfo, error as CVarArg) - reply(nil, nil, error) - return - } + // And generate and upload any tlkShares + let tlkShares: [TLKShare] + do { + // Note that this might not be the whole list, so filter some of them out + let peerViews = try? self.model.getViewsForPeer(beneficiaryPermanentInfo, + stableInfo: beneficiaryStableInfo) - guard !tlkShares.isEmpty else { - os_log("No TLKShares to upload for new peer, returning voucher", log: tplogDebug, type: .default) - reply(voucher.data, voucher.sig, nil) - return - } + // Note: we only want to send up TLKs for uploaded ckks zones + let ckksTLKs = ckksKeys + .filter { !$0.newUpload } + .filter { peerViews?.contains($0.tlk.zoneID.zoneName) ?? false } + .map { $0.tlk } - self.cuttlefish.updateTrust(changeToken: self.containerMO.changeToken ?? "", - peerID: egoPeerID, - stableInfoAndSig: nil, - dynamicInfoAndSig: nil, - tlkShares: tlkShares, - viewKeys: []) { response, error in - guard let response = response, error == nil else { - os_log("Unable to upload new tlkshares: %@", log: tplogDebug, type: .default, error as CVarArg? ?? "no error") - reply(voucher.data, voucher.sig, error ?? ContainerError.cloudkitResponseMissing) - return - } + tlkShares = try makeTLKShares(ckksTLKs: ckksTLKs, + asPeer: egoPeerKeys, + toPeer: beneficiaryPermanentInfo, + epoch: Int(selfPermanentInfo.epoch)) + } catch { + os_log("Unable to make TLKShares for beneficiary %{public}@(%{public}@): %{public}@", log: tplogDebug, type: .default, peerID, beneficiaryPermanentInfo, error as CVarArg) + reply(nil, nil, error) + return + } - let newKeyRecords = response.zoneKeyHierarchyRecords.map(CKRecord.init) - os_log("Uploaded new tlkshares: %@", log: tplogDebug, type: .default, newKeyRecords) - // We don't need to save these; CKKS will refetch them as needed + guard !tlkShares.isEmpty else { + os_log("No TLKShares to upload for new peer, returning voucher", log: tplogDebug, type: .default) + reply(voucher.data, voucher.sig, nil) + return + } - reply(voucher.data, voucher.sig, nil) + self.cuttlefish.updateTrust(changeToken: self.containerMO.changeToken ?? "", + peerID: egoPeerID, + stableInfoAndSig: nil, + dynamicInfoAndSig: nil, + tlkShares: tlkShares, + viewKeys: []) { response, error in + guard let response = response, error == nil else { + os_log("Unable to upload new tlkshares: %{public}@", log: tplogDebug, type: .default, error as CVarArg? ?? "no error") + reply(voucher.data, voucher.sig, error ?? ContainerError.cloudkitResponseMissing) + return + } + + let newKeyRecords = response.zoneKeyHierarchyRecords.map(CKRecord.init) + os_log("Uploaded new tlkshares: %@", log: tplogDebug, type: .default, newKeyRecords) + // We don't need to save these; CKKS will refetch them as needed + + reply(voucher.data, voucher.sig, nil) + } } } } @@ -2206,7 +2248,7 @@ class Container: NSObject { func departByDistrustingSelf(reply: @escaping (Error?) -> Void) { self.semaphore.wait() let reply: (Error?) -> Void = { - os_log("departByDistrustingSelf complete: %@", log: tplogTrace, type: .info, traceError($0)) + os_log("departByDistrustingSelf complete: %{public}@", log: tplogTrace, type: .info, traceError($0)) self.semaphore.signal() reply($0) } @@ -2226,7 +2268,7 @@ class Container: NSObject { reply: @escaping (Error?) -> Void) { self.semaphore.wait() let reply: (Error?) -> Void = { - os_log("distrust complete: %@", log: tplogTrace, type: .info, traceError($0)) + os_log("distrust complete: %{public}@", log: tplogTrace, type: .info, traceError($0)) self.semaphore.signal() reply($0) } @@ -2250,7 +2292,6 @@ class Container: NSObject { func onqueueDistrust(peerIDs: Set, reply: @escaping (Error?) -> Void) { - guard let egoPeerID = self.containerMO.egoPeerID else { os_log("No dynamic info for self?", log: tplogDebug, type: .default) reply(ContainerError.noPreparedIdentity) @@ -2259,7 +2300,7 @@ class Container: NSObject { loadEgoKeyPair(identifier: signingKeyIdentifier(peerID: egoPeerID)) { signingKeyPair, error in guard let signingKeyPair = signingKeyPair else { - os_log("No longer have signing key pair; can't sign distrust: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "nil") + os_log("No longer have signing key pair; can't sign distrust: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "nil") reply(error) return } @@ -2273,15 +2314,14 @@ class Container: NSObject { preapprovedKeys: nil, signing: signingKeyPair, currentMachineIDs: self.onqueueCurrentMIDList()) - } catch { - os_log("Error preparing dynamic info: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "nil") + os_log("Error preparing dynamic info: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "nil") reply(error) return } let signedDynamicInfo = SignedPeerDynamicInfo(dynamicInfo) - os_log("attempting distrust for %@ with: %@", log: tplogDebug, type: .default, peerIDs, dynamicInfo) + os_log("attempting distrust for %{public}@ with: %{public}@", log: tplogDebug, type: .default, peerIDs, dynamicInfo) let request = UpdateTrustRequest.with { $0.changeToken = self.containerMO.changeToken ?? "" @@ -2289,9 +2329,8 @@ class Container: NSObject { $0.dynamicInfoAndSig = signedDynamicInfo } self.cuttlefish.updateTrust(request) { response, error in - os_log("UpdateTrust(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { - os_log("updateTrust failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + os_log("updateTrust failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(error ?? ContainerError.cloudkitResponseMissing) return } @@ -2301,7 +2340,7 @@ class Container: NSObject { os_log("distrust succeeded", log: tplogDebug, type: .default) reply(nil) } catch { - os_log("distrust handling failed: %@", log: tplogDebug, type: .default, (error as CVarArg)) + os_log("distrust handling failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg)) reply(error) } } @@ -2312,7 +2351,7 @@ class Container: NSObject { func fetchEscrowContents(reply: @escaping (Data?, String?, Data?, Error?) -> Void) { self.semaphore.wait() let reply: (Data?, String?, Data?, Error?) -> Void = { - os_log("fetchEscrowContents complete: %@", log: tplogTrace, type: .info, traceError($3)) + os_log("fetchEscrowContents complete: %{public}@", log: tplogTrace, type: .info, traceError($3)) self.semaphore.signal() reply($0, $1, $2, $3) } @@ -2331,8 +2370,12 @@ class Container: NSObject { return } - var bmoSet = bottles.filter { $0.peerID == egoPeerID } - let bmo = bmoSet.removeFirst() + guard let bmo = bottles.filter({ $0.peerID == egoPeerID }).first else { + os_log("fetchEscrowContents no bottle matches peerID", log: tplogDebug, type: .default) + reply(nil, nil, nil, ContainerError.noBottleForPeer) + return + } + let bottleID = bmo.bottleID var entropy: Data @@ -2344,7 +2387,7 @@ class Container: NSObject { } entropy = loaded } catch { - os_log("fetchEscrowContents failed to load entropy: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + os_log("fetchEscrowContents failed to load entropy: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, nil, nil, error) return } @@ -2361,7 +2404,7 @@ class Container: NSObject { func fetchViableBottles(reply: @escaping ([String]?, [String]?, Error?) -> Void) { self.semaphore.wait() let reply: ([String]?, [String]?, Error?) -> Void = { - os_log("fetchViableBottles complete: %@", log: tplogTrace, type: .info, traceError($2)) + os_log("fetchViableBottles complete: %{public}@", log: tplogTrace, type: .info, traceError($2)) self.semaphore.signal() reply($0, $1, $2) } @@ -2369,51 +2412,179 @@ class Container: NSObject { self.fetchViableBottlesWithSemaphore(reply: reply) } - func onqueueCachedBottlesContainEgoPeerBottle(cachedBottles: TPCachedViableBottles) -> Bool { - guard let egoPeerID = self.containerMO.egoPeerID else { - os_log("bottleForEgoPeer: No identity.", log: tplogDebug, type: .default) - return false + func handleFetchViableBottlesResponseWithSemaphore(response: FetchViableBottlesResponse?) { + guard let escrowPairs = response?.viableBottles else { + os_log("fetchViableBottles returned no viable bottles", log: tplogDebug, type: .default) + return } - guard let bottles: Set = self.containerMO.bottles as? Set else { - os_log("bottleForEgoPeer: No Bottles.", log: tplogDebug, type: .default) - return false + + var partialPairs: [EscrowPair] = [] + if let partial = response?.partialBottles { + partialPairs = partial + } else { + os_log("fetchViableBottles returned no partially viable bottles, but that's ok", log: tplogDebug, type: .default) } - var matchesCached: Bool = false - for bottle in bottles { - guard let bottleID: String = bottle.bottleID else { - continue + + var legacyEscrowInformations: [EscrowInformation] = [] + if let legacy = response?.legacyRecords { + legacyEscrowInformations = legacy + } else { + os_log("fetchViableBottles returned no legacy escrow records", log: tplogDebug, type: .default) + } + + escrowPairs.forEach { pair in + let bottle = pair.bottle + let record = pair.record + if pair.hasRecord { + // Save this escrow record only if we don't already have it + if let existingRecords = self.containerMO.fullyViableEscrowRecords as? Set { + let matchingRecords: Set = existingRecords.filter { existing in existing.label == record.label + && existing.escrowMetadata?.bottleID == record.escrowInformationMetadata.bottleID } + if !matchingRecords.isEmpty { + os_log("fetchViableBottles already knows about record, re-adding entry", log: tplogDebug, type: .default, record.label) + self.containerMO.removeFromFullyViableEscrowRecords(matchingRecords as NSSet) + } + self.setEscrowRecord(record: record, viability: .full) + } } - if bottle.peerID == egoPeerID && (cachedBottles.viableBottles.contains(bottleID) || cachedBottles.partialBottles.contains(bottleID)) { - matchesCached = true - break + // Save this bottle only if we don't already have it + if let existingBottles = self.containerMO.bottles as? Set { + let matchingBottles: Set = existingBottles.filter { existing in + existing.peerID == bottle.peerID && + existing.bottleID == bottle.bottleID && + existing.escrowedSigningSPKI == bottle.escrowedSigningSpki && + existing.signatureUsingEscrowKey == bottle.signatureUsingEscrowKey && + existing.signatureUsingPeerKey == bottle.signatureUsingPeerKey && + existing.contents == bottle.contents + } + if !matchingBottles.isEmpty { + os_log("fetchViableBottles already knows about bottle", log: tplogDebug, type: .default, bottle.bottleID) + return + } + } + + let bmo = BottleMO(context: self.moc) + bmo.peerID = bottle.peerID + bmo.bottleID = bottle.bottleID + bmo.escrowedSigningSPKI = bottle.escrowedSigningSpki + bmo.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey + bmo.signatureUsingPeerKey = bottle.signatureUsingPeerKey + bmo.contents = bottle.contents + + os_log("fetchViableBottles saving new bottle: %{public}@", log: tplogDebug, type: .default, bmo) + self.containerMO.addToBottles(bmo) + } + + partialPairs.forEach { pair in + let bottle = pair.bottle + + let record = pair.record + // Save this escrow record only if we don't already have it + if pair.hasRecord { + if let existingRecords = self.containerMO.partiallyViableEscrowRecords as? Set { + let matchingRecords: Set = existingRecords.filter { existing in existing.label == record.label + && existing.escrowMetadata?.bottleID == record.escrowInformationMetadata.bottleID } + if !matchingRecords.isEmpty { + os_log("fetchViableBottles already knows about record, re-adding entry", log: tplogDebug, type: .default, record.label) + self.containerMO.removeFromPartiallyViableEscrowRecords(matchingRecords as NSSet) + } + self.setEscrowRecord(record: record, viability: Viability.partial) + } + } + + // Save this bottle only if we don't already have it + if let existingBottles = self.containerMO.bottles as? Set { + let matchingBottles: Set = existingBottles.filter { existing in + existing.peerID == bottle.peerID && + existing.bottleID == bottle.bottleID && + existing.escrowedSigningSPKI == bottle.escrowedSigningSpki && + existing.signatureUsingEscrowKey == bottle.signatureUsingEscrowKey && + existing.signatureUsingPeerKey == bottle.signatureUsingPeerKey && + existing.contents == bottle.contents + } + if !matchingBottles.isEmpty { + os_log("fetchViableBottles already knows about bottle", log: tplogDebug, type: .default, bottle.bottleID) + return + } + } + + let bmo = BottleMO(context: self.moc) + bmo.peerID = bottle.peerID + bmo.bottleID = bottle.bottleID + bmo.escrowedSigningSPKI = bottle.escrowedSigningSpki + bmo.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey + bmo.signatureUsingPeerKey = bottle.signatureUsingPeerKey + bmo.contents = bottle.contents + + os_log("fetchViableBottles saving new bottle: %{public}@", log: tplogDebug, type: .default, bmo) + self.containerMO.addToBottles(bmo) + } + legacyEscrowInformations.forEach { record in + // Save this escrow record only if we don't already have it + if let existingRecords = self.containerMO.legacyEscrowRecords as? Set { + let matchingRecords: Set = existingRecords.filter { existing in existing.label == record.label } + if !matchingRecords.isEmpty { + os_log("fetchViableBottles already knows about legacy record %@, re-adding entry", log: tplogDebug, type: .default, record.label) + self.containerMO.removeFromLegacyEscrowRecords(matchingRecords as NSSet) + } + if record.label.hasSuffix(".double") { + os_log("ignoring double enrollment record %@", record.label) + } else { + self.setEscrowRecord(record: record, viability: Viability.none) + } } } - return matchesCached } func fetchViableBottlesWithSemaphore(reply: @escaping ([String]?, [String]?, Error?) -> Void) { os_log("beginning a fetchViableBottles", log: tplogDebug, type: .default) - let cachedBottles: TPCachedViableBottles = self.model.currentCachedViableBottlesSet() self.moc.performAndWait { - if self.onqueueCachedBottlesContainEgoPeerBottle(cachedBottles: cachedBottles) - && (cachedBottles.viableBottles.count > 0 || cachedBottles.partialBottles.count > 0) { + var cachedBottles = TPCachedViableBottles(viableBottles: [], partialBottles: []) + + if OctagonIsOptimizationEnabled() { + if let lastDate = self.containerMO.escrowFetchDate { + if Date() < lastDate.addingTimeInterval(escrowCacheTimeout) { + os_log("escrow cache still valid", log: tplogDebug, type: .default) + cachedBottles = onqueueCachedBottlesFromEscrowRecords() + } else { + os_log("escrow cache no longer valid", log: tplogDebug, type: .default) + if let records = self.containerMO.fullyViableEscrowRecords { + self.containerMO.removeFromFullyViableEscrowRecords(records) + } + if let records = self.containerMO.partiallyViableEscrowRecords { + self.containerMO.removeFromPartiallyViableEscrowRecords(records) + } + self.containerMO.escrowFetchDate = nil + } + } + } else { + cachedBottles = self.model.currentCachedViableBottlesSet() + } + + if !cachedBottles.viableBottles.isEmpty || !cachedBottles.partialBottles.isEmpty { os_log("returning from fetchViableBottles, using cached bottles", log: tplogDebug, type: .default) reply(cachedBottles.viableBottles, cachedBottles.partialBottles, nil) return } - - self.cuttlefish.fetchViableBottles { response, error in + + let request = FetchViableBottlesRequest.with { + $0.filterRequest = OctagonPlatformSupportsSOS() ? .unknown : .byOctagonOnly + } + if request.filterRequest == .byOctagonOnly { + os_log("Requesting Cuttlefish sort records by Octagon Only", log: tplogDebug, type: .default) + } + + self.cuttlefish.fetchViableBottles(request) { response, error in guard error == nil else { - os_log("fetchViableBottles failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + os_log("fetchViableBottles failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, nil, error) return } self.moc.performAndWait { - guard let escrowPairs = response?.viableBottles else { - os_log("fetchViableBottles returned no viable bottles: %@", log: tplogDebug, type: .default) + os_log("fetchViableBottles returned no viable bottles", log: tplogDebug, type: .default) reply([], [], nil) return } @@ -2422,211 +2593,319 @@ class Container: NSObject { if let partial = response?.partialBottles { partialPairs = partial } else { - os_log("fetchViableBottles returned no partially viable bottles, but that's ok: %@", log: tplogDebug, type: .default) + os_log("fetchViableBottles returned no partially viable bottles, but that's ok", log: tplogDebug, type: .default) } let viableBottleIDs = escrowPairs.compactMap { $0.bottle.bottleID } - os_log("fetchViableBottles returned viable bottles: %@", log: tplogDebug, type: .default, viableBottleIDs) + os_log("fetchViableBottles returned viable bottles: %{public}@", log: tplogDebug, type: .default, viableBottleIDs) let partialBottleIDs = partialPairs.compactMap { $0.bottle.bottleID } - os_log("fetchViableBottles returned partial bottles: %@", log: tplogDebug, type: .default, partialBottleIDs) + os_log("fetchViableBottles returned partial bottles: %{public}@", log: tplogDebug, type: .default, partialBottleIDs) - escrowPairs.forEach { pair in - let bottle = pair.bottle - - // Save this bottle only if we don't already have it - if let existingBottles = self.containerMO.bottles as? Set { - let matchingBottles: Set = existingBottles.filter { existing in - existing.peerID == bottle.peerID && - existing.bottleID == bottle.bottleID && - existing.escrowedSigningSPKI == bottle.escrowedSigningSpki && - existing.signatureUsingEscrowKey == bottle.signatureUsingEscrowKey && - existing.signatureUsingPeerKey == bottle.signatureUsingPeerKey && - existing.contents == bottle.contents - } - if !matchingBottles.isEmpty { - os_log("fetchViableBottles already knows about bottle", log: tplogDebug, type: .default, bottle.bottleID) - return - } - } - - let bmo = BottleMO(context: self.moc) - bmo.peerID = bottle.peerID - bmo.bottleID = bottle.bottleID - bmo.escrowedSigningSPKI = bottle.escrowedSigningSpki - bmo.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey - bmo.signatureUsingPeerKey = bottle.signatureUsingPeerKey - bmo.contents = bottle.contents - - os_log("fetchViableBottles saving new bottle: %@", log: tplogDebug, type: .default, bmo) - self.containerMO.addToBottles(bmo) - } - - partialPairs.forEach { pair in - let bottle = pair.bottle - - // Save this bottle only if we don't already have it - if let existingBottles = self.containerMO.bottles as? Set { - let matchingBottles: Set = existingBottles.filter { existing in - existing.peerID == bottle.peerID && - existing.bottleID == bottle.bottleID && - existing.escrowedSigningSPKI == bottle.escrowedSigningSpki && - existing.signatureUsingEscrowKey == bottle.signatureUsingEscrowKey && - existing.signatureUsingPeerKey == bottle.signatureUsingPeerKey && - existing.contents == bottle.contents - } - if !matchingBottles.isEmpty { - os_log("fetchViableBottles already knows about bottle", log: tplogDebug, type: .default, bottle.bottleID) - return - } - } - - let bmo = BottleMO(context: self.moc) - bmo.peerID = bottle.peerID - bmo.bottleID = bottle.bottleID - bmo.escrowedSigningSPKI = bottle.escrowedSigningSpki - bmo.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey - bmo.signatureUsingPeerKey = bottle.signatureUsingPeerKey - bmo.contents = bottle.contents - - os_log("fetchViableBottles saving new bottle: %@", log: tplogDebug, type: .default, bmo) - self.containerMO.addToBottles(bmo) - } + self.handleFetchViableBottlesResponseWithSemaphore(response: response) do { try self.moc.save() os_log("fetchViableBottles saved bottles", log: tplogDebug, type: .default) let cached = TPCachedViableBottles(viableBottles: viableBottleIDs, partialBottles: partialBottleIDs) self.model.setViableBottles(cached) + self.containerMO.escrowFetchDate = Date() reply(viableBottleIDs, partialBottleIDs, nil) } catch { - os_log("fetchViableBottles unable to save bottles: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + os_log("fetchViableBottles unable to save bottles: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, nil, error) } - } } } } - func fetchPolicy(reply: @escaping (TPPolicy?, Error?) -> Void) { + func removeEscrowCache(reply: @escaping (Error?) -> Void) { + os_log("beginning a removeEscrowCache", log: tplogDebug, type: .default) + self.semaphore.wait() - let reply: (TPPolicy?, Error?) -> Void = { - os_log("fetchPolicy complete: %@", log: tplogTrace, type: .info, traceError($1)) + let reply: (Error?) -> Void = { + os_log("removeEscrowCache complete %{public}@", log: tplogTrace, type: .info, traceError($0)) self.semaphore.signal() - reply($0, $1) + reply($0) } self.moc.performAndWait { - var keys: [NSNumber: String] = [:] + self.onQueueRemoveEscrowCache() + reply(nil) + } + } - guard let stableInfoData = self.containerMO.egoPeerStableInfo, - let stableInfoSig = self.containerMO.egoPeerStableInfoSig else { - os_log("fetchPolicy failed to find ego peer stableinfodata/sig", log: tplogDebug, type: .error) - reply(nil, ContainerError.noPreparedIdentity) - return - } - guard let stableInfo = TPPeerStableInfo(data: stableInfoData, sig: stableInfoSig) else { - os_log("fetchPolicy failed to create TPPeerStableInfo", log: tplogDebug, type: .error) - reply(nil, ContainerError.invalidStableInfoOrSig) - return - } + private func onQueueRemoveEscrowCache() { + if let records = self.containerMO.fullyViableEscrowRecords { + self.containerMO.removeFromFullyViableEscrowRecords(records) + } + if let records = self.containerMO.partiallyViableEscrowRecords { + self.containerMO.removeFromPartiallyViableEscrowRecords(records) + } + if let records = self.containerMO.legacyEscrowRecords { + self.containerMO.removeFromLegacyEscrowRecords(records) + } + self.containerMO.escrowFetchDate = nil + } - let policyVersionCounter = stableInfo.policyVersion - let policyVersion = NSNumber(value: policyVersionCounter) - keys[policyVersion] = stableInfo.policyHash + func fetchEscrowRecordsWithSemaphore(forceFetch: Bool, reply: @escaping ([Data]?, Error?) -> Void) { + os_log("beginning a fetchEscrowRecords", log: tplogDebug, type: .default) - if let policyDocument = self.model.policy(withVersion: policyVersionCounter) { - os_log("fetchPolicy: have a local version of policy %@: %@", log: tplogDebug, type: .default, policyVersion, policyDocument) - do { - let policy = try policyDocument.policy(withSecrets: stableInfo.policySecrets, decrypter: Decrypter()) - reply(policy, nil) - return - } catch { - os_log("TPPolicyDocument failed: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, error) - return + self.moc.performAndWait { + var cachedRecords: [OTEscrowRecord] = [] + + if forceFetch == false { + os_log("fetchEscrowRecords: force fetch flag is off", log: tplogDebug, type: .default) + if let lastDate = self.containerMO.escrowFetchDate { + if Date() < lastDate.addingTimeInterval(escrowCacheTimeout) { + os_log("escrow cache still valid", log: tplogDebug, type: .default) + cachedRecords = onqueueCachedEscrowRecords() + } else { + os_log("escrow cache no longer valid", log: tplogDebug, type: .default) + self.onQueueRemoveEscrowCache() + } } + } else { + os_log("fetchEscrowRecords: force fetch flag is on, removing escrow cache", log: tplogDebug, type: .default) + self.onQueueRemoveEscrowCache() } - self.fetchPolicyDocuments(keys: keys) { result, error in + if !cachedRecords.isEmpty { + os_log("returning from fetchEscrowRecords, using cached escrow records", log: tplogDebug, type: .default) + let recordData: [Data] = cachedRecords.map { $0.data } + reply(recordData, nil) + return + } + + let request = FetchViableBottlesRequest.with { + $0.filterRequest = OctagonPlatformSupportsSOS() ? .unknown : .byOctagonOnly + } + if request.filterRequest == .byOctagonOnly { + os_log("Requesting Cuttlefish sort records by Octagon Only", log: tplogDebug, type: .default) + } + + self.cuttlefish.fetchViableBottles(request) { response, error in guard error == nil else { + os_log("fetchViableBottles failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, error) return } - guard let result = result else { - os_log("fetchPolicy: nil policies returned") - reply(nil, ContainerError.policyDocumentDoesNotValidate) - return - } - guard result.count == 1 else { - os_log("fetchPolicy: wrong length returned") - reply(nil, ContainerError.policyDocumentDoesNotValidate) - return - } - guard let r = result[policyVersion] else { - os_log("fetchPolicy: version not found") - reply(nil, ContainerError.unknownPolicyVersion(policyVersion.uint64Value)) - return - } - guard let data = r[1].data(using: .utf8) else { - os_log("fetchPolicy: failed to convert data") - reply(nil, ContainerError.unknownPolicyVersion(policyVersion.uint64Value)) - return - } - guard let pd = TPPolicyDocument.policyDoc(withHash: r[0], data: data) else { - os_log("fetchPolicy: pd is nil") - reply(nil, ContainerError.policyDocumentDoesNotValidate) - return + + self.moc.performAndWait { + guard response?.viableBottles != nil else { + os_log("fetchViableBottles returned no viable bottles", log: tplogDebug, type: .default) + reply([], nil) + return + } + + self.handleFetchViableBottlesResponseWithSemaphore(response: response) } + do { - let policy = try pd.policy(withSecrets: stableInfo.policySecrets, decrypter: Decrypter()) - reply(policy, nil) + try self.moc.save() + os_log("fetchViableBottles saved bottles and records", log: tplogDebug, type: .default) + self.containerMO.escrowFetchDate = Date() + + var allEscrowRecordData: [Data] = [] + if let fullyViableRecords = self.containerMO.fullyViableEscrowRecords as? Set { + for record in fullyViableRecords { + if let r = self.escrowRecordMOToEscrowRecords(record: record, viability: .full) { + allEscrowRecordData.append(r.data) + } + } + } + if let partiallyViableRecords = self.containerMO.partiallyViableEscrowRecords as? Set { + for record in partiallyViableRecords { + if let r = self.escrowRecordMOToEscrowRecords(record: record, viability: .partial) { + allEscrowRecordData.append(r.data) + } + } + } + if let legacyRecords = self.containerMO.legacyEscrowRecords as? Set { + for record in legacyRecords { + if let r = self.escrowRecordMOToEscrowRecords(record: record, viability: .none) { + allEscrowRecordData.append(r.data) + } + } + } + reply(allEscrowRecordData, nil) } catch { - os_log("TPPolicyDocument: %@", log: tplogDebug, type: .default, error as CVarArg) + os_log("fetchViableBottles unable to save bottles and records: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, error) } } } } + func fetchCurrentPolicy(modelIDOverride: String?, reply: @escaping (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) -> Void) { + self.semaphore.wait() + let reply: (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) -> Void = { + os_log("fetchCurrentPolicy complete: %{public}@", log: tplogTrace, type: .info, traceError($2)) + self.semaphore.signal() + reply($0, $1, $2) + } + + self.moc.performAndWait { + guard let egoPeerID = self.containerMO.egoPeerID, + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig, + let stableInfoData = self.containerMO.egoPeerStableInfo, + let stableInfoSig = self.containerMO.egoPeerStableInfoSig else { + os_log("fetchCurrentPolicy failed to find ego peer information", log: tplogDebug, type: .error) + // This is technically an error, but we also need to know the prevailing syncing policy at CloudKit signin time, not just after we've started to join + + guard let modelID = modelIDOverride else { + os_log("no model ID override; returning error", log: tplogDebug, type: .default) + reply(nil, .UNKNOWN, ContainerError.noPreparedIdentity) + return + } + + guard let policyDocument = self.model.policy(withVersion: prevailingPolicyVersion.versionNumber) else { + os_log("prevailing policy is missing?", log: tplogDebug, type: .default) + reply(nil, .UNKNOWN, ContainerError.noPreparedIdentity) + return + } + + do { + let prevailingPolicy = try policyDocument.policy(withSecrets: [:], decrypter: Decrypter()) + let syncingPolicy = try prevailingPolicy.syncingPolicy(forModel: modelID, syncUserControllableViews: .UNKNOWN) + + os_log("returning a policy for model ID %{public}@", log: tplogDebug, type: .default, modelID) + reply(syncingPolicy, .UNKNOWN, nil) + return + } catch { + os_log("fetchCurrentPolicy failed to prevailing policy: %{public}@", log: tplogDebug, type: .error) + reply(nil, .UNKNOWN, ContainerError.noPreparedIdentity) + return + } + } + + let keyFactory = TPECPublicKeyFactory() + guard let permanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { + os_log("fetchCurrentPolicy failed to create TPPeerPermanentInfo", log: tplogDebug, type: .error) + reply(nil, .UNKNOWN, ContainerError.invalidPermanentInfoOrSig) + return + } + guard let stableInfo = TPPeerStableInfo(data: stableInfoData, sig: stableInfoSig) else { + os_log("fetchCurrentPolicy failed to create TPPeerStableInfo", log: tplogDebug, type: .error) + reply(nil, .UNKNOWN, ContainerError.invalidStableInfoOrSig) + return + } + + // We should know about all policy versions that peers might use before trying to find the best one + let allPolicyVersions = self.model.allPolicyVersions() + self.fetchPolicyDocumentsWithSemaphore(versions: allPolicyVersions) { _, policyFetchError in + if let error = policyFetchError { + os_log("join: error fetching all requested policies (continuing anyway): %{public}@", log: tplogDebug, type: .default, error as CVarArg) + } + + + do { + let syncingPolicy = try self.syncingPolicyFor(modelID: modelIDOverride ?? permanentInfo.modelID, stableInfo: stableInfo) + + guard let peer = self.model.peer(withID: permanentInfo.peerID), let dynamicInfo = peer.dynamicInfo else { + os_log("fetchCurrentPolicy with no dynamic info", log: tplogDebug, type: .error) + reply(syncingPolicy, .UNKNOWN, nil) + return + } + + // Note: we specifically do not want to sanitize this value for the platform: returning FOLLOWING here isn't that helpful + let peersUserViewSyncability = self.model.userViewSyncabilityConsensusAmongTrustedPeers(dynamicInfo) + reply(syncingPolicy, peersUserViewSyncability, nil) + return + } catch { + os_log("Fetching the syncing policy failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, .UNKNOWN, error) + return + } + } + } + } + + func syncingPolicyFor(modelID: String, stableInfo: TPPeerStableInfo) throws -> TPSyncingPolicy { + let bestPolicyVersion : TPPolicyVersion + + let peerPolicyVersion = stableInfo.bestPolicyVersion() + if peerPolicyVersion.versionNumber < frozenPolicyVersion.versionNumber { + // This peer was from before CKKS4All, and we shouldn't listen to them when it comes to Syncing Policies + bestPolicyVersion = prevailingPolicyVersion + os_log("Ignoring policy version from pre-CKKS4All peer", log: tplogDebug, type: .default) + + } else { + bestPolicyVersion = peerPolicyVersion + } + + guard let policyDocument = self.model.policy(withVersion: bestPolicyVersion.versionNumber) else { + os_log("best policy(%@) is missing?", log: tplogDebug, type: .default, bestPolicyVersion) + throw ContainerError.unknownPolicyVersion(bestPolicyVersion.versionNumber) + } + + let policy = try policyDocument.policy(withSecrets: stableInfo.policySecrets, decrypter: Decrypter()) + return try policy.syncingPolicy(forModel: modelID, syncUserControllableViews: stableInfo.syncUserControllableViews) + } + // All-or-nothing: return an error in case full list cannot be returned. // Completion handler data format: [version : [hash, data]] - func fetchPolicyDocuments(keys: [NSNumber: String], - reply: @escaping ([NSNumber: [String]]?, Error?) -> Void) { + func fetchPolicyDocuments(versions: Set, + reply: @escaping ([TPPolicyVersion: Data]?, Error?) -> Void) { self.semaphore.wait() - let reply: ([NSNumber: [String]]?, Error?) -> Void = { - os_log("fetchPolicyDocuments complete: %@", log: tplogTrace, type: .info, traceError($1)) + let reply: ([TPPolicyVersion: Data]?, Error?) -> Void = { + os_log("fetchPolicyDocuments complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) self.semaphore.signal() reply($0, $1) } - var keys = keys - var docs: [NSNumber: [String]] = [:] + self.fetchPolicyDocumentsWithSemaphore(versions: versions) { policyDocuments, fetchError in + reply(policyDocuments.flatMap { $0.mapValues { policyDoc in policyDoc.protobuf } }, fetchError) + } + } + + func fetchPolicyDocumentWithSemaphore(version: TPPolicyVersion, + reply: @escaping (TPPolicyDocument?, Error?) -> Void) { + self.fetchPolicyDocumentsWithSemaphore(versions: Set([version])) { versions, fetchError in + guard fetchError == nil else { + reply(nil, fetchError) + return + } + + guard let doc = versions?[version] else { + os_log("fetchPolicyDocument: didn't return policy of version: %{public}@", log: tplogDebug, versions ?? "no versions") + reply(nil, ContainerError.unknownPolicyVersion(version.versionNumber)) + return + } + + reply(doc, nil) + } + } + + func fetchPolicyDocumentsWithSemaphore(versions: Set, + reply: @escaping ([TPPolicyVersion: TPPolicyDocument]?, Error?) -> Void) { + var remaining = versions + var docs: [TPPolicyVersion: TPPolicyDocument] = [:] self.moc.performAndWait { - for (version, hash) in keys { - if let policydoc = try? self.getPolicyDoc(version.uint64Value), policydoc.policyHash == hash { - docs[version] = [policydoc.policyHash, policydoc.protobuf.base64EncodedString()] - keys[version] = nil + for version in remaining { + if let policydoc = try? self.getPolicyDoc(version.versionNumber), policydoc.version.policyHash == version.policyHash { + docs[policydoc.version] = policydoc + remaining.remove(version) } } } - if keys.isEmpty { + guard !remaining.isEmpty else { reply(docs, nil) return } let request = FetchPolicyDocumentsRequest.with { - $0.keys = keys.map { key, value in - PolicyDocumentKey.with { $0.version = key.uint64Value; $0.hash = value }} + $0.keys = remaining.map { version in + PolicyDocumentKey.with { $0.version = version.versionNumber; $0.hash = version.policyHash }} } self.cuttlefish.fetchPolicyDocuments(request) { response, error in - os_log("FetchPolicyDocuments(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { - os_log("FetchPolicyDocuments failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + os_log("FetchPolicyDocuments failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, error ?? ContainerError.cloudkitResponseMissing) return } @@ -2636,21 +2915,36 @@ class Container: NSObject { // TODO: validate the policy's signature guard let doc = TPPolicyDocument.policyDoc(withHash: mapEntry.key.hash, data: mapEntry.value) else { - os_log("Can't make policy document with hash %@ and data %@", + os_log("Can't make policy document with hash %{public}@ and data %{public}@", log: tplogDebug, type: .default, mapEntry.key.hash, mapEntry.value.base64EncodedString()) reply(nil, ContainerError.policyDocumentDoesNotValidate) return } - guard let hash = keys[NSNumber(value: doc.policyVersion)], hash == doc.policyHash else { - os_log("Requested hash %@ does not match fetched hash %@", log: tplogDebug, type: .default, - keys[NSNumber(value: doc.policyVersion)] ?? "", doc.policyHash) + guard let expectedVersion = (remaining.first { $0.versionNumber == doc.version.versionNumber }) else { + os_log("Received a policy version we didn't request: %d", log: tplogDebug, type: .default, doc.version.versionNumber) reply(nil, ContainerError.policyDocumentDoesNotValidate) return } - keys[NSNumber(value: doc.policyVersion)] = nil // Server responses should be unique, let's enforce - docs[NSNumber(value: doc.policyVersion)] = [doc.policyHash, doc.protobuf.base64EncodedString()] + + guard expectedVersion.policyHash == doc.version.policyHash else { + os_log("Requested hash %{public}@ does not match fetched hash %{public}@", log: tplogDebug, type: .default, + expectedVersion.policyHash, doc.version.policyHash) + reply(nil, ContainerError.policyDocumentDoesNotValidate) + return + } + + remaining.remove(expectedVersion) // Server responses should be unique, let's enforce + + docs[doc.version] = doc self.model.register(doc) + + let policyMO = PolicyMO(context: self.moc) + policyMO.version = Int64(doc.version.versionNumber) + policyMO.policyHash = doc.version.policyHash + policyMO.policyData = mapEntry.value + + self.containerMO.addToPolicies(policyMO) } do { @@ -2660,13 +2954,14 @@ class Container: NSObject { return } - if !keys.isEmpty { - let (unknownVersion, _) = keys.first! - reply(nil, ContainerError.unknownPolicyVersion(unknownVersion.uint64Value)) + // Determine if there's anything left to fetch + guard let unfetchedVersion = remaining.first else { + // Nothing remaining? Success! + reply(docs, nil) return } - reply(docs, nil) + reply(nil, ContainerError.unknownPolicyVersion(unfetchedVersion.versionNumber)) } } } @@ -2701,20 +2996,23 @@ class Container: NSObject { } vouchers?.forEach { voucher in self.model.register(voucher) - let voucherMO = VoucherMO(context: self.moc) - voucherMO.voucherInfo = voucher.data - voucherMO.voucherInfoSig = voucher.sig - peer.addToVouchers(voucherMO) + + if (peer.vouchers as? Set ?? Set()).filter({ $0.data == voucher.data && $0.sig == voucher.sig }).isEmpty { + let voucherMO = VoucherMO(context: self.moc) + voucherMO.voucherInfo = voucher.data + voucherMO.voucherInfoSig = voucher.sig + peer.addToVouchers(voucherMO) + } } return peer } /* Returns any new CKKS keys that need uploading, as well as any TLKShares necessary for those keys */ func makeSharesForNewKeySets(ckksKeys: [CKKSKeychainBackedKeySet], - tlkShares: [CKKSTLKShare], - egoPeerKeys: OctagonSelfPeerKeys, - egoPeerDynamicInfo: TPPeerDynamicInfo, - epoch: Int) throws -> ([ViewKeys], [TLKShare]) { + tlkShares: [CKKSTLKShare], + egoPeerKeys: OctagonSelfPeerKeys, + egoPeerDynamicInfo: TPPeerDynamicInfo, + epoch: Int) throws -> ([ViewKeys], [TLKShare]) { let newCKKSKeys = ckksKeys.filter { $0.newUpload } let newViewKeys: [ViewKeys] = newCKKSKeys.map(ViewKeys.convert) @@ -2730,7 +3028,7 @@ class Container: NSObject { do { let peerIDsWithAccess = try self.model.getPeerIDsTrustedByPeer(with: egoPeerDynamicInfo, toAccessView: keyset.tlk.zoneID.zoneName) - os_log("Planning to share %@ with peers %@", log: tplogDebug, type: .default, String(describing: keyset.tlk), peerIDsWithAccess) + os_log("Planning to share %@ with peers %{public}@", log: tplogDebug, type: .default, String(describing: keyset.tlk), peerIDsWithAccess) let peers = peerIDsWithAccess.compactMap { self.model.peer(withID: $0) } let viewPeerShares = try peers.map { receivingPeer in @@ -2741,10 +3039,9 @@ class Container: NSObject { poisoned: 0)) } - peerShares = peerShares + viewPeerShares - + peerShares += viewPeerShares } catch { - os_log("Unable to create TLKShares for keyset %@: %@", log: tplogDebug, type: .default, String(describing: keyset), error as CVarArg) + os_log("Unable to create TLKShares for keyset %@: %{public}@", log: tplogDebug, type: .default, String(describing: keyset), error as CVarArg) } } @@ -2766,8 +3063,31 @@ class Container: NSObject { signing: egoPeerKeys.signingKey, currentMachineIDs: self.onqueueCurrentMIDList()) - let newStableInfo = try self.createNewStableInfoIfNeeded(stableChanges: nil, - egoPeerID: egoPeerID, + let userViewSyncability: TPPBPeerStableInfo_UserControllableViewStatus? + if [.ENABLED, .DISABLED].contains(stableInfo.syncUserControllableViews) { + // No change! + userViewSyncability = nil + } else { + let newUserViewSyncability: TPPBPeerStableInfo_UserControllableViewStatus + + if peerPermanentInfo.modelID.hasPrefix("AppleTV") || + peerPermanentInfo.modelID.hasPrefix("AudioAccessory") || + peerPermanentInfo.modelID.hasPrefix("Watch") { + // Watches, TVs, and AudioAccessories always join as FOLLOWING. + newUserViewSyncability = .FOLLOWING + } else { + // All other platforms select what the other devices say to do + newUserViewSyncability = self.model.userViewSyncabilityConsensusAmongTrustedPeers(dynamicInfo) + } + + os_log("join: setting 'user view sync' control as: %{public}@", log: tplogDebug, type: .default, + TPPBPeerStableInfo_UserControllableViewStatusAsString(newUserViewSyncability)) + userViewSyncability = newUserViewSyncability + } + + let newStableInfo = try self.createNewStableInfoIfNeeded(stableChanges: StableChanges.change(viewStatus: userViewSyncability), + permanentInfo: peerPermanentInfo, + existingStableInfo: stableInfo, dynamicInfo: dynamicInfo, signingKeyPair: egoPeerKeys.signingKey) @@ -2787,26 +3107,388 @@ class Container: NSObject { ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord], Error?) -> Void) { + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (String?, [CKRecord], Error?) -> Void = { - os_log("join complete: %@", log: tplogTrace, type: .info, traceError($2)) + let reply: (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void = { + os_log("join complete: %{public}@", log: tplogTrace, type: .info, traceError($3)) self.semaphore.signal() - reply($0, $1, $2) + reply($0, $1, $2, $3) } self.fetchAndPersistChanges { error in guard error == nil else { - reply(nil, [], error) + reply(nil, [], nil, error) + return + } + + // To join, you must know all policies that exist + let allPolicyVersions = self.model.allPolicyVersions() + self.fetchPolicyDocumentsWithSemaphore(versions: allPolicyVersions) { _, policyFetchError in + if let error = policyFetchError { + os_log("join: error fetching all requested policies (continuing anyway): %{public}@", log: tplogDebug, type: .default, error as CVarArg) + } + + self.moc.performAndWait { + guard let voucher = TPVoucher(infoWith: voucherData, sig: voucherSig) else { + reply(nil, [], nil, ContainerError.invalidVoucherOrSig) + return + } + guard let sponsor = self.model.peer(withID: voucher.sponsorID) else { + reply(nil, [], nil, ContainerError.sponsorNotRegistered(voucher.sponsorID)) + return + } + + // Fetch ego peer identity from local storage. + guard let egoPeerID = self.containerMO.egoPeerID, + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig, + let egoStableData = self.containerMO.egoPeerStableInfo, + let egoStableSig = self.containerMO.egoPeerStableInfoSig + else { + reply(nil, [], nil, ContainerError.noPreparedIdentity) + return + } + + let keyFactory = TPECPublicKeyFactory() + guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { + reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig) + return + } + guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) + return + } + guard self.onqueueMachineIDAllowedByIDMS(machineID: selfPermanentInfo.machineID) else { + os_log("join: self machineID %{public}@ not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID) + self.onqueueTTRUntrusted() + reply(nil, [], nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) + return + } + + loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in + guard let egoPeerKeys = egoPeerKeys else { + os_log("Don't have my own peer keys; can't join: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + reply(nil, [], nil, error) + return + } + self.moc.performAndWait { + let peer: Peer + let newDynamicInfo: TPPeerDynamicInfo + do { + (peer, newDynamicInfo) = try self.onqueuePreparePeerForJoining(egoPeerID: egoPeerID, + peerPermanentInfo: selfPermanentInfo, + stableInfo: selfStableInfo, + sponsorID: sponsor.peerID, + preapprovedKeys: preapprovedKeys, + vouchers: [SignedVoucher.with { + $0.voucher = voucher.data + $0.sig = voucher.sig + }, ], + egoPeerKeys: egoPeerKeys) + } catch { + os_log("Unable to create peer for joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, [], nil, error) + return + } + + guard let peerStableInfo = peer.stableInfoAndSig.toStableInfo() else { + os_log("Unable to create new peer stable info for joining", log: tplogDebug, type: .default) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) + return + } + + let allTLKShares: [TLKShare] + let viewKeys: [ViewKeys] + do { + (viewKeys, allTLKShares) = try self.makeSharesForNewKeySets(ckksKeys: ckksKeys, + tlkShares: tlkShares, + egoPeerKeys: egoPeerKeys, + egoPeerDynamicInfo: newDynamicInfo, + epoch: Int(selfPermanentInfo.epoch)) + } catch { + os_log("Unable to process keys before joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, [], nil, error) + return + } + + do { + try self.model.checkIntroduction(forCandidate: selfPermanentInfo, + stableInfo: peer.stableInfoAndSig.toStableInfo(), + withSponsorID: sponsor.peerID) + } catch { + os_log("Error checking introduction: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, [], nil, error) + return + } + + var bottle: Bottle + do { + bottle = try self.assembleBottle(egoPeerID: egoPeerID) + } catch { + reply(nil, [], nil, error) + return + } + + os_log("Beginning join for peer %{public}@", log: tplogDebug, type: .default, egoPeerID) + os_log("Join permanentInfo: %{public}@", log: tplogDebug, type: .debug, egoPermData.base64EncodedString()) + os_log("Join permanentInfoSig: %{public}@", log: tplogDebug, type: .debug, egoPermSig.base64EncodedString()) + os_log("Join stableInfo: %{public}@", log: tplogDebug, type: .debug, peer.stableInfoAndSig.peerStableInfo.base64EncodedString()) + os_log("Join stableInfoSig: %{public}@", log: tplogDebug, type: .debug, peer.stableInfoAndSig.sig.base64EncodedString()) + os_log("Join dynamicInfo: %{public}@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.peerDynamicInfo.base64EncodedString()) + os_log("Join dynamicInfoSig: %{public}@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.sig.base64EncodedString()) + + os_log("Join vouchers: %{public}@", log: tplogDebug, type: .debug, peer.vouchers.map { $0.voucher.base64EncodedString() }) + os_log("Join voucher signatures: %{public}@", log: tplogDebug, type: .debug, peer.vouchers.map { $0.sig.base64EncodedString() }) + + os_log("Uploading %d tlk shares", log: tplogDebug, type: .default, allTLKShares.count) + + do { + os_log("Join peer: %{public}@", log: tplogDebug, type: .debug, try peer.serializedData().base64EncodedString()) + } catch { + os_log("Join unable to encode peer: %{public}@", log: tplogDebug, type: .debug, error as CVarArg) + } + + let changeToken = self.containerMO.changeToken ?? "" + let request = JoinWithVoucherRequest.with { + $0.changeToken = changeToken + $0.peer = peer + $0.bottle = bottle + $0.tlkShares = allTLKShares + $0.viewKeys = viewKeys + } + self.cuttlefish.joinWithVoucher(request) { response, error in + guard let response = response, error == nil else { + os_log("joinWithVoucher failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, [], nil, error ?? ContainerError.cloudkitResponseMissing) + return + } + + self.moc.performAndWait { + do { + self.containerMO.egoPeerStableInfo = peer.stableInfoAndSig.peerStableInfo + self.containerMO.egoPeerStableInfoSig = peer.stableInfoAndSig.sig + + let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID, + stableInfo: peerStableInfo) + + try self.onQueuePersist(changes: response.changes) + os_log("JoinWithVoucher succeeded", log: tplogDebug) + + let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } + reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil) + } catch { + os_log("JoinWithVoucher failed: %{public}@", log: tplogDebug, String(describing: error)) + reply(nil, [], nil, error) + } + } + } + } + } + } + } + } + } + + func requestHealthCheck(requiresEscrowCheck: Bool, reply: @escaping (Bool, Bool, Bool, Bool, Error?) -> Void) { + self.semaphore.wait() + let reply: (Bool, Bool, Bool, Bool, Error?) -> Void = { + os_log("health check complete: %{public}@", log: tplogTrace, type: .info, traceError($4)) + self.semaphore.signal() + reply($0, $1, $2, $3, $4) + } + + os_log("requestHealthCheck requiring escrow check: %d", log: tplogDebug, type: .default, requiresEscrowCheck) + + self.moc.performAndWait { + guard let egoPeerID = self.containerMO.egoPeerID else { + // No identity, nothing to do + os_log("requestHealthCheck: No identity.", log: tplogDebug, type: .default) + reply(false, false, false, false, ContainerError.noPreparedIdentity) + return + } + let request = GetRepairActionRequest.with { + $0.peerID = egoPeerID + $0.requiresEscrowCheck = requiresEscrowCheck + } + + self.cuttlefish.getRepairAction(request) { response, error in + guard error == nil else { + reply(false, false, false, false, error) + return + } + guard let action = response?.repairAction else { + os_log("repair response is empty, returning false", log: tplogDebug, type: .default) + reply(false, false, false, false, nil) + return + } + var postRepairAccount: Bool = false + var postRepairEscrow: Bool = false + var resetOctagon: Bool = false + var leaveTrust: Bool = false + + switch action { + case .noAction: + break + case .postRepairAccount: + postRepairAccount = true + case .postRepairEscrow: + postRepairEscrow = true + case .resetOctagon: + resetOctagon = true + case .leaveTrust: + leaveTrust = true + case .UNRECOGNIZED: + break + } + reply(postRepairAccount, postRepairEscrow, resetOctagon, leaveTrust, nil) + } + } + } + + func getSupportAppInfo(reply: @escaping (Data?, Error?) -> Void) { + self.semaphore.wait() + let reply: (Data?, Error?) -> Void = { + os_log("getSupportAppInfo complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) + self.semaphore.signal() + reply($0, $1) + } + + self.cuttlefish.getSupportAppInfo { response, error in + guard let response = response, error == nil else { + os_log("getSupportAppInfo failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, error ?? ContainerError.cloudkitResponseMissing) + return + } + + guard let data = try? response.serializedData() else { + reply(nil, ContainerError.failedToSerializeData) + return + } + + reply(data, nil) + } + } + + func resetCDPAccountData(reply: @escaping (Error?) -> Void) { + self.semaphore.wait() + let reply: (Error?) -> Void = { + os_log("resetCDPAccountData complete: %{public}@", log: tplogTrace, type: .info, traceError($0)) + self.semaphore.signal() + reply($0) + } + + let request = ResetAccountCDPContentsRequest.with { + $0.resetReason = .testGenerated + } + self.cuttlefish.resetAccountCdpcontents(request){ response, error in + guard let _ = response, error == nil else { + os_log("resetCDPAccountData failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(error ?? ContainerError.cloudkitResponseMissing) return } self.moc.performAndWait { - guard let voucher = TPVoucher(infoWith: voucherData, sig: voucherSig) else { - reply(nil, [], ContainerError.invalidVoucherOrSig) + self.onQueueRemoveEscrowCache() + } + reply(nil) + } + } + + func preflightPreapprovedJoin(preapprovedKeys: [Data]?, + reply: @escaping (Bool, Error?) -> Void) { + self.semaphore.wait() + let reply: (Bool, Error?) -> Void = { + os_log("preflightPreapprovedJoin complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) + self.semaphore.signal() + reply($0, $1) + } + + self.fetchAndPersistChanges { error in + guard error == nil else { + os_log("preflightPreapprovedJoin unable to fetch changes: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") + reply(false, error) + return + } + + // We need to try to have all policy versions that our peers claim to behave + let allPolicyVersions = self.model.allPolicyVersions() + self.fetchPolicyDocumentsWithSemaphore(versions: allPolicyVersions) { _, policyFetchError in + if let error = policyFetchError { + os_log("preflightPreapprovedJoin: error fetching all requested policies (continuing anyway): %{public}@", log: tplogDebug, type: .default, error as CVarArg) + } + + // We explicitly ignore the machine ID list here; we're only interested in the peer states: do they preapprove us? + + guard !self.model.allPeerIDs().isEmpty else { + // If, after fetch and handle changes, there's no peers, then we can likely establish. + reply(true, nil) return } - guard let sponsor = self.model.peer(withID: voucher.sponsorID) else { - reply(nil, [], ContainerError.sponsorNotRegistered(voucher.sponsorID)) + + guard let egoPeerID = self.containerMO.egoPeerID, + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig + else { + os_log("preflightPreapprovedJoin: no prepared identity", log: tplogDebug, type: .debug) + reply(false, ContainerError.noPreparedIdentity) + return + } + + let keyFactory = TPECPublicKeyFactory() + guard let egoPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { + os_log("preflightPreapprovedJoin: invalid permanent info", log: tplogDebug, type: .debug) + reply(false, ContainerError.invalidPermanentInfoOrSig) + return + } + + guard self.model.hasPotentiallyTrustedPeerPreapprovingKey(egoPermanentInfo.signingPubKey.spki()) else { + os_log("preflightPreapprovedJoin: no peers preapprove our key", log: tplogDebug, type: .debug) + reply(false, ContainerError.noPeersPreapprovePreparedIdentity) + return + } + + let keysApprovingPeers = preapprovedKeys?.filter { key in + self.model.hasPotentiallyTrustedPeer(withSigningKey: key) + } + + guard (keysApprovingPeers?.count ?? 0) > 0 else { + os_log("preflightPreapprovedJoin: no reciprocal trust for existing peers", log: tplogDebug, type: .debug) + reply(false, ContainerError.noPeersPreapprovedBySelf) + return + } + + reply(true, nil) + } + } + } + + func preapprovedJoin(ckksKeys: [CKKSKeychainBackedKeySet], + tlkShares: [CKKSTLKShare], + preapprovedKeys: [Data]?, + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { + self.semaphore.wait() + let reply: (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void = { + os_log("preapprovedJoin complete: %{public}@", log: tplogTrace, type: .info, traceError($3)) + self.semaphore.signal() + reply($0, $1, $2, $3) + } + + self.fetchAndPersistChangesIfNeeded { error in + guard error == nil else { + os_log("preapprovedJoin unable to fetch changes: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") + reply(nil, [], nil, error) + return + } + self.moc.performAndWait { + // If, after fetch and handle changes, there's no peers, then fire off an establish + // Note that if the establish fails, retrying this call might work. + // That's up to the caller. + if self.model.allPeerIDs().isEmpty { + os_log("preapprovedJoin but no existing peers, attempting establish", log: tplogDebug, type: .debug) + + self.onqueueEstablish(ckksKeys: ckksKeys, + tlkShares: tlkShares, + preapprovedKeys: preapprovedKeys, + reply: reply) return } @@ -2817,32 +3499,40 @@ class Container: NSObject { let egoStableData = self.containerMO.egoPeerStableInfo, let egoStableSig = self.containerMO.egoPeerStableInfoSig else { - reply(nil, [], ContainerError.noPreparedIdentity) + os_log("preapprovedJoin: no prepared identity", log: tplogDebug, type: .debug) + reply(nil, [], nil, ContainerError.noPreparedIdentity) return } let keyFactory = TPECPublicKeyFactory() guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - reply(nil, [], ContainerError.invalidPermanentInfoOrSig) + reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig) return } guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { - reply(nil, [], ContainerError.invalidStableInfoOrSig) - return - } - guard self.onqueueMachineIDAllowedByIDMS(machineID: selfPermanentInfo.machineID) else { - os_log("join: self machineID %@ not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID) - self.onqueueTTRUntrusted() - reply(nil, [], ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) return } + guard self.onqueueMachineIDAllowedByIDMS(machineID: selfPermanentInfo.machineID) else { + os_log("preapprovedJoin: self machineID %{public}@ (me) not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID) + self.onqueueTTRUntrusted() + reply(nil, [], nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) + return + } loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in guard let egoPeerKeys = egoPeerKeys else { - os_log("Don't have my own peer keys; can't join: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, [], error) + os_log("preapprovedJoin: Don't have my own keys: can't join", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, [], nil, error) return } + + guard self.model.hasPotentiallyTrustedPeerPreapprovingKey(egoPeerKeys.signingKey.publicKey().spki()) else { + os_log("preapprovedJoin: no peers preapprove our key", log: tplogDebug, type: .debug) + reply(nil, [], nil, ContainerError.noPeersPreapprovePreparedIdentity) + return + } + self.moc.performAndWait { let peer: Peer let newDynamicInfo: TPPeerDynamicInfo @@ -2850,16 +3540,19 @@ class Container: NSObject { (peer, newDynamicInfo) = try self.onqueuePreparePeerForJoining(egoPeerID: egoPeerID, peerPermanentInfo: selfPermanentInfo, stableInfo: selfStableInfo, - sponsorID: sponsor.peerID, + sponsorID: nil, preapprovedKeys: preapprovedKeys, - vouchers: [SignedVoucher.with { - $0.voucher = voucher.data - $0.sig = voucher.sig - }, ], + vouchers: [], egoPeerKeys: egoPeerKeys) } catch { - os_log("Unable to create peer for joining: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], error) + os_log("Unable to create peer for joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, [], nil, error) + return + } + + guard let peerStableInfo = peer.stableInfoAndSig.toStableInfo() else { + os_log("Unable to create new peer stable info for joining", log: tplogDebug, type: .default) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) return } @@ -2872,18 +3565,8 @@ class Container: NSObject { egoPeerDynamicInfo: newDynamicInfo, epoch: Int(selfPermanentInfo.epoch)) } catch { - os_log("Unable to process keys before joining: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], error) - return - } - - do { - try self.model.checkIntroduction(forCandidate: selfPermanentInfo, - stableInfo: peer.stableInfoAndSig.toStableInfo(), - withSponsorID: sponsor.peerID) - } catch { - os_log("Error checking introduction: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], error) + os_log("Unable to process keys before joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, [], nil, error) return } @@ -2891,326 +3574,27 @@ class Container: NSObject { do { bottle = try self.assembleBottle(egoPeerID: egoPeerID) } catch { - reply(nil, [], error) + reply(nil, [], nil, error) return } - os_log("Beginning join for peer %@", log: tplogDebug, type: .default, egoPeerID) - os_log("Join permanentInfo: %@", log: tplogDebug, type: .debug, egoPermData.base64EncodedString()) - os_log("Join permanentInfoSig: %@", log: tplogDebug, type: .debug, egoPermSig.base64EncodedString()) - os_log("Join stableInfo: %@", log: tplogDebug, type: .debug, peer.stableInfoAndSig.peerStableInfo.base64EncodedString()) - os_log("Join stableInfoSig: %@", log: tplogDebug, type: .debug, peer.stableInfoAndSig.sig.base64EncodedString()) - os_log("Join dynamicInfo: %@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.peerDynamicInfo.base64EncodedString()) - os_log("Join dynamicInfoSig: %@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.sig.base64EncodedString()) + os_log("Beginning preapprovedJoin for peer %{public}@", log: tplogDebug, type: .default, egoPeerID) + os_log("preapprovedJoin permanentInfo: %{public}@", log: tplogDebug, type: .debug, egoPermData.base64EncodedString()) + os_log("preapprovedJoin permanentInfoSig: %{public}@", log: tplogDebug, type: .debug, egoPermSig.base64EncodedString()) + os_log("preapprovedJoin stableInfo: %{public}@", log: tplogDebug, type: .debug, egoStableData.base64EncodedString()) + os_log("preapprovedJoin stableInfoSig: %{public}@", log: tplogDebug, type: .debug, egoStableSig.base64EncodedString()) + os_log("preapprovedJoin dynamicInfo: %{public}@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.peerDynamicInfo.base64EncodedString()) + os_log("preapprovedJoin dynamicInfoSig: %{public}@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.sig.base64EncodedString()) - os_log("Join vouchers: %@", log: tplogDebug, type: .debug, peer.vouchers.map { $0.voucher.base64EncodedString() }) - os_log("Join voucher signatures: %@", log: tplogDebug, type: .debug, peer.vouchers.map { $0.sig.base64EncodedString() }) - - os_log("Uploading %d tlk shares", log: tplogDebug, type: .default, allTLKShares.count) - - do { - os_log("Join peer: %@", log: tplogDebug, type: .debug, try peer.serializedData().base64EncodedString()) - } catch { - os_log("Join unable to encode peer: %@", log: tplogDebug, type: .debug, error as CVarArg) - } - - let changeToken = self.containerMO.changeToken ?? "" - let request = JoinWithVoucherRequest.with { - $0.changeToken = changeToken - $0.peer = peer - $0.bottle = bottle - $0.tlkShares = allTLKShares - $0.viewKeys = viewKeys - } - self.cuttlefish.joinWithVoucher(request) { response, error in - os_log("JoinWithVoucher(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") - guard let response = response, error == nil else { - os_log("joinWithVoucher failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, [], error ?? ContainerError.cloudkitResponseMissing) - return - } - - self.moc.performAndWait { - do { - self.containerMO.egoPeerStableInfo = peer.stableInfoAndSig.peerStableInfo - self.containerMO.egoPeerStableInfoSig = peer.stableInfoAndSig.sig - try self.onQueuePersist(changes: response.changes) - os_log("JoinWithVoucher succeeded", log: tplogDebug) - - let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } - reply(egoPeerID, keyHierarchyRecords, nil) - } catch { - os_log("JoinWithVoucher failed: %@", log: tplogDebug, String(describing: error)) - reply(nil, [], error) - } - } - } - } - } - } - } - } - - func requestHealthCheck(requiresEscrowCheck: Bool, reply: @escaping (Bool, Bool, Bool, Error?) -> Void) { - self.semaphore.wait() - let reply: (Bool, Bool, Bool, Error?) -> Void = { - os_log("health check complete: %@", log: tplogTrace, type: .info, traceError($3)) - self.semaphore.signal() - reply($0, $1, $2, $3) - } - - os_log("requestHealthCheck requiring escrow check: %d", log: tplogDebug, type: .default, requiresEscrowCheck) - - self.moc.performAndWait { - guard let egoPeerID = self.containerMO.egoPeerID else { - // No identity, nothing to do - os_log("requestHealthCheck: No identity.", log: tplogDebug, type: .default) - reply(false, false, false, ContainerError.noPreparedIdentity) - return - } - let request = GetRepairActionRequest.with { - $0.peerID = egoPeerID - $0.requiresEscrowCheck = requiresEscrowCheck - } - - self.cuttlefish.getRepairAction(request) { response, error in - guard error == nil else { - reply(false, false, false, error) - return - } - guard let action = response?.repairAction else { - os_log("repair response is empty, returning false: %@", log: tplogDebug, type: .default) - reply(false, false, false, nil) - return - } - var postRepairAccount: Bool = false - var postRepairEscrow: Bool = false - var resetOctagon: Bool = false - - switch action { - case .noAction: - break - case .postRepairAccount: - postRepairAccount = true - break - case .postRepairEscrow: - postRepairEscrow = true - break - case .resetOctagon: - resetOctagon = true - break - case .UNRECOGNIZED: - break - } - reply(postRepairAccount, postRepairEscrow, resetOctagon, nil) - } - } - } - - func getSupportAppInfo(reply: @escaping (Data?, Error?) -> Void) { - self.semaphore.wait() - let reply: (Data?, Error?) -> Void = { - os_log("getSupportAppInfo complete: %@", log: tplogTrace, type: .info, traceError($1)) - self.semaphore.signal() - reply($0, $1) - } - - self.cuttlefish.getSupportAppInfo { response, error in - os_log("getSupportAppInfo(): %@, error: %@", log: tplogDebug, - "(\(String(describing: response))", "\(String(describing: error))") - guard let response = response, error == nil else { - os_log("getSupportAppInfo failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, error ?? ContainerError.cloudkitResponseMissing) - return - } - - guard let data = try? response.serializedData() else { - reply(nil, ContainerError.failedToSerializeData) - return - } - - reply(data, nil) - } - - } - - func preflightPreapprovedJoin(reply: @escaping (Bool, Error?) -> Void) { - self.semaphore.wait() - let reply: (Bool, Error?) -> Void = { - os_log("preflightPreapprovedJoin complete: %@", log: tplogTrace, type: .info, traceError($1)) - self.semaphore.signal() - reply($0, $1) - } - - self.fetchAndPersistChanges { error in - guard error == nil else { - os_log("preflightPreapprovedJoin unable to fetch changes: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(false, error) - return - } - - // We explicitly ignore the machine ID list here; we're only interested in the peer states: do they preapprove us? - - guard !self.model.allPeerIDs().isEmpty else { - // If, after fetch and handle changes, there's no peers, then we can likely establish. - reply(true, nil) - return - } - - guard let egoPeerID = self.containerMO.egoPeerID, - let egoPermData = self.containerMO.egoPeerPermanentInfo, - let egoPermSig = self.containerMO.egoPeerPermanentInfoSig - else { - os_log("preflightPreapprovedJoin: no prepared identity", log: tplogDebug, type: .debug) - reply(false, ContainerError.noPreparedIdentity) - return - } - - let keyFactory = TPECPublicKeyFactory() - guard let egoPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - os_log("preflightPreapprovedJoin: invalid permanent info", log: tplogDebug, type: .debug) - reply(false, ContainerError.invalidPermanentInfoOrSig) - return - } - - guard self.model.hasPotentiallyTrustedPeerPreapprovingKey(egoPermanentInfo.signingPubKey.spki()) else { - os_log("preflightPreapprovedJoin: no peers preapprove our key", log: tplogDebug, type: .debug) - reply(false, ContainerError.noPeersPreapprovePreparedIdentity) - return - } - - reply(true, nil) - } - } - - func preapprovedJoin(ckksKeys: [CKKSKeychainBackedKeySet], - tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord], Error?) -> Void) { - self.semaphore.wait() - let reply: (String?, [CKRecord], Error?) -> Void = { - os_log("preapprovedJoin complete: %@", log: tplogTrace, type: .info, traceError($2)) - self.semaphore.signal() - reply($0, $1, $2) - } - - self.fetchAndPersistChangesIfNeeded { error in - guard error == nil else { - os_log("preapprovedJoin unable to fetch changes: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, [], error) - return - } - self.moc.performAndWait { - // If, after fetch and handle changes, there's no peers, then fire off an establish - // Note that if the establish fails, retrying this call might work. - // That's up to the caller. - if self.model.allPeerIDs().isEmpty { - os_log("preapprovedJoin but no existing peers, attempting establish", log: tplogDebug, type: .debug) - self.onqueueEstablish(ckksKeys: ckksKeys, - tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys, - reply: reply) - return - } - - // Fetch ego peer identity from local storage. - guard let egoPeerID = self.containerMO.egoPeerID, - let egoPermData = self.containerMO.egoPeerPermanentInfo, - let egoPermSig = self.containerMO.egoPeerPermanentInfoSig, - let egoStableData = self.containerMO.egoPeerStableInfo, - let egoStableSig = self.containerMO.egoPeerStableInfoSig - else { - os_log("preapprovedJoin: no prepared identity", log: tplogDebug, type: .debug) - reply(nil, [], ContainerError.noPreparedIdentity) - return - } - - let keyFactory = TPECPublicKeyFactory() - guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - reply(nil, [], ContainerError.invalidPermanentInfoOrSig) - return - } - guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { - reply(nil, [], ContainerError.invalidStableInfoOrSig) - return - } - - guard self.onqueueMachineIDAllowedByIDMS(machineID: selfPermanentInfo.machineID) else { - os_log("preapprovedJoin: self machineID %@ (me) not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID) - self.onqueueTTRUntrusted() - reply(nil, [], ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) - return - } - loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in - guard let egoPeerKeys = egoPeerKeys else { - os_log("preapprovedJoin: Don't have my own keys: can't join", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, [], error) - return - } - - guard self.model.hasPotentiallyTrustedPeerPreapprovingKey(egoPeerKeys.signingKey.publicKey().spki()) else { - os_log("preapprovedJoin: no peers preapprove our key", log: tplogDebug, type: .debug) - reply(nil, [], ContainerError.noPeersPreapprovePreparedIdentity) - return - } - - self.moc.performAndWait { - - let peer: Peer - let newDynamicInfo: TPPeerDynamicInfo - do { - (peer, newDynamicInfo) = try self.onqueuePreparePeerForJoining(egoPeerID: egoPeerID, - peerPermanentInfo: selfPermanentInfo, - stableInfo: selfStableInfo, - sponsorID: nil, - preapprovedKeys: preapprovedKeys, - vouchers: [], - egoPeerKeys: egoPeerKeys) - } catch { - os_log("Unable to create peer for joining: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], error) - return - } - - let allTLKShares: [TLKShare] - let viewKeys: [ViewKeys] - do { - (viewKeys, allTLKShares) = try self.makeSharesForNewKeySets(ckksKeys: ckksKeys, - tlkShares: tlkShares, - egoPeerKeys: egoPeerKeys, - egoPeerDynamicInfo: newDynamicInfo, - epoch: Int(selfPermanentInfo.epoch)) - } catch { - os_log("Unable to process keys before joining: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], error) - return - } - - var bottle: Bottle - do { - bottle = try self.assembleBottle(egoPeerID: egoPeerID) - } catch { - reply(nil, [], error) - return - } - - os_log("Beginning preapprovedJoin for peer %@", log: tplogDebug, type: .default, egoPeerID) - os_log("preapprovedJoin permanentInfo: %@", log: tplogDebug, type: .debug, egoPermData.base64EncodedString()) - os_log("preapprovedJoin permanentInfoSig: %@", log: tplogDebug, type: .debug, egoPermSig.base64EncodedString()) - os_log("preapprovedJoin stableInfo: %@", log: tplogDebug, type: .debug, egoStableData.base64EncodedString()) - os_log("preapprovedJoin stableInfoSig: %@", log: tplogDebug, type: .debug, egoStableSig.base64EncodedString()) - os_log("preapprovedJoin dynamicInfo: %@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.peerDynamicInfo.base64EncodedString()) - os_log("preapprovedJoin dynamicInfoSig: %@", log: tplogDebug, type: .debug, peer.dynamicInfoAndSig.sig.base64EncodedString()) - - os_log("preapprovedJoin vouchers: %@", log: tplogDebug, type: .debug, peer.vouchers.map { $0.voucher.base64EncodedString() }) - os_log("preapprovedJoin voucher signatures: %@", log: tplogDebug, type: .debug, peer.vouchers.map { $0.sig.base64EncodedString() }) + os_log("preapprovedJoin vouchers: %{public}@", log: tplogDebug, type: .debug, peer.vouchers.map { $0.voucher.base64EncodedString() }) + os_log("preapprovedJoin voucher signatures: %{public}@", log: tplogDebug, type: .debug, peer.vouchers.map { $0.sig.base64EncodedString() }) os_log("preapprovedJoin: uploading %d tlk shares", log: tplogDebug, type: .default, allTLKShares.count) do { - os_log("preapprovedJoin peer: %@", log: tplogDebug, type: .debug, try peer.serializedData().base64EncodedString()) + os_log("preapprovedJoin peer: %{public}@", log: tplogDebug, type: .debug, try peer.serializedData().base64EncodedString()) } catch { - os_log("preapprovedJoin unable to encode peer: %@", log: tplogDebug, type: .debug, error as CVarArg) + os_log("preapprovedJoin unable to encode peer: %{public}@", log: tplogDebug, type: .debug, error as CVarArg) } let changeToken = self.containerMO.changeToken ?? "" @@ -3222,10 +3606,9 @@ class Container: NSObject { $0.viewKeys = viewKeys } self.cuttlefish.joinWithVoucher(request) { response, error in - os_log("preapprovedJoin(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { - os_log("preapprovedJoin failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, [], error ?? ContainerError.cloudkitResponseMissing) + os_log("preapprovedJoin failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, [], nil, error ?? ContainerError.cloudkitResponseMissing) return } @@ -3233,14 +3616,18 @@ class Container: NSObject { do { self.containerMO.egoPeerStableInfo = peer.stableInfoAndSig.peerStableInfo self.containerMO.egoPeerStableInfoSig = peer.stableInfoAndSig.sig + + let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID, + stableInfo: peerStableInfo) + try self.onQueuePersist(changes: response.changes) os_log("preapprovedJoin succeeded", log: tplogDebug) let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } - reply(egoPeerID, keyHierarchyRecords, nil) + reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil) } catch { - os_log("preapprovedJoin failed: %@", log: tplogDebug, String(describing: error)) - reply(nil, [], error) + os_log("preapprovedJoin failed: %{public}@", log: tplogDebug, String(describing: error)) + reply(nil, [], nil, error) } } } @@ -3255,12 +3642,13 @@ class Container: NSObject { osVersion: String?, policyVersion: UInt64?, policySecrets: [String: Data]?, - reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus?, + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (TrustedPeersHelperPeerState?, Error?) -> Void = { - os_log("update complete: %@", log: tplogTrace, type: .info, traceError($1)) + let reply: (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void = { + os_log("update complete: %{public}@", log: tplogTrace, type: .info, traceError($2)) self.semaphore.signal() - reply($0, $1) + reply($0, $1, $2) } // Get (and save) the latest from cuttlefish @@ -3269,18 +3657,17 @@ class Container: NSObject { osVersion: osVersion, policyVersion: policyVersion, policySecrets: policySecrets, - recoverySigningPubKey: nil, - recoveryEncryptionPubKey: nil) + setSyncUserControllableViews: syncUserControllableViews) self.fetchChangesAndUpdateTrustIfNeeded(stableChanges: stableChanges, reply: reply) } func set(preapprovedKeys: [Data], - reply: @escaping (Error?) -> Void) { + reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { self.semaphore.wait() - let reply: (Error?) -> Void = { - os_log("setPreapprovedKeys complete: %@", log: tplogTrace, type: .info, traceError($0)) + let reply: (TrustedPeersHelperPeerState?, Error?) -> Void = { + os_log("setPreapprovedKeys complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) self.semaphore.signal() - reply($0) + reply($0, $1) } self.moc.performAndWait { @@ -3289,13 +3676,13 @@ class Container: NSObject { guard let egoPeerID = self.containerMO.egoPeerID else { // No identity, nothing to do os_log("setPreapprovedKeys: No identity.", log: tplogDebug, type: .default) - reply(ContainerError.noPreparedIdentity) + reply(nil, ContainerError.noPreparedIdentity) return } loadEgoKeyPair(identifier: signingKeyIdentifier(peerID: egoPeerID)) { signingKeyPair, error in guard let signingKeyPair = signingKeyPair else { - os_log("setPreapprovedKeys: no signing key pair: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(error ?? ContainerError.unableToCreateKeyPair) + os_log("setPreapprovedKeys: no signing key pair: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, error ?? ContainerError.unableToCreateKeyPair) return } @@ -3309,44 +3696,39 @@ class Container: NSObject { signing: signingKeyPair, currentMachineIDs: self.onqueueCurrentMIDList()) } catch { - os_log("setPreapprovedKeys: couldn't calculate dynamic info: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(error) + os_log("setPreapprovedKeys: couldn't calculate dynamic info: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, error) return } - os_log("setPreapprovedKeys: produced a dynamicInfo: %@", log: tplogDebug, type: .default, dynamicInfo) + os_log("setPreapprovedKeys: produced a dynamicInfo: %{public}@", log: tplogDebug, type: .default, dynamicInfo) if dynamicInfo == self.model.peer(withID: egoPeerID)?.dynamicInfo { os_log("setPreapprovedKeys: no change; nothing to do.", log: tplogDebug, type: .default) - reply(nil) + + // Calling this will fill in the peer status + self.updateTrustIfNeeded { status, _, error in + reply(status, error) + } return } - os_log("setPreapprovedKeys: attempting updateTrust for %@ with: %@", log: tplogDebug, type: .default, egoPeerID, dynamicInfo) + os_log("setPreapprovedKeys: attempting updateTrust for %{public}@ with: %{public}@", log: tplogDebug, type: .default, egoPeerID, dynamicInfo) let request = UpdateTrustRequest.with { $0.changeToken = self.containerMO.changeToken ?? "" $0.peerID = egoPeerID $0.dynamicInfoAndSig = SignedPeerDynamicInfo(dynamicInfo) } - self.cuttlefish.updateTrust(request) { response, error in - os_log("setPreapprovedKeys(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") - guard let response = response, error == nil else { - os_log("setPreapprovedKeys failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(error ?? ContainerError.cloudkitResponseMissing) - return - } - os_log("setPreapprovedKeys: updateTrust suceeded", log: tplogDebug, type: .default) - - do { - try self.persist(changes: response.changes) - } catch { - os_log("setPreapprovedKeys: could not persist changes: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(error) + self.perform(updateTrust: request) { state, _, error in + guard error == nil else { + os_log("setPreapprovedKeys: failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg? ?? "no error") + reply(state, error) return } - reply(nil) + os_log("setPreapprovedKeys: updateTrust succeeded", log: tplogDebug, type: .default) + reply(state, nil) } } } @@ -3358,7 +3740,7 @@ class Container: NSObject { reply: @escaping ([CKRecord]?, Error?) -> Void) { self.semaphore.wait() let reply: ([CKRecord]?, Error?) -> Void = { - os_log("updateTLKs complete: %@", log: tplogTrace, type: .info, traceError($1)) + os_log("updateTLKs complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) self.semaphore.signal() reply($0, $1) } @@ -3366,67 +3748,71 @@ class Container: NSObject { os_log("Uploading some new TLKs: %@", log: tplogDebug, type: .default, ckksKeys) self.moc.performAndWait { - guard let egoPeerID = self.containerMO.egoPeerID, - let egoPermData = self.containerMO.egoPeerPermanentInfo, - let egoPermSig = self.containerMO.egoPeerPermanentInfoSig - else { - os_log("Have no self identity, can't make tlk shares", log: tplogDebug, type: .default) - reply(nil, ContainerError.noPreparedIdentity) - return - } + self.onqueueUpdateTLKs(ckksKeys: ckksKeys, tlkShares: tlkShares, reply: reply) + } + } - guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: TPECPublicKeyFactory()) else { - os_log("Couldn't parse self identity", log: tplogDebug, type: .default, ckksKeys) - reply(nil, ContainerError.invalidPermanentInfoOrSig) + func onqueueUpdateTLKs(ckksKeys: [CKKSKeychainBackedKeySet], + tlkShares: [CKKSTLKShare], + reply: @escaping ([CKRecord]?, Error?) -> Void) { + guard let egoPeerID = self.containerMO.egoPeerID, + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig + else { + os_log("Have no self identity, can't make tlk shares", log: tplogDebug, type: .default) + reply(nil, ContainerError.noPreparedIdentity) + return + } + + guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: TPECPublicKeyFactory()) else { + os_log("Couldn't parse self identity", log: tplogDebug, type: .default, ckksKeys) + reply(nil, ContainerError.invalidPermanentInfoOrSig) + return + } + + loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in + guard let egoPeerKeys = egoPeerKeys else { + os_log("Don't have my own peer keys; can't upload new TLKs: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + reply(nil, error) return } + self.moc.performAndWait { + guard let egoPeerDynamicInfo = self.model.getDynamicInfoForPeer(withID: egoPeerID) else { + os_log("Unable to fetch dynamic info for self", log: tplogDebug, type: .default) + reply(nil, ContainerError.missingDynamicInfo) + return + } - loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in - guard let egoPeerKeys = egoPeerKeys else { - os_log("Don't have my own peer keys; can't upload new TLKs: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + let allTLKShares: [TLKShare] + let viewKeys: [ViewKeys] + do { + (viewKeys, allTLKShares) = try self.makeSharesForNewKeySets(ckksKeys: ckksKeys, + tlkShares: tlkShares, + egoPeerKeys: egoPeerKeys, + egoPeerDynamicInfo: egoPeerDynamicInfo, + epoch: Int(selfPermanentInfo.epoch)) + } catch { + os_log("Unable to process keys before uploading: %{public}@", log: tplogDebug, type: .default, error as CVarArg) reply(nil, error) return } - self.moc.performAndWait { - guard let egoPeerDynamicInfo = self.model.getDynamicInfoForPeer(withID: egoPeerID) else { - os_log("Unable to fetch dynamic info for self", log: tplogDebug, type: .default) - reply(nil, ContainerError.missingDynamicInfo) - return - } - let allTLKShares: [TLKShare] - let viewKeys: [ViewKeys] - do { - (viewKeys, allTLKShares) = try self.makeSharesForNewKeySets(ckksKeys: ckksKeys, - tlkShares: tlkShares, - egoPeerKeys: egoPeerKeys, - egoPeerDynamicInfo: egoPeerDynamicInfo, - epoch: Int(selfPermanentInfo.epoch)) - } catch { - os_log("Unable to process keys before uploading: %@", log: tplogDebug, type: .default, error as CVarArg) + let request = UpdateTrustRequest.with { + $0.changeToken = self.containerMO.changeToken ?? "" + $0.peerID = egoPeerID + $0.tlkShares = allTLKShares + $0.viewKeys = viewKeys + } + + self.cuttlefish.updateTrust(request) { response, error in + guard error == nil else { reply(nil, error) return } - let request = UpdateTrustRequest.with { - $0.changeToken = self.containerMO.changeToken ?? "" - $0.peerID = egoPeerID - $0.tlkShares = allTLKShares - $0.viewKeys = viewKeys - } - - self.cuttlefish.updateTrust(request) { response, error in - os_log("UpdateTrust(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") - - guard error == nil else { - reply(nil, error) - return - } - - let keyHierarchyRecords = response?.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } ?? [] - os_log("Recevied %d CKRecords back", log: tplogDebug, type: .default, keyHierarchyRecords.count) - reply(keyHierarchyRecords, nil) - } + let keyHierarchyRecords = response?.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } ?? [] + os_log("Recevied %d CKRecords back", log: tplogDebug, type: .default, keyHierarchyRecords.count) + reply(keyHierarchyRecords, nil) } } } @@ -3435,7 +3821,7 @@ class Container: NSObject { func getState(reply: @escaping (ContainerState) -> Void) { self.semaphore.wait() let reply: (ContainerState) -> Void = { - os_log("getState complete: %@", log: tplogTrace, type: .info, $0.egoPeerID ?? "") + os_log("getState complete: %{public}@", log: tplogTrace, type: .info, $0.egoPeerID ?? "") self.semaphore.signal() reply($0) } @@ -3450,6 +3836,18 @@ class Container: NSObject { } } + if self.containerMO.fullyViableEscrowRecords != nil { + self.containerMO.fullyViableEscrowRecords!.forEach { record in + state.escrowRecords.insert(record as! EscrowRecordMO) + } + } + + if self.containerMO.partiallyViableEscrowRecords != nil { + self.containerMO.partiallyViableEscrowRecords!.forEach { record in + state.escrowRecords.insert(record as! EscrowRecordMO) + } + } + self.model.allPeers().forEach { peer in state.peers[peer.peerID] = peer } @@ -3459,7 +3857,7 @@ class Container: NSObject { } // This will only fetch changes if no changes have ever been fetched before - private func fetchAndPersistChangesIfNeeded(reply: @escaping (Error?) -> Void) { + func fetchAndPersistChangesIfNeeded(reply: @escaping (Error?) -> Void) { self.moc.performAndWait { if self.containerMO.changeToken == nil { self.onqueueFetchAndPersistChanges(reply: reply) @@ -3469,7 +3867,7 @@ class Container: NSObject { } } - private func fetchAndPersistChanges(reply: @escaping (Error?) -> Void) { + func fetchAndPersistChanges(reply: @escaping (Error?) -> Void) { self.moc.performAndWait { self.onqueueFetchAndPersistChanges(reply: reply) } @@ -3479,10 +3877,9 @@ class Container: NSObject { let request = FetchChangesRequest.with { $0.changeToken = self.containerMO.changeToken ?? "" } - os_log("Fetching with change token: %@", log: tplogDebug, type: .default, request.changeToken.count > 0 ? request.changeToken : "empty") + os_log("Fetching with change token: %{public}@", log: tplogDebug, type: .default, !request.changeToken.isEmpty ? request.changeToken : "empty") self.cuttlefish.fetchChanges(request) { response, error in - os_log("FetchChanges(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { switch error { case CuttlefishErrorMatcher(code: CuttlefishErrorCode.changeTokenExpired): @@ -3492,7 +3889,7 @@ class Container: NSObject { do { try self.deleteLocalCloudKitData() } catch { - os_log("Failed to reset local data: %@", log: tplogDebug, type: .default, error as CVarArg) + os_log("Failed to reset local data: %{public}@", log: tplogDebug, type: .default, error as CVarArg) reply(error) return } @@ -3502,10 +3899,10 @@ class Container: NSObject { return default: - os_log("Fetch error is an unknown error: %@", log: tplogDebug, type: .default, String(describing: error)) + os_log("Fetch error is an unknown error: %{public}@", log: tplogDebug, type: .default, String(describing: error)) } - os_log("Could not fetch changes: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + os_log("Could not fetch changes: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(error) return } @@ -3513,7 +3910,7 @@ class Container: NSObject { do { try self.persist(changes: response.changes) } catch { - os_log("Could not persist changes: %@", log: tplogDebug, type: .default, error as CVarArg) + os_log("Could not persist changes: %{public}@", log: tplogDebug, type: .default, error as CVarArg) reply(error) return } @@ -3536,13 +3933,13 @@ class Container: NSObject { guard let oldDynamicInfo = oldDynamicInfo else { return true } - if (newDynamicInfo.includedPeerIDs != oldDynamicInfo.includedPeerIDs) { + if newDynamicInfo.includedPeerIDs != oldDynamicInfo.includedPeerIDs { return true } - if (newDynamicInfo.excludedPeerIDs != oldDynamicInfo.excludedPeerIDs) { + if newDynamicInfo.excludedPeerIDs != oldDynamicInfo.excludedPeerIDs { return true } - if (newDynamicInfo.preapprovals != oldDynamicInfo.preapprovals) { + if newDynamicInfo.preapprovals != oldDynamicInfo.preapprovals { return true } return false @@ -3558,16 +3955,16 @@ class Container: NSObject { // the caller's responsibility to release it after it completes // (i.e. after reply is invoked). internal func fetchChangesAndUpdateTrustIfNeeded(stableChanges: StableChanges? = nil, - changesPending: Bool = false, - reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { + peerChanges: Bool = false, + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { self.fetchAndPersistChanges { error in if let error = error { - os_log("fetchChangesAndUpdateTrustIfNeeded: fetching failed: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, error) + os_log("fetchChangesAndUpdateTrustIfNeeded: fetching failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, error) return } - self.updateTrustIfNeeded(stableChanges: stableChanges, changesPending: changesPending, reply: reply) + self.updateTrustIfNeeded(stableChanges: stableChanges, peerChanges: peerChanges, reply: reply) } } @@ -3581,132 +3978,168 @@ class Container: NSObject { // the caller's responsibility to release it after it completes // (i.e. after reply is invoked). private func updateTrustIfNeeded(stableChanges: StableChanges? = nil, - changesPending: Bool = false, - reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { + peerChanges: Bool = false, + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { self.moc.performAndWait { guard let egoPeerID = self.containerMO.egoPeerID else { // No identity, nothing to do os_log("updateTrustIfNeeded: No identity.", log: tplogDebug, type: .default) - reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: changesPending, unknownMachineIDs: false, osVersion: nil), nil) + reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), + nil, + nil) return } loadEgoKeyPair(identifier: signingKeyIdentifier(peerID: egoPeerID)) { signingKeyPair, error in guard let signingKeyPair = signingKeyPair else { - os_log("updateTrustIfNeeded: no signing key pair: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: changesPending, unknownMachineIDs: false, osVersion: nil), error) + os_log("updateTrustIfNeeded: no signing key pair: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), + nil, + error) return } - guard self.model.hasPeer(withID: egoPeerID) else { + guard let currentSelfInModel = self.model.peer(withID: egoPeerID) else { // Not in circle, nothing to do let isPreapproved = self.model.hasPotentiallyTrustedPeerPreapprovingKey(signingKeyPair.publicKey().spki()) - os_log("updateTrustIfNeeded: ego peer is not in model, is %@", log: tplogDebug, type: .default, isPreapproved ? "preapproved" : "not yet preapproved") + os_log("updateTrustIfNeeded: ego peer is not in model, is %{public}@", log: tplogDebug, type: .default, isPreapproved ? "preapproved" : "not yet preapproved") reply(TrustedPeersHelperPeerState(peerID: egoPeerID, isPreapproved: isPreapproved, status: .unknown, - memberChanges: changesPending, + memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), + nil, nil) return } - self.moc.performAndWait { - let dynamicInfo: TPPeerDynamicInfo - var stableInfo: TPPeerStableInfo? - do { - // FIXME We should be able to calculate the contents of dynamicInfo without the signingKeyPair, - // and then only load the key if it has changed and we need to sign a new one. This would also - // help make our detection of change immune from non-canonical serialization of dynamicInfo. - dynamicInfo = try self.model.calculateDynamicInfoForPeer(withID: egoPeerID, - addingPeerIDs: nil, - removingPeerIDs: nil, - preapprovedKeys: nil, - signing: signingKeyPair, - currentMachineIDs: self.onqueueCurrentMIDList()) - stableInfo = try self.createNewStableInfoIfNeeded(stableChanges: stableChanges, - egoPeerID: egoPeerID, - dynamicInfo: dynamicInfo, - signingKeyPair: signingKeyPair) - } catch { - os_log("updateTrustIfNeeded: couldn't calculate dynamic info: %@", log: tplogDebug, type: .default, error as CVarArg) - reply(TrustedPeersHelperPeerState(peerID: egoPeerID, - isPreapproved: false, - status: self.model.statusOfPeer(withID: egoPeerID), - memberChanges: changesPending, - unknownMachineIDs: false, - osVersion: nil), - error) - return + // We need to try to have all policy versions that our peers claim to behave + let allPolicyVersions = self.model.allPolicyVersions() + self.fetchPolicyDocumentsWithSemaphore(versions: allPolicyVersions) { _, policyFetchError in + if let error = policyFetchError { + os_log("updateTrustIfNeeded: error fetching all requested policies (continuing anyway): %{public}@", log: tplogDebug, type: .default, error as CVarArg) } - os_log("updateTrustIfNeeded: produced a stableInfo: %@", log: tplogDebug, type: .default, String(describing: stableInfo)) - os_log("updateTrustIfNeeded: produced a dynamicInfo: %@", log: tplogDebug, type: .default, dynamicInfo) - - let peer = self.model.peer(withID: egoPeerID) - if (stableInfo == nil || stableInfo == peer?.stableInfo) && - dynamicInfo == peer?.dynamicInfo { - os_log("updateTrustIfNeeded: complete.", log: tplogDebug, type: .default) - // No change to the dynamicInfo: update the MID list now that we've reached a steady state + self.moc.performAndWait { + let dynamicInfo: TPPeerDynamicInfo + var stableInfo: TPPeerStableInfo? do { - self.onqueueUpdateMachineIDListFromModel(dynamicInfo: dynamicInfo) - try self.moc.save() + // FIXME We should be able to calculate the contents of dynamicInfo without the signingKeyPair, + // and then only load the key if it has changed and we need to sign a new one. This would also + // help make our detection of change immune from non-canonical serialization of dynamicInfo. + dynamicInfo = try self.model.calculateDynamicInfoForPeer(withID: egoPeerID, + addingPeerIDs: nil, + removingPeerIDs: nil, + preapprovedKeys: nil, + signing: signingKeyPair, + currentMachineIDs: self.onqueueCurrentMIDList()) + + stableInfo = try self.createNewStableInfoIfNeeded(stableChanges: stableChanges, + permanentInfo: currentSelfInModel.permanentInfo, + existingStableInfo: currentSelfInModel.stableInfo, + dynamicInfo: dynamicInfo, + signingKeyPair: signingKeyPair) } catch { - os_log("updateTrustIfNeeded: unable to remove untrusted MachineIDs: %@", log: tplogDebug, type: .default, error as CVarArg) - } - - reply(TrustedPeersHelperPeerState(peerID: egoPeerID, - isPreapproved: false, - status: self.model.statusOfPeer(withID: egoPeerID), - memberChanges: changesPending, - unknownMachineIDs: self.onqueueFullIDMSListWouldBeHelpful(), - osVersion: peer?.stableInfo?.osVersion), - nil) - return - } - // Check if we change that should trigger a notification that should trigger TLKShare updates - let haveChanges = changesPending || self.haveTrustMemberChanges(newDynamicInfo: dynamicInfo, oldDynamicInfo: peer?.dynamicInfo) - - let signedDynamicInfo = SignedPeerDynamicInfo(dynamicInfo) - os_log("updateTrustIfNeeded: attempting updateTrust for %@ with: %@", log: tplogDebug, type: .default, egoPeerID, dynamicInfo) - var request = UpdateTrustRequest.with { - $0.changeToken = self.containerMO.changeToken ?? "" - $0.peerID = egoPeerID - $0.dynamicInfoAndSig = signedDynamicInfo - } - if let stableInfo = stableInfo { - request.stableInfoAndSig = SignedPeerStableInfo(stableInfo) - } - self.cuttlefish.updateTrust(request) { response, error in - os_log("UpdateTrust(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") - guard let response = response, error == nil else { - os_log("UpdateTrust failed: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, error ?? ContainerError.cloudkitResponseMissing) + os_log("updateTrustIfNeeded: couldn't calculate dynamic info: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(TrustedPeersHelperPeerState(peerID: egoPeerID, + isPreapproved: false, + status: self.model.statusOfPeer(withID: egoPeerID), + memberChanges: peerChanges, + unknownMachineIDs: false, + osVersion: nil), + nil, + error) return } - do { - try self.persist(changes: response.changes) - } catch { - os_log("updateTrust failed: %@", log: tplogDebug, String(describing: error)) - reply(nil, error) + os_log("updateTrustIfNeeded: produced a stableInfo: %{public}@", log: tplogDebug, type: .default, String(describing: stableInfo)) + os_log("updateTrustIfNeeded: produced a dynamicInfo: %{public}@", log: tplogDebug, type: .default, dynamicInfo) + + let peer = self.model.peer(withID: egoPeerID) + if (stableInfo == nil || stableInfo == peer?.stableInfo) && + dynamicInfo == peer?.dynamicInfo { + os_log("updateTrustIfNeeded: complete.", log: tplogDebug, type: .default) + // No change to the dynamicInfo: update the MID list now that we've reached a steady state + do { + self.onqueueUpdateMachineIDListFromModel(dynamicInfo: dynamicInfo) + try self.moc.save() + } catch { + os_log("updateTrustIfNeeded: unable to remove untrusted MachineIDs: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + } + + let syncingPolicy: TPSyncingPolicy? + do { + if let peer = self.model.peer(withID: egoPeerID), let stableInfo = peer.stableInfo { + syncingPolicy = try self.syncingPolicyFor(modelID: peer.permanentInfo.modelID, stableInfo: stableInfo) + } else { + syncingPolicy = nil + } + } catch { + os_log("updateTrustIfNeeded: unable to compute a new syncing policy: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + syncingPolicy = nil + } + + reply(TrustedPeersHelperPeerState(peerID: egoPeerID, + isPreapproved: false, + status: self.model.statusOfPeer(withID: egoPeerID), + memberChanges: peerChanges, + unknownMachineIDs: self.onqueueFullIDMSListWouldBeHelpful(), + osVersion: peer?.stableInfo?.osVersion), + syncingPolicy, + nil) return } + // Check if we change that should trigger a notification that should trigger TLKShare updates + let havePeerChanges = peerChanges || self.haveTrustMemberChanges(newDynamicInfo: dynamicInfo, oldDynamicInfo: peer?.dynamicInfo) - if response.changes.more { - self.fetchChangesAndUpdateTrustIfNeeded(stableChanges: stableChanges, - changesPending: haveChanges, - reply: reply) - } else { - self.updateTrustIfNeeded(stableChanges: stableChanges, - changesPending: haveChanges, - reply: reply) + let signedDynamicInfo = SignedPeerDynamicInfo(dynamicInfo) + os_log("updateTrustIfNeeded: attempting updateTrust for %{public}@ with: %{public}@", log: tplogDebug, type: .default, egoPeerID, dynamicInfo) + var request = UpdateTrustRequest.with { + $0.changeToken = self.containerMO.changeToken ?? "" + $0.peerID = egoPeerID + $0.dynamicInfoAndSig = signedDynamicInfo } + if let stableInfo = stableInfo { + request.stableInfoAndSig = SignedPeerStableInfo(stableInfo) + } + + self.perform(updateTrust: request, stableChanges: stableChanges, peerChanges: havePeerChanges, reply: reply) } } } } } + private func perform(updateTrust request: UpdateTrustRequest, + stableChanges: StableChanges? = nil, + peerChanges: Bool = false, + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { + self.cuttlefish.updateTrust(request) { response, error in + guard let response = response, error == nil else { + os_log("UpdateTrust failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, nil, error ?? ContainerError.cloudkitResponseMissing) + return + } + + do { + try self.persist(changes: response.changes) + } catch { + os_log("UpdateTrust failed: %{public}@", log: tplogDebug, String(describing: error)) + reply(nil, nil, error) + return + } + + if response.changes.more { + self.fetchChangesAndUpdateTrustIfNeeded(stableChanges: stableChanges, + peerChanges: peerChanges, + reply: reply) + } else { + self.updateTrustIfNeeded(stableChanges: stableChanges, + peerChanges: peerChanges, + reply: reply) + } + } + } + private func persist(changes: Changes) throws { // This is some nonsense: I can't figure out how to tell swift to throw an exception across performAndWait. // So, do it ourself @@ -3716,7 +4149,7 @@ class Container: NSObject { os_log("persist: Received %d peer differences, more: %d", log: tplogDebug, type: .default, changes.differences.count, changes.more) - os_log("persist: New change token: %@", log: tplogDebug, type: .default, changes.changeToken) + os_log("persist: New change token: %{public}@", log: tplogDebug, type: .default, changes.changeToken) do { try self.onQueuePersist(changes: changes) @@ -3736,17 +4169,16 @@ class Container: NSObject { self.containerMO.changeToken = changes.changeToken self.containerMO.moreChanges = changes.more - if changes.differences.count > 0 { + if !changes.differences.isEmpty { self.model.clearViableBottles() + os_log("escrow cache and viable bottles are no longer valid", log: tplogDebug, type: .default) + self.onQueueRemoveEscrowCache() } try changes.differences.forEach { peerDifference in if let operation = peerDifference.operation { switch operation { - case .add(let peer): - try self.addOrUpdate(peer: peer) - - case .update(let peer): + case .add(let peer), .update(let peer): try self.addOrUpdate(peer: peer) // Update containerMO ego data if it has changed. if peer.peerID == self.containerMO.egoPeerID { @@ -3769,7 +4201,7 @@ class Container: NSObject { let signingKey = changes.recoverySigningPubKey let encryptionKey = changes.recoveryEncryptionPubKey - if signingKey.count > 0 && encryptionKey.count > 0 { + if !signingKey.isEmpty && !encryptionKey.isEmpty { self.addOrUpdate(signingKey: signingKey, encryptionKey: encryptionKey) } try self.moc.save() @@ -3785,19 +4217,32 @@ class Container: NSObject { peerRequest.predicate = NSPredicate(format: "container == %@", self.containerMO) try self.moc.execute(NSBatchDeleteRequest(fetchRequest: peerRequest)) - let bottleRequest = NSFetchRequest(entityName: "Bottle") - bottleRequest.predicate = NSPredicate(format: "container == %@", self.containerMO) - try self.moc.execute(NSBatchDeleteRequest(fetchRequest: bottleRequest)) + // If we have an ego peer ID, keep the bottle associated with it + if let peerID = self.containerMO.egoPeerID, let bottles = self.containerMO.bottles { + let nonPeerBottles = NSSet(array: bottles.filter { + switch $0 { + case let bottleMO as BottleMO: + return bottleMO.peerID != peerID + default: + return false + } + }) + self.containerMO.removeFromBottles(nonPeerBottles as NSSet) + } else { + let bottleRequest = NSFetchRequest(entityName: "Bottle") + bottleRequest.predicate = NSPredicate(format: "container == %@", self.containerMO) + try self.moc.execute(NSBatchDeleteRequest(fetchRequest: bottleRequest)) + self.containerMO.bottles = nil + } self.containerMO.peers = nil - self.containerMO.bottles = nil self.containerMO.changeToken = nil self.containerMO.moreChanges = false self.model = Container.loadModel(from: self.containerMO) try self.moc.save() } catch { - os_log("Local delete failed: %@", log: tplogDebug, type: .default, error as CVarArg) + os_log("Local delete failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) throw error } @@ -3807,7 +4252,10 @@ class Container: NSObject { // Must be on moc queue to call this. private func addOrUpdate(signingKey: Data, encryptionKey: Data) { self.model.setRecoveryKeys( - TPRecoveryKeyPair(signingSPKI: signingKey, encryptionSPKI: encryptionKey)) + TPRecoveryKeyPair(signingKeyData: signingKey, encryptionKeyData: encryptionKey)) + + self.containerMO.recoveryKeySigningSPKI = signingKey + self.containerMO.recoveryKeyEncryptionSPKI = encryptionKey } // Must be on moc queue to call this. @@ -3832,7 +4280,9 @@ class Container: NSObject { } else { // Update: // The assertion here is that every peer registered in model is also present in containerMO - let peerMO = try self.fetchPeerMO(peerID: peer.peerID)! + guard let peerMO = try self.fetchPeerMO(peerID: peer.peerID) else { + throw ContainerError.peerRegisteredButNotStored(peer.peerID) + } if let stableInfo = peer.stableInfoAndSig.toStableInfo() { try self.model.update(stableInfo, forPeerWithID: peer.peerID) @@ -3853,10 +4303,12 @@ class Container: NSObject { peer.vouchers.forEach { if let voucher = TPVoucher(infoWith: $0.voucher, sig: $0.sig) { self.model.register(voucher) - let voucherMO = VoucherMO(context: self.moc) - voucherMO.voucherInfo = voucher.data - voucherMO.voucherInfoSig = voucher.sig - peerMO.addToVouchers(voucherMO) + if peer.vouchers.filter({ $0.voucher == voucher.data && $0.sig == voucher.sig }).isEmpty { + let voucherMO = VoucherMO(context: self.moc) + voucherMO.voucherInfo = voucher.data + voucherMO.voucherInfoSig = voucher.sig + peerMO.addToVouchers(voucherMO) + } } } } @@ -3875,52 +4327,71 @@ class Container: NSObject { guard let policyDoc = self.model.policy(withVersion: policyVersion) else { throw ContainerError.unknownPolicyVersion(policyVersion) } - assert(policyVersion == policyDoc.policyVersion) - if policyVersion == prevailingPolicyVersion { - assert(policyDoc.policyHash == prevailingPolicyHash) + assert(policyVersion == policyDoc.version.versionNumber) + if policyVersion == prevailingPolicyVersion.versionNumber { + assert(policyDoc.version.policyHash == prevailingPolicyVersion.policyHash) } return policyDoc } // Must be on moc queue to call this. private func createNewStableInfoIfNeeded(stableChanges: StableChanges?, - egoPeerID: String, + permanentInfo: TPPeerPermanentInfo, + existingStableInfo: TPPeerStableInfo?, dynamicInfo: TPPeerDynamicInfo, signingKeyPair: _SFECKeyPair) throws -> TPPeerStableInfo? { func noChange(_ change: T?, _ existing: T?) -> Bool { return (nil == change) || change == existing } - let existingStableInfo = self.model.peer(withID: egoPeerID)?.stableInfo + + let policyOfPeers = try? self.model.policy(forPeerIDs: dynamicInfo.includedPeerIDs, + candidatePeerID: permanentInfo.peerID, + candidateStableInfo: existingStableInfo) + + // Pick the best version of: + // 1. The policy version asked for by the client + // 2. The policy override set on this object (tests only) + // 3. The max of our existing policyVersion, the highest policy used by our trusted peers, and the compile-time prevailing policy version + let optimalPolicyVersionNumber = stableChanges?.policyVersion ?? + self.policyVersionOverride?.versionNumber ?? + max(existingStableInfo?.bestPolicyVersion().versionNumber ?? prevailingPolicyVersion.versionNumber, + policyOfPeers?.version.versionNumber ?? prevailingPolicyVersion.versionNumber, + prevailingPolicyVersion.versionNumber) + + // Determine which recovery key we'd like to be using, given our current idea of who to trust + let optimalRecoveryKey = self.model.bestRecoveryKey(for: existingStableInfo, dynamicInfo: dynamicInfo) + + let intendedSyncUserControllableViews = stableChanges?.setSyncUserControllableViews?.sanitizeForPlatform(permanentInfo: permanentInfo) + if noChange(stableChanges?.deviceName, existingStableInfo?.deviceName) && noChange(stableChanges?.serialNumber, existingStableInfo?.serialNumber) && noChange(stableChanges?.osVersion, existingStableInfo?.osVersion) && - noChange(stableChanges?.policyVersion, existingStableInfo?.policyVersion) && + noChange(optimalPolicyVersionNumber, existingStableInfo?.bestPolicyVersion().versionNumber) && noChange(stableChanges?.policySecrets, existingStableInfo?.policySecrets) && - noChange(stableChanges?.recoverySigningPubKey, existingStableInfo?.recoverySigningPublicKey) && - noChange(stableChanges?.recoveryEncryptionPubKey, existingStableInfo?.recoveryEncryptionPublicKey) && - self.model.doesPeerRecoveryKeyMatchPeers(egoPeerID) { + noChange(optimalRecoveryKey?.signingKeyData, existingStableInfo?.recoverySigningPublicKey) && + noChange(optimalRecoveryKey?.encryptionKeyData, existingStableInfo?.recoveryEncryptionPublicKey) && + noChange(intendedSyncUserControllableViews, existingStableInfo?.syncUserControllableViews) { return nil } - let policyHash: String? - if let policyVersion = stableChanges?.policyVersion { - let policyDoc = try self.getPolicyDoc(policyVersion) - policyHash = policyDoc.policyHash - } else { - policyHash = nil + + // If a test has asked a policy version before we froze this policy, then don't set a flexible version--it's trying to build a peer from before the policy was frozen + let optimalPolicyVersion = try self.getPolicyDoc(optimalPolicyVersionNumber).version + let useFrozenPolicyVersion = optimalPolicyVersion.versionNumber >= frozenPolicyVersion.versionNumber + + if let intendedSyncUserControllableViews = intendedSyncUserControllableViews { + os_log("Intending to set user-controllable views to %{public}@", log: tplogTrace, type: .info, TPPBPeerStableInfo_UserControllableViewStatusAsString(intendedSyncUserControllableViews)) } - // Determine which recovery key we'd like to be using, given our current idea of who to trust - let newRecoveryKeys = self.model.bestRecoveryKey(with: dynamicInfo) - - return try self.model.createStableInfo(withPolicyVersion: stableChanges?.policyVersion ?? existingStableInfo?.policyVersion ?? prevailingPolicyVersion, - policyHash: policyHash ?? existingStableInfo?.policyHash ?? prevailingPolicyHash, + return try self.model.createStableInfo(withFrozenPolicyVersion: useFrozenPolicyVersion ? frozenPolicyVersion : optimalPolicyVersion, + flexiblePolicyVersion: useFrozenPolicyVersion ? optimalPolicyVersion : nil, policySecrets: stableChanges?.policySecrets ?? existingStableInfo?.policySecrets, + syncUserControllableViews: intendedSyncUserControllableViews ?? existingStableInfo?.syncUserControllableViews ?? .UNKNOWN, deviceName: stableChanges?.deviceName ?? existingStableInfo?.deviceName ?? "", serialNumber: stableChanges?.serialNumber ?? existingStableInfo?.serialNumber ?? "", osVersion: stableChanges?.osVersion ?? existingStableInfo?.osVersion ?? "", signing: signingKeyPair, - recoverySigningPubKey: newRecoveryKeys?.signingSPKI ?? existingStableInfo?.recoverySigningPublicKey, - recoveryEncryptionPubKey: newRecoveryKeys?.encryptionSPKI ?? existingStableInfo?.recoveryEncryptionPublicKey) + recoverySigningPubKey: optimalRecoveryKey?.signingKeyData, + recoveryEncryptionPubKey: optimalRecoveryKey?.encryptionKeyData) } private func assembleBottle(egoPeerID: String) throws -> Bottle { @@ -3933,7 +4404,9 @@ class Container: NSObject { if let count = bottleMOs?.count { if count > 1 { throw ContainerError.tooManyBottlesForPeer + // swiftlint:disable empty_count } else if count == 0 { + // swiftlint:enable empty_count throw ContainerError.noBottleForPeer } } else { @@ -3982,7 +4455,7 @@ class Container: NSObject { func reportHealth(request: ReportHealthRequest, reply: @escaping (Error?) -> Void) { self.semaphore.wait() let reply: (Error?) -> Void = { - os_log("reportHealth complete %@", log: tplogTrace, type: .info, traceError($0)) + os_log("reportHealth complete %{public}@", log: tplogTrace, type: .info, traceError($0)) self.semaphore.signal() reply($0) } @@ -3996,8 +4469,7 @@ class Container: NSObject { } self.moc.performAndWait { - self.cuttlefish.reportHealth(updatedRequest) { response, error in - os_log("reportHealth(%@): %@, error: %@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") + self.cuttlefish.reportHealth(updatedRequest) { _, error in guard error == nil else { reply(error) return @@ -4010,14 +4482,13 @@ class Container: NSObject { func pushHealthInquiry(reply: @escaping (Error?) -> Void) { self.semaphore.wait() let reply: (Error?) -> Void = { - os_log("reportHealth complete %@", log: tplogTrace, type: .info, traceError($0)) + os_log("reportHealth complete %{public}@", log: tplogTrace, type: .info, traceError($0)) self.semaphore.signal() reply($0) } self.moc.performAndWait { - self.cuttlefish.pushHealthInquiry(PushHealthInquiryRequest()) { response, error in - os_log("pushHealthInquiry(): %@, error: %@", log: tplogDebug, "\(String(describing: response))", "\(String(describing: error))") + self.cuttlefish.pushHealthInquiry(PushHealthInquiryRequest()) { _, error in guard error == nil else { reply(error) return diff --git a/keychain/TrustedPeersHelper/ContainerMap.swift b/keychain/TrustedPeersHelper/ContainerMap.swift index 59f539dc..7f6e03c5 100644 --- a/keychain/TrustedPeersHelper/ContainerMap.swift +++ b/keychain/TrustedPeersHelper/ContainerMap.swift @@ -47,7 +47,7 @@ func ~= (pattern: CKInternalErrorMatcher, value: Error?) -> Bool { return false } return error.domain == CKErrorDomain && error.code == pattern.code && - underlyingError.domain == CKInternalErrorDomain && underlyingError.code == pattern.internalCode + underlyingError.domain == CKInternalErrorDomain && underlyingError.code == pattern.internalCode } struct CKErrorMatcher { @@ -83,7 +83,7 @@ public class RetryingInvocable: CloudKitCode.Invocable { self.underlyingInvocable = retry } - public class func retryableError(error: Error?) -> Bool { + public class func retryableError(error: Error?) -> Bool { switch error { case NSURLErrorMatcher(code: NSURLErrorTimedOut): return true @@ -120,34 +120,33 @@ public class RetryingInvocable: CloudKitCode.Invocable { deadline: Date, minimumDelay: TimeInterval, completion: @escaping (ResponseType?, Error?) -> Void) { - self.underlyingInvocable.invoke(function: function, request: request) { (response: ResponseType?, error: Error?) in - if let error = error, RetryingInvocable.retryableError(error: error) { - let now = Date() + if let error = error, RetryingInvocable.retryableError(error: error) { + let now = Date() - // Check cuttlefish and CKError retry afters. - let cuttlefishDelay = CuttlefishRetryAfter(error: error) - let ckDelay = CKRetryAfterSecondsForError(error) - let delay = max(minimumDelay, cuttlefishDelay, ckDelay) - let cutoff = Date(timeInterval: delay, since: now) + // Check cuttlefish and CKError retry afters. + let cuttlefishDelay = CuttlefishRetryAfter(error: error) + let ckDelay = CKRetryAfterSecondsForError(error) + let delay = max(minimumDelay, cuttlefishDelay, ckDelay) + let cutoff = Date(timeInterval: delay, since: now) - guard cutoff.compare(deadline) == ComparisonResult.orderedDescending else { - Thread.sleep(forTimeInterval: delay) - os_log("%{public}@ error: %{public}@ (retrying, now=%{public}@, deadline=%{public}@)", log: tplogDebug, - function, - "\(String(describing: error))", - "\(String(describing: now))", - "\(String(describing: deadline))") - self.invokeRetry(function: function, - request: request, - deadline: deadline, - minimumDelay: minimumDelay, - completion: completion) - return - } - } - completion(response, error) + guard cutoff.compare(deadline) == ComparisonResult.orderedDescending else { + Thread.sleep(forTimeInterval: delay) + os_log("%{public}@ error: %{public}@ (retrying, now=%{public}@, deadline=%{public}@)", log: tplogDebug, + function, + "\(String(describing: error))", + "\(String(describing: now))", + "\(String(describing: deadline))") + self.invokeRetry(function: function, + request: request, + deadline: deadline, + minimumDelay: minimumDelay, + completion: completion) + return + } + } + completion(response, error) } } } @@ -172,10 +171,8 @@ public class MyCodeConnection: CloudKitCode.Invocable { public func invoke( function: String, request: RequestType, completion: @escaping (ResponseType?, Error?) -> Void) { - // Hack to fool CloudKit, real solution is tracked in self.queue.async { - let operation = CodeOperation( service: self.serviceName, functionName: function, @@ -191,7 +188,7 @@ public class MyCodeConnection: CloudKitCode.Invocable { operation.requestCompletedBlock = requestCompletion let loggingCompletion = { (response: ResponseType?, error: Error?) -> Void in - os_log("%@(%@): %@, error: %@", + os_log("%{public}@(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, function, "\(String(describing: request))", @@ -213,8 +210,7 @@ public class MyCodeConnection: CloudKitCode.Invocable { operation.configuration.discretionaryNetworkBehavior = .nonDiscretionary operation.configuration.automaticallyRetryNetworkFailures = false operation.configuration.isCloudKitSupportOperation = true - - operation.configuration.sourceApplicationBundleIdentifier = CuttlefishPushTopicBundleIdentifier + operation.configuration.setApplicationBundleIdentifierOverride(CuttlefishPushTopicBundleIdentifier) let database = self.container.database(with: self.databaseScope) @@ -234,7 +230,7 @@ class CKCodeCuttlefishInvocableCreator: ContainerNameToCuttlefishInvocable { // Cuttlefish is using its own push topic. // To register for this push topic, we need to issue CK operations with a specific bundle identifier - ckContainer.sourceApplicationBundleIdentifier = CuttlefishPushTopicBundleIdentifier + ckContainer.options.setApplicationBundleIdentifierOverride(CuttlefishPushTopicBundleIdentifier) let ckDatabase = ckContainer.privateCloudDatabase return MyCodeConnection(service: "Cuttlefish", container: ckContainer, @@ -262,7 +258,6 @@ class ContainerMap { if let container = self.containers[name] { return container } else { - // Set up Core Data stack let persistentStoreURL = ContainerMap.urlForPersistentStore(name: name) let description = NSPersistentStoreDescription(url: persistentStoreURL) @@ -284,4 +279,19 @@ class ContainerMap { let filename = name.container + "-" + name.context + ".TrustedPeersHelper.db" return SecCopyURLForFileInKeychainDirectory(filename as CFString) as URL } + + // To be called via test only + func removeAllContainers() { + queue.sync { + self.containers.removeAll() + } + } + + func deleteAllPersistentStores() throws { + try queue.sync { + try self.containers.forEach { + try $0.value.deletePersistentStore() + } + } + } } diff --git a/keychain/TrustedPeersHelper/Container_BottledPeers.swift b/keychain/TrustedPeersHelper/Container_BottledPeers.swift new file mode 100644 index 00000000..e9908f5b --- /dev/null +++ b/keychain/TrustedPeersHelper/Container_BottledPeers.swift @@ -0,0 +1,106 @@ +import CoreData +import Foundation + +extension Container { + func onMOCQueueFindBottle(bottleID: String) throws -> (BottleMO) { + guard let containerBottles = self.containerMO.bottles as? Set else { + throw ContainerError.noBottlesPresent + } + + let bottles = containerBottles.filter { $0.bottleID == bottleID } + + guard let bottle = bottles.first else { + throw ContainerError.noBottlesForEscrowRecordID + } + + return bottle + } + + func preflightVouchWithBottle(bottleID: String, + reply: @escaping (String?, TPSyncingPolicy?, Bool, Error?) -> Void) { + self.semaphore.wait() + let reply: (String?, TPSyncingPolicy?, Bool, Error?) -> Void = { + os_log("preflightVouchWithBottle complete: %{public}@", + log: tplogTrace, type: .info, traceError($3)) + self.semaphore.signal() + reply($0, $1, $2, $3) + } + + self.moc.performAndWait { + do { + let (_, peerID, syncingPolicy) = try self.onMOCQueuePerformPreflight(bottleID: bottleID) + reply(peerID, syncingPolicy, false, nil) + } catch { + os_log("preflightVouchWithBottle failed; forcing refetch and retrying: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") + + self.fetchAndPersistChanges { fetchError in + guard fetchError == nil else { + os_log("preflightVouchWithBottle unable to fetch current peers: %{public}@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "") + reply(nil, nil, true, fetchError) + return + } + + // Ensure we have all policy versions claimed by peers, including our sponsor + let allPolicyVersions = self.model.allPolicyVersions() + self.fetchPolicyDocumentsWithSemaphore(versions: allPolicyVersions) { _, fetchPolicyDocumentsError in + guard fetchPolicyDocumentsError == nil else { + os_log("preflightVouchWithBottle unable to fetch policy documents: %{public}@", log: tplogDebug, type: .default, (fetchPolicyDocumentsError as CVarArg?) ?? "no error") + reply(nil, nil, true, fetchPolicyDocumentsError) + return + } + + self.fetchViableBottlesWithSemaphore { _, _, fetchBottlesError in + guard fetchBottlesError == nil else { + os_log("preflightVouchWithBottle unable to fetch viable bottles: %{public}@", log: tplogDebug, type: .default, (fetchPolicyDocumentsError as CVarArg?) ?? "no error") + reply(nil, nil, true, fetchBottlesError) + return + } + + // and try again: + self.moc.performAndWait { + do { + let (_, peerID, syncingPolicy) = try self.onMOCQueuePerformPreflight(bottleID: bottleID) + reply(peerID, syncingPolicy, true, nil) + } catch { + os_log("preflightVouchWithBottle failed after refetches; failing: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") + reply(nil, nil, true, error) + } + } + } + } + } + } + } + } + + func onMOCQueuePerformPreflight(bottleID: String) throws -> (BottleMO, String, TPSyncingPolicy) { + guard let egoPeerID = self.containerMO.egoPeerID, + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig else { + os_log("fetchCurrentPolicy failed to find ego peer information", log: tplogDebug, type: .error) + throw ContainerError.noPreparedIdentity + } + + let keyFactory = TPECPublicKeyFactory() + guard let egoPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { + os_log("fetchCurrentPolicy failed to create TPPeerPermanentInfo", log: tplogDebug, type: .error) + throw ContainerError.invalidPermanentInfoOrSig + } + + let bottleMO = try self.onMOCQueueFindBottle(bottleID: bottleID) + + guard let sponsorPeer = self.model.peer(withID: bottleMO.peerID ?? "") else { + os_log("preflightVouchWithBottle found no peer to match bottle", log: tplogDebug, type: .default) + throw ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given") + } + + guard let sponsorPeerStableInfo = sponsorPeer.stableInfo else { + os_log("preflightVouchWithBottle sponsor peer has no stable info", log: tplogDebug, type: .default) + throw ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given") + } + + // We need to extract the syncing policy that the remote peer would have used (if they were the type of device that we are) + let policy = try self.syncingPolicyFor(modelID: egoPermanentInfo.modelID, stableInfo: sponsorPeerStableInfo) + return (bottleMO, sponsorPeer.peerID, policy) + } +} diff --git a/keychain/TrustedPeersHelper/Container_EscrowRecords.swift b/keychain/TrustedPeersHelper/Container_EscrowRecords.swift new file mode 100644 index 00000000..27f22af7 --- /dev/null +++ b/keychain/TrustedPeersHelper/Container_EscrowRecords.swift @@ -0,0 +1,206 @@ +import CoreData +import Foundation + +extension Container { + + func onqueueCachedRecordsContainEgoPeerBottle(cachedRecords: [OTEscrowRecord]) -> Bool { + guard let egoPeerID = self.containerMO.egoPeerID else { + os_log("onqueueCachedRecordsContainEgoPeerBottle: No identity.", log: tplogDebug, type: .default) + return false + } + guard let bottles: Set = self.containerMO.bottles as? Set else { + os_log("onqueueCachedRecordsContainEgoPeerBottle: No Bottles.", log: tplogDebug, type: .default) + return false + } + var matchesCached: Bool = false + for bottle in bottles { + guard let bottleID: String = bottle.bottleID else { + continue + } + if bottle.peerID == egoPeerID && (cachedRecords.compactMap { $0.escrowInformationMetadata.bottleId }).contains(bottleID) { + matchesCached = true + break + } + } + return matchesCached + } + + func escrowRecordMOToEscrowRecords(record: EscrowRecordMO, viability: Viability) -> OTEscrowRecord? { + let escrowRecord = OTEscrowRecord() + let escrowRecordMetadata = OTEscrowRecordMetadata() + let clientMetadata = OTEscrowRecordMetadataClientMetadata() + + if let e = escrowRecord { + if let creationDate = record.creationDate { + e.creationDate = UInt64(creationDate.timeIntervalSince1970) + } + e.label = record.label ?? "" + e.remainingAttempts = UInt64(record.remainingAttempts) + e.silentAttemptAllowed = UInt64(record.silentAttemptAllowed) + e.recordStatus = record.recordStatus == 0 ? .RECORD_STATUS_VALID : .RECORD_STATUS_INVALID + e.federationId = record.federationID ?? "" + e.expectedFederationId = record.expectedFederationID ?? "" + + switch viability { + case .full: + e.recordViability = .RECORD_VIABILITY_FULLY_VIABLE + case .partial: + e.recordViability = .RECORD_VIABILITY_PARTIALLY_VIABLE + case .none: + e.recordViability = .RECORD_VIABILITY_LEGACY + } + + switch record.sosViability { + case 0: + e.viabilityStatus = .SOS_VIABLE_UNKNOWN + case 1: + e.viabilityStatus = .SOS_VIABLE + case 2: + e.viabilityStatus = .SOS_NOT_VIABLE + default: + e.viabilityStatus = .SOS_VIABLE_UNKNOWN + } + + if let metadata = escrowRecordMetadata { + if let m = record.escrowMetadata { + metadata.backupKeybagDigest = m.backupKeybagDigest ?? Data() + if let timestamp = m.secureBackupTimestamp { + metadata.secureBackupTimestamp = UInt64(timestamp.timeIntervalSince1970) + } + metadata.secureBackupUsesMultipleIcscs = UInt64(m.secureBackupUsesMultipleiCSCS) + metadata.bottleId = m.bottleID ?? "" + metadata.escrowedSpki = m.escrowedSPKI ?? Data() + metadata.peerInfo = m.peerInfo ?? Data() + metadata.serial = m.serial ?? "" + if let cmToFill = clientMetadata { + if let cm = m.clientMetadata { + cmToFill.deviceMid = cm.deviceMid ?? "" + cmToFill.deviceColor = cm.deviceColor ?? "" + cmToFill.deviceModel = cm.deviceModel ?? "" + cmToFill.deviceName = cm.deviceName ?? "" + cmToFill.devicePlatform = UInt64(cm.devicePlatform) + cmToFill.deviceModelClass = cm.deviceModelClass ?? "" + cmToFill.deviceModelVersion = cm.deviceModelVersion ?? "" + cmToFill.deviceEnclosureColor = cm.deviceEnclosureColor ?? "" + if let timestamp = cm.secureBackupMetadataTimestamp { + cmToFill.secureBackupMetadataTimestamp = UInt64(timestamp.timeIntervalSince1970) + } + cmToFill.secureBackupUsesComplexPassphrase = UInt64(cm.secureBackupUsesComplexPassphrase) + cmToFill.secureBackupUsesNumericPassphrase = UInt64(cm.secureBackupUsesNumericPassphrase) + cmToFill.secureBackupNumericPassphraseLength = UInt64(cm.secureBackupNumericPassphraseLength) + } + } + metadata.clientMetadata = clientMetadata + } + e.escrowInformationMetadata = metadata + } + } + + return escrowRecord + } + + func setEscrowRecord(record: EscrowInformation, viability: Viability) { + let escrowRecordMO = EscrowRecordMO(context: self.moc) + escrowRecordMO.label = record.label + escrowRecordMO.creationDate = record.creationDate.date + escrowRecordMO.remainingAttempts = Int64(record.remainingAttempts) + escrowRecordMO.silentAttemptAllowed = Int64(record.silentAttemptAllowed) + escrowRecordMO.recordStatus = Int64(record.recordStatus.rawValue) + escrowRecordMO.sosViability = Int64(record.viabilityStatus.rawValue) + escrowRecordMO.federationID = record.federationID + escrowRecordMO.expectedFederationID = record.expectedFederationID + + let escrowRecordMetadataMO = EscrowMetadataMO(context: self.moc) + escrowRecordMetadataMO.backupKeybagDigest = record.escrowInformationMetadata.backupKeybagDigest + escrowRecordMetadataMO.secureBackupUsesMultipleiCSCS = Int64(record.escrowInformationMetadata.secureBackupUsesMultipleIcscs) + escrowRecordMetadataMO.bottleID = record.escrowInformationMetadata.bottleID + escrowRecordMetadataMO.secureBackupTimestamp = record.escrowInformationMetadata.secureBackupTimestamp.date + escrowRecordMetadataMO.escrowedSPKI = record.escrowInformationMetadata.escrowedSpki + escrowRecordMetadataMO.peerInfo = record.escrowInformationMetadata.peerInfo + escrowRecordMetadataMO.serial = record.escrowInformationMetadata.serial + escrowRecordMO.escrowMetadata = escrowRecordMetadataMO + + let escrowRecordClientMetadataMO = EscrowClientMetadataMO(context: self.moc) + escrowRecordClientMetadataMO.secureBackupMetadataTimestamp = record.escrowInformationMetadata.clientMetadata.secureBackupMetadataTimestamp.date + escrowRecordClientMetadataMO.secureBackupNumericPassphraseLength = Int64(record.escrowInformationMetadata.clientMetadata.secureBackupNumericPassphraseLength) + escrowRecordClientMetadataMO.secureBackupUsesComplexPassphrase = Int64(record.escrowInformationMetadata.clientMetadata.secureBackupUsesComplexPassphrase) + escrowRecordClientMetadataMO.secureBackupUsesNumericPassphrase = Int64(record.escrowInformationMetadata.clientMetadata.secureBackupUsesNumericPassphrase) + escrowRecordClientMetadataMO.deviceColor = record.escrowInformationMetadata.clientMetadata.deviceColor + escrowRecordClientMetadataMO.deviceEnclosureColor = record.escrowInformationMetadata.clientMetadata.deviceEnclosureColor + escrowRecordClientMetadataMO.deviceMid = record.escrowInformationMetadata.clientMetadata.deviceMid + escrowRecordClientMetadataMO.deviceModel = record.escrowInformationMetadata.clientMetadata.deviceModel + escrowRecordClientMetadataMO.deviceModelClass = record.escrowInformationMetadata.clientMetadata.deviceModelClass + escrowRecordClientMetadataMO.deviceModelVersion = record.escrowInformationMetadata.clientMetadata.deviceModelVersion + escrowRecordClientMetadataMO.deviceName = record.escrowInformationMetadata.clientMetadata.deviceName + escrowRecordClientMetadataMO.devicePlatform = Int64(record.escrowInformationMetadata.clientMetadata.devicePlatform) + + escrowRecordMetadataMO.clientMetadata = escrowRecordClientMetadataMO + + os_log("setEscrowRecord saving new escrow record: %@", log: tplogDebug, type: .default, escrowRecordMO) + switch viability { + case .full: + self.containerMO.addToFullyViableEscrowRecords(escrowRecordMO) + break + case .partial: + self.containerMO.addToPartiallyViableEscrowRecords(escrowRecordMO) + break + case .none: + self.containerMO.addToLegacyEscrowRecords(escrowRecordMO) + break + } + } + + func onqueueCachedBottlesFromEscrowRecords() -> (TPCachedViableBottles) { + var viableRecords: [String] = [] + var partiallyViableRecords: [String] = [] + + if let fullyViableEscrowRecords = self.containerMO.fullyViableEscrowRecords as? Set { + viableRecords = fullyViableEscrowRecords.compactMap { $0.escrowMetadata?.bottleID } + } + if let partiallyViableEscrowRecords = self.containerMO.partiallyViableEscrowRecords as? Set { + partiallyViableRecords = partiallyViableEscrowRecords.compactMap { $0.escrowMetadata?.bottleID } + } + return TPCachedViableBottles(viableBottles: viableRecords, partialBottles: partiallyViableRecords) + } + + func onqueueCachedEscrowRecords() -> ([OTEscrowRecord]) { + var escrowRecords: [OTEscrowRecord] = [] + + if let fullyViableEscrowRecords = self.containerMO.fullyViableEscrowRecords as? Set { + for record in fullyViableEscrowRecords { + let convertedRecord = escrowRecordMOToEscrowRecords(record: record, viability: .full) + if let r = convertedRecord { + escrowRecords.append(r) + } + } + } + if let partiallyViableEscrowRecords = self.containerMO.partiallyViableEscrowRecords as? Set { + for record in partiallyViableEscrowRecords { + let convertedRecord = escrowRecordMOToEscrowRecords(record: record, viability: .partial) + if let r = convertedRecord { + escrowRecords.append(r) + } + } + } + if let legacyEscrowRecords = self.containerMO.legacyEscrowRecords as? Set { + for record in legacyEscrowRecords { + let convertedRecord = escrowRecordMOToEscrowRecords(record: record, viability: .none) + if let r = convertedRecord { + escrowRecords.append(r) + } + } + } + return escrowRecords + } + + func fetchEscrowRecords(forceFetch: Bool, reply: @escaping ([Data]?, Error?) -> Void) { + self.semaphore.wait() + let reply: ([Data]?, Error?) -> Void = { + os_log("fetchEscrowRecords complete: %@", log: tplogTrace, type: .info, traceError($1)) + self.semaphore.signal() + reply($0, $1) + } + + self.fetchEscrowRecordsWithSemaphore(forceFetch: forceFetch, reply: reply) + } +} diff --git a/keychain/TrustedPeersHelper/Container_MachineIDs.swift b/keychain/TrustedPeersHelper/Container_MachineIDs.swift index 0a8dd0bc..58692a56 100644 --- a/keychain/TrustedPeersHelper/Container_MachineIDs.swift +++ b/keychain/TrustedPeersHelper/Container_MachineIDs.swift @@ -57,7 +57,7 @@ extension Container { // Once we run this upgrade, we will set the allowed bool to false, since it's unused. // Therefore, if we have a single record with "allowed" set, we haven't run the upgrade. - let runUpgrade = knownMachineMOs.filter { $0.allowed }.count > 0 + let runUpgrade = knownMachineMOs.contains { $0.allowed } if runUpgrade { knownMachineMOs.forEach { mo in if mo.allowed { @@ -70,15 +70,29 @@ extension Container { } } - func setAllowedMachineIDs(_ allowedMachineIDs: Set, reply: @escaping (Bool, Error?) -> Void) { + func enforceIDMSListChanges(knownMachines: Set) -> Bool { + if self.containerMO.honorIDMSListChanges == "YES"{ + return true + } else if self.containerMO.honorIDMSListChanges == "NO" { + return false + } else if self.containerMO.honorIDMSListChanges == "UNKNOWN" && knownMachines.isEmpty { + return false + } else if self.containerMO.honorIDMSListChanges == "UNKNOWN" && !knownMachines.isEmpty { + return true + } else { + return true + } + } + + func setAllowedMachineIDs(_ allowedMachineIDs: Set, honorIDMSListChanges: Bool, reply: @escaping (Bool, Error?) -> Void) { self.semaphore.wait() let reply: (Bool, Error?) -> Void = { - os_log("setAllowedMachineIDs complete: %@", log: tplogTrace, type: .info, traceError($1)) + os_log("setAllowedMachineIDs complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) self.semaphore.signal() reply($0, $1) } - os_log("Setting allowed machine IDs: %@", log: tplogDebug, type: .default, allowedMachineIDs) + os_log("Setting allowed machine IDs: %{public}@", log: tplogDebug, type: .default, allowedMachineIDs) // Note: we currently ignore any machineIDs that are set in the model, but never appeared on the // Trusted Devices list. We should give them a grace period (1wk?) then kick them out. @@ -86,20 +100,21 @@ extension Container { self.moc.performAndWait { do { var differences = false + self.containerMO.honorIDMSListChanges = honorIDMSListChanges ? "YES" : "NO" var knownMachines = containerMO.machines as? Set ?? Set() let knownMachineIDs = Set(knownMachines.compactMap { $0.machineID }) knownMachines.forEach { machine in guard let mid = machine.machineID else { - os_log("Machine has no ID: %@", log: tplogDebug, type: .default, machine) + os_log("Machine has no ID: %{public}@", log: tplogDebug, type: .default, machine) return } if allowedMachineIDs.contains(mid) { if machine.status == TPMachineIDStatus.allowed.rawValue { - os_log("Machine ID still trusted: %@", log: tplogDebug, type: .default, String(describing: machine.machineID)) + os_log("Machine ID still trusted: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) } else { - os_log("Machine ID newly retrusted: %@", log: tplogDebug, type: .default, String(describing: machine.machineID)) + os_log("Machine ID newly retrusted: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) differences = true } machine.status = Int64(TPMachineIDStatus.allowed.rawValue) @@ -115,25 +130,23 @@ extension Container { if machine.seenOnFullList { machine.status = Int64(TPMachineIDStatus.disallowed.rawValue) machine.modified = Date() - os_log("Newly distrusted machine ID: %@", log: tplogDebug, type: .default, String(describing: machine.machineID)) + os_log("Newly distrusted machine ID: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) differences = true - } else { if machine.modifiedInPast(hours: cutoffHours) { - os_log("Allowed-but-unseen machine ID isn't on full list, last modified %@, ignoring: %@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) + os_log("Allowed-but-unseen machine ID isn't on full list, last modified %{public}@, ignoring: %{public}@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) } else { - os_log("Allowed-but-unseen machine ID isn't on full list, last modified %@, distrusting: %@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) + os_log("Allowed-but-unseen machine ID isn't on full list, last modified %{public}@, distrusting: %{public}@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) machine.status = Int64(TPMachineIDStatus.disallowed.rawValue) machine.modified = Date() differences = true } } - } else if machine.status == TPMachineIDStatus.unknown.rawValue { if machine.modifiedInPast(hours: cutoffHours) { - os_log("Unknown machine ID last modified %@; leaving unknown: %@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) + os_log("Unknown machine ID last modified %{public}@; leaving unknown: %{public}@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) } else { - os_log("Unknown machine ID last modified %@; distrusting: %@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) + os_log("Unknown machine ID last modified %{public}@; distrusting: %{public}@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) machine.status = Int64(TPMachineIDStatus.disallowed.rawValue) machine.modified = Date() differences = true @@ -144,7 +157,7 @@ extension Container { // Do we need to create any further objects? allowedMachineIDs.forEach { machineID in - if(!knownMachineIDs.contains(machineID)) { + if !knownMachineIDs.contains(machineID) { // We didn't know about this machine before; it's newly trusted! let machine = MachineMO(context: self.moc) machine.machineID = machineID @@ -152,7 +165,7 @@ extension Container { machine.seenOnFullList = true machine.modified = Date() machine.status = Int64(TPMachineIDStatus.allowed.rawValue) - os_log("Newly trusted machine ID: %@", log: tplogDebug, type: .default, String(describing: machine.machineID)) + os_log("Newly trusted machine ID: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) differences = true self.containerMO.addToMachines(machine) @@ -160,13 +173,12 @@ extension Container { } } - // if this account is not a demo account... - if knownMachines.count > 0 { + if self.enforceIDMSListChanges(knownMachines: knownMachines) { // Are there any machine IDs in the model that aren't in the list? If so, add them as "unknown" let modelMachineIDs = self.model.allMachineIDs() modelMachineIDs.forEach { peerMachineID in if !knownMachineIDs.contains(peerMachineID) && !allowedMachineIDs.contains(peerMachineID) { - os_log("Peer machineID is unknown, beginning grace period: %@", log: tplogDebug, type: .default, peerMachineID) + os_log("Peer machineID is unknown, beginning grace period: %{public}@", log: tplogDebug, type: .default, peerMachineID) let machine = MachineMO(context: self.moc) machine.machineID = peerMachineID machine.container = containerMO @@ -179,7 +191,7 @@ extension Container { } } } else { - os_log("Believe we're in a demo account; not starting an unknown machine ID grace period", log: tplogDebug, type: .default) + os_log("Believe we're in a demo account, not enforcing IDMS list", log: tplogDebug, type: .default) } // We no longer use allowed machine IDs. @@ -189,7 +201,7 @@ extension Container { reply(differences, nil) } catch { - os_log("Error setting machine ID list: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + os_log("Error setting machine ID list: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(false, error) } } @@ -198,12 +210,12 @@ extension Container { func addAllow(_ machineIDs: [String], reply: @escaping (Error?) -> Void) { self.semaphore.wait() let reply: (Error?) -> Void = { - os_log("addAllow complete: %@", log: tplogTrace, type: .info, traceError($0)) + os_log("addAllow complete: %{public}@", log: tplogTrace, type: .info, traceError($0)) self.semaphore.signal() reply($0) } - os_log("Adding allowed machine IDs: %@", log: tplogDebug, type: .default, machineIDs) + os_log("Adding allowed machine IDs: %{public}@", log: tplogDebug, type: .default, machineIDs) self.moc.performAndWait { do { @@ -218,10 +230,9 @@ extension Container { if machine.machineID == machineID { machine.status = Int64(TPMachineIDStatus.allowed.rawValue) machine.modified = Date() - os_log("Continue to trust machine ID: %@", log: tplogDebug, type: .default, String(describing: machine.machineID)) + os_log("Continue to trust machine ID: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) } } - } else { let machine = MachineMO(context: self.moc) machine.machineID = machineID @@ -229,7 +240,7 @@ extension Container { machine.seenOnFullList = false machine.modified = Date() machine.status = Int64(TPMachineIDStatus.allowed.rawValue) - os_log("Newly trusted machine ID: %@", log: tplogDebug, type: .default, String(describing: machine.machineID)) + os_log("Newly trusted machine ID: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) self.containerMO.addToMachines(machine) knownMachines.insert(machine) @@ -247,12 +258,12 @@ extension Container { func removeAllow(_ machineIDs: [String], reply: @escaping (Error?) -> Void) { self.semaphore.wait() let reply: (Error?) -> Void = { - os_log("removeAllow complete: %@", log: tplogTrace, type: .info, traceError($0)) + os_log("removeAllow complete: %{public}@", log: tplogTrace, type: .info, traceError($0)) self.semaphore.signal() reply($0) } - os_log("Removing allowed machine IDs: %@", log: tplogDebug, type: .default, machineIDs) + os_log("Removing allowed machine IDs: %{public}@", log: tplogDebug, type: .default, machineIDs) self.moc.performAndWait { do { @@ -268,17 +279,16 @@ extension Container { if machine.machineID == machineID { machine.status = Int64(TPMachineIDStatus.unknown.rawValue) machine.modified = Date.distantPast - os_log("Now suspicious of machine ID: %@", log: tplogDebug, type: .default, String(describing: machine.machineID)) + os_log("Now suspicious of machine ID: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) } } - } else { let machine = MachineMO(context: self.moc) machine.machineID = machineID machine.container = containerMO machine.status = Int64(TPMachineIDStatus.unknown.rawValue) machine.modified = Date.distantPast - os_log("Suspicious of new machine ID: %@", log: tplogDebug, type: .default, String(describing: machine.machineID)) + os_log("Suspicious of new machine ID: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) self.containerMO.addToMachines(machine) knownMachines.insert(machine) @@ -296,7 +306,7 @@ extension Container { func fetchAllowedMachineIDs(reply: @escaping (Set?, Error?) -> Void) { self.semaphore.wait() let reply: (Set?, Error?) -> Void = { - os_log("fetchAllowedMachineIDs complete: %@", log: tplogTrace, type: .info, traceError($1)) + os_log("fetchAllowedMachineIDs complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) self.semaphore.signal() reply($0, $1) } @@ -305,34 +315,34 @@ extension Container { self.moc.performAndWait { let knownMachines = containerMO.machines as? Set ?? Set() - let allowedMachineIDs = knownMachines.filter { $0.status == Int64(TPMachineIDStatus.allowed.rawValue) }.compactMap({ $0.machineID }) + let allowedMachineIDs = knownMachines.filter { $0.status == Int64(TPMachineIDStatus.allowed.rawValue) }.compactMap { $0.machineID } reply(Set(allowedMachineIDs), nil) } } func onqueueMachineIDAllowedByIDMS(machineID: String) -> Bool { + // For Demo accounts, if the list is entirely empty, then everything is allowed - let machines = containerMO.machines as? Set ?? Set() - if machines.count == 0 { - os_log("machineID list is empty; allowing %@", log: tplogDebug, type: .debug, machineID) + let knownMachines = containerMO.machines as? Set ?? Set() + + if !self.enforceIDMSListChanges(knownMachines: knownMachines) { + os_log("not enforcing idms list changes; allowing %{public}@", log: tplogDebug, type: .debug, machineID) return true } // Note: this function rejects grey devices: machineIDs that are neither allowed nor disallowed - for mo in machines { - if mo.machineID == machineID { - if mo.status == TPMachineIDStatus.allowed.rawValue { - return true - } else { - os_log("machineID %@ not explicitly allowed: %@", log: tplogDebug, type: .debug, machineID, mo) - return false - } + for mo in knownMachines where mo.machineID == machineID { + if mo.status == TPMachineIDStatus.allowed.rawValue { + return true + } else { + os_log("machineID %{public}@ not explicitly allowed: %{public}@", log: tplogDebug, type: .debug, machineID, mo) + return false } } // Didn't find it? reject. - os_log("machineID %@ not found on list", log: tplogDebug, type: .debug, machineID) + os_log("machineID %{public}@ not found on list", log: tplogDebug, type: .debug, machineID) return false } @@ -358,9 +368,9 @@ extension Container { let trustedMachineIDs = Set(dynamicInfo.includedPeerIDs.compactMap { self.model.peer(withID: $0)?.permanentInfo.machineID }) // if this account is not a demo account... - if machines.count > 0 { + if self.enforceIDMSListChanges(knownMachines: machines) { for peerMachineID in trustedMachineIDs.subtracting(knownMachineIDs) { - os_log("Peer machineID is unknown, beginning grace period: %@", log: tplogDebug, type: .default, peerMachineID) + os_log("Peer machineID is unknown, beginning grace period: %{public}@", log: tplogDebug, type: .default, peerMachineID) let machine = MachineMO(context: self.moc) machine.machineID = peerMachineID machine.container = self.containerMO @@ -371,14 +381,13 @@ extension Container { self.containerMO.addToMachines(machine) } } else { - os_log("Believe we're in a demo account; not starting an unknown machine ID timer", log: tplogDebug, type: .default) + os_log("Not enforcing IDMS list changes", log: tplogDebug, type: .default) } - for mo in (machines) { - if mo.status == TPMachineIDStatus.disallowed.rawValue { - os_log("Dropping knowledge of machineID %@", log: tplogDebug, type: .debug, String(describing: mo.machineID)) - self.containerMO.removeFromMachines(mo) - } + // Remove all disallowed MIDs, unless we continue to trust the peer for some other reason + for mo in (machines) where mo.status == TPMachineIDStatus.disallowed.rawValue && !trustedMachineIDs.contains(mo.machineID ?? "") { + os_log("Dropping knowledge of machineID %{public}@", log: tplogDebug, type: .debug, String(describing: mo.machineID)) + self.containerMO.removeFromMachines(mo) } } @@ -386,9 +395,14 @@ extension Container { // Useful means that there's an unknown MID whose modification date is before the cutoff // A full list fetch would either confirm it as 'untrusted' or make it trusted again func onqueueFullIDMSListWouldBeHelpful() -> Bool { + + if self.containerMO.honorIDMSListChanges == "UNKNOWN" { + return true + } + let unknownMOs = (containerMO.machines as? Set ?? Set()).filter { $0.status == TPMachineIDStatus.unknown.rawValue } let outdatedMOs = unknownMOs.filter { !$0.modifiedInPast(hours: cutoffHours) } - return outdatedMOs.count > 0 + return !outdatedMOs.isEmpty } } diff --git a/keychain/TrustedPeersHelper/Container_Peers.swift b/keychain/TrustedPeersHelper/Container_Peers.swift new file mode 100644 index 00000000..4c9903ed --- /dev/null +++ b/keychain/TrustedPeersHelper/Container_Peers.swift @@ -0,0 +1,42 @@ +import CloudKitCode +import CloudKitCodeProtobuf +import CoreData +import Foundation +import os +import Security +import SecurityFoundation + +extension Container { + internal static func removingDuplicates(vouchers: Set) -> Set { + var unique: Set = Set() + + for voucher in vouchers { + if !unique.contains(voucher) { + unique.insert(voucher) + } + } + return unique + } + + internal static func onqueueRemoveDuplicateVouchersPerPeer(container: ContainerMO, moc: NSManagedObjectContext) { + var peersWithUniqueSetOfVouchers: Set = Set() + let peers = container.peers as? Set ?? Set() + for peer in peers { + let vouchers = peer.vouchers as? Set ?? Set() + let uniqueSet = Container.removingDuplicates(vouchers: vouchers) + for voucher in vouchers { + peer.removeFromVouchers(voucher) + } + for voucher in uniqueSet { + peer.addToVouchers(voucher) + } + peersWithUniqueSetOfVouchers.insert(peer) + } + for peer in peers { + container.removeFromPeers(peer) + } + for peer in peersWithUniqueSetOfVouchers { + container.addToPeers(peer) + } + } +} diff --git a/keychain/TrustedPeersHelper/Container_RecoveryKey.swift b/keychain/TrustedPeersHelper/Container_RecoveryKey.swift new file mode 100644 index 00000000..0d7fe828 --- /dev/null +++ b/keychain/TrustedPeersHelper/Container_RecoveryKey.swift @@ -0,0 +1,92 @@ +import CoreData +import Foundation + +extension Container { + func preflightVouchWithRecoveryKey(recoveryKey: String, + salt: String, + reply: @escaping (String?, TPSyncingPolicy?, Error?) -> Void) { + self.semaphore.wait() + let reply: (String?, TPSyncingPolicy?, Error?) -> Void = { + os_log("preflightRecoveryKey complete: %{public}@", + log: tplogTrace, type: .info, traceError($2)) + self.semaphore.signal() + reply($0, $1, $2) + } + + self.fetchAndPersistChangesIfNeeded { fetchError in + guard fetchError == nil else { + os_log("preflightRecoveryKey unable to fetch current peers: %{public}@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "") + reply(nil, nil, fetchError) + return + } + + // Ensure we have all policy versions claimed by peers, including our sponsor + self.fetchPolicyDocumentsWithSemaphore(versions: self.model.allPolicyVersions()) { _, fetchPolicyDocumentsError in + guard fetchPolicyDocumentsError == nil else { + os_log("preflightRecoveryKey unable to fetch policy documents: %{public}@", log: tplogDebug, type: .default, (fetchPolicyDocumentsError as CVarArg?) ?? "no error") + reply(nil, nil, fetchPolicyDocumentsError) + return + } + + self.moc.performAndWait { + guard let egoPeerID = self.containerMO.egoPeerID, + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig else { + os_log("preflightRecoveryKey: no ego peer ID", log: tplogDebug, type: .default) + reply(nil, nil, ContainerError.noPreparedIdentity) + return + } + + let keyFactory = TPECPublicKeyFactory() + guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { + reply(nil, nil, ContainerError.invalidPermanentInfoOrSig) + return + } + + var recoveryKeys: RecoveryKey + do { + recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) + } catch { + os_log("preflightRecoveryKey: failed to create recovery keys: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, ContainerError.failedToCreateRecoveryKey) + return + } + + // Dear model: if i were to use this recovery key, what peers would I end up using? + guard self.model.isRecoveryKeyEnrolled() else { + os_log("preflightRecoveryKey: recovery Key is not enrolled", log: tplogDebug, type: .default) + reply(nil, nil, ContainerError.recoveryKeysNotEnrolled) + return + } + + guard let sponsorPeerID = self.model.peerIDThatTrustsRecoveryKeys(TPRecoveryKeyPair(signingKeyData: recoveryKeys.peerKeys.signingKey.publicKey.keyData, + encryptionKeyData: recoveryKeys.peerKeys.encryptionKey.publicKey.keyData)) else { + os_log("preflightRecoveryKey Untrusted recovery key set", log: tplogDebug, type: .default) + reply(nil, nil, ContainerError.untrustedRecoveryKeys) + return + } + + guard let sponsor = self.model.peer(withID: sponsorPeerID) else { + os_log("preflightRecoveryKey Failed to find peer with ID", log: tplogDebug, type: .default) + reply(nil, nil, ContainerError.sponsorNotRegistered(sponsorPeerID)) + return + } + + do { + let bestPolicy = try self.model.policy(forPeerIDs: sponsor.dynamicInfo?.includedPeerIDs ?? [sponsor.peerID], + candidatePeerID: egoPeerID, + candidateStableInfo: sponsor.stableInfo) + let syncingPolicy = try bestPolicy.syncingPolicy(forModel: selfPermanentInfo.modelID, + syncUserControllableViews: sponsor.stableInfo?.syncUserControllableViews ?? .UNKNOWN) + + reply(recoveryKeys.peerKeys.peerID, syncingPolicy, nil) + } catch { + os_log("preflightRecoveryKey: error fetching policy: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, error) + return + } + } + } + } + } +} diff --git a/keychain/TrustedPeersHelper/Container_UserSync.swift b/keychain/TrustedPeersHelper/Container_UserSync.swift new file mode 100644 index 00000000..498f4a7d --- /dev/null +++ b/keychain/TrustedPeersHelper/Container_UserSync.swift @@ -0,0 +1,41 @@ +import Foundation + +// Apple TVs and watches have no UI to enable or disable this status. +// So, help them out by ignoring all efforts. +extension TPPBPeerStableInfo_UserControllableViewStatus { + func sanitizeForPlatform(permanentInfo: TPPeerPermanentInfo) -> TPPBPeerStableInfo_UserControllableViewStatus { + // Unknown is the unknown for any platform + if self == .UNKNOWN { + return .UNKNOWN + } + + if permanentInfo.modelID.hasPrefix("AppleTV") || + permanentInfo.modelID.hasPrefix("AudioAccessory") { + // Apple TVs, and HomePods don't have UI to set this bit. So, they should always sync the + // user-controlled views to which they have access. + // + // Some watches don't have UI to set the bit, but some do. + // + // Note that we want this sanitization behavior to be baked into the local OS, which is what owns + // the UI software, and not in the Policy, which can change. + return .FOLLOWING + } else { + // All other platforms can choose their own fate + return self + } + } +} + +extension StableChanges { + static func change(viewStatus: TPPBPeerStableInfo_UserControllableViewStatus?) -> StableChanges? { + if viewStatus == nil { + return nil + } + return StableChanges(deviceName: nil, + serialNumber: nil, + osVersion: nil, + policyVersion: nil, + policySecrets: nil, + setSyncUserControllableViews: viewStatus) + } +} diff --git a/keychain/TrustedPeersHelper/CuttlefishErrors.swift b/keychain/TrustedPeersHelper/CuttlefishErrors.swift index 04d9b902..c10415de 100644 --- a/keychain/TrustedPeersHelper/CuttlefishErrors.swift +++ b/keychain/TrustedPeersHelper/CuttlefishErrors.swift @@ -5,7 +5,7 @@ struct CuttlefishErrorMatcher { } // Use a 'pattern match operator' to make pretty case statements matching Cuttlefish errors -func ~=(pattern: CuttlefishErrorMatcher, value: Error?) -> Bool { +func ~= (pattern: CuttlefishErrorMatcher, value: Error?) -> Bool { guard let error = value else { return false } diff --git a/keychain/TrustedPeersHelper/OctagonPeerKeys.swift b/keychain/TrustedPeersHelper/OctagonPeerKeys.swift index 535ef221..8014ccbb 100644 --- a/keychain/TrustedPeersHelper/OctagonPeerKeys.swift +++ b/keychain/TrustedPeersHelper/OctagonPeerKeys.swift @@ -29,7 +29,7 @@ class OctagonSelfPeerKeys: NSObject, CKKSSelfPeer { self.publicSigningKey = signingKey.publicKey as? _SFECPublicKey guard let encryptionVerificationKey = self.publicEncryptionKey, - let signingVerificationKey = self.publicSigningKey else { + let signingVerificationKey = self.publicSigningKey else { throw OctagonSelfPeerKeysError.noPublicKeys } diff --git a/keychain/TrustedPeersHelper/Policy.swift b/keychain/TrustedPeersHelper/Policy.swift index 2cbece09..b319a3ca 100644 --- a/keychain/TrustedPeersHelper/Policy.swift +++ b/keychain/TrustedPeersHelper/Policy.swift @@ -24,22 +24,23 @@ import Foundation struct RawPolicy { - let policyVersion: Int - let policyHash: String + let version: TPPolicyVersion let policyData: String let plaintextPolicy: TPPolicyDocument } -let prevailingPolicyVersion: UInt64 = 5 -let prevailingPolicyHash: String = "SHA256:O/ECQlWhvNlLmlDNh2+nal/yekUC87bXpV3k+6kznSo=" +let prevailingPolicyVersion = TPPolicyVersion(version: 9, hash: "SHA256:uynvb6IWdFbCM2AQX0aKv0yUMLg8Z2wZjZY5k4jtAj8=") + +// Some peers don't know how to handle new policies when pairing. If we're pairing with one of those, +// we must prepare our identity using this policy. +let frozenPolicyVersion = TPPolicyVersion(version: 5, hash: "SHA256:O/ECQlWhvNlLmlDNh2+nal/yekUC87bXpV3k+6kznSo=") func builtInPolicyDocuments() -> [TPPolicyDocument] { - + // swiftlint:disable force_try // These bytes are generated by tppolicy let rawPolicies = [ RawPolicy( - policyVersion: 1, - policyHash: "SHA256:TLXrcQmY4ue3oP5pCX1pwsi9BF8cKfohlJBilCroeBs=", + version: TPPolicyVersion(version: 1, hash: "SHA256:TLXrcQmY4ue3oP5pCX1pwsi9BF8cKfohlJBilCroeBs="), policyData: "CAESDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSCwoDTWFjEgRmdWxsEgwKBGlNYWMSBGZ1bGwSDQoHQXBwbGVUVhICdHYSDgoFV2F0Y2gSBXdhdGNoGhEKCVBDU0VzY3JvdxIEZnVsbBoXCgRXaUZpEgRmdWxsEgJ0dhIFd2F0Y2gaGQoRU2FmYXJpQ3JlZGl0Q2FyZHMSBGZ1bGwiDAoEZnVsbBIEZnVsbCIUCgV3YXRjaBIEZnVsbBIFd2F0Y2giDgoCdHYSBGZ1bGwSAnR2", plaintextPolicy: try! TPPolicyDocument(version: 1, modelToCategory: [ @@ -62,12 +63,14 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { ], redactions: [:], keyViewMapping: [], + userControllableViewList: [], + piggybackViews: [], + priorityViews: [], hashAlgo: .SHA256) ), RawPolicy( - policyVersion: 2, - policyHash: "SHA256:ZL1WBUCyO155rHBJQeghomCCKGmfjtS0jvsK+UEvx5o=", + version: TPPolicyVersion(version: 2, hash: "SHA256:ZL1WBUCyO155rHBJQeghomCCKGmfjtS0jvsK+UEvx5o="), policyData: "CAISDgoGaUN5Y2xlEgRmdWxsEg4KBmlQaG9uZRIEZnVsbBIMCgRpUGFkEgRmdWxsEgsKA01hYxIEZnVsbBIMCgRpTWFjEgRmdWxsEg0KB0FwcGxlVFYSAnR2Eg4KBVdhdGNoEgV3YXRjaBoRCglQQ1NFc2Nyb3cSBGZ1bGwaFwoEV2lGaRIEZnVsbBICdHYSBXdhdGNoGhkKEVNhZmFyaUNyZWRpdENhcmRzEgRmdWxsIgwKBGZ1bGwSBGZ1bGwiFAoFd2F0Y2gSBGZ1bGwSBXdhdGNoIg4KAnR2EgRmdWxsEgJ0dg==", plaintextPolicy: try! TPPolicyDocument(version: 2, modelToCategory: [ @@ -91,11 +94,13 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { ], redactions: [:], keyViewMapping: [], + userControllableViewList: [], + piggybackViews: [], + priorityViews: [], hashAlgo: .SHA256) ), - RawPolicy(policyVersion: 3, - policyHash: "SHA256:JZzazSuHXrUhiOfSgElsg6vYKpnvvEPVpciR8FewRWg=", + RawPolicy(version: TPPolicyVersion(version: 3, hash: "SHA256:JZzazSuHXrUhiOfSgElsg6vYKpnvvEPVpciR8FewRWg="), policyData: "CAMSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSCwoDTWFjEgRmdWxsEgwKBGlNYWMSBGZ1bGwSDQoHQXBwbGVUVhICdHYSDgoFV2F0Y2gSBXdhdGNoEhcKDkF1ZGlvQWNjZXNzb3J5EgVhdWRpbxocCg1EZXZpY2VQYWlyaW5nEgRmdWxsEgV3YXRjaBoXCghBcHBsZVBheRIEZnVsbBIFd2F0Y2gaJAoVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlEgRmdWxsEgV3YXRjaBoXCghCYWNrc3RvcBIEZnVsbBIFd2F0Y2gaGQoKQXV0b1VubG9jaxIEZnVsbBIFd2F0Y2gaHwoQU2VjdXJlT2JqZWN0U3luYxIEZnVsbBIFd2F0Y2gaIAoRU2FmYXJpQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoGhMKBEhvbWUSBGZ1bGwSBXdhdGNoGh4KD1NhZmFyaVBhc3N3b3JkcxIEZnVsbBIFd2F0Y2gaGwoMQXBwbGljYXRpb25zEgRmdWxsEgV3YXRjaBoVCgZFbmdyYW0SBGZ1bGwSBXdhdGNoGi0KE0xpbWl0ZWRQZWVyc0FsbG93ZWQSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aFgoHTWFuYXRlZRIEZnVsbBIFd2F0Y2gaHgoEV2lGaRIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxoVCgZIZWFsdGgSBGZ1bGwSBXdhdGNoIhMKBGZ1bGwSBGZ1bGwSBXdhdGNoIhsKBWF1ZGlvEgRmdWxsEgV3YXRjaBIFYXVkaW8iFAoFd2F0Y2gSBGZ1bGwSBXdhdGNoIhUKAnR2EgRmdWxsEgV3YXRjaBICdHYyIgoWAAQiEgIEdndodAoKXkFwcGxlUGF5JBIIQXBwbGVQYXkyJgoYAAQiFAIEdndodAoMXkF1dG9VbmxvY2skEgpBdXRvVW5sb2NrMh4KFAAEIhACBHZ3aHQKCF5FbmdyYW0kEgZFbmdyYW0yHgoUAAQiEAIEdndodAoIXkhlYWx0aCQSBkhlYWx0aDIaChIABCIOAgR2d2h0CgZeSG9tZSQSBEhvbWUyIAoVAAQiEQIEdndodAoJXk1hbmF0ZWUkEgdNYW5hdGVlMjgKIQAEIh0CBHZ3aHQKFV5MaW1pdGVkUGVlcnNBbGxvd2VkJBITTGltaXRlZFBlZXJzQWxsb3dlZDJdClAAAhIeAAQiGgIEdndodAoSXkNvbnRpbnVpdHlVbmxvY2skEhUABCIRAgR2d2h0CgleSG9tZUtpdCQSFQAEIhECBHZ3aHQKCV5BcHBsZVRWJBIJTm90U3luY2VkMisKGwAEIhcCBGFncnAKD15bMC05QS1aXXsxMH1cLhIMQXBwbGljYXRpb25zMsUBCrABAAISNAABChMABCIPAgVjbGFzcwoGXmdlbnAkChsABCIXAgRhZ3JwCg9eY29tLmFwcGxlLnNiZCQSPQABChMABCIPAgVjbGFzcwoGXmtleXMkCiQABCIgAgRhZ3JwChheY29tLmFwcGxlLnNlY3VyaXR5LnNvcyQSGQAEIhUCBHZ3aHQKDV5CYWNrdXBCYWdWMCQSHAAEIhgCBHZ3aHQKEF5pQ2xvdWRJZGVudGl0eSQSEFNlY3VyZU9iamVjdFN5bmMyYwpbAAISEgAEIg4CBHZ3aHQKBl5XaUZpJBJDAAEKEwAEIg8CBWNsYXNzCgZeZ2VucCQKEwAEIg8CBGFncnAKB15hcHBsZSQKFQAEIhECBHN2Y2UKCV5BaXJQb3J0JBIEV2lGaTLbAgrBAgACEhkABCIVAgR2d2h0Cg1eUENTQ2xvdWRLaXQkEhcABCITAgR2d2h0CgteUENTRXNjcm93JBIUAAQiEAIEdndodAoIXlBDU0ZERSQSGQAEIhUCBHZ3aHQKDV5QQ1NGZWxkc3BhciQSGQAEIhUCBHZ3aHQKDV5QQ1NNYWlsRHJvcCQSGgAEIhYCBHZ3aHQKDl5QQ1NNYXN0ZXJLZXkkEhYABCISAgR2d2h0CgpeUENTTm90ZXMkEhcABCITAgR2d2h0CgteUENTUGhvdG9zJBIYAAQiFAIEdndodAoMXlBDU1NoYXJpbmckEh0ABCIZAgR2d2h0ChFeUENTaUNsb3VkQmFja3VwJBIcAAQiGAIEdndodAoQXlBDU2lDbG91ZERyaXZlJBIZAAQiFQIEdndodAoNXlBDU2lNZXNzYWdlJBIVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlMkAKKwAEIicCBGFncnAKH15jb20uYXBwbGUuc2FmYXJpLmNyZWRpdC1jYXJkcyQSEVNhZmFyaUNyZWRpdENhcmRzMjQKIQAEIh0CBGFncnAKFV5jb20uYXBwbGUuY2ZuZXR3b3JrJBIPU2FmYXJpUGFzc3dvcmRzMm0KXAACEh4ABCIaAgR2d2h0ChJeQWNjZXNzb3J5UGFpcmluZyQSGgAEIhYCBHZ3aHQKDl5OYW5vUmVnaXN0cnkkEhwABCIYAgR2d2h0ChBeV2F0Y2hNaWdyYXRpb24kEg1EZXZpY2VQYWlyaW5nMi0KIQAEIh0CBGFncnAKFV5jb20uYXBwbGUuY2ZuZXR3b3JrJBIIQmFja3N0b3A=", plaintextPolicy: try! TPPolicyDocument(version: 3, modelToCategory: [ @@ -208,10 +213,12 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com.apple.cfnetwork$")), ], + userControllableViewList: [], + piggybackViews: [], + priorityViews: [], hashAlgo: .SHA256) ), - RawPolicy(policyVersion: 4, - policyHash: "SHA256:Tjdu5QrWGvKWMx7k3VWFrEWSsBDPZAwCql9ybDkvFs8=", + RawPolicy(version: TPPolicyVersion(version: 4, hash: "SHA256:Tjdu5QrWGvKWMx7k3VWFrEWSsBDPZAwCql9ybDkvFs8="), policyData: "CAQSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSCwoDTWFjEgRmdWxsEgwKBGlNYWMSBGZ1bGwSDQoHQXBwbGVUVhICdHYSDgoFV2F0Y2gSBXdhdGNoEhcKDkF1ZGlvQWNjZXNzb3J5EgVhdWRpbxoTCgRIb21lEgRmdWxsEgV3YXRjaBobCgxBcHBsaWNhdGlvbnMSBGZ1bGwSBXdhdGNoGh4KBFdpRmkSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aGQoKQXV0b1VubG9jaxIEZnVsbBIFd2F0Y2gaFwoIQXBwbGVQYXkSBGZ1bGwSBXdhdGNoGhUKBkhlYWx0aBIEZnVsbBIFd2F0Y2gaFgoHTWFuYXRlZRIEZnVsbBIFd2F0Y2gaLQoTTGltaXRlZFBlZXJzQWxsb3dlZBIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxokChVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2USBGZ1bGwSBXdhdGNoGhgKCVBhc3N3b3JkcxIEZnVsbBIFd2F0Y2gaHAoNRGV2aWNlUGFpcmluZxIEZnVsbBIFd2F0Y2gaHwoQU2VjdXJlT2JqZWN0U3luYxIEZnVsbBIFd2F0Y2gaFQoGRW5ncmFtEgRmdWxsEgV3YXRjaBoaCgtDcmVkaXRDYXJkcxIEZnVsbBIFd2F0Y2giGwoFYXVkaW8SBGZ1bGwSBXdhdGNoEgVhdWRpbyITCgRmdWxsEgRmdWxsEgV3YXRjaCIUCgV3YXRjaBIEZnVsbBIFd2F0Y2giFQoCdHYSBGZ1bGwSBXdhdGNoEgJ0djIiChYABCISAgR2d2h0CgpeQXBwbGVQYXkkEghBcHBsZVBheTImChgABCIUAgR2d2h0CgxeQXV0b1VubG9jayQSCkF1dG9VbmxvY2syHgoUAAQiEAIEdndodAoIXkVuZ3JhbSQSBkVuZ3JhbTIeChQABCIQAgR2d2h0CgheSGVhbHRoJBIGSGVhbHRoMhoKEgAEIg4CBHZ3aHQKBl5Ib21lJBIESG9tZTIgChUABCIRAgR2d2h0CgleTWFuYXRlZSQSB01hbmF0ZWUyOAohAAQiHQIEdndodAoVXkxpbWl0ZWRQZWVyc0FsbG93ZWQkEhNMaW1pdGVkUGVlcnNBbGxvd2VkMl0KUAACEh4ABCIaAgR2d2h0ChJeQ29udGludWl0eVVubG9jayQSFQAEIhECBHZ3aHQKCV5Ib21lS2l0JBIVAAQiEQIEdndodAoJXkFwcGxlVFYkEglOb3RTeW5jZWQyKwobAAQiFwIEYWdycAoPXlswLTlBLVpdezEwfVwuEgxBcHBsaWNhdGlvbnMyxQEKsAEAAhI0AAEKEwAEIg8CBWNsYXNzCgZeZ2VucCQKGwAEIhcCBGFncnAKD15jb20uYXBwbGUuc2JkJBI9AAEKEwAEIg8CBWNsYXNzCgZea2V5cyQKJAAEIiACBGFncnAKGF5jb20uYXBwbGUuc2VjdXJpdHkuc29zJBIZAAQiFQIEdndodAoNXkJhY2t1cEJhZ1YwJBIcAAQiGAIEdndodAoQXmlDbG91ZElkZW50aXR5JBIQU2VjdXJlT2JqZWN0U3luYzJjClsAAhISAAQiDgIEdndodAoGXldpRmkkEkMAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAoTAAQiDwIEYWdycAoHXmFwcGxlJAoVAAQiEQIEc3ZjZQoJXkFpclBvcnQkEgRXaUZpMucCCs0CAAISGgAEIhYCBHZ3aHQKDl5QQ1MtQ2xvdWRLaXQkEhgABCIUAgR2d2h0CgxeUENTLUVzY3JvdyQSFQAEIhECBHZ3aHQKCV5QQ1MtRkRFJBIaAAQiFgIEdndodAoOXlBDUy1GZWxkc3BhciQSGgAEIhYCBHZ3aHQKDl5QQ1MtTWFpbERyb3AkEhsABCIXAgR2d2h0Cg9eUENTLU1hc3RlcktleSQSFwAEIhMCBHZ3aHQKC15QQ1MtTm90ZXMkEhgABCIUAgR2d2h0CgxeUENTLVBob3RvcyQSGQAEIhUCBHZ3aHQKDV5QQ1MtU2hhcmluZyQSHgAEIhoCBHZ3aHQKEl5QQ1MtaUNsb3VkQmFja3VwJBIdAAQiGQIEdndodAoRXlBDUy1pQ2xvdWREcml2ZSQSGgAEIhYCBHZ3aHQKDl5QQ1MtaU1lc3NhZ2UkEhVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2UyOgorAAQiJwIEYWdycAofXmNvbS5hcHBsZS5zYWZhcmkuY3JlZGl0LWNhcmRzJBILQ3JlZGl0Q2FyZHMyLgohAAQiHQIEYWdycAoVXmNvbS5hcHBsZS5jZm5ldHdvcmskEglQYXNzd29yZHMybQpcAAISHgAEIhoCBHZ3aHQKEl5BY2Nlc3NvcnlQYWlyaW5nJBIaAAQiFgIEdndodAoOXk5hbm9SZWdpc3RyeSQSHAAEIhgCBHZ3aHQKEF5XYXRjaE1pZ3JhdGlvbiQSDURldmljZVBhaXJpbmc=", plaintextPolicy: try! TPPolicyDocument(version: 4, modelToCategory: [ @@ -319,11 +326,13 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WatchMigration$"), ])), ], + userControllableViewList: [], + piggybackViews: [], + priorityViews: [], hashAlgo: .SHA256) ), - RawPolicy(policyVersion: 5, - policyHash: "SHA256:O/ECQlWhvNlLmlDNh2+nal/yekUC87bXpV3k+6kznSo=", + RawPolicy(version: TPPolicyVersion(version: 5, hash: "SHA256:O/ECQlWhvNlLmlDNh2+nal/yekUC87bXpV3k+6kznSo="), policyData: "CAUSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGhsKDEFwcGxpY2F0aW9ucxIEZnVsbBIFd2F0Y2gaHwoQU2VjdXJlT2JqZWN0U3luYxIEZnVsbBIFd2F0Y2gaHAoNRGV2aWNlUGFpcmluZxIEZnVsbBIFd2F0Y2gaGgoLQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoGhUKBkhlYWx0aBIEZnVsbBIFd2F0Y2gaLQoTTGltaXRlZFBlZXJzQWxsb3dlZBIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxokChVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2USBGZ1bGwSBXdhdGNoGhcKCEFwcGxlUGF5EgRmdWxsEgV3YXRjaBoZCgpBdXRvVW5sb2NrEgRmdWxsEgV3YXRjaBoWCgdNYW5hdGVlEgRmdWxsEgV3YXRjaBoYCglQYXNzd29yZHMSBGZ1bGwSBXdhdGNoGhUKBkVuZ3JhbRIEZnVsbBIFd2F0Y2gaHgoEV2lGaRIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxoTCgRIb21lEgRmdWxsEgV3YXRjaCIbCgVhdWRpbxIEZnVsbBIFd2F0Y2gSBWF1ZGlvIhMKBGZ1bGwSBGZ1bGwSBXdhdGNoIhUKAnR2EgRmdWxsEgV3YXRjaBICdHYiFAoFd2F0Y2gSBGZ1bGwSBXdhdGNoMiIKFgAEIhICBHZ3aHQKCl5BcHBsZVBheSQSCEFwcGxlUGF5MiYKGAAEIhQCBHZ3aHQKDF5BdXRvVW5sb2NrJBIKQXV0b1VubG9jazIeChQABCIQAgR2d2h0CgheRW5ncmFtJBIGRW5ncmFtMh4KFAAEIhACBHZ3aHQKCF5IZWFsdGgkEgZIZWFsdGgyGgoSAAQiDgIEdndodAoGXkhvbWUkEgRIb21lMiAKFQAEIhECBHZ3aHQKCV5NYW5hdGVlJBIHTWFuYXRlZTI4CiEABCIdAgR2d2h0ChVeTGltaXRlZFBlZXJzQWxsb3dlZCQSE0xpbWl0ZWRQZWVyc0FsbG93ZWQyXQpQAAISHgAEIhoCBHZ3aHQKEl5Db250aW51aXR5VW5sb2NrJBIVAAQiEQIEdndodAoJXkhvbWVLaXQkEhUABCIRAgR2d2h0CgleQXBwbGVUViQSCU5vdFN5bmNlZDIrChsABCIXAgRhZ3JwCg9eWzAtOUEtWl17MTB9XC4SDEFwcGxpY2F0aW9uczLFAQqwAQACEjQAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAobAAQiFwIEYWdycAoPXmNvbS5hcHBsZS5zYmQkEj0AAQoTAAQiDwIFY2xhc3MKBl5rZXlzJAokAAQiIAIEYWdycAoYXmNvbS5hcHBsZS5zZWN1cml0eS5zb3MkEhkABCIVAgR2d2h0Cg1eQmFja3VwQmFnVjAkEhwABCIYAgR2d2h0ChBeaUNsb3VkSWRlbnRpdHkkEhBTZWN1cmVPYmplY3RTeW5jMmMKWwACEhIABCIOAgR2d2h0CgZeV2lGaSQSQwABChMABCIPAgVjbGFzcwoGXmdlbnAkChMABCIPAgRhZ3JwCgdeYXBwbGUkChUABCIRAgRzdmNlCgleQWlyUG9ydCQSBFdpRmkynQMKgwMAAhIYAAQiFAIEdndodAoMXlBDUy1CYWNrdXAkEhoABCIWAgR2d2h0Cg5eUENTLUNsb3VkS2l0JBIYAAQiFAIEdndodAoMXlBDUy1Fc2Nyb3ckEhUABCIRAgR2d2h0CgleUENTLUZERSQSGgAEIhYCBHZ3aHQKDl5QQ1MtRmVsZHNwYXIkEhoABCIWAgR2d2h0Cg5eUENTLU1haWxEcm9wJBIaAAQiFgIEdndodAoOXlBDUy1NYWlsZHJvcCQSGwAEIhcCBHZ3aHQKD15QQ1MtTWFzdGVyS2V5JBIXAAQiEwIEdndodAoLXlBDUy1Ob3RlcyQSGAAEIhQCBHZ3aHQKDF5QQ1MtUGhvdG9zJBIZAAQiFQIEdndodAoNXlBDUy1TaGFyaW5nJBIeAAQiGgIEdndodAoSXlBDUy1pQ2xvdWRCYWNrdXAkEh0ABCIZAgR2d2h0ChFeUENTLWlDbG91ZERyaXZlJBIaAAQiFgIEdndodAoOXlBDUy1pTWVzc2FnZSQSFVByb3RlY3RlZENsb3VkU3RvcmFnZTI6CisABCInAgRhZ3JwCh9eY29tLmFwcGxlLnNhZmFyaS5jcmVkaXQtY2FyZHMkEgtDcmVkaXRDYXJkczIuCiEABCIdAgRhZ3JwChVeY29tLmFwcGxlLmNmbmV0d29yayQSCVBhc3N3b3JkczJtClwAAhIeAAQiGgIEdndodAoSXkFjY2Vzc29yeVBhaXJpbmckEhoABCIWAgR2d2h0Cg5eTmFub1JlZ2lzdHJ5JBIcAAQiGAIEdndodAoQXldhdGNoTWlncmF0aW9uJBINRGV2aWNlUGFpcmluZzIOCgIABhIIQmFja3N0b3A=", plaintextPolicy: try! TPPolicyDocument(version: 5, modelToCategory: [ @@ -437,18 +446,552 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: TPDictionaryMatchingRule.trueMatch()), ], + userControllableViewList: [], + piggybackViews: [], + priorityViews: [], hashAlgo: .SHA256) ), - ] - assert(rawPolicies.filter { prevailingPolicyVersion == $0.policyVersion }.count == 1) + RawPolicy(version: TPPolicyVersion(version: 6, hash: "SHA256:L2Px1aYyR1tgChe8dIyTBSmCHCWEFJirZ3ELMFXz2PY="), + policyData: "CAYSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGhoKC0NyZWRpdENhcmRzEgRmdWxsEgV3YXRjaBofChBTZWN1cmVPYmplY3RTeW5jEgRmdWxsEgV3YXRjaBoVCgZIZWFsdGgSBGZ1bGwSBXdhdGNoGhkKCkF1dG9VbmxvY2sSBGZ1bGwSBXdhdGNoGh4KBFdpRmkSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aHgoESG9tZRIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxokChVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2USBGZ1bGwSBXdhdGNoGi0KE0xpbWl0ZWRQZWVyc0FsbG93ZWQSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aGAoJUGFzc3dvcmRzEgRmdWxsEgV3YXRjaBobCgxBcHBsaWNhdGlvbnMSBGZ1bGwSBXdhdGNoGhwKDURldmljZVBhaXJpbmcSBGZ1bGwSBXdhdGNoGhcKCEFwcGxlUGF5EgRmdWxsEgV3YXRjaBoWCgdNYW5hdGVlEgRmdWxsEgV3YXRjaBoVCgZFbmdyYW0SBGZ1bGwSBXdhdGNoIhsKBWF1ZGlvEgRmdWxsEgV3YXRjaBIFYXVkaW8iFQoCdHYSBGZ1bGwSBXdhdGNoEgJ0diIUCgV3YXRjaBIEZnVsbBIFd2F0Y2giEwoEZnVsbBIEZnVsbBIFd2F0Y2gyIgoWAAQiEgIEdndodAoKXkFwcGxlUGF5JBIIQXBwbGVQYXkyJgoYAAQiFAIEdndodAoMXkF1dG9VbmxvY2skEgpBdXRvVW5sb2NrMh4KFAAEIhACBHZ3aHQKCF5FbmdyYW0kEgZFbmdyYW0yHgoUAAQiEAIEdndodAoIXkhlYWx0aCQSBkhlYWx0aDIaChIABCIOAgR2d2h0CgZeSG9tZSQSBEhvbWUyIAoVAAQiEQIEdndodAoJXk1hbmF0ZWUkEgdNYW5hdGVlMjgKIQAEIh0CBHZ3aHQKFV5MaW1pdGVkUGVlcnNBbGxvd2VkJBITTGltaXRlZFBlZXJzQWxsb3dlZDJdClAAAhIeAAQiGgIEdndodAoSXkNvbnRpbnVpdHlVbmxvY2skEhUABCIRAgR2d2h0CgleSG9tZUtpdCQSFQAEIhECBHZ3aHQKCV5BcHBsZVRWJBIJTm90U3luY2VkMisKGwAEIhcCBGFncnAKD15bMC05QS1aXXsxMH1cLhIMQXBwbGljYXRpb25zMsoBCrUBAAISNgABChMABCIPAgVjbGFzcwoGXmdlbnAkCh0ABCIZAgRhZ3JwChFeY29tXC5hcHBsZVwuc2JkJBJAAAEKEwAEIg8CBWNsYXNzCgZea2V5cyQKJwAEIiMCBGFncnAKG15jb21cLmFwcGxlXC5zZWN1cml0eVwuc29zJBIZAAQiFQIEdndodAoNXkJhY2t1cEJhZ1YwJBIcAAQiGAIEdndodAoQXmlDbG91ZElkZW50aXR5JBIQU2VjdXJlT2JqZWN0U3luYzJjClsAAhISAAQiDgIEdndodAoGXldpRmkkEkMAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAoTAAQiDwIEYWdycAoHXmFwcGxlJAoVAAQiEQIEc3ZjZQoJXkFpclBvcnQkEgRXaUZpMp0DCoMDAAISGAAEIhQCBHZ3aHQKDF5QQ1MtQmFja3VwJBIaAAQiFgIEdndodAoOXlBDUy1DbG91ZEtpdCQSGAAEIhQCBHZ3aHQKDF5QQ1MtRXNjcm93JBIVAAQiEQIEdndodAoJXlBDUy1GREUkEhoABCIWAgR2d2h0Cg5eUENTLUZlbGRzcGFyJBIaAAQiFgIEdndodAoOXlBDUy1NYWlsRHJvcCQSGgAEIhYCBHZ3aHQKDl5QQ1MtTWFpbGRyb3AkEhsABCIXAgR2d2h0Cg9eUENTLU1hc3RlcktleSQSFwAEIhMCBHZ3aHQKC15QQ1MtTm90ZXMkEhgABCIUAgR2d2h0CgxeUENTLVBob3RvcyQSGQAEIhUCBHZ3aHQKDV5QQ1MtU2hhcmluZyQSHgAEIhoCBHZ3aHQKEl5QQ1MtaUNsb3VkQmFja3VwJBIdAAQiGQIEdndodAoRXlBDUy1pQ2xvdWREcml2ZSQSGgAEIhYCBHZ3aHQKDl5QQ1MtaU1lc3NhZ2UkEhVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2UyPQouAAQiKgIEYWdycAoiXmNvbVwuYXBwbGVcLnNhZmFyaVwuY3JlZGl0LWNhcmRzJBILQ3JlZGl0Q2FyZHMyMAojAAQiHwIEYWdycAoXXmNvbVwuYXBwbGVcLmNmbmV0d29yayQSCVBhc3N3b3JkczJtClwAAhIeAAQiGgIEdndodAoSXkFjY2Vzc29yeVBhaXJpbmckEhoABCIWAgR2d2h0Cg5eTmFub1JlZ2lzdHJ5JBIcAAQiGAIEdndodAoQXldhdGNoTWlncmF0aW9uJBINRGV2aWNlUGFpcmluZzIOCgIABhIIQmFja3N0b3A=", + plaintextPolicy: try! TPPolicyDocument(version: 6, + modelToCategory: [ + ["prefix": "iPhone", "category": "full"], + ["prefix": "iPad", "category": "full"], + ["prefix": "iPod", "category": "full"], + ["prefix": "Mac", "category": "full"], + ["prefix": "iMac", "category": "full"], + ["prefix": "AppleTV", "category": "tv"], + ["prefix": "Watch", "category": "watch"], + ["prefix": "AudioAccessory", "category": "audio"], + ], + categoriesByView: [ + "AutoUnlock": ["full", "watch"], + "ApplePay": ["full", "watch"], + "Engram": ["full", "watch"], + "Health": ["full", "watch"], + "Home": ["full", "watch", "tv", "audio"], + "LimitedPeersAllowed": ["full", "watch", "tv", "audio"], + "Manatee": ["full", "watch"], + "Applications": ["full", "watch"], + "SecureObjectSync": ["full", "watch"], + "WiFi": ["full", "watch", "tv", "audio"], + "ProtectedCloudStorage": ["full", "watch"], + "CreditCards": ["full", "watch"], + "Passwords": ["full", "watch"], + "DevicePairing": ["full", "watch"], + ], + introducersByCategory: [ + "full": ["full", "watch"], + "watch": ["full", "watch"], + "tv": ["full", "watch", "tv"], + "audio": ["full", "watch", "audio"], + ], + redactions: [:], + keyViewMapping: [ + TPPBPolicyKeyViewMapping(view: "ApplePay", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ApplePay$")), + TPPBPolicyKeyViewMapping(view: "AutoUnlock", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AutoUnlock$")), + TPPBPolicyKeyViewMapping(view: "Engram", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Engram$")), + TPPBPolicyKeyViewMapping(view: "Health", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Health$")), + TPPBPolicyKeyViewMapping(view: "Home", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Home$")), + TPPBPolicyKeyViewMapping(view: "Manatee", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Manatee$")), + TPPBPolicyKeyViewMapping(view: "LimitedPeersAllowed", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^LimitedPeersAllowed$")), + + // These items will not be synced by Octagon + TPPBPolicyKeyViewMapping(view: "NotSynced", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ContinuityUnlock$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^HomeKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AppleTV$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Applications", matchingRule: + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^[0-9A-Z]{10}\\.")), + + TPPBPolicyKeyViewMapping(view: "SecureObjectSync", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.sbd$"), + ]), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^keys$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.security\\.sos$"), + ]), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^BackupBagV0$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^iCloudIdentity$"), + ])), + + TPPBPolicyKeyViewMapping(view: "WiFi", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WiFi$"), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^apple$"), + TPDictionaryMatchingRule.fieldMatch("svce", fieldRegex: "^AirPort$"), + ]), + ])), + + TPPBPolicyKeyViewMapping(view: "ProtectedCloudStorage", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Backup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-CloudKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Escrow$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-FDE$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Feldspar$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MailDrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Maildrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MasterKey$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Notes$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Photos$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Sharing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudBackup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudDrive$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iMessage$"), + ])), + + TPPBPolicyKeyViewMapping(view: "CreditCards", + matchingRule: TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.safari\\.credit-cards$")), + + TPPBPolicyKeyViewMapping(view: "Passwords", + matchingRule: TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.cfnetwork$")), + + TPPBPolicyKeyViewMapping(view: "DevicePairing", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AccessoryPairing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^NanoRegistry$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WatchMigration$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: + TPDictionaryMatchingRule.trueMatch()), + ], + userControllableViewList: [], + piggybackViews: [], + priorityViews: [], + hashAlgo: .SHA256) + ), + RawPolicy(version: TPPolicyVersion(version: 7, hash: "SHA256:dL8Qujqzprhp6FdH5GzNMtPlnZtLWMwfiiF7aykr8WU="), + policyData: "CAcSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGh4KBEhvbWUSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aJAoVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlEgRmdWxsEgV3YXRjaBoYCglQYXNzd29yZHMSBGZ1bGwSBXdhdGNoGh8KEFNlY3VyZU9iamVjdFN5bmMSBGZ1bGwSBXdhdGNoGh4KBFdpRmkSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aGgoLQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoGhcKCEFwcGxlUGF5EgRmdWxsEgV3YXRjaBoVCgZIZWFsdGgSBGZ1bGwSBXdhdGNoGhkKCkF1dG9VbmxvY2sSBGZ1bGwSBXdhdGNoGi0KE0xpbWl0ZWRQZWVyc0FsbG93ZWQSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aHAoNRGV2aWNlUGFpcmluZxIEZnVsbBIFd2F0Y2gaFgoHTWFuYXRlZRIEZnVsbBIFd2F0Y2gaFQoGRW5ncmFtEgRmdWxsEgV3YXRjaBoXCghCYWNrc3RvcBIEZnVsbBIFd2F0Y2gaGwoMQXBwbGljYXRpb25zEgRmdWxsEgV3YXRjaCITCgRmdWxsEgRmdWxsEgV3YXRjaCIVCgJ0dhIEZnVsbBIFd2F0Y2gSAnR2IhQKBXdhdGNoEgRmdWxsEgV3YXRjaCIbCgVhdWRpbxIEZnVsbBIFd2F0Y2gSBWF1ZGlvMiIKFgAEIhICBHZ3aHQKCl5BcHBsZVBheSQSCEFwcGxlUGF5MiYKGAAEIhQCBHZ3aHQKDF5BdXRvVW5sb2NrJBIKQXV0b1VubG9jazIeChQABCIQAgR2d2h0CgheRW5ncmFtJBIGRW5ncmFtMh4KFAAEIhACBHZ3aHQKCF5IZWFsdGgkEgZIZWFsdGgyGgoSAAQiDgIEdndodAoGXkhvbWUkEgRIb21lMiAKFQAEIhECBHZ3aHQKCV5NYW5hdGVlJBIHTWFuYXRlZTI4CiEABCIdAgR2d2h0ChVeTGltaXRlZFBlZXJzQWxsb3dlZCQSE0xpbWl0ZWRQZWVyc0FsbG93ZWQyXQpQAAISHgAEIhoCBHZ3aHQKEl5Db250aW51aXR5VW5sb2NrJBIVAAQiEQIEdndodAoJXkhvbWVLaXQkEhUABCIRAgR2d2h0CgleQXBwbGVUViQSCU5vdFN5bmNlZDIrChsABCIXAgRhZ3JwCg9eWzAtOUEtWl17MTB9XC4SDEFwcGxpY2F0aW9uczLKAQq1AQACEjYAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAodAAQiGQIEYWdycAoRXmNvbVwuYXBwbGVcLnNiZCQSQAABChMABCIPAgVjbGFzcwoGXmtleXMkCicABCIjAgRhZ3JwChteY29tXC5hcHBsZVwuc2VjdXJpdHlcLnNvcyQSGQAEIhUCBHZ3aHQKDV5CYWNrdXBCYWdWMCQSHAAEIhgCBHZ3aHQKEF5pQ2xvdWRJZGVudGl0eSQSEFNlY3VyZU9iamVjdFN5bmMyYwpbAAISEgAEIg4CBHZ3aHQKBl5XaUZpJBJDAAEKEwAEIg8CBWNsYXNzCgZeZ2VucCQKEwAEIg8CBGFncnAKB15hcHBsZSQKFQAEIhECBHN2Y2UKCV5BaXJQb3J0JBIEV2lGaTKdAwqDAwACEhgABCIUAgR2d2h0CgxeUENTLUJhY2t1cCQSGgAEIhYCBHZ3aHQKDl5QQ1MtQ2xvdWRLaXQkEhgABCIUAgR2d2h0CgxeUENTLUVzY3JvdyQSFQAEIhECBHZ3aHQKCV5QQ1MtRkRFJBIaAAQiFgIEdndodAoOXlBDUy1GZWxkc3BhciQSGgAEIhYCBHZ3aHQKDl5QQ1MtTWFpbERyb3AkEhoABCIWAgR2d2h0Cg5eUENTLU1haWxkcm9wJBIbAAQiFwIEdndodAoPXlBDUy1NYXN0ZXJLZXkkEhcABCITAgR2d2h0CgteUENTLU5vdGVzJBIYAAQiFAIEdndodAoMXlBDUy1QaG90b3MkEhkABCIVAgR2d2h0Cg1eUENTLVNoYXJpbmckEh4ABCIaAgR2d2h0ChJeUENTLWlDbG91ZEJhY2t1cCQSHQAEIhkCBHZ3aHQKEV5QQ1MtaUNsb3VkRHJpdmUkEhoABCIWAgR2d2h0Cg5eUENTLWlNZXNzYWdlJBIVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlMj0KLgAEIioCBGFncnAKIl5jb21cLmFwcGxlXC5zYWZhcmlcLmNyZWRpdC1jYXJkcyQSC0NyZWRpdENhcmRzMjAKIwAEIh8CBGFncnAKF15jb21cLmFwcGxlXC5jZm5ldHdvcmskEglQYXNzd29yZHMybQpcAAISHgAEIhoCBHZ3aHQKEl5BY2Nlc3NvcnlQYWlyaW5nJBIaAAQiFgIEdndodAoOXk5hbm9SZWdpc3RyeSQSHAAEIhgCBHZ3aHQKEF5XYXRjaE1pZ3JhdGlvbiQSDURldmljZVBhaXJpbmcyDgoCAAYSCEJhY2tzdG9w", + plaintextPolicy: try! TPPolicyDocument(version: 7, + modelToCategory: [ + ["prefix": "iPhone", "category": "full"], + ["prefix": "iPad", "category": "full"], + ["prefix": "iPod", "category": "full"], + ["prefix": "Mac", "category": "full"], + ["prefix": "iMac", "category": "full"], + ["prefix": "AppleTV", "category": "tv"], + ["prefix": "Watch", "category": "watch"], + ["prefix": "AudioAccessory", "category": "audio"], + ], + categoriesByView: [ + "AutoUnlock": ["full", "watch"], + "ApplePay": ["full", "watch"], + "Backstop": ["full", "watch"], + "Engram": ["full", "watch"], + "Health": ["full", "watch"], + "Home": ["full", "watch", "tv", "audio"], + "LimitedPeersAllowed": ["full", "watch", "tv", "audio"], + "Manatee": ["full", "watch"], + "Applications": ["full", "watch"], + "SecureObjectSync": ["full", "watch"], + "WiFi": ["full", "watch", "tv", "audio"], + "ProtectedCloudStorage": ["full", "watch"], + "CreditCards": ["full", "watch"], + "Passwords": ["full", "watch"], + "DevicePairing": ["full", "watch"], + ], + introducersByCategory: [ + "full": ["full", "watch"], + "watch": ["full", "watch"], + "tv": ["full", "watch", "tv"], + "audio": ["full", "watch", "audio"], + ], + redactions: [:], + keyViewMapping: [ + TPPBPolicyKeyViewMapping(view: "ApplePay", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ApplePay$")), + TPPBPolicyKeyViewMapping(view: "AutoUnlock", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AutoUnlock$")), + TPPBPolicyKeyViewMapping(view: "Engram", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Engram$")), + TPPBPolicyKeyViewMapping(view: "Health", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Health$")), + TPPBPolicyKeyViewMapping(view: "Home", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Home$")), + TPPBPolicyKeyViewMapping(view: "Manatee", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Manatee$")), + TPPBPolicyKeyViewMapping(view: "LimitedPeersAllowed", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^LimitedPeersAllowed$")), + + // These items will not be synced by Octagon + TPPBPolicyKeyViewMapping(view: "NotSynced", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ContinuityUnlock$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^HomeKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AppleTV$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Applications", matchingRule: + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^[0-9A-Z]{10}\\.")), + + TPPBPolicyKeyViewMapping(view: "SecureObjectSync", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.sbd$"), + ]), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^keys$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.security\\.sos$"), + ]), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^BackupBagV0$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^iCloudIdentity$"), + ])), + + TPPBPolicyKeyViewMapping(view: "WiFi", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WiFi$"), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^apple$"), + TPDictionaryMatchingRule.fieldMatch("svce", fieldRegex: "^AirPort$"), + ]), + ])), + + TPPBPolicyKeyViewMapping(view: "ProtectedCloudStorage", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Backup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-CloudKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Escrow$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-FDE$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Feldspar$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MailDrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Maildrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MasterKey$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Notes$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Photos$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Sharing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudBackup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudDrive$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iMessage$"), + ])), + + TPPBPolicyKeyViewMapping(view: "CreditCards", + matchingRule: TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.safari\\.credit-cards$")), + + TPPBPolicyKeyViewMapping(view: "Passwords", + matchingRule: TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.cfnetwork$")), + + TPPBPolicyKeyViewMapping(view: "DevicePairing", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AccessoryPairing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^NanoRegistry$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WatchMigration$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: + TPDictionaryMatchingRule.trueMatch()), + ], + userControllableViewList: [], + piggybackViews: [], + priorityViews: [], + hashAlgo: .SHA256) + ), + RawPolicy(version: TPPolicyVersion(version: 8, hash: "SHA256:TeQdvkO5GhKk6ayq004RlKDspusM8keCq3sXvKlmp7g="), + policyData: "CAgSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGhsKDEFwcGxpY2F0aW9ucxIEZnVsbBIFd2F0Y2gaLwoVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlEgRmdWxsEgV3YXRjaBICdHYSBWF1ZGlvGhgKCVBhc3N3b3JkcxIEZnVsbBIFd2F0Y2gaFwoIQmFja3N0b3ASBGZ1bGwSBXdhdGNoGh4KBFdpRmkSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aHwoQU2VjdXJlT2JqZWN0U3luYxIEZnVsbBIFd2F0Y2gaFwoIQXBwbGVQYXkSBGZ1bGwSBXdhdGNoGhUKBkhlYWx0aBIEZnVsbBIFd2F0Y2gaGQoKQXV0b1VubG9jaxIEZnVsbBIFd2F0Y2gaLQoTTGltaXRlZFBlZXJzQWxsb3dlZBIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxocCg1EZXZpY2VQYWlyaW5nEgRmdWxsEgV3YXRjaBoWCgdNYW5hdGVlEgRmdWxsEgV3YXRjaBoVCgZFbmdyYW0SBGZ1bGwSBXdhdGNoGh4KBEhvbWUSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aGgoLQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoIhMKBGZ1bGwSBGZ1bGwSBXdhdGNoIhQKBXdhdGNoEgRmdWxsEgV3YXRjaCIbCgVhdWRpbxIEZnVsbBIFd2F0Y2gSBWF1ZGlvIhUKAnR2EgRmdWxsEgV3YXRjaBICdHYyIgoWAAQiEgIEdndodAoKXkFwcGxlUGF5JBIIQXBwbGVQYXkyJgoYAAQiFAIEdndodAoMXkF1dG9VbmxvY2skEgpBdXRvVW5sb2NrMh4KFAAEIhACBHZ3aHQKCF5FbmdyYW0kEgZFbmdyYW0yHgoUAAQiEAIEdndodAoIXkhlYWx0aCQSBkhlYWx0aDIaChIABCIOAgR2d2h0CgZeSG9tZSQSBEhvbWUyIAoVAAQiEQIEdndodAoJXk1hbmF0ZWUkEgdNYW5hdGVlMjgKIQAEIh0CBHZ3aHQKFV5MaW1pdGVkUGVlcnNBbGxvd2VkJBITTGltaXRlZFBlZXJzQWxsb3dlZDJdClAAAhIeAAQiGgIEdndodAoSXkNvbnRpbnVpdHlVbmxvY2skEhUABCIRAgR2d2h0CgleSG9tZUtpdCQSFQAEIhECBHZ3aHQKCV5BcHBsZVRWJBIJTm90U3luY2VkMisKGwAEIhcCBGFncnAKD15bMC05QS1aXXsxMH1cLhIMQXBwbGljYXRpb25zMsoBCrUBAAISNgABChMABCIPAgVjbGFzcwoGXmdlbnAkCh0ABCIZAgRhZ3JwChFeY29tXC5hcHBsZVwuc2JkJBJAAAEKEwAEIg8CBWNsYXNzCgZea2V5cyQKJwAEIiMCBGFncnAKG15jb21cLmFwcGxlXC5zZWN1cml0eVwuc29zJBIZAAQiFQIEdndodAoNXkJhY2t1cEJhZ1YwJBIcAAQiGAIEdndodAoQXmlDbG91ZElkZW50aXR5JBIQU2VjdXJlT2JqZWN0U3luYzJjClsAAhISAAQiDgIEdndodAoGXldpRmkkEkMAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAoTAAQiDwIEYWdycAoHXmFwcGxlJAoVAAQiEQIEc3ZjZQoJXkFpclBvcnQkEgRXaUZpMp0DCoMDAAISGAAEIhQCBHZ3aHQKDF5QQ1MtQmFja3VwJBIaAAQiFgIEdndodAoOXlBDUy1DbG91ZEtpdCQSGAAEIhQCBHZ3aHQKDF5QQ1MtRXNjcm93JBIVAAQiEQIEdndodAoJXlBDUy1GREUkEhoABCIWAgR2d2h0Cg5eUENTLUZlbGRzcGFyJBIaAAQiFgIEdndodAoOXlBDUy1NYWlsRHJvcCQSGgAEIhYCBHZ3aHQKDl5QQ1MtTWFpbGRyb3AkEhsABCIXAgR2d2h0Cg9eUENTLU1hc3RlcktleSQSFwAEIhMCBHZ3aHQKC15QQ1MtTm90ZXMkEhgABCIUAgR2d2h0CgxeUENTLVBob3RvcyQSGQAEIhUCBHZ3aHQKDV5QQ1MtU2hhcmluZyQSHgAEIhoCBHZ3aHQKEl5QQ1MtaUNsb3VkQmFja3VwJBIdAAQiGQIEdndodAoRXlBDUy1pQ2xvdWREcml2ZSQSGgAEIhYCBHZ3aHQKDl5QQ1MtaU1lc3NhZ2UkEhVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2UyXApNAAISLgAEIioCBGFncnAKIl5jb21cLmFwcGxlXC5zYWZhcmlcLmNyZWRpdC1jYXJkcyQSGQAEIhUCBHZ3aHQKDV5DcmVkaXRDYXJkcyQSC0NyZWRpdENhcmRzMqYBCpgBAAISIwAEIh8CBGFncnAKF15jb21cLmFwcGxlXC5jZm5ldHdvcmskEioABCImAgRhZ3JwCh5eY29tXC5hcHBsZVwucGFzc3dvcmQtbWFuYWdlciQSKgAEIiYCBGFncnAKHl5jb21cLmFwcGxlXC5XZWJLaXRcLldlYkF1dGhuJBIXAAQiEwIEdndodAoLXlBhc3N3b3JkcyQSCVBhc3N3b3JkczJtClwAAhIeAAQiGgIEdndodAoSXkFjY2Vzc29yeVBhaXJpbmckEhoABCIWAgR2d2h0Cg5eTmFub1JlZ2lzdHJ5JBIcAAQiGAIEdndodAoQXldhdGNoTWlncmF0aW9uJBINRGV2aWNlUGFpcmluZzIOCgIABhIIQmFja3N0b3A6DEFwcGxpY2F0aW9uczoIQmFja3N0b3A6C0NyZWRpdENhcmRzOglQYXNzd29yZHM6BFdpRmlCCVBhc3N3b3Jkcw==", + plaintextPolicy: try! TPPolicyDocument(version: 8, + modelToCategory: [ + ["prefix": "iPhone", "category": "full"], + ["prefix": "iPad", "category": "full"], + ["prefix": "iPod", "category": "full"], + ["prefix": "Mac", "category": "full"], + ["prefix": "iMac", "category": "full"], + ["prefix": "AppleTV", "category": "tv"], + ["prefix": "Watch", "category": "watch"], + ["prefix": "AudioAccessory", "category": "audio"], + ], + categoriesByView: [ + "AutoUnlock": ["full", "watch"], + "ApplePay": ["full", "watch"], + "Backstop": ["full", "watch"], + "Engram": ["full", "watch"], + "Health": ["full", "watch"], + "Home": ["full", "watch", "tv", "audio"], + "LimitedPeersAllowed": ["full", "watch", "tv", "audio"], + "Manatee": ["full", "watch"], + "Applications": ["full", "watch"], + "SecureObjectSync": ["full", "watch"], + "WiFi": ["full", "watch", "tv", "audio"], + "ProtectedCloudStorage": ["full", "watch", "tv", "audio"], + "CreditCards": ["full", "watch"], + "Passwords": ["full", "watch"], + "DevicePairing": ["full", "watch"], + ], + introducersByCategory: [ + "full": ["full", "watch"], + "watch": ["full", "watch"], + "tv": ["full", "watch", "tv"], + "audio": ["full", "watch", "audio"], + ], + redactions: [:], + keyViewMapping: [ + TPPBPolicyKeyViewMapping(view: "ApplePay", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ApplePay$")), + TPPBPolicyKeyViewMapping(view: "AutoUnlock", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AutoUnlock$")), + TPPBPolicyKeyViewMapping(view: "Engram", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Engram$")), + TPPBPolicyKeyViewMapping(view: "Health", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Health$")), + TPPBPolicyKeyViewMapping(view: "Home", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Home$")), + TPPBPolicyKeyViewMapping(view: "Manatee", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Manatee$")), + TPPBPolicyKeyViewMapping(view: "LimitedPeersAllowed", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^LimitedPeersAllowed$")), + + // These items will not be synced by Octagon + TPPBPolicyKeyViewMapping(view: "NotSynced", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ContinuityUnlock$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^HomeKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AppleTV$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Applications", matchingRule: + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^[0-9A-Z]{10}\\.")), + + TPPBPolicyKeyViewMapping(view: "SecureObjectSync", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.sbd$"), + ]), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^keys$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.security\\.sos$"), + ]), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^BackupBagV0$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^iCloudIdentity$"), + ])), + + TPPBPolicyKeyViewMapping(view: "WiFi", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WiFi$"), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^apple$"), + TPDictionaryMatchingRule.fieldMatch("svce", fieldRegex: "^AirPort$"), + ]), + ])), + + TPPBPolicyKeyViewMapping(view: "ProtectedCloudStorage", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Backup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-CloudKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Escrow$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-FDE$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Feldspar$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MailDrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Maildrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MasterKey$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Notes$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Photos$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Sharing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudBackup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudDrive$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iMessage$"), + ])), + + TPPBPolicyKeyViewMapping(view: "CreditCards", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.safari\\.credit-cards$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^CreditCards$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Passwords", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.cfnetwork$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.password-manager$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.WebKit\\.WebAuthn$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Passwords$"), + ])), + + TPPBPolicyKeyViewMapping(view: "DevicePairing", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AccessoryPairing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^NanoRegistry$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WatchMigration$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: + TPDictionaryMatchingRule.trueMatch()), + ], + userControllableViewList: [ + "Applications", + "Backstop", + "CreditCards", + "Passwords", + "WiFi", + ], + piggybackViews: [ + "Passwords", + ], + priorityViews: [], + hashAlgo: .SHA256) + ), + RawPolicy(version: TPPolicyVersion(version: 9, hash: "SHA256:uynvb6IWdFbCM2AQX0aKv0yUMLg8Z2wZjZY5k4jtAj8="), + policyData: "CAkSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGh4KBEhvbWUSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aLwoVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlEgRmdWxsEgV3YXRjaBICdHYSBWF1ZGlvGhgKCVBhc3N3b3JkcxIEZnVsbBIFd2F0Y2gaHwoQU2VjdXJlT2JqZWN0U3luYxIEZnVsbBIFd2F0Y2gaHgoEV2lGaRIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxobCgxBcHBsaWNhdGlvbnMSBGZ1bGwSBXdhdGNoGhcKCEFwcGxlUGF5EgRmdWxsEgV3YXRjaBoVCgZIZWFsdGgSBGZ1bGwSBXdhdGNoGhkKCkF1dG9VbmxvY2sSBGZ1bGwSBXdhdGNoGi0KE0xpbWl0ZWRQZWVyc0FsbG93ZWQSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aHAoNRGV2aWNlUGFpcmluZxIEZnVsbBIFd2F0Y2gaFgoHTWFuYXRlZRIEZnVsbBIFd2F0Y2gaFQoGRW5ncmFtEgRmdWxsEgV3YXRjaBoXCghCYWNrc3RvcBIEZnVsbBIFd2F0Y2gaGgoLQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoIhMKBGZ1bGwSBGZ1bGwSBXdhdGNoIhsKBWF1ZGlvEgRmdWxsEgV3YXRjaBIFYXVkaW8iFQoCdHYSBGZ1bGwSBXdhdGNoEgJ0diIUCgV3YXRjaBIEZnVsbBIFd2F0Y2gyIgoWAAQiEgIEdndodAoKXkFwcGxlUGF5JBIIQXBwbGVQYXkyJgoYAAQiFAIEdndodAoMXkF1dG9VbmxvY2skEgpBdXRvVW5sb2NrMh4KFAAEIhACBHZ3aHQKCF5FbmdyYW0kEgZFbmdyYW0yHgoUAAQiEAIEdndodAoIXkhlYWx0aCQSBkhlYWx0aDIaChIABCIOAgR2d2h0CgZeSG9tZSQSBEhvbWUyIAoVAAQiEQIEdndodAoJXk1hbmF0ZWUkEgdNYW5hdGVlMjgKIQAEIh0CBHZ3aHQKFV5MaW1pdGVkUGVlcnNBbGxvd2VkJBITTGltaXRlZFBlZXJzQWxsb3dlZDJdClAAAhIeAAQiGgIEdndodAoSXkNvbnRpbnVpdHlVbmxvY2skEhUABCIRAgR2d2h0CgleSG9tZUtpdCQSFQAEIhECBHZ3aHQKCV5BcHBsZVRWJBIJTm90U3luY2VkMisKGwAEIhcCBGFncnAKD15bMC05QS1aXXsxMH1cLhIMQXBwbGljYXRpb25zMsoBCrUBAAISNgABChMABCIPAgVjbGFzcwoGXmdlbnAkCh0ABCIZAgRhZ3JwChFeY29tXC5hcHBsZVwuc2JkJBJAAAEKEwAEIg8CBWNsYXNzCgZea2V5cyQKJwAEIiMCBGFncnAKG15jb21cLmFwcGxlXC5zZWN1cml0eVwuc29zJBIZAAQiFQIEdndodAoNXkJhY2t1cEJhZ1YwJBIcAAQiGAIEdndodAoQXmlDbG91ZElkZW50aXR5JBIQU2VjdXJlT2JqZWN0U3luYzJjClsAAhISAAQiDgIEdndodAoGXldpRmkkEkMAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAoTAAQiDwIEYWdycAoHXmFwcGxlJAoVAAQiEQIEc3ZjZQoJXkFpclBvcnQkEgRXaUZpMp0DCoMDAAISGAAEIhQCBHZ3aHQKDF5QQ1MtQmFja3VwJBIaAAQiFgIEdndodAoOXlBDUy1DbG91ZEtpdCQSGAAEIhQCBHZ3aHQKDF5QQ1MtRXNjcm93JBIVAAQiEQIEdndodAoJXlBDUy1GREUkEhoABCIWAgR2d2h0Cg5eUENTLUZlbGRzcGFyJBIaAAQiFgIEdndodAoOXlBDUy1NYWlsRHJvcCQSGgAEIhYCBHZ3aHQKDl5QQ1MtTWFpbGRyb3AkEhsABCIXAgR2d2h0Cg9eUENTLU1hc3RlcktleSQSFwAEIhMCBHZ3aHQKC15QQ1MtTm90ZXMkEhgABCIUAgR2d2h0CgxeUENTLVBob3RvcyQSGQAEIhUCBHZ3aHQKDV5QQ1MtU2hhcmluZyQSHgAEIhoCBHZ3aHQKEl5QQ1MtaUNsb3VkQmFja3VwJBIdAAQiGQIEdndodAoRXlBDUy1pQ2xvdWREcml2ZSQSGgAEIhYCBHZ3aHQKDl5QQ1MtaU1lc3NhZ2UkEhVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2UyXApNAAISLgAEIioCBGFncnAKIl5jb21cLmFwcGxlXC5zYWZhcmlcLmNyZWRpdC1jYXJkcyQSGQAEIhUCBHZ3aHQKDV5DcmVkaXRDYXJkcyQSC0NyZWRpdENhcmRzMtIBCsQBAAISIwAEIh8CBGFncnAKF15jb21cLmFwcGxlXC5jZm5ldHdvcmskEioABCImAgRhZ3JwCh5eY29tXC5hcHBsZVwucGFzc3dvcmQtbWFuYWdlciQSKgAEIiYCBGFncnAKHl5jb21cLmFwcGxlXC5XZWJLaXRcLldlYkF1dGhuJBIqAAQiJgIEYWdycAoeXmNvbVwuYXBwbGVcLndlYmtpdFwud2ViYXV0aG4kEhcABCITAgR2d2h0CgteUGFzc3dvcmRzJBIJUGFzc3dvcmRzMm0KXAACEh4ABCIaAgR2d2h0ChJeQWNjZXNzb3J5UGFpcmluZyQSGgAEIhYCBHZ3aHQKDl5OYW5vUmVnaXN0cnkkEhwABCIYAgR2d2h0ChBeV2F0Y2hNaWdyYXRpb24kEg1EZXZpY2VQYWlyaW5nMg4KAgAGEghCYWNrc3RvcDoMQXBwbGljYXRpb25zOghCYWNrc3RvcDoLQ3JlZGl0Q2FyZHM6CVBhc3N3b3JkczoEV2lGaUIJUGFzc3dvcmRzShVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2VKEFNlY3VyZU9iamVjdFN5bmM=", + plaintextPolicy: try! TPPolicyDocument(version: 9, + modelToCategory: [ + ["prefix": "iPhone", "category": "full"], + ["prefix": "iPad", "category": "full"], + ["prefix": "iPod", "category": "full"], + ["prefix": "Mac", "category": "full"], + ["prefix": "iMac", "category": "full"], + ["prefix": "AppleTV", "category": "tv"], + ["prefix": "Watch", "category": "watch"], + ["prefix": "AudioAccessory", "category": "audio"], + ], + categoriesByView: [ + "AutoUnlock": ["full", "watch"], + "ApplePay": ["full", "watch"], + "Backstop": ["full", "watch"], + "Engram": ["full", "watch"], + "Health": ["full", "watch"], + "Home": ["full", "watch", "tv", "audio"], + "LimitedPeersAllowed": ["full", "watch", "tv", "audio"], + "Manatee": ["full", "watch"], + "Applications": ["full", "watch"], + "SecureObjectSync": ["full", "watch"], + "WiFi": ["full", "watch", "tv", "audio"], + "ProtectedCloudStorage": ["full", "watch", "tv", "audio"], + "CreditCards": ["full", "watch"], + "Passwords": ["full", "watch"], + "DevicePairing": ["full", "watch"], + ], + introducersByCategory: [ + "full": ["full", "watch"], + "watch": ["full", "watch"], + "tv": ["full", "watch", "tv"], + "audio": ["full", "watch", "audio"], + ], + redactions: [:], + keyViewMapping: [ + TPPBPolicyKeyViewMapping(view: "ApplePay", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ApplePay$")), + TPPBPolicyKeyViewMapping(view: "AutoUnlock", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AutoUnlock$")), + TPPBPolicyKeyViewMapping(view: "Engram", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Engram$")), + TPPBPolicyKeyViewMapping(view: "Health", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Health$")), + TPPBPolicyKeyViewMapping(view: "Home", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Home$")), + TPPBPolicyKeyViewMapping(view: "Manatee", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Manatee$")), + TPPBPolicyKeyViewMapping(view: "LimitedPeersAllowed", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^LimitedPeersAllowed$")), + + // These items will not be synced by Octagon + TPPBPolicyKeyViewMapping(view: "NotSynced", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ContinuityUnlock$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^HomeKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AppleTV$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Applications", matchingRule: + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^[0-9A-Z]{10}\\.")), + + TPPBPolicyKeyViewMapping(view: "SecureObjectSync", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.sbd$"), + ]), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^keys$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.security\\.sos$"), + ]), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^BackupBagV0$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^iCloudIdentity$"), + ])), + + TPPBPolicyKeyViewMapping(view: "WiFi", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WiFi$"), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^apple$"), + TPDictionaryMatchingRule.fieldMatch("svce", fieldRegex: "^AirPort$"), + ]), + ])), + + TPPBPolicyKeyViewMapping(view: "ProtectedCloudStorage", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Backup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-CloudKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Escrow$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-FDE$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Feldspar$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MailDrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Maildrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MasterKey$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Notes$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Photos$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Sharing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudBackup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudDrive$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iMessage$"), + ])), + + TPPBPolicyKeyViewMapping(view: "CreditCards", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.safari\\.credit-cards$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^CreditCards$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Passwords", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.cfnetwork$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.password-manager$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.WebKit\\.WebAuthn$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.webkit\\.webauthn$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Passwords$"), + ])), + + TPPBPolicyKeyViewMapping(view: "DevicePairing", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AccessoryPairing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^NanoRegistry$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WatchMigration$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: + TPDictionaryMatchingRule.trueMatch()), + ], + userControllableViewList: [ + "Applications", + "Backstop", + "CreditCards", + "Passwords", + "WiFi", + ], + piggybackViews: [ + "Passwords", + ], + priorityViews: [ + "ProtectedCloudStorage", + "SecureObjectSync", + ], + hashAlgo: .SHA256) + ), + + // Note to you, the next person to add a policy: + // We added user_controllable_views and views_to_piggyback to the policy proto after creating v7. + // We added priority_views to the policy proto after creating v8. + + // TPPolicy.m has hacky pactches around these changes. + ] + // swiftlint:enable force_try + + assert(rawPolicies.filter { prevailingPolicyVersion.versionNumber == $0.version.versionNumber }.count == 1) return rawPolicies.map { raw in let data = Data(base64Encoded: raw.policyData)! - let doc = TPPolicyDocument.policyDoc(withHash: raw.policyHash, data: data)! - assert(doc.policyVersion == raw.policyVersion) - if raw.policyVersion == prevailingPolicyVersion { - assert(prevailingPolicyHash == raw.policyHash) + let doc = TPPolicyDocument.policyDoc(withHash: raw.version.policyHash, data: data)! + + if !doc.isEqual(to: raw.plaintextPolicy) { + let bodyData = raw.plaintextPolicy.protobuf + let bodyBase64 = bodyData.base64EncodedString() + let hash = TPHashBuilder.hash(with: .SHA256, of: bodyData) + os_log("raw policy doesn't match encoded bytes, new hash would be: %{public}@ new data: %{public}@", log: tplogDebug, hash, bodyBase64) + } + + assert(doc.version.versionNumber == raw.version.versionNumber) + if raw.version.versionNumber == prevailingPolicyVersion.versionNumber { + assert(prevailingPolicyVersion.policyHash == raw.version.policyHash) } assert(doc.isEqual(to: raw.plaintextPolicy)) return doc diff --git a/keychain/TrustedPeersHelper/RecoveryKey/RecoverKeySet.swift b/keychain/TrustedPeersHelper/RecoveryKey/RecoverKeySet.swift index 1ab70461..f300de19 100644 --- a/keychain/TrustedPeersHelper/RecoveryKey/RecoverKeySet.swift +++ b/keychain/TrustedPeersHelper/RecoveryKey/RecoverKeySet.swift @@ -27,29 +27,31 @@ import SecurityFoundation let OT_RECOVERY_SIGNING_HKDF_SIZE = 56 let OT_RECOVERY_ENCRYPTION_HKDF_SIZE = 56 -enum recoveryKeyType: Int { +enum RecoveryKeyType: Int { case kOTRecoveryKeySigning = 1 case kOTRecoveryKeyEncryption = 2 } class RecoveryKeySet: NSObject { - public var encryptionKey: _SFECKeyPair - public var signingKey: _SFECKeyPair + var encryptionKey: _SFECKeyPair + var signingKey: _SFECKeyPair - public var secret: Data - public var recoverySalt: String + var secret: Data + var recoverySalt: String - public init (secret: Data, recoverySalt: String) throws { + init (secret: Data, recoverySalt: String) throws { self.secret = secret self.recoverySalt = recoverySalt - let encryptionKeyData = try RecoveryKeySet.generateRecoveryKey(keyType: recoveryKeyType.kOTRecoveryKeyEncryption, masterSecret: secret, recoverySalt: recoverySalt) + let encryptionKeyData = try RecoveryKeySet.generateRecoveryKey(keyType: RecoveryKeyType.kOTRecoveryKeyEncryption, masterSecret: secret, recoverySalt: recoverySalt) self.encryptionKey = _SFECKeyPair.init(secKey: try RecoveryKeySet.createSecKey(keyData: encryptionKeyData)) - let signingKeyData = try RecoveryKeySet.generateRecoveryKey(keyType: recoveryKeyType.kOTRecoveryKeySigning, masterSecret: secret, recoverySalt: recoverySalt) + let signingKeyData = try RecoveryKeySet.generateRecoveryKey(keyType: RecoveryKeyType.kOTRecoveryKeySigning, masterSecret: secret, recoverySalt: recoverySalt) self.signingKey = _SFECKeyPair.init(secKey: try RecoveryKeySet.createSecKey(keyData: signingKeyData)) - let RecoverySigningPubKeyHash = try RecoveryKeySet.hashRecoveryedSigningPublicKey(keyData: self.signingKey.publicKey().spki()) + // Note: this uses the SPKI hash, and not the key data hash + // So, this will not match the RK's peer ID + let RecoverySigningPubKeyHash = RecoveryKeySet.hashRecoveryedSigningPublicKey(keyData: self.signingKey.publicKey().spki()) _ = try RecoveryKeySet.storeRecoveryedSigningKeyPair(keyData: self.signingKey.keyData, label: RecoverySigningPubKeyHash) _ = try RecoveryKeySet.storeRecoveryedEncryptionKeyPair(keyData: self.encryptionKey.keyData, label: RecoverySigningPubKeyHash) } @@ -58,27 +60,24 @@ class RecoveryKeySet: NSObject { return SecRKCreateRecoveryKeyString(nil) as String } - class func generateRecoveryKey(keyType: recoveryKeyType, masterSecret: Data, recoverySalt: String) throws -> (Data) { + class func generateRecoveryKey(keyType: RecoveryKeyType, masterSecret: Data, recoverySalt: String) throws -> (Data) { var keyLength: Int var info: Data var derivedKey: Data var finalKey = Data() switch keyType { - case recoveryKeyType.kOTRecoveryKeyEncryption: + case RecoveryKeyType.kOTRecoveryKeyEncryption: keyLength = OT_RECOVERY_ENCRYPTION_HKDF_SIZE let infoString = Array("Recovery Encryption Private Key".utf8) info = Data(bytes: infoString, count: infoString.count) - break - case recoveryKeyType.kOTRecoveryKeySigning: + case RecoveryKeyType.kOTRecoveryKeySigning: keyLength = OT_RECOVERY_SIGNING_HKDF_SIZE let infoString = Array("Recovery Signing Private Key".utf8) info = Data(bytes: infoString, count: infoString.count) - - break } guard let cp = ccec_cp_384() else { @@ -108,10 +107,10 @@ class RecoveryKeySet: NSObject { throw RecoveryKeySetError.corecryptoKeyGeneration(corecryptoError: status) } - if(keyType == recoveryKeyType.kOTRecoveryKeyEncryption || keyType == recoveryKeyType.kOTRecoveryKeySigning) { + if keyType == RecoveryKeyType.kOTRecoveryKeyEncryption || keyType == RecoveryKeyType.kOTRecoveryKeySigning { status = ccec_generate_key_deterministic(cp, derivedKeyBytes.count, derivedKeyBytes.bindMemory(to: UInt8.self).baseAddress!, - ccDRBGGetRngState(), + ccrng(nil), UInt32(CCEC_GENKEY_DETERMINISTIC_FIPS), fullKey) @@ -143,7 +142,7 @@ class RecoveryKeySet: NSObject { return key } - class func setKeyMaterialInKeychain(query: Dictionary) throws -> (Bool) { + class func setKeyMaterialInKeychain(query: [CFString: Any]) throws -> (Bool) { var result = false var results: CFTypeRef? @@ -152,7 +151,7 @@ class RecoveryKeySet: NSObject { if status == errSecSuccess { result = true } else if status == errSecDuplicateItem { - var updateQuery: Dictionary = query + var updateQuery: [CFString: Any] = query updateQuery[kSecClass] = nil status = SecItemUpdate(query as CFDictionary, updateQuery as CFDictionary) @@ -169,7 +168,7 @@ class RecoveryKeySet: NSObject { return result } - class func hashRecoveryedSigningPublicKey(keyData: Data) throws -> (String) { + class func hashRecoveryedSigningPublicKey(keyData: Data) -> (String) { let di = ccsha384_di() var result = Data(count: TPHObjectiveC.ccsha384_diSize()) @@ -185,7 +184,6 @@ class RecoveryKeySet: NSObject { } class func storeRecoveryedEncryptionKeyPair(keyData: Data, label: String) throws -> (Bool) { - let query: [CFString: Any] = [ kSecClass: kSecClassKey, kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, @@ -213,8 +211,8 @@ class RecoveryKeySet: NSObject { return try RecoveryKeySet.setKeyMaterialInKeychain(query: query) } - class func retrieveRecoveryKeysFromKeychain(label: String) throws -> [Dictionary ]? { - var keySet: [Dictionary]? + class func retrieveRecoveryKeysFromKeychain(label: String) throws -> [ [CFString: Any]]? { + var keySet: [[CFString: Any]]? let query: [CFString: Any] = [ kSecClass: kSecClassKey, @@ -234,10 +232,10 @@ class RecoveryKeySet: NSObject { } if result != nil { - if let dictionaryArray = result as? [Dictionary] { + if let dictionaryArray = result as? [[CFString: Any]] { keySet = dictionaryArray } else { - if let dictionary = result as? Dictionary { + if let dictionary = result as? [CFString: Any] { keySet = [dictionary] } else { keySet = nil @@ -259,11 +257,11 @@ class RecoveryKeySet: NSObject { let keyTypeData = item[kSecAttrApplicationLabel as CFString] as! Data let keyType = String(data: keyTypeData, encoding: .utf8)! - if keyType.range(of: "Encryption") != nil { + if keyType.contains("Encryption") { let keyData = item[kSecValueData as CFString] as! Data let encryptionSecKey = try RecoveryKeySet.createSecKey(keyData: keyData) encryptionKey = _SFECKeyPair.init(secKey: encryptionSecKey) - } else if keyType.range(of: "Signing") != nil { + } else if keyType.contains("Signing") { let keyData = item[kSecValueData as CFString] as! Data let signingSecKey = try RecoveryKeySet.createSecKey(keyData: keyData) signingKey = _SFECKeyPair.init(secKey: signingSecKey) @@ -302,7 +300,6 @@ extension RecoveryKeySetError: LocalizedError { } extension RecoveryKeySetError: CustomNSError { - public static var errorDomain: String { return "com.apple.security.trustedpeers.RecoveryKeySetError" } diff --git a/keychain/TrustedPeersHelper/RecoveryKey/RecoveryKey.swift b/keychain/TrustedPeersHelper/RecoveryKey/RecoveryKey.swift index 35cd9b3f..373a256d 100644 --- a/keychain/TrustedPeersHelper/RecoveryKey/RecoveryKey.swift +++ b/keychain/TrustedPeersHelper/RecoveryKey/RecoveryKey.swift @@ -25,20 +25,38 @@ import Foundation import SecurityFoundation class RecoveryKey: NSObject { - public var recoveryKeys: RecoveryKeySet - public var secret: Data + internal var recoveryKeys: RecoveryKeySet + internal var secret: Data - public var peerKeys: OctagonSelfPeerKeys + internal var peerKeys: OctagonSelfPeerKeys - public init(recoveryKeyString: String, recoverySalt: String) throws { + internal init(recoveryKeyString: String, recoverySalt: String) throws { self.secret = Data(bytes: Array(recoveryKeyString.utf8), count: recoveryKeyString.utf8.count) self.recoveryKeys = try RecoveryKeySet(secret: self.secret, recoverySalt: recoverySalt) - let hash = try RecoveryKeySet.hashRecoveryedSigningPublicKey(keyData: self.recoveryKeys.signingKey.publicKey.keyData) - let peerID = "RK-" + hash + let peerID = RecoveryKey.PeerID(signingPublicKeyData: self.recoveryKeys.signingKey.publicKey.keyData) try self.peerKeys = OctagonSelfPeerKeys(peerID: peerID, signingKey: self.recoveryKeys.signingKey, encryptionKey: self.recoveryKeys.encryptionKey) } + + static func PeerID(signingPublicKeyData: Data) -> String { + let hash = RecoveryKeySet.hashRecoveryedSigningPublicKey(keyData: signingPublicKeyData) + let peerID = "RK-" + hash + + return peerID + } + + static func spki(publicKeyData: Data) throws -> Data { + let key = try _SFECPublicKey(data: publicKeyData, specifier: _SFECKeySpecifier(curve: SFEllipticCurve.nistp384)) + return key.encodeSubjectPublicKeyInfo() + } + + public static func asPeer(recoveryKeys: TPRecoveryKeyPair, viewList: Set) throws -> TrustedPeersHelperPeer { + return TrustedPeersHelperPeer(peerID: self.PeerID(signingPublicKeyData: recoveryKeys.signingKeyData), + signingSPKI: try self.spki(publicKeyData: recoveryKeys.signingKeyData), + encryptionSPKI: try self.spki(publicKeyData: recoveryKeys.encryptionKeyData), + viewList: viewList) + } } extension RecoveryKey { diff --git a/keychain/TrustedPeersHelper/SetValueTransformer.swift b/keychain/TrustedPeersHelper/SetValueTransformer.swift index 2529be27..e670dbde 100644 --- a/keychain/TrustedPeersHelper/SetValueTransformer.swift +++ b/keychain/TrustedPeersHelper/SetValueTransformer.swift @@ -13,7 +13,9 @@ class SetValueTransformer: ValueTransformer { override func transformedValue(_ value: Any?) -> Any? { do { - guard let value = value else { return nil } + guard let value = value else { + return nil + } return try NSKeyedArchiver.archivedData(withRootObject: value, requiringSecureCoding: true) } catch { os_log("Failed to serialize a Set: %@", log: tplogDebug, type: .default, error as CVarArg) @@ -23,8 +25,12 @@ class SetValueTransformer: ValueTransformer { override func reverseTransformedValue(_ value: Any?) -> Any? { do { - guard let dataOp = value as? Data? else { return nil } - guard let data = dataOp else { return nil } + guard let dataOp = value as? Data? else { + return nil + } + guard let data = dataOp else { + return nil + } let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data) return unarchiver.decodeObject(of: [NSSet.self], forKey: NSKeyedArchiveRootObjectKey) diff --git a/keychain/TrustedPeersHelper/TPHObjcTranslation.m b/keychain/TrustedPeersHelper/TPHObjcTranslation.m index 5254fe76..51128fa0 100644 --- a/keychain/TrustedPeersHelper/TPHObjcTranslation.m +++ b/keychain/TrustedPeersHelper/TPHObjcTranslation.m @@ -6,7 +6,7 @@ #import #import #import -#import +#import @implementation TPHObjectiveC : NSObject diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h b/keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h index a633cef5..38ec749f 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h +++ b/keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h @@ -29,6 +29,10 @@ #import "keychain/ot/OTConstants.h" #import "keychain/ot/OTDefines.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecord.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h" + #import "keychain/TrustedPeersHelper/TPHObjcTranslation.h" #import "keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h" #import "keychain/TrustedPeersHelper/proto/generated_source/OTBottle.h" @@ -52,7 +56,11 @@ #import #import #import +#import -#import #import #include + +#if TARGET_OS_OSX +#include +#endif diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelper-entitlements.plist b/keychain/TrustedPeersHelper/TrustedPeersHelper-entitlements.plist index 6947f3d5..539efa03 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelper-entitlements.plist +++ b/keychain/TrustedPeersHelper/TrustedPeersHelper-entitlements.plist @@ -24,6 +24,8 @@ com.apple.private.cloudkit.systemService + com.apple.private.cloudkit.spi + com.apple.private.cloudkit.supportservice com.apple.private.cloudkit.prefix @@ -37,5 +39,24 @@ com.apple.symptom_diagnostics.report + seatbelt-profiles + + temporary-sandbox + + com.apple.security.ts.cloudkit-client + + com.apple.security.exception.files.absolute-path.read-write + + /private/var/Keychains/ + + com.apple.security.exception.mach-lookup.global-name + + com.apple.securityd + com.apple.security.sfkeychainserver + + com.apple.security.exception.shared-preference.read-write + + com.apple.TrustedPeersHelper + diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelper.xcdatamodeld/TrustedPeersHelper_2.xcdatamodel/contents b/keychain/TrustedPeersHelper/TrustedPeersHelper.xcdatamodeld/TrustedPeersHelper_2.xcdatamodel/contents index 34e02638..ec21b7db 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelper.xcdatamodeld/TrustedPeersHelper_2.xcdatamodel/contents +++ b/keychain/TrustedPeersHelper/TrustedPeersHelper.xcdatamodeld/TrustedPeersHelper_2.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -18,13 +18,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -65,7 +112,10 @@ - + + + + diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h b/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h index 197d419b..6031e61d 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h +++ b/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h @@ -23,6 +23,7 @@ #import #import +#import #import "keychain/ckks/CKKSKeychainBackedKey.h" #import "keychain/ckks/CKKSTLKShare.h" @@ -65,6 +66,7 @@ NS_ASSUME_NONNULL_BEGIN @interface TrustedPeersHelperEgoPeerStatus : NSObject @property TPPeerStatus egoStatus; @property NSString* _Nullable egoPeerID; +@property NSString* _Nullable egoPeerMachineID; @property (assign) uint64_t numberOfPeersInOctagon; // Note: this field does not include untrusted peers @@ -77,6 +79,7 @@ NS_ASSUME_NONNULL_BEGIN @property BOOL isLocked; - (instancetype)initWithEgoPeerID:(NSString* _Nullable)egoPeerID + egoPeerMachineID:(NSString* _Nullable)egoPeerMachineID status:(TPPeerStatus)egoStatus viablePeerCountsByModelID:(NSDictionary*)viablePeerCountsByModelID peerCountsByMachineID:(NSDictionary*)peerCountsByMachineID @@ -129,6 +132,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)setAllowedMachineIDsWithContainer:(NSString *)container context:(NSString *)context allowedMachineIDs:(NSSet *)allowedMachineIDs + honorIDMSListChanges:(BOOL)honorIDMSListChanges reply:(void (^)(BOOL listDifferences, NSError * _Nullable error))reply; - (void)addAllowedMachineIDsWithContainer:(NSString *)container @@ -157,11 +161,12 @@ NS_ASSUME_NONNULL_BEGIN bottleSalt:(NSString *)bottleSalt bottleID:(NSString *)bottleID modelID:(NSString *)modelID - deviceName:(nullable NSString*)deviceName - serialNumber:(NSString *)serialNumber + deviceName:(nullable NSString *)deviceName + serialNumber:(nullable NSString *)serialNumber osVersion:(NSString *)osVersion - policyVersion:(nullable NSNumber *)policyVersion + policyVersion:(nullable TPPolicyVersion *)policyVersion policySecrets:(nullable NSDictionary *)policySecrets + syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews signingPrivKeyPersistentRef:(nullable NSData *)spkPr encPrivKeyPersistentRef:(nullable NSData*)epkPr reply:(void (^)(NSString * _Nullable peerID, @@ -169,6 +174,7 @@ NS_ASSUME_NONNULL_BEGIN NSData * _Nullable permanentInfoSig, NSData * _Nullable stableInfo, NSData * _Nullable stableInfoSig, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply; // If there already are existing CKKSViews, please pass in their key sets anyway. @@ -180,6 +186,7 @@ NS_ASSUME_NONNULL_BEGIN preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply; // Returns a voucher for the given peer ID using our own identity @@ -196,12 +203,16 @@ NS_ASSUME_NONNULL_BEGIN NSData * _Nullable voucherSig, NSError * _Nullable error))reply; -// Preflighting a vouch will return the peer ID associated with the bottle you will be recovering. +// Preflighting a vouch will return the peer ID associated with the bottle you will be recovering, as well as +// the syncing policy used by that peer, and, // You can then use that peer ID to filter the tlkshares provided to vouchWithBottle. +// If TPH had to refetch anything from the network, it will report that fact as refetchNeeded. - (void)preflightVouchWithBottleWithContainer:(NSString *)container context:(NSString *)context bottleID:(NSString*)bottleID reply:(void (^)(NSString* _Nullable peerID, + TPSyncingPolicy* _Nullable syncingPolicy, + BOOL refetchWasNeeded, NSError * _Nullable error))reply; // Returns a voucher for our own identity, created by the identity inside this bottle @@ -213,8 +224,20 @@ NS_ASSUME_NONNULL_BEGIN tlkShares:(NSArray *)tlkShares reply:(void (^)(NSData * _Nullable voucher, NSData * _Nullable voucherSig, + int64_t uniqueTLKsRecovered, + int64_t totalTLKSharesRecovered, NSError * _Nullable error))reply; +// Preflighting a vouch will return the RK ID, view list and policy associated with the RK you will be recovering. +// You can then use that peer ID to filter the tlkshares provided to vouchWithRecoveryKey. +- (void)preflightVouchWithRecoveryKeyWithContainer:(NSString*)container + context:(NSString*)context + recoveryKey:(NSString*)recoveryKey + salt:(NSString*)salt + reply:(void (^)(NSString* _Nullable recoveryKeyID, + TPSyncingPolicy* _Nullable syncingPolicy, + NSError * _Nullable error))reply; + // Returns a voucher for our own identity, using recovery key - (void)vouchWithRecoveryKeyWithContainer:(NSString *)container context:(NSString *)context @@ -234,18 +257,21 @@ NS_ASSUME_NONNULL_BEGIN voucherSig:(NSData *)voucherSig ckksKeys:(NSArray *)viewKeySets tlkShares:(NSArray *)tlkShares - preapprovedKeys:(NSArray *)preapprovedKeys + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply; // Preflighting a preapproved join suggests whether or not you expect to succeed in an immediate preapprovedJoin() call // This only inspects the Octagon model, and ignores the trusted device list, so that you can preflight the preapprovedJoin() // before fetching that list. -// This will return YES if there are no existing peers, or if the existing peers preapprove your prepared identity. +// This will return YES if there are no existing peers, or if the existing peers preapprove your prepared identity, and +// you are intending to trust at least one preapproving peer (so that you don't stomp all over everyone else at join time). // This will return NO otherwise. - (void)preflightPreapprovedJoinWithContainer:(NSString *)container context:(NSString *)context + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(BOOL launchOkay, NSError * _Nullable error))reply; @@ -255,12 +281,14 @@ NS_ASSUME_NONNULL_BEGIN context:(NSString *)context ckksKeys:(NSArray *)ckksKeys tlkShares:(NSArray *)tlkShares - preapprovedKeys:(NSArray *)preapprovedKeys + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply; // TODO: if the new policy causes someone to lose access to a view, how should this API work? +// syncUserControllableViews should contain the raw value of the TPPBPeerStableInfo_UserControllableViewStatus enum, or be nil - (void)updateWithContainer:(NSString *)container context:(NSString *)context deviceName:(nullable NSString *)deviceName @@ -268,12 +296,15 @@ NS_ASSUME_NONNULL_BEGIN osVersion:(nullable NSString *)osVersion policyVersion:(nullable NSNumber *)policyVersion policySecrets:(nullable NSDictionary *)policySecrets - reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, NSError * _Nullable error))reply; + syncUserControllableViews:(nullable NSNumber *)syncUserControllableViews + reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, + TPSyncingPolicy* _Nullable syncingPolicy, + NSError * _Nullable error))reply; - (void)setPreapprovedKeysWithContainer:(NSString *)container context:(NSString *)context preapprovedKeys:(NSArray *)preapprovedKeys - reply:(void (^)(NSError * _Nullable error))reply; + reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, NSError * _Nullable error))reply; /* Rather thin pass-through for uploading new TLKs (for zones which may have disappeared) */ - (void)updateTLKsWithContainer:(NSString *)container @@ -286,6 +317,11 @@ NS_ASSUME_NONNULL_BEGIN context:(NSString *)context reply:(void (^)(NSArray* _Nullable sortedBottleIDs, NSArray* _Nullable sortedPartialBottleIDs, NSError* _Nullable error))reply; +- (void)fetchViableEscrowRecordsWithContainer:(NSString *)container + context:(NSString *)context + forceFetch:(BOOL)forceFetch + reply:(void (^)(NSArray* _Nullable records, NSError* _Nullable error))reply; + - (void)fetchEscrowContentsWithContainer:(NSString *)container context:(NSString *)context reply:(void (^)(NSData* _Nullable entropy, @@ -293,19 +329,22 @@ NS_ASSUME_NONNULL_BEGIN NSData* _Nullable signingPublicKey, NSError* _Nullable error))reply; -// The argument contains N [version:hash] keys, -// the reply block contains 0<=N [version:[hash, data]] entries. - (void)fetchPolicyDocumentsWithContainer:(NSString*)container context:(NSString*)context - keys:(NSDictionary*)keys - reply:(void (^)(NSDictionary*>* _Nullable entries, + versions:(NSSet*)versions + reply:(void (^)(NSDictionary* _Nullable entries, NSError * _Nullable error))reply; -// Fetch the policy for current peer. -- (void)fetchPolicyWithContainer:(NSString*)container - context:(NSString*)context - reply:(void (^)(TPPolicy * _Nullable policy, - NSError * _Nullable error))reply; +// Fetch the policy and view list for current peer. +// Note: userControllableViewStatusOfPeers is not our current peer's view of the world, but rather what +// our peers believe. +// If there is no prepared ego peer, the returned policy will be for a device with modelIDOverride +- (void)fetchCurrentPolicyWithContainer:(NSString*)container + context:(NSString*)context + modelIDOverride:(NSString* _Nullable)modelID + reply:(void (^)(TPSyncingPolicy* _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, + NSError * _Nullable error))reply; - (void)validatePeersWithContainer:(NSString *)container context:(NSString *)context @@ -324,7 +363,8 @@ NS_ASSUME_NONNULL_BEGIN recoveryKey:(NSString *)recoveryKey salt:(NSString *)salt ckksKeys:(NSArray *)ckksKeys - reply:(void (^)(NSError* _Nullable error))reply; + reply:(void (^)(NSArray* _Nullable keyHierarchyRecords, + NSError* _Nullable error))reply; - (void)reportHealthWithContainer:(NSString *)container context:(NSString *)context @@ -336,20 +376,23 @@ NS_ASSUME_NONNULL_BEGIN context:(NSString *)context reply:(void (^)(NSError* _Nullable error))reply; -- (void)getViewsWithContainer:(NSString *)container - context:(NSString *)context - inViews:(NSArray*)inViews - reply:(void (^)(NSArray* _Nullable, NSError* _Nullable))reply; - - (void)requestHealthCheckWithContainer:(NSString *)container context:(NSString *)context requiresEscrowCheck:(BOOL)requiresEscrowCheck - reply:(void (^)(BOOL postRepairCFU, BOOL postEscrowCFU, BOOL resetOctagon, NSError* _Nullable))reply; + reply:(void (^)(BOOL postRepairCFU, BOOL postEscrowCFU, BOOL resetOctagon, BOOL leaveTrust, NSError* _Nullable))reply; - (void)getSupportAppInfoWithContainer:(NSString *)container context:(NSString *)context reply:(void (^)(NSData * _Nullable, NSError * _Nullable))reply; +- (void)resetAccountCDPContentsWithContainer:(NSString *)container + context:(NSString *)context + reply:(void (^)(NSError * _Nullable))reply; + +- (void)removeEscrowCacheWithContainer:(NSString *)container + context:(NSString *)context + reply:(void (^)(NSError * _Nullable))reply; + @end /* diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.m b/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.m index 66031113..c64e1a73 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.m +++ b/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.m @@ -6,6 +6,7 @@ #import "utilities/debugging.h" #import #import +#import #endif NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) @@ -16,29 +17,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ errClasses = [NSMutableSet setWithSet:CKAcceptableValueClasses()]; - - char *classes[] = { - "CKPrettyError", - "CKRecordID", - "NSArray", - "NSData", - "NSDate", - "NSDictionary", - "NSError", - "NSNull", - "NSNumber", - "NSOrderedSet", - "NSSet", - "NSString", - "NSURL", - }; - - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) { - [errClasses addObject:cls]; - } - } + [errClasses unionSet:[SecXPCHelper safeErrorClasses]]; }); @try { @@ -50,6 +29,45 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) NSSet* arrayOfTrustedPeersHelperPeer = [NSSet setWithArray:@[[NSArray class], [TrustedPeersHelperPeer class]]]; + [interface setClasses:errClasses forSelector:@selector(dumpWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(departByDistrustingSelfWithContainer:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(distrustPeerIDsWithContainer:context:peerIDs:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(trustStatusWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(resetWithContainer:context:resetReason:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(localResetWithContainer:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(setAllowedMachineIDsWithContainer:context:allowedMachineIDs:honorIDMSListChanges:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(addAllowedMachineIDsWithContainer:context:machineIDs:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(removeAllowedMachineIDsWithContainer:context:machineIDs:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchAllowedMachineIDsWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchEgoEpochWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(prepareWithContainer:context:epoch:machineID:bottleSalt:bottleID:modelID:deviceName:serialNumber:osVersion:policyVersion:policySecrets:syncUserControllableViews:signingPrivKeyPersistentRef:encPrivKeyPersistentRef:reply:) argumentIndex:6 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(establishWithContainer:context:ckksKeys:tlkShares:preapprovedKeys:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(vouchWithContainer:context:peerID:permanentInfo:permanentInfoSig:stableInfo:stableInfoSig:ckksKeys:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(preflightVouchWithBottleWithContainer:context:bottleID:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(vouchWithBottleWithContainer:context:bottleID:entropy:bottleSalt:tlkShares:reply:) argumentIndex:4 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(preflightVouchWithRecoveryKeyWithContainer:context:recoveryKey:salt:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(vouchWithRecoveryKeyWithContainer:context:recoveryKey:salt:tlkShares:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(joinWithContainer:context:voucherData:voucherSig:ckksKeys:tlkShares:preapprovedKeys:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(preflightPreapprovedJoinWithContainer:context:preapprovedKeys:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(attemptPreapprovedJoinWithContainer:context:ckksKeys:tlkShares:preapprovedKeys:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(updateWithContainer:context:deviceName:serialNumber:osVersion:policyVersion:policySecrets:syncUserControllableViews:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(setPreapprovedKeysWithContainer:context:preapprovedKeys:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(updateTLKsWithContainer:context:ckksKeys:tlkShares:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchViableBottlesWithContainer:context:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchViableEscrowRecordsWithContainer:context:forceFetch:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchEscrowContentsWithContainer:context:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchPolicyDocumentsWithContainer:context:versions:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchCurrentPolicyWithContainer:context:modelIDOverride:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(validatePeersWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchTrustStateWithContainer:context:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(setRecoveryKeyWithContainer:context:recoveryKey:salt:ckksKeys:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(reportHealthWithContainer:context:stateMachineState:trustState:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(pushHealthInquiryWithContainer:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(requestHealthCheckWithContainer:context:requiresEscrowCheck:reply:) argumentIndex:4 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(getSupportAppInfoWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(removeEscrowCacheWithContainer:context:reply:) argumentIndex:0 ofReply:YES]; + + [interface setClasses:arrayOfStrings forSelector:@selector(addAllowedMachineIDsWithContainer:context:machineIDs:reply:) argumentIndex:2 ofReply:NO]; [interface setClasses:arrayOfStrings forSelector:@selector(removeAllowedMachineIDsWithContainer:context:machineIDs:reply:) argumentIndex:2 ofReply:NO]; @@ -88,6 +106,12 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) salt: ckksKeys: reply:) argumentIndex:4 ofReply:NO]; + [interface setClasses:arrayOfCKRecords forSelector:@selector(setRecoveryKeyWithContainer: + context: + recoveryKey: + salt: + ckksKeys: + reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:arrayOfTLKShares forSelector:@selector(vouchWithRecoveryKeyWithContainer: context: recoveryKey: @@ -95,10 +119,6 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) tlkShares: reply:) argumentIndex:4 ofReply:NO]; - [interface setClasses:[NSSet setWithObject:[TPPolicy class]] forSelector:@selector(fetchPolicyWithContainer: - context: - reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:trustedPeersHelperPeerState forSelector:@selector(updateWithContainer: context: deviceName: @@ -106,6 +126,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) osVersion: policyVersion: policySecrets: + syncUserControllableViews: reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:trustedPeersHelperPeerState forSelector:@selector(fetchTrustStateWithContainer: @@ -133,9 +154,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) } @catch(NSException* e) { secerror("TrustedPeersHelperSetupProtocol failed, continuing, but you might crash later: %@", e); -#if DEBUG @throw e; -#endif } #endif @@ -164,10 +183,10 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) - (NSString*)description { - return [NSString stringWithFormat:@"", + return [NSString stringWithFormat:@"", self.peerID, self.identityIsPreapproved, - (int64_t)self.peerStatus, + TPPeerStatusToString(self.peerStatus), self.memberChanges ? @"YES" : @"NO", self.unknownMachineIDsPresent ? @"YES" : @"NO", self.osVersion?:@"unknown"]; @@ -203,6 +222,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) @implementation TrustedPeersHelperEgoPeerStatus - (instancetype)initWithEgoPeerID:(NSString* _Nullable)egoPeerID + egoPeerMachineID:(NSString* _Nullable)egoPeerMachineID status:(TPPeerStatus)egoStatus viablePeerCountsByModelID:(NSDictionary*)viablePeerCountsByModelID peerCountsByMachineID:(NSDictionary * _Nonnull)peerCountsByMachineID @@ -211,6 +231,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) { if((self = [super init])) { _egoPeerID = egoPeerID; + _egoPeerMachineID = egoPeerMachineID; _egoStatus = egoStatus; _viablePeerCountsByModelID = viablePeerCountsByModelID; _peerCountsByMachineID = peerCountsByMachineID; @@ -226,7 +247,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) - (NSString*)description { - return [NSString stringWithFormat:@"", self.egoPeerID]; + return [NSString stringWithFormat:@"", self.egoPeerID, self.egoPeerMachineID]; } + (BOOL)supportsSecureCoding { @@ -236,6 +257,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) - (instancetype)initWithCoder:(NSCoder *)coder { if ((self = [super init])) { _egoPeerID = [coder decodeObjectOfClass:[NSString class] forKey:@"peerID"]; + _egoPeerMachineID = [coder decodeObjectOfClass:[NSString class] forKey:@"mID"]; _egoStatus = (TPPeerStatus)[coder decodeInt64ForKey:@"egoStatus"]; _viablePeerCountsByModelID = [coder decodeObjectOfClasses:[NSSet setWithArray:@[[NSDictionary class], [NSString class], [NSNumber class]]] forKey:@"viablePeerCountsByModelID"]; _numberOfPeersInOctagon = 0; @@ -253,6 +275,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:self.egoPeerID forKey:@"peerID"]; + [coder encodeObject:self.egoPeerMachineID forKey:@"mID"]; [coder encodeInt64:self.egoStatus forKey:@"egoStatus"]; [coder encodeObject:self.viablePeerCountsByModelID forKey:@"viablePeerCountsByModelID"]; [coder encodeObject:self.peerCountsByMachineID forKey:@"peerCountsByMachineID"]; diff --git a/keychain/TrustedPeersHelper/Utils.swift b/keychain/TrustedPeersHelper/Utils.swift index 6293393d..a4aeb996 100644 --- a/keychain/TrustedPeersHelper/Utils.swift +++ b/keychain/TrustedPeersHelper/Utils.swift @@ -58,3 +58,13 @@ extension SignedPeerDynamicInfo { return TPPeerDynamicInfo(data: self.peerDynamicInfo, sig: self.sig) } } + +extension TPPolicyVersion: Comparable { + public static func < (lhs: TPPolicyVersion, rhs: TPPolicyVersion) -> Bool { + if lhs.versionNumber != rhs.versionNumber { + return lhs.versionNumber < rhs.versionNumber + } else { + return lhs.policyHash < rhs.policyHash + } + } +} diff --git a/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb b/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb new file mode 100644 index 00000000..a3d85d50 --- /dev/null +++ b/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb @@ -0,0 +1,41 @@ +(version 1) + +(define (home-subpath home-relative-subpath) + (subpath (string-append (param "HOME") home-relative-subpath))) + +(deny default) +(deny file-map-executable iokit-get-properties process-info* nvram*) +(deny dynamic-code-generation) + +(deny mach-priv-host-port) +(import "system.sb") +(import "com.apple.corefoundation.sb") +(corefoundation) + +(allow distributed-notification-post) + +(allow process-info* (target self)) +(allow process-info-codesignature) + +(allow file-read-metadata) + +(allow file-read* file-write* + (home-subpath "/Library/Keychains/")) + +(allow mach-lookup + (global-name "com.apple.cloudd") + (global-name "com.apple.apsd") + (global-name "com.apple.securityd.xpc") + (global-name "com.apple.security.sfkeychainserver") + (global-name "com.apple.SecurityServer") + (global-name "com.apple.lsd.mapdb") +) + +(allow user-preference-read + (preference-domain "kCFPreferencesAnyApplication") +) + +(allow file-read* file-write* + (subpath "/private/var/db/mds/") + (subpath "/Library/Keychains/") +) diff --git a/keychain/TrustedPeersHelper/main.swift b/keychain/TrustedPeersHelper/main.swift index 7111e5b9..3f98b40d 100644 --- a/keychain/TrustedPeersHelper/main.swift +++ b/keychain/TrustedPeersHelper/main.swift @@ -30,23 +30,23 @@ class ServiceDelegate: NSObject, NSXPCListenerDelegate { func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool { let tphEntitlement = "com.apple.private.trustedpeershelper.client" - os_log("Received a new client: %@", log: tplogDebug, type: .default, newConnection) + os_log("Received a new client: %{public}@", log: tplogDebug, type: .default, newConnection) switch newConnection.value(forEntitlement: tphEntitlement) { case 1 as Int: - os_log("client has entitlement '%@'", log: tplogDebug, type: .default, tphEntitlement) + os_log("client has entitlement '%{public}@'", log: tplogDebug, type: .default, tphEntitlement) case true as Bool: - os_log("client has entitlement '%@'", log: tplogDebug, type: .default, tphEntitlement) + os_log("client has entitlement '%{public}@'", log: tplogDebug, type: .default, tphEntitlement) case let someInt as Int: - os_log("client(%@) has wrong integer value for '%@' (%d), rejecting", log: tplogDebug, type: .default, newConnection, tphEntitlement, someInt) + os_log("client(%{public}@) has wrong integer value for '%{public}@' (%d), rejecting", log: tplogDebug, type: .default, newConnection, tphEntitlement, someInt) return false case let someBool as Bool: - os_log("client(%@) has wrong boolean value for '%@' (%d), rejecting", log: tplogDebug, type: .default, newConnection, tphEntitlement, someBool) + os_log("client(%{public}@) has wrong boolean value for '%{public}@' (%d), rejecting", log: tplogDebug, type: .default, newConnection, tphEntitlement, someBool) return false default: - os_log("client(%@) is missing entitlement '%@', rejecting", log: tplogDebug, type: .default, newConnection, tphEntitlement) + os_log("client(%{public}@) is missing entitlement '%{public}@', rejecting", log: tplogDebug, type: .default, newConnection, tphEntitlement) return false } @@ -59,11 +59,42 @@ class ServiceDelegate: NSObject, NSXPCListenerDelegate { } } +#if os(macOS) +public func withArrayOfCStrings( + _ args: [String], + _ body: ([UnsafePointer?]) -> R +) -> R { + var mutableCStrings = args.map { strdup($0) } + mutableCStrings.append(nil) + + let cStrings = mutableCStrings.map { UnsafePointer($0) } + + defer { + mutableCStrings.forEach { free($0) } + } + return body(cStrings) +} + +withArrayOfCStrings(["HOME", NSHomeDirectory()]) { parameters in + var sandboxErrors: UnsafeMutablePointer? + + let rc = sandbox_init_with_parameters("com.apple.TrustedPeersHelper", UInt64(SANDBOX_NAMED), parameters, &sandboxErrors) + guard rc == 0 else { + let printableMessage = sandboxErrors.map { String(cString: $0 ) } + os_log("Unable to enter sandbox. Error code:%d message: %@", log: tplogDebug, type: .default, rc, printableMessage ?? "no printable message") + sandbox_free_error(sandboxErrors) + abort() + } + os_log("Sandbox entered", log: tplogDebug, type: .default) +} +#endif + os_log("Starting up", log: tplogDebug, type: .default) ValueTransformer.setValueTransformer(SetValueTransformer(), forName: SetValueTransformer.name) let delegate = ServiceDelegate() let listener = NSXPCListener.service() + listener.delegate = delegate listener.resume() diff --git a/keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h b/keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h index 926ae2d0..0afee106 100644 --- a/keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h +++ b/keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h @@ -5,7 +5,6 @@ #import #import -@class OTPrivateKey; @class OTPrivateKey; #ifdef __cplusplus diff --git a/keychain/TrustedPeersHelperUnitTests/.swiftlint.yml b/keychain/TrustedPeersHelperUnitTests/.swiftlint.yml new file mode 100644 index 00000000..f8391d9b --- /dev/null +++ b/keychain/TrustedPeersHelperUnitTests/.swiftlint.yml @@ -0,0 +1,4 @@ +disabled_rules: + - force_cast + - force_try + - implicitly_unwrapped_optional diff --git a/keychain/TrustedPeersHelperUnitTests/ContainerSync.swift b/keychain/TrustedPeersHelperUnitTests/ContainerSync.swift index f3b3eb19..e7e07646 100644 --- a/keychain/TrustedPeersHelperUnitTests/ContainerSync.swift +++ b/keychain/TrustedPeersHelperUnitTests/ContainerSync.swift @@ -8,7 +8,6 @@ import XCTest extension Container { - func dumpSync(test: XCTestCase) -> ([AnyHashable: Any]?, Error?) { let expectation = XCTestExpectation(description: "dump replied") var reta: [AnyHashable: Any]?, reterr: Error? @@ -52,13 +51,15 @@ extension Container { deviceName: String = "test device name", serialNumber: String = "456", osVersion: String = "123", - policyVersion: UInt64? = nil, + policyVersion: TPPolicyVersion? = nil, policySecrets: [String: Data]? = nil, + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus = .UNKNOWN, signingPrivateKeyPersistentRef: Data? = nil, encryptionPrivateKeyPersistentRef: Data? = nil - ) -> (String?, Data?, Data?, Data?, Data?, Error?) { + ) -> (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "prepare replied") var reta: String?, retb: Data?, retc: Data?, retd: Data?, rete: Data?, reterr: Error? + var retpolicy: TPSyncingPolicy? self.prepare(epoch: epoch, machineID: machineID, bottleSalt: bottleSalt, @@ -69,37 +70,41 @@ extension Container { osVersion: osVersion, policyVersion: policyVersion, policySecrets: policySecrets, + syncUserControllableViews: syncUserControllableViews, signingPrivateKeyPersistentRef: signingPrivateKeyPersistentRef, encryptionPrivateKeyPersistentRef: encryptionPrivateKeyPersistentRef - ) { a, b, c, d, e, err in + ) { a, b, c, d, e, f, err in reta = a retb = b retc = c retd = d rete = e + retpolicy = f reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retb, retc, retd, rete, reterr) + return (reta, retb, retc, retd, rete, retpolicy, reterr) } func establishSync(test: XCTestCase, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data]?) -> (String?, [CKRecord], Error?) { + preapprovedKeys: [Data]?) -> (String?, [CKRecord], TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "prepare replied") var reta: String?, retkhr: [CKRecord]?, reterr: Error? + var retpolicy: TPSyncingPolicy? self.establish(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { a, khr, err in + preapprovedKeys: preapprovedKeys) { a, khr, policy, err in reta = a retkhr = khr + retpolicy = policy reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retkhr!, reterr) + return (reta, retkhr!, retpolicy, reterr) } func vouchSync(test: XCTestCase, @@ -126,29 +131,35 @@ extension Container { return (reta, retb, reterr) } - func preflightVouchWithBottleSync(test: XCTestCase, bottleID: String) -> (String?, Error?) { + func preflightVouchWithBottleSync(test: XCTestCase, bottleID: String) -> (String?, TPSyncingPolicy?, Bool, Error?) { let expectation = XCTestExpectation(description: "preflightVouchWithBottle replied") var reta: String?, reterr: Error? - self.preflightVouchWithBottle(bottleID: bottleID) { a, err in + var retrefetched: Bool = false + var retpolicy: TPSyncingPolicy? + self.preflightVouchWithBottle(bottleID: bottleID) { a, policy, refetched, err in reta = a + retpolicy = policy + retrefetched = refetched reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, reterr) + return (reta, retpolicy, retrefetched, reterr) } - func vouchWithBottleSync(test: XCTestCase, b: String, entropy: Data, bottleSalt: String, tlkShares: [CKKSTLKShare]) -> (Data?, Data?, Error?) { + func vouchWithBottleSync(test: XCTestCase, b: String, entropy: Data, bottleSalt: String, tlkShares: [CKKSTLKShare]) -> (Data?, Data?, Int64, Int64, Error?) { let expectation = XCTestExpectation(description: "vouchWithBottle replied") - var reta: Data?, retb: Data?, reterr: Error? - self.vouchWithBottle(bottleID: b, entropy: entropy, bottleSalt: bottleSalt, tlkShares: tlkShares) { a, b, err in + var reta: Data?, retb: Data?, retc: Int64 = 0, retd: Int64 = 0, reterr: Error? + self.vouchWithBottle(bottleID: b, entropy: entropy, bottleSalt: bottleSalt, tlkShares: tlkShares) { a, b, c, d, err in reta = a retb = b + retc = c + retd = d reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retb, reterr) + return (reta, retb, retc, retd, reterr) } func joinSync(test: XCTestCase, @@ -156,69 +167,78 @@ extension Container { voucherSig: Data, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, Error?) { + preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "join replied") var reta: String?, retkhr: [CKRecord]?, reterr: Error? + var retpolicy: TPSyncingPolicy? self.join(voucherData: voucherData, voucherSig: voucherSig, ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { a, khr, err in + preapprovedKeys: preapprovedKeys) { a, khr, policy, err in reta = a retkhr = khr + retpolicy = policy reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retkhr, reterr) + return (reta, retkhr, retpolicy, reterr) } func preapprovedJoinSync(test: XCTestCase, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, Error?) { + preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "preapprovedjoin replied") var reta: String? var retkhr: [CKRecord]? + var retpolicy: TPSyncingPolicy? var reterr: Error? self.preapprovedJoin(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { a, khr, err in + preapprovedKeys: preapprovedKeys) { a, khr, policy, err in reta = a retkhr = khr + retpolicy = policy reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retkhr, reterr) + return (reta, retkhr, retpolicy, reterr) } func updateSync(test: XCTestCase, deviceName: String? = nil, - serialNumner: String? = nil, + serialNumber: String? = nil, osVersion: String? = nil, policyVersion: UInt64? = nil, - policySecrets: [String: Data]? = nil) -> (TrustedPeersHelperPeerState?, Error?) { + policySecrets: [String: Data]? = nil, + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus? = nil) -> (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "update replied") var reterr: Error? var retstate: TrustedPeersHelperPeerState? + var retpolicy: TPSyncingPolicy? self.update(deviceName: deviceName, - serialNumber: serialNumner, + serialNumber: serialNumber, osVersion: osVersion, policyVersion: policyVersion, - policySecrets: policySecrets) { state, err in + policySecrets: policySecrets, + syncUserControllableViews: syncUserControllableViews) { state, policy, err in retstate = state + retpolicy = policy reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (retstate, reterr) + return (retstate, retpolicy, reterr) } - func setAllowedMachineIDsSync(test: XCTestCase, allowedMachineIDs: Set, listDifference: Bool = true) -> (Error?) { + func setAllowedMachineIDsSync(test: XCTestCase, allowedMachineIDs: Set, accountIsDemo: Bool, listDifference: Bool = true) -> (Error?) { let expectation = XCTestExpectation(description: "setAllowedMachineIDs replied") var reterr: Error? - self.setAllowedMachineIDs(allowedMachineIDs) { differences, err in + let honorIDMSListChanges = accountIsDemo ? false : true + self.setAllowedMachineIDs(allowedMachineIDs, honorIDMSListChanges: honorIDMSListChanges) { differences, err in XCTAssertEqual(differences, listDifference, "Reported list difference should match expectation") reterr = err expectation.fulfill() @@ -253,7 +273,7 @@ extension Container { let expectation = XCTestExpectation(description: "fetchMIDList replied") var retlist: Set? var reterr: Error? - self.fetchAllowedMachineIDs() { list, err in + self.fetchAllowedMachineIDs { list, err in retlist = list reterr = err expectation.fulfill() @@ -301,21 +321,22 @@ extension Container { do { secret = try loadSecret(label: label) } catch { - } return secret } - func setRecoveryKeySync(test: XCTestCase, recoveryKey: String, recoverySalt: String, ckksKeys: [CKKSKeychainBackedKeySet]) -> (Error?) { + func setRecoveryKeySync(test: XCTestCase, recoveryKey: String, recoverySalt: String, ckksKeys: [CKKSKeychainBackedKeySet]) -> ([CKRecord]?, Error?) { let expectation = XCTestExpectation(description: "setRecoveryKey replied") + var retrecords: [CKRecord]? var reterr: Error? - self.setRecoveryKey(recoveryKey: recoveryKey, salt: recoverySalt, ckksKeys: ckksKeys) { error in + self.setRecoveryKey(recoveryKey: recoveryKey, salt: recoverySalt, ckksKeys: ckksKeys) { records, error in + retrecords = records reterr = error expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reterr) + return (retrecords, reterr) } func fetchViableBottlesSync(test: XCTestCase) -> ([String]?, [String]?, Error?) { @@ -336,6 +357,7 @@ extension Container { func trustStatusSync(test: XCTestCase) -> (TrustedPeersHelperEgoPeerStatus, Error?) { let expectation = XCTestExpectation(description: "trustStatus replied") var retEgoStatus = TrustedPeersHelperEgoPeerStatus(egoPeerID: nil, + egoPeerMachineID: nil, status: .unknown, viablePeerCountsByModelID: [:], peerCountsByMachineID: [:], @@ -352,10 +374,10 @@ extension Container { } func fetchPolicyDocumentsSync(test: XCTestCase, - keys: [NSNumber: String]) -> ([NSNumber: [String]]?, Error?) { + versions: Set) -> ([TPPolicyVersion: Data]?, Error?) { let expectation = XCTestExpectation(description: "fetchPolicyDocuments replied") - var reta: [NSNumber: [String]]?, reterr: Error? - self.fetchPolicyDocuments(keys: keys) { a, err in + var reta: [TPPolicyVersion: Data]?, reterr: Error? + self.fetchPolicyDocuments(versions: versions) { a, err in reta = a reterr = err expectation.fulfill() @@ -364,6 +386,20 @@ extension Container { return (reta, reterr) } + func fetchCurrentPolicySync(test: XCTestCase) -> (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) { + let expectation = XCTestExpectation(description: "fetchCurrentPolicy replied") + var reta: TPSyncingPolicy?, reterr: Error? + var retOp: TPPBPeerStableInfo_UserControllableViewStatus = .UNKNOWN + self.fetchCurrentPolicy(modelIDOverride: nil) { a, peerOpinion, err in + reta = a + retOp = peerOpinion + reterr = err + expectation.fulfill() + } + test.wait(for: [expectation], timeout: 10.0) + return (reta, retOp, reterr) + } + func fetchEscrowContentsSync(test: XCTestCase) -> (Data?, String?, Data?, Error?) { let expectation = XCTestExpectation(description: "fetchEscrowContents replied") var retentropy: Data? @@ -383,22 +419,24 @@ extension Container { return (retentropy, retbottleID, retspki, reterror) } - func requestHealthCheckSync(requiresEscrowCheck: Bool, test: XCTestCase) -> (Bool, Bool, Bool, Error?) { + func requestHealthCheckSync(requiresEscrowCheck: Bool, test: XCTestCase) -> (Bool, Bool, Bool, Bool, Error?) { let expectation = XCTestExpectation(description: "requestHealthCheck replied") var retrepairaccount: Bool = false var retrepairescrow: Bool = false var retresetoctagon: Bool = false + var retleavetrust: Bool = false var reterror: Error? - self.requestHealthCheck(requiresEscrowCheck: requiresEscrowCheck) { repairAccount, repairEscrow, resetOctagon, error in + self.requestHealthCheck(requiresEscrowCheck: requiresEscrowCheck) { repairAccount, repairEscrow, resetOctagon, leaveTrust, error in retrepairaccount = repairAccount retrepairescrow = repairEscrow retresetoctagon = resetOctagon + retleavetrust = leaveTrust reterror = error expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (retrepairaccount, retrepairescrow, retresetoctagon, reterror) + return (retrepairaccount, retrepairescrow, retresetoctagon, retleavetrust, reterror) } } diff --git a/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift b/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift index fbef651a..5332b5ef 100644 --- a/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift +++ b/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift @@ -6,14 +6,9 @@ // import CloudKitCode +import CloudKitCodeProtobuf import Foundation -enum FakeCuttlefishError: Error { - case notEmpty - case unknownChangeToken - case unknownPeerID -} - enum FakeCuttlefishOpinion { case trusts case trustsByPreapproval @@ -66,16 +61,20 @@ struct FakeCuttlefishAssertion: CustomStringConvertible { } } -@objc class FakeCuttlefishNotify: NSObject { +@objc +class FakeCuttlefishNotify: NSObject { let pushes: (Data) -> Void let containerName: String - @objc init(_ containerName: String, pushes: @escaping (Data) -> Void) { + + @objc + init(_ containerName: String, pushes: @escaping (Data) -> Void) { self.containerName = containerName self.pushes = pushes } - @objc public func notify(_ function: String) throws { - let notification: [String: Dictionary] = [ + @objc + func notify(_ function: String) throws { + let notification: [String: [String: Any]] = [ "aps": ["content-available": 1], "cf": [ "f": function, @@ -99,7 +98,7 @@ extension ViewKey { record[SecCKRecordWrappedKeyKey] = self.wrappedkeyBase64 - switch(self.keyclass) { + switch self.keyclass { case .tlk: record[SecCKRecordKeyClassKey] = "tlk" case .classA: @@ -110,7 +109,7 @@ extension ViewKey { abort() } - if self.parentkeyUuid.count > 0 { + if !self.parentkeyUuid.isEmpty { // TODO: no idea how to tell it about the 'verify' action record[SecCKRecordParentKeyRefKey] = CKRecord.Reference(recordID: CKRecord.ID(__recordName: self.parentkeyUuid, zoneID: zoneID), action: .none) } @@ -120,7 +119,7 @@ extension ViewKey { func fakeKeyPointer(zoneID: CKRecordZone.ID) -> CKRecord { let recordName: String - switch(self.keyclass) { + switch self.keyclass { case .tlk: recordName = "tlk" case .classA: @@ -165,18 +164,44 @@ extension TLKShare { } class FakeCuttlefishServer: CuttlefishAPIAsync { - + struct State { var peersByID: [String: Peer] = [:] var recoverySigningPubKey: Data? var recoveryEncryptionPubKey: Data? var bottles: [Bottle] = [] + var escrowRecords: [EscrowInformation] = [] var viewKeys: [CKRecordZone.ID: ViewKeys] = [:] var tlkShares: [CKRecordZone.ID: [TLKShare]] = [:] init() { } + + func model(updating newPeer: Peer?) throws -> TPModel { + let model = TPModel(decrypter: Decrypter()) + + for existingPeer in self.peersByID.values { + if let pi = existingPeer.permanentInfoAndSig.toPermanentInfo(peerID: existingPeer.peerID), + let si = existingPeer.stableInfoAndSig.toStableInfo(), + let di = existingPeer.dynamicInfoAndSig.toDynamicInfo() { + model.registerPeer(with: pi) + try model.update(si, forPeerWithID: existingPeer.peerID) + try model.update(di, forPeerWithID: existingPeer.peerID) + } + } + + if let peerUpdate = newPeer { + // This peer needs to have been in the model before; on pain of throwing here + if let si = peerUpdate.stableInfoAndSig.toStableInfo(), + let di = peerUpdate.dynamicInfoAndSig.toDynamicInfo() { + try model.update(si, forPeerWithID: peerUpdate.peerID) + try model.update(di, forPeerWithID: peerUpdate.peerID) + } + } + + return model + } } var state = State() @@ -191,6 +216,9 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { // @property (nullable) NSMutableDictionary* keys; var ckksZoneKeys: NSMutableDictionary + var injectLegacyEscrowRecords: Bool = false + var includeEscrowRecords: Bool = true + var nextFetchErrors: [Error] = [] var fetchViableBottlesError: [Error] = [] var nextJoinErrors: [Error] = [] @@ -199,8 +227,12 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { var returnRepairAccountResponse: Bool = false var returnRepairEscrowResponse: Bool = false var returnResetOctagonResponse: Bool = false + var returnLeaveTrustResponse: Bool = false var returnRepairErrorResponse: Error? var fetchChangesCalledCount: Int = 0 + var fetchChangesReturnEmptyResponse: Bool = false + + var fetchViableBottlesEscrowRecordCacheTimeout: TimeInterval = 2.0 var nextEstablishReturnsMoreChanges: Bool = false @@ -211,6 +243,10 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { var healthListener: ((GetRepairActionRequest) -> NSError?)? var fetchViableBottlesListener: ((FetchViableBottlesRequest) -> NSError?)? var resetListener: ((ResetRequest) -> NSError?)? + var setRecoveryKeyListener: ((SetRecoveryKeyRequest) -> NSError?)? + + // Any policies in here will be returned by FetchPolicy before any inbuilt policies + var policyOverlay: [TPPolicyDocument] = [] var fetchViableBottlesDontReturnBottleWithID: String? @@ -259,7 +295,7 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { return Changes.with { changes in changes.changeToken = self.currentChangeToken - changes.differences = self.state.peersByID.compactMap({ (key: String, value: Peer) -> PeerDifference? in + changes.differences = self.state.peersByID.compactMap { (key: String, value: Peer) -> PeerDifference? in let old = snapshot.peersByID[key] if old == nil { return PeerDifference.with { @@ -272,9 +308,9 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } else { return nil } - }) + } snapshot.peersByID.forEach { (key: String, _: Peer) in - if nil == self.state.peersByID[key] { + if self.state.peersByID[key] == nil { changes.differences.append(PeerDifference.with { $0.remove = Peer.with { $0.peerID = key @@ -289,7 +325,6 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { if self.state.recoveryEncryptionPubKey != snapshot.recoveryEncryptionPubKey { changes.recoveryEncryptionPubKey = self.state.recoveryEncryptionPubKey ?? Data() } - } } @@ -402,7 +437,6 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { let record = share.fakeRecord(zoneID: rzid) fakeZone.add(toZone: record) allRecords.append(record) - } else { print("Received an unexpected zone id: \(rzid)") } @@ -414,7 +448,7 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { func establish(_ request: EstablishRequest, completion: @escaping (EstablishResponse?, Error?) -> Void) { print("FakeCuttlefish: establish called") if !self.state.peersByID.isEmpty { - completion(nil, FakeCuttlefishError.notEmpty) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .establishFailed)) } // Before performing write, check if we should error @@ -434,6 +468,38 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { self.state.peersByID[request.peer.peerID] = request.peer self.state.bottles.append(request.bottle) + let escrowInformation = EscrowInformation.with { + $0.label = "com.apple.icdp.record." + request.bottle.bottleID + $0.creationDate = Google_Protobuf_Timestamp(date: Date()) + $0.remainingAttempts = 10 + $0.silentAttemptAllowed = 1 + $0.recordStatus = .valid + let e = EscrowInformation.Metadata.with { + $0.backupKeybagDigest = Data() + $0.secureBackupUsesMultipleIcscs = 1 + $0.secureBackupTimestamp = Google_Protobuf_Timestamp(date: Date()) + $0.peerInfo = Data() + $0.bottleID = request.bottle.bottleID + $0.escrowedSpki = request.bottle.escrowedSigningSpki + let cm = EscrowInformation.Metadata.ClientMetadata.with { + $0.deviceColor = "#202020" + $0.deviceEnclosureColor = "#020202" + $0.deviceModel = "model" + $0.deviceModelClass = "modelClass" + $0.deviceModelVersion = "modelVersion" + $0.deviceMid = "mid" + $0.deviceName = "my device" + $0.devicePlatform = 1 + $0.secureBackupNumericPassphraseLength = 6 + $0.secureBackupMetadataTimestamp = Google_Protobuf_Timestamp(date: Date()) + $0.secureBackupUsesNumericPassphrase = 1 + $0.secureBackupUsesComplexPassphrase = 1 + } + $0.clientMetadata = cm + } + $0.escrowInformationMetadata = e + } + self.state.escrowRecords.append(escrowInformation) var keyRecords: [CKRecord] = [] keyRecords.append(contentsOf: store(viewKeys: request.viewKeys)) @@ -482,12 +548,43 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } guard let snapshot = self.snapshotsByChangeToken[request.changeToken] else { - completion(nil, FakeCuttlefishError.unknownChangeToken) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) return } self.state.peersByID[request.peer.peerID] = request.peer self.state.bottles.append(request.bottle) - + let escrowInformation = EscrowInformation.with { + $0.label = "com.apple.icdp.record." + request.bottle.bottleID + $0.creationDate = Google_Protobuf_Timestamp(date: Date()) + $0.remainingAttempts = 10 + $0.silentAttemptAllowed = 1 + $0.recordStatus = .valid + let e = EscrowInformation.Metadata.with { + $0.backupKeybagDigest = Data() + $0.secureBackupUsesMultipleIcscs = 1 + $0.secureBackupTimestamp = Google_Protobuf_Timestamp(date: Date()) + $0.peerInfo = Data() + $0.bottleID = request.bottle.bottleID + $0.escrowedSpki = request.bottle.escrowedSigningSpki + let cm = EscrowInformation.Metadata.ClientMetadata.with { + $0.deviceColor = "#202020" + $0.deviceEnclosureColor = "#020202" + $0.deviceModel = "model" + $0.deviceModelClass = "modelClass" + $0.deviceModelVersion = "modelVersion" + $0.deviceMid = "mid" + $0.deviceName = "my device" + $0.devicePlatform = 1 + $0.secureBackupNumericPassphraseLength = 6 + $0.secureBackupMetadataTimestamp = Google_Protobuf_Timestamp(date: Date()) + $0.secureBackupUsesNumericPassphrase = 1 + $0.secureBackupUsesComplexPassphrase = 1 + } + $0.clientMetadata = cm + } + $0.escrowInformationMetadata = e + } + self.state.escrowRecords.append(escrowInformation) var keyRecords: [CKRecord] = [] keyRecords.append(contentsOf: store(viewKeys: request.viewKeys)) keyRecords.append(contentsOf: store(tlkShares: request.tlkShares)) @@ -512,20 +609,16 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } guard let snapshot = self.snapshotsByChangeToken[request.changeToken] else { - completion(nil, FakeCuttlefishError.unknownChangeToken) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) return } - guard var peer = self.state.peersByID[request.peerID] else { - completion(nil, FakeCuttlefishError.unknownPeerID) + guard let existingPeer = self.state.peersByID[request.peerID] else { + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .updateTrustPeerNotFound)) return } - if request.hasStableInfoAndSig { - peer.stableInfoAndSig = request.stableInfoAndSig - } - if request.hasDynamicInfoAndSig { - peer.dynamicInfoAndSig = request.dynamicInfoAndSig - } - self.state.peersByID[request.peerID] = peer + + // copy Peer so that we can update it safely + var peer = try! Peer(serializedData: try! existingPeer.serializedData()) // Before performing write, check if we should error if let updateListener = self.updateListener { @@ -536,6 +629,32 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } } + if request.hasStableInfoAndSig { + peer.stableInfoAndSig = request.stableInfoAndSig + } + if request.hasDynamicInfoAndSig { + peer.dynamicInfoAndSig = request.dynamicInfoAndSig + } + + // Will Cuttlefish reject this due to peer graph issues? + do { + let model = try self.state.model(updating: peer) + + // Is there any non-excluded peer that trusts itself? + let nonExcludedPeerIDs = model.allPeerIDs().filter { !model.statusOfPeer(withID: $0).contains(.excluded) } + let selfTrustedPeerIDs = nonExcludedPeerIDs.filter { model.statusOfPeer(withID: $0).contains(.selfTrust) } + + guard selfTrustedPeerIDs.count > 0 else { + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .resultGraphHasNoPotentiallyTrustedPeers)) + return + } + } catch { + print("FakeCuttlefish: updateTrust failed to make model: ", String(describing: error)) + } + + // Cuttlefish has accepted the write. + self.state.peersByID[request.peerID] = peer + // Also check if we should bail due to conflicting viewKeys if self.newKeysConflict(viewKeys: request.viewKeys) { completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .keyHierarchyAlreadyExists)) @@ -562,16 +681,31 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { func setRecoveryKey(_ request: SetRecoveryKeyRequest, completion: @escaping (SetRecoveryKeyResponse?, Error?) -> Void) { print("FakeCuttlefish: setRecoveryKey called") + + if let listener = self.setRecoveryKeyListener { + let operationError = listener(request) + guard operationError == nil else { + completion(nil, operationError) + return + } + } + guard let snapshot = self.snapshotsByChangeToken[request.changeToken] else { - completion(nil, FakeCuttlefishError.unknownChangeToken) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) return } self.state.recoverySigningPubKey = request.recoverySigningPubKey self.state.recoveryEncryptionPubKey = request.recoveryEncryptionPubKey self.state.peersByID[request.peerID]?.stableInfoAndSig = request.stableInfoAndSig + + var keyRecords: [CKRecord] = [] + //keyRecords.append(contentsOf: store(viewKeys: request.viewKeys)) + keyRecords.append(contentsOf: store(tlkShares: request.tlkShares)) + self.makeSnapshot() completion(SetRecoveryKeyResponse.with { $0.changes = self.changesSince(snapshot: snapshot) + $0.zoneKeyHierarchyRecords = keyRecords.map { try! CloudKitCode.Ckcode_RecordTransport($0) } }, nil) self.pushNotify("setRecoveryKey") } @@ -587,6 +721,10 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { completion(nil, possibleError) return } + if fetchChangesReturnEmptyResponse == true { + completion(FetchChangesResponse(), nil) + return + } } if let injectedError = self.nextFetchErrors.first { @@ -597,11 +735,11 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } let snapshot: State - if request.changeToken == "" { + if request.changeToken.isEmpty { snapshot = State() } else { guard let s = self.snapshotsByChangeToken[request.changeToken] else { - completion(nil, FakeCuttlefishError.unknownChangeToken) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) return } snapshot = s @@ -615,7 +753,7 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { func fetchViableBottles(_ request: FetchViableBottlesRequest, completion: @escaping (FetchViableBottlesResponse?, Error?) -> Void) { print("FakeCuttlefish: fetchViableBottles called") - + if let fetchViableBottlesListener = self.fetchViableBottlesListener { let possibleError = fetchViableBottlesListener(request) guard possibleError == nil else { @@ -631,14 +769,29 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { return } + var legacy: [EscrowInformation] = [] + if self.injectLegacyEscrowRecords { + print("FakeCuttlefish: fetchViableBottles injecting legacy records") + let record = EscrowInformation.with { + $0.label = "fake-label" + } + legacy.append(record) + } let bottles = self.state.bottles.filter { $0.bottleID != fetchViableBottlesDontReturnBottleWithID } + completion(FetchViableBottlesResponse.with { $0.viableBottles = bottles.compactMap { bottle in EscrowPair.with { $0.escrowRecordID = bottle.bottleID $0.bottle = bottle + if self.includeEscrowRecords { + $0.record = self.state.escrowRecords.first { $0.escrowInformationMetadata.bottleID == bottle.bottleID } ?? EscrowInformation() + } } } + if self.injectLegacyEscrowRecords { + $0.legacyRecords = legacy + } }, nil) } @@ -648,8 +801,15 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { var response = FetchPolicyDocumentsResponse() let policies = builtInPolicyDocuments() - let dummyPolicies = Dictionary(uniqueKeysWithValues: policies.map({ ($0.policyVersion, ($0.policyHash, $0.protobuf)) })) + let dummyPolicies = Dictionary(uniqueKeysWithValues: policies.map { ($0.version.versionNumber, ($0.version.policyHash, $0.protobuf)) }) + let overlayPolicies = Dictionary(uniqueKeysWithValues: self.policyOverlay.map { ($0.version.versionNumber, ($0.version.policyHash, $0.protobuf)) }) + for key in request.keys { + if let (hash, data) = overlayPolicies[key.version], hash == key.hash { + response.entries.append(PolicyDocumentMapEntry.with { $0.key = key; $0.value = data }) + continue + } + guard let (hash, data) = dummyPolicies[key.version] else { continue } @@ -703,6 +863,11 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { $0.repairAction = .resetOctagon } completion(response, nil) + } else if returnLeaveTrustResponse { + let response = GetRepairActionResponse.with { + $0.repairAction = .leaveTrust + } + completion(response, nil) } else if self.returnNoActionResponse { let response = GetRepairActionResponse.with { $0.repairAction = .noAction @@ -718,9 +883,23 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } } + func getClubCertificates(_: GetClubCertificatesRequest, completion: @escaping (GetClubCertificatesResponse?, Error?) -> Void) { + completion(GetClubCertificatesResponse(), nil) + } + func getSupportAppInfo(_: GetSupportAppInfoRequest, completion: @escaping (GetSupportAppInfoResponse?, Error?) -> Void) { completion(GetSupportAppInfoResponse(), nil) } + + func fetchSosiCloudIdentity(_: FetchSOSiCloudIdentityRequest, completion: @escaping (FetchSOSiCloudIdentityResponse?, Error?) -> Void) { + completion(FetchSOSiCloudIdentityResponse(), nil) + } + func addCustodianRecoveryKey(_: AddCustodianRecoveryKeyRequest, completion: @escaping (AddCustodianRecoveryKeyResponse?, Error?) -> Void) { + completion(AddCustodianRecoveryKeyResponse(), nil) + } + func resetAccountCdpcontents(_: ResetAccountCDPContentsRequest, completion: @escaping (ResetAccountCDPContentsResponse?, Error?) -> Void) { + completion(ResetAccountCDPContentsResponse(), nil) + } } extension FakeCuttlefishServer: CloudKitCode.Invocable { diff --git a/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift b/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift index 5d8d2c33..580b6034 100644 --- a/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift +++ b/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift @@ -15,13 +15,13 @@ enum Handler { case updateTrust((UpdateTrustRequest, @escaping (UpdateTrustResponse?, Error?) -> Void) -> Void) case setRecoveryKey((SetRecoveryKeyRequest, @escaping (SetRecoveryKeyResponse?, Error?) -> Void) -> Void) case fetchChanges((FetchChangesRequest, @escaping (FetchChangesResponse?, Error?) -> Void) -> Void) - case fetchViableBottles((FetchViableBottlesRequest, @escaping (FetchViableBottlesResponse?, Error?) -> Void) ->Void) + case fetchViableBottles((FetchViableBottlesRequest, @escaping (FetchViableBottlesResponse?, Error?) -> Void) -> Void) case fetchPolicyDocuments((FetchPolicyDocumentsRequest, @escaping (FetchPolicyDocumentsResponse?, Error?) -> Void) -> Void) } class MockCuttlefishAPIAsyncClient: CuttlefishAPIAsync { - + var handlers: [Handler] = [] var index: Int = 0 @@ -164,10 +164,20 @@ class MockCuttlefishAPIAsyncClient: CuttlefishAPIAsync { } func getRepairAction(_: GetRepairActionRequest, completion: @escaping (GetRepairActionResponse?, Error?) -> Void) { completion(GetRepairActionResponse(), nil) - } func getSupportAppInfo(_: GetSupportAppInfoRequest, completion: @escaping (GetSupportAppInfoResponse?, Error?) -> Void) { completion(GetSupportAppInfoResponse(), nil) } - + func getClubCertificates(_: GetClubCertificatesRequest, completion: @escaping (GetClubCertificatesResponse?, Error?) -> Void) { + completion(GetClubCertificatesResponse(), nil) + } + func fetchSosiCloudIdentity(_: FetchSOSiCloudIdentityRequest, completion: @escaping (FetchSOSiCloudIdentityResponse?, Error?) -> Void) { + completion(FetchSOSiCloudIdentityResponse(), nil) + } + func addCustodianRecoveryKey(_: AddCustodianRecoveryKeyRequest, completion: @escaping (AddCustodianRecoveryKeyResponse?, Error?) -> Void) { + completion(AddCustodianRecoveryKeyResponse(), nil) + } + func resetAccountCdpcontents(_: ResetAccountCDPContentsRequest, completion: @escaping (ResetAccountCDPContentsResponse?, Error?) -> Void) { + completion(ResetAccountCDPContentsResponse(), nil) + } } diff --git a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h index fc2d9223..1ab6328e 100644 --- a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h +++ b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h @@ -19,5 +19,7 @@ #import #import "keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h" +#import "keychain/securityd/SecItemDataSource.h" #import "keychain/ckks/tests/MockCloudKit.h" +#import diff --git a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests.swift b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests.swift index 7d7ecae1..d56102ab 100644 --- a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests.swift +++ b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests.swift @@ -5,6 +5,7 @@ // Created by Ben Williamson on 5/1/18. // +import CloudKitCodeProtobuf import CoreData import XCTest @@ -21,7 +22,6 @@ let recovery_signingKey_384 = Data(base64Encoded: "BK5nrmP6oitJHtGV2Josk5cUKnG3p let recovery_encryptionKey_384 = Data(base64Encoded: "BKkZpYHTbMi2yrWFo+ErM3HbcYJCngPuWDYoVUD7egKkmiHFvv1Bsk0j/Dcj3xTR12vj5QOpZQV3GzE5estf75BV+EZz1cjUUSi/MysfpKsqEbwYrhIEkmeyMGr7CVWQWRLR2LnoihnQajvWi1LmO0AoDl3+LzVgTJBjjDQ5ANyw0Yv1EgOgBvZsLA9UTN4oAg==") class TrustedPeersHelperUnitTests: XCTestCase { - var tmpPath: String! var tmpURL: URL! var cuttlefish: FakeCuttlefishServer! @@ -46,11 +46,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { cuttlefish = FakeCuttlefishServer(nil, ckZones: [:], ckksZoneKeys: [:]) // Make a new fake keychain - tmpPath = String(format: "/tmp/%@-%X", testName, arc4random()) + tmpPath = String(format: "/tmp/%@-%X", testName, Int.random(in: 0..<1000000)) tmpURL = URL(fileURLWithPath: tmpPath, isDirectory: true) do { try FileManager.default.createDirectory(atPath: String(format: "%@/Library/Keychains", tmpPath), withIntermediateDirectories: true, attributes: nil) - SetCustomHomeURLString(tmpPath as CFString) + SecSetCustomHomeURLString(tmpPath as CFString) SecKeychainDbReset(nil) } catch { XCTFail("setUp failed: \(error)") @@ -72,6 +72,23 @@ class TrustedPeersHelperUnitTests: XCTestCase { override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. cuttlefish = nil + + if let nskeychainDir : NSURL = SecCopyHomeURL(), let keychainDir : URL = nskeychainDir as URL? { + SecItemDataSourceFactoryReleaseAll() + SecKeychainDbForceClose() + SecKeychainDbReset(nil) + + // Only perform the destructive step if the url matches what we expect! + let testName = self.name.components(separatedBy: CharacterSet(charactersIn: " ]"))[1] + if keychainDir.path.hasPrefix("/tmp/" + testName) { + do { + try FileManager.default.removeItem(at: keychainDir) + } catch { + print("Failed to remove keychain directory: \(error)") + } + } + } + super.tearDown() } @@ -157,21 +174,31 @@ class TrustedPeersHelperUnitTests: XCTestCase { func establish(reload: Bool, store: NSPersistentStoreDescription) throws -> (Container, String) { - return try self.establish(reload: reload, contextID: OTDefaultContext, store: store) + return try self.establish(reload: reload, contextID: OTDefaultContext, accountIsDemo: false, store: store) } func establish(reload: Bool, contextID: String, allowedMachineIDs: Set = Set(["aaa", "bbb", "ccc"]), + accountIsDemo: Bool, + modelID: String = "iPhone1,1", + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus = .UNKNOWN, store: NSPersistentStoreDescription) throws -> (Container, String) { var container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: store, cuttlefish: cuttlefish) - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: allowedMachineIDs, listDifference: allowedMachineIDs.count > 0), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: allowedMachineIDs, accountIsDemo: accountIsDemo, listDifference: !allowedMachineIDs.isEmpty), "should be able to set allowed machine IDs") + + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, + epoch: 1, + machineID: "aaa", + bottleSalt: "123456789", + bottleID: UUID().uuidString, + modelID: modelID, + syncUserControllableViews: syncUserControllableViews) - let (peerID, permanentInfo, permanentInfoSig, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = container.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = container.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -183,15 +210,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = container.dumpSync(test: self) - if (reload) { + if reload { do { container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: store, cuttlefish: cuttlefish) } catch { - XCTFail() + XCTFail("Creating container errored: \(error)") } } - let (peerID2, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID2, _, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error2) XCTAssertNotNil(peerID2) @@ -202,24 +229,97 @@ class TrustedPeersHelperUnitTests: XCTestCase { func testEstablishWithReload() throws { let description = tmpStoreDescription(name: "container.db") - let (_, peerID) = try establish(reload: true, store: description) + let (container, peerID) = try establish(reload: true, store: description) assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + // With no other input, the syncing policy should say to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + XCTAssertEqual(policy?.syncUserControllableViews, .DISABLED, "Peer should not desire to sync user controllable views (as the client didn't have any input)") } func testEstablishNoReload() throws { let description = tmpStoreDescription(name: "container.db") - _ = try establish(reload: false, store: description) + let (container, peerID) = try establish(reload: false, store: description) + + assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + // With no other input, the syncing policy should say to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + XCTAssertEqual(policy?.syncUserControllableViews, .DISABLED, "Peer should not desire to sync user controllable views (as the client didn't have any input)") + } + + func testEstablishWithUserSyncableViews() throws { + let description = tmpStoreDescription(name: "container.db") + + let (container, peerID) = try self.establish(reload: false, + contextID: OTDefaultContext, + accountIsDemo: false, + syncUserControllableViews: .ENABLED, + store: description) + + assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + //The syncing policy should say not to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + + XCTAssertEqual(policy?.syncUserControllableViews, .ENABLED, "Peer should desire to sync user controllable views (per request)") + } + + func testEstablishWithoutUserSyncableViews() throws { + let description = tmpStoreDescription(name: "container.db") + + let (container, peerID) = try self.establish(reload: false, + contextID: OTDefaultContext, + accountIsDemo: false, + syncUserControllableViews: .DISABLED, + store: description) + + assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + //The syncing policy should say not to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + + XCTAssertEqual(policy?.syncUserControllableViews, .DISABLED, "Peer should not desire to sync user controllable views (per request)") + } + + func testEstablishWithoutUserSyncableViewsOnWatch() throws { + let description = tmpStoreDescription(name: "container.db") + + // Watches will listen to the input here. If we set FOLLOWING, it should remain FOLLOWING (as some watches don't have UI to change this value) + let (container, peerID) = try self.establish(reload: false, + contextID: OTDefaultContext, + accountIsDemo: false, + modelID: "Watch1,1", + syncUserControllableViews: .FOLLOWING, + store: description) + + assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + //The syncing policy should say not to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + + XCTAssertEqual(policy?.syncUserControllableViews, .FOLLOWING, "Peer should desire to sync user controllable views (ignoring the request)") } func testEstablishNotOnAllowListErrors() throws { let description = tmpStoreDescription(name: "container.db") let container = try Container(name: ContainerName(container: "test", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = container.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = container.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -232,9 +332,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { // Note that an empty machine ID list means "all are allowed", so an establish now will succeed // Now set up a machine ID list that positively does not have our peer - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa"]), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa"], accountIsDemo: false), "should be able to set allowed machine IDs") - let (peerID3, _, error3) = container.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID3, _, _, error3) = container.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNotNil(peerID3, "Should get a peer when you establish a now allow-listed peer") XCTAssertNil(error3, "Should not get an error when you establish a now allow-listed peer") } @@ -243,15 +343,16 @@ class TrustedPeersHelperUnitTests: XCTestCase { containerID: String, machineID: String, machineIDs: Set, + accountIsDemo: Bool, store: NSPersistentStoreDescription) throws -> (Container, String) { let c = try Container(name: ContainerName(container: containerID, context: OTDefaultContext), persistentStoreDescription: store, cuttlefish: cuttlefish) - XCTAssertNil(c.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, listDifference: machineIDs.count > 0), "Should be able to set machine IDs") + XCTAssertNil(c.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: accountIsDemo, listDifference: !machineIDs.isEmpty), "Should be able to set machine IDs") print("preparing \(containerID)") - let (peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error) = + let (peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error) = c.prepareSync(test: self, epoch: 1, machineID: machineID, bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(peerID) @@ -280,11 +381,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: peerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("\(containerID) joins") - let (joinedPeerID, _, joinError) = c.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [], - tlkShares: []) + let (joinedPeerID, _, _, joinError) = c.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) XCTAssertNil(joinError) XCTAssertEqual(joinedPeerID, peerID!) } @@ -299,16 +400,20 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerC = try Container(name: ContainerName(container: "c", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb", "ccc"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerC.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerC.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + XCTAssertNotNil(aPolicy, "Should have a syncing policy coming back from a successful prepare") + XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .UNKNOWN, "Policy coming back from prepare() should not have an opinion on views") + do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -320,17 +425,25 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } + do { + // With no other input, the syncing policy should say to sync user views + let (aPolicy, _, aPolicyError) = containerA.fetchCurrentPolicySync(test: self) + XCTAssertNil(aPolicyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(aPolicy, "Should have a syncing policy") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .DISABLED, "Peer should desire to not sync user controllable views (as the client didn't have any input)") + } + print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, error2) = + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -386,13 +499,16 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, error) = containerB.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [], - tlkShares: []) + let (peerID, _, bPolicy, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) XCTAssertNil(error) XCTAssertEqual(peerID, bPeerID!) + + XCTAssertNotNil(bPolicy, "Should have a syncing policy") + XCTAssertEqual(bPolicy?.syncUserControllableViews, .DISABLED, "Peer should desire to not sync user controllable views (following A's lead)") } _ = containerA.dumpSync(test: self) @@ -400,11 +516,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerC.dumpSync(test: self) print("preparing C") - let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, error4) = + let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _, error4) = containerC.prepareSync(test: self, epoch: 1, machineID: "ccc", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerC.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == cPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == cPeerID }, "should have a bottle for peer") let secret = containerC.loadSecretSync(test: self, label: cPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -438,14 +554,17 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: cPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("C joins") - let (peerID, _, error2) = containerC.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [self.manateeKeySet, provisionalEngramKeySet], - tlkShares: []) + let (peerID, _, cPolicy, error2) = containerC.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [self.manateeKeySet, provisionalEngramKeySet], + tlkShares: []) XCTAssertNil(error2) XCTAssertEqual(peerID, cPeerID!) + XCTAssertNotNil(cPolicy, "Should have a syncing policy") + XCTAssertEqual(cPolicy?.syncUserControllableViews, .DISABLED, "Peer should desire to not sync user controllable views (following A and B's lead)") + assertTLKShareFor(peerID: cPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) assertTLKShareFor(peerID: aPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) assertTLKShareFor(peerID: bPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) @@ -453,7 +572,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("A updates") do { - let (_, error) = containerA.updateSync(test: self) + let (_, _, error) = containerA.updateSync(test: self) XCTAssertNil(error) } @@ -468,15 +587,130 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerC.dumpSync(test: self) } + func testJoinWithEnabledUserControllableViews() throws { + let description = tmpStoreDescription(name: "container.db") + let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + + let machineIDs = Set(["aaa", "bbb", "ccc"]) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + + print("preparing A") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = + containerA.prepareSync(test: self, + epoch: 1, + machineID: "aaa", + bottleSalt: "123456789", + bottleID: UUID().uuidString, + modelID: "iPhone1,1", + syncUserControllableViews: .ENABLED) + XCTAssertNotNil(aPolicy, "Should have a syncing policy coming back from a successful prepare") + XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .ENABLED, "Policy coming back from prepare() should already have an opinion of user view syncing") + + XCTAssertNil(error) + XCTAssertNotNil(aPeerID) + XCTAssertNotNil(aPermanentInfo) + XCTAssertNotNil(aPermanentInfoSig) + + print("establishing A") + do { + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + XCTAssertNil(error) + XCTAssertNotNil(peerID) + } + + do { + let (aPolicy, _, aPolicyError) = containerA.fetchCurrentPolicySync(test: self) + XCTAssertNil(aPolicyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(aPolicy, "Should have a syncing policy") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .ENABLED, "Peer should desire to sync user controllable views (as per request)") + } + + print("preparing B") + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, error2) = + containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + let state = containerB.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") + let secret = containerB.loadSecretSync(test: self, label: bPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(error2) + XCTAssertNotNil(bPeerID) + XCTAssertNotNil(bPermanentInfo) + XCTAssertNotNil(bPermanentInfoSig) + + do { + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + print("A vouches for B, but doesn't provide any TLKShares") + let (_, _, errorVouchingWithoutTLKs) = + containerA.vouchSync(test: self, + peerID: bPeerID!, + permanentInfo: bPermanentInfo!, + permanentInfoSig: bPermanentInfoSig!, + stableInfo: bStableInfo!, + stableInfoSig: bStableInfoSig!, + ckksKeys: []) + XCTAssertNil(errorVouchingWithoutTLKs, "Should be no error vouching without uploading TLKShares") + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("A vouches for B, but doesn't only has provisional TLKs at the time") + let provisionalManateeKeySet = try self.makeFakeKeyHierarchy(zoneID: CKRecordZone.ID(zoneName: "Manatee")) + provisionalManateeKeySet.newUpload = true + + let (_, _, errorVouchingWithProvisionalTLKs) = + containerA.vouchSync(test: self, + peerID: bPeerID!, + permanentInfo: bPermanentInfo!, + permanentInfoSig: bPermanentInfoSig!, + stableInfo: bStableInfo!, + stableInfoSig: bStableInfoSig!, + ckksKeys: [provisionalManateeKeySet]) + XCTAssertNil(errorVouchingWithProvisionalTLKs, "Should be no error vouching without uploading TLKShares for a non-existent key") + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("A vouches for B") + let (voucherData, voucherSig, error3) = + containerA.vouchSync(test: self, + peerID: bPeerID!, + permanentInfo: bPermanentInfo!, + permanentInfoSig: bPermanentInfoSig!, + stableInfo: bStableInfo!, + stableInfoSig: bStableInfoSig!, + ckksKeys: [self.manateeKeySet]) + XCTAssertNil(error3) + XCTAssertNotNil(voucherData) + XCTAssertNotNil(voucherSig) + + // As part of the vouch, A should have uploaded a tlkshare for B + assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("B joins") + let (peerID, _, bPolicy, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) + XCTAssertNil(error) + XCTAssertEqual(peerID, bPeerID!) + + XCTAssertNotNil(bPolicy, "Should have a syncing policy") + XCTAssertEqual(bPolicy?.syncUserControllableViews, .ENABLED, "Peer should desire to sync user controllable views (following A's lead)") + } + } + func testJoinWithoutAllowListErrors() throws { let description = tmpStoreDescription(name: "container.db") let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -486,18 +720,18 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNotNil(permanentInfo, "Should have a permanent info after preparing A") XCTAssertNotNil(permanentInfoSig, "Should have a signature after preparing A") - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa"]), "should be able to set allowed machine IDs") + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa"], accountIsDemo: false), "should be able to set allowed machine IDs") - let (peerID2, _, error2) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID2, _, _, error2) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNotNil(peerID2, "Should get a peer when you establish a now allow-listed peer") XCTAssertNil(error2, "Should not get an error when you establish a now allow-listed peer") print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, errorPrepareB) = + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, errorPrepareB) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -507,7 +741,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNotNil(bPermanentInfo, "Should have a permanent info after preparing B") XCTAssertNotNil(bPermanentInfoSig, "Should have a signature after preparing B") - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa"]), "should be able to set allowed machine IDs on container B") + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa"], accountIsDemo: false), "should be able to set allowed machine IDs on container B") do { print("A vouches for B") @@ -524,11 +758,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNotNil(voucherSig, "Should have a signature from A") print("B joins") - let (peerID, _, error) = containerB.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [], - tlkShares: []) + let (peerID, _, _, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) XCTAssertNotNil(error, "Should have an error joining with an unapproved machine ID") XCTAssertNil(peerID, "Should not receive a peer ID joining with an unapproved machine ID") } @@ -539,13 +773,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -558,7 +792,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) @@ -573,7 +807,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { let (dict, error) = containerA.dumpSync(test: self) XCTAssertNil(error) XCTAssertNotNil(dict) - let peers: Array = dict!["peers"] as! Array + let peers: [Any] = dict!["peers"] as! [Any] XCTAssertEqual(0, peers.count) } } @@ -583,12 +817,12 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -613,6 +847,8 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { let error = containerA.localResetSync(test: self) XCTAssertNil(error, "local-reset shouldn't error") + let peers = containerA.containerMO.peers as! Set + XCTAssertEqual(peers.count, 0, "peers should be empty ") } do { let (dict, error) = containerA.dumpSync(test: self) @@ -634,29 +870,29 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let containerC = try Container(name: ContainerName(container: "c", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]))) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]))) - XCTAssertNil(containerC.setAllowedMachineIDsSync(test: self, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]))) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), accountIsDemo: false)) + XCTAssertNil(containerC.setAllowedMachineIDsSync(test: self, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), accountIsDemo: false)) print("preparing") - let (peerID, _, _, _, _, _) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, _, _, _, _, _, _) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") } - let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, _) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") } - let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _) = containerC.prepareSync(test: self, epoch: 1, machineID: "ccc", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _, _) = containerC.prepareSync(test: self, epoch: 1, machineID: "ccc", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerC.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == cPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == cPeerID }, "should have a bottle for peer") let secret = containerC.loadSecretSync(test: self, label: cPeerID!) XCTAssertNotNil(secret, "secret should not be nil") } @@ -739,61 +975,91 @@ class TrustedPeersHelperUnitTests: XCTestCase { } } - // TODO: need a real configurable mock cuttlefish func testFetchPolicyDocuments() throws { - // 1 is known locally via builtin, 3 is not but is known to cuttlefish - let policies = - [ - 1: ("SHA256:TLXrcQmY4ue3oP5pCX1pwsi9BF8cKfohlJBilCroeBs=", - "CAESDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSCwoDTWFjEgRmdWxsEgwKBGlNYWMSBGZ1bGwSDQoHQXBwbGVUVhICdHYS" + - "DgoFV2F0Y2gSBXdhdGNoGhEKCVBDU0VzY3JvdxIEZnVsbBoXCgRXaUZpEgRmdWxsEgJ0dhIFd2F0Y2gaGQoRU2FmYXJpQ3JlZGl0" + - "Q2FyZHMSBGZ1bGwiDAoEZnVsbBIEZnVsbCIUCgV3YXRjaBIEZnVsbBIFd2F0Y2giDgoCdHYSBGZ1bGwSAnR2"), - 3: ("SHA256:JZzazSuHXrUhiOfSgElsg6vYKpnvvEPVpciR8FewRWg=", - "CAMSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSCwoDTWFjEgRmdWxsEgwKBGlNYWMSBGZ1bGwSDQoHQXBwbGVUVhICdHYSDgoFV2F0Y2gSBXdhdGNoEhcKDkF1ZGlvQWNjZXNzb3J5EgVhdWRpbxocCg1EZXZpY2VQYWlyaW5nEgRmdWxsEgV3YXRjaBoXCghBcHBsZVBheRIEZnVsbBIFd2F0Y2gaJAoVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlEgRmdWxsEgV3YXRjaBoXCghCYWNrc3RvcBIEZnVsbBIFd2F0Y2gaGQoKQXV0b1VubG9jaxIEZnVsbBIFd2F0Y2gaHwoQU2VjdXJlT2JqZWN0U3luYxIEZnVsbBIFd2F0Y2gaIAoRU2FmYXJpQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoGhMKBEhvbWUSBGZ1bGwSBXdhdGNoGh4KD1NhZmFyaVBhc3N3b3JkcxIEZnVsbBIFd2F0Y2gaGwoMQXBwbGljYXRpb25zEgRmdWxsEgV3YXRjaBoVCgZFbmdyYW0SBGZ1bGwSBXdhdGNoGi0KE0xpbWl0ZWRQZWVyc0FsbG93ZWQSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aFgoHTWFuYXRlZRIEZnVsbBIFd2F0Y2gaHgoEV2lGaRIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxoVCgZIZWFsdGgSBGZ1bGwSBXdhdGNoIhMKBGZ1bGwSBGZ1bGwSBXdhdGNoIhsKBWF1ZGlvEgRmdWxsEgV3YXRjaBIFYXVkaW8iFAoFd2F0Y2gSBGZ1bGwSBXdhdGNoIhUKAnR2EgRmdWxsEgV3YXRjaBICdHYyIgoWAAQiEgIEdndodAoKXkFwcGxlUGF5JBIIQXBwbGVQYXkyJgoYAAQiFAIEdndodAoMXkF1dG9VbmxvY2skEgpBdXRvVW5sb2NrMh4KFAAEIhACBHZ3aHQKCF5FbmdyYW0kEgZFbmdyYW0yHgoUAAQiEAIEdndodAoIXkhlYWx0aCQSBkhlYWx0aDIaChIABCIOAgR2d2h0CgZeSG9tZSQSBEhvbWUyIAoVAAQiEQIEdndodAoJXk1hbmF0ZWUkEgdNYW5hdGVlMjgKIQAEIh0CBHZ3aHQKFV5MaW1pdGVkUGVlcnNBbGxvd2VkJBITTGltaXRlZFBlZXJzQWxsb3dlZDJdClAAAhIeAAQiGgIEdndodAoSXkNvbnRpbnVpdHlVbmxvY2skEhUABCIRAgR2d2h0CgleSG9tZUtpdCQSFQAEIhECBHZ3aHQKCV5BcHBsZVRWJBIJTm90U3luY2VkMisKGwAEIhcCBGFncnAKD15bMC05QS1aXXsxMH1cLhIMQXBwbGljYXRpb25zMsUBCrABAAISNAABChMABCIPAgVjbGFzcwoGXmdlbnAkChsABCIXAgRhZ3JwCg9eY29tLmFwcGxlLnNiZCQSPQABChMABCIPAgVjbGFzcwoGXmtleXMkCiQABCIgAgRhZ3JwChheY29tLmFwcGxlLnNlY3VyaXR5LnNvcyQSGQAEIhUCBHZ3aHQKDV5CYWNrdXBCYWdWMCQSHAAEIhgCBHZ3aHQKEF5pQ2xvdWRJZGVudGl0eSQSEFNlY3VyZU9iamVjdFN5bmMyYwpbAAISEgAEIg4CBHZ3aHQKBl5XaUZpJBJDAAEKEwAEIg8CBWNsYXNzCgZeZ2VucCQKEwAEIg8CBGFncnAKB15hcHBsZSQKFQAEIhECBHN2Y2UKCV5BaXJQb3J0JBIEV2lGaTLbAgrBAgACEhkABCIVAgR2d2h0Cg1eUENTQ2xvdWRLaXQkEhcABCITAgR2d2h0CgteUENTRXNjcm93JBIUAAQiEAIEdndodAoIXlBDU0ZERSQSGQAEIhUCBHZ3aHQKDV5QQ1NGZWxkc3BhciQSGQAEIhUCBHZ3aHQKDV5QQ1NNYWlsRHJvcCQSGgAEIhYCBHZ3aHQKDl5QQ1NNYXN0ZXJLZXkkEhYABCISAgR2d2h0CgpeUENTTm90ZXMkEhcABCITAgR2d2h0CgteUENTUGhvdG9zJBIYAAQiFAIEdndodAoMXlBDU1NoYXJpbmckEh0ABCIZAgR2d2h0ChFeUENTaUNsb3VkQmFja3VwJBIcAAQiGAIEdndodAoQXlBDU2lDbG91ZERyaXZlJBIZAAQiFQIEdndodAoNXlBDU2lNZXNzYWdlJBIVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlMkAKKwAEIicCBGFncnAKH15jb20uYXBwbGUuc2FmYXJpLmNyZWRpdC1jYXJkcyQSEVNhZmFyaUNyZWRpdENhcmRzMjQKIQAEIh0CBGFncnAKFV5jb20uYXBwbGUuY2ZuZXR3b3JrJBIPU2FmYXJpUGFzc3dvcmRzMm0KXAACEh4ABCIaAgR2d2h0ChJeQWNjZXNzb3J5UGFpcmluZyQSGgAEIhYCBHZ3aHQKDl5OYW5vUmVnaXN0cnkkEhwABCIYAgR2d2h0ChBeV2F0Y2hNaWdyYXRpb24kEg1EZXZpY2VQYWlyaW5nMi0KIQAEIh0CBGFncnAKFV5jb20uYXBwbGUuY2ZuZXR3b3JrJBIIQmFja3N0b3A="), - ] - let (request1, data1) = policies[1]! - let (request3, data3) = policies[3]! + + let missingTuple = TPPolicyVersion(version: 900, hash: "not a hash") + + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } + XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") + let currentPolicy = currentPolicyOptional! + + let newPolicy = currentPolicy.clone(withVersionNumber: currentPolicy.version.versionNumber + 1)! + self.cuttlefish.policyOverlay.append(newPolicy) + + let policy1Tuple = TPPolicyVersion(version: 1, hash: "SHA256:TLXrcQmY4ue3oP5pCX1pwsi9BF8cKfohlJBilCroeBs=") + let policy1Data = Data(base64Encoded: "CAESDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSCwoDTWFjEgRmdWxsEgwKBGlNYWMSBGZ1bGwSDQoHQXBwbGVUVhICdHYS" + + "DgoFV2F0Y2gSBXdhdGNoGhEKCVBDU0VzY3JvdxIEZnVsbBoXCgRXaUZpEgRmdWxsEgJ0dhIFd2F0Y2gaGQoRU2FmYXJpQ3JlZGl0" + + "Q2FyZHMSBGZ1bGwiDAoEZnVsbBIEZnVsbCIUCgV3YXRjaBIEZnVsbBIFd2F0Y2giDgoCdHYSBGZ1bGwSAnR2")! let description = tmpStoreDescription(name: "container.db") let container = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) // nothing - let (response1, error1) = container.fetchPolicyDocumentsSync(test: self, keys: [:]) + let (response1, error1) = container.fetchPolicyDocumentsSync(test: self, versions: []) XCTAssertNil(error1, "No error querying for an empty list") XCTAssertEqual(response1, [:], "Received empty dictionary") // local stuff - let (response2, error2) = container.fetchPolicyDocumentsSync(test: self, keys: [1: request1]) - XCTAssertNil(error2, "No error getting locally known policy document") - XCTAssertEqual(response2?.count, 1, "Got one response for request for one locally known policy") - XCTAssertEqual(response2?[1]?[0], request1, "retrieved hash matches request hash") - XCTAssertEqual(response2?[1]?[1], data1, "retrieved data matches known data") + do { + let (response2, error2) = container.fetchPolicyDocumentsSync(test: self, versions: Set([policy1Tuple])) + XCTAssertNil(error2, "No error getting locally known policy document") + XCTAssertEqual(response2?.count, 1, "Got one response for request for one locally known policy") + XCTAssert(response2?.keys.contains(policy1Tuple) ?? false, "Should have retrieved request for policy1") + XCTAssertEqual(response2?[policy1Tuple], policy1Data, "retrieved data matches known data") + } + + + do { + let knownPolicies = container.model.allRegisteredPolicyVersions() + XCTAssert(knownPolicies.contains(policy1Tuple), "TPModel should know about policy 1") + XCTAssertFalse(knownPolicies.contains(newPolicy.version), "TPModel should not know about newPolicy") + } // fetch remote - let (response3, error3) = container.fetchPolicyDocumentsSync(test: self, keys: [1: request1, 3: request3]) - XCTAssertNil(error3, "No error fetching local + remote policy") - XCTAssertEqual(response3?.count, 2, "Got two responses for local+remote policy request") - XCTAssertEqual(response3?[1]?[0], request1, "retrieved hash matches local request hash") - XCTAssertEqual(response3?[1]?[1], data1, "retrieved data matches local known data") - XCTAssertEqual(response3?[3]?[0], request3, "retrieved hash matches remote request hash") - XCTAssertEqual(response3?[3]?[1], data3, "retrieved data matches remote known data") + do { + let (response3, error3) = container.fetchPolicyDocumentsSync(test: self, versions: [policy1Tuple, newPolicy.version]) + XCTAssertNil(error3, "No error fetching local + remote policy") + XCTAssertEqual(response3?.count, 2, "Got two responses for local+remote policy request") + + XCTAssert(response3?.keys.contains(policy1Tuple) ?? false, "Should have retrieved request for policy1") + XCTAssertEqual(response3?[policy1Tuple], policy1Data, "retrieved data matches known data") + + XCTAssert(response3?.keys.contains(newPolicy.version) ?? false, "Should have retrieved request for newPolicy") + XCTAssertEqual(response3?[newPolicy.version], newPolicy.protobuf, "retrieved data matches known data") + } // invalid version - let (response4, error4) = container.fetchPolicyDocumentsSync(test: self, keys: [9000: "not a hash"]) - XCTAssertNil(response4, "No response for wrong [version: hash] combination") - XCTAssertNotNil(error4, "Expected error fetching invalid policy version") + do { + let (response4, error4) = container.fetchPolicyDocumentsSync(test: self, versions: Set([missingTuple])) + XCTAssertNil(response4, "No response for wrong [version: hash] combination") + XCTAssertNotNil(error4, "Expected error fetching invalid policy version") + } // valid + invalid - let (response5, error5) = container.fetchPolicyDocumentsSync(test: self, keys: [9000: "not a hash", - 1: request1, - 3: request3, ]) - XCTAssertNil(response5, "No response for valid + unknown [version: hash] combination") - XCTAssertNotNil(error5, "Expected error fetching valid + invalid policy version") + do { + let (response5, error5) = container.fetchPolicyDocumentsSync(test: self, versions: Set([missingTuple, + policy1Tuple, + newPolicy.version, ])) + XCTAssertNil(response5, "No response for valid + unknown [version: hash] combination") + XCTAssertNotNil(error5, "Expected error fetching valid + invalid policy version") + } + + do { + let knownPolicies = container.model.allRegisteredPolicyVersions() + XCTAssert(knownPolicies.contains(policy1Tuple), "TPModel should know about policy 1") + XCTAssert(knownPolicies.contains(newPolicy.version), "TPModel should know about newPolicy") + } + + do { + let reloadedContainer = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let reloadedKnownPolicies = reloadedContainer.model.allRegisteredPolicyVersions() + XCTAssert(reloadedKnownPolicies.contains(policy1Tuple), "TPModel should know about policy 1 after restart") + XCTAssert(reloadedKnownPolicies.contains(newPolicy.version), "TPModel should know about newPolicy after a restart") + } } func testEscrowKeys() throws { - XCTAssertThrowsError(try EscrowKeys.retrieveEscrowKeysFromKeychain(label: "hash"), "retrieveEscrowKeysFromKeychain should throw error") XCTAssertThrowsError(try EscrowKeys.findEscrowKeysForLabel(label: "hash"), "findEscrowKeysForLabel should throw error") @@ -828,31 +1094,30 @@ class TrustedPeersHelperUnitTests: XCTestCase { } func testEscrowKeyTestVectors() { - let secretString = "I'm a secretI'm a secretI'm a secretI'm a secretI'm a secretI'm a secret" let secret = secretString.data(using: .utf8) do { - let testv1 = try EscrowKeys.generateEscrowKey(keyType: escrowKeyType.kOTEscrowKeySigning, masterSecret: secret!, bottleSalt: testDSID) + let testv1 = try EscrowKeys.generateEscrowKey(keyType: EscrowKeyType.kOTEscrowKeySigning, masterSecret: secret!, bottleSalt: testDSID) XCTAssertEqual(testv1, signingKey_384, "signing keys should match") - let testv2 = try EscrowKeys.generateEscrowKey(keyType: escrowKeyType.kOTEscrowKeyEncryption, masterSecret: secret!, bottleSalt: testDSID) + let testv2 = try EscrowKeys.generateEscrowKey(keyType: EscrowKeyType.kOTEscrowKeyEncryption, masterSecret: secret!, bottleSalt: testDSID) XCTAssertEqual(testv2, encryptionKey_384, "encryption keys should match") - let testv3 = try EscrowKeys.generateEscrowKey(keyType: escrowKeyType.kOTEscrowKeySymmetric, masterSecret: secret!, bottleSalt: testDSID) + let testv3 = try EscrowKeys.generateEscrowKey(keyType: EscrowKeyType.kOTEscrowKeySymmetric, masterSecret: secret!, bottleSalt: testDSID) XCTAssertEqual(testv3, symmetricKey_384, "symmetric keys should match") let newSecretString = "I'm f secretI'm a secretI'm a secretI'm a secretI'm a secretI'm a secret" let newSecret = newSecretString.data(using: .utf8) - let testv4 = try EscrowKeys.generateEscrowKey(keyType: escrowKeyType.kOTEscrowKeySigning, masterSecret: newSecret!, bottleSalt: testDSID) + let testv4 = try EscrowKeys.generateEscrowKey(keyType: EscrowKeyType.kOTEscrowKeySigning, masterSecret: newSecret!, bottleSalt: testDSID) XCTAssertNotEqual(testv4, signingKey_384, "signing keys should not match") - let testv5 = try EscrowKeys.generateEscrowKey(keyType: escrowKeyType.kOTEscrowKeyEncryption, masterSecret: newSecret!, bottleSalt: testDSID) + let testv5 = try EscrowKeys.generateEscrowKey(keyType: EscrowKeyType.kOTEscrowKeyEncryption, masterSecret: newSecret!, bottleSalt: testDSID) XCTAssertNotEqual(testv5, encryptionKey_384, "encryption keys should not match") - let testv6 = try EscrowKeys.generateEscrowKey(keyType: escrowKeyType.kOTEscrowKeySymmetric, masterSecret: newSecret!, bottleSalt: testDSID) + let testv6 = try EscrowKeys.generateEscrowKey(keyType: EscrowKeyType.kOTEscrowKeySymmetric, masterSecret: newSecret!, bottleSalt: testDSID) XCTAssertNotEqual(testv6, symmetricKey_384, "symmetric keys should not match") } catch { XCTFail("error testing escrow key test vectors \(error)") @@ -865,19 +1130,19 @@ class TrustedPeersHelperUnitTests: XCTestCase { let secret = secretString.data(using: .utf8) do { - let testv1 = try RecoveryKeySet.generateRecoveryKey(keyType: recoveryKeyType.kOTRecoveryKeySigning, masterSecret: secret!, recoverySalt: testDSID) + let testv1 = try RecoveryKeySet.generateRecoveryKey(keyType: RecoveryKeyType.kOTRecoveryKeySigning, masterSecret: secret!, recoverySalt: testDSID) XCTAssertEqual(testv1, recovery_signingKey_384, "signing keys should match") - let testv2 = try RecoveryKeySet.generateRecoveryKey(keyType: recoveryKeyType.kOTRecoveryKeyEncryption, masterSecret: secret!, recoverySalt: testDSID) + let testv2 = try RecoveryKeySet.generateRecoveryKey(keyType: RecoveryKeyType.kOTRecoveryKeyEncryption, masterSecret: secret!, recoverySalt: testDSID) XCTAssertEqual(testv2, recovery_encryptionKey_384, "encryption keys should match") let newSecretString = "I'm f secretI'm a secretI'm a secretI'm a secretI'm a secretI'm a secret" let newSecret = newSecretString.data(using: .utf8) - let testv4 = try RecoveryKeySet.generateRecoveryKey(keyType: recoveryKeyType.kOTRecoveryKeySigning, masterSecret: newSecret!, recoverySalt: testDSID) + let testv4 = try RecoveryKeySet.generateRecoveryKey(keyType: RecoveryKeyType.kOTRecoveryKeySigning, masterSecret: newSecret!, recoverySalt: testDSID) XCTAssertNotEqual(testv4, recovery_signingKey_384, "signing keys should not match") - let testv5 = try RecoveryKeySet.generateRecoveryKey(keyType: recoveryKeyType.kOTRecoveryKeyEncryption, masterSecret: newSecret!, recoverySalt: testDSID) + let testv5 = try RecoveryKeySet.generateRecoveryKey(keyType: RecoveryKeyType.kOTRecoveryKeyEncryption, masterSecret: newSecret!, recoverySalt: testDSID) XCTAssertNotEqual(testv5, recovery_encryptionKey_384, "encryption keys should not match") } catch { XCTFail("error testing RecoveryKey test vectors \(error)") @@ -892,15 +1157,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") bottleA = state.bottles.removeFirst() @@ -915,14 +1180,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -932,11 +1197,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -946,11 +1211,12 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B prepares to join via bottle") - let (bottlePeerID, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") + XCTAssertNotNil(policy, "Should have a policy") - let (voucherData, voucherSig, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) XCTAssertNil(error3) XCTAssertNotNil(voucherData) @@ -960,7 +1226,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) + let (peerID, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) XCTAssertNil(error) XCTAssertEqual(peerID, bPeerID!) @@ -977,15 +1243,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") bottleA = state.bottles.removeFirst() @@ -1000,14 +1266,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1017,11 +1283,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1031,11 +1297,12 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B prepares to join via bottle") - let (bottlePeerID, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") + XCTAssertNotNil(policy, "Should have a policy") - let (voucherData, voucherSig, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) XCTAssertNil(error3) XCTAssertNotNil(voucherData) @@ -1045,7 +1312,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) + let (peerID, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) XCTAssertNil(error) XCTAssertEqual(peerID, bPeerID!) @@ -1061,15 +1328,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1081,13 +1348,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1097,11 +1364,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1111,11 +1378,12 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B joins via bottle") - let (bottlePeerID, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: "wrong escrow record") + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: "wrong escrow record") XCTAssertNotNil(errorPreflight, "Should be an error preflighting bottle that doesn't exist") XCTAssertNil(bottlePeerID, "peerID should be nil for no bottle") + XCTAssertNil(policy, "Should not have a policy") - let (voucherData, voucherSig, error3) = containerB.vouchWithBottleSync(test: self, b: "wrong escrow record", entropy: entropy, bottleSalt: "123456789", tlkShares: []) + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: "wrong escrow record", entropy: entropy, bottleSalt: "123456789", tlkShares: []) XCTAssertNotNil(error3) XCTAssertNil(voucherData) @@ -1131,15 +1399,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1151,13 +1419,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1165,11 +1433,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { } print("preparing B") - let (bPeerID, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") bottleB = state.bottles.removeFirst() let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") @@ -1180,11 +1448,12 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B joins via bottle") - let (bottlePeerID, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleB.bottleID!) - XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") - XCTAssertEqual(bottlePeerID, bPeerID, "Bottle should be for peer B") + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleB.bottleID!) + XCTAssertNotNil(errorPreflight, "Should be an error preflighting bottle that doesn't correspond to a peer") + XCTAssertNil(bottlePeerID, "Should have no peer for invalid bottle") + XCTAssertNil(policy, "Should not have a policy") - let (voucherData, voucherSig, error3) = containerB.vouchWithBottleSync(test: self, b: bottleB.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleB.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) XCTAssertNotNil(error3) XCTAssertNil(voucherData) @@ -1200,15 +1469,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) bottleA = state.bottles.removeFirst() XCTAssertNotNil(secret, "secret should not be nil") @@ -1221,13 +1490,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1237,11 +1506,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1251,11 +1520,12 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B joins via bottle") - let (bottlePeerID, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") + XCTAssertNotNil(policy, "Should have a policy") - let (voucherData, voucherSig, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "987654321", tlkShares: []) + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "987654321", tlkShares: []) XCTAssertNotNil(error3) XCTAssertNil(voucherData) @@ -1270,15 +1540,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) bottleA = state.bottles.removeFirst() XCTAssertNotNil(secret, "secret should not be nil") @@ -1291,13 +1561,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1306,11 +1576,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1320,11 +1590,12 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B joins via bottle") - let (bottlePeerID, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") + XCTAssertNotNil(policy, "Should have a policy") - let (voucherData, voucherSig, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: Data(count: Int(OTMasterSecretLength)), bottleSalt: "123456789", tlkShares: []) + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: Data(count: Int(OTMasterSecretLength)), bottleSalt: "123456789", tlkShares: []) XCTAssertNotNil(error3) XCTAssertNil(voucherData) @@ -1340,15 +1611,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! bottleA = state.bottles.removeFirst() @@ -1362,24 +1633,24 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") } print("preparing B") - let (bPeerID, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1391,13 +1662,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { self.cuttlefish.fetchViableBottlesError.append(FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) - let (bottlePeerID, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNotNil(errorPreflight, "Should be an error preflighting a vouch with bottle with a fetch error") XCTAssertNil(bottlePeerID, "peerID should be nil") + XCTAssertNil(policy, "Should not have a policy") self.cuttlefish.fetchViableBottlesError.append(FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) - let (voucherData, voucherSig, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) XCTAssertNotNil(error3) XCTAssertNil(voucherData) @@ -1409,25 +1681,37 @@ class TrustedPeersHelperUnitTests: XCTestCase { let description = tmpStoreDescription(name: "container.db") let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let containerC = try Container(name: ContainerName(container: "c", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) - let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + let machineIDs = Set(["aaa", "bbb", "ccc"]) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerC.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(aPeerID) XCTAssertNotNil(aPermanentInfo) XCTAssertNotNil(aPermanentInfoSig) + XCTAssertNotNil(aPolicy, "Should have a policy coming back from a successful prepare") + XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .UNKNOWN, "Policy shouldn't yet know whether we want to sync user views") + print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, _, _, error2) = - containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (bPeerID, bPermanentInfo, bPermanentInfoSig, _, _, _, error2) = + containerB.prepareSync(test: self, + epoch: 1, + machineID: "bbb", + bottleSalt: "123456789", + bottleID: UUID().uuidString, + modelID: "iPhone1,1", + syncUserControllableViews: .DISABLED) do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1437,40 +1721,130 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNotNil(bPermanentInfo) XCTAssertNotNil(bPermanentInfoSig) - // Now, A establishes preapproving B + print("preparing C") + let (cPeerID, cPermanentInfo, cPermanentInfoSig, _, _, _, cPrepareError) = + containerC.prepareSync(test: self, + epoch: 1, + machineID: "ccc", + bottleSalt: "123456789", + bottleID: UUID().uuidString, + modelID: "iPhone1,1", + syncUserControllableViews: .ENABLED) + do { + let state = containerC.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == cPeerID }, "should have a bottle for peer") + let secret = containerC.loadSecretSync(test: self, label: cPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(cPrepareError) + XCTAssertNotNil(cPeerID) + XCTAssertNotNil(cPermanentInfo) + XCTAssertNotNil(cPermanentInfoSig) + + // Now, A establishes preapproving B & C // Note: secd is responsible for passing in TLKShares to these preapproved keys in sosTLKShares + let aPermanentInfoParsed = TPPeerPermanentInfo(peerID: aPeerID!, data: aPermanentInfo!, sig: aPermanentInfoSig!, keyFactory: TPECPublicKeyFactory()) + XCTAssertNotNil(aPermanentInfoParsed, "Should have parsed A's permanent info") + let bPermanentInfoParsed = TPPeerPermanentInfo(peerID: bPeerID!, data: bPermanentInfo!, sig: bPermanentInfoSig!, keyFactory: TPECPublicKeyFactory()) XCTAssertNotNil(bPermanentInfoParsed, "Should have parsed B's permanent info") + let cPermanentInfoParsed = TPPeerPermanentInfo(peerID: cPeerID!, data: cPermanentInfo!, sig: cPermanentInfoSig!, keyFactory: TPECPublicKeyFactory()) + XCTAssertNotNil(cPermanentInfoParsed, "Should have parsed C's permanent info") + + print(bPermanentInfoParsed!.signingPubKey.spki().base64EncodedString()) + print(cPermanentInfoParsed!.signingPubKey.spki().base64EncodedString()) + print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: [bPermanentInfoParsed!.signingPubKey.spki()]) + let (peerID, _, _, error) = containerA.establishSync(test: self, + ckksKeys: [self.manateeKeySet], + tlkShares: [], + preapprovedKeys: [bPermanentInfoParsed!.signingPubKey.spki(), + cPermanentInfoParsed!.signingPubKey.spki(), ]) XCTAssertNil(error) XCTAssertNotNil(peerID) + + let (aPolicy, _, aPolicyError) = containerA.fetchCurrentPolicySync(test: self) + XCTAssertNil(aPolicyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(aPolicy, "Should have a syncing policy") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .DISABLED, "A should desire to not ync user controllable views (as the client didn't have any input)") } do { assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins by preapproval, and uploads all TLKShares that it has") - let (bJoinedPeerID, _, bJoinedError) = containerB.preapprovedJoinSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: []) + let (bJoinedPeerID, _, bPolicy, bJoinedError) = containerB.preapprovedJoinSync(test: self, + ckksKeys: [self.manateeKeySet], + tlkShares: [], + preapprovedKeys: [aPermanentInfoParsed!.signingPubKey.spki(), + cPermanentInfoParsed!.signingPubKey.spki(), ]) XCTAssertNil(bJoinedError, "Should be no error joining by preapproval") XCTAssertNotNil(bJoinedPeerID, "Should have a peer ID out of join") + XCTAssertNotNil(bPolicy, "Should have a policy back from preapprovedjoin") + XCTAssertEqual(bPolicy?.syncUserControllableViews, .DISABLED, "Policy should say not to sync user controllable views") assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) } + do { + assertNoTLKShareFor(peerID: cPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("B joins by preapproval, and uploads all TLKShares that it has") + let (cJoinedPeerID, _, cPolicy, cJoinedError) = containerC.preapprovedJoinSync(test: self, + ckksKeys: [self.manateeKeySet], + tlkShares: [], + preapprovedKeys: [aPermanentInfoParsed!.signingPubKey.spki(), + bPermanentInfoParsed!.signingPubKey.spki(), ]) + XCTAssertNil(cJoinedError, "Should be no error joining by preapproval") + XCTAssertNotNil(cJoinedPeerID, "Should have a peer ID out of join") + XCTAssertEqual(cPeerID, cJoinedPeerID, "PeerID after joining should match") + XCTAssertNotNil(cPolicy, "Should have a policy back from preapprovedjoin") + XCTAssertEqual(cPolicy?.syncUserControllableViews, .ENABLED, "Policy should say to sync user controllable views") + + assertTLKShareFor(peerID: cPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + } + _ = containerA.dumpSync(test: self) _ = containerB.dumpSync(test: self) + _ = containerC.dumpSync(test: self) } - func testDepart() throws { + func testDepartLastTrustedPeer() throws { let description = tmpStoreDescription(name: "container.db") let (container, peerID) = try establish(reload: false, store: description) - XCTAssertNil(container.departByDistrustingSelfSync(test: self), "Should be no error distrusting self") - assertDistrusts(context: container, peerIDs: [peerID]) + XCTAssertNotNil(container.departByDistrustingSelfSync(test: self), "Should be an error distrusting self (when it's illegal to do so)") + + // But, having no trusted peers is not a valid state. So, this peer must still trust itself... + assertTrusts(context: container, peerIDs: [peerID]) + } + + func testDepart() throws { + let store = tmpStoreDescription(name: "container.db") + let (c, peerID1) = try establish(reload: false, store: store) + + let (c2, peerID2) = try joinByVoucher(sponsor: c, + containerID: "second", + machineID: "bbb", + machineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, + store: store) + + let (_, _, cUpdateError) = c.updateSync(test: self) + XCTAssertNil(cUpdateError, "Should be able to update first container") + assertTrusts(context: c, peerIDs: [peerID1, peerID2]) + + XCTAssertNil(c.departByDistrustingSelfSync(test: self), "Should be no error distrusting self") + assertDistrusts(context: c, peerIDs: [peerID1]) + assertTrusts(context: c, peerIDs: []) + + let (_, _, c2UpdateError) = c2.updateSync(test: self) + XCTAssertNil(c2UpdateError, "Should be able to update second container") + assertDistrusts(context: c2, peerIDs: [peerID1]) + assertTrusts(context: c2, peerIDs: [peerID2]) } func testDistrustPeers() throws { @@ -1480,16 +1854,16 @@ class TrustedPeersHelperUnitTests: XCTestCase { let (c2, peerID2) = try joinByVoucher(sponsor: c, containerID: "second", machineID: "bbb", - machineIDs: ["aaa", "bbb", "ccc"], + machineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, store: store) let (c3, peerID3) = try joinByVoucher(sponsor: c, containerID: "third", machineID: "ccc", - machineIDs: ["aaa", "bbb", "ccc"], + machineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, store: store) - let (_, cUpdateError) = c.updateSync(test: self) + let (_, _, cUpdateError) = c.updateSync(test: self) XCTAssertNil(cUpdateError, "Should be able to update first container") assertTrusts(context: c, peerIDs: [peerID1, peerID2, peerID3]) @@ -1505,11 +1879,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertDistrusts(context: c, peerIDs: [peerID2, peerID3]) // peers should accept their fates - let (_, c2UpdateError) = c2.updateSync(test: self) + let (_, _, c2UpdateError) = c2.updateSync(test: self) XCTAssertNil(c2UpdateError, "Should be able to update second container") assertDistrusts(context: c2, peerIDs: [peerID2]) - let (_, c3UpdateError) = c3.updateSync(test: self) + let (_, _, c3UpdateError) = c3.updateSync(test: self) XCTAssertNil(c3UpdateError, "Should be able to update third container") assertDistrusts(context: c3, peerIDs: [peerID3]) } @@ -1519,11 +1893,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { // But all that goes away, and a new peer establishes self.cuttlefish.state = FakeCuttlefishServer.State() - let (_, peerID2) = try establish(reload: false, contextID: "second", store: tmpStoreDescription(name: "container-peer2.db")) + let (_, peerID2) = try establish(reload: false, contextID: "second", accountIsDemo: false, store: tmpStoreDescription(name: "container-peer2.db")) // And the first container fetches again, which should succeed self.cuttlefish.nextFetchErrors.append(FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) - let (_, updateError) = c.updateSync(test: self) + let (_, _, updateError) = c.updateSync(test: self) XCTAssertNil(updateError, "Update should have succeeded") // and c's model should only include peerID2 @@ -1583,7 +1957,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNotNil(deserializedBottle, "deserializedBottle should not be nil") XCTAssertEqual(deserializedBottle.contents, bottle.contents, "bottle data should be equal") - } catch { XCTFail("error testing bottles \(error)") } @@ -1601,12 +1974,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { let state = c.getStateSync(test: self) XCTAssertEqual(state.bottles.count, 1, "first container should have a bottle for peer") + XCTAssertEqual(state.escrowRecords.count, 1, "first container should have an escrow record for peer") } let c2 = try Container(name: ContainerName(container: "test", context: "newcomer"), persistentStoreDescription: store, cuttlefish: self.cuttlefish) do { let state = c2.getStateSync(test: self) XCTAssertEqual(state.bottles.count, 0, "before fetch, second container should not have any stored bottles") + XCTAssertEqual(state.escrowRecords.count, 0, "before fetch, second container should not have any escrow records") } let (c2bottles, _, c2FetchError) = c2.fetchViableBottlesSync(test: self) @@ -1617,6 +1992,128 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { let state = c2.getStateSync(test: self) XCTAssertEqual(state.bottles.count, 1, "after fetch, second container should have one stored bottles") + XCTAssertEqual(state.escrowRecords.count, 1, "after fetch, second container should have one escrow record") + } + } + + func testFetchBottlesAfterCacheExpires() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + var bottleA: BottleMO + var entropy: Data + let description = tmpStoreDescription(name: "container.db") + let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + + let machineIDs = Set(["aaa", "bbb"]) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + + print("preparing A") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = + containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + var state = containerA.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") + + bottleA = state.bottles.removeFirst() + + let secret = containerA.loadSecretSync(test: self, label: aPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNotNil(aPeerID) + XCTAssertNotNil(aPermanentInfo) + XCTAssertNotNil(aPermanentInfoSig) + + print("establishing A") + do { + assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + XCTAssertNil(error) + XCTAssertNotNil(peerID) + assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + } + do { + let state = containerA.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") + let secret = containerA.loadSecretSync(test: self, label: aPeerID!) + entropy = secret! + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + + let (bottles, _, fetchError) = containerA.fetchViableBottlesSync(test: self) + XCTAssertNil(fetchError, "should be no error fetching viable bottles") + XCTAssertNotNil(bottles, "should have fetched some bottles") + XCTAssertEqual(bottles!.count, 1, "should have fetched one bottle") + + do { + let state = containerA.getStateSync(test: self) + XCTAssertEqual(state.bottles.count, 1, "first container should have a bottle for peer") + XCTAssertEqual(state.escrowRecords.count, 1, "first container should have an escrow record for peer") + } + + //have another peer join + _ = containerB.updateSync(test: self) + + print("preparing B") + let (bPeerID, _, _, _, _, _, error2) = + containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + let state = containerB.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") + let secret = containerB.loadSecretSync(test: self, label: bPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(error2) + + do { + print("B prepares to join via bottle") + + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") + XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") + XCTAssertNotNil(policy, "Should have a policy") + + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) + + XCTAssertNil(error3) + XCTAssertNotNil(voucherData) + XCTAssertNotNil(voucherSig) + + // Before B joins, there should be no TLKShares for B + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("B joins") + let (peerID, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) + XCTAssertNil(error) + XCTAssertEqual(peerID, bPeerID!) + + // But afterward, it has one! + assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + } + + //now fetch bottles and we should get the cached version + let (_, _, _) = containerA.fetchViableBottlesSync(test: self) + do { + let state = containerA.getStateSync(test: self) + XCTAssertEqual(state.bottles.count, 1, "first container should have a bottle for peer") + XCTAssertEqual(state.escrowRecords.count, 1, "first container should have an escrow record for peer") + } + + sleep(2) + + //now fetch bottles again after the cache expired + containerA.escrowCacheTimeout = 2.0 + + let (_, _, _) = containerA.fetchViableBottlesSync(test: self) + do { + let state = containerA.getStateSync(test: self) + XCTAssertEqual(state.bottles.count, 2, "container A should have 2 bottles") + XCTAssertEqual(state.escrowRecords.count, 2, "container A should have 2 escrow records") } } @@ -1676,18 +2173,18 @@ class TrustedPeersHelperUnitTests: XCTestCase { let store = tmpStoreDescription(name: "container.db") let c = try Container(name: ContainerName(container: "c", context: "context"), - persistentStoreDescription: store, - cuttlefish: self.cuttlefish) + persistentStoreDescription: store, + cuttlefish: self.cuttlefish) let machineIDs = Set(["aaa", "bbb", "ccc"]) - XCTAssertNil(c.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(c.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing peer A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = c.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = c.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = c.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1699,14 +2196,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = c.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) + let (peerID, _, _, error) = c.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) XCTAssertNil(error) XCTAssertNotNil(peerID) } let recoveryKey = SecRKCreateRecoveryKeyString(nil) XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") - let (setRecoveryError) = c.setRecoveryKeySync(test: self, recoveryKey: recoveryKey!, recoverySalt: "altDSID", ckksKeys: []) + let (_, setRecoveryError) = c.setRecoveryKeySync(test: self, recoveryKey: recoveryKey!, recoverySalt: "altDSID", ckksKeys: []) XCTAssertNil(setRecoveryError, "error should be nil") } @@ -1736,14 +2233,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { cuttlefish: self.cuttlefish) let machineIDs = Set(["aaa", "bbb", "ccc"]) - XCTAssertNil(c.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(c.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing peer A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = c.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = c.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = c.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1755,14 +2252,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = c.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) + let (peerID, _, _, error) = c.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) XCTAssertNil(error) XCTAssertNotNil(peerID) } - let (repairAccount, repairEscrow, resetOctagon, healthError) = c.requestHealthCheckSync(requiresEscrowCheck: true, test: self) - XCTAssertEqual(repairAccount, false, "") - XCTAssertEqual(repairEscrow, false, "") - XCTAssertEqual(resetOctagon, false, "") + let (repairAccount, repairEscrow, resetOctagon, leaveTrust, healthError) = c.requestHealthCheckSync(requiresEscrowCheck: true, test: self) + XCTAssertFalse(repairAccount, "") + XCTAssertFalse(repairEscrow, "") + XCTAssertFalse(resetOctagon, "") + XCTAssertFalse(leaveTrust, "") XCTAssertNil(healthError) } @@ -1774,15 +2272,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") bottleA = state.bottles.removeFirst() @@ -1797,14 +2295,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1814,11 +2312,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1828,11 +2326,12 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B prepares to join via bottle") - let (bottlePeerID, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") + XCTAssertNotNil(policy, "Should have a policy") - let (voucherData, voucherSig, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) XCTAssertNil(error3) XCTAssertNotNil(voucherData) @@ -1844,9 +2343,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) - XCTAssertNotNil(error) - XCTAssertNil(peerID) + let (peerID, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) + XCTAssertNil(error, "Should be no error joining with a fetch error") + XCTAssertNotNil(peerID, "Should have a peer ID") } } @@ -1856,15 +2355,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let machineIDs = Set(["aaa", "bbb"]) - XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) - XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs)) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing peer A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, aStableInfo, aStableInfoSig, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, aStableInfo, aStableInfoSig, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1878,17 +2377,17 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) XCTAssertNil(error) XCTAssertNotNil(peerID) } print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, error2) = + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1944,23 +2443,23 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, error) = containerB.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [], - tlkShares: []) + let (peerID, _, _, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) XCTAssertNil(error) XCTAssertEqual(peerID, bPeerID!) } print("A updates") do { - let (_, error) = containerA.updateSync(test: self) + let (_, _, error) = containerA.updateSync(test: self) XCTAssertNil(error) } print("B updates") do { - let (_, error) = containerB.updateSync(test: self) + let (_, _, error) = containerB.updateSync(test: self) XCTAssertNil(error) } @@ -1971,17 +2470,17 @@ class TrustedPeersHelperUnitTests: XCTestCase { let recoveryKey = SecRKCreateRecoveryKeyString(nil) XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") - let (setRecoveryError) = containerB.setRecoveryKeySync(test: self, recoveryKey: recoveryKey!, recoverySalt: "altDSID", ckksKeys: []) + let (_, setRecoveryError) = containerB.setRecoveryKeySync(test: self, recoveryKey: recoveryKey!, recoverySalt: "altDSID", ckksKeys: []) XCTAssertNil(setRecoveryError, "error should be nil") print("A updates") do { - let (_, error) = containerA.updateSync(test: self) + let (_, _, error) = containerA.updateSync(test: self) XCTAssertNil(error) } print("B updates") do { - let (_, error) = containerB.updateSync(test: self) + let (_, _, error) = containerB.updateSync(test: self) XCTAssertNil(error) } @@ -2002,7 +2501,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { let recoveryEncryptionPublicKey: Data? = stableInfo!["recovery_encryption_public_key"] as! Data? XCTAssertNil(recoveryEncryptionPublicKey, "recoveryEncryptionPublicKey should be nil") - } } @@ -2012,13 +2510,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { unknownMachineIDs: Set = Set(), persistentStore: NSPersistentStoreDescription, cuttlefish: FakeCuttlefishServer) throws { - let midList = container.onqueueCurrentMIDList() XCTAssertEqual(midList.machineIDs(in: .allowed), allowedMachineIDs, "List of allowed machine IDs should match") XCTAssertEqual(midList.machineIDs(in: .disallowed), disallowedMachineIDs, "List of disallowed machine IDs should match") XCTAssertEqual(midList.machineIDs(in: .unknown), unknownMachineIDs, "List of unknown machine IDs should match") - let (fetchedAllowList, fetchErr) = container.fetchAllowedMachineIDsSync(test: self) XCTAssertNil(fetchErr, "Should be no error fetching the allowed list") XCTAssertEqual(fetchedAllowList, allowedMachineIDs, "A fetched list of allowed machine IDs should match the loaded list") @@ -2036,7 +2532,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { let description = tmpStoreDescription(name: "container.db") let container = try Container(name: ContainerName(container: "test", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(peerID) @@ -2045,11 +2541,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { try self.assert(container: container, allowedMachineIDs: [], disallowedMachineIDs: [], persistentStore: description, cuttlefish: self.cuttlefish) - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc"]), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), disallowedMachineIDs: [], persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"]), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], accountIsDemo: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb"]), disallowedMachineIDs: Set(["ccc"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") @@ -2063,37 +2559,37 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertTrue(container.onqueueFullIDMSListWouldBeHelpful(), "Container should think it could use an IDMS list set: there's machine IDs pending removal") // once they're unknown, a full list set will make them disallowed - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "zzz", "kkk"]), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "zzz", "kkk"], accountIsDemo: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "zzz", "kkk"]), disallowedMachineIDs: Set(["bbb", "ccc", "fff"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // Resetting the list to what it is doesn't change the list - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "zzz", "kkk"], listDifference: false), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "zzz", "kkk"], accountIsDemo: false, listDifference: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "zzz", "kkk"]), disallowedMachineIDs: Set(["bbb", "ccc", "fff"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // But changing it to something completely new does - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["xxx", "mmm"]), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["xxx", "mmm"], accountIsDemo: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["xxx", "mmm"]), disallowedMachineIDs: Set(["aaa", "zzz", "kkk", "bbb", "ccc", "fff"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // And, readding a previously disallowed machine ID works too - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["xxx", "mmm", "aaa"]), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["xxx", "mmm", "aaa"], accountIsDemo: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["xxx", "mmm", "aaa"]), disallowedMachineIDs: Set(["zzz", "kkk", "bbb", "ccc", "fff"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // A update() before establish() doesn't change the list, since it isn't actually changing anything - let (_, updateError) = container.updateSync(test: self) + let (_, _, updateError) = container.updateSync(test: self) XCTAssertNil(updateError, "Should not be an error updating the container without first establishing") try self.assert(container: container, allowedMachineIDs: Set(["xxx", "mmm", "aaa"]), disallowedMachineIDs: Set(["zzz", "kkk", "bbb", "ccc", "fff"]), persistentStore: description, cuttlefish: self.cuttlefish) - let (_, _, establishError) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (_, _, _, establishError) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(establishError, "Should be able to establish() with no error") try self.assert(container: container, allowedMachineIDs: Set(["xxx", "mmm", "aaa"]), disallowedMachineIDs: Set(["zzz", "kkk", "bbb", "ccc", "fff"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // But a successful update() does remove all disallowed machine IDs, as they're no longer relevant - let (_, updateError2) = container.updateSync(test: self) + let (_, _, updateError2) = container.updateSync(test: self) XCTAssertNil(updateError2, "Should not be an error updating the container after establishing") try self.assert(container: container, allowedMachineIDs: Set(["xxx", "mmm", "aaa"]), disallowedMachineIDs: Set([]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") @@ -2105,7 +2601,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { try self.assert(container: container, allowedMachineIDs: [], disallowedMachineIDs: [], persistentStore: description, cuttlefish: self.cuttlefish) - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc"], listDifference: true), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), disallowedMachineIDs: [], persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") @@ -2115,7 +2611,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // But, the next time we ask IDMS, they still haven't made it to the full list, and in fact, C has disappeared. - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], listDifference: true), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ddd", "eee"]), disallowedMachineIDs: Set(["ccc"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") @@ -2125,23 +2621,23 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertTrue(container.onqueueFullIDMSListWouldBeHelpful(), "Container should think it could use an IDMS list set: there's machine IDs pending removal") // and a list set after the remove confirms the removal - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], listDifference: true), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ddd"]), disallowedMachineIDs: Set(["ccc", "eee"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // Then a new list set includes D! Hurray IDMS. Note that this is not a "list change", because the list doesn't actually change - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ddd"], listDifference: false), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ddd"], accountIsDemo: false, listDifference: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ddd"]), disallowedMachineIDs: Set(["ccc", "eee"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // And another list set no longer includes D, so it should now be disallowed - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], listDifference: true), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb"]), disallowedMachineIDs: Set(["ccc", "ddd", "eee"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // And just to check the 48 hour boundary... XCTAssertNil(container.addAllowedMachineIDsSync(test: self, machineIDs: ["xxx"]), "should be able to receive an add push") - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], listDifference: false), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], accountIsDemo: false, listDifference: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "xxx"]), disallowedMachineIDs: Set(["ccc", "ddd", "eee"]), persistentStore: description, cuttlefish: self.cuttlefish) container.moc.performAndWait { @@ -2159,10 +2655,45 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // Setting the list again should kick out X, since it was 'added' too long ago - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], listDifference: true), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb"]), disallowedMachineIDs: Set(["ccc", "ddd", "eee", "xxx"]), persistentStore: description, cuttlefish: self.cuttlefish) } + func testSingleDeviceWillNotDepartWhenTakenOffMIDList() throws { + let description = tmpStoreDescription(name: "container.db") + let container = try Container(name: ContainerName(container: "test", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + + XCTAssertNil(error) + XCTAssertNotNil(peerID) + XCTAssertNotNil(permanentInfo) + XCTAssertNotNil(permanentInfoSig) + + try self.assert(container: container, allowedMachineIDs: [], disallowedMachineIDs: [], persistentStore: description, cuttlefish: self.cuttlefish) + + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false), "should be able to set allowed machine IDs") + let (_, _, _, establishError) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + XCTAssertNil(establishError, "Should be able to establish() with no error") + try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), disallowedMachineIDs: Set([]), persistentStore: description, cuttlefish: self.cuttlefish) + XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") + + // Removing the peer from the MID list doesn't cause the sole peer to distrust itself + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: [], accountIsDemo: false), "should be able to set allowed machine IDs") + try self.assert(container: container, allowedMachineIDs: Set([]), disallowedMachineIDs: Set(["aaa", "bbb", "ccc"]), persistentStore: description, cuttlefish: self.cuttlefish) + + do { + let (_, _, updateError) = container.updateSync(test: self) + XCTAssertNil(updateError, "Should not be an error updating the container after establishing") + } + + assertTrusts(context: container, peerIDs: [peerID!]) + + // THe update() will wipe out the deny-listing of bbb and ccc, but we should keep aaa. around. + try self.assert(container: container, allowedMachineIDs: Set([]), disallowedMachineIDs: Set(["aaa"]), persistentStore: description, cuttlefish: self.cuttlefish) + XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") + } + func testAllowSetUpgrade() throws { let containerName = ContainerName(container: "test", context: OTDefaultContext) @@ -2188,7 +2719,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { // Now TPH boots up with a preexisting model let container = try Container(name: containerName, persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(peerID) @@ -2198,7 +2729,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), disallowedMachineIDs: [], persistentStore: description, cuttlefish: self.cuttlefish) // Setting a new list should work fine - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ddd"]), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ddd"], accountIsDemo: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ddd"]), disallowedMachineIDs: ["ccc"], persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertEqual(container.containerMO.allowedMachineIDs, Set() as NSSet, "Set of allowed machine IDs should now be empty") @@ -2242,7 +2773,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { try self.assert(container: container, allowedMachineIDs: Set(["aaa"]), disallowedMachineIDs: ["bbb"], persistentStore: description, cuttlefish: self.cuttlefish) // Setting a new list should work fine - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "ddd"]), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "ddd"], accountIsDemo: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "ddd"]), disallowedMachineIDs: ["bbb"], persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertEqual(container.containerMO.allowedMachineIDs, Set() as NSSet, "Set of allowed machine IDs should now be empty") @@ -2263,7 +2794,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { } // and set the machine ID list to something that doesn't include 'aaa' - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["bbb", "ccc"], listDifference: true), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["bbb", "ccc"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["bbb", "ccc"]), disallowedMachineIDs: [], unknownMachineIDs: Set(["aaa"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") @@ -2286,7 +2817,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // Setting it again is fine... - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["bbb", "ccc"], listDifference: false), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["bbb", "ccc"], accountIsDemo: false, listDifference: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["bbb", "ccc"]), disallowedMachineIDs: [], unknownMachineIDs: Set(["aaa"]), persistentStore: description, cuttlefish: self.cuttlefish) // And doesn't reset the modified date on the record @@ -2304,53 +2835,182 @@ class TrustedPeersHelperUnitTests: XCTestCase { } // And can be promoted to 'allowed' - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], listDifference: true), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb"]), disallowedMachineIDs: ["ccc"], persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") } + func testDuplicateVouchersWhenRegisteringOnModel() throws { + let store = tmpStoreDescription(name: "container.db") + let (c, peerID1) = try establish(reload: false, store: store) + + let (c2, peerID2) = try joinByVoucher(sponsor: c, + containerID: "second", + machineID: "bbb", + machineIDs: ["aaa", "bbb"], accountIsDemo: false, + store: store) + + let (_, _, cUpdateError) = c.updateSync(test: self) + XCTAssertNil(cUpdateError, "Should be able to update first container") + assertTrusts(context: c, peerIDs: [peerID1, peerID2]) + + let (_, _, c2UpdateError) = c2.updateSync(test: self) + XCTAssertNil(c2UpdateError, "Should be able to update second container") + assertTrusts(context: c2, peerIDs: [peerID1, peerID2]) + + //attempt to register a bunch of vouchers it likely already has + for voucher in c2.model.allVouchers() { + c.model.register(voucher) + } + XCTAssertEqual(c.model.allVouchers().count, 1, "voucher count should be 1") + XCTAssertEqual(c2.model.allVouchers().count, 1, "voucher count should be 1") + } + + func testDuplicateVouchersOnload() throws { + let description = tmpStoreDescription(name: "container.db") + + let store = tmpStoreDescription(name: "container.db") + let (c, peerID1) = try establish(reload: false, store: store) + + let (c2, peerID2) = try joinByVoucher(sponsor: c, + containerID: "second", + machineID: "bbb", + machineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, + store: store) + + let (c3, peerID3) = try joinByVoucher(sponsor: c, + containerID: "third", + machineID: "ccc", + machineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, + store: store) + + let (_, _, cUpdateError) = c.updateSync(test: self) + XCTAssertNil(cUpdateError, "Should be able to update first container") + + let (_, _, cUpdateError2) = c2.updateSync(test: self) + XCTAssertNil(cUpdateError2, "Should be able to update first container") + let (_, _, cUpdateError3) = c3.updateSync(test: self) + XCTAssertNil(cUpdateError3, "Should be able to update first container") + let (_, _, _) = c.updateSync(test: self) + + assertTrusts(context: c, peerIDs: [peerID1, peerID2, peerID3]) + + var vouchers: [VoucherMO] = Array() + + let c1Peers = c.containerMO.peers as! Set + for peer in c1Peers { + for voucher in peer.vouchers! { + let vouch = voucher as! VoucherMO + vouchers.append(vouch) + } + } + for peer in c1Peers { + for voucher in peer.vouchers! { + let vouch = voucher as! VoucherMO + vouchers.append(vouch) + } + } + + for peer in c1Peers { + for voucher in peer.vouchers! { + let vouch = voucher as! VoucherMO + vouchers.append(vouch) + } + } + + //reload container + XCTAssertEqual(vouchers.count, 6, "should have 6 vouchers") + + c.moc.performAndWait { + let containerMO = ContainerMO(context: c.moc) + do { + + for peer in containerMO.peers as! Set { + for vouch in vouchers { + peer.addToVouchers(vouch) + } + } + } + XCTAssertNoThrow(try! c.moc.save()) + } + + //reload container + do { + let container = try Container(name: c.name, persistentStoreDescription: description, cuttlefish: cuttlefish) + XCTAssertEqual(container.model.allVouchers().count, 2, "voucher count should be 2") + } catch { + XCTFail("Creating container errored: \(error)") + } + } + func testMachineIDListSetDisallowedOldUnknownMachineIDs() throws { let description = tmpStoreDescription(name: "container.db") - let (container, _) = try establish(reload: false, contextID: OTDefaultContext, allowedMachineIDs: Set(), store: description) + var (container, peerID1) = try establish(reload: false, contextID: OTDefaultContext, allowedMachineIDs: Set(["aaa"]), accountIsDemo: false, store: description) - // and set the machine ID list to something that doesn't include 'aaa' - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["bbb", "ccc"], listDifference: true), "should be able to set allowed machine IDs") - try self.assert(container: container, allowedMachineIDs: Set(["bbb", "ccc"]), disallowedMachineIDs: [], unknownMachineIDs: Set(["aaa"]), persistentStore: description, cuttlefish: self.cuttlefish) + // and set the machine ID list to something that doesn't include 'ddd' + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") + try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), disallowedMachineIDs: [], unknownMachineIDs: Set(), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "YES", "honorIDMSListChanges should be YES") - // But an entry for "aaa" should exist, as a peer in the model claims it as their MID + let unknownMachineID = "ddd" + let (_, peerID3) = try self.joinByVoucher(sponsor: container, + containerID: "second", + machineID: unknownMachineID, + machineIDs: Set([unknownMachineID, "aaa", "bbb", "ccc"]), accountIsDemo: false, + store: description) + + // And the first container accepts the join... + let (_, _, cUpdateError) = container.updateSync(test: self) + XCTAssertNil(cUpdateError, "Should be able to update first container") + assertTrusts(context: container, peerIDs: [peerID1, peerID3]) + + try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), disallowedMachineIDs: [], unknownMachineIDs: Set([unknownMachineID]), persistentStore: description, cuttlefish: self.cuttlefish) + + XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "YES", "honorIDMSListChanges should be YES") + + // But an entry for "ddd" should exist, as a peer in the model claims it as their MID container.moc.performAndWait { let knownMachineMOs = container.containerMO.machines as? Set ?? Set() - let aaaMOs = knownMachineMOs.filter { $0.machineID == "aaa" } - XCTAssertEqual(aaaMOs.count, 1, "Should have one machine MO for aaa") + let unknownMOs = knownMachineMOs.filter { $0.machineID == unknownMachineID } + XCTAssertEqual(unknownMOs.count, 1, "Should have one machine MO for ddd") - let aaaMO = aaaMOs.first! - XCTAssertEqual(aaaMO.status, Int64(TPMachineIDStatus.unknown.rawValue), "Status of aaa MO should be 'unknown'") - XCTAssertFalse(aaaMO.allowed, "allowed should no longer be a used field") + let dddMO = unknownMOs.first! + XCTAssertEqual(dddMO.status, Int64(TPMachineIDStatus.unknown.rawValue), "Status of ddd MO should be 'unknown'") + XCTAssertFalse(dddMO.allowed, "allowed should no longer be a used field") - // Pretend that aaa was added 49 hours ago - aaaMO.modified = Date(timeIntervalSinceNow: -60 * 60 * 49) + // Pretend that ddd was added 49 hours ago + dddMO.modified = Date(timeIntervalSinceNow: -60 * 60 * 49) try! container.moc.save() } + //reload container + do { + container = try Container(name: ContainerName(container: "test", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "YES", "honorIDMSListChanges should be YES") + } catch { + XCTFail("Creating container errored: \(error)") + } XCTAssertTrue(container.onqueueFullIDMSListWouldBeHelpful(), "Container should think it could use an IDMS list set: there's machine IDs pending removal") - // And, setting the list again should disallow aaa, since it is so old - // Note that this _should_ return a list difference, since A is promoted to disallowed - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["bbb", "ccc"], listDifference: true), "should be able to set allowed machine IDs") - try self.assert(container: container, allowedMachineIDs: Set(["bbb", "ccc"]), disallowedMachineIDs: ["aaa"], persistentStore: description, cuttlefish: self.cuttlefish) + // And, setting the list again should disallow ddd, since it is so old + // Note that this _should_ return a list difference, since D is promoted to disallowed + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") + try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), disallowedMachineIDs: [unknownMachineID], persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // Setting ths list again has no change - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["bbb", "ccc"], listDifference: false), "should be able to set allowed machine IDs") - try self.assert(container: container, allowedMachineIDs: Set(["bbb", "ccc"]), disallowedMachineIDs: ["aaa"], persistentStore: description, cuttlefish: self.cuttlefish) + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, listDifference: false), "should be able to set allowed machine IDs") + try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), disallowedMachineIDs: [unknownMachineID], persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") - // But A can appear again, no problem. - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc"], listDifference: true), "should be able to set allowed machine IDs") - try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), disallowedMachineIDs: [], persistentStore: description, cuttlefish: self.cuttlefish) + // But D can appear again, no problem. + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa", "bbb", "ccc", "ddd"], accountIsDemo: false, listDifference: true), "should be able to set allowed machine IDs") + try self.assert(container: container, allowedMachineIDs: Set(["aaa", "bbb", "ccc", "ddd"]), disallowedMachineIDs: [], persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "YES", "honorIDMSListChanges should be YES") } func testMachineIDListHandlingWithPeers() throws { @@ -2363,11 +3023,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { let (_, peerID2) = try self.joinByVoucher(sponsor: container, containerID: "second", machineID: unknownMachineID, - machineIDs: Set([unknownMachineID, "aaa", "bbb", "ccc"]), + machineIDs: Set([unknownMachineID, "aaa", "bbb", "ccc"]), accountIsDemo: false, store: description) // And the first container accepts the join... - let (_, cUpdateError) = container.updateSync(test: self) + let (_, _, cUpdateError) = container.updateSync(test: self) XCTAssertNil(cUpdateError, "Should be able to update first container") assertTrusts(context: container, peerIDs: [peerID1, peerID2]) @@ -2377,7 +3037,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { func testMachineIDListHandlingInDemoAccounts() throws { // Demo accounts have no machine IDs in their lists let description = tmpStoreDescription(name: "container.db") - let (container, peerID1) = try establish(reload: false, contextID: OTDefaultContext, allowedMachineIDs: Set(), store: description) + var (container, peerID1) = try establish(reload: false, contextID: OTDefaultContext, allowedMachineIDs: Set(), accountIsDemo: true, store: description) // And so we just don't write down any MIDs try self.assert(container: container, allowedMachineIDs: Set([]), disallowedMachineIDs: [], unknownMachineIDs: Set([]), persistentStore: description, cuttlefish: self.cuttlefish) @@ -2388,30 +3048,41 @@ class TrustedPeersHelperUnitTests: XCTestCase { containerID: "second", machineID: unknownMachineID, machineIDs: Set(), + accountIsDemo: true, store: description) try self.assert(container: c2, allowedMachineIDs: Set([]), disallowedMachineIDs: [], unknownMachineIDs: Set([]), persistentStore: description, cuttlefish: self.cuttlefish) + c2.containerMO.honorIDMSListChanges = "NO" + // And the first container accepts the join... - let (_, cUpdateError) = container.updateSync(test: self) + let (_, _, cUpdateError) = container.updateSync(test: self) XCTAssertNil(cUpdateError, "Should be able to update first container") assertTrusts(context: container, peerIDs: [peerID1, peerID2]) // And still has nothing in its list... try self.assert(container: container, allowedMachineIDs: Set([]), disallowedMachineIDs: [], unknownMachineIDs: Set([]), persistentStore: description, cuttlefish: self.cuttlefish) + //reload container + do { + container = try Container(name: ContainerName(container: "test", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "NO", "honorIDMSListChanges should be NO") + } catch { + XCTFail("Creating container errored: \(error)") + } + // Even after a full list set - XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: [], listDifference: false), "should be able to set allowed machine IDs") + XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: [], accountIsDemo: true, listDifference: false), "should be able to set allowed machine IDs") try self.assert(container: container, allowedMachineIDs: Set([]), disallowedMachineIDs: [], unknownMachineIDs: Set([]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "NO", "honorIDMSListChanges should be NO") } func testContainerAndModelConsistency() throws { - let preTestContainerName = ContainerName(container: "testToCreatePrepareData", context: "context") let description = tmpStoreDescription(name: "container.db") let containerTest = try Container(name: preTestContainerName, persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error) = containerTest.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error) = containerTest.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(peerID) XCTAssertNotNil(permanentInfo) @@ -2442,17 +3113,18 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerEgoStableInfo = TPPeerStableInfo(data: stableInfo!, sig: stableInfoSig!) do { let peerKeys: OctagonSelfPeerKeys = try loadEgoKeysSync(peerID: containerMO.egoPeerID!) - let info3 = TPPeerStableInfo(clock: containerEgoStableInfo!.clock + 2, - policyVersion: containerEgoStableInfo!.policyVersion, - policyHash: containerEgoStableInfo!.policyHash, - policySecrets: containerEgoStableInfo!.policySecrets, - deviceName: containerEgoStableInfo!.deviceName, - serialNumber: containerEgoStableInfo!.serialNumber, - osVersion: containerEgoStableInfo!.osVersion, - signing: peerKeys.signingKey, - recoverySigningPubKey: containerEgoStableInfo!.recoverySigningPublicKey, - recoveryEncryptionPubKey: containerEgoStableInfo!.recoveryEncryptionPublicKey, - error: nil) + let newClock = containerEgoStableInfo!.clock + 2 + let info3 = try TPPeerStableInfo(clock: newClock, + frozenPolicyVersion: containerEgoStableInfo!.frozenPolicyVersion, + flexiblePolicyVersion: containerEgoStableInfo!.flexiblePolicyVersion!, + policySecrets: containerEgoStableInfo!.policySecrets, + syncUserControllableViews: containerEgoStableInfo!.syncUserControllableViews, + deviceName: containerEgoStableInfo!.deviceName, + serialNumber: containerEgoStableInfo!.serialNumber, + osVersion: containerEgoStableInfo!.osVersion, + signing: peerKeys.signingKey, + recoverySigningPubKey: containerEgoStableInfo!.recoverySigningPublicKey, + recoveryEncryptionPubKey: containerEgoStableInfo!.recoveryEncryptionPublicKey) //setting the containerMO's ego stable info to an old clock containerMO.egoPeerStableInfo = containerEgoStableInfo!.data @@ -2518,4 +3190,324 @@ class TrustedPeersHelperUnitTests: XCTestCase { let e4 = NSError(domain: CKErrorDomain, code: CKError.serverRejectedRequest.rawValue, userInfo: [NSUnderlyingErrorKey: int4]) XCTAssertTrue(RetryingInvocable.retryableError(error: e4)) } + + func testEstablishWithEnforceIDMSListNotSetBehavior() throws { + let contextID = "OTDefaultContext" + let description = tmpStoreDescription(name: "container.db") + + var container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: description, cuttlefish: cuttlefish) + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + let state = container.getStateSync(test: self) + XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + let secret = container.loadSecretSync(test: self, label: peerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNotNil(peerID) + XCTAssertNotNil(permanentInfo) + XCTAssertNotNil(permanentInfoSig) + XCTAssertNil(error) + + _ = container.dumpSync(test: self) + + do { + container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: description, cuttlefish: cuttlefish) + } catch { + XCTFail("Creating container errored: \(error)") + } + + let (peerID2, _, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + XCTAssertNil(error2) + XCTAssertNotNil(peerID2) + + _ = container.dumpSync(test: self) + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + } + + func testJoinWithEnforceIDMSListNotSetBehavior() throws { + let description = tmpStoreDescription(name: "container.db") + let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let containerC = try Container(name: ContainerName(container: "c", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + + XCTAssertEqual(containerA.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + XCTAssertEqual(containerB.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + XCTAssertEqual(containerC.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + + print("preparing A") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = + containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + XCTAssertNotNil(aPolicy, "Should have a policy coming back from a successful prepare") + XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") + + do { + let state = containerA.getStateSync(test: self) + XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + let secret = containerA.loadSecretSync(test: self, label: aPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(error) + XCTAssertNotNil(aPeerID) + XCTAssertNotNil(aPermanentInfo) + XCTAssertNotNil(aPermanentInfoSig) + + print("establishing A") + do { + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + XCTAssertNil(error) + XCTAssertNotNil(peerID) + } + + print("preparing B") + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, error2) = + containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + let state = containerB.getStateSync(test: self) + XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + let secret = containerB.loadSecretSync(test: self, label: bPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(error2) + XCTAssertNotNil(bPeerID) + XCTAssertNotNil(bPermanentInfo) + XCTAssertNotNil(bPermanentInfoSig) + + do { + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + print("A vouches for B, but doesn't provide any TLKShares") + let (_, _, errorVouchingWithoutTLKs) = + containerA.vouchSync(test: self, + peerID: bPeerID!, + permanentInfo: bPermanentInfo!, + permanentInfoSig: bPermanentInfoSig!, + stableInfo: bStableInfo!, + stableInfoSig: bStableInfoSig!, + ckksKeys: []) + XCTAssertNil(errorVouchingWithoutTLKs, "Should be no error vouching without uploading TLKShares") + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("A vouches for B, but doesn't only has provisional TLKs at the time") + let provisionalManateeKeySet = try self.makeFakeKeyHierarchy(zoneID: CKRecordZone.ID(zoneName: "Manatee")) + provisionalManateeKeySet.newUpload = true + + let (_, _, errorVouchingWithProvisionalTLKs) = + containerA.vouchSync(test: self, + peerID: bPeerID!, + permanentInfo: bPermanentInfo!, + permanentInfoSig: bPermanentInfoSig!, + stableInfo: bStableInfo!, + stableInfoSig: bStableInfoSig!, + ckksKeys: [provisionalManateeKeySet]) + XCTAssertNil(errorVouchingWithProvisionalTLKs, "Should be no error vouching without uploading TLKShares for a non-existent key") + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("A vouches for B") + let (voucherData, voucherSig, error3) = + containerA.vouchSync(test: self, + peerID: bPeerID!, + permanentInfo: bPermanentInfo!, + permanentInfoSig: bPermanentInfoSig!, + stableInfo: bStableInfo!, + stableInfoSig: bStableInfoSig!, + ckksKeys: [self.manateeKeySet]) + XCTAssertNil(error3) + XCTAssertNotNil(voucherData) + XCTAssertNotNil(voucherSig) + + // As part of the vouch, A should have uploaded a tlkshare for B + assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("B joins") + let (peerID, _, _, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) + XCTAssertNil(error) + XCTAssertEqual(peerID, bPeerID!) + } + + _ = containerA.dumpSync(test: self) + _ = containerB.dumpSync(test: self) + _ = containerC.dumpSync(test: self) + + print("preparing C") + let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _, error4) = + containerC.prepareSync(test: self, epoch: 1, machineID: "ccc", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + let state = containerC.getStateSync(test: self) + XCTAssertFalse( state.bottles.filter { $0.peerID == cPeerID } .isEmpty, "should have a bottle for peer") + let secret = containerC.loadSecretSync(test: self, label: cPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(error4) + XCTAssertNotNil(cPeerID) + XCTAssertNotNil(cPermanentInfo) + XCTAssertNotNil(cPermanentInfoSig) + + do { + // C, when it joins, will create a new CKKS zone. It should also upload TLKShares for A and B. + let provisionalEngramKeySet = try self.makeFakeKeyHierarchy(zoneID: CKRecordZone.ID(zoneName: "Engram")) + provisionalEngramKeySet.newUpload = true + + assertNoTLKShareFor(peerID: cPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + assertNoTLKShareFor(peerID: cPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) + + print("B vouches for C") + let (voucherData, voucherSig, error) = + containerB.vouchSync(test: self, + peerID: cPeerID!, + permanentInfo: cPermanentInfo!, + permanentInfoSig: cPermanentInfoSig!, + stableInfo: cStableInfo!, + stableInfoSig: cStableInfoSig!, + ckksKeys: [self.manateeKeySet]) + XCTAssertNil(error) + XCTAssertNotNil(voucherData) + XCTAssertNotNil(voucherSig) + + assertTLKShareFor(peerID: cPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("C joins") + let (peerID, _, _, error2) = containerC.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [self.manateeKeySet, provisionalEngramKeySet], + tlkShares: []) + XCTAssertNil(error2) + XCTAssertEqual(peerID, cPeerID!) + + assertTLKShareFor(peerID: cPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) + assertTLKShareFor(peerID: aPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) + assertTLKShareFor(peerID: bPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) + } + + print("A updates") + do { + let (_, _, error) = containerA.updateSync(test: self) + XCTAssertNil(error) + } + + do { + let state = containerA.getStateSync(test: self) + let a = state.peers[aPeerID!]! + XCTAssertTrue(a.dynamicInfo!.includedPeerIDs.contains(cPeerID!)) + } + + _ = containerA.dumpSync(test: self) + _ = containerB.dumpSync(test: self) + _ = containerC.dumpSync(test: self) + + XCTAssertEqual(containerA.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + XCTAssertEqual(containerB.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + XCTAssertEqual(containerC.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + } + + func testPreApprovedJoinWithEnforceIDMSListNotSetBehavior() throws { + let description = tmpStoreDescription(name: "container.db") + let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + + XCTAssertEqual(containerA.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + XCTAssertEqual(containerB.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + + print("preparing A") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = + containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + XCTAssertNil(error) + XCTAssertNotNil(aPeerID) + XCTAssertNotNil(aPermanentInfo) + XCTAssertNotNil(aPermanentInfoSig) + + XCTAssertNotNil(aPolicy, "Should have a policy coming back from a successful prepare") + XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") + + print("preparing B") + let (bPeerID, bPermanentInfo, bPermanentInfoSig, _, _, _, error2) = + containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + let state = containerB.getStateSync(test: self) + XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + let secret = containerB.loadSecretSync(test: self, label: bPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(error2) + XCTAssertNotNil(bPeerID) + XCTAssertNotNil(bPermanentInfo) + XCTAssertNotNil(bPermanentInfoSig) + + // Now, A establishes preapproving B + // Note: secd is responsible for passing in TLKShares to these preapproved keys in sosTLKShares + + let bPermanentInfoParsed = TPPeerPermanentInfo(peerID: bPeerID!, data: bPermanentInfo!, sig: bPermanentInfoSig!, keyFactory: TPECPublicKeyFactory()) + XCTAssertNotNil(bPermanentInfoParsed, "Should have parsed B's permanent info") + + print("establishing A") + do { + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: [bPermanentInfoParsed!.signingPubKey.spki()]) + XCTAssertNil(error) + XCTAssertNotNil(peerID) + } + + do { + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("B joins by preapproval, and uploads all TLKShares that it has") + let (bJoinedPeerID, _, policy, bJoinedError) = containerB.preapprovedJoinSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: []) + XCTAssertNil(bJoinedError, "Should be no error joining by preapproval") + XCTAssertNotNil(bJoinedPeerID, "Should have a peer ID out of join") + XCTAssertNotNil(policy, "Should have a policy back from preapprovedjoin") + + assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + } + + _ = containerA.dumpSync(test: self) + _ = containerB.dumpSync(test: self) + + XCTAssertEqual(containerA.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + XCTAssertEqual(containerB.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + } + + func testReloadingContainerIDMSListVariable() throws { + let store = tmpStoreDescription(name: "container.db") + let contextID = "contextID" + var container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: store, cuttlefish: cuttlefish) + + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + let state = container.getStateSync(test: self) + XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + let secret = container.loadSecretSync(test: self, label: peerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNotNil(peerID) + XCTAssertNotNil(permanentInfo) + XCTAssertNotNil(permanentInfoSig) + XCTAssertNil(error) + + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + + _ = container.dumpSync(test: self) + + do { + container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: store, cuttlefish: cuttlefish) + XCTAssertEqual(container.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") + } catch { + XCTFail("Creating container errored: \(error)") + } + + let (peerID2, _, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + XCTAssertNil(error2) + XCTAssertNotNil(peerID2) + + _ = container.dumpSync(test: self) + } } diff --git a/keychain/analytics/SecEventMetric.m b/keychain/analytics/SecEventMetric.m index f40e458d..7f1493b1 100644 --- a/keychain/analytics/SecEventMetric.m +++ b/keychain/analytics/SecEventMetric.m @@ -54,8 +54,7 @@ } - (instancetype)initWithCoder:(NSCoder *)coder { - self = [super init]; - if (self) { + if ((self = [super init])) { NSMutableSet *attributeClasses = [[[self class] supportedAttributeClasses] mutableCopy]; [attributeClasses addObject:[NSDictionary class]]; diff --git a/keychain/analytics/SecMetrics.m b/keychain/analytics/SecMetrics.m index 5aa7ef4c..cabdc1c7 100644 --- a/keychain/analytics/SecMetrics.m +++ b/keychain/analytics/SecMetrics.m @@ -23,7 +23,7 @@ #import #import -#import +#import #import #import #import @@ -42,6 +42,8 @@ #import "keychain/analytics/C2Metric/SECC2MPDeviceInfo.h" #import +#import + @interface SecMetrics () diff --git a/keychain/behavior/SFBehavior.h b/keychain/behavior/SFBehavior.h deleted file mode 100644 index 69fc256a..00000000 --- a/keychain/behavior/SFBehavior.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#if __OBJC2__ - -#import - -typedef NS_ENUM(uint32_t, SFBehaviorRamping) { - SFBehaviorRampingDisabled = 0, /* must not be enabled */ - SFBehaviorRampingEnabled = 1, /* unconditionally enabled */ - SFBehaviorRampingPromoted = 2, /* should be promoted by application */ - SFBehaviorRampingVisible = 3, /* allowed to enabled */ -}; - -@interface SFBehavior : NSObject - -+ (SFBehavior *)behaviorFamily:(NSString *)family; -- (instancetype)init NS_UNAVAILABLE; - -/* - * Ramping control controlled by CloudKit and configuration - * - * Return the current ramping state, can be called as often as clients want, state is cached - * and fetched in background (returning SFBehaviorRampingDisabled) until server changes the value. - * - * Ramping always go from Disable -> Visiable -> Promoted -> Enabled, can can skip over steps in-between. - * - * The feature can also go from { Visiable, Promoted, Enabled } -> Disabled if the feature is disabled - * - * Passing in force will for fetching the value from the server and bypass all caching, this will - * take its sweet time, so don't block UI on this operation, using force is not recommended. - */ -- (SFBehaviorRamping)ramping:(NSString *)feature force:(bool)force; - -/* - * This feature is assumed to be enabled unless disabled by configuration. - */ -- (bool)featureEnabled:(NSString *)feature; -/* - * This feature is assumed to be disabled unless enabled by configuration. - */ -- (bool)featureDisabled:(NSString *)feature; - -/* - * Fetch configuration values that might be changed from server configuration - */ -- (NSNumber *)configurationNumber:(NSString *)configuration defaultValue:(NSNumber *)defaultValue; -- (NSString *)configurationString:(NSString *)configuration defaultValue:(NSString *)defaultValue; - -@end - -#endif diff --git a/keychain/behavior/SFBehavior.m b/keychain/behavior/SFBehavior.m deleted file mode 100644 index cd46021f..00000000 --- a/keychain/behavior/SFBehavior.m +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#import "SFBehavior.h" -#import - -#if __OBJC2__ - -@interface SFBehavior () -@property NSString *family; -@property NSXPCConnection *connection; -- (instancetype)initBehaviorFamily:(NSString *)family connection:(NSXPCConnection *)connection; -@end - -@protocol SFBehaviorProtocol -- (void)ramping:(NSString *)feature family:(NSString*)family complete:(void (^)(SFBehaviorRamping))complete; -- (void)feature:(NSString *)feature family:(NSString*)family defaultValue:(bool)defaultValue complete:(void (^)(bool))complete; - -- (void)configNumber:(NSString *)configuration family:(NSString*)family complete:(void (^)(NSNumber *))complete; -- (void)configString:(NSString *)configuration family:(NSString*)family complete:(void (^)(NSString *))complete; -@end - - -@implementation SFBehavior - -+ (SFBehavior *)behaviorFamily:(NSString *)family -{ - static dispatch_once_t onceToken = 0; - static NSMutableDictionary *behaviors; - static NSXPCConnection *connection = NULL; - dispatch_once(&onceToken, ^{ - behaviors = [NSMutableDictionary dictionary]; - connection = [[NSXPCConnection alloc] initWithMachServiceName:@"com.apple.security.behavior" options:NSXPCConnectionPrivileged]; - - connection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(SFBehaviorProtocol)]; - [connection resume]; - }); - - SFBehavior *behavior = nil; - @synchronized (behaviors) { - behavior = behaviors[family]; - if (behavior == NULL) { - behavior = [[SFBehavior alloc] initBehaviorFamily:family connection:connection]; - behaviors[family] = behavior; - } - } - - return behavior; -} - -- (instancetype)initBehaviorFamily:(NSString *)family connection:(NSXPCConnection *)connection -{ - self = [super init]; - if (self) { - _family = family; - _connection = connection; - } - return self; -} - -- (SFBehaviorRamping)ramping:(NSString *)feature force:(bool)force -{ - __block SFBehaviorRamping _ramping = SFBehaviorRampingDisabled; - [[_connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - }] ramping:feature family:_family complete:^(SFBehaviorRamping ramping) { - _ramping = ramping; - }]; - return _ramping; -} - -- (bool)feature:(NSString *)feature defaultValue:(bool)defaultValue -{ - __block bool enabled = defaultValue; - - [[_connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - }] feature:feature family:_family defaultValue:defaultValue complete:^(bool returnFeature) { - enabled = returnFeature; - }]; - return enabled; - -} - -- (bool)featureEnabled:(NSString *)feature -{ - return [self feature:feature defaultValue:true]; -} - -- (bool)featureDisabled:(NSString *)feature -{ - return ![self feature:feature defaultValue:false]; -} - -- (NSNumber *)configurationNumber:(NSString *)configuration defaultValue:(NSNumber *)defaultValue -{ - __block NSNumber *_number = defaultValue; - - [[_connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - }] configNumber:configuration family:_family complete:^(NSNumber *number) { - if (number) - _number = number; - }]; - return _number; -} - -- (NSString *)configurationString:(NSString *)configuration defaultValue:(NSString *)defaultValue -{ - __block NSString *_string = defaultValue; - - [[_connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - }] configString:configuration family:_family complete:^(NSString *string) { - if (string) - _string = string; - }]; - return _string; -} - -@end - -#endif /* __OBJC2__ */ - diff --git a/keychain/ckks/CKKS.h b/keychain/ckks/CKKS.h index 50070ebc..99b0aad4 100644 --- a/keychain/ckks/CKKS.h +++ b/keychain/ckks/CKKS.h @@ -32,10 +32,10 @@ #ifdef __OBJC__ #import -NS_ASSUME_NONNULL_BEGIN -#else +#import "keychain/ot/OctagonStateMachine.h" +#endif /* __OBJC__ */ + CF_ASSUME_NONNULL_BEGIN -#endif #ifdef __OBJC__ @@ -62,6 +62,7 @@ extern CKKSItemState* const SecCKKSStateInFlight; extern CKKSItemState* const SecCKKSStateReencrypt; extern CKKSItemState* const SecCKKSStateError; extern CKKSItemState* const SecCKKSStateDeleted; // meta-state: please delete this item! +extern CKKSItemState* const SecCKKSStateMismatchedView; // This item was for a different view at processing time. Held pending a policy refresh. /* Processed States */ @protocol SecCKKSProcessedState @@ -157,9 +158,16 @@ extern NSString* const SecCKRecordManifestLeafDERKey; extern NSString* const SecCKRecordManifestLeafDigestKey; /* Zone Key Hierarchy States */ +#if OCTAGON +typedef OctagonState CKKSZoneKeyState; +#else +// This is here to allow for building with Octagon off @protocol SecCKKSZoneKeyState @end typedef NSString CKKSZoneKeyState; +#endif + +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForCloudKitAccountStatus; // CKKS is currently logged out extern CKKSZoneKeyState* const SecCKKSZoneKeyStateLoggedOut; @@ -170,17 +178,28 @@ extern CKKSZoneKeyState* const SecCKKSZoneKeyStateInitializing; extern CKKSZoneKeyState* const SecCKKSZoneKeyStateInitialized; // CKKSZone has informed us that zone setup did not work. Try again soon! extern CKKSZoneKeyState* const SecCKKSZoneKeyStateZoneCreationFailed; + +// Everything is likely ready. Double-check. +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateBecomeReady; // Everything is ready and waiting for input. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateReady; + // We're presumably ready, but we'd like to do one or two more checks after we unlock. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateReadyPendingUnlock; +// A key hierarchy fetch will now begin +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateBeginFetch; + // We're currently refetching the zone extern CKKSZoneKeyState* const SecCKKSZoneKeyStateFetch; // A Fetch has just been completed which includes some new keys to process extern CKKSZoneKeyState* const SecCKKSZoneKeyStateFetchComplete; // We'd really like a full refetch. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateNeedFullRefetch; + +// The TLK doesn't appear to be present. Determine what to to next! +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateTLKMissing; + // We've received a wrapped TLK, but we don't have its contents yet. Wait until they arrive. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLK; @@ -191,8 +210,11 @@ extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLKUpload; // We've received a wrapped TLK, but we can't process it until the keybag unlocks. Wait until then. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForUnlock; +// Some operation has noticed that trust is lost. Will enter WaitForTrust. +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateLoseTrust; // We've done some CK ops, but are waiting for the trust system to tell us to continue extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTrust; + // Things are unhealthy, but we're not sure entirely why. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateUnhealthy; // Something has gone horribly wrong with the current key pointers. @@ -215,8 +237,6 @@ extern CKKSZoneKeyState* const SecCKKSZoneKeyStateResettingLocalData; // Fatal error. Will not proceed unless fixed from outside class. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateError; -// This CKKS instance has been cancelled. -extern CKKSZoneKeyState* const SecCKKSZoneKeyStateCancelled; // If you absolutely need to numberify one of the above constants, here's your maps. NSDictionary* CKKSZoneKeyStateMap(void); @@ -226,7 +246,7 @@ CKKSZoneKeyState* CKKSZoneKeyRecover(NSNumber* stateNumber); // Use this to determine if CKKS believes the current state is "transient": that is, should resolve itself with further local processing // or 'nontransient': further local processing won't progress. Either we're ready, or waiting for the user to unlock, or a remote device to do something. -bool CKKSKeyStateTransient(CKKSZoneKeyState* state); +NSSet* CKKSKeyStateNonTransientStates(void); /* Hide Item Length */ extern const NSUInteger SecCKKSItemPaddingBlockSize; @@ -298,6 +318,9 @@ void SecCKKSTestSetDisableSOS(bool set); bool SecCKKSTestDisableKeyNotifications(void); void SecCKKSTestSetDisableKeyNotifications(bool set); +bool SecCKKSTestSkipScan(void); +bool SecCKKSSetTestSkipScan(bool value); + // TODO: handle errors better typedef CF_ENUM(CFIndex, CKKSErrorCode) { CKKSNotInitialized = 9, @@ -337,6 +360,12 @@ typedef CF_ENUM(CFIndex, CKKSErrorCode) { CKKSKeysMissing = 53, CKKSCircularKeyReference = 54, + + CKKSErrorViewIsPaused = 55, + CKKSErrorPolicyNotLoaded = 56, + + CKKSErrorUnexpectedNil = 57, + CKKSErrorGenerationCountMismatch = 58, }; typedef CF_ENUM(CFIndex, CKKSResultDescriptionErrorCode) { @@ -384,6 +413,8 @@ typedef CF_ENUM(CFIndex, CKKSServerExtensionErrorCode) { //CKKSServerInvalidCurrentItem = 17, }; +#if __OBJC__ + #define SecTranslateError(nserrorptr, cferror) \ if(nserrorptr) { \ *nserrorptr = (__bridge_transfer NSError*)cferror; \ @@ -391,62 +422,38 @@ typedef CF_ENUM(CFIndex, CKKSServerExtensionErrorCode) { CFReleaseNull(cferror); \ } +extern os_log_t CKKSLogObject(NSString* scope, NSString* _Nullable zoneName); + // Very similar to the secerror, secnotice, and secinfo macros in debugging.h, but add zoneNames -#define ckkserrorwithzonename(scope, zoneName, format, ...) \ - { \ - os_log(secLogObjForScope("SecError"), scope "-%@: " format, (zoneName ? zoneName : @"unknown"), ##__VA_ARGS__); \ - } -#define ckksnoticewithzonename(scope, zoneName, format, ...) \ - { \ - os_log(secLogObjForCFScope((__bridge CFStringRef)[@(scope "-") stringByAppendingString:(zoneName ? zoneName : @"unknown")]), \ - format, \ - ##__VA_ARGS__); \ - } -#define ckksinfowithzonename(scope, zoneName, format, ...) \ - { \ - os_log_debug(secLogObjForCFScope((__bridge CFStringRef)[@(scope "-") stringByAppendingString:(zoneName ? zoneName : @"unknown")]), \ - format, \ - ##__VA_ARGS__); \ - } +#define ckkserrorwithzonename(scope, zoneName, format, ...) \ +{ \ + os_log_with_type(CKKSLogObject(@scope, zoneName), \ + OS_LOG_TYPE_ERROR, \ + format, \ + ##__VA_ARGS__); \ +} -#define ckkserror(scope, zoneNameHaver, format, ...) \ - { \ - NSString* znh = zoneNameHaver.zoneName; \ - ckkserrorwithzonename(scope, znh, format, ##__VA_ARGS__) \ - } -#define ckksnotice(scope, zoneNameHaver, format, ...) \ - { \ - NSString* znh = zoneNameHaver.zoneName; \ - ckksnoticewithzonename(scope, znh, format, ##__VA_ARGS__) \ - } -#define ckksinfo(scope, zoneNameHaver, format, ...) \ - { \ - NSString* znh = zoneNameHaver.zoneName; \ - ckksinfowithzonename(scope, znh, format, ##__VA_ARGS__) \ - } +#define ckkserror(scope, zoneNameBearer, format, ...) \ + ckkserrorwithzonename(scope, zoneNameBearer.zoneName, format, ##__VA_ARGS__) -#undef ckksdebug -#if !defined(NDEBUG) -#define ckksdebugwithzonename(scope, zoneName, format, ...) \ - { \ - os_log_debug(secLogObjForCFScope((__bridge CFStringRef)[@(scope "-") stringByAppendingString:(zoneName ? zoneName : @"unknown")]), \ - format, \ - ##__VA_ARGS__); \ - } -#define ckksdebug(scope, zoneNameHaver, format, ...) \ - { \ - NSString* znh = zoneNameHaver.zoneName; \ - ckksdebugwithzonename(scope, znh, format, ##__VA_ARGS__) \ - } -#else -#define ckksdebug(scope, ...) /* nothing */ -#endif +#define ckkserror_global(scope, format, ...) \ + ckkserrorwithzonename(scope, nil, format, ##__VA_ARGS__) + +#define ckksnotice(scope, zoneNameBearer, format, ...) \ + os_log(CKKSLogObject(@scope, zoneNameBearer.zoneName), format, ##__VA_ARGS__) + +#define ckksnotice_global(scope, format, ...) \ + os_log(CKKSLogObject(@scope, nil), format, ##__VA_ARGS__) + +#define ckksinfo(scope, zoneNameBearer, format, ...) \ + os_log_debug(CKKSLogObject(@scope, zoneNameBearer.zoneName), format, ##__VA_ARGS__) + +#define ckksinfo_global(scope, format, ...) \ + os_log_debug(CKKSLogObject(@scope, nil), format, ##__VA_ARGS__) + +#endif // __OBJC__ -#ifdef __OBJC__ -NS_ASSUME_NONNULL_END -#else CF_ASSUME_NONNULL_END -#endif #endif /* CKKS_h */ diff --git a/keychain/ckks/CKKS.m b/keychain/ckks/CKKS.m index 934ff6a2..31ce6d7a 100644 --- a/keychain/ckks/CKKS.m +++ b/keychain/ckks/CKKS.m @@ -27,7 +27,6 @@ #import #endif -#include #include "keychain/securityd/SecItemServer.h" #include @@ -38,6 +37,7 @@ #import "keychain/ckks/CKKSKey.h" #import "keychain/ot/OTManager.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" NSDictionary* CKKSZoneKeyStateMap(void) { static NSDictionary* map = nil; @@ -46,7 +46,7 @@ NSDictionary* CKKSZoneKeyStateMap(void) { map = @{ SecCKKSZoneKeyStateReady: @0U, SecCKKSZoneKeyStateError: @1U, - SecCKKSZoneKeyStateCancelled: @2U, + //SecCKKSZoneKeyStateCancelled: @2U, SecCKKSZoneKeyStateInitializing: @3U, SecCKKSZoneKeyStateInitialized: @4U, @@ -70,6 +70,11 @@ NSDictionary* CKKSZoneKeyStateMap(void) { SecCKKSZoneKeyStateWaitForTLKUpload: @22U, SecCKKSZoneKeyStateWaitForTLKCreation: @23U, SecCKKSZoneKeyStateProcess: @24U, + SecCKKSZoneKeyStateBecomeReady: @25U, + SecCKKSZoneKeyStateLoseTrust: @26U, + SecCKKSZoneKeyStateTLKMissing: @27U, + SecCKKSZoneKeyStateWaitForCloudKitAccountStatus:@28U, + SecCKKSZoneKeyStateBeginFetch: @29U, }; }); return map; @@ -106,18 +111,27 @@ CKKSZoneKeyState* CKKSZoneKeyRecover(NSNumber* stateNumber) { return SecCKKSZoneKeyStateError; } -bool CKKSKeyStateTransient(CKKSZoneKeyState* state) { - // Easier to compare against a blacklist of end states - bool nontransient = [state isEqualToString:SecCKKSZoneKeyStateReady] || - [state isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForTrust] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForTLK] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForUnlock] || - [state isEqualToString:SecCKKSZoneKeyStateError] || - [state isEqualToString:SecCKKSZoneKeyStateCancelled]; - return !nontransient; +NSSet* CKKSKeyStateNonTransientStates() +{ + static NSSet* states = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + states = [NSSet setWithArray:@[ + SecCKKSZoneKeyStateReady, + SecCKKSZoneKeyStateReadyPendingUnlock, + SecCKKSZoneKeyStateWaitForTrust, + SecCKKSZoneKeyStateWaitForTLK, + SecCKKSZoneKeyStateWaitForTLKCreation, + SecCKKSZoneKeyStateWaitForTLKUpload, + SecCKKSZoneKeyStateWaitForUnlock, + SecCKKSZoneKeyStateError, + SecCKKSZoneKeyStateLoggedOut, +#if OCTAGON + OctagonStateMachineHalted, +#endif + ]]; + }); + return states; } #if OCTAGON @@ -128,7 +142,7 @@ static bool testCKKS = false; bool SecCKKSIsEnabled(void) { if([CKDatabase class] == nil) { // CloudKit is not linked. We cannot bring CKKS up; disable it with prejudice. - secerror("CKKS: CloudKit.framework appears to not be linked. Cannot enable CKKS (on pain of crash)."); + ckkserror_global("ckks", "CloudKit.framework appears to not be linked. Cannot enable CKKS (on pain of crash)."); return false; } @@ -146,7 +160,8 @@ bool SecCKKSDisable() { } bool SecCKKSResetSyncing(void) { - [CKKSViewManager resetManager: true setTo: nil]; + // The function name is a bit of a lie, but it does the thing. + [OTManager resetManager:true to:nil]; return SecCKKSIsEnabled(); } @@ -157,7 +172,7 @@ bool SecCKKSTestsEnabled(void) { bool SecCKKSTestsEnable(void) { if([CKDatabase class] == nil) { // CloudKit is not linked. We cannot bring CKKS up; disable it with prejudice. - secerror("CKKS: CloudKit.framework appears to not be linked. Cannot enable CKKS testing."); + ckkserror_global("ckks", "CloudKit.framework appears to not be linked. Cannot enable CKKS testing."); testCKKS = false; return false; } @@ -209,7 +224,7 @@ bool SecCKKSReduceRateLimiting(void) { [defaults registerDefaults: @{key: CKKSReduceRateLimiting ? @YES : @NO}]; CKKSReduceRateLimiting = !![defaults boolForKey:@"reduce-rate-limiting"]; - secnotice("ckks", "reduce-rate-limiting is %@", CKKSReduceRateLimiting ? @"on" : @"off"); + ckksnotice_global("ratelimit", "reduce-rate-limiting is %@", CKKSReduceRateLimiting ? @"on" : @"off"); }); return CKKSReduceRateLimiting; @@ -218,7 +233,7 @@ bool SecCKKSReduceRateLimiting(void) { bool SecCKKSSetReduceRateLimiting(bool value) { (void) SecCKKSReduceRateLimiting(); // Call this once to read the defaults write CKKSReduceRateLimiting = value; - secnotice("ckks", "reduce-rate-limiting is now %@", CKKSReduceRateLimiting ? @"on" : @"off"); + ckksnotice_global("ratelimit", "reduce-rate-limiting is now %@", CKKSReduceRateLimiting ? @"on" : @"off"); return CKKSReduceRateLimiting; } @@ -233,7 +248,7 @@ bool SecCKKSShareTLKs(void) { [defaults registerDefaults: @{@"tlksharing": CKKSShareTLKs ? @YES : @NO}]; CKKSShareTLKs = !![defaults boolForKey:@"tlksharing"]; - secnotice("ckksshare", "TLK sharing is %@", CKKSShareTLKs ? @"on" : @"off"); + ckksnotice_global("ckksshare", "TLK sharing is %@", CKKSShareTLKs ? @"on" : @"off"); }); return CKKSShareTLKs; @@ -277,16 +292,26 @@ void SecCKKSTestSetDisableKeyNotifications(bool set) { CKKSDisableKeyNotifications = set; } +static bool CKKSSkipScan = false; +bool SecCKKSTestSkipScan(void) { + return CKKSSkipScan; +} +bool SecCKKSSetTestSkipScan(bool value) { + CKKSSkipScan = value; + return CKKSSkipScan; +} + void SecCKKSTestResetFlags(void) { SecCKKSTestSetDisableAutomaticUUID(false); SecCKKSTestSetDisableSOS(false); SecCKKSTestSetDisableKeyNotifications(false); + SecCKKSSetTestSkipScan(false); } #else /* NO OCTAGON */ bool SecCKKSIsEnabled(void) { - secerror("CKKS was disabled at compile time."); + ckkserror_global("ckks", "CKKS was disabled at compile time."); return false; } @@ -322,7 +347,7 @@ void SecCKKSInitialize(SecDbRef db) { if(!SecCKKSTestsEnabled()) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - [OctagonAPSReceiver receiverForEnvironment:APSEnvironmentProduction namedDelegatePort:SecCKKSAPSNamedPort apsConnectionClass:[APSConnection class]]; + [[OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort apsConnectionClass:[APSConnection class]] registerForEnvironment:APSEnvironmentProduction]; }); } } @@ -337,7 +362,7 @@ void SecCKKSNotifyBlock(SecDbConnectionRef dbconn, SecDbTransactionPhase phase, // Ignore our own changes, otherwise we'd infinite-loop. if(source == kSecDbCKKSTransaction) { - secinfo("ckks", "Ignoring kSecDbCKKSTransaction notification"); + ckksinfo_global("ckks", "Ignoring kSecDbCKKSTransaction notification"); return; } @@ -348,7 +373,7 @@ void SecCKKSNotifyBlock(SecDbConnectionRef dbconn, SecDbTransactionPhase phase, SecDbEventTranslateComponents(r, (CFTypeRef*) &deleted, (CFTypeRef*) &added); if(!added && !deleted) { - secerror("CKKS: SecDbEvent gave us garbage: %@", r); + ckkserror_global("ckks", "SecDbEvent gave us garbage: %@", r); return; } @@ -378,13 +403,15 @@ void CKKSRegisterSyncStatusCallback(CFStringRef cfuuid, SecBoolCFErrorCallback c void SecCKKSPerformLocalResync() { #if OCTAGON - secnotice("ckks", "Local keychain was reset; performing local resync"); - [[CKKSViewManager manager] rpcResyncLocal:nil reply:^(NSError *result) { - if(result) { - secnotice("ckks", "Local keychain reset resync finished with an error: %@", result); - } else { - secnotice("ckks", "Local keychain reset resync finished successfully"); - } - }]; + if(SecCKKSIsEnabled()) { + ckksnotice_global("reset", "Local keychain was reset; performing local resync"); + [[CKKSViewManager manager] rpcResyncLocal:nil reply:^(NSError *result) { + if(result) { + ckksnotice_global("reset", "Local keychain reset resync finished with an error: %@", result); + } else { + ckksnotice_global("reset", "Local keychain reset resync finished successfully"); + } + }]; + } #endif } diff --git a/keychain/ckks/CKKSAccountStateTracker.h b/keychain/ckks/CKKSAccountStateTracker.h index e83a8a24..ef217967 100644 --- a/keychain/ckks/CKKSAccountStateTracker.h +++ b/keychain/ckks/CKKSAccountStateTracker.h @@ -83,6 +83,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status); @end @protocol CKKSCloudKitAccountStateTrackingProvider - (dispatch_semaphore_t)registerForNotificationsOfCloudKitAccountStatusChange:(id)listener; +- (BOOL)notifyCKAccountStatusChangeAndWait:(dispatch_time_t)timeout; @end #pragma mark -- Tracker diff --git a/keychain/ckks/CKKSAccountStateTracker.m b/keychain/ckks/CKKSAccountStateTracker.m index 05900dc0..8db458f7 100644 --- a/keychain/ckks/CKKSAccountStateTracker.m +++ b/keychain/ckks/CKKSAccountStateTracker.m @@ -24,7 +24,6 @@ #if OCTAGON #include -#include #include #include #include "keychain/SecureObjectSync/SOSInternal.h" @@ -100,7 +99,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) _hsa2iCloudAccountInitialized = [[CKKSCondition alloc] init]; id notificationCenter = [self.nsnotificationCenterClass defaultCenter]; - secinfo("ckksaccount", "Registering with notification center %@", notificationCenter); + ckksinfo_global("ckksaccount", "Registering with notification center %@", notificationCenter); [notificationCenter addObserver:self selector:@selector(notifyCKAccountStatusChange:) name:CKAccountChangedNotification object:NULL]; WEAKIFY(self); @@ -178,15 +177,15 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_queue_t objQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); [self.ckChangeListeners setObject:listener forKey: objQueue]; - secinfo("ckksaccount-ck", "adding a new listener: %@", listener); + ckksinfo_global("ckksaccount-ck", "adding a new listener: %@", listener); // If we know the current account status, let this listener know if(self.firstCKAccountFetch) { - secinfo("ckksaccount-ck", "notifying new listener %@ of current state %@", listener, self.currentCKAccountInfo); + ckksinfo_global("ckksaccount-ck", "notifying new listener %@ of current state %@", listener, self.currentCKAccountInfo); dispatch_group_t g = dispatch_group_create(); if(!g) { - secnotice("ckksaccount-ck", "Unable to get dispatch group."); + ckkserror_global("ckksaccount-ck", "Unable to get dispatch group."); dispatch_semaphore_signal(finishedSema); return; } @@ -217,14 +216,14 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) STRONGIFY(self); if(error) { - secerror("ckksaccount: error getting account info: %@", error); + ckkserror_global("ckksaccount", "error getting account info: %@", error); dispatch_semaphore_signal(finishedSema); return; } dispatch_sync(self.queue, ^{ self.firstCKAccountFetch = true; - secnotice("ckksaccount", "received CK Account info: %@", ckAccountInfo); + ckksnotice_global("ckksaccount", "received CK Account info: %@", ckAccountInfo); [self _onqueueUpdateAccountState:ckAccountInfo deliveredSemaphore:finishedSema]; }); }]; @@ -242,7 +241,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) [self.container fetchCurrentDeviceIDWithCompletionHandler:^(NSString* deviceID, NSError* ckerror) { STRONGIFY(self); if(!self) { - secerror("ckksaccount: Received fetchCurrentDeviceIDWithCompletionHandler callback with null AccountStateTracker"); + ckkserror_global("ckksaccount", "Received fetchCurrentDeviceIDWithCompletionHandler callback with null AccountStateTracker"); return; } @@ -250,14 +249,14 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_async(self.queue, ^{ STRONGIFY(self); if(self.currentCKAccountInfo.accountStatus == CKAccountStatusAvailable) { - secnotice("ckksaccount", "CloudKit deviceID is: %@ %@", deviceID, ckerror); + ckksnotice_global("ckksaccount", "CloudKit deviceID is: %@ %@", deviceID, ckerror); self.ckdeviceID = deviceID; self.ckdeviceIDError = ckerror; [self.ckdeviceIDInitialized fulfill]; } else { // Logged out! No ckdeviceid. - secerror("ckksaccount: Logged back out but still received a fetchCurrentDeviceIDWithCompletionHandler callback"); + ckkserror_global("ckksaccount", "Logged back out but still received a fetchCurrentDeviceIDWithCompletionHandler callback"); self.ckdeviceID = nil; self.ckdeviceIDError = nil; @@ -279,7 +278,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) SOSAccountStatus* sosstatus = [CKKSAccountStateTracker getCircleStatus]; dispatch_sync(self.queue, ^{ if(self.currentCircleStatus == nil || ![self.currentCircleStatus isEqual:sosstatus]) { - secnotice("ckksaccount", "moving to circle status: %@", sosstatus); + ckksnotice_global("ckksaccount", "moving to circle status: %@", sosstatus); self.currentCircleStatus = sosstatus; if (sosstatus.status == kSOSCCInCircle) { @@ -315,7 +314,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) [CKKSAccountStateTracker fetchCirclePeerID:^(NSString* peerID, NSError* error) { STRONGIFY(self); if(!self) { - secerror("ckksaccount: Received fetchCirclePeerID callback with null AccountStateTracker"); + ckkserror_global("ckksaccount", "Received fetchCirclePeerID callback with null AccountStateTracker"); return; } @@ -323,13 +322,13 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) STRONGIFY(self); if(self.currentCircleStatus && self.currentCircleStatus.status == kSOSCCInCircle) { - secnotice("ckksaccount", "Circle peerID is: %@ %@", peerID, error); + ckksnotice_global("ckksaccount", "Circle peerID is: %@ %@", peerID, error); // Still in circle. Proceed. self.accountCirclePeerID = peerID; self.accountCirclePeerIDError = error; [self.accountCirclePeerIDInitialized fulfill]; } else { - secerror("ckksaccount: Out of circle but still received a fetchCirclePeerID callback"); + ckkserror_global("ckksaccount", "Out of circle but still received a fetchCirclePeerID callback"); // Not in-circle. Throw away circle id. self.accountCirclePeerID = nil; self.accountCirclePeerIDError = nil; @@ -339,7 +338,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) }]; } else { // Not in-circle, reset circle ID - secnotice("ckksaccount", "out of circle(%@): resetting peer ID", sosstatus); + ckksnotice_global("ckksaccount", "out of circle(%@): resetting peer ID", sosstatus); self.accountCirclePeerID = nil; self.accountCirclePeerIDError = nil; self.accountCirclePeerIDInitialized = [[CKKSCondition alloc] init]; @@ -356,7 +355,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_group_t g = dispatch_group_create(); if(!g) { - secnotice("ckksaccount", "Unable to get dispatch group."); + ckksnotice_global("ckksaccount", "Unable to get dispatch group."); dispatch_semaphore_signal(finishedSema); return; } @@ -376,13 +375,13 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) if([self.currentCKAccountInfo isEqual: ckAccountInfo]) { // no-op. - secinfo("ckksaccount", "received another notification of CK Account State %@", ckAccountInfo); + ckksinfo_global("ckksaccount", "received another notification of CK Account State %@", ckAccountInfo); return; } if((self.currentCKAccountInfo == nil && ckAccountInfo != nil) || !(self.currentCKAccountInfo == ckAccountInfo || [self.currentCKAccountInfo isEqual: ckAccountInfo])) { - secnotice("ckksaccount", "moving to CK Account info: %@", ckAccountInfo); + ckksnotice_global("ckksaccount", "moving to CK Account info: %@", ckAccountInfo); CKAccountInfo* oldAccountInfo = self.currentCKAccountInfo; self.currentCKAccountInfo = ckAccountInfo; [self.ckAccountInfoInitialized fulfill]; @@ -424,8 +423,13 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) } } +- (BOOL)notifyCKAccountStatusChangeAndWait:(dispatch_time_t)timeout +{ + return dispatch_semaphore_wait([self notifyCKAccountStatusChange:nil], dispatch_time(DISPATCH_TIME_NOW, timeout)) == 0; +} + -(void)notifyCKAccountStatusChangeAndWaitForSignal { - dispatch_semaphore_wait([self notifyCKAccountStatusChange: nil], DISPATCH_TIME_FOREVER); + [self notifyCKAccountStatusChangeAndWait:DISPATCH_TIME_FOREVER]; } -(void)notifyCircleStatusChangeAndWaitForSignal { @@ -436,7 +440,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_group_t g = dispatch_group_create(); if(!g) { - secnotice("ckksaccount", "Unable to get dispatch group."); + ckksnotice_global("ckksaccount", "Unable to get dispatch group."); return nil; } @@ -448,12 +452,12 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) while ((dq = [enumerator nextObject])) { id listener = [self.ckChangeListeners objectForKey: dq]; - secinfo("ckksaccountblock", "Starting blocking for listener %@", listener); + ckksinfo_global("ckksaccountblock", "Starting blocking for listener %@", listener); WEAKIFY(listener); dispatch_group_async(g, dq, ^{ STRONGIFY(listener); // Do nothing in particular. It's just important that this block runs. - secinfo("ckksaccountblock", "Done blocking for listener %@", listener); + ckksinfo_global("ckksaccountblock", "Done blocking for listener %@", listener); }); } }); @@ -467,7 +471,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) SOSCCStatus status = SOSCCThisDeviceIsInCircle(&cferror); if(cferror) { - secerror("ckksaccount: error getting circle status: %@", cferror); + ckkserror_global("ckksaccount", "error getting circle status: %@", cferror); return [[SOSAccountStatus alloc] init:kSOSCCError error:CFBridgingRelease(cferror)]; } @@ -503,10 +507,10 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_sync(self.queue, ^{ if(error) { - secerror("ckksaccount: error getting octagon status: %@", error); + ckkserror_global("ckksaccount", "error getting octagon status: %@", error); self.octagonStatus = [[OTCliqueStatusWrapper alloc] initWithStatus:CliqueStatusError]; } else { - secnotice("ckksaccount", "Caching octagon status as (%@, %@)", OTCliqueStatusToString(status), peerID); + ckksnotice_global("ckksaccount", "Caching octagon status as (%@, %@)", OTCliqueStatusToString(status), peerID); self.octagonStatus = [[OTCliqueStatusWrapper alloc] initWithStatus:status]; } diff --git a/keychain/ckks/CKKSAnalytics.h b/keychain/ckks/CKKSAnalytics.h index 6c80b5c5..959d1511 100644 --- a/keychain/ckks/CKKSAnalytics.h +++ b/keychain/ckks/CKKSAnalytics.h @@ -38,10 +38,16 @@ extern NSString* const CKKSAnalyticsLastUnlock; extern NSString* const CKKSAnalyticsLastKeystateReady; extern NSString* const CKKSAnalyticsLastInCircle; +extern NSString* const CKKSAnalyticsNumberOfSyncItems; +extern NSString* const CKKSAnalyticsNumberOfTLKShares; +extern NSString* const CKKSAnalyticsNumberOfSyncKeys; + extern NSString* const OctagonAnalyticsStateMachineState; extern NSString* const OctagonAnalyticIcloudAccountState; +extern NSString* const OctagonAnalyticCDPBitStatus; extern NSString* const OctagonAnalyticsTrustState; extern NSString* const OctagonAnalyticsAttemptedJoin; +extern NSString* const OctagonAnalyticsUserControllableViewsSyncing; extern NSString* const OctagonAnalyticsLastHealthCheck; extern NSString* const OctagonAnalyticsSOSStatus; extern NSString* const OctagonAnalyticsDateOfLastPreflightPreapprovedJoin; @@ -55,6 +61,10 @@ extern NSString* const OctagonAnalyticsCDPStateRun; extern NSString* const OctagonAnalyticsHaveMachineID; extern NSString* const OctagonAnalyticsMIDOnMemoizedList; extern NSString* const OctagonAnalyticsPeersWithMID; +extern NSString* const OctagonAnalyticsEgoMIDMatchesCurrentMID; + +extern NSString* const OctagonAnalyticsTotalPeers; +extern NSString* const OctagonAnalyticsTotalViablePeers; extern NSString* const CKKSAnalyticsLastCKKSPush; extern NSString* const CKKSAnalyticsLastOctagonPush; @@ -65,8 +75,13 @@ extern NSString* const OctagonAnalyticsKeychainSyncProvisioned; extern NSString* const OctagonAnalyticsKeychainSyncEnabled; extern NSString* const OctagonAnalyticsCloudKitProvisioned; extern NSString* const OctagonAnalyticsCloudKitEnabled; +extern NSString* const OctagonAnalyticsSecureBackupTermsAccepted; -@class CKKSKeychainView; +extern NSString* const OctagonAnalyticsBottledUniqueTLKsRecovered; +extern NSString* const OctagonAnalyticsBottledTotalTLKShares; +extern NSString* const OctagonAnalyticsBottledTotalTLKSharesRecovered; +extern NSString* const OctagonAnalyticsBottledUniqueTLKsWithSharesCount; +extern NSString* const OctagonAnalyticsBottledTLKUniqueViewCount; @protocol CKKSAnalyticsFailableEvent @end @@ -129,6 +144,7 @@ extern CKKSAnalyticsFailableEvent* const OctagonEventPreflightVouchWithBottle; extern CKKSAnalyticsFailableEvent* const OctagonEventVoucherWithBottle; /* inner: join with recovery key */ +extern CKKSAnalyticsFailableEvent* const OctagonEventPreflightVouchWithRecoveryKey; extern CKKSAnalyticsFailableEvent* const OctagonEventVoucherWithRecoveryKey; extern CKKSAnalyticsFailableEvent* const OctagonEventJoinRecoveryKeyValidationFailed; extern CKKSAnalyticsFailableEvent* const OctagonEventJoinRecoveryKeyFailed; @@ -203,17 +219,12 @@ extern CKKSAnalyticsActivity* const OctagonSOSAdapterUpdateKeys; + (instancetype)logger; -- (void)logSuccessForEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view; +- (void)logSuccessForEvent:(CKKSAnalyticsFailableEvent*)event zoneName:(NSString*)viewName; - (void)logRecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event - inView:(CKKSKeychainView*)view + zoneName:(NSString*)viewName withAttributes:(NSDictionary*)attributes; -- (void)logRecoverableError:(NSError*)error - forEvent:(CKKSAnalyticsFailableEvent*)event - zoneName:(NSString*)zoneName - withAttributes:(NSDictionary *)attributes; - - (void)logRecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event withAttributes:(NSDictionary *)attributes; @@ -224,21 +235,21 @@ extern CKKSAnalyticsActivity* const OctagonSOSAdapterUpdateKeys; - (void)logUnrecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event - inView:(CKKSKeychainView*)view + zoneName:(NSString*)viewName withAttributes:(NSDictionary*)attributes; - (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event; -- (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event inView:(CKKSKeychainView*)view; +- (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event zoneName:(NSString*)zoneName; -- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key inView:(CKKSKeychainView *)view; -- (NSDate *)datePropertyForKey:(NSString *)key inView:(CKKSKeychainView *)view; +- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key zoneName:(NSString*)zoneName; +- (NSDate *)datePropertyForKey:(NSString *)key zoneName:(NSString*)zoneName; @end @interface CKKSAnalytics (UnitTesting) - (NSDate*)dateOfLastSuccessForEvent:(CKKSAnalyticsFailableEvent*)event - inView:(CKKSKeychainView*)view; + zoneName:(NSString*)zoneName; - (NSDictionary *)errorChain:(NSError *)error depth:(NSUInteger)depth; - (NSDictionary *)createErrorAttributes:(NSError *)error diff --git a/keychain/ckks/CKKSAnalytics.m b/keychain/ckks/CKKSAnalytics.m index dea0502b..08230cbe 100644 --- a/keychain/ckks/CKKSAnalytics.m +++ b/keychain/ckks/CKKSAnalytics.m @@ -47,10 +47,17 @@ NSString* const CKKSAnalyticsLastUnlock = @"lastUnlock"; NSString* const CKKSAnalyticsLastKeystateReady = @"lastKSR"; NSString* const CKKSAnalyticsLastInCircle = @"lastInCircle"; +NSString* const CKKSAnalyticsNumberOfSyncItems = @"numItems"; +NSString* const CKKSAnalyticsNumberOfTLKShares = @"numTLKShares"; +NSString* const CKKSAnalyticsNumberOfSyncKeys = @"numSyncKeys"; + NSString* const OctagonAnalyticsStateMachineState = @"OASMState"; NSString* const OctagonAnalyticIcloudAccountState = @"OAiC"; +NSString* const OctagonAnalyticCDPBitStatus = @"OACDPStatus"; + NSString* const OctagonAnalyticsTrustState = @"OATrust"; NSString* const OctagonAnalyticsAttemptedJoin = @"OAAttemptedJoin"; +NSString* const OctagonAnalyticsUserControllableViewsSyncing = @"OAUserViewsSyncing"; NSString* const OctagonAnalyticsLastHealthCheck = @"OAHealthCheck"; NSString* const OctagonAnalyticsSOSStatus = @"OASOSStatus"; NSString* const OctagonAnalyticsDateOfLastPreflightPreapprovedJoin = @"OALastPPJ"; @@ -62,9 +69,19 @@ NSString* const OctagonAnalyticsCoreFollowupLastFailureTime = @"OACFULastFailure NSString* const OctagonAnalyticsPrerecordPending = @"OAPrerecordPending"; NSString* const OctagonAnalyticsCDPStateRun = @"OACDPStateRun"; +NSString* const OctagonAnalyticsBottledUniqueTLKsRecovered = @"OABottledUniqueTLKsRecoveredCount"; +NSString* const OctagonAnalyticsBottledTotalTLKShares = @"OABottledTotalTLKSharesCount"; +NSString* const OctagonAnalyticsBottledTotalTLKSharesRecovered = @"OABottledTotalTLKSharesRecoveredCount"; +NSString* const OctagonAnalyticsBottledUniqueTLKsWithSharesCount = @"OABottledUniqueTLKsWithSharesCount"; +NSString* const OctagonAnalyticsBottledTLKUniqueViewCount = @"OABottledTLKUniqueViewCount"; + NSString* const OctagonAnalyticsHaveMachineID = @"OAMIDPresent"; NSString* const OctagonAnalyticsMIDOnMemoizedList = @"OAMIDOnList"; NSString* const OctagonAnalyticsPeersWithMID = @"OAPeersWithMID"; +NSString* const OctagonAnalyticsEgoMIDMatchesCurrentMID = @"OAMIDMatchesCurrentMID"; + +NSString* const OctagonAnalyticsTotalPeers = @"OAnPeers"; +NSString* const OctagonAnalyticsTotalViablePeers = @"OAnViablePeers"; NSString* const CKKSAnalyticsLastCKKSPush = @"lastCKKSPush"; NSString* const CKKSAnalyticsLastOctagonPush = @"lastOctagonPush"; @@ -75,6 +92,7 @@ NSString* const OctagonAnalyticsKeychainSyncProvisioned = @"OADCKCSProvisioned"; NSString* const OctagonAnalyticsKeychainSyncEnabled = @"OADCKCSEnabled"; NSString* const OctagonAnalyticsCloudKitProvisioned = @"OADCCKProvisioned"; NSString* const OctagonAnalyticsCloudKitEnabled = @"OADCCKEnabled"; +NSString* const OctagonAnalyticsSecureBackupTermsAccepted = @"OASecureBackupTermsAccepted"; static NSString* const CKKSAnalyticsAttributeRecoverableError = @"recoverableError"; static NSString* const CKKSAnalyticsAttributeZoneName = @"zone"; @@ -128,6 +146,7 @@ CKKSAnalyticsFailableEvent* const OctagonEventJoinWithVoucher = (CKKSAnalyticsFa CKKSAnalyticsFailableEvent* const OctagonEventPreflightVouchWithBottle = (CKKSAnalyticsFailableEvent*)@"OctagonEventPreflightVouchWithBottle"; CKKSAnalyticsFailableEvent* const OctagonEventVoucherWithBottle = (CKKSAnalyticsFailableEvent*)@"OctagonEventVoucherWithBottle"; +CKKSAnalyticsFailableEvent* const OctagonEventPreflightVouchWithRecoveryKey = (CKKSAnalyticsFailableEvent*)@"OctagonEventPreflightVouchWithRecoveryKey";; CKKSAnalyticsFailableEvent* const OctagonEventVoucherWithRecoveryKey = (CKKSAnalyticsFailableEvent*)@"OctagonEventVoucherWithRecoveryKey"; CKKSAnalyticsFailableEvent* const OctagonEventSetRecoveryKey = (CKKSAnalyticsFailableEvent*)@"OctagonEventSetRecoveryKey"; @@ -212,10 +231,10 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti return [super logger]; } -- (void)logSuccessForEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view +- (void)logSuccessForEvent:(CKKSAnalyticsFailableEvent*)event zoneName:(NSString*)zoneName { - [self logSuccessForEventNamed:[NSString stringWithFormat:@"%@-%@", view.zoneName, event]]; - [self setDateProperty:[NSDate date] forKey:[NSString stringWithFormat:@"last_success_%@-%@", view.zoneName, event]]; + [self logSuccessForEventNamed:[NSString stringWithFormat:@"%@-%@", zoneName, event]]; + [self setDateProperty:[NSDate date] forKey:[NSString stringWithFormat:@"last_success_%@-%@", zoneName, event]]; } - (bool)isCKPartialError:(NSError *)error @@ -288,7 +307,10 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti return eventAttributes; } -- (void)logRecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event zoneName:(NSString*)zoneName withAttributes:(NSDictionary *)attributes +- (void)logRecoverableError:(NSError*)error + forEvent:(CKKSAnalyticsFailableEvent*)event + zoneName:(NSString*)zoneName + withAttributes:(NSDictionary *)attributes { if (error == nil){ return; @@ -337,32 +359,10 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti [super logSoftFailureForEventNamed:event withAttributes:eventAttributes]; } -- (void)logRecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view withAttributes:(NSDictionary *)attributes -{ - if (error == nil){ - return; - } - NSMutableDictionary* eventAttributes = [NSMutableDictionary dictionary]; - - /* Don't allow caller to overwrite our attributes, lets merge them first */ - if (attributes) { - [eventAttributes setValuesForKeysWithDictionary:attributes]; - } - - [eventAttributes setValuesForKeysWithDictionary:@{ - CKKSAnalyticsAttributeRecoverableError : @(YES), - CKKSAnalyticsAttributeZoneName : view.zoneName, - CKKSAnalyticsAttributeErrorDomain : error.domain, - CKKSAnalyticsAttributeErrorCode : @(error.code) - }]; - - eventAttributes[CKKSAnalyticsAttributeErrorChain] = [self errorChain:error.userInfo[NSUnderlyingErrorKey] depth:0]; - [self addCKPartialError:eventAttributes error:error depth:0]; - - [super logSoftFailureForEventNamed:event withAttributes:eventAttributes]; -} - -- (void)logUnrecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view withAttributes:(NSDictionary *)attributes +- (void)logUnrecoverableError:(NSError*)error + forEvent:(CKKSAnalyticsFailableEvent*)event + zoneName:(NSString*)zoneName + withAttributes:(NSDictionary *)attributes { if (error == nil){ return; @@ -377,7 +377,7 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti [eventAttributes setValuesForKeysWithDictionary:@{ CKKSAnalyticsAttributeRecoverableError : @(NO), - CKKSAnalyticsAttributeZoneName : view.zoneName, + CKKSAnalyticsAttributeZoneName : zoneName, CKKSAnalyticsAttributeErrorDomain : error.domain, CKKSAnalyticsAttributeErrorCode : @(error.code) }]; @@ -385,7 +385,9 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti [self logHardFailureForEventNamed:event withAttributes:eventAttributes]; } -- (void)logUnrecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event withAttributes:(NSDictionary *)attributes +- (void)logUnrecoverableError:(NSError*)error + forEvent:(CKKSAnalyticsFailableEvent*)event + withAttributes:(NSDictionary *)attributes { if (error == nil){ return; @@ -414,23 +416,23 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti { [self noteEventNamed:event]; } -- (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event inView:(CKKSKeychainView*)view +- (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event zoneName:(NSString*)zoneName { - [self noteEventNamed:[NSString stringWithFormat:@"%@-%@", view.zoneName, event]]; + [self noteEventNamed:[NSString stringWithFormat:@"%@-%@", zoneName, event]]; } -- (NSDate*)dateOfLastSuccessForEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view +- (NSDate*)dateOfLastSuccessForEvent:(CKKSAnalyticsFailableEvent*)event zoneName:(NSString*)zoneName { - return [self datePropertyForKey:[NSString stringWithFormat:@"last_success_%@-%@", view.zoneName, event]]; + return [self datePropertyForKey:[NSString stringWithFormat:@"last_success_%@-%@", zoneName, event]]; } -- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key inView:(CKKSKeychainView *)view +- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key zoneName:(NSString*)zoneName { - [self setDateProperty:date forKey:[NSString stringWithFormat:@"%@-%@", key, view.zoneName]]; + [self setDateProperty:date forKey:[NSString stringWithFormat:@"%@-%@", key, zoneName]]; } -- (NSDate *)datePropertyForKey:(NSString *)key inView:(CKKSKeychainView *)view +- (NSDate *)datePropertyForKey:(NSString *)key zoneName:(NSString*)zoneName { - return [self datePropertyForKey:[NSString stringWithFormat:@"%@-%@", key, view.zoneName]]; + return [self datePropertyForKey:[NSString stringWithFormat:@"%@-%@", key, zoneName]]; } @end diff --git a/keychain/ckks/CKKSCheckKeyHierarchyOperation.h b/keychain/ckks/CKKSCheckKeyHierarchyOperation.h new file mode 100644 index 00000000..0ed27699 --- /dev/null +++ b/keychain/ckks/CKKSCheckKeyHierarchyOperation.h @@ -0,0 +1,23 @@ + +#import + +#if OCTAGON + +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSCheckKeyHierarchyOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSCheckKeyHierarchyOperation.m b/keychain/ckks/CKKSCheckKeyHierarchyOperation.m new file mode 100644 index 00000000..874969c0 --- /dev/null +++ b/keychain/ckks/CKKSCheckKeyHierarchyOperation.m @@ -0,0 +1,198 @@ + +#if OCTAGON + +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKSCheckKeyHierarchyOperation.h" +#import "keychain/ckks/CKKSMirrorEntry.h" +#import "keychain/ot/OTDefines.h" +#import "utilities/SecTrace.h" + +@implementation CKKSCheckKeyHierarchyOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if(self = [super init]) { + _deps = dependencies; + + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)main { + NSArray* currentTrustStates = [self.deps currentTrustStates]; + + __block CKKSCurrentKeySet* set = nil; + + [self.deps.databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ + set = [CKKSCurrentKeySet loadForZone:self.deps.zoneID]; + }]; + + // Drop off the sql queue: we can do the rest of this function with what we've already loaded + + if(set.error && !([set.error.domain isEqual: @"securityd"] && set.error.code == errSecItemNotFound)) { + ckkserror("ckkskey", self.deps.zoneID, "Error examining existing key hierarchy: %@", set.error); + } + + if(!set.currentTLKPointer && !set.currentClassAPointer && !set.currentClassCPointer) { + ckkserror("ckkskey", self.deps.zoneID, "Error examining existing key hierarchy (missing all CKPs, likely no hierarchy exists): %@", set); + self.nextState = SecCKKSZoneKeyStateWaitForTLKCreation; + return; + } + + // Check keyset + if(!set.tlk || !set.classA || !set.classC) { + ckkserror("ckkskey", self.deps.zoneID, "Error examining existing key hierarchy (missing at least one key): %@", set); + self.error = set.error; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + + NSError* localerror = nil; + bool probablyOkIfUnlocked = false; + + // keychain being locked is not a fatal error here + [set.tlk loadKeyMaterialFromKeychain:&localerror]; + if(localerror && ![self.deps.lockStateTracker isLockedError:localerror]) { + ckkserror("ckkskey", self.deps.zoneID, "Error loading TLK(%@): %@", set.tlk, localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } else if(localerror) { + ckkserror("ckkskey", self.deps.zoneID, "Soft error loading TLK(%@), maybe locked: %@", set.tlk, localerror); + probablyOkIfUnlocked = true; + } + localerror = nil; + + // keychain being locked is not a fatal error here + [set.classA loadKeyMaterialFromKeychain:&localerror]; + if(localerror && ![self.deps.lockStateTracker isLockedError:localerror]) { + ckkserror("ckkskey", self.deps.zoneID, "Error loading classA key(%@): %@", set.classA, localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } else if(localerror) { + ckkserror("ckkskey", self.deps.zoneID, "Soft error loading classA key(%@), maybe locked: %@", set.classA, localerror); + probablyOkIfUnlocked = true; + } + localerror = nil; + + // keychain being locked is a fatal error here, since this is class C + [set.classC loadKeyMaterialFromKeychain:&localerror]; + if(localerror) { + ckkserror("ckkskey", self.deps.zoneID, "Error loading classC(%@): %@", set.classC, localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + + // Check that the classA and classC keys point to the current TLK + if(![set.classA.parentKeyUUID isEqualToString: set.tlk.uuid]) { + localerror = [NSError errorWithDomain:CKKSServerExtensionErrorDomain + code:CKKSServerUnexpectedSyncKeyInChain + userInfo:@{ + NSLocalizedDescriptionKey: @"Current class A key does not wrap to current TLK", + }]; + ckkserror("ckkskey", self.deps.zoneID, "Key hierarchy unhealthy: %@", localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + if(![set.classC.parentKeyUUID isEqualToString: set.tlk.uuid]) { + localerror = [NSError errorWithDomain:CKKSServerExtensionErrorDomain + code:CKKSServerUnexpectedSyncKeyInChain + userInfo:@{ + NSLocalizedDescriptionKey: @"Current class C key does not wrap to current TLK", + }]; + ckkserror("ckkskey", self.deps.zoneID, "Key hierarchy unhealthy: %@", localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + + // Now that we're pretty sure we have the keys, are they shared appropriately? + // We need trust in order to proceed here + if(currentTrustStates.count == 0u) { + ckkserror("ckkskey", self.deps.zoneID, "Can't check TLKShares due to missing trust states"); + [self.deps provideKeySet:set]; + self.nextState = SecCKKSZoneKeyStateLoseTrust; + return; + } + + // If we've reached this point, we have a workable keyset. Let's provide it to all waiters. + [self.deps provideKeySet:set]; + + if(probablyOkIfUnlocked) { + ckkserror("ckkskey", self.deps.zoneID, "Can't check TLKShares due to lock state"); + [self.deps provideKeySet:set]; + self.nextState = SecCKKSZoneKeyStateReadyPendingUnlock; + return; + } + + // Check that every trusted peer has at least one TLK share + // If any trust state check works, don't error out + bool anyTrustStateSucceeded = false; + for(CKKSPeerProviderState* trustState in currentTrustStates) { + NSSet>* missingShares = [trustState findPeersMissingTLKSharesFor:set + error:&localerror]; + + if(localerror && [self.deps.lockStateTracker isLockedError:localerror]) { + ckkserror("ckkskey", self.deps.zoneID, "Couldn't find missing TLK shares due to lock state: %@", localerror); + continue; + + } else if(([localerror.domain isEqualToString:TrustedPeersHelperErrorDomain] && localerror.code == TrustedPeersHelperErrorNoPreparedIdentity) || + ([localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSLackingTrust) || + ([localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSNoPeersAvailable)) { + ckkserror("ckkskey", self.deps.zoneID, "Couldn't find missing TLK shares due some trust issue: %@", localerror); + + if(trustState.essential) { + ckkserror("ckkskey", self.deps.zoneID, "Trust state is considered essential; entering waitfortrust: %@", trustState); + + // Octagon can reinform us when it thinks we should start again + self.nextState = SecCKKSZoneKeyStateLoseTrust; + + return; + } else { + ckkserror("ckkskey", self.deps.zoneID, "Peer provider is considered nonessential; ignoring error: %@", trustState); + continue; + } + + } else if(localerror) { + ckkserror("ckkskey", self.deps.zoneID, "Error finding missing TLK shares: %@", localerror); + continue; + } + + if(!missingShares || missingShares.count != 0u) { + ckksnotice("ckksshare", self.deps.zoneID, "TLK (%@) is not shared correctly for trust state %@, but we believe AKS is locked", set.tlk, trustState.peerProviderID); + + self.error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSMissingTLKShare + description:[NSString stringWithFormat:@"Missing shares for %lu peers", (unsigned long)missingShares.count]]; + self.nextState = SecCKKSZoneKeyStateHealTLKShares; + return; + } else { + ckksnotice("ckksshare", self.deps.zoneID, "TLK (%@) is shared correctly for trust state %@", set.tlk, trustState.peerProviderID); + } + + anyTrustStateSucceeded |= true; + } + + if(!anyTrustStateSucceeded) { + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateError; + + return; + } + + // Got to the bottom? Cool! All keys are present and accounted for. + self.nextState = SecCKKSZoneKeyStateReady; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSConstants.m b/keychain/ckks/CKKSConstants.m index f680d81b..60c3ce96 100644 --- a/keychain/ckks/CKKSConstants.m +++ b/keychain/ckks/CKKSConstants.m @@ -16,6 +16,7 @@ CKKSItemState* const SecCKKSStateInFlight = (CKKSItemState*) @"inflight"; CKKSItemState* const SecCKKSStateReencrypt = (CKKSItemState*) @"reencrypt"; CKKSItemState* const SecCKKSStateError = (CKKSItemState*) @"error"; CKKSItemState* const SecCKKSStateDeleted = (CKKSItemState*) @"deleted"; +CKKSItemState* const SecCKKSStateMismatchedView = (CKKSItemState*) @"mismatched_view"; CKKSProcessedState* const SecCKKSProcessedStateLocal = (CKKSProcessedState*) @"local"; CKKSProcessedState* const SecCKKSProcessedStateRemote = (CKKSProcessedState*) @"remote"; @@ -87,21 +88,27 @@ NSString* const SecCKRecordManifestLeafType = @"manifest_leaf"; NSString* const SecCKRecordManifestLeafDERKey = @"der"; NSString* const SecCKRecordManifestLeafDigestKey = @"digest"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForCloudKitAccountStatus = (CKKSZoneKeyState*)@"wait_for_ck_account_status"; + CKKSZoneKeyState* const SecCKKSZoneKeyStateReady = (CKKSZoneKeyState*) @"ready"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateBecomeReady = (CKKSZoneKeyState*) @"become_ready"; CKKSZoneKeyState* const SecCKKSZoneKeyStateReadyPendingUnlock = (CKKSZoneKeyState*) @"readypendingunlock"; CKKSZoneKeyState* const SecCKKSZoneKeyStateError = (CKKSZoneKeyState*) @"error"; -CKKSZoneKeyState* const SecCKKSZoneKeyStateCancelled = (CKKSZoneKeyState*) @"cancelled"; CKKSZoneKeyState* const SecCKKSZoneKeyStateInitializing = (CKKSZoneKeyState*) @"initializing"; CKKSZoneKeyState* const SecCKKSZoneKeyStateInitialized = (CKKSZoneKeyState*) @"initialized"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateBeginFetch = (CKKSZoneKeyState*) @"begin_fetch"; CKKSZoneKeyState* const SecCKKSZoneKeyStateFetch = (CKKSZoneKeyState*) @"fetching"; CKKSZoneKeyState* const SecCKKSZoneKeyStateFetchComplete = (CKKSZoneKeyState*) @"fetchcomplete"; CKKSZoneKeyState* const SecCKKSZoneKeyStateNeedFullRefetch = (CKKSZoneKeyState*) @"needrefetch"; + +CKKSZoneKeyState* const SecCKKSZoneKeyStateTLKMissing = (CKKSZoneKeyState*) @"tlkmissing"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLK = (CKKSZoneKeyState*) @"waitfortlk"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLKCreation = (CKKSZoneKeyState*) @"waitfortlkcreation"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLKUpload = (CKKSZoneKeyState*) @"waitfortlkupload"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForUnlock = (CKKSZoneKeyState*) @"waitforunlock"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateLoseTrust = (CKKSZoneKeyState*) @"lose_trust"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTrust = (CKKSZoneKeyState*) @"waitfortrust"; CKKSZoneKeyState* const SecCKKSZoneKeyStateUnhealthy = (CKKSZoneKeyState*) @"unhealthy"; CKKSZoneKeyState* const SecCKKSZoneKeyStateBadCurrentPointers = (CKKSZoneKeyState*) @"badcurrentpointers"; @@ -113,7 +120,7 @@ CKKSZoneKeyState* const SecCKKSZoneKeyStateResettingZone = (CKKSZoneKeyState*) @ CKKSZoneKeyState* const SecCKKSZoneKeyStateResettingLocalData = (CKKSZoneKeyState*) @"resetlocal"; CKKSZoneKeyState* const SecCKKSZoneKeyStateLoggedOut = (CKKSZoneKeyState*) @"loggedout"; CKKSZoneKeyState* const SecCKKSZoneKeyStateZoneCreationFailed = (CKKSZoneKeyState*) @"zonecreationfailed"; -CKKSZoneKeyState* const SecCKKSZoneKeyStateProcess = (CKKSZoneKeyState*) @"process"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateProcess = (CKKSZoneKeyState*) @"process_key_hierarchy"; NSString* const CKKSErrorDomain = @"CKKSErrorDomain"; NSString* const CKKSServerExtensionErrorDomain = @"CKKSServerExtensionErrorDomain"; diff --git a/keychain/ckks/CKKSControl.h b/keychain/ckks/CKKSControl.h index 7a071d0a..92ddf330 100644 --- a/keychain/ckks/CKKSControl.h +++ b/keychain/ckks/CKKSControl.h @@ -34,6 +34,7 @@ typedef NS_ENUM(NSUInteger, CKKSKnownBadState) { CKKSKnownStateTLKsMissing = 1, // CKKS doesn't have the TLKs: your operation will likely not succeed CKKSKnownStateWaitForUnlock = 2, // CKKS has some important things to do, but the device is locked. Your operation will likely not succeed CKKSKnownStateWaitForOctagon = 3, // CKKS has important things to do, but Octagon hasn't done them yet. Your operation will likely not succeed + CKKSKnownStateNoCloudKitAccount = 4, // The device isn't signed into CloudKit. Your operation will likely not succeed }; @interface CKKSControl : NSObject @@ -49,6 +50,7 @@ typedef NS_ENUM(NSUInteger, CKKSKnownBadState) { reply:(void (^)(NSArray* _Nullable result, NSError* _Nullable error))reply; - (void)rpcResetLocal:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; - (void)rpcResetCloudKit:(NSString* _Nullable)viewName reason:(NSString *)reason reply:(void (^)(NSError* _Nullable error))reply; +- (void)rpcResyncLocal:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; - (void)rpcResync:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; - (void)rpcFetchAndProcessChanges:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; - (void)rpcFetchAndProcessClassAChanges:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; diff --git a/keychain/ckks/CKKSControl.m b/keychain/ckks/CKKSControl.m index f4d75de7..876dc631 100644 --- a/keychain/ckks/CKKSControl.m +++ b/keychain/ckks/CKKSControl.m @@ -31,8 +31,7 @@ #import "keychain/ckks/CKKSControl.h" #import "keychain/ckks/CKKSControlProtocol.h" #import "keychain/ckks/CKKSControlServer.h" - -#include +#import "utilities/debugging.h" @interface CKKSControl () @property (readwrite,assign) BOOL synchronous; @@ -49,6 +48,10 @@ return self; } +- (void)dealloc { + [self.connection invalidate]; +} + - (id)objectProxyWithErrorHandler:(void(^)(NSError * _Nonnull error))failureHandler { if (self.synchronous) { @@ -78,47 +81,96 @@ - (void)rpcResetLocal:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a local reset for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcResetLocal:viewName reply:^(NSError* error){ + if(error) { + secnotice("ckkscontrol", "Local reset finished with error: %@", error); + } else { + secnotice("ckkscontrol", "Local reset finished successfully"); + } reply(error); }]; } - (void)rpcResetCloudKit:(NSString*)viewName reason:(NSString *)reason reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a CloudKit reset for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcResetCloudKit:viewName reason:reason reply:^(NSError* error){ + if(error) { + secnotice("ckkscontrol", "CloudKit reset finished with error: %@", error); + } else { + secnotice("ckkscontrol", "CloudKit reset finished successfully"); + } reply(error); }]; } - +- (void)rpcResyncLocal:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply +{ + secnotice("ckkscontrol", "Requesting a local resync for view %@", viewName); + [[self objectProxyWithErrorHandler:^(NSError* error) { + reply(error); + }] rpcResyncLocal:viewName reply:^(NSError* error){ + if(error) { + secnotice("ckkscontrol", "Local resync finished with error: %@", error); + } else { + secnotice("ckkscontrol", "Local resync finished successfully"); + } + reply(error); + }]; +} - (void)rpcResync:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a resync for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcResync:viewName reply:^(NSError* error){ + if(error) { + secnotice("ckkscontrol", "Resync finished with error: %@", error); + } else { + secnotice("ckkscontrol", "Resync finished successfully"); + } reply(error); }]; } - (void)rpcFetchAndProcessChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a fetch for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcFetchAndProcessChanges:viewName reply:^(NSError* error){ + if(error) { + secnotice("ckkscontrol", "Fetch(classA) finished with error: %@", error); + } else { + secnotice("ckkscontrol", "Fetch(classA) finished successfully"); + } reply(error); }]; } - (void)rpcFetchAndProcessClassAChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a fetch(classA) for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcFetchAndProcessClassAChanges:viewName reply:^(NSError* error){ + if(error) { + secnotice("ckkscontrol", "Fetch finished with error: %@", error); + } else { + secnotice("ckkscontrol", "Fetch finished successfully"); + } reply(error); }]; } - (void)rpcPushOutgoingChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a push for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcPushOutgoingChanges:viewName reply:^(NSError* error){ + if(error) { + secnotice("ckkscontrol", "Push finished with error: %@", error); + } else { + secnotice("ckkscontrol", "Push finished successfully"); + } reply(error); }]; } @@ -174,6 +226,7 @@ bool tlkMissing = false; bool waitForUnlock = false; bool waitForOctagon = false; + bool noAccount = false; CKKSKnownBadState response = CKKSKnownStatePossiblyGood; @@ -194,15 +247,21 @@ } if([keystate isEqualToString:@"waitfortlkcreation"] || - [keystate isEqualToString:@"waitfortlkupload"]) { + [keystate isEqualToString:@"waitfortlkupload"] || + [keystate isEqualToString:@"waitfortrust"]) { waitForOctagon = true; } + + if([keystate isEqualToString:@"loggedout"]) { + noAccount = true; + } } - response = (tlkMissing ? CKKSKnownStateTLKsMissing : - (waitForUnlock ? CKKSKnownStateWaitForUnlock : - (waitForOctagon ? CKKSKnownStateWaitForOctagon : - CKKSKnownStatePossiblyGood))); + response = (noAccount ? CKKSKnownStateNoCloudKitAccount : + (tlkMissing ? CKKSKnownStateTLKsMissing : + (waitForUnlock ? CKKSKnownStateWaitForUnlock : + (waitForOctagon ? CKKSKnownStateWaitForOctagon : + CKKSKnownStatePossiblyGood)))); reply(response); }]; diff --git a/keychain/ckks/CKKSControlProtocol.h b/keychain/ckks/CKKSControlProtocol.h index d96fae7b..1775d890 100644 --- a/keychain/ckks/CKKSControlProtocol.h +++ b/keychain/ckks/CKKSControlProtocol.h @@ -25,7 +25,7 @@ @protocol CKKSControlProtocol - (void)performanceCounters:(void(^)(NSDictionary *))reply; -- (void)rpcResetLocal: (NSString*)viewName reply: (void(^)(NSError* result)) reply; +- (void)rpcResetLocal: (NSString*)viewName reply: (void(^)(NSError* result)) reply; /** * Reset CloudKit zone with a caller provided reason, the reason will be logged in the operation group diff --git a/keychain/ckks/CKKSControlProtocol.m b/keychain/ckks/CKKSControlProtocol.m index 648b8253..4109183b 100644 --- a/keychain/ckks/CKKSControlProtocol.m +++ b/keychain/ckks/CKKSControlProtocol.m @@ -28,8 +28,10 @@ #if OCTAGON #import #import -#import +#import +#import "utilities/debugging.h" #include +#import // Weak-link CloudKit, until we can get ckksctl out of base system static void *cloudKit = NULL; @@ -67,48 +69,26 @@ NSXPCInterface* CKKSSetupControlProtocol(NSXPCInterface* interface) { __typeof(CKAcceptableValueClasses) *soft_CKAcceptableValueClasses = NULL; getCloudKitSymbol((void **)&soft_CKAcceptableValueClasses, "CKAcceptableValueClasses"); errClasses = [NSMutableSet setWithSet:soft_CKAcceptableValueClasses()]; - - char *classes[] = { - "CKPrettyError", - "CKRecordID", - "NSArray", - "NSData", - "NSDate", - "NSDictionary", - "NSError", - "NSNull", - "NSNumber", - "NSOrderedSet", - "NSSet", - "NSString", - "NSURL", - }; - - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) { - [errClasses addObject:cls]; - } - } + [errClasses unionSet:[SecXPCHelper safeErrorClasses]]; }); @try { - [interface setClasses:errClasses forSelector:@selector(rpcResetCloudKit:reason:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcResetLocal:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcResetCloudKit:reason:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcResync:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(rpcStatus:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcResyncLocal:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcStatus:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcFastStatus:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcFetchAndProcessChanges:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcFetchAndProcessClassAChanges:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcPushOutgoingChanges:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcGetCKDeviceIDWithReply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcCKMetric:attributes:reply:) argumentIndex:0 ofReply:YES]; } @catch(NSException* e) { secerror("CKKSSetupControlProtocol failed, continuing, but you might crash later: %@", e); -#if DEBUG @throw e; -#endif } #endif diff --git a/keychain/ckks/CKKSControlServer.m b/keychain/ckks/CKKSControlServer.m index fecffc4c..a76d72ee 100644 --- a/keychain/ckks/CKKSControlServer.m +++ b/keychain/ckks/CKKSControlServer.m @@ -16,14 +16,14 @@ #if OCTAGON NSNumber *num = [newConnection valueForEntitlement:(__bridge NSString *)kSecEntitlementPrivateCKKS]; if (![num isKindOfClass:[NSNumber class]] || ![num boolValue]) { - secerror("ckks: Client pid: %d doesn't have entitlement: %@", + ckkserror_global("ckks", "Client pid: %d doesn't have entitlement: %@", [newConnection processIdentifier], kSecEntitlementPrivateCKKS); return NO; } // In the future, we should consider vending a proxy object that can return a nicer error. if (!SecCKKSIsEnabled()) { - secerror("ckks: Client pid: %d attempted to use CKKS, but CKKS is not enabled.", + ckkserror_global("ckks", "Client pid: %d attempted to use CKKS, but CKKS is not enabled.", newConnection.processIdentifier); return NO; } diff --git a/keychain/ckks/CKKSCreateCKZoneOperation.h b/keychain/ckks/CKKSCreateCKZoneOperation.h new file mode 100644 index 00000000..8e9473f2 --- /dev/null +++ b/keychain/ckks/CKKSCreateCKZoneOperation.h @@ -0,0 +1,23 @@ + +#import + +#if OCTAGON + +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSCreateCKZoneOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSCreateCKZoneOperation.m b/keychain/ckks/CKKSCreateCKZoneOperation.m new file mode 100644 index 00000000..3edc2c31 --- /dev/null +++ b/keychain/ckks/CKKSCreateCKZoneOperation.m @@ -0,0 +1,121 @@ +#if OCTAGON + +#import +#import + +#import "keychain/ckks/CKKSCreateCKZoneOperation.h" +#import "keychain/ckks/CKKSZoneStateEntry.h" +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ot/ObjCImprovements.h" +#import "keychain/ot/OTDefines.h" + +@implementation CKKSCreateCKZoneOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if(self = [super init]) { + _deps = dependencies; + + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + __block CKKSZoneStateEntry* ckseOriginal = nil; + [self.deps.databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ + ckseOriginal = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName]; + }]; + + if(ckseOriginal.ckzonecreated && ckseOriginal.ckzonesubscribed) { + ckksinfo("ckkskey", self.deps.zoneID, "Zone is already created and subscribed"); + self.nextState = self.intendedState; + return; + } + + ckksnotice("ckkszone", self.deps.zoneID, "Asking to create and subscribe to CloudKit zone '%@'", self.deps.zoneID.zoneName); + CKRecordZone* zone = [[CKRecordZone alloc] initWithZoneID:self.deps.zoneID]; + CKKSZoneModifyOperations* zoneOps = [self.deps.zoneModifier createZone:zone]; + + WEAKIFY(self); + + CKKSResultOperation* handleModificationsOperation = [CKKSResultOperation named:@"handle-modification" withBlock:^{ + STRONGIFY(self); + BOOL zoneCreated = NO; + BOOL zoneSubscribed = NO; + if([zoneOps.savedRecordZones containsObject:zone]) { + ckksinfo("ckkszone", self.deps.zoneID, "Successfully created '%@'", self.deps.zoneID); + zoneCreated = YES; + } else { + ckkserror("ckkszone", self.deps.zoneID, "Failed to create '%@'", self.deps.zoneID); + } + + bool createdSubscription = false; + for(CKSubscription* subscription in zoneOps.savedSubscriptions) { + if([subscription.subscriptionID isEqual:[@"zone:" stringByAppendingString: self.deps.zoneID.zoneName]]) { + zoneSubscribed = true; + break; + } + } + + if(createdSubscription) { + ckksinfo("ckkszone", self.deps.zoneID, "Successfully subscribed '%@'", self.deps.zoneID); + zoneSubscribed = YES; + } else { + ckkserror("ckkszone", self.deps.zoneID, "Failed to subscribe to '%@'", self.deps.zoneID); + } + + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + ckksnotice("ckkszone", self.deps.zoneID, "Zone setup progress: created:%d %@ subscribed:%d %@", + zoneCreated, + zoneOps.zoneModificationOperation.error, + zoneSubscribed, + zoneOps.zoneSubscriptionOperation.error); + + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName]; + ckse.ckzonecreated = zoneCreated; + ckse.ckzonesubscribed = zoneSubscribed; + + // Although, if the zone subscribed error says there's no zone, mark down that there's no zone + if(zoneOps.zoneSubscriptionOperation.error && + [zoneOps.zoneSubscriptionOperation.error.domain isEqualToString:CKErrorDomain] && zoneOps.zoneSubscriptionOperation.error.code == CKErrorPartialFailure) { + NSError* subscriptionError = zoneOps.zoneSubscriptionOperation.error.userInfo[CKPartialErrorsByItemIDKey][self.deps.zoneID]; + if(subscriptionError && [subscriptionError.domain isEqualToString:CKErrorDomain] && subscriptionError.code == CKErrorZoneNotFound) { + + ckkserror("ckks", self.deps.zoneID, "zone subscription error appears to say the zone doesn't exist, fixing status: %@", zoneOps.zoneSubscriptionOperation.error); + ckse.ckzonecreated = false; + } + } + + [ckse saveToDatabase:&error]; + if(error) { + ckkserror("ckks", self.deps.zoneID, "couldn't save zone creation status for %@: %@", self.deps.zoneID, error); + } + + if(!zoneCreated || !zoneSubscribed) { + // Go into 'zonecreationfailed' + self.nextState = SecCKKSZoneKeyStateZoneCreationFailed; + self.error = zoneOps.zoneModificationOperation.error ?: zoneOps.zoneSubscriptionOperation.error; + } else { + self.nextState = self.intendedState; + } + + return CKKSDatabaseTransactionCommit; + }]; + }]; + + [handleModificationsOperation addNullableDependency:zoneOps.zoneModificationOperation]; + [handleModificationsOperation addNullableDependency:zoneOps.zoneSubscriptionOperation]; + [self runBeforeGroupFinished:handleModificationsOperation]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSCurrentItemPointer.h b/keychain/ckks/CKKSCurrentItemPointer.h index 8d9c4d5d..1c960e49 100644 --- a/keychain/ckks/CKKSCurrentItemPointer.h +++ b/keychain/ckks/CKKSCurrentItemPointer.h @@ -56,6 +56,9 @@ NS_ASSUME_NONNULL_BEGIN + (bool)deleteAll:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (NSArray*)allInZone:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error; ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSCurrentItemPointer.m b/keychain/ckks/CKKSCurrentItemPointer.m index cf03a4a3..f2abb13b 100644 --- a/keychain/ckks/CKKSCurrentItemPointer.m +++ b/keychain/ckks/CKKSCurrentItemPointer.m @@ -163,6 +163,90 @@ encodedCKRecord:row[@"ckrecord"].asBase64DecodedData]; } ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error +{ + if(resync) { + NSError* ciperror = nil; + CKKSCurrentItemPointer* localcip = [CKKSCurrentItemPointer tryFromDatabase:record.recordID.recordName state:SecCKKSProcessedStateLocal zoneID:record.recordID.zoneID error:&ciperror]; + CKKSCurrentItemPointer* remotecip = [CKKSCurrentItemPointer tryFromDatabase:record.recordID.recordName state:SecCKKSProcessedStateRemote zoneID:record.recordID.zoneID error:&ciperror]; + if(ciperror) { + ckkserror("ckksresync", record.recordID.zoneID, "error loading cip: %@", ciperror); + } + if(!(localcip || remotecip)) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: No current item pointer matching resynced CloudKit record: %@", record); + } else if(! ([localcip matchesCKRecord:record] || [remotecip matchesCKRecord:record]) ) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: Local current item pointer doesn't match resynced CloudKit record(s): %@ %@ %@", localcip, remotecip, record); + } else { + ckksnotice("ckksresync", record.recordID.zoneID, "Already know about this current item pointer, skipping update: %@", record); + return YES; + } + } + + NSError* localerror = nil; + CKKSCurrentItemPointer* cip = [[CKKSCurrentItemPointer alloc] initWithCKRecord:record]; + cip.state = SecCKKSProcessedStateRemote; + + bool saved = [cip saveToDatabase:&localerror]; + if(!saved || localerror) { + ckkserror("currentitem", record.recordID.zoneID, "Couldn't save current item pointer to database: %@: %@ %@", cip, localerror, record); + if(error) { + *error = localerror; + } + return NO; + } + return YES; +} + ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error +{ + NSError* localerror = nil; + ckksinfo("currentitem", recordID.zoneID, "CloudKit notification: deleted current item pointer(%@): %@", SecCKRecordCurrentItemType, recordID); + + CKKSCurrentItemPointer* remote = [CKKSCurrentItemPointer tryFromDatabase:[recordID recordName] state:SecCKKSProcessedStateRemote zoneID:recordID.zoneID error:&localerror]; + if(localerror) { + if(error) { + *error = localerror; + } + + ckkserror("currentitem", recordID.zoneID, "Failed to find remote CKKSCurrentItemPointer to delete %@: %@", recordID, localerror); + return NO; + } + + [remote deleteFromDatabase:&localerror]; + if(localerror) { + if(error) { + *error = localerror; + } + ckkserror("currentitem", recordID.zoneID, "Failed to delete remote CKKSCurrentItemPointer %@: %@", recordID, localerror); + return NO; + } + + CKKSCurrentItemPointer* local = [CKKSCurrentItemPointer tryFromDatabase:[recordID recordName] state:SecCKKSProcessedStateLocal zoneID:recordID.zoneID error:&localerror]; + if(localerror) { + if(error) { + *error = localerror; + } + ckkserror("currentitem", recordID.zoneID, "Failed to find local CKKSCurrentItemPointer %@: %@", recordID, localerror); + return NO; + } + [local deleteFromDatabase:&localerror]; + if(localerror) { + if(error) { + *error = localerror; + } + ckkserror("currentitem", recordID.zoneID, "Failed to delete local CKKSCurrentItemPointer %@: %@", recordID, localerror); + return NO; + } + + ckksinfo("currentitem", recordID.zoneID, "CKKSCurrentItemPointer was deleted: %@ error: %@", recordID, localerror); + + if(error && localerror) { + *error = localerror; + } + + return (localerror == nil); +} + @end #endif // OCTAGON diff --git a/keychain/ckks/CKKSCurrentKeyPointer.h b/keychain/ckks/CKKSCurrentKeyPointer.h index 7f8cc8cf..4dca3831 100644 --- a/keychain/ckks/CKKSCurrentKeyPointer.h +++ b/keychain/ckks/CKKSCurrentKeyPointer.h @@ -43,17 +43,21 @@ NS_ASSUME_NONNULL_BEGIN zoneID:(CKRecordZoneID*)zoneID encodedCKRecord:(NSData* _Nullable)encodedrecord; -+ (instancetype)fromDatabase:(CKKSKeyClass*)keyclass zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; -+ (instancetype)tryFromDatabase:(CKKSKeyClass*)keyclass zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; ++ (instancetype _Nullable)fromDatabase:(CKKSKeyClass*)keyclass zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; ++ (instancetype _Nullable)tryFromDatabase:(CKKSKeyClass*)keyclass zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; -+ (instancetype)forKeyClass:(CKKSKeyClass*)keyclass - withKeyUUID:(NSString*)keyUUID - zoneID:(CKRecordZoneID*)zoneID - error:(NSError* __autoreleasing*)error; ++ (instancetype _Nullable)forKeyClass:(CKKSKeyClass*)keyclass + withKeyUUID:(NSString*)keyUUID + zoneID:(CKRecordZoneID*)zoneID + error:(NSError* __autoreleasing*)error; + (NSArray*)all:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (bool)deleteAll:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; ++ (BOOL)intransactionRecordChanged:(CKRecord*)record + resync:(BOOL)resync + flagHandler:(id)flagHandler + error:(NSError**)error; @end @interface CKKSCurrentKeySet : NSObject diff --git a/keychain/ckks/CKKSCurrentKeyPointer.m b/keychain/ckks/CKKSCurrentKeyPointer.m index 78a935ad..087cc753 100644 --- a/keychain/ckks/CKKSCurrentKeyPointer.m +++ b/keychain/ckks/CKKSCurrentKeyPointer.m @@ -25,6 +25,7 @@ #if OCTAGON +#import "keychain/ckks/CKKSStates.h" #import "keychain/categories/NSError+UsefulConstructors.h" @implementation CKKSCurrentKeyPointer @@ -39,7 +40,7 @@ _currentKeyUUID = currentKeyUUID; if(self.currentKeyUUID == nil) { - secerror("ckkscurrentkey: created a CKKSCurrentKey with a nil currentKeyUUID. Why?"); + ckkserror_global("currentkey", "created a CKKSCurrentKey with a nil currentKeyUUID. Why?"); } } return self; @@ -126,21 +127,24 @@ self.currentKeyUUID = [record[SecCKRecordParentKeyRefKey] recordID].recordName; if(self.currentKeyUUID == nil) { - secerror("ckkscurrentkey: No current key UUID in record! How/why? %@", record); + ckkserror_global("currentkey", "No current key UUID in record! How/why? %@", record); } } #pragma mark - Load from database -+ (instancetype) fromDatabase: (CKKSKeyClass*) keyclass zoneID:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { ++ (instancetype _Nullable)fromDatabase:(CKKSKeyClass*)keyclass zoneID:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error +{ return [self fromDatabaseWhere: @{@"keyclass": keyclass, @"ckzone":zoneID.zoneName} error: error]; } -+ (instancetype) tryFromDatabase: (CKKSKeyClass*) keyclass zoneID:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { ++ (instancetype _Nullable)tryFromDatabase:(CKKSKeyClass*)keyclass zoneID:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error +{ return [self tryFromDatabaseWhere: @{@"keyclass": keyclass, @"ckzone":zoneID.zoneName} error: error]; } -+ (instancetype) forKeyClass: (CKKSKeyClass*) keyclass withKeyUUID: (NSString*) keyUUID zoneID:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { ++ (instancetype _Nullable)forKeyClass:(CKKSKeyClass*)keyclass withKeyUUID:(NSString*)keyUUID zoneID:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error +{ NSError* localerror = nil; CKKSCurrentKeyPointer* current = [self tryFromDatabase: keyclass zoneID:zoneID error: &localerror]; if(localerror) { @@ -202,6 +206,52 @@ encodedCKRecord:row[@"ckrecord"].asBase64DecodedData]; } ++ (BOOL)intransactionRecordChanged:(CKRecord*)record + resync:(BOOL)resync + flagHandler:(id)flagHandler + error:(NSError**)error +{ + // Pull out the old CKP, if it exists + NSError* ckperror = nil; + CKKSCurrentKeyPointer* oldckp = [CKKSCurrentKeyPointer tryFromDatabase:((CKKSKeyClass*)record.recordID.recordName) zoneID:record.recordID.zoneID error:&ckperror]; + if(ckperror) { + ckkserror("ckkskey", record.recordID.zoneID, "error loading ckp: %@", ckperror); + } + + if(resync) { + if(!oldckp) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: No current key pointer matching resynced CloudKit record: %@", record); + } else if(![oldckp matchesCKRecord:record]) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: Local current key pointer doesn't match resynced CloudKit record: %@ %@", oldckp, record); + } else { + ckksnotice("ckksresync", record.recordID.zoneID, "Current key pointer has 'changed', but it matches our local copy: %@", record); + } + } + + NSError* localerror = nil; + CKKSCurrentKeyPointer* currentkey = [[CKKSCurrentKeyPointer alloc] initWithCKRecord:record]; + + bool saved = [currentkey saveToDatabase:&localerror]; + if(!saved || localerror != nil) { + ckkserror("ckkskey", record.recordID.zoneID, "Couldn't save current key pointer to database: %@: %@", currentkey, localerror); + ckksinfo("ckkskey", record.recordID.zoneID, "CKRecord was %@", record); + + if(error) { + *error = localerror; + } + return NO; + } + + if([oldckp matchesCKRecord:record]) { + ckksnotice("ckkskey", record.recordID.zoneID, "Current key pointer modification doesn't change anything interesting; skipping reprocess: %@", record); + } else { + // We've saved a new key in the database; trigger a rekey operation. + [flagHandler _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; + } + + return YES; +} + @end @implementation CKKSCurrentKeySet diff --git a/keychain/ckks/CKKSDeleteCKZoneOperation.h b/keychain/ckks/CKKSDeleteCKZoneOperation.h new file mode 100644 index 00000000..bb7a5402 --- /dev/null +++ b/keychain/ckks/CKKSDeleteCKZoneOperation.h @@ -0,0 +1,22 @@ +#import + +#if OCTAGON + +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSDeleteCKZoneOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSDeleteCKZoneOperation.m b/keychain/ckks/CKKSDeleteCKZoneOperation.m new file mode 100644 index 00000000..e2b5aa79 --- /dev/null +++ b/keychain/ckks/CKKSDeleteCKZoneOperation.m @@ -0,0 +1,101 @@ + + +#if OCTAGON + +#import +#import + +#import "keychain/ckks/CKKSDeleteCKZoneOperation.h" +#import "keychain/ckks/CKKSZoneStateEntry.h" +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ot/ObjCImprovements.h" +#import "keychain/ot/OTDefines.h" + +@implementation CKKSDeleteCKZoneOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if(self = [super init]) { + _deps = dependencies; + + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + + ckksnotice("ckkszone", self.deps.zoneID, "Deleting CloudKit zone '%@'", self.deps.zoneID); + CKKSZoneModifyOperations* zoneOps = [self.deps.zoneModifier deleteZone:self.deps.zoneID]; + + + WEAKIFY(self); + + CKKSResultOperation* handleModificationsOperation = [CKKSResultOperation named:@"handle-modification" withBlock:^{ + STRONGIFY(self); + + bool fatalError = false; + + NSError* operationError = zoneOps.zoneModificationOperation.error; + bool removed = [zoneOps.deletedRecordZoneIDs containsObject:self.deps.zoneID]; + + if(!removed && operationError) { + // Okay, but if this error is either 'ZoneNotFound' or 'UserDeletedZone', that's fine by us: the zone is deleted. + NSDictionary* partialErrors = operationError.userInfo[CKPartialErrorsByItemIDKey]; + if([operationError.domain isEqualToString:CKErrorDomain] && operationError.code == CKErrorPartialFailure && partialErrors) { + for(CKRecordZoneID* errorZoneID in partialErrors.allKeys) { + NSError* errorZone = partialErrors[errorZoneID]; + + if(errorZone && [errorZone.domain isEqualToString:CKErrorDomain] && + (errorZone.code == CKErrorZoneNotFound || errorZone.code == CKErrorUserDeletedZone)) { + ckksnotice("ckkszone", self.deps.zoneID, "Attempted to delete zone %@, but it's already missing. This is okay: %@", errorZoneID, errorZone); + } else { + fatalError = true; + } + } + + } else { + fatalError = true; + } + + ckksnotice("ckkszone", self.deps.zoneID, "deletion of record zone %@ completed with error: %@", self.deps.zoneID, operationError); + + if(fatalError) { + // Early-exit + self.error = operationError; + return; + } + } + + ckksnotice("ckkszone", self.deps.zoneID, "deletion of record zone %@ completed successfully", self.deps.zoneID); + + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName]; + ckse.ckzonecreated = NO; + ckse.ckzonesubscribed = NO; + + [ckse saveToDatabase:&error]; + if(error) { + ckkserror("ckks", self.deps.zoneID, "couldn't save zone creation status for %@: %@", self.deps.zoneID, error); + } + + self.nextState = self.intendedState; + return CKKSDatabaseTransactionCommit; + }]; + }]; + + [handleModificationsOperation addNullableDependency:zoneOps.zoneModificationOperation]; + [handleModificationsOperation addNullableDependency:zoneOps.zoneSubscriptionOperation]; + [self runBeforeGroupFinished:handleModificationsOperation]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSDeviceStateEntry.h b/keychain/ckks/CKKSDeviceStateEntry.h index f542e185..0684278a 100644 --- a/keychain/ckks/CKKSDeviceStateEntry.h +++ b/keychain/ckks/CKKSDeviceStateEntry.h @@ -48,6 +48,8 @@ NS_ASSUME_NONNULL_BEGIN * - We will have receive such records from other devices */ +@class CKKSKeychainViewState; + @interface CKKSDeviceStateEntry : CKKSCKRecordHolder @property NSString* device; @@ -88,6 +90,15 @@ NS_ASSUME_NONNULL_BEGIN currentClassCUUID:(NSString* _Nullable)currentClassCUUID zoneID:(CKRecordZoneID*)zoneID encodedCKRecord:(NSData* _Nullable)encodedrecord; + ++ (CKKSDeviceStateEntry* _Nullable)intransactionCreateDeviceStateForView:(CKKSKeychainViewState*)viewState + accountTracker:(CKKSAccountStateTracker*)accountTracker + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + error:(NSError**)error; + ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error; ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSDeviceStateEntry.m b/keychain/ckks/CKKSDeviceStateEntry.m index 557de53c..1eba8a81 100644 --- a/keychain/ckks/CKKSDeviceStateEntry.m +++ b/keychain/ckks/CKKSDeviceStateEntry.m @@ -104,7 +104,7 @@ case (uint32_t)kSOSCCError: // And, if by some miracle, you end up with -1 as a uint32_t, accept that too return kSOSCCError; default: - secerror("ckks: %d is not an SOSCCStatus?", n); + ckkserror_global("ckks", "%d is not an SOSCCStatus?", n); return kSOSCCError; } } @@ -146,7 +146,7 @@ case (uint32_t)kSOSCCErrorPositive: // Use the magic number return [[OTCliqueStatusWrapper alloc] initWithStatus:CliqueStatusError]; default: - secerror("ckks: %d is not an OTCliqueStatus?", n); + ckkserror_global("ckks", "%d is not an OTCliqueStatus?", n); return [[OTCliqueStatusWrapper alloc] initWithStatus:CliqueStatusError];; } } @@ -406,6 +406,182 @@ ]; } +#pragma mark - CKKS interaction methods + ++ (CKKSDeviceStateEntry* _Nullable)intransactionCreateDeviceStateForView:(CKKSKeychainViewState*)viewState + accountTracker:(CKKSAccountStateTracker*)accountTracker + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + error:(NSError**)error +{ + NSError* localerror = nil; + + CKKSAccountStatus hsa2Status = accountTracker.hsa2iCloudAccountStatus; + + // We must have an HSA2 iCloud account and a CloudKit account to even create one of these + if(hsa2Status != CKKSAccountStatusAvailable || + accountTracker.currentCKAccountInfo.accountStatus != CKAccountStatusAvailable) { + ckkserror("ckksdevice", viewState, "No iCloud account active: %@ hsa2 account:%@", + accountTracker.currentCKAccountInfo, + CKKSAccountStatusToString(hsa2Status)); + localerror = [NSError errorWithDomain:@"securityd" + code:errSecInternalError + userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No active HSA2 iCloud account: %@", accountTracker.currentCKAccountInfo]}]; + if(error) { + *error = localerror; + } + return nil; + } + + NSString* ckdeviceID = accountTracker.ckdeviceID; + if(ckdeviceID == nil) { + ckkserror("ckksdevice", viewState, "No CK device ID available; cannot make device state entry"); + localerror = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNotLoggedIn + userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No CK device ID: %@", accountTracker.currentCKAccountInfo]}]; + if(error) { + *error = localerror; + } + return nil; + } + + CKKSDeviceStateEntry* oldcdse = [CKKSDeviceStateEntry tryFromDatabase:ckdeviceID zoneID:viewState.zoneID error:&localerror]; + if(localerror) { + ckkserror("ckksdevice", viewState, "Couldn't read old CKKSDeviceStateEntry from database: %@", localerror); + if(error) { + *error = localerror; + } + return nil; + } + + // Find out what we think the current keys are + CKKSCurrentKeyPointer* currentTLKPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassTLK zoneID:viewState.zoneID error:&localerror]; + CKKSCurrentKeyPointer* currentClassAPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassA zoneID:viewState.zoneID error:&localerror]; + CKKSCurrentKeyPointer* currentClassCPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassC zoneID:viewState.zoneID error:&localerror]; + if(localerror) { + // Things is broken, but the whole point of this record is to share the brokenness. Continue. + ckkserror("ckksdevice", viewState, "Couldn't read current key pointers from database: %@; proceeding", localerror); + localerror = nil; + } + + CKKSKey* suggestedTLK = currentTLKPointer.currentKeyUUID ? [CKKSKey tryFromDatabase:currentTLKPointer.currentKeyUUID zoneID:viewState.zoneID error:&localerror] : nil; + CKKSKey* suggestedClassAKey = currentClassAPointer.currentKeyUUID ? [CKKSKey tryFromDatabase:currentClassAPointer.currentKeyUUID zoneID:viewState.zoneID error:&localerror] : nil; + CKKSKey* suggestedClassCKey = currentClassCPointer.currentKeyUUID ? [CKKSKey tryFromDatabase:currentClassCPointer.currentKeyUUID zoneID:viewState.zoneID error:&localerror] : nil; + + if(localerror) { + // Things is broken, but the whole point of this record is to share the brokenness. Continue. + ckkserror("ckksdevice", viewState, "Couldn't read keys from database: %@; proceeding", localerror); + localerror = nil; + } + + // Check if we posess the keys in the keychain + [suggestedTLK ensureKeyLoaded:&localerror]; + if(localerror && [lockStateTracker isLockedError:localerror]) { + ckkserror("ckksdevice", viewState, "Device is locked; couldn't read TLK from keychain. Assuming it is present and continuing; error was %@", localerror); + localerror = nil; + } else if(localerror) { + ckkserror("ckksdevice", viewState, "Couldn't read TLK from keychain. We do not have a current TLK. Error was %@", localerror); + suggestedTLK = nil; + } + + [suggestedClassAKey ensureKeyLoaded:&localerror]; + if(localerror && [lockStateTracker isLockedError:localerror]) { + ckkserror("ckksdevice", viewState, "Device is locked; couldn't read ClassA key from keychain. Assuming it is present and continuing; error was %@", localerror); + localerror = nil; + } else if(localerror) { + ckkserror("ckksdevice", viewState, "Couldn't read ClassA key from keychain. We do not have a current ClassA key. Error was %@", localerror); + suggestedClassAKey = nil; + } + + [suggestedClassCKey ensureKeyLoaded:&localerror]; + // class C keys are stored class C, so uh, don't check lock state. + if(localerror) { + ckkserror("ckksdevice", viewState, "Couldn't read ClassC key from keychain. We do not have a current ClassC key. Error was %@", localerror); + suggestedClassCKey = nil; + } + + // We'd like to have the circle peer ID. Give the account state tracker a fighting chance, but not having it is not an error + // But, if the platform doesn't have SOS, don't bother + if(OctagonPlatformSupportsSOS() && [accountTracker.accountCirclePeerIDInitialized wait:500*NSEC_PER_MSEC] != 0 && !accountTracker.accountCirclePeerID) { + ckkserror("ckksdevice", viewState, "No SOS peer ID available"); + } + + // We'd also like the Octagon status + if([accountTracker.octagonInformationInitialized wait:500*NSEC_PER_MSEC] != 0 && !accountTracker.octagonPeerID) { + ckkserror("ckksdevice", viewState, "No octagon peer ID available"); + } + + // Reset the last unlock time to 'day' granularity in UTC + NSCalendar* calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierISO8601]; + calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; + NSDate* lastUnlockDay = lockStateTracker.lastUnlockTime; + lastUnlockDay = lastUnlockDay ? [calendar startOfDayForDate:lastUnlockDay] : nil; + + // We only really want the oldcdse for its encodedCKRecord, so make a new cdse here + CKKSDeviceStateEntry* newcdse = [[CKKSDeviceStateEntry alloc] initForDevice:ckdeviceID + osVersion:SecCKKSHostOSVersion() + lastUnlockTime:lastUnlockDay + octagonPeerID:accountTracker.octagonPeerID + octagonStatus:accountTracker.octagonStatus + circlePeerID:accountTracker.accountCirclePeerID + circleStatus:accountTracker.currentCircleStatus.status + keyState:viewState.zoneCKKSState + currentTLKUUID:suggestedTLK.uuid + currentClassAUUID:suggestedClassAKey.uuid + currentClassCUUID:suggestedClassCKey.uuid + zoneID:viewState.zoneID + encodedCKRecord:oldcdse.encodedCKRecord]; + return newcdse; +} + ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error +{ + if(resync) { + NSError* dserror = nil; + CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry tryFromDatabase:record.recordID.recordName zoneID:record.recordID.zoneID error:&dserror]; + if(dserror) { + ckkserror("ckksresync", record.recordID.zoneID, "error loading cdse: %@", dserror); + } + if(!cdse) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: No current device state entry matching resynced CloudKit record: %@", record); + } else if(![cdse matchesCKRecord:record]) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: Local current device state entry doesn't match resynced CloudKit record(s): %@ %@", cdse, record); + } else { + ckksnotice("ckksresync", record.recordID.zoneID, "Already know about this current item pointer, skipping update: %@", record); + return YES; + } + } + + NSError* localerror = nil; + CKKSDeviceStateEntry* cdse = [[CKKSDeviceStateEntry alloc] initWithCKRecord:record]; + bool saved = [cdse saveToDatabase:&localerror]; + if (!saved || localerror != nil) { + ckkserror("ckksdevice", record.recordID.zoneID, "Failed to save device record to database: %@: %@ %@", cdse, localerror, record); + if(error) { + *error = localerror; + } + return NO; + } + + return YES; +} + ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error +{ + NSError* localerror = nil; + ckksinfo("ckksdevice", recordID.zoneID, "CloudKit notification: deleted device state record(%@): %@", SecCKRecordDeviceStateType, recordID); + + CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry tryFromDatabaseFromCKRecordID:recordID error:&localerror]; + [cdse deleteFromDatabase:&localerror]; + + ckksinfo("ckksdevice", recordID.zoneID, "CKKSCurrentItemPointer(%@) was deleted: %@ error: %@", cdse, recordID, localerror); + + if(error && localerror) { + *error = localerror; + } + + return (localerror == nil); +} + @end #endif diff --git a/keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.m b/keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.m index 9a03e976..7212cf97 100644 --- a/keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.m +++ b/keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.m @@ -144,7 +144,7 @@ if(!self.forceResync) { if (self.changeTokens[clientZoneID]) { options.previousServerChangeToken = self.changeTokens[clientZoneID]; - secnotice("ckksfetch", "Using cached change token for %@: %@", clientZoneID, self.changeTokens[clientZoneID]); + ckksnotice_global("ckksfetch", "Using cached change token for %@: %@", clientZoneID, self.changeTokens[clientZoneID]); } else { options.previousServerChangeToken = clientPreference.changeToken; } @@ -168,7 +168,7 @@ if(self.fetchedZoneIDs.count == 0) { // No clients actually want to fetch right now, so quit self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSNoFetchesRequested description:@"No clients want a fetch right now"]; - secnotice("ckksfetch", "Cancelling fetch: %@", self.error); + ckksnotice_global("ckksfetch", "Cancelling fetch: %@", self.error); return; } @@ -196,7 +196,7 @@ // networkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; //} - secnotice("ckksfetch", "Beginning fetch with discretionary network (%d): %@", (int)networkBehavior, self.allClientOptions); + ckksnotice_global("ckksfetch", "Beginning fetch with discretionary network (%d): %@", (int)networkBehavior, self.allClientOptions); self.fetchRecordZoneChangesOperation = [[self.fetchRecordZoneChangesOperationClass alloc] initWithRecordZoneIDs:self.fetchedZoneIDs configurationsByRecordZoneID:self.allClientOptions]; @@ -204,11 +204,11 @@ self.fetchRecordZoneChangesOperation.configuration.discretionaryNetworkBehavior = networkBehavior; self.fetchRecordZoneChangesOperation.configuration.isCloudKitSupportOperation = YES; self.fetchRecordZoneChangesOperation.group = self.ckoperationGroup; - secnotice("ckksfetch", "Operation group is %@", self.ckoperationGroup); + ckksnotice_global("ckksfetch", "Operation group is %@", self.ckoperationGroup); self.fetchRecordZoneChangesOperation.recordChangedBlock = ^(CKRecord *record) { STRONGIFY(self); - secinfo("ckksfetch", "CloudKit notification: record changed(%@): %@", [record recordType], record); + ckksinfo_global("ckksfetch", "CloudKit notification: record changed(%@): %@", [record recordType], record); // Add this to the modifications, and remove it from the deletions self.modifications[record.recordID] = record; @@ -218,7 +218,7 @@ self.fetchRecordZoneChangesOperation.recordWithIDWasDeletedBlock = ^(CKRecordID *recordID, NSString *recordType) { STRONGIFY(self); - secinfo("ckksfetch", "CloudKit notification: deleted record(%@): %@", recordType, recordID); + ckksinfo_global("ckksfetch", "CloudKit notification: deleted record(%@): %@", recordType, recordID); // Add to the deletions, and remove any pending modifications [self.modifications removeObjectForKey: recordID]; @@ -229,25 +229,25 @@ self.fetchRecordZoneChangesOperation.recordZoneChangeTokensUpdatedBlock = ^(CKRecordZoneID *recordZoneID, CKServerChangeToken *serverChangeToken, NSData *clientChangeTokenData) { STRONGIFY(self); - secinfo("ckksfetch", "Received a new server change token (via block) for %@: %@ %@", recordZoneID, serverChangeToken, clientChangeTokenData); + ckksinfo_global("ckksfetch", "Received a new server change token (via block) for %@: %@ %@", recordZoneID, serverChangeToken, clientChangeTokenData); self.changeTokens[recordZoneID] = serverChangeToken; }; self.fetchRecordZoneChangesOperation.recordZoneFetchCompletionBlock = ^(CKRecordZoneID *recordZoneID, CKServerChangeToken *serverChangeToken, NSData *clientChangeTokenData, BOOL moreComing, NSError * recordZoneError) { STRONGIFY(self); - secnotice("ckksfetch", "Received a new server change token for %@: %@ %@", recordZoneID, serverChangeToken, clientChangeTokenData); + ckksinfo_global("ckksfetch", "Received a new server change token for %@: %@ %@", recordZoneID, serverChangeToken, clientChangeTokenData); self.changeTokens[recordZoneID] = serverChangeToken; self.allClientOptions[recordZoneID].previousServerChangeToken = serverChangeToken; self.moreComing |= moreComing; if(moreComing) { - secnotice("ckksfetch", "more changes pending for %@, will start a new fetch at change token %@", recordZoneID, self.changeTokens[recordZoneID]); + ckksnotice_global("ckksfetch", "more changes pending for %@, will start a new fetch at change token %@", recordZoneID, self.changeTokens[recordZoneID]); } - ckksnotice("ckksfetch", recordZoneID, "Record zone fetch complete: changeToken=%@ clientChangeTokenData=%@ moreComing=%@ error=%@", serverChangeToken, clientChangeTokenData, - moreComing ? @"YES" : @"NO", - recordZoneError); + ckksinfo("ckksfetch", recordZoneID, "Record zone fetch complete: changeToken=%@ clientChangeTokenData=%@ moreComing=%@ error=%@", serverChangeToken, clientChangeTokenData, + moreComing ? @"YES" : @"NO", + recordZoneError); [self sendChangesToClient:recordZoneID moreComing:moreComing]; }; @@ -257,7 +257,7 @@ self.fetchRecordZoneChangesOperation.fetchRecordZoneChangesCompletionBlock = ^(NSError * _Nullable operationError) { STRONGIFY(self); if(!self) { - secerror("ckksfetch: received callback for released object"); + ckkserror_global("ckksfetch", "received callback for released object"); return; } @@ -273,7 +273,7 @@ // If we were told that there were moreChanges coming for any zone, we'd like to fetch again. // This is true if we recieve no error or a network timeout. Any other error should cause a failure. if(self.moreComing && (operationError == nil || [CKKSReachabilityTracker isNetworkFailureError:operationError])) { - secnotice("ckksfetch", "Must issue another fetch (with potential error %@)", operationError); + ckksnotice_global("ckksfetch", "Must issue another fetch (with potential error %@)", operationError); self.moreComing = false; [self performFetch]; return; @@ -283,7 +283,7 @@ self.error = operationError; } - secnotice("ckksfetch", "Record zone changes fetch complete: error=%@", operationError); + ckksnotice_global("ckksfetcher", "Record zone changes fetch complete: error=%@", operationError); [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventFetchAllChanges count:self.fetchedItems]; @@ -300,7 +300,7 @@ for(CKRecordZoneNotification* rz in self.apnsPushes) { if(rz.ckksPushTracingEnabled) { - secnotice("ckksfetch", "Submitting post-fetch CKEventMetric due to notification %@", rz); + ckksnotice_global("ckksfetch", "Submitting post-fetch CKEventMetric due to notification %@", rz); // Schedule submitting this metric on another operation, so hopefully CK will have marked this fetch as done by the time that fires? CKEventMetric *metric = [[CKEventMetric alloc] initWithEventName:@"APNSPushMetrics"]; @@ -339,11 +339,11 @@ CKKSResultOperation* launchMetricOp = [CKKSResultOperation named:@"submit-metric" withBlock:^{ if(![metric associateWithCompletedOperation:rzcOperation]) { - secerror("ckksfetch: Couldn't associate metric with operation: %@ %@", metric, rzcOperation); + ckkserror_global("ckksfetch", "Couldn't associate metric with operation: %@ %@", metric, rzcOperation); } [container submitEventMetric:metric]; [[SecMetrics managerObject] submitEvent:metric2]; - secnotice("ckksfetch", "Metric submitted: %@", metric); + ckksnotice_global("ckksfetch", "Metric submitted: %@", metric); }]; [launchMetricOp addSuccessDependency:self.fetchCompletedOperation]; @@ -367,7 +367,7 @@ { id client = self.clientMap[recordZoneID]; if(!client) { - secerror("ckksfetch: no client registered for %@, so why did we get any data?", recordZoneID); + ckkserror_global("ckksfetch", "no client registered for %@, so why did we get any data?", recordZoneID); return; } @@ -395,8 +395,8 @@ BOOL resync = [self.resyncingZones containsObject:recordZoneID]; - ckksnotice("ckksfetch", recordZoneID, "Delivering fetched changes: changed=%lu deleted=%lu moreComing=%lu resync=%u", - (unsigned long)zoneModifications.count, (unsigned long)zoneDeletions.count, (unsigned long)moreComing, resync); + ckksnotice("ckksfetch", recordZoneID, "Delivering fetched changes: changed=%lu deleted=%lu moreComing=%lu resync=%u changeToken=%@", + (unsigned long)zoneModifications.count, (unsigned long)zoneDeletions.count, (unsigned long)moreComing, resync, self.changeTokens[recordZoneID]); // Tell the client about these changes! [client changesFetched:zoneModifications diff --git a/keychain/ckks/CKKSFixups.h b/keychain/ckks/CKKSFixups.h index 98e48dd7..d64fba89 100644 --- a/keychain/ckks/CKKSFixups.h +++ b/keychain/ckks/CKKSFixups.h @@ -40,11 +40,12 @@ typedef NS_ENUM(NSUInteger, CKKSFixup) { CKKSFixupFetchTLKShares, CKKSFixupLocalReload, CKKSFixupResaveDeviceStateEntries, + CKKSFixupDeleteAllCKKSTombstones, }; -#define CKKSCurrentFixupNumber (CKKSFixupResaveDeviceStateEntries) +#define CKKSCurrentFixupNumber (CKKSFixupDeleteAllCKKSTombstones) @interface CKKSFixups : NSObject -+(CKKSGroupOperation*)fixup:(CKKSFixup)lastfixup for:(CKKSKeychainView*)keychainView; ++(nullable CKKSGroupOperation*)fixup:(CKKSFixup)lastfixup for:(CKKSKeychainView*)keychainView; @end // Fixup declarations. You probably don't need to look at these @@ -61,6 +62,7 @@ typedef NS_ENUM(NSUInteger, CKKSFixup) { @interface CKKSFixupLocalReloadOperation : CKKSGroupOperation @property (weak) CKKSKeychainView* ckks; - (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)keychainView + fixupNumber:(CKKSFixup)fixupNumber ckoperationGroup:(CKOperationGroup*)ckoperationGroup; @end diff --git a/keychain/ckks/CKKSFixups.m b/keychain/ckks/CKKSFixups.m index 927cf56e..af99a348 100644 --- a/keychain/ckks/CKKSFixups.m +++ b/keychain/ckks/CKKSFixups.m @@ -31,7 +31,7 @@ #import "keychain/ot/ObjCImprovements.h" @implementation CKKSFixups -+(CKKSGroupOperation*)fixup:(CKKSFixup)lastfixup for:(CKKSKeychainView*)keychainView ++(nullable CKKSGroupOperation*)fixup:(CKKSFixup)lastfixup for:(CKKSKeychainView*)keychainView { if(lastfixup == CKKSCurrentFixupNumber) { return nil; @@ -61,6 +61,7 @@ if(lastfixup < CKKSFixupLocalReload) { CKKSResultOperation* localSync = [[CKKSFixupLocalReloadOperation alloc] initWithCKKSKeychainView:keychainView + fixupNumber:CKKSFixupLocalReload ckoperationGroup:fixupCKGroup]; [localSync addNullableSuccessDependency:previousOp]; [fixups runBeforeGroupFinished:localSync]; @@ -75,6 +76,15 @@ previousOp = resave; } + if(lastfixup < CKKSFixupDeleteAllCKKSTombstones) { + CKKSResultOperation* localSync = [[CKKSFixupLocalReloadOperation alloc] initWithCKKSKeychainView:keychainView + fixupNumber:CKKSFixupDeleteAllCKKSTombstones + ckoperationGroup:fixupCKGroup]; + [localSync addNullableSuccessDependency:previousOp]; + [fixups runBeforeGroupFinished:localSync]; + previousOp = localSync; + } + (void)previousOp; return fixups; } @@ -111,13 +121,13 @@ return; } - [ckks dispatchSyncWithAccountKeys:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; NSArray* cips = [CKKSCurrentItemPointer allInZone: ckks.zoneID error:&error]; if(error) { ckkserror("ckksfixup", ckks, "Couldn't fetch current item pointers: %@", error); - return false; + return CKKSDatabaseTransactionRollback; } NSMutableSet* recordIDs = [NSMutableSet set]; @@ -137,12 +147,12 @@ WEAKIFY(self); NSBlockOperation* doneOp = [NSBlockOperation named:@"fetch-records-operation-complete" withBlock:^{}]; - id fetch = [[ckks.cloudKitClassDependencies.fetchRecordsOperationClass alloc] initWithRecordIDs: [recordIDs allObjects]]; + CKDatabaseOperation* fetch = [[ckks.cloudKitClassDependencies.fetchRecordsOperationClass alloc] initWithRecordIDs: [recordIDs allObjects]]; fetch.fetchRecordsCompletionBlock = ^(NSDictionary * _Nullable recordsByRecordID, NSError * _Nullable error) { STRONGIFY(self); CKKSKeychainView* strongCKKS = self.ckks; - [strongCKKS dispatchSync:^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(error) { ckkserror("ckksfixup", strongCKKS, "Finished record fetch with error: %@", error); @@ -186,14 +196,14 @@ } [self runBeforeGroupFinished:doneOp]; - return true; + return CKKSDatabaseTransactionCommit; }]; }; - [ckks.database addOperation: fetch]; + [ckks.operationDependencies.ckdatabase addOperation:fetch]; [self dependOnBeforeGroupFinished:fetch]; [self dependOnBeforeGroupFinished:doneOp]; - return true; + return CKKSDatabaseTransactionCommit; }]; } @end @@ -229,25 +239,25 @@ return; } - [ckks dispatchSyncWithAccountKeys:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ WEAKIFY(self); NSBlockOperation* doneOp = [NSBlockOperation named:@"fetch-records-operation-complete" withBlock:^{}]; NSPredicate *yes = [NSPredicate predicateWithValue:YES]; CKQuery *query = [[CKQuery alloc] initWithRecordType:SecCKRecordTLKShareType predicate:yes]; - id fetch = [[ckks.cloudKitClassDependencies.queryOperationClass alloc] initWithQuery:query]; + CKDatabaseOperation* fetch = [[ckks.cloudKitClassDependencies.queryOperationClass alloc] initWithQuery:query]; fetch.zoneID = ckks.zoneID; fetch.desiredKeys = nil; fetch.recordFetchedBlock = ^(CKRecord * _Nonnull record) { STRONGIFY(self); CKKSKeychainView* strongCKKS = self.ckks; - [strongCKKS dispatchSync:^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ ckksnotice("ckksfixup", strongCKKS, "Recieved tlk share record from query: %@", record); [strongCKKS _onqueueCKRecordChanged:record resync:true]; - return true; + return CKKSDatabaseTransactionCommit; }]; }; @@ -255,11 +265,11 @@ STRONGIFY(self); CKKSKeychainView* strongCKKS = self.ckks; - [strongCKKS dispatchSync:^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(error) { ckkserror("ckksfixup", strongCKKS, "Couldn't fetch all TLKShare records: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } ckksnotice("ckksfixup", strongCKKS, "Successfully fetched TLKShare records (%@)", cursor); @@ -273,16 +283,16 @@ } else { ckksnotice("ckksfixup", strongCKKS, "Updated zone fixup state to CKKSFixupFetchTLKShares"); } - return true; + return CKKSDatabaseTransactionCommit; }]; [self runBeforeGroupFinished:doneOp]; }; - [ckks.database addOperation: fetch]; + [ckks.operationDependencies.ckdatabase addOperation:fetch]; [self dependOnBeforeGroupFinished:fetch]; [self dependOnBeforeGroupFinished:doneOp]; - return true; + return CKKSDatabaseTransactionCommit; }]; } @end @@ -291,24 +301,31 @@ @interface CKKSFixupLocalReloadOperation () @property CKOperationGroup* group; +@property CKKSFixup fixupNumber; @end // In Server Generated CloudKit "Manatee Identity Lost" // items could be deleted from the local keychain after CKKS believed they were already synced, and therefore wouldn't resync // Perform a local resync operation +// +// In CKKS: adjust UUID and tombstone handling +// some CKKS participants uploaded entries with tomb=1 to CKKS +// Performing a local reload operation should find and delete those entries @implementation CKKSFixupLocalReloadOperation - (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)keychainView + fixupNumber:(CKKSFixup)fixupNumber ckoperationGroup:(CKOperationGroup *)ckoperationGroup { if((self = [super init])) { _ckks = keychainView; + _fixupNumber = fixupNumber; _group = ckoperationGroup; } return self; } - (NSString*)description { - return [NSString stringWithFormat:@"", self.ckks]; + return [NSString stringWithFormat:@"", (int)self.fixupNumber, self.ckks]; } - (void)groupStart { CKKSKeychainView* ckks = self.ckks; @@ -325,25 +342,26 @@ CKKSResultOperation* cleanup = [CKKSResultOperation named:@"local-reload-cleanup" withBlock:^{ STRONGIFY(self); __strong __typeof(self.ckks) strongCKKS = self.ckks; - [strongCKKS dispatchSync:^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(reload.error) { ckkserror("ckksfixup", strongCKKS, "Couldn't perform a reload: %@", reload.error); self.error = reload.error; - return false; + return CKKSDatabaseTransactionRollback; } - ckksnotice("ckksfixup", strongCKKS, "Successfully performed a reload fixup"); + ckksnotice("ckksfixup", strongCKKS, "Successfully performed a reload fixup. New fixup number is %d", + (int)self.fixupNumber); NSError* localerror = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:strongCKKS.zoneName error:&localerror]; - ckse.lastFixup = CKKSFixupLocalReload; + ckse.lastFixup = self.fixupNumber; [ckse saveToDatabase:&localerror]; if(localerror) { ckkserror("ckksfixup", strongCKKS, "Couldn't save CKKSZoneStateEntry(%@): %@", ckse, localerror); } else { ckksnotice("ckksfixup", strongCKKS, "Updated zone fixup state to CKKSFixupLocalReload"); } - return true; + return CKKSDatabaseTransactionCommit; }]; }]; [cleanup addNullableDependency:reload]; @@ -377,7 +395,7 @@ } // This operation simply loads all CDSEs, remakes them from their CKRecord, and resaves them - [ckks dispatchSync:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; NSArray* cdses = [CKKSDeviceStateEntry allInZone:ckks.zoneID error:&error]; @@ -385,7 +403,7 @@ if(error) { ckkserror("ckksfixup", ckks, "Unable to fetch all CDSEs: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } for(CKKSDeviceStateEntry* cdse in cdses) { @@ -397,7 +415,7 @@ if(error) { ckkserror("ckksfixup", ckks, "Unable to save CDSE: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } } else { ckksnotice("ckksfixup", ckks, "Saved CDSE has no stored record: %@", cdse); @@ -413,12 +431,12 @@ if(localerror) { ckkserror("ckksfixup", ckks, "Couldn't save CKKSZoneStateEntry(%@): %@", ckse, localerror); self.error = localerror; - return false; + return CKKSDatabaseTransactionRollback; } ckksnotice("ckksfixup", ckks, "Updated zone fixup state to CKKSFixupResaveDeviceStateEntries"); - return true; + return CKKSDatabaseTransactionCommit; }]; } diff --git a/keychain/ckks/CKKSGroupOperation.m b/keychain/ckks/CKKSGroupOperation.m index d85e9fad..bc984f44 100644 --- a/keychain/ckks/CKKSGroupOperation.m +++ b/keychain/ckks/CKKSGroupOperation.m @@ -25,7 +25,7 @@ #import "CKKSGroupOperation.h" #import "keychain/ot/ObjCImprovements.h" -#include +#import "keychain/ckks/CKKS.h" @interface CKKSGroupOperation() @property bool fillInError; @@ -53,12 +53,12 @@ _startOperation = [NSBlockOperation blockOperationWithBlock:^{ STRONGIFY(self); if(!self) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } if(![self allDependentsSuccessful]) { - secdebug("ckksgroup", "Not running due to some failed dependent: %@", self.error); + ckksinfo_global("ckksgroup", "Not running due to some failed dependent: %@", self.error); [self cancel]; return; } @@ -71,7 +71,7 @@ _finishOperation = [NSBlockOperation blockOperationWithBlock:^{ STRONGIFY(self); if(!self) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } @@ -114,37 +114,62 @@ } - (NSString*)description { - if(self.isFinished) { + + static __thread unsigned __descriptionRecursion = 0; + NSString* state = [self operationStateString]; + NSString *desc = NULL; + + __descriptionRecursion++; + + if(__descriptionRecursion > 10) { + desc = [NSString stringWithFormat: @"<%@: %@ recursion>", [self selfname], state]; + + } else if(self.isFinished) { if(self.error) { - return [NSString stringWithFormat: @"<%@: %@ %@ - %@>", [self selfname], - [self operationStateString], + desc = [NSString stringWithFormat: @"<%@: %@ %@ - %@>", [self selfname], + state, self.finishDate, self.error]; } else { - return [NSString stringWithFormat: @"<%@: %@ %@>", [self selfname], - [self operationStateString], + desc = [NSString stringWithFormat: @"<%@: %@ %@>", [self selfname], + state, self.finishDate]; } - } + } else { - NSMutableArray* ops = [self.operationQueue.operations mutableCopy]; + NSString* opsString = nil; - [ops removeObject: self.finishOperation]; + if (self.operationQueue.operationCount + self.finishOperation.dependencies.count > 20) { + opsString = @"Potentially more than 20 operations"; + } else { + NSMutableArray* ops = [self.operationQueue.operations mutableCopy]; - // Any extra dependencies from the finish operation should be considered part of this group - for(NSOperation* finishDep in self.finishOperation.dependencies) { - if(finishDep != self.startOperation && (NSNotFound == [ops indexOfObject: finishDep])) { - [ops addObject: finishDep]; + [ops removeObject: self.finishOperation]; + + // Any extra dependencies from the finish operation should be considered part of this group + for(NSOperation* finishDep in self.finishOperation.dependencies) { + if (ops.count > 20) { + opsString = @"Potentially more than 20 operations"; + break; + } + if(finishDep != self.startOperation && (NSNotFound == [ops indexOfObject: finishDep])) { + [ops addObject: finishDep]; + } + } + if (opsString == nil) { + opsString = [ops componentsJoinedByString:@", "]; + } + } + + if(self.error) { + desc = [NSString stringWithFormat: @"<%@: %@ [%@] error:%@>", [self selfname], state, opsString, self.error]; + } else { + desc = [NSString stringWithFormat: @"<%@: %@ [%@]%@>", [self selfname], state, opsString, [self pendingDependenciesString:@" dep:"]]; } } + __descriptionRecursion--; - NSString* opsString = [ops componentsJoinedByString:@", "]; - - if(self.error) { - return [NSString stringWithFormat: @"<%@: %@ [%@] error:%@>", [self selfname], [self operationStateString], opsString, self.error]; - } else { - return [NSString stringWithFormat: @"<%@: %@ [%@]%@>", [self selfname], [self operationStateString], opsString, [self pendingDependenciesString:@" dep:"]]; - } + return desc; } - (NSString*)debugDescription { @@ -275,7 +300,7 @@ if([self isCancelled]) { // Cancelled operations can't add anything. - secnotice("ckksgroup", "Can't add operation dependency to cancelled group"); + ckksnotice_global("ckksgroup", "Can't add operation dependency to cancelled group"); return; } diff --git a/keychain/ckks/CKKSHealKeyHierarchyOperation.h b/keychain/ckks/CKKSHealKeyHierarchyOperation.h index 2e30b8c3..7fbbb63e 100644 --- a/keychain/ckks/CKKSHealKeyHierarchyOperation.h +++ b/keychain/ckks/CKKSHealKeyHierarchyOperation.h @@ -23,6 +23,8 @@ #import #import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" #if OCTAGON @@ -30,12 +32,16 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@interface CKKSHealKeyHierarchyOperation : CKKSGroupOperation +@interface CKKSHealKeyHierarchyOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; +@property OctagonState* nextState; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; - +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSHealKeyHierarchyOperation.m b/keychain/ckks/CKKSHealKeyHierarchyOperation.m index 21351856..bc4f316f 100644 --- a/keychain/ckks/CKKSHealKeyHierarchyOperation.m +++ b/keychain/ckks/CKKSHealKeyHierarchyOperation.m @@ -28,6 +28,7 @@ #import "CKKSGroupOperation.h" #import "CKKSAnalytics.h" #import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/CKKSHealTLKSharesOperation.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "keychain/ot/ObjCImprovements.h" @@ -35,18 +36,26 @@ @interface CKKSHealKeyHierarchyOperation () @property NSBlockOperation* cloudkitModifyOperationFinished; -@property CKOperationGroup* ckoperationGroup; @end @implementation CKKSHealKeyHierarchyOperation +@synthesize intendedState = _intendedState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { - if(self = [super init]) { + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if((self = [super init])) { + _deps = dependencies; _ckks = ckks; - _ckoperationGroup = ckoperationGroup; + + _intendedState = intendedState; + _nextState = errorState; } return self; } @@ -73,11 +82,13 @@ return; } + NSArray* currentTrustStates = self.deps.currentTrustStates; + // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. - [ckks dispatchSyncWithAccountKeys: ^bool{ + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckksheal", ckks, "CKKSHealKeyHierarchyOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } NSError* error = nil; @@ -109,8 +120,8 @@ // If we haven't done one yet, initiate a refetch of everything from cloudkit, and write down that we did so if(!ckks.keyStateMachineRefetched) { ckksnotice("ckksheal", ckks, "Have current key pointers, but no keys. This is exceptional; requesting full refetch"); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateNeedFullRefetch withError:nil]; - return true; + self.nextState = SecCKKSZoneKeyStateNeedFullRefetch; + return CKKSDatabaseTransactionCommit; } } @@ -150,39 +161,42 @@ newTLK = topKey; } else if(![newTLK.uuid isEqualToString: topKey.uuid]) { ckkserror("ckksheal", ckks, "key hierarchy has split: there's two top keys. Currently we don't handle this situation."); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: [NSError errorWithDomain:CKKSErrorDomain - code:CKKSSplitKeyHierarchy - userInfo:@{NSLocalizedDescriptionKey: - [NSString stringWithFormat:@"Key hierarchy has split: %@ and %@ are roots", newTLK, topKey]}]]; - return true; + self.error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSSplitKeyHierarchy + description:[NSString stringWithFormat:@"Key hierarchy has split: %@ and %@ are roots", newTLK, topKey]]; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; } } if(!newTLK) { // We don't have any TLKs lying around, but we're supposed to heal the key hierarchy. This isn't any good; let's wait for TLK creation. ckkserror("ckksheal", ckks, "No possible TLK found. Waiting for creation."); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForTLKCreation withError:nil]; - return true; + self.nextState = SecCKKSZoneKeyStateWaitForTLKCreation; + return CKKSDatabaseTransactionCommit; } - if(![ckks _onqueueWithAccountKeysCheckTLK: newTLK error: &error]) { - // Was this error "I've never seen that TLK before in my life"? If so, enter the "wait for TLK sync" state. - if(error && [error.domain isEqualToString: @"securityd"] && error.code == errSecItemNotFound) { - ckksnotice("ckksheal", ckks, "Received a TLK which we don't have in the local keychain(%@). Entering waitfortlk.", newTLK); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForTLK withError:nil]; - return true; - } else if(error && [ckks.lockStateTracker isLockedError:error]) { - ckksnotice("ckkskey", ckks, "Received a TLK(%@), but keybag appears to be locked. Entering WaitForUnlock.", newTLK); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForUnlock withError:nil]; - return true; + if(![newTLK validTLK:&error]) { + // Something has gone horribly wrong. Enter error state. + ckkserror("ckkskey", ckks, "CKKS claims %@ is not a valid TLK: %@", newTLK, error); + self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"Invalid TLK from CloudKit (during heal)" underlying:error]; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; + } + // This key is our proposed TLK. + if(![newTLK tlkMaterialPresentOrRecoverableViaTLKShare:currentTrustStates + error:&error]) { + // TLK is valid, but not present locally + if(error && [self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", ckks, "Received a TLK(%@), but keybag appears to be locked. Entering a waiting state.", newTLK); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; } else { - // Otherwise, something has gone horribly wrong. enter error state. - ckkserror("ckksheal", ckks, "CKKS claims %@ is not a valid TLK: %@", newTLK, error); - NSError* newError = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"Invalid TLK from CloudKit (during heal)" underlying:error]; - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:newError]; - return true; + ckksnotice("ckkskey", ckks, "Received a TLK(%@) which we don't have in the local keychain: %@", newTLK, error); + self.error = error; + self.nextState = SecCKKSZoneKeyStateTLKMissing; } + return CKKSDatabaseTransactionCommit; } // We have our new TLK. @@ -224,12 +238,14 @@ if(error && [ckks.lockStateTracker isLockedError:error]) { ckksnotice("ckksheal", ckks, "Couldn't create a new class A key, but keybag appears to be locked. Entering waitforunlock."); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForUnlock withError:error]; - return true; + self.error = error; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + return CKKSDatabaseTransactionCommit; } else if(error) { ckkserror("ckksheal", ckks, "couldn't create new classA key: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return true; + self.error = error; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; } keyset.classA = newClassAKey; @@ -242,12 +258,14 @@ if(error && [ckks.lockStateTracker isLockedError:error]) { ckksnotice("ckksheal", ckks, "Couldn't create a new class C key, but keybag appears to be locked. Entering waitforunlock."); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForUnlock withError:error]; - return true; + self.error = error; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + return CKKSDatabaseTransactionCommit; } else if(error) { ckkserror("ckksheal", ckks, "couldn't create new class C key: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return true; + self.error = error; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; } keyset.classC = newClassCKey; @@ -279,11 +297,12 @@ } // We've selected a new TLK. Compute any TLKShares that should go along with it. - NSSet* tlkShares = [ckks _onqueueCreateMissingKeyShares:keyset.tlk - error:&error]; + NSSet* tlkShares = [CKKSHealTLKSharesOperation createMissingKeyShares:keyset + trustStates:currentTrustStates + error:&error]; if(error) { ckkserror("ckksshare", ckks, "Unable to create TLK shares for new tlk: %@", error); - return false; + return CKKSDatabaseTransactionRollback; } for(CKKSTLKShareRecord* share in tlkShares) { @@ -316,8 +335,8 @@ modifyRecordsOp.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; modifyRecordsOp.configuration.isCloudKitSupportOperation = YES; - modifyRecordsOp.group = self.ckoperationGroup; - ckksnotice("ckksheal", ckks, "Operation group is %@", self.ckoperationGroup); + modifyRecordsOp.group = self.deps.ckoperationGroup; + ckksnotice("ckksheal", ckks, "Operation group is %@", self.deps.ckoperationGroup); modifyRecordsOp.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) { STRONGIFY(self); @@ -335,15 +354,15 @@ STRONGIFY(self); CKKSKeychainView* strongCKKS = self.ckks; if(!self) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } ckksnotice("ckksheal", strongCKKS, "Completed Key Heal CloudKit operation with error: %@", error); - [strongCKKS dispatchSyncWithAccountKeys: ^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(error == nil) { - [[CKKSAnalytics logger] logSuccessForEvent:CKKSEventProcessHealKeyHierarchy inView:ckks]; + [[CKKSAnalytics logger] logSuccessForEvent:CKKSEventProcessHealKeyHierarchy zoneName:ckks.zoneName]; // Success. Persist the keys to the CKKS database. // Save the new CKRecords to the before persisting to database @@ -381,62 +400,73 @@ if(localerror != nil) { ckkserror("ckksheal", strongCKKS, "couldn't save new key hierarchy to database; this is very bad: %@", localerror); - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: localerror]; - return false; + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionRollback; } else { // Everything is groovy. HOWEVER, we might still not have processed the keys. Ask for that! - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateProcess withError: nil]; + self.nextState = SecCKKSZoneKeyStateProcess; } } else { // ERROR. This isn't a total-failure error state, but one that should kick off a healing process. - [[CKKSAnalytics logger] logUnrecoverableError:error forEvent:CKKSEventProcessHealKeyHierarchy inView:ckks withAttributes:NULL]; + [[CKKSAnalytics logger] logUnrecoverableError:error forEvent:CKKSEventProcessHealKeyHierarchy zoneName:ckks.zoneName withAttributes:NULL]; ckkserror("ckksheal", strongCKKS, "couldn't save new key hierarchy to CloudKit: %@", error); [strongCKKS _onqueueCKWriteFailed:error attemptedRecordsChanged:attemptedRecords]; - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateNewTLKsFailed withError: nil]; + + self.nextState = SecCKKSZoneKeyStateNewTLKsFailed; } - return true; + return CKKSDatabaseTransactionCommit; }]; // Notify that we're done [self.operationQueue addOperation: self.cloudkitModifyOperationFinished]; }; - [ckks.database addOperation: modifyRecordsOp]; + [self.deps.ckdatabase addOperation:modifyRecordsOp]; return true; } // Check if CKKS can recover this TLK. - bool haveTLK = [ckks _onqueueWithAccountKeysCheckTLK:keyset.tlk error:&error]; - if(error && [ckks.lockStateTracker isLockedError:error]) { - ckksnotice("ckkskey", ckks, "Failed to load TLK from keychain, keybag is locked. Entering waitforunlock: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForUnlock withError:nil]; - return false; - } else if(error && [error.domain isEqualToString: @"securityd"] && error.code == errSecItemNotFound) { - ckkserror("ckksheal", ckks, "CKKS couldn't find TLK, triggering move to wait state: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateWaitForTLK withError: nil]; - } else if(!haveTLK) { - ckkserror("ckksheal", ckks, "CKKS errored examining TLK, triggering move to bad state: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return false; + if(![keyset.tlk validTLK:&error]) { + // Something has gone horribly wrong. Enter error state. + ckkserror("ckkskey", ckks, "CKKS claims %@ is not a valid TLK: %@", keyset.tlk, error); + self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"Invalid TLK from CloudKit (during heal)" underlying:error]; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; + } + + // This key is our proposed TLK. + if(![keyset.tlk tlkMaterialPresentOrRecoverableViaTLKShare:currentTrustStates + error:&error]) { + // TLK is valid, but not present locally + if(error && [self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", ckks, "Received a TLK(%@), but keybag appears to be locked. Entering a waiting state.", keyset.tlk); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckksnotice("ckkskey", ckks, "Received a TLK(%@) which we don't have in the local keychain: %@", keyset.tlk, error); + self.error = error; + self.nextState = SecCKKSZoneKeyStateTLKMissing; + } + return CKKSDatabaseTransactionCommit; } if(![self ensureKeyPresent:keyset.tlk]) { - return false; + return CKKSDatabaseTransactionRollback; } if(![self ensureKeyPresent:keyset.classA]) { - return false; + return CKKSDatabaseTransactionRollback; } if(![self ensureKeyPresent:keyset.classC]) { - return false; + return CKKSDatabaseTransactionRollback; } // Seems good to us. Check if we're ready? - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateReady withError: nil]; + self.nextState = self.intendedState; - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -450,16 +480,29 @@ error = nil; [key unwrapViaKeyHierarchy: &error]; if(error) { + if([ckks.lockStateTracker isLockedError:error]) { + ckkserror("ckksheal", ckks, "Couldn't unwrap key(%@) using key hierarchy due to the lock state: %@", key, error); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + self.error = error; + return false; + } ckkserror("ckksheal", ckks, "Couldn't unwrap key(%@) using key hierarchy. Keys are broken, quitting: %@", key, error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; + self.error = error; + self.nextState = SecCKKSZoneKeyStateError; self.error = error; return false; } [key saveKeyMaterialToKeychain:&error]; if(error) { + if([ckks.lockStateTracker isLockedError:error]) { + ckkserror("ckksheal", ckks, "Couldn't save key(%@) to keychain due to the lock state: %@", key, error); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + self.error = error; + return false; + } ckkserror("ckksheal", ckks, "Couldn't save key(%@) to keychain: %@", key, error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; self.error = error; + self.nextState = SecCKKSZoneKeyStateError; return false; } } diff --git a/keychain/ckks/CKKSHealTLKSharesOperation.h b/keychain/ckks/CKKSHealTLKSharesOperation.h index 9dc61050..910cd917 100644 --- a/keychain/ckks/CKKSHealTLKSharesOperation.h +++ b/keychain/ckks/CKKSHealTLKSharesOperation.h @@ -23,18 +23,32 @@ #import #import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ckks/CKKSCurrentKeyPointer.h" +#import "keychain/ot/OctagonStateMachine.h" #if OCTAGON NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; +@class CKKSOperationDependencies; -@interface CKKSHealTLKSharesOperation : CKKSGroupOperation +@interface CKKSHealTLKSharesOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; +- (instancetype)initWithOperationDependencies:(CKKSOperationDependencies*)operationDependencies + ckks:(CKKSKeychainView*)ckks; + + +// For this keyset, who doesn't yet have a CKKSTLKShare for its TLK, shared to their current Octagon keys? +// Note that we really want a record sharing the TLK to ourselves, so this function might return +// a non-empty set even if all peers have the TLK: it wants us to make a record for ourself. +// If you pass in a non-empty set in afterUploading, those records will be included in the calculation. ++ (NSSet* _Nullable)createMissingKeyShares:(CKKSCurrentKeySet*)keyset + trustStates:(NSArray*)trustStates + error:(NSError* __autoreleasing*)errore; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSHealTLKSharesOperation.m b/keychain/ckks/CKKSHealTLKSharesOperation.m index a407f466..7571a256 100644 --- a/keychain/ckks/CKKSHealTLKSharesOperation.m +++ b/keychain/ckks/CKKSHealTLKSharesOperation.m @@ -38,18 +38,25 @@ @interface CKKSHealTLKSharesOperation () @property NSBlockOperation* cloudkitModifyOperationFinished; -@property CKOperationGroup* ckoperationGroup; @end @implementation CKKSHealTLKSharesOperation +@synthesize intendedState = _intendedState; +@synthesize nextState = _nextState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { + +- (instancetype)initWithOperationDependencies:(CKKSOperationDependencies*)operationDependencies + ckks:(CKKSKeychainView*)ckks +{ if(self = [super init]) { _ckks = ckks; - _ckoperationGroup = ckoperationGroup; + _deps = operationDependencies; + + _nextState = SecCKKSZoneKeyStateHealTLKSharesFailed; + _intendedState = SecCKKSZoneKeyStateBecomeReady; } return self; } @@ -63,168 +70,160 @@ WEAKIFY(self); - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksshare", ckks, "no CKKS object"); - return; - } - if(self.cancelled) { - ckksnotice("ckksshare", ckks, "CKKSHealTLKSharesOperation cancelled, quitting"); + ckksnotice("ckksshare", self.deps.zoneID, "CKKSHealTLKSharesOperation cancelled, quitting"); return; } - [ckks dispatchSyncWithAccountKeys: ^bool{ - if(self.cancelled) { - ckksnotice("ckksshare", ckks, "CKKSHealTLKSharesOperation cancelled, quitting"); - return false; - } + NSArray* trustStates = [self.deps currentTrustStates]; - NSError* error = nil; + NSError* error = nil; + __block CKKSCurrentKeySet* keyset = nil; - CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:ckks.zoneID]; - - if(keyset.error) { - self.error = keyset.error; - ckkserror("ckksshare", ckks, "couldn't load current keys: can't fix TLK shares"); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateUnhealthy withError:nil]; - return true; - } else { - ckksnotice("ckksshare", ckks, "Key set is %@", keyset); - } - - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventTLKShareProcessing zone:ckks.zoneName]; - - // Okay! Perform the checks. - if(![keyset.tlk loadKeyMaterialFromKeychain:&error] || error) { - // Well, that's no good. We can't share a TLK we don't have. - if([ckks.lockStateTracker isLockedError: error]) { - ckkserror("ckksshare", ckks, "Keychain is locked: can't fix shares yet: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateReadyPendingUnlock withError:nil]; - } else { - // TODO go to waitfortlk - ckkserror("ckksshare", ckks, "couldn't load current tlk from keychain: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateUnhealthy withError:nil]; - } - return true; - } - - NSSet* newShares = [ckks _onqueueCreateMissingKeyShares:keyset.tlk - error:&error]; - if(error) { - ckkserror("ckksshare", ckks, "Unable to create shares: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateUnhealthy withError:nil]; - return false; - } - - if(newShares.count == 0u) { - ckksnotice("ckksshare", ckks, "Don't believe we need to change any TLKShares, stopping"); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateReady withError:nil]; - return true; - } - - // Let's double-check: if we upload these TLKShares, will the world be right? - BOOL newSharesSufficient = [ckks _onqueueAreNewSharesSufficient:newShares - currentTLK:keyset.tlk - error:&error]; - if(!newSharesSufficient || error) { - ckksnotice("ckksshare", ckks, "New shares won't resolve the share issue; erroring to avoid infinite loops"); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return true; - } - - // Fire up our CloudKit operation! - - NSMutableArray* recordsToSave = [[NSMutableArray alloc] init]; - NSMutableArray* recordIDsToDelete = [[NSMutableArray alloc] init]; - NSMutableDictionary* attemptedRecords = [[NSMutableDictionary alloc] init]; - - for(CKKSTLKShareRecord* share in newShares) { - CKRecord* record = [share CKRecordWithZoneID:ckks.zoneID]; - [recordsToSave addObject: record]; - attemptedRecords[record.recordID] = record; - } - - // Use the spare operation trick to wait for the CKModifyRecordsOperation to complete - self.cloudkitModifyOperationFinished = [NSBlockOperation named:@"heal-tlkshares-modify-operation-finished" withBlock:^{}]; - [self dependOnBeforeGroupFinished: self.cloudkitModifyOperationFinished]; - - - // Get the CloudKit operation ready... - CKModifyRecordsOperation* modifyRecordsOp = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave - recordIDsToDelete:recordIDsToDelete]; - modifyRecordsOp.atomic = YES; - modifyRecordsOp.longLived = NO; - - // very important: get the TLKShares off-device ASAP - modifyRecordsOp.configuration.automaticallyRetryNetworkFailures = NO; - modifyRecordsOp.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; - modifyRecordsOp.configuration.isCloudKitSupportOperation = YES; - - modifyRecordsOp.group = self.ckoperationGroup; - ckksnotice("ckksshare", ckks, "Operation group is %@", self.ckoperationGroup); - - modifyRecordsOp.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) { - STRONGIFY(self); - CKKSKeychainView* blockCKKS = self.ckks; - - // These should all fail or succeed as one. Do the hard work in the records completion block. - if(!error) { - ckksnotice("ckksshare", blockCKKS, "Successfully completed upload for record %@", record.recordID.recordName); - } else { - ckkserror("ckksshare", blockCKKS, "error on row: %@ %@", record.recordID, error); - } - }; - - modifyRecordsOp.modifyRecordsCompletionBlock = ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *error) { - STRONGIFY(self); - CKKSKeychainView* strongCKKS = self.ckks; - if(!self) { - secerror("ckks: received callback for released object"); - return; - } - - [strongCKKS dispatchSyncWithAccountKeys: ^bool { - if(error == nil) { - // Success. Persist the records to the CKKS database - ckksnotice("ckksshare", strongCKKS, "Completed TLK Share heal operation with success"); - NSError* localerror = nil; - - // Save the new CKRecords to the database - for(CKRecord* record in savedRecords) { - CKKSTLKShareRecord* savedShare = [[CKKSTLKShareRecord alloc] initWithCKRecord:record]; - bool saved = [savedShare saveToDatabase:&localerror]; - - if(!saved || localerror != nil) { - // erroring means we were unable to save the new TLKShare records to the database. This will cause us to try to reupload them. Fail. - // No recovery from this, really... - ckkserror("ckksshare", strongCKKS, "Couldn't save new TLKShare record to database: %@", localerror); - [strongCKKS _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError: localerror]; - return true; - - } else { - ckksnotice("ckksshare", strongCKKS, "Successfully completed upload for %@", savedShare); - } - } - - // Successfully sharing TLKs means we're now in ready! - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateReady withError: nil]; - } else { - ckkserror("ckksshare", strongCKKS, "Completed TLK Share heal operation with error: %@", error); - [strongCKKS _onqueueCKWriteFailed:error attemptedRecordsChanged:attemptedRecords]; - // Send the key state machine into tlksharesfailed - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateHealTLKSharesFailed withError: nil]; - } - return true; - }]; - - // Notify that we're done - [self.operationQueue addOperation: self.cloudkitModifyOperationFinished]; - }; - - [ckks.database addOperation: modifyRecordsOp]; - return true; + [self.deps.databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ + keyset = [CKKSCurrentKeySet loadForZone:self.deps.zoneID]; }]; + + if(keyset.error) { + self.nextState = SecCKKSZoneKeyStateUnhealthy; + self.error = keyset.error; + ckkserror("ckksshare", self.deps.zoneID, "couldn't load current keys: can't fix TLK shares"); + return; + } else { + ckksnotice("ckksshare", self.deps.zoneID, "Key set is %@", keyset); + } + + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventTLKShareProcessing zone:self.deps.zoneID.zoneName]; + + // Okay! Perform the checks. + if(![keyset.tlk loadKeyMaterialFromKeychain:&error] || error) { + // Well, that's no good. We can't share a TLK we don't have. + if([self.deps.lockStateTracker isLockedError: error]) { + ckkserror("ckksshare", self.deps.zoneID, "Keychain is locked: can't fix shares yet: %@", error); + self.nextState = SecCKKSZoneKeyStateBecomeReady; + } else { + ckkserror("ckksshare", self.deps.zoneID, "couldn't load current tlk from keychain: %@", error); + self.nextState = SecCKKSZoneKeyStateUnhealthy; + } + return; + } + + NSSet* newShares = [CKKSHealTLKSharesOperation createMissingKeyShares:keyset + trustStates:trustStates + error:&error]; + if(error) { + ckkserror("ckksshare", self.deps.zoneID, "Unable to create shares: %@", error); + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + + if(newShares.count == 0u) { + ckksnotice("ckksshare", self.deps.zoneID, "Don't believe we need to change any TLKShares, stopping"); + self.nextState = self.intendedState; + return; + } + + keyset.pendingTLKShares = [newShares allObjects]; + + // Let's double-check: if we upload these TLKShares, will the world be right? + BOOL newSharesSufficient = [CKKSHealTLKSharesOperation areNewSharesSufficient:keyset + trustStates:trustStates + error:&error]; + if(!newSharesSufficient || error) { + ckksnotice("ckksshare", self.deps.zoneID, "New shares won't resolve the share issue; erroring to avoid infinite loops"); + self.nextState = SecCKKSZoneKeyStateError; + return; + } + + // Fire up our CloudKit operation! + + NSMutableArray* recordsToSave = [[NSMutableArray alloc] init]; + NSMutableArray* recordIDsToDelete = [[NSMutableArray alloc] init]; + NSMutableDictionary* attemptedRecords = [[NSMutableDictionary alloc] init]; + + ckksnotice("ckksshare", self.deps.zoneID, "Uploading %d new TLKShares", (unsigned int)newShares.count); + for(CKKSTLKShareRecord* share in newShares) { + ckksnotice("ckksshare", self.deps.zoneID, "Uploading TLKShare to %@ (as %@)", share.share.receiverPeerID, share.senderPeerID); + + CKRecord* record = [share CKRecordWithZoneID:self.deps.zoneID]; + [recordsToSave addObject: record]; + attemptedRecords[record.recordID] = record; + } + + // Use the spare operation trick to wait for the CKModifyRecordsOperation to complete + self.cloudkitModifyOperationFinished = [NSBlockOperation named:@"heal-tlkshares-modify-operation-finished" withBlock:^{}]; + [self dependOnBeforeGroupFinished: self.cloudkitModifyOperationFinished]; + + // Get the CloudKit operation ready... + CKModifyRecordsOperation* modifyRecordsOp = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave + recordIDsToDelete:recordIDsToDelete]; + modifyRecordsOp.atomic = YES; + modifyRecordsOp.longLived = NO; + + // very important: get the TLKShares off-device ASAP + modifyRecordsOp.configuration.automaticallyRetryNetworkFailures = NO; + modifyRecordsOp.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; + modifyRecordsOp.configuration.isCloudKitSupportOperation = YES; + + modifyRecordsOp.group = self.deps.ckoperationGroup; + ckksnotice("ckksshare", self.deps.zoneID, "Operation group is %@", self.deps.ckoperationGroup); + + modifyRecordsOp.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) { + STRONGIFY(self); + + // These should all fail or succeed as one. Do the hard work in the records completion block. + if(!error) { + ckksnotice("ckksshare", self.deps.zoneID, "Successfully completed upload for record %@", record.recordID.recordName); + } else { + ckkserror("ckksshare", self.deps.zoneID, "error on row: %@ %@", record.recordID, error); + } + }; + + modifyRecordsOp.modifyRecordsCompletionBlock = ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *error) { + STRONGIFY(self); + + CKKSKeychainView* strongCKKS = self.ckks; + + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + if(error == nil) { + // Success. Persist the records to the CKKS database + ckksnotice("ckksshare", self.deps.zoneID, "Completed TLK Share heal operation with success"); + NSError* localerror = nil; + + // Save the new CKRecords to the database + for(CKRecord* record in savedRecords) { + CKKSTLKShareRecord* savedShare = [[CKKSTLKShareRecord alloc] initWithCKRecord:record]; + bool saved = [savedShare saveToDatabase:&localerror]; + + if(!saved || localerror != nil) { + // erroring means we were unable to save the new TLKShare records to the database. This will cause us to try to reupload them. Fail. + // No recovery from this, really... + ckkserror("ckksshare", self.deps.zoneID, "Couldn't save new TLKShare record to database: %@", localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; + + } else { + ckksnotice("ckksshare", self.deps.zoneID, "Successfully completed upload for %@", savedShare); + } + } + + // Successfully sharing TLKs means we're now in ready! + self.nextState = SecCKKSZoneKeyStateBecomeReady; + } else { + ckkserror("ckksshare", self.deps.zoneID, "Completed TLK Share heal operation with error: %@", error); + [strongCKKS _onqueueCKWriteFailed:error attemptedRecordsChanged:attemptedRecords]; + // Send the key state machine into tlksharesfailed + self.nextState = SecCKKSZoneKeyStateHealTLKSharesFailed; + } + return CKKSDatabaseTransactionCommit; + }]; + + // Notify that we're done + [self.operationQueue addOperation: self.cloudkitModifyOperationFinished]; + }; + + [self.deps.ckdatabase addOperation:modifyRecordsOp]; } - (void)cancel { @@ -232,6 +231,127 @@ [super cancel]; } ++ (BOOL)areNewSharesSufficient:(CKKSCurrentKeySet*)keyset + trustStates:(NSArray*)trustStates + error:(NSError* __autoreleasing*)error +{ + for(CKKSPeerProviderState* trustState in trustStates) { + NSError* localError = nil; + NSSet>* peersMissingShares = [trustState findPeersMissingTLKSharesFor:keyset + error:&localError]; + if(peersMissingShares == nil || localError) { + if(trustState.essential) { + if(error) { + *error = localError; + } + return NO; + } else { + ckksnotice("ckksshare", keyset.tlk, "Failed to find peers for nonessential system: %@", trustState); + // Not a hard failure. + } + } + + if(peersMissingShares.count > 0) { + ckksnotice("ckksshare", keyset.tlk, "New share set is missing shares for peers: %@", peersMissingShares); + return NO; + } + } + + return YES; +} + + ++ (NSSet* _Nullable)createMissingKeyShares:(CKKSCurrentKeySet*)keyset + trustStates:(NSArray*)trustStates + error:(NSError* __autoreleasing*)error +{ + NSError* localerror = nil; + NSSet* newShares = nil; + + // If any one of our trust states succeed, this function doesn't have an error + for(CKKSPeerProviderState* trustState in trustStates) { + NSError* stateError = nil; + + NSSet* newTrustShares = [self createMissingKeyShares:keyset + peers:trustState + error:&stateError]; + + + if(newTrustShares && !stateError) { + newShares = newShares ? [newShares setByAddingObjectsFromSet:newTrustShares] : newTrustShares; + } else { + ckksnotice("ckksshare", keyset.tlk, "Unable to create shares for trust set %@: %@", trustState, stateError); + if(localerror == nil) { + localerror = stateError; + } + } + } + + // Only report an error if none of the trust states were able to succeed + if(newShares) { + return newShares; + } else { + if(error && localerror) { + *error = localerror; + } + return nil; + } +} + ++ (NSSet*)createMissingKeyShares:(CKKSCurrentKeySet*)keyset + peers:(CKKSPeerProviderState*)trustState + error:(NSError* __autoreleasing*)error +{ + NSError* localerror = nil; + if(![keyset.tlk ensureKeyLoaded:&localerror]) { + ckkserror("ckksshare", keyset.tlk, "TLK not loaded; cannot make shares for peers: %@", localerror); + if(error) { + *error = localerror; + } + return nil; + } + + NSSet>* remainingPeers = [trustState findPeersMissingTLKSharesFor:keyset + error:&localerror]; + if(!remainingPeers) { + ckkserror("ckksshare", keyset.tlk, "Unable to find peers missing TLKShares: %@", localerror); + if(error) { + *error = localerror; + } + return nil; + } + + NSMutableSet* newShares = [NSMutableSet set]; + + for(id peer in remainingPeers) { + if(!peer.publicEncryptionKey) { + ckksnotice("ckksshare", keyset.tlk, "No need to make TLK for %@; they don't have any encryption keys", peer); + continue; + } + + // Create a share for this peer. + ckksnotice("ckksshare", keyset.tlk, "Creating share of %@ as %@ for %@", keyset.tlk, trustState.currentSelfPeers.currentSelf, peer); + CKKSTLKShareRecord* newShare = [CKKSTLKShareRecord share:keyset.tlk + as:trustState.currentSelfPeers.currentSelf + to:peer + epoch:-1 + poisoned:0 + error:&localerror]; + + if(localerror) { + ckkserror("ckksshare", keyset.tlk, "Couldn't create new share for %@: %@", peer, localerror); + if(error) { + *error = localerror; + } + return nil; + } + + [newShares addObject: newShare]; + } + + return newShares; +} + @end; #endif diff --git a/keychain/ckks/CKKSIncomingQueueEntry.h b/keychain/ckks/CKKSIncomingQueueEntry.h index 8d425b21..64e36437 100644 --- a/keychain/ckks/CKKSIncomingQueueEntry.h +++ b/keychain/ckks/CKKSIncomingQueueEntry.h @@ -46,8 +46,9 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype _Nullable)tryFromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (NSArray* _Nullable)fetch:(ssize_t)n - startingAtUUID:(NSString*)uuid + startingAtUUID:(NSString* _Nullable)uuid state:(NSString*)state + action:(NSString* _Nullable)action zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; diff --git a/keychain/ckks/CKKSIncomingQueueEntry.m b/keychain/ckks/CKKSIncomingQueueEntry.m index 3bb5e78d..4e3e51fd 100644 --- a/keychain/ckks/CKKSIncomingQueueEntry.m +++ b/keychain/ckks/CKKSIncomingQueueEntry.m @@ -84,11 +84,13 @@ + (NSArray*)fetch:(ssize_t)n startingAtUUID:(NSString*)uuid state:(NSString*)state + action:(NSString* _Nullable)action zoneID:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { NSMutableDictionary* whereDict = [@{@"state": CKKSNilToNSNull(state), @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} mutableCopy]; + whereDict[@"action"] = action; if(uuid) { - whereDict[@"UUID"] = [CKKSSQLWhereObject op:@">" stringValue:uuid]; + whereDict[@"UUID"] = [CKKSSQLWhereValue op:CKKSSQLWhereComparatorGreaterThan value:uuid]; } return [self fetch:n where:whereDict diff --git a/keychain/ckks/CKKSIncomingQueueOperation.h b/keychain/ckks/CKKSIncomingQueueOperation.h index 8b897285..7c98d518 100644 --- a/keychain/ckks/CKKSIncomingQueueOperation.h +++ b/keychain/ckks/CKKSIncomingQueueOperation.h @@ -24,26 +24,42 @@ #import #import "keychain/ckks/CKKSGroupOperation.h" #if OCTAGON + +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ckks/CKKSMemoryKeyCache.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; @class CKKSItem; -@interface CKKSIncomingQueueOperation : CKKSResultOperation -@property (weak) CKKSKeychainView* ckks; +@interface CKKSIncomingQueueOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; // Set this to true if this instance of CKKSIncomingQueueOperation // should error if it can't process class A items due to the keychain being locked. @property bool errorOnClassAFailure; +// Set this to true if you're pretty sure that the policy set on the CKKS object +// should be considered authoritative, and items that do not match this policy should +// be moved. +@property bool handleMismatchedViewItems; + @property size_t successfulItemsProcessed; @property size_t errorItemsProcessed; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks errorOnClassAFailure:(bool)errorOnClassAFailure; +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intending:(OctagonState*)intending + errorState:(OctagonState*)errorState + errorOnClassAFailure:(bool)errorOnClassAFailure + handleMismatchedViewItems:(bool)handleMismatchedViewItems; // Use this to turn a CKKS item into a keychain dictionary suitable for keychain insertion -+ (NSDictionary* _Nullable)decryptCKKSItemToAttributes:(CKKSItem*)item error:(NSError**)error; ++ (NSDictionary* _Nullable)decryptCKKSItemToAttributes:(CKKSItem*)item + keyCache:(CKKSMemoryKeyCache* _Nullable)keyCache + error:(NSError**)error; @end diff --git a/keychain/ckks/CKKSIncomingQueueOperation.m b/keychain/ckks/CKKSIncomingQueueOperation.m index f53425a1..30450d91 100644 --- a/keychain/ckks/CKKSIncomingQueueOperation.m +++ b/keychain/ckks/CKKSIncomingQueueOperation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2016-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,23 +21,25 @@ * @APPLE_LICENSE_HEADER_END@ */ -#import "CKKSKeychainView.h" -#import "CKKSIncomingQueueOperation.h" -#import "CKKSIncomingQueueEntry.h" -#import "CKKSItemEncrypter.h" -#import "CKKSOutgoingQueueEntry.h" -#import "CKKSKey.h" -#import "CKKSManifest.h" -#import "CKKSAnalytics.h" -#import "CKKSPowerCollection.h" +#import "keychain/analytics/CKKSPowerCollection.h" +#import "keychain/ckks/CKKSAnalytics.h" #import "keychain/ckks/CKKSCurrentItemPointer.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSIncomingQueueOperation.h" +#import "keychain/ckks/CKKSItemEncrypter.h" +#import "keychain/ckks/CKKSKey.h" +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSMemoryKeyCache.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CKKSStates.h" +#import "keychain/ckks/CKKSViewManager.h" +#import "keychain/ckks/CloudKitCategories.h" #import "keychain/ot/ObjCImprovements.h" #include "keychain/securityd/SecItemServer.h" #include "keychain/securityd/SecItemDb.h" #include -#include #import #if OCTAGON @@ -46,127 +48,89 @@ @property bool newOutgoingEntries; @property bool pendingClassAEntries; @property bool missingKey; + +@property NSMutableSet* viewsToScan; @end @implementation CKKSIncomingQueueOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks errorOnClassAFailure:(bool)errorOnClassAFailure { + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intending:(OctagonState*)intending + errorState:(OctagonState*)errorState + errorOnClassAFailure:(bool)errorOnClassAFailure + handleMismatchedViewItems:(bool)handleMismatchedViewItems +{ if(self = [super init]) { - _ckks = ckks; + _deps = dependencies; - // Can't process unless we have a reasonable key hierarchy. - if(ckks.keyStateReadyDependency) { - [self addDependency: ckks.keyStateReadyDependency]; - } - - [self addNullableDependency: ckks.holdIncomingQueueOperation]; + _intendedState = intending; + _nextState = errorState; _errorOnClassAFailure = errorOnClassAFailure; _pendingClassAEntries = false; - [self linearDependencies:ckks.incomingQueueOperations]; + _handleMismatchedViewItems = handleMismatchedViewItems; - if ([CKKSManifest shouldSyncManifests]) { - WEAKIFY(self); - CKKSResultOperation* updateManifestOperation = [CKKSResultOperation operationWithBlock:^{ - STRONGIFY(self); - CKKSKeychainView* strongCKKS = self.ckks; - __block NSError* error = nil; - if (!strongCKKS || !self) { - ckkserror("ckksincoming", strongCKKS, "update manifest operation fired for released object"); - return; - } - - [strongCKKS dispatchSyncWithAccountKeys:^bool{ - strongCKKS.latestManifest = [CKKSManifest latestTrustedManifestForZone:strongCKKS.zoneName error:&error]; - if (error) { - self.error = error; - ckkserror("ckksincoming", strongCKKS, "failed to get latest manifest: %@", error); - return false; - } - else { - return true; - } - }]; - }]; - updateManifestOperation.name = @"update-manifest-operation"; - - [ckks scheduleOperation:updateManifestOperation]; - [self addSuccessDependency:updateManifestOperation]; - } + _viewsToScan = [NSMutableSet set]; } return self; } -- (bool)processNewCurrentItemPointers:(NSArray*)queueEntries withManifest:(CKKSManifest*)manifest egoManifest:(CKKSEgoManifest*)egoManifest +- (bool)processNewCurrentItemPointers:(NSArray*)queueEntries + viewState:(CKKSKeychainViewState*)viewState { - CKKSKeychainView* ckks = self.ckks; - NSError* error = nil; for(CKKSCurrentItemPointer* p in queueEntries) { @autoreleasepool { - if ([CKKSManifest shouldSyncManifests]) { - if (![manifest validateCurrentItem:p withError:&error]) { - ckkserror("ckksincoming", ckks, "Unable to validate current item pointer (%@) against manifest (%@)", p, manifest); - if ([CKKSManifest shouldEnforceManifests]) { - return false; - } - } - } - p.state = SecCKKSProcessedStateLocal; [p saveToDatabase:&error]; - ckksnotice("ckkspointer", ckks, "Saving new current item pointer: %@", p); + ckksnotice("ckkspointer", viewState, "Saving new current item pointer: %@", p); if(error) { - ckkserror("ckksincoming", ckks, "Error saving new current item pointer: %@ %@", error, p); + ckkserror("ckksincoming", viewState, "Error saving new current item pointer: %@ %@", error, p); } - - // Schedule a view change notification - [ckks.notifyViewChangedScheduler trigger]; } } if(queueEntries.count > 0) { - // Schedule a view change notification - [ckks.notifyViewChangedScheduler trigger]; + [viewState.notifyViewChangedScheduler trigger]; } return (error == nil); } -- (bool)processQueueEntries:(NSArray*)queueEntries withManifest:(CKKSManifest*)manifest egoManifest:(CKKSEgoManifest*)egoManifest +- (bool)intransaction:(CKKSKeychainViewState*)viewState processQueueEntries:(NSArray*)queueEntries { - CKKSKeychainView* ckks = self.ckks; - NSMutableArray* newOrChangedRecords = [[NSMutableArray alloc] init]; NSMutableArray* deletedRecordIDs = [[NSMutableArray alloc] init]; + CKKSMemoryKeyCache* keyCache = [[CKKSMemoryKeyCache alloc] init]; + for(id entry in queueEntries) { @autoreleasepool { - if(self.cancelled) { - ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting"); - return false; - } - NSError* error = nil; CKKSIncomingQueueEntry* iqe = (CKKSIncomingQueueEntry*) entry; - ckksnotice("ckksincoming", ckks, "ready to process an incoming queue entry: %@ %@ %@", iqe, iqe.uuid, iqe.action); + ckksnotice("ckksincoming", viewState.zoneID, "ready to process an incoming queue entry: %@ %@ %@", iqe, iqe.uuid, iqe.action); // Note that we currently unencrypt the item before deleting it, instead of just deleting it // This finds the class, which is necessary for the deletion process. We could just try to delete // across all classes, though... - NSDictionary* attributes = [CKKSIncomingQueueOperation decryptCKKSItemToAttributes:iqe.item error:&error]; + NSDictionary* attributes = [CKKSIncomingQueueOperation decryptCKKSItemToAttributes:iqe.item + keyCache:keyCache + error:&error]; if(!attributes || error) { - if([ckks.lockStateTracker isLockedError:error]) { + if([self.deps.lockStateTracker isLockedError:error]) { NSError* localerror = nil; - ckkserror("ckksincoming", ckks, "Keychain is locked; can't decrypt IQE %@", iqe); - CKKSKey* key = [CKKSKey tryFromDatabase:iqe.item.parentKeyUUID zoneID:ckks.zoneID error:&localerror]; + ckkserror("ckksincoming", viewState.zoneID, "Keychain is locked; can't decrypt IQE %@", iqe); + CKKSKey* key = [CKKSKey tryFromDatabase:iqe.item.parentKeyUUID zoneID:viewState.zoneID error:&localerror]; if(localerror || ([key.keyclass isEqualToString:SecCKKSKeyClassA] && self.errorOnClassAFailure)) { self.error = error; } @@ -177,11 +141,12 @@ } } else if ([error.domain isEqualToString:@"securityd"] && error.code == errSecItemNotFound) { - ckkserror("ckksincoming", ckks, "Coudn't find key in keychain; will attempt to poke key hierarchy: %@", error) + ckkserror("ckksincoming", viewState.zoneID, "Coudn't find key in keychain; will attempt to poke key hierarchy: %@", error) self.missingKey = true; + self.error = error; } else { - ckkserror("ckksincoming", ckks, "Couldn't decrypt IQE %@ for some reason: %@", iqe, error); + ckkserror("ckksincoming", viewState.zoneID, "Couldn't decrypt IQE %@ for some reason: %@", iqe, error); self.error = error; } self.errorItemsProcessed += 1; @@ -193,7 +158,7 @@ self.error = [NSError errorWithDomain:@"securityd" code:errSecInternalError userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Item did not have a reasonable class: %@", classStr]}]; - ckkserror("ckksincoming", ckks, "Synced item seems wrong: %@", self.error); + ckkserror("ckksincoming", viewState.zoneID, "Synced item seems wrong: %@", self.error); self.errorItemsProcessed += 1; continue; } @@ -201,75 +166,147 @@ const SecDbClass * classP = !classStr ? NULL : kc_class_with_name((__bridge CFStringRef) classStr); if(!classP) { - ckkserror("ckksincoming", ckks, "unknown class in object: %@ %@", classStr, iqe); + ckkserror("ckksincoming", viewState.zoneID, "unknown class in object: %@ %@", classStr, iqe); iqe.state = SecCKKSStateError; [iqe saveToDatabase:&error]; if(error) { - ckkserror("ckksincoming", ckks, "Couldn't save errored IQE to database: %@", error); + ckkserror("ckksincoming", viewState.zoneID, "Couldn't save errored IQE to database: %@", error); self.error = error; } self.errorItemsProcessed += 1; continue; } - if([iqe.action isEqualToString: SecCKKSActionAdd] || [iqe.action isEqualToString: SecCKKSActionModify]) { - BOOL requireManifestValidation = [CKKSManifest shouldEnforceManifests]; - BOOL manifestValidatesItem = [manifest validateItem:iqe.item withError:&error]; - - if (!requireManifestValidation || manifestValidatesItem) { - [self _onqueueHandleIQEChange: iqe attributes:attributes class:classP]; - [newOrChangedRecords addObject:[iqe.item CKRecordWithZoneID:ckks.zoneID]]; - } - else { - ckkserror("ckksincoming", ckks, "could not validate incoming item against manifest with error: %@", error); - if (![self _onqueueUpdateIQE:iqe withState:SecCKKSStateUnauthenticated error:&error]) { - ckkserror("ckksincoming", ckks, "failed to save incoming item back to database in unauthenticated state with error: %@", error); - return false; - } - self.errorItemsProcessed += 1; - continue; - } - } else if ([iqe.action isEqualToString: SecCKKSActionDelete]) { - BOOL requireManifestValidation = [CKKSManifest shouldEnforceManifests]; - BOOL manifestValidatesDelete = ![manifest itemUUIDExistsInManifest:iqe.uuid]; - - if (!requireManifestValidation || manifestValidatesDelete) { - // if the item does not exist in the latest manifest, we're good to delete it - [self _onqueueHandleIQEDelete: iqe class:classP]; - [deletedRecordIDs addObject:[[CKRecordID alloc] initWithRecordName:iqe.uuid zoneID:ckks.zoneID]]; - } - else { - // if the item DOES exist in the manifest, we can't trust the deletion - ckkserror("ckksincoming", ckks, "could not validate incoming item deletion against manifest"); - if (![self _onqueueUpdateIQE:iqe withState:SecCKKSStateUnauthenticated error:&error]) { - ckkserror("ckksincoming", ckks, "failed to save incoming item deletion back to database in unauthenticated state with error: %@", error); + NSString* intendedView = [self.deps.syncingPolicy mapDictionaryToView:attributes]; + if(![viewState.zoneID.zoneName isEqualToString:intendedView]) { + if(self.handleMismatchedViewItems) { + [self _onqueueHandleMismatchedViewItem:iqe + secDbClass:classP + attributes:attributes + intendedView:intendedView + viewState:viewState + keyCache:keyCache]; + } else { + ckksnotice("ckksincoming", viewState.zoneID, "Received an item (%@), but our current policy claims it should be in view %@", iqe.uuid, intendedView); + [self _onqueueUpdateIQE:iqe withState:SecCKKSStateMismatchedView error:&error]; + if(error) { + ckkserror("ckksincoming", viewState.zoneID, "Couldn't save mismatched IQE to database: %@", error); self.errorItemsProcessed += 1; - return false; + self.error = error; } + + [self.deps.requestPolicyCheck trigger]; } + continue; + } + + if([iqe.action isEqualToString: SecCKKSActionAdd] || [iqe.action isEqualToString: SecCKKSActionModify]) { + [self _onqueueHandleIQEChange:iqe + attributes:attributes + class:classP + viewState:viewState + sortedForThisView:YES + keyCache:keyCache]; + [newOrChangedRecords addObject:[iqe.item CKRecordWithZoneID:viewState.zoneID]]; + + } else if ([iqe.action isEqualToString: SecCKKSActionDelete]) { + [self _onqueueHandleIQEDelete:iqe + class:classP + viewState:viewState]; + [deletedRecordIDs addObject:[[CKRecordID alloc] initWithRecordName:iqe.uuid zoneID:viewState.zoneID]]; } } } if(newOrChangedRecords.count > 0 || deletedRecordIDs > 0) { // Schedule a view change notification - [ckks.notifyViewChangedScheduler trigger]; + [viewState.notifyViewChangedScheduler trigger]; } if(self.missingKey) { - [ckks.pokeKeyStateMachineScheduler trigger]; + // TODO: will be removed when the IncomingQueueOperation is part of the state machine + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; + self.nextState = SecCKKSZoneKeyStateUnhealthy; } - if ([CKKSManifest shouldSyncManifests]) { - [egoManifest updateWithNewOrChangedRecords:newOrChangedRecords deletedRecordIDs:deletedRecordIDs]; - } return true; } -+ (NSDictionary* _Nullable)decryptCKKSItemToAttributes:(CKKSItem*)item error:(NSError**)error +- (void)_onqueueHandleMismatchedViewItem:(CKKSIncomingQueueEntry*)iqe + secDbClass:(const SecDbClass*)secDbClass + attributes:(NSDictionary*)attributes + intendedView:(NSString* _Nullable)intendedView + viewState:(CKKSKeychainViewState*)viewState + keyCache:(CKKSMemoryKeyCache*)keyCache { - NSMutableDictionary* attributes = [[CKKSItemEncrypter decryptItemToDictionary:item error:error] mutableCopy]; + ckksnotice("ckksincoming", viewState.zoneID, "Received an item (%@), which should be in view %@", iqe.uuid, intendedView); + + // Here's the plan: + // + // If this is an add or a modify, we will execute the modification _if we do not currently have this item_. + // Then, ask the view that should handle this item to scan. + // + // When, we will leave the CloudKit record in the existing 'wrong' view. + // This will allow garbage to collect, but should prevent item loss in complicated multi-device scenarios. + // + // If this is a deletion, then we will inspect the other zone's current on-disk state. If it knows about the item, + // we will ignore the deletion from this view. Otherwise, we will proceed with the deletion. + // Note that the deletion approach already ensures that the UUID of the deleted item matches the UUID of the CKRecord. + // This protects against an item being in multiple views, and deleted from only one. + + if([iqe.action isEqualToString:SecCKKSActionAdd] || [iqe.action isEqualToString:SecCKKSActionModify]) { + CFErrorRef cferror = NULL; + SecDbItemRef item = SecDbItemCreateWithAttributes(NULL, secDbClass, (__bridge CFDictionaryRef) attributes, KEYBAG_DEVICE, &cferror); + + if(!item || cferror) { + ckkserror("ckksincoming", viewState.zoneID, "Unable to create SecDbItemRef from IQE: %@", cferror); + return; + } + + [self _onqueueHandleIQEChange:iqe + item:item + viewState:viewState + sortedForThisView:NO + keyCache:keyCache]; + [self.viewsToScan addObject:intendedView]; + + CFReleaseNull(item); + + } else if ([iqe.action isEqualToString:SecCKKSActionDelete]) { + NSError* loadError = nil; + + CKRecordZoneID* otherZoneID = [[CKRecordZoneID alloc] initWithZoneName:intendedView ownerName:CKCurrentUserDefaultName]; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:iqe.uuid zoneID:otherZoneID error:&loadError]; + + if(!ckme || loadError) { + ckksnotice("ckksincoming", viewState.zoneID, "Unable to load CKKSMirrorEntry from database* %@", loadError); + return; + } + + if(ckme) { + ckksnotice("ckksincoming", viewState.zoneID, "Other view (%@) already knows about this item, dropping incoming queue entry: %@", intendedView, ckme); + NSError* saveError = nil; + [iqe deleteFromDatabase:&saveError]; + if(saveError) { + ckkserror("ckksincoming", viewState.zoneID, "Unable to delete IQE: %@", saveError); + } + + } else { + ckksnotice("ckksincoming", viewState.zoneID, "Other view (%@) does not know about this item; processing delete for %@", intendedView, iqe); + [self _onqueueHandleIQEDelete:iqe class:secDbClass viewState:viewState]; + } + + } else { + // We don't recognize this action. Do nothing. + } +} + ++ (NSDictionary* _Nullable)decryptCKKSItemToAttributes:(CKKSItem*)item + keyCache:(CKKSMemoryKeyCache*)keyCache + error:(NSError**)error +{ + NSMutableDictionary* attributes = [[CKKSItemEncrypter decryptItemToDictionary:item keyCache:keyCache error:error] mutableCopy]; if(!attributes) { return nil; } @@ -294,7 +331,9 @@ return attributes; } -- (bool)_onqueueUpdateIQE:(CKKSIncomingQueueEntry*)iqe withState:(NSString*)newState error:(NSError**)error +- (bool)_onqueueUpdateIQE:(CKKSIncomingQueueEntry*)iqe + withState:(NSString*)newState + error:(NSError**)error { if (![iqe.state isEqualToString:newState]) { NSMutableDictionary* oldWhereClause = iqe.whereClauseToFindSelf.mutableCopy; @@ -313,259 +352,366 @@ return true; } -- (void) main { - // Synchronous, on some thread. Get back on the CKKS queue for thread-safety. - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksincoming", ckks, "no CKKS object"); - return; - } - +- (void)main +{ WEAKIFY(self); self.completionBlock = ^(void) { STRONGIFY(self); if (!self) { - ckkserror("ckksincoming", ckks, "received callback for released object"); + ckkserror("ckksincoming", self.deps.zoneID, "received callback for released object"); return; } CKKSAnalytics* logger = [CKKSAnalytics logger]; - if (!self.error) { - [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassC inView:ckks]; - if (!self.pendingClassAEntries) { - [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassA inView:ckks]; + for(CKKSKeychainViewState* viewState in self.deps.zones) { + // This will produce slightly incorrect results when processing multiple zones... + if (!self.error) { + [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassC zoneName:viewState.zoneID.zoneName]; + + if (!self.pendingClassAEntries) { + [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassA zoneName:viewState.zoneID.zoneName]; + } + } else { + [logger logRecoverableError:self.error + forEvent:self.errorOnClassAFailure ? CKKSEventProcessIncomingQueueClassA : CKKSEventProcessIncomingQueueClassC + zoneName:viewState.zoneID.zoneName + withAttributes:NULL]; } - } else { - [logger logRecoverableError:self.error - forEvent:self.errorOnClassAFailure ? CKKSEventProcessIncomingQueueClassA : CKKSEventProcessIncomingQueueClassC - inView:ckks - withAttributes:NULL]; } }; - __block bool errored = false; - [ckks dispatchSync: ^bool{ - if(self.cancelled) { - ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting"); - return false; - } - ckks.lastIncomingQueueOperation = self; + id databaseProvider = self.deps.databaseProvider; - ckksnotice("ckksincoming", ckks, "Processing incoming queue"); - - if ([CKKSManifest shouldSyncManifests]) { - if (!ckks.latestManifest) { - // Until we can make manifests in our unit tests, we can't abort here - ckkserror("ckksincoming", ckks, "no manifest in ckks"); - } - if (!ckks.egoManifest) { - ckkserror("ckksincoming", ckks, "no ego manifest in ckks"); - } + for(CKKSKeychainViewState* viewState in self.deps.zones) { + if(![self.deps.syncingPolicy isSyncingEnabledForView:viewState.zoneName]) { + ckkserror("ckksincoming", viewState, "Item syncing for this view is disabled"); + self.nextState = self.intendedState; + continue; } - bool ok = true; // Should commit transaction? - __block NSError* error = nil; + ckksnotice("ckksincoming", viewState, "Processing incoming queue"); - if ([CKKSManifest shouldSyncManifests]) { - NSInteger unauthenticatedItemCount = [CKKSIncomingQueueEntry countByState:SecCKKSStateUnauthenticated zone:ckks.zoneID error:&error]; - if (error || unauthenticatedItemCount < 0) { - ckkserror("ckksincoming", ckks, "Error fetching incoming queue state counts: %@", error); - self.error = error; - return false; - } + // First, process all item deletions. + // Then, process all modifications and additions. + // Therefore, if there's both a delete and a re-add of a single Primary Key item in the queue, + // we should end up with the item still existing in tthe keychain afterward. + // But, since we're dropping off the queue inbetween, we might accidentally tell our clients that + // their item doesn't exist. Fixing that would take quite a bit of complexity and memory. - // take any existing unauthenticated entries and put them back in the new state - NSArray* unauthenticatedEntries = nil; - NSString* lastMaxUUID = nil; - NSInteger numEntriesProcessed = 0; - while (numEntriesProcessed < unauthenticatedItemCount && (unauthenticatedEntries == nil || unauthenticatedEntries.count == SecCKKSIncomingQueueItemsAtOnce)) { - if(self.cancelled) { - ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting"); - return false; - } - - unauthenticatedEntries = [CKKSIncomingQueueEntry fetch:SecCKKSIncomingQueueItemsAtOnce - startingAtUUID:lastMaxUUID - state:SecCKKSStateUnauthenticated - zoneID:ckks.zoneID - error:&error]; - if (error) { - ckkserror("ckksincoming", ckks, "Error fetching unauthenticated queue records: %@", error); - self.error = error; - return false; - } - - if (unauthenticatedEntries.count == 0) { - ckksinfo("ckksincoming", ckks, "No unauthenticated entries in incoming queue to process"); - break; - } - - for (CKKSIncomingQueueEntry* unauthenticatedEntry in unauthenticatedEntries) { - if (![self _onqueueUpdateIQE:unauthenticatedEntry withState:SecCKKSStateNew error:&error]) { - ckkserror("ckksincoming", ckks, "Error saving unauthenticated entry back to new state: %@", error); - self.error = error; - return false; - } - - lastMaxUUID = ([lastMaxUUID compare:unauthenticatedEntry.uuid] == NSOrderedDescending) ? lastMaxUUID : unauthenticatedEntry.uuid; - } - } + BOOL success = [self loadAndProcessEntries:viewState withActionFilter:SecCKKSActionDelete]; + if(!success) { + ckksnotice("ckksincoming", viewState, "Early-exiting from IncomingQueueOperation (after processing deletes): %@", self.error); + return; } - errored = !ok; - return ok; - }]; - if(errored) { - ckksnotice("ckksincoming", ckks, "Early-exiting from IncomingQueueOperation"); - return; + success = [self loadAndProcessEntries:viewState withActionFilter:nil]; + if(!success) { + ckksnotice("ckksincoming", viewState, "Early-exiting from IncomingQueueOperation (after processing all incoming entries): %@", self.error); + return; + } + + ckksnotice("ckksincoming", viewState, "Processed %lu items in incoming queue (%lu errors)", (unsigned long)self.successfulItemsProcessed, (unsigned long)self.errorItemsProcessed); + + if(![self fixMismatchedViewItems:viewState]) { + ckksnotice("ckksincoming", viewState, "Early-exiting from IncomingQueueOperation due to failure fixing mismatched items"); + return; + } + + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + + NSArray* newCIPs = [CKKSCurrentItemPointer remoteItemPointers:viewState.zoneID error:&error]; + if(error || !newCIPs) { + ckkserror("ckksincoming", viewState, "Could not load remote item pointers: %@", error); + } else { + if (![self processNewCurrentItemPointers:newCIPs viewState:viewState]) { + return CKKSDatabaseTransactionRollback; + } + ckksnotice("ckksincoming", viewState, "Processed %lu items in CIP queue", (unsigned long)newCIPs.count); + } + + return CKKSDatabaseTransactionCommit; + }]; + } + if(self.newOutgoingEntries) { + self.deps.currentOutgoingQueueOperationGroup = [CKOperationGroup CKKSGroupWithName:@"incoming-queue-response"]; + [self.deps.flagHandler handleFlag:CKKSFlagProcessOutgoingQueue]; + } + + if(self.pendingClassAEntries) { + OctagonPendingFlag* whenUnlocked = [[OctagonPendingFlag alloc] initWithFlag:CKKSFlagProcessIncomingQueue + conditions:OctagonPendingConditionsDeviceUnlocked]; + [self.deps.flagHandler handlePendingFlag:whenUnlocked]; + } + + for(NSString* viewName in self.viewsToScan) { + CKKSKeychainView* view = [[CKKSViewManager manager] findView:viewName]; + ckksnotice("ckksincoming", self.deps.zoneID, "Requesting scan for %@ (%@)", view, viewName); + [view scanLocalItems:@"policy-mismatch"]; + } + + self.nextState = self.intendedState; +} + +- (BOOL)loadAndProcessEntries:(CKKSKeychainViewState*)viewState withActionFilter:(NSString* _Nullable)actionFilter +{ + __block bool errored = false; + // Now for the tricky bit: take and drop the account queue for each batch of queue entries // This is for peak memory concerns, but also to allow keychain API clients to make changes while we're processing many items // Note that IncomingQueueOperations are no longer transactional: they can partially succeed. This might make them harder to reason about. __block NSUInteger lastCount = SecCKKSIncomingQueueItemsAtOnce; __block NSString* lastMaxUUID = nil; + id databaseProvider = self.deps.databaseProvider; + while(lastCount == SecCKKSIncomingQueueItemsAtOnce) { - [ckks dispatchSync: ^bool{ + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSArray * queueEntries = nil; if(self.cancelled) { - ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting"); + ckksnotice("ckksincoming", viewState, "CKKSIncomingQueueOperation cancelled, quitting"); errored = true; - return false; + return CKKSDatabaseTransactionRollback; } NSError* error = nil; - queueEntries = [CKKSIncomingQueueEntry fetch: SecCKKSIncomingQueueItemsAtOnce + queueEntries = [CKKSIncomingQueueEntry fetch:SecCKKSIncomingQueueItemsAtOnce startingAtUUID:lastMaxUUID state:SecCKKSStateNew - zoneID:ckks.zoneID - error: &error]; + action:actionFilter + zoneID:viewState.zoneID + error:&error]; if(error != nil) { - ckkserror("ckksincoming", ckks, "Error fetching incoming queue records: %@", error); + ckkserror("ckksincoming", viewState, "Error fetching incoming queue records: %@", error); self.error = error; - errored = true; - return false; + return CKKSDatabaseTransactionRollback; } lastCount = queueEntries.count; if([queueEntries count] == 0) { // Nothing to do! exit. - ckksnotice("ckksincoming", ckks, "Nothing in incoming queue to process"); - return true; + ckksinfo("ckksincoming", viewState, "Nothing in incoming queue to process (filter: %@)", actionFilter); + return CKKSDatabaseTransactionCommit; } - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventOutgoingQueue zone:ckks.zoneName count:[queueEntries count]]; + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventIncommingQueue zone:viewState.zoneID.zoneName count:[queueEntries count]]; - if (![self processQueueEntries:queueEntries withManifest:ckks.latestManifest egoManifest:ckks.egoManifest]) { - ckksnotice("ckksincoming", ckks, "processQueueEntries didn't complete successfully"); + if (![self intransaction:viewState processQueueEntries:queueEntries]) { + ckksnotice("ckksincoming", viewState, "processQueueEntries didn't complete successfully"); errored = true; - return false; + return CKKSDatabaseTransactionRollback; } // Find the highest UUID for the next fetch. for(CKKSIncomingQueueEntry* iqe in queueEntries) { lastMaxUUID = ([lastMaxUUID compare:iqe.uuid] == NSOrderedDescending) ? lastMaxUUID : iqe.uuid; - }; - return true; + } + + return CKKSDatabaseTransactionCommit; }]; if(errored) { - ckksnotice("ckksincoming", ckks, "Early-exiting from IncomingQueueOperation"); - return; + ckksnotice("ckksincoming", viewState, "Early-exiting from IncomingQueueOperation"); + return false; } } - ckksnotice("ckksincoming", ckks, "Processed %lu items in incoming queue (%lu errors)", (unsigned long)self.successfulItemsProcessed, (unsigned long)self.errorItemsProcessed); + return true; +} +- (BOOL)fixMismatchedViewItems:(CKKSKeychainViewState*)viewState +{ + if(!self.handleMismatchedViewItems) { + return YES; + } - [ckks dispatchSync: ^bool{ - NSError* error = nil; + ckksnotice("ckksincoming", viewState, "Handling policy-mismatched items"); + __block NSUInteger lastCount = SecCKKSIncomingQueueItemsAtOnce; + __block NSString* lastMaxUUID = nil; + __block BOOL errored = NO; - NSArray* newCIPs = [CKKSCurrentItemPointer remoteItemPointers:ckks.zoneID error:&error]; - if(error || !newCIPs) { - ckkserror("ckksincoming", ckks, "Could not load remote item pointers: %@", error); - } else { - if (![self processNewCurrentItemPointers:newCIPs withManifest:ckks.latestManifest egoManifest:ckks.egoManifest]) { - return false; + id databaseProvider = self.deps.databaseProvider; + + while(lastCount == SecCKKSIncomingQueueItemsAtOnce) { + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + NSArray* queueEntries = [CKKSIncomingQueueEntry fetch:SecCKKSIncomingQueueItemsAtOnce + startingAtUUID:lastMaxUUID + state:SecCKKSStateMismatchedView + action:nil + zoneID:viewState.zoneID + error:&error]; + if(error) { + ckksnotice("ckksincoming", viewState, "Cannot fetch mismatched view items"); + self.error = error; + errored = true; + return CKKSDatabaseTransactionRollback; } - ckksnotice("ckksincoming", ckks, "Processed %lu items in CIP queue", (unsigned long)newCIPs.count); - } - if(self.newOutgoingEntries) { - // No operation group - [ckks processOutgoingQueue:nil]; - } + lastCount = queueEntries.count; - if(self.pendingClassAEntries) { - [self.ckks processIncomingQueueAfterNextUnlock]; - } + if(queueEntries.count == 0) { + ckksnotice("ckksincoming",viewState, "No mismatched view items"); + return CKKSDatabaseTransactionCommit; + } - return true; - }]; + ckksnotice("ckksincoming", viewState, "Inspecting %lu mismatched items", (unsigned long)queueEntries.count); + + if (![self intransaction:viewState processQueueEntries:queueEntries]) { + ckksnotice("ckksincoming", viewState, "processQueueEntries didn't complete successfully"); + errored = true; + return CKKSDatabaseTransactionRollback; + } + + for(CKKSIncomingQueueEntry* iqe in queueEntries) { + lastMaxUUID = ([lastMaxUUID compare:iqe.uuid] == NSOrderedDescending) ? lastMaxUUID : iqe.uuid; + } + + return CKKSDatabaseTransactionCommit; + }]; + } + + return !errored; } -- (void)_onqueueHandleIQEChange: (CKKSIncomingQueueEntry*) iqe attributes:(NSDictionary*)attributes class:(const SecDbClass *)classP { - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksincoming", ckks, "no CKKS object"); - return; - } +- (void)_onqueueHandleIQEChange:(CKKSIncomingQueueEntry*)iqe + attributes:(NSDictionary*)attributes + class:(const SecDbClass *)classP + viewState:(CKKSKeychainViewState*)viewState + sortedForThisView:(BOOL)sortedForThisView + keyCache:keyCache +{ + __block CFErrorRef cferror = NULL; + SecDbItemRef item = SecDbItemCreateWithAttributes(NULL, classP, (__bridge CFDictionaryRef) attributes, KEYBAG_DEVICE, &cferror); - dispatch_assert_queue(ckks.queue); + if(!item || cferror) { + ckkserror("ckksincoming", viewState.zoneID, "Unable to make SecDbItemRef out of attributes: %@", cferror); + return; + } + CFReleaseNull(cferror); + [self _onqueueHandleIQEChange:iqe + item:item + viewState:viewState + sortedForThisView:sortedForThisView + keyCache:keyCache]; + + CFReleaseNull(item); +} + +- (void)_onqueueHandleIQEChange:(CKKSIncomingQueueEntry*)iqe + item:(SecDbItemRef)item + viewState:(CKKSKeychainViewState*)viewState + sortedForThisView:(BOOL)sortedForThisView + keyCache:(CKKSMemoryKeyCache*)keyCache +{ bool ok = false; __block CFErrorRef cferror = NULL; __block NSError* error = NULL; - SecDbItemRef item = SecDbItemCreateWithAttributes(NULL, classP, (__bridge CFDictionaryRef) attributes, KEYBAG_DEVICE, &cferror); + if(SecDbItemIsTombstone(item)) { + ckkserror("ckksincoming", viewState.zoneID, "Rejecting a tombstone item addition from CKKS(%@): %@", iqe.uuid, item); + + NSError* error = nil; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry withItem:item + action:SecCKKSActionDelete + zoneID:viewState.zoneID + keyCache:keyCache + error:&error]; + [oqe saveToDatabase:&error]; + + if(error) { + ckkserror("ckksincoming", viewState.zoneID, "Unable to save new deletion OQE: %@", error); + } else { + [iqe deleteFromDatabase: &error]; + if(error) { + ckkserror("ckksincoming", viewState.zoneID, "couldn't delete CKKSIncomingQueueEntry: %@", error); + self.error = error; + self.errorItemsProcessed += 1; + } else { + self.successfulItemsProcessed += 1; + } + } + self.newOutgoingEntries = true; + + return; + } __block NSDate* moddate = (__bridge NSDate*) CFDictionaryGetValue(item->attributes, kSecAttrModificationDate); ok = kc_with_dbt(true, &cferror, ^(SecDbConnectionRef dbt){ bool replaceok = SecDbItemInsertOrReplace(item, dbt, &cferror, ^(SecDbItemRef olditem, SecDbItemRef *replace) { - // If the UUIDs do not match, then select the item with the 'lower' UUID, and tell CKKS to + // If the UUIDs do not match, then check to be sure that the local item is known to CKKS. If not, accept the cloud value. + // Otherwise, when the UUIDs do not match, then select the item with the 'lower' UUID, and tell CKKS to // delete the item with the 'higher' UUID. // Otherwise, the cloud wins. - SecADAddValueForScalarKey((__bridge CFStringRef) SecCKKSAggdPrimaryKeyConflict,1); + [SecCoreAnalytics sendEvent:SecCKKSAggdPrimaryKeyConflict event:@{SecCoreAnalyticsValue: @1}]; // Note that SecDbItemInsertOrReplace CFReleases any replace pointer it's given, so, be careful if(!CFDictionaryContainsKey(olditem->attributes, kSecAttrUUID)) { // No UUID -> no good. - ckksnotice("ckksincoming", ckks, "Replacing item (it doesn't have a UUID) for %@", iqe.uuid); + ckksnotice("ckksincoming", viewState.zoneID, "Replacing item (it doesn't have a UUID) for %@", iqe.uuid); if(replace) { *replace = CFRetainSafe(item); } return; } + // If this item arrived in what we believe to be the wrong view, drop the modification entirely. + if(!sortedForThisView) { + ckksnotice("ckksincoming", viewState.zoneID, "Primary key conflict; dropping CK item (arriving from wrong view) %@", item); + return; + } + CFStringRef itemUUID = CFDictionaryGetValue(item->attributes, kSecAttrUUID); CFStringRef olditemUUID = CFDictionaryGetValue(olditem->attributes, kSecAttrUUID); + // Is the old item already somewhere in CKKS? + NSError* ckmeError = nil; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:(__bridge NSString*)olditemUUID + zoneID:viewState.zoneID + error:&ckmeError]; + + if(ckmeError) { + ckksnotice("ckksincoming", viewState.zoneID, "Unable to fetch ckme: %@", ckmeError); + // We'll just have to assume that there is a CKME, and let the comparison analysis below win + } + CFComparisonResult compare = CFStringCompare(itemUUID, olditemUUID, 0); CKKSOutgoingQueueEntry* oqe = nil; - if (compare == kCFCompareGreaterThan) { + if (compare == kCFCompareGreaterThan && (ckme || ckmeError)) { // olditem wins; don't change olditem; delete item - ckksnotice("ckksincoming", ckks, "Primary key conflict; dropping CK item %@", item); - oqe = [CKKSOutgoingQueueEntry withItem:item action:SecCKKSActionDelete ckks:ckks error:&error]; + ckksnotice("ckksincoming", viewState.zoneID, "Primary key conflict; dropping CK item %@", item); + oqe = [CKKSOutgoingQueueEntry withItem:item + action:SecCKKSActionDelete + zoneID:viewState.zoneID + keyCache:keyCache + error:&error]; [oqe saveToDatabase: &error]; self.newOutgoingEntries = true; moddate = nil; } else { - // item wins - ckksnotice("ckksincoming", ckks, "Primary key conflict; replacing %@ with CK item %@", olditem, item); + // item wins, either due to the UUID winning or the item not being in CKKS yet + ckksnotice("ckksincoming", viewState.zoneID, "Primary key conflict; replacing %@%@ with CK item %@", + ckme ? @"" : @"non-onboarded", olditem, item); if(replace) { *replace = CFRetainSafe(item); moddate = (__bridge NSDate*) CFDictionaryGetValue(item->attributes, kSecAttrModificationDate); } // delete olditem if UUID differs (same UUID is the normal update case) if (compare != kCFCompareEqualTo) { - oqe = [CKKSOutgoingQueueEntry withItem:olditem action:SecCKKSActionDelete ckks:ckks error:&error]; + oqe = [CKKSOutgoingQueueEntry withItem:olditem + action:SecCKKSActionDelete + zoneID:viewState.zoneID + keyCache:keyCache + error:&error]; [oqe saveToDatabase: &error]; self.newOutgoingEntries = true; } @@ -580,34 +726,32 @@ return replaceok; }); - CFReleaseNull(item); - if(cferror) { - ckkserror("ckksincoming", ckks, "couldn't process item from IncomingQueue: %@", cferror); + ckkserror("ckksincoming", viewState.zoneID, "couldn't process item from IncomingQueue: %@", cferror); SecTranslateError(&error, cferror); self.error = error; iqe.state = SecCKKSStateError; [iqe saveToDatabase:&error]; if(error) { - ckkserror("ckksincoming", ckks, "Couldn't save errored IQE to database: %@", error); + ckkserror("ckksincoming", viewState.zoneID, "Couldn't save errored IQE to database: %@", error); self.error = error; } return; } if(error) { - ckkserror("ckksincoming", ckks, "Couldn't handle IQE, but why?: %@", error); + ckkserror("ckksincoming", viewState.zoneID, "Couldn't handle IQE, but why?: %@", error); self.error = error; return; } if(ok) { - ckksinfo("ckksincoming", ckks, "Correctly processed an IQE; deleting"); + ckksinfo("ckksincoming", viewState.zoneID, "Correctly processed an IQE; deleting"); [iqe deleteFromDatabase: &error]; if(error) { - ckkserror("ckksincoming", ckks, "couldn't delete CKKSIncomingQueueEntry: %@", error); + ckkserror("ckksincoming", viewState.zoneID, "couldn't delete CKKSIncomingQueueEntry: %@", error); self.error = error; self.errorItemsProcessed += 1; } else { @@ -617,20 +761,20 @@ if(moddate) { // Log the number of ms it took to propagate this change uint64_t delayInMS = [[NSDate date] timeIntervalSinceDate:moddate] * 1000; - [SecCoreAnalytics sendEvent:@"com.apple.ckks.item.propagation" event:@{ + [SecCoreAnalytics sendEvent:@"com.apple.self.deps.item.propagation" event:@{ @"time" : @(delayInMS) }]; } } else { - ckksnotice("ckksincoming", ckks, "IQE not correctly processed, but why? %@ %@", error, cferror); + ckksnotice("ckksincoming", viewState.zoneID, "IQE not correctly processed, but why? %@ %@", error, cferror); self.error = error; iqe.state = SecCKKSStateError; [iqe saveToDatabase:&error]; if(error) { - ckkserror("ckksincoming", ckks, "Couldn't save errored IQE to database: %@", error); + ckkserror("ckksincoming", viewState.zoneID, "Couldn't save errored IQE to database: %@", error); self.error = error; } @@ -638,28 +782,22 @@ } } -- (void)_onqueueHandleIQEDelete: (CKKSIncomingQueueEntry*) iqe class:(const SecDbClass *)classP { - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksincoming", ckks, "no CKKS object"); - return; - } - - dispatch_assert_queue(ckks.queue); - +- (void)_onqueueHandleIQEDelete:(CKKSIncomingQueueEntry*)iqe + class:(const SecDbClass *)classP + viewState:(CKKSKeychainViewState*)viewState +{ bool ok = false; __block CFErrorRef cferror = NULL; NSError* error = NULL; NSDictionary* queryAttributes = @{(__bridge NSString*) kSecClass: (__bridge NSString*) classP->name, (__bridge NSString*) kSecAttrUUID: iqe.uuid, - (__bridge NSString*) kSecAttrSyncViewHint: ckks.zoneID.zoneName, (__bridge NSString*) kSecAttrSynchronizable: @(YES)}; - ckksnotice("ckksincoming", ckks, "trying to delete with query: %@", queryAttributes); - Query *q = query_create_with_limit( (__bridge CFDictionaryRef) queryAttributes, NULL, kSecMatchUnlimited, &cferror); - + ckksnotice("ckksincoming", viewState.zoneID, "trying to delete with query: %@", queryAttributes); + Query *q = query_create_with_limit( (__bridge CFDictionaryRef) queryAttributes, NULL, kSecMatchUnlimited, NULL, &cferror); + q->q_tombstone_use_mdat_from_item = true; if(cferror) { - ckkserror("ckksincoming", ckks, "couldn't create query: %@", cferror); + ckkserror("ckksincoming", viewState.zoneID, "couldn't create query: %@", cferror); SecTranslateError(&error, cferror); self.error = error; return; @@ -671,11 +809,11 @@ if(cferror) { if(CFErrorGetCode(cferror) == errSecItemNotFound) { - ckkserror("ckksincoming", ckks, "couldn't delete item (as it's already gone); this is okay: %@", cferror); + ckkserror("ckksincoming", viewState.zoneID, "couldn't delete item (as it's already gone); this is okay: %@", cferror); ok = true; CFReleaseNull(cferror); } else { - ckkserror("ckksincoming", ckks, "couldn't delete item: %@", cferror); + ckkserror("ckksincoming", viewState.zoneID, "couldn't delete item: %@", cferror); SecTranslateError(&error, cferror); self.error = error; query_destroy(q, NULL); @@ -687,25 +825,25 @@ ok = query_notify_and_destroy(q, ok, &cferror); if(cferror) { - ckkserror("ckksincoming", ckks, "couldn't delete query: %@", cferror); + ckkserror("ckksincoming", viewState.zoneID, "couldn't delete query: %@", cferror); SecTranslateError(&error, cferror); self.error = error; return; } if(ok) { - ckksnotice("ckksincoming", ckks, "Correctly processed an IQE; deleting"); + ckksnotice("ckksincoming", viewState.zoneID, "Correctly processed an IQE; deleting"); [iqe deleteFromDatabase: &error]; if(error) { - ckkserror("ckksincoming", ckks, "couldn't delete CKKSIncomingQueueEntry: %@", error); + ckkserror("ckksincoming", viewState.zoneID, "couldn't delete CKKSIncomingQueueEntry: %@", error); self.error = error; self.errorItemsProcessed += 1; } else { self.successfulItemsProcessed += 1; } } else { - ckkserror("ckksincoming", ckks, "IQE not correctly processed, but why? %@ %@", error, cferror); + ckkserror("ckksincoming", viewState.zoneID, "IQE not correctly processed, but why? %@ %@", error, cferror); self.error = error; self.errorItemsProcessed += 1; } diff --git a/keychain/ckks/CKKSItem.h b/keychain/ckks/CKKSItem.h index 75e0f601..3be817bb 100644 --- a/keychain/ckks/CKKSItem.h +++ b/keychain/ckks/CKKSItem.h @@ -96,6 +96,8 @@ NS_ASSUME_NONNULL_BEGIN // Convenience function: set the upload version for this record to be the current OS version + (void)setOSVersionInRecord:(CKRecord*)record; ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error; ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error; @end diff --git a/keychain/ckks/CKKSItem.m b/keychain/ckks/CKKSItem.m index 445d4898..139555b2 100644 --- a/keychain/ckks/CKKSItem.m +++ b/keychain/ckks/CKKSItem.m @@ -36,6 +36,11 @@ #import #import +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKSMirrorEntry.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" + @implementation CKKSItem - (instancetype) initWithCKRecord: (CKRecord*) record { @@ -178,7 +183,17 @@ plaintextPCSServiceIdentifier: (NSNumber*) pcsServiceIdentifier _uuid = [[record recordID] recordName]; self.parentKeyUUID = [record[SecCKRecordParentKeyRefKey] recordID].recordName; self.encitem = record[SecCKRecordDataKey]; - self.wrappedkey = [[CKKSWrappedAESSIVKey alloc] initWithBase64: record[SecCKRecordWrappedKeyKey]]; + + // If wrapped key is nil, this is a bad record. We've seen this at least once, though, and so need to be resilient to it. + // Passing nil here will cause a crash, so pass all zeroes. + NSString* wrappedKey = record[SecCKRecordWrappedKeyKey]; + if(wrappedKey) { + self.wrappedkey = [[CKKSWrappedAESSIVKey alloc] initWithBase64:wrappedKey]; + } else { + ckkserror("ckksitem", record.recordID.zoneID, "Corrupt item recieved with no wrapped key"); + self.wrappedkey = [CKKSWrappedAESSIVKey zeroedKey]; + } + self.generationCount = [record[SecCKRecordGenerationCountKey] unsignedIntegerValue]; self.encver = [record[SecCKRecordEncryptionVersionKey] unsignedIntegerValue]; @@ -228,27 +243,27 @@ plaintextPCSServiceIdentifier: (NSNumber*) pcsServiceIdentifier // Note that since all of those things are included as authenticated data into the AES-SIV ciphertext, we could just // compare that. However, check 'em all. if(![record.recordID.recordName isEqualToString: self.uuid]) { - secinfo("ckksitem", "UUID does not match"); + ckksinfo_global("ckksitem", "UUID does not match"); return false; } if(![[record[SecCKRecordParentKeyRefKey] recordID].recordName isEqualToString: self.parentKeyUUID]) { - secinfo("ckksitem", "wrapping key reference does not match"); + ckksinfo_global("ckksitem", "wrapping key reference does not match"); return false; } if(![record[SecCKRecordGenerationCountKey] isEqual: [NSNumber numberWithInteger:self.generationCount]]) { - secinfo("ckksitem", "SecCKRecordGenerationCountKey does not match"); + ckksinfo_global("ckksitem", "SecCKRecordGenerationCountKey does not match"); return false; } if(![record[SecCKRecordWrappedKeyKey] isEqual: [self.wrappedkey base64WrappedKey]]) { - secinfo("ckksitem", "SecCKRecordWrappedKeyKey does not match"); + ckksinfo_global("ckksitem", "SecCKRecordWrappedKeyKey does not match"); return false; } if(![record[SecCKRecordDataKey] isEqual: self.encitem]) { - secinfo("ckksitem", "SecCKRecordDataKey does not match"); + ckksinfo_global("ckksitem", "SecCKRecordDataKey does not match"); return false; } @@ -256,19 +271,19 @@ plaintextPCSServiceIdentifier: (NSNumber*) pcsServiceIdentifier // Why is obj-c nullable equality so difficult? if(!((record[SecCKRecordPCSServiceIdentifier] == nil && self.plaintextPCSServiceIdentifier == nil) || [record[SecCKRecordPCSServiceIdentifier] isEqual: self.plaintextPCSServiceIdentifier])) { - secinfo("ckksitem", "SecCKRecordPCSServiceIdentifier does not match"); + ckksinfo_global("ckksitem", "SecCKRecordPCSServiceIdentifier does not match"); return false; } if(!((record[SecCKRecordPCSPublicKey] == nil && self.plaintextPCSPublicKey == nil) || [record[SecCKRecordPCSPublicKey] isEqual: self.plaintextPCSPublicKey])) { - secinfo("ckksitem", "SecCKRecordPCSPublicKey does not match"); + ckksinfo_global("ckksitem", "SecCKRecordPCSPublicKey does not match"); return false; } if(!((record[SecCKRecordPCSPublicIdentity] == nil && self.plaintextPCSPublicIdentity == nil) || [record[SecCKRecordPCSPublicIdentity] isEqual: self.plaintextPCSPublicIdentity])) { - secinfo("ckksitem", "SecCKRecordPCSPublicIdentity does not match"); + ckksinfo_global("ckksitem", "SecCKRecordPCSPublicIdentity does not match"); return false; } @@ -457,6 +472,181 @@ plaintextPCSServiceIdentifier: (NSNumber*) pcsServiceIdentifier ]; } ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error +{ + NSError* localerror = nil; + // Find if we knew about this record in the past + bool update = false; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:[[record recordID] recordName] + zoneID:record.recordID.zoneID + error:&localerror]; + + if(localerror) { + ckkserror("ckks", record.recordID.zoneID, "error loading a CKKSMirrorEntry from database: %@", localerror); + if(error) { + *error = localerror; + } + return NO; + } + + if(resync) { + if(!ckme) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: No local item matching resynced CloudKit record: %@", record); + } else if(![ckme matchesCKRecord:record]) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: Local item doesn't match resynced CloudKit record: %@ %@", ckme, record); + } else { + ckksnotice("ckksresync", record.recordID.zoneID, "Already know about this item record, updating anyway: %@", record.recordID); + } + } + + if(ckme && ckme.item && ckme.item.generationCount > [record[SecCKRecordGenerationCountKey] unsignedLongLongValue]) { + ckkserror("ckks", record.recordID.zoneID, "received a record from CloudKit with a bad generation count: %@ (%ld > %@)", ckme.uuid, + (long) ckme.item.generationCount, + record[SecCKRecordGenerationCountKey]); + + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSErrorGenerationCountMismatch + description:[NSString stringWithFormat:@"Received a record(%@) with a bad generation count (%ld > %@)", + ckme.uuid, + (long) ckme.item.generationCount, + record[SecCKRecordGenerationCountKey]]]; + } + // Abort processing this record. + return NO; + } + + // If we found an old version in the database; this might be an update + if(ckme) { + if([ckme matchesCKRecord:record] && !resync) { + // This is almost certainly a record we uploaded; CKFetchChanges sends them back as new records + ckksnotice("ckks", record.recordID.zoneID, "CloudKit has told us of record we already know about for %@; skipping update", ckme.uuid); + return YES; + } + + update = true; + // Set the CKKSMirrorEntry's fields to be whatever this record holds + [ckme setFromCKRecord: record]; + } else { + // Have to make a new CKKSMirrorEntry + ckme = [[CKKSMirrorEntry alloc] initWithCKRecord:record]; + } + + bool mirrorsaved = [ckme saveToDatabase:&localerror]; + + if(!mirrorsaved || localerror) { + ckkserror("ckks", record.recordID.zoneID, "couldn't save new CKRecord to database: %@ %@", record, localerror); + if(error) { + *error = localerror; + } + return NO; + } else { + ckksinfo("ckks", record.recordID.zoneID, "CKKSMirrorEntry was created: %@", ckme); + } + + NSError* iqeerror = nil; + CKKSIncomingQueueEntry* iqe = [[CKKSIncomingQueueEntry alloc] initWithCKKSItem:ckme.item + action:(update ? SecCKKSActionModify : SecCKKSActionAdd) + state:SecCKKSStateNew]; + bool iqesaved = [iqe saveToDatabase:&iqeerror]; + if(!iqesaved || iqeerror) { + ckkserror("ckks", record.recordID.zoneID, "Couldn't save modified incoming queue entry: %@", iqeerror); + if(error) { + *error = iqeerror; + } + return NO; + } else { + ckksinfo("ckks", record.recordID.zoneID, "CKKSIncomingQueueEntry was created: %@", iqe); + } + + // A remote change has occured for this record. Delete any pending local changes; they will be overwritten. + NSArray* siblings = [CKKSOutgoingQueueEntry allWithUUID:iqe.uuid + states:@[SecCKKSStateNew, + SecCKKSStateReencrypt, + SecCKKSStateError] + zoneID:record.recordID.zoneID + error:&localerror]; + if(!siblings || localerror) { + ckkserror("ckks", record.recordID.zoneID, "Couldn't load OQE sibling for %@: %@", iqe.uuid, localerror); + } + + for(CKKSOutgoingQueueEntry* oqe in siblings) { + NSError* deletionError = nil; + [oqe deleteFromDatabase:&deletionError]; + if(deletionError) { + ckkserror("ckks", record.recordID.zoneID, "Couldn't delete OQE sibling(%@) for %@: %@", oqe, iqe.uuid, deletionError); + if(error) { + *error = deletionError; + } + return NO; + } + } + + return YES; +} + + ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error +{ + ckksnotice("ckks", recordID.zoneID, "CloudKit notification: deleted record(%@): %@", SecCKRecordItemType, recordID); + NSError* iqeerror = nil; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:recordID.recordName + zoneID:recordID.zoneID + error:error]; + + // Deletes always succeed, not matter the generation count + if(ckme) { + NSError* localerror = nil; + if(![ckme deleteFromDatabase:&localerror]) { + if(error) { + *error = localerror; + } + return NO; + } + + CKKSIncomingQueueEntry* iqe = [[CKKSIncomingQueueEntry alloc] initWithCKKSItem:ckme.item action:SecCKKSActionDelete state:SecCKKSStateNew]; + [iqe saveToDatabase:&iqeerror]; + if(iqeerror) { + ckkserror("ckks", recordID.zoneID, "Couldn't save incoming queue entry: %@", iqeerror); + if(error) { + *error = iqeerror; + } + return NO; + } + + // Delete any pending local changes; this delete wins + NSError* deleteError = nil; + NSArray* siblings = [CKKSOutgoingQueueEntry allWithUUID:iqe.uuid + states:@[SecCKKSStateNew, + SecCKKSStateReencrypt, + SecCKKSStateError] + zoneID:recordID.zoneID + error:&deleteError]; + if(deleteError) { + ckkserror("ckks", recordID.zoneID, "Couldn't load OQE sibling for %@: %@", iqe.uuid, deleteError); + if(error) { + *error = deleteError; + } + return NO; + } + + for(CKKSOutgoingQueueEntry* oqe in siblings) { + NSError* deletionError = nil; + [oqe deleteFromDatabase:&deletionError]; + if(deletionError) { + ckkserror("ckks", recordID.zoneID, "Couldn't delete OQE sibling(%@) for %@: %@", oqe, iqe.uuid, deletionError); + if(error) { + *error = deletionError; + } + return NO; + } + } + } + ckksinfo("ckks", recordID.zoneID, "CKKSMirrorEntry was deleted: %@ %@", recordID, ckme); + return YES; +} + + @end #pragma mark - CK-Aware Database Helpers diff --git a/keychain/ckks/CKKSItemEncrypter.h b/keychain/ckks/CKKSItemEncrypter.h index 0780da11..c5317d89 100644 --- a/keychain/ckks/CKKSItemEncrypter.h +++ b/keychain/ckks/CKKSItemEncrypter.h @@ -28,6 +28,7 @@ @class CKKSItem; @class CKKSMirrorEntry; @class CKKSKey; +@class CKKSMemoryKeyCache; @class CKKSOutgoingQueueEntry; @class CKKSAESSIVKey; @class CKRecordZoneID; @@ -42,9 +43,12 @@ NS_ASSUME_NONNULL_BEGIN dataDictionary:(NSDictionary*)dict updatingCKKSItem:(CKKSItem* _Nullable)olditem parentkey:(CKKSKey*)parentkey + keyCache:(CKKSMemoryKeyCache* _Nullable)keyCache error:(NSError* _Nullable __autoreleasing* _Nullable)error; -+ (NSDictionary* _Nullable)decryptItemToDictionary:(CKKSItem*)item error:(NSError* _Nullable __autoreleasing* _Nullable)error; ++ (NSDictionary* _Nullable)decryptItemToDictionary:(CKKSItem*)item + keyCache:(CKKSMemoryKeyCache* _Nullable)keyCache + error:(NSError* _Nullable __autoreleasing* _Nullable)error; + (NSData* _Nullable)encryptDictionary:(NSDictionary*)dict key:(CKKSAESSIVKey*)key diff --git a/keychain/ckks/CKKSItemEncrypter.m b/keychain/ckks/CKKSItemEncrypter.m index 90810cef..d6f59971 100644 --- a/keychain/ckks/CKKSItemEncrypter.m +++ b/keychain/ckks/CKKSItemEncrypter.m @@ -76,19 +76,20 @@ return nil; } -+(CKKSItem*)encryptCKKSItem:(CKKSItem*)baseitem - dataDictionary:(NSDictionary *)dict - updatingCKKSItem:(CKKSItem*)olditem - parentkey:(CKKSKey *)parentkey - error:(NSError * __autoreleasing *) error ++ (CKKSItem*)encryptCKKSItem:(CKKSItem*)baseitem + dataDictionary:(NSDictionary *)dict + updatingCKKSItem:(CKKSItem*)olditem + parentkey:(CKKSKey *)parentkey + keyCache:(CKKSMemoryKeyCache* _Nullable)keyCache + error:(NSError * __autoreleasing *) error { CKKSKey *itemkey = nil; // If we're updating a CKKSItem, extract its dictionary and overlay our new one on top if(olditem) { - NSMutableDictionary* oldDictionary = [[CKKSItemEncrypter decryptItemToDictionary: olditem error:error] mutableCopy]; + NSMutableDictionary* oldDictionary = [[CKKSItemEncrypter decryptItemToDictionary:olditem keyCache:keyCache error:error] mutableCopy]; if(!oldDictionary) { - secerror("Couldn't decrypt old CKMirror entry: %@", (error ? *error : @"null error passed in")); + ckkserror("ckme", olditem.zoneID, "Couldn't decrypt old CKMirror entry: %@", (error ? *error : @"null error passed in")); return nil; } @@ -123,7 +124,7 @@ NSDictionary* authenticatedData = [encryptedItem makeAuthenticatedDataDictionaryUpdatingCKKSItem: olditem encryptionVersion:encryptedItem.encver]; - encryptedItem.encitem = [self encryptDictionary: dict key:itemkey.aessivkey authenticatedData:authenticatedData error:error]; + encryptedItem.encitem = [CKKSItemEncrypter encryptDictionary: dict key:itemkey.aessivkey authenticatedData:authenticatedData error:error]; if(!encryptedItem.encitem) { return nil; } @@ -139,12 +140,21 @@ } // Note that the only difference between v1 and v2 is the authenticated data selection, so we can happily pass encver along -+ (NSDictionary*) decryptItemToDictionaryVersion1or2: (CKKSItem*) item error: (NSError * __autoreleasing *) error { ++ (NSDictionary*)decryptItemToDictionaryVersion1or2:(CKKSItem*)item + keyCache:(CKKSMemoryKeyCache* _Nullable)keyCache + error:(NSError * __autoreleasing *)error +{ NSDictionary* authenticatedData = nil; CKKSAESSIVKey* itemkey = nil; + CKKSKey* key = nil; + + if(keyCache) { + key = [keyCache loadKeyForUUID:item.parentKeyUUID zoneID:item.zoneID error:error]; + } else { + key = [CKKSKey loadKeyWithUUID:item.parentKeyUUID zoneID:item.zoneID error:error]; + } - CKKSKey* key = [CKKSKey loadKeyWithUUID: item.parentKeyUUID zoneID:item.zoneID error:error]; if(!key) { return nil; } @@ -159,17 +169,20 @@ NSDictionary* result = [self decryptDictionary: item.encitem key:itemkey authenticatedData:authenticatedData error:error]; if(!result) { - secwarning("ckks: couldn't decrypt item %@", *error); + ckkserror("item", item.zoneID, "ckks: couldn't decrypt item %@", *error); } return result; } -+ (NSDictionary*) decryptItemToDictionary: (CKKSItem*) item error: (NSError * __autoreleasing *) error { ++ (NSDictionary*)decryptItemToDictionary:(CKKSItem*) item + keyCache:(CKKSMemoryKeyCache* _Nullable)keyCache + error:(NSError * __autoreleasing *)error +{ switch (item.encver) { case CKKSItemEncryptionVersion1: - return [CKKSItemEncrypter decryptItemToDictionaryVersion1or2:item error:error]; + return [CKKSItemEncrypter decryptItemToDictionaryVersion1or2:item keyCache:keyCache error:error]; case CKKSItemEncryptionVersion2: - return [CKKSItemEncrypter decryptItemToDictionaryVersion1or2:item error:error]; + return [CKKSItemEncrypter decryptItemToDictionaryVersion1or2:item keyCache:keyCache error:error]; case CKKSItemEncryptionVersionNone: /* version 0 was no encrypted, no longer supported */ default: { @@ -177,7 +190,7 @@ code:1 userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Unrecognized encryption version: %lu", (unsigned long)item.encver]}]; - secerror("decryptItemToDictionary %@", localError); + ckkserror("item", item.zoneID, "decryptItemToDictionary failed: %@", localError); if (error) { *error = localError; } @@ -186,7 +199,11 @@ } } -+ (NSData*)encryptDictionary: (NSDictionary*) dict key: (CKKSAESSIVKey*) key authenticatedData: (NSDictionary*) ad error: (NSError * __autoreleasing *) error { ++ (NSData*)encryptDictionary:(NSDictionary*)dict + key:(CKKSAESSIVKey*)key + authenticatedData:(NSDictionary*)ad + error:(NSError * __autoreleasing *)error +{ NSData* data = [NSPropertyListSerialization dataWithPropertyList:dict format:NSPropertyListBinaryFormat_v1_0 options:0 diff --git a/keychain/ckks/CKKSKey.h b/keychain/ckks/CKKSKey.h index 766e5479..39631a06 100644 --- a/keychain/ckks/CKKSKey.h +++ b/keychain/ckks/CKKSKey.h @@ -34,6 +34,8 @@ NS_ASSUME_NONNULL_BEGIN +@class CKKSPeerProviderState; + @interface CKKSKey : CKKSCKRecordHolder @property CKKSKeychainBackedKey* keycore; @@ -47,6 +49,8 @@ NS_ASSUME_NONNULL_BEGIN @property (copy) CKKSProcessedState* state; @property bool currentkey; +@property (readonly) NSString* zoneName; + // Fetches and attempts to unwrap this key for use + (instancetype _Nullable)loadKeyWithUUID:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; @@ -78,7 +82,19 @@ NS_ASSUME_NONNULL_BEGIN error:(NSError* __autoreleasing*)error; +// Returns false if this key is not a valid TLK for any reason. +- (BOOL)validTLK:(NSError**)error; + +// First, attempts to load the key from the keychain. If it isn't present, this will +// load the TLKShares for this key from the database, then attempts to use them to unwrap this key. +// If no TLKShares are trusted, returns an error. +- (BOOL)tlkMaterialPresentOrRecoverableViaTLKShare:(NSArray*)trustStates + error:(NSError**)error; + + (instancetype _Nullable)fromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; ++ (instancetype _Nullable)fromDatabaseAnyState:(NSString*)uuid + zoneID:(CKRecordZoneID*)zoneID + error:(NSError* __autoreleasing*)error; + (instancetype _Nullable)tryFromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (instancetype _Nullable)tryFromDatabaseAnyState:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; @@ -132,10 +148,10 @@ NS_ASSUME_NONNULL_BEGIN - (CKKSKey* _Nullable)topKeyInAnyState:(NSError* __autoreleasing*)error; // Attempts checks if the AES key is already loaded, or attempts to load it from the keychain. Returns false if it fails. -- (CKKSAESSIVKey*)ensureKeyLoaded:(NSError* __autoreleasing*)error; +- (CKKSAESSIVKey* _Nullable)ensureKeyLoaded:(NSError* __autoreleasing*)error; // Attempts to unwrap this key via unwrapping its wrapping keys via the key hierarchy. -- (CKKSAESSIVKey*)unwrapViaKeyHierarchy:(NSError* __autoreleasing*)error; +- (CKKSAESSIVKey* _Nullable)unwrapViaKeyHierarchy:(NSError* __autoreleasing*)error; // On a self-wrapped key, determine if this AES-SIV key is the self-wrapped key. // If it is, save the key as this CKKSKey's unwrapped key. @@ -156,7 +172,13 @@ NS_ASSUME_NONNULL_BEGIN - (NSData* _Nullable)serializeAsProtobuf:(NSError* __autoreleasing*)error; + (CKKSKey* _Nullable)loadFromProtobuf:(NSData*)data error:(NSError* __autoreleasing*)error; ++ (NSNumber* _Nullable)counts:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (NSDictionary*)countsByClass:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + ++ (BOOL)intransactionRecordChanged:(CKRecord*)record + resync:(BOOL)resync + flagHandler:(id)flagHandler + error:(NSError**)error; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSKey.m b/keychain/ckks/CKKSKey.m index 10e88f36..62502e97 100644 --- a/keychain/ckks/CKKSKey.m +++ b/keychain/ckks/CKKSKey.m @@ -27,6 +27,8 @@ #import "CKKSKeychainView.h" #import "CKKSCurrentKeyPointer.h" #import "CKKSKey.h" +#import "keychain/ckks/CKKSPeerProvider.h" +#import "keychain/ckks/CKKSStates.h" #import "keychain/categories/NSError+UsefulConstructors.h" #include "keychain/securityd/SecItemSchema.h" #include @@ -41,7 +43,8 @@ @implementation CKKSKey - (instancetype)init { - self = [super init]; + if ((self = [super init])) { + } return self; } @@ -155,6 +158,11 @@ return self.keycore.uuid; } +- (NSString*)zoneName +{ + return self.keycore.zoneID.zoneName; +} + - (void)setUuid:(NSString *)uuid { self.keycore.uuid = uuid; @@ -265,9 +273,11 @@ // Check for circular references. if([seenUUID containsObject:key.uuid]) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSCircularKeyReference - description:@"Circular reference in key hierarchy"]; + if (error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSCircularKeyReference + description:@"Circular reference in key hierarchy"]; + } return nil; } @@ -302,7 +312,7 @@ // Attempt to save this new key, but don't error if it fails NSError* resaveError = nil; if(![self saveKeyMaterialToKeychain:&resaveError] || resaveError) { - secerror("ckkskey: Resaving missing key failed, continuing: %@", resaveError); + ckkserror("ckkskey", self.zoneID, "Resaving missing key failed, continuing: %@", resaveError); } return self.aessivkey; @@ -352,6 +362,130 @@ return self.aessivkey; } +- (BOOL)unwrapViaTLKSharesTrustedBy:(NSArray*)trustStates + error:(NSError**)error +{ + NSError* localerror = nil; + + if(trustStates.count == 0u) { + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSLackingTrust + description:@"No current trust states; can't unwrap TLK"]; + } + return NO; + } + + NSArray* possibleShares = [CKKSTLKShareRecord allForUUID:self.uuid + zoneID:self.zoneID + error:&localerror]; + + if(!possibleShares || localerror) { + ckkserror("ckksshare", self, "Unable to load TLK shares for TLK(%@): %@", self, localerror); + if(error) { + *error = localerror; + } + return NO; + } + + NSError* lastTrustStateError = nil; + for(CKKSPeerProviderState* trustState in trustStates) { + BOOL extracted = [trustState unwrapKey:self + fromShares:possibleShares + error:&localerror]; + + if(!extracted || localerror) { + ckkserror("ckksshare", self, "Failed to recover tlk (%@) from trust state (%@): %@", self.uuid, trustState, localerror); + lastTrustStateError = localerror; + localerror = nil; + } else { + ckkserror("ckksshare", self, "Recovered tlk (%@) from trust state (%@)", self.uuid, trustState); + return YES; + } + } + + // Because there's at least one trustState, then either we returned the TLK above, or we filled in lastTrustStateError. + if(error) { + *error = lastTrustStateError; + } + + return NO; +} + +- (BOOL)validTLK:(NSError**)error +{ + if(![self wrapsSelf]) { + NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSKeyNotSelfWrapped + description:[NSString stringWithFormat:@"Potential TLK %@ doesn't wrap itself: %@", + self, + self.parentKeyUUID] + underlying:NULL]; + ckkserror("ckksshare", self, "Error with TLK: %@", localerror); + if (error) { + *error = localerror; + } + return NO; + } + + return YES; +} + +- (BOOL)tlkMaterialPresentOrRecoverableViaTLKShare:(NSArray*)trustStates + error:(NSError**)error +{ + // If we have the key material, then this TLK is considered valid. + NSError* loadError = nil; + CKKSAESSIVKey* loadedKey = [self ensureKeyLoaded:&loadError]; + if(!loadedKey || loadError) { + if(loadError.code == errSecInteractionNotAllowed) { + ckkserror("ckksshare", self, "Unable to load key due to lock state: %@", loadError); + if(error) { + *error = loadError; + } + + return NO; + } + + ckkserror("ckksshare", self, "Do not yet have this key in the keychain: %@", loadError); + // Fall through to attempt to recover the TLK via shares below + } else { + bool result = [self trySelfWrappedKeyCandidate:loadedKey error:&loadError]; + if(result) { + // We have a key, and it can decrypt itself. + return YES; + } else { + ckkserror("ckksshare", self, "Some key is present, but the key is not self-wrapped: %@", loadError); + // Key seems broken. Fall through. + } + } + + NSError* localerror = nil; + BOOL success = [self unwrapViaTLKSharesTrustedBy:trustStates + error:&localerror]; + + if(!success || localerror) { + ckkserror("ckksshare", self, "Failed to unwrap tlk(%@) via shares: %@", self.uuid, localerror); + if(error) { + *error = localerror; + } + return NO; + } + + success = [self saveKeyMaterialToKeychain:true error:&localerror]; + + if(!success || localerror) { + ckkserror("ckksshare", self, "Errored saving TLK to keychain: %@", localerror); + + if(error) { + *error = localerror; + return NO; + } + } + + return YES; +} + - (bool)trySelfWrappedKeyCandidate:(CKKSAESSIVKey*)candidate error:(NSError * __autoreleasing *) error { return [self.keycore trySelfWrappedKeyCandidate:candidate error:error]; } @@ -459,7 +593,11 @@ } + (NSArray*)selfWrappedKeys:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { - return [self allWhere: @{@"UUID": [CKKSSQLWhereObject op:@"=" string:@"parentKeyUUID"], @"state": SecCKKSProcessedStateLocal, @"ckzone":zoneID.zoneName} error:error]; + return [self allWhere: @{@"UUID": [CKKSSQLWhereColumn op:CKKSSQLWhereComparatorEquals + column:CKKSSQLWhereColumnNameParentKeyUUID], + @"state": SecCKKSProcessedStateLocal, + @"ckzone":zoneID.zoneName} + error:error]; } + (instancetype _Nullable)currentKeyForClass:(CKKSKeyClass*)keyclass @@ -588,31 +726,31 @@ } if(![record.recordID.recordName isEqualToString: self.uuid]) { - secinfo("ckkskey", "UUID does not match"); + ckksinfo_global("ckkskey", "UUID does not match"); return false; } // For the parent key ref, ensure that if it's nil, we wrap ourself if(record[SecCKRecordParentKeyRefKey] == nil) { if(![self wrapsSelf]) { - secinfo("ckkskey", "wrapping key reference (self-wrapped) does not match"); + ckksinfo_global("ckkskey", "wrapping key reference (self-wrapped) does not match"); return false; } } else { if(![[[record[SecCKRecordParentKeyRefKey] recordID] recordName] isEqualToString: self.parentKeyUUID]) { - secinfo("ckkskey", "wrapping key reference (non-self-wrapped) does not match"); + ckksinfo_global("ckkskey", "wrapping key reference (non-self-wrapped) does not match"); return false; } } if(![record[SecCKRecordKeyClassKey] isEqual: self.keyclass]) { - secinfo("ckkskey", "key class does not match"); + ckksinfo_global("ckkskey", "key class does not match"); return false; } if(![record[SecCKRecordWrappedKeyKey] isEqual: [self.wrappedkey base64WrappedKey]]) { - secinfo("ckkskey", "wrapped key does not match"); + ckksinfo_global("ckkskey", "wrapped key does not match"); return false; } @@ -669,6 +807,23 @@ } ++ (NSNumber* _Nullable)counts:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error +{ + __block NSNumber *result = nil; + + [CKKSSQLDatabaseObject queryDatabaseTable:[[self class] sqlTable] + where:@{@"ckzone": CKKSNilToNSNull(zoneID.zoneName)} + columns:@[@"count(rowid)"] + groupBy:nil + orderBy:nil + limit:-1 + processRow:^(NSDictionary* row) { + result = row[@"count(rowid)"].asNSNumberInteger; + } + error: error]; + return result; +} + + (NSDictionary*)countsByClass:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { NSMutableDictionary* results = [[NSMutableDictionary alloc] init]; @@ -728,6 +883,79 @@ return nil; } + ++ (BOOL)intransactionRecordChanged:(CKRecord*)record + resync:(BOOL)resync + flagHandler:(id)flagHandler + error:(NSError**)error +{ + NSError* localerror = nil; + + if(resync) { + NSError* resyncerror = nil; + + CKKSKey* key = [CKKSKey tryFromDatabaseAnyState:record.recordID.recordName zoneID:record.recordID.zoneID error:&resyncerror]; + if(resyncerror) { + ckkserror("ckksresync", record.recordID.zoneID, "error loading key: %@", resyncerror); + } + if(!key) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: No sync key matching resynced CloudKit record: %@", record); + } else if(![key matchesCKRecord:record]) { + ckkserror("ckksresync", record.recordID.zoneID, "BUG: Local sync key doesn't match resynced CloudKit record(s): %@ %@", key, record); + } else { + ckksnotice("ckksresync", record.recordID.zoneID, "Already know about this sync key, skipping update: %@", record); + return YES; + } + } + + CKKSKey* remotekey = [[CKKSKey alloc] initWithCKRecord:record]; + + // Do we already know about this key? + CKKSKey* possibleLocalKey = [CKKSKey tryFromDatabase:remotekey.uuid + zoneID:record.recordID.zoneID + error:&localerror]; + if(localerror) { + ckkserror("ckkskey", record.recordID.zoneID, "Error finding existing local key for %@: %@", remotekey, localerror); + // Go on, assuming there isn't a local key + + localerror = nil; + } else if(possibleLocalKey && [possibleLocalKey matchesCKRecord:record]) { + // Okay, nothing new here. Update the CKRecord and move on. + // Note: If the new record doesn't match the local copy, we have to go through the whole dance below + possibleLocalKey.storedCKRecord = record; + bool newKeySaved = [possibleLocalKey saveToDatabase:&localerror]; + + if(!newKeySaved || localerror) { + ckkserror("ckkskey", record.recordID.zoneID, "Couldn't update existing key: %@: %@", possibleLocalKey, localerror); + if(error) { + *error = localerror; + } + return NO; + } + return YES; + } + + // Drop into the synckeys table as a 'remote' key, then ask for a rekey operation. + remotekey.state = SecCKKSProcessedStateRemote; + remotekey.currentkey = false; + + bool remoteKeySaved = [remotekey saveToDatabase:&localerror]; + if(!remoteKeySaved || localerror) { + ckkserror("ckkskey", record.recordID.zoneID, "Couldn't save key record to database: %@: %@", remotekey, localerror); + ckksinfo("ckkskey", record.recordID.zoneID, "CKRecord was %@", record); + + if(error) { + *error = localerror; + } + return NO; + } + + // We've saved a new key in the database; trigger a rekey operation. + [flagHandler _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; + + return YES; +} + @end #endif // OCTAGON diff --git a/keychain/ckks/CKKSKeychainBackedKey.m b/keychain/ckks/CKKSKeychainBackedKey.m index 8552ee42..eca829c6 100644 --- a/keychain/ckks/CKKSKeychainBackedKey.m +++ b/keychain/ckks/CKKSKeychainBackedKey.m @@ -31,7 +31,7 @@ NSError* error = nil; [self wrapUnder:self error:&error]; if(error != nil) { - secerror("CKKSKeychainBackedKey: Couldn't self-wrap key: %@", error); + ckkserror_global("ckkskey", "Couldn't self-wrap key: %@", error); return nil; } } @@ -55,7 +55,7 @@ NSError* error = nil; [self wrapUnder:wrappingKey error:&error]; if(error != nil) { - secerror("CKKSKeychainBackedKey: Couldn't wrap key with key: %@", error); + ckkserror_global("ckkskey", "Couldn't wrap key with key: %@", error); return nil; } } @@ -118,16 +118,18 @@ error:(NSError* __autoreleasing*)error { NSError* localError = nil; - self.wrappedkey = [wrappingKey wrapAESKey:self.aessivkey error:&localError]; - if(self.wrappedkey == nil) { - secerror("CKKSKeychainBackedKey: couldn't wrap key: %@", localError); + CKKSWrappedAESSIVKey* wrappedKey = [wrappingKey wrapAESKey:self.aessivkey error:&localError]; + if (wrappedKey == nil) { + ckkserror_global("ckkskey", "couldn't wrap key: %@", localError); if(error) { *error = localError; } + return false; } else { + self.wrappedkey = wrappedKey; self.parentKeyUUID = wrappingKey.uuid; } - return (self.wrappedkey != nil); + return true; } - (bool)unwrapSelfWithAESKey:(CKKSAESSIVKey*)unwrappingKey @@ -335,7 +337,7 @@ [CKKSKeychainBackedKey setKeyMaterialInKeychain:query error:&localError]; if(stashError) { - secerror("CKKSKeychainBackedKey: Couldn't stash %@ to keychain: %@", self, stashError); + ckkserror_global("ckkskey", "Couldn't stash %@ to keychain: %@", self, stashError); } } @@ -481,7 +483,7 @@ result = [self queryKeyMaterialInKeychain:query error:&localError]; if(localError == nil) { - secnotice("CKKSKeychainBackedKey", "loaded a piggy TLK (%@)", key.uuid); + ckksnotice_global("ckkskey", "loaded a piggy TLK (%@)", key.uuid); if(resavePtr) { *resavePtr = true; @@ -527,7 +529,7 @@ result = [self queryKeyMaterialInKeychain:query error:&localError]; if(localError == nil) { - secnotice("CKKSKeychainBackedKey", "loaded a stashed TLK (%@)", key.uuid); + ckksnotice_global("ckkskey", "loaded a stashed TLK (%@)", key.uuid); if(resavePtr) { *resavePtr = true; @@ -579,7 +581,7 @@ NSMutableData* keymaterial = [[NSMutableData alloc] initWithBase64EncodedData:b64keymaterial options:0]; if(!keymaterial) { - secnotice("CKKSKeychainBackedKey", "Unable to unbase64 key: %@", self); + ckkserror_global("ckkskey", "Unable to unbase64 key: %@", self); if(error) { *error = [NSError errorWithDomain:CKKSErrorDomain @@ -595,11 +597,11 @@ self.aessivkey = key; if(resave) { - secnotice("CKKSKeychainBackedKey", "Resaving %@ as per request", self); + ckksnotice_global("ckkskey", "Resaving %@ as per request", self); NSError* resaveError = nil; [self saveKeyMaterialToKeychain:&resaveError]; if(resaveError) { - secnotice("CKKSKeychainBackedKey", "Resaving %@ failed: %@", self, resaveError); + ckksnotice_global("ckkskey", "Resaving %@ failed: %@", self, resaveError); } } @@ -727,8 +729,7 @@ - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _uuid = [decoder decodeObjectOfClass:[NSString class] forKey:@"uuid"]; _parentKeyUUID = [decoder decodeObjectOfClass:[NSString class] forKey:@"parentKeyUUID"]; @@ -786,8 +787,7 @@ - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _tlk = [decoder decodeObjectOfClass:[CKKSKeychainBackedKey class] forKey:@"tlk"]; _classA = [decoder decodeObjectOfClass:[CKKSKeychainBackedKey class] forKey:@"classA"]; _classC = [decoder decodeObjectOfClass:[CKKSKeychainBackedKey class] forKey:@"classC"]; diff --git a/keychain/ckks/CKKSKeychainView.h b/keychain/ckks/CKKSKeychainView.h index ac6e0339..18d12662 100644 --- a/keychain/ckks/CKKSKeychainView.h +++ b/keychain/ckks/CKKSKeychainView.h @@ -31,6 +31,9 @@ #import "keychain/ckks/CKKSReachabilityTracker.h" #import "keychain/ckks/CloudKitDependencies.h" +#import "keychain/ot/OctagonFlags.h" +#import "keychain/ot/OctagonStateMachine.h" + #include "keychain/securityd/SecDbItem.h" #include @@ -38,6 +41,7 @@ #import "keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.h" #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ckks/CKKSIncomingQueueOperation.h" +#import "keychain/ckks/CKKSKeychainViewState.h" #import "keychain/ckks/CKKSNearFutureScheduler.h" #import "keychain/ckks/CKKSNewTLKOperation.h" #import "keychain/ckks/CKKSNotifier.h" @@ -49,12 +53,13 @@ #import "keychain/ckks/CKKSScanLocalItemsOperation.h" #import "keychain/ckks/CKKSTLKShareRecord.h" #import "keychain/ckks/CKKSUpdateDeviceStateOperation.h" -#import "keychain/ckks/CKKSZone.h" #import "keychain/ckks/CKKSZoneModifier.h" #import "keychain/ckks/CKKSZoneChangeFetcher.h" #import "keychain/ckks/CKKSSynchronizeOperation.h" #import "keychain/ckks/CKKSLocalSynchronizeOperation.h" #import "keychain/ckks/CKKSProvideKeySetOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" #include "CKKS.h" @@ -64,34 +69,47 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSAESSIVKey; @class CKKSSynchronizeOperation; @class CKKSRateLimiter; -@class CKKSManifest; -@class CKKSEgoManifest; @class CKKSOutgoingQueueEntry; @class CKKSZoneChangeFetcher; @class CKKSCurrentKeySet; -@interface CKKSKeychainView : CKKSZone -{ - CKKSZoneKeyState* _keyHierarchyState; -} + CKKSPeerUpdateListener, + CKKSDatabaseProviderProtocol, + OctagonStateMachineEngine> + +// CKKS is in the middle of a transition period, where this class will take ownership +// of multiple CKKS views and CK zones. +// The following properties are intended for use in that transition, and should eventually disappear +@property (readonly) NSString* zoneName; +@property (readonly) CKRecordZoneID* zoneID; +@property CKKSKeychainViewState* viewState; + +// This will hold every view currently active. +@property NSSet* viewStates; + +@property CKKSAccountStatus accountStatus; +@property (readonly) CKContainer* container; +@property (weak) CKKSAccountStateTracker* accountTracker; +@property (weak) CKKSReachabilityTracker* reachabilityTracker; +@property (readonly) CKKSCloudKitClassDependencies* cloudKitClassDependencies; +@property (readonly) dispatch_queue_t queue; @property CKKSCondition* loggedIn; @property CKKSCondition* loggedOut; @property CKKSCondition* accountStateKnown; @property CKKSAccountStatus trustStatus; -@property (nullable) CKKSResultOperation* trustDependency; @property (nullable) CKKSLaunchSequence *launch; @property CKKSLockStateTracker* lockStateTracker; -@property CKKSZoneKeyState* keyHierarchyState; -@property (nullable) NSError* keyHierarchyError; -@property (nullable) CKOperationGroup* keyHierarchyOperationGroup; -@property (nullable) NSOperation* keyStateMachineOperation; +// Is this view currently syncing keychain modifications? +@property (readonly) BOOL itemSyncingEnabled; + +@property (readonly) OctagonStateMachine* stateMachine; // If the key hierarchy isn't coming together, it might be because we're out of sync with cloudkit. // Use this to track if we've completed a full refetch, so fix-up operations can be done. @@ -100,27 +118,15 @@ NS_ASSUME_NONNULL_BEGIN // Set this to request a key state refetch (tests only) @property bool keyStateFullRefetchRequested; -@property (nullable) CKKSEgoManifest* egoManifest; -@property (nullable) CKKSManifest* latestManifest; @property (nullable) CKKSResultOperation* keyStateReadyDependency; -// Wait for the key state to become 'nontransient': no pending operation is expected to advance it (at least until intervention) -@property (nullable) CKKSResultOperation* keyStateNonTransientDependency; - -// True if we believe there's any items in the keychain which haven't been brought up in CKKS yet -@property bool droppedItems; - -@property (readonly) NSString* lastActiveTLKUUID; - // Full of condition variables, if you'd like to try to wait until the key hierarchy is in some state -@property NSMutableDictionary* keyHierarchyConditions; +@property (readonly) NSDictionary* keyHierarchyConditions; @property CKKSZoneChangeFetcher* zoneChangeFetcher; -@property (weak) CKKSNearFutureScheduler* savedTLKNotifier; - @property (nullable) CKKSNearFutureScheduler* suggestTLKUpload; - +@property (nullable) CKKSNearFutureScheduler* requestPolicyCheck; /* Used for debugging: just what happened last time we ran this? */ @property CKKSIncomingQueueOperation* lastIncomingQueueOperation; @@ -128,7 +134,6 @@ NS_ASSUME_NONNULL_BEGIN @property CKKSOutgoingQueueOperation* lastOutgoingQueueOperation; @property CKKSProcessReceivedKeysOperation* lastProcessReceivedKeysOperation; @property CKKSReencryptOutgoingItemsOperation* lastReencryptOutgoingItemsOperation; -@property CKKSScanLocalItemsOperation* lastScanLocalItemsOperation; @property CKKSSynchronizeOperation* lastSynchronizeOperation; @property CKKSResultOperation* lastFixupOperation; @@ -139,23 +144,10 @@ NS_ASSUME_NONNULL_BEGIN @property NSOperation* holdLocalSynchronizeOperation; @property CKKSResultOperation* holdFixupOperation; -/* Trigger this to tell the whole machine that this view has changed */ -@property CKKSNearFutureScheduler* notifyViewChangedScheduler; +/* Used for testing */ +@property BOOL initiatedLocalScan; -/* Trigger this to tell the whole machine that this view is more ready then before */ -@property CKKSNearFutureScheduler* notifyViewReadyScheduler; - -/* trigger this to request key state machine poking */ -@property CKKSNearFutureScheduler* pokeKeyStateMachineScheduler; - -// The current list of peer providers. If empty, CKKS will consider itself untrusted, and halt operation -@property (readonly) NSArray>* currentPeerProviders; - -// These are available when you're in a dispatchSyncWithAccountKeys call, but at no other time -// These must be pre-fetched before you get on the CKKS queue, otherwise we end up with CKKS<->SQLite<->SOSAccountQueue deadlocks - -// They will be in a parallel array with currentPeerProviders above -@property (readonly) NSArray* currentTrustStates; +@property (readonly) CKKSOperationDependencies* operationDependencies; - (instancetype)initWithContainer:(CKContainer*)container zoneName:(NSString*)zoneName @@ -168,17 +160,34 @@ NS_ASSUME_NONNULL_BEGIN cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; /* Trust state management */ + +// suggestTLKUpload and requestPolicyCheck are essentially callbacks to request certain procedures from the view owner. +// When suggestTLKUpload is triggered, the CKKS view believes it has some new TLKs that need uploading, and Octagon should take care of them. +// When requestPolicyCheck is triggered, the CKKS view would like Octagon to perform a live check on which syncing policy is in effect, +// successfully retrieving all peer's opinions, and would like -setCurrentSyncingPolicy to be called with the updated policy (even if it is +// unchanged.) - (void)beginTrustedOperation:(NSArray>*)peerProviders - suggestTLKUpload:(CKKSNearFutureScheduler*)suggestTLKUpload; + suggestTLKUpload:(CKKSNearFutureScheduler*)suggestTLKUpload + requestPolicyCheck:(CKKSNearFutureScheduler*)requestPolicyCheck; + - (void)endTrustedOperation; +/* CloudKit account management */ + +- (void)beginCloudKitOperation; + +// If this policy indicates that this view should not sync, this view will no longer sync keychain items, +// but it will continue to particpate in TLK sharing. +// If policyIsFresh is set, any items discovered that do not match this policy will be moved. +- (void)setCurrentSyncingPolicy:(TPSyncingPolicy*)syncingPolicy policyIsFresh:(BOOL)policyIsFresh; + /* Synchronous operations */ - (void)handleKeychainEventDbConnection:(SecDbConnectionRef)dbconn + source:(SecDbTransactionSource)txionSource added:(SecDbItemRef _Nullable)added deleted:(SecDbItemRef _Nullable)deleted - rateLimiter:(CKKSRateLimiter*)rateLimiter - syncCallback:(SecBoolNSErrorCallback)syncCallback; + rateLimiter:(CKKSRateLimiter*)rateLimiter; - (void)setCurrentItemForAccessGroup:(NSData*)newItemPersistentRef hash:(NSData*)newItemSHA1 @@ -195,29 +204,23 @@ NS_ASSUME_NONNULL_BEGIN - (bool)outgoingQueueEmpty:(NSError* __autoreleasing*)error; -- (CKKSResultOperation*)findKeySet; +- (CKKSResultOperation*)findKeySet:(BOOL)refetchBeforeReturningKeySet; - (void)receiveTLKUploadRecords:(NSArray*)records; -- (CKKSResultOperation*)waitForFetchAndIncomingQueueProcessing; +// Returns true if this zone would like a new TLK to be uploaded +- (BOOL)requiresTLKUpload; + - (void)waitForKeyHierarchyReadiness; - (void)cancelAllOperations; -- (CKKSKey* _Nullable)keyForItem:(SecDbItemRef)item error:(NSError* __autoreleasing*)error; - -- (bool)_onqueueWithAccountKeysCheckTLK:(CKKSKey*)proposedTLK error:(NSError* __autoreleasing*)error; - -- (BOOL)otherDevicesReportHavingTLKs:(CKKSCurrentKeySet*)keyset; - -- (NSSet*)_onqueuePriorityOutgoingQueueUUIDs; - /* Asynchronous kickoffs */ - (CKKSOutgoingQueueOperation*)processOutgoingQueue:(CKOperationGroup* _Nullable)ckoperationGroup; - (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup; -- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation*)after +- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after requiredDelay:(uint64_t)requiredDelay - ckoperationGroup:(CKOperationGroup*)ckoperationGroup; + ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup; - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA; - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA after:(CKKSResultOperation* _Nullable)after; @@ -239,8 +242,6 @@ NS_ASSUME_NONNULL_BEGIN - (CKKSSynchronizeOperation*)resyncWithCloud; - (CKKSLocalSynchronizeOperation*)resyncLocal; -- (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because; - - (CKKSResultOperation*)resetLocalData; - (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup; @@ -250,65 +251,50 @@ NS_ASSUME_NONNULL_BEGIN // For our serial queue to work with how handleKeychainEventDbConnection is called from the main thread, // every block on our queue must have a SecDBConnectionRef available to it before it begins on the queue. // Use these helper methods to make sure those exist. -- (void)dispatchSync:(bool (^)(void))block; -- (void)dispatchSyncWithAccountKeys:(bool (^)(void))block; +- (void)dispatchSyncWithSQLTransaction:(CKKSDatabaseTransactionResult (^)(void))block; +- (void)dispatchSyncWithReadOnlySQLTransaction:(void (^)(void))block; /* Synchronous operations which must be called from inside a dispatchAsyncWithAccountKeys or dispatchSync block */ -// Call this to request the key hierarchy state machine to fetch new updates -- (void)_onqueueKeyStateMachineRequestFetch; - -// Call this to request the key hierarchy state machine to reprocess -- (void)_onqueueKeyStateMachineRequestProcess; - -// Call this from a key hierarchy operation to move the state machine, and record the results of the last move. -- (void)_onqueueAdvanceKeyStateMachineToState:(CKKSZoneKeyState* _Nullable)state withError:(NSError* _Nullable)error; - -// Since we might have people interested in the state transitions of objects, please do those transitions via these methods -- (bool)_onqueueChangeOutgoingQueueEntry:(CKKSOutgoingQueueEntry*)oqe - toState:(NSString*)state - error:(NSError* __autoreleasing*)error; -- (bool)_onqueueErrorOutgoingQueueEntry:(CKKSOutgoingQueueEntry*)oqe - itemError:(NSError*)itemError - error:(NSError* __autoreleasing*)error; - -// Call this if you've done a write and received an error. It'll pull out any new records returned as CKErrorServerRecordChanged and pretend we received them in a fetch -// -// Note that you need to tell this function the records you wanted to save, so it can determine which record failed from its CKRecordID. -// I don't know why CKRecordIDs don't have record types, either. - (bool)_onqueueCKWriteFailed:(NSError*)ckerror attemptedRecordsChanged:(NSDictionary*)savedRecords; - - (bool)_onqueueCKRecordChanged:(CKRecord*)record resync:(bool)resync; - (bool)_onqueueCKRecordDeleted:(CKRecordID*)recordID recordType:(NSString*)recordType resync:(bool)resync; -// For this key, who doesn't yet have a CKKSTLKShare for it, shared to their current Octagon keys? -// Note that we really want a record sharing the TLK to ourselves, so this function might return -// a non-empty set even if all peers have the TLK: it wants us to make a record for ourself. -// If you pass in a non-empty set in afterUploading, those records will be included in the calculation. -- (NSSet>*)_onqueueFindPeers:(CKKSPeerProviderState*)trustState - missingShare:(CKKSKey*)key - afterUploading:(NSSet* _Nullable)newShares - error:(NSError* __autoreleasing*)error; - -- (BOOL)_onqueueAreNewSharesSufficient:(NSSet*)newShares - currentTLK:(CKKSKey*)key - error:(NSError* __autoreleasing*)error; - -// For this key, share it to all trusted peers who don't have it yet -- (NSSet* _Nullable)_onqueueCreateMissingKeyShares:(CKKSKey*)key error:(NSError* __autoreleasing*)error; - -- (bool)_onqueueUpdateLatestManifestWithError:(NSError**)error; - - (CKKSDeviceStateEntry* _Nullable)_onqueueCurrentDeviceStateEntry:(NSError* __autoreleasing*)error; // Please don't use these unless you're an Operation in this package @property NSHashTable* incomingQueueOperations; @property NSHashTable* outgoingQueueOperations; -@property CKKSScanLocalItemsOperation* initialScanOperation; + +@property NSHashTable* scanLocalItemsOperations; // Returns the current state of this view, fastStatus is the same, but as name promise, no expensive calculations - (NSDictionary*)status; - (NSDictionary*)fastStatus; + +- (void)xpc24HrNotification; + +// NSOperation Helpers +- (void)scheduleOperation:(NSOperation*)op; +@end + +@interface CKKSKeychainView (Testing) + +// Call this to just nudge the state machine (without a request) +// This is used internally, but you should only call it if you're a test. +- (void)_onqueuePokeKeyStateMachine; + +/* NSOperation helpers */ +- (void)cancelAllOperations; +- (void)waitUntilAllOperationsAreFinished; +- (void)waitForOperationsOfClass:(Class)operationClass; + +- (void)waitForFetchAndIncomingQueueProcessing; + +- (void)halt; + +- (void)handleCKLogout; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSKeychainView.m b/keychain/ckks/CKKSKeychainView.m index 3e7a16fe..afb4aad8 100644 --- a/keychain/ckks/CKKSKeychainView.m +++ b/keychain/ckks/CKKSKeychainView.m @@ -32,6 +32,7 @@ #endif #import "CKKS.h" +#import "keychain/ckks/CKKSStates.h" #import "OctagonAPSReceiver.h" #import "CKKSIncomingQueueEntry.h" #import "CKKSOutgoingQueueEntry.h" @@ -43,9 +44,8 @@ #import "CKKSIncomingQueueOperation.h" #import "CKKSNewTLKOperation.h" #import "CKKSProcessReceivedKeysOperation.h" -#import "CKKSZone.h" #import "CKKSFetchAllRecordZoneChangesOperation.h" -#import "CKKSHealKeyHierarchyOperation.h" +#import "keychain/ckks/CKKSHealKeyHierarchyOperation.h" #import "CKKSReencryptOutgoingItemsOperation.h" #import "CKKSScanLocalItemsOperation.h" #import "CKKSSynchronizeOperation.h" @@ -59,6 +59,8 @@ #import "keychain/ckks/CKKSDeviceStateEntry.h" #import "keychain/ckks/CKKSNearFutureScheduler.h" #import "keychain/ckks/CKKSCurrentItemPointer.h" +#import "keychain/ckks/CKKSCreateCKZoneOperation.h" +#import "keychain/ckks/CKKSDeleteCKZoneOperation.h" #import "keychain/ckks/CKKSUpdateCurrentItemPointerOperation.h" #import "keychain/ckks/CKKSUpdateDeviceStateOperation.h" #import "keychain/ckks/CKKSNotifier.h" @@ -67,8 +69,12 @@ #import "keychain/ckks/CKKSHealTLKSharesOperation.h" #import "keychain/ckks/CKKSLocalSynchronizeOperation.h" #import "keychain/ckks/CKKSPeerProvider.h" +#import "keychain/ckks/CKKSCheckKeyHierarchyOperation.h" +#import "keychain/ckks/CKKSViewManager.h" #import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKSLocalResetOperation.h" + #import "keychain/ot/OTConstants.h" #import "keychain/ot/OTDefines.h" #import "keychain/ot/OctagonCKKSPeerAdapter.h" @@ -81,33 +87,17 @@ #include "keychain/securityd/SecItemDb.h" #include "keychain/securityd/SecItemSchema.h" #include "keychain/securityd/SecItemServer.h" -#include #include #include "keychain/SecureObjectSync/SOSAccountTransaction.h" -#include #include #include +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" +#import + #if OCTAGON @interface CKKSKeychainView() -@property bool keyStateFetchRequested; -@property bool keyStateProcessRequested; -@property bool trustedPeersSetChanged; - -@property bool keyStateCloudKitDeleteRequested; -@property NSHashTable* cloudkitDeleteZoneOperations; - -@property bool keyStateLocalResetRequested; -@property NSHashTable* localResetOperations; - -@property bool tlkCreationRequested; -@property NSHashTable*>* keysetProviderOperations; - - -@property (atomic) NSString *activeTLK; - -@property (readonly) Class notifierClass; // Slows down all outgoing queue operations @property CKKSNearFutureScheduler* outgoingQueueOperationScheduler; @@ -115,18 +105,22 @@ @property CKKSResultOperation* processIncomingQueueAfterNextUnlockOperation; @property CKKSResultOperation* resultsOfNextIncomingQueueOperationOperation; -@property NSMutableDictionary* pendingSyncCallbacks; - // An extra queue for semaphore-waiting-based NSOperations @property NSOperationQueue* waitingQueue; // Scratch space for resyncs @property (nullable) NSMutableSet* resyncRecordsSeen; + + +@property NSOperationQueue* operationQueue; +@property CKKSResultOperation* accountLoggedInDependency; +@property BOOL halted; + // Make these readwrite -@property NSArray>* currentPeerProviders; @property NSArray* currentTrustStates; +@property NSMutableSet* currentFetchReasons; @end #endif @@ -144,128 +138,127 @@ cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies { - if(self = [super initWithContainer:container - zoneName:zoneName - accountTracker:accountTracker - reachabilityTracker:reachabilityTracker - zoneModifier:zoneModifier - cloudKitClassDependencies:cloudKitClassDependencies]) { + if((self = [super init])) { WEAKIFY(self); + _container = container; + _accountTracker = accountTracker; + _reachabilityTracker = reachabilityTracker; + _lockStateTracker = lockStateTracker; + _cloudKitClassDependencies = cloudKitClassDependencies; + + _halted = NO; + + _accountStatus = CKKSAccountStatusUnknown; + _accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in."]; + + _queue = dispatch_queue_create([[NSString stringWithFormat:@"CKKSQueue.%@.zone.%@", container.containerIdentifier, zoneName] UTF8String], DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + _operationQueue = [[NSOperationQueue alloc] init]; + _waitingQueue = [[NSOperationQueue alloc] init]; + _waitingQueue.maxConcurrentOperationCount = 5; + + _loggedIn = [[CKKSCondition alloc] init]; _loggedOut = [[CKKSCondition alloc] init]; _accountStateKnown = [[CKKSCondition alloc] init]; + _initiatedLocalScan = NO; + _trustStatus = CKKSAccountStatusUnknown; - _trustDependency = [CKKSResultOperation named:@"wait-for-trust" withBlock:^{}]; _incomingQueueOperations = [NSHashTable weakObjectsHashTable]; _outgoingQueueOperations = [NSHashTable weakObjectsHashTable]; - _cloudkitDeleteZoneOperations = [NSHashTable weakObjectsHashTable]; - _localResetOperations = [NSHashTable weakObjectsHashTable]; - _keysetProviderOperations = [NSHashTable weakObjectsHashTable]; + _scanLocalItemsOperations = [NSHashTable weakObjectsHashTable]; - _currentPeerProviders = @[]; _currentTrustStates = @[]; + _currentFetchReasons = [NSMutableSet set]; + _launch = [[CKKSLaunchSequence alloc] initWithRocketName:@"com.apple.security.ckks.launch"]; [_launch addAttribute:@"view" value:zoneName]; - _zoneChangeFetcher = fetcher; - [fetcher registerClient:self]; - _resyncRecordsSeen = nil; - _notifierClass = cloudKitClassDependencies.notifierClass; - _notifyViewChangedScheduler = [[CKKSNearFutureScheduler alloc] initWithName:[NSString stringWithFormat: @"%@-notify-scheduler", self.zoneName] - initialDelay:250*NSEC_PER_MSEC - continuingDelay:1*NSEC_PER_SEC - keepProcessAlive:true - dependencyDescriptionCode:CKKSResultDescriptionPendingViewChangedScheduling - block:^{ - STRONGIFY(self); - [self.notifierClass post:[NSString stringWithFormat:@"com.apple.security.view-change.%@", self.zoneName]]; + CKKSNearFutureScheduler* notifyViewChangedScheduler = [[CKKSNearFutureScheduler alloc] initWithName:[NSString stringWithFormat: @"ckks-%@-notify-scheduler", zoneName] + initialDelay:250*NSEC_PER_MSEC + continuingDelay:1*NSEC_PER_SEC + keepProcessAlive:true + dependencyDescriptionCode:CKKSResultDescriptionPendingViewChangedScheduling + block:^{ + STRONGIFY(self); + [self.cloudKitClassDependencies.notifierClass post:[NSString stringWithFormat:@"com.apple.security.view-change.%@", zoneName]]; + [self.cloudKitClassDependencies.notifierClass post:[NSString stringWithUTF8String:kSecServerKeychainChangedNotification]]; - // Ugly, but: the Manatee and Engram views need to send a fake 'PCS' view change. - // TODO: make this data-driven somehow - if([self.zoneName isEqualToString:@"Manatee"] || - [self.zoneName isEqualToString:@"Engram"] || - [self.zoneName isEqualToString:@"ApplePay"] || - [self.zoneName isEqualToString:@"Home"] || - [self.zoneName isEqualToString:@"LimitedPeersAllowed"]) { - [self.notifierClass post:@"com.apple.security.view-change.PCS"]; - } - }]; - - _notifyViewReadyScheduler = [[CKKSNearFutureScheduler alloc] initWithName:[NSString stringWithFormat: @"%@-ready-scheduler", self.zoneName] - initialDelay:250*NSEC_PER_MSEC - continuingDelay:120*NSEC_PER_SEC - keepProcessAlive:true - dependencyDescriptionCode:CKKSResultDescriptionPendingViewChangedScheduling - block:^{ - STRONGIFY(self); - NSDistributedNotificationCenter *center = [self.cloudKitClassDependencies.nsdistributednotificationCenterClass defaultCenter]; - - [center postNotificationName:@"com.apple.security.view-become-ready" - object:nil - userInfo:@{ @"view" : self.zoneName ?: @"unknown" } - options:0]; - }]; - - - _pendingSyncCallbacks = [[NSMutableDictionary alloc] init]; - - _lockStateTracker = lockStateTracker; - _savedTLKNotifier = savedTLKNotifier; - - _keyHierarchyConditions = [[NSMutableDictionary alloc] init]; - [CKKSZoneKeyStateMap() enumerateKeysAndObjectsUsingBlock:^(CKKSZoneKeyState * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) { - [self.keyHierarchyConditions setObject: [[CKKSCondition alloc] init] forKey:key]; + // Ugly, but: the Manatee and Engram views need to send a fake 'PCS' view change. + // TODO: make this data-driven somehow + if([zoneName isEqualToString:@"Manatee"] || + [zoneName isEqualToString:@"Engram"] || + [zoneName isEqualToString:@"ApplePay"] || + [zoneName isEqualToString:@"Home"] || + [zoneName isEqualToString:@"LimitedPeersAllowed"]) { + [self.cloudKitClassDependencies.notifierClass post:@"com.apple.security.view-change.PCS"]; + } }]; - // Use the keyHierarchyState setter to modify the zone key state map - self.keyHierarchyState = SecCKKSZoneKeyStateLoggedOut; + CKKSNearFutureScheduler* notifyViewReadyScheduler = [[CKKSNearFutureScheduler alloc] initWithName:[NSString stringWithFormat: @"%@-ready-scheduler", zoneName] + initialDelay:250*NSEC_PER_MSEC + continuingDelay:120*NSEC_PER_SEC + keepProcessAlive:true + dependencyDescriptionCode:CKKSResultDescriptionPendingViewChangedScheduling + block:^{ + STRONGIFY(self); + NSDistributedNotificationCenter *center = [self.cloudKitClassDependencies.nsdistributednotificationCenterClass defaultCenter]; - _keyHierarchyError = nil; - _keyHierarchyOperationGroup = nil; - _keyStateMachineOperation = nil; - _keyStateFetchRequested = false; - _keyStateProcessRequested = false; - _tlkCreationRequested = false; + [center postNotificationName:@"com.apple.security.view-become-ready" + object:nil + userInfo:@{ @"view" : zoneName ?: @"unknown" } + options:0]; + }]; - _waitingQueue = [[NSOperationQueue alloc] init]; - _waitingQueue.maxConcurrentOperationCount = 5; + _stateMachine = [[OctagonStateMachine alloc] initWithName:[NSString stringWithFormat:@"ckks-%@", zoneName] + states:[NSSet setWithArray:[CKKSZoneKeyStateMap() allKeys]] + flags:CKKSAllStateFlags() + initialState:SecCKKSZoneKeyStateWaitForCloudKitAccountStatus + queue:self.queue + stateEngine:self + lockStateTracker:lockStateTracker + reachabilityTracker:reachabilityTracker]; - _keyStateReadyDependency = [self createKeyStateReadyDependency: @"Key state has become ready for the first time." ckoperationGroup:[CKOperationGroup CKKSGroupWithName:@"initial-key-state-ready-scan"]]; + _viewState = [[CKKSKeychainViewState alloc] initWithZoneID:[[CKRecordZoneID alloc] initWithZoneName:zoneName ownerName:CKCurrentUserDefaultName] + viewStateMachine:self.stateMachine + notifyViewChangedScheduler:notifyViewChangedScheduler + notifyViewReadyScheduler:notifyViewReadyScheduler]; + _viewStates = [NSSet setWithObject:_viewState]; - _keyStateNonTransientDependency = [self createKeyStateNontransientDependency]; + _keyStateReadyDependency = [self createKeyStateReadyDependency: @"Key state has become ready for the first time."]; dispatch_time_t initialOutgoingQueueDelay = SecCKKSReduceRateLimiting() ? NSEC_PER_MSEC * 200 : NSEC_PER_SEC * 1; dispatch_time_t continuingOutgoingQueueDelay = SecCKKSReduceRateLimiting() ? NSEC_PER_MSEC * 200 : NSEC_PER_SEC * 30; - _outgoingQueueOperationScheduler = [[CKKSNearFutureScheduler alloc] initWithName:[NSString stringWithFormat: @"%@-outgoing-queue-scheduler", self.zoneName] + _outgoingQueueOperationScheduler = [[CKKSNearFutureScheduler alloc] initWithName:[NSString stringWithFormat: @"%@-outgoing-queue-scheduler", zoneName] initialDelay:initialOutgoingQueueDelay continuingDelay:continuingOutgoingQueueDelay keepProcessAlive:false dependencyDescriptionCode:CKKSResultDescriptionPendingOutgoingQueueScheduling block:^{}]; + _operationDependencies = [[CKKSOperationDependencies alloc] initWithViewState:_viewState + zoneModifier:zoneModifier + ckdatabase:[_container privateCloudDatabase] + ckoperationGroup:nil + flagHandler:_stateMachine + launchSequence:_launch + accountStateTracker:accountTracker + lockStateTracker:_lockStateTracker + reachabilityTracker:reachabilityTracker + peerProviders:@[] + databaseProvider:self + notifyViewChangedScheduler:_viewState.notifyViewChangedScheduler + savedTLKNotifier:savedTLKNotifier]; - dispatch_time_t initialKeyHierachyPokeDelay = SecCKKSReduceRateLimiting() ? NSEC_PER_MSEC * 100 : NSEC_PER_MSEC * 500; - dispatch_time_t continuingKeyHierachyPokeDelay = SecCKKSReduceRateLimiting() ? NSEC_PER_MSEC * 200 : NSEC_PER_SEC * 5; - _pokeKeyStateMachineScheduler = [[CKKSNearFutureScheduler alloc] initWithName:[NSString stringWithFormat: @"%@-reprocess-scheduler", self.zoneName] - initialDelay:initialKeyHierachyPokeDelay - continuingDelay:continuingKeyHierachyPokeDelay - keepProcessAlive:true - dependencyDescriptionCode:CKKSResultDescriptionPendingKeyHierachyPokeScheduling - block:^{ - STRONGIFY(self); - [self dispatchSyncWithAccountKeys: ^bool{ - STRONGIFY(self); + _zoneChangeFetcher = fetcher; + [fetcher registerClient:self]; - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; - }]; - }]; + [_stateMachine startOperation]; } return self; } @@ -279,427 +272,211 @@ } - (CKKSZoneKeyState*)keyHierarchyState { - return _keyHierarchyState; + return self.stateMachine.currentState; } -- (void)setKeyHierarchyState:(CKKSZoneKeyState *)keyHierarchyState { - if((keyHierarchyState == nil && _keyHierarchyState == nil) || ([keyHierarchyState isEqualToString:_keyHierarchyState])) { - // No change, do nothing. - } else { - // Fixup the condition variables as part of setting this state - if(_keyHierarchyState) { - self.keyHierarchyConditions[_keyHierarchyState] = [[CKKSCondition alloc] init]; - } - - _keyHierarchyState = keyHierarchyState; - - if(keyHierarchyState) { - [self.keyHierarchyConditions[keyHierarchyState] fulfill]; - } - } -} - -- (NSString *)lastActiveTLKUUID +- (NSDictionary*)keyHierarchyConditions { - return self.activeTLK; + return self.stateMachine.stateConditions; } -- (void)_onqueueResetSetup:(CKKSZoneKeyState*)newState resetMessage:(NSString*)resetMessage ckoperationGroup:(CKOperationGroup*)group { - [super resetSetup]; +- (NSString*)zoneName +{ + return self.viewState.zoneName; +} - self.keyHierarchyState = newState; - self.keyHierarchyError = nil; - - [self.keyStateMachineOperation cancel]; - self.keyStateMachineOperation = nil; - - self.keyStateFetchRequested = false; - self.keyStateProcessRequested = false; - - self.keyHierarchyOperationGroup = group; - - [self ensureKeyStateReadyDependency:resetMessage]; - - NSOperation* oldKSNTD = self.keyStateNonTransientDependency; - self.keyStateNonTransientDependency = [self createKeyStateNontransientDependency]; - if(oldKSNTD) { - [oldKSNTD addDependency:self.keyStateNonTransientDependency]; - [self.waitingQueue addOperation:oldKSNTD]; - } +- (CKRecordZoneID*)zoneID +{ + return self.viewState.zoneID; } - (void)ensureKeyStateReadyDependency:(NSString*)resetMessage { NSOperation* oldKSRD = self.keyStateReadyDependency; - self.keyStateReadyDependency = [self createKeyStateReadyDependency:resetMessage ckoperationGroup:self.keyHierarchyOperationGroup]; + self.keyStateReadyDependency = [self createKeyStateReadyDependency:resetMessage]; if(oldKSRD) { [oldKSRD addDependency:self.keyStateReadyDependency]; [self.waitingQueue addOperation:oldKSRD]; } } -- (CKKSResultOperation*)createPendingInitializationOperation { - +- (CKKSResultOperation*)performInitializedOperation +{ WEAKIFY(self); - CKKSResultOperation* initializationOp = [CKKSGroupOperation named:@"view-initialization" withBlockTakingSelf:^(CKKSGroupOperation * _Nonnull strongOp) { + return [OctagonStateTransitionOperation named:@"ckks-initialized-operation" + intending:SecCKKSZoneKeyStateBecomeReady + errorState:SecCKKSZoneKeyStateError + withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { STRONGIFY(self); + [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + CKKSOutgoingQueueOperation* outgoingOperation = nil; + CKKSIncomingQueueOperation* initialProcess = nil; + CKKSScanLocalItemsOperation* initialScan = nil; - __block CKKSResultOperation* zoneCreationOperation = nil; - [self dispatchSync:^bool { - CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state: self.zoneName]; - zoneCreationOperation = [self handleCKLogin:ckse.ckzonecreated zoneSubscribed:ckse.ckzonesubscribed]; - return true; - }]; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName]; - CKKSResultOperation* viewInitializationOperation = [CKKSResultOperation named:@"view-initialization" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull strongInternalOp) { - STRONGIFY(self); - if(!self) { - ckkserror("ckks", self, "received callback for released object"); - return; - } + // Check if we believe we've synced this zone before. + if(ckse.changeToken == nil) { + self.operationDependencies.ckoperationGroup = [CKOperationGroup CKKSGroupWithName:@"initial-setup"]; - [self dispatchSyncWithAccountKeys: ^bool { - ckksnotice("ckks", self, "Zone setup progress: %@ %d %@ %d %@", - [CKKSAccountStateTracker stringFromAccountStatus:self.accountStatus], - self.zoneCreated, self.zoneCreatedError, self.zoneSubscribed, self.zoneSubscribedError); + ckksnotice("ckks", self, "No existing change token; going to try to match local items with CloudKit ones."); + // Onboard this keychain: there's likely items in it that we haven't synced yet. + // But, there might be items in The Cloud that correspond to these items, with UUIDs that we don't know yet. + // First, fetch all remote items. + + [self.currentFetchReasons addObject:CKKSFetchBecauseInitialStart]; + op.nextState = SecCKKSZoneKeyStateBeginFetch; + + // Next, try to process them (replacing local entries). This will wait for the key state to be ready. + initialProcess = [self processIncomingQueue:true after:nil]; + + // If all that succeeds, iterate through all keychain items and find the ones which need to be uploaded + initialScan = [self scanLocalItems:@"initial-scan-operation" + ckoperationGroup:self.operationDependencies.ckoperationGroup + after:initialProcess]; + + } else { + // Likely a restart of securityd! + + // Are there any fixups to run first? + self.lastFixupOperation = [CKKSFixups fixup:ckse.lastFixup for:self]; + if(self.lastFixupOperation) { + ckksnotice("ckksfixup", self, "We have a fixup to perform: %@", self.lastFixupOperation); + [self scheduleOperation:self.lastFixupOperation]; + op.nextState = SecCKKSZoneKeyStateWaitForFixupOperation; + return CKKSDatabaseTransactionCommit; + } + + // First off, are there any in-flight queue entries? If so, put them back into New. + // If they're truly in-flight, we'll "conflict" with ourselves, but that should be fine. NSError* error = nil; - CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state: self.zoneName]; - ckse.ckzonecreated = self.zoneCreated; - ckse.ckzonesubscribed = self.zoneSubscribed; + [self _onqueueResetAllInflightOQE:&error]; + if(error) { + ckkserror("ckks", self, "Couldn't reset in-flight OQEs, bad behavior ahead: %@", error); + } - // Although, if the zone subscribed error says there's no zone, mark down that there's no zone - if(self.zoneSubscribedError && - [self.zoneSubscribedError.domain isEqualToString:CKErrorDomain] && self.zoneSubscribedError.code == CKErrorPartialFailure) { - NSError* subscriptionError = self.zoneSubscribedError.userInfo[CKPartialErrorsByItemIDKey][self.zoneID]; - if(subscriptionError && [subscriptionError.domain isEqualToString:CKErrorDomain] && subscriptionError.code == CKErrorZoneNotFound) { + // Are there any entries waiting for reencryption? If so, set the flag. + error = nil; + NSArray* reencryptOQEs = [CKKSOutgoingQueueEntry allInState:SecCKKSStateReencrypt + zoneID:self.zoneID + error:&error]; + if(error) { + ckkserror("ckks", self, "Couldn't load reencrypt OQEs, bad behavior ahead: %@", error); + } + if(reencryptOQEs.count > 0) { + [self.stateMachine _onqueueHandleFlag:CKKSFlagItemReencryptionNeeded]; + } - ckkserror("ckks", self, "zone subscription error appears to say the zone doesn't exist, fixing status: %@", self.zoneSubscribedError); - ckse.ckzonecreated = false; + self.operationDependencies.ckoperationGroup = [CKOperationGroup CKKSGroupWithName:@"restart-setup"]; + + // If it's been more than 24 hours since the last fetch, fetch and process everything. + // Or, if we think we were interrupted in the middle of fetching, fetch some more. + // Otherwise, just kick off the local queue processing. + + NSDate* now = [NSDate date]; + NSDateComponents* offset = [[NSDateComponents alloc] init]; + [offset setHour:-24]; + NSDate* deadline = [[NSCalendar currentCalendar] dateByAddingComponents:offset toDate:now options:0]; + + if(ckse.lastFetchTime == nil || + [ckse.lastFetchTime compare: deadline] == NSOrderedAscending || + ckse.moreRecordsInCloudKit) { + + op.nextState = SecCKKSZoneKeyStateBeginFetch; + + } else { + // Check if we have an existing key hierarchy in keyset + CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; + if(keyset.error && !([keyset.error.domain isEqual: @"securityd"] && keyset.error.code == errSecItemNotFound)) { + ckkserror("ckkskey", self, "Error examining existing key hierarchy: %@", keyset.error); + } + + if(keyset.tlk && keyset.classA && keyset.classC && !keyset.error) { + // This is likely a restart of securityd, and we think we're ready. Double check. + op.nextState = SecCKKSZoneKeyStateBecomeReady; + + } else { + ckksnotice("ckkskey", self, "No existing key hierarchy for %@. Check if there's one in CloudKit...", self.zoneID.zoneName); + op.nextState = SecCKKSZoneKeyStateBeginFetch; } } - [ckse saveToDatabase: &error]; - if(error) { - ckkserror("ckks", self, "couldn't save zone creation status for %@: %@", self.zoneName, error); + if(ckse.lastLocalKeychainScanTime == nil || [ckse.lastLocalKeychainScanTime compare:deadline] == NSOrderedAscending) { + // TODO handle with a state flow + ckksnotice("ckksscan", self, "CKKS scan last occurred at %@; beginning a new one", ckse.lastLocalKeychainScanTime); + initialScan = [self scanLocalItems:ckse.lastLocalKeychainScanTime == nil ? @"initial-scan-operation" : @"24-hr-scan-operation" + ckoperationGroup:self.operationDependencies.ckoperationGroup + after:nil]; } - if(!self.zoneCreated || !self.zoneSubscribed) { - // Go into 'zonecreationfailed' - strongInternalOp.error = self.zoneCreatedError ? self.zoneCreatedError : self.zoneSubscribedError; - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateZoneCreationFailed withError:strongInternalOp.error]; - - return true; - } else { - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateInitialized withError:nil]; - } - - return true; - }]; - }]; - - [viewInitializationOperation addDependency:zoneCreationOperation]; - [strongOp runBeforeGroupFinished:viewInitializationOperation]; - }]; - - return initializationOp; -} - -- (void)_onqueuePerformKeyStateInitialized:(CKKSZoneStateEntry*)ckse { - CKKSOutgoingQueueOperation* outgoingOperation = nil; - NSOperation* initialProcess = nil; - - // Check if we believe we've synced this zone before. - if(ckse.changeToken == nil) { - self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"initial-setup"]; - - ckksnotice("ckks", self, "No existing change token; going to try to match local items with CloudKit ones."); - - // Onboard this keychain: there's likely items in it that we haven't synced yet. - // But, there might be items in The Cloud that correspond to these items, with UUIDs that we don't know yet. - // First, fetch all remote items. - CKKSResultOperation* fetch = [self.zoneChangeFetcher requestSuccessfulFetch:CKKSFetchBecauseInitialStart]; - fetch.name = @"initial-fetch"; - - // Next, try to process them (replacing local entries) - initialProcess = [self processIncomingQueue:true after:fetch]; - initialProcess.name = @"initial-process-incoming-queue"; - - // If all that succeeds, iterate through all keychain items and find the ones which need to be uploaded - self.initialScanOperation = [self scanLocalItems:@"initial-scan-operation" - ckoperationGroup:self.keyHierarchyOperationGroup - after:initialProcess]; - - } else { - // Likely a restart of securityd! - - // First off, are there any in-flight queue entries? If so, put them back into New. - // If they're truly in-flight, we'll "conflict" with ourselves, but that should be fine. - NSError* error = nil; - [self _onqueueResetAllInflightOQE:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't reset in-flight OQEs, bad behavior ahead: %@", error); - } - - // Are there any fixups to run first? - self.lastFixupOperation = [CKKSFixups fixup:ckse.lastFixup for:self]; - if(self.lastFixupOperation) { - ckksnotice("ckksfixup", self, "We have a fixup to perform: %@", self.lastFixupOperation); - [self scheduleOperation:self.lastFixupOperation]; - } - - self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"restart-setup"]; - - if ([CKKSManifest shouldSyncManifests]) { - self.egoManifest = [CKKSEgoManifest tryCurrentEgoManifestForZone:self.zoneName]; - } - - // If it's been more than 24 hours since the last fetch, fetch and process everything. - // Or, if we think we were interrupted in the middle of fetching, fetch some more. - // Otherwise, just kick off the local queue processing. - - NSDate* now = [NSDate date]; - NSDateComponents* offset = [[NSDateComponents alloc] init]; - [offset setHour:-24]; - NSDate* deadline = [[NSCalendar currentCalendar] dateByAddingComponents:offset toDate:now options:0]; - - if(ckse.lastFetchTime == nil || - [ckse.lastFetchTime compare: deadline] == NSOrderedAscending || - ckse.moreRecordsInCloudKit) { - initialProcess = [self fetchAndProcessCKChanges:CKKSFetchBecauseSecuritydRestart after:self.lastFixupOperation]; - - // Also, kick off a scan local items: it'll find any out-of-sync issues in the local keychain - self.initialScanOperation = [self scanLocalItems:@"24-hr-scan-operation" - ckoperationGroup:self.keyHierarchyOperationGroup - after:initialProcess]; - } else { - initialProcess = [self processIncomingQueue:false after:self.lastFixupOperation]; - } - - if([CKKSManifest shouldSyncManifests]) { - if (!self.egoManifest && !self.initialScanOperation) { - ckksnotice("ckksmanifest", self, "No ego manifest on restart; rescanning"); - self.initialScanOperation = [self scanLocalItems:@"initial-scan-operation" - ckoperationGroup:self.keyHierarchyOperationGroup - after:initialProcess]; + // Process outgoing queue after re-start + outgoingOperation = [self processOutgoingQueueAfter:nil ckoperationGroup:self.operationDependencies.ckoperationGroup]; } - } - // Process outgoing queue after re-start - outgoingOperation = [self processOutgoingQueueAfter:self.lastFixupOperation ckoperationGroup:self.keyHierarchyOperationGroup]; - } + /* + * Launch time is determined by when the zone have: + * 1. keystate have become ready + * 2. scan local items (if needed) + * 3. processed all outgoing item (if needed) + * TODO: this should move, once queue processing becomes part of the state machine + */ - /* - * Launch time is determined by when the zone have: - * 1. keystate have become ready - * 2. scan local items (if needed) - * 3. processed all outgoing item (if needed) - */ - - WEAKIFY(self); - NSBlockOperation *seemReady = [NSBlockOperation named:[NSString stringWithFormat:@"seemsReadyForSyncing-%@", self.zoneName] withBlock:^void{ - STRONGIFY(self); - NSError *error = nil; - ckksnotice("launch", self, "Launch complete"); - NSNumber *zoneSize = [CKKSMirrorEntry counts:self.zoneID error:&error]; - if (zoneSize) { - zoneSize = @(SecBucket1Significant([zoneSize longValue])); - [self.launch addAttribute:@"zonesize" value:zoneSize]; - } - [self.launch launch]; - - /* - * Since we think we are ready, signal to CK that its to check for PCS identities again, and create the - * since before we completed this operation, we would probably have failed with a timeout because - * we where busy downloading items from CloudKit and then processing them. - */ - [self.notifyViewReadyScheduler trigger]; - }]; - - [seemReady addNullableDependency:self.keyStateReadyDependency]; - [seemReady addNullableDependency:outgoingOperation]; - [seemReady addNullableDependency:self.initialScanOperation]; - [seemReady addNullableDependency:initialProcess]; - - [self scheduleOperation: seemReady]; -} - -- (bool)_onqueueResetLocalData: (NSError * __autoreleasing *) error { - dispatch_assert_queue(self.queue); - - NSError* localerror = nil; - bool setError = false; // Ugly, but this is the only way to return the first error given - - CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state: self.zoneName]; - ckse.ckzonecreated = false; - ckse.ckzonesubscribed = false; // I'm actually not sure about this: can you be subscribed to a non-existent zone? - ckse.changeToken = NULL; - [ckse saveToDatabase: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't reset zone status for %@: %@", self.zoneName, localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSMirrorEntry deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSMirrorEntry: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSOutgoingQueueEntry deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSOutgoingQueueEntry: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSIncomingQueueEntry deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSIncomingQueueEntry: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSKey deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSKey: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSTLKShareRecord deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSTLKShare: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSCurrentKeyPointer deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSCurrentKeyPointer: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSCurrentItemPointer deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSCurrentItemPointer: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSDeviceStateEntry deleteAll:self.zoneID error:&localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSDeviceStateEntry: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - return (localerror == nil && !setError); -} - -- (CKKSResultOperation*)createPendingResetLocalDataOperation { - @synchronized(self.localResetOperations) { - CKKSResultOperation* pendingResetLocalOperation = (CKKSResultOperation*) [self findFirstPendingOperation:self.localResetOperations]; - if(!pendingResetLocalOperation) { WEAKIFY(self); - pendingResetLocalOperation = [CKKSResultOperation named:@"reset-local" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull strongOp) { + NSBlockOperation *seemReady = [NSBlockOperation named:[NSString stringWithFormat:@"seemsReadyForSyncing-%@", self.zoneName] withBlock:^void{ STRONGIFY(self); - __block NSError* error = nil; + NSError *error = nil; + ckksnotice("launch", self, "Launch complete"); + NSNumber *zoneSize = [CKKSMirrorEntry counts:self.zoneID error:&error]; + if (zoneSize) { + zoneSize = @(SecBucket1Significant([zoneSize longValue])); + [self.launch addAttribute:@"zonesize" value:zoneSize]; + } + [self.launch launch]; - [self dispatchSync: ^bool{ - [self _onqueueResetLocalData: &error]; - return true; - }]; - - strongOp.error = error; + /* + * Since we think we are ready, signal to CK that its to check for PCS identities again, and create the + * since before we completed this operation, we would probably have failed with a timeout because + * we where busy downloading items from CloudKit and then processing them. + */ + [self.viewState.notifyViewReadyScheduler trigger]; }]; - [pendingResetLocalOperation linearDependencies:self.localResetOperations]; - } - return pendingResetLocalOperation; - } + + [seemReady addNullableDependency:self.keyStateReadyDependency]; + [seemReady addNullableDependency:outgoingOperation]; + [seemReady addNullableDependency:initialScan]; + [seemReady addNullableDependency:initialProcess]; + [self scheduleOperation:seemReady]; + + return CKKSDatabaseTransactionCommit; + }]; + }]; } - (CKKSResultOperation*)resetLocalData { - // Not overly thread-safe, but a single read is okay - CKKSAccountStatus accountStatus = self.accountStatus; ckksnotice("ckksreset", self, "Requesting local data reset"); - // If we're currently signed in, the reset operation will be handled by the CKKS key state machine, and a reset should end up in 'ready' - if(accountStatus == CKKSAccountStatusAvailable) { - WEAKIFY(self); - CKKSGroupOperation* resetOperationGroup = [CKKSGroupOperation named:@"local-reset" withBlockTakingSelf:^(CKKSGroupOperation *strongOp) { - STRONGIFY(self); - - __block CKKSResultOperation* resetOperation = nil; - - [self dispatchSyncWithAccountKeys:^bool { - self.keyStateLocalResetRequested = true; - resetOperation = [self createPendingResetLocalDataOperation]; - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; - }]; - - [strongOp dependOnBeforeGroupFinished:resetOperation]; - }]; - [self scheduleOperationWithoutDependencies:resetOperationGroup]; - - CKKSGroupOperation* viewReset = [CKKSGroupOperation named:@"local-data-reset" withBlockTakingSelf:^(CKKSGroupOperation *strongOp) { - STRONGIFY(self); - // Now that the local reset finished, wait for the key hierarchy state machine to churn - ckksnotice("ckksreset", self, "waiting for key hierarchy to become nontransient (after local reset)"); - CKKSResultOperation* waitOp = [CKKSResultOperation named:@"waiting-for-local-reset" withBlock:^{}]; - [waitOp timeout: 60*NSEC_PER_SEC]; - [waitOp addNullableDependency:self.keyStateNonTransientDependency]; - - [strongOp runBeforeGroupFinished:waitOp]; - }]; - [viewReset addSuccessDependency:resetOperationGroup]; - - [self scheduleOperationWithoutDependencies:viewReset]; - return viewReset; - } else { - // Since we're logged out, we must run the reset ourselves - WEAKIFY(self); - CKKSResultOperation* pendingResetLocalOperation = [CKKSResultOperation named:@"reset-local" - withBlockTakingSelf:^(CKKSResultOperation * _Nonnull strongOp) { - STRONGIFY(self); - __block NSError* error = nil; - - [self dispatchSync: ^bool{ - [self _onqueueResetLocalData: &error]; - return true; - }]; - - strongOp.error = error; - }]; - [self scheduleOperationWithoutDependencies:pendingResetLocalOperation]; - return pendingResetLocalOperation; - } + return [self.stateMachine doWatchedStateMachineRPC:@"ckks-local-reset" + sourceStates:[NSSet setWithArray:@[ + // TODO: possibly every state? + SecCKKSZoneKeyStateReady, + SecCKKSZoneKeyStateWaitForTLK, + SecCKKSZoneKeyStateWaitForTrust, + SecCKKSZoneKeyStateWaitForTLKUpload, + SecCKKSZoneKeyStateLoggedOut, + ]] + path:[OctagonStateTransitionPath pathFromDictionary:@{ + SecCKKSZoneKeyStateResettingLocalData: @{ + SecCKKSZoneKeyStateInitializing: @{ + SecCKKSZoneKeyStateInitialized: [OctagonStateTransitionPathStep success], + SecCKKSZoneKeyStateLoggedOut: [OctagonStateTransitionPathStep success], + } + } + }] + reply:^(NSError * _Nonnull error) {}]; } -- (CKKSResultOperation*)createPendingDeleteZoneOperation:(CKOperationGroup*)operationGroup { - @synchronized(self.cloudkitDeleteZoneOperations) { - CKKSResultOperation* pendingDeleteOperation = (CKKSResultOperation*) [self findFirstPendingOperation:self.cloudkitDeleteZoneOperations]; - if(!pendingDeleteOperation) { - pendingDeleteOperation = [self deleteCloudKitZoneOperation:operationGroup]; - [pendingDeleteOperation linearDependencies:self.cloudkitDeleteZoneOperations]; - } - return pendingDeleteOperation; - } -} - -- (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup { +- (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup +{ [self.accountStateKnown wait:(SecCKKSTestsEnabled() ? 1*NSEC_PER_SEC : 10*NSEC_PER_SEC)]; // Not overly thread-safe, but a single read is okay @@ -716,777 +493,660 @@ return errorOp; } - // Actually running the delete operation will be handled by the CKKS key state machine ckksnotice("ckksreset", self, "Requesting reset of CK zone (logged in)"); - - __block CKKSResultOperation* deleteOperation = nil; - [self dispatchSyncWithAccountKeys:^bool { - self.keyStateCloudKitDeleteRequested = true; - deleteOperation = [self createPendingDeleteZoneOperation:operationGroup]; - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; - }]; - WEAKIFY(self); - CKKSGroupOperation* viewReset = [CKKSGroupOperation named:[NSString stringWithFormat:@"cloudkit-view-reset-%@", self.zoneName] - withBlockTakingSelf:^(CKKSGroupOperation *strongOp) { - STRONGIFY(self); - // Now that the delete finished, wait for the key hierarchy state machine - ckksnotice("ckksreset", self, "waiting for key hierarchy to become nontransient (after cloudkit reset)"); - CKKSResultOperation* waitOp = [CKKSResultOperation named:@"waiting-for-reset" withBlock:^{}]; - [waitOp timeout: 60*NSEC_PER_SEC]; - [waitOp addNullableDependency:self.keyStateNonTransientDependency]; + NSDictionary* localResetPath = @{ + SecCKKSZoneKeyStateInitializing: @{ + SecCKKSZoneKeyStateInitialized: [OctagonStateTransitionPathStep success], + SecCKKSZoneKeyStateLoggedOut: [OctagonStateTransitionPathStep success], + }, + }; - [strongOp runBeforeGroupFinished:waitOp]; - }]; + // If the zone delete doesn't work, try it up to two more times - [viewReset timeout:30*NSEC_PER_SEC]; - [viewReset addDependency:deleteOperation]; - [self.waitingQueue addOperation:viewReset]; - - return viewReset; -} - -- (void)_onqueueKeyStateMachineRequestFetch { - dispatch_assert_queue(self.queue); - - // We're going to set this flag, then nudge the key state machine. - // If it was idle, then it should launch a fetch. If there was an active process, this flag will stay high - // and the fetch will be launched later. - - self.keyStateFetchRequested = true; - [self _onqueueAdvanceKeyStateMachineToState: nil withError: nil]; + return [self.stateMachine doWatchedStateMachineRPC:@"ckks-cloud-reset" + sourceStates:[NSSet setWithArray:@[ + // TODO: possibly every state? + SecCKKSZoneKeyStateReady, + SecCKKSZoneKeyStateInitialized, + SecCKKSZoneKeyStateFetchComplete, + SecCKKSZoneKeyStateWaitForTLK, + SecCKKSZoneKeyStateWaitForTrust, + SecCKKSZoneKeyStateWaitForTLKUpload, + SecCKKSZoneKeyStateLoggedOut, + ]] + path:[OctagonStateTransitionPath pathFromDictionary:@{ + SecCKKSZoneKeyStateResettingZone: @{ + SecCKKSZoneKeyStateResettingLocalData: localResetPath, + SecCKKSZoneKeyStateResettingZone: @{ + SecCKKSZoneKeyStateResettingLocalData: localResetPath, + SecCKKSZoneKeyStateResettingZone: @{ + SecCKKSZoneKeyStateResettingLocalData: localResetPath, + } + } + } + }] + reply:^(NSError * _Nonnull error) {}]; } - (void)keyStateMachineRequestProcess { - // Since bools are atomic, we don't need to get on-queue here - // Just set the flag high and hope - self.keyStateProcessRequested = true; - [self.pokeKeyStateMachineScheduler trigger]; + [self.stateMachine handleFlag:CKKSFlagKeyStateProcessRequested]; } -- (void)_onqueueKeyStateMachineRequestProcess { - dispatch_assert_queue(self.queue); - - // Set the request flag, then nudge the key state machine. - // If it was idle, then it should launch a process. If there was an active process, this flag will stay high - // and the process will be launched later. - - self.keyStateProcessRequested = true; - [self _onqueueAdvanceKeyStateMachineToState: nil withError: nil]; -} - -- (CKKSResultOperation*)createKeyStateReadyDependency:(NSString*)message ckoperationGroup:(CKOperationGroup*)group { +- (CKKSResultOperation*)createKeyStateReadyDependency:(NSString*)message { WEAKIFY(self); CKKSResultOperation* keyStateReadyDependency = [CKKSResultOperation operationWithBlock:^{ STRONGIFY(self); - if(!self) { - return; - } - ckksnotice("ckkskey", self, "%@", message); - - [self dispatchSync:^bool { - if(self.droppedItems) { - // While we weren't in 'ready', keychain modifications might have come in and were dropped on the floor. Find them! - ckksnotice("ckkskey", self, "Launching scan operation for missed items"); - [self scanLocalItems:@"ready-again-scan" ckoperationGroup:group after:nil]; - } - return true; - }]; + ckksnotice("ckkskey", self, "CKKS became ready: %@", message); }]; keyStateReadyDependency.name = [NSString stringWithFormat: @"%@-key-state-ready", self.zoneName]; keyStateReadyDependency.descriptionErrorCode = CKKSResultDescriptionPendingKeyReady; return keyStateReadyDependency; } -- (CKKSResultOperation*)createKeyStateNontransientDependency { - WEAKIFY(self); - return [CKKSResultOperation named:[NSString stringWithFormat: @"%@-key-state-nontransient", self.zoneName] withBlock:^{ - STRONGIFY(self); - ckksnotice("ckkskey", self, "Key state is now non-transient"); - }]; +- (void)_onqueuePokeKeyStateMachine +{ + dispatch_assert_queue(self.queue); + [self.stateMachine _onqueuePokeStateMachine]; } -// The operations suggested by this state machine should call _onqueueAdvanceKeyStateMachineToState once they are complete. -// At no other time should keyHierarchyState be modified. - -// Note that this function cannot rely on doing any database work; it might get rolled back, especially in an error state -- (void)_onqueueAdvanceKeyStateMachineToState: (CKKSZoneKeyState*) state withError: (NSError*) error { +- (CKKSResultOperation* _Nullable)_onqueueNextStateMachineTransition:(OctagonState*)currentState + flags:(OctagonFlags*)flags + pendingFlags:(id)pendingFlagHandler +{ dispatch_assert_queue(self.queue); - WEAKIFY(self); // Resetting back to 'loggedout' takes all precedence. - if([state isEqual:SecCKKSZoneKeyStateLoggedOut]) { - ckksnotice("ckkskey", self, "Resetting the key hierarchy state machine back to '%@'", state); + if([flags _onqueueContains:CKKSFlagCloudKitLoggedOut]) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedOut]; + ckksnotice("ckkskey", self, "CK account is not present"); - [self _onqueueResetSetup:SecCKKSZoneKeyStateLoggedOut - resetMessage:@"Key state has become ready for the first time (after reset)." - ckoperationGroup:[CKOperationGroup CKKSGroupWithName:@"key-state-after-logout"]]; - - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - self.launch = nil; - return; + [self ensureKeyStateReadyDependency:@"cloudkit-account-not-present"]; + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateLoggedOut + errorState:SecCKKSZoneKeyStateError]; } - [self.launch addEvent:state]; + if([flags _onqueueContains:CKKSFlagCloudKitZoneMissing]) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitZoneMissing]; - // Resetting back to 'initialized' also takes precedence - if([state isEqual:SecCKKSZoneKeyStateInitializing]) { - ckksnotice("ckkskey", self, "Resetting the key hierarchy state machine back to '%@'", state); - - [self _onqueueResetSetup:SecCKKSZoneKeyStateInitializing - resetMessage:@"Key state has become ready for the first time (after re-initializing)." - ckoperationGroup:[CKOperationGroup CKKSGroupWithName:@"key-state-reset-to-initializing"]]; - - // Begin initialization, but rate-limit it - self.keyStateMachineOperation = [self createPendingInitializationOperation]; - [self.keyStateMachineOperation addNullableDependency:self.zoneModifier.cloudkitRetryAfter.operationDependency]; - [self.zoneModifier.cloudkitRetryAfter trigger]; - [self scheduleOperation:self.keyStateMachineOperation]; - - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; + [self ensureKeyStateReadyDependency:@"cloudkit-zone-missing"]; + // The zone is gone! Let's reset our local state, which will feed into recreating the zone + return [OctagonStateTransitionOperation named:@"ck-zone-missing" + entering:SecCKKSZoneKeyStateResettingLocalData]; } - // Resetting to 'waitfortrust' also takes precedence - if([state isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) { - if([self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateLoggedOut]) { - ckksnotice("ckks", self, "Asked to waitfortrust, but we're already in loggedout. Ignoring..."); - return; + if([flags _onqueueContains:CKKSFlagChangeTokenExpired]) { + [flags _onqueueRemoveFlag:CKKSFlagChangeTokenExpired]; + + [self ensureKeyStateReadyDependency:@"cloudkit-change-token-expired"]; + // Our change token is invalid! We'll have to refetch the world, so let's delete everything locally. + return [OctagonStateTransitionOperation named:@"ck-token-expired" + entering:SecCKKSZoneKeyStateResettingLocalData]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateLoggedOut]) { + if([flags _onqueueContains:CKKSFlagCloudKitLoggedIn] || self.accountStatus == CKKSAccountStatusAvailable) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedIn]; + + ckksnotice("ckkskey", self, "CloudKit account now present"); + return [OctagonStateTransitionOperation named:@"ck-sign-in" + entering:SecCKKSZoneKeyStateInitializing]; } - ckksnotice("ckks", self, "Entering waitfortrust"); - self.keyHierarchyState = SecCKKSZoneKeyStateWaitForTrust; - self.keyHierarchyError = nil; - self.keyStateMachineOperation = nil; + if([flags _onqueueContains:CKKSFlag24hrNotification]) { + [flags _onqueueRemoveFlag:CKKSFlag24hrNotification]; + } + return nil; + } - [self ensureKeyStateReadyDependency:@"Key state has become ready for the first time (after lacking trust)."]; + if([currentState isEqualToString: SecCKKSZoneKeyStateWaitForCloudKitAccountStatus]) { + if([flags _onqueueContains:CKKSFlagCloudKitLoggedIn] || self.accountStatus == CKKSAccountStatusAvailable) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedIn]; - if(self.trustStatus == CKKSAccountStatusAvailable) { - // Note: we go to initialized here, since to enter waitfortrust CKKS has already gone through initializing - // initialized should refetch only if needed. - ckksnotice("ckks", self, "CKKS is trusted, moving to initialized"); - self.keyStateMachineOperation = [self operationToEnterState:SecCKKSZoneKeyStateInitialized - keyStateError:nil - named:@"re-enter initialized"]; - [self scheduleOperation:self.keyStateMachineOperation]; + ckksnotice("ckkskey", self, "CloudKit account now present"); + return [OctagonStateTransitionOperation named:@"ck-sign-in" + entering:SecCKKSZoneKeyStateInitializing]; } - // In wait for trust, we might have a keyset. Who knows! - CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - [self _onqueueHandleKeyStateNonTransientDependency:keyset]; + if([flags _onqueueContains:CKKSFlagCloudKitLoggedOut]) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedOut]; + ckksnotice("ckkskey", self, "No account available"); - return; - } - - // Cancels and error states take precedence - if([self.keyHierarchyState isEqualToString: SecCKKSZoneKeyStateError] || - [self.keyHierarchyState isEqualToString: SecCKKSZoneKeyStateCancelled] || - self.keyHierarchyError != nil) { - // Error state: nowhere to go. Early-exit. - ckkserror("ckkskey", self, "Asked to advance state machine from non-exit state %@ (to %@): %@", self.keyHierarchyState, state, self.keyHierarchyError); - return; - } - - if([state isEqual: SecCKKSZoneKeyStateError]) { - // But wait! Is this a "we're locked" error? - if(error && [self.lockStateTracker isLockedError:error]) { - ckkserror("ckkskey", self, "advised of 'keychain locked' error, ignoring: coming from state (%@): %@", self.keyHierarchyState, error); - // After the next unlock, fake that we received the last zone transition - CKKSZoneKeyState* lastState = self.keyHierarchyState; - self.keyStateMachineOperation = [NSBlockOperation named:@"key-state-after-unlock" withBlock:^{ - STRONGIFY(self); - if(!self) { - return; - } - [self dispatchSyncWithAccountKeys:^bool{ - [self _onqueueAdvanceKeyStateMachineToState:lastState withError:nil]; - return true; - }]; - }]; - state = nil; - - self.keyHierarchyState = SecCKKSZoneKeyStateWaitForUnlock; - - [self.keyStateMachineOperation addNullableDependency:self.lockStateTracker.unlockDependency]; - [self scheduleOperation:self.keyStateMachineOperation]; - - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; - - } else { - // Error state: record the error and exit early - ckkserror("ckkskey", self, "advised of error: coming from state (%@): %@", self.keyHierarchyState, error); - - [[CKKSAnalytics logger] logUnrecoverableError:error - forEvent:CKKSEventStateError - inView:self - withAttributes:@{ @"previousKeyHierarchyState" : self.keyHierarchyState }]; - - - self.keyHierarchyState = SecCKKSZoneKeyStateError; - self.keyHierarchyError = error; - - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateLoggedOut + errorState:SecCKKSZoneKeyStateError]; } + return nil; } - if([state isEqual: SecCKKSZoneKeyStateCancelled]) { - ckkserror("ckkskey", self, "advised of cancel: coming from state (%@): %@", self.keyHierarchyState, error); - self.keyHierarchyState = SecCKKSZoneKeyStateCancelled; - self.keyHierarchyError = error; + [self.launch addEvent:currentState]; - // Cancel the key ready dependency. Strictly Speaking, this will cause errors down the line, but we're in a cancel state: those operations should be canceled anyway. - self.keyHierarchyOperationGroup = nil; - [self.keyStateReadyDependency cancel]; - self.keyStateReadyDependency = nil; - - [self.keyStateNonTransientDependency cancel]; - self.keyStateNonTransientDependency = nil; - return; - } - - // Now that the current or new state isn't an error or a cancel, proceed. - if(self.keyStateMachineOperation && ![self.keyStateMachineOperation isFinished]) { - if(state == nil) { - // we started this operation to move the state machine. Since you aren't asking for a state transition, and there's an active operation, no need to do anything - ckksnotice("ckkskey", self, "Not advancing state machine: waiting for %@", self.keyStateMachineOperation); - return; - } - } - - if(state) { - ckksnotice("ckkskey", self, "Preparing to advance key hierarchy state machine from %@ to %@", self.keyHierarchyState, state); - self.keyStateMachineOperation = nil; - } else { - ckksnotice("ckkskey", self, "Key hierarchy state machine is being poked; currently %@", self.keyHierarchyState); - state = self.keyHierarchyState; - } - -#if DEBUG - // During testing, keep the developer honest: this function should always have the self identities, unless the account has lost trust - if(self.trustStatus == CKKSAccountStatusAvailable && ![state isEqualToString:SecCKKSZoneKeyStateLoggedOut]) { - bool hasSelfIdentities = false; - NSAssert(self.currentTrustStates.count > 0, @"Should have at least one trust state"); - for(CKKSPeerProviderState* state in self.currentTrustStates) { - if(state.currentSelfPeersError == nil || state.currentSelfPeersError.code != CKKSNoPeersAvailable) { - hasSelfIdentities = true; - } + if([currentState isEqual:SecCKKSZoneKeyStateInitializing]) { + if(self.accountStatus == CKKSAccountStatusNoAccount) { + ckksnotice("ckkskey", self, "CloudKit account is missing. Departing!"); + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateLoggedOut + errorState:SecCKKSZoneKeyStateError]; } - NSAssert(hasSelfIdentities, @"Must have viable (or errored) self peers to advance key state"); + // Begin zone creation, but rate-limit it + CKKSCreateCKZoneOperation* pendingInitializeOp = [[CKKSCreateCKZoneOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateInitialized + errorState:SecCKKSZoneKeyStateZoneCreationFailed]; + [pendingInitializeOp addNullableDependency:self.operationDependencies.zoneModifier.cloudkitRetryAfter.operationDependency]; + [self.operationDependencies.zoneModifier.cloudkitRetryAfter trigger]; + + return pendingInitializeOp; } -#endif - // Do any of these state transitions below want to change which state we're in? - CKKSZoneKeyState* nextState = nil; - NSError* nextError = nil; + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForFixupOperation]) { + // TODO: fixup operations should become part of the state machine + ckksnotice("ckkskey", self, "Waiting for the fixup operation: %@", self.lastFixupOperation); + OctagonStateTransitionOperation* op = [OctagonStateTransitionOperation named:@"wait-for-fixup" entering:SecCKKSZoneKeyStateInitialized]; + [op addNullableDependency:self.lastFixupOperation]; + return op; + } - // Any state that wants should fill this in; it'll be used at the end of this function as well - CKKSCurrentKeySet* keyset = nil; + if([currentState isEqualToString:SecCKKSZoneKeyStateInitialized]) { + // We're initialized and CloudKit is ready. If we're trusted, see what needs done. Otherwise, wait. + return [self performInitializedOperation]; + } -#if !defined(NDEBUG) - { - NSError* localerror = nil; - NSError* allKeysError = nil; - NSArray* allKeys = [CKKSKey allKeys:self.zoneID error:&allKeysError]; + // In error? You probably aren't getting out. + if([currentState isEqualToString:SecCKKSZoneKeyStateError]) { + if([flags _onqueueContains:CKKSFlagCloudKitLoggedIn]) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedIn]; - if(localerror) { - ckkserror("ckkskey", self, "couldn't fetch all keys from local database, entering error state: %@", allKeysError); + // Worth one last shot. Reset everything locally, and try again. + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateInitializing + errorState:SecCKKSZoneKeyStateError]; } - ckksdebug("ckkskey", self, "All keys: %@", allKeys); + + ckkserror("ckkskey", self, "Staying in error state %@", currentState); + return nil; } -#endif - NSError* hierarchyError = nil; - - if(self.keyStateCloudKitDeleteRequested || [state isEqualToString:SecCKKSZoneKeyStateResettingZone]) { - // CloudKit reset requests take precedence over all other state transitions + if([currentState isEqualToString:SecCKKSZoneKeyStateResettingZone]) { ckksnotice("ckkskey", self, "Deleting the CloudKit Zone"); - CKKSGroupOperation* op = [[CKKSGroupOperation alloc] init]; - CKKSResultOperation* deleteOp = [self createPendingDeleteZoneOperation:self.keyHierarchyOperationGroup]; - [op runBeforeGroupFinished: deleteOp]; + [self ensureKeyStateReadyDependency:@"ck-zone-reset"]; + return [[CKKSDeleteCKZoneOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateResettingLocalData + errorState:SecCKKSZoneKeyStateResettingZone]; + } - NSOperation* nextStateOp = [CKKSResultOperation named:@"inspect-zone-delete" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { - STRONGIFY(self); - [self dispatchSyncWithAccountKeys:^bool { - // Did the delete op succeed? - if(deleteOp.error == nil) { - ckksnotice("ckkskey", self, "Zone deletion operation complete! Proceeding to reset local data"); - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateResettingLocalData withError:nil]; - return true; - } - - ckksnotice("ckkskey", self, "Zone deletion operation failed, will retry: %@", deleteOp.error); - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateResettingZone withError:nil]; - - return true; - }]; - }]; - - [nextStateOp addDependency:deleteOp]; - [op runBeforeGroupFinished:nextStateOp]; - - self.keyStateMachineOperation = op; - self.keyStateCloudKitDeleteRequested = false; - - // Also, pending operations should be cancelled - [self cancelPendingOperations]; - - } else if(self.keyStateLocalResetRequested || [state isEqualToString:SecCKKSZoneKeyStateResettingLocalData]) { - // Local reset requests take precedence over all other state transitions + if([currentState isEqualToString:SecCKKSZoneKeyStateResettingLocalData]) { ckksnotice("ckkskey", self, "Resetting local data"); - CKKSGroupOperation* op = [[CKKSGroupOperation alloc] init]; - CKKSResultOperation* resetOp = [self createPendingResetLocalDataOperation]; - [op runBeforeGroupFinished: resetOp]; + [self ensureKeyStateReadyDependency:@"local-data-reset"]; + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateInitializing + errorState:SecCKKSZoneKeyStateError]; + } - NSOperation* nextStateOp = [self operationToEnterState:SecCKKSZoneKeyStateInitializing keyStateError:nil named:@"state-resetting-initialize"]; - [nextStateOp addDependency:resetOp]; - [op runBeforeGroupFinished:nextStateOp]; - - self.keyStateMachineOperation = op; - self.keyStateLocalResetRequested = false; - - } else if([state isEqualToString:SecCKKSZoneKeyStateZoneCreationFailed]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateZoneCreationFailed]) { //Prepare to go back into initializing, as soon as the cloudkitRetryAfter is happy - self.keyStateMachineOperation = [self operationToEnterState:SecCKKSZoneKeyStateInitializing keyStateError:nil named:@"recover-from-cloudkit-failure"]; - [self.keyStateMachineOperation addNullableDependency:self.zoneModifier.cloudkitRetryAfter.operationDependency]; - [self.zoneModifier.cloudkitRetryAfter trigger]; + OctagonStateTransitionOperation* op = [OctagonStateTransitionOperation named:@"recover-from-cloudkit-failure" entering:SecCKKSZoneKeyStateInitializing]; - } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) { - // Actually entering this state should have been handled above, so let's check if we can exit it here... + [op addNullableDependency:self.operationDependencies.zoneModifier.cloudkitRetryAfter.operationDependency]; + [self.operationDependencies.zoneModifier.cloudkitRetryAfter trigger]; + + return op; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateLoseTrust]) { + if([flags _onqueueContains:CKKSFlagBeginTrustedOperation]) { + [flags _onqueueRemoveFlag:CKKSFlagBeginTrustedOperation]; + // This was likely a race between some operation and the beginTrustedOperation call! Skip changing state and try again. + return [OctagonStateTransitionOperation named:@"begin-trusted-operation" entering:SecCKKSZoneKeyStateInitialized]; + } + + // If our current state is "trusted", fall out + if(self.trustStatus == CKKSAccountStatusAvailable) { + self.trustStatus = CKKSAccountStatusUnknown; + } + return [OctagonStateTransitionOperation named:@"trust-loss" entering:SecCKKSZoneKeyStateWaitForTrust]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) { if(self.trustStatus == CKKSAccountStatusAvailable) { ckksnotice("ckkskey", self, "Beginning trusted state machine operation"); - nextState = SecCKKSZoneKeyStateInitialized; - - } else if (self.tlkCreationRequested) { - ckksnotice("ckkskey", self, "No trust, but TLK creation is requested. Moving to fetchcomplete."); - nextState = SecCKKSZoneKeyStateFetchComplete; - - } else { - ckksnotice("ckkskey", self, "Remaining in 'waitfortrust'"); + return [OctagonStateTransitionOperation named:@"begin-trusted-operation" entering:SecCKKSZoneKeyStateInitialized]; } - } else if([state isEqualToString: SecCKKSZoneKeyStateReady]) { - NSError* localerror = nil; - NSArray* remoteKeys = [CKKSKey remoteKeys:self.zoneID error: &localerror]; - - if(remoteKeys == nil || localerror) { - ckkserror("ckkskey", self, "couldn't fetch keys from local database, entering error state: %@", localerror); - self.keyHierarchyState = SecCKKSZoneKeyStateError; - self.keyHierarchyError = localerror; - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; + if([flags _onqueueContains:CKKSFlagFetchRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagFetchRequested]; + return [OctagonStateTransitionOperation named:@"fetch-requested" entering:SecCKKSZoneKeyStateBeginFetch]; } - if(self.keyStateProcessRequested || [remoteKeys count] > 0) { - // We've either received some remote keys from the last fetch, or someone has requested a reprocess. - ckksnotice("ckkskey", self, "Kicking off a key reprocess based on request:%d and remote key count %lu", self.keyStateProcessRequested, (unsigned long)[remoteKeys count]); - nextState = SecCKKSZoneKeyStateProcess; + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; + return [OctagonStateTransitionOperation named:@"begin-trusted-operation" entering:SecCKKSZoneKeyStateProcess]; + } - } else if(self.keyStateFullRefetchRequested) { - // In ready, but someone has requested a full fetch. Kick it off. + if([flags _onqueueContains:CKKSFlagKeySetRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeySetRequested]; + return [OctagonStateTransitionOperation named:@"process" entering:SecCKKSZoneKeyStateProcess]; + } + + if([flags _onqueueContains:CKKSFlag24hrNotification]) { + [flags _onqueueRemoveFlag:CKKSFlag24hrNotification]; + } + + return nil; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateBecomeReady]) { + return [[CKKSCheckKeyHierarchyOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateReady]) { + // If we're ready, we can ignore the begin trusted flag + [flags _onqueueRemoveFlag:CKKSFlagBeginTrustedOperation]; + + if(self.keyStateFullRefetchRequested) { + // In ready, but something has requested a full refetch. ckksnotice("ckkskey", self, "Kicking off a full key refetch based on request:%d", self.keyStateFullRefetchRequested); - nextState = SecCKKSZoneKeyStateNeedFullRefetch; + [self ensureKeyStateReadyDependency:@"key-state-full-refetch"]; + return [OctagonStateTransitionOperation named:@"full-refetch" entering:SecCKKSZoneKeyStateNeedFullRefetch]; + } - } else if(self.keyStateFetchRequested) { - // In ready, but someone has requested a fetch. Kick it off. - ckksnotice("ckkskey", self, "Kicking off a key refetch based on request:%d", self.keyStateFetchRequested); - nextState = SecCKKSZoneKeyStateFetch; // Don't go to 'ready', go to 'initialized', since we want to fetch again - } else if (self.trustStatus != CKKSAccountStatusAvailable) { - ckksnotice("ckkskey", self, "Asked to go into ready, but there's no trust; going into waitfortrust"); - nextState = SecCKKSZoneKeyStateWaitForTrust; - } else if (self.trustedPeersSetChanged) { + if([flags _onqueueContains:CKKSFlagFetchRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagFetchRequested]; + ckksnotice("ckkskey", self, "Kicking off a key refetch based on request"); + [self ensureKeyStateReadyDependency:@"key-state-fetch"]; + return [OctagonStateTransitionOperation named:@"fetch-requested" entering:SecCKKSZoneKeyStateBeginFetch]; + } + + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; + ckksnotice("ckkskey", self, "Kicking off a key reprocess based on request"); + [self ensureKeyStateReadyDependency:@"key-state-process"]; + return [OctagonStateTransitionOperation named:@"key-process" entering:SecCKKSZoneKeyStateProcess]; + } + + if([flags _onqueueContains:CKKSFlagKeySetRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeySetRequested]; + [self ensureKeyStateReadyDependency:@"key-state-process"]; + return [OctagonStateTransitionOperation named:@"provide-key-set" entering:SecCKKSZoneKeyStateProcess]; + } + + if(self.trustStatus != CKKSAccountStatusAvailable) { + ckksnotice("ckkskey", self, "In ready, but there's no trust; going into waitfortrust"); + [self ensureKeyStateReadyDependency:@"trust loss"]; + return [OctagonStateTransitionOperation named:@"trust-gone" entering:SecCKKSZoneKeyStateLoseTrust]; + } + + if([flags _onqueueContains:CKKSFlagTrustedPeersSetChanged]) { + [flags _onqueueRemoveFlag:CKKSFlagTrustedPeersSetChanged]; ckksnotice("ckkskey", self, "Received a nudge that the trusted peers set might have changed! Reprocessing."); - nextState = SecCKKSZoneKeyStateProcess; - self.trustedPeersSetChanged = false; + [self ensureKeyStateReadyDependency:@"Peer set changed"]; + return [OctagonStateTransitionOperation named:@"trusted-peers-changed" entering:SecCKKSZoneKeyStateProcess]; + } + + if([flags _onqueueContains:CKKSFlag24hrNotification]) { + [flags _onqueueRemoveFlag:CKKSFlag24hrNotification]; + + // We'd like to trigger our 24-hr backup fetch and scan. + // That's currently part of the Initialized state, so head that way + return [OctagonStateTransitionOperation named:@"24-hr-check" entering:SecCKKSZoneKeyStateInitialized]; + } + + if([flags _onqueueContains:CKKSFlagItemReencryptionNeeded]) { + [flags _onqueueRemoveFlag:CKKSFlagItemReencryptionNeeded]; + + // TODO: this should be part of the state machine + CKKSReencryptOutgoingItemsOperation* op = [[CKKSReencryptOutgoingItemsOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intendedState:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError]; + [self scheduleOperation:op]; + // fall through. + } + + if([flags _onqueueContains:CKKSFlagProcessIncomingQueue]) { + [flags _onqueueRemoveFlag:CKKSFlagProcessIncomingQueue]; + // TODO: this should be part of the state machine + + [self processIncomingQueue:true]; + //return [OctagonStateTransitionOperation named:@"process-outgoing" entering:SecCKKSZoneKeyStateProcessIncomingQueue]; + } + + if([flags _onqueueContains:CKKSFlagScanLocalItems]) { + [flags _onqueueRemoveFlag:CKKSFlagScanLocalItems]; + ckksnotice("ckkskey", self, "Launching a scan operation to find dropped items"); + + // TODO: this should be a state flow + [self scanLocalItems:@"per-request"]; + // fall through + } + + if([flags _onqueueContains:CKKSFlagProcessOutgoingQueue]) { + [flags _onqueueRemoveFlag:CKKSFlagProcessOutgoingQueue]; + + [self processOutgoingQueue:nil]; + // TODO: this should be a state flow. + //return [OctagonStateTransitionOperation named:@"process-outgoing" entering:SecCKKSZoneKeyStateProcessOutgoingQueue]; + // fall through } // TODO: kick off a key roll if one has been requested - if(!self.keyStateMachineOperation && !nextState) { - // We think we're ready. Double check. - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - CKKSZoneKeyState* checkedstate = [self _onqueueEnsureKeyHierarchyHealth:keyset error:&hierarchyError]; - if(![checkedstate isEqualToString:SecCKKSZoneKeyStateReady] || hierarchyError) { - // Things is bad. Kick off a heal to fix things up. - ckksnotice("ckkskey", self, "Thought we were ready, but the key hierarchy is %@: %@", checkedstate, hierarchyError); - nextState = checkedstate; - if([nextState isEqualToString:SecCKKSZoneKeyStateError]) { - nextError = hierarchyError; - } - } + + // If we reach this point, we're in ready, and will stay there. + // Tell the launch and the viewReadyScheduler about that. + + [self.launch launch]; + + [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastKeystateReady zoneName:self.zoneName]; + if(self.keyStateReadyDependency) { + [self scheduleOperation:self.keyStateReadyDependency]; + self.keyStateReadyDependency = nil; } - } else if([state isEqualToString: SecCKKSZoneKeyStateInitialized]) { - // We're initialized and CloudKit is ready. If we're trusted, see what needs done. Otherwise, wait. + return nil; + } - // Note: we might be still 'untrusted' at this point. The state machine is responsible for not entering 'ready' until - // we are trusted. - // This is acceptable only if the key state machine does not make new TLKs without being trusted! - - // Set this state, for test use - self.keyHierarchyState = SecCKKSZoneKeyStateInitialized; - - CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName]; - [self _onqueuePerformKeyStateInitialized:ckse]; - - // We need to either: - // Wait for the fixup operation to occur - // Go into 'ready' - // Or start a key state fetch - if(self.lastFixupOperation && ![self.lastFixupOperation isFinished]) { - nextState = SecCKKSZoneKeyStateWaitForFixupOperation; - } else { - // Check if we have an existing key hierarchy in keyset - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - if(keyset.error && !([keyset.error.domain isEqual: @"securityd"] && keyset.error.code == errSecItemNotFound)) { - ckkserror("ckkskey", self, "Error examining existing key hierarchy: %@", error); - } - - if(keyset.tlk && keyset.classA && keyset.classC && !keyset.error) { - // This is likely a restart of securityd, and we think we're ready. Double check. - - CKKSZoneKeyState* checkedstate = [self _onqueueEnsureKeyHierarchyHealth:keyset error:&hierarchyError]; - if([checkedstate isEqualToString:SecCKKSZoneKeyStateReady] && !hierarchyError) { - ckksnotice("ckkskey", self, "Already have existing key hierarchy for %@; using it.", self.zoneID.zoneName); - } else { - ckksnotice("ckkskey", self, "Initial scan shows key hierarchy is %@: %@", checkedstate, hierarchyError); - } - nextState = checkedstate; - - } else { - // We have no local key hierarchy. One might exist in CloudKit, or it might not. - ckksnotice("ckkskey", self, "No existing key hierarchy for %@. Check if there's one in CloudKit...", self.zoneID.zoneName); - nextState = SecCKKSZoneKeyStateFetch; - } + if([currentState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]) { + if([flags _onqueueContains:CKKSFlagDeviceUnlocked]) { + [flags _onqueueRemoveFlag:CKKSFlagDeviceUnlocked]; + [self ensureKeyStateReadyDependency:@"Device unlocked"]; + return [OctagonStateTransitionOperation named:@"key-state-ready-after-unlock" entering:SecCKKSZoneKeyStateBecomeReady]; } - } else if([state isEqualToString:SecCKKSZoneKeyStateFetch]) { + if([flags _onqueueContains:CKKSFlagProcessOutgoingQueue]) { + [flags _onqueueRemoveFlag:CKKSFlagProcessOutgoingQueue]; + [self processOutgoingQueue:nil]; + // TODO: this should become part of the key state hierarchy + } + + // Ready enough! + + [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastKeystateReady zoneName:self.zoneName]; + if(self.keyStateReadyDependency) { + [self scheduleOperation:self.keyStateReadyDependency]; + self.keyStateReadyDependency = nil; + } + + OctagonPendingFlag* unlocked = [[OctagonPendingFlag alloc] initWithFlag:CKKSFlagDeviceUnlocked + conditions:OctagonPendingConditionsDeviceUnlocked]; + [pendingFlagHandler _onqueueHandlePendingFlag:unlocked]; + return nil; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateBeginFetch]) { ckksnotice("ckkskey", self, "Starting a key hierarchy fetch"); - [self _onqueueKeyHierarchyFetch]; + [flags _onqueueRemoveFlag:CKKSFlagFetchComplete]; - } else if([state isEqualToString: SecCKKSZoneKeyStateNeedFullRefetch]) { - ckksnotice("ckkskey", self, "Starting a key hierarchy full refetch"); - [self _onqueueKeyHierarchyFetchForReasons:[NSSet setWithObjects:CKKSFetchBecauseKeyHierarchy, CKKSFetchBecauseResync, nil]]; - self.keyStateMachineRefetched = true; - self.keyStateFullRefetchRequested = false; + WEAKIFY(self); - } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForFixupOperation]) { - // We should enter 'initialized' when the fixup operation completes - ckksnotice("ckkskey", self, "Waiting for the fixup operation: %@", self.lastFixupOperation); + NSSet* fetchReasons = self.currentFetchReasons ? + [self.currentFetchReasons setByAddingObject:CKKSFetchBecauseKeyHierarchy] : + [NSSet setWithObject:CKKSFetchBecauseKeyHierarchy]; - self.keyStateMachineOperation = [NSBlockOperation named:@"key-state-after-fixup" withBlock:^{ + CKKSResultOperation* fetchOp = [self.zoneChangeFetcher requestSuccessfulFetchForManyReasons:fetchReasons]; + CKKSResultOperation* flagOp = [CKKSResultOperation named:@"post-fetch" + withBlock:^{ STRONGIFY(self); - [self dispatchSyncWithAccountKeys:^bool{ - ckksnotice("ckkskey", self, "Fixup operation complete! Restarting key hierarchy machinery"); - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateInitialized withError:nil]; - return true; - }]; + [self.stateMachine handleFlag:CKKSFlagFetchComplete]; }]; - [self.keyStateMachineOperation addNullableDependency:self.lastFixupOperation]; + [flagOp addDependency:fetchOp]; + [self scheduleOperation:flagOp]; - } else if([state isEqualToString: SecCKKSZoneKeyStateFetchComplete]) { - // We've just completed a fetch of everything. Are there any remote keys? - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; + return [OctagonStateTransitionOperation named:@"waiting-for-fetch" entering:SecCKKSZoneKeyStateFetch]; + } - NSError* localerror = nil; - - NSArray* localKeys = [CKKSKey localKeys:self.zoneID error:&localerror]; - NSArray* remoteKeys = [CKKSKey remoteKeys:self.zoneID error: &localerror]; - - if(localKeys == nil || remoteKeys == nil || localerror) { - ckkserror("ckkskey", self, "couldn't fetch keys from local database, entering error state: %@", localerror); - self.keyHierarchyState = SecCKKSZoneKeyStateError; - self.keyHierarchyError = localerror; - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; + if([currentState isEqualToString:SecCKKSZoneKeyStateFetch]) { + if([flags _onqueueContains:CKKSFlagFetchComplete]) { + [flags _onqueueRemoveFlag:CKKSFlagFetchComplete]; + return [OctagonStateTransitionOperation named:@"fetch-complete" entering:SecCKKSZoneKeyStateFetchComplete]; } - if(remoteKeys.count > 0u) { - // Process the keys we received. - self.keyStateMachineOperation = [[CKKSProcessReceivedKeysStateMachineOperation alloc] initWithCKKSKeychainView: self]; - } else if( (keyset.currentTLKPointer || keyset.currentClassAPointer || keyset.currentClassCPointer) && - !(keyset.tlk && keyset.classA && keyset.classC)) { - // Huh. We appear to have current key pointers, but the keys themselves don't exist. That's weird. - // Transfer to the "unhealthy" state to request a fix - ckksnotice("ckkskey", self, "We appear to have current key pointers but no keys to match them: %@ Moving to 'unhealthy'", keyset); - nextState = SecCKKSZoneKeyStateUnhealthy; - } else { - // No remote keys, and the pointers look sane? Do we have an existing key hierarchy? - CKKSZoneKeyState* checkedstate = [self _onqueueEnsureKeyHierarchyHealth:keyset error:&hierarchyError]; - if([checkedstate isEqualToString:SecCKKSZoneKeyStateReady] && !hierarchyError) { - ckksnotice("ckkskey", self, "After fetch, everything looks good."); - nextState = checkedstate; + // The flags CKKSFlagCloudKitZoneMissing and CKKSFlagChangeTokenOutdated are both handled at the top of this function + // So, we don't need to handle them here. - } else if(localKeys.count == 0 && remoteKeys.count == 0) { - ckksnotice("ckkskey", self, "After fetch, we don't have any key hierarchy. Entering a waiting state: %@", hierarchyError ?: @"no error"); - nextState = SecCKKSZoneKeyStateWaitForTLKCreation; - } else { - ckksnotice("ckkskey", self, "After fetch, we have a possibly unhealthy key hierarchy. Moving to %@: %@", checkedstate, hierarchyError ?: @"no error"); - nextState = checkedstate; - } - } + return nil; + } - } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateNeedFullRefetch]) { + ckksnotice("ckkskey", self, "Starting a key hierarchy full refetch"); - if(self.tlkCreationRequested) { - self.tlkCreationRequested = false; - ckksnotice("ckkskey", self, "TLK creation requested; kicking off operation"); - self.keyStateMachineOperation = [[CKKSNewTLKOperation alloc] initWithCKKSKeychainView: self ckoperationGroup:self.keyHierarchyOperationGroup]; + //TODO use states here instead of flags + self.keyStateMachineRefetched = true; + self.keyStateFullRefetchRequested = false; - } else if(self.keyStateProcessRequested) { + return [OctagonStateTransitionOperation named:@"fetch-complete" entering:SecCKKSZoneKeyStateResettingLocalData]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateFetchComplete]) { + [self.launch addEvent:@"fetch-complete"]; + [self.currentFetchReasons removeAllObjects]; + + return [OctagonStateTransitionOperation named:@"post-fetch-process" entering:SecCKKSZoneKeyStateProcess]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation]) { + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; ckksnotice("ckkskey", self, "We believe we need to create TLKs but we also received a key nudge; moving to key state Process."); - nextState = SecCKKSZoneKeyStateProcess; + return [OctagonStateTransitionOperation named:@"wait-for-tlk-creation-process" entering:SecCKKSZoneKeyStateProcess]; + + } else if([flags _onqueueContains:CKKSFlagFetchRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagFetchRequested]; + return [OctagonStateTransitionOperation named:@"fetch-requested" entering:SecCKKSZoneKeyStateBeginFetch]; + + } else if([flags _onqueueContains:CKKSFlagTLKCreationRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagTLKCreationRequested]; + + // It's very likely that we're already untrusted at this point. But, sometimes we will be trusted right now, and can lose trust while waiting for the upload. + // This probably should be handled by a state increase. + [flags _onqueueRemoveFlag:CKKSFlagEndTrustedOperation]; + + ckksnotice("ckkskey", self, "TLK creation requested; kicking off operation"); + return [[CKKSNewTLKOperation alloc] initWithDependencies:self.operationDependencies + ckks:self]; + } else if(self.lastNewTLKOperation.keyset) { + // This means that we _have_ created new TLKs, and should wait for them to be uploaded. This is ugly and should probably be done with more states. + return [OctagonStateTransitionOperation named:@"" entering:SecCKKSZoneKeyStateWaitForTLKUpload]; } else { ckksnotice("ckkskey", self, "We believe we need to create TLKs; waiting for Octagon (via %@)", self.suggestTLKUpload); [self.suggestTLKUpload trigger]; } + } - - } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload]) { ckksnotice("ckkskey", self, "We believe we have TLKs that need uploading"); - - if(self.keyStateProcessRequested) { - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - if(keyset.currentTLKPointer.currentKeyUUID) { - ckksnotice("ckkskey", self, "Received a nudge that our TLK records might be here (and there's some current TLK pointer)"); - nextState = SecCKKSZoneKeyStateProcess; - } else { - ckksnotice("ckkskey", self, "Received a nudge that our TLK records might be here, but there's no TLK pointer. Staying in WaitForTLKUpload."); - self.keyStateProcessRequested = false; - } + if([flags _onqueueContains:CKKSFlagFetchRequested]) { + ckksnotice("ckkskey", self, "Received a nudge to refetch CKKS"); + return [OctagonStateTransitionOperation named:@"tlk-upload-refetch" entering:SecCKKSZoneKeyStateBeginFetch]; } - if(nextState == nil) { - ckksnotice("ckkskey", self, "Alerting any listener of our proposed keyset: %@", self.lastNewTLKOperation.keyset); - [self _onqueueRunKeysetProviderOperations:self.lastNewTLKOperation.keyset]; + if([flags _onqueueContains:CKKSFlagKeyStateTLKsUploaded]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateTLKsUploaded]; - ckksnotice("ckkskey", self, "Notifying Octagon again, just in case"); - [self.suggestTLKUpload trigger]; + return [OctagonStateTransitionOperation named:@"wait-for-tlk-upload-process" entering:SecCKKSZoneKeyStateProcess]; } - } else if([state isEqualToString: SecCKKSZoneKeyStateWaitForTLK]) { + if([flags _onqueueContains:CKKSFlagEndTrustedOperation]) { + [flags _onqueueRemoveFlag:CKKSFlagEndTrustedOperation]; + + return [OctagonStateTransitionOperation named:@"trust-loss" entering:SecCKKSZoneKeyStateLoseTrust]; + } + + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + return [OctagonStateTransitionOperation named:@"wait-for-tlk-fetch-process" entering:SecCKKSZoneKeyStateProcess]; + } + + // This is quite the hack, but it'll do for now. + [flags _onqueueRemoveFlag:CKKSFlagKeySetRequested]; + [self.operationDependencies provideKeySet:self.lastNewTLKOperation.keyset]; + + ckksnotice("ckkskey", self, "Notifying Octagon again, just in case"); + [self.suggestTLKUpload trigger]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateTLKMissing]) { + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; + return [OctagonStateTransitionOperation named:@"wait-for-tlk-process" entering:SecCKKSZoneKeyStateProcess]; + } + + return [self tlkMissingOperation:SecCKKSZoneKeyStateWaitForTLK]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForTLK]) { // We're in a hold state: waiting for the TLK bytes to arrive. - if(self.keyStateProcessRequested) { + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; // Someone has requsted a reprocess! Go to the correct state. ckksnotice("ckkskey", self, "Received a nudge that our TLK might be here! Reprocessing."); - nextState = SecCKKSZoneKeyStateProcess; + return [OctagonStateTransitionOperation named:@"wait-for-tlk-process" entering:SecCKKSZoneKeyStateProcess]; + + } else if([flags _onqueueContains:CKKSFlagTrustedPeersSetChanged]) { + [flags _onqueueRemoveFlag:CKKSFlagTrustedPeersSetChanged]; - } else if(self.trustedPeersSetChanged) { // Hmm, maybe this trust set change will cause us to recover this TLK (due to a previously-untrusted share becoming trusted). Worth a shot! ckksnotice("ckkskey", self, "Received a nudge that the trusted peers set might have changed! Reprocessing."); - nextState = SecCKKSZoneKeyStateProcess; - self.trustedPeersSetChanged = false; - - } else { - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - - // Should we nuke this zone? - if(self.trustStatus == CKKSAccountStatusAvailable) { - if([self _onqueueOtherDevicesReportHavingTLKs:keyset]) { - ckksnotice("ckkskey", self, "Other devices report having TLK(%@). Entering a waiting state", keyset.currentTLKPointer); - } else { - ckksnotice("ckkskey", self, "No other devices have TLK(%@). Beginning zone reset...", keyset.currentTLKPointer); - self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"tlk-missing"]; - nextState = SecCKKSZoneKeyStateResettingZone; - } - } else { - ckksnotice("ckkskey", self, "This device isn't trusted, so don't modify the existing TLK(%@)", keyset.currentTLKPointer); - nextState = SecCKKSZoneKeyStateWaitForTrust; - } + return [OctagonStateTransitionOperation named:@"wait-for-tlk-peers" entering:SecCKKSZoneKeyStateProcess]; } - } else if([state isEqualToString: SecCKKSZoneKeyStateWaitForUnlock]) { + if([flags _onqueueContains:CKKSFlagKeySetRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeySetRequested]; + return [OctagonStateTransitionOperation named:@"provide-key-set" entering:SecCKKSZoneKeyStateProcess]; + } + + return nil; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForUnlock]) { ckksnotice("ckkskey", self, "Requested to enter waitforunlock"); - self.keyStateMachineOperation = [self operationToEnterState:SecCKKSZoneKeyStateInitialized keyStateError:nil named:@"key-state-after-unlock"]; - [self.keyStateMachineOperation addNullableDependency: self.lockStateTracker.unlockDependency]; - } else if([state isEqualToString: SecCKKSZoneKeyStateReadyPendingUnlock]) { - ckksnotice("ckkskey", self, "Believe we're ready, but rechecking after unlock"); - self.keyStateMachineOperation = [self operationToEnterState:SecCKKSZoneKeyStateInitialized keyStateError:nil named:@"key-state-after-unlock"]; - [self.keyStateMachineOperation addNullableDependency: self.lockStateTracker.unlockDependency]; + if([flags _onqueueContains:CKKSFlagDeviceUnlocked ]) { + [flags _onqueueRemoveFlag:CKKSFlagDeviceUnlocked]; + return [OctagonStateTransitionOperation named:@"key-state-after-unlock" entering:SecCKKSZoneKeyStateInitialized]; + } - } else if([state isEqualToString: SecCKKSZoneKeyStateBadCurrentPointers]) { + OctagonPendingFlag* unlocked = [[OctagonPendingFlag alloc] initWithFlag:CKKSFlagDeviceUnlocked + conditions:OctagonPendingConditionsDeviceUnlocked]; + [pendingFlagHandler _onqueueHandlePendingFlag:unlocked]; + + return nil; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateBadCurrentPointers]) { // The current key pointers are broken, but we're not sure why. ckksnotice("ckkskey", self, "Our current key pointers are reported broken. Attempting a fix!"); - self.keyStateMachineOperation = [[CKKSHealKeyHierarchyOperation alloc] initWithCKKSKeychainView: self ckoperationGroup:self.keyHierarchyOperationGroup]; + return [[CKKSHealKeyHierarchyOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intending:SecCKKSZoneKeyStateBecomeReady + errorState:SecCKKSZoneKeyStateError]; + } - } else if([state isEqualToString: SecCKKSZoneKeyStateNewTLKsFailed]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateNewTLKsFailed]) { ckksnotice("ckkskey", self, "Creating new TLKs didn't work. Attempting to refetch!"); - [self _onqueueKeyHierarchyFetch]; + return [OctagonStateTransitionOperation named:@"new-tlks-failed" entering:SecCKKSZoneKeyStateBeginFetch]; + } - } else if([state isEqualToString: SecCKKSZoneKeyStateHealTLKSharesFailed]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateHealTLKSharesFailed]) { ckksnotice("ckkskey", self, "Creating new TLK shares didn't work. Attempting to refetch!"); - [self _onqueueKeyHierarchyFetch]; + return [OctagonStateTransitionOperation named:@"heal-tlks-failed" entering:SecCKKSZoneKeyStateBeginFetch]; + } - } else if([state isEqualToString:SecCKKSZoneKeyStateUnhealthy]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateUnhealthy]) { if(self.trustStatus != CKKSAccountStatusAvailable) { ckksnotice("ckkskey", self, "Looks like the key hierarchy is unhealthy, but we're untrusted."); - nextState = SecCKKSZoneKeyStateWaitForTrust; + return [OctagonStateTransitionOperation named:@"unhealthy-lacking-trust" entering:SecCKKSZoneKeyStateLoseTrust]; } else { ckksnotice("ckkskey", self, "Looks like the key hierarchy is unhealthy. Launching fix."); - self.keyStateMachineOperation = [[CKKSHealKeyHierarchyOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:self.keyHierarchyOperationGroup]; + return [[CKKSHealKeyHierarchyOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intending:SecCKKSZoneKeyStateBecomeReady + errorState:SecCKKSZoneKeyStateError]; } + } - } else if([state isEqualToString:SecCKKSZoneKeyStateHealTLKShares]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateHealTLKShares]) { ckksnotice("ckksshare", self, "Key hierarchy is okay, but not shared appropriately. Launching fix."); - self.keyStateMachineOperation = [[CKKSHealTLKSharesOperation alloc] initWithCKKSKeychainView:self - ckoperationGroup:self.keyHierarchyOperationGroup]; + return [[CKKSHealTLKSharesOperation alloc] initWithOperationDependencies:self.operationDependencies + ckks:self]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateProcess]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; - } else if([state isEqualToString:SecCKKSZoneKeyStateProcess]) { ckksnotice("ckksshare", self, "Launching key state process"); - self.keyStateMachineOperation = [[CKKSProcessReceivedKeysStateMachineOperation alloc] initWithCKKSKeychainView: self]; - - // Since we're starting a reprocess, this is answering all previous requests. - self.keyStateProcessRequested = false; - - } else { - ckkserror("ckks", self, "asked to advance state machine to unknown state: %@", state); - self.keyHierarchyState = state; - - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - [self _onqueueHandleKeyStateNonTransientDependency:keyset]; - return; + return [[CKKSProcessReceivedKeysOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateBecomeReady + errorState:SecCKKSZoneKeyStateError]; } - // Handle the key state ready dependency - // If we're in ready and not entering a non-ready state, we should activate the ready dependency. Otherwise, we should create it. - if(([state isEqualToString:SecCKKSZoneKeyStateReady] || [state isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]) && - (nextState == nil || [nextState isEqualToString:SecCKKSZoneKeyStateReady] || [nextState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock])) { - - // Ready enough! - [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastKeystateReady inView:self]; - - if(self.keyStateReadyDependency) { - [self scheduleOperation: self.keyStateReadyDependency]; - self.keyStateReadyDependency = nil; - } - - // If there are any OQEs waiting to be encrypted, launch an op to fix them - NSError* localerror = nil; - NSInteger outdatedOQEs = [CKKSOutgoingQueueEntry countByState:SecCKKSStateReencrypt zone:self.zoneID error:&localerror]; - - if(localerror) { - ckkserror("ckkskey", self, "couldn't fetch OQEs from local database, entering error state: %@", localerror); - self.keyHierarchyState = SecCKKSZoneKeyStateError; - self.keyHierarchyError = localerror; - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; - } - - if(outdatedOQEs > 0) { - ckksnotice("ckksreencrypt", self, "Reencrypting outgoing items as the key hierarchy is ready"); - CKKSReencryptOutgoingItemsOperation* op = [[CKKSReencryptOutgoingItemsOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:self.keyHierarchyOperationGroup]; - [self scheduleOperation:op]; - } - } else { - // Not in ready: we need a key state ready dependency - if(self.keyStateReadyDependency == nil || [self.keyStateReadyDependency isFinished]) { - self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"key-state-broken"]; - self.keyStateReadyDependency = [self createKeyStateReadyDependency:@"Key state has become ready again." ckoperationGroup:self.keyHierarchyOperationGroup]; - } - } - - NSAssert(!((self.keyStateMachineOperation != nil) && - (nextState != nil)), - @"Should have a machine operation or a next state, not both"); - - // Start any operations, or log that we aren't - if(self.keyStateMachineOperation) { - [self scheduleOperation: self.keyStateMachineOperation]; - ckksnotice("ckkskey", self, "Now in key state: %@", state); - self.keyHierarchyState = state; - - } else if([state isEqualToString:SecCKKSZoneKeyStateError]) { - ckksnotice("ckkskey", self, "Entering key state 'error'"); - self.keyHierarchyState = state; - - } else if(nextState == nil) { - ckksnotice("ckkskey", self, "Entering key state: %@", state); - self.keyHierarchyState = state; - - } else if(![state isEqualToString: nextState]) { - ckksnotice("ckkskey", self, "Staying in state %@, but proceeding to %@ as soon as possible", self.keyHierarchyState, nextState); - self.keyStateMachineOperation = [self operationToEnterState:nextState keyStateError:nextError named:[NSString stringWithFormat:@"next-key-state-%@", nextState]]; - [self scheduleOperation: self.keyStateMachineOperation]; - - } else { - // Nothing to do and not in a waiting state? This is likely a bug, but, hey: pretend to be in ready! - if(!([state isEqualToString:SecCKKSZoneKeyStateReady] || [state isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock])) { - ckkserror("ckkskey", self, "No action to take in state %@; BUG, but: maybe we're ready?", state); - nextState = SecCKKSZoneKeyStateReady; - self.keyStateMachineOperation = [self operationToEnterState:nextState keyStateError:nil named:@"next-key-state"]; - [self scheduleOperation: self.keyStateMachineOperation]; - } - } - - // If the keystate is non-transient, ensure we've loaded the keyset, and provide it to any waiters - // If it is transient, just call the handler anyway: it needs to set up the dependency - if(!CKKSKeyStateTransient(self.keyHierarchyState) && keyset == nil) { - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - } - [self _onqueueHandleKeyStateNonTransientDependency:keyset]; + return nil; } -- (void)_onqueueHandleKeyStateNonTransientDependency:(CKKSCurrentKeySet* _Nullable)keyset { - dispatch_assert_queue(self.queue); - - if(CKKSKeyStateTransient(self.keyHierarchyState)) { - if(self.keyStateNonTransientDependency == nil || [self.keyStateNonTransientDependency isFinished]) { - self.keyStateNonTransientDependency = [self createKeyStateNontransientDependency]; - } - } else { - // Nontransient: go for it - if(self.keyStateNonTransientDependency) { - [self scheduleOperation: self.keyStateNonTransientDependency]; - self.keyStateNonTransientDependency = nil; - } - - if(keyset && keyset.currentTLKPointer.currentKeyUUID) { - [self _onqueueRunKeysetProviderOperations:keyset]; - } else { - ckksnotice("ckkskey", self, "State machine is nontransient, but no keyset..."); - } - } -} - -- (NSOperation*)operationToEnterState:(CKKSZoneKeyState*)state keyStateError:(NSError* _Nullable)keyStateError named:(NSString*)name { +- (OctagonStateTransitionOperation*)tlkMissingOperation:(CKKSZoneKeyState*)newState +{ WEAKIFY(self); - - return [NSBlockOperation named:name withBlock:^{ + return [OctagonStateTransitionOperation named:@"tlk-missing" + intending:newState + errorState:SecCKKSZoneKeyStateError + withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { STRONGIFY(self); - if(!self) { + + NSArray* trustStates = self.operationDependencies.currentTrustStates; + + [self.operationDependencies.databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ + CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; + + if(keyset.error) { + ckkserror("ckkskey", self, "Unable to load keyset: %@", keyset.error); + op.nextState = newState; + + [self.operationDependencies provideKeySet:keyset]; + return; + } + + if(!keyset.currentTLKPointer.currentKeyUUID) { + // In this case, there's no current TLK at all. Go into "wait for tlkcreation"; + op.nextState = SecCKKSZoneKeyStateWaitForTLKCreation; + [self.operationDependencies provideKeySet:keyset]; + return; + } + + if(self.trustStatus != CKKSAccountStatusAvailable) { + ckksnotice("ckkskey", self, "TLK is missing, but no trust is present."); + op.nextState = SecCKKSZoneKeyStateLoseTrust; + + [self.operationDependencies provideKeySet:keyset]; + return; + } + + bool otherDevicesPresent = [self _onqueueOtherDevicesReportHavingTLKs:keyset + trustStates:trustStates]; + if(otherDevicesPresent) { + // We expect this keyset to continue to exist. Send it to our listeners. + [self.operationDependencies provideKeySet:keyset]; + + op.nextState = newState; + } else { + ckksnotice("ckkskey", self, "No other devices claim to have the TLK. Resetting zone..."); + op.nextState = SecCKKSZoneKeyStateResettingZone; + } return; - } - [self dispatchSyncWithAccountKeys:^bool{ - [self _onqueueAdvanceKeyStateMachineToState:state withError:keyStateError]; - return true; }]; }]; } -- (BOOL)otherDevicesReportHavingTLKs:(CKKSCurrentKeySet*)keyset -{ - __block BOOL report = false; - [self dispatchSync:^bool{ - report = [self _onqueueOtherDevicesReportHavingTLKs:keyset]; - return true; - }]; - return report ? YES : NO; -} - - (bool)_onqueueOtherDevicesReportHavingTLKs:(CKKSCurrentKeySet*)keyset + trustStates:(NSArray*)trustStates { - dispatch_assert_queue(self.queue); - //Has there been any activity indicating that other trusted devices have keys in the past 45 days, or untrusted devices in the past 4? // (We chose 4 as devices attempt to upload their device state every 3 days. If a device is unceremoniously kicked out of circle, we normally won't immediately reset.) NSDate* now = [NSDate date]; @@ -1500,7 +1160,7 @@ NSMutableSet* trustedPeerIDs = [NSMutableSet set]; - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { + for(CKKSPeerProviderState* trustState in trustStates) { for(id peer in trustState.currentTrustedPeers) { [trustedPeerIDs addObject:peer.peerID]; } @@ -1508,7 +1168,7 @@ NSError* localerror = nil; - NSArray* allDeviceStates = [CKKSDeviceStateEntry allInZone:self.zoneID error:&localerror]; + NSArray* allDeviceStates = [CKKSDeviceStateEntry allInZone:keyset.currentTLKPointer.zoneID error:&localerror]; if(localerror) { ckkserror("ckkskey", self, "Error fetching device states: %@", localerror); localerror = nil; @@ -1544,8 +1204,8 @@ } NSArray* tlkShares = [CKKSTLKShareRecord allForUUID:keyset.currentTLKPointer.currentKeyUUID - zoneID:self.zoneID - error:&localerror]; + zoneID:keyset.currentTLKPointer.zoneID + error:&localerror]; if(localerror) { ckkserror("ckkskey", self, "Error fetching device states: %@", localerror); localerror = nil; @@ -1571,461 +1231,12 @@ return false; } -// For this key, who doesn't yet have a valid CKKSTLKShare for it? -// Note that we really want a record sharing the TLK to ourselves, so this function might return -// a non-empty set even if all peers have the TLK: it wants us to make a record for ourself. -- (NSSet>*)_onqueueFindPeers:(CKKSPeerProviderState*)trustState - missingShare:(CKKSKey*)key - afterUploading:(NSSet* _Nullable)newShares - error:(NSError* __autoreleasing*)error +- (void)handleKeychainEventDbConnection:(SecDbConnectionRef) dbconn + source:(SecDbTransactionSource)txionSource + added:(SecDbItemRef) added + deleted:(SecDbItemRef) deleted + rateLimiter:(CKKSRateLimiter*) rateLimiter { - dispatch_assert_queue(self.queue); - - if(!key) { - ckkserror("ckksshare", self, "Attempting to find missing shares for nil key"); - return [NSSet set]; - } - - if(trustState.currentTrustedPeersError) { - ckkserror("ckksshare", self, "Couldn't find missing shares because trusted peers aren't available: %@", trustState.currentTrustedPeersError); - if(error) { - *error = trustState.currentTrustedPeersError; - } - return [NSSet set]; - } - if(trustState.currentSelfPeersError) { - ckkserror("ckksshare", self, "Couldn't find missing shares because self peers aren't available: %@", trustState.currentSelfPeersError); - if(error) { - *error = trustState.currentSelfPeersError; - } - return [NSSet set]; - } - - NSMutableSet>* peersMissingShares = [NSMutableSet set]; - - // Ensure that the 'self peer' is one of the current trusted peers. Otherwise, any TLKShare we create - // won't be considered trusted the next time through... - if(![trustState.currentTrustedPeerIDs containsObject:trustState.currentSelfPeers.currentSelf.peerID]) { - ckkserror("ckksshare", self, "current self peer (%@) is not in the set of trusted peers: %@", - trustState.currentSelfPeers.currentSelf.peerID, - trustState.currentTrustedPeerIDs); - - if(error) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSLackingTrust - description:[NSString stringWithFormat:@"current self peer (%@) is not in the set of trusted peers", - trustState.currentSelfPeers.currentSelf.peerID]]; - } - - return nil; - } - - for(id peer in trustState.currentTrustedPeers) { - if(![peer shouldHaveView:self.zoneName]) { - ckkserror("ckksshare", self, "Peer (%@) is not supposed to have view, skipping", peer); - continue; - } - - NSError* peerError = nil; - // Find all the shares for this peer for this key - NSArray* currentPeerShares = [CKKSTLKShareRecord allFor:peer.peerID - keyUUID:key.uuid - zoneID:self.zoneID - error:&peerError]; - - if(peerError) { - ckkserror("ckksshare", self, "Couldn't load shares for peer %@: %@", peer, peerError); - if(error) { - *error = peerError; - } - return nil; - } - - // Include the new shares, too.... - NSArray* possiblePeerShares = newShares ? [currentPeerShares arrayByAddingObjectsFromArray:[newShares allObjects]] : currentPeerShares; - - // Determine if we think this peer has enough things shared to them - bool alreadyShared = false; - for(CKKSTLKShareRecord* existingPeerShare in possiblePeerShares) { - // Ensure this share is to this peer... - if(![existingPeerShare.share.receiverPeerID isEqualToString:peer.peerID]) { - continue; - } - - // If an SOS Peer sent this share, is its signature still valid? Or did the signing key change? - if([existingPeerShare.senderPeerID hasPrefix:CKKSSOSPeerPrefix]) { - NSError* signatureError = nil; - if(![existingPeerShare signatureVerifiesWithPeerSet:trustState.currentTrustedPeers error:&signatureError]) { - ckksnotice("ckksshare", self, "Existing TLKShare's signature doesn't verify with current peer set: %@ %@", signatureError, existingPeerShare); - continue; - } - } - - if([existingPeerShare.tlkUUID isEqualToString:key.uuid] && [trustState.currentTrustedPeerIDs containsObject:existingPeerShare.senderPeerID]) { - // Was this shared to us? - if([peer.peerID isEqualToString: trustState.currentSelfPeers.currentSelf.peerID]) { - // We only count this as 'found' if we did the sharing and it's to our current keys - NSData* currentKey = trustState.currentSelfPeers.currentSelf.publicEncryptionKey.keyData; - - if([existingPeerShare.senderPeerID isEqualToString:trustState.currentSelfPeers.currentSelf.peerID] && - [existingPeerShare.share.receiverPublicEncryptionKeySPKI isEqual:currentKey]) { - ckksnotice("ckksshare", self, "Local peer %@ is shared %@ via self: %@", peer, key, existingPeerShare); - alreadyShared = true; - break; - } else { - ckksnotice("ckksshare", self, "Local peer %@ is shared %@ via trusted %@, but that's not good enough", peer, key, existingPeerShare); - } - - } else { - // Was this shared to the remote peer's current keys? - NSData* currentKeySPKI = peer.publicEncryptionKey.keyData; - - if([existingPeerShare.share.receiverPublicEncryptionKeySPKI isEqual:currentKeySPKI]) { - // Some other peer has a trusted share. Cool! - ckksnotice("ckksshare", self, "Peer %@ is shared %@ via trusted %@", peer, key, existingPeerShare); - alreadyShared = true; - break; - } else { - ckksnotice("ckksshare", self, "Peer %@ has a share for %@, but to old keys: %@", peer, key, existingPeerShare); - } - } - } - } - - if(!alreadyShared) { - // Add this peer to our set, if it has an encryption key to receive the share - if(peer.publicEncryptionKey) { - [peersMissingShares addObject:peer]; - } - } - } - - if(peersMissingShares.count > 0u) { - // Log each and every one of the things - ckksnotice("ckksshare", self, "Missing TLK shares for %lu peers: %@", (unsigned long)peersMissingShares.count, peersMissingShares); - ckksnotice("ckksshare", self, "Self peers are (%@) %@", trustState.currentSelfPeersError ?: @"no error", trustState.currentSelfPeers); - ckksnotice("ckksshare", self, "Trusted peers are (%@) %@", trustState.currentTrustedPeersError ?: @"no error", trustState.currentTrustedPeers); - } - - return peersMissingShares; -} - -- (BOOL)_onqueueAreNewSharesSufficient:(NSSet*)newShares - currentTLK:(CKKSKey*)key - error:(NSError* __autoreleasing*)error -{ - dispatch_assert_queue(self.queue); - - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { - NSError* localError = nil; - NSSet>* peersMissingShares = [self _onqueueFindPeers:trustState - missingShare:key - afterUploading:newShares - error:&localError]; - if(peersMissingShares == nil || localError) { - if(trustState.essential) { - if(error) { - *error = localError; - } - return NO; - } else { - ckksnotice("ckksshare", self, "Failed to find peers for nonessential system: %@", trustState); - // Not a hard failure. - } - } - - if(peersMissingShares.count > 0) { - ckksnotice("ckksshare", self, "New share set is missing shares for peers: %@", peersMissingShares); - return NO; - } - } - - return YES; -} - -- (NSSet*)_onqueueCreateMissingKeyShares:(CKKSKey*)key - error:(NSError* __autoreleasing*)error -{ - NSError* localerror = nil; - NSSet* newShares = nil; - - // If any one of our trust states succeed, this function doesn't have an error - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { - NSError* stateError = nil; - - NSSet* newTrustShares = [self _onqueueCreateMissingKeyShares:key - peers:trustState - error:&stateError]; - - - if(newTrustShares && !stateError) { - newShares = newShares ? [newShares setByAddingObjectsFromSet:newTrustShares] : newTrustShares; - } else { - ckksnotice("ckksshare", self, "Unable to create shares for trust set %@: %@", trustState, stateError); - if(localerror == nil) { - localerror = stateError; - } - } - } - - // Only report an error if none of the trust states were able to succeed - if(newShares) { - return newShares; - } else { - if(error && localerror) { - *error = localerror; - } - return nil; - } -} - -- (NSSet*)_onqueueCreateMissingKeyShares:(CKKSKey*)key - peers:(CKKSPeerProviderState*)trustState - error:(NSError* __autoreleasing*)error -{ - dispatch_assert_queue(self.queue); - - if(trustState.currentTrustedPeersError) { - ckkserror("ckksshare", self, "Couldn't create missing shares because trusted peers aren't available: %@", trustState.currentTrustedPeersError); - if(error) { - *error = trustState.currentTrustedPeersError; - } - return nil; - } - if(trustState.currentSelfPeersError) { - ckkserror("ckksshare", self, "Couldn't create missing shares because self peers aren't available: %@", trustState.currentSelfPeersError); - if(error) { - *error = trustState.currentSelfPeersError; - } - return nil; - } - - NSSet>* remainingPeers = [self _onqueueFindPeers:trustState missingShare:key afterUploading:nil error:error]; - NSMutableSet* newShares = [NSMutableSet set]; - - if(!remainingPeers) { - return nil; - } - - NSError* localerror = nil; - - if(![key ensureKeyLoaded:error]) { - return nil; - } - - for(id peer in remainingPeers) { - if(!peer.publicEncryptionKey) { - ckksnotice("ckksshare", self, "No need to make TLK for %@; they don't have any encryption keys", peer); - continue; - } - - // Create a share for this peer. - ckksnotice("ckksshare", self, "Creating share of %@ as %@ for %@", key, trustState.currentSelfPeers.currentSelf, peer); - CKKSTLKShareRecord* newShare = [CKKSTLKShareRecord share:key - as:trustState.currentSelfPeers.currentSelf - to:peer - epoch:-1 - poisoned:0 - error:&localerror]; - - if(localerror) { - ckkserror("ckksshare", self, "Couldn't create new share for %@: %@", peer, localerror); - if(error) { - *error = localerror; - } - return nil; - } - - [newShares addObject: newShare]; - } - - return newShares; -} - -- (CKKSZoneKeyState*)_onqueueEnsureKeyHierarchyHealth:(CKKSCurrentKeySet*)set error:(NSError* __autoreleasing *)error { - dispatch_assert_queue(self.queue); - - if(!set.currentTLKPointer && !set.currentClassAPointer && !set.currentClassCPointer) { - ckkserror("ckkskey", self, "Error examining existing key hierarchy (missing all CKPs, likely no hierarchy exists): %@", set); - return SecCKKSZoneKeyStateWaitForTLKCreation; - } - - // Check keyset - if(!set.tlk || !set.classA || !set.classC) { - ckkserror("ckkskey", self, "Error examining existing key hierarchy (missing at least one key): %@", set); - if(error) { - *error = set.error; - } - return SecCKKSZoneKeyStateUnhealthy; - } - - NSError* localerror = nil; - bool probablyOkIfUnlocked = false; - - // keychain being locked is not a fatal error here - [set.tlk loadKeyMaterialFromKeychain:&localerror]; - if(localerror && !([localerror.domain isEqual: @"securityd"] && localerror.code == errSecInteractionNotAllowed)) { - ckkserror("ckkskey", self, "Error loading TLK(%@): %@", set.tlk, localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } else if(localerror) { - ckkserror("ckkskey", self, "Soft error loading TLK(%@), maybe locked: %@", set.tlk, localerror); - probablyOkIfUnlocked = true; - } - localerror = nil; - - // keychain being locked is not a fatal error here - [set.classA loadKeyMaterialFromKeychain:&localerror]; - if(localerror && !([localerror.domain isEqual: @"securityd"] && localerror.code == errSecInteractionNotAllowed)) { - ckkserror("ckkskey", self, "Error loading classA key(%@): %@", set.classA, localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } else if(localerror) { - ckkserror("ckkskey", self, "Soft error loading classA key(%@), maybe locked: %@", set.classA, localerror); - probablyOkIfUnlocked = true; - } - localerror = nil; - - // keychain being locked is a fatal error here, since this is class C - [set.classC loadKeyMaterialFromKeychain:&localerror]; - if(localerror) { - ckkserror("ckkskey", self, "Error loading classC(%@): %@", set.classC, localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } - - // Check that the classA and classC keys point to the current TLK - if(![set.classA.parentKeyUUID isEqualToString: set.tlk.uuid]) { - localerror = [NSError errorWithDomain:CKKSServerExtensionErrorDomain - code:CKKSServerUnexpectedSyncKeyInChain - userInfo:@{ - NSLocalizedDescriptionKey: @"Current class A key does not wrap to current TLK", - }]; - ckkserror("ckkskey", self, "Key hierarchy unhealthy: %@", localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } - if(![set.classC.parentKeyUUID isEqualToString: set.tlk.uuid]) { - localerror = [NSError errorWithDomain:CKKSServerExtensionErrorDomain - code:CKKSServerUnexpectedSyncKeyInChain - userInfo:@{ - NSLocalizedDescriptionKey: @"Current class C key does not wrap to current TLK", - }]; - ckkserror("ckkskey", self, "Key hierarchy unhealthy: %@", localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } - - self.activeTLK = [set.tlk uuid]; - - // Now that we're pretty sure we have the keys, are they shared appropriately? - // We need trust in order to proceed here - if(self.currentTrustStates.count == 0u) { - ckkserror("ckkskey", self, "Can't check TLKShares due to missing trust states"); - return SecCKKSZoneKeyStateWaitForTrust; - } - - // Check that every trusted peer has at least one TLK share - // If any trust state check works, don't error out - bool anyTrustStateSucceeded = false; - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { - NSSet>* missingShares = [self _onqueueFindPeers:trustState missingShare:set.tlk afterUploading:nil error:&localerror]; - if(localerror && [self.lockStateTracker isLockedError: localerror]) { - ckkserror("ckkskey", self, "Couldn't find missing TLK shares due to lock state: %@", localerror); - probablyOkIfUnlocked = true; - - } else if(([localerror.domain isEqualToString:TrustedPeersHelperErrorDomain] && localerror.code == TrustedPeersHelperErrorNoPreparedIdentity) || - ([localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSLackingTrust) || - ([localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSNoPeersAvailable)) { - ckkserror("ckkskey", self, "Couldn't find missing TLK shares due some trust issue: %@", localerror); - - if(trustState.essential) { - ckkserror("ckkskey", self, "Trust state is considered essential; entering waitfortrust: %@", trustState); - - // Octagon can reinform us when it thinks we should start again - self.trustStatus = CKKSAccountStatusUnknown; - return SecCKKSZoneKeyStateWaitForTrust; - } else { - ckkserror("ckkskey", self, "Peer provider is considered nonessential; ignoring error: %@", trustState); - continue; - } - - } else if(localerror) { - ckkserror("ckkskey", self, "Error finding missing TLK shares: %@", localerror); - continue; - } - - if(!missingShares || missingShares.count != 0u) { - localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSMissingTLKShare - description:[NSString stringWithFormat:@"Missing shares for %lu peers", (unsigned long)missingShares.count]]; - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateHealTLKShares; - } else { - ckksnotice("ckksshare", self, "TLK (%@) is shared correctly for trust state %@", set.tlk, trustState.peerProviderID); - } - - anyTrustStateSucceeded |= true; - } - - if(!anyTrustStateSucceeded) { - if(error) { - *error = localerror; - } - - return SecCKKSZoneKeyStateError; - } - - // Got to the bottom? Cool! All keys are present and accounted for. - return probablyOkIfUnlocked ? SecCKKSZoneKeyStateReadyPendingUnlock : SecCKKSZoneKeyStateReady; -} - -- (void)_onqueueKeyHierarchyFetch { - [self _onqueueKeyHierarchyFetchForReasons:[NSSet setWithArray:@[CKKSFetchBecauseKeyHierarchy]]]; -} - -- (void)_onqueueKeyHierarchyFetchForReasons:(NSSet*)reasons -{ - dispatch_assert_queue(self.queue); - - WEAKIFY(self); - self.keyStateMachineOperation = [NSBlockOperation blockOperationWithBlock: ^{ - STRONGIFY(self); - if(!self) { - ckkserror("ckks", self, "received callback for released object"); - return; - } - [self.launch addEvent:@"fetch-complete"]; - - [self dispatchSyncWithAccountKeys: ^bool{ - [self _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateFetchComplete withError: nil]; - return true; - }]; - }]; - self.keyStateMachineOperation.name = @"waiting-for-fetch"; - - NSOperation* fetchOp = [self.zoneChangeFetcher requestSuccessfulFetchForManyReasons:reasons]; - [self.keyStateMachineOperation addDependency: fetchOp]; - - self.keyStateFetchRequested = false; -} - -- (void) handleKeychainEventDbConnection: (SecDbConnectionRef) dbconn - added: (SecDbItemRef) added - deleted: (SecDbItemRef) deleted - rateLimiter: (CKKSRateLimiter*) rateLimiter - syncCallback: (SecBoolNSErrorCallback) syncCallback { if(!SecCKKSIsEnabled()) { ckksnotice("ckks", self, "Skipping handleKeychainEventDbConnection due to disabled CKKS"); return; @@ -2040,6 +1251,7 @@ bool addedSync = added && SecDbItemIsSyncable(added); bool deletedSync = deleted && SecDbItemIsSyncable(deleted); + bool isTombstoneModification = addedTombstone && deletedTombstone; bool isAdd = ( added && !deleted) || (added && deleted && !addedTombstone && deletedTombstone) || (added && deleted && addedSync && !deletedSync); bool isDelete = (!added && deleted) || (added && deleted && addedTombstone && !deletedTombstone) || (added && deleted && !addedSync && deletedSync); bool isModify = ( added && deleted) && (!isAdd) && (!isDelete); @@ -2063,6 +1275,11 @@ return; } + if(isTombstoneModification) { + ckksnotice("ckks", self, "skipping syncing update of tombstone item (%d, %d)", addedTombstone, deletedTombstone); + return; + } + // It's possible to ask for an item to be deleted without adding a corresponding tombstone. // This is arguably a bug, as it generates an out-of-sync state, but it is in the API contract. // CKKS should ignore these, but log very upset messages. @@ -2080,65 +1297,78 @@ return; } + if(txionSource == kSecDbSOSTransaction) { + NSString* addedUUID = (__bridge NSString*)SecDbItemGetValue(added, &v10itemuuid, NULL); + ckksnotice("ckks", self, "Received an incoming %@ from SOS (%@)", + isAdd ? @"addition" : (isModify ? @"modification" : @"deletion"), + addedUUID); + } + // Our caller gave us a database connection. We must get on the local queue to ensure atomicity // Note that we're at the mercy of the surrounding db transaction, so don't try to rollback here - [self dispatchSyncWithConnection: dbconn block: ^bool { + [self dispatchSyncWithConnection:dbconn + readWriteTxion:YES + block:^CKKSDatabaseTransactionResult { // Schedule a "view changed" notification - [self.notifyViewChangedScheduler trigger]; + [self.viewState.notifyViewChangedScheduler trigger]; if(self.accountStatus == CKKSAccountStatusNoAccount) { // No account; CKKS shouldn't attempt anything. - self.droppedItems = true; + [self.stateMachine _onqueueHandleFlag:CKKSFlagScanLocalItems]; ckksnotice("ckks", self, "Dropping sync item modification due to CK account state; will scan to find changes later"); + // We're positively not logged into CloudKit, and therefore don't expect this item to be synced anytime particularly soon. + NSString* uuid = (__bridge NSString*)SecDbItemGetValue(added ? added : deleted, &v10itemuuid, NULL); + + SecBoolNSErrorCallback syncCallback = [[CKKSViewManager manager] claimCallbackForUUID:uuid]; if(syncCallback) { - // We're positively not logged into CloudKit, and therefore don't expect this item to be synced anytime particularly soon. - [self callSyncCallbackWithErrorNoAccount: syncCallback]; + [CKKSViewManager callSyncCallbackWithErrorNoAccount: syncCallback]; } - return true; + + return CKKSDatabaseTransactionCommit; } - // Always record the callback, even if we can't encrypt the item right now. Maybe we'll get to it soon! - if(syncCallback) { - CFErrorRef cferror = NULL; - NSString* uuid = (__bridge_transfer NSString*) CFRetain(SecDbItemGetValue(added, &v10itemuuid, &cferror)); - if(!cferror && uuid) { - self.pendingSyncCallbacks[uuid] = syncCallback; - } - CFReleaseNull(cferror); - } + CKKSMemoryKeyCache* keyCache = [[CKKSMemoryKeyCache alloc] init]; CKKSOutgoingQueueEntry* oqe = nil; if (isAdd) { - oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionAdd ckks:self error: &error]; + oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionAdd zoneID:self.zoneID keyCache:keyCache error: &error]; } else if(isDelete) { - oqe = [CKKSOutgoingQueueEntry withItem: deleted action: SecCKKSActionDelete ckks:self error: &error]; + oqe = [CKKSOutgoingQueueEntry withItem: deleted action: SecCKKSActionDelete zoneID:self.zoneID keyCache:keyCache error: &error]; } else if(isModify) { - oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionModify ckks:self error: &error]; + oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionModify zoneID:self.zoneID keyCache:keyCache error: &error]; } else { ckkserror("ckks", self, "processKeychainEventItemAdded given garbage: %@ %@", added, deleted); - return true; + return CKKSDatabaseTransactionCommit; } - CKOperationGroup* operationGroup = [CKOperationGroup CKKSGroupWithName:@"keychain-api-use"]; + if(!self.itemSyncingEnabled) { + // Call any callback now; they're not likely to get the sync they wanted + SecBoolNSErrorCallback syncCallback = [[CKKSViewManager manager] claimCallbackForUUID:oqe.uuid]; + if(syncCallback) { + syncCallback(false, [NSError errorWithDomain:CKKSErrorDomain + code:CKKSErrorViewIsPaused + description:@"View is paused; item is not expected to sync"]); + } + } + + CKOperationGroup* operationGroup = txionSource == kSecDbSOSTransaction + ? [CKOperationGroup CKKSGroupWithName:@"sos-incoming-item"] + : [CKOperationGroup CKKSGroupWithName:@"keychain-api-use"]; if(error) { ckkserror("ckks", self, "Couldn't create outgoing queue entry: %@", error); - self.droppedItems = true; - - // If the problem is 'no UUID', launch a scan operation to find and fix it - // We don't want to fix it up here, in the closing moments of a transaction - if([error.domain isEqualToString:CKKSErrorDomain] && error.code == CKKSNoUUIDOnItem) { - ckksnotice("ckks", self, "Launching scan operation to find UUID"); - [self scanLocalItems:@"uuid-find-scan" ckoperationGroup:operationGroup after:nil]; - } + [self.stateMachine _onqueueHandleFlag:CKKSFlagScanLocalItems]; // If the problem is 'couldn't load key', tell the key hierarchy state machine to fix it if([error.domain isEqualToString:CKKSErrorDomain] && error.code == errSecItemNotFound) { - [self.pokeKeyStateMachineScheduler trigger]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; } - return true; + return CKKSDatabaseTransactionCommit; + } else if(!oqe) { + ckkserror("ckks", self, "Decided that no operation needs to occur for %@", error); + return CKKSDatabaseTransactionCommit; } if(rateLimiter) { @@ -2153,39 +1383,46 @@ [oqe saveToDatabaseWithConnection: dbconn error: &error]; if(error) { ckkserror("ckks", self, "Couldn't save outgoing queue entry to database: %@", error); - return true; + return CKKSDatabaseTransactionCommit; } else { ckksnotice("ckks", self, "Saved %@ to outgoing queue", oqe); } // This update supercedes all other local modifications to this item (_except_ those in-flight). // Delete all items in reencrypt or error. - CKKSOutgoingQueueEntry* reencryptOQE = [CKKSOutgoingQueueEntry tryFromDatabase:oqe.uuid state:SecCKKSStateReencrypt zoneID:self.zoneID error:&error]; + NSArray* siblings = [CKKSOutgoingQueueEntry allWithUUID:oqe.uuid + states:@[SecCKKSStateReencrypt, SecCKKSStateError] + zoneID:self.zoneID + error:&error]; if(error) { - ckkserror("ckks", self, "Couldn't load reencrypt OQE sibling for %@: %@", oqe, error); - } - if(reencryptOQE) { - [reencryptOQE deleteFromDatabase:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't delete reencrypt OQE sibling(%@) for %@: %@", reencryptOQE, oqe, error); - } - error = nil; + ckkserror("ckks", self, "Couldn't load OQE siblings for %@: %@", oqe, error); } - CKKSOutgoingQueueEntry* errorOQE = [CKKSOutgoingQueueEntry tryFromDatabase:oqe.uuid state:SecCKKSStateError zoneID:self.zoneID error:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't load error OQE sibling for %@: %@", oqe, error); + for(CKKSOutgoingQueueEntry* oqeSibling in siblings) { + NSError* deletionError = nil; + [oqeSibling deleteFromDatabase:&deletionError]; + if(deletionError) { + ckkserror("ckks", self, "Couldn't delete OQE sibling(%@) for %@: %@", oqeSibling, oqe.uuid, deletionError); + } } - if(errorOQE) { - [errorOQE deleteFromDatabase:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't delete error OQE sibling(%@) for %@: %@", reencryptOQE, oqe, error); + + // This update also supercedes any remote changes that are pending. + NSError* iqeError = nil; + CKKSIncomingQueueEntry* iqe = [CKKSIncomingQueueEntry tryFromDatabase:oqe.uuid zoneID:self.zoneID error:&iqeError]; + if(iqeError) { + ckkserror("ckks", self, "Couldn't find IQE matching %@: %@", oqe.uuid, error); + } else if(iqe) { + [iqe deleteFromDatabase:&iqeError]; + if(iqeError) { + ckkserror("ckks", self, "Couldn't delete IQE matching %@: %@", oqe.uuid, error); + } else { + ckksnotice("ckks", self, "Deleted IQE matching changed item %@", oqe.uuid); } } [self processOutgoingQueue:operationGroup]; - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -2295,7 +1532,7 @@ STRONGIFY(self); - [self dispatchSync: ^bool { + [self dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSString* currentIdentifier = [NSString stringWithFormat:@"%@-%@", accessGroup, identifier]; @@ -2304,9 +1541,15 @@ zoneID:self.zoneID error:&error]; if(!cip || error) { - ckkserror("ckkscurrent", self, "No current item pointer for %@", currentIdentifier); + if([error.domain isEqualToString:@"securityd"] && error.code == errSecItemNotFound) { + // This error is common and very, very noisy. Shorten it and don't log here (the framework should log for us) + ckksinfo("ckkscurrent", self, "No current item pointer for %@", currentIdentifier); + error = [NSError errorWithDomain:@"securityd" code:errSecItemNotFound description:[NSString stringWithFormat:@"No current item pointer found for %@", currentIdentifier]]; + } else { + ckkserror("ckkscurrent", self, "No current item pointer for %@", currentIdentifier); + } complete(nil, error); - return false; + return; } if(!cip.currentItemUUID) { @@ -2314,12 +1557,12 @@ complete(nil, [NSError errorWithDomain:CKKSErrorDomain code:errSecInternalError description:@"Current item pointer is empty"]); - return false; + return; } ckksinfo("ckkscurrent", self, "Retrieved current item pointer: %@", cip); complete(cip.currentItemUUID, NULL); - return true; + return; }]; }]; @@ -2327,109 +1570,50 @@ [self scheduleOperation: getCurrentItem]; } -- (CKKSKey*) keyForItem: (SecDbItemRef) item error: (NSError * __autoreleasing *) error { - CKKSKeyClass* class = nil; - - NSString* protection = (__bridge NSString*)SecDbItemGetCachedValueWithName(item, kSecAttrAccessible); - if([protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleWhenUnlocked]) { - class = SecCKKSKeyClassA; - } else if([protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleAlwaysPrivate] || - [protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleAfterFirstUnlock]) { - class = SecCKKSKeyClassC; - } else { - NSError* localError = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSInvalidKeyClass - description:[NSString stringWithFormat:@"can't pick key class for protection %@", protection]]; - ckkserror("ckks", self, "can't pick key class: %@ %@", localError, item); - if(error) { - *error = localError; - } - - return nil; - } - - NSError* currentKeyError = nil; - CKKSKey* key = [CKKSKey currentKeyForClass: class zoneID:self.zoneID error:¤tKeyError]; - if(!key || currentKeyError) { - ckkserror("ckks", self, "Couldn't find current key for %@: %@", class, currentKeyError); - - if(error) { - *error = currentKeyError; - } - return nil; - } - - // and make sure it's unwrapped. - NSError* loadedError = nil; - if(![key ensureKeyLoaded:&loadedError]) { - ckkserror("ckks", self, "Couldn't load key(%@): %@", key, loadedError); - if(error) { - *error = loadedError; - } - return nil; - } - - return key; -} - -- (CKKSResultOperation*)findKeySet +- (CKKSResultOperation*)findKeySet:(BOOL)refetchBeforeReturningKeySet { __block CKKSResultOperation* keysetOp = nil; - [self dispatchSyncWithAccountKeys:^bool { - CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - if(keyset.currentTLKPointer.currentKeyUUID && keyset.tlk.uuid) { - ckksnotice("ckks", self, "Already have keyset %@", keyset); + [self dispatchSyncWithReadOnlySQLTransaction:^{ + keysetOp = (CKKSProvideKeySetOperation*)[self findFirstPendingOperation:self.operationDependencies.keysetProviderOperations]; + if(!keysetOp) { + keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName]; + [self.operationDependencies.keysetProviderOperations addObject:keysetOp]; - keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName keySet:keyset]; + // This is an abuse of operations: they should generally run when added to a queue, not wait, but this allows recipients to set timeouts [self scheduleOperationWithoutDependencies:keysetOp]; - return true; - } else if([self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload]) { - CKKSCurrentKeySet* proposedKeySet = self.lastNewTLKOperation.keyset; - ckksnotice("ckks", self, "Already have proposed keyset %@", proposedKeySet); - - keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName keySet:proposedKeySet]; - [self scheduleOperationWithoutDependencies:keysetOp]; - return true; - } else { - // No existing keyset (including keys) exists. - // The state machine will know what to do! - self.tlkCreationRequested = true; - - ckksnotice("ckks", self, "Received a keyset request; forwarding to state machine"); - - keysetOp = (CKKSProvideKeySetOperation*) [self findFirstPendingOperation:self.keysetProviderOperations]; - if(!keysetOp) { - keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName]; - [self.keysetProviderOperations addObject:keysetOp]; - - // This is an abuse of operations: they should generally run when added to a queue, not wait, but this allows recipients to set timeouts - [self scheduleOperationWithoutDependencies:keysetOp]; - } - - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; } - return true; + if(refetchBeforeReturningKeySet) { + ckksnotice("ckks", self, "Refetch requested before returning key set!"); + + [self.stateMachine _onqueueHandleFlag:CKKSFlagFetchRequested]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeySetRequested]; + + return; + } + + CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; + if(keyset.currentTLKPointer.currentKeyUUID && + (keyset.tlk.uuid || + [self.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateWaitForTrust] || + [self.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateWaitForTLK])) { + ckksnotice("ckks", self, "Already have keyset %@", keyset); + + [keysetOp provideKeySet:keyset]; + return; + + } else { + // The key state machine will know what to do. + [self.stateMachine _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeySetRequested]; + }; }]; return keysetOp; } -- (void)_onqueueRunKeysetProviderOperations:(CKKSCurrentKeySet*)keyset -{ - ckksnotice("ckkskey", self, "Providing keyset (%@) to listeners", keyset); - - // We have some keyset; they can ask again if they want a new one - self.tlkCreationRequested = false; - - for(CKKSResultOperation* op in self.keysetProviderOperations) { - if([op isPending]) { - [op provideKeySet:keyset]; - } - } -} - - (void)receiveTLKUploadRecords:(NSArray*)records { // First, filter for records matching this zone @@ -2446,16 +1630,31 @@ return; } - [self dispatchSyncWithAccountKeys:^bool { - + [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for(CKRecord* record in zoneRecords) { [self _onqueueCKRecordChanged:record resync:false]; } - return true; + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateTLKsUploaded]; + + return CKKSDatabaseTransactionCommit; }]; } +- (BOOL)requiresTLKUpload +{ + __block BOOL requiresUpload = NO; + dispatch_sync(self.queue, ^{ + // We want to return true only if we're in a state that immediately requires an upload. + if(([self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload] || + [self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation])) { + requiresUpload = YES; + } + }); + + return requiresUpload; +} + // Use the following method to find the first pending operation in a weak collection - (NSOperation*)findFirstPendingOperation: (NSHashTable*) table { return [self findFirstPendingOperation:table ofClass:nil]; @@ -2473,36 +1672,27 @@ } } -// Use the following method to count the pending operations in a weak collection -- (int64_t)countPendingOperations: (NSHashTable*) table { - @synchronized(table) { - int count = 0; - for(NSOperation* op in table) { - if(op != nil && !([op isExecuting] || [op isFinished])) { - count++; - } - } - return count; - } -} - -- (NSSet*)_onqueuePriorityOutgoingQueueUUIDs -{ - return [self.pendingSyncCallbacks.allKeys copy]; -} - -- (CKKSOutgoingQueueOperation*)processOutgoingQueue:(CKOperationGroup*)ckoperationGroup { +- (CKKSOutgoingQueueOperation*)processOutgoingQueue:(CKOperationGroup* _Nullable)ckoperationGroup { return [self processOutgoingQueueAfter:nil ckoperationGroup:ckoperationGroup]; } -- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation*)after ckoperationGroup:(CKOperationGroup*)ckoperationGroup { +- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after + ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup { return [self processOutgoingQueueAfter:after requiredDelay:DISPATCH_TIME_FOREVER ckoperationGroup:ckoperationGroup]; } -- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation*)after +- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after requiredDelay:(uint64_t)requiredDelay - ckoperationGroup:(CKOperationGroup*)ckoperationGroup + ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup { + if(ckoperationGroup) { + if(self.operationDependencies.currentOutgoingQueueOperationGroup) { + ckkserror("ckks", self, "Throwing away CKOperationGroup(%@) in favor of (%@)", ckoperationGroup.name, self.operationDependencies.ckoperationGroup.name); + } else { + self.operationDependencies.currentOutgoingQueueOperationGroup = ckoperationGroup; + } + } + CKKSOutgoingQueueOperation* outgoingop = (CKKSOutgoingQueueOperation*) [self findFirstPendingOperation:self.outgoingQueueOperations ofClass:[CKKSOutgoingQueueOperation class]]; @@ -2511,14 +1701,8 @@ [outgoingop addDependency: after]; } if([outgoingop isPending]) { - if(!outgoingop.ckoperationGroup && ckoperationGroup) { - outgoingop.ckoperationGroup = ckoperationGroup; - } else if(ckoperationGroup) { - ckkserror("ckks", self, "Throwing away CKOperationGroup(%@) in favor of (%@)", ckoperationGroup.name, outgoingop.ckoperationGroup.name); - } - // Will log any pending dependencies as well - ckksnotice("ckksoutgoing", self, "Returning existing %@", outgoingop); + ckksinfo("ckksoutgoing", self, "Returning existing %@", outgoingop); // Shouldn't be necessary, but can't hurt [self.outgoingQueueOperationScheduler triggerAt:requiredDelay]; @@ -2526,7 +1710,14 @@ } } - CKKSOutgoingQueueOperation* op = [[CKKSOutgoingQueueOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:ckoperationGroup]; + CKKSOutgoingQueueOperation* op = [[CKKSOutgoingQueueOperation alloc] initWithDependencies:self.operationDependencies + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy]; + + [op addNullableDependency:self.holdOutgoingQueueOperation]; + [op addNullableDependency:self.keyStateReadyDependency]; + [op linearDependencies:self.outgoingQueueOperations]; + op.name = @"outgoing-queue-operation"; [op addNullableDependency:after]; [op addNullableDependency:self.outgoingQueueOperationScheduler.operationDependency]; @@ -2535,6 +1726,16 @@ [self scheduleOperation: op]; ckksnotice("ckksoutgoing", self, "Scheduled %@", op); + + WEAKIFY(self); + CKKSResultOperation* bookkeeping = [CKKSResultOperation named:@"bookkeping-oqo" withBlock:^{ + STRONGIFY(self); + self.lastOutgoingQueueOperation = op; + }]; + + [bookkeeping addDependency:op]; + [self scheduleOperation:bookkeeping]; + return op; } @@ -2572,6 +1773,13 @@ } - (CKKSIncomingQueueOperation*) processIncomingQueue:(bool)failOnClassA after: (CKKSResultOperation*) after { + return [self processIncomingQueue:failOnClassA after:after policyConsideredAuthoritative:false]; +} + +- (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA + after:(CKKSResultOperation*)after + policyConsideredAuthoritative:(bool)policyConsideredAuthoritative +{ CKKSIncomingQueueOperation* incomingop = (CKKSIncomingQueueOperation*) [self findFirstPendingOperation:self.incomingQueueOperations]; if(incomingop) { ckksinfo("ckks", self, "Skipping processIncomingQueue due to at least one pending instance"); @@ -2582,12 +1790,23 @@ // check (again) for race condition; if the op has started we need to add another (for the dependency) if([incomingop isPending]) { incomingop.errorOnClassAFailure |= failOnClassA; + incomingop.handleMismatchedViewItems |= policyConsideredAuthoritative; return incomingop; } } - CKKSIncomingQueueOperation* op = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:self errorOnClassAFailure:failOnClassA]; + CKKSIncomingQueueOperation* op = [[CKKSIncomingQueueOperation alloc] initWithDependencies:self.operationDependencies + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy + errorOnClassAFailure:failOnClassA + handleMismatchedViewItems:policyConsideredAuthoritative]; op.name = @"incoming-queue-operation"; + + // Can't process unless we have a reasonable key hierarchy. + [op addNullableDependency:self.keyStateReadyDependency]; + [op addNullableDependency:self.holdIncomingQueueOperation]; + [op linearDependencies:self.incomingQueueOperations]; + if(after != nil) { [op addSuccessDependency: after]; } @@ -2595,9 +1814,19 @@ if(self.resultsOfNextIncomingQueueOperationOperation) { [self.resultsOfNextIncomingQueueOperationOperation addSuccessDependency:op]; [self scheduleOperation:self.resultsOfNextIncomingQueueOperationOperation]; + self.resultsOfNextIncomingQueueOperationOperation = nil; } [self scheduleOperation: op]; + + WEAKIFY(self); + CKKSResultOperation* bookkeeping = [CKKSResultOperation named:@"bookkeping-oqo" withBlock:^{ + STRONGIFY(self); + self.lastIncomingQueueOperation = op; + }]; + + [bookkeeping addDependency:op]; + [self scheduleOperation:bookkeeping]; return op; } @@ -2605,8 +1834,31 @@ return [self scanLocalItems:operationName ckoperationGroup:nil after:nil]; } -- (CKKSScanLocalItemsOperation*)scanLocalItems:(NSString*)operationName ckoperationGroup:(CKOperationGroup*)operationGroup after:(NSOperation*)after { - CKKSScanLocalItemsOperation* scanOperation = [[CKKSScanLocalItemsOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:operationGroup]; +- (CKKSScanLocalItemsOperation*)scanLocalItems:(NSString*)operationName + ckoperationGroup:(CKOperationGroup*)operationGroup + after:(NSOperation*)after +{ + CKKSScanLocalItemsOperation* scanOperation = (CKKSScanLocalItemsOperation*)[self findFirstPendingOperation:self.scanLocalItemsOperations]; + + if(scanOperation) { + [scanOperation addNullableDependency:after]; + + // check (again) for race condition; if the op has started we need to add another (for the dependency) + if([scanOperation isPending]) { + if(operationGroup) { + scanOperation.ckoperationGroup = operationGroup; + } + + scanOperation.name = [NSString stringWithFormat:@"%@::%@", scanOperation.name, operationName]; + return scanOperation; + } + } + + scanOperation = [[CKKSScanLocalItemsOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError + ckoperationGroup:operationGroup]; scanOperation.name = operationName; [scanOperation addNullableDependency:self.lastFixupOperation]; @@ -2614,30 +1866,30 @@ [scanOperation addNullableDependency:self.keyStateReadyDependency]; [scanOperation addNullableDependency:after]; - [self scheduleOperation: scanOperation]; + [scanOperation linearDependencies:self.scanLocalItemsOperations]; + + // This might generate items for upload. Make sure that any uploads wait until the scan is complete, so we know what to upload + [scanOperation linearDependencies:self.outgoingQueueOperations]; + + [self scheduleOperation:scanOperation]; + self.initiatedLocalScan = YES; return scanOperation; } - (CKKSUpdateDeviceStateOperation*)updateDeviceState:(bool)rateLimit waitForKeyHierarchyInitialization:(uint64_t)timeout ckoperationGroup:(CKOperationGroup*)ckoperationGroup { - - WEAKIFY(self); - // If securityd just started, the key state might be in some transient early state. Wait a bit. - CKKSResultOperation* waitForKeyReady = [CKKSResultOperation named:@"device-state-wait" withBlock:^{ - STRONGIFY(self); - ckksnotice("ckksdevice", self, "Finished waiting for key hierarchy transient state, currently %@", self.keyHierarchyState); - }]; - - [waitForKeyReady addNullableDependency:self.keyStateNonTransientDependency]; - [waitForKeyReady timeout:timeout]; - [self.waitingQueue addOperation:waitForKeyReady]; + OctagonStateMultiStateArrivalWatcher* waitForTransient = [[OctagonStateMultiStateArrivalWatcher alloc] initNamed:@"rpc-watcher" + serialQueue:self.queue + states:CKKSKeyStateNonTransientStates()]; + [waitForTransient timeout:timeout]; + [self.stateMachine registerMultiStateArrivalWatcher:waitForTransient]; CKKSUpdateDeviceStateOperation* op = [[CKKSUpdateDeviceStateOperation alloc] initWithCKKSKeychainView:self rateLimit:rateLimit ckoperationGroup:ckoperationGroup]; op.name = @"device-state-operation"; - [op addDependency: waitForKeyReady]; + [op addDependency:waitForTransient.result]; // op modifies the CloudKit zone, so it should insert itself into the list of OutgoingQueueOperations. // Then, we won't have simultaneous zone-modifying operations and confuse ourselves. @@ -2650,127 +1902,18 @@ return op; } +- (void)xpc24HrNotification +{ + // Called roughly once every 24hrs + [self.stateMachine handleFlag:CKKSFlag24hrNotification]; +} + // There are some errors which won't be reported but will be reflected in the CDSE; any error coming out of here is fatal - (CKKSDeviceStateEntry*)_onqueueCurrentDeviceStateEntry: (NSError* __autoreleasing*)error { - NSError* localerror = nil; - - CKKSAccountStateTracker* accountTracker = self.accountTracker; - CKKSAccountStatus hsa2Status = accountTracker.hsa2iCloudAccountStatus; - - // We must have an HSA2 iCloud account and a CloudKit account to even create one of these - if(hsa2Status != CKKSAccountStatusAvailable || - accountTracker.currentCKAccountInfo.accountStatus != CKAccountStatusAvailable) { - ckkserror("ckksdevice", self, "No iCloud account active: %@ hsa2 account:%@", - accountTracker.currentCKAccountInfo, - CKKSAccountStatusToString(hsa2Status)); - localerror = [NSError errorWithDomain:@"securityd" - code:errSecInternalError - userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No active HSA2 iCloud account: %@", accountTracker.currentCKAccountInfo]}]; - if(error) { - *error = localerror; - } - return nil; - } - - NSString* ckdeviceID = accountTracker.ckdeviceID; - if(ckdeviceID == nil) { - ckkserror("ckksdevice", self, "No CK device ID available; cannot make device state entry"); - localerror = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNotLoggedIn - userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No CK device ID: %@", accountTracker.currentCKAccountInfo]}]; - if(error) { - *error = localerror; - } - return nil; - } - - CKKSDeviceStateEntry* oldcdse = [CKKSDeviceStateEntry tryFromDatabase:ckdeviceID zoneID:self.zoneID error:&localerror]; - if(localerror) { - ckkserror("ckksdevice", self, "Couldn't read old CKKSDeviceStateEntry from database: %@", localerror); - if(error) { - *error = localerror; - } - return nil; - } - - // Find out what we think the current keys are - CKKSCurrentKeyPointer* currentTLKPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassTLK zoneID:self.zoneID error:&localerror]; - CKKSCurrentKeyPointer* currentClassAPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassA zoneID:self.zoneID error:&localerror]; - CKKSCurrentKeyPointer* currentClassCPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassC zoneID:self.zoneID error:&localerror]; - if(localerror) { - // Things is broken, but the whole point of this record is to share the brokenness. Continue. - ckkserror("ckksdevice", self, "Couldn't read current key pointers from database: %@; proceeding", localerror); - localerror = nil; - } - - CKKSKey* suggestedTLK = currentTLKPointer.currentKeyUUID ? [CKKSKey tryFromDatabase:currentTLKPointer.currentKeyUUID zoneID:self.zoneID error:&localerror] : nil; - CKKSKey* suggestedClassAKey = currentClassAPointer.currentKeyUUID ? [CKKSKey tryFromDatabase:currentClassAPointer.currentKeyUUID zoneID:self.zoneID error:&localerror] : nil; - CKKSKey* suggestedClassCKey = currentClassCPointer.currentKeyUUID ? [CKKSKey tryFromDatabase:currentClassCPointer.currentKeyUUID zoneID:self.zoneID error:&localerror] : nil; - - if(localerror) { - // Things is broken, but the whole point of this record is to share the brokenness. Continue. - ckkserror("ckksdevice", self, "Couldn't read keys from database: %@; proceeding", localerror); - localerror = nil; - } - - // Check if we posess the keys in the keychain - [suggestedTLK ensureKeyLoaded:&localerror]; - if(localerror && [self.lockStateTracker isLockedError:localerror]) { - ckkserror("ckksdevice", self, "Device is locked; couldn't read TLK from keychain. Assuming it is present and continuing; error was %@", localerror); - localerror = nil; - } else if(localerror) { - ckkserror("ckksdevice", self, "Couldn't read TLK from keychain. We do not have a current TLK. Error was %@", localerror); - suggestedTLK = nil; - } - - [suggestedClassAKey ensureKeyLoaded:&localerror]; - if(localerror && [self.lockStateTracker isLockedError:localerror]) { - ckkserror("ckksdevice", self, "Device is locked; couldn't read ClassA key from keychain. Assuming it is present and continuing; error was %@", localerror); - localerror = nil; - } else if(localerror) { - ckkserror("ckksdevice", self, "Couldn't read ClassA key from keychain. We do not have a current ClassA key. Error was %@", localerror); - suggestedClassAKey = nil; - } - - [suggestedClassCKey ensureKeyLoaded:&localerror]; - // class C keys are stored class C, so uh, don't check lock state. - if(localerror) { - ckkserror("ckksdevice", self, "Couldn't read ClassC key from keychain. We do not have a current ClassC key. Error was %@", localerror); - suggestedClassCKey = nil; - } - - // We'd like to have the circle peer ID. Give the account state tracker a fighting chance, but not having it is not an error - // But, if the platform doesn't have SOS, don't bother - if(OctagonPlatformSupportsSOS() && [accountTracker.accountCirclePeerIDInitialized wait:500*NSEC_PER_MSEC] != 0 && !accountTracker.accountCirclePeerID) { - ckkserror("ckksdevice", self, "No SOS peer ID available"); - } - - // We'd also like the Octagon status - if([accountTracker.octagonInformationInitialized wait:500*NSEC_PER_MSEC] != 0 && !accountTracker.octagonPeerID) { - ckkserror("ckksdevice", self, "No octagon peer ID available"); - } - - // Reset the last unlock time to 'day' granularity in UTC - NSCalendar* calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierISO8601]; - calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; - NSDate* lastUnlockDay = self.lockStateTracker.lastUnlockTime; - lastUnlockDay = lastUnlockDay ? [calendar startOfDayForDate:lastUnlockDay] : nil; - - // We only really want the oldcdse for its encodedCKRecord, so make a new cdse here - CKKSDeviceStateEntry* newcdse = [[CKKSDeviceStateEntry alloc] initForDevice:ckdeviceID - osVersion:SecCKKSHostOSVersion() - lastUnlockTime:lastUnlockDay - octagonPeerID:accountTracker.octagonPeerID - octagonStatus:accountTracker.octagonStatus - circlePeerID:accountTracker.accountCirclePeerID - circleStatus:accountTracker.currentCircleStatus.status - keyState:self.keyHierarchyState - currentTLKUUID:suggestedTLK.uuid - currentClassAUUID:suggestedClassAKey.uuid - currentClassCUUID:suggestedClassCKey.uuid - zoneID:self.zoneID - encodedCKRecord:oldcdse.encodedCKRecord]; - return newcdse; + return [CKKSDeviceStateEntry intransactionCreateDeviceStateForView:self.viewState + accountTracker:self.accountTracker + lockStateTracker:self.lockStateTracker + error:error]; } - (CKKSSynchronizeOperation*) resyncWithCloud { @@ -2785,511 +1928,34 @@ return op; } -- (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because { - return [self fetchAndProcessCKChanges:because after:nil]; -} - -- (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because after:(CKKSResultOperation*)after { - if(!SecCKKSIsEnabled()) { +- (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because +{ + if(!SecCKKSIsEnabled()) { ckksinfo("ckks", self, "Skipping fetchAndProcessCKChanges due to disabled CKKS"); return nil; } - if(after) { - [self.zoneChangeFetcher holdFetchesUntil:after]; - } - - // We fetched some changes; try to process them! + // We fetched some changes; try to process them! return [self processIncomingQueue:false after:[self.zoneChangeFetcher requestSuccessfulFetch:because]]; } -- (CKKSResultOperation*)fetchAndProcessCKChangesDueToAPNS:(CKRecordZoneNotification*)notification { - if(!SecCKKSIsEnabled()) { - ckksinfo("ckks", self, "Skipping fetchAndProcessCKChanges due to disabled CKKS"); - return nil; - } - - CKKSResultOperation *fetchOp = [self.zoneChangeFetcher requestFetchDueToAPNS:notification]; - if (fetchOp == nil) { - ckksnotice("ckks", self, "Skipping push induced processCKChanges due to zones are not ready"); - return nil; - } - - // We fetched some changes; try to process them! - return [self processIncomingQueue:false after:fetchOp]; -} - -// Lets the view know about a failed CloudKit write. If the error is "already have one of these records", it will -// store the new records and kick off the new processing -// -// Note that you need to tell this function the records you wanted to save, so it can determine what needs deletion -- (bool)_onqueueCKWriteFailed:(NSError*)ckerror attemptedRecordsChanged:(NSDictionary*)savedRecords { - dispatch_assert_queue(self.queue); - - NSDictionary* partialErrors = ckerror.userInfo[CKPartialErrorsByItemIDKey]; - if([ckerror.domain isEqual:CKErrorDomain] && ckerror.code == CKErrorPartialFailure && partialErrors) { - // Check if this error was "you're out of date" - bool recordChanged = true; - - for(NSError* error in partialErrors.allValues) { - if((![error.domain isEqual:CKErrorDomain]) || (error.code != CKErrorBatchRequestFailed && error.code != CKErrorServerRecordChanged && error.code != CKErrorUnknownItem)) { - // There's an error in there that isn't CKErrorServerRecordChanged, CKErrorBatchRequestFailed, or CKErrorUnknownItem. Don't handle nicely... - recordChanged = false; - } - } - - if(recordChanged) { - ckksnotice("ckks", self, "Received a ServerRecordChanged error, attempting to update new records and delete unknown ones"); - - bool updatedRecord = false; - - for(CKRecordID* recordID in partialErrors.allKeys) { - NSError* error = partialErrors[recordID]; - if([error.domain isEqual:CKErrorDomain] && error.code == CKErrorServerRecordChanged) { - CKRecord* newRecord = error.userInfo[CKRecordChangedErrorServerRecordKey]; - ckksnotice("ckks", self, "On error: updating our idea of: %@", newRecord); - - updatedRecord |= [self _onqueueCKRecordChanged:newRecord resync:true]; - } else if([error.domain isEqual:CKErrorDomain] && error.code == CKErrorUnknownItem) { - CKRecord* record = savedRecords[recordID]; - ckksnotice("ckks", self, "On error: handling an unexpected delete of: %@ %@", recordID, record); - - updatedRecord |= [self _onqueueCKRecordDeleted:recordID recordType:record.recordType resync:true]; - } - } - - if(updatedRecord) { - [self processIncomingQueue:false]; - return true; - } - } - - // Check if this error was the CKKS server extension rejecting the write - for(CKRecordID* recordID in partialErrors.allKeys) { - NSError* error = partialErrors[recordID]; - - NSError* underlyingError = error.userInfo[NSUnderlyingErrorKey]; - NSError* thirdLevelError = underlyingError.userInfo[NSUnderlyingErrorKey]; - ckksnotice("ckks", self, "Examining 'write failed' error: %@ %@ %@", error, underlyingError, thirdLevelError); - - if([error.domain isEqualToString:CKErrorDomain] && error.code == CKErrorServerRejectedRequest && - underlyingError && [underlyingError.domain isEqualToString:CKInternalErrorDomain] && underlyingError.code == CKErrorInternalPluginError && - thirdLevelError && [thirdLevelError.domain isEqualToString:@"CloudkitKeychainService"]) { - - if(thirdLevelError.code == CKKSServerUnexpectedSyncKeyInChain) { - // The server thinks the classA/C synckeys don't wrap directly the to top TLK, but we don't (otherwise, we would have fixed it). - // Issue a key hierarchy fetch and see what's what. - ckkserror("ckks", self, "CKKS Server extension has told us about %@ for record %@; requesting refetch and reprocess of key hierarchy", thirdLevelError, recordID); - [self _onqueueKeyStateMachineRequestFetch]; - - } else if(thirdLevelError.code == CKKSServerMissingRecord) { - // The server is concerned that there's a missing record somewhere. - // Issue a key hierarchy fetch and see what's happening - ckkserror("ckks", self, "CKKS Server extension has told us about %@ for record %@; requesting refetch and reprocess of key hierarchy", thirdLevelError, recordID); - [self _onqueueKeyStateMachineRequestFetch]; - - } else { - ckkserror("ckks", self, "CKKS Server extension has told us about %@ for record %@, but we don't currently handle this error", thirdLevelError, recordID); - } - } - } - } - - return false; -} - -- (bool)_onqueueCKRecordDeleted:(CKRecordID*)recordID recordType:(NSString*)recordType resync:(bool)resync { - dispatch_assert_queue(self.queue); - - // TODO: resync doesn't really mean much here; what does it mean for a record to be 'deleted' if you're fetching from scratch? - - if([recordType isEqual: SecCKRecordItemType]) { - ckksinfo("ckks", self, "CloudKit notification: deleted record(%@): %@", recordType, recordID); - NSError* error = nil; - NSError* iqeerror = nil; - CKKSMirrorEntry* ckme = [CKKSMirrorEntry fromDatabase: [recordID recordName] zoneID:self.zoneID error: &error]; - - // Deletes always succeed, not matter the generation count - if(ckme) { - [ckme deleteFromDatabase:&error]; - - CKKSIncomingQueueEntry* iqe = [[CKKSIncomingQueueEntry alloc] initWithCKKSItem:ckme.item action:SecCKKSActionDelete state:SecCKKSStateNew]; - [iqe saveToDatabase:&iqeerror]; - if(iqeerror) { - ckkserror("ckks", self, "Couldn't save incoming queue entry: %@", iqeerror); - } - } - ckksinfo("ckks", self, "CKKSMirrorEntry was deleted: %@ %@ error: %@", recordID, ckme, error); - // TODO: actually pass error back up - return (error == nil); - - } else if([recordType isEqual: SecCKRecordCurrentItemType]) { - ckksinfo("ckks", self, "CloudKit notification: deleted current item pointer(%@): %@", recordType, recordID); - NSError* error = nil; - - [[CKKSCurrentItemPointer tryFromDatabase:[recordID recordName] state:SecCKKSProcessedStateRemote zoneID:self.zoneID error:&error] deleteFromDatabase:&error]; - [[CKKSCurrentItemPointer fromDatabase:[recordID recordName] state:SecCKKSProcessedStateLocal zoneID:self.zoneID error:&error] deleteFromDatabase:&error]; - - ckksinfo("ckks", self, "CKKSCurrentItemPointer was deleted: %@ error: %@", recordID, error); - return (error == nil); - - } else if([recordType isEqual: SecCKRecordIntermediateKeyType]) { - // TODO: handle in some interesting way - return true; - } else if([recordType isEqual: SecCKRecordTLKShareType]) { - NSError* error = nil; - ckksinfo("ckks", self, "CloudKit notification: deleted tlk share record(%@): %@", recordType, recordID); - CKKSTLKShareRecord* share = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:recordID error:&error]; - [share deleteFromDatabase:&error]; - - if(error) { - ckkserror("ckks", self, "CK notification: Couldn't delete deleted TLKShare: %@ %@", recordID, error); - } - return (error == nil); - - } else if([recordType isEqual: SecCKRecordDeviceStateType]) { - NSError* error = nil; - ckksinfo("ckks", self, "CloudKit notification: deleted device state record(%@): %@", recordType, recordID); - - CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry tryFromDatabaseFromCKRecordID:recordID error:&error]; - [cdse deleteFromDatabase: &error]; - ckksinfo("ckks", self, "CKKSCurrentItemPointer(%@) was deleted: %@ error: %@", cdse, recordID, error); - - return (error == nil); - - } else if ([recordType isEqualToString:SecCKRecordManifestType]) { - ckksinfo("ckks", self, "CloudKit notification: deleted manifest record (%@): %@", recordType, recordID); - - NSError* error = nil; - CKKSManifest* manifest = [CKKSManifest manifestForRecordName:recordID.recordName error:&error]; - if (manifest) { - [manifest deleteFromDatabase:&error]; - } - - ckksinfo("ckks", self, "CKKSManifest was deleted: %@ %@ error: %@", recordID, manifest, error); - // TODO: actually pass error back up - return error == nil; - } - - else { - ckkserror("ckksfetch", self, "unknown record type: %@ %@", recordType, recordID); - return false; - } -} - -- (bool)_onqueueCKRecordChanged:(CKRecord*)record resync:(bool)resync { - dispatch_assert_queue(self.queue); - - @autoreleasepool { - ckksnotice("ckksfetch", self, "Processing record modification(%@): %@", record.recordType, record); - - if([[record recordType] isEqual: SecCKRecordItemType]) { - [self _onqueueCKRecordItemChanged:record resync:resync]; - return true; - } else if([[record recordType] isEqual: SecCKRecordCurrentItemType]) { - [self _onqueueCKRecordCurrentItemPointerChanged:record resync:resync]; - return true; - } else if([[record recordType] isEqual: SecCKRecordIntermediateKeyType]) { - [self _onqueueCKRecordKeyChanged:record resync:resync]; - return true; - } else if ([[record recordType] isEqual: SecCKRecordTLKShareType]) { - [self _onqueueCKRecordTLKShareChanged:record resync:resync]; - return true; - } else if([[record recordType] isEqualToString: SecCKRecordCurrentKeyType]) { - [self _onqueueCKRecordCurrentKeyPointerChanged:record resync:resync]; - return true; - } else if ([[record recordType] isEqualToString:SecCKRecordManifestType]) { - [self _onqueueCKRecordManifestChanged:record resync:resync]; - return true; - } else if ([[record recordType] isEqualToString:SecCKRecordManifestLeafType]) { - [self _onqueueCKRecordManifestLeafChanged:record resync:resync]; - return true; - } else if ([[record recordType] isEqualToString:SecCKRecordDeviceStateType]) { - [self _onqueueCKRecordDeviceStateChanged:record resync:resync]; - return true; - } else { - ckkserror("ckksfetch", self, "unknown record type: %@ %@", [record recordType], record); - return false; - } - } -} - -- (void)_onqueueCKRecordItemChanged:(CKRecord*)record resync:(bool)resync { - dispatch_assert_queue(self.queue); - - NSError* error = nil; - // Find if we knew about this record in the past - bool update = false; - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: [[record recordID] recordName] zoneID:self.zoneID error:&error]; - - if(error) { - ckkserror("ckks", self, "error loading a CKKSMirrorEntry from database: %@", error); - // TODO: quit? - } - - if(resync) { - if(!ckme) { - ckkserror("ckksresync", self, "BUG: No local item matching resynced CloudKit record: %@", record); - } else if(![ckme matchesCKRecord:record]) { - ckkserror("ckksresync", self, "BUG: Local item doesn't match resynced CloudKit record: %@ %@", ckme, record); - } else { - ckksnotice("ckksresync", self, "Already know about this item record, updating anyway: %@", record.recordID); - } - } - - if(ckme && ckme.item && ckme.item.generationCount > [record[SecCKRecordGenerationCountKey] unsignedLongLongValue]) { - ckkserror("ckks", self, "received a record from CloudKit with a bad generation count: %@ (%ld > %@)", ckme.uuid, - (long) ckme.item.generationCount, - record[SecCKRecordGenerationCountKey]); - // Abort processing this record. - return; - } - - // If we found an old version in the database; this might be an update - if(ckme) { - if([ckme matchesCKRecord:record] && !resync) { - // This is almost certainly a record we uploaded; CKFetchChanges sends them back as new records - ckksnotice("ckks", self, "CloudKit has told us of record we already know about; skipping update"); - return; - } - - update = true; - // Set the CKKSMirrorEntry's fields to be whatever this record holds - [ckme setFromCKRecord: record]; - } else { - // Have to make a new CKKSMirrorEntry - ckme = [[CKKSMirrorEntry alloc] initWithCKRecord: record]; - } - - [ckme saveToDatabase: &error]; - - if(error) { - ckkserror("ckks", self, "couldn't save new CKRecord to database: %@ %@", record, error); - } else { - ckksdebug("ckks", self, "CKKSMirrorEntry was created: %@", ckme); - } - - NSError* iqeerror = nil; - CKKSIncomingQueueEntry* iqe = [[CKKSIncomingQueueEntry alloc] initWithCKKSItem:ckme.item - action:(update ? SecCKKSActionModify : SecCKKSActionAdd) - state:SecCKKSStateNew]; - [iqe saveToDatabase:&iqeerror]; - if(iqeerror) { - ckkserror("ckks", self, "Couldn't save modified incoming queue entry: %@", iqeerror); - } else { - ckksdebug("ckks", self, "CKKSIncomingQueueEntry was created: %@", iqe); - } - - // A remote change has occured for this record. Delete any pending local changes; they will be overwritten. - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:ckme.uuid state: SecCKKSStateNew zoneID:self.zoneID error: &error]; - if(error) { - ckkserror("ckks", self, "Couldn't load OutgoingQueueEntry: %@", error); - } - if(oqe) { - [self _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&error]; - } - - // Reencryptions are pending changes too - oqe = [CKKSOutgoingQueueEntry tryFromDatabase:ckme.uuid state: SecCKKSStateReencrypt zoneID:self.zoneID error: &error]; - if(error) { - ckkserror("ckks", self, "Couldn't load reencrypted OutgoingQueueEntry: %@", error); - } - if(oqe) { - [oqe deleteFromDatabase:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't delete reencrypted oqe(%@): %@", oqe, error); - } - } -} - -- (void)_onqueueCKRecordKeyChanged:(CKRecord*)record resync:(bool)resync { - dispatch_assert_queue(self.queue); - - NSError* error = nil; - - if(resync) { - NSError* resyncerror = nil; - - CKKSKey* key = [CKKSKey tryFromDatabaseAnyState:record.recordID.recordName zoneID:self.zoneID error:&resyncerror]; - if(resyncerror) { - ckkserror("ckksresync", self, "error loading key: %@", resyncerror); - } - if(!key) { - ckkserror("ckksresync", self, "BUG: No sync key matching resynced CloudKit record: %@", record); - } else if(![key matchesCKRecord:record]) { - ckkserror("ckksresync", self, "BUG: Local sync key doesn't match resynced CloudKit record(s): %@ %@", key, record); - } else { - ckksnotice("ckksresync", self, "Already know about this sync key, skipping update: %@", record); - return; - } - } - - CKKSKey* remotekey = [[CKKSKey alloc] initWithCKRecord: record]; - - // Do we already know about this key? - CKKSKey* possibleLocalKey = [CKKSKey tryFromDatabase:remotekey.uuid zoneID:self.zoneID error:&error]; - if(error) { - ckkserror("ckkskey", self, "Error findibg exsiting local key for %@: %@", remotekey, error); - // Go on, assuming there isn't a local key - } else if(possibleLocalKey && [possibleLocalKey matchesCKRecord:record]) { - // Okay, nothing new here. Update the CKRecord and move on. - // Note: If the new record doesn't match the local copy, we have to go through the whole dance below - possibleLocalKey.storedCKRecord = record; - [possibleLocalKey saveToDatabase:&error]; - - if(error) { - ckkserror("ckkskey", self, "Couldn't update existing key: %@: %@", possibleLocalKey, error); - } - return; - } - - // Drop into the synckeys table as a 'remote' key, then ask for a rekey operation. - remotekey.state = SecCKKSProcessedStateRemote; - remotekey.currentkey = false; - - [remotekey saveToDatabase:&error]; - if(error) { - ckkserror("ckkskey", self, "Couldn't save key record to database: %@: %@", remotekey, error); - ckksinfo("ckkskey", self, "CKRecord was %@", record); - } - - // We've saved a new key in the database; trigger a rekey operation. - [self _onqueueKeyStateMachineRequestProcess]; -} - -- (void)_onqueueCKRecordTLKShareChanged:(CKRecord*)record resync:(bool)resync { - dispatch_assert_queue(self.queue); - - NSError* error = nil; - if(resync) { - // TODO fill in - } - - // CKKSTLKShares get saved with no modification - CKKSTLKShareRecord* share = [[CKKSTLKShareRecord alloc] initWithCKRecord:record]; - [share saveToDatabase:&error]; - if(error) { - ckkserror("ckksshare", self, "Couldn't save new TLK share to database: %@ %@", share, error); - } - - [self _onqueueKeyStateMachineRequestProcess]; -} - -- (void)_onqueueCKRecordCurrentKeyPointerChanged:(CKRecord*)record resync:(bool)resync { - dispatch_assert_queue(self.queue); - - // Pull out the old CKP, if it exists - NSError* ckperror = nil; - CKKSCurrentKeyPointer* oldckp = [CKKSCurrentKeyPointer tryFromDatabase:((CKKSKeyClass*) record.recordID.recordName) zoneID:self.zoneID error:&ckperror]; - if(ckperror) { - ckkserror("ckkskey", self, "error loading ckp: %@", ckperror); - } - - if(resync) { - if(!oldckp) { - ckkserror("ckksresync", self, "BUG: No current key pointer matching resynced CloudKit record: %@", record); - } else if(![oldckp matchesCKRecord:record]) { - ckkserror("ckksresync", self, "BUG: Local current key pointer doesn't match resynced CloudKit record: %@ %@", oldckp, record); - } else { - ckksnotice("ckksresync", self, "Current key pointer has 'changed', but it matches our local copy: %@", record); - } - } - - NSError* error = nil; - CKKSCurrentKeyPointer* currentkey = [[CKKSCurrentKeyPointer alloc] initWithCKRecord: record]; - - [currentkey saveToDatabase: &error]; - if(error) { - ckkserror("ckkskey", self, "Couldn't save current key pointer to database: %@: %@", currentkey, error); - ckksinfo("ckkskey", self, "CKRecord was %@", record); - } - - if([oldckp matchesCKRecord:record]) { - ckksnotice("ckkskey", self, "Current key pointer modification doesn't change anything interesting; skipping reprocess: %@", record); - } else { - // We've saved a new key in the database; trigger a rekey operation. - [self _onqueueKeyStateMachineRequestProcess]; - } -} - -- (void)_onqueueCKRecordCurrentItemPointerChanged:(CKRecord*)record resync:(bool)resync { - dispatch_assert_queue(self.queue); - - if(resync) { - NSError* ciperror = nil; - CKKSCurrentItemPointer* localcip = [CKKSCurrentItemPointer tryFromDatabase:record.recordID.recordName state:SecCKKSProcessedStateLocal zoneID:self.zoneID error:&ciperror]; - CKKSCurrentItemPointer* remotecip = [CKKSCurrentItemPointer tryFromDatabase:record.recordID.recordName state:SecCKKSProcessedStateRemote zoneID:self.zoneID error:&ciperror]; - if(ciperror) { - ckkserror("ckksresync", self, "error loading cip: %@", ciperror); - } - if(!(localcip || remotecip)) { - ckkserror("ckksresync", self, "BUG: No current item pointer matching resynced CloudKit record: %@", record); - } else if(! ([localcip matchesCKRecord:record] || [remotecip matchesCKRecord:record]) ) { - ckkserror("ckksresync", self, "BUG: Local current item pointer doesn't match resynced CloudKit record(s): %@ %@ %@", localcip, remotecip, record); - } else { - ckksnotice("ckksresync", self, "Already know about this current item pointer, skipping update: %@", record); - return; - } - } - - NSError* error = nil; - CKKSCurrentItemPointer* cip = [[CKKSCurrentItemPointer alloc] initWithCKRecord: record]; - cip.state = SecCKKSProcessedStateRemote; - - [cip saveToDatabase: &error]; - if(error) { - ckkserror("currentitem", self, "Couldn't save current item pointer to database: %@: %@ %@", cip, error, record); - } -} - -- (void)_onqueueCKRecordManifestChanged:(CKRecord*)record resync:(bool)resync +- (bool)_onqueueCKWriteFailed:(NSError*)ckerror attemptedRecordsChanged:(NSDictionary*)savedRecords { - NSError* error = nil; - CKKSPendingManifest* manifest = [[CKKSPendingManifest alloc] initWithCKRecord:record]; - [manifest saveToDatabase:&error]; - if (error) { - ckkserror("CKKS", self, "Failed to save fetched manifest record to database: %@: %@", manifest, error); - ckksinfo("CKKS", self, "manifest CKRecord was %@", record); - } + return [self.operationDependencies intransactionCKWriteFailed:ckerror attemptedRecordsChanged:savedRecords]; } -- (void)_onqueueCKRecordManifestLeafChanged:(CKRecord*)record resync:(bool)resync +- (bool)_onqueueCKRecordChanged:(CKRecord*)record resync:(bool)resync { - NSError* error = nil; - CKKSManifestLeafRecord* manifestLeaf = [[CKKSManifestPendingLeafRecord alloc] initWithCKRecord:record]; - [manifestLeaf saveToDatabase:&error]; - if (error) { - ckkserror("CKKS", self, "Failed to save fetched manifest leaf record to database: %@: %@", manifestLeaf, error); - ckksinfo("CKKS", self, "manifest leaf CKRecord was %@", record); - } + return [self.operationDependencies intransactionCKRecordChanged:record resync:resync]; } -- (void)_onqueueCKRecordDeviceStateChanged:(CKRecord*)record resync:(bool)resync { - if(resync) { - NSError* dserror = nil; - CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry tryFromDatabase:record.recordID.recordName zoneID:self.zoneID error:&dserror]; - if(dserror) { - ckkserror("ckksresync", self, "error loading cdse: %@", dserror); - } - if(!cdse) { - ckkserror("ckksresync", self, "BUG: No current device state entry matching resynced CloudKit record: %@", record); - } else if(![cdse matchesCKRecord:record]) { - ckkserror("ckksresync", self, "BUG: Local current device state entry doesn't match resynced CloudKit record(s): %@ %@", cdse, record); - } else { - ckksnotice("ckksresync", self, "Already know about this current item pointer, skipping update: %@", record); - return; - } - } - - NSError* error = nil; - CKKSDeviceStateEntry* cdse = [[CKKSDeviceStateEntry alloc] initWithCKRecord:record]; - [cdse saveToDatabase:&error]; - if (error) { - ckkserror("ckksdevice", self, "Failed to save device record to database: %@: %@ %@", cdse, error, record); - } +- (bool)_onqueueCKRecordDeleted:(CKRecordID*)recordID recordType:(NSString*)recordType resync:(bool)resync +{ + return [self.operationDependencies intransactionCKRecordDeleted:recordID recordType:recordType resync:resync]; } - (bool)_onqueueResetAllInflightOQE:(NSError**)error { + dispatch_assert_queue(self.queue); NSError* localError = nil; while(true) { @@ -3311,7 +1977,7 @@ } for(CKKSOutgoingQueueEntry* oqe in inflightQueueEntries) { - [self _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateNew error:&localError]; + [oqe intransactionMoveToState:SecCKKSStateNew viewState:self.viewState error:&localError]; if(localError) { ckkserror("ckks", self, "Error fixing up inflight OQE(%@): %@", oqe, localError); @@ -3326,287 +1992,33 @@ return true; } -- (bool)_onqueueChangeOutgoingQueueEntry: (CKKSOutgoingQueueEntry*) oqe toState: (NSString*) state error: (NSError* __autoreleasing*) error { - dispatch_assert_queue(self.queue); - - NSError* localerror = nil; - - if([state isEqualToString: SecCKKSStateDeleted]) { - // Hurray, this must be a success - SecBoolNSErrorCallback callback = self.pendingSyncCallbacks[oqe.uuid]; - if(callback) { - callback(true, nil); - self.pendingSyncCallbacks[oqe.uuid] = nil; - } - - [oqe deleteFromDatabase: &localerror]; - if(localerror) { - ckkserror("ckks", self, "Couldn't delete %@: %@", oqe, localerror); - } - - } else if([oqe.state isEqualToString:SecCKKSStateInFlight] && [state isEqualToString:SecCKKSStateNew]) { - // An in-flight OQE is moving to new? See if it's been superceded - CKKSOutgoingQueueEntry* newOQE = [CKKSOutgoingQueueEntry tryFromDatabase:oqe.uuid state:SecCKKSStateNew zoneID:self.zoneID error:&localerror]; - if(localerror) { - ckkserror("ckksoutgoing", self, "Couldn't fetch an overwriting OQE, assuming one doesn't exist: %@", localerror); - newOQE = nil; - } - - if(newOQE) { - ckksnotice("ckksoutgoing", self, "New modification has come in behind inflight %@; dropping failed change", oqe); - // recurse for that lovely code reuse - [self _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&localerror]; - if(localerror) { - ckkserror("ckksoutgoing", self, "Couldn't delete in-flight OQE: %@", localerror); - if(error) { - *error = localerror; - } - } - } else { - oqe.state = state; - [oqe saveToDatabase: &localerror]; - if(localerror) { - ckkserror("ckks", self, "Couldn't save %@ as %@: %@", oqe, state, localerror); - } - } - - } else { - oqe.state = state; - [oqe saveToDatabase: &localerror]; - if(localerror) { - ckkserror("ckks", self, "Couldn't save %@ as %@: %@", oqe, state, localerror); - } - } - - if(error && localerror) { - *error = localerror; - } - return localerror == nil; -} - -- (bool)_onqueueErrorOutgoingQueueEntry: (CKKSOutgoingQueueEntry*) oqe itemError: (NSError*) itemError error: (NSError* __autoreleasing*) error { - dispatch_assert_queue(self.queue); - - SecBoolNSErrorCallback callback = self.pendingSyncCallbacks[oqe.uuid]; - if(callback) { - callback(false, itemError); - self.pendingSyncCallbacks[oqe.uuid] = nil; - } - NSError* localerror = nil; - - // Now, delete the OQE: it's never coming back - [oqe deleteFromDatabase:&localerror]; - if(localerror) { - ckkserror("ckks", self, "Couldn't delete %@ (due to error %@): %@", oqe, itemError, localerror); - } - - if(error && localerror) { - *error = localerror; - } - return localerror == nil; -} - -- (bool)_onqueueUpdateLatestManifestWithError:(NSError**)error +- (bool)dispatchSyncWithConnection:(SecDbConnectionRef _Nonnull)dbconn + readWriteTxion:(BOOL)readWriteTxion + block:(CKKSDatabaseTransactionResult (^)(void))block { - dispatch_assert_queue(self.queue); - CKKSManifest* manifest = [CKKSManifest latestTrustedManifestForZone:self.zoneName error:error]; - if (manifest) { - self.latestManifest = manifest; - return true; - } - else { - return false; - } -} - -- (bool)_onqueueWithAccountKeysCheckTLK:(CKKSKey*)proposedTLK error:(NSError* __autoreleasing *)error { - dispatch_assert_queue(self.queue); - // First, if we have a local identity, check for any TLK shares - NSError* localerror = nil; - - if(![proposedTLK wrapsSelf]) { - localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSKeyNotSelfWrapped description:[NSString stringWithFormat:@"Potential TLK %@ doesn't wrap itself: %@", proposedTLK, proposedTLK.parentKeyUUID] underlying:NULL]; - ckkserror("ckksshare", self, "%@", localerror); - if (error) { - *error = localerror; - } - } else { - bool tlkShares = [self _onqueueWithAccountKeysCheckTLKFromShares:proposedTLK error:&localerror]; - // We only want to error out if a positive error occurred. "No shares" is okay. - if(!tlkShares || localerror) { - bool noTrustedTLKShares = [localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSNoTrustedTLKShares; - bool noSelfPeer = [localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSNoEncryptionKey; - bool noTrust = [localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSLackingTrust; - - // If this error was something worse than 'couldn't unwrap for reasons including there not being data', report it - if(!(noTrustedTLKShares || noSelfPeer || noTrust)) { - if(error) { - *error = localerror; - } - ckkserror("ckksshare", self, "Errored unwrapping TLK with TLKShares: %@", localerror); - return false; - } else { - ckkserror("ckksshare", self, "Non-fatal error unwrapping TLK with TLKShares: %@", localerror); - } - } - } - - if([proposedTLK loadKeyMaterialFromKeychain:error]) { - // Hurray! - return true; - } else { - return false; - } -} - -// This version only examines if this TLK is recoverable from TLK shares -- (bool)_onqueueWithAccountKeysCheckTLKFromShares:(CKKSKey*)proposedTLK error:(NSError* __autoreleasing *)error { - // But being recoverable from any trust set is okay - NSError* localerror = nil; - - if(self.currentTrustStates.count == 0u) { - if(error) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSLackingTrust - description:@"No current trust states; can't check TLK"]; - } - return false; - } - - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { - ckkserror("ckksshare", self, "Checking TLK from trust state %@", trustState); - bool recovered = [self _onqueueWithAccountKeysWithPeers:trustState - checkTLK:proposedTLK - error:&localerror]; - - if(recovered) { - ckkserror("ckksshare", self, "Recovered the TLK"); - return true; - } - - ckkserror("ckksshare", self, "Unable to recover TLK from trust set: %@", localerror); - } - - // Only report the last error - if(error && localerror) { - *error = localerror; - } - return false; -} - -- (bool)_onqueueWithAccountKeysWithPeers:(CKKSPeerProviderState*)trustState - checkTLK:(CKKSKey*)proposedTLK - error:(NSError* __autoreleasing *)error -{ - NSError* localerror = NULL; - if(!trustState.currentSelfPeers.currentSelf || trustState.currentSelfPeersError) { - ckkserror("ckksshare", self, "Don't have self peers for %@: %@", trustState.peerProviderID, trustState.currentSelfPeersError); - if(error) { - if([self.lockStateTracker isLockedError:trustState.currentSelfPeersError]) { - // Locked error should propagate - *error = trustState.currentSelfPeersError; - } else { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoEncryptionKey - description:@"No current self peer" - underlying:trustState.currentSelfPeersError]; - } - } - return false; - } - - if(!trustState.currentTrustedPeers || trustState.currentTrustedPeersError) { - ckkserror("ckksshare", self, "Don't have trusted peers: %@", trustState.currentTrustedPeersError); - if(error) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoPeersAvailable - description:@"No trusted peers" - underlying:trustState.currentTrustedPeersError]; - } - return false; - } - - NSError* lastShareError = nil; - - for(id selfPeer in trustState.currentSelfPeers.allSelves) { - NSArray* possibleShares = [CKKSTLKShareRecord allFor:selfPeer.peerID - keyUUID:proposedTLK.uuid - zoneID:self.zoneID - error:&localerror]; - if(localerror) { - ckkserror("ckksshare", self, "Error fetching CKKSTLKShares for %@: %@", selfPeer, localerror); - } - - if(possibleShares.count == 0) { - ckksnotice("ckksshare", self, "No CKKSTLKShares to %@ for %@", selfPeer, proposedTLK); - continue; - } - - for(CKKSTLKShareRecord* possibleShare in possibleShares) { - NSError* possibleShareError = nil; - ckksnotice("ckksshare", self, "Checking possible TLK share %@ as %@", possibleShare, selfPeer); - - CKKSKey* possibleKey = [possibleShare recoverTLK:selfPeer - trustedPeers:trustState.currentTrustedPeers - error:&possibleShareError]; - - if(possibleShareError) { - ckkserror("ckksshare", self, "Unable to unwrap TLKShare(%@) as %@: %@", - possibleShare, selfPeer, possibleShareError); - ckkserror("ckksshare", self, "Current trust set: %@", trustState.currentTrustedPeers); - lastShareError = possibleShareError; - continue; - } - - bool result = [proposedTLK trySelfWrappedKeyCandidate:possibleKey.aessivkey error:&possibleShareError]; - if(possibleShareError) { - ckkserror("ckksshare", self, "Unwrapped TLKShare(%@) does not unwrap proposed TLK(%@) as %@: %@", - possibleShare, proposedTLK, trustState.currentSelfPeers.currentSelf, possibleShareError); - lastShareError = possibleShareError; - continue; - } - - if(result) { - ckksnotice("ckksshare", self, "TLKShare(%@) unlocked TLK(%@) as %@", - possibleShare, proposedTLK, selfPeer); - - // The proposed TLK is trusted key material. Persist it as a "trusted" key. - [proposedTLK saveKeyMaterialToKeychain:true error:&possibleShareError]; - if(possibleShareError) { - ckkserror("ckksshare", self, "Couldn't store the new TLK(%@) to the keychain: %@", proposedTLK, possibleShareError); - if(error) { - *error = possibleShareError; - } - return false; - } - - return true; - } - } - } - - if(error) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoTrustedTLKShares - description:[NSString stringWithFormat:@"No trusted TLKShares for %@", proposedTLK] - underlying:lastShareError]; - } - return false; -} - -- (bool)dispatchSyncWithConnection:(SecDbConnectionRef _Nonnull)dbconn block:(bool (^)(void))block { CFErrorRef cferror = NULL; // Take the DB transaction, then get on the local queue. // In the case of exclusive DB transactions, we don't really _need_ the local queue, but, it's here for future use. - bool ret = kc_transaction_type(dbconn, kSecDbExclusiveRemoteCKKSTransactionType, &cferror, ^bool{ - __block bool ok = false; + + SecDbTransactionType txtionType = readWriteTxion ? kSecDbExclusiveRemoteCKKSTransactionType : kSecDbNormalTransactionType; + bool ret = kc_transaction_type(dbconn, txtionType, &cferror, ^bool{ + __block CKKSDatabaseTransactionResult result = CKKSDatabaseTransactionRollback; + + CKKSSQLInTransaction = true; + if(readWriteTxion) { + CKKSSQLInWriteTransaction = true; + } dispatch_sync(self.queue, ^{ - ok = block(); + result = block(); }); - return ok; + if(readWriteTxion) { + CKKSSQLInWriteTransaction = false; + } + CKKSSQLInTransaction = false; + return result == CKKSDatabaseTransactionCommit; }); if(cferror) { @@ -3615,7 +2027,8 @@ return ret; } -- (void)dispatchSync: (bool (^)(void)) block { +- (void)dispatchSyncWithSQLTransaction:(CKKSDatabaseTransactionResult (^)(void))block +{ // important enough to block this thread. Must get a connection first, though! // Please don't jetsam us... @@ -3623,7 +2036,10 @@ CFErrorRef cferror = NULL; kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { - return [self dispatchSyncWithConnection:dbt block:block]; + return [self dispatchSyncWithConnection:dbt + readWriteTxion:YES + block:block]; + }); if(cferror) { ckkserror("ckks", self, "error getting database connection, major problems ahead: %@", cferror); @@ -3632,137 +2048,177 @@ (void)transaction; } -- (void)dispatchSyncWithAccountKeys:(bool (^)(void))block +- (void)dispatchSyncWithReadOnlySQLTransaction:(void (^)(void))block { - [self dispatchSyncWithPeerProviders:self.currentPeerProviders override:false block:block]; -} + // Please don't jetsam us... + os_transaction_t transaction = os_transaction_create([[NSString stringWithFormat:@"com.apple.securityd.ckks.%@", self.zoneName] UTF8String]); -- (void)dispatchSyncWithPeerProviders:(NSArray>*)peerProviders - override:(bool)overridePeerProviders - block:(bool (^)(void))block -{ - NSArray>* actualPeerProviders = overridePeerProviders ? peerProviders : self.currentPeerProviders; - NSMutableArray* trustStates = [NSMutableArray array]; + CFErrorRef cferror = NULL; - for(id provider in actualPeerProviders) { - ckksnotice("ckks", self, "Fetching account keys for provider %@", provider); - [trustStates addObject:provider.currentState]; + // Note: we are lying to kc_with_dbt here about whether we're read-and-write or read-only. + // This is because the SOS engine's queue are broken: SOSEngineSetNotifyPhaseBlock attempts + // to take the SOS engine's queue while a SecDb transaction is still ongoing. But, in + // SOSEngineCopyPeerConfirmedDigests, SOS takes the engine queue, then calls dsCopyManifestWithViewNameSet() + // which attempts to get a read-only SecDb connection. + // + // The issue manifests when many CKKS read-only transactions are in-flight, and starve out + // the pool of read-only connections. Then, a deadlock forms. + // + // By claiming to be a read-write connection here, we'll contend on the pool of writer threads, + // and shouldn't starve SOS of its read thread. + // + // But, since we pass NO to readWriteTxion, the SQLite transaction will be of type + // kSecDbNormalTransactionType, which won't block other readers. + + kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { + return [self dispatchSyncWithConnection:dbt + readWriteTxion:NO + block:^CKKSDatabaseTransactionResult { + block(); + return CKKSDatabaseTransactionCommit; + }]; + + }); + if(cferror) { + ckkserror("ckks", self, "error getting database connection, major problems ahead: %@", cferror); } - [self dispatchSync:^bool{ - if(overridePeerProviders) { - self.currentPeerProviders = peerProviders; - } - self.currentTrustStates = trustStates; + (void)transaction; +} - bool result = block(); +- (BOOL)insideSQLTransaction +{ + return CKKSSQLInTransaction; +} - // Forget the peers; they might have class A key material - NSMutableArray* noTrustStates = [NSMutableArray array]; - for(id provider in peerProviders) { - (void)provider; - [noTrustStates addObject:[CKKSPeerProviderState noPeersState:provider]]; - } - self.currentTrustStates = noTrustStates; +#pragma mark - CKKSZone operations - return result; +- (void)beginCloudKitOperation +{ + [self.accountTracker registerForNotificationsOfCloudKitAccountStatusChange:self]; +} + +- (CKKSResultOperation*)createAccountLoggedInDependency:(NSString*)message +{ + WEAKIFY(self); + CKKSResultOperation* accountLoggedInDependency = [CKKSResultOperation named:@"account-logged-in-dependency" withBlock:^{ + STRONGIFY(self); + ckksnotice("ckkszone", self, "%@", message); }]; + accountLoggedInDependency.descriptionErrorCode = CKKSResultDescriptionPendingAccountLoggedIn; + return accountLoggedInDependency; } -#pragma mark - CKKSZoneUpdateReceiver +#pragma mark - CKKSZoneUpdateReceiverProtocol -- (void)notifyZoneChange: (CKRecordZoneNotification*) notification { - ckksnotice("ckks", self, "received a zone change notification for %@ %@", self, notification); - - [self fetchAndProcessCKChangesDueToAPNS:notification]; +- (CKKSAccountStatus)accountStatusFromCKAccountInfo:(CKAccountInfo*)info +{ + if(!info) { + return CKKSAccountStatusUnknown; + } + if(info.accountStatus == CKAccountStatusAvailable && + info.hasValidCredentials) { + return CKKSAccountStatusAvailable; + } else { + return CKKSAccountStatusNoAccount; + } } -- (void)superHandleCKLogin { - [super handleCKLogin]; +- (void)cloudkitAccountStateChange:(CKAccountInfo* _Nullable)oldAccountInfo to:(CKAccountInfo*)currentAccountInfo +{ + ckksnotice("ckkszone", self, "%@ Received notification of CloudKit account status change, moving from %@ to %@", + self.zoneID.zoneName, + oldAccountInfo, + currentAccountInfo); + + // Filter for device2device encryption and cloudkit grey mode + CKKSAccountStatus oldStatus = [self accountStatusFromCKAccountInfo:oldAccountInfo]; + CKKSAccountStatus currentStatus = [self accountStatusFromCKAccountInfo:currentAccountInfo]; + + if(oldStatus == currentStatus) { + ckksnotice("ckkszone", self, "Computed status of new CK account info is same as old status: %@", [CKKSAccountStateTracker stringFromAccountStatus:currentStatus]); + return; + } + + switch(currentStatus) { + case CKKSAccountStatusAvailable: { + ckksnotice("ckkszone", self, "Logged into iCloud."); + [self handleCKLogin]; + + if(self.accountLoggedInDependency) { + [self.operationQueue addOperation:self.accountLoggedInDependency]; + self.accountLoggedInDependency = nil; + }; + } + break; + + case CKKSAccountStatusNoAccount: { + ckksnotice("ckkszone", self, "Logging out of iCloud. Shutting down."); + + if(!self.accountLoggedInDependency) { + self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."]; + } + + [self handleCKLogout]; + } + break; + + case CKKSAccountStatusUnknown: { + // We really don't expect to receive this as a notification, but, okay! + ckksnotice("ckkszone", self, "Account status has become undetermined. Pausing for %@", self.zoneID.zoneName); + + if(!self.accountLoggedInDependency) { + self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."]; + } + + [self handleCKLogout]; + } + break; + } } -- (void)handleCKLogin { +- (void)handleCKLogin +{ ckksnotice("ckks", self, "received a notification of CK login"); if(!SecCKKSIsEnabled()) { ckksnotice("ckks", self, "Skipping CloudKit initialization due to disabled CKKS"); return; } - WEAKIFY(self); - CKKSResultOperation* login = [CKKSResultOperation named:@"ckks-login" withBlock:^{ - STRONGIFY(self); - - [self dispatchSyncWithAccountKeys:^bool{ - [self superHandleCKLogin]; - - // Reset key hierarchy state machine to initializing - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateInitializing withError:nil]; - return true; - }]; + dispatch_sync(self.queue, ^{ + ckksinfo("ckkszone", self, "received a notification of CK login"); // Change our condition variables to reflect that we think we're logged in + self.accountStatus = CKKSAccountStatusAvailable; self.loggedOut = [[CKKSCondition alloc] initToChain:self.loggedOut]; [self.loggedIn fulfill]; - [self.accountStateKnown fulfill]; - }]; - - [self scheduleAccountStatusOperation:login]; -} - -- (void)superHandleCKLogout { - [super handleCKLogout]; -} - -- (void)handleCKLogout { - WEAKIFY(self); - CKKSResultOperation* logout = [CKKSResultOperation named:@"ckks-logout" withBlock: ^{ - STRONGIFY(self); - if(!self) { - return; - } - [self dispatchSync:^bool { - ckksnotice("ckks", self, "received a notification of CK logout"); - [self superHandleCKLogout]; - - NSError* error = nil; - [self _onqueueResetLocalData: &error]; - if(error) { - ckkserror("ckks", self, "error while resetting local data: %@", error); - } - - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateLoggedOut withError:nil]; - - self.loggedIn = [[CKKSCondition alloc] initToChain: self.loggedIn]; - [self.loggedOut fulfill]; - [self.accountStateKnown fulfill]; - - // Tell all pending sync clients that we don't expect to ever sync - for(NSString* callbackUUID in self.pendingSyncCallbacks.allKeys) { - [self callSyncCallbackWithErrorNoAccount:self.pendingSyncCallbacks[callbackUUID]]; - self.pendingSyncCallbacks[callbackUUID] = nil; - } - - return true; - }]; - }]; - - [self scheduleAccountStatusOperation: logout]; -} - -- (void)callSyncCallbackWithErrorNoAccount:(SecBoolNSErrorCallback)syncCallback { - CKKSAccountStatus accountStatus = self.accountStatus; - dispatch_async(self.queue, ^{ - syncCallback(false, [NSError errorWithDomain:@"securityd" - code:errSecNotLoggedIn - userInfo:@{NSLocalizedDescriptionKey: - [NSString stringWithFormat: @"No iCloud account available(%d); item is not expected to sync", (int)accountStatus]}]); }); + + [self.stateMachine handleFlag:CKKSFlagCloudKitLoggedIn]; + + [self.accountStateKnown fulfill]; +} + +- (void)handleCKLogout +{ + dispatch_sync(self.queue, ^{ + ckksinfo("ckkszone", self, "received a notification of CK logout"); + + self.accountStatus = CKKSAccountStatusNoAccount; + self.loggedIn = [[CKKSCondition alloc] initToChain:self.loggedIn]; + [self.loggedOut fulfill]; + }); + + [self.stateMachine handleFlag:CKKSFlagCloudKitLoggedOut]; + + [self.accountStateKnown fulfill]; } #pragma mark - Trust operations - (void)beginTrustedOperation:(NSArray>*)peerProviders suggestTLKUpload:(CKKSNearFutureScheduler*)suggestTLKUpload + requestPolicyCheck:(CKKSNearFutureScheduler*)requestPolicyCheck { for(id peerProvider in peerProviders) { [peerProvider registerForPeerChangeUpdates:self]; @@ -3770,52 +2226,73 @@ [self.launch addEvent:@"beginTrusted"]; - [self dispatchSyncWithPeerProviders:peerProviders override:true block:^bool { + dispatch_sync(self.queue, ^{ ckksnotice("ckkstrust", self, "Beginning trusted operation"); + self.operationDependencies.peerProviders = peerProviders; + self.operationDependencies.requestPolicyCheck = requestPolicyCheck; + CKKSAccountStatus oldTrustStatus = self.trustStatus; self.suggestTLKUpload = suggestTLKUpload; self.trustStatus = CKKSAccountStatusAvailable; - if(self.trustDependency) { - [self scheduleOperation: self.trustDependency]; - self.trustDependency = nil; - } - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagBeginTrustedOperation]; + + // Re-process the key hierarchy, just in case the answer is now different + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; if(oldTrustStatus == CKKSAccountStatusNoAccount) { ckksnotice("ckkstrust", self, "Moving from an untrusted status; we need to process incoming queue and scan for any new items"); - // Next, try to process them (replacing local entries) - CKKSIncomingQueueOperation* initialProcess = [self processIncomingQueue:true after:nil]; - initialProcess.name = @"initial-process-incoming-queue"; - - // If all that succeeds, iterate through all keychain items and find the ones which need to be uploaded - self.initialScanOperation = [self scanLocalItems:@"newly-trusted-scan" - ckoperationGroup:nil - after:initialProcess]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagProcessIncomingQueue]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagScanLocalItems]; } - - return true; - }]; + }); } - (void)endTrustedOperation { [self.launch addEvent:@"endTrusted"]; - [self dispatchSyncWithPeerProviders:nil override:true block:^bool { + dispatch_sync(self.queue, ^{ ckksnotice("ckkstrust", self, "Ending trusted operation"); + self.operationDependencies.peerProviders = @[]; + self.suggestTLKUpload = nil; self.trustStatus = CKKSAccountStatusNoAccount; - if(!self.trustDependency) { - self.trustDependency = [CKKSResultOperation named:@"wait-for-trust" withBlock:^{}]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagEndTrustedOperation]; + }); +} + +- (BOOL)itemSyncingEnabled +{ + if(!self.operationDependencies.syncingPolicy) { + ckksnotice("ckks", self, "No syncing policy loaded; item syncing is disabled"); + return NO; + } else { + return [self.operationDependencies.syncingPolicy isSyncingEnabledForView:self.zoneName]; + } +} + +- (void)setCurrentSyncingPolicy:(TPSyncingPolicy*)syncingPolicy policyIsFresh:(BOOL)policyIsFresh +{ + dispatch_sync(self.queue, ^{ + BOOL oldEnabled = [self itemSyncingEnabled]; + + self.operationDependencies.syncingPolicy = syncingPolicy; + + BOOL enabled = [self itemSyncingEnabled]; + if(enabled != oldEnabled) { + ckksnotice("ckks", self, "Syncing for this view is now %@ (policy: %@)", enabled ? @"enabled" : @"paused", self.operationDependencies.syncingPolicy); } - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; - }]; + + if(enabled) { + CKKSResultOperation* incomingOp = [self processIncomingQueue:false after:nil policyConsideredAuthoritative:policyIsFresh]; + [self processOutgoingQueueAfter:incomingOp ckoperationGroup:nil]; + } + }); } #pragma mark - CKKSChangeFetcherClient @@ -3824,9 +2301,8 @@ { __block BOOL ready = NO; - [self dispatchSync: ^bool { + [self dispatchSyncWithReadOnlySQLTransaction:^{ ready = (bool)[self _onQueueZoneIsReadyForFetching]; - return ready; }]; return ready; @@ -3834,12 +2310,15 @@ - (BOOL)_onQueueZoneIsReadyForFetching { + dispatch_assert_queue(self.queue); if(self.accountStatus != CKKSAccountStatusAvailable) { ckksnotice("ckksfetch", self, "Not participating in fetch: not logged in"); return NO; } - if(!self.zoneCreated) { + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.operationDependencies.zoneID.zoneName]; + + if(!ckse.ckzonecreated) { ckksnotice("ckksfetch", self, "Not participating in fetch: zone not created yet"); return NO; } @@ -3850,10 +2329,10 @@ { __block CKKSCloudKitFetchRequest* request = [[CKKSCloudKitFetchRequest alloc] init]; - [self dispatchSync: ^bool { + [self dispatchSyncWithReadOnlySQLTransaction:^{ if (![self _onQueueZoneIsReadyForFetching]) { ckksnotice("ckksfetch", self, "skipping fetch since zones are not ready"); - return false; + return; } request.participateInFetch = true; @@ -3868,11 +2347,10 @@ CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName]; if(!ckse) { ckkserror("ckksfetch", self, "couldn't fetch zone change token for %@", self.zoneName); - return false; + return; } request.changeToken = ckse.changeToken; } - return true; }]; if (request.changeToken == nil) { @@ -3890,7 +2368,26 @@ { [self.launch addEvent:@"changes-fetched"]; - [self dispatchSyncWithAccountKeys:^bool{ + if(changedRecords.count == 0 && deletedRecords.count == 0 && !moreComing && !resync) { + // Early-exit, so we don't pick up the account keys or kick off an IncomingQueue operation for no changes + [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + ckksinfo("ckksfetch", self, "No record changes in this fetch"); + + NSError* error = nil; + CKKSZoneStateEntry* state = [CKKSZoneStateEntry state:self.zoneName]; + state.lastFetchTime = [NSDate date]; // The last fetch happened right now! + state.changeToken = newChangeToken; + state.moreRecordsInCloudKit = moreComing; + [state saveToDatabase:&error]; + if(error) { + ckkserror("ckksfetch", self, "Couldn't save new server change token: %@", error); + } + return CKKSDatabaseTransactionCommit; + }]; + return; + } + + [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for (CKRecord* record in changedRecords) { [self _onqueueCKRecordChanged:record resync:resync]; } @@ -3965,7 +2462,7 @@ ckksnotice("ckksfetch", self, "Finished processing changes for %@", self.zoneID); - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -3990,30 +2487,7 @@ if(isChangeTokenExpiredError) { ckkserror("ckks", self, "Received notice that our change token is out of date (for %@). Resetting local data...", self.zoneID); - // This is a bit scary: we might confuse some poor key hierarchy state machine operation. But, if a key state machine - // operation is waiting for a successful fetch, we need to do this reset - [self dispatchSyncWithAccountKeys:^bool{ - NSError* error = nil; - [self _onqueueResetLocalData:&error]; - - // We need to rescan the local keychain once we return to a good state - self.droppedItems = true; - - if(error) { - ckksnotice("ckksreset", self, "CloudKit-inspired local reset of %@ ended with error: %@", self.zoneID, error); - } else { - ckksnotice("ckksreset", self, "CloudKit-inspired local reset of %@ ended successfully", self.zoneID); - } - - // If we're in the middle of a fetch for the key state, then the retried fetch (which should succeed) will be sufficient to progress - // Otherwise, we need to poke the key hierarchy state machine: all of its data is gone - if(![self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateFetch]) { - [self _onqueueKeyStateMachineRequestFetch]; - } - - return true; - }]; - + [self.stateMachine handleFlag:CKKSFlagChangeTokenExpired]; return true; } @@ -4021,23 +2495,7 @@ if(isDeletedZoneError) { ckkserror("ckks", self, "Received notice that our zone(%@) does not exist. Resetting local data.", self.zoneID); - /* - * If someone delete our zone, lets just start over from the begining - */ - [self dispatchSync: ^bool{ - NSError* resetError = nil; - - [self _onqueueResetLocalData: &resetError]; - if(resetError) { - ckksnotice("ckksreset", self, "CloudKit-inspired local reset of %@ ended with error: %@", self.zoneID, resetError); - } else { - ckksnotice("ckksreset", self, "CloudKit-inspired local reset of %@ ended successfully", self.zoneID); - } - - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateInitializing withError:nil]; - return true; - }]; - + [self.stateMachine handleFlag:CKKSFlagCloudKitZoneMissing]; return false; } @@ -4064,27 +2522,25 @@ // The key state machine should handle that, so poke it. ckkserror("ckks", self, "Received update that the trust set has changed"); - self.trustedPeersSetChanged = true; - [self.pokeKeyStateMachineScheduler trigger]; + [self.stateMachine handleFlag:CKKSFlagTrustedPeersSetChanged]; } #pragma mark - Test Support - (bool) outgoingQueueEmpty: (NSError * __autoreleasing *) error { __block bool ret = false; - [self dispatchSync: ^bool{ + [self dispatchSyncWithReadOnlySQLTransaction:^{ NSArray* queueEntries = [CKKSOutgoingQueueEntry all: error]; ret = queueEntries && ([queueEntries count] == 0); - return true; }]; return ret; } -- (CKKSResultOperation*)waitForFetchAndIncomingQueueProcessing { - CKKSResultOperation* op = [self fetchAndProcessCKChanges:CKKSFetchBecauseTesting]; - [op waitUntilFinished]; - return op; +- (void)waitForFetchAndIncomingQueueProcessing +{ + [[self.zoneChangeFetcher inflightFetch] waitUntilFinished]; + [self waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; } - (void)waitForKeyHierarchyReadiness { @@ -4093,6 +2549,46 @@ } } +#pragma mark - NSOperation assistance + +- (void)scheduleOperation:(NSOperation*)op +{ + if(self.halted) { + ckkserror("ckkszone", self, "attempted to schedule an operation on a halted zone, ignoring"); + return; + } + + [op addNullableDependency:self.accountLoggedInDependency]; + [self.operationQueue addOperation: op]; +} + +// to be used rarely, if at all +- (bool)scheduleOperationWithoutDependencies:(NSOperation*)op +{ + if(self.halted) { + ckkserror("ckkszone", self, "attempted to schedule an non-dependent operation on a halted zone, ignoring"); + return false; + } + + [self.operationQueue addOperation: op]; + return true; +} + +- (void)waitUntilAllOperationsAreFinished +{ + [self.operationQueue waitUntilAllOperationsAreFinished]; +} + +- (void)waitForOperationsOfClass:(Class)operationClass +{ + NSArray* operations = [self.operationQueue.operations copy]; + for(NSOperation* op in operations) { + if([op isKindOfClass:operationClass]) { + [op waitUntilFinished]; + } + } +} + - (void)cancelPendingOperations { @synchronized(self.outgoingQueueOperations) { for(NSOperation* op in self.outgoingQueueOperations) { @@ -4108,30 +2604,44 @@ [self.incomingQueueOperations removeAllObjects]; } - [super cancelAllOperations]; + @synchronized(self.scanLocalItemsOperations) { + for(NSOperation* op in self.scanLocalItemsOperations) { + [op cancel]; + } + [self.scanLocalItemsOperations removeAllObjects]; + } } - (void)cancelAllOperations { - [self.zoneSetupOperation cancel]; - [self.keyStateMachineOperation cancel]; [self.keyStateReadyDependency cancel]; - [self.keyStateNonTransientDependency cancel]; - [self.zoneChangeFetcher cancel]; - [self.notifyViewChangedScheduler cancel]; + // We don't own the zoneChangeFetcher, so don't cancel it + [self.viewState.notifyViewChangedScheduler cancel]; [self cancelPendingOperations]; - - [self dispatchSync:^bool{ - [self _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateCancelled withError: nil]; - return true; - }]; + [self.operationQueue cancelAllOperations]; } - (void)halt { - [super halt]; + [self.stateMachine haltOperation]; + + // Synchronously set the 'halted' bit + dispatch_sync(self.queue, ^{ + self.halted = true; + }); + + // Bring all operations down, too + [self cancelAllOperations]; + + // And now, wait for all operations that are running + for(NSOperation* op in self.operationQueue.operations) { + if(op.isExecuting) { + [op waitUntilFinished]; + } + } // Don't send any more notifications, either - _notifierClass = nil; + [self.viewState.notifyViewChangedScheduler cancel]; + [self.viewState.notifyViewReadyScheduler cancel]; } - (NSDictionary*)status { @@ -4139,20 +2649,15 @@ #define boolstr(obj) (!!(obj) ? @"yes" : @"no") __block NSMutableDictionary* ret = nil; __block NSError* error = nil; - CKKSManifest* manifest = nil; ret = [[self fastStatus] mutableCopy]; - manifest = [CKKSManifest latestTrustedManifestForZone:self.zoneName error:&error]; - [self dispatchSync: ^bool { - + [self dispatchSyncWithReadOnlySQLTransaction:^{ CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; if(keyset.error) { error = keyset.error; } - NSString* manifestGeneration = manifest ? [NSString stringWithFormat:@"%lu", (unsigned long)manifest.generationCount] : nil; - if(error) { ckkserror("ckks", self, "error during status: %@", error); } @@ -4186,9 +2691,8 @@ @"currentTLKPtr": CKKSNilToNSNull(keyset.currentTLKPointer.currentKeyUUID), @"currentClassAPtr": CKKSNilToNSNull(keyset.currentClassAPointer.currentKeyUUID), @"currentClassCPtr": CKKSNilToNSNull(keyset.currentClassCPointer.currentKeyUUID), - @"currentManifestGen": CKKSNilToNSNull(manifestGeneration), + @"itemsyncing": self.itemSyncingEnabled ? @"enabled" : @"paused", }]; - return false; }]; return ret; } @@ -4197,7 +2701,8 @@ __block NSDictionary* ret = nil; - [self dispatchSync: ^bool { + [self dispatchSyncWithReadOnlySQLTransaction:^{ + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName]; ret = @{ @"view": CKKSNilToNSNull(self.zoneName), @@ -4207,25 +2712,18 @@ self.accountStatus == CKAccountStatusNoAccount ? @"logged out" : @"unknown", @"accounttracker": stringify(self.accountTracker), @"fetcher": stringify(self.zoneChangeFetcher), - @"zoneCreated": boolstr(self.zoneCreated), - @"zoneCreatedError": stringify(self.zoneCreatedError), - @"zoneSubscribed": boolstr(self.zoneSubscribed), - @"zoneSubscribedError": stringify(self.zoneSubscribedError), + @"zoneCreated": boolstr(ckse.ckzonecreated), + @"zoneSubscribed": boolstr(ckse.ckzonesubscribed), @"keystate": CKKSNilToNSNull(self.keyHierarchyState), - @"keyStateError": stringify(self.keyHierarchyError), @"statusError": [NSNull null], @"launchSequence": CKKSNilToNSNull([self.launch eventsByTime]), - @"zoneSetupOperation": stringify(self.zoneSetupOperation), - @"keyStateOperation": stringify(self.keyStateMachineOperation), @"lastIncomingQueueOperation": stringify(self.lastIncomingQueueOperation), @"lastNewTLKOperation": stringify(self.lastNewTLKOperation), @"lastOutgoingQueueOperation": stringify(self.lastOutgoingQueueOperation), @"lastProcessReceivedKeysOperation": stringify(self.lastProcessReceivedKeysOperation), @"lastReencryptOutgoingItemsOperation":stringify(self.lastReencryptOutgoingItemsOperation), - @"lastScanLocalItemsOperation": stringify(self.lastScanLocalItemsOperation), }; - return false; }]; return ret; diff --git a/keychain/ckks/CKKSKeychainViewState.h b/keychain/ckks/CKKSKeychainViewState.h new file mode 100644 index 00000000..0f0eb077 --- /dev/null +++ b/keychain/ckks/CKKSKeychainViewState.h @@ -0,0 +1,34 @@ + +#if OCTAGON + +#import +#import + +#import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSNearFutureScheduler.h" +#import "keychain/ot/OctagonStateMachine.h" + +NS_ASSUME_NONNULL_BEGIN +@class OctagonStateMachine; + +@interface CKKSKeychainViewState : NSObject +@property (readonly) NSString* zoneName; +@property (readonly) CKRecordZoneID* zoneID; + +@property (readonly) CKKSZoneKeyState* zoneCKKSState; + +/* Trigger this to tell the whole machine that this view has changed */ +@property CKKSNearFutureScheduler* notifyViewChangedScheduler; + +/* Trigger this to tell the whole machine that this view is more ready then before */ +@property CKKSNearFutureScheduler* notifyViewReadyScheduler; + +- (instancetype)initWithZoneID:(CKRecordZoneID*)zoneID + viewStateMachine:(OctagonStateMachine*)stateMachine + notifyViewChangedScheduler:(CKKSNearFutureScheduler*)notifyViewChangedScheduler + notifyViewReadyScheduler:(CKKSNearFutureScheduler*)notifyViewReadyScheduler; +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/keychain/ckks/CKKSKeychainViewState.m b/keychain/ckks/CKKSKeychainViewState.m new file mode 100644 index 00000000..c5b814d0 --- /dev/null +++ b/keychain/ckks/CKKSKeychainViewState.m @@ -0,0 +1,36 @@ + +#if OCTAGON + +#import "keychain/ckks/CKKSKeychainViewState.h" + +@interface CKKSKeychainViewState () +@property OctagonStateMachine* zoneStateMachine; +@end + +@implementation CKKSKeychainViewState + +- (instancetype)initWithZoneID:(CKRecordZoneID*)zoneID + viewStateMachine:(OctagonStateMachine*)stateMachine + notifyViewChangedScheduler:(CKKSNearFutureScheduler*)notifyViewChangedScheduler + notifyViewReadyScheduler:(CKKSNearFutureScheduler*)notifyViewReadyScheduler +{ + if((self = [super init])) { + _zoneName = zoneID.zoneName; + _zoneID = zoneID; + + _zoneStateMachine = stateMachine; + + _notifyViewChangedScheduler = notifyViewChangedScheduler; + _notifyViewReadyScheduler = notifyViewReadyScheduler; + } + return self; +} + +- (CKKSZoneKeyState*)zoneCKKSState +{ + return self.zoneStateMachine.currentState; +} + +@end + +#endif diff --git a/keychain/ckks/CKKSLocalResetOperation.h b/keychain/ckks/CKKSLocalResetOperation.h new file mode 100644 index 00000000..def140d4 --- /dev/null +++ b/keychain/ckks/CKKSLocalResetOperation.h @@ -0,0 +1,26 @@ + +#import + +#if OCTAGON + +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSOperationDependencies.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSLocalResetOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +// Used to run a local reset without scheduling its surrounding operation. +// Please be on a SQL transaction when you run this. +- (void)onqueuePerformLocalReset; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSLocalResetOperation.m b/keychain/ckks/CKKSLocalResetOperation.m new file mode 100644 index 00000000..f9660258 --- /dev/null +++ b/keychain/ckks/CKKSLocalResetOperation.m @@ -0,0 +1,126 @@ + +#if OCTAGON + +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKSLocalResetOperation.h" +#import "keychain/ckks/CKKSZoneStateEntry.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSCurrentItemPointer.h" +#import "keychain/ckks/CKKSMirrorEntry.h" +#import "keychain/ot/OTDefines.h" + +@implementation CKKSLocalResetOperation + +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if(self = [super init]) { + _deps = dependencies; + + _intendedState = intendedState; + _nextState = errorState; + + self.name = @"ckks-local-reset"; + } + return self; +} + +- (void)main { + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult { + [self onqueuePerformLocalReset]; + return CKKSDatabaseTransactionCommit; + }]; +} + +- (void)onqueuePerformLocalReset +{ + NSError* localerror = nil; + + for(CKKSKeychainViewState* view in self.deps.zones) { + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:view.zoneID.zoneName]; + ckse.ckzonecreated = false; + ckse.ckzonesubscribed = false; // I'm actually not sure about this: can you be subscribed to a non-existent zone? + ckse.changeToken = NULL; + [ckse saveToDatabase:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", view.zoneID, "couldn't reset zone status: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSMirrorEntry deleteAll:view.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", view.zoneID, "couldn't delete all CKKSMirrorEntry: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSOutgoingQueueEntry deleteAll:view.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", view.zoneID, "couldn't delete all CKKSOutgoingQueueEntry: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSIncomingQueueEntry deleteAll:view.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", view.zoneID, "couldn't delete all CKKSIncomingQueueEntry: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSKey deleteAll:view.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", view.zoneID, "couldn't delete all CKKSKey: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSTLKShareRecord deleteAll:view.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", view.zoneID, "couldn't delete all CKKSTLKShare: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSCurrentKeyPointer deleteAll:view.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", view.zoneID, "couldn't delete all CKKSCurrentKeyPointer: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSCurrentItemPointer deleteAll:view.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", view.zoneID, "couldn't delete all CKKSCurrentItemPointer: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSDeviceStateEntry deleteAll:view.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", view.zoneID, "couldn't delete all CKKSDeviceStateEntry: %@", localerror); + self.error = localerror; + localerror = nil; + } + + if(self.error) { + break; + } + } + + if(!self.error) { + ckksnotice_global("local-reset", "Successfully deleted all local data for zones: %@", self.deps.zones); + self.nextState = self.intendedState; + } +} + +@end + +#endif // OCTAGON + diff --git a/keychain/ckks/CKKSLocalSynchronizeOperation.m b/keychain/ckks/CKKSLocalSynchronizeOperation.m index fe5c09d0..abf9aa2d 100644 --- a/keychain/ckks/CKKSLocalSynchronizeOperation.m +++ b/keychain/ckks/CKKSLocalSynchronizeOperation.m @@ -74,10 +74,10 @@ CKKSKeychainView* ckks = self.ckks; // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. - [ckks dispatchSync: ^bool{ + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckksresync", ckks, "CKKSSynchronizeOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } //ckks.lastLocalSynchronizeOperation = self; @@ -94,7 +94,12 @@ [self dependOnBeforeGroupFinished:outgoingOp]; // Step 2 - CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:ckks errorOnClassAFailure:true]; + CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithDependencies:ckks.operationDependencies + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy + errorOnClassAFailure:true + handleMismatchedViewItems:false]; + incomingOp.name = [NSString stringWithFormat: @"resync-step%u-incoming", self.restartCount * steps + 2]; [incomingOp addSuccessDependency:outgoingOp]; [self runBeforeGroupFinished:incomingOp]; @@ -105,13 +110,22 @@ [self runBeforeGroupFinished:reloadOp]; // Step 4 - CKKSIncomingQueueOperation* incomingResyncOp = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:ckks errorOnClassAFailure:true]; + CKKSIncomingQueueOperation* incomingResyncOp = [[CKKSIncomingQueueOperation alloc] initWithDependencies:ckks.operationDependencies + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy + errorOnClassAFailure:true + handleMismatchedViewItems:false]; + incomingResyncOp.name = [NSString stringWithFormat: @"resync-step%u-incoming-again", self.restartCount * steps + 4]; [incomingResyncOp addSuccessDependency: reloadOp]; [self runBeforeGroupFinished:incomingResyncOp]; // Step 5 - CKKSScanLocalItemsOperation* scan = [[CKKSScanLocalItemsOperation alloc] initWithCKKSKeychainView:ckks ckoperationGroup:operationGroup]; + CKKSScanLocalItemsOperation* scan = [[CKKSScanLocalItemsOperation alloc] initWithDependencies:ckks.operationDependencies + ckks:ckks + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError + ckoperationGroup:operationGroup]; scan.name = [NSString stringWithFormat: @"resync-step%u-scan", self.restartCount * steps + 5]; [scan addSuccessDependency: incomingResyncOp]; [self runBeforeGroupFinished: scan]; @@ -122,7 +136,7 @@ [restart addExecutionBlock:^{ STRONGIFY(self); if(!self) { - secerror("ckksresync: received callback for released object"); + ckkserror("ckksresync", ckks, "received callback for released object"); return; } @@ -151,7 +165,7 @@ [restart addSuccessDependency: scan]; [self runBeforeGroupFinished: restart]; - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -175,14 +189,14 @@ - (void)main { CKKSKeychainView* strongCKKS = self.ckks; - [strongCKKS dispatchSync: ^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; NSArray* mirrorItems = [CKKSMirrorEntry all:strongCKKS.zoneID error:&error]; if(error) { ckkserror("ckksresync", strongCKKS, "Couldn't fetch mirror items: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } // Reload all entries back into the local keychain @@ -198,7 +212,7 @@ [strongCKKS _onqueueCKRecordChanged:ckmeRecord resync:true]; } - return true; + return CKKSDatabaseTransactionCommit; }]; } @end diff --git a/keychain/ckks/CKKSLockStateTracker.h b/keychain/ckks/CKKSLockStateTracker.h index 7e64f2f5..2bf9d0be 100644 --- a/keychain/ckks/CKKSLockStateTracker.h +++ b/keychain/ckks/CKKSLockStateTracker.h @@ -24,6 +24,7 @@ #if OCTAGON #import +#import @protocol CKKSLockStateNotification - (void)lockStateChangeNotification:(bool)unlocked; @@ -31,13 +32,20 @@ NS_ASSUME_NONNULL_BEGIN +@protocol CKKSLockStateProviderProtocol +- (BOOL)queryAKSLocked; +@end + @interface CKKSLockStateTracker : NSObject @property (nullable) NSOperation* unlockDependency; @property (readonly) bool isLocked; @property (readonly,nullable) NSDate* lastUnlockTime; -- (instancetype)init; +@property id lockStateProvider; + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithProvider:(id)provider; // Force a recheck of the keybag lock state - (void)recheck; @@ -45,14 +53,15 @@ NS_ASSUME_NONNULL_BEGIN // Check if this error code is related to keybag is locked and we should retry later - (bool)isLockedError:(NSError*)error; --(void)addLockStateObserver:(id)object; - -// Ask AKS if the user's keybag is locked -+ (bool)queryAKSLocked; +- (void)addLockStateObserver:(id)object; // Call this to get a CKKSLockStateTracker to use. This tracker will likely be tracking real AKS. + (CKKSLockStateTracker*)globalTracker; @end +@interface CKKSActualLockStateProvider : NSObject +- (instancetype)init; +@end + NS_ASSUME_NONNULL_END #endif // OCTAGON diff --git a/keychain/ckks/CKKSLockStateTracker.m b/keychain/ckks/CKKSLockStateTracker.m index 46e6cb2a..8383880a 100644 --- a/keychain/ckks/CKKSLockStateTracker.m +++ b/keychain/ckks/CKKSLockStateTracker.m @@ -46,8 +46,11 @@ @implementation CKKSLockStateTracker -- (instancetype)init { +- (instancetype)initWithProvider:(id)provider +{ if((self = [super init])) { + _lockStateProvider = provider; + _queue = dispatch_queue_create("lock-state-tracker", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); _operationQueue = [[NSOperationQueue alloc] init]; @@ -113,31 +116,19 @@ -(void)resetUnlockDependency { if(self.unlockDependency == nil || ![self.unlockDependency isPending]) { CKKSResultOperation* op = [CKKSResultOperation named:@"keybag-unlocked-dependency" withBlock: ^{ - secinfo("ckks", "Keybag unlocked"); + ckksinfo_global("ckks", "Keybag unlocked"); }]; op.descriptionErrorCode = CKKSResultDescriptionPendingUnlock; self.unlockDependency = op; } } -+(bool)queryAKSLocked { - CFErrorRef aksError = NULL; - bool locked = true; - - if(!SecAKSGetIsLocked(&locked, &aksError)) { - secerror("ckks: error querying lock state: %@", aksError); - CFReleaseNull(aksError); - } - - return locked; -} - -(void)_onqueueRecheck { dispatch_assert_queue(self.queue); static bool first = true; bool wasLocked = self.queueIsLocked; - self.queueIsLocked = [CKKSLockStateTracker queryAKSLocked]; + self.queueIsLocked = [self.lockStateProvider queryAKSLocked]; if(wasLocked != self.queueIsLocked || first) { first = false; @@ -173,9 +164,28 @@ }); } --(bool)isLockedError:(NSError *)error { +- (bool)lockedError:(NSError *)error +{ bool isLockedError = error.code == errSecInteractionNotAllowed && ([error.domain isEqualToString:@"securityd"] || [error.domain isEqualToString:(__bridge NSString*)kSecErrorDomain]); + return isLockedError; +} + +- (bool)checkErrorChainForLockState:(NSError*)error +{ + while(error != nil) { + if([self lockedError:error]) { + return true; + } + + error = error.userInfo[NSUnderlyingErrorKey]; + } + + return false; +} + +-(bool)isLockedError:(NSError *)error { + bool isLockedError = [self checkErrorChainForLockState:error]; /* * If we are locked, and the the current lock state track disagree, lets double check @@ -210,7 +220,7 @@ static CKKSLockStateTracker* tracker; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - tracker = [[CKKSLockStateTracker alloc] init]; + tracker = [[CKKSLockStateTracker alloc] initWithProvider:[[CKKSActualLockStateProvider alloc] init]]; }); return tracker; } @@ -218,4 +228,24 @@ @end +@implementation CKKSActualLockStateProvider +- (instancetype)init { + if((self = [super init])) { + } + return self; +} + +- (BOOL)queryAKSLocked { + CFErrorRef aksError = NULL; + bool locked = true; + + if(!SecAKSGetIsLocked(&locked, &aksError)) { + ckkserror_global("ckks", "error querying lock state: %@", aksError); + CFReleaseNull(aksError); + } + + return locked ? YES : NO; +} +@end + #endif // OCTAGON diff --git a/keychain/ckks/CKKSLogging.m b/keychain/ckks/CKKSLogging.m new file mode 100644 index 00000000..4971f413 --- /dev/null +++ b/keychain/ckks/CKKSLogging.m @@ -0,0 +1,33 @@ + +#import +#import "keychain/ckks/CKKS.h" + +os_log_t CKKSLogObject(NSString* scope, NSString* _Nullable zoneName) +{ + __block os_log_t ret = OS_LOG_DISABLED; + + static dispatch_queue_t logQueue = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + logQueue = dispatch_queue_create("ckks-logger", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + }); + + static NSMutableDictionary* scopeMap = nil; + + dispatch_sync(logQueue, ^{ + if(scopeMap == nil) { + scopeMap = [NSMutableDictionary dictionary]; + } + + NSString* key = zoneName ? [scope stringByAppendingFormat:@"-%@", zoneName] : scope; + + ret = scopeMap[key]; + + if(!ret) { + ret = os_log_create("com.apple.security.ckks", [key cStringUsingEncoding:NSUTF8StringEncoding]); + scopeMap[key] = ret; + } + }); + + return ret; +} diff --git a/keychain/ckks/CKKSManifest.h b/keychain/ckks/CKKSManifest.h index 139614b6..db6c0b86 100644 --- a/keychain/ckks/CKKSManifest.h +++ b/keychain/ckks/CKKSManifest.h @@ -63,6 +63,8 @@ extern NSString* const CKKSManifestGenCountKey; - (BOOL)itemUUIDExistsInManifest:(NSString*)uuid; - (BOOL)contentsAreEqualToManifest:(CKKSManifest*)otherManifest; ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error; + @end @interface CKKSPendingManifest : CKKSManifest @@ -71,6 +73,8 @@ extern NSString* const CKKSManifestGenCountKey; - (nullable CKKSManifest*)commitToDatabaseWithError:(NSError**)error; ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error; + @end @interface CKKSEgoManifest : CKKSManifest diff --git a/keychain/ckks/CKKSManifest.m b/keychain/ckks/CKKSManifest.m index 0d7f5562..beed1ed0 100644 --- a/keychain/ckks/CKKSManifest.m +++ b/keychain/ckks/CKKSManifest.m @@ -286,7 +286,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) [[CKKSEgoManifest egoHelper] performWithSigningKey:^(SFECKeyPair* signingKey, NSError* error) { accountInfo.signingKey = signingKey; if(error) { - secerror("ckksmanifest: cannot get signing key from account: %@", error); + ckkserror_global("ckksmanifest", "cannot get signing key from account: %@", error); if(accountInfo.setupError == nil) { accountInfo.setupError = error; } @@ -297,7 +297,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) accountInfo.egoPeerID = egoPeerID; if(error) { - secerror("ckksmanifest: cannot get ego peer ID from account: %@", error); + ckkserror_global("ckksmanifest", "cannot get ego peer ID from account: %@", error); if(accountInfo.setupError == nil) { accountInfo.setupError = error; } @@ -307,7 +307,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) [[CKKSEgoManifest egoHelper] performWithPeerVerifyingKeys:^(NSDictionary* peerKeys, NSError* error) { accountInfo.peerVerifyingKeys = peerKeys; if(error) { - secerror("ckksmanifest: cannot get peer keys from account: %@", error); + ckkserror_global("ckksmanifest", "cannot get peer keys from account: %@", error); if(accountInfo.setupError == nil) { accountInfo.setupError = error; } @@ -471,11 +471,11 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) - (instancetype)initWithDigestValue:(NSData*)digestValue zone:(NSString*)zone generationCount:(NSUInteger)generationCount leafRecordIDs:(NSArray*)leafRecordIDs peerManifestIDs:(NSArray*)peerManifestIDs currentItems:(NSDictionary*)currentItems futureData:(NSDictionary*)futureData signatures:(NSDictionary*)signatures signerID:(NSString*)signerID schema:(NSDictionary*)schema helper:(CKKSManifestInjectionPointHelper*)helper { if ([zone containsString:manifestRecordNameDelimiter]) { - secerror("zone contains delimiter: %@", zone); + ckkserror_global("ckksmanifest", "zone contains delimiter: %@", zone); return nil; } if ([signerID containsString:manifestRecordNameDelimiter]) { - secerror("signerID contains delimiter: %@", signerID); + ckkserror_global("ckksmanifest", "signerID contains delimiter: %@", signerID); return nil; } @@ -687,7 +687,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) void (^addValueSafelyToDictionaryAndLogIfNil)(NSMutableDictionary*, NSString*, id) = ^(NSMutableDictionary* dictionary, NSString* key, id value) { if (!value) { value = [NSNull null]; - secerror("CKKSManifest: saving manifest to database but %@ is nil", key); + ckkserror_global("ckksmanifest", "saving manifest to database but %@ is nil", key); } dictionary[key] = value; @@ -728,7 +728,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) { NSArray* components = [recordName componentsSeparatedByString:manifestRecordNameDelimiter]; if (components.count < 4) { - secerror("CKKSManifest: could not parse components from record name: %@", recordName); + ckkserror_global("ckksmanifest", "could not parse components from record name: %@", recordName); } return @{ @"ckzone" : components[1], @@ -948,6 +948,25 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) _schema = nil; } ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error +{ + NSError* localerror = nil; + + ckksinfo("ckksmanifest", recordID.zoneID, "CloudKit notification: deleted manifest record (%@): %@", SecCKRecordManifestType, recordID); + + CKKSManifest* manifest = [CKKSManifest manifestForRecordName:recordID.recordName error:&localerror]; + if (manifest) { + [manifest deleteFromDatabase:&localerror]; + } + + ckksinfo("ckksmanifest", recordID.zoneID, "CKKSManifest was deleted: %@ %@ error: %@", recordID, manifest, localerror); + if(error && localerror) { + *error = localerror; + } + + return localerror == nil; +} + @end @implementation CKKSPendingManifest @@ -1017,6 +1036,23 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) } } + ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error +{ + NSError* localerror = nil; + CKKSPendingManifest* manifest = [[CKKSPendingManifest alloc] initWithCKRecord:record]; + bool saved = [manifest saveToDatabase:&localerror]; + if (!saved || localerror != nil) { + ckkserror("ckksmanifest", record.recordID.zoneID, "Failed to save fetched manifest record to database: %@: %@", manifest, localerror); + ckksinfo("ckksmanifest", record.recordID.zoneID, "manifest CKRecord was %@", record); + if(error) { + *error = localerror; + } + return NO; + } + return YES; +} + @end @implementation CKKSEgoManifest @@ -1145,7 +1181,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) if (leafRecord) { [leafRecords addObject:leafRecord]; } else { - secerror("ckksmanifest: error loading leaf record from database: %@", error ? *error : nil); + ckkserror_global("ckksmanifest", "error loading leaf record from database: %@", error ? *error : nil); return false; } } diff --git a/keychain/ckks/CKKSManifestLeafRecord.h b/keychain/ckks/CKKSManifestLeafRecord.h index 4a10f75f..5fb94f33 100644 --- a/keychain/ckks/CKKSManifestLeafRecord.h +++ b/keychain/ckks/CKKSManifestLeafRecord.h @@ -48,6 +48,8 @@ NS_ASSUME_NONNULL_BEGIN - (nullable CKKSManifestLeafRecord*)commitToDatabaseWithError:(NSError**)error; ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error; + @end @interface CKKSEgoManifestLeafRecord : CKKSManifestLeafRecord diff --git a/keychain/ckks/CKKSManifestLeafRecord.m b/keychain/ckks/CKKSManifestLeafRecord.m index a35b519b..87ba8193 100644 --- a/keychain/ckks/CKKSManifestLeafRecord.m +++ b/keychain/ckks/CKKSManifestLeafRecord.m @@ -137,7 +137,7 @@ static NSDictionary* RecordDigestDictFromDER(NSData* data, NSError** error) NSData* derData = [[NSData alloc] initWithBase64EncodedString:record[SecCKRecordManifestLeafDERKey] options:0]; NSDictionary* recordDigestDict = RecordDigestDictFromDER(derData, &error); if (!recordDigestDict) { - secerror("failed to decode manifest leaf node DER with error: %@", error); + ckkserror_global("ckksmanifest", "failed to decode manifest leaf node DER with error: %@", error); return nil; } @@ -148,7 +148,7 @@ static NSDictionary* RecordDigestDictFromDER(NSData* data, NSError** error) - (instancetype)initWithUUID:(NSString*)uuid digest:(NSData*)digest recordDigestDict:(NSDictionary*)recordDigestDict zone:(NSString*)zone { if ([uuid containsString:manifestLeafRecordNameDelimiter]) { - secerror("uuid contains delimiter: %@", uuid); + ckkserror_global("ckksmanifest", "uuid contains delimiter: %@", uuid); return nil; } @@ -176,7 +176,7 @@ static NSDictionary* RecordDigestDictFromDER(NSData* data, NSError** error) void (^addValueSafelyToDictionaryAndLogIfNil)(NSMutableDictionary*, NSString*, id) = ^(NSMutableDictionary* dictionary, NSString* key, id value) { if (!value) { value = [NSNull null]; - secerror("CKKSManifestLeafRecord: saving manifest leaf record to database but %@ is nil", key); + ckkserror_global("ckksmanifest", "CKKSManifestLeafRecord: saving manifest leaf record to database but %@ is nil", key); } dictionary[key] = value; @@ -222,7 +222,7 @@ static NSDictionary* RecordDigestDictFromDER(NSData* data, NSError** error) NSData* derData = [[NSData alloc] initWithBase64EncodedString:record[SecCKRecordManifestLeafDERKey] options:0]; NSDictionary* recordDigestDict = RecordDigestDictFromDER(derData, &error); if (!recordDigestDict || error) { - secerror("failed to decode manifest leaf node DER with error: %@", error); + ckkserror_global("ckksmanifest", "failed to decode manifest leaf node DER with error: %@", error); return; } @@ -289,6 +289,23 @@ static NSDictionary* RecordDigestDictFromDER(NSData* data, NSError** error) } } ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error +{ + NSError* localerror = nil; + CKKSManifestLeafRecord* manifestLeaf = [[CKKSManifestPendingLeafRecord alloc] initWithCKRecord:record]; + bool saved = [manifestLeaf saveToDatabase:&localerror]; + if (!saved || localerror != nil) { + ckkserror("ckksmanifest", record.recordID.zoneID, "Failed to save fetched manifest leaf record to database: %@: %@", manifestLeaf, localerror); + ckksinfo("ckksmanifest", record.recordID.zoneID, "manifest leaf CKRecord was %@", record); + if(error) { + *error = localerror; + } + return NO; + } + + return YES; +} + @end @implementation CKKSEgoManifestLeafRecord diff --git a/keychain/ckks/CKKSMemoryKeyCache.h b/keychain/ckks/CKKSMemoryKeyCache.h new file mode 100644 index 00000000..fff7a902 --- /dev/null +++ b/keychain/ckks/CKKSMemoryKeyCache.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import + +#import "keychain/ckks/CKKSKey.h" + +#if OCTAGON + +NS_ASSUME_NONNULL_BEGIN + +// +// Usage Note: +// +// This object transparently caches CKKSKey objects, with their key material +// intact. Since those keys are loaded from the database, they remain +// valid while you're in the database transaction where you loaded them. +// To preverve this property, this cache must be destroyed before the end +// of the database transaction in which it is created. +// + +@interface CKKSMemoryKeyCache : NSObject + +// An instance of a CKKSItemEncrypter also contains a cache of (loaded and ready) CKKSKeys +// Use these to access the cache +- (instancetype)init; +- (CKKSKey* _Nullable)loadKeyForUUID:(NSString*)keyUUID + zoneID:(CKRecordZoneID*)zoneID + error:(NSError**)error; +- (CKKSKey* _Nullable)currentKeyForClass:(CKKSKeyClass*)keyclass + zoneID:(CKRecordZoneID*)zoneID + error:(NSError *__autoreleasing*)error; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/keychain/ckks/CKKSMemoryKeyCache.m b/keychain/ckks/CKKSMemoryKeyCache.m new file mode 100644 index 00000000..89d8de74 --- /dev/null +++ b/keychain/ckks/CKKSMemoryKeyCache.m @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import + +#import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSMemoryKeyCache.h" +#import "keychain/ckks/CKKSCurrentKeyPointer.h" + +#if OCTAGON + +@interface CKKSMemoryKeyCache () +@property NSMutableDictionary* keyCache; +@end + +@implementation CKKSMemoryKeyCache + +- (instancetype)init +{ + if((self = [super init])) { + _keyCache = [NSMutableDictionary dictionary]; + } + return self; +} + +- (CKKSKey* _Nullable)loadKeyForUUID:(NSString*)keyUUID zoneID:(CKRecordZoneID*)zoneID error:(NSError**)error +{ + CKKSKey* key = self.keyCache[keyUUID]; + if(key) { + return key; + } + + // Note: returns nil (and empties the cache) if there is an error + key = [CKKSKey loadKeyWithUUID:keyUUID zoneID:zoneID error:error]; + self.keyCache[keyUUID] = key; + return key; +} + +- (CKKSKey* _Nullable)loadKeyForItem:(CKKSItem*)item error:(NSError**)error +{ + return [self loadKeyForUUID:item.parentKeyUUID zoneID:item.zoneID error:error]; +} + +- (CKKSKey* _Nullable)currentKeyForClass:(CKKSKeyClass*)keyclass + zoneID:(CKRecordZoneID*)zoneID + error:(NSError *__autoreleasing*)error +{ + // Load the CurrentKey record, and find the key for it + CKKSCurrentKeyPointer* ckp = [CKKSCurrentKeyPointer fromDatabase:keyclass zoneID:zoneID error:error]; + if(!ckp) { + return nil; + } + return [self loadKeyForUUID:ckp.currentKeyUUID zoneID:zoneID error:error]; +} + +@end + +#endif diff --git a/keychain/ckks/CKKSMirrorEntry.h b/keychain/ckks/CKKSMirrorEntry.h index 17839f25..7faf2556 100644 --- a/keychain/ckks/CKKSMirrorEntry.h +++ b/keychain/ckks/CKKSMirrorEntry.h @@ -53,7 +53,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)tryFromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (NSDictionary*)countsByParentKey:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; -+ (NSNumber*)counts:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error; ++ (NSNumber* _Nullable)counts:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error; @end diff --git a/keychain/ckks/CKKSMirrorEntry.m b/keychain/ckks/CKKSMirrorEntry.m index 59900f08..bf7e17f0 100644 --- a/keychain/ckks/CKKSMirrorEntry.m +++ b/keychain/ckks/CKKSMirrorEntry.m @@ -78,7 +78,7 @@ // Why is obj-c nullable equality so difficult? if(!((record[SecCKRecordServerWasCurrent] == nil && self.wasCurrent == 0) || [record[SecCKRecordServerWasCurrent] isEqual: [NSNumber numberWithUnsignedLongLong:self.wasCurrent]])) { - secinfo("ckksitem", "was_current does not match"); + ckksinfo_global("ckksitem", "was_current does not match"); matches = false; } } @@ -149,7 +149,7 @@ return results; } -+ (NSNumber*)counts:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { ++ (NSNumber* _Nullable)counts:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { __block NSNumber *result = nil; [CKKSSQLDatabaseObject queryDatabaseTable: [[self class] sqlTable] @@ -163,7 +163,6 @@ } error: error]; return result; - } diff --git a/keychain/ckks/CKKSNewTLKOperation.h b/keychain/ckks/CKKSNewTLKOperation.h index fb831ffe..562ff05c 100644 --- a/keychain/ckks/CKKSNewTLKOperation.h +++ b/keychain/ckks/CKKSNewTLKOperation.h @@ -26,16 +26,21 @@ #import #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ckks/CKKSProvideKeySetOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachine.h" NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@interface CKKSNewTLKOperation : CKKSGroupOperation +@interface CKKSNewTLKOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks; @end diff --git a/keychain/ckks/CKKSNewTLKOperation.m b/keychain/ckks/CKKSNewTLKOperation.m index 2cc46843..6f39b601 100644 --- a/keychain/ckks/CKKSNewTLKOperation.m +++ b/keychain/ckks/CKKSNewTLKOperation.m @@ -27,6 +27,7 @@ #import "CKKSNewTLKOperation.h" #import "CKKSGroupOperation.h" #import "CKKSNearFutureScheduler.h" +#import "keychain/ckks/CKKSStates.h" #import "keychain/ckks/CloudKitCategories.h" #import "keychain/categories/NSError+UsefulConstructors.h" @@ -35,22 +36,26 @@ #import "keychain/ckks/CKKSTLKShareRecord.h" @interface CKKSNewTLKOperation () -@property NSBlockOperation* cloudkitModifyOperationFinished; -@property CKOperationGroup* ckoperationGroup; - @property (nullable) CKKSCurrentKeySet* keyset; @end @implementation CKKSNewTLKOperation +@synthesize intendedState = _intendedState; +@synthesize nextState = _nextState; @synthesize keyset; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks +{ if(self = [super init]) { + _deps = dependencies; _ckks = ckks; - _ckoperationGroup = ckoperationGroup; + + _nextState = SecCKKSZoneKeyStateError; + _intendedState = SecCKKSZoneKeyStateWaitForTLKUpload; } return self; } @@ -82,11 +87,13 @@ return; } + NSArray* currentTrustStates = self.deps.currentTrustStates; + // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. - [ckks dispatchSyncWithAccountKeys: ^bool{ + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckkstlk", ckks, "CKKSNewTLKOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } ckks.lastNewTLKOperation = self; @@ -117,9 +124,16 @@ ckksnotice("ckkstlk", ckks, "Old TLK is: %@ %@", oldTLK, error); if(error != nil) { - ckkserror("ckkstlk", ckks, "Couldn't fetch and unwrap old TLK: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + if([self.deps.lockStateTracker isLockedError:error]) { + ckkserror("ckkstlk", self.deps.zoneID, "Couldn't fetch and unwrap old TLK due to lock state. Entering a waiting state; %@", error); + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckkserror("ckkstlk", self.deps.zoneID, "Couldn't fetch and unwrap old TLK: %@", error); + self.nextState = SecCKKSZoneKeyStateError; + } + self.error = error; + return CKKSDatabaseTransactionRollback; } // Generate new hierarchy: @@ -132,9 +146,9 @@ CKKSAESSIVKey* newAESKey = [CKKSAESSIVKey randomKey:&error]; if(error) { ckkserror("ckkstlk", ckks, "Couldn't create new TLK: %@", error); + self.nextState = SecCKKSZoneKeyStateError; self.error = error; - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return false; + return CKKSDatabaseTransactionRollback; } newTLK = [[CKKSKey alloc] initSelfWrappedWithAESKey:newAESKey uuid:[[NSUUID UUID] UUIDString] @@ -150,8 +164,9 @@ if(error != nil) { ckkserror("ckkstlk", ckks, "couldn't make new key hierarchy: %@", error); // TODO: this really isn't the error state, but a 'retry'. - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + self.error = error; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionRollback; } CKKSCurrentKeyPointer* currentTLKPointer = [CKKSCurrentKeyPointer forKeyClass: SecCKKSKeyClassTLK withKeyUUID:newTLK.uuid zoneID:ckks.zoneID error: &error]; @@ -161,8 +176,9 @@ if(error != nil) { ckkserror("ckkstlk", ckks, "couldn't make current key records: %@", error); // TODO: this really isn't the error state, but a 'retry'. - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + self.nextState = SecCKKSZoneKeyStateError; + self.error = error; + return CKKSDatabaseTransactionRollback; } // Wrap old TLK under the new TLK @@ -170,23 +186,32 @@ if(wrappedOldTLK) { [wrappedOldTLK ensureKeyLoaded: &error]; if(error != nil) { - ckkserror("ckkstlk", ckks, "couldn't unwrap TLK, aborting new TLK operation: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + if([self.deps.lockStateTracker isLockedError:error]) { + ckkserror("ckkstlk", self.deps.zoneID, "Couldn't unwrap TLK due to lock state. Entering a waiting state; %@", error); + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckkserror("ckkstlk", self.deps.zoneID, "couldn't unwrap TLK, aborting new TLK operation: %@", error); + self.nextState = SecCKKSZoneKeyStateError; + } + self.error = error; + return CKKSDatabaseTransactionRollback; } [wrappedOldTLK wrapUnder: newTLK error:&error]; // TODO: should we continue in this error state? Might be required to fix broken TLKs/argue over which TLK should be used if(error != nil) { ckkserror("ckkstlk", ckks, "couldn't wrap oldTLK, aborting new TLK operation: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + self.nextState = SecCKKSZoneKeyStateError; + self.error = error; + return CKKSDatabaseTransactionRollback; } wrappedOldTLK.currentkey = false; } CKKSCurrentKeySet* keyset = [[CKKSCurrentKeySet alloc] init]; + keyset.viewName = newTLK.zoneID.zoneName; keyset.tlk = newTLK; keyset.classA = newClassAKey; @@ -209,21 +234,27 @@ [newClassAKey saveKeyMaterialToKeychain: &error]; [newClassCKey saveKeyMaterialToKeychain: &error]; if(error) { + if([self.deps.lockStateTracker isLockedError:error]) { + ckkserror("ckkstlk", self.deps.zoneID, "Couldn't save new key material to keychain due to lock state. Entering a waiting state; %@", error); + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckkserror("ckkstlk", self.deps.zoneID, "couldn't save new key material to keychain; aborting new TLK operation: %@", error); + self.nextState = SecCKKSZoneKeyStateError; + } self.error = error; - ckkserror("ckkstlk", ckks, "couldn't save new key material to keychain, aborting new TLK operation: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + return CKKSDatabaseTransactionRollback; } // Generate the TLK sharing records for all trusted peers NSMutableSet* tlkShares = [NSMutableSet set]; - for(CKKSPeerProviderState* trustState in ckks.currentTrustStates) { + for(CKKSPeerProviderState* trustState in currentTrustStates) { if(trustState.currentSelfPeers.currentSelf == nil || trustState.currentSelfPeersError) { if(trustState.essential) { ckksnotice("ckkstlk", ckks, "Fatal error: unable to generate TLK shares for (%@): %@", newTLK, trustState.currentSelfPeersError); self.error = trustState.currentSelfPeersError; - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:trustState.currentSelfPeersError]; - return false; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionRollback; } ckksnotice("ckkstlk", ckks, "Unable to generate TLK shares for (%@): %@", newTLK, trustState); continue; @@ -246,10 +277,16 @@ self.keyset = keyset; - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForTLKUpload withError:nil]; - - return true; + // Finish this transaction to cause a keychiain db commit + // This means that if we provide the new keys to another thread, they'll be able to immediately load them from the keychain + // We'll provide the keyset after the commit occurs. + self.nextState = SecCKKSZoneKeyStateWaitForTLKUpload; + return CKKSDatabaseTransactionCommit; }]; + + if(self.keyset) { + [self.deps provideKeySet:self.keyset]; + } } - (void)cancel { diff --git a/keychain/ckks/CKKSNotifier.m b/keychain/ckks/CKKSNotifier.m index 2591a046..25531ee7 100644 --- a/keychain/ckks/CKKSNotifier.m +++ b/keychain/ckks/CKKSNotifier.m @@ -25,13 +25,13 @@ #import "CKKSNotifier.h" #import -#import +#import "keychain/ckks/CKKS.h" @implementation CKKSNotifyPostNotifier +(void)post:(NSString*)notification { if(notification) { - secnotice("ckks", "posting notification %@", notification); + ckksnotice_global("ckks", "posting notification %@", notification); notify_post([notification UTF8String]); } } diff --git a/keychain/ckks/CKKSOperationDependencies.h b/keychain/ckks/CKKSOperationDependencies.h new file mode 100644 index 00000000..60a8aff1 --- /dev/null +++ b/keychain/ckks/CKKSOperationDependencies.h @@ -0,0 +1,95 @@ +#if OCTAGON + +#import +#import + +#import "keychain/ckks/CKKSAccountStateTracker.h" +#import "keychain/ckks/CKKSCurrentKeyPointer.h" +#import "keychain/ckks/CKKSKeychainViewState.h" +#import "keychain/ckks/CKKSLockStateTracker.h" +#import "keychain/ckks/CKKSPeerProvider.h" +#import "keychain/ckks/CKKSProvideKeySetOperation.h" +#import "keychain/ckks/CKKSReachabilityTracker.h" +#import "keychain/ckks/CKKSNearFutureScheduler.h" +#import "keychain/ckks/CKKSSQLDatabaseObject.h" +#import "keychain/ckks/CKKSZoneModifier.h" +#import "keychain/analytics/CKKSLaunchSequence.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSOperationDependencies : NSObject + +@property (readonly) NSSet* zones; +@property (readonly) CKRecordZoneID* zoneID; + +@property (nullable) CKOperationGroup* ckoperationGroup; +@property CKDatabase* ckdatabase; + +@property (nullable) CKOperationGroup* currentOutgoingQueueOperationGroup; + +@property (readonly) CKKSLaunchSequence* launch; +@property (readonly) id flagHandler; + +@property (readonly) CKKSAccountStateTracker* accountStateTracker; +@property (readonly) CKKSLockStateTracker* lockStateTracker; +@property (readonly) CKKSReachabilityTracker* reachabilityTracker; + +// Due to CKKS's current operation scheduling model, these might be updated after object creation +// For example, if an operation is created and waiting to run, and trust arrives, CKKS will reach in +// and inject the new providers, possibly before the operation runs. +@property (atomic) NSArray>* peerProviders; + +// Filled in after creation item creation +@property (nullable) TPSyncingPolicy* syncingPolicy; + +// This is weak as, currently, the databaseProvider owns the CKKSOperationDependencies. +@property (readonly,weak) id databaseProvider; + +@property CKKSZoneModifier* zoneModifier; + +@property (readonly) CKKSNearFutureScheduler* notifyViewChangedScheduler; +@property (readonly) CKKSNearFutureScheduler* savedTLKNotifier; + +// Trigger this to request that the syncing policy be rechecked and reasserted. +@property (nullable) CKKSNearFutureScheduler* requestPolicyCheck; + +// This might contain some key set provider operations. if you're an operation that knows about keysets, feel free to provide them. +@property NSHashTable*>* keysetProviderOperations; + +- (instancetype)initWithViewState:(CKKSKeychainViewState*)viewState + zoneModifier:(CKKSZoneModifier*)zoneModifier + ckdatabase:(CKDatabase*)ckdatabase + ckoperationGroup:(CKOperationGroup* _Nullable)operationGroup + flagHandler:(id)flagHandler + launchSequence:(CKKSLaunchSequence*)launchSequence + accountStateTracker:(CKKSAccountStateTracker*)accountStateTracker + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker + peerProviders:(NSArray>*)peerProviders + databaseProvider:(id)databaseProvider + notifyViewChangedScheduler:(CKKSNearFutureScheduler*)notifyViewChangedScheduler + savedTLKNotifier:(CKKSNearFutureScheduler*)savedTLKNotifier; + +// Convenience method to fetch the trust states from all peer providers +// Do not call this while on the SQL transaction queue! +- (NSArray*)currentTrustStates; + +- (void)provideKeySet:(CKKSCurrentKeySet*)keyset; + +// Helper Methods to change on-disk state +- (bool)intransactionCKRecordChanged:(CKRecord*)record resync:(bool)resync; +- (bool)intransactionCKRecordDeleted:(CKRecordID*)recordID recordType:(NSString*)recordType resync:(bool)resync; + +// Call this if you've done a write and received an error. It'll pull out any new records returned as CKErrorServerRecordChanged and pretend we received them in a fetch +// +// Note that you need to tell this function the records you wanted to save, so it can determine which record failed from its CKRecordID. +// I don't know why CKRecordIDs don't have record types, either. +- (bool)intransactionCKWriteFailed:(NSError*)ckerror attemptedRecordsChanged:(NSDictionary*)savedRecords; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSOperationDependencies.m b/keychain/ckks/CKKSOperationDependencies.m new file mode 100644 index 00000000..f8c0d703 --- /dev/null +++ b/keychain/ckks/CKKSOperationDependencies.m @@ -0,0 +1,258 @@ + +#if OCTAGON + +#import +#import + +#import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSStates.h" +#import "keychain/ckks/CKKSOperationDependencies.h" + +#import "keychain/ckks/CKKSCurrentKeyPointer.h" +#import "keychain/ckks/CKKSCurrentItemPointer.h" +#import "keychain/ckks/CKKSItem.h" +#import "keychain/ckks/CKKSManifest.h" +#import "keychain/ckks/CKKSManifestLeafRecord.h" +#import "keychain/ckks/CKKSTLKShareRecord.h" + +@implementation CKKSOperationDependencies + +- (instancetype)initWithViewState:(CKKSKeychainViewState*)viewState + zoneModifier:(CKKSZoneModifier*)zoneModifier + ckdatabase:(CKDatabase*)ckdatabase + ckoperationGroup:(CKOperationGroup* _Nullable)operationGroup + flagHandler:(id)flagHandler + launchSequence:(CKKSLaunchSequence*)launchSequence + accountStateTracker:(CKKSAccountStateTracker*)accountStateTracker + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker + peerProviders:(NSArray>*)peerProviders + databaseProvider:(id)databaseProvider + notifyViewChangedScheduler:(CKKSNearFutureScheduler*)notifyViewChangedScheduler + savedTLKNotifier:(CKKSNearFutureScheduler*)savedTLKNotifier +{ + if((self = [super init])) { + _zones = [NSSet setWithObject:viewState]; + _zoneID = viewState.zoneID; + + _zoneModifier = zoneModifier; + _ckdatabase = ckdatabase; + _ckoperationGroup = operationGroup; + _flagHandler = flagHandler; + _launch = launchSequence; + _accountStateTracker = accountStateTracker; + _lockStateTracker = lockStateTracker; + _reachabilityTracker = reachabilityTracker; + _peerProviders = peerProviders; + _databaseProvider = databaseProvider; + _notifyViewChangedScheduler = notifyViewChangedScheduler; + _savedTLKNotifier = savedTLKNotifier; + + _currentOutgoingQueueOperationGroup = nil; + _requestPolicyCheck = nil; + + _keysetProviderOperations = [NSHashTable weakObjectsHashTable]; + } + return self; +} + +- (NSArray*)currentTrustStates +{ + NSArray>* peerProviders = self.peerProviders; + NSMutableArray* trustStates = [NSMutableArray array]; + +#if DEBUG + NSAssert(![self.databaseProvider insideSQLTransaction], @"Cannot fetch current trust states from inside a SQL transaction, on pain of deadlocK"); +#endif + + for(id provider in peerProviders) { + ckksnotice("ckks", self.zoneID, "Fetching account keys for provider %@", provider); + [trustStates addObject:provider.currentState]; + } + + return trustStates; +} + +- (void)provideKeySet:(CKKSCurrentKeySet*)keyset +{ + if(!keyset || !keyset.currentTLKPointer.currentKeyUUID) { + ckksnotice("ckkskey", self.zoneID, "No valid keyset provided: %@", keyset); + return; + } + ckksnotice("ckkskey", self.zoneID, "Providing keyset (%@) to listeners", keyset); + + for(CKKSResultOperation* op in self.keysetProviderOperations) { + [op provideKeySet:keyset]; + } +} + +- (bool)intransactionCKRecordChanged:(CKRecord*)record resync:(bool)resync +{ + @autoreleasepool { + ckksnotice("ckksfetch", self.zoneID, "Processing record modification(%@): %@", record.recordType, record); + + NSError* localerror = nil; + + if([[record recordType] isEqual: SecCKRecordItemType]) { + [CKKSItem intransactionRecordChanged:record resync:resync error:&localerror]; + + } else if([[record recordType] isEqual: SecCKRecordCurrentItemType]) { + [CKKSCurrentItemPointer intransactionRecordChanged:record resync:resync error:&localerror]; + + } else if([[record recordType] isEqual: SecCKRecordIntermediateKeyType]) { + [CKKSKey intransactionRecordChanged:record resync:resync flagHandler:self.flagHandler error:&localerror]; + [self.flagHandler _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; + + } else if ([[record recordType] isEqual: SecCKRecordTLKShareType]) { + [CKKSTLKShareRecord intransactionRecordChanged:record resync:resync error:&localerror]; + [self.flagHandler _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; + + } else if([[record recordType] isEqualToString: SecCKRecordCurrentKeyType]) { + [CKKSCurrentKeyPointer intransactionRecordChanged:record resync:resync flagHandler:self.flagHandler error:&localerror]; + + } else if ([[record recordType] isEqualToString:SecCKRecordManifestType]) { + [CKKSPendingManifest intransactionRecordChanged:record resync:resync error:&localerror]; + + } else if ([[record recordType] isEqualToString:SecCKRecordManifestLeafType]) { + [CKKSManifestPendingLeafRecord intransactionRecordChanged:record resync:resync error:&localerror]; + + } else if ([[record recordType] isEqualToString:SecCKRecordDeviceStateType]) { + [CKKSDeviceStateEntry intransactionRecordChanged:record resync:resync error:&localerror]; + + } else { + ckkserror("ckksfetch", self.zoneID, "unknown record type: %@ %@", [record recordType], record); + return false; + } + + if(localerror) { + ckksnotice("ckksfetch", self.zoneID, "Record modification(%@) failed:: %@", record.recordType, localerror); + return false; + } + return true; + } +} + +- (bool)intransactionCKRecordDeleted:(CKRecordID*)recordID recordType:(NSString*)recordType resync:(bool)resync +{ + // TODO: resync doesn't really mean much here; what does it mean for a record to be 'deleted' if you're fetching from scratch? + ckksnotice("ckksfetch", self.zoneID, "Processing record deletion(%@): %@", recordType, recordID.recordName); + + NSError* error = nil; + + if([recordType isEqual: SecCKRecordItemType]) { + [CKKSItem intransactionRecordDeleted:recordID resync:resync error:&error]; + + } else if([recordType isEqual: SecCKRecordCurrentItemType]) { + [CKKSCurrentItemPointer intransactionRecordDeleted:recordID resync:resync error:&error]; + + } else if([recordType isEqual: SecCKRecordIntermediateKeyType]) { + // TODO: handle in some interesting way + return true; + + } else if([recordType isEqual: SecCKRecordTLKShareType]) { + [CKKSTLKShareRecord intransactionRecordDeleted:recordID resync:resync error:&error]; + + } else if([recordType isEqualToString: SecCKRecordCurrentKeyType]) { + // Ignore these as well + return true; + + } else if([recordType isEqual: SecCKRecordDeviceStateType]) { + [CKKSDeviceStateEntry intransactionRecordDeleted:recordID resync:resync error:&error]; + + } else if ([recordType isEqualToString:SecCKRecordManifestType]) { + [CKKSManifest intransactionRecordDeleted:recordID resync:resync error:&error]; + + } else { + ckkserror("ckksfetch", self.zoneID, "unknown record type: %@ %@", recordType, recordID); + return false; + } + + if(error) { + ckksnotice("ckksfetch", self.zoneID, "Record deletion(%@) failed:: %@", recordID, error); + return false; + } + + return true; +} + +// Lets the view know about a failed CloudKit write. If the error is "already have one of these records", it will +// store the new records and kick off the new processing +// +// Note that you need to tell this function the records you wanted to save, so it can determine what needs deletion +- (bool)intransactionCKWriteFailed:(NSError*)ckerror attemptedRecordsChanged:(NSDictionary*)savedRecords +{ + NSDictionary* partialErrors = ckerror.userInfo[CKPartialErrorsByItemIDKey]; + if([ckerror.domain isEqual:CKErrorDomain] && ckerror.code == CKErrorPartialFailure && partialErrors) { + // Check if this error was "you're out of date" + bool recordChanged = true; + + for(NSError* error in partialErrors.allValues) { + if((![error.domain isEqual:CKErrorDomain]) || (error.code != CKErrorBatchRequestFailed && error.code != CKErrorServerRecordChanged && error.code != CKErrorUnknownItem)) { + // There's an error in there that isn't CKErrorServerRecordChanged, CKErrorBatchRequestFailed, or CKErrorUnknownItem. Don't handle nicely... + recordChanged = false; + } + } + + if(recordChanged) { + ckksnotice("ckks", self.zoneID, "Received a ServerRecordChanged error, attempting to update new records and delete unknown ones"); + + bool updatedRecord = false; + + for(CKRecordID* recordID in partialErrors.allKeys) { + NSError* error = partialErrors[recordID]; + if([error.domain isEqual:CKErrorDomain] && error.code == CKErrorServerRecordChanged) { + CKRecord* newRecord = error.userInfo[CKRecordChangedErrorServerRecordKey]; + ckksnotice("ckks", self.zoneID, "On error: updating our idea of: %@", newRecord); + + updatedRecord |= [self intransactionCKRecordChanged:newRecord resync:true]; + } else if([error.domain isEqual:CKErrorDomain] && error.code == CKErrorUnknownItem) { + CKRecord* record = savedRecords[recordID]; + ckksnotice("ckks", self.zoneID, "On error: handling an unexpected delete of: %@ %@", recordID, record); + + updatedRecord |= [self intransactionCKRecordDeleted:recordID recordType:record.recordType resync:true]; + } + } + + if(updatedRecord) { + [self.flagHandler _onqueueHandleFlag:CKKSFlagProcessIncomingQueue]; + return true; + } + } + + // Check if this error was the CKKS server extension rejecting the write + for(CKRecordID* recordID in partialErrors.allKeys) { + NSError* error = partialErrors[recordID]; + + NSError* underlyingError = error.userInfo[NSUnderlyingErrorKey]; + NSError* thirdLevelError = underlyingError.userInfo[NSUnderlyingErrorKey]; + ckksnotice("ckks", self.zoneID, "Examining 'write failed' error: %@ %@ %@", error, underlyingError, thirdLevelError); + + if([error.domain isEqualToString:CKErrorDomain] && error.code == CKErrorServerRejectedRequest && + underlyingError && [underlyingError.domain isEqualToString:CKInternalErrorDomain] && underlyingError.code == CKErrorInternalPluginError && + thirdLevelError && [thirdLevelError.domain isEqualToString:@"CloudkitKeychainService"]) { + + if(thirdLevelError.code == CKKSServerUnexpectedSyncKeyInChain) { + // The server thinks the classA/C synckeys don't wrap directly the to top TLK, but we don't (otherwise, we would have fixed it). + // Issue a key hierarchy fetch and see what's what. + ckkserror("ckks", self.zoneID, "CKKS Server extension has told us about %@ for record %@; requesting refetch and reprocess of key hierarchy", thirdLevelError, recordID); + [self.flagHandler _onqueueHandleFlag:CKKSFlagFetchRequested]; + + } else if(thirdLevelError.code == CKKSServerMissingRecord) { + // The server is concerned that there's a missing record somewhere. + // Issue a key hierarchy fetch and see what's happening + ckkserror("ckks", self.zoneID, "CKKS Server extension has told us about %@ for record %@; requesting refetch and reprocess of key hierarchy", thirdLevelError, recordID); + [self.flagHandler _onqueueHandleFlag:CKKSFlagFetchRequested]; + + } else { + ckkserror("ckks", self.zoneID, "CKKS Server extension has told us about %@ for record %@, but we don't currently handle this error", thirdLevelError, recordID); + } + } + } + } + + return false; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSOutgoingQueueEntry.h b/keychain/ckks/CKKSOutgoingQueueEntry.h index dd7b00d4..a64f93fd 100644 --- a/keychain/ckks/CKKSOutgoingQueueEntry.h +++ b/keychain/ckks/CKKSOutgoingQueueEntry.h @@ -32,10 +32,12 @@ #if OCTAGON #import +#import "keychain/ckks/CKKSMemoryKeyCache.h" NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; +@class CKKSKeychainViewState; @interface CKKSOutgoingQueueEntry : CKKSSQLDatabaseObject @@ -53,19 +55,20 @@ NS_ASSUME_NONNULL_BEGIN waitUntil:(NSDate* _Nullable)waitUntil accessGroup:(NSString*)accessgroup; -+ (instancetype)withItem:(SecDbItemRef)item - action:(NSString*)action - ckks:(CKKSKeychainView*)ckks - error:(NSError* __autoreleasing*)error; -+ (instancetype)fromDatabase:(NSString*)uuid - state:(NSString*)state - zoneID:(CKRecordZoneID*)zoneID - error:(NSError* __autoreleasing*)error; -+ (instancetype)tryFromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; -+ (instancetype)tryFromDatabase:(NSString*)uuid - state:(NSString*)state - zoneID:(CKRecordZoneID*)zoneID - error:(NSError* __autoreleasing*)error; ++ (instancetype _Nullable)withItem:(SecDbItemRef)item + action:(NSString*)action + zoneID:(CKRecordZoneID*)zoneID + keyCache:(CKKSMemoryKeyCache* _Nullable)keyCache + error:(NSError* __autoreleasing*)error; ++ (instancetype _Nullable)fromDatabase:(NSString*)uuid + state:(NSString*)state + zoneID:(CKRecordZoneID*)zoneID + error:(NSError* __autoreleasing*)error; ++ (instancetype _Nullable)tryFromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; ++ (instancetype _Nullable)tryFromDatabase:(NSString*)uuid + state:(NSString*)state + zoneID:(CKRecordZoneID*)zoneID + error:(NSError* __autoreleasing*)error; + (NSArray*)fetch:(ssize_t)n state:(NSString*)state @@ -75,9 +78,21 @@ NS_ASSUME_NONNULL_BEGIN zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; ++ (NSArray*)allWithUUID:(NSString*)uuid + states:(NSArray*)states + zoneID:(CKRecordZoneID*)zoneID + error:(NSError * __autoreleasing *)error; + + (NSDictionary*)countsByStateInZone:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (NSInteger)countByState:(CKKSItemState *)state zone:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error; +- (BOOL)intransactionMoveToState:(NSString*)state + viewState:(CKKSKeychainViewState*)viewState + error:(NSError**)error; +- (BOOL)intransactionMarkAsError:(NSError*)itemError + viewState:(CKKSKeychainViewState*)viewState + error:(NSError**)error; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSOutgoingQueueEntry.m b/keychain/ckks/CKKSOutgoingQueueEntry.m index 4097edd9..70b6a72b 100644 --- a/keychain/ckks/CKKSOutgoingQueueEntry.m +++ b/keychain/ckks/CKKSOutgoingQueueEntry.m @@ -42,6 +42,8 @@ #import "keychain/ckks/CloudKitCategories.h" #import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKSViewManager.h" + @implementation CKKSOutgoingQueueEntry @@ -86,7 +88,78 @@ true) ? YES : NO; } -+ (instancetype)withItem:(SecDbItemRef)item action:(NSString*)action ckks:(CKKSKeychainView*)ckks error: (NSError * __autoreleasing *) error { + ++ (CKKSKey*)keyForItem:(SecDbItemRef)item + zoneID:(CKRecordZoneID*)zoneID + keyCache:(CKKSMemoryKeyCache* _Nullable)keyCache + error:(NSError * __autoreleasing *)error +{ + if(!item) { + ckkserror("ckks-key", zoneID, "Cannot select a key for no item!"); + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSErrorUnexpectedNil + description:@"can't pick a key class for an empty item"]; + } + return nil; + } + + CKKSKeyClass* class = nil; + + NSString* protection = (__bridge NSString*)SecDbItemGetCachedValueWithName(item, kSecAttrAccessible); + if([protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleWhenUnlocked]) { + class = SecCKKSKeyClassA; + } else if([protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleAlwaysPrivate] || + [protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleAfterFirstUnlock]) { + class = SecCKKSKeyClassC; + } else { + NSError* localError = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSInvalidKeyClass + description:[NSString stringWithFormat:@"can't pick key class for protection %@", protection]]; + ckkserror("ckks-key", zoneID, "can't pick key class: %@ %@", localError, item); + if(error) { + *error = localError; + } + + return nil; + } + + NSError* currentKeyError = nil; + CKKSKey* key = nil; + + if(keyCache) { + key = [keyCache currentKeyForClass:class zoneID:zoneID error:¤tKeyError]; + } else { + key = [CKKSKey currentKeyForClass:class zoneID:zoneID error:¤tKeyError]; + } + if(!key || currentKeyError) { + ckkserror("ckks-key", zoneID, "Couldn't find current key for %@: %@", class, currentKeyError); + + if(error) { + *error = currentKeyError; + } + return nil; + } + + // and make sure it's unwrapped. + NSError* loadedError = nil; + if(![key ensureKeyLoaded:&loadedError]) { + ckkserror("ckks-key", zoneID, "Couldn't load key(%@): %@", key, loadedError); + if(error) { + *error = loadedError; + } + return nil; + } + + return key; +} + ++ (instancetype)withItem:(SecDbItemRef)item + action:(NSString*)action + zoneID:(CKRecordZoneID*)zoneID + keyCache:(CKKSMemoryKeyCache* _Nullable)keyCache + error:(NSError * __autoreleasing *)error +{ CFErrorRef cferror = NULL; CKKSKey* key = nil; NSString* uuid = nil; @@ -96,11 +169,16 @@ NSMutableDictionary* objd = nil; + ckkserror("ckksitem", zoneID, "Creating a (%@) outgoing queue entry for: %@", action, item); + NSError* keyError = nil; - key = [ckks keyForItem:item error:&keyError]; + key = [self keyForItem:item + zoneID:zoneID + keyCache:keyCache + error:&keyError]; if(!key || keyError) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:keyError.code description:@"No key for item" underlying:keyError]; - ckkserror("ckksitem", ckks, "no key for item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "no key for item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -110,7 +188,7 @@ objd = (__bridge_transfer NSMutableDictionary*) SecDbItemCopyPListWithMask(item, kSecDbSyncFlag, &cferror); if(!objd) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CFErrorGetCode(cferror) description:@"Couldn't create object plist" underlying:(__bridge_transfer NSError*)cferror]; - ckkserror("ckksitem", ckks, "no plist: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "no plist: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -123,7 +201,7 @@ uuid = (__bridge_transfer NSString*) CFRetainSafe(SecDbItemGetValue(item, &v10itemuuid, &cferror)); if(!uuid || cferror) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSNoUUIDOnItem description:@"No UUID for item" underlying:(__bridge_transfer NSError*)cferror]; - ckkserror("ckksitem", ckks, "No UUID for item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "No UUID for item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -131,7 +209,7 @@ } if([uuid isKindOfClass:[NSNull class]]) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSNoUUIDOnItem description:@"UUID not found in object" underlying:nil]; - ckkserror("ckksitem", ckks, "couldn't fetch UUID: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "couldn't fetch UUID: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -141,7 +219,7 @@ accessgroup = (__bridge_transfer NSString*) CFRetainSafe(SecDbItemGetValue(item, &v6agrp, &cferror)); if(!accessgroup || cferror) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CFErrorGetCode(cferror) description:@"accessgroup not found in object" underlying:(__bridge_transfer NSError*)cferror]; - ckkserror("ckksitem", ckks, "couldn't fetch access group from item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "couldn't fetch access group from item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -149,11 +227,11 @@ } if([accessgroup isKindOfClass:[NSNull class]]) { // That's okay; this is only used for rate limiting. - ckkserror("ckksitem", ckks, "couldn't fetch accessgroup: %@", item); + ckkserror("ckksitem", zoneID, "couldn't fetch accessgroup: %@", item); accessgroup = @"no-group"; } - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid zoneID:ckks.zoneID error:error]; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid zoneID:zoneID error:error]; // The action this change should be depends on any existing pending action, if any // Particularly, we need to coalesce (existing action, new action) to: @@ -162,7 +240,8 @@ // (delete, add) => modify NSString* actualAction = action; - CKKSOutgoingQueueEntry* existingOQE = [CKKSOutgoingQueueEntry tryFromDatabase:uuid state:SecCKKSStateNew zoneID:ckks.zoneID error:error]; + NSError* fetchError = nil; + CKKSOutgoingQueueEntry* existingOQE = [CKKSOutgoingQueueEntry tryFromDatabase:uuid state:SecCKKSStateNew zoneID:zoneID error:&fetchError]; if(existingOQE) { if([existingOQE.action isEqual: SecCKKSActionAdd]) { if([action isEqual:SecCKKSActionModify]) { @@ -180,10 +259,47 @@ if([existingOQE.action isEqual: SecCKKSActionDelete] && [action isEqual:SecCKKSActionAdd]) { actualAction = SecCKKSActionModify; } + } else if(fetchError) { + ckkserror("ckksitem", zoneID, "Unable to fetch an existing OQE due to error: %@", fetchError); + fetchError = nil; + + } else { + if(!ckme && [action isEqualToString:SecCKKSActionDelete]) { + CKKSOutgoingQueueEntry* anyExistingOQE = [CKKSOutgoingQueueEntry tryFromDatabase:uuid zoneID:zoneID error:&fetchError]; + + if(fetchError) { + ckkserror("ckksitem", zoneID, "Unable to fetch an existing OQE (any state) due to error: %@", fetchError); + } else if(!anyExistingOQE) { + // This is a delete for an item which doesn't exist. Therefore, this is a no-op. + ckkserror("ckksitem", zoneID, "Asked to delete a record for which we don't have a CKME or any OQE, ignoring: %@", uuid); + return nil; + } + } } newGenerationCount = ckme ? ckme.item.generationCount : (NSInteger) 0; // TODO: this is wrong + // Is this modification just changing the mdat? As a performance improvement, don't update the item in CK + if(ckme && !existingOQE && [actualAction isEqualToString:SecCKKSActionModify]) { + NSError* ckmeError = nil; + NSMutableDictionary* mirror = [[CKKSItemEncrypter decryptItemToDictionary:ckme.item keyCache:keyCache error:&ckmeError] mutableCopy]; + NSMutableDictionary* objdCopy = [objd mutableCopy]; + + if(ckmeError) { + ckkserror("ckksitem", zoneID, "Unable to decrypt current CKME: %@", ckmeError); + } else { + mirror[(__bridge id)kSecAttrModificationDate] = nil; + mirror[(__bridge id)kSecAttrSHA1] = nil; + objdCopy[(__bridge id)kSecAttrModificationDate] = nil; + objdCopy[(__bridge id)kSecAttrSHA1] = nil; + + if([mirror isEqualToDictionary:objdCopy]) { + ckksnotice("ckksitem", zoneID, "Update to item only changes mdat; skipping %@", uuid); + return nil; + } + } + } + // Pull out any unencrypted fields NSNumber* pcsServiceIdentifier = objd[(id)kSecAttrPCSPlaintextServiceIdentifier]; objd[(id)kSecAttrPCSPlaintextServiceIdentifier] = nil; @@ -196,7 +312,7 @@ CKKSItem* baseitem = [[CKKSItem alloc] initWithUUID:uuid parentKeyUUID:key.uuid - zoneID:ckks.zoneID + zoneID:zoneID encodedCKRecord:nil encItem:nil wrappedkey:nil @@ -208,7 +324,7 @@ if(!baseitem) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSItemCreationFailure description:@"Couldn't create an item" underlying:nil]; - ckkserror("ckksitem", ckks, "couldn't create an item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "couldn't create an item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -220,11 +336,12 @@ dataDictionary:objd updatingCKKSItem:ckme.item parentkey:key + keyCache:keyCache error:&encryptionError]; if(!encryptedItem || encryptionError) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:encryptionError.code description:@"Couldn't encrypt item" underlying:encryptionError]; - ckkserror("ckksitem", ckks, "couldn't encrypt item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "couldn't encrypt item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -270,6 +387,14 @@ return [self allWhere: @{@"state":CKKSNilToNSNull(state), @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} error:error]; } ++ (NSArray*)allWithUUID:(NSString*)uuid states:(NSArray*)states zoneID:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error +{ + return [self allWhere:@{@"UUID": CKKSNilToNSNull(uuid), + @"state": [[CKKSSQLWhereIn alloc] initWithValues:states], + @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} + error:error]; +} + #pragma mark - CKKSSQLDatabaseObject methods @@ -339,6 +464,90 @@ } +#pragma mark - State Transitions + +- (BOOL)intransactionMoveToState:(NSString*)state + viewState:(CKKSKeychainViewState*)viewState + error:(NSError**)error +{ + NSError* localerror = nil; + + if([state isEqualToString:SecCKKSStateDeleted]) { + // Hurray, this must be a success + SecBoolNSErrorCallback syncCallback = [[CKKSViewManager manager] claimCallbackForUUID:self.uuid]; + if(syncCallback) { + syncCallback(true, nil); + } + + [self deleteFromDatabase:&localerror]; + if(localerror) { + ckkserror("ckks", viewState, "Couldn't delete %@: %@", self, localerror); + } + + } else if([self.state isEqualToString:SecCKKSStateInFlight] && [state isEqualToString:SecCKKSStateNew]) { + // An in-flight OQE is moving to new? See if it's been superceded + CKKSOutgoingQueueEntry* newOQE = [CKKSOutgoingQueueEntry tryFromDatabase:self.uuid + state:SecCKKSStateNew + zoneID:viewState.zoneID + error:&localerror]; + if(localerror) { + ckkserror("ckksoutgoing", viewState, "Couldn't fetch an overwriting OQE, assuming one doesn't exist: %@", localerror); + newOQE = nil; + } + + if(newOQE) { + ckksnotice("ckksoutgoing", viewState, "New modification has come in behind inflight %@; dropping failed change", self); + // recurse for that lovely code reuse + [self intransactionMoveToState:SecCKKSStateDeleted + viewState:viewState + error:&localerror]; + if(localerror) { + ckkserror("ckksoutgoing", viewState, "Couldn't delete in-flight OQE: %@", localerror); + } + } else { + self.state = state; + [self saveToDatabase:&localerror]; + if(localerror) { + ckkserror("ckks", viewState, "Couldn't save %@ as %@: %@", self, state, localerror); + } + } + + } else { + self.state = state; + [self saveToDatabase: &localerror]; + if(localerror) { + ckkserror("ckks", viewState, "Couldn't save %@ as %@: %@", self, state, localerror); + } + } + + if(error && localerror) { + *error = localerror; + } + return localerror == nil; +} + +- (BOOL)intransactionMarkAsError:(NSError*)itemError + viewState:(CKKSKeychainViewState*)viewState + error:(NSError* __autoreleasing*)error +{ + SecBoolNSErrorCallback callback = [[CKKSViewManager manager] claimCallbackForUUID:self.uuid]; + if(callback) { + callback(false, itemError); + } + NSError* localerror = nil; + + // Now, delete the OQE: it's never coming back + [self deleteFromDatabase:&localerror]; + if(localerror) { + ckkserror("ckks", viewState, "Couldn't delete %@ (due to error %@): %@", self, itemError, localerror); + } + + if(error && localerror) { + *error = localerror; + } + return localerror == nil; +} + @end #endif diff --git a/keychain/ckks/CKKSOutgoingQueueOperation.h b/keychain/ckks/CKKSOutgoingQueueOperation.h index 9bce4142..3c91001a 100644 --- a/keychain/ckks/CKKSOutgoingQueueOperation.h +++ b/keychain/ckks/CKKSOutgoingQueueOperation.h @@ -21,27 +21,29 @@ * @APPLE_LICENSE_HEADER_END@ */ -#import -#import "keychain/ckks/CKKSGroupOperation.h" #if OCTAGON +#import #import +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@interface CKKSOutgoingQueueOperation : CKKSGroupOperation -@property (weak) CKKSKeychainView* ckks; -@property CKOperationGroup* ckoperationGroup; - +@interface CKKSOutgoingQueueOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; @property size_t itemsProcessed; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; - +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intending:(OctagonState*)intending + errorState:(OctagonState*)errorState; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSOutgoingQueueOperation.m b/keychain/ckks/CKKSOutgoingQueueOperation.m index 940cf26a..d58d1855 100644 --- a/keychain/ckks/CKKSOutgoingQueueOperation.m +++ b/keychain/ckks/CKKSOutgoingQueueOperation.m @@ -26,579 +26,593 @@ #import #import -#import "CKKSKeychainView.h" -#import "CKKSCurrentKeyPointer.h" -#import "CKKSOutgoingQueueOperation.h" -#import "CKKSIncomingQueueEntry.h" -#import "CKKSItemEncrypter.h" -#import "CKKSOutgoingQueueEntry.h" -#import "CKKSReencryptOutgoingItemsOperation.h" -#import "CKKSManifest.h" -#import "CKKSAnalytics.h" +#import "keychain/ckks/CKKSAnalytics.h" +#import "keychain/ckks/CKKSCurrentKeyPointer.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSItemEncrypter.h" +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSManifest.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CKKSOutgoingQueueOperation.h" +#import "keychain/ckks/CKKSReencryptOutgoingItemsOperation.h" +#import "keychain/ckks/CKKSStates.h" +#import "keychain/ckks/CKKSViewManager.h" #import "keychain/ckks/CloudKitCategories.h" #import "keychain/ot/ObjCImprovements.h" #include "keychain/securityd/SecItemServer.h" #include "keychain/securityd/SecItemDb.h" #include -#include #import "CKKSPowerCollection.h" - -@interface CKKSOutgoingQueueOperation() -@property CKModifyRecordsOperation* modifyRecordsOperation; -@end +#import "utilities/SecCoreAnalytics.h" @implementation CKKSOutgoingQueueOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; -- (instancetype)init { +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intending:(OctagonState*)intending + errorState:(OctagonState*)errorState +{ if(self = [super init]) { - } - return nil; -} -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { - if(self = [super init]) { - _ckks = ckks; - _ckoperationGroup = ckoperationGroup; + _deps = dependencies; - [self addNullableDependency:ckks.holdOutgoingQueueOperation]; - - // Depend on all previous CKKSOutgoingQueueOperations - [self linearDependencies:ckks.outgoingQueueOperations]; - - // We also depend on the view being setup and the key hierarchy being reasonable - [self addNullableDependency:ckks.keyStateReadyDependency]; + _nextState = errorState; + _intendedState = intending; } return self; } -- (void) groupStart { - // Synchronous, on some thread. Get back on the CKKS queue for thread-safety. - WEAKIFY(self); ++ (NSArray* _Nullable)ontransactionFetchEntries:(CKKSKeychainViewState*)viewState error:(NSError**)error +{ + NSSet* priorityUUIDs = [[CKKSViewManager manager] pendingCallbackUUIDs]; - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksoutgoing", ckks, "no ckks object"); - return; + NSMutableArray* priorityEntries = [NSMutableArray array]; + NSMutableSet* priorityEntryUUIDs = [NSMutableSet set]; + + for(NSString* uuid in priorityUUIDs) { + NSError* priorityFetchError = nil; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:uuid zoneID:viewState.zoneID error:&priorityFetchError]; + + if(priorityFetchError) { + ckkserror("ckksoutgoing", viewState.zoneID, "Unable to fetch priority uuid %@: %@", uuid, priorityFetchError); + continue; + } + + if(!oqe) { + continue; + } + + if(![oqe.state isEqualToString:SecCKKSStateNew]) { + ckksnotice("ckksoutgoing", viewState.zoneID, "Priority uuid %@ is not in 'new': %@", uuid, oqe); + continue; + } + + if(oqe) { + ckksnotice("ckksoutgoing", viewState.zoneID, "Found OQE to fetch priority uuid %@: %@", uuid, priorityFetchError); + [priorityEntries addObject:oqe]; + [priorityEntryUUIDs addObject:oqe.uuid]; + } } - [ckks dispatchSync: ^bool{ - ckks.lastOutgoingQueueOperation = self; - if(self.cancelled) { - ckksnotice("ckksoutgoing", ckks, "CKKSOutgoingQueueOperation cancelled, quitting"); - return false; - } + // We only actually care about queue items in the 'new' state + NSArray * newEntries = [CKKSOutgoingQueueEntry fetch:SecCKKSOutgoingQueueItemsAtOnce + state:SecCKKSStateNew + zoneID:viewState.zoneID + error:error]; + if(!newEntries) { + return nil; + } - NSError* error = nil; - - NSSet* priorityUUIDs = [ckks _onqueuePriorityOutgoingQueueUUIDs]; - - NSMutableArray* priorityEntries = [NSMutableArray array]; - NSMutableSet* priorityEntryUUIDs = [NSMutableSet set]; - - for(NSString* uuid in priorityUUIDs) { - NSError* priorityFetchError = nil; - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:uuid zoneID:ckks.zoneID error:&priorityFetchError]; - - if(priorityFetchError) { - ckkserror("ckksoutgoing", ckks, "Unable to fetch priority uuid %@: %@", uuid, priorityFetchError); - continue; - } - - if(!oqe) { - continue; - } - - if(![oqe.state isEqualToString:SecCKKSStateNew]) { - ckksnotice("ckksoutgoing", ckks, "Priority uuid %@ is not in 'new': %@", uuid, oqe); - continue; - } - - if(oqe) { - ckksnotice("ckksoutgoing", ckks, "Found OQE to fetch priority uuid %@: %@", uuid, priorityFetchError); - [priorityEntries addObject:oqe]; - [priorityEntryUUIDs addObject:oqe.uuid]; + // Build our list of oqes to transmit + NSMutableArray* queueEntries = [priorityEntries mutableCopy]; + for(CKKSOutgoingQueueEntry* oqe in newEntries) { + if(queueEntries.count >= SecCKKSOutgoingQueueItemsAtOnce) { + break; + } else { + // We only need to add this OQE if it wasn't already there + if(![priorityEntryUUIDs containsObject:oqe.uuid]) { + [queueEntries addObject:oqe]; } } + } - // We only actually care about queue items in the 'new' state - NSArray * newEntries = [CKKSOutgoingQueueEntry fetch:SecCKKSOutgoingQueueItemsAtOnce - state:SecCKKSStateNew - zoneID:ckks.zoneID - error:&error]; - if(error != nil) { - ckkserror("ckksoutgoing", ckks, "Error fetching outgoing queue records: %@", error); - self.error = error; - return false; + return queueEntries; +} + +- (void)groupStart +{ + WEAKIFY(self); + + id databaseProvider = self.deps.databaseProvider; + + NSHashTable* ckWriteOperations = [NSHashTable weakObjectsHashTable]; + + for(CKKSKeychainViewState* viewState in self.deps.zones) { + if(![self.deps.syncingPolicy isSyncingEnabledForView:viewState.zoneID.zoneName]) { + ckkserror("ckksoutgoing", viewState, "Item syncing for this view is disabled"); + continue; } - // Build our list of oqes to transmit - NSMutableArray* queueEntries = [priorityEntries mutableCopy]; - for(CKKSOutgoingQueueEntry* oqe in newEntries) { - if(queueEntries.count >= SecCKKSOutgoingQueueItemsAtOnce) { - break; - } else { - // We only need to add this OQE if it wasn't already there - if(![priorityEntryUUIDs containsObject:oqe.uuid]) { - [queueEntries addObject:oqe]; - } - } - } + // Each zone should get its own transaction, in case errors cause us to roll back queue modifications after marking entries as in-flight + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; - bool fullUpload = queueEntries.count >= SecCKKSOutgoingQueueItemsAtOnce; + NSArray* queueEntries = [CKKSOutgoingQueueOperation ontransactionFetchEntries:viewState error:&error]; - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventOutgoingQueue zone:ckks.zoneName count:[queueEntries count]]; - - ckksinfo("ckksoutgoing", ckks, "processing outgoing queue: %@", queueEntries); - - NSMutableDictionary* recordsToSave = [[NSMutableDictionary alloc] init]; - NSMutableSet* recordIDsModified = [[NSMutableSet alloc] init]; - NSMutableSet*oqesModified = [[NSMutableSet alloc] init]; - NSMutableArray* recordIDsToDelete = [[NSMutableArray alloc] init]; - - CKKSCurrentKeyPointer* currentClassAKeyPointer = [CKKSCurrentKeyPointer fromDatabase: SecCKKSKeyClassA zoneID:ckks.zoneID error: &error]; - CKKSCurrentKeyPointer* currentClassCKeyPointer = [CKKSCurrentKeyPointer fromDatabase: SecCKKSKeyClassC zoneID:ckks.zoneID error: &error]; - NSMutableDictionary* currentKeysToSave = [[NSMutableDictionary alloc] init]; - bool needsReencrypt = false; - - if(error != nil) { - ckkserror("ckksoutgoing", ckks, "Couldn't load current class keys: %@", error); - return false; - } - - for(CKKSOutgoingQueueEntry* oqe in queueEntries) { - if(self.cancelled) { - secdebug("ckksoutgoing", "CKKSOutgoingQueueOperation cancelled, quitting"); - return false; + if(!queueEntries || error) { + ckkserror("ckksoutgoing", viewState.zoneID, "Error fetching outgoing queue records: %@", error); + self.error = error; + return CKKSDatabaseTransactionRollback; } - CKKSOutgoingQueueEntry* inflight = [CKKSOutgoingQueueEntry tryFromDatabase: oqe.uuid state:SecCKKSStateInFlight zoneID:ckks.zoneID error: &error]; - if(!error && inflight) { - // There is an inflight request with this UUID. Leave this request in-queue until CloudKit returns and we resolve the inflight request. - continue; + bool fullUpload = queueEntries.count >= SecCKKSOutgoingQueueItemsAtOnce; + + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventOutgoingQueue zone:viewState.zoneID.zoneName count:[queueEntries count]]; + + ckksinfo("ckksoutgoing", viewState.zoneID, "processing outgoing queue: %@", queueEntries); + + NSMutableDictionary* recordsToSave = [[NSMutableDictionary alloc] init]; + NSMutableSet* recordIDsModified = [[NSMutableSet alloc] init]; + NSMutableSet*oqesModified = [[NSMutableSet alloc] init]; + NSMutableArray* recordIDsToDelete = [[NSMutableArray alloc] init]; + + CKKSCurrentKeyPointer* currentClassAKeyPointer = [CKKSCurrentKeyPointer fromDatabase:SecCKKSKeyClassA zoneID:viewState.zoneID error:&error]; + CKKSCurrentKeyPointer* currentClassCKeyPointer = [CKKSCurrentKeyPointer fromDatabase:SecCKKSKeyClassC zoneID:viewState.zoneID error:&error]; + NSMutableDictionary* currentKeysToSave = [[NSMutableDictionary alloc] init]; + bool needsReencrypt = false; + + if(error != nil) { + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't load current class keys: %@", error); + self.error = error; + return CKKSDatabaseTransactionRollback; } - // If this item is not a delete, check the encryption status of this item. - if(![oqe.action isEqualToString: SecCKKSActionDelete]) { - // Check if this item is encrypted under a current key - if([oqe.item.parentKeyUUID isEqualToString: currentClassAKeyPointer.currentKeyUUID]) { - // Excellent. - currentKeysToSave[SecCKKSKeyClassA] = currentClassAKeyPointer; - - } else if([oqe.item.parentKeyUUID isEqualToString: currentClassCKeyPointer.currentKeyUUID]) { - // Works for us! - currentKeysToSave[SecCKKSKeyClassC] = currentClassCKeyPointer; - - } else { - // This item is encrypted under an old key. Set it up for reencryption and move on. - ckksnotice("ckksoutgoing", ckks, "Item's encryption key (%@ %@) is neither %@ or %@", oqe, oqe.item.parentKeyUUID, currentClassAKeyPointer, currentClassCKeyPointer); - [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateReencrypt error:&error]; - if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save oqe to database: %@", error); - self.error = error; - error = nil; - } - needsReencrypt = true; + for(CKKSOutgoingQueueEntry* oqe in queueEntries) { + CKKSOutgoingQueueEntry* inflight = [CKKSOutgoingQueueEntry tryFromDatabase: oqe.uuid state:SecCKKSStateInFlight zoneID:viewState.zoneID error:&error]; + if(!error && inflight) { + // There is an inflight request with this UUID. Leave this request in-queue until CloudKit returns and we resolve the inflight request. continue; } - } - if([oqe.action isEqualToString: SecCKKSActionAdd]) { - CKRecord* record = [oqe.item CKRecordWithZoneID: ckks.zoneID]; - recordsToSave[record.recordID] = record; - [recordIDsModified addObject: record.recordID]; - [oqesModified addObject:oqe]; + // If this item is not a delete, check the encryption status of this item. + if(![oqe.action isEqualToString: SecCKKSActionDelete]) { + // Check if this item is encrypted under a current key + if([oqe.item.parentKeyUUID isEqualToString: currentClassAKeyPointer.currentKeyUUID]) { + // Excellent. + currentKeysToSave[SecCKKSKeyClassA] = currentClassAKeyPointer; - [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateInFlight error:&error]; - if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); - self.error = error; - } + } else if([oqe.item.parentKeyUUID isEqualToString: currentClassCKeyPointer.currentKeyUUID]) { + // Works for us! + currentKeysToSave[SecCKKSKeyClassC] = currentClassCKeyPointer; - } else if ([oqe.action isEqualToString: SecCKKSActionDelete]) { - CKRecordID* recordIDToDelete = [[CKRecordID alloc] initWithRecordName: oqe.item.uuid zoneID: ckks.zoneID]; - [recordIDsToDelete addObject: recordIDToDelete]; - [recordIDsModified addObject: recordIDToDelete]; - [oqesModified addObject:oqe]; - - [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateInFlight error:&error]; - if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); - } - - } else if ([oqe.action isEqualToString: SecCKKSActionModify]) { - // Load the existing item from the ckmirror. - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: oqe.item.uuid zoneID:ckks.zoneID error:&error]; - if(!ckme) { - // This is a problem: we have an update to an item that doesn't exist. - // Either: an Add operation we launched failed due to a CloudKit error (conflict?) and this is a follow-on update - // Or: ? - ckkserror("ckksoutgoing", ckks, "update to a record that doesn't exist? %@", oqe.item.uuid); - // treat as an add. - CKRecord* record = [oqe.item CKRecordWithZoneID: ckks.zoneID]; - recordsToSave[record.recordID] = record; - [recordIDsModified addObject: record.recordID]; - [oqesModified addObject:oqe]; - - [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateInFlight error:&error]; - if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); - self.error = error; - } - } else { - if(![oqe.item.storedCKRecord.recordChangeTag isEqual: ckme.item.storedCKRecord.recordChangeTag]) { - // The mirror entry has updated since this item was created. If we proceed, we might end up with - // a badly-authenticated record. - ckksnotice("ckksoutgoing", ckks, "Record (%@)'s change tag doesn't match ckmirror's change tag, reencrypting", oqe); - [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateReencrypt error:&error]; + } else { + // This item is encrypted under an old key. Set it up for reencryption and move on. + ckksnotice("ckksoutgoing", viewState.zoneID, "Item's encryption key (%@ %@) is neither %@ or %@", oqe, oqe.item.parentKeyUUID, currentClassAKeyPointer, currentClassCKeyPointer); + [oqe intransactionMoveToState:SecCKKSStateReencrypt viewState:viewState error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save oqe to database: %@", error); + ckkserror("ckksoutgoing", viewState.zoneID, "couldn't save oqe to database: %@", error); self.error = error; error = nil; } needsReencrypt = true; continue; } - // Grab the old ckrecord and update it - CKRecord* record = [oqe.item updateCKRecord: ckme.item.storedCKRecord zoneID: ckks.zoneID]; + } + + if([oqe.action isEqualToString: SecCKKSActionAdd]) { + CKRecord* record = [oqe.item CKRecordWithZoneID:viewState.zoneID]; recordsToSave[record.recordID] = record; [recordIDsModified addObject: record.recordID]; [oqesModified addObject:oqe]; - [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateInFlight error:&error]; + [oqe intransactionMoveToState:SecCKKSStateInFlight viewState:viewState error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); + ckkserror("ckksoutgoing", viewState.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); + self.error = error; } - } - } - } - if(needsReencrypt) { - ckksnotice("ckksoutgoing", ckks, "An item needs reencryption!"); + } else if ([oqe.action isEqualToString: SecCKKSActionDelete]) { + CKRecordID* recordIDToDelete = [[CKRecordID alloc] initWithRecordName:oqe.item.uuid zoneID:viewState.zoneID]; + [recordIDsToDelete addObject: recordIDToDelete]; + [recordIDsModified addObject: recordIDToDelete]; + [oqesModified addObject:oqe]; - CKKSReencryptOutgoingItemsOperation* op = [[CKKSReencryptOutgoingItemsOperation alloc] initWithCKKSKeychainView:ckks ckoperationGroup:self.ckoperationGroup]; - [ckks scheduleOperation: op]; - } + [oqe intransactionMoveToState:SecCKKSStateInFlight viewState:viewState error:&error]; + if(error) { + ckkserror("ckksoutgoing", viewState.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); + } - if([recordsToSave count] == 0 && [recordIDsToDelete count] == 0) { - // Nothing to do! exit. - ckksnotice("ckksoutgoing", ckks, "Nothing in outgoing queue to process"); - if(self.ckoperationGroup) { - ckksnotice("ckksoutgoing", ckks, "End of operation group: %@", self.ckoperationGroup); - } - return true; - } + } else if ([oqe.action isEqualToString: SecCKKSActionModify]) { + // Load the existing item from the ckmirror. + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:oqe.item.uuid zoneID:viewState.zoneID error:&error]; + if(!ckme) { + // This is a problem: we have an update to an item that doesn't exist. + // Either: an Add operation we launched failed due to a CloudKit error (conflict?) and this is a follow-on update + // Or: ? + ckkserror("ckksoutgoing", viewState.zoneID, "update to a record that doesn't exist? %@", oqe.item.uuid); + // treat as an add. + CKRecord* record = [oqe.item CKRecordWithZoneID:viewState.zoneID]; + recordsToSave[record.recordID] = record; + [recordIDsModified addObject: record.recordID]; + [oqesModified addObject:oqe]; - self.itemsProcessed = recordsToSave.count; - - NSBlockOperation* modifyComplete = [[NSBlockOperation alloc] init]; - modifyComplete.name = @"modifyRecordsComplete"; - [self dependOnBeforeGroupFinished: modifyComplete]; - - if ([CKKSManifest shouldSyncManifests]) { - if (ckks.egoManifest) { - [ckks.egoManifest updateWithNewOrChangedRecords:recordsToSave.allValues deletedRecordIDs:recordIDsToDelete]; - for(CKRecord* record in [ckks.egoManifest allCKRecordsWithZoneID:ckks.zoneID]) { - recordsToSave[record.recordID] = record; - } - NSError* saveError = nil; - if (![ckks.egoManifest saveToDatabase:&saveError]) { - self.error = saveError; - ckkserror("ckksoutgoing", ckks, "could not save ego manifest with error: %@", saveError); - } - } - else { - ckkserror("ckksoutgoing", ckks, "could not get current ego manifest to update"); - } - } - - void (^modifyRecordsCompletionBlock)(NSArray*, NSArray*, NSError*) = ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *ckerror) { - STRONGIFY(self); - CKKSKeychainView* strongCKKS = self.ckks; - if(!self || !strongCKKS) { - ckkserror("ckksoutgoing", strongCKKS, "received callback for released object"); - return; - } - - CKKSAnalytics* logger = [CKKSAnalytics logger]; - - [strongCKKS dispatchSyncWithAccountKeys: ^bool{ - if(ckerror) { - ckkserror("ckksoutgoing", strongCKKS, "error processing outgoing queue: %@", ckerror); - - [logger logRecoverableError:ckerror - forEvent:CKKSEventProcessOutgoingQueue - inView:strongCKKS - withAttributes:NULL]; - - // Tell CKKS about any out-of-date records - [strongCKKS _onqueueCKWriteFailed:ckerror attemptedRecordsChanged:recordsToSave]; - - // Check if these are due to key records being out of date. We'll see a CKErrorBatchRequestFailed, with a bunch of errors inside - if([ckerror.domain isEqualToString:CKErrorDomain] && (ckerror.code == CKErrorPartialFailure)) { - NSMutableDictionary* failedRecords = ckerror.userInfo[CKPartialErrorsByItemIDKey]; - - bool askForReencrypt = false; - - if([self _onqueueIsErrorBadEtagOnKeyPointersOnly:ckerror]) { - // The current key pointers have updated without our knowledge, so CloudKit failed this operation. Mark all records as 'needs reencryption' and kick that off. - ckksnotice("ckksoutgoing", strongCKKS, "Error is simply due to current key pointers changing; marking all records as 'needs reencrypt'"); - [self _onqueueModifyAllRecords:failedRecords.allKeys as:SecCKKSStateReencrypt]; - askForReencrypt = true; - - } else if([self _onqueueIsErrorMissingSyncKey:ckerror]) { - ckksnotice("ckksoutgoing", strongCKKS, "Error is due to the key records missing. Marking all as 'needs reencrypt'"); - [self _onqueueModifyAllRecords:failedRecords.allKeys as:SecCKKSStateReencrypt]; - askForReencrypt = true; - - } else { - // Iterate all failures, and reset each item - for(CKRecordID* recordID in failedRecords) { - NSError* recordError = failedRecords[recordID]; - - ckksnotice("ckksoutgoing", strongCKKS, "failed record: %@ %@", recordID, recordError); - - if([recordError.domain isEqualToString: CKErrorDomain] && recordError.code == CKErrorServerRecordChanged) { - if([recordID.recordName isEqualToString: SecCKKSKeyClassA] || - [recordID.recordName isEqualToString: SecCKKSKeyClassC]) { - // Note that _onqueueCKWriteFailed is responsible for kicking the key state machine, so we don't need to do it here. - askForReencrypt = true; - } else { - // CKErrorServerRecordChanged on an item update means that we've been overwritten. - if([recordIDsModified containsObject:recordID]) { - [self _onqueueModifyRecordAsError:recordID recordError:recordError]; - } - } - } else if([recordError.domain isEqualToString: CKErrorDomain] && recordError.code == CKErrorBatchRequestFailed) { - // Also fine. This record only didn't succeed because something else failed. - // OQEs should be placed back into the 'new' state, unless they've been overwritten by a new OQE. Other records should be ignored. - - if([recordIDsModified containsObject:recordID]) { - NSError* localerror = nil; - CKKSOutgoingQueueEntry* inflightOQE = [CKKSOutgoingQueueEntry tryFromDatabase:recordID.recordName state:SecCKKSStateInFlight zoneID:recordID.zoneID error:&localerror]; - [strongCKKS _onqueueChangeOutgoingQueueEntry:inflightOQE toState:SecCKKSStateNew error:&localerror]; - if(localerror) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't clean up outgoing queue entry: %@", localerror); - } - } - - } else { - // Some unknown error occurred on this record. If it's an OQE, move it to the error state. - ckkserror("ckksoutgoing", strongCKKS, "Unknown error on row: %@ %@", recordID, recordError); - if([recordIDsModified containsObject:recordID]) { - [self _onqueueModifyRecordAsError:recordID recordError:recordError]; - } - } - } - } - - if(askForReencrypt) { - // This will wait for the key hierarchy to become 'ready' - ckkserror("ckksoutgoing", strongCKKS, "Starting new Reencrypt items operation"); - CKKSReencryptOutgoingItemsOperation* op = [[CKKSReencryptOutgoingItemsOperation alloc] initWithCKKSKeychainView:strongCKKS - ckoperationGroup:self.ckoperationGroup]; - [strongCKKS scheduleOperation: op]; + [oqe intransactionMoveToState:SecCKKSStateInFlight viewState:viewState error:&error]; + if(error) { + ckkserror("ckksoutgoing", viewState.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); + self.error = error; } } else { - // Some non-partial error occured. We should place all "inflight" OQEs back into the outgoing queue. - ckksnotice("ckks", strongCKKS, "Error is scary: putting all inflight OQEs back into state 'new'"); - [self _onqueueModifyAllRecords:[recordIDsModified allObjects] as:SecCKKSStateNew]; - } - - self.error = ckerror; - return true; - } - - ckksnotice("ckksoutgoing", strongCKKS, "Completed processing outgoing queue (%d modifications, %d deletions)", (int)savedRecords.count, (int)deletedRecordIDs.count); - NSError* error = NULL; - CKKSPowerCollection *plstats = [[CKKSPowerCollection alloc] init]; - - for(CKRecord* record in savedRecords) { - // Save the item records - if([record.recordType isEqualToString: SecCKRecordItemType]) { - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase: record.recordID.recordName state: SecCKKSStateInFlight zoneID:strongCKKS.zoneID error:&error]; - [strongCKKS _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&error]; - if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't update %@ in outgoingqueue: %@", record.recordID.recordName, error); - self.error = error; + if(![oqe.item.storedCKRecord.recordChangeTag isEqual: ckme.item.storedCKRecord.recordChangeTag]) { + // The mirror entry has updated since this item was created. If we proceed, we might end up with + // a badly-authenticated record. + ckksnotice("ckksoutgoing", viewState.zoneID, "Record (%@)'s change tag doesn't match ckmirror's change tag, reencrypting", oqe); + [oqe intransactionMoveToState:SecCKKSStateReencrypt viewState:viewState error:&error]; + if(error) { + ckkserror("ckksoutgoing", viewState.zoneID, "couldn't save oqe to database: %@", error); + self.error = error; + error = nil; + } + needsReencrypt = true; + continue; } - error = nil; - CKKSMirrorEntry* ckme = [[CKKSMirrorEntry alloc] initWithCKRecord: record]; - [ckme saveToDatabase: &error]; + // Grab the old ckrecord and update it + CKRecord* record = [oqe.item updateCKRecord: ckme.item.storedCKRecord zoneID: viewState.zoneID]; + recordsToSave[record.recordID] = record; + [recordIDsModified addObject: record.recordID]; + [oqesModified addObject:oqe]; + + [oqe intransactionMoveToState:SecCKKSStateInFlight viewState:viewState error:&error]; if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't save %@ to ckmirror: %@", record.recordID.recordName, error); - self.error = error; + ckkserror("ckksoutgoing", viewState.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); } - - [plstats storedOQE:oqe]; - - // And the CKCurrentKeyRecords (do we need to do this? Will the server update the change tag on a save which saves nothing?) - } else if([record.recordType isEqualToString: SecCKRecordCurrentKeyType]) { - CKKSCurrentKeyPointer* currentkey = [[CKKSCurrentKeyPointer alloc] initWithCKRecord: record]; - [currentkey saveToDatabase: &error]; - if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't save %@ to currentkey: %@", record.recordID.recordName, error); - self.error = error; - } - - } else if ([record.recordType isEqualToString:SecCKRecordDeviceStateType]) { - CKKSDeviceStateEntry* newcdse = [[CKKSDeviceStateEntry alloc] initWithCKRecord:record]; - [newcdse saveToDatabase:&error]; - if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't save %@ to ckdevicestate: %@", record.recordID.recordName, error); - self.error = error; - } - - } else if ([record.recordType isEqualToString:SecCKRecordManifestType]) { - - } else if (![record.recordType isEqualToString:SecCKRecordManifestLeafType]) { - ckkserror("ckksoutgoing", strongCKKS, "unknown record type in results: %@", record); } } + } - // Delete the deleted record IDs - for(CKRecordID* ckrecordID in deletedRecordIDs) { + if(needsReencrypt) { + ckksnotice("ckksoutgoing", viewState.zoneID, "An item needs reencryption!"); + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagItemReencryptionNeeded]; + } - NSError* error = nil; - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase: ckrecordID.recordName state: SecCKKSStateInFlight zoneID:strongCKKS.zoneID error:&error]; - [strongCKKS _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&error]; - if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't delete %@ from outgoingqueue: %@", ckrecordID.recordName, error); - self.error = error; - } - error = nil; - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: ckrecordID.recordName zoneID:strongCKKS.zoneID error:&error]; - [ckme deleteFromDatabase: &error]; - if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't delete %@ from ckmirror: %@", ckrecordID.recordName, error); - self.error = error; - } - - [plstats deletedOQE:oqe]; - } - - [plstats commit]; - - if(self.error) { - ckkserror("ckksoutgoing", strongCKKS, "Operation failed; rolling back: %@", self.error); - [logger logRecoverableError:self.error - forEvent:CKKSEventProcessOutgoingQueue - inView:strongCKKS - withAttributes:NULL]; - return false; - } else { - [logger logSuccessForEvent:CKKSEventProcessOutgoingQueue inView:strongCKKS]; + if([recordsToSave count] == 0 && [recordIDsToDelete count] == 0) { + // Nothing to do! exit. + ckksnotice("ckksoutgoing", viewState.zoneID, "Nothing in outgoing queue to process"); + if(self.deps.currentOutgoingQueueOperationGroup) { + ckksinfo("ckksoutgoing", self.deps.zoneID, "End of operation group: %@", self.deps.currentOutgoingQueueOperationGroup); + self.deps.currentOutgoingQueueOperationGroup = nil; } return true; - }]; - - [self.operationQueue addOperation: modifyComplete]; - // Kick off another queue process. We expect it to exit instantly, but who knows! - // If we think the network is iffy, though, wait for it to come back - CKKSResultOperation* possibleNetworkDependency = nil; - CKKSReachabilityTracker* reachabilityTracker = strongCKKS.reachabilityTracker; - if(ckerror && [reachabilityTracker isNetworkError:ckerror]) { - possibleNetworkDependency = reachabilityTracker.reachabilityDependency; } - [strongCKKS processOutgoingQueueAfter:possibleNetworkDependency - requiredDelay:fullUpload && !ckerror ? NSEC_PER_MSEC * 100 : DISPATCH_TIME_FOREVER - ckoperationGroup:self.ckoperationGroup]; - }; + self.itemsProcessed = recordsToSave.count; - ckksinfo("ckksoutgoing", ckks, "Current keys to update: %@", currentKeysToSave); - for(CKKSCurrentKeyPointer* keypointer in currentKeysToSave.allValues) { - CKRecord* record = [keypointer CKRecordWithZoneID: ckks.zoneID]; - recordsToSave[record.recordID] = record; - } + ckksinfo("ckksoutgoing", viewState.zoneID, "Current keys to update: %@", currentKeysToSave); + for(CKKSCurrentKeyPointer* keypointer in currentKeysToSave.allValues) { + CKRecord* record = [keypointer CKRecordWithZoneID:viewState.zoneID]; + recordsToSave[record.recordID] = record; + } - // Piggyback on this operation to update our device state - NSError* cdseError = nil; - CKKSDeviceStateEntry* cdse = [ckks _onqueueCurrentDeviceStateEntry:&cdseError]; - CKRecord* cdseRecord = [cdse CKRecordWithZoneID: ckks.zoneID]; - if(cdseError) { - ckkserror("ckksoutgoing", ckks, "Can't make current device state: %@", cdseError); - } else if(!cdseRecord) { - ckkserror("ckksoutgoing", ckks, "Can't make current device state cloudkit record, but no reason why"); - } else { - // Add the CDSE to the outgoing records - // TODO: maybe only do this every few hours? - ckksnotice("ckksoutgoing", ckks, "Updating device state: %@", cdse); - recordsToSave[cdseRecord.recordID] = cdseRecord; - } - - ckksinfo("ckksoutgoing", ckks, "Saving records %@ to CloudKit zone %@", recordsToSave, ckks.zoneID); - - self.modifyRecordsOperation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave.allValues recordIDsToDelete:recordIDsToDelete]; - self.modifyRecordsOperation.atomic = TRUE; - - // Until Changes to discretionary-ness (explicit or derived from QoS) should be "live", all requests should be nondiscretionary - self.modifyRecordsOperation.configuration.automaticallyRetryNetworkFailures = NO; - self.modifyRecordsOperation.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; - self.modifyRecordsOperation.configuration.isCloudKitSupportOperation = YES; - - self.modifyRecordsOperation.savePolicy = CKRecordSaveIfServerRecordUnchanged; - self.modifyRecordsOperation.group = self.ckoperationGroup; - ckksnotice("ckksoutgoing", ckks, "QoS: %d; operation group is %@", (int)self.modifyRecordsOperation.qualityOfService, self.modifyRecordsOperation.group); - ckksnotice("ckksoutgoing", ckks, "Beginning upload for %@ %@", recordsToSave.allKeys, recordIDsToDelete); - - self.modifyRecordsOperation.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) { - STRONGIFY(self); - CKKSKeychainView* blockCKKS = self.ckks; - - if(!error) { - ckksnotice("ckksoutgoing", blockCKKS, "Record upload successful for %@ (%@)", record.recordID.recordName, record.recordChangeTag); + // Piggyback on this operation to update our device state + NSError* cdseError = nil; + CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry intransactionCreateDeviceStateForView:viewState + accountTracker:self.deps.accountStateTracker + lockStateTracker:self.deps.lockStateTracker + error:&cdseError]; + CKRecord* cdseRecord = [cdse CKRecordWithZoneID:viewState.zoneID]; + if(cdseError) { + ckkserror("ckksoutgoing", viewState.zoneID, "Can't make current device state: %@", cdseError); + } else if(!cdseRecord) { + ckkserror("ckksoutgoing", viewState.zoneID, "Can't make current device state cloudkit record, but no reason why"); } else { - ckkserror("ckksoutgoing", blockCKKS, "error on row: %@ %@", error, record); + // Add the CDSE to the outgoing records + // TODO: maybe only do this every few hours? + ckksnotice("ckksoutgoing", viewState.zoneID, "Updating device state: %@", cdse); + recordsToSave[cdseRecord.recordID] = cdseRecord; } - }; - self.modifyRecordsOperation.modifyRecordsCompletionBlock = modifyRecordsCompletionBlock; - [self dependOnBeforeGroupFinished: self.modifyRecordsOperation]; - [ckks.database addOperation: self.modifyRecordsOperation]; + ckksinfo("ckksoutgoing", viewState.zoneID, "Saving records %@ to CloudKit zone %@", recordsToSave, viewState.zoneID); - return true; - }]; + NSBlockOperation* modifyComplete = [[NSBlockOperation alloc] init]; + modifyComplete.name = @"modifyRecordsComplete"; + [self dependOnBeforeGroupFinished: modifyComplete]; + + CKModifyRecordsOperation* modifyRecordsOperation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave.allValues recordIDsToDelete:recordIDsToDelete]; + modifyRecordsOperation.atomic = TRUE; + + [modifyRecordsOperation linearDependencies:ckWriteOperations]; + + // Until Changes to discretionary-ness (explicit or derived from QoS) should be "live", all requests should be nondiscretionary + modifyRecordsOperation.configuration.automaticallyRetryNetworkFailures = NO; + modifyRecordsOperation.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; + modifyRecordsOperation.configuration.isCloudKitSupportOperation = YES; + + modifyRecordsOperation.savePolicy = CKRecordSaveIfServerRecordUnchanged; + modifyRecordsOperation.group = self.deps.currentOutgoingQueueOperationGroup; + ckksnotice("ckksoutgoing", viewState.zoneID, "QoS: %d; operation group is %@", (int)modifyRecordsOperation.qualityOfService, modifyRecordsOperation.group); + ckksnotice("ckksoutgoing", viewState.zoneID, "Beginning upload for %d records, deleting %d records", + (int)recordsToSave.count, + (int)recordIDsToDelete.count); + + for(CKRecordID* recordID in [recordsToSave allKeys]) { + ckksinfo("ckksoutgoing", recordID.zoneID, "Record to save: %@", recordID); + } + for(CKRecordID* recordID in recordIDsToDelete) { + ckksinfo("ckksoutgoing", recordID.zoneID, "Record to delete: %@", recordID); + } + + modifyRecordsOperation.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) { + if(!error) { + ckksnotice("ckksoutgoing", record.recordID.zoneID, "Record upload successful for %@ (%@)", record.recordID.recordName, record.recordChangeTag); + } else { + ckkserror("ckksoutgoing", record.recordID.zoneID, "error on row: %@ %@", error, record); + } + }; + + modifyRecordsOperation.modifyRecordsCompletionBlock = ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *ckerror) { + STRONGIFY(self); + [self modifyRecordsCompleted:viewState + fullUpload:fullUpload + recordsToSave:recordsToSave + recordIDsToDelete:recordIDsToDelete + recordIDsModified:recordIDsModified + modifyComplete:modifyComplete + savedRecords:savedRecords + deletedRecordIDs:deletedRecordIDs + ckerror:ckerror]; + };; + [self dependOnBeforeGroupFinished:modifyRecordsOperation]; + [self.deps.ckdatabase addOperation:modifyRecordsOperation]; + + return CKKSDatabaseTransactionCommit; + }]; + } } -- (void)_onqueueModifyRecordAsError:(CKRecordID*)recordID recordError:(NSError*)itemerror { - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksoutgoing", ckks, "no CKKS object"); - return; +- (void)modifyRecordsCompleted:(CKKSKeychainViewState*)viewState + fullUpload:(BOOL)fullUpload + recordsToSave:(NSDictionary*)recordsToSave + recordIDsToDelete:(NSArray*)recordIDsToDelete + recordIDsModified:(NSSet*)recordIDsModified + modifyComplete:(NSOperation*)modifyComplete + savedRecords:(NSArray*)savedRecords + deletedRecordIDs:(NSArray*)deletedRecordIDs + ckerror:(NSError*)ckerror +{ + CKKSAnalytics* logger = [CKKSAnalytics logger]; + + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + if(ckerror) { + ckkserror("ckksoutgoing", viewState.zoneID, "error processing outgoing queue: %@", ckerror); + + [logger logRecoverableError:ckerror + forEvent:CKKSEventProcessOutgoingQueue + zoneName:viewState.zoneID.zoneName + withAttributes:NULL]; + + // Tell CKKS about any out-of-date records + [self.deps intransactionCKWriteFailed:ckerror attemptedRecordsChanged:recordsToSave]; + + // Check if these are due to key records being out of date. We'll see a CKErrorBatchRequestFailed, with a bunch of errors inside + if([ckerror.domain isEqualToString:CKErrorDomain] && (ckerror.code == CKErrorPartialFailure)) { + NSMutableDictionary* failedRecords = ckerror.userInfo[CKPartialErrorsByItemIDKey]; + + bool askForReencrypt = false; + + if([self intransactionIsErrorBadEtagOnKeyPointersOnly:ckerror]) { + // The current key pointers have updated without our knowledge, so CloudKit failed this operation. Mark all records as 'needs reencryption' and kick that off. + ckksnotice("ckksoutgoing", viewState.zoneID, "Error is simply due to current key pointers changing; marking all records as 'needs reencrypt'"); + [self _onqueueModifyAllRecords:failedRecords.allKeys + as:SecCKKSStateReencrypt + viewState:viewState]; + askForReencrypt = true; + + } else if([self _onqueueIsErrorMissingSyncKey:ckerror]) { + ckksnotice("ckksoutgoing", viewState.zoneID, "Error is due to the key records missing. Marking all as 'needs reencrypt'"); + [self _onqueueModifyAllRecords:failedRecords.allKeys + as:SecCKKSStateReencrypt + viewState:viewState]; + askForReencrypt = true; + + } else { + // Iterate all failures, and reset each item + for(CKRecordID* recordID in failedRecords) { + NSError* recordError = failedRecords[recordID]; + + ckksnotice("ckksoutgoing", viewState.zoneID, "failed record: %@ %@", recordID, recordError); + + if([recordError.domain isEqualToString: CKErrorDomain] && recordError.code == CKErrorServerRecordChanged) { + if([recordID.recordName isEqualToString: SecCKKSKeyClassA] || + [recordID.recordName isEqualToString: SecCKKSKeyClassC]) { + askForReencrypt = true; + } else { + // CKErrorServerRecordChanged on an item update means that we've been overwritten. + if([recordIDsModified containsObject:recordID]) { + [self _onqueueModifyRecordAsError:recordID + recordError:recordError + viewState:viewState]; + } + } + } else if([recordError.domain isEqualToString: CKErrorDomain] && recordError.code == CKErrorBatchRequestFailed) { + // Also fine. This record only didn't succeed because something else failed. + // OQEs should be placed back into the 'new' state, unless they've been overwritten by a new OQE. Other records should be ignored. + + if([recordIDsModified containsObject:recordID]) { + NSError* localerror = nil; + CKKSOutgoingQueueEntry* inflightOQE = [CKKSOutgoingQueueEntry tryFromDatabase:recordID.recordName state:SecCKKSStateInFlight zoneID:recordID.zoneID error:&localerror]; + [inflightOQE intransactionMoveToState:SecCKKSStateNew viewState:viewState error:&localerror]; + if(localerror) { + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't clean up outgoing queue entry: %@", localerror); + } + } + + } else { + // Some unknown error occurred on this record. If it's an OQE, move it to the error state. + ckkserror("ckksoutgoing", viewState.zoneID, "Unknown error on row: %@ %@", recordID, recordError); + if([recordIDsModified containsObject:recordID]) { + [self _onqueueModifyRecordAsError:recordID + recordError:recordError + viewState:viewState]; + } + } + } + } + + if(askForReencrypt) { + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagItemReencryptionNeeded]; + } + } else { + // Some non-partial error occured. We should place all "inflight" OQEs back into the outgoing queue. + ckksnotice("ckks", viewState.zoneID, "Error is scary: putting all inflight OQEs back into state 'new'"); + [self _onqueueModifyAllRecords:[recordIDsModified allObjects] + as:SecCKKSStateNew + viewState:viewState]; + } + + self.error = ckerror; + return CKKSDatabaseTransactionCommit; + } + + for(CKRecordID* deletedRecordID in deletedRecordIDs) { + ckksnotice("ckksoutgoing", viewState.zoneID, "Record deletion successful for %@", deletedRecordID.recordName); + } + + ckksnotice("ckksoutgoing", viewState.zoneID, "Completed processing outgoing queue (%d modifications, %d deletions)", (int)savedRecords.count, (int)deletedRecordIDs.count); + NSError* error = NULL; + CKKSPowerCollection *plstats = [[CKKSPowerCollection alloc] init]; + + for(CKRecord* record in savedRecords) { + // Save the item records + if([record.recordType isEqualToString: SecCKRecordItemType]) { + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:record.recordID.recordName + state:SecCKKSStateInFlight + zoneID:viewState.zoneID + error:&error]; + [oqe intransactionMoveToState:SecCKKSStateDeleted viewState:viewState error:&error]; + if(error) { + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't update %@ in outgoingqueue: %@", record.recordID.recordName, error); + self.error = error; + } + error = nil; + CKKSMirrorEntry* ckme = [[CKKSMirrorEntry alloc] initWithCKRecord: record]; + [ckme saveToDatabase: &error]; + if(error) { + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't save %@ to ckmirror: %@", record.recordID.recordName, error); + self.error = error; + } + + [plstats storedOQE:oqe]; + + // And the CKCurrentKeyRecords (do we need to do this? Will the server update the change tag on a save which saves nothing?) + } else if([record.recordType isEqualToString: SecCKRecordCurrentKeyType]) { + CKKSCurrentKeyPointer* currentkey = [[CKKSCurrentKeyPointer alloc] initWithCKRecord: record]; + [currentkey saveToDatabase: &error]; + if(error) { + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't save %@ to currentkey: %@", record.recordID.recordName, error); + self.error = error; + } + + } else if ([record.recordType isEqualToString:SecCKRecordDeviceStateType]) { + CKKSDeviceStateEntry* newcdse = [[CKKSDeviceStateEntry alloc] initWithCKRecord:record]; + [newcdse saveToDatabase:&error]; + if(error) { + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't save %@ to ckdevicestate: %@", record.recordID.recordName, error); + self.error = error; + } + + } else if ([record.recordType isEqualToString:SecCKRecordManifestType]) { + + } else if (![record.recordType isEqualToString:SecCKRecordManifestLeafType]) { + ckkserror("ckksoutgoing", viewState.zoneID, "unknown record type in results: %@", record); + } + } + + // Delete the deleted record IDs + for(CKRecordID* ckrecordID in deletedRecordIDs) { + + NSError* error = nil; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:ckrecordID.recordName + state:SecCKKSStateInFlight + zoneID:viewState.zoneID + error:&error]; + [oqe intransactionMoveToState:SecCKKSStateDeleted viewState:viewState error:&error]; + if(error) { + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't delete %@ from outgoingqueue: %@", ckrecordID.recordName, error); + self.error = error; + } + error = nil; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: ckrecordID.recordName zoneID:viewState.zoneID error:&error]; + [ckme deleteFromDatabase: &error]; + if(error) { + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't delete %@ from ckmirror: %@", ckrecordID.recordName, error); + self.error = error; + } + + [plstats deletedOQE:oqe]; + } + + [plstats commit]; + + if(self.error) { + ckkserror("ckksoutgoing", viewState.zoneID, "Operation failed; rolling back: %@", self.error); + [logger logRecoverableError:self.error + forEvent:CKKSEventProcessOutgoingQueue + zoneName:viewState.zoneID.zoneName + withAttributes:NULL]; + return CKKSDatabaseTransactionRollback; + } else { + [logger logSuccessForEvent:CKKSEventProcessOutgoingQueue zoneName:viewState.zoneID.zoneName]; + } + return CKKSDatabaseTransactionCommit; + }]; + + self.nextState = self.intendedState; + [self.operationQueue addOperation:modifyComplete]; + + // If this was a "full upload", or we errored in any way, then kick off another queue process. There might be more items to send! + if(fullUpload || self.error) { + // If we think the network is iffy, though, wait for it to come back + bool networkError = ckerror && [self.deps.reachabilityTracker isNetworkError:ckerror]; + + // But wait for the network to be available! + OctagonPendingFlag* pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:CKKSFlagProcessOutgoingQueue + conditions:networkError ? OctagonPendingConditionsNetworkReachable : 0 + delayInSeconds:.4]; + [self.deps.flagHandler handlePendingFlag:pendingFlag]; } +} - dispatch_assert_queue(ckks.queue); +- (void)_onqueueModifyRecordAsError:(CKRecordID*)recordID + recordError:(NSError*)itemerror + viewState:(CKKSKeychainViewState*)viewState +{ NSError* error = nil; uint64_t count = 0; // At this stage, cloudkit doesn't give us record types - if([recordID.recordName isEqualToString: SecCKKSKeyClassA] || - [recordID.recordName isEqualToString: SecCKKSKeyClassC] || + if([recordID.recordName isEqualToString:SecCKKSKeyClassA] || + [recordID.recordName isEqualToString:SecCKKSKeyClassC] || [recordID.recordName hasPrefix:@"Manifest:-:"] || [recordID.recordName hasPrefix:@"ManifestLeafRecord:-:"]) { // Nothing to do here. We need a whole key refetch and synchronize. } else { - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state: SecCKKSStateInFlight zoneID:ckks.zoneID error:&error]; - [ckks _onqueueErrorOutgoingQueueEntry: oqe itemError: itemerror error:&error]; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state:SecCKKSStateInFlight zoneID:viewState.zoneID error:&error]; + [oqe intransactionMarkAsError:itemerror + viewState:viewState + error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "Couldn't set OQE %@ as error: %@", recordID.recordName, error); + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't set OQE %@ as error: %@", recordID.recordName, error); self.error = error; } count ++; } } - -- (void)_onqueueModifyAllRecords:(NSArray*)recordIDs as:(CKKSItemState*)state { - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksoutgoing", ckks, "no CKKS object"); - return; - } - - dispatch_assert_queue(ckks.queue); - +- (void)_onqueueModifyAllRecords:(NSArray*)recordIDs + as:(CKKSItemState*)state + viewState:(CKKSKeychainViewState*)viewState +{ NSError* error = nil; uint64_t count = 0; @@ -608,10 +622,12 @@ [recordID.recordName isEqualToString: SecCKKSKeyClassC]) { // Nothing to do here. We need a whole key refetch and synchronize. } else { - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state: SecCKKSStateInFlight zoneID:ckks.zoneID error:&error]; - [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:state error:&error]; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state:SecCKKSStateInFlight zoneID:viewState.zoneID error:&error]; + [oqe intransactionMoveToState:state + viewState:viewState + error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "Couldn't set OQE %@ as %@: %@", recordID.recordName, state, error); + ckkserror("ckksoutgoing", viewState.zoneID, "Couldn't set OQE %@ as %@: %@", recordID.recordName, state, error); self.error = error; } count ++; @@ -619,7 +635,7 @@ } if([state isEqualToString:SecCKKSStateReencrypt]) { - SecADAddValueForScalarKey((__bridge CFStringRef) SecCKKSAggdItemReencryption, count); + [SecCoreAnalytics sendEvent:SecCKKSAggdItemReencryption event:@{SecCoreAnalyticsValue: [NSNumber numberWithUnsignedInteger:count]}]; } } @@ -631,7 +647,7 @@ NSError* recordError = failedRecords[recordID]; if([recordError isCKKSServerPluginError:CKKSServerMissingRecord]) { - secnotice("ckksoutgoing", "Error is a 'missing record' error: %@", recordError); + ckksnotice("ckksoutgoing", recordID.zoneID, "Error is a 'missing record' error: %@", recordError); return YES; } } @@ -640,7 +656,7 @@ return NO; } -- (bool)_onqueueIsErrorBadEtagOnKeyPointersOnly:(NSError*)ckerror { +- (bool)intransactionIsErrorBadEtagOnKeyPointersOnly:(NSError*)ckerror { bool anyOtherErrors = false; if([ckerror.domain isEqualToString:CKErrorDomain] && (ckerror.code == CKErrorPartialFailure)) { diff --git a/keychain/ckks/CKKSPeer.m b/keychain/ckks/CKKSPeer.m index 4904574f..75d82dde 100644 --- a/keychain/ckks/CKKSPeer.m +++ b/keychain/ckks/CKKSPeer.m @@ -100,8 +100,7 @@ NSString* const CKKSSOSPeerPrefix = @"spid-"; - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _peerID = [decoder decodeObjectOfClass:[NSString class] forKey:@"peerID"]; NSData* encryptionSPKI = [decoder decodeObjectOfClass:[NSData class] forKey:@"encryptionKey"]; @@ -185,8 +184,7 @@ NSString* const CKKSSOSPeerPrefix = @"spid-"; - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _spid = [decoder decodeObjectOfClass:[NSString class] forKey:@"spid"]; NSData* encryptionSPKI = [decoder decodeObjectOfClass:[NSData class] forKey:@"encryptionKey"]; diff --git a/keychain/ckks/CKKSPeerProvider.h b/keychain/ckks/CKKSPeerProvider.h index 6811e63c..cb9f30ec 100644 --- a/keychain/ckks/CKKSPeerProvider.h +++ b/keychain/ckks/CKKSPeerProvider.h @@ -2,6 +2,7 @@ #import #import "keychain/ckks/CKKSPeer.h" +#import "keychain/ckks/CKKSCurrentKeyPointer.h" NS_ASSUME_NONNULL_BEGIN @@ -34,6 +35,9 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - CKKSPeerProviderState +@class CKKSKey; +@class CKKSTLKShareRecord; + @interface CKKSPeerProviderState : NSObject @property NSString* peerProviderID; @@ -54,6 +58,13 @@ NS_ASSUME_NONNULL_BEGIN trustedPeers:(NSSet>* _Nullable)currentTrustedPeers trustedPeersError:(NSError* _Nullable)trustedPeersError; +- (NSSet>* _Nullable)findPeersMissingTLKSharesFor:(CKKSCurrentKeySet*)keyset + error:(NSError**)error; + +- (BOOL)unwrapKey:(CKKSKey*)proposedTLK + fromShares:(NSArray*)tlkShares + error:(NSError**)error; + + (CKKSPeerProviderState*)noPeersState:(id)provider; // Intended for use in PeerProviders. Thread-safety is up to the PeerProvider. diff --git a/keychain/ckks/CKKSPeerProvider.m b/keychain/ckks/CKKSPeerProvider.m index f773204d..66fe568a 100644 --- a/keychain/ckks/CKKSPeerProvider.m +++ b/keychain/ckks/CKKSPeerProvider.m @@ -1,6 +1,8 @@ #if OCTAGON #import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSKey.h" #import "keychain/ckks/CKKSPeerProvider.h" +#import "keychain/ckks/CKKSTLKShareRecord.h" #import "keychain/categories/NSError+UsefulConstructors.h" @implementation CKKSPeerProviderState @@ -70,6 +72,204 @@ trustedPeers:currentTrustedPeers trustedPeersError:trustedPeersError]; } + +// For this key, who doesn't yet have a valid CKKSTLKShare for it? +// Note that we really want a record sharing the TLK to ourselves, so this function might return +// a non-empty set even if all peers have the TLK: it wants us to make a record for ourself. +- (NSSet>* _Nullable)findPeersMissingTLKSharesFor:(CKKSCurrentKeySet*)keyset + error:(NSError**)error +{ + if(self.currentTrustedPeersError) { + ckkserror("ckksshare", keyset.tlk, "Couldn't find missing shares because trusted peers aren't available: %@", self.currentTrustedPeersError); + if(error) { + *error = self.currentTrustedPeersError; + } + return [NSSet set]; + } + if(self.currentSelfPeersError) { + ckkserror("ckksshare", keyset.tlk, "Couldn't find missing shares because self peers aren't available: %@", self.currentSelfPeersError); + if(error) { + *error = self.currentSelfPeersError; + } + return [NSSet set]; + } + + NSArray* tlkShares = [keyset.tlkShares arrayByAddingObjectsFromArray:keyset.pendingTLKShares ?: @[]]; + + NSMutableSet>* peersMissingShares = [NSMutableSet set]; + + // Ensure that the 'self peer' is one of the current trusted peers. Otherwise, any TLKShare we create + // won't be considered trusted the next time through... + if(![self.currentTrustedPeerIDs containsObject:self.currentSelfPeers.currentSelf.peerID]) { + ckkserror("ckksshare", keyset.tlk, "current self peer (%@) is not in the set of trusted peers: %@", + self.currentSelfPeers.currentSelf.peerID, + self.currentTrustedPeerIDs); + + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSLackingTrust + description:[NSString stringWithFormat:@"current self peer (%@) is not in the set of trusted peers", + self.currentSelfPeers.currentSelf.peerID]]; + } + + return nil; + } + + for(id peer in self.currentTrustedPeers) { + if(![peer shouldHaveView:keyset.tlk.zoneName]) { + ckkserror("ckksshare", keyset.tlk.keycore.zoneID, "Peer (%@) is not supposed to have view, skipping", peer); + continue; + } + + // Determine if we think this peer has enough things shared to them + bool alreadyShared = false; + for(CKKSTLKShareRecord* existingShare in tlkShares) { + // Ensure this share is to this peer... + if(![existingShare.share.receiverPeerID isEqualToString:peer.peerID]) { + continue; + } + + // If an SOS Peer sent this share, is its signature still valid? Or did the signing key change? + if([existingShare.senderPeerID hasPrefix:CKKSSOSPeerPrefix]) { + NSError* signatureError = nil; + if(![existingShare signatureVerifiesWithPeerSet:self.currentTrustedPeers error:&signatureError]) { + ckksnotice("ckksshare", keyset.tlk, "Existing TLKShare's signature doesn't verify with current peer set: %@ %@", signatureError, existingShare); + continue; + } + } + + if([existingShare.tlkUUID isEqualToString:keyset.tlk.uuid] && [self.currentTrustedPeerIDs containsObject:existingShare.senderPeerID]) { + // Was this shared to us? + if([peer.peerID isEqualToString:self.currentSelfPeers.currentSelf.peerID]) { + // We only count this as 'found' if we did the sharing and it's to our current keys + NSData* currentKey = self.currentSelfPeers.currentSelf.publicEncryptionKey.keyData; + + if([existingShare.senderPeerID isEqualToString:self.currentSelfPeers.currentSelf.peerID] && + [existingShare.share.receiverPublicEncryptionKeySPKI isEqual:currentKey]) { + ckksnotice("ckksshare", keyset.tlk, "Local peer %@ is shared %@ via self: %@", peer, keyset.tlk, existingShare); + alreadyShared = true; + break; + } else { + ckksnotice("ckksshare", keyset.tlk, "Local peer %@ is shared %@ via trusted %@, but that's not good enough", peer, keyset.tlk, existingShare); + } + + } else { + // Was this shared to the remote peer's current keys? + NSData* currentKeySPKI = peer.publicEncryptionKey.keyData; + + if([existingShare.share.receiverPublicEncryptionKeySPKI isEqual:currentKeySPKI]) { + // Some other peer has a trusted share. Cool! + ckksnotice("ckksshare", keyset.tlk, "Peer %@ is shared %@ via trusted %@", peer, keyset.tlk, existingShare); + alreadyShared = true; + break; + } else { + ckksnotice("ckksshare", keyset.tlk, "Peer %@ has a share for %@, but to old keys: %@", peer, keyset.tlk, existingShare); + } + } + } + } + + if(!alreadyShared) { + // Add this peer to our set, if it has an encryption key to receive the share + if(peer.publicEncryptionKey) { + [peersMissingShares addObject:peer]; + } + } + } + + if(peersMissingShares.count > 0u) { + // Log each and every one of the things + ckksnotice("ckksshare", keyset.tlk, "Missing TLK shares for %lu peers: %@", (unsigned long)peersMissingShares.count, peersMissingShares); + ckksnotice("ckksshare", keyset.tlk, "Self peers are (%@) %@", self.currentSelfPeersError ?: @"no error", self.currentSelfPeers); + ckksnotice("ckksshare", keyset.tlk, "Trusted peers are (%@) %@", self.currentTrustedPeersError ?: @"no error", self.currentTrustedPeers); + } + + return peersMissingShares; +} + +- (BOOL)unwrapKey:(CKKSKey*)proposedTLK + fromShares:(NSArray*)tlkShares + error:(NSError**)error +{ + if(!self.currentSelfPeers.currentSelf || self.currentSelfPeersError) { + ckkserror("ckksshare", proposedTLK, "Don't have self peers for %@: %@", self.peerProviderID, self.currentSelfPeersError); + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNoEncryptionKey + description:@"Key unwrap failed" + underlying:self.currentSelfPeersError];; + } + return NO; + } + + if(!self.currentTrustedPeers || self.currentTrustedPeersError) { + ckkserror("ckksshare", proposedTLK, "Don't have trusted peers: %@", self.currentTrustedPeersError); + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNoPeersAvailable + description:@"No trusted peers" + underlying:self.currentTrustedPeersError]; + } + return NO; + } + + NSError* lastShareError = nil; + + for(id selfPeer in self.currentSelfPeers.allSelves) { + NSMutableArray* possibleShares = [NSMutableArray array]; + + for(CKKSTLKShareRecord* share in tlkShares) { + if([share.share.receiverPeerID isEqualToString:selfPeer.peerID]) { + [possibleShares addObject:share]; + } + } + + if(possibleShares.count == 0) { + ckksnotice("ckksshare", proposedTLK, "No CKKSTLKShares to %@ for %@", selfPeer, proposedTLK); + continue; + } + + for(CKKSTLKShareRecord* possibleShare in possibleShares) { + NSError* possibleShareError = nil; + ckksnotice("ckksshare", proposedTLK, "Checking possible TLK share %@ as %@", possibleShare, selfPeer); + + CKKSKey* possibleKey = [possibleShare recoverTLK:selfPeer + trustedPeers:self.currentTrustedPeers + error:&possibleShareError]; + + if(!possibleKey || possibleShareError) { + ckkserror("ckksshare", proposedTLK, "Unable to unwrap TLKShare(%@) as %@: %@", + possibleShare, selfPeer, possibleShareError); + ckkserror("ckksshare", proposedTLK, "Current trust set: %@", self.currentTrustedPeers); + lastShareError = possibleShareError; + continue; + } + + bool result = [proposedTLK trySelfWrappedKeyCandidate:possibleKey.aessivkey error:&possibleShareError]; + if(!result || possibleShareError) { + ckkserror("ckksshare", proposedTLK, "Unwrapped TLKShare(%@) does not unwrap proposed TLK(%@) as %@: %@", + possibleShare, proposedTLK, self.currentSelfPeers.currentSelf, possibleShareError); + lastShareError = possibleShareError; + continue; + } + + ckksnotice("ckksshare", proposedTLK, "TLKShare(%@) unlocked TLK(%@) as %@", + possibleShare, proposedTLK, selfPeer); + + return YES; + } + } + + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNoTrustedTLKShares + description:[NSString stringWithFormat:@"No trusted TLKShares for %@", proposedTLK] + underlying:lastShareError]; + } + + return NO; +} + @end #endif diff --git a/keychain/ckks/CKKSProcessReceivedKeysOperation.h b/keychain/ckks/CKKSProcessReceivedKeysOperation.h index 362843ec..ccc7fcd7 100644 --- a/keychain/ckks/CKKSProcessReceivedKeysOperation.h +++ b/keychain/ckks/CKKSProcessReceivedKeysOperation.h @@ -32,24 +32,16 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -// CKKS's state machine depends on its operations performing callbacks to move the state, but this means -// the operations cannot be reused outside of the state machine context. -// Therefore, split this operation into two: one which does the work, and another which does the CKKS state manipulation. - -@interface CKKSProcessReceivedKeysOperation : CKKSResultOperation +@interface CKKSProcessReceivedKeysOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; @property CKKSZoneKeyState* nextState; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks; -@end - -@interface CKKSProcessReceivedKeysStateMachineOperation : CKKSResultOperation -@property (weak) CKKSKeychainView* ckks; - -- (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks; +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSProcessReceivedKeysOperation.m b/keychain/ckks/CKKSProcessReceivedKeysOperation.m index 3ccc4fe1..d626171f 100644 --- a/keychain/ckks/CKKSProcessReceivedKeysOperation.m +++ b/keychain/ckks/CKKSProcessReceivedKeysOperation.m @@ -29,50 +29,37 @@ #import "CKKSCurrentKeyPointer.h" #import "CKKSKey.h" #import "CKKSProcessReceivedKeysOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" #import "keychain/ckks/CloudKitCategories.h" #import "keychain/categories/NSError+UsefulConstructors.h" @implementation CKKSProcessReceivedKeysOperation +@synthesize intendedState = _intendedState; -- (instancetype)init { - return nil; -} -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks { +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ if(self = [super init]) { - _ckks = ckks; - _nextState = SecCKKSZoneKeyStateError; + _deps = dependencies; + _intendedState = intendedState; + _nextState = errorState; } return self; } - (void)main { - // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. + NSArray* currentTrustStates = self.deps.currentTrustStates; - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - secerror("ckkskeys: No CKKS object"); - return; - } + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult { + bool ok = [self _onqueueMain:currentTrustStates]; - if(self.cancelled) { - ckksinfo("ckkskey", ckks, "CKKSProcessReceivedKeysOperation cancelled, quitting"); - return; - } - - [ckks dispatchSyncWithAccountKeys: ^bool{ - return [self _onqueueMain:ckks]; + return ok ? CKKSDatabaseTransactionCommit : CKKSDatabaseTransactionRollback; }]; } -- (bool)_onqueueMain:(CKKSKeychainView*)ckks +- (bool)_onqueueMain:(NSArray*)currentTrustStates { - if(self.cancelled) { - ckksinfo("ckkskey", ckks, "CKKSProcessReceivedKeysOperation cancelled, quitting"); - return false; - } - - ckks.lastProcessReceivedKeysOperation = self; - NSError* error = nil; CKKSKey* tlk = nil; CKKSKey* topKey = nil; @@ -81,39 +68,39 @@ // Updates from CloudKit are marked 'remote'; everything else is 'local'. // Step 1. Find all remote keys. - NSArray* remoteKeys = [CKKSKey remoteKeys:ckks.zoneID error:&error]; + NSArray* remoteKeys = [CKKSKey remoteKeys:self.deps.zoneID error:&error]; if(!remoteKeys) { - ckkserror("ckkskey", ckks, "couldn't fetch list of remote keys: %@", error); + ckkserror("ckkskey", self.deps.zoneID, "couldn't fetch list of remote keys: %@", error); self.error = error; self.nextState = SecCKKSZoneKeyStateError; return false; } if([remoteKeys count] == 0u) { - ckksnotice("ckkskey", ckks, "No remote keys? Quitting."); + ckksnotice("ckkskey", self.deps.zoneID, "No remote keys? Quitting."); // Not a ready state, more of a quizzical one? The key state machine will know what to do. self.error = error; - self.nextState = SecCKKSZoneKeyStateReady; + self.nextState = SecCKKSZoneKeyStateBecomeReady; return false; } - ckksinfo("ckkskey", ckks, "remote keys: %@", remoteKeys); + ckksinfo("ckkskey", self.deps.zoneID, "remote keys: %@", remoteKeys); // current TLK record: - CKKSCurrentKeyPointer* currentTLKPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassTLK zoneID:ckks.zoneID error:&error]; - CKKSCurrentKeyPointer* currentClassAPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassA zoneID:ckks.zoneID error:&error]; - CKKSCurrentKeyPointer* currentClassCPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassC zoneID:ckks.zoneID error:&error]; + CKKSCurrentKeyPointer* currentTLKPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassTLK zoneID:self.deps.zoneID error:&error]; + CKKSCurrentKeyPointer* currentClassAPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassA zoneID:self.deps.zoneID error:&error]; + CKKSCurrentKeyPointer* currentClassCPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassC zoneID:self.deps.zoneID error:&error]; // Do these pointers point at anything? NSError* localerror = nil; - CKKSKey* suggestedTLK = currentTLKPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentTLKPointer.currentKeyUUID zoneID:ckks.zoneID error:&localerror] : nil; - CKKSKey* suggestedClassA = currentClassAPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentClassAPointer.currentKeyUUID zoneID:ckks.zoneID error:&localerror] : nil; - CKKSKey* suggestedClassC = currentClassCPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentClassCPointer.currentKeyUUID zoneID:ckks.zoneID error:&localerror] : nil; + CKKSKey* suggestedTLK = currentTLKPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentTLKPointer.currentKeyUUID zoneID:self.deps.zoneID error:&localerror] : nil; + CKKSKey* suggestedClassA = currentClassAPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentClassAPointer.currentKeyUUID zoneID:self.deps.zoneID error:&localerror] : nil; + CKKSKey* suggestedClassC = currentClassCPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentClassCPointer.currentKeyUUID zoneID:self.deps.zoneID error:&localerror] : nil; if(!currentTLKPointer || !currentClassAPointer || !currentClassCPointer || !currentTLKPointer.currentKeyUUID || !currentClassAPointer.currentKeyUUID || !currentClassCPointer.currentKeyUUID || !suggestedTLK || !suggestedClassA || !suggestedClassC) { - ckkserror("ckkskey", ckks, "no current pointer for some keyclass: tlk:%@ a:%@ c:%@ %@ %@", + ckkserror("ckkskey", self.deps.zoneID, "no current pointer for some keyclass: tlk:%@ a:%@ c:%@ %@ %@", currentTLKPointer, currentClassAPointer, currentClassCPointer, error, localerror); self.error = error; self.nextState = SecCKKSZoneKeyStateBadCurrentPointers; @@ -127,7 +114,7 @@ tlk = key; } else { NSError *newError = [NSError errorWithDomain:CKKSErrorDomain code:CKKSKeyNotSelfWrapped description:[NSString stringWithFormat: @"current TLK doesn't wrap itself: %@ %@", key, key.parentKeyUUID] underlying:error]; - ckkserror("ckkskey", ckks, "%@", error); + ckkserror("ckkskey", self.deps.zoneID, "%@", error); self.error = newError; self.nextState = SecCKKSZoneKeyStateUnhealthy; return true; @@ -136,31 +123,33 @@ } if(!tlk) { - ckkserror("ckkskey", ckks, "couldn't find active TLK: %@", currentTLKPointer); + ckkserror("ckkskey", self.deps.zoneID, "couldn't find active TLK: %@", currentTLKPointer); self.error = error; self.nextState = SecCKKSZoneKeyStateUnhealthy; return true; } - // This key is our proposed TLK. Check with the CKKS object. - if(![ckks _onqueueWithAccountKeysCheckTLK: tlk error: &error]) { - // Was this error "I've never seen that TLK before in my life"? If so, enter the "wait for TLK sync" state. - if(error && [error.domain isEqualToString: @"securityd"] && error.code == errSecItemNotFound) { - ckksnotice("ckkskey", ckks, "Received a TLK which we don't have in the local keychain(%@). Entering waitfortlk.", tlk); - self.nextState = SecCKKSZoneKeyStateWaitForTLK; - return true; - } else if(error && [ckks.lockStateTracker isLockedError:error]) { - // TODO: _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError should handle this. But, we don't have tests, so, leave this in until 33204154 - ckksnotice("ckkskey", ckks, "Received a TLK(%@), but keybag appears to be locked. Entering a waiting state.", tlk); + if(![tlk validTLK:&error]) { + // Something has gone horribly wrong. Enter error state. + ckkserror("ckkskey", self.deps.zoneID, "CKKS claims %@ is not a valid TLK: %@", tlk, error); + self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"invalid TLK from CloudKit" underlying:error]; + self.nextState = SecCKKSZoneKeyStateError; + return true; + } + + // This key is our proposed TLK. + if(![tlk tlkMaterialPresentOrRecoverableViaTLKShare:currentTrustStates + error:&error]) { + // TLK is valid, but not present locally + if(error && [self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", self.deps.zoneID, "Received a TLK(%@), but keybag appears to be locked. Entering a waiting state.", tlk); self.nextState = SecCKKSZoneKeyStateWaitForUnlock; - return true; } else { - // Otherwise, something has gone horribly wrong. enter error state. - ckkserror("ckkskey", ckks, "CKKS claims %@ is not a valid TLK: %@", tlk, error); - self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"invalid TLK from CloudKit" underlying:error]; - self.nextState = SecCKKSZoneKeyStateError; - return true; + ckksnotice("ckkskey", self.deps.zoneID, "Received a TLK(%@) which we don't have in the local keychain: %@", tlk, error); + self.error = error; + self.nextState = SecCKKSZoneKeyStateTLKMissing; } + return true; } // Ensure that new keys wrap to the TLK. @@ -172,7 +161,7 @@ topKey = [key topKeyInAnyState:&error]; if(error != nil || ![topKey.uuid isEqual: tlk.uuid]) { - ckkserror("ckkskey", ckks, "new key %@ is orphaned (%@)", key, error); + ckkserror("ckkskey", self.deps.zoneID, "new key %@ is orphaned (%@)", key, error); // TODO: possibly re-fetch. Maybe not an actual error state. self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSOrphanedKey @@ -185,13 +174,13 @@ // Okay, it wraps to the TLK. Can we unwrap it? if(![key unwrapViaKeyHierarchy:&error] || error != nil) { - if(error && [ckks.lockStateTracker isLockedError:error]) { - ckksnotice("ckkskey", ckks, "Couldn't unwrap new key (%@), but keybag appears to be locked. Entering waitforunlock.", key); + if(error && [self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", self.deps.zoneID, "Couldn't unwrap new key (%@), but keybag appears to be locked. Entering waitforunlock.", key); self.error = error; self.nextState = SecCKKSZoneKeyStateWaitForUnlock; return true; } else { - ckkserror("ckkskey", ckks, "new key %@ claims to wrap to TLK, but we can't unwrap it: %@", topKey, error); + ckkserror("ckkskey", self.deps.zoneID, "new key %@ claims to wrap to TLK, but we can't unwrap it: %@", topKey, error); self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSOrphanedKey description:[NSString stringWithFormat:@"unwrappable key(%@) in hierarchy: %@", topKey, error] @@ -201,7 +190,7 @@ } } - ckksnotice("ckkskey", ckks, "New key %@ wraps to tlk %@", key, tlk); + ckksnotice("ckkskey", self.deps.zoneID, "New key %@ wraps to tlk %@", key, tlk); } @@ -218,25 +207,31 @@ [key saveKeyMaterialToKeychain: &error]; + if(error) { - ckkserror("ckkskey", ckks, "couldn't save newly local key %@ to database: %@", key, error); + if([self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", self.deps.zoneID, "Couldn't save newly local key %@ keychain, due to lock state. Entering a waiting state; %@", key, error); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckkserror("ckkskey", self.deps.zoneID, "couldn't save newly local key %@ to database: %@", key, error); + self.nextState = SecCKKSZoneKeyStateError; + } self.error = error; - self.nextState = SecCKKSZoneKeyStateError; return false; } } // New key hierarchy? Get it backed up! // TLKs are now saved in the local keychain; fire off a backup - CKKSNearFutureScheduler* tlkNotifier = ckks.savedTLKNotifier; - ckksnotice("ckkstlk", ckks, "triggering new TLK notification: %@", tlkNotifier); + CKKSNearFutureScheduler* tlkNotifier = self.deps.savedTLKNotifier; + ckksnotice("ckkstlk", self.deps.zoneID, "triggering new TLK notification: %@", tlkNotifier); [tlkNotifier trigger]; if(!error) { - ckksnotice("ckkskey", ckks, "Accepted new key hierarchy"); - self.nextState = SecCKKSZoneKeyStateReady; + ckksnotice("ckkskey", self.deps.zoneID, "Accepted new key hierarchy"); + self.nextState = self.intendedState; } else { - ckkserror("ckkskey", ckks, "error accepting new key hierarchy: %@", error); + ckkserror("ckkskey", self.deps.zoneID, "error accepting new key hierarchy: %@", error); self.error = error; self.nextState = SecCKKSZoneKeyStateError; } @@ -245,29 +240,4 @@ @end; -@implementation CKKSProcessReceivedKeysStateMachineOperation -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks { - if(self = [super init]) { - _ckks = ckks; - } - return self; -} - -- (void)main -{ - CKKSKeychainView* ckks = self.ckks; - - // The following is an abuse of operations, but we need the state machine advancement to be in the same txion as the decision - CKKSProcessReceivedKeysOperation* op = [[CKKSProcessReceivedKeysOperation alloc] initWithCKKSKeychainView:ckks]; - - [ckks dispatchSyncWithAccountKeys:^bool { - bool ret = [op _onqueueMain:ckks]; - ckksnotice("ckkskey", ckks, "Finished processing received keys, moving to state %@", op.nextState); - [ckks _onqueueAdvanceKeyStateMachineToState:op.nextState withError:op.error]; - return ret; - }]; -} - -@end - #endif diff --git a/keychain/ckks/CKKSProvideKeySetOperation.h b/keychain/ckks/CKKSProvideKeySetOperation.h index 5ea8c2fe..f037108e 100644 --- a/keychain/ckks/CKKSProvideKeySetOperation.h +++ b/keychain/ckks/CKKSProvideKeySetOperation.h @@ -23,7 +23,6 @@ NS_ASSUME_NONNULL_BEGIN // But! -timeout: will work, and the operation will finish @interface CKKSProvideKeySetOperation : CKKSGroupOperation - (instancetype)initWithZoneName:(NSString*)zoneName; -- (instancetype)initWithZoneName:(NSString*)zoneName keySet:(CKKSCurrentKeySet*)set; - (void)provideKeySet:(CKKSCurrentKeySet*)keyset; @end diff --git a/keychain/ckks/CKKSProvideKeySetOperation.m b/keychain/ckks/CKKSProvideKeySetOperation.m index 0ea2aa79..a274764a 100644 --- a/keychain/ckks/CKKSProvideKeySetOperation.m +++ b/keychain/ckks/CKKSProvideKeySetOperation.m @@ -5,6 +5,7 @@ @interface CKKSProvideKeySetOperation () @property (nullable) CKKSCurrentKeySet* keyset; +@property dispatch_queue_t queue; @property (nullable) NSOperation* startDependency; @end @@ -19,29 +20,30 @@ _zoneName = zoneName; _keyset = nil; _startDependency = [NSBlockOperation blockOperationWithBlock:^{}]; + _startDependency.name = @"key-set-provided"; + + _queue = dispatch_queue_create("key-set-queue", DISPATCH_QUEUE_SERIAL); [self addDependency:_startDependency]; } return self; } -- (instancetype)initWithZoneName:(NSString*)zoneName keySet:(CKKSCurrentKeySet*)set -{ - if((self = [super init])) { - _zoneName = zoneName; - _keyset = set; - _startDependency = nil; - } - return self; -} - - (void)provideKeySet:(CKKSCurrentKeySet *)keyset { - self.keyset = keyset; - if(self.startDependency) { - [[NSOperationQueue currentQueue] addOperation:self.startDependency]; - self.startDependency = nil; - } + // Ensure that only one keyset is provided through each operation + dispatch_sync(self.queue, ^{ + if(!self.keyset) { + self.keyset = keyset; + if(self.startDependency) { + // Create a new queue here, just to be safe in case someone is waiting + NSOperationQueue* queue = [[NSOperationQueue alloc] init]; + [queue addOperation:self.startDependency]; + self.startDependency = nil; + } + } + }); + } @end diff --git a/keychain/ckks/CKKSRateLimiter.m b/keychain/ckks/CKKSRateLimiter.m index 7eb34b36..9994c922 100644 --- a/keychain/ckks/CKKSRateLimiter.m +++ b/keychain/ckks/CKKSRateLimiter.m @@ -23,7 +23,6 @@ #if OCTAGON #import "CKKSRateLimiter.h" -#import #import typedef NS_ENUM(int, BucketType) { @@ -45,8 +44,7 @@ typedef NS_ENUM(int, BucketType) { } - (instancetype)initWithCoder:(NSCoder *)coder { - self = [super init]; - if (self) { + if ((self = [super init])) { if (coder) { NSDictionary *encoded; encoded = [coder decodeObjectOfClasses:[NSSet setWithObjects:[NSDictionary class], diff --git a/keychain/ckks/CKKSReachabilityTracker.m b/keychain/ckks/CKKSReachabilityTracker.m index d13ecc3c..736a7367 100644 --- a/keychain/ckks/CKKSReachabilityTracker.m +++ b/keychain/ckks/CKKSReachabilityTracker.m @@ -71,7 +71,7 @@ STRONGIFY(self); bool networkAvailable = (nw_path_get_status(path) == nw_path_status_satisfied); - secinfo("ckksnetwork", "nw_path update: network is %@", networkAvailable ? @"available" : @"unavailable"); + ckksinfo_global("ckksnetwork", "nw_path update: network is %@", networkAvailable ? @"available" : @"unavailable"); [self _onqueueSetNetworkReachability:networkAvailable]; }); nw_path_monitor_start(self.networkMonitor); @@ -112,14 +112,14 @@ if(self.reachabilityDependency == nil || ![self.reachabilityDependency isPending]) { WEAKIFY(self); - secnotice("ckksnetwork", "Network unavailable"); + ckksnotice_global("network", "Network unavailable"); self.reachabilityDependency = [CKKSResultOperation named:@"network-available-dependency" withBlock: ^{ STRONGIFY(self); if (self.haveNetwork) { - secnotice("ckksnetwork", "Network available"); + ckksnotice_global("network", "Network available"); } else { - secnotice("ckksnetwork", "Network still not available, retrying after waiting %2.1f hours", - ((float)(REACHABILITY_TIMEOUT/NSEC_PER_SEC)) / 3600); + ckksnotice_global("network", "Network still not available, retrying after waiting %2.1f hours", + ((float)(REACHABILITY_TIMEOUT/NSEC_PER_SEC)) / 3600); } }]; diff --git a/keychain/ckks/CKKSRecordHolder.m b/keychain/ckks/CKKSRecordHolder.m index bb9db913..3ad87f77 100644 --- a/keychain/ckks/CKKSRecordHolder.m +++ b/keychain/ckks/CKKSRecordHolder.m @@ -54,7 +54,7 @@ _encodedCKRecord = encodedCKRecord; if(self.encodedCKRecord && ![self.storedCKRecord.recordID.zoneID isEqual: self.zoneID]) { - secerror("ckks: mismatching zone ids in a single record: %@ and %@", self.zoneID, self.storedCKRecord.recordID.zoneID); + ckkserror("ckks", self.zoneID, "mismatching zone ids in a single record: %@ and %@", self.zoneID, self.storedCKRecord.recordID.zoneID); } } return self; diff --git a/keychain/ckks/CKKSReencryptOutgoingItemsOperation.h b/keychain/ckks/CKKSReencryptOutgoingItemsOperation.h index e8947de5..ae94d53c 100644 --- a/keychain/ckks/CKKSReencryptOutgoingItemsOperation.h +++ b/keychain/ckks/CKKSReencryptOutgoingItemsOperation.h @@ -25,17 +25,23 @@ #import #import #import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@interface CKKSReencryptOutgoingItemsOperation : CKKSResultOperation - +@interface CKKSReencryptOutgoingItemsOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + @end diff --git a/keychain/ckks/CKKSReencryptOutgoingItemsOperation.m b/keychain/ckks/CKKSReencryptOutgoingItemsOperation.m index 6727f3bb..08d9b569 100644 --- a/keychain/ckks/CKKSReencryptOutgoingItemsOperation.m +++ b/keychain/ckks/CKKSReencryptOutgoingItemsOperation.m @@ -25,6 +25,7 @@ #import "keychain/ckks/CKKSKeychainView.h" #import "keychain/ckks/CKKSCurrentKeyPointer.h" #import "keychain/ckks/CKKSKey.h" +#import "keychain/ckks/CKKSMemoryKeyCache.h" #import "keychain/ckks/CKKSOutgoingQueueEntry.h" #import "keychain/ckks/CKKSReencryptOutgoingItemsOperation.h" #import "keychain/ckks/CKKSItemEncrypter.h" @@ -37,40 +38,44 @@ // Note: reencryption is not, strictly speaking, a CloudKit operation. However, we preserve this to pass it back to the outgoing queue operation we'll create @interface CKKSReencryptOutgoingItemsOperation () -@property CKOperationGroup* ckoperationGroup; @end @implementation CKKSReencryptOutgoingItemsOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ if(self = [super init]) { + _deps = dependencies; _ckks = ckks; - _ckoperationGroup = ckoperationGroup; + + _nextState = errorState; + _intendedState = intendedState; [self addNullableDependency:ckks.keyStateReadyDependency]; [self addNullableDependency:ckks.holdReencryptOutgoingItemsOperation]; // We also depend on the key hierarchy being reasonable [self addNullableDependency:ckks.keyStateReadyDependency]; - } return self; } -- (void) main { +- (void)main +{ CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksreencrypt", ckks, "no CKKS object"); - return; - } - [ckks dispatchSync: ^bool{ + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { - ckksnotice("ckksreencrypt", ckks, "CKKSReencryptOutgoingItemsOperation cancelled, quitting"); - return false; + ckksnotice("ckksreencrypt", self.deps.zoneID, "CKKSReencryptOutgoingItemsOperation cancelled, quitting"); + return CKKSDatabaseTransactionRollback; } ckks.lastReencryptOutgoingItemsOperation = self; @@ -78,30 +83,32 @@ NSError* error = nil; bool newItems = false; - NSArray* oqes = [CKKSOutgoingQueueEntry allInState: SecCKKSStateReencrypt zoneID:ckks.zoneID error:&error]; + NSArray* oqes = [CKKSOutgoingQueueEntry allInState:SecCKKSStateReencrypt zoneID:self.deps.zoneID error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Error fetching oqes from database: %@", error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Error fetching oqes from database: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventReencryptOutgoing zone:ckks.zoneName count:oqes.count]; + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventReencryptOutgoing zone:self.deps.zoneID.zoneName count:oqes.count]; + + CKKSMemoryKeyCache* keyCache = [[CKKSMemoryKeyCache alloc] init]; for(CKKSOutgoingQueueEntry* oqe in oqes) { // If there's already a 'new' item replacing this one, drop the reencryption on the floor CKKSOutgoingQueueEntry* newOQE = [CKKSOutgoingQueueEntry tryFromDatabase:oqe.uuid state:SecCKKSStateNew zoneID:oqe.item.zoneID error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't load 'new' OQE to determine status: %@", error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't load 'new' OQE to determine status: %@", error); self.error = error; error = nil; continue; } if(newOQE) { - ckksnotice("ckksreencrypt", ckks, "Have a new OQE superceding %@ (%@), skipping", oqe, newOQE); + ckksnotice("ckksreencrypt", self.deps.zoneID, "Have a new OQE superceding %@ (%@), skipping", oqe, newOQE); // Don't use the state transition here, either, since this item isn't really changing states [oqe deleteFromDatabase:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't delete reencrypting OQE(%@) from database: %@", oqe, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't delete reencrypting OQE(%@) from database: %@", oqe, error); self.error = error; error = nil; continue; @@ -109,15 +116,17 @@ continue; } - ckksnotice("ckksreencrypt", ckks, "Reencrypting item %@", oqe); + ckksnotice("ckksreencrypt", self.deps.zoneID, "Reencrypting item %@", oqe); - NSDictionary* item = [CKKSItemEncrypter decryptItemToDictionary: oqe.item error:&error]; + + NSDictionary* item = [CKKSItemEncrypter decryptItemToDictionary:oqe.item keyCache:keyCache error:&error]; if(error) { if ([error.domain isEqualToString:@"securityd"] && error.code == errSecItemNotFound) { - ckkserror("ckksreencrypt", ckks, "Couldn't find key in keychain; attempting to poke key hierarchy: %@", error); - [ckks.pokeKeyStateMachineScheduler trigger]; + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't find key in keychain; asking for reset: %@", error); + [ckks _onqueuePokeKeyStateMachine]; + self.nextState = SecCKKSZoneKeyStateUnhealthy; } else { - ckkserror("ckksreencrypt", ckks, "Couldn't decrypt item %@: %@", oqe, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't decrypt item %@: %@", oqe, error); } self.error = error; error = nil; @@ -125,26 +134,26 @@ } // Pick a key whose class matches the keyclass that this item - CKKSKey* originalKey = [CKKSKey fromDatabase: oqe.item.parentKeyUUID zoneID:ckks.zoneID error:&error]; + CKKSKey* originalKey = [keyCache loadKeyForUUID:oqe.item.parentKeyUUID zoneID:self.deps.zoneID error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't fetch key (%@) for item %@: %@", oqe.item.parentKeyUUID, oqe, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't fetch key (%@) for item %@: %@", oqe.item.parentKeyUUID, oqe, error); self.error = error; error = nil; continue; } - CKKSKey* newkey = [CKKSKey currentKeyForClass: originalKey.keyclass zoneID:ckks.zoneID error:&error]; + CKKSKey* newkey = [keyCache currentKeyForClass:originalKey.keyclass zoneID:self.deps.zoneID error:&error]; [newkey ensureKeyLoaded: &error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't fetch the current key for class %@: %@", originalKey.keyclass, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't fetch the current key for class %@: %@", originalKey.keyclass, error); self.error = error; error = nil; continue; } - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:oqe.item.uuid zoneID:ckks.zoneID error:&error]; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:oqe.item.uuid zoneID:self.deps.zoneID error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't fetch ckme (%@) for item %@: %@", oqe.item.parentKeyUUID, oqe, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't fetch ckme (%@) for item %@: %@", oqe.item.parentKeyUUID, oqe, error); self.error = error; error = nil; continue; @@ -154,10 +163,11 @@ dataDictionary:item updatingCKKSItem:ckme.item parentkey:newkey + keyCache:keyCache error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't encrypt under the new key %@: %@", newkey, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't encrypt under the new key %@: %@", newkey, error); self.error = error; error = nil; continue; @@ -173,7 +183,7 @@ [oqe deleteFromDatabase:&error]; [replacement saveToDatabase:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't save newly-encrypted oqe %@: %@", replacement, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't save newly-encrypted oqe %@: %@", replacement, error); self.error = error; error = nil; continue; @@ -184,14 +194,15 @@ CKKSAnalytics* logger = [CKKSAnalytics logger]; if (self.error) { - [logger logRecoverableError:error forEvent:CKKSEventProcessReencryption inView:ckks withAttributes:nil]; + [logger logRecoverableError:error forEvent:CKKSEventProcessReencryption zoneName:self.deps.zoneID.zoneName withAttributes:nil]; } else { - [logger logSuccessForEvent:CKKSEventProcessReencryption inView:ckks]; + [logger logSuccessForEvent:CKKSEventProcessReencryption zoneName:self.deps.zoneID.zoneName ]; } if(newItems) { - [ckks processOutgoingQueue:self.ckoperationGroup]; + [ckks processOutgoingQueue:self.deps.ckoperationGroup]; } + self.nextState = self.intendedState; return true; }]; } diff --git a/keychain/ckks/CKKSResultOperation.h b/keychain/ckks/CKKSResultOperation.h index 5b29fccc..318f3665 100644 --- a/keychain/ckks/CKKSResultOperation.h +++ b/keychain/ckks/CKKSResultOperation.h @@ -45,7 +45,7 @@ enum { @property (nullable) NSDate* finishDate; @property CKKSCondition* completionHandlerDidRunCondition; -@property NSInteger descriptionErrorCode; // Set to non-0 for inclusion of this operation in NSError chains. Code is application-dependent. +@property NSInteger descriptionErrorCode; // Set to non-0 for inclusion of this operation in NSError chains. Code is application-dependent, but will be -1 in cases of excessive recursion. // If you subclass CKKSResultOperation, this is the method corresponding to descriptionErrorCode. Fill it in to your heart's content. - (NSError* _Nullable)descriptionError; diff --git a/keychain/ckks/CKKSResultOperation.m b/keychain/ckks/CKKSResultOperation.m index 57417657..8228f0e6 100644 --- a/keychain/ckks/CKKSResultOperation.m +++ b/keychain/ckks/CKKSResultOperation.m @@ -28,7 +28,7 @@ #import "keychain/ckks/CKKSCondition.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "keychain/ot/ObjCImprovements.h" -#include +#import "keychain/ckks/CKKS.h" @interface CKKSResultOperation() @property NSMutableArray* successDependencies; @@ -92,7 +92,7 @@ [super setCompletionBlock:^(void) { STRONGIFY(self); if (!self) { - secerror("ckksresultoperation: completion handler called on deallocated operation instance"); + ckkserror_global("resultoperation", "completion handler called on deallocated operation instance"); completionBlock(); // go ahead and still behave as things would if this method override were not here return; } @@ -149,16 +149,31 @@ // Returns, for this CKKSResultOperation, an error describing this operation or its dependents. // Used mainly by other CKKSResultOperations who time out waiting for this operation to start/complete. - (NSError* _Nullable)descriptionError { + static __thread unsigned __descriptionRecursion = 0; + + NSError* result = nil; + + __descriptionRecursion += 1; + if(self.descriptionErrorCode != 0) { - return [NSError errorWithDomain:CKKSResultDescriptionErrorDomain - code:self.descriptionErrorCode - userInfo:nil]; + result = [NSError errorWithDomain:CKKSResultDescriptionErrorDomain + code:self.descriptionErrorCode + userInfo:nil]; + } else if(__descriptionRecursion > 10) { + result = [NSError errorWithDomain:CKKSResultDescriptionErrorDomain + code:-1 + description:@"Excess recursion"]; } else { - return [self dependenciesDescriptionError]; + result = [self dependenciesDescriptionError]; } + + __descriptionRecursion -= 1; + + return result; } - (NSError*)_onqueueTimeoutError { + dispatch_assert_queue(self.timeoutQueue); // Find if any of our dependencies are CKKSResultOperations with a custom reason for existing NSError* underlyingReason = [self descriptionError]; diff --git a/keychain/ckks/CKKSSIV.h b/keychain/ckks/CKKSSIV.h index 718954e8..3b9e492a 100644 --- a/keychain/ckks/CKKSSIV.h +++ b/keychain/ckks/CKKSSIV.h @@ -52,6 +52,9 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithData:(NSData*)data; - (NSData*)wrappedData; - (NSString*)base64WrappedKey; + +// Almost certainly not a valid key; use if you need a placeholder ++ (CKKSWrappedAESSIVKey*)zeroedKey; @end @interface CKKSAESSIVKey : CKKSBaseAESSIVKey @@ -71,6 +74,9 @@ NS_ASSUME_NONNULL_BEGIN authenticatedData:(NSDictionary* _Nullable)ad error:(NSError* __autoreleasing*)error; +// Please only call this if you're storing this key to the keychain, or sending it to a peer. +- (NSData*)keyMaterial; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSSIV.m b/keychain/ckks/CKKSSIV.m index dde5f3c1..7388162c 100644 --- a/keychain/ckks/CKKSSIV.m +++ b/keychain/ckks/CKKSSIV.m @@ -155,8 +155,7 @@ } - (nullable instancetype)initWithCoder:(nonnull NSCoder *)decoder { - self = [super init]; - if (self) { + if ((self = [super init])) { NSUInteger len = 0; const uint8_t * bytes = [decoder decodeBytesForKey:@"wrappedkey" returnedLength:&len]; @@ -167,6 +166,12 @@ return self; } ++ (CKKSWrappedAESSIVKey*)zeroedKey +{ + NSData* zeroedData = [NSMutableData dataWithLength:CKKSWrappedKeySize]; + return [[CKKSWrappedAESSIVKey alloc] initWithData:zeroedData]; +} + @end @implementation CKKSAESSIVKey @@ -427,6 +432,11 @@ out: return localerror == NULL; } +- (NSData*)keyMaterial +{ + return [NSData _newZeroingDataWithBytes:self->key length:self->size]; +} + @end diff --git a/keychain/ckks/CKKSSQLDatabaseObject.h b/keychain/ckks/CKKSSQLDatabaseObject.h index 85f6ad5c..c8579763 100644 --- a/keychain/ckks/CKKSSQLDatabaseObject.h +++ b/keychain/ckks/CKKSSQLDatabaseObject.h @@ -53,6 +53,26 @@ NS_ASSUME_NONNULL_BEGIN - (NSData* _Nullable)asBase64DecodedData; @end +// These thread-local variables should be set by your database layer +// This ensures that all SQL write operations are performed under the protection of a transaction. +// Use [CKKSSQLDatabaseObject +performCKKSTransaction] to get one of these if you don't have any other mechanism. +extern __thread bool CKKSSQLInTransaction; +extern __thread bool CKKSSQLInWriteTransaction; + +typedef NS_ENUM(uint8_t, CKKSDatabaseTransactionResult) { + CKKSDatabaseTransactionRollback = 0, + CKKSDatabaseTransactionCommit = 1, +}; + +// A database provider must provide these operations. +@protocol CKKSDatabaseProviderProtocol +- (void)dispatchSyncWithSQLTransaction:(CKKSDatabaseTransactionResult (^)(void))block; +- (void)dispatchSyncWithReadOnlySQLTransaction:(void (^)(void))block; + +// Used to maintain lock ordering. +- (BOOL)insideSQLTransaction; +@end + @interface CKKSSQLDatabaseObject : NSObject @property (copy) NSDictionary* originalSelfWhereClause; @@ -114,6 +134,8 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *)quotedString:(NSString *)string; ++ (BOOL)performCKKSTransaction:(CKKSDatabaseTransactionResult (^)(void))block; + #pragma mark - Subclasses must implement the following: // Given a row from the database, make this object @@ -135,13 +157,46 @@ NS_ASSUME_NONNULL_BEGIN @end // Helper class to use with where clauses -// If you pass in one of these instead of a concrete value, its substring will be used directly, instead of binding the value as a named parameter -@interface CKKSSQLWhereObject : NSObject -@property NSString* sqlOp; -@property NSString* contents; -- (instancetype)initWithOperation:(NSString*)op string:(NSString*)str; -+ (instancetype)op:(NSString*)op string:(NSString*)str; -+ (instancetype)op:(NSString*)op stringValue:(NSString*)str; // Will add single quotes around your value. +// If you pass in one of these in a where dictionary instead of a concrete value, columnName will be +// used directly, instead of binding as a named parameter. Therefore, it's essential to use +// compile-time constants for both fields. + +typedef NS_ENUM(uint64_t, CKKSSQLWhereComparator) { + CKKSSQLWhereComparatorEquals = 1, + CKKSSQLWhereComparatorNotEquals = 2, + CKKSSQLWhereComparatorGreaterThan = 3, + CKKSSQLWhereComparatorLessThan = 4, +}; + +NSString* CKKSSQLWhereComparatorAsString(CKKSSQLWhereComparator comparator); + +// This typedef is to ensure that CKKSSQLWhereColumn can only ever produce static strings +typedef NS_ENUM(uint64_t, CKKSSQLWhereColumnName) { + CKKSSQLWhereColumnNameUUID = 1, + CKKSSQLWhereColumnNameParentKeyUUID = 2, +}; +NSString* CKKSSQLWhereColumnNameAsString(CKKSSQLWhereColumnName columnName); + +@interface CKKSSQLWhereColumn : NSObject +@property CKKSSQLWhereComparator sqlOp; +@property CKKSSQLWhereColumnName columnName; +- (instancetype)initWithOperation:(CKKSSQLWhereComparator)op columnName:(CKKSSQLWhereColumnName)column; ++ (instancetype)op:(CKKSSQLWhereComparator)op column:(CKKSSQLWhereColumnName)columnName; @end +// Unlike CKKSSQLWhereColumn, this will insert the value as a parameter in a prepared statement +// but gives you the flexbility to inject a sqlOp. sqlOp must be a compile-time constant. +@interface CKKSSQLWhereValue : NSObject +@property CKKSSQLWhereComparator sqlOp; +@property NSString* value; +- (instancetype)initWithOperation:(CKKSSQLWhereComparator)op value:(NSString*)value; ++ (instancetype)op:(CKKSSQLWhereComparator)op value:(NSString*)value; +@end + +@interface CKKSSQLWhereIn : NSObject +@property NSArray* values; +- (instancetype)initWithValues:(NSArray*)values; +@end + + NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSSQLDatabaseObject.m b/keychain/ckks/CKKSSQLDatabaseObject.m index 356424cc..55b1dc24 100644 --- a/keychain/ckks/CKKSSQLDatabaseObject.m +++ b/keychain/ckks/CKKSSQLDatabaseObject.m @@ -24,6 +24,7 @@ #import #import "CKKSSQLDatabaseObject.h" #include "keychain/securityd/SecItemServer.h" +#include "keychain/securityd/SecItemDb.h" #import "keychain/ckks/CKKS.h" #import "CKKSKeychainView.h" @@ -83,11 +84,19 @@ } @end +__thread bool CKKSSQLInTransaction = false; +__thread bool CKKSSQLInWriteTransaction = false; + @implementation CKKSSQLDatabaseObject + (bool) saveToDatabaseTable: (NSString*) table row: (NSDictionary*) row connection: (SecDbConnectionRef) dbconn error: (NSError * __autoreleasing *) error { __block CFErrorRef cferror = NULL; +#if DEBUG + NSAssert(CKKSSQLInTransaction, @"Must be in a transaction to perform database writes"); + NSAssert(CKKSSQLInWriteTransaction, @"Must be in a write transaction to perform database writes"); +#endif + bool (^doWithConnection)(SecDbConnectionRef) = ^bool (SecDbConnectionRef dbconn) { NSString * columns = [row.allKeys componentsJoinedByString:@", "]; NSMutableString * values = [[NSMutableString alloc] init]; @@ -140,10 +149,30 @@ [whereClause appendFormat: @" AND "]; } - if([value class] == [CKKSSQLWhereObject class]) { - // Use this string verbatim - CKKSSQLWhereObject* whereob = (CKKSSQLWhereObject*) value; - [whereClause appendFormat: @"%@%@%@", key, whereob.sqlOp, whereob.contents]; + if([value class] == [CKKSSQLWhereValue class]) { + CKKSSQLWhereValue* obj = (CKKSSQLWhereValue*)value; + [whereClause appendFormat: @"%@%@(?)", key, CKKSSQLWhereComparatorAsString(obj.sqlOp)]; + + } else if([value class] == [CKKSSQLWhereColumn class]) { + CKKSSQLWhereColumn* obj = (CKKSSQLWhereColumn*)value; + [whereClause appendFormat: @"%@%@%@", + key, + CKKSSQLWhereComparatorAsString(obj.sqlOp), + CKKSSQLWhereColumnNameAsString(obj.columnName)]; + + } else if([value isMemberOfClass:[CKKSSQLWhereIn class]]) { + CKKSSQLWhereIn* obj = (CKKSSQLWhereIn*)value; + + NSMutableArray* q = [NSMutableArray arrayWithCapacity:obj.values.count]; + for(NSString* value in obj.values) { + [q addObject: @"?"]; + (void)value; + } + + NSString* binds = [q componentsJoinedByString:@", "]; + + [whereClause appendFormat:@"%@ IN (%@)", key, binds]; + } else { [whereClause appendFormat: @"%@=(?)", key]; } @@ -193,23 +222,47 @@ return orderByClause; } ++ (void)bindWhereClause:(sqlite3_stmt*)stmt whereDict:(NSDictionary*)whereDict cferror:(CFErrorRef*)cferror +{ + __block int whereLocation = 1; + + [whereDict.allKeys enumerateObjectsUsingBlock:^(id _Nonnull key, NSUInteger i, BOOL * _Nonnull stop) { + if([whereDict[key] class] == [CKKSSQLWhereValue class]) { + CKKSSQLWhereValue* obj = (CKKSSQLWhereValue*)whereDict[key]; + SecDbBindObject(stmt, whereLocation, (__bridge CFStringRef)obj.value, cferror); + whereLocation++; + + } else if([whereDict[key] class] == [CKKSSQLWhereColumn class]) { + // skip + } else if([whereDict[key] isMemberOfClass:[CKKSSQLWhereIn class]]) { + CKKSSQLWhereIn* obj = (CKKSSQLWhereIn*)whereDict[key]; + + for(NSString* value in obj.values) { + SecDbBindObject(stmt, whereLocation, (__bridge CFStringRef)value, cferror); + whereLocation++; + } + + } else { + SecDbBindObject(stmt, whereLocation, (__bridge CFStringRef) whereDict[key], cferror); + whereLocation++; + } + }]; +} + + (bool) deleteFromTable: (NSString*) table where: (NSDictionary*) whereDict connection:(SecDbConnectionRef) dbconn error: (NSError * __autoreleasing *) error { __block CFErrorRef cferror = NULL; +#if DEBUG + NSAssert(CKKSSQLInTransaction, @"Must be in a transaction to perform database writes"); + NSAssert(CKKSSQLInWriteTransaction, @"Must be in a write transaction to perform database writes"); +#endif + bool (^doWithConnection)(SecDbConnectionRef) = ^bool (SecDbConnectionRef dbconn) { NSString* whereClause = [CKKSSQLDatabaseObject makeWhereClause: whereDict]; NSString * sql = [[NSString alloc] initWithFormat: @"DELETE FROM %@%@;", table, whereClause]; SecDbPrepare(dbconn, (__bridge CFStringRef) sql, &cferror, ^void (sqlite3_stmt *stmt) { - __block int whereObjectsSkipped = 0; - - [whereDict.allKeys enumerateObjectsUsingBlock:^(id _Nonnull key, NSUInteger i, BOOL * _Nonnull stop) { - if([whereDict[key] class] != [CKKSSQLWhereObject class]) { - SecDbBindObject(stmt, (int)(i+1-whereObjectsSkipped), (__bridge CFStringRef) whereDict[key], &cferror); - } else { - whereObjectsSkipped += 1; - } - }]; + [self bindWhereClause:stmt whereDict:whereDict cferror:&cferror]; SecDbStep(dbconn, stmt, &cferror, ^(bool *stop) { }); @@ -254,14 +307,7 @@ NSString * sql = [[NSString alloc] initWithFormat: @"SELECT %@ FROM %@%@%@%@%@;", columns, table, whereClause, groupByClause, orderByClause, limitClause]; SecDbPrepare(dbconn, (__bridge CFStringRef) sql, &cferror, ^void (sqlite3_stmt *stmt) { - __block int whereObjectsSkipped = 0; - [whereDict.allKeys enumerateObjectsUsingBlock:^(id _Nonnull key, NSUInteger i, BOOL * _Nonnull stop) { - if([whereDict[key] class] != [CKKSSQLWhereObject class]) { - SecDbBindObject(stmt, (int)(i+1-whereObjectsSkipped), (__bridge CFStringRef) whereDict[key], &cferror); - } else { - whereObjectsSkipped += 1; - } - }]; + [self bindWhereClause:stmt whereDict:whereDict cferror:&cferror]; SecDbStep(dbconn, stmt, &cferror, ^(bool *stop) { __block NSMutableDictionary* row = [[NSMutableDictionary alloc] init]; @@ -315,11 +361,7 @@ NSString* sql = [[NSString alloc] initWithFormat:@"SELECT %@ FROM %@%@", columns, quotedTable, whereClause]; SecDbPrepare(dbconn, (__bridge CFStringRef)sql, &cferror, ^(sqlite3_stmt* stmt) { - [whereDict.allKeys enumerateObjectsUsingBlock:^(id _Nonnull key, NSUInteger i, BOOL* _Nonnull stop) { - if ([whereDict[key] class] != [CKKSSQLWhereObject class]) { - SecDbBindObject(stmt, (int)(i+1), (__bridge CFStringRef) whereDict[key], &cferror); - } - }]; + [self bindWhereClause:stmt whereDict:whereDict cferror:&cferror]; SecDbStep(dbconn, stmt, &cferror, ^(bool*stop) { __block NSMutableDictionary* row = [[NSMutableDictionary alloc] init]; @@ -340,6 +382,60 @@ return ret; } ++ (BOOL)performCKKSTransaction:(CKKSDatabaseTransactionResult (^)(void))block +{ + CFErrorRef cferror = NULL; + bool ok = kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbconn) { + CFErrorRef cferrorInternal = NULL; + bool ret = kc_transaction_type(dbconn, kSecDbExclusiveRemoteCKKSTransactionType, &cferrorInternal, ^bool{ + CKKSDatabaseTransactionResult result = CKKSDatabaseTransactionRollback; + + CKKSSQLInTransaction = true; + CKKSSQLInWriteTransaction = true; + result = block(); + CKKSSQLInWriteTransaction = false; + CKKSSQLInTransaction = false; + return result == CKKSDatabaseTransactionCommit; + }); + if(cferrorInternal) { + ckkserror_global("ckkssql", "error performing database transaction, major problems ahead: %@", cferrorInternal); + } + CFReleaseNull(cferrorInternal); + return ret; + }); + + if(cferror) { + ckkserror_global("ckkssql", "error performing database operation, major problems ahead: %@", cferror); + } + CFReleaseNull(cferror); + return ok; +} + ++ (BOOL)performCKKSReadonlyTransaction:(void(^)(void))block +{ + CFErrorRef cferror = NULL; + bool ok = kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbconn) { + CFErrorRef cferrorInternal = NULL; + bool ret = kc_transaction_type(dbconn, kSecDbNormalTransactionType, &cferrorInternal, ^bool{ + CKKSSQLInTransaction = true; + block(); + CKKSSQLInTransaction = false; + return true; + }); + if(cferrorInternal) { + ckkserror_global("ckkssql", "error performing database transaction, major problems ahead: %@", cferrorInternal); + } + CFReleaseNull(cferrorInternal); + return ret; + }); + + if(cferror) { + ckkserror_global("ckkssql", "error performing database operation, major problems ahead: %@", cferror); + } + CFReleaseNull(cferror); + return ok; +} + #pragma mark - Instance methods - (bool) saveToDatabase: (NSError * __autoreleasing *) error { @@ -517,24 +613,73 @@ } @end -#pragma mark - CKKSSQLWhereObject +NSString* CKKSSQLWhereComparatorAsString(CKKSSQLWhereComparator comparator) +{ + switch(comparator) { + case CKKSSQLWhereComparatorEquals: + return @"="; + case CKKSSQLWhereComparatorNotEquals: + return @"<>"; + case CKKSSQLWhereComparatorGreaterThan: + return @">"; + case CKKSSQLWhereComparatorLessThan: + return @"<"; + } +} -@implementation CKKSSQLWhereObject -- (instancetype)initWithOperation:(NSString*)op string: (NSString*) str { - if(self = [super init]) { +NSString* CKKSSQLWhereColumnNameAsString(CKKSSQLWhereColumnName columnName) +{ + switch(columnName) { + case CKKSSQLWhereColumnNameUUID: + return @"uuid"; + case CKKSSQLWhereColumnNameParentKeyUUID: + return @"parentKeyUUID"; + } +} + +#pragma mark - CKKSSQLWhereColumn + +@implementation CKKSSQLWhereColumn +- (instancetype)initWithOperation:(CKKSSQLWhereComparator)op columnName:(CKKSSQLWhereColumnName)column +{ + if((self = [super init])) { _sqlOp = op; - _contents = str; + _columnName = column; } return self; } - -+ (instancetype)op:(NSString*) op string: (NSString*) str { - return [[CKKSSQLWhereObject alloc] initWithOperation:op string: str]; ++ (instancetype)op:(CKKSSQLWhereComparator)op column:(CKKSSQLWhereColumnName)columnName +{ + return [[CKKSSQLWhereColumn alloc] initWithOperation:op columnName:columnName]; +} +@end + +#pragma mark - CKKSSQLWhereObject + +@implementation CKKSSQLWhereValue +- (instancetype)initWithOperation:(CKKSSQLWhereComparator)op value:(NSString*)value +{ + if((self = [super init])) { + _sqlOp = op; + _value = value; + } + return self; +} ++ (instancetype)op:(CKKSSQLWhereComparator)op value:(NSString*)value +{ + return [[CKKSSQLWhereValue alloc] initWithOperation:op value:value]; + +} +@end + +#pragma mark - CKKSSQLWhereIn + +@implementation CKKSSQLWhereIn : NSObject +- (instancetype)initWithValues:(NSArray*)values +{ + if((self = [super init])) { + _values = values; + } + return self; } - -+ (instancetype)op:(NSString*) op stringValue: (NSString*) str { - return [[CKKSSQLWhereObject alloc] initWithOperation:op string:[NSString stringWithFormat:@"'%@'", str]]; -} - - @end diff --git a/keychain/ckks/CKKSScanLocalItemsOperation.h b/keychain/ckks/CKKSScanLocalItemsOperation.h index a35a240d..3b1f930a 100644 --- a/keychain/ckks/CKKSScanLocalItemsOperation.h +++ b/keychain/ckks/CKKSScanLocalItemsOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2016-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,16 +23,20 @@ #import -#import "keychain/ckks/CKKSGroupOperation.h" - #if OCTAGON +#import "keychain/ckks/CKKSResultOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@class CKKSEgoManifest; -@interface CKKSScanLocalItemsOperation : CKKSResultOperation +@interface CKKSScanLocalItemsOperation : CKKSResultOperation +@property (nullable) CKOperationGroup* ckoperationGroup; + +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; @property size_t recordsFound; @@ -41,8 +45,11 @@ NS_ASSUME_NONNULL_BEGIN @property size_t missingLocalItemsFound; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; - +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState + ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSScanLocalItemsOperation.m b/keychain/ckks/CKKSScanLocalItemsOperation.m index 7d285ad6..134abab8 100644 --- a/keychain/ckks/CKKSScanLocalItemsOperation.m +++ b/keychain/ckks/CKKSScanLocalItemsOperation.m @@ -22,6 +22,9 @@ */ #if OCTAGON +#import +#import +#import #import "keychain/ckks/CKKSAnalytics.h" #import "keychain/ckks/CKKSKeychainView.h" @@ -32,9 +35,11 @@ #import "keychain/ckks/CKKSOutgoingQueueEntry.h" #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ckks/CKKSKey.h" +#import "keychain/ckks/CKKSMemoryKeyCache.h" #import "keychain/ckks/CKKSViewManager.h" -#import "keychain/ckks/CKKSManifest.h" #import "keychain/ckks/CKKSItemEncrypter.h" +#import "keychain/ckks/CKKSStates.h" +#import "keychain/ckks/CKKSZoneStateEntry.h" #import "CKKSPowerCollection.h" @@ -47,305 +52,532 @@ #import @interface CKKSScanLocalItemsOperation () -@property CKOperationGroup* ckoperationGroup; @property (assign) NSUInteger processedItems; + +@property BOOL newCKKSEntries; @end @implementation CKKSScanLocalItemsOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { - if(self = [super init]) { +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState + ckoperationGroup:(CKOperationGroup*)ckoperationGroup +{ + if((self = [super init])) { + _deps = dependencies; _ckks = ckks; _ckoperationGroup = ckoperationGroup; + + _nextState = errorState; + _intendedState = intendedState; + _recordsFound = 0; _recordsAdded = 0; } return self; } -- (void) main { - // Take a strong reference. - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksscan", ckks, "no CKKS object"); +- (NSDictionary*)queryPredicatesForViewMapping { + TPPBPolicyKeyViewMapping* viewRule = nil; + + // If there's more than one rule matching this view, then exit with an empty dictionary: the language doesn't support ORs. + for(TPPBPolicyKeyViewMapping* mapping in [CKKSViewManager manager].policy.keyViewMapping) { + if([mapping.view isEqualToString:self.deps.zoneID.zoneName]) { + if(viewRule == nil) { + viewRule = mapping; + } else { + // Too many rules for this view! Don't perform optimization. + ckksnotice("ckksscan", self.deps.zoneID, "Too many policy rules for view %@", self.deps.zoneID.zoneName); + return @{}; + } + } + } + + if(viewRule.hasMatchingRule && + viewRule.matchingRule.andsCount == 0 && + viewRule.matchingRule.orsCount == 0 && + !viewRule.matchingRule.hasNot && + !viewRule.matchingRule.hasExists && + viewRule.matchingRule.hasMatch) { + if([((id)kSecAttrSyncViewHint) isEqualToString:viewRule.matchingRule.match.fieldName] && + [viewRule.matchingRule.match.regex isEqualToString:[NSString stringWithFormat:@"^%@$", self.deps.zoneID.zoneName]]) { + return @{ + (id)kSecAttrSyncViewHint: self.deps.zoneID.zoneName, + }; + } else if([((id)kSecAttrAccessGroup) isEqualToString:viewRule.matchingRule.match.fieldName] && + [viewRule.matchingRule.match.regex isEqualToString:@"^com\\.apple\\.cfnetwork$"]) { + // We can't match on any regex agrp match, because it might be some actually difficult regex. But, we know about this one! + return @{ + (id)kSecAttrAccessGroup: @"com.apple.cfnetwork", + }; + + } else if([((id)kSecAttrAccessGroup) isEqualToString:viewRule.matchingRule.match.fieldName] && + [viewRule.matchingRule.match.regex isEqualToString:@"^com\\.apple\\.safari\\.credit-cards$"]) { + // We can't match on any regex agrp match, because it might be some actually difficult regex. But, we know about this one! + return @{ + (id)kSecAttrAccessGroup: @"com.apple.safari.credit-cards", + }; + + } else { + ckksnotice("ckksscan", self.deps.zoneID, "Policy view rule is not a match against viewhint: %@", viewRule); + } + } else { + ckksnotice("ckksscan", self.deps.zoneID, "Policy view rule is complex: %@", viewRule); + } + + return @{}; +} + +- (BOOL)executeQuery:(NSDictionary*)queryPredicates readWrite:(bool)readWrite error:(NSError**)error block:(void (^_Nonnull)(SecDbItemRef item))block +{ + __block CFErrorRef cferror = NULL; + __block bool ok = false; + + Query *q = query_create_with_limit((__bridge CFDictionaryRef)queryPredicates, NULL, kSecMatchUnlimited, NULL, &cferror); + + if(cferror) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't create query: %@", cferror); + SecTranslateError(error, cferror); + return NO; + } + + ok = kc_with_dbt(readWrite, &cferror, ^(SecDbConnectionRef dbt) { + return SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef item, bool *stop) { + block(item); + }); + }); + + if(readWrite) { + ok = query_notify_and_destroy(q, ok, &cferror); + } else { + ok = query_destroy(q, &cferror); + } + + if(cferror || !ok) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't execute query: %@", cferror); + SecTranslateError(error, cferror); + return NO; + } + + return YES; +} + +- (BOOL)onboardItemToCKKS:(SecDbItemRef)item + keyCache:(CKKSMemoryKeyCache*)keyCache + error:(NSError**)error +{ + NSError* itemSaveError = nil; + + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry withItem:item + action:SecCKKSActionAdd + zoneID:self.deps.zoneID + keyCache:keyCache + error:&itemSaveError]; + + if(itemSaveError) { + ckkserror("ckksscan", self.deps.zoneID, "Need to upload %@, but can't create outgoing entry: %@", item, itemSaveError); + if(error) { + *error = itemSaveError; + } + return NO; + } + + ckksnotice("ckksscan", self.deps.zoneID, "Syncing new item: %@", oqe); + + [oqe saveToDatabase:&itemSaveError]; + if(itemSaveError) { + ckkserror("ckksscan", self.deps.zoneID, "Need to upload %@, but can't save to database: %@", oqe, itemSaveError); + self.error = itemSaveError; + return NO; + } + + self.newCKKSEntries = true; + self.recordsAdded += 1; + + return YES; +} + +- (void)onboardItemsWithUUIDs:(NSSet*)uuids itemClass:(NSString*)itemClass databaseProvider:(id)databaseProvider +{ + ckksnotice("ckksscan", self.deps.zoneID, "Found %d missing %@ items", (int)uuids.count, itemClass); + // Use one transaction for each item to allow for SecItem API calls to interleave + for(NSString* itemUUID in uuids) { + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult { + CKKSMemoryKeyCache* keyCache = [[CKKSMemoryKeyCache alloc] init]; + + NSDictionary* queryAttributes = @{ + (id)kSecClass: itemClass, + (id)kSecReturnRef: @(YES), + (id)kSecAttrSynchronizable: @(YES), + (id)kSecAttrTombstone: @(NO), + (id)kSecAttrUUID: itemUUID, + }; + + ckksnotice("ckksscan", self.deps.zoneID, "Onboarding %@ %@", itemClass, itemUUID); + + __block NSError* itemSaveError = nil; + + [self executeQuery:queryAttributes readWrite:false error:&itemSaveError block:^(SecDbItemRef itemToSave) { + [self onboardItemToCKKS:itemToSave keyCache:keyCache error:&itemSaveError]; + }]; + + if(itemSaveError) { + ckkserror("ckksscan", self.deps.zoneID, "Need to upload %@, but can't save to database: %@", itemUUID, itemSaveError); + self.error = itemSaveError; + return CKKSDatabaseTransactionRollback; + } + + return CKKSDatabaseTransactionCommit; + }]; + } +} + +- (void)fixUUIDlessItemsWithPrimaryKeys:(NSMutableSet*)primaryKeys databaseProvider:(id)databaseProvider +{ + ckksnotice("ckksscan", self.deps.zoneID, "Found %d items missing UUIDs", (int)primaryKeys.count); + + if([primaryKeys count] == 0) { return; } - [ckks.launch addEvent:@"scan-local-items"]; + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + __block NSError* itemError = nil; - [ckks dispatchSyncWithAccountKeys: ^bool{ - if(self.cancelled) { - ckksnotice("ckksscan", ckks, "CKKSScanLocalItemsOperation cancelled, quitting"); - return false; + __block CKKSMemoryKeyCache* keyCache = [[CKKSMemoryKeyCache alloc] init]; + + for(NSDictionary* primaryKey in primaryKeys) { + ckksnotice("ckksscan", self.deps.zoneID, "Found item with no uuid: %@", primaryKey); + + __block CFErrorRef cferror = NULL; + + bool connectionSuccess = kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { + Query *q = query_create_with_limit((__bridge CFDictionaryRef)primaryKey, NULL, kSecMatchUnlimited, NULL, &cferror); + + if(!q || cferror) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't create query: %@", cferror); + return false; + } + + __block bool ok = true; + + ok &= SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef uuidlessItem, bool *stop) { + NSString* uuid = [[NSUUID UUID] UUIDString]; + NSDictionary* updates = @{(id)kSecAttrUUID: uuid}; + + ckksnotice("ckksscan", self.deps.zoneID, "Assigning new UUID %@ for item %@", uuid, uuidlessItem); + + SecDbItemRef new_item = SecDbItemCopyWithUpdates(uuidlessItem, (__bridge CFDictionaryRef)updates, &cferror); + + if(!new_item) { + SecTranslateError(&itemError, cferror); + self.error = itemError; + ckksnotice("ckksscan", self.deps.zoneID, "Unable to copy item with new UUID: %@", cferror); + return; + } + + bool updateSuccess = kc_transaction_type(dbt, kSecDbExclusiveRemoteCKKSTransactionType, &cferror, ^{ + return SecDbItemUpdate(uuidlessItem, new_item, dbt, kCFBooleanFalse, q->q_uuid_from_primary_key, &cferror); + }); + + if(updateSuccess) { + [self onboardItemToCKKS:new_item + keyCache:keyCache + error:&itemError]; + } else { + ckksnotice("ckksscan", self.deps.zoneID, "Unable to update item with new UUID: %@", cferror); + } + + ok &= updateSuccess; + }); + + ok &= query_notify_and_destroy(q, ok, &cferror); + + return true; + }); + + if(!connectionSuccess) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't execute query: %@", cferror); + SecTranslateError(&itemError, cferror); + self.error = itemError; + return CKKSDatabaseTransactionRollback; + } } - ckks.lastScanLocalItemsOperation = self; - NSMutableArray* itemsForManifest = [NSMutableArray array]; + return CKKSDatabaseTransactionCommit; + }]; +} +- (void)retriggerMissingMirrorEntires:(NSSet*)mirrorUUIDs + ckks:(CKKSKeychainView*)ckks + databaseProvider:(id)databaseProvider +{ + if (mirrorUUIDs.count > 0) { + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + ckkserror("ckksscan", self.deps.zoneID, "BUG: keychain missing %lu items from mirror and/or queues: %@", (unsigned long)mirrorUUIDs.count, mirrorUUIDs); + self.missingLocalItemsFound = mirrorUUIDs.count; + + [[CKKSAnalytics logger] logMetric:[NSNumber numberWithUnsignedInteger:mirrorUUIDs.count] withName:CKKSEventMissingLocalItemsFound]; + + for (NSString* uuid in mirrorUUIDs) { + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid zoneID:self.deps.zoneID error:&error]; + + if(!ckme || error) { + ckkserror("ckksscan", self.deps.zoneID, "BUG: error fetching previously-extant CKME (uuid: %@) from database: %@", uuid, error); + self.error = error; + } else { + [ckks _onqueueCKRecordChanged:ckme.item.storedCKRecord resync:true]; + } + } + + // And, if you're not in the tests, try to collect a sysdiagnose I guess? + // Re-enable IMCore autosysdiagnose capture to securityd + //if(SecIsInternalRelease() && !SecCKKSTestsEnabled()) { + // [[IMCloudKitHooks sharedInstance] tryToAutoCollectLogsWithErrorString:@"35810558" sendLogsTo:@"rowdy_bot@icloud.com"]; + //} + return CKKSDatabaseTransactionCommit; + }]; + } else { + ckksnotice("ckksscan", self.deps.zoneID,"No missing local items found"); + } +} + +- (void)main +{ + if(SecCKKSTestsEnabled() && SecCKKSTestSkipScan()) { + ckksnotice("ckksscan", self.deps.zoneID, "Scan cancelled by test request"); + return; + } + + // We need to not be jetsamed while running this + os_transaction_t transaction = os_transaction_create([[NSString stringWithFormat:@"com.apple.securityd.ckks.scan.%@", self.deps.zoneID] UTF8String]); + + id databaseProvider = self.deps.databaseProvider; + CKKSKeychainView* ckks = self.ckks; + + [self.deps.launch addEvent:@"scan-local-items"]; + + // A map of ItemClass -> Set of found UUIDs + NSMutableDictionary*>* itemUUIDsNotYetInCKKS = [NSMutableDictionary dictionary]; + + // A list of primary keys of items that fit in this view, but have no UUIDs + NSMutableSet* primaryKeysWithNoUUIDs = [NSMutableSet set]; + + // We want this set to be empty after scanning, or else the keychain (silently) dropped something on the floor + NSMutableSet* mirrorUUIDs = [NSMutableSet set]; + + [databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ // First, query for all synchronizable items - __block CFErrorRef cferror = NULL; __block NSError* error = nil; - __block bool newEntries = false; - // We want this set to be empty after scanning, or else the keychain (silently) dropped something on the floor - NSMutableSet* mirrorUUIDs = [NSMutableSet setWithArray:[CKKSMirrorEntry allUUIDs:ckks.zoneID error:&error]]; + [mirrorUUIDs addObjectsFromArray:[CKKSMirrorEntry allUUIDs:self.deps.zoneID error:&error]]; + __block CKKSMemoryKeyCache* keyCache = [[CKKSMemoryKeyCache alloc] init]; // Must query per-class, so: const SecDbSchema *newSchema = current_schema(); for (const SecDbClass *const *class = newSchema->classes; *class != NULL; class++) { - cferror = NULL; - if(!((*class)->itemclass)) { // Don't try to scan non-item 'classes' continue; } - NSDictionary* queryAttributes = @{(__bridge NSString*) kSecClass: (__bridge NSString*) (*class)->name, - (__bridge NSString*) kSecReturnRef: @(YES), - (__bridge NSString*) kSecAttrSynchronizable: @(YES), - (__bridge NSString*) kSecAttrTombstone: @(NO), - // This works ~as long as~ item views are chosen by view hint only. It's a significant perf win, though. - // SpinTracer: CKKSScanLocalItemsOperation expensive on M8 machines - (__bridge NSString*) kSecAttrSyncViewHint: ckks.zoneName, - }; - ckksinfo("ckksscan", ckks, "Scanning all synchronizable items for: %@", queryAttributes); + NSString* itemClass = (__bridge NSString*)(*class)->name; - Query *q = query_create_with_limit( (__bridge CFDictionaryRef) queryAttributes, NULL, kSecMatchUnlimited, &cferror); - bool ok = false; + NSMutableDictionary* queryAttributes = [ + @{(__bridge NSString*)kSecClass: itemClass, + (__bridge NSString*)kSecReturnRef: @(YES), + (__bridge NSString*)kSecAttrSynchronizable: @(YES), + (__bridge NSString*)kSecAttrTombstone: @(NO), + } mutableCopy]; - if(cferror) { - ckkserror("ckksscan", ckks, "couldn't create query: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - continue; - } + NSDictionary* extraQueryPredicates = [self queryPredicatesForViewMapping]; + [queryAttributes addEntriesFromDictionary:extraQueryPredicates]; - ok = kc_with_dbt(true, &cferror, ^(SecDbConnectionRef dbt) { - return SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef item, bool *stop) { - ckksnotice("ckksscan", ckks, "scanning item: %@", item); + ckksnotice("ckksscan", self.deps.zoneID, "Scanning all synchronizable %@ items(%@) for: %@", itemClass, self.name, queryAttributes); - self.processedItems += 1; + [self executeQuery:queryAttributes readWrite:false error:&error block:^(SecDbItemRef item) { + ckksnotice("ckksscan", self.deps.zoneID, "scanning item: %@", item); - SecDbItemRef itemToSave = NULL; + self.processedItems += 1; - // First check: is this a tombstone? If so, skip with prejudice. - if(SecDbItemIsTombstone(item)) { - ckksinfo("ckksscan", ckks, "Skipping tombstone %@", item); - return; - } - - // Second check: is this item even for this view? If not, skip. - NSString* viewForItem = [[CKKSViewManager manager] viewNameForItem:item]; - if(![viewForItem isEqualToString: ckks.zoneName]) { - ckksinfo("ckksscan", ckks, "Scanned item is for view %@, skipping", viewForItem); - return; - } - - // Third check: is this item one of our keys for a view? If not, skip. - if([CKKSKey isItemKeyForKeychainView: item] != nil) { - ckksinfo("ckksscan", ckks, "Scanned item is a CKKS internal key, skipping"); - return; - } - - // Fourth check: does this item have a UUID? If not, ONBOARD! - NSString* uuid = (__bridge_transfer NSString*) CFRetain(SecDbItemGetValue(item, &v10itemuuid, &cferror)); - if(!uuid || [uuid isEqual: [NSNull null]]) { - ckksnotice("ckksscan", ckks, "making new UUID for item %@", item); - - uuid = [[NSUUID UUID] UUIDString]; - NSDictionary* updates = @{(id) kSecAttrUUID: uuid}; - - SecDbItemRef new_item = SecDbItemCopyWithUpdates(item, (__bridge CFDictionaryRef) updates, &cferror); - if(SecErrorGetOSStatus(cferror) != errSecSuccess) { - ckkserror("ckksscan", ckks, "couldn't update item with new UUID: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - CFReleaseNull(new_item); - return; - } - - if (new_item) { - bool ok = kc_transaction_type(dbt, kSecDbExclusiveRemoteCKKSTransactionType, &cferror, ^{ - return SecDbItemUpdate(item, new_item, dbt, kCFBooleanFalse, q->q_uuid_from_primary_key, &cferror); - }); - - if(!ok || SecErrorGetOSStatus(cferror) != errSecSuccess) { - ckkserror("ckksscan", ckks, "couldn't update item with new UUID: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - CFReleaseNull(new_item); - return; - } - } - itemToSave = CFRetainSafe(new_item); - CFReleaseNull(new_item); - - } else { - // Is there a known sync item with this UUID? - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: uuid zoneID:ckks.zoneID error: &error]; - if(ckme != nil) { - if ([CKKSManifest shouldSyncManifests]) { - [itemsForManifest addObject:ckme.item]; - } - [mirrorUUIDs removeObject:uuid]; - ckksinfo("ckksscan", ckks, "Existing mirror entry with UUID %@", uuid); - - if([self areEquivalent:item ckksItem:ckme.item]) { - // Fair enough. - return; - } else { - ckksnotice("ckksscan", ckks, "Existing mirror entry with UUID %@ does not match local item", uuid); - } - } - - // We don't care about the oqe state here, just that one exists - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase: uuid zoneID:ckks.zoneID error: &error]; - if(oqe != nil) { - ckksnotice("ckksscan", ckks, "Existing outgoing queue entry with UUID %@", uuid); - // If its state is 'new', mark down that we've seen new entries that need processing - newEntries |= !![oqe.state isEqualToString: SecCKKSStateNew]; - return; - } - - itemToSave = CFRetainSafe(item); - } - - // Hurray, we can help! - self.recordsFound += 1; - - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry withItem: itemToSave action: SecCKKSActionAdd ckks:ckks error: &error]; - - if(error) { - ckkserror("ckksscan", ckks, "Need to upload %@, but can't create outgoing entry: %@", item, error); - self.error = error; - CFReleaseNull(itemToSave); - return; - } - - ckksnotice("ckksscan", ckks, "Syncing new item: %@", oqe); - CFReleaseNull(itemToSave); - - [oqe saveToDatabase: &error]; - if(error) { - ckkserror("ckksscan", ckks, "Need to upload %@, but can't save to database: %@", oqe, error); - self.error = error; - return; - } - newEntries = true; - if ([CKKSManifest shouldSyncManifests]) { - [itemsForManifest addObject:oqe.item]; - } - - self.recordsAdded += 1; - }); - }); - - if(cferror || !ok) { - ckkserror("ckksscan", ckks, "error processing or finding items: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - query_destroy(q, NULL); - continue; - } - - ok = query_notify_and_destroy(q, ok, &cferror); - - if(cferror || !ok) { - ckkserror("ckksscan", ckks, "couldn't delete query: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - continue; - } - } - - // We're done checking local keychain for extra items, now let's make sure the mirror doesn't have extra items, either - if (mirrorUUIDs.count > 0) { - ckksnotice("ckksscan", ckks, "keychain missing %lu items from mirror, proceeding with queue scanning", (unsigned long)mirrorUUIDs.count); - [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSIncomingQueueEntry allUUIDs:ckks.zoneID error:&error]]]; - if (error) { - ckkserror("ckksscan", ckks, "unable to inspect incoming queue: %@", error); - self.error = error; - return false; - } - - [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSOutgoingQueueEntry allUUIDs:ckks.zoneID error:&error]]]; - if (error) { - ckkserror("ckksscan", ckks, "unable to inspect outgoing queue: %@", error); - self.error = error; - return false; - } - - if (mirrorUUIDs.count > 0) { - ckkserror("ckksscan", ckks, "BUG: keychain missing %lu items from mirror and/or queues: %@", (unsigned long)mirrorUUIDs.count, mirrorUUIDs); - self.missingLocalItemsFound = mirrorUUIDs.count; - - [[CKKSAnalytics logger] logMetric:[NSNumber numberWithUnsignedInteger:mirrorUUIDs.count] withName:CKKSEventMissingLocalItemsFound]; - - for (NSString* uuid in mirrorUUIDs) { - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid zoneID:ckks.zoneID error:&error]; - [ckks _onqueueCKRecordChanged:ckme.item.storedCKRecord resync:true]; + // First check: is this a tombstone? If so, skip with prejudice. + if(SecDbItemIsTombstone(item)) { + ckksinfo("ckksscan", self.deps.zoneID, "Skipping tombstone %@", item); + return; } - // And, if you're not in the tests, try to collect a sysdiagnose I guess? - // Re-enable IMCore autosysdiagnose capture to securityd - //if(SecIsInternalRelease() && !SecCKKSTestsEnabled()) { - // [[IMCloudKitHooks sharedInstance] tryToAutoCollectLogsWithErrorString:@"35810558" sendLogsTo:@"rowdy_bot@icloud.com"]; - //} - } else { - ckksnotice("ckksscan", ckks, "No missing local items found"); - } + // Second check: is this item a CKKS key for a view? If so, skip. + if([CKKSKey isItemKeyForKeychainView:item] != nil) { + ckksinfo("ckksscan", self.deps.zoneID, "Scanned item is a CKKS internal key, skipping"); + return; + } + + // Third check: What view is this for? + NSString* viewForItem = [[CKKSViewManager manager] viewNameForItem:item]; + if(![viewForItem isEqualToString:self.deps.zoneID.zoneName]) { + ckksinfo("ckksscan", self.deps.zoneID, "Scanned item is for view %@, skipping", viewForItem); + return; + } + + // Fourth check: does this item have a UUID? If not, mark for later onboarding. + CFErrorRef cferror = NULL; + + NSString* uuid = (__bridge_transfer NSString*) CFRetain(SecDbItemGetValue(item, &v10itemuuid, &cferror)); + if(!uuid || [uuid isEqual: [NSNull null]]) { + ckksnotice("ckksscan", self.deps.zoneID, "making new UUID for item %@: %@", item, cferror); + + NSMutableDictionary* primaryKey = [(NSDictionary*)CFBridgingRelease(SecDbItemCopyPListWithMask(item, kSecDbPrimaryKeyFlag, &cferror)) mutableCopy]; + + // Class is an important part of a primary key, SecDb + primaryKey[(id)kSecClass] = itemClass; + + if(SecErrorGetOSStatus(cferror) != errSecSuccess) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't copy UUID-less item's primary key: %@", cferror); + SecTranslateError(&error, cferror); + self.error = error; + return; + } + + [primaryKeysWithNoUUIDs addObject:primaryKey]; + return; + } + + // Is there a known sync item with this UUID? + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid + zoneID:self.deps.zoneID + error:&error]; + if(ckme != nil) { + [mirrorUUIDs removeObject:uuid]; + ckksinfo("ckksscan", self.deps.zoneID, "Existing mirror entry with UUID %@", uuid); + + if([self areEquivalent:item ckksItem:ckme.item keyCache:keyCache]) { + // Fair enough. + return; + } else { + ckksnotice("ckksscan", self.deps.zoneID, "Existing mirror entry with UUID %@ does not match local item", uuid); + } + } + + // We don't care about the oqe state here, just that one exists + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:uuid + zoneID:self.deps.zoneID + error:&error]; + if(oqe != nil) { + ckksnotice("ckksscan", self.deps.zoneID, "Existing outgoing queue entry with UUID %@", uuid); + // If its state is 'new', mark down that we've seen new entries that need processing + self.newCKKSEntries |= !![oqe.state isEqualToString:SecCKKSStateNew]; + return; + } + + // Hurray, we can help! + ckksnotice("ckksscan", self.deps.zoneID, "Item(%@) is new; will attempt to add to CKKS", uuid); + self.recordsFound += 1; + + NSMutableSet* classUUIDs = itemUUIDsNotYetInCKKS[itemClass]; + if(!classUUIDs) { + classUUIDs = [NSMutableSet set]; + itemUUIDsNotYetInCKKS[itemClass] = classUUIDs; + } + [classUUIDs addObject:uuid]; + }]; } - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventScanLocalItems zone:ckks.zoneName count:self.processedItems]; - - if ([CKKSManifest shouldSyncManifests]) { - // TODO: this manifest needs to incorporate peer manifests - CKKSEgoManifest* manifest = [CKKSEgoManifest newManifestForZone:ckks.zoneName withItems:itemsForManifest peerManifestIDs:@[] currentItems:@{} error:&error]; - if (!manifest || error) { - ckkserror("ckksscan", ckks, "could not create manifest: %@", error); - self.error = error; - return false; - } - - [manifest saveToDatabase:&error]; + // We're done checking local keychain for extra items, now let's make sure the mirror doesn't have extra items that the keychain doesn't have, either + if (mirrorUUIDs.count > 0) { + ckksnotice("ckksscan", self.deps.zoneID, "keychain missing %lu items from mirror, proceeding with queue scanning", (unsigned long)mirrorUUIDs.count); + [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSIncomingQueueEntry allUUIDs:self.deps.zoneID error:&error]]]; if (error) { - ckkserror("ckksscan", ckks, "could not save manifest to database: %@", error); + ckkserror("ckksscan", self.deps.zoneID, "unable to inspect incoming queue: %@", error); self.error = error; - return false; + return; } - ckks.egoManifest = manifest; + [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSOutgoingQueueEntry allUUIDs:self.deps.zoneID error:&error]]]; + if (error) { + ckkserror("ckksscan", self.deps.zoneID, "unable to inspect outgoing queue: %@", error); + self.error = error; + return; + } } - if(newEntries) { - // Schedule a "view changed" notification - [ckks.notifyViewChangedScheduler trigger]; - - // notify CKKS that it should process these new entries - [ckks processOutgoingQueue:self.ckoperationGroup]; - } - - if(self.missingLocalItemsFound > 0) { - [ckks processIncomingQueue:false]; - } - - ckksnotice("ckksscan", ckks, "Completed scan"); - ckks.droppedItems = false; - return true; + // Drop off of read-only transaction }]; + + if(self.error) { + ckksnotice("ckksscan", self.deps.zoneID, "Exiting due to previous error: %@", self.error); + return; + } + + ckksnotice("ckksscan", self.deps.zoneID, "Found %d item classes with missing items", (int)itemUUIDsNotYetInCKKS.count); + + for(NSString* itemClass in [itemUUIDsNotYetInCKKS allKeys]) { + [self onboardItemsWithUUIDs:itemUUIDsNotYetInCKKS[itemClass] itemClass:itemClass databaseProvider:databaseProvider]; + } + + [self fixUUIDlessItemsWithPrimaryKeys:primaryKeysWithNoUUIDs databaseProvider:databaseProvider]; + + [self retriggerMissingMirrorEntires:mirrorUUIDs + ckks:ckks + databaseProvider:databaseProvider]; + + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventScanLocalItems zone:self.deps.zoneID.zoneName count:self.processedItems]; + + // Write down that a scan occurred + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + CKKSZoneStateEntry* zoneState = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName]; + + zoneState.lastLocalKeychainScanTime = [NSDate now]; + + NSError* saveError = nil; + [zoneState saveToDatabase:&saveError]; + + if(saveError) { + ckkserror("ckksscan", self.deps.zoneID, "Unable to save 'scanned' bit: %@", saveError); + } else { + ckksnotice("ckksscan", self.deps.zoneID, "Saved scanned status."); + } + + return CKKSDatabaseTransactionCommit; + }]; + + if(self.newCKKSEntries) { + // Schedule a "view changed" notification + [self.deps.notifyViewChangedScheduler trigger]; + + // notify CKKS that it should process these new entries + [ckks processOutgoingQueue:self.ckoperationGroup]; + // TODO: self.nextState = SecCKKSZoneKeyStateProcessOutgoingQueue; + } else { + self.nextState = self.intendedState; + } + + if(self.missingLocalItemsFound > 0) { + [ckks processIncomingQueue:false]; + // TODO [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagProcessIncomingQueue]; + } + + ckksnotice("ckksscan", self.deps.zoneID, "Completed scan"); + (void)transaction; } -- (BOOL)areEquivalent:(SecDbItemRef)item ckksItem:(CKKSItem*)ckksItem +- (BOOL)areEquivalent:(SecDbItemRef)item + ckksItem:(CKKSItem*)ckksItem + keyCache:(CKKSMemoryKeyCache*)keyCache { - CKKSKeychainView* ckks = self.ckks; - NSError* localerror = nil; - NSDictionary* attributes = [CKKSIncomingQueueOperation decryptCKKSItemToAttributes:ckksItem error:&localerror]; + + NSDictionary* attributes = [CKKSIncomingQueueOperation decryptCKKSItemToAttributes:ckksItem + keyCache:keyCache + error:&localerror]; if(!attributes || localerror) { - ckksnotice("ckksscan", ckks, "Could not decrypt item for comparison: %@", localerror); + ckksnotice("ckksscan", self.deps.zoneID, "Could not decrypt item for comparison: %@", localerror); return YES; } @@ -354,7 +586,7 @@ localerror = (NSError*)CFBridgingRelease(cferror); if(!objdict || localerror) { - ckksnotice("ckksscan", ckks, "Could not get item contents for comparison: %@", localerror); + ckksnotice("ckksscan", self.deps.zoneID, "Could not get item contents for comparison: %@", localerror); // Fail open: assert that this item doesn't match return NO; diff --git a/keychain/ckks/CKKSStates.h b/keychain/ckks/CKKSStates.h new file mode 100644 index 00000000..bb9bbbec --- /dev/null +++ b/keychain/ckks/CKKSStates.h @@ -0,0 +1,51 @@ + +#if OCTAGON + +#import +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ot/OctagonStateMachine.h" + +NS_ASSUME_NONNULL_BEGIN + +// Flag initialization +typedef OctagonFlag CKKSFlag; + +// The set of trusted peers has changed +extern CKKSFlag* const CKKSFlagTrustedPeersSetChanged; + +// A client has requested that TLKs be created +extern CKKSFlag* const CKKSFlagTLKCreationRequested; +// We were waiting for a TLK upload, and one has occurred +extern CKKSFlag* const CKKSFlagKeyStateTLKsUploaded; + +extern CKKSFlag* const CKKSFlagCloudKitLoggedIn; +extern CKKSFlag* const CKKSFlagCloudKitLoggedOut; + +extern CKKSFlag* const CKKSFlagBeginTrustedOperation; +extern CKKSFlag* const CKKSFlagEndTrustedOperation; + +extern CKKSFlag* const CKKSFlagChangeTokenExpired; +extern CKKSFlag* const CKKSFlagCloudKitZoneMissing; + +extern CKKSFlag* const CKKSFlagDeviceUnlocked; + +extern CKKSFlag* const CKKSFlagFetchRequested; +// Added when a key hierarchy fetch completes. +extern CKKSFlag* const CKKSFlagFetchComplete; + +extern CKKSFlag* const CKKSFlagKeyStateProcessRequested; +extern CKKSFlag* const CKKSFlagKeySetRequested; + +extern CKKSFlag* const CKKSFlagProcessIncomingQueue; +extern CKKSFlag* const CKKSFlagProcessOutgoingQueue; +extern CKKSFlag* const CKKSFlagScanLocalItems; +extern CKKSFlag* const CKKSFlagItemReencryptionNeeded; + +extern CKKSFlag* const CKKSFlag24hrNotification; + +NSSet* CKKSAllStateFlags(void); + +NS_ASSUME_NONNULL_END + +#endif diff --git a/keychain/ckks/CKKSStates.m b/keychain/ckks/CKKSStates.m new file mode 100644 index 00000000..cd0b6946 --- /dev/null +++ b/keychain/ckks/CKKSStates.m @@ -0,0 +1,68 @@ + +#if OCTAGON + +#import "keychain/ckks/CKKSStates.h" +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ot/ObjCImprovements.h" + +CKKSFlag* const CKKSFlagTrustedPeersSetChanged = (CKKSFlag*) @"trusted_peers_changed"; + +CKKSFlag* const CKKSFlagTLKCreationRequested = (CKKSFlag*)@"tlk_creation"; +CKKSFlag* const CKKSFlagKeyStateTLKsUploaded = (CKKSFlag*)@"tlks_uploaded"; + +CKKSFlag* const CKKSFlagCloudKitLoggedIn = (CKKSFlag*)@"ck_account_logged_in"; +CKKSFlag* const CKKSFlagCloudKitLoggedOut = (CKKSFlag*)@"ck_account_logged_out"; + +CKKSFlag* const CKKSFlagBeginTrustedOperation = (CKKSFlag*)@"trusted_operation_begin"; +CKKSFlag* const CKKSFlagEndTrustedOperation = (CKKSFlag*)@"trusted_operation_end"; + +CKKSFlag* const CKKSFlagChangeTokenExpired = (CKKSFlag*)@"ck_change_token_expired"; +CKKSFlag* const CKKSFlagCloudKitZoneMissing = (CKKSFlag*)@"ck_zone_missing"; + +CKKSFlag* const CKKSFlagDeviceUnlocked = (CKKSFlag*)@"device_unlocked"; + +CKKSFlag* const CKKSFlagFetchRequested = (CKKSFlag*) @"fetch_requested"; +CKKSFlag* const CKKSFlagFetchComplete = (CKKSFlag*)@"fetch_complete"; + +CKKSFlag* const CKKSFlagKeyStateProcessRequested = (CKKSFlag*) @"key_process_requested"; + +CKKSFlag* const CKKSFlagKeySetRequested = (CKKSFlag*) @"key_set"; + +CKKSFlag* const CKKSFlagProcessIncomingQueue = (CKKSFlag*)@"process_incoming_queue"; +CKKSFlag* const CKKSFlagProcessOutgoingQueue = (CKKSFlag*)@"process_outgoing_queue"; +CKKSFlag* const CKKSFlagScanLocalItems = (CKKSFlag*)@"dropped_items"; +CKKSFlag* const CKKSFlagItemReencryptionNeeded = (CKKSFlag*)@"item_reencryption_needed"; + +CKKSFlag* const CKKSFlag24hrNotification = (CKKSFlag*)@"24_hr_notification"; + +NSSet* CKKSAllStateFlags(void) +{ + static NSSet* s = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + s = [NSSet setWithArray:@[ + CKKSFlagFetchRequested, + CKKSFlagKeyStateProcessRequested, + CKKSFlagTrustedPeersSetChanged, + CKKSFlagTLKCreationRequested, + CKKSFlagScanLocalItems, + CKKSFlagCloudKitLoggedIn, + CKKSFlagCloudKitLoggedOut, + CKKSFlagCloudKitZoneMissing, + CKKSFlagChangeTokenExpired, + CKKSFlagProcessIncomingQueue, + CKKSFlagProcessOutgoingQueue, + CKKSFlagItemReencryptionNeeded, + CKKSFlagBeginTrustedOperation, + CKKSFlagEndTrustedOperation, + CKKSFlagDeviceUnlocked, + CKKSFlagKeyStateTLKsUploaded, + CKKSFlagFetchComplete, + CKKSFlag24hrNotification, + CKKSFlagKeySetRequested, + ]]; + }); + return s; +} + +#endif diff --git a/keychain/ckks/CKKSSynchronizeOperation.m b/keychain/ckks/CKKSSynchronizeOperation.m index f507bcb6..b473053d 100644 --- a/keychain/ckks/CKKSSynchronizeOperation.m +++ b/keychain/ckks/CKKSSynchronizeOperation.m @@ -76,10 +76,10 @@ CKKSKeychainView* ckks = self.ckks; // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. - [ckks dispatchSync: ^bool{ + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckksresync", ckks, "CKKSSynchronizeOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } ckks.lastSynchronizeOperation = self; @@ -102,13 +102,22 @@ [self runBeforeGroupFinished: fetchOp]; // Step 2 - CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:ckks errorOnClassAFailure:true]; + CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithDependencies:ckks.operationDependencies + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy + errorOnClassAFailure:true + handleMismatchedViewItems:false]; + incomingOp.name = [NSString stringWithFormat: @"resync-step%u-incoming", self.restartCount * steps + 2]; [incomingOp addSuccessDependency:fetchOp]; [self runBeforeGroupFinished:incomingOp]; // Step 3 - CKKSScanLocalItemsOperation* scan = [[CKKSScanLocalItemsOperation alloc] initWithCKKSKeychainView:ckks ckoperationGroup:operationGroup]; + CKKSScanLocalItemsOperation* scan = [[CKKSScanLocalItemsOperation alloc] initWithDependencies:ckks.operationDependencies + ckks:ckks + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError + ckoperationGroup:operationGroup]; scan.name = [NSString stringWithFormat: @"resync-step%u-scan", self.restartCount * steps + 3]; [scan addSuccessDependency: incomingOp]; [self runBeforeGroupFinished: scan]; @@ -117,6 +126,7 @@ CKKSOutgoingQueueOperation* outgoingOp = [ckks processOutgoingQueue: operationGroup]; outgoingOp.name = [NSString stringWithFormat: @"resync-step%u-outgoing", self.restartCount * steps + 4]; [self dependOnBeforeGroupFinished:outgoingOp]; + [outgoingOp addDependency:scan]; // Step 5: CKKSResultOperation* restart = [[CKKSResultOperation alloc] init]; @@ -124,7 +134,7 @@ [restart addExecutionBlock:^{ STRONGIFY(self); if(!self) { - secerror("ckksresync: received callback for released object"); + ckkserror("ckksresync", ckks, "received callback for released object"); return; } @@ -147,7 +157,7 @@ [restart addSuccessDependency: outgoingOp]; [self runBeforeGroupFinished: restart]; - return true; + return CKKSDatabaseTransactionCommit; }]; } diff --git a/keychain/ckks/CKKSTLKShare.h b/keychain/ckks/CKKSTLKShare.h index eb4de292..29753d6a 100644 --- a/keychain/ckks/CKKSTLKShare.h +++ b/keychain/ckks/CKKSTLKShare.h @@ -75,7 +75,7 @@ typedef NS_ENUM(NSUInteger, SecCKKSTLKShareVersion) { - (instancetype)initForKey:(NSString*)tlkUUID senderPeerID:(NSString*)senderPeerID recieverPeerID:(NSString*)receiverPeerID - receiverEncPublicKeySPKI:(NSData*)publicKeySPKI + receiverEncPublicKeySPKI:(NSData* _Nullable)publicKeySPKI curve:(SFEllipticCurve)curve version:(SecCKKSTLKShareVersion)version epoch:(NSInteger)epoch diff --git a/keychain/ckks/CKKSTLKShare.m b/keychain/ckks/CKKSTLKShare.m index f1019b9f..281f1ead 100644 --- a/keychain/ckks/CKKSTLKShare.m +++ b/keychain/ckks/CKKSTLKShare.m @@ -69,7 +69,7 @@ - (instancetype)initForKey:(NSString*)tlkUUID senderPeerID:(NSString*)senderPeerID recieverPeerID:(NSString*)receiverPeerID - receiverEncPublicKeySPKI:(NSData*)publicKeySPKI + receiverEncPublicKeySPKI:(NSData* _Nullable)publicKeySPKI curve:(SFEllipticCurve)curve version:(SecCKKSTLKShareVersion)version epoch:(NSInteger)epoch @@ -248,7 +248,7 @@ error:(NSError* __autoreleasing*)error { if(!peer.publicSigningKey) { - secerror("ckksshare: no signing key for peer: %@", peer); + ckkserror("ckksshare", self.zoneID, "no signing key for peer: %@", peer); if(error) { *error = [NSError errorWithDomain:CKKSErrorDomain @@ -283,7 +283,7 @@ ckrecord:ckrecord error:&localerror]; if(localerror) { - secerror("ckksshare: signature didn't verify for %@ %@: %@", self, peer, localerror); + ckkserror("ckksshare", self.zoneID, "signature didn't verify for %@ %@: %@", self, peer, localerror); lastVerificationError = localerror; } if(isSigned) { @@ -345,8 +345,7 @@ - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _zoneID = [decoder decodeObjectOfClass:[CKRecordZoneID class] forKey:@"zoneID"]; _curve = (SFEllipticCurve) [decoder decodeInt64ForKey:@"curve"]; _version = (SecCKKSTLKShareVersion)[decoder decodeInt64ForKey:@"version"]; @@ -405,7 +404,7 @@ share.wrappedTLK = [share wrap:key publicKey:receiver.publicEncryptionKey error:&localerror]; if(localerror) { - secerror("ckksshare: couldn't share %@ (wrap failed): %@", key, localerror); + ckkserror("ckksshare", key.zoneID, "couldn't share %@ (wrap failed): %@", key, localerror); if(error) { *error = localerror; } @@ -416,7 +415,7 @@ ckrecord:nil error:&localerror]; if(localerror) { - secerror("ckksshare: couldn't share %@ (signing failed): %@", key, localerror); + ckkserror("ckksshare", key.zoneID, "couldn't share %@ (signing failed): %@", key, localerror); if(error) { *error = localerror; } diff --git a/keychain/ckks/CKKSTLKShareRecord.h b/keychain/ckks/CKKSTLKShareRecord.h index 9fd54c0c..c8503267 100644 --- a/keychain/ckks/CKKSTLKShareRecord.h +++ b/keychain/ckks/CKKSTLKShareRecord.h @@ -87,6 +87,11 @@ NS_ASSUME_NONNULL_BEGIN // Returns a prefix that all every CKKSTLKShare CKRecord will have + (NSString*)ckrecordPrefix; ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error; ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error; + ++ (NSNumber* _Nullable)counts:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error; + // For tests - (CKKSKey* _Nullable)unwrapUsing:(id)localPeer error:(NSError**)error; - (NSData* _Nullable)signRecord:(SFECKeyPair*)signingKey error:(NSError**)error; diff --git a/keychain/ckks/CKKSTLKShareRecord.m b/keychain/ckks/CKKSTLKShareRecord.m index ac6ee5ad..19e7c18f 100644 --- a/keychain/ckks/CKKSTLKShareRecord.m +++ b/keychain/ckks/CKKSTLKShareRecord.m @@ -220,7 +220,7 @@ zoneID:key.zoneID error:&localerror]; if(localerror) { - secerror("ckksshare: couldn't load old share for %@: %@", key, localerror); + ckkserror("ckksshare", key.zoneID, "couldn't load old share for %@: %@", key, localerror); if(error) { *error = localerror; } @@ -470,6 +470,58 @@ ]; } ++ (BOOL)intransactionRecordChanged:(CKRecord*)record resync:(BOOL)resync error:(NSError**)error +{ + NSError* localerror = nil; + + // CKKSTLKShares get saved with no modification + CKKSTLKShareRecord* share = [[CKKSTLKShareRecord alloc] initWithCKRecord:record]; + bool saved = [share saveToDatabase:&localerror]; + if(!saved || localerror) { + ckkserror("ckksshare", record.recordID.zoneID, "Couldn't save new TLK share to database: %@ %@", share, localerror); + if(error) { + *error = localerror; + } + return NO; + } + return YES; +} + ++ (BOOL)intransactionRecordDeleted:(CKRecordID*)recordID resync:(BOOL)resync error:(NSError**)error +{ + NSError* localerror = nil; + ckksinfo("ckksshare", recordID.zoneID, "CloudKit notification: deleted tlk share record(%@): %@", SecCKRecordTLKShareType, recordID); + + CKKSTLKShareRecord* share = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:recordID error:&localerror]; + [share deleteFromDatabase:&localerror]; + + if(localerror) { + ckkserror("ckksshare", recordID.zoneID, "CK notification: Couldn't delete deleted TLKShare: %@ %@", recordID, localerror); + if(error) { + *error = localerror; + } + return NO; + } + return YES; +} + ++ (NSNumber* _Nullable)counts:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error +{ + __block NSNumber *result = nil; + + [CKKSSQLDatabaseObject queryDatabaseTable:[[self class] sqlTable] + where:@{@"ckzone": CKKSNilToNSNull(zoneID.zoneName)} + columns:@[@"count(rowid)"] + groupBy:nil + orderBy:nil + limit:-1 + processRow:^(NSDictionary* row) { + result = row[@"count(rowid)"].asNSNumberInteger; + } + error: error]; + return result; +} + @end #endif // OCTAGON diff --git a/keychain/ckks/CKKSUpdateCurrentItemPointerOperation.m b/keychain/ckks/CKKSUpdateCurrentItemPointerOperation.m index 00080ba2..b8b3b839 100644 --- a/keychain/ckks/CKKSUpdateCurrentItemPointerOperation.m +++ b/keychain/ckks/CKKSUpdateCurrentItemPointerOperation.m @@ -101,10 +101,10 @@ WEAKIFY(self); - [ckks dispatchSyncWithAccountKeys:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckkscurrent", ckks, "CKKSUpdateCurrentItemPointerOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } NSError* error = nil; @@ -117,7 +117,7 @@ if(!self.newItem || error) { ckksnotice("ckkscurrent", ckks, "Couldn't fetch new item, quitting: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } // Now that we're on the db queue, ensure that the given hashes for the items match the hashes as they are now. @@ -130,14 +130,14 @@ code:CKKSItemChanged description:@"New item has changed; hashes mismatch. Refetch and try again." underlying:(NSError*)CFBridgingRelease(cferror)]; - return false; + return CKKSDatabaseTransactionRollback; } newItemUUID = (NSString*) CFBridgingRelease(CFRetainSafe(SecDbItemGetValue(self.newItem, &v10itemuuid, &cferror))); if(!newItemUUID || cferror) { ckkserror("ckkscurrent", ckks, "Error fetching UUID for new item: %@", cferror); self.error = (NSError*) CFBridgingRelease(cferror); - return false; + return CKKSDatabaseTransactionRollback; } // If the old item is nil, that's an indicator that the old item isn't expected to exist in the keychain anymore @@ -147,7 +147,7 @@ if(!self.oldItem || error) { ckksnotice("ckkscurrent", ckks, "Couldn't fetch old item, quitting: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } oldCurrentItemHash = (NSData*) CFBridgingRelease(CFRetainSafe(SecDbItemGetSHA1(self.oldItem, &cferror))); @@ -158,14 +158,14 @@ code:CKKSItemChanged description:@"Old item has changed; hashes mismatch. Refetch and try again." underlying:(NSError*)CFBridgingRelease(cferror)]; - return false; + return CKKSDatabaseTransactionRollback; } oldCurrentItemUUID = (NSString*) CFBridgingRelease(CFRetainSafe(SecDbItemGetValue(self.oldItem, &v10itemuuid, &cferror))); if(!oldCurrentItemUUID || cferror) { ckkserror("ckkscurrent", ckks, "Error fetching UUID for old item: %@", cferror); self.error = (NSError*) CFBridgingRelease(cferror); - return false; + return CKKSDatabaseTransactionRollback; } } @@ -180,7 +180,7 @@ code:CKKSRemoteItemChangePending description:[NSString stringWithFormat:@"Update to current item pointer is pending."]]; ckkserror("ckkscurrent", ckks, "Attempt to set a new current item pointer when one exists: %@", self.error); - return false; + return CKKSDatabaseTransactionRollback; } CKKSCurrentItemPointer* cip = [CKKSCurrentItemPointer tryFromDatabase:self.currentPointerIdentifier state:SecCKKSProcessedStateLocal zoneID:ckks.zoneID error:&error]; @@ -198,7 +198,7 @@ self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSItemChanged description:[NSString stringWithFormat:@"Current pointer(%@) does not match user-supplied %@, aborting", cip, oldCurrentItemUUID]]; - return false; + return CKKSDatabaseTransactionRollback; } // Cool. Since you know what you're updating, you're allowed to update! cip.currentItemUUID = newItemUUID; @@ -209,7 +209,7 @@ self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSItemChanged description:[NSString stringWithFormat:@"Current pointer(%@) does not match given value of '%@', aborting", cip, oldCurrentItemUUID]]; - return false; + return CKKSDatabaseTransactionRollback; } else { // No current item pointer? How exciting! Let's make you a nice new one. cip = [[CKKSCurrentItemPointer alloc] initForIdentifier:self.currentPointerIdentifier @@ -237,7 +237,7 @@ if(error) { ckkserror("ckkscurrent", ckks, "Error attempting to update current item pointer %@: %@", self.currentPointerIdentifier, error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } // Make sure the item is synced, though! @@ -250,11 +250,7 @@ underlying:error]; self.error = error; - return false; - } - - if ([CKKSManifest shouldSyncManifests]) { - [ckks.egoManifest setCurrentItemUUID:newItemUUID forIdentifier:self.currentPointerIdentifier]; + return CKKSDatabaseTransactionRollback; } ckksnotice("ckkscurrent", ckks, "Saving new current item pointer %@", cip); @@ -263,12 +259,6 @@ CKRecord* record = [cip CKRecordWithZoneID:ckks.zoneID]; recordsToSave[record.recordID] = record; - if([CKKSManifest shouldSyncManifests]) { - for(CKRecord* record in [ckks.egoManifest allCKRecordsWithZoneID:ckks.zoneID]) { - recordsToSave[record.recordID] = record; - } - } - // Start a CKModifyRecordsOperation to save this new/updated record. NSBlockOperation* modifyComplete = [[NSBlockOperation alloc] init]; modifyComplete.name = @"updateCurrentItemPointer-modifyRecordsComplete"; @@ -311,8 +301,8 @@ ckkserror("ckkscurrent", strongCKKS, "CloudKit returned an error: %@", ckerror); self.error = ckerror; - [strongCKKS dispatchSync:^bool { - return [strongCKKS _onqueueCKWriteFailed:ckerror attemptedRecordsChanged:recordsToSave]; + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + return [strongCKKS _onqueueCKWriteFailed:ckerror attemptedRecordsChanged:recordsToSave] ? CKKSDatabaseTransactionCommit : CKKSDatabaseTransactionRollback; }]; [strongCKKS scheduleOperation: modifyComplete]; @@ -321,7 +311,7 @@ __block NSError* error = nil; - [strongCKKS dispatchSync: ^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for(CKRecord* record in savedRecords) { // Save the item records if([record.recordType isEqualToString: SecCKRecordCurrentItemType]) { @@ -345,9 +335,9 @@ } // Schedule a 'view changed' notification - [strongCKKS.notifyViewChangedScheduler trigger]; + [strongCKKS.viewState.notifyViewChangedScheduler trigger]; } - return true; + return CKKSDatabaseTransactionCommit; }]; self.error = error; @@ -355,18 +345,19 @@ }; [self dependOnBeforeGroupFinished: self.modifyRecordsOperation]; - [ckks.database addOperation: self.modifyRecordsOperation]; + [ckks.operationDependencies.ckdatabase addOperation:self.modifyRecordsOperation]; - return true; + return CKKSDatabaseTransactionCommit; }]; } - (SecDbItemRef _Nullable)_onqueueFindSecDbItem:(NSData*)persistentRef accessGroup:(NSString*)accessGroup error:(NSError**)error { + CKKSKeychainView* ckks = self.ckks; + dispatch_assert_queue(ckks.queue); __block SecDbItemRef blockItem = NULL; CFErrorRef cferror = NULL; __block NSError* localerror = NULL; - CKKSKeychainView* ckks = self.ckks; bool ok = kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { // Find the items from their persistent refs. CFErrorRef blockcfError = NULL; @@ -376,6 +367,7 @@ }, NULL, 1, + NULL, &blockcfError); if(blockcfError || !q) { ckkserror("ckkscurrent", ckks, "couldn't create query for item persistentRef: %@", blockcfError); diff --git a/keychain/ckks/CKKSUpdateDeviceStateOperation.m b/keychain/ckks/CKKSUpdateDeviceStateOperation.m index 7905d589..8502fb91 100644 --- a/keychain/ckks/CKKSUpdateDeviceStateOperation.m +++ b/keychain/ckks/CKKSUpdateDeviceStateOperation.m @@ -87,13 +87,13 @@ ckkserror("ckksdevice", ckks, "Not quite sure if the account isa HSA2 or not. Probably will quit?"); } - [ckks dispatchSyncWithAccountKeys:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [ckks _onqueueCurrentDeviceStateEntry:&error]; if(error || !cdse) { ckkserror("ckksdevice", ckks, "Error creating device state entry; quitting: %@", error); - return false; + return CKKSDatabaseTransactionRollback; } if(self.rateLimit) { @@ -116,7 +116,7 @@ self.error = [NSError errorWithDomain:@"securityd" code:errSecInternalError userInfo:@{NSLocalizedDescriptionKey: @"Rate-limited the CKKSUpdateDeviceStateOperation"}]; - return false; + return CKKSDatabaseTransactionRollback; } } @@ -165,7 +165,7 @@ __block NSError* error = nil; - [strongCKKS dispatchSync: ^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for(CKRecord* record in savedRecords) { // Save the item records if([record.recordType isEqualToString: SecCKRecordDeviceStateType]) { @@ -176,7 +176,7 @@ } } } - return true; + return CKKSDatabaseTransactionCommit; }]; self.error = error; @@ -184,9 +184,9 @@ }; [self dependOnBeforeGroupFinished: self.modifyRecordsOperation]; - [ckks.database addOperation: self.modifyRecordsOperation]; + [ckks.operationDependencies.ckdatabase addOperation:self.modifyRecordsOperation]; - return true; + return CKKSDatabaseTransactionCommit; }]; } diff --git a/keychain/ckks/CKKSViewManager.h b/keychain/ckks/CKKSViewManager.h index cd6ac8cd..f8841521 100644 --- a/keychain/ckks/CKKSViewManager.h +++ b/keychain/ckks/CKKSViewManager.h @@ -41,13 +41,14 @@ #import "keychain/ckks/CloudKitDependencies.h" #import "keychain/ckks/CKKSZoneChangeFetcher.h" #import "keychain/ckks/CKKSZoneModifier.h" +#import "keychain/ckks/CKKSKeychainBackedKey.h" #import "keychain/ot/OTSOSAdapter.h" #import "keychain/ot/OTDefines.h" NS_ASSUME_NONNULL_BEGIN -@class CKKSKeychainView, CKKSRateLimiter, TPPolicy; +@class CKKSKeychainView, CKKSRateLimiter, TPSyncingPolicy; @interface CKKSViewManager : NSObject @@ -65,27 +66,36 @@ NS_ASSUME_NONNULL_BEGIN @property id sosPeerAdapter; -@property (nullable) TPPolicy* policy; +@property (readonly, nullable) TPSyncingPolicy* policy; -@property NSMutableDictionary* views; +@property (readonly) NSMutableDictionary* views; -- (instancetype)initWithContainerName:(NSString*)containerName - usePCS:(bool)usePCS - sosAdapter:(id _Nullable)sosAdapter - cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; +- (instancetype)initWithContainer:(CKContainer*)container + sosAdapter:(id _Nullable)sosAdapter + accountStateTracker:(CKKSAccountStateTracker*)accountTracker + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker + cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; -- (CKKSKeychainView*)findView:(NSString*)viewName; +// Note: findView will not wait for any views to be created. You must handle +// states where the daemon has not entirely started up yourself +- (CKKSKeychainView* _Nullable)findView:(NSString*)viewName; + +// Similar to findView, but will create the view if it's not already present. - (CKKSKeychainView*)findOrCreateView:(NSString*)viewName; + +// findViewOrError will wait for the Syncing Policy to be loaded, which +// creates all views. Don't call this from any important queues. +- (CKKSKeychainView* _Nullable)findView:(NSString*)viewName error:(NSError**)error; + - (void)setView:(CKKSKeychainView*)obj; - (void)clearView:(NSString*)viewName; - (NSSet*)currentViews; -- (NSDictionary*)activeTLKs; - - (void)setupAnalytics; -- (NSString*)viewNameForItem:(SecDbItemRef)item; +- (NSString* _Nullable)viewNameForItem:(SecDbItemRef)item; - (void)handleKeychainEventDbConnection:(SecDbConnectionRef)dbconn source:(SecDbTransactionSource)txionSource @@ -112,29 +122,34 @@ NS_ASSUME_NONNULL_BEGIN // Cancels pending operations owned by this view manager - (void)cancelPendingOperations; -// Use these to acquire (and set) the singleton + (instancetype)manager; -+ (instancetype _Nullable)resetManager:(bool)reset setTo:(CKKSViewManager* _Nullable)obj; // Called by XPC every 24 hours - (void)xpc24HrNotification; -/* White-box testing only */ -- (CKKSKeychainView*)restartZone:(NSString*)viewName; - -// Returns the viewList for a CKKSViewManager +// Returns the current set of views - (NSSet*)viewList; - (NSSet*)defaultViewList; -- (void)setViewList:(NSSet* _Nullable)newViewList; +// Call this to set the syncing views+policy that this manager will use. +// If beginCloudKitOperationOfAllViews has previously been called, then any new views created +// as a result of this call will begin CK operation. +- (BOOL)setCurrentSyncingPolicy:(TPSyncingPolicy* _Nullable)syncingPolicy; + +// Similar to above, but please only pass policyIsFresh=YES if Octagon has contacted cuttlefish immediately previously +// Returns YES if the view set has changed as part of this set +- (BOOL)setCurrentSyncingPolicy:(TPSyncingPolicy* _Nullable)syncingPolicy policyIsFresh:(BOOL)policyIsFresh; - (void)clearAllViews; // Create all views, but don't begin CK/network operations +// Remove as part of CKKS: ensure we collect keychain changes made before policy is loaded from disk - (void)createViews; // Call this to begin CK operation of all views +// This bit will be 'sticky', in that any new views created with also begin cloudkit operation immediately. +// (clearAllViews will reset this bit.) - (void)beginCloudKitOperationOfAllViews; // Notify sbd to re-backup. @@ -145,11 +160,33 @@ NS_ASSUME_NONNULL_BEGIN // first time after launch, only waits the the initial call - (BOOL)waitForTrustReady; -// For testing -- (void)setOverrideCKKSViewsFromPolicy:(BOOL)value; -- (BOOL)useCKKSViewsFromPolicy; -- (void)haltAll; +// Helper function to make CK containers ++ (CKContainer*)makeCKContainer:(NSString*)containerName + usePCS:(bool)usePCS; +// Checks featureflags to return whether we should use policy-based views, or use the hardcoded list +- (BOOL)useCKKSViewsFromPolicy; + +// Extract TLKs for sending to some peer. Pass restrictToPolicy=True if you want to restrict the returned TLKs +// to what the current policy indicates (allowing to prioritize transferred TLKs) +- (NSArray* _Nullable)currentTLKsFilteredByPolicy:(BOOL)restrictToPolicy error:(NSError**)error; + +// Interfaces to examine sync callbacks +- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString* _Nullable)uuid; +- (NSSet*)pendingCallbackUUIDs; ++ (void)callSyncCallbackWithErrorNoAccount:(SecBoolNSErrorCallback)syncCallback; +@end + +@interface CKKSViewManager (Testing) +- (void)setOverrideCKKSViewsFromPolicy:(BOOL)value; +- (void)resetSyncingPolicy; + +- (void)haltAll; +- (CKKSKeychainView*)restartZone:(NSString*)viewName; +- (void)haltZone:(NSString*)viewName; + +// If set, any set passed to setSyncingViews will be intersected with this set +- (void)setSyncingViewsAllowList:(NSSet* _Nullable)viewNames; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSViewManager.m b/keychain/ckks/CKKSViewManager.m index 8a226dfc..2bfbfd4b 100644 --- a/keychain/ckks/CKKSViewManager.m +++ b/keychain/ckks/CKKSViewManager.m @@ -23,6 +23,7 @@ #import +#import "keychain/ckks/CKKSAccountStateTracker.h" #import "keychain/ckks/CKKSViewManager.h" #import "keychain/ckks/CKKSKeychainView.h" #import "keychain/ckks/CKKSSynchronizeOperation.h" @@ -33,6 +34,7 @@ #import "keychain/ckks/CKKSCondition.h" #import "keychain/ckks/CKKSListenerCollection.h" #import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/OctagonAPSReceiver.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "keychain/analytics/SecEventMetric.h" #import "keychain/analytics/SecMetrics.h" @@ -42,7 +44,7 @@ #import "keychain/ot/OTConstants.h" #import "keychain/ot/ObjCImprovements.h" -#import "TPPolicy.h" +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" #import "SecEntitlements.h" @@ -67,10 +69,16 @@ #import "CKKSAnalytics.h" #endif +#if !OCTAGON @interface CKKSViewManager () -#if OCTAGON +#else +@interface CKKSViewManager () + @property NSXPCListener *listener; +@property (nullable) NSSet* viewAllowList; + // Once you set these, all CKKSKeychainViews created will use them @property CKKSCloudKitClassDependencies* cloudKitClassDependencies; @@ -82,6 +90,13 @@ @property (nonatomic) BOOL overrideCKKSViewsFromPolicy; @property (nonatomic) BOOL valueCKKSViewsFromPolicy; +@property (nonatomic) BOOL startCKOperationAtViewCreation; + +@property BOOL itemModificationsBeforePolicyLoaded; + +// Make writable +@property (nullable) TPSyncingPolicy* policy; +@property CKKSCondition* policyLoaded; #endif @end @@ -94,27 +109,31 @@ @implementation CKKSViewManager #if OCTAGON -NSSet* _viewList; - -- (instancetype)initWithContainerName: (NSString*) containerName - usePCS: (bool)usePCS - sosAdapter:(id _Nullable)sosAdapter - cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies +- (instancetype)initWithContainer:(CKContainer*)container + sosAdapter:(id _Nullable)sosAdapter + accountStateTracker:(CKKSAccountStateTracker*)accountTracker + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker + cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies { if(self = [super init]) { _cloudKitClassDependencies = cloudKitClassDependencies; _sosPeerAdapter = sosAdapter; - _viewList = nil; - _container = [self makeCKContainer: containerName usePCS:usePCS]; - _accountTracker = [[CKKSAccountStateTracker alloc] init:self.container nsnotificationCenterClass:cloudKitClassDependencies.nsnotificationCenterClass]; - _lockStateTracker = [[CKKSLockStateTracker alloc] init]; + _viewAllowList = nil; + _container = container; + _accountTracker = accountTracker; + _lockStateTracker = lockStateTracker; [_lockStateTracker addLockStateObserver:self]; - _reachabilityTracker = [[CKKSReachabilityTracker alloc] init]; + _reachabilityTracker = reachabilityTracker; + _itemModificationsBeforePolicyLoaded = NO; _zoneChangeFetcher = [[CKKSZoneChangeFetcher alloc] initWithContainer:_container fetchClass:cloudKitClassDependencies.fetchRecordZoneChangesOperationClass reachabilityTracker:_reachabilityTracker]; + OctagonAPSReceiver* globalAPSReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:cloudKitClassDependencies.apsConnectionClass]; + [globalAPSReceiver registerCKKSReceiver:_zoneChangeFetcher]; _zoneModifier = [[CKKSZoneModifier alloc] initWithContainer:_container reachabilityTracker:_reachabilityTracker @@ -127,6 +146,8 @@ NSSet* _viewList; _views = [[NSMutableDictionary alloc] init]; _pendingSyncCallbacks = [[NSMutableDictionary alloc] init]; + _startCKOperationAtViewCreation = NO; + _completedSecCKKSInitialize = [[CKKSCondition alloc] init]; WEAKIFY(self); @@ -139,14 +160,22 @@ NSSet* _viewList; [self notifyNewTLKsInKeychain]; }]; + _policy = nil; + _policyLoaded = [[CKKSCondition alloc] init]; + _listener = [NSXPCListener anonymousListener]; _listener.delegate = self; [_listener resume]; + + // Start listening for CK account status (for sync callbacks) + [_accountTracker registerForNotificationsOfCloudKitAccountStatusChange:self]; } return self; } --(CKContainer*)makeCKContainer:(NSString*)containerName usePCS:(bool)usePCS { ++ (CKContainer*)makeCKContainer:(NSString*)containerName + usePCS:(bool)usePCS +{ CKContainer* container = [CKContainer containerWithIdentifier:containerName]; if(!usePCS) { CKContainerOptions* containerOptions = [[CKContainerOptions alloc] init]; @@ -163,7 +192,7 @@ NSSet* _viewList; __block BOOL success = YES; dispatch_once(&onceToken, ^{ OTManager* manager = [OTManager manager]; - if (![manager waitForReady:OTCKContainerName context:OTDefaultContext wait:3*NSEC_PER_SEC]) { + if (![manager waitForReady:OTCKContainerName context:OTDefaultContext wait:2*NSEC_PER_SEC]) { success = NO; } }); @@ -188,7 +217,7 @@ NSSet* _viewList; NSError* sosCircleError = nil; SOSCCStatus sosStatus = [self.sosPeerAdapter circleStatus:&sosCircleError]; if(sosCircleError) { - secerror("CKKSViewManager: couldn't fetch sos status for SF report: %@", sosCircleError); + ckkserror_global("manager", " couldn't fetch sos status for SF report: %@", sosCircleError); } NSMutableDictionary* values = [NSMutableDictionary dictionary]; @@ -221,14 +250,14 @@ NSSet* _viewList; NSError* sosCircleError = nil; SOSCCStatus sosStatus = [self.sosPeerAdapter circleStatus:&sosCircleError]; if(sosCircleError) { - secerror("CKKSViewManager: couldn't fetch sos status for SF report: %@", sosCircleError); + ckkserror_global("manager", " couldn't fetch sos status for SF report: %@", sosCircleError); } BOOL inCircle = (sosStatus == kSOSCCInCircle); NSMutableDictionary* values = [NSMutableDictionary dictionary]; CKKSKeychainView* view = [self findOrCreateView:viewName]; - NSDate* dateOfLastSyncClassA = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassA inView:view]; - NSDate* dateOfLastSyncClassC = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC inView:view]; - NSDate* dateOfLastKSR = [[CKKSAnalytics logger] datePropertyForKey:CKKSAnalyticsLastKeystateReady inView:view]; + NSDate* dateOfLastSyncClassA = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassA zoneName:view.zoneName]; + NSDate* dateOfLastSyncClassC = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC zoneName:view.zoneName]; + NSDate* dateOfLastKSR = [[CKKSAnalytics logger] datePropertyForKey:CKKSAnalyticsLastKeystateReady zoneName:view.zoneName]; NSInteger fuzzyDaysSinceClassASync = [CKKSAnalytics fuzzyDaysSinceDate:dateOfLastSyncClassA]; NSInteger fuzzyDaysSinceClassCSync = [CKKSAnalytics fuzzyDaysSinceDate:dateOfLastSyncClassC]; @@ -237,8 +266,35 @@ NSSet* _viewList; [values setValue:@(fuzzyDaysSinceClassCSync) forKey:[NSString stringWithFormat:@"%@-daysSinceClassCSync", viewName]]; [values setValue:@(fuzzyDaysSinceKSR) forKey:[NSString stringWithFormat:@"%@-daysSinceLastKeystateReady", viewName]]; - BOOL hasTLKs = [view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateReady] || [view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]; - /* only synced recently if between [0...7, ie withing 7 days */ + NSError* ckmeError = nil; + NSNumber* syncedItemRecords = [CKKSMirrorEntry counts:view.zoneID error:&ckmeError]; + if(ckmeError || !syncedItemRecords) { + ckkserror_global("manager", "couldn't fetch CKMirror counts for %@: %@", view.zoneID, ckmeError); + } else { + ckksnotice("metrics", view, "View has %@ item ckrecords", syncedItemRecords); + values[[NSString stringWithFormat:@"%@-%@", viewName, CKKSAnalyticsNumberOfSyncItems]] = [CKKSAnalytics fuzzyNumber:syncedItemRecords]; + } + + NSError* tlkShareCountError = nil; + NSNumber* tlkShareCount = [CKKSTLKShareRecord counts:view.zoneID error:&tlkShareCountError]; + if(tlkShareCountError || !tlkShareCount) { + ckkserror_global("manager", "couldn't fetch CKKSTLKShare counts for %@: %@", view.zoneID, tlkShareCountError); + } else { + ckksnotice("metrics", view, "View has %@ tlkshares", tlkShareCount); + values[[NSString stringWithFormat:@"%@-%@", viewName, CKKSAnalyticsNumberOfTLKShares]] = [CKKSAnalytics fuzzyNumber:tlkShareCount]; + } + + NSError* syncKeyCountError = nil; + NSNumber* syncKeyCount = [CKKSKey counts:view.zoneID error:&syncKeyCountError]; + if(syncKeyCountError || !syncKeyCount) { + ckkserror_global("manager", "couldn't fetch CKKSKey counts for %@: %@", view.zoneID, syncKeyCountError); + } else { + ckksnotice("metrics", view, "View has %@ sync keys", syncKeyCount); + values[[NSString stringWithFormat:@"%@-%@", viewName, CKKSAnalyticsNumberOfSyncKeys]] = syncKeyCount; + } + + BOOL hasTLKs = [view.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateReady] || [view.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]; + /* only synced recently if between [0...7, ie within 7 days */ BOOL syncedClassARecently = fuzzyDaysSinceClassASync >= 0 && fuzzyDaysSinceClassASync < 7; BOOL syncedClassCRecently = fuzzyDaysSinceClassCSync >= 0 && fuzzyDaysSinceClassCSync < 7; BOOL incomingQueueIsErrorFree = view.lastIncomingQueueOperation.error == nil; @@ -292,7 +348,7 @@ dispatch_once_t globalZoneStateQueueOnce; CKKSZoneStateEntry* allEntry = [CKKSZoneStateEntry tryFromDatabase: @"all" error:&error]; if(error) { - secerror("CKKSViewManager: couldn't load global zone state: %@", error); + ckkserror_global("manager", " couldn't load global zone state: %@", error); } if(!error && allEntry.rateLimiter) { @@ -312,6 +368,8 @@ dispatch_once_t globalZoneStateQueueOnce; } } +#pragma mark - View List handling + - (NSSet*)defaultViewList { NSSet* fullList = [OTSOSActualAdapter sosCKKSViewList]; @@ -338,18 +396,115 @@ dispatch_once_t globalZoneStateQueueOnce; return fullList; } --(NSSet*)viewList { - if (_viewList) { - return _viewList; - } else { - return [self defaultViewList]; - } +- (NSSet*)viewList { + return [self.views.allKeys copy]; } -- (void)setViewList:(NSSet* _Nullable)newViewList { - _viewList = newViewList; +- (BOOL)setCurrentSyncingPolicy:(TPSyncingPolicy* _Nullable)syncingPolicy +{ + return [self setCurrentSyncingPolicy:syncingPolicy policyIsFresh:NO]; } +- (BOOL)setCurrentSyncingPolicy:(TPSyncingPolicy* _Nullable)syncingPolicy policyIsFresh:(BOOL)policyIsFresh +{ + if(syncingPolicy == nil) { + ckksnotice_global("ckks-policy", "Nil syncing policy presented; ignoring"); + return NO; + } + + NSSet* viewNames = syncingPolicy.viewList; + ckksnotice_global("ckks-policy", "New syncing policy: %@ views: %@", syncingPolicy, viewNames); + + if(![self useCKKSViewsFromPolicy]) { + // Thanks, but no thanks. + viewNames = [self defaultViewList]; + ckksnotice_global("ckks-policy", "Reverting to default view list: %@", viewNames); + } + + if(self.viewAllowList) { + ckksnotice_global("ckks-policy", "Intersecting view list with allow list: %@", self.viewAllowList); + NSMutableSet* set = [viewNames mutableCopy]; + [set intersectSet:self.viewAllowList]; + + viewNames = set; + ckksnotice_global("ckks-policy", "Final list: %@", viewNames); + } + + // We need to not be synchronized on self.views before issuing commands to CKKS views. + // So, store the pointers for use after the critical section. + NSArray* activeViews = nil; + BOOL scanAll = NO; + BOOL viewsChanged = NO; + + @synchronized(self.views) { + self.policy = syncingPolicy; + + NSArray* previousViewNames = [self.views.allKeys copy]; + + // First, shut down any views that are no longer in the set + for(NSString* viewName in previousViewNames) { + if(![viewNames containsObject:viewName]) { + ckksnotice_global("ckks-policy", "Stopping old view %@", viewName); + [self clearView:viewName]; + viewsChanged = YES; + } + } + + for(NSString* viewName in viewNames) { + CKKSKeychainView* view = nil; + + if([previousViewNames containsObject:viewName]) { + view = [self findView:viewName]; + ckksinfo_global("ckks-policy", "Already have view %@", view); + + } else { + view = [self findOrCreateView:viewName]; + ckksnotice_global("ckks-policy", "Created new view %@", view); + viewsChanged = YES; + } + } + + activeViews = [self.views.allValues copy]; + + if(self.itemModificationsBeforePolicyLoaded) { + ckksnotice_global("ckks-policy", "Issuing scan suggestions to handle missed items"); + scanAll = YES; + self.itemModificationsBeforePolicyLoaded = NO; + } + } + + for(CKKSKeychainView* view in activeViews) { + [view setCurrentSyncingPolicy:self.policy policyIsFresh:policyIsFresh]; + + if(scanAll) { + [view scanLocalItems:@"item-added-before-policy"]; + } + } + + // Retrigger the analytics setup, so that our views will report status + [self setupAnalytics]; + + // The policy is considered loaded once the views have been created + [self.policyLoaded fulfill]; + return viewsChanged; +} + +- (void)setSyncingViewsAllowList:(NSSet*)viewNames +{ + self.viewAllowList = viewNames; +} + +- (void)resetSyncingPolicy +{ + ckksnotice_global("ckks-policy", "Setting policy to nil"); + self.policy = nil; + self.policyLoaded = [[CKKSCondition alloc] init]; + + self.startCKOperationAtViewCreation = NO; +} + +#pragma mark - View Handling + - (void)setView: (CKKSKeychainView*) obj { CKKSKeychainView* kcv = nil; @@ -368,6 +523,8 @@ dispatch_once_t globalZoneStateQueueOnce; @synchronized(self.views) { tempviews = [self.views.allValues copy]; [self.views removeAllObjects]; + + self.startCKOperationAtViewCreation = NO; } for(CKKSKeychainView* view in tempviews) { @@ -391,11 +548,43 @@ dispatch_once_t globalZoneStateQueueOnce; if(!viewName) { return nil; } + @synchronized(self.views) { return self.views[viewName]; } } +- (CKKSKeychainView* _Nullable)findView:(NSString*)viewName error:(NSError**)error +{ + if([self.policyLoaded wait:5*NSEC_PER_SEC] != 0) { + ckkserror_global("ckks", "Haven't yet received a syncing policy; expect failure finding views"); + + if([self useCKKSViewsFromPolicy]) { + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSErrorPolicyNotLoaded + userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"CKKS syncing policy not yet loaded; cannot find view '%@'", viewName]}]; + + } + return nil; + } + } + + @synchronized(self.views) { + CKKSKeychainView* view = self.views[viewName]; + if(!view) { + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNoSuchView + userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No syncing view for '%@'", viewName]}]; + } + return nil; + } + + return view; + } +} + - (CKKSKeychainView*)findOrCreateView:(NSString*)viewName { @synchronized(self.views) { CKKSKeychainView* kcv = self.views[viewName]; @@ -412,6 +601,10 @@ dispatch_once_t globalZoneStateQueueOnce; zoneModifier:self.zoneModifier savedTLKNotifier: self.savedTLKNotifier cloudKitClassDependencies:self.cloudKitClassDependencies]; + + if(self.startCKOperationAtViewCreation) { + [self.views[viewName] beginCloudKitOperation]; + } return self.views[viewName]; } } @@ -429,43 +622,44 @@ dispatch_once_t globalZoneStateQueueOnce; - (void)createViews { - // In the future, the CKKSViewManager needs to persist its policy property through daemon restarts - // and load it here, before creating whatever views it was told to (in a previous daemon lifetime) - for (NSString* viewName in self.viewList) { - CKKSKeychainView* view = [self findOrCreateView:viewName]; - (void)view; + if(![self useCKKSViewsFromPolicy]) { + // In the future, the CKKSViewManager needs to persist its policy property through daemon restarts + // and load it here, before creating whatever views it was told to (in a previous daemon lifetime) + for (NSString* viewName in [self defaultViewList]) { + CKKSKeychainView* view = [self findOrCreateView:viewName]; + (void)view; + } + } else { + ckksnotice_global("ckks-views", "Not loading default view list due to enabled CKKS4All"); } } - (void)beginCloudKitOperationOfAllViews { - for (NSString* viewName in self.viewList) { - CKKSKeychainView* view = [self findView:viewName]; + self.startCKOperationAtViewCreation = YES; + + for (CKKSKeychainView* view in self.views.allValues) { [view beginCloudKitOperation]; } } -- (NSDictionary *)activeTLKs +- (void)haltZone:(NSString*)viewName { - NSMutableDictionary *tlks = [NSMutableDictionary new]; @synchronized(self.views) { - for (NSString *name in self.views) { - CKKSKeychainView *view = self.views[name]; - NSString *tlk = view.lastActiveTLKUUID; - if (tlk) { - tlks[name] = tlk; - } - } + CKKSKeychainView* view = self.views[viewName]; + [view halt]; + [view cancelAllOperations]; + self.views[viewName] = nil; } - return tlks; } - (CKKSKeychainView*)restartZone:(NSString*)viewName { - @synchronized(self.views) { - [self.views[viewName] halt]; - self.views[viewName] = nil; - } - return [self findOrCreateView: viewName]; + [self haltZone:viewName]; + CKKSKeychainView* view = [self findOrCreateView: viewName]; + + [view setCurrentSyncingPolicy:self.policy policyIsFresh:NO]; + + return view; } - (NSString*)viewNameForViewHint: (NSString*) viewHint { @@ -491,35 +685,44 @@ dispatch_once_t globalZoneStateQueueOnce; if (self.overrideCKKSViewsFromPolicy) { return self.valueCKKSViewsFromPolicy; } else { - return os_feature_enabled(Security, CKKSViewsFromPolicy); + BOOL viewsFromPolicy = os_feature_enabled(Security, CKKSViewsFromPolicy); + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + ckksnotice_global("ckks", "ViewsFromPolicy feature flag: %@", viewsFromPolicy ? @"on" : @"off"); + }); + return viewsFromPolicy; } } -- (NSString*)viewNameForItem: (SecDbItemRef) item { +- (NSString* _Nullable)viewNameForItem:(SecDbItemRef)item +{ if ([self useCKKSViewsFromPolicy]) { CFErrorRef cferror = NULL; - NSMutableDictionary *dict = (__bridge_transfer NSMutableDictionary*) SecDbItemCopyPListWithMask(item, ~0, &cferror); + NSMutableDictionary *dict = (__bridge_transfer NSMutableDictionary*) SecDbItemCopyPListWithMask(item, kSecDbSyncFlag, &cferror); if(cferror) { - secerror("ckks: Couldn't fetch attributes from item: %@", cferror); + ckkserror_global("ckks", "Couldn't fetch attributes from item: %@", cferror); CFReleaseNull(cferror); - return [self viewNameForViewHint: nil]; + return nil; } - TPPolicy* policy = self.policy; - if (policy == nil) { - return [self viewNameForViewHint: nil]; - } - NSString* view = [policy mapKeyToView:dict]; + + // Ensure that we've added the class name, because SecDbItemCopyPListWithMask doesn't do that for some reason. + dict[(__bridge NSString*)kSecClass] = (__bridge NSString*)item->class->name; + + NSString* view = [self.policy mapDictionaryToView:dict]; if (view == nil) { - return [self viewNameForViewHint: nil]; + ckkserror_global("ckks", "No view returned from policy (%@): %@", self.policy, item); + return nil; } + return view; } else { CFErrorRef cferror = NULL; NSString* viewHint = (__bridge NSString*) SecDbItemGetValue(item, &v7vwht, &cferror); if(cferror) { - secerror("ckks: Couldn't fetch the viewhint for some reason: %@", cferror); + ckkserror_global("ckks", "Couldn't fetch the viewhint for some reason: %@", cferror); CFReleaseNull(cferror); viewHint = nil; } @@ -531,15 +734,67 @@ dispatch_once_t globalZoneStateQueueOnce; - (void)registerSyncStatusCallback: (NSString*) uuid callback: (SecBoolNSErrorCallback) callback { // Someone is requesting future notification of this item. @synchronized(self.pendingSyncCallbacks) { + ckksnotice_global("ckkscallback", "registered callback for UUID: %@", uuid); self.pendingSyncCallbacks[uuid] = callback; } } +- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString* _Nullable)uuid +{ + if(!uuid) { + return nil; + } + + @synchronized(self.pendingSyncCallbacks) { + SecBoolNSErrorCallback callback = self.pendingSyncCallbacks[uuid]; + + if(callback) { + ckksnotice_global("ckkscallback", "fetched UUID: %@", uuid); + } + + self.pendingSyncCallbacks[uuid] = nil; + return callback; + } +} + +- (NSSet*)pendingCallbackUUIDs +{ + @synchronized(self.pendingSyncCallbacks) { + return [[self.pendingSyncCallbacks allKeys] copy]; + } +} + +- (void)cloudkitAccountStateChange:(CKAccountInfo* _Nullable)oldAccountInfo to:(CKAccountInfo*)currentAccountInfo +{ + if(currentAccountInfo.accountStatus == CKAccountStatusAvailable && currentAccountInfo.hasValidCredentials) { + // Account is okay! + } else { + @synchronized(self.pendingSyncCallbacks) { + if(self.pendingSyncCallbacks.count > 0) { + ckksnotice_global("ckkscallback", "No CK account; failing all pending sync callbacks"); + + for(NSString* uuid in [self.pendingSyncCallbacks allKeys]) { + [CKKSViewManager callSyncCallbackWithErrorNoAccount:self.pendingSyncCallbacks[uuid]]; + } + + [self.pendingSyncCallbacks removeAllObjects]; + } + } + } +} + ++ (void)callSyncCallbackWithErrorNoAccount:(SecBoolNSErrorCallback)syncCallback +{ + // I don't love using this domain, but PCS depends on it + syncCallback(false, [NSError errorWithDomain:@"securityd" + code:errSecNotLoggedIn + description:@"No iCloud account available; item is not expected to sync"]); +} + - (void) handleKeychainEventDbConnection: (SecDbConnectionRef) dbconn source:(SecDbTransactionSource)txionSource added: (SecDbItemRef) added deleted: (SecDbItemRef) deleted { SecDbItemRef modified = added ? added : deleted; - NSString* viewName = [self viewNameForItem: modified]; NSString* keyViewName = [CKKSKey isItemKeyForKeychainView: modified]; if(keyViewName) { @@ -557,44 +812,56 @@ dispatch_once_t globalZoneStateQueueOnce; return; } - // When SOS is in charge of a view, CKKS is not. - // Since this isn't a CKKS key item, we don't care about it. - if(txionSource == kSecDbSOSTransaction) { - secinfo("ckks", "Ignoring new non-CKKS item in kSecDbSOSTransaction notification"); + bool addedSync = added && SecDbItemIsSyncable(added); + bool deletedSync = deleted && SecDbItemIsSyncable(deleted); + + if(!addedSync && !deletedSync) { + // Local-only change. Skip with prejudice. + ckksinfo_global("ckks", "skipping sync of non-sync item (%d, %d)", addedSync, deletedSync); + return; + } + + NSString* viewName = nil; + + @synchronized(self.views) { + if([self useCKKSViewsFromPolicy] && !self.policy) { + ckkserror_global("ckks", "No policy configured(%@). Skipping item: %@", self.policy, modified); + self.itemModificationsBeforePolicyLoaded = YES; + + return; + } + } + + viewName = [self viewNameForItem:modified]; + + if(!viewName) { + ckksnotice_global("ckks", "No intended CKKS view for item; skipping: %@", modified); + return; } // Looks like a normal item. Proceed! CKKSKeychainView* view = [self findView:viewName]; - NSString* uuid = (__bridge NSString*) SecDbItemGetValue(modified, &v10itemuuid, NULL); - SecBoolNSErrorCallback syncCallback = nil; - if(uuid) { - @synchronized(self.pendingSyncCallbacks) { - syncCallback = self.pendingSyncCallbacks[uuid]; - self.pendingSyncCallbacks[uuid] = nil; - - if(syncCallback) { - secinfo("ckks", "Have a pending callback for %@; passing along", uuid); - } - } - } - if(!view) { - if(viewName) { - secnotice("ckks", "No CKKS view for %@, skipping: %@", viewName, modified); - } else { - secinfo("ckks", "No CKKS view for %@, skipping: %@", viewName, modified); - } + ckksnotice_global("ckks", "No CKKS view for %@, skipping: %@", viewName, modified); + + NSString* uuid = (__bridge NSString*) SecDbItemGetValue(modified, &v10itemuuid, NULL); + SecBoolNSErrorCallback syncCallback = [self claimCallbackForUUID:uuid]; + if(syncCallback) { - syncCallback(false, [NSError errorWithDomain:@"securityd" - code:kSOSCCNoSuchView + syncCallback(false, [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNoSuchView userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No syncing view for '%@'", viewName]}]); } return; } ckksnotice("ckks", view, "Routing item to zone %@: %@", viewName, modified); - [view handleKeychainEventDbConnection: dbconn added:added deleted:deleted rateLimiter:self.globalRateLimiter syncCallback: syncCallback]; + [view handleKeychainEventDbConnection:dbconn + source:txionSource + added:added + deleted:deleted + rateLimiter:self.globalRateLimiter]; } -(void)setCurrentItemForAccessGroup:(NSData* _Nonnull)newItemPersistentRef @@ -606,13 +873,12 @@ dispatch_once_t globalZoneStateQueueOnce; hash:(NSData*)oldItemSHA1 complete:(void (^) (NSError* operror)) complete { - CKKSKeychainView* view = [self findView:viewHint]; + NSError* viewError = nil; + CKKSKeychainView* view = [self findView:viewHint error:&viewError]; if(!view) { - secnotice("ckks", "No CKKS view for %@, skipping current request", viewHint); - complete([NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoSuchView - description:[NSString stringWithFormat: @"No syncing view for view hint '%@'", viewHint]]); + ckksnotice_global("ckks", "No CKKS view for %@, skipping setcurrent request: %@", viewHint, viewError); + complete(viewError); return; } @@ -631,12 +897,11 @@ dispatch_once_t globalZoneStateQueueOnce; fetchCloudValue:(bool)fetchCloudValue complete:(void (^) (NSString* uuid, NSError* operror)) complete { - CKKSKeychainView* view = [self findView:viewHint]; + NSError* viewError = nil; + CKKSKeychainView* view = [self findView:viewHint error:&viewError]; if(!view) { - secnotice("ckks", "No CKKS view for %@, skipping current fetch request", viewHint); - complete(NULL, [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoSuchView - description:[NSString stringWithFormat: @"No view for '%@'", viewHint]]); + ckksnotice_global("ckks", "No CKKS view for %@, skipping current fetch request: %@", viewHint, viewError); + complete(NULL, viewError); return; } @@ -646,40 +911,9 @@ dispatch_once_t globalZoneStateQueueOnce; complete:complete]; } - -+ (instancetype) manager { - return [self resetManager: false setTo: nil]; -} - -+ (instancetype) resetManager: (bool) reset setTo: (CKKSViewManager*) obj { - static CKKSViewManager* manager = nil; - - if([CKDatabase class] == nil) { - secerror("CKKS: CloudKit.framework appears to not be linked. Can't create CKKS objects."); - return nil; - } - - if(!manager || reset || obj) { - @synchronized([self class]) { - if(obj != nil) { - [manager clearAllViews]; - manager = obj; - } else { - if(reset) { - [manager clearAllViews]; - manager = nil; - } else if (manager == nil && SecCKKSIsEnabled()) { - // The CKKSViewManager doesn't do much with its adapter, so leave as nonessentialq - manager = [[CKKSViewManager alloc] initWithContainerName:SecCKKSContainerName - usePCS:SecCKKSContainerUsePCS - sosAdapter:[[OTSOSActualAdapter alloc] initAsEssential:NO] - cloudKitClassDependencies:[CKKSCloudKitClassDependencies forLiveCloudKit]]; - } - } - } - } - - return manager; ++ (instancetype)manager +{ + return [OTManager manager].viewManager; } - (void)cancelPendingOperations { @@ -688,7 +922,7 @@ dispatch_once_t globalZoneStateQueueOnce; -(void)notifyNewTLKsInKeychain { // Why two functions here? Limitation of OCMock, unfortunately: can't stub and expect the same method - secnotice("ckksbackup", "New TLKs have arrived"); + ckksnotice_global("ckksbackup", "New TLKs have arrived"); [self syncBackupAndNotifyAboutSync]; } @@ -696,7 +930,7 @@ dispatch_once_t globalZoneStateQueueOnce; SOSAccount* account = (__bridge SOSAccount*)SOSKeychainAccountGetSharedAccount(); if(!account) { - secnotice("ckks", "Failed to get account object"); + ckksnotice_global("ckks", "Failed to get account object"); return; } @@ -706,14 +940,71 @@ dispatch_once_t globalZoneStateQueueOnce; (void)ignore; if(error) { - secerror("ckksbackup: Couldn't process sync with backup peers: %@", error); + ckkserror_global("backup", "Couldn't process sync with backup peers: %@", error); } else { - secnotice("ckksbackup", "telling CloudServices about TLK arrival"); + ckksnotice_global("ckksbackup", "telling CloudServices about TLK arrival"); notify_post(kSecItemBackupNotification); }; }]; } + + +- (NSArray* _Nullable)currentTLKsFilteredByPolicy:(BOOL)restrictToPolicy error:(NSError**)error +{ + NSError* localError = nil; + NSArray* actualViews = [self views:nil operation:@"current TLKs" error:&localError]; + if(localError) { + ckkserror_global("ckks", "Error getting views: %@", localError); + if(error) { + *error = localError; + } + return nil; + } + + NSMutableArray*>* keyFetchOperations = [NSMutableArray array]; + for (CKKSKeychainView* view in actualViews) { + if(restrictToPolicy && [self useCKKSViewsFromPolicy] && ![self.policy.viewsToPiggybackTLKs containsObject:view.zoneName]) { + continue; + } + + CKKSResultOperation* op = [view findKeySet:NO]; + [op timeout:10*NSEC_PER_SEC]; + [keyFetchOperations addObject:op]; + } + + NSMutableArray* tlks = [NSMutableArray array]; + + for(CKKSResultOperation* op in keyFetchOperations) { + [op waitUntilFinished]; + + if(op.error) { + ckkserror_global("ckks", "Error getting keyset: %@", op.error); + if(error) { + *error = op.error; + } + } else { + if(op.keyset.tlk) { + // Keys provided by this function must have the key material loaded + NSError* loadError = nil; + [op.keyset.tlk ensureKeyLoaded:&loadError]; + if(loadError) { + ckkserror_global("ckks", "Error loading key: %@", loadError); + if(error) { + *error = loadError; + } + } else { + [tlks addObject:[op.keyset.tlk.keycore copy]]; + } + } else { + ckkserror_global("ckks", "Do not have TLK: %@", op.keyset); + } + } + } + + return tlks; +} + #pragma mark - RPCs to manage and report state - (void)performanceCounters:(void(^)(NSDictionary *counter))reply { @@ -721,32 +1012,53 @@ dispatch_once_t globalZoneStateQueueOnce; } - (NSArray*)views:(NSString*)viewName operation:(NSString*)opName error:(NSError**)error +{ + return [self views:viewName operation:opName errorOnPolicyMissing:YES error:error]; +} + +- (NSArray*)views:(NSString*)viewName + operation:(NSString*)opName + errorOnPolicyMissing:(BOOL)errorOnPolicyMissing + error:(NSError**)error { NSArray* actualViews = nil; // Ensure we've actually set up, but don't wait too long. Clients get impatient. if([self.completedSecCKKSInitialize wait:5*NSEC_PER_SEC]) { - secerror("ckks: Haven't yet initialized zones; expect failure fetching views"); + ckkserror_global("ckks", "Haven't yet initialized zones; expect failure fetching views"); } - @synchronized(self.views) { - if(viewName) { - CKKSKeychainView* view = self.views[viewName]; - secnotice("ckks", "Received a %@ request for zone %@ (%@)", opName, viewName, view); + // If the caller doesn't mind if the policy is missing, wait some, but not the full 5s + BOOL policyLoaded = [self.policyLoaded wait:(errorOnPolicyMissing ? 5 : 0.5)*NSEC_PER_SEC] == 0; + if(!policyLoaded) { + ckkserror_global("ckks", "Haven't yet received a policy; expect failure fetching views"); + } - if(!view) { + if(viewName) { + CKKSKeychainView* view = errorOnPolicyMissing ? [self findView:viewName error:error] : [self findView:viewName]; + ckksnotice_global("ckks", "Received a %@ request for zone %@ (%@)", opName, viewName, view); + + if(!view) { + return nil; + } + + actualViews = @[view]; + + } else { + if(!policyLoaded && [self useCKKSViewsFromPolicy] && errorOnPolicyMissing) { + if(error) { if(error) { *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoSuchView - userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No view for '%@'", viewName]}]; + code:CKKSErrorPolicyNotLoaded + userInfo:@{NSLocalizedDescriptionKey: @"CKKS syncing policy not yet loaded; cannot list all views"}]; } - return nil; } + return nil; + } - actualViews = @[view]; - } else { + @synchronized(self.views) { actualViews = [self.views.allValues copy]; - secnotice("ckks", "Received a %@ request for all zones: %@", opName, actualViews); + ckksnotice_global("ckks", "Received a %@ request for all zones: %@", opName, actualViews); } } actualViews = [actualViews sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"zoneName" ascending:YES]]]; @@ -757,16 +1069,16 @@ dispatch_once_t globalZoneStateQueueOnce; NSError* localError = nil; NSArray* actualViews = [self views:viewName operation:@"local reset" error:&localError]; if(localError) { - secerror("ckks: Error getting view %@: %@", viewName, localError); + ckkserror_global("ckks", "Error getting view %@: %@", viewName, localError); reply(localError); return; } CKKSResultOperation* op = [CKKSResultOperation named:@"local-reset-zones-waiter" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull strongOp) { if(!strongOp.error) { - secnotice("ckksreset", "Completed rpcResetLocal"); + ckksnotice_global("ckksreset", "Completed rpcResetLocal"); } else { - secnotice("ckks", "Completed rpcResetLocal with error: %@", strongOp.error); + ckksnotice_global("ckks", "Completed rpcResetLocal with error: %@", strongOp.error); } reply(CKXPCSuitableError(strongOp.error)); }]; @@ -784,7 +1096,7 @@ dispatch_once_t globalZoneStateQueueOnce; NSError* localError = nil; NSArray* actualViews = [self views:viewName operation:@"CloudKit reset" error:&localError]; if(localError) { - secerror("ckks: Error getting view %@: %@", viewName, localError); + ckkserror_global("ckks", "Error getting view %@: %@", viewName, localError); reply(localError); return; } @@ -796,9 +1108,9 @@ dispatch_once_t globalZoneStateQueueOnce; [op setCompletionBlock:^{ __strong __typeof(op) strongOp = weakOp; if(!strongOp.error) { - secnotice("ckksreset", "Completed rpcResetCloudKit"); + ckksnotice_global("ckksreset", "Completed rpcResetCloudKit"); } else { - secnotice("ckksreset", "Completed rpcResetCloudKit with error: %@", strongOp.error); + ckksnotice_global("ckksreset", "Completed rpcResetCloudKit with error: %@", strongOp.error); } reply(CKXPCSuitableError(strongOp.error)); }]; @@ -817,7 +1129,7 @@ dispatch_once_t globalZoneStateQueueOnce; NSError* localError = nil; NSArray* actualViews = [self views:viewName operation:@"CloudKit resync" error:&localError]; if(localError) { - secerror("ckks: Error getting view %@: %@", viewName, localError); + ckkserror_global("ckks", "Error getting view %@: %@", viewName, localError); reply(localError); return; } @@ -829,7 +1141,7 @@ dispatch_once_t globalZoneStateQueueOnce; // Use the completion block instead of the operation block, so that it runs even if the cancel fires [op setCompletionBlock:^{ __strong __typeof(op) strongOp = weakOp; - secnotice("ckks", "Ending rsync-CloudKit rpc with %@", strongOp.error); + ckksnotice_global("ckks", "Ending rsync-CloudKit rpc with %@", strongOp.error); reply(CKXPCSuitableError(strongOp.error)); }]; @@ -848,7 +1160,7 @@ dispatch_once_t globalZoneStateQueueOnce; NSError* localError = nil; NSArray* actualViews = [self views:viewName operation:@"local resync" error:&localError]; if(localError) { - secerror("ckks: Error getting view %@: %@", viewName, localError); + ckkserror_global("ckks", "Error getting view %@: %@", viewName, localError); reply(localError); return; } @@ -859,7 +1171,7 @@ dispatch_once_t globalZoneStateQueueOnce; // Use the completion block instead of the operation block, so that it runs even if the cancel fires [op setCompletionBlock:^{ __strong __typeof(op) strongOp = weakOp; - secnotice("ckks", "Ending rsync-local rpc with %@", strongOp.error); + ckksnotice_global("ckks", "Ending rsync-local rpc with %@", strongOp.error); reply(CKXPCSuitableError(strongOp.error)); }]; @@ -879,9 +1191,9 @@ dispatch_once_t globalZoneStateQueueOnce; { NSMutableArray* a = [[NSMutableArray alloc] init]; - // Now, query the views about their status + // Now, query the views about their status. Don't wait for the policy to be loaded NSError* error = nil; - NSArray* actualViews = [self views:viewName operation:@"status" error:&error]; + NSArray* actualViews = [self views:viewName operation:@"status" errorOnPolicyMissing:NO error:&error]; if(!actualViews || error) { reply(nil, error); return; @@ -907,6 +1219,8 @@ dispatch_once_t globalZoneStateQueueOnce; @"lockstatetracker": stringify(self.lockStateTracker), @"cloudkitRetryAfter": stringify(self.zoneModifier.cloudkitRetryAfter), @"lastCKKSPush": CKKSNilToNSNull(lastCKKSPush), + @"policy": stringify(self.policy), + @"viewsFromPolicy": [self useCKKSViewsFromPolicy] ? @"yes" : @"no", }; [a addObject: global]; } @@ -928,22 +1242,24 @@ dispatch_once_t globalZoneStateQueueOnce; }]; // If we're signed in, give the views a few seconds to enter what they consider to be a non-transient state (in case this daemon just launched) - if([self.accountTracker.ckAccountInfoInitialized wait:5*NSEC_PER_SEC]) { - secerror("ckks status: Haven't yet figured out cloudkit account state"); + if([self.accountTracker.ckAccountInfoInitialized wait:2*NSEC_PER_SEC]) { + ckkserror_global("account", "Haven't yet figured out cloudkit account state"); } if(self.accountTracker.currentCKAccountInfo.accountStatus == CKAccountStatusAvailable) { if (![self waitForTrustReady]) { - secerror("ckks status: Haven't yet figured out trust status"); + ckkserror_global("trust", "Haven't yet figured out trust status"); } - CKKSResultOperation* blockOp = [CKKSResultOperation named:@"wait-for-status" withBlock:^{}]; - [blockOp timeout:8*NSEC_PER_SEC]; for(CKKSKeychainView* view in actualViews) { - [blockOp addNullableDependency:view.keyStateNonTransientDependency]; + OctagonStateMultiStateArrivalWatcher* waitForTransient = [[OctagonStateMultiStateArrivalWatcher alloc] initNamed:@"rpc-watcher" + serialQueue:view.queue + states:CKKSKeyStateNonTransientStates()]; + [waitForTransient timeout:2*NSEC_PER_SEC]; + [view.stateMachine registerMultiStateArrivalWatcher:waitForTransient]; + + [statusOp addDependency:waitForTransient.result]; } - [statusOp addDependency:blockOp]; - [self.operationQueue addOperation:blockOp]; } [self.operationQueue addOperation:statusOp]; @@ -990,7 +1306,7 @@ dispatch_once_t globalZoneStateQueueOnce; ckksnotice("ckks", view, "Beginning fetch for %@", view); CKKSResultOperation* op = [view processIncomingQueue:classAError after:[view.zoneChangeFetcher requestSuccessfulFetch: CKKSFetchBecauseAPIFetchRequest]]; - [blockOp addDependency:op]; + [blockOp addSuccessDependency:op]; } [self.operationQueue addOperation: [blockOp timeout:(SecCKKSTestsEnabled() ? NSEC_PER_SEC * 5 : NSEC_PER_SEC * 120)]]; @@ -1018,7 +1334,7 @@ dispatch_once_t globalZoneStateQueueOnce; ckksnotice("ckks-rpc", view, "Beginning push for %@", view); CKKSResultOperation* op = [view processOutgoingQueue: [CKOperationGroup CKKSGroupWithName:@"rpc-push"]]; - [blockOp addDependency:op]; + [blockOp addSuccessDependency:op]; } [self.operationQueue addOperation: [blockOp timeout:(SecCKKSTestsEnabled() ? NSEC_PER_SEC * 2 : NSEC_PER_SEC * 120)]]; @@ -1042,15 +1358,14 @@ dispatch_once_t globalZoneStateQueueOnce; }]; [[SecMetrics managerObject] submitEvent:metric]; reply(NULL); - } -(void)xpc24HrNotification { // XPC has poked us and said we should do some cleanup! - secnotice("ckks", "Received a 24hr notification from XPC"); + ckksnotice_global("ckks", "Received a 24hr notification from XPC"); if (![self waitForTrustReady]) { - secnotice("ckks", "Trust not ready, still going ahead"); + ckksnotice_global("ckks", "Trust not ready, still going ahead"); } [[CKKSAnalytics logger] dailyCoreAnalyticsMetrics:@"com.apple.security.CKKSHealthSummary"]; @@ -1067,19 +1382,19 @@ dispatch_once_t globalZoneStateQueueOnce; ckksnotice("ckks", view, "Starting device state XPC update"); // Let the update know it should rate-limit itself [view updateDeviceState:true waitForKeyHierarchyInitialization:30*NSEC_PER_SEC ckoperationGroup:group]; + [view xpc24HrNotification]; } } - (void)haltAll { - [self.zoneModifier halt]; - @synchronized(self.views) { for(CKKSKeychainView* view in self.views.allValues) { [view halt]; } } + [self.zoneModifier halt]; } #endif // OCTAGON diff --git a/keychain/ckks/CKKSZone.h b/keychain/ckks/CKKSZone.h deleted file mode 100644 index 5869326c..00000000 --- a/keychain/ckks/CKKSZone.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#import - -#if OCTAGON -#import "keychain/ckks/CKKSAccountStateTracker.h" -#import "keychain/ckks/CKKSReachabilityTracker.h" -#import "keychain/ckks/CloudKitDependencies.h" -#import "keychain/ckks/CKKSCloudKitClassDependencies.h" -#import "keychain/ckks/OctagonAPSReceiver.h" -#import "keychain/ckks/CKKSGroupOperation.h" -#import "keychain/ckks/CKKSNearFutureScheduler.h" -#import "keychain/ckks/CKKSZoneModifier.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface CKKSZone : NSObject -{ - CKContainer* _container; - CKDatabase* _database; - CKRecordZone* _zone; -} - -@property (readonly) NSString* zoneName; - -@property CKKSGroupOperation* zoneSetupOperation; -@property (nullable) CKOperationGroup* zoneSetupOperationGroup; // set this if you want zone creates to use a different operation group - -@property bool zoneCreated; -@property bool zoneSubscribed; -@property (nullable) NSError* zoneCreatedError; -@property (nullable) NSError* zoneSubscribedError; - -// True if this zone object has been halted. Halted zones will never recover. -@property (readonly) bool halted; - -@property CKKSAccountStatus accountStatus; - -@property (readonly) CKContainer* container; -@property (readonly) CKDatabase* database; - -@property (weak) CKKSAccountStateTracker* accountTracker; -@property (weak) CKKSReachabilityTracker* reachabilityTracker; - -@property (readonly) CKRecordZone* zone; -@property (readonly) CKRecordZoneID* zoneID; - -@property (readonly) CKKSZoneModifier* zoneModifier; - -// Dependencies (for injection) -@property (readonly) CKKSCloudKitClassDependencies* cloudKitClassDependencies; - -@property dispatch_queue_t queue; - -- (instancetype)initWithContainer:(CKContainer*)container - zoneName:(NSString*)zoneName - accountTracker:(CKKSAccountStateTracker*)accountTracker - reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker - zoneModifier:(CKKSZoneModifier*)zoneModifier - cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; - - -- (CKKSResultOperation* _Nullable)deleteCloudKitZoneOperation:(CKOperationGroup* _Nullable)ckoperationGroup; - -// Called when CloudKit notifies us that we just logged in. -// That is, if we transition from any state to CKAccountStatusAvailable. -// This will be called under the protection of dispatchSync. -// This is a no-op; you should intercept this call and call handleCKLogin:zoneSubscribed: -// with the appropriate state -- (void)handleCKLogin; - -// Actually start a cloudkit login. Pass in whether you believe this zone has been created and if this device has -// subscribed to this zone on the server. -- (CKKSResultOperation* _Nullable)handleCKLogin:(bool)zoneCreated zoneSubscribed:(bool)zoneSubscribed; - -// Called when CloudKit notifies us that we just logged out. -// i.e. we transition from CKAccountStatusAvailable to any other state. -// This will be called under the protection of dispatchSync -- (void)handleCKLogout; - -// Call this when you're ready for this zone to kick off operations -// based on iCloud account status -- (void)beginCloudKitOperation; - -// Cancels all operations (no matter what they are). -- (void)cancelAllOperations; - -// Schedules this operation for execution (if the CloudKit account exists) -- (bool)scheduleOperation:(NSOperation*)op; - -// Use this to schedule an operation handling account status (cleaning up after logout, etc.). -- (bool)scheduleAccountStatusOperation:(NSOperation*)op; - -// Schedules this operation for execution, and doesn't do any dependency magic -// This should _only_ be used if you want to run something even if the CloudKit account is logged out -- (bool)scheduleOperationWithoutDependencies:(NSOperation*)op; - -// Use this for testing. -- (void)waitUntilAllOperationsAreFinished; - -// Use this for testing, to only wait for a certain type of operation to finish. -- (void)waitForOperationsOfClass:(Class)operationClass; - -// If this object wants to do anything that needs synchronization, use this. -// If this object has had -halt called, this block will never fire. -- (void)dispatchSync:(bool (^)(void))block; - -// Call this to halt everything this zone is doing. This object will never recover. Use for testing. -- (void)halt; - -// Call this to reset this object's setup, so you can call createSetupOperation again. -- (void)resetSetup; - -@end - -NS_ASSUME_NONNULL_END -#endif // OCTAGON diff --git a/keychain/ckks/CKKSZone.m b/keychain/ckks/CKKSZone.m deleted file mode 100644 index b51bf477..00000000 --- a/keychain/ckks/CKKSZone.m +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include - -#import - -#if OCTAGON -#import "CloudKitDependencies.h" -#import "keychain/ckks/CKKSAccountStateTracker.h" -#import "keychain/ckks/CloudKitCategories.h" -#import "keychain/categories/NSError+UsefulConstructors.h" -#import -#import - -#import "keychain/ot/ObjCImprovements.h" - -#import "CKKSKeychainView.h" -#import "CKKSZone.h" - -#include - -@interface CKKSZone() - -@property CKDatabaseOperation* zoneCreationOperation; -@property CKDatabaseOperation* zoneDeletionOperation; -@property CKDatabaseOperation* zoneSubscriptionOperation; - -@property NSOperationQueue* operationQueue; -@property CKKSResultOperation* accountLoggedInDependency; - -@property NSHashTable* accountOperations; - -// Make writable -@property bool halted; -@end - -@implementation CKKSZone - -- (instancetype)initWithContainer:(CKContainer*)container - zoneName:(NSString*)zoneName - accountTracker:(CKKSAccountStateTracker*)accountTracker - reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker - zoneModifier:(CKKSZoneModifier*)zoneModifier - cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies -{ - if(self = [super init]) { - _container = container; - _zoneName = zoneName; - _accountTracker = accountTracker; - _reachabilityTracker = reachabilityTracker; - - _zoneModifier = zoneModifier; - - _halted = false; - - _database = [_container privateCloudDatabase]; - _zone = [[CKRecordZone alloc] initWithZoneID: [[CKRecordZoneID alloc] initWithZoneName:zoneName ownerName:CKCurrentUserDefaultName]]; - - _accountStatus = CKKSAccountStatusUnknown; - - _accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in."]; - - _accountOperations = [NSHashTable weakObjectsHashTable]; - - _cloudKitClassDependencies = cloudKitClassDependencies; - - _queue = dispatch_queue_create([[NSString stringWithFormat:@"CKKSQueue.%@.zone.%@", container.containerIdentifier, zoneName] UTF8String], DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - _operationQueue = [[NSOperationQueue alloc] init]; - } - return self; -} - -- (CKKSResultOperation*)createAccountLoggedInDependency:(NSString*)message { - WEAKIFY(self); - CKKSResultOperation* accountLoggedInDependency = [CKKSResultOperation named:@"account-logged-in-dependency" withBlock:^{ - STRONGIFY(self); - ckksnotice("ckkszone", self, "%@", message); - }]; - accountLoggedInDependency.descriptionErrorCode = CKKSResultDescriptionPendingAccountLoggedIn; - return accountLoggedInDependency; -} - -- (void)beginCloudKitOperation { - [self.accountTracker registerForNotificationsOfCloudKitAccountStatusChange:self]; -} - -- (void)resetSetup { - self.zoneCreated = false; - self.zoneSubscribed = false; - self.zoneCreatedError = nil; - self.zoneSubscribedError = nil; - - self.zoneCreationOperation = nil; - self.zoneSubscriptionOperation = nil; - self.zoneDeletionOperation = nil; -} - -- (CKRecordZoneID*)zoneID { - return [self.zone zoneID]; -} - -- (CKKSAccountStatus)accountStatusFromCKAccountInfo:(CKAccountInfo*)info -{ - if(!info) { - return CKKSAccountStatusUnknown; - } - if(info.accountStatus == CKAccountStatusAvailable && - info.hasValidCredentials) { - return CKKSAccountStatusAvailable; - } else { - return CKKSAccountStatusNoAccount; - } -} - - -- (void)cloudkitAccountStateChange:(CKAccountInfo* _Nullable)oldAccountInfo to:(CKAccountInfo*)currentAccountInfo -{ - ckksnotice("ckkszone", self, "%@ Received notification of CloudKit account status change, moving from %@ to %@", - self.zoneID.zoneName, - oldAccountInfo, - currentAccountInfo); - - // Filter for device2device encryption and cloudkit grey mode - CKKSAccountStatus oldStatus = [self accountStatusFromCKAccountInfo:oldAccountInfo]; - CKKSAccountStatus currentStatus = [self accountStatusFromCKAccountInfo:currentAccountInfo]; - - if(oldStatus == currentStatus) { - ckksnotice("ckkszone", self, "Computed status of new CK account info is same as old status: %@", [CKKSAccountStateTracker stringFromAccountStatus:currentStatus]); - return; - } - - switch(currentStatus) { - case CKKSAccountStatusAvailable: { - ckksnotice("ckkszone", self, "Logged into iCloud."); - [self handleCKLogin]; - - if(self.accountLoggedInDependency) { - [self.operationQueue addOperation:self.accountLoggedInDependency]; - self.accountLoggedInDependency = nil; - }; - } - break; - - case CKKSAccountStatusNoAccount: { - ckksnotice("ckkszone", self, "Logging out of iCloud. Shutting down."); - - if(!self.accountLoggedInDependency) { - self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."]; - } - - [self handleCKLogout]; - } - break; - - case CKKSAccountStatusUnknown: { - // We really don't expect to receive this as a notification, but, okay! - ckksnotice("ckkszone", self, "Account status has become undetermined. Pausing for %@", self.zoneID.zoneName); - - if(!self.accountLoggedInDependency) { - self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."]; - } - - [self handleCKLogout]; - } - break; - } -} - -- (CKKSResultOperation*)handleCKLogin:(bool)zoneCreated zoneSubscribed:(bool)zoneSubscribed { - if(!SecCKKSIsEnabled()) { - ckksinfo("ckkszone", self, "Skipping CloudKit registration due to disabled CKKS"); - return nil; - } - - // If we've already started set up and that hasn't finished, complain - if([self.zoneSetupOperation isPending] || [self.zoneSetupOperation isExecuting]) { - ckksnotice("ckkszone", self, "Asked to handleCKLogin, but zoneSetupOperation appears to not be complete? %@ Continuing anyway", self.zoneSetupOperation); - } - - self.zoneSetupOperation = [[CKKSGroupOperation alloc] init]; - self.zoneSetupOperation.name = [NSString stringWithFormat:@"zone-setup-operation-%@", self.zoneName]; - - self.zoneCreated = zoneCreated; - self.zoneSubscribed = zoneSubscribed; - - ckksnotice("ckkszone", self, "Setting up zone %@", self.zoneName); - - WEAKIFY(self); - - // First, check the account status. If it's sufficient, add the necessary CloudKit operations to this operation - __weak CKKSGroupOperation* weakZoneSetupOperation = self.zoneSetupOperation; - [self.zoneSetupOperation runBeforeGroupFinished:[CKKSResultOperation named:[NSString stringWithFormat:@"zone-setup-%@", self.zoneName] withBlock:^{ - STRONGIFY(self); - __strong __typeof(self.zoneSetupOperation) zoneSetupOperation = weakZoneSetupOperation; - if(!self || !zoneSetupOperation) { - ckkserror("ckkszone", self, "received callback for released object"); - return; - } - - if(self.accountStatus != CKKSAccountStatusAvailable) { - ckkserror("ckkszone", self, "Zone doesn't believe it's logged in; quitting setup"); - return; - } - - NSBlockOperation* setupCompleteOperation = [NSBlockOperation blockOperationWithBlock:^{ - STRONGIFY(self); - if(!self) { - secerror("ckkszone: received callback for released object"); - return; - } - - ckksnotice("ckkszone", self, "%@: Setup complete", self.zoneName); - }]; - setupCompleteOperation.name = @"zone-setup-complete-operation"; - - // We have an account, so fetch the push environment and bring up APS - [self.container serverPreferredPushEnvironmentWithCompletionHandler: ^(NSString *apsPushEnvString, NSError *error) { - STRONGIFY(self); - if(!self) { - secerror("ckkszone: received callback for released object"); - return; - } - - if(error || (apsPushEnvString == nil)) { - ckkserror("ckkszone", self, "Received error fetching preferred push environment (%@). Keychain syncing is highly degraded: %@", apsPushEnvString, error); - } else { - OctagonAPSReceiver* aps = [OctagonAPSReceiver receiverForEnvironment:apsPushEnvString - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:self.cloudKitClassDependencies.apsConnectionClass]; - [aps registerReceiver:self forZoneID:self.zoneID]; - } - }]; - - if(!zoneCreated || !zoneSubscribed) { - ckksnotice("ckkszone", self, "Asking to create and subscribe to CloudKit zone '%@'", self.zoneName); - CKKSZoneModifyOperations* zoneOps = [self.zoneModifier createZone:self.zone]; - - CKKSResultOperation* handleModificationsOperation = [CKKSResultOperation named:@"handle-modification" withBlock:^{ - STRONGIFY(self); - if([zoneOps.savedRecordZones containsObject:self.zone]) { - ckksnotice("ckkszone", self, "Successfully created '%@'", self.zoneName); - self.zoneCreated = true; - } else { - ckksnotice("ckkszone", self, "Failed to create '%@'", self.zoneName); - self.zoneCreatedError = zoneOps.zoneModificationOperation.error; - } - - bool createdSubscription = false; - for(CKSubscription* subscription in zoneOps.savedSubscriptions) { - if([subscription.zoneID isEqual:self.zoneID]) { - createdSubscription = true; - break; - } - } - - if(createdSubscription) { - ckksnotice("ckkszone", self, "Successfully subscribed '%@'", self.zoneName); - self.zoneSubscribed = true; - } else { - ckksnotice("ckkszone", self, "Failed to subscribe to '%@'", self.zoneName); - self.zoneSubscribedError = zoneOps.zoneSubscriptionOperation.error; - } - }]; - [setupCompleteOperation addDependency:zoneOps.zoneModificationOperation]; - [handleModificationsOperation addDependency:zoneOps.zoneModificationOperation]; - [handleModificationsOperation addDependency:zoneOps.zoneSubscriptionOperation]; - [zoneSetupOperation runBeforeGroupFinished:handleModificationsOperation]; - } else { - ckksnotice("ckkszone", self, "no need to create or subscribe to the zone '%@'", self.zoneName); - } - - [self.zoneSetupOperation runBeforeGroupFinished:setupCompleteOperation]; - }]]; - - [self scheduleAccountStatusOperation:self.zoneSetupOperation]; - return self.zoneSetupOperation; -} - - -- (CKKSResultOperation*)deleteCloudKitZoneOperation:(CKOperationGroup* _Nullable)ckoperationGroup { - if(!SecCKKSIsEnabled()) { - ckksnotice("ckkszone", self, "Skipping CloudKit reset due to disabled CKKS"); - return nil; - } - - WEAKIFY(self); - - // We want to delete this zone and this subscription from CloudKit. - - // Step 1: cancel setup operations (if they exist) - [self.accountLoggedInDependency cancel]; - [self.zoneSetupOperation cancel]; - [self.zoneCreationOperation cancel]; - [self.zoneSubscriptionOperation cancel]; - - // Step 2: Try to delete the zone - - CKKSZoneModifyOperations* zoneOps = [self.zoneModifier deleteZone:self.zoneID]; - - CKKSResultOperation* afterModification = [CKKSResultOperation named:@"after-modification" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { - STRONGIFY(self); - - bool fatalError = false; - - NSError* operationError = zoneOps.zoneModificationOperation.error; - bool removed = [zoneOps.deletedRecordZoneIDs containsObject:self.zoneID]; - - if(!removed && operationError) { - // Okay, but if this error is either 'ZoneNotFound' or 'UserDeletedZone', that's fine by us: the zone is deleted. - NSDictionary* partialErrors = operationError.userInfo[CKPartialErrorsByItemIDKey]; - if([operationError.domain isEqualToString:CKErrorDomain] && operationError.code == CKErrorPartialFailure && partialErrors) { - for(CKRecordZoneID* errorZoneID in partialErrors.allKeys) { - NSError* errorZone = partialErrors[errorZoneID]; - - if(errorZone && [errorZone.domain isEqualToString:CKErrorDomain] && - (errorZone.code == CKErrorZoneNotFound || errorZone.code == CKErrorUserDeletedZone)) { - ckksnotice("ckkszone", self, "Attempted to delete zone %@, but it's already missing. This is okay: %@", errorZoneID, errorZone); - } else { - fatalError = true; - } - } - - } else { - fatalError = true; - } - - ckksnotice("ckkszone", self, "deletion of record zone %@ completed with error: %@", self.zoneID, operationError); - - if(fatalError) { - op.error = operationError; - } - } else { - ckksnotice("ckkszone", self, "deletion of record zone %@ completed successfully", self.zoneID); - } - }]; - - [afterModification addDependency:zoneOps.zoneModificationOperation]; - return afterModification; -} - -- (void)notifyZoneChange: (CKRecordZoneNotification*) notification { - ckksnotice("ckkszone", self, "received a notification for CK zone change, ignoring"); -} - -- (void)handleCKLogin { - ckksinfo("ckkszone", self, "received a notification of CK login"); - self.accountStatus = CKKSAccountStatusAvailable; -} - -- (void)handleCKLogout { - ckksinfo("ckkszone", self, "received a notification of CK logout"); - self.accountStatus = CKKSAccountStatusNoAccount; - [self resetSetup]; -} - -- (bool)scheduleOperation: (NSOperation*) op { - if(self.halted) { - ckkserror("ckkszone", self, "attempted to schedule an operation on a halted zone, ignoring"); - return false; - } - - [op addNullableDependency:self.accountLoggedInDependency]; - - [self.operationQueue addOperation: op]; - return true; -} - -- (void)cancelAllOperations { - [self.operationQueue cancelAllOperations]; -} - -- (void)waitUntilAllOperationsAreFinished { - [self.operationQueue waitUntilAllOperationsAreFinished]; -} - -- (void)waitForOperationsOfClass:(Class) operationClass { - NSArray* operations = [self.operationQueue.operations copy]; - for(NSOperation* op in operations) { - if([op isKindOfClass:operationClass]) { - [op waitUntilFinished]; - } - } -} - -- (bool)scheduleAccountStatusOperation: (NSOperation*) op { - if(self.halted) { - ckkserror("ckkszone", self, "attempted to schedule an account operation on a halted zone, ignoring"); - return false; - } - - // Always succeed. But, account status operations should always proceed in-order. - [op linearDependencies:self.accountOperations]; - [self.operationQueue addOperation: op]; - return true; -} - -// to be used rarely, if at all -- (bool)scheduleOperationWithoutDependencies:(NSOperation*)op { - if(self.halted) { - ckkserror("ckkszone", self, "attempted to schedule an non-dependent operation on a halted zone, ignoring"); - return false; - } - - [self.operationQueue addOperation: op]; - return true; -} - -- (void) dispatchSync: (bool (^)(void)) block { - // important enough to block this thread. - __block bool ok = false; - dispatch_sync(self.queue, ^{ - if(self.halted) { - ckkserror("ckkszone", self, "CKKSZone not dispatchSyncing a block (due to being halted)"); - return; - } - - ok = block(); - if(!ok) { - ckkserror("ckkszone", self, "CKKSZone block returned false"); - } - }); -} - -- (void)halt { - // Synchronously set the 'halted' bit - dispatch_sync(self.queue, ^{ - self.halted = true; - }); - - // Bring all operations down, too - [self cancelAllOperations]; -} - -@end - -#endif /* OCTAGON */ - diff --git a/keychain/ckks/CKKSZoneChangeFetcher.h b/keychain/ckks/CKKSZoneChangeFetcher.h index 08510fb2..e51e6925 100644 --- a/keychain/ckks/CKKSZoneChangeFetcher.h +++ b/keychain/ckks/CKKSZoneChangeFetcher.h @@ -26,6 +26,7 @@ #import #import "keychain/ckks/CKKSResultOperation.h" #import "keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.h" +#import "keychain/ckks/OctagonAPSReceiver.h" NS_ASSUME_NONNULL_BEGIN @@ -39,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSReachabilityTracker; @class CKKSNearFutureScheduler; -@interface CKKSZoneChangeFetcher : NSObject +@interface CKKSZoneChangeFetcher : NSObject @property (readonly) Class fetchRecordZoneChangesOperationClass; @property (readonly) CKContainer* container; @property CKKSReachabilityTracker* reachabilityTracker; @@ -56,13 +57,17 @@ NS_ASSUME_NONNULL_BEGIN - (CKKSResultOperation*)requestSuccessfulFetch:(CKKSFetchBecause*)why; - (CKKSResultOperation*)requestSuccessfulFetchForManyReasons:(NSSet*)why; -// let server know we seen this push and if zones are ready actually perform a fetch -- (CKKSResultOperation* _Nullable)requestFetchDueToAPNS:(CKRecordZoneNotification*)notification; +// Returns the next fetch, if one is scheduled, or the last/currently executing fetch if not. +- (CKKSResultOperation* _Nullable)inflightFetch; + +// CKKSZoneUpdateReceiverProtocol +- (void)notifyZoneChange:(CKRecordZoneNotification* _Nullable)notification; // We don't particularly care what this does, as long as it finishes - (void)holdFetchesUntil:(CKKSResultOperation* _Nullable)holdOperation; - (void)cancel; +- (void)halt; // I don't recommend using these unless you're a test. @property CKKSNearFutureScheduler* fetchScheduler; diff --git a/keychain/ckks/CKKSZoneChangeFetcher.m b/keychain/ckks/CKKSZoneChangeFetcher.m index ead140b9..179b27fc 100644 --- a/keychain/ckks/CKKSZoneChangeFetcher.m +++ b/keychain/ckks/CKKSZoneChangeFetcher.m @@ -91,6 +91,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- @property NSString* name; @property NSOperationQueue* operationQueue; @property dispatch_queue_t queue; +@property BOOL halted; @property NSError* lastCKFetchError; @@ -104,6 +105,8 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- @property bool newRequests; // true if there's someone pending on successfulFetchDependency @property CKKSZoneChangeFetchDependencyOperation* successfulFetchDependency; +@property (nullable) CKKSZoneChangeFetchDependencyOperation* inflightFetchDependency; + @property CKKSResultOperation* holdOperation; @end @@ -127,11 +130,12 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- _queue = dispatch_queue_create([_name UTF8String], DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); _operationQueue = [[NSOperationQueue alloc] init]; _successfulFetchDependency = [self createSuccesfulFetchDependency]; + _inflightFetchDependency = nil; _newRequests = false; - // If we're testing, for the initial delay, use 0.25 second. Otherwise, 2s. - dispatch_time_t initialDelay = (SecCKKSReduceRateLimiting() ? 250 * NSEC_PER_MSEC : 2 * NSEC_PER_SEC); + // If we're testing, for the initial delay, use 0.5 second. Otherwise, 2s. + dispatch_time_t initialDelay = (SecCKKSReduceRateLimiting() ? 500 * NSEC_PER_MSEC : 2 * NSEC_PER_SEC); // If we're testing, for the maximum delay, use 6 second. Otherwise, 2m. dispatch_time_t maximumDelay = (SecCKKSReduceRateLimiting() ? 6 * NSEC_PER_SEC : 120 * NSEC_PER_SEC); @@ -185,6 +189,12 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- return [self requestSuccessfulFetchForManyReasons:[NSSet setWithObject:why]]; } +- (void)notifyZoneChange:(CKRecordZoneNotification* _Nullable)notification +{ + ckksnotice_global("ckkspush", "received a zone change notification for %@ %@", self, notification); + [self requestFetchDueToAPNS:notification]; +} + - (CKKSResultOperation*)requestFetchDueToAPNS:(CKRecordZoneNotification*)notification { __block BOOL notReady = YES; @@ -197,6 +207,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- for(id client in clients) { if([client zoneIsReadyForFetching]) { notReady = NO; + break; } } @@ -206,7 +217,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- [self.apnsPushes addObject:notification]; if(notification.ckksPushTracingEnabled) { // Report that we saw this notification before doing anything else - secnotice("ckksfetch", "Submitting initial CKEventMetric due to notification %@", notification); + ckksnotice_global("ckksfetch", "Submitting initial CKEventMetric due to notification %@", notification); CKEventMetric *metric = [[CKEventMetric alloc] initWithEventName:@"APNSPushMetrics"]; metric.isPushTriggerFired = true; @@ -230,7 +241,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- }); if (notReady) { - secnotice("ckksfetch", "Skipping fetching size no zone is ready"); + ckksnotice_global("ckksfetch", "Skipping fetching size no zone is ready"); return NULL; } @@ -251,8 +262,31 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- return dependency; } +- (CKKSResultOperation* _Nullable)inflightFetch +{ + __block CKKSResultOperation* dependency = nil; + dispatch_sync(self.queue, ^{ + + // If we'll have a new fetch in the future, return its status. + if(self.newRequests || self.inflightFetchDependency == nil) { + dependency = self.successfulFetchDependency; + } else { + // Otherwise, return the last triggered fetch + dependency = self.inflightFetchDependency; + } + }); + + return dependency; +} + -(void)maybeCreateNewFetchOnQueue { dispatch_assert_queue(self.queue); + + if(self.halted) { + ckksnotice_global("ckksfetcher", "Halted; not starting a new fetch"); + return; + } + if(self.newRequests && (self.currentFetch == nil || [self.currentFetch isFinished]) && (self.currentProcessResult == nil || [self.currentProcessResult isFinished])) { @@ -272,12 +306,14 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- WEAKIFY(self); CKKSZoneChangeFetchDependencyOperation* dependency = self.successfulFetchDependency; + self.inflightFetchDependency = dependency; + NSMutableSet* lastFetchReasons = self.currentFetchReasons; self.currentFetchReasons = [[NSMutableSet alloc] init]; NSString *reasonsString = [[lastFetchReasons sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES]]] componentsJoinedByString:@","]; - secnotice("ckksfetcher", "Starting a new fetch, reasons: %@", reasonsString); + ckksnotice_global("ckksfetcher", "Starting a new fetch, reasons: %@", reasonsString); NSMutableSet* lastAPNSPushes = self.apnsPushes; self.apnsPushes = [[NSMutableSet alloc] init]; @@ -287,7 +323,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- NSArray> *clients = [self clients]; if(clients.count == 0u) { - secnotice("ckksfetcher", "No clients"); + ckksnotice_global("ckksfetcher", "No clients"); // Nothing to do, really. } @@ -300,7 +336,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- ckoperationGroup:operationGroup]; if ([lastFetchReasons containsObject:CKKSFetchBecauseNetwork]) { - secnotice("ckksfetcher", "blocking fetch on network reachability"); + ckksnotice_global("ckksfetcher", "blocking fetch on network reachability"); [fetchAllChanges addNullableDependency: self.reachabilityTracker.reachabilityDependency]; // wait on network, if its unavailable } [fetchAllChanges addNullableDependency: self.holdOperation]; @@ -308,13 +344,13 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- self.currentProcessResult = [CKKSResultOperation operationWithBlock: ^{ STRONGIFY(self); if(!self) { - secerror("ckksfetcher: Received a null self pointer; strange."); + ckkserror_global("ckksfetcher", "Received a null self pointer; strange."); return; } bool attemptAnotherFetch = false; if(fetchAllChanges.error != nil) { - secerror("ckksfetcher: Interrogating clients about fetch error: %@", fetchAllChanges.error); + ckkserror_global("ckksfetcher", "Interrogating clients about fetch error: %@", fetchAllChanges.error); // Check in with clients: should we keep fetching for them? @synchronized(self.clientMap) { @@ -345,17 +381,17 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- [self.operationQueue addOperation: dependency]; if(!attemptAnotherFetch) { - secerror("ckksfetcher: All clients thought %@ is a fatal error. Not restarting fetch.", fetchAllChanges.error); + ckkserror_global("ckksfetcher", "All clients thought %@ is a fatal error. Not restarting fetch.", fetchAllChanges.error); return; } // And in a bit, try the fetch again. NSTimeInterval delay = CKRetryAfterSecondsForError(fetchAllChanges.error); if (delay) { - secnotice("ckksfetcher", "Fetch failed with rate-limiting error, restarting in %.1f seconds: %@", delay, fetchAllChanges.error); + ckksnotice_global("ckksfetcher", "Fetch failed with rate-limiting error, restarting in %.1f seconds: %@", delay, fetchAllChanges.error); [self.fetchScheduler waitUntil:NSEC_PER_SEC * delay]; } else { - secnotice("ckksfetcher", "Fetch failed with error, restarting soon: %@", fetchAllChanges.error); + ckksnotice_global("ckksfetcher", "Fetch failed with error, restarting soon: %@", fetchAllChanges.error); } // Add the failed fetch reasons to the new fetch reasons @@ -406,6 +442,20 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- [self.fetchScheduler cancel]; } +- (void)halt +{ + [self.fetchScheduler cancel]; + dispatch_sync(self.queue, ^{ + self.halted = YES; + }); + + [self.currentFetch cancel]; + if(self.holdOperation) { + [self.currentFetch removeDependency:self.holdOperation]; + } + [self.currentFetch waitUntilFinished]; +} + @end #endif diff --git a/keychain/ckks/CKKSZoneModifier.m b/keychain/ckks/CKKSZoneModifier.m index 58905c26..85dd700f 100644 --- a/keychain/ckks/CKKSZoneModifier.m +++ b/keychain/ckks/CKKSZoneModifier.m @@ -8,7 +8,6 @@ #import "keychain/ckks/CKKSReachabilityTracker.h" #import "keychain/ckks/CKKSZoneModifier.h" -#import "utilities/debugging.h" #import "keychain/ot/ObjCImprovements.h" @implementation CKKSZoneModifyOperations @@ -99,11 +98,11 @@ if(!self.pendingOperations) { CKKSResultOperation* zoneModificationOperationDependency = [CKKSResultOperation named:@"zone-modification" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { - secnotice("ckkszonemodifier", "finished creating zones"); + ckksnotice_global("ckkszonemodifier", "finished creating zones"); }]; CKKSResultOperation* zoneSubscriptionOperationDependency = [CKKSResultOperation named:@"zone-subscription" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { - secnotice("ckkszonemodifier", "finished subscribing to zones"); + ckksnotice_global("ckkszonemodifier", "finished subscribing to zones"); }]; self.pendingOperations = [[CKKSZoneModifyOperations alloc] initWithZoneModificationOperation:zoneModificationOperationDependency @@ -158,19 +157,19 @@ { dispatch_sync(self.queue, ^{ if(self.halted) { - secnotice("ckkszonemodifier", "Halted; not launching operations"); + ckksnotice_global("ckkszonemodifier", "Halted; not launching operations"); return; } CKKSZoneModifyOperations* ops = self.pendingOperations; if(!ops) { - secinfo("ckkszonemodifier", "No pending zone modification operations; quitting"); + ckksinfo_global("ckkszonemodifier", "No pending zone modification operations; quitting"); return; } if(self.inflightOperations && (![self.inflightOperations.zoneModificationOperation isFinished] || ![self.inflightOperations.zoneSubscriptionOperation isFinished])) { - secnotice("ckkszonemodifier", "Have in-flight zone modification operations, will retry later"); + ckksnotice_global("ckkszonemodifier", "Have in-flight zone modification operations, will retry later"); WEAKIFY(self); CKKSResultOperation* retrigger = [CKKSResultOperation named:@"retry" withBlock:^{ @@ -198,7 +197,7 @@ - (CKDatabaseOperation*)createModifyZonesOperation:(CKKSZoneModifyOperations*)ops { - secnotice("ckkszonemodifier", "Attempting to create zones %@, delete zones %@", ops.zonesToCreate, ops.zoneIDsToDelete); + ckksnotice_global("ckkszonemodifier", "Attempting to create zones %@, delete zones %@", ops.zonesToCreate, ops.zoneIDsToDelete); CKDatabaseOperation* zoneModifyOperation = [[self.cloudKitClassDependencies.modifyRecordZonesOperationClass alloc] initWithRecordZonesToSave:ops.zonesToCreate recordZoneIDsToDelete:ops.zoneIDsToDelete]; [zoneModifyOperation linearDependencies:self.ckOperations]; @@ -219,15 +218,15 @@ STRONGIFY(self); if(operationError) { - secerror("ckkszonemodifier: Zone modification failed: %@", operationError); + ckkserror_global("ckkszonemodifier", "Zone modification failed: %@", operationError); [self inspectErrorForRetryAfter:operationError]; if ([self.reachabilityTracker isNetworkError:operationError]){ self.networkFailure = true; } } - secnotice("ckkszonemodifier", "created zones: %@", savedRecordZones); - secnotice("ckkszonemodifier", "deleted zones: %@", deletedRecordZoneIDs); + ckksnotice_global("ckkszonemodifier", "created zones: %@", savedRecordZones); + ckksnotice_global("ckkszonemodifier", "deleted zones: %@", deletedRecordZoneIDs); ops.savedRecordZones = savedRecordZones; ops.deletedRecordZoneIDs = deletedRecordZoneIDs; @@ -237,7 +236,7 @@ }; if(self.networkFailure) { - secnotice("ckkszonemodifier", "Waiting for reachabilty before issuing zone creation"); + ckksnotice_global("ckkszonemodifier", "Waiting for reachabilty before issuing zone creation"); [zoneModifyOperation addNullableDependency:self.reachabilityTracker.reachabilityDependency]; } @@ -246,7 +245,7 @@ - (CKDatabaseOperation* _Nullable)createModifySubscriptionsOperation:(CKKSZoneModifyOperations*)ops { - secnotice("ckkszonemodifier", "Attempting to subscribe to zones %@", ops.subscriptionsToSubscribe); + ckksnotice_global("ckkszonemodifier", "Attempting to subscribe to zones %@", ops.subscriptionsToSubscribe); if(ops.subscriptionsToSubscribe.count == 0) { [self.operationQueue addOperation: ops.zoneSubscriptionOperation]; @@ -269,14 +268,14 @@ STRONGIFY(self); if(operationError) { - secerror("ckkszonemodifier: Couldn't create cloudkit zone subscription; keychain syncing is severely degraded: %@", operationError); + ckkserror_global("ckkszonemodifier", "Couldn't create cloudkit zone subscription; keychain syncing is severely degraded: %@", operationError); [self inspectErrorForRetryAfter:operationError]; if ([self.reachabilityTracker isNetworkError:operationError]){ self.networkFailure = true; } } - secnotice("ckkszonemodifier", "Successfully subscribed to %@", savedSubscriptions); + ckksnotice_global("ckkszonemodifier", "Successfully subscribed to %@", savedSubscriptions); ops.savedSubscriptions = savedSubscriptions; ops.deletedSubscriptionIDs = deletedSubscriptionIDs; @@ -288,7 +287,7 @@ [zoneSubscriptionOperation addNullableDependency:ops.zoneModificationOperation]; if(self.networkFailure) { - secnotice("ckkszonemodifier", "Waiting for reachabilty before issuing zone subscription"); + ckksnotice_global("ckkszonemodifier", "Waiting for reachabilty before issuing zone subscription"); [zoneSubscriptionOperation addNullableDependency:self.reachabilityTracker.reachabilityDependency]; } @@ -300,7 +299,7 @@ NSTimeInterval delay = CKRetryAfterSecondsForError(ckerror); if(delay) { uint64_t ns_delay = NSEC_PER_SEC * ((uint64_t) delay); - secnotice("ckkszonemodifier", "CK operation failed with rate-limit, scheduling delay for %.1f seconds: %@", delay, ckerror); + ckksnotice_global("ckkszonemodifier", "CK operation failed with rate-limit, scheduling delay for %.1f seconds: %@", delay, ckerror); [self.cloudkitRetryAfter waitUntil:ns_delay]; } } diff --git a/keychain/ckks/CKKSZoneStateEntry.h b/keychain/ckks/CKKSZoneStateEntry.h index 27213bca..f2c7a5b2 100644 --- a/keychain/ckks/CKKSZoneStateEntry.h +++ b/keychain/ckks/CKKSZoneStateEntry.h @@ -57,9 +57,11 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable) NSData* encodedChangeToken; @property BOOL moreRecordsInCloudKit; @property (nullable) NSDate* lastFetchTime; +@property (nullable) NSDate* lastLocalKeychainScanTime; @property CKKSFixup lastFixup; + @property (nullable) CKKSRateLimiter* rateLimiter; @property (nullable) NSData* encodedRateLimiter; @@ -74,10 +76,11 @@ NS_ASSUME_NONNULL_BEGIN changeToken:(NSData* _Nullable)changetoken moreRecordsInCloudKit:(BOOL)moreRecords lastFetch:(NSDate* _Nullable)lastFetch + lastScan:(NSDate* _Nullable)localKeychainScanned lastFixup:(CKKSFixup)lastFixup encodedRateLimiter:(NSData* _Nullable)encodedRateLimiter; -- (CKServerChangeToken*)getChangeToken; +- (CKServerChangeToken* _Nullable)getChangeToken; - (void)setChangeToken:(CKServerChangeToken* _Nullable)token; - (BOOL)isEqual:(id)object; diff --git a/keychain/ckks/CKKSZoneStateEntry.m b/keychain/ckks/CKKSZoneStateEntry.m index f835d9ab..0f15f257 100644 --- a/keychain/ckks/CKKSZoneStateEntry.m +++ b/keychain/ckks/CKKSZoneStateEntry.m @@ -48,6 +48,7 @@ changeToken:(NSData*)changetoken moreRecordsInCloudKit:(BOOL)moreRecords lastFetch:(NSDate*)lastFetch + lastScan:(NSDate* _Nullable)lastScan lastFixup:(CKKSFixup)lastFixup encodedRateLimiter:(NSData*)encodedRateLimiter { @@ -58,6 +59,7 @@ _encodedChangeToken = changetoken; _moreRecordsInCloudKit = moreRecords; _lastFetchTime = lastFetch; + _lastLocalKeychainScanTime = lastScan; _lastFixup = lastFixup; self.encodedRateLimiter = encodedRateLimiter; @@ -80,6 +82,7 @@ ((self.lastFetchTime == nil && obj.lastFetchTime == nil) || [self.lastFetchTime isEqualToDate: obj.lastFetchTime]) && ((self.rateLimiter == nil && obj.rateLimiter == nil) || [self.rateLimiter isEqual: obj.rateLimiter]) && self.lastFixup == obj.lastFixup && + ((self.lastLocalKeychainScanTime == nil && obj.lastLocalKeychainScanTime == nil) || [self.lastLocalKeychainScanTime isEqualToDate: obj.lastLocalKeychainScanTime]) && true) ? YES : NO; } @@ -88,7 +91,7 @@ CKKSZoneStateEntry* ret = [CKKSZoneStateEntry tryFromDatabase:ckzone error:&error]; if(error) { - secerror("CKKS: error fetching CKState(%@): %@", ckzone, error); + ckkserror_global("ckks", "error fetching CKState(%@): %@", ckzone, error); } if(!ret) { @@ -98,13 +101,14 @@ changeToken:nil moreRecordsInCloudKit:NO lastFetch:nil + lastScan:nil lastFixup:CKKSCurrentFixupNumber encodedRateLimiter:nil]; } return ret; } -- (CKServerChangeToken*) getChangeToken { +- (CKServerChangeToken* _Nullable) getChangeToken { if(self.encodedChangeToken) { NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:self.encodedChangeToken error:nil]; return [unarchiver decodeObjectOfClass:[CKServerChangeToken class] forKey:NSKeyedArchiveRootObjectKey]; @@ -151,7 +155,8 @@ } + (NSArray*) sqlColumns { - return @[@"ckzone", @"ckzonecreated", @"ckzonesubscribed", @"changetoken", @"lastfetch", @"ratelimiter", @"lastFixup", @"morecoming"]; + // Note that 'extra' is not currently used, but the schema supports adding a protobuf or other serialized data + return @[@"ckzone", @"ckzonecreated", @"ckzonesubscribed", @"changetoken", @"lastfetch", @"ratelimiter", @"lastFixup", @"morecoming", @"lastscan", @"extra"]; } - (NSDictionary*) whereClauseToFindSelf { @@ -161,15 +166,17 @@ - (NSDictionary*) sqlValues { NSISO8601DateFormatter* dateFormat = [[NSISO8601DateFormatter alloc] init]; - return @{@"ckzone": self.ckzone, - @"ckzonecreated": [NSNumber numberWithBool:self.ckzonecreated], - @"ckzonesubscribed": [NSNumber numberWithBool:self.ckzonesubscribed], - @"changetoken": CKKSNilToNSNull([self.encodedChangeToken base64EncodedStringWithOptions:0]), - @"lastfetch": CKKSNilToNSNull(self.lastFetchTime ? [dateFormat stringFromDate: self.lastFetchTime] : nil), - @"ratelimiter": CKKSNilToNSNull([self.encodedRateLimiter base64EncodedStringWithOptions:0]), - @"lastFixup": [NSNumber numberWithLong:self.lastFixup], - @"morecoming": [NSNumber numberWithBool:self.moreRecordsInCloudKit], - }; + return @{ + @"ckzone": self.ckzone, + @"ckzonecreated": [NSNumber numberWithBool:self.ckzonecreated], + @"ckzonesubscribed": [NSNumber numberWithBool:self.ckzonesubscribed], + @"changetoken": CKKSNilToNSNull([self.encodedChangeToken base64EncodedStringWithOptions:0]), + @"lastfetch": CKKSNilToNSNull(self.lastFetchTime ? [dateFormat stringFromDate: self.lastFetchTime] : nil), + @"ratelimiter": CKKSNilToNSNull([self.encodedRateLimiter base64EncodedStringWithOptions:0]), + @"lastFixup": [NSNumber numberWithLong:self.lastFixup], + @"morecoming": [NSNumber numberWithBool:self.moreRecordsInCloudKit], + @"lastscan": CKKSNilToNSNull(self.lastLocalKeychainScanTime ? [dateFormat stringFromDate:self.lastLocalKeychainScanTime] : nil), + }; } + (instancetype)fromDatabaseRow:(NSDictionary*)row { @@ -179,6 +186,7 @@ changeToken:row[@"changetoken"].asBase64DecodedData moreRecordsInCloudKit:row[@"morecoming"].asBOOL lastFetch:row[@"lastfetch"].asISO8601Date + lastScan:row[@"lastscan"].asISO8601Date lastFixup:(CKKSFixup)row[@"lastFixup"].asNSInteger encodedRateLimiter:row[@"ratelimiter"].asBase64DecodedData ]; diff --git a/keychain/ckks/CloudKitCategories.h b/keychain/ckks/CloudKitCategories.h index c7995009..33881b20 100644 --- a/keychain/ckks/CloudKitCategories.h +++ b/keychain/ckks/CloudKitCategories.h @@ -44,6 +44,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSTimeInterval)cuttlefishRetryAfter; - (BOOL)isCKKSServerPluginError:(NSInteger)code; +- (BOOL)isCKServerInternalError; @end // Ensure we don't print addresses @interface CKAccountInfo (CKKS) diff --git a/keychain/ckks/CloudKitCategories.m b/keychain/ckks/CloudKitCategories.m index 50bb8904..f65de9c0 100644 --- a/keychain/ckks/CloudKitCategories.m +++ b/keychain/ckks/CloudKitCategories.m @@ -24,6 +24,7 @@ #if OCTAGON #import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/CKKS.h" @implementation CKOperationGroup (CKKS) +(instancetype) CKKSGroupWithName:(NSString*)name { @@ -83,7 +84,7 @@ if([cuttlefishError.domain isEqualToString:CuttlefishErrorDomain]) { NSNumber* val = cuttlefishError.userInfo[CuttlefishErrorRetryAfterKey]; - if (val) { + if (val != nil) { return (NSTimeInterval)val.doubleValue; } } @@ -92,7 +93,6 @@ return 0; } - - (BOOL)isCKKSServerPluginError:(NSInteger)code { NSError* underlyingError = self.userInfo[NSUnderlyingErrorKey]; @@ -108,6 +108,16 @@ thirdLevelError.code == code); } +- (BOOL)isCKServerInternalError { + NSError* underlyingError = self.userInfo[NSUnderlyingErrorKey]; + + return [self.domain isEqualToString:CKErrorDomain] && + self.code == CKErrorServerRejectedRequest && + underlyingError && + [underlyingError.domain isEqualToString:CKInternalErrorDomain] && + underlyingError.code == CKErrorInternalServerInternalError; +} + @end @implementation CKAccountInfo (CKKS) diff --git a/keychain/ckks/CloudKitDependencies.h b/keychain/ckks/CloudKitDependencies.h index ae9ad1c3..15c4b901 100644 --- a/keychain/ckks/CloudKitDependencies.h +++ b/keychain/ckks/CloudKitDependencies.h @@ -103,6 +103,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) NSString *operationID; @property (nonatomic, readonly, strong, nullable) CKOperationConfiguration *resolvedConfiguration; + +@property (nonatomic, strong) NSString *deviceIdentifier; @end @interface CKFetchRecordZoneChangesOperation () @@ -151,13 +153,15 @@ NS_ASSUME_NONNULL_BEGIN /* APSConnection */ @protocol OctagonAPSConnection +@property NSArray* enabledTopics; +@property NSArray* opportunisticTopics; +@property NSArray* darkWakeTopics; + + (instancetype)alloc; - (id)initWithEnvironmentName:(NSString*)environmentName namedDelegatePort:(NSString*)namedDelegatePort queue:(dispatch_queue_t)queue; -- (void)setEnabledTopics:(NSArray *)enabledTopics; -- (void)setDarkWakeTopics:(NSArray *)darkWakeTopics; @property (nonatomic, readwrite, assign) id delegate; @end diff --git a/keychain/ckks/NSOperationCategories.m b/keychain/ckks/NSOperationCategories.m index b9ea9410..5867d700 100644 --- a/keychain/ckks/NSOperationCategories.m +++ b/keychain/ckks/NSOperationCategories.m @@ -22,9 +22,9 @@ */ #import +#import "keychain/ckks/CKKS.h" #import "keychain/ckks/NSOperationCategories.h" #import "keychain/ot/ObjCImprovements.h" -#import "utilities/debugging.h" @implementation NSOperation (CKKSUsefulPrintingOperation) - (NSString*)selfname { @@ -43,7 +43,7 @@ continue; } #if DEBUG - secnotice("ckks-operation", "adding dependency of %@ on %@", self, existingop); + ckksnotice_global("ckks-operation", "adding dependency of %@ on %@", self.name, existingop); #endif [self addDependency: existingop]; } diff --git a/keychain/ckks/OctagonAPSReceiver.h b/keychain/ckks/OctagonAPSReceiver.h index 98b8920c..a5c22a02 100644 --- a/keychain/ckks/OctagonAPSReceiver.h +++ b/keychain/ckks/OctagonAPSReceiver.h @@ -39,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, nullable) NSDate* ckksPushReceivedDate; @end -@protocol CKKSZoneUpdateReceiver +@protocol CKKSZoneUpdateReceiverProtocol - (void)notifyZoneChange:(CKRecordZoneNotification* _Nullable)notification; @end @@ -55,28 +55,32 @@ NS_ASSUME_NONNULL_BEGIN @property (readonly) BOOL haveStalePushes; -+ (instancetype)receiverForEnvironment:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort - apsConnectionClass:(Class)apsConnectionClass; ++ (instancetype)receiverForNamedDelegatePort:(NSString*)namedDelegatePort + apsConnectionClass:(Class)apsConnectionClass; ++ (void)resetGlobalDelegatePortMap; -- (CKKSCondition*)registerReceiver:(id)receiver forZoneID:(CKRecordZoneID*)zoneID; +- (void)registerForEnvironment:(NSString*)environmentName; + +- (CKKSCondition*)registerCKKSReceiver:(id)receiver; + +// APS reserves the right to coalesce pushes by topic. So, any cuttlefish container push might hide pushes for other cuttlefish containers. +// This is okay for now, as we only have one active cuttlefish container per device, but if we start to have multiple accounts, this handling might need to change. - (CKKSCondition*)registerCuttlefishReceiver:(id)receiver forContainerName:(NSString*)containerName; // Test support: -- (instancetype)initWithEnvironmentName:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort +- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort apsConnectionClass:(Class)apsConnectionClass; -- (instancetype)initWithEnvironmentName:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort +- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort apsConnectionClass:(Class)apsConnectionClass stalePushTimeout:(uint64_t)stalePushTimeout; + // This is the queue that APNS will use send the notifications to us + (dispatch_queue_t)apsDeliveryQueue; +- (NSArray*)registeredPushEnvironments; @end @interface OctagonAPSReceiver (Testing) -+ (void)resetGlobalEnviornmentMap; -- (void)reportDroppedPushes:(NSDictionary*>*)notifications; +- (void)reportDroppedPushes:(NSSet*)notifications; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/OctagonAPSReceiver.m b/keychain/ckks/OctagonAPSReceiver.m index e8eeb4f7..40f4894e 100644 --- a/keychain/ckks/OctagonAPSReceiver.m +++ b/keychain/ckks/OctagonAPSReceiver.m @@ -23,6 +23,8 @@ #if OCTAGON +#import + #import "keychain/ckks/OctagonAPSReceiver.h" #import "keychain/ckks/CKKS.h" #import "keychain/ckks/CKKSCondition.h" @@ -33,7 +35,6 @@ #import "keychain/ot/ObjCImprovements.h" #import #include -#include @implementation CKRecordZoneNotification (CKKSPushTracing) - (void)setCkksPushTracingEnabled:(BOOL)ckksPushTracingEnabled { @@ -66,62 +67,70 @@ @property CKKSNearFutureScheduler *clearStalePushNotifications; +@property NSString* namedDelegatePort; +@property NSMutableDictionary>* environmentMap; + + // If we receive notifications for a record zone that hasn't been registered yet, send them a their updates when they register -@property NSMutableDictionary*>* undeliveredUpdates; +@property NSMutableSet* undeliveredUpdates; // Same, but for cuttlefish containers (and only remember that a push was received; don't remember the pushes themselves) @property NSMutableSet* undeliveredCuttlefishUpdates; -@property NSMapTable>* zoneMap; +@property (nullable) id zoneUpdateReceiver; @property NSMapTable>* octagonContainerMap; @end @implementation OctagonAPSReceiver -+ (instancetype)receiverForEnvironment:(NSString *)environmentName - namedDelegatePort:(NSString*)namedDelegatePort - apsConnectionClass:(Class)apsConnectionClass ++ (instancetype)receiverForNamedDelegatePort:(NSString*)namedDelegatePort + apsConnectionClass:(Class)apsConnectionClass { - if(environmentName == nil) { - secnotice("octagonpush", "No push environment; not bringing up APS."); - return nil; - } - @synchronized([self class]) { - NSMutableDictionary* environmentMap = [self synchronizedGlobalEnvironmentMap]; + NSMutableDictionary* delegatePortMap = [self synchronizedGlobalDelegatePortMap]; - OctagonAPSReceiver* recv = [environmentMap valueForKey: environmentName]; + OctagonAPSReceiver* recv = delegatePortMap[namedDelegatePort]; if(recv == nil) { - recv = [[OctagonAPSReceiver alloc] initWithEnvironmentName: environmentName namedDelegatePort:namedDelegatePort apsConnectionClass: apsConnectionClass]; - [environmentMap setValue: recv forKey: environmentName]; + recv = [[OctagonAPSReceiver alloc] initWithNamedDelegatePort:namedDelegatePort + apsConnectionClass:apsConnectionClass]; + delegatePortMap[namedDelegatePort] = recv; } return recv; } } -+ (void)resetGlobalEnviornmentMap ++ (void)resetGlobalDelegatePortMap { @synchronized (self) { - [self resettableSynchronizedGlobalEnvironmentMap:YES]; + [self resettableSynchronizedGlobalDelegatePortMap:YES]; } } -+ (NSMutableDictionary*)synchronizedGlobalEnvironmentMap ++ (NSMutableDictionary*)synchronizedGlobalDelegatePortMap { - return [self resettableSynchronizedGlobalEnvironmentMap:NO]; + return [self resettableSynchronizedGlobalDelegatePortMap:NO]; } -+ (NSMutableDictionary*)resettableSynchronizedGlobalEnvironmentMap:(BOOL)reset ++ (NSMutableDictionary*)resettableSynchronizedGlobalDelegatePortMap:(BOOL)reset { - static NSMutableDictionary* environmentMap = nil; + static NSMutableDictionary* delegatePortMap = nil; - if(environmentMap == nil || reset) { - environmentMap = [[NSMutableDictionary alloc] init]; + if(delegatePortMap == nil || reset) { + delegatePortMap = [[NSMutableDictionary alloc] init]; } - return environmentMap; + return delegatePortMap; +} + +- (NSArray*)registeredPushEnvironments +{ + __block NSArray* environments = nil; + dispatch_sync([OctagonAPSReceiver apsDeliveryQueue], ^{ + environments = [self.environmentMap allKeys]; + }); + return environments; } + (dispatch_queue_t)apsDeliveryQueue { @@ -142,66 +151,46 @@ return haveStalePushes; } -- (NSSet*)cuttlefishPushTopics +- (NSArray*)cuttlefishPushTopics { NSString* cuttlefishTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.security.cuttlefish"]; // Currently cuttlefish pushes are sent to TPH. System XPC services can't properly register to be woken // at push time, so receive them for it. NSString* tphTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.TrustedPeersHelper"]; - NSString* securitydTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.securityd"]; - return [NSSet setWithArray:@[cuttlefishTopic, tphTopic, securitydTopic]]; + return @[cuttlefishTopic, tphTopic]; } -- (instancetype)initWithEnvironmentName:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort - apsConnectionClass:(Class)apsConnectionClass +- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort + apsConnectionClass:(Class)apsConnectionClass { - return [self initWithEnvironmentName:environmentName - namedDelegatePort:namedDelegatePort - apsConnectionClass:apsConnectionClass - stalePushTimeout:5*60*NSEC_PER_SEC]; + return [self initWithNamedDelegatePort:namedDelegatePort + apsConnectionClass:apsConnectionClass + stalePushTimeout:5*60*NSEC_PER_SEC]; } -- (instancetype)initWithEnvironmentName:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort - apsConnectionClass:(Class)apsConnectionClass - stalePushTimeout:(uint64_t)stalePushTimeout +- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort + apsConnectionClass:(Class)apsConnectionClass + stalePushTimeout:(uint64_t)stalePushTimeout { - if(self = [super init]) { + if((self = [super init])) { _apsConnectionClass = apsConnectionClass; - _apsConnection = NULL; - _undeliveredUpdates = [NSMutableDictionary dictionary]; + _undeliveredUpdates = [NSMutableSet set]; _undeliveredCuttlefishUpdates = [[NSMutableSet alloc] init]; - // APS might be slow. This doesn't need to happen immediately, so let it happen later. - WEAKIFY(self); - dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ - STRONGIFY(self); - if(!self) { - return; - } - self.apsConnection = [[self.apsConnectionClass alloc] initWithEnvironmentName:environmentName namedDelegatePort:namedDelegatePort queue:[OctagonAPSReceiver apsDeliveryQueue]]; - self.apsConnection.delegate = self; + _namedDelegatePort = namedDelegatePort; - // The following string should match: [[NSBundle mainBundle] bundleIdentifier] - NSString* ckksTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.securityd"]; + _environmentMap = [NSMutableDictionary dictionary]; - NSArray* topics = [@[ckksTopic] arrayByAddingObjectsFromArray:[self cuttlefishPushTopics].allObjects]; - [self.apsConnection setEnabledTopics:topics]; -#if TARGET_OS_OSX - [self.apsConnection setDarkWakeTopics:topics]; -#endif - }); - - _zoneMap = [NSMapTable strongToWeakObjectsMapTable]; _octagonContainerMap = [NSMapTable strongToWeakObjectsMapTable]; + _zoneUpdateReceiver = nil; + WEAKIFY(self); void (^clearPushBlock)(void) = ^{ dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ - NSDictionary*> *droppedUpdates; + NSMutableSet *droppedUpdates; STRONGIFY(self); if (self == nil) { return; @@ -209,7 +198,7 @@ droppedUpdates = self.undeliveredUpdates; - self.undeliveredUpdates = [NSMutableDictionary dictionary]; + self.undeliveredUpdates = [NSMutableSet set]; [self.undeliveredCuttlefishUpdates removeAllObjects]; [self reportDroppedPushes:droppedUpdates]; @@ -225,8 +214,47 @@ return self; } +- (void)registerForEnvironment:(NSString*)environmentName +{ + WEAKIFY(self); + + // APS might be slow. This doesn't need to happen immediately, so let it happen later. + dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ + STRONGIFY(self); + if(!self) { + return; + } + + id apsConnection = self.environmentMap[environmentName]; + if(apsConnection) { + // We've already set one of these up. + return; + } + + apsConnection = [[self.apsConnectionClass alloc] initWithEnvironmentName:environmentName namedDelegatePort:self.namedDelegatePort queue:[OctagonAPSReceiver apsDeliveryQueue]]; + self.environmentMap[environmentName] = apsConnection; + + apsConnection.delegate = self; + + // The following string should match: [[NSBundle mainBundle] bundleIdentifier] + NSString* ckksTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.securityd"]; + +#if TARGET_OS_WATCH + // Watches treat CKKS as opportunistic, and Octagon as normal priority. + apsConnection.enabledTopics = [self cuttlefishPushTopics]; + apsConnection.opportunisticTopics = @[ckksTopic]; +#else + apsConnection.enabledTopics = [[self cuttlefishPushTopics] arrayByAddingObject:ckksTopic]; +#if TARGET_OS_OSX + apsConnection.darkWakeTopics = self.apsConnection.enabledTopics; +#endif // TARGET_OS_OSX + +#endif // TARGET_OS_WATCH + }); +} + // Report that pushes we are dropping -- (void)reportDroppedPushes:(NSDictionary*>*)notifications +- (void)reportDroppedPushes:(NSSet*)notifications { bool hasBeenUnlocked = false; CFErrorRef error = NULL; @@ -243,44 +271,43 @@ eventName = @"CKKS APNS Push Dropped - never unlocked"; } - for (NSString *zone in notifications) { - for (CKRecordZoneNotification *notification in notifications[zone]) { - if (notification.ckksPushTracingEnabled) { - secnotice("apsnotification", "Submitting initial CKEventMetric due to notification %@", notification); + for (CKRecordZoneNotification *notification in notifications) { + if (notification.ckksPushTracingEnabled) { + ckksnotice_global("apsnotification", "Submitting initial CKEventMetric due to notification %@", notification); - SecEventMetric *metric = [[SecEventMetric alloc] initWithEventName:@"APNSPushMetrics"]; - metric[@"push_token_uuid"] = notification.ckksPushTracingUUID; - metric[@"push_received_date"] = notification.ckksPushReceivedDate; + SecEventMetric *metric = [[SecEventMetric alloc] initWithEventName:@"APNSPushMetrics"]; + metric[@"push_token_uuid"] = notification.ckksPushTracingUUID; + metric[@"push_received_date"] = notification.ckksPushReceivedDate; - metric[@"push_event_name"] = eventName; + metric[@"push_event_name"] = eventName; - [[SecMetrics managerObject] submitEvent:metric]; - } + [[SecMetrics managerObject] submitEvent:metric]; } } } - - -- (CKKSCondition*)registerReceiver:(id)receiver forZoneID:(CKRecordZoneID *)zoneID { +- (CKKSCondition*)registerCKKSReceiver:(id)receiver +{ CKKSCondition* finished = [[CKKSCondition alloc] init]; WEAKIFY(self); dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ STRONGIFY(self); if(!self) { - secerror("ckks: received registration for released OctagonAPSReceiver"); + ckkserror_global("octagonpush", "received registration for released OctagonAPSReceiver"); return; } - [self.zoneMap setObject:receiver forKey: zoneID.zoneName]; + ckksnotice_global("octagonpush", "Registering new CKKS push receiver: %@", receiver); - NSMutableSet* currentPendingMessages = self.undeliveredUpdates[zoneID.zoneName]; - [self.undeliveredUpdates removeObjectForKey:zoneID.zoneName]; + self.zoneUpdateReceiver = receiver; + + NSMutableSet* currentPendingMessages = [self.undeliveredUpdates copy]; + [self.undeliveredUpdates removeAllObjects]; for(CKRecordZoneNotification* message in currentPendingMessages.allObjects) { // Now, send the receiver its notification! - secerror("ckks: sending stored push(%@) to newly-registered zone(%@): %@", message, zoneID.zoneName, receiver); + ckkserror_global("octagonpush", "sending stored push(%@) to newly-registered receiver: %@", message, receiver); [receiver notifyZoneChange:message]; } @@ -299,7 +326,7 @@ dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ STRONGIFY(self); if(!self) { - secerror("octagon: received registration for released OctagonAPSReceiver"); + ckkserror_global("octagonpush", "received registration for released OctagonAPSReceiver"); return; } @@ -308,7 +335,7 @@ [self.undeliveredCuttlefishUpdates removeObject:containerName]; // Now, send the receiver its fake notification! - secerror("octagon: sending fake push to newly-registered cuttlefish receiver(%@): %@", containerName, receiver); + ckkserror_global("octagonpush", "sending fake push to newly-registered cuttlefish receiver(%@): %@", containerName, receiver); [receiver notifyContainerChange:nil]; } @@ -322,29 +349,27 @@ - (void)connection:(APSConnection *)connection didReceivePublicToken:(NSData *)publicToken { // no-op. - secnotice("octagonpush", "OctagonAPSDelegate initiated: %@", connection); + ckksnotice_global("octagonpush", "OctagonAPSDelegate initiated: %@", connection); } - (void)connection:(APSConnection *)connection didReceiveToken:(NSData *)token forTopic:(NSString *)topic identifier:(NSString *)identifier { - secnotice("octagonpush", "Received per-topic push token \"%@\" for topic \"%@\" identifier \"%@\" on connection %@", token, topic, identifier, connection); + ckksnotice_global("octagonpush", "Received per-topic push token \"%@\" for topic \"%@\" identifier \"%@\" on connection %@", token, topic, identifier, connection); } - (void)connection:(APSConnection *)connection didReceiveIncomingMessage:(APSIncomingMessage *)message { - secnotice("octagonpush", "OctagonAPSDelegate received a message(%@): %@ ", message.topic, message.userInfo); + ckksnotice_global("octagonpush", "OctagonAPSDelegate received a message(%@): %@ ", message.topic, message.userInfo); // Report back through APS that we received a message if(message.tracingEnabled) { [connection confirmReceiptForMessage:message]; } - NSSet* cuttlefishTopics = [self cuttlefishPushTopics]; - // Separate and handle cuttlefish notifications - if([cuttlefishTopics containsObject:message.topic] && [message.userInfo objectForKey:@"cf"]) { + if(message.userInfo[@"cf"] != nil) { NSDictionary* cfInfo = message.userInfo[@"cf"]; NSString* container = cfInfo[@"c"]; - secnotice("octagonpush", "Received a cuttlefish push to container %@", container); + ckksnotice_global("octagonpush", "Received a cuttlefish push to container %@", container); [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastOctagonPush]; if(container) { @@ -353,7 +378,7 @@ if(receiver) { [receiver notifyContainerChange:message]; } else { - secerror("octagonpush: received cuttlefish push for unregistered container: %@", container); + ckkserror_global("octagonpush", "received cuttlefish push for unregistered container: %@", container); [self.undeliveredCuttlefishUpdates addObject:container]; [self.clearStalePushNotifications trigger]; } @@ -380,23 +405,16 @@ [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastCKKSPush]; // Find receiever in map - id recv = [self.zoneMap objectForKey:rznotification.recordZoneID.zoneName]; + id recv = self.zoneUpdateReceiver; if(recv) { [recv notifyZoneChange:rznotification]; } else { - secerror("ckks: received push for unregistered zone: %@", rznotification); - if(rznotification.recordZoneID) { - NSMutableSet* currentPendingMessages = self.undeliveredUpdates[rznotification.recordZoneID.zoneName]; - if(currentPendingMessages) { - [currentPendingMessages addObject:rznotification]; - } else { - self.undeliveredUpdates[rznotification.recordZoneID.zoneName] = [NSMutableSet setWithObject:rznotification]; - [self.clearStalePushNotifications trigger]; - } - } + ckkserror_global("ckkspush", "received push for unregistered receiver: %@", rznotification); + [self.undeliveredUpdates addObject:rznotification]; + [self.clearStalePushNotifications trigger]; } } else { - secerror("ckks: unexpected notification: %@", notification); + ckkserror_global("ckkspush", "unexpected notification: %@", notification); } } diff --git a/keychain/ckks/RateLimiter.m b/keychain/ckks/RateLimiter.m index 1dd84320..ed7fb034 100644 --- a/keychain/ckks/RateLimiter.m +++ b/keychain/ckks/RateLimiter.m @@ -22,8 +22,8 @@ */ #import "RateLimiter.h" -#import #import "sec_action.h" +#import "keychain/ckks/CKKS.h" #import // For clarity. Also included in debugging.h @interface RateLimiter() @@ -37,8 +37,7 @@ @implementation RateLimiter - (instancetype)initWithConfig:(NSDictionary *)config { - self = [super init]; - if (self) { + if ((self = [super init])) { _config = config; _assetType = nil; [self reset]; @@ -50,8 +49,7 @@ if (!coder) { return nil; } - self = [super init]; - if (self) { + if ((self = [super init])) { _groups = [coder decodeObjectOfClasses:[NSSet setWithObjects: [NSArray class], [NSMutableDictionary class], [NSString class], @@ -87,7 +85,7 @@ dispatch_once(&token, ^{ action = sec_action_create("ratelimiterdisabledlogevent", 60); sec_action_set_handler(action, ^{ - secnotice("ratelimit", "Rate limiting disabled, returning automatic all-clear"); + ckksnotice_global("ratelimit", "Rate limiting disabled, returning automatic all-clear"); }); }); sec_action_perform(action); @@ -135,7 +133,7 @@ // approved properties 'accessGroup' and 'uuid' and if the item doesn't have either it's sad times anyway. // Improve rate limiter error handling if (!name) { - secerror("RateLimiter[%@]: Got nil instead of property named %@", self.config[@"general"][@"name"], groupConfig[@"property"]); + ckkserror_global("ratelimiter", "RateLimiter[%@]: Got nil instead of property named %@", self.config[@"general"][@"name"], groupConfig[@"property"]); continue; } NSDate *singleTokenTime = [self consumeTokenFromBucket:self.groups[idx] @@ -205,7 +203,7 @@ if ([self stateSize] > [self.config[@"general"][@"maxStateSize"] unsignedIntegerValue]) { // Trimming did not reduce size (enough), we need to take measures self.overloadUntil = [time dateByAddingTimeInterval:[self.config[@"general"][@"overloadDuration"] unsignedIntValue]]; - secerror("RateLimiter[%@] state size %lu exceeds max %lu, overloaded until %@", + ckkserror_global("ratelimiter", "RateLimiter[%@] state size %lu exceeds max %lu, overloaded until %@", self.config[@"general"][@"name"], (unsigned long)[self stateSize], [self.config[@"general"][@"maxStateSize"] unsignedLongValue], diff --git a/keychain/ckks/tests/AutoreleaseTest.c b/keychain/ckks/tests/AutoreleaseTest.c index 796ef505..81fb47f4 100644 --- a/keychain/ckks/tests/AutoreleaseTest.c +++ b/keychain/ckks/tests/AutoreleaseTest.c @@ -41,8 +41,7 @@ read_releases_pending(int fd, void (^handler)(ssize_t)) char *line = NULL; size_t linecap = 0; - ssize_t linelen; - while ((linelen = getline(&line, &linecap, fp)) > 0) { + while (getline(&line, &linecap, fp) > 0) { ssize_t pending; if (sscanf(line, "objc[%*d]: %ld releases pending", &pending) == 1) { diff --git a/keychain/ckks/tests/CKKSAESSIVEncryptionTests.m b/keychain/ckks/tests/CKKSAESSIVEncryptionTests.m index 1dc7249f..0cdf49d5 100644 --- a/keychain/ckks/tests/CKKSAESSIVEncryptionTests.m +++ b/keychain/ckks/tests/CKKSAESSIVEncryptionTests.m @@ -28,6 +28,7 @@ #import "keychain/ckks/CKKS.h" #import "keychain/ckks/CKKSKey.h" +#import "keychain/ckks/CKKSMemoryKeyCache.h" #import "keychain/ckks/CKKSItem.h" #import "keychain/ckks/CKKSOutgoingQueueEntry.h" #import "keychain/ckks/CKKSIncomingQueueEntry.h" @@ -308,7 +309,13 @@ NSData* testCKRecord = [@"nonsense" dataUsingEncoding:NSUTF8StringEncoding]; CKKSKey* tlk = [self fakeTLK:self.testZoneID]; - [tlk saveToDatabase:&error]; + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [tlk saveToDatabase:&saveError]; + XCTAssertNil(saveError, "tlk saved to database without error"); + return CKKSDatabaseTransactionCommit; + }]; + [tlk saveKeyMaterialToKeychain:&error]; XCTAssertNil(error, "tlk saved to database without error"); @@ -317,15 +324,24 @@ XCTAssertNotNil(level1, "level 1 key created"); XCTAssertNil(error, "level 1 key created"); - [level1 saveToDatabase:&error]; - XCTAssertNil(error, "level 1 key saved to database without error"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [level1 saveToDatabase:&saveError]; + XCTAssertNil(saveError, "level 1 key saved to database without error"); + return CKKSDatabaseTransactionCommit; + }]; CKKSKey* level2 = [CKKSKey randomKeyWrappedByParent: level1 error:&error]; level2.encodedCKRecord = testCKRecord; XCTAssertNotNil(level2, "level 2 key created"); XCTAssertNil(error, "no error creating level 2 key"); - [level2 saveToDatabase:&error]; - XCTAssertNil(error, "level 2 key saved to database without error"); + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [level2 saveToDatabase:&saveError]; + XCTAssertNil(saveError, "level 2 key saved to database without error"); + return CKKSDatabaseTransactionCommit; + }]; NSString* level2UUID = level2.uuid; @@ -344,8 +360,14 @@ - (void)ensureKeychainSaveLoad: (CKKSKey*) key { NSError* error = nil; - [key saveToDatabase:&error]; - XCTAssertNil(error, "no error saving to database"); + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [key saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; + [key saveKeyMaterialToKeychain:&error]; XCTAssertNil(error, "no error saving to keychain"); @@ -398,7 +420,7 @@ - (BOOL)tryDecryptWithProperAuthData:(CKKSItem*)ciphertext plaintext:(NSDictionary*)plaintext { NSDictionary* roundtrip; NSError *error = nil; - roundtrip = [CKKSItemEncrypter decryptItemToDictionary: (CKKSItem*) ciphertext error: &error]; + roundtrip = [CKKSItemEncrypter decryptItemToDictionary: (CKKSItem*) ciphertext keyCache:nil error: &error]; XCTAssertNil(error, "No error decrypting roundtrip"); XCTAssertNotNil(roundtrip, "Received a plaintext"); XCTAssertEqualObjects(plaintext, roundtrip, "roundtripped dictionary matches input"); @@ -408,7 +430,7 @@ - (BOOL)tryDecryptWithBrokenAuthData:(CKKSItem *)ciphertext { NSDictionary* brokenAuthentication; NSError *error = nil; - brokenAuthentication = [CKKSItemEncrypter decryptItemToDictionary: (CKKSItem*) ciphertext error: &error]; + brokenAuthentication = [CKKSItemEncrypter decryptItemToDictionary: (CKKSItem*) ciphertext keyCache:nil error: &error]; XCTAssertNotNil(error, "Error exists decrypting ciphertext with bad authenticated data: %@", error); XCTAssertNil(brokenAuthentication, "Did not receive a plaintext if authenticated data was mucked with"); return error != nil && brokenAuthentication == nil; @@ -421,7 +443,12 @@ NSString *uuid = @"8b2aeb7f-4af3-43e9-b6e6-70d5c728ebf7"; CKKSKey* key = [self fakeTLK:self.testZoneID]; - [key saveToDatabase: &error]; + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [key saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; [key saveKeyMaterialToKeychain:&error]; XCTAssertNil(error, @"could save the fake TLK to the database"); @@ -431,6 +458,7 @@ dataDictionary:plaintext updatingCKKSItem:nil parentkey:key + keyCache:nil error:&error]; XCTAssertNil(error, "No error encrypting plaintext"); XCTAssertNotNil(ciphertext, "Received a ciphertext"); @@ -467,9 +495,15 @@ error:&error]; XCTAssertNil(error); CKKSKey* key = [self fakeTLK:self.testZoneID]; - [key saveToDatabase: &error]; + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [key saveToDatabase:&saveError]; + XCTAssertNil(saveError, "could save the fake TLK to the database"); + return CKKSDatabaseTransactionCommit; + }]; [key saveKeyMaterialToKeychain:&error]; - XCTAssertNil(error, @"could save the fake TLK to the database"); + XCTAssertNil(error, @"could save the fake TLK to the keychain"); CKKSAESSIVKey* keyToWrap = [[CKKSAESSIVKey alloc] initWithBase64: @"uImdbZ7Zg+6WJXScTnRBfNmoU1UiMkSYxWc+d1Vuq3IFn2RmTRkTdWTe3HmeWo1pAomqy+upK8KHg2PGiRGhqg=="]; CKKSWrappedAESSIVKey* wrappedKey = [key wrapAESKey: keyToWrap error:&error]; @@ -484,8 +518,10 @@ encver:CKKSItemEncryptionVersionNone]; XCTAssertNotNil(baseitem, "Constructed CKKSItem"); + CKKSMemoryKeyCache* keyCache = [[CKKSMemoryKeyCache alloc] init]; + // First try versionNone. Should fail, we don't support unencrypted data - output = [CKKSItemEncrypter decryptItemToDictionary:baseitem error:&error]; + output = [CKKSItemEncrypter decryptItemToDictionary:baseitem keyCache:keyCache error:&error]; XCTAssert(error, "Did not failed to decrypt v0 item"); XCTAssertNil(output, "Did not failed to decrypt v0 item"); error = nil; @@ -493,7 +529,7 @@ // Then try version1. Should take actual decryption path and fail because there's no properly encrypted data. baseitem.encver = CKKSItemEncryptionVersion1; - output = [CKKSItemEncrypter decryptItemToDictionary:baseitem error:&error]; + output = [CKKSItemEncrypter decryptItemToDictionary:baseitem keyCache:keyCache error:&error]; XCTAssertNotNil(error, "Taking v1 codepath without encrypted item fails"); XCTAssertEqualObjects(error.localizedDescription, @"could not ccsiv_crypt", "Error specifically failure to ccsiv_crypt"); XCTAssertNil(output, "Did not receive output from failed decryption call"); @@ -502,7 +538,7 @@ // Finally, some unknown version should fail immediately baseitem.encver = 100; - output = [CKKSItemEncrypter decryptItemToDictionary:baseitem error:&error]; + output = [CKKSItemEncrypter decryptItemToDictionary:baseitem keyCache:keyCache error:&error]; XCTAssertNotNil(error); NSString *errstr = [NSString stringWithFormat:@"%@", error.localizedDescription]; NSString *expected = @"Unrecognized encryption version: 100"; @@ -735,7 +771,7 @@ memset((unsigned char *)[data mutableBytes], 0x55, 23); NSData *padded = [CKKSItemEncrypter padData:data blockSize:0 additionalBlock:extra]; XCTAssertNotNil(padded, "Padding never returns nil"); - XCTAssertTrue(padded.length == data.length + extra ? 2 : 1, "One byte of padding has been added, 2 if extra padding"); + XCTAssertTrue(padded.length == data.length + (extra ? 2 : 1), "One byte of padding has been added, 2 if extra padding"); NSData *unpadded = [CKKSItemEncrypter removePaddingFromData:padded]; XCTAssertNotNil(unpadded, "Successfully removed padding again"); XCTAssertEqualObjects(data, unpadded, "Data effectively unmodified through padding-unpadding trip"); diff --git a/keychain/ckks/tests/CKKSAPSHandlingTests.m b/keychain/ckks/tests/CKKSAPSHandlingTests.m index 4aa357ac..3a5e8077 100644 --- a/keychain/ckks/tests/CKKSAPSHandlingTests.m +++ b/keychain/ckks/tests/CKKSAPSHandlingTests.m @@ -144,9 +144,8 @@ // Inject a message at the APS layer // Because we can only make APS receivers once iCloud tells us the push environment after sign-in, we can't use our normal injection strategy, and fell back on global state. - OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForEnvironment:self.apsEnvironment - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsReceiver, "Should have gotten an APS receiver"); // Also, CKKS should handle this in one single fetch @@ -209,9 +208,8 @@ // Inject a message at the APS layer // Because we can only make APS receivers once iCloud tells us the push environment after sign-in, we can't use our normal injection strategy, and fell back on global state. - OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForEnvironment:self.apsEnvironment - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsReceiver, "Should have gotten an APS receiver"); // Also, CKKS should handle this in one single fetch @@ -224,6 +222,7 @@ // Launch! [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage]; OCMVerifyAllWithDelay(self.mockContainerExpectations, 16); + OCMVerifyAllWithDelay(self.mockDatabase, 20); // Now, wait for both views to run their processing [keychainProcessTimeoutOp waitUntilFinished]; @@ -258,14 +257,10 @@ // Inject a message at the APS layer // Because we can only make APS receivers once iCloud tells us the push environment after sign-in, we can't use our normal injection strategy, and fell back on global state. - OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForEnvironment:self.apsEnvironment - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsReceiver, "Should have gotten an APS receiver"); - [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage]; - [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage2]; - // Expect four metric pushes, two per push: one from receiving the push and one from after we finish the fetch // AFAICT there's no way to introspect a metric object to ensure we did it right OCMExpect([self.mockContainerExpectations submitEventMetric:[OCMArg any]]); @@ -273,6 +268,9 @@ OCMExpect([self.mockContainerExpectations submitEventMetric:[OCMArg any]]); OCMExpect([self.mockContainerExpectations submitEventMetric:[OCMArg any]]); + [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage]; + [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage2]; + // Launch! CKKSKeychainView* pushTestView = [self.injectedManager findOrCreateView:pushTestZone.zoneName]; [self.ckksViews addObject:pushTestView]; @@ -291,8 +289,7 @@ APSIncomingMessage* apsMessage = [CKKSAPSHandlingTests messageWithTracingEnabledForZoneID:pushTestZone]; // Don't use the global map here, because we need to ensure we create a new object (to use the stalePushTimeout we injected above) - OctagonAPSReceiver* apsReceiver = OCMPartialMock([[OctagonAPSReceiver alloc] initWithEnvironmentName:self.apsEnvironment - namedDelegatePort:SecCKKSAPSNamedPort + OctagonAPSReceiver* apsReceiver = OCMPartialMock([[OctagonAPSReceiver alloc] initWithNamedDelegatePort:SecCKKSAPSNamedPort apsConnectionClass:[FakeAPSConnection class] stalePushTimeout:4 * NSEC_PER_SEC]); XCTAssertNotNil(apsReceiver, "Should have gotten an APS receiver"); diff --git a/keychain/ckks/tests/CKKSCloudKitTests.m b/keychain/ckks/tests/CKKSCloudKitTests.m deleted file mode 100644 index 6add0637..00000000 --- a/keychain/ckks/tests/CKKSCloudKitTests.m +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#import -#import -#import - -#import -#import -#import "keychain/securityd/SecItemServer.h" -#if NO_SERVER -#include "keychain/securityd/spi.h" -#endif - -#import "keychain/ckks/CKKS.h" -#import "keychain/ckks/CKKSViewManager.h" -#import "keychain/ckks/CKKSKeychainView.h" -#import "keychain/ckks/CKKSCurrentKeyPointer.h" -#import "keychain/ckks/CKKSMirrorEntry.h" -#import "keychain/ckks/CKKSItemEncrypter.h" -#import "keychain/ckks/CloudKitCategories.h" -#import "keychain/categories/NSError+UsefulConstructors.h" -#import "keychain/ckks/tests/MockCloudKit.h" - -@interface CKKSCloudKitTests : XCTestCase - -@property NSOperationQueue *operationQueue; -@property CKContainer *container; -@property CKDatabase *database; -@property CKKSKeychainView *kcv; -@property NSString *zoneName; -@property CKRecordZoneID *zoneID; -@property NSDictionary *remoteItems; -@property NSInteger queueTimeout; - -@end - -// TODO: item modification should up gencount, check this - -@implementation CKKSCloudKitTests - -#if OCTAGON - -#pragma mark Setup - -+ (void)setUp { - SecCKKSResetSyncing(); - SecCKKSTestsEnable(); - SecCKKSSetReduceRateLimiting(true); - [super setUp]; - -#if NO_SERVER - securityd_init_local_spi(); -#endif -} - -- (void)setUp { - self.remoteItems = nil; - self.queueTimeout = 900; // CloudKit can be *very* slow, and some tests upload a lot of items indeed - NSString *containerName = [NSString stringWithFormat:@"com.apple.test.p01.B.com.apple.security.keychain.%@", [[NSUUID new] UUIDString]]; - self.container = [CKContainer containerWithIdentifier:containerName]; - - SecCKKSTestResetFlags(); - SecCKKSTestSetDisableSOS(true); - - self.operationQueue = [NSOperationQueue new]; - - CKKSCloudKitClassDependencies* cloudKitClassDependencies = [[CKKSCloudKitClassDependencies alloc] initWithFetchRecordZoneChangesOperationClass:[CKFetchRecordZoneChangesOperation class] - fetchRecordsOperationClass:[CKFetchRecordsOperation class] - queryOperationClass:[CKQueryOperation class] - modifySubscriptionsOperationClass:[CKModifySubscriptionsOperation class] - modifyRecordZonesOperationClass:[CKModifyRecordZonesOperation class] - apsConnectionClass:[APSConnection class] - nsnotificationCenterClass:[NSNotificationCenter class] - nsdistributednotificationCenterClass:[NSDistributedNotificationCenter class] - notifierClass:[FakeCKKSNotifier class]]; - - CKKSViewManager* manager = [[CKKSViewManager alloc] initWithContainerName:containerName - usePCS:SecCKKSContainerUsePCS - sosAdapter:nil - cloudKitClassDependencies:cloudKitClassDependencies]; - [CKKSViewManager resetManager:false setTo:manager]; - - // Make a new fake keychain - NSString* smallName = [self.name componentsSeparatedByString:@" "][1]; - smallName = [smallName stringByReplacingOccurrencesOfString:@"]" withString:@""]; - - NSString* tmp_dir = [NSString stringWithFormat: @"/tmp/%@.%X", smallName, arc4random()]; - [[NSFileManager defaultManager] createDirectoryAtPath:[NSString stringWithFormat: @"%@/Library/Keychains", tmp_dir] withIntermediateDirectories:YES attributes:nil error:NULL]; - - SetCustomHomeURLString((__bridge CFStringRef) tmp_dir); - SecKeychainDbReset(NULL); - // Actually load the database. - kc_with_dbt(true, NULL, ^bool (SecDbConnectionRef dbt) { return false; }); - - self.zoneName = @"keychain"; - self.zoneID = [[CKRecordZoneID alloc] initWithZoneName:self.zoneName ownerName:CKCurrentUserDefaultName]; - self.kcv = [[CKKSViewManager manager] findOrCreateView:@"keychain"]; -} - -- (void)tearDown { - self.remoteItems = nil; - [[CKKSViewManager manager] clearView:@"keychain"]; - SecCKKSTestResetFlags(); -} - -+ (void)tearDown { - SecCKKSResetSyncing(); -} - -#pragma mark Helpers - -- (BOOL)waitForEmptyOutgoingQueue:(CKKSKeychainView *)view { - [view processOutgoingQueue:[CKOperationGroup CKKSGroupWithName:@"waitForEmptyOutgoingQueue"]]; - NSInteger secondsToWait = self.queueTimeout; - while (true) { - if ([view outgoingQueueEmpty:nil]) { - return YES; - } - [NSThread sleepForTimeInterval:1]; - if (--secondsToWait % 60 == 0) { - long minutesWaited = (self.queueTimeout - secondsToWait)/60; - NSLog(@"Waiting %ld minute%@ for empty outgoingQueue", minutesWaited, minutesWaited > 1 ? @"s" : @""); - } - if (secondsToWait <= 0) { - XCTFail(@"Timed out waiting for '%@' OutgoingQueue to become empty", view); - NSLog(@"Giving up waiting for empty outgoingQueue"); - return NO; - } - - } -} - -- (void)startCKKSSubsystem { - // TODO: we removed this mechanism, but haven't tested to see if these tests still succeed -} - -- (NSMutableDictionary *)fetchLocalItems { - NSDictionary *query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecReturnAttributes : (id)kCFBooleanTrue, - (id)kSecReturnData : (id)kCFBooleanTrue, - (id)kSecMatchLimit : (id)kSecMatchLimitAll, - }; - CFTypeRef cfresults; - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &cfresults); - XCTAssert(status == errSecSuccess || status == errSecItemNotFound, @"retrieved zero or more local items"); - if (status == errSecItemNotFound) { - return [NSMutableDictionary new]; - } else if (status != errSecSuccess) { - return nil; - } - - NSArray *results = CFBridgingRelease(cfresults); - - NSMutableDictionary *ret = [NSMutableDictionary new]; - for (NSMutableDictionary *item in results) { - ret[item[@"UUID"]] = item; - } - - return ret; -} - -- (NSMutableDictionary *)fetchRemoteItems { - CKFetchRecordZoneChangesConfiguration *options = [CKFetchRecordZoneChangesConfiguration new]; - options.previousServerChangeToken = nil; - - CKFetchRecordZoneChangesOperation *op = [[CKFetchRecordZoneChangesOperation alloc] initWithRecordZoneIDs:@[self.zoneID] configurationsByRecordZoneID:@{self.zoneID : options}]; - op.configuration.automaticallyRetryNetworkFailures = NO; - op.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; - op.configuration.isCloudKitSupportOperation = YES; - op.configuration.container = self.container; - - __block NSMutableDictionary *data = [NSMutableDictionary new]; - __block NSUInteger synckeys = 0; - __block NSUInteger currkeys = 0; - op.recordChangedBlock = ^(CKRecord *record) { - if ([record.recordType isEqualToString:SecCKRecordItemType]) { - data[record.recordID.recordName] = [self decryptRecord:record]; - } else if ([record.recordType isEqualToString:SecCKRecordIntermediateKeyType]) { - synckeys += 1; - } else if ([record.recordType isEqualToString:SecCKRecordCurrentKeyType]) { - currkeys += 1; - } else { - XCTFail(@"Encountered unexpected item %@", record); - } - }; - - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - op.recordZoneFetchCompletionBlock = ^(CKRecordZoneID * _Nonnull recordZoneID, - CKServerChangeToken * _Nullable serverChangeToken, - NSData * _Nullable clientChangeTokenData, - BOOL moreComing, - NSError * _Nullable recordZoneError) { - XCTAssertNil(recordZoneError, @"No error in recordZoneFetchCompletionBlock"); - if (!moreComing) { - dispatch_semaphore_signal(sema); - } - }; - - [op start]; - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - - // These are new, fresh zones for each test. There should not be old keys yet. - if (synckeys != 3) {XCTFail(@"Unexpected number of synckeys: %lu", (unsigned long)synckeys);} - if (currkeys != 3) {XCTFail(@"Unexpected number of current keys: %lu", (unsigned long)currkeys);} - - self.remoteItems = data; - return data; -} - -- (BOOL)compareLocalItem:(NSDictionary *)lhs remote:(NSDictionary *)rhs { - if ([lhs[@"cdat"] compare: rhs[@"cdat"]] != NSOrderedSame) {XCTFail(@"Creation date differs"); return NO;} - if ([lhs[@"mdat"] compare: rhs[@"mdat"]] != NSOrderedSame) {XCTFail(@"Modification date differs"); return NO;} - if (![lhs[@"agrp"] isEqualToString:rhs[@"agrp"]]) {XCTFail(@"Access group differs"); return NO;} - if (![lhs[@"acct"] isEqualToString:rhs[@"acct"]]) {XCTFail(@"Account differs"); return NO;} - if (![lhs[@"v_Data"] isEqualToData:rhs[@"v_Data"]]) {XCTFail(@"Data differs"); return NO;} - // class for lhs is already genp due to copymatching query - if (![rhs[@"class"] isEqualToString:@"genp"]) {XCTFail(@"Class not genp for remote item"); return NO;} - return YES; -} - -- (BOOL)compareLocalKeychainWithCloudKitState { - BOOL success = YES; - NSMutableDictionary *localItems = [self fetchLocalItems]; - if (localItems == nil) {XCTFail(@"Received nil for localItems"); return NO;} - NSMutableDictionary *remoteItems = [self fetchRemoteItems]; - if (remoteItems == nil) {XCTFail(@"Received nil for remoteItems"); return NO;} - - for (NSString *uuid in localItems.allKeys) { - if (remoteItems[uuid] == nil) { - XCTFail(@"account %@ item %@ not present in remote", localItems[uuid][@"acct"], localItems[uuid]); - success = NO; - continue; - } - if (![self compareLocalItem:localItems[uuid] remote:remoteItems[uuid]]) { - XCTFail(@"local item %@ matches remote item %@", localItems[uuid], remoteItems[uuid]); - success = NO; - } - [remoteItems removeObjectForKey:uuid]; - } - if ([remoteItems count]) { - XCTFail(@"No remote items present not found in local, %@", remoteItems); - return NO; - } - return success; -} - -- (BOOL)updateGenericPassword:(NSString *)password account:(NSString *)account { - NSDictionary *query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - }; - NSDictionary *newpasswd = @{(id)kSecValueData : (id) [password dataUsingEncoding:NSUTF8StringEncoding]}; - - return errSecSuccess == SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)newpasswd); -} - -- (BOOL)uploadRecords:(NSArray*)records { - CKModifyRecordsOperation *op = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:records recordIDsToDelete:nil]; - op.configuration.automaticallyRetryNetworkFailures = NO; - op.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; - op.configuration.isCloudKitSupportOperation = YES; - op.configuration.container = self.container; - - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - __block BOOL result = NO; - op.modifyRecordsCompletionBlock = ^(NSArray *savedRecords, - NSArray *deletedRecordIDs, - NSError *operationError) { - XCTAssertNil(operationError, @"No error uploading records, %@", operationError); - if (operationError == nil) { - result = YES; - } - dispatch_semaphore_signal(sema); - }; - - [op start]; - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - - return result; -} - -#pragma mark Helpers Adapted from MockXCTest - -- (CKRecord*)createFakeRecord: (CKRecordZoneID*)zoneID recordName:(NSString*)recordName { - return [self createFakeRecord: zoneID recordName:recordName withAccount: nil]; -} - -- (CKRecord*)createFakeRecord: (CKRecordZoneID*)zoneID recordName:(NSString*)recordName withAccount: (NSString*) account { - NSError* error = nil; - - /* Basically: @{ - @"acct" : @"account-delete-me", - @"agrp" : @"com.apple.security.sos", - @"cdat" : @"2016-12-21 03:33:25 +0000", - @"class" : @"genp", - @"mdat" : @"2016-12-21 03:33:25 +0000", - @"musr" : [[NSData alloc] init], - @"pdmn" : @"ak", - @"sha1" : [[NSData alloc] initWithBase64EncodedString: @"C3VWONaOIj8YgJjk/xwku4By1CY=" options:0], - @"svce" : @"", - @"tomb" : [NSNumber numberWithInt: 0], - @"v_Data" : [@"data" dataUsingEncoding: NSUTF8StringEncoding], - }; - TODO: this should be binary encoded instead of expanded, but the plist encoder should handle it fine */ - NSData* itemdata = [[NSData alloc] initWithBase64EncodedString:@"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8ZGljdD4KCTxrZXk+YWNjdDwva2V5PgoJPHN0cmluZz5hY2NvdW50LWRlbGV0ZS1tZTwvc3RyaW5nPgoJPGtleT5hZ3JwPC9rZXk+Cgk8c3RyaW5nPmNvbS5hcHBsZS5zZWN1cml0eS5zb3M8L3N0cmluZz4KCTxrZXk+Y2RhdDwva2V5PgoJPGRhdGU+MjAxNi0xMi0yMVQwMzozMzoyNVo8L2RhdGU+Cgk8a2V5PmNsYXNzPC9rZXk+Cgk8c3RyaW5nPmdlbnA8L3N0cmluZz4KCTxrZXk+bWRhdDwva2V5PgoJPGRhdGU+MjAxNi0xMi0yMVQwMzozMzoyNVo8L2RhdGU+Cgk8a2V5Pm11c3I8L2tleT4KCTxkYXRhPgoJPC9kYXRhPgoJPGtleT5wZG1uPC9rZXk+Cgk8c3RyaW5nPmFrPC9zdHJpbmc+Cgk8a2V5PnNoYTE8L2tleT4KCTxkYXRhPgoJQzNWV09OYU9JajhZZ0pqay94d2t1NEJ5MUNZPQoJPC9kYXRhPgoJPGtleT5zdmNlPC9rZXk+Cgk8c3RyaW5nPjwvc3RyaW5nPgoJPGtleT50b21iPC9rZXk+Cgk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJPGtleT52X0RhdGE8L2tleT4KCTxkYXRhPgoJWkdGMFlRPT0KCTwvZGF0YT4KPC9kaWN0Pgo8L3BsaXN0Pgo=" options:0]; - NSMutableDictionary * item = [[NSPropertyListSerialization propertyListWithData:itemdata - options:0 - format:nil - error:&error] mutableCopy]; - // Fix up dictionary - item[@"agrp"] = @"com.apple.security.ckks"; - - XCTAssertNil(error, "interpreted data as item"); - - if(account) { - [item setObject: account forKey: (__bridge id) kSecAttrAccount]; - } - - CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:recordName zoneID:zoneID]; - return [self newRecord: ckrid withNewItemData: item]; -} - -- (CKRecord*)newRecord: (CKRecordID*) recordID withNewItemData:(NSDictionary*) dictionary { - NSError* error = nil; - CKKSKey* classCKey = [CKKSKey currentKeyForClass:SecCKKSKeyClassC zoneID:recordID.zoneID error:&error]; - XCTAssertNotNil(classCKey, "Have class C key for zone"); - - CKKSItem* cipheritem = [CKKSItemEncrypter encryptCKKSItem:[[CKKSItem alloc] initWithUUID:recordID.recordName - parentKeyUUID:classCKey.uuid - zoneID:recordID.zoneID] - dataDictionary:dictionary - updatingCKKSItem:nil - parentkey:classCKey - error:&error]; - - CKKSOutgoingQueueEntry* ciphertext = [[CKKSOutgoingQueueEntry alloc] initWithCKKSItem:cipheritem - action:SecCKKSActionAdd - state:SecCKKSStateNew - waitUntil:nil - accessGroup:@"unused in this function"]; - XCTAssertNil(error, "encrypted item with class c key"); - - CKRecord* ckr = [ciphertext.item CKRecordWithZoneID: recordID.zoneID]; - XCTAssertNotNil(ckr, "Created a CKRecord"); - return ckr; -} - -- (NSDictionary*)decryptRecord: (CKRecord*) record { - CKKSMirrorEntry* ckme = [[CKKSMirrorEntry alloc] initWithCKRecord: record]; - - NSError* error = nil; - - NSDictionary* ret = [CKKSItemEncrypter decryptItemToDictionary:ckme.item error:&error]; - XCTAssertNil(error); - XCTAssertNotNil(ret); - return ret; -} - -- (BOOL)addMultiplePasswords:(NSString *)password account:(NSString *)account amount:(NSUInteger)amount { - while (amount > 0) { - if (![self addGenericPassword:password account:[NSString stringWithFormat:@"%@%03lu", account, amount]]) { - return NO; - } - amount -= 1; - } - return YES; -} - -- (BOOL)deleteMultiplePasswords:(NSString *)account amount:(NSUInteger)amount { - while (amount > 0) { - if (![self deleteGenericPassword:[NSString stringWithFormat:@"%@%03lu", account, amount]]) { - return NO; - } - amount -= 1; - } - return YES; -} - -- (BOOL)addGenericPassword: (NSString*) password account: (NSString*) account viewHint: (NSString*) viewHint expecting: (OSStatus) status message: (NSString*) message { - NSMutableDictionary* query = [@{ - (id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecValueData : (id) [password dataUsingEncoding:NSUTF8StringEncoding], - } mutableCopy]; - - if(viewHint) { - query[(id)kSecAttrSyncViewHint] = viewHint; - } - - return status == SecItemAdd((__bridge CFDictionaryRef) query, NULL); -} - -- (BOOL)addGenericPassword: (NSString*) password account: (NSString*) account expecting: (OSStatus) status message: (NSString*) message { - return [self addGenericPassword:password account:account viewHint:nil expecting:errSecSuccess message:message]; -} - -- (BOOL)addGenericPassword: (NSString*) password account: (NSString*) account { - return [self addGenericPassword:password account:account viewHint:nil expecting:errSecSuccess message:@"Add item to keychain"]; -} - -- (BOOL)addGenericPassword: (NSString*) password account: (NSString*) account viewHint:(NSString*)viewHint { - return [self addGenericPassword:password account:account viewHint:viewHint expecting:errSecSuccess message:@"Add item to keychain with a viewhint"]; -} - -- (BOOL)deleteGenericPassword: (NSString*) account { - NSDictionary* query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue,}; - - return errSecSuccess == SecItemDelete((__bridge CFDictionaryRef) query); -} - -- (BOOL)findGenericPassword: (NSString*) account expecting: (OSStatus) status { - NSDictionary *query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecMatchLimit : (id)kSecMatchLimitOne,}; - - return status == SecItemCopyMatching((__bridge CFDictionaryRef) query, NULL); -} - -- (void)checkGenericPassword: (NSString*) password account: (NSString*) account { - NSDictionary *query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecMatchLimit : (id)kSecMatchLimitOne, - (id)kSecReturnData : (id)kCFBooleanTrue, - }; - CFTypeRef result = NULL; - - XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &result), "Finding item %@", account); - XCTAssertNotNil((__bridge id)result, "Received an item"); - - NSString* storedPassword = [[NSString alloc] initWithData: (__bridge NSData*) result encoding: NSUTF8StringEncoding]; - XCTAssertNotNil(storedPassword, "Password parsed as a password"); - - XCTAssertEqualObjects(storedPassword, password, "Stored password matches received password"); -} - -#pragma mark Tests - -- (void)testAddDelete { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self addGenericPassword:@"data" account:@"ck-test-adddelete"], @"Added single item"); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAdd: states match after add"); - - XCTAssert([self deleteGenericPassword:@"ck-test-adddelete"], @"Deleted single item"); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAdd: states match after delete"); -} - -- (void)testAddModDelete { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - [self addGenericPassword:@"data" account:@"ck-test-addmoddelete"]; - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMod: states match after add"); - - [self updateGenericPassword:@"otherdata" account:@"ck-test-addmoddelete"]; - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMod: states match after mod"); - - [self deleteGenericPassword:@"ck-test-addmoddelete"]; - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMod: states match after del"); -} - -- (void)testAddModDeleteImmediate { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self addGenericPassword:@"data" account:@"ck-test-addmoddeleteimmediate"], @"Added item"); - XCTAssert([self updateGenericPassword:@"otherdata" account:@"ck-test-addmoddeleteimmediate"], @"Modified item"); - XCTAssert([self deleteGenericPassword:@"ck-test-addmoddeleteimmediate"], @"Deleted item"); - - [self waitForEmptyOutgoingQueue:self.kcv]; - [self.kcv waitForFetchAndIncomingQueueProcessing]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMod: states match after immediate add/mod/delete"); -} - -- (void)testReceive { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - [self findGenericPassword:@"ck-test-receive" expecting:errSecItemNotFound]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testReceive: states match before receive"); - - CKRecord *record = [self createFakeRecord:self.zoneID recordName:@"b6050e4d-e7b7-4e4e-b318-825cacc34722" withAccount:@"ck-test-receive"]; - [self uploadRecords:@[record]]; - - [self.kcv notifyZoneChange:nil]; - [self.kcv waitForFetchAndIncomingQueueProcessing]; - - [self findGenericPassword:@"ck-test-receive" expecting:errSecSuccess]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testReceive: states match after receive"); -} - -- (void)testReceiveColliding { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self findGenericPassword:@"ck-test-receivecolliding" expecting:errSecItemNotFound], @"test item not yet in keychain"); - - // Conflicting items! This test does not care how conflict gets resolved, just that state is consistent after syncing - CKRecord *r1 = [self createFakeRecord:self.zoneID recordName:@"97576447-c6b8-47fe-8f00-64f5da49d538" withAccount:@"ck-test-receivecolliding"]; - CKRecord *r2 = [self createFakeRecord:self.zoneID recordName:@"c6b86447-9757-47fe-8f00-64f5da49d538" withAccount:@"ck-test-receivecolliding"]; - [self uploadRecords:@[r1,r2]]; - - // poke CKKS since we won't have a real CK notification - [self.kcv notifyZoneChange:nil]; - [self.kcv waitForFetchAndIncomingQueueProcessing]; - [self waitForEmptyOutgoingQueue:self.kcv]; - - XCTAssert([self findGenericPassword:@"ck-test-receivecolliding" expecting:errSecSuccess], @"Item present after download"); - // This will also flag an issue if the two conflicting items persist - XCTAssert([self compareLocalKeychainWithCloudKitState], @"Back in sync after processing incoming changes"); -} - -- (void)testAddMultipleDeleteAll { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self addMultiplePasswords:@"data" account:@"ck-test-addmultipledeleteall" amount:5]); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMultipleDeleteAll: states match after adds"); - - XCTAssert([self deleteMultiplePasswords:@"ck-test-addmultipledeleteall" amount:3]); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMultipleDeleteAll: states match after deletes"); - - XCTAssert([self deleteGenericPassword:@"ck-test-addmultipledeleteall005"]); - XCTAssert([self deleteGenericPassword:@"ck-test-addmultipledeleteall004"]); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMultipleDeleteAll: states match after deletes"); -} - -- (void)testAddLotsOfItems { - [ self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self addMultiplePasswords:@"data" account:@"ck-test-addlotsofitems" amount:250], @"Added a truckload of items"); - - XCTAssert([self waitForEmptyOutgoingQueue:self.kcv], @"Completed upload within %ld seconds", (long)self.queueTimeout); - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddLotsOfItems: states match after adding tons of items"); - - XCTAssert([self deleteMultiplePasswords:@"ck-test-addlotsofitems" amount:250], @"Got rid of a truckload of items"); - XCTAssert([self waitForEmptyOutgoingQueue:self.kcv], @"Completed deletions within %ld seconds",(long)self.queueTimeout); - - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddLotsOfItems: states match after removing tons of items again"); -} - -#endif - -@end diff --git a/keychain/ckks/tests/CKKSConditionTests.m b/keychain/ckks/tests/CKKSConditionTests.m index 1c0c6bb2..df6bc28f 100644 --- a/keychain/ckks/tests/CKKSConditionTests.m +++ b/keychain/ckks/tests/CKKSConditionTests.m @@ -25,7 +25,6 @@ #import #import #import "keychain/ckks/CKKSCondition.h" -#import @interface CKKSConditionTests : XCTestCase @end diff --git a/keychain/ckks/tests/CKKSDeviceStateUploadTests.m b/keychain/ckks/tests/CKKSDeviceStateUploadTests.m index 8d0c019a..0986399d 100644 --- a/keychain/ckks/tests/CKKSDeviceStateUploadTests.m +++ b/keychain/ckks/tests/CKKSDeviceStateUploadTests.m @@ -85,6 +85,7 @@ return NO; } } + inspectOperationGroup:nil runAfterModification:nil]; [self.keychainView updateDeviceState:false waitForKeyHierarchyInitialization:2*NSEC_PER_SEC ckoperationGroup:nil]; @@ -131,6 +132,7 @@ return NO; } } + inspectOperationGroup:nil runAfterModification:nil]; CKKSUpdateDeviceStateOperation* op = [self.keychainView updateDeviceState:true waitForKeyHierarchyInitialization:2*NSEC_PER_SEC ckoperationGroup:nil]; @@ -152,7 +154,7 @@ [op waitUntilFinished]; // And now, if the update is old enough, that'll work too - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry fromDatabase:self.accountStateTracker.ckdeviceID zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "No error fetching device state entry"); @@ -176,7 +178,7 @@ [cdse saveToDatabase:&error]; XCTAssertNil(error, "No error saving device state entry"); - return true; + return CKKSDatabaseTransactionCommit; }]; // And now the rate-limiting doesn't get in the way @@ -212,7 +214,7 @@ NSString* oldDeviceID = self.accountStateTracker.ckdeviceID; self.accountStateTracker.ckdeviceID = nil; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry fromDatabase:oldDeviceID zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "No error fetching device state entry"); @@ -222,8 +224,6 @@ NSDate* m = record.modificationDate; XCTAssertNotNil(m, "Have modification date"); - - return true; }]; // It shouldn't try to upload a new CDSE; there's no device ID @@ -455,10 +455,10 @@ [self.keychainZone addToZone:[octagonOnly CKRecordWithZoneID:self.keychainZoneID]]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* cdses = [CKKSDeviceStateEntry allInZone:self.keychainZoneID error:&error]; XCTAssertNil(error, "No error fetching CDSEs"); @@ -519,8 +519,6 @@ XCTAssertEqualObjects(octagondevice.currentTLKUUID, zoneKeys.tlk.uuid, "correct tlk uuid"); XCTAssertEqualObjects(octagondevice.currentClassAUUID, zoneKeys.classA.uuid, "correct classA uuid"); XCTAssertEqualObjects(octagondevice.currentClassCUUID, zoneKeys.classC.uuid, "correct classC uuid"); - - return false; }]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -533,7 +531,6 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "CKKS entered waitfortlk"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateWaitForTLK, "CKKS entered waitfortlk"); __weak __typeof(self) weakSelf = self; [self expectCKModifyRecords: @{SecCKRecordDeviceStateType: [NSNumber numberWithInt:1]} @@ -629,13 +626,11 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "CKKS entered waitfortlk"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateWaitForTLK, "CKKS entered waitfortlk"); // And restart CKKS... self.keychainView = [[CKKSViewManager manager] restartZone: self.keychainZoneID.zoneName]; [self beginSOSTrustedViewOperation:self.keychainView]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "CKKS entered waitfortlk"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateWaitForTLK, "CKKS entered waitfortlk"); __weak __typeof(self) weakSelf = self; [self expectCKModifyRecords: @{SecCKRecordDeviceStateType: [NSNumber numberWithInt:1]} @@ -770,7 +765,8 @@ [self.keychainView updateDeviceState:false waitForKeyHierarchyInitialization:8*NSEC_PER_SEC ckoperationGroup:nil]; - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateFetch, "CKKS re-entered fetch"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateFetch] wait:20*NSEC_PER_SEC], "Key state should become fetch"); [self releaseCloudKitFetchHold]; OCMVerifyAllWithDelay(self.mockDatabase, 20); diff --git a/keychain/ckks/tests/CKKSDispatchTests.m b/keychain/ckks/tests/CKKSDispatchTests.m deleted file mode 100644 index eff091fc..00000000 --- a/keychain/ckks/tests/CKKSDispatchTests.m +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#import -#import "keychain/ckks/CKKSNearFutureScheduler.h" - -@interface CKKSNearFutureSchedulerTests : XCTestCase - -@end - -@implementation CKKSNearFutureSchedulerTests - -- (void)setUp { - [super setUp]; -} - -- (void)tearDown { - [super tearDown]; -} - -- (void)testOneShot { - XCTestExpectation *expectation = [self expectationWithDescription:@"FutureScheduler fired"]; - - CKKSNearFutureScheduler* scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" delay:50*NSEC_PER_MSEC keepProcessAlive:true block:^{ - [expectation fulfill]; - }]; - - [scheduler trigger]; - - [self waitForExpectationsWithTimeout:1 handler:nil]; -} - -- (void)testOneShotDelay { - XCTestExpectation *toofastexpectation = [self expectationWithDescription:@"FutureScheduler fired (too soon)"]; - toofastexpectation.inverted = YES; - - XCTestExpectation *expectation = [self expectationWithDescription:@"FutureScheduler fired"]; - - CKKSNearFutureScheduler* scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" delay: 200*NSEC_PER_MSEC keepProcessAlive:false block:^{ - [toofastexpectation fulfill]; - [expectation fulfill]; - }]; - - [scheduler trigger]; - - // Make sure it waits at least 0.1 seconds - [self waitForExpectations: @[toofastexpectation] timeout:0.1]; - - // But finishes within 1.1s (total) - [self waitForExpectations: @[expectation] timeout:1]; -} - -- (void)testOneShotManyTrigger { - XCTestExpectation *toofastexpectation = [self expectationWithDescription:@"FutureScheduler fired (too soon)"]; - toofastexpectation.inverted = YES; - - XCTestExpectation *expectation = [self expectationWithDescription:@"FutureScheduler fired"]; - expectation.assertForOverFulfill = YES; - - CKKSNearFutureScheduler* scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" delay: 200*NSEC_PER_MSEC keepProcessAlive:true block:^{ - [toofastexpectation fulfill]; - [expectation fulfill]; - }]; - - [scheduler trigger]; - [scheduler trigger]; - [scheduler trigger]; - [scheduler trigger]; - [scheduler trigger]; - [scheduler trigger]; - [scheduler trigger]; - [scheduler trigger]; - - // Make sure it waits at least 0.1 seconds - [self waitForExpectations: @[toofastexpectation] timeout:0.1]; - - // But finishes within .6s (total) - [self waitForExpectations: @[expectation] timeout:0.5]; - - // Ensure we don't get called again in the next 0.3 s - XCTestExpectation* waitmore = [self expectationWithDescription:@"waiting"]; - waitmore.inverted = YES; - [self waitForExpectations: @[waitmore] timeout: 0.3]; -} - - -- (void)testMultiShot { - XCTestExpectation *first = [self expectationWithDescription:@"FutureScheduler fired (one)"]; - first.assertForOverFulfill = NO; - - XCTestExpectation *second = [self expectationWithDescription:@"FutureScheduler fired (two)"]; - second.expectedFulfillmentCount = 2; - second.assertForOverFulfill = YES; - - CKKSNearFutureScheduler* scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" delay: 100*NSEC_PER_MSEC keepProcessAlive:false block:^{ - [first fulfill]; - [second fulfill]; - }]; - - [scheduler trigger]; - - [self waitForExpectations: @[first] timeout:0.2]; - - [scheduler trigger]; - [scheduler trigger]; - [scheduler trigger]; - - [self waitForExpectations: @[second] timeout:0.2]; - - XCTestExpectation* waitmore = [self expectationWithDescription:@"waiting"]; - waitmore.inverted = YES; - [self waitForExpectations: @[waitmore] timeout: 0.2]; -} - -- (void)testMultiShotDelays { - XCTestExpectation *first = [self expectationWithDescription:@"FutureScheduler fired (one)"]; - first.assertForOverFulfill = NO; - - XCTestExpectation *longdelay = [self expectationWithDescription:@"FutureScheduler fired (long delay expectation)"]; - longdelay.inverted = YES; - longdelay.expectedFulfillmentCount = 2; - - XCTestExpectation *second = [self expectationWithDescription:@"FutureScheduler fired (two)"]; - second.expectedFulfillmentCount = 2; - second.assertForOverFulfill = YES; - - CKKSNearFutureScheduler* scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" initialDelay: 50*NSEC_PER_MSEC continuingDelay:300*NSEC_PER_MSEC keepProcessAlive:false block:^{ - [first fulfill]; - [longdelay fulfill]; - [second fulfill]; - }]; - - [scheduler trigger]; - - [self waitForExpectations: @[first] timeout:0.2]; - - [scheduler trigger]; - [scheduler trigger]; - [scheduler trigger]; - - // longdelay should NOT be fulfilled twice in the first 0.3 seconds - [self waitForExpectations: @[longdelay] timeout:0.2]; - - // But second should be fulfilled in the first 0.8 seconds - [self waitForExpectations: @[second] timeout:0.5]; - - XCTestExpectation* waitmore = [self expectationWithDescription:@"waiting"]; - waitmore.inverted = YES; - [self waitForExpectations: @[waitmore] timeout: 0.2]; -} - -- (void)testCancel { - XCTestExpectation *cancelexpectation = [self expectationWithDescription:@"FutureScheduler fired (after cancel)"]; - cancelexpectation.inverted = YES; - - CKKSNearFutureScheduler* scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" delay: 100*NSEC_PER_MSEC keepProcessAlive:true block:^{ - [cancelexpectation fulfill]; - }]; - - [scheduler trigger]; - [scheduler cancel]; - - // Make sure it does not fire in 0.5 s - [self waitForExpectations: @[cancelexpectation] timeout:0.2]; -} - -- (void)testDelayedNoShot { - XCTestExpectation *toofastexpectation = [self expectationWithDescription:@"FutureScheduler fired (too soon)"]; - toofastexpectation.inverted = YES; - - CKKSNearFutureScheduler* scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" delay: 10*NSEC_PER_MSEC keepProcessAlive:false block:^{ - [toofastexpectation fulfill]; - }]; - - // Tell the scheduler to wait, but don't trigger it. It shouldn't fire. - [scheduler waitUntil: 50*NSEC_PER_MSEC]; - - [self waitForExpectations: @[toofastexpectation] timeout:0.1]; -} - -- (void)testDelayedOneShot { - XCTestExpectation *first = [self expectationWithDescription:@"FutureScheduler fired (one)"]; - first.assertForOverFulfill = NO; - - XCTestExpectation *toofastexpectation = [self expectationWithDescription:@"FutureScheduler fired (too soon)"]; - toofastexpectation.inverted = YES; - - CKKSNearFutureScheduler* scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" delay: 10*NSEC_PER_MSEC keepProcessAlive:false block:^{ - [first fulfill]; - [toofastexpectation fulfill]; - }]; - - [scheduler waitUntil: 150*NSEC_PER_MSEC]; - [scheduler trigger]; - - [self waitForExpectations: @[toofastexpectation] timeout:0.1]; - [self waitForExpectations: @[first] timeout:0.2]; -} - -- (void)testDelayedMultiShot { - XCTestExpectation *first = [self expectationWithDescription:@"FutureScheduler fired (one)"]; - first.assertForOverFulfill = NO; - - XCTestExpectation *toofastexpectation = [self expectationWithDescription:@"FutureScheduler fired (too soon)"]; - toofastexpectation.expectedFulfillmentCount = 2; - toofastexpectation.inverted = YES; - - XCTestExpectation *second = [self expectationWithDescription:@"FutureScheduler fired (two)"]; - second.expectedFulfillmentCount = 2; - second.assertForOverFulfill = YES; - - CKKSNearFutureScheduler* scheduler = [[CKKSNearFutureScheduler alloc] initWithName: @"test" delay: 10*NSEC_PER_MSEC keepProcessAlive:false block:^{ - [first fulfill]; - [second fulfill]; - [toofastexpectation fulfill]; - }]; - - [scheduler trigger]; - [self waitForExpectations: @[first] timeout:0.2]; - - [scheduler waitUntil: 150*NSEC_PER_MSEC]; - [scheduler trigger]; - - [self waitForExpectations: @[toofastexpectation] timeout:0.1]; - [self waitForExpectations: @[second] timeout:0.3]; -} - -@end diff --git a/keychain/ckks/tests/CKKSFetchTests.m b/keychain/ckks/tests/CKKSFetchTests.m index 433a2b20..f1f97783 100644 --- a/keychain/ckks/tests/CKKSFetchTests.m +++ b/keychain/ckks/tests/CKKSFetchTests.m @@ -53,9 +53,7 @@ } } runBeforeFinished:^{}]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -122,9 +120,7 @@ } } runBeforeFinished:^{}]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -177,9 +173,7 @@ } } runBeforeFinished:^{}]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -225,7 +219,7 @@ }]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; // Wait for both fetches.... OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -277,7 +271,7 @@ [self expectCKFetch]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; @@ -287,7 +281,7 @@ // Now, edit the on-disk CKSE [self.keychainView halt]; - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; @@ -297,7 +291,7 @@ ckse.moreRecordsInCloudKit = YES; [ckse saveToDatabase: &error]; XCTAssertNil(error, "no error saving to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // CKKS should, upon restart, kick off a fetch starting from the previous checkpoint diff --git a/keychain/ckks/tests/CKKSLoggerTests.m b/keychain/ckks/tests/CKKSLoggerTests.m index 692f1a05..0c60d25e 100644 --- a/keychain/ckks/tests/CKKSLoggerTests.m +++ b/keychain/ckks/tests/CKKSLoggerTests.m @@ -179,7 +179,14 @@ static void _XCTAssertTimeDiffWithInterval(CKKSAnalyticsTests* self, const char* va_end(args); arg = [[NSString alloc] initWithFormat: format arguments: args]; } - [self recordFailureWithDescription: [comparison stringByAppendingString: arg] inFile: [NSString stringWithUTF8String: filename] atLine: line expected: YES]; + + XCTIssue* issue = [[XCTIssue alloc] initWithType:XCTIssueTypeAssertionFailure + compactDescription:[comparison stringByAppendingString: arg] + detailedDescription:nil + sourceCodeContext:[[XCTSourceCodeContext alloc] init] + associatedError:nil + attachments:@[]]; + [self recordIssue:issue]; } } @@ -190,24 +197,25 @@ static void _XCTAssertTimeDiffWithInterval(CKKSAnalyticsTests* self, const char* CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone: ckr]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - - [[[self.keychainView waitForFetchAndIncomingQueueProcessing] completionHandlerDidRunCondition] wait:4 * NSEC_PER_SEC]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + + [[self.injectedManager.zoneChangeFetcher inflightFetch] waitUntilFinished]; + CKKSResultOperation* op = [self.keychainView processIncomingQueue:false]; + [[op completionHandlerDidRunCondition] wait:4 * NSEC_PER_SEC]; NSDate* nowDate = [NSDate date]; /* * Check last sync date for class A */ - NSDate* syncADate = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassA inView:self.keychainView]; + NSDate* syncADate = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassA zoneName:self.keychainView.zoneName]; XCTAssertNotNil(syncADate, "Failed to get a last successful A sync date"); XCTAssertTimeDiffWithInterval(syncADate, nowDate, 15, "Last sync A date should be recent"); /* * Check last sync date for class C */ - NSDate *syncCDate = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC inView:self.keychainView]; + NSDate *syncCDate = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC zoneName:self.keychainView.zoneName]; XCTAssertNotNil(syncCDate, "Failed to get a last successful C sync date"); XCTAssertTimeDiffWithInterval(syncCDate, nowDate, 15, "Last sync C date should be recent"); @@ -246,7 +254,7 @@ static void _XCTAssertTimeDiffWithInterval(CKKSAnalyticsTests* self, const char* for (NSInteger i = 0; i < 5; i++) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ CKKSAnalytics* logger = [CKKSAnalytics logger]; - [logger logSuccessForEvent:(CKKSAnalyticsFailableEvent*)@"test_event" inView:self.keychainView]; + [logger logSuccessForEvent:(CKKSAnalyticsFailableEvent*)@"test_event" zoneName:self.keychainView.zoneName]; dispatch_semaphore_signal(semaphore); }); } diff --git a/keychain/ckks/tests/CKKSManifestTests.m b/keychain/ckks/tests/CKKSManifestTests.m index fbd7f991..064e99cc 100644 --- a/keychain/ckks/tests/CKKSManifestTests.m +++ b/keychain/ckks/tests/CKKSManifestTests.m @@ -53,7 +53,7 @@ NSMutableArray* items = [[NSMutableArray alloc] init]; __weak __typeof(self) weakSelf = self; __block NSError* error = nil; - [self.keychainView dispatchSync:^bool(void) { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for (CKRecord* record in records) { CKKSMirrorEntry* mirrorEntry = [CKKSMirrorEntry tryFromDatabase:record.recordID.recordName zoneID:weakSelf.keychainZoneID error:&error]; XCTAssertNil(error, @"error encountered trying to generate CKKSMirrorEntry: %@", error); @@ -63,7 +63,7 @@ } } - return YES; + return CKKSDatabaseTransactionCommit; }]; return items; @@ -82,11 +82,11 @@ SFECKeyPair* keyPair = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]]; [CKKSManifestInjectionPointHelper registerEgoPeerID:@"MeMyselfAndI" keyPair:keyPair]; - // Always sync manifests, and never enforce them - SecCKKSSetSyncManifests(true); + // We've now disabled manifests. + SecCKKSSetSyncManifests(false); SecCKKSSetEnforceManifests(false); - XCTAssertTrue([CKKSManifest shouldSyncManifests], "Manifests syncing is enabled"); + XCTAssertFalse([CKKSManifest shouldSyncManifests], "Manifests syncing is disabled"); XCTAssertFalse([CKKSManifest shouldEnforceManifests], "Manifests enforcement is disabled"); NSError* error = nil; @@ -280,9 +280,7 @@ [self.keychainZone addToZone:record]; } - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; return query; @@ -329,12 +327,15 @@ - (void)testSaveManifestWithNilValues { - SFECKeyPair* keyPair = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]]; - CKKSManifest* manifest = [CKKSEgoManifest newFakeManifestForZone:@"SomeZone" withItemRecords:@[] currentItems:@{} signerID:@"BadBoy" keyPair:keyPair error:nil]; - [manifest nilAllIvars]; - XCTAssertNil(manifest.zoneID); - XCTAssertNil(manifest.signerID); - XCTAssertNoThrow([manifest saveToDatabase:nil]); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + SFECKeyPair* keyPair = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]]; + CKKSManifest* manifest = [CKKSEgoManifest newFakeManifestForZone:@"SomeZone" withItemRecords:@[] currentItems:@{} signerID:@"BadBoy" keyPair:keyPair error:nil]; + [manifest nilAllIvars]; + XCTAssertNil(manifest.zoneID); + XCTAssertNil(manifest.signerID); + XCTAssertNoThrow([manifest saveToDatabase:nil]); + return CKKSDatabaseTransactionRollback; + }]; } @end diff --git a/keychain/ckks/tests/CKKSMockLockStateProvider.h b/keychain/ckks/tests/CKKSMockLockStateProvider.h new file mode 100644 index 00000000..0549b6c8 --- /dev/null +++ b/keychain/ckks/tests/CKKSMockLockStateProvider.h @@ -0,0 +1,18 @@ + +#ifndef CKKSMockLockStateProvider_h +#define CKKSMockLockStateProvider_h + +#if OCTAGON + +#import +#import "keychain/ckks/CKKSLockStateTracker.h" + +@interface CKKSMockLockStateProvider : NSObject +@property BOOL aksCurrentlyLocked; + +- (instancetype)initWithCurrentLockStatus:(BOOL)currentlyLocked; +@end + +#endif + +#endif /* CKKSMockLockStateProvider_h */ diff --git a/keychain/ckks/tests/CKKSMockLockStateProvider.m b/keychain/ckks/tests/CKKSMockLockStateProvider.m new file mode 100644 index 00000000..25c096f9 --- /dev/null +++ b/keychain/ckks/tests/CKKSMockLockStateProvider.m @@ -0,0 +1,39 @@ +#if OCTAGON + +#import +#import "keychain/ckks/tests/CKKSMockLockStateProvider.h" +#import "tests/secdmockaks/mockaks.h" + +@implementation CKKSMockLockStateProvider +@synthesize aksCurrentlyLocked = _aksCurrentlyLocked; + +- (instancetype)initWithCurrentLockStatus:(BOOL)currentlyLocked +{ + if((self = [super init])) { + _aksCurrentlyLocked = currentlyLocked; + } + return self; +} + +- (BOOL)queryAKSLocked { + return self.aksCurrentlyLocked; +} + +- (BOOL)aksCurrentlyLocked { + return _aksCurrentlyLocked; +} + +- (void)setAksCurrentlyLocked:(BOOL)aksCurrentlyLocked +{ + if(aksCurrentlyLocked) { + [SecMockAKS lockClassA]; + } else { + [SecMockAKS unlockAllClasses]; + } + + _aksCurrentlyLocked = aksCurrentlyLocked; +} + +@end + +#endif diff --git a/keychain/ckks/tests/CKKSMockSOSPresentAdapter.h b/keychain/ckks/tests/CKKSMockSOSPresentAdapter.h index 7fcff165..66d11d89 100644 --- a/keychain/ckks/tests/CKKSMockSOSPresentAdapter.h +++ b/keychain/ckks/tests/CKKSMockSOSPresentAdapter.h @@ -13,12 +13,21 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable) NSError* selfPeerError; @property (nullable) NSError* trustedPeersError; +@property BOOL aksLocked; + @property bool excludeSelfPeerFromTrustSet; @property SOSCCStatus circleStatus; +@property (nullable) NSError* circleStatusError; + @property CKKSSOSSelfPeer* selfPeer; @property NSMutableSet>* trustedPeers; +@property BOOL safariViewEnabled; + +@property BOOL ckks4AllStatus; +@property BOOL ckks4AllStatusIsSet; + @property (nullable) void (^updateOctagonKeySetListener)(id); - (instancetype)initWithSelfPeer:(CKKSSOSSelfPeer*)selfPeer diff --git a/keychain/ckks/tests/CKKSMockSOSPresentAdapter.m b/keychain/ckks/tests/CKKSMockSOSPresentAdapter.m index ec18e233..d1696e64 100644 --- a/keychain/ckks/tests/CKKSMockSOSPresentAdapter.m +++ b/keychain/ckks/tests/CKKSMockSOSPresentAdapter.m @@ -18,11 +18,15 @@ _essential = essential; _circleStatus = kSOSCCInCircle; + _safariViewEnabled = YES; _excludeSelfPeerFromTrustSet = false; _peerChangeListeners = [[CKKSListenerCollection alloc] initWithName:@"ckks-mock-sos"]; + _ckks4AllStatus = NO; + _ckks4AllStatusIsSet = NO; + _selfPeer = selfPeer; _trustedPeers = [trustedPeers mutableCopy]; } @@ -38,7 +42,8 @@ { if(!self.sosEnabled || self.circleStatus == kSOSCCError) { if(error && self.circleStatus == kSOSCCError) { - *error = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:self.circleStatus userInfo:nil]; + // I'm not at all sure that the second error here actually is any error in particular + *error = self.circleStatusError ?: [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:self.circleStatus userInfo:nil]; } return kSOSCCError; } @@ -57,6 +62,13 @@ return nil; } + if(self.aksLocked) { + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecInteractionNotAllowed userInfo:nil]; + } + return nil; + } + if(self.sosEnabled && self.circleStatus == kSOSCCInCircle) { return self.selfPeer; } else { @@ -80,7 +92,7 @@ - (NSSet> * _Nullable)fetchTrustedPeers:(NSError * _Nullable __autoreleasing * _Nullable)error { if(self.trustedPeersError) { - if(*error) { + if(error) { *error = self.trustedPeersError; } return nil; @@ -101,11 +113,18 @@ } } -- (void)updateOctagonKeySetWithAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { +- (BOOL)updateOctagonKeySetWithAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { if(self.updateOctagonKeySetListener) { self.updateOctagonKeySetListener(currentSelfPeer); } - return; + return YES; +} + +- (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error +{ + self.ckks4AllStatus = status; + self.ckks4AllStatusIsSet = YES; + return YES; } - (void)registerForPeerChangeUpdates:(nonnull id)listener { @@ -139,4 +158,15 @@ return [self.trustedPeers setByAddingObject: s]; } +- (BOOL)safariViewSyncingEnabled:(NSError**)error +{ + // TODO: what happens if you call this when not in circle? + return self.safariViewEnabled; +} + +- (BOOL)preloadOctagonKeySetOnAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { + // No-op + return YES; +} + @end diff --git a/keychain/ckks/tests/CKKSOperationTests.m b/keychain/ckks/tests/CKKSOperationTests.m index 913a7901..b3c6e30d 100644 --- a/keychain/ckks/tests/CKKSOperationTests.m +++ b/keychain/ckks/tests/CKKSOperationTests.m @@ -616,6 +616,38 @@ XCTAssertFalse([group isPending], "group operation isn't pending, as it's cancelled"); } +- (void)testResultOperationDeepDependencyChain { + NSMutableArray* ops = [NSMutableArray array]; + + CKKSResultOperation* op = nil; + + for(int i = 0; i < 100; i++) { + op = [CKKSResultOperation named:[NSString stringWithFormat:@"operation-%d", i] withBlock:^{}]; + [op addNullableDependency:[ops lastObject]]; + + [ops addObject:op]; + } + + NSString* description = [op description]; + XCTAssertNotNil(description, "Should have received some description for the operation"); +} + +- (void)testGroupOperationDeepDependencyChain { + NSMutableArray* ops = [NSMutableArray array]; + + CKKSGroupOperation* op = nil; + + for(int i = 0; i < 100; i++) { + op = [CKKSGroupOperation named:[NSString stringWithFormat:@"operation-%d", i] withBlock:^{}]; + [op addNullableDependency:[ops lastObject]]; + + [ops addObject:op]; + } + + NSString* description = [op description]; + XCTAssertNotNil(description, "Should have received some description for the operation"); +} + @end diff --git a/keychain/ckks/tests/CKKSSOSTests.m b/keychain/ckks/tests/CKKSSOSTests.m index 7ac4dbac..c773c09f 100644 --- a/keychain/ckks/tests/CKKSSOSTests.m +++ b/keychain/ckks/tests/CKKSSOSTests.m @@ -70,6 +70,8 @@ [self saveFakeKeyHierarchyToLocalDatabase:self.manateeZoneID]; [self saveTLKMaterialToKeychain:self.manateeZoneID]; + [self startCKKSSubsystem]; + NSDictionary* piggyTLKs = [self SOSPiggyBackCopyFromKeychain]; [self deleteTLKMaterialFromKeychain:self.manateeZoneID]; @@ -86,6 +88,8 @@ [self putFakeDeviceStatusesInCloudKit]; [self saveTLKsToKeychain]; + [self startCKKSSubsystem]; + NSDictionary* piggyTLKs = [self SOSPiggyBackCopyFromKeychain]; [self deleteTLKMaterialsFromKeychain]; @@ -112,17 +116,6 @@ XCTAssertNil(error, "No error loading Home tlk from piggy contents"); } --(NSString*)fileForStorage -{ - static dispatch_once_t onceToken; - static NSString *tempPath = NULL; - dispatch_once(&onceToken, ^{ - tempPath = [[[[NSFileManager defaultManager] temporaryDirectory] URLByAppendingPathComponent:@"PiggyPacket"] path]; - - }); - return tempPath; -} - -(void)testPiggybackingData{ [self putFakeKeyHierachiesInCloudKit]; [self saveTLKsToKeychain]; @@ -154,8 +147,6 @@ NSData *initial = SOSPiggyCreateInitialSyncData(icloudidentities, tlks); XCTAssertNotNil(initial, "Initial not set"); - BOOL writeStatus = [initial writeToFile:[self fileForStorage] options:NSDataWritingAtomic error: nil]; - XCTAssertTrue(writeStatus, "had trouble writing to disk"); XCTAssertNotEqual((int)[initial length], 0, "initial sync data is greater than 0"); /* @@ -176,6 +167,44 @@ XCTAssertEqual([copiediCloudidentities count], [icloudidentities count], "ident count not same"); } + +- (void)testPiggybackingTLKRequest { + [self putFakeKeyHierachiesInCloudKit]; + [self saveTLKsToKeychain]; + + for(CKRecordZoneID* zoneID in self.ckksZones) { + [self expectCKKSTLKSelfShareUpload:zoneID]; + } + [self startCKKSSubsystem]; + [self waitForKeyHierarchyReadinesses]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // The "tlk request" piggybacking session calls SOSAccountCopyInitialSyncData + __block CFErrorRef cferror = NULL; + NSData* piggybackingData = (NSData*) CFBridgingRelease(SOSAccountCopyInitialSyncData(nil, kSOSInitialSyncFlagTLKsRequestOnly, &cferror)); + + XCTAssertEqual(cferror, NULL, "Should have no error fetching only the TLKs"); + XCTAssertNotNil(piggybackingData, "Should have received some sync data"); + + const uint8_t* der = [piggybackingData bytes]; + const uint8_t *der_end = der + [piggybackingData length]; + + NSDictionary *result = SOSPiggyCopyInitialSyncData(&der, der_end); + XCTAssertNotNil(result, "Should be able to parse the piggybacking data"); + + NSArray *copiedTLKs = result[@"tlks"]; + XCTAssertNotNil(copiedTLKs, "should have some tlks"); + XCTAssertEqual([copiedTLKs count], 1u, "piggybacking should have gotten 1 TLK"); + XCTAssertEqualObjects(copiedTLKs[0][@"srvr"], @"Passwords", "should have the passwords TLK only"); + NSData* keyData = copiedTLKs[0][@"v_Data"]; + XCTAssertNotNil(keyData, "Should have some key material"); + XCTAssertEqual([keyData length], 64, "Key material should be 64 bytes"); + + NSArray *copiediCloudidentities = result[@"idents"]; + XCTAssertNotNil(copiediCloudidentities, "idents not set"); + XCTAssertEqual([copiediCloudidentities count], 0, "Should have no icloud identities"); +} + -(void)testVerifyTLKSorting { char key[32*2] = {0}; NSArray *tlks = @[ @@ -250,7 +279,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.manateeView dispatchSync: ^bool{ + [self.manateeView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -280,8 +309,6 @@ XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef)query, &result), "Found a syncable TLK"); XCTAssertNotNil((__bridge id) result, "Received a result from SecItemCopyMatching"); CFReleaseNull(result); - - return false; }]; } diff --git a/keychain/ckks/tests/CKKSSQLTests.m b/keychain/ckks/tests/CKKSSQLTests.m index 8bd89e46..4361b474 100644 --- a/keychain/ckks/tests/CKKSSQLTests.m +++ b/keychain/ckks/tests/CKKSSQLTests.m @@ -30,7 +30,9 @@ #import "keychain/ckks/CKKS.h" #import "keychain/ckks/CKKSKey.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" #import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" #import "keychain/ckks/CKKSZoneStateEntry.h" #import "keychain/ckks/CKKSDeviceStateEntry.h" #import "keychain/ckks/CKKSRateLimiter.h" @@ -97,11 +99,14 @@ waitUntil:nil accessGroup:@"nope"]; - NSError* error = nil; - [one saveToDatabase:&error]; - [two saveToDatabase: &error]; - [three saveToDatabase: &error]; - XCTAssertNil(error, "no error saving ZoneStateEntries to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* error = nil; + [one saveToDatabase:&error]; + [two saveToDatabase: &error]; + [three saveToDatabase: &error]; + XCTAssertNil(error, "no error saving ZoneStateEntries to database"); + return CKKSDatabaseTransactionCommit; + }]; } - (void)testCKKSOutgoingQueueEntry { @@ -160,8 +165,12 @@ state:SecCKKSStateError waitUntil:[NSDate date] accessGroup:@"nope"]; - [other saveToDatabase:&nserror]; - XCTAssertNil(nserror, "no error occurred saving to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [other saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving to database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSOutgoingQueueEntry * oqe = [CKKSOutgoingQueueEntry fromDatabase:testUUID state:@"unprocessed" zoneID:self.testZoneID error: &nserror]; XCTAssertNil(nserror, "no error occurred creating from database"); @@ -177,7 +186,12 @@ oqe.item.base64encitem = @"bW9yZW5vbnNlbnNlCg=="; oqe.item.encver = 1; - XCTAssertTrue([oqe saveToDatabase: &nserror], "saving to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [oqe saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving to database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSOutgoingQueueEntry * oqe2 = [CKKSOutgoingQueueEntry fromDatabase:testUUID state:@"savedtocloud" zoneID:self.testZoneID error: &nserror]; XCTAssertNil(nserror, "no error occurred"); @@ -207,8 +221,15 @@ // Test row deletion nserror = nil; - [oqe2 deleteFromDatabase:&nserror]; - XCTAssertNil(nserror, "No NSError exists when deleting existing item"); + + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* deleteError = nil; + [oqe2 deleteFromDatabase:&deleteError]; + XCTAssertNil(deleteError, "no error occurred deleting existing item"); + return CKKSDatabaseTransactionCommit; + }]; + oqe2 = [CKKSOutgoingQueueEntry fromDatabase:testUUID state:@"savedtocloud" zoneID:self.testZoneID error: &nserror]; XCTAssertNil(oqe2, "Can't find a nonexisting object"); XCTAssertNotNil(nserror, "NSError exists when things break"); @@ -221,6 +242,47 @@ XCTAssertEqualObjects(other, other2, "loaded object is equal to object"); } +- (void)testOverwriteCKKSIncomingQueueEntry { + NSError* error = nil; + + CKKSItem* baseitem = [[CKKSItem alloc] initWithUUID: [[NSUUID UUID] UUIDString] + parentKeyUUID:[[NSUUID UUID] UUIDString] + zoneID:self.testZoneID + encItem:[@"nonsense" dataUsingEncoding:NSUTF8StringEncoding] + wrappedkey:[[CKKSWrappedAESSIVKey alloc]initWithBase64: @"KFfL58XtugiYNoD859EjG0StfrYd6eakm0CQrgX7iO+DEo4kio3WbEeA1kctCU0GaeTGsRFpbdy4oo6jXhVu7cZqB0svhUPGq55aGnszUjI="] + generationCount:0 + encver:0]; + CKKSIncomingQueueEntry* delete = [[CKKSIncomingQueueEntry alloc] initWithCKKSItem:baseitem + action:SecCKKSActionDelete + state:SecCKKSStateNew]; + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [delete saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving delete IQE to database"); + return CKKSDatabaseTransactionCommit; + }]; + + NSArray* entries = [CKKSIncomingQueueEntry all:&error]; + XCTAssertNil(error, "Should be no error fetching alll IQEs"); + XCTAssertEqual(entries.count, 1u, "Should be one entry"); + XCTAssertEqualObjects(entries[0].action, SecCKKSActionDelete, "Should have delete as an action"); + + CKKSIncomingQueueEntry* add = [[CKKSIncomingQueueEntry alloc] initWithCKKSItem:baseitem + action:SecCKKSActionAdd + state:SecCKKSStateNew]; + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [add saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving add IQE to database"); + return CKKSDatabaseTransactionCommit; + }]; + + entries = [CKKSIncomingQueueEntry all:&error]; + XCTAssertNil(error, "Should be no error fetching alll IQEs"); + XCTAssertEqual(entries.count, 1u, "Should be one entry"); + XCTAssertEqualObjects(entries[0].action, SecCKKSActionAdd, "Should have add as an action"); +} + -(void)testCKKSZoneStateEntrySQL { CKKSZoneStateEntry* zse = [[CKKSZoneStateEntry alloc] initWithCKZone:@"sqltest" zoneCreated:true @@ -228,6 +290,7 @@ changeToken:[@"nonsense" dataUsingEncoding:NSUTF8StringEncoding] moreRecordsInCloudKit:YES lastFetch:[NSDate date] + lastScan:[NSDate date] lastFixup:CKKSCurrentFixupNumber encodedRateLimiter:nil]; zse.rateLimiter = [[CKKSRateLimiter alloc] init]; @@ -238,6 +301,7 @@ changeToken:[@"nonsense" dataUsingEncoding:NSUTF8StringEncoding] moreRecordsInCloudKit:YES lastFetch:zse.lastFetchTime + lastScan:zse.lastLocalKeychainScanTime lastFixup:CKKSCurrentFixupNumber encodedRateLimiter:zse.encodedRateLimiter]; @@ -247,6 +311,7 @@ changeToken:[@"allnonsense" dataUsingEncoding:NSUTF8StringEncoding] moreRecordsInCloudKit:NO lastFetch:zse.lastFetchTime + lastScan:zse.lastLocalKeychainScanTime lastFixup:CKKSCurrentFixupNumber encodedRateLimiter:zse.encodedRateLimiter]; XCTAssertEqualObjects(zse, zseClone, "CKKSZoneStateEntry isEqual of equal objects seems sane"); @@ -257,8 +322,12 @@ XCTAssertNil(error, "No error trying to load nonexistent record"); XCTAssertNil(loaded, "No record saved in database"); - [zse saveToDatabase: &error]; - XCTAssertNil(error, "no error saving CKKSZoneStateEntry to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [zse saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving CKKSZoneStateEntry to database"); + return CKKSDatabaseTransactionCommit; + }]; loaded = [CKKSZoneStateEntry tryFromDatabase: @"sqltest" error:&error]; XCTAssertNil(error, "No error trying to load saved record"); @@ -269,8 +338,17 @@ XCTAssertEqual (zse.ckzonesubscribed, loaded.ckzonesubscribed, "ckzonesubscribed persisted through db save and load"); XCTAssertEqualObjects(zse.encodedChangeToken, loaded.encodedChangeToken, "encodedChangeToken persisted through db save and load"); - XCTAssert([[NSCalendar currentCalendar] isDate:zse.lastFetchTime equalToDate: loaded.lastFetchTime toUnitGranularity:NSCalendarUnitSecond], + secnotice("ckkstests", "zse.lastFetchTime: %@", zse.lastFetchTime); + secnotice("ckkstests", "loaded.lastFetchTime: %@", loaded.lastFetchTime); + + secnotice("ckkstests", "equal?: %d", [zse.lastFetchTime isEqualToDate:loaded.lastFetchTime]); + secnotice("ckkstests", "equal to seconds?: %d", [[NSCalendar currentCalendar] isDate:zse.lastFetchTime equalToDate: loaded.lastFetchTime toUnitGranularity:NSCalendarUnitSecond]); + + // We only compare to the minute level, as that's enough to test the save+load. + XCTAssert([[NSCalendar currentCalendar] isDate:zse.lastFetchTime equalToDate: loaded.lastFetchTime toUnitGranularity:NSCalendarUnitMinute], "lastFetchTime persisted through db save and load"); + XCTAssert([[NSCalendar currentCalendar] isDate:zse.lastLocalKeychainScanTime equalToDate:loaded.lastLocalKeychainScanTime toUnitGranularity:NSCalendarUnitMinute], + "lastLocalKeychainScanTime persisted through db save and load"); } -(void)testRoundtripCKKSDeviceStateEntry { @@ -290,9 +368,12 @@ zoneID:self.testZoneID encodedCKRecord:nil]; XCTAssertNotNil(cdse, "Constructor works"); - NSError* saveError = nil; - [cdse saveToDatabase:&saveError]; - XCTAssertNil(saveError, "No error saving cdse to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [cdse saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving cdse to database"); + return CKKSDatabaseTransactionCommit; + }]; NSError* loadError = nil; CKKSDeviceStateEntry* loadedCDSE = [CKKSDeviceStateEntry fromDatabase:testUUID zoneID:self.testZoneID error:&loadError]; @@ -369,8 +450,12 @@ currentkey:true]; XCTAssertNotNil(key, "could create key"); - [key saveToDatabase: &error]; - XCTAssertNil(error, "could save key to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [key saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving key to database"); + return CKKSDatabaseTransactionCommit; + }]; error = nil; CKKSKey* key2 = [CKKSKey fromDatabase:testUUID zoneID:self.testZoneID error:&error]; @@ -397,8 +482,13 @@ zoneID:self.testZoneID encodedCKRecord: testCKRecord currentkey: true]; - XCTAssertTrue([tlk saveToDatabase: &error], "TLK saved to database"); - XCTAssertNil(error, "no error saving TLK to database"); + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [tlk saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving TLK to database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSKey* wrappedKey = [[CKKSKey alloc] initWrappedBy: tlk AESKey:[CKKSAESSIVKey randomKey:&error] @@ -408,26 +498,60 @@ zoneID:self.testZoneID encodedCKRecord:testCKRecord currentkey:true]; - XCTAssertTrue([wrappedKey saveToDatabase: &error], "key saved to database"); - XCTAssertNil(error, "no error saving key to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [wrappedKey saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving key to database"); + return CKKSDatabaseTransactionCommit; + }]; + + NSString* secondUUID = @"8b2aeb7f-0000-0000-0000-70d5c728ebf7"; + CKKSKey* secondtlk = [[CKKSKey alloc] initSelfWrappedWithAESKey:[[CKKSAESSIVKey alloc] initWithBase64: @"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="] + uuid:secondUUID + keyclass:SecCKKSKeyClassTLK + state:SecCKKSProcessedStateLocal + zoneID:self.testZoneID + encodedCKRecord:testCKRecord + currentkey:true]; + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + XCTAssertTrue([secondtlk saveToDatabase:&saveError], "Second TLK saved to database"); + XCTAssertNil(saveError, "no error occurred saving second TLK to database"); + return CKKSDatabaseTransactionCommit; + }]; NSArray* tlks = [CKKSKey allWhere: @{@"UUID": @"8b2aeb7f-4af3-43e9-b6e6-70d5c728ebf7"} error: &error]; XCTAssertNotNil(tlks, "Returned some array from allWhere"); XCTAssertNil(error, "no error back from allWhere"); XCTAssertEqual([tlks count], 1ul, "Received one row (and expected one row)"); - NSArray* selfWrapped = [CKKSKey allWhere: @{@"parentKeyUUID": [CKKSSQLWhereObject op:@"=" string:@"uuid"]} error: &error]; + NSArray* selfWrapped = [CKKSKey allWhere: @{@"parentKeyUUID": [CKKSSQLWhereColumn op:CKKSSQLWhereComparatorEquals column:CKKSSQLWhereColumnNameUUID]} error: &error]; XCTAssertNotNil(selfWrapped, "Returned some array from allWhere"); XCTAssertNil(error, "no error back from allWhere"); - XCTAssertEqual([selfWrapped count], 1ul, "Received one row (and expected one row)"); + XCTAssertEqual([selfWrapped count], 2ul, "Should have recievied two rows"); - // Try using CKKSSQLWhereObject alongside normal binds - NSArray* selfWrapped2 = [CKKSKey allWhere: @{@"parentKeyUUID": [CKKSSQLWhereObject op:@"=" string:@"uuid"], + // Try using CKKSSQLWhereColumn alongside normal binds + NSArray* selfWrapped2 = [CKKSKey allWhere: @{@"parentKeyUUID": [CKKSSQLWhereColumn op:CKKSSQLWhereComparatorEquals column:CKKSSQLWhereColumnNameUUID], @"uuid": @"8b2aeb7f-4af3-43e9-b6e6-70d5c728ebf7"} error: &error]; XCTAssertNotNil(selfWrapped2, "Returned some array from allWhere"); XCTAssertNil(error, "no error back from allWhere"); XCTAssertEqual([selfWrapped2 count], 1ul, "Received one row (and expected one row)"); + XCTAssertEqualObjects([selfWrapped2[0] uuid], @"8b2aeb7f-4af3-43e9-b6e6-70d5c728ebf7", "Should received first TLK UUID"); + + NSArray* selfWrapped3 = [CKKSKey allWhere: @{@"parentKeyUUID": [CKKSSQLWhereColumn op:CKKSSQLWhereComparatorEquals column:CKKSSQLWhereColumnNameUUID], + @"uuid": [CKKSSQLWhereValue op:CKKSSQLWhereComparatorNotEquals value:@"8b2aeb7f-4af3-43e9-b6e6-70d5c728ebf7"]} + error: &error]; + XCTAssertNotNil(selfWrapped3, "Returned some array from allWhere"); + XCTAssertNil(error, "no error back from allWhere"); + XCTAssertEqual([selfWrapped3 count], 1ul, "Should have received one rows"); + XCTAssertEqualObjects([selfWrapped3[0] uuid], secondUUID, "Should received second TLK UUID"); + + NSArray* whereFound = [CKKSKey allWhere: @{@"uuid": [[CKKSSQLWhereIn alloc] initWithValues:@[tlk.uuid, wrappedKey.uuid, @"not-found"]]} error:&error]; + XCTAssertNil(error, "no error back from search"); + XCTAssertEqual([whereFound count], 2ul, "Should have received two rows"); + XCTAssertEqualObjects([whereFound[1] uuid], tlk.uuid, "Should received TLK UUID"); + XCTAssertEqualObjects([whereFound[0] uuid], wrappedKey.uuid, "Should received wrapped key UUID"); } - (void)testGroupBy { @@ -507,7 +631,7 @@ while(count == 0 || uuid != nil) { uuid = nil; [CKKSSQLDatabaseObject queryDatabaseTable: [CKKSOutgoingQueueEntry sqlTable] - where: lastUUID ? @{@"UUID": [CKKSSQLWhereObject op:@">" stringValue:lastUUID]} : nil + where: lastUUID ? @{@"UUID": [CKKSSQLWhereValue op:CKKSSQLWhereComparatorGreaterThan value:lastUUID]} : nil columns: @[@"action", @"UUID"] groupBy:nil orderBy:@[@"uuid"] diff --git a/keychain/ckks/tests/CKKSServerValidationRecoveryTests.m b/keychain/ckks/tests/CKKSServerValidationRecoveryTests.m index acc1818d..2e800d88 100644 --- a/keychain/ckks/tests/CKKSServerValidationRecoveryTests.m +++ b/keychain/ckks/tests/CKKSServerValidationRecoveryTests.m @@ -143,11 +143,11 @@ self.keychainZone.currentDatabase[self.keychainZoneKeys.currentClassCPointer.storedCKRecord.recordID][SecCKRecordParentKeyRefKey] = oldClassCKey; self.keychainZoneKeys.currentClassCPointer.currentKeyUUID = oldClassCKey.recordID.recordName; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; // CKKS should then fix the pointers and give itself a new TLK share record, but not update any keys [self expectCKModifyKeyRecords:0 currentKeyPointerRecords:1 tlkShareRecords:1 zoneID:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // And then upload the item as usual @@ -210,7 +210,7 @@ [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; [self saveTLKMaterialToKeychain:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // And then use the 'new' key as it should diff --git a/keychain/ckks/tests/CKKSTLKSharingEncryptionTests.m b/keychain/ckks/tests/CKKSTLKSharingEncryptionTests.m index 67b08ac5..d22c68ae 100644 --- a/keychain/ckks/tests/CKKSTLKSharingEncryptionTests.m +++ b/keychain/ckks/tests/CKKSTLKSharingEncryptionTests.m @@ -27,6 +27,7 @@ #import "keychain/ckks/CKKS.h" #import "keychain/ckks/CKKSKey.h" #import "keychain/ckks/CKKSTLKShareRecord.h" +#import "keychain/ckks/CKKSSQLDatabaseObject.h" #import "keychain/ckks/CKKSPeer.h" #import "keychain/ckks/tests/CloudKitMockXCTest.h" @@ -58,13 +59,13 @@ viewList:self.managedViewList]; XCTAssertNotNil(self.localPeer, "Should be able to make a new local peer"); - self.remotePeer = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote" + self.remotePeer = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote1" encryptionKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] signingKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] viewList:self.managedViewList]; XCTAssertNotNil(self.remotePeer, "Should be able to make a new remote peer"); - self.remotePeer2 = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote" + self.remotePeer2 = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote2" encryptionKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] signingKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] viewList:self.managedViewList]; @@ -214,8 +215,12 @@ error:&error]; XCTAssertNil(error, "Should have been no error sharing a CKKSKey"); - [share saveToDatabase:&error]; - XCTAssertNil(error, "Shouldn't be an error saving a TLKShare record to the database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [share saveToDatabase:&saveError]; + XCTAssertNil(saveError, "Shouldn't be an error saving a TLKShare record to the database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSTLKShareRecord* loadedShare = [CKKSTLKShareRecord fromDatabase:self.tlk.uuid receiverPeerID:self.remotePeer.peerID @@ -237,6 +242,58 @@ XCTAssertEqualObjects(share, fromCKRecord, "TLK shares sent through CloudKit should be identical"); } +- (void)testKeyExtractFromTrustState { + NSError* error = nil; + CKKSTLKShareRecord* share = [CKKSTLKShareRecord share:self.tlk + as:self.remotePeer + to:self.localPeer + epoch:-1 + poisoned:0 + error:&error]; + XCTAssertNotNil(share, "Should have a TLKShare"); + XCTAssertNil(error, "Should have been no error sharing a CKKSKey from a remote peer to a local peer"); + + CKKSPeerProviderState* trustState = [[CKKSPeerProviderState alloc] initWithPeerProviderID:@"test-provider" + essential:YES + selfPeers:[[CKKSSelves alloc] initWithCurrent:self.localPeer allSelves:nil] + selfPeersError:nil + trustedPeers:[NSSet setWithArray:@[ + self.localPeer, + self.remotePeer, + self.remotePeer2, + ]] + trustedPeersError:nil]; + CKKSKey* shareExtraction = [share recoverTLK:self.localPeer + trustedPeers:trustState.currentTrustedPeers + error:&error]; + XCTAssertNotNil(shareExtraction, "Should be able to recover the share from the currently trusted peers"); + XCTAssertNil(error, "Should be no error extracting TLK"); + + BOOL extracted = [trustState unwrapKey:self.tlk + fromShares:@[share] + error:&error]; + + XCTAssertTrue(extracted, "Should be able to extract the TLK via a share"); + XCTAssertNil(error, "Should be no error extracting TLK"); + + CKKSPeerProviderState* remotePeer2TrustState = [[CKKSPeerProviderState alloc] initWithPeerProviderID:@"test-provider" + essential:YES + selfPeers:[[CKKSSelves alloc] initWithCurrent:self.remotePeer2 allSelves:nil] + selfPeersError:nil + trustedPeers:[NSSet setWithArray:@[ + self.localPeer, + self.remotePeer, + self.remotePeer2, + ]] + trustedPeersError:nil]; + + BOOL remotePeerExtracted = [remotePeer2TrustState unwrapKey:self.tlk + fromShares:@[share] + error:&error]; + XCTAssertFalse(remotePeerExtracted, "Should not be able to extract the TLK if there's no share to the self peer"); + XCTAssertNotNil(error, "Should be an error when failing to extract TLK"); +} + - (void)testKeyShareSignExtraFieldsInCKRecord { NSError* error = nil; CKKSTLKShareRecord* share = [CKKSTLKShareRecord share:self.tlk @@ -282,8 +339,13 @@ // And verify that saving to disk and reloading is successful share2.storedCKRecord = record; XCTAssert([share2 verifySignature:share2.signature verifyingPeer:self.localPeer error:&error], "Signature with extra data should verify"); - [share2 saveToDatabase:&error]; - XCTAssertNil(error, "No error saving share2 to database"); + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [share2 saveToDatabase:&saveError]; + XCTAssertNil(saveError, "No error saving share2 to database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSTLKShareRecord* loadedShare2 = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:record.recordID error:&error]; XCTAssertNil(error, "No error loading loadedShare2 from database"); diff --git a/keychain/ckks/tests/CKKSTLKSharingTests.m b/keychain/ckks/tests/CKKSTLKSharingTests.m index ece1aebd..d770ef68 100644 --- a/keychain/ckks/tests/CKKSTLKSharingTests.m +++ b/keychain/ckks/tests/CKKSTLKSharingTests.m @@ -134,7 +134,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -147,8 +147,6 @@ NSArray* currentkeys = [CKKSCurrentKeyPointer all:&error]; XCTAssertNil(error, "no error fetching current keys"); XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database"); - - return false; }]; } @@ -183,7 +181,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -196,8 +194,6 @@ NSArray* currentkeys = [CKKSCurrentKeyPointer all:&error]; XCTAssertNil(error, "no error fetching current keys"); XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database"); - - return false; }]; } @@ -250,7 +246,7 @@ // Verify that making a new share will have the old share's change tag __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSyncWithAccountKeys: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -272,8 +268,6 @@ XCTAssertNotNil(cloudKitRecord.recordChangeTag, "Existing record should have a change tag"); XCTAssertEqualObjects(cloudKitRecord.recordChangeTag, newRecord.recordChangeTag, "Change tags on existing and new records should match"); - - return false; }]; } @@ -308,31 +302,28 @@ CKRecord* shareCKRecord = [share CKRecordWithZoneID: self.keychainZoneID]; XCTAssertNotNil(shareCKRecord, "Should have been able to create a CKRecord"); [self.keychainZone addToZone:shareCKRecord]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* blockerror = nil; CKKSTLKShareRecord* localshare = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:shareCKRecord.recordID error:&blockerror]; XCTAssertNil(blockerror, "Shouldn't error finding TLKShare record in database"); XCTAssertNotNil(localshare, "Should be able to find a TLKShare record in database"); - return true; }]; // Delete the record in CloudKit... [self.keychainZone deleteCKRecordIDFromZone:shareCKRecord.recordID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Should be gone now. - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* blockerror = nil; CKKSTLKShareRecord* localshare = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:shareCKRecord.recordID error:&blockerror]; XCTAssertNil(blockerror, "Shouldn't error trying to find non-existent TLKShare record in database"); XCTAssertNil(localshare, "Shouldn't be able to find a TLKShare record in database"); - - return true; }]; } @@ -352,7 +343,7 @@ [self expectCKModifyKeyRecords:0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; [self putTLKSharesInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 zoneID:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); @@ -400,6 +391,35 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testEnterWaitForTLKJustAsTrustArrives { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + + // The TLKShares are in CK, no worries there... + [self putTLKSharesInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 zoneID:self.keychainZoneID]; + + // CKKS _should_ upload itself a share. + [self expectCKModifyKeyRecords:0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; + + // We start untrusted, but receive trust just as we fail to unwrap the TLK.... + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; + + [self startCKKSSubsystem]; + + [self.keychainView.stateMachine testPauseStateMachineAfterEntering:SecCKKSZoneKeyStateTLKMissing]; + + // The CKKS subsystem should not try to write anything to the CloudKit database, but it should enter waitfortlk + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateTLKMissing] wait:20*NSEC_PER_SEC], "Key state should become tlk_missing"); + + self.mockSOSAdapter.circleStatus = kSOSCCInCircle; + [self beginSOSTrustedViewOperation:self.keychainView]; + + [self.keychainView.stateMachine testReleaseStateMachinePause:SecCKKSZoneKeyStateTLKMissing]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); +} + - (void)testUploadTLKSharesForExistingHierarchy { // Test starts with key material locally and in CloudKit. [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; @@ -424,7 +444,7 @@ [self waitForCKModifications]; // Now, delete all the TLK Shares, so CKKS will upload them again - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; [CKKSTLKShareRecord deleteAll:self.keychainZoneID error:&error]; XCTAssertNil(error, "Shouldn't be an error deleting all TLKShares"); @@ -436,7 +456,7 @@ } } - return true; + return CKKSDatabaseTransactionCommit; }]; // Restart. We expect an upload of 3 TLK shares. @@ -467,7 +487,7 @@ [self expectCKModifyKeyRecords: 0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; // Trigger a notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -502,7 +522,7 @@ [self saveTLKMaterialToKeychain:self.keychainZoneID]; // Trigger a notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); @@ -572,7 +592,7 @@ // The CKKS subsystem should go into waitfortlk, since it doesn't trust this peer, but the peer is active [self startCKKSSubsystem]; - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "Key state should become ready"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "Key state should become waitfortlk"); } - (void)testAcceptSharedTLKOnTrustSetAdditionOfSharer { @@ -631,7 +651,7 @@ // step 2: add a new peer who already has a share; no share should be created [self putTLKShareInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 to:self.remotePeer2 zoneID:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // CKKS should not upload a tlk share for this peer @@ -796,7 +816,7 @@ }]; [self putTLKSharesInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 zoneID:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); @@ -1123,7 +1143,7 @@ NSMutableArray*>* keysetOps = [NSMutableArray array]; for(CKKSKeychainView* view in self.ckksViews) { XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:40*NSEC_PER_SEC], @"key state should enter 'waitfortlkcreation' (view %@)", view); - [keysetOps addObject: [view findKeySet]]; + [keysetOps addObject: [view findKeySet:NO]]; } // Now that we've kicked them all off, wait for them to not crash @@ -1246,7 +1266,9 @@ [self.keychainView endTrustedOperation]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], "Key state should become 'waitfortrust'"); - [self.keychainView beginTrustedOperation:@[self.mockSOSAdapter, brokenAdapter] suggestTLKUpload:self.suggestTLKUpload]; + [self.keychainView beginTrustedOperation:@[self.mockSOSAdapter, brokenAdapter] + suggestTLKUpload:self.suggestTLKUpload + requestPolicyCheck:self.requestPolicyCheck]; // CKKS should ignore the non-essential and broken peer adapter XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become 'ready'"); @@ -1269,13 +1291,31 @@ // Spin up Octagon. We expect an upload of 3 TLK shares, this time for the octagon peer [self expectCKModifyKeyRecords: 0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; - [self.keychainView beginTrustedOperation:@[self.mockSOSAdapter, self.mockOctagonAdapter] suggestTLKUpload:self.suggestTLKUpload]; + [self.keychainView beginTrustedOperation:@[self.mockSOSAdapter, self.mockOctagonAdapter] + suggestTLKUpload:self.suggestTLKUpload + requestPolicyCheck:self.requestPolicyCheck]; [self.mockOctagonAdapter sendTrustedPeerSetChangedUpdate]; OCMVerifyAllWithDelay(self.mockDatabase, 20); XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); } +- (void)testQuiesceOnTrustLossDuringInitialFetch { + // Test starts with no keys in CKKS database, but one in our fake CloudKit. + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putTLKSharesInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 zoneID:self.keychainZoneID]; + + [self holdCloudKitFetches]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateFetch] wait:20*NSEC_PER_SEC], "Key state should become 'fetch'"); + + [self endSOSTrustedOperationForAllViews]; + + [self releaseCloudKitFetchHold]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], "Key state should become 'waitfortrust'"); +} + @end #endif // OCTAGON diff --git a/keychain/ckks/tests/CKKSTests+API.m b/keychain/ckks/tests/CKKSTests+API.m index 0b8ad45e..b3f90822 100644 --- a/keychain/ckks/tests/CKKSTests+API.m +++ b/keychain/ckks/tests/CKKSTests+API.m @@ -69,6 +69,7 @@ (id)kSecAttrAccount : account, (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, (id)kSecValueData : data, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, (id)kSecAttrDeriveSyncIDFromItemAttributes : (id)kCFBooleanTrue, (id)kSecAttrPCSPlaintextServiceIdentifier : serviceIdentifier, (id)kSecAttrPCSPlaintextPublicKey : publicKey, @@ -180,6 +181,7 @@ (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccount : @"testaccount", (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], } mutableCopy]; @@ -192,6 +194,8 @@ [blockExpectation fulfill]; }), @"_SecItemAddAndNotifyOnSync succeeded"); + OCMVerifyAllWithDelay(self.mockDatabase, 10); + [self waitForExpectationsWithTimeout:5.0 handler:nil]; } @@ -209,8 +213,9 @@ [self waitForCKModifications]; OCMVerifyAllWithDelay(self.mockDatabase, 40); + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.keychainView.holdOutgoingQueueOperation = [CKKSGroupOperation named:@"outgoing-hold" withBlock: ^{ - secnotice("ckks", "releasing outgoing-queue hold"); + ckksnotice_global("ckks", "releasing outgoing-queue hold"); }]; for(size_t count = 0; count < 150; count++) { @@ -223,6 +228,7 @@ (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccount : @"testaccount", (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, (id)kSecAttrPCSPlaintextPublicKey : [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], } mutableCopy]; @@ -236,8 +242,6 @@ [blockExpectation fulfill]; }), @"_SecItemAddAndNotifyOnSync succeeded"); - // Release the hounds - [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; XCTestExpectation* firstQueueOperation = [self expectationWithDescription: @"found the item in the first queue iteration"]; [self expectCKModifyItemRecords:SecCKKSOutgoingQueueItemsAtOnce @@ -251,13 +255,19 @@ }]; [self expectCKModifyItemRecords:51 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; - [self waitForExpectationsWithTimeout:5.0 handler:nil]; + // Release the hounds + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; + + [self waitForExpectations:@[blockExpectation, firstQueueOperation] timeout:20]; + OCMVerifyAllWithDelay(self.mockDatabase, 10); } - (void)testAddAndNotifyOnSyncFailure { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); + [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Due to item UUID selection, this item will be added with UUID 50184A35-4480-E8BA-769B-567CF72F1EC0. @@ -275,6 +285,7 @@ (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccount : @"testaccount", (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], (id)kSecAttrSyncViewHint : self.keychainView.zoneName, // @ fake view hint for fake view } mutableCopy]; @@ -306,6 +317,7 @@ (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccount : @"testaccount", (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], } mutableCopy]; @@ -333,6 +345,7 @@ (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccount : @"testaccount", (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], } mutableCopy]; @@ -363,7 +376,7 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.loggedIn wait:20*NSEC_PER_SEC], "CKKS should log in"); - [self.keychainView.zoneSetupOperation waitUntilFinished]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateFetch] wait:20*NSEC_PER_SEC], @"Should have reached key state 'fetch', but no further"); NSMutableDictionary* query = [@{ (id)kSecClass : (id)kSecClassGenericPassword, @@ -398,6 +411,120 @@ [self waitForExpectationsWithTimeout:5.0 handler:nil]; } +- (void)testAddAndNotifyOnSyncBeforePolicyLoaded { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self saveTLKMaterialToKeychain:self.keychainZoneID]; + [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; + + [self startCKKSSubsystem]; + + // Allow CKKS to spin up fully + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered ready"); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + // Simulate a daemon restart + self.automaticallyBeginCKKSViewCloudKitOperation = false; + [self.injectedManager resetSyncingPolicy]; + [self.injectedManager haltZone:self.keychainZoneID.zoneName]; + + // Issue the query (to simulate the query starting securityd) + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, + (id)kSecAttrAccount : @"testaccount", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, + (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + + XCTestExpectation* blockExpectation = [self expectationWithDescription: @"callback occurs"]; + + XCTAssertEqual(errSecSuccess, _SecItemAddAndNotifyOnSync((__bridge CFDictionaryRef) query, NULL, ^(bool didSync, CFErrorRef error) { + XCTAssertTrue(didSync, "Item synced"); + XCTAssertNil((__bridge NSError*)error, "Shouldn't have received an error syncing item"); + + [blockExpectation fulfill]; + }), @"_SecItemAddAndNotifyOnSync succeeded"); + + // When the policy is loaded, the item should upload and the callback should fire + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + self.keychainView = [self.injectedManager findView:self.keychainZoneID.zoneName]; + + [self.injectedManager beginCloudKitOperationOfAllViews]; + [self beginSOSTrustedViewOperation:self.keychainView]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Should have reached key state 'ready'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self waitForExpectations:@[blockExpectation] timeout:5]; +} + +- (void)testAddAndNotifyOnSyncReaddAtSameUUIDAfterDeleteItem { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; // Make life easy for this test. + + __block CKRecordID* itemRecordID = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + itemRecordID = record.recordID; + return YES; + }]; + + [self startCKKSSubsystem]; + + // Let things shake themselves out. + [self.keychainView waitForKeyHierarchyReadiness]; + [self waitForCKModifications]; + + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, + (id)kSecAttrAccount : @"testaccount", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, + (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + + XCTestExpectation* blockExpectation = [self expectationWithDescription: @"callback occurs"]; + + XCTAssertEqual(errSecSuccess, _SecItemAddAndNotifyOnSync((__bridge CFDictionaryRef) query, NULL, ^(bool didSync, CFErrorRef error) { + XCTAssertTrue(didSync, "Item synced properly"); + XCTAssertNil((__bridge NSError*)error, "No error syncing item"); + + [blockExpectation fulfill]; + }), @"_SecItemAddAndNotifyOnSync succeeded"); + + OCMVerifyAllWithDelay(self.mockDatabase, 10); + + [self waitForExpectations:@[blockExpectation] timeout:5]; + + // And the item is deleted + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + [self deleteGenericPassword:@"testaccount"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item is readded. It should come back to its previous UUID. + XCTAssertNotNil(itemRecordID, "Should have an item record ID"); + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + XCTAssertEqualObjects(itemRecordID.recordName, record.recordID.recordName, "Uploaded item UUID should match previous upload"); + return YES; + }]; + XCTestExpectation* blockExpectation2 = [self expectationWithDescription: @"callback occurs"]; + XCTAssertEqual(errSecSuccess, _SecItemAddAndNotifyOnSync((__bridge CFDictionaryRef) query, NULL, ^(bool didSync, CFErrorRef error) { + XCTAssertTrue(didSync, "Item synced properly"); + XCTAssertNil((__bridge NSError*)error, "No error syncing item"); + + [blockExpectation2 fulfill]; + }), @"_SecItemAddAndNotifyOnSync succeeded"); + + OCMVerifyAllWithDelay(self.mockDatabase, 10); + [self waitForExpectations:@[blockExpectation2] timeout:5]; +} + - (void)testPCSUnencryptedFieldsAdd { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. @@ -605,7 +732,7 @@ [self.keychainZone addToZone: record]; // Trigger a notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; CFTypeRef item = NULL; @@ -660,6 +787,7 @@ [self.keychainZone addToZone:[cipheritem CKRecordWithZoneID: recordID.zoneID]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword, @@ -718,6 +846,7 @@ [self.keychainZone addToZone:[cipheritem CKRecordWithZoneID: recordID.zoneID]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword, @@ -799,21 +928,25 @@ [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; - // Spin up CKKS subsystem. + // Spin up CKKS subsystem. It should fetch once. + [self expectCKFetch]; [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.loggedIn wait:500*NSEC_PER_MSEC], "Should have been told of a 'login' event on startup"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should arrive at 'waitfortrust''"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + NSData* changeTokenData = [[[NSUUID UUID] UUIDString] dataUsingEncoding:NSUTF8StringEncoding]; CKServerChangeToken* changeToken = [[CKServerChangeToken alloc] initWithData:changeTokenData]; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.keychainView.zoneName]; ckse.changeToken = changeToken; NSError* error = nil; [ckse saveToDatabase:&error]; XCTAssertNil(error, "No error saving new zone state to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // after the reset, CKKS should refetch what's available @@ -822,12 +955,11 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"local reset callback occurs"]; [self.injectedManager rpcResetLocal:nil reply:^(NSError* result) { XCTAssertNil(result, "no error resetting local"); - secnotice("ckks", "Received a rpcResetLocal callback"); + ckksnotice_global("ckks", "Received a rpcResetLocal callback"); - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.keychainView.zoneName]; XCTAssertNotEqualObjects(changeToken, ckse.changeToken, "Change token is reset"); - return true; }]; [resetExpectation fulfill]; @@ -844,6 +976,9 @@ [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; [self beginSOSTrustedViewOperation:self.keychainView]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at 'ready''"); + [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem:[self checkClassABlock:self.keychainZoneID message:@"Object was encrypted under class A key in hierarchy"]]; [self addGenericPassword:@"asdf" account:@"account-class-A" @@ -854,6 +989,35 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testResetLocalWhileLoggedOut { + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + self.accountStatus = CKAccountStatusNoAccount; + [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; + self.silentFetchesAllowed = false; + + // Test starts with local TLK and key hierarchy in our fake cloudkit + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.loggedOut wait:20*NSEC_PER_SEC], "CKKS should positively log out"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], @"Key state should arrive at 'loggedout'"); + + // Can we reset local data while logged out? + XCTestExpectation* resetExpectation = [self expectationWithDescription: @"local reset callback occurs"]; + [self.injectedManager rpcResetLocal:nil reply:^(NSError* result) { + XCTAssertNil(result, "no error resetting local"); + ckksnotice_global("ckks", "Received a rpcResetLocal callback"); + + [resetExpectation fulfill]; + }]; + + [self waitForExpectations:@[resetExpectation] timeout:20]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], @"Key state should arrive at 'loggedout'"); +} + -(void)testResetLocalMultipleTimes { // Test starts with nothing in database, but one in our fake CloudKit. [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; @@ -930,6 +1094,7 @@ [self addGenericPassword: @"data" account: @"account-delete-me"]; OCMVerifyAllWithDelay(self.mockDatabase, 20); [self waitForCKModifications]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); // During the reset, Octagon will upload the key hierarchy, and then CKKS will upload the class C item [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; @@ -937,7 +1102,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -957,6 +1122,8 @@ expecting:errSecSuccess message:@"Adding class A item"]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); } - (void)testResetCloudKitZoneCloudKitRejects { @@ -993,7 +1160,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -1063,7 +1230,6 @@ [self waitForExpectations:@[resetExpectation] timeout:20]; - XCTAssertTrue([outgoingOp isCancelled], "old stuck ProcessOutgoingQueue should be cancelled"); OCMVerifyAllWithDelay(self.mockDatabase, 20); // And adding another item works too @@ -1075,6 +1241,8 @@ expecting:errSecSuccess message:@"Adding class A item"]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertTrue([outgoingOp isFinished], "old ProcessOutgoingQueue should be finished"); } /* @@ -1151,16 +1319,21 @@ XCTAssertNotNil(self.keychainZone.currentDatabase, "Zone exists"); XCTAssertNotNil(self.keychainZone.currentDatabase[ckr.recordID], "An item exists in the fake zone"); + // Make the zone, so we know if it was deleted + self.keychainZone.flag = true; + XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; [self waitForExpectations:@[resetExpectation] timeout:20]; - XCTAssertNil(self.keychainZone.currentDatabase, "No zone anymore!"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], "CKKS entered 'waitfortlkcreation'"); + + XCTAssertFalse(self.keychainZone.flag, "Zone was deleted at some point"); OCMVerifyAllWithDelay(self.mockDatabase, 20); // Now log in, and see what happens! It should create the zone again and upload a whole new key hierarchy @@ -1329,6 +1502,90 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testRPCFetchAndProcessClassAChangesWhileLocked { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + self.aksLockState = true; + [self.lockStateTracker recheck]; + + CKRecord* ckr = [self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" withAccount:@"account-should-exist" key:self.keychainZoneKeys.classA]; + [self.keychainZone addToZone:ckr]; + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + [self.ckksControl rpcFetchAndProcessClassAChanges:nil reply:^(NSError * _Nullable error) { + XCTAssertNotNil(error, "Should have received an error attempting to fetch and process"); + NSError* underlying = error.userInfo[NSUnderlyingErrorKey]; + XCTAssertNotNil(underlying, "Should have received an underlying error"); + XCTAssertEqualObjects(underlying.domain, @"securityd", "Underlying error should be 'securityd' domain"); + XCTAssertEqual(underlying.code, errSecInteractionNotAllowed, "Underlying error should be 'device locked'"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:20]; + [self releaseCloudKitFetchHold]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testRPCPushWithFailingWrite { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS should enter ready"); + + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + self.keychainView.holdOutgoingQueueOperation = [CKKSResultOperation named:@"outgoing-queue-hold" withBlock:^{}]; + + [self failNextCKAtomicModifyItemRecordsUpdateFailure:self.keychainZoneID]; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + + [self addGenericPassword: @"data" account: @"account-delete-me"]; + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + [self.ckksControl rpcPushOutgoingChanges:nil reply:^(NSError * _Nullable error) { + // done! we should have an underlying error of "atomic write failed" + XCTAssertNotNil(error, "Should have received an error due to the failed push"); + NSError* underlying = error.userInfo[NSUnderlyingErrorKey]; + XCTAssertNotNil(underlying, "Should have received an underlying error"); + XCTAssertEqualObjects(underlying.domain, CKErrorDomain, "Underlying error should be CKErrorDomain"); + XCTAssertEqual(underlying.code, CKErrorPartialFailure, "Underlying error should be 'CKErrorPartialFailure'"); + [callbackOccurs fulfill]; + }]; + + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; + + [self waitForExpectations:@[callbackOccurs] timeout:20]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testRPCPushWhileInWaitForTLK { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "CKKS entered waitfortlk"); + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + [self.ckksControl rpcPushOutgoingChanges:nil reply:^(NSError * _Nullable error) { + // done! we should have an underlying error of "fetch isn't working" + XCTAssertNotNil(error, "Should have received an error attempting to push a broken zone"); + NSError* underlying = error.userInfo[NSUnderlyingErrorKey]; + XCTAssertNotNil(underlying, "Should have received an underlying error"); + XCTAssertEqualObjects(underlying.domain, CKKSResultDescriptionErrorDomain, "Underlying error should be CKKSResultDescriptionErrorDomain"); + XCTAssertEqual(underlying.code, CKKSResultDescriptionPendingKeyReady, "Underlying error should be 'pending key ready'"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:20]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + - (void)testRPCTLKMissingWhenMissing { // Bring CKKS up in waitfortlk [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; @@ -1370,6 +1627,48 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testRPCKnownBadStateWhenNoCloudKit { + self.accountStatus = CKAccountStatusNoAccount; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered loggedout"); + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + + [self.ckksControl rpcKnownBadState:@"keychain" reply:^(CKKSKnownBadState result) { + XCTAssertEqual(result, CKKSKnownStateNoCloudKitAccount, "State should be 'no cloudkit account'"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:20]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testRPCKnownBadStateWhenNoTrust { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], "CKKS entered waitfortrust"); + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + + [self.ckksControl rpcKnownBadState:@"keychain" reply:^(CKKSKnownBadState result) { + XCTAssertEqual(result, CKKSKnownStateWaitForOctagon, "State should be 'waitforoctagon'"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:20]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + - (void)testRPCKnownBadStateWhenTLKsMissing { // Bring CKKS up in waitfortlk [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; @@ -1544,10 +1843,18 @@ - (void)testRpcStatusIsFastDuringError { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. - self.keychainFetchError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecInternalError description:@"injected keychain failure"]; - - // Let CKKS come up; it should enter 'error' + // Let CKKS come up, then force it into error [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + + OctagonStateTransitionOperation* op = [OctagonStateTransitionOperation named:@"enter" entering:SecCKKSZoneKeyStateError]; + OctagonStateTransitionRequest* request = [[OctagonStateTransitionRequest alloc] init:@"enter-wait-for-trust" + sourceStates:[NSSet setWithArray:[CKKSZoneKeyStateMap() allKeys]] + serialQueue:self.keychainView.queue + timeout:10 * NSEC_PER_SEC + transitionOp:op]; + [self.keychainView.stateMachine handleExternalRequest:request]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateError] wait:20*NSEC_PER_SEC], "CKKS entered 'error'"); // Fire off the status RPC; it should return immediately @@ -1568,6 +1875,108 @@ [self waitForExpectations:@[callbackOccurs] timeout:20]; } +- (void)testResetLocalAPIWakesDaemon { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:[self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + + // Now, simulate a restart: all views suddenly go missing from the ViewManager + [self.injectedManager clearAllViews]; + [self.injectedManager resetSyncingPolicy]; + [self.injectedManager beginCloudKitOperationOfAllViews]; + + // And a reset-local API call wakes the daemon + // The policy arrives after 500ms + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0.5 * NSEC_PER_SEC)), dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + self.ckksViews = [NSMutableSet setWithArray:[self.injectedManager.views allValues]]; + self.keychainView = [self.injectedManager findView:@"keychain"]; + [self beginSOSTrustedOperationForAllViews]; + }); + + XCTestExpectation* resetExpectation = [self expectationWithDescription: @"local reset callback occurs"]; + [self.injectedManager rpcResetLocal:self.keychainZoneID.zoneName reply:^(NSError* result) { + XCTAssertNil(result, "no error resetting local"); + [resetExpectation fulfill]; + }]; + + [self waitForExpectations:@[resetExpectation] timeout:20]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testPushAPIWakesDaemon { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:[self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + + // Now, simulate a restart: all views suddenly go missing from the ViewManager + [self.injectedManager clearAllViews]; + [self.injectedManager resetSyncingPolicy]; + [self.injectedManager beginCloudKitOperationOfAllViews]; + + // And a fetch API call wakes the daemon + // The policy arrives after 500msx + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0.5 * NSEC_PER_SEC)), dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + self.ckksViews = [NSMutableSet setWithArray:[self.injectedManager.views allValues]]; + [self beginSOSTrustedOperationForAllViews]; + }); + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + [self.ckksControl rpcPushOutgoingChanges:nil reply:^(NSError * _Nullable error) { + XCTAssertNil(error, "Should have received no error"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:60]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testFetchAPIWakesDaemon { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:[self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + + // Now, simulate a restart: all views suddenly go missing from the ViewManager + [self.injectedManager clearAllViews]; + [self.injectedManager resetSyncingPolicy]; + [self.injectedManager beginCloudKitOperationOfAllViews]; + + // And a fetch API call wakes the daemon + // The policy arrives after 500ms + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0.5 * NSEC_PER_SEC)), dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + self.ckksViews = [NSMutableSet setWithArray:[self.injectedManager.views allValues]]; + [self beginSOSTrustedOperationForAllViews]; + }); + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + [self.ckksControl rpcFetchAndProcessChanges:nil reply:^(NSError * _Nullable error) { + XCTAssertNil(error, "Should have received no error"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:20]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + @end #endif // OCTAGON diff --git a/keychain/ckks/tests/CKKSTests+Coalesce.m b/keychain/ckks/tests/CKKSTests+Coalesce.m index b4964441..1006a9e8 100644 --- a/keychain/ckks/tests/CKKSTests+Coalesce.m +++ b/keychain/ckks/tests/CKKSTests+Coalesce.m @@ -96,25 +96,119 @@ [self waitForCKModifications]; // Okay, now the delete/add. Note that this is not a coalescing operation, since the new item - // will have a completely different UUID, and so will delete the old record and upload the new one. + // has different contents. (This test used to upload the item to a different UUID, but no longer). + + self.keychainView.holdOutgoingQueueOperation = [CKKSResultOperation named:@"hold-outgoing-queue" + withBlock:^{}]; - [self.keychainView.operationQueue waitUntilAllOperationsAreFinished]; - self.keychainView.operationQueue.suspended = YES; [self deleteGenericPassword: account]; - [self addGenericPassword: @"data" account: account]; + [self addGenericPassword: @"data_new_contents" account: account]; - [self expectCKModifyRecords:@{SecCKRecordItemType: [NSNumber numberWithUnsignedInteger: 1], - SecCKRecordCurrentKeyType: [NSNumber numberWithUnsignedInteger: 1], - SecCKRecordDeviceStateType: [NSNumber numberWithUnsignedInteger: 1], - } - deletedRecordTypeCounts:@{SecCKRecordItemType: [NSNumber numberWithUnsignedInteger: 1]} - zoneID:self.keychainZoneID - checkModifiedRecord:nil - runAfterModification:nil]; - self.keychainView.operationQueue.suspended = NO; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID + checkItem:[self checkPasswordBlock:self.keychainZoneID account:account password:@"data_new_contents"]]; + + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testCoalesceReceiveModifyWhileDeletingItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + NSString* account = @"account-delete-me"; + + [self addGenericPassword:@"data" account:account]; + + // We expect a single record to be uploaded. + __block CKRecord* itemRecord = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID + checkItem:^BOOL(CKRecord * _Nonnull record) { + itemRecord = record; + return YES; + }]; + + [self startCKKSSubsystem]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + // Now, we receive a modification from CK, but then delete the item locally before processing the IQE. + + XCTAssertNotNil(itemRecord, "Should have a record for the uploaded item"); + NSMutableDictionary* contents = [[self decryptRecord:itemRecord] mutableCopy]; + contents[@"v_Data"] = [@"updated" dataUsingEncoding:NSUTF8StringEncoding]; + + CKRecord* recordUpdate = [self newRecord:itemRecord.recordID withNewItemData:contents]; + [self.keychainZone addCKRecordToZone:recordUpdate]; + + self.keychainView.holdIncomingQueueOperation = [NSBlockOperation blockOperationWithBlock:^{}]; + + // Ensure we wait for the whole fetch + NSOperation* fetchOp = [self.keychainView.zoneChangeFetcher requestSuccessfulFetch:CKKSFetchBecauseTesting]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + + [fetchOp waitUntilFinished]; + + // now, delete the item + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + [self deleteGenericPassword:account]; + + [self.operationQueue addOperation:self.keychainView.holdIncomingQueueOperation]; + + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item shouldn't be present, since it was deleted via API after the item was fetched + [self findGenericPassword:account expecting:errSecItemNotFound]; +} + +- (void)testCoalesceReceiveDeleteWhileModifyingItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + NSString* account = @"account-delete-me"; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); + + __block CKRecord* itemRecord = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID + checkItem:^BOOL(CKRecord * _Nonnull record) { + itemRecord = record; + return YES; + }]; + + [self addGenericPassword:@"data" account:account]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + // Ensure we fetch again, to prime the delete (due to insufficient mock CK) + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + // Now, we receive a delete from CK, but after we modify the item locally + self.keychainView.holdOutgoingQueueOperation = [NSBlockOperation blockOperationWithBlock:^{}]; + + XCTAssertNotNil(itemRecord, "Should have an item record from the upload"); + [self.keychainZone deleteCKRecordIDFromZone:itemRecord.recordID]; + [self updateGenericPassword:@"new-password" account:account]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:account expecting:errSecItemNotFound]; + + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; + + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item shouldn't be present, since it was deleted via CK after the API change + [self findGenericPassword:account expecting:errSecItemNotFound]; +} + @end #endif diff --git a/keychain/ckks/tests/CKKSTests+CurrentPointerAPI.m b/keychain/ckks/tests/CKKSTests+CurrentPointerAPI.m index c75ef74c..faa093d1 100644 --- a/keychain/ckks/tests/CKKSTests+CurrentPointerAPI.m +++ b/keychain/ckks/tests/CKKSTests+CurrentPointerAPI.m @@ -142,7 +142,7 @@ // Check that the record is where we expect it in CloudKit [self waitForCKModifications]; - CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID]; + CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID]; XCTAssertNotNil(record, "Found record in CloudKit at expected UUID"); @@ -153,6 +153,7 @@ deletedRecordTypeCounts:nil zoneID:self.keychainZoneID checkModifiedRecord:nil + inspectOperationGroup:nil runAfterModification:nil]; // Set the 'current' pointer. @@ -206,7 +207,7 @@ // Check that the record is where we expect it [self waitForCKModifications]; - CKRecordID* pcsOtherItemRecordID = [[CKRecordID alloc] initWithRecordName: @"878BEAA6-1EE9-1079-1025-E6832AC8F2F3" zoneID:self.keychainZoneID]; + CKRecordID* pcsOtherItemRecordID = [[CKRecordID alloc] initWithRecordName: @"2DEA6136-2505-6BFD-E3E8-B44A6E39C3B5" zoneID:self.keychainZoneID]; CKRecord* recordOther = self.keychainZone.currentDatabase[pcsOtherItemRecordID]; XCTAssertNotNil(recordOther, "Found other record in CloudKit at expected UUID"); @@ -228,7 +229,7 @@ CFReleaseNull(cfresult); if(![actualSHA1 isEqual:sha1]) { - secnotice("ckks", "SHA1s don't match, but why?"); + ckksnotice_global("ckks", "SHA1s don't match, but why?"); } XCTestExpectation* otherSetCurrentExpectation = [self expectationWithDescription: @"callback occurs"]; @@ -237,6 +238,7 @@ deletedRecordTypeCounts:nil zoneID:self.keychainZoneID checkModifiedRecord:nil + inspectOperationGroup:nil runAfterModification:nil]; // Ensure that setting the current pointer sends a notification @@ -344,7 +346,7 @@ // Check that the record is where we expect it in CloudKit [self waitForCKModifications]; - CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID]; + CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID]; XCTAssertNotNil(record, "Found record in CloudKit at expected UUID"); @@ -547,11 +549,11 @@ // Check that the records are where we expect them in CloudKit [self waitForCKModifications]; - CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID]; + CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID]; XCTAssertNotNil(record, "Found record in CloudKit at expected UUID"); - CKRecordID* pcsItemRecordID2 = [[CKRecordID alloc] initWithRecordName: @"3AB8E78D-75AF-CFEF-F833-FA3E3E90978A" zoneID:self.keychainZoneID]; + CKRecordID* pcsItemRecordID2 = [[CKRecordID alloc] initWithRecordName: @"10E76B80-CE1C-A52A-B0CB-462A2EBA05AF" zoneID:self.keychainZoneID]; CKRecord* record2 = self.keychainZone.currentDatabase[pcsItemRecordID2]; XCTAssertNotNil(record2, "Found 2nd record in CloudKit at expected UUID"); @@ -560,7 +562,7 @@ // Another machine comes along and updates the pointer! CKKSCurrentItemPointer* cip = [[CKKSCurrentItemPointer alloc] initForIdentifier:@"com.apple.security.ckks-pcsservice" - currentItemUUID:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" + currentItemUUID:@"50184A35-4480-E8BA-769B-567CF72F1EC0" state:SecCKKSProcessedStateRemote zoneID:self.keychainZoneID encodedCKRecord:nil]; @@ -572,7 +574,7 @@ // Ensure that receiving the current item pointer generates a notification keychainChanged = [self expectChangeForView:self.keychainZoneID.zoneName]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self waitForExpectations:@[keychainChanged] timeout:8]; @@ -591,7 +593,7 @@ keychainChanged = [self expectChangeForView:self.keychainZoneID.zoneName]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self waitForExpectations:@[keychainChanged] timeout:8]; @@ -638,7 +640,7 @@ // Check that the record is where we expect it in CloudKit [self waitForCKModifications]; - CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID]; + CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID]; XCTAssertNotNil(record, "Found record in CloudKit at expected UUID"); @@ -647,7 +649,7 @@ // Another machine comes along and updates the pointer! CKKSCurrentItemPointer* cip = [[CKKSCurrentItemPointer alloc] initForIdentifier:@"com.apple.security.ckks-pcsservice" - currentItemUUID:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" + currentItemUUID:@"50184A35-4480-E8BA-769B-567CF72F1EC0" state:SecCKKSProcessedStateRemote zoneID:self.keychainZoneID encodedCKRecord:nil]; @@ -656,7 +658,7 @@ CKRecord* currentPointerRecord = self.keychainZone.currentDatabase[currentPointerRecordID]; XCTAssertNotNil(currentPointerRecord, "Found record in CloudKit at expected UUID"); - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self fetchCurrentPointer:false persistentRef:persistentRef]; @@ -666,7 +668,8 @@ // Another machine comes along and deletes the pointer! [self.keychainZone deleteCKRecordIDFromZone: currentPointerRecordID]; - [self.keychainView notifyZoneChange:nil]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self waitForExpectations:@[keychainChanged] timeout:8]; @@ -712,7 +715,7 @@ // Check that the record is where we expect it in CloudKit [self waitForCKModifications]; - NSString* recordUUID = @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3"; + NSString* recordUUID = @"50184A35-4480-E8BA-769B-567CF72F1EC0"; CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName:recordUUID zoneID:self.keychainZoneID]; CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID]; XCTAssertNotNil(record, "Found record in CloudKit at expected UUID"); @@ -792,7 +795,7 @@ // Check that the record is where we expect it in CloudKit [self waitForCKModifications]; - CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID]; + CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID]; XCTAssertNotNil(record, "Found record in CloudKit at expected UUID"); @@ -803,6 +806,7 @@ deletedRecordTypeCounts:nil zoneID:self.keychainZoneID checkModifiedRecord:nil + inspectOperationGroup:nil runAfterModification:nil]; // Set the 'current' pointer. @@ -826,20 +830,18 @@ modifiedRecord[SecCKRecordServerWasCurrent] = [NSNumber numberWithInteger:10]; [self.keychainZone addToZone:modifiedRecord]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Check that the number is on the CKKSMirrorEntry - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; - CKKSMirrorEntry* ckme = [CKKSMirrorEntry fromDatabase:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID error:&error]; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry fromDatabase:@"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "no error fetching ckme"); XCTAssertNotNil(ckme, "Received a ckme"); XCTAssertEqual(ckme.wasCurrent, 10u, "Properly received wasCurrent"); - - return true; }]; } @@ -879,7 +881,7 @@ // Check that the record is where we expect it in CloudKit [self waitForCKModifications]; - CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID]; + CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID]; XCTAssertNotNil(record, "Found record in CloudKit at expected UUID"); @@ -943,7 +945,7 @@ // Check that the record is where we expect it in CloudKit [self waitForCKModifications]; - CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID]; + CKRecordID* pcsItemRecordID = [[CKRecordID alloc] initWithRecordName: @"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; CKRecord* record = self.keychainZone.currentDatabase[pcsItemRecordID]; XCTAssertNotNil(record, "Found record in CloudKit at expected UUID"); @@ -954,6 +956,7 @@ deletedRecordTypeCounts:nil zoneID:self.keychainZoneID checkModifiedRecord:nil + inspectOperationGroup:nil runAfterModification:nil]; // Set the 'current' pointer. @@ -1009,6 +1012,7 @@ deletedRecordTypeCounts:nil zoneID:self.keychainZoneID checkModifiedRecord:nil + inspectOperationGroup:nil runAfterModification:nil]; // Set the 'current' pointer. @@ -1061,12 +1065,13 @@ XCTAssertNil(error, "Error should be nil parsing base64 item"); item[@"v_Data"] = [@"conflictingdata" dataUsingEncoding:NSUTF8StringEncoding]; - CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID]; + item[@"vwht"] = @"keychain"; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; CKRecord* mismatchedRecord = [self newRecord:ckrid withNewItemData:item]; [self.keychainZone addToZone: mismatchedRecord]; self.keychainView.holdIncomingQueueOperation = [CKKSResultOperation named:@"hold-incoming" withBlock:^{ - secnotice("ckks", "Releasing process incoming queue hold"); + ckksnotice_global("ckks", "Releasing process incoming queue hold"); }]; NSData* firstItemData = [@"asdf" dataUsingEncoding:NSUTF8StringEncoding]; @@ -1142,6 +1147,7 @@ [self waitForExpectations:@[setCurrentExpectation] timeout:20]; // Reissue a fetch and find the new persistent ref and sha1 for the item at this UUID + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // The conflicting item update should have won @@ -1168,6 +1174,7 @@ deletedRecordTypeCounts:nil zoneID:self.keychainZoneID checkModifiedRecord:nil + inspectOperationGroup:nil runAfterModification:nil]; XCTestExpectation* newSetCurrentExpectation = [self expectationWithDescription: @"callback occurs"]; diff --git a/keychain/ckks/tests/CKKSTests+ForwardCompatibility.m b/keychain/ckks/tests/CKKSTests+ForwardCompatibility.m new file mode 100644 index 00000000..34385d03 --- /dev/null +++ b/keychain/ckks/tests/CKKSTests+ForwardCompatibility.m @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if OCTAGON + +#import +#import +#import + +#import +#import +#import + +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/tests/CKKSTests.h" +#import "keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h" +#import "keychain/ckks/tests/CloudKitMockXCTest.h" +#import "keychain/ckks/tests/MockCloudKit.h" + +@interface CloudKitKeychainForwardCompatibilityTests : CloudKitKeychainSyncingTestsBase +@property CKRecordZoneID* unknownZoneID; +@property CKRecordZoneID* passwordsZoneID; +@property CKKSKeychainView* passwordsView; + +@property TPSyncingPolicy* originalPolicy; +@property TPSyncingPolicy* originalPolicyPlusUnknownVwht; +@property TPSyncingPolicy* allItemsToPasswordsPolicy; +@end + +@implementation CloudKitKeychainForwardCompatibilityTests + +- (void)setUp { + [super setUp]; + + self.passwordsZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"Passwords" ownerName:CKCurrentUserDefaultName]; + self.unknownZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"unknown-zone" ownerName:CKCurrentUserDefaultName]; + + self.zones[self.passwordsZoneID] = [[FakeCKZone alloc] initZone:self.passwordsZoneID]; + + self.originalPolicy = self.viewSortingPolicyForManagedViewList; + + + NSMutableArray* newRules = [self.originalPolicy.keyViewMapping mutableCopy]; + TPPBPolicyKeyViewMapping* unknownVwhtMapping = [[TPPBPolicyKeyViewMapping alloc] init]; + unknownVwhtMapping.view = self.keychainZoneID.zoneName; + unknownVwhtMapping.matchingRule = [TPDictionaryMatchingRule fieldMatch:@"vwht" + fieldRegex:[NSString stringWithFormat:@"^%@$", self.unknownZoneID.zoneName]]; + [newRules insertObject:unknownVwhtMapping atIndex:0]; + + self.originalPolicyPlusUnknownVwht = [[TPSyncingPolicy alloc] initWithModel:@"test-policy" + version:[[TPPolicyVersion alloc] initWithVersion:2 hash:@"fake-policy-for-views-with-unknown-view"] + viewList:self.originalPolicy.viewList + priorityViews:self.originalPolicy.priorityViews + userControllableViews:self.originalPolicy.userControllableViews + syncUserControllableViews:self.originalPolicy.syncUserControllableViews + viewsToPiggybackTLKs:self.originalPolicy.viewsToPiggybackTLKs + keyViewMapping:newRules]; + + TPPBPolicyKeyViewMapping* passwordsVwhtMapping = [[TPPBPolicyKeyViewMapping alloc] init]; + passwordsVwhtMapping.view = self.passwordsZoneID.zoneName; + passwordsVwhtMapping.matchingRule = [TPDictionaryMatchingRule trueMatch]; + + self.allItemsToPasswordsPolicy = [[TPSyncingPolicy alloc] initWithModel:@"test-policy" + version:[[TPPolicyVersion alloc] initWithVersion:2 hash:@"fake-policy-for-views-with-passwords-view"] + viewList:[NSSet setWithArray:@[self.keychainView.zoneName, self.passwordsZoneID.zoneName]] + priorityViews:[NSSet set] + userControllableViews:self.originalPolicy.userControllableViews + syncUserControllableViews:self.originalPolicy.syncUserControllableViews + viewsToPiggybackTLKs:self.originalPolicy.viewsToPiggybackTLKs + keyViewMapping:@[passwordsVwhtMapping]]; +} + +- (void)setPolicyAndWaitForQuiescence:(TPSyncingPolicy*)policy policyIsFresh:(BOOL)policyIsFresh { + [self.injectedManager setCurrentSyncingPolicy:policy policyIsFresh:policyIsFresh]; + self.ckksViews = [NSMutableSet setWithArray:[[self.injectedManager views] allValues]]; + [self beginSOSTrustedOperationForAllViews]; + + // And wait for everything to enter a resting state + for(CKKSKeychainView* view in self.ckksViews) { + XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + [view waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [view waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + } +} + +- (void)testReceiveItemForWrongView { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSString* wrongZoneAccount = @"wrong-zone"; + NSDictionary* item = [self fakeRecordDictionary:wrongZoneAccount zoneID:self.unknownZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self findGenericPassword:wrongZoneAccount expecting:errSecItemNotFound]; + + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + + NSError* zoneError = nil; + NSInteger count = [CKKSIncomingQueueEntry countByState:SecCKKSStateMismatchedView zone:self.keychainView.zoneID error:&zoneError]; + XCTAssertNil(zoneError, "should be no error counting all IQEs"); + XCTAssertEqual(count, 1, "Should be one mismatched IQE"); +} + +- (void)testConflictingItemInWrongView { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + self.passwordsView = [self.injectedManager findView:@"Passwords"]; + XCTAssertNotNil(self.passwordsView, @"Policy created a passwords view"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + XCTAssertEqual(0, [self.passwordsView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSDictionary* item = [self fakeRecordDictionary:@"account-delete-me" zoneID:self.passwordsZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.passwordsZoneID]; + CKRecordID* ckr2id = [[CKRecordID alloc] initWithRecordName:@"FFFF8D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + + NSMutableDictionary* item2 = [item mutableCopy]; + item2[@"v_Data"] = @"wrongview"; + CKRecord* ckr2 = [self newRecord:ckr2id withNewItemData:item2]; + + // Receive the passwords item first + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.passwordsView waitForFetchAndIncomingQueueProcessing]; + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + [self.zones[self.keychainZoneID] addToZone:ckr2]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // THe view should ask for an update, and receive one + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + // And we have ignored the change in the other view + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item is then deleted + [self.zones[self.keychainZoneID] deleteCKRecordIDFromZone:ckr2id]; + OCMExpect([self.requestPolicyCheck trigger]); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + // The password should still exist + [self checkGenericPassword:@"data" account:@"account-delete-me"]; +} + +- (void)testConflictingItemInWrongViewWithLowerUUID { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + self.passwordsView = [self.injectedManager findView:@"Passwords"]; + XCTAssertNotNil(self.passwordsView, @"Policy created a passwords view"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + XCTAssertEqual(0, [self.passwordsView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSDictionary* item = [self fakeRecordDictionary:@"account-delete-me" zoneID:self.passwordsZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.passwordsZoneID]; + CKRecordID* ckr2id = [[CKRecordID alloc] initWithRecordName:@"00008D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + + NSMutableDictionary* item2 = [item mutableCopy]; + item2[@"v_Data"] = @"wrongview"; + CKRecord* ckr2 = [self newRecord:ckr2id withNewItemData:item2]; + + // Receive the passwords item first + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.passwordsView waitForFetchAndIncomingQueueProcessing]; + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + [self.zones[self.keychainZoneID] addToZone:ckr2]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // THe view should ask for an update, and receive one + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + // And the item is then deleted + [self.zones[self.keychainZoneID] deleteCKRecordIDFromZone:ckr2id]; + OCMExpect([self.requestPolicyCheck trigger]); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + // The password should still exist + [self checkGenericPassword:@"data" account:@"account-delete-me"]; +} + +- (void)testConflictingItemInWrongViewWithSameUUID { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + self.passwordsView = [self.injectedManager findView:@"Passwords"]; + XCTAssertNotNil(self.passwordsView, @"Policy created a passwords view"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + XCTAssertEqual(0, [self.passwordsView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSDictionary* item = [self fakeRecordDictionary:@"account-delete-me" zoneID:self.passwordsZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.passwordsZoneID]; + CKRecordID* ckr2id = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + + NSMutableDictionary* item2 = [item mutableCopy]; + item2[@"v_Data"] = @"wrongview"; + CKRecord* ckr2 = [self newRecord:ckr2id withNewItemData:item2]; + + // Receive the passwords item first + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.passwordsView waitForFetchAndIncomingQueueProcessing]; + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + [self.zones[self.keychainZoneID] addToZone:ckr2]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // THe view should ask for a policy update, and receive one + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + // And the item is then deleted + [self.zones[self.keychainZoneID] deleteCKRecordIDFromZone:ckr2id]; + OCMExpect([self.requestPolicyCheck trigger]); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + // The password should still exist + [self checkGenericPassword:@"data" account:@"account-delete-me"]; +} + +- (void)testReceiveItemForFuturePolicy { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSString* wrongZoneAccount = @"wrong-zone"; + NSDictionary* item = [self fakeRecordDictionary:wrongZoneAccount zoneID:self.unknownZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self findGenericPassword:wrongZoneAccount expecting:errSecItemNotFound]; + + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + + // Now, Octagon discovers that there's a new policy that allows this item in the keychain view + TPSyncingPolicy* currentPolicy = self.injectedManager.policy; + XCTAssertNotNil(currentPolicy, "should have a current policy"); + + [self setPolicyAndWaitForQuiescence:self.originalPolicyPlusUnknownVwht policyIsFresh:YES]; + + [self findGenericPassword:wrongZoneAccount expecting:errSecSuccess]; +} + +- (void)testHandleItemMovedBetweenViewsBeforePolicyChange { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + // A password is created and uploaded out of the keychain view. + __block CKRecord* itemCKRecord = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + itemCKRecord = record; + return YES; + }]; + NSString* itemAccount = @"account-delete-me"; + [self addGenericPassword:@"data" account:itemAccount viewHint:self.keychainZoneID.zoneName]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertNotNil(itemCKRecord, "Should have some CKRecord for the added item"); + + // Update etag as well + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // Another device shows up, changes the item sync policy, and moves the item over into the passwords view. + + NSDictionary* itemContents = [self decryptRecord:itemCKRecord]; + XCTAssertNotNil(itemContents, "should have some item contents"); + + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:itemCKRecord.recordID.recordName zoneID:self.passwordsZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:itemContents]; + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + TPSyncingPolicy* currentPolicy = self.injectedManager.policy; + XCTAssertNotNil(currentPolicy, "should have a current policy"); + + // In this test, we receive the deletion, and then the policy change adding the Passwords view + [self.keychainZone deleteCKRecordIDFromZone:itemCKRecord.recordID]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:itemAccount expecting:errSecItemNotFound]; + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + + // And once passwords syncs, the item should appear again + [self findGenericPassword:itemAccount expecting:errSecSuccess]; +} + +- (void)testHandleItemMovedBetweenViewsAfterPolicyChange { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + // A password is created and uploaded out of the keychain view. + __block CKRecord* itemCKRecord = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + itemCKRecord = record; + return YES; + }]; + NSString* itemAccount = @"account-delete-me"; + [self addGenericPassword:@"data" account:itemAccount viewHint:self.keychainZoneID.zoneName]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertNotNil(itemCKRecord, "Should have some CKRecord for the added item"); + + // Update etag as well + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // Another device shows up, changes the item sync policy, and moves the item over into the Passwords view. + // But, in this case, we receive the item delete in the Keychain view after we've synced the item in the Passwords view + + NSDictionary* itemContents = [self decryptRecord:itemCKRecord]; + XCTAssertNotNil(itemContents, "should have some item contents"); + + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:itemCKRecord.recordID.recordName zoneID:self.passwordsZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:itemContents]; + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + TPSyncingPolicy* currentPolicy = self.injectedManager.policy; + XCTAssertNotNil(currentPolicy, "should have a current policy"); + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + + CKKSKeychainView* passwordsView = [self.injectedManager findView:self.passwordsZoneID.zoneName]; + XCTAssertNotNil(passwordsView, @"Should have a passwords view"); + + // And once Passwords syncs, the item should appear again + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + + // And now we receive the delete in the keychain view. The item should still exist! + [self.keychainZone deleteCKRecordIDFromZone:itemCKRecord.recordID]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + + // Keychain View should have asked for a policy set + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + [self.injectedManager setCurrentSyncingPolicy:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + + NSError* zoneError = nil; + NSInteger count = [CKKSIncomingQueueEntry countByState:SecCKKSStateMismatchedView zone:self.keychainView.zoneID error:&zoneError]; + XCTAssertNil(zoneError, "should be no error counting all IQEs"); + XCTAssertEqual(count, 0, "Should be no remaining mismatched IQEs"); +} + +- (void)testMoveItemUploadedToOldZone { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + + // Now, someone uploads an item to the keychain view. We should move it to the passwords view + CKRecord* ckr = [self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" withAccount:@"account0"]; + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // The keychain view should request a policy refetch + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + + // Note that ideally, we'd remove the old item from CloudKit. But, other devices which participate in CKKS4All + // might not have this forward-compatiblity change, and will treat this as a deletion. If they process this deletion, + // then sync the resulting tombstone to a third SOS device, then receive the addition in the 'right' view, and then the + // tombstone syncs back to the CKKS4All devices, then we might end up deleting the item across the account. + // Until enough internal folk have moved onto builds with this forward-compat change, we can't issue these deletes. + //[self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + + // The item should be reuploaded to Passwords, though. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.passwordsZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + return [record.recordID.recordName isEqualToString:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; + }]; + + [self.injectedManager setCurrentSyncingPolicy:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the keychain item should still exist + [self findGenericPassword:@"account0" expecting:errSecSuccess]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/tests/CKKSTests+ItemSyncChoice.m b/keychain/ckks/tests/CKKSTests+ItemSyncChoice.m new file mode 100644 index 00000000..7ec26bf1 --- /dev/null +++ b/keychain/ckks/tests/CKKSTests+ItemSyncChoice.m @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if OCTAGON + +#import +#import +#import + +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/tests/CKKSTests.h" +#import "keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h" +#import "keychain/ckks/tests/CloudKitMockXCTest.h" +#import "keychain/ckks/tests/MockCloudKit.h" + +@interface CloudKitKeychainSyncingItemSyncChoiceTests : CloudKitKeychainSyncingTestsBase +@property CKKSSOSSelfPeer* remotePeer1; +@end + +@implementation CloudKitKeychainSyncingItemSyncChoiceTests + +- (size_t)outgoingQueueSize:(CKKSKeychainView*)view { + __block size_t result = 0; + + [view dispatchSyncWithReadOnlySQLTransaction:^{ + NSError* zoneError = nil; + NSArray* entries = [CKKSOutgoingQueueEntry all:view.zoneID error:&zoneError]; + XCTAssertNil(zoneError, "should be no error fetching all OQEs"); + + result = (size_t)entries.count; + }]; + return result; +} + +- (size_t)incomingQueueSize:(CKKSKeychainView*)view { + __block size_t result = 0; + + [view dispatchSyncWithReadOnlySQLTransaction:^{ + NSError* zoneError = nil; + NSArray* entries = [CKKSIncomingQueueEntry all:view.zoneID error:&zoneError]; + XCTAssertNil(zoneError, "should be no error fetching all IQEs"); + + result = (size_t)entries.count; + }]; + return result; +} + +- (void)setUp { + [super setUp]; + + self.remotePeer1 = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote-peer1" + encryptionKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] + signingKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] + viewList:self.managedViewList]; +} + +- (void)testAddItemToPausedView { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + [self addGenericPassword:@"data" account:@"account-delete-me"]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + XCTAssertEqual(1, [self outgoingQueueSize:self.keychainView], "There should be one pending item in the outgoing queue"); + + // and again + [self addGenericPassword:@"data" account:@"account-delete-me-2"]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + XCTAssertEqual(2, [self outgoingQueueSize:self.keychainView], "There should be two pending item in the outgoing queue"); + + // When syncing is enabled, these items should sync + [self expectCKModifyItemRecords:2 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED] + policyIsFresh:NO]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testReceiveItemToPausedView { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + [self findGenericPassword: @"account0" expecting:errSecItemNotFound]; + + [self.keychainZone addToZone:[self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D00" withAccount:@"account0"]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + XCTAssertEqual(1, [self incomingQueueSize:self.keychainView], "There should be one pending item in the incoming queue"); + + [self.keychainZone addToZone:[self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-0000-5A507ACB2D00" withAccount:@"account1"]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + XCTAssertEqual(2, [self incomingQueueSize:self.keychainView], "There should be two pending item in the incoming queue"); + + [self findGenericPassword:@"account0" expecting:errSecItemNotFound]; + [self findGenericPassword:@"account1" expecting:errSecItemNotFound]; + + // When syncing is enabled, these items should sync + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED] + policyIsFresh:NO]; + + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [self findGenericPassword:@"account0" expecting:errSecSuccess]; + [self findGenericPassword:@"account1" expecting:errSecSuccess]; +} + +- (void)testAcceptKeyHierarchyWhilePaused { + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self saveTLKMaterialToKeychain:self.keychainZoneID]; + [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should have become ready"); +} + +- (void)testUploadSelfTLKShare { + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + // Test starts with no keys in CKKS database, but one in our fake CloudKit. + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + + // Test also starts with the TLK shared to all trusted peers from peer1 + [self.mockSOSAdapter.trustedPeers addObject:self.remotePeer1]; + [self putTLKSharesInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 zoneID:self.keychainZoneID]; + + // The CKKS subsystem should accept the keys, and share the TLK back to itself + [self expectCKModifyKeyRecords:0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); + + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testSendNewTLKSharesOnTrustSetAddition { + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + // step 1: add a new peer; we should share the TLK with them + // start with no trusted peers + [self.mockSOSAdapter.trustedPeers removeAllObjects]; + + [self startCKKSSubsystem]; + [self performOctagonTLKUpload:self.ckksViews]; + + [self expectCKModifyKeyRecords:0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; + [self.mockSOSAdapter.trustedPeers addObject:self.remotePeer1]; + [self.mockSOSAdapter sendTrustedPeerSetChangedUpdate]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + // and just double-check that no syncing is occurring + [self addGenericPassword:@"data" account:@"account-delete-me"]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + XCTAssertEqual(1, [self outgoingQueueSize:self.keychainView], "There should be one pending item in the outgoing queue"); +} + +- (void)testAddAndNotifyOnSyncDuringPausedOperation { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should have become ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, + (id)kSecAttrAccount : @"testaccount", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, + (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + + XCTestExpectation* blockExpectation = [self expectationWithDescription: @"callback occurs"]; + + XCTAssertEqual(errSecSuccess, _SecItemAddAndNotifyOnSync((__bridge CFDictionaryRef) query, NULL, ^(bool didSync, CFErrorRef cferror) { + XCTAssertFalse(didSync, "Item did not sync"); + + NSError* error = (__bridge NSError*)cferror; + XCTAssertNotNil(error, "Error syncing item"); + XCTAssertEqual(error.domain, CKKSErrorDomain, "Error domain was CKKSErrorDomain"); + XCTAssertEqual(error.code, CKKSErrorViewIsPaused, "Error code is 'view is paused'"); + + [blockExpectation fulfill]; + }), @"_SecItemAddAndNotifyOnSync succeeded"); + + OCMVerifyAllWithDelay(self.mockDatabase, 10); + + [self waitForExpectationsWithTimeout:5.0 handler:nil]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/tests/CKKSTests+LockStateTracker.m b/keychain/ckks/tests/CKKSTests+LockStateTracker.m index 3219d033..96307695 100644 --- a/keychain/ckks/tests/CKKSTests+LockStateTracker.m +++ b/keychain/ckks/tests/CKKSTests+LockStateTracker.m @@ -4,52 +4,31 @@ #import #import "keychain/ckks/CKKSLockStateTracker.h" +#import "keychain/ckks/tests/CKKSMockLockStateProvider.h" #import "tests/secdmockaks/mockaks.h" @interface CKKSTests_LockStateTracker : XCTestCase -@property bool aksLockState; -@property (nullable) id mockLockStateTracker; + +@property CKKSMockLockStateProvider* lockStateProvider; @property CKKSLockStateTracker* lockStateTracker; @end @implementation CKKSTests_LockStateTracker -@synthesize aksLockState = _aksLockState; - - (void)setUp { [super setUp]; - self.aksLockState = false; // Lie and say AKS is always unlocked - self.mockLockStateTracker = OCMClassMock([CKKSLockStateTracker class]); - OCMStub([self.mockLockStateTracker queryAKSLocked]).andCall(self, @selector(aksLockState)); - - self.lockStateTracker = [[CKKSLockStateTracker alloc] init]; - + self.lockStateProvider = [[CKKSMockLockStateProvider alloc] initWithCurrentLockStatus:NO]; + self.lockStateTracker = [[CKKSLockStateTracker alloc] initWithProvider:self.lockStateProvider]; [SecMockAKS reset]; } - (void)tearDown { - [self.mockLockStateTracker stopMocking]; + self.lockStateProvider = nil; self.lockStateTracker = nil; } -- (bool)aksLockState -{ - return _aksLockState; -} - -- (void)setAksLockState:(bool)aksLockState -{ - - if(aksLockState) { - [SecMockAKS lockClassA]; - } else { - [SecMockAKS unlockAllClasses]; - } - _aksLockState = aksLockState; -} - - (void)testLockedBehindOurBack { /* @@ -66,7 +45,7 @@ XCTAssertFalse([self.lockStateTracker isLockedError:fileError], "file errors are not lock errors"); XCTAssertFalse([self.lockStateTracker isLocked], "should be unlocked after lock failure"); - self.aksLockState = true; + self.lockStateProvider.aksCurrentlyLocked = true; XCTAssertFalse([self.lockStateTracker isLocked], "should be reporting unlocked since we 'missed' the notification"); XCTAssertFalse([self.lockStateTracker isLockedError:fileError], "file errors are not lock errors"); @@ -75,7 +54,7 @@ XCTAssertTrue([self.lockStateTracker isLockedError:lockError], "errSecInteractionNotAllowed is a lock errors"); XCTAssertTrue([self.lockStateTracker isLocked], "should be locked after lock failure"); - self.aksLockState = false; + self.lockStateProvider.aksCurrentlyLocked = false; [self.lockStateTracker recheck]; XCTAssertFalse([self.lockStateTracker isLocked], "should be unlocked"); @@ -83,7 +62,7 @@ - (void)testWaitForUnlock { - self.aksLockState = true; + self.lockStateProvider.aksCurrentlyLocked = true; [self.lockStateTracker recheck]; XCTestExpectation* expectation = [self expectationWithDescription: @"unlock occurs"]; @@ -96,7 +75,7 @@ [queue addOperation:unlockEvent]; - self.aksLockState = false; + self.lockStateProvider.aksCurrentlyLocked = false; [self.lockStateTracker recheck]; [self waitForExpectations:@[expectation] timeout:5]; diff --git a/keychain/ckks/tests/CKKSTests+MultiZone.h b/keychain/ckks/tests/CKKSTests+MultiZone.h index 1d0b619b..57207e33 100644 --- a/keychain/ckks/tests/CKKSTests+MultiZone.h +++ b/keychain/ckks/tests/CKKSTests+MultiZone.h @@ -44,6 +44,11 @@ @property FakeCKZone* limitedZone; @property (readonly) ZoneKeys* limitedZoneKeys; +@property CKRecordZoneID* passwordsZoneID; +@property CKKSKeychainView* passwordsView; +@property FakeCKZone* passwordsZone; +@property (readonly) ZoneKeys* passwordsZoneKeys; + - (void)saveFakeKeyHierarchiesToLocalDatabase; - (void)putFakeDeviceStatusesInCloudKit; - (void)putFakeKeyHierachiesInCloudKit; diff --git a/keychain/ckks/tests/CKKSTests+MultiZone.m b/keychain/ckks/tests/CKKSTests+MultiZone.m index f3179612..a49b1841 100644 --- a/keychain/ckks/tests/CKKSTests+MultiZone.m +++ b/keychain/ckks/tests/CKKSTests+MultiZone.m @@ -7,6 +7,9 @@ #import #include +#import +#import +#import #import "keychain/ckks/tests/CloudKitMockXCTest.h" #import "keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h" @@ -17,11 +20,13 @@ #import "keychain/ckks/CKKSKey.h" #import "keychain/ckks/CKKSOutgoingQueueEntry.h" #import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSStates.h" #import "keychain/ckks/CKKSSynchronizeOperation.h" #import "keychain/ckks/CKKSViewManager.h" #import "keychain/ckks/CKKSZoneStateEntry.h" #import "keychain/ckks/CKKSManifest.h" +#import "keychain/ckks/tests/CKKSTests+MultiZone.h" #import "keychain/ckks/tests/MockCloudKit.h" #pragma clang diagnostic push @@ -37,43 +42,7 @@ #include #pragma clang diagnostic pop -@interface CloudKitKeychainSyncingMultiZoneTestsBase : CloudKitKeychainSyncingMockXCTest - -@property CKRecordZoneID* engramZoneID; -@property CKKSKeychainView* engramView; -@property FakeCKZone* engramZone; -@property (readonly) ZoneKeys* engramZoneKeys; - -@property CKRecordZoneID* manateeZoneID; -@property CKKSKeychainView* manateeView; -@property FakeCKZone* manateeZone; -@property (readonly) ZoneKeys* manateeZoneKeys; - -@property CKRecordZoneID* autoUnlockZoneID; -@property CKKSKeychainView* autoUnlockView; -@property FakeCKZone* autoUnlockZone; -@property (readonly) ZoneKeys* autoUnlockZoneKeys; - -@property CKRecordZoneID* healthZoneID; -@property CKKSKeychainView* healthView; -@property FakeCKZone* healthZone; -@property (readonly) ZoneKeys* healthZoneKeys; - -@property CKRecordZoneID* applepayZoneID; -@property CKKSKeychainView* applepayView; -@property FakeCKZone* applepayZone; -@property (readonly) ZoneKeys* applepayZoneKeys; - -@property CKRecordZoneID* homeZoneID; -@property CKKSKeychainView* homeView; -@property FakeCKZone* homeZone; -@property (readonly) ZoneKeys* homeZoneKeys; - -@property CKRecordZoneID* limitedZoneID; -@property CKKSKeychainView* limitedView; -@property FakeCKZone* limitedZone; -@property (readonly) ZoneKeys* limitedZoneKeys; - +@interface CloudKitKeychainSyncingMultiZoneTestsBase () @end @implementation CloudKitKeychainSyncingMultiZoneTestsBase @@ -83,6 +52,46 @@ [super setUp]; } +- (NSSet*)managedViewList { + NSMutableSet* parentSet = [[super managedViewList] mutableCopy]; + [parentSet addObject:@"Passwords"]; + return parentSet; +} + +// Make a policy as normal for most views, but Passwords is special +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewList +{ + NSMutableArray* rules = [NSMutableArray array]; + + for(NSString* viewName in self.managedViewList) { + TPPBPolicyKeyViewMapping* mapping = [[TPPBPolicyKeyViewMapping alloc] init]; + mapping.view = viewName; + + // The real passwords view is on com.appple.cfnetwork, but for these tests, let's just use the sbd agrp (because of how the entitlements are specified) + if([viewName isEqualToString:@"Passwords"]) { + mapping.matchingRule = [TPDictionaryMatchingRule fieldMatch:@"agrp" + fieldRegex:[NSString stringWithFormat:@"^com\\.apple\\.sbd$"]]; + } else { + mapping.matchingRule = [TPDictionaryMatchingRule fieldMatch:@"vwht" + fieldRegex:[NSString stringWithFormat:@"^%@$", viewName]]; + } + + [rules addObject:mapping]; + } + + NSSet* viewList = [self managedViewList]; + TPSyncingPolicy* policy = [[TPSyncingPolicy alloc] initWithModel:@"test-policy" + version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"] + viewList:viewList + priorityViews:[NSSet set] + userControllableViews:[NSSet set] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED + viewsToPiggybackTLKs:[viewList containsObject:@"Passwords"] ? [NSSet setWithObject:@"Passwords"] : [NSSet set] + keyViewMapping:rules]; + + return policy; +} + - (void)setUp { SecCKKSSetSyncManifests(false); SecCKKSSetEnforceManifests(false); @@ -149,6 +158,19 @@ XCTAssertNotNil(self.limitedView, "CKKSViewManager created the LimitedPeersAllowed view"); [self.ckksViews addObject:self.limitedView]; [self.ckksZones addObject:self.limitedZoneID]; + + self.passwordsZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"Passwords" ownerName:CKCurrentUserDefaultName]; + self.passwordsZone = [[FakeCKZone alloc] initZone: self.passwordsZoneID]; + self.zones[self.passwordsZoneID] = self.passwordsZone; + self.passwordsView = [[CKKSViewManager manager] findOrCreateView:@"Passwords"]; + XCTAssertNotNil(self.passwordsView, "should have a passwords ckks view"); + XCTAssertNotNil(self.passwordsView, "CKKSViewManager created the Passwords view"); + [self.ckksViews addObject:self.passwordsView]; + [self.ckksZones addObject:self.passwordsZoneID]; + + // These tests, at least, will use the policy codepaths! + [self.injectedManager setOverrideCKKSViewsFromPolicy:YES]; + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; } + (void)tearDown { @@ -186,6 +208,14 @@ [self.homeView waitUntilAllOperationsAreFinished]; self.homeView = nil; + [self.limitedView halt]; + [self.limitedView waitUntilAllOperationsAreFinished]; + self.limitedView = nil; + + [self.passwordsView halt]; + [self.passwordsView waitUntilAllOperationsAreFinished]; + self.passwordsView = nil; + [super tearDown]; } @@ -211,6 +241,7 @@ [self putFakeDeviceStatusInCloudKit: self.applepayZoneID]; [self putFakeDeviceStatusInCloudKit: self.homeZoneID]; [self putFakeDeviceStatusInCloudKit: self.limitedZoneID]; + [self putFakeDeviceStatusInCloudKit: self.passwordsZoneID]; } - (void)putFakeKeyHierachiesInCloudKit{ @@ -221,6 +252,7 @@ [self putFakeKeyHierarchyInCloudKit: self.applepayZoneID]; [self putFakeKeyHierarchyInCloudKit: self.homeZoneID]; [self putFakeKeyHierarchyInCloudKit: self.limitedZoneID]; + [self putFakeKeyHierarchyInCloudKit: self.passwordsZoneID]; } - (void)saveTLKsToKeychain{ @@ -231,6 +263,7 @@ [self saveTLKMaterialToKeychain:self.applepayZoneID]; [self saveTLKMaterialToKeychain:self.homeZoneID]; [self saveTLKMaterialToKeychain:self.limitedZoneID]; + [self saveTLKMaterialToKeychain:self.passwordsZoneID]; } - (void)deleteTLKMaterialsFromKeychain{ @@ -241,6 +274,7 @@ [self deleteTLKMaterialFromKeychain: self.applepayZoneID]; [self deleteTLKMaterialFromKeychain: self.homeZoneID]; [self deleteTLKMaterialFromKeychain:self.limitedZoneID]; + [self deleteTLKMaterialFromKeychain:self.passwordsZoneID]; } - (void)waitForKeyHierarchyReadinesses { @@ -251,6 +285,7 @@ [self.applepayView waitForKeyHierarchyReadiness]; [self.homeView waitForKeyHierarchyReadiness]; [self.limitedView waitForKeyHierarchyReadiness]; + [self.passwordsView waitForKeyHierarchyReadiness]; } - (void)expectCKKSTLKSelfShareUploads { @@ -424,6 +459,114 @@ [self waitForExpectations:@[pcsChanged] timeout:0.2]; } +- (void)testMultipleZoneAdd { + [self saveFakeKeyHierarchiesToLocalDatabase]; // Make life easy for this test. + + // Let the horses loose + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded to the 'LimitedPeersAllowed' view + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.limitedZoneID]; + [self addGenericPassword: @"data" account: @"account-delete-me-limited-peers" viewHint:(NSString*)kSecAttrViewHintLimitedPeersAllowed]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // We expect a single record to be uploaded to the 'atv' home + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.homeZoneID]; + [self addGenericPassword: @"data" account: @"account-delete-me-home" viewHint:(NSString*)kSecAttrViewHintHome]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + OCMVerifyAllWithDelay(self.mockCKKSViewManager, 10); +} + +- (void)testMultipleZoneDelete { + [self saveFakeKeyHierarchiesToLocalDatabase]; // Make life easy for this test. + + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.limitedZoneID]; + [self addGenericPassword: @"data" account: @"account-delete-me-limited-peers" viewHint:(NSString*)kSecAttrViewHintLimitedPeersAllowed]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.homeZoneID]; + [self addGenericPassword: @"data" account: @"account-delete-me-home" viewHint:(NSString*)kSecAttrViewHintHome]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + // We expect a single record to be deleted from the ATV zone + [self expectCKDeleteItemRecords:1 zoneID:self.homeZoneID]; + [self deleteGenericPassword:@"account-delete-me-home"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // Now we expect a single record to be deleted from the test zone + [self expectCKDeleteItemRecords:1 zoneID:self.limitedZoneID]; + [self deleteGenericPassword:@"account-delete-me-limited-peers"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testAddAndReceiveDeleteForSafariPasswordItem { + [self saveFakeKeyHierarchiesToLocalDatabase]; // Make life easy for this test. + + [self startCKKSSubsystem]; + + XCTestExpectation* passwordChanged = [self expectChangeForView:self.passwordsView.zoneName]; + + // We expect a single record to be uploaded to the Passwords view. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.passwordsZoneID]; + + [self addGenericPassword:@"data" + account:@"account-delete-me" + access:(id)kSecAttrAccessibleWhenUnlocked + viewHint:nil + accessGroup:@"com.apple.sbd" + expecting:errSecSuccess + message:@"Item for Password view"]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForExpectations:@[passwordChanged] timeout:1]; + [self waitForCKModifications]; + + [self waitForKeyHierarchyReadinesses]; + [self.passwordsView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + + // Ensure that we catch up to the newest CK change token so our fake cloudkit will notice the delete at fetch time + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.passwordsView waitForFetchAndIncomingQueueProcessing]; + + // Now, the item is deleted. Do we properly remove it? + CKRecord* itemRecord = nil; + for(CKRecord* record in [self.passwordsZone.currentDatabase allValues]) { + if([record.recordType isEqualToString:SecCKRecordItemType]) { + itemRecord = record; + break; + } + } + XCTAssertNotNil(itemRecord, "Should have found the item in the password zone"); + + NSDictionary *query = @{(id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.sbd", + (id)kSecAttrAccount : @"account-delete-me", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecMatchLimit : (id)kSecMatchLimitOne, + (id)kSecReturnData : (id)kCFBooleanTrue, + }; + + CFTypeRef item = NULL; + XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should still exist"); + XCTAssertNotNil((__bridge id)item, "An item should have been found"); + CFReleaseNull(item); + + // Now, the item is deleted. The passwords view should delete the local item, even though it has the wrong 'vwht' on disk. + XCTAssertNotNil(self.passwordsZone.currentDatabase[itemRecord.recordID], "Record should exist in fake CK"); + [self.passwordsZone deleteCKRecordIDFromZone:itemRecord.recordID]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.passwordsView waitForFetchAndIncomingQueueProcessing]; + + XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should no longer exist"); + XCTAssertNil((__bridge id)item, "No item should have been found"); +} + - (void)testAddOtherViewHintItem { [self saveFakeKeyHierarchiesToLocalDatabase]; // Make life easy for this test. @@ -431,21 +574,55 @@ // We expect no uploads to CKKS. [self addGenericPassword: @"data" account: @"account-delete-me-no-viewhint"]; - [self addGenericPassword: @"data" account: @"account-delete-me-password" viewHint:(NSString*) kSOSViewAutofillPasswords]; + [self addGenericPassword: @"data" account: @"account-delete-me-password" viewHint:(NSString*) kSOSViewBackupBagV0]; sleep(1); OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testUploadItemsAddedBeforeStart { + [self addGenericPassword:@"data" + account:@"account-delete-me" + access:(id)kSecAttrAccessibleAfterFirstUnlock + viewHint:nil + accessGroup:@"com.apple.sbd" + expecting:errSecSuccess + message:@"Item for Password view"]; + + [self addGenericPassword:@"data" + account:@"account-delete-me-2" + access:(id)kSecAttrAccessibleAfterFirstUnlock + viewHint:nil + accessGroup:@"com.apple.sbd" + expecting:errSecSuccess + message:@"Item for Password view"]; + + [self addGenericPassword:@"data" account:@"account-delete-me-limited-peers" viewHint:(NSString*)kSecAttrViewHintLimitedPeersAllowed]; + + NSError* error = nil; + NSDictionary* currentOQEs = [CKKSOutgoingQueueEntry countsByStateInZone:self.passwordsZoneID error:&error]; + XCTAssertNil(error, "Should be no error counting OQEs"); + XCTAssertEqual(0, currentOQEs.count, "Should be no OQEs"); + + [self saveFakeKeyHierarchiesToLocalDatabase]; // Make life easy for this test. + + // Now CKKS starts up + // Upon sign in, these items should be uploaded + [self expectCKModifyItemRecords:2 currentKeyPointerRecords:1 zoneID:self.passwordsZoneID + checkItem:[self checkClassCBlock:self.passwordsZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.limitedZoneID]; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.passwordsView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + - (void)testReceiveItemInView { [self saveFakeKeyHierarchiesToLocalDatabase]; // Make life easy for this test. [self startCKKSSubsystem]; - for(CKRecordZoneID* zoneID in self.ckksZones) { - [self expectCKKSTLKSelfShareUpload:zoneID]; - } - [self waitForKeyHierarchyReadinesses]; + [self.engramView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; [self findGenericPassword:@"account-delete-me" expecting:errSecItemNotFound]; @@ -455,10 +632,15 @@ XCTestExpectation* engramChanged = [self expectChangeForView:self.engramZoneID.zoneName]; XCTestExpectation* pcsChanged = [self expectChangeForView:@"PCS"]; - // Trigger a notification (with hilariously fake data) - [self.engramView notifyZoneChange:nil]; + self.silentFetchesAllowed = false; + [self expectCKFetch]; + // Trigger a notification (with hilariously fake data) + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); [self.engramView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:@"account-delete-me" expecting:errSecSuccess]; [self waitForExpectations:@[engramChanged] timeout:1]; @@ -490,14 +672,12 @@ [self expectCKFetch]; // one to fail with a CKErrorChangeTokenExpired error [self expectCKFetch]; // and one to succeed - [self.manateeView dispatchSyncWithAccountKeys: ^bool { - [self.manateeView _onqueueKeyStateMachineRequestFetch]; - return true; - }]; + [self.manateeView.stateMachine handleFlag:CKKSFlagFetchRequested]; XCTAssertEqual(0, [self.manateeView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS should enter 'ready'"); - [self.manateeView waitForFetchAndIncomingQueueProcessing]; + // Don't cause another fetch, because the machinery might not be ready + [self.manateeView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -540,7 +720,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-all-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -594,7 +774,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-all-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -650,7 +830,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -742,15 +922,15 @@ self.manateeZone.limitFetchTo = manateeChangeToken1; // Attempt to trigger simultaneous key state resyncs. This is a horrible hack... - [self.manateeView dispatchSyncWithAccountKeys:^bool { + [self.manateeView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ self.manateeView.keyStateFullRefetchRequested = YES; - [self.manateeView _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; + [self.manateeView _onqueuePokeKeyStateMachine]; + return CKKSDatabaseTransactionCommit; }]; - [self.healthView dispatchSyncWithAccountKeys:^bool { + [self.healthView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ self.healthView.keyStateFullRefetchRequested = YES; - [self.healthView _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; + [self.healthView _onqueuePokeKeyStateMachine]; + return CKKSDatabaseTransactionCommit; }]; OCMVerifyAllWithDelay(self.mockDatabase, 20); diff --git a/keychain/ckks/tests/CKKSTests.m b/keychain/ckks/tests/CKKSTests.m index 1aaf5cd8..4b5a0edf 100644 --- a/keychain/ckks/tests/CKKSTests.m +++ b/keychain/ckks/tests/CKKSTests.m @@ -44,12 +44,12 @@ #import "keychain/ckks/CKKSKey.h" #import "keychain/ckks/CKKSOutgoingQueueEntry.h" #import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSStates.h" #import "keychain/ckks/CKKSSynchronizeOperation.h" #import "keychain/ckks/CKKSViewManager.h" #import "keychain/ckks/CKKSZoneStateEntry.h" #import "keychain/ckks/CKKSManifest.h" #import "keychain/ckks/CKKSAnalytics.h" -#import "keychain/ckks/CKKSHealKeyHierarchyOperation.h" #import "keychain/ckks/CKKSZoneChangeFetcher.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "keychain/ckks/CKKSPeer.h" @@ -57,6 +57,7 @@ #import "keychain/ckks/tests/MockCloudKit.h" #import "keychain/ckks/tests/CKKSTests.h" +#import "keychain/ot/ObjCImprovements.h" #import // break abstraction @@ -89,24 +90,56 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } -- (void)testActiveTLKS { +- (void)testActiveTLKs { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. // We expect a single record to be uploaded. [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; [self startCKKSSubsystem]; - [self addGenericPassword: @"data" account: @"account-delete-me"]; OCMVerifyAllWithDelay(self.mockDatabase, 20); - NSDictionary* tlks = [[CKKSViewManager manager] activeTLKs]; + NSError* localError = nil; + NSArray* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:NO error:&localError]; + XCTAssertNil(localError, "Should have no error fetching current TLKs"); - XCTAssertEqual([tlks count], (NSUInteger)1, "One TLK"); - XCTAssertNotNil(tlks[@"keychain"], "keychain have a UUID"); + XCTAssertEqual([tlks count], (NSUInteger)1, "Should have one TLK"); + XCTAssertEqualObjects(tlks[0].zoneID.zoneName, @"keychain", "should have a TLK for keychain"); + + XCTAssertEqualObjects(tlks[0].uuid, self.keychainZoneKeys.tlk.uuid, "should have the TLK matching cloudkit"); } +- (void)testActiveTLKsWhenMissing { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], @"Key state should have arrived at waitfortlk"); + + NSError* localError = nil; + NSArray* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:NO error:&localError]; + XCTAssertNil(localError, "Should have no error fetching current TLKs"); + + XCTAssertEqual([tlks count], (NSUInteger)0, "Should have zero TLKs"); +} + +- (void)testActiveTLKsWhenLocked { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + self.aksLockState = true; + [self.lockStateTracker recheck]; + + NSError* localError = nil; + NSArray* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:NO error:&localError]; + XCTAssertNotNil(localError, "Should have an error fetching current TLKs"); + + XCTAssertEqual([tlks count], (NSUInteger)0, "Should have zero TLKs"); +} - (void)testAddMultipleItems { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. @@ -135,13 +168,14 @@ [self.keychainView waitUntilAllOperationsAreFinished]; + // We expect an upload of the added item, once CKKS finds the UUID-less item and fixes it + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + SecCKKSTestSetDisableAutomaticUUID(true); [self addGenericPassword: @"data" account: @"account-delete-me-no-UUID" expecting:errSecSuccess message: @"Add item (no UUID) to keychain"]; - SecCKKSTestSetDisableAutomaticUUID(false); - // We then expect an upload of the added item - [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; + [self findGenericPassword:@"account-delete-me-no-UUID" expecting:errSecSuccess]; OCMVerifyAllWithDelay(self.mockDatabase, 20); } @@ -228,7 +262,7 @@ // Stop the reencrypt operation from happening self.keychainView.holdReencryptOutgoingItemsOperation = [CKKSGroupOperation named:@"reencrypt-hold" withBlock: ^{ - secnotice("ckks", "releasing reencryption hold"); + ckksnotice_global("ckks", "releasing reencryption hold"); }]; // The cloudkit operation finishes, letting the next OQO proceed (and set up the reencryption operation) @@ -241,7 +275,7 @@ // Pause outgoing queue operations to ensure the reencryption operation runs first self.keychainView.holdOutgoingQueueOperation = [CKKSGroupOperation named:@"outgoing-hold" withBlock: ^{ - secnotice("ckks", "releasing outgoing-queue hold"); + ckksnotice_global("ckks", "releasing outgoing-queue hold"); }]; // Run the reencrypt items operation to completion. @@ -277,7 +311,7 @@ // Stop the reencrypt operation from happening self.keychainView.holdReencryptOutgoingItemsOperation = [CKKSGroupOperation named:@"reencrypt-hold" withBlock: ^{ - secnotice("ckks", "releasing reencryption hold"); + ckksnotice_global("ckks", "releasing reencryption hold"); }]; // The cloudkit operation finishes, letting the next OQO proceed (and set up the reencryption operation) @@ -337,10 +371,10 @@ [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. NSString* account = @"fake-account"; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; - CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" zoneID:self.keychainZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; CKKSItem* item = [self newItem:ckrid withNewItemData:[self fakeRecordDictionary:account zoneID:self.keychainZoneID] key:self.keychainZoneKeys.classC]; XCTAssertNotNil(item, "Should be able to create a new fake item"); @@ -350,7 +384,7 @@ [oqe saveToDatabase:&error]; XCTAssertNil(error, "Shouldn't error saving new OQE to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; NSError *error = NULL; @@ -416,6 +450,35 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testDeleteItemAndReaddAtSameUUID { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded. + __block CKRecordID* itemRecordID = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + itemRecordID = record.recordID; + return YES; + }]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // We expect a single record to be deleted. + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + [self deleteGenericPassword:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item is readded. It should come back to its previous UUID. + XCTAssertNotNil(itemRecordID, "Should have an item record ID"); + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + XCTAssertEqualObjects(itemRecordID.recordName, record.recordID.recordName, "Uploaded item UUID should match previous upload"); + return YES; + }]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + - (void)testDeleteItemImmediatelyAfterModify { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. NSString* account = @"account-delete-me"; @@ -447,6 +510,68 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testDeleteItemDuringAddUpload { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + NSString* account = @"account-delete-me"; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:10*NSEC_PER_SEC], @"key state should enter 'ready'"); + + // We expect a single record to be uploaded. But, while that's happening, delete it via the API. + + XCTestExpectation *deleteBlock = [self expectationWithDescription:@"delete block called"]; + + WEAKIFY(self); + self.keychainZone.blockBeforeWriteOperation = ^() { + STRONGIFY(self); + [self deleteGenericPassword:account]; + self.keychainZone.blockBeforeWriteOperation = nil; + [deleteBlock fulfill]; + }; + + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + + // This should cause a deletion + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword:@"data" account:account]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self waitForExpectations: @[deleteBlock] timeout:5]; +} + +- (void)testDeleteItemDuringModificationUpload { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + NSString* account = @"account-delete-me"; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:10*NSEC_PER_SEC], @"key state should enter 'ready'"); + + // We expect a single record to be uploaded. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword: @"data" account: account]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // We expect a single modification record to be uploaded, and want to delete the item while the upload is ongoing + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID + checkItem:[self checkPasswordBlock:self.keychainZoneID account:account password:@"otherdata"]]; + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + + XCTestExpectation *deleteBlock = [self expectationWithDescription:@"delete block called"]; + + WEAKIFY(self); + self.keychainZone.blockBeforeWriteOperation = ^() { + STRONGIFY(self); + [self deleteGenericPassword:account]; + self.keychainZone.blockBeforeWriteOperation = nil; + [deleteBlock fulfill]; + }; + + [self updateGenericPassword:@"otherdata" account:account]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self waitForExpectations: @[deleteBlock] timeout:5]; +} + - (void)testDeleteItemAfterFetchAfterModify { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. NSString* account = @"account-delete-me"; @@ -470,24 +595,23 @@ // Right now, the write in CloudKit is pending. Place a hold on outgoing queue processing // Place a hold on processing the outgoing queue. - CKKSResultOperation* blockOutgoing = [CKKSResultOperation operationWithBlock:^{ - secnotice("ckks", "Outgoing queue hold released."); + self.keychainView.holdOutgoingQueueOperation = [CKKSResultOperation named:@"outgoing-queue-hold" + withBlock:^{ + ckksnotice_global("ckks", "Outgoing queue hold released."); }]; - blockOutgoing.name = @"outgoing-queue-hold"; - CKKSResultOperation* outgoingQueueOperation = [self.keychainView processOutgoingQueueAfter:blockOutgoing ckoperationGroup:nil]; [self deleteGenericPassword:account]; - [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; // Release the CK modification hold //[self releaseCloudKitModificationHold]; // And cause a fetch + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - [self.operationQueue addOperation:blockOutgoing]; - [outgoingQueueOperation waitUntilFinished]; + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); } @@ -516,16 +640,16 @@ [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; // Ensure nothing is in the outgoing queue - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* uuids = [CKKSOutgoingQueueEntry allUUIDs:self.keychainZoneID error:&error]; XCTAssertNil(error, "should be no error fetching uuids"); XCTAssertEqual(uuids.count, 0u, "There should be zero OQEs"); - return false; }]; // And a simple fetch doesn't bring it back + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:account expecting:errSecItemNotFound]; @@ -555,13 +679,15 @@ CFTypeRef item = NULL; XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should not yet exist"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); + CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone: ckr]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; + XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should exist now"); } @@ -591,9 +717,7 @@ } } - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword: @"account0" expecting:errSecSuccess]; @@ -631,16 +755,49 @@ [self.keychainZone addToZone: ckr2]; // We expect a delete operation with the "higher" UUID. - [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + [self expectCKDeleteItemRecords:1 + zoneID:self.keychainZoneID + expectedOperationGroupName:@"incoming-queue-response"]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil];; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should exist now"); [self waitForCKModifications]; XCTAssertNil(self.keychainZone.currentDatabase[ckr2.recordID], "Correct record was deleted from CloudKit"); + + // And the local item should have ckr's UUID + [self checkGenericPasswordStoredUUID:ckr.recordID.recordName account:@"account-delete-me"]; +} + +- (void)testReceiveCorruptedItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + [self startCKKSSubsystem]; + + [self findGenericPassword:@"account-delete-me" expecting:errSecItemNotFound]; + + CKRecord* ckr = [self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; + + // I don't know of any codepaths that cause this, but it apparently has happened. + ckr[SecCKRecordWrappedKeyKey] = nil; + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // The item still shouldn't exist, because it was corrupted in flight + [self findGenericPassword:@"account-delete-me" expecting:errSecItemNotFound]; + + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ + NSError* error = nil; + NSArray* iqes = [CKKSIncomingQueueEntry all:&error]; + XCTAssertNil(error, "No error loading IQEs"); + XCTAssertNotNil(iqes, "Could load IQEs"); + XCTAssertEqual(iqes.count, 1u, "Incoming queue has one item"); + XCTAssertEqualObjects(iqes[0].state, SecCKKSStateNew, "Item state should be 'new'"); + }]; } -(void)testReceiveItemDelete { @@ -651,30 +808,143 @@ (id)kSecAttrAccessGroup : @"com.apple.security.ckks", (id)kSecAttrAccount : @"account-delete-me", (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecReturnAttributes : @YES, (id)kSecMatchLimit : (id)kSecMatchLimitOne, }; - CFTypeRef item = NULL; - XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should not yet exist"); + CFTypeRef cfitem = NULL; + XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &cfitem), "item should not yet exist"); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName: @"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone: ckr]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should exist now"); - CFReleaseNull(item); + XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &cfitem), "item should exist now"); + + NSDictionary* item = (NSDictionary*) CFBridgingRelease(cfitem); + cfitem = NULL; + NSDate* itemModificationDate = item[(id)kSecAttrModificationDate]; + XCTAssertNotNil(itemModificationDate, "Should have a modification date"); // Trigger a delete [self.keychainZone deleteCKRecordIDFromZone: [ckr recordID]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should no longer exist"); + XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &cfitem), "item should no longer exist"); + CFReleaseNull(cfitem); + + // Now, double-check the tombstone. Its modification date should be derived from the item's mdat. + NSDictionary *tombquery = @{(id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : @"account-delete-me", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrTombstone : @YES, + (id)kSecReturnAttributes : @YES, + (id)kSecMatchLimit : (id)kSecMatchLimitOne,}; + + CFTypeRef cfref = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)tombquery, &cfref); + XCTAssertEqual(status, errSecSuccess, "Should have found a tombstone"); + + NSDictionary* tombstone = (NSDictionary*)CFBridgingRelease(cfref); + XCTAssertNotNil(tombstone, "Should have found a tombstone"); + + NSDate* tombstoneModificationDate = tombstone[(id)kSecAttrModificationDate]; + XCTAssertEqual([tombstoneModificationDate compare:itemModificationDate], NSOrderedDescending, "tombstone should be later than item"); + + NSTimeInterval tombestoneDelta = [tombstoneModificationDate timeIntervalSinceDate:itemModificationDate]; + XCTAssertGreaterThan(tombestoneDelta, 0, "Delta should be positive"); + XCTAssertLessThan(tombestoneDelta, 5, "tombstone mdat should be no later than 5s after item mdat"); + + // And just as a sanity, mdat is already far ago, right? + NSTimeInterval itemDelta = [[NSDate date] timeIntervalSinceDate:itemModificationDate]; + XCTAssertGreaterThan(itemDelta, 10, "item mdat should at least 10s in the past"); +} + +- (void)testReceiveTombstoneItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + [self startCKKSSubsystem]; + + NSString* account = @"account-delete-me"; + + CKRecord* ckr = [self createFakeTombstoneRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" account:account]; + [self.keychainZone addToZone:ckr]; + + // This device should delete the tombstone entry + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // The tombstone shouldn't exist + NSDictionary *tombquery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : account, + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecReturnAttributes : @YES, + (id)kSecAttrTombstone : @YES, + }; + + CFTypeRef cftype = NULL; + XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef)tombquery, &cftype), "item should not exist now"); + XCTAssertNil((__bridge id)cftype, "Should have found no tombstones"); + + // And the delete should occur + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ + NSError* error = nil; + NSArray* uuids = [CKKSIncomingQueueEntry allUUIDs:self.keychainZoneID + error:&error]; + XCTAssertNil(error, "should be no error fetching uuids"); + XCTAssertEqual(uuids.count, 0u, "There should be zero IQEs"); + }]; +} + +- (void)testReceiveItemDeleteAndReaddAtDifferentUUIDInSameFetch { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + [self startCKKSSubsystem]; + + NSString* itemAccount = @"account-delete-me"; + [self findGenericPassword:itemAccount expecting:errSecItemNotFound]; + + NSString* uuidOriginalItem = @"7B598D31-F9C5-481E-98AC-5A507ACB2D85"; + NSString* uuidGreater = @"7B598D31-FFFF-FFFF-98AC-5A507ACB2D85"; + + CKRecord* ckr = [self createFakeRecord:self.keychainZoneID recordName:uuidOriginalItem]; + CKRecord* ckrGreater = [self createFakeRecord:self.keychainZoneID recordName:uuidGreater]; + + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + [self checkGenericPasswordStoredUUID:uuidOriginalItem account:itemAccount]; + + // Now, the item is deleted and re-added with a greater UUID + [self.keychainZone deleteCKRecordIDFromZone:[ckr recordID]]; + [self.keychainZone addToZone:ckrGreater]; + + // This node should not upload anything. + [[self.mockDatabase reject] addOperation:[OCMArg any]]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + + // Item should still exist. + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + [self checkGenericPasswordStoredUUID:uuidGreater account:itemAccount]; } -(void)testReceiveItemPhantomDelete { @@ -691,13 +961,13 @@ CFTypeRef item = NULL; XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should not yet exist"); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName: @"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone: ckr]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should exist now"); @@ -709,7 +979,7 @@ [self.keychainZone deleteCKRecordIDFromZone: [ckr recordID]]; // and add another, incorrect IQE - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ // Inefficient, but hey, it works CKRecord* record = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-FFFF-FFFF-5A507ACB2D85"]; CKKSItem* fakeItem = [[CKKSItem alloc] initWithCKRecord: record]; @@ -721,16 +991,16 @@ NSError* error = nil; XCTAssert([iqe saveToDatabase: &error], "Saved fake IQE to database"); XCTAssertNil(error, "No error saving fake IQE to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should no longer exist"); // The incoming queue should be empty - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* iqes = [CKKSIncomingQueueEntry all:&error]; XCTAssertNil(error, "No error loading IQEs"); @@ -747,23 +1017,21 @@ [self.keychainView waitUntilAllOperationsAreFinished]; // Place a hold on processing the outgoing queue. - CKKSResultOperation* blockOutgoing = [CKKSResultOperation operationWithBlock:^{ - secnotice("ckks", "Outgoing queue hold released."); + self.keychainView.holdOutgoingQueueOperation = [CKKSResultOperation named:@"outgoing-queue-hold" + withBlock:^{ + ckksnotice_global("ckks", "Outgoing queue hold released."); }]; - blockOutgoing.name = @"outgoing-queue-hold"; - CKKSResultOperation* outgoingQueueOperation = [self.keychainView processOutgoingQueueAfter:blockOutgoing ckoperationGroup:nil]; - CKKSResultOperation* blockIncoming = [CKKSResultOperation operationWithBlock:^{ - secnotice("ckks", "Incoming queue hold released."); + self.keychainView.holdIncomingQueueOperation = [CKKSResultOperation named:@"incoming-queue-hold" + withBlock:^{ + ckksnotice_global("ckks", "Incoming queue hold released."); }]; - blockIncoming.name = @"incoming-queue-hold"; - CKKSResultOperation* incomingQueueOperation = [self.keychainView processIncomingQueue:false after: blockIncoming]; [self addGenericPassword:@"localchange" account:@"account-delete-me"]; // Pull out the new item's UUID. __block NSString* itemUUID = nil; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* uuids = [CKKSOutgoingQueueEntry allUUIDs:self.keychainZoneID ?: [[CKRecordZoneID alloc] initWithZoneName:@"keychain" ownerName:CKCurrentUserDefaultName] @@ -773,21 +1041,20 @@ itemUUID = uuids[0]; XCTAssertNotNil(itemUUID, "Have a UUID for our new item"); - return false; }]; [self.keychainZone addToZone: [self createFakeRecord: self.keychainZoneID recordName: itemUUID]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [[self.keychainView.zoneChangeFetcher requestSuccessfulFetch:CKKSFetchBecauseTesting] waitUntilFinished]; // Allow the outgoing queue operation to proceed - [self.operationQueue addOperation:blockOutgoing]; - [outgoingQueueOperation waitUntilFinished]; + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; // Allow the incoming queue operation to proceed - [self.operationQueue addOperation:blockIncoming]; - [incomingQueueOperation waitUntilFinished]; + [self.operationQueue addOperation:self.keychainView.holdIncomingQueueOperation]; + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; [self checkGenericPassword:@"data" account:@"account-delete-me"]; @@ -802,15 +1069,16 @@ [self.keychainView waitUntilAllOperationsAreFinished]; // Place a hold on processing the outgoing queue. + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.keychainView.holdOutgoingQueueOperation = [CKKSResultOperation named:@"outgoing-queue-hold" withBlock:^{ - secnotice("ckks", "Outgoing queue hold released."); + ckksnotice_global("ckks", "Outgoing queue hold released."); }]; [self addGenericPassword:@"localchange" account:@"account-delete-me"]; // Pull out the new item's UUID. __block NSString* itemUUID = nil; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* uuids = [CKKSOutgoingQueueEntry allUUIDs:self.keychainZoneID ?: [[CKRecordZoneID alloc] initWithZoneName:@"keychain" ownerName:CKCurrentUserDefaultName] @@ -820,7 +1088,6 @@ itemUUID = uuids[0]; XCTAssertNotNil(itemUUID, "Have a UUID for our new item"); - return false; }]; // Add a second item: this item should be uploaded after the failure of the first item @@ -885,7 +1152,6 @@ uint64_t n = OSSwapHostToLittleConstInt64([future_number_field unsignedLongValue]); authenticatedData[@"future_number_field"] = [NSData dataWithBytes:&n length:sizeof(n)]; - cipheritem.encitem = [CKKSItemEncrypter encryptDictionary:item key:itemkey.aessivkey authenticatedData:authenticatedData error:&error]; XCTAssertNil(error, "no error encrypting object"); XCTAssertNotNil(cipheritem.encitem, "Recieved ciphertext"); @@ -897,6 +1163,7 @@ ckr[@"server_new_server_field"] = future_server_field; [self.keychainZone addToZone:ckr]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword, @@ -966,6 +1233,7 @@ [self.keychainZone addToZone:[cipheritem CKRecordWithZoneID: recordID.zoneID]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword, @@ -989,20 +1257,153 @@ XCTAssertEqualObjects(newRecord[SecCKRecordEncryptionVersionKey], [NSNumber numberWithInteger:(int) CKKSItemEncryptionVersion2], "Uploaded using encv2"); } +- (void)testLocalUpdateToTombstoneItem { + // Some CKKS clients may accidentally upload entries with tomb=1. + // We should delete these items with extreme predjudice. + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword: @"data" account: @"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // We expect a single record to be deleted. + [self expectCKDeleteItemRecords: 1 zoneID:self.keychainZoneID]; + [self deleteGenericPassword:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // Now, SOS comes along and updates the tombstone + // CKKS should _not_ try to upload a tombstone + NSDictionary *tombquery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : @"account-delete-me", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrTombstone : @YES, + }; + + NSDictionary* update = @{ + (id)kSecAttrModificationDate : [NSDate date], + }; + + __block CFErrorRef cferror = NULL; + kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { + bool ok = kc_transaction_type(dbt, kSecDbExclusiveRemoteSOSTransactionType, &cferror, ^bool { + OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)tombquery, (__bridge CFDictionaryRef)update); + XCTAssertEqual(status, errSecSuccess, "Should have been able to update a tombstone"); + + return true; + }); + return ok; + }); + + XCTAssertNil((__bridge NSError*)cferror, "Should be no error updating a tombstone"); + + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; +} + +- (void)testIgnoreUpdateToModificationDateItem { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword:@"data" account: @"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // Nothing more should be uploaded + NSDictionary *query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : @"account-delete-me", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + }; + + NSDictionary* update = @{ + (id)kSecAttrModificationDate : [NSDate date], + }; + + __block CFErrorRef cferror = NULL; + kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { + bool ok = kc_transaction_type(dbt, kSecDbExclusiveRemoteSOSTransactionType, &cferror, ^bool { + OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update); + XCTAssertEqual(status, errSecSuccess, "Should have been able to update the item"); + + return true; + }); + return ok; + }); + + XCTAssertNil((__bridge NSError*)cferror, "Should be no error updating just the mdat"); + + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; +} + - (void)testUploadPagination { - [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + [self saveTLKMaterialToKeychain:self.keychainZoneID]; + [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; for(size_t count = 0; count < 250; count++) { [self addGenericPassword: @"data" account: [NSString stringWithFormat:@"account-delete-me-%03lu", count]]; } - [self startCKKSSubsystem]; - [self expectCKModifyItemRecords: SecCKKSOutgoingQueueItemsAtOnce currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; [self expectCKModifyItemRecords: SecCKKSOutgoingQueueItemsAtOnce currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; [self expectCKModifyItemRecords: 50 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // For the next 5 seconds, try to add and then find an item. Each attempt should be fairly quick: no long multisecond pauses while CKKS Scans + NSTimeInterval elapsed = 0; + uint64_t count = 0; + while(elapsed < 10) { + NSDate* begin = [NSDate now]; + + NSString* account = [NSString stringWithFormat:@"non-syncable-%d", (int)count]; + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : account, + (id)kSecAttrSynchronizable : @NO, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecValueData : [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], + }; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess, @"Should be able to add nonsyncable item"); + ckksnotice("ckkstest", self.keychainView, "SecItemAdd of %@ successful", account); + + NSDictionary *findQuery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : account, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecMatchLimit : (id)kSecMatchLimitOne, + }; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)findQuery, NULL), errSecSuccess, "Finding item %@", account); + ckksnotice("ckkstest", self.keychainView, "SecItemCopyMatching of %@ successful", account); + + NSDate* end = [NSDate now]; + NSTimeInterval delta = [end timeIntervalSinceDate:begin]; + + XCTAssertLessThan(delta, 2, @"Keychain API should respond in two seconds"); + ckksnotice("ckkstest", self.keychainView, "SecItemAdd/SecItemCopyMatching pair of %@ took %.4fs", account, delta); + + usleep(10000); // sleep for 10ms, to let some other things get done + + // And retake the time elasped for the overall count + elapsed += [[NSDate now] timeIntervalSinceDate:begin]; + count += 1; + } + OCMVerifyAllWithDelay(self.mockDatabase, 40); + + [self measureBlock:^{ + CKKSScanLocalItemsOperation* scan = [self.keychainView scanLocalItems:@"test-speed"]; + [scan waitUntilFinished]; + }]; } - (void)testUploadInitialKeyHierarchy { @@ -1027,7 +1428,7 @@ for(CKKSKeychainView* view in self.ckksViews) { XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:40*NSEC_PER_SEC], @"key state should enter 'waitfortlkcreation' (view %@)", view); - [keysetOps addObject: [view findKeySet]]; + [keysetOps addObject: [view findKeySet:NO]]; } // Now that we've kicked them all off, wait for them to resolve (and nudge each one, as if a key was saved) @@ -1036,7 +1437,10 @@ CKKSCondition* viewProcess = view.keyHierarchyConditions[SecCKKSZoneKeyStateProcess]; [view keyStateMachineRequestProcess]; - XCTAssertNotEqual(0, [viewProcess wait:500*NSEC_PER_MSEC], "CKKS should not reprocess the key hierarchy, even if nudged"); + + // Since we do need to leave SecCKKSZoneKeyStateWaitForTLKUpload if a fetch occurs with new keys, make sure we do the right thing + XCTAssertEqual(0, [viewProcess wait:10*NSEC_PER_MSEC], "CKKS should reprocess the key hierarchy when nudged"); + XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKUpload] wait:40*NSEC_PER_SEC], @"key state should re-enter 'waitfortlkupload'"); } // The views should remain in waitfortlkcreation, and not go through process into an error @@ -1061,28 +1465,142 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); } + +- (void)testReceiveChangedKeySetFromWaitingForTLKUpload { + // Test starts with nothing in database. CKKS should get into the "please upload my keys" state + + [self startCKKSSubsystem]; + + // After each zone arrives in WaitForTLKCreation, new keys are uploaded + for(CKKSKeychainView* view in self.ckksViews) { + XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:40*NSEC_PER_SEC], @"key state should enter 'waitfortlkcreation' (view %@)", view); + } + + for(CKKSKeychainView* view in self.ckksViews) { + [self putFakeKeyHierarchyInCloudKit:view.zoneID]; + [self putFakeDeviceStatusInCloudKit:view.zoneID]; + } + + // If we ask the zones for their keysets, they should return the local set ready for upload + NSMutableArray*>* keysetOps = [NSMutableArray array]; + + for(CKKSKeychainView* view in self.ckksViews) { + [keysetOps addObject:[view findKeySet:NO]]; + } + + for(CKKSResultOperation* keysetOp in keysetOps) { + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, "Should be no error fetching keyset from CKKS"); + + CKRecordZoneID* zoneID = [[CKRecordZoneID alloc] initWithZoneName:keysetOp.zoneName + ownerName:CKCurrentUserDefaultName]; + ZoneKeys* zk = self.keys[zoneID]; + XCTAssertNotNil(zk, "Should have new zone keys for zone %@", keysetOp.zoneName); + XCTAssertNotEqualObjects(keysetOp.keyset.currentTLKPointer.currentKeyUUID, zk.tlk.uuid, "Fetched TLK and CK TLK should be different"); + } + + // Now, find the keysets again, asking for a fetch this time + NSMutableArray*>* fetchedKeysetOps = [NSMutableArray array]; + + for(CKKSKeychainView* view in self.ckksViews) { + [fetchedKeysetOps addObject:[view findKeySet:YES]]; + } + + for(CKKSResultOperation* keysetOp in fetchedKeysetOps) { + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, "Should be no error fetching keyset from CKKS"); + + CKRecordZoneID* zoneID = [[CKRecordZoneID alloc] initWithZoneName:keysetOp.zoneName + ownerName:CKCurrentUserDefaultName]; + ZoneKeys* zk = self.keys[zoneID]; + XCTAssertNotNil(zk, "Should have new zone keys for zone %@", keysetOp.zoneName); + XCTAssertEqualObjects(keysetOp.keyset.currentTLKPointer.currentKeyUUID, zk.tlk.uuid, "Fetched TLK and CK TLK should now match"); + } +} + - (void)testProvideKeysetFromNoTrust { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; [self startCKKSSubsystem]; - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortlkcreation'"); - // I'm not sure how CKKS ends up in 'waitfortrust' without a keyset, so force that state - // In 52301278, it occurred with some complex interaction of zone deletions, fetches, and trust operations - [self.keychainView dispatchSyncWithAccountKeys:^bool{ - [self.keychainView _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForTrust withError:nil]; - return true; - }]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'"); - CKKSResultOperation* keysetOp = [self.keychainView findKeySet]; + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; [keysetOp timeout:20*NSEC_PER_SEC]; [keysetOp waitUntilFinished]; XCTAssertNil(keysetOp.error, "Should be no error fetching a keyset"); } -// This test no longer is very interesting, since Octagon needs to handle lock states, not CKKS... +- (void)testProvideKeysetFromNoTrustWithRefetch { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'"); + + self.silentFetchesAllowed = false; + [self expectCKFetch]; + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:YES]; + [keysetOp timeout:20*NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + + XCTAssertNil(keysetOp.error, "Should be no error fetching a keyset"); + + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testProvideKeysetAfterReceivingTLKInNoTrust { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'"); + + // This isn't necessarily SOS, but perhaps SBD. + [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; + + // Still ends up in waitfortrust... + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'"); + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; + [keysetOp timeout:20*NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + + XCTAssertNil(keysetOp.error, "Should be no error fetching a keyset"); + XCTAssertNotNil(keysetOp.keyset, "Should have a keyset"); + XCTAssertNotNil(keysetOp.keyset.tlk, "Should have a TLK"); +} + +- (void)testProvideKeysetWhileActivelyLosingTrust { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + + [self.keychainView.stateMachine testPauseStateMachineAfterEntering:SecCKKSZoneKeyStateLoseTrust]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoseTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'lose-trust'"); + XCTAssertTrue([self.keychainView.stateMachine isPaused], @"State machine should be in a test pause"); + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; + + [self.keychainView.stateMachine testReleaseStateMachinePause:SecCKKSZoneKeyStateLoseTrust]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'"); + + [keysetOp timeout:20*NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + + XCTAssertNil(keysetOp.error, "Should be no error fetching a keyset"); + XCTAssertNotNil(keysetOp.keyset, "Should have a keyset"); + XCTAssertNil(keysetOp.keyset.tlk, "Should not have a TLK while without trust (and without receiving the tlk bits)"); +} + - (void)testUploadInitialKeyHierarchyAfterLockedStart { // 'Lock' the keybag self.aksLockState = true; @@ -1090,14 +1608,27 @@ [self startCKKSSubsystem]; - // Wait for the key hierarchy state machine to get stuck waiting for the unlock dependency. No uploads should occur. XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], @"Key state should get stuck in waitfortlkcreation"); + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; + + // Wait for the key hierarchy state machine to get stuck waiting for the unlock dependency. No uploads should occur. + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForUnlock] wait:20*NSEC_PER_SEC], @"Key state should get stuck in waitforunlock"); + // After unlock, the key hierarchy should be created. self.aksLockState = false; [self.lockStateTracker recheck]; - [self performOctagonTLKUpload:self.ckksViews]; + [keysetOp timeout:10 * NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, @"Should be no error performing keyset op"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKUpload] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortlkupload'"); + + NSArray* keyHierarchyRecords = [self putKeySetInCloudKit:keysetOp.keyset]; + [self.keychainView receiveTLKUploadRecords:keyHierarchyRecords]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should enter 'ready'"); // We expect a single class C record to be uploaded. [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; @@ -1106,6 +1637,55 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testExitWaitForTLKUploadIfTLKsCreated { + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], @"Key state should get stuck in waitfortlkcreation"); + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; + + [keysetOp timeout:10 * NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, @"Should be no error performing keyset op"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKUpload] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortlkupload'"); + + // But another device beats us to it! + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortlk'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testExitWaitForTLKUploadIfTLKsCreatedWhileNoTrust { + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], @"Key state should get stuck in waitfortlkcreation"); + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; + + [keysetOp timeout:10 * NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, @"Should be no error performing keyset op"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKUpload] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortlkupload'"); + + // But another device beats us to it! + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortrust'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + - (void)testLockImmediatelyAfterUploadingInitialKeyHierarchy { __weak __typeof(self) weakSelf = self; @@ -1157,7 +1737,7 @@ // Now, another device comes along and creates the hierarchy; we download it; and it and sends us the TLK [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [[self.keychainView.zoneChangeFetcher requestSuccessfulFetch:CKKSFetchBecauseTesting] waitUntilFinished]; self.aksLockState = false; @@ -1172,6 +1752,7 @@ [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; [self addGenericPassword: @"data" account: @"account-delete-me"]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should become 'ready'"); OCMVerifyAllWithDelay(self.mockDatabase, 20); } @@ -1214,13 +1795,23 @@ [self waitForCKModifications]; // We expect a single class C record to be uploaded. - [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + [self expectCKModifyItemRecords:1 + deletedRecords:0 + currentKeyPointerRecords:1 + zoneID:self.keychainZoneID + checkItem:[self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"] + expectedOperationGroupName:@"keychain-api-use"]; [self addGenericPassword: @"data" account: @"account-delete-me"]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // now, expect a single class A record to be uploaded - [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassABlock:self.keychainZoneID message:@"Object was encrypted under class A key in hierarchy"]]; + [self expectCKModifyItemRecords:1 + deletedRecords:0 + currentKeyPointerRecords:1 + zoneID:self.keychainZoneID + checkItem:[self checkClassABlock:self.keychainZoneID message:@"Object was encrypted under class A key in hierarchy"] + expectedOperationGroupName:@"keychain-api-use"]; XCTAssertEqual(errSecSuccess, SecItemAdd((__bridge CFDictionaryRef)@{ (id)kSecClass : (id)kSecClassGenericPassword, @@ -1228,6 +1819,7 @@ (id)kSecAttrAccessible: (id)kSecAttrAccessibleWhenUnlocked, (id)kSecAttrAccount : @"account-class-A", (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], }, NULL), @"Adding class A item"); OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -1375,7 +1967,7 @@ [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; // Also, CKKS _should_ be able to return the key hierarchy if asked before it starts - CKKSResultOperation* keysetOp = [self.keychainView findKeySet]; + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; NSDateComponents* offset = [[NSDateComponents alloc] init]; [offset setDay:-5]; @@ -1479,7 +2071,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -1492,8 +2084,6 @@ NSArray* currentkeys = [CKKSCurrentKeyPointer all: &error]; XCTAssertNil(error, "no error fetching current keys"); XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database"); - - return false; }]; } @@ -1558,7 +2148,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -1571,8 +2161,6 @@ NSArray* currentkeys = [CKKSCurrentKeyPointer all: &error]; XCTAssertNil(error, "no error fetching current keys"); XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database"); - - return false; }]; } @@ -1583,6 +2171,8 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should become 'ready'"); + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:@"classCItem" expecting:errSecItemNotFound]; @@ -1596,10 +2186,8 @@ XCTAssertNotNil(self.keychainZoneKeys.classA, "Have class A key for zone"); XCTAssertNotNil(self.keychainZoneKeys.classC, "Have class C key for zone"); - [self.keychainView dispatchSyncWithAccountKeys: ^bool { - [self.keychainView _onqueueKeyStateMachineRequestProcess]; - return true; - }]; + [self.keychainView.stateMachine handleFlag:CKKSFlagKeyStateProcessRequested]; + // And ensure we end up back in 'readypendingunlock': we have the keys, we're just locked now [self.keychainView waitForOperationsOfClass:[CKKSProcessReceivedKeysOperation class]]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReadyPendingUnlock] wait:20*NSEC_PER_SEC], @"Key state should become 'readypendingunlock'"); @@ -1607,7 +2195,9 @@ [self.keychainZone addToZone: [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" withAccount:@"classCItem" key:self.keychainZoneKeys.classC]]; [self.keychainZone addToZone: [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-FFFF-FFFF-FFFF-5A507ACB2D85" withAccount:@"classAItem" key:self.keychainZoneKeys.classA]]; - CKKSResultOperation* op = [self.keychainView waitForFetchAndIncomingQueueProcessing]; + CKKSResultOperation* op = self.keychainView.resultsOfNextProcessIncomingQueueOperation; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; // The processing op should NOT error, even though it didn't manage to process the classA item XCTAssertNil(op.error, "no error while failing to process a class A item"); @@ -1618,9 +2208,10 @@ [self findGenericPassword:@"classCItem" expecting:errSecSuccess]; [self findGenericPassword:@"classAItem" expecting:errSecItemNotFound]; + NSOperation* results = [self.keychainView resultsOfNextProcessIncomingQueueOperation]; self.aksLockState = false; [self.lockStateTracker recheck]; - [self.keychainView waitUntilAllOperationsAreFinished]; + [results waitUntilFinished]; [self findGenericPassword:@"classCItem" expecting:errSecSuccess]; [self findGenericPassword:@"classAItem" expecting:errSecSuccess]; @@ -1675,22 +2266,21 @@ [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; [self saveTLKMaterialToKeychain:self.keychainZoneID]; - // Trigger a notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; // Make life easy on this test; testAcceptKeyConflictAndUploadReencryptedItem will check the case when we don't receive the notification [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Just in extra case of threading issues, force a reexamination of the key hierarchy - [self.keychainView dispatchSyncWithAccountKeys: ^bool { - [self.keychainView _onqueueAdvanceKeyStateMachineToState: nil withError: nil]; - return true; + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + [self.keychainView _onqueuePokeKeyStateMachine]; + return CKKSDatabaseTransactionCommit; }]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should become 'ready'"); // Verify that there are six local keys, and three local current key records - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -1714,14 +2304,13 @@ XCTFail("Unknown key class: %@", key.keyclass); } } - - return false; }]; // We expect a single record to be uploaded. [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; // TODO: remove this by writing code for item reencrypt after key arrival + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self addGenericPassword: @"data" account: @"account-delete-me-rolled-key"]; @@ -1738,6 +2327,8 @@ [self startCKKSSubsystem]; [self.keychainView waitUntilAllOperationsAreFinished]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); + // We expect a single record to be uploaded. [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; @@ -1745,6 +2336,7 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); [self waitForCKModifications]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); [self rollFakeKeyHierarchyInCloudKit:self.keychainZoneID]; @@ -1872,15 +2464,13 @@ [self waitForCKModifications]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); // CKKS should not roll the keys while progressing back to 'ready', but it will fetch once self.silentFetchesAllowed = false; [self expectCKFetch]; - [self.keychainView dispatchSyncWithAccountKeys: ^bool { - [self.keychainView _onqueueKeyStateMachineRequestFetch]; - return true; - }]; + [self.keychainView.stateMachine handleFlag:CKKSFlagFetchRequested]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should have returned to ready"); OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -1894,6 +2484,7 @@ // Spin up CKKS subsystem. [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); [self.keychainView waitForFetchAndIncomingQueueProcessing]; // just to be sure it's fetched // Items should upload. @@ -1926,6 +2517,7 @@ // Spin up CKKS subsystem. [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); [self.keychainView waitForFetchAndIncomingQueueProcessing]; // just to be sure it's fetched // Items should upload. @@ -1944,8 +2536,9 @@ XCTAssertNotEqualObjects(currentClassC.etag, self.keychainZone.currentDatabase[currentClassCID].etag, "Etag should have changed"); // Add another item. This write should fail, then CKKS should recover without rolling the key hierarchy or issuing a fetch. + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.keychainView.holdOutgoingQueueOperation = [CKKSGroupOperation named:@"outgoing-hold" withBlock: ^{ - secnotice("ckks", "releasing outgoing-queue hold"); + ckksnotice_global("ckks", "releasing outgoing-queue hold"); }]; self.silentFetchesAllowed = false; @@ -2044,6 +2637,28 @@ XCTAssertTrue(self.keychainZone.flag, "Keychain zone shouldn't have been reset"); } +- (void)testOnboardOldItemMatchingExistingCKKSItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + NSString* itemAccount = @"account-delete-me"; + [self addGenericPassword:@"password" account:itemAccount]; + + CKRecord* ckr = [self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; + [self.keychainZone addToZone:ckr]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should have become ready"); + + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + + // And, the local item should now match the UUID downloaded from CKKS + [self checkGenericPasswordStoredUUID:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" account:itemAccount]; +} + - (void)testResync { // We need to set up a desynced situation to test our resync. // First, let CKKS start up and send several items to CloudKit (that we'll then desync!) @@ -2059,13 +2674,15 @@ [self addGenericPassword: @"data" account: @"third"]; [self addGenericPassword: @"data" account: @"fourth"]; [self addGenericPassword: @"data" account: @"fifth"]; - NSUInteger passwordCount = 5u; + [self addGenericPassword: @"data" account: @"sixth"]; + NSUInteger passwordCount = 6u; [self checkGenericPassword: @"data" account: @"first"]; [self checkGenericPassword: @"data" account: @"second"]; [self checkGenericPassword: @"data" account: @"third"]; [self checkGenericPassword: @"data" account: @"fourth"]; [self checkGenericPassword: @"data" account: @"fifth"]; + [self checkGenericPassword: @"data" account: @"sixth"]; [self expectCKModifyItemRecords: passwordCount currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; @@ -2089,7 +2706,7 @@ XCTAssertNotNil(deleteAccount, "received an account for the local delete object"); __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync:^bool{ + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -2108,7 +2725,7 @@ [iqe deleteFromDatabase: &error]; } XCTAssertNil(error, "no error removing IQE"); - return true; + return CKKSDatabaseTransactionCommit; }]; // For the second record, delete all traces of it from CloudKit. @@ -2151,6 +2768,16 @@ [self checkGenericPassword:@"newpassword" account:localDataChangedAccount]; SecCKKSEnable(); + // The sixth record matches what's in CloudKit, but the local UUID has changed (and CKKS didn't notice, for whatever reason) + CKRecord* uuidMismatch = items[5]; + NSMutableDictionary* uuidMisMatchDictionary = [[self decryptRecord:uuidMismatch] mutableCopy]; + NSString* uuidMismatchAccount = uuidMisMatchDictionary[(__bridge id)kSecAttrAccount]; + NSString* newUUID = @"55463F83-3AAE-462D-B95F-2FA6AD088980"; + SecCKKSDisable(); + [self setGenericPasswordStoredUUID:newUUID account:uuidMismatchAccount]; + [self checkGenericPasswordStoredUUID:newUUID account:uuidMismatchAccount]; + SecCKKSEnable(); + // To make this more challenging, CK returns the refetch in multiple batches. This shouldn't affect the resync... CKServerChangeToken* ck1 = self.keychainZone.currentChangeToken; self.silentFetchesAllowed = false; @@ -2168,7 +2795,7 @@ self.keychainZone.limitFetchTo = ck1; self.keychainZone.limitFetchError = [[CKPrettyError alloc] initWithDomain:CKErrorDomain code:CKErrorNetworkFailure userInfo:@{CKErrorRetryAfterKey : [NSNumber numberWithInt:4]}]; - // The sixth record gets magically added to CloudKit, but CKKS has never heard of it + // The seventh record gets magically added to CloudKit, but CKKS has never heard of it // (emulates a lost record on the client, but that CloudKit already believes it's sent the record for) // Expected outcome: added to local keychain NSString* remoteOnlyAccount = @"remote-only"; @@ -2183,6 +2810,7 @@ ckksnotice("ckksresync", self.keychainView, "Remote data changed: %@ %@", remoteDataChanged.recordID.recordName, remoteDataChangedAccount); ckksnotice("ckksresync", self.keychainView, "in-sync: %@ %@", items[3].recordID.recordName, insyncAccount); ckksnotice("ckksresync", self.keychainView, "local update: %@ %@", items[4].recordID.recordName, localDataChangedAccount); + ckksnotice("ckksresync", self.keychainView, "uuid mismatch: %@ %@", items[5].recordID.recordName, uuidMismatchAccount); ckksnotice("ckksresync", self.keychainView, "Remote only: %@ %@", ckr.recordID.recordName, remoteOnlyAccount); CKKSSynchronizeOperation* resyncOperation = [self.keychainView resyncWithCloud]; @@ -2199,6 +2827,7 @@ [self findGenericPassword: remoteDataChangedAccount expecting: errSecSuccess]; [self findGenericPassword: insyncAccount expecting: errSecSuccess]; [self findGenericPassword: localDataChangedAccount expecting: errSecSuccess]; + [self findGenericPassword: uuidMismatchAccount expecting: errSecSuccess]; [self findGenericPassword: remoteOnlyAccount expecting: errSecSuccess]; [self checkGenericPassword: @"data" account: deleteAccount]; @@ -2206,9 +2835,12 @@ [self checkGenericPassword: @"CloudKitWins" account: remoteDataChangedAccount]; [self checkGenericPassword: @"data" account: insyncAccount]; [self checkGenericPassword:@"data" account:localDataChangedAccount]; + [self checkGenericPassword:@"data" account:uuidMismatchAccount]; [self checkGenericPassword: @"data" account: remoteOnlyAccount]; - [self.keychainView dispatchSync:^bool{ + [self checkGenericPasswordStoredUUID:uuidMismatch.recordID.recordName account:uuidMismatchAccount]; + + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -2237,7 +2869,6 @@ ckme = [CKKSMirrorEntry tryFromDatabase:ckr.recordID.recordName zoneID:strongSelf.keychainZoneID error:&error]; XCTAssertNil(error); XCTAssertNotNil(ckme); - return true; }]; } @@ -2261,6 +2892,8 @@ [self startCKKSSubsystem]; OCMVerifyAllWithDelay(self.mockDatabase, 20); [self waitForCKModifications]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Now, place an item in the outgoing queue @@ -2304,19 +2937,23 @@ CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" withAccount:@"fourth"]; [self.keychainZone addToZone:ckr]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; // Now, where are we.... CKKSScanLocalItemsOperation* scanLocal = [self.keychainView scanLocalItems:@"test-scan"]; - [scanLocal waitUntilFinished]; - - XCTAssertEqual(scanLocal.missingLocalItemsFound, 1u, "Should have found one missing item"); + // This operation will wait for the CKKSOutgoingQueue operation (currently held writing to cloudkit) to finish before beginning // Allow everything to proceed [self releaseCloudKitModificationHold]; + + [scanLocal waitUntilFinished]; + XCTAssertEqual(scanLocal.missingLocalItemsFound, 1u, "Should have found one missing item"); + [self.operationQueue addOperation:self.keychainView.holdIncomingQueueOperation]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; // And ensure that all four items are present again @@ -2341,6 +2978,8 @@ [self startCKKSSubsystem]; OCMVerifyAllWithDelay(self.mockDatabase, 20); [self waitForCKModifications]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; @@ -2368,6 +3007,47 @@ [self findGenericPassword: @"second" expecting: errSecSuccess]; } +- (void)testEnsureScanOccursOnNextStartIfCancelled { + // We want to set up a situation where a CKKSScanLocalItemsOperation is cancelled by daemon quitting. + NSString* itemAccount = @"first"; + [self addGenericPassword:@"data" account:itemAccount]; + [self addGenericPassword:@"data" account:@"second"]; + + // We're going to pretend that the scan doesn't happen due to daemon restart + SecCKKSSetTestSkipScan(true); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; // Make life easy for this test. + + [self startCKKSSubsystem]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + // CKKS should perform normally if new items are added + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword:@"found" account:@"after-setup"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // Now, simulate a restart + SecCKKSSetTestSkipScan(false); + + [self expectCKModifyItemRecords:2 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + + [self.keychainView halt]; + self.keychainView = [[CKKSViewManager manager] restartZone:self.keychainZoneID.zoneName]; + [self.keychainView beginCloudKitOperation]; + [self beginSOSTrustedViewOperation:self.keychainView]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self findGenericPassword:@"first" expecting:errSecSuccess]; + [self findGenericPassword:@"second" expecting:errSecSuccess]; +} + - (void)testResyncLocal { [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; @@ -2457,74 +3137,6 @@ [self checkGenericPassword: @"data" account: @"second"]; } -- (void)testMultipleZoneAdd { - // Bring up a new zone: we expect a key hierarchy upload. - CKKSKeychainView* atvView = [self.injectedManager findOrCreateView:(id)kSecAttrViewHintAppleTV]; - [self.ckksViews addObject:atvView]; - CKRecordZoneID* appleTVZoneID = [[CKRecordZoneID alloc] initWithZoneName:(__bridge NSString*) kSecAttrViewHintAppleTV ownerName:CKCurrentUserDefaultName]; - - // We also expect the view manager's notifyNewTLKsInKeychain call to fire once (after some delay) - OCMExpect([self.mockCKKSViewManager notifyNewTLKsInKeychain]); - - // Let the horses loose - [self startCKKSSubsystem]; - [self performOctagonTLKUpload:self.ckksViews]; - - // We expect a single record to be uploaded to the 'keychain' view - [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; - [self addGenericPassword: @"data" account: @"account-delete-me"]; - OCMVerifyAllWithDelay(self.mockDatabase, 20); - - // We expect a single record to be uploaded to the 'atv' view - [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:appleTVZoneID]; - [self addGenericPassword: @"atv" - account: @"tvaccount" - viewHint:(__bridge NSString*) kSecAttrViewHintAppleTV - access:(id)kSecAttrAccessibleAfterFirstUnlock - expecting:errSecSuccess message:@"AppleTV view-hinted object"]; - - OCMVerifyAllWithDelay(self.mockDatabase, 20); - - OCMVerifyAllWithDelay(self.mockCKKSViewManager, 10); -} - -- (void)testMultipleZoneDelete { - [self startCKKSSubsystem]; - - // Bring up a new zone: we expect a key hierarchy and an item. - CKKSKeychainView* atvView = [self.injectedManager findOrCreateView:(id)kSecAttrViewHintAppleTV]; - XCTAssertNotNil(atvView, "Should have a new ATV view"); - [self.ckksViews addObject:atvView]; - [self beginSOSTrustedViewOperation:atvView]; - CKRecordZoneID* appleTVZoneID = [[CKRecordZoneID alloc] initWithZoneName:(__bridge NSString*) kSecAttrViewHintAppleTV ownerName:CKCurrentUserDefaultName]; - - [self performOctagonTLKUpload:self.ckksViews]; - - // We expect a single record to be uploaded. - [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; - [self addGenericPassword: @"data" account: @"account-delete-me"]; - OCMVerifyAllWithDelay(self.mockDatabase, 20); - - [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:appleTVZoneID]; - [self addGenericPassword: @"atv" - account: @"tvaccount" - viewHint:(__bridge NSString*) kSecAttrViewHintAppleTV - access:(id)kSecAttrAccessibleAfterFirstUnlock - expecting:errSecSuccess - message:@"AppleTV view-hinted object"]; - OCMVerifyAllWithDelay(self.mockDatabase, 20); - - // We expect a single record to be deleted from the ATV zone - [self expectCKDeleteItemRecords: 1 zoneID:appleTVZoneID]; - [self deleteGenericPassword:@"tvaccount"]; - OCMVerifyAllWithDelay(self.mockDatabase, 20); - - // Now we expect a single record to be deleted from the test zone - [self expectCKDeleteItemRecords: 1 zoneID:self.keychainZoneID]; - [self deleteGenericPassword:@"account-delete-me"]; - OCMVerifyAllWithDelay(self.mockDatabase, 20); -} - - (void)testRestartWithoutRefetch { // Restarting the CKKS operation should check that it's been 15 minutes since the last fetch before it fetches again. Simulate this. [self startCKKSSubsystem]; @@ -2535,6 +3147,9 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + // Tear down the CKKS object and disallow fetches [self.keychainView halt]; self.silentFetchesAllowed = false; @@ -2544,11 +3159,13 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertFalse(self.keychainView.initiatedLocalScan, "Should not have initiated a local items scan due to a restart with a recent fetch"); + // Okay, cool, rad, now let's set the date to be very long ago and check that there's positively a fetch [self.keychainView halt]; self.silentFetchesAllowed = false; - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; @@ -2558,7 +3175,7 @@ ckse.lastFetchTime = [NSDate distantPast]; [ckse saveToDatabase: &error]; XCTAssertNil(error, "no error saving to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; [self expectCKFetch]; @@ -2566,6 +3183,108 @@ [self beginSOSTrustedViewOperation:self.keychainView]; [self.keychainView waitForKeyHierarchyReadiness]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertFalse(self.keychainView.initiatedLocalScan, "Should not have initiated a local items scan due to a restart (when we haven't fetched in a while, but did scan recently)"); + + // Now restart again, but cause a scan to occur + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; + XCTAssertNil(error, "no error pulling ckse from database"); + XCTAssertNotNil(ckse, "received a ckse"); + + ckse.lastLocalKeychainScanTime = [NSDate distantPast]; + [ckse saveToDatabase:&error]; + XCTAssertNil(error, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; + + [self.keychainView halt]; + self.keychainView = [[CKKSViewManager manager] restartZone: self.keychainZoneID.zoneName]; + [self beginSOSTrustedViewOperation:self.keychainView]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + XCTAssertTrue(self.keychainView.initiatedLocalScan, "Should have initiated a local items scan due to 24-hr notification"); +} + +- (void)testFetchAndScanOn24HrNotification { + // Every 24 hrs, CKKS should fetch if there hasn't been a fetch in a while. + [self startCKKSSubsystem]; + [self performOctagonTLKUpload:self.ckksViews]; + + [self waitForCKModifications]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + // We now get the 24-hr notification. Set this bit for later checking + XCTAssertTrue(self.keychainView.initiatedLocalScan, "Should have initiated a local items scan during bringup"); + self.keychainView.initiatedLocalScan = NO; + + self.silentFetchesAllowed = false; + + [self.keychainView xpc24HrNotification]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertFalse(self.keychainView.initiatedLocalScan, "Should not have initiated a local items scan due to a 24-hr notification with a recent fetch"); + + // Okay, cool, rad, now let's set the last local-keychain-scan date to be very long ago and retry + // This shouldn't fetch, but it should scan the local keychain + self.silentFetchesAllowed = false; + + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; + XCTAssertNil(error, "no error pulling ckse from database"); + XCTAssertNotNil(ckse, "received a ckse"); + + ckse.lastLocalKeychainScanTime = [NSDate distantPast]; + [ckse saveToDatabase:&error]; + XCTAssertNil(error, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; + + [self.keychainView xpc24HrNotification]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + XCTAssertTrue(self.keychainView.initiatedLocalScan, "Should have initiated a local items scan due to 24-hr notification"); + self.keychainView.initiatedLocalScan = false; + + // And check that the fetch occurs as well + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; + XCTAssertNil(error, "no error pulling ckse from database"); + XCTAssertNotNil(ckse, "received a ckse"); + + ckse.lastFetchTime = [NSDate distantPast]; + [ckse saveToDatabase:&error]; + XCTAssertNil(error, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; + + [self expectCKFetch]; + [self.keychainView xpc24HrNotification]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + XCTAssertFalse(self.keychainView.initiatedLocalScan, "Should not have initiated a local items scan due to 24-hr notification (if we've done one recently)"); } - (void)testRecoverFromZoneCreationFailure { @@ -2896,6 +3615,7 @@ [self waitForCKModifications]; [self.keychainView waitUntilAllOperationsAreFinished]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" withAccount:@"account0"]; @@ -2910,10 +3630,8 @@ }), @"Deleting local keys"); SecCKKSTestSetDisableKeyNotifications(false); - // Trigger a notification (with hilariously fake data) [self.keychainZone addToZone: ckr]; - [self.keychainView notifyZoneChange:nil]; - [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword: @"account0" expecting:errSecSuccess]; @@ -2945,12 +3663,13 @@ // Trigger a notification (with hilariously fake data) [self.keychainZone addToZone: ckr]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should return to 'ready'"); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Do this again, to allow for non-atomic key state machinery switching [self findGenericPassword: @"account0" expecting:errSecSuccess]; @@ -2988,6 +3707,7 @@ XCTAssertNil(error, "Should be no error deleting old key material from keychain"); [self.keychainZone addToZone:ckrAddedLater]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:accountShouldExist expecting:errSecSuccess]; @@ -3033,6 +3753,7 @@ [self.lockStateTracker recheck]; [self.keychainZone addToZone:ckrAddedLater]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Item should still not exist due to the lock state.... @@ -3041,11 +3762,12 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReadyPendingUnlock] wait:20*NSEC_PER_SEC], "Key state should have returned to readypendingunlock"); + NSOperation* results = [self.keychainView resultsOfNextProcessIncomingQueueOperation]; self.aksLockState = false; [self.lockStateTracker recheck]; // And now it does - [self.keychainView waitUntilAllOperationsAreFinished]; + [results waitUntilFinished]; [self findGenericPassword:accountShouldExist expecting:errSecSuccess]; [self findGenericPassword:accountWillExist expecting:errSecSuccess]; @@ -3143,7 +3865,7 @@ [self waitForCKModifications]; // Now, delete most of the key records are from on-disk, but the change token is not changed - [self.keychainView dispatchSync:^bool{ + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.keychainZoneID]; XCTAssertNotNil(keyset.currentTLKPointer, @"should be a TLK pointer"); @@ -3168,7 +3890,7 @@ [keyset.classC deleteFromDatabase:&error]; XCTAssertNil(error, "Should be no error deleting classC from database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // A restart should realize there's an issue, and pause for help @@ -3227,7 +3949,6 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered ready"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateReady, "CKKS entered ready"); // Network is unavailable [self.reachabilityTracker setNetworkReachability:false]; @@ -3240,6 +3961,7 @@ // Say network is available [self.reachabilityTracker setNetworkReachability:true]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:@"account-delete-me" expecting:errSecSuccess]; @@ -3259,7 +3981,6 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateInitializing] wait:20*NSEC_PER_SEC], "CKKS entered initializing"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateInitializing, "CKKS entered initializing"); // Now, save the TLK to the keychain (to simulate it coming in later via SOS). [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; @@ -3283,6 +4004,8 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:8*NSEC_PER_SEC], "CKKS entered ready"); + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + // Network is now unavailable [self.reachabilityTracker setNetworkReachability:false]; @@ -3374,7 +4097,7 @@ [self expectCKFetch]; // and one to succeed // Trigger a fake change notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -3396,7 +4119,7 @@ [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; // Save a new device state record with some fake etag - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ CKKSDeviceStateEntry* cdse = [[CKKSDeviceStateEntry alloc] initForDevice:self.ckDeviceID osVersion:@"fake-record" lastUnlockTime:[NSDate date] @@ -3420,7 +4143,7 @@ [cdse saveToDatabase:&error]; XCTAssertNil(error, @"No error saving cdse to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // Spin up CKKS subsystem. @@ -3448,7 +4171,7 @@ CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone:ckr]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:@"account-delete-me" expecting:errSecSuccess]; @@ -3491,7 +4214,7 @@ // We expect CKKS to recreate the zone, then have octagon reupload the keys, and then the class C item upload [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self performOctagonTLKUpload:self.ckksViews]; @@ -3538,7 +4261,7 @@ // We expect CKKS to reset itself and recover, then have octagon upload the keys, and then the class C item upload [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self performOctagonTLKUpload:self.ckksViews]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -3592,7 +4315,6 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); [self addGenericPassword: @"data" account: @"account-delete-me"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; // simulate a NSNotification callback (but still logged out) self.accountStatus = CKAccountStatusNoAccount; @@ -3602,7 +4324,6 @@ [self addGenericPassword: @"data" account: @"account-delete-me-2"]; [self addGenericPassword: @"data" account: @"account-delete-me-3"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // Test that there are no items in the database (since we never logged in) @@ -3624,11 +4345,10 @@ [self.accountStateTracker notifyCKAccountStatusChangeAndWaitForSignal]; OCMVerifyAllWithDelay(self.mockDatabase, 20); - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS should enter 'loggedout'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS should enter 'waitforcloudkitaccount'"); // There should be no uploads, even when we save keychain items and enter/exit circle [self addGenericPassword: @"data" account: @"account-delete-me"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; @@ -3640,7 +4360,6 @@ [self beginSOSTrustedViewOperation:self.keychainView]; [self addGenericPassword: @"data" account: @"account-delete-me-3"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // Test that there are no items in the database (since we never were in an HSA2 account) @@ -3683,7 +4402,6 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); [self addGenericPassword: @"data" account: @"account-delete-me"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], "CKKS entered 'waitfortlkcreation'"); @@ -3697,7 +4415,6 @@ [self addGenericPassword: @"data" account: @"account-delete-me-2"]; [self addGenericPassword: @"data" account: @"account-delete-me-3"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // Test that there are no items in the database (since we never logged in) @@ -3710,6 +4427,7 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; // But then, trust departs self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; @@ -3755,7 +4473,6 @@ // No writes yet, since we're not in circle XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], "CKKS entered 'waitfortlkcreation'"); - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.mockSOSAdapter.circleStatus = kSOSCCInCircle; [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; @@ -3896,7 +4613,14 @@ [self checkNoCKKSData: self.keychainView]; // Force zone into error state - self.keychainView.keyHierarchyState = SecCKKSZoneKeyStateError; + OctagonStateTransitionOperation* transitionOp = [OctagonStateTransitionOperation named:@"enter" entering:SecCKKSZoneKeyStateError]; + OctagonStateTransitionRequest* request = [[OctagonStateTransitionRequest alloc] init:@"enter-wait-for-trust" + sourceStates:[NSSet setWithArray:[CKKSZoneKeyStateMap() allKeys]] + serialQueue:self.keychainView.queue + timeout:10 * NSEC_PER_SEC + transitionOp:transitionOp]; + [self.keychainView.stateMachine handleExternalRequest:request]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateError] wait:20*NSEC_PER_SEC], "CKKS entered 'error'"); self.accountStatus = CKAccountStatusAvailable; [self.accountStateTracker notifyCKAccountStatusChangeAndWaitForSignal]; @@ -3913,6 +4637,8 @@ [op addDependency:self.keychainView.keyStateReadyDependency]; [self.operationQueue addOperation:op]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + XCTAssertEqual(0, [self.keychainView.loggedIn wait:2000*NSEC_PER_MSEC], "Should have been told of a 'login'"); XCTAssertNotEqual(0, [self.keychainView.loggedOut wait:100*NSEC_PER_MSEC], "'logout' event should be reset"); XCTAssertEqual(0, [self.keychainView.accountStateKnown wait:50*NSEC_PER_MSEC], "CKK should know the account state"); @@ -3943,14 +4669,15 @@ XCTAssertEqual(0, [self.keychainView.loggedOut wait:20*NSEC_PER_SEC], "Should have been told of a 'logout'"); XCTAssertNotEqual(0, [self.keychainView.loggedIn wait:50*NSEC_PER_MSEC], "'login' event should be reset"); XCTAssertEqual(0, [self.keychainView.accountStateKnown wait:50*NSEC_PER_MSEC], "CKK should know the account state"); - [self checkNoCKKSData: self.keychainView]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'logged out'"); + [self checkNoCKKSData:self.keychainView]; // There should be no further uploads, even when we save keychain items [self addGenericPassword: @"data" account: @"account-delete-me-2"]; [self addGenericPassword: @"data" account: @"account-delete-me-3"]; - [self.keychainView waitUntilAllOperationsAreFinished]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // Also, fetches shouldn't occur @@ -3975,7 +4702,7 @@ // And fetching still works! [self.keychainZone addToZone: [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D00" withAccount:@"account0"]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword: @"account0" expecting:errSecSuccess]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); @@ -3992,8 +4719,8 @@ // Add a keychain item, and make sure it doesn't upload yet. [self addGenericPassword: @"data" account: @"account-delete-me"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'loggedout'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS entered 'waitforcloudkitaccount'"); + XCTAssertNotEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:1*NSEC_PER_SEC], "CKKS shouldn't have entered 'waitforcloudkitaccount'"); OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -4083,15 +4810,9 @@ // CKKS shouldn't decide to poke its state machine, but it should still send the notification XCTestExpectation* viewChangeNotification = [self expectChangeForView:self.keychainZoneID.zoneName]; - // Reject all attempts to trigger a state machine update - id pokeKeyStateMachineScheduler = OCMClassMock([CKKSNearFutureScheduler class]); - OCMReject([pokeKeyStateMachineScheduler trigger]); - self.keychainView.pokeKeyStateMachineScheduler = pokeKeyStateMachineScheduler; - [self addGenericPassword: @"data" account: @"account-delete-me-2"]; [self waitForExpectations:@[viewChangeNotification] timeout:8]; - [pokeKeyStateMachineScheduler stopMocking]; } - (void)testUploadSyncableItemsAddedWhileUntrusted { @@ -4109,11 +4830,9 @@ [self addGenericPassword: @"data" account: @"account-delete-me-2"]; - sleep(2); - NSError* error = nil; NSDictionary* currentOQEs = [CKKSOutgoingQueueEntry countsByStateInZone:self.keychainZoneID error:&error]; - XCTAssertNil(error, "Should be no error coutning OQEs"); + XCTAssertNil(error, "Should be no error counting OQEs"); XCTAssertEqual(0, currentOQEs.count, "Should be no OQEs"); // Now, insert a restart to simulate securityd restarting (and throwing away all pending operations), then a real sign in @@ -4122,8 +4841,12 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], "CKKS entered waitfortrust"); // Okay! Upon sign in, this item should be uploaded - [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID - checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + [self expectCKModifyItemRecords:1 + deletedRecords:0 + currentKeyPointerRecords:1 + zoneID:self.keychainZoneID + checkItem:[self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"] + expectedOperationGroupName:@"restart-setup"]; [self putSelfTLKSharesInCloudKit:self.keychainZoneID]; self.mockSOSAdapter.circleStatus = kSOSCCInCircle; @@ -4134,6 +4857,42 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testSyncableItemAddedOnDaemonRestartBeforePolicyLoaded { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered ready"); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + // Daemon restarts + self.automaticallyBeginCKKSViewCloudKitOperation = false; + [self.injectedManager resetSyncingPolicy]; + [self.injectedManager haltZone:self.keychainZoneID.zoneName]; + + // This item addition shouldn't be uploaded yet, or in any queues + [self addGenericPassword:@"data" account:@"account-delete-me-2"]; + + NSError* error = nil; + NSDictionary* currentOQEs = [CKKSOutgoingQueueEntry countsByStateInZone:self.keychainZoneID error:&error]; + XCTAssertNil(error, "Should be no error counting OQEs"); + XCTAssertEqual(0, currentOQEs.count, "Should be no OQEs"); + + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + self.keychainView = [self.injectedManager findView:self.keychainZoneID.zoneName]; + // end of daemon restart + + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID + checkItem:[self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + + [self.injectedManager beginCloudKitOperationOfAllViews]; + [self beginSOSTrustedViewOperation:self.keychainView]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + // Note that this test assumes that the keychainView object was created at daemon restart. // I don't really know how to write a test for that... - (void)testSyncableItemAddedOnDaemonRestartBeforeCloudKitAccountKnown { @@ -4150,7 +4909,7 @@ [self addGenericPassword: @"data" account: @"account-delete-me-2"]; XCTAssertNotEqual(0, [self.keychainView.accountStateKnown wait:100*NSEC_PER_MSEC], "CKKS should still have no idea what the account state is"); XCTAssertEqual(self.keychainView.accountStatus, CKKSAccountStatusUnknown, "Account status should be unknown"); - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'logged out'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS entered 'waitforcloudkitaccount'"); [self.keychainView beginCloudKitOperation]; @@ -4179,7 +4938,7 @@ [self updateGenericPassword:@"newdata" account: @"account-delete-me-2"]; XCTAssertNotEqual(0, [self.keychainView.accountStateKnown wait:100*NSEC_PER_MSEC], "CKKS should still have no idea what the account state is"); XCTAssertEqual(self.keychainView.accountStatus, CKKSAccountStatusUnknown, "Account status should be unknown"); - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'logged out'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS entered 'waitforcloudkitaccount'"); [self.keychainView beginCloudKitOperation]; @@ -4208,7 +4967,7 @@ [self deleteGenericPassword:@"account-delete-me-2"]; XCTAssertNotEqual(0, [self.keychainView.accountStateKnown wait:100*NSEC_PER_MSEC], "CKKS should still have no idea what the account state is"); XCTAssertEqual(self.keychainView.accountStatus, CKKSAccountStatusUnknown, "Account status should be unknown"); - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'logged out'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS entered 'waitforcloudkitaccount'"); [self.keychainView beginCloudKitOperation]; @@ -4234,6 +4993,7 @@ [self startCKKSSubsystem]; [self waitForExpectations: @[operationRun] timeout:20]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); } - (void)testCKKSControlBringup { @@ -4316,11 +5076,11 @@ } [self measureBlock:^{ - [self.keychainView dispatchSyncWithAccountKeys:^bool{ + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for(CKRecord* record in tlkShareRecords) { [self.keychainView _onqueueCKRecordChanged:record resync:false]; } - return true; + return CKKSDatabaseTransactionCommit; }]; }]; } @@ -4337,7 +5097,7 @@ [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; XCTAssertNotEqual(0, [fetcherCondition wait:(3 * NSEC_PER_SEC)], "not supposed to get a fetch data"); diff --git a/keychain/ckks/tests/CloudKitKeychainSyncingFixupTests.m b/keychain/ckks/tests/CloudKitKeychainSyncingFixupTests.m index fddf4ca6..dea65b2a 100644 --- a/keychain/ckks/tests/CloudKitKeychainSyncingFixupTests.m +++ b/keychain/ckks/tests/CloudKitKeychainSyncingFixupTests.m @@ -49,7 +49,7 @@ - (void)testNoFixupOnInitialStart { id mockFixups = OCMClassMock([CKKSFixups class]); - OCMReject([[[mockFixups stub] ignoringNonObjectArgs] fixup:0 for:[OCMArg any]]); + [[[mockFixups reject] ignoringNonObjectArgs] fixup:0 for:[OCMArg any]]; [self startCKKSSubsystem]; [self performOctagonTLKUpload:self.ckksViews]; @@ -99,7 +99,7 @@ // Add some current item pointers. They don't necessarily need to point to anything... CKKSCurrentItemPointer* cip = [[CKKSCurrentItemPointer alloc] initForIdentifier:@"com.apple.security.ckks-pcsservice" - currentItemUUID:@"DD7C2F9B-B22D-3B90-C299-E3B48174BFA3" + currentItemUUID:@"50184A35-4480-E8BA-769B-567CF72F1EC0" state:SecCKKSProcessedStateRemote zoneID:self.keychainZoneID encodedCKRecord:nil]; @@ -109,7 +109,7 @@ XCTAssertNotNil(currentPointerRecord, "Found record in CloudKit at expected UUID"); CKKSCurrentItemPointer* cip2 = [[CKKSCurrentItemPointer alloc] initForIdentifier:@"com.apple.security.ckks-pcsservice2" - currentItemUUID:@"3AB8E78D-75AF-CFEF-F833-FA3E3E90978A" + currentItemUUID:@"10E76B80-CE1C-A52A-B0CB-462A2EBA05AF" state:SecCKKSProcessedStateRemote zoneID:self.keychainZoneID encodedCKRecord:nil]; @@ -118,13 +118,13 @@ CKRecord* currentPointerRecord2 = self.keychainZone.currentDatabase[currentPointerRecordID2]; XCTAssertNotNil(currentPointerRecord2, "Found record in CloudKit at expected UUID"); - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Tear down the CKKS object [self.keychainView halt]; - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ // Edit the zone state entry to have no fixups NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; @@ -138,7 +138,7 @@ // And add a garbage CIP CKKSCurrentItemPointer* cip3 = [[CKKSCurrentItemPointer alloc] initForIdentifier:@"garbage" - currentItemUUID:@"3AB8E78D-75AF-CFEF-F833-FA3E3E90978A" + currentItemUUID:@"10E76B80-CE1C-A52A-B0CB-462A2EBA05AF" state:SecCKKSProcessedStateLocal zoneID:self.keychainZoneID encodedCKRecord:nil]; @@ -146,7 +146,7 @@ XCTAssertEqual(cip3.identifier, @"garbage", "Identifier is what we thought it was"); [cip3 saveToDatabase:&error]; XCTAssertNil(error, "no error saving to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; self.silentFetchesAllowed = false; @@ -165,7 +165,7 @@ [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ // The zone state entry should be up the most recent fixup level NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; @@ -187,12 +187,11 @@ } [self waitForExpectations:@[foundCIP2] timeout:0.1]; - return true; }]; } - (void)setFixupNumber:(CKKSFixup)newFixup ckks:(CKKSKeychainView*)ckks { - [ckks dispatchSync: ^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ // Edit the zone state entry to have no fixups NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:ckks.zoneID.zoneName error:&error]; @@ -203,7 +202,7 @@ ckse.lastFixup = newFixup; [ckse saveToDatabase: &error]; XCTAssertNil(error, "no error saving to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -218,6 +217,8 @@ [self waitForCKModifications]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); + // Tear down the CKKS object [self.keychainView halt]; [self setFixupNumber:CKKSFixupRefetchCurrentItemPointers ckks:self.keychainView]; @@ -256,7 +257,6 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForFixupOperation] wait:20*NSEC_PER_SEC], "Key state should become waitforfixup"); - self.silentFetchesAllowed = true; [self releaseCloudKitFetchHold]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); @@ -266,12 +266,11 @@ XCTAssertNil(self.keychainView.lastFixupOperation.error, "Shouldn't have been any error performing fixup"); // and check that the share made it - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* blockerror = nil; CKKSTLKShareRecord* localshare = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:shareCKRecord.recordID error:&blockerror]; XCTAssertNil(blockerror, "Shouldn't error finding new TLKShare record in database"); XCTAssertNotNil(localshare, "Should be able to find a new TLKShare record in database"); - return true; }]; } @@ -313,7 +312,7 @@ [self deleteGenericPassword:@"first"]; // Corrupt the second item's CKMirror entry to only contain system fields in the CKRecord portion (to emulate early CKKS behavior) - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSMirrorEntry* ckme = [CKKSMirrorEntry fromDatabase:secondRecordID.recordName zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "Should have no error pulling second CKKSMirrorEntry from database"); @@ -324,7 +323,7 @@ [ckme saveToDatabase:&error]; XCTAssertNil(error, "No error saving system-fielded CKME back to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // Now, restart CKKS, but place a hold on the fixup operation @@ -367,7 +366,7 @@ // Modify the sqlite DB to simulate how earlier verions would save these records - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry fromDatabase:self.remoteSOSOnlyPeer.peerID zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "Should have no error pulling CKKSDeviceStateEntry from database"); @@ -379,7 +378,7 @@ [cdse saveToDatabase:&error]; XCTAssertNil(error, "No error saving modified CDSE back to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // Tear down the CKKS object @@ -402,17 +401,59 @@ [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; // And all CDSEs should have an octagon peer ID again! - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry fromDatabase:self.remoteSOSOnlyPeer.peerID zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "Should have no error pulling CKKSDeviceStateEntry from database"); XCTAssertNotNil(cdse.octagonPeerID, "CDSE should have an octagon peer ID"); XCTAssertNotNil(cdse.octagonStatus, "CDSE should have an octagon status"); - return false; }]; } +- (void)testFixupDeletesTombstoneEntries { + [self startCKKSSubsystem]; + [self performOctagonTLKUpload:self.ckksViews]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should become 'ready'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + // The CKKS stack now rejects tombstone items. So, let's inject one out of band. + + [self.keychainView halt]; + + [self setFixupNumber:CKKSFixupResaveDeviceStateEntries ckks:self.keychainView]; + + CKRecord* ckr = [self createFakeTombstoneRecord:self.keychainZoneID + recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" + account:@"account-delete-me"]; + [self.keychainZone addToZone:ckr]; + + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + CKKSMirrorEntry* ckme = [[CKKSMirrorEntry alloc] initWithCKRecord:ckr]; + NSError* error = nil; + [ckme saveToDatabase:&error]; + + XCTAssertNil(error, "Should be no error saving the CKME to the database"); + return CKKSDatabaseTransactionCommit; + }]; + + // Now, restart CKKS. The bad record should be deleted. + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + + self.keychainView = [[CKKSViewManager manager] restartZone:self.keychainZoneID.zoneName]; + [self beginSOSTrustedViewOperation:self.keychainView]; + + // Deletions should occur + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView.lastFixupOperation waitUntilFinished]; + XCTAssertNil(self.keychainView.lastFixupOperation.error, "Shouldn't have been any error performing fixup"); + + [self findGenericPassword:@"account-delete-me" expecting:errSecItemNotFound]; +} + @end #endif // OCTAGON diff --git a/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h b/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h index 933305d3..1b01318e 100644 --- a/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h +++ b/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h @@ -29,7 +29,6 @@ #import "keychain/ckks/CKKSCurrentKeyPointer.h" #import "keychain/ckks/CKKSItem.h" #import "keychain/ckks/tests/CKKSMockSOSPresentAdapter.h" -#import "keychain/ot/proto/generated_source/OTAccountMetadataClassC.h" #import "keychain/ot/OTCuttlefishAccountStateHolder.h" #include "OSX/sec/Security/SecItemShim.h" @@ -51,7 +50,6 @@ NS_ASSUME_NONNULL_BEGIN @interface CloudKitKeychainSyncingMockXCTest : CloudKitMockXCTest @property CKKSControl* ckksControl; -@property OTCuttlefishAccountStateHolder *accountMetaDataStore; @property (nullable) id mockCKKSKeychainBackedKey; @property (nullable) NSError* keychainFetchError; @@ -62,8 +60,9 @@ NS_ASSUME_NONNULL_BEGIN // Set this to false after calling -setUp if you want to initialize the views yourself @property bool automaticallyBeginCKKSViewCloudKitOperation; -// Fill this in before allowing initialization to use your own mock instead of a default stub +// Fill these in before allowing initialization to use your own mock instead of a default stub @property id suggestTLKUpload; +@property id requestPolicyCheck; @property NSMutableSet* ckksViews; @property NSMutableSet* ckksZones; @@ -122,20 +121,34 @@ NS_ASSUME_NONNULL_BEGIN withAccount:(NSString* _Nullable)account key:(CKKSKey* _Nullable)key; +- (CKRecord*)createFakeTombstoneRecord:(CKRecordZoneID*)zoneID recordName:(NSString*)recordName account:(NSString*)account; + - (CKKSItem*)newItem:(CKRecordID*)recordID withNewItemData:(NSDictionary*) dictionary key:(CKKSKey*)key; - (CKRecord*)newRecord:(CKRecordID*)recordID withNewItemData:(NSDictionary*)dictionary; - (CKRecord*)newRecord:(CKRecordID*)recordID withNewItemData:(NSDictionary*)dictionary key:(CKKSKey*)key; - (NSDictionary*)decryptRecord:(CKRecord*)record; +- (void)addItemToCloudKitZone:(NSDictionary*)itemDict recordName:(NSString*)recordName zoneID:(CKRecordZoneID*)zoneID; + // Do keychain things: - (void)addGenericPassword:(NSString*)password account:(NSString*)account; - (void)addGenericPassword:(NSString*)password account:(NSString*)account viewHint:(NSString* _Nullable)viewHint; +- (void)addGenericPassword:(NSString*)password account:(NSString*)account accessGroup:(NSString*)accessGroup; - (void)addGenericPassword:(NSString*)password account:(NSString*)account viewHint:(NSString* _Nullable)viewHint access:(NSString*)access expecting:(OSStatus)status message:(NSString*)message; + +- (BOOL)addGenericPassword:(NSString*)password + account:(NSString*)account + access:(NSString*)access + viewHint:(NSString* _Nullable)viewHint + accessGroup:(NSString* _Nullable)accessGroup + expecting:(OSStatus)status + message:(NSString*)message; + - (void)addGenericPassword:(NSString*)password account:(NSString*)account expecting:(OSStatus)status message:(NSString*)message; - (void)updateGenericPassword:(NSString*)newPassword account:(NSString*)account; @@ -149,6 +162,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)findGenericPassword:(NSString*)account expecting:(OSStatus)status; - (void)checkGenericPassword:(NSString*)password account:(NSString*)account; +- (void)checkGenericPasswordStoredUUID:(NSString*)uuid account:(NSString*)account; +- (void)setGenericPasswordStoredUUID:(NSString*)uuid account:(NSString*)account; + - (void)createClassCItemAndWaitForUpload:(CKRecordZoneID*)zoneID account:(NSString*)account; - (void)createClassAItemAndWaitForUpload:(CKRecordZoneID*)zoneID account:(NSString*)account; diff --git a/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.m b/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.m index 3ea304a4..949aebe0 100644 --- a/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.m +++ b/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.m @@ -23,11 +23,15 @@ #if OCTAGON +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" #import +#pragma clang diagnostic pop #import "keychain/ckks/tests/CloudKitMockXCTest.h" #import "keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h" +#import "keychain/securityd/SecItemSchema.h" #import "keychain/securityd/SecItemServer.h" #import "keychain/securityd/SecItemDb.h" @@ -36,6 +40,7 @@ #import "keychain/ckks/CKKSCurrentKeyPointer.h" #import "keychain/ckks/CKKSItemEncrypter.h" #import "keychain/ckks/CKKSKey.h" +#import "keychain/ckks/CKKSMemoryKeyCache.h" #import "keychain/ckks/CKKSOutgoingQueueEntry.h" #import "keychain/ckks/CKKSIncomingQueueEntry.h" #import "keychain/ckks/CKKSSynchronizeOperation.h" @@ -106,9 +111,13 @@ self.suggestTLKUpload = OCMClassMock([CKKSNearFutureScheduler class]); OCMStub([self.suggestTLKUpload trigger]); - self.ckksZones = [NSMutableSet set]; - self.ckksViews = [NSMutableSet set]; - self.keys = [[NSMutableDictionary alloc] init]; + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMStub([self.requestPolicyCheck trigger]); + + // If a subclass wants to fill these in before calling setUp, fine. + self.ckksZones = self.ckksZones ?: [NSMutableSet set]; + self.ckksViews = self.ckksViews ?: [NSMutableSet set]; + self.keys = self.keys ?: [[NSMutableDictionary alloc] init]; [SecMockAKS reset]; @@ -139,15 +148,12 @@ OCMStub([mockConnection remoteObjectProxyWithErrorHandler:[OCMArg any]]).andCall(self, @selector(injectedManager)); self.ckksControl = [[CKKSControl alloc] initWithConnection:mockConnection]; XCTAssertNotNil(self.ckksControl, "Should have received control object"); - - self.accountMetaDataStore = OCMPartialMock([[OTCuttlefishAccountStateHolder alloc]init]); - OCMStub([self.accountMetaDataStore loadOrCreateAccountMetadata:[OCMArg anyObjectRef]]).andCall(self, @selector(loadOrCreateAccountMetadata:)); } - (void)tearDown { - // Make sure the key state machine won't be poked after teardown + // Make sure the key state machines won't continue for(CKKSKeychainView* view in self.ckksViews) { - [view.pokeKeyStateMachineScheduler cancel]; + [view.stateMachine haltOperation]; } [self.ckksViews removeAllObjects]; @@ -157,8 +163,6 @@ [self.mockCKKSKeychainBackedKey stopMocking]; self.mockCKKSKeychainBackedKey = nil; - [((id)self.accountMetaDataStore) stopMocking]; - self.remoteSOSOnlyPeer = nil; } @@ -184,7 +188,9 @@ [view beginCloudKitOperation]; } - [view beginTrustedOperation:@[self.mockSOSAdapter] suggestTLKUpload:self.suggestTLKUpload]; + [view beginTrustedOperation:@[self.mockSOSAdapter] + suggestTLKUpload:self.suggestTLKUpload + requestPolicyCheck:self.requestPolicyCheck]; } - (void)endSOSTrustedOperationForAllViews { @@ -203,6 +209,7 @@ - (void)verifyDatabaseMocks { OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; } - (void)createClassCItemAndWaitForUpload:(CKRecordZoneID*)zoneID account:(NSString*)account { @@ -257,6 +264,7 @@ NSError* error = nil; ZoneKeys* zonekeys = [[ZoneKeys alloc] init]; + zonekeys.viewName = zoneID.zoneName; zonekeys.tlk = [self fakeTLK:zoneID]; [zonekeys.tlk CKRecordWithZoneID: zoneID]; // no-op here, but memoize in the object @@ -289,26 +297,31 @@ } - (void)saveFakeKeyHierarchyToLocalDatabase: (CKRecordZoneID*)zoneID { - NSError* error = nil; ZoneKeys* zonekeys = [self createFakeKeyHierarchy: zoneID oldTLK:nil]; - [zonekeys.tlk saveToDatabase:&error]; - XCTAssertNil(error, "TLK saved to database successfully"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* error = nil; - [zonekeys.classA saveToDatabase:&error]; - XCTAssertNil(error, "Class A key saved to database successfully"); + [zonekeys.tlk saveToDatabase:&error]; + XCTAssertNil(error, "TLK saved to database successfully"); - [zonekeys.classC saveToDatabase:&error]; - XCTAssertNil(error, "Class C key saved to database successfully"); + [zonekeys.classA saveToDatabase:&error]; + XCTAssertNil(error, "Class A key saved to database successfully"); - [zonekeys.currentTLKPointer saveToDatabase:&error]; - XCTAssertNil(error, "Current TLK pointer saved to database successfully"); + [zonekeys.classC saveToDatabase:&error]; + XCTAssertNil(error, "Class C key saved to database successfully"); - [zonekeys.currentClassAPointer saveToDatabase:&error]; - XCTAssertNil(error, "Current Class A pointer saved to database successfully"); + [zonekeys.currentTLKPointer saveToDatabase:&error]; + XCTAssertNil(error, "Current TLK pointer saved to database successfully"); - [zonekeys.currentClassCPointer saveToDatabase:&error]; - XCTAssertNil(error, "Current Class C pointer saved to database successfully"); + [zonekeys.currentClassAPointer saveToDatabase:&error]; + XCTAssertNil(error, "Current Class A pointer saved to database successfully"); + + [zonekeys.currentClassCPointer saveToDatabase:&error]; + XCTAssertNil(error, "Current Class C pointer saved to database successfully"); + + return CKKSDatabaseTransactionCommit; + }]; } - (void)putFakeDeviceStatusInCloudKit:(CKRecordZoneID*)zoneID zonekeys:(ZoneKeys*)zonekeys { @@ -458,7 +471,7 @@ for(CKKSKeychainView* view in views) { XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:40*NSEC_PER_SEC], @"key state should enter 'waitfortlkcreation' (view %@)", view); - [keysetOps addObject: [view findKeySet]]; + [keysetOps addObject: [view findKeySet:NO]]; } // Now that we've kicked them all off, wait for them to resolve @@ -575,6 +588,7 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) CFReleaseNull(cferror); return piggybackdata; } + - (void)SOSPiggyBackAddToKeychain:(NSDictionary*)piggydata{ __block CFErrorRef cferror = NULL; kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { @@ -674,11 +688,15 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) ZoneKeys* keys = self.keys[zoneID]; XCTAssertNotNil(keys, "Have a zonekeys object for this zone"); - for(CKKSTLKShareRecord* share in keys.tlkShares) { - NSError* error = nil; - [share saveToDatabase:&error]; - XCTAssertNil(error, "Shouldn't have been an error saving a TLKShare to the database"); - } + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult{ + for(CKKSTLKShareRecord* share in keys.tlkShares) { + NSError* error = nil; + [share saveToDatabase:&error]; + XCTAssertNil(error, "Shouldn't have been an error saving a TLKShare to the database"); + } + + return CKKSDatabaseTransactionCommit; + }]; } - (void)createAndSaveFakeKeyHierarchy: (CKRecordZoneID*)zoneID { @@ -697,8 +715,9 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) - (void)expectCKModifyRecords:(NSDictionary*)expectedRecordTypeCounts deletedRecordTypeCounts:(NSDictionary*)expectedDeletedRecordTypeCounts zoneID:(CKRecordZoneID*)zoneID - checkModifiedRecord:(BOOL (^)(CKRecord*))checkRecord - runAfterModification:(void (^) (void))afterModification + checkModifiedRecord:(BOOL (^ _Nullable)(CKRecord*))checkRecord + inspectOperationGroup:(void (^ _Nullable)(CKOperationGroup * _Nullable))inspectOperationGroup + runAfterModification:(void (^ _Nullable) (void))afterModification { void (^newAfterModification)(void) = afterModification; @@ -769,6 +788,7 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) deletedRecordTypeCounts:expectedDeletedRecordTypeCounts zoneID:zoneID checkModifiedRecord:checkRecord + inspectOperationGroup:inspectOperationGroup runAfterModification:newAfterModification]; } @@ -860,7 +880,7 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) - (void)checkNoCKKSData: (CKKSKeychainView*) view { // Test that there are no items in the database - [view dispatchSync:^bool{ + [view dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* ckmes = [CKKSMirrorEntry all: view.zoneID error:&error]; XCTAssertNil(error, "No error fetching CKMEs"); @@ -881,7 +901,6 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) NSArray* deviceStates = [CKKSDeviceStateEntry allInZone:view.zoneID error:&error]; XCTAssertNil(error, "should be no error fetching device states"); XCTAssertEqual(deviceStates.count, 0ul, "No Device State entries"); - return false; }]; } @@ -934,7 +953,7 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) CKKSMirrorEntry* ckme = [[CKKSMirrorEntry alloc] initWithCKRecord: record]; NSError* error = nil; - NSDictionary* dict = [CKKSItemEncrypter decryptItemToDictionary:ckme.item error:&error]; + NSDictionary* dict = [CKKSItemEncrypter decryptItemToDictionary:ckme.item keyCache:nil error:&error]; XCTAssertNil(error, "No error decrypting item"); XCTAssertEqualObjects(account, dict[(id)kSecAttrAccount], "Account matches"); XCTAssertEqualObjects([password dataUsingEncoding:NSUTF8StringEncoding], dict[(id)kSecValueData], "Password matches"); @@ -980,6 +999,15 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) return item; } + +- (CKRecord*)createFakeTombstoneRecord:(CKRecordZoneID*)zoneID recordName:(NSString*)recordName account:(NSString*)account { + NSMutableDictionary* item = [[self fakeRecordDictionary:account zoneID:zoneID] mutableCopy]; + item[@"tomb"] = @YES; + + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:recordName zoneID:zoneID]; + return [self newRecord:ckrid withNewItemData:item]; +} + - (CKRecord*)createFakeRecord: (CKRecordZoneID*)zoneID recordName:(NSString*)recordName { return [self createFakeRecord: zoneID recordName:recordName withAccount: nil key:nil]; } @@ -1020,6 +1048,7 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) dataDictionary:dictionary updatingCKKSItem:nil parentkey:key + keyCache:nil error:&error]; XCTAssertNil(error, "encrypted item with class c key"); XCTAssertNotNil(cipheritem, "Have an encrypted item"); @@ -1035,27 +1064,46 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) return ckr; } +- (void)addItemToCloudKitZone:(NSDictionary*)itemDict recordName:(NSString*)recordName zoneID:(CKRecordZoneID*)zoneID +{ + FakeCKZone* zone = self.zones[zoneID]; + XCTAssertNotNil(zone, "Should have a zone for %@", zoneID); + + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:recordName zoneID:zoneID]; + CKRecord* record = [self newRecord:ckrid withNewItemData:itemDict]; + + [zone addToZone:record]; +} + - (NSDictionary*)decryptRecord: (CKRecord*) record { CKKSItem* item = [[CKKSItem alloc] initWithCKRecord: record]; NSError* error = nil; - NSDictionary* ret = [CKKSItemEncrypter decryptItemToDictionary: item error:&error]; + NSDictionary* ret = [CKKSItemEncrypter decryptItemToDictionary: item keyCache:nil error:&error]; XCTAssertNil(error); XCTAssertNotNil(ret); return ret; } -- (void)addGenericPassword: (NSString*) password account: (NSString*) account viewHint: (NSString*) viewHint access: (NSString*) access expecting: (OSStatus) status message: (NSString*) message { +- (BOOL)addGenericPassword:(NSString*)password + account:(NSString*)account + access:(NSString*)access + viewHint:(NSString* _Nullable)viewHint + accessGroup:(NSString* _Nullable)accessGroup + expecting:(OSStatus)status + message:(NSString*)message +{ NSMutableDictionary* query = [@{ (id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccessible: access, + (id)kSecAttrAccessible: (id)access, (id)kSecAttrAccount : account, (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, (id)kSecValueData : (id) [password dataUsingEncoding:NSUTF8StringEncoding], } mutableCopy]; + query[(id)kSecAttrAccessGroup] = accessGroup ?: @"com.apple.security.ckks"; + if(viewHint) { query[(id)kSecAttrSyncViewHint] = viewHint; } else { @@ -1066,6 +1114,16 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) XCTAssertEqual(status, SecItemAdd((__bridge CFDictionaryRef) query, NULL), @"%@", message); } +- (void)addGenericPassword: (NSString*) password account: (NSString*) account viewHint: (NSString*) viewHint access: (NSString*) access expecting: (OSStatus) status message: (NSString*) message { + [self addGenericPassword:password + account:account + access:access + viewHint:viewHint + accessGroup:nil + expecting:status + message:message]; +} + - (void)addGenericPassword: (NSString*) password account: (NSString*) account expecting: (OSStatus) status message: (NSString*) message { [self addGenericPassword:password account:account viewHint:nil access:(id)kSecAttrAccessibleAfterFirstUnlock expecting:errSecSuccess message:message]; @@ -1079,6 +1137,18 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) [self addGenericPassword:password account:account viewHint:viewHint access:(id)kSecAttrAccessibleAfterFirstUnlock expecting:errSecSuccess message:@"Add item to keychain with a viewhint"]; } + +- (void)addGenericPassword:(NSString*)password account:(NSString*)account accessGroup:(NSString*)accessGroup +{ + [self addGenericPassword:password + account:account + access:(id)kSecAttrAccessibleAfterFirstUnlock + viewHint:nil + accessGroup:accessGroup + expecting:errSecSuccess + message:@"Add item to keychain with an access group"]; +} + - (void)updateGenericPassword: (NSString*) newPassword account: (NSString*)account { NSDictionary* query = @{ (id)kSecClass : (id)kSecClassGenericPassword, @@ -1158,10 +1228,83 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) XCTAssertEqualObjects(storedPassword, password, "Stored password should match received password"); } +- (void)checkGenericPasswordStoredUUID:(NSString*)uuid account:(NSString*)account { + NSDictionary* queryAttributes = @{(id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : account, + (id)kSecAttrSynchronizable: @(YES), + (id)kSecReturnAttributes : @(YES), + (id)kSecReturnData : (id)kCFBooleanTrue, + }; + + __block CFErrorRef cferror = nil; + Query *q = query_create_with_limit( (__bridge CFDictionaryRef)queryAttributes, NULL, kSecMatchUnlimited, NULL, &cferror); + XCTAssertNil((__bridge id)cferror, "Should be no error creating query"); + CFReleaseNull(cferror); + + __block size_t count = 0; + + bool ok = kc_with_dbt(true, &cferror, ^(SecDbConnectionRef dbt) { + return SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef item, bool *stop) { + count += 1; + + NSString* itemUUID = (NSString*) CFBridgingRelease(CFRetain(SecDbItemGetValue(item, &v10itemuuid, &cferror))); + XCTAssertEqualObjects(uuid, itemUUID, "Item uuid should match expectation"); + }); + }); + + XCTAssertTrue(ok, "query should have been successful"); + XCTAssertNil((__bridge id)cferror, "Should be no error performing query"); + CFReleaseNull(cferror); + + XCTAssertEqual(count, 1, "Should have processed one item"); +} + +- (void)setGenericPasswordStoredUUID:(NSString*)uuid account:(NSString*)account { + NSDictionary* queryAttributes = @{(id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : account, + (id)kSecAttrSynchronizable: @(YES), + (id)kSecReturnAttributes : @(YES), + (id)kSecReturnData : (id)kCFBooleanTrue, + }; + + __block CFErrorRef cferror = nil; + Query *q = query_create_with_limit( (__bridge CFDictionaryRef)queryAttributes, NULL, kSecMatchUnlimited, NULL, &cferror); + XCTAssertNil((__bridge id)cferror, "Should be no error creating query"); + CFReleaseNull(cferror); + + __block size_t count = 0; + + bool ok = kc_with_dbt(true, &cferror, ^(SecDbConnectionRef dbt) { + return SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef item, bool *stop) { + count += 1; + + NSDictionary* updates = @{(id) kSecAttrUUID: uuid}; + + SecDbItemRef new_item = SecDbItemCopyWithUpdates(item, (__bridge CFDictionaryRef)updates, &cferror); + XCTAssertTrue(new_item != NULL, "Should be able to create a new item"); + + bool updateOk = kc_transaction_type(dbt, kSecDbExclusiveRemoteCKKSTransactionType, &cferror, ^{ + return SecDbItemUpdate(item, new_item, dbt, kCFBooleanFalse, q->q_uuid_from_primary_key, &cferror); + }); + XCTAssertTrue(updateOk, "Should be able to update item"); + + return; + }); + }); + + XCTAssertTrue(ok, "query should have been successful"); + XCTAssertNil((__bridge id)cferror, "Should be no error performing query"); + CFReleaseNull(cferror); + + XCTAssertEqual(count, 1, "Should have processed one item"); +} + -(XCTestExpectation*)expectChangeForView:(NSString*)view { NSString* notification = [NSString stringWithFormat: @"com.apple.security.view-change.%@", view]; return [self expectationForNotification:notification object:nil handler:^BOOL(NSNotification * _Nonnull nsnotification) { - secnotice("ckks", "Got a notification for %@: %@", notification, nsnotification); + ckksnotice_global("ckks", "Got a notification for %@: %@", notification, nsnotification); return YES; }]; } @@ -1190,14 +1333,6 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) } } -- (OTAccountMetadataClassC*)loadOrCreateAccountMetadata:(NSError**)error -{ - if(error) { - *error = [NSError errorWithDomain:@"securityd" code:errSecInteractionNotAllowed userInfo:nil]; - } - return nil; -} - @end #endif // OCTAGON diff --git a/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h b/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h index 2c669584..f8694906 100644 --- a/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h +++ b/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h @@ -25,7 +25,12 @@ #define CloudKitKeychainSyncingTestsBase_h #import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" #import +#pragma clang diagnostic pop + #import #include @@ -53,9 +58,6 @@ NS_ASSUME_NONNULL_BEGIN @property NSCalendar* utcCalendar; -- (NSSet*)managedViewList; - - - (ZoneKeys*)keychainZoneKeys; @end diff --git a/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.m b/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.m index 35640b3c..f122a1bd 100644 --- a/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.m +++ b/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.m @@ -62,7 +62,7 @@ // Wait for the ViewManager to be brought up XCTAssertEqual(0, [self.injectedManager.completedSecCKKSInitialize wait:20*NSEC_PER_SEC], "No timeout waiting for SecCKKSInitialize"); - self.keychainView = [[CKKSViewManager manager] findOrCreateView:@"keychain"]; + self.keychainView = [[CKKSViewManager manager] findView:@"keychain"]; XCTAssertNotNil(self.keychainView, "CKKSViewManager created the keychain view"); [self.ckksViews addObject:self.keychainView]; } @@ -70,10 +70,6 @@ // Check that your environment is set up correctly XCTAssertFalse([CKKSManifest shouldSyncManifests], "Manifests syncing is disabled"); XCTAssertFalse([CKKSManifest shouldEnforceManifests], "Manifests enforcement is disabled"); - - self.aksLockState = false; // Lie and say AKS is always unlocked - self.mockLockStateTracker = OCMClassMock([CKKSLockStateTracker class]); - OCMStub([self.mockLockStateTracker queryAKSLocked]).andCall(self, @selector(aksLockState)); } diff --git a/keychain/ckks/tests/CloudKitMockXCTest.h b/keychain/ckks/tests/CloudKitMockXCTest.h index 0e3573d6..db471a77 100644 --- a/keychain/ckks/tests/CloudKitMockXCTest.h +++ b/keychain/ckks/tests/CloudKitMockXCTest.h @@ -32,9 +32,13 @@ #import "keychain/ckks/tests/CKKSMockSOSPresentAdapter.h" #import "keychain/ckks/tests/CKKSMockOctagonAdapter.h" +#import "keychain/ckks/tests/CKKSMockLockStateProvider.h" #import "keychain/ckks/CKKSAccountStateTracker.h" #import "keychain/ckks/tests/MockCloudKit.h" +#import "keychain/ot/OTManager.h" +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" + NS_ASSUME_NONNULL_BEGIN @class CKKSKey; @@ -46,6 +50,9 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSReachabilityTracker; @class SOSCKKSPeerAdapter; +@interface CKKSTestFailureLogger : NSObject +@end + @interface CloudKitMockXCTest : XCTestCase @property CKRecordZoneID* testZoneID; @@ -82,8 +89,9 @@ NS_ASSUME_NONNULL_BEGIN @property NSString* apsEnvironment; @property bool aksLockState; // The current 'AKS lock state' +@property CKKSMockLockStateProvider* lockStateProvider; + @property (readonly) CKKSLockStateTracker* lockStateTracker; -@property (nullable) id mockLockStateTracker; @property (readonly) CKKSReachabilityTracker *reachabilityTracker; @@ -103,13 +111,33 @@ NS_ASSUME_NONNULL_BEGIN @property CKKSMockSOSPresentAdapter* mockSOSAdapter; @property (nullable) CKKSMockOctagonAdapter *mockOctagonAdapter; --(NSSet*)managedViewList; +- (NSSet*)managedViewList; +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewList; +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewListWithUserControllableViews:(NSSet*)ucv + syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews; + @property (nullable) id mockCKKSViewManager; @property (nullable) CKKSViewManager* injectedManager; +// Injected into CKKSViewManager using OCMock +@property BOOL overrideUseCKKSViewsFromPolicy; + +// Set this to true before calling -setup if you're going to configure the ckks view manager yourself +// !disable format used because this will be initialized to false, and so will happen unless subclasses take positive action +@property BOOL disableConfigureCKKSViewManagerWithViews; + +// Set this to true to override CKKSViewsFromPolicy to NO instead of the default YES +// !disable format used because this will be initialized to false, and so will happen unless subclasses take positive action +@property BOOL setCKKSViewsFromPolicyToNo; + +@property (nullable) OTManager* injectedOTManager; + // Fill this in to fail the next modifyzones operation @property (nullable) NSError* nextModifyRecordZonesError; +// Used to track the test failure logger (for test teardown purposes) +@property (class) CKKSTestFailureLogger* testFailureLogger; + - (CKKSKey*)fakeTLK:(CKRecordZoneID*)zoneID; - (void)expectCKModifyItemRecords:(NSUInteger)expectedNumberOfRecords @@ -126,7 +154,17 @@ NS_ASSUME_NONNULL_BEGIN zoneID:(CKRecordZoneID*)zoneID checkItem:(BOOL (^_Nullable)(CKRecord*))checkItem; +- (void)expectCKModifyItemRecords:(NSUInteger)expectedNumberOfModifiedRecords + deletedRecords:(NSUInteger)expectedNumberOfDeletedRecords + currentKeyPointerRecords:(NSUInteger)expectedCurrentKeyRecords + zoneID:(CKRecordZoneID*)zoneID + checkItem:(BOOL (^ _Nullable)(CKRecord*))checkItem + expectedOperationGroupName:(NSString* _Nullable)operationGroupName; + - (void)expectCKDeleteItemRecords:(NSUInteger)expectedNumberOfRecords zoneID:(CKRecordZoneID*)zoneID; +- (void)expectCKDeleteItemRecords:(NSUInteger)expectedNumberOfRecords + zoneID:(CKRecordZoneID*)zoneID + expectedOperationGroupName:(NSString* _Nullable)operationGroupName; - (void)expectCKModifyKeyRecords:(NSUInteger)expectedNumberOfRecords currentKeyPointerRecords:(NSUInteger)expectedCurrentKeyRecords @@ -138,11 +176,18 @@ NS_ASSUME_NONNULL_BEGIN zoneID:(CKRecordZoneID*)zoneID checkModifiedRecord:(BOOL (^_Nullable)(CKRecord*))checkModifiedRecord; -- (void)expectCKModifyRecords:(NSDictionary*)expectedRecordTypeCounts +- (void)expectCKModifyRecords:(NSDictionary* _Nullable) expectedRecordTypeCounts + deletedRecordTypeCounts:(NSDictionary* _Nullable) expectedDeletedRecordTypeCounts + zoneID:(CKRecordZoneID*) zoneID + checkModifiedRecord:(BOOL (^ _Nullable)(CKRecord*)) checkModifiedRecord + runAfterModification:(void (^ _Nullable) (void))afterModification; + +- (void)expectCKModifyRecords:(NSDictionary* _Nullable)expectedRecordTypeCounts deletedRecordTypeCounts:(NSDictionary* _Nullable)expectedDeletedRecordTypeCounts zoneID:(CKRecordZoneID*)zoneID - checkModifiedRecord:(BOOL (^_Nullable)(CKRecord*))checkRecord - runAfterModification:(void (^_Nullable)(void))afterModification; + checkModifiedRecord:(BOOL (^ _Nullable)(CKRecord*)) checkModifiedRecord + inspectOperationGroup:(void (^ _Nullable)(CKOperationGroup* _Nullable))inspectOperationGroup + runAfterModification:(void (^ _Nullable)(void))afterModification; - (void)failNextCKAtomicModifyItemRecordsUpdateFailure:(CKRecordZoneID*)zoneID; - (void)failNextCKAtomicModifyItemRecordsUpdateFailure:(CKRecordZoneID*)zoneID @@ -160,6 +205,11 @@ NS_ASSUME_NONNULL_BEGIN - (NSError* _Nullable)shouldFailModifyRecordZonesOperation; - (void)ensureZoneDeletionAllowed:(FakeCKZone*)zone; +// Override this to interpose on how an OTManager is created +// This will be called during setUp, after the CloudKit mocks are in-place +// This needs to fill in the injectedOTManager variable on this class +- (OTManager*)setUpOTManager:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; + // Use this to assert that a fetch occurs (especially if silentFetchesAllowed = false) - (void)expectCKFetch; diff --git a/keychain/ckks/tests/CloudKitMockXCTest.m b/keychain/ckks/tests/CloudKitMockXCTest.m index 76916eab..a8641783 100644 --- a/keychain/ckks/tests/CloudKitMockXCTest.m +++ b/keychain/ckks/tests/CloudKitMockXCTest.m @@ -30,11 +30,20 @@ #import #import #import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" #import +#pragma clang diagnostic pop + +#import +#import +#import #include "keychain/securityd/Regressions/SecdTestKeychainUtilities.h" #include #include "keychain/securityd/SecItemServer.h" +#include "keychain/securityd/SecItemDataSource.h" #if NO_SERVER #include "keychain/securityd/spi.h" @@ -54,11 +63,16 @@ #include "keychain/ckks/CKKSLockStateTracker.h" #include "keychain/ckks/CKKSReachabilityTracker.h" +#include "keychain/ot/OT.h" +#include "keychain/ot/OTManager.h" + #import "tests/secdmockaks/mockaks.h" #import "utilities/SecTapToRadar.h" #import "MockCloudKit.h" +#include "keychain/ckks/CKKSAnalytics.h" + @interface BoolHolder : NSObject @property bool state; @end @@ -71,15 +85,37 @@ - (void)_checkSelfCloudServicesEntitlement; @end +@implementation CKKSTestFailureLogger +- (instancetype)init { + if((self = [super init])) { + } + return self; +} + +- (void)testCase:(XCTestCase *)testCase didRecordIssue:(XCTIssue *)issue { + ckksnotice_global("ckkstests", "XCTest failure: (%@)%@:%lu error: %@ -- %@\n%@", + testCase.name, + issue.sourceCodeContext.location.fileURL, + (unsigned long)issue.sourceCodeContext.location.lineNumber, + issue.compactDescription, + issue.detailedDescription, + issue.sourceCodeContext.callStack); +} +@end @implementation CloudKitMockXCTest -@synthesize aksLockState = _aksLockState; +static CKKSTestFailureLogger* _testFailureLoggerVariable; + (void)setUp { // Turn on testing SecCKKSEnable(); SecCKKSTestsEnable(); SecCKKSSetReduceRateLimiting(true); + + self.testFailureLogger = [[CKKSTestFailureLogger alloc] init]; + + [[XCTestObservationCenter sharedTestObservationCenter] addTestObserver:self.testFailureLogger]; + [super setUp]; #if NO_SERVER @@ -87,6 +123,19 @@ #endif } ++ (void)tearDown { + [super tearDown]; + [[XCTestObservationCenter sharedTestObservationCenter] removeTestObserver:self.testFailureLogger]; +} + ++ (CKKSTestFailureLogger*)testFailureLogger { + return _testFailureLoggerVariable; +} + ++ (void)setTestFailureLogger:(CKKSTestFailureLogger*)logger { + _testFailureLoggerVariable = logger; +} + - (BOOL)isRateLimited:(SecTapToRadar *)ttrRequest { return self.isTTRRatelimited; @@ -120,12 +169,12 @@ self.operationQueue = [[NSOperationQueue alloc] init]; self.operationQueue.maxConcurrentOperationCount = 1; - self.zones = [[NSMutableDictionary alloc] init]; + self.zones = self.zones ?: [[NSMutableDictionary alloc] init]; self.apsEnvironment = @"fake APS push string"; // Static variables are a scourge. Let's reset this one... - [OctagonAPSReceiver resetGlobalEnviornmentMap]; + [OctagonAPSReceiver resetGlobalDelegatePortMap]; self.mockDatabaseExceptionCatcher = OCMStrictClassMock([CKDatabase class]); self.mockDatabase = OCMStrictClassMock([CKDatabase class]); @@ -155,46 +204,11 @@ // Inject a fake operation dependency so we won't respond with the CloudKit account status immediately // The CKKSAccountStateTracker won't send any login/logout calls without that information, so this blocks all CKKS setup self.ckaccountHoldOperation = [NSBlockOperation named:@"ckaccount-hold" withBlock:^{ - secnotice("ckks", "CKKS CK account status test hold released"); + ckksnotice_global("ckks", "CKKS CK account status test hold released"); }]; - OCMStub([self.mockContainer accountStatusWithCompletionHandler: - [OCMArg checkWithBlock:^BOOL(void (^passedBlock) (CKAccountStatus accountStatus, - NSError * _Nullable error)) { - - if(passedBlock) { - __strong __typeof(self) strongSelf = weakSelf; - NSBlockOperation* fulfillBlock = [NSBlockOperation named:@"account-status-completion" withBlock: ^{ - passedBlock(weakSelf.accountStatus, nil); - }]; - [fulfillBlock addDependency: strongSelf.ckaccountHoldOperation]; - [strongSelf.operationQueue addOperation: fulfillBlock]; - - return YES; - } - return NO; - }]]); - - OCMStub([self.mockContainer accountInfoWithCompletionHandler: - [OCMArg checkWithBlock:^BOOL(void (^passedBlock) (CKAccountInfo* accountInfo, - NSError * error)) { - __strong __typeof(self) strongSelf = weakSelf; - if(passedBlock && strongSelf) { - NSBlockOperation* fulfillBlock = [NSBlockOperation named:@"account-info-completion" withBlock: ^{ - __strong __typeof(self) blockStrongSelf = weakSelf; - CKAccountInfo* account = [[CKAccountInfo alloc] init]; - account.accountStatus = blockStrongSelf.accountStatus; - account.hasValidCredentials = blockStrongSelf.iCloudHasValidCredentials; - account.accountPartition = CKAccountPartitionTypeProduction; - passedBlock((CKAccountInfo*)account, nil); - }]; - [fulfillBlock addDependency: strongSelf.ckaccountHoldOperation]; - [strongSelf.operationQueue addOperation: fulfillBlock]; - - return YES; - } - return NO; - }]]); + OCMStub([self.mockContainer accountStatusWithCompletionHandler:[OCMArg any]]).andCall(self, @selector(ckcontainerAccountStatusWithCompletionHandler:)); + OCMStub([self.mockContainer accountInfoWithCompletionHandler:[OCMArg any]]).andCall(self, @selector(ckcontainerAccountInfoWithCompletionHandler:)); self.mockAccountStateTracker = OCMClassMock([CKKSAccountStateTracker class]); OCMStub([self.mockAccountStateTracker getCircleStatus]).andCall(self, @selector(circleStatus)); @@ -211,26 +225,10 @@ trustedPeers:[NSSet set] essential:YES]; - // If we're in circle, come up with a fake circle id. Otherwise, return an error. - OCMStub([self.mockAccountStateTracker fetchCirclePeerID: - [OCMArg checkWithBlock:^BOOL(void (^passedBlock) (NSString* peerID, - NSError * error)) { - __strong __typeof(self) strongSelf = weakSelf; - if(passedBlock && strongSelf) { - if(strongSelf.mockSOSAdapter.circleStatus == kSOSCCInCircle) { - passedBlock(strongSelf.mockSOSAdapter.selfPeer.peerID, nil); - } else { - passedBlock(nil, [NSError errorWithDomain:@"securityd" code:errSecInternalError userInfo:@{NSLocalizedDescriptionKey:@"no account, no circle id"}]); - } - - return YES; - } - return NO; - }]]); + OCMStub([self.mockAccountStateTracker fetchCirclePeerID:[OCMArg any]]).andCall(self, @selector(sosFetchCirclePeerID:)); + self.lockStateProvider = [[CKKSMockLockStateProvider alloc] initWithCurrentLockStatus:NO]; self.aksLockState = false; // Lie and say AKS is always unlocked - self.mockLockStateTracker = OCMClassMock([CKKSLockStateTracker class]); - OCMStub([self.mockLockStateTracker queryAKSLocked]).andCall(self, @selector(aksLockState)); self.mockTTR = OCMClassMock([SecTapToRadar class]); OCMStub([self.mockTTR isRateLimited:[OCMArg any]]).andCall(self, @selector(isRateLimited:)); @@ -340,20 +338,18 @@ nsdistributednotificationCenterClass:[FakeNSDistributedNotificationCenter class] notifierClass:[FakeCKKSNotifier class]]; - self.mockCKKSViewManager = OCMPartialMock( - [[CKKSViewManager alloc] initWithContainerName:SecCKKSContainerName - usePCS:SecCKKSContainerUsePCS - sosAdapter:self.mockSOSAdapter - cloudKitClassDependencies:cloudKitClassDependencies]); + self.injectedOTManager = [self setUpOTManager:cloudKitClassDependencies]; + [OTManager resetManager:false to:self.injectedOTManager]; + + self.mockCKKSViewManager = OCMPartialMock(self.injectedOTManager.viewManager); + self.injectedManager = self.mockCKKSViewManager; + + [self.mockCKKSViewManager setOverrideCKKSViewsFromPolicy:!self.setCKKSViewsFromPolicyToNo]; OCMStub([self.mockCKKSViewManager defaultViewList]).andCall(self, @selector(managedViewList)); OCMStub([self.mockCKKSViewManager syncBackupAndNotifyAboutSync]); OCMStub([self.mockCKKSViewManager waitForTrustReady]).andReturn(YES); - self.injectedManager = self.mockCKKSViewManager; - - [CKKSViewManager resetManager:false setTo:self.injectedManager]; - // Lie and say network is available [self.reachabilityTracker setNetworkReachability:true]; @@ -361,11 +357,25 @@ NSString* tmp_dir = [NSString stringWithFormat: @"/tmp/%@.%X", testName, arc4random()]; [[NSFileManager defaultManager] createDirectoryAtPath:[NSString stringWithFormat: @"%@/Library/Keychains", tmp_dir] withIntermediateDirectories:YES attributes:nil error:NULL]; - SetCustomHomeURLString((__bridge CFStringRef) tmp_dir); + SecSetCustomHomeURLString((__bridge CFStringRef) tmp_dir); SecKeychainDbReset(NULL); // Actually load the database. kc_with_dbt(true, NULL, ^bool (SecDbConnectionRef dbt) { return false; }); + + if(!self.disableConfigureCKKSViewManagerWithViews) { + // Normally, the Octagon state machine calls this. But, since we won't be running that, help it out. + // CKKS might try to take a DB lock, so do this after the DB load above + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + } +} + +- (OTManager*)setUpOTManager:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies +{ + return [[OTManager alloc] initWithSOSAdapter:self.mockSOSAdapter + lockStateTracker:[[CKKSLockStateTracker alloc] initWithProvider:self.lockStateProvider] + cloudKitClassDependencies:cloudKitClassDependencies]; + } - (SOSAccountStatus*)circleStatus { @@ -376,24 +386,34 @@ - (bool)aksLockState { - return _aksLockState; + return self.lockStateProvider.aksCurrentlyLocked; } - (void)setAksLockState:(bool)aksLockState { - - if(aksLockState) { - [SecMockAKS lockClassA]; - } else { - [SecMockAKS unlockAllClasses]; - } - _aksLockState = aksLockState; + ckksnotice_global("ckkstests", "Setting mock AKS lock state to: %@", (aksLockState ? @"locked" : @"unlocked")); + self.mockSOSAdapter.aksLocked = aksLockState ? YES : NO; + self.lockStateProvider.aksCurrentlyLocked = aksLockState; } - (bool)isNetworkReachable { return self.reachabilityTracker.currentReachability; } +- (void)sosFetchCirclePeerID:(void (^)(NSString* _Nullable peerID, NSError* _Nullable error))callback +{ + if(callback) { + // If we're in circle, come up with a fake circle id. Otherwise, return an error. + if(self.mockSOSAdapter.circleStatus == kSOSCCInCircle) { + callback(self.mockSOSAdapter.selfPeer.peerID, nil); + } else { + callback(nil, [NSError errorWithDomain:@"securityd" + code:errSecInternalError + userInfo:@{NSLocalizedDescriptionKey:@"no account, no circle id"}]); + } + } +} + - (void)ckcontainerSubmitEventMetric:(CKEventMetric*)metric { @try { [self.mockContainerExpectations submitEventMetric:metric]; @@ -402,6 +422,41 @@ } } +- (void)ckcontainerAccountStatusWithCompletionHandler:(void (^)(CKAccountStatus accountStatus, NSError * _Nullable error))completionHandler +{ + __weak __typeof(self) weakSelf = self; + + NSBlockOperation* fulfillBlock = [NSBlockOperation named:@"account-status-completion" withBlock: ^{ + __strong __typeof(self) strongOperationSelf = weakSelf; + + if(completionHandler) { + completionHandler(strongOperationSelf.accountStatus, nil); + } + }]; + [fulfillBlock addNullableDependency:self.ckaccountHoldOperation]; + [self.operationQueue addOperation:fulfillBlock]; +} + +- (void)ckcontainerAccountInfoWithCompletionHandler:(void (^)(CKAccountInfo * _Nullable accountInfo, NSError * _Nullable error))completionHandler +{ + __weak __typeof(self) weakSelf = self; + + NSBlockOperation* fulfillBlock = [NSBlockOperation named:@"account-info-completion" withBlock: ^{ + __strong __typeof(self) blockStrongSelf = weakSelf; + CKAccountInfo* account = [[CKAccountInfo alloc] init]; + account.accountStatus = blockStrongSelf.accountStatus; + account.hasValidCredentials = blockStrongSelf.iCloudHasValidCredentials; + account.accountPartition = CKAccountPartitionTypeProduction; + + if(completionHandler) { + completionHandler(account, nil); + } + }]; + + [fulfillBlock addNullableDependency:self.ckaccountHoldOperation]; + [self.operationQueue addOperation:fulfillBlock]; +} + - (void)ckdatabaseAddOperation:(NSOperation*)op { @try { [self.mockDatabase addOperation:op]; @@ -423,12 +478,12 @@ XCTAssertTrue(self.silentZoneDeletesAllowed, "Should be allowing zone deletes"); } --(CKKSAccountStateTracker*)accountStateTracker { - return self.injectedManager.accountTracker; +- (CKKSAccountStateTracker*)accountStateTracker { + return self.injectedOTManager.accountStateTracker; } -(CKKSLockStateTracker*)lockStateTracker { - return self.injectedManager.lockStateTracker; + return self.injectedOTManager.lockStateTracker; } -(CKKSReachabilityTracker*)reachabilityTracker { @@ -439,6 +494,37 @@ return (NSSet*) CFBridgingRelease(SOSViewCopyViewSet(kViewSetCKKS)); } +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewList +{ + return [self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet set] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED]; +} + +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewListWithUserControllableViews:(NSSet*)ucv + syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews +{ + NSMutableArray* rules = [NSMutableArray array]; + + for(NSString* viewName in self.managedViewList) { + TPPBPolicyKeyViewMapping* mapping = [[TPPBPolicyKeyViewMapping alloc] init]; + mapping.view = viewName; + mapping.matchingRule = [TPDictionaryMatchingRule fieldMatch:@"vwht" + fieldRegex:[NSString stringWithFormat:@"^%@$", viewName]]; + + [rules addObject:mapping]; + } + + TPSyncingPolicy* policy = [[TPSyncingPolicy alloc] initWithModel:@"test-policy" + version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"] + viewList:[self managedViewList] + priorityViews:[NSSet set] + userControllableViews:ucv + syncUserControllableViews:syncUserControllableViews + viewsToPiggybackTLKs:[NSSet set] + keyViewMapping:rules]; + return policy; +} + -(void)expectCKFetch { [self expectCKFetchAndRunBeforeFinished: nil]; } @@ -547,7 +633,7 @@ -(void)holdCloudKitModifications { XCTAssertFalse([self.ckModifyHoldOperation isPending], "Shouldn't already be a pending cloudkit modify hold operation"); self.ckModifyHoldOperation = [NSBlockOperation blockOperationWithBlock:^{ - secnotice("ckks", "Released CloudKit modification hold."); + ckksnotice_global("ckks", "Released CloudKit modification hold."); }]; } -(void)releaseCloudKitModificationHold { @@ -559,7 +645,7 @@ -(void)holdCloudKitFetches { XCTAssertFalse([self.ckFetchHoldOperation isPending], "Shouldn't already be a pending cloudkit fetch hold operation"); self.ckFetchHoldOperation = [NSBlockOperation blockOperationWithBlock:^{ - secnotice("ckks", "Released CloudKit fetch hold."); + ckksnotice_global("ckks", "Released CloudKit fetch hold."); }]; } -(void)releaseCloudKitFetchHold { @@ -571,7 +657,7 @@ -(void)holdCloudKitModifyRecordZones { XCTAssertFalse([self.ckModifyRecordZonesHoldOperation isPending], "Shouldn't already be a pending cloudkit zone create hold operation"); self.ckModifyRecordZonesHoldOperation = [NSBlockOperation blockOperationWithBlock:^{ - secnotice("ckks", "Released CloudKit zone create hold."); + ckksnotice_global("ckks", "Released CloudKit zone create hold."); }]; } -(void)releaseCloudKitModifyRecordZonesHold { @@ -583,7 +669,7 @@ -(void)holdCloudKitModifySubscription { XCTAssertFalse([self.ckModifySubscriptionsHoldOperation isPending], "Shouldn't already be a pending cloudkit subscription hold operation"); self.ckModifySubscriptionsHoldOperation = [NSBlockOperation blockOperationWithBlock:^{ - secnotice("ckks", "Released CloudKit zone create hold."); + ckksnotice_global("ckks", "Released CloudKit zone create hold."); }]; } -(void)releaseCloudKitModifySubscriptionHold { @@ -612,6 +698,21 @@ currentKeyPointerRecords:(NSUInteger)expectedCurrentKeyRecords zoneID:(CKRecordZoneID*)zoneID checkItem:(BOOL (^)(CKRecord*))checkItem { + [self expectCKModifyItemRecords:expectedNumberOfModifiedRecords + deletedRecords:expectedNumberOfDeletedRecords + currentKeyPointerRecords:expectedCurrentKeyRecords + zoneID:zoneID + checkItem:checkItem + expectedOperationGroupName:nil]; +} + +- (void)expectCKModifyItemRecords:(NSUInteger)expectedNumberOfModifiedRecords + deletedRecords:(NSUInteger)expectedNumberOfDeletedRecords + currentKeyPointerRecords:(NSUInteger)expectedCurrentKeyRecords + zoneID:(CKRecordZoneID*)zoneID + checkItem:(BOOL (^ _Nullable)(CKRecord*))checkItem + expectedOperationGroupName:(NSString* _Nullable)operationGroupName +{ // We're updating the device state type on every update, so add it in here NSMutableDictionary* expectedRecords = [@{SecCKRecordItemType: [NSNumber numberWithUnsignedInteger: expectedNumberOfModifiedRecords], SecCKRecordCurrentKeyType: [NSNumber numberWithUnsignedInteger: expectedCurrentKeyRecords], @@ -638,6 +739,9 @@ return YES; } } + inspectOperationGroup:operationGroupName != nil ? ^(CKOperationGroup* group) { + XCTAssertEqualObjects(group.name, operationGroupName, "Should have expected group name"); + } : nil runAfterModification:nil]; } @@ -672,13 +776,29 @@ deletedRecordTypeCounts:nil zoneID:zoneID checkModifiedRecord:checkModifiedRecord + inspectOperationGroup:nil runAfterModification:nil]; } -- (void)expectCKModifyRecords:(NSDictionary*) expectedRecordTypeCounts - deletedRecordTypeCounts:(NSDictionary*) expectedDeletedRecordTypeCounts +- (void)expectCKModifyRecords:(NSDictionary* _Nullable) expectedRecordTypeCounts + deletedRecordTypeCounts:(NSDictionary* _Nullable) expectedDeletedRecordTypeCounts + zoneID:(CKRecordZoneID*) zoneID + checkModifiedRecord:(BOOL (^ _Nullable)(CKRecord*)) checkModifiedRecord + runAfterModification:(void (^ _Nullable) (void))afterModification +{ + [self expectCKModifyRecords:expectedRecordTypeCounts + deletedRecordTypeCounts:expectedDeletedRecordTypeCounts + zoneID:zoneID + checkModifiedRecord:checkModifiedRecord + inspectOperationGroup:nil + runAfterModification:afterModification]; +} + +- (void)expectCKModifyRecords:(NSDictionary* _Nullable)expectedRecordTypeCounts + deletedRecordTypeCounts:(NSDictionary* _Nullable)expectedDeletedRecordTypeCounts zoneID:(CKRecordZoneID*) zoneID checkModifiedRecord:(BOOL (^)(CKRecord*)) checkModifiedRecord + inspectOperationGroup:(void (^ _Nullable)(CKOperationGroup* _Nullable))inspectOperationGroup runAfterModification:(void (^) (void))afterModification { __weak __typeof(self) weakSelf = self; @@ -770,14 +890,14 @@ if(expectedRecordTypeCounts) { matches &= !![modifiedRecordTypeCounts isEqual: filteredExpectedRecordTypeCounts]; if(!matches) { - secnotice("fakecloudkit", "Record number mismatch: %@ %@", modifiedRecordTypeCounts, filteredExpectedRecordTypeCounts); + secnotice("fakecloudkit", "Record number mismatch: attempted:%@ expected:%@", modifiedRecordTypeCounts, filteredExpectedRecordTypeCounts); result = NO; return; } } else { matches &= op.recordsToSave.count == 0u; if(!matches) { - secnotice("fakecloudkit", "Record number mismatch: %@ 0", modifiedRecordTypeCounts); + secnotice("fakecloudkit", "Record number mismatch: attempted:%@ expected:0", modifiedRecordTypeCounts); result = NO; return; } @@ -785,14 +905,14 @@ if(expectedDeletedRecordTypeCounts) { matches &= !![deletedRecordTypeCounts isEqual: expectedDeletedRecordTypeCounts]; if(!matches) { - secnotice("fakecloudkit", "Deleted record number mismatch: %@ %@", deletedRecordTypeCounts, expectedDeletedRecordTypeCounts); + secnotice("fakecloudkit", "Deleted record number mismatch: attempted:%@ expected:%@", deletedRecordTypeCounts, expectedDeletedRecordTypeCounts); result = NO; return; } } else { matches &= op.recordIDsToDelete.count == 0u; if(!matches) { - secnotice("fakecloudkit", "Deleted record number mismatch: %@ 0", deletedRecordTypeCounts); + secnotice("fakecloudkit", "Deleted record number mismatch: attempted:%@ expected:0", deletedRecordTypeCounts); result = NO; return; } @@ -812,10 +932,18 @@ } if(matches) { + if(inspectOperationGroup) { + inspectOperationGroup(op.group); + } + // Emulate cloudkit and schedule the operation for execution. Be sure to wait for this operation // if you'd like to read the data from this write. NSBlockOperation* ckop = [NSBlockOperation named:@"cloudkit-write" withBlock: ^{ @synchronized(zone.currentDatabase) { + if(zone.blockBeforeWriteOperation) { + zone.blockBeforeWriteOperation(); + } + NSMutableArray* savedRecords = [[NSMutableArray alloc] init]; for(CKRecord* record in op.recordsToSave) { CKRecord* reflectedRecord = [record copy]; @@ -1020,8 +1148,17 @@ } - (void)expectCKDeleteItemRecords:(NSUInteger)expectedNumberOfRecords - zoneID:(CKRecordZoneID*) zoneID { + zoneID:(CKRecordZoneID*)zoneID +{ + return [self expectCKDeleteItemRecords:expectedNumberOfRecords + zoneID:zoneID + expectedOperationGroupName:nil]; +} +- (void)expectCKDeleteItemRecords:(NSUInteger)expectedNumberOfRecords + zoneID:(CKRecordZoneID*)zoneID + expectedOperationGroupName:(NSString* _Nullable)operationGroupName +{ // We're updating the device state type on every update, so add it in here NSMutableDictionary* expectedRecords = [@{ SecCKRecordDeviceStateType: [NSNumber numberWithUnsignedInteger:expectedNumberOfRecords], @@ -1036,6 +1173,9 @@ deletedRecordTypeCounts:@{SecCKRecordItemType: [NSNumber numberWithUnsignedInteger: expectedNumberOfRecords]} zoneID:zoneID checkModifiedRecord:nil + inspectOperationGroup:operationGroupName != nil ? ^(CKOperationGroup* group) { + XCTAssertEqualObjects(group.name, operationGroupName, "Should have expected group name"); + } : nil runAfterModification:nil]; } @@ -1082,20 +1222,26 @@ } } + [self.injectedManager.zoneChangeFetcher halt]; + [super tearDown]; [self.injectedManager cancelPendingOperations]; - [CKKSViewManager resetManager:true setTo:nil]; + [self.injectedManager clearAllViews]; self.injectedManager = nil; + [self.mockCKKSViewManager stopMocking]; self.mockCKKSViewManager = nil; + self.injectedOTManager.viewManager = nil; + + [self.injectedOTManager clearAllContexts]; + self.injectedOTManager = nil; + [OTManager resetManager:true to:nil]; + [self.mockAccountStateTracker stopMocking]; self.mockAccountStateTracker = nil; - [self.mockLockStateTracker stopMocking]; - self.mockLockStateTracker = nil; - [self.mockFakeCKModifyRecordZonesOperation stopMocking]; self.mockFakeCKModifyRecordZonesOperation = nil; @@ -1130,6 +1276,29 @@ _mockSOSAdapter = nil; _mockOctagonAdapter = nil; + // Bring the database down and delete it + + NSURL* keychainDir = (NSURL*)CFBridgingRelease(SecCopyHomeURL()); + + // Force-close the analytics DBs so we can clean out the test directory + [[CKKSAnalytics logger] removeState]; + + SecItemDataSourceFactoryReleaseAll(); + SecKeychainDbForceClose(); + SecKeychainDbReset(NULL); + + // Only perform the desctructive step if the url matches what we expect! + if([keychainDir.path hasPrefix:[NSString stringWithFormat:@"/tmp/%@", testName]]) { + secnotice("ckkstest", "Removing test-specific keychain directory at %@", keychainDir); + + NSError* removeError = nil; + [[NSFileManager defaultManager] removeItemAtURL:keychainDir error:&removeError]; + + XCTAssertNil(removeError, "Should have been able to remove temporary files"); + } else { + XCTFail("Unsure what happened to the keychain directory URL: %@", keychainDir); + } + SecCKKSTestResetFlags(); } diff --git a/keychain/ckks/tests/MockCloudKit.h b/keychain/ckks/tests/MockCloudKit.h index 91226056..6267a478 100644 --- a/keychain/ckks/tests/MockCloudKit.h +++ b/keychain/ckks/tests/MockCloudKit.h @@ -120,6 +120,9 @@ typedef NSMutableDictionary FakeCKDatabase; // Serial queue. Use this for transactionality. @property dispatch_queue_t queue; +// Set this to run some code after a write operation has started, but before any results are delivered +@property (nullable) void (^blockBeforeWriteOperation)(void); + - (instancetype)initZone:(CKRecordZoneID*)zoneID; // Always Succeed diff --git a/keychain/ckks/tests/MockCloudKit.m b/keychain/ckks/tests/MockCloudKit.m index 1a15ff54..33775047 100644 --- a/keychain/ckks/tests/MockCloudKit.m +++ b/keychain/ckks/tests/MockCloudKit.m @@ -75,7 +75,7 @@ self.completionBlock = ^{ __strong __typeof(weakSelf) strongSelf = weakSelf; if(!strongSelf) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } @@ -121,7 +121,7 @@ if(!skipCreation) { // Create the zone: - secnotice("ckks", "Creating zone %@", zone); + ckksnotice_global("ckks", "Creating zone %@", zone); ckdb[zone.zoneID] = [[FakeCKZone alloc] initZone: zone.zoneID]; } @@ -213,7 +213,7 @@ self.completionBlock = ^{ __strong __typeof(weakSelf) strongSelf = weakSelf; if(!strongSelf) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } @@ -291,6 +291,8 @@ @synthesize recordZoneFetchCompletionBlock = _recordZoneFetchCompletionBlock; @synthesize fetchRecordZoneChangesCompletionBlock = _fetchRecordZoneChangesCompletionBlock; +@synthesize deviceIdentifier = _deviceIdentifier; + @synthesize operationID = _operationID; @synthesize resolvedConfiguration = _resolvedConfiguration; @synthesize group = _group; @@ -313,6 +315,7 @@ _configurationsByRecordZoneID = configurationsByRecordZoneID; _operationID = @"fake-operation-ID"; + _deviceIdentifier = @"ckkstests"; } return self; } @@ -422,11 +425,10 @@ self.recordZoneChangeTokensUpdatedBlock(zoneID, currentChangeToken, nil); self.recordZoneFetchCompletionBlock(zoneID, currentChangeToken, nil, moreComing, opError); + } - if(self.blockAfterFetch) { - self.blockAfterFetch(); - } - + if(self.blockAfterFetch) { + self.blockAfterFetch(); } self.fetchRecordZoneChangesCompletionBlock(nil); @@ -598,18 +600,15 @@ @implementation FakeAPSConnection @synthesize delegate; +@synthesize enabledTopics; +@synthesize opportunisticTopics; +@synthesize darkWakeTopics; + - (id)initWithEnvironmentName:(NSString *)environmentName namedDelegatePort:(NSString*)namedDelegatePort queue:(dispatch_queue_t)queue { if(self = [super init]) { } return self; } - -- (void)setEnabledTopics:(NSArray *)enabledTopics { -} - -- (void)setDarkWakeTopics:(NSArray *)darkWakeTopics { -} - @end // Do literally nothing @@ -767,10 +766,14 @@ - (NSError*)deleteCKRecordIDFromZone:(CKRecordID*) recordID { // todo: fail somehow dispatch_sync(self.queue, ^{ + ckksnotice("fakeck", self.zoneID, "Change token before server-deleted record is : %@", self.currentChangeToken); + self.pastDatabases[self.currentChangeToken] = [self.currentDatabase mutableCopy]; [self _onqueueRollChangeToken]; [self.currentDatabase removeObjectForKey: recordID]; + + ckksnotice("fakeck", self.zoneID, "Change token after server-deleted record is : %@", self.currentChangeToken); }); return nil; } @@ -824,7 +827,7 @@ if(notification) { // This isn't actually fake, but XCTest likes NSNotificationCenter a whole lot. // These notifications shouldn't escape this process, so it's perfect. - secnotice("ckks", "sending fake NSNotification %@", notification); + ckksnotice_global("ckks", "sending fake NSNotification %@", notification); [[NSNotificationCenter defaultCenter] postNotificationName:notification object:nil]; } } diff --git a/keychain/ckks/tests/OctagonAPSReceiverTests.m b/keychain/ckks/tests/OctagonAPSReceiverTests.m index 12ae14e6..18970fcb 100644 --- a/keychain/ckks/tests/OctagonAPSReceiverTests.m +++ b/keychain/ckks/tests/OctagonAPSReceiverTests.m @@ -33,7 +33,7 @@ #if OCTAGON -@interface CKKSAPSNotificationReceiver : NSObject +@interface CKKSAPSNotificationReceiver : NSObject @property XCTestExpectation* expectation; @property void (^block)(CKRecordZoneNotification* notification); @@ -107,9 +107,8 @@ - (void)testRegisterAndReceive { __weak __typeof(self)weakSelf = self; - OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithEnvironmentName:@"testenvironment" - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsr, "Should have received a OctagonAPSReceiver"); @@ -121,7 +120,7 @@ XCTAssertEqual(strongSelf.testZoneID, notification.recordZoneID, "Should have received a notification for the test zone"); }]; - CKKSCondition* registered = [apsr registerReceiver:anr forZoneID:self.testZoneID]; + CKKSCondition* registered = [apsr registerCKKSReceiver:anr]; XCTAssertEqual(0, [registered wait:1*NSEC_PER_SEC], "Registration should have completed within a second"); APSIncomingMessage* message = [OctagonAPSReceiverTests messageForZoneID:self.testZoneID]; XCTAssertNotNil(message, "Should have received a APSIncomingMessage"); @@ -131,46 +130,9 @@ [self waitForExpectationsWithTimeout:5.0 handler:nil]; } -- (void)testRegisterMultipleAndReceive { - __weak __typeof(self)weakSelf = self; - - OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithEnvironmentName:@"testenvironment" - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; - - XCTAssertNotNil(apsr, "Should have received a OctagonAPSReceiver"); - - CKRecordZoneID* otherZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"otherzone" ownerName:CKCurrentUserDefaultName]; - - CKKSAPSNotificationReceiver* anr = [[CKKSAPSNotificationReceiver alloc] initWithExpectation:[self expectationWithDescription:@"receive testZoneID notification"] - block: - ^(CKRecordZoneNotification* notification) { - __strong __typeof(self) strongSelf = weakSelf; - XCTAssertNotNil(notification, "Should have received a notification"); - XCTAssertEqual(strongSelf.testZoneID, notification.recordZoneID, "Should have received a notification for the test zone"); - }]; - CKKSAPSNotificationReceiver* anr2 = [[CKKSAPSNotificationReceiver alloc] initWithExpectation:[self expectationWithDescription:@"receive otherzone notification"] - block: - ^(CKRecordZoneNotification* notification) { - XCTAssertNotNil(notification, "Should have received a notification"); - XCTAssertEqual(otherZoneID, notification.recordZoneID, "Should have received a notification for the test zone"); - }]; - - CKKSCondition* registered = [apsr registerReceiver:anr forZoneID:self.testZoneID]; - CKKSCondition* registered2 = [apsr registerReceiver:anr2 forZoneID:otherZoneID]; - XCTAssertEqual(0, [registered wait:1*NSEC_PER_SEC], "Registration should have completed within a second"); - XCTAssertEqual(0, [registered2 wait:1*NSEC_PER_SEC], "Registration should have completed within a second"); - - [apsr connection:apsr.apsConnection didReceiveIncomingMessage:[OctagonAPSReceiverTests messageForZoneID:self.testZoneID]]; - [apsr connection:apsr.apsConnection didReceiveIncomingMessage:[OctagonAPSReceiverTests messageForZoneID:otherZoneID]]; - - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - - (void)testReceiveNotificationIfRegisteredAfterDelivery { - OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithEnvironmentName:@"testenvironment" - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsr, "Should have received a OctagonAPSReceiver"); // Receives a notification for the test zone @@ -184,7 +146,7 @@ XCTAssertNotNil(notification, "Should have received a (stored) notification"); }]; - CKKSCondition* registered = [apsr registerReceiver:anr forZoneID:self.testZoneID]; + CKKSCondition* registered = [apsr registerCKKSReceiver:anr]; XCTAssertEqual(0, [registered wait:1*NSEC_PER_SEC], "Registration should have completed within a second"); [self waitForExpectationsWithTimeout:5.0 handler:nil]; diff --git a/keychain/ckks/tests/RateLimiterTests.m b/keychain/ckks/tests/RateLimiterTests.m index 67f906bc..03c8056f 100644 --- a/keychain/ckks/tests/RateLimiterTests.m +++ b/keychain/ckks/tests/RateLimiterTests.m @@ -33,16 +33,14 @@ @implementation TestObject - (instancetype)init { - self = [super init]; - if (self) { + if ((self = [super init])) { _uuid = [[NSUUID UUID] UUIDString]; } return self; } - (instancetype)initWithNilUuid { - self = [super init]; - if (self) { + if ((self = [super init])) { _uuid = nil; } return self; diff --git a/keychain/ckks/tests/gen_test_plist.py b/keychain/ckks/tests/gen_test_plist.py new file mode 100644 index 00000000..d3b6db8c --- /dev/null +++ b/keychain/ckks/tests/gen_test_plist.py @@ -0,0 +1,78 @@ +#!/usr/bin/python +# +# TODO(kirk or SEAR/QA) after radar 53867279 is fixed, please delete this script +# +# WARNING: if you add new tests to the swift octagon tests, it is possible that +# this script will not find them and then your new tests will not get executed +# in BATS! +# +import sys +import Foundation +from glob import glob +import re +import os +import pprint + +test_dir = sys.argv[1] +outfile = sys.argv[2] + +test_plist = Foundation.NSMutableDictionary.dictionary() +test_plist['BATSConfigVersion'] = '0.1.0' +test_plist['Project'] = 'Security' +test_list = Foundation.NSMutableArray.array() + +test_files = glob(test_dir + '/*.m') + glob(test_dir + '/*.h') + +def get_class_names(): + test_classes = ['CKKSLaunchSequenceTests'] + for filename in test_files: + f = open(filename, 'r') + for line in f: + match = re.search('@interface ([a-zA-Z0-9_]+) ?: ?CloudKitKeychain[a-zA-Z0-9_]*TestsBase', line) + #match = re.search('class (([a-zA-Z0-9_]+Tests)|(OctagonTests[a-zA-Z0-9_]*(? - - - - BATSConfigVersion - 0.1.0 - Project - Security - Tests - - - TestName - CKKSTests - WorkingDirectory - /AppleInternal/XCTests/com.apple.security/ - ShowSubtestResults - - Timeout - 1200 - Command - - BATS_XCTEST_CMD CKKSTests.xctest - - - - - - diff --git a/keychain/ckksctl/ckksctl.m b/keychain/ckksctl/ckksctl.m index bad4d21b..48d96d62 100644 --- a/keychain/ckksctl/ckksctl.m +++ b/keychain/ckksctl/ckksctl.m @@ -284,7 +284,7 @@ static void print_entry(id k, id v, int ind) return status; } -- (void)printHumanReadableStatus: (NSString*) view { +- (void)printHumanReadableStatus:(NSString*)view shortenOutput:(BOOL)shortenOutput { #if OCTAGON dispatch_semaphore_t sema = dispatch_semaphore_create(0); @@ -306,15 +306,25 @@ static void print_entry(id k, id v, int ind) NSString* lockStateTracker = pop(global,@"lockstatetracker", NSString); NSString* retry = pop(global,@"cloudkitRetryAfter", NSString); NSDate *lastCKKSPush = pop(global, @"lastCKKSPush", NSDate); + NSString *syncingPolicy = pop(global, @"policy", NSString); + NSString *viewsFromPolicy = pop(global, @"viewsFromPolicy", NSString); - printf("================================================================================\n\n"); - printf("Global state:\n\n"); - printf("Reachability: %s\n", [[reachability description] UTF8String]); - printf("Retry: %s\n", [[retry description] UTF8String]); - printf("CK DeviceID: %s\n", [[ckdeviceID description] UTF8String]); - printf("CK DeviceID Error: %s\n", [[ckdeviceIDError description] UTF8String]); - printf("Lock state: %s\n", [[lockStateTracker description] UTF8String]); - printf("Last CKKS push: %s\n", [[lastCKKSPush description] UTF8String]); + if(!shortenOutput) { + printf("================================================================================\n\n"); + printf("Global state:\n\n"); + } + + printf("Syncing Policy: %s\n", [[syncingPolicy description] UTF8String]); + printf("Views from policy: %s\n", [[viewsFromPolicy description] UTF8String]); + + if(!shortenOutput) { + printf("Reachability: %s\n", [[reachability description] UTF8String]); + printf("Retry: %s\n", [[retry description] UTF8String]); + printf("CK DeviceID: %s\n", [[ckdeviceID description] UTF8String]); + printf("CK DeviceID Error: %s\n", [[ckdeviceIDError description] UTF8String]); + printf("Lock state: %s\n", [[lockStateTracker description] UTF8String]); + printf("Last CKKS push: %s\n", [[lastCKKSPush description] UTF8String]); + } printf("\n"); } @@ -326,6 +336,16 @@ static void print_entry(id k, id v, int ind) } for(NSDictionary* viewStatus in remainingViews) { + if(shortenOutput) { + NSMutableDictionary* status = [viewStatus mutableCopy]; + + NSString* viewName = pop(status, @"view", NSString); + NSString* keystate = pop(status, @"keystate", NSString); + + printf("%-25s: %s\n", [viewName UTF8String], [keystate UTF8String]); + continue; + } + NSMutableDictionary* status = [viewStatus mutableCopy]; NSString* viewName = pop(status,@"view", NSString); @@ -333,20 +353,17 @@ static void print_entry(id k, id v, int ind) NSString* accountTracker = pop(status,@"accounttracker", NSString); NSString* fetcher = pop(status,@"fetcher", NSString); NSString* zoneCreated = pop(status,@"zoneCreated", NSString); - NSString* zoneCreatedError = pop(status,@"zoneCreatedError", NSString); NSString* zoneSubscribed = pop(status,@"zoneSubscribed", NSString); - NSString* zoneSubscribedError = pop(status,@"zoneSubscribedError", NSString); NSString* zoneInitializeScheduler = pop(status,@"zoneInitializeScheduler", NSString); NSString* keystate = pop(status,@"keystate", NSString); - NSString* keyStateError = pop(status,@"keyStateError", NSString); NSString* statusError = pop(status,@"statusError", NSString); + NSString* itemSyncEnabled = pop(status,@"itemsyncing", NSString); NSString* currentTLK = pop(status,@"currentTLK", NSString); NSString* currentClassA = pop(status,@"currentClassA", NSString); NSString* currentClassC = pop(status,@"currentClassC", NSString); NSString* currentTLKPtr = pop(status,@"currentTLKPtr", NSString); NSString* currentClassAPtr = pop(status,@"currentClassAPtr", NSString); NSString* currentClassCPtr = pop(status,@"currentClassCPtr", NSString); - NSString* currentManifestGeneration = pop(status,@"currentManifestGen", NSString); NSArray* launchSequence = pop(status, @"launchSequence", NSArray); NSDictionary* oqe = pop(status,@"oqe", NSDictionary); @@ -356,14 +373,11 @@ static void print_entry(id k, id v, int ind) NSArray* devicestates = pop(status, @"devicestates", NSArray); NSArray* tlkshares = pop(status, @"tlkshares", NSArray); - NSString* zoneSetupOperation = pop(status,@"zoneSetupOperation", NSString); - NSString* keyStateOperation = pop(status,@"keyStateOperation", NSString); NSString* lastIncomingQueueOperation = pop(status,@"lastIncomingQueueOperation", NSString); NSString* lastNewTLKOperation = pop(status,@"lastNewTLKOperation", NSString); NSString* lastOutgoingQueueOperation = pop(status,@"lastOutgoingQueueOperation", NSString); NSString* lastProcessReceivedKeysOperation = pop(status,@"lastProcessReceivedKeysOperation", NSString); NSString* lastReencryptOutgoingItemsOperation = pop(status,@"lastReencryptOutgoingItemsOperation", NSString); - NSString* lastScanLocalItemsOperation = pop(status,@"lastScanLocalItemsOperation", NSString); printf("================================================================================\n\n"); @@ -378,18 +392,12 @@ static void print_entry(id k, id v, int ind) if(!([zoneCreated isEqualToString:@"yes"] && [zoneSubscribed isEqualToString:@"yes"])) { printf("CK Zone Created: %s\n", [[zoneCreated description] UTF8String]); - printf("CK Zone Created error: %s\n", [[zoneCreatedError description] UTF8String]); - printf("CK Zone Subscribed: %s\n", [[zoneSubscribed description] UTF8String]); - printf("CK Zone Subscription error: %s\n", [[zoneSubscribedError description] UTF8String]); printf("CK Zone initialize retry: %s\n", [[zoneInitializeScheduler description] UTF8String]); printf("\n"); } printf("Key state: %s\n", [keystate UTF8String]); - if(keyStateError != nil) { - printf("Key State Error: %s\n", [keyStateError UTF8String]); - } printf("Current TLK: %s\n", currentTLK != nil ? [currentTLK UTF8String] : [[NSString stringWithFormat:@"missing; pointer is %@", currentTLKPtr] UTF8String]); @@ -402,23 +410,20 @@ static void print_entry(id k, id v, int ind) printf("TLK shares: %s\n", [[tlkshares description] UTF8String]); + printf("Item syncing: %s\n", [[itemSyncEnabled description] UTF8String]); printf("Outgoing Queue counts: %s\n", [[oqe description] UTF8String]); printf("Incoming Queue counts: %s\n", [[iqe description] UTF8String]); printf("Key counts: %s\n", [[keys description] UTF8String]); - printf("latest manifest generation: %s\n", currentManifestGeneration == nil ? "null" : currentManifestGeneration.UTF8String); printf("Item counts (by key): %s\n", [[ckmirror description] UTF8String]); printf("Peer states: %s\n", [[devicestates description] UTF8String]); printf("zone change fetcher: %s\n", [[fetcher description] UTF8String]); - printf("zoneSetupOperation: %s\n", zoneSetupOperation == nil ? "never" : [zoneSetupOperation UTF8String]); - printf("keyStateOperation: %s\n", keyStateOperation == nil ? "never" : [keyStateOperation UTF8String]); printf("lastIncomingQueueOperation: %s\n", lastIncomingQueueOperation == nil ? "never" : [lastIncomingQueueOperation UTF8String]); printf("lastNewTLKOperation: %s\n", lastNewTLKOperation == nil ? "never" : [lastNewTLKOperation UTF8String]); printf("lastOutgoingQueueOperation: %s\n", lastOutgoingQueueOperation == nil ? "never" : [lastOutgoingQueueOperation UTF8String]); printf("lastProcessReceivedKeysOperation: %s\n", lastProcessReceivedKeysOperation == nil ? "never" : [lastProcessReceivedKeysOperation UTF8String]); printf("lastReencryptOutgoingItemsOperation: %s\n", lastReencryptOutgoingItemsOperation == nil ? "never" : [lastReencryptOutgoingItemsOperation UTF8String]); - printf("lastScanLocalItemsOperation: %s\n", lastScanLocalItemsOperation == nil ? "never" : [lastScanLocalItemsOperation UTF8String]); printf("Launch sequence:\n"); for (NSString *event in launchSequence) { @@ -456,7 +461,8 @@ static void print_entry(id k, id v, int ind) dispatch_semaphore_signal(sema); }]; - if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 65)) != 0) { + // The maximum device-side delay to start a fetch is 120s, so we must wait longer than that for a response. + if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 135)) != 0) { printf("\n\nError: timed out waiting for response\n"); return -1; } @@ -525,6 +531,7 @@ static int resetCloudKit = false; static int fetch = false; static int push = false; static int json = false; +static int shortOutput = false; static int ckmetric = false; static char* viewArg = NULL; @@ -534,6 +541,7 @@ int main(int argc, char **argv) static struct argument options[] = { { .shortname='p', .longname="perfcounters", .flag=&perfCounters, .flagval=true, .description="Print CKKS performance counters"}, { .shortname='j', .longname="json", .flag=&json, .flagval=true, .description="Output in JSON format"}, + { .shortname='s', .longname="short", .flag=&shortOutput, .flagval=true, .description="Output a short format"}, { .shortname='v', .longname="view", .argument=&viewArg, .description="Operate on a single view"}, { .command="status", .flag=&status, .flagval=true, .description="Report status on CKKS views"}, @@ -585,7 +593,7 @@ int main(int argc, char **argv) } if(!json) { - [ctl printHumanReadableStatus:view]; + [ctl printHumanReadableStatus:view shortenOutput:shortOutput]; } return 0; } else if(perfCounters) { diff --git a/keychain/escrowrequest/EscrowRequestController.m b/keychain/escrowrequest/EscrowRequestController.m index 517279ee..ee477af4 100644 --- a/keychain/escrowrequest/EscrowRequestController.m +++ b/keychain/escrowrequest/EscrowRequestController.m @@ -45,7 +45,8 @@ OctagonState* const EscrowRequestStateWaitForUnlock = (OctagonState*)@"wait_for_ initialState:EscrowRequestStateNothingToDo queue:_queue stateEngine:self - lockStateTracker:lockStateTracker]; + lockStateTracker:lockStateTracker + reachabilityTracker:nil]; _forceIgnoreCloudServicesRateLimiting = false; } @@ -57,6 +58,7 @@ OctagonState* const EscrowRequestStateWaitForUnlock = (OctagonState*)@"wait_for_ flags:(nonnull OctagonFlags *)flags pendingFlags:(nonnull id)pendingFlagHandler { + dispatch_assert_queue(self.queue); if([flags _onqueueContains:OctagonFlagEscrowRequestInformCloudServicesOperation]) { [flags _onqueueRemoveFlag:OctagonFlagEscrowRequestInformCloudServicesOperation]; return [[EscrowRequestInformCloudServicesOperation alloc] initWithIntendedState:EscrowRequestStateNothingToDo diff --git a/keychain/escrowrequest/EscrowRequestXPCProtocol.m b/keychain/escrowrequest/EscrowRequestXPCProtocol.m index 2bdaa7ae..a35ad32f 100644 --- a/keychain/escrowrequest/EscrowRequestXPCProtocol.m +++ b/keychain/escrowrequest/EscrowRequestXPCProtocol.m @@ -1,51 +1,27 @@ #import #import +#import #import "keychain/escrowrequest/EscrowRequestXPCProtocol.h" #import "utilities/debugging.h" NSXPCInterface* SecEscrowRequestSetupControlProtocol(NSXPCInterface* interface) { - static NSMutableSet *errClasses; - - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - errClasses = [NSMutableSet set]; - char *classes[] = { - "NSArray", - "NSData", - "NSDate", - "NSDictionary", - "NSError", - "NSNull", - "NSNumber", - "NSOrderedSet", - "NSSet", - "NSString", - "NSURL", - }; - - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) { - [errClasses addObject:cls]; - } - } - }); + NSSet* errClasses = [SecXPCHelper safeErrorClasses]; @try { [interface setClasses:errClasses forSelector:@selector(triggerEscrowUpdate:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(cachePrerecord:serializedPrerecord:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(fetchPrerecord:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(fetchRequestWaitingOnPasscode:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchRequestStatuses:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(resetAllRequests:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(storePrerecordsInEscrow:) argumentIndex:1 ofReply:YES]; } @catch(NSException* e) { secerror("SecEscrowRequestSetupControlProtocol failed, continuing, but you might crash later: %@", e); -#if DEBUG @throw e; -#endif } return interface; diff --git a/keychain/escrowrequest/Framework/SecEscrowRequest.m b/keychain/escrowrequest/Framework/SecEscrowRequest.m index b386705f..8432a1f1 100644 --- a/keychain/escrowrequest/Framework/SecEscrowRequest.m +++ b/keychain/escrowrequest/Framework/SecEscrowRequest.m @@ -10,8 +10,6 @@ NSString* const SecEscrowRequestHavePrecord = @"have_prerecord"; NSString* const SecEscrowRequestPendingPasscode = @"pending_passcode"; NSString* const SecEscrowRequestPendingCertificate = @"pending_certificate"; -// `!defined(DARLING)` is used to indicate that normally (in Apple's original code) the body is present without a conditional -#if !defined(DARLING) || defined(__OBJC2__) @interface SecEscrowRequest () @property NSXPCConnection *connection; @end @@ -248,5 +246,3 @@ NSString* const SecEscrowRequestPendingCertificate = @"pending_certificate"; } @end - -#endif // !defined(DARLING) || defined(__OBJC2__) diff --git a/keychain/escrowrequest/generated_source/SecEscrowPendingRecord.m b/keychain/escrowrequest/generated_source/SecEscrowPendingRecord.m index 689908a9..6dd81f06 100644 --- a/keychain/escrowrequest/generated_source/SecEscrowPendingRecord.m +++ b/keychain/escrowrequest/generated_source/SecEscrowPendingRecord.m @@ -30,7 +30,7 @@ } - (BOOL)hasCertCached { - return _has.certCached; + return _has.certCached != 0; } - (BOOL)hasSerializedPrerecord { @@ -49,7 +49,7 @@ } - (BOOL)hasLastCloudServicesTriggerTime { - return _has.lastCloudServicesTriggerTime; + return _has.lastCloudServicesTriggerTime != 0; } @synthesize lastEscrowAttemptTime = _lastEscrowAttemptTime; - (void)setLastEscrowAttemptTime:(uint64_t)v @@ -63,7 +63,7 @@ } - (BOOL)hasLastEscrowAttemptTime { - return _has.lastEscrowAttemptTime; + return _has.lastEscrowAttemptTime != 0; } @synthesize uploadCompleted = _uploadCompleted; - (void)setUploadCompleted:(BOOL)v @@ -77,7 +77,7 @@ } - (BOOL)hasUploadCompleted { - return _has.uploadCompleted; + return _has.uploadCompleted != 0; } @synthesize uploadRetries = _uploadRetries; - (void)setUploadRetries:(uint64_t)v @@ -91,7 +91,7 @@ } - (BOOL)hasUploadRetries { - return _has.uploadRetries; + return _has.uploadRetries != 0; } - (BOOL)hasAltDSID { @@ -110,7 +110,7 @@ } - (BOOL)hasTriggerRequestTime { - return _has.triggerRequestTime; + return _has.triggerRequestTime != 0; } - (NSString *)description diff --git a/keychain/escrowrequest/operations/EscrowRequestPerformEscrowEnrollOperation.m b/keychain/escrowrequest/operations/EscrowRequestPerformEscrowEnrollOperation.m index 758884c0..d8f5d535 100644 --- a/keychain/escrowrequest/operations/EscrowRequestPerformEscrowEnrollOperation.m +++ b/keychain/escrowrequest/operations/EscrowRequestPerformEscrowEnrollOperation.m @@ -83,6 +83,11 @@ SecEscrowPendingRecord* record = nil; for(SecEscrowPendingRecord* existingRecord in records) { + if(existingRecord.uploadCompleted) { + secnotice("escrowrequest", "Skipping completed escrow request (%@)", existingRecord); + continue; + } + if(self.enforceRateLimiting && [existingRecord escrowAttemptedWithinLastSeconds:5*60]) { secnotice("escrowrequest", "Skipping pending escrow request (%@); it's rate limited", existingRecord); continue; diff --git a/keychain/escrowrequest/tests/SecEscrowRequestTests.m b/keychain/escrowrequest/tests/SecEscrowRequestTests.m index d504c786..a9dba90e 100644 --- a/keychain/escrowrequest/tests/SecEscrowRequestTests.m +++ b/keychain/escrowrequest/tests/SecEscrowRequestTests.m @@ -68,7 +68,7 @@ OCMStub([mockConnection synchronousRemoteObjectProxyWithErrorHandler:[OCMArg any]]).andCall(self, @selector(synchronousEscrowServer)); self.escrowRequest = [[SecEscrowRequest alloc] initWithConnection:mockConnection]; - SetCustomHomeURLString((__bridge CFStringRef) tmp_dir); + SecSetCustomHomeURLString((__bridge CFStringRef) tmp_dir); SecKeychainDbReset(NULL); // Actually load the database. diff --git a/keychain/headers/SecAccessControl.h b/keychain/headers/SecAccessControl.h index 5b66b242..5d54f581 100644 --- a/keychain/headers/SecAccessControl.h +++ b/keychain/headers/SecAccessControl.h @@ -94,7 +94,7 @@ typedef CF_OPTIONS(CFOptionFlags, SecAccessControlCreateFlags) { kSecAccessControlBiometryCurrentSet API_AVAILABLE(macos(10.13.4), ios(11.3)) = 1u << 3, kSecAccessControlTouchIDCurrentSet API_DEPRECATED_WITH_REPLACEMENT("kSecAccessControlBiometryCurrentSet", macos(10.12.1, 10.13.4), ios(9.0, 11.3)) = 1u << 3, kSecAccessControlDevicePasscode API_AVAILABLE(macos(10.11), ios(9.0)) = 1u << 4, - kSecAccessControlWatch API_AVAILABLE(macos(10.15), ios(NA), iosmac(13.0)) = 1u << 5, + kSecAccessControlWatch API_AVAILABLE(macos(10.15), ios(NA), macCatalyst(13.0)) = 1u << 5, kSecAccessControlOr API_AVAILABLE(macos(10.12.1), ios(9.0)) = 1u << 14, kSecAccessControlAnd API_AVAILABLE(macos(10.12.1), ios(9.0)) = 1u << 15, kSecAccessControlPrivateKeyUsage API_AVAILABLE(macos(10.12.1), ios(9.0)) = 1u << 30, diff --git a/keychain/headers/SecIdentity.h b/keychain/headers/SecIdentity.h index ea002f3e..08776cfd 100644 --- a/keychain/headers/SecIdentity.h +++ b/keychain/headers/SecIdentity.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2011,2012-2013,2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2011,2012-2013,2016-2021 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -119,7 +119,7 @@ OSStatus SecIdentityCopyPreference(CFStringRef name, CSSM_KEYUSE keyUsage, CFArr @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to ignore this parameter. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) @param validIssuers (optional) An array of CFDataRef instances whose contents are the subject names of allowable issuers, as returned by a call to SSLCopyDistinguishedNames (SecureTransport.h). Pass NULL if any issuer is allowed. @result An identity or NULL, if the preferred identity has not been set. Your code should then typically perform a search for possible identities using the SecItem APIs. - @discussion If a preferred identity has not been set for the supplied name, the returned identity reference will be NULL. Your code should then perform a search for possible identities, using the SecItemCopyMatching API. + @discussion If a preferred identity has not been set for the supplied name, the returned identity reference will be NULL. Your code should then perform a search for possible identities, using the SecItemCopyMatching API. Note: in versions of macOS prior to 11.3, identity preferences are shared between processes running as the same user. Starting in 11.3, URI names are considered per-application preferences. An identity preference for a URI name may not be found if the calling application is different from the one which set the preference with SecIdentitySetPreferred. */ __nullable SecIdentityRef SecIdentityCopyPreferred(CFStringRef name, CFArrayRef __nullable keyUsage, CFArrayRef __nullable validIssuers) @@ -144,6 +144,7 @@ OSStatus SecIdentitySetPreference(SecIdentityRef identity, CFStringRef name, CSS @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies a service requiring this identity. @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to specify any key usage. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Note: in versions of macOS prior to 11.3, identity preferences are shared between processes running as the same user. Starting in 11.3, URI names are considered per-application preferences. An identity preference for a URI name will be scoped to the application which created it, such that a subsequent call to SecIdentityCopyPreferred will only return it for that same application. */ OSStatus SecIdentitySetPreferred(SecIdentityRef __nullable identity, CFStringRef name, CFArrayRef __nullable keyUsage) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); diff --git a/keychain/headers/SecIdentityPriv.h b/keychain/headers/SecIdentityPriv.h index 99a62abb..20d3b861 100644 --- a/keychain/headers/SecIdentityPriv.h +++ b/keychain/headers/SecIdentityPriv.h @@ -51,91 +51,6 @@ SecIdentityRef SecIdentityCreate( //__OSX_AVAILABLE_STARTING(__MAC_10_3, __SEC_IPHONE_UNKNOWN); #if SEC_OS_OSX -/*! - @function SecIdentityCompare - @abstract Compares two SecIdentityRef instances for equality. - @param identity1 An identity reference. - @param identity2 An identity reference. - @param compareOptions A value containing option flags. Currently there are no compare options, so 0 should be passed for this parameter. - @result An enumerated value of type CFComparisonResult. See CFBase.h. - @discussion Two identities are considered equal if they contain identical certificate and private key components. - @deprecated in Mac OS X 10.5 and later; the CFEqual function should be used instead (CFBase.h). - */ -CFComparisonResult SecIdentityCompare( - SecIdentityRef identity1, - SecIdentityRef identity2, - CFOptionFlags compareOptions) - DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; - -/*! - @function SecIdentityFindPreferenceItem - @abstract Returns an identity preference item, given an identity string. - @param keychainOrArray A reference to an array of keychains to search, a single keychain, or NULL to search the user's default keychain search list. - @param idString A string containing a URI, hostname, or email (RFC822) address. - @param itemRef On return, a reference to the keychain item which was found. The caller is responsible for releasing this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion An identity preference item maps a particular identity to a string, such as a URI or email address. It specifies that this identity should be preferred in transactions which match the provided string. - @deprecated in Mac OS X 10.7 and later; use SecIdentityCopyPreferred() instead (SecIdentity.h) - - WARNING: This function is based on an implementation detail and will go away - in a future release; its use should be avoided at all costs. It does not - provide a way to find a preference item based on key usage, and it can only - find preferences which are stored as keychain items, so it may fail to find - the item you expect. Please use the public API functions to manipulate - identity preferences. -*/ -OSStatus SecIdentityFindPreferenceItem( - CFTypeRef keychainOrArray, - CFStringRef idString, - SecKeychainItemRef *itemRef) - API_DEPRECATED_WITH_REPLACEMENT("SecIdentityCopyPreferred", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - -/*! - @function SecIdentityAddPreferenceItem - @abstract Adds a new identity preference item to the specified keychain. - @param keychainRef A reference to the keychain in which to store the preference item. Pass NULL to specify the user's default keychain. - @param identityRef An identity reference. - @param idString A string containing a URI, hostname, or email (RFC822) address. - @param itemRef On return, a reference to the new keychain item. The caller is responsible for releasing this reference. Pass NULL if the reference is not needed. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion An identity preference item maps a particular identity to a string, such as a URI or email address. It specifies that this identity should be preferred in transactions which match the provided string. - @deprecated in Mac OS X 10.5; use SecIdentitySetPreference() instead (SecIdentity.h). -*/ -OSStatus SecIdentityAddPreferenceItem( - SecKeychainRef keychainRef, - SecIdentityRef identityRef, - CFStringRef idString, - SecKeychainItemRef *itemRef) - API_DEPRECATED_WITH_REPLACEMENT("SecIdentitySetPreference", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - -/*! - @function SecIdentityUpdatePreferenceItem - @abstract Given an existing identity preference keychain item, update it with the provided identity. - @param itemRef An identity preference keychain item, as returned by SecIdentityFindPreferenceItem or SecIdentityAddPreferenceItem. - @param identityRef An identity reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is used to update an existing preference item when a different identity is preferred. - @deprecated in Mac OS X 10.5; use SecIdentitySetPreference() instead (SecIdentity.h). -*/ -OSStatus SecIdentityUpdatePreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef identityRef) - API_DEPRECATED_WITH_REPLACEMENT("SecIdentitySetPreference", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - -/*! - @function SecIdentityCopyFromPreferenceItem - @abstract Given an existing identity preference keychain item, obtain a SecIdentityRef for the identity it specifies. - @param itemRef An identity preference keychain item, as returned by SecIdentityFindPreferenceItem or SecIdentityAddPreferenceItem. - @param identityRef On return, an identity reference. The caller is responsible for releasing this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is used to obtain a SecIdentityRef from an existing preference item. - @deprecated in Mac OS X 10.5; use SecIdentityCopyPreference() instead (SecIdentity.h). -*/ -OSStatus SecIdentityCopyFromPreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef *identityRef) - API_DEPRECATED_WITH_REPLACEMENT("SecIdentityCopyPreference", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - /*! @function ConvertArrayToKeyUsage @abstract Given an array of key usages defined in SecItem.h return the equivalent CSSM_KEYUSE @@ -152,6 +67,21 @@ OSStatus SecIdentityCopyFromPreferenceItem( */ CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage) __SEC_MAC_ONLY_UNKNOWN; + +/*! + @function SecIdentityDeleteApplicationPreferenceItems + @abstract Delete identity preference items created by the calling application. + @result errSecSuccess on successful deletion, or errSecItemNotFound if no items + were found to be deleted. Other keychain error results may be possible (SecBase.h). + @discussion This function deletes all identity preference items which match the + application identifier of the caller. This implies that items to be deleted were + created with SecIdentitySetPreferred on a version of macOS where this function + is implemented, since older versions of macOS did not add application identifier + information. Note: currently, deletion is also limited to preference items whose + name is in URI format. +*/ +OSStatus SecIdentityDeleteApplicationPreferenceItems(void); + #endif // SEC_OS_OSX __END_DECLS diff --git a/keychain/headers/SecImportExport.h b/keychain/headers/SecImportExport.h index c6c91c6a..ba56a792 100644 --- a/keychain/headers/SecImportExport.h +++ b/keychain/headers/SecImportExport.h @@ -149,7 +149,7 @@ typedef CF_OPTIONS(uint32_t, SecKeyImportExportFlags) /* * Parameters specific to SecKeyRefs. */ -typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) +typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) { /* for import and export */ uint32_t version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */ @@ -166,10 +166,10 @@ typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) CSSM_KEYUSE keyUsage; /* CSSM_KEYUSE_DECRYPT, CSSM_KEYUSE_SIGN, * etc. */ CSSM_KEYATTR_FLAGS keyAttributes; /* CSSM_KEYATTR_PERMANENT, etc. */ -} SecKeyImportExportParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +} SecKeyImportExportParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) +typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) { /* for import and export */ uint32_t version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */ @@ -194,7 +194,7 @@ typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) * - kSecAttrIsSensitive for private keys * - kSecAttrIsExtractable by default */ -} SecItemImportExportKeyParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +} SecItemImportExportKeyParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * SecKeychainItemExport() @@ -254,7 +254,7 @@ OSStatus SecKeychainItemExport( SecItemImportExportFlags flags, /* kSecItemPemArmour, etc. */ const SecKeyImportExportParameters * __nullable keyParams, /* optional */ CFDataRef * __nonnull CF_RETURNS_RETAINED exportedData) /* external representation returned here */ - API_DEPRECATED_WITH_REPLACEMENT("SecItemExport", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecItemExport", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * SecItemExport() @@ -472,7 +472,7 @@ OSStatus SecKeychainItemImport( const SecKeyImportExportParameters * __nullable keyParams, /* optional */ SecKeychainRef __nullable importKeychain, /* optional */ CFArrayRef * __nullable CF_RETURNS_RETAINED outItems) /* optional */ - API_DEPRECATED_WITH_REPLACEMENT("SecItemImport", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecItemImport", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * SecItemImport() diff --git a/keychain/headers/SecImportExportPriv.h b/keychain/headers/SecImportExportPriv.h index 6d43101f..c70c3958 100644 --- a/keychain/headers/SecImportExportPriv.h +++ b/keychain/headers/SecImportExportPriv.h @@ -10,7 +10,7 @@ CF_IMPLICIT_BRIDGING_ENABLED #if TARGET_OS_OSX OSStatus SecPKCS12Import_ios(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef * __nonnull CF_RETURNS_RETAINED items) - SPI_AVAILABLE(macos(10.15), iosmac(13.0)) API_UNAVAILABLE(ios, watchos, tvos); + SPI_AVAILABLE(macos(10.15), macCatalyst(13.0)) API_UNAVAILABLE(ios, watchos, tvos); #endif CF_IMPLICIT_BRIDGING_DISABLED diff --git a/keychain/headers/SecItem.h b/keychain/headers/SecItem.h index f39dabbc..03a0d784 100644 --- a/keychain/headers/SecItem.h +++ b/keychain/headers/SecItem.h @@ -770,7 +770,8 @@ extern const CFStringRef kSecAttrKeyClassSymmetric @discussion Predefined item attribute constants used to get or set values in a dictionary. The kSecAttrKeyType constant is the key and its value is one of the constants defined here. - @constant kSecAttrKeyTypeECSECPrimeRandom. + @constant kSecAttrKeyTypeECSECPrimeRandom. The used curve is P-192, P-256, P-384 or P-521. + The size is specified by kSecAttrKeySizeInBits attribute. Curves are defined in FIPS PUB 186-4 standard. @constant kSecAttrKeyTypeEC This is the legacy name for kSecAttrKeyTypeECSECPrimeRandom, new applications should not use it. @constant kSecAttrKeyTypeDSA (OSX only) @constant kSecAttrKeyTypeAES (OSX only) @@ -1025,12 +1026,12 @@ extern const CFStringRef kSecValuePersistentRef */ extern const CFStringRef kSecUseItemList API_AVAILABLE(macos(10.6)) - API_DEPRECATED("Not implemented on this platform", ios(2.0, 12.0), tvos(9.0, 12.0), watchos(1.0, 5.0)) - API_UNAVAILABLE(bridgeos, iosmac); + API_DEPRECATED("Not implemented on this platform", ios(2.0, 12.0), tvos(9.0, 12.0), watchos(1.0, 5.0), macCatalyst(13.0, 13.0)) + API_UNAVAILABLE(bridgeos); extern const CFStringRef kSecUseKeychain API_AVAILABLE(macos(10.7), ios(NA), bridgeos(NA)); extern const CFStringRef kSecUseOperationPrompt - API_AVAILABLE(macos(10.10), ios(8.0)); + API_DEPRECATED("Use kSecUseAuthenticationContext and set LAContext.localizedReason property", macos(10.10, 10.16), ios(8.0, 14.0)); extern const CFStringRef kSecUseNoAuthenticationUI API_DEPRECATED("Use kSecUseAuthenticationUI instead.", macos(10.10, 10.11), ios(8.0, 9.0)); extern const CFStringRef kSecUseAuthenticationUI @@ -1056,9 +1057,9 @@ extern const CFStringRef kSecUseDataProtectionKeychain only with SecItemCopyMatching. */ extern const CFStringRef kSecUseAuthenticationUIAllow - API_AVAILABLE(macos(10.11), ios(9.0)); + API_DEPRECATED("Instead of kSecUseAuthenticationUI, use kSecUseAuthenticationContext and set LAContext.interactionNotAllowed property", macos(10.11, 10.16), ios(9.0, 14.0)); extern const CFStringRef kSecUseAuthenticationUIFail - API_AVAILABLE(macos(10.11), ios(9.0)); + API_DEPRECATED("Instead of kSecUseAuthenticationUI, use kSecUseAuthenticationContext and set LAContext.interactionNotAllowed property", macos(10.11, 10.16), ios(9.0, 14.0)); extern const CFStringRef kSecUseAuthenticationUISkip API_AVAILABLE(macos(10.11), ios(9.0)); diff --git a/keychain/headers/SecItemPriv.h b/keychain/headers/SecItemPriv.h index c458816d..e72636f3 100644 --- a/keychain/headers/SecItemPriv.h +++ b/keychain/headers/SecItemPriv.h @@ -305,6 +305,19 @@ extern const CFStringRef kSecAttrPCSPlaintextPublicKey extern const CFStringRef kSecAttrPCSPlaintextPublicIdentity __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0) __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0); +extern const CFStringRef kSecDataInetExtraNotes +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraHistory +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraClientDefined0 +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraClientDefined1 +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraClientDefined2 +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraClientDefined3 +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); + // ObjectID of item stored on the token. Token-type specific BLOB. // For kSecAttrTokenIDSecureEnclave and kSecAttrTokenIDAppleKeyStore, ObjectID is libaks's blob representation of encoded key. extern const CFStringRef kSecAttrTokenOID @@ -433,7 +446,7 @@ extern const CFStringRef kSecUseCallerName extern const CFStringRef kSecUseTokenRawItems __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0) __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0); extern const CFStringRef kSecUseCertificatesWithMatchIssuers - __OSX_AVAILABLE(10.14) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); + __OSX_AVAILABLE(10.14) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); extern const CFStringRef kSOSInternalAccessGroup __OSX_AVAILABLE(10.9) __IOS_AVAILABLE(7.0) __TVOS_AVAILABLE(9.3) __WATCHOS_AVAILABLE(2.3); @@ -455,24 +468,6 @@ extern const CFStringRef kSecAttrTokenIDAppleKeyStore extern const CFStringRef kSecNetworkExtensionAccessGroupSuffix; -/*! - @function SecItemCopyDisplayNames - @abstract Returns an array containing unique display names for each of the - certificates, keys, identities, or passwords in the provided items - array. - @param items An array containing items of type SecKeychainItemRef, - SecKeyRef, SecCertificateRef, or SecIdentityRef. All items in the - array should be of the same type. - @param displayNames On return, an array of CFString references containing - unique names for the supplied items. You are responsible for releasing - this array reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Use this function to obtain item names which are suitable for - display in a menu or list view. The returned names are guaranteed to - be unique across the set of provided items. -*/ -OSStatus SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames); - /*! @function SecItemDeleteAll @abstract Removes all items from the keychain. @@ -480,6 +475,23 @@ OSStatus SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames); */ OSStatus SecItemDeleteAll(void); +/*! + @function SecItemPersistKeychainWritesAtHighPerformanceCost + @abstract Attempts to ensure that all previous writes to the keychain are durably committed to disk. + This overrides existing performance and device disk durability tradeoffs, so you should + not use this SPI until you have a full understanding of how data loss resulting from power loss + impacts your distributed system. + + Note: This SPI is not guaranteed to work on macOS, if the user is in a non-standard hardware configuration + or is using network home folders. + + Note: on macOS, this will only affect the data protection keychain. Legacy macOS keychains are untouched. + @param error An error returned, if any. + @result A result code. + */ +OSStatus SecItemPersistKeychainWritesAtHighPerformanceCost(CFErrorRef* CF_RETURNS_RETAINED error) + API_AVAILABLE(macos(11.3), ios(14.5), tvos(14.5), watchos(7.4)); + /*! @function _SecItemAddAndNotifyOnSync @abstract Adds an item to the keychain, and calls syncCallback when the item has synced @@ -526,6 +538,7 @@ void SecItemFetchCurrentItemAcrossAllDevices(CFStringRef accessGroup, @function SecItemVerifyBackupIntegrity @abstract Verifies the presence and integrity of all key material required to restore a backup of the keychain. + @discussion This function performs a synchronous call to securityd, be prepared to wait for it to scan the keychain. @param lightweight Only verify the item keys wrapped by backup keys instead of the default rigorous pass. This mode can be run in any security class. @@ -601,8 +614,7 @@ bool _SecSystemKeychainTransfer(CFErrorRef *error); bool _SecSyncDeleteUserViews(uid_t uid, CFErrorRef *error); - -OSStatus SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes); +OSStatus SecItemUpdateTokenItemsForAccessGroups(CFTypeRef tokenID, CFArrayRef accessGroups, CFArrayRef tokenItemsAttributes); #if SEC_OS_OSX CFTypeRef SecItemCreateFromAttributeDictionary_osx(CFDictionaryRef refAttributes); @@ -695,6 +707,17 @@ __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_NA); extern const CFStringRef kSecAttrTokenIDSecureElement SPI_AVAILABLE(ios(10.13)); +/*! + @function SecItemDeleteKeychainItemsForAppClip + @abstract Remove all keychain items of specified App Clip's application identifier + @discussion At uninstallation time an App Clip should not leave behind any data. This function deletes any keychain items it might have had. + @param applicationIdentifier Name of the App Clip application identifier which is getting uninstalled. + @result Returns errSecSuccess if zero or more items were successfully deleted, otherwise errSecInternal + */ +OSStatus +SecItemDeleteKeychainItemsForAppClip(CFStringRef applicationIdentifier) +SPI_AVAILABLE(ios(10.14)); + __END_DECLS #endif /* !_SECURITY_SECITEMPRIV_H_ */ diff --git a/keychain/headers/SecKey.h b/keychain/headers/SecKey.h index 021a672a..a905732c 100644 --- a/keychain/headers/SecKey.h +++ b/keychain/headers/SecKey.h @@ -871,7 +871,7 @@ __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AV * kSecAttrKeySizeInBits * kSecAttrTokenID * kSecAttrApplicationLabel - Other values returned in that dictionary are RFU. + The set of values is not fixed. Future versions may return more values in this dictionary. */ CFDictionaryRef _Nullable SecKeyCopyAttributes(SecKeyRef key) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); @@ -915,19 +915,19 @@ __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AV RSA signature with PKCS#1 padding, input data must be SHA-512 generated digest. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1 - RSA signature with PKCS#1 padding, SHA-1 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-1 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224 - RSA signature with PKCS#1 padding, SHA-224 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-224 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256 - RSA signature with PKCS#1 padding, SHA-256 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-256 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384 - RSA signature with PKCS#1 padding, SHA-384 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-384 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512 - RSA signature with PKCS#1 padding, SHA-512 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-512 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureDigestPSSSHA1 RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, input data must be SHA-1 generated digest. @@ -950,60 +950,60 @@ __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AV PSS padding is calculated using MGF1 with SHA512 and saltLength parameter is set to 64 (SHA-512 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA1 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-1 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-1 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA1 and saltLength parameter is set to 20 (SHA-1 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA224 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-224 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-224 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA224 and saltLength parameter is set to 28 (SHA-224 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA256 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-256 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-256 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA256 and saltLength parameter is set to 32 (SHA-256 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA384 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-384 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-384 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA384 and saltLength parameter is set to 48 (SHA-384 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA512 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-512 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-512 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA512 and saltLength parameter is set to 64 (SHA-512 output size). @constant kSecKeyAlgorithmECDSASignatureRFC4754 - ECDSA algorithm, signature is concatenated r and s, big endian, data is message digest. + ECDSA algorithm, signature is concatenated r and s, big endian, input data must be message digest generated by some hash function. @constant kSecKeyAlgorithmECDSASignatureDigestX962 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest. + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest generated by some hash functions. @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA1 algorithm. + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA1 algorithm. - @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA224 algorithm. + @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA224 + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA224 algorithm. - @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA256 algorithm. + @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA256 + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA256 algorithm. - @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA384 algorithm. + @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA384 + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA384 algorithm. - @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA512 algorithm. + @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA512 + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA512 algorithm. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-1 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-1 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA224 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-224 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-224 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA256 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-256 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-256 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA384 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-384 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-384 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA512 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-512 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-512 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSAEncryptionRaw Raw RSA encryption or decryption, size of data must match RSA key modulus size. Note that direct diff --git a/keychain/headers/SecKeyPriv.h b/keychain/headers/SecKeyPriv.h index 1f22315a..06eaa37c 100644 --- a/keychain/headers/SecKeyPriv.h +++ b/keychain/headers/SecKeyPriv.h @@ -357,7 +357,7 @@ SPI_AVAILABLE(macos(10.8), ios(9.0)); For compatibility, your code should migrate to use SecKeyGetAlgorithmId instead. */ CFIndex SecKeyGetAlgorithmID(SecKeyRef key) -API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", ios(5.0, 9.0)) API_UNAVAILABLE(iosmac); +API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", ios(5.0, 9.0)) API_UNAVAILABLE(macCatalyst); #endif // TARGET_OS_IPHONE #if TARGET_OS_OSX @@ -372,7 +372,7 @@ API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", ios(5.0, 9.0)) API_UNAVA had different arguments and a different return value. Use SecKeyGetAlgorithmId instead. */ OSStatus SecKeyGetAlgorithmID(SecKeyRef key, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) -API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", macos(10.2, 10.8)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); +API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", macos(10.2, 10.8)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); #endif #if !SEC_OS_OSX @@ -473,7 +473,7 @@ OSStatus SecKeyImportPair( SecAccessRef initialAccess, SecKeyRef* publicKey, SecKeyRef* privateKey) - API_DEPRECATED_WITH_REPLACEMENT("SecItemImport", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecItemImport", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeyCreate @@ -504,7 +504,7 @@ SecKeyRef SecKeyCreate(CFAllocatorRef allocator, */ OSStatus SecKeyCreateWithCSSMKey(const CSSM_KEY *key, SecKeyRef* keyRef) API_DEPRECATED("CSSM_KEY is deprecated", macos(10.11, 10.14)); -// Alias macOS versions of this deprecated SPI to unique macOS names. Undecorated names are used for iosmac. +// Alias macOS versions of this deprecated SPI to unique macOS names. Undecorated names are used for macCatalyst. #define SecKeyRawSign SecKeyRawSign_macOS #define SecKeyRawVerify SecKeyRawVerify_macOS @@ -809,6 +809,10 @@ typedef CF_ENUM(uint32_t, SecKeyAttestationKeyType) kSecKeyAttestationKeyTypeUIKCommitted SPI_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 2, kSecKeyAttestationKeyTypeUIKProposed SPI_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 3, kSecKeyAttestationKeyTypeSecureElement SPI_AVAILABLE(ios(13.0)) = 4, + kSecKeyAttestationKeyTypeOIKCommitted SPI_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0)) = 5, + kSecKeyAttestationKeyTypeOIKProposed SPI_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0)) = 6, + kSecKeyAttestationKeyTypeDAKCommitted SPI_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0)) = 7, + kSecKeyAttestationKeyTypeDAKProposed SPI_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0)) = 8, } SPI_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)); /*! diff --git a/keychain/headers/SecSharedCredential.h b/keychain/headers/SecSharedCredential.h index 21a89444..0d047b70 100644 --- a/keychain/headers/SecSharedCredential.h +++ b/keychain/headers/SecSharedCredential.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2014-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -52,7 +52,9 @@ CF_IMPLICIT_BRIDGING_ENABLED shared password. You use this key to get a value of type CFStringRef that contains a password. */ -extern const CFStringRef kSecSharedPassword API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos, iosmac, tvos, watchos); +extern const CFStringRef kSecSharedPassword + API_AVAILABLE(ios(8.0), macCatalyst(14.0), macos(10.16)) + API_UNAVAILABLE(tvos, watchos); /*! @function SecAddSharedWebCredential @@ -66,7 +68,9 @@ extern const CFStringRef kSecSharedPassword API_AVAILABLE(ios(8.0)) API_UNAVAILA Note: since a request involving shared web credentials may potentially require user interaction or other verification to be approved, this function is dispatched asynchronously; your code provides a completion handler that will be called once the results (if any) are available. */ void SecAddSharedWebCredential(CFStringRef fqdn, CFStringRef account, CFStringRef __nullable password, - void (^completionHandler)(CFErrorRef __nullable error)) API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos, iosmac, tvos, watchos); + void (^completionHandler)(CFErrorRef __nullable error)) + API_AVAILABLE(ios(8.0), macCatalyst(14.0), macos(10.16)) + API_UNAVAILABLE(tvos, watchos); /*! @function SecRequestSharedWebCredential @@ -87,7 +91,10 @@ void SecAddSharedWebCredential(CFStringRef fqdn, CFStringRef account, CFStringRe Note: since a request involving shared web credentials may potentially require user interaction or other verification to be approved, this function is dispatched asynchronously; your code provides a completion handler that will be called once the results (if any) are available. */ void SecRequestSharedWebCredential(CFStringRef __nullable fqdn, CFStringRef __nullable account, - void (^completionHandler)(CFArrayRef __nullable credentials, CFErrorRef __nullable error)) API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos, iosmac, tvos, watchos); + void (^completionHandler)(CFArrayRef __nullable credentials, CFErrorRef __nullable error)) + API_DEPRECATED("Use ASAuthorizationController to make an ASAuthorizationPasswordRequest (AuthenticationServices framework)", + ios(8.0,14.0), macCatalyst(14.0,14.0), macos(10.16,10.16)) + API_UNAVAILABLE(tvos, watchos); /*! @function SecCreateSharedWebCredentialPassword @@ -95,7 +102,9 @@ void SecRequestSharedWebCredential(CFStringRef __nullable fqdn, CFStringRef __nu @return CFStringRef password in the form xxx-xxx-xxx-xxx where x is taken from the sets "abcdefghkmnopqrstuvwxy", "ABCDEFGHJKLMNPQRSTUVWXYZ", "3456789" with at least one character from each set being present. */ __nullable -CFStringRef SecCreateSharedWebCredentialPassword(void) API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos, iosmac, tvos, watchos); +CFStringRef SecCreateSharedWebCredentialPassword(void) + API_AVAILABLE(ios(8.0), macCatalyst(14.0), macos(10.16)) + API_UNAVAILABLE(tvos, watchos); #endif /* __BLOCKS__ */ diff --git a/keychain/ot/CuttlefishXPCWrapper.m b/keychain/ot/CuttlefishXPCWrapper.m index c67395bb..34339cfd 100644 --- a/keychain/ot/CuttlefishXPCWrapper.m +++ b/keychain/ot/CuttlefishXPCWrapper.m @@ -189,6 +189,7 @@ enum {NUM_RETRIES = 5}; - (void)setAllowedMachineIDsWithContainer:(NSString *)container context:(NSString *)context allowedMachineIDs:(NSSet *)allowedMachineIDs + honorIDMSListChanges:(BOOL)accountIsDemo reply:(void (^)(BOOL listDifferences, NSError * _Nullable error))reply { __block int i = 0; @@ -204,7 +205,7 @@ enum {NUM_RETRIES = 5}; reply(NO, error); } ++i; - }] setAllowedMachineIDsWithContainer:container context:context allowedMachineIDs:allowedMachineIDs reply:reply]; + }] setAllowedMachineIDsWithContainer:container context:context allowedMachineIDs:allowedMachineIDs honorIDMSListChanges:accountIsDemo reply:reply]; } while (retry); } @@ -309,8 +310,9 @@ enum {NUM_RETRIES = 5}; deviceName:(nullable NSString*)deviceName serialNumber:(NSString *)serialNumber osVersion:(NSString *)osVersion - policyVersion:(nullable NSNumber *)policyVersion + policyVersion:(nullable TPPolicyVersion *)policyVersion policySecrets:(nullable NSDictionary *)policySecrets + syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews signingPrivKeyPersistentRef:(nullable NSData *)spkPr encPrivKeyPersistentRef:(nullable NSData*)epkPr reply:(void (^)(NSString * _Nullable peerID, @@ -318,6 +320,7 @@ enum {NUM_RETRIES = 5}; NSData * _Nullable permanentInfoSig, NSData * _Nullable stableInfo, NSData * _Nullable stableInfoSig, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply { __block int i = 0; @@ -330,10 +333,25 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, nil, nil, nil, error); + reply(nil, nil, nil, nil, nil, nil, error); } ++i; - }] prepareWithContainer:container context:context epoch:epoch machineID:machineID bottleSalt:bottleSalt bottleID:bottleID modelID:modelID deviceName:deviceName serialNumber:serialNumber osVersion:osVersion policyVersion:policyVersion policySecrets:policySecrets signingPrivKeyPersistentRef:spkPr encPrivKeyPersistentRef:epkPr reply:reply]; + }] prepareWithContainer:container + context:context + epoch:epoch + machineID:machineID + bottleSalt:bottleSalt + bottleID:bottleID + modelID:modelID + deviceName:deviceName + serialNumber:serialNumber + osVersion:osVersion + policyVersion:policyVersion + policySecrets:policySecrets + syncUserControllableViews:syncUserControllableViews + signingPrivKeyPersistentRef:spkPr + encPrivKeyPersistentRef:epkPr + reply:reply]; } while (retry); } @@ -344,6 +362,7 @@ enum {NUM_RETRIES = 5}; preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply { __block int i = 0; @@ -356,7 +375,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, error); + reply(nil, nil, nil, error); } ++i; }] establishWithContainer:container context:context ckksKeys:viewKeySets tlkShares:tlkShares preapprovedKeys:preapprovedKeys reply:reply]; @@ -396,7 +415,10 @@ enum {NUM_RETRIES = 5}; - (void)preflightVouchWithBottleWithContainer:(nonnull NSString *)container context:(nonnull NSString *)context bottleID:(nonnull NSString *)bottleID - reply:(nonnull void (^)(NSString * _Nullable, NSError * _Nullable))reply { + reply:(nonnull void (^)(NSString * _Nullable, + TPSyncingPolicy* _Nullable peerSyncingPolicy, + BOOL refetchWasNeeded, + NSError * _Nullable))reply { __block int i = 0; __block bool retry; do { @@ -407,7 +429,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, error); + reply(nil, nil, false, error); } ++i; }] preflightVouchWithBottleWithContainer:container @@ -425,10 +447,36 @@ enum {NUM_RETRIES = 5}; tlkShares:(NSArray *)tlkShares reply:(void (^)(NSData * _Nullable voucher, NSData * _Nullable voucherSig, + int64_t uniqueTLKsRecovered, + int64_t totalTLKSharesRecovered, NSError * _Nullable error))reply { __block int i = 0; __block bool retry; + do { + retry = false; + [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { + if (i < NUM_RETRIES && [self.class retryable:error]) { + secnotice("octagon", "retrying cuttlefish XPC, (%d, %@)", i, error); + retry = true; + } else { + secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); + reply(nil, nil, 0, 0, error); + } + ++i; + }] vouchWithBottleWithContainer:container context:context bottleID:bottleID entropy:entropy bottleSalt:bottleSalt tlkShares:tlkShares reply:reply]; + } while (retry); +} + +- (void)preflightVouchWithRecoveryKeyWithContainer:(nonnull NSString *)container + context:(nonnull NSString *)context + recoveryKey:(NSString*)recoveryKey + salt:(NSString*)salt + reply:(nonnull void (^)(NSString * _Nullable, + TPSyncingPolicy* _Nullable peerSyncingPolicy, + NSError * _Nullable))reply { + __block int i = 0; + __block bool retry; do { retry = false; [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { @@ -440,7 +488,11 @@ enum {NUM_RETRIES = 5}; reply(nil, nil, error); } ++i; - }] vouchWithBottleWithContainer:container context:context bottleID:bottleID entropy:entropy bottleSalt:bottleSalt tlkShares:tlkShares reply:reply]; + }] preflightVouchWithRecoveryKeyWithContainer:container + context:context + recoveryKey:recoveryKey + salt:salt + reply:reply]; } while (retry); } @@ -476,9 +528,10 @@ enum {NUM_RETRIES = 5}; voucherSig:(NSData *)voucherSig ckksKeys:(NSArray *)viewKeySets tlkShares:(NSArray *)tlkShares - preapprovedKeys:(NSArray *)preapprovedKeys + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply { __block int i = 0; @@ -491,7 +544,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, error); + reply(nil, nil, nil, error); } ++i; }] joinWithContainer:container context:context voucherData:voucherData voucherSig:voucherSig ckksKeys:viewKeySets tlkShares:tlkShares preapprovedKeys:preapprovedKeys reply:reply]; @@ -500,6 +553,7 @@ enum {NUM_RETRIES = 5}; - (void)preflightPreapprovedJoinWithContainer:(NSString *)container context:(NSString *)context + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(BOOL launchOkay, NSError * _Nullable error))reply { @@ -516,7 +570,7 @@ enum {NUM_RETRIES = 5}; reply(NO, error); } ++i; - }] preflightPreapprovedJoinWithContainer:container context:context reply:reply]; + }] preflightPreapprovedJoinWithContainer:container context:context preapprovedKeys:preapprovedKeys reply:reply]; } while (retry); } @@ -524,10 +578,43 @@ enum {NUM_RETRIES = 5}; context:(NSString *)context ckksKeys:(NSArray *)ckksKeys tlkShares:(NSArray *)tlkShares - preapprovedKeys:(NSArray *)preapprovedKeys + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply +{ + __block int i = 0; + __block bool retry; + do { + retry = false; + [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { + if (i < NUM_RETRIES && [self.class retryable:error]) { + secnotice("octagon", "retrying cuttlefish XPC, (%d, %@)", i, error); + retry = true; + } else { + secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); + reply(nil, nil, nil, error); + } + ++i; + }] attemptPreapprovedJoinWithContainer:container + context:context + ckksKeys:ckksKeys + tlkShares:tlkShares + preapprovedKeys:preapprovedKeys + reply:reply]; + } while (retry); +} + +- (void)updateWithContainer:(NSString *)container + context:(NSString *)context + deviceName:(nullable NSString *)deviceName + serialNumber:(nullable NSString *)serialNumber + osVersion:(nullable NSString *)osVersion + policyVersion:(nullable NSNumber *)policyVersion + policySecrets:(nullable NSDictionary *)policySecrets + syncUserControllableViews:(nullable NSNumber *)syncUserControllableViews + reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, TPSyncingPolicy* _Nullable policy, NSError * _Nullable error))reply { __block int i = 0; __block bool retry; @@ -542,18 +629,22 @@ enum {NUM_RETRIES = 5}; reply(nil, nil, error); } ++i; - }] attemptPreapprovedJoinWithContainer:container context:context ckksKeys:ckksKeys tlkShares:tlkShares preapprovedKeys:preapprovedKeys reply:reply]; + }] updateWithContainer:container + context:context + deviceName:deviceName + serialNumber:serialNumber + osVersion:osVersion + policyVersion:policyVersion + policySecrets:policySecrets + syncUserControllableViews:syncUserControllableViews + reply:reply]; } while (retry); } -- (void)updateWithContainer:(NSString *)container - context:(NSString *)context - deviceName:(nullable NSString *)deviceName - serialNumber:(nullable NSString *)serialNumber - osVersion:(nullable NSString *)osVersion - policyVersion:(nullable NSNumber *)policyVersion - policySecrets:(nullable NSDictionary *)policySecrets - reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, NSError * _Nullable error))reply +- (void)setPreapprovedKeysWithContainer:(NSString *)container + context:(NSString *)context + preapprovedKeys:(NSArray *)preapprovedKeys + reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, NSError * _Nullable error))reply { __block int i = 0; __block bool retry; @@ -568,28 +659,6 @@ enum {NUM_RETRIES = 5}; reply(nil, error); } ++i; - }] updateWithContainer:container context:context deviceName:deviceName serialNumber:serialNumber osVersion:osVersion policyVersion:policyVersion policySecrets:policySecrets reply:reply]; - } while (retry); -} - -- (void)setPreapprovedKeysWithContainer:(NSString *)container - context:(NSString *)context - preapprovedKeys:(NSArray *)preapprovedKeys - reply:(void (^)(NSError * _Nullable error))reply -{ - __block int i = 0; - __block bool retry; - do { - retry = false; - [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { - if (i < NUM_RETRIES && [self.class retryable:error]) { - secnotice("octagon", "retrying cuttlefish XPC, (%d, %@)", i, error); - retry = true; - } else { - secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(error); - } - ++i; }] setPreapprovedKeysWithContainer:container context:context preapprovedKeys:preapprovedKeys reply:reply]; } while (retry); } @@ -664,8 +733,8 @@ enum {NUM_RETRIES = 5}; - (void)fetchPolicyDocumentsWithContainer:(NSString*)container context:(NSString*)context - keys:(NSDictionary*)keys - reply:(void (^)(NSDictionary*>* _Nullable entries, + versions:(NSSet*)versions + reply:(void (^)(NSDictionary* _Nullable entries, NSError * _Nullable error))reply { __block int i = 0; @@ -681,14 +750,16 @@ enum {NUM_RETRIES = 5}; reply(nil, error); } ++i; - }] fetchPolicyDocumentsWithContainer:container context:context keys:keys reply:reply]; + }] fetchPolicyDocumentsWithContainer:container context:context versions:versions reply:reply]; } while (retry); } -- (void)fetchPolicyWithContainer:(NSString*)container - context:(NSString*)context - reply:(void (^)(TPPolicy * _Nullable policy, - NSError * _Nullable error))reply +- (void)fetchCurrentPolicyWithContainer:(NSString*)container + context:(NSString*)context + modelIDOverride:(NSString* _Nullable)modelIDOverride + reply:(void (^)(TPSyncingPolicy* _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, + NSError * _Nullable error))reply { __block int i = 0; __block bool retry; @@ -700,10 +771,12 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, error); + reply(nil, + TPPBPeerStableInfo_UserControllableViewStatus_UNKNOWN, + error); } ++i; - }] fetchPolicyWithContainer:container context:context reply:reply]; + }] fetchCurrentPolicyWithContainer:container context:context modelIDOverride:modelIDOverride reply:reply]; } while (retry); } @@ -757,7 +830,8 @@ enum {NUM_RETRIES = 5}; recoveryKey:(NSString *)recoveryKey salt:(NSString *)salt ckksKeys:(NSArray *)ckksKeys - reply:(void (^)(NSError* _Nullable error))reply + reply:(void (^)(NSArray* _Nullable keyHierarchyRecords, + NSError* _Nullable error))reply { __block int i = 0; __block bool retry; @@ -769,7 +843,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(error); + reply(nil, error); } ++i; }] setRecoveryKeyWithContainer:container context:context recoveryKey:recoveryKey salt:salt ckksKeys:ckksKeys reply:reply]; @@ -820,32 +894,10 @@ enum {NUM_RETRIES = 5}; } while (retry); } -- (void)getViewsWithContainer:(NSString *)container - context:(NSString *)context - inViews:(NSArray*)inViews - reply:(void (^)(NSArray* _Nullable, NSError* _Nullable))reply -{ - __block int i = 0; - __block bool retry; - do { - retry = false; - [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { - if (i < NUM_RETRIES && [self.class retryable:error]) { - secnotice("octagon", "retrying cuttlefish XPC, (%d, %@)", i, error); - retry = true; - } else { - secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, error); - } - ++i; - }] getViewsWithContainer:container context:context inViews:inViews reply:reply]; - } while (retry); -} - - (void)requestHealthCheckWithContainer:(NSString *)container context:(NSString *)context requiresEscrowCheck:(BOOL)requiresEscrowCheck - reply:(void (^)(BOOL postRepairCFU, BOOL postEscrowCFU, BOOL resetOctagon, NSError* _Nullable))reply + reply:(void (^)(BOOL postRepairCFU, BOOL postEscrowCFU, BOOL resetOctagon, BOOL leaveTrust, NSError* _Nullable))reply { __block int i = 0; __block bool retry; @@ -857,10 +909,10 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(NO, NO, NO, error); + reply(NO, NO, NO, NO, error); } ++i; - }] requestHealthCheckWithContainer:container context:context requiresEscrowCheck:requiresEscrowCheck reply:reply]; + }] requestHealthCheckWithContainer:container context:context requiresEscrowCheck:requiresEscrowCheck reply:reply]; } while (retry); } @@ -886,4 +938,62 @@ enum {NUM_RETRIES = 5}; } +- (void)fetchViableEscrowRecordsWithContainer:(nonnull NSString *)container context:(nonnull NSString *)context forceFetch:(BOOL)forceFetch reply:(nonnull void (^)(NSArray * _Nullable, NSError * _Nullable))reply +{ + __block int i = 0; + __block bool retry; + do { + retry = false; + [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { + if (i < NUM_RETRIES && [self.class retryable:error]) { + secnotice("octagon", "retrying cuttlefish XPC, (%d, %@)", i, error); + retry = true; + } else { + secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); + reply(nil, error); + } + ++i; + }] fetchViableEscrowRecordsWithContainer:container context:context forceFetch:forceFetch reply:reply]; + } while (retry); +} + +- (void)removeEscrowCacheWithContainer:(nonnull NSString *)container context:(nonnull NSString *)context reply:(nonnull void (^)(NSError * _Nullable))reply { + __block int i = 0; + __block bool retry; + do { + retry = false; + [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { + if (i < NUM_RETRIES && [self.class retryable:error]) { + secnotice("octagon", "retrying cuttlefish XPC, (%d, %@)", i, error); + retry = true; + } else { + secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); + reply(error); + } + ++i; + }] removeEscrowCacheWithContainer:container context:context reply:reply]; + } while (retry); +} + +- (void)resetAccountCDPContentsWithContainer:(nonnull NSString *)container context:(nonnull NSString *)context reply:(nonnull void (^)(NSError * _Nullable))reply { + __block int i = 0; + __block bool retry; + do { + retry = false; + [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { + if (i < NUM_RETRIES && [self.class retryable:error]) { + secnotice("octagon", "retrying cuttlefish XPC, (%d, %@)", i, error); + retry = true; + } else { + secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); + reply(error); + } + ++i; + }] resetAccountCDPContentsWithContainer:container context:context reply:reply]; + } while (retry); +} + + + + @end diff --git a/keychain/ot/OT.m b/keychain/ot/OT.m index c5246045..4e515885 100644 --- a/keychain/ot/OT.m +++ b/keychain/ot/OT.m @@ -31,6 +31,7 @@ void OctagonInitialize(void) { OTManager* manager = [OTManager manager]; [manager initializeOctagon]; + [manager setupAnalytics]; } // If you want octagon to be initialized in your daemon/tests, you must set this to be true @@ -48,11 +49,7 @@ void OctagonSetShouldPerformInitialization(bool value) void SecOctagon24hrNotification(void) { #if OCTAGON @autoreleasepool { - [[OTManager manager] xpc24HrNotification:OTCKContainerName context:OTDefaultContext skipRateLimitingCheck:NO reply: ^(NSError * error) { - if(error){ - secerror("error attempting to check octagon health: %@", error); - } - }]; + [[OTManager manager] xpc24HrNotification]; } #endif } diff --git a/keychain/ot/OTAuthKitAdapter.h b/keychain/ot/OTAuthKitAdapter.h index 5539aa1f..e0f4ec03 100644 --- a/keychain/ot/OTAuthKitAdapter.h +++ b/keychain/ot/OTAuthKitAdapter.h @@ -20,6 +20,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSString* _Nullable)primaryiCloudAccountAltDSID:(NSError **)error; - (BOOL)accountIsHSA2ByAltDSID:(NSString*)altDSID; +- (BOOL)accountIsDemoAccount:(NSError**)error NS_SWIFT_NOTHROW; - (NSString* _Nullable)machineID:(NSError**)error; - (void)fetchCurrentDeviceList:(void (^)(NSSet* _Nullable machineIDs, NSError* _Nullable error))complete; diff --git a/keychain/ot/OTAuthKitAdapter.m b/keychain/ot/OTAuthKitAdapter.m index b9452d2e..80e1ff92 100644 --- a/keychain/ot/OTAuthKitAdapter.m +++ b/keychain/ot/OTAuthKitAdapter.m @@ -53,18 +53,43 @@ - (BOOL)accountIsHSA2ByAltDSID:(NSString*)altDSID { - bool hsa2 = false; + BOOL hsa2 = NO; AKAccountManager *manager = [AKAccountManager sharedInstance]; ACAccount *authKitAccount = [manager authKitAccountWithAltDSID:altDSID]; AKAppleIDSecurityLevel securityLevel = [manager securityLevelForAccount:authKitAccount]; if(securityLevel == AKAppleIDSecurityLevelHSA2) { - hsa2 = true; + hsa2 = YES; } secnotice("security-authkit", "Security level for altDSID %@ is %lu", altDSID, (unsigned long)securityLevel); return hsa2; } +- (BOOL)accountIsDemoAccount:(NSError**)error +{ + NSError* localError = nil; + NSString* altDSID = [self primaryiCloudAccountAltDSID:&localError]; + + if(altDSID == nil) { + secerror("octagon-authkit:could not retrieve altDSID"); + } + if (localError) { + secerror("octagon-authkit: hit an error retrieving altDSID: %@", localError); + if(error){ + *error = localError; + } + return NO; + } + + AKAccountManager *manager = [AKAccountManager sharedInstance]; + ACAccount *authKitAccount = [manager authKitAccountWithAltDSID:altDSID]; + BOOL isDemo = [manager demoAccountForAccount:authKitAccount]; + + secnotice("security-authkit", "Account with altDSID %@ is a demo account: %@", altDSID, isDemo ? @"true" : @"false"); + + return isDemo; +} + - (NSString* _Nullable)machineID:(NSError**)error { AKAnisetteProvisioningController* anisetteController = [[AKAnisetteProvisioningController alloc] init]; diff --git a/keychain/ot/OTCheckHealthOperation.h b/keychain/ot/OTCheckHealthOperation.h index e3463e6d..430fa43f 100644 --- a/keychain/ot/OTCheckHealthOperation.h +++ b/keychain/ot/OTCheckHealthOperation.h @@ -53,6 +53,7 @@ NS_ASSUME_NONNULL_BEGIN @property BOOL postRepairCFU; @property BOOL postEscrowCFU; @property BOOL resetOctagon; +@property BOOL leaveTrust; @end diff --git a/keychain/ot/OTCheckHealthOperation.m b/keychain/ot/OTCheckHealthOperation.m index b76ce462..8158222a 100644 --- a/keychain/ot/OTCheckHealthOperation.m +++ b/keychain/ot/OTCheckHealthOperation.m @@ -61,6 +61,7 @@ _postRepairCFU = NO; _postEscrowCFU = NO; _resetOctagon = NO; + _leaveTrust = NO; _skipRateLimitingCheck = skipRateLimitedCheck; } return self; @@ -99,7 +100,9 @@ self.error = nil; lastUpdate = [self.deps.stateHolder lastHealthCheckupDate:&accountLoadError]; - if([self.deps.viewManager.lockStateTracker isLockedError: accountLoadError]) { + + CKKSViewManager* viewManager = self.deps.viewManager; + if([viewManager.lockStateTracker isLockedError: accountLoadError]) { secnotice("octagon-health", "device is locked, not performing cuttlefish check"); [self runBeforeGroupFinished:self.finishOp]; return; @@ -132,7 +135,7 @@ NSError* persistedError = nil; BOOL persisted = [self.deps.stateHolder persistLastHealthCheck:now error:&persistedError]; - if([self.deps.viewManager.lockStateTracker isLockedError: persistedError]) { + if([viewManager.lockStateTracker isLockedError: persistedError]) { secnotice("octagon-health", "device is locked, not performing cuttlefish check"); [self runBeforeGroupFinished:self.finishOp]; return; @@ -150,7 +153,7 @@ [self.deps.cuttlefishXPCWrapper requestHealthCheckWithContainer:self.deps.containerName context:self.deps.contextID requiresEscrowCheck: [self checkIfPasscodeIsSetForDevice] - reply:^(BOOL postRepairCFU, BOOL postEscrowCFU, BOOL resetOctagon, NSError *error) { + reply:^(BOOL postRepairCFU, BOOL postEscrowCFU, BOOL resetOctagon, BOOL leaveTrust, NSError *error) { STRONGIFY(self); if(error) { secerror("octagon-health: error: %@", error); @@ -159,23 +162,28 @@ [self runBeforeGroupFinished:self.finishOp]; return; } else { - secnotice("octagon-health", "cuttlefish came back with these suggestions\n: post repair? %d\n, post escrow? %d\n, reset octagon? %d", postRepairCFU, postEscrowCFU, resetOctagon); + secnotice("octagon-health", "cuttlefish came back with these suggestions\n: post repair? %d\n, post escrow? %d\n, reset octagon? %d\n leave trust? %d\n", postRepairCFU, postEscrowCFU, resetOctagon, leaveTrust); [self handleRepairSuggestions:postRepairCFU postEscrowCFU:postEscrowCFU - resetOctagon:resetOctagon]; + resetOctagon:resetOctagon + leaveTrust:leaveTrust]; } }]; } -- (void)handleRepairSuggestions:(BOOL)postRepairCFU postEscrowCFU:(BOOL)postEscrowCFU resetOctagon:(BOOL)resetOctagon +- (void)handleRepairSuggestions:(BOOL)postRepairCFU postEscrowCFU:(BOOL)postEscrowCFU resetOctagon:(BOOL)resetOctagon leaveTrust:(BOOL)leaveTrust { self.postEscrowCFU = postEscrowCFU; self.postRepairCFU = postRepairCFU; self.resetOctagon = resetOctagon; + self.leaveTrust = leaveTrust; if (resetOctagon) { secnotice("octagon-health", "Resetting Octagon as per Cuttlefish request"); self.nextState = OctagonStateHealthCheckReset; + } else if(leaveTrust) { + secnotice("octagon-health", "Leaving clique as per Cuttlefish request"); + self.nextState = OctagonStateHealthCheckLeaveClique; } else { self.nextState = self.intendedState; } diff --git a/keychain/ot/OTClientStateMachine.m b/keychain/ot/OTClientStateMachine.m index b36a24aa..cbb6e8ad 100644 --- a/keychain/ot/OTClientStateMachine.m +++ b/keychain/ot/OTClientStateMachine.m @@ -42,7 +42,6 @@ #import "keychain/ot/OTConstants.h" #import "keychain/ot/OTClientStateMachine.h" -#import "keychain/ot/OTPrepareOperation.h" #import "keychain/ot/OTSOSAdapter.h" #import "keychain/ot/OTEpochOperation.h" #import "keychain/ot/OTClientVoucherOperation.h" @@ -287,7 +286,8 @@ NSDictionary* OctagonClientStateMap(void) { osVersion:nil policyVersion:nil policySecrets:nil - reply:^(TrustedPeersHelperPeerState* peerState, NSError* error) { + syncUserControllableViews:nil + reply:^(TrustedPeersHelperPeerState* peerState, TPSyncingPolicy* policy, NSError* error) { if(error) { secerror("OTCuttlefishContext: updating errored: %@", error); } else { diff --git a/keychain/ot/OTClientVoucherOperation.m b/keychain/ot/OTClientVoucherOperation.m index 6257c0d2..f7951b8d 100644 --- a/keychain/ot/OTClientVoucherOperation.m +++ b/keychain/ot/OTClientVoucherOperation.m @@ -77,7 +77,8 @@ WEAKIFY(self); // Acquire the CKKS TLKs to pass in - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.operationDependencies]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.operationDependencies + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"vouch-with-keys" diff --git a/keychain/ot/OTClique+Private.h b/keychain/ot/OTClique+Private.h new file mode 100644 index 00000000..298321dd --- /dev/null +++ b/keychain/ot/OTClique+Private.h @@ -0,0 +1,24 @@ + +#ifndef OTClique_Private_h +#define OTClique_Private_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OTClique(Private) + ++ (NSArray* _Nullable)fetchEscrowRecordsInternal:(OTConfigurationContext*)configurationContext + error:(NSError* __autoreleasing *)error; + ++ (BOOL)isCloudServicesAvailable; + +- (BOOL)resetAndEstablish:(CuttlefishResetReason)resetReason error:(NSError**)error; + +- (BOOL)establish:(NSError**)error; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* OTClique_Private_h */ diff --git a/keychain/ot/OTClique.h b/keychain/ot/OTClique.h index b03be4ae..e0027c4c 100644 --- a/keychain/ot/OTClique.h +++ b/keychain/ot/OTClique.h @@ -25,6 +25,15 @@ #ifndef OTClique_h #define OTClique_h +#if __OBJC2__ + +#import +#import +#import +#import +#import +#import + typedef NS_ENUM(NSInteger, CliqueStatus) { CliqueStatusIn = 0, /*There is a clique and I am in it*/ CliqueStatusNotIn = 1, /*There is a clique and I am not in it - you should get a voucher to join or tell another peer to trust us*/ @@ -34,37 +43,42 @@ typedef NS_ENUM(NSInteger, CliqueStatus) { CliqueStatusError = -1 /*unable to determine circle status, inspect CFError to find out why */ }; -#import - -#if __OBJC2__ - -#import -#import -#import -#import -#import +typedef NS_ENUM(NSInteger, OTCDPStatus) { + OTCDPStatusUnknown = 0, + OTCDPStatusDisabled = 1, + OTCDPStatusEnabled = 2, +}; NS_ASSUME_NONNULL_BEGIN NSString* OTCliqueStatusToString(CliqueStatus status); CliqueStatus OTCliqueStatusFromString(NSString* str); +NSString* OTCDPStatusToString(OTCDPStatus status); @class KCPairingChannelContext; @class KCPairingChannel; @class OTPairingChannel; @class OTPairingChannelContext; @class OTControl; +@class CKKSControl; extern NSString* kSecEntitlementPrivateOctagonEscrow; @interface OTConfigurationContext : NSObject -@property (nonatomic, copy, nullable) NSString* context; -@property (nonatomic, copy) NSString* dsid; -@property (nonatomic, copy) NSString* altDSID; -@property (nonatomic, strong, nullable) SFSignInAnalytics* analytics; +@property (nonatomic, copy) NSString* context; +@property (nonatomic, copy) NSString* containerName; +@property (nonatomic, copy, nullable) NSString* dsid; +@property (nonatomic, copy, nullable) NSString* altDSID; +@property (nonatomic, copy, nullable) NSString* authenticationAppleID; +@property (nonatomic, copy, nullable) NSString* passwordEquivalentToken; +@property (nonatomic) BOOL overrideEscrowCache; // Use this to inject your own OTControl object. It must be configured as synchronous. @property (nullable, strong) OTControl* otControl; + +// Use this to inject your own CKKSControl object. It must be configured as synchronous. +@property (nullable, strong) CKKSControl* ckksControl; + // Use this to inject your own SecureBackup object. It must conform to the OctagonEscrowRecoverer protocol. @property (nullable, strong) id sbd; @@ -86,22 +100,6 @@ extern NSString* kSecEntitlementPrivateOctagonEscrow; @property (nonatomic, assign) BOOL useCachedAccountStatus; @end -#endif // this #endif was added for Darling -// see OTControlProtocol.m for an explanation of why we need to do this -#if defined(DARLING) || defined(__OBJC2__) - -#if defined(DARLING) -#if __OBJC2__ -NS_ASSUME_NONNULL_END -#endif - -#import - -#if __OBJC2__ -NS_ASSUME_NONNULL_BEGIN -#endif -#endif - typedef NSString* OTCliqueCDPContextType NS_STRING_ENUM; extern OTCliqueCDPContextType OTCliqueCDPContextTypeNone; extern OTCliqueCDPContextType OTCliqueCDPContextTypeSignIn; @@ -110,9 +108,7 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeFinishPasscodeChange; extern OTCliqueCDPContextType OTCliqueCDPContextTypeRecoveryKeyGenerate; extern OTCliqueCDPContextType OTCliqueCDPContextTypeRecoveryKeyNew; extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; - -#endif // defined(DARLING) || defined(__OBJC2__) -#if __OBJC2__ // this #if was added for Darling +extern OTCliqueCDPContextType OTCliqueCDPContextTypeConfirmPasscodeCyrus; // OTClique @@ -129,10 +125,10 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; /* * * @abstract, initializes a clique object given a context. A clique object enables octagon trust operations for a given context and dsid. - * @param ctx, a unique string that is used as a way to retrieve current trust state + * @param ctx, a collection of arguments describing the world * @return an instance of octagon trust */ -- (instancetype _Nullable)initWithContextData:(OTConfigurationContext *)ctx error:(NSError * __autoreleasing * _Nonnull)error; +- (instancetype)initWithContextData:(OTConfigurationContext *)ctx; /* * * @abstract Establish a new clique, reset protected data @@ -174,10 +170,8 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; /* * * @abstract Create pairing channel with * - * @param ctx, context containing parameters to setup OTClique - * @param pairingChannelContext, context containing parameters to setup the pairing channel as the initiator - * @return clique, An instance of an OTClique - * @return error, error gets filled if something goes horribly wrong + * @param ctx, context containing parameters to setup the pairing channel as the initiator + * @return KCPairingChannel, An instance of a KCPairingCHannel */ - (KCPairingChannel *)setupPairingChannelAsInitiator:(KCPairingChannelContext *)ctx; @@ -186,10 +180,8 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; /* * * @abstract Configure this peer as the acceptor during piggybacking * - * @param ctx, context containing parameters to setup OTClique - * @param pairingChannelContext, context containing parameters to setup the pairing channel as the acceptor - * @param error, error gets filled if something goes horribly wrong - * @return KCPairingChannel, An instance of an OTClique + * @param ctx, context containing parameters to setup the pairing channel as the acceptor + * @return KCPairingChannel, An instance of a KCPairingChannel */ - (KCPairingChannel *)setupPairingChannelAsAcceptor:(KCPairingChannelContext *)ctx; @@ -251,13 +243,41 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; */ - (NSDictionary* _Nullable)peerDeviceNamesByPeerID:(NSError * __autoreleasing *)error; +/* + * CDP bit handling + */ ++ (BOOL)setCDPEnabled:(OTConfigurationContext*)arguments + error:(NSError* __autoreleasing*)error; + ++ (OTCDPStatus)getCDPStatus:(OTConfigurationContext*)arguments + error:(NSError* __autoreleasing *)error; + +/* + * User view handling + */ + +/* * + * @abstract Set the current status of user-controllable views. This is unavailable on TV and Watch, and will error. + * @param error, This will return an error if anything goes wrong + * @return success + */ +- (BOOL)setUserControllableViewsSyncStatus:(BOOL)enabled + error:(NSError* __autoreleasing *)error; + +/* * + * @abstract Fetch the current status of user-controllable views + * @param error, This will return an error if anything goes wrong + * @return status, The status of syncing. Note that in the success case, this can be NO while error remains empty. + */ +- (BOOL)fetchUserControllableViewsSyncingEnabled:(NSError* __autoreleasing *)error __attribute__((swift_error(nonnull_error))); /* SOS glue */ - (BOOL)joinAfterRestore:(NSError * __autoreleasing *)error; -- (BOOL)safariPasswordSyncingEnabled:(NSError *__autoreleasing*)error; +- (BOOL)safariPasswordSyncingEnabled:(NSError *__autoreleasing*)error +API_DEPRECATED_WITH_REPLACEMENT("fetchUserControllableViewsSyncingEnabled",macos(10.15, 10.16), ios(13.0, 14.0), watchos(6.0, 7.0), tvos(13.0,14.0)); - (BOOL)isLastFriend:(NSError *__autoreleasing*)error; @@ -265,7 +285,9 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; - (NSArray* _Nullable)copyViewUnawarePeerInfo:(NSError *__autoreleasing*)error; -- (BOOL)viewSet:(NSSet*)enabledViews disabledViews:(NSSet*)disabledViews; +- (BOOL)viewSet:(NSSet*)enabledViews disabledViews:(NSSet*)disabledViews +API_DEPRECATED_WITH_REPLACEMENT("setUserControllableViewsSyncStatus",macos(10.15, 10.16), ios(13.0, 14.0), watchos(6.0, 7.0), tvos(13.0,14.0)); + - (BOOL)setUserCredentialsAndDSID:(NSString*)userLabel password:(NSData*)userPassword @@ -340,6 +362,17 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; // CoreCDP will call this function when they are upgrading an account from SA to HSA2 - (BOOL)waitForOctagonUpgrade:(NSError** _Nullable)error; + +/* +* @abstract CoreCDP to call this function when they need to reset protected data. +* This routine resets all circles, creates a new octagon and sos circle, then puts this device into each circle. +* This routine does not create a new escrow record +* This routine will need ensure OTConfigurationContext contains appleID and passwordEquivalentToken to delete all CDP records +* @param data The OTClique configuration data +* @param error Reports any error along the process +* @return a new clique +*/ ++ (OTClique* _Nullable)resetProtectedData:(OTConfigurationContext*)data error:(NSError**)error; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTClique.m b/keychain/ot/OTClique.m index d2d18689..b3fb4522 100644 --- a/keychain/ot/OTClique.m +++ b/keychain/ot/OTClique.m @@ -27,6 +27,7 @@ #import #import "keychain/ot/OTClique.h" +#import "keychain/ot/OTClique+Private.h" #import "keychain/ot/OTConstants.h" #import "keychain/ot/OTDefines.h" #import "keychain/SigninMetrics/OctagonSignPosts.h" @@ -37,6 +38,8 @@ #import "keychain/SecureObjectSync/SOSCloudCircle.h" #import "KeychainCircle/PairingChannel.h" #import +#import "keychain/SecureObjectSync/SOSViews.h" +#import "keychain/SecureObjectSync/SOSInternal.h" const NSString* kSecEntitlementPrivateOctagonEscrow = @"com.apple.private.octagon.escrow-content"; @@ -47,10 +50,11 @@ const NSString* kSecEntitlementPrivateOctagonEscrow = @"com.apple.private.octago #import #import #import "keychain/ot/OTControl.h" +#import "keychain/ckks/CKKSControl.h" #import "keychain/ot/categories/OctagonEscrowRecoverer.h" SOFT_LINK_FRAMEWORK(PrivateFrameworks, KeychainCircle); -SOFT_LINK_FRAMEWORK(PrivateFrameworks, CloudServices); +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CloudServices); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wstrict-prototypes" @@ -58,17 +62,16 @@ SOFT_LINK_CLASS(KeychainCircle, KCPairingChannel); SOFT_LINK_CLASS(KeychainCircle, OTPairingChannel); SOFT_LINK_CLASS(CloudServices, SecureBackup); SOFT_LINK_CONSTANT(CloudServices, kSecureBackupErrorDomain, NSErrorDomain); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationAppleID, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationPassword, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupiCloudDataProtectionDeleteAllRecordsKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupContainsiCDPDataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryKeyKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesRecoveryKeyKey, NSString*); #pragma clang diagnostic pop #endif -#endif // this #endif was added for Darling -// see OTControlProtocol.m for an explanation of why we need to do this -#if defined(DARLING) || defined(__OBJC2__) - -#import -#import "keychain/ot/OTClique.h" - OTCliqueCDPContextType OTCliqueCDPContextTypeNone = @"cdpContextTypeNone"; OTCliqueCDPContextType OTCliqueCDPContextTypeSignIn = @"cdpContextTypeSignIn"; OTCliqueCDPContextType OTCliqueCDPContextTypeRepair = @"cdpContextTypeRepair"; @@ -76,6 +79,7 @@ OTCliqueCDPContextType OTCliqueCDPContextTypeFinishPasscodeChange = @"cdpContext OTCliqueCDPContextType OTCliqueCDPContextTypeRecoveryKeyGenerate = @"cdpContextTypeRecoveryKeyGenerate"; OTCliqueCDPContextType OTCliqueCDPContextTypeRecoveryKeyNew = @"cdpContextTypeRecoveryKeyNew"; OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode = @"cdpContextTypeUpdatePasscode"; +OTCliqueCDPContextType OTCliqueCDPContextTypeConfirmPasscodeCyrus = @"cdpContextTypeConfirmPasscodeCyrus"; NSString* OTCliqueStatusToString(CliqueStatus status) { @@ -112,11 +116,21 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) return CliqueStatusError; } -#endif // defined(DARLING) || defined(__OBJC2__) -#if __OBJC2__ // this #if was added for Darling + +NSString* OTCDPStatusToString(OTCDPStatus status) { + switch(status) { + case OTCDPStatusUnknown: + return @"unknown"; + case OTCDPStatusDisabled: + return @"disabled"; + case OTCDPStatusEnabled: + return @"enabled"; + } +} @implementation OTConfigurationContext + - (OTControl* _Nullable)makeOTControl:(NSError**)error { #if OCTAGON @@ -128,6 +142,26 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) return nil; #endif } + +- (CKKSControl* _Nullable)makeCKKSControl:(NSError**)error +{ +#if OCTAGON + if(self.ckksControl) { + return self.ckksControl; + } + return [CKKSControl CKKSControlObject:true error:error]; +#else + return nil; +#endif +} + +- (instancetype)init +{ + if((self = [super init])) { + _context = OTDefaultContext; + } + return self; +} @end @implementation OTBottleIDs @@ -198,24 +232,28 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) [self.defaults removeObjectForKey:OTDefaultsOctagonEnable]; } -- (instancetype)initWithContextData:(OTConfigurationContext *)ctx error:(NSError * __autoreleasing *)error +- (instancetype)initWithContextData:(OTConfigurationContext *)ctx { #if OCTAGON - self = [super init]; - if(self){ + if ((self = [super init])) { _ctx = [[OTConfigurationContext alloc]init]; _ctx.context = ctx.context ?: OTDefaultContext; _ctx.dsid = [ctx.dsid copy]; _ctx.altDSID = [ctx.altDSID copy]; - _ctx.analytics = ctx.analytics; _ctx.otControl = ctx.otControl; + _ctx.ckksControl = ctx.ckksControl; + _ctx.overrideEscrowCache = ctx.overrideEscrowCache; self.defaults = [NSMutableDictionary dictionary]; } return self; #else NSAssert(false, @"OTClique is not implemented on this platform"); - return nil; + + // make the build analyzer happy + if ((self = [super init])) { + } + return self; #endif // OCTAGON } @@ -251,6 +289,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) SOSPeerInfoRef me = SOSCCCopyMyPeerInfo(&error); retPeerID = (NSString*)CFBridgingRelease(CFRetainSafe(SOSPeerInfoGetPeerID(me))); CFReleaseNull(me); + CFBridgingRelease(error); } secnotice("clique", "cliqueMemberIdentifier complete: %@", retPeerID); @@ -287,7 +326,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) if(operationError) { secnotice("clique-establish", "establish returned an error: %@", operationError); } - success = !!operationError; + success = operationError == nil; localError = operationError; }]; @@ -321,7 +360,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) if(operationError) { secnotice("clique-resetandestablish", "resetAndEstablish returned an error: %@", operationError); } - success = !!operationError; + success = operationError == nil; localError = operationError; }]; @@ -348,9 +387,9 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) secnotice("clique-newfriends", "makeNewFriends invoked using context: %@, dsid: %@", data.context, data.dsid); bool result = false; bool subTaskSuccess = false; - OctagonSignpost performEscrowRecoverySignpost = OctagonSignpostBegin(OctagonSignpostNameMakeNewFriends); + OctagonSignpost newFriendsSignpost = OctagonSignpostBegin(OctagonSignpostNameMakeNewFriends); - OTClique* clique = [[OTClique alloc] initWithContextData:data error:error]; + OTClique* clique = [[OTClique alloc] initWithContextData:data]; if(OctagonIsEnabled()) { NSError* localError = nil; @@ -361,7 +400,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) if(error) { *error = localError; } - OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); + OctagonSignpostEnd(newFriendsSignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); return nil; } else { secnotice("clique-newfriends", "Octagon account reset succeeded"); @@ -370,24 +409,16 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) if([OTClique platformSupportsSOS]) { CFErrorRef resetError = NULL; - NSData* analyticsData = nil; - if(data.analytics) { - NSError* encodingError = nil; - analyticsData = [NSKeyedArchiver archivedDataWithRootObject:data.analytics requiringSecureCoding:YES error:&encodingError]; - - if(encodingError) { - secnotice("clique-newfriends", "newFriendsWithContextData: unable to serialize analytics: %@", encodingError); - } - } - result = SOSCCResetToOffering(&resetError); if(!result || resetError){ secnotice("clique-newfriends", "newFriendsWithContextData: resetToOffering failed: %@", resetError); if(error) { *error = CFBridgingRelease(resetError); + } else { + CFBridgingRelease(resetError); } - OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); + OctagonSignpostEnd(newFriendsSignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); return nil; } secnotice("clique-newfriends", "newFriendsWithContextData: reset the SOS circle"); @@ -397,7 +428,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) secnotice("clique-newfriends", "makeNewFriends complete"); subTaskSuccess = true; - OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); + OctagonSignpostEnd(newFriendsSignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); return clique; @@ -408,25 +439,40 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) #endif } ++ (BOOL)isCloudServicesAvailable +{ +#if OCTAGON + if (isCloudServicesAvailable()) { + return YES; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + secnotice("octagon", "CloudServices is unavailable on this platform"); + }); + return NO; +#else + return NO; +#endif +} + + (OTClique* _Nullable)performEscrowRecoveryWithContextData:(OTConfigurationContext*)data escrowArguments:(NSDictionary*)sbdRecoveryArguments error:(NSError**)error { #if OCTAGON + if ([OTClique isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } + OctagonSignpost performEscrowRecoverySignpost = OctagonSignpostBegin(OctagonSignpostNamePerformEscrowRecovery); bool subTaskSuccess = false; NSError* localError = nil; - OTClique* clique = [[OTClique alloc] initWithContextData:data - error:&localError]; - if(!clique || localError) { - secnotice("clique-recovery", "unable to create otclique: %@", localError); - if(error) { - *error = localError; - } - OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNamePerformEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformEscrowRecovery), (int)subTaskSuccess); - return nil; - } + OTClique* clique = [[OTClique alloc] initWithContextData:data]; // Attempt the recovery from sbd secnotice("clique-recovery", "attempting an escrow recovery for context:%@, altdsid:%@", data.context, data.altDSID); @@ -450,6 +496,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) } else { secnotice("clique-recovery", "resetting SOS circle successful"); } + CFBridgingRelease(blowItAwayError); } else { secnotice("clique-recovery", "Legacy restore failed on a non-SOS platform"); } @@ -469,6 +516,20 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) } } + NSString* recoveryKey = sbdRecoveryArguments[getkSecureBackupRecoveryKeyKey()]; + NSNumber* usesRecoveryKey = sbdRecoveryArguments[getkSecureBackupUsesRecoveryKeyKey()]; + + if((recoveryKey != nil || [usesRecoveryKey boolValue] == YES) + && [clique fetchCliqueStatus:&localError] == CliqueStatusIn) { + secnotice("clique-recovery", "recovery key used during secure backup recovery, skipping bottle check"); + secnotice("clique-recovery", "recovery complete: %@", clique); + + subTaskSuccess = clique ? true : false; + OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNamePerformEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformEscrowRecovery), (int)subTaskSuccess); + + return clique; + } + // look for OT Bottles OTControl* control = [clique makeOTControl:&localError]; if (!control) { @@ -490,7 +551,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) secnotice("clique-recovery", "recovering from bottle: %@", bottleID); __block NSError* restoreBottleError = nil; - OctagonSignpost bottleRecoverySignPost = OctagonSignpostBegin(OctagonSignpostNamePerformBottleRecovery); + OctagonSignpost bottleRecoverySignPost = OctagonSignpostBegin(OctagonSignpostNamePerformOctagonJoin); //restore bottle! [control restore:OTCKContainerName contextID:data.context @@ -507,7 +568,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) }]; subTaskSuccess = (restoreBottleError == nil) ? true : false; - OctagonSignpostEnd(bottleRecoverySignPost, OctagonSignpostNamePerformBottleRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformBottleRecovery), (int)subTaskSuccess); + OctagonSignpostEnd(bottleRecoverySignPost, OctagonSignpostNamePerformOctagonJoin, OctagonSignpostNumber1(OctagonSignpostNamePerformOctagonJoin), (int)subTaskSuccess); if(restoreBottleError) { if(error){ @@ -532,6 +593,11 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) if(resetError) { secnotice("clique-recovery", "failed to reset octagon: %@", resetError); + if(error){ + *error = resetError; + } + OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNamePerformEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformEscrowRecovery), (int)subTaskSuccess); + return nil; } else{ secnotice("clique-recovery", "reset octagon succeeded"); } @@ -770,20 +836,9 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) if([OTClique platformSupportsSOS] && sosIdentifiers.count >0) { CFErrorRef removeFriendError = NULL; - NSData* analyticsData = nil; secnotice("clique-removefriends", "removing sos friends: %@", sosIdentifiers); - - if(self.ctx.analytics){ - NSError* encodingError = nil; - analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - } - - if(analyticsData) { - result = SOSCCRemovePeersFromCircleWithAnalytics((__bridge CFArrayRef)friendIdentifiers, (__bridge CFDataRef)analyticsData, &removeFriendError); - } else { - result = SOSCCRemovePeersFromCircle((__bridge CFArrayRef)friendIdentifiers, &removeFriendError); - } + result = SOSCCRemovePeersFromCircle((__bridge CFArrayRef)friendIdentifiers, &removeFriendError); if(removeFriendError) { secnotice("clique-removefriends", "removeFriendsInClique failed: unable to remove friends: %@", removeFriendError); @@ -858,21 +913,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) } if([OTClique platformSupportsSOS]) { - NSData* analyticsData = nil; - - if(self.ctx.analytics) { - NSError* encodingError = nil; - analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - if(!analyticsData){ - secnotice("clique-leaveClique", "leaveClique unable to archive analytics object: %@", encodingError); - } - } - - if(analyticsData) { - result &= SOSCCRemoveThisDeviceFromCircleWithAnalytics((__bridge CFDataRef)analyticsData, &removeThisDeviceError); - } else { - result &= SOSCCRemoveThisDeviceFromCircle(&removeThisDeviceError); - } + result &= SOSCCRemoveThisDeviceFromCircle(&removeThisDeviceError); if (error) { *error = (NSError*)CFBridgingRelease(removeThisDeviceError); } else { @@ -992,6 +1033,11 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) } - (BOOL)safariPasswordSyncingEnabled:(NSError **)error +{ + return [self fetchUserControllableViewsSyncingEnabled:error]; +} + +- (BOOL)sosSafariPasswordSyncingEnabled:(NSError **)error { secnotice("clique-safari", "safariPasswordSyncingEnabled for context:%@, altdsid:%@", self.ctx.context, self.ctx.altDSID); OctagonSignpost safariSyncingEnabledSignPost = OctagonSignpostBegin(OctagonSignpostNameSafariPasswordSyncingEnabled); @@ -1025,6 +1071,158 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) } } +- (BOOL)setUserControllableViewsSyncStatus:(BOOL)enabled + error:(NSError* __autoreleasing *)error +{ + if([OTClique platformSupportsSOS]) { + // We either enable or disable this list of SOS views, taken from CDP. + NSSet* sosViews = [NSSet setWithObjects:(__bridge id)kSOSViewWiFi, + (__bridge id)kSOSViewAutofillPasswords, + (__bridge id)kSOSViewSafariCreditCards, + (__bridge id)kSOSViewOtherSyncable, + nil]; + + BOOL sosResult = NO; + if(enabled) { + sosResult = [self sosViewSet:sosViews disabledViews:[NSSet set]]; + } else { + sosResult = [self sosViewSet:[NSSet set] disabledViews:sosViews]; + } + + if(sosResult == NO) { + secnotice("clique-user-sync", "SOS view setting failed, but no error returned"); + if(error) { + *error = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain + code:kSOSErrorNotReady + userInfo:@{ + NSLocalizedDescriptionKey: @"SOS reported failure, but no error given" + }]; + } + + return NO; + } + } + + if(OctagonIsEnabled()) { + return [self setOctagonUserControllableViewsSyncEnabled:enabled + error:error]; + } + + return YES; +} + +- (BOOL)setOctagonUserControllableViewsSyncEnabled:(BOOL)enabled + error:(NSError* __autoreleasing *)error +{ +#if OCTAGON + OTControl* control = [self makeOTControl:error]; + if(!control) { + return NO; + } + + __block NSError* localError = nil; + + secnotice("clique-user-sync", "setting user-controllable-sync status to %@", enabled ? @"enabled" : @"paused"); + + [control setUserControllableViewsSyncStatus:self.ctx.containerName + contextID:self.ctx.context + enabled:enabled + reply:^(BOOL nowSyncing, NSError* _Nullable fetchError) { + if(fetchError) { + secnotice("clique-user-sync", "setting user-controllable-sync status errored: %@", fetchError); + localError = fetchError; + } else { + secnotice("clique-user-sync", "setting user-controllable-sync status succeeded, now : %@", nowSyncing ? @"enabled" : @"paused"); + } + }]; + + if(error && localError) { + *error = localError; + } + + return localError == nil; +#else + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + userInfo:@{NSLocalizedDescriptionKey: @"setOctagonUserControllableViewSync unimplemented on this platform"}]; + } + return NO; +#endif +} + +- (BOOL)fetchUserControllableViewsSyncingEnabled:(NSError* __autoreleasing *)error +{ + if(!OctagonIsEnabled() && ![OTClique platformSupportsSOS]) { + secnotice("clique-user-sync", "No syncing platforms enabled; views are not syncing"); + return NO; + } + + __block BOOL octagonSyncing = NO; +#if OCTAGON + if(OctagonIsEnabled()) { + OTControl* control = [self makeOTControl:error]; + if(!control) { + return NO; + } + + __block NSError* localError = nil; + [control fetchUserControllableViewsSyncStatus:self.ctx.containerName + contextID:self.ctx.context + reply:^(BOOL nowSyncing, NSError* _Nullable fetchError) { + if(fetchError) { + secnotice("clique-user-sync", "fetching user-controllable-sync status errored: %@", fetchError); + } else { + secnotice("clique-user-sync", "fetched user-controllable-sync status as : %@", nowSyncing ? @"enabled" : @"paused"); + } + octagonSyncing = nowSyncing; + localError = fetchError; + }]; + + if(localError) { + if(error) { + *error = localError; + } + return octagonSyncing; + } + } +#endif + + BOOL sosSafariEnabled = NO; + if([OTClique platformSupportsSOS]) { + NSError* localError = nil; + sosSafariEnabled = [self sosSafariPasswordSyncingEnabled:&localError]; + + if(localError) { + if(error) { + *error = localError; + } + return sosSafariEnabled; + } + } + + if(OctagonIsEnabled() && [OTClique platformSupportsSOS]) { + // Return the OR of this value, so that the UI checkbox will be on if any syncing is occurring + return octagonSyncing || sosSafariEnabled; + + } else if(OctagonIsEnabled() && ![OTClique platformSupportsSOS]) { + return octagonSyncing; + + } else if(!OctagonIsEnabled()&& [OTClique platformSupportsSOS]) { + return sosSafariEnabled; + + } else { + // Should be impossible, due to the check above. So: + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + userInfo:@{NSLocalizedDescriptionKey: @"fetchUserControllableViewsSyncingEnabled has no meaning if all sync systems are not on this platform"}]; + } + return NO; + } +} + + - (BOOL)isLastFriend:(NSError **)error { secnotice("clique-isLastFriend", "is last friend"); @@ -1040,20 +1238,8 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) if([OTClique platformSupportsSOS]) { CFErrorRef initialSyncErrorRef = NULL; - bool result = false; - if(self.ctx.analytics){ - NSError* encodingError = nil; - NSData* analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - if(!encodingError && analyticsData){ - result = SOSCCWaitForInitialSyncWithAnalytics((__bridge CFDataRef)analyticsData, &initialSyncErrorRef); - }else{ - result = SOSCCWaitForInitialSync(&initialSyncErrorRef); - } - }else{ - result = SOSCCWaitForInitialSync(&initialSyncErrorRef); - } + BOOL initialSyncResult = SOSCCWaitForInitialSync(&initialSyncErrorRef) ? YES : NO; - BOOL initialSyncResult = result ? YES : NO; if (error) { *error = (NSError*)CFBridgingRelease(initialSyncErrorRef); } else { @@ -1112,26 +1298,44 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) - (BOOL)viewSet:(NSSet*)enabledViews disabledViews:(NSSet*)disabledViews { - secnotice("clique-legacy", "viewSet for context:%@, altdsid:%@", self.ctx.context, self.ctx.altDSID); + if(OctagonIsEnabled()) { + + bool enableUserViews = [enabledViews containsObject:(__bridge NSString*)kSOSViewAutofillPasswords]; + if(enableUserViews && SOSVisibleKeychainNotAllowed()) { + secnotice("clique-legacy", "Cannot enable visible keychain views due to profile restrictions"); + return NO; + } + + NSError* octagonError = nil; + // This function should log its success or failure + BOOL result = [self setOctagonUserControllableViewsSyncEnabled:enableUserViews error:&octagonError]; + if(!result) { + return NO; + } + } + + return [self sosViewSet:enabledViews disabledViews:disabledViews]; +} + +- (BOOL)sosViewSet:(NSSet*)enabledViews disabledViews:(NSSet*)disabledViews +{ + secnotice("clique-legacy", "viewSet for context:%@, altdsid:%@ enable:%@, disable:%@", + self.ctx.context, self.ctx.altDSID, enabledViews, disabledViews); OctagonSignpost signPost = OctagonSignpostBegin(OctagonSignpostNameViewSet); bool subTaskSuccess = false; if([OTClique platformSupportsSOS]) { - bool result = false; - if(self.ctx.analytics){ - NSError* encodingError = nil; - NSData* analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - if(!encodingError && analyticsData){ - result = SOSCCViewSetWithAnalytics((__bridge CFSetRef)enabledViews, (__bridge CFSetRef)disabledViews, (__bridge CFDataRef)analyticsData); - }else{ - result = SOSCCViewSet((__bridge CFSetRef)enabledViews, (__bridge CFSetRef)disabledViews); - } - }else{ - result = SOSCCViewSet((__bridge CFSetRef)enabledViews, (__bridge CFSetRef)disabledViews); + if(SOSVisibleKeychainNotAllowed() && enabledViews && [enabledViews count] && SOSViewSetIntersectsV0((__bridge CFSetRef)(enabledViews))) { + secnotice("clique-legacy", "Cannot enable visible keychain views due to profile restrictions"); + enabledViews = nil; } - BOOL viewSetResult = result ? YES : NO; - subTaskSuccess = result; + BOOL viewSetResult = NO; + if(enabledViews || disabledViews) { + bool result = SOSCCViewSet((__bridge CFSetRef)enabledViews, (__bridge CFSetRef)disabledViews); + viewSetResult = result ? YES : NO; + subTaskSuccess = result; + } OctagonSignpostEnd(signPost, OctagonSignpostNameViewSet, OctagonSignpostNumber1(OctagonSignpostNameViewSet), (int)subTaskSuccess); return viewSetResult; } else { @@ -1151,36 +1355,18 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) if([OTClique platformSupportsSOS]) { CFErrorRef setCredentialsErrorRef = NULL; - bool result = false; - if(self.ctx.analytics){ - NSError* encodingError = nil; - NSData* analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - if(!encodingError && analyticsData){ - result = SOSCCSetUserCredentialsAndDSIDWithAnalytics((__bridge CFStringRef)userLabel, - (__bridge CFDataRef)userPassword, - (__bridge CFStringRef)self.ctx.dsid, - (__bridge CFDataRef)analyticsData, - &setCredentialsErrorRef); - }else{ - result = SOSCCSetUserCredentialsAndDSID((__bridge CFStringRef)userLabel, - (__bridge CFDataRef)userPassword, - (__bridge CFStringRef)self.ctx.dsid, - &setCredentialsErrorRef); - } - }else{ - result = SOSCCSetUserCredentialsAndDSID((__bridge CFStringRef)userLabel, - (__bridge CFDataRef)userPassword, - (__bridge CFStringRef)self.ctx.dsid, - &setCredentialsErrorRef); - } + bool result = SOSCCSetUserCredentialsAndDSID((__bridge CFStringRef)userLabel, + (__bridge CFDataRef)userPassword, + (__bridge CFStringRef)self.ctx.dsid, + &setCredentialsErrorRef); BOOL setCredentialsResult = result ? YES : NO; + secnotice("clique-legacy", "setUserCredentialsAndDSID results: %d %@", setCredentialsResult, setCredentialsErrorRef); if (error) { *error = (NSError*)CFBridgingRelease(setCredentialsErrorRef); } else { CFBridgingRelease(setCredentialsErrorRef); } - secnotice("clique-legacy", "setUserCredentialsAndDSID results: %d %@", setCredentialsResult, setCredentialsErrorRef); subTaskSuccess = result; OctagonSignpostEnd(signPost, OctagonSignpostNameSetUserCredentialsAndDSID, OctagonSignpostNumber1(OctagonSignpostNameSetUserCredentialsAndDSID), (int)subTaskSuccess); @@ -1213,12 +1399,12 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) &tryCredentialsErrorRef); BOOL tryCredentialsResult = result ? YES : NO; + secnotice("clique-legacy", "tryUserCredentialsAndDSID results: %d %@", tryCredentialsResult, tryCredentialsErrorRef); if (error) { *error = (NSError*)CFBridgingRelease(tryCredentialsErrorRef); } else { CFBridgingRelease(tryCredentialsErrorRef); } - secnotice("clique-legacy", "tryUserCredentialsAndDSID results: %d %@", tryCredentialsResult, tryCredentialsErrorRef); subTaskSuccess = result; OctagonSignpostEnd(signPost, OctagonSignpostNameTryUserCredentialsAndDSID, OctagonSignpostNumber1(OctagonSignpostNameTryUserCredentialsAndDSID), (int)subTaskSuccess); return tryCredentialsResult; @@ -1247,12 +1433,12 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) NSArray* peerList = (result ? (NSArray*)(CFBridgingRelease(result)) : nil); + secnotice("clique-legacy", "copyPeerPeerInfo results: %@ (%@)", peerList, copyPeerErrorRef); if (error) { *error = (NSError*)CFBridgingRelease(copyPeerErrorRef); } else { CFBridgingRelease(copyPeerErrorRef); } - secnotice("clique-legacy", "copyPeerPeerInfo results: %@", peerList); subTaskSuccess = (peerList != nil) ? true : false; OctagonSignpostEnd(signPost, OctagonSignpostNameCopyPeerPeerInfo, OctagonSignpostNumber1(OctagonSignpostNameCopyPeerPeerInfo), (int)subTaskSuccess); return peerList; @@ -1282,12 +1468,13 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) if(result){ viewsEnabledResult = CFBooleanGetValue(result) ? YES : NO; } + secnotice("clique-legacy", "peersHaveViewsEnabled results: %@ (%@)", viewsEnabledResult ? @"YES" : @"NO", + viewsEnabledErrorRef); if (error) { *error = (NSError*)CFBridgingRelease(viewsEnabledErrorRef); } else { CFBridgingRelease(viewsEnabledErrorRef); } - secnotice("clique-legacy", "peersHaveViewsEnabled results: %@", viewsEnabledResult ? @"YES" : @"NO"); subTaskSuccess = viewsEnabledResult ? true : false; OctagonSignpostEnd(signPost, OctagonSignpostNamePeersHaveViewsEnabled, OctagonSignpostNumber1(OctagonSignpostNamePeersHaveViewsEnabled), (int)subTaskSuccess); return viewsEnabledResult; @@ -1306,7 +1493,6 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) - (BOOL)requestToJoinCircle:(NSError *__autoreleasing*)error { bool result = false; - CFErrorRef joinErrorRef = NULL; bool subTaskSuccess = false; OctagonSignpost signPost = OctagonSignpostBegin(OctagonSignpostNameRequestToJoinCircle); @@ -1349,7 +1535,7 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) // If we didn't early-exit, and we aren't going to invoke SOS below, we succeeded. if(!OctagonPlatformSupportsSOS()) { - secnotice("clique-legacy", "requestToJoinCircle results: %d %@", result, joinErrorRef); + secnotice("clique-legacy", "requestToJoinCircle platform does not support SOS"); subTaskSuccess = true; OctagonSignpostEnd(signPost, OctagonSignpostNameRequestToJoinCircle, OctagonSignpostNumber1(OctagonSignpostNameRequestToJoinCircle), (int)subTaskSuccess); return YES; @@ -1358,26 +1544,16 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) #endif // OCTAGON if([OTClique platformSupportsSOS]) { - NSData* analyticsData = nil; - if(self.ctx.analytics){ - NSError* encodingError = nil; - analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - } - - if(analyticsData){ - result = SOSCCRequestToJoinCircleWithAnalytics((__bridge CFDataRef)analyticsData, &joinErrorRef); - } else { - result = SOSCCRequestToJoinCircle(&joinErrorRef); - } - + CFErrorRef joinErrorRef = NULL; + result = SOSCCRequestToJoinCircle(&joinErrorRef); secnotice("clique-legacy", "sos requestToJoinCircle complete: %d %@", result, joinErrorRef); + if (error) { + *error = (NSError*)CFBridgingRelease(joinErrorRef); + } else { + CFBridgingRelease(joinErrorRef); + } } - if (error) { - *error = (NSError*)CFBridgingRelease(joinErrorRef); - } else { - CFBridgingRelease(joinErrorRef); - } subTaskSuccess = result; OctagonSignpostEnd(signPost, OctagonSignpostNameRequestToJoinCircle, OctagonSignpostNumber1(OctagonSignpostNameRequestToJoinCircle), (int)subTaskSuccess); @@ -1405,6 +1581,62 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) } } ++ (NSArray* _Nullable)fetchEscrowRecordsInternal:(OTConfigurationContext*)configurationContext + error:(NSError**)error +{ +#if OCTAGON + secnotice("clique-fetchrecords", "fetching escrow records for context:%@, altdsid:%@", configurationContext.context, configurationContext.altDSID); + + if(OctagonIsEnabled()) { + __block NSError* localError = nil; + __block NSArray* localRecords = nil; + + OTControl *control = [configurationContext makeOTControl:&localError]; + if (!control) { + secnotice("clique-fetchrecords", "unable to create otcontrol: %@", localError); + if (error) { + *error = localError; + } + return nil; + } + [control fetchEscrowRecords:OTCKContainerName + contextID:configurationContext.context + forceFetch:configurationContext.overrideEscrowCache + reply:^(NSArray * _Nullable records, + NSError * _Nullable fetchError) { + if(fetchError) { + secnotice("clique-fetchrecords", "fetchEscrowRecords errored: %@", fetchError); + } else { + secnotice("clique-fetchrecords", "fetchEscrowRecords succeeded: %@", records); + } + localError = fetchError; + localRecords = records; + }]; + + if(error && localError) { + *error = localError; + } + + secnotice("clique-fetchrecords", "fetchEscrowRecords complete"); + + return localRecords; + } else { + // With octagon off, fail with 'unimplemented' + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + userInfo:@{NSLocalizedDescriptionKey: @"fetching escrow records unimplemented"}]; + } + return nil; + } +#else // !OCTAGON + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return NULL; +#endif +} + // MARK: SBD interfaces + (OTBottleIDs* _Nullable)findOptimalBottleIDsWithContextData:(OTConfigurationContext*)data error:(NSError**)error @@ -1552,7 +1784,11 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) secerror("octagon-setrecoverykey, SecRKCreateRecoveryKeyWithError() failed: %@", createRecoveryKeyError); userInfo[NSLocalizedDescriptionKey] = @"SecRKCreateRecoveryKeyWithError() failed"; userInfo[NSUnderlyingErrorKey] = createRecoveryKeyError; - retError = [NSError errorWithDomain:getkSecureBackupErrorDomain() code:kSecureBackupInternalError userInfo:userInfo]; + if ([OTClique isCloudServicesAvailable] == NO) { + retError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:userInfo]; + } else { + retError = [NSError errorWithDomain:getkSecureBackupErrorDomain() code:kSecureBackupInternalError userInfo:userInfo]; + } OctagonSignpostEnd(signPost, OctagonSignpostNameSetNewRecoveryKeyWithData, OctagonSignpostNumber1(OctagonSignpostNameSetNewRecoveryKeyWithData), (int)subTaskSuccess); reply(nil, retError); return; @@ -1564,7 +1800,11 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) NSError *underlyingError = CFBridgingRelease(registerError); userInfo[NSLocalizedDescriptionKey] = @"SecRKRegisterBackupPublicKey() failed"; userInfo[NSUnderlyingErrorKey] = underlyingError; - retError = [NSError errorWithDomain:getkSecureBackupErrorDomain() code:kSecureBackupInternalError userInfo:userInfo]; + if ([OTClique isCloudServicesAvailable] == NO) { + retError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:userInfo]; + } else { + retError = [NSError errorWithDomain:getkSecureBackupErrorDomain() code:kSecureBackupInternalError userInfo:userInfo]; + } OctagonSignpostEnd(signPost, OctagonSignpostNameSetNewRecoveryKeyWithData, OctagonSignpostNumber1(OctagonSignpostNameSetNewRecoveryKeyWithData), (int)subTaskSuccess); reply(nil,retError); return; @@ -1750,6 +1990,174 @@ CliqueStatus OTCliqueStatusFromString(NSString* str) [self performedCDPStateMachineRun:type success:YES error:nil reply:reply]; } ++ (BOOL)setCDPEnabled:(OTConfigurationContext*)arguments + error:(NSError* __autoreleasing*)error +{ +#if OCTAGON + NSError *controlError = nil; + OTControl* control = [arguments makeOTControl:&controlError]; + if (!control) { + secerror("octagon-setcdpenabled: failed to fetch OTControl object: %@", controlError); + if (error) { + *error = controlError; + } + return NO; + } + + __block NSError* reterror = nil; + + [control setCDPEnabled:nil + contextID:arguments.context + reply:^(NSError * _Nullable resultError) { + if(resultError) { + secnotice("octagon-setcdpenabled", "failed to set CDP bit: %@", resultError); + reterror = resultError; + } else { + secnotice("octagon-setcdpenabled", "successfully set CDP bit"); + } + }]; + + if(reterror && error) { + *error = reterror; + } + + return (reterror == nil); +#else // !OCTAGON + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return NO; +#endif +} + ++ (OTCDPStatus)getCDPStatus:(OTConfigurationContext*)arguments + error:(NSError* __autoreleasing *)error +{ +#if OCTAGON + NSError *controlError = nil; + OTControl* control = [arguments makeOTControl:&controlError]; + if (!control) { + secerror("octagon-cdp-status: failed to fetch OTControl object: %@", controlError); + if (error) { + *error = controlError; + } + return OTCDPStatusUnknown; + } + + __block NSError* reterror = nil; + __block OTCDPStatus retcdpstatus = OTCDPStatusUnknown; + + [control getCDPStatus:nil + contextID:arguments.context + reply:^(OTCDPStatus status, NSError * _Nullable resultError) { + if(resultError) { + secnotice("octagon-cdp-status", "failed to fetch CDP status: %@", resultError); + reterror = resultError; + + } else { + secnotice("octagon-cdp-status", "successfully fetched CDP status as %@", OTCDPStatusToString(status)); + retcdpstatus = status; + } + }]; + + if(reterror && error) { + *error = reterror; + } + + return retcdpstatus; +#else // !OCTAGON + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return OTCDPStatusDisabled; +#endif +} + ++ (OTClique* _Nullable)resetProtectedData:(OTConfigurationContext*)data error:(NSError**)error +{ +#if OCTAGON + if ([OTClique isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } + NSError *controlError = nil; + OTControl *control = [data makeOTControl:&controlError]; + if (!control) { + secerror("clique-reset-protected-data: unable to create otcontrol: %@", controlError); + if (error) { + *error = controlError; + } + return nil; + } + + __block NSError* localError = nil; + + //delete all records + id sb = data.sbd ?: [[getSecureBackupClass() alloc] init]; + + NSDictionary* deletionInformation = @{ getkSecureBackupAuthenticationAppleID() : data.authenticationAppleID, + getkSecureBackupAuthenticationPassword() : data.passwordEquivalentToken, + getkSecureBackupiCloudDataProtectionDeleteAllRecordsKey() : @YES, + getkSecureBackupContainsiCDPDataKey() : @YES}; + + NSError* sbError = [sb disableWithInfo:deletionInformation]; + if(sbError) { + secerror("clique-reset-protected-data: secure backup escrow record deletion failed: %@", sbError); + if(error) { + *error = sbError; + } + return nil; + } else { + secnotice("clique-reset-protected-data", "sbd disableWithInfo succeeded"); + } + + //reset sos + if(OctagonPlatformSupportsSOS()) { + //reset SOS + CFErrorRef sosError = NULL; + bool resetSuccess = SOSCCResetToOffering(&sosError); + + if(sosError || !resetSuccess) { + secerror("clique-reset-protected-data: sos reset failed: %@", sosError); + if(error) { + *error = (NSError*)CFBridgingRelease(sosError); + } + return nil; + } else { + secnotice("clique-reset-protected-data", "sos reset succeeded"); + } + } else { + secnotice("clique-reset-protected-data", "platform does not support sos"); + } + + //reset octagon + OTClique* clique = [[OTClique alloc] initWithContextData:data]; + if(OctagonIsEnabled()) { + [clique resetAndEstablish:CuttlefishResetReasonUserInitiatedReset error:&localError]; + + if(localError) { + secerror("clique-reset-protected-data: account reset failed: %@", localError); + if(error) { + *error = localError; + } + return nil; + } else { + secnotice("clique-reset-protected-data", "Octagon account reset succeeded"); + } + } + + return clique; +#else // !OCTAGON + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; +#endif + +} + @end #endif /* OBJC2 */ diff --git a/keychain/ot/OTConstants.h b/keychain/ot/OTConstants.h index 736ab162..6898c1b7 100644 --- a/keychain/ot/OTConstants.h +++ b/keychain/ot/OTConstants.h @@ -27,6 +27,7 @@ #include bool OctagonIsEnabled(void); +bool SecErrorIsNestedErrorCappingEnabled(void); #if __OBJC__ @@ -44,6 +45,7 @@ extern NSString* OTProtocolPairing; extern NSString* OTProtocolPiggybacking; extern const char * OTTrustStatusChangeNotification; +extern NSString* OTEscrowRecordPrefix; BOOL OctagonPlatformSupportsSOS(void); @@ -64,6 +66,17 @@ void OctagonAuthoritativeTrustSetIsEnabled(BOOL value); BOOL OctagonIsSOSFeatureEnabled(void); void OctagonSetSOSFeatureEnabled(BOOL value); +BOOL OctagonIsOptimizationEnabled(void); +void OctagonSetOptimizationEnabled(BOOL value); + +BOOL OctagonIsEscrowRecordFetchEnabled(void); +void OctagonSetEscrowRecordFetchEnabled(BOOL value); + +BOOL SecKVSOnCloudKitIsEnabled(void); +void SecKVSOnCloudKitSetOverrideIsEnabled(BOOL value); + +void SecErrorSetOverrideNestedErrorCappingIsEnabled(BOOL value); + typedef NS_ENUM(NSInteger, CuttlefishResetReason) { CuttlefishResetReasonUnknown = 0, CuttlefishResetReasonUserInitiatedReset = 1, @@ -74,6 +87,9 @@ typedef NS_ENUM(NSInteger, CuttlefishResetReason) { CuttlefishResetReasonTestGenerated = 6, }; +extern NSString* const CuttlefishErrorDomain; +extern NSString* const CuttlefishErrorRetryAfterKey; + #endif // __OBJC__ #endif /* OTConstants_h */ diff --git a/keychain/ot/OTConstants.m b/keychain/ot/OTConstants.m index e839d139..9d133e61 100644 --- a/keychain/ot/OTConstants.m +++ b/keychain/ot/OTConstants.m @@ -42,6 +42,11 @@ NSString* OTProtocolPiggybacking = @"OctagonPiggybacking"; const char * OTTrustStatusChangeNotification = "com.apple.security.octagon.trust-status-change"; +NSString* const CuttlefishErrorDomain = @"CuttlefishError"; +NSString* const CuttlefishErrorRetryAfterKey = @"retryafter"; + +NSString* OTEscrowRecordPrefix = @"com.apple.icdp.record."; + // I don't recommend using this command, but it does describe the plist that will enable this feature: // // defaults write /System/Library/FeatureFlags/Domain/Security octagon -dict Enabled -bool YES @@ -58,6 +63,18 @@ static bool OctagonAuthoritativeTrustEnabledOverride = false; static bool OctagonSOSFeatureIsEnabledOverrideSet = false; static bool OctagonSOSFeatureIsEnabledOverride = false; +static bool OctagonOptimizationIsEnabledOverrideSet = false; +static bool OctagonOptimizationIsEnabledOverride = false; + +static bool OctagonEscrowRecordFetchIsEnabledOverrideSet = false; +static bool OctagonEscrowRecordFetchIsEnabledOverride = false; + +static bool SecKVSOnCloudKitIsEnabledOverrideSet = false; +static bool SecKVSOnCloudKitIsEnabledOverride = false; + +static bool SecErrorNestedErrorCappingIsEnabledOverrideSet = false; +static bool SecErrorNestedErrorCappingIsEnabledOverride = false; + bool OctagonIsEnabled(void) { if(OctagonEnabledOverrideSet) { @@ -191,7 +208,7 @@ BOOL OctagonIsSOSFeatureEnabled(void) { if(OctagonSOSFeatureIsEnabledOverrideSet) { secnotice("octagon", "SOS Feature is %@ (overridden)", OctagonSOSFeatureIsEnabledOverride ? @"enabled" : @"disabled"); - return OctagonSOSFeatureIsEnabledOverrideSet; + return OctagonSOSFeatureIsEnabledOverride; } static bool sosEnabled = true; @@ -209,3 +226,100 @@ void OctagonSetSOSFeatureEnabled(BOOL value) OctagonSOSFeatureIsEnabledOverrideSet = true; OctagonSOSFeatureIsEnabledOverride = value; } + +//feature flag for enabling/disabling performance enhancements +BOOL OctagonIsOptimizationEnabled(void) +{ + if(OctagonOptimizationIsEnabledOverrideSet) { + secnotice("octagon", "Octagon Optimization is %@ (overridden)", OctagonOptimizationIsEnabledOverride ? @"enabled" : @"disabled"); + return OctagonOptimizationIsEnabledOverride; + } + + static bool optimizationEnabled = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + optimizationEnabled = os_feature_enabled(Security, OctagonOptimization); + secnotice("octagon", "Octagon Optimization is %@ (via feature flags)", optimizationEnabled ? @"enabled" : @"disabled"); + }); + + return optimizationEnabled; +} + +void OctagonSetOptimizationEnabled(BOOL value) +{ + OctagonOptimizationIsEnabledOverrideSet = true; + OctagonOptimizationIsEnabledOverride = value; +} + + +//feature flag for checking if escrow record fetching is enabled +BOOL OctagonIsEscrowRecordFetchEnabled(void) +{ + if(OctagonEscrowRecordFetchIsEnabledOverrideSet) { + secnotice("octagon", "Octagon Escrow Record Fetching is %@ (overridden)", OctagonEscrowRecordFetchIsEnabledOverride ? @"enabled" : @"disabled"); + return OctagonEscrowRecordFetchIsEnabledOverride; + } + + static bool escrowRecordFetchingEnabled = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + escrowRecordFetchingEnabled = os_feature_enabled(Security, OctagonEscrowRecordFetch); + secnotice("octagon", "Octagon Escrow Record Fetching is %@ (via feature flags)", escrowRecordFetchingEnabled ? @"enabled" : @"disabled"); + }); + + return escrowRecordFetchingEnabled; +} + +void OctagonSetEscrowRecordFetchEnabled(BOOL value) +{ + OctagonEscrowRecordFetchIsEnabledOverrideSet = true; + OctagonEscrowRecordFetchIsEnabledOverride = value; +} + +//feature flag for checking kvs on cloudkit enablement +BOOL SecKVSOnCloudKitIsEnabled(void) +{ + if(SecKVSOnCloudKitIsEnabledOverrideSet) { + secnotice("octagon", "KVS on CloudKit is %@ (overridden)", SecKVSOnCloudKitIsEnabledOverride ? @"enabled" : @"disabled"); + return SecKVSOnCloudKitIsEnabledOverride; + } + + static bool kvsOnCloudKitEnabled = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + kvsOnCloudKitEnabled = os_feature_enabled(KVS, KVSOnCloudKitForAll); + secnotice("octagon", "KVS on CloudKit is %@ (via feature flags)", kvsOnCloudKitEnabled ? @"enabled" : @"disabled"); + }); + + return kvsOnCloudKitEnabled; +} + +void SecKVSOnCloudKitSetOverrideIsEnabled(BOOL value) +{ + SecKVSOnCloudKitIsEnabledOverrideSet = true; + SecKVSOnCloudKitIsEnabledOverride = value; +} + +//feature flag for checking whether or not we should cap the number of nested errors +bool SecErrorIsNestedErrorCappingEnabled(void) +{ + if(SecErrorNestedErrorCappingIsEnabledOverrideSet) { + secnotice("octagon", "SecError Nested Error Capping is %@ (overridden)", SecErrorNestedErrorCappingIsEnabledOverride ? @"enabled" : @"disabled"); + return SecErrorNestedErrorCappingIsEnabledOverride; + } + + static bool errorCappingEnabled = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + errorCappingEnabled = os_feature_enabled(Security, SecErrorNestedErrorCapping); + secnotice("octagon", "SecError Nested Error Capping is %@ (via feature flags)", errorCappingEnabled ? @"enabled" : @"disabled"); + }); + + return errorCappingEnabled; +} + +void SecErrorSetOverrideNestedErrorCappingIsEnabled(BOOL value) +{ + SecErrorNestedErrorCappingIsEnabledOverrideSet = true; + SecErrorNestedErrorCappingIsEnabledOverride = value; +} diff --git a/keychain/ot/OTControl.h b/keychain/ot/OTControl.h index 6e8b48de..85589e1d 100644 --- a/keychain/ot/OTControl.h +++ b/keychain/ot/OTControl.h @@ -85,12 +85,12 @@ NS_ASSUME_NONNULL_BEGIN NSError * _Nullable error))reply; - (void)rpcPrepareIdentityAsApplicantWithConfiguration:(OTJoiningConfiguration*)config - reply:(void (^)(NSString * _Nullable peerID, - NSData * _Nullable permanentInfo, - NSData * _Nullable permanentInfoSig, - NSData * _Nullable stableInfo, - NSData * _Nullable stableInfoSig, - NSError * _Nullable error))reply; + reply:(void (^)(NSString * _Nullable peerID, + NSData * _Nullable permanentInfo, + NSData * _Nullable permanentInfoSig, + NSData * _Nullable stableInfo, + NSData * _Nullable stableInfoSig, + NSError * _Nullable error))reply; - (void)rpcVoucherWithConfiguration:(OTJoiningConfiguration*)config peerID:(NSString*)peerID permanentInfo:(NSData *)permanentInfo @@ -102,7 +102,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)rpcJoinWithConfiguration:(OTJoiningConfiguration*)config vouchData:(NSData*)vouchData vouchSig:(NSData*)vouchSig - preapprovedKeys:(NSArray* _Nullable)preapprovedKeys reply:(void (^)(NSError * _Nullable error))reply; @@ -215,10 +214,6 @@ NS_ASSUME_NONNULL_BEGIN skipRateLimitingCheck:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError *_Nullable error))reply; -- (void)attemptSosUpgrade:(NSString* _Nullable)container - context:(NSString*)context - reply:(void (^)(NSError* _Nullable error))reply; - - (void)waitForOctagonUpgrade:(NSString* _Nullable)container context:(NSString*)context reply:(void (^)(NSError* _Nullable error))reply; @@ -235,6 +230,42 @@ skipRateLimitingCheck:(BOOL)skipRateLimitingCheck radar:(NSString *)radar reply:(void (^)(NSError* _Nullable error))reply; +- (void)setCDPEnabled:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply; + +- (void)getCDPStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(OTCDPStatus status, NSError* _Nullable error))reply; + +- (void)refetchCKKSPolicy:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply; + + +- (void)fetchEscrowRecords:(NSString * _Nullable)container + contextID:(NSString*)contextID + forceFetch:(BOOL)forceFetch + reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply; + +- (void)setUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + enabled:(BOOL)enabled + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply; + +- (void)fetchUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply; + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply; + +- (void)resetAccountCDPContents:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTControl.m b/keychain/ot/OTControl.m index ce1d0965..1f73d89d 100644 --- a/keychain/ot/OTControl.m +++ b/keychain/ot/OTControl.m @@ -232,13 +232,12 @@ - (void)rpcJoinWithConfiguration:(OTJoiningConfiguration*)config vouchData:(NSData*)vouchData vouchSig:(NSData*)vouchSig - preapprovedKeys:(NSArray* _Nullable)preapprovedKeys reply:(void (^)(NSError * _Nullable error))reply { #if OCTAGON [[self getConnection: ^(NSError* error) { reply(error); - }] rpcJoinWithConfiguration:config vouchData:vouchData vouchSig:vouchSig preapprovedKeys:preapprovedKeys reply:^(NSError* e) { + }] rpcJoinWithConfiguration:config vouchData:vouchData vouchSig:vouchSig reply:^(NSError* e) { reply(e); }]; #else @@ -442,15 +441,6 @@ skipRateLimitingCheck:(BOOL)skipRateLimitingCheck }] healthCheck:container context:context skipRateLimitingCheck:skipRateLimitingCheck reply:reply]; } -- (void)attemptSosUpgrade:(NSString* _Nullable)container - context:(NSString*)context - reply:(void (^)(NSError* _Nullable error))reply -{ - [[self getConnection: ^(NSError* error) { - reply(error); - }] attemptSosUpgrade:container context:context reply:reply]; -} - - (void)waitForOctagonUpgrade:(NSString* _Nullable)container context:(NSString*)context reply:(void (^)(NSError* _Nullable error))reply @@ -482,6 +472,82 @@ skipRateLimitingCheck:(BOOL)skipRateLimitingCheck }] tapToRadar:action description:description radar:radar reply:reply]; } +- (void)refetchCKKSPolicy:(NSString* _Nullable)container + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* error) { + reply(error); + }] refetchCKKSPolicy:container contextID:contextID reply:reply]; +} + +- (void)setCDPEnabled:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(connectionError); + }] setCDPEnabled:containerName contextID:contextID reply:reply]; +} + +- (void)getCDPStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(OTCDPStatus status, NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(OTCDPStatusUnknown, connectionError); + }] getCDPStatus:containerName contextID:contextID reply:reply]; +} + +- (void)fetchEscrowRecords:(NSString * _Nullable)container + contextID:(NSString*)contextID + forceFetch:(BOOL)forceFetch + reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(nil, connectionError); + }] fetchEscrowRecords:container contextID:contextID forceFetch:forceFetch reply:reply]; +} + +- (void)setUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + enabled:(BOOL)enabled + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(NO, connectionError); + }] setUserControllableViewsSyncStatus:containerName contextID:contextID enabled:enabled reply:reply]; + +} + +- (void)fetchUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(NO, connectionError); + }] fetchUserControllableViewsSyncStatus:containerName contextID:contextID reply:reply]; +} + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(connectionError); + }] invalidateEscrowCache:containerName contextID:contextID reply:reply]; +} + +- (void)resetAccountCDPContents:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(connectionError); + }] resetAccountCDPContents:containerName contextID:contextID reply:reply]; +} + + (OTControl*)controlObject:(NSError* __autoreleasing *)error { return [OTControl controlObject:false error:error]; } diff --git a/keychain/ot/OTControlProtocol.h b/keychain/ot/OTControlProtocol.h index 6af4bbef..2f5f3a0b 100644 --- a/keychain/ot/OTControlProtocol.h +++ b/keychain/ot/OTControlProtocol.h @@ -34,8 +34,6 @@ NS_ASSUME_NONNULL_BEGIN @class OTJoiningConfiguration; -typedef void (^OTNextJoinCompleteBlock)(BOOL finished, NSData* _Nullable message, NSError* _Nullable error); - @protocol OTControlProtocol - (void)restore:(NSString *)contextID dsid:(NSString *)dsid secret:(NSData*)secret escrowRecordID:(NSString*)escrowRecordID reply:(void (^)(NSData* _Nullable signingKeyData, NSData* _Nullable encryptionKeyData, NSError * _Nullable error))reply; - (void)octagonEncryptionPublicKey:(void (^)(NSData* _Nullable encryptionKey, NSError * _Nullable))reply; @@ -86,7 +84,6 @@ typedef void (^OTNextJoinCompleteBlock)(BOOL finished, NSData* _Nullable message - (void)rpcJoinWithConfiguration:(OTJoiningConfiguration*)config vouchData:(NSData*)vouchData vouchSig:(NSData*)vouchSig - preapprovedKeys:(NSArray* _Nullable)preapprovedKeys reply:(void (^)(NSError * _Nullable error))reply; - (void)preflightBottledPeer:(NSString*)contextID @@ -186,10 +183,6 @@ typedef void (^OTNextJoinCompleteBlock)(BOOL finished, NSData* _Nullable message skipRateLimitingCheck:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError *_Nullable error))reply; -- (void)attemptSosUpgrade:(NSString* _Nullable)container - context:(NSString*)context - reply:(void (^)(NSError* _Nullable error))reply; - - (void)waitForOctagonUpgrade:(NSString* _Nullable)container context:(NSString*)context reply:(void (^)(NSError* _Nullable error))reply; @@ -206,6 +199,41 @@ skipRateLimitingCheck:(BOOL)skipRateLimitingCheck radar:(NSString *)radar reply:(void (^)(NSError* _Nullable error))reply; +- (void)refetchCKKSPolicy:(NSString* _Nullable)container + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply; + +- (void)setCDPEnabled:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply; + +- (void)getCDPStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(OTCDPStatus status, NSError* _Nullable error))reply; + +- (void)fetchEscrowRecords:(NSString * _Nullable)container + contextID:(NSString*)contextID + forceFetch:(BOOL)forceFetch + reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply; + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply; + +/* View Handling */ +- (void)setUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + enabled:(BOOL)enabled + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply; + +- (void)fetchUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply; + +- (void)resetAccountCDPContents:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply; @end NSXPCInterface* OTSetupControlProtocol(NSXPCInterface* interface); diff --git a/keychain/ot/OTControlProtocol.m b/keychain/ot/OTControlProtocol.m index 8fa72582..5b3ea2fe 100644 --- a/keychain/ot/OTControlProtocol.m +++ b/keychain/ot/OTControlProtocol.m @@ -22,86 +22,64 @@ */ #import -#if !defined(DARLING) || OCTAGON -// Apple has some weird stuff going on here -// -// they say this function needs to be exported even when the "modern" Objective-C runtime (a.k.a. __OBJC2__) isn't available -// (you can see this in Security.exp-in) -// but then they turn around and make it impossible to compile this file as-is for i386 -// (because some classes and types aren't defined when __OBJC2__ isn't available) -// i had to manually disable these includes to make it possible to compile this file for i386 #import "keychain/ot/OTClique.h" #import "keychain/ot/OTControlProtocol.h" #import "keychain/ot/OTJoiningConfiguration.h" #import -#endif - -#if OCTAGON -#import -#import -#import -#include -#import -#import -#endif // OCTAGON - +#include NSXPCInterface* OTSetupControlProtocol(NSXPCInterface* interface) { #if OCTAGON NSSet *errorClasses = [SecXPCHelper safeErrorClasses]; @try { - [interface setClasses:errorClasses forSelector:@selector(restore:dsid:secret:escrowRecordID:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(octagonEncryptionPublicKey:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(octagonSigningPublicKey:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(listOfEligibleBottledPeerRecords:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(signOut:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(restore:dsid:secret:escrowRecordID:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(octagonEncryptionPublicKey:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(octagonSigningPublicKey:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(listOfEligibleBottledPeerRecords:) argumentIndex:1 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(signIn:container:context:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(reset:) argumentIndex:0 ofReply:YES]; - + [interface setClasses:errorClasses forSelector:@selector(signOut:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(notifyIDMSTrustLevelChangeForContainer:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(reset:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(handleIdentityChangeForSigningKey:ForEncryptionKey:ForPeerID:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcEpochWithConfiguration:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcPrepareIdentityAsApplicantWithConfiguration:reply:) argumentIndex:5 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcVoucherWithConfiguration:peerID:permanentInfo:permanentInfoSig:stableInfo:stableInfoSig:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcJoinWithConfiguration:vouchData:vouchSig:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(preflightBottledPeer:dsid:reply:) argumentIndex:3 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(launchBottledPeer:bottleID:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(scrubBottledPeer:bottleID:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(handleIdentityChangeForSigningKey:ForEncryptionKey:ForPeerID:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(status:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(fetchEgoPeerID:context:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(fetchCliqueStatus:context:configuration:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(fetchTrustStatus:context:configuration:reply:) argumentIndex:4 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(fetchEscrowContents:contextID:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(startOctagonStateMachine:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(resetAndEstablish:context:altDSID:resetReason:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(establish:context:altDSID:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(leaveClique:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(removeFriendsInClique:context:peerIDs:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(peerDeviceNamesByPeerID:context:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(fetchAllViableBottles:context:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(restore:contextID:bottleSalt:entropy:bottleID:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(fetchEscrowContents:contextID:reply:) argumentIndex:3 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(createRecoveryKey:contextID:recoveryKey:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(joinWithRecoveryKey:contextID:recoveryKey:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(healthCheck:context:skipRateLimitingCheck:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(attemptSosUpgrade:context:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(waitForOctagonUpgrade:context:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(postCDPFollowupResult:type:error:containerName:contextName:reply:) argumentIndex:2 ofReply:NO]; [interface setClasses:errorClasses forSelector:@selector(postCDPFollowupResult:type:error:containerName:contextName:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(tapToRadar:description:radar:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(resetAndEstablish:context:altDSID:resetReason:reply:) argumentIndex:0 ofReply:YES]; - -#if __OBJC2__ - - [interface setClasses:errorClasses - forSelector:@selector(rpcEpochWithConfiguration:reply:) - argumentIndex:1 - ofReply:YES]; - [interface setClasses:errorClasses - forSelector:@selector(rpcPrepareIdentityAsApplicantWithConfiguration:reply:) - argumentIndex:5 - ofReply:YES]; - [interface setClasses:errorClasses - forSelector:@selector(rpcVoucherWithConfiguration:peerID:permanentInfo:permanentInfoSig:stableInfo:stableInfoSig:reply:) - argumentIndex:2 - ofReply:YES]; - [interface setClasses:errorClasses - forSelector:@selector(rpcJoinWithConfiguration:vouchData:vouchSig:preapprovedKeys:reply:) - argumentIndex:0 - ofReply:YES]; -#endif /* __OBJC2__ */ + [interface setClasses:errorClasses forSelector:@selector(refetchCKKSPolicy:contextID:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(setCDPEnabled:contextID:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(getCDPStatus:contextID:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(fetchEscrowRecords:contextID:forceFetch:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(setUserControllableViewsSyncStatus:contextID:enabled:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(fetchUserControllableViewsSyncStatus:contextID:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(resetAccountCDPContents:contextID:reply:) argumentIndex:0 ofReply:YES]; } @catch(NSException* e) { secerror("OTSetupControlProtocol failed, continuing, but you might crash later: %@", e); -#if DEBUG @throw e; -#endif } #endif diff --git a/keychain/ot/OTCuttlefishAccountStateHolder.h b/keychain/ot/OTCuttlefishAccountStateHolder.h index 4630b7f9..5d82007e 100644 --- a/keychain/ot/OTCuttlefishAccountStateHolder.h +++ b/keychain/ot/OTCuttlefishAccountStateHolder.h @@ -3,6 +3,7 @@ #import #import "keychain/ot/proto/generated_source/OTAccountMetadataClassC.h" +#import "keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h" extern NSString* _Nonnull OTCuttlefishContextErrorDomain; typedef NS_ENUM(uint32_t, OTCuttlefishContextErrors) { @@ -33,18 +34,15 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)persistNewTrustState:(OTAccountMetadataClassC_TrustState)newState error:(NSError**)error; -- (BOOL)persistNewEpoch:(uint64_t)epoch error:(NSError**)error; - -- (BOOL)persistAccountChanges:(OTAccountMetadataClassC* (^)(OTAccountMetadataClassC* metadata))makeChanges +- (BOOL)persistAccountChanges:(OTAccountMetadataClassC* _Nullable (^)(OTAccountMetadataClassC* metadata))makeChanges error:(NSError**)error; -- (BOOL)_onqueuePersistAccountChanges:(OTAccountMetadataClassC* (^)(OTAccountMetadataClassC* metadata))makeChanges +- (BOOL)_onqueuePersistAccountChanges:(OTAccountMetadataClassC* _Nullable (^)(OTAccountMetadataClassC* metadata))makeChanges error:(NSError**)error; -- (NSDate *)lastHealthCheckupDate:(NSError * _Nullable *)error; +- (NSDate* _Nullable)lastHealthCheckupDate:(NSError * _Nullable *)error; - (BOOL)persistLastHealthCheck:(NSDate*)lastCheck error:(NSError**)error; -- (OTAccountMetadataClassC_AttemptedAJoinState)fetchPersistedJoinAttempt:(NSError * _Nullable *)error; - (BOOL)persistOctagonJoinAttempt:(OTAccountMetadataClassC_AttemptedAJoinState)attempt error:(NSError**)error; @end diff --git a/keychain/ot/OTCuttlefishAccountStateHolder.m b/keychain/ot/OTCuttlefishAccountStateHolder.m index 2455c543..320bee93 100644 --- a/keychain/ot/OTCuttlefishAccountStateHolder.m +++ b/keychain/ot/OTCuttlefishAccountStateHolder.m @@ -99,20 +99,7 @@ return current.peerID; } -- (OTAccountMetadataClassC_AttemptedAJoinState)fetchPersistedJoinAttempt:(NSError * _Nullable *)error { - NSError* localError = nil; - OTAccountMetadataClassC* current = [self loadOrCreateAccountMetadata:&localError]; - - if(localError || !current) { - if(error) { - *error = localError; - } - return OTAccountMetadataClassC_AttemptedAJoinState_UNKNOWN; - } - return current.attemptedJoin; -} - -- (NSDate *)lastHealthCheckupDate:(NSError * _Nullable *)error { +- (NSDate * _Nullable)lastHealthCheckupDate:(NSError * _Nullable *)error { NSError* localError = nil; OTAccountMetadataClassC* current = [self loadOrCreateAccountMetadata:&localError]; @@ -144,27 +131,7 @@ } error:error]; } -- (BOOL)persistNewAccountState:(OTAccountMetadataClassC_AccountState)newState - optionalAltDSID:(NSString* _Nullable)altDSID - error:(NSError**)error -{ - return [self persistAccountChanges:^(OTAccountMetadataClassC *metadata) { - metadata.icloudAccountState = newState; - metadata.altDSID = altDSID; - return metadata; - } error:error]; -} - -- (BOOL)persistNewEpoch:(uint64_t)epoch - error:(NSError**)error -{ - return [self persistAccountChanges:^(OTAccountMetadataClassC *metadata) { - metadata.epoch = epoch; - return metadata; - } error:error]; -} - -- (BOOL)persistAccountChanges:(OTAccountMetadataClassC* (^)(OTAccountMetadataClassC*))makeChanges +- (BOOL)persistAccountChanges:(OTAccountMetadataClassC* _Nullable (^)(OTAccountMetadataClassC*))makeChanges error:(NSError**)error { __block NSError* localError = nil; @@ -178,7 +145,7 @@ } newState = makeChanges([oldState copy]); - if(![newState saveToKeychainForContainer:self.containerName contextID:self.contextID error:&localError]) { + if(newState && ![newState saveToKeychainForContainer:self.containerName contextID:self.contextID error:&localError]) { newState = nil; } }); @@ -213,7 +180,7 @@ } error:error]; } -- (BOOL)_onqueuePersistAccountChanges:(OTAccountMetadataClassC* (^)(OTAccountMetadataClassC* metadata))makeChanges +- (BOOL)_onqueuePersistAccountChanges:(OTAccountMetadataClassC* _Nullable (^)(OTAccountMetadataClassC* metadata))makeChanges error:(NSError**)error { __block NSError* localError = nil; @@ -256,5 +223,4 @@ }); } - @end diff --git a/keychain/ot/OTCuttlefishContext.h b/keychain/ot/OTCuttlefishContext.h index 426c5dc8..a90002aa 100644 --- a/keychain/ot/OTCuttlefishContext.h +++ b/keychain/ot/OTCuttlefishContext.h @@ -35,6 +35,7 @@ #import "keychain/ckks/CKKSCondition.h" #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" #import "OTDeviceInformation.h" +#import "keychain/ot/OTConstants.h" #import "keychain/ot/OTDefines.h" #import "keychain/ot/OTClique.h" #import "keychain/ot/OTFollowup.h" @@ -54,6 +55,7 @@ #import #import "keychain/ckks/CKKSLockStateTracker.h" +#import "keychain/ckks/CKKSReachabilityTracker.h" #import "keychain/ckks/CKKSViewManager.h" #import "keychain/ckks/CKKSKeychainView.h" @@ -76,15 +78,13 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) CKKSLockStateTracker *lockStateTracker; @property (nonatomic, readonly) OTCuttlefishAccountStateHolder* accountMetadataStore; @property (readonly) OctagonStateMachine* stateMachine; -@property (readonly) BOOL postedRepairCFU; -@property (readonly) BOOL postedEscrowRepairCFU; -@property (readonly) BOOL postedRecoveryKeyCFU; @property (nullable, nonatomic) CKKSNearFutureScheduler* apsRateLimiter; @property (nullable, nonatomic) CKKSNearFutureScheduler* sosConsistencyRateLimiter; @property (readonly, nullable) CKKSViewManager* viewManager; // Dependencies (for injection) +@property (readonly) id deviceAdapter; @property id authKitAdapter; @property dispatch_queue_t queue; @@ -96,6 +96,7 @@ NS_ASSUME_NONNULL_BEGIN authKitAdapter:(id)authKitAdapter ckksViewManager:(CKKSViewManager* _Nullable)viewManager lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker accountStateTracker:(id)accountStateTracker deviceInformationAdapter:(id)deviceInformationAdapter apsConnectionClass:(Class)apsConnectionClass @@ -107,6 +108,11 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)accountNoLongerAvailable:(NSError**)error; - (BOOL)idmsTrustLevelChanged:(NSError**)error; +// Call these to manipulate the "CDP-ness" of the account +// Note that there is no way to turn CDP back off again +- (OTCDPStatus)getCDPStatus:(NSError* __autoreleasing *)error; +- (BOOL)setCDPEnabled:(NSError* __autoreleasing *)error; + - (void)deviceNameUpdated; - (void)startOctagonStateMachine; @@ -122,7 +128,6 @@ NS_ASSUME_NONNULL_BEGIN NSError * _Nullable error))reply; - (void)rpcJoin:(NSData*)vouchData vouchSig:(NSData*)vouchSig -preapprovedKeys:(NSArray* _Nullable)preapprovedKeys reply:(void (^)(NSError * _Nullable error))reply; - (void)rpcResetAndEstablish:(CuttlefishResetReason)resetReason reply:(nonnull void (^)(NSError * _Nullable))reply; @@ -156,15 +161,28 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys NSString* _Nullable peerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable))reply; - (void)rpcFetchDeviceNamesByPeerID:(void (^)(NSDictionary* _Nullable peers, NSError* _Nullable error))reply; -- (void)rpcFetchAllViableBottles:(void (^)(NSArray* _Nullable sortedBottleIDs, NSArray* _Nullable sortedPartialEscrowRecordIDs, NSError* _Nullable error))reply; +- (void)rpcFetchAllViableBottles:(void (^)(NSArray* _Nullable sortedBottleIDs, + NSArray* _Nullable sortedPartialEscrowRecordIDs, + NSError* _Nullable error))reply; + +- (void)rpcFetchAllViableEscrowRecords:(BOOL)forceFetch reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply; +- (void)rpcInvalidateEscrowCache:(void (^)(NSError* _Nullable error))reply; + - (void)fetchEscrowContents:(void (^)(NSData* _Nullable entropy, NSString* _Nullable bottleID, NSData* _Nullable signingPublicKey, NSError* _Nullable error))reply; - (void)rpcSetRecoveryKey:(NSString*)recoveryKey reply:(void (^)(NSError * _Nullable error))reply; +- (void)rpcRefetchCKKSPolicy:(void (^)(NSError * _Nullable error))reply; + +- (void)rpcFetchUserControllableViewsSyncingStatus:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply; +- (void)rpcSetUserControllableViewsSyncingStatus:(BOOL)status reply:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply; + - (void)requestTrustedDeviceListRefresh; - (OTDeviceInformation*)prepareInformation; @@ -174,32 +192,27 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys - (OTOperationDependencies*)operationDependencies; -- (void)attemptSOSUpgrade:(void (^)(NSError* _Nullable error))reply; - - (void)waitForOctagonUpgrade:(void (^)(NSError* error))reply NS_SWIFT_NAME(waitForOctagonUpgrade(reply:)); -- (void)clearPendingCFUFlags; - - (BOOL)waitForReady:(int64_t)timeOffset; - // For testing. -- (void)setPostedBool:(BOOL)posted; - (OTAccountMetadataClassC_AccountState)currentMemoizedAccountState; - (OTAccountMetadataClassC_TrustState)currentMemoizedTrustState; - (NSDate* _Nullable) currentMemoizedLastHealthCheck; -- (void) checkTrustStatusAndPostRepairCFUIfNecessary:(void (^ _Nullable)(CliqueStatus status, BOOL posted, BOOL hasIdentity, NSError * _Nullable error))reply; -- (void) setAccountStateHolder:(OTCuttlefishAccountStateHolder*)accountMetadataStore; +- (void)checkTrustStatusAndPostRepairCFUIfNecessary:(void (^ _Nullable)(CliqueStatus status, BOOL posted, BOOL hasIdentity, BOOL isLocked, NSError * _Nullable error))reply; +- (void)rpcResetAccountCDPContents:(void (^)(NSError* _Nullable error))reply; + +- (void)clearCKKSViewManager; + +@property (nullable) TPPolicyVersion* policyOverride; // Octagon Health Check Helpers - (void)checkOctagonHealth:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError * _Nullable error))reply; -- (BOOL)postRepairCFU:(NSError**)error; -- (void)postConfirmPasscodeCFU:(NSError**)error; -- (void)postRecoveryKeyCFU:(NSError**)error; // For reporting - (BOOL)machineIDOnMemoizedList:(NSString*)machineID error:(NSError**)error NS_SWIFT_NOTHROW; -- (NSNumber* _Nullable)numberOfPeersInModelWithMachineID:(NSString*)machineID error:(NSError**)error; +- (TrustedPeersHelperEgoPeerStatus* _Nullable)egoPeerStatus:(NSError**)error; @end diff --git a/keychain/ot/OTCuttlefishContext.m b/keychain/ot/OTCuttlefishContext.m index 0eac866a..34b6da1f 100644 --- a/keychain/ot/OTCuttlefishContext.m +++ b/keychain/ot/OTCuttlefishContext.m @@ -22,81 +22,86 @@ */ #if OCTAGON -#include - +#import +#import #import - #import - -#include #include #import +#include +#import + #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" -#import -#import "keychain/ckks/CKKS.h" -#import "keychain/ckks/CKKSAnalytics.h" -#import "keychain/ckks/CKKSResultOperation.h" +#include "keychain/SecureObjectSync/SOSInternal.h" -#import "keychain/ckks/OctagonAPSReceiver.h" #import "keychain/analytics/CKKSLaunchSequence.h" -#import "keychain/ot/OTDeviceInformationAdapter.h" - - -#import "keychain/ot/OctagonStateMachine.h" -#import "keychain/ot/OctagonStateMachineHelpers.h" -#import "keychain/ot/OctagonCKKSPeerAdapter.h" -#import "keychain/ot/OctagonCheckTrustStateOperation.h" -#import "keychain/ot/OTStates.h" -#import "keychain/ot/OTFollowup.h" +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSAccountStateTracker.h" +#import "keychain/ckks/CKKSAnalytics.h" +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSResultOperation.h" +#import "keychain/ckks/CKKSViewManager.h" +#import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/OctagonAPSReceiver.h" +#import "keychain/escrowrequest/EscrowRequestServer.h" #import "keychain/ot/OTAuthKitAdapter.h" -#import "keychain/ot/OTConstants.h" -#import "keychain/ot/OTOperationDependencies.h" -#import "keychain/ot/OTClique.h" -#import "keychain/ot/OTCuttlefishContext.h" -#import "keychain/ot/OTPrepareOperation.h" -#import "keychain/ot/OTSOSAdapter.h" -#import "keychain/ot/OTSOSUpgradeOperation.h" -#import "keychain/ot/OTUpdateTPHOperation.h" -#import "keychain/ot/OTEpochOperation.h" +#import "keychain/ot/OTCheckHealthOperation.h" #import "keychain/ot/OTClientVoucherOperation.h" -#import "keychain/ot/OTLeaveCliqueOperation.h" -#import "keychain/ot/OTRemovePeersOperation.h" +#import "keychain/ot/OTClique.h" +#import "keychain/ot/OTConstants.h" +#import "keychain/ot/OTCuttlefishAccountStateHolder.h" +#import "keychain/ot/OTCuttlefishContext.h" +#import "keychain/ot/OTDetermineCDPBitStatusOperation.h" +#import "keychain/ot/OTDetermineHSA2AccountStatusOperation.h" +#import "keychain/ot/OTDeviceInformationAdapter.h" +#import "keychain/ot/OTEnsureOctagonKeyConsistency.h" +#import "keychain/ot/OTPreloadOctagonKeysOperation.h" +#import "keychain/ot/OTEpochOperation.h" +#import "keychain/ot/OTEstablishOperation.h" +#import "keychain/ot/OTFetchViewsOperation.h" +#import "keychain/ot/OTFollowup.h" #import "keychain/ot/OTJoinWithVoucherOperation.h" +#import "keychain/ot/OTLeaveCliqueOperation.h" +#import "keychain/ot/OTLocalCKKSResetOperation.h" +#import "keychain/ot/OTLocalCuttlefishReset.h" +#import "keychain/ot/OTModifyUserControllableViewStatusOperation.h" +#import "keychain/ot/OTOperationDependencies.h" +#import "keychain/ot/OTPrepareOperation.h" +#import "keychain/ot/OTRemovePeersOperation.h" +#import "keychain/ot/OTResetCKKSZonesLackingTLKsOperation.h" +#import "keychain/ot/OTResetOperation.h" +#import "keychain/ot/OTSOSAdapter.h" +#import "keychain/ot/OTSOSUpdatePreapprovalsOperation.h" +#import "keychain/ot/OTSOSUpgradeOperation.h" +#import "keychain/ot/OTSetCDPBitOperation.h" +#import "keychain/ot/OTSetRecoveryKeyOperation.h" +#import "keychain/ot/OTStates.h" +#import "keychain/ot/OTTriggerEscrowUpdateOperation.h" +#import "keychain/ot/OTUpdateTPHOperation.h" +#import "keychain/ot/OTUpdateTrustedDeviceListOperation.h" +#import "keychain/ot/OTUploadNewCKKSTLKsOperation.h" #import "keychain/ot/OTVouchWithBottleOperation.h" #import "keychain/ot/OTVouchWithRecoveryKeyOperation.h" -#import "keychain/ot/OTEstablishOperation.h" -#import "keychain/ot/OTLocalCKKSResetOperation.h" -#import "keychain/ot/OTUpdateTrustedDeviceListOperation.h" -#import "keychain/ot/OTSOSUpdatePreapprovalsOperation.h" -#import "keychain/ot/OTResetOperation.h" -#import "keychain/ot/OTLocalCuttlefishReset.h" -#import "keychain/ot/OTSetRecoveryKeyOperation.h" -#import "keychain/ot/OTResetCKKSZonesLackingTLKsOperation.h" -#import "keychain/ot/OTUploadNewCKKSTLKsOperation.h" -#import "keychain/ot/OTCuttlefishAccountStateHolder.h" #import "keychain/ot/ObjCImprovements.h" +#import "keychain/ot/OctagonCKKSPeerAdapter.h" +#import "keychain/ot/OctagonCheckTrustStateOperation.h" +#import "keychain/ot/OctagonStateMachine.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" +#import "keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h" #import "keychain/ot/proto/generated_source/OTAccountMetadataClassC.h" -#import "keychain/ot/OTTriggerEscrowUpdateOperation.h" -#import "keychain/ot/OTCheckHealthOperation.h" -#import "keychain/ot/OTEnsureOctagonKeyConsistency.h" -#import "keychain/ot/OTDetermineHSA2AccountStatusOperation.h" -#import "keychain/ckks/CKKSAccountStateTracker.h" -#import "keychain/ckks/CloudKitCategories.h" -#import "keychain/escrowrequest/EscrowRequestServer.h" +#import "keychain/securityd/SOSCloudCircleServer.h" + +#import "utilities/SecFileLocations.h" +#import "utilities/SecTapToRadar.h" #if TARGET_OS_WATCH #import "keychain/otpaird/OTPairingClient.h" #endif /* TARGET_OS_WATCH */ -#import "keychain/ckks/CKKSViewManager.h" -#import "keychain/ckks/CKKSKeychainView.h" -#import "utilities/SecTapToRadar.h" -#import "keychain/categories/NSError+UsefulConstructors.h" -#import -#import NSString* OTCuttlefishContextErrorDomain = @"otcuttlefish"; static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; @@ -105,12 +110,9 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; @interface OTCuttlefishContext () { - NSData* _vouchData; - NSData* _vouchSig; NSString* _bottleID; NSString* _bottleSalt; NSData* _entropy; - NSArray* _preapprovedKeys; NSString* _recoveryKey; CuttlefishResetReason _resetReason; BOOL _skipRateLimitingCheck; @@ -125,21 +127,20 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; @property CKAccountInfo* cloudKitAccountInfo; @property CKKSCondition *cloudKitAccountStateKnown; -@property BOOL getViewsSuccess; - @property CKKSNearFutureScheduler* suggestTLKUploadNotifier; +@property CKKSNearFutureScheduler* requestPolicyCheckNotifier; +@property CKKSNearFutureScheduler* upgradeUserControllableViewsRateLimiter; + +@property OctagonAPSReceiver* apsReceiver; + +// Make writable +@property (nullable) CKKSViewManager* viewManager; // Dependencies (for injection) @property id sosAdapter; @property id octagonAdapter; -@property id deviceAdapter; -@property (readonly) Class apsConnectionClass; @property (readonly) Class escrowRequestClass; -@property (nonatomic) BOOL postedRepairCFU; -@property (nonatomic) BOOL postedEscrowRepairCFU; -@property (nonatomic) BOOL postedRecoveryKeyCFU; - @property (nonatomic) BOOL initialBecomeUntrustedPosted; @end @@ -153,6 +154,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; authKitAdapter:(id)authKitAdapter ckksViewManager:(CKKSViewManager* _Nullable)viewManager lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker accountStateTracker:(id)accountStateTracker deviceInformationAdapter:(id)deviceInformationAdapter apsConnectionClass:(Class)apsConnectionClass @@ -165,14 +167,14 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; _containerName = containerName; _contextID = contextID; + _apsReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:apsConnectionClass]; + [_apsReceiver registerCuttlefishReceiver:self forContainerName:self.containerName]; + _viewManager = viewManager; - _postedRepairCFU = NO; - _postedRecoveryKeyCFU = NO; - _postedEscrowRepairCFU = NO; _initialBecomeUntrustedPosted = NO; - _apsConnectionClass = apsConnectionClass; _launchSequence = [[CKKSLaunchSequence alloc] initWithRocketName:@"com.apple.octagon.launch"]; _queue = dispatch_queue_create("com.apple.security.otcuttlefishcontext", DISPATCH_QUEUE_SERIAL); @@ -190,7 +192,8 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; initialState:OctagonStateInitializing queue:_queue stateEngine:self - lockStateTracker:lockStateTracker]; + lockStateTracker:lockStateTracker + reachabilityTracker:reachabilityTracker]; _sosAdapter = sosAdapter; [_sosAdapter registerForPeerChangeUpdates:self]; @@ -218,10 +221,36 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; secnotice("octagon-ckks", "Adding flag for CKKS TLK upload"); [self.stateMachine handleFlag:OctagonFlagCKKSRequestsTLKUpload]; }]; + + _requestPolicyCheckNotifier = [[CKKSNearFutureScheduler alloc] initWithName:@"octagon-policy-check" + delay:500*NSEC_PER_MSEC + keepProcessAlive:false + dependencyDescriptionCode:0 block:^{ + STRONGIFY(self); + secnotice("octagon-ckks", "Adding flag for CKKS policy check"); + [self.stateMachine handleFlag:OctagonFlagCKKSRequestsPolicyCheck]; + }]; + + _upgradeUserControllableViewsRateLimiter = [[CKKSNearFutureScheduler alloc] initWithName:@"octagon-upgrade-ucv" + initialDelay:0*NSEC_PER_SEC + continuingDelay:10*NSEC_PER_SEC + keepProcessAlive:false + dependencyDescriptionCode:0 + block:^{ + STRONGIFY(self); + OctagonPendingFlag* pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptUserControllableViewStatusUpgrade + conditions:OctagonPendingConditionsDeviceUnlocked | OctagonPendingConditionsNetworkReachable]; + [self.stateMachine handlePendingFlag:pendingFlag]; + }]; } return self; } +- (void)clearCKKSViewManager +{ + self.viewManager = nil; +} + - (void)dealloc { // TODO: how to invalidate this? @@ -399,7 +428,11 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } [self.stateMachine handleFlag:OctagonFlagAccountIsAvailable]; - + + if(OctagonIsOptimizationEnabled()){ + [self.stateMachine handleFlag:OctagonFlagWarmEscrowRecordCache]; + } + if(localError) { if(error) { *error = localError; @@ -410,6 +443,10 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } - (void) moveToCheckTrustedState { + if (self.lockStateTracker) { + [self.lockStateTracker recheck]; + } + CKKSResultOperation* checkTrust = [OctagonStateTransitionOperation named:[NSString stringWithFormat:@"%@", @"check-trust-state"] entering:OctagonStateCheckTrustState]; @@ -433,6 +470,10 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; - (BOOL)accountNoLongerAvailable:(NSError**)error { + if (self.lockStateTracker) { + [self.lockStateTracker recheck]; + } + OctagonStateTransitionOperation* attemptOp = [OctagonStateTransitionOperation named:@"octagon-account-gone" intending:OctagonStateNoAccountDoReset errorState:OctagonStateNoAccountDoReset @@ -444,6 +485,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; metadata.icloudAccountState = OTAccountMetadataClassC_AccountState_NO_ACCOUNT; metadata.altDSID = nil; metadata.trustState = OTAccountMetadataClassC_TrustState_UNKNOWN; + metadata.cdpState = OTAccountMetadataClassC_CDPState_UNKNOWN; return metadata; } error:&localError]; @@ -476,8 +518,65 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return YES; } +- (OTCDPStatus)getCDPStatus:(NSError*__autoreleasing*)error +{ + NSError* localError = nil; + OTAccountMetadataClassC* accountState = [self.accountMetadataStore loadOrCreateAccountMetadata:&localError]; + + if(localError) { + secnotice("octagon-cdp-status", "error fetching account metadata: %@", localError); + if(error) { + *error = localError; + } + + return OTCDPStatusUnknown; + } + + OTCDPStatus status = OTCDPStatusUnknown; + switch(accountState.cdpState) { + case OTAccountMetadataClassC_CDPState_UNKNOWN: + status = OTCDPStatusUnknown; + break; + case OTAccountMetadataClassC_CDPState_DISABLED: + status = OTCDPStatusDisabled; + break; + case OTAccountMetadataClassC_CDPState_ENABLED: + status = OTCDPStatusEnabled; + break; + } + + secnotice("octagon-cdp-status", "current cdp status is: %@", OTCDPStatusToString(status)); + return status; +} + +- (BOOL)setCDPEnabled:(NSError* __autoreleasing *)error +{ + NSError* localError = nil; + [self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.cdpState = OTAccountMetadataClassC_CDPState_ENABLED; + return metadata; + } error:&localError]; + + [self.stateMachine handleFlag:OctagonFlagCDPEnabled]; + + if(localError) { + secerror("octagon-cdp-status: unable to persist CDP enablement: %@", localError); + if(error) { + *error = localError; + } + return NO; + } + + secnotice("octagon-cdp-status", "Successfully set CDP status bit to 'enabled''"); + return YES; +} + - (void)resetOctagonStateMachine { + if (self.lockStateTracker) { + [self.lockStateTracker recheck]; + } + OctagonStateTransitionOperation* op = [OctagonStateTransitionOperation named:@"resetting-state-machine" entering:OctagonStateInitializing]; NSMutableSet* sourceStates = [NSMutableSet setWithArray: OctagonStateMap().allKeys]; @@ -494,11 +593,9 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; - (void)localReset:(nonnull void (^)(NSError * _Nullable))reply { - OTLocalResetOperation* pendingOp = [[OTLocalResetOperation alloc] init:self.containerName - contextID:self.contextID - intendedState:OctagonStateBecomeUntrusted - errorState:OctagonStateError - cuttlefishXPCWrapper:self.cuttlefishXPCWrapper]; + OTLocalResetOperation* pendingOp = [[OTLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateInitializing + errorState:OctagonStateError]; NSMutableSet* sourceStates = [NSMutableSet setWithArray: OctagonStateMap().allKeys]; [self.stateMachine doSimpleStateMachineRPC:@"local-reset" op:pendingOp sourceStates:sourceStates reply:reply]; @@ -507,21 +604,23 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; - (NSDictionary*)establishStatePathDictionary { return @{ - OctagonStateReEnactDeviceList: @{ - OctagonStateReEnactPrepare: @{ - OctagonStateReEnactReadyToEstablish: @{ - OctagonStateEscrowTriggerUpdate: @{ - OctagonStateBecomeReady: @{ - OctagonStateReady: [OctagonStateTransitionPathStep success], + OctagonStateEstablishEnableCDPBit: @{ + OctagonStateReEnactDeviceList: @{ + OctagonStateReEnactPrepare: @{ + OctagonStateReEnactReadyToEstablish: @{ + OctagonStateEscrowTriggerUpdate: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + }, }, - }, - // Error handling extra states: - OctagonStateEstablishCKKSReset: @{ - OctagonStateEstablishAfterCKKSReset: @{ - OctagonStateEscrowTriggerUpdate: @{ - OctagonStateBecomeReady: @{ - OctagonStateReady: [OctagonStateTransitionPathStep success], + // Error handling extra states: + OctagonStateEstablishCKKSReset: @{ + OctagonStateEstablishAfterCKKSReset: @{ + OctagonStateEscrowTriggerUpdate: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + }, }, }, }, @@ -566,12 +665,19 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; - (void)rpcLeaveClique:(nonnull void (^)(NSError * _Nullable))reply { + if ([self.stateMachine isPaused]) { + if ([OctagonNotInCliqueStates() intersectsSet: [NSSet setWithArray: @[[self.stateMachine currentState]]]]) { + secnotice("octagon-leave-clique", "device is not in clique to begin with - returning"); + reply(nil); + return; + } + } + OTLeaveCliqueOperation* op = [[OTLeaveCliqueOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateBecomeUntrusted - errorState:OctagonStateError]; + errorState:OctagonStateCheckTrustState]; - NSSet* sourceStates = [NSSet setWithObject: OctagonStateReady]; - [self.stateMachine doSimpleStateMachineRPC:@"leave-clique" op:op sourceStates:sourceStates reply:reply]; + [self.stateMachine doSimpleStateMachineRPC:@"leave-clique" op:op sourceStates:OctagonInAccountStates() reply:reply]; } - (void)rpcRemoveFriendsInClique:(NSArray*)peerIDs @@ -660,8 +766,6 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; { dispatch_assert_queue(self.queue); - WEAKIFY(self); - [self.launchSequence addEvent:currentState]; // If We're initializing, or there was some recent update to the account state, @@ -694,7 +798,44 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } if([currentState isEqualToString:OctagonStateCloudKitNewlyAvailable]) { - return [self cloudKitAccountNewlyAvailableOperation]; + OctagonFlag* warmEscrowCache = nil; + if([flags _onqueueContains:OctagonFlagWarmEscrowRecordCache] && OctagonIsOptimizationEnabled()) { + [flags _onqueueRemoveFlag:OctagonFlagWarmEscrowRecordCache]; + warmEscrowCache = OctagonFlagWarmEscrowRecordCache; + } + return [self cloudKitAccountNewlyAvailableOperation:warmEscrowCache]; + } + + if([currentState isEqualToString:OctagonStateDetermineCDPState]) { + return [[OTDetermineCDPBitStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateCheckTrustState + errorState:OctagonStateWaitForCDP]; + } + + if([currentState isEqualToString:OctagonStateWaitForCDP]) { + if([flags _onqueueContains:OctagonFlagCDPEnabled]) { + [flags _onqueueRemoveFlag:OctagonFlagCDPEnabled]; + secnotice("octagon", "CDP is newly available!"); + + return [OctagonStateTransitionOperation named:@"cdp_enabled" + entering:OctagonStateDetermineiCloudAccountState]; + + } else if([flags _onqueueContains:OctagonFlagCuttlefishNotification]) { + [flags _onqueueRemoveFlag:OctagonFlagCuttlefishNotification]; + return [OctagonStateTransitionOperation named:@"cdp_enabled_push_received" + entering:OctagonStateWaitForCDPUpdated]; + + } else { + return nil; + } + } + + if([currentState isEqualToString:OctagonStateWaitForCDPUpdated]) { + return [[OTUpdateTPHOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateDetermineCDPState + peerUnknownState:OctagonStateDetermineCDPState + errorState:OctagonStateError + retryFlag:OctagonFlagCuttlefishNotification]; } if([currentState isEqualToString:OctagonStateCheckTrustState]) { @@ -705,12 +846,18 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; #pragma mark --- Octagon Health Check States if([currentState isEqualToString:OctagonStateHSA2HealthCheck]) { return [[OTDetermineHSA2AccountStatusOperation alloc] initWithDependencies:self.operationDependencies - stateIfHSA2:OctagonStateSecurityTrustCheck + stateIfHSA2:OctagonStateCDPHealthCheck stateIfNotHSA2:OctagonStateWaitForHSA2 stateIfNoAccount:OctagonStateNoAccount errorState:OctagonStateError]; } + if([currentState isEqualToString:OctagonStateCDPHealthCheck]) { + return [[OTDetermineCDPBitStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateSecurityTrustCheck + errorState:OctagonStateWaitForCDP]; + } + if([currentState isEqualToString:OctagonStateSecurityTrustCheck]) { return [self evaluateSecdOctagonTrust]; } @@ -749,6 +896,37 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if([currentState isEqualToString:OctagonStateBecomeReady]) { return [self becomeReadyOperation]; } + + if([currentState isEqualToString:OctagonStateRefetchCKKSPolicy]) { + return [[OTFetchViewsOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBecomeReady + errorState:OctagonStateError]; + } + + if([currentState isEqualToString:OctagonStateEnableUserControllableViews]) { + return [[OTModifyUserControllableViewStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedViewStatus:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED + intendedState:OctagonStateBecomeReady + peerMissingState:OctagonStateReadyUpdated + errorState:OctagonStateBecomeReady]; + } + + if([currentState isEqualToString:OctagonStateDisableUserControllableViews]) { + return [[OTModifyUserControllableViewStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedViewStatus:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED + intendedState:OctagonStateBecomeReady + peerMissingState:OctagonStateReadyUpdated + errorState:OctagonStateBecomeReady]; + } + + if([currentState isEqualToString:OctagonStateSetUserControllableViewsToPeerConsensus]) { + // Setting the status to FOLLOWING will either enable or disable the value, depending on our peers. + return [[OTModifyUserControllableViewStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedViewStatus:TPPBPeerStableInfo_UserControllableViewStatus_FOLLOWING + intendedState:OctagonStateBecomeReady + peerMissingState:OctagonStateReadyUpdated + errorState:OctagonStateBecomeReady]; + } if([currentState isEqualToString:OctagonStateNoAccount]) { // We only want to move out of untrusted if something useful has happened! @@ -786,6 +964,17 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } } + if([flags _onqueueContains:OctagonFlagAttemptSOSConsistency]) { + [flags _onqueueRemoveFlag:OctagonFlagAttemptSOSConsistency]; + if(self.sosAdapter.sosEnabled) { + secnotice("octagon", "Attempting SOS upgrade again (due to a consistency notification)"); + return [OctagonStateTransitionOperation named:@"attempt-sos-upgrade" + entering:OctagonStateAttemptSOSUpgrade]; + } else { + secnotice("octagon", "Someone would like us to check SOS consistency, but this platform doesn't support SOS."); + } + } + if([flags _onqueueContains:OctagonFlagCuttlefishNotification]) { [flags _onqueueRemoveFlag:OctagonFlagCuttlefishNotification]; secnotice("octagon", "Updating TPH (while untrusted) due to push"); @@ -797,11 +986,18 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if([flags _onqueueContains:OctagonFlagIDMSLevelChanged]) { [flags _onqueueRemoveFlag:OctagonFlagIDMSLevelChanged]; } + + // We're untrusted; no need for the CDP level flag anymore + if([flags _onqueueContains:OctagonFlagCDPEnabled]) { + secnotice("octagon", "Removing 'CDP enabled' flag"); + [flags _onqueueRemoveFlag:OctagonFlagCDPEnabled]; + } } if([currentState isEqualToString:OctagonStateUntrustedUpdated]) { return [[OTUpdateTPHOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateUntrusted + peerUnknownState:OctagonStateBecomeUntrusted errorState:OctagonStateError retryFlag:OctagonFlagCuttlefishNotification]; } @@ -809,69 +1005,25 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if([currentState isEqualToString:OctagonStateDetermineiCloudAccountState]) { secnotice("octagon", "Determine iCloud account status"); - // TODO replace with OTDetermineHSA2AccountStatusOperation in Octagon: ensure Octagon operations can't occur on SA accounts - return [OctagonStateTransitionOperation named:@"octagon-determine-icloud-state" - intending:OctagonStateNoAccount - errorState:OctagonStateError - withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { - STRONGIFY(self); - - NSError *authKitError = nil; - NSString* primaryAccountAltDSID = [self.authKitAdapter primaryiCloudAccountAltDSID:&authKitError]; - - dispatch_sync(self.queue, ^{ - NSError* error = nil; - - if(primaryAccountAltDSID != nil) { - secnotice("octagon", "iCloud account is present; checking HSA2 status"); - - bool hsa2 = [self.authKitAdapter accountIsHSA2ByAltDSID:primaryAccountAltDSID]; - secnotice("octagon", "HSA2 is %@", hsa2 ? @"enabled" : @"disabled"); - - [self.accountMetadataStore _onqueuePersistAccountChanges:^OTAccountMetadataClassC *(OTAccountMetadataClassC * metadata) { - if(hsa2) { - metadata.icloudAccountState = OTAccountMetadataClassC_AccountState_ACCOUNT_AVAILABLE; - } else { - metadata.icloudAccountState = OTAccountMetadataClassC_AccountState_NO_ACCOUNT; - } - metadata.altDSID = primaryAccountAltDSID; - return metadata; - } error:&error]; - - // If there's an HSA2 account, return to 'initializing' here, as we want to centralize decisions on what to do next - if(hsa2) { - op.nextState = OctagonStateInitializing; - } else { - [self.accountStateTracker setHSA2iCloudAccountStatus:CKKSAccountStatusNoAccount]; - op.nextState = OctagonStateWaitForHSA2; - } - - } else { - secnotice("octagon", "iCloud account is not present: %@", authKitError); - - [self.accountMetadataStore _onqueuePersistAccountChanges:^OTAccountMetadataClassC *(OTAccountMetadataClassC * metadata) { - metadata.icloudAccountState = OTAccountMetadataClassC_AccountState_NO_ACCOUNT; - metadata.altDSID = nil; - return metadata; - } error:&error]; - - op.nextState = OctagonStateNoAccount; - } - - if(error) { - secerror("octagon: unable to save new account state: %@", error); - } - }); - }]; + // If there's an HSA2 account, return to 'initializing' here, as we want to centralize decisions on what to do next + return [[OTDetermineHSA2AccountStatusOperation alloc] initWithDependencies:self.operationDependencies + stateIfHSA2:OctagonStateInitializing + stateIfNotHSA2:OctagonStateWaitForHSA2 + stateIfNoAccount:OctagonStateNoAccount + errorState:OctagonStateError]; } if([currentState isEqualToString:OctagonStateNoAccountDoReset]) { secnotice("octagon", "Attempting local-reset as part of signout"); - return [[OTLocalResetOperation alloc] init:self.containerName - contextID:self.contextID - intendedState:OctagonStateNoAccount - errorState:OctagonStateNoAccount - cuttlefishXPCWrapper:self.cuttlefishXPCWrapper]; + return [[OTLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateNoAccount + errorState:OctagonStateNoAccount]; + } + + if([currentState isEqualToString:OctagonStateLostAccountAuth]) { + return [[OTLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBecomeUntrusted + errorState:OctagonStateBecomeUntrusted]; } if([currentState isEqualToString:OctagonStateEnsureConsistency]) { @@ -887,6 +1039,18 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; entering:OctagonStateBecomeReady]; } + if([currentState isEqualToString:OctagonStateBottlePreloadOctagonKeysInSOS]) { + secnotice("octagon", "Preloading Octagon Keys on the SOS Account"); + if(self.sosAdapter.sosEnabled) { + return [[OTPreloadOctagonKeysOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBecomeReady + errorState:OctagonStateBecomeReady]; + } + // Add further consistency checks here. + return [OctagonStateTransitionOperation named:@"no-preload-octagon-key" + entering:OctagonStateBecomeReady]; + } + if([currentState isEqualToString:OctagonStateEnsureUpdatePreapprovals]) { secnotice("octagon", "SOS is enabled; ensuring preapprovals are correct"); return [[OTSOSUpdatePreapprovalsOperation alloc] initWithDependencies:self.operationDependencies @@ -895,13 +1059,20 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; errorState:OctagonStateBecomeReady]; } + if([currentState isEqualToString:OctagonStateAttemptSOSUpgradeDetermineCDPState]) { + return [[OTDetermineCDPBitStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateAttemptSOSUpgrade + errorState:OctagonStateWaitForCDP]; + } + if([currentState isEqualToString:OctagonStateAttemptSOSUpgrade] && OctagonPerformSOSUpgrade()) { secnotice("octagon", "Investigating SOS status"); return [[OTSOSUpgradeOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateBecomeReady ckksConflictState:OctagonStateSOSUpgradeCKKSReset errorState:OctagonStateBecomeUntrusted - deviceInfo:self.prepareInformation]; + deviceInfo:self.prepareInformation + policyOverride:self.policyOverride]; } else if([currentState isEqualToString:OctagonStateSOSUpgradeCKKSReset]) { return [[OTLocalCKKSResetOperation alloc] initWithDependencies:self.operationDependencies @@ -913,79 +1084,62 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; intendedState:OctagonStateBecomeReady ckksConflictState:OctagonStateBecomeUntrusted errorState:OctagonStateBecomeUntrusted - deviceInfo:self.prepareInformation]; + deviceInfo:self.prepareInformation + policyOverride:self.policyOverride]; } else if([currentState isEqualToString:OctagonStateCreateIdentityForRecoveryKey]) { - OTPrepareOperation* op = [[OTPrepareOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateVouchWithRecoveryKey - errorState:OctagonStateBecomeUntrusted - deviceInfo:[self prepareInformation] - epoch:1]; - return op; + return [[OTPrepareOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateVouchWithRecoveryKey + errorState:OctagonStateBecomeUntrusted + deviceInfo:[self prepareInformation] + policyOverride:self.policyOverride + epoch:1]; - } else if([currentState isEqualToString:OctagonStateInitiatorCreateIdentity]) { - OTPrepareOperation* op = [[OTPrepareOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateInitiatorVouchWithBottle - errorState:OctagonStateBecomeUntrusted - deviceInfo:[self prepareInformation] - epoch:1]; - return op; + } else if([currentState isEqualToString:OctagonStateBottleJoinCreateIdentity]) { + return [[OTPrepareOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBottleJoinVouchWithBottle + errorState:OctagonStateBecomeUntrusted + deviceInfo:[self prepareInformation] + policyOverride:self.policyOverride + epoch:1]; - } else if([currentState isEqualToString:OctagonStateInitiatorVouchWithBottle]) { - OTVouchWithBottleOperation* pendingOp = [[OTVouchWithBottleOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateInitiatorUpdateDeviceList - errorState:OctagonStateBecomeUntrusted - bottleID:_bottleID - entropy:_entropy - bottleSalt:_bottleSalt]; - - CKKSResultOperation* callback = [CKKSResultOperation named:@"vouchWithBottle-callback" - withBlock:^{ - secnotice("otrpc", "Returning a vouch with bottle call: %@, %@ %@", pendingOp.voucher, pendingOp.voucherSig, pendingOp.error); - self->_vouchSig = pendingOp.voucherSig; - self->_vouchData = pendingOp.voucher; - }]; - [callback addDependency:pendingOp]; - [self.operationQueue addOperation: callback]; - - return pendingOp; + } else if([currentState isEqualToString:OctagonStateBottleJoinVouchWithBottle]) { + return [[OTVouchWithBottleOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateInitiatorSetCDPBit + errorState:OctagonStateBecomeUntrusted + bottleID:_bottleID + entropy:_entropy + bottleSalt:_bottleSalt + saveVoucher:YES]; } else if([currentState isEqualToString:OctagonStateVouchWithRecoveryKey]) { - OTVouchWithRecoveryKeyOperation* pendingOp = [[OTVouchWithRecoveryKeyOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateInitiatorUpdateDeviceList - errorState:OctagonStateBecomeUntrusted - recoveryKey:_recoveryKey]; + return [[OTVouchWithRecoveryKeyOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateInitiatorSetCDPBit + errorState:OctagonStateBecomeUntrusted + recoveryKey:_recoveryKey + saveVoucher:YES]; - CKKSResultOperation* callback = [CKKSResultOperation named:@"vouchWithRecoveryKey-callback" - withBlock:^{ - secnotice("otrpc", "Returning a vouch with recovery key call: %@, %@ %@", pendingOp.voucher, pendingOp.voucherSig, pendingOp.error); - self->_vouchSig = pendingOp.voucherSig; - self->_vouchData = pendingOp.voucher; - }]; - [callback addDependency:pendingOp]; - [self.operationQueue addOperation: callback]; - - return pendingOp; + } else if([currentState isEqualToString:OctagonStateInitiatorSetCDPBit]) { + return [[OTSetCDPBitOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateInitiatorUpdateDeviceList + errorState:OctagonStateDetermineCDPState]; } else if([currentState isEqualToString:OctagonStateInitiatorUpdateDeviceList]) { // As part of the 'initiate' flow, we need to update the trusted device list-you're probably on it already OTUpdateTrustedDeviceListOperation* op = [[OTUpdateTrustedDeviceListOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateInitiatorJoin listUpdatesState:OctagonStateInitiatorJoin + authenticationErrorState:OctagonStateLostAccountAuth errorState:OctagonStateBecomeUntrusted retryFlag:nil]; return op; } else if ([currentState isEqualToString:OctagonStateInitiatorJoin]){ - OTJoinWithVoucherOperation* op = [[OTJoinWithVoucherOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateBecomeReady - ckksConflictState:OctagonStateInitiatorJoinCKKSReset - errorState:OctagonStateBecomeUntrusted - voucherData:_vouchData - voucherSig:_vouchSig - preapprovedKeys:_preapprovedKeys]; - return op; + return [[OTJoinWithVoucherOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBottlePreloadOctagonKeysInSOS + ckksConflictState:OctagonStateInitiatorJoinCKKSReset + errorState:OctagonStateBecomeUntrusted]; } else if([currentState isEqualToString:OctagonStateInitiatorJoinCKKSReset]) { return [[OTLocalCKKSResetOperation alloc] initWithDependencies:self.operationDependencies @@ -994,12 +1148,9 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } else if ([currentState isEqualToString:OctagonStateInitiatorJoinAfterCKKSReset]){ return [[OTJoinWithVoucherOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateBecomeReady + intendedState:OctagonStateBottlePreloadOctagonKeysInSOS ckksConflictState:OctagonStateBecomeUntrusted - errorState:OctagonStateBecomeUntrusted - voucherData:_vouchData - voucherSig:_vouchSig - preapprovedKeys:_preapprovedKeys]; + errorState:OctagonStateBecomeUntrusted]; } else if([currentState isEqualToString:OctagonStateResetBecomeUntrusted]) { return [self becomeUntrustedOperation:OctagonStateResetAndEstablish]; @@ -1014,22 +1165,30 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } else if([currentState isEqualToString:OctagonStateResetAnyMissingTLKCKKSViews]) { return [[OTResetCKKSZonesLackingTLKsOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateReEnactDeviceList - errorState:OctagonStateError]; + intendedState:OctagonStateEstablishEnableCDPBit + errorState:OctagonStateError]; + + } else if([currentState isEqualToString:OctagonStateEstablishEnableCDPBit]) { + return [[OTSetCDPBitOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateReEnactDeviceList + errorState:OctagonStateError]; } else if([currentState isEqualToString:OctagonStateReEnactDeviceList]) { return [[OTUpdateTrustedDeviceListOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateReEnactPrepare listUpdatesState:OctagonStateReEnactPrepare - errorState:OctagonStateError + authenticationErrorState:OctagonStateLostAccountAuth + errorState:OctagonStateBecomeUntrusted retryFlag:nil]; } else if([currentState isEqualToString:OctagonStateReEnactPrepare]) { + // Octagon: use epoch transmitted across pairing channel // Note: Resetting the account returns epoch to 0. return [[OTPrepareOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateReEnactReadyToEstablish errorState:OctagonStateError deviceInfo:[self prepareInformation] + policyOverride:self.policyOverride epoch:0]; } else if([currentState isEqualToString:OctagonStateReEnactReadyToEstablish]) { @@ -1051,11 +1210,26 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; errorState:OctagonStateBecomeUntrusted]; } else if ([currentState isEqualToString:OctagonStateEscrowTriggerUpdate]){ - return [[OTTriggerEscrowUpdateOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateBecomeReady errorState:OctagonStateError]; + } else if ([currentState isEqualToString:OctagonStateHealthCheckLeaveClique]) { + return [[OTLeaveCliqueOperation alloc] initWithDependencies: self.operationDependencies + intendedState: OctagonStateBecomeUntrusted + errorState: OctagonStateBecomeUntrusted]; + + } else if([currentState isEqualToString:OctagonStateWaitForClassCUnlock]) { + if([flags _onqueueContains:OctagonFlagUnlocked]) { + [flags _onqueueRemoveFlag:OctagonFlagUnlocked]; + return [OctagonStateTransitionOperation named:[NSString stringWithFormat:@"%@", @"initializing-after-initial-unlock"] + entering:OctagonStateInitializing]; + } + + [pendingFlagHandler _onqueueHandlePendingFlag:[[OctagonPendingFlag alloc] initWithFlag:OctagonFlagUnlocked + conditions:OctagonPendingConditionsDeviceUnlocked]]; + return nil; + } else if([currentState isEqualToString: OctagonStateWaitForUnlock]) { if([flags _onqueueContains:OctagonFlagUnlocked]) { [flags _onqueueRemoveFlag:OctagonFlagUnlocked]; @@ -1081,6 +1255,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return [[OTUploadNewCKKSTLKsOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateReady ckksConflictState:OctagonStateAssistCKKSTLKUploadCKKSReset + peerMissingState:OctagonStateReadyUpdated errorState:OctagonStateReady]; } else if([currentState isEqualToString:OctagonStateAssistCKKSTLKUploadCKKSReset]) { @@ -1093,20 +1268,51 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return [[OTUploadNewCKKSTLKsOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateReady ckksConflictState:OctagonStateReady + peerMissingState:OctagonStateReadyUpdated errorState:OctagonStateReady]; } else if([currentState isEqualToString:OctagonStateReady]) { + if([flags _onqueueContains:OctagonFlagCuttlefishNotification]) { + [flags _onqueueRemoveFlag:OctagonFlagCuttlefishNotification]; + secnotice("octagon", "Updating TPH (while ready) due to push"); + return [OctagonStateTransitionOperation named:@"octagon-update" + entering:OctagonStateReadyUpdated]; + } + if([flags _onqueueContains:OctagonFlagCKKSRequestsTLKUpload]) { [flags _onqueueRemoveFlag:OctagonFlagCKKSRequestsTLKUpload]; return [OctagonStateTransitionOperation named:@"ckks-assist" entering:OctagonStateAssistCKKSTLKUpload]; } - if([flags _onqueueContains:OctagonFlagCuttlefishNotification]) { - [flags _onqueueRemoveFlag:OctagonFlagCuttlefishNotification]; - secnotice("octagon", "Updating TPH (while ready) due to push"); - return [OctagonStateTransitionOperation named:@"octagon-update" - entering:OctagonStateReadyUpdated]; + if([flags _onqueueContains:OctagonFlagAttemptBottleTLKExtraction]) { + [flags _onqueueRemoveFlag:OctagonFlagAttemptBottleTLKExtraction]; + if(_bottleID && _entropy && _bottleSalt) { + // Reuse the vouch-with-bottle operation. That'll make us a new voucher, but as a side effect, it will extract TLKs. + return [[OTVouchWithBottleOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBecomeReady + errorState:OctagonStateBecomeReady + bottleID:_bottleID + entropy:_entropy + bottleSalt:_bottleSalt + saveVoucher:NO]; + } else { + secnotice("octagon", "Received an suggestion to retry TLK extraction via bottle, but have no entropy stashed"); + } + } + + if([flags _onqueueContains:OctagonFlagAttemptRecoveryKeyTLKExtraction]) { + [flags _onqueueRemoveFlag:OctagonFlagAttemptRecoveryKeyTLKExtraction]; + if(_recoveryKey) { + // Reuse the vouch-with-rk operation. That'll make us a new voucher, but as a side effect, it will extract TLKs. + return [[OTVouchWithRecoveryKeyOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBecomeReady + errorState:OctagonStateBecomeReady + recoveryKey:_recoveryKey + saveVoucher:NO]; + } else { + secnotice("octagon", "Received an suggestion to retry TLK extraction via RK, but have no recovery key stashed"); + } } if([flags _onqueueContains:OctagonFlagFetchAuthKitMachineIDList]) { @@ -1118,6 +1324,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return [[OTUpdateTrustedDeviceListOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateReady listUpdatesState:OctagonStateReadyUpdated + authenticationErrorState:OctagonStateLostAccountAuth errorState:OctagonStateReady retryFlag:OctagonFlagFetchAuthKitMachineIDList]; } @@ -1144,6 +1351,27 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } } + if([flags _onqueueContains:OctagonFlagAttemptUserControllableViewStatusUpgrade]) { + [flags _onqueueRemoveFlag:OctagonFlagAttemptUserControllableViewStatusUpgrade]; + secnotice("octagon", "Attempting user-view control upgrade"); + return [OctagonStateTransitionOperation named:@"attempt-user-view-upgrade" + entering:OctagonStateSetUserControllableViewsToPeerConsensus]; + } + + if([flags _onqueueContains:OctagonFlagCKKSRequestsPolicyCheck]) { + [flags _onqueueRemoveFlag:OctagonFlagCKKSRequestsPolicyCheck]; + secnotice("octagon", "Updating CKKS policy"); + return [OctagonStateTransitionOperation named:@"ckks-policy-update" + entering:OctagonStateReadyUpdated]; + } + + if([flags _onqueueContains:OctagonFlagCKKSViewSetChanged]) { + // We want to tell CKKS that we're trusted again. + [flags _onqueueRemoveFlag:OctagonFlagCKKSViewSetChanged]; + return [OctagonStateTransitionOperation named:@"ckks-update-trust" + entering:OctagonStateBecomeReady]; + } + if([flags _onqueueContains:OctagonFlagAccountIsAvailable]) { // We're in ready--we already know the account is available secnotice("octagon", "Removing 'account is available' flag"); @@ -1156,17 +1384,26 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; [flags _onqueueRemoveFlag:OctagonFlagIDMSLevelChanged]; } - secnotice("octagon", "Entering state ready"); + // We're ready; no need for the CDP level flag anymore + if([flags _onqueueContains:OctagonFlagCDPEnabled]) { + secnotice("octagon", "Removing 'CDP enabled' flag"); + [flags _onqueueRemoveFlag:OctagonFlagCDPEnabled]; + } + [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:OctagonAnalyticsLastKeystateReady]; [self.launchSequence launch]; return nil; } else if([currentState isEqualToString:OctagonStateReadyUpdated]) { return [[OTUpdateTPHOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateReady + peerUnknownState:OctagonStateBecomeUntrusted errorState:OctagonStateError retryFlag:OctagonFlagCuttlefishNotification]; - } else if ([currentState isEqualToString:OctagonStateError]) { + } + + if ([currentState isEqualToString:OctagonStateError]) { + return nil; } return nil; @@ -1184,7 +1421,9 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; OTAccountMetadataClassC* account = [self.accountMetadataStore loadOrCreateAccountMetadata:&localError]; if(localError && [self.lockStateTracker isLockedError:localError]){ secnotice("octagon", "Device is locked! pending initialization on unlock"); - op.nextState = OctagonStateWaitForUnlock; + // Since we can't load a class C item, we go to a different waitforunlock state. + // That way, we'll be less likely for an RPC to break us. + op.nextState = OctagonStateWaitForClassCUnlock; return; } @@ -1201,6 +1440,20 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; // This seems an odd place to do this, but CKKS currently also tracks the CloudKit account state. // Since we think we have an HSA2 account, let CKKS figure out its own CloudKit state secnotice("octagon-ckks", "Initializing CKKS views"); + [self.cuttlefishXPCWrapper fetchCurrentPolicyWithContainer:self.containerName + context:self.contextID + modelIDOverride:self.deviceAdapter.modelID + reply:^(TPSyncingPolicy * _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, + NSError * _Nullable policyError) { + if(!syncingPolicy || policyError) { + secnotice("octagon-ckks", "Unable to fetch initial syncing policy: %@", policyError); + } else { + secnotice("octagon-ckks", "Fetched initial syncing policy: %@", syncingPolicy); + [self.viewManager setCurrentSyncingPolicy:syncingPolicy]; + } + }]; + [self.viewManager createViews]; [self.viewManager beginCloudKitOperationOfAllViews]; @@ -1237,7 +1490,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } else { secnotice("octagon-health", "trust state (%@). checking in with TPH", [account trustStateAsString:account.trustState]); - op.nextState = [self repairAccountIfTrustedByTPHWithIntededState:OctagonStateTPHTrustCheck errorState:OctagonStatePostRepairCFU]; + op.nextState = [self repairAccountIfTrustedByTPHWithIntendedState:OctagonStateTPHTrustCheck]; } }]; } @@ -1248,7 +1501,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; intending:OctagonStateCuttlefishTrustCheck errorState:OctagonStatePostRepairCFU withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { - [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, NSError *trustFromTPHError) { + [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, BOOL isLocked, NSError *trustFromTPHError) { [[CKKSAnalytics logger] logResultForEvent:OctagonEventTPHHealthCheckStatus hardFailure:false result:trustFromTPHError]; if(trustFromTPHError) { @@ -1256,7 +1509,10 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; op.error = trustFromTPHError; op.nextState = OctagonStateError; } else { - if(hasIdentity == NO) { + if (isLocked == YES) { + op.nextState = OctagonStateWaitForUnlock; + secnotice("octagon-health", "TPH says device is locked!"); + } else if (hasIdentity == NO) { op.nextState = OctagonStateUntrusted; } else if(hasIdentity == YES && status == CliqueStatusIn){ secnotice("octagon-health", "TPH says we're trusted and in"); @@ -1284,8 +1540,8 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; CKKSResultOperation* callback = [CKKSResultOperation named:@"rpcHealthCheck" withBlock:^{ - secnotice("octagon-health", "Returning from cuttlefish trust check call: postRepairCFU(%d), postEscrowCFU(%d), resetOctagon(%d)", - op.postRepairCFU, op.postEscrowCFU, op.resetOctagon); + secnotice("octagon-health", "Returning from cuttlefish trust check call: postRepairCFU(%d), postEscrowCFU(%d), resetOctagon(%d), leaveTrust(%d)", + op.postRepairCFU, op.postEscrowCFU, op.resetOctagon, op.leaveTrust); if(op.postRepairCFU) { secnotice("octagon-health", "Posting Repair CFU"); NSError* postRepairCFUError = nil; @@ -1305,14 +1561,22 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if(shouldPost) { secnotice("octagon-health", "Posting Escrow CFU"); NSError* postEscrowCFUError = nil; - [self postConfirmPasscodeCFU:&postEscrowCFUError]; - if(postEscrowCFUError) { + BOOL ret = [self postConfirmPasscodeCFU:&postEscrowCFUError]; + if(!ret) { op.error = postEscrowCFUError; } } else { secnotice("octagon-health", "Not posting confirm passcode CFU, already pending a prerecord upload"); } + } + if(op.leaveTrust){ + secnotice("octagon-health", "Leaving Octagon and SOS trust"); + NSError* leaveError = nil; + if(![self leaveTrust:&leaveError]) { + op.error = leaveError; + } + } }]; [callback addDependency:op]; [self.operationQueue addOperation: callback]; @@ -1325,31 +1589,54 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; intending:OctagonStateUntrusted errorState:OctagonStateError withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { + __block BOOL deviceIsLocked = NO; [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, + BOOL isLocked, NSError * _Nullable postError) { if(postError) { secerror("ocagon-health: failed to post repair cfu via state machine: %@", postError); + } else if (isLocked) { + deviceIsLocked = isLocked; + secnotice("octagon-health", "device is locked, not posting cfu"); } else { secnotice("octagon-health", "posted repair cfu via state machine"); } }]; - op.nextState = OctagonStateUntrusted; + if (deviceIsLocked == YES) { + op.nextState = OctagonStateWaitForUnlock; + } else { + op.nextState = OctagonStateUntrusted; + } }]; } -- (CKKSResultOperation* _Nullable)cloudKitAccountNewlyAvailableOperation +- (CKKSResultOperation* _Nullable)cloudKitAccountNewlyAvailableOperation:(OctagonFlag*)warmEscrowCache { WEAKIFY(self); + return [OctagonStateTransitionOperation named:@"octagon-icloud-account-available" - intending:OctagonStateCheckTrustState + intending:OctagonStateDetermineCDPState errorState:OctagonStateError withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { STRONGIFY(self); - // Register with APS, but don't bother to wait until it's complete. secnotice("octagon", "iCloud sign in occurred. Attemping to register with APS..."); - + // Check if escrow fetch flag is set to warm up the escrow cache + if(warmEscrowCache != nil && OctagonIsOptimizationEnabled()) { + secnotice("octagon-warm-escrowcache", "Beginning fetching escrow records to warm up the escrow cache in TPH"); + dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{ + STRONGIFY(self); + [self rpcFetchAllViableEscrowRecords:NO reply:^(NSArray *records, NSError *error) { + if(error){ + secerror("octagon-warm-escrowcache: failed to fetch escrow records, %@", error); + } else { + secnotice("octagon-warm-escrowcache", "Successfully fetched escrow records"); + } + }]; + }); + } + // Register with APS, but don't bother to wait until it's complete. CKContainer* ckContainer = [CKContainer containerWithIdentifier:self.containerName]; [ckContainer serverPreferredPushEnvironmentWithCompletionHandler: ^(NSString *apsPushEnvString, NSError *error) { STRONGIFY(self); @@ -1364,10 +1651,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } else { secnotice("octagonpush", "Registering for environment '%@'", apsPushEnvString); - OctagonAPSReceiver* aps = [OctagonAPSReceiver receiverForEnvironment:apsPushEnvString - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:self.apsConnectionClass]; - [aps registerCuttlefishReceiver:self forContainerName:self.containerName]; + [self.apsReceiver registerForEnvironment:apsPushEnvString]; } }]; @@ -1375,12 +1659,12 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; }]; } -- (OctagonState*) repairAccountIfTrustedByTPHWithIntededState:(OctagonState*)intendedState errorState:(OctagonState*)errorState +- (OctagonState*) repairAccountIfTrustedByTPHWithIntendedState:(OctagonState*)intendedState { __block OctagonState* nextState = intendedState; //let's check in with TPH real quick to make sure it agrees with our local assessment - secnotice("octagon-health", "repairAccountIfTrustedByTPHWithIntededState: calling into TPH for trust status"); + secnotice("octagon-health", "repairAccountIfTrustedByTPHWithIntendedState: calling into TPH for trust status"); OTOperationConfiguration *config = [[OTOperationConfiguration alloc]init]; @@ -1388,9 +1672,10 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; NSString* egoPeerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable error) { BOOL hasIdentity = egoPeerID != nil; - secnotice("octagon-health", "repairAccountIfTrustedByTPHWithIntededState status: %ld, peerID: %@, isExcluded: %d error: %@", (long)status, egoPeerID, isExcluded, error); + secnotice("octagon-health", "repairAccountIfTrustedByTPHWithIntendedState status: %ld, peerID: %@, isExcluded: %d error: %@", (long)status, egoPeerID, isExcluded, error); if (error) { secnotice("octagon-health", "got an error from tph, returning to become_ready state: %@", error); @@ -1398,68 +1683,39 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return; } + if (isLocked) { + secnotice("octagon-health", "device is locked"); + nextState = OctagonStateWaitForUnlock; + return; + } + if(OctagonAuthoritativeTrustIsEnabled() && hasIdentity && status == CliqueStatusIn) { - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - [self rpcStatus:^(NSDictionary *dump, NSError *dumpError) { - if(dumpError) { - secerror("octagon-health: error fetching ego peer id!: %@", dumpError); - nextState = errorState; - } else { - NSDictionary* egoInformation = dump[@"self"]; - NSString* peerID = egoInformation[@"peerID"]; - NSError* persistError = nil; - BOOL persisted = [self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { - metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; - metadata.icloudAccountState = OTAccountMetadataClassC_AccountState_ACCOUNT_AVAILABLE; - metadata.peerID = peerID; - return metadata; - } error:&persistError]; - if(!persisted || persistError) { - secerror("octagon-health: couldn't persist results: %@", persistError); - nextState = errorState; - } else { - secnotice("octagon-health", "added trusted identity to account metadata"); - nextState = intendedState; - } - } - dispatch_semaphore_signal(sema); - }]; - if (0 != dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 10))) { - secerror("octagon: Timed out checking trust status"); + secnotice("octagon-health", "TPH believes we're trusted, accepting ego peerID as %@", egoPeerID); + + NSError* persistError = nil; + BOOL persisted = [self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; + metadata.peerID = egoPeerID; + return metadata; + } error:&persistError]; + if(!persisted || persistError) { + secerror("octagon-health: couldn't persist results: %@", persistError); + nextState = OctagonStateError; + } else { + secnotice("octagon-health", "added trusted identity to account metadata"); + nextState = intendedState; } - } else if (OctagonAuthoritativeTrustIsEnabled() && (self.postedRepairCFU == NO) && hasIdentity && status != CliqueStatusIn){ - nextState = errorState; + + } else if (OctagonAuthoritativeTrustIsEnabled() && hasIdentity && status != CliqueStatusIn){ + secnotice("octagon-health", "TPH believes we're not trusted, requesting CFU post"); + nextState = OctagonStatePostRepairCFU; } }]; return nextState; } -- (BOOL) didDeviceAttemptToJoinOctagon:(NSError**)error -{ - NSError* fetchAttemptError = nil; - OTAccountMetadataClassC_AttemptedAJoinState attemptedAJoin = [self.accountMetadataStore fetchPersistedJoinAttempt:&fetchAttemptError]; - if(fetchAttemptError) { - secerror("octagon: failed to fetch data indicating device attempted to join octagon, assuming it did: %@", fetchAttemptError); - if(error){ - *error = fetchAttemptError; - } - return YES; - } - BOOL attempted = YES; - switch (attemptedAJoin) { - case OTAccountMetadataClassC_AttemptedAJoinState_NOTATTEMPTED: - attempted = NO; - break; - case OTAccountMetadataClassC_AttemptedAJoinState_ATTEMPTED: - case OTAccountMetadataClassC_AttemptedAJoinState_UNKNOWN: - default: - break; - } - return attempted; -} - -- (void)checkTrustStatusAndPostRepairCFUIfNecessary:(void (^ _Nullable)(CliqueStatus status, BOOL posted, BOOL hasIdentity, NSError * _Nullable error))reply +- (void)checkTrustStatusAndPostRepairCFUIfNecessary:(void (^ _Nullable)(CliqueStatus status, BOOL posted, BOOL hasIdentity, BOOL isLocked, NSError * _Nullable error))reply { WEAKIFY(self); OTOperationConfiguration *configuration = [[OTOperationConfiguration alloc] init]; @@ -1467,6 +1723,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; NSString* _Nullable egoPeerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable error) { STRONGIFY(self); @@ -1474,7 +1731,13 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; BOOL hasIdentity = egoPeerID != nil; if (error && error.code != errSecInteractionNotAllowed) { - reply(status, NO, hasIdentity, error); + reply(status, NO, hasIdentity, isLocked, error); + return; + } + + if (isLocked) { + secnotice("octagon", "device is locked; not posting CFU"); + reply(status, NO, hasIdentity, isLocked, error); return; } @@ -1497,7 +1760,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } if(!phonePeerPresent) { secnotice("octagon", "No iOS peers in account; not posting CFU"); - reply(status, NO, hasIdentity, nil); + reply(status, NO, hasIdentity, isLocked, nil); return; } #endif @@ -1505,27 +1768,48 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; // On platforms with SOS, we only want to post a CFU if we've attempted to join at least once. // This prevents us from posting a CFU, then performing an SOS upgrade and succeeding. if(self.sosAdapter.sosEnabled) { - NSError* fetchAttemptError = nil; - BOOL attemptedToJoin = [self didDeviceAttemptToJoinOctagon:&fetchAttemptError]; - if(fetchAttemptError){ - secerror("octagon: failed to retrieve joining attempt information: %@", fetchAttemptError); - attemptedToJoin = YES; - } + NSError* fetchError = nil; + OTAccountMetadataClassC* accountState = [self.accountMetadataStore loadOrCreateAccountMetadata:&fetchError]; - if(!attemptedToJoin) { - secnotice("octagon", "SOS is enabled and we haven't attempted to join; not posting CFU"); - reply(status, NO, hasIdentity, nil); - return; + if(!accountState || fetchError){ + secerror("octagon: failed to retrieve joining attempt information: %@", fetchError); + // fall through to below: posting the CFU is better than a false negative + + } else if(accountState.attemptedJoin == OTAccountMetadataClassC_AttemptedAJoinState_ATTEMPTED) { + // Normal flow, fall through to below + } else { + // Triple-check with SOS: if it's in a bad state, post the CFU anyway + secnotice("octagon", "SOS is enabled and we haven't attempted to join; checking with SOS"); + + NSError* circleError = nil; + SOSCCStatus sosStatus = [self.sosAdapter circleStatus:&circleError]; + + if(circleError && [circleError.domain isEqualToString:(__bridge NSString*)kSOSErrorDomain] && circleError.code == kSOSErrorNotReady) { + secnotice("octagon", "SOS is not ready, not posting CFU until it becomes so"); + reply(status, NO, hasIdentity, isLocked, nil); + return; + + } else if(circleError) { + // Any other error probably indicates that there is some circle, but we're not in it + secnotice("octagon", "SOS is in an unknown error state, posting CFU: %@", circleError); + + } else if(sosStatus == kSOSCCInCircle) { + secnotice("octagon", "SOS is InCircle, not posting CFU"); + reply(status, NO, hasIdentity, isLocked, nil); + return; + } else { + secnotice("octagon", "SOS is %@, posting CFU", (__bridge NSString*)SOSCCGetStatusDescription(sosStatus)); + } } } if(OctagonAuthoritativeTrustIsEnabled() && (status == CliqueStatusNotIn || status == CliqueStatusAbsent || isExcluded)) { NSError* localError = nil; BOOL posted = [self postRepairCFU:&localError]; - reply(status, posted, hasIdentity, localError); + reply(status, posted, hasIdentity, isLocked, localError); return; } - reply(status, NO, hasIdentity, nil); + reply(status, NO, hasIdentity, isLocked, nil); return; }]; } @@ -1565,18 +1849,31 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; STRONGIFY(self); NSError* localError = nil; - [self.accountStateTracker triggerOctagonStatusFetch]; + // During testing, don't kick this off until it's needed + if([self.contextID isEqualToString:OTDefaultContext]) { + [self.accountStateTracker triggerOctagonStatusFetch]; + } - [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, NSError * _Nullable postError) { + __block BOOL deviceIsLocked = NO; + [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, BOOL isLocked, NSError * _Nullable postError) { [[CKKSAnalytics logger] logResultForEvent:OctagonEventCheckTrustForCFU hardFailure:false result:postError]; if(postError){ secerror("octagon: cfu failed to post"); + } else if (isLocked == YES) { + deviceIsLocked = isLocked; + secerror("octagon: device is locked, not posting cfu"); } else { secnotice("octagon", "clique status: %@, posted cfu: %d", OTCliqueStatusToString(status), !!posted); } }]; + if (deviceIsLocked == YES) { + secnotice("octagon", "device is locked, state moving to wait for unlock"); + op.nextState = OctagonStateWaitForUnlock; + return; + } + [self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { metadata.trustState = OTAccountMetadataClassC_TrustState_UNTRUSTED; return metadata; @@ -1595,6 +1892,15 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; [view endTrustedOperation]; } + // We are no longer in a CKKS4All world. Tell SOS! + if(self.sosAdapter.sosEnabled) { + NSError* soserror = nil; + [self.sosAdapter updateCKKS4AllStatus:NO error:&soserror]; + if(soserror) { + secnotice("octagon-ckks", "Unable to disable the CKKS4All status in SOS: %@", soserror); + } + } + /* * Initial notification that we let the world know that trust is up and doing something */ @@ -1616,59 +1922,108 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { STRONGIFY(self); - // Note: we don't modify the account metadata store here; that will have been done - // by a join or upgrade operation, possibly long ago + if([self.contextID isEqualToString:OTDefaultContext]) { + [self.accountStateTracker triggerOctagonStatusFetch]; + } - [self.accountStateTracker triggerOctagonStatusFetch]; + // Note: we don't modify the account metadata trust state; that will have been done + // by a join or upgrade operation, possibly long ago - NSError* localError = nil; - NSString* peerID = [self.accountMetadataStore getEgoPeerID:&localError]; - if(!peerID || localError) { - secerror("octagon-ckks: No peer ID to pass to CKKS. Syncing will be disabled."); - } else { - OctagonCKKSPeerAdapter* octagonAdapter = [[OctagonCKKSPeerAdapter alloc] initWithPeerID:peerID operationDependencies:[self operationDependencies]]; + // but, we do set the 'attempted join' bit, just in case the device joined before we started setting this bit - // This octagon adapter must be able to load the self peer keys, or we're in trouble. - NSError* egoPeerKeysError = nil; - CKKSSelves* selves = [octagonAdapter fetchSelfPeers:&egoPeerKeysError]; - if(!selves || egoPeerKeysError) { - secerror("octagon-ckks: Unable to fetch self peers for %@: %@", octagonAdapter, egoPeerKeysError); + // Also, ensure that the CKKS policy is correctly present and set in the view manager + __block NSString* peerID = nil; + NSError* localError = nil; - if([self.lockStateTracker isLockedError:egoPeerKeysError]) { - secnotice("octagon-ckks", "Waiting for device unlock to proceed"); - op.nextState = OctagonStateWaitForUnlock; - } else { - secnotice("octagon-ckks", "Error is scary; becoming untrusted"); - op.nextState = OctagonStateBecomeUntrusted; - } - return; - } + __block TPSyncingPolicy* policy = nil; - // stash a reference to the adapter so we can provided updates later - self.octagonAdapter = octagonAdapter; + [self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + peerID = metadata.peerID; - // Start all our CKKS views! - for (id key in self.viewManager.views) { - CKKSKeychainView* view = self.viewManager.views[key]; - secnotice("octagon-ckks", "Informing CKKS view '%@' of trusted operation with self peer %@", view.zoneName, peerID); + policy = metadata.hasSyncingPolicy ? [metadata getTPSyncingPolicy] : nil; - NSArray>* peerProviders = nil; + if(metadata.attemptedJoin == OTAccountMetadataClassC_AttemptedAJoinState_ATTEMPTED) { + return nil; + } + metadata.attemptedJoin = OTAccountMetadataClassC_AttemptedAJoinState_ATTEMPTED; + return metadata; + } error:&localError]; - if(self.sosAdapter.sosEnabled) { - peerProviders = @[self.octagonAdapter, self.sosAdapter]; + if(!peerID || localError) { + secerror("octagon-ckks: No peer ID to pass to CKKS. Syncing will be disabled."); + } else if(!policy) { + secerror("octagon-ckks: No memoized CKKS policy, re-fetching"); + op.nextState = OctagonStateRefetchCKKSPolicy; + return; - } else { - peerProviders = @[self.octagonAdapter]; - } + } else { + if(policy.syncUserControllableViews == TPPBPeerStableInfo_UserControllableViewStatus_UNKNOWN) { + secnotice("octagon-ckks", "Memoized CKKS policy has no opinion of user-controllable view status"); + // Suggest the update, whenever possible + [self.upgradeUserControllableViewsRateLimiter trigger]; - [view beginTrustedOperation:peerProviders - suggestTLKUpload:self.suggestTLKUploadNotifier]; - } - } - [self notifyTrustChanged:OTAccountMetadataClassC_TrustState_TRUSTED]; + } else { + // We are now in a CKKS4All world. Tell SOS! + if(self.sosAdapter.sosEnabled) { + NSError* soserror = nil; + [self.sosAdapter updateCKKS4AllStatus:YES error:&soserror]; + if(soserror) { + secnotice("octagon-ckks", "Unable to enable the CKKS4All status in SOS: %@", soserror); + } + } + } - op.nextState = op.intendedState; - }]; + secnotice("octagon-ckks", "Initializing CKKS views with policy %@: %@", policy, policy.viewList); + + [self.viewManager setCurrentSyncingPolicy:policy]; + + OctagonCKKSPeerAdapter* octagonAdapter = [[OctagonCKKSPeerAdapter alloc] initWithPeerID:peerID + containerName:self.containerName + contextID:self.contextID + cuttlefishXPC:self.cuttlefishXPCWrapper]; + + // This octagon adapter must be able to load the self peer keys, or we're in trouble. + NSError* egoPeerKeysError = nil; + CKKSSelves* selves = [octagonAdapter fetchSelfPeers:&egoPeerKeysError]; + if(!selves || egoPeerKeysError) { + secerror("octagon-ckks: Unable to fetch self peers for %@: %@", octagonAdapter, egoPeerKeysError); + + if([self.lockStateTracker isLockedError:egoPeerKeysError]) { + secnotice("octagon-ckks", "Waiting for device unlock to proceed"); + op.nextState = OctagonStateWaitForUnlock; + } else { + secnotice("octagon-ckks", "Error is scary; becoming untrusted"); + op.nextState = OctagonStateBecomeUntrusted; + } + return; + } + + // stash a reference to the adapter so we can provide updates later + self.octagonAdapter = octagonAdapter; + + // Start all our CKKS views! + for (id key in self.viewManager.views) { + CKKSKeychainView* view = self.viewManager.views[key]; + secnotice("octagon-ckks", "Informing CKKS view '%@' of trusted operation with self peer %@", view.zoneName, peerID); + + NSArray>* peerProviders = nil; + + if(self.sosAdapter.sosEnabled) { + peerProviders = @[self.octagonAdapter, self.sosAdapter]; + + } else { + peerProviders = @[self.octagonAdapter]; + } + + [view beginTrustedOperation:peerProviders + suggestTLKUpload:self.suggestTLKUploadNotifier + requestPolicyCheck:self.requestPolicyCheckNotifier]; + } + } + [self notifyTrustChanged:OTAccountMetadataClassC_TrustState_TRUSTED]; + + op.nextState = op.intendedState; + }]; } #pragma mark --- Utilities to run at times @@ -1713,7 +2068,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } if (ckDeviceId) { NSString *selfDeviceID = self.viewManager.accountTracker.ckdeviceID; - if (![selfDeviceID isEqualToString:serialNumber]) { + if (serialNumber == nil || ![selfDeviceID isEqualToString:serialNumber]) { secnotice("octagon", "TTR request not for me (deviceId)"); return; } @@ -1744,7 +2099,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; - (void)notifyContainerChangeWithUserInfo:(NSDictionary*)userInfo { - secerror("OTCuttlefishContext: received a cuttlefish push notification (%@): %@", + secnotice("octagonpush", "received a cuttlefish push notification (%@): %@", self.containerName, userInfo); NSDictionary *cfDictionary = userInfo[@"cf"]; @@ -1837,7 +2192,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if(accountMetadata.lastHealthCheckup == 0) { return nil; } - return [[NSDate alloc] initWithTimeIntervalSince1970: accountMetadata.lastHealthCheckup]; + return [[NSDate alloc] initWithTimeIntervalSince1970: ((NSTimeInterval)accountMetadata.lastHealthCheckup) / 1000.0]; } - (void)requestTrustedDeviceListRefresh @@ -1924,6 +2279,21 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; haveAccount = false; } }); + + if(!haveAccount) { + // Right after account sign-in, it's possible that the CK account exists, but that we just haven't learned about + // it yet, and still have the 'no account' state cached. So, let's check in... + secnotice("octagon-ck", "No CK account present. Attempting to refetch CK account status..."); + if(![self.accountStateTracker notifyCKAccountStatusChangeAndWait:timeout]) { + secnotice("octagon-ck", "Fetching new CK account status did not complete in time"); + } + + // After the above call finishes, we should have a fresh value in self.cloudKitAccountInfo + dispatch_sync(self.queue, ^{ + haveAccount = self.cloudKitAccountInfo.accountStatus == CKKSAccountStatusAvailable; + }); + secnotice("octagon-ck", "After refetch, CK account status is %@", haveAccount ? @"present" : @"missing"); + } return haveAccount ? CKKSAccountStatusAvailable : CKKSAccountStatusNoAccount; } @@ -1952,13 +2322,18 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } secnotice("otrpc", "Preparing identity as applicant"); + + if (self.lockStateTracker) { + [self.lockStateTracker recheck]; + } + OTPrepareOperation* pendingOp = [[OTPrepareOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateInitiatorAwaitingVoucher errorState:OctagonStateBecomeUntrusted deviceInfo:[self prepareInformation] + policyOverride:self.policyOverride epoch:epoch]; - dispatch_time_t timeOut = 0; if(config.timeout != 0) { timeOut = config.timeout; @@ -1966,7 +2341,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; // Non-iphone non-mac platforms can be slow; heuristically slow them down timeOut = 60*NSEC_PER_SEC; } else { - timeOut = 2*NSEC_PER_SEC; + timeOut = 10*NSEC_PER_SEC; } OctagonStateTransitionRequest* request = [[OctagonStateTransitionRequest alloc] init:@"prepareForApplicant" @@ -1993,10 +2368,10 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return; } --(void)joinWithBottle:(NSString*)bottleID - entropy:(NSData *)entropy - bottleSalt:(NSString *)bottleSalt - reply:(void (^)(NSError * _Nullable error))reply +- (void)joinWithBottle:(NSString*)bottleID + entropy:(NSData *)entropy + bottleSalt:(NSString *)bottleSalt + reply:(void (^)(NSError * _Nullable error))reply { _bottleID = bottleID; _entropy = entropy; @@ -2010,8 +2385,8 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } OctagonStateTransitionPath* path = [OctagonStateTransitionPath pathFromDictionary:@{ - OctagonStateInitiatorCreateIdentity: @{ - OctagonStateInitiatorVouchWithBottle: [self joinStatePathDictionary], + OctagonStateBottleJoinCreateIdentity: @{ + OctagonStateBottleJoinVouchWithBottle: [self joinStatePathDictionary], }, }]; @@ -2048,19 +2423,24 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; - (NSDictionary*)joinStatePathDictionary { return @{ - OctagonStateInitiatorUpdateDeviceList: @{ - OctagonStateInitiatorJoin: @{ - OctagonStateBecomeReady: @{ - OctagonStateReady: [OctagonStateTransitionPathStep success], - }, - - OctagonStateInitiatorJoinCKKSReset: @{ - OctagonStateInitiatorJoinAfterCKKSReset: @{ - OctagonStateBecomeReady: @{ - OctagonStateReady: [OctagonStateTransitionPathStep success] - }, + OctagonStateInitiatorSetCDPBit: @{ + OctagonStateInitiatorUpdateDeviceList: @{ + OctagonStateInitiatorJoin: @{ + OctagonStateBottlePreloadOctagonKeysInSOS: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + }, + }, + OctagonStateInitiatorJoinCKKSReset: @{ + OctagonStateInitiatorJoinAfterCKKSReset: @{ + OctagonStateBottlePreloadOctagonKeysInSOS: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success] + }, + }, + }, + }, }, - }, }, }, }; @@ -2068,20 +2448,27 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; - (void)rpcJoin:(NSData*)vouchData vouchSig:(NSData*)vouchSig -preapprovedKeys:(NSArray* _Nullable)preapprovedKeys reply:(void (^)(NSError * _Nullable error))reply { - _vouchData = vouchData; - _vouchSig = vouchSig; - _preapprovedKeys = preapprovedKeys; - if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { secnotice("octagon", "No cloudkit account present"); reply([self errorNoiCloudAccount]); return; } + NSError* metadataError = nil; + [self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.voucher = vouchData; + metadata.voucherSignature = vouchSig; + return metadata; + } error:&metadataError]; + if(metadataError) { + secnotice("octagon", "Unable to save voucher for joining: %@", metadataError); + reply(metadataError); + return; + } + NSMutableSet* sourceStates = [NSMutableSet setWithObject:OctagonStateInitiatorAwaitingVoucher]; OctagonStateTransitionPath* path = [OctagonStateTransitionPath pathFromDictionary:[self joinStatePathDictionary]]; @@ -2165,7 +2552,9 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys result[@"containerName"] = self.containerName; result[@"contextID"] = self.contextID; - if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { + OTOperationConfiguration* timeoutContext = [[OTOperationConfiguration alloc] init]; + timeoutContext.timeoutWaitForCKAccount = 2 * NSEC_PER_SEC; + if ([self checkForCKAccount:timeoutContext] != CKKSAccountStatusAvailable) { secnotice("octagon", "No cloudkit account present"); reply(NULL, [self errorNoiCloudAccount]); return; @@ -2181,10 +2570,19 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys result[@"statePendingFlags"] = [self.stateMachine dumpPendingFlags]; result[@"stateFlags"] = [self.stateMachine.flags dumpFlags]; - result[@"memoizedTrustState"] = @(self.currentMemoizedTrustState); - result[@"memoizedAccountState"] = @(self.currentMemoizedAccountState); + NSError* metadataError = nil; + OTAccountMetadataClassC* currentAccountMetadata = [self.accountMetadataStore loadOrCreateAccountMetadata:&metadataError]; + if(metadataError) { + secnotice("octagon", "Failed to load account metaada for container (%@) and context (%@): %@", self.containerName, self.contextID, metadataError); + } + + result[@"memoizedTrustState"] = @(currentAccountMetadata.trustState); + result[@"memoizedAccountState"] = @(currentAccountMetadata.icloudAccountState); + result[@"memoizedCDPStatus"] = @(currentAccountMetadata.cdpState); result[@"octagonLaunchSeqence"] = [self.launchSequence eventsByTime]; - result[@"memoizedlastHealthCheck"] = self.currentMemoizedLastHealthCheck ? self.currentMemoizedLastHealthCheck : @"Never checked"; + + NSDate* lastHealthCheck = self.currentMemoizedLastHealthCheck; + result[@"memoizedlastHealthCheck"] = lastHealthCheck ?: @"Never checked"; if (self.sosAdapter.sosEnabled) { result[@"sosTrustedPeersStatus"] = [self sosTrustedPeersStatus]; result[@"sosSelvesStatus"] = [self sosSelvesStatus]; @@ -2197,8 +2595,9 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys } result[@"CoreFollowUp"] = [self.followupHandler sysdiagnoseStatus]; - result[@"lastOctagonPush"] = [[CKKSAnalytics logger] datePropertyForKey:CKKSAnalyticsLastOctagonPush]; + result[@"lastOctagonPush"] = [[CKKSAnalytics logger] datePropertyForKey:CKKSAnalyticsLastOctagonPush]; + result[@"pushEnvironments"] = [self.apsReceiver registeredPushEnvironments]; [self.cuttlefishXPCWrapper dumpWithContainer:self.containerName context:self.contextID @@ -2276,6 +2675,10 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys - (void)rpcSetRecoveryKey:(NSString*)recoveryKey reply:(void (^)(NSError * _Nullable error))reply { + if (self.lockStateTracker) { + [self.lockStateTracker recheck]; + } + OTSetRecoveryKeyOperation *pendingOp = [[OTSetRecoveryKeyOperation alloc] initWithDependencies:self.operationDependencies recoveryKey:recoveryKey]; @@ -2295,6 +2698,7 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys NSString* egoPeerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError *error))reply { CliqueStatus status = CliqueStatusAbsent; @@ -2305,8 +2709,8 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys status = CliqueStatusNotIn; } - secnotice("octagon", "returning cached clique status: %@", OTCliqueStatusToString(status)); - reply(status, account.peerID, nil, NO, NULL); + secinfo("octagon", "returning cached clique status: %@", OTCliqueStatusToString(status)); + reply(status, account.peerID, nil, NO, NO, NULL); } @@ -2315,6 +2719,7 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys NSString* _Nullable peerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError *error))reply { __block NSError* localError = nil; @@ -2322,13 +2727,13 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys OTAccountMetadataClassC* account = [self.accountMetadataStore loadOrCreateAccountMetadata:&localError]; if(localError && [self.lockStateTracker isLockedError:localError]){ secnotice("octagon", "Device is locked! pending initialization on unlock"); - reply(CliqueStatusError, nil, nil, NO, localError); + reply(CliqueStatusError, nil, nil, NO, NO, localError); return; } if(account.icloudAccountState == OTAccountMetadataClassC_AccountState_NO_ACCOUNT) { secnotice("octagon", "no account! returning clique status 'no account'"); - reply(CliqueStatusNoCloudKitAccount, nil, nil, NO, NULL); + reply(CliqueStatusNoCloudKitAccount, nil, nil, NO, NO, NULL); return; } @@ -2340,7 +2745,7 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys CKKSAccountStatus ckAccountStatus = [self checkForCKAccount:configuration]; if(ckAccountStatus == CKKSAccountStatusNoAccount) { secnotice("octagon", "No cloudkit account present"); - reply(CliqueStatusNoCloudKitAccount, nil, nil, NO, NULL); + reply(CliqueStatusNoCloudKitAccount, nil, nil, NO, NO, NULL); return; } else if(ckAccountStatus == CKKSAccountStatusUnknown) { secnotice("octagon", "Unknown cloudkit account status, returning cached trust value"); @@ -2352,6 +2757,7 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys __block NSDictionary* peerModelCounts = nil; __block BOOL excluded = NO; __block CliqueStatus trustStatus = CliqueStatusError; + __block BOOL isLocked = NO; [self.cuttlefishXPCWrapper trustStatusWithContainer:self.containerName context:self.contextID @@ -2361,6 +2767,7 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys peerID = egoStatus.egoPeerID; excluded = egoStatus.isExcluded; peerModelCounts = egoStatus.viablePeerCountsByModelID; + isLocked = egoStatus.isLocked; localError = xpcError; if(xpcError) { @@ -2385,12 +2792,15 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys else if((status&TPPeerStatusFullyReciprocated) == TPPeerStatusFullyReciprocated){ trustStatus = CliqueStatusIn; } - else if((status&TPPeerStatusUnknown) == TPPeerStatusUnknown){ - trustStatus = CliqueStatusAbsent; - } else if ((status&TPPeerStatusSelfTrust) == TPPeerStatusSelfTrust) { trustStatus = CliqueStatusIn; } + else if ((status&TPPeerStatusIgnored) == TPPeerStatusIgnored) { + trustStatus = CliqueStatusNotIn; + } + else if((status&TPPeerStatusUnknown) == TPPeerStatusUnknown){ + trustStatus = CliqueStatusAbsent; + } else { secnotice("octagon", "TPPeerStatus is empty"); trustStatus = CliqueStatusAbsent; @@ -2398,13 +2808,7 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys } }]; - if(trustStatus == CliqueStatusIn && self.postedRepairCFU == YES){ - NSError* clearError = nil; - [self.followupHandler clearFollowUp:OTFollowupContextTypeStateRepair error:&clearError]; - // TODO(caw): should we clear this flag if `clearFollowUpForContext` fails? - self.postedRepairCFU = NO; - } - reply(trustStatus, peerID, peerModelCounts, excluded, localError); + reply(trustStatus, peerID, peerModelCounts, excluded, isLocked, localError); } - (void)rpcFetchAllViableBottles:(void (^)(NSArray* _Nullable sortedBottleIDs, NSArray* _Nullable sortedPartialEscrowRecordIDs, NSError* _Nullable error))reply @@ -2430,6 +2834,51 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys }]; } +- (void)rpcFetchAllViableEscrowRecords:(BOOL)forceFetch reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply +{ + if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { + secnotice("octagon", "No cloudkit account present"); + reply(NULL, [self errorNoiCloudAccount]); + return; + } + + // As this isn't a state-modifying operation, we don't need to go through the state machine. + [self.cuttlefishXPCWrapper fetchViableEscrowRecordsWithContainer:self.containerName + context:self.contextID + forceFetch:(BOOL)forceFetch + reply:^(NSArray * _Nullable records, NSError * _Nullable error) { + if(error){ + secerror("octagon: error fetching all viable escrow records: %@", error); + reply(nil, error); + }else{ + secnotice("octagon", "fetched escrow records: %@", records); + + reply(records, error); + } + }]; +} + +- (void)rpcInvalidateEscrowCache:(void (^)(NSError* _Nullable error))reply +{ + if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { + secnotice("octagon", "No cloudkit account present"); + reply([self errorNoiCloudAccount]); + return; + } + + // As this isn't a state-modifying operation, we don't need to go through the state machine. + [self.cuttlefishXPCWrapper removeEscrowCacheWithContainer:self.containerName context:self.contextID reply:^(NSError * _Nullable removeError) { + if (removeError){ + secerror("octagon: failed to remove escrow cache: %@", removeError); + reply(removeError); + } else{ + secnotice("octagon", "successfully removed escrow cache"); + reply(nil); + } + }]; +} + - (void)fetchEscrowContents:(void (^)(NSData* _Nullable entropy, NSString* _Nullable bottleID, NSData* _Nullable signingPublicKey, @@ -2476,16 +2925,155 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys }]; } - -#pragma mark --- Testing -- (void) setAccountStateHolder:(OTCuttlefishAccountStateHolder*)accountMetadataStore +- (void)rpcRefetchCKKSPolicy:(void (^)(NSError * _Nullable error))reply { - self.accountMetadataStore = accountMetadataStore; + [self.stateMachine doWatchedStateMachineRPC:@"octagon-refetch-ckks-policy" + sourceStates:[NSMutableSet setWithArray: @[OctagonStateReady]] + path:[OctagonStateTransitionPath pathFromDictionary:@{ + OctagonStateRefetchCKKSPolicy: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + }, + }, + }] + reply:reply]; } -- (void)setPostedBool:(BOOL)posted +- (void)rpcFetchUserControllableViewsSyncingStatus:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply { - self.postedRepairCFU = posted; + if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { + secnotice("octagon-ckks", "No cloudkit account present"); + reply(NO, [self errorNoiCloudAccount]); + return; + } + + if ([self.stateMachine isPaused]) { + if ([[self.stateMachine currentState] isEqualToString:OctagonStateWaitForHSA2]) { + secnotice("octagon-ckks", "account is not hsa2 yet, returning"); + reply(NO, nil); + return; + } + } + + if(self.viewManager.policy) { + BOOL syncing = self.viewManager.policy.syncUserControllableViewsAsBoolean; + + secnotice("octagon-ckks", "Returning user-controllable status as %@ (%@)", + syncing ? @"enabled" : @"disabled", + TPPBPeerStableInfo_UserControllableViewStatusAsString(self.viewManager.policy.syncUserControllableViews)); + + reply(syncing, nil); + return; + } + + // No loaded policy? Let's trigger a fetch. + [self rpcRefetchCKKSPolicy:^(NSError * _Nullable error) { + if(error) { + secnotice("octagon-ckks", "Failed to fetch policy: %@", error); + reply(NO, error); + return; + } + + if(self.viewManager.policy) { + BOOL syncing = self.viewManager.policy.syncUserControllableViewsAsBoolean; + + secnotice("octagon-ckks", "Returning user-controllable status as %@ (%@)", + syncing ? @"enabled" : @"disabled", + TPPBPeerStableInfo_UserControllableViewStatusAsString(self.viewManager.policy.syncUserControllableViews)); + + reply(syncing, nil); + return; + + } else { + // The tests sometimes don't have a viewManager. If we're in the tests, try this last-ditch effort: + if(SecCKKSTestsEnabled()) { + NSError* metadataError = nil; + OTAccountMetadataClassC* accountState = [self.accountMetadataStore loadOrCreateAccountMetadata:&metadataError]; + if(metadataError) { + secnotice("octagon-ckks", "Error fetching acount state: %@", metadataError); + } + TPSyncingPolicy* policy = [accountState getTPSyncingPolicy]; + if(policy) { + BOOL syncing = policy.syncUserControllableViewsAsBoolean; + secnotice("octagon-ckks", "Returning user-controllable status (fetched from account state) as %@ (%@)", + syncing ? @"enabled" : @"disabled", + TPPBPeerStableInfo_UserControllableViewStatusAsString(self.viewManager.policy.syncUserControllableViews)); + reply(syncing, nil); + return; + } + } + + secnotice("octagon-ckks", "Policy missing even after a refetch?"); + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorSyncPolicyMissing + description:@"Sync policy is missing even after refetching"]); + return; + } + }]; +} + +- (void)rpcSetUserControllableViewsSyncingStatus:(BOOL)status reply:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply +{ +#if TARGET_OS_TV + // TVs can't set this value. + secnotice("octagon-ckks", "Rejecting set of user-controllable sync status due to platform"); + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNotSupported + description:@"This platform does not support setting the user-controllable view syncing status"]); +#else + + OctagonState* firstState = status ? OctagonStateEnableUserControllableViews : OctagonStateDisableUserControllableViews; + + secnotice("octagon-ckks", "Settting user-controllable sync status as '%@'", status ? @"enabled" : @"disabled"); + + [self.stateMachine doWatchedStateMachineRPC:@"octagon-set-policy" + sourceStates:[NSMutableSet setWithArray: @[OctagonStateReady]] + path:[OctagonStateTransitionPath pathFromDictionary:@{ + firstState: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + }, + }, + }] + reply:^(NSError * _Nullable error) { + if(error) { + secnotice("octagon-ckks", "Failed to set sync policy to '%@': %@", status ? @"enabled" : @"disabled", error); + reply(NO, error); + return; + } + + if(self.viewManager.policy) { + BOOL finalStatus = self.viewManager.policy.syncUserControllableViewsAsBoolean; + secnotice("octagon-ckks", "User-controllable sync status is set as '%@'", finalStatus ? @"enabled" : @"disabled"); + reply(finalStatus, nil); + return; + } + + // The tests sometimes don't have a viewManager. If we're in the tests, try this last-ditch effort: + if(SecCKKSTestsEnabled()) { + NSError* metadataError = nil; + OTAccountMetadataClassC* accountState = [self.accountMetadataStore loadOrCreateAccountMetadata:&metadataError]; + if(metadataError) { + secnotice("octagon-ckks", "Error fetching acount state: %@", metadataError); + } + TPSyncingPolicy* policy = [accountState getTPSyncingPolicy]; + if(policy) { + BOOL syncing = policy.syncUserControllableViewsAsBoolean; + secnotice("octagon-ckks", "Returning user-controllable status (fetched from account state) as %@ (%@)", + syncing ? @"enabled" : @"disabled", + TPPBPeerStableInfo_UserControllableViewStatusAsString(self.viewManager.policy.syncUserControllableViews)); + reply(syncing, nil); + return; + } + } + + secnotice("octagon-ckks", "Policy missing even after a refetch?"); + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorSyncPolicyMissing + description:@"Sync policy is missing even after refetching"]); + return; + }]; +#endif } #pragma mark --- Health Checker @@ -2494,21 +3082,16 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys { NSError* localError = nil; BOOL postSuccess = NO; - if (self.postedRepairCFU == NO) { - [self.followupHandler postFollowUp:OTFollowupContextTypeStateRepair error:&localError]; - if(localError){ - secerror("octagon-health: CoreCDP repair failed: %@", localError); - if(error){ - *error = localError; - } + [self.followupHandler postFollowUp:OTFollowupContextTypeStateRepair error:&localError]; + if(localError){ + secerror("octagon-health: CoreCDP repair failed: %@", localError); + if(error){ + *error = localError; } - else{ - secnotice("octagon-health", "CoreCDP post repair success"); - self.postedRepairCFU = YES; - postSuccess = YES; - } - } else { - secnotice("octagon-health", "already posted a repair CFU!"); + } + else{ + secnotice("octagon-health", "CoreCDP post repair success"); + postSuccess = YES; } return postSuccess; } @@ -2543,39 +3126,36 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys } } -- (void)postConfirmPasscodeCFU:(NSError**)error +- (BOOL)leaveTrust:(NSError**)error { - NSError* localError = nil; - if (self.postedEscrowRepairCFU == NO) { - [self.followupHandler postFollowUp:OTFollowupContextTypeOfflinePasscodeChange error:&localError]; - if(localError){ - secerror("octagon-health: CoreCDP offline passcode change failed: %@", localError); - *error = localError; + if (OctagonPlatformSupportsSOS()) { + CFErrorRef cfError = NULL; + bool left = SOSCCRemoveThisDeviceFromCircle_Server(&cfError); + + if(!left || cfError) { + secerror("failed to leave SOS circle: %@", cfError); + if(error) { + *error = (NSError*)CFBridgingRelease(cfError); + } else { + CFReleaseNull(cfError); + } + return NO; } - else{ - secnotice("octagon-health", "CoreCDP offline passcode change success"); - self.postedEscrowRepairCFU = YES; - } - } else { - secnotice("octagon-health", "already posted escrow CFU"); } + secnotice("octagon-health", "Successfully left SOS"); + return YES; } -- (void)postRecoveryKeyCFU:(NSError**)error +- (BOOL)postConfirmPasscodeCFU:(NSError**)error { + BOOL ret = NO; NSError* localError = nil; - if (self.postedRecoveryKeyCFU == NO) { - [self.followupHandler postFollowUp:OTFollowupContextTypeRecoveryKeyRepair error:&localError]; - if(localError){ - secerror("octagon-health: CoreCDP recovery key cfu failed: %@", localError); - } - else{ - secnotice("octagon-health", "CoreCDP recovery key cfu success"); - self.postedRecoveryKeyCFU = YES; - } - } else { - secnotice("octagon-health", "already posted recovery key CFU"); + ret = [self.followupHandler postFollowUp:OTFollowupContextTypeConfirmExistingSecret error:&localError]; + if(localError){ + secerror("octagon-health: CoreCDP confirm existing secret failed: %@", localError); + *error = localError; } + return ret; } - (void)checkOctagonHealth:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError * _Nullable error))reply @@ -2589,18 +3169,23 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys sourceStates:OctagonHealthSourceStates() path:[OctagonStateTransitionPath pathFromDictionary:@{ OctagonStateHSA2HealthCheck: @{ - OctagonStateSecurityTrustCheck: @{ - OctagonStateTPHTrustCheck: @{ - OctagonStateCuttlefishTrustCheck: @{ - OctagonStateBecomeReady: @{ - OctagonStateReady: [OctagonStateTransitionPathStep success], - OctagonStateWaitForUnlock: [OctagonStateTransitionPathStep success], + OctagonStateCDPHealthCheck: @{ + OctagonStateSecurityTrustCheck: @{ + OctagonStateTPHTrustCheck: @{ + OctagonStateCuttlefishTrustCheck: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + OctagonStateWaitForUnlock: [OctagonStateTransitionPathStep success], + }, + // Cuttlefish can suggest we reset the world. Consider reaching here a success, + // instead of tracking the whole reset. + OctagonStateHealthCheckReset: [OctagonStateTransitionPathStep success], + OctagonStateHealthCheckLeaveClique: [OctagonStateTransitionPathStep success], }, - // Cuttlefish can suggest we reset the world. Consider reaching here a success, - // instead of tracking the whole reset. - OctagonStateHealthCheckReset: [OctagonStateTransitionPathStep success], + OctagonStateWaitForUnlock: [OctagonStateTransitionPathStep success], }, }, + OctagonStateWaitForCDP: [OctagonStateTransitionPathStep success], }, OctagonStateWaitForHSA2: [OctagonStateTransitionPathStep success], } @@ -2608,51 +3193,27 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys reply:reply]; } -- (void)attemptSOSUpgrade:(void (^)(NSError* _Nullable error))reply -{ - secnotice("octagon-sos", "attempting to perform an sos upgrade"); - - if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { - secnotice("octagon-sos", "No cloudkit account present"); - reply([self errorNoiCloudAccount]); - return; - } - - NSSet* sourceStates = [NSSet setWithArray: @[OctagonStateUntrusted]]; - - OTSOSUpgradeOperation *pendingOp = [[OTSOSUpgradeOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateBecomeReady - ckksConflictState:OctagonStateBecomeUntrusted - errorState:OctagonStateBecomeUntrusted - deviceInfo:self.prepareInformation]; - - OctagonStateTransitionRequest* request = [[OctagonStateTransitionRequest alloc] init:@"attempt-sos-upgrade" - sourceStates:sourceStates - serialQueue:self.queue - timeout:OctagonStateTransitionDefaultTimeout - transitionOp:pendingOp]; - - CKKSResultOperation* callback = [CKKSResultOperation named:@"sos-upgrade-callback" - withBlock:^{ - secnotice("otrpc", "Returning from an sos upgrade attempt: %@", pendingOp.error); - [[CKKSAnalytics logger] logResultForEvent:OctagonEventUpgradePreapprovedJoinAfterPairing hardFailure:false result:pendingOp.error]; - reply(pendingOp.error); - }]; - - [callback addDependency:pendingOp]; - [self.operationQueue addOperation: callback]; - - [self.stateMachine handleExternalRequest:request]; -} - - (void)waitForOctagonUpgrade:(void (^)(NSError* error))reply { secnotice("octagon-sos", "waitForOctagonUpgrade"); + NSError* localError = nil; + if (!self.sosAdapter.sosEnabled) { secnotice("octagon-sos", "sos not enabled, nothing to do for waitForOctagonUpgrade"); reply(nil); return; + } else if ([self.sosAdapter circleStatus:&localError] != kSOSCCInCircle) { + secnotice("octagon-sos", "SOS circle status: %d, cannot perform sos upgrade", [self.sosAdapter circleStatus:&localError]); + if (localError == nil) { + localError = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:kSOSErrorNoCircle userInfo:@{NSLocalizedDescriptionKey : @"Not in circle"}]; + } else { + secerror("octagon-sos: error retrieving circle status: %@", localError); + } + reply(localError); + return; + } else { + secnotice("octagon-sos", "in sos circle!, attempting upgrade"); } if ([self.stateMachine isPaused]) { @@ -2671,12 +3232,15 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys } } - NSSet* sourceStates = [NSSet setWithArray: @[OctagonStateUntrusted]]; + NSSet* sourceStates = [NSSet setWithArray: @[OctagonStateWaitForCDP, + OctagonStateUntrusted]]; OctagonStateTransitionPath* path = [OctagonStateTransitionPath pathFromDictionary:@{ - OctagonStateAttemptSOSUpgrade: @{ - OctagonStateBecomeReady: @{ - OctagonStateReady: [OctagonStateTransitionPathStep success], + OctagonStateAttemptSOSUpgradeDetermineCDPState: @{ + OctagonStateAttemptSOSUpgrade: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + }, }, }, }]; @@ -2687,13 +3251,6 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys reply:reply]; } -- (void)clearPendingCFUFlags -{ - self.postedRecoveryKeyCFU = NO; - self.postedEscrowRepairCFU = NO; - self.postedRepairCFU = NO; -} - // Metrics passthroughs - (BOOL)machineIDOnMemoizedList:(NSString*)machineID error:(NSError**)error @@ -2720,10 +3277,11 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys return onList; } -- (NSNumber* _Nullable)numberOfPeersInModelWithMachineID:(NSString*)machineID error:(NSError**)error +- (TrustedPeersHelperEgoPeerStatus* _Nullable)egoPeerStatus:(NSError**)error { - __block NSNumber* ret = nil; + __block TrustedPeersHelperEgoPeerStatus* ret = nil; __block NSError* retError = nil; + [self.cuttlefishXPCWrapper trustStatusWithContainer:self.containerName context:self.contextID reply:^(TrustedPeersHelperEgoPeerStatus *egoStatus, @@ -2732,8 +3290,7 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys secnotice("octagon-metrics", "Unable to fetch trust status: %@", xpcError); retError = xpcError; } else { - ret = egoStatus.peerCountsByMachineID[machineID] ?: @(0); - secnotice("octagon-metrics", "Number of peers with machineID (%@): %@", machineID, ret); + ret = egoStatus; } }]; @@ -2744,5 +3301,24 @@ preapprovedKeys:(NSArray* _Nullable)preapprovedKeys return ret; } +- (void)rpcResetAccountCDPContents:(void (^)(NSError* _Nullable error))reply +{ + if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { + secnotice("octagon", "No cloudkit account present"); + reply([self errorNoiCloudAccount]); + return; + } + + // As this isn't a state-modifying operation, we don't need to go through the state machine. + [self.cuttlefishXPCWrapper resetAccountCDPContentsWithContainer:self.containerName context:self.contextID reply:^(NSError * resetError) { + if (resetError){ + secerror("octagon: failed to reset cdp account contents: %@", resetError); + reply(resetError); + } else{ + secnotice("octagon", "successfully reset cdp account contents"); + reply(nil); + } + }]; +} @end #endif diff --git a/keychain/ot/OTDefines.h b/keychain/ot/OTDefines.h index 8d5f6e71..74e09e3e 100644 --- a/keychain/ot/OTDefines.h +++ b/keychain/ot/OTDefines.h @@ -36,11 +36,8 @@ extern NSString* const OctagonEventAttributeTimeSinceLastPostedFollowUp; extern NSString* OTCKContainerName; extern NSString* const CuttlefishTrustZone; -extern NSString* const CuttlefishErrorDomain; extern NSString* const TrustedPeersHelperErrorDomain; -extern NSString* const CuttlefishErrorRetryAfterKey; - /* Octagon Errors */ typedef NS_ERROR_ENUM(OctagonErrorDomain, OctagonError) { //OTErrorNoColumn = 1, @@ -90,6 +87,8 @@ typedef NS_ERROR_ENUM(OctagonErrorDomain, OctagonError) { OTAuthKitNoAuthenticationController = 45, OTAuthKitMachineIDMissing = 46, OTAuthKitPrimaryAccountHaveNoDSID = 47, + OTErrorFailedToLeaveClique = 48, + OTErrorSyncPolicyMissing = 49, }; #define OTMasterSecretLength 72 @@ -97,7 +96,10 @@ typedef NS_ERROR_ENUM(OctagonErrorDomain, OctagonError) { typedef NS_ENUM(NSInteger, TrustedPeersHelperErrorCode) { TrustedPeersHelperErrorNoPreparedIdentity = 1, TrustedPeersHelperErrorNoPeersPreapprovePreparedIdentity = 14, + TrustedPeersHelperErrorCodeUntrustedRecoveryKeys = 32, TrustedPeersHelperErrorCodeNotEnrolled = 34, + TrustedPeersHelperErrorUnknownCloudKitError = 36, + TrustedPeersHelperErrorNoPeersPreapprovedBySelf = 47, }; // See cuttlefish/CuttlefishService/Sources/CuttlefishService/CuttlefishError.swift @@ -125,6 +127,16 @@ typedef NS_ENUM(NSInteger, CuttlefishErrorCode) { CuttlefishErrorPreflightGraphValidationError = 1022, CuttlefishErrorKeyHierarchyAlreadyExists = 1033, CuttlefishErrorDuplicatePeerIdUnderConsideration = 1034, + CuttlefishErrorIneligibleExclusionDenied = 1035, + CuttlefishErrorMultiplePreapprovedJoinDenied = 1036, + CuttlefishErrorUpdateTrustPeerNotFound = 1037, + CuttlefishErrorEscrowProxyFailure = 1038, + CuttlefishErrorResetFailed = 1039, + CuttlefishErrorViewZoneDeletionFailed = 1040, + + // For testing error handling. Never returned from actual cuttlefish. + // Should not be retried. + CuttlefishErrorTestGeneratedFailure = 9999, }; NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTDefines.m b/keychain/ot/OTDefines.m index 0aa95a36..476426dd 100644 --- a/keychain/ot/OTDefines.m +++ b/keychain/ot/OTDefines.m @@ -31,7 +31,5 @@ NSString* const OctagonEventAttributeTimeSinceLastPostedFollowUp = @"TimeSinceLa NSString* OTCKContainerName = @"com.apple.security.keychain"; NSString* const CuttlefishTrustZone = @"CuttlefishTrustZone"; -NSString* const CuttlefishErrorDomain = @"CuttlefishError"; NSString* const TrustedPeersHelperErrorDomain = @"com.apple.security.trustedpeers.container"; -NSString* const CuttlefishErrorRetryAfterKey = @"retryafter"; diff --git a/keychain/ot/OTDetermineCDPBitStatusOperation.h b/keychain/ot/OTDetermineCDPBitStatusOperation.h new file mode 100644 index 00000000..f4b377cb --- /dev/null +++ b/keychain/ot/OTDetermineCDPBitStatusOperation.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if OCTAGON + +#import +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" +#import "keychain/ot/OTOperationDependencies.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface OTDetermineCDPBitStatusOperation : CKKSGroupOperation + +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ot/OTDetermineCDPBitStatusOperation.m b/keychain/ot/OTDetermineCDPBitStatusOperation.m new file mode 100644 index 00000000..b776287b --- /dev/null +++ b/keychain/ot/OTDetermineCDPBitStatusOperation.m @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2019 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if OCTAGON + +#import "utilities/debugging.h" + +#import "keychain/ot/ObjCImprovements.h" +#import "keychain/ot/OTDetermineCDPBitStatusOperation.h" +#import "keychain/ot/OTStates.h" + +@interface OTDetermineCDPBitStatusOperation () +@property OTOperationDependencies* deps; +@end + +@implementation OTDetermineCDPBitStatusOperation +@synthesize intendedState = _intendedState; +@synthesize nextState = _nextState; + +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if((self = [super init])) { + _deps = dependencies; + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + secnotice("octagon-cdp-status", "Checking CDP status"); + + NSError* localError = nil; + OTAccountMetadataClassC* account = [self.deps.stateHolder loadOrCreateAccountMetadata:&localError]; + if(localError && [self.deps.lockStateTracker isLockedError:localError]) { + secnotice("octagon-cdp-status", "Device is locked! restarting on unlock"); + self.nextState = OctagonStateWaitForClassCUnlock; + return; + } + + if(localError) { + secnotice("octagon-cdp-status", "Failed to load account metadata: %@", localError); + self.error = localError; + return; + } + + secnotice("octagon-cdp-status", "CDP is %@", OTAccountMetadataClassC_CDPStateAsString(account.cdpState)); + + if(account.cdpState == OTAccountMetadataClassC_CDPState_ENABLED) { + self.nextState = self.intendedState; + } else { + // If the CDP status is unknown or disabled, double-check with TPH. + // If there are any peers, the CDP status really should be ENABLED. + __block OTAccountMetadataClassC_CDPState newState = OTAccountMetadataClassC_CDPState_UNKNOWN; + + WEAKIFY(self); + [self.deps.cuttlefishXPCWrapper trustStatusWithContainer:self.deps.containerName + context:self.deps.contextID + reply:^(TrustedPeersHelperEgoPeerStatus *egoStatus, + NSError *xpcError) { + STRONGIFY(self); + if(xpcError) { + secnotice("octagon-cdp-status", "Unable to talk with TPH; leaving CDP status as 'unknown': %@", xpcError); + return; + } + + secnotice("octagon-cdp-status", "Octagon reports %d peers", (int)egoStatus.numberOfPeersInOctagon); + if(egoStatus.numberOfPeersInOctagon > 0) { + newState = OTAccountMetadataClassC_CDPState_ENABLED; + } else { + // As a last gasp, check in with SOS (if enabled). If there's a circle (in or out), CDP is on + if(self.deps.sosAdapter.sosEnabled) { + secnotice("octagon-cdp-status", "Requesting SOS status..."); + + NSError* circleError = nil; + SOSCCStatus circleStatus = [self.deps.sosAdapter circleStatus:&circleError]; + + if(circleError || circleStatus == kSOSCCError) { + secnotice("octagon-cdp-status", "Error fetching circle status. Leaving CDP status as 'unknown': %@", circleError); + } else if(circleStatus == kSOSCCCircleAbsent) { + secnotice("octagon-cdp-status", "SOS reports circle absent. Setting CDP to 'disabled'"); + newState = OTAccountMetadataClassC_CDPState_DISABLED; + } else { + secnotice("octagon-cdp-status", "SOS reports some existing circle (%d). Setting CDP to 'enabled'", (int)circleStatus); + newState = OTAccountMetadataClassC_CDPState_ENABLED; + } + } else { + // No SOS? no CDP. + secnotice("octagon-cdp-status", "No SOS. CDP bit is off."); + newState = OTAccountMetadataClassC_CDPState_DISABLED; + } + } + }]; + + if(account.cdpState != newState) { + NSError* stateError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + if(metadata.cdpState == OTAccountMetadataClassC_CDPState_ENABLED) { + secnotice("octagon-cdp-status", "CDP bit is enabled on-disk, not modifying (would have been %@)", OTAccountMetadataClassC_CDPStateAsString(newState)); + + // Set this here to perform the right state choice later + newState = OTAccountMetadataClassC_CDPState_ENABLED; + return nil; + } else { + secnotice("octagon-cdp-status", "Writing CDP bit as %@", OTAccountMetadataClassC_CDPStateAsString(newState)); + metadata.cdpState = newState; + return metadata; + } + } error:&stateError]; + + if(stateError) { + secnotice("octagon-cdp-status", "Failed to load account metadata: %@", stateError); + } + } + + if(newState == OTAccountMetadataClassC_CDPState_ENABLED) { + self.nextState = self.intendedState; + } else { + self.nextState = OctagonStateWaitForCDP; + } + } +} + +@end + +#endif // OCTAGON diff --git a/keychain/ot/OTDeviceInformation.h b/keychain/ot/OTDeviceInformation.h index 39d49a9a..62c2b2ef 100644 --- a/keychain/ot/OTDeviceInformation.h +++ b/keychain/ot/OTDeviceInformation.h @@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN @property NSString* containerName; @property NSString* contextID; @property uint64_t epoch; -@property NSString* machineID; +@property (nullable) NSString* machineID; @property NSString* modelID; @property NSString* deviceName; @property NSString* serialNumber; @@ -40,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initForContainerName:(NSString*)containerName contextID:(NSString*)contextID epoch:(uint64_t)epoch - machineID:(NSString*)machineID + machineID:(NSString* _Nullable)machineID modelID:(NSString*)modelID deviceName:(NSString*)deviceName serialNumber:(NSString*)serialNumber diff --git a/keychain/ot/OTDeviceInformation.m b/keychain/ot/OTDeviceInformation.m index f84a1d3e..243212d2 100644 --- a/keychain/ot/OTDeviceInformation.m +++ b/keychain/ot/OTDeviceInformation.m @@ -41,7 +41,7 @@ - (instancetype)initForContainerName:(NSString*)containerName contextID:(NSString*)contextID epoch:(uint64_t)epoch - machineID:(NSString*)machineID + machineID:(NSString* _Nullable)machineID modelID:(NSString*)modelID deviceName:(NSString*)deviceName serialNumber:(NSString*)serialNumber diff --git a/keychain/ot/OTDeviceInformationAdapter.h b/keychain/ot/OTDeviceInformationAdapter.h index 43279916..f283c950 100644 --- a/keychain/ot/OTDeviceInformationAdapter.h +++ b/keychain/ot/OTDeviceInformationAdapter.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSString*)osVersion; /* Returns the serial number as a string. */ -- (NSString*)serialNumber; +- (NSString* _Nullable)serialNumber; /* register for deviceName updates */ - (void)registerForDeviceNameUpdates:(id)listener; diff --git a/keychain/ot/OTDeviceInformationAdapter.m b/keychain/ot/OTDeviceInformationAdapter.m index acd71ebe..9e8cf990 100644 --- a/keychain/ot/OTDeviceInformationAdapter.m +++ b/keychain/ot/OTDeviceInformationAdapter.m @@ -107,7 +107,7 @@ static void updateDeviceNameChanges(SCDynamicStoreRef store, CFArrayRef keys, vo #else -- (NSString*)serialNumber +- (NSString* _Nullable)serialNumber { io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); if (platformExpert == MACH_PORT_NULL) { diff --git a/keychain/ot/OTEnsureOctagonKeyConsistency.m b/keychain/ot/OTEnsureOctagonKeyConsistency.m index bb86a39c..965fb863 100644 --- a/keychain/ot/OTEnsureOctagonKeyConsistency.m +++ b/keychain/ot/OTEnsureOctagonKeyConsistency.m @@ -95,10 +95,16 @@ return; } - OctagonCKKSPeerAdapter* octagonAdapter = [[OctagonCKKSPeerAdapter alloc] initWithPeerID:octagonPeerID operationDependencies:self.deps]; + OctagonCKKSPeerAdapter* octagonAdapter = [[OctagonCKKSPeerAdapter alloc] initWithPeerID:octagonPeerID + containerName:self.deps.containerName + contextID:self.deps.contextID + cuttlefishXPC:self.deps.cuttlefishXPCWrapper]; + + secnotice("octagon", "Fetched SOS Self! Fetching Octagon Adapter now: %@", octagonAdapter); NSError* fetchSelfPeersError = nil; CKKSSelves *selfPeers = [octagonAdapter fetchSelfPeers:&fetchSelfPeersError]; + if((!selfPeers) || fetchSelfPeersError) { secnotice("octagon", "failed to retrieve self peers: %@", fetchSelfPeersError); self.error = fetchSelfPeersError; @@ -122,8 +128,8 @@ if(![octagonSigningKeyData isEqualToData:sosSigningKeyData] || ![octagonEncryptionKeyData isEqualToData:sosEncryptionKeyData]) { secnotice("octagon", "SOS and Octagon signing keys do NOT match! updating SOS"); NSError* updateError = nil; - [self.deps.sosAdapter updateOctagonKeySetWithAccount:currentSelfPeer error:&updateError]; - if(updateError) { + BOOL ret = [self.deps.sosAdapter updateOctagonKeySetWithAccount:currentSelfPeer error:&updateError]; + if(!ret) { self.error = updateError; [self runBeforeGroupFinished:self.finishOp]; return; diff --git a/keychain/ot/OTEstablishOperation.m b/keychain/ot/OTEstablishOperation.m index cfb4a621..93c6689c 100644 --- a/keychain/ot/OTEstablishOperation.m +++ b/keychain/ot/OTEstablishOperation.m @@ -31,6 +31,7 @@ #import "keychain/ckks/CloudKitCategories.h" #import "keychain/ckks/CKKSCurrentKeyPointer.h" #import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/SecureObjectSync/SOSAccount.h" #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" #import "keychain/ot/ObjCImprovements.h" @@ -74,7 +75,8 @@ [self dependOnBeforeGroupFinished:self.finishedOp]; // First, interrogate CKKS views, and see when they have a TLK proposal. - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.operationDependencies]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.operationDependencies + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"establish-with-keys" @@ -93,19 +95,16 @@ WEAKIFY(self); NSArray* publicSigningSPKIs = nil; - if(self.operationDependencies.sosAdapter.sosEnabled) { - NSError* peerError = nil; + NSError* sosPreapprovalError = nil; + publicSigningSPKIs = [OTSOSAdapterHelpers peerPublicSigningKeySPKIsForCircle:self.operationDependencies.sosAdapter error:&sosPreapprovalError]; - secnotice("octagon-sos", "SOS not enabled; no preapproved keys"); - NSSet>* peerSet = [self.operationDependencies.sosAdapter fetchTrustedPeers:&peerError]; - - if(!peerSet || peerError) { - secerror("octagon-sos: Can't fetch trusted peers during establish: %@", peerError); + if(publicSigningSPKIs) { + secnotice("octagon-sos", "SOS preapproved keys are %@", publicSigningSPKIs); + } else { + secnotice("octagon-sos", "Unable to fetch SOS preapproved keys: %@", sosPreapprovalError); } - publicSigningSPKIs = [OTSOSActualAdapter peerPublicSigningKeySPKIs:peerSet]; - secnotice("octagon-sos", "SOS preapproved keys are %@", publicSigningSPKIs); } else { secnotice("octagon-sos", "SOS not enabled; no preapproved keys"); } @@ -122,7 +121,10 @@ ckksKeys:viewKeySets tlkShares:pendingTLKShares preapprovedKeys:publicSigningSPKIs - reply:^(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, NSError * _Nullable error) { + reply:^(NSString * _Nullable peerID, + NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, + NSError * _Nullable error) { STRONGIFY(self); [[CKKSAnalytics logger] logResultForEvent:OctagonEventEstablishIdentity hardFailure:true result:error]; @@ -143,10 +145,12 @@ NSError* localError = nil; BOOL persisted = [self.operationDependencies.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { - metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; - metadata.peerID = peerID; - return metadata; - } error:&localError]; + metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; + metadata.peerID = peerID; + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&localError]; + if(!persisted || localError) { secnotice("octagon", "Couldn't persist results: %@", localError); self.error = localError; @@ -154,6 +158,8 @@ self.nextState = self.intendedState; } + [self.operationDependencies.viewManager setCurrentSyncingPolicy:syncingPolicy]; + // Tell CKKS about our shiny new records! for (id key in self.operationDependencies.viewManager.views) { CKKSKeychainView* view = self.operationDependencies.viewManager.views[key]; diff --git a/keychain/ot/OTFetchCKKSKeysOperation.h b/keychain/ot/OTFetchCKKSKeysOperation.h index 5bd5a0ee..bb2e1d98 100644 --- a/keychain/ot/OTFetchCKKSKeysOperation.h +++ b/keychain/ot/OTFetchCKKSKeysOperation.h @@ -2,6 +2,7 @@ #if OCTAGON #import +#import #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ckks/CKKSKeychainBackedKey.h" @@ -24,7 +25,15 @@ NS_ASSUME_NONNULL_BEGIN // Any new TLKShares that CKKS suggested we upload along with this keyset @property NSArray* pendingTLKShares; -- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies; +// Any views that didn't provide a keyset within time +@property NSSet* viewsTimedOutWithoutKeysets; + +// Set this to configure how long to wait for CKKS to resonse +@property dispatch_time_t desiredTimeout; + +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + refetchNeeded:(BOOL)refetchNeeded; +; - (instancetype)initWithViews:(NSSet*)views; @end diff --git a/keychain/ot/OTFetchCKKSKeysOperation.m b/keychain/ot/OTFetchCKKSKeysOperation.m index fc7fd5ed..7380f780 100644 --- a/keychain/ot/OTFetchCKKSKeysOperation.m +++ b/keychain/ot/OTFetchCKKSKeysOperation.m @@ -8,11 +8,14 @@ @interface OTFetchCKKSKeysOperation () @property NSSet* views; @property CKKSViewManager* manager; + +@property BOOL fetchBeforeGettingKeyset; @end @implementation OTFetchCKKSKeysOperation - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + refetchNeeded:(BOOL)refetchNeeded { if((self = [super init])) { _manager = dependencies.viewManager; @@ -21,6 +24,12 @@ _tlkShares = @[]; _pendingTLKShares = @[]; _incompleteKeySets = @[]; + + _desiredTimeout = SecCKKSTestsEnabled() ? 5*NSEC_PER_SEC : 15*NSEC_PER_SEC; + + _fetchBeforeGettingKeyset = refetchNeeded; + + _viewsTimedOutWithoutKeysets = [NSSet set]; } return self; } @@ -34,6 +43,12 @@ _tlkShares = @[]; _pendingTLKShares = @[]; _incompleteKeySets = @[]; + + _desiredTimeout = SecCKKSTestsEnabled() ? 5*NSEC_PER_SEC : 15*NSEC_PER_SEC; + + _fetchBeforeGettingKeyset = NO; + + _viewsTimedOutWithoutKeysets = [NSSet set]; } return self; } @@ -53,60 +68,70 @@ for (CKKSKeychainView* view in self.views) { secnotice("octagon-ckks", "Waiting for %@", view); - [keyOps addObject:[[view findKeySet] timeout:45*NSEC_PER_SEC]]; + [keyOps addObject:[[view findKeySet:self.fetchBeforeGettingKeyset] timeout:self.desiredTimeout]]; } WEAKIFY(self); CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"proceed-with-ckks-keys" withBlock:^{ - STRONGIFY(self); + STRONGIFY(self); - NSMutableArray* viewKeySets = [NSMutableArray array]; - NSMutableArray* ckksBrokenKeySets = [NSMutableArray array]; - NSMutableArray* tlkShares = [NSMutableArray array]; - NSMutableArray* pendingTLKShares = [NSMutableArray array]; + NSMutableArray* viewKeySets = [NSMutableArray array]; + NSMutableArray* ckksBrokenKeySets = [NSMutableArray array]; + NSMutableArray* tlkShares = [NSMutableArray array]; + NSMutableArray* pendingTLKShares = [NSMutableArray array]; - for(CKKSResultOperation* op in keyOps) { - if(op.error) { - secnotice("octagon-ckks", "No keys for zone %@: %@", op.zoneName, op.error); - continue; - } + NSMutableSet* viewsMIA = [NSMutableSet set]; - NSError* localerror = nil; - CKKSKeychainBackedKeySet* keyset = [op.keyset asKeychainBackedSet:&localerror]; + for(CKKSResultOperation* op in keyOps) { + if(op.error) { + secnotice("octagon-ckks", "No keys for zone %@: %@", op.zoneName, op.error); - if(keyset) { - secnotice("octagon-ckks", "Have proposed keys: %@", op.keyset); - [viewKeySets addObject:keyset]; - } else { - secnotice("octagon-ckks", "Unable to convert proposed keys: %@ %@", op.keyset, localerror); - if(op.keyset) { - [ckksBrokenKeySets addObject:op.keyset]; - } - } + if([op.error.domain isEqualToString:CKKSResultErrorDomain] && op.error.code == CKKSResultTimedOut) { + [viewsMIA addObject:op.zoneName]; + } + continue; + } - for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.tlkShares) { - [tlkShares addObject:tlkShareRecord.share]; - } - secnotice("octagon-ckks", "Have %u tlk shares", (uint32_t)op.keyset.tlkShares.count); + NSError* localerror = nil; + CKKSCurrentKeySet* keyset = op.keyset; + CKKSKeychainBackedKeySet* keychainBackedKeyset = [keyset asKeychainBackedSet:&localerror]; - for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.pendingTLKShares) { - [pendingTLKShares addObject:tlkShareRecord.share]; - } - secnotice("octagon-ckks", "Have %u pending tlk shares", (uint32_t)op.keyset.pendingTLKShares.count); - } + if(keychainBackedKeyset) { + secnotice("octagon-ckks", "Have proposed keys: %@", keyset); + [viewKeySets addObject:keychainBackedKeyset]; + } else { + if(keyset) { + secnotice("octagon-ckks", "Unable to convert proposed keys: %@ %@", keyset, localerror); + [ckksBrokenKeySets addObject:op.keyset]; + } + } - self.viewKeySets = viewKeySets; - self.incompleteKeySets = ckksBrokenKeySets; - self.tlkShares = tlkShares; - self.pendingTLKShares = pendingTLKShares; + for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.tlkShares) { + [tlkShares addObject:tlkShareRecord.share]; + } - secnotice("octagon-ckks", "Fetched %d key sets, %d broken key set,s %d tlk shares, and %d pendingTLKShares", - (int)self.viewKeySets.count, - (int)self.incompleteKeySets.count, - (int)self.tlkShares.count, - (int)self.pendingTLKShares.count); - }]; + for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.pendingTLKShares) { + [pendingTLKShares addObject:tlkShareRecord.share]; + } + secnotice("octagon-ckks", "Have %u tlk shares, %u pending tlk shares", + (uint32_t)op.keyset.tlkShares.count, + (uint32_t)op.keyset.pendingTLKShares.count); + } + + self.viewKeySets = viewKeySets; + self.incompleteKeySets = ckksBrokenKeySets; + self.tlkShares = tlkShares; + self.pendingTLKShares = pendingTLKShares; + self.viewsTimedOutWithoutKeysets = viewsMIA; + + secnotice("octagon-ckks", "Fetched %d key sets, %d broken key sets, %d tlk shares, %d pendingTLKShares, and %d views timing out", + (int)self.viewKeySets.count, + (int)self.incompleteKeySets.count, + (int)self.tlkShares.count, + (int)self.pendingTLKShares.count, + (int)self.viewsTimedOutWithoutKeysets.count); + }]; for(CKKSResultOperation* op in keyOps) { [proceedWithKeys addDependency: op]; diff --git a/keychain/ot/OTFetchViewsOperation.h b/keychain/ot/OTFetchViewsOperation.h index b7fbb418..f866bd21 100644 --- a/keychain/ot/OTFetchViewsOperation.h +++ b/keychain/ot/OTFetchViewsOperation.h @@ -31,12 +31,11 @@ NS_ASSUME_NONNULL_BEGIN -@interface OTFetchViewsOperation : CKKSGroupOperation +@interface OTFetchViewsOperation : CKKSGroupOperation -- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies; - -@property (nonatomic) NSSet* viewList; -@property (nonatomic) TPPolicy* _Nullable policy; +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; @end diff --git a/keychain/ot/OTFetchViewsOperation.m b/keychain/ot/OTFetchViewsOperation.m index cbe4e56a..c7cbdacf 100644 --- a/keychain/ot/OTFetchViewsOperation.m +++ b/keychain/ot/OTFetchViewsOperation.m @@ -26,21 +26,26 @@ #import "keychain/ot/OTFetchViewsOperation.h" #import "keychain/ot/ObjCImprovements.h" #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" +#import "keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h" #import "keychain/ckks/CKKSAnalytics.h" @interface OTFetchViewsOperation () @property OTOperationDependencies* deps; -@property NSOperation* finishedOp; -@property CKKSViewManager* ckm; @end @implementation OTFetchViewsOperation +@synthesize intendedState = _intendedState; +@synthesize nextState = _nextState; - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState { if ((self = [super init])) { _deps = dependencies; - _ckm = dependencies.viewManager; + + _intendedState = intendedState; + _nextState = errorState; } return self; } @@ -49,60 +54,41 @@ { secnotice("octagon", "fetching views"); - self.finishedOp = [[NSOperation alloc] init]; - [self dependOnBeforeGroupFinished:self.finishedOp]; + WEAKIFY(self); + [self.deps.cuttlefishXPCWrapper fetchCurrentPolicyWithContainer:self.deps.containerName + context:self.deps.contextID + modelIDOverride:nil + reply:^(TPSyncingPolicy* _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, + NSError* _Nullable error) { + STRONGIFY(self); + [[CKKSAnalytics logger] logResultForEvent:OctagonEventFetchViews hardFailure:true result:error]; - NSSet* sosViewList = [self.ckm viewList]; - self.policy = nil; - self.viewList = sosViewList; + if (error) { + secerror("octagon: failed to retrieve policy+views: %@", error); + self.error = error; + return; + } - if ([self.ckm useCKKSViewsFromPolicy]) { - WEAKIFY(self); - - [self.deps.cuttlefishXPCWrapper fetchPolicyWithContainer:self.deps.containerName context:self.deps.contextID reply:^(TPPolicy* _Nullable policy, NSError* _Nullable error) { - STRONGIFY(self); - if (error) { - secerror("octagon: failed to retrieve policy: %@", error); - [[CKKSAnalytics logger] logResultForEvent:OctagonEventFetchViews hardFailure:true result:error]; - self.error = error; - [self runBeforeGroupFinished:self.finishedOp]; - } else { - if (policy == nil) { - secerror("octagon: no policy returned"); - } - self.policy = policy; - NSArray* sosViews = [sosViewList allObjects]; - [self.deps.cuttlefishXPCWrapper getViewsWithContainer:self.deps.containerName context:self.deps.contextID inViews:sosViews reply:^(NSArray* _Nullable outViews, NSError* _Nullable error) { - STRONGIFY(self); - if (error) { - secerror("octagon: failed to retrieve list of views: %@", error); - [[CKKSAnalytics logger] logResultForEvent:OctagonEventFetchViews hardFailure:true result:error]; - self.error = error; - [self runBeforeGroupFinished:self.finishedOp]; - } else { - if (outViews == nil) { - secerror("octagon: bad results from getviews"); - } else { - self.viewList = [NSSet setWithArray:outViews]; - } - [self complete]; - } - }]; - } - }]; - } else { - [self complete]; - } -} + secnotice("octagon-ckks", "Received syncing policy %@ with view list: %@", syncingPolicy, syncingPolicy.viewList); + // Write them down before continuing -- (void)complete { - secnotice("octagon", "viewList: %@", self.viewList); - self.ckm.policy = self.policy; - self.ckm.viewList = self.viewList; + NSError* stateError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&stateError]; - [self.ckm createViews]; - [self.ckm beginCloudKitOperationOfAllViews]; - [self runBeforeGroupFinished:self.finishedOp]; + if(stateError) { + secerror("octagon: failed to save policy+views: %@", stateError); + self.error = stateError; + return; + } + + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; + + self.nextState = self.intendedState; + }]; } @end diff --git a/keychain/ot/OTFollowup.h b/keychain/ot/OTFollowup.h index e6f738ca..1929df5d 100644 --- a/keychain/ot/OTFollowup.h +++ b/keychain/ot/OTFollowup.h @@ -36,7 +36,7 @@ typedef NS_ENUM(uint8_t, OTFollowupContextType) { OTFollowupContextTypeNone, OTFollowupContextTypeRecoveryKeyRepair, OTFollowupContextTypeStateRepair, - OTFollowupContextTypeOfflinePasscodeChange, + OTFollowupContextTypeConfirmExistingSecret, }; NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType); @@ -55,9 +55,14 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType); - (BOOL)clearFollowUp:(OTFollowupContextType)contextType error:(NSError **)error; -- (NSDictionary *)sysdiagnoseStatus; +- (NSDictionary *_Nullable)sysdiagnoseStatus; - (NSDictionary *)sfaStatus; +@end +@interface OTFollowup (Testing) +// Reports on whether this individual OTFollowUp object has posted a CFU of this type. +- (BOOL)hasPosted:(OTFollowupContextType)contextType; +- (void)clearAllPostedFlags; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTFollowup.m b/keychain/ot/OTFollowup.m index 419f399c..b92e5367 100644 --- a/keychain/ot/OTFollowup.m +++ b/keychain/ot/OTFollowup.m @@ -46,8 +46,8 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType) return @"recovery key"; case OTFollowupContextTypeStateRepair: return @"repair"; - case OTFollowupContextTypeOfflinePasscodeChange: - return @"offline passcode change"; + case OTFollowupContextTypeConfirmExistingSecret: + return @"confirm existing secret"; } } @@ -56,6 +56,8 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType) @property NSTimeInterval previousFollowupEnd; @property NSTimeInterval followupStart; @property NSTimeInterval followupEnd; + +@property NSMutableSet* postedCFUTypes; @end @implementation OTFollowup : NSObject @@ -64,6 +66,8 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType) { if (self = [super init]) { self.cdpd = cdpFollowupController; + + _postedCFUTypes = [NSMutableSet set]; } return self; } @@ -77,8 +81,8 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType) case OTFollowupContextTypeRecoveryKeyRepair: { return [CDPFollowUpContext contextForRecoveryKeyRepair]; } - case OTFollowupContextTypeOfflinePasscodeChange: { - return [CDPFollowUpContext contextForOfflinePasscodeChange]; + case OTFollowupContextTypeConfirmExistingSecret: { + return [CDPFollowUpContext contextForConfirmExistingSecret]; } default: { return nil; @@ -95,9 +99,16 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType) } NSError *followupError = nil; + + secnotice("followup", "Posting a follow up (for Octagon) of type %@", OTFollowupContextTypeToString(contextType)); BOOL result = [self.cdpd postFollowUpWithContext:context error:&followupError]; - if (error) { - *error = followupError; + + if(result) { + [self.postedCFUTypes addObject:OTFollowupContextTypeToString(contextType)]; + } else { + if (error) { + *error = followupError; + } } return result; @@ -112,11 +123,17 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType) return NO; } - return [self.cdpd clearFollowUpWithContext:context error:error]; + secnotice("followup", "Clearing follow ups (for Octagon) of type %@", OTFollowupContextTypeToString(contextType)); + BOOL result = [self.cdpd clearFollowUpWithContext:context error:error]; + if(result) { + [self.postedCFUTypes removeObject:OTFollowupContextTypeToString(contextType)]; + } + + return result; } -- (NSDictionary *)sysdiagnoseStatus +- (NSDictionary *_Nullable)sysdiagnoseStatus { NSMutableDictionary *pendingCFUs = nil; @@ -168,7 +185,18 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType) return values; } +@end +@implementation OTFollowup (Testing) +- (BOOL)hasPosted:(OTFollowupContextType)contextType +{ + return [self.postedCFUTypes containsObject:OTFollowupContextTypeToString(contextType)]; +} + +- (void)clearAllPostedFlags +{ + [self.postedCFUTypes removeAllObjects]; +} @end #endif // OCTAGON diff --git a/keychain/ot/OTJoinWithVoucherOperation.h b/keychain/ot/OTJoinWithVoucherOperation.h index 3668f4d1..325bf4b9 100644 --- a/keychain/ot/OTJoinWithVoucherOperation.h +++ b/keychain/ot/OTJoinWithVoucherOperation.h @@ -38,16 +38,12 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState ckksConflictState:(OctagonState*)ckksConflictState - errorState:(OctagonState*)errorState - voucherData:(NSData*)voucherData - voucherSig:(NSData*)voucherSig - preapprovedKeys:(NSArray*)preapprovedKeys; + errorState:(OctagonState*)errorState; -@property (nonatomic) NSData* voucherData; -@property (nonatomic) NSData* voucherSig; -@property (nonatomic) NSArray* preapprovedKeys; +@property (nullable) NSData* voucherData; +@property (nullable) NSData* voucherSig; -@property (nonatomic) NSString* peerID; +@property (nullable) NSString* peerID; @end diff --git a/keychain/ot/OTJoinWithVoucherOperation.m b/keychain/ot/OTJoinWithVoucherOperation.m index f68765d5..d2d6a332 100644 --- a/keychain/ot/OTJoinWithVoucherOperation.m +++ b/keychain/ot/OTJoinWithVoucherOperation.m @@ -53,9 +53,6 @@ intendedState:(OctagonState*)intendedState ckksConflictState:(OctagonState*)ckksConflictState errorState:(OctagonState*)errorState - voucherData:(NSData*)voucherData - voucherSig:(NSData*)voucherSig - preapprovedKeys:(NSArray*)preapprovedKeys { if((self = [super init])) { _deps = dependencies; @@ -64,23 +61,39 @@ _nextState = errorState; _ckksConflictState = ckksConflictState; - _voucherData = voucherData; - _voucherSig = voucherSig; - _preapprovedKeys = preapprovedKeys; + _peerID = nil; + _voucherData = nil; + _voucherSig = nil; } return self; } - (void)groupStart { - secnotice("octagon", "joining"); + // Load the voucher from the state handler + NSError* error = nil; + OTAccountMetadataClassC* metadata = [self.deps.stateHolder loadOrCreateAccountMetadata:&error]; + + if(!metadata.voucher || !metadata.voucherSignature || error) { + secnotice("octagon", "No voucher available: %@", error); + self.error = error; + return; + } + + self.voucherData = metadata.voucher; + self.voucherSig = metadata.voucherSignature; + + secnotice("octagon", "joining with a voucher: %@", self.voucherData); self.finishedOp = [[NSOperation alloc] init]; [self dependOnBeforeGroupFinished:self.finishedOp]; WEAKIFY(self); - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; + // We only care about TLKs that are ready for upload. Don't wait long. + fetchKeysOp.desiredTimeout = 2*NSEC_PER_SEC; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"vouch-with-keys" @@ -98,14 +111,32 @@ { WEAKIFY(self); + NSArray* publicSigningSPKIs = nil; + if(self.deps.sosAdapter.sosEnabled) { + NSError* sosPreapprovalError = nil; + publicSigningSPKIs = [OTSOSAdapterHelpers peerPublicSigningKeySPKIsForCircle:self.deps.sosAdapter error:&sosPreapprovalError]; + + if(publicSigningSPKIs) { + secnotice("octagon-sos", "SOS preapproved keys are %@", publicSigningSPKIs); + } else { + secnotice("octagon-sos", "Unable to fetch SOS preapproved keys: %@", sosPreapprovalError); + } + + } else { + secnotice("octagon-sos", "SOS not enabled; no preapproved keys"); + } + [self.deps.cuttlefishXPCWrapper joinWithContainer:self.deps.containerName context:self.deps.contextID voucherData:self.voucherData voucherSig:self.voucherSig ckksKeys:viewKeySets tlkShares:pendingTLKShares - preapprovedKeys:self.preapprovedKeys - reply:^(NSString * _Nullable peerID, NSArray* keyHierarchyRecords, NSError * _Nullable error) { + preapprovedKeys:publicSigningSPKIs + reply:^(NSString * _Nullable peerID, + NSArray* keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, + NSError * _Nullable error) { STRONGIFY(self); if(error){ secerror("octagon: Error joining with voucher: %@", error); @@ -127,12 +158,19 @@ [[CKKSAnalytics logger] logSuccessForEventNamed:OctagonEventJoinWithVoucher]; + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; + NSError* localError = nil; BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { - metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; - metadata.peerID = peerID; - return metadata; - } error:&localError]; + metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; + metadata.peerID = peerID; + + metadata.voucher = nil; + metadata.voucherSignature = nil; + + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&localError]; if(!persisted || localError) { secnotice("octagon", "Couldn't persist results: %@", localError); self.error = localError; diff --git a/keychain/ot/OTJoiningConfiguration.h b/keychain/ot/OTJoiningConfiguration.h index af3b327a..9207a19f 100644 --- a/keychain/ot/OTJoiningConfiguration.h +++ b/keychain/ot/OTJoiningConfiguration.h @@ -44,14 +44,6 @@ NS_ASSUME_NONNULL_BEGIN // Set this to non-zero if you want to configure your timeouts @property int64_t timeout; -- (instancetype)initWithProtocolType:(NSString*)protocolType - uniqueDeviceID:(NSString*)uniqueDeviceID - uniqueClientID:(NSString*)uniqueClientID - containerName:(NSString* _Nullable)containerName - contextID:(NSString*)contextID - epoch:(uint64_t)epoch - isInitiator:(BOOL)isInitiator; - - (instancetype)initWithProtocolType:(NSString*)protocolType uniqueDeviceID:(NSString*)uniqueDeviceID uniqueClientID:(NSString*)uniqueClientID diff --git a/keychain/ot/OTJoiningConfiguration.m b/keychain/ot/OTJoiningConfiguration.m index 339311f5..e0150f3a 100644 --- a/keychain/ot/OTJoiningConfiguration.m +++ b/keychain/ot/OTJoiningConfiguration.m @@ -33,24 +33,6 @@ NS_ASSUME_NONNULL_BEGIN return YES; } -- (instancetype)initWithProtocolType:(NSString*)protocolType - uniqueDeviceID:(NSString*)uniqueDeviceID - uniqueClientID:(NSString*)uniqueClientID - containerName:(NSString* _Nullable)containerName - contextID:(NSString*)contextID - epoch:(uint64_t)epoch - isInitiator:(BOOL)isInitiator -{ - return [self initWithProtocolType:protocolType - uniqueDeviceID:uniqueDeviceID - uniqueClientID:uniqueClientID - pairingUUID:[NSUUID UUID].UUIDString - containerName:containerName - contextID:contextID - epoch:(uint64_t)epoch - isInitiator:isInitiator]; -} - - (instancetype)initWithProtocolType:(NSString*)protocolType uniqueDeviceID:(NSString*)uniqueDeviceID uniqueClientID:(NSString*)uniqueClientID @@ -60,8 +42,7 @@ NS_ASSUME_NONNULL_BEGIN epoch:(uint64_t)epoch isInitiator:(BOOL)isInitiator { - self = [super init]; - if (self){ + if ((self = [super init])) { self.protocolType = protocolType; self.uniqueDeviceID = uniqueDeviceID; self.uniqueClientID = uniqueClientID; @@ -89,8 +70,7 @@ NS_ASSUME_NONNULL_BEGIN } - (nullable instancetype)initWithCoder:(nonnull NSCoder *)decoder { - self = [super init]; - if (self) { + if ((self = [super init])) { _protocolType = [decoder decodeObjectOfClass:[NSString class] forKey:@"protocolType"]; _uniqueClientID = [decoder decodeObjectOfClass:[NSString class] forKey:@"uniqueClientID"]; _uniqueDeviceID = [decoder decodeObjectOfClass:[NSString class] forKey:@"uniqueDeviceID"]; diff --git a/keychain/ot/OTLocalCuttlefishReset.h b/keychain/ot/OTLocalCuttlefishReset.h index 90011df7..65f7c0df 100644 --- a/keychain/ot/OTLocalCuttlefishReset.h +++ b/keychain/ot/OTLocalCuttlefishReset.h @@ -27,17 +27,17 @@ #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ot/OctagonStateMachineHelpers.h" -#import "keychain/ot/CuttlefishXPCWrapper.h" +#import "keychain/ot/OTOperationDependencies.h" + +@class OTOperationDependencies; NS_ASSUME_NONNULL_BEGIN @interface OTLocalResetOperation : CKKSGroupOperation -- (instancetype)init:(NSString*)containerName - contextID:(NSString*)contextID - intendedState:(OctagonState*)intendedState - errorState:(OctagonState*)errorState -cuttlefishXPCWrapper:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper; +- (instancetype)initWithDependencies:(OTOperationDependencies*)deps + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTLocalCuttlefishReset.m b/keychain/ot/OTLocalCuttlefishReset.m index 30cd3608..7fcf57e6 100644 --- a/keychain/ot/OTLocalCuttlefishReset.m +++ b/keychain/ot/OTLocalCuttlefishReset.m @@ -30,9 +30,8 @@ #import "utilities/debugging.h" @interface OTLocalResetOperation () -@property NSString* containerName; -@property NSString* contextID; -@property CuttlefishXPCWrapper* cuttlefishXPCWrapper; +@property OTOperationDependencies* deps; + @property NSOperation* finishedOp; @end @@ -40,19 +39,15 @@ @synthesize intendedState = _intendedState; @synthesize nextState = _nextState; -- (instancetype)init:(NSString*)containerName - contextID:(NSString*)contextID - intendedState:(OctagonState*)intendedState - errorState:(OctagonState*)errorState -cuttlefishXPCWrapper:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper +- (instancetype)initWithDependencies:(OTOperationDependencies *)deps + intendedState:(OctagonState *)intendedState + errorState:(OctagonState *)errorState { if((self = [super init])) { _intendedState = intendedState; _nextState = errorState; - _containerName = containerName; - _contextID = contextID; - _cuttlefishXPCWrapper = cuttlefishXPCWrapper; + _deps = deps; } return self; } @@ -65,16 +60,34 @@ cuttlefishXPCWrapper:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper [self dependOnBeforeGroupFinished:self.finishedOp]; WEAKIFY(self); - [self.cuttlefishXPCWrapper localResetWithContainer:self.containerName - context:self.contextID - reply:^(NSError * _Nullable error) { + [self.deps.cuttlefishXPCWrapper localResetWithContainer:self.deps.containerName + context:self.deps.contextID + reply:^(NSError * _Nullable error) { STRONGIFY(self); if(error) { - secnotice("octagon", "Unable to reset local cuttlefish for (%@,%@): %@", self.containerName, self.contextID, error); + secnotice("octagon", "Unable to reset local cuttlefish for (%@,%@): %@", self.deps.containerName, self.deps.contextID, error); self.error = error; } else { secnotice("octagon", "Successfully reset local cuttlefish"); - self.nextState = self.intendedState; + + NSError* localError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.trustState = OTAccountMetadataClassC_TrustState_UNKNOWN; + metadata.peerID = nil; + metadata.syncingPolicy = nil; + + // Don't touch the CDP or account states; those can carry over + + return metadata; + } error:&localError]; + + if(localError) { + secnotice("octagon", "Error resetting local account state: %@", localError); + + } else { + secnotice("octagon", "Successfully reset local account state"); + self.nextState = self.intendedState; + } } [self runBeforeGroupFinished:self.finishedOp]; diff --git a/keychain/ot/OTManager.h b/keychain/ot/OTManager.h index 88a1820f..34dcb05e 100644 --- a/keychain/ot/OTManager.h +++ b/keychain/ot/OTManager.h @@ -36,6 +36,9 @@ #import "keychain/ot/OTCuttlefishAccountStateHolder.h" #import "keychain/escrowrequest/Framework/SecEscrowRequest.h" #import "keychain/ckks/CKKSAccountStateTracker.h" +#import "keychain/ckks/CKKSLockStateTracker.h" +#import "keychain/ckks/CKKSReachabilityTracker.h" +#import "keychain/ckks/CKKSViewManager.h" #include "keychain/securityd/SecDbItem.h" #import NS_ASSUME_NONNULL_BEGIN @@ -45,22 +48,29 @@ NS_ASSUME_NONNULL_BEGIN @class OTClientStateMachine; @class CKKSLockStateTracker; @class CKKSAccountStateTracker; +@class CloudKitClassDependencies; @interface OTManager : NSObject @property (nonatomic, readonly) CKKSLockStateTracker* lockStateTracker; -@property id accountStateTracker; +@property CKKSAccountStateTracker* accountStateTracker; +@property CKKSReachabilityTracker* reachabilityTracker; -- (instancetype)init NS_UNAVAILABLE; +@property (readonly) CKContainer* cloudKitContainer; +@property (nullable) CKKSViewManager* viewManager; + +// Creates an OTManager ready for use with live external systems. +- (instancetype)init; - (instancetype)initWithSOSAdapter:(id)sosAdapter - authKitAdapter:(id)authKitAdapter + authKitAdapter:(id)authKitAdapter deviceInformationAdapter:(id)deviceInformationAdapter apsConnectionClass:(Class)apsConnectionClass escrowRequestClass:(Class)escrowRequestClass - loggerClass:(Class _Nullable)loggerClass - lockStateTracker:(CKKSLockStateTracker* _Nullable)lockStateTracker - accountStateTracker:(id)accountStateTracker + loggerClass:(Class)loggerClass + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker + cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies cuttlefishXPCConnection:(id _Nullable)cuttlefishXPCConnection cdpd:(id)cdpd; @@ -69,9 +79,12 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)waitForReady:(NSString* _Nullable)containerName context:(NSString*)context wait:(int64_t)wait; - (void)moveToCheckTrustedStateForContainer:(NSString* _Nullable)containerName context:(NSString*)context; +// Call this to ensure SFA is ready +- (void)setupAnalytics; + + (instancetype _Nullable)manager; + (instancetype _Nullable)resetManager:(bool)reset to:(OTManager* _Nullable)obj; -- (void)xpc24HrNotification:(NSString* _Nullable)containerName context:(NSString*)context skipRateLimitingCheck:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError *error))reply; +- (void)xpc24HrNotification; - (OTCuttlefishContext*)contextForContainerName:(NSString* _Nullable)containerName contextID:(NSString*)contextID @@ -127,10 +140,24 @@ NS_ASSUME_NONNULL_BEGIN containerName:(NSString* _Nullable)containerName contextName:(NSString *)contextName reply:(void (^)(NSError *error))reply; - -//test only -- (void)setSOSEnabledForPlatformFlag:(bool) value; @end + +@interface OTManager (Testing) +- (void)setSOSEnabledForPlatformFlag:(bool) value; + +- (void)clearAllContexts; + +// Note that the OTManager returned by this will not work particularly well, if you want to do Octagon things +// This should only be used for the CKKS tests +- (instancetype)initWithSOSAdapter:(id)sosAdapter + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply; +@end + NS_ASSUME_NONNULL_END #endif // OCTAGON diff --git a/keychain/ot/OTManager.m b/keychain/ot/OTManager.m index 92c0caae..b11c13b0 100644 --- a/keychain/ot/OTManager.m +++ b/keychain/ot/OTManager.m @@ -49,6 +49,7 @@ #import "keychain/ckks/CKKS.h" #import "keychain/ckks/CKKSViewManager.h" #import "keychain/ckks/CKKSLockStateTracker.h" +#import "keychain/ckks/CKKSCloudKitClassDependencies.h" #import #import @@ -77,6 +78,9 @@ #import +#import +#import + #import "keychain/TrustedPeersHelper/TPHObjcTranslation.h" #import "keychain/SecureObjectSync/SOSAccountTransaction.h" #pragma clang diagnostic push @@ -86,6 +90,9 @@ #import "utilities/SecTapToRadar.h" +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CloudServices); +SOFT_LINK_CLASS(CloudServices, SecureBackup); + static NSString* const kOTRampForEnrollmentRecordName = @"metadata_rampstate_enroll"; static NSString* const kOTRampForRestoreRecordName = @"metadata_rampstate_restore"; static NSString* const kOTRampForCFURecordName = @"metadata_rampstate_cfu"; @@ -135,11 +142,11 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; - (instancetype)init { - // Under Octagon, the sos adatper is not considered essential. + // Under Octagon, the sos adapter is not considered essential. id sosAdapter = (OctagonPlatformSupportsSOS() ? [[OTSOSActualAdapter alloc] initAsEssential:NO] : [[OTSOSMissingAdapter alloc] init]); - + return [self initWithSOSAdapter:sosAdapter authKitAdapter:[[OTAuthKitActualAdapter alloc] init] deviceInformationAdapter:[[OTDeviceInformationActualAdapter alloc] init] @@ -147,23 +154,23 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; escrowRequestClass:[EscrowRequestServer class] // Use the server class here to skip the XPC layer loggerClass:[CKKSAnalytics class] lockStateTracker:[CKKSLockStateTracker globalTracker] - // The use of CKKS's account tracker here is an inversion, and will be fixed with CKKS-for-all when we - // have Octagon own the CKKS objects - accountStateTracker:[CKKSViewManager manager].accountTracker + reachabilityTracker:[[CKKSReachabilityTracker alloc] init] + cloudKitClassDependencies:[CKKSCloudKitClassDependencies forLiveCloudKit] cuttlefishXPCConnection:nil cdpd:[[CDPFollowUpController alloc] init]]; } --(instancetype)initWithSOSAdapter:(id)sosAdapter - authKitAdapter:(id)authKitAdapter - deviceInformationAdapter:(id)deviceInformationAdapter - apsConnectionClass:(Class)apsConnectionClass - escrowRequestClass:(Class)escrowRequestClass - loggerClass:(Class)loggerClass - lockStateTracker:(CKKSLockStateTracker*)lockStateTracker - accountStateTracker:(id)accountStateTracker - cuttlefishXPCConnection:(id)cuttlefishXPCConnection - cdpd:(id)cdpd +- (instancetype)initWithSOSAdapter:(id)sosAdapter + authKitAdapter:(id)authKitAdapter + deviceInformationAdapter:(id)deviceInformationAdapter + apsConnectionClass:(Class)apsConnectionClass + escrowRequestClass:(Class)escrowRequestClass + loggerClass:(Class)loggerClass + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker + cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies + cuttlefishXPCConnection:(id)cuttlefishXPCConnection + cdpd:(id)cdpd { if((self = [super init])) { _sosAdapter = sosAdapter; @@ -171,10 +178,15 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; _deviceInformationAdapter = deviceInformationAdapter; _loggerClass = loggerClass; _lockStateTracker = lockStateTracker; - _accountStateTracker = accountStateTracker; + _reachabilityTracker = reachabilityTracker; + _sosEnabledForPlatform = OctagonPlatformSupportsSOS(); _cuttlefishXPCConnection = cuttlefishXPCConnection; + _cloudKitContainer = [CKKSViewManager makeCKContainer:SecCKKSContainerName usePCS:SecCKKSContainerUsePCS]; + _accountStateTracker = [[CKKSAccountStateTracker alloc] init:_cloudKitContainer + nsnotificationCenterClass:cloudKitClassDependencies.nsnotificationCenterClass]; + self.contexts = [NSMutableDictionary dictionary]; self.clients = [NSMutableDictionary dictionary]; @@ -185,19 +197,44 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; _cdpd = cdpd; + _viewManager = [[CKKSViewManager alloc] initWithContainer:_cloudKitContainer + sosAdapter:sosAdapter + accountStateTracker:_accountStateTracker + lockStateTracker:lockStateTracker + reachabilityTracker:_reachabilityTracker + cloudKitClassDependencies:cloudKitClassDependencies]; + // The default CuttlefishContext always exists: (void) [self contextForContainerName:OTCKContainerName contextID:OTDefaultContext]; - - // Tell SFA to expect us - if(OctagonIsEnabled()){ - [self setupAnalytics]; - } secnotice("octagon", "otmanager init"); } return self; } +- (instancetype)initWithSOSAdapter:(id)sosAdapter + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies +{ + if((self = [super init])) { + _sosAdapter = sosAdapter; + _lockStateTracker = lockStateTracker; + + _cloudKitContainer = [CKKSViewManager makeCKContainer:SecCKKSContainerName usePCS:SecCKKSContainerUsePCS]; + _accountStateTracker = [[CKKSAccountStateTracker alloc] init:_cloudKitContainer + nsnotificationCenterClass:cloudKitClassDependencies.nsnotificationCenterClass]; + _reachabilityTracker = [[CKKSReachabilityTracker alloc] init]; + + _viewManager = [[CKKSViewManager alloc] initWithContainer:_cloudKitContainer + sosAdapter:sosAdapter + accountStateTracker:_accountStateTracker + lockStateTracker:lockStateTracker + reachabilityTracker:_reachabilityTracker + cloudKitClassDependencies:cloudKitClassDependencies]; + } + return self; +} + - (void)initializeOctagon { secnotice("octagon", "Initializing Octagon..."); @@ -246,6 +283,12 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; return nil; } + if([CKDatabase class] == nil) { + // CloudKit is not linked. We cannot bring Octagon up. + secerror("Octagon: CloudKit.framework appears to not be linked. Cannot create an Octagon manager (on pain of crash)."); + return nil; + } + return [self resetManager:false to:nil]; } @@ -584,7 +627,7 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; CKKSViewManager* viewManager = nil; if([containerName isEqualToString:SecCKKSContainerName] && [contextID isEqualToString:OTDefaultContext]) { - viewManager = [CKKSViewManager manager]; + viewManager = self.viewManager; } if(!context) { @@ -595,6 +638,7 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; authKitAdapter:authKitAdapter ckksViewManager:viewManager lockStateTracker:lockStateTracker + reachabilityTracker:self.reachabilityTracker accountStateTracker:accountStateTracker deviceInformationAdapter:deviceInformationAdapter apsConnectionClass:self.apsConnectionClass @@ -607,6 +651,15 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; return context; } +- (void)clearAllContexts +{ + if(self.contexts) { + dispatch_sync(self.queue, ^{ + [self.contexts removeAllObjects]; + }); + } +} + - (void)fetchEgoPeerID:(NSString* _Nullable)container context:(NSString*)context reply:(void (^)(NSString* _Nullable peerID, NSError* _Nullable error))reply @@ -641,6 +694,7 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; NSString * _Nullable peerID, NSDictionary * _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable error) { // Our clients don't need the whole breakout of peers, so just count for them long peerCount = 0; @@ -683,6 +737,7 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; NSString* egoPeerID, NSDictionary * _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable error) { reply(status, error); }]; @@ -842,7 +897,14 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; OTCuttlefishContext* cfshContext = [self contextForContainerName:config.containerName contextID:config.contextID]; [cfshContext handlePairingRestart:config]; [cfshContext startOctagonStateMachine]; - [cfshContext rpcPrepareIdentityAsApplicantWithConfiguration:config epoch:config.epoch reply:^(NSString * _Nullable peerID, NSData * _Nullable permanentInfo, NSData * _Nullable permanentInfoSig, NSData * _Nullable stableInfo, NSData * _Nullable stableInfoSig, NSError * _Nullable error) { + [cfshContext rpcPrepareIdentityAsApplicantWithConfiguration:config + epoch:config.epoch + reply:^(NSString * _Nullable peerID, + NSData * _Nullable permanentInfo, + NSData * _Nullable permanentInfoSig, + NSData * _Nullable stableInfo, + NSData * _Nullable stableInfoSig, + NSError * _Nullable error) { reply(peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error); }]; } @@ -850,13 +912,12 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; - (void)rpcJoinWithConfiguration:(OTJoiningConfiguration*)config vouchData:(NSData*)vouchData vouchSig:(NSData*)vouchSig - preapprovedKeys:(NSArray* _Nullable)preapprovedKeys reply:(void (^)(NSError * _Nullable error))reply { OTCuttlefishContext* cfshContext = [self contextForContainerName:config.containerName contextID:config.contextID]; [cfshContext handlePairingRestart:config]; [cfshContext startOctagonStateMachine]; - [cfshContext rpcJoin:vouchData vouchSig:vouchSig preapprovedKeys:preapprovedKeys reply:^(NSError * _Nullable error) { + [cfshContext rpcJoin:vouchData vouchSig:vouchSig reply:^(NSError * _Nullable error) { reply(error); }]; } @@ -980,8 +1041,12 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; secnotice("octagon-analytics", "Error fetching Octagon metadata: %@", metadataError); } values[OctagonAnalyticIcloudAccountState] = metadata ? @(metadata.icloudAccountState) : nil; + values[OctagonAnalyticCDPBitStatus] = metadata? @(metadata.cdpState) : nil; values[OctagonAnalyticsTrustState] = metadata ? @(metadata.trustState) : nil; + TPSyncingPolicy* syncingPolicy = [metadata getTPSyncingPolicy]; + values[OctagonAnalyticsUserControllableViewsSyncing] = syncingPolicy ? @(syncingPolicy.syncUserControllableViewsAsBoolean) : nil; + NSDate* healthCheck = [cuttlefishContext currentMemoizedLastHealthCheck]; values[OctagonAnalyticsLastHealthCheck] = @([CKKSAnalytics fuzzyDaysSinceDate:healthCheck]); @@ -1009,12 +1074,32 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; values[OctagonAnalyticsMIDOnMemoizedList] = @(midOnList); } - NSError* peersWithMIDError = nil; - NSNumber* peersWithMID = [cuttlefishContext numberOfPeersInModelWithMachineID:machineID error:&peersWithMIDError]; - if(peersWithMID && peersWithMIDError == nil) { - values[OctagonAnalyticsPeersWithMID] = peersWithMID; + NSError* egoPeerStatusError = nil; + TrustedPeersHelperEgoPeerStatus* egoPeerStatus = [cuttlefishContext egoPeerStatus:&egoPeerStatusError]; + + if(egoPeerStatus && egoPeerStatusError == nil) { + NSNumber* numberOfPeersWithMachineID = egoPeerStatus.peerCountsByMachineID[machineID] ?: @(0); + secnotice("octagon-metrics", "Number of peers with machineID (%@): %@", machineID, numberOfPeersWithMachineID); + values[OctagonAnalyticsPeersWithMID] = numberOfPeersWithMachineID; + + values[OctagonAnalyticsEgoMIDMatchesCurrentMID] = @([machineID isEqualToString:egoPeerStatus.egoPeerMachineID]); + secnotice("octagon-metrics", "MID match (current vs Octagon peer): %@, %@, %@", values[OctagonAnalyticsEgoMIDMatchesCurrentMID], machineID, egoPeerStatus.egoPeerMachineID); + + size_t totalPeers = 0; + for(NSNumber* peers in egoPeerStatus.peerCountsByMachineID.allValues) { + totalPeers += [peers longValue]; + } + + size_t totalViablePeers = 0; + for(NSNumber* peers in egoPeerStatus.viablePeerCountsByModelID.allValues) { + totalViablePeers += [peers longValue]; + } + secnotice("octagon-metrics", "Peers: %zu, viable peers %zu", totalPeers, totalViablePeers); + values[OctagonAnalyticsTotalPeers] = @(totalPeers); + values[OctagonAnalyticsTotalViablePeers] = @(totalViablePeers); + } else { - secnotice("octagon-analytics", "Error fetching how many peers have our MID: %@", midOnListError); + secnotice("octagon-analytics", "Error fetching how many peers have our MID: %@", egoPeerStatusError); } } } @@ -1062,6 +1147,11 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; values[OctagonAnalyticsKeychainSyncEnabled] = @([primaryAccount isEnabledForDataclass:ACAccountDataclassKeychainSync]); values[OctagonAnalyticsCloudKitProvisioned] = @([primaryAccount isProvisionedForDataclass:ACAccountDataclassCKDatabaseService]); values[OctagonAnalyticsCloudKitEnabled] = @([primaryAccount isEnabledForDataclass:ACAccountDataclassCKDatabaseService]); + + NSString *altDSID = primaryAccount.aa_altDSID; + if(altDSID) { + values[OctagonAnalyticsSecureBackupTermsAccepted] = @([getSecureBackupClass() getAcceptedTermsForAltDSID:altDSID withError:nil] != nil); + } } } @@ -1088,6 +1178,7 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; OTCliqueCDPContextTypeRecoveryKeyGenerate, OTCliqueCDPContextTypeRecoveryKeyNew, OTCliqueCDPContextTypeUpdatePasscode, + OTCliqueCDPContextTypeConfirmPasscodeCyrus, ]; }); return contextTypes; @@ -1107,7 +1198,7 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; SFAnalyticsActivityTracker *tracker = [[self.loggerClass logger] startLogSystemMetricsForActivityNamed:OctagonActivitySetRecoveryKey]; if (!self.sosEnabledForPlatform) { - secnotice("octagon-recovery", "Device is considered a limited peer, cannot enroll recovery key in Octagon"); + secnotice("octagon-recovery", "Device does not participate in SOS; cannot enroll recovery key in Octagon"); NSError* notFullPeerError = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorLimitedPeer userInfo:@{NSLocalizedDescriptionKey : @"Device is considered a limited peer, cannot enroll recovery key in Octagon"}]; [tracker stopWithEvent:OctagonEventRecoveryKey result:notFullPeerError]; reply(notFullPeerError); @@ -1176,8 +1267,18 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; [cfshContext startOctagonStateMachine]; [cfshContext joinWithRecoveryKey:recoveryKey reply:^(NSError *error) { - if (error.code == TrustedPeersHelperErrorCodeNotEnrolled && [error.domain isEqualToString:TrustedPeersHelperErrorDomain]) { - // If we hit this error, let's reset and establish octagon then enroll this recovery key in the new circle + if ((error.code == TrustedPeersHelperErrorCodeNotEnrolled || error.code == TrustedPeersHelperErrorCodeUntrustedRecoveryKeys) + && [error.domain isEqualToString:TrustedPeersHelperErrorDomain]){ + // If we hit either of these errors, and the local device thinks it should be able to set a recovery key, + // let's reset and establish octagon then enroll this recovery key in the new circle + + if (!self.sosEnabledForPlatform) { + secerror("octagon: recovery key is not enrolled in octagon, and current device can't set recovery keys"); + [tracker stopWithEvent:OctagonEventJoinRecoveryKeyCircleResetFailed result:error]; + reply(error); + return; + } + secerror("octagon, recovery key is not enrolled in octagon, resetting octagon circle"); [[self.loggerClass logger] logResultForEvent:OctagonEventJoinRecoveryKeyCircleReset hardFailure:NO result:error]; @@ -1190,25 +1291,19 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; } else { // Now enroll the recovery key secnotice("octagon", "attempting enrolling recovery key"); - if (self.sosEnabledForPlatform) { - [self createRecoveryKey:containerName contextID:contextID recoveryKey:recoveryKey reply:^(NSError *enrollError) { - if(enrollError){ - secerror("octagon, failed to enroll new recovery key: %@", enrollError); - [tracker stopWithEvent:OctagonEventJoinRecoveryKeyEnrollFailed result:enrollError]; - reply(enrollError); - return; - }else{ - secnotice("octagon", "successfully enrolled recovery key"); - [tracker stopWithEvent:OctagonEventRecoveryKey result:nil]; - reply (nil); - return; - } - }]; - } else { - secnotice("octagon", "Limited Peer, can't enroll recovery key"); - reply (nil); - return; - } + [self createRecoveryKey:containerName contextID:contextID recoveryKey:recoveryKey reply:^(NSError *enrollError) { + if(enrollError){ + secerror("octagon, failed to enroll new recovery key: %@", enrollError); + [tracker stopWithEvent:OctagonEventJoinRecoveryKeyEnrollFailed result:enrollError]; + reply(enrollError); + return; + }else{ + secnotice("octagon", "successfully enrolled recovery key"); + [tracker stopWithEvent:OctagonEventRecoveryKey result:nil]; + reply (nil); + return; + } + }]; } }]; } else { @@ -1219,17 +1314,22 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; }]; } -- (void)healthCheck:(NSString *)container context:(NSString *)context skipRateLimitingCheck:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError *_Nullable error))reply +- (void)xpc24HrNotification { - [self xpc24HrNotification:container context:context skipRateLimitingCheck:skipRateLimitingCheck reply:reply]; + secnotice("octagon-health", "Received 24hr xpc notification"); + + [self healthCheck:OTCKContainerName context:OTDefaultContext skipRateLimitingCheck:NO reply:^(NSError * _Nullable error) { + if(error) { + secerror("octagon: error attempting to check octagon health: %@", error); + } else { + secnotice("octagon", "health check success"); + } + }]; } - -- (void)xpc24HrNotification:(NSString* _Nullable)containerName context:(NSString*)context skipRateLimitingCheck:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError *error))reply +- (void)healthCheck:(NSString *)container context:(NSString *)context skipRateLimitingCheck:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError *_Nullable error))reply { - secnotice("octagon-health", "Received 24 xpc notification"); - - OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:context]; + OTCuttlefishContext* cfshContext = [self contextForContainerName:container contextID:context]; secnotice("octagon", "notifying container of change"); @@ -1253,6 +1353,9 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; { for(OTCuttlefishContext* context in self.contexts.allValues) { [context.stateMachine haltOperation]; + + // Also, clear the viewManager strong pointer + [context clearCKKSViewManager]; } } @@ -1275,27 +1378,12 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; return true; } -- (void)attemptSosUpgrade:(NSString* _Nullable)containerName - context:(NSString*)context - reply:(void (^)(NSError* error))reply - -{ - secnotice("octagon-sos", "Attempting sos upgrade"); - OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:context]; - - [cfshContext startOctagonStateMachine]; - - [cfshContext attemptSOSUpgrade:^(NSError *error) { - reply(error); - }]; -} - - (void)waitForOctagonUpgrade:(NSString* _Nullable)containerName context:(NSString*)context reply:(void (^)(NSError* error))reply { - secnotice("octagon-sos", "waitForOctagonUpgrade"); + secnotice("octagon-sos", "Attempting wait for octagon upgrade"); OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:context]; [cfshContext startOctagonStateMachine]; @@ -1305,27 +1393,6 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; }]; } -- (OTFollowupContextType)cliqueCDPTypeToFollowupContextType:(OTCliqueCDPContextType)type -{ - if ([type isEqualToString:OTCliqueCDPContextTypeNone]) { - return OTFollowupContextTypeNone; - } else if ([type isEqualToString:OTCliqueCDPContextTypeSignIn]) { - return OTFollowupContextTypeNone; - } else if ([type isEqualToString:OTCliqueCDPContextTypeRepair]) { - return OTFollowupContextTypeStateRepair; - } else if ([type isEqualToString:OTCliqueCDPContextTypeFinishPasscodeChange]) { - return OTFollowupContextTypeOfflinePasscodeChange; - } else if ([type isEqualToString:OTCliqueCDPContextTypeRecoveryKeyGenerate]) { - return OTFollowupContextTypeRecoveryKeyRepair; - } else if ([type isEqualToString:OTCliqueCDPContextTypeRecoveryKeyNew]) { - return OTFollowupContextTypeRecoveryKeyRepair; - } else if ([type isEqualToString:OTCliqueCDPContextTypeUpdatePasscode]) { - return OTFollowupContextTypeNone; - } else { - return OTFollowupContextTypeNone; - } -} - - (void)postCDPFollowupResult:(BOOL)success type:(OTCliqueCDPContextType)type error:(NSError * _Nullable)error @@ -1333,8 +1400,6 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; contextName:(NSString *)contextName reply:(void (^)(NSError *error))reply { - OTCuttlefishContext *cuttlefishContext = [self contextForContainerName:containerName contextID:contextName]; - NSString* metricName = [NSString stringWithFormat:@"%@%@", OctagonAnalyticsCDPStateRun, type]; NSString* countName = [NSString stringWithFormat:@"%@%@Tries", OctagonAnalyticsCDPStateRun, type]; @@ -1349,9 +1414,6 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; [[CKKSAnalytics logger] setNumberProperty:NULL forKey:countName]; } - // Clear all CFU state variables, too - [cuttlefishContext clearPendingCFUFlags]; - // Always return without error reply(nil); } @@ -1366,6 +1428,214 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; reply(NULL); } +- (void)refetchCKKSPolicy:(NSString * _Nullable)containerName + contextID:(nonnull NSString *)contextID + reply:(nonnull void (^)(NSError * _Nullable))reply { + secnotice("octagon-ckks", "refetch-ckks-policy"); + + if(!containerName) { + containerName = OTCKContainerName; + } + + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply([NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcRefetchCKKSPolicy:^(NSError* error) { + secnotice("octagon-ckks", "refetch-ckks-policy result: %@", error ?: @"no error"); + reply(error); + }]; +} + +- (void)getCDPStatus:(NSString * _Nullable)containerName + contextID:(nonnull NSString *)contextID + reply:(nonnull void (^)(OTCDPStatus, NSError * _Nullable))reply { + secnotice("octagon-cdp", "get-cdp-status"); + + if(!containerName) { + containerName = OTCKContainerName; + } + + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply(OTCDPStatusUnknown, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + NSError* error = nil; + OTCDPStatus status = [cfshContext getCDPStatus:&error]; + + reply(status, error); +} + + +- (void)setCDPEnabled:(NSString * _Nullable)containerName + contextID:(nonnull NSString *)contextID + reply:(nonnull void (^)(NSError * _Nullable))reply { + secnotice("octagon-cdp", "set-cdp-enabled"); + if(!containerName) { + containerName = OTCKContainerName; + } + + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply([NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + NSError* localError = nil; + [cfshContext setCDPEnabled:&localError]; + + reply(localError); +} + +- (void)fetchEscrowRecords:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + forceFetch:(BOOL)forceFetch + reply:(nonnull void (^)(NSArray * _Nullable records, + NSError * _Nullable error))reply { + + secnotice("octagon-fetch-escrow-records", "fetching records"); + if(!containerName) { + containerName = OTCKContainerName; + } + + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply(nil, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcFetchAllViableEscrowRecords:forceFetch reply:^(NSArray * _Nullable records, NSError * _Nullable error) { + if(error) { + secerror("octagon-fetch-escrow-records: error fetching records: %@", error); + reply(nil, error); + return; + } + secnotice("octagon-fetch-escrow-records", "successfully fetched records"); + reply(records, nil); + }]; +} + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply { + + secnotice("octagon-remove-escrow-cache", "beginning removing escrow cache!"); + if(!containerName) { + containerName = OTCKContainerName; + } + + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply([NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcInvalidateEscrowCache:^(NSError * _Nullable invalidateError) { + if(invalidateError) { + secerror("octagon-remove-escrow-cache: error invalidating escrow cache: %@", invalidateError); + reply(invalidateError); + return; + } + secnotice("octagon-remove-escrow-caches", "successfully invalidated escrow cache"); + reply(nil); + }]; +} + +- (void)setUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + enabled:(BOOL)enabled + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply +{ + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcSetUserControllableViewsSyncingStatus:enabled reply:^(BOOL areSyncing, NSError * _Nullable error) { + if(error) { + secerror("octagon-user-controllable-views: error setting status: %@", error); + reply(NO, error); + return; + } + + secnotice("octagon-user-controllable-views", "successfully set status to: %@", areSyncing ? @"enabled" : @"paused"); + reply(areSyncing, nil); + }]; +} + +- (void)fetchUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply +{ + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcFetchUserControllableViewsSyncingStatus:^(BOOL areSyncing, NSError * _Nullable error) { + if(error) { + secerror("octagon-user-controllable-views: error fetching status: %@", error); + reply(NO, error); + return; + } + + secnotice("octagon-user-controllable-views", "successfully fetched status as: %@", areSyncing ? @"enabled" : @"paused"); + reply(areSyncing, nil); + }]; +} + +- (void)resetAccountCDPContents:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(NSError* _Nullable error))reply +{ + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply([NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcResetAccountCDPContents:^(NSError * _Nullable error) { + if(error) { + secerror("octagon-reset-account-cdp-contents: error resetting account cdp contents: %@", error); + reply(error); + return; + } + + secnotice("octagon-reset-account-cdp-contents", "successfully reset account cdp contents"); + reply(nil); + }]; +} + @end #endif diff --git a/keychain/ot/OTModifyUserControllableViewStatusOperation.h b/keychain/ot/OTModifyUserControllableViewStatusOperation.h new file mode 100644 index 00000000..17ccd75f --- /dev/null +++ b/keychain/ot/OTModifyUserControllableViewStatusOperation.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if OCTAGON + +#import + +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ot/OTOperationDependencies.h" +#import "keychain/ot/OTOperationDependencies.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface OTModifyUserControllableViewStatusOperation : CKKSGroupOperation + +// Pass 'unknown' to intendedViewStatus to set your peer view status to the opinion of your peers +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedViewStatus:(TPPBPeerStableInfo_UserControllableViewStatus)intendedViewStatus + intendedState:(OctagonState*)intendedState + peerMissingState:(OctagonState*)peerMissingState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ot/OTModifyUserControllableViewStatusOperation.m b/keychain/ot/OTModifyUserControllableViewStatusOperation.m new file mode 100644 index 00000000..c0e77b23 --- /dev/null +++ b/keychain/ot/OTModifyUserControllableViewStatusOperation.m @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if OCTAGON + +#import +#import "keychain/ckks/CKKSAnalytics.h" +#import "keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h" +#import "keychain/ot/OTModifyUserControllableViewStatusOperation.h" +#import "keychain/ot/OTStates.h" +#import "keychain/ot/ObjCImprovements.h" +#import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" + +@interface OTModifyUserControllableViewStatusOperation () +@property OTOperationDependencies* deps; + +@property OctagonState* peerMissingState; + +@property TPPBPeerStableInfo_UserControllableViewStatus intendedViewStatus; +@end + +@implementation OTModifyUserControllableViewStatusOperation +@synthesize intendedState = _intendedState; +@synthesize nextState = _nextState; + +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedViewStatus:(TPPBPeerStableInfo_UserControllableViewStatus)intendedViewStatus + intendedState:(OctagonState*)intendedState + peerMissingState:(OctagonState*)peerMissingState + errorState:(OctagonState*)errorState +{ + if ((self = [super init])) { + _deps = dependencies; + + _intendedViewStatus = intendedViewStatus; + + _intendedState = intendedState; + _peerMissingState = peerMissingState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + + if(self.intendedViewStatus == TPPBPeerStableInfo_UserControllableViewStatus_FOLLOWING) { +#if TARGET_OS_WATCH || TARGET_OS_TV + // Watches and TVs want to be able to set the FOLLOWING state + [self performWithStatus:self.intendedViewStatus]; +#else + // For other platforms, we want to determine the actual state by asking + WEAKIFY(self); + + // Should we ask SOS? Or Octagon? + if(self.deps.sosAdapter.sosEnabled) { + NSError* error = nil; + BOOL safariViewEnabled = [self.deps.sosAdapter safariViewSyncingEnabled:&error]; + + if(error) { + secerror("octagon-ckks: Unable to fetch SOS Safari view status: %@", error); + self.error = error; + return; + } + + secnotice("octagon-ckks", "Currently SOS believes the safari view is '%@'", safariViewEnabled ? @"enabled" : @"disabled"); + + TPPBPeerStableInfo_UserControllableViewStatus status = safariViewEnabled ? + TPPBPeerStableInfo_UserControllableViewStatus_ENABLED : + TPPBPeerStableInfo_UserControllableViewStatus_DISABLED; + + [self performWithStatus:status]; + return; + } + + secnotice("octagon-ckks", "Determining peers' user-controllable views policy"); + + [self.deps.cuttlefishXPCWrapper fetchCurrentPolicyWithContainer:self.deps.containerName + context:self.deps.contextID + modelIDOverride:nil + reply:^(TPSyncingPolicy* _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, + NSError* _Nullable error) { + STRONGIFY(self); + + if(error) { + secnotice("octagon-ckks", "Determining peers' user-controllable views policy failed: %@", error); + self.error = error; + return; + } + + secnotice("octagon-ckks", "Retrieved peers' user-controllable views policy as: %@", + TPPBPeerStableInfo_UserControllableViewStatusAsString(userControllableViewStatusOfPeers)); + + [self performWithStatus:userControllableViewStatusOfPeers]; + return; + }]; +#endif + + } else { + [self performWithStatus:self.intendedViewStatus]; + } +} + +- (void)performWithStatus:(TPPBPeerStableInfo_UserControllableViewStatus)intendedViewStatus +{ + WEAKIFY(self); + + secnotice("octagon-ckks", "Setting user-controllable views to %@", TPPBPeerStableInfo_UserControllableViewStatusAsString(self.intendedViewStatus)); + + [self.deps.cuttlefishXPCWrapper updateWithContainer:self.deps.containerName + context:self.deps.contextID + deviceName:nil + serialNumber:nil + osVersion:nil + policyVersion:nil + policySecrets:nil + syncUserControllableViews:[NSNumber numberWithInt:intendedViewStatus] + reply:^(TrustedPeersHelperPeerState* peerState, TPSyncingPolicy* syncingPolicy, NSError* error) { + STRONGIFY(self); + if(error || !syncingPolicy) { + secerror("octagon-ckks: setting user-controllable views status errored: %@", error); + self.error = error; + + if([self.deps.lockStateTracker isLockedError:self.error]) { + secnotice("octagon-ckks", "Updating user-controllable view status failed because of lock state, will retry once unlocked: %@", self.error); + OctagonPendingFlag* pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptUserControllableViewStatusUpgrade + conditions:OctagonPendingConditionsDeviceUnlocked]; + + [self.deps.flagHandler handlePendingFlag:pendingFlag]; + } + if(peerState.peerStatus & (TPPeerStatusExcluded | TPPeerStatusUnknown)) { + secnotice("octagon-ckks", "Updating user-controllable view status failed because our self peer is excluded or missing"); + self.nextState = self.peerMissingState; + } + return; + } + + secnotice("octagon-ckks", "Received syncing policy %@ with view list: %@", syncingPolicy, syncingPolicy.viewList); + + NSError* stateError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&stateError]; + + if(stateError) { + secerror("octagon: failed to save policy+views: %@", stateError); + self.error = stateError; + return; + } + + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; + + self.nextState = self.intendedState; + }]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ot/OTOperationDependencies.h b/keychain/ot/OTOperationDependencies.h index e9e5aeb6..373177f6 100644 --- a/keychain/ot/OTOperationDependencies.h +++ b/keychain/ot/OTOperationDependencies.h @@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN @property id authKitAdapter; @property id deviceInformationAdapter; @property (readonly) CuttlefishXPCWrapper* cuttlefishXPCWrapper; -@property CKKSViewManager* viewManager; +@property (readonly, weak) CKKSViewManager* viewManager; @property CKKSLockStateTracker* lockStateTracker; @property Class escrowRequestClass; diff --git a/keychain/ot/OTPreloadOctagonKeysOperation.h b/keychain/ot/OTPreloadOctagonKeysOperation.h new file mode 100644 index 00000000..cd2e7a6b --- /dev/null +++ b/keychain/ot/OTPreloadOctagonKeysOperation.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if OCTAGON + +#import + +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" +#import "keychain/ot/OTOperationDependencies.h" + +@class OTCuttlefishContext; + +NS_ASSUME_NONNULL_BEGIN + +@interface OTPreloadOctagonKeysOperation : CKKSGroupOperation +@property OctagonState* nextState; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ot/OTPreloadOctagonKeysOperation.m b/keychain/ot/OTPreloadOctagonKeysOperation.m new file mode 100644 index 00000000..58952f96 --- /dev/null +++ b/keychain/ot/OTPreloadOctagonKeysOperation.m @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if OCTAGON + +#import + +#import +#import "keychain/ot/OTPreloadOctagonKeysOperation.h" +#import "keychain/ot/OTClientStateMachine.h" +#import "keychain/ot/OTCuttlefishContext.h" +#import "keychain/ot/OTFetchCKKSKeysOperation.h" +#import "keychain/ot/OTDefines.h" +#import "keychain/ot/OTConstants.h" +#import "keychain/ot/OctagonCKKSPeerAdapter.h" +#import "utilities/debugging.h" +#import +#import + +#import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" +#import "keychain/ot/ObjCImprovements.h" +#import "keychain/securityd/SOSCloudCircleServer.h" + +@interface OTPreloadOctagonKeysOperation () +@property OTOperationDependencies* deps; + +@property NSOperation* finishOp; +@end + +@implementation OTPreloadOctagonKeysOperation +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if((self = [super init])) { + _deps = dependencies; + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + secnotice("octagon-preload-keys", "Beginning operation that preloads the SOSAccount with newly created Octagon Keys"); + + self.finishOp = [[NSOperation alloc] init]; + [self dependOnBeforeGroupFinished:self.finishOp]; + + if(!self.deps.sosAdapter.sosEnabled) { + self.error = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorSOSAdapter userInfo:@{NSLocalizedDescriptionKey : @"sos adapter not enabled"}]; + [self runBeforeGroupFinished:self.finishOp]; + return; + } + + NSError* fetchSelfPeersError = nil; + CKKSSelves *selfPeers = [self.deps.octagonAdapter fetchSelfPeers:&fetchSelfPeersError]; + if((!selfPeers) || fetchSelfPeersError) { + secnotice("octagon-preload-keys", "failed to retrieve self peers: %@", fetchSelfPeersError); + self.error = fetchSelfPeersError; + [self runBeforeGroupFinished:self.finishOp]; + return; + } + + id currentSelfPeer = selfPeers.currentSelf; + if(currentSelfPeer == nil) { + secnotice("octagon-preload-keys", "failed to retrieve current self"); + self.error = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorOctagonAdapter userInfo: @{ NSLocalizedDescriptionKey : @"failed to retrieve current self"}]; + [self runBeforeGroupFinished:self.finishOp]; + return; + } + + NSError* updateError = nil; + BOOL ret = [self.deps.sosAdapter preloadOctagonKeySetOnAccount:currentSelfPeer error:&updateError]; + if(!ret) { + self.error = updateError; + [self runBeforeGroupFinished:self.finishOp]; + return; + } + + self.nextState = self.intendedState; + [self runBeforeGroupFinished:self.finishOp]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ot/OTPrepareOperation.h b/keychain/ot/OTPrepareOperation.h index 9f03512a..a18e23a0 100644 --- a/keychain/ot/OTPrepareOperation.h +++ b/keychain/ot/OTPrepareOperation.h @@ -24,6 +24,7 @@ #if OCTAGON #import +#import #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ot/OctagonStateMachineHelpers.h" @@ -41,6 +42,7 @@ NS_ASSUME_NONNULL_BEGIN intendedState:(OctagonState*)intendedState errorState:(OctagonState*)errorState deviceInfo:(OTDeviceInformation*)deviceInfo + policyOverride:(TPPolicyVersion* _Nullable)policyOverride epoch:(uint64_t)epoch; @property (nonatomic) uint64_t epoch; @@ -52,6 +54,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable) NSData* stableInfo; @property (nullable) NSData* stableInfoSig; +@property (nullable) TPPolicyVersion* policyOverride; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTPrepareOperation.m b/keychain/ot/OTPrepareOperation.m index 2b34ec23..f6de077b 100644 --- a/keychain/ot/OTPrepareOperation.m +++ b/keychain/ot/OTPrepareOperation.m @@ -28,7 +28,6 @@ #import #import "keychain/ot/OTCuttlefishContext.h" -#import "keychain/ot/OTFetchViewsOperation.h" #import "keychain/ot/OTOperationDependencies.h" #import "keychain/ot/OTPrepareOperation.h" @@ -48,6 +47,7 @@ intendedState:(OctagonState*)intendedState errorState:(OctagonState*)errorState deviceInfo:(OTDeviceInformation*)deviceInfo + policyOverride:(TPPolicyVersion* _Nullable)policyOverride epoch:(uint64_t)epoch { if((self = [super init])) { @@ -58,6 +58,8 @@ _intendedState = intendedState; _nextState = errorState; + + _policyOverride = policyOverride; } return self; } @@ -133,6 +135,9 @@ secerror("octagon: failed to save 'attempted join' state: %@", persistError); } + // Note: we pass syncUserControllableViews as FOLLOWING here, with the intention that + // it will be set later, when this peer decides who it trusts and accepts their value. + [self.deps.cuttlefishXPCWrapper prepareWithContainer:self.deps.containerName context:self.deps.contextID epoch:self.epoch @@ -143,11 +148,18 @@ deviceName:self.deviceInfo.deviceName serialNumber:self.deviceInfo.serialNumber osVersion:self.deviceInfo.osVersion - policyVersion:nil + policyVersion:self.policyOverride policySecrets:nil + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_FOLLOWING signingPrivKeyPersistentRef:signingKeyPersistRef encPrivKeyPersistentRef:encryptionKeyPersistRef - reply:^(NSString * _Nullable peerID, NSData * _Nullable permanentInfo, NSData * _Nullable permanentInfoSig, NSData * _Nullable stableInfo, NSData * _Nullable stableInfoSig, NSError * _Nullable error) { + reply:^(NSString * _Nullable peerID, + NSData * _Nullable permanentInfo, + NSData * _Nullable permanentInfoSig, + NSData * _Nullable stableInfo, + NSData * _Nullable stableInfoSig, + TPSyncingPolicy* _Nullable syncingPolicy, + NSError * _Nullable error) { STRONGIFY(self); [[CKKSAnalytics logger] logResultForEvent:OctagonEventPrepareIdentity hardFailure:true result:error]; if(error) { @@ -163,27 +175,28 @@ self.stableInfoSig = stableInfoSig; NSError* localError = nil; - BOOL persisted = [self.deps.stateHolder persistNewEgoPeerID:peerID error:&localError]; + + secnotice("octagon-ckks", "New syncing policy: %@ views: %@", syncingPolicy, syncingPolicy.viewList); + + BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.peerID = peerID; + + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&localError]; + if(!persisted || localError) { - secnotice("octagon", "Couldn't persist peer ID: %@", localError); + secnotice("octagon", "Couldn't persist metadata: %@", localError); self.error = localError; [self runBeforeGroupFinished:self.finishedOp]; - } else { - WEAKIFY(self); - - CKKSResultOperation *doneOp = [CKKSResultOperation named:@"ot-prepare" - withBlock:^{ - STRONGIFY(self); - self.nextState = self.intendedState; - }]; - - OTFetchViewsOperation *fetchViewsOp = [[OTFetchViewsOperation alloc] initWithDependencies:self.deps]; - [self runBeforeGroupFinished:fetchViewsOp]; - [doneOp addDependency:fetchViewsOp]; - [self runBeforeGroupFinished:doneOp]; - [self.finishedOp addDependency:doneOp]; - [self runBeforeGroupFinished:self.finishedOp]; + return; } + + // Let CKKS know of the new policy, so it can spin up + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; + + self.nextState = self.intendedState; + [self runBeforeGroupFinished:self.finishedOp]; } }]; } diff --git a/keychain/ot/OTRamping.m b/keychain/ot/OTRamping.m index 11fdfedb..72a7d8c3 100644 --- a/keychain/ot/OTRamping.m +++ b/keychain/ot/OTRamping.m @@ -87,8 +87,7 @@ static NSString* kRampPriorityKey = @"RampPriority"; fetchRecordRecordsOperationClass:(Class) fetchRecordRecordsOperationClass { - self = [super init]; - if(self){ + if ((self = [super init])) { _container = container; _recordName = [recordName copy]; _localSettingName = [localSettingName copy]; diff --git a/keychain/ot/OTResetCKKSZonesLackingTLKsOperation.m b/keychain/ot/OTResetCKKSZonesLackingTLKsOperation.m index 0a09dd2f..84883ebf 100644 --- a/keychain/ot/OTResetCKKSZonesLackingTLKsOperation.m +++ b/keychain/ot/OTResetCKKSZonesLackingTLKsOperation.m @@ -49,7 +49,8 @@ }]; [self dependOnBeforeGroupFinished:self.finishedOp]; - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"continue-ckks-resets" @@ -73,7 +74,8 @@ for(CKKSCurrentKeySet* incompleteKeySet in incompleteKeySets) { if(incompleteKeySet.error == nil) { - CKKSKeychainView* viewMatchingSet = [self.deps.viewManager findView:incompleteKeySet.viewName]; + CKKSViewManager* viewManager = self.deps.viewManager; + CKKSKeychainView* viewMatchingSet = [viewManager findView:incompleteKeySet.viewName]; if(!viewMatchingSet) { secnotice("octagon-ckks", "No view matching viewset %@?", incompleteKeySet); @@ -83,13 +85,10 @@ if(incompleteKeySet.currentTLKPointer != nil && incompleteKeySet.tlk == nil) { - BOOL otherDevicesAlive = [viewMatchingSet otherDevicesReportHavingTLKs:incompleteKeySet]; - if(otherDevicesAlive) { - secnotice("octagon-ckks", "Recently active devices claim to have TLK from key set %@; not scheduling for reset", incompleteKeySet); - } else { - secnotice("octagon-ckks", "Key set %@ has no TLK; scheduling for reset", incompleteKeySet); - [viewsToReset addObject:viewMatchingSet]; - } + // We used to not reset the TLKs if there was a recent device claiming to have them, but + // in our Octagon-primary world, an Octagon reset should take precedence over existing Cloud-based data + secnotice("octagon-ckks", "Key set %@ has no TLK; scheduling for reset", incompleteKeySet); + [viewsToReset addObject:viewMatchingSet]; } } else { secnotice("octagon-ckks", "Error loading key set %@; not attempting reset", incompleteKeySet); @@ -115,7 +114,9 @@ // Use an intermediary operation, just to ensure we have a timeout CKKSResultOperation* waitOp = [CKKSResultOperation named:[NSString stringWithFormat:@"wait-for-%@", view.zoneName] - withBlock:^{}]; + withBlock:^{ + secnotice("octagon-ckks", "Successfully reset %@", view); + }]; [waitOp timeout:120*NSEC_PER_SEC]; [waitOp addDependency:op]; [self.operationQueue addOperation:waitOp]; diff --git a/keychain/ot/OTSOSAdapter.h b/keychain/ot/OTSOSAdapter.h index dddda03b..0403f382 100644 --- a/keychain/ot/OTSOSAdapter.h +++ b/keychain/ot/OTSOSAdapter.h @@ -12,23 +12,31 @@ NS_ASSUME_NONNULL_BEGIN - (SOSCCStatus)circleStatus:(NSError**)error; - (id _Nullable)currentSOSSelf:(NSError**)error; - (NSSet>* _Nullable)fetchTrustedPeers:(NSError**)error; -- (void)updateOctagonKeySetWithAccount:(id)currentSelfPeer error:(NSError**)error; +- (BOOL)updateOctagonKeySetWithAccount:(id)currentSelfPeer error:(NSError**)error; +- (BOOL)preloadOctagonKeySetOnAccount:(id)currentSelfPeer error:(NSError**)error; +- (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error; + +- (BOOL)safariViewSyncingEnabled:(NSError**)error __attribute__((swift_error(nonnull_error))); @end @interface OTSOSActualAdapter : NSObject - (instancetype)init NS_UNAVAILABLE; - (instancetype)initAsEssential:(BOOL)essential; -// Helper methods -+ (NSArray*)peerPublicSigningKeySPKIs:(NSSet>* _Nullable)peers; - +// Helper methods. + (NSSet*)sosCKKSViewList; @end + // This adapter is for a platform which does not have SOS (e.g., aTV, Watch, HomePod) @interface OTSOSMissingAdapter : NSObject @end +// Helper code +@interface OTSOSAdapterHelpers : NSObject ++ (NSArray* _Nullable)peerPublicSigningKeySPKIsForCircle:(id)sosAdapter error:(NSError**)error; +@end + NS_ASSUME_NONNULL_END #endif // OCTAGON diff --git a/keychain/ot/OTSOSAdapter.m b/keychain/ot/OTSOSAdapter.m index 69ed211f..51ec8864 100644 --- a/keychain/ot/OTSOSAdapter.m +++ b/keychain/ot/OTSOSAdapter.m @@ -98,7 +98,7 @@ code:CKKSNoPeersAvailable description:@"Not in SOS circle, but no error returned"]; } - secerror("octagon-sos: Not in circle : %d %@", circleStatus, localerror); + secerror("octagon-sos: Not in circle : %@ %@", SOSAccountGetSOSCCStatusString(circleStatus), localerror); if(error) { *error = localerror; } @@ -229,12 +229,60 @@ return peerSet; } -- (void)updateOctagonKeySetWithAccount:(id)currentSelfPeer error:(NSError**)error { + +- (BOOL)preloadOctagonKeySetOnAccount:(id)currentSelfPeer error:(NSError**)error { + // in case we don't have the keys, don't try to update them + if (currentSelfPeer.publicSigningKey.secKey == NULL || currentSelfPeer.publicEncryptionKey.secKey == NULL) { + secnotice("octagon-preload-keys", "no octagon keys available skipping updating SOS record"); + return YES; + } + + __block CFDataRef signingFullKey = CFBridgingRetain(currentSelfPeer.signingKey.keyData); + __block CFDataRef encryptionFullKey = CFBridgingRetain(currentSelfPeer.encryptionKey.keyData); + __block SecKeyRef octagonSigningPubSecKey = CFRetainSafe(currentSelfPeer.publicSigningKey.secKey); + __block SecKeyRef octagonEncryptionPubSecKey = CFRetainSafe(currentSelfPeer.publicEncryptionKey.secKey); + __block SecKeyRef signingFullKeyRef = CFRetainSafe(currentSelfPeer.signingKey.secKey); + __block SecKeyRef encryptionFullKeyRef = CFRetainSafe(currentSelfPeer.encryptionKey.secKey); + + SFAnalyticsActivityTracker *tracker = [[[CKKSAnalytics class] logger] startLogSystemMetricsForActivityNamed:OctagonSOSAdapterUpdateKeys]; + + __block BOOL ret; + __block NSError *localError = nil; + + /* WARNING! Please be very very careful passing keys to this routine. Note the slightly different variations of keys*/ + SOSCCPerformPreloadOfAllOctagonKeys(signingFullKey, encryptionFullKey, + signingFullKeyRef, encryptionFullKeyRef, + octagonSigningPubSecKey, octagonEncryptionPubSecKey, + ^(CFErrorRef cferror) { + [tracker stopWithEvent: OctagonSOSAdapterUpdateKeys result:(__bridge NSError * _Nullable)(cferror)]; + if(cferror) { + secerror("octagon-preload-keys: failed to preload Octagon keys in SOS:%@", cferror); + ret = NO; + localError = (__bridge NSError *)cferror; + } else { + ret = YES; + secnotice("octagon-preload-keys", "successfully preloaded Octagon keys in SOS!"); + } + CFRelease(signingFullKey); + CFRelease(encryptionFullKey); + CFRelease(octagonSigningPubSecKey); + CFRelease(octagonEncryptionPubSecKey); + CFRelease(signingFullKeyRef); + CFRelease(encryptionFullKeyRef); + }); + if (error) { + *error = localError; + } + return ret; + +} + +- (BOOL)updateOctagonKeySetWithAccount:(id)currentSelfPeer error:(NSError**)error { // in case we don't have the keys, don't try to update them if (currentSelfPeer.publicSigningKey.secKey == NULL || currentSelfPeer.publicEncryptionKey.secKey == NULL) { secnotice("octagon-sos", "no octagon keys available skipping updating SOS record"); - return; + return YES; } __block CFDataRef signingFullKey = CFBridgingRetain(currentSelfPeer.signingKey.keyData); @@ -246,15 +294,21 @@ SFAnalyticsActivityTracker *tracker = [[[CKKSAnalytics class] logger] startLogSystemMetricsForActivityNamed:OctagonSOSAdapterUpdateKeys]; + __block BOOL ret; + __block NSError *localError = nil; + /* WARNING! Please be very very careful passing keys to this routine. Note the slightly different variations of keys*/ SOSCCPerformUpdateOfAllOctagonKeys(signingFullKey, encryptionFullKey, signingPublicKey, encryptionPublicKey, octagonSigningPubSecKey, octagonEncryptionPubSecKey, - ^(CFErrorRef error) { - [tracker stopWithEvent: OctagonSOSAdapterUpdateKeys result:(__bridge NSError * _Nullable)(error)]; - if(error){ - secerror("octagon-sos: failed to update Octagon keys in SOS:%@", error); - }else { + ^(CFErrorRef cferror) { + [tracker stopWithEvent: OctagonSOSAdapterUpdateKeys result:(__bridge NSError * _Nullable)(cferror)]; + if(cferror) { + secerror("octagon-sos: failed to update Octagon keys in SOS:%@", cferror); + ret = NO; + localError = (__bridge NSError *)cferror; + } else { + ret = YES; secnotice("octagon-sos", "successfully updated Octagon keys in SOS!"); } CFRelease(signingFullKey); @@ -264,6 +318,29 @@ CFRelease(octagonSigningPubSecKey); CFRelease(octagonEncryptionPubSecKey); }); + if (error) { + *error = localError; + } + return ret; +} + +- (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error +{ + CFErrorRef cferror = nil; + bool result = SOSCCSetCKKS4AllStatus(status, &cferror); + + NSError* localerror = CFBridgingRelease(cferror); + + if(!result || localerror) { + secerror("octagon-sos: failed to update CKKS4All status in SOS: %@", localerror); + } else { + secnotice("octagon-sos", "successfully updated CKKS4All status in SOS to '%@'", status ? @"supported" : @"not supported"); + } + + if(error && localerror) { + *error = localerror; + } + return result; } - (void)registerForPeerChangeUpdates:(nonnull id)listener { @@ -303,20 +380,21 @@ return result; } -+ (NSArray*)peerPublicSigningKeySPKIs:(NSSet>* _Nullable)peerSet +- (BOOL)safariViewSyncingEnabled:(NSError**)error { - NSMutableArray* publicSigningSPKIs = [NSMutableArray array]; + CFErrorRef viewCFError = NULL; + SOSViewResultCode result = SOSCCView(kSOSViewAutofillPasswords, kSOSCCViewQuery, &viewCFError); - for(id peer in peerSet) { - NSData* spki = [peer.publicSigningKey encodeSubjectPublicKeyInfo]; - if(!spki) { - secerror("octagon-sos: Can't create SPKI for peer: %@", peer); + if(viewCFError) { + if(error) { + *error = CFBridgingRelease(viewCFError); } else { - secerror("octagon-sos: Created SPKI for peer: %@", peer); - [publicSigningSPKIs addObject:spki]; + CFReleaseNull(viewCFError); } + return NO; } - return publicSigningSPKIs; + + return result == kSOSCCViewMember; } @end @@ -361,12 +439,23 @@ return nil; } -- (void)updateOctagonKeySetWithAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { +- (BOOL)updateOctagonKeySetWithAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { if(error) { *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented description:@"SOS unsupported on this platform"]; } + return NO; +} + +- (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error +{ + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + description:@"SOS unsupported on this platform"]; + } + return NO; } - (CKKSSelves * _Nullable)fetchSelfPeers:(NSError * _Nullable __autoreleasing * _Nullable)error @@ -406,7 +495,67 @@ trustedPeersError:unimplementedError]; } +- (BOOL)safariViewSyncingEnabled:(NSError**)error +{ + return NO; +} +- (BOOL)preloadOctagonKeySetOnAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + description:@"SOS unsupported on this platform"]; + } + return NO; +} +@end + +@implementation OTSOSAdapterHelpers + ++ (NSArray*)peerPublicSigningKeySPKIs:(NSSet>* _Nullable)peerSet +{ + NSMutableArray* publicSigningSPKIs = [NSMutableArray array]; + + for(id peer in peerSet) { + NSData* spki = [peer.publicSigningKey encodeSubjectPublicKeyInfo]; + if(!spki) { + secerror("octagon-sos: Can't create SPKI for peer: %@", peer); + } else { + secerror("octagon-sos: Created SPKI for peer: %@", peer); + [publicSigningSPKIs addObject:spki]; + } + } + return publicSigningSPKIs; +} + ++ (NSArray* _Nullable)peerPublicSigningKeySPKIsForCircle:(id)sosAdapter error:(NSError**)error +{ + NSError* peerError = nil; + SOSCCStatus sosStatus = [sosAdapter circleStatus:&peerError]; + + if(sosStatus != kSOSCCInCircle || peerError) { + secerror("octagon-sos: Not in circle; not preapproving keys: %@ (%@)", SOSAccountGetSOSCCStatusString(sosStatus), peerError); + if(error) { + *error = peerError; + } + return nil; + } else { + // We're in-circle: preapprove these peers + NSError* peerError = nil; + + NSSet>* peerSet = [sosAdapter fetchTrustedPeers:&peerError]; + + if(!peerSet || peerError) { + secerror("octagon-sos: Can't fetch trusted peer SPKIs: %@", peerError); + if(error) { + *error = peerError; + } + return nil; + } + + return [self peerPublicSigningKeySPKIs:peerSet]; + } +} @end #endif // OCTAGON diff --git a/keychain/ot/OTSOSUpdatePreapprovalsOperation.m b/keychain/ot/OTSOSUpdatePreapprovalsOperation.m index 7abf6522..2f252242 100644 --- a/keychain/ot/OTSOSUpdatePreapprovalsOperation.m +++ b/keychain/ot/OTSOSUpdatePreapprovalsOperation.m @@ -52,63 +52,50 @@ } self.finishedOp = [NSBlockOperation blockOperationWithBlock:^{ - // If we errored in some unknown way, ask to try again! STRONGIFY(self); if(self.error) { - // Is this a very scary error? - bool fatal = false; - - NSTimeInterval ckDelay = CKRetryAfterSecondsForError(self.error); - NSTimeInterval cuttlefishDelay = [self.error cuttlefishRetryAfter]; - NSTimeInterval delay = MAX(ckDelay, cuttlefishDelay); - if (delay == 0) { - delay = 30; - } - - if([self.error isCuttlefishError:CuttlefishErrorResultGraphNotFullyReachable]) { - secnotice("octagon-sos", "SOS update preapproval error is 'result graph not reachable'; retrying is useless: %@", self.error); - fatal = true; - } - - if([self.error.domain isEqualToString:TrustedPeersHelperErrorDomain] && self.error.code == TrustedPeersHelperErrorNoPreparedIdentity) { - secnotice("octagon-sos", "SOS update preapproval error is 'no prepared identity'; retrying immediately is useless: %@", self.error); - fatal = true; - } - - if(!fatal) { + if ([self.error retryableCuttlefishError]) { + NSTimeInterval delay = [self.error overallCuttlefishRetry]; secnotice("octagon-sos", "SOS update preapproval error is not fatal: requesting retry in %0.2fs: %@", delay, self.error); [self.deps.flagHandler handlePendingFlag:[[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptSOSUpdatePreapprovals delayInSeconds:delay]]; + } else { + secnotice("octagon-sos", "SOS update preapproval error is: %@, not retrying", self.error); } } }]; [self dependOnBeforeGroupFinished:self.finishedOp]; - NSError* error = nil; - NSSet>* peerSet = [self.deps.sosAdapter fetchTrustedPeers:&error]; + NSError* sosPreapprovalError = nil; + NSArray* publicSigningSPKIs = [OTSOSAdapterHelpers peerPublicSigningKeySPKIsForCircle:self.deps.sosAdapter error:&sosPreapprovalError]; - if(!peerSet || error) { - secerror("octagon-sos: Can't fetch trusted peers; stopping preapproved key update: %@", error); - self.error = error; + if(!publicSigningSPKIs || sosPreapprovalError) { + secerror("octagon-sos: Can't fetch trusted peers; stopping preapproved key update: %@", sosPreapprovalError); + self.error = sosPreapprovalError; self.nextState = self.sosNotPresentState; [self runBeforeGroupFinished:self.finishedOp]; return; } - NSArray* publicSigningSPKIs = [OTSOSActualAdapter peerPublicSigningKeySPKIs:peerSet]; secnotice("octagon-sos", "Updating SOS preapproved keys to %@", publicSigningSPKIs); [self.deps.cuttlefishXPCWrapper setPreapprovedKeysWithContainer:self.deps.containerName context:self.deps.contextID preapprovedKeys:publicSigningSPKIs - reply:^(NSError* error) { + reply:^(TrustedPeersHelperPeerState* _Nullable peerState, NSError* error) { STRONGIFY(self); if(error) { secerror("octagon-sos: unable to update preapproved keys: %@", error); self.error = error; } else { secnotice("octagon-sos", "Updated SOS preapproved keys"); + + if (peerState.memberChanges) { + secnotice("octagon", "Member list changed"); + [self.deps.octagonAdapter sendTrustedPeerSetChangedUpdate]; + } + self.nextState = self.intendedState; } [self runBeforeGroupFinished:self.finishedOp]; diff --git a/keychain/ot/OTSOSUpgradeOperation.h b/keychain/ot/OTSOSUpgradeOperation.h index 04bbfec9..8c87b128 100644 --- a/keychain/ot/OTSOSUpgradeOperation.h +++ b/keychain/ot/OTSOSUpgradeOperation.h @@ -2,6 +2,7 @@ #if OCTAGON #import +#import #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ot/OctagonStateMachineHelpers.h" #import "keychain/ot/OTStates.h" @@ -16,11 +17,14 @@ NS_ASSUME_NONNULL_BEGIN @interface OTSOSUpgradeOperation : CKKSGroupOperation +@property (readonly, nullable) TPPolicyVersion* policyOverride; + - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState ckksConflictState:(OctagonState*)ckksConflictState errorState:(OctagonState*)errorState - deviceInfo:(OTDeviceInformation*)deviceInfo; + deviceInfo:(OTDeviceInformation*)deviceInfo + policyOverride:(TPPolicyVersion* _Nullable)policyOverride; @end diff --git a/keychain/ot/OTSOSUpgradeOperation.m b/keychain/ot/OTSOSUpgradeOperation.m index 8f223984..33ee4e11 100644 --- a/keychain/ot/OTSOSUpgradeOperation.m +++ b/keychain/ot/OTSOSUpgradeOperation.m @@ -34,6 +34,8 @@ @property NSOperation* finishedOp; @property OTUpdateTrustedDeviceListOperation* updateOp; + +@property (nullable) NSArray* peerPreapprovedSPKIs; @end @implementation OTSOSUpgradeOperation @@ -45,6 +47,7 @@ ckksConflictState:(OctagonState*)ckksConflictState errorState:(OctagonState*)errorState deviceInfo:(OTDeviceInformation*)deviceInfo + policyOverride:(TPPolicyVersion* _Nullable)policyOverride { if((self = [super init])) { _deps = dependencies; @@ -54,6 +57,7 @@ _ckksConflictState = ckksConflictState; _deviceInfo = deviceInfo; + _policyOverride = policyOverride; } return self; } @@ -97,9 +101,13 @@ return; } - // Now that we have some non-error SOS status, write down that we attempted an SOS Upgrade. + // Now that we have some non-error SOS status, write down that we attempted an SOS Upgrade (and make sure the CDP bit is on) NSError* persistError = nil; - BOOL persisted = [self.deps.stateHolder persistOctagonJoinAttempt:OTAccountMetadataClassC_AttemptedAJoinState_ATTEMPTED error:&persistError]; + BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.attemptedJoin = OTAccountMetadataClassC_AttemptedAJoinState_ATTEMPTED; + metadata.cdpState = OTAccountMetadataClassC_CDPState_ENABLED; + return metadata; + } error:&persistError]; if(!persisted || persistError) { secerror("octagon: failed to save 'attempted join' state: %@", persistError); } @@ -133,39 +141,35 @@ } self.finishedOp = [NSBlockOperation blockOperationWithBlock:^{ - // If we errored in some unknown way, ask to try again! STRONGIFY(self); if(self.error) { - // Is this a very scary error? - bool fatal = false; - - NSTimeInterval ckDelay = CKRetryAfterSecondsForError(self.error); - NSTimeInterval cuttlefishDelay = [self.error cuttlefishRetryAfter]; - NSTimeInterval delay = MAX(ckDelay, cuttlefishDelay); - if (delay == 0) { - delay = 30; - } - - if([self.error isCuttlefishError:CuttlefishErrorResultGraphNotFullyReachable]) { - secnotice("octagon-sos", "SOS upgrade error is 'result graph not reachable'; retrying is useless: %@", self.error); - fatal = true; - } - - if([self.error.domain isEqualToString:TrustedPeersHelperErrorDomain] && self.error.code == TrustedPeersHelperErrorNoPeersPreapprovePreparedIdentity) { - secnotice("octagon-sos", "SOS upgrade error is 'no peers preapprove us'; retrying immediately is useless: %@", self.error); - fatal = true; - } - - if(!fatal) { + if ([self.error retryableCuttlefishError]) { + NSTimeInterval delay = [self.error overallCuttlefishRetry]; secnotice("octagon-sos", "SOS upgrade error is not fatal: requesting retry in %0.2fs: %@", delay, self.error); [self.deps.flagHandler handlePendingFlag:[[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptSOSUpgrade delayInSeconds:delay]]; + } else { + secnotice("octagon-sos", "SOS upgrade error is: %@; not retrying", self.error); } } }]; [self dependOnBeforeGroupFinished:self.finishedOp]; + secnotice("octagon-sos", "Fetching trusted peers from SOS"); + + NSError* sosPreapprovalError = nil; + self.peerPreapprovedSPKIs = [OTSOSAdapterHelpers peerPublicSigningKeySPKIsForCircle:self.deps.sosAdapter error:&sosPreapprovalError]; + + if(self.peerPreapprovedSPKIs) { + secnotice("octagon-sos", "SOS preapproved keys are %@", self.peerPreapprovedSPKIs); + } else { + secnotice("octagon-sos", "Unable to fetch SOS preapproved keys: %@", sosPreapprovalError); + self.error = sosPreapprovalError; + [self runBeforeGroupFinished:self.finishedOp]; + return; + } + NSString* bottleSalt = nil; NSError *authKitError = nil; @@ -186,6 +190,14 @@ } } + NSError* sosViewError = nil; + BOOL safariViewEnabled = [self.deps.sosAdapter safariViewSyncingEnabled:&sosViewError]; + if(sosViewError) { + secnotice("octagon-sos", "Unable to check safari view status: %@", sosViewError); + } + + secnotice("octagon-sos", "Safari view is: %@", safariViewEnabled ? @"enabled" : @"disabled"); + [self.deps.cuttlefishXPCWrapper prepareWithContainer:self.deps.containerName context:self.deps.contextID epoch:self.deviceInfo.epoch @@ -196,8 +208,11 @@ deviceName:self.deviceInfo.deviceName serialNumber:self.self.deviceInfo.serialNumber osVersion:self.deviceInfo.osVersion - policyVersion:nil + policyVersion:self.policyOverride policySecrets:nil + syncUserControllableViews:safariViewEnabled ? + TPPBPeerStableInfo_UserControllableViewStatus_ENABLED : + TPPBPeerStableInfo_UserControllableViewStatus_DISABLED signingPrivKeyPersistentRef:signingKeyPersistRef encPrivKeyPersistentRef:encryptionKeyPersistRef reply:^(NSString * _Nullable peerID, @@ -205,6 +220,7 @@ NSData * _Nullable permanentInfoSig, NSData * _Nullable stableInfo, NSData * _Nullable stableInfoSig, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error) { STRONGIFY(self); @@ -216,12 +232,28 @@ [self handlePrepareErrors:error nextExpectedState:OctagonStateBecomeUntrusted]; [self runBeforeGroupFinished:self.finishedOp]; - } else { - secnotice("octagon-sos", "Prepared: %@ %@ %@", peerID, permanentInfo, permanentInfoSig); - - [self afterPrepare]; + return; } + secnotice("octagon-sos", "Prepared: %@ %@ %@", peerID, permanentInfo, permanentInfoSig); + + NSError* localError = nil; + BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&localError]; + + if(!persisted || localError) { + secerror("octagon-ckks: Error persisting new views and policy: %@", localError); + self.error = localError; + [self handlePrepareErrors:error nextExpectedState:OctagonStateBecomeUntrusted]; + [self runBeforeGroupFinished:self.finishedOp]; + return; + } + + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; + + [self afterPrepare]; }]; } @@ -230,6 +262,7 @@ WEAKIFY(self); [self.deps.cuttlefishXPCWrapper preflightPreapprovedJoinWithContainer:self.deps.containerName context:self.deps.contextID + preapprovedKeys:self.peerPreapprovedSPKIs reply:^(BOOL launchOkay, NSError * _Nullable error) { STRONGIFY(self); @@ -261,6 +294,7 @@ self.updateOp = [[OTUpdateTrustedDeviceListOperation alloc] initWithDependencies:self.deps intendedState:OctagonStateReady listUpdatesState:OctagonStateReady + authenticationErrorState:OctagonStateLostAccountAuth errorState:OctagonStateError retryFlag:nil]; self.updateOp.logForUpgrade = YES; @@ -321,11 +355,8 @@ { WEAKIFY(self); - OTFetchViewsOperation *fetchViews = [[OTFetchViewsOperation alloc] initWithDependencies:self.deps]; - [self runBeforeGroupFinished:fetchViews]; - - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; - [fetchKeysOp addDependency:fetchViews]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; secnotice("octagon-sos", "Fetching keys from CKKS"); @@ -342,77 +373,67 @@ { WEAKIFY(self); - secnotice("octagon-sos", "Fetching trusted peers from SOS"); - - NSError* error = nil; - NSSet>* peerSet = [self.deps.sosAdapter fetchTrustedPeers:&error]; - - if(!peerSet || error) { - secerror("octagon-sos: Can't fetch trusted peers; stopping upgrade: %@", error); - self.error = error; - self.nextState = OctagonStateBecomeUntrusted; - [self runBeforeGroupFinished:self.finishedOp]; - return; - } - - NSArray* publicSigningSPKIs = [OTSOSActualAdapter peerPublicSigningKeySPKIs:peerSet]; - secnotice("octagon-sos", "Creating SOS preapproved keys as %@", publicSigningSPKIs); - - secnotice("octagon-sos", "Beginning SOS upgrade with %d key sets and %d SOS peers", (int)viewKeySets.count, (int)peerSet.count); + secnotice("octagon-sos", "Beginning SOS upgrade with %d key sets and %d SOS peers", (int)viewKeySets.count, (int)self.peerPreapprovedSPKIs.count); [self.deps.cuttlefishXPCWrapper attemptPreapprovedJoinWithContainer:self.deps.containerName context:self.deps.contextID ckksKeys:viewKeySets tlkShares:pendingTLKShares - preapprovedKeys:publicSigningSPKIs - reply:^(NSString * _Nullable peerID, NSArray* keyHierarchyRecords, NSError * _Nullable error) { - STRONGIFY(self); + preapprovedKeys:self.peerPreapprovedSPKIs + reply:^(NSString * _Nullable peerID, + NSArray* keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, + NSError * _Nullable error) { + STRONGIFY(self); - [[CKKSAnalytics logger] logResultForEvent:OctagonEventUpgradePreapprovedJoin hardFailure:true result:error]; - if(error) { - secerror("octagon-sos: attemptPreapprovedJoin failed: %@", error); + [[CKKSAnalytics logger] logResultForEvent:OctagonEventUpgradePreapprovedJoin hardFailure:true result:error]; + if(error) { + secerror("octagon-sos: attemptPreapprovedJoin failed: %@", error); - if ([error isCuttlefishError:CuttlefishErrorKeyHierarchyAlreadyExists]) { - secnotice("octagon-ckks", "A CKKS key hierarchy is out of date; requesting reset"); - self.nextState = self.ckksConflictState; - } else { - self.error = error; - self.nextState = OctagonStateBecomeUntrusted; - } - [self runBeforeGroupFinished:self.finishedOp]; - return; + if ([error isCuttlefishError:CuttlefishErrorKeyHierarchyAlreadyExists]) { + secnotice("octagon-ckks", "A CKKS key hierarchy is out of date; requesting reset"); + self.nextState = self.ckksConflictState; + } else { + self.error = error; + self.nextState = OctagonStateBecomeUntrusted; } - - [self requestSilentEscrowUpdate]; - - secerror("octagon-sos: attemptPreapprovedJoin succeded"); - - NSError* localError = nil; - BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { - metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; - metadata.peerID = peerID; - return metadata; - } error:&localError]; - - if(!persisted || localError) { - secnotice("octagon-sos", "Couldn't persist results: %@", localError); - self.error = localError; - self.nextState = OctagonStateError; - [self runBeforeGroupFinished:self.finishedOp]; - return; - } - - self.nextState = self.intendedState; - - // Tell CKKS about our shiny new records! - for (id key in self.deps.viewManager.views) { - CKKSKeychainView* view = self.deps.viewManager.views[key]; - secnotice("octagon-ckks", "Providing ck records (from sos upgrade) to %@", view); - [view receiveTLKUploadRecords: keyHierarchyRecords]; - } - [self runBeforeGroupFinished:self.finishedOp]; - }]; + return; + } + + [self requestSilentEscrowUpdate]; + + secerror("octagon-sos: attemptPreapprovedJoin succeded"); + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; + + NSError* localError = nil; + BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; + metadata.peerID = peerID; + + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&localError]; + + if(!persisted || localError) { + secnotice("octagon-sos", "Couldn't persist results: %@", localError); + self.error = localError; + self.nextState = OctagonStateError; + [self runBeforeGroupFinished:self.finishedOp]; + return; + } + + self.nextState = self.intendedState; + + // Tell CKKS about our shiny new records! + for (id key in self.deps.viewManager.views) { + CKKSKeychainView* view = self.deps.viewManager.views[key]; + secnotice("octagon-ckks", "Providing ck records (from sos upgrade) to %@", view); + [view receiveTLKUploadRecords: keyHierarchyRecords]; + } + + [self runBeforeGroupFinished:self.finishedOp]; + }]; } @end diff --git a/keychain/SecureObjectSync/SOSBackupInformation.h b/keychain/ot/OTSetCDPBitOperation.h similarity index 59% rename from keychain/SecureObjectSync/SOSBackupInformation.h rename to keychain/ot/OTSetCDPBitOperation.h index b11d57b6..03a53964 100644 --- a/keychain/SecureObjectSync/SOSBackupInformation.h +++ b/keychain/ot/OTSetCDPBitOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2019 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,29 +21,23 @@ * @APPLE_LICENSE_HEADER_END@ */ -// -// SOSBackupInformation.h -// Security -// +#if OCTAGON -#ifndef SOSBackupInformation_h -#define SOSBackupInformation_h +#import +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" +#import "keychain/ot/OTOperationDependencies.h" -#include -#import "keychain/SecureObjectSync/SOSAccountTransaction.h" +NS_ASSUME_NONNULL_BEGIN -enum { - noError = 0, - noTxnorAcct, - noAlloc, - noTrustedPubKey, - noBSKBs, -}; +@interface OTSetCDPBitOperation : CKKSGroupOperation -extern const CFStringRef kSOSBkpInfoStatus; -extern const CFStringRef kSOSBkpInfoBSKB; -extern const CFStringRef kSOSBkpInfoRKBG; +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; -CFDictionaryRef SOSBackupInformation(SOSAccountTransaction* txn, CFErrorRef *error); +@end -#endif /* SOSBackupInformation_h */ +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ot/OTSetCDPBitOperation.m b/keychain/ot/OTSetCDPBitOperation.m new file mode 100644 index 00000000..9b1b3592 --- /dev/null +++ b/keychain/ot/OTSetCDPBitOperation.m @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#if OCTAGON + +#import "utilities/debugging.h" + +#import "keychain/ot/OTSetCDPBitOperation.h" +#import "keychain/ot/ObjCImprovements.h" + +@interface OTSetCDPBitOperation () +@property OTOperationDependencies* deps; + +@property NSOperation* finishedOp; +@end + +@implementation OTSetCDPBitOperation +@synthesize intendedState = _intendedState; +@synthesize nextState = _nextState; + +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if((self = [super init])) { + _deps = dependencies; + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + NSError* localError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.cdpState = OTAccountMetadataClassC_CDPState_ENABLED; + return metadata; + } error:&localError]; + + if(localError) { + secnotice("octagon-cdp-status", "Unable to set CDP bit: %@", localError); + } else { + secnotice("octagon-cdp-status", "Successfully set CDP bit"); + self.nextState = self.intendedState; + } +} + +@end + +#endif // OCTAGON diff --git a/keychain/ot/OTSetRecoveryKeyOperation.m b/keychain/ot/OTSetRecoveryKeyOperation.m index 4761d525..b66d44a2 100644 --- a/keychain/ot/OTSetRecoveryKeyOperation.m +++ b/keychain/ot/OTSetRecoveryKeyOperation.m @@ -81,7 +81,8 @@ WEAKIFY(self); - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"setting-recovery-tlks" @@ -103,7 +104,8 @@ recoveryKey:self.recoveryKey salt:salt ckksKeys:viewKeySets - reply:^(NSError * _Nullable setError) { + reply:^(NSArray* _Nullable keyHierarchyRecords, + NSError * _Nullable setError) { STRONGIFY(self); if(setError){ [[CKKSAnalytics logger] logResultForEvent:OctagonEventSetRecoveryKey hardFailure:true result:setError]; @@ -112,6 +114,12 @@ [self runBeforeGroupFinished:self.finishOp]; } else { secnotice("octagon", "successfully set recovery key"); + + for (id key in self.deps.viewManager.views) { + CKKSKeychainView* view = self.deps.viewManager.views[key]; + secnotice("octagon-ckks", "Providing setRecoveryKey() records to %@", view); + [view receiveTLKUploadRecords:keyHierarchyRecords]; + } [self runBeforeGroupFinished:self.finishOp]; } }]; diff --git a/keychain/ot/OTStates.h b/keychain/ot/OTStates.h index ede2cb05..79ad416b 100644 --- a/keychain/ot/OTStates.h +++ b/keychain/ot/OTStates.h @@ -33,9 +33,11 @@ NS_ASSUME_NONNULL_BEGIN // No iCloud Account (the state machine won't help at all) // Untrusted (user interaction is required to resolve) // WaitForHSA2 (there's some primary icloud account, but it's not HSA2 (yet)) +// WaitForCDP (there's some HSA2 primary icloud account, but it's not CDP-enabled (yet) extern OctagonState* const OctagonStateNoAccount; extern OctagonState* const OctagonStateUntrusted; extern OctagonState* const OctagonStateWaitForHSA2; +extern OctagonState* const OctagonStateWaitForCDP; // Entering this state will mark down that the device is untrusted, then go to OctagonStateUntrusted extern OctagonState* const OctagonStateBecomeUntrusted; @@ -43,6 +45,9 @@ extern OctagonState* const OctagonStateBecomeUntrusted; // WaitForUnlock indicates that Octagon is waiting for the device to unlock before attempting the pended operation extern OctagonState* const OctagonStateWaitForUnlock; +// Similar to the above, but we can't even be sure there's an account until the device unlocks for the first time. +extern OctagonState* const OctagonStateWaitForClassCUnlock; + // 'ready' indicates that this machine believes it is trusted by its peers // and has no pending things to do. extern OctagonState* const OctagonStateReady; @@ -50,6 +55,14 @@ extern OctagonState* const OctagonStateReady; // This state runs any final preparation to enter the Ready state extern OctagonState* const OctagonStateBecomeReady; +// BecomeReady might go here, if it's not actually ready +extern OctagonState* const OctagonStateRefetchCKKSPolicy; + +// Used in RPCs to set CKKS sync status +extern OctagonState* const OctagonStateEnableUserControllableViews; +extern OctagonState* const OctagonStateDisableUserControllableViews; +extern OctagonState* const OctagonStateSetUserControllableViewsToPeerConsensus; + // Enter this state if you'd like the state machine to double-check everything extern OctagonState* const OctagonStateEnsureConsistency; extern OctagonState* const OctagonStateEnsureOctagonKeysAreConsistent; @@ -59,23 +72,26 @@ extern OctagonState* const OctagonStateEnsureUpdatePreapprovals; extern OctagonState* const OctagonStateInitializing; extern OctagonState* const OctagonStateWaitingForCloudKitAccount; extern OctagonState* const OctagonStateCloudKitNewlyAvailable; +extern OctagonState* const OctagonStateDetermineCDPState; extern OctagonState* const OctagonStateCheckTrustState; /*Piggybacking and ProximitySetup as Initiator, Octagon only*/ extern OctagonState* const OctagonStateInitiatorAwaitingVoucher; +extern OctagonState* const OctagonStateInitiatorSetCDPBit; extern OctagonState* const OctagonStateInitiatorUpdateDeviceList; extern OctagonState* const OctagonStateInitiatorJoin; extern OctagonState* const OctagonStateInitiatorJoinCKKSReset; extern OctagonState* const OctagonStateInitiatorJoinAfterCKKSReset; -extern OctagonState* const OctagonStateInitiatorVouchWithBottle; +extern OctagonState* const OctagonStateBottleJoinVouchWithBottle; extern OctagonState* const OctagonStateIdentityPrepared; // OctagonStateIdentityPrepared leads directly to extern OctagonState* const OctagonStateDeviceListUpdated; /* used for join with bottle */ -extern OctagonState* const OctagonStateInitiatorCreateIdentity; +extern OctagonState* const OctagonStateBottleJoinCreateIdentity; +extern OctagonState* const OctagonStateBottlePreloadOctagonKeysInSOS; /* used for join with recovery key */ extern OctagonState* const OctagonStateCreateIdentityForRecoveryKey; @@ -87,6 +103,7 @@ extern OctagonState* const OctagonStateVouchWithRecoveryKey; extern OctagonState* const OctagonStateResetBecomeUntrusted; extern OctagonState* const OctagonStateResetAndEstablish; extern OctagonState* const OctagonStateResetAnyMissingTLKCKKSViews; +extern OctagonState* const OctagonStateEstablishEnableCDPBit; extern OctagonState* const OctagonStateReEnactDeviceList; extern OctagonState* const OctagonStateReEnactPrepare; extern OctagonState* const OctagonStateReEnactReadyToEstablish; @@ -96,6 +113,7 @@ extern OctagonState* const OctagonStateEstablishAfterCKKSReset; /* used for trust health checks */ extern OctagonState* const OctagonStateHSA2HealthCheck; +extern OctagonState* const OctagonStateCDPHealthCheck; extern OctagonState* const OctagonStateSecurityTrustCheck; extern OctagonState* const OctagonStateTPHTrustCheck; extern OctagonState* const OctagonStateCuttlefishTrustCheck; @@ -104,10 +122,16 @@ extern OctagonState* const OctagonStateHealthCheckReset; // End of account reset state flow +//Leave Clique +extern OctagonState* const OctagonStateHealthCheckLeaveClique; + // Part of the signout flow extern OctagonState* const OctagonStateNoAccountDoReset; // +// Used if the local device no longer can talk to the account +extern OctagonState* const OctagonStateLostAccountAuth; + // escrow extern OctagonState* const OctagonStateEscrowTriggerUpdate; @@ -117,6 +141,7 @@ extern OctagonState* const OctagonStateUpdateSOSPreapprovals; extern OctagonState* const OctagonStateError; extern OctagonState* const OctagonStateDisabled; +extern OctagonState* const OctagonStateAttemptSOSUpgradeDetermineCDPState; extern OctagonState* const OctagonStateAttemptSOSUpgrade; extern OctagonState* const OctagonStateSOSUpgradeCKKSReset; extern OctagonState* const OctagonStateSOSUpgradeAfterCKKSReset; @@ -131,6 +156,9 @@ extern OctagonState* const OctagonStateAssistCKKSTLKUploadAfterCKKSReset; // Call out to otpaird (KCPairing via IDS), then proceed to BecomeUntrusted extern OctagonState* const OctagonStateStartCompanionPairing; +// Cuttlefish notification while waiting for CDP +extern OctagonState* const OctagonStateWaitForCDPUpdated; + // Untrusted cuttlefish notification. extern OctagonState* const OctagonStateUntrustedUpdated; @@ -148,6 +176,7 @@ NSDictionary* OctagonStateInverseMap(void); NSSet* OctagonInAccountStates(void); NSSet* OctagonHealthSourceStates(void); NSSet* AllOctagonFlags(void); +NSSet* OctagonNotInCliqueStates(void); ////// State machine flags extern OctagonFlag* const OctagonFlagIDMSLevelChanged; @@ -155,6 +184,10 @@ extern OctagonFlag* const OctagonFlagIDMSLevelChanged; extern OctagonFlag* const OctagonFlagEgoPeerPreapproved; extern OctagonFlag* const OctagonFlagCKKSRequestsTLKUpload; +extern OctagonFlag* const OctagonFlagCKKSRequestsPolicyCheck; + +// Set by Octagon when the CKKS view set has changed. Indicates a need to re-tell CKKS if it's trusted or not. +extern OctagonFlag* const OctagonFlagCKKSViewSetChanged; // We've received a change notification from cuttlefish; we should probably see what's new extern OctagonFlag* const OctagonFlagCuttlefishNotification NS_SWIFT_NAME(OctagonFlagCuttlefishNotification); @@ -163,6 +196,7 @@ extern OctagonFlag* const OctagonFlagCuttlefishNotification NS_SWIFT_NAME(Octago extern OctagonFlag* const OctagonFlagFetchAuthKitMachineIDList; extern OctagonFlag* const OctagonFlagAccountIsAvailable; +extern OctagonFlag* const OctagonFlagCDPEnabled; extern OctagonFlag* const OctagonFlagAttemptSOSUpgrade; extern OctagonFlag* const OctagonFlagUnlocked; @@ -171,6 +205,12 @@ extern OctagonFlag* const OctagonFlagAttemptSOSUpdatePreapprovals; extern OctagonFlag* const OctagonFlagAttemptSOSConsistency; extern OctagonFlag* const OctagonFlagEscrowRequestInformCloudServicesOperation; +extern OctagonFlag* const OctagonFlagWarmEscrowRecordCache; + +extern OctagonFlag* const OctagonFlagAttemptBottleTLKExtraction; +extern OctagonFlag* const OctagonFlagAttemptRecoveryKeyTLKExtraction; + +extern OctagonFlag* const OctagonFlagAttemptUserControllableViewStatusUpgrade; NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTStates.m b/keychain/ot/OTStates.m index 5af0ffb4..29e69659 100644 --- a/keychain/ot/OTStates.m +++ b/keychain/ot/OTStates.m @@ -33,6 +33,7 @@ OctagonState* const OctagonStateNoAccount = (OctagonState*) @"no_account"; OctagonState* const OctagonStateWaitForHSA2 = (OctagonState*) @"wait_for_hsa2"; +OctagonState* const OctagonStateWaitForCDP = (OctagonState*) @"wait_for_cdp_enable"; OctagonState* const OctagonStateUntrusted = (OctagonState*) @"untrusted"; OctagonState* const OctagonStateBecomeUntrusted = (OctagonState*) @"become_untrusted"; @@ -47,11 +48,18 @@ OctagonState* const OctagonStateEnsureUpdatePreapprovals = (OctagonState*)@"ensu OctagonState* const OctagonStateInitializing = (OctagonState*) @"initializing"; OctagonState* const OctagonStateWaitingForCloudKitAccount = (OctagonState*) @"waiting_for_cloudkit_account"; OctagonState* const OctagonStateCloudKitNewlyAvailable = (OctagonState*) @"account_newly_available"; +OctagonState* const OctagonStateRefetchCKKSPolicy = (OctagonState*) @"ckks_fetch_policy"; +OctagonState* const OctagonStateDetermineCDPState = (OctagonState*) @"check_cdp_state"; OctagonState* const OctagonStateCheckTrustState = (OctagonState*) @"check_trust_state"; +OctagonState* const OctagonStateEnableUserControllableViews = (OctagonState*) @"ckks_set_user_controllable_views_on"; +OctagonState* const OctagonStateDisableUserControllableViews = (OctagonState*) @"ckks_set_user_controlable_views_off"; +OctagonState* const OctagonStateSetUserControllableViewsToPeerConsensus = (OctagonState*) @"ckks_set_user_controlable_views_peer_consensus"; + OctagonState* const OctagonStateUpdateSOSPreapprovals = (OctagonState*) @"update_sos_preapprovals"; /*Piggybacking and ProximitySetup as Initiator Octagon only*/ +OctagonState* const OctagonStateInitiatorSetCDPBit = (OctagonState*) @"initiator_set_cdp"; OctagonState* const OctagonStateInitiatorUpdateDeviceList = (OctagonState*) @"initiator_device_list_update"; OctagonState* const OctagonStateInitiatorAwaitingVoucher = (OctagonState*)@"await_voucher"; OctagonState* const OctagonStateInitiatorJoin = (OctagonState*)@"join"; @@ -59,15 +67,18 @@ OctagonState* const OctagonStateInitiatorJoinCKKSReset = (OctagonState*)@"join_c OctagonState* const OctagonStateInitiatorJoinAfterCKKSReset = (OctagonState*)@"join_after_ckks_reset"; /* used in restore (join with bottle)*/ -OctagonState* const OctagonStateInitiatorCreateIdentity = (OctagonState*)@"create_identity"; -OctagonState* const OctagonStateInitiatorVouchWithBottle = (OctagonState*)@"vouchWithBottle"; +OctagonState* const OctagonStateBottleJoinCreateIdentity = (OctagonState*)@"bottle_join_create_identity"; +OctagonState* const OctagonStateBottleJoinVouchWithBottle = (OctagonState*)@"bottle_join_vouch_with_bottle"; OctagonState* const OctagonStateCreateIdentityForRecoveryKey = (OctagonState*)@"vouchWithRecovery"; +OctagonState* const OctagonStateBottlePreloadOctagonKeysInSOS = (OctagonState*)@"bottle_preload_octagon_keys_in_sos"; /* used in resotre (join with recovery key)*/ OctagonState* const OctagonStateVouchWithRecoveryKey = (OctagonState*)@"vouchWithRecoveryKey"; OctagonState* const OctagonStateStartCompanionPairing = (OctagonState*)@"start_companion_pairing"; +OctagonState* const OctagonStateWaitForCDPUpdated = (OctagonState*)@"wait_for_cdp_update"; + // Untrusted cuttlefish notification. OctagonState* const OctagonStateUntrustedUpdated = (OctagonState*)@"untrusted_update"; @@ -78,6 +89,8 @@ OctagonState* const OctagonStateError = (OctagonState*) @"error"; OctagonState* const OctagonStateDisabled = (OctagonState*) @"disabled"; OctagonState* const OctagonStateDetermineiCloudAccountState = (OctagonState*) @"determine_icloud_account"; + +OctagonState* const OctagonStateAttemptSOSUpgradeDetermineCDPState = (OctagonState*) @"sosupgrade_cdp_check"; OctagonState* const OctagonStateAttemptSOSUpgrade = (OctagonState*) @"sosupgrade"; OctagonState* const OctagonStateSOSUpgradeCKKSReset = (OctagonState*) @"sosupgrade_ckks_reset"; OctagonState* const OctagonStateSOSUpgradeAfterCKKSReset = (OctagonState*) @"sosupgrade_after_ckks_reset"; @@ -87,6 +100,7 @@ OctagonState* const OctagonStateUnimplemented = (OctagonState*) @"unimplemented" OctagonState* const OctagonStateResetBecomeUntrusted = (OctagonState*) @"reset_become_untrusted"; OctagonState* const OctagonStateResetAndEstablish = (OctagonState*) @"reset_and_establish"; OctagonState* const OctagonStateResetAnyMissingTLKCKKSViews = (OctagonState*) @"reset_ckks_missing_views"; +OctagonState* const OctagonStateEstablishEnableCDPBit = (OctagonState*) @"reenact_cdp_bit"; OctagonState* const OctagonStateReEnactDeviceList = (OctagonState*) @"reenact_device_list"; OctagonState* const OctagonStateReEnactPrepare = (OctagonState*) @"reenact_prepare"; OctagonState* const OctagonStateReEnactReadyToEstablish = (OctagonState*) @"reenact_ready_to_establish"; @@ -95,6 +109,7 @@ OctagonState* const OctagonStateEstablishAfterCKKSReset = (OctagonState*) @"reen /* used for trust health checks */ OctagonState* const OctagonStateHSA2HealthCheck = (OctagonState*) @"health_hsa2_check"; +OctagonState* const OctagonStateCDPHealthCheck = (OctagonState*) @"health_cdp_check"; OctagonState* const OctagonStateTPHTrustCheck = (OctagonState*) @"tph_trust_check"; OctagonState* const OctagonStateCuttlefishTrustCheck = (OctagonState*) @"cuttlefish_trust_check"; OctagonState* const OctagonStatePostRepairCFU = (OctagonState*) @"post_repair_cfu"; @@ -103,12 +118,17 @@ OctagonState* const OctagonStateHealthCheckReset = (OctagonState*) @"health_chec /* signout */ OctagonState* const OctagonStateNoAccountDoReset = (OctagonState*) @"no_account_do_reset"; +OctagonState* const OctagonStateLostAccountAuth = (OctagonState*) @"authkit_auth_lost"; + OctagonState* const OctagonStateWaitForUnlock = (OctagonState*) @"wait_for_unlock"; +OctagonState* const OctagonStateWaitForClassCUnlock = (OctagonState*) @"wait_for_class_c_unlock"; OctagonState* const OctagonStateAssistCKKSTLKUpload = (OctagonState*) @"assist_ckks_tlk_upload"; OctagonState* const OctagonStateAssistCKKSTLKUploadCKKSReset = (OctagonState*) @"assist_ckks_tlk_upload_ckks_reset"; OctagonState* const OctagonStateAssistCKKSTLKUploadAfterCKKSReset = (OctagonState*) @"assist_ckks_tlk_upload_after_ckks_reset"; +OctagonState* const OctagonStateHealthCheckLeaveClique = (OctagonState*) @"leave_clique"; + /* escrow */ OctagonState* const OctagonStateEscrowTriggerUpdate = (OctagonState*) @"escrow-trigger-update"; @@ -145,8 +165,8 @@ NSDictionary* OctagonStateMap(void) { OctagonStateReEnactPrepare: @14U, OctagonStateReEnactReadyToEstablish: @15U, OctagonStateNoAccountDoReset: @16U, - OctagonStateInitiatorVouchWithBottle: @17U, - OctagonStateInitiatorCreateIdentity: @18U, + OctagonStateBottleJoinVouchWithBottle: @17U, + OctagonStateBottleJoinCreateIdentity: @18U, OctagonStateCloudKitNewlyAvailable: @19U, OctagonStateCheckTrustState: @20U, OctagonStateBecomeUntrusted: @21U, @@ -181,6 +201,21 @@ NSDictionary* OctagonStateMap(void) { OctagonStateHealthCheckReset: @50U, OctagonStateAssistCKKSTLKUploadCKKSReset: @51U, OctagonStateAssistCKKSTLKUploadAfterCKKSReset: @52U, + OctagonStateWaitForCDP: @53U, + OctagonStateDetermineCDPState: @54U, + OctagonStateWaitForCDPUpdated: @55U, + OctagonStateEstablishEnableCDPBit: @56U, + OctagonStateInitiatorSetCDPBit: @57U, + OctagonStateCDPHealthCheck: @58U, + OctagonStateHealthCheckLeaveClique: @59U, + OctagonStateRefetchCKKSPolicy: @60U, + OctagonStateEnableUserControllableViews: @61U, + OctagonStateDisableUserControllableViews: @62U, + OctagonStateSetUserControllableViewsToPeerConsensus: @63U, + OctagonStateWaitForClassCUnlock: @64U, + OctagonStateBottlePreloadOctagonKeysInSOS: @65U, + OctagonStateAttemptSOSUpgradeDetermineCDPState: @66U, + OctagonStateLostAccountAuth: @67U, }; }); return map; @@ -213,6 +248,30 @@ NSSet* OctagonInAccountStates(void) [sourceStates removeObject:OctagonStateCloudKitNewlyAvailable]; [sourceStates removeObject:OctagonStateWaitForHSA2]; + // If the device hasn't unlocked yet, we don't know what we wrote down for iCloud account status + [sourceStates removeObject:OctagonStateWaitForClassCUnlock]; + + s = sourceStates; + }); + return s; +} + +NSSet* OctagonNotInCliqueStates(void) +{ + static NSSet* s = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableSet* sourceStates = [NSMutableSet set]; + + [sourceStates addObject:OctagonStateNoAccount]; + [sourceStates addObject:OctagonStateNoAccountDoReset]; + [sourceStates addObject:OctagonStateInitializing]; + [sourceStates addObject:OctagonStateDetermineiCloudAccountState]; + [sourceStates addObject:OctagonStateWaitingForCloudKitAccount]; + [sourceStates addObject:OctagonStateCloudKitNewlyAvailable]; + [sourceStates addObject:OctagonStateWaitForHSA2]; + [sourceStates addObject:OctagonStateUntrusted]; + s = sourceStates; }); return s; @@ -230,6 +289,7 @@ NSSet* OctagonHealthSourceStates(void) [sourceStates addObject:OctagonStateUntrusted]; [sourceStates addObject:OctagonStateWaitForHSA2]; [sourceStates addObject:OctagonStateWaitForUnlock]; + [sourceStates addObject:OctagonStateWaitForCDP]; s = sourceStates; }); @@ -239,15 +299,23 @@ NSSet* OctagonHealthSourceStates(void) // Flags OctagonFlag* const OctagonFlagIDMSLevelChanged = (OctagonFlag*) @"idms_level"; OctagonFlag* const OctagonFlagEgoPeerPreapproved = (OctagonFlag*) @"preapproved"; -OctagonFlag* const OctagonFlagCKKSRequestsTLKUpload = (OctagonFlag*) @"tlk_upload_needed"; +OctagonFlag* const OctagonFlagCKKSRequestsTLKUpload = (OctagonFlag*) @"tlk_upload_needed"; +OctagonFlag* const OctagonFlagCKKSRequestsPolicyCheck = (OctagonFlag*) @"policy_check_needed";; +OctagonFlag* const OctagonFlagCKKSViewSetChanged = (OctagonFlag*) @"ckks_views_changed"; OctagonFlag* const OctagonFlagCuttlefishNotification = (OctagonFlag*) @"recd_push"; OctagonFlag* const OctagonFlagAccountIsAvailable = (OctagonFlag*)@"account_available"; +OctagonFlag* const OctagonFlagCDPEnabled = (OctagonFlag*) @"cdp_enabled"; OctagonFlag* const OctagonFlagAttemptSOSUpgrade = (OctagonFlag*)@"attempt_sos_upgrade"; OctagonFlag* const OctagonFlagFetchAuthKitMachineIDList = (OctagonFlag*)@"attempt_machine_id_list"; OctagonFlag* const OctagonFlagUnlocked = (OctagonFlag*)@"unlocked"; OctagonFlag* const OctagonFlagAttemptSOSUpdatePreapprovals = (OctagonFlag*)@"attempt_sos_update_preapprovals"; OctagonFlag* const OctagonFlagAttemptSOSConsistency = (OctagonFlag*)@"attempt_sos_consistency"; OctagonFlag* const OctagonFlagEscrowRequestInformCloudServicesOperation = (OctagonFlag*)@"escrowrequest_inform_cloudservices"; +OctagonFlag* const OctagonFlagWarmEscrowRecordCache = (OctagonFlag*)@"warm_escrow_cache"; +OctagonFlag* const OctagonFlagAttemptBottleTLKExtraction = (OctagonFlag*)@"retry_bottle_tlk_extraction"; +OctagonFlag* const OctagonFlagAttemptRecoveryKeyTLKExtraction = (OctagonFlag*)@"retry_rk_tlk_extraction"; + +OctagonFlag* const OctagonFlagAttemptUserControllableViewStatusUpgrade = (OctagonFlag*)@"attempt_ucv_upgrade"; NSSet* AllOctagonFlags(void) { @@ -259,13 +327,20 @@ NSSet* AllOctagonFlags(void) [flags addObject:OctagonFlagIDMSLevelChanged]; [flags addObject:OctagonFlagEgoPeerPreapproved]; [flags addObject:OctagonFlagCKKSRequestsTLKUpload]; + [flags addObject:OctagonFlagCKKSRequestsPolicyCheck]; + [flags addObject:OctagonFlagCKKSViewSetChanged]; [flags addObject:OctagonFlagCuttlefishNotification]; [flags addObject:OctagonFlagAccountIsAvailable]; + [flags addObject:OctagonFlagCDPEnabled]; [flags addObject:OctagonFlagAttemptSOSUpgrade]; [flags addObject:OctagonFlagFetchAuthKitMachineIDList]; [flags addObject:OctagonFlagUnlocked]; [flags addObject:OctagonFlagAttemptSOSUpdatePreapprovals]; [flags addObject:OctagonFlagAttemptSOSConsistency]; + [flags addObject:OctagonFlagWarmEscrowRecordCache]; + [flags addObject:OctagonFlagAttemptUserControllableViewStatusUpgrade]; + [flags addObject:OctagonFlagAttemptBottleTLKExtraction]; + [flags addObject:OctagonFlagAttemptRecoveryKeyTLKExtraction]; f = flags; }); diff --git a/keychain/ot/OTUpdateTPHOperation.h b/keychain/ot/OTUpdateTPHOperation.h index 6dbc7022..18999f22 100644 --- a/keychain/ot/OTUpdateTPHOperation.h +++ b/keychain/ot/OTUpdateTPHOperation.h @@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState + peerUnknownState:(OctagonState*)peerUnknownState errorState:(OctagonState*)errorState retryFlag:(OctagonFlag* _Nullable)retryFlag; @end diff --git a/keychain/ot/OTUpdateTPHOperation.m b/keychain/ot/OTUpdateTPHOperation.m index 5a24b829..b418f81e 100644 --- a/keychain/ot/OTUpdateTPHOperation.m +++ b/keychain/ot/OTUpdateTPHOperation.m @@ -18,6 +18,8 @@ @interface OTUpdateTPHOperation () @property OTOperationDependencies* deps; +@property OctagonState* peerUnknownState; + @property NSOperation* finishedOp; @property (nullable) OctagonFlag* retryFlag; @@ -29,6 +31,7 @@ - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState + peerUnknownState:(OctagonState*)peerUnknownState errorState:(OctagonState*)errorState retryFlag:(OctagonFlag* _Nullable)retryFlag { @@ -37,6 +40,7 @@ _intendedState = intendedState; _nextState = errorState; + _peerUnknownState = peerUnknownState; _retryFlag = retryFlag; } @@ -74,13 +78,7 @@ if(!fatal) { if(!pendingFlag) { - NSTimeInterval baseDelay = SecCKKSTestsEnabled() ? 2 : 30; - NSTimeInterval ckDelay = CKRetryAfterSecondsForError(self.error); - NSTimeInterval cuttlefishDelay = [self.error cuttlefishRetryAfter]; - NSTimeInterval delay = MAX(ckDelay, cuttlefishDelay); - if (delay == 0) { - delay = baseDelay; - } + NSTimeInterval delay = [self.error overallCuttlefishRetry]; pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:self.retryFlag delayInSeconds:delay]; @@ -101,20 +99,42 @@ osVersion:self.deps.deviceInformationAdapter.osVersion policyVersion:nil policySecrets:nil - reply:^(TrustedPeersHelperPeerState* peerState, NSError* error) { + syncUserControllableViews:nil + reply:^(TrustedPeersHelperPeerState* peerState, TPSyncingPolicy* syncingPolicy, NSError* error) { STRONGIFY(self); if(error || !peerState) { secerror("octagon: update errored: %@", error); self.error = error; - // On an error, for now, go back to the intended state - // Octagon: handle lock state errors in update() - self.nextState = self.intendedState; + if ([error isCuttlefishError:CuttlefishErrorUpdateTrustPeerNotFound]) { + secnotice("octagon-ckks", "Cuttlefish reports we no longer exist."); + self.nextState = self.peerUnknownState; + } else { + // On an error, for now, go back to the intended state + // Octagon: handle lock state errors in update() + self.nextState = self.intendedState; + } [self runBeforeGroupFinished:self.finishedOp]; return; } - secnotice("octagon", "update complete: %@", peerState); + secnotice("octagon", "update complete: %@, %@", peerState, syncingPolicy); + + NSError* localError = nil; + BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&localError]; + if(!persisted || localError) { + secerror("octagon: Unable to save new syncing state: %@", localError); + + } else { + // After an update(), we're sure that we have a fresh policy + BOOL viewSetChanged = [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy policyIsFresh:YES]; + if(viewSetChanged) { + [self.deps.flagHandler handleFlag:OctagonFlagCKKSViewSetChanged]; + } + } if(peerState.identityIsPreapproved) { secnotice("octagon-sos", "Self peer is now preapproved!"); @@ -130,14 +150,17 @@ [self.deps.flagHandler handleFlag:OctagonFlagFetchAuthKitMachineIDList]; } - if(peerState.peerStatus & TPPeerStatusExcluded) { + if (peerState.peerStatus & TPPeerStatusExcluded) { secnotice("octagon", "Self peer (%@) is excluded; moving to untrusted", peerState.peerID); self.nextState = OctagonStateBecomeUntrusted; - } else if(peerState.peerStatus & TPPeerStatusUnknown) { - secnotice("octagon", "Self peer (%@) is unknown; moving to untrusted", peerState.peerID); - self.nextState = OctagonStateBecomeUntrusted; - + if (peerState.identityIsPreapproved) { + secnotice("octagon", "Self peer (%@) is excluded but is preapproved, moving to sosuprade", peerState.peerID); + self.nextState = OctagonStateAttemptSOSUpgrade; + } else { + secnotice("octagon", "Self peer (%@) is unknown; moving to '%@''", peerState.peerID, self.peerUnknownState); + self.nextState = self.peerUnknownState; + } } else { self.nextState = self.intendedState; } diff --git a/keychain/ot/OTUpdateTrustedDeviceListOperation.h b/keychain/ot/OTUpdateTrustedDeviceListOperation.h index 3d044371..f1c6b7d5 100644 --- a/keychain/ot/OTUpdateTrustedDeviceListOperation.h +++ b/keychain/ot/OTUpdateTrustedDeviceListOperation.h @@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState listUpdatesState:(OctagonState*)stateIfListUpdates + authenticationErrorState:(OctagonState*)stateIfNotAuthenticated errorState:(OctagonState*)errorState retryFlag:(OctagonFlag* _Nullable)retryFlag; diff --git a/keychain/ot/OTUpdateTrustedDeviceListOperation.m b/keychain/ot/OTUpdateTrustedDeviceListOperation.m index 5f8a8763..3de52233 100644 --- a/keychain/ot/OTUpdateTrustedDeviceListOperation.m +++ b/keychain/ot/OTUpdateTrustedDeviceListOperation.m @@ -22,6 +22,8 @@ @property OctagonState* stateIfListUpdates; +@property OctagonState* stateIfAuthenticationError; + @property (nullable) OctagonFlag* retryFlag; // Since we're making callback based async calls, use this operation trick to hold off the ending of this operation @@ -35,6 +37,7 @@ - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState listUpdatesState:(OctagonState*)stateIfListUpdates + authenticationErrorState:(OctagonState*)stateIfNotAuthenticated errorState:(OctagonState*)errorState retryFlag:(OctagonFlag*)retryFlag @@ -45,6 +48,7 @@ _intendedState = intendedState; _nextState = errorState; _stateIfListUpdates = stateIfListUpdates; + _stateIfAuthenticationError = stateIfNotAuthenticated; _retryFlag = retryFlag; } @@ -87,10 +91,33 @@ }]; [self dependOnBeforeGroupFinished:self.finishedOp]; + NSError* localError = nil; + BOOL isAccountDemo = [self.deps.authKitAdapter accountIsDemoAccount:&localError]; + if(localError) { + secerror("octagon-authkit: failed to fetch demo account flag: %@", localError); + } + [self.deps.authKitAdapter fetchCurrentDeviceList:^(NSSet * _Nullable machineIDs, NSError * _Nullable error) { STRONGIFY(self); - if(!machineIDs || error) { + + if (error) { secerror("octagon-authkit: Unable to fetch machine ID list: %@", error); + + if (self.logForUpgrade) { + [[CKKSAnalytics logger] logRecoverableError:error + forEvent:OctagonEventUpgradeFetchDeviceIDs + withAttributes:NULL]; + } + self.error = error; + + if([AKAppleIDAuthenticationErrorDomain isEqualToString:error.domain] && error.code == AKAuthenticationErrorNotPermitted) { + self.nextState = self.stateIfAuthenticationError; + } + + [self runBeforeGroupFinished:self.finishedOp]; + + } else if (!machineIDs) { + secerror("octagon-authkit: empty machine id list"); if (self.logForUpgrade) { [[CKKSAnalytics logger] logRecoverableError:error forEvent:OctagonEventUpgradeFetchDeviceIDs @@ -103,17 +130,20 @@ if (self.logForUpgrade) { [[CKKSAnalytics logger] logSuccessForEventNamed:OctagonEventUpgradeFetchDeviceIDs]; } - [self afterAuthKitFetch:machineIDs]; + [self afterAuthKitFetch:machineIDs accountIsDemo:isAccountDemo]; } }]; } -- (void)afterAuthKitFetch:(NSSet*)allowedMachineIDs +- (void)afterAuthKitFetch:(NSSet*)allowedMachineIDs accountIsDemo:(BOOL)accountIsDemo { WEAKIFY(self); + BOOL honorIDMSListChanges = accountIsDemo ? NO : YES; + [self.deps.cuttlefishXPCWrapper setAllowedMachineIDsWithContainer:self.deps.containerName context:self.deps.contextID allowedMachineIDs:allowedMachineIDs + honorIDMSListChanges:honorIDMSListChanges reply:^(BOOL listDifferences, NSError * _Nullable error) { STRONGIFY(self); diff --git a/keychain/ot/OTUploadNewCKKSTLKsOperation.h b/keychain/ot/OTUploadNewCKKSTLKsOperation.h index 3feeab6a..205e130e 100644 --- a/keychain/ot/OTUploadNewCKKSTLKsOperation.h +++ b/keychain/ot/OTUploadNewCKKSTLKsOperation.h @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState ckksConflictState:(OctagonState*)ckksConflictState + peerMissingState:(OctagonState*)peerMissingState errorState:(OctagonState*)errorState; @property OctagonState* nextState; diff --git a/keychain/ot/OTUploadNewCKKSTLKsOperation.m b/keychain/ot/OTUploadNewCKKSTLKsOperation.m index f5430804..15968b1b 100644 --- a/keychain/ot/OTUploadNewCKKSTLKsOperation.m +++ b/keychain/ot/OTUploadNewCKKSTLKsOperation.m @@ -8,6 +8,7 @@ #import "keychain/ot/OTUploadNewCKKSTLKsOperation.h" #import "keychain/ot/OTCuttlefishAccountStateHolder.h" #import "keychain/ot/OTFetchCKKSKeysOperation.h" +#import "keychain/ot/OTStates.h" #import "keychain/ckks/CKKSCurrentKeyPointer.h" #import "keychain/ckks/CKKSKeychainView.h" #import "keychain/ckks/CKKSNearFutureScheduler.h" @@ -20,6 +21,7 @@ @property OTOperationDependencies* deps; @property OctagonState* ckksConflictState; +@property OctagonState* peerMissingState; @property NSOperation* finishedOp; @end @@ -30,6 +32,7 @@ - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState ckksConflictState:(OctagonState*)ckksConflictState + peerMissingState:(OctagonState*)peerMissingState errorState:(OctagonState*)errorState { if((self = [super init])) { @@ -37,6 +40,7 @@ _intendedState = intendedState; _ckksConflictState = ckksConflictState; + _peerMissingState = peerMissingState; _nextState = errorState; } return self; @@ -44,16 +48,16 @@ - (void)groupStart { - secnotice("octagon", "Beginning to upload any pending CKKS tlks operation"); + secnotice("octagon", "Beginning an operation to upload any pending CKKS tlks"); WEAKIFY(self); NSMutableSet* viewsToUpload = [NSMutableSet set]; // One (or more) of our sub-CKKSes believes it needs to upload new TLKs. - for(CKKSKeychainView* view in [self.deps.viewManager currentViews]) { - if([view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload] || - [view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation]) { + CKKSViewManager* viewManager = self.deps.viewManager; + for(CKKSKeychainView* view in viewManager.currentViews) { + if([view requiresTLKUpload]) { secnotice("octagon-ckks", "CKKS view %@ needs TLK uploads!", view); [viewsToUpload addObject: view]; } @@ -105,6 +109,11 @@ if ([error isCuttlefishError:CuttlefishErrorKeyHierarchyAlreadyExists]) { secnotice("octagon-ckks", "A CKKS key hierarchy is out of date; moving to '%@'", self.ckksConflictState); self.nextState = self.ckksConflictState; + } else if ([error isCuttlefishError:CuttlefishErrorUpdateTrustPeerNotFound]) { + secnotice("octagon-ckks", "Cuttlefish reports we no longer exist."); + self.nextState = self.peerMissingState; + self.error = error; + } else { secerror("octagon: Error calling tlk upload: %@", error); self.error = error; diff --git a/keychain/ot/OTVouchWithBottleOperation.h b/keychain/ot/OTVouchWithBottleOperation.h index dc3ef075..f9960c81 100644 --- a/keychain/ot/OTVouchWithBottleOperation.h +++ b/keychain/ot/OTVouchWithBottleOperation.h @@ -41,7 +41,8 @@ NS_ASSUME_NONNULL_BEGIN errorState:(OctagonState*)errorState bottleID:(NSString*)bottleID entropy:(NSData*)entropy - bottleSalt:(NSString*)bottleSalt; + bottleSalt:(NSString*)bottleSalt + saveVoucher:(BOOL)saveVoucher; @property (weak) OTCuttlefishContext* cuttlefishContext; @property (nonatomic) NSString* bottleID; @@ -50,6 +51,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) NSData* voucher; @property (nonatomic) NSData* voucherSig; + +// Controls whether or not to save the received voucher in the state handler. +@property (readonly) BOOL saveVoucher; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTVouchWithBottleOperation.m b/keychain/ot/OTVouchWithBottleOperation.m index 48a381bc..da298b6d 100644 --- a/keychain/ot/OTVouchWithBottleOperation.m +++ b/keychain/ot/OTVouchWithBottleOperation.m @@ -29,6 +29,7 @@ #import "keychain/ot/OTClientStateMachine.h" #import "keychain/ot/OTCuttlefishContext.h" #import "keychain/ot/OTFetchCKKSKeysOperation.h" +#import "keychain/ot/OTStates.h" #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" #import "keychain/ot/ObjCImprovements.h" @@ -48,6 +49,7 @@ bottleID:(NSString*)bottleID entropy:(NSData*)entropy bottleSalt:(NSString*)bottleSalt + saveVoucher:(BOOL)saveVoucher { if((self = [super init])) { _deps = dependencies; @@ -57,6 +59,8 @@ _bottleID = bottleID; _entropy = entropy; _bottleSalt = bottleSalt; + + _saveVoucher = saveVoucher; } return self; } @@ -94,35 +98,20 @@ } } - WEAKIFY(self); - - // After a vouch, we also want to acquire all TLKs that the bottled peer might have had - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; - [self runBeforeGroupFinished:fetchKeysOp]; - - CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"bottle-tlks" - withBlock:^{ - STRONGIFY(self); - [self proceedWithKeys:fetchKeysOp.viewKeySets tlkShares:fetchKeysOp.tlkShares]; - }]; - - [proceedWithKeys addDependency:fetchKeysOp]; - [self runBeforeGroupFinished:proceedWithKeys]; -} - -- (void)proceedWithKeys:(NSArray*)viewKeySets tlkShares:(NSArray*)tlkShares -{ // Preflight the vouch: this will tell us the peerID of the recovering peer. // Then, filter the tlkShares array to include only tlks sent to that peer. WEAKIFY(self); [self.deps.cuttlefishXPCWrapper preflightVouchWithBottleWithContainer:self.deps.containerName context:self.deps.contextID bottleID:self.bottleID - reply:^(NSString * _Nullable peerID, NSError * _Nullable error) { + reply:^(NSString * _Nullable peerID, + TPSyncingPolicy* peerSyncingPolicy, + BOOL refetchWasNeeded, + NSError * _Nullable error) { STRONGIFY(self); [[CKKSAnalytics logger] logResultForEvent:OctagonEventPreflightVouchWithBottle hardFailure:true result:error]; - if(error){ + if(error || !peerID) { secerror("octagon: Error preflighting voucher using bottle: %@", error); self.error = error; [self runBeforeGroupFinished:self.finishedOp]; @@ -131,16 +120,62 @@ secnotice("octagon", "Bottle %@ is for peerID %@", self.bottleID, peerID); + // Tell CKKS to spin up the new views and policy + // But, do not persist this view set! We'll do that when we actually manager to join + [self.deps.viewManager setCurrentSyncingPolicy:peerSyncingPolicy]; + + [self proceedWithPeerID:peerID refetchWasNeeded:refetchWasNeeded]; + }]; +} + +- (void)proceedWithPeerID:(NSString*)peerID refetchWasNeeded:(BOOL)refetchWasNeeded +{ + WEAKIFY(self); + + // After a vouch, we also want to acquire all TLKs that the bottled peer might have had + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:refetchWasNeeded]; + [self runBeforeGroupFinished:fetchKeysOp]; + + CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"bottle-tlks" + withBlock:^{ + STRONGIFY(self); + NSMutableArray* filteredTLKShares = [NSMutableArray array]; - for(CKKSTLKShare* share in tlkShares) { + for(CKKSTLKShare* share in fetchKeysOp.tlkShares) { // If we didn't get a peerID, just pass every tlkshare and hope for the best if(peerID == nil || [share.receiverPeerID isEqualToString:peerID]) { [filteredTLKShares addObject:share]; } } - [self proceedWithKeys:viewKeySets filteredTLKShares:filteredTLKShares]; + if(fetchKeysOp.viewsTimedOutWithoutKeysets.count > 0) { + // At least one view failed to find a keyset in time. + // Set up a retry with this bottle, once CKKS is done fetching + secnotice("octagon", "Timed out fetching key hierarchy for CKKS views; marking for TLK recovery follow up: %@", fetchKeysOp.viewsTimedOutWithoutKeysets); + OctagonPendingFlag* flag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptBottleTLKExtraction + after:self.deps.viewManager.zoneChangeFetcher.inflightFetch]; + [self.deps.flagHandler handlePendingFlag:flag]; + } + + [self proceedWithKeys:fetchKeysOp.viewKeySets filteredTLKShares:filteredTLKShares]; }]; + + [proceedWithKeys addDependency:fetchKeysOp]; + [self runBeforeGroupFinished:proceedWithKeys]; +} + + +- (void)noteMetric:(NSString*)metric count:(int64_t)count +{ + NSString* metricName = [NSString stringWithFormat:@"%@%lld", metric, count]; + + [[CKKSAnalytics logger] logResultForEvent:metricName + hardFailure:NO + result:nil]; + + [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:metricName]; + [[CKKSAnalytics logger] setNumberProperty:[[NSNumber alloc]initWithLong:count] forKey:metric]; } - (void)proceedWithKeys:(NSArray*)viewKeySets filteredTLKShares:(NSArray*)tlkShares @@ -153,7 +188,11 @@ entropy:self.entropy bottleSalt:self.bottleSalt tlkShares:tlkShares - reply:^(NSData * _Nullable voucher, NSData * _Nullable voucherSig, NSError * _Nullable error) { + reply:^(NSData * _Nullable voucher, + NSData * _Nullable voucherSig, + int64_t uniqueTLKsRecovered, + int64_t totalTLKSharesRecovered, + NSError * _Nullable error) { STRONGIFY(self); [[CKKSAnalytics logger] logResultForEvent:OctagonEventVoucherWithBottle hardFailure:true result:error]; @@ -164,10 +203,43 @@ return; } - secnotice("octagon", "Received bottle voucher"); + //collect TLK count metrics + [self noteMetric:OctagonAnalyticsBottledUniqueTLKsRecovered count:uniqueTLKsRecovered]; + [self noteMetric:OctagonAnalyticsBottledTotalTLKSharesRecovered count:totalTLKSharesRecovered]; + [self noteMetric:OctagonAnalyticsBottledTotalTLKShares count:tlkShares.count]; + + NSMutableSet* uniqueTLKsWithShares = [NSMutableSet set]; + for (CKKSTLKShare* share in tlkShares) { + [uniqueTLKsWithShares addObject:share.tlkUUID]; + } + + [self noteMetric:OctagonAnalyticsBottledUniqueTLKsWithSharesCount count:uniqueTLKsWithShares.count]; + + NSMutableDictionary *views = [NSMutableDictionary dictionary]; + for (CKKSTLKShare *share in tlkShares) { + views[share.zoneID] = share.zoneID; + } + [self noteMetric:OctagonAnalyticsBottledTLKUniqueViewCount count:views.count]; self.voucher = voucher; self.voucherSig = voucherSig; + + if(self.saveVoucher) { + secnotice("octagon", "Saving voucher for later use..."); + NSError* saveError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.voucher = voucher; + metadata.voucherSignature = voucherSig; + return metadata; + } error:&saveError]; + if(saveError) { + secnotice("octagon", "unable to save voucher: %@", saveError); + [self runBeforeGroupFinished:self.finishedOp]; + return; + } + } + + secnotice("octagon", "Successfully vouched with a bottle: %@, %@", voucher, voucherSig); self.nextState = self.intendedState; [self runBeforeGroupFinished:self.finishedOp]; }]; diff --git a/keychain/ot/OTVouchWithRecoveryKeyOperation.h b/keychain/ot/OTVouchWithRecoveryKeyOperation.h index 12712c0e..ba3f884a 100644 --- a/keychain/ot/OTVouchWithRecoveryKeyOperation.h +++ b/keychain/ot/OTVouchWithRecoveryKeyOperation.h @@ -39,14 +39,16 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState errorState:(OctagonState*)errorState - recoveryKey:(NSString*)recoveryKey; + recoveryKey:(NSString*)recoveryKey + saveVoucher:(BOOL)saveVoucher; @property (weak) OTCuttlefishContext* cuttlefishContext; -@property (nonatomic) NSString* salt; -@property (nonatomic) NSString* recoveryKey; @property (nonatomic) NSData* voucher; @property (nonatomic) NSData* voucherSig; + +// Controls whether or not to save the received voucher in the state handler. +@property (readonly) BOOL saveVoucher; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTVouchWithRecoveryKeyOperation.m b/keychain/ot/OTVouchWithRecoveryKeyOperation.m index 0bb767fe..89012c95 100644 --- a/keychain/ot/OTVouchWithRecoveryKeyOperation.m +++ b/keychain/ot/OTVouchWithRecoveryKeyOperation.m @@ -29,6 +29,7 @@ #import "keychain/ot/OTClientStateMachine.h" #import "keychain/ot/OTCuttlefishContext.h" #import "keychain/ot/OTFetchCKKSKeysOperation.h" +#import "keychain/ot/OTStates.h" #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" #import "keychain/ot/ObjCImprovements.h" @@ -36,6 +37,9 @@ @interface OTVouchWithRecoveryKeyOperation () @property OTOperationDependencies* deps; +@property NSString* salt; +@property NSString* recoveryKey; + @property NSOperation* finishOp; @end @@ -46,6 +50,7 @@ intendedState:(OctagonState*)intendedState errorState:(OctagonState*)errorState recoveryKey:(NSString*)recoveryKey + saveVoucher:(BOOL)saveVoucher { if((self = [super init])) { _deps = dependencies; @@ -53,6 +58,8 @@ _nextState = errorState; _recoveryKey = recoveryKey; + + _saveVoucher = saveVoucher; } return self; } @@ -64,42 +71,85 @@ self.finishOp = [[NSOperation alloc] init]; [self dependOnBeforeGroupFinished:self.finishOp]; - NSString* salt = nil; + NSString *altDSID = [self.deps.authKitAdapter primaryiCloudAccountAltDSID:nil]; + if(altDSID){ + secnotice("octagon", "using auth kit adapter, altdsid is: %@", altDSID); + self.salt = altDSID; + } + else { + NSError* accountError = nil; + OTAccountMetadataClassC* account = [self.deps.stateHolder loadOrCreateAccountMetadata:&accountError]; - if(self.salt != nil) { - secnotice("octagon", "using passed in altdsid, altdsid is: %@", self.salt); - salt = self.salt; - } else{ - NSString *altDSID = [self.deps.authKitAdapter primaryiCloudAccountAltDSID:nil]; - if(altDSID){ - secnotice("octagon", "using auth kit adapter, altdsid is: %@", altDSID); - salt = altDSID; + if(account && !accountError) { + secnotice("octagon", "retrieved account, altdsid is: %@", account.altDSID); + self.salt = account.altDSID; } - else { - NSError* accountError = nil; - OTAccountMetadataClassC* account = [self.deps.stateHolder loadOrCreateAccountMetadata:&accountError]; - - if(account && !accountError) { - secnotice("octagon", "retrieved account, altdsid is: %@", account.altDSID); - salt = account.altDSID; - } - if(accountError || !account){ - secerror("failed to rerieve account object: %@", accountError); - } + if(accountError || !account){ + secerror("failed to rerieve account object: %@", accountError); } } + // First, let's preflight the vouch (to receive a policy and view set to use for TLK fetching + WEAKIFY(self); + [self.deps.cuttlefishXPCWrapper preflightVouchWithRecoveryKeyWithContainer:self.deps.containerName + context:self.deps.contextID + recoveryKey:self.recoveryKey + salt:self.salt + reply:^(NSString * _Nullable recoveryKeyID, + TPSyncingPolicy* _Nullable peerSyncingPolicy, + NSError * _Nullable error) { + STRONGIFY(self); + [[CKKSAnalytics logger] logResultForEvent:OctagonEventPreflightVouchWithRecoveryKey hardFailure:true result:error]; + + if(error || !recoveryKeyID) { + secerror("octagon: Error preflighting voucher using recovery key: %@", error); + self.error = error; + [self runBeforeGroupFinished:self.finishOp]; + return; + } + + secnotice("octagon", "Recovery key ID %@ looks good to go", recoveryKeyID); + + // Tell CKKS to spin up the new views and policy + // But, do not persist this view set! We'll do that when we actually manage to join + [self.deps.viewManager setCurrentSyncingPolicy:peerSyncingPolicy]; + + [self proceedWithRecoveryKeyID:recoveryKeyID]; + }]; +} + +- (void)proceedWithRecoveryKeyID:(NSString*)recoveryKeyID +{ WEAKIFY(self); // After a vouch, we also want to acquire all TLKs that the bottled peer might have had - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"recovery-tlks" withBlock:^{ - STRONGIFY(self); - [self proceedWithKeys:fetchKeysOp.viewKeySets tlkShares:fetchKeysOp.tlkShares salt:salt]; - }]; + STRONGIFY(self); + + NSMutableArray* filteredTLKShares = [NSMutableArray array]; + for(CKKSTLKShare* share in fetchKeysOp.tlkShares) { + // If we didn't get a recoveryKeyID, just pass every tlkshare and hope for the best + if(recoveryKeyID == nil || [share.receiverPeerID isEqualToString:recoveryKeyID]) { + [filteredTLKShares addObject:share]; + } + } + + if(fetchKeysOp.viewsTimedOutWithoutKeysets.count > 0) { + // At least one view failed to find a keyset in time. + // Set up a retry with this recovery key, once CKKS is done fetching + secnotice("octagon", "Timed out fetching key hierarchy for CKKS views; marking for TLK recovery follow up: %@", fetchKeysOp.viewsTimedOutWithoutKeysets); + OctagonPendingFlag* flag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptRecoveryKeyTLKExtraction + after:self.deps.viewManager.zoneChangeFetcher.inflightFetch]; + [self.deps.flagHandler handlePendingFlag:flag]; + } + + [self proceedWithKeys:fetchKeysOp.viewKeySets tlkShares:filteredTLKShares salt:self.salt]; + }]; [proceedWithKeys addDependency:fetchKeysOp]; [self runBeforeGroupFinished:proceedWithKeys]; @@ -125,6 +175,23 @@ } self.voucher = voucher; self.voucherSig = voucherSig; + + if(self.saveVoucher) { + secnotice("octagon", "Saving voucher for later use..."); + NSError* saveError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.voucher = voucher; + metadata.voucherSignature = voucherSig; + return metadata; + } error:&saveError]; + if(saveError) { + secnotice("octagon", "unable to save voucher: %@", saveError); + [self runBeforeGroupFinished:self.finishOp]; + return; + } + } + + secnotice("octagon", "Successfully vouched with a recovery key: %@, %@", voucher, voucherSig); self.nextState = self.intendedState; [self runBeforeGroupFinished:self.finishOp]; }]; diff --git a/keychain/ot/OctagonCKKSPeerAdapter.h b/keychain/ot/OctagonCKKSPeerAdapter.h index 4936cc22..ead418ae 100644 --- a/keychain/ot/OctagonCKKSPeerAdapter.h +++ b/keychain/ot/OctagonCKKSPeerAdapter.h @@ -2,8 +2,9 @@ #if OCTAGON #import -#import "keychain/ot/OTOperationDependencies.h" #import "keychain/ckks/CKKSPeer.h" +#import "keychain/ckks/CKKSPeerProvider.h" +#import "keychain/ot/CuttlefishXPCWrapper.h" NS_ASSUME_NONNULL_BEGIN @@ -19,10 +20,15 @@ NS_ASSUME_NONNULL_BEGIN @interface OctagonCKKSPeerAdapter : NSObject @property (nullable) NSString* peerID; -@property OTOperationDependencies* deps; +@property (readonly) CuttlefishXPCWrapper* cuttlefishXPCWrapper; +@property (readonly) NSString* containerName; +@property (readonly) NSString* contextID; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithPeerID:(NSString*)peerID operationDependencies:(OTOperationDependencies*)deps; +- (instancetype)initWithPeerID:(NSString*)peerID + containerName:(NSString*)containerName + contextID:(NSString*)contextID + cuttlefishXPC:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OctagonCKKSPeerAdapter.m b/keychain/ot/OctagonCKKSPeerAdapter.m index b7707e9e..b664f8c7 100644 --- a/keychain/ot/OctagonCKKSPeerAdapter.m +++ b/keychain/ot/OctagonCKKSPeerAdapter.m @@ -80,12 +80,19 @@ @synthesize essential = _essential; @synthesize providerID = _providerID; -- (instancetype)initWithPeerID:(NSString*)peerID operationDependencies:(OTOperationDependencies*)deps + +- (instancetype)initWithPeerID:(NSString*)peerID + containerName:(NSString*)containerName + contextID:(NSString*)contextID + cuttlefishXPC:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper { if((self = [super init])) { _providerID = [NSString stringWithFormat:@"[OctagonCKKSPeerAdapter:%@]", peerID]; _peerID = peerID; - _deps = deps; + + _containerName = containerName; + _contextID = contextID; + _cuttlefishXPCWrapper = cuttlefishXPCWrapper; _peerChangeListeners = [[CKKSListenerCollection alloc] initWithName:@"ckks-sos"]; @@ -181,14 +188,14 @@ __block NSMutableSet> * peers = nil; WEAKIFY(self); - [self.deps.cuttlefishXPCWrapper fetchTrustStateWithContainer:self.deps.containerName - context:self.deps.contextID - reply:^(TrustedPeersHelperPeerState * _Nullable selfPeerState, - NSArray * _Nullable trustedPeers, - NSError * _Nullable operror) { + [self.cuttlefishXPCWrapper fetchTrustStateWithContainer:self.containerName + context:self.contextID + reply:^(TrustedPeersHelperPeerState * _Nullable selfPeerState, + NSArray * _Nullable trustedPeers, + NSError * _Nullable operror) { STRONGIFY(self); if(operror) { - secnotice("octagon", "Unable to fetch trusted peers for (%@,%@): %@", self.deps.containerName, self.deps.contextID, operror); + secnotice("octagon", "Unable to fetch trusted peers for (%@,%@): %@", self.containerName, self.contextID, operror); localerror = operror; } else { @@ -203,8 +210,6 @@ encryptionPublicKey:encryptionKey signingPublicKey:signingKey viewList:peer.viewList]; - secnotice("octagon", "Have trusted peer %@", ckkspeer); - [peers addObject:ckkspeer]; } } diff --git a/keychain/ot/OctagonCheckTrustStateOperation.m b/keychain/ot/OctagonCheckTrustStateOperation.m index 9fe406bf..254d3278 100644 --- a/keychain/ot/OctagonCheckTrustStateOperation.m +++ b/keychain/ot/OctagonCheckTrustStateOperation.m @@ -79,7 +79,7 @@ if(localError) { if([self.deps.lockStateTracker isLockedError:localError]) { secerror("octagon-consistency: Unable to fetch current account state due to lock state: %@", localError); - self.nextState = OctagonStateWaitForUnlock; + self.nextState = OctagonStateWaitForClassCUnlock; [self runBeforeGroupFinished:self.finishedOp]; return; } @@ -148,7 +148,7 @@ if(!persisted || localError) { if([self.deps.lockStateTracker isLockedError:localError]) { secerror("octagon-consistency: Unable to save new account state due to lock state: %@", localError); - self.nextState = OctagonStateWaitForUnlock; + self.nextState = OctagonStateWaitForClassCUnlock; [self runBeforeGroupFinished:self.finishedOp]; return; } diff --git a/keychain/ot/OctagonControlServer.m b/keychain/ot/OctagonControlServer.m index 9d67c837..97350422 100644 --- a/keychain/ot/OctagonControlServer.m +++ b/keychain/ot/OctagonControlServer.m @@ -115,7 +115,7 @@ return NO; } - secnotice("octagon", "received connection from client pid %d", [newConnection processIdentifier]); + secinfo("octagon", "received connection from client pid %d", [newConnection processIdentifier]); newConnection.exportedInterface = OTSetupControlProtocol([NSXPCInterface interfaceWithProtocol:@protocol(OTControlProtocol)]); newConnection.exportedObject = [OctagonXPCEntitlementChecker createWithManager:[OTManager manager] entitlementBearer:newConnection]; diff --git a/keychain/ot/OctagonFlags.m b/keychain/ot/OctagonFlags.m index b42fc447..455ee795 100644 --- a/keychain/ot/OctagonFlags.m +++ b/keychain/ot/OctagonFlags.m @@ -22,9 +22,9 @@ _flagConditions = [[NSMutableDictionary alloc] init]; _allowableFlags = possibleFlags; - [possibleFlags enumerateObjectsUsingBlock:^(OctagonState * _Nonnull obj, BOOL * _Nonnull stop) { - self.flagConditions[obj] = [[CKKSCondition alloc] init]; - }]; + for(OctagonFlag* flag in possibleFlags) { + self.flagConditions[flag] = [[CKKSCondition alloc] init]; + } } return self; } diff --git a/keychain/ot/OctagonPendingFlag.h b/keychain/ot/OctagonPendingFlag.h index a130fcef..c922e02a 100644 --- a/keychain/ot/OctagonPendingFlag.h +++ b/keychain/ot/OctagonPendingFlag.h @@ -13,6 +13,7 @@ NS_ASSUME_NONNULL_BEGIN typedef NS_OPTIONS(NSUInteger, OctagonPendingConditions) { OctagonPendingConditionsDeviceUnlocked = 1, + OctagonPendingConditionsNetworkReachable = 2, }; NSString* OctagonPendingConditionsToString(OctagonPendingConditions cond); @@ -25,8 +26,15 @@ NSString* OctagonPendingConditionsToString(OctagonPendingConditions cond); @property (readonly) OctagonPendingConditions conditions; +@property (nullable) NSOperation* afterOperation; + - (instancetype)initWithFlag:(OctagonFlag*)flag delayInSeconds:(NSTimeInterval)delay; - (instancetype)initWithFlag:(OctagonFlag*)flag conditions:(OctagonPendingConditions)conditions; +- (instancetype)initWithFlag:(OctagonFlag*)flag after:(NSOperation*)op; + +- (instancetype)initWithFlag:(OctagonFlag*)flag + conditions:(OctagonPendingConditions)conditions + delayInSeconds:(NSTimeInterval)delay; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OctagonPendingFlag.m b/keychain/ot/OctagonPendingFlag.m index d192ae41..672093d6 100644 --- a/keychain/ot/OctagonPendingFlag.m +++ b/keychain/ot/OctagonPendingFlag.m @@ -21,6 +21,7 @@ NSString* OctagonPendingConditionsToString(OctagonPendingConditions cond) if ((self = [super init])) { _flag = flag; _fireTime = [NSDate dateWithTimeIntervalSinceNow:delay]; + _afterOperation = nil; _conditions = 0; } return self; @@ -28,11 +29,30 @@ NSString* OctagonPendingConditionsToString(OctagonPendingConditions cond) - (instancetype)initWithFlag:(OctagonFlag*)flag conditions:(OctagonPendingConditions)conditions +{ + return [self initWithFlag:flag conditions:conditions delayInSeconds:0]; +} + +- (instancetype)initWithFlag:(OctagonFlag*)flag + conditions:(OctagonPendingConditions)conditions + delayInSeconds:(NSTimeInterval)delay +{ + if ((self = [super init])) { + _flag = flag; + _fireTime = delay > 0 ? [NSDate dateWithTimeIntervalSinceNow:delay] : nil; + _afterOperation = nil; + _conditions = conditions; + } + return self; +} + +- (instancetype)initWithFlag:(OctagonFlag*)flag after:(NSOperation*)op { if ((self = [super init])) { _flag = flag; _fireTime = nil; - _conditions = conditions; + _afterOperation = op; + _conditions = 0; } return self; } @@ -40,6 +60,8 @@ NSString* OctagonPendingConditionsToString(OctagonPendingConditions cond) - (NSString*)description { if(self.fireTime) { return [NSString stringWithFormat:@"", self.flag, self.fireTime]; + } else if(self.afterOperation) { + return [NSString stringWithFormat:@"", self.flag, self.afterOperation]; } else { return [NSString stringWithFormat:@"", self.flag, OctagonPendingConditionsToString(self.conditions)]; } diff --git a/keychain/ot/OctagonStateMachine.h b/keychain/ot/OctagonStateMachine.h index 4aeabe1c..d50038f9 100644 --- a/keychain/ot/OctagonStateMachine.h +++ b/keychain/ot/OctagonStateMachine.h @@ -5,6 +5,7 @@ #import "keychain/ckks/CKKSResultOperation.h" #import "keychain/ckks/CKKSCondition.h" #import "keychain/ckks/CKKSLockStateTracker.h" +#import "keychain/ckks/CKKSReachabilityTracker.h" #import "keychain/ot/OctagonStateMachineHelpers.h" #import "keychain/ot/OctagonStateMachineObservers.h" @@ -27,12 +28,15 @@ NS_ASSUME_NONNULL_BEGIN @protocol OctagonStateMachineEngine - (CKKSResultOperation* _Nullable)_onqueueNextStateMachineTransition:(OctagonState*)currentState flags:(OctagonFlags*)flags - pendingFlags:(id)pendingFlagHandler; + pendingFlags:(id)pendingFlags; @end @protocol OctagonStateFlagHandler - (void)handleFlag:(OctagonFlag*)flag; - (void)handlePendingFlag:(OctagonPendingFlag*)pendingFlag; + +// If you've truly broken your queue ordering, then call this from whatever queue your flag handler is using. +- (void)_onqueueHandleFlag:(OctagonFlag*)flag; @end @interface OctagonStateMachine : NSObject @@ -42,16 +46,18 @@ NS_ASSUME_NONNULL_BEGIN // Adding flags should use -handleFlag on the state machine @property (readonly) id flags; -@property NSMutableDictionary* stateConditions; +@property (readonly) NSDictionary* stateConditions; @property (readonly) CKKSCondition* paused; @property (readonly) NSSet* allowableStates; @property (nonatomic) uint64_t timeout; -@property (nullable) CKKSLockStateTracker* lockStateTracker; +@property (readonly, nullable) CKKSLockStateTracker* lockStateTracker; +@property (readonly, nullable) CKKSReachabilityTracker* reachabilityTracker; // If you don't pass a lock state tracker, then you cannot reasonably use OctagonPendingConditionsDeviceUnlocked +// If you don't pass a reachability tracker, then you cannot reasonably use OctagonPendingConditionsNetworkReachable - (instancetype)initWithName:(NSString*)name states:(NSSet*)possibleStates @@ -59,7 +65,8 @@ NS_ASSUME_NONNULL_BEGIN initialState:(OctagonState*)initialState queue:(dispatch_queue_t)queue stateEngine:(id)stateEngine - lockStateTracker:(CKKSLockStateTracker*)lockStateTracker; + lockStateTracker:(CKKSLockStateTracker* _Nullable)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker* _Nullable)reachabilityTracker; - (void)startOperation; - (void)haltOperation; @@ -70,27 +77,27 @@ NS_ASSUME_NONNULL_BEGIN // This will set the given flag, and ensure that the state machine spins to handle it. - (void)handleFlag:(OctagonFlag*)flag; +- (void)_onqueueHandleFlag:(OctagonFlag*)flag; // This will schedule the flag for future addition - (void)handlePendingFlag:(OctagonPendingFlag *)pendingFlag; - (NSDictionary*)dumpPendingFlags; -// For testing -- (NSArray*)possiblePendingFlags; -- (void)disablePendingFlags; - (void)handleExternalRequest:(OctagonStateTransitionRequest*>*)request; + - (void)registerStateTransitionWatcher:(OctagonStateTransitionWatcher*)watcher; +- (void)registerMultiStateArrivalWatcher:(OctagonStateMultiStateArrivalWatcher*)watcher; - (void)doSimpleStateMachineRPC:(NSString*)name op:(CKKSResultOperation*)op sourceStates:(NSSet*)sourceStates reply:(nonnull void (^)(NSError * _Nullable))reply; -- (void)doWatchedStateMachineRPC:(NSString*)name - sourceStates:(NSSet*)sourceStates - path:(OctagonStateTransitionPath*)path - reply:(nonnull void (^)(NSError *error))reply; +- (CKKSResultOperation*)doWatchedStateMachineRPC:(NSString*)name + sourceStates:(NSSet*)sourceStates + path:(OctagonStateTransitionPath*)path + reply:(nonnull void (^)(NSError *error))reply; - (void)setWatcherTimeout:(uint64_t)timeout; - (BOOL)isPaused; @@ -101,6 +108,15 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface OctagonStateMachine (Testing) +// For testing +- (NSArray*)possiblePendingFlags; +- (void)disablePendingFlags; + +- (void)testPauseStateMachineAfterEntering:(OctagonState*)pauseState; +- (void)testReleaseStateMachinePause:(OctagonState*)pauseState; +@end + NS_ASSUME_NONNULL_END #endif diff --git a/keychain/ot/OctagonStateMachine.m b/keychain/ot/OctagonStateMachine.m index dcd693ad..2bc0d3d6 100644 --- a/keychain/ot/OctagonStateMachine.m +++ b/keychain/ot/OctagonStateMachine.m @@ -23,6 +23,8 @@ format, @property (weak) id stateEngine; +@property NSMutableDictionary* mutableStateConditions; + @property dispatch_queue_t queue; @property NSOperationQueue* operationQueue; @@ -36,10 +38,13 @@ format, // Set this to an operation to pause the state machine in-flight @property NSOperation* holdStateMachineOperation; +// When entering any state in this set, holdStateMachineOperation will be filled in +@property NSMutableSet* testHoldStates; + @property (nullable) CKKSResultOperation* nextStateMachineCycleOperation; @property NSMutableArray*>*>* stateMachineRequests; -@property NSMutableArray* stateMachineWatchers; +@property NSMutableArray>* stateMachineWatchers; @property BOOL halted; @property bool allowPendingFlags; @@ -48,7 +53,8 @@ format, @property OctagonPendingConditions conditionChecksInFlight; @property OctagonPendingConditions currentConditions; -@property NSOperation* checkUnlockOperation; +@property (nullable) NSOperation* checkUnlockOperation; +@property (nullable) NSOperation* checkReachabilityOperation; @end @implementation OctagonStateMachine @@ -60,11 +66,13 @@ format, queue:(dispatch_queue_t)queue stateEngine:(id)stateEngine lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker { if ((self = [super init])) { _name = name; _lockStateTracker = lockStateTracker; + _reachabilityTracker = reachabilityTracker; _conditionChecksInFlight = 0; _currentConditions = 0; @@ -78,11 +86,12 @@ format, _stateEngine = stateEngine; _holdStateMachineOperation = [NSBlockOperation blockOperationWithBlock:^{}]; + _testHoldStates = [NSMutableSet set]; _halted = false; - _stateConditions = [[NSMutableDictionary alloc] init]; + _mutableStateConditions = [[NSMutableDictionary alloc] init]; [possibleStates enumerateObjectsUsingBlock:^(OctagonState * _Nonnull obj, BOOL * _Nonnull stop) { - self.stateConditions[obj] = [[CKKSCondition alloc] init]; + self.mutableStateConditions[obj] = [[CKKSCondition alloc] init]; }]; // Use the setter method to set the condition variables @@ -118,6 +127,17 @@ format, return self; } + +- (NSDictionary*)stateConditions +{ + __block NSDictionary* conditions = nil; + dispatch_sync(self.queue, ^{ + conditions = [self.mutableStateConditions copy]; + }); + + return conditions; +} + - (NSString*)pendingFlagsString { return [self.pendingFlags.allValues componentsJoinedByString:@","]; @@ -148,14 +168,14 @@ format, } else { // Fixup the condition variables as part of setting this state if(_currentState) { - self.stateConditions[_currentState] = [[CKKSCondition alloc] init]; + self.mutableStateConditions[_currentState] = [[CKKSCondition alloc] init]; } NSAssert([self.allowableStates containsObject:state], @"state machine tried to enter unknown state %@", state); _currentState = state; if(state) { - [self.stateConditions[state] fulfill]; + [self.mutableStateConditions[state] fulfill]; } } } @@ -209,6 +229,12 @@ format, return; } + if([self.testHoldStates containsObject:self.currentState]) { + statemachinelog("state", "In test hold for state %@; pausing", self.currentState); + [self.paused fulfill]; + return; + } + CKKSResultOperation* nextOp = [self _onqueueNextStateMachineTransition]; if(nextOp) { statemachinelog("state", "Beginning state transition attempt %@", nextOp); @@ -246,7 +272,7 @@ format, op, op.error ?: @"(no error)"); - for(OctagonStateTransitionWatcher* watcher in self.stateMachineWatchers) { + for(id watcher in self.stateMachineWatchers) { statemachinelog("state", "notifying watcher: %@", watcher); [watcher onqueueHandleTransition:op]; } @@ -286,11 +312,18 @@ format, - (void)handleFlag:(OctagonFlag*)flag { dispatch_sync(self.queue, ^{ - [self.currentFlags _onqueueSetFlag:flag]; - [self _onqueuePokeStateMachine]; + [self _onqueueHandleFlag:flag]; }); } + +- (void)_onqueueHandleFlag:(OctagonFlag*)flag +{ + dispatch_assert_queue(self.queue); + [self.currentFlags _onqueueSetFlag:flag]; + [self _onqueuePokeStateMachine]; +} + - (void)handlePendingFlag:(OctagonPendingFlag *)pendingFlag { dispatch_sync(self.queue, ^{ [self _onqueueHandlePendingFlag:pendingFlag]; @@ -303,15 +336,27 @@ format, // Overwrite any existing pending flag! self.pendingFlags[pendingFlag.flag] = pendingFlag; - self.currentFlags.flagConditions[pendingFlag.flag] = [[CKKSCondition alloc]init]; - - // Do we need to recheck any conditions? Anything which is currently the state of the world needs checking + // Do we need to recheck any conditions? Anything which is currently the state of the world needs checking, as it might have changed since the last check OctagonPendingConditions recheck = pendingFlag.conditions & self.currentConditions; + // Technically don't need this if check, as the bit-twiddling below will no-op if it's false, but it adds readability if(recheck != 0x0) { - // Technically don't need this if, but it adds readability self.currentConditions &= ~recheck; } + if(pendingFlag.afterOperation) { + WEAKIFY(self); + NSOperation* after = [NSBlockOperation blockOperationWithBlock:^{ + STRONGIFY(self); + dispatch_sync(self.queue, ^{ + statemachinelog("pending-flag", "Finished waiting for operation"); + [self _onqueueSendAnyPendingFlags]; + }); + }]; + + [after addNullableDependency:pendingFlag.afterOperation]; + [self.operationQueue addOperation:after]; + } + [self _onqueueRecheckConditions]; [self _onqueueSendAnyPendingFlags]; } @@ -366,6 +411,7 @@ format, WEAKIFY(self); if(conditionsToCheck & OctagonPendingConditionsDeviceUnlocked) { + NSAssert(self.lockStateTracker != nil, @"Must have a lock state tracker to wait for unlock"); statemachinelog("conditions", "Waiting for unlock"); self.checkUnlockOperation = [NSBlockOperation blockOperationWithBlock:^{ STRONGIFY(self); @@ -381,6 +427,24 @@ format, [self.checkUnlockOperation addNullableDependency:self.lockStateTracker.unlockDependency]; [self.operationQueue addOperation:self.checkUnlockOperation]; } + + if(conditionsToCheck & OctagonPendingConditionsNetworkReachable) { + statemachinelog("conditions", "Waiting for network reachability"); + NSAssert(self.reachabilityTracker != nil, @"Must have a network reachability tracker to use network reachability pending flags"); + self.checkReachabilityOperation = [NSBlockOperation blockOperationWithBlock:^{ + STRONGIFY(self); + dispatch_sync(self.queue, ^{ + statemachinelog("pending-flag", "Network is reachable"); + self.currentConditions |= OctagonPendingConditionsNetworkReachable; + self.conditionChecksInFlight &= ~OctagonPendingConditionsNetworkReachable; + [self _onqueueSendAnyPendingFlags]; + }); + }]; + self.conditionChecksInFlight |= OctagonPendingConditionsNetworkReachable; + + [self.checkReachabilityOperation addNullableDependency:self.reachabilityTracker.reachabilityDependency]; + [self.operationQueue addOperation:self.checkReachabilityOperation]; + } } - (void)_onqueueSendAnyPendingFlags @@ -411,6 +475,14 @@ format, } } + if(pendingFlag.afterOperation) { + if(![pendingFlag.afterOperation isFinished]) { + send = false; + } else { + statemachinelog("pending-flag", "Operation has ended for pending flag %@: %@", pendingFlag.flag, pendingFlag.afterOperation); + } + } + if(pendingFlag.conditions != 0x0) { // Also, send the flag if the conditions are right if((pendingFlag.conditions & self.currentConditions) == pendingFlag.conditions) { @@ -442,6 +514,22 @@ format, #pragma mark - Client Services + +- (void)testPauseStateMachineAfterEntering:(OctagonState*)pauseState +{ + dispatch_sync(self.queue, ^{ + [self.testHoldStates addObject:pauseState]; + }); +} + +- (void)testReleaseStateMachinePause:(OctagonState*)pauseState +{ + dispatch_sync(self.queue, ^{ + [self.testHoldStates removeObject:pauseState]; + [self _onqueuePokeStateMachine]; + }); +} + - (BOOL)isPaused { __block BOOL ret = false; @@ -487,6 +575,7 @@ format, }); } + - (void)registerStateTransitionWatcher:(OctagonStateTransitionWatcher*)watcher { dispatch_sync(self.queue, ^{ @@ -495,6 +584,18 @@ format, }); } +- (void)registerMultiStateArrivalWatcher:(OctagonStateMultiStateArrivalWatcher*)watcher +{ + dispatch_sync(self.queue, ^{ + if([watcher.states containsObject:self.currentState]) { + [watcher onqueueEnterState:self.currentState]; + } else { + [self.stateMachineWatchers addObject:watcher]; + [self _onqueuePokeStateMachine]; + } + }); +} + #pragma mark - RPC Helpers - (void)doSimpleStateMachineRPC:(NSString*)name @@ -504,6 +605,9 @@ format, { statemachinelog("state-rpc", "Beginning a '%@' rpc", name); + if (self.lockStateTracker) { + [self.lockStateTracker recheck]; + } OctagonStateTransitionRequest* request = [[OctagonStateTransitionRequest alloc] init:name sourceStates:sourceStates serialQueue:self.queue @@ -527,13 +631,17 @@ format, self.timeout = timeout; } -- (void)doWatchedStateMachineRPC:(NSString*)name - sourceStates:(NSSet*)sourceStates - path:(OctagonStateTransitionPath*)path - reply:(nonnull void (^)(NSError *error))reply +- (CKKSResultOperation*)doWatchedStateMachineRPC:(NSString*)name + sourceStates:(NSSet*)sourceStates + path:(OctagonStateTransitionPath*)path + reply:(nonnull void (^)(NSError *error))reply { statemachinelog("state-rpc", "Beginning a '%@' rpc", name); + if (self.lockStateTracker) { + [self.lockStateTracker recheck]; + } + CKKSResultOperation* initialTransitionOp = [OctagonStateTransitionOperation named:[NSString stringWithFormat:@"intial-transition-%@", name] entering:path.initialState]; @@ -553,18 +661,21 @@ format, [self registerStateTransitionWatcher:watcher]; - WEAKIFY(self); CKKSResultOperation* replyOp = [CKKSResultOperation named:[NSString stringWithFormat: @"%@-callback", name] - withBlock:^{ - STRONGIFY(self); - statemachinelog("state-rpc", "Returning '%@' result: %@", name, watcher.result.error ?: @"no error"); - reply(watcher.result.error); - }]; + withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { + statemachinelog("state-rpc", "Returning '%@' result: %@", name, watcher.result.error ?: @"no error"); + if(reply) { + reply(watcher.result.error); + } + op.error = watcher.result.error; + }]; + [replyOp addDependency:watcher.result]; [self.operationQueue addOperation:replyOp]; [self handleExternalRequest:request]; + return replyOp; } @end diff --git a/keychain/ot/OctagonStateMachineHelpers.h b/keychain/ot/OctagonStateMachineHelpers.h index d936223d..acbd2ff7 100644 --- a/keychain/ot/OctagonStateMachineHelpers.h +++ b/keychain/ot/OctagonStateMachineHelpers.h @@ -25,6 +25,7 @@ #import #import "keychain/ckks/CKKSResultOperation.h" +#import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ckks/CKKSAnalytics.h" NS_ASSUME_NONNULL_BEGIN @@ -66,6 +67,17 @@ extern OctagonState* const OctagonStateMachineHalted; entering:(OctagonState*)intendedState NS_SWIFT_NAME(init(name:entering:)); @end +// Just like OctagonStateTransitionOperation, but as a Group Operation +@interface OctagonStateTransitionGroupOperation : CKKSGroupOperation +@property OctagonState* nextState; +@property (readonly) OctagonState* intendedState; + ++ (instancetype)named:(NSString*)name + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState + withBlockTakingSelf:(void(^)(OctagonStateTransitionGroupOperation* op))block; +@end + @interface OctagonStateTransitionRequest<__covariant OperationType : CKKSResultOperation*> : NSObject @property (readonly) NSString* name; @@ -82,6 +94,11 @@ extern OctagonState* const OctagonStateMachineHalted; transitionOp:(OperationType)transitionOp; @end +@interface NSError (Octagon) +- (NSTimeInterval)overallCuttlefishRetry; +- (bool)retryableCuttlefishError; +@end + NS_ASSUME_NONNULL_END #endif // OCTAGON diff --git a/keychain/ot/OctagonStateMachineHelpers.m b/keychain/ot/OctagonStateMachineHelpers.m index a2362e32..b3cb0ef2 100644 --- a/keychain/ot/OctagonStateMachineHelpers.m +++ b/keychain/ot/OctagonStateMachineHelpers.m @@ -28,11 +28,15 @@ #import "keychain/ot/OTDefines.h" #import "keychain/ot/OTConstants.h" #import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/CKKS.h" OctagonState* const OctagonStateMachineNotStarted = (OctagonState*) @"not_started"; OctagonState* const OctagonStateMachineHalted = (OctagonState*) @"halted"; -@implementation OctagonStateTransitionOperation : CKKSResultOperation +#pragma mark -- OctagonStateTransitionOperation + +@implementation OctagonStateTransitionOperation - (instancetype)initIntending:(OctagonState*)intendedState errorState:(OctagonState*)errorState { @@ -75,6 +79,43 @@ OctagonState* const OctagonStateMachineHalted = (OctagonState*) @"halted"; @end +#pragma mark -- OctagonStateTransitionGroupOperation + +@implementation OctagonStateTransitionGroupOperation +- (instancetype)initIntending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if((self = [super init])) { + _nextState = errorState; + _intendedState = intendedState; + } + return self; +} + +- (NSString*)description +{ + return [NSString stringWithFormat:@"", self.name, self.intendedState, self.nextState]; +} + ++ (instancetype)named:(NSString*)name + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState + withBlockTakingSelf:(void(^)(OctagonStateTransitionGroupOperation* op))block +{ + OctagonStateTransitionGroupOperation* op = [[self alloc] initIntending:intendedState + errorState:errorState]; + WEAKIFY(op); + [op runBeforeGroupFinished:[NSBlockOperation blockOperationWithBlock:^{ + STRONGIFY(op); + block(op); + }]]; + op.name = name; + return op; +} +@end + +#pragma mark -- OctagonStateTransitionRequest + @interface OctagonStateTransitionRequest () @property dispatch_queue_t queue; @property bool timeoutCanOccur; @@ -104,7 +145,7 @@ OctagonState* const OctagonStateMachineHalted = (OctagonState*) @"halted"; - (NSString*)description { - return [NSString stringWithFormat:@"", self.name, self.transitionOperation, self.sourceStates]; + return [NSString stringWithFormat:@"", self.name, self.transitionOperation, (unsigned int)[self.sourceStates count]]; } - (CKKSResultOperation* _Nullable)_onqueueStart @@ -138,4 +179,67 @@ OctagonState* const OctagonStateMachineHalted = (OctagonState*) @"halted"; @end +@implementation NSError (Octagon) + +- (NSTimeInterval)overallCuttlefishRetry { + NSTimeInterval baseDelay = SecCKKSTestsEnabled() ? 2 : 30; + NSTimeInterval ckDelay = CKRetryAfterSecondsForError(self); + NSTimeInterval cuttlefishDelay = [self cuttlefishRetryAfter]; + NSTimeInterval delay = MAX(ckDelay, cuttlefishDelay); + if (delay == 0) { + delay = baseDelay; + } + return delay; +} + +- (bool)retryableCuttlefishError { + bool retry = false; + // Specific errors that are transaction failed -- try them again + if ([self isCuttlefishError:CuttlefishErrorRetryableServerFailure] || + [self isCuttlefishError:CuttlefishErrorTransactionalFailure]) { + retry = true; + // These are the CuttlefishError -> FunctionErrorType + } else if ([self isCuttlefishError:CuttlefishErrorJoinFailed] || + [self isCuttlefishError:CuttlefishErrorUpdateTrustFailed] || + [self isCuttlefishError:CuttlefishErrorEstablishPeerFailed] || + [self isCuttlefishError:CuttlefishErrorEstablishBottleFailed] || + [self isCuttlefishError:CuttlefishErrorEscrowProxyFailure]) { + retry = true; + } else if ([self.domain isEqualToString:TrustedPeersHelperErrorDomain]) { + switch (self.code) { + case TrustedPeersHelperErrorUnknownCloudKitError: + retry = true; + break; + default: + break; + } + } else if ([self.domain isEqualToString:NSURLErrorDomain]) { + switch (self.code) { + case NSURLErrorTimedOut: + retry = true; + break; + default: + break; + } + } else if ([self.domain isEqualToString:CKErrorDomain]) { + if (self.userInfo[CKErrorRetryAfterKey] != nil) { + retry = true; + } else { + switch (self.code) { + case CKErrorNetworkFailure: + retry = true; + break; + default: + break; + } + } + } else if ([self isCKServerInternalError]) { + retry = true; + } + + return retry; +} + +@end + #endif // OCTAGON diff --git a/keychain/ot/OctagonStateMachineObservers.h b/keychain/ot/OctagonStateMachineObservers.h index afa30844..806da455 100644 --- a/keychain/ot/OctagonStateMachineObservers.h +++ b/keychain/ot/OctagonStateMachineObservers.h @@ -44,7 +44,13 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface OctagonStateTransitionWatcher : NSObject + +@protocol OctagonStateTransitionWatcherProtocol +@property (readonly) CKKSResultOperation* result; +- (void)onqueueHandleTransition:(CKKSResultOperation*)attempt; +@end + +@interface OctagonStateTransitionWatcher : NSObject @property (readonly) NSString* name; @property (readonly) CKKSResultOperation* result; @property (readonly) OctagonStateTransitionPath* intendedPath; @@ -57,7 +63,22 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)timeout:(dispatch_time_t)timeout; -- (void)onqueueHandleTransition:(CKKSResultOperation*)attempt; +@end + +// Reports on if any of the given states are entered +@interface OctagonStateMultiStateArrivalWatcher : NSObject +@property (readonly) NSString* name; +@property (readonly) CKKSResultOperation* result; +@property (readonly) NSSet* states; + +- (instancetype)initNamed:(NSString*)name + serialQueue:(dispatch_queue_t)queue + states:(NSSet*)states; + +// Called by the state machine if it's already in a state at registration time +- (void)onqueueEnterState:(OctagonState*)state; + +- (instancetype)timeout:(dispatch_time_t)timeout; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OctagonStateMachineObservers.m b/keychain/ot/OctagonStateMachineObservers.m index d7e86808..e7a819f2 100644 --- a/keychain/ot/OctagonStateMachineObservers.m +++ b/keychain/ot/OctagonStateMachineObservers.m @@ -268,4 +268,91 @@ @end +#pragma mark - OctagonStateMultiStateArrivalWatcher + +@interface OctagonStateMultiStateArrivalWatcher () +@property BOOL completed; +@property NSOperationQueue* operationQueue; + +@property (nullable) CKKSResultOperation* initialTimeoutListenerOp; + +@property bool timeoutCanOccur; +@property dispatch_queue_t queue; +@end + + +@implementation OctagonStateMultiStateArrivalWatcher +- (instancetype)initNamed:(NSString*)name + serialQueue:(dispatch_queue_t)queue + states:(NSSet*)states +{ + if((self = [super init])) { + _name = name; + _states = states; + + _result = [CKKSResultOperation named:[NSString stringWithFormat:@"watcher-%@", name] withBlock:^{}]; + _operationQueue = [[NSOperationQueue alloc] init]; + + _queue = queue; + _timeoutCanOccur = true; + + _completed = NO; + } + return self; +} + +- (void)onqueueHandleTransition:(CKKSResultOperation*)attempt +{ + dispatch_assert_queue(self.queue); + [self onqueueEnterState:attempt.nextState]; +} + +- (void)onqueueEnterState:(OctagonState*)state +{ + if(!self.completed) { + if([self.states containsObject:state]) { + [self onqueueStartFinishOperation]; + } + } +} + +- (void)_onqueuePerformTimeoutWithUnderlyingError +{ + dispatch_assert_queue(self.queue); + + if(self.timeoutCanOccur) { + self.timeoutCanOccur = false; + + NSString* description = [NSString stringWithFormat:@"Operation(%@) timed out waiting to start for any state in [%@]", + self.name, + self.states]; + + self.result.error = [NSError errorWithDomain:CKKSResultErrorDomain + code:CKKSResultTimedOut + description:description]; + [self onqueueStartFinishOperation]; + } +} + +- (instancetype)timeout:(dispatch_time_t)timeout +{ + WEAKIFY(self); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeout), self.queue, ^{ + STRONGIFY(self); + [self _onqueuePerformTimeoutWithUnderlyingError]; + }); + + return self; +} + +- (void)onqueueStartFinishOperation { + dispatch_assert_queue(self.queue); + + self.timeoutCanOccur = false; + [self.operationQueue addOperation:self.result]; + self.completed = TRUE; +} +@end + + #endif diff --git a/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h b/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h index 4278b499..015ea20b 100644 --- a/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h +++ b/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h @@ -15,6 +15,12 @@ NS_ASSUME_NONNULL_BEGIN + (OTAccountMetadataClassC* _Nullable)loadFromKeychainForContainer:(NSString*)containerName contextID:(NSString*)contextID error:(NSError**)error; @end +@class TPSyncingPolicy; +@interface OTAccountMetadataClassC (NSSecureCodingSupport) +- (void)setTPSyncingPolicy:(TPSyncingPolicy* _Nullable)policy; +- (TPSyncingPolicy* _Nullable)getTPSyncingPolicy; +@end + NS_ASSUME_NONNULL_END #endif // OCTAGON diff --git a/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.m b/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.m index 68f33b21..11731a47 100644 --- a/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.m +++ b/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.m @@ -12,6 +12,7 @@ #import "keychain/ot/OTDefines.h" #import "keychain/ot/OTConstants.h" +#import @implementation OTAccountMetadataClassC (KeychainSupport) @@ -158,6 +159,28 @@ return state; } +#pragma mark - Field Coding support + +- (void)setTPSyncingPolicy:(TPSyncingPolicy*)policy +{ + if(policy) { + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; + [policy encodeWithCoder:archiver]; + self.syncingPolicy = archiver.encodedData; + } else { + self.syncingPolicy = nil; + } +} + +- (TPSyncingPolicy* _Nullable)getTPSyncingPolicy +{ + NSKeyedUnarchiver *coder = [[NSKeyedUnarchiver alloc] initForReadingFromData:self.syncingPolicy error:nil]; + TPSyncingPolicy* policy = [[TPSyncingPolicy alloc] initWithCoder:coder]; + [coder finishDecoding]; + + return policy; +} + @end #endif // OCTAGON diff --git a/keychain/ot/categories/OctagonEscrowRecoverer.h b/keychain/ot/categories/OctagonEscrowRecoverer.h index 3943683f..e69060b8 100644 --- a/keychain/ot/categories/OctagonEscrowRecoverer.h +++ b/keychain/ot/categories/OctagonEscrowRecoverer.h @@ -4,13 +4,10 @@ #ifndef OctagonEscrowRecoverer_h #define OctagonEscrowRecoverer_h -#import - @protocol OctagonEscrowRecovererPrococol - (NSError*)recoverWithInfo:(NSDictionary*)info results:(NSDictionary**)results; -@end - -@interface SecureBackup (OctagonProtocolConformance) +- (NSError *)getAccountInfoWithInfo:(NSDictionary *)info results:(NSDictionary**)results; +- (NSError *)disableWithInfo:(NSDictionary *)info; @end #endif /* OctagonEscrowRecoverer_h */ diff --git a/keychain/ot/proto/OTAccountMetadataClassC.proto b/keychain/ot/proto/OTAccountMetadataClassC.proto index a3f0379f..8bf438e2 100644 --- a/keychain/ot/proto/OTAccountMetadataClassC.proto +++ b/keychain/ot/proto/OTAccountMetadataClassC.proto @@ -13,6 +13,9 @@ message AccountMetadataClassC { // If there is an SA account, we will bt in NO_ACCOUNT and have an altDSID // If there is an HSA2 account, we will be in ACCOUNT_AVAILABLE and have an altDSID + // Once you're in an HSA2 account, CDP might be enabled or disabled. If it's not enabled, + // then Octagon shouldn't be active. + enum AccountState { UNKNOWN = 0; NO_ACCOUNT = 1; @@ -32,6 +35,12 @@ message AccountMetadataClassC { ATTEMPTED = 2; } + enum CDPState { + UNKNOWN = 0; + DISABLED = 1; + ENABLED = 2; + } + optional string peerID = 1; optional AccountState icloudAccountState = 2; optional int64 epoch = 3; @@ -43,4 +52,17 @@ message AccountMetadataClassC { optional uint64 lastHealthCheckup = 6; optional AttemptedAJoinState attemptedJoin = 7; + + optional CDPState cdpState = 8; + + // Used during development + //reserved 9; + //reserved 10; + + // This holds the current syncing policy for the local peer, including the view list. + optional bytes syncingPolicy = 11; + + // This might contain a voucher for use in joining Octagon. + optional bytes voucher = 12; + optional bytes voucherSignature = 13; } diff --git a/keychain/ot/proto/OTCDPRecoveryInformation.proto b/keychain/ot/proto/OTCDPRecoveryInformation.proto new file mode 100644 index 00000000..04f28dbc --- /dev/null +++ b/keychain/ot/proto/OTCDPRecoveryInformation.proto @@ -0,0 +1,37 @@ +syntax = "proto2"; + +option objc_class_naming = "extended"; + +package OT; +import "OTEscrowRecord.proto"; + +message CDPRecoveryInformation { + optional string recovery_secret = 1; + optional bool use_cached_secret = 2; + optional string recovery_key = 3; + optional bool use_previously_cached_recovery_key = 4; + optional bool silent_recovery_attempt = 5; + optional bool contains_icdp_data = 6; + optional bool uses_multiple_icsc = 7; +} + +message EscrowAuthenticationInformation { + optional string authentication_password = 1; + optional string authentication_dsid = 2; + optional string authentication_appleid = 3; + optional string fmip_uuid = 4; + optional bool fmip_recovery = 5; + optional bool idms_recovery = 6; + optional string authentication_auth_token = 7; + optional string authentication_escrowproxy_url = 8; + optional string authentication_icloud_environment = 9; +} + +message ICDPRecordContext { + optional CDPRecoveryInformation cdpInfo = 1; + optional EscrowAuthenticationInformation authInfo = 2; +} +message ICDPRecordSilentContext { + optional CDPRecoveryInformation cdpInfo = 1; + optional EscrowAuthenticationInformation authInfo = 2; +} diff --git a/keychain/ot/proto/OTEscrowRecord.proto b/keychain/ot/proto/OTEscrowRecord.proto new file mode 100644 index 00000000..1aacb546 --- /dev/null +++ b/keychain/ot/proto/OTEscrowRecord.proto @@ -0,0 +1,77 @@ +syntax = "proto2"; + +option objc_class_naming = "extended"; + +package OT; + +message EscrowRecord { + optional uint64 creation_date = 1; + optional uint64 remaining_attempts = 2; + message Metadata { + optional bytes backup_keybag_digest = 1; + message ClientMetadata { + optional uint64 secure_backup_metadata_timestamp = 1; + optional uint64 secure_backup_numeric_passphrase_length = 2; + optional uint64 secure_backup_uses_complex_passphrase = 3; + optional uint64 secure_backup_uses_numeric_passphrase = 4; + optional string device_color = 5; + optional string device_enclosure_color = 6; + optional string device_mid = 7; + optional string device_model = 8; + optional string device_model_class = 9; + optional string device_model_version = 10; + optional string device_name = 11; + optional uint64 device_platform = 12; + } + optional ClientMetadata client_metadata = 2; + optional uint64 secure_backup_uses_multiple_icscs = 3; + optional string bottle_id = 4; + optional uint64 secure_backup_timestamp = 5; + optional bytes escrowed_spki = 6; + optional bytes peer_info = 7; + optional string bottle_validity = 8; + optional string serial = 9; + } + optional Metadata escrow_information_metadata = 3; + optional string label = 4; + // optional reserved string reserved5 = 5; + // optional reserved string reserved6 = 6; + // optional reserved string reserved7 = 7; + // optional reserved string reserved8 = 8; + + optional uint64 silent_attempt_allowed = 9; + + enum RecordStatus { + RECORD_STATUS_VALID = 0; + RECORD_STATUS_INVALID = 1; + } + + optional RecordStatus record_status = 10; + optional string record_id = 11; + + enum RecoveryStatus { + RECOVERY_STATUS_VALID = 0; + RECOVERY_STATUS_SOFT_LIMIT_REACHED = 1; + RECOVERY_STATUS_HARD_LIMIT_REACHED = 2; + } + optional RecoveryStatus recovery_status = 12; + optional uint64 cool_off_end = 13; + optional string serial_number = 14; + + enum RecordViability { + RECORD_VIABILITY_FULLY_VIABLE = 0; + RECORD_VIABILITY_PARTIALLY_VIABLE = 1; + RECORD_VIABILITY_LEGACY = 2; + } + optional RecordViability record_viability = 15; + + enum SOSViability { + SOS_VIABLE_UNKNOWN = 0; + SOS_VIABLE = 1; + SOS_NOT_VIABLE = 2; + } + optional SOSViability viability_status = 16; + + optional string federation_id = 17; + optional string expected_federation_id = 18; +} diff --git a/keychain/ot/proto/OTPairingMessage.proto b/keychain/ot/proto/OTPairingMessage.proto index c6b68a56..d6e3fe63 100644 --- a/keychain/ot/proto/OTPairingMessage.proto +++ b/keychain/ot/proto/OTPairingMessage.proto @@ -28,14 +28,21 @@ option objc_class_visibility = "hidden"; package OT; -message SOSMessage { - optional bytes credential = 1; - optional bytes peerInfo = 2; - optional bytes circleBlob = 3; - optional bytes initialSyncItems = 4; +enum SupportType { + unknown = 0; + supported = 1; + not_supported = 2; } -message SponsorToApplicantRound1M2{ +message supportSOSMessage { + optional SupportType supported = 1; +} + +message supportOctagonMessage { + optional SupportType supported = 1; +} + +message SponsorToApplicantRound1M2 { optional uint64 epoch = 1; } @@ -50,12 +57,16 @@ message ApplicantToSponsorRound2M1 { message SponsorToApplicantRound2M2{ optional bytes voucher = 1; optional bytes voucherSignature = 2; - repeated bytes preapprovedKeys = 3; + // Claimed for a field, but never used + //reserved 3; } message PairingMessage { - optional SponsorToApplicantRound1M2 epoch= 1; + optional SponsorToApplicantRound1M2 epoch = 1; optional ApplicantToSponsorRound2M1 prepare = 2; optional SponsorToApplicantRound2M2 voucher = 3; - optional SOSMessage sosPairingMessage = 4; + // reserved is not a keyword (it should be) + // reserved 4; + optional supportOctagonMessage supportsOctagon = 5; + optional supportSOSMessage supportsSOS = 6; } diff --git a/keychain/ot/proto/generated_source/OTAccountMetadataClassC.h b/keychain/ot/proto/generated_source/OTAccountMetadataClassC.h index aeef0ac0..1f645a69 100644 --- a/keychain/ot/proto/generated_source/OTAccountMetadataClassC.h +++ b/keychain/ot/proto/generated_source/OTAccountMetadataClassC.h @@ -10,6 +10,8 @@ * If there is no account, we will be in NO_ACCOUNT and have no altDSID * If there is an SA account, we will bt in NO_ACCOUNT and have an altDSID * If there is an HSA2 account, we will be in ACCOUNT_AVAILABLE and have an altDSID + * Once you're in an HSA2 account, CDP might be enabled or disabled. If it's not enabled, + * then Octagon shouldn't be active. */ typedef NS_ENUM(int32_t, OTAccountMetadataClassC_AccountState) { OTAccountMetadataClassC_AccountState_UNKNOWN = 0, @@ -92,6 +94,32 @@ NS_INLINE OTAccountMetadataClassC_AttemptedAJoinState StringAsOTAccountMetadataC return OTAccountMetadataClassC_AttemptedAJoinState_UNKNOWN; } #endif /* __OBJC__ */ +typedef NS_ENUM(int32_t, OTAccountMetadataClassC_CDPState) { + OTAccountMetadataClassC_CDPState_UNKNOWN = 0, + OTAccountMetadataClassC_CDPState_DISABLED = 1, + OTAccountMetadataClassC_CDPState_ENABLED = 2, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTAccountMetadataClassC_CDPStateAsString(OTAccountMetadataClassC_CDPState value) +{ + switch (value) + { + case OTAccountMetadataClassC_CDPState_UNKNOWN: return @"UNKNOWN"; + case OTAccountMetadataClassC_CDPState_DISABLED: return @"DISABLED"; + case OTAccountMetadataClassC_CDPState_ENABLED: return @"ENABLED"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTAccountMetadataClassC_CDPState StringAsOTAccountMetadataClassC_CDPState(NSString *value) +{ + if ([value isEqualToString:@"UNKNOWN"]) return OTAccountMetadataClassC_CDPState_UNKNOWN; + if ([value isEqualToString:@"DISABLED"]) return OTAccountMetadataClassC_CDPState_DISABLED; + if ([value isEqualToString:@"ENABLED"]) return OTAccountMetadataClassC_CDPState_ENABLED; + return OTAccountMetadataClassC_CDPState_UNKNOWN; +} +#endif /* __OBJC__ */ #ifdef __cplusplus #define OTACCOUNTMETADATACLASSC_FUNCTION extern "C" __attribute__((visibility("hidden"))) @@ -106,13 +134,18 @@ __attribute__((visibility("hidden"))) uint64_t _lastHealthCheckup; NSString *_altDSID; OTAccountMetadataClassC_AttemptedAJoinState _attemptedJoin; + OTAccountMetadataClassC_CDPState _cdpState; OTAccountMetadataClassC_AccountState _icloudAccountState; NSString *_peerID; + NSData *_syncingPolicy; OTAccountMetadataClassC_TrustState _trustState; + NSData *_voucher; + NSData *_voucherSignature; struct { int epoch:1; int lastHealthCheckup:1; int attemptedJoin:1; + int cdpState:1; int icloudAccountState:1; int trustState:1; } _has; @@ -147,6 +180,27 @@ __attribute__((visibility("hidden"))) - (NSString *)attemptedJoinAsString:(OTAccountMetadataClassC_AttemptedAJoinState)value; - (OTAccountMetadataClassC_AttemptedAJoinState)StringAsAttemptedJoin:(NSString *)str; +@property (nonatomic) BOOL hasCdpState; +@property (nonatomic) OTAccountMetadataClassC_CDPState cdpState; +- (NSString *)cdpStateAsString:(OTAccountMetadataClassC_CDPState)value; +- (OTAccountMetadataClassC_CDPState)StringAsCdpState:(NSString *)str; + +@property (nonatomic, readonly) BOOL hasSyncingPolicy; +/** + * Used during development + * reserved 9; + * reserved 10; + * This holds the current syncing policy for the local peer, including the view list. + */ +@property (nonatomic, retain) NSData *syncingPolicy; + +@property (nonatomic, readonly) BOOL hasVoucher; +/** This might contain a voucher for use in joining Octagon. */ +@property (nonatomic, retain) NSData *voucher; + +@property (nonatomic, readonly) BOOL hasVoucherSignature; +@property (nonatomic, retain) NSData *voucherSignature; + // Performs a shallow copy into other - (void)copyTo:(OTAccountMetadataClassC *)other; diff --git a/keychain/ot/proto/generated_source/OTAccountMetadataClassC.m b/keychain/ot/proto/generated_source/OTAccountMetadataClassC.m index c7e41deb..5dbcb98f 100644 --- a/keychain/ot/proto/generated_source/OTAccountMetadataClassC.m +++ b/keychain/ot/proto/generated_source/OTAccountMetadataClassC.m @@ -34,7 +34,7 @@ } - (BOOL)hasIcloudAccountState { - return _has.icloudAccountState; + return _has.icloudAccountState != 0; } - (NSString *)icloudAccountStateAsString:(OTAccountMetadataClassC_AccountState)value { @@ -56,7 +56,7 @@ } - (BOOL)hasEpoch { - return _has.epoch; + return _has.epoch != 0; } - (BOOL)hasAltDSID { @@ -79,7 +79,7 @@ } - (BOOL)hasTrustState { - return _has.trustState; + return _has.trustState != 0; } - (NSString *)trustStateAsString:(OTAccountMetadataClassC_TrustState)value { @@ -101,7 +101,7 @@ } - (BOOL)hasLastHealthCheckup { - return _has.lastHealthCheckup; + return _has.lastHealthCheckup != 0; } @synthesize attemptedJoin = _attemptedJoin; - (OTAccountMetadataClassC_AttemptedAJoinState)attemptedJoin @@ -119,7 +119,7 @@ } - (BOOL)hasAttemptedJoin { - return _has.attemptedJoin; + return _has.attemptedJoin != 0; } - (NSString *)attemptedJoinAsString:(OTAccountMetadataClassC_AttemptedAJoinState)value { @@ -129,6 +129,47 @@ { return StringAsOTAccountMetadataClassC_AttemptedAJoinState(str); } +@synthesize cdpState = _cdpState; +- (OTAccountMetadataClassC_CDPState)cdpState +{ + return _has.cdpState ? _cdpState : OTAccountMetadataClassC_CDPState_UNKNOWN; +} +- (void)setCdpState:(OTAccountMetadataClassC_CDPState)v +{ + _has.cdpState = YES; + _cdpState = v; +} +- (void)setHasCdpState:(BOOL)f +{ + _has.cdpState = f; +} +- (BOOL)hasCdpState +{ + return _has.cdpState != 0; +} +- (NSString *)cdpStateAsString:(OTAccountMetadataClassC_CDPState)value +{ + return OTAccountMetadataClassC_CDPStateAsString(value); +} +- (OTAccountMetadataClassC_CDPState)StringAsCdpState:(NSString *)str +{ + return StringAsOTAccountMetadataClassC_CDPState(str); +} +- (BOOL)hasSyncingPolicy +{ + return _syncingPolicy != nil; +} +@synthesize syncingPolicy = _syncingPolicy; +- (BOOL)hasVoucher +{ + return _voucher != nil; +} +@synthesize voucher = _voucher; +- (BOOL)hasVoucherSignature +{ + return _voucherSignature != nil; +} +@synthesize voucherSignature = _voucherSignature; - (NSString *)description { @@ -166,6 +207,22 @@ { [dict setObject:OTAccountMetadataClassC_AttemptedAJoinStateAsString(self->_attemptedJoin) forKey:@"attemptedJoin"]; } + if (self->_has.cdpState) + { + [dict setObject:OTAccountMetadataClassC_CDPStateAsString(self->_cdpState) forKey:@"cdpState"]; + } + if (self->_syncingPolicy) + { + [dict setObject:self->_syncingPolicy forKey:@"syncingPolicy"]; + } + if (self->_voucher) + { + [dict setObject:self->_voucher forKey:@"voucher"]; + } + if (self->_voucherSignature) + { + [dict setObject:self->_voucherSignature forKey:@"voucherSignature"]; + } return dict; } @@ -227,6 +284,30 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC self->_attemptedJoin = PBReaderReadInt32(reader); } break; + case 8 /* cdpState */: + { + self->_has.cdpState = YES; + self->_cdpState = PBReaderReadInt32(reader); + } + break; + case 11 /* syncingPolicy */: + { + NSData *new_syncingPolicy = PBReaderReadData(reader); + self->_syncingPolicy = new_syncingPolicy; + } + break; + case 12 /* voucher */: + { + NSData *new_voucher = PBReaderReadData(reader); + self->_voucher = new_voucher; + } + break; + case 13 /* voucherSignature */: + { + NSData *new_voucherSignature = PBReaderReadData(reader); + self->_voucherSignature = new_voucherSignature; + } + break; default: if (!PBReaderSkipValueWithTag(reader, tag, aType)) return NO; @@ -291,6 +372,34 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC PBDataWriterWriteInt32Field(writer, self->_attemptedJoin, 7); } } + /* cdpState */ + { + if (self->_has.cdpState) + { + PBDataWriterWriteInt32Field(writer, self->_cdpState, 8); + } + } + /* syncingPolicy */ + { + if (self->_syncingPolicy) + { + PBDataWriterWriteDataField(writer, self->_syncingPolicy, 11); + } + } + /* voucher */ + { + if (self->_voucher) + { + PBDataWriterWriteDataField(writer, self->_voucher, 12); + } + } + /* voucherSignature */ + { + if (self->_voucherSignature) + { + PBDataWriterWriteDataField(writer, self->_voucherSignature, 13); + } + } } - (void)copyTo:(OTAccountMetadataClassC *)other @@ -328,6 +437,23 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC other->_attemptedJoin = _attemptedJoin; other->_has.attemptedJoin = YES; } + if (self->_has.cdpState) + { + other->_cdpState = _cdpState; + other->_has.cdpState = YES; + } + if (_syncingPolicy) + { + other.syncingPolicy = _syncingPolicy; + } + if (_voucher) + { + other.voucher = _voucher; + } + if (_voucherSignature) + { + other.voucherSignature = _voucherSignature; + } } - (id)copyWithZone:(NSZone *)zone @@ -360,6 +486,14 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC copy->_attemptedJoin = _attemptedJoin; copy->_has.attemptedJoin = YES; } + if (self->_has.cdpState) + { + copy->_cdpState = _cdpState; + copy->_has.cdpState = YES; + } + copy->_syncingPolicy = [_syncingPolicy copyWithZone:zone]; + copy->_voucher = [_voucher copyWithZone:zone]; + copy->_voucherSignature = [_voucherSignature copyWithZone:zone]; return copy; } @@ -381,6 +515,14 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC ((self->_has.lastHealthCheckup && other->_has.lastHealthCheckup && self->_lastHealthCheckup == other->_lastHealthCheckup) || (!self->_has.lastHealthCheckup && !other->_has.lastHealthCheckup)) && ((self->_has.attemptedJoin && other->_has.attemptedJoin && self->_attemptedJoin == other->_attemptedJoin) || (!self->_has.attemptedJoin && !other->_has.attemptedJoin)) + && + ((self->_has.cdpState && other->_has.cdpState && self->_cdpState == other->_cdpState) || (!self->_has.cdpState && !other->_has.cdpState)) + && + ((!self->_syncingPolicy && !other->_syncingPolicy) || [self->_syncingPolicy isEqual:other->_syncingPolicy]) + && + ((!self->_voucher && !other->_voucher) || [self->_voucher isEqual:other->_voucher]) + && + ((!self->_voucherSignature && !other->_voucherSignature) || [self->_voucherSignature isEqual:other->_voucherSignature]) ; } @@ -401,6 +543,14 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC (self->_has.lastHealthCheckup ? PBHashInt((NSUInteger)self->_lastHealthCheckup) : 0) ^ (self->_has.attemptedJoin ? PBHashInt((NSUInteger)self->_attemptedJoin) : 0) + ^ + (self->_has.cdpState ? PBHashInt((NSUInteger)self->_cdpState) : 0) + ^ + [self->_syncingPolicy hash] + ^ + [self->_voucher hash] + ^ + [self->_voucherSignature hash] ; } @@ -439,6 +589,23 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC self->_attemptedJoin = other->_attemptedJoin; self->_has.attemptedJoin = YES; } + if (other->_has.cdpState) + { + self->_cdpState = other->_cdpState; + self->_has.cdpState = YES; + } + if (other->_syncingPolicy) + { + [self setSyncingPolicy:other->_syncingPolicy]; + } + if (other->_voucher) + { + [self setVoucher:other->_voucher]; + } + if (other->_voucherSignature) + { + [self setVoucherSignature:other->_voucherSignature]; + } } @end diff --git a/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.h b/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.h new file mode 100644 index 00000000..2e070eac --- /dev/null +++ b/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.h @@ -0,0 +1,66 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import +#import + +#ifdef __cplusplus +#define OTCDPRECOVERYINFORMATION_FUNCTION extern "C" +#else +#define OTCDPRECOVERYINFORMATION_FUNCTION extern +#endif + +@interface OTCDPRecoveryInformation : PBCodable +{ + NSString *_recoveryKey; + NSString *_recoverySecret; + BOOL _containsIcdpData; + BOOL _silentRecoveryAttempt; + BOOL _useCachedSecret; + BOOL _usePreviouslyCachedRecoveryKey; + BOOL _usesMultipleIcsc; + struct { + int containsIcdpData:1; + int silentRecoveryAttempt:1; + int useCachedSecret:1; + int usePreviouslyCachedRecoveryKey:1; + int usesMultipleIcsc:1; + } _has; +} + + +@property (nonatomic, readonly) BOOL hasRecoverySecret; +@property (nonatomic, retain) NSString *recoverySecret; + +@property (nonatomic) BOOL hasUseCachedSecret; +@property (nonatomic) BOOL useCachedSecret; + +@property (nonatomic, readonly) BOOL hasRecoveryKey; +@property (nonatomic, retain) NSString *recoveryKey; + +@property (nonatomic) BOOL hasUsePreviouslyCachedRecoveryKey; +@property (nonatomic) BOOL usePreviouslyCachedRecoveryKey; + +@property (nonatomic) BOOL hasSilentRecoveryAttempt; +@property (nonatomic) BOOL silentRecoveryAttempt; + +@property (nonatomic) BOOL hasContainsIcdpData; +@property (nonatomic) BOOL containsIcdpData; + +@property (nonatomic) BOOL hasUsesMultipleIcsc; +@property (nonatomic) BOOL usesMultipleIcsc; + +// Performs a shallow copy into other +- (void)copyTo:(OTCDPRecoveryInformation *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTCDPRecoveryInformation *)other; + +OTCDPRECOVERYINFORMATION_FUNCTION BOOL OTCDPRecoveryInformationReadFrom(__unsafe_unretained OTCDPRecoveryInformation *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.m b/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.m new file mode 100644 index 00000000..242d1634 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.m @@ -0,0 +1,409 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import "OTCDPRecoveryInformation.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTCDPRecoveryInformation + +- (BOOL)hasRecoverySecret +{ + return _recoverySecret != nil; +} +@synthesize recoverySecret = _recoverySecret; +@synthesize useCachedSecret = _useCachedSecret; +- (void)setUseCachedSecret:(BOOL)v +{ + _has.useCachedSecret = YES; + _useCachedSecret = v; +} +- (void)setHasUseCachedSecret:(BOOL)f +{ + _has.useCachedSecret = f; +} +- (BOOL)hasUseCachedSecret +{ + return _has.useCachedSecret != 0; +} +- (BOOL)hasRecoveryKey +{ + return _recoveryKey != nil; +} +@synthesize recoveryKey = _recoveryKey; +@synthesize usePreviouslyCachedRecoveryKey = _usePreviouslyCachedRecoveryKey; +- (void)setUsePreviouslyCachedRecoveryKey:(BOOL)v +{ + _has.usePreviouslyCachedRecoveryKey = YES; + _usePreviouslyCachedRecoveryKey = v; +} +- (void)setHasUsePreviouslyCachedRecoveryKey:(BOOL)f +{ + _has.usePreviouslyCachedRecoveryKey = f; +} +- (BOOL)hasUsePreviouslyCachedRecoveryKey +{ + return _has.usePreviouslyCachedRecoveryKey != 0; +} +@synthesize silentRecoveryAttempt = _silentRecoveryAttempt; +- (void)setSilentRecoveryAttempt:(BOOL)v +{ + _has.silentRecoveryAttempt = YES; + _silentRecoveryAttempt = v; +} +- (void)setHasSilentRecoveryAttempt:(BOOL)f +{ + _has.silentRecoveryAttempt = f; +} +- (BOOL)hasSilentRecoveryAttempt +{ + return _has.silentRecoveryAttempt != 0; +} +@synthesize containsIcdpData = _containsIcdpData; +- (void)setContainsIcdpData:(BOOL)v +{ + _has.containsIcdpData = YES; + _containsIcdpData = v; +} +- (void)setHasContainsIcdpData:(BOOL)f +{ + _has.containsIcdpData = f; +} +- (BOOL)hasContainsIcdpData +{ + return _has.containsIcdpData != 0; +} +@synthesize usesMultipleIcsc = _usesMultipleIcsc; +- (void)setUsesMultipleIcsc:(BOOL)v +{ + _has.usesMultipleIcsc = YES; + _usesMultipleIcsc = v; +} +- (void)setHasUsesMultipleIcsc:(BOOL)f +{ + _has.usesMultipleIcsc = f; +} +- (BOOL)hasUsesMultipleIcsc +{ + return _has.usesMultipleIcsc != 0; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_recoverySecret) + { + [dict setObject:self->_recoverySecret forKey:@"recovery_secret"]; + } + if (self->_has.useCachedSecret) + { + [dict setObject:[NSNumber numberWithBool:self->_useCachedSecret] forKey:@"use_cached_secret"]; + } + if (self->_recoveryKey) + { + [dict setObject:self->_recoveryKey forKey:@"recovery_key"]; + } + if (self->_has.usePreviouslyCachedRecoveryKey) + { + [dict setObject:[NSNumber numberWithBool:self->_usePreviouslyCachedRecoveryKey] forKey:@"use_previously_cached_recovery_key"]; + } + if (self->_has.silentRecoveryAttempt) + { + [dict setObject:[NSNumber numberWithBool:self->_silentRecoveryAttempt] forKey:@"silent_recovery_attempt"]; + } + if (self->_has.containsIcdpData) + { + [dict setObject:[NSNumber numberWithBool:self->_containsIcdpData] forKey:@"contains_icdp_data"]; + } + if (self->_has.usesMultipleIcsc) + { + [dict setObject:[NSNumber numberWithBool:self->_usesMultipleIcsc] forKey:@"uses_multiple_icsc"]; + } + return dict; +} + +BOOL OTCDPRecoveryInformationReadFrom(__unsafe_unretained OTCDPRecoveryInformation *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* recoverySecret */: + { + NSString *new_recoverySecret = PBReaderReadString(reader); + self->_recoverySecret = new_recoverySecret; + } + break; + case 2 /* useCachedSecret */: + { + self->_has.useCachedSecret = YES; + self->_useCachedSecret = PBReaderReadBOOL(reader); + } + break; + case 3 /* recoveryKey */: + { + NSString *new_recoveryKey = PBReaderReadString(reader); + self->_recoveryKey = new_recoveryKey; + } + break; + case 4 /* usePreviouslyCachedRecoveryKey */: + { + self->_has.usePreviouslyCachedRecoveryKey = YES; + self->_usePreviouslyCachedRecoveryKey = PBReaderReadBOOL(reader); + } + break; + case 5 /* silentRecoveryAttempt */: + { + self->_has.silentRecoveryAttempt = YES; + self->_silentRecoveryAttempt = PBReaderReadBOOL(reader); + } + break; + case 6 /* containsIcdpData */: + { + self->_has.containsIcdpData = YES; + self->_containsIcdpData = PBReaderReadBOOL(reader); + } + break; + case 7 /* usesMultipleIcsc */: + { + self->_has.usesMultipleIcsc = YES; + self->_usesMultipleIcsc = PBReaderReadBOOL(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTCDPRecoveryInformationReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* recoverySecret */ + { + if (self->_recoverySecret) + { + PBDataWriterWriteStringField(writer, self->_recoverySecret, 1); + } + } + /* useCachedSecret */ + { + if (self->_has.useCachedSecret) + { + PBDataWriterWriteBOOLField(writer, self->_useCachedSecret, 2); + } + } + /* recoveryKey */ + { + if (self->_recoveryKey) + { + PBDataWriterWriteStringField(writer, self->_recoveryKey, 3); + } + } + /* usePreviouslyCachedRecoveryKey */ + { + if (self->_has.usePreviouslyCachedRecoveryKey) + { + PBDataWriterWriteBOOLField(writer, self->_usePreviouslyCachedRecoveryKey, 4); + } + } + /* silentRecoveryAttempt */ + { + if (self->_has.silentRecoveryAttempt) + { + PBDataWriterWriteBOOLField(writer, self->_silentRecoveryAttempt, 5); + } + } + /* containsIcdpData */ + { + if (self->_has.containsIcdpData) + { + PBDataWriterWriteBOOLField(writer, self->_containsIcdpData, 6); + } + } + /* usesMultipleIcsc */ + { + if (self->_has.usesMultipleIcsc) + { + PBDataWriterWriteBOOLField(writer, self->_usesMultipleIcsc, 7); + } + } +} + +- (void)copyTo:(OTCDPRecoveryInformation *)other +{ + if (_recoverySecret) + { + other.recoverySecret = _recoverySecret; + } + if (self->_has.useCachedSecret) + { + other->_useCachedSecret = _useCachedSecret; + other->_has.useCachedSecret = YES; + } + if (_recoveryKey) + { + other.recoveryKey = _recoveryKey; + } + if (self->_has.usePreviouslyCachedRecoveryKey) + { + other->_usePreviouslyCachedRecoveryKey = _usePreviouslyCachedRecoveryKey; + other->_has.usePreviouslyCachedRecoveryKey = YES; + } + if (self->_has.silentRecoveryAttempt) + { + other->_silentRecoveryAttempt = _silentRecoveryAttempt; + other->_has.silentRecoveryAttempt = YES; + } + if (self->_has.containsIcdpData) + { + other->_containsIcdpData = _containsIcdpData; + other->_has.containsIcdpData = YES; + } + if (self->_has.usesMultipleIcsc) + { + other->_usesMultipleIcsc = _usesMultipleIcsc; + other->_has.usesMultipleIcsc = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTCDPRecoveryInformation *copy = [[[self class] allocWithZone:zone] init]; + copy->_recoverySecret = [_recoverySecret copyWithZone:zone]; + if (self->_has.useCachedSecret) + { + copy->_useCachedSecret = _useCachedSecret; + copy->_has.useCachedSecret = YES; + } + copy->_recoveryKey = [_recoveryKey copyWithZone:zone]; + if (self->_has.usePreviouslyCachedRecoveryKey) + { + copy->_usePreviouslyCachedRecoveryKey = _usePreviouslyCachedRecoveryKey; + copy->_has.usePreviouslyCachedRecoveryKey = YES; + } + if (self->_has.silentRecoveryAttempt) + { + copy->_silentRecoveryAttempt = _silentRecoveryAttempt; + copy->_has.silentRecoveryAttempt = YES; + } + if (self->_has.containsIcdpData) + { + copy->_containsIcdpData = _containsIcdpData; + copy->_has.containsIcdpData = YES; + } + if (self->_has.usesMultipleIcsc) + { + copy->_usesMultipleIcsc = _usesMultipleIcsc; + copy->_has.usesMultipleIcsc = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTCDPRecoveryInformation *other = (OTCDPRecoveryInformation *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_recoverySecret && !other->_recoverySecret) || [self->_recoverySecret isEqual:other->_recoverySecret]) + && + ((self->_has.useCachedSecret && other->_has.useCachedSecret && ((self->_useCachedSecret && other->_useCachedSecret) || (!self->_useCachedSecret && !other->_useCachedSecret))) || (!self->_has.useCachedSecret && !other->_has.useCachedSecret)) + && + ((!self->_recoveryKey && !other->_recoveryKey) || [self->_recoveryKey isEqual:other->_recoveryKey]) + && + ((self->_has.usePreviouslyCachedRecoveryKey && other->_has.usePreviouslyCachedRecoveryKey && ((self->_usePreviouslyCachedRecoveryKey && other->_usePreviouslyCachedRecoveryKey) || (!self->_usePreviouslyCachedRecoveryKey && !other->_usePreviouslyCachedRecoveryKey))) || (!self->_has.usePreviouslyCachedRecoveryKey && !other->_has.usePreviouslyCachedRecoveryKey)) + && + ((self->_has.silentRecoveryAttempt && other->_has.silentRecoveryAttempt && ((self->_silentRecoveryAttempt && other->_silentRecoveryAttempt) || (!self->_silentRecoveryAttempt && !other->_silentRecoveryAttempt))) || (!self->_has.silentRecoveryAttempt && !other->_has.silentRecoveryAttempt)) + && + ((self->_has.containsIcdpData && other->_has.containsIcdpData && ((self->_containsIcdpData && other->_containsIcdpData) || (!self->_containsIcdpData && !other->_containsIcdpData))) || (!self->_has.containsIcdpData && !other->_has.containsIcdpData)) + && + ((self->_has.usesMultipleIcsc && other->_has.usesMultipleIcsc && ((self->_usesMultipleIcsc && other->_usesMultipleIcsc) || (!self->_usesMultipleIcsc && !other->_usesMultipleIcsc))) || (!self->_has.usesMultipleIcsc && !other->_has.usesMultipleIcsc)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_recoverySecret hash] + ^ + (self->_has.useCachedSecret ? PBHashInt((NSUInteger)self->_useCachedSecret) : 0) + ^ + [self->_recoveryKey hash] + ^ + (self->_has.usePreviouslyCachedRecoveryKey ? PBHashInt((NSUInteger)self->_usePreviouslyCachedRecoveryKey) : 0) + ^ + (self->_has.silentRecoveryAttempt ? PBHashInt((NSUInteger)self->_silentRecoveryAttempt) : 0) + ^ + (self->_has.containsIcdpData ? PBHashInt((NSUInteger)self->_containsIcdpData) : 0) + ^ + (self->_has.usesMultipleIcsc ? PBHashInt((NSUInteger)self->_usesMultipleIcsc) : 0) + ; +} + +- (void)mergeFrom:(OTCDPRecoveryInformation *)other +{ + if (other->_recoverySecret) + { + [self setRecoverySecret:other->_recoverySecret]; + } + if (other->_has.useCachedSecret) + { + self->_useCachedSecret = other->_useCachedSecret; + self->_has.useCachedSecret = YES; + } + if (other->_recoveryKey) + { + [self setRecoveryKey:other->_recoveryKey]; + } + if (other->_has.usePreviouslyCachedRecoveryKey) + { + self->_usePreviouslyCachedRecoveryKey = other->_usePreviouslyCachedRecoveryKey; + self->_has.usePreviouslyCachedRecoveryKey = YES; + } + if (other->_has.silentRecoveryAttempt) + { + self->_silentRecoveryAttempt = other->_silentRecoveryAttempt; + self->_has.silentRecoveryAttempt = YES; + } + if (other->_has.containsIcdpData) + { + self->_containsIcdpData = other->_containsIcdpData; + self->_has.containsIcdpData = YES; + } + if (other->_has.usesMultipleIcsc) + { + self->_usesMultipleIcsc = other->_usesMultipleIcsc; + self->_has.usesMultipleIcsc = YES; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.h b/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.h new file mode 100644 index 00000000..1956fd4d --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.h @@ -0,0 +1,71 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import +#import + +#ifdef __cplusplus +#define OTESCROWAUTHENTICATIONINFORMATION_FUNCTION extern "C" +#else +#define OTESCROWAUTHENTICATIONINFORMATION_FUNCTION extern +#endif + +@interface OTEscrowAuthenticationInformation : PBCodable +{ + NSString *_authenticationAppleid; + NSString *_authenticationAuthToken; + NSString *_authenticationDsid; + NSString *_authenticationEscrowproxyUrl; + NSString *_authenticationIcloudEnvironment; + NSString *_authenticationPassword; + NSString *_fmipUuid; + BOOL _fmipRecovery; + BOOL _idmsRecovery; + struct { + int fmipRecovery:1; + int idmsRecovery:1; + } _has; +} + + +@property (nonatomic, readonly) BOOL hasAuthenticationPassword; +@property (nonatomic, retain) NSString *authenticationPassword; + +@property (nonatomic, readonly) BOOL hasAuthenticationDsid; +@property (nonatomic, retain) NSString *authenticationDsid; + +@property (nonatomic, readonly) BOOL hasAuthenticationAppleid; +@property (nonatomic, retain) NSString *authenticationAppleid; + +@property (nonatomic, readonly) BOOL hasFmipUuid; +@property (nonatomic, retain) NSString *fmipUuid; + +@property (nonatomic) BOOL hasFmipRecovery; +@property (nonatomic) BOOL fmipRecovery; + +@property (nonatomic) BOOL hasIdmsRecovery; +@property (nonatomic) BOOL idmsRecovery; + +@property (nonatomic, readonly) BOOL hasAuthenticationAuthToken; +@property (nonatomic, retain) NSString *authenticationAuthToken; + +@property (nonatomic, readonly) BOOL hasAuthenticationEscrowproxyUrl; +@property (nonatomic, retain) NSString *authenticationEscrowproxyUrl; + +@property (nonatomic, readonly) BOOL hasAuthenticationIcloudEnvironment; +@property (nonatomic, retain) NSString *authenticationIcloudEnvironment; + +// Performs a shallow copy into other +- (void)copyTo:(OTEscrowAuthenticationInformation *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTEscrowAuthenticationInformation *)other; + +OTESCROWAUTHENTICATIONINFORMATION_FUNCTION BOOL OTEscrowAuthenticationInformationReadFrom(__unsafe_unretained OTEscrowAuthenticationInformation *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.m b/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.m new file mode 100644 index 00000000..c0b0c86f --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.m @@ -0,0 +1,434 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import "OTEscrowAuthenticationInformation.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTEscrowAuthenticationInformation + +- (BOOL)hasAuthenticationPassword +{ + return _authenticationPassword != nil; +} +@synthesize authenticationPassword = _authenticationPassword; +- (BOOL)hasAuthenticationDsid +{ + return _authenticationDsid != nil; +} +@synthesize authenticationDsid = _authenticationDsid; +- (BOOL)hasAuthenticationAppleid +{ + return _authenticationAppleid != nil; +} +@synthesize authenticationAppleid = _authenticationAppleid; +- (BOOL)hasFmipUuid +{ + return _fmipUuid != nil; +} +@synthesize fmipUuid = _fmipUuid; +@synthesize fmipRecovery = _fmipRecovery; +- (void)setFmipRecovery:(BOOL)v +{ + _has.fmipRecovery = YES; + _fmipRecovery = v; +} +- (void)setHasFmipRecovery:(BOOL)f +{ + _has.fmipRecovery = f; +} +- (BOOL)hasFmipRecovery +{ + return _has.fmipRecovery != 0; +} +@synthesize idmsRecovery = _idmsRecovery; +- (void)setIdmsRecovery:(BOOL)v +{ + _has.idmsRecovery = YES; + _idmsRecovery = v; +} +- (void)setHasIdmsRecovery:(BOOL)f +{ + _has.idmsRecovery = f; +} +- (BOOL)hasIdmsRecovery +{ + return _has.idmsRecovery != 0; +} +- (BOOL)hasAuthenticationAuthToken +{ + return _authenticationAuthToken != nil; +} +@synthesize authenticationAuthToken = _authenticationAuthToken; +- (BOOL)hasAuthenticationEscrowproxyUrl +{ + return _authenticationEscrowproxyUrl != nil; +} +@synthesize authenticationEscrowproxyUrl = _authenticationEscrowproxyUrl; +- (BOOL)hasAuthenticationIcloudEnvironment +{ + return _authenticationIcloudEnvironment != nil; +} +@synthesize authenticationIcloudEnvironment = _authenticationIcloudEnvironment; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_authenticationPassword) + { + [dict setObject:self->_authenticationPassword forKey:@"authentication_password"]; + } + if (self->_authenticationDsid) + { + [dict setObject:self->_authenticationDsid forKey:@"authentication_dsid"]; + } + if (self->_authenticationAppleid) + { + [dict setObject:self->_authenticationAppleid forKey:@"authentication_appleid"]; + } + if (self->_fmipUuid) + { + [dict setObject:self->_fmipUuid forKey:@"fmip_uuid"]; + } + if (self->_has.fmipRecovery) + { + [dict setObject:[NSNumber numberWithBool:self->_fmipRecovery] forKey:@"fmip_recovery"]; + } + if (self->_has.idmsRecovery) + { + [dict setObject:[NSNumber numberWithBool:self->_idmsRecovery] forKey:@"idms_recovery"]; + } + if (self->_authenticationAuthToken) + { + [dict setObject:self->_authenticationAuthToken forKey:@"authentication_auth_token"]; + } + if (self->_authenticationEscrowproxyUrl) + { + [dict setObject:self->_authenticationEscrowproxyUrl forKey:@"authentication_escrowproxy_url"]; + } + if (self->_authenticationIcloudEnvironment) + { + [dict setObject:self->_authenticationIcloudEnvironment forKey:@"authentication_icloud_environment"]; + } + return dict; +} + +BOOL OTEscrowAuthenticationInformationReadFrom(__unsafe_unretained OTEscrowAuthenticationInformation *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* authenticationPassword */: + { + NSString *new_authenticationPassword = PBReaderReadString(reader); + self->_authenticationPassword = new_authenticationPassword; + } + break; + case 2 /* authenticationDsid */: + { + NSString *new_authenticationDsid = PBReaderReadString(reader); + self->_authenticationDsid = new_authenticationDsid; + } + break; + case 3 /* authenticationAppleid */: + { + NSString *new_authenticationAppleid = PBReaderReadString(reader); + self->_authenticationAppleid = new_authenticationAppleid; + } + break; + case 4 /* fmipUuid */: + { + NSString *new_fmipUuid = PBReaderReadString(reader); + self->_fmipUuid = new_fmipUuid; + } + break; + case 5 /* fmipRecovery */: + { + self->_has.fmipRecovery = YES; + self->_fmipRecovery = PBReaderReadBOOL(reader); + } + break; + case 6 /* idmsRecovery */: + { + self->_has.idmsRecovery = YES; + self->_idmsRecovery = PBReaderReadBOOL(reader); + } + break; + case 7 /* authenticationAuthToken */: + { + NSString *new_authenticationAuthToken = PBReaderReadString(reader); + self->_authenticationAuthToken = new_authenticationAuthToken; + } + break; + case 8 /* authenticationEscrowproxyUrl */: + { + NSString *new_authenticationEscrowproxyUrl = PBReaderReadString(reader); + self->_authenticationEscrowproxyUrl = new_authenticationEscrowproxyUrl; + } + break; + case 9 /* authenticationIcloudEnvironment */: + { + NSString *new_authenticationIcloudEnvironment = PBReaderReadString(reader); + self->_authenticationIcloudEnvironment = new_authenticationIcloudEnvironment; + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTEscrowAuthenticationInformationReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* authenticationPassword */ + { + if (self->_authenticationPassword) + { + PBDataWriterWriteStringField(writer, self->_authenticationPassword, 1); + } + } + /* authenticationDsid */ + { + if (self->_authenticationDsid) + { + PBDataWriterWriteStringField(writer, self->_authenticationDsid, 2); + } + } + /* authenticationAppleid */ + { + if (self->_authenticationAppleid) + { + PBDataWriterWriteStringField(writer, self->_authenticationAppleid, 3); + } + } + /* fmipUuid */ + { + if (self->_fmipUuid) + { + PBDataWriterWriteStringField(writer, self->_fmipUuid, 4); + } + } + /* fmipRecovery */ + { + if (self->_has.fmipRecovery) + { + PBDataWriterWriteBOOLField(writer, self->_fmipRecovery, 5); + } + } + /* idmsRecovery */ + { + if (self->_has.idmsRecovery) + { + PBDataWriterWriteBOOLField(writer, self->_idmsRecovery, 6); + } + } + /* authenticationAuthToken */ + { + if (self->_authenticationAuthToken) + { + PBDataWriterWriteStringField(writer, self->_authenticationAuthToken, 7); + } + } + /* authenticationEscrowproxyUrl */ + { + if (self->_authenticationEscrowproxyUrl) + { + PBDataWriterWriteStringField(writer, self->_authenticationEscrowproxyUrl, 8); + } + } + /* authenticationIcloudEnvironment */ + { + if (self->_authenticationIcloudEnvironment) + { + PBDataWriterWriteStringField(writer, self->_authenticationIcloudEnvironment, 9); + } + } +} + +- (void)copyTo:(OTEscrowAuthenticationInformation *)other +{ + if (_authenticationPassword) + { + other.authenticationPassword = _authenticationPassword; + } + if (_authenticationDsid) + { + other.authenticationDsid = _authenticationDsid; + } + if (_authenticationAppleid) + { + other.authenticationAppleid = _authenticationAppleid; + } + if (_fmipUuid) + { + other.fmipUuid = _fmipUuid; + } + if (self->_has.fmipRecovery) + { + other->_fmipRecovery = _fmipRecovery; + other->_has.fmipRecovery = YES; + } + if (self->_has.idmsRecovery) + { + other->_idmsRecovery = _idmsRecovery; + other->_has.idmsRecovery = YES; + } + if (_authenticationAuthToken) + { + other.authenticationAuthToken = _authenticationAuthToken; + } + if (_authenticationEscrowproxyUrl) + { + other.authenticationEscrowproxyUrl = _authenticationEscrowproxyUrl; + } + if (_authenticationIcloudEnvironment) + { + other.authenticationIcloudEnvironment = _authenticationIcloudEnvironment; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTEscrowAuthenticationInformation *copy = [[[self class] allocWithZone:zone] init]; + copy->_authenticationPassword = [_authenticationPassword copyWithZone:zone]; + copy->_authenticationDsid = [_authenticationDsid copyWithZone:zone]; + copy->_authenticationAppleid = [_authenticationAppleid copyWithZone:zone]; + copy->_fmipUuid = [_fmipUuid copyWithZone:zone]; + if (self->_has.fmipRecovery) + { + copy->_fmipRecovery = _fmipRecovery; + copy->_has.fmipRecovery = YES; + } + if (self->_has.idmsRecovery) + { + copy->_idmsRecovery = _idmsRecovery; + copy->_has.idmsRecovery = YES; + } + copy->_authenticationAuthToken = [_authenticationAuthToken copyWithZone:zone]; + copy->_authenticationEscrowproxyUrl = [_authenticationEscrowproxyUrl copyWithZone:zone]; + copy->_authenticationIcloudEnvironment = [_authenticationIcloudEnvironment copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTEscrowAuthenticationInformation *other = (OTEscrowAuthenticationInformation *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_authenticationPassword && !other->_authenticationPassword) || [self->_authenticationPassword isEqual:other->_authenticationPassword]) + && + ((!self->_authenticationDsid && !other->_authenticationDsid) || [self->_authenticationDsid isEqual:other->_authenticationDsid]) + && + ((!self->_authenticationAppleid && !other->_authenticationAppleid) || [self->_authenticationAppleid isEqual:other->_authenticationAppleid]) + && + ((!self->_fmipUuid && !other->_fmipUuid) || [self->_fmipUuid isEqual:other->_fmipUuid]) + && + ((self->_has.fmipRecovery && other->_has.fmipRecovery && ((self->_fmipRecovery && other->_fmipRecovery) || (!self->_fmipRecovery && !other->_fmipRecovery))) || (!self->_has.fmipRecovery && !other->_has.fmipRecovery)) + && + ((self->_has.idmsRecovery && other->_has.idmsRecovery && ((self->_idmsRecovery && other->_idmsRecovery) || (!self->_idmsRecovery && !other->_idmsRecovery))) || (!self->_has.idmsRecovery && !other->_has.idmsRecovery)) + && + ((!self->_authenticationAuthToken && !other->_authenticationAuthToken) || [self->_authenticationAuthToken isEqual:other->_authenticationAuthToken]) + && + ((!self->_authenticationEscrowproxyUrl && !other->_authenticationEscrowproxyUrl) || [self->_authenticationEscrowproxyUrl isEqual:other->_authenticationEscrowproxyUrl]) + && + ((!self->_authenticationIcloudEnvironment && !other->_authenticationIcloudEnvironment) || [self->_authenticationIcloudEnvironment isEqual:other->_authenticationIcloudEnvironment]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_authenticationPassword hash] + ^ + [self->_authenticationDsid hash] + ^ + [self->_authenticationAppleid hash] + ^ + [self->_fmipUuid hash] + ^ + (self->_has.fmipRecovery ? PBHashInt((NSUInteger)self->_fmipRecovery) : 0) + ^ + (self->_has.idmsRecovery ? PBHashInt((NSUInteger)self->_idmsRecovery) : 0) + ^ + [self->_authenticationAuthToken hash] + ^ + [self->_authenticationEscrowproxyUrl hash] + ^ + [self->_authenticationIcloudEnvironment hash] + ; +} + +- (void)mergeFrom:(OTEscrowAuthenticationInformation *)other +{ + if (other->_authenticationPassword) + { + [self setAuthenticationPassword:other->_authenticationPassword]; + } + if (other->_authenticationDsid) + { + [self setAuthenticationDsid:other->_authenticationDsid]; + } + if (other->_authenticationAppleid) + { + [self setAuthenticationAppleid:other->_authenticationAppleid]; + } + if (other->_fmipUuid) + { + [self setFmipUuid:other->_fmipUuid]; + } + if (other->_has.fmipRecovery) + { + self->_fmipRecovery = other->_fmipRecovery; + self->_has.fmipRecovery = YES; + } + if (other->_has.idmsRecovery) + { + self->_idmsRecovery = other->_idmsRecovery; + self->_has.idmsRecovery = YES; + } + if (other->_authenticationAuthToken) + { + [self setAuthenticationAuthToken:other->_authenticationAuthToken]; + } + if (other->_authenticationEscrowproxyUrl) + { + [self setAuthenticationEscrowproxyUrl:other->_authenticationEscrowproxyUrl]; + } + if (other->_authenticationIcloudEnvironment) + { + [self setAuthenticationIcloudEnvironment:other->_authenticationIcloudEnvironment]; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecord.h b/keychain/ot/proto/generated_source/OTEscrowRecord.h new file mode 100644 index 00000000..5c1e77e7 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecord.h @@ -0,0 +1,215 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import +#import + +@class OTEscrowRecordMetadata; + +typedef NS_ENUM(int32_t, OTEscrowRecord_RecordStatus) { + OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID = 0, + OTEscrowRecord_RecordStatus_RECORD_STATUS_INVALID = 1, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTEscrowRecord_RecordStatusAsString(OTEscrowRecord_RecordStatus value) +{ + switch (value) + { + case OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID: return @"RECORD_STATUS_VALID"; + case OTEscrowRecord_RecordStatus_RECORD_STATUS_INVALID: return @"RECORD_STATUS_INVALID"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTEscrowRecord_RecordStatus StringAsOTEscrowRecord_RecordStatus(NSString *value) +{ + if ([value isEqualToString:@"RECORD_STATUS_VALID"]) return OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + if ([value isEqualToString:@"RECORD_STATUS_INVALID"]) return OTEscrowRecord_RecordStatus_RECORD_STATUS_INVALID; + return OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; +} +#endif /* __OBJC__ */ +typedef NS_ENUM(int32_t, OTEscrowRecord_RecoveryStatus) { + OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID = 0, + OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_SOFT_LIMIT_REACHED = 1, + OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_HARD_LIMIT_REACHED = 2, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTEscrowRecord_RecoveryStatusAsString(OTEscrowRecord_RecoveryStatus value) +{ + switch (value) + { + case OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID: return @"RECOVERY_STATUS_VALID"; + case OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_SOFT_LIMIT_REACHED: return @"RECOVERY_STATUS_SOFT_LIMIT_REACHED"; + case OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_HARD_LIMIT_REACHED: return @"RECOVERY_STATUS_HARD_LIMIT_REACHED"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTEscrowRecord_RecoveryStatus StringAsOTEscrowRecord_RecoveryStatus(NSString *value) +{ + if ([value isEqualToString:@"RECOVERY_STATUS_VALID"]) return OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID; + if ([value isEqualToString:@"RECOVERY_STATUS_SOFT_LIMIT_REACHED"]) return OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_SOFT_LIMIT_REACHED; + if ([value isEqualToString:@"RECOVERY_STATUS_HARD_LIMIT_REACHED"]) return OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_HARD_LIMIT_REACHED; + return OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID; +} +#endif /* __OBJC__ */ +typedef NS_ENUM(int32_t, OTEscrowRecord_RecordViability) { + OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE = 0, + OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE = 1, + OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY = 2, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTEscrowRecord_RecordViabilityAsString(OTEscrowRecord_RecordViability value) +{ + switch (value) + { + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE: return @"RECORD_VIABILITY_FULLY_VIABLE"; + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE: return @"RECORD_VIABILITY_PARTIALLY_VIABLE"; + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY: return @"RECORD_VIABILITY_LEGACY"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTEscrowRecord_RecordViability StringAsOTEscrowRecord_RecordViability(NSString *value) +{ + if ([value isEqualToString:@"RECORD_VIABILITY_FULLY_VIABLE"]) return OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE; + if ([value isEqualToString:@"RECORD_VIABILITY_PARTIALLY_VIABLE"]) return OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE; + if ([value isEqualToString:@"RECORD_VIABILITY_LEGACY"]) return OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY; + return OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE; +} +#endif /* __OBJC__ */ +typedef NS_ENUM(int32_t, OTEscrowRecord_SOSViability) { + OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN = 0, + OTEscrowRecord_SOSViability_SOS_VIABLE = 1, + OTEscrowRecord_SOSViability_SOS_NOT_VIABLE = 2, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTEscrowRecord_SOSViabilityAsString(OTEscrowRecord_SOSViability value) +{ + switch (value) + { + case OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN: return @"SOS_VIABLE_UNKNOWN"; + case OTEscrowRecord_SOSViability_SOS_VIABLE: return @"SOS_VIABLE"; + case OTEscrowRecord_SOSViability_SOS_NOT_VIABLE: return @"SOS_NOT_VIABLE"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTEscrowRecord_SOSViability StringAsOTEscrowRecord_SOSViability(NSString *value) +{ + if ([value isEqualToString:@"SOS_VIABLE_UNKNOWN"]) return OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN; + if ([value isEqualToString:@"SOS_VIABLE"]) return OTEscrowRecord_SOSViability_SOS_VIABLE; + if ([value isEqualToString:@"SOS_NOT_VIABLE"]) return OTEscrowRecord_SOSViability_SOS_NOT_VIABLE; + return OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN; +} +#endif /* __OBJC__ */ + +#ifdef __cplusplus +#define OTESCROWRECORD_FUNCTION extern "C" +#else +#define OTESCROWRECORD_FUNCTION extern +#endif + +@interface OTEscrowRecord : PBCodable +{ + uint64_t _coolOffEnd; + uint64_t _creationDate; + uint64_t _remainingAttempts; + uint64_t _silentAttemptAllowed; + OTEscrowRecordMetadata *_escrowInformationMetadata; + NSString *_expectedFederationId; + NSString *_federationId; + NSString *_label; + NSString *_recordId; + OTEscrowRecord_RecordStatus _recordStatus; + OTEscrowRecord_RecordViability _recordViability; + OTEscrowRecord_RecoveryStatus _recoveryStatus; + NSString *_serialNumber; + OTEscrowRecord_SOSViability _viabilityStatus; + struct { + int coolOffEnd:1; + int creationDate:1; + int remainingAttempts:1; + int silentAttemptAllowed:1; + int recordStatus:1; + int recordViability:1; + int recoveryStatus:1; + int viabilityStatus:1; + } _has; +} + + +@property (nonatomic) BOOL hasCreationDate; +@property (nonatomic) uint64_t creationDate; + +@property (nonatomic) BOOL hasRemainingAttempts; +@property (nonatomic) uint64_t remainingAttempts; + +@property (nonatomic, readonly) BOOL hasEscrowInformationMetadata; +@property (nonatomic, retain) OTEscrowRecordMetadata *escrowInformationMetadata; + +@property (nonatomic, readonly) BOOL hasLabel; +@property (nonatomic, retain) NSString *label; + +@property (nonatomic) BOOL hasSilentAttemptAllowed; +/** + * optional reserved string reserved5 = 5; + * optional reserved string reserved6 = 6; + * optional reserved string reserved7 = 7; + * optional reserved string reserved8 = 8; + */ +@property (nonatomic) uint64_t silentAttemptAllowed; + +@property (nonatomic) BOOL hasRecordStatus; +@property (nonatomic) OTEscrowRecord_RecordStatus recordStatus; +- (NSString *)recordStatusAsString:(OTEscrowRecord_RecordStatus)value; +- (OTEscrowRecord_RecordStatus)StringAsRecordStatus:(NSString *)str; + +@property (nonatomic, readonly) BOOL hasRecordId; +@property (nonatomic, retain) NSString *recordId; + +@property (nonatomic) BOOL hasRecoveryStatus; +@property (nonatomic) OTEscrowRecord_RecoveryStatus recoveryStatus; +- (NSString *)recoveryStatusAsString:(OTEscrowRecord_RecoveryStatus)value; +- (OTEscrowRecord_RecoveryStatus)StringAsRecoveryStatus:(NSString *)str; + +@property (nonatomic) BOOL hasCoolOffEnd; +@property (nonatomic) uint64_t coolOffEnd; + +@property (nonatomic, readonly) BOOL hasSerialNumber; +@property (nonatomic, retain) NSString *serialNumber; + +@property (nonatomic) BOOL hasRecordViability; +@property (nonatomic) OTEscrowRecord_RecordViability recordViability; +- (NSString *)recordViabilityAsString:(OTEscrowRecord_RecordViability)value; +- (OTEscrowRecord_RecordViability)StringAsRecordViability:(NSString *)str; + +@property (nonatomic) BOOL hasViabilityStatus; +@property (nonatomic) OTEscrowRecord_SOSViability viabilityStatus; +- (NSString *)viabilityStatusAsString:(OTEscrowRecord_SOSViability)value; +- (OTEscrowRecord_SOSViability)StringAsViabilityStatus:(NSString *)str; + +@property (nonatomic, readonly) BOOL hasFederationId; +@property (nonatomic, retain) NSString *federationId; + +@property (nonatomic, readonly) BOOL hasExpectedFederationId; +@property (nonatomic, retain) NSString *expectedFederationId; + +// Performs a shallow copy into other +- (void)copyTo:(OTEscrowRecord *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTEscrowRecord *)other; + +OTESCROWRECORD_FUNCTION BOOL OTEscrowRecordReadFrom(__unsafe_unretained OTEscrowRecord *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecord.m b/keychain/ot/proto/generated_source/OTEscrowRecord.m new file mode 100644 index 00000000..030c0824 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecord.m @@ -0,0 +1,765 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import "OTEscrowRecord.h" +#import +#import +#import + +#import "OTEscrowRecordMetadata.h" + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTEscrowRecord + +@synthesize creationDate = _creationDate; +- (void)setCreationDate:(uint64_t)v +{ + _has.creationDate = YES; + _creationDate = v; +} +- (void)setHasCreationDate:(BOOL)f +{ + _has.creationDate = f; +} +- (BOOL)hasCreationDate +{ + return _has.creationDate != 0; +} +@synthesize remainingAttempts = _remainingAttempts; +- (void)setRemainingAttempts:(uint64_t)v +{ + _has.remainingAttempts = YES; + _remainingAttempts = v; +} +- (void)setHasRemainingAttempts:(BOOL)f +{ + _has.remainingAttempts = f; +} +- (BOOL)hasRemainingAttempts +{ + return _has.remainingAttempts != 0; +} +- (BOOL)hasEscrowInformationMetadata +{ + return _escrowInformationMetadata != nil; +} +@synthesize escrowInformationMetadata = _escrowInformationMetadata; +- (BOOL)hasLabel +{ + return _label != nil; +} +@synthesize label = _label; +@synthesize silentAttemptAllowed = _silentAttemptAllowed; +- (void)setSilentAttemptAllowed:(uint64_t)v +{ + _has.silentAttemptAllowed = YES; + _silentAttemptAllowed = v; +} +- (void)setHasSilentAttemptAllowed:(BOOL)f +{ + _has.silentAttemptAllowed = f; +} +- (BOOL)hasSilentAttemptAllowed +{ + return _has.silentAttemptAllowed != 0; +} +@synthesize recordStatus = _recordStatus; +- (OTEscrowRecord_RecordStatus)recordStatus +{ + return _has.recordStatus ? _recordStatus : OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; +} +- (void)setRecordStatus:(OTEscrowRecord_RecordStatus)v +{ + _has.recordStatus = YES; + _recordStatus = v; +} +- (void)setHasRecordStatus:(BOOL)f +{ + _has.recordStatus = f; +} +- (BOOL)hasRecordStatus +{ + return _has.recordStatus != 0; +} +- (NSString *)recordStatusAsString:(OTEscrowRecord_RecordStatus)value +{ + return OTEscrowRecord_RecordStatusAsString(value); +} +- (OTEscrowRecord_RecordStatus)StringAsRecordStatus:(NSString *)str +{ + return StringAsOTEscrowRecord_RecordStatus(str); +} +- (BOOL)hasRecordId +{ + return _recordId != nil; +} +@synthesize recordId = _recordId; +@synthesize recoveryStatus = _recoveryStatus; +- (OTEscrowRecord_RecoveryStatus)recoveryStatus +{ + return _has.recoveryStatus ? _recoveryStatus : OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID; +} +- (void)setRecoveryStatus:(OTEscrowRecord_RecoveryStatus)v +{ + _has.recoveryStatus = YES; + _recoveryStatus = v; +} +- (void)setHasRecoveryStatus:(BOOL)f +{ + _has.recoveryStatus = f; +} +- (BOOL)hasRecoveryStatus +{ + return _has.recoveryStatus != 0; +} +- (NSString *)recoveryStatusAsString:(OTEscrowRecord_RecoveryStatus)value +{ + return OTEscrowRecord_RecoveryStatusAsString(value); +} +- (OTEscrowRecord_RecoveryStatus)StringAsRecoveryStatus:(NSString *)str +{ + return StringAsOTEscrowRecord_RecoveryStatus(str); +} +@synthesize coolOffEnd = _coolOffEnd; +- (void)setCoolOffEnd:(uint64_t)v +{ + _has.coolOffEnd = YES; + _coolOffEnd = v; +} +- (void)setHasCoolOffEnd:(BOOL)f +{ + _has.coolOffEnd = f; +} +- (BOOL)hasCoolOffEnd +{ + return _has.coolOffEnd != 0; +} +- (BOOL)hasSerialNumber +{ + return _serialNumber != nil; +} +@synthesize serialNumber = _serialNumber; +@synthesize recordViability = _recordViability; +- (OTEscrowRecord_RecordViability)recordViability +{ + return _has.recordViability ? _recordViability : OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE; +} +- (void)setRecordViability:(OTEscrowRecord_RecordViability)v +{ + _has.recordViability = YES; + _recordViability = v; +} +- (void)setHasRecordViability:(BOOL)f +{ + _has.recordViability = f; +} +- (BOOL)hasRecordViability +{ + return _has.recordViability != 0; +} +- (NSString *)recordViabilityAsString:(OTEscrowRecord_RecordViability)value +{ + return OTEscrowRecord_RecordViabilityAsString(value); +} +- (OTEscrowRecord_RecordViability)StringAsRecordViability:(NSString *)str +{ + return StringAsOTEscrowRecord_RecordViability(str); +} +@synthesize viabilityStatus = _viabilityStatus; +- (OTEscrowRecord_SOSViability)viabilityStatus +{ + return _has.viabilityStatus ? _viabilityStatus : OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN; +} +- (void)setViabilityStatus:(OTEscrowRecord_SOSViability)v +{ + _has.viabilityStatus = YES; + _viabilityStatus = v; +} +- (void)setHasViabilityStatus:(BOOL)f +{ + _has.viabilityStatus = f; +} +- (BOOL)hasViabilityStatus +{ + return _has.viabilityStatus != 0; +} +- (NSString *)viabilityStatusAsString:(OTEscrowRecord_SOSViability)value +{ + return OTEscrowRecord_SOSViabilityAsString(value); +} +- (OTEscrowRecord_SOSViability)StringAsViabilityStatus:(NSString *)str +{ + return StringAsOTEscrowRecord_SOSViability(str); +} +- (BOOL)hasFederationId +{ + return _federationId != nil; +} +@synthesize federationId = _federationId; +- (BOOL)hasExpectedFederationId +{ + return _expectedFederationId != nil; +} +@synthesize expectedFederationId = _expectedFederationId; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.creationDate) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_creationDate] forKey:@"creation_date"]; + } + if (self->_has.remainingAttempts) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_remainingAttempts] forKey:@"remaining_attempts"]; + } + if (self->_escrowInformationMetadata) + { + [dict setObject:[_escrowInformationMetadata dictionaryRepresentation] forKey:@"escrow_information_metadata"]; + } + if (self->_label) + { + [dict setObject:self->_label forKey:@"label"]; + } + if (self->_has.silentAttemptAllowed) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_silentAttemptAllowed] forKey:@"silent_attempt_allowed"]; + } + if (self->_has.recordStatus) + { + [dict setObject:OTEscrowRecord_RecordStatusAsString(self->_recordStatus) forKey:@"record_status"]; + } + if (self->_recordId) + { + [dict setObject:self->_recordId forKey:@"record_id"]; + } + if (self->_has.recoveryStatus) + { + [dict setObject:OTEscrowRecord_RecoveryStatusAsString(self->_recoveryStatus) forKey:@"recovery_status"]; + } + if (self->_has.coolOffEnd) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_coolOffEnd] forKey:@"cool_off_end"]; + } + if (self->_serialNumber) + { + [dict setObject:self->_serialNumber forKey:@"serial_number"]; + } + if (self->_has.recordViability) + { + [dict setObject:OTEscrowRecord_RecordViabilityAsString(self->_recordViability) forKey:@"record_viability"]; + } + if (self->_has.viabilityStatus) + { + [dict setObject:OTEscrowRecord_SOSViabilityAsString(self->_viabilityStatus) forKey:@"viability_status"]; + } + if (self->_federationId) + { + [dict setObject:self->_federationId forKey:@"federation_id"]; + } + if (self->_expectedFederationId) + { + [dict setObject:self->_expectedFederationId forKey:@"expected_federation_id"]; + } + return dict; +} + +BOOL OTEscrowRecordReadFrom(__unsafe_unretained OTEscrowRecord *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* creationDate */: + { + self->_has.creationDate = YES; + self->_creationDate = PBReaderReadUint64(reader); + } + break; + case 2 /* remainingAttempts */: + { + self->_has.remainingAttempts = YES; + self->_remainingAttempts = PBReaderReadUint64(reader); + } + break; + case 3 /* escrowInformationMetadata */: + { + OTEscrowRecordMetadata *new_escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + self->_escrowInformationMetadata = new_escrowInformationMetadata; + PBDataReaderMark mark_escrowInformationMetadata; + BOOL markError = !PBReaderPlaceMark(reader, &mark_escrowInformationMetadata); + if (markError) + { + return NO; + } + BOOL inError = !OTEscrowRecordMetadataReadFrom(new_escrowInformationMetadata, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_escrowInformationMetadata); + } + break; + case 4 /* label */: + { + NSString *new_label = PBReaderReadString(reader); + self->_label = new_label; + } + break; + case 9 /* silentAttemptAllowed */: + { + self->_has.silentAttemptAllowed = YES; + self->_silentAttemptAllowed = PBReaderReadUint64(reader); + } + break; + case 10 /* recordStatus */: + { + self->_has.recordStatus = YES; + self->_recordStatus = PBReaderReadInt32(reader); + } + break; + case 11 /* recordId */: + { + NSString *new_recordId = PBReaderReadString(reader); + self->_recordId = new_recordId; + } + break; + case 12 /* recoveryStatus */: + { + self->_has.recoveryStatus = YES; + self->_recoveryStatus = PBReaderReadInt32(reader); + } + break; + case 13 /* coolOffEnd */: + { + self->_has.coolOffEnd = YES; + self->_coolOffEnd = PBReaderReadUint64(reader); + } + break; + case 14 /* serialNumber */: + { + NSString *new_serialNumber = PBReaderReadString(reader); + self->_serialNumber = new_serialNumber; + } + break; + case 15 /* recordViability */: + { + self->_has.recordViability = YES; + self->_recordViability = PBReaderReadInt32(reader); + } + break; + case 16 /* viabilityStatus */: + { + self->_has.viabilityStatus = YES; + self->_viabilityStatus = PBReaderReadInt32(reader); + } + break; + case 17 /* federationId */: + { + NSString *new_federationId = PBReaderReadString(reader); + self->_federationId = new_federationId; + } + break; + case 18 /* expectedFederationId */: + { + NSString *new_expectedFederationId = PBReaderReadString(reader); + self->_expectedFederationId = new_expectedFederationId; + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTEscrowRecordReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* creationDate */ + { + if (self->_has.creationDate) + { + PBDataWriterWriteUint64Field(writer, self->_creationDate, 1); + } + } + /* remainingAttempts */ + { + if (self->_has.remainingAttempts) + { + PBDataWriterWriteUint64Field(writer, self->_remainingAttempts, 2); + } + } + /* escrowInformationMetadata */ + { + if (self->_escrowInformationMetadata != nil) + { + PBDataWriterWriteSubmessage(writer, self->_escrowInformationMetadata, 3); + } + } + /* label */ + { + if (self->_label) + { + PBDataWriterWriteStringField(writer, self->_label, 4); + } + } + /* silentAttemptAllowed */ + { + if (self->_has.silentAttemptAllowed) + { + PBDataWriterWriteUint64Field(writer, self->_silentAttemptAllowed, 9); + } + } + /* recordStatus */ + { + if (self->_has.recordStatus) + { + PBDataWriterWriteInt32Field(writer, self->_recordStatus, 10); + } + } + /* recordId */ + { + if (self->_recordId) + { + PBDataWriterWriteStringField(writer, self->_recordId, 11); + } + } + /* recoveryStatus */ + { + if (self->_has.recoveryStatus) + { + PBDataWriterWriteInt32Field(writer, self->_recoveryStatus, 12); + } + } + /* coolOffEnd */ + { + if (self->_has.coolOffEnd) + { + PBDataWriterWriteUint64Field(writer, self->_coolOffEnd, 13); + } + } + /* serialNumber */ + { + if (self->_serialNumber) + { + PBDataWriterWriteStringField(writer, self->_serialNumber, 14); + } + } + /* recordViability */ + { + if (self->_has.recordViability) + { + PBDataWriterWriteInt32Field(writer, self->_recordViability, 15); + } + } + /* viabilityStatus */ + { + if (self->_has.viabilityStatus) + { + PBDataWriterWriteInt32Field(writer, self->_viabilityStatus, 16); + } + } + /* federationId */ + { + if (self->_federationId) + { + PBDataWriterWriteStringField(writer, self->_federationId, 17); + } + } + /* expectedFederationId */ + { + if (self->_expectedFederationId) + { + PBDataWriterWriteStringField(writer, self->_expectedFederationId, 18); + } + } +} + +- (void)copyTo:(OTEscrowRecord *)other +{ + if (self->_has.creationDate) + { + other->_creationDate = _creationDate; + other->_has.creationDate = YES; + } + if (self->_has.remainingAttempts) + { + other->_remainingAttempts = _remainingAttempts; + other->_has.remainingAttempts = YES; + } + if (_escrowInformationMetadata) + { + other.escrowInformationMetadata = _escrowInformationMetadata; + } + if (_label) + { + other.label = _label; + } + if (self->_has.silentAttemptAllowed) + { + other->_silentAttemptAllowed = _silentAttemptAllowed; + other->_has.silentAttemptAllowed = YES; + } + if (self->_has.recordStatus) + { + other->_recordStatus = _recordStatus; + other->_has.recordStatus = YES; + } + if (_recordId) + { + other.recordId = _recordId; + } + if (self->_has.recoveryStatus) + { + other->_recoveryStatus = _recoveryStatus; + other->_has.recoveryStatus = YES; + } + if (self->_has.coolOffEnd) + { + other->_coolOffEnd = _coolOffEnd; + other->_has.coolOffEnd = YES; + } + if (_serialNumber) + { + other.serialNumber = _serialNumber; + } + if (self->_has.recordViability) + { + other->_recordViability = _recordViability; + other->_has.recordViability = YES; + } + if (self->_has.viabilityStatus) + { + other->_viabilityStatus = _viabilityStatus; + other->_has.viabilityStatus = YES; + } + if (_federationId) + { + other.federationId = _federationId; + } + if (_expectedFederationId) + { + other.expectedFederationId = _expectedFederationId; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTEscrowRecord *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.creationDate) + { + copy->_creationDate = _creationDate; + copy->_has.creationDate = YES; + } + if (self->_has.remainingAttempts) + { + copy->_remainingAttempts = _remainingAttempts; + copy->_has.remainingAttempts = YES; + } + copy->_escrowInformationMetadata = [_escrowInformationMetadata copyWithZone:zone]; + copy->_label = [_label copyWithZone:zone]; + if (self->_has.silentAttemptAllowed) + { + copy->_silentAttemptAllowed = _silentAttemptAllowed; + copy->_has.silentAttemptAllowed = YES; + } + if (self->_has.recordStatus) + { + copy->_recordStatus = _recordStatus; + copy->_has.recordStatus = YES; + } + copy->_recordId = [_recordId copyWithZone:zone]; + if (self->_has.recoveryStatus) + { + copy->_recoveryStatus = _recoveryStatus; + copy->_has.recoveryStatus = YES; + } + if (self->_has.coolOffEnd) + { + copy->_coolOffEnd = _coolOffEnd; + copy->_has.coolOffEnd = YES; + } + copy->_serialNumber = [_serialNumber copyWithZone:zone]; + if (self->_has.recordViability) + { + copy->_recordViability = _recordViability; + copy->_has.recordViability = YES; + } + if (self->_has.viabilityStatus) + { + copy->_viabilityStatus = _viabilityStatus; + copy->_has.viabilityStatus = YES; + } + copy->_federationId = [_federationId copyWithZone:zone]; + copy->_expectedFederationId = [_expectedFederationId copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTEscrowRecord *other = (OTEscrowRecord *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.creationDate && other->_has.creationDate && self->_creationDate == other->_creationDate) || (!self->_has.creationDate && !other->_has.creationDate)) + && + ((self->_has.remainingAttempts && other->_has.remainingAttempts && self->_remainingAttempts == other->_remainingAttempts) || (!self->_has.remainingAttempts && !other->_has.remainingAttempts)) + && + ((!self->_escrowInformationMetadata && !other->_escrowInformationMetadata) || [self->_escrowInformationMetadata isEqual:other->_escrowInformationMetadata]) + && + ((!self->_label && !other->_label) || [self->_label isEqual:other->_label]) + && + ((self->_has.silentAttemptAllowed && other->_has.silentAttemptAllowed && self->_silentAttemptAllowed == other->_silentAttemptAllowed) || (!self->_has.silentAttemptAllowed && !other->_has.silentAttemptAllowed)) + && + ((self->_has.recordStatus && other->_has.recordStatus && self->_recordStatus == other->_recordStatus) || (!self->_has.recordStatus && !other->_has.recordStatus)) + && + ((!self->_recordId && !other->_recordId) || [self->_recordId isEqual:other->_recordId]) + && + ((self->_has.recoveryStatus && other->_has.recoveryStatus && self->_recoveryStatus == other->_recoveryStatus) || (!self->_has.recoveryStatus && !other->_has.recoveryStatus)) + && + ((self->_has.coolOffEnd && other->_has.coolOffEnd && self->_coolOffEnd == other->_coolOffEnd) || (!self->_has.coolOffEnd && !other->_has.coolOffEnd)) + && + ((!self->_serialNumber && !other->_serialNumber) || [self->_serialNumber isEqual:other->_serialNumber]) + && + ((self->_has.recordViability && other->_has.recordViability && self->_recordViability == other->_recordViability) || (!self->_has.recordViability && !other->_has.recordViability)) + && + ((self->_has.viabilityStatus && other->_has.viabilityStatus && self->_viabilityStatus == other->_viabilityStatus) || (!self->_has.viabilityStatus && !other->_has.viabilityStatus)) + && + ((!self->_federationId && !other->_federationId) || [self->_federationId isEqual:other->_federationId]) + && + ((!self->_expectedFederationId && !other->_expectedFederationId) || [self->_expectedFederationId isEqual:other->_expectedFederationId]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.creationDate ? PBHashInt((NSUInteger)self->_creationDate) : 0) + ^ + (self->_has.remainingAttempts ? PBHashInt((NSUInteger)self->_remainingAttempts) : 0) + ^ + [self->_escrowInformationMetadata hash] + ^ + [self->_label hash] + ^ + (self->_has.silentAttemptAllowed ? PBHashInt((NSUInteger)self->_silentAttemptAllowed) : 0) + ^ + (self->_has.recordStatus ? PBHashInt((NSUInteger)self->_recordStatus) : 0) + ^ + [self->_recordId hash] + ^ + (self->_has.recoveryStatus ? PBHashInt((NSUInteger)self->_recoveryStatus) : 0) + ^ + (self->_has.coolOffEnd ? PBHashInt((NSUInteger)self->_coolOffEnd) : 0) + ^ + [self->_serialNumber hash] + ^ + (self->_has.recordViability ? PBHashInt((NSUInteger)self->_recordViability) : 0) + ^ + (self->_has.viabilityStatus ? PBHashInt((NSUInteger)self->_viabilityStatus) : 0) + ^ + [self->_federationId hash] + ^ + [self->_expectedFederationId hash] + ; +} + +- (void)mergeFrom:(OTEscrowRecord *)other +{ + if (other->_has.creationDate) + { + self->_creationDate = other->_creationDate; + self->_has.creationDate = YES; + } + if (other->_has.remainingAttempts) + { + self->_remainingAttempts = other->_remainingAttempts; + self->_has.remainingAttempts = YES; + } + if (self->_escrowInformationMetadata && other->_escrowInformationMetadata) + { + [self->_escrowInformationMetadata mergeFrom:other->_escrowInformationMetadata]; + } + else if (!self->_escrowInformationMetadata && other->_escrowInformationMetadata) + { + [self setEscrowInformationMetadata:other->_escrowInformationMetadata]; + } + if (other->_label) + { + [self setLabel:other->_label]; + } + if (other->_has.silentAttemptAllowed) + { + self->_silentAttemptAllowed = other->_silentAttemptAllowed; + self->_has.silentAttemptAllowed = YES; + } + if (other->_has.recordStatus) + { + self->_recordStatus = other->_recordStatus; + self->_has.recordStatus = YES; + } + if (other->_recordId) + { + [self setRecordId:other->_recordId]; + } + if (other->_has.recoveryStatus) + { + self->_recoveryStatus = other->_recoveryStatus; + self->_has.recoveryStatus = YES; + } + if (other->_has.coolOffEnd) + { + self->_coolOffEnd = other->_coolOffEnd; + self->_has.coolOffEnd = YES; + } + if (other->_serialNumber) + { + [self setSerialNumber:other->_serialNumber]; + } + if (other->_has.recordViability) + { + self->_recordViability = other->_recordViability; + self->_has.recordViability = YES; + } + if (other->_has.viabilityStatus) + { + self->_viabilityStatus = other->_viabilityStatus; + self->_has.viabilityStatus = YES; + } + if (other->_federationId) + { + [self setFederationId:other->_federationId]; + } + if (other->_expectedFederationId) + { + [self setExpectedFederationId:other->_expectedFederationId]; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h b/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h new file mode 100644 index 00000000..1d75c3ad --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h @@ -0,0 +1,73 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import +#import + +@class OTEscrowRecordMetadataClientMetadata; + +#ifdef __cplusplus +#define OTESCROWRECORDMETADATA_FUNCTION extern "C" +#else +#define OTESCROWRECORDMETADATA_FUNCTION extern +#endif + +@interface OTEscrowRecordMetadata : PBCodable +{ + uint64_t _secureBackupTimestamp; + uint64_t _secureBackupUsesMultipleIcscs; + NSData *_backupKeybagDigest; + NSString *_bottleId; + NSString *_bottleValidity; + OTEscrowRecordMetadataClientMetadata *_clientMetadata; + NSData *_escrowedSpki; + NSData *_peerInfo; + NSString *_serial; + struct { + int secureBackupTimestamp:1; + int secureBackupUsesMultipleIcscs:1; + } _has; +} + + +@property (nonatomic, readonly) BOOL hasBackupKeybagDigest; +@property (nonatomic, retain) NSData *backupKeybagDigest; + +@property (nonatomic, readonly) BOOL hasClientMetadata; +@property (nonatomic, retain) OTEscrowRecordMetadataClientMetadata *clientMetadata; + +@property (nonatomic) BOOL hasSecureBackupUsesMultipleIcscs; +@property (nonatomic) uint64_t secureBackupUsesMultipleIcscs; + +@property (nonatomic, readonly) BOOL hasBottleId; +@property (nonatomic, retain) NSString *bottleId; + +@property (nonatomic) BOOL hasSecureBackupTimestamp; +@property (nonatomic) uint64_t secureBackupTimestamp; + +@property (nonatomic, readonly) BOOL hasEscrowedSpki; +@property (nonatomic, retain) NSData *escrowedSpki; + +@property (nonatomic, readonly) BOOL hasPeerInfo; +@property (nonatomic, retain) NSData *peerInfo; + +@property (nonatomic, readonly) BOOL hasBottleValidity; +@property (nonatomic, retain) NSString *bottleValidity; + +@property (nonatomic, readonly) BOOL hasSerial; +@property (nonatomic, retain) NSString *serial; + +// Performs a shallow copy into other +- (void)copyTo:(OTEscrowRecordMetadata *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTEscrowRecordMetadata *)other; + +OTESCROWRECORDMETADATA_FUNCTION BOOL OTEscrowRecordMetadataReadFrom(__unsafe_unretained OTEscrowRecordMetadata *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.m b/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.m new file mode 100644 index 00000000..ca48c520 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.m @@ -0,0 +1,452 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import "OTEscrowRecordMetadata.h" +#import +#import +#import + +#import "OTEscrowRecordMetadataClientMetadata.h" + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTEscrowRecordMetadata + +- (BOOL)hasBackupKeybagDigest +{ + return _backupKeybagDigest != nil; +} +@synthesize backupKeybagDigest = _backupKeybagDigest; +- (BOOL)hasClientMetadata +{ + return _clientMetadata != nil; +} +@synthesize clientMetadata = _clientMetadata; +@synthesize secureBackupUsesMultipleIcscs = _secureBackupUsesMultipleIcscs; +- (void)setSecureBackupUsesMultipleIcscs:(uint64_t)v +{ + _has.secureBackupUsesMultipleIcscs = YES; + _secureBackupUsesMultipleIcscs = v; +} +- (void)setHasSecureBackupUsesMultipleIcscs:(BOOL)f +{ + _has.secureBackupUsesMultipleIcscs = f; +} +- (BOOL)hasSecureBackupUsesMultipleIcscs +{ + return _has.secureBackupUsesMultipleIcscs != 0; +} +- (BOOL)hasBottleId +{ + return _bottleId != nil; +} +@synthesize bottleId = _bottleId; +@synthesize secureBackupTimestamp = _secureBackupTimestamp; +- (void)setSecureBackupTimestamp:(uint64_t)v +{ + _has.secureBackupTimestamp = YES; + _secureBackupTimestamp = v; +} +- (void)setHasSecureBackupTimestamp:(BOOL)f +{ + _has.secureBackupTimestamp = f; +} +- (BOOL)hasSecureBackupTimestamp +{ + return _has.secureBackupTimestamp != 0; +} +- (BOOL)hasEscrowedSpki +{ + return _escrowedSpki != nil; +} +@synthesize escrowedSpki = _escrowedSpki; +- (BOOL)hasPeerInfo +{ + return _peerInfo != nil; +} +@synthesize peerInfo = _peerInfo; +- (BOOL)hasBottleValidity +{ + return _bottleValidity != nil; +} +@synthesize bottleValidity = _bottleValidity; +- (BOOL)hasSerial +{ + return _serial != nil; +} +@synthesize serial = _serial; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_backupKeybagDigest) + { + [dict setObject:self->_backupKeybagDigest forKey:@"backup_keybag_digest"]; + } + if (self->_clientMetadata) + { + [dict setObject:[_clientMetadata dictionaryRepresentation] forKey:@"client_metadata"]; + } + if (self->_has.secureBackupUsesMultipleIcscs) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupUsesMultipleIcscs] forKey:@"secure_backup_uses_multiple_icscs"]; + } + if (self->_bottleId) + { + [dict setObject:self->_bottleId forKey:@"bottle_id"]; + } + if (self->_has.secureBackupTimestamp) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupTimestamp] forKey:@"secure_backup_timestamp"]; + } + if (self->_escrowedSpki) + { + [dict setObject:self->_escrowedSpki forKey:@"escrowed_spki"]; + } + if (self->_peerInfo) + { + [dict setObject:self->_peerInfo forKey:@"peer_info"]; + } + if (self->_bottleValidity) + { + [dict setObject:self->_bottleValidity forKey:@"bottle_validity"]; + } + if (self->_serial) + { + [dict setObject:self->_serial forKey:@"serial"]; + } + return dict; +} + +BOOL OTEscrowRecordMetadataReadFrom(__unsafe_unretained OTEscrowRecordMetadata *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* backupKeybagDigest */: + { + NSData *new_backupKeybagDigest = PBReaderReadData(reader); + self->_backupKeybagDigest = new_backupKeybagDigest; + } + break; + case 2 /* clientMetadata */: + { + OTEscrowRecordMetadataClientMetadata *new_clientMetadata = [[OTEscrowRecordMetadataClientMetadata alloc] init]; + self->_clientMetadata = new_clientMetadata; + PBDataReaderMark mark_clientMetadata; + BOOL markError = !PBReaderPlaceMark(reader, &mark_clientMetadata); + if (markError) + { + return NO; + } + BOOL inError = !OTEscrowRecordMetadataClientMetadataReadFrom(new_clientMetadata, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_clientMetadata); + } + break; + case 3 /* secureBackupUsesMultipleIcscs */: + { + self->_has.secureBackupUsesMultipleIcscs = YES; + self->_secureBackupUsesMultipleIcscs = PBReaderReadUint64(reader); + } + break; + case 4 /* bottleId */: + { + NSString *new_bottleId = PBReaderReadString(reader); + self->_bottleId = new_bottleId; + } + break; + case 5 /* secureBackupTimestamp */: + { + self->_has.secureBackupTimestamp = YES; + self->_secureBackupTimestamp = PBReaderReadUint64(reader); + } + break; + case 6 /* escrowedSpki */: + { + NSData *new_escrowedSpki = PBReaderReadData(reader); + self->_escrowedSpki = new_escrowedSpki; + } + break; + case 7 /* peerInfo */: + { + NSData *new_peerInfo = PBReaderReadData(reader); + self->_peerInfo = new_peerInfo; + } + break; + case 8 /* bottleValidity */: + { + NSString *new_bottleValidity = PBReaderReadString(reader); + self->_bottleValidity = new_bottleValidity; + } + break; + case 9 /* serial */: + { + NSString *new_serial = PBReaderReadString(reader); + self->_serial = new_serial; + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTEscrowRecordMetadataReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* backupKeybagDigest */ + { + if (self->_backupKeybagDigest) + { + PBDataWriterWriteDataField(writer, self->_backupKeybagDigest, 1); + } + } + /* clientMetadata */ + { + if (self->_clientMetadata != nil) + { + PBDataWriterWriteSubmessage(writer, self->_clientMetadata, 2); + } + } + /* secureBackupUsesMultipleIcscs */ + { + if (self->_has.secureBackupUsesMultipleIcscs) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupUsesMultipleIcscs, 3); + } + } + /* bottleId */ + { + if (self->_bottleId) + { + PBDataWriterWriteStringField(writer, self->_bottleId, 4); + } + } + /* secureBackupTimestamp */ + { + if (self->_has.secureBackupTimestamp) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupTimestamp, 5); + } + } + /* escrowedSpki */ + { + if (self->_escrowedSpki) + { + PBDataWriterWriteDataField(writer, self->_escrowedSpki, 6); + } + } + /* peerInfo */ + { + if (self->_peerInfo) + { + PBDataWriterWriteDataField(writer, self->_peerInfo, 7); + } + } + /* bottleValidity */ + { + if (self->_bottleValidity) + { + PBDataWriterWriteStringField(writer, self->_bottleValidity, 8); + } + } + /* serial */ + { + if (self->_serial) + { + PBDataWriterWriteStringField(writer, self->_serial, 9); + } + } +} + +- (void)copyTo:(OTEscrowRecordMetadata *)other +{ + if (_backupKeybagDigest) + { + other.backupKeybagDigest = _backupKeybagDigest; + } + if (_clientMetadata) + { + other.clientMetadata = _clientMetadata; + } + if (self->_has.secureBackupUsesMultipleIcscs) + { + other->_secureBackupUsesMultipleIcscs = _secureBackupUsesMultipleIcscs; + other->_has.secureBackupUsesMultipleIcscs = YES; + } + if (_bottleId) + { + other.bottleId = _bottleId; + } + if (self->_has.secureBackupTimestamp) + { + other->_secureBackupTimestamp = _secureBackupTimestamp; + other->_has.secureBackupTimestamp = YES; + } + if (_escrowedSpki) + { + other.escrowedSpki = _escrowedSpki; + } + if (_peerInfo) + { + other.peerInfo = _peerInfo; + } + if (_bottleValidity) + { + other.bottleValidity = _bottleValidity; + } + if (_serial) + { + other.serial = _serial; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTEscrowRecordMetadata *copy = [[[self class] allocWithZone:zone] init]; + copy->_backupKeybagDigest = [_backupKeybagDigest copyWithZone:zone]; + copy->_clientMetadata = [_clientMetadata copyWithZone:zone]; + if (self->_has.secureBackupUsesMultipleIcscs) + { + copy->_secureBackupUsesMultipleIcscs = _secureBackupUsesMultipleIcscs; + copy->_has.secureBackupUsesMultipleIcscs = YES; + } + copy->_bottleId = [_bottleId copyWithZone:zone]; + if (self->_has.secureBackupTimestamp) + { + copy->_secureBackupTimestamp = _secureBackupTimestamp; + copy->_has.secureBackupTimestamp = YES; + } + copy->_escrowedSpki = [_escrowedSpki copyWithZone:zone]; + copy->_peerInfo = [_peerInfo copyWithZone:zone]; + copy->_bottleValidity = [_bottleValidity copyWithZone:zone]; + copy->_serial = [_serial copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTEscrowRecordMetadata *other = (OTEscrowRecordMetadata *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_backupKeybagDigest && !other->_backupKeybagDigest) || [self->_backupKeybagDigest isEqual:other->_backupKeybagDigest]) + && + ((!self->_clientMetadata && !other->_clientMetadata) || [self->_clientMetadata isEqual:other->_clientMetadata]) + && + ((self->_has.secureBackupUsesMultipleIcscs && other->_has.secureBackupUsesMultipleIcscs && self->_secureBackupUsesMultipleIcscs == other->_secureBackupUsesMultipleIcscs) || (!self->_has.secureBackupUsesMultipleIcscs && !other->_has.secureBackupUsesMultipleIcscs)) + && + ((!self->_bottleId && !other->_bottleId) || [self->_bottleId isEqual:other->_bottleId]) + && + ((self->_has.secureBackupTimestamp && other->_has.secureBackupTimestamp && self->_secureBackupTimestamp == other->_secureBackupTimestamp) || (!self->_has.secureBackupTimestamp && !other->_has.secureBackupTimestamp)) + && + ((!self->_escrowedSpki && !other->_escrowedSpki) || [self->_escrowedSpki isEqual:other->_escrowedSpki]) + && + ((!self->_peerInfo && !other->_peerInfo) || [self->_peerInfo isEqual:other->_peerInfo]) + && + ((!self->_bottleValidity && !other->_bottleValidity) || [self->_bottleValidity isEqual:other->_bottleValidity]) + && + ((!self->_serial && !other->_serial) || [self->_serial isEqual:other->_serial]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_backupKeybagDigest hash] + ^ + [self->_clientMetadata hash] + ^ + (self->_has.secureBackupUsesMultipleIcscs ? PBHashInt((NSUInteger)self->_secureBackupUsesMultipleIcscs) : 0) + ^ + [self->_bottleId hash] + ^ + (self->_has.secureBackupTimestamp ? PBHashInt((NSUInteger)self->_secureBackupTimestamp) : 0) + ^ + [self->_escrowedSpki hash] + ^ + [self->_peerInfo hash] + ^ + [self->_bottleValidity hash] + ^ + [self->_serial hash] + ; +} + +- (void)mergeFrom:(OTEscrowRecordMetadata *)other +{ + if (other->_backupKeybagDigest) + { + [self setBackupKeybagDigest:other->_backupKeybagDigest]; + } + if (self->_clientMetadata && other->_clientMetadata) + { + [self->_clientMetadata mergeFrom:other->_clientMetadata]; + } + else if (!self->_clientMetadata && other->_clientMetadata) + { + [self setClientMetadata:other->_clientMetadata]; + } + if (other->_has.secureBackupUsesMultipleIcscs) + { + self->_secureBackupUsesMultipleIcscs = other->_secureBackupUsesMultipleIcscs; + self->_has.secureBackupUsesMultipleIcscs = YES; + } + if (other->_bottleId) + { + [self setBottleId:other->_bottleId]; + } + if (other->_has.secureBackupTimestamp) + { + self->_secureBackupTimestamp = other->_secureBackupTimestamp; + self->_has.secureBackupTimestamp = YES; + } + if (other->_escrowedSpki) + { + [self setEscrowedSpki:other->_escrowedSpki]; + } + if (other->_peerInfo) + { + [self setPeerInfo:other->_peerInfo]; + } + if (other->_bottleValidity) + { + [self setBottleValidity:other->_bottleValidity]; + } + if (other->_serial) + { + [self setSerial:other->_serial]; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h b/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h new file mode 100644 index 00000000..6b913b4b --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h @@ -0,0 +1,86 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import +#import + +#ifdef __cplusplus +#define OTESCROWRECORDMETADATACLIENTMETADATA_FUNCTION extern "C" +#else +#define OTESCROWRECORDMETADATACLIENTMETADATA_FUNCTION extern +#endif + +@interface OTEscrowRecordMetadataClientMetadata : PBCodable +{ + uint64_t _devicePlatform; + uint64_t _secureBackupMetadataTimestamp; + uint64_t _secureBackupNumericPassphraseLength; + uint64_t _secureBackupUsesComplexPassphrase; + uint64_t _secureBackupUsesNumericPassphrase; + NSString *_deviceColor; + NSString *_deviceEnclosureColor; + NSString *_deviceMid; + NSString *_deviceModel; + NSString *_deviceModelClass; + NSString *_deviceModelVersion; + NSString *_deviceName; + struct { + int devicePlatform:1; + int secureBackupMetadataTimestamp:1; + int secureBackupNumericPassphraseLength:1; + int secureBackupUsesComplexPassphrase:1; + int secureBackupUsesNumericPassphrase:1; + } _has; +} + + +@property (nonatomic) BOOL hasSecureBackupMetadataTimestamp; +@property (nonatomic) uint64_t secureBackupMetadataTimestamp; + +@property (nonatomic) BOOL hasSecureBackupNumericPassphraseLength; +@property (nonatomic) uint64_t secureBackupNumericPassphraseLength; + +@property (nonatomic) BOOL hasSecureBackupUsesComplexPassphrase; +@property (nonatomic) uint64_t secureBackupUsesComplexPassphrase; + +@property (nonatomic) BOOL hasSecureBackupUsesNumericPassphrase; +@property (nonatomic) uint64_t secureBackupUsesNumericPassphrase; + +@property (nonatomic, readonly) BOOL hasDeviceColor; +@property (nonatomic, retain) NSString *deviceColor; + +@property (nonatomic, readonly) BOOL hasDeviceEnclosureColor; +@property (nonatomic, retain) NSString *deviceEnclosureColor; + +@property (nonatomic, readonly) BOOL hasDeviceMid; +@property (nonatomic, retain) NSString *deviceMid; + +@property (nonatomic, readonly) BOOL hasDeviceModel; +@property (nonatomic, retain) NSString *deviceModel; + +@property (nonatomic, readonly) BOOL hasDeviceModelClass; +@property (nonatomic, retain) NSString *deviceModelClass; + +@property (nonatomic, readonly) BOOL hasDeviceModelVersion; +@property (nonatomic, retain) NSString *deviceModelVersion; + +@property (nonatomic, readonly) BOOL hasDeviceName; +@property (nonatomic, retain) NSString *deviceName; + +@property (nonatomic) BOOL hasDevicePlatform; +@property (nonatomic) uint64_t devicePlatform; + +// Performs a shallow copy into other +- (void)copyTo:(OTEscrowRecordMetadataClientMetadata *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTEscrowRecordMetadataClientMetadata *)other; + +OTESCROWRECORDMETADATACLIENTMETADATA_FUNCTION BOOL OTEscrowRecordMetadataClientMetadataReadFrom(__unsafe_unretained OTEscrowRecordMetadataClientMetadata *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.m b/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.m new file mode 100644 index 00000000..6b27339d --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.m @@ -0,0 +1,584 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import "OTEscrowRecordMetadataClientMetadata.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTEscrowRecordMetadataClientMetadata + +@synthesize secureBackupMetadataTimestamp = _secureBackupMetadataTimestamp; +- (void)setSecureBackupMetadataTimestamp:(uint64_t)v +{ + _has.secureBackupMetadataTimestamp = YES; + _secureBackupMetadataTimestamp = v; +} +- (void)setHasSecureBackupMetadataTimestamp:(BOOL)f +{ + _has.secureBackupMetadataTimestamp = f; +} +- (BOOL)hasSecureBackupMetadataTimestamp +{ + return _has.secureBackupMetadataTimestamp != 0; +} +@synthesize secureBackupNumericPassphraseLength = _secureBackupNumericPassphraseLength; +- (void)setSecureBackupNumericPassphraseLength:(uint64_t)v +{ + _has.secureBackupNumericPassphraseLength = YES; + _secureBackupNumericPassphraseLength = v; +} +- (void)setHasSecureBackupNumericPassphraseLength:(BOOL)f +{ + _has.secureBackupNumericPassphraseLength = f; +} +- (BOOL)hasSecureBackupNumericPassphraseLength +{ + return _has.secureBackupNumericPassphraseLength != 0; +} +@synthesize secureBackupUsesComplexPassphrase = _secureBackupUsesComplexPassphrase; +- (void)setSecureBackupUsesComplexPassphrase:(uint64_t)v +{ + _has.secureBackupUsesComplexPassphrase = YES; + _secureBackupUsesComplexPassphrase = v; +} +- (void)setHasSecureBackupUsesComplexPassphrase:(BOOL)f +{ + _has.secureBackupUsesComplexPassphrase = f; +} +- (BOOL)hasSecureBackupUsesComplexPassphrase +{ + return _has.secureBackupUsesComplexPassphrase != 0; +} +@synthesize secureBackupUsesNumericPassphrase = _secureBackupUsesNumericPassphrase; +- (void)setSecureBackupUsesNumericPassphrase:(uint64_t)v +{ + _has.secureBackupUsesNumericPassphrase = YES; + _secureBackupUsesNumericPassphrase = v; +} +- (void)setHasSecureBackupUsesNumericPassphrase:(BOOL)f +{ + _has.secureBackupUsesNumericPassphrase = f; +} +- (BOOL)hasSecureBackupUsesNumericPassphrase +{ + return _has.secureBackupUsesNumericPassphrase != 0; +} +- (BOOL)hasDeviceColor +{ + return _deviceColor != nil; +} +@synthesize deviceColor = _deviceColor; +- (BOOL)hasDeviceEnclosureColor +{ + return _deviceEnclosureColor != nil; +} +@synthesize deviceEnclosureColor = _deviceEnclosureColor; +- (BOOL)hasDeviceMid +{ + return _deviceMid != nil; +} +@synthesize deviceMid = _deviceMid; +- (BOOL)hasDeviceModel +{ + return _deviceModel != nil; +} +@synthesize deviceModel = _deviceModel; +- (BOOL)hasDeviceModelClass +{ + return _deviceModelClass != nil; +} +@synthesize deviceModelClass = _deviceModelClass; +- (BOOL)hasDeviceModelVersion +{ + return _deviceModelVersion != nil; +} +@synthesize deviceModelVersion = _deviceModelVersion; +- (BOOL)hasDeviceName +{ + return _deviceName != nil; +} +@synthesize deviceName = _deviceName; +@synthesize devicePlatform = _devicePlatform; +- (void)setDevicePlatform:(uint64_t)v +{ + _has.devicePlatform = YES; + _devicePlatform = v; +} +- (void)setHasDevicePlatform:(BOOL)f +{ + _has.devicePlatform = f; +} +- (BOOL)hasDevicePlatform +{ + return _has.devicePlatform != 0; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.secureBackupMetadataTimestamp) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupMetadataTimestamp] forKey:@"secure_backup_metadata_timestamp"]; + } + if (self->_has.secureBackupNumericPassphraseLength) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupNumericPassphraseLength] forKey:@"secure_backup_numeric_passphrase_length"]; + } + if (self->_has.secureBackupUsesComplexPassphrase) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupUsesComplexPassphrase] forKey:@"secure_backup_uses_complex_passphrase"]; + } + if (self->_has.secureBackupUsesNumericPassphrase) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupUsesNumericPassphrase] forKey:@"secure_backup_uses_numeric_passphrase"]; + } + if (self->_deviceColor) + { + [dict setObject:self->_deviceColor forKey:@"device_color"]; + } + if (self->_deviceEnclosureColor) + { + [dict setObject:self->_deviceEnclosureColor forKey:@"device_enclosure_color"]; + } + if (self->_deviceMid) + { + [dict setObject:self->_deviceMid forKey:@"device_mid"]; + } + if (self->_deviceModel) + { + [dict setObject:self->_deviceModel forKey:@"device_model"]; + } + if (self->_deviceModelClass) + { + [dict setObject:self->_deviceModelClass forKey:@"device_model_class"]; + } + if (self->_deviceModelVersion) + { + [dict setObject:self->_deviceModelVersion forKey:@"device_model_version"]; + } + if (self->_deviceName) + { + [dict setObject:self->_deviceName forKey:@"device_name"]; + } + if (self->_has.devicePlatform) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_devicePlatform] forKey:@"device_platform"]; + } + return dict; +} + +BOOL OTEscrowRecordMetadataClientMetadataReadFrom(__unsafe_unretained OTEscrowRecordMetadataClientMetadata *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* secureBackupMetadataTimestamp */: + { + self->_has.secureBackupMetadataTimestamp = YES; + self->_secureBackupMetadataTimestamp = PBReaderReadUint64(reader); + } + break; + case 2 /* secureBackupNumericPassphraseLength */: + { + self->_has.secureBackupNumericPassphraseLength = YES; + self->_secureBackupNumericPassphraseLength = PBReaderReadUint64(reader); + } + break; + case 3 /* secureBackupUsesComplexPassphrase */: + { + self->_has.secureBackupUsesComplexPassphrase = YES; + self->_secureBackupUsesComplexPassphrase = PBReaderReadUint64(reader); + } + break; + case 4 /* secureBackupUsesNumericPassphrase */: + { + self->_has.secureBackupUsesNumericPassphrase = YES; + self->_secureBackupUsesNumericPassphrase = PBReaderReadUint64(reader); + } + break; + case 5 /* deviceColor */: + { + NSString *new_deviceColor = PBReaderReadString(reader); + self->_deviceColor = new_deviceColor; + } + break; + case 6 /* deviceEnclosureColor */: + { + NSString *new_deviceEnclosureColor = PBReaderReadString(reader); + self->_deviceEnclosureColor = new_deviceEnclosureColor; + } + break; + case 7 /* deviceMid */: + { + NSString *new_deviceMid = PBReaderReadString(reader); + self->_deviceMid = new_deviceMid; + } + break; + case 8 /* deviceModel */: + { + NSString *new_deviceModel = PBReaderReadString(reader); + self->_deviceModel = new_deviceModel; + } + break; + case 9 /* deviceModelClass */: + { + NSString *new_deviceModelClass = PBReaderReadString(reader); + self->_deviceModelClass = new_deviceModelClass; + } + break; + case 10 /* deviceModelVersion */: + { + NSString *new_deviceModelVersion = PBReaderReadString(reader); + self->_deviceModelVersion = new_deviceModelVersion; + } + break; + case 11 /* deviceName */: + { + NSString *new_deviceName = PBReaderReadString(reader); + self->_deviceName = new_deviceName; + } + break; + case 12 /* devicePlatform */: + { + self->_has.devicePlatform = YES; + self->_devicePlatform = PBReaderReadUint64(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTEscrowRecordMetadataClientMetadataReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* secureBackupMetadataTimestamp */ + { + if (self->_has.secureBackupMetadataTimestamp) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupMetadataTimestamp, 1); + } + } + /* secureBackupNumericPassphraseLength */ + { + if (self->_has.secureBackupNumericPassphraseLength) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupNumericPassphraseLength, 2); + } + } + /* secureBackupUsesComplexPassphrase */ + { + if (self->_has.secureBackupUsesComplexPassphrase) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupUsesComplexPassphrase, 3); + } + } + /* secureBackupUsesNumericPassphrase */ + { + if (self->_has.secureBackupUsesNumericPassphrase) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupUsesNumericPassphrase, 4); + } + } + /* deviceColor */ + { + if (self->_deviceColor) + { + PBDataWriterWriteStringField(writer, self->_deviceColor, 5); + } + } + /* deviceEnclosureColor */ + { + if (self->_deviceEnclosureColor) + { + PBDataWriterWriteStringField(writer, self->_deviceEnclosureColor, 6); + } + } + /* deviceMid */ + { + if (self->_deviceMid) + { + PBDataWriterWriteStringField(writer, self->_deviceMid, 7); + } + } + /* deviceModel */ + { + if (self->_deviceModel) + { + PBDataWriterWriteStringField(writer, self->_deviceModel, 8); + } + } + /* deviceModelClass */ + { + if (self->_deviceModelClass) + { + PBDataWriterWriteStringField(writer, self->_deviceModelClass, 9); + } + } + /* deviceModelVersion */ + { + if (self->_deviceModelVersion) + { + PBDataWriterWriteStringField(writer, self->_deviceModelVersion, 10); + } + } + /* deviceName */ + { + if (self->_deviceName) + { + PBDataWriterWriteStringField(writer, self->_deviceName, 11); + } + } + /* devicePlatform */ + { + if (self->_has.devicePlatform) + { + PBDataWriterWriteUint64Field(writer, self->_devicePlatform, 12); + } + } +} + +- (void)copyTo:(OTEscrowRecordMetadataClientMetadata *)other +{ + if (self->_has.secureBackupMetadataTimestamp) + { + other->_secureBackupMetadataTimestamp = _secureBackupMetadataTimestamp; + other->_has.secureBackupMetadataTimestamp = YES; + } + if (self->_has.secureBackupNumericPassphraseLength) + { + other->_secureBackupNumericPassphraseLength = _secureBackupNumericPassphraseLength; + other->_has.secureBackupNumericPassphraseLength = YES; + } + if (self->_has.secureBackupUsesComplexPassphrase) + { + other->_secureBackupUsesComplexPassphrase = _secureBackupUsesComplexPassphrase; + other->_has.secureBackupUsesComplexPassphrase = YES; + } + if (self->_has.secureBackupUsesNumericPassphrase) + { + other->_secureBackupUsesNumericPassphrase = _secureBackupUsesNumericPassphrase; + other->_has.secureBackupUsesNumericPassphrase = YES; + } + if (_deviceColor) + { + other.deviceColor = _deviceColor; + } + if (_deviceEnclosureColor) + { + other.deviceEnclosureColor = _deviceEnclosureColor; + } + if (_deviceMid) + { + other.deviceMid = _deviceMid; + } + if (_deviceModel) + { + other.deviceModel = _deviceModel; + } + if (_deviceModelClass) + { + other.deviceModelClass = _deviceModelClass; + } + if (_deviceModelVersion) + { + other.deviceModelVersion = _deviceModelVersion; + } + if (_deviceName) + { + other.deviceName = _deviceName; + } + if (self->_has.devicePlatform) + { + other->_devicePlatform = _devicePlatform; + other->_has.devicePlatform = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTEscrowRecordMetadataClientMetadata *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.secureBackupMetadataTimestamp) + { + copy->_secureBackupMetadataTimestamp = _secureBackupMetadataTimestamp; + copy->_has.secureBackupMetadataTimestamp = YES; + } + if (self->_has.secureBackupNumericPassphraseLength) + { + copy->_secureBackupNumericPassphraseLength = _secureBackupNumericPassphraseLength; + copy->_has.secureBackupNumericPassphraseLength = YES; + } + if (self->_has.secureBackupUsesComplexPassphrase) + { + copy->_secureBackupUsesComplexPassphrase = _secureBackupUsesComplexPassphrase; + copy->_has.secureBackupUsesComplexPassphrase = YES; + } + if (self->_has.secureBackupUsesNumericPassphrase) + { + copy->_secureBackupUsesNumericPassphrase = _secureBackupUsesNumericPassphrase; + copy->_has.secureBackupUsesNumericPassphrase = YES; + } + copy->_deviceColor = [_deviceColor copyWithZone:zone]; + copy->_deviceEnclosureColor = [_deviceEnclosureColor copyWithZone:zone]; + copy->_deviceMid = [_deviceMid copyWithZone:zone]; + copy->_deviceModel = [_deviceModel copyWithZone:zone]; + copy->_deviceModelClass = [_deviceModelClass copyWithZone:zone]; + copy->_deviceModelVersion = [_deviceModelVersion copyWithZone:zone]; + copy->_deviceName = [_deviceName copyWithZone:zone]; + if (self->_has.devicePlatform) + { + copy->_devicePlatform = _devicePlatform; + copy->_has.devicePlatform = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTEscrowRecordMetadataClientMetadata *other = (OTEscrowRecordMetadataClientMetadata *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.secureBackupMetadataTimestamp && other->_has.secureBackupMetadataTimestamp && self->_secureBackupMetadataTimestamp == other->_secureBackupMetadataTimestamp) || (!self->_has.secureBackupMetadataTimestamp && !other->_has.secureBackupMetadataTimestamp)) + && + ((self->_has.secureBackupNumericPassphraseLength && other->_has.secureBackupNumericPassphraseLength && self->_secureBackupNumericPassphraseLength == other->_secureBackupNumericPassphraseLength) || (!self->_has.secureBackupNumericPassphraseLength && !other->_has.secureBackupNumericPassphraseLength)) + && + ((self->_has.secureBackupUsesComplexPassphrase && other->_has.secureBackupUsesComplexPassphrase && self->_secureBackupUsesComplexPassphrase == other->_secureBackupUsesComplexPassphrase) || (!self->_has.secureBackupUsesComplexPassphrase && !other->_has.secureBackupUsesComplexPassphrase)) + && + ((self->_has.secureBackupUsesNumericPassphrase && other->_has.secureBackupUsesNumericPassphrase && self->_secureBackupUsesNumericPassphrase == other->_secureBackupUsesNumericPassphrase) || (!self->_has.secureBackupUsesNumericPassphrase && !other->_has.secureBackupUsesNumericPassphrase)) + && + ((!self->_deviceColor && !other->_deviceColor) || [self->_deviceColor isEqual:other->_deviceColor]) + && + ((!self->_deviceEnclosureColor && !other->_deviceEnclosureColor) || [self->_deviceEnclosureColor isEqual:other->_deviceEnclosureColor]) + && + ((!self->_deviceMid && !other->_deviceMid) || [self->_deviceMid isEqual:other->_deviceMid]) + && + ((!self->_deviceModel && !other->_deviceModel) || [self->_deviceModel isEqual:other->_deviceModel]) + && + ((!self->_deviceModelClass && !other->_deviceModelClass) || [self->_deviceModelClass isEqual:other->_deviceModelClass]) + && + ((!self->_deviceModelVersion && !other->_deviceModelVersion) || [self->_deviceModelVersion isEqual:other->_deviceModelVersion]) + && + ((!self->_deviceName && !other->_deviceName) || [self->_deviceName isEqual:other->_deviceName]) + && + ((self->_has.devicePlatform && other->_has.devicePlatform && self->_devicePlatform == other->_devicePlatform) || (!self->_has.devicePlatform && !other->_has.devicePlatform)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.secureBackupMetadataTimestamp ? PBHashInt((NSUInteger)self->_secureBackupMetadataTimestamp) : 0) + ^ + (self->_has.secureBackupNumericPassphraseLength ? PBHashInt((NSUInteger)self->_secureBackupNumericPassphraseLength) : 0) + ^ + (self->_has.secureBackupUsesComplexPassphrase ? PBHashInt((NSUInteger)self->_secureBackupUsesComplexPassphrase) : 0) + ^ + (self->_has.secureBackupUsesNumericPassphrase ? PBHashInt((NSUInteger)self->_secureBackupUsesNumericPassphrase) : 0) + ^ + [self->_deviceColor hash] + ^ + [self->_deviceEnclosureColor hash] + ^ + [self->_deviceMid hash] + ^ + [self->_deviceModel hash] + ^ + [self->_deviceModelClass hash] + ^ + [self->_deviceModelVersion hash] + ^ + [self->_deviceName hash] + ^ + (self->_has.devicePlatform ? PBHashInt((NSUInteger)self->_devicePlatform) : 0) + ; +} + +- (void)mergeFrom:(OTEscrowRecordMetadataClientMetadata *)other +{ + if (other->_has.secureBackupMetadataTimestamp) + { + self->_secureBackupMetadataTimestamp = other->_secureBackupMetadataTimestamp; + self->_has.secureBackupMetadataTimestamp = YES; + } + if (other->_has.secureBackupNumericPassphraseLength) + { + self->_secureBackupNumericPassphraseLength = other->_secureBackupNumericPassphraseLength; + self->_has.secureBackupNumericPassphraseLength = YES; + } + if (other->_has.secureBackupUsesComplexPassphrase) + { + self->_secureBackupUsesComplexPassphrase = other->_secureBackupUsesComplexPassphrase; + self->_has.secureBackupUsesComplexPassphrase = YES; + } + if (other->_has.secureBackupUsesNumericPassphrase) + { + self->_secureBackupUsesNumericPassphrase = other->_secureBackupUsesNumericPassphrase; + self->_has.secureBackupUsesNumericPassphrase = YES; + } + if (other->_deviceColor) + { + [self setDeviceColor:other->_deviceColor]; + } + if (other->_deviceEnclosureColor) + { + [self setDeviceEnclosureColor:other->_deviceEnclosureColor]; + } + if (other->_deviceMid) + { + [self setDeviceMid:other->_deviceMid]; + } + if (other->_deviceModel) + { + [self setDeviceModel:other->_deviceModel]; + } + if (other->_deviceModelClass) + { + [self setDeviceModelClass:other->_deviceModelClass]; + } + if (other->_deviceModelVersion) + { + [self setDeviceModelVersion:other->_deviceModelVersion]; + } + if (other->_deviceName) + { + [self setDeviceName:other->_deviceName]; + } + if (other->_has.devicePlatform) + { + self->_devicePlatform = other->_devicePlatform; + self->_has.devicePlatform = YES; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTGlobalEnums.h b/keychain/ot/proto/generated_source/OTGlobalEnums.h new file mode 100644 index 00000000..b491935d --- /dev/null +++ b/keychain/ot/proto/generated_source/OTGlobalEnums.h @@ -0,0 +1,43 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#include +#ifdef __OBJC__ +#include +#endif + +#ifndef NS_ENUM +#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum)) +#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +#else +#define NS_ENUM(_type, _name) _type _name; enum +#endif +#endif // !defined(NS_ENUM) + +typedef NS_ENUM(int32_t, OTSupportType) { + OTSupportType_unknown = 0, + OTSupportType_supported = 1, + OTSupportType_not_supported = 2, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTSupportTypeAsString(OTSupportType value) +{ + switch (value) + { + case OTSupportType_unknown: return @"unknown"; + case OTSupportType_supported: return @"supported"; + case OTSupportType_not_supported: return @"not_supported"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTSupportType StringAsOTSupportType(NSString *value) +{ + if ([value isEqualToString:@"unknown"]) return OTSupportType_unknown; + if ([value isEqualToString:@"supported"]) return OTSupportType_supported; + if ([value isEqualToString:@"not_supported"]) return OTSupportType_not_supported; + return OTSupportType_unknown; +} +#endif /* __OBJC__ */ diff --git a/keychain/ot/proto/generated_source/OTICDPRecordContext.h b/keychain/ot/proto/generated_source/OTICDPRecordContext.h new file mode 100644 index 00000000..08fac608 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTICDPRecordContext.h @@ -0,0 +1,42 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import +#import + +@class OTCDPRecoveryInformation; +@class OTEscrowAuthenticationInformation; + +#ifdef __cplusplus +#define OTICDPRECORDCONTEXT_FUNCTION extern "C" +#else +#define OTICDPRECORDCONTEXT_FUNCTION extern +#endif + +@interface OTICDPRecordContext : PBCodable +{ + OTEscrowAuthenticationInformation *_authInfo; + OTCDPRecoveryInformation *_cdpInfo; +} + + +@property (nonatomic, readonly) BOOL hasCdpInfo; +@property (nonatomic, retain) OTCDPRecoveryInformation *cdpInfo; + +@property (nonatomic, readonly) BOOL hasAuthInfo; +@property (nonatomic, retain) OTEscrowAuthenticationInformation *authInfo; + +// Performs a shallow copy into other +- (void)copyTo:(OTICDPRecordContext *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTICDPRecordContext *)other; + +OTICDPRECORDCONTEXT_FUNCTION BOOL OTICDPRecordContextReadFrom(__unsafe_unretained OTICDPRecordContext *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTICDPRecordContext.m b/keychain/ot/proto/generated_source/OTICDPRecordContext.m new file mode 100644 index 00000000..1d74b152 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTICDPRecordContext.m @@ -0,0 +1,194 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import "OTICDPRecordContext.h" +#import +#import +#import + +#import "OTCDPRecoveryInformation.h" +#import "OTEscrowAuthenticationInformation.h" + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTICDPRecordContext + +- (BOOL)hasCdpInfo +{ + return _cdpInfo != nil; +} +@synthesize cdpInfo = _cdpInfo; +- (BOOL)hasAuthInfo +{ + return _authInfo != nil; +} +@synthesize authInfo = _authInfo; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_cdpInfo) + { + [dict setObject:[_cdpInfo dictionaryRepresentation] forKey:@"cdpInfo"]; + } + if (self->_authInfo) + { + [dict setObject:[_authInfo dictionaryRepresentation] forKey:@"authInfo"]; + } + return dict; +} + +BOOL OTICDPRecordContextReadFrom(__unsafe_unretained OTICDPRecordContext *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* cdpInfo */: + { + OTCDPRecoveryInformation *new_cdpInfo = [[OTCDPRecoveryInformation alloc] init]; + self->_cdpInfo = new_cdpInfo; + PBDataReaderMark mark_cdpInfo; + BOOL markError = !PBReaderPlaceMark(reader, &mark_cdpInfo); + if (markError) + { + return NO; + } + BOOL inError = !OTCDPRecoveryInformationReadFrom(new_cdpInfo, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_cdpInfo); + } + break; + case 2 /* authInfo */: + { + OTEscrowAuthenticationInformation *new_authInfo = [[OTEscrowAuthenticationInformation alloc] init]; + self->_authInfo = new_authInfo; + PBDataReaderMark mark_authInfo; + BOOL markError = !PBReaderPlaceMark(reader, &mark_authInfo); + if (markError) + { + return NO; + } + BOOL inError = !OTEscrowAuthenticationInformationReadFrom(new_authInfo, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_authInfo); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTICDPRecordContextReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* cdpInfo */ + { + if (self->_cdpInfo != nil) + { + PBDataWriterWriteSubmessage(writer, self->_cdpInfo, 1); + } + } + /* authInfo */ + { + if (self->_authInfo != nil) + { + PBDataWriterWriteSubmessage(writer, self->_authInfo, 2); + } + } +} + +- (void)copyTo:(OTICDPRecordContext *)other +{ + if (_cdpInfo) + { + other.cdpInfo = _cdpInfo; + } + if (_authInfo) + { + other.authInfo = _authInfo; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTICDPRecordContext *copy = [[[self class] allocWithZone:zone] init]; + copy->_cdpInfo = [_cdpInfo copyWithZone:zone]; + copy->_authInfo = [_authInfo copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTICDPRecordContext *other = (OTICDPRecordContext *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_cdpInfo && !other->_cdpInfo) || [self->_cdpInfo isEqual:other->_cdpInfo]) + && + ((!self->_authInfo && !other->_authInfo) || [self->_authInfo isEqual:other->_authInfo]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_cdpInfo hash] + ^ + [self->_authInfo hash] + ; +} + +- (void)mergeFrom:(OTICDPRecordContext *)other +{ + if (self->_cdpInfo && other->_cdpInfo) + { + [self->_cdpInfo mergeFrom:other->_cdpInfo]; + } + else if (!self->_cdpInfo && other->_cdpInfo) + { + [self setCdpInfo:other->_cdpInfo]; + } + if (self->_authInfo && other->_authInfo) + { + [self->_authInfo mergeFrom:other->_authInfo]; + } + else if (!self->_authInfo && other->_authInfo) + { + [self setAuthInfo:other->_authInfo]; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.h b/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.h new file mode 100644 index 00000000..5576e3f8 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.h @@ -0,0 +1,42 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import +#import + +@class OTCDPRecoveryInformation; +@class OTEscrowAuthenticationInformation; + +#ifdef __cplusplus +#define OTICDPRECORDSILENTCONTEXT_FUNCTION extern "C" +#else +#define OTICDPRECORDSILENTCONTEXT_FUNCTION extern +#endif + +@interface OTICDPRecordSilentContext : PBCodable +{ + OTEscrowAuthenticationInformation *_authInfo; + OTCDPRecoveryInformation *_cdpInfo; +} + + +@property (nonatomic, readonly) BOOL hasCdpInfo; +@property (nonatomic, retain) OTCDPRecoveryInformation *cdpInfo; + +@property (nonatomic, readonly) BOOL hasAuthInfo; +@property (nonatomic, retain) OTEscrowAuthenticationInformation *authInfo; + +// Performs a shallow copy into other +- (void)copyTo:(OTICDPRecordSilentContext *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTICDPRecordSilentContext *)other; + +OTICDPRECORDSILENTCONTEXT_FUNCTION BOOL OTICDPRecordSilentContextReadFrom(__unsafe_unretained OTICDPRecordSilentContext *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.m b/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.m new file mode 100644 index 00000000..4d8e4f66 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.m @@ -0,0 +1,194 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import "OTICDPRecordSilentContext.h" +#import +#import +#import + +#import "OTCDPRecoveryInformation.h" +#import "OTEscrowAuthenticationInformation.h" + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTICDPRecordSilentContext + +- (BOOL)hasCdpInfo +{ + return _cdpInfo != nil; +} +@synthesize cdpInfo = _cdpInfo; +- (BOOL)hasAuthInfo +{ + return _authInfo != nil; +} +@synthesize authInfo = _authInfo; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_cdpInfo) + { + [dict setObject:[_cdpInfo dictionaryRepresentation] forKey:@"cdpInfo"]; + } + if (self->_authInfo) + { + [dict setObject:[_authInfo dictionaryRepresentation] forKey:@"authInfo"]; + } + return dict; +} + +BOOL OTICDPRecordSilentContextReadFrom(__unsafe_unretained OTICDPRecordSilentContext *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* cdpInfo */: + { + OTCDPRecoveryInformation *new_cdpInfo = [[OTCDPRecoveryInformation alloc] init]; + self->_cdpInfo = new_cdpInfo; + PBDataReaderMark mark_cdpInfo; + BOOL markError = !PBReaderPlaceMark(reader, &mark_cdpInfo); + if (markError) + { + return NO; + } + BOOL inError = !OTCDPRecoveryInformationReadFrom(new_cdpInfo, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_cdpInfo); + } + break; + case 2 /* authInfo */: + { + OTEscrowAuthenticationInformation *new_authInfo = [[OTEscrowAuthenticationInformation alloc] init]; + self->_authInfo = new_authInfo; + PBDataReaderMark mark_authInfo; + BOOL markError = !PBReaderPlaceMark(reader, &mark_authInfo); + if (markError) + { + return NO; + } + BOOL inError = !OTEscrowAuthenticationInformationReadFrom(new_authInfo, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_authInfo); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTICDPRecordSilentContextReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* cdpInfo */ + { + if (self->_cdpInfo != nil) + { + PBDataWriterWriteSubmessage(writer, self->_cdpInfo, 1); + } + } + /* authInfo */ + { + if (self->_authInfo != nil) + { + PBDataWriterWriteSubmessage(writer, self->_authInfo, 2); + } + } +} + +- (void)copyTo:(OTICDPRecordSilentContext *)other +{ + if (_cdpInfo) + { + other.cdpInfo = _cdpInfo; + } + if (_authInfo) + { + other.authInfo = _authInfo; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTICDPRecordSilentContext *copy = [[[self class] allocWithZone:zone] init]; + copy->_cdpInfo = [_cdpInfo copyWithZone:zone]; + copy->_authInfo = [_authInfo copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTICDPRecordSilentContext *other = (OTICDPRecordSilentContext *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_cdpInfo && !other->_cdpInfo) || [self->_cdpInfo isEqual:other->_cdpInfo]) + && + ((!self->_authInfo && !other->_authInfo) || [self->_authInfo isEqual:other->_authInfo]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_cdpInfo hash] + ^ + [self->_authInfo hash] + ; +} + +- (void)mergeFrom:(OTICDPRecordSilentContext *)other +{ + if (self->_cdpInfo && other->_cdpInfo) + { + [self->_cdpInfo mergeFrom:other->_cdpInfo]; + } + else if (!self->_cdpInfo && other->_cdpInfo) + { + [self setCdpInfo:other->_cdpInfo]; + } + if (self->_authInfo && other->_authInfo) + { + [self->_authInfo mergeFrom:other->_authInfo]; + } + else if (!self->_authInfo && other->_authInfo) + { + [self setAuthInfo:other->_authInfo]; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTPairingMessage.h b/keychain/ot/proto/generated_source/OTPairingMessage.h index f2fad2f1..ba31f284 100644 --- a/keychain/ot/proto/generated_source/OTPairingMessage.h +++ b/keychain/ot/proto/generated_source/OTPairingMessage.h @@ -5,10 +5,11 @@ #import #import -@class OTSponsorToApplicantRound1M2; @class OTApplicantToSponsorRound2M1; +@class OTSponsorToApplicantRound1M2; @class OTSponsorToApplicantRound2M2; -@class OTSOSMessage; +@class OTSupportOctagonMessage; +@class OTSupportSOSMessage; #ifdef __cplusplus #define OTPAIRINGMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden"))) @@ -16,12 +17,17 @@ #define OTPAIRINGMESSAGE_FUNCTION extern __attribute__((visibility("hidden"))) #endif +/** + * Claimed for a field, but never used + * reserved 3; + */ __attribute__((visibility("hidden"))) @interface OTPairingMessage : PBCodable { OTSponsorToApplicantRound1M2 *_epoch; OTApplicantToSponsorRound2M1 *_prepare; - OTSOSMessage *_sosPairingMessage; + OTSupportOctagonMessage *_supportsOctagon; + OTSupportSOSMessage *_supportsSOS; OTSponsorToApplicantRound2M2 *_voucher; } @@ -35,8 +41,11 @@ __attribute__((visibility("hidden"))) @property (nonatomic, readonly) BOOL hasVoucher; @property (nonatomic, retain) OTSponsorToApplicantRound2M2 *voucher; -@property (nonatomic, readonly) BOOL hasSosPairingMessage; -@property (nonatomic, retain) OTSOSMessage *sosPairingMessage; +@property (nonatomic, readonly) BOOL hasSupportsOctagon; +@property (nonatomic, retain) OTSupportOctagonMessage *supportsOctagon; + +@property (nonatomic, readonly) BOOL hasSupportsSOS; +@property (nonatomic, retain) OTSupportSOSMessage *supportsSOS; // Performs a shallow copy into other - (void)copyTo:(OTPairingMessage *)other; diff --git a/keychain/ot/proto/generated_source/OTPairingMessage.m b/keychain/ot/proto/generated_source/OTPairingMessage.m index 3416a4f9..76cefe59 100644 --- a/keychain/ot/proto/generated_source/OTPairingMessage.m +++ b/keychain/ot/proto/generated_source/OTPairingMessage.m @@ -8,9 +8,10 @@ #import #import "OTApplicantToSponsorRound2M1.h" -#import "OTSOSMessage.h" #import "OTSponsorToApplicantRound1M2.h" #import "OTSponsorToApplicantRound2M2.h" +#import "OTSupportOctagonMessage.h" +#import "OTSupportSOSMessage.h" #if !__has_feature(objc_arc) # error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. @@ -33,11 +34,16 @@ return _voucher != nil; } @synthesize voucher = _voucher; -- (BOOL)hasSosPairingMessage +- (BOOL)hasSupportsOctagon { - return _sosPairingMessage != nil; + return _supportsOctagon != nil; } -@synthesize sosPairingMessage = _sosPairingMessage; +@synthesize supportsOctagon = _supportsOctagon; +- (BOOL)hasSupportsSOS +{ + return _supportsSOS != nil; +} +@synthesize supportsSOS = _supportsSOS; - (NSString *)description { @@ -59,9 +65,13 @@ { [dict setObject:[_voucher dictionaryRepresentation] forKey:@"voucher"]; } - if (self->_sosPairingMessage) + if (self->_supportsOctagon) { - [dict setObject:[_sosPairingMessage dictionaryRepresentation] forKey:@"sosPairingMessage"]; + [dict setObject:[_supportsOctagon dictionaryRepresentation] forKey:@"supportsOctagon"]; + } + if (self->_supportsSOS) + { + [dict setObject:[_supportsSOS dictionaryRepresentation] forKey:@"supportsSOS"]; } return dict; } @@ -136,22 +146,40 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa PBReaderRecallMark(reader, &mark_voucher); } break; - case 4 /* sosPairingMessage */: + case 5 /* supportsOctagon */: { - OTSOSMessage *new_sosPairingMessage = [[OTSOSMessage alloc] init]; - self->_sosPairingMessage = new_sosPairingMessage; - PBDataReaderMark mark_sosPairingMessage; - BOOL markError = !PBReaderPlaceMark(reader, &mark_sosPairingMessage); + OTSupportOctagonMessage *new_supportsOctagon = [[OTSupportOctagonMessage alloc] init]; + self->_supportsOctagon = new_supportsOctagon; + PBDataReaderMark mark_supportsOctagon; + BOOL markError = !PBReaderPlaceMark(reader, &mark_supportsOctagon); if (markError) { return NO; } - BOOL inError = !OTSOSMessageReadFrom(new_sosPairingMessage, reader); + BOOL inError = !OTSupportOctagonMessageReadFrom(new_supportsOctagon, reader); if (inError) { return NO; } - PBReaderRecallMark(reader, &mark_sosPairingMessage); + PBReaderRecallMark(reader, &mark_supportsOctagon); + } + break; + case 6 /* supportsSOS */: + { + OTSupportSOSMessage *new_supportsSOS = [[OTSupportSOSMessage alloc] init]; + self->_supportsSOS = new_supportsSOS; + PBDataReaderMark mark_supportsSOS; + BOOL markError = !PBReaderPlaceMark(reader, &mark_supportsSOS); + if (markError) + { + return NO; + } + BOOL inError = !OTSupportSOSMessageReadFrom(new_supportsSOS, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_supportsSOS); } break; default: @@ -190,11 +218,18 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa PBDataWriterWriteSubmessage(writer, self->_voucher, 3); } } - /* sosPairingMessage */ + /* supportsOctagon */ { - if (self->_sosPairingMessage != nil) + if (self->_supportsOctagon != nil) { - PBDataWriterWriteSubmessage(writer, self->_sosPairingMessage, 4); + PBDataWriterWriteSubmessage(writer, self->_supportsOctagon, 5); + } + } + /* supportsSOS */ + { + if (self->_supportsSOS != nil) + { + PBDataWriterWriteSubmessage(writer, self->_supportsSOS, 6); } } } @@ -213,9 +248,13 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa { other.voucher = _voucher; } - if (_sosPairingMessage) + if (_supportsOctagon) { - other.sosPairingMessage = _sosPairingMessage; + other.supportsOctagon = _supportsOctagon; + } + if (_supportsSOS) + { + other.supportsSOS = _supportsSOS; } } @@ -225,7 +264,8 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa copy->_epoch = [_epoch copyWithZone:zone]; copy->_prepare = [_prepare copyWithZone:zone]; copy->_voucher = [_voucher copyWithZone:zone]; - copy->_sosPairingMessage = [_sosPairingMessage copyWithZone:zone]; + copy->_supportsOctagon = [_supportsOctagon copyWithZone:zone]; + copy->_supportsSOS = [_supportsSOS copyWithZone:zone]; return copy; } @@ -240,7 +280,9 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa && ((!self->_voucher && !other->_voucher) || [self->_voucher isEqual:other->_voucher]) && - ((!self->_sosPairingMessage && !other->_sosPairingMessage) || [self->_sosPairingMessage isEqual:other->_sosPairingMessage]) + ((!self->_supportsOctagon && !other->_supportsOctagon) || [self->_supportsOctagon isEqual:other->_supportsOctagon]) + && + ((!self->_supportsSOS && !other->_supportsSOS) || [self->_supportsSOS isEqual:other->_supportsSOS]) ; } @@ -254,7 +296,9 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa ^ [self->_voucher hash] ^ - [self->_sosPairingMessage hash] + [self->_supportsOctagon hash] + ^ + [self->_supportsSOS hash] ; } @@ -284,13 +328,21 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa { [self setVoucher:other->_voucher]; } - if (self->_sosPairingMessage && other->_sosPairingMessage) + if (self->_supportsOctagon && other->_supportsOctagon) { - [self->_sosPairingMessage mergeFrom:other->_sosPairingMessage]; + [self->_supportsOctagon mergeFrom:other->_supportsOctagon]; } - else if (!self->_sosPairingMessage && other->_sosPairingMessage) + else if (!self->_supportsOctagon && other->_supportsOctagon) { - [self setSosPairingMessage:other->_sosPairingMessage]; + [self setSupportsOctagon:other->_supportsOctagon]; + } + if (self->_supportsSOS && other->_supportsSOS) + { + [self->_supportsSOS mergeFrom:other->_supportsSOS]; + } + else if (!self->_supportsSOS && other->_supportsSOS) + { + [self setSupportsSOS:other->_supportsSOS]; } } diff --git a/keychain/ot/proto/generated_source/OTSOSMessage.h b/keychain/ot/proto/generated_source/OTSOSMessage.h deleted file mode 100644 index e515077e..00000000 --- a/keychain/ot/proto/generated_source/OTSOSMessage.h +++ /dev/null @@ -1,48 +0,0 @@ -// This file was automatically generated by protocompiler -// DO NOT EDIT! -// Compiled from OTPairingMessage.proto - -#import -#import - -#ifdef __cplusplus -#define OTSOSMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden"))) -#else -#define OTSOSMESSAGE_FUNCTION extern __attribute__((visibility("hidden"))) -#endif - -__attribute__((visibility("hidden"))) -@interface OTSOSMessage : PBCodable -{ - NSData *_circleBlob; - NSData *_credential; - NSData *_initialSyncItems; - NSData *_peerInfo; -} - - -@property (nonatomic, readonly) BOOL hasCredential; -@property (nonatomic, retain) NSData *credential; - -@property (nonatomic, readonly) BOOL hasPeerInfo; -@property (nonatomic, retain) NSData *peerInfo; - -@property (nonatomic, readonly) BOOL hasCircleBlob; -@property (nonatomic, retain) NSData *circleBlob; - -@property (nonatomic, readonly) BOOL hasInitialSyncItems; -@property (nonatomic, retain) NSData *initialSyncItems; - -// Performs a shallow copy into other -- (void)copyTo:(OTSOSMessage *)other; - -// Performs a deep merge from other into self -// If set in other, singular values in self are replaced in self -// Singular composite values are recursively merged -// Repeated values from other are appended to repeated values in self -- (void)mergeFrom:(OTSOSMessage *)other; - -OTSOSMESSAGE_FUNCTION BOOL OTSOSMessageReadFrom(__unsafe_unretained OTSOSMessage *self, __unsafe_unretained PBDataReader *reader); - -@end - diff --git a/keychain/ot/proto/generated_source/OTSOSMessage.m b/keychain/ot/proto/generated_source/OTSOSMessage.m deleted file mode 100644 index e4a1f2a5..00000000 --- a/keychain/ot/proto/generated_source/OTSOSMessage.m +++ /dev/null @@ -1,229 +0,0 @@ -// This file was automatically generated by protocompiler -// DO NOT EDIT! -// Compiled from OTPairingMessage.proto - -#import "OTSOSMessage.h" -#import -#import -#import - -#if !__has_feature(objc_arc) -# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. -#endif - -@implementation OTSOSMessage - -- (BOOL)hasCredential -{ - return _credential != nil; -} -@synthesize credential = _credential; -- (BOOL)hasPeerInfo -{ - return _peerInfo != nil; -} -@synthesize peerInfo = _peerInfo; -- (BOOL)hasCircleBlob -{ - return _circleBlob != nil; -} -@synthesize circleBlob = _circleBlob; -- (BOOL)hasInitialSyncItems -{ - return _initialSyncItems != nil; -} -@synthesize initialSyncItems = _initialSyncItems; - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; -} - -- (NSDictionary *)dictionaryRepresentation -{ - NSMutableDictionary *dict = [NSMutableDictionary dictionary]; - if (self->_credential) - { - [dict setObject:self->_credential forKey:@"credential"]; - } - if (self->_peerInfo) - { - [dict setObject:self->_peerInfo forKey:@"peerInfo"]; - } - if (self->_circleBlob) - { - [dict setObject:self->_circleBlob forKey:@"circleBlob"]; - } - if (self->_initialSyncItems) - { - [dict setObject:self->_initialSyncItems forKey:@"initialSyncItems"]; - } - return dict; -} - -BOOL OTSOSMessageReadFrom(__unsafe_unretained OTSOSMessage *self, __unsafe_unretained PBDataReader *reader) { - while (PBReaderHasMoreData(reader)) { - uint32_t tag = 0; - uint8_t aType = 0; - - PBReaderReadTag32AndType(reader, &tag, &aType); - - if (PBReaderHasError(reader)) - break; - - if (aType == TYPE_END_GROUP) { - break; - } - - switch (tag) { - - case 1 /* credential */: - { - NSData *new_credential = PBReaderReadData(reader); - self->_credential = new_credential; - } - break; - case 2 /* peerInfo */: - { - NSData *new_peerInfo = PBReaderReadData(reader); - self->_peerInfo = new_peerInfo; - } - break; - case 3 /* circleBlob */: - { - NSData *new_circleBlob = PBReaderReadData(reader); - self->_circleBlob = new_circleBlob; - } - break; - case 4 /* initialSyncItems */: - { - NSData *new_initialSyncItems = PBReaderReadData(reader); - self->_initialSyncItems = new_initialSyncItems; - } - break; - default: - if (!PBReaderSkipValueWithTag(reader, tag, aType)) - return NO; - break; - } - } - return !PBReaderHasError(reader); -} - -- (BOOL)readFrom:(PBDataReader *)reader -{ - return OTSOSMessageReadFrom(self, reader); -} -- (void)writeTo:(PBDataWriter *)writer -{ - /* credential */ - { - if (self->_credential) - { - PBDataWriterWriteDataField(writer, self->_credential, 1); - } - } - /* peerInfo */ - { - if (self->_peerInfo) - { - PBDataWriterWriteDataField(writer, self->_peerInfo, 2); - } - } - /* circleBlob */ - { - if (self->_circleBlob) - { - PBDataWriterWriteDataField(writer, self->_circleBlob, 3); - } - } - /* initialSyncItems */ - { - if (self->_initialSyncItems) - { - PBDataWriterWriteDataField(writer, self->_initialSyncItems, 4); - } - } -} - -- (void)copyTo:(OTSOSMessage *)other -{ - if (_credential) - { - other.credential = _credential; - } - if (_peerInfo) - { - other.peerInfo = _peerInfo; - } - if (_circleBlob) - { - other.circleBlob = _circleBlob; - } - if (_initialSyncItems) - { - other.initialSyncItems = _initialSyncItems; - } -} - -- (id)copyWithZone:(NSZone *)zone -{ - OTSOSMessage *copy = [[[self class] allocWithZone:zone] init]; - copy->_credential = [_credential copyWithZone:zone]; - copy->_peerInfo = [_peerInfo copyWithZone:zone]; - copy->_circleBlob = [_circleBlob copyWithZone:zone]; - copy->_initialSyncItems = [_initialSyncItems copyWithZone:zone]; - return copy; -} - -- (BOOL)isEqual:(id)object -{ - OTSOSMessage *other = (OTSOSMessage *)object; - return [other isMemberOfClass:[self class]] - && - ((!self->_credential && !other->_credential) || [self->_credential isEqual:other->_credential]) - && - ((!self->_peerInfo && !other->_peerInfo) || [self->_peerInfo isEqual:other->_peerInfo]) - && - ((!self->_circleBlob && !other->_circleBlob) || [self->_circleBlob isEqual:other->_circleBlob]) - && - ((!self->_initialSyncItems && !other->_initialSyncItems) || [self->_initialSyncItems isEqual:other->_initialSyncItems]) - ; -} - -- (NSUInteger)hash -{ - return 0 - ^ - [self->_credential hash] - ^ - [self->_peerInfo hash] - ^ - [self->_circleBlob hash] - ^ - [self->_initialSyncItems hash] - ; -} - -- (void)mergeFrom:(OTSOSMessage *)other -{ - if (other->_credential) - { - [self setCredential:other->_credential]; - } - if (other->_peerInfo) - { - [self setPeerInfo:other->_peerInfo]; - } - if (other->_circleBlob) - { - [self setCircleBlob:other->_circleBlob]; - } - if (other->_initialSyncItems) - { - [self setInitialSyncItems:other->_initialSyncItems]; - } -} - -@end - diff --git a/keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.m b/keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.m index 7a2aad45..43b70418 100644 --- a/keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.m +++ b/keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.m @@ -25,7 +25,7 @@ } - (BOOL)hasEpoch { - return _has.epoch; + return _has.epoch != 0; } - (NSString *)description diff --git a/keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h b/keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h index b7495329..a0a32e48 100644 --- a/keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h +++ b/keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h @@ -14,7 +14,6 @@ __attribute__((visibility("hidden"))) @interface OTSponsorToApplicantRound2M2 : PBCodable { - NSMutableArray *_preapprovedKeys; NSData *_voucher; NSData *_voucherSignature; } @@ -26,13 +25,6 @@ __attribute__((visibility("hidden"))) @property (nonatomic, readonly) BOOL hasVoucherSignature; @property (nonatomic, retain) NSData *voucherSignature; -@property (nonatomic, retain) NSMutableArray *preapprovedKeys; -- (void)clearPreapprovedKeys; -- (void)addPreapprovedKeys:(NSData *)i; -- (NSUInteger)preapprovedKeysCount; -- (NSData *)preapprovedKeysAtIndex:(NSUInteger)idx; -+ (Class)preapprovedKeysType; - // Performs a shallow copy into other - (void)copyTo:(OTSponsorToApplicantRound2M2 *)other; diff --git a/keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.m b/keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.m index 6737b641..c51eaced 100644 --- a/keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.m +++ b/keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.m @@ -23,31 +23,6 @@ return _voucherSignature != nil; } @synthesize voucherSignature = _voucherSignature; -@synthesize preapprovedKeys = _preapprovedKeys; -- (void)clearPreapprovedKeys -{ - [_preapprovedKeys removeAllObjects]; -} -- (void)addPreapprovedKeys:(NSData *)i -{ - if (!_preapprovedKeys) - { - _preapprovedKeys = [[NSMutableArray alloc] init]; - } - [_preapprovedKeys addObject:i]; -} -- (NSUInteger)preapprovedKeysCount -{ - return [_preapprovedKeys count]; -} -- (NSData *)preapprovedKeysAtIndex:(NSUInteger)idx -{ - return [_preapprovedKeys objectAtIndex:idx]; -} -+ (Class)preapprovedKeysType -{ - return [NSData class]; -} - (NSString *)description { @@ -65,10 +40,6 @@ { [dict setObject:self->_voucherSignature forKey:@"voucherSignature"]; } - if (self->_preapprovedKeys) - { - [dict setObject:self->_preapprovedKeys forKey:@"preapprovedKeys"]; - } return dict; } @@ -100,15 +71,6 @@ BOOL OTSponsorToApplicantRound2M2ReadFrom(__unsafe_unretained OTSponsorToApplica self->_voucherSignature = new_voucherSignature; } break; - case 3 /* preapprovedKeys */: - { - NSData *new_preapprovedKeys = PBReaderReadData(reader); - if (new_preapprovedKeys) - { - [self addPreapprovedKeys:new_preapprovedKeys]; - } - } - break; default: if (!PBReaderSkipValueWithTag(reader, tag, aType)) return NO; @@ -138,13 +100,6 @@ BOOL OTSponsorToApplicantRound2M2ReadFrom(__unsafe_unretained OTSponsorToApplica PBDataWriterWriteDataField(writer, self->_voucherSignature, 2); } } - /* preapprovedKeys */ - { - for (NSData *s_preapprovedKeys in self->_preapprovedKeys) - { - PBDataWriterWriteDataField(writer, s_preapprovedKeys, 3); - } - } } - (void)copyTo:(OTSponsorToApplicantRound2M2 *)other @@ -157,15 +112,6 @@ BOOL OTSponsorToApplicantRound2M2ReadFrom(__unsafe_unretained OTSponsorToApplica { other.voucherSignature = _voucherSignature; } - if ([self preapprovedKeysCount]) - { - [other clearPreapprovedKeys]; - NSUInteger preapprovedKeysCnt = [self preapprovedKeysCount]; - for (NSUInteger i = 0; i < preapprovedKeysCnt; i++) - { - [other addPreapprovedKeys:[self preapprovedKeysAtIndex:i]]; - } - } } - (id)copyWithZone:(NSZone *)zone @@ -173,11 +119,6 @@ BOOL OTSponsorToApplicantRound2M2ReadFrom(__unsafe_unretained OTSponsorToApplica OTSponsorToApplicantRound2M2 *copy = [[[self class] allocWithZone:zone] init]; copy->_voucher = [_voucher copyWithZone:zone]; copy->_voucherSignature = [_voucherSignature copyWithZone:zone]; - for (NSData *v in _preapprovedKeys) - { - NSData *vCopy = [v copyWithZone:zone]; - [copy addPreapprovedKeys:vCopy]; - } return copy; } @@ -189,8 +130,6 @@ BOOL OTSponsorToApplicantRound2M2ReadFrom(__unsafe_unretained OTSponsorToApplica ((!self->_voucher && !other->_voucher) || [self->_voucher isEqual:other->_voucher]) && ((!self->_voucherSignature && !other->_voucherSignature) || [self->_voucherSignature isEqual:other->_voucherSignature]) - && - ((!self->_preapprovedKeys && !other->_preapprovedKeys) || [self->_preapprovedKeys isEqual:other->_preapprovedKeys]) ; } @@ -201,8 +140,6 @@ BOOL OTSponsorToApplicantRound2M2ReadFrom(__unsafe_unretained OTSponsorToApplica [self->_voucher hash] ^ [self->_voucherSignature hash] - ^ - [self->_preapprovedKeys hash] ; } @@ -216,10 +153,6 @@ BOOL OTSponsorToApplicantRound2M2ReadFrom(__unsafe_unretained OTSponsorToApplica { [self setVoucherSignature:other->_voucherSignature]; } - for (NSData *iter_preapprovedKeys in other->_preapprovedKeys) - { - [self addPreapprovedKeys:iter_preapprovedKeys]; - } } @end diff --git a/keychain/ot/proto/generated_source/OTSupportOctagonMessage.h b/keychain/ot/proto/generated_source/OTSupportOctagonMessage.h new file mode 100644 index 00000000..bfe58f0d --- /dev/null +++ b/keychain/ot/proto/generated_source/OTSupportOctagonMessage.h @@ -0,0 +1,43 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#import +#import + +#import "OTGlobalEnums.h" + +#ifdef __cplusplus +#define OTSUPPORTOCTAGONMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden"))) +#else +#define OTSUPPORTOCTAGONMESSAGE_FUNCTION extern __attribute__((visibility("hidden"))) +#endif + +__attribute__((visibility("hidden"))) +@interface OTSupportOctagonMessage : PBCodable +{ + OTSupportType _supported; + struct { + int supported:1; + } _has; +} + + +@property (nonatomic) BOOL hasSupported; +@property (nonatomic) OTSupportType supported; +- (NSString *)supportedAsString:(OTSupportType)value; +- (OTSupportType)StringAsSupported:(NSString *)str; + +// Performs a shallow copy into other +- (void)copyTo:(OTSupportOctagonMessage *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTSupportOctagonMessage *)other; + +OTSUPPORTOCTAGONMESSAGE_FUNCTION BOOL OTSupportOctagonMessageReadFrom(__unsafe_unretained OTSupportOctagonMessage *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTSupportOctagonMessage.m b/keychain/ot/proto/generated_source/OTSupportOctagonMessage.m new file mode 100644 index 00000000..dceeaee4 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTSupportOctagonMessage.m @@ -0,0 +1,151 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#import "OTSupportOctagonMessage.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTSupportOctagonMessage + +@synthesize supported = _supported; +- (OTSupportType)supported +{ + return _has.supported ? _supported : OTSupportType_unknown; +} +- (void)setSupported:(OTSupportType)v +{ + _has.supported = YES; + _supported = v; +} +- (void)setHasSupported:(BOOL)f +{ + _has.supported = f; +} +- (BOOL)hasSupported +{ + return _has.supported != 0; +} +- (NSString *)supportedAsString:(OTSupportType)value +{ + return OTSupportTypeAsString(value); +} +- (OTSupportType)StringAsSupported:(NSString *)str +{ + return StringAsOTSupportType(str); +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.supported) + { + [dict setObject:OTSupportTypeAsString(self->_supported) forKey:@"supported"]; + } + return dict; +} + +BOOL OTSupportOctagonMessageReadFrom(__unsafe_unretained OTSupportOctagonMessage *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* supported */: + { + self->_has.supported = YES; + self->_supported = PBReaderReadInt32(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTSupportOctagonMessageReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* supported */ + { + if (self->_has.supported) + { + PBDataWriterWriteInt32Field(writer, self->_supported, 1); + } + } +} + +- (void)copyTo:(OTSupportOctagonMessage *)other +{ + if (self->_has.supported) + { + other->_supported = _supported; + other->_has.supported = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTSupportOctagonMessage *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.supported) + { + copy->_supported = _supported; + copy->_has.supported = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTSupportOctagonMessage *other = (OTSupportOctagonMessage *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.supported && other->_has.supported && self->_supported == other->_supported) || (!self->_has.supported && !other->_has.supported)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.supported ? PBHashInt((NSUInteger)self->_supported) : 0) + ; +} + +- (void)mergeFrom:(OTSupportOctagonMessage *)other +{ + if (other->_has.supported) + { + self->_supported = other->_supported; + self->_has.supported = YES; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTSupportSOSMessage.h b/keychain/ot/proto/generated_source/OTSupportSOSMessage.h new file mode 100644 index 00000000..d9982886 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTSupportSOSMessage.h @@ -0,0 +1,43 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#import +#import + +#import "OTGlobalEnums.h" + +#ifdef __cplusplus +#define OTSUPPORTSOSMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden"))) +#else +#define OTSUPPORTSOSMESSAGE_FUNCTION extern __attribute__((visibility("hidden"))) +#endif + +__attribute__((visibility("hidden"))) +@interface OTSupportSOSMessage : PBCodable +{ + OTSupportType _supported; + struct { + int supported:1; + } _has; +} + + +@property (nonatomic) BOOL hasSupported; +@property (nonatomic) OTSupportType supported; +- (NSString *)supportedAsString:(OTSupportType)value; +- (OTSupportType)StringAsSupported:(NSString *)str; + +// Performs a shallow copy into other +- (void)copyTo:(OTSupportSOSMessage *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTSupportSOSMessage *)other; + +OTSUPPORTSOSMESSAGE_FUNCTION BOOL OTSupportSOSMessageReadFrom(__unsafe_unretained OTSupportSOSMessage *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTSupportSOSMessage.m b/keychain/ot/proto/generated_source/OTSupportSOSMessage.m new file mode 100644 index 00000000..059472c6 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTSupportSOSMessage.m @@ -0,0 +1,151 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#import "OTSupportSOSMessage.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTSupportSOSMessage + +@synthesize supported = _supported; +- (OTSupportType)supported +{ + return _has.supported ? _supported : OTSupportType_unknown; +} +- (void)setSupported:(OTSupportType)v +{ + _has.supported = YES; + _supported = v; +} +- (void)setHasSupported:(BOOL)f +{ + _has.supported = f; +} +- (BOOL)hasSupported +{ + return _has.supported != 0; +} +- (NSString *)supportedAsString:(OTSupportType)value +{ + return OTSupportTypeAsString(value); +} +- (OTSupportType)StringAsSupported:(NSString *)str +{ + return StringAsOTSupportType(str); +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.supported) + { + [dict setObject:OTSupportTypeAsString(self->_supported) forKey:@"supported"]; + } + return dict; +} + +BOOL OTSupportSOSMessageReadFrom(__unsafe_unretained OTSupportSOSMessage *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* supported */: + { + self->_has.supported = YES; + self->_supported = PBReaderReadInt32(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTSupportSOSMessageReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* supported */ + { + if (self->_has.supported) + { + PBDataWriterWriteInt32Field(writer, self->_supported, 1); + } + } +} + +- (void)copyTo:(OTSupportSOSMessage *)other +{ + if (self->_has.supported) + { + other->_supported = _supported; + other->_has.supported = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTSupportSOSMessage *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.supported) + { + copy->_supported = _supported; + copy->_has.supported = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTSupportSOSMessage *other = (OTSupportSOSMessage *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.supported && other->_has.supported && self->_supported == other->_supported) || (!self->_has.supported && !other->_has.supported)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.supported ? PBHashInt((NSUInteger)self->_supported) : 0) + ; +} + +- (void)mergeFrom:(OTSupportSOSMessage *)other +{ + if (other->_has.supported) + { + self->_supported = other->_supported; + self->_has.supported = YES; + } +} + +@end + diff --git a/keychain/ot/proto/source/OTSOSMessage.h b/keychain/ot/proto/source/OTSOSMessage.h deleted file mode 100644 index e515077e..00000000 --- a/keychain/ot/proto/source/OTSOSMessage.h +++ /dev/null @@ -1,48 +0,0 @@ -// This file was automatically generated by protocompiler -// DO NOT EDIT! -// Compiled from OTPairingMessage.proto - -#import -#import - -#ifdef __cplusplus -#define OTSOSMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden"))) -#else -#define OTSOSMESSAGE_FUNCTION extern __attribute__((visibility("hidden"))) -#endif - -__attribute__((visibility("hidden"))) -@interface OTSOSMessage : PBCodable -{ - NSData *_circleBlob; - NSData *_credential; - NSData *_initialSyncItems; - NSData *_peerInfo; -} - - -@property (nonatomic, readonly) BOOL hasCredential; -@property (nonatomic, retain) NSData *credential; - -@property (nonatomic, readonly) BOOL hasPeerInfo; -@property (nonatomic, retain) NSData *peerInfo; - -@property (nonatomic, readonly) BOOL hasCircleBlob; -@property (nonatomic, retain) NSData *circleBlob; - -@property (nonatomic, readonly) BOOL hasInitialSyncItems; -@property (nonatomic, retain) NSData *initialSyncItems; - -// Performs a shallow copy into other -- (void)copyTo:(OTSOSMessage *)other; - -// Performs a deep merge from other into self -// If set in other, singular values in self are replaced in self -// Singular composite values are recursively merged -// Repeated values from other are appended to repeated values in self -- (void)mergeFrom:(OTSOSMessage *)other; - -OTSOSMESSAGE_FUNCTION BOOL OTSOSMessageReadFrom(__unsafe_unretained OTSOSMessage *self, __unsafe_unretained PBDataReader *reader); - -@end - diff --git a/keychain/ot/proto/source/OTSOSMessage.m b/keychain/ot/proto/source/OTSOSMessage.m deleted file mode 100644 index e4a1f2a5..00000000 --- a/keychain/ot/proto/source/OTSOSMessage.m +++ /dev/null @@ -1,229 +0,0 @@ -// This file was automatically generated by protocompiler -// DO NOT EDIT! -// Compiled from OTPairingMessage.proto - -#import "OTSOSMessage.h" -#import -#import -#import - -#if !__has_feature(objc_arc) -# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. -#endif - -@implementation OTSOSMessage - -- (BOOL)hasCredential -{ - return _credential != nil; -} -@synthesize credential = _credential; -- (BOOL)hasPeerInfo -{ - return _peerInfo != nil; -} -@synthesize peerInfo = _peerInfo; -- (BOOL)hasCircleBlob -{ - return _circleBlob != nil; -} -@synthesize circleBlob = _circleBlob; -- (BOOL)hasInitialSyncItems -{ - return _initialSyncItems != nil; -} -@synthesize initialSyncItems = _initialSyncItems; - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; -} - -- (NSDictionary *)dictionaryRepresentation -{ - NSMutableDictionary *dict = [NSMutableDictionary dictionary]; - if (self->_credential) - { - [dict setObject:self->_credential forKey:@"credential"]; - } - if (self->_peerInfo) - { - [dict setObject:self->_peerInfo forKey:@"peerInfo"]; - } - if (self->_circleBlob) - { - [dict setObject:self->_circleBlob forKey:@"circleBlob"]; - } - if (self->_initialSyncItems) - { - [dict setObject:self->_initialSyncItems forKey:@"initialSyncItems"]; - } - return dict; -} - -BOOL OTSOSMessageReadFrom(__unsafe_unretained OTSOSMessage *self, __unsafe_unretained PBDataReader *reader) { - while (PBReaderHasMoreData(reader)) { - uint32_t tag = 0; - uint8_t aType = 0; - - PBReaderReadTag32AndType(reader, &tag, &aType); - - if (PBReaderHasError(reader)) - break; - - if (aType == TYPE_END_GROUP) { - break; - } - - switch (tag) { - - case 1 /* credential */: - { - NSData *new_credential = PBReaderReadData(reader); - self->_credential = new_credential; - } - break; - case 2 /* peerInfo */: - { - NSData *new_peerInfo = PBReaderReadData(reader); - self->_peerInfo = new_peerInfo; - } - break; - case 3 /* circleBlob */: - { - NSData *new_circleBlob = PBReaderReadData(reader); - self->_circleBlob = new_circleBlob; - } - break; - case 4 /* initialSyncItems */: - { - NSData *new_initialSyncItems = PBReaderReadData(reader); - self->_initialSyncItems = new_initialSyncItems; - } - break; - default: - if (!PBReaderSkipValueWithTag(reader, tag, aType)) - return NO; - break; - } - } - return !PBReaderHasError(reader); -} - -- (BOOL)readFrom:(PBDataReader *)reader -{ - return OTSOSMessageReadFrom(self, reader); -} -- (void)writeTo:(PBDataWriter *)writer -{ - /* credential */ - { - if (self->_credential) - { - PBDataWriterWriteDataField(writer, self->_credential, 1); - } - } - /* peerInfo */ - { - if (self->_peerInfo) - { - PBDataWriterWriteDataField(writer, self->_peerInfo, 2); - } - } - /* circleBlob */ - { - if (self->_circleBlob) - { - PBDataWriterWriteDataField(writer, self->_circleBlob, 3); - } - } - /* initialSyncItems */ - { - if (self->_initialSyncItems) - { - PBDataWriterWriteDataField(writer, self->_initialSyncItems, 4); - } - } -} - -- (void)copyTo:(OTSOSMessage *)other -{ - if (_credential) - { - other.credential = _credential; - } - if (_peerInfo) - { - other.peerInfo = _peerInfo; - } - if (_circleBlob) - { - other.circleBlob = _circleBlob; - } - if (_initialSyncItems) - { - other.initialSyncItems = _initialSyncItems; - } -} - -- (id)copyWithZone:(NSZone *)zone -{ - OTSOSMessage *copy = [[[self class] allocWithZone:zone] init]; - copy->_credential = [_credential copyWithZone:zone]; - copy->_peerInfo = [_peerInfo copyWithZone:zone]; - copy->_circleBlob = [_circleBlob copyWithZone:zone]; - copy->_initialSyncItems = [_initialSyncItems copyWithZone:zone]; - return copy; -} - -- (BOOL)isEqual:(id)object -{ - OTSOSMessage *other = (OTSOSMessage *)object; - return [other isMemberOfClass:[self class]] - && - ((!self->_credential && !other->_credential) || [self->_credential isEqual:other->_credential]) - && - ((!self->_peerInfo && !other->_peerInfo) || [self->_peerInfo isEqual:other->_peerInfo]) - && - ((!self->_circleBlob && !other->_circleBlob) || [self->_circleBlob isEqual:other->_circleBlob]) - && - ((!self->_initialSyncItems && !other->_initialSyncItems) || [self->_initialSyncItems isEqual:other->_initialSyncItems]) - ; -} - -- (NSUInteger)hash -{ - return 0 - ^ - [self->_credential hash] - ^ - [self->_peerInfo hash] - ^ - [self->_circleBlob hash] - ^ - [self->_initialSyncItems hash] - ; -} - -- (void)mergeFrom:(OTSOSMessage *)other -{ - if (other->_credential) - { - [self setCredential:other->_credential]; - } - if (other->_peerInfo) - { - [self setPeerInfo:other->_peerInfo]; - } - if (other->_circleBlob) - { - [self setCircleBlob:other->_circleBlob]; - } - if (other->_initialSyncItems) - { - [self setInitialSyncItems:other->_initialSyncItems]; - } -} - -@end - diff --git a/keychain/ot/tests/OTFollowupTests.m b/keychain/ot/tests/OTFollowupTests.m deleted file mode 100644 index 73897a1a..00000000 --- a/keychain/ot/tests/OTFollowupTests.m +++ /dev/null @@ -1,19 +0,0 @@ -// -// OTFollowupTests.m -// OctagonTests -// - -#import -#import -#import "keychain/ckks/CKKSAnalytics.h" -#import "keychain/ot/OTFollowup.h" - -@interface OTFollowupTests : XCTestCase -@end - -@implementation OTFollowupTests - -- (void)testPostCFUFollowup { -} - -@end diff --git a/keychain/ot/tests/gen_test_plist.py b/keychain/ot/tests/gen_test_plist.py index 2b01e9a4..9cc08537 100644 --- a/keychain/ot/tests/gen_test_plist.py +++ b/keychain/ot/tests/gen_test_plist.py @@ -23,7 +23,7 @@ test_list = Foundation.NSMutableArray.array() test_files = glob(test_dir + '/octagon/*.swift') + glob(test_dir + '/octagon/*/*.swift') def get_class_names(): - test_classes = ['OTFollowupTests'] + test_classes = ['OctagonTests.OctagonStateMachineTests'] for filename in test_files: f = open(filename, 'r') for line in f: @@ -43,7 +43,24 @@ for x in ['TrustedPeersTests', 'TrustedPeersHelperUnitTests']: test_dictionary['WorkingDirectory'] = '/AppleInternal/XCTests/com.apple.security/' test_command = Foundation.NSMutableArray.array() - test_command.append('BATS_XCTEST_CMD {}.xctest'.format(x)) + test_command.append('BATS_XCTEST_CMD') + test_command.append('{}.xctest'.format(x)) + test_dictionary['Command'] = test_command + + test_list.append(test_dictionary) + + +for x in ['OctagonTrustTests']: + + test_dictionary = Foundation.NSMutableDictionary.dictionary() + test_dictionary['TestName'] = x + test_dictionary['Timeout']= 1200 + test_dictionary['ShowSubtestResults']= True + test_dictionary['WorkingDirectory'] = '/AppleInternal/XCTests/com.apple.security/' + + test_command = Foundation.NSMutableArray.array() + test_command.append('BATS_XCTEST_CMD') + test_command.append('{}.xctest'.format(x)) test_dictionary['Command'] = test_command test_list.append(test_dictionary) @@ -58,7 +75,10 @@ for x in get_class_names(): test_dictionary['WorkingDirectory'] = '/AppleInternal/XCTests/com.apple.security/' test_command = Foundation.NSMutableArray.array() - test_command.append('BATS_XCTEST_CMD -XCTest {} OctagonTests.xctest'.format(x)) + test_command.append('BATS_XCTEST_CMD') + test_command.append('-XCTest') + test_command.append('{}'.format(x)) + test_command.append('OctagonTests.xctest') test_dictionary['Command'] = test_command test_list.append(test_dictionary) diff --git a/keychain/ot/tests/octagon/.swiftlint.yml b/keychain/ot/tests/octagon/.swiftlint.yml new file mode 100644 index 00000000..f8391d9b --- /dev/null +++ b/keychain/ot/tests/octagon/.swiftlint.yml @@ -0,0 +1,4 @@ +disabled_rules: + - force_cast + - force_try + - implicitly_unwrapped_optional diff --git a/keychain/ot/tests/octagon/OctagonDataPersistenceTests.swift b/keychain/ot/tests/octagon/OctagonDataPersistenceTests.swift index 0b457d23..5dd8c49c 100644 --- a/keychain/ot/tests/octagon/OctagonDataPersistenceTests.swift +++ b/keychain/ot/tests/octagon/OctagonDataPersistenceTests.swift @@ -3,7 +3,6 @@ import XCTest #if OCTAGON class OctagonAccountMetadataClassCPersistenceTests: CloudKitKeychainSyncingMockXCTest { - override static func setUp() { super.setUp() @@ -19,6 +18,7 @@ class OctagonAccountMetadataClassCPersistenceTests: CloudKitKeychainSyncingMockX state.peerID = "asdf" state.icloudAccountState = .ACCOUNT_AVAILABLE state.trustState = .TRUSTED + state.cdpState = .ENABLED XCTAssertNoThrow(try state.saveToKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext), "saving to the keychain should work") @@ -28,6 +28,7 @@ class OctagonAccountMetadataClassCPersistenceTests: CloudKitKeychainSyncingMockX XCTAssertEqual(state2.peerID, state.peerID, "peer ID persists through keychain") XCTAssertEqual(state2.icloudAccountState, state.icloudAccountState, "account state persists through keychain") XCTAssertEqual(state2.trustState, state.trustState, "trust state persists through keychain") + XCTAssertEqual(state2.cdpState, state.cdpState, "cdp state persists through keychain") } catch { XCTFail("error loading from keychain: \(error)") } @@ -145,7 +146,7 @@ class OctagonAccountMetadataClassCPersistenceTests: CloudKitKeychainSyncingMockX do { let state2 = try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext) XCTAssertNotNil(state2) - XCTAssertEqual(state2.peerID, nil, "peerID should be nil") + XCTAssertNil(state2.peerID, "peerID should be nil") XCTAssertEqual(state2.icloudAccountState, OTAccountMetadataClassC_AccountState.UNKNOWN, "account state should be OTAccountMetadataClassC_AccountState_UNKNOWN") XCTAssertEqual(state2.trustState, OTAccountMetadataClassC_TrustState.UNKNOWN, "trust state should be OTAccountMetadataClassC_TrustState_UNKNOWN") } catch { diff --git a/keychain/ot/tests/octagon/OctagonPolicyTests.swift b/keychain/ot/tests/octagon/OctagonPolicyTests.swift new file mode 100644 index 00000000..4152e8cc --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonPolicyTests.swift @@ -0,0 +1,57 @@ +import Foundation + +class OctagonPolicyTests: XCTestCase { + func prevailingPolicy() throws -> TPPolicy { + let policyDocument = builtInPolicyDocuments().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first + XCTAssertNotNil(policyDocument, "Should have a prevailing policy document") + + let policy = try policyDocument!.policy(withSecrets: [:], decrypter: Decrypter()) + return policy + } + + func testPrevailingPolicyHasModelsForAllViewRules() throws { + let policy = try self.prevailingPolicy() + + // There's a rule for 'NotSynced', but we explicitly don't want to bring up that view + let viewsWithRules = Set(policy.keyViewMapping.compactMap { $0.view }).subtracting(Set(["NotSynced"])) + XCTAssertEqual(Set(policy.categoriesByView.keys), + viewsWithRules, + "Every view should have a rule") + } + + func testPrevailingPolicyIntroducerGraphIsClosed() throws { + // Let's check that, for each model, introducing a new peer doesn't give them more introduction power + let policy = try self.prevailingPolicy() + + policy.introducersByCategory.forEach { category, introducers in + let allowedIntroducers = Set(introducers) + let allAccessible = Set(allowedIntroducers.compactMap { category in policy.introducersByCategory[category] }.joined()) + + XCTAssertEqual(allowedIntroducers, allAccessible, "A device class shouldn't be able to introduce a peer which can introduce a peer that the original device couldn't introduce") + } + } + + func testPrePolicyViews() throws { + let policy = try self.prevailingPolicy() + + XCTAssert(policy.keyViewMapping.count >= 7, "Should always have 7 basic views") + + let firstSevenRules = policy.keyViewMapping[..<7] + + let firstSevenViews = firstSevenRules.compactMap { $0.view } + XCTAssertEqual(Set(firstSevenViews), + Set(["ApplePay", "AutoUnlock", "Engram", "Health", "Home", "Manatee", "LimitedPeersAllowed"]), + "First seven rules should be for prepolicy views") + + // Now, ensure that the first seven rules match vwht only + firstSevenRules.forEach { viewRule in + XCTAssertNotNil(viewRule.view, "View rule should have a name") + XCTAssertNotNil(viewRule.matchingRule, "Rule should have a matching rule") + let rule = viewRule.matchingRule! + + XCTAssertNotNil(rule.match, "Rule should have a match subrule") + XCTAssertEqual(rule.match.fieldName, "vwht", "Rule should match field vwht") + XCTAssertEqual(rule.match.regex, "^\(viewRule.view!)$", "Regex should match field name") + } + } +} diff --git a/keychain/ot/tests/octagon/OctagonStateMachineTests.swift b/keychain/ot/tests/octagon/OctagonStateMachineTests.swift new file mode 100644 index 00000000..ca8d023d --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonStateMachineTests.swift @@ -0,0 +1,196 @@ + +import Foundation + +extension OctagonStateMachine { + func condition(_ state: OctagonStateMachineTests.TestEngine.State) -> CKKSCondition { + return self.stateConditions[state.rawValue]! + } + + func handle(flag: OctagonStateMachineTests.TestEngine.Flag) { + self.handleFlag(flag.rawValue) + } +} + +extension OctagonStateTransitionOperation { + convenience init(_ state: OctagonStateMachineTests.TestEngine.State) { + self.init(name: "test-op", entering: state.rawValue) + } +} + +extension OctagonFlags { + func checkAndRemove(_ flag: OctagonStateMachineTests.TestEngine.Flag) -> Bool { + if(self._onqueueContains(flag.rawValue)) { + self._onqueueRemoveFlag(flag.rawValue) + return true + } + return false + } +} + +class OctagonStateMachineTests : XCTestCase { + class TestEngine: OctagonStateMachineEngine { + enum State: String, CaseIterable { + case base = "base" + case receivedFlag = "received_flag" + } + + enum Flag: String, CaseIterable { + case aFlag = "a_flag" + case returnToBase = "return_to_base" + } + + func _onqueueNextStateMachineTransition(_ currentState: String, + flags: OctagonFlags, + pendingFlags: OctagonStateOnqueuePendingFlagHandler) -> (CKKSResultOperation & OctagonStateTransitionOperationProtocol)? { + guard let state = State(rawValue: currentState) else { + return nil + } + + switch(state) { + case .base: + if flags.checkAndRemove(.aFlag) { + return OctagonStateTransitionOperation(.receivedFlag) + } + return nil + case .receivedFlag: + if flags.checkAndRemove(.returnToBase) { + return OctagonStateTransitionOperation(.base) + } + return nil + } + } + } + + var stateMachine : OctagonStateMachine! + var lockStateProvider : CKKSMockLockStateProvider! + + // The state machine doesn't hold a strong reference to its engine. Help! + var testEngine : TestEngine! + + override func setUp() { + super.setUp() + + self.lockStateProvider = CKKSMockLockStateProvider(currentLockStatus: false) + self.testEngine = TestEngine() + self.stateMachine = OctagonStateMachine(name: "test-machine", + states: Set(TestEngine.State.allCases.map { $0.rawValue as String } ), + flags: Set(TestEngine.Flag.allCases.map { $0.rawValue as String } ), + initialState: TestEngine.State.base.rawValue, + queue: DispatchQueue(label: "test-state-machine"), + stateEngine: self.testEngine, + lockStateTracker: CKKSLockStateTracker(provider: self.lockStateProvider), + reachabilityTracker: CKKSReachabilityTracker()) + } + + override func tearDown() { + self.stateMachine.haltOperation() + + self.lockStateProvider = nil + self.stateMachine = nil + } + + func testHandleFlag() { + self.stateMachine.startOperation() + + XCTAssertEqual(0, self.stateMachine.condition(.base).wait(1*NSEC_PER_SEC), "Should enter base state") + XCTAssertTrue(self.stateMachine.isPaused(), "State machine should consider itself paused") + XCTAssertEqual(0, self.stateMachine.paused.wait(1*NSEC_PER_SEC), "Paused condition should be fulfilled") + + self.stateMachine.handle(flag: .aFlag) + + XCTAssertEqual(0, self.stateMachine.condition(.receivedFlag).wait(100*NSEC_PER_SEC), "Should enter 'received flag' state") + XCTAssertTrue(self.stateMachine.isPaused(), "State machine should consider itself paused") + XCTAssertEqual(0, self.stateMachine.paused.wait(1*NSEC_PER_SEC), "Paused condition should be fulfilled") + + self.stateMachine.handle(flag: .returnToBase) + + XCTAssertEqual(0, self.stateMachine.condition(.base).wait(1*NSEC_PER_SEC), "Should enter base state") + XCTAssertTrue(self.stateMachine.isPaused(), "State machine should consider itself paused") + XCTAssertEqual(0, self.stateMachine.paused.wait(1*NSEC_PER_SEC), "Paused condition should be fulfilled") + } + + func testPendingFlagByTime() { + self.stateMachine.startOperation() + + XCTAssertEqual(0, self.stateMachine.condition(.base).wait(1*NSEC_PER_SEC), "Should enter base state") + + self.stateMachine.handle(OctagonPendingFlag(flag: TestEngine.Flag.aFlag.rawValue, + delayInSeconds: 2)) + + // We should _not_ advance within a second + XCTAssertNotEqual(0, self.stateMachine.condition(.receivedFlag).wait(1*NSEC_PER_SEC), "Should not enter 'received flag' state") + + // And then we should! + XCTAssertEqual(0, self.stateMachine.condition(.receivedFlag).wait(2*NSEC_PER_SEC), "Should enter 'received flag' state") + } + + func testPendingFlagByLockState() { + self.stateMachine.startOperation() + + XCTAssertEqual(0, self.stateMachine.condition(.base).wait(1*NSEC_PER_SEC), "Should enter base state") + + self.lockStateProvider.aksCurrentlyLocked = true + self.stateMachine.lockStateTracker?.recheck() + + self.stateMachine.handle(OctagonPendingFlag(flag: TestEngine.Flag.aFlag.rawValue, + conditions: .deviceUnlocked)) + + // We should _not_ advance + XCTAssertNotEqual(0, self.stateMachine.condition(.receivedFlag).wait(1*NSEC_PER_SEC), "Should not enter 'received flag' state") + + self.lockStateProvider.aksCurrentlyLocked = false + self.stateMachine.lockStateTracker?.recheck() + + // But after an unlock, we should + XCTAssertEqual(0, self.stateMachine.condition(.receivedFlag).wait(1*NSEC_PER_SEC), "Should not enter 'received flag' state") + + // And it works the same in the other direction + self.lockStateProvider.aksCurrentlyLocked = true + self.stateMachine.lockStateTracker?.recheck() + + self.stateMachine.handle(OctagonPendingFlag(flag: TestEngine.Flag.returnToBase.rawValue, + conditions: .deviceUnlocked)) + XCTAssertNotEqual(0, self.stateMachine.condition(.base).wait(5*NSEC_PER_SEC), "Should not enter base state") + + self.lockStateProvider.aksCurrentlyLocked = false + self.stateMachine.lockStateTracker?.recheck() + XCTAssertEqual(0, self.stateMachine.condition(.base).wait(1*NSEC_PER_SEC), "Should enter base state") + } + + func testPendingFlagCombination() { + self.stateMachine.startOperation() + + XCTAssertEqual(0, self.stateMachine.condition(.base).wait(1*NSEC_PER_SEC), "Should enter base state") + + // First, the condition arrives before the timeout expires + self.lockStateProvider.aksCurrentlyLocked = true + self.stateMachine.lockStateTracker?.recheck() + + self.stateMachine.handle(OctagonPendingFlag(flag: TestEngine.Flag.aFlag.rawValue, + conditions: .deviceUnlocked, + delayInSeconds: 2)) + + XCTAssertNotEqual(0, self.stateMachine.condition(.receivedFlag).wait(500*NSEC_PER_MSEC), "Should not enter 'received flag' state") + + self.lockStateProvider.aksCurrentlyLocked = false + self.stateMachine.lockStateTracker?.recheck() + + XCTAssertNotEqual(0, self.stateMachine.condition(.receivedFlag).wait(1*NSEC_PER_SEC), "Should not enter 'received flag' state") + + // But after 2s total, we should + XCTAssertEqual(0, self.stateMachine.condition(.receivedFlag).wait(3*NSEC_PER_SEC), "Should enter 'received flag' state") + + // And the same thing happens if the delay expires before the condition + self.lockStateProvider.aksCurrentlyLocked = true + self.stateMachine.lockStateTracker?.recheck() + + self.stateMachine.handle(OctagonPendingFlag(flag: TestEngine.Flag.returnToBase.rawValue, + conditions: .deviceUnlocked, + delayInSeconds: 0.5)) + + XCTAssertNotEqual(0, self.stateMachine.condition(.base).wait(1*NSEC_PER_SEC), "Should not enter 'base' state") + self.lockStateProvider.aksCurrentlyLocked = false + self.stateMachine.lockStateTracker?.recheck() + XCTAssertEqual(0, self.stateMachine.condition(.base).wait(1*NSEC_PER_SEC), "Should not enter 'base' state") + } +} diff --git a/keychain/ot/tests/octagon/OctagonTestMocks.swift b/keychain/ot/tests/octagon/OctagonTestMocks.swift index a9d31759..874585e8 100644 --- a/keychain/ot/tests/octagon/OctagonTestMocks.swift +++ b/keychain/ot/tests/octagon/OctagonTestMocks.swift @@ -12,24 +12,24 @@ class OTMockSecureBackup: NSObject, OctagonEscrowRecovererPrococol { super.init() } - func recover(withInfo info: [AnyHashable: Any]!, - results: AutoreleasingUnsafeMutablePointer!) -> Error! { + func recover(withInfo info: [AnyHashable: Any]?, + results: AutoreleasingUnsafeMutablePointer?) -> Error? { if self.bottleID == nil && self.entropy == nil { - results.pointee = [ + results!.pointee = [ "bottleValid": "invalid", ] } else if self.bottleID == nil && self.entropy != nil { - results.pointee = [ + results!.pointee = [ "EscrowServiceEscrowData": ["BottledPeerEntropy": self.entropy], "bottleValid": "invalid", ] } else if self.bottleID != nil && self.entropy == nil { - results.pointee = [ + results!.pointee = [ "bottleID": self.bottleID!, "bottleValid": "invalid", ] } else { //entropy and bottleID must exist, so its a good bottle. - results.pointee = [ + results!.pointee = [ "bottleID": self.bottleID!, "bottleValid": "valid", "EscrowServiceEscrowData": ["BottledPeerEntropy": self.entropy], @@ -37,6 +37,21 @@ class OTMockSecureBackup: NSObject, OctagonEscrowRecovererPrococol { } return nil } + + func disable(withInfo info: [AnyHashable: Any]!) -> Error? { + return nil + } + + @objc func getAccountInfo(withInfo info: [AnyHashable: Any]!, results: AutoreleasingUnsafeMutablePointer!) -> Error? { + let recordData = accountInfoWithInfoSample.data(using: .utf8)! + var propertyListFormat = PropertyListSerialization.PropertyListFormat.xml + do { + results.pointee = try PropertyListSerialization.propertyList(from: recordData, options: .mutableContainersAndLeaves, format: &propertyListFormat) as! [String: AnyObject] as NSDictionary + } catch { + print("Error reading plist: \(error), format: \(propertyListFormat)") + } + return nil + } } class OTMockFollowUpController: NSObject, OctagonFollowUpControllerProtocol { diff --git a/keychain/ot/tests/octagon/OctagonTests+Account.swift b/keychain/ot/tests/octagon/OctagonTests+Account.swift new file mode 100644 index 00000000..b19af22d --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonTests+Account.swift @@ -0,0 +1,580 @@ +/* +* Copyright (c) 2019 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +import Foundation + +#if OCTAGON + +class OctagonAccountTests: OctagonTestsBase { + func testAccountSave() throws { + let contextName = OTDefaultContext + let containerName = OTCKContainerName + + self.startCKAccountStatusMock() + + // Before resetAndEstablish, there shouldn't be any stored account state + XCTAssertThrowsError(try OTAccountMetadataClassC.loadFromKeychain(forContainer: containerName, contextID: contextName), "Before doing anything, loading a non-existent account state should fail") + + let resetAndEstablishExpectation = self.expectation(description: "resetAndEstablish callback occurs") + self.manager.resetAndEstablish(containerName, + context: contextName, + altDSID: "new altDSID", + resetReason: .testGenerated) { resetError in + XCTAssertNil(resetError, "Should be no error calling resetAndEstablish") + resetAndEstablishExpectation.fulfill() + } + + self.wait(for: [resetAndEstablishExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + let selfPeerID = try self.cuttlefishContext.accountMetadataStore.loadOrCreateAccountMetadata().peerID + + // After resetAndEstablish, you should be able to see the persisted account state + do { + let accountState = try OTAccountMetadataClassC.loadFromKeychain(forContainer: containerName, contextID: contextName) + XCTAssertEqual(selfPeerID, accountState.peerID, "Saved account state should have the same peer ID that prepare returned") + XCTAssertEqual(accountState.cdpState, .ENABLED, "Saved CDP status should be 'enabled' after a resetAndEstablish") + } catch { + XCTFail("error loading account state: \(error)") + } + } + + func testLoadToNoAccount() throws { + // No CloudKit account, either + self.accountStatus = .noAccount + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // With no identity and AuthKit reporting no iCloud account, Octagon should go directly into 'no account' + self.mockAuthKit.altDSID = nil + + let asyncExpectation = self.expectation(description: "dispatch works") + let quiescentExpectation = self.expectation(description: "quiescence has been determined") + DispatchQueue.global(qos: .userInitiated).async { [weak self] in + asyncExpectation.fulfill() + + let c = self!.cuttlefishContext.stateMachine.paused + XCTAssertEqual(0, c.wait(10 * NSEC_PER_SEC), "State machine should become quiescent") + quiescentExpectation.fulfill() + } + // Wait for the block above to fire before continuing + self.wait(for: [asyncExpectation], timeout: 10) + + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(self.cuttlefishContext.stateMachine.isPaused(), "State machine should be stopped") + self.assertNoAccount(context: self.cuttlefishContext) + + XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should be quiescent") + + self.wait(for: [quiescentExpectation], timeout: 10) + + // Since there's no acocunt, CKKS shouldn't even have any views loaded + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have 0 CKKS views loaded") + } + + func testNoAccountLeadsToInitialize() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // With no identity and AuthKit reporting no iCloud account, Octagon should go directly into 'no account' + self.mockAuthKit.altDSID = nil + + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + self.mockAuthKit.altDSID = "1234" + let signinExpectation = self.expectation(description: "sign in returns") + self.otControl.sign(in: "1234", container: nil, context: OTDefaultContext) { error in + XCTAssertNil(error, "error should be nil") + signinExpectation.fulfill() + } + self.wait(for: [signinExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + + // And now the CDP bit is set... + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + } + + func testSignIn() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // Device is signed out + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + // Sign in occurs + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + self.mockAuthKit.hsa2 = true + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + // Octagon should go into 'waitforcdp' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have not posted a repair CFU while waiting for CDP") + + // And CDP is enabled: + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .enabled, "CDP status should be 'enabled'") + + #if !os(tvOS) + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have posted a repair CFU") + #else + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "posted should be false on tvOS; there aren't any devices around to repair it") + #endif + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + + // On sign-out, octagon should go back to 'no account' + self.mockAuthKit.altDSID = nil + XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "sign-out shouldn't error") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + self.assertNoAccount(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .unknown, "CDP status should be 'unknown'") + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + } + + func testSignInWithDelayedHSA2Status() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // Device is signed out + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + // Sign in occurs, but HSA2 status isn't here yet + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + // Octagon should go into 'waitforhsa2' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForHSA2, within: 10 * NSEC_PER_SEC) + + self.mockAuthKit.hsa2 = true + XCTAssertNoThrow(try self.cuttlefishContext.idmsTrustLevelChanged(), "Notification of IDMS trust level shouldn't error") + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + + // On sign-out, octagon should go back to 'no account' + self.mockAuthKit.altDSID = nil + XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "sign-out shouldn't error") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + self.assertNoAccount(context: self.cuttlefishContext) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + } + + func testSignInWithCDPStateBeforeDelayedHSA2Status() throws { + self.startCKAccountStatusMock() + + // Device is signed out + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + // CDP state is set. Cool? + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + + // Sign in occurs, but HSA2 status isn't here yet + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + self.mockAuthKit.hsa2 = true + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + // Octagon should go into 'untrusted', as everything is in place + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + + // On sign-out, octagon should go back to 'no account' + self.mockAuthKit.altDSID = nil + XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "sign-out shouldn't error") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + self.assertNoAccount(context: self.cuttlefishContext) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + } + + func testSetCDPStateWithUnconfiguredArguments() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // Device is signed out + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + // Now set the CDP state, but using the OTClique API (and not configuring the context) + let unconfigured = OTConfigurationContext() + unconfigured.otControl = self.otControl + XCTAssertNoThrow(try OTClique.setCDPEnabled(unconfigured)) + + // Sign in occurs, but HSA2 status isn't here yet + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + // Octagon should go into 'waitforhsa2' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForHSA2, within: 10 * NSEC_PER_SEC) + + self.mockAuthKit.hsa2 = true + XCTAssertNoThrow(try self.cuttlefishContext.idmsTrustLevelChanged(), "Notification of IDMS trust level shouldn't error") + + // and we should skip waiting for CDP, as it's already set + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + + // On sign-out, octagon should go back to 'no account' + self.mockAuthKit.altDSID = nil + XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "sign-out shouldn't error") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + self.assertNoAccount(context: self.cuttlefishContext) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + } + + func testSignInWithExistingCuttlefishRecordsSetsCDPStatus() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // signing in to an account with pre-existing Octagon data should turn on the CDP bit by default: + // no setting needed. + + let remote = self.makeInitiatorContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) + + // when this context boots up, it should go straight into untrusted, and set its CDP bit + // since there's already CDP data in the account + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .enabled, "CDP status should be 'enabled'") + + #if !os(tvOS) + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have posted a repair CFU after the CDP bit was set") + #else + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should not have posted on tvOS; there aren't any iphones around to repair it") + #endif + } + + func testEnableCDPStatusIfNotificationArrives() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // default context comes up, but CDP is not enabled + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have not posted a repair CFU while waiting for CDP") + + // If a cuttlefish push occurs without any data existing, the CDP bit should stay off + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, states: [OctagonStateWaitForCDPUpdated, OctagonStateDetermineCDPState]) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have not posted a repair CFU while waiting for CDP") + + // Another peer comes along and performs Octagon operations + let remote = self.makeInitiatorContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) + + // And some SOS operations. SOS now returns "error" when asked its state + self.mockSOSAdapter.circleStatusError = NSError(domain: kSOSErrorDomain as String, code: kSOSErrorPublicKeyAbsent, userInfo: nil) + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCError) + + // And after the update, the context should go into 'untrusted' + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, states: [OctagonStateWaitForCDPUpdated, OctagonStateDetermineCDPState]) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .enabled, "CDP status should be 'enabled'") + + #if !os(tvOS) + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have posted a repair CFU") + #else + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should not have posted on tvOS; there aren't any iphones around to repair it") + #endif + } + + func testEnableCDPStatusIfNotificationArrivesWithoutCreatingSOSCircle() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // default context comes up, but CDP is not enabled + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have not posted a repair CFU while waiting for CDP") + + // If a cuttlefish push occurs without any data existing, the CDP bit should stay off + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, states: [OctagonStateWaitForCDPUpdated, OctagonStateDetermineCDPState]) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have not posted a repair CFU while waiting for CDP") + + // Another peer comes along and performs Octagon operations + let remote = self.makeInitiatorContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) + + // Unlike testEnableCDPStatusIfNotificationArrives, SOS remains in 'absent', simulating a non-sos platform creating Octagon + + // And after the update, the context should go into 'untrusted' + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, states: [OctagonStateWaitForCDPUpdated, OctagonStateDetermineCDPState]) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .enabled, "CDP status should be 'enabled'") + + #if !os(tvOS) + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have posted a repair CFU") + #else + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should not have posted on tvOS; there aren't any iphones around to repair it") + #endif + } + + func testCDPEnableAPIRaceWithCDPStateDetermination() throws { + // The API call to enable CDP might occur while Octagon is figuring out that it should be disabled + // Octagon should respect the API call + + // SOS is absent + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + self.startCKAccountStatusMock() + + // The initial CDP-enable API call happens while Octagon is fetching the world's state + let fetchExpectation = self.expectation(description: "fetchChanges called") + self.fakeCuttlefishServer.fetchChangesListener = { [unowned self] _ in + do { + try self.cuttlefishContext.setCDPEnabled() + } catch { + XCTFail("Expected to be able to set CDP status without error: \(error)") + } + fetchExpectation.fulfill() + return nil + } + + self.cuttlefishContext.startOctagonStateMachine() + + // Octagon should go into 'untrusted', as the API call said that CDP was there + self.wait(for: [fetchExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + } + + func testDetermineCDPStateFromSOSError() throws { + // If SOS reports that it doesn't have the user key, a circle might exist and it might not + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCError) + self.mockSOSAdapter.circleStatusError = NSError(domain: kSOSErrorDomain as String, code: kSOSErrorPublicKeyAbsent, userInfo: nil) + + self.startCKAccountStatusMock() + + // Octagon should discover the right CDP state, and end up in untrusted + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .unknown, "CDP status should be 'unknown'") + } + + func testSignOut() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + do { + let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + } + + // Now, we should be in 'ready' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.verifyDatabaseMocks() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + // And 'dump' should show some information + let dumpExpectation = self.expectation(description: "dump callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in + XCTAssertNil(error, "Should be no error dumping data") + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let peerID = egoSelf!["peerID"] as? String + XCTAssertNotNil(peerID, "peerID should not be nil") + + dumpExpectation.fulfill() + } + self.wait(for: [dumpExpectation], timeout: 10) + + // Turn off the CK account too + self.accountStatus = .noAccount + self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() + + XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "Should be no issue signing out") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + self.assertNoAccount(context: self.cuttlefishContext) + + // And 'dump' should show nothing + let signedOutDumpExpectation = self.expectation(description: "dump callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in + XCTAssertNil(error, "Should be no error dumping data") + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + XCTAssertEqual(egoSelf!.count, 0, "egoSelf should have zero elements") + + signedOutDumpExpectation.fulfill() + } + self.wait(for: [signedOutDumpExpectation], timeout: 10) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + + //check trust status + let checkTrustExpectation = self.expectation(description: "checkTrustExpectation callback occurs") + let configuration = OTOperationConfiguration() + self.cuttlefishContext.rpcTrustStatus(configuration) { _, _, _, _, _, _ in + checkTrustExpectation.fulfill() + } + self.wait(for: [checkTrustExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + // And 'dump' should show nothing + let signedOutDumpExpectationAfterCheckTrustStatus = self.expectation(description: "dump callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in + XCTAssertNil(error, "Should be no error dumping data") + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + XCTAssertEqual(egoSelf!.count, 0, "egoSelf should have zero elements") + + signedOutDumpExpectationAfterCheckTrustStatus.fulfill() + } + self.wait(for: [signedOutDumpExpectationAfterCheckTrustStatus], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + self.assertNoAccount(context: self.cuttlefishContext) + } + + func testSignOutFromWaitForCDP() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + + // Turn off the CK account too + self.accountStatus = .noAccount + self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() + + XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "Should be no issue signing out") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + self.assertNoAccount(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .unknown, "CDP status should be 'unknown'") + } + + func testNoAccountTimeoutTransitionWatcher() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // With no identity and AuthKit reporting no iCloud account, Octagon should go directly into 'no account' + self.mockAuthKit.altDSID = nil + + self.cuttlefishContext.startOctagonStateMachine() + self.cuttlefishContext.stateMachine.setWatcherTimeout(2 * NSEC_PER_SEC) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(self.cuttlefishContext.stateMachine.isPaused(), "State machine should be stopped") + self.assertNoAccount(context: self.cuttlefishContext) + XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should be quiescent") + + let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") + self.cuttlefishContext.join(withBottle: "bottleID", entropy: Data(), bottleSalt: "peer2AltDSID") { error in + XCTAssertNotNil(error, "error should not be nil") + joinWithBottleExpectation.fulfill() + } + self.wait(for: [joinWithBottleExpectation], timeout: 3) + } +} + +#endif diff --git a/keychain/ot/tests/octagon/OctagonTests+CKKS.swift b/keychain/ot/tests/octagon/OctagonTests+CKKS.swift index d088ab71..9805ddb7 100644 --- a/keychain/ot/tests/octagon/OctagonTests+CKKS.swift +++ b/keychain/ot/tests/octagon/OctagonTests+CKKS.swift @@ -1,16 +1,73 @@ #if OCTAGON class OctagonCKKSTests: OctagonTestsBase { + var previousKeychainAccessGroups: [String]! + + override func setUp() { + // These tests would like to examine the behavior of a CKKS user-controlled-view + if self.mockDeviceInfo == nil { + let actualDeviceAdapter = OTDeviceInformationActualAdapter() + self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(), + deviceName: actualDeviceAdapter.deviceName(), + serialNumber: NSUUID().uuidString, + osVersion: actualDeviceAdapter.osVersion()) + } + + if self.mockDeviceInfo.mockModelID.contains("AppleTV") { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + ]) + } else { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + CKRecordZone.ID(zoneName: "Manatee"), + CKRecordZone.ID(zoneName: "Passwords"), + CKRecordZone.ID(zoneName: "SecureObjectSync"), + CKRecordZone.ID(zoneName: "Backstop"), + ]) + } + + super.setUp() + + XCTAssertTrue(self.cuttlefishContext.viewManager!.useCKKSViewsFromPolicy(), "CKKS should be configured to listen to policy-based views") + + // Allow ourselves to add safari items + self.previousKeychainAccessGroups = (SecAccessGroupsGetCurrent()?.takeUnretainedValue()) as? [String] + SecAccessGroupsSetCurrent((self.previousKeychainAccessGroups + ["com.apple.cfnetwork", "com.apple.sbd"]) as CFArray) + } + + override func tearDown() { + SecAccessGroupsSetCurrent(self.previousKeychainAccessGroups as CFArray) + super.tearDown() + } + + func testHandleSBDItemAddSort() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + #if os(tvOS) + // do not continue: TVs don't sync sos items. + #else + + self.expectCKModifyItemRecords(1, currentKeyPointerRecords: 1, zoneID: CKRecordZone.ID(zoneName: "SecureObjectSync")) + self.addGenericPassword("asdf", + account: "SBD-test", + accessGroup: "com.apple.sbd") + + self.verifyDatabaseMocks() + #endif // tvos test skip + } + func testHandleCKKSKeyHierarchyConflictOnEstablish() throws { self.startCKAccountStatusMock() // Right after CKKS fetches for the first time, insert a new key hierarchy into CloudKit self.silentFetchesAllowed = false - self.expectCKFetchAndRun(beforeFinished: { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + self.expectCKFetchAndRun { + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() self.silentFetchesAllowed = true - }) + } self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) @@ -37,12 +94,12 @@ class OctagonCKKSTests: OctagonTestsBase { // Right after CKKS fetches for the first time, insert a new key hierarchy into CloudKit self.silentFetchesAllowed = false - self.expectCKFetchAndRun(beforeFinished: { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.expectCKFetchAndRun { + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() + self.saveTLKMaterialToKeychain() self.silentFetchesAllowed = true - }) + } self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) @@ -64,6 +121,466 @@ class OctagonCKKSTests: OctagonTestsBase { self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) self.verifyDatabaseMocks() } + + func testUserControllableViewStatusAPI() throws { + self.startCKAccountStatusMock() + + let establishExpectation = self.expectation(description: "establish") + self.fakeCuttlefishServer.establishListener = { request in + XCTAssertTrue(request.peer.hasStableInfoAndSig, "updateTrust request should have a stableInfo info") + let newStableInfo = request.peer.stableInfoAndSig.stableInfo() + #if os(tvOS) || os(watchOS) + XCTAssertEqual(newStableInfo.syncUserControllableViews, .FOLLOWING, "User-controllable views should be 'following'") + #else + XCTAssertEqual(newStableInfo.syncUserControllableViews, .DISABLED, "User-controllable views should be disabled") + #endif + establishExpectation.fulfill() + return nil + } + + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + self.wait(for: [establishExpectation], timeout: 10) + self.fakeCuttlefishServer.establishListener = nil + + #if os(tvOS) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow") + + XCTAssertTrue(self.injectedManager?.policy?.syncUserControllableViewsAsBoolean() ?? false, "CKKS should be syncing user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + // Watches won't ever disable the user views, so the API should fail + XCTAssertThrowsError(try clique.setUserControllableViewsSyncStatus(false), "Should be an error setting user-visible sync status") + XCTAssertThrowsError(try clique.setUserControllableViewsSyncStatus(true), "Should be an error setting user-visible sync status") + + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow peer's opinions of sync user views") + XCTAssertTrue(self.injectedManager?.policy?.syncUserControllableViewsAsBoolean() ?? false, "CKKS should be syncing user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + #else + + #if !os(watchOS) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + + // And disabling it again doesn't write to the server + self.assertModifyUserViewsWithNoPeerUpdate(clique: clique, intendedSyncStatus: false) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + #else + // Watches, since some support this UI, and others don't, get special handling + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow") + XCTAssertTrue(self.injectedManager?.policy?.syncUserControllableViewsAsBoolean() ?? false, "CKKS should be syncing user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + self.assertModifyUserViews(clique: clique, intendedSyncStatus: false) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + #endif // watchOS + + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Manatee items should upload + self.expectCKModifyItemRecords(1, currentKeyPointerRecords: 1, zoneID: self.manateeZoneID) + self.addGenericPassword("asdf", account: "account-delete-me", viewHint: "Manatee") + self.verifyDatabaseMocks() + + // But Passwords items should not + self.addGenericPassword("asdf", + account: "account-apple.com", + access: kSecAttrAccessibleWhenUnlocked as String, + viewHint: nil, + accessGroup: "com.apple.cfnetwork", + expecting: errSecSuccess, + message: "Should be able to add a CFNetwork keychain item") + let passwordsView = self.injectedManager?.findView("Passwords") + XCTAssertNotNil(passwordsView, "Should have a passwords view") + passwordsView!.waitForOperations(of: CKKSOutgoingQueueOperation.self) + + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // And how about enabling it? That should upload the password + self.expectCKModifyItemRecords(1, currentKeyPointerRecords: 1, zoneID: self.passwordsZoneID) + self.assertModifyUserViews(clique: clique, intendedSyncStatus: true) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .ENABLED, "CKKS should be configured to sync user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + self.verifyDatabaseMocks() + + // And enabling it again doesn't write to the server + self.assertModifyUserViewsWithNoPeerUpdate(clique: clique, intendedSyncStatus: true) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .ENABLED, "CKKS should be configured to sync user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + // And we can turn it off again + self.assertModifyUserViews(clique: clique, intendedSyncStatus: false) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + #endif // !os(tvOS) + } + + func testJoinFollowsUserViewStatus() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) + // For tvs, this is always on + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + // Add a peer + let peer2Context = self.makeInitiatorContext(contextID: "peer2") + self.assertJoinViaEscrowRecovery(joiningContext: peer2Context, sponsor: self.cuttlefishContext) + + // The new peer should automatically have turned on user view syncing + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2Context), status: true) + + // TVs can't ever modify this value + let peer2Clique = self.cliqueFor(context: peer2Context) + XCTAssertThrowsError(try peer2Clique.setUserControllableViewsSyncStatus(false), "Should be an error setting user-visible sync status") + XCTAssertThrowsError(try peer2Clique.setUserControllableViewsSyncStatus(true), "Should be an error setting user-visible sync status") + self.assertFetchUserControllableViewsSyncStatus(clique: peer2Clique, status: true) + + #elseif os(watchOS) + // Watches are following by default. Turn the status off for the rest of the test + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow") + + self.assertModifyUserViews(clique: clique, intendedSyncStatus: false) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + + // Add a peer + let peer2Context = self.makeInitiatorContext(contextID: "peer2") + self.assertJoinViaEscrowRecovery(joiningContext: peer2Context, sponsor: self.cuttlefishContext) + + // A new watch peer will be FOLLOWING, so this API will return true + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2Context), status: true) + + #else // iOS, macOS + + // By default, the sync status is "off" + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Add a peer + let peer2Context = self.makeInitiatorContext(contextID: "peer2") + self.assertJoinViaEscrowRecovery(joiningContext: peer2Context, sponsor: self.cuttlefishContext) + + // The new peer should automatically have disabled syncing + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2Context), status: false) + + self.assertModifyUserViews(clique: self.cliqueFor(context: peer2Context), intendedSyncStatus: true) + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2Context), status: true) + #endif // iOS, macOS + + // And a third peer joins! + let peer3Context = self.makeInitiatorContext(contextID: "peer3", authKitAdapter: self.mockAuthKit3) + self.assertJoinViaEscrowRecovery(joiningContext: peer3Context, sponsor: peer2Context) + + #if os(tvOS) || os(watchOS) + // Watches and TVs won't ever turn this off (without extra UI), so a freshly joined peer will report this status as true + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer3Context), status: true) + #else + // Peer3, by default, should have disabled the user controllable views (following peer1) + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer3Context), status: false) + #endif + } + + func testUpgradePeerToHaveUserSyncableViewsOpinionViaAskingSOS() throws { + self.mockSOSAdapter.safariViewEnabled = true + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) || os(watchOS) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + // Now, fake that the peer no longer has this opinion: + do { + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, + context: self.cuttlefishContext.contextID) + + let (_, newSyncingPolicy, updateError) = container.updateSync(test: self, + syncUserControllableViews: .UNKNOWN) + XCTAssertNil(updateError, "Should be no error performing update") + XCTAssertNotNil(newSyncingPolicy, "Should have a syncing policy") + XCTAssertEqual(newSyncingPolicy?.syncUserControllableViews, .UNKNOWN, "Should now have 'unknown' user controlled views setting") + + self.injectedManager?.setCurrentSyncingPolicy(newSyncingPolicy) + + try self.cuttlefishContext.accountMetadataStore.persistAccountChanges { metadata in + metadata.setTPSyncingPolicy(newSyncingPolicy) + return metadata + } + } + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Upon daemon restart, Octagon should notice and update its opinion + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + #if os(tvOS) || os(watchOS) + XCTAssertEqual(newStableInfo.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow peer's user views") + #else + XCTAssertEqual(newStableInfo.syncUserControllableViews, .ENABLED, "CKKS should be configured to sync user views (following SOS's lead)") + #endif + updateTrustExpectation.fulfill() + return nil + } + + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + self.wait(for: [updateTrustExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should pause") + } + + func testUpgradePeerToHaveUserSyncableViewsOpinionViaPeersOpinion() throws { + self.mockSOSAdapter.sosEnabled = false + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) || os(watchOS) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + // Now, fake that the peer no longer has this opinion: + do { + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, + context: self.cuttlefishContext.contextID) + + let (_, newSyncingPolicy, updateError) = container.updateSync(test: self, + syncUserControllableViews: .UNKNOWN) + XCTAssertNil(updateError, "Should be no error performing update") + XCTAssertNotNil(newSyncingPolicy, "Should have a syncing policy") + XCTAssertEqual(newSyncingPolicy?.syncUserControllableViews, .UNKNOWN, "Should now have 'unknown' user controlled views setting") + + self.injectedManager?.setCurrentSyncingPolicy(newSyncingPolicy) + + try self.cuttlefishContext.accountMetadataStore.persistAccountChanges { metadata in + metadata.setTPSyncingPolicy(newSyncingPolicy) + return metadata + } + } + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Upon daemon restart, Octagon should notice and update its opinion + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + #if os(tvOS) || os(watchOS) + XCTAssertEqual(newStableInfo.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow peer's user views") + #else + XCTAssertEqual(newStableInfo.syncUserControllableViews, .DISABLED, "CKKS should be configured to disable user views, since no peers have it actively enabled") + #endif + updateTrustExpectation.fulfill() + return nil + } + + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + self.wait(for: [updateTrustExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should pause") + } + + func testUpgradePeerToHaveUserSyncableViewsOpinionWhileLocked() throws { + self.mockSOSAdapter.safariViewEnabled = true + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) || os(watchOS) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + // Now, fake that the peer no longer has this opinion: + do { + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, + context: self.cuttlefishContext.contextID) + + let (_, newSyncingPolicy, updateError) = container.updateSync(test: self, + syncUserControllableViews: .UNKNOWN) + XCTAssertNil(updateError, "Should be no error performing update") + XCTAssertNotNil(newSyncingPolicy, "Should have a syncing policy") + XCTAssertEqual(newSyncingPolicy?.syncUserControllableViews, .UNKNOWN, "Should now have 'unknown' user controlled views setting") + + self.injectedManager?.setCurrentSyncingPolicy(newSyncingPolicy) + + try self.cuttlefishContext.accountMetadataStore.persistAccountChanges { metadata in + metadata.setTPSyncingPolicy(newSyncingPolicy) + return metadata + } + } + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Upon daemon restart, Octagon should notice and update its opinion + + self.aksLockState = true + self.lockStateTracker.recheck() + + self.fakeCuttlefishServer.updateListener = { _ in + XCTFail("No update should happen while the device is locked") + return nil + } + + // We should get to 'wait for unlock' + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 100 * NSEC_PER_SEC) + + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + #if os(tvOS) || os(watchOS) + XCTAssertEqual(newStableInfo.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow peer's user views") + #else + XCTAssertEqual(newStableInfo.syncUserControllableViews, .ENABLED, "CKKS should be configured to sync user views (following SOS's lead)") + #endif + updateTrustExpectation.fulfill() + return nil + } + + // and once we unlock, the update should go through + self.aksLockState = false + self.lockStateTracker.recheck() + + self.wait(for: [updateTrustExpectation], timeout: 10) + } + + func testHandleFailureUpgradingPeerToHaveUserSyncableViewsOpinion() throws { + self.mockSOSAdapter.safariViewEnabled = true + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) || os(watchOS) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + // Now, fake that the peer no longer has this opinion: + do { + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, + context: self.cuttlefishContext.contextID) + + let (_, newSyncingPolicy, updateError) = container.updateSync(test: self, + syncUserControllableViews: .UNKNOWN) + XCTAssertNil(updateError, "Should be no error performing update") + XCTAssertNotNil(newSyncingPolicy, "Should have a syncing policy") + XCTAssertEqual(newSyncingPolicy?.syncUserControllableViews, .UNKNOWN, "Should now have 'unknown' user controlled views setting") + + self.injectedManager?.setCurrentSyncingPolicy(newSyncingPolicy) + + try self.cuttlefishContext.accountMetadataStore.persistAccountChanges { metadata in + metadata.setTPSyncingPolicy(newSyncingPolicy) + return metadata + } + } + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Upon daemon restart, Octagon should notice and attempt to update its opinion + // But, that fails the first time + let fastUpdateTrustExpectation = self.expectation(description: "fast updateTrust") + let retriedUpdateTrustExpectation = self.expectation(description: "retried updateTrust") + let restartAt = Date() + + self.fakeCuttlefishServer.updateListener = { _ in + let now = Date() + + // Entering this block twice will fail the test. + // The rate limiter in OTCuttlefishContext is set to retry after 10seconds, + // so 7s was chosen to allow for some slop in timing/slow restarts. + // If update() is called twice within 7s, the test will fail. + if restartAt.distance(to: now) < 7 { + fastUpdateTrustExpectation.fulfill() + return FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .testGeneratedFailure) + } else { + retriedUpdateTrustExpectation.fulfill() + return nil; + } + } + + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + self.wait(for: [fastUpdateTrustExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should pause") + + self.wait(for: [retriedUpdateTrustExpectation], timeout: 20) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should pause") + } + + func testAssistCKKSTLKUploadWhenMissingFromOctagon() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + // Another peer resets Octagon, but we miss the push + let reset = self.makeInitiatorContext(contextID: "reset") + self.assertResetAndBecomeTrusted(context: reset) + + // This should cause the original peer to notice that it's no longer trusted + self.silentZoneDeletesAllowed = true + self.resetAllCKKSViews() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 100 * NSEC_PER_SEC) + } + + func testFetchUserControllableViewsSyncingStatusNoAccount() throws { + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitingForCloudKitAccount, within: 10 * NSEC_PER_SEC) + + let fetchExpectation = self.expectation(description: "fetch user controllable views syncing status returns") + self.cuttlefishContext.rpcFetchUserControllableViewsSyncingStatus { isSyncing, error in + XCTAssertNotNil(error, "error should not be nil") + XCTAssertFalse(isSyncing, "should not be syncing with no account") + fetchExpectation.fulfill() + } + self.wait(for: [fetchExpectation], timeout: 10) + } + + func testSignInWithDelayedHSA2StatusAndAttemptFetchUserControllableViewsSyncingStatus() throws { + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // Device is signed out + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + // Sign in occurs, but HSA2 status isn't here yet + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + // Octagon should go into 'waitforhsa2' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForHSA2, within: 10 * NSEC_PER_SEC) + + let fetchExpectation = self.expectation(description: "fetch user controllable views syncing status returns") + self.cuttlefishContext.rpcFetchUserControllableViewsSyncingStatus { isSyncing, error in + XCTAssertNil(error, "error should be nil") + XCTAssertFalse(isSyncing, "should not be syncing with non hsa2 account") + fetchExpectation.fulfill() + } + self.wait(for: [fetchExpectation], timeout: 2) + } + } #endif // OCTAGON diff --git a/keychain/ot/tests/octagon/OctagonTests+CKKSConfiguration.swift b/keychain/ot/tests/octagon/OctagonTests+CKKSConfiguration.swift new file mode 100644 index 00000000..5cad6bd4 --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonTests+CKKSConfiguration.swift @@ -0,0 +1,142 @@ +import Foundation + +class OctagonCKKSConfigurationTestsPolicyDisabled: OctagonTestsBase { + // Pre-configure some things, so the OctagonTests will only operate on these views + override func setUp() { + if self.mockDeviceInfo == nil { + let actualDeviceAdapter = OTDeviceInformationActualAdapter() + self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(), + deviceName: actualDeviceAdapter.deviceName(), + serialNumber: NSUUID().uuidString, + osVersion: actualDeviceAdapter.osVersion()) + } + + // With the policy disabled, we only want to operate on a few zones + if self.mockDeviceInfo.mockModelID.contains("AppleTV") { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + ]) + } else { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + CKRecordZone.ID(zoneName: "Manatee"), + ]) + } + + self.setCKKSViewsFromPolicyToNo = true + + super.setUp() + + XCTAssertFalse(self.cuttlefishContext.viewManager!.useCKKSViewsFromPolicy(), "CKKS should not be configured to listen to policy-based views") + } + + func testMergedViewListOff() throws { + XCTAssertFalse(self.cuttlefishContext.viewManager!.useCKKSViewsFromPolicy(), "CKKS should not be configured to listen to policy-based views") + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + let viewList = self.cuttlefishContext.viewManager!.viewList() + #if !os(tvOS) + let expected = Set(["Manatee", "LimitedPeersAllowed"]) + #else + let expected = Set(["LimitedPeersAllowed"]) + #endif + XCTAssertEqual(expected, viewList) + } +} + +class OctagonCKKSConfigurationTestsPolicyEnabled: OctagonTestsBase { + override func setUp() { + if self.mockDeviceInfo == nil { + let actualDeviceAdapter = OTDeviceInformationActualAdapter() + self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(), + deviceName: actualDeviceAdapter.deviceName(), + serialNumber: NSUUID().uuidString, + osVersion: actualDeviceAdapter.osVersion()) + } + + // Most tests will use a much smaller list of views. But not us! Go wild! + if self.mockDeviceInfo.mockModelID.contains("AppleTV") { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "Home"), + self.limitedPeersAllowedZoneID!, + CKRecordZone.ID(zoneName: "WiFi"), + ]) + } else { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "ApplePay"), + CKRecordZone.ID(zoneName: "Applications"), + CKRecordZone.ID(zoneName: "AutoUnlock"), + CKRecordZone.ID(zoneName: "Backstop"), + CKRecordZone.ID(zoneName: "CreditCards"), + CKRecordZone.ID(zoneName: "DevicePairing"), + CKRecordZone.ID(zoneName: "Engram"), + CKRecordZone.ID(zoneName: "Health"), + CKRecordZone.ID(zoneName: "Home"), + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + CKRecordZone.ID(zoneName: "Manatee"), + CKRecordZone.ID(zoneName: "Passwords"), + CKRecordZone.ID(zoneName: "ProtectedCloudStorage"), + CKRecordZone.ID(zoneName: "SecureObjectSync"), + CKRecordZone.ID(zoneName: "WiFi"), + ]) + } + + super.setUp() + } + + func testMergedViewListOn() throws { + XCTAssertTrue(self.cuttlefishContext.viewManager!.useCKKSViewsFromPolicy(), "CKKS should be configured to listen to policy-based views") + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + let viewList = self.cuttlefishContext.viewManager!.viewList() + + #if !os(tvOS) + let expected = Set([ + "ApplePay", + "Applications", + "AutoUnlock", + "Backstop", + "CreditCards", + "DevicePairing", + "Engram", + "Health", + "Home", + "LimitedPeersAllowed", + "Manatee", + "Passwords", + "ProtectedCloudStorage", + "SecureObjectSync", + "WiFi", + ]) + #else + let expected = Set(["LimitedPeersAllowed", + "Home", + "WiFi", ]) + #endif + XCTAssertEqual(expected, viewList) + } + + func testPolicyResetRPC() throws { + XCTAssertTrue(self.cuttlefishContext.viewManager!.useCKKSViewsFromPolicy(), "CKKS should be configured to listen to policy-based views") + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + XCTAssertNotNil(self.injectedManager?.policy, "Should have given CKKS a TPPolicy during initialization") + XCTAssertEqual(self.injectedManager?.policy?.version, prevailingPolicyVersion, "Policy given to CKKS should be prevailing policy") + + self.injectedManager!.resetSyncingPolicy() + XCTAssertNil(self.injectedManager?.policy, "CKKS policy should be reset (by the test)") + + self.otControl.refetchCKKSPolicy(nil, contextID: self.cuttlefishContext.contextID) { error in + XCTAssertNil(error, "Should be no error refetching the CKKS policy") + } + + XCTAssertNotNil(self.injectedManager?.policy, "Should have given CKKS a TPPolicy during refetch") + XCTAssertEqual(self.injectedManager?.policy?.version, prevailingPolicyVersion, "Policy given to CKKS should be prevailing policy") + } +} diff --git a/keychain/ot/tests/octagon/OctagonTests+CloudKitAccount.swift b/keychain/ot/tests/octagon/OctagonTests+CloudKitAccount.swift index 5a43ca54..812520c6 100644 --- a/keychain/ot/tests/octagon/OctagonTests+CloudKitAccount.swift +++ b/keychain/ot/tests/octagon/OctagonTests+CloudKitAccount.swift @@ -10,6 +10,9 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.startCKAccountStatusMock() self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + // With no account, Octagon should go directly into 'NoAccount' self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) @@ -19,9 +22,9 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.mockAuthKit.altDSID = newAltDSID XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") - // We should reach 'untrusted', as we cached the CK value - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + // We should reach 'waitforcdp', as we cached the CK value + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) } func testSignInPausesForCloudKit() throws { @@ -32,12 +35,15 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.accountStatus = .noAccount self.startCKAccountStatusMock() + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + // With no account, Octagon should go directly into 'NoAccount' self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - // And CKKS should be in 'loggedout' - assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + // And CKKS shouldn't be spun up + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views before CK login") // Account sign in occurs let newAltDSID = UUID().uuidString @@ -48,10 +54,16 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitingForCloudKitAccount, within: 10 * NSEC_PER_SEC) assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) - // And when CK shows up, we should go into 'untrusted' + // And when CK shows up, we should go into 'waitforcdp' self.accountStatus = .available self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) + + // And then CDP is set to be on + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) @@ -108,6 +120,9 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.accountStatus = .noAccount self.startCKAccountStatusMock() + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + // With no account, Octagon should go directly into 'NoAccount' self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) @@ -120,10 +135,16 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { // Octagon should go into 'wait for cloudkit account' self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitingForCloudKitAccount, within: 10 * NSEC_PER_SEC) - // And when CK shows up, we should go into 'untrusted' + // And when CK shows up, we should go into 'waitforcdp' self.accountStatus = .available self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) + + // and then, when CDP tells us, we should go into 'untrusted' + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) @@ -167,7 +188,7 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForHSA2, within: 10 * NSEC_PER_SEC) self.assertNoAccount(context: self.cuttlefishContext) - self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views in an SA account") // On CK account sign-out, Octagon should stay in 'wait for hsa2': if there's no HSA2, we don't actually care about the CK account status self.accountStatus = .noAccount @@ -181,7 +202,7 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) self.assertNoAccount(context: self.cuttlefishContext) - self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views in an SA account") } func testSAtoHSA2PromotionWithoutCloudKit() throws { @@ -194,6 +215,68 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.accountStatus = .noAccount self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + // Account signs in as SA. + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + + XCTAssertNoThrow(try self.cuttlefishContext.idmsTrustLevelChanged(), "Notification of IDMS trust level shouldn't error") + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForHSA2, within: 10 * NSEC_PER_SEC) + self.assertNoAccount(context: self.cuttlefishContext) + + // Account promotes to HSA2 + self.mockAuthKit.hsa2 = true + XCTAssertNoThrow(try self.cuttlefishContext.idmsTrustLevelChanged(), "Notification of IDMS trust level shouldn't error") + + // Octagon should go into 'waitforcloudkit' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitingForCloudKitAccount, within: 10 * NSEC_PER_SEC) + self.assertAccountAvailable(context: self.cuttlefishContext) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + + // On CK account sign-in, Octagon should race to 'waitforcdp' + self.accountStatus = .available + self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfWaitingForCDP(context: self.cuttlefishContext) + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + + // On sign-out, octagon should go back to 'no account' + self.mockAuthKit.altDSID = nil + XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "sign-out shouldn't error") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + self.assertNoAccount(context: self.cuttlefishContext) + + // But CKKS is listening for the CK account removal, not the accountNoLongerAvailable call + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + + self.accountStatus = .noAccount + self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + } + + func testSAtoHSA2PromotionandCDPWithoutCloudKit() throws { + self.startCKAccountStatusMock() + + // Device is signed out + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + self.accountStatus = .noAccount + self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() + // With no account, Octagon should go directly into 'NoAccount' self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) @@ -218,6 +301,10 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + // And setting CDP bit now should be successful, but not move the state machine + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitingForCloudKitAccount, within: 10 * NSEC_PER_SEC) + // On CK account sign-in, Octagon should race to 'untrusted' self.accountStatus = .available self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() @@ -264,15 +351,138 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { let statusexpectation = self.expectation(description: "trust status returns") let configuration = OTOperationConfiguration() configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _ in + self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, error in XCTAssertEqual(.noCloudKitAccount, egoStatus, "cliqueStatus should be 'no cloudkit account'") + XCTAssertNil(error, "should have no error fetching status") statusexpectation.fulfill() } self.wait(for: [statusexpectation], timeout: 10) self.assertNoAccount(context: self.cuttlefishContext) + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views") + } + + func testStatusRPCsWithUnknownCloudKitAccount() throws { + // If CloudKit isn't returning our calls, we should still return something reasonable... + let statusexpectation = self.expectation(description: "trust status returns") + let configuration = OTOperationConfiguration() + configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC + self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, _ in + XCTAssertTrue([.absent].contains(egoStatus), "Self peer should be in the 'absent' state") + statusexpectation.fulfill() + } + self.wait(for: [statusexpectation], timeout: 10) + + // Now sign in to 'untrusted' + self.startCKAccountStatusMock() + + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + // And restart, without any idea of the cloudkit state + self.ckaccountHoldOperation = BlockOperation() + self.manager.accountStateTracker = CKKSAccountStateTracker(self.manager.cloudKitContainer, + nsnotificationCenterClass: FakeNSNotificationCenter.self as CKKSNSNotificationCenter.Type) + self.injectedManager!.accountTracker = self.manager.accountStateTracker + + self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + self.restartCKKSViews() + self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + + // Should know it's untrusted + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + self.startCKAccountStatusMock() + + // Now become ready + do { + let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + } + + // Now, we should be in 'ready' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) + + // and all subCKKSes should enter ready... + assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // Restart one more time: + + self.ckaccountHoldOperation = BlockOperation() + self.manager.accountStateTracker = CKKSAccountStateTracker(self.manager.cloudKitContainer, + nsnotificationCenterClass: FakeNSNotificationCenter.self as CKKSNSNotificationCenter.Type) + self.injectedManager!.accountTracker = self.manager.accountStateTracker + + self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + self.restartCKKSViews() + self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) + + // Let Octagon know about the account status, so test teardown is fast + self.startCKAccountStatusMock() + } + + func testReceiveOctagonAPICallBeforeCKAccountNotification() throws { + // Device is signed out of everything + self.mockAuthKit.altDSID = nil + self.accountStatus = .noAccount + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views before CK login") + + // Account sign in occurs + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + // Octagon should go into 'wait for cloudkit account' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitingForCloudKitAccount, within: 10 * NSEC_PER_SEC) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + + // RPCs should fail, since CK is not present + let fetchViableFailureExpectation = self.expectation(description: "fetchViableBottles callback occurs") + self.cuttlefishContext.rpcFetchAllViableBottles { _, _, error in + XCTAssertNotNil(error, "should be an error fetching viable bottles before CK is ready") + + if let nserror = error as NSError? { + XCTAssertEqual(nserror.domain, OctagonErrorDomain, "Error should be from correct domain") + XCTAssertEqual(nserror.code, OctagonError.OTErrorNotSignedIn.rawValue, "Error should indicate no account present") + } else { + XCTFail("Unable to convert error to nserror") + } + fetchViableFailureExpectation.fulfill() + } + self.wait(for: [fetchViableFailureExpectation], timeout: 10) + + // CK signs in, but we aren't yet notified about it + self.accountStatus = .available + + // RPCs should cause Octagon to recheck the CK account status and wake up + // In particular, fetching all viable bottles should succeed, instead of erroring with 'no CK account' + let fetchViableExpectation = self.expectation(description: "fetchViableBottles callback occurs") + self.cuttlefishContext.rpcFetchAllViableBottles { _, _, error in + XCTAssertNil(error, "should be no error fetching viable bottles") + fetchViableExpectation.fulfill() + } + self.wait(for: [fetchViableExpectation], timeout: 10) + + // With no SOS and no CDP, Octagon should wait for enablement + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) } } diff --git a/keychain/ot/tests/octagon/OctagonTests+CoreFollowUp.swift b/keychain/ot/tests/octagon/OctagonTests+CoreFollowUp.swift index c2692037..810b8e41 100644 --- a/keychain/ot/tests/octagon/OctagonTests+CoreFollowUp.swift +++ b/keychain/ot/tests/octagon/OctagonTests+CoreFollowUp.swift @@ -16,14 +16,15 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { machineID: "asdf", bottleSalt: "123456789", bottleID: UUID().uuidString, - modelID: "asdf", + modelID: "iPhone9,1", deviceName: "asdf", serialNumber: "1234", osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -44,8 +45,9 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { XCTAssertNoThrow(try account.saveToKeychain(forContainer: containerName, contextID: contextName), "Should be no error saving fake account metadata") - OctagonInitialize() + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) @@ -53,10 +55,10 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) #if !os(tvOS) - XCTAssertTrue(self.cuttlefishContext.postedRepairCFU, "should have posted an repair CFU") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should have posted an repair CFU") #else // Apple TV should not post a CFU, as there's no peers to join - XCTAssertFalse(self.cuttlefishContext.postedRepairCFU, "appleTV should not have posted a repair CFU") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "appleTV should not have posted a repair CFU") #endif } @@ -78,14 +80,15 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { machineID: "asdf", bottleSalt: "123456789", bottleID: UUID().uuidString, - modelID: "asdf", + modelID: "iPhone9,1", deviceName: "asdf", serialNumber: "1234", osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -106,8 +109,9 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { XCTAssertNoThrow(try account.saveToKeychain(forContainer: containerName, contextID: contextName), "Should be no error saving fake account metadata") - OctagonInitialize() + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) @@ -116,17 +120,19 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { // Since SOS isn't around to help, Octagon should post a CFU #if os(tvOS) - XCTAssertEqual(self.cuttlefishContext.postedRepairCFU, false, "Should not have posted a CFU on aTV (due to having no peers to join)") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should not have posted a CFU on aTV (due to having no peers to join)") #else - XCTAssertTrue(self.cuttlefishContext.postedRepairCFU, "should have posted an repair CFU, as SOS can't help") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should have posted an repair CFU, as SOS can't help") #endif } func testAttemptedJoinNotAttemptedStateSOSError() throws { self.startCKAccountStatusMock() + // Note that some errors mean "out of circle", so use NotReady here to avoid that self.mockSOSAdapter.sosEnabled = true self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCError) + self.mockSOSAdapter.circleStatusError = NSError(domain: kSOSErrorDomain as String, code: kSOSErrorNotReady, userInfo: nil) // Prepare an identity, then pretend like securityd thought it was in the right account let containerName = OTCKContainerName @@ -140,14 +146,15 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { machineID: "asdf", bottleSalt: "123456789", bottleID: UUID().uuidString, - modelID: "asdf", + modelID: "iPhone9,1", deviceName: "asdf", serialNumber: "1234", osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -168,8 +175,9 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { XCTAssertNoThrow(try account.saveToKeychain(forContainer: containerName, contextID: contextName), "Should be no error saving fake account metadata") - OctagonInitialize() + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) @@ -177,7 +185,7 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) // Since SOS is in 'error', octagon shouldn't post until SOS can say y/n - XCTAssertFalse(self.cuttlefishContext.postedRepairCFU, "should NOT have posted an repair CFU") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should NOT have posted an repair CFU") } func testAttemptedJoinNotAttemptedStateSOSDisabled() throws { @@ -188,6 +196,7 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { // No need to mock not joining; Octagon won't have attempted a join if we just start it self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) @@ -195,10 +204,10 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) #if !os(tvOS) - XCTAssertTrue(self.cuttlefishContext.postedRepairCFU, "should have posted an repair CFU, as SOS is disabled") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should have posted an repair CFU, as SOS is disabled") #else // Apple TV should not post a CFU, as there's no peers to join - XCTAssertFalse(self.cuttlefishContext.postedRepairCFU, "appleTV should not have posted a repair CFU") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "appleTV should not have posted a repair CFU") #endif } @@ -217,14 +226,15 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { machineID: "asdf", bottleSalt: "123456789", bottleID: UUID().uuidString, - modelID: "asdf", + modelID: "iPhone9,1", deviceName: "asdf", serialNumber: "1234", osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -245,8 +255,9 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { XCTAssertNoThrow(try account.saveToKeychain(forContainer: containerName, contextID: contextName), "Should be no error saving fake account metadata") - OctagonInitialize() + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) @@ -254,10 +265,10 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) #if !os(tvOS) - XCTAssertTrue(self.cuttlefishContext.postedRepairCFU, "should have posted an repair CFU") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should have posted an repair CFU") #else // Apple TV should not post a CFU, as there's no peers to join - XCTAssertFalse(self.cuttlefishContext.postedRepairCFU, "appleTV should not have posted a repair CFU") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "appleTV should not have posted a repair CFU") #endif } @@ -268,12 +279,13 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { self.mockSOSAdapter.sosEnabled = false self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) // Apple TV should not post a CFU, as there's no peers to join - XCTAssertFalse(self.cuttlefishContext.postedRepairCFU, "appleTV should not have posted a repair CFU") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "appleTV should not have posted a repair CFU") // Now, an iphone appears! let iphone = self.manager.context(forContainerName: OTCKContainerName, @@ -296,7 +308,7 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { // The TV should now post a CFU, as there's an iphone that can repair it self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - XCTAssertTrue(self.cuttlefishContext.postedRepairCFU, "appleTV should have posted a repair CFU") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "appleTV should have posted a repair CFU") } func testDontPostCFUWhenApprovalIncapablePeerJoins() throws { @@ -305,21 +317,22 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { self.mockSOSAdapter.sosEnabled = false self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) // Apple TV should not post a CFU, as there's no peers to join - XCTAssertFalse(self.cuttlefishContext.postedRepairCFU, "appleTV should not have posted a repair CFU") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "appleTV should not have posted a repair CFU") // Now, a mac appears! macs cannot fix apple TVs. let mac = self.manager.context(forContainerName: OTCKContainerName, - contextID: "asdf", - sosAdapter: self.mockSOSAdapter, - authKitAdapter: self.mockAuthKit2, - lockStateTracker: self.lockStateTracker, - accountStateTracker: self.accountStateTracker, - deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iMac7,1", deviceName: "test-mac", serialNumber: "456", osVersion: "macOS (fake version)")) + contextID: "asdf", + sosAdapter: self.mockSOSAdapter, + authKitAdapter: self.mockAuthKit2, + lockStateTracker: self.lockStateTracker, + accountStateTracker: self.accountStateTracker, + deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iMac7,1", deviceName: "test-mac", serialNumber: "456", osVersion: "macOS (fake version)")) mac.startOctagonStateMachine() let resetAndEstablishExpectation = self.expectation(description: "resetAndEstablishExpectation returns") @@ -333,7 +346,7 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { // The TV should not post a CFU, as there's still no iPhone to repair it self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - XCTAssertFalse(self.cuttlefishContext.postedRepairCFU, "appleTV should not have posted a repair CFU; no devices present can repair it") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "appleTV should not have posted a repair CFU; no devices present can repair it") } func testDontPostCFUWhenCapablePeersAreUntrusted() throws { @@ -373,6 +386,7 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { "iphone should distrust itself") self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) // Ensure that the aTV has fetched properly @@ -382,7 +396,7 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) // Apple TV should not post a CFU, as the only iPhone around is untrusted - XCTAssertFalse(self.cuttlefishContext.postedRepairCFU, "appleTV should not have posted a repair CFU") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "appleTV should not have posted a repair CFU") // Another iPhone resets the world let iphone2 = self.manager.context(forContainerName: OTCKContainerName, @@ -403,7 +417,7 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { // The aTV is notified, and now posts a CFU self.sendContainerChangeWaitForUntrustedFetch(context: self.cuttlefishContext) - XCTAssertTrue(self.cuttlefishContext.postedRepairCFU, "appleTV should have posted a repair CFU") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "appleTV should have posted a repair CFU") } #endif @@ -413,14 +427,15 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCNotInCircle) self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) #if os(tvOS) - XCTAssertEqual(self.cuttlefishContext.postedRepairCFU, false, "Should not have posted a CFU on aTV (due to having no peers to join)") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should not have posted a CFU on aTV (due to having no peers to join)") #else - XCTAssertTrue(self.cuttlefishContext.postedRepairCFU, "should have posted an repair CFU, as SOS can't help") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should have posted an repair CFU, as SOS can't help") #endif } } diff --git a/keychain/ot/tests/octagon/OctagonTests+DeviceList.swift b/keychain/ot/tests/octagon/OctagonTests+DeviceList.swift index 848bb213..6bb1262a 100644 --- a/keychain/ot/tests/octagon/OctagonTests+DeviceList.swift +++ b/keychain/ot/tests/octagon/OctagonTests+DeviceList.swift @@ -35,6 +35,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.startCKAccountStatusMock() self.mockAuthKit.excludeDevices.formUnion(self.mockAuthKit.currentDeviceList()) + self.mockAuthKit.isDemoAccount = true XCTAssertTrue(self.mockAuthKit.currentDeviceList().isEmpty, "should have zero devices") self.cuttlefishContext.startOctagonStateMachine() @@ -79,7 +80,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // Then peer2 drops off the device list. Peer 1 should distrust peer2. let updateTrustExpectation = self.expectation(description: "updateTrust") @@ -101,7 +102,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .excludes, target: peer2ID)), - "peer 1 should distrust peer 2 after update") + "peer 1 should distrust peer 2 after update") } func testNumberOfPeersInModel() throws { @@ -116,15 +117,13 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() do { - let number = try self.cuttlefishContext.numberOfPeersInModel(withMachineID: self.mockAuthKit.currentMachineID) - XCTAssertEqual(number.intValue, 1, "Should have a one peer for numberOfPeersInModel after an initial join") - } catch { - XCTFail("Should not have failed fetching the number of peers with a mid: \(error)") - } + let egoPeerStatus = try self.cuttlefishContext.egoPeerStatus() - do { - let number = try self.cuttlefishContext.numberOfPeersInModel(withMachineID: "not-a-real-machine-id") - XCTAssertEqual(number.intValue, 0, "Should have a zero peers for an invalid MID") + let numberOfPeersWithMID = egoPeerStatus.peerCountsByMachineID[self.mockAuthKit.currentMachineID] ?? NSNumber(0) + XCTAssertEqual(numberOfPeersWithMID.intValue, 1, "Should have a one peer for the current MID after an initial join") + + let numberOfPeersWithInvalidMID = egoPeerStatus.peerCountsByMachineID["not-a-real-machine-id"] + XCTAssertNil(numberOfPeersWithInvalidMID, "Should have a zero peers for an invalid MID") } catch { XCTFail("Should not have failed fetching the number of peers with a mid: \(error)") } @@ -147,7 +146,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // Then peer2 drops off the device list. Peer 1 should distrust peer2. let updateTrustExpectation = self.expectation(description: "updateTrust") @@ -193,7 +192,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") self.assertMIDList(context: self.cuttlefishContext, allowed: self.mockAuthKit.currentDeviceList(), disallowed: Set(), @@ -230,7 +229,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") } func testRemoveSelfWhenRemovedFromOnlySelfList() throws { @@ -244,26 +243,17 @@ class OctagonDeviceListTests: OctagonTestsBase { "peer 1 should trust peer 1") // Then peer1 drops off the device list - // It should remove trust in itself - let updateTrustExpectation = self.expectation(description: "updateTrust") + // It should _not_ remove trust in itself, as it's the only peer around self.fakeCuttlefishServer.updateListener = { request in - XCTAssertTrue(request.hasDynamicInfoAndSig, "updateTrust request should have a dynamic info") - let newDynamicInfo = TPPeerDynamicInfo(data: request.dynamicInfoAndSig.peerDynamicInfo, - sig: request.dynamicInfoAndSig.sig) - XCTAssertNotNil(newDynamicInfo, "should be able to make a dynamic info from protobuf") - - XCTAssertEqual(newDynamicInfo!.includedPeerIDs.count, 0, "peer1 should no longer trust anyone") - XCTAssertEqual(newDynamicInfo!.excludedPeerIDs, Set([peer1ID]), "peer1 should exclude itself") - updateTrustExpectation.fulfill() + XCTFail("Should not have updatedTrust") return nil } self.mockAuthKit.removeAndSendNotification(machineID: try! self.mockAuthKit.machineID()) - self.wait(for: [updateTrustExpectation], timeout: 10) - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } func testRemoveSelfWhenRemovedFromLargeDeviceList() throws { @@ -275,8 +265,11 @@ class OctagonDeviceListTests: OctagonTestsBase { XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer1ID)), "peer 1 should trust peer 1") + let joiningContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit2) + self.assertJoinViaEscrowRecoveryFromDefaultContextWithReciprocationAndTLKShares(joiningContext: joiningContext) + // Then peer1 drops off the device list - // It should remove trust in itself + // It should remove trust in itself, as joiner is still around let updateTrustExpectation = self.expectation(description: "updateTrust") self.fakeCuttlefishServer.updateListener = { request in XCTAssertTrue(request.hasDynamicInfoAndSig, "updateTrust request should have a dynamic info") @@ -307,6 +300,9 @@ class OctagonDeviceListTests: OctagonTestsBase { XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer1ID)), "peer 1 should trust peer 1") + let joiningContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit2) + self.assertJoinViaEscrowRecoveryFromDefaultContextWithReciprocationAndTLKShares(joiningContext: joiningContext) + // Then peer1 drops off the device list // It should remove trust in itself let updateTrustExpectation = self.expectation(description: "updateTrust") @@ -350,7 +346,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // We receive a 'remove' push for peer2's ID, but for the wrong DSID. The peer should do nothing useful. self.fakeCuttlefishServer.updateListener = { request in @@ -364,7 +360,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") self.assertMIDList(context: self.cuttlefishContext, allowed: self.mockAuthKit.currentDeviceList(), @@ -389,7 +385,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // We receive a 'add' push for a new ID, but for the wrong DSID. The peer should do nothing useful. self.fakeCuttlefishServer.updateListener = { request in @@ -404,7 +400,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // newMachineID should be on no lists self.assertMIDList(context: self.cuttlefishContext, @@ -450,13 +446,12 @@ class OctagonDeviceListTests: OctagonTestsBase { let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) container.moc.performAndWait { var foundPeer2 = false - for machinemo in container.containerMO.machines as? Set ?? Set() { - if machinemo.machineID == self.mockAuthKit2.currentMachineID { + for machinemo in container.containerMO.machines as? Set ?? Set() + where machinemo.machineID == self.mockAuthKit2.currentMachineID { foundPeer2 = true // machinemo.modified = Date(timeIntervalSinceNow: -60 * 60 * TimeInterval(72)) XCTAssertEqual(machinemo.status, Int64(TPMachineIDStatus.unknown.rawValue), "peer2's MID entry should be 'unknown'") - } } XCTAssertTrue(foundPeer2, "Should have found an entry for peer2") @@ -490,7 +485,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // Then peer2 arrives on the device list. Peer 1 should update its dynamic info to no longer have a disposition for peer2. let updateTrustExpectation = self.expectation(description: "updateTrust") @@ -515,15 +510,17 @@ class OctagonDeviceListTests: OctagonTestsBase { self.mockAuthKit.addAndSendNotification(machineID: try! self.mockAuthKit2.machineID()) - sleep(1) - + try self.waitForPushToArriveAtStateMachine(context: self.cuttlefishContext) XCTAssertTrue(self.cuttlefishContext.stateMachine.possiblePendingFlags().contains(OctagonFlagCuttlefishNotification), "Should have recd_push pending flag") + let pendingFlagCondition = try XCTUnwrap(self.cuttlefishContext.stateMachine.flags.condition(forFlag: OctagonFlagCuttlefishNotification)) + // Now, peer should unlock and receive an Octagon push self.aksLockState = false self.lockStateTracker.recheck() - self.assertPendingFlagHandled(context: self.cuttlefishContext, pendingFlag: OctagonFlagCuttlefishNotification, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, pendingFlagCondition.wait(10 * NSEC_PER_SEC), "State machine should have handled the notification") + XCTAssertEqual(self.cuttlefishContext.stateMachine.possiblePendingFlags(), [], "Should have 0 pending flags") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) @@ -534,6 +531,227 @@ class OctagonDeviceListTests: OctagonTestsBase { XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), "peer 1 should trust peer 2 after update") } + + func testDemoAccountBypassIDMSTrustedDeviceList() throws { + // Check that we can bypass IdMS trusted device list (needed for demo accounts) + + self.startCKAccountStatusMock() + + self.mockAuthKit.excludeDevices.formUnion(self.mockAuthKit.currentDeviceList()) + self.mockAuthKit.isDemoAccount = true + XCTAssertTrue(self.mockAuthKit.currentDeviceList().isEmpty, "should have zero devices") + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + do { + let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + } + + // Now, we should be in 'ready' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) + + // and all subCKKSes should enter ready... + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + + // And we haven't helpfully added anything to the MID list + self.assertMIDList(context: self.cuttlefishContext, allowed: Set(), disallowed: Set(), unknown: Set()) + } + + func testDemoAccountTrustPeerWhenMissingFromDeviceList() throws { + self.startCKAccountStatusMock() + + self.mockAuthKit.otherDevices.removeAll() + self.mockAuthKit.isDemoAccount = true + self.mockAuthKit2.isDemoAccount = true + + XCTAssertEqual(self.mockAuthKit.currentDeviceList(), Set([self.mockAuthKit.currentMachineID]), "AuthKit should have exactly one device on the list") + XCTAssertFalse(self.mockAuthKit.currentDeviceList().contains(self.mockAuthKit2.currentMachineID), "AuthKit should not already have device 2 on the list") + + let peer1ID = self.assertResetAndBecomeTrustedInDefaultContext() + + let joiningContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit2) + let peer2ID = self.assertJoinViaEscrowRecovery(joiningContext: joiningContext, sponsor: self.cuttlefishContext) + + // Now, tell peer1 about the change. It will trust the peer, despite it missing from the list, and upload some TLK shares + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), + "peer 1 should trust peer 2 after update") + self.assertMIDList(context: self.cuttlefishContext, + allowed: self.mockAuthKit.currentDeviceList(), + disallowed: Set(), + unknown: Set()) + + // On a follow-up update, peer1 should _not_ hit IDMS, even though there's an unknown peer ID in its DB + let currentCount = self.mockAuthKit.fetchInvocations + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, states: [OctagonStateReadyUpdated, OctagonStateReady]) + self.assertMIDList(context: self.cuttlefishContext, + allowed: self.mockAuthKit.currentDeviceList(), + disallowed: Set(), + unknown: Set()) + XCTAssertEqual(currentCount, self.mockAuthKit.fetchInvocations, "Receving a push while having an unknown peer MID should not cause an AuthKit fetch") + + //////// + + // Then peer2 arrives on the device list. Peer 1 should update its dynamic info to no longer have a disposition for peer2. + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + XCTAssertTrue(request.hasDynamicInfoAndSig, "updateTrust request should have a dynamic info") + let newDynamicInfo = TPPeerDynamicInfo(data: request.dynamicInfoAndSig.peerDynamicInfo, + sig: request.dynamicInfoAndSig.sig) + XCTAssertNotNil(newDynamicInfo, "should be able to make a dynamic info from protobuf") + + // TODO: swift refuses to see the dispositions object on newDynamicInfo; ah well + updateTrustExpectation.fulfill() + return nil + } + + self.mockAuthKit.addAndSendNotification(machineID: try! self.mockAuthKit2.machineID()) + + self.wait(for: [updateTrustExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), + "peer 1 should trust peer 2 after update") + } + + func testRemovePeerWhenRemovedFromDeviceListAndAuthkitThrowsError() throws { + self.startCKAccountStatusMock() + + XCTAssert(self.mockAuthKit.currentDeviceList().contains(self.mockAuthKit2.currentMachineID), "AuthKit should already have device 2 on the list") + + let peer2ContextID = "joiner" + let peer1ID = self.assertResetAndBecomeTrustedInDefaultContext() + + let joiningContext = self.makeInitiatorContext(contextID: peer2ContextID, authKitAdapter: self.mockAuthKit2) + let peer2ID = self.assertJoinViaEscrowRecovery(joiningContext: joiningContext, sponsor: self.cuttlefishContext) + + // Now, tell peer1 about the change. It will trust the peer and upload some TLK shares + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), + "peer 1 should trust peer 2 after update") + + // Then peer2 drops off the device list, and is no longer able to fetch the deveice list. + // It shouldn't even try to update Cuttlefish: the write will fail + self.fakeCuttlefishServer.updateListener = { _ in + XCTFail("no update was expected") + return nil + } + + let deviceListFetches = self.mockAuthKit2.fetchInvocations + self.mockAuthKit2.injectAuthErrorsAtFetchTime = true + self.mockAuthKit2.removeAndSendNotification(machineID: self.mockAuthKit2.currentMachineID) + + self.assertEnters(context: joiningContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: joiningContext) + + #if !os(tvOS) + XCTAssertTrue(joiningContext.followupHandler.hasPosted(.stateRepair), "Octagon should have posted a repair CFU after falling off the trusted device list") + #else + XCTAssertFalse(joiningContext.followupHandler.hasPosted(.stateRepair), "posted should be false on tvOS; there aren't any iOS devices around to repair it") + #endif + + // And it should even report itself as not on the list anymore + do { + let errorPtr: NSErrorPointer = nil + let onList = joiningContext.machineID(onMemoizedList: self.mockAuthKit2.currentMachineID, error: errorPtr) + XCTAssertNil(errorPtr, "Should have had no error checking memoized list") + XCTAssertFalse(onList, "Should no longer report that the local MID is on the memoized MID list") + } + + XCTAssertEqual(deviceListFetches + 1, self.mockAuthKit2.fetchInvocations, "Should have fetched device list exactly once") + + // Now, when peer1 hears of the change, it should distrust peer2. + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + XCTAssertTrue(request.hasDynamicInfoAndSig, "updateTrust request should have a dynamic info") + let newDynamicInfo = TPPeerDynamicInfo(data: request.dynamicInfoAndSig.peerDynamicInfo, + sig: request.dynamicInfoAndSig.sig) + XCTAssertNotNil(newDynamicInfo, "should be able to make a dynamic info from protobuf") + + XCTAssertTrue(!(newDynamicInfo?.includedPeerIDs.contains(peer2ID) ?? true), "peer1 should no longer trust peer2") + updateTrustExpectation.fulfill() + return nil + } + + self.mockAuthKit.removeAndSendNotification(machineID: try! self.mockAuthKit2.machineID()) + + self.wait(for: [updateTrustExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .excludes, target: peer2ID)), + "peer 1 should distrust peer 2 after update") + + // But peer2 can always rejoin, if it's readded! + self.mockAuthKit2.excludeDevices.remove(self.mockAuthKit2.currentMachineID) + let peer2ID_retry = self.assertJoinViaEscrowRecovery(joiningContext: joiningContext, sponsor: self.cuttlefishContext) + + XCTAssertNotEqual(peer2ID, peer2ID_retry, "Should use a different peer ID after rejoining") + self.assertEnters(context: joiningContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: joiningContext) + + do { + let errorPtr: NSErrorPointer = nil + let onList = joiningContext.machineID(onMemoizedList: self.mockAuthKit2.currentMachineID, error: errorPtr) + XCTAssertNil(errorPtr, "Should have had no error checking memoized list") + XCTAssertTrue(onList, "Should be on the memoized list again") + } + } + + func testResetWhileNotOnListQuiesces() throws { + self.startCKAccountStatusMock() + + self.assertResetAndBecomeTrustedInDefaultContext() + + self.fakeCuttlefishServer.updateListener = { _ in + XCTFail("no update was expected") + return nil + } + + self.mockAuthKit.injectAuthErrorsAtFetchTime = true + self.mockAuthKit.removeAndSendNotification(machineID: self.mockAuthKit.currentMachineID) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + let deviceListFetches = self.mockAuthKit.fetchInvocations + + do { + let arguments = OTConfigurationContext() + arguments.altDSID = try self.cuttlefishContext.authKitAdapter.primaryiCloudAccountAltDSID() + arguments.context = self.cuttlefishContext.contextID + arguments.otControl = self.otControl + + try OTClique.newFriends(withContextData: arguments, resetReason: .testGenerated) + XCTFail("Should have errored trying to perform an Octagon Establish while not on the trusted device list") + } catch { + //pass + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(3 * NSEC_PER_SEC), "State machine should be paused, and not looping") + XCTAssertEqual(deviceListFetches + 1, self.mockAuthKit.fetchInvocations, "Should have fetched device list exactly once") + } } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+ErrorHandling.swift b/keychain/ot/tests/octagon/OctagonTests+ErrorHandling.swift index b5069a73..64572e0b 100644 --- a/keychain/ot/tests/octagon/OctagonTests+ErrorHandling.swift +++ b/keychain/ot/tests/octagon/OctagonTests+ErrorHandling.swift @@ -1,13 +1,35 @@ #if OCTAGON class OctagonErrorHandlingTests: OctagonTestsBase { + func testEstablishFailedError() throws { + self.startCKAccountStatusMock() + + let establishExpectation = self.expectation(description: "establishExpectation") + + self.fakeCuttlefishServer.establishListener = { [unowned self] request in + self.fakeCuttlefishServer.establishListener = nil + + self.fakeCuttlefishServer.establish(request) { response, error in + XCTAssertNil(error, "should be no error from establish") + XCTAssertNotNil(response, "should get a response from establish") + // drop the response on the floor + } + + establishExpectation.fulfill() + + return FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .establishFailed) + } + + _ = self.assertResetAndBecomeTrustedInDefaultContext() + self.wait(for: [establishExpectation], timeout: 10) + } func testRecoverFromImmediateTimeoutDuringEstablish() throws { self.startCKAccountStatusMock() let establishExpectation = self.expectation(description: "establishExpectation") - self.fakeCuttlefishServer.establishListener = { [unowned self] request in + self.fakeCuttlefishServer.establishListener = { [unowned self] request in self.fakeCuttlefishServer.establishListener = nil establishExpectation.fulfill() @@ -27,7 +49,7 @@ class OctagonErrorHandlingTests: OctagonTestsBase { var t0 = Date.distantPast - self.fakeCuttlefishServer.establishListener = { [unowned self] request in + self.fakeCuttlefishServer.establishListener = { [unowned self] request in self.fakeCuttlefishServer.establishListener = nil establishExpectation.fulfill() @@ -75,6 +97,7 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.aksLockState = true @@ -86,10 +109,11 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) } - func testReceiveUpdateWhileReadyAndLocked() { + func testReceiveUpdateWhileReadyAndLocked() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -121,21 +145,23 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.lockStateTracker.recheck() self.sendContainerChange(context: self.cuttlefishContext) - sleep(1) + try self.waitForPushToArriveAtStateMachine(context: self.cuttlefishContext) XCTAssertTrue(self.cuttlefishContext.stateMachine.possiblePendingFlags().contains(OctagonFlagCuttlefishNotification), "Should have recd_push pending flag") - let waitForUnlockStateCondition = self.cuttlefishContext.stateMachine.stateConditions[OctagonStateWaitForUnlock] as! CKKSCondition + let waitForUnlockStateCondition : CKKSCondition = self.cuttlefishContext.stateMachine.stateConditions[OctagonStateWaitForUnlock]! XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "state machine should pause") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) // Check that we haven't been spinning - let sameWaitForUnlockStateCondition = self.cuttlefishContext.stateMachine.stateConditions[OctagonStateWaitForUnlock] as! CKKSCondition + let sameWaitForUnlockStateCondition : CKKSCondition = self.cuttlefishContext.stateMachine.stateConditions[OctagonStateWaitForUnlock]! XCTAssert(waitForUnlockStateCondition == sameWaitForUnlockStateCondition, "Conditions should be the same (as the state machine should be halted)") + let pendingFlagCondition = try XCTUnwrap(self.cuttlefishContext.stateMachine.flags.condition(forFlag: OctagonFlagCuttlefishNotification)) + self.aksLockState = false self.lockStateTracker.recheck() - self.assertPendingFlagHandled(context: self.cuttlefishContext, pendingFlag: OctagonFlagCuttlefishNotification, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, pendingFlagCondition.wait(10 * NSEC_PER_SEC), "State machine should have handled the OctagonFlagCuttlefishNotification notification") XCTAssertEqual(self.cuttlefishContext.stateMachine.possiblePendingFlags(), [], "Should have 0 pending flags") @@ -146,6 +172,7 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -161,8 +188,8 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) self.mockAuthKit.machineIDFetchErrors.append(CKPrettyError(domain: CKErrorDomain, - code: CKError.networkUnavailable.rawValue, - userInfo: [CKErrorRetryAfterKey: 2])) + code: CKError.networkUnavailable.rawValue, + userInfo: [CKErrorRetryAfterKey: 2])) self.sendContainerChange(context: self.cuttlefishContext) @@ -174,10 +201,11 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) } - func testReceiveUpdateWhileReadyAndLockedAndAuthkitRetry() { + func testReceiveUpdateWhileReadyAndLockedAndAuthkitRetry() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -196,8 +224,8 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.lockStateTracker.recheck() self.mockAuthKit.machineIDFetchErrors.append(CKPrettyError(domain: CKErrorDomain, - code: CKError.networkUnavailable.rawValue, - userInfo: [CKErrorRetryAfterKey: 2])) + code: CKError.networkUnavailable.rawValue, + userInfo: [CKErrorRetryAfterKey: 2])) self.sendContainerChange(context: self.cuttlefishContext) @@ -208,14 +236,14 @@ class OctagonErrorHandlingTests: OctagonTestsBase { XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "state machine should pause") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - sleep(1) - + try self.waitForPushToArriveAtStateMachine(context: self.cuttlefishContext) XCTAssertTrue(self.cuttlefishContext.stateMachine.possiblePendingFlags().contains(OctagonFlagCuttlefishNotification), "Should have recd_push pending flag") + let pendingFlagCondition = try XCTUnwrap(self.cuttlefishContext.stateMachine.flags.condition(forFlag: OctagonFlagCuttlefishNotification)) self.aksLockState = false self.lockStateTracker.recheck() - self.assertPendingFlagHandled(context: self.cuttlefishContext, pendingFlag: OctagonFlagCuttlefishNotification, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, pendingFlagCondition.wait(10 * NSEC_PER_SEC), "State machine should have handled the notification") XCTAssertEqual(self.cuttlefishContext.stateMachine.possiblePendingFlags(), [], "Should have 0 pending flags") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) @@ -225,6 +253,7 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -258,9 +287,9 @@ class OctagonErrorHandlingTests: OctagonTestsBase { func testPreapprovedPushWhileLocked() throws { // Peer 1 becomes SOS+Octagon - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -277,7 +306,7 @@ class OctagonErrorHandlingTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - // Peer 2 attempts to join via preapprovalh + // Peer 2 attempts to join via preapproval let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") let peer2contextID = "peer2" let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) @@ -324,31 +353,36 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.wait(for: [updateTrustExpectation], timeout: 100) self.fakeCuttlefishServer.updateListener = nil + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + // Now, peer 2 should lock and receive an Octagon push self.aksLockState = true self.lockStateTracker.recheck() - // Now, peer2 should receive an Octagon push, try to realize it is preapproved, and get stuck + // Now, peer2 should receive an Octagon push, try to realize it is preapproved, and get stuck waiting for an unlock + let flagCondition = peer2.stateMachine.flags.condition(forFlag: OctagonFlagCuttlefishNotification) + self.sendContainerChange(context: peer2) self.assertEnters(context: peer2, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - sleep(1) - XCTAssertTrue(peer2.stateMachine.possiblePendingFlags().contains(OctagonFlagCuttlefishNotification), "Should have recd_push pending flag") + // The pending flag should become a real flag after the lock state changes + // But it should not fire for a bit + XCTAssertNotEqual(0, flagCondition.wait(1 * NSEC_PER_SEC), "Cuttlefish Notification flag should not be removed while locked") self.aksLockState = false self.lockStateTracker.recheck() - XCTAssertEqual(self.cuttlefishContext.stateMachine.possiblePendingFlags(), [], "Should have 0 pending flags") - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, flagCondition.wait(10 * NSEC_PER_SEC), "Cuttlefish Notification flag should be removed") + XCTAssertEqual(peer2.stateMachine.possiblePendingFlags(), [], "Should have 0 pending flags") self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) } func testReceiveMachineListUpdateWhileReadyAndLocked() throws { // Peer 1 becomes SOS+Octagon - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -367,7 +401,7 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) // Peer 2 arrives (with a voucher), but is not on the trusted device list let firstPeerID = clique.cliqueMemberIdentifier @@ -383,12 +417,12 @@ class OctagonErrorHandlingTests: OctagonTestsBase { bNewOTCliqueContext.otControl = self.otcliqueContext.otControl bNewOTCliqueContext.sbd = OTMockSecureBackup(bottleID: bottle.bottleID, entropy: entropy!) - let deviceBmockAuthKit = OTMockAuthKitAdapter(altDSID: self.otcliqueContext.altDSID, + let deviceBmockAuthKit = OTMockAuthKitAdapter(altDSID: self.otcliqueContext.altDSID!, machineID: "b-machine-id", otherDevices: [self.mockAuthKit.currentMachineID]) let bRestoreContext = self.manager.context(forContainerName: OTCKContainerName, - contextID: bNewOTCliqueContext.context!, + contextID: bNewOTCliqueContext.context, sosAdapter: OTSOSMissingAdapter(), authKitAdapter: deviceBmockAuthKit, lockStateTracker: self.lockStateTracker, @@ -439,28 +473,34 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) // And on unlock, it should handle the update + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.aksLockState = false self.lockStateTracker.recheck() self.wait(for: [updateTrustExpectation], timeout: 30) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() } func testCKKSResetRecoverFromCKKSConflict() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() // But do NOT add them to the keychain // CKKS should get stuck in waitfortlk self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { - let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) - XCTAssertNotNil(clique, "Clique should not be nil") + let clique = OTClique(contextData: self.otcliqueContext) + try clique.establish() } catch { - XCTFail("Shouldn't have errored making new friends: \(error)") + XCTFail("Shouldn't have errored establishing Octagon: \(error)") } // Now, we should be in 'ready', and CKKS should be stuck @@ -473,23 +513,18 @@ class OctagonErrorHandlingTests: OctagonTestsBase { var tlkUUIDs: [CKRecordZone.ID: String] = [:] self.silentFetchesAllowed = false - self.expectCKFetchAndRun(beforeFinished: { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + self.expectCKFetchAndRun { + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() self.silentFetchesAllowed = true - // Use the commented version below when multi-zone support is readded to the tets - tlkUUIDs[self.manateeZoneID!] = (self.keys![self.manateeZoneID!] as? ZoneKeys)?.tlk?.uuid - /* for zoneID in self.ckksZones { tlkUUIDs[zoneID as! CKRecordZone.ID] = (self.keys![zoneID] as? ZoneKeys)?.tlk?.uuid } - */ - }) + } let resetExepctation = self.expectation(description: "reset callback is called") - self.cuttlefishContext.viewManager!.rpcResetCloudKit(nil, reason: "unit-test") { - error in + self.cuttlefishContext.viewManager!.rpcResetCloudKit(nil, reason: "unit-test") { error in XCTAssertNil(error, "should be no error resetting cloudkit") resetExepctation.fulfill() } @@ -507,6 +542,78 @@ class OctagonErrorHandlingTests: OctagonTestsBase { XCTAssertEqual(tlkUUID, (self.keys![zoneID] as? ZoneKeys)?.tlk?.uuid, "TLK should match conflicted version") } } + + func testHandlePeerMissingOnSetUserControllableViews() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + // Another device updates the world, but we don't get the push + let reset = self.makeInitiatorContext(contextID: "reset") + self.assertResetAndBecomeTrusted(context: reset) + + // Now, the original peer sets their view status + #if os(tvOS) + throw XCTSkip("TVs don't set user-controllable views") + #else + + let clique = self.cliqueFor(context: self.cuttlefishContext) + + do { + try clique.setUserControllableViewsSyncStatus(true) + XCTFail("Should be an error setting user-visible sync status") + } catch { + } + + // Octagon should notice that it's been kicked out. + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + #endif // os(tvOS) + } + + func testHandlePeerMissingOnTrustUpdate() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + // Another device joins + let joiner = self.makeInitiatorContext(contextID: "joiner") + self.assertJoinViaEscrowRecovery(joiningContext: joiner, sponsor: self.cuttlefishContext) + + // Now, directly after the default context fetches, another device resets Octagon. + // To simulate this, we reset things in the updateTrust listener. + let reset = self.makeInitiatorContext(contextID: "reset") + + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + reset.startOctagonStateMachine() + + do { + try reset.setCDPEnabled() + self.assertEnters(context: reset, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let arguments = OTConfigurationContext() + arguments.altDSID = try reset.authKitAdapter.primaryiCloudAccountAltDSID() + arguments.context = reset.contextID + arguments.otControl = self.otControl + + let clique = try OTClique.newFriends(withContextData: arguments, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + } + self.assertEnters(context: reset, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + updateTrustExpectation.fulfill() + return FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .updateTrustPeerNotFound) + } + + // Notify Octagon of the join + self.sendContainerChange(context: self.cuttlefishContext) + + self.wait(for: [updateTrustExpectation], timeout: 10) + + // Octagon should notice that it's been kicked out. + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + } } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift b/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift new file mode 100644 index 00000000..91aadb9c --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift @@ -0,0 +1,904 @@ +#if OCTAGON + +@objcMembers +class OctagonEscrowRecordTests: OctagonTestsBase { + + func testFetchEscrowRecord() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let entropy = try self.loadSecret(label: clique.cliqueMemberIdentifier!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + OctagonSetPlatformSupportsSOS(true) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords: [OTEscrowRecord] = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow record") + let reduced = escrowRecords.compactMap { $0.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + } + + func testViableBottleCachingAfterJoin() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let entropy = try self.loadSecret(label: clique.cliqueMemberIdentifier!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in + XCTAssertNil(error, "error should be nil") + joinWithBottleExpectation.fulfill() + } + + self.wait(for: [joinWithBottleExpectation], timeout: 100) + + let dumpCallback = self.expectation(description: "dumpCallback callback occurs") + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + dumpCallback.fulfill() + } + self.wait(for: [dumpCallback], timeout: 10) + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + + OctagonSetPlatformSupportsSOS(true) + + //now call fetchviablebottles, we should get the uncached version + let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + fetchUnCachedViableBottlesExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + + //now call fetchviablebottles, we should get the cached version + let fetchViableBottlesExpectation = self.expectation(description: "fetch Cached ViableBottles") + fetchViableBottlesExpectation.isInverted = true + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + fetchViableBottlesExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow record") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesExpectation], timeout: 1) + } + + func testCachedEscrowRecordFetch() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let entropy = try self.loadSecret(label: clique.cliqueMemberIdentifier!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in + XCTAssertNil(error, "error should be nil") + joinWithBottleExpectation.fulfill() + } + + self.wait(for: [joinWithBottleExpectation], timeout: 100) + + let dumpCallback = self.expectation(description: "dumpCallback callback occurs") + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + dumpCallback.fulfill() + } + self.wait(for: [dumpCallback], timeout: 10) + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + + OctagonSetPlatformSupportsSOS(true) + + //now call fetchviablebottles, we should get the uncached version + let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + fetchUnCachedViableBottlesExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + //now call fetchviablebottles, we should get the cached version + let fetchViableBottlesExpectation = self.expectation(description: "fetch Cached ViableBottles") + fetchViableBottlesExpectation.isInverted = true + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + fetchViableBottlesExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesExpectation], timeout: 1) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: initiatorContextID) + container.escrowCacheTimeout = 1 + + //sleep to invalidate the cache + sleep(1) + + //now call fetchviablebottles, we should get the uncached version + let uncachedViableBottlesFetchExpectation = self.expectation(description: "fetch Uncached ViableBottles") + let fetchBottlesFromCuttlefishFetchExpectation = self.expectation(description: "fetch bottles from cuttlefish expectation") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + fetchBottlesFromCuttlefishFetchExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + uncachedViableBottlesFetchExpectation.fulfill() + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchBottlesFromCuttlefishFetchExpectation], timeout: 10) + self.wait(for: [uncachedViableBottlesFetchExpectation], timeout: 10) + } + + func testForcedEscrowRecordFetch() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + bottlerotcliqueContext.overrideEscrowCache = false + + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let entropy = try self.loadSecret(label: clique.cliqueMemberIdentifier!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in + XCTAssertNil(error, "error should be nil") + joinWithBottleExpectation.fulfill() + } + + self.wait(for: [joinWithBottleExpectation], timeout: 100) + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + + OctagonSetPlatformSupportsSOS(true) + + //now call fetchviablebottles, we should get records from cuttlefish + let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + fetchUnCachedViableBottlesExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) + + //set the override to force an escrow record fetch + bottlerotcliqueContext.overrideEscrowCache = true + + //now call fetchviablebottles, we should get records from cuttlefish + let fetchViableBottlesExpectation = self.expectation(description: "fetch forced ViableBottles") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + fetchViableBottlesExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesExpectation], timeout: 10) + } + + func testSignInWithEscrowPrecachingEnabled() throws { + self.startCKAccountStatusMock() + + let contextName = OTDefaultContext + let containerName = OTCKContainerName + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + OctagonSetPlatformSupportsSOS(true) + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + //expect fetch escrow record fetch + let fetchViableBottlesExpectation = self.expectation(description: "fetch Cached ViableBottles") + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + fetchViableBottlesExpectation.fulfill() + return nil + } + + // Device is signed out + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + self.mockAuthKit.hsa2 = true + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + let signInExpectation = self.expectation(description: "signing in expectation") + + self.manager.sign(in: newAltDSID, container: containerName, context: contextName) { error in + XCTAssertNil(error, "error should not be nil") + signInExpectation.fulfill() + } + + self.wait(for: [signInExpectation], timeout: 10) + self.wait(for: [fetchViableBottlesExpectation], timeout: 10) + } + + func testLegacyEscrowRecordFetch() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + OctagonSetPlatformSupportsSOS(true) + + self.startCKAccountStatusMock() + + let initiatorContextID = "joiner" + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = OTDefaultContext + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + self.mockAuthKit.hsa2 = true + bottlerotcliqueContext.otControl = self.otControl + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") + + // SOS TLK shares will be uploaded after the establish + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + self.verifyDatabaseMocks() + + let joinerContext = self.makeInitiatorContext(contextID: initiatorContextID) + self.assertJoinViaEscrowRecovery(joiningContext: joinerContext, sponsor: self.cuttlefishContext) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: OTDefaultContext) + + //now call fetchviablebottles, we should get the uncached version + let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + + self.fakeCuttlefishServer.injectLegacyEscrowRecords = true + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + fetchUnCachedViableBottlesExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + + XCTAssertEqual(escrowRecords.count, 3, "should be 3 escrow records") + let recordsWithBottles = escrowRecords.filter { $0!.escrowInformationMetadata.bottleId != "" } + XCTAssertEqual(recordsWithBottles.count, 2, "should be 2 escrow records with a bottleID") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) + + //now call fetchviablebottles, we should get the cached version + let fetchViableBottlesExpectation = self.expectation(description: "fetch Cached ViableBottles") + fetchViableBottlesExpectation.isInverted = true + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + + let legacy = container.containerMO.legacyEscrowRecords as! Set + let partial = container.containerMO.partiallyViableEscrowRecords as! Set + let full = container.containerMO.fullyViableEscrowRecords as! Set + + XCTAssertEqual(legacy.count, 1, "legacy escrowRecords should contain 1 record") + XCTAssertEqual(partial.count, 1, "partially viable escrowRecords should contain 1 record") + XCTAssertEqual(full.count, 1, "fully viable escrowRecords should contain 1 record") + + fetchViableBottlesExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + + XCTAssertEqual(escrowRecords.count, 3, "should be 3 escrow record") + let recordsWithBottles = escrowRecords.filter { $0!.escrowInformationMetadata.bottleId != "" } + XCTAssertEqual(recordsWithBottles.count, 2, "should be 2 escrow records with a bottleID") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesExpectation], timeout: 1) + + //check cache is empty after escrow fetch timeout expires + container.escrowCacheTimeout = 1 + sleep(1) + + //now call fetchviablebottles, we should get the uncached version, check there's 0 cached records + let fetchViableBottlesAfterExpiredTimeoutExpectation = self.expectation(description: "fetch Cached ViableBottles expectaiton after timeout") + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + + fetchViableBottlesAfterExpiredTimeoutExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 3, "should be 3 escrow record") + let recordsWithBottles = escrowRecords.filter { $0!.escrowInformationMetadata.bottleId != "" } + XCTAssertEqual(recordsWithBottles.count, 2, "should be 2 escrow records with a bottleID") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesAfterExpiredTimeoutExpectation], timeout: 10) + } + + func testEmptyEscrowRecords() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + self.fakeCuttlefishServer.includeEscrowRecords = false + self.fakeCuttlefishServer.injectLegacyEscrowRecords = false + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: initiatorContextID) + + OctagonSetPlatformSupportsSOS(true) + + let fetchViableBottlesAfterExpiredTimeoutExpectation = self.expectation(description: "fetch Cached ViableBottles expectaiton after timeout") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + + container.moc.performAndWait { + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + } + fetchViableBottlesAfterExpiredTimeoutExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + XCTAssertEqual(escrowRecordDatas.count, 0, "should be 0 escrow records") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesAfterExpiredTimeoutExpectation], timeout: 10) + container.moc.performAndWait { + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + } + } + + func testRemoveEscrowCache() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + OctagonSetPlatformSupportsSOS(true) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords: [OTEscrowRecord] = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow record") + let reduced = escrowRecords.compactMap { $0.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + + let removeExpectation = self.expectation(description: "remove expectation") + self.manager.invalidateEscrowCache(OTCKContainerName, contextID: initiatorContextID) { error in + XCTAssertNil(error, "error should not be nil") + removeExpectation.fulfill() + } + self.wait(for: [removeExpectation], timeout: 10) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: initiatorContextID) + + let fetchViableBottlesAfterCacheRemovalExpectation = self.expectation(description: "fetchViableBottles expectation after cache removal") + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .unknown, "request filtering should be unknown") + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + + fetchViableBottlesAfterCacheRemovalExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesAfterCacheRemovalExpectation], timeout: 10) + } + + func testFetchViableBottlesFilteringOctagonOnly() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + OctagonSetPlatformSupportsSOS(false) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords: [OTEscrowRecord] = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow record") + let reduced = escrowRecords.compactMap { $0.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + + let removeExpectation = self.expectation(description: "remove expectation") + self.manager.invalidateEscrowCache(OTCKContainerName, contextID: initiatorContextID) { error in + XCTAssertNil(error, "error should not be nil") + removeExpectation.fulfill() + } + self.wait(for: [removeExpectation], timeout: 10) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: initiatorContextID) + + let fetchViableBottlesAfterCacheRemovalExpectation = self.expectation(description: "fetchViableBottles expectation after cache removal") + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(request.filterRequest, .byOctagonOnly, "request filtering should be unknown") + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + + fetchViableBottlesAfterCacheRemovalExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesAfterCacheRemovalExpectation], timeout: 10) + } +} + +#endif diff --git a/keychain/ot/tests/octagon/OctagonTests+EscrowRecovery.swift b/keychain/ot/tests/octagon/OctagonTests+EscrowRecovery.swift index 64a4006f..7d34c91c 100644 --- a/keychain/ot/tests/octagon/OctagonTests+EscrowRecovery.swift +++ b/keychain/ot/tests/octagon/OctagonTests+EscrowRecovery.swift @@ -1,6 +1,7 @@ #if OCTAGON -@objcMembers class OctagonEscrowRecoveryTests: OctagonTestsBase { +@objcMembers +class OctagonEscrowRecoveryTests: OctagonTestsBase { override func setUp() { super.setUp() } @@ -16,6 +17,7 @@ ckacctinfo.accountPartition = .production bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -40,8 +42,8 @@ XCTAssertNotNil(entropy, "entropy should not be nil") // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: bottlerContext, zoneID: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) let bottle = self.fakeCuttlefishServer.state.bottles[0] @@ -49,12 +51,6 @@ self.startCKAccountStatusMock() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - // Try to enforce that that CKKS doesn't know about the key hierarchy until Octagon asks it - self.holdCloudKitFetches() - - // Note: CKKS will want to upload a TLKShare for its self - self.expectCKModifyKeyRecords(0, currentKeyPointerRecords: 0, tlkShareRecords: 1, zoneID: self.manateeZoneID) - // Before you call joinWithBottle, you need to call fetchViableBottles. let fetchViableExpectation = self.expectation(description: "fetchViableBottles callback occurs") self.cuttlefishContext.rpcFetchAllViableBottles { viable, _, error in @@ -65,25 +61,21 @@ self.wait(for: [fetchViableExpectation], timeout: 10) let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } - sleep(1) - self.releaseCloudKitFetchHold() - self.wait(for: [joinWithBottleExpectation], timeout: 100) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") dumpCallback.fulfill() @@ -92,7 +84,8 @@ self.verifyDatabaseMocks() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) } func testBottleRestoreEntersOctagonReady() throws { @@ -100,6 +93,7 @@ let initiatorContextID = "initiator-context-id" self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -126,7 +120,7 @@ initiatorContext.startOctagonStateMachine() let restoreExpectation = self.expectation(description: "restore returns") - self.manager!.restore(OTCKContainerName, contextID: initiatorContextID, bottleSalt: self.otcliqueContext.altDSID, entropy: entropy!, bottleID: bottle.bottleID) { error in + self.manager!.restore(OTCKContainerName, contextID: initiatorContextID, bottleSalt: self.otcliqueContext.altDSID!, entropy: entropy!, bottleID: bottle.bottleID) { error in XCTAssertNil(error, "error should be nil") restoreExpectation.fulfill() } @@ -135,14 +129,13 @@ self.assertEnters(context: initiatorContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -162,6 +155,7 @@ ckacctinfo.accountPartition = .production bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -189,11 +183,11 @@ // During the join, there's a CKKS key race self.silentFetchesAllowed = false - self.expectCKFetchAndRun(beforeFinished: { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + self.expectCKFetchAndRun { + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() self.silentFetchesAllowed = true - }) + } self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() @@ -209,7 +203,7 @@ self.wait(for: [fetchViableExpectation], timeout: 10) let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } @@ -225,6 +219,7 @@ self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -251,8 +246,8 @@ let differentRestoreExpectation = self.expectation(description: "different restore returns") differentDevice.startOctagonStateMachine() differentDevice.join(withBottle: bottle.bottleID, - entropy: entropy!, - bottleSalt: self.otcliqueContext.altDSID) { error in + entropy: entropy!, + bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") differentRestoreExpectation.fulfill() } @@ -276,9 +271,9 @@ let restoreExpectation = self.expectation(description: "restore returns") restoreContext.join(withBottle: bottle.bottleID, entropy: entropy!, - bottleSalt: self.otcliqueContext.altDSID) { error in - XCTAssertNil(error, "error should be nil") - restoreExpectation.fulfill() + bottleSalt: self.otcliqueContext.altDSID!) { error in + XCTAssertNil(error, "error should be nil") + restoreExpectation.fulfill() } self.wait(for: [restoreExpectation], timeout: 10) @@ -303,6 +298,7 @@ let initiatorContextID = "initiator-context-id" self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -327,25 +323,25 @@ initiatorContext.startOctagonStateMachine() + XCTAssertNoThrow(try initiatorContext.setCDPEnabled()) self.assertEnters(context: initiatorContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let restoreExpectation = self.expectation(description: "restore returns") - self.manager!.restore(OTCKContainerName, contextID: initiatorContextID, bottleSalt: self.otcliqueContext.altDSID, entropy: entropy!, bottleID: bottle.bottleID) { error in + self.manager!.restore(OTCKContainerName, contextID: initiatorContextID, bottleSalt: self.otcliqueContext.altDSID!, entropy: entropy!, bottleID: bottle.bottleID) { error in XCTAssertNil(error, "error should be nil") restoreExpectation.fulfill() } self.wait(for: [restoreExpectation], timeout: 10) let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -359,6 +355,7 @@ let initiatorContextID = "initiator-context-id" self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -386,7 +383,7 @@ let restoreExpectation = self.expectation(description: "restore returns") - self.manager!.restore(OTCKContainerName, contextID: initiatorContextID, bottleSalt: self.otcliqueContext.altDSID, entropy: entropy!, bottleID: "bad escrow record ID") { error in + self.manager!.restore(OTCKContainerName, contextID: initiatorContextID, bottleSalt: self.otcliqueContext.altDSID!, entropy: entropy!, bottleID: "bad escrow record ID") { error in XCTAssertNotNil(error, "error should not be nil") restoreExpectation.fulfill() } @@ -394,14 +391,13 @@ self.assertEnters(context: initiatorContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 1, "should be 1 peer ids") @@ -464,7 +460,8 @@ // We will upload a new TLK for the new peer self.assertAllCKKSViewsUpload(tlkShares: 1) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() self.sendContainerChangeWaitForFetch(context: initiatorContext) bottleIDs = try OTClique.findOptimalBottleIDs(withContextData: self.otcliqueContext) @@ -537,7 +534,8 @@ // We will upload a new TLK for the new peer self.assertAllCKKSViewsUpload(tlkShares: 1) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() self.sendContainerChangeWaitForFetch(context: initiatorContext) @@ -547,11 +545,10 @@ XCTAssertEqual(bottleIDs.partialRecoveryBottleIDs.count, 0, "partialRecoveryBottleIDs should be empty") let dumpExpectation = self.expectation(description: "dump callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, error in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in XCTAssertNil(error, "Should be no error dumping data") XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") let peerID = egoSelf!["peerID"] as? String XCTAssertNotNil(peerID, "peerID should not be nil") @@ -561,7 +558,7 @@ self.wait(for: [dumpExpectation], timeout: 10) self.otControlCLI.status(OTCKContainerName, - context: newOTCliqueContext.context!, + context: newOTCliqueContext.context, json: false) } @@ -604,7 +601,6 @@ fetchEscrowContentsException.fulfill() } self.wait(for: [fetchEscrowContentsException], timeout: 10) - } catch { XCTFail("failed to reset clique: \(error)") } @@ -673,6 +669,7 @@ let initiatorContextID = "initiator-context-id" self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -699,7 +696,7 @@ initiatorContext.startOctagonStateMachine() let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - initiatorContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + initiatorContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNotNil(error, "error should not be nil") joinWithBottleExpectation.fulfill() } @@ -713,6 +710,7 @@ let initiatorContextID = "initiator-context-id" self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -739,7 +737,7 @@ initiatorContext.startOctagonStateMachine() let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - initiatorContext.join(withBottle: "sos peer id", entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + initiatorContext.join(withBottle: "sos peer id", entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNotNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } @@ -752,6 +750,7 @@ let initiatorContextID = "initiator-context-id" self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -779,7 +778,7 @@ self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - initiatorContext.join(withBottle: bottle.bottleID, entropy: Data(count: 72), bottleSalt: self.otcliqueContext.altDSID) { error in + initiatorContext.join(withBottle: bottle.bottleID, entropy: Data(count: 72), bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNotNil(error, "error should not be nil, when entropy is missing") joinWithBottleExpectation.fulfill() } @@ -792,6 +791,7 @@ let initiatorContextID = "initiator-context-id" self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -865,12 +865,12 @@ bNewOTCliqueContext.otControl = self.otcliqueContext.otControl bNewOTCliqueContext.sbd = OTMockSecureBackup(bottleID: bottle.bottleID, entropy: entropy!) - let deviceBmockAuthKit = OTMockAuthKitAdapter(altDSID: self.otcliqueContext.altDSID, + let deviceBmockAuthKit = OTMockAuthKitAdapter(altDSID: self.otcliqueContext.altDSID!, machineID: "b-machine-id", otherDevices: [self.mockAuthKit.currentMachineID]) let bRestoreContext = self.manager.context(forContainerName: OTCKContainerName, - contextID: bNewOTCliqueContext.context!, + contextID: bNewOTCliqueContext.context, sosAdapter: OTSOSMissingAdapter(), authKitAdapter: deviceBmockAuthKit, lockStateTracker: self.lockStateTracker, @@ -889,16 +889,16 @@ // And introduce C, which will kick out A // During the next sign in, the machine ID list has changed to just the new one - let restoremockAuthKit = OTMockAuthKitAdapter(altDSID: self.otcliqueContext.altDSID, + let restoremockAuthKit = OTMockAuthKitAdapter(altDSID: self.otcliqueContext.altDSID!, machineID: "c-machine-id", otherDevices: [self.mockAuthKit.currentMachineID, deviceBmockAuthKit.currentMachineID]) let restoreContext = self.manager.context(forContainerName: OTCKContainerName, - contextID: "restoreContext", - sosAdapter: OTSOSMissingAdapter(), - authKitAdapter: restoremockAuthKit, - lockStateTracker: self.lockStateTracker, - accountStateTracker: self.accountStateTracker, - deviceInformationAdapter: self.makeInitiatorDeviceInfoAdapter()) + contextID: "restoreContext", + sosAdapter: OTSOSMissingAdapter(), + authKitAdapter: restoremockAuthKit, + lockStateTracker: self.lockStateTracker, + accountStateTracker: self.accountStateTracker, + deviceInformationAdapter: self.makeInitiatorDeviceInfoAdapter()) restoreContext.startOctagonStateMachine() let newOTCliqueContext = OTConfigurationContext() @@ -922,14 +922,13 @@ self.assertConsidersSelfTrusted(context: restoreContext) let restoreDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: newOTCliqueContext.context!) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: newOTCliqueContext.context) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 3, "should be 3 peer id included") @@ -962,6 +961,7 @@ } func testCachedBottleFetch() throws { + OctagonSetOptimizationEnabled(false) let initiatorContextID = "initiator-context-id" let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) @@ -972,6 +972,7 @@ ckacctinfo.accountPartition = .production bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -996,23 +997,20 @@ XCTAssertNotNil(entropy, "entropy should not be nil") // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: bottlerContext, zoneID: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) let bottle = self.fakeCuttlefishServer.state.bottles[0] + // Try to enforce that that CKKS doesn't know about the key hierarchy until Octagon asks it + self.holdCloudKitFetches() + self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - // Try to enforce that that CKKS doesn't know about the key hierarchy until Octagon asks it - self.holdCloudKitFetches() - - // Note: CKKS will want to upload a TLKShare for its self - self.expectCKModifyKeyRecords(0, currentKeyPointerRecords: 0, tlkShareRecords: 1, zoneID: self.manateeZoneID) - let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } @@ -1023,14 +1021,13 @@ self.wait(for: [joinWithBottleExpectation], timeout: 100) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") dumpCallback.fulfill() @@ -1039,7 +1036,7 @@ self.verifyDatabaseMocks() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) //now call fetchviablebottles, we should get the uncached version let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") @@ -1054,6 +1051,10 @@ self.cuttlefishContext.rpcFetchAllViableBottles { viable, _, error in XCTAssertNil(error, "should be no error fetching viable bottles") XCTAssert(viable?.contains(bottle.bottleID) ?? false, "The bottle we're about to restore should be viable") + XCTAssertEqual(viable?.count, 2, "There should be 2 bottles") + XCTAssertNotEqual(viable?[0], "", "Bottle should not be empty") + XCTAssertNotEqual(viable?[1], "", "Bottle should not be empty") + FetchAllViableBottles.fulfill() } self.wait(for: [FetchAllViableBottles], timeout: 10) @@ -1088,6 +1089,7 @@ } func testViableBottleCachingAfterJoin() throws { + OctagonSetOptimizationEnabled(false) let initiatorContextID = "initiator-context-id" let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) @@ -1098,6 +1100,7 @@ ckacctinfo.accountPartition = .production bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -1122,41 +1125,32 @@ XCTAssertNotNil(entropy, "entropy should not be nil") // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: bottlerContext, zoneID: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) let bottle = self.fakeCuttlefishServer.state.bottles[0] self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - // Try to enforce that that CKKS doesn't know about the key hierarchy until Octagon asks it - self.holdCloudKitFetches() - - // Note: CKKS will want to upload a TLKShare for its self - self.expectCKModifyKeyRecords(0, currentKeyPointerRecords: 0, tlkShareRecords: 1, zoneID: self.manateeZoneID) - let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } - sleep(1) - self.releaseCloudKitFetchHold() - self.wait(for: [joinWithBottleExpectation], timeout: 100) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") dumpCallback.fulfill() @@ -1165,7 +1159,8 @@ self.verifyDatabaseMocks() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) //now call fetchviablebottles, we should get the uncached version let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") @@ -1224,6 +1219,7 @@ ckacctinfo.accountPartition = .production bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -1248,8 +1244,8 @@ XCTAssertNotNil(entropy, "entropy should not be nil") // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: bottlerContext, zoneID: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) let bottle = self.fakeCuttlefishServer.state.bottles[0] @@ -1257,35 +1253,25 @@ self.startCKAccountStatusMock() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - // Try to enforce that that CKKS doesn't know about the key hierarchy until Octagon asks it - self.holdCloudKitFetches() - - // Note: CKKS will want to upload a TLKShare for its self - self.expectCKModifyKeyRecords(0, currentKeyPointerRecords: 0, tlkShareRecords: 1, zoneID: self.manateeZoneID) - let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } - sleep(1) - self.releaseCloudKitFetchHold() - self.wait(for: [joinWithBottleExpectation], timeout: 100) var egoPeerID: String? let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") egoPeerID = egoSelf!["peerID"] as? String - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") dumpCallback.fulfill() @@ -1294,7 +1280,8 @@ self.verifyDatabaseMocks() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) let bottles: [Bottle] = self.fakeCuttlefishServer.state.bottles var bottleToExclude: String? @@ -1325,8 +1312,9 @@ self.wait(for: [FetchAllViableBottles], timeout: 10) self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 10) - //now call fetchviablebottles, we should get the uncached version - fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + //now call fetchviablebottles, we should get the cached version + fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch cached ViableBottles") + fetchUnCachedViableBottlesExpectation.isInverted = true self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil @@ -1344,7 +1332,224 @@ FetchAllViableBottles.fulfill() } self.wait(for: [FetchAllViableBottles], timeout: 10) - self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 10) + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) + } + + func testRecoverTLKSharesSendByPeers() throws { + // First, set up the world: two peers, one of which has sent TLKs to itself and the other + let noSelfSharesContext = self.makeInitiatorContext(contextID: "noShares", authKitAdapter: self.mockAuthKit2) + let allSharesContext = self.makeInitiatorContext(contextID: "allShares", authKitAdapter: self.mockAuthKit3) + + self.startCKAccountStatusMock() + let noSelfSharesPeerID = self.assertResetAndBecomeTrusted(context: noSelfSharesContext) + let allSharesPeerID = self.assertJoinViaEscrowRecovery(joiningContext: allSharesContext, sponsor: noSelfSharesContext) + + self.sendContainerChangeWaitForFetch(context: noSelfSharesContext) + self.assertEnters(context: noSelfSharesContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: noSelfSharesPeerID, opinion: .trusts, target: allSharesPeerID)), + "noShares should trust allShares") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: noSelfSharesPeerID, opinion: .trusts, target: noSelfSharesPeerID)), + "No shares should trust itself") + + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: allSharesContext) + try self.putAllTLKSharesInCloudKit(to: noSelfSharesContext, from: allSharesContext) + + self.ckksZones.forEach { zone in + XCTAssertFalse(self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: noSelfSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should not have self shares for noSelfShares") + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: allSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should have a share for noSelfShares from allShares") + } + + // Now, recover from noSelfShares + self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: noSelfSharesContext) + // And CKKS should enter ready! + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testRecoverTLKSharesSentByPeersAfterCKKSFetchTimeout() throws { + // First, set up the world: two peers, one of which has sent TLKs to itself and the other + let noSelfSharesContext = self.makeInitiatorContext(contextID: "noShares", authKitAdapter: self.mockAuthKit2) + let allSharesContext = self.makeInitiatorContext(contextID: "allShares", authKitAdapter: self.mockAuthKit3) + + self.startCKAccountStatusMock() + let noSelfSharesPeerID = self.assertResetAndBecomeTrusted(context: noSelfSharesContext) + let allSharesPeerID = self.assertJoinViaEscrowRecovery(joiningContext: allSharesContext, sponsor: noSelfSharesContext) + + self.sendContainerChangeWaitForFetch(context: noSelfSharesContext) + self.assertEnters(context: noSelfSharesContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: noSelfSharesPeerID, opinion: .trusts, target: allSharesPeerID)), + "noShares should trust allShares") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: noSelfSharesPeerID, opinion: .trusts, target: noSelfSharesPeerID)), + "No shares should trust itself") + + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: allSharesContext) + try self.putAllTLKSharesInCloudKit(to: noSelfSharesContext, from: allSharesContext) + + self.ckksZones.forEach { zone in + XCTAssertFalse(self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: noSelfSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should not have self shares for noSelfShares") + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: allSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should have a share for noSelfShares from allShares") + } + + // Simulate CKKS fetches taking forever. In practice, this is caused by many round-trip fetches to CK happening over minutes. + self.holdCloudKitFetches() + + self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: noSelfSharesContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateFetch, within: 10 * NSEC_PER_SEC) + + // now, let CKKS fetch and become ready + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.releaseCloudKitFetchHold() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testJoinWithBottleCreatedBeforeSignin() throws { + // A remote device creates the keys before CKKS starts up at all + self.putFakeKeyHierarchiesInCloudKit() + + self.startCKAccountStatusMock() + + let remote = self.makeInitiatorContext(contextID: "remote") + let remotePeerID = self.assertResetAndBecomeTrusted(context: remote) + + // Note that depending on when CKKS starts up, it may or may not have received this in its initial fetch. But, Octagon should force a fetch during signin anyway! + try self.putSelfTLKSharesInCloudKit(context: remote) + + let entropy = try self.loadSecret(label: remotePeerID) + XCTAssertNotNil(entropy, "entropy should not be nil") + + self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: remote) + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testJoinWithBottleCreatedAfterInitialFetch() throws { + // Our local machine signs into CloudKit, and becomes untrusted + + self.startCKAccountStatusMock() + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + + // Now, another device comes along and performs an establish + let remote = self.makeInitiatorContext(contextID: "remote") + let remotePeerID = self.assertResetAndBecomeTrusted(context: remote) + + let entropy = try self.loadSecret(label: remotePeerID) + XCTAssertNotNil(entropy, "entropy should not be nil") + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: remote) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + // And now our local machine is told to restore from the newly-joined peer + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + self.otcliqueContext.sbd = OTMockSecureBackup(bottleID: bottle.bottleID, entropy: entropy) + + let newClique: OTClique + do { + newClique = try OTClique.performEscrowRecovery(withContextData: self.otcliqueContext, escrowArguments: [:]) + XCTAssertNotNil(newClique, "newClique should not be nil") + } catch { + XCTFail("Shouldn't have errored recovering: \(error)") + throw error + } + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testRestoreUsingRecoveryKey() throws { + OctagonRecoveryKeySetIsEnabled(true) + self.manager.setSOSEnabledForPlatformFlag(false) + self.startCKAccountStatusMock() + + let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String + XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") + + self.manager.setSOSEnabledForPlatformFlag(true) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + self.sendContainerChangeWaitForUntrustedFetch(context: self.cuttlefishContext) + + //joining via recovery key just as if SBD kicked off a join during _recoverWithRequest() + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKey callback occurs") + + self.manager.join(withRecoveryKey: OTCKContainerName, contextID: OTDefaultContext, recoveryKey: recoveryKey) { error in + XCTAssertNil(error, "error should be nil") + joinWithRecoveryKeyExpectation.fulfill() + } + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + + var peerIDBeforeRestore: String? + + var dumpExpectation = self.expectation(description: "dump callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in + XCTAssertNil(error, "Should be no error dumping data") + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let egoPeerID = egoSelf!["peerID"] as? String + XCTAssertNotNil(egoPeerID, "egoPeerID should not be nil") + peerIDBeforeRestore = egoPeerID + dumpExpectation.fulfill() + } + self.wait(for: [dumpExpectation], timeout: 10) + + XCTAssertNotNil(peerIDBeforeRestore, "peerIDBeforeRestore should not be nil") + + let newOTCliqueContext = OTConfigurationContext() + newOTCliqueContext.context = OTDefaultContext + newOTCliqueContext.dsid = self.otcliqueContext.dsid + newOTCliqueContext.altDSID = self.otcliqueContext.altDSID + newOTCliqueContext.otControl = self.otcliqueContext.otControl + newOTCliqueContext.sbd = OTMockSecureBackup(bottleID: "", entropy: Data()) + + let newClique: OTClique + do { + newClique = try OTClique.performEscrowRecovery(withContextData: newOTCliqueContext, escrowArguments: ["SecureBackupRecoveryKey": recoveryKey]) + XCTAssertNotNil(newClique, "newClique should not be nil") + } catch { + XCTFail("Shouldn't have errored recovering: \(error)") + throw error + } + + //ensure the ego peer id hasn't changed + dumpExpectation = self.expectation(description: "dump callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in + XCTAssertNil(error, "Should be no error dumping data") + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let egoPeerID = egoSelf!["peerID"] as? String + XCTAssertNotNil(egoPeerID, "egoPeerID should not be nil") + XCTAssertTrue(egoPeerID == peerIDBeforeRestore, "peerIDs should be the same") + + dumpExpectation.fulfill() + } + self.wait(for: [dumpExpectation], timeout: 10) + } } diff --git a/keychain/ot/tests/octagon/OctagonTests+EscrowTestVectors.swift b/keychain/ot/tests/octagon/OctagonTests+EscrowTestVectors.swift new file mode 100644 index 00000000..ee1b70a9 --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonTests+EscrowTestVectors.swift @@ -0,0 +1,1872 @@ +#if OCTAGON + + let accountInfoWithInfoSample = """ + + + + + SecureBackupAccountIsHighSecurity + + SecureBackupAlliCDPRecords + + + SecureBackupEscrowDate + 2020-01-31T03:07:40Z + SecureBackupRemainingAttempts + 10 + encodedMetadata + YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ== + label + com.apple.icdp.record + metadata + + BackupKeybagDigest + + yFGtyxY2ZzDt0j/26GkNSmrgVnY= + + ClientMetadata + + SecureBackupMetadataTimestamp + 2020-01-31 03:07:40 + SecureBackupNumericPassphraseLength + 6 + SecureBackupUsesComplexPassphrase + + SecureBackupUsesNumericPassphrase + + device_color + 1 + device_enclosure_color + 1 + device_mid + yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X + device_model + iPhone 8 Plus + device_model_class + iPhone + device_model_version + iPhone10,5 + device_name + iPhone + device_platform + 1 + + SecureBackupUsesMultipleiCSCs + + bottleID + DD5E3F9F-3702-4789-8ACF-2D28BC86A94C + build + 18A214 + com.apple.securebackup.timestamp + 2020-01-31 03:07:40 + escrowedSPKI + + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC + Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b + 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj + Ug+fyh0c0xABOXt2Kdup7IYTGrzn + + peerInfo + + MIIErjGCBGEwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsM + D0FwcGxpY2F0aW9uRGF0ZQQYGBYyMDIwMDEzMDIyNDEy + Ni4yODAwNTdaMFUMEFB1YmxpY1NpZ25pbmdLZXkEQQTl + vn18gJwjGum8v3Chn9Yh5HM/VRLGuq6HAV4KyxlUm+w8 + uF80+32tY3/l9nKOmU61691beekwSWcfF+mDTGPrMFgM + D0FwcGxpY2F0aW9uVXNpZwRFMEMCIGOIXWe83FnflHu+ + yShdjivfTaPDFHvX+RYNgMy74iSnAh9OHeQzmDchZOi0 + 81lbhw/9rjEe8wEmozXX126RUOe/MHAMDURldmljZUdl + c3RhbHQxXzATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlP + U1ZlcnNpb24MBjE4QTIxNDAWDAxDb21wdXRlck5hbWUM + BmlQaG9uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJzaW9u + AgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEE + oLohYY3GpRSv20AT67jLJ1s2dKr+1bT8JoY23QkCeJgj + GNb+vutEQhLFjLPsENtNE7+NA7wgac0QAXLDO9H/LbpN + UP8DF1Q0NpFX4JiFZqG876jS8HEgR6VOOJzhJzUZMH8M + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEDRnS + sPQ/mTEl5dmMEYnQYhcm9hiPzBnQ0ghQzb70auYoPbCR + xjCoG7MCpbb+4JGM4L74OdbJZJbTtHeZ0JtCbqo93ZyI + fULWz131HsOyxowTSSI9yDiPAyXZz6nRnnvnMIIB+AwQ + VjJEaWN0aW9uYXJ5RGF0YQSCAeIxggHeMBAMDEVzY3Jv + d1JlY29yZAUAMBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw + OUFKOUw1MC0MCUJhY2t1cEtleQQgZlnxFs5NJO9YlR/4 + SDWH+e9rD/+Jf7lWWjMoTW9+n68wYAwMTWFjaGluZUlE + S2V5DFB5V25JOHZkTmc2RVdheWVXL0ZQNGNEWlJzZTNM + TW44UHhnL3gvc1B6WkpJUzVjczNSS280L3N0T1c0Nm5R + OThpTmxwU0hyblIwa2ZzYlIzWDCCARkMBVZpZXdz0YIB + DgwHQXBwbGVUVgwHSG9tZUtpdAwHUENTLUZERQwJUENT + LU5vdGVzDApQQ1MtQmFja3VwDApQQ1MtRXNjcm93DApQ + Q1MtUGhvdG9zDAtCYWNrdXBCYWdWMAwLUENTLVNoYXJp + bmcMDE5hbm9SZWdpc3RyeQwMUENTLUNsb3VkS2l0DAxQ + Q1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN + ZXNzYWdlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1pZ3Jh + dGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWRE + cml2ZQwQQWNjZXNzb3J5UGFpcmluZwwQQ29udGludWl0 + eVVubG9jawRHMEUCIES5okyKP4YMZqDjIGRMoLE83SYh + zjEyOvGPA0BoF6ViAiEAh6/dd57K+JBWmGXd4v4qGELp + vAeSjqcRUfdLtQj4DxI= + + serial + C39V209AJ9L5 + + osVersion + 18A214 + peerInfoSerialNumber + C39V209AJ9L5 + recordID + sNs6voV0N35D/T91SuGmJnGO29 + recordStatus + valid + silentAttemptAllowed + + + + SecureBackupContainsiCloudIdentity + + SecureBackupEnabled + + SecureBackupEscrowTrustStatus + 0 + SecureBackupRecoveryRequiresVerificationToken + + SecureBackupStingrayMetadata + + BackupKeybagDigest + + LTrJHVHFZ5vQO59wUih1MEgg1qI= + + ClientMetadata + + SecureBackupClientVersion + iPhone OS;18A214 + SecureBackupKeyRegistry + + AccessibilityVOPronunciation2 + + PublicIdentities + + + YYH5MIH2AgE0AgEBBCDeXT460rcv + jIDp8aJE+uDw1JKyosrd5OaCN/Ke + QJy+kqBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZTBjBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRIMEYCIQDOAegi + 450wm5Yk2Qtu7sSf4/jGWzCWU0a4 + FPRQSCgCUwIhANpyPSOc/yiCIIfd + YULrKwcZ0dm710etKYFNitrv8VRx + + + + AccessibilityVOPronunciation3 + + PublicIdentities + + + YYGSMIGPAgE1AgEBBCAmObm/AMsh + CPishw7Zj5VqF7pxEz7WPYFQoTdN + WC6PkqFlMGMEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEgwRgIhAKUc + sWDKPbwQt2TLHm2bzDWTVg2rOYrb + o+4sGs0sT5alAiEAv3x1jY/E/xXN + Jbex7oy7x0dLq4FGmNJFHWLQrDQd + GRw= + + + + AccountData + + PublicIdentities + + + YYGRMIGOAgEmAgEBBCApjqgrPqZL + BVUo4ShL7VlQX14zLBzgjiiVP6ke + WE57G6FkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgaaOc + o1aiL8bKLKXv4WmWg6kRwTFQjdZM + S+GRIJmxe1oCIQDAdSxG+N8iojUF + dRAMlGqgzMZMVxKZDiviyf7O0YOR + 9Q== + + + + Activities + + PublicIdentities + + + YYGRMIGOAgEOAgEBBCDXTpaU32V/ + ljxo71s2tcojaFlrzWTu93dunzeY + 6K5TK6FkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAMxT + 7l56PjtGjLM/rK1TLAeJmg5QkgIt + Mo77FSHyMHH/AiBjR6GOatFE+CtQ + uaz7uL+JNEoF0R0+1MykoHRSHqPI + pQ== + + + + BTAnnouncement + + PublicIdentities + + + YYGQMIGNAgETAgEBBCD0zBfXeZOJ + FS8oXM/hL8rH9HaMyKBeHoOKMdfw + MtAo9qFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgb/2S + ceDq75L07mzvNa3IgnlUh8hvlAAs + TJPyGtgFJNwCIGNWkSlYNNQEGUQZ + R9GHVgIWMD8ccRKjz17kMtdoJSkI + + + + BTPairing + + PublicIdentities + + + YYGRMIGOAgESAgEBBCBsRs9WTIBy + 92mIMVd6URteSUxiAwRpHEKiT1ky + 0MZPOqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgQDg5 + 9S8sDoDS4OkFJKCCOIo/0gkLy7ol + bA0ebbRqbOcCIQCONcU18leu/dVG + clWNgN4FPWIHMX3Xs6QD4h+hpJFs + 9g== + + + + Backup + + PublicIdentities + + + YYGRMIGOAgEIAgEBBCBezDIWdM56 + G/KBXahejdDg+W06PIZORqx808HB + k+J2dqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAPF5 + A/HcSV4gftgp/JNJt3YncN6UaO7W + fN2uLJpFVbtMAiBdbyb1R/79q4An + Mv+DFCsR274j/nc4TBJl52libm+i + 9g== + + + + BluetoothCloudPairing2 + + PublicIdentities + + + YYH5MIH2AgEyAgEBBCClfvDzGvfD + bRAjpecc9+7M+if4wO/tdWQ8vOb1 + 1L1+pKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZTBjBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRIMEYCIQD+DnMw + WzcKXCpNN7vODSoCFnuMeHrQV3Hd + E7W6PtJ7WwIhAPNmAa/o0hGaVoZQ + QMDMDy6x4aILZSev+q+H1SzxFU9P + + + + BulkMail + + PublicIdentities + + + YYGRMIGOAgERAgEBBCCI3XoOP4Ko + su3w8M+ECPTMCnjbM3nLmjK/6WlJ + OUoIgaFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAIgz + I2bYHyqRHAQpYq3liI6jtn8ZT1ve + /Pz6euQP4NAuAiBB2dIbtiuwSxgV + IkqI699bhauRROHjO9r48FrjrTJl + cA== + + + + CloudKit + + PublicIdentities + + + YYGSMIGPAgEEAgEBBCDX4Lqi2liR + QKhXA2QYm0l7edIQPhVLwuk/TWLl + yAT9PaFlMGMEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEgwRgIhAL2u + oy74rk2RNImZA2BlpEt1lbYXDjQD + LVWFl48ZiGflAiEArkFMxuEWlWOH + BtNjjZ44fmxKxWsZi8+NGAHfBCd+ + IAU= + + + + CloudKitApple + + PublicIdentities + + + YYGRMIGOAgEXAgEBBCAjsVTQ0pZm + rzPCJAdrUjU8RDTgE57XNKIyvXPY + 0HkVhqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgfrBi + TRmWf4KPF+HN26p3jCAjdIeTIySY + CHoXSYnuDxMCIQDPm8w+aF9D5f8n + ZdPGAJgZGf7IfYYej7uksgAfWpiv + 6Q== + + + + Continuity + + PublicIdentities + + + YYGRMIGOAgEVAgEBBCAACkc0AMRb + cY8hsM3mTlgYJovohPSj6QIjo2tB + hGJGoaFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgHKPo + mEfyG4Y5oqrUXC3ILH97fFYNLXT/ + vxnypm4m3NACIQDO3uZEcTXfDXT7 + 7iJlctPPnWtskWaGZdxaKSEdQ1Ga + BQ== + + + + CoreSuggestionsPseudoEvents2 + + PublicIdentities + + + YYH3MIH0AgEzAgEBBCCvNPJB1xx7 + x/4UOr+5IH/0UzVKX+QpvmqX7ODO + leMkrKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIGfKKUNL + wZhpIi9OIrEtkrsB7rzpdPRx/nc+ + pd53aepmAiArIUBx0EAPslG1TrYH + SLNo0XCtF4C0ihTQfaJPBAiyqA== + + + + Gaming + + PublicIdentities + + + YYGQMIGNAgEPAgEBBCDJbjy/eQN5 + 71Uz8wPWukKE0SZY/QvIlA4GfkVy + 102fBqFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgSrBW + Rcxox1/CdtChoDYXmabj8Y4vZYBS + LOgHMdIwKQoCIEkq6KImjlvmlWBk + ewyK0jUwqSyhtuJuJtXux0TUKIpa + + + + KeyboardServices + + PublicIdentities + + + YYGSMIGPAgENAgEBBCAZ2Mqr74uD + cAkMedabKkMBE1YVv3r9BY+ZQxiz + tbxuOaFlMGMEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEgwRgIhAJSI + 7dsRXpoxNc7bFCtPFSDwUrWlwNbN + oa+j9VpBg/nqAiEAuj1iKHKO5ixZ + 92iBCwS6tta9CNYL8DZMMoJYhrkg + LSA= + + + + Maildrop + + PublicIdentities + + + YYGQMIGNAgEHAgEBBCChFkKqgrWz + OfMgBCCorBsVT8hy+zmWs15UbouB + PzHsGKFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgJUhO + SBsTLydtk7Xu0V2PP7A+Q3VoDsDr + JTGWbd8z01wCIE03dzox48zVifu5 + Uo5LPTqD5n1HxwNX21flE1bs+W8Y + + + + MapsSync + + PublicIdentities + + + YYGQMIGNAgEoAgEBBCADagtpAora + 2dL8YgDGudGGs9SNDfTdlEkAmFcE + DYVR76FjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgYIZn + OdcURVO0mg3mLmB3McpFItiTlpsv + 0fhSNluJZHYCIEX2PE8he+N4PSLE + q4HDjL2NVwGPX7mfXhQR/mrdrD+l + + + + MasterKey + + PublicIdentities + + + YYHDMIHAAgEBAgEBBCDBd3m4WFN5 + LsrHxCmPrmepRrZHDyx66Xo8SFTT + 8u9bpqAwMC4wLAIBAQQnMCWgEAwO + TWFjIE9TIFg7MTdENDehERgPMjAx + ODA5MjgxOTQ1MjVaoWQwYgQUAaKG + m18QogpAmwTW7wAhpcqfemgCAQEE + RzBFAiB9fOTaJMlRDK+FkotvzkJu + jB1quh9OBx3CqmLNpiry1wIhAOJ4 + wV3ckIwdzk/YNkGZLoSP9GhxsoY3 + 0yQKPqkZzQEQ + + + + Messages2 + + PublicIdentities + + + YYH3MIH0AgEpAgEBBCC/q5CztxOc + zrhN7w5PxTq2sWqTTdIRGht/2++h + NuGp36BlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIECcCDJY + COrM8qBndA7BeEQh8i70wcFIk34v + 0hyC1VEcAiAdpGuOYOq8iCydXCrZ + kUOOCLK97fcO89AxaaDQ49r2KA== + + + + News + + PublicIdentities + + + YYGSMIGPAgELAgEBBCA3ZmHh5Ky4 + vX3DShRnlUuRPEIL1k/g4tvJJbkF + 5IfVWaFlMGMEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEgwRgIhAMeT + 2qHhhVTbb/0mF5IMLllOCL4wljRT + TVKzc2tDhdVKAiEAgJVLdcM90d+3 + j16ZxlF195knpfHs/9dor1wEIixd + EjY= + + + + Notes + + PublicIdentities + + + YYGRMIGOAgEJAgEBBCCKIp/yJqTm + 4Iuf/SWj8j1YQa6azRmpCY/bKq/g + iO6aZqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAOF5 + JxJkSDXw6hNSF9eJkwt5cKRsMMV3 + JuDJK/fBGW1lAiABjZZ1U+XzytGp + 5i1A6YgE7VVpR9btI6/QQi2iZbFA + Ag== + + + + Photos + + PublicIdentities + + + YYGQMIGNAgEDAgEBBCCcav3S7T1z + VLM9B88tyXLT6Y5GjRD2jCzDdlKs + YdfhsaFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgPwDW + JNcSN2+zAN47Hg0UcbnzPRbHJBR3 + JrDpBOEn7pYCICtNOoLuVEwfqX7j + A2fX7soQVUfT4j/y34C5CPrIbKxL + + + + Rawhide + + PublicIdentities + + + YYH4MIH1AgE2AgEBBCAO/9RLJMcH + o3qhFeFb3qanoK8t49rSDrm9ilPv + AeiKJ6BlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIEqa4Rq2 + iCw3ULDe3577bLpHuUyRvUDtEKE0 + rS7H4IIGAiEA4yG/enWyQuz+TacB + Vbe3U0cZ8mNarFnCWvjagNZ/BU4= + + + + Rawhide3 + + PublicIdentities + + + YYH4MIH1AgE4AgEBBCDfi1Ny5x/R + aYdLHWW+xFbNw90R5XCc5isHN6ud + qaGyKqBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIQClF2jC + dx76r4x23i8sBLm6syiQYYhvPmC2 + bEvnxPkxagIgUg/wLELGQMoReD12 + SiiQglIgKNtzSuCgRfdUjAYB7fY= + + + + Safari + + PublicIdentities + + + YYGRMIGOAgEWAgEBBCBqKP7jb+TP + nhhTpvziH9LG4aDa6i1IDLJmtFBl + 7u7AXKFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgYT1t + a5nB5G1GRccSzXyo84mvxb3xTeqS + V0HNw3zP9uUCIQDnoAU+3LtXDkVK + 4n51tfLXr3XZIVEwPGImBB/p2qGx + QQ== + + + + Sharing + + PublicIdentities + + + YYGRMIGOAgEMAgEBBCCeimmOmppn + EufS9uArUm8PTZ8AQfV1cAszCMD8 + uJoN9qFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgIyyv + XdIJY2RRQcBHo7Uf8qzZwq3GYHqK + yCbh3voiR2gCIQD/cgaeToE5Z7be + wD6evPVSPSXwBc7OH0FJFy+1iqCc + Og== + + + + TTYCallHistory + + PublicIdentities + + + YYGRMIGOAgEUAgEBBCCNrMVagA0+ + ttQkY4NGtYqj49b4PHHV7YFaAHyV + d9vodqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgAUD9 + nE+lBkcEnXyL0pcE/LE4diyBd/Ub + osjHyB5j22wCIQCUcJfgxHVChg8A + e6FjMuYjf7cVoyNf0YmuUEWkmwvo + Ig== + + + + com.apple.health.sync2 + + PublicIdentities + + + YYH3MIH0AgEsAgEBBCBC9NWuZFgs + rkDeXFDLnakWgoI4L/cXyz+m43lC + 2JWUJKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIGo37UsM + Xb7GaLeBwYfg302TWGv0xbM6XDuo + xi/RX09VAiBOSD4os5NX+GTYqLdR + erCTQ5dEVScIWaR6n45SATDuRg== + + + + com.apple.icloud-appleid.privacy + + PublicIdentities + + + YYGRMIGOAgE/AgEBBCDyKeoxY5kg + 0jXZokvw9XIZk/dXsLybRdeGyOhC + RXTz/6FkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhANGl + TEY7KpACQHm7qcSuuS/j63P5/AHu + M/CFNtpxHPs2AiBB4iFuMmexGzcA + dxjD8AweXzf3BuT2eAMPveTum/As + YQ== + + + + com.apple.knowledgestore2 + + PublicIdentities + + + YYH3MIH0AgEvAgEBBCBbIpT6tptz + 5puJ0XdYbcQiOBT9JDtH4o1W9en3 + P4hJPqBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIBEFJhmK + SW5huLbY39W2AuOZ7sMzOwTka/Bl + aOYDw/qNAiBNsupg44L53rbTy0+J + ItQBOKQPFMyS4ggM+38xEh1o/w== + + + + com.apple.news.private.secure2 + + PublicIdentities + + + YYH3MIH0AgExAgEBBCBjOqSZoGDw + ScKt5ncrZEkl/5e43V/wCItiOI3f + fCu3XaBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIBbcBuay + kWaCE1IFXL/4nmckm8tSDLnSLUje + T2YtgVB6AiA7S+NREY9sOh3WrB5p + VpmZfhd3Blv6JbeHkBsMjWDCUg== + + + + com.apple.routined2 + + PublicIdentities + + + YYH4MIH1AgErAgEBBCCO6YXL9f4P + kkoFCTOYTejP548/+n2QYLyev/v9 + 60tVSKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIG1WEsAe + upMhR1v7+1RxWB5AosnbhgnLueM0 + FT4xIYFgAiEAokT0B7qa+pQMJgVi + Jy48mJOwTbFTVcN9Csz1cbxD6+w= + + + + com.apple.siri.knowledge2 + + PublicIdentities + + + YYH5MIH2AgEuAgEBBCCM34oVJt4n + 8zzP2NzHDaKADwE6BqMEvWbXPXnG + LiJfzaBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZTBjBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRIMEYCIQD+HNJz + cwUhn+8nGbYmaXsYgjUN5IGBuhwG + kkws3W66pAIhAIHSbuQ7n6p/Rkjs + KOeVOq25ZcL+3hibiJJZIvNEqtSU + + + + com.apple.siri.profile2 + + PublicIdentities + + + YYH3MIH0AgEtAgEBBCCOKC4GWP07 + MXtnJuAXpyVkRwrXBhFMf1fEv1EN + L2HFGKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCID6kHeWN + nKA2CRiHtOssTg7KKMONOf5K8wnO + spBk+d9vAiBKRpXkBbHzObbc9Sz6 + 3WEfAi+2Z6iOZ+vVDVirAbFr/A== + + + + com.apple.textinput.KeyboardServices.Secure2 + + PublicIdentities + + + YYH4MIH1AgEqAgEBBCDtVL0VIeP3 + V7gD9jkiaWu4xwxe215t3PammS0L + No2WIaBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIQCLfuV/ + Hulb54Wrc8pNt1ibM8IFuN6XvkDj + ijiryyxGVgIgHfaVTZE/F2b02h4X + aAPBi1YIDvMAoycxd9ylXQI1cr0= + + + + com.apple.wallet.paymentservices2 + + PublicIdentities + + + YYH4MIH1AgEwAgEBBCDMr1rH/wSx + KnXhhMuq2kmQAsbuu8aQ7CUjAaP7 + ltmt56BlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIQC2O2y2 + BdX70rfntL/TRaSfQ2hi2HDlJRcD + Y4Ac7dTNDAIgMCCNLTjH3w3yanom + cdUpUYpUXk0xg7rmWv776V2/ph0= + + + + iAD + + PublicIdentities + + + YYGQMIGNAgEQAgEBBCDcezl6FqtG + yHkX174CEG8VSAOi4P3lIlFNO4qJ + fVX0saFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgQvuS + zR9rw1O2ySTcaQADxxJd1GuffZ2c + xK1kGvS45cUCICC++3nOux4yl6TG + ku4P9QDla3NQp/7hH+lKmOIpvcOk + + + + iCloudDrive + + PublicIdentities + + + YYGRMIGOAgECAgEBBCAXOlNsMQNV + JQUY+dqcGt39XUTbDVT2ksgEBMVv + yOjkPaFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAIL+ + 1l8MsRW3rN9wMeM7tSinakp/c2/D + p2kO8Z8OZBxSAiAL15IC/CrJgkQL + yS4rarGeTmMFKGz34i/jQ1AQHzQy + 0Q== + + + + iMessage + + PublicIdentities + + + YYGQMIGNAgEKAgEBBCDK+TvjMZ0j + zhAklsGuo1nbUpfAsRutInhCa0uX + k/HLA6FjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgaDaM + i4SMzCnvHsQyB4k94BaG6y34FbB3 + LDlMT2pa7EYCIHJGgdwlbbRfFyYz + j08ohfXpCRbck5akTbDkOxRYIdyB + + + + + SecureBackupStableMetadata + + EscrowKey + wVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3k= + LooseLeaves + + AccessibilityVOPronunciation3 + + + ZIIBnTCCAZkEUwEA7coGYUYS65YH + nBubKFI66JIshlD/zcZadtS7UPht + /gQw4Na60gEDpn3LLWAPmNzSU5aF + q2i5FdGApmZz2ZjxJhKs34OzsSz2 + kh2Dpg1xkYYABIH6KTIPWejPTEmB + IMu/M8MHedxNSBN92aCUaaFKlFpI + Efr4ERxhq2+7aqBDUod+agFjj6Bz + Ei4NBHu/j4LZsb4fcOMwq2G594K7 + cevsVg5hsWb800lTOnIWzgnPfk// + T7CYB3S5UnPQnLtORz7gQZzWlqlo + HJSGltcXdt9nF5hOsawKZttCDaL6 + 0j00MtfeD0WO+aLl2BmD8syaCwNF + RCG8zplq3ot9Anh6xzoeTGzljjuY + mPQPAKVFkUNyBI81ZK04m9wxPUh1 + 64CPXdv2hsm+zGqNrTX1sny7hlcA + VbMXspR54l7EpBlHw0hO9D+2wtrf + I4cwtfSpKFG9oAQgJjm5vwDLIQj4 + rIcO2Y+Vahe6cRM+1j2BUKE3TVgu + j5ICAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + AccountData + + + ZIIBnDCCAZgEUwEAIkREyheGTEpx + 90YhB0zt3gW7v4Jjgs2YF9K8fDOd + GFYwGDCkB4bB6j9FZr1ZEg57UMjq + djwsUAthex7ePflo01Wn4PzatH1r + LOwjHLfTO+12BIH5P5Bm3AyaWPJq + W138OzxseZfkxmZayjGK2tHsbrRi + gth3AkOUvysatYcgmAzVFfBUITc2 + F2eUOMlX05Lq98JWGJUN1wx6LKYK + CAmISy7GfaDDSWd35YlSRXrYHl2m + kDjGpUkUT4RB2REVsBH6OuOXM1NG + 3sFrV3Mx7LZt7qWt8j8fbpwT9S36 + l77TyJIMPu/xkywGxLSUP5UDjiby + e/Z8T1SEpqyikOx+r7/YY3iZczIi + KcDVJCkzxQbEGEka4a9r8h35SgM5 + uy8bzjO/heXIh9OhxcKv2bYqQbln + bMjtL0vLqp2ihT9blHf7JZRrW/86 + Yo0hO1V3e310BCApjqgrPqZLBVUo + 4ShL7VlQX14zLBzgjiiVP6keWE57 + GwIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Activities + + + ZIIBnDCCAZgEUwEAit6fWo+OJu+u + 0AmgeLcyLkhTi2UnNSi+KCrMPwq7 + cLkwDDfCp19sx91iRV66MjOXnyac + 2K3Z4Ne0Yu1pTA80NvfKboJngDgI + sGXGdipH0RiWBIH5IVxHisC8FLLk + JrToYv9zZNkscu5xh1v9/RC43IEQ + +1VIYwvzCkUGCfRNg/rf7mHIT4o0 + nQppvEb75QbPXoHzB2TembqJYBID + ltYQBrVSwII0rwDipCH+LrPNJkRc + QoyRuVsH2baT2e6Jz3L630zc4vzm + Dxt2tPEWfluCjjQPkgX96A2mF0lF + F8lHIQyVTQOxs7KwgrreCk92/XVP + qS/31SlphaMV87/ZCnKtMpVb0F3u + GFM21274mvl+83giEOUgMqzDhMqO + SJ6MXIgW2/lYpBz+UKpLZVHNnYzA + FIO9soDHThSGR/wCjOFVo2PhYruS + 9zwtMg+iJuy+BCDXTpaU32V/ljxo + 71s2tcojaFlrzWTu93dunzeY6K5T + KwIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + BTAnnouncement + + + ZIIBmzCCAZcEUwEAt971wW2seGN1 + VyUtU9Uo26f45e+nwJSlPDuZnJ7k + 8YwwrOft/abFvpL9EQi55rdaFcWZ + MA9Nm1kqyDno1lScw7YDhPXFOFmu + RLiUcfJcVu+lBIH40fYFa6SwWaS1 + A4fpAmULHHJpuG2kya+ESnHHZFw6 + G6ok39oj0ji/GRTW5WsWhjMxn7YM + ziN7ZUuImxTbNFQyvTEymOVBaxxR + 6MD7Bg+yie/glTHQdFUFlxnOimIz + C6AsPCbWm8Z7BDTEr6i7t4f1tjDu + eAT7Jj7Uxe9W2eQzx/+J9JbjBPSB + 4OxHRfqpRc7DeMMGTZy/fAQKND6V + AMYPdhnUARGxAkzkUf8gAmJD3nc/ + v9NGnU6TLtxRjEytKSQhUy9A6zyX + YMxK7nyv56dTPMGnxg8uIOdNIixA + DIhy5WeV/vUsn3sabMHP7tyXcnMt + BxyawjgsL14EIPTMF9d5k4kVLyhc + z+Evysf0dozIoF4eg4ox1/Ay0Cj2 + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + BTPairing + + + ZIIBnDCCAZgEUwEAQ3obteunNorD + 2SpZOpGB+88OlqQgI4mYVzIeqYzr + MqcwjpgS+EMayACEgCy30mwZkXV+ + y1mxtVo8Jz5sAHprj3wiiyHrur2q + uQnLjJJ4s88dBIH58t/+KhpQs7BR + mUgocoztX8bNopGuc08Uq5hHiBeZ + L5Q72jHu8wRIC/SSuz2o+THUyF8J + duh8fnOanFdTTVvm4sZVONCKCHF1 + O2XAy5kOeYRY43/omrS0rFyELiSY + 1ABalykBCBQYH/5WCzGAQnh3h6s7 + lVuYvTpsFlz+wzWxXnhAH0HVST9A + f8COEpidxATAZ7OTpBAYD9SXvBmT + axSsB6sPdhQ83WLGFz4D+W4raymg + uSRIQXUUjw0PSP2LPIaWagww/4hE + ZGp74PILQOeiOzBjeeNbzTdr5r2n + IFCcQr1jmYh2Eb2fhB+HjU2Wn9EX + 5yd6VOzXfqAOBCBsRs9WTIBy92mI + MVd6URteSUxiAwRpHEKiT1ky0MZP + OgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Backup + + + ZIIBnDCCAZgEUwEA3A/n4WhznwF/ + LvLzAhTFBE7oIxKivBNqU7OSE6FT + GWUw5pLbLd3Uq72xUPHw4nDGp7mY + m/aNK4J9BKbsgmKDLNVwls7anxkS + JkA706XCsbdgBIH5It/fR9OHWKzu + 8iHEaf7YYhQSabWoNfJRpZS1EkNV + e9DojJDJfg8ExcQQsPu6JSLFhQ+a + cvPEWsoKzW0PIsVb5oiiqU4WWeAG + US5LbxAENGeAEOJqbna0D7iWXHkm + EGtRKl+raWSZAsXAGpSKGy9efsst + DbNGOcN4ievp8DnSkFwSoQ+EvkUA + Mb1MoiCCCB0NCfn+MK8LIg0g+MhB + Hp3lf8HC8Aie+gcj5hzVesMeG6lj + OOeBVE8BS6fUet5IWoSNhhRyDoyE + 0V5kja4Mr8hY5XnB3G0770VoDwYY + mPQj0jgrG+jS4AQsSDW4PknNxLgK + Hk/7StJ7vJx6BCBezDIWdM56G/KB + XahejdDg+W06PIZORqx808HBk+J2 + dgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + BulkMail + + + ZIIBnDCCAZgEUwEA8MWcOAuFRzvg + Ybrd2u3dBi/D1UFZ9oqNL2EdTjM7 + 314wOTSbbAqyhIYWd5wkNwbwh4QQ + ZN5ZKEcv+VpIOLTc5gg9dF9GAtq7 + iWQnctLlI/RZBIH54/fs/QwzrSJh + en5U1iskhIsWbBzdK+QtdekgVFYI + P34Q28Qang7eN0hZo+ndyiBcqHJ3 + kL5mfk6ZIpvcUHFpXgC0wwxTgDDm + T0yHAEOevwgf2Qng2jobFp5PwpHi + wmqCI4RltMVMwnnv4vh8yM8WZihe + sZEXMBiqS3gmWRk43dBTCKAzHhKP + lR82vZHOTiJDbj3Ewpnu2MjfjMFL + C9wi+Dcuk8K2a6YRq4N5voLQ5Aiv + KO/rW/Te7P4wrObgCEtTWZZETQmE + QjMa7uGqA8rD3yoWXX+TcVIj1Bhg + psCJUT6kyYEvv8Y5q9oCYMMLy+6o + 2trU56gfq1xMBCCI3XoOP4Kosu3w + 8M+ECPTMCnjbM3nLmjK/6WlJOUoI + gQIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + CloudKit + + + ZIIBnTCCAZkEUwEA7mcfkI9joA5Y + RiHMKVPYdCl0EZbdHHSkd+XbtD7M + z1swmsOp0wrFLe6Vs8Fl/eLiARGA + oFbEyqKuOqGBvVJcANDyON1SpccP + YyE+m9Fv1N84BIH68b9LFxZu11g2 + wdpwAoLfHGAIpixj/l/ExdN1SejD + h42zj68oMRJipC5Pzuy7Rsfo8hBq + DgSCZQ0ASzcyZvd/r1eUVlkPdtfW + 3e1G8CiLvEJjalHXMK/q+ZkT5ix5 + RrImOK4L8KpwVcLyYf6RxPhvLtQI + FuyDWZ/zcGeOQfXbEU0N3DEcM86j + T5VpOVvbejiFABDV2auJtxAzcbPo + imkyfQH6B0hb7J4MoUBqojYp3/Wb + Xgd+xsZueOYaioaD5F47gGJJt68v + V79KNCrerlvSaoAAFZMT3aj1EfjW + zc2Q+XU2ugjdA7yNrxDXAtzteqcT + bqVa7k48t+smmgQg1+C6otpYkUCo + VwNkGJtJe3nSED4VS8LpP01i5cgE + /T0CAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + CloudKitApple + + + ZIIBnDCCAZgEUwEA2gOwrczljkPA + WHgRADJ6o8gdgLyxKKfRWNqWUnri + s14w5TsyO/m09rQMYaqozK92iNdi + KgZVS4ewntjnRL0MINfQuxE83RV7 + rGrDO3oEuJ6cBIH5V8A65gqIk5kQ + 7ZgU+4YDOpi8zZcfMSPbssw5fPy2 + RcH112RboQAPpDRWqfRA+v6ozvIU + BLFt3yHfhZLpd13PbxxjaSKjxd/x + LhdMWk39WAcIlIQFTyurBS3C0Nsf + pH2oVVjoOaLI/iv1cIITjgHgjUcQ + oX161WZTUcp4C7GD6eExWGNfc9lh + 7jEXNoutRL7W2eBMIJbca0cNaoen + zh8Ee4t/CNeBuWe2Ex2ka+KZBRGP + Ruw4o5T2W/iCOu3dY+izFhzp1BLZ + 0AbBDpmEII7+8evOrXHqYX7rEt9F + te5bDvZoO1hmO6sIuuONuiK9ad43 + zWXdZMqNOZk6BCAjsVTQ0pZmrzPC + JAdrUjU8RDTgE57XNKIyvXPY0HkV + hgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Continuity + + + ZIIBnDCCAZgEUwEAEJ5swAeKdGml + KBxozSTpsTC97zVft9/MWvYmFdVB + askw0WgUkVHiegWuHKE5xphAVwc9 + 8fEHr8WdxDfrbg0k8X/oUBAhjK09 + QFBdKAAT6sAuBIH5MiYviQHOuAnJ + mFIVlH6qMoiv+JHzgkXl4futwcwV + oI/t8Y8VE81qeXgP6N6y9iF/VpRV + GhVqaD7jNqXjVFycgWrwOXHYF5V6 + HgxGIGe7/lIIytjAy0Ubrn4IZGn1 + hKGmFM39r4hoFFn4UYL11wXTl3xC + BxG+Nt66tnD2tZSMvlVOkBi1Z/uW + xFsm7veDYzCveRI38yOKmdmG4zkn + fw+AQF8tYcWOKYe39TKhwgNEYe5/ + WI9/3CxWUqxd9H0g9wb6OOlUjnJE + Jf/3uoYFLUpAlYLyDP8JlDqDad1T + xL9wdUmt+DeiHHTC72wHCt0Q1Tnv + HJhBBhiUR6x7BCAACkc0AMRbcY8h + sM3mTlgYJovohPSj6QIjo2tBhGJG + oQIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Escrow + + + ZIIBnTCCAZkEUwEAq92z+A2mGWee + OAh6/oSmx+1nNN8OVrv0OZFF9ACP + 0L0w3Tq7x0BsXOKji8FqrajsM0b/ + 9vvFNDPKpeD0iM6qgjnOjXhTEVU3 + 5BNEd9eXuNpWBIH6NWYRYQLnDg/R + X2JWnmomZjRrOIr058bkXVsn7nbE + CP5XP8UiniHnk1DchxDMlkkmckV9 + 612PnxNyegWg29s0i1hf9s+NLrhk + 3KQEQ585xa6Ghc14F2oN8M6T1xMp + K86u3bO7NeSVJXbst2LqeGFYf6no + p176vubd+jrNAvMVemeCADoYLyDY + LgNmAPrVfQC/THUMQVMC954K12m6 + 0I4xoenEvFOR6Vlg4wyuR9eJCcUh + b4+iqBQO62xtbxakcQETMx4GBL/y + y69NTEfA+hGKD0uTqiU1PTGmOtUr + KTfH6X9y0aju9o0B5jAUMJ6rkOHu + nLQr6jYvW+L59gQgwVKb12gOwEEt + jafTc2RgvD+ONtNzFtZ/v9mEkf1D + d3kCAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + FDE + + + ZIIBnDCCAZgEUwEAMAsrg/pUgwcX + RauUPBcyWRKaaIrhSthNfvQSO2pB + HKkw8daKeW6oP3npBiMnXgGZAohM + k5VD2zlLd/jHgN5vL4WwoR0ohT2c + ZjYHzUG81P1oBIH5TR0h3tRdlap8 + wORCCEhoRaZOXozPoQLc6UQb06yb + KSG54WqWIeiYDDYBNSJ3Pqn7pTIx + bhyxg569iDwnBWlHZcOmlbTQPePx + 2r+Qysu/a8Pf+S9IYBkz6BCBoS8i + K7d7ZonfO6P6ObuXHQXIUeDqeCqF + CwYIVslDBViyywv8v30zmKB+Gs5C + IlwrkDUeXGjimKsynu5FghhOKNc1 + hrmfn+XLV8Ht+eS8SkcjmuZ4NAiy + 4YZpyKGVX8VEC7WtwnVQv7Dj7+AB + Q+dZYZZDIMkRYLff8sP4vizqDK8/ + wXOKv06sBpSG1avueWr0O5jXxLdH + tqQjjFU/fXPPBCAkfz8NsHhEsMkD + wr+lLP6dfwEGvs83Be0DwG+OwI3G + UgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Gaming + + + ZIIBmzCCAZcEUwEAL9qPoxGTOloQ + mg+k5v9L9DK1FVDLI94ISo0SIl2g + IWswe/PThv4UwYAvYy151JYnVXRG + pIglXCh3wMmRn/HeBt0pwoeVc8Qp + tw60Ds997cnEBIH4Pi3mibPRMb11 + 8nGz+D4A5bzm/9+SZyW8lXsr9vb9 + CppQEXP3xp+2IosFV3J8YgZhFkNk + foB9fcjjSuk4NE++NnoGXG3FqT88 + UrvDvpykFttHs7odv+n1yMn1HYlO + KD0lCrp0LAzsRrDfm8rQHt8XxACR + mBmUGuR/hreDWw+kLaeWfi7YJ+UO + lCmOJWo02jUyusVoasNyYh09oCJP + 8P+jnJKaLbI7uJsty5kLMpVFHqP9 + RMYB5GQT0n18q0fUEO6XREgBSn0S + Og412K7XjJaZeqE0DqkF87Hi3JLg + 1zRjAGS2B9nAes/fntuQco/eyCPx + LHAsqDaHsecEIMluPL95A3nvVTPz + A9a6QoTRJlj9C8iUDgZ+RXLXTZ8G + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + KeyboardServices + + + ZIIBnTCCAZkEUwEA/tGjVinL3pjD + EQPaRVbA1KOHUUWoLy2O4ImMlSZP + Qxowjy3uVmizCnwAr4HCq8tQezOX + 6Rmr7UYEf4CXVQ30BCuKrTC4iIwt + mvqWuk68Fh2MBIH63FQzTbLYTz8H + meAieQeF7vk39HOcW1gJIu4nFk8n + x1sc+sA56IWcFZYDHzJsauykjz4s + ezTE/45Crpl3qiCgnAgdQ29fQnDZ + sQVOGChZI+H83dN0lobteC4Nsxkx + EOWS+csPvEYREAcZWAz8C2cl2MEA + crhKqAQ+0QxiorH5Coif+M9+nnTR + AAPsmw1MOqA7JNecRfwV69W8SjAD + 8fJcx46hH9aehHd0eVgxUZz9qoXq + VbjOEFL2Zx1aYvqc2wGyWEUIDmdC + Sof3DYZ/U8ePGQteXjTduaetIfTD + N8+4gE9/APPDiVNzwKaZQYOGshk+ + DZw7wedOQwn0wgQgGdjKq++Lg3AJ + DHnWmypDARNWFb96/QWPmUMYs7W8 + bjkCAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + Maildrop + + + ZIIBmzCCAZcEUwEAq3Qy6v5D1m+q + f++g6YHn64jfWkV8Relexixw2tY8 + GdgwJ6cmMqCgtvNO8S+o9/s2Q7x1 + iY7Z+D2l2YS6bo5QMtr2XxZtL648 + vKlQXw9m+TeDBIH41LFxD1yx7/x4 + qYqVSUgiWJJQVHgj5ld63Fxrf7SH + 8JMqluC/D232rw3aGNrIbJ9De7ZZ + B90/2BQEvt31H574yy6AA69fr6EI + gZQDw8aYXye7H0ZEnUIvb0vJqhxJ + okO8+qLryVYZp2b9VGmAtRCtSJJm + o9SQqBzYVDyeS5Fwe/7qTnYT/6f7 + 0frJBen0IMB2F6B9Ymh2EfB5mgIt + YvQsi/iedZ0SoShEhELv/dkMFQfE + sBL4fWGgZdXWSIvaQDw/r/t1p5Qx + CgFazEZ3P2Nma3CONYe4DdmdzvrC + 9pU/sngdKk8W+yKB8XivorNvSA2v + ItMNxcrBPQ4EIKEWQqqCtbM58yAE + IKisGxVPyHL7OZazXlRui4E/MewY + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + MapsSync + + + ZIIBmzCCAZcEUwEApFg3dOexxalj + 8nUrzt4S8lvykjPlpatoQaZV5jXH + utow2+O3Yevp/vk2zN3BZA8Z57Rr + irw/eSC66GQAIdaXTkQrQT/4pB6O + iKxPo0t6Zy0tBIH4khoiH57Ia4E8 + v4OSvsWDJhdW+VG62anIBrNq/VjN + YQGe0tNceaXA1xDmmCtATLQzjiZT + cHCGXn5whPdXaNBnpWJZr5S2v6zF + Hbja5DQKAoJN9tX6SiHsnkjFKblN + 4FzcCXZwtcatnvzn7quAhczRe9MH + aS6Fjx3sll9v/fhoVv59f8+NBoQx + ZKsEJVbJ3JiR2K5Gd5ddwMhckZjL + 2ukh2zheY7nH71M/0h+5tlvQD2JG + AfGjjsIco0wMFkZRcB7TcnklYVrk + +pn/Qvz8GAWmrThOJpwoNmYSgaSm + +R2M4cL0KLSvuqyHjDHk0dDjXgoV + U6FcHhuItnoEIANqC2kCitrZ0vxi + AMa50Yaz1I0N9N2USQCYVwQNhVHv + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + MasterKey + + + ZIIB0DCCAcwEUwEAl0pbM+TN/wyy + dy8KAtqB2Ra739lKTulOuUSwbnNh + 360w+LwPDymGHkz8b9qb8G8CQysT + yrmi+cXbp9WY8PpWpxSfrzK78mGE + j5aLPVEHXU0sBIIBLK9R/FnK18rb + q6AgmjGZid6JlPzBvvGN6C73embB + eMYoALRyxQ/DZOk44jzcP31LYfSO + Co+Q3MEKiITdA2wp8csupYRh/U1b + iFgsin+KeGi7WchB3GXvsE2Xiyvq + p78e4V20nVihsGjHfAGgJ3qe7JjJ + Bxfs8+SojxfWRGlCrjjnFa+yY0Vz + XgqELEKP+Y2YvpPoSxq5NYWTbIkF + 29mlPT8sbI0jW2odY1cNzuPKCQEp + nK9o8adqOSIe6Rq+wtUVRaAuN04N + CQZD8oVfjxTdPGq2EXlbUx+5po4K + /yCJzA4wBONR6nxzc8AsF0rycSop + 1ZaYMONrMjQjtR1/JvVZnNnZWBSD + vBz/74gdRPui0jG2ddKrubI1pZ7T + oELHtdw5WdGRb+LVkDncchopcAQg + wXd5uFhTeS7Kx8Qpj65nqUa2Rw8s + eul6PEhU0/LvW6YCAQIEIMFSm9do + DsBBLY2n03NkYLw/jjbTcxbWf7/Z + hJH9Q3d5 + + + News + + + ZIIBnTCCAZkEUwEAbLiwWK0ZW+qd + E7VQF/Vgc6Ca06iAa0KjlCHxqzfa + QWAwTUxr9mwi+sFXnZtJZS1lxjmf + 7Dkz/lfogz+o2A0eUMtT2veBw676 + 0wjRg1OUVEATBIH6uUM8GHhyqc1v + eSwAwr1M2jpDpw2T1KGfjKYIlD3l + AKC0SEt21m8KWdZbK9wIpK5XKblp + mqZ74iezeRWyUm4wYE0DaZQd0uNp + De63OU636GybAXMvJ3NbNbBhoXsS + 7Vrjp4luJq3/Hc1Z1v8Bs5/VU0ca + KAlH/MxLNJnAFu3wKzOSqpqvM0Al + XsrZd9HaBOKTz6cVpb46eM7GkXNy + YfoFripk2XfYIgB4ZTRMJstAbw9i + AxcSfN6UE0VaVYk+kcfcC41km/kt + 5yQXPEteuDhTZF36Ls09fmwRjry2 + 7O3gzYtC/N2bcXKEvqMQJHw6972O + NBjNkxyvkdyIKgQgN2Zh4eSsuL19 + w0oUZ5VLkTxCC9ZP4OLbySW5BeSH + 1VkCAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + Notes + + + ZIIBnDCCAZgEUwEA5QBs7cwCbsgx + b6+/WPrQqmz8PyGvRm1M9by43vPo + XpEwIvaozyKcDGBuIUOKXPoZHm8q + MLwCqjz3la7fD2E8zysNgHx8R94d + Zs6RTFm00Kd8BIH5+z6ZZmeFMqKu + 14NIZXFS4lpZ5wVa0dBMzkU34qNb + dfzIGnOrtJdvTdBjlt7RBpwjdnxU + Om9+v/7OqzfPvu7Jfs7knMiDYNdd + 4VV1RYSvXngW413oMoWQrgt7Di6D + 4yEXwB6iCTjo4eRzhwRKqGVXL+MB + bzxKbQlQ5T5GmQO26dHeOW2bomPa + RP7an00X2C82dZIO4ri0HO++9yhA + Optmyos5C36lj4TASVuyHJddwmoj + RySv1ma4DezRxcCZzY3MF3ZjUIIK + pIX5NzNCkFbCFYLz/YJ8vSmNm2TZ + C4FhwSEPI3M9BwqSdVXzVTO7I0CN + U12UPyTaW6exBCCKIp/yJqTm4Iuf + /SWj8j1YQa6azRmpCY/bKq/giO6a + ZgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Photos + + + ZIIBmzCCAZcEUwEA5N7lj1BTLUER + P51xbaN4uvwmaMYtYNZfXtNEqvOX + SL0wsbOiat59vkct3mt211TBke09 + P8RBWD5Sqzrdfhutqg88shqDVvNP + iYFzHfAv6syDBIH4o/HHz51zYY9J + hNwCHW8G//opH42HzklRulXLOFy2 + 3QwDRUfiJIae2P6Y8sTYbHU8NbuK + BSEos5i0siIdqDD7lXi2/Y68uu6S + k2jNnRZS2sfO9qOFGOwZv6JGDh2i + 3YBAptDnESr7hlvAZ8HZyrl8SYi1 + IN6R0DHalhTF0kx+K+i78u7yqipB + H6oUeYc6GuAFYkkYt1E2os6b2M1+ + H9h47Skl21hvah+UAnMXpRHuDhFR + dNXy6LtQPmKlKOStp6AwS3JQfTEv + 1kEdUv27R2MpQib7pQwXEn2L0MFQ + R4QFj1TPG7hPkHPI25hotdFod0dV + 0v0LK6S2Af0EIJxq/dLtPXNUsz0H + zy3JctPpjkaNEPaMLMN2Uqxh1+Gx + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + Safari + + + ZIIBnDCCAZgEUwEAbbqSrvyPe8zp + 5T3WiZy6a2oIop8rT9+jxu7K8kt/ + UTcwK6jGuKAWyE3vKuzyYFZsD6W1 + 7aCq0ZGfCAxU7LOg+Ss+T5AP7LsX + RsLuG4qs8c2QBIH5DVOG01pG8RvW + FZxMYkq4xHTH+XPP6Mki0ppRbiqv + vXk/R3i3CWr7sdRcgHLrWEuu20b7 + MOujrqRatx3x9LeCydhiLgmr9G9x + Rm8AmRlcYipgD49Dsvd4BF4NkNWS + jtc4A645IyZBdH+GJ2JWQOtubT8p + GWEES2waAuuUm47FftMgdH33HfjG + ypG7d6f4rnoU5NgrauIrz8uA9ezT + TJeJYj4dI4AJ72LA8FnlZNPJ+p2w + c5CWTuLKHKjcA+DSJirdYJGFusTj + JiBmPBzEfHWTU+dEcehSCMxJnsK0 + sKYUy8Gx86NMB5T7qK8dzgvbep7B + 4iivY5KjPirOBCBqKP7jb+TPnhhT + pvziH9LG4aDa6i1IDLJmtFBl7u7A + XAIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Sharing + + + ZIIBnDCCAZgEUwEAH/kF2CGnaMF7 + EeY5ls9Fd5WSvugys6kQdLxXU9+u + 0xgw9ZoHh1n6tl/l8TjVn68IfqcK + UtbkGEgcwgPj7oykBnDlUJxEBdW/ + LtWleF8Xp2Y1BIH5zaaktjtHOx4k + bXWPLNKOdF/zLfiGnI35fpzSZzLD + 7F1eanbVaIAxWcNNO/83Q7qirjcO + Oy8mU3dNQmE6+x7owH1Bpxk97IJX + cqL62Qm8tbeQG+K2w5iq+X7CZYzx + wKlo3pw5dgzuBSPv7llYcsjlzlie + 3zYDHFHDpXhtJM/pgCGcZ0xxJDi0 + wO/eSc8eW+6ea7S9F83aTiK4lDiN + l9DnDcowEpXR9mBzvWRyaf8yXO/R + 2wwZbF9X47eYfeB7r2AZmyhnoQdt + doet0A27Cp6jpuvBFvLiLqR2dDhR + OnY/2LsluiY6qTcsmtcoOliHNjXk + VXQWRizDA2ZOBCCeimmOmppnEufS + 9uArUm8PTZ8AQfV1cAszCMD8uJoN + 9gIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + TTYCallHistory + + + ZIIBnDCCAZgEUwEAxUH7GAzWiPzn + ziecAwy1WBgXS+jYd3WPN2bYMol7 + ZGgwOPm2ifOo7M9szW9cjl/dI3JM + 419ce2yWog/TbFJ2cAWKpfB3WsDE + 0cyPrUBYHIJ6BIH5ImIZ9NBEdMrP + e1zKlrFLEnwOxncJCen7RrQd3/bt + WSG42saJI10Zk8lQSW09YGJ7xh8Y + NQp2IOWKBytmxdvR9jAudn/8z4w7 + NXWqhfqYpjrzVmG5nz9XTxt75DBz + bozqsYvKVQWfmq/C7FXRPP9we27S + KXjNNnMgk2u6ircum+tWn9OftEEA + s0EXGcI30YqoTKcgLsfyGGlTsG5C + 9P9CffzpOtrzY+nprBxZSmIScK4i + FTx6N8w+j9S3lQeqTLthvBH6DTc6 + 0pCCF4OnxgWpP9POm9IltCgo9WJv + llIGI5T1WT7C7SgMpxscLu84aCrD + EUdxjL8SpNBMBCCNrMVagA0+ttQk + Y4NGtYqj49b4PHHV7YFaAHyVd9vo + dgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + com.apple.icloud-appleid.privacy + + + ZIIBnDCCAZgEUwEApcI++fPiMp2F + 7719sTxSJqaM6ee9DlujcuWuzM6t + JVow1MYYRnnH8QbtORp2/ddi/I/o + OoPNQ7y8LVOGFVyJoARvHXAuJbiy + oT/PNy3FzHjbBIH5rEU6m8vdSuPs + 0ygcTuIPvXnGDYdkGzx4c39oflgm + aFgUsuW++rH1HOa6cCgJ/lstbJUX + RWhgoOMro9kMmgI89wzcd5DSBiG9 + UhQt9ZDVvWz262k5O01os9poHy5Q + WHECo4HqcfykUXLt/pQUo0QcQ9b4 + xGRis/X7vzpprRcK8M983alsaJH6 + Zeh87J6DDPajPfxHN/HPzB3D+Gkl + TSbzm+WRA0d3Iea3wh5edoJl9HSq + Xgxx4UFnpQyz+Y9Yl467o7Yn42/C + +2IvNFRQM98STxWssxamHdoHl5p1 + rUIUxseaHYCmdhvMUAslosNalc/p + wDmXbrlFVqktBCDyKeoxY5kg0jXZ + okvw9XIZk/dXsLybRdeGyOhCRXTz + /wIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + iAD + + + ZIIBmzCCAZcEUwEAT1yMt7X/tEb5 + DGCA2BPD9zgwPca1ZgTNiFadCztP + NZEwQzlt/Wmok9wBFnZtBF1eSoDw + W+hkyWSHqMLWbw7nhDCGFsK5mhxX + SD2syn2d4JYBBIH43drE0fkWOe+h + /k/tlsA0K+MVK4mjDGX+Rob97aDe + +AK5hR4Td8TOTPdilMfO4o5DpToD + Q7wzVF+tYqesLviZcTLlbtK+8+OI + bxx7OprVdxp8L1UQcRRDe5MrzEpn + yUGad/VmIvqBWJXVH+IaqLXTLhsV + T1XwYvaM3Q2gk3h3EYA6zjTLUKl/ + GagiADSmJUnL/sz6dI81fXhstcWw + ELvvxM1VqpBIZPQJ3E9XPNTX96bg + 6tdsH1xyzezqijanhcOqIYcR8fbu + PocuN220LJOZ89k0gQTYWswU9V77 + qw8TCiBu6KBL82omINf51oA3cXoS + MjQCQBnUl+QEINx7OXoWq0bIeRfX + vgIQbxVIA6Lg/eUiUU07iol9VfSx + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + iCloudDrive + + + ZIIBnDCCAZgEUwEAhTriZPlk5ba8 + weQP8abhLwtXIMRdFUPlVDwmgqCY + 2U8w/ZpeoOaJ5wp+7NNBOQgGi88J + CQfor7ChKRLSy0rdlAZDLKEHZifl + NJMpqaRLDNMFBIH5Zo4hPORCAtqi + KM6BZmXDM4ZnyqLNREjAw8SAyQKq + viDGU5f55CavjkHluBLUzvddxRPu + e+IFc6+Yes+Rs6R0Xj9xZpprfAFk + 1vusLNajPhT+a4+ChnEtrp5c8keB + z7xte8YgPINm9HyTERH4X/QrwHXE + 0un5d2iU5tE1Q9a+V9FctlUHl4De + EKk1cO6+UdckPo5l/1ozpxscvNpt + wgfla36ivuZQ8Nawz7Bc9s9EiFRv + Pa3EaHN1pJOMzJ3eWCqkFy+XheEa + F6riryW/Ybl/prjzre3i0EKTzzXO + bnZ6OceTfOzMmPHKmCj56rjqharV + hoo2e8zhwV0lBCAXOlNsMQNVJQUY + +dqcGt39XUTbDVT2ksgEBMVvyOjk + PQIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + iMessage + + + ZIIBmzCCAZcEUwEAEZKDmq9tWraG + 4Q3otQnxhDK/rs9+l6EeptQ0JF/j + PCgw4ua1T1g9j/IC4OOk9PEUUQix + 4R5VYCTstE9HtdVC7AhhOIbFUp+K + 8ms36ITjerXQBIH4egZIG+JkLXf2 + n9WCQHv2Ue/cw6SbxEmKtrNtYfqs + 85x9rhhZLaEag55ko7hq/5nvRyAN + 0MMH1DxU7TipecTWz4we5FRHWn00 + 2PM4TqMDci7/0+Z6+UAQwXzF8SyA + X12W2UZns78mKKCLCWMBfsj2Dvu1 + sab7LIn4eZHiMq25bk+w5s2kI/X7 + 2ee6eeNGqhPS2Qx5a7uHSkuQ/+OY + TUG8v/3Azsb0Gzn0gplS7peFXNAm + /FyzYhMeWQWbPlWc8HdDshzppCbq + XkBbXq5Szlbh/68pTMHAXYLWqWsU + LEkgtNgu/zAm405LDqU/pXb1MzIk + bJAbsvGpie8EIMr5O+MxnSPOECSW + wa6jWdtSl8CxG60ieEJrS5eT8csD + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + + + SecureBackupiCloudDataProtection + + kPCSMetadataEscrowedKeys + + ZIIayjCCGsYEUwEAPy4812ENrmwVk6t0W6sfIrlO6AiE + gmqgnxn3sL0HIeEwRUGvxCIWt3mQR09OyX60jN44aMzY + PANLmNbWzcM1aHDJm6yLdO6haQEjAvmG8/8NBIIaRp3E + xXChfOzkEz30rxfRi4Dzk+uU3c2qN/qmO9jcdYHB18ja + gteFAASSTK5JofeMqNMqbnd81l2wXbhC2gdok/dawR85 + kVCYOO8Bf0y8pTaZUrjX2b4UYR9fDf79kNP0oyvncn43 + u9kYdnh0q9PDKf1E0VYFt74P2ZTRQxDgd5pSglYe82md + FZhv0vgmjF+kykzlfFbftYughM6Wg8pvzMP+5luRj31e + vzrc0cTSzUWSCQMLmipkWg6RL7+ee0cuRSdSzQxYBvzd + 61uc5GYfw6Z20B7qlVAdcSDgyl49hrSIb7JZcpOHSVIV + dcQiOD8+00avphT2gH1IEm1ckMtTqObftwgrXiysQs4z + y42OtdWBclOATpn2h41lBiKUPRfLhiZRHDi2ewly6d9v + 2oHA4nzo2ydxK7IrmkQpG0HGuJwQL0aBK0eyu9tapo0G + BG2gprNitthlMleO3NlGOcID+2Zc2TFiLe0R3Qtj3Wk/ + Pvg1G1wchPi0uIgDBs+3GY1+EY7OBSTlRiQQXG7doQ68 + YyFfI9XDEJq2T5dfeSvQ/Ii+ERWDRge1uZ0p60oox6Bu + e8tZzo+yOOQD0uSqPtlcjjsbkGHykR3J0gBQLxxnuKF1 + 7odIY9oeScrJfsnVmnsE//XtllmcLgLhZj1jThqqcEJ/ + jg6Zk+q3vtk5L4t9c0HzNrDZYC8KnUPZ3xQVF5wYgBqy + UL7fIOtLfCzKmdWM1EZaKbpv2frwgs/updXRMFCT1do1 + 7FgznRruGobBbfW5Hzg9MAhnmOlqnHKgrDTLlsLyOUOY + PK2w1DkIWz6eG7lKN8JGwFgGjK60w9/3wMsmZzsX2aOe + sMtnjpxtJgx00ab7rEWp+HH8dpPq00butcsriePkpTQ7 + M65m6r1du+05vxscAxCazxCKigWK3B8+VBcJOuQSQ5w8 + uTbBoD5SexSvzun7MeCbLuI5p5B4WITXOhekn23sMwMs + St5+6iSANjtnNOY4DUikYTjkJ+Cc6kWR3h9MIlmh+Ros + DSRf+QyArypm/EAY5Xw9sHrGsQ+4lrbuEjvxKH5b5kI8 + QsrI5ktdxDSZn1WicbiMK+U1H46KJSaAeY9RwcudGoVn + pD2XvoD329/TgdgoQ6zrQ0cuXl/M5sCLzcmFBLJbJD0g + 5O+vMhhc4pF3Udy5Xxuuji8/xpa5Gkae2rwQL28P/ZCP + RZyazSOx0aK9TCDfBBkgwYzYYmcSXWk0bYYrs2Zracut + 3NnUN8efIJb8SnjRd6kCLWvMgSyRdU7vbTMfjpa66Mii + TF1avDiNJ6WRmHw6HgzOXE7MiKk5d2WEPC6h33Z/jGVp + iuFqMSajXetwUbc97nffiTxraaHnxAi8U+EL0X6uxyRd + xKu//fAfbpwy4W9MZzOEd9fkqomSQb1A6fDftsVhHP+m + 7rk+WIGYn6DKHSLqQMGnXdKG1VQxqbQZkXra2Z6Z47ok + XxavfUA8Vy7qiT3HDWDVAq5IKFnAO7pltkpYQ8KBRCrF + 0JWDPuXua23jyqNW9zUjGwGw3+hZ2dpGSuYIRGcnp8he + uJe85jkJ3YGeYXQSRPNHHZqiflA7PcVtHTaG0Oy6QDDK + 57sp7n6UOsON4S2xBmNkMJ3kXBlR227y21HrE/fnWtBA + B9Tsmrd4ydXisIW4qxKZzMkNoBQlE+68Y8zwZXaqRHQ3 + zIap916Zmdn5nAlWWDZWwA7VA6W02IAvjxQO7Q5V8wZ3 + lQ77cZJRA9udptfV/oWu8sI6U/w9Ju+DVAHmbn+Y0834 + TpGalDwKcWgrwdgL0UCd/VHRoLK+5fcPKz9Q1KXbpFWk + glZ9priGzXfc3M6rlM95tpgoabmjruGVnPIHYnAKl80S + v/1/gVOQf7cHsK5oKg2c9euXKSeouJMbDPd0DvtZrmGU + tiWZiXjvmuKajIhLO9AAtubYWMBjQkimw1/oo7xH9qys + Pr4nvv3S8gA3mbwstnePqO4h3iiZJLnkYrudRKNWq3w8 + qNPY63Vd6IVCR9bjySSOhwcXmvwEGe4Vtz/linzjEsgr + 75hMYT3xJDXiXk01azsXbHWAyz5aF+oQaz6G6PySQGUZ + GeN26qCNL4VWeFt7sGa36MnH5tJSczLO9yXMX3kbiqJh + j5ipDCgd0duhsfqnURiU7SmB4fYRuvfw5wDnHLfbuU6x + qwaW0IKYsBBtgvn+i1AvxhE5bwaMqyn2RdAgxMiRB8Af + X6LRBk0aOBcGahwmbLLxtLeGMD5jvbT4kkfA6u24Af3q + PXCKO07aP4YUyXMtrti89wnkzqaMACiul8PVfXeWuvGK + hBVJPf3zcD14fdDk/oeTZRlHyf5PD0D5cMbU1lVv+1Ld + vm7f+zoMXMv18If2pWpK8Nc6pqG5OuDa8mcdvR3iY6z0 + HpTQdVMUnH31Y6pncR6JYOc6DPXF7mvaizUvK5Jgl3Jx + BoZauBw5f1ZS4gC6TD1omkJETgmb2qKy8O14qDSpFBlm + gyCkXLacP8mK4xbM2KU4Tz9dm+jcuGH9GYWLERzkGir2 + ksbeDLR8zjOUwFAvJuHYC835rL7TeNI6Ieb5xqz2Z0OJ + 40hiaarxpXolNon00JvOLjo3GPvTE0d/pA+SRiXm1Ez0 + AtaBkbYywgbQYWbFZvQr88EATOnzaUrBHIYfjCAxT5RV + OHVzlhH35D2hhXD3fpbRpXGegXVG91de7bb5EZg5aHAG + 2qTfcOA/rYez4O8U/xh4RLIFL9ew9fulhfm1sUhKgPRt + e/BurazU6fAzlzNPZ3soA/sN6C0xwhR6InxUHr8WtrJx + 8ak+s+ISmQav7gwo9Nc4JF345HSUGgKZefJcKko5pOrs + cym8NDDEFhJDISItu5r8SV71heSho9lTXC15r980BxC+ + TNTlXSKp6ua8cZj3Mvn5/Zi32+I+eLqeAkbHiROZm0mX + vkgSeplFBp7K2WfeSY2N72AWcV2b9TdZ3KQ2MYTv3qJz + u57WMkwvMGfGRukfsGJwBxeFpJnVCJnDQ5wyPSXxkbIN + eAOhCKLnkqpZjKuivVz6TSNJ8TOhgjK38KhKQW4pRY9H + NwGR6VSNe2vxJQoOdslgVekl91Al+RlU5AVykyKLEycu + 60g+rjesTmDPP/Tr/b2tIqRmAJbcxM05baUFdkNAXi0j + 9uzjZtis2QQfqjLOIdSQUXWAQ3mafw3r3vNjofgOyVyS + cuSv10SKSxqqsZreix4ae6KX9kGsI0al/lyPA6qQuQpe + WG7HkjAmQc+AGemGMqruJd/xbRyp28guxkiVsI52ljHM + K9iu0jUKGQnH72Hr/InEAVxjk1s3/wrOjOsYha4mhOSt + Lvu3qH5NCqRDBOd69hzpKRu9QVU8MdbvYqbsz/WJI6yG + 8mTh5VFEhjkVb/QhXTWSrhoXsaqv8oQBk4Xde9v2lWzQ + j9QvwXKeulngVsf8dEqV8xJD6SLH+NoSLxAebk1qEItc + feZTzvEt57wWMOX+8zalFSDLkqEuTWd8ViQ9ZlSo5WV3 + AFbcKDcWvoyCF347IVA7y+FzWmTLbfSjSmtKIu/bX1d1 + WnlDZqL5oAPRcMh+Njp9Zh4uvnOBPnwoxnVvOpDrbhrx + fmF6tXzSjz2/y66mpNT2upQZBRATIKy9rn8fdC0WUSTS + yi2Br0JYKrw4ajm7QkoGIniQeZ+bbtqQyfu2lgMKUyeU + mHhj7vH441xYcj6bn6Umy5iY+oHb+JkrcWQmNKHA5dTg + OB35cC0/i9hB+jkOWAMGx4MJZ5Si9jCe9myhWZzuk+km + FsAueeg/HjYjNBEfYuMUMrpRIJpzgPQ7AolfUE9EieeV + 1CPzRZbl1EteDdD1RYd7wWo2qWwhbYMopGGTZtgpBZwl + dIxkSnRFwuaeqSq5h6FFriDbtvZAsl+smRVPgWQl3O6M + UQQfRS2Mqe4lfi1wi7znhGEGZnQr2zeoKfudbU4xrq7C + 6KcfCineZ66pRSqTF1ERpo5olierMsn7Q6sGvezb3umO + aGi5KmysL4CStBM/rMfk4UAJP8/JHOe8hj5BzJ0Vj2p0 + QH/icLnwxQXPlt3An6EoLVyfea2n+Xz5zBsPsFem3aE+ + MOyNuBT+Wi99iISUGjYCeoK0IPMxDowQlgO8bdL5frG8 + v3rGEidUYEkSX3kv/3dqg/m2+L/rHzaKZo09HQSLGaCF + BngxviUGzC7IRNdSwNGWiz5dvvALrkMDheqNb5Zs9KHV + nmzs4xyKNHh2rwziYD+qP0gtcvja7Q7rp/30JLUoh7lE + HSlox8LZvrhcKsX5Fj2tJ5y1gEAWOThhRsw7eVVS034G + Uue76HsHzNA+Sszh3v5tawcqVuXXkVCJPabPRjoEVTxz + 3Ngzp13qm1uQcdshmCBhSWZ0spKSjIVmSgJbKj+GRKBu + XV4+e2zFGMEfnnyJXWt91gErH/+22LQmROrWReucNmf2 + HWS0RGaL9OUehhrriV1Tt1Y5YD8A23DtErU+9NWCHcyF + 1KnL3CoYyNWKTPnptrqD8N7RaS28JOtDT9bi7hn/nTgz + alO6SUzBIa9TKSugQd9F/AHQfiMTSyEbz+RrWNWHlfQj + S5Kjuo0GG2kypc7jRDSVeHnZ6xAWvl/gpl+PU3RyALDo + oPJ97ETYH5hMpOJa7/AnlduBwQyd+Ix7Dg4+Z+rKQscN + Sxc/Gfb29OBIi1LUU+g3WqiMK34T1zF0QqzynMMVt/rz + eeB/R1ea9yO3FIQCvyNVTBOMbOwt32kSKraiRa1JZ183 + 0PYAOKoLy7eEC9h9n7JLXV2V/F/1O7/lU6RzB46SZUiR + 9Ye8wKfTlA3EZcc5LdWgZFG34kLEMr5Z6P5gOPcYuwae + QiMcBVYAb3Cce1uDsgLhSPJXHJfhQG5mEaKFfomNe++X + +fK8uYplGPjB0hxmJPIh4lFAqNhJhI6tozTyd/+KmJHH + sSniBG+LEcuR621TQVUf56mx6cCE5Pzxaee4faEPsC9X + YK6NonfXuOpEFkbH9mPsIUprwOE/s2MOBCg6yTgiQ6Ok + u+FNltMGm1mWkFqsgvkAUYTCvB2zYfV1qVxjf+VgyJ11 + oUHrbMJ+jZwKISKSnvTLAiq013mA5BJ4vDsDU4S5O9Uv + GRHmejmbYbfmGVIw50TwTnFJHIpyrwpkjZOqsJ1p/k/e + rUwwZ2OGxZ85qPTRTDEwCnJGSxKI7BbEfi7wbNT4OBKW + zlTmtr+uCWpRw6joQ76vyYWHtj0BrmMK2TYKsl6zZZFP + ARBCFGrO8hjpAkQ3k9oZ5p8KU7dWXspPwAgOESWllmOE + 4kUtuTWFuUtt77vo6Jy1Him/d8jQiNdVBcw+7gnTGBXz + zrljq65uBO2pzUBkdG5nkBXwK/161E5MXQb6bkXxPyJq + heGzvkVtIfTS/zAeswBO+WNXyGqONOfa7qaGl+IPnVaJ + PalQXuuka+IxsEMIwkw/In03x+Jb6Hud7p9qAaCxd9IH + rrNq73BkTw2GQAm7VTwm5nzE61WWwuh0XaKhquse0znP + xyBijVUAkyBvht7NaXA04wj8HX1sTDnSwH1RFDyQIMei + V2uVrqKFtyVfQLxNbn6YfXjbA8iwethkLGJGS5rXq/ay + pk8fs2rvYYywL48s+gcMgxDbfWu8rux8F9ymO/DM5sNJ + buCCcc+kYL4VMNAtM22CAZM0/OrAL8ItUXUsn0MvVAs1 + skDQuyZBPlPTmJ5Ta7DPXoHJikeMclNki6TjmROFuCM6 + 5rMa3pOTrb+UKh0ozqK8lrmYQVRJ8ZBfr48DkdgHDd8d + Kyb1ymSmGWd9dnS2eV62J+nd2nKIfZ0j1JiMY7cgESMe + v1kD3SXRdCLlen80L0sdLRjcFbzg7M2Pq6IV5W54tgt4 + LKgYettPhlMNoPeEvUProp+AkbWDfeptakwxgmYrRrhw + 9nhlbX9paKSZ9JQ/2skUknBPc2zc04qCL4ghXwcG8X4/ + a0DzaUBLiW35rp6WwqnmlndkwUeJ6VSiH113JjK3oyRg + dDQgHhdecffQysaWn0+03ccx8eVe3FMAknX8KYI6Q/iM + Uum+KsGcUH/Cza4qbSEZKERvc59jeN6rY1/J7U/JCown + jyKelYJ4ai0i2lMenpmzM9xkXw8amhubeCiAEDpklntX + 0nWuVYjSy2hzqo6N3KC4Py+0sY0tAqp23EYnatxCwYTr + aQUZ5CHW3SzsP4PjOLEhoixBuX3b/HjG8C59KN18cIcR + HdQU4IYMmkZV3DfxpEWxAwM3M+1sAA+ZHzYQB8I/OppV + 2YiZaHcDxDUO5aj98w3Qr1BbE3l89Z+tMWBIe/QigCA8 + JIOf032BQ+RM5Q5rzprOzyKCfCJIcwsSMv3cQpuiWPG8 + 79TmWzkd4Ayv9lKWbHY2eoTqieRc5B49fdtMAo94OFlV + zC6EY+823s6pkI0LiOuc5PRxRnhexSixsCrbsU7e/0DX + BX9vK4E2ShGs3EJFEbvshbuDQSFitds4HsotmIBvZH7T + UFqbKfVUyuQfdKd53mzZ9RwIVVOleMtjwfdSFGut15pU + J/RqcSAtYaObnc44EbeelmA5HzMfuji6GO+sN90UVD9J + +Wk6BPIefRf+JOof89byJuYS2IQ7cFckPa2Yjd8roWgb + uqNP5h8mVZf+SzMNwcHWIAHBxMZ7ymqLq4RcjriNzGUY + wv4hJsnsMGFJz7HPg3jxiNKe5RLsaF3volW1ROVyAs8f + OoAdAJasXh5SGbhW5jppCkNhrjJrfWsHI2tX8vbMVO3H + hr00mrx1Gaz7jcE88H2kQruDuqv0VdFIfeCIEzI9FoAh + 0xtj7IKBYhazOtIGXNr/3SDH1esUPgFbMz9KOBzdsamH + F32hva6NFI4FZHNnXmckB1eNiKD8fiGNN8NTg+K7rEJT + FXAWLDwbKQKjffZkQELfHGMubGct9jRkb4PcLkeY6G6a + ICxbIdWD/1oNeMUrO7ma42ii1k2gOeIocthJf6S7QRxU + 3sL7YCDSeL+qYRynyMRgYNbjGCKehdQsYvHLwFqgCPf5 + 9+dCKkK7Qu3u4hoUahircTW1jbe98jkjuo/qOgmUBT3S + j5dWR3wjV4EguKW1A936NxkGWMooVdxk2iV1jJkn8p1a + zsQAn4KhBH18sfzTR10zDxPC8pHEE9HyhOyVYsgiSh4V + 5X3aFICEYjb1LlxkycNuYv1Sd+PnUEMDTaFLgZyrj7pR + 5AKY4Kbb7cQTbCpxUbHSs4nie/Q2Inl22XQ6Mz7NTtQG + kNE7uUvOzc1J3OBl/vpyy3arKf6NfXIIKPD3I60pHzoB + 0OIPexhasJPHyBoQ/0P4k99JCBux6wt6scmRC6fUxvzV + FAf15Oo81W1Z51hLL30fFospXFPcknxo2FVxIs3yPvKJ + zBpOWBtLbznDHCf3IDPGoVQ1HuhguvFUylc0G7Z3rM5T + z3ORkHExX8V8Vb1ROFAOuo3X0jB8wzv+ir5bKykZXQmL + V01FQpF8Q+SvERgwNr1Gn8Gv5WVeoQ7XhA1pEmR+iOwK + VmH8LepXPQP9Ggm1fH/CSrjhMju+0YsrnIIuiiAWa/zw + ++guaPx02owWBd6FQVg7KrjyrWLdXmRwt1m8Hset7e7C + a3D1DttfOWFqrd87CE+2GSTR6WBptLGtWgsWkBsUx3kq + xtnW9t3eEDOIn3TmgRyQ4tekktczPS21FZwFLnx/s2dm + yEWAU1/2rswSSv83Hb+bKECbyFSLl4mKB89qjQ6vPYVu + hVwFer7xCyt6o5kh+/6MJ0Ts3lU0xqHgddsOxn3Vmtac + LwTBemQfIMo5CTOE222qeIuxXn9pxSN6/FpIBxHPUANH + fRzOS8G2/gSHX4cgP6JWPt1UYXWwY6aoeUj0jBWu4iwl + 8tNrI9W/8ELjji4IhIJB2zraowhL4ri81RogsCIyquaP + U5lvqD+y2glp7nD+eb8OhfaqsQAVIqZUm0oPgbqij2D8 + M2S2NSAmD1Fn4WzR8PtDN+6K7TJBP8qz/cNXIRcx8AZH + LYyhJ+oY4+mlxWVpyhM/K6VMJZ2757JMPNnuO8MwaGbj + xyoCfc0YPLHcdH9JI8x2QQtUwXb+kH8PtrEUcfm4BeXK + 0qjwCa7igKxA0QyzqG6WybelTNZYhSC0of1F1pN3eOqN + wtNvj4jN0R3iBG3wklEQ/ySh7RGdzaLqIRFpAudvZWVk + SnNYnmbEQyJFEv7o39kjvAPTL/Lw2oa0LHBdmgzueHZ7 + cb8avYCyuyiY4wf0cA+ZN7OBLmrzVuAffWNqf34yvTk1 + BcagiFN4idpmsjZWNu58L49LOPPO/HeVl9DBUqu1ISzi + TAPoEalrXmm/IDw65RAo7QuuEaUlxLFlrAvIUnbv6Ofp + nfkH4TgEwVDKwnlclvhV09NmhqUx2Zn7sSvbofNcvRPP + SNQrkLPRN8nScpYtr2dfoPQHCVI1mwxPfqd/pt9D0j64 + dfDM7gLYsxk7r7QeBF1f0d27vpQlYw3NNWFzV8rHhUwF + jwu+mc0REFuecKvuVk1ETajKX5uPnJ/wDK3dEHNQWYfx + O1lrlvqzyHhh4TJpjKn1FGIwCl7DsnBknkq/Ftg2MpE3 + 7bDsXbQTPVthfGoVwis46X7rf07zzFDQtLrDauZFKqVF + Xvq2JnMzIBuQKYoPZVJpI263kIznFrNex2dOiF1XfoRP + BN5KiwjgfQgQGbcDrRzaGScflHMAwhC/maZ/XH/RO7do + weNT0usHXBKdL5yuyeKJWN2WiNJUi4jYGH4gh9WOW88Z + YUQeOnQu7PiYhD9dGwJQF1L5Q8sgJXttoQVmc7hnQu2n + UdyO9zE+htxDuvmjS4up6rC0e1mmpbNcKZXzQf03iQIc + wmIT+9607OEw4p9c6efsFhwP8UE5hVplF1iVJ60MC8L1 + rhO90R47+S/xhvAr+BlY3bsOJdgAnacA4TAIPiwZ1HjU + 9Q533lQVU0ZaJhNZefomfmA4fi5OkC/rv73AMxIc0wtm + fZCAW06HrgTX/UJu6GmoPUF8XudtJcZIj9J20yepihji + 75pvJuzp0ELRB9uW8k+EqFZFtQyW4+WD8QQAAgEDBCDB + UpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eQ== + + kPCSMetadataiCDP + + kPCSMetadataiCDPArmed + + + SecureBackupiCloudIdentityPublicData + + YYGRMIGOAgECAgEBBCAXOlNsMQNVJQUY+dqcGt39XUTbDVT2ksgE + BMVvyOjkPaFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcw + RQIhAIL+1l8MsRW3rN9wMeM7tSinakp/c2/Dp2kO8Z8OZBxSAiAL + 15IC/CrJgkQLyS4rarGeTmMFKGz34i/jQ1AQHzQy0Q== + + + com.apple.securebackup.timestamp + 2018-09-28 19:45:25 + + SecureBackupStingrayMetadataHash + + BackupKeybagDigest + + LTrJHVHFZ5vQO59wUih1MEgg1qI= + + com.apple.securebackup.timestamp + 2018-09-28 19:45:25 + encodedMetadata + YnBsaXN0MDDTAAEAAwAFAAIABAAGXxAgY29tLmFwcGxlLnNlY3VyZWJhY2t1cC50aW1lc3RhbXBfEBMyMDE4LTA5LTI4IDE5OjQ1OjI1XxASQmFja3VwS2V5YmFnRGlnZXN0TxAULTrJHVHFZ5vQO59wUih1MEgg1qJeQ2xpZW50TWV0YWRhdGHVAAcADgDTANUBLAAIAA8A1ADWAS1fECBTZWN1cmVCYWNrdXBpQ2xvdWREYXRhUHJvdGVjdGlvbtMACQALAAwACgAKAA1fEBVrUENTTWV0YWRhdGFpQ0RQQXJtZWQJXxAQa1BDU01ldGFkYXRhaUNEUF8QGGtQQ1NNZXRhZGF0YUVzY3Jvd2VkS2V5c08RGs5kghrKMIIaxgRTAQA/LjzXYQ2ubBWTq3Rbqx8iuU7oCISCaqCfGfewvQch4TBFQa/EIha3eZBHT07JfrSM3jhozNg8A0uY1tbNwzVocMmbrIt07qFpASMC+Ybz/w0EghpGncTFcKF87OQTPfSvF9GLgPOT65Tdzao3+qY72Nx1gcHXyNqC14UABJJMrkmh94yo0ypud3zWXbBduELaB2iT91rBHzmRUJg47wF/TLylNplSuNfZvhRhH18N/v2Q0/SjK+dyfje72Rh2eHSr08Mp/UTRVgW3vg/ZlNFDEOB3mlKCVh7zaZ0VmG/S+CaMX6TKTOV8Vt+1i6CEzpaDym/Mw/7mW5GPfV6/OtzRxNLNRZIJAwuaKmRaDpEvv557Ry5FJ1LNDFgG/N3rW5zkZh/DpnbQHuqVUB1xIODKXj2GtIhvsllyk4dJUhV1xCI4Pz7TRq+mFPaAfUgSbVyQy1Oo5t+3CCteLKxCzjPLjY611YFyU4BOmfaHjWUGIpQ9F8uGJlEcOLZ7CXLp32/agcDifOjbJ3ErsiuaRCkbQca4nBAvRoErR7K721qmjQYEbaCms2K22GUyV47c2UY5wgP7ZlzZMWIt7RHdC2PdaT8++DUbXByE+LS4iAMGz7cZjX4Rjs4FJOVGJBBcbt2hDrxjIV8j1cMQmrZPl195K9D8iL4RFYNGB7W5nSnrSijHoG57y1nOj7I45APS5Ko+2VyOOxuQYfKRHcnSAFAvHGe4oXXuh0hj2h5Jysl+ydWaewT/9e2WWZwuAuFmPWNOGqpwQn+ODpmT6re+2Tkvi31zQfM2sNlgLwqdQ9nfFBUXnBiAGrJQvt8g60t8LMqZ1YzURlopum/Z+vCCz+6l1dEwUJPV2jXsWDOdGu4ahsFt9bkfOD0wCGeY6WqccqCsNMuWwvI5Q5g8rbDUOQhbPp4buUo3wkbAWAaMrrTD3/fAyyZnOxfZo56wy2eOnG0mDHTRpvusRan4cfx2k+rTRu61yyuJ4+SlNDszrmbqvV277Tm/GxwDEJrPEIqKBYrcHz5UFwk65BJDnDy5NsGgPlJ7FK/O6fsx4Jsu4jmnkHhYhNc6F6SfbewzAyxK3n7qJIA2O2c05jgNSKRhOOQn4JzqRZHeH0wiWaH5GiwNJF/5DICvKmb8QBjlfD2wesaxD7iWtu4SO/EoflvmQjxCysjmS13ENJmfVaJxuIwr5TUfjoolJoB5j1HBy50ahWekPZe+gPfb39OB2ChDrOtDRy5eX8zmwIvNyYUEslskPSDk768yGFzikXdR3LlfG66OLz/GlrkaRp7avBAvbw/9kI9FnJrNI7HRor1MIN8EGSDBjNhiZxJdaTRthiuzZmtpy63c2dQ3x58glvxKeNF3qQIta8yBLJF1Tu9tMx+OlrroyKJMXVq8OI0npZGYfDoeDM5cTsyIqTl3ZYQ8LqHfdn+MZWmK4WoxJqNd63BRtz3ud9+JPGtpoefECLxT4QvRfq7HJF3Eq7/98B9unDLhb0xnM4R31+SqiZJBvUDp8N+2xWEc/6buuT5YgZifoModIupAwadd0obVVDGptBmRetrZnpnjuiRfFq99QDxXLuqJPccNYNUCrkgoWcA7umW2SlhDwoFEKsXQlYM+5e5rbePKo1b3NSMbAbDf6FnZ2kZK5ghEZyenyF64l7zmOQndgZ5hdBJE80cdmqJ+UDs9xW0dNobQ7LpAMMrnuynufpQ6w43hLbEGY2QwneRcGVHbbvLbUesT9+da0EAH1Oyat3jJ1eKwhbirEpnMyQ2gFCUT7rxjzPBldqpEdDfMhqn3XpmZ2fmcCVZYNlbADtUDpbTYgC+PFA7tDlXzBneVDvtxklED252m19X+ha7ywjpT/D0m74NUAeZuf5jTzfhOkZqUPApxaCvB2AvRQJ39UdGgsr7l9w8rP1DUpdukVaSCVn2muIbNd9zczquUz3m2mChpuaOu4ZWc8gdicAqXzRK//X+BU5B/twewrmgqDZz165cpJ6i4kxsM93QO+1muYZS2JZmJeO+a4pqMiEs70AC25thYwGNCSKbDX+ijvEf2rKw+vie+/dLyADeZvCy2d4+o7iHeKJkkueRiu51Eo1arfDyo09jrdV3ohUJH1uPJJI6HBxea/AQZ7hW3P+WKfOMSyCvvmExhPfEkNeJeTTVrOxdsdYDLPloX6hBrPobo/JJAZRkZ43bqoI0vhVZ4W3uwZrfoycfm0lJzMs73JcxfeRuKomGPmKkMKB3R26Gx+qdRGJTtKYHh9hG69/DnAOcct9u5TrGrBpbQgpiwEG2C+f6LUC/GETlvBoyrKfZF0CDEyJEHwB9fotEGTRo4FwZqHCZssvG0t4YwPmO9tPiSR8Dq7bgB/eo9cIo7Tto/hhTJcy2u2Lz3CeTOpowAKK6Xw9V9d5a68YqEFUk9/fNwPXh90OT+h5NlGUfJ/k8PQPlwxtTWVW/7Ut2+bt/7Ogxcy/Xwh/alakrw1zqmobk64NryZx29HeJjrPQelNB1UxScffVjqmdxHolg5zoM9cXua9qLNS8rkmCXcnEGhlq4HDl/VlLiALpMPWiaQkROCZvaorLw7XioNKkUGWaDIKRctpw/yYrjFszYpThPP12b6Ny4Yf0ZhYsRHOQaKvaSxt4MtHzOM5TAUC8m4dgLzfmsvtN40joh5vnGrPZnQ4njSGJpqvGleiU2ifTQm84uOjcY+9MTR3+kD5JGJebUTPQC1oGRtjLCBtBhZsVm9CvzwQBM6fNpSsEchh+MIDFPlFU4dXOWEffkPaGFcPd+ltGlcZ6BdUb3V17ttvkRmDlocAbapN9w4D+th7Pg7xT/GHhEsgUv17D1+6WF+bWxSEqA9G178G6trNTp8DOXM09neygD+w3oLTHCFHoifFQevxa2snHxqT6z4hKZBq/uDCj01zgkXfjkdJQaApl58lwqSjmk6uxzKbw0MMQWEkMhIi27mvxJXvWF5KGj2VNcLXmv3zQHEL5M1OVdIqnq5rxxmPcy+fn9mLfb4j54up4CRseJE5mbSZe+SBJ6mUUGnsrZZ95JjY3vYBZxXZv1N1ncpDYxhO/eonO7ntYyTC8wZ8ZG6R+wYnAHF4WkmdUImcNDnDI9JfGRsg14A6EIoueSqlmMq6K9XPpNI0nxM6GCMrfwqEpBbilFj0c3AZHpVI17a/ElCg52yWBV6SX3UCX5GVTkBXKTIosTJy7rSD6uN6xOYM8/9Ov9va0ipGYAltzEzTltpQV2Q0BeLSP27ONm2KzZBB+qMs4h1JBRdYBDeZp/Deve82Oh+A7JXJJy5K/XRIpLGqqxmt6LHhp7opf2QawjRqX+XI8DqpC5Cl5YbseSMCZBz4AZ6YYyqu4l3/FtHKnbyC7GSJWwjnaWMcwr2K7SNQoZCcfvYev8icQBXGOTWzf/Cs6M6xiFriaE5K0u+7eofk0KpEME53r2HOkpG71BVTwx1u9ipuzP9YkjrIbyZOHlUUSGORVv9CFdNZKuGhexqq/yhAGThd172/aVbNCP1C/Bcp66WeBWx/x0SpXzEkPpIsf42hIvEB5uTWoQi1x95lPO8S3nvBYw5f7zNqUVIMuSoS5NZ3xWJD1mVKjlZXcAVtwoNxa+jIIXfjshUDvL4XNaZMtt9KNKa0oi79tfV3VaeUNmovmgA9FwyH42On1mHi6+c4E+fCjGdW86kOtuGvF+YXq1fNKPPb/Lrqak1Pa6lBkFEBMgrL2ufx90LRZRJNLKLYGvQlgqvDhqObtCSgYieJB5n5tu2pDJ+7aWAwpTJ5SYeGPu8fjjXFhyPpufpSbLmJj6gdv4mStxZCY0ocDl1OA4HflwLT+L2EH6OQ5YAwbHgwlnlKL2MJ72bKFZnO6T6SYWwC556D8eNiM0ER9i4xQyulEgmnOA9DsCiV9QT0SJ55XUI/NFluXUS14N0PVFh3vBajapbCFtgyikYZNm2CkFnCV0jGRKdEXC5p6pKrmHoUWuINu29kCyX6yZFU+BZCXc7oxRBB9FLYyp7iV+LXCLvOeEYQZmdCvbN6gp+51tTjGursLopx8KKd5nrqlFKpMXURGmjmiWJ6syyftDqwa97Nve6Y5oaLkqbKwvgJK0Ez+sx+ThQAk/z8kc57yGPkHMnRWPanRAf+JwufDFBc+W3cCfoSgtXJ95raf5fPnMGw+wV6bdoT4w7I24FP5aL32IhJQaNgJ6grQg8zEOjBCWA7xt0vl+sby/esYSJ1RgSRJfeS//d2qD+bb4v+sfNopmjT0dBIsZoIUGeDG+JQbMLshE11LA0ZaLPl2+8AuuQwOF6o1vlmz0odWebOzjHIo0eHavDOJgP6o/SC1y+NrtDuun/fQktSiHuUQdKWjHwtm+uFwqxfkWPa0nnLWAQBY5OGFGzDt5VVLTfgZS57voewfM0D5KzOHe/m1rBypW5deRUIk9ps9GOgRVPHPc2DOnXeqbW5Bx2yGYIGFJZnSykpKMhWZKAlsqP4ZEoG5dXj57bMUYwR+efIlda33WASsf/7bYtCZE6tZF65w2Z/YdZLREZov05R6GGuuJXVO3VjlgPwDbcO0StT701YIdzIXUqcvcKhjI1YpM+em2uoPw3tFpLbwk60NP1uLuGf+dODNqU7pJTMEhr1MpK6BB30X8AdB+IxNLIRvP5GtY1YeV9CNLkqO6jQYbaTKlzuNENJV4ednrEBa+X+CmX49TdHIAsOig8n3sRNgfmEyk4lrv8CeV24HBDJ34jHsODj5n6spCxw1LFz8Z9vb04EiLUtRT6DdaqIwrfhPXMXRCrPKcwxW3+vN54H9HV5r3I7cUhAK/I1VME4xs7C3faRIqtqJFrUlnXzfQ9gA4qgvLt4QL2H2fsktdXZX8X/U7v+VTpHMHjpJlSJH1h7zAp9OUDcRlxzkt1aBkUbfiQsQyvlno/mA49xi7Bp5CIxwFVgBvcJx7W4OyAuFI8lccl+FAbmYRooV+iY1775f58ry5imUY+MHSHGYk8iHiUUCo2EmEjq2jNPJ3/4qYkcexKeIEb4sRy5HrbVNBVR/nqbHpwITk/PFp57h9oQ+wL1dgro2id9e46kQWRsf2Y+whSmvA4T+zYw4EKDrJOCJDo6S74U2W0wabWZaQWqyC+QBRhMK8HbNh9XWpXGN/5WDInXWhQetswn6NnAohIpKe9MsCKrTXeYDkEni8OwNThLk71S8ZEeZ6OZtht+YZUjDnRPBOcUkcinKvCmSNk6qwnWn+T96tTDBnY4bFnzmo9NFMMTAKckZLEojsFsR+LvBs1Pg4EpbOVOa2v64JalHDqOhDvq/JhYe2PQGuYwrZNgqyXrNlkU8BEEIUas7yGOkCRDeT2hnmnwpTt1Zeyk/ACA4RJaWWY4TiRS25NYW5S23vu+jonLUeKb93yNCI11UFzD7uCdMYFfPOuWOrrm4E7anNQGR0bmeQFfAr/XrUTkxdBvpuRfE/ImqF4bO+RW0h9NL/MB6zAE75Y1fIao4059rupoaX4g+dVok9qVBe66Rr4jGwQwjCTD8ifTfH4lvoe53un2oBoLF30geus2rvcGRPDYZACbtVPCbmfMTrVZbC6HRdoqGq6x7TOc/HIGKNVQCTIG+G3s1pcDTjCPwdfWxMOdLAfVEUPJAgx6JXa5WuooW3JV9AvE1ufph9eNsDyLB62GQsYkZLmter9rKmTx+zau9hjLAvjyz6BwyDENt9a7yu7HwX3KY78Mzmw0lu4IJxz6RgvhUw0C0zbYIBkzT86sAvwi1RdSyfQy9UCzWyQNC7JkE+U9OYnlNrsM9egcmKR4xyU2SLpOOZE4W4Izrmsxrek5Otv5QqHSjOoryWuZhBVEnxkF+vjwOR2AcN3x0rJvXKZKYZZ312dLZ5XrYn6d3acoh9nSPUmIxjtyARIx6/WQPdJdF0IuV6fzQvSx0tGNwVvODszY+rohXlbni2C3gsqBh620+GUw2g94S9Q+uin4CRtYN96m1qTDGCZitGuHD2eGVtf2lopJn0lD/ayRSScE9zbNzTioIviCFfBwbxfj9rQPNpQEuJbfmunpbCqeaWd2TBR4npVKIfXXcmMrejJGB0NCAeF15x99DKxpafT7TdxzHx5V7cUwCSdfwpgjpD+IxS6b4qwZxQf8LNriptIRkoRG9zn2N43qtjX8ntT8kKjCePIp6VgnhqLSLaUx6embMz3GRfDxqaG5t4KIAQOmSWe1fSda5ViNLLaHOqjo3coLg/L7SxjS0CqnbcRidq3ELBhOtpBRnkIdbdLOw/g+M4sSGiLEG5fdv8eMbwLn0o3XxwhxEd1BTghgyaRlXcN/GkRbEDAzcz7WwAD5kfNhAHwj86mlXZiJlodwPENQ7lqP3zDdCvUFsTeXz1n60xYEh79CKAIDwkg5/TfYFD5EzlDmvOms7PIoJ8IkhzCxIy/dxCm6JY8bzv1OZbOR3gDK/2UpZsdjZ6hOqJ5FzkHj1920wCj3g4WVXMLoRj7zbezqmQjQuI65zk9HFGeF7FKLGwKtuxTt7/QNcFf28rgTZKEazcQkURu+yFu4NBIWK12zgeyi2YgG9kftNQWpsp9VTK5B90p3nebNn1HAhVU6V4y2PB91IUa63XmlQn9GpxIC1ho5udzjgRt56WYDkfMx+6OLoY76w33RRUP0n5aToE8h59F/4k6h/z1vIm5hLYhDtwVyQ9rZiN3yuhaBu6o0/mHyZVl/5LMw3BwdYgAcHExnvKaourhFyOuI3MZRjC/iEmyewwYUnPsc+DePGI0p7lEuxoXe+iVbVE5XICzx86gB0AlqxeHlIZuFbmOmkKQ2GuMmt9awcja1fy9sxU7ceGvTSavHUZrPuNwTzwfaRCu4O6q/RV0Uh94IgTMj0WgCHTG2PsgoFiFrM60gZc2v/dIMfV6xQ+AVszP0o4HN2xqYcXfaG9ro0UjgVkc2deZyQHV42IoPx+IY03w1OD4rusQlMVcBYsPBspAqN99mRAQt8cYy5sZy32NGRvg9wuR5jobpogLFsh1YP/Wg14xSs7uZrjaKLWTaA54ihy2El/pLtBHFTewvtgINJ4v6phHKfIxGBg1uMYIp6F1Cxi8cvAWqAI9/n350IqQrtC7e7iGhRqGKtxNbWNt73yOSO6j+o6CZQFPdKPl1ZHfCNXgSC4pbUD3fo3GQZYyihV3GTaJXWMmSfynVrOxACfgqEEfXyx/NNHXTMPE8LykcQT0fKE7JViyCJKHhXlfdoUgIRiNvUuXGTJw25i/VJ34+dQQwNNoUuBnKuPulHkApjgptvtxBNsKnFRsdKzieJ79DYieXbZdDozPs1O1AaQ0Tu5S87NzUnc4GX++nLLdqsp/o19cggo8PcjrSkfOgHQ4g97GFqwk8fIGhD/Q/iT30kIG7HrC3qxyZELp9TG/NUUB/Xk6jzVbVnnWEsvfR8WiylcU9ySfGjYVXEizfI+8onMGk5YG0tvOcMcJ/cgM8ahVDUe6GC68VTKVzQbtneszlPPc5GQcTFfxXxVvVE4UA66jdfSMHzDO/6KvlsrKRldCYtXTUVCkXxD5K8RGDA2vUafwa/lZV6hDteEDWkSZH6I7ApWYfwt6lc9A/0aCbV8f8JKuOEyO77Riyucgi6KIBZr/PD76C5o/HTajBYF3oVBWDsquPKtYt1eZHC3Wbwex63t7sJrcPUO2185YWqt3zsIT7YZJNHpYGm0sa1aCxaQGxTHeSrG2db23d4QM4ifdOaBHJDi16SS1zM9LbUVnAUufH+zZ2bIRYBTX/auzBJK/zcdv5soQJvIVIuXiYoHz2qNDq89hW6FXAV6vvELK3qjmSH7/ownROzeVTTGoeB12w7GfdWa1pwvBMF6ZB8gyjkJM4Tbbap4i7Fef2nFI3r8WkgHEc9QA0d9HM5Lwbb+BIdfhyA/olY+3VRhdbBjpqh5SPSMFa7iLCXy02sj1b/wQuOOLgiEgkHbOtqjCEviuLzVGiCwIjKq5o9TmW+oP7LaCWnucP55vw6F9qqxABUiplSbSg+BuqKPYPwzZLY1ICYPUWfhbNHw+0M37ortMkE/yrP9w1chFzHwBkctjKEn6hjj6aXFZWnKEz8rpUwlnbvnskw82e47wzBoZuPHKgJ9zRg8sdx0f0kjzHZBC1TBdv6Qfw+2sRRx+bgF5crSqPAJruKArEDRDLOobpbJt6VM1liFILSh/UXWk3d46o3C02+PiM3RHeIEbfCSURD/JKHtEZ3NouohEWkC529lZWRKc1ieZsRDIkUS/ujf2SO8A9Mv8vDahrQscF2aDO54dntxvxq9gLK7KJjjB/RwD5k3s4EuavNW4B99Y2p/fjK9OTUFxqCIU3iJ2mayNlY27nwvj0s48878d5WX0MFSq7UhLOJMA+gRqWteab8gPDrlECjtC64RpSXEsWWsC8hSdu/o5+md+QfhOATBUMrCeVyW+FXT02aGpTHZmfuxK9uh81y9E89I1CuQs9E3ydJyli2vZ1+g9AcJUjWbDE9+p3+m30PSPrh18MzuAtizGTuvtB4EXV/R3bu+lCVjDc01YXNXyseFTAWPC76ZzREQW55wq+5WTURNqMpfm4+cn/AMrd0Qc1BZh/E7WWuW+rPIeGHhMmmMqfUUYjAKXsOycGSeSr8W2DYykTftsOxdtBM9W2F8ahXCKzjpfut/TvPMUNC0usNq5kUqpUVe+rYmczMgG5Apig9lUmkjbreQjOcWs17HZ06IXVd+hE8E3kqLCOB9CBAZtwOtHNoZJx+UcwDCEL+Zpn9cf9E7t2jB41PS6wdcEp0vnK7J4olY3ZaI0lSLiNgYfiCH1Y5bzxlhRB46dC7s+JiEP10bAlAXUvlDyyAle22hBWZzuGdC7adR3I73MT6G3EO6+aNLi6nqsLR7Waals1wplfNB/TeJAhzCYhP73rTs4TDin1zp5+wWHA/xQTmFWmUXWJUnrQwLwvWuE73RHjv5L/GG8Cv4GVjduw4l2ACdpwDhMAg+LBnUeNT1DnfeVBVTRlomE1l5+iZ+YDh+Lk6QL+u/vcAzEhzTC2Z9kIBbToeuBNf9Qm7oaag9QXxe520lxkiP0nbTJ6mKGOLvmm8m7OnQQtEH25byT4SoVkW1DJbj5YPxBAACAQMEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5XxAXU2VjdXJlQmFja3VwS2V5UmVnaXN0cnnfECcAEAAVABoAHwAkACkALgAzADgAPQBCAEcATABRAFYAWwBgAGUAagBvAHQAeQB+AIMAiACNAJIAlwCcAKEApgCrALAAtQC6AL8AxADJAM4AEQAWABsAIAAlACoALwA0ADkAPgBDAEgATQBSAFcAXABhAGYAawBwAHUAegB/AIQAiQCOAJMAmACdAKIApwCsALEAtgC7AMAAxQDKAM9YQ2xvdWRLaXTRABIAE18QEFB1YmxpY0lkZW50aXRpZXOhABRPEQCVYYGSMIGPAgEEAgEBBCDX4Lqi2liRQKhXA2QYm0l7edIQPhVLwuk/TWLlyAT9PaFlMGMEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEgwRgIhAL2uoy74rk2RNImZA2BlpEt1lbYXDjQDLVWFl48ZiGflAiEArkFMxuEWlWOHBtNjjZ44fmxKxWsZi8+NGAHfBCd+IAVfECxjb20uYXBwbGUudGV4dGlucHV0LktleWJvYXJkU2VydmljZXMuU2VjdXJlMtEAFwAYXxAQUHVibGljSWRlbnRpdGllc6EAGU8RAPthgfgwgfUCASoCAQEEIO1UvRUh4/dXuAP2OSJpa7jHDF7bXm3c9qaZLQs2jZYhoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIhAIt+5X8e6Vvnhatzyk23WJszwgW43pe+QOOKOKvLLEZWAiAd9pVNkT8XZvTaHhdoA8GLVggO8wCjJzF33KVdAjVyvV8QEEtleWJvYXJkU2VydmljZXPRABwAHV8QEFB1YmxpY0lkZW50aXRpZXOhAB5PEQCVYYGSMIGPAgENAgEBBCAZ2Mqr74uDcAkMedabKkMBE1YVv3r9BY+ZQxiztbxuOaFlMGMEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEgwRgIhAJSI7dsRXpoxNc7bFCtPFSDwUrWlwNbNoa+j9VpBg/nqAiEAuj1iKHKO5ixZ92iBCwS6tta9CNYL8DZMMoJYhrkgLSBYTWFpbGRyb3DRACEAIl8QEFB1YmxpY0lkZW50aXRpZXOhACNPEQCTYYGQMIGNAgEHAgEBBCChFkKqgrWzOfMgBCCorBsVT8hy+zmWs15UbouBPzHsGKFjMGEEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEYwRAIgJUhOSBsTLydtk7Xu0V2PP7A+Q3VoDsDrJTGWbd8z01wCIE03dzox48zVifu5Uo5LPTqD5n1HxwNX21flE1bs+W8YXxAWY29tLmFwcGxlLmhlYWx0aC5zeW5jMtEAJgAnXxAQUHVibGljSWRlbnRpdGllc6EAKE8RAPphgfcwgfQCASwCAQEEIEL01a5kWCyuQN5cUMudqRaCgjgv9xfLP6bjeULYlZQkoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFjMGEEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEYwRAIgajftSwxdvsZot4HBh+DfTZNYa/TFszpcO6jGL9FfT1UCIE5IPiizk1f4ZNiot1F6sJNDl0RVJwhZpHqfjlIBMO5GV1Jhd2hpZGXRACsALF8QEFB1YmxpY0lkZW50aXRpZXOhAC1PEQD7YYH4MIH1AgE2AgEBBCAO/9RLJMcHo3qhFeFb3qanoK8t49rSDrm9ilPvAeiKJ6BlMGMwCgIBAwQFMAMCAQAwJwIBBgQiBCAownsDFvISVYfCbbD/50T51ZSZzt04daIl5fdJpmI89jAsAgEBBCcwJaAQDA5NYWMgT1MgWDsxN0Q0N6ERGA8yMDE4MDkyODE5NDUzMFqhZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIEqa4Rq2iCw3ULDe3577bLpHuUyRvUDtEKE0rS7H4IIGAiEA4yG/enWyQuz+TacBVbe3U0cZ8mNarFnCWvjagNZ/BU5fEBxDb3JlU3VnZ2VzdGlvbnNQc2V1ZG9FdmVudHMy0QAwADFfEBBQdWJsaWNJZGVudGl0aWVzoQAyTxEA+mGB9zCB9AIBMwIBAQQgrzTyQdcce8f+FDq/uSB/9FM1Sl/kKb5ql+zgzpXjJKygZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiBnyilDS8GYaSIvTiKxLZK7Ae686XT0cf53PqXed2nqZgIgKyFAcdBAD7JRtU62B0izaNFwrReAtIoU0H2iTwQIsqhZTWVzc2FnZXMy0QA1ADZfEBBQdWJsaWNJZGVudGl0aWVzoQA3TxEA+mGB9zCB9AIBKQIBAQQgv6uQs7cTnM64Te8OT8U6trFqk03SERobf9vvoTbhqd+gZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiBAnAgyWAjqzPKgZ3QOwXhEIfIu9MHBSJN+L9IcgtVRHAIgHaRrjmDqvIgsnVwq2ZFDjgiyve33DvPQMWmg0OPa9ihaQWN0aXZpdGllc9EAOgA7XxAQUHVibGljSWRlbnRpdGllc6EAPE8RAJRhgZEwgY4CAQ4CAQEEINdOlpTfZX+WPGjvWza1yiNoWWvNZO73d26fN5jorlMroWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEAzFPuXno+O0aMsz+srVMsB4maDlCSAi0yjvsVIfIwcf8CIGNHoY5q0UT4K1C5rPu4v4k0SgXRHT7UzKSgdFIeo8ilXxAgY29tLmFwcGxlLmljbG91ZC1hcHBsZWlkLnByaXZhY3nRAD8AQF8QEFB1YmxpY0lkZW50aXRpZXOhAEFPEQCUYYGRMIGOAgE/AgEBBCDyKeoxY5kg0jXZokvw9XIZk/dXsLybRdeGyOhCRXTz/6FkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIhANGlTEY7KpACQHm7qcSuuS/j63P5/AHuM/CFNtpxHPs2AiBB4iFuMmexGzcAdxjD8AweXzf3BuT2eAMPveTum/AsYVpDb250aW51aXR50QBEAEVfEBBQdWJsaWNJZGVudGl0aWVzoQBGTxEAlGGBkTCBjgIBFQIBAQQgAApHNADEW3GPIbDN5k5YGCaL6IT0o+kCI6NrQYRiRqGhZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIByj6JhH8huGOaKq1FwtyCx/e3xWDS10/78Z8qZuJtzQAiEAzt7mRHE13w10++4iZXLTz51rbJFmhmXcWikhHUNRmgVfEBZCbHVldG9vdGhDbG91ZFBhaXJpbmcy0QBJAEpfEBBQdWJsaWNJZGVudGl0aWVzoQBLTxEA/GGB+TCB9gIBMgIBAQQgpX7w8xr3w20QI6XnHPfuzPon+MDv7XVkPLzm9dS9fqSgZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWUwYwQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEESDBGAiEA/g5zMFs3ClwqTTe7zg0qAhZ7jHh60Fdx3RO1uj7Se1sCIQDzZgGv6NIRmlaGUEDAzA8useGiC2Unr/qvh9Us8RVPT1hCdWxrTWFpbNEATgBPXxAQUHVibGljSWRlbnRpdGllc6EAUE8RAJRhgZEwgY4CARECAQEEIIjdeg4/gqiy7fDwz4QI9MwKeNszecuaMr/paUk5SgiBoWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEAiDMjZtgfKpEcBClireWIjqO2fxlPW978/Pp65A/g0C4CIEHZ0hu2K7BLGBUiSojr31uFq5FE4eM72vjwWuOtMmVwVkJhY2t1cNEAUwBUXxAQUHVibGljSWRlbnRpdGllc6EAVU8RAJRhgZEwgY4CAQgCAQEEIF7MMhZ0znob8oFdqF6N0OD5bTo8hk5GrHzTwcGT4nZ2oWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEA8XkD8dxJXiB+2Cn8k0m3didw3pRo7tZ83a4smkVVu0wCIF1vJvVH/v2rgCcy/4MUKxHbviP+dzhMEmXnaWJub6L2WUJUUGFpcmluZ9EAWABZXxAQUHVibGljSWRlbnRpdGllc6EAWk8RAJRhgZEwgY4CARICAQEEIGxGz1ZMgHL3aYgxV3pRG15JTGIDBGkcQqJPWTLQxk86oWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiBAODn1LywOgNLg6QUkoII4ij/SCQvLuiVsDR5ttGps5wIhAI41xTXyV6791UZyVY2A3gU9YgcxfdezpAPiH6GkkWz2W0FjY291bnREYXRh0QBdAF5fEBBQdWJsaWNJZGVudGl0aWVzoQBfTxEAlGGBkTCBjgIBJgIBAQQgKY6oKz6mSwVVKOEoS+1ZUF9eMywc4I4olT+pHlhOexuhZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIGmjnKNWoi/Gyiyl7+FploOpEcExUI3WTEvhkSCZsXtaAiEAwHUsRvjfIqI1BXUQDJRqoMzGTFcSmQ4r4sn+ztGDkfVfEBNjb20uYXBwbGUucm91dGluZWQy0QBiAGNfEBBQdWJsaWNJZGVudGl0aWVzoQBkTxEA+2GB+DCB9QIBKwIBAQQgjumFy/X+D5JKBQkzmE3oz+ePP/p9kGC8nr/7/etLVUigZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiBtVhLAHrqTIUdb+/tUcVgeQKLJ24YJy7njNBU+MSGBYAIhAKJE9Ae6mvqUDCYFYicuPJiTsE2xU1XDfQrM9XG8Q+vsXUNsb3VkS2l0QXBwbGXRAGcAaF8QEFB1YmxpY0lkZW50aXRpZXOhAGlPEQCUYYGRMIGOAgEXAgEBBCAjsVTQ0pZmrzPCJAdrUjU8RDTgE57XNKIyvXPY0HkVhqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIgfrBiTRmWf4KPF+HN26p3jCAjdIeTIySYCHoXSYnuDxMCIQDPm8w+aF9D5f8nZdPGAJgZGf7IfYYej7uksgAfWpiv6V8QF2NvbS5hcHBsZS5zaXJpLnByb2ZpbGUy0QBsAG1fEBBQdWJsaWNJZGVudGl0aWVzoQBuTxEA+mGB9zCB9AIBLQIBAQQgjiguBlj9OzF7ZybgF6clZEcK1wYRTH9XxL9RDS9hxRigZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiA+pB3ljZygNgkYh7TrLE4OyijDjTn+SvMJzrKQZPnfbwIgSkaV5AWx8zm23PUs+t1hHwIvtmeojmfr1Q1YqwGxa/xWR2FtaW5n0QBxAHJfEBBQdWJsaWNJZGVudGl0aWVzoQBzTxEAk2GBkDCBjQIBDwIBAQQgyW48v3kDee9VM/MD1rpChNEmWP0LyJQOBn5FctdNnwahYzBhBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRGMEQCIEqwVkXMaMdfwnbQoaA2F5mm4/GOL2WAUizoBzHSMCkKAiBJKuiiJo5b5pVgZHsMitI1MKksobbibibV7sdE1CiKWltpQ2xvdWREcml2ZdEAdgB3XxAQUHVibGljSWRlbnRpdGllc6EAeE8RAJRhgZEwgY4CAQICAQEEIBc6U2wxA1UlBRj52pwa3f1dRNsNVPaSyAQExW/I6OQ9oWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEAgv7WXwyxFbes33Ax4zu1KKdqSn9zb8OnaQ7xnw5kHFICIAvXkgL8KsmCRAvJLitqsZ5OYwUobPfiL+NDUBAfNDLRVlNhZmFyadEAewB8XxAQUHVibGljSWRlbnRpdGllc6EAfU8RAJRhgZEwgY4CARYCAQEEIGoo/uNv5M+eGFOm/OIf0sbhoNrqLUgMsma0UGXu7sBcoWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiBhPW1rmcHkbUZFxxLNfKjzia/FvfFN6pJXQc3DfM/25QIhAOegBT7cu1cORUrifnW18tevddkhUTA8YiYEH+naobFBVU5vdGVz0QCAAIFfEBBQdWJsaWNJZGVudGl0aWVzoQCCTxEAlGGBkTCBjgIBCQIBAQQgiiKf8iak5uCLn/0lo/I9WEGums0ZqQmP2yqv4IjummahZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIQDheScSZEg18OoTUhfXiZMLeXCkbDDFdybgySv3wRltZQIgAY2WdVPl88rRqeYtQOmIBO1VaUfW7SOv0EItomWxQAJfECFjb20uYXBwbGUud2FsbGV0LnBheW1lbnRzZXJ2aWNlczLRAIUAhl8QEFB1YmxpY0lkZW50aXRpZXOhAIdPEQD7YYH4MIH1AgEwAgEBBCDMr1rH/wSxKnXhhMuq2kmQAsbuu8aQ7CUjAaP7ltmt56BlMGMwCgIBAwQFMAMCAQAwJwIBBgQiBCAownsDFvISVYfCbbD/50T51ZSZzt04daIl5fdJpmI89jAsAgEBBCcwJaAQDA5NYWMgT1MgWDsxN0Q0N6ERGA8yMDE4MDkyODE5NDUzMFqhZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIQC2O2y2BdX70rfntL/TRaSfQ2hi2HDlJRcDY4Ac7dTNDAIgMCCNLTjH3w3yanomcdUpUYpUXk0xg7rmWv776V2/ph1fEB1BY2Nlc3NpYmlsaXR5Vk9Qcm9udW5jaWF0aW9uMtEAigCLXxAQUHVibGljSWRlbnRpdGllc6EAjE8RAPxhgfkwgfYCATQCAQEEIN5dPjrSty+MgOnxokT64PDUkrKiyt3k5oI38p5AnL6SoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFlMGMEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEgwRgIhAM4B6CLjnTCbliTZC27uxJ/j+MZbMJZTRrgU9FBIKAJTAiEA2nI9I5z/KIIgh91hQusrBxnR2bvXR60pgU2K2u/xVHFfEB1BY2Nlc3NpYmlsaXR5Vk9Qcm9udW5jaWF0aW9uM9EAjwCQXxAQUHVibGljSWRlbnRpdGllc6EAkU8RAJVhgZIwgY8CATUCAQEEICY5ub8AyyEI+KyHDtmPlWoXunETPtY9gVChN01YLo+SoWUwYwQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEESDBGAiEApRyxYMo9vBC3ZMsebZvMNZNWDas5ituj7iwazSxPlqUCIQC/fHWNj8T/Fc0lt7HujLvHR0urgUaY0kUdYtCsNB0ZHFhSYXdoaWRlM9EAlACVXxAQUHVibGljSWRlbnRpdGllc6EAlk8RAPthgfgwgfUCATgCAQEEIN+LU3LnH9Fph0sdZb7EVs3D3RHlcJzmKwc3q52pobIqoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIhAKUXaMJ3HvqvjHbeLywEubqzKJBhiG8+YLZsS+fE+TFqAiBSD/AsQsZAyhF4PXZKKJCCUiAo23NK4KBF91SMBgHt9ldTaGFyaW5n0QCZAJpfEBBQdWJsaWNJZGVudGl0aWVzoQCbTxEAlGGBkTCBjgIBDAIBAQQgnoppjpqaZxLn0vbgK1JvD02fAEH1dXALMwjA/LiaDfahZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCICMsr13SCWNkUUHAR6O1H/Ks2cKtxmB6isgm4d76IkdoAiEA/3IGnk6BOWe23sA+nrz1Uj0l8AXOzh9BSRcvtYqgnDpfEBljb20uYXBwbGUua25vd2xlZGdlc3RvcmUy0QCeAJ9fEBBQdWJsaWNJZGVudGl0aWVzoQCgTxEA+mGB9zCB9AIBLwIBAQQgWyKU+rabc+abidF3WG3EIjgU/SQ7R+KNVvXp9z+IST6gZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiARBSYZikluYbi22N/VtgLjme7DMzsE5GvwZWjmA8P6jQIgTbLqYOOC+d6208tPiSLUATikDxTMkuIIDPt/MRIdaP9WUGhvdG9z0QCjAKRfEBBQdWJsaWNJZGVudGl0aWVzoQClTxEAk2GBkDCBjQIBAwIBAQQgnGr90u09c1SzPQfPLcly0+mORo0Q9owsw3ZSrGHX4bGhYzBhBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRGMEQCID8A1iTXEjdvswDeOx4NFHG58z0WxyQUdyaw6QThJ+6WAiArTTqC7lRMH6l+4wNn1+7KEFVH0+I/8t+AuQj6yGysS1NpQUTRAKgAqV8QEFB1YmxpY0lkZW50aXRpZXOhAKpPEQCTYYGQMIGNAgEQAgEBBCDcezl6FqtGyHkX174CEG8VSAOi4P3lIlFNO4qJfVX0saFjMGEEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEYwRAIgQvuSzR9rw1O2ySTcaQADxxJd1GuffZ2cxK1kGvS45cUCICC++3nOux4yl6TGku4P9QDla3NQp/7hH+lKmOIpvcOkWE1hcHNTeW5j0QCtAK5fEBBQdWJsaWNJZGVudGl0aWVzoQCvTxEAk2GBkDCBjQIBKAIBAQQgA2oLaQKK2tnS/GIAxrnRhrPUjQ303ZRJAJhXBA2FUe+hYzBhBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRGMEQCIGCGZznXFEVTtJoN5i5gdzHKRSLYk5abL9H4UjZbiWR2AiBF9jxPIXvjeD0ixKuBw4y9jVcBj1+5n14UEf5q3aw/pVROZXdz0QCyALNfEBBQdWJsaWNJZGVudGl0aWVzoQC0TxEAlWGBkjCBjwIBCwIBAQQgN2Zh4eSsuL19w0oUZ5VLkTxCC9ZP4OLbySW5BeSH1VmhZTBjBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRIMEYCIQDHk9qh4YVU22/9JheSDC5ZTgi+MJY0U01Ss3NrQ4XVSgIhAICVS3XDPdHft49emcZRdfeZJ6Xx7P/XaK9cBCIsXRI2XxAZY29tLmFwcGxlLnNpcmkua25vd2xlZGdlMtEAtwC4XxAQUHVibGljSWRlbnRpdGllc6EAuU8RAPxhgfkwgfYCAS4CAQEEIIzfihUm3ifzPM/Y3McNooAPAToGowS9Ztc9ecYuIl/NoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFlMGMEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEgwRgIhAP4c0nNzBSGf7ycZtiZpexiCNQ3kgYG6HAaSTCzdbrqkAiEAgdJu5Dufqn9GSOwo55U6rbllwv7eGJuIklki80Sq1JRfEB5jb20uYXBwbGUubmV3cy5wcml2YXRlLnNlY3VyZTLRALwAvV8QEFB1YmxpY0lkZW50aXRpZXOhAL5PEQD6YYH3MIH0AgExAgEBBCBjOqSZoGDwScKt5ncrZEkl/5e43V/wCItiOI3ffCu3XaBlMGMwCgIBAwQFMAMCAQAwJwIBBgQiBCAownsDFvISVYfCbbD/50T51ZSZzt04daIl5fdJpmI89jAsAgEBBCcwJaAQDA5NYWMgT1MgWDsxN0Q0N6ERGA8yMDE4MDkyODE5NDUzMFqhYzBhBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRGMEQCIBbcBuaykWaCE1IFXL/4nmckm8tSDLnSLUjeT2YtgVB6AiA7S+NREY9sOh3WrB5pVpmZfhd3Blv6JbeHkBsMjWDCUl5CVEFubm91bmNlbWVudNEAwQDCXxAQUHVibGljSWRlbnRpdGllc6EAw08RAJNhgZAwgY0CARMCAQEEIPTMF9d5k4kVLyhcz+Evysf0dozIoF4eg4ox1/Ay0Cj2oWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiBv/ZJx4OrvkvTubO81rciCeVSHyG+UACxMk/Ia2AUk3AIgY1aRKVg01AQZRBlH0YdWAhYwPxxxEqPPXuQy12glKQhZTWFzdGVyS2V50QDGAMdfEBBQdWJsaWNJZGVudGl0aWVzoQDITxEAxmGBwzCBwAIBAQIBAQQgwXd5uFhTeS7Kx8Qpj65nqUa2Rw8seul6PEhU0/LvW6agMDAuMCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTI1WqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIgfXzk2iTJUQyvhZKLb85CbowdarofTgcdwqpizaYq8tcCIQDieMFd3JCMHc5P2DZBmS6Ej/RocbKGN9MkCj6pGc0BEFhpTWVzc2FnZdEAywDMXxAQUHVibGljSWRlbnRpdGllc6EAzU8RAJNhgZAwgY0CAQoCAQEEIMr5O+MxnSPOECSWwa6jWdtSl8CxG60ieEJrS5eT8csDoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiBoNoyLhIzMKe8exDIHiT3gFobrLfgVsHcsOUxPalrsRgIgckaB3CVttF8XJjOPTyiF9ekJFtyTlqRNsOQ7FFgh3IFeVFRZQ2FsbEhpc3RvcnnRANAA0V8QEFB1YmxpY0lkZW50aXRpZXOhANJPEQCUYYGRMIGOAgEUAgEBBCCNrMVagA0+ttQkY4NGtYqj49b4PHHV7YFaAHyVd9vodqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIgAUD9nE+lBkcEnXyL0pcE/LE4diyBd/UbosjHyB5j22wCIQCUcJfgxHVChg8Ae6FjMuYjf7cVoyNf0YmuUEWkmwvoIl8QGVNlY3VyZUJhY2t1cENsaWVudFZlcnNpb25fEBBpUGhvbmUgT1M7MThBMjE0XxAaU2VjdXJlQmFja3VwU3RhYmxlTWV0YWRhdGHSANcA2QDYANpZRXNjcm93S2V5XxAsd1ZLYjEyZ093RUV0amFmVGMyUmd2RCtPTnROekZ0Wi92OW1Fa2YxRGQzaz1bTG9vc2VMZWF2ZXPfEBsA2wDeAOEA5ADnAOoA7QDwAPMA9gD5APwA/wECAQUBCAELAQ4BEQEUARcBGgEdASABIwEmASkA3ADfAOIA5QDoAOsA7gDxAPQA9wD6AP0BAAEDAQYBCQEMAQ8BEgEVARgBGwEeASEBJAEnASpYQ2xvdWRLaXShAN1PEQGhZIIBnTCCAZkEUwEA7mcfkI9joA5YRiHMKVPYdCl0EZbdHHSkd+XbtD7Mz1swmsOp0wrFLe6Vs8Fl/eLiARGAoFbEyqKuOqGBvVJcANDyON1SpccPYyE+m9Fv1N84BIH68b9LFxZu11g2wdpwAoLfHGAIpixj/l/ExdN1SejDh42zj68oMRJipC5Pzuy7Rsfo8hBqDgSCZQ0ASzcyZvd/r1eUVlkPdtfW3e1G8CiLvEJjalHXMK/q+ZkT5ix5RrImOK4L8KpwVcLyYf6RxPhvLtQIFuyDWZ/zcGeOQfXbEU0N3DEcM86jT5VpOVvbejiFABDV2auJtxAzcbPoimkyfQH6B0hb7J4MoUBqojYp3/WbXgd+xsZueOYaioaD5F47gGJJt68vV79KNCrerlvSaoAAFZMT3aj1EfjWzc2Q+XU2ugjdA7yNrxDXAtzteqcTbqVa7k48t+smmgQg1+C6otpYkUCoVwNkGJtJe3nSED4VS8LpP01i5cgE/T0CAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5XxAdQWNjZXNzaWJpbGl0eVZPUHJvbnVuY2lhdGlvbjOhAOBPEQGhZIIBnTCCAZkEUwEA7coGYUYS65YHnBubKFI66JIshlD/zcZadtS7UPht/gQw4Na60gEDpn3LLWAPmNzSU5aFq2i5FdGApmZz2ZjxJhKs34OzsSz2kh2Dpg1xkYYABIH6KTIPWejPTEmBIMu/M8MHedxNSBN92aCUaaFKlFpIEfr4ERxhq2+7aqBDUod+agFjj6BzEi4NBHu/j4LZsb4fcOMwq2G594K7cevsVg5hsWb800lTOnIWzgnPfk//T7CYB3S5UnPQnLtORz7gQZzWlqloHJSGltcXdt9nF5hOsawKZttCDaL60j00MtfeD0WO+aLl2BmD8syaCwNFRCG8zplq3ot9Anh6xzoeTGzljjuYmPQPAKVFkUNyBI81ZK04m9wxPUh164CPXdv2hsm+zGqNrTX1sny7hlcAVbMXspR54l7EpBlHw0hO9D+2wtrfI4cwtfSpKFG9oAQgJjm5vwDLIQj4rIcO2Y+Vahe6cRM+1j2BUKE3TVguj5ICAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5XxAQS2V5Ym9hcmRTZXJ2aWNlc6EA408RAaFkggGdMIIBmQRTAQD+0aNWKcvemMMRA9pFVsDUo4dRRagvLY7giYyVJk9DGjCPLe5WaLMKfACvgcKry1B7M5fpGavtRgR/gJdVDfQEK4qtMLiIjC2a+pa6TrwWHYwEgfrcVDNNsthPPweZ4CJ5B4Xu+Tf0c5xbWAki7icWTyfHWxz6wDnohZwVlgMfMmxq7KSPPix7NMT/jkKumXeqIKCcCB1Db19CcNmxBU4YKFkj4fzd03SWhu14Lg2zGTEQ5ZL5yw+8RhEQBxlYDPwLZyXYwQByuEqoBD7RDGKisfkKiJ/4z36edNEAA+ybDUw6oDsk15xF/BXr1bxKMAPx8lzHjqEf1p6Ed3R5WDFRnP2qhepVuM4QUvZnHVpi+pzbAbJYRQgOZ0JKh/cNhn9Tx48ZC15eNN25p60h9MM3z7iAT38A88OJU3PApplBg4ayGT4NnDvB505DCfTCBCAZ2Mqr74uDcAkMedabKkMBE1YVv3r9BY+ZQxiztbxuOQIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lTRkRFoQDmTxEBoGSCAZwwggGYBFMBADALK4P6VIMHF0WrlDwXMlkSmmiK4UrYTX70EjtqQRypMPHWinluqD956QYjJ14BmQKITJOVQ9s5S3f4x4Deby+FsKEdKIU9nGY2B81BvNT9aASB+U0dId7UXZWqfMDkQghIaEWmTl6Mz6EC3OlEG9OsmykhueFqliHomAw2ATUidz6p+6UyMW4csYOevYg8JwVpR2XDppW00D3j8dq/kMrLv2vD3/kvSGAZM+gQgaEvIiu3e2aJ3zuj+jm7lx0FyFHg6ngqhQsGCFbJQwVYsssL/L99M5igfhrOQiJcK5A1Hlxo4pirMp7uRYIYTijXNYa5n5/ly1fB7fnkvEpHI5rmeDQIsuGGacihlV/FRAu1rcJ1UL+w4+/gAUPnWWGWQyDJEWC33/LD+L4s6gyvP8Fzir9OrAaUhtWr7nlq9DuY18S3R7akI4xVP31zzwQgJH8/DbB4RLDJA8K/pSz+nX8BBr7PNwXtA8BvjsCNxlICAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WEJ1bGtNYWlsoQDpTxEBoGSCAZwwggGYBFMBAPDFnDgLhUc74GG63drt3QYvw9VBWfaKjS9hHU4zO99eMDk0m2wKsoSGFnecJDcG8IeEEGTeWShHL/laSDi03OYIPXRfRgLau4lkJ3LS5SP0WQSB+eP37P0MM60iYXp+VNYrJISLFmwc3SvkLXXpIFRWCD9+ENvEGp4O3jdIWaPp3cogXKhyd5C+Zn5OmSKb3FBxaV4AtMMMU4Aw5k9MhwBDnr8IH9kJ4No6GxaeT8KR4sJqgiOEZbTFTMJ57+L4fMjPFmYoXrGRFzAYqkt4JlkZON3QUwigMx4Sj5UfNr2Rzk4iQ249xMKZ7tjI34zBSwvcIvg3LpPCtmumEauDeb6C0OQIryjv61v03uz+MKzm4AhLU1mWRE0JhEIzGu7hqgPKw98qFl1/k3FSI9QYYKbAiVE+pMmBL7/GOavaAmDDC8vuqNra1OeoH6tcTAQgiN16Dj+CqLLt8PDPhAj0zAp42zN5y5oyv+lpSTlKCIECAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5U2lBRKEA7E8RAZ9kggGbMIIBlwRTAQBPXIy3tf+0RvkMYIDYE8P3ODA9xrVmBM2IVp0LO081kTBDOW39aaiT3AEWdm0EXV5KgPBb6GTJZIeowtZvDueEMIYWwrmaHFdIPazKfZ3glgEEgfjd2sTR+RY576H+T+2WwDQr4xUriaMMZf5Ghv3toN74ArmFHhN3xM5M92KUx87ijkOlOgNDvDNUX61ip6wu+JlxMuVu0r7z44hvHHs6mtV3GnwvVRBxFEN7kyvMSmfJQZp39WYi+oFYldUf4hqotdMuGxVPVfBi9ozdDaCTeHcRgDrONMtQqX8ZqCIANKYlScv+zPp0jzV9eGy1xbAQu+/EzVWqkEhk9AncT1c81Nf3puDq12wfXHLN7OqKNqeFw6ohhxHx9u4+hy43bbQsk5nz2TSBBNhazBT1XvurDxMKIG7ooEvzaiYg1/nWgDdxehIyNAJAGdSX5AQg3Hs5eharRsh5F9e+AhBvFUgDouD95SJRTTuKiX1V9LECAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WGlNZXNzYWdloQDvTxEBn2SCAZswggGXBFMBABGSg5qvbVq2huEN6LUJ8YQyv67PfpehHqbUNCRf4zwoMOLmtU9YPY/yAuDjpPTxFFEIseEeVWAk7LRPR7XVQuwIYTiGxVKfivJrN+iE43q10ASB+HoGSBviZC139p/VgkB79lHv3MOkm8RJirazbWH6rPOcfa4YWS2hGoOeZKO4av+Z70cgDdDDB9Q8VO04qXnE1s+MHuRUR1p9NNjzOE6jA3Iu/9PmevlAEMF8xfEsgF9dltlGZ7O/JiigiwljAX7I9g77tbGm+yyJ+HmR4jKtuW5PsObNpCP1+9nnunnjRqoT0tkMeWu7h0pLkP/jmE1BvL/9wM7G9Bs59IKZUu6XhVzQJvxcs2ITHlkFmz5VnPB3Q7Ic6aQm6l5AW16uUs5W4f+vKUzBwF2C1qlrFCxJILTYLv8wJuNOSw6lP6V29TMyJGyQG7LxqYnvBCDK+TvjMZ0jzhAklsGuo1nbUpfAsRutInhCa0uXk/HLAwIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lWR2FtaW5noQDyTxEBn2SCAZswggGXBFMBAC/aj6MRkzpaEJoPpOb/S/QytRVQyyPeCEqNEiJdoCFrMHvz04b+FMGAL2MtedSWJ1V0RqSIJVwod8DJkZ/x3gbdKcKHlXPEKbcOtA7Pfe3JxASB+D4t5omz0TG9dfJxs/g+AOW85v/fkmclvJV7K/b2/QqaUBFz98aftiKLBVdyfGIGYRZDZH6AfX3I40rpODRPvjZ6Blxtxak/PFK7w76cpBbbR7O6Hb/p9cjJ9R2JTig9JQq6dCwM7Eaw35vK0B7fF8QAkZgZlBrkf4a3g1sPpC2nln4u2CflDpQpjiVqNNo1MrrFaGrDcmIdPaAiT/D/o5ySmi2yO7ibLcuZCzKVRR6j/UTGAeRkE9J9fKtH1BDul0RIAUp9EjoONdiu14yWmXqhNA6pBfOx4tyS4Nc0YwBktgfZwHrP357bkHKP3sgj8SxwLKg2h7HnBCDJbjy/eQN571Uz8wPWukKE0SZY/QvIlA4GfkVy102fBgIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3laQ29udGludWl0eaEA9U8RAaBkggGcMIIBmARTAQAQnmzAB4p0aaUoHGjNJOmxML3vNV+338xa9iYV1UFqyTDRaBSRUeJ6Ba4coTnGmEBXBz3x8QevxZ3EN+tuDSTxf+hQECGMrT1AUF0oABPqwC4EgfkyJi+JAc64CcmYUhWUfqoyiK/4kfOCReXh+63BzBWgj+3xjxUTzWp5eA/o3rL2IX9WlFUaFWpoPuM2peNUXJyBavA5cdgXlXoeDEYgZ7v+UgjK2MDLRRuufghkafWEoaYUzf2viGgUWfhRgvXXBdOXfEIHEb423rq2cPa1lIy+VU6QGLVn+5bEWybu94NjMK95EjfzI4qZ2YbjOSd/D4BAXy1hxY4ph7f1MqHCA0Rh7n9Yj3/cLFZSrF30fSD3Bvo46VSOckQl//e6hgUtSkCVgvIM/wmUOoNp3VPEv3B1Sa34N6IcdMLvbAcK3RDVOe8cmEEGGJRHrHsEIAAKRzQAxFtxjyGwzeZOWBgmi+iE9KPpAiOja0GEYkahAgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eVpBY3Rpdml0aWVzoQD4TxEBoGSCAZwwggGYBFMBAIren1qPjibvrtAJoHi3Mi5IU4tlJzUovigqzD8Ku3C5MAw3wqdfbMfdYkVeujIzl58mnNit2eDXtGLtaUwPNDb3ym6CZ4A4CLBlxnYqR9EYlgSB+SFcR4rAvBSy5Ca06GL/c2TZLHLucYdb/f0QuNyBEPtVSGML8wpFBgn0TYP63+5hyE+KNJ0KabxG++UGz16B8wdk3pm6iWASA5bWEAa1UsCCNK8A4qQh/i6zzSZEXEKMkblbB9m2k9nuic9y+t9M3OL85g8bdrTxFn5bgo40D5IF/egNphdJRRfJRyEMlU0DsbOysIK63gpPdv11T6kv99UpaYWjFfO/2QpyrTKVW9Bd7hhTNtdu+Jr5fvN4IhDlIDKsw4TKjkiejFyIFtv5WKQc/lCqS2VRzZ2MwBSDvbKAx04Uhkf8AozhVaNj4WK7kvc8LTIPoibsvgQg106WlN9lf5Y8aO9bNrXKI2hZa81k7vd3bp83mOiuUysCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WUJUUGFpcmluZ6EA+08RAaBkggGcMIIBmARTAQBDehu166c2isPZKlk6kYH7zw6WpCAjiZhXMh6pjOsypzCOmBL4QxrIAISALLfSbBmRdX7LWbG1WjwnPmwAemuPfCKLIeu6vaq5CcuMknizzx0Egfny3/4qGlCzsFGZSChyjO1fxs2ika5zTxSrmEeIF5kvlDvaMe7zBEgL9JK7Paj5MdTIXwl26Hx+c5qcV1NNW+bixlU40IoIcXU7ZcDLmQ55hFjjf+iatLSsXIQuJJjUAFqXKQEIFBgf/lYLMYBCeHeHqzuVW5i9OmwWXP7DNbFeeEAfQdVJP0B/wI4SmJ3EBMBns5OkEBgP1Je8GZNrFKwHqw92FDzdYsYXPgP5bitrKaC5JEhBdRSPDQ9I/Ys8hpZqDDD/iERkanvg8gtA56I7MGN541vNN2vmvacgUJxCvWOZiHYRvZ+EH4eNTZaf0RfnJ3pU7Nd+oA4EIGxGz1ZMgHL3aYgxV3pRG15JTGIDBGkcQqJPWTLQxk86AgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eVtBY2NvdW50RGF0YaEA/k8RAaBkggGcMIIBmARTAQAiRETKF4ZMSnH3RiEHTO3eBbu/gmOCzZgX0rx8M50YVjAYMKQHhsHqP0VmvVkSDntQyOp2PCxQC2F7Ht49+WjTVafg/Nq0fWss7CMct9M77XYEgfk/kGbcDJpY8mpbXfw7PGx5l+TGZlrKMYra0exutGKC2HcCQ5S/Kxq1hyCYDNUV8FQhNzYXZ5Q4yVfTkur3wlYYlQ3XDHospgoICYhLLsZ9oMNJZ3fliVJFetgeXaaQOMalSRRPhEHZERWwEfo645czU0bewWtXczHstm3upa3yPx9unBP1LfqXvtPIkgw+7/GTLAbEtJQ/lQOOJvJ79nxPVISmrKKQ7H6vv9hjeJlzMiIpwNUkKTPFBsQYSRrhr2vyHflKAzm7LxvOM7+F5ciH06HFwq/ZtipBuWdsyO0vS8uqnaKFP1uUd/sllGtb/zpijSE7VXd7fXQEICmOqCs+pksFVSjhKEvtWVBfXjMsHOCOKJU/qR5YTnsbAgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eV1DbG91ZEtpdEFwcGxloQEBTxEBoGSCAZwwggGYBFMBANoDsK3M5Y5DwFh4EQAyeqPIHYC8sSin0VjallJ64rNeMOU7Mjv5tPa0DGGqqMyvdojXYioGVUuHsJ7Y50S9DCDX0LsRPN0Ve6xqwzt6BLienASB+VfAOuYKiJOZEO2YFPuGAzqYvM2XHzEj27LMOXz8tkXB9ddkW6EAD6Q0Vqn0QPr+qM7yFASxbd8h34WS6Xddz28cY2kio8Xf8S4XTFpN/VgHCJSEBU8rqwUtwtDbH6R9qFVY6DmiyP4r9XCCE44B4I1HEKF9etVmU1HKeAuxg+nhMVhjX3PZYe4xFzaLrUS+1tngTCCW3GtHDWqHp84fBHuLfwjXgblnthMdpGvimQURj0bsOKOU9lv4gjrt3WPosxYc6dQS2dAGwQ6ZhCCO/vHrzq1x6mF+6xLfRbXuWw72aDtYZjurCLrjjboivWneN81l3WTKjTmZOgQgI7FU0NKWZq8zwiQHa1I1PEQ04BOe1zSiMr1z2NB5FYYCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5XxAgY29tLmFwcGxlLmljbG91ZC1hcHBsZWlkLnByaXZhY3mhAQRPEQGgZIIBnDCCAZgEUwEApcI++fPiMp2F7719sTxSJqaM6ee9DlujcuWuzM6tJVow1MYYRnnH8QbtORp2/ddi/I/oOoPNQ7y8LVOGFVyJoARvHXAuJbiyoT/PNy3FzHjbBIH5rEU6m8vdSuPs0ygcTuIPvXnGDYdkGzx4c39oflgmaFgUsuW++rH1HOa6cCgJ/lstbJUXRWhgoOMro9kMmgI89wzcd5DSBiG9UhQt9ZDVvWz262k5O01os9poHy5QWHECo4HqcfykUXLt/pQUo0QcQ9b4xGRis/X7vzpprRcK8M983alsaJH6Zeh87J6DDPajPfxHN/HPzB3D+GklTSbzm+WRA0d3Iea3wh5edoJl9HSqXgxx4UFnpQyz+Y9Yl467o7Yn42/C+2IvNFRQM98STxWssxamHdoHl5p1rUIUxseaHYCmdhvMUAslosNalc/pwDmXbrlFVqktBCDyKeoxY5kg0jXZokvw9XIZk/dXsLybRdeGyOhCRXTz/wIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lbaUNsb3VkRHJpdmWhAQdPEQGgZIIBnDCCAZgEUwEAhTriZPlk5ba8weQP8abhLwtXIMRdFUPlVDwmgqCY2U8w/ZpeoOaJ5wp+7NNBOQgGi88JCQfor7ChKRLSy0rdlAZDLKEHZiflNJMpqaRLDNMFBIH5Zo4hPORCAtqiKM6BZmXDM4ZnyqLNREjAw8SAyQKqviDGU5f55CavjkHluBLUzvddxRPue+IFc6+Yes+Rs6R0Xj9xZpprfAFk1vusLNajPhT+a4+ChnEtrp5c8keBz7xte8YgPINm9HyTERH4X/QrwHXE0un5d2iU5tE1Q9a+V9FctlUHl4DeEKk1cO6+UdckPo5l/1ozpxscvNptwgfla36ivuZQ8Nawz7Bc9s9EiFRvPa3EaHN1pJOMzJ3eWCqkFy+XheEaF6riryW/Ybl/prjzre3i0EKTzzXObnZ6OceTfOzMmPHKmCj56rjqharVhoo2e8zhwV0lBCAXOlNsMQNVJQUY+dqcGt39XUTbDVT2ksgEBMVvyOjkPQIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lWU2FmYXJpoQEKTxEBoGSCAZwwggGYBFMBAG26kq78j3vM6eU91omcumtqCKKfK0/fo8buyvJLf1E3MCuoxrigFshN7yrs8mBWbA+lte2gqtGRnwgMVOyzoPkrPk+QD+y7F0bC7huKrPHNkASB+Q1ThtNaRvEb1hWcTGJKuMR0x/lzz+jJItKaUW4qr715P0d4twlq+7HUXIBy61hLrttG+zDro66kWrcd8fS3gsnYYi4Jq/RvcUZvAJkZXGIqYA+PQ7L3eAReDZDVko7XOAOuOSMmQXR/hidiVkDrbm0/KRlhBEtsGgLrlJuOxX7TIHR99x34xsqRu3en+K56FOTYK2riK8/LgPXs00yXiWI+HSOACe9iwPBZ5WTTyfqdsHOQlk7iyhyo3APg0iYq3WCRhbrE4yYgZjwcxHx1k1PnRHHoUgjMSZ7CtLCmFMvBsfOjTAeU+6ivHc4L23qeweIor2OSoz4qzgQgaij+42/kz54YU6b84h/SxuGg2uotSAyyZrRQZe7uwFwCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5VlBob3Rvc6EBDU8RAZ9kggGbMIIBlwRTAQDk3uWPUFMtQRE/nXFto3i6/CZoxi1g1l9e00Sq85dIvTCxs6Jq3n2+Ry3ea3bXVMGR7T0/xEFYPlKrOt1+G62qDzyyGoNW80+JgXMd8C/qzIMEgfij8cfPnXNhj0mE3AIdbwb/+ikfjYfOSVG6Vcs4XLbdDANFR+Ikhp7Y/pjyxNhsdTw1u4oFISizmLSyIh2oMPuVeLb9jry67pKTaM2dFlLax872o4UY7Bm/okYOHaLdgECm0OcRKvuGW8BnwdnKuXxJiLUg3pHQMdqWFMXSTH4r6Lvy7vKqKkEfqhR5hzoa4AViSRi3UTaizpvYzX4f2HjtKSXbWG9qH5QCcxelEe4OEVF01fLou1A+YqUo5K2noDBLclB9MS/WQR1S/btHYylCJvulDBcSfYvQwVBHhAWPVM8buE+Qc8jbmGi10Wh3R1XS/QsrpLYB/QQgnGr90u09c1SzPQfPLcly0+mORo0Q9owsw3ZSrGHX4bECAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5VkJhY2t1cKEBEE8RAaBkggGcMIIBmARTAQDcD+fhaHOfAX8u8vMCFMUETugjEqK8E2pTs5IToVMZZTDmktst3dSrvbFQ8fDicManuZib9o0rgn0EpuyCYoMs1XCWztqfGRImQDvTpcKxt2AEgfki399H04dYrO7yIcRp/thiFBJptag18lGllLUSQ1V70OiMkMl+DwTFxBCw+7olIsWFD5py88RaygrNbQ8ixVvmiKKpThZZ4AZRLktvEAQ0Z4AQ4mpudrQPuJZceSYQa1EqX6tpZJkCxcAalIobL15+yy0Ns0Y5w3iJ6+nwOdKQXBKhD4S+RQAxvUyiIIIIHQ0J+f4wrwsiDSD4yEEeneV/wcLwCJ76ByPmHNV6wx4bqWM454FUTwFLp9R63khahI2GFHIOjITRXmSNrgyvyFjlecHcbTvvRWgPBhiY9CPSOCsb6NLgBCxINbg+Sc3EuAoeT/tK0nu8nHoEIF7MMhZ0znob8oFdqF6N0OD5bTo8hk5GrHzTwcGT4nZ2AgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eVZFc2Nyb3ehARNPEQGhZIIBnTCCAZkEUwEAq92z+A2mGWeeOAh6/oSmx+1nNN8OVrv0OZFF9ACP0L0w3Tq7x0BsXOKji8FqrajsM0b/9vvFNDPKpeD0iM6qgjnOjXhTEVU35BNEd9eXuNpWBIH6NWYRYQLnDg/RX2JWnmomZjRrOIr058bkXVsn7nbECP5XP8UiniHnk1DchxDMlkkmckV9612PnxNyegWg29s0i1hf9s+NLrhk3KQEQ585xa6Ghc14F2oN8M6T1xMpK86u3bO7NeSVJXbst2LqeGFYf6nop176vubd+jrNAvMVemeCADoYLyDYLgNmAPrVfQC/THUMQVMC954K12m60I4xoenEvFOR6Vlg4wyuR9eJCcUhb4+iqBQO62xtbxakcQETMx4GBL/yy69NTEfA+hGKD0uTqiU1PTGmOtUrKTfH6X9y0aju9o0B5jAUMJ6rkOHunLQr6jYvW+L59gQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3kCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WE1haWxkcm9woQEWTxEBn2SCAZswggGXBFMBAKt0Mur+Q9Zvqn/voOmB5+uI31pFfEXpXsYscNrWPBnYMCenJjKgoLbzTvEvqPf7NkO8dYmO2fg9pdmEum6OUDLa9l8WbS+uPLypUF8PZvk3gwSB+NSxcQ9cse/8eKmKlUlIIliSUFR4I+ZXetxca3+0h/CTKpbgvw9t9q8N2hjayGyfQ3u2WQfdP9gUBL7d9R+e+MsugAOvX6+hCIGUA8PGmF8nux9GRJ1CL29LyaocSaJDvPqi68lWGadm/VRpgLUQrUiSZqPUkKgc2FQ8nkuRcHv+6k52E/+n+9H6yQXp9CDAdhegfWJodhHweZoCLWL0LIv4nnWdEqEoRIRC7/3ZDBUHxLAS+H1hoGXV1kiL2kA8P6/7daeUMQoBWsxGdz9jZmtwjjWHuA3Znc76wvaVP7J4HSpPFvsigfF4r6Kzb0gNryLTDcXKwT0OBCChFkKqgrWzOfMgBCCorBsVT8hy+zmWs15UbouBPzHsGAIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lVTm90ZXOhARlPEQGgZIIBnDCCAZgEUwEA5QBs7cwCbsgxb6+/WPrQqmz8PyGvRm1M9by43vPoXpEwIvaozyKcDGBuIUOKXPoZHm8qMLwCqjz3la7fD2E8zysNgHx8R94dZs6RTFm00Kd8BIH5+z6ZZmeFMqKu14NIZXFS4lpZ5wVa0dBMzkU34qNbdfzIGnOrtJdvTdBjlt7RBpwjdnxUOm9+v/7OqzfPvu7Jfs7knMiDYNdd4VV1RYSvXngW413oMoWQrgt7Di6D4yEXwB6iCTjo4eRzhwRKqGVXL+MBbzxKbQlQ5T5GmQO26dHeOW2bomPaRP7an00X2C82dZIO4ri0HO++9yhAOptmyos5C36lj4TASVuyHJddwmojRySv1ma4DezRxcCZzY3MF3ZjUIIKpIX5NzNCkFbCFYLz/YJ8vSmNm2TZC4FhwSEPI3M9BwqSdVXzVTO7I0CNU12UPyTaW6exBCCKIp/yJqTm4Iuf/SWj8j1YQa6azRmpCY/bKq/giO6aZgIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lYTWFwc1N5bmOhARxPEQGfZIIBmzCCAZcEUwEApFg3dOexxalj8nUrzt4S8lvykjPlpatoQaZV5jXHutow2+O3Yevp/vk2zN3BZA8Z57Rrirw/eSC66GQAIdaXTkQrQT/4pB6OiKxPo0t6Zy0tBIH4khoiH57Ia4E8v4OSvsWDJhdW+VG62anIBrNq/VjNYQGe0tNceaXA1xDmmCtATLQzjiZTcHCGXn5whPdXaNBnpWJZr5S2v6zFHbja5DQKAoJN9tX6SiHsnkjFKblN4FzcCXZwtcatnvzn7quAhczRe9MHaS6Fjx3sll9v/fhoVv59f8+NBoQxZKsEJVbJ3JiR2K5Gd5ddwMhckZjL2ukh2zheY7nH71M/0h+5tlvQD2JGAfGjjsIco0wMFkZRcB7TcnklYVrk+pn/Qvz8GAWmrThOJpwoNmYSgaSm+R2M4cL0KLSvuqyHjDHk0dDjXgoVU6FcHhuItnoEIANqC2kCitrZ0vxiAMa50Yaz1I0N9N2USQCYVwQNhVHvAgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eVROZXdzoQEfTxEBoWSCAZ0wggGZBFMBAGy4sFitGVvqnRO1UBf1YHOgmtOogGtCo5Qh8as32kFgME1Ma/ZsIvrBV52bSWUtZcY5n+w5M/5X6IM/qNgNHlDLU9r3gcOu+tMI0YNTlFRAEwSB+rlDPBh4cqnNb3ksAMK9TNo6Q6cNk9Shn4ymCJQ95QCgtEhLdtZvClnWWyvcCKSuVym5aZqme+Ins3kVslJuMGBNA2mUHdLjaQ3utzlOt+hsmwFzLydzWzWwYaF7Eu1a46eJbiat/x3NWdb/AbOf1VNHGigJR/zMSzSZwBbt8CszkqqarzNAJV7K2XfR2gTik8+nFaW+OnjOxpFzcmH6Ba4qZNl32CIAeGU0TCbLQG8PYgMXEnzelBNFWlWJPpHH3AuNZJv5LeckFzxLXrg4U2Rd+i7NPX5sEY68tuzt4M2LQvzdm3FyhL6jECR8Ove9jjQYzZMcr5HciCoEIDdmYeHkrLi9fcNKFGeVS5E8QgvWT+Di28kluQXkh9VZAgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eV5CVEFubm91bmNlbWVudKEBIk8RAZ9kggGbMIIBlwRTAQC33vXBbax4Y3VXJS1T1Sjbp/jl76fAlKU8O5mcnuTxjDCs5+39psW+kv0RCLnmt1oVxZkwD02bWSrIOejWVJzDtgOE9cU4Wa5EuJRx8lxW76UEgfjR9gVrpLBZpLUDh+kCZQsccmm4baTJr4RKccdkXDobqiTf2iPSOL8ZFNblaxaGMzGftgzOI3tlS4ibFNs0VDK9MTKY5UFrHFHowPsGD7KJ7+CVMdB0VQWXGc6KYjMLoCw8JtabxnsENMSvqLu3h/W2MO54BPsmPtTF71bZ5DPH/4n0luME9IHg7EdF+qlFzsN4wwZNnL98BAo0PpUAxg92GdQBEbECTORR/yACYkPedz+/00adTpMu3FGMTK0pJCFTL0DrPJdgzErufK/np1M8wafGDy4g500iLEAMiHLlZ5X+9Syfexpswc/u3Jdycy0HHJrCOCwvXgQg9MwX13mTiRUvKFzP4S/Kx/R2jMigXh6DijHX8DLQKPYCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WU1hc3RlcktleaEBJU8RAdRkggHQMIIBzARTAQCXSlsz5M3/DLJ3LwoC2oHZFrvf2UpO6U65RLBuc2HfrTD4vA8PKYYeTPxv2pvwbwJDKxPKuaL5xdun1Zjw+lanFJ+vMrvyYYSPlos9UQddTSwEggEsr1H8WcrXyturoCCaMZmJ3omU/MG+8Y3oLvd6ZsF4xigAtHLFD8Nk6TjiPNw/fUth9I4Kj5DcwQqIhN0DbCnxyy6lhGH9TVuIWCyKf4p4aLtZyEHcZe+wTZeLK+qnvx7hXbSdWKGwaMd8AaAnep7smMkHF+zz5KiPF9ZEaUKuOOcVr7JjRXNeCoQsQo/5jZi+k+hLGrk1hZNsiQXb2aU9PyxsjSNbah1jVw3O48oJASmcr2jxp2o5Ih7pGr7C1RVFoC43Tg0JBkPyhV+PFN08arYReVtTH7mmjgr/IInMDjAE41HqfHNzwCwXSvJxKinVlpgw42syNCO1HX8m9Vmc2dlYFIO8HP/viB1E+6LSMbZ10qu5sjWlntOgQse13DlZ0ZFv4tWQOdxyGilwBCDBd3m4WFN5LsrHxCmPrmepRrZHDyx66Xo8SFTT8u9bpgIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lXU2hhcmluZ6EBKE8RAaBkggGcMIIBmARTAQAf+QXYIadowXsR5jmWz0V3lZK+6DKzqRB0vFdT367TGDD1mgeHWfq2X+XxONWfrwh+pwpS1uQYSBzCA+PujKQGcOVQnEQF1b8u1aV4XxenZjUEgfnNpqS2O0c7HiRtdY8s0o50X/Mt+Iacjfl+nNJnMsPsXV5qdtVogDFZw007/zdDuqKuNw47LyZTd01CYTr7HujAfUGnGT3sgldyovrZCby1t5Ab4rbDmKr5fsJljPHAqWjenDl2DO4FI+/uWVhyyOXOWJ7fNgMcUcOleG0kz+mAIZxnTHEkOLTA795Jzx5b7p5rtL0XzdpOIriUOI2X0OcNyjASldH2YHO9ZHJp/zJc79HbDBlsX1fjt5h94HuvYBmbKGehB212h63QDbsKnqOm68EW8uIupHZ0OFE6dj/YuyW6JjqpNyya1yg6WIc2NeRVdBZGLMMDZk4EIJ6KaY6ammcS59L24CtSbw9NnwBB9XVwCzMIwPy4mg32AgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eV5UVFlDYWxsSGlzdG9yeaEBK08RAaBkggGcMIIBmARTAQDFQfsYDNaI/OfOJ5wDDLVYGBdL6Nh3dY83ZtgyiXtkaDA4+baJ86jsz2zNb1yOX90jckzjX1x7bJaiD9NsUnZwBYql8HdawMTRzI+tQFgcgnoEgfkiYhn00ER0ys97XMqWsUsSfA7GdwkJ6ftGtB3f9u1ZIbjaxokjXRmTyVBJbT1gYnvGHxg1CnYg5YoHK2bF29H2MC52f/zPjDs1daqF+pimOvNWYbmfP1dPG3vkMHNujOqxi8pVBZ+ar8LsVdE8/3B7btIpeM02cyCTa7qKty6b61af05+0QQCzQRcZwjfRiqhMpyAux/IYaVOwbkL0/0J9/Ok62vNj6emsHFlKYhJwriIVPHo3zD6P1LeVB6pMu2G8EfoNNzrSkIIXg6fGBak/086b0iW0KCj1Ym+WUgYjlPVZPsLtKAynGxwu7zhoKsMRR3GMvxKk0EwEII2sxVqADT621CRjg0a1iqPj1vg8cdXtgVoAfJV32+h2AgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eV8QJFNlY3VyZUJhY2t1cGlDbG91ZElkZW50aXR5UHVibGljRGF0YU8RAJRhgZEwgY4CAQICAQEEIBc6U2wxA1UlBRj52pwa3f1dRNsNVPaSyAQExW/I6OQ9oWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEAgv7WXwyxFbes33Ax4zu1KKdqSn9zb8OnaQ7xnw5kHFICIAvXkgL8KsmCRAvJLitqsZ5OYwUobPfiL+NDUBAfNDLRAAgAFQA4AE4AYwB6AIkAngDBAM4A5gDnAPoBFRvnHAEcoBypHK4cwRzEHV0djB2RHaQdpx6mHrkevh7RHtQfbR92H3sfjh+RICggQSBGIFkgXCFaIWIhZyF6IX0ifCKbIqAisyK2I7QjviPDI9Yj2STXJOIk5yT6JP0llSW4Jb0l0CXTJmsmdiZ7Jo4mkScpJ0InRydaJ10oXShmKGsofiiBKRkpICklKTgpOynTKd0p4in1KfgqkCqcKqEqtCq3K08rZStqK30rgCx/LI0skiylLKgtQC1aLV8tci11LnMuei5/LpIulS8sLzgvPS9QL1Mv6y/yL/cwCjANMKUwqzCwMMMwxjFeMYIxhzGaMZ0ynDK8MsEy1DLXM9cz9zP8NA80EjSrNLQ0uTTMNM81zjXWNds17jXxNok2pTaqNr02wDe+N8U3yjfdN+A4dzh7OIA4kziWOS05Njk7OU45UTnoOe058joFOgg6oTq9OsI61TrYO9g7+Tv+PBE8FD0SPSE9Jj05PTw90z3dPeI99T34PsI+yz7QPuM+5j99P4w/kT+kP6dAP0BbQG5Ai0CUQJ5AzUDZQUhBUUFUQvlDGUMcRMFE1ETXRnxGgEaDSCdIMEgzSddJ20neS4FLikuNTTBNN006Tt1O6E7rUI9QmlCdUkFSS1JOU/JT/lQBVaVVs1W2V1pXfVeAWSRZMFkzWtda3lrhXIVcjFyPXjJeOV48X+Bf51/qYY9hmGGbYz5jRGNHZOtk9GT3Zppmn2aiaEdoVmhZafxqBmoJa+Fr6WvsbZBtn22ib0ZvbQAAAAAAAAICAAAAAAAAAS4AAAAAAAAAAAAAAAAAAHAF + + SecureBackupStableMetadata + + SecureBackupUsesRecoveryKey + + SecureBackupiCDPRecords + + + SecureBackupEscrowDate + 2020-01-31T03:07:40Z + SecureBackupRemainingAttempts + 10 + encodedMetadata + YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ== + label + com.apple.icdp.record + metadata + + BackupKeybagDigest + + yFGtyxY2ZzDt0j/26GkNSmrgVnY= + + ClientMetadata + + SecureBackupMetadataTimestamp + 2020-01-31 03:07:40 + SecureBackupNumericPassphraseLength + 6 + SecureBackupUsesComplexPassphrase + + SecureBackupUsesNumericPassphrase + + device_color + 1 + device_enclosure_color + 1 + device_mid + yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X + device_model + iPhone 8 Plus + device_model_class + iPhone + device_model_version + iPhone10,5 + device_name + iPhone + device_platform + 1 + + SecureBackupUsesMultipleiCSCs + + bottleID + DD5E3F9F-3702-4789-8ACF-2D28BC86A94C + bottleValid + valid + build + 18A214 + com.apple.securebackup.timestamp + 2020-01-31 03:07:40 + escrowedSPKI + + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC + Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b + 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj + Ug+fyh0c0xABOXt2Kdup7IYTGrzn + + peerInfo + + MIIErjGCBGEwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsM + D0FwcGxpY2F0aW9uRGF0ZQQYGBYyMDIwMDEzMDIyNDEy + Ni4yODAwNTdaMFUMEFB1YmxpY1NpZ25pbmdLZXkEQQTl + vn18gJwjGum8v3Chn9Yh5HM/VRLGuq6HAV4KyxlUm+w8 + uF80+32tY3/l9nKOmU61691beekwSWcfF+mDTGPrMFgM + D0FwcGxpY2F0aW9uVXNpZwRFMEMCIGOIXWe83FnflHu+ + yShdjivfTaPDFHvX+RYNgMy74iSnAh9OHeQzmDchZOi0 + 81lbhw/9rjEe8wEmozXX126RUOe/MHAMDURldmljZUdl + c3RhbHQxXzATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlP + U1ZlcnNpb24MBjE4QTIxNDAWDAxDb21wdXRlck5hbWUM + BmlQaG9uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJzaW9u + AgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEE + oLohYY3GpRSv20AT67jLJ1s2dKr+1bT8JoY23QkCeJgj + GNb+vutEQhLFjLPsENtNE7+NA7wgac0QAXLDO9H/LbpN + UP8DF1Q0NpFX4JiFZqG876jS8HEgR6VOOJzhJzUZMH8M + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEDRnS + sPQ/mTEl5dmMEYnQYhcm9hiPzBnQ0ghQzb70auYoPbCR + xjCoG7MCpbb+4JGM4L74OdbJZJbTtHeZ0JtCbqo93ZyI + fULWz131HsOyxowTSSI9yDiPAyXZz6nRnnvnMIIB+AwQ + VjJEaWN0aW9uYXJ5RGF0YQSCAeIxggHeMBAMDEVzY3Jv + d1JlY29yZAUAMBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw + OUFKOUw1MC0MCUJhY2t1cEtleQQgZlnxFs5NJO9YlR/4 + SDWH+e9rD/+Jf7lWWjMoTW9+n68wYAwMTWFjaGluZUlE + S2V5DFB5V25JOHZkTmc2RVdheWVXL0ZQNGNEWlJzZTNM + TW44UHhnL3gvc1B6WkpJUzVjczNSS280L3N0T1c0Nm5R + OThpTmxwU0hyblIwa2ZzYlIzWDCCARkMBVZpZXdz0YIB + DgwHQXBwbGVUVgwHSG9tZUtpdAwHUENTLUZERQwJUENT + LU5vdGVzDApQQ1MtQmFja3VwDApQQ1MtRXNjcm93DApQ + Q1MtUGhvdG9zDAtCYWNrdXBCYWdWMAwLUENTLVNoYXJp + bmcMDE5hbm9SZWdpc3RyeQwMUENTLUNsb3VkS2l0DAxQ + Q1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN + ZXNzYWdlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1pZ3Jh + dGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWRE + cml2ZQwQQWNjZXNzb3J5UGFpcmluZwwQQ29udGludWl0 + eVVubG9jawRHMEUCIES5okyKP4YMZqDjIGRMoLE83SYh + zjEyOvGPA0BoF6ViAiEAh6/dd57K+JBWmGXd4v4qGELp + vAeSjqcRUfdLtQj4DxI= + + serial + C39V209AJ9L5 + + osVersion + 18A214 + peerInfoSerialNumber + C39V209AJ9L5 + recordID + sNs6voV0N35D/T91SuGmJnGO29 + recordStatus + valid + silentAttemptAllowed + + + + SecureBackupiCloudDataProtectionEnabled + + + + +""" +#endif diff --git a/keychain/ot/tests/octagon/OctagonTests+ForwardCompatibility.swift b/keychain/ot/tests/octagon/OctagonTests+ForwardCompatibility.swift new file mode 100644 index 00000000..db845c38 --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonTests+ForwardCompatibility.swift @@ -0,0 +1,843 @@ +#if OCTAGON + +import Foundation + +class OctagonForwardCompatibilityTests: OctagonTestsBase { + func testApprovePeerWithNewPolicy() throws { + self.startCKAccountStatusMock() + let peer1ID = self.assertResetAndBecomeTrustedInDefaultContext() + + // Now, we'll approve a new peer with a new policy! First, make that new policy. + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } + XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") + let currentPolicy = currentPolicyOptional! + + let newPolicy = currentPolicy.clone(withVersionNumber: currentPolicy.version.versionNumber + 1)! + self.fakeCuttlefishServer.policyOverlay.append(newPolicy) + + let peer2ContextID = "asdf" + + // Assist the other client here: it'll likely already have the policy built-in + let fetchExpectation = self.expectation(description: "fetch callback occurs") + self.tphClient.fetchPolicyDocuments(withContainer: OTCKContainerName, + context: peer2ContextID, + versions: Set([newPolicy.version])) { _, error in + XCTAssertNil(error, "Should have no error") + fetchExpectation.fulfill() + } + self.wait(for: [fetchExpectation], timeout: 10) + + var peer2ID: String = "not initialized" + + let prepareExpectation = self.expectation(description: "prepare callback occurs") + let vouchExpectation = self.expectation(description: "vouch callback occurs") + let joinExpectation = self.expectation(description: "join callback occurs") + let serverJoinExpectation = self.expectation(description: "joinWithVoucher is called") + + self.tphClient.prepare(withContainer: OTCKContainerName, + context: peer2ContextID, + epoch: 1, + machineID: self.mockAuthKit2.currentMachineID, + bottleSalt: self.mockAuthKit2.altDSID!, + bottleID: "why-is-this-nonnil", + modelID: self.mockDeviceInfo.modelID(), + deviceName: "new-policy-peer", + serialNumber: "1234", + osVersion: "something", + policyVersion: newPolicy.version, + policySecrets: nil, + syncUserControllableViews: .UNKNOWN, + signingPrivKeyPersistentRef: nil, + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in + XCTAssertNil(error, "Should be no error preparing the second peer") + XCTAssertNotNil(peerID, "Should have a peerID") + peer2ID = peerID! + + XCTAssertNotNil(stableInfo, "Should have a stable info") + XCTAssertNotNil(stableInfoSig, "Should have a stable info signature") + + let newStableInfo = TPPeerStableInfo(data: stableInfo!, sig: stableInfoSig!) + XCTAssertNotNil(newStableInfo, "should be able to make a stableInfo info from protobuf") + + XCTAssertEqual(newStableInfo?.frozenPolicyVersion, frozenPolicyVersion, "Frozen policy version in new identity should match frozen policy version") + XCTAssertEqual(newStableInfo?.flexiblePolicyVersion, newPolicy.version, "Flexible policy version in new identity should match new policy version") + + self.tphClient.vouch(withContainer: self.cuttlefishContext.containerName, + context: self.cuttlefishContext.contextID, + peerID: peerID!, + permanentInfo: permanentInfo!, + permanentInfoSig: permanentInfoSig!, + stableInfo: stableInfo!, + stableInfoSig: stableInfoSig!, + ckksKeys: []) { voucher, voucherSig, error in + XCTAssertNil(error, "Should be no error vouching") + XCTAssertNotNil(voucher, "Should have a voucher") + XCTAssertNotNil(voucherSig, "Should have a voucher signature") + + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertEqual(peer2ID, joinRequest.peer.peerID, "joinWithVoucher request should be for peer 2") + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Frozen policy version in new identity should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicy.version, "Flexible policy version in new identity should match new policy version (as provided by new peer)") + + serverJoinExpectation.fulfill() + return nil + } + + self.tphClient.join(withContainer: OTCKContainerName, + context: peer2ContextID, + voucherData: voucher!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: [], + preapprovedKeys: []) { peerID, _, _, error in + XCTAssertNil(error, "Should be no error joining") + XCTAssertNotNil(peerID, "Should have a peerID") + joinExpectation.fulfill() + } + vouchExpectation.fulfill() + } + prepareExpectation.fulfill() + } + self.wait(for: [prepareExpectation, vouchExpectation, joinExpectation, serverJoinExpectation], timeout: 10) + + // Then, after the remote peer joins, the original peer should realize it trusts the new peer and update its own stableinfo to use the new policy + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + XCTAssertEqual(peer1ID, request.peerID, "updateTrust request should be for peer 1") + let newDynamicInfo = request.dynamicInfoAndSig.dynamicInfo() + XCTAssert(newDynamicInfo.includedPeerIDs.contains(peer2ID), "Peer1 should trust peer2") + + let newStableInfo = request.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicy.version, "Prevailing policy version in peer should match new policy version") + + updateTrustExpectation.fulfill() + return nil + } + + self.assertAllCKKSViewsUpload(tlkShares: 1) + + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.wait(for: [updateTrustExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + let policy = self.injectedManager!.policy + XCTAssertNotNil(policy, "asdf") + + XCTAssertEqual(policy?.version.versionNumber ?? 0, newPolicy.version.versionNumber, "CKKS policy should have new policy version") + + // Cause a TPH+securityd restart, and ensure that the new policy can be gotten from TPH + self.tphClient.containerMap.removeAllContainers() + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + + let refetchPolicyExpectation = self.expectation(description: "refetchPolicy callback occurs") + self.cuttlefishContext.rpcRefetchCKKSPolicy { error in + XCTAssertNil(error, "Should be no error refetching the policy") + refetchPolicyExpectation.fulfill() + } + self.wait(for: [refetchPolicyExpectation], timeout: 10) + + let dumpCallback = self.expectation(description: "dumpCallback callback occurs") + self.cuttlefishContext.cuttlefishXPCWrapper.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in + XCTAssertNil(error, "Should be no error getting dump") + XCTAssertNotNil(dump, "dump should not be nil") + let policies = dump!["registeredPolicyVersions"] as? [String] + XCTAssertNotNil(policies, "policies should not be nil") + + XCTAssert(policies?.contains("\(newPolicy.version.versionNumber), \(newPolicy.version.policyHash)") == true, "Registered policies should include newPolicy") + + dumpCallback.fulfill() + } + self.wait(for: [dumpCallback], timeout: 10) + + let statusExpectation = self.expectation(description: "status callback occurs") + self.cuttlefishContext.rpcStatus { result, error in + XCTAssertNil(error, "Should have no error getting status") + XCTAssertNotNil(result, "Should have some staatus") + statusExpectation.fulfill() + } + self.wait(for: [statusExpectation], timeout: 10) + } + + func testRejectVouchingForPeerWithUnknownNewPolicy() throws { + self.startCKAccountStatusMock() + _ = self.assertResetAndBecomeTrustedInDefaultContext() + + // Now, a new peer joins with a policy we can't fetch + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } + XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") + let currentPolicy = currentPolicyOptional! + + let newPolicy = currentPolicy.clone(withVersionNumber: currentPolicy.version.versionNumber + 1)! + + let peer2ContextID = "asdf" + + // Assist the other client here: it'll likely already have this built-in + self.fakeCuttlefishServer.policyOverlay.append(newPolicy) + + let fetchExpectation = self.expectation(description: "fetch callback occurs") + self.tphClient.fetchPolicyDocuments(withContainer: OTCKContainerName, + context: peer2ContextID, + versions: Set([newPolicy.version])) { _, error in + XCTAssertNil(error, "Should have no error") + fetchExpectation.fulfill() + } + self.wait(for: [fetchExpectation], timeout: 10) + + // Remove the policy, now that peer2 has it + self.fakeCuttlefishServer.policyOverlay.removeAll() + + let prepareExpectation = self.expectation(description: "prepare callback occurs") + let vouchExpectation = self.expectation(description: "vouch callback occurs") + + self.tphClient.prepare(withContainer: OTCKContainerName, + context: peer2ContextID, + epoch: 1, + machineID: self.mockAuthKit2.currentMachineID, + bottleSalt: self.mockAuthKit2.altDSID!, + bottleID: "why-is-this-nonnil", + modelID: self.mockDeviceInfo.modelID(), + deviceName: "new-policy-peer", + serialNumber: "1234", + osVersion: "something", + policyVersion: newPolicy.version, + policySecrets: nil, + syncUserControllableViews: .UNKNOWN, + signingPrivKeyPersistentRef: nil, + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in + XCTAssertNil(error, "Should be no error preparing the second peer") + XCTAssertNotNil(peerID, "Should have a peerID") + + XCTAssertNotNil(stableInfo, "Should have a stable info") + XCTAssertNotNil(stableInfoSig, "Should have a stable info signature") + + let newStableInfo = TPPeerStableInfo(data: stableInfo!, sig: stableInfoSig!) + XCTAssertNotNil(newStableInfo, "should be able to make a stableInfo info from protobuf") + + XCTAssertEqual(newStableInfo?.frozenPolicyVersion, frozenPolicyVersion, "Frozen policy version in new identity should match frozen policy version") + XCTAssertEqual(newStableInfo?.flexiblePolicyVersion, newPolicy.version, "Flexible policy version in new identity should match new policy version") + + self.tphClient.vouch(withContainer: self.cuttlefishContext.containerName, + context: self.cuttlefishContext.contextID, + peerID: peerID!, + permanentInfo: permanentInfo!, + permanentInfoSig: permanentInfoSig!, + stableInfo: stableInfo!, + stableInfoSig: stableInfoSig!, + ckksKeys: []) { voucher, voucherSig, error in + XCTAssertNotNil(error, "should be an error vouching for a peer with an unknown policy") + XCTAssertNil(voucher, "Should have no voucher") + XCTAssertNil(voucherSig, "Should have no voucher signature") + + vouchExpectation.fulfill() + } + prepareExpectation.fulfill() + } + self.wait(for: [prepareExpectation, vouchExpectation], timeout: 10) + } + + func testIgnoreAlreadyJoinedPeerWithUnknownNewPolicy() throws { + self.startCKAccountStatusMock() + let peer1ID = self.assertResetAndBecomeTrustedInDefaultContext() + + // Now, a new peer joins with a policy we can't fetch + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } + XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") + let currentPolicy = currentPolicyOptional! + + let newPolicy = currentPolicy.clone(withVersionNumber: currentPolicy.version.versionNumber + 1)! + + let peer2ContextID = "asdf" + + // Assist the other client here: it'll likely already have this built-in + self.fakeCuttlefishServer.policyOverlay.append(newPolicy) + + let fetchExpectation = self.expectation(description: "fetch callback occurs") + self.tphClient.fetchPolicyDocuments(withContainer: OTCKContainerName, + context: peer2ContextID, + versions: Set([newPolicy.version])) { _, error in + XCTAssertNil(error, "Should have no error") + fetchExpectation.fulfill() + } + self.wait(for: [fetchExpectation], timeout: 10) + + // Remove the policy, now that peer2 has it + self.fakeCuttlefishServer.policyOverlay.removeAll() + + let joiningContext = self.makeInitiatorContext(contextID: peer2ContextID, authKitAdapter: self.mockAuthKit2) + joiningContext.policyOverride = newPolicy.version + + let serverJoinExpectation = self.expectation(description: "peer2 joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Frozen policy version in new identity should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicy.version, "Flexible policy version in new identity should match new policy version (as provided by new peer)") + + serverJoinExpectation.fulfill() + return nil + } + + _ = self.assertJoinViaEscrowRecovery(joiningContext: joiningContext, sponsor: self.cuttlefishContext) + self.wait(for: [serverJoinExpectation], timeout: 10) + + // Then, after the remote peer joins, the original peer should ignore it entirely: peer1 has no idea what this new policy is about + // That means it won't update its trust in response to the join + self.fakeCuttlefishServer.updateListener = { request in + XCTFail("Expected no updateTrust after peer1 joins") + XCTAssertEqual(peer1ID, request.peerID, "updateTrust request should be for peer 1") + /* + * But, if it did update its trust, here's what we would expect: + let newDynamicInfo = request.dynamicInfoAndSig.dynamicInfo() + XCTAssertFalse(newDynamicInfo.includedPeerIDs.contains(peer2ID), "Peer1 should not trust peer2") + XCTAssertFalse(newDynamicInfo.excludedPeerIDs.contains(peer2ID), "Peer1 should not distrust peer2") + + let newStableInfo = request.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, prevailingPolicyVersion, "Prevailing policy version in peer should match current prevailing policy version") + + updateTrustExpectation.fulfill() + */ + return nil + } + + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + } + + func createOctagonAndCKKSUsingFuturePolicy() throws -> (TPPolicyDocument, CKRecordZone.ID) { + // We want to set up a world with a peer, in Octagon, with TLKs for zones that don't even exist in our current policy. + // First, make a new policy. + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } + XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") + let currentPolicyDocument = currentPolicyOptional! + + let futureViewName = "FutureView" + let futureViewMapping = TPPBPolicyKeyViewMapping()! + + let futureViewZoneID = CKRecordZone.ID(zoneName: futureViewName) + self.ckksZones.add(futureViewZoneID) + self.injectedManager!.setSyncingViewsAllowList(Set((self.intendedCKKSZones.union([futureViewZoneID])).map { $0.zoneName })) + + self.zones![futureViewZoneID] = FakeCKZone(zone: futureViewZoneID) + + XCTAssertFalse(currentPolicyDocument.categoriesByView.keys.contains(futureViewName), "Current policy should not include future view") + + let newPolicyDocument = try TPPolicyDocument(internalVersion: currentPolicyDocument.version.versionNumber + 1, + modelToCategory: currentPolicyDocument.modelToCategory, + categoriesByView: currentPolicyDocument.categoriesByView.merging([futureViewName: Set(["watch", "full", "tv"])]) { _, new in new }, + introducersByCategory: currentPolicyDocument.introducersByCategory, + redactions: [:], + keyViewMapping: [futureViewMapping] + currentPolicyDocument.keyViewMapping, + userControllableViewList: currentPolicyDocument.userControllableViewList, + piggybackViews: currentPolicyDocument.piggybackViews, + priorityViews: currentPolicyDocument.priorityViews, + hashAlgo: .SHA256) + + self.fakeCuttlefishServer.policyOverlay.append(newPolicyDocument) + + return (newPolicyDocument, futureViewZoneID) + } + + func createFuturePolicyMovingAllItemsToLimitedPeers() throws -> (TPPolicyDocument) { + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } + XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") + let currentPolicyDocument = currentPolicyOptional! + + let limitedPeersViewMapping = TPPBPolicyKeyViewMapping(view: "LimitedPeersAllowed", + matchingRule: TPDictionaryMatchingRule.trueMatch()) + + let newPolicyDocument = try TPPolicyDocument(internalVersion: currentPolicyDocument.version.versionNumber + 1, + modelToCategory: currentPolicyDocument.modelToCategory, + categoriesByView: currentPolicyDocument.categoriesByView, + introducersByCategory: currentPolicyDocument.introducersByCategory, + redactions: [:], + keyViewMapping: [limitedPeersViewMapping] + currentPolicyDocument.keyViewMapping, + userControllableViewList: currentPolicyDocument.userControllableViewList, + piggybackViews: currentPolicyDocument.piggybackViews, + priorityViews: currentPolicyDocument.priorityViews, + hashAlgo: .SHA256) + + self.fakeCuttlefishServer.policyOverlay.append(newPolicyDocument) + + return newPolicyDocument + } + + func testRestoreBottledPeerUsingFuturePolicy() throws { + let (newPolicyDocument, futureViewZoneID) = try self.createOctagonAndCKKSUsingFuturePolicy() + + let futurePeerContext = self.makeInitiatorContext(contextID: "futurePeer") + futurePeerContext.policyOverride = newPolicyDocument.version + + self.startCKAccountStatusMock() + let futurePeerID = self.assertResetAndBecomeTrusted(context: futurePeerContext) + + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: futurePeerContext) + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID)) + + // Now, our peer (with no inbuilt knowledge of newPolicyDocument) joins via escrow recovery. + + let serverJoinExpectation = self.expectation(description: "peer1 joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + + serverJoinExpectation.fulfill() + return nil + } + + let peerID = self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: futurePeerContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.policy?.version, newPolicyDocument.version, "CKKS should be configured with new policy") + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + self.verifyDatabaseMocks() + + self.wait(for: [serverJoinExpectation], timeout: 10) + + // And the joined peer should have recovered the TLK, and uploaded itself a share + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID)) + } + + func testPairingJoinUsingFuturePolicy() throws { + let (newPolicyDocument, futureViewZoneID) = try self.createOctagonAndCKKSUsingFuturePolicy() + + let futurePeerContext = self.makeInitiatorContext(contextID: "futurePeer") + futurePeerContext.policyOverride = newPolicyDocument.version + + self.startCKAccountStatusMock() + let futurePeerID = self.assertResetAndBecomeTrusted(context: futurePeerContext) + + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: futurePeerContext) + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID)) + + // Now, our peer (with no inbuilt knowledge of newPolicyDocument) joins via pairing + // It should be able to recover the FutureView TLK + self.assertAllCKKSViewsUpload(tlkShares: 1) + + let serverJoinExpectation = self.expectation(description: "peer1 joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + + serverJoinExpectation.fulfill() + return nil + } + + let peerID = self.assertJoinViaProximitySetup(joiningContext: self.cuttlefishContext, sponsor: futurePeerContext) + + // And then fake like the other peer uploaded TLKShares after the join succeeded (it would normally happen during, but that's okay) + try self.putAllTLKSharesInCloudKit(to: self.cuttlefishContext, from: futurePeerContext) + self.injectedManager!.zoneChangeFetcher.notifyZoneChange(nil) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.policy?.version, newPolicyDocument.version, "CKKS should be configured with new policy") + self.verifyDatabaseMocks() + + self.wait(for: [serverJoinExpectation], timeout: 10) + + // And the joined peer should have recovered the TLK, and uploaded itself a share + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID)) + } + + func testRecoveryKeyJoinUsingFuturePolicy() throws { + let (newPolicyDocument, futureViewZoneID) = try self.createOctagonAndCKKSUsingFuturePolicy() + + let futurePeerContext = self.makeInitiatorContext(contextID: "futurePeer") + futurePeerContext.policyOverride = newPolicyDocument.version + + self.startCKAccountStatusMock() + let futurePeerID = self.assertResetAndBecomeTrusted(context: futurePeerContext) + + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: futurePeerContext) + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID)) + + // Create the recovery key + let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String + XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") + + self.manager.setSOSEnabledForPlatformFlag(true) + + let createRecoveryExpectation = self.expectation(description: "createRecoveryExpectation returns") + self.manager.createRecoveryKey(OTCKContainerName, contextID: futurePeerContext.contextID, recoveryKey: recoveryKey) { error in + XCTAssertNil(error, "error should be nil") + createRecoveryExpectation.fulfill() + } + self.wait(for: [createRecoveryExpectation], timeout: 10) + + // Setting the RK will make TLKShares to the RK, so help that out too + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: self.mockAuthKit.altDSID!) + + // Now, our peer (with no inbuilt knowledge of newPolicyDocument) joins via RecoveryKey + let serverJoinExpectation = self.expectation(description: "peer1 joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + + serverJoinExpectation.fulfill() + return nil + } + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKey callback occurs") + self.cuttlefishContext.join(withRecoveryKey: recoveryKey) { error in + XCTAssertNil(error, "error should be nil") + joinWithRecoveryKeyExpectation.fulfill() + } + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.policy?.version, newPolicyDocument.version, "CKKS should be configured with new policy") + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + + // And double-check that the future view is covered + let accountMetadata = try self.cuttlefishContext.accountMetadataStore.loadOrCreateAccountMetadata() + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: accountMetadata.peerID, senderPeerID: accountMetadata.peerID, zoneID: futureViewZoneID)) + self.verifyDatabaseMocks() + + self.wait(for: [serverJoinExpectation], timeout: 10) + } + + func testPreapprovedJoinUsingFuturePolicy() throws { + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: self.createSOSPeer(peerID: "peer2ID"), trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + print(peer2mockSOS.allPeers()) + self.mockSOSAdapter.trustedPeers.add(peer2mockSOS.selfPeer) + + let futurePeerContext = self.manager.context(forContainerName: OTCKContainerName, + contextID: "futurePeer", + sosAdapter: peer2mockSOS, + authKitAdapter: self.mockAuthKit2, + lockStateTracker: self.lockStateTracker, + accountStateTracker: self.accountStateTracker, + deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iPhone9,1", deviceName: "test-SOS-iphone", serialNumber: "456", osVersion: "iOS (fake version)")) + + let (newPolicyDocument, _) = try self.createOctagonAndCKKSUsingFuturePolicy() + futurePeerContext.policyOverride = newPolicyDocument.version + + let serverEstablishExpectation = self.expectation(description: "futurePeer establishes successfully") + self.fakeCuttlefishServer.establishListener = { establishRequest in + XCTAssertTrue(establishRequest.peer.hasStableInfoAndSig, "Establishing peer should have a stable info") + let newStableInfo = establishRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + serverEstablishExpectation.fulfill() + return nil + } + + // Setup is complete. Join using a new peer + self.startCKAccountStatusMock() + futurePeerContext.startOctagonStateMachine() + self.assertEnters(context: futurePeerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.wait(for: [serverEstablishExpectation], timeout: 10) + + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: futurePeerContext) + + // Now, the default peer joins via SOS preapproval + let serverJoinExpectation = self.expectation(description: "peer1 joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + serverJoinExpectation.fulfill() + return nil + } + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.wait(for: [serverJoinExpectation], timeout: 10) + + // But, since we're not mocking the remote peer sharing the TLKs, ckks should get stuck + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.policy?.version, newPolicyDocument.version, "CKKS should be configured with new policy") + self.verifyDatabaseMocks() + } + + func testRespondToFuturePoliciesInPeerUpdates() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + // Now, another peer comes along and joins via BP recovery, using a new policy + let (newPolicyDocument, futureZoneID) = try self.createOctagonAndCKKSUsingFuturePolicy() + + let futurePeerContext = self.makeInitiatorContext(contextID: "futurePeer") + futurePeerContext.policyOverride = newPolicyDocument.version + + let serverJoinExpectation = self.expectation(description: "futurePeer joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + serverJoinExpectation.fulfill() + return nil + } + + let peer2ID = self.assertJoinViaEscrowRecovery(joiningContext: futurePeerContext, sponsor: self.cuttlefishContext) + self.wait(for: [serverJoinExpectation], timeout: 10) + + // And the other peer creates the new View, and shares it with us + self.putFakeKeyHierarchiesInCloudKit { zoneID in + return zoneID.zoneName == futureZoneID.zoneName + } + + // The remote peer uploads tlkshares for itself, because it received them during its escrow recovery + try self.putSelfTLKSharesInCloudKit(context: futurePeerContext) //, filter) + try self.putTLKShareInCloudKit(to: self.cuttlefishContext, from: futurePeerContext, zoneID: futureZoneID) + + // First, tell all existing CKKS views to fetch, and wait for it to do so. This will ensure that it receives the tlkshares uploaded above, and + // won't immediately upload new ones when the peer list changes. + self.silentFetchesAllowed = false + self.expectCKFetch() + try XCTUnwrap(self.injectedManager).zoneChangeFetcher.notifyZoneChange(nil) + self.verifyDatabaseMocks() + self.silentFetchesAllowed = true + + // Now, tell our first peer about the new changes. It should trust the new peer, and update its policy + // It should also upload itself a TLKShare for the future view + self.assertAllCKKSViewsUpload(tlkShares: 1, filter: { $0.zoneName == futureZoneID.zoneName }) + + let updateTrustExpectation = self.expectation(description: "updateTrustExpectation successfully") + self.fakeCuttlefishServer.updateListener = { + request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + + let newDynamicInfo = request.dynamicInfoAndSig.dynamicInfo() + XCTAssert(newDynamicInfo.includedPeerIDs.contains(peer2ID), "Peer1 should trust peer2") + + updateTrustExpectation.fulfill() + return nil + } + + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.wait(for: [updateTrustExpectation], timeout: 10) + + // Once we've uploaded the TLKShare for the future view, then we're fairly sure the view object has been created locally. + self.verifyDatabaseMocks() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + } + + func testRecoverFromPeerUsingOldPolicy() throws { + self.startCKAccountStatusMock() + + let pastPeerContext = self.makeInitiatorContext(contextID: "pastPeer") + + let policyV6Document = builtInPolicyDocuments().filter { $0.version.versionNumber == 6 }.first! + pastPeerContext.policyOverride = policyV6Document.version + + let serverEstablishExpectation = self.expectation(description: "futurePeer establishes successfully") + self.fakeCuttlefishServer.establishListener = { establishRequest in + XCTAssertTrue(establishRequest.peer.hasStableInfoAndSig, "Establishing peer should have a stable info") + let newStableInfo = establishRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Frozen policy version in peer should be frozen version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, policyV6Document.version, "Prevailing policy version in peer should be v6") + serverEstablishExpectation.fulfill() + return nil + } + + self.assertResetAndBecomeTrusted(context: pastPeerContext) + self.wait(for: [serverEstablishExpectation], timeout: 10) + + self.putFakeKeyHierarchiesInCloudKit(filter: { zoneID in policyV6Document.keyViewMapping.contains { $0.view == zoneID.zoneName } }) + try self.putSelfTLKSharesInCloudKit(context: pastPeerContext, filter: { zoneID in policyV6Document.keyViewMapping.contains { $0.view == zoneID.zoneName } }) + + // Ensure that CKKS will bring up the Backstop view + self.injectedManager!.setSyncingViewsAllowList(Set(["Backstop"] + self.intendedCKKSZones!.map { $0.zoneName })) + + // Now, Octagon comes along and recovers the bottle. + + // Right now, Octagon will join and then immediately updateTrust to upload the new set of TLKs + // This probably can be reworked for performance. + let serverJoinExpectation = self.expectation(description: "joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertEqual(joinRequest.viewKeys.count, 0, "Should have zero sets of new viewkeys during join") + serverJoinExpectation.fulfill() + return nil + } + + // TVs do not participate in the backstop view, and so won't upload anything + #if !os(tvOS) + let serverUpdateTrustExpectation = self.expectation(description: "updateTrust successfully") + self.fakeCuttlefishServer.updateListener = { updateRequest in + XCTAssertEqual(updateRequest.viewKeys.count, 1, "Should have one new set of viewkeys during update") + serverUpdateTrustExpectation.fulfill() + return nil + } + #endif + + self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: pastPeerContext) + self.wait(for: [serverJoinExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + #if !os(tvOS) + self.wait(for: [serverUpdateTrustExpectation], timeout: 10) + #endif + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testRecoverFromPeerUsingExtremelyOldPolicy() throws { + self.startCKAccountStatusMock() + + let pastPeerContext = self.makeInitiatorContext(contextID: "pastPeer") + + let policyV1Document = builtInPolicyDocuments().filter { $0.version.versionNumber == 1 }.first! + pastPeerContext.policyOverride = policyV1Document.version + + let serverEstablishExpectation = self.expectation(description: "futurePeer establishes successfully") + self.fakeCuttlefishServer.establishListener = { establishRequest in + XCTAssertTrue(establishRequest.peer.hasStableInfoAndSig, "Establishing peer should have a stable info") + let newStableInfo = establishRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertNil(newStableInfo.flexiblePolicyVersion, "Peer should be from before prevailing policy version were set") + XCTAssertEqual(newStableInfo.frozenPolicyVersion, policyV1Document.version, "Frozen policy version in peer should be v1 - a very old peer") + serverEstablishExpectation.fulfill() + return nil + } + + self.assertResetAndBecomeTrusted(context: pastPeerContext) + self.wait(for: [serverEstablishExpectation], timeout: 10) + + // This filtering should only add Manatee + self.putFakeKeyHierarchiesInCloudKit(filter: { zoneID in policyV1Document.keyViewMapping.contains { $0.view == zoneID.zoneName } }) + try self.putSelfTLKSharesInCloudKit(context: pastPeerContext, filter: { zoneID in policyV1Document.keyViewMapping.contains { $0.view == zoneID.zoneName } }) + + // Ensure that CKKS will bring up the Backstop view, and allow it to bring up PCSEscrow if that's what it wants (it shouldn't) + self.injectedManager!.setSyncingViewsAllowList(Set(["Backstop", "PCSEscrow"] + self.intendedCKKSZones!.map { $0.zoneName })) + + // Now, Octagon comes along and recovers the bottle. + + // Right now, Octagon will join and then immediately updateTrust to upload the new set of TLKs + // This probably can be reworked for performance. + let serverJoinExpectation = self.expectation(description: "joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + // Since Octagon ignores the other peer's policy, it will create the TLKs at establish time + let zones = Set(joinRequest.viewKeys.map { $0.view }) + + #if !os(tvOS) + XCTAssertEqual(zones.count, 3, "Should have three sets of new viewkeys during join") + XCTAssertTrue(zones.contains("Manatee"), "Should have a TLK for the manatee view") + #else + XCTAssertEqual(zones.count, 1, "Should have one set of new viewkeys during join") + #endif + XCTAssertTrue(zones.contains("LimitedPeersAllowed"), "Should have a TLK for the LimitedPeersAllowed view") + + XCTAssertFalse(zones.contains("PCSEscrow"), "Should not have a TLK for the PCSEscrow view") + + let joiningPeer = joinRequest.peer.stableInfoAndSig.stableInfo() + XCTAssertEqual(joiningPeer.flexiblePolicyVersion, prevailingPolicyVersion, "Our current policy should be the prevailing policy - the sponsor peer should be ignored") + XCTAssertEqual(joiningPeer.frozenPolicyVersion, frozenPolicyVersion, "Frozen policy version in peer should be the real policy") + + serverJoinExpectation.fulfill() + return nil + } + + self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: pastPeerContext) + self.wait(for: [serverJoinExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testCKKSRequestPolicyCheck() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + let newPolicyDocument = try self.createFuturePolicyMovingAllItemsToLimitedPeers() + + let futurePeerContext = self.makeInitiatorContext(contextID: "futurePeer") + futurePeerContext.policyOverride = newPolicyDocument.version + + let serverJoinExpectation = self.expectation(description: "futurePeer joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + serverJoinExpectation.fulfill() + return nil + } + + self.assertJoinViaEscrowRecovery(joiningContext: futurePeerContext, sponsor: self.cuttlefishContext) + self.wait(for: [serverJoinExpectation], timeout: 10) + + // And the peer adds a new item to the LimitedPeersAllowed view, but one that didn't used to go there + var item = self.fakeRecordDictionary("account0", zoneID: self.limitedPeersAllowedZoneID) + item["vwht"] = "asdf" + + self.addItem(toCloudKitZone: item, recordName: "7B598D31-F9C5-481E-98AC-5A507ACB2D85", zoneID: self.limitedPeersAllowedZoneID) + + let limitedPeersView = self.injectedManager?.findView("LimitedPeersAllowed") + XCTAssertNotNil(limitedPeersView, "Should have a LimitedPeersAllowed view") + + // This CKKS notification should cause Octagon to update trust, and then fill CKKS in (which should then accept the item) + + let updateExpectation = self.expectation(description: "peer updates successfully") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + + updateExpectation.fulfill() + return nil + } + + // CKKS will also upload TLKShares for the new peer + self.assertAllCKKSViewsUpload(tlkShares: 1) + + try XCTUnwrap(self.injectedManager).zoneChangeFetcher.notifyZoneChange(nil) + limitedPeersView!.waitForFetchAndIncomingQueueProcessing() + + // And wait for the updateTrust to occur, then for Octagon to return to ready, then for any incoming queue processing in ckks + self.wait(for: [updateExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + limitedPeersView!.waitForOperations(of: CKKSIncomingQueueOperation.self) + self.verifyDatabaseMocks() + + // The item should be found + self.findGenericPassword("account0", expecting: errSecSuccess) + } +} + +#endif diff --git a/keychain/ot/tests/octagon/OctagonTests+HealthCheck.swift b/keychain/ot/tests/octagon/OctagonTests+HealthCheck.swift index e1fd51bd..40f389be 100644 --- a/keychain/ot/tests/octagon/OctagonTests+HealthCheck.swift +++ b/keychain/ot/tests/octagon/OctagonTests+HealthCheck.swift @@ -1,7 +1,6 @@ #if OCTAGON class OctagonHealthCheckTests: OctagonTestsBase { - func testHealthCheckAllTrusted() throws { let containerName = OTCKContainerName let contextName = OTDefaultContext @@ -9,6 +8,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -39,10 +39,9 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.wait(for: [healthCheckCallback], timeout: 10) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") dumpCallback.fulfill() } @@ -56,6 +55,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") @@ -69,16 +69,16 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) #if os(tvOS) - XCTAssertEqual(self.cuttlefishContext.postedRepairCFU, false, "Should not have posted a CFU on aTV") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should not have posted a CFU on aTV") #else - XCTAssertEqual(self.cuttlefishContext.postedRepairCFU, true, "Should have posted a CFU (due to being untrusted)") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should have posted a CFU (due to being untrusted)") #endif self.verifyDatabaseMocks() self.assertEnters(context: cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) // Reset flag for remainder of test - self.cuttlefishContext.setPostedBool(false) + self.cuttlefishContext.followupHandler.clearAllPostedFlags() // Set the "have I attempted to join" bit; TVs should still not CFU, but other devices should try! self.cuttlefishContext.accountMetadataStore.persistOctagonJoinAttempt(.ATTEMPTED) @@ -91,9 +91,9 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.wait(for: [healthCheckCallback2], timeout: 10) #if os(tvOS) - XCTAssertEqual(self.cuttlefishContext.postedRepairCFU, false, "Should not have posted a CFU on aTV") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should not have posted a CFU on aTV") #else - XCTAssertEqual(self.cuttlefishContext.postedRepairCFU, true, "Should have posted a CFU") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should have posted a CFU") #endif } @@ -104,6 +104,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -140,14 +141,13 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: cuttlefishContext) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 1, "should be 1 peer ids") dumpCallback.fulfill() @@ -165,6 +165,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -210,19 +211,20 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.wait(for: [healthCheckCallback], timeout: 10) #if !os(tvOS) - XCTAssertEqual(cuttlefishContext.postedRepairCFU, true, "Should have posted a CFU") + XCTAssertTrue(cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should have posted a CFU") #else - XCTAssertFalse(cuttlefishContext.postedRepairCFU, "aTV should not have posted a CFU, as there's no iphone to recover from") + XCTAssertFalse(cuttlefishContext.followupHandler.hasPosted(.stateRepair), "aTV should not have posted a CFU, as there's no iphone to recover from") #endif } - func responseTestsSetup() throws -> (OTCuttlefishContext, String) { + func responseTestsSetup(expectedState: String) throws -> (OTCuttlefishContext, String) { let containerName = OTCKContainerName let contextName = OTDefaultContext self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -249,6 +251,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { // Reset any CFUs we've done so far self.otFollowUpController.postedFollowUp = false + self.cuttlefishContext.followupHandler.clearAllPostedFlags() let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") self.manager.healthCheck(containerName, context: contextName, skipRateLimitingCheck: false) { error in @@ -258,57 +261,55 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.wait(for: [healthCheckCallback], timeout: 10) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") dumpCallback.fulfill() } self.wait(for: [dumpCallback], timeout: 10) self.verifyDatabaseMocks() - self.assertEnters(context: cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: cuttlefishContext, state: expectedState, within: 10 * NSEC_PER_SEC) return (cuttlefishContext, originalCliqueIdentifier!) } func testCuttlefishResponseNoAction() throws { self.fakeCuttlefishServer.returnNoActionResponse = true - let (cuttlefishContext, _) = try responseTestsSetup() + let (cuttlefishContext, _) = try responseTestsSetup(expectedState: OctagonStateReady) XCTAssertFalse(self.otFollowUpController.postedFollowUp, "should not have posted a CFU") - XCTAssertEqual(cuttlefishContext.postedRepairCFU, false, "should not have posted a CFU") + XCTAssertFalse(cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should not have posted a Repair CFU") } func testCuttlefishResponseRepairAccount() throws { self.fakeCuttlefishServer.returnRepairAccountResponse = true - let (_, _) = try responseTestsSetup() - XCTAssertTrue(self.otFollowUpController.postedFollowUp, "should have posted a CFU") + let (_, _) = try responseTestsSetup(expectedState: OctagonStateReady) + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should have posted a Repair CFU") } func testCuttlefishResponseRepairEscrow() throws { self.fakeCuttlefishServer.returnRepairEscrowResponse = true OTMockSecEscrowRequest.self.populateStatuses = false - let (cuttlefishContext, _) = try responseTestsSetup() + let (cuttlefishContext, _) = try responseTestsSetup(expectedState: OctagonStateReady) XCTAssertTrue(self.otFollowUpController.postedFollowUp, "should have posted a CFU") - XCTAssertEqual(cuttlefishContext.postedEscrowRepairCFU, true, "should have posted an escrow CFU") + XCTAssertTrue(cuttlefishContext.followupHandler.hasPosted(.confirmExistingSecret), "should have posted an escrow CFU") } func testCuttlefishResponseResetOctagon() throws { let contextName = OTDefaultContext let containerName = OTCKContainerName self.fakeCuttlefishServer.returnResetOctagonResponse = true - let (cuttlefishContext, cliqueIdentifier) = try responseTestsSetup() + let (cuttlefishContext, cliqueIdentifier) = try responseTestsSetup(expectedState: OctagonStateReady) assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() var newCliqueIdentifier: String? let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] newCliqueIdentifier = egoSelf!["peerID"]! as? String XCTAssertNotNil(egoSelf, "egoSelf should not be nil") dumpCallback.fulfill() @@ -321,12 +322,22 @@ class OctagonHealthCheckTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } + func testCuttlefishResponseLeaveTrust() throws { + OctagonSetSOSFeatureEnabled(false) + + self.fakeCuttlefishServer.returnLeaveTrustResponse = true + let (_, _) = try responseTestsSetup(expectedState: OctagonStateUntrusted) + + self.verifyDatabaseMocks() + assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) + } + func testCuttlefishResponseError() throws { self.fakeCuttlefishServer.returnRepairErrorResponse = FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired) - let (cuttlefishContext, _) = try responseTestsSetup() - XCTAssertEqual(cuttlefishContext.postedRepairCFU, false, "should not have posted an account repair CFU") - XCTAssertEqual(cuttlefishContext.postedEscrowRepairCFU, false, "should not have posted an escrow repair CFU") + let (cuttlefishContext, _) = try responseTestsSetup(expectedState: OctagonStateReady) + XCTAssertFalse(cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should not have posted an account repair CFU") + XCTAssertFalse(cuttlefishContext.followupHandler.hasPosted(.confirmExistingSecret), "should not have posted an escrow repair CFU") } func testHealthCheckBeforeStateMachineStarts() throws { @@ -350,6 +361,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -378,10 +390,9 @@ class OctagonHealthCheckTests: OctagonTestsBase { } let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") dumpCallback.fulfill() } @@ -395,6 +406,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { let containerName = OTCKContainerName let contextName = OTDefaultContext + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() @@ -430,10 +442,9 @@ class OctagonHealthCheckTests: OctagonTestsBase { } let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") dumpCallback.fulfill() } @@ -450,6 +461,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") @@ -481,10 +493,9 @@ class OctagonHealthCheckTests: OctagonTestsBase { } let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") dumpCallback.fulfill() } @@ -523,14 +534,67 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) } - func testHealthCheckWhenLocked() throws { + func testHealthCheckWaitingForCDP() throws { + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + + self.cuttlefishContext.stateMachine.setWatcherTimeout(2 * NSEC_PER_SEC) + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(OTCKContainerName, context: self.cuttlefishContext.contextID, skipRateLimitingCheck: false) { error in + XCTAssertNil(error, "error should be nil") + healthCheckCallback.fulfill() + } + self.wait(for: [healthCheckCallback], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + } + + func testHealthCheckRecoversFromWrongWaitingForCDP() throws { + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + + // Now, another client creates the circle, but we miss the push + let remote = self.makeInitiatorContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) + + // Now, does the health check get us into Untrusted? + self.cuttlefishContext.stateMachine.setWatcherTimeout(2 * NSEC_PER_SEC) + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(OTCKContainerName, context: self.cuttlefishContext.contextID, skipRateLimitingCheck: false) { error in + XCTAssertNil(error, "error should be nil") + healthCheckCallback.fulfill() + } + self.wait(for: [healthCheckCallback], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + #if !os(tvOS) + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Octagon should have posted a repair CFU after the health check") + #else + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "posted should be false on tvOS; there aren't any iphones around to repair it") + #endif + } + + func testHealthCheckWhenLocked() throws { let containerName = OTCKContainerName let contextName = OTDefaultContext self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -564,10 +628,9 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.wait(for: [healthCheckCallback], timeout: 10) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") dumpCallback.fulfill() } @@ -577,6 +640,37 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) } + func testHealthCheckBeforeClassCUnlock() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + // Now, the device restarts, and isn't unlocked immediately. + self.aksLockState = true + SecMockAKS.lockClassA_C() + self.lockStateTracker.recheck() + + do { + _ = try OTAccountMetadataClassC.loadFromKeychain(forContainer: self.cuttlefishContext.containerName, contextID: self.cuttlefishContext.contextID) + XCTFail("shouldn't have been able to load the class c metadata") + } catch { + // We expected this error; fall through + } + + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForClassCUnlock, within: 10 * NSEC_PER_SEC) + + // A health check should fail, and leave us waiting for the initial unlock + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID, skipRateLimitingCheck: false) { error in + XCTAssertNotNil(error, "error should be present") + healthCheckCallback.fulfill() + } + self.wait(for: [healthCheckCallback], timeout: 20) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForClassCUnlock, within: 10 * NSEC_PER_SEC) + } + func testLastHealthCheckPersistedTime() throws { let containerName = OTCKContainerName let contextName = OTDefaultContext @@ -584,6 +678,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -623,10 +718,9 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.wait(for: [healthCheckCallback], timeout: 10) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") dumpCallback.fulfill() } @@ -660,7 +754,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { //update the last health check to something way in the past do { let state = try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext) - state.lastHealthCheckup = state.lastHealthCheckup - 172800000 /* 2 days of seconds * 1000*/ + state.lastHealthCheckup -= 172800000 /* 2 days of seconds * 1000*/ healthCheckMinusTwoDays = state.lastHealthCheckup XCTAssertNoThrow(try state.saveToKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext), "saving to the keychain should work") } catch { @@ -705,6 +799,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { bottlerContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -729,13 +824,14 @@ class OctagonHealthCheckTests: OctagonTestsBase { XCTAssertNotNil(entropy, "entropy should not be nil") // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: bottlerContext, zoneID: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) let bottle = self.fakeCuttlefishServer.state.bottles[0] self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) // cheat: a bottle restore can only succeed after a fetch occurs @@ -766,7 +862,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { } let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNotNil(error, "error should not be nil") joinWithBottleExpectation.fulfill() } @@ -783,8 +879,8 @@ class OctagonHealthCheckTests: OctagonTestsBase { func testCuttlefishDontPostEscrowCFUDueToPendingPrecord() throws { self.fakeCuttlefishServer.returnRepairEscrowResponse = true OTMockSecEscrowRequest.self.populateStatuses = true - let (cuttlefishContext, _) = try responseTestsSetup() - XCTAssertEqual(cuttlefishContext.postedEscrowRepairCFU, false, "should NOT have posted an escrow CFU") + let (cuttlefishContext, _) = try responseTestsSetup(expectedState: OctagonStateReady) + XCTAssertFalse(cuttlefishContext.followupHandler.hasPosted(.confirmExistingSecret), "should NOT have posted an escrow CFU") } func testHealthCheckWhileLocked() throws { @@ -794,6 +890,7 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -841,6 +938,236 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.assertEnters(context: cuttlefishContext, state: OctagonStateWaitForHSA2, within: 10 * NSEC_PER_SEC) } + + func testRPCTrustStatusReturnsIsLocked() throws { + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + do { + clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + + self.aksLockState = true + self.lockStateTracker.recheck() + + let configuration = OTOperationConfiguration() + + let statusexpectation = self.expectation(description: "status callback occurs") + self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, isLocked, error in + XCTAssertEqual(egoStatus, .in, "Self peer for OTDefaultContext should be trusted") + XCTAssertNotNil(egoPeerID, "Should have a peerID") + XCTAssertEqual(isLocked, true, "should be true") + XCTAssertNil(error, "error should be nil") + statusexpectation.fulfill() + } + self.wait(for: [statusexpectation], timeout: 10) + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(OTCKContainerName, context: OTDefaultContext, skipRateLimitingCheck: false) { error in + XCTAssertNil(error, "error should be nil") + healthCheckCallback.fulfill() + } + self.wait(for: [healthCheckCallback], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + } + + func testBecomeUntrustedResultsInWaitForUnlock() throws { + self.startCKAccountStatusMock() + + // First, peer 1 establishes, preapproving both peer2 and peer3. Then, peer2 and peer3 join and harmonize. + // Peer1 is never told about the follow-on joins. + // Then, the test can begin. + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + let peer3SOSMockPeer = self.createSOSPeer(peerID: "peer3ID") + + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + self.mockSOSAdapter.trustedPeers.add(peer3SOSMockPeer) + + // Due to how everything is shaking out, SOS TLKShares will be uploaded in a second transaction after Octagon uploads its TLKShares + // This isn't great: Octagon: upload SOS TLKShares alongside initial key hierarchy + self.assertAllCKKSViewsUpload(tlkShares: 3) + + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + let peer1ID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // peer2 + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + let peer2ID = try peer2.accountMetadataStore.getEgoPeerID() + + // peer3 + let peer3mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer3SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let peer3 = self.makeInitiatorContext(contextID: "peer3", authKitAdapter: self.mockAuthKit3, sosAdapter: peer3mockSOS) + + peer3.startOctagonStateMachine() + self.assertEnters(context: peer3, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer3) + let peer3ID = try peer3.accountMetadataStore.getEgoPeerID() + + // Now, tell peer2 about peer3's join + self.sendContainerChangeWaitForFetch(context: peer2) + + // Peer 1 should preapprove both peers. + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trustsByPreapproval, target: peer2ID)), + "peer 1 should trust peer 2 by preapproval") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trustsByPreapproval, target: peer2ID)), + "peer 1 should trust peer 3 by preapproval") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer1ID)), + "peer 2 should trust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer3ID)), + "peer 2 should trust peer 3") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer3ID, opinion: .trusts, target: peer1ID)), + "peer 3 should trust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer3ID, opinion: .trusts, target: peer2ID)), + "peer 3 should trust peer 2") + + // Now, the test can begin. Peer2 decides it rules the world. + let removalExpectation = self.expectation(description: "removal occurs") + peer2.rpcRemoveFriends(inClique: [peer1ID, peer3ID]) { removeError in + XCTAssertNil(removeError, "Should be no error removing peer1 and peer3") + removalExpectation.fulfill() + } + self.wait(for: [removalExpectation], timeout: 5) + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .excludes, target: peer1ID)), + "peer 2 should distrust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .excludes, target: peer3ID)), + "peer 2 should distrust peer 3") + + // And we notify peer3 about this, and it should become sad + let updateTrustExpectation = self.expectation(description: "fetchChanges") + + // Ths push will only be delivered when the device is unlocked, so simulate the device locking during the fetch + self.fakeCuttlefishServer.fetchChangesListener = { request in + self.fakeCuttlefishServer.fetchChangesListener = nil + + self.aksLockState = true + self.lockStateTracker.recheck() + + updateTrustExpectation.fulfill() + return nil + } + peer3.notifyContainerChange(nil) + self.wait(for: [updateTrustExpectation], timeout: 10) + + self.assertEnters(context: peer3, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + + self.aksLockState = false + self.lockStateTracker.recheck() + + self.assertEnters(context: peer3, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: peer3) + } + + func testEvaluateTPHOctagonTrust() throws { + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + do { + clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(OTCKContainerName, context: OTDefaultContext, skipRateLimitingCheck: false) { error in + XCTAssertNil(error, "error should be nil") + healthCheckCallback.fulfill() + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateTPHTrustCheck, within: 10 * NSEC_PER_SEC) + + self.aksLockState = true + self.lockStateTracker.recheck() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + + self.wait(for: [healthCheckCallback], timeout: 10) + + self.aksLockState = false + self.lockStateTracker.recheck() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + } + + func testEvaluateSecdOctagonTrust() throws { + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + + self.assertResetAndBecomeTrustedInDefaultContext() + + // Join with another peer, so that the depart will work + let joiningContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit2) + self.assertJoinViaEscrowRecoveryFromDefaultContextWithReciprocationAndTLKShares(joiningContext: joiningContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + let leaveExpectation = self.expectation(description: "rpcLeaveClique returns") + self.cuttlefishContext.rpcLeaveClique { leaveError in + XCTAssertNil(leaveError, "Should be no error leaving") + leaveExpectation.fulfill() + } + self.wait(for: [leaveExpectation], timeout: 10) + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(OTCKContainerName, context: OTDefaultContext, skipRateLimitingCheck: false) { error in + XCTAssertNotNil(error, "error should not be nil") + healthCheckCallback.fulfill() + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStatePostRepairCFU, within: 10 * NSEC_PER_SEC) + + self.aksLockState = true + self.lockStateTracker.recheck() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + + self.wait(for: [healthCheckCallback], timeout: 10) + + self.aksLockState = false + self.lockStateTracker.recheck() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + } } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+Helpers.swift b/keychain/ot/tests/octagon/OctagonTests+Helpers.swift new file mode 100644 index 00000000..7b7cb3fa --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonTests+Helpers.swift @@ -0,0 +1,104 @@ +#if OCTAGON +import Foundation + +extension SignedPeerStableInfo { + func stableInfo() -> TPPeerStableInfo { + let newStableInfo = TPPeerStableInfo(data: self.peerStableInfo, sig: self.sig) + XCTAssertNotNil(newStableInfo, "should be able to make a stableInfo from protobuf") + return newStableInfo! + } +} + +extension SignedPeerDynamicInfo { + func dynamicInfo() -> TPPeerDynamicInfo { + let newDynamicInfo = TPPeerDynamicInfo(data: self.peerDynamicInfo, sig: self.sig) + XCTAssertNotNil(newDynamicInfo, "should be able to make a dynamicInfo from protobuf") + return newDynamicInfo! + } +} + +extension EstablishRequest { + func permanentInfo() -> TPPeerPermanentInfo { + XCTAssertTrue(self.hasPeer, "establish request should have a peer") + XCTAssertTrue(self.peer.hasPermanentInfoAndSig, "establish request should have a permanentInfo") + let newPermanentInfo = TPPeerPermanentInfo(peerID: self.peer.peerID, + data: self.peer.permanentInfoAndSig.peerPermanentInfo, + sig: self.peer.permanentInfoAndSig.sig, + keyFactory: TPECPublicKeyFactory()) + XCTAssertNotNil(newPermanentInfo, "should be able to make a permanantInfo from protobuf") + return newPermanentInfo! + } +} + +extension OctagonTestsBase { + func simulateRestart(context: OTCuttlefishContext) -> OTCuttlefishContext { + self.manager.removeContext(forContainerName: context.containerName, contextID: context.contextID) + + if context.contextID == OTDefaultContext { + self.restartCKKSViews() + } + + let newContext = self.manager.context(forContainerName: context.containerName, contextID: context.contextID) + + if context.contextID == OTDefaultContext { + XCTAssertNil(self.injectedManager?.policy, "CKKS should not have a policy after 'restart'") + } + + newContext.startOctagonStateMachine() + + return newContext + } + + func cliqueFor(context: OTCuttlefishContext) -> OTClique { + let otcliqueContext = OTConfigurationContext() + otcliqueContext.context = context.contextID + otcliqueContext.altDSID = try! context.authKitAdapter.primaryiCloudAccountAltDSID() + otcliqueContext.otControl = self.otControl + + return OTClique(contextData: otcliqueContext) + } + + func assertFetchUserControllableViewsSyncStatus(clique: OTClique, status: Bool) { + do { + let result = try clique.fetchUserControllableViewsSyncingEnabled() + XCTAssertEqual(result, status, "API should report that sync status matches expectation") + } catch { + XCTFail("Should be no error fetching status: \(error)") + } + } + + func assertModifyUserViews(clique: OTClique, intendedSyncStatus: Bool) { + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + if intendedSyncStatus { + XCTAssertEqual(newStableInfo.syncUserControllableViews, .ENABLED, "User views should now be enabled") + } else { + XCTAssertEqual(newStableInfo.syncUserControllableViews, .DISABLED, "User views should now be disabled") + } + updateTrustExpectation.fulfill() + + return nil + } + + XCTAssertNoThrow(try clique.setUserControllableViewsSyncStatus(intendedSyncStatus), "Should be no error setting user-visible sync status") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: intendedSyncStatus) + + self.wait(for: [updateTrustExpectation], timeout: 10) + self.fakeCuttlefishServer.updateListener = nil + } + + func assertModifyUserViewsWithNoPeerUpdate(clique: OTClique, intendedSyncStatus: Bool, finalSyncStatus: Bool? = nil) { + self.fakeCuttlefishServer.updateListener = { request in + XCTFail("Expected no updates during user view status modification") + return nil + } + + XCTAssertNoThrow(try clique.setUserControllableViewsSyncStatus(intendedSyncStatus), "Should be no error setting user-visible sync status") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: finalSyncStatus ?? intendedSyncStatus) + + self.fakeCuttlefishServer.updateListener = nil + } +} + +#endif diff --git a/keychain/ot/tests/octagon/OctagonTests+RecoveryKey.swift b/keychain/ot/tests/octagon/OctagonTests+RecoveryKey.swift index ad69de5b..92cf0eb3 100644 --- a/keychain/ot/tests/octagon/OctagonTests+RecoveryKey.swift +++ b/keychain/ot/tests/octagon/OctagonTests+RecoveryKey.swift @@ -1,15 +1,39 @@ #if OCTAGON -@objcMembers class OctagonRecoveryKeyTests: OctagonTestsBase { +extension Container { + func removeRKFromContainer() { + self.moc.performAndWait { + self.containerMO.recoveryKeySigningSPKI = nil + self.containerMO.recoveryKeyEncryptionSPKI = nil + + try! self.moc.save() + } + } +} + +@objcMembers +class OctagonRecoveryKeyTests: OctagonTestsBase { override func setUp() { + // Please don't make the SOS API calls, no matter what + OctagonSetSOSFeatureEnabled(false) + super.setUp() + + // Set this to what it normally is. Each test can muck with it, if they like + #if os(macOS) || os(iOS) + OctagonSetPlatformSupportsSOS(true) + self.manager.setSOSEnabledForPlatformFlag(true) + #else + self.manager.setSOSEnabledForPlatformFlag(false) + OctagonSetPlatformSupportsSOS(false) + #endif } func testSetRecoveryKey() throws { self.startCKAccountStatusMock() - self.manager.setSOSEnabledForPlatformFlag(false) self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) XCTAssertFalse(self.mockAuthKit.currentDeviceList().isEmpty, "should not have zero devices") @@ -34,7 +58,7 @@ self.manager.setSOSEnabledForPlatformFlag(true) let createKeyExpectation = self.expectation(description: "createKeyExpectation returns") - self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context ?? "defaultContext", recoveryKey: recoveryKey) { error in + self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context, recoveryKey: recoveryKey) { error in XCTAssertNil(error, "error should be nil") createKeyExpectation.fulfill() } @@ -46,6 +70,7 @@ self.manager.setSOSEnabledForPlatformFlag(false) self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -59,6 +84,7 @@ self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String @@ -66,7 +92,7 @@ self.manager.setSOSEnabledForPlatformFlag(true) let createKeyExpectation = self.expectation(description: "createKeyExpectation returns") - self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context ?? "defaultContext", recoveryKey: recoveryKey) { error in + self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context, recoveryKey: recoveryKey) { error in XCTAssertNil(error, "error should be nil") createKeyExpectation.fulfill() } @@ -77,8 +103,13 @@ self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) self.verifyDatabaseMocks() + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + let bottle = self.fakeCuttlefishServer.state.bottles[0] let initiatorContextID = "new guy" @@ -89,7 +120,7 @@ self.sendContainerChange(context: initiatorContext) let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - initiatorContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + initiatorContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } @@ -97,25 +128,27 @@ self.verifyDatabaseMocks() self.sendContainerChangeWaitForFetch(context: initiatorContext) + + self.assertAllCKKSViewsUpload(tlkShares: 1) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() let stableInfoCheckDumpCallback = self.expectation(description: "stableInfoCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -124,20 +157,19 @@ self.wait(for: [stableInfoCheckDumpCallback], timeout: 10) let stableInfoAcceptorCheckDumpCallback = self.expectation(description: "stableInfoAcceptorCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: self.otcliqueContext.context ?? "defaultContext") { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: self.otcliqueContext.context) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -152,6 +184,7 @@ self.manager.setSOSEnabledForPlatformFlag(false) self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -165,6 +198,7 @@ self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String @@ -172,7 +206,7 @@ self.manager.setSOSEnabledForPlatformFlag(true) let createKeyExpectation = self.expectation(description: "createKeyExpectation returns") - self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context ?? "defaultContext", recoveryKey: recoveryKey) { error in + self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context, recoveryKey: recoveryKey) { error in XCTAssertNil(error, "error should be nil") createKeyExpectation.fulfill() } @@ -183,6 +217,8 @@ self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) let bottle = self.fakeCuttlefishServer.state.bottles[0] @@ -196,7 +232,7 @@ self.assertEnters(context: initiatorContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - initiatorContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + initiatorContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } @@ -213,20 +249,19 @@ self.verifyDatabaseMocks() let stableInfoCheckDumpCallback = self.expectation(description: "stableInfoCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -235,20 +270,19 @@ self.wait(for: [stableInfoCheckDumpCallback], timeout: 10) let stableInfoAcceptorCheckDumpCallback = self.expectation(description: "stableInfoAcceptorCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: self.otcliqueContext.context ?? "defaultContext") { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: self.otcliqueContext.context) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -263,7 +297,7 @@ self.sendContainerChange(context: thirdPeerContext) let thirdPeerJoinWithBottleExpectation = self.expectation(description: "thirdPeerJoinWithBottleExpectation callback occurs") - thirdPeerContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID) { error in + thirdPeerContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") thirdPeerJoinWithBottleExpectation.fulfill() } @@ -273,30 +307,34 @@ self.sendContainerChangeWaitForFetch(context: thirdPeerContext) let thirdPeerStableInfoCheckDumpCallback = self.expectation(description: "thirdPeerStableInfoCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: thirdPeerContextID) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: thirdPeerContextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 3, "should be 3df peer ids") thirdPeerStableInfoCheckDumpCallback.fulfill() } self.wait(for: [thirdPeerStableInfoCheckDumpCallback], timeout: 10) + + // And ensure that the original peer uploads shares for the third as well + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() } func createEstablishContext(contextID: String) -> OTCuttlefishContext { - return self.manager.context(forContainerName: OTCKContainerName, contextID: contextID, sosAdapter: self.mockSOSAdapter, @@ -315,6 +353,7 @@ let establishContext = self.createEstablishContext(contextID: establishContextID) establishContext.startOctagonStateMachine() + XCTAssertNoThrow(try establishContext.setCDPEnabled()) self.assertEnters(context: establishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -335,10 +374,11 @@ self.assertEnters(context: establishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: establishContext) - // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: establishContext, zoneID: self.manateeZoneID) + let establishedPeerID = self.fetchEgoPeerID(context: establishContext) + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: establishContext) self.assertSelfTLKSharesInCloudKit(context: establishContext) let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String @@ -353,8 +393,10 @@ } self.wait(for: [createRecoveryExpectation], timeout: 10) + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID)) self.sendContainerChangeWaitForFetch(context: establishContext) + // Now, join from a new device let recoveryContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) recoveryContext.startOctagonStateMachine() @@ -367,25 +409,27 @@ XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + let joinedPeerID = self.fetchEgoPeerID(context: recoveryContext) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.sendContainerChangeWaitForFetch(context: recoveryContext) let stableInfoCheckDumpCallback = self.expectation(description: "stableInfoCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") let vouchers = dump!["vouchers"] @@ -397,20 +441,19 @@ self.sendContainerChangeWaitForFetch(context: establishContext) let stableInfoAcceptorCheckDumpCallback = self.expectation(description: "stableInfoAcceptorCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: establishContextID) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: establishContextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") let vouchers = dump!["vouchers"] @@ -418,7 +461,19 @@ stableInfoAcceptorCheckDumpCallback.fulfill() } self.wait(for: [stableInfoAcceptorCheckDumpCallback], timeout: 10) - try self.putSelfTLKShareInCloudKit(context: recoveryContext, zoneID: self.manateeZoneID) + + // And check the current state of the world + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: joinedPeerID, opinion: .trusts, target: joinedPeerID)), + "joined peer should trust itself") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: joinedPeerID, opinion: .trusts, target: establishedPeerID)), + "joined peer should trust establish peer") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: establishedPeerID, opinion: .trusts, target: establishedPeerID)), + "establish peer should trust itself") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: establishedPeerID, opinion: .trusts, target: joinedPeerID)), + "establish peer should trust joined peer") + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertSelfTLKSharesInCloudKit(context: recoveryContext) } @@ -431,6 +486,7 @@ let establishContext = self.createEstablishContext(contextID: establishContextID) establishContext.startOctagonStateMachine() + XCTAssertNoThrow(try establishContext.setCDPEnabled()) self.assertEnters(context: establishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -466,11 +522,11 @@ self.sendContainerChangeWaitForFetch(context: establishContext) self.silentFetchesAllowed = false - self.expectCKFetchAndRun(beforeFinished: { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + self.expectCKFetchAndRun { + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() self.silentFetchesAllowed = true - }) + } let recoveryContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) recoveryContext.startOctagonStateMachine() @@ -483,7 +539,7 @@ XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) self.assertConsidersSelfTrusted(context: recoveryContext) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC) @@ -497,6 +553,7 @@ let establishContext = self.createEstablishContext(contextID: establishContextID) establishContext.startOctagonStateMachine() + XCTAssertNoThrow(try establishContext.setCDPEnabled()) self.assertEnters(context: establishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -532,6 +589,7 @@ let establishContext = self.createEstablishContext(contextID: establishContextID) establishContext.startOctagonStateMachine() + XCTAssertNoThrow(try establishContext.setCDPEnabled()) self.assertEnters(context: establishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -575,6 +633,7 @@ let initiatorContextID = "initiator-context-id" self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -592,6 +651,7 @@ XCTAssertNotNil(entropy, "entropy should not be nil") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) let bottle = self.fakeCuttlefishServer.state.bottles[0] @@ -607,7 +667,7 @@ self.sendContainerChange(context: initiatorContext) let restoreExpectation = self.expectation(description: "restore returns") - self.manager!.restore(OTCKContainerName, contextID: initiatorContextID, bottleSalt: self.otcliqueContext.altDSID, entropy: entropy!, bottleID: bottle.bottleID) { error in + self.manager!.restore(OTCKContainerName, contextID: initiatorContextID, bottleSalt: self.otcliqueContext.altDSID!, entropy: entropy!, bottleID: bottle.bottleID) { error in XCTAssertNil(error, "error should be nil") restoreExpectation.fulfill() } @@ -616,14 +676,13 @@ self.assertEnters(context: initiatorContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) var initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -642,9 +701,9 @@ } self.wait(for: [setRecoveryKeyExpectation], timeout: 10) - let recoveryKey2 = SecRKCreateRecoveryKeyString(nil) + let recoveryKey2 = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil)) let setRecoveryKeyExpectationAgain = self.expectation(description: "setRecoveryKeyExpectationAgain callback occurs") - TestsObjectiveC.setNewRecoveryKeyWithData(initiatorConfigurationContext, recoveryKey: recoveryKey2!) { rk, error in + TestsObjectiveC.setNewRecoveryKeyWithData(initiatorConfigurationContext, recoveryKey: recoveryKey2) { rk, error in XCTAssertNil(error, "error should be nil") XCTAssertNotNil(rk, "rk should not be nil") setRecoveryKeyExpectationAgain.fulfill() @@ -652,7 +711,16 @@ self.wait(for: [setRecoveryKeyExpectationAgain], timeout: 10) self.sendContainerChangeWaitForFetch(context: initiatorContext) + + // When the original peer responds to the new peer, it should upload tlkshares for the new peer and the new RK + // (since the remote peer didn't upload shares for the new RK) + self.assertAllCKKSViewsUpload(tlkShares: 2) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey2, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey2, salt: try XCTUnwrap(self.mockAuthKit.altDSID), sender: self.cuttlefishContext)) var initiatorRecoverySigningKey: Data? var initiatorRecoveryEncryptionKey: Data? @@ -662,15 +730,14 @@ //now let's ensure recovery keys are set for both the first device and second device initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: initiatorContextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") @@ -678,7 +745,7 @@ initiatorRecoverySigningKey = stableInfo!["recovery_signing_public_key"] as? Data initiatorRecoveryEncryptionKey = stableInfo!["recovery_encryption_public_key"] as? Data - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") let vouchers = dump!["vouchers"] @@ -688,15 +755,14 @@ self.wait(for: [initiatorDumpCallback], timeout: 10) let firstDeviceDumpCallback = self.expectation(description: "firstDeviceDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") @@ -704,7 +770,7 @@ firstDeviceRecoverySigningKey = stableInfo!["recovery_signing_public_key"] as? Data firstDeviceRecoveryEncryptionKey = stableInfo!["recovery_encryption_public_key"] as? Data - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") let vouchers = dump!["vouchers"] @@ -726,6 +792,7 @@ let establishContext = self.createEstablishContext(contextID: establishContextID) establishContext.startOctagonStateMachine() + XCTAssertNoThrow(try establishContext.setCDPEnabled()) self.assertEnters(context: establishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -747,22 +814,23 @@ self.assertConsidersSelfTrusted(context: establishContext) // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: establishContext, zoneID: self.manateeZoneID) - + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: establishContext) self.assertSelfTLKSharesInCloudKit(context: establishContext) - let recoveryKey = SecRKCreateRecoveryKeyString(nil) + let recoveryKey = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil)) XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") self.manager.setSOSEnabledForPlatformFlag(true) let setRecoveryKeyExpectation = self.expectation(description: "setRecoveryKeyExpectation callback occurs") - TestsObjectiveC.setNewRecoveryKeyWithData(recoverykeyotcliqueContext, recoveryKey: recoveryKey!) { _, error in + TestsObjectiveC.setNewRecoveryKeyWithData(recoverykeyotcliqueContext, recoveryKey: recoveryKey) { _, error in XCTAssertNil(error, "error should be nil") setRecoveryKeyExpectation.fulfill() } self.wait(for: [setRecoveryKeyExpectation], timeout: 10) + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID)) + self.sendContainerChangeWaitForFetch(context: establishContext) let newCliqueContext = OTConfigurationContext() @@ -775,32 +843,36 @@ newGuyContext.startOctagonStateMachine() self.sendContainerChangeWaitForUntrustedFetch(context: newGuyContext) + self.verifyDatabaseMocks() self.manager.setSOSEnabledForPlatformFlag(true) let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") - OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in + OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey) { error in XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) self.sendContainerChangeWaitForFetch(context: newGuyContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) + let stableInfoAcceptorCheckDumpCallback = self.expectation(description: "stableInfoAcceptorCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") let vouchers = dump!["vouchers"] @@ -810,26 +882,25 @@ self.wait(for: [stableInfoAcceptorCheckDumpCallback], timeout: 10) self.assertEnters(context: newGuyContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: newGuyContext) - try self.putSelfTLKShareInCloudKit(context: newGuyContext, zoneID: self.manateeZoneID) + try self.putSelfTLKSharesInCloudKit(context: newGuyContext) self.assertSelfTLKSharesInCloudKit(context: newGuyContext) self.sendContainerChangeWaitForFetch(context: establishContext) let stableInfoCheckDumpCallback = self.expectation(description: "stableInfoCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: establishContextID) { - dump, _ in + self.tphClient.dump(withContainer: OTCKContainerName, context: establishContextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") let vouchers = dump!["vouchers"] @@ -839,57 +910,67 @@ self.wait(for: [stableInfoCheckDumpCallback], timeout: 10) } - func testOTCliqueJoinUsingANotEnrolledRecoveryKey() throws { + func testJoinWithUnknownRecoveryKey() throws { OctagonRecoveryKeySetIsEnabled(true) - self.manager.setSOSEnabledForPlatformFlag(false) + self.startCKAccountStatusMock() - let recoveryKey = SecRKCreateRecoveryKeyString(nil) - XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") + let remote = self.makeInitiatorContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) - let newCliqueContext = OTConfigurationContext() - newCliqueContext.context = OTDefaultContext - newCliqueContext.dsid = self.otcliqueContext.dsid - newCliqueContext.altDSID = self.mockAuthKit.altDSID! - newCliqueContext.otControl = self.otControl + let recoveryKey = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil), "recoveryKey should not be nil") - let recoveryGuyContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.manager.setSOSEnabledForPlatformFlag(true) + #if !os(macOS) && !os(iOS) + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") + TestsObjectiveC.recoverOctagon(usingData: self.otcliqueContext, recoveryKey: recoveryKey) { error in + XCTAssertNotNil(error, "error should exist") + joinWithRecoveryKeyExpectation.fulfill() + } + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + // double-check that the status is not in + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + #else let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") - TestsObjectiveC.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in + TestsObjectiveC.recoverOctagon(usingData: self.otcliqueContext, recoveryKey: recoveryKey) { error in XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) - self.sendContainerChange(context: recoveryGuyContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) - let newGuyCheckDumpCallback = self.expectation(description: "newGuyCheckDumpCallback callback occurs") - self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { - dump, _ in + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) + self.verifyDatabaseMocks() + + let rejoinedDumpCallback = self.expectation(description: "dump callback occurs") + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let stableInfo = egoSelf!["stableInfo"] as? Dictionary + let stableInfo = egoSelf!["stableInfo"] as? [String: AnyObject] XCTAssertNotNil(stableInfo, "stableInfo should not be nil") XCTAssertNotNil(stableInfo!["recovery_signing_public_key"], "recoverySigningPublicKey should not be nil") XCTAssertNotNil(stableInfo!["recovery_encryption_public_key"], "recoveryEncryptionPublicKey should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 1, "should be 1 peer ids") let vouchers = dump!["vouchers"] XCTAssertNotNil(vouchers, "vouchers should not be nil") - newGuyCheckDumpCallback.fulfill() + rejoinedDumpCallback.fulfill() } - self.wait(for: [newGuyCheckDumpCallback], timeout: 10) - self.assertEnters(context: recoveryGuyContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - - self.assertSelfTLKSharesInCloudKit(context: recoveryGuyContext) + self.wait(for: [rejoinedDumpCallback], timeout: 10) + #endif } func testSetRecoveryKeyAsLimitedPeer() throws { @@ -898,6 +979,7 @@ self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) XCTAssertFalse(self.mockAuthKit.currentDeviceList().isEmpty, "should not have zero devices") @@ -921,7 +1003,7 @@ XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") let createKeyExpectation = self.expectation(description: "createKeyExpectation returns") - self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context ?? "defaultContext", recoveryKey: recoveryKey) { error in + self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context, recoveryKey: recoveryKey) { error in XCTAssertNotNil(error, "error should not be nil") XCTAssertEqual((error! as NSError).code, OctagonError.OTErrorLimitedPeer.rawValue, "error code should be limited peer") createKeyExpectation.fulfill() @@ -938,6 +1020,7 @@ let establishContext = self.createEstablishContext(contextID: establishContextID) establishContext.startOctagonStateMachine() + XCTAssertNoThrow(try establishContext.setCDPEnabled()) self.assertEnters(context: establishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -959,17 +1042,20 @@ self.assertConsidersSelfTrusted(context: establishContext) // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: establishContext, zoneID: self.manateeZoneID) - + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: establishContext) self.assertSelfTLKSharesInCloudKit(context: establishContext) - let recoveryKey = SecRKCreateRecoveryKeyString(nil) - XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") + let joiningPeerContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit3) + self.assertJoinViaEscrowRecovery(joiningContext: joiningPeerContext, sponsor: establishContext) + self.sendContainerChangeWaitForFetch(context: establishContext) + + // Now, create the Recovery Key + let recoveryKey = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil), "should be able to create a recovery key") self.manager.setSOSEnabledForPlatformFlag(true) let setRecoveryKeyExpectation = self.expectation(description: "setRecoveryKeyExpectation callback occurs") - TestsObjectiveC.setNewRecoveryKeyWithData(recoverykeyotcliqueContext, recoveryKey: recoveryKey!) { _, error in + TestsObjectiveC.setNewRecoveryKeyWithData(recoverykeyotcliqueContext, recoveryKey: recoveryKey) { _, error in XCTAssertNil(error, "error should be nil") setRecoveryKeyExpectation.fulfill() } @@ -995,13 +1081,19 @@ self.sendContainerChangeWaitForUntrustedFetch(context: newGuyContext) + // We'll perform a reset here. Allow for CKKS to do the same. + self.silentZoneDeletesAllowed = true + self.manager.setSOSEnabledForPlatformFlag(true) let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") - OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in + OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey) { error in XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) } func testVouchWithWrongRecoveryKey() throws { @@ -1013,6 +1105,7 @@ let establishContext = self.createEstablishContext(contextID: establishContextID) establishContext.startOctagonStateMachine() + XCTAssertNoThrow(try establishContext.setCDPEnabled()) self.assertEnters(context: establishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -1034,8 +1127,8 @@ self.assertConsidersSelfTrusted(context: establishContext) // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: establishContext, zoneID: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: establishContext) self.assertSelfTLKSharesInCloudKit(context: establishContext) @@ -1070,13 +1163,16 @@ recoveryKey = SecRKCreateRecoveryKeyString(nil) XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") + // We'll reset Octagon here, so allow for CKKS to reset as well + self.silentZoneDeletesAllowed = true + OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in - XCTAssertNotNil(error, "error should NOT be nil") - XCTAssertEqual((error! as NSError).code, 32, "error code should be 32/untrusted recovery keys") - XCTAssertEqual((error! as NSError).domain, "com.apple.security.trustedpeers.container", "error code domain should be com.apple.security.trustedpeers.container") + XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } func testRecoveryWithDistrustedPeers() throws { @@ -1088,6 +1184,7 @@ let establishContext = self.createEstablishContext(contextID: establishContextID) establishContext.startOctagonStateMachine() + XCTAssertNoThrow(try establishContext.setCDPEnabled()) self.assertEnters(context: establishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -1109,11 +1206,15 @@ self.assertConsidersSelfTrusted(context: establishContext) // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: establishContext, zoneID: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: establishContext) self.assertSelfTLKSharesInCloudKit(context: establishContext) + let joiningPeerContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit3) + self.assertJoinViaEscrowRecovery(joiningContext: joiningPeerContext, sponsor: establishContext) + self.sendContainerChangeWaitForFetch(context: establishContext) + let recoveryKey = SecRKCreateRecoveryKeyString(nil) XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") self.manager.setSOSEnabledForPlatformFlag(true) @@ -1127,6 +1228,8 @@ self.sendContainerChangeWaitForFetch(context: establishContext) + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey!, salt: self.mockAuthKit.altDSID!) + //now this peer will leave octagon XCTAssertNoThrow(try clique.leave(), "Should be no error departing clique") @@ -1148,11 +1251,17 @@ self.manager.setSOSEnabledForPlatformFlag(true) let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") + // We expect an Octagon reset here, because the RK is for a distrusted peer + // This also performs a CKKS reset + self.silentZoneDeletesAllowed = true + OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } func testMalformedRecoveryKey() throws { @@ -1164,6 +1273,7 @@ let establishContext = self.createEstablishContext(contextID: establishContextID) establishContext.startOctagonStateMachine() + XCTAssertNoThrow(try establishContext.setCDPEnabled()) self.assertEnters(context: establishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -1185,9 +1295,8 @@ self.assertConsidersSelfTrusted(context: establishContext) // Fake that this peer also created some TLKShares for itself - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - try self.putSelfTLKShareInCloudKit(context: establishContext, zoneID: self.manateeZoneID) - + self.putFakeKeyHierarchiesInCloudKit() + try! self.putSelfTLKSharesInCloudKit(context: establishContext) self.assertSelfTLKSharesInCloudKit(context: establishContext) let recoveryKey = "malformedRecoveryKey" @@ -1195,7 +1304,7 @@ self.manager.setSOSEnabledForPlatformFlag(true) let createKeyExpectation = self.expectation(description: "createKeyExpectation returns") - self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context ?? "defaultContext", recoveryKey: recoveryKey) { error in + self.manager.createRecoveryKey(OTCKContainerName, contextID: self.otcliqueContext.context, recoveryKey: recoveryKey) { error in XCTAssertNotNil(error, "error should NOT be nil") XCTAssertEqual((error! as NSError).code, 41, "error code should be 41/malformed recovery key") XCTAssertEqual((error! as NSError).domain, "com.apple.security.octagon", "error code domain should be com.apple.security.octagon") @@ -1223,7 +1332,243 @@ XCTAssertEqual((error! as NSError).domain, "com.apple.security.octagon", "error code domain should be com.apple.security.octagon") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + } + + @discardableResult + func createAndSetRecoveryKey(context: OTCuttlefishContext) throws -> String { + let cliqueConfiguration = OTConfigurationContext() + cliqueConfiguration.context = context.contextID + cliqueConfiguration.altDSID = try! context.authKitAdapter.primaryiCloudAccountAltDSID() + cliqueConfiguration.otControl = self.otControl + + let recoveryKey = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil), "should be able to create a recovery key") + + let setRecoveryKeyExpectation = self.expectation(description: "setRecoveryKeyExpectation callback occurs") + TestsObjectiveC.setNewRecoveryKeyWithData(cliqueConfiguration, recoveryKey: recoveryKey) { _, error in + XCTAssertNil(error, "error should be nil") + setRecoveryKeyExpectation.fulfill() + } + self.wait(for: [setRecoveryKeyExpectation], timeout: 10) + + return recoveryKey + } + + func testConcurWithTrustedPeer() throws { + self.startCKAccountStatusMock() + self.manager.setSOSEnabledForPlatformFlag(true) + + self.assertResetAndBecomeTrustedInDefaultContext() + + let peer2Context = self.makeInitiatorContext(contextID: "peer2") + let peer2ID = self.assertJoinViaEscrowRecovery(joiningContext: peer2Context, sponsor: self.cuttlefishContext) + + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // peer1 sets a recovery key + var rkSigningPubKey: Data? + var rkEncryptionPubKey: Data? + + let setRKExpectation = self.expectation(description: "setRecoveryKey") + self.fakeCuttlefishServer.setRecoveryKeyListener = { request in + XCTAssertNotNil(request.recoverySigningPubKey, "signing public key should be present") + XCTAssertNotNil(request.recoveryEncryptionPubKey, "encryption public key should be present") + + rkSigningPubKey = request.recoverySigningPubKey + rkEncryptionPubKey = request.recoveryEncryptionPubKey + + setRKExpectation.fulfill() + return nil + } + + try self.createAndSetRecoveryKey(context: self.cuttlefishContext) + self.wait(for: [setRKExpectation], timeout: 10) + + // And peer2 concurs with it upon receiving a push + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { [unowned self] request in + XCTAssertEqual(request.peerID, peer2ID, "Update should be for peer2") + + let newStableInfo = request.stableInfoAndSig.stableInfo() + XCTAssertEqual(newStableInfo.recoverySigningPublicKey, rkSigningPubKey, "Recovery signing key should match other peer") + XCTAssertEqual(newStableInfo.recoveryEncryptionPublicKey, rkEncryptionPubKey, "Recovery encryption key should match other peer") + self.fakeCuttlefishServer.updateListener = nil + updateTrustExpectation.fulfill() + + return nil + } + + self.sendContainerChangeWaitForFetch(context: peer2Context) + self.wait(for: [updateTrustExpectation], timeout: 10) + + // Restart TPH, and ensure that more updates succeed + self.tphClient.containerMap.removeAllContainers() + + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.sendContainerChangeWaitForFetch(context: peer2Context) + } + + func testRecoveryKeyLoadingOnContainerLoad() throws { + self.startCKAccountStatusMock() + self.manager.setSOSEnabledForPlatformFlag(true) + + _ = self.assertResetAndBecomeTrustedInDefaultContext() + // peer1 sets a recovery key + try self.createAndSetRecoveryKey(context: self.cuttlefishContext) + + // Restart TPH + self.tphClient.containerMap.removeAllContainers() + + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + } + + func testRecoveryKeyLoadingOnContainerLoadEvenIfMissing() throws { + self.startCKAccountStatusMock() + self.manager.setSOSEnabledForPlatformFlag(true) + + _ = self.assertResetAndBecomeTrustedInDefaultContext() + // peer1 sets a recovery key + try self.createAndSetRecoveryKey(context: self.cuttlefishContext) + + // Before restarting TPH, emulate a world in which the RK variables were not set on the container + + let containerName = ContainerName(container: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) + let container = try self.tphClient.containerMap.findOrCreate(name: containerName) + container.removeRKFromContainer() + + // Restart TPH + self.tphClient.containerMap.removeAllContainers() + + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + } + + func testCKKSSendsTLKSharesToRecoveryKey() throws { + #if os(tvOS) || os(watchOS) + self.startCKAccountStatusMock() + throw XCTSkip("Apple TVs and watches will not set recovery key") + #else + + self.startCKAccountStatusMock() + + // To get into a state where we don't upload the TLKShares to each RK on RK creation, put Octagon into a waitfortlk state + // Right after CKKS fetches for the first time, insert a new key hierarchy into CloudKit + self.silentFetchesAllowed = false + self.expectCKFetchAndRun { + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() + self.silentFetchesAllowed = true + } + + do { + let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + } + + // Now, we should be in 'ready' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) + + // and all subCKKSes should enter waitfortlk, as they don't have the TLKs uploaded by the other peer + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // And a recovery key is set + let recoveryKey = try self.createAndSetRecoveryKey(context: self.cuttlefishContext) + + // and now, all TLKs arrive! CKKS should upload two shares: one for itself, and one for the recovery key + self.assertAllCKKSViewsUpload(tlkShares: 2) + self.saveTLKMaterialToKeychain() + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) + + #endif // tvOS || watchOS + } + + func testRKRecoveryRecoversCKKSCreatedShares() throws { + self.startCKAccountStatusMock() + + let remote = self.createEstablishContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) + + #if os(tvOS) || os(watchOS) + self.manager.setSOSEnabledForPlatformFlag(true) + let recoveryKey = try self.createAndSetRecoveryKey(context: remote) + self.manager.setSOSEnabledForPlatformFlag(false) + #else + let recoveryKey = try self.createAndSetRecoveryKey(context: remote) + #endif + + // And TLKShares for the RK are sent from the Octagon peer + self.putFakeKeyHierarchiesInCloudKit() + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID), sender: remote) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID), sender: remote)) + + // Now, join! This should recover the TLKs. + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + self.assertAllCKKSViewsUpload(tlkShares: 1) + + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKey callback occurs") + self.cuttlefishContext.join(withRecoveryKey: recoveryKey) { error in + XCTAssertNil(error, "error should be nil") + joinWithRecoveryKeyExpectation.fulfill() + } + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + } + + func testRecoverTLKSharesSentToRKAfterCKKSTimeout() throws { + OctagonRecoveryKeySetIsEnabled(true) + self.manager.setSOSEnabledForPlatformFlag(false) + self.startCKAccountStatusMock() + + let remote = self.createEstablishContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: remote) + self.assertSelfTLKSharesInCloudKit(context: remote) + + self.manager.setSOSEnabledForPlatformFlag(true) + let recoveryKey = try self.createAndSetRecoveryKey(context: remote) + + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID)) + + // Now, join from a new device + // Simulate CKKS fetches taking forever. In practice, this is caused by many round-trip fetches to CK happening over minutes. + self.holdCloudKitFetches() + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKey callback occurs") + self.cuttlefishContext.join(withRecoveryKey: recoveryKey) { error in + XCTAssertNil(error, "error should be nil") + joinWithRecoveryKeyExpectation.fulfill() + } + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateFetch, within: 10 * NSEC_PER_SEC) + + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.releaseCloudKitFetchHold() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) } } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+Reset.swift b/keychain/ot/tests/octagon/OctagonTests+Reset.swift index 00037248..8daace77 100644 --- a/keychain/ot/tests/octagon/OctagonTests+Reset.swift +++ b/keychain/ot/tests/octagon/OctagonTests+Reset.swift @@ -5,6 +5,7 @@ class OctagonResetTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) _ = try self.cuttlefishContext.accountAvailable("13453464") @@ -21,6 +22,7 @@ class OctagonResetTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.cuttlefishContext.rpcResetAndEstablish(.testGenerated) { resetError in @@ -37,6 +39,7 @@ class OctagonResetTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.cuttlefishContext.rpcResetAndEstablish(.testGenerated) { resetError in @@ -58,7 +61,7 @@ class OctagonResetTests: OctagonTestsBase { self.startCKAccountStatusMock() // Before resetAndEstablish, there shouldn't be any stored account state - XCTAssertThrowsError(try OTAccountMetadataClassC.loadFromKeychain(forContainer: containerName, contextID: contextName), "Before doing anything, loading a non-existent account state should fail") + XCTAssertThrowsError(try OTAccountMetadataClassC.loadFromKeychain(forContainer: containerName, contextID: contextName), "Before doing anything, loading a non-existent account state should fail") let resetAndEstablishExpectation = self.expectation(description: "resetAndEstablish callback occurs") let escrowRequestNotification = expectation(forNotification: OTMockEscrowRequestNotification, @@ -94,6 +97,7 @@ class OctagonResetTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -113,10 +117,10 @@ class OctagonResetTests: OctagonTestsBase { self.verifyDatabaseMocks() // CKKS should pass through "waitfortrust" during a reset - let waitfortrusts = self.ckksViews.compactMap { view in - (view as! CKKSKeychainView).keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] as? CKKSCondition + let waitfortrusts = self.injectedManager!.views.allValues.map { view in + (view as! CKKSKeychainView).keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust]! } - XCTAssert(waitfortrusts.count > 0, "Should have at least one waitfortrust condition") + XCTAssert(!waitfortrusts.isEmpty, "Should have at least one waitfortrust condition") let resetAndEstablishExpectation = self.expectation(description: "resetAndEstablish callback occurs") let escrowRequestNotification = expectation(forNotification: OTMockEscrowRequestNotification, @@ -143,16 +147,18 @@ class OctagonResetTests: OctagonTestsBase { } func testOctagonResetAlsoResetsCKKSViewsMissingTLKs() { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() - let zoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys + let zoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys XCTAssertNotNil(zoneKeys, "Should have some zone keys") XCTAssertNotNil(zoneKeys?.tlk, "Should have a tlk in the original key set") self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) self.silentZoneDeletesAllowed = true @@ -162,9 +168,9 @@ class OctagonResetTests: OctagonTestsBase { XCTFail("failed to make new friends: \(error)") } - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - let laterZoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys + let laterZoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys XCTAssertNotNil(laterZoneKeys, "Should have some zone keys") XCTAssertNotNil(laterZoneKeys?.tlk, "Should have a tlk in the newly created keyset") XCTAssertNotEqual(zoneKeys?.tlk?.uuid, laterZoneKeys?.tlk?.uuid, "CKKS zone should now have different keys") @@ -172,23 +178,39 @@ class OctagonResetTests: OctagonTestsBase { func testOctagonResetIgnoresOldRemoteDevicesWithKeysAndResetsCKKS() { // CKKS has no keys, and there's another device claiming to have them already, but it's old - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() + #if !os(tvOS) (self.zones![self.manateeZoneID!]! as! FakeCKZone).currentDatabase.allValues.forEach { record in let r = record as! CKRecord - if(r.recordType == SecCKRecordDeviceStateType) { + if r.recordType == SecCKRecordDeviceStateType { + r.creationDate = NSDate.distantPast + r.modificationDate = NSDate.distantPast + } + } + #endif + (self.zones![self.limitedPeersAllowedZoneID!]! as! FakeCKZone).currentDatabase.allValues.forEach { record in + let r = record as! CKRecord + if r.recordType == SecCKRecordDeviceStateType { r.creationDate = NSDate.distantPast r.modificationDate = NSDate.distantPast } } + #if !os(tvOS) let zoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys - XCTAssertNotNil(zoneKeys, "Should have some zone keys") - XCTAssertNotNil(zoneKeys?.tlk, "Should have a tlk in the original key set") + XCTAssertNotNil(zoneKeys, "Should have some zone keys for Manatee") + XCTAssertNotNil(zoneKeys?.tlk, "Should have a tlk in the original key set for Manatee") + #endif + + let lpZoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys + XCTAssertNotNil(lpZoneKeys, "Should have some zone keys for LimitedPeers") + XCTAssertNotNil(lpZoneKeys?.tlk, "Should have a tlk in the original key set for LimitedPeers") self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.silentZoneDeletesAllowed = true @@ -199,25 +221,43 @@ class OctagonResetTests: OctagonTestsBase { XCTFail("failed to make new friends: \(error)") } - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + #if !os(tvOS) let laterZoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys - XCTAssertNotNil(laterZoneKeys, "Should have some zone keys") - XCTAssertNotNil(laterZoneKeys?.tlk, "Should have a tlk in the newly created keyset") - XCTAssertNotEqual(zoneKeys?.tlk?.uuid, laterZoneKeys?.tlk?.uuid, "CKKS zone should now have different keys") + XCTAssertNotNil(laterZoneKeys, "Should have some zone keys for Manatee") + XCTAssertNotNil(laterZoneKeys?.tlk, "Should have a tlk in the newly created keyset for Manatee") + XCTAssertNotEqual(zoneKeys?.tlk?.uuid, laterZoneKeys?.tlk?.uuid, "CKKS zone should now have different keys for Manatee") + #else + let laterZoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys + XCTAssertNil(laterZoneKeys, "Should have no Manatee zone keys for aTV") + #endif + + let laterLpZoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys + XCTAssertNotNil(laterLpZoneKeys, "Should have some zone keys for LimitedPeers") + XCTAssertNotNil(laterLpZoneKeys?.tlk, "Should have a tlk in the newly created keyset for LimitedPeers") + XCTAssertNotEqual(lpZoneKeys?.tlk?.uuid, laterLpZoneKeys?.tlk?.uuid, "CKKS zone should now have different keys for LimitedPeers") } func testOctagonResetWithRemoteDevicesWithKeysDoesNotResetCKKS() { - // CKKS has no keys, and there's another device claiming to have them already, so CKKS won't immediately reset it - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + // CKKS has no keys, and there's another device claiming to have them already, so CKKS won't immediately reset it. + // But, Octagon will! + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() + #if !os(tvOS) let zoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys XCTAssertNotNil(zoneKeys, "Should have some zone keys") XCTAssertNotNil(zoneKeys?.tlk, "Should have a tlk in the original key set") + #endif + + let lpZoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys + XCTAssertNotNil(lpZoneKeys, "Should have some zone keys for LimitedPeers") + XCTAssertNotNil(lpZoneKeys?.tlk, "Should have a tlk in the original key set for LimitedPeers") self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.silentZoneDeletesAllowed = true @@ -228,25 +268,42 @@ class OctagonResetTests: OctagonTestsBase { XCTFail("failed to make new friends: \(error)") } - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + #if !os(tvOS) let laterZoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys XCTAssertNotNil(laterZoneKeys, "Should have some zone keys") XCTAssertNotNil(laterZoneKeys?.tlk, "Should have a tlk in the newly created keyset") - XCTAssertEqual(zoneKeys?.tlk?.uuid, laterZoneKeys?.tlk?.uuid, "CKKS zone should now have the same keys") + XCTAssertNotEqual(zoneKeys?.tlk?.uuid, laterZoneKeys?.tlk?.uuid, "CKKS zone should not have the same keys - a reset should have occurred") + #else + let laterZoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys + XCTAssertNil(laterZoneKeys, "Should have no Manatee zone keys for aTV") + #endif + + let lpLaterZoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys + XCTAssertNotNil(lpLaterZoneKeys, "Should have some zone keys for LimitedPeersAllowed") + XCTAssertNotNil(lpLaterZoneKeys?.tlk, "Should have a tlk in the newly created keyset for LimitedPeersAllowed") + XCTAssertNotEqual(lpZoneKeys?.tlk?.uuid, lpLaterZoneKeys?.tlk?.uuid, "CKKS zone should not have the same keys for LimitedPeersAllowed - a reset should have occurred") } func testOctagonResetWithTLKsDoesNotResetCKKS() { // CKKS has the keys keys - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.saveTLKMaterialToKeychain() + #if !os(tvOS) let zoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys XCTAssertNotNil(zoneKeys, "Should have some zone keys") XCTAssertNotNil(zoneKeys?.tlk, "Should have a tlk in the original key set") + #endif + + let lpZoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys + XCTAssertNotNil(lpZoneKeys, "Should have some zone keys for LimitedPeers") + XCTAssertNotNil(lpZoneKeys?.tlk, "Should have a tlk in the original key set for LimitedPeers") self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -258,10 +315,20 @@ class OctagonResetTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + #if !os(tvOS) let laterZoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys XCTAssertNotNil(laterZoneKeys, "Should have some zone keys") XCTAssertNotNil(laterZoneKeys?.tlk, "Should have a tlk in the newly created keyset") XCTAssertEqual(zoneKeys?.tlk?.uuid, laterZoneKeys?.tlk?.uuid, "CKKS zone should now have the same keys") + #else + let laterZoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys + XCTAssertNil(laterZoneKeys, "Should have no Manatee zone keys for aTV") + #endif + + let lpLaterZoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys + XCTAssertNotNil(lpLaterZoneKeys, "Should have some zone keys for LimitedPeersAllowed") + XCTAssertNotNil(lpLaterZoneKeys?.tlk, "Should have a tlk in the newly created keyset for LimitedPeersAllowed") + XCTAssertEqual(lpZoneKeys?.tlk?.uuid, lpLaterZoneKeys?.tlk?.uuid, "CKKS zone should now have the same keys for LimitedPeersAllowed") } func testOctagonResetAndEstablishFail() throws { @@ -269,6 +336,7 @@ class OctagonResetTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) _ = try self.cuttlefishContext.accountAvailable("13453464") @@ -291,12 +359,26 @@ class OctagonResetTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() + + // And after this reset, can we put together an escrow record? + let escrowContentsExpectation = self.expectation(description: "fetchEscrowContents") + self.cuttlefishContext.fetchEscrowContents { entropy, bottleID, signingPubKey, error in + XCTAssertNil(error, "Should be no error fetching escrow contents") + + XCTAssertNotNil(entropy, "Should have some entropy") + XCTAssertNotNil(bottleID, "Should have some bottleID") + XCTAssertNotNil(signingPubKey, "Should have some signing public key") + + escrowContentsExpectation.fulfill() + } + self.wait(for: [escrowContentsExpectation], timeout: 10) } func testResetReasonUnknown() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) _ = try self.cuttlefishContext.accountAvailable("13453464") @@ -322,13 +404,14 @@ class OctagonResetTests: OctagonTestsBase { } func testResetReasonUserInitiatedReset() throws { - // Make sure if establish fail we end up in untrusted instead of error - self.startCKAccountStatusMock() + // Make sure if establish fail we end up in untrusted instead of error + self.startCKAccountStatusMock() - self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - _ = try self.cuttlefishContext.accountAvailable("13453464") + _ = try self.cuttlefishContext.accountAvailable("13453464") let resetExpectation = self.expectation(description: "resetExpectation") @@ -366,19 +449,11 @@ class OctagonResetTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) _ = try self.cuttlefishContext.accountAvailable("13453464") - let resetExpectation = self.expectation(description: "resetExpectation") - - self.fakeCuttlefishServer.resetListener = { request in - self.fakeCuttlefishServer.resetListener = nil - resetExpectation.fulfill() - XCTAssertTrue(request.resetReason.rawValue == CuttlefishResetReason.recoveryKey.rawValue, "reset reason should be recovery key") - return nil - } - let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") @@ -388,15 +463,42 @@ class OctagonResetTests: OctagonTestsBase { newCliqueContext.altDSID = self.mockAuthKit.altDSID! newCliqueContext.otControl = self.otControl + // Calling with an unknown RK only resets if the local device is SOS capable, so pretend it is + OctagonSetSOSFeatureEnabled(false) + #if os(macOS) || os(iOS) + OctagonSetPlatformSupportsSOS(true) + self.manager.setSOSEnabledForPlatformFlag(true) + + let resetExpectation = self.expectation(description: "resetExpectation") + + self.fakeCuttlefishServer.resetListener = { request in + self.fakeCuttlefishServer.resetListener = nil + resetExpectation.fulfill() + XCTAssertTrue(request.resetReason.rawValue == CuttlefishResetReason.recoveryKey.rawValue, "reset reason should be recovery key") + return nil + } + #else + self.manager.setSOSEnabledForPlatformFlag(false) + OctagonSetPlatformSupportsSOS(false) + #endif + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") TestsObjectiveC.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey) { error in + #if os(macOS) || os(iOS) XCTAssertNil(error, "error should be nil") + #else + XCTAssertNotNil(error, "error should not be nil") + #endif joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) - self.wait(for: [resetExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + #if os(macOS) || os(iOS) + self.wait(for: [resetExpectation], timeout: 10) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + #else + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + #endif self.verifyDatabaseMocks() } @@ -404,6 +506,7 @@ class OctagonResetTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let initiatorContext = self.manager.context(forContainerName: OTCKContainerName, @@ -439,15 +542,14 @@ class OctagonResetTests: OctagonTestsBase { throw error } self.wait(for: [resetExpectation], timeout: 10) - } func testResetReasonHealthCheck() throws { - let containerName = OTCKContainerName let contextName = OTDefaultContext self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.startCKAccountStatusMock() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) @@ -493,26 +595,24 @@ class OctagonResetTests: OctagonTestsBase { } self.wait(for: [healthCheckCallback, resetExpectation], timeout: 10) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() let dumpCallback = self.expectation(description: "dumpCallback callback occurs") - self.tphClient.dump(withContainer: containerName, context: contextName) { - dump, _ in + self.tphClient.dump(withContainer: containerName, context: contextName) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") dumpCallback.fulfill() } self.wait(for: [dumpCallback], timeout: 10) - - self.verifyDatabaseMocks() - self.assertEnters(context: cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) } func testLegacyJoinCircleDoesNotReset() throws { self.cuttlefishContext.startOctagonStateMachine() self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) @@ -556,6 +656,7 @@ class OctagonResetTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) _ = try self.cuttlefishContext.accountAvailable("13453464") @@ -579,6 +680,165 @@ class OctagonResetTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() } + + func testCliqueResetAllSPI() throws { + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + OctagonSetSOSFeatureEnabled(false) + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let establishAndResetExpectation = self.expectation(description: "resetExpectation") + let clique: OTClique + let otcliqueContext = OTConfigurationContext() + var firstCliqueIdentifier: String? + + otcliqueContext.context = OTDefaultContext + otcliqueContext.dsid = "13453464" + otcliqueContext.altDSID = self.mockAuthKit.altDSID! + otcliqueContext.authenticationAppleID = "appleID" + otcliqueContext.passwordEquivalentToken = "petpetpetpetpet" + otcliqueContext.otControl = self.otControl + otcliqueContext.ckksControl = self.ckksControl + otcliqueContext.sbd = OTMockSecureBackup(bottleID: nil, entropy: nil) + + do { + clique = try OTClique.newFriends(withContextData: otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + firstCliqueIdentifier = clique.cliqueMemberIdentifier + establishAndResetExpectation.fulfill() + } catch { + XCTFail("Shouldn't have errored making new friends everything: \(error)") + throw error + } + self.wait(for: [establishAndResetExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + self.silentZoneDeletesAllowed = true + + let newClique: OTClique + do { + newClique = try OTClique.resetProtectedData(otcliqueContext) + XCTAssertNotEqual(newClique.cliqueMemberIdentifier, firstCliqueIdentifier, "clique identifiers should be different") + } catch { + XCTFail("Shouldn't have errored resetting everything: \(error)") + throw error + } + XCTAssertNotNil(newClique, "newClique should not be nil") + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + } + + func testCliqueResetProtectedDataHandlingInMultiPeerCircle() throws { + OctagonSetSOSFeatureEnabled(false) + self.startCKAccountStatusMock() + + var firstCliqueIdentifier: String? + + let clique: OTClique + let cliqueContextConfiguration = OTConfigurationContext() + cliqueContextConfiguration.context = OTDefaultContext + cliqueContextConfiguration.dsid = "13453464" + cliqueContextConfiguration.altDSID = self.mockAuthKit.altDSID! + cliqueContextConfiguration.authenticationAppleID = "appleID" + cliqueContextConfiguration.passwordEquivalentToken = "petpetpetpetpet" + cliqueContextConfiguration.otControl = self.otControl + cliqueContextConfiguration.ckksControl = self.ckksControl + cliqueContextConfiguration.sbd = OTMockSecureBackup(bottleID: nil, entropy: nil) + do { + clique = try OTClique.newFriends(withContextData: cliqueContextConfiguration, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + firstCliqueIdentifier = clique.cliqueMemberIdentifier + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + + let entropy = try self.loadSecret(label: clique.cliqueMemberIdentifier!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + let bottleJoinerContextID = "bottleJoiner" + let joinerContext = self.manager.context(forContainerName: OTCKContainerName, contextID: bottleJoinerContextID) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + joinerContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: joinerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + // Before you call joinWithBottle, you need to call fetchViableBottles. + let fetchViableExpectation = self.expectation(description: "fetchViableBottles callback occurs") + joinerContext.rpcFetchAllViableBottles { viable, _, error in + XCTAssertNil(error, "should be no error fetching viable bottles") + XCTAssert(viable?.contains(bottle.bottleID) ?? false, "The bottle we're about to restore should be viable") + fetchViableExpectation.fulfill() + } + self.wait(for: [fetchViableExpectation], timeout: 10) + + let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") + joinerContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.mockAuthKit.altDSID!) { error in + XCTAssertNil(error, "error should be nil") + joinWithBottleExpectation.fulfill() + } + + self.wait(for: [joinWithBottleExpectation], timeout: 10) + + self.assertEnters(context: joinerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: joinerContext) + + self.silentZoneDeletesAllowed = true + + let newClique: OTClique + do { + newClique = try OTClique.resetProtectedData(cliqueContextConfiguration) + XCTAssertNotEqual(newClique.cliqueMemberIdentifier, firstCliqueIdentifier, "clique identifiers should be different") + } catch { + XCTFail("Shouldn't have errored resetting everything: \(error)") + throw error + } + XCTAssertNotNil(newClique, "newClique should not be nil") + + self.sendContainerChangeWaitForFetchForStates(context: joinerContext, states: [OctagonStateUntrusted]) + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, states: [OctagonStateReady]) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + + let statusExpectation = self.expectation(description: "status callback occurs") + let configuration = OTOperationConfiguration() + + joinerContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, _ in + XCTAssertEqual(.notIn, egoStatus, "cliqueStatus should be 'Not In'") + statusExpectation.fulfill() + } + self.wait(for: [statusExpectation], timeout: 10) + } + + func testAcceptResetRemovesSelfPeer() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + let otherPeer = self.makeInitiatorContext(contextID: "peer2") + self.assertResetAndBecomeTrusted(context: otherPeer) + + // And we get told about the reset + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, + states: [OctagonStateReadyUpdated, + OctagonStateUntrusted, ]) + + XCTAssertEqual(self.cuttlefishContext.stateMachine.paused.wait(5 * NSEC_PER_SEC), 0, "State machine should have paused") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 1 * NSEC_PER_SEC) + } } #endif // OCTAGON diff --git a/keychain/ot/tests/octagon/OctagonTests+SOS.swift b/keychain/ot/tests/octagon/OctagonTests+SOS.swift index a239ad9b..b1640e56 100644 --- a/keychain/ot/tests/octagon/OctagonTests+SOS.swift +++ b/keychain/ot/tests/octagon/OctagonTests+SOS.swift @@ -1,11 +1,10 @@ #if OCTAGON class OctagonSOSTests: OctagonTestsBase { - func testSOSOctagonKeyConsistency() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() @@ -53,9 +52,9 @@ class OctagonSOSTests: OctagonTestsBase { } func testSOSOctagonKeyConsistencyLocked() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() @@ -67,11 +66,13 @@ class OctagonSOSTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() self.waitForCKModifications() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) let peerID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() @@ -85,8 +86,6 @@ class OctagonSOSTests: OctagonTestsBase { self.aksLockState = true self.lockStateTracker.recheck() - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - // Now restart the context self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) self.restartCKKSViews() @@ -115,26 +114,27 @@ class OctagonSOSTests: OctagonTestsBase { } func testSOSOctagonKeyConsistencySucceedsAfterUpdatingSOS() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID!) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID!) - self.saveTLKMaterial(toKeychain: self.manateeZoneID!) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") + self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() self.waitForCKModifications() self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) let peerID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() XCTAssertNotNil(peerID, "Should have a peer ID") @@ -144,11 +144,6 @@ class OctagonSOSTests: OctagonTestsBase { self.mockSOSAdapter.trustedPeers.add(newSOSPeer) - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) - self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - // Now restart the context self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) self.restartCKKSViews() @@ -160,7 +155,7 @@ class OctagonSOSTests: OctagonTestsBase { self.lockStateTracker.recheck() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) self.assertAllCKKSViewsUpload(tlkShares: 2) self.aksLockState = false @@ -176,7 +171,7 @@ class OctagonSOSTests: OctagonTestsBase { self.verifyDatabaseMocks() self.waitForCKModifications() - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } func testSOSPerformOctagonKeyConsistencyOnCircleChange() throws { @@ -241,11 +236,16 @@ class OctagonSOSTests: OctagonTestsBase { XCTAssertNotNil(error, "error should not be nil") } + /* + * I don't see any way in swift to call a deprecated API. + * But, since we're not actually testing behavior here, it's + * okay to ignore. do { try clique.safariPasswordSyncingEnabled() } catch { XCTAssertNotNil(error, "error should not be nil") } + */ do { try clique.waitForInitialSync() @@ -253,7 +253,12 @@ class OctagonSOSTests: OctagonTestsBase { XCTAssertNotNil(error, "error should not be nil") } + /* + * I don't see any way in swift to call a deprecated API. + * But, since we're not actually testing behavior here, it's + * okay to ignore. clique.viewSet(Set(), disabledViews: Set()) + */ do { try clique.setUserCredentialsAndDSID("", password: Data()) @@ -292,6 +297,221 @@ class OctagonSOSTests: OctagonTestsBase { XCTAssertNotNil(error, "error should not be nil") } } + + func testPreapproveSOSPeersWhenInCircle() throws { + self.startCKAccountStatusMock() + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + let peer1Preapproval = TPHashBuilder.hash(with: .SHA256, of: self.mockSOSAdapter.selfPeer.publicSigningKey.encodeSubjectPublicKeyInfo()) + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + let peer2Preapproval = TPHashBuilder.hash(with: .SHA256, of: peer2SOSMockPeer.publicSigningKey.encodeSubjectPublicKeyInfo()) + + let peer3SOSMockPeer = self.createSOSPeer(peerID: "peer3ID") + self.mockSOSAdapter.trustedPeers.add(peer3SOSMockPeer) + let peer3Preapproval = TPHashBuilder.hash(with: .SHA256, of: peer3SOSMockPeer.publicSigningKey.encodeSubjectPublicKeyInfo()) + + let establishTwiceExpectation = self.expectation(description: "establish should be called twice") + establishTwiceExpectation.expectedFulfillmentCount = 2 + + self.fakeCuttlefishServer.establishListener = { request in + XCTAssertTrue(request.hasPeer, "establish request should have a peer") + + let newDynamicInfo = TPPeerDynamicInfo(data: request.peer.dynamicInfoAndSig.peerDynamicInfo, sig: request.peer.dynamicInfoAndSig.sig) + XCTAssertNotNil(newDynamicInfo, "should be able to make a dynamicInfo from protobuf") + + XCTAssertTrue(newDynamicInfo?.preapprovals.contains(peer2Preapproval) ?? false, "Fake peer 2 should be preapproved") + XCTAssertTrue(newDynamicInfo?.preapprovals.contains(peer3Preapproval) ?? false, "Fake peer 3 should be preapproved") + + establishTwiceExpectation.fulfill() + return nil + } + + self.assertAllCKKSViewsUpload(tlkShares: 3) + + // Just starting the state machine is sufficient; it should perform an SOS upgrade + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // And a reset does the right thing with preapprovals as well + do { + let arguments = OTConfigurationContext() + arguments.altDSID = try self.cuttlefishContext.authKitAdapter.primaryiCloudAccountAltDSID() + arguments.context = self.cuttlefishContext.contextID + arguments.otControl = self.otControl + + let clique = try OTClique.newFriends(withContextData: arguments, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + self.wait(for: [establishTwiceExpectation], timeout: 1) + + // And do we do the right thing when joining via SOS preapproval? + let peer2JoinExpectation = self.expectation(description: "join called") + self.fakeCuttlefishServer.joinListener = { request in + XCTAssertTrue(request.hasPeer, "establish request should have a peer") + + let newDynamicInfo = TPPeerDynamicInfo(data: request.peer.dynamicInfoAndSig.peerDynamicInfo, sig: request.peer.dynamicInfoAndSig.sig) + XCTAssertNotNil(newDynamicInfo, "should be able to make a dynamicInfo from protobuf") + + XCTAssertFalse(newDynamicInfo?.preapprovals.contains(peer1Preapproval) ?? false, "Fake peer 1 should NOT be preapproved by peer2 (as it's already in Octagon)") + XCTAssertTrue(newDynamicInfo?.preapprovals.contains(peer3Preapproval) ?? false, "Fake peer 3 should be preapproved by peer2") + + peer2JoinExpectation.fulfill() + + return nil + } + + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + + self.wait(for: [peer2JoinExpectation], timeout: 1) + } + + func testDoNotPreapproveSOSPeerWhenOutOfCircle() throws { + self.startCKAccountStatusMock() + + // SOS returns 'trusted' peers without actually being in-circle + // We don't want to preapprove those peers + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCNotInCircle) + let peer1Preapproval = TPHashBuilder.hash(with: .SHA256, of: self.mockSOSAdapter.selfPeer.publicSigningKey.encodeSubjectPublicKeyInfo()) + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + let peer2Preapproval = TPHashBuilder.hash(with: .SHA256, of: peer2SOSMockPeer.publicSigningKey.encodeSubjectPublicKeyInfo()) + + let peer3SOSMockPeer = self.createSOSPeer(peerID: "peer3ID") + self.mockSOSAdapter.trustedPeers.add(peer3SOSMockPeer) + let peer3Preapproval = TPHashBuilder.hash(with: .SHA256, of: peer3SOSMockPeer.publicSigningKey.encodeSubjectPublicKeyInfo()) + + self.fakeCuttlefishServer.establishListener = { request in + XCTAssertTrue(request.hasPeer, "establish request should have a peer") + + let newDynamicInfo = TPPeerDynamicInfo(data: request.peer.dynamicInfoAndSig.peerDynamicInfo, sig: request.peer.dynamicInfoAndSig.sig) + XCTAssertNotNil(newDynamicInfo, "should be able to make a dynamicInfo from protobuf") + + XCTAssertFalse(newDynamicInfo?.preapprovals.contains(peer2Preapproval) ?? false, "Fake peer 2 should not be preapproved") + XCTAssertFalse(newDynamicInfo?.preapprovals.contains(peer3Preapproval) ?? false, "Fake peer 3 should not be preapproved") + + return nil + } + + self.assertResetAndBecomeTrustedInDefaultContext() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + self.verifyDatabaseMocks() + + // And do we do the right thing when joining via bottle? + let peer2JoinExpectation = self.expectation(description: "join called") + self.fakeCuttlefishServer.joinListener = { request in + XCTAssertTrue(request.hasPeer, "establish request should have a peer") + + let newDynamicInfo = TPPeerDynamicInfo(data: request.peer.dynamicInfoAndSig.peerDynamicInfo, sig: request.peer.dynamicInfoAndSig.sig) + XCTAssertNotNil(newDynamicInfo, "should be able to make a dynamicInfo from protobuf") + + XCTAssertFalse(newDynamicInfo?.preapprovals.contains(peer1Preapproval) ?? false, "Fake peer 1 should NOT be preapproved by peer2 (as it's not in SOS)") + XCTAssertFalse(newDynamicInfo?.preapprovals.contains(peer3Preapproval) ?? false, "Fake peer 3 should not be preapproved by peer2 (as it's not in SOS)") + + peer2JoinExpectation.fulfill() + + return nil + } + + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + peer2mockSOS.circleStatus = SOSCCStatus(kSOSCCNotInCircle) + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + + _ = self.assertJoinViaEscrowRecovery(joiningContext: peer2, sponsor: self.cuttlefishContext) + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + + self.wait(for: [peer2JoinExpectation], timeout: 1) + } + + func testRespondToNewOctagonPeerWhenUpdatingPreapprovedKeys() throws { + self.startCKAccountStatusMock() + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + let peer1Preapproval = TPHashBuilder.hash(with: .SHA256, of: self.mockSOSAdapter.selfPeer.publicSigningKey.encodeSubjectPublicKeyInfo()) + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + let peer2Preapproval = TPHashBuilder.hash(with: .SHA256, of: peer2SOSMockPeer.publicSigningKey.encodeSubjectPublicKeyInfo()) + + self.assertAllCKKSViewsUpload(tlkShares: 2) + + // Just starting the state machine is sufficient; it should perform an SOS upgrade + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + let peer1ID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // Another peer arrives, but we miss the Octagon push + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let joiningContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + let peer2ID = self.assertJoinViaEscrowRecovery(joiningContext: joiningContext, sponsor: self.cuttlefishContext) + + // Now, SOS updates its key list: we should update our preapproved keys (and then also trust the newly-joined peer) + let peer3SOSMockPeer = self.createSOSPeer(peerID: "peer3ID") + self.mockSOSAdapter.trustedPeers.add(peer3SOSMockPeer) + let peer3Preapproval = TPHashBuilder.hash(with: .SHA256, of: peer3SOSMockPeer.publicSigningKey.encodeSubjectPublicKeyInfo()) + + let updateKeysExpectation = self.expectation(description: "UpdateTrust should fire (once)") + self.fakeCuttlefishServer.updateListener = { [unowned self] request in + XCTAssertEqual(request.peerID, peer1ID, "UpdateTrust should be for peer1") + + let newDynamicInfo = request.dynamicInfoAndSig.dynamicInfo() + + XCTAssertFalse(newDynamicInfo.preapprovals.contains(peer1Preapproval), "Fake peer 1 should NOT be preapproved by peer1 (as it's its own keys)") + XCTAssertTrue(newDynamicInfo.preapprovals.contains(peer2Preapproval), "Fake peer 2 should be preapproved by original peer") + XCTAssertTrue(newDynamicInfo.preapprovals.contains(peer3Preapproval), "Fake peer 3 should be preapproved by original peer") + + self.fakeCuttlefishServer.updateListener = nil + updateKeysExpectation.fulfill() + + return nil + } + + // And we'll send TLKShares to the new SOS peer and the new Octagon peer + self.assertAllCKKSViewsUpload(tlkShares: 2) + + // to avoid CKKS race conditions (wherein it uploads each TLKShare in its own operation), send the SOS notification only to the Octagon context + //self.mockSOSAdapter.sendTrustedPeerSetChangedUpdate() + self.cuttlefishContext.trustedPeerSetChanged(self.mockSOSAdapter) + self.wait(for: [updateKeysExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer1ID)), + "peer 1 should trust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), + "peer 1 should trust peer 2") + } } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+SOSUpgrade.swift b/keychain/ot/tests/octagon/OctagonTests+SOSUpgrade.swift index f1a10e25..7661d0cd 100644 --- a/keychain/ot/tests/octagon/OctagonTests+SOSUpgrade.swift +++ b/keychain/ot/tests/octagon/OctagonTests+SOSUpgrade.swift @@ -2,9 +2,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { func testSOSUpgrade() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -33,14 +33,27 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.verifyDatabaseMocks() self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + // Also, CKKS should be configured with the prevailing policy version + XCTAssertNotNil(self.injectedManager?.policy, "Should have given CKKS a TPPolicy during SOS upgrade") + XCTAssertEqual(self.injectedManager?.policy?.version, prevailingPolicyVersion, "Policy given to CKKS should be prevailing policy") + + // And we should have followed the SOS Safari view state + XCTAssertTrue(self.mockSOSAdapter.safariViewEnabled, "SOS adapter should say that the safari view is enabled") + + // And we should have told SOS that CKKS4All is on + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + + let clique = self.cliqueFor(context: self.cuttlefishContext) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) } // Verify that an SOS upgrade only does one establish (and no update trust). func testSOSUpgradeUpdateNoUpdateTrust() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -74,9 +87,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } func testSOSUpgradeAuthkitError() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID!) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID!) - self.saveTLKMaterial(toKeychain: self.manateeZoneID!) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -116,9 +129,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { // Test that we tries to perform SOS upgrade once we unlock device again // - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -148,9 +161,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { func testSOSUpgradeDuringNetworkOutage() throws { // Test that we tries to perform SOS upgrade after a bit after a failure - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -182,9 +195,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { func testSOSUpgradeStopsIfSplitGraph() throws { // Test that we tries to perform SOS upgrade after a bit after a failure - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -204,6 +217,8 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.wait(for: [establishExpectation], timeout: 10) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + XCTAssertFalse(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should not have been told that CKKS4All is enabled") + // It should be paused XCTAssertEqual(self.cuttlefishContext.stateMachine.possiblePendingFlags(), [], "Should have zero pending flags after 'not reachable'") } @@ -227,7 +242,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.assertEnters(context: peer2, state: OctagonStateReady, within: 100 * NSEC_PER_SEC) // Now we arrive, and attempt to SOS join - let sosUpgradeStateCondition = self.cuttlefishContext.stateMachine.stateConditions[OctagonStateAttemptSOSUpgrade] as! CKKSCondition + let sosUpgradeStateCondition : CKKSCondition = self.cuttlefishContext.stateMachine.stateConditions[OctagonStateAttemptSOSUpgrade]! self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) self.cuttlefishContext.startOctagonStateMachine() @@ -242,8 +257,8 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } func testSOSUpgradeWithNoTLKs() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() self.startCKAccountStatusMock() @@ -262,11 +277,11 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { func testsSOSUpgradeWithCKKSConflict() throws { // Right after CKKS fetches for the first time, insert a new key hierarchy into CloudKit self.silentFetchesAllowed = false - self.expectCKFetchAndRun(beforeFinished: { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + self.expectCKFetchAndRun { + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() self.silentFetchesAllowed = true - }) + } self.startCKAccountStatusMock() @@ -282,8 +297,92 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC) } + func testDontSOSUpgradeIfWouldRemovePreapprover() throws { + // If a remote peer resets Octagon, they might preapprove the local device's SOS identity. + // But, if the local device responds to the reset and rejoins, it might not have received the + // SOS circle containing the remote peer. + // + // In that case, it should accept its kicked-out fate and not rejoin (and kick out the reset device). + + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.startCKAccountStatusMock() + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.verifyDatabaseMocks() + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + // Now, peer2 comes along, and resets the world + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + // but note: this peer is not yet added to the mockSOSAdapter + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, + trustedPeers: self.mockSOSAdapter.allPeers(), + essential: false) + let peer2 = self.makeInitiatorContext(contextID: "peer2", + authKitAdapter: self.mockAuthKit2, + sosAdapter: peer2mockSOS) + + self.assertResetAndBecomeTrusted(context: peer2) + + // Peer1 should accept the reset, and not rejoin. + self.fakeCuttlefishServer.joinListener = { _ in + XCTFail("Should not have attemped to re-join") + return nil + } + + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, + states: [OctagonStateReadyUpdated, + OctagonStateBecomeUntrusted, + OctagonStateAttemptSOSUpgrade, + OctagonStateUntrusted, ]) + + XCTAssertEqual(self.cuttlefishContext.stateMachine.paused.wait(5 * NSEC_PER_SEC), 0, "State machine should have paused") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 1 * NSEC_PER_SEC) + + // But when SOS does catch up, we join just fine. + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + self.assertAllCKKSViewsUpload(tlkShares: 2) + + self.fakeCuttlefishServer.joinListener = { joinRequest in + let newDynamicInfo = joinRequest.peer.dynamicInfoAndSig.dynamicInfo() + XCTAssertEqual(newDynamicInfo.includedPeerIDs.count, 2, "Peer should trust two identities") + return nil + } + + self.mockSOSAdapter.sendTrustedPeerSetChangedUpdate() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + + self.verifyDatabaseMocks() + } + + func testDontSOSUpgradeIfErrorFetchingPeers() throws { + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.mockSOSAdapter.trustedPeersError = NSError(domain: NSOSStatusErrorDomain, + code: 1) + self.startCKAccountStatusMock() + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateAttemptSOSUpgrade, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + } + func testSOSJoin() throws { - if(!OctagonPerformSOSUpgrade()) { + if !OctagonPerformSOSUpgrade() { return } self.startCKAccountStatusMock() @@ -310,6 +409,10 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() + XCTAssertTrue(self.mockSOSAdapter.safariViewEnabled, "SOS adapter should say that the safari view is enabled") + let clique = self.cliqueFor(context: self.cuttlefishContext) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + // Peer1 should have sent a request for silent escrow update self.wait(for: [peer1EscrowRequestNotification], timeout: 5) @@ -336,6 +439,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: peer2) + XCTAssertTrue(peer2mockSOS.safariViewEnabled, "SOS adapter should say that the safari view is enabled") + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2), status: true) + // Peer2 should have sent a request for silent escrow update self.wait(for: [peer2EscrowRequestNotification], timeout: 5) @@ -350,19 +456,115 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { "peer 1 should not trust peer 2 (as it hasn't responded to peer2's upgradeJoin yet)") // Now, tell peer1 about the change + self.assertAllCKKSViewsUpload(tlkShares: 1) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) // Peer1 should trust peer2 now, since it upgraded it from implicitly explicitly trusted XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), "peer 1 should trust peer 2 after update") XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles") + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + } + + func testSOSJoinWithDisabledSafariView() throws { + self.startCKAccountStatusMock() + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.mockSOSAdapter.safariViewEnabled = false + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + + self.assertAllCKKSViewsUpload(tlkShares: 2) + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + let clique = self.cliqueFor(context: self.cuttlefishContext) + + XCTAssertFalse(self.mockSOSAdapter.safariViewEnabled, "SOS adapter should say that the safari view is disabled") + + #if os(tvOS) + // TVs won't ever turn this off + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + // Watches don't have SOS, but in this test, we fake that they do. They should follow "SOS"'s state, just like phones and macs + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, + trustedPeers: self.mockSOSAdapter.allPeers(), + essential: false) + peer2mockSOS.safariViewEnabled = false + + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + + #if os(tvOS) + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2), status: true) + #else + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2), status: false) + #endif + } + + func testSOSJoinWithEnabledSafariViewButDisabledByPeer() throws { + self.startCKAccountStatusMock() + + // This peer joins with disabled user views + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.mockSOSAdapter.safariViewEnabled = false + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + + self.assertAllCKKSViewsUpload(tlkShares: 2) + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + XCTAssertFalse(self.mockSOSAdapter.safariViewEnabled, "SOS adapter should say that the safari view is disabled") + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) + // TVs won't ever turn this off + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + // Watches don't have SOS, but in this test, we fake that they do. They should follow "SOS"'s state, just like phones and macs + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, + trustedPeers: self.mockSOSAdapter.allPeers(), + essential: false) + // peer2 joins via SOS preapproval, but with the safari view enabled. It should enable user view syncing, even though the other peer has it off + peer2mockSOS.safariViewEnabled = true + + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2), status: true) } func testSOSJoinUponNotificationOfPreapproval() throws { // Peer 1 becomes SOS+Octagon - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -378,8 +580,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { XCTAssertNotNil(peerID, "Should have a peer ID after making new friends") assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") - // Peer 2 attempts to join via preapprovalh + // Peer 2 attempts to join via preapproval let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") let peer2contextID = "peer2" let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) @@ -433,9 +636,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { func testSOSJoinUponNotificationOfPreapprovalRetry() throws { // Peer 1 becomes SOS+Octagon - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID!) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID!) - self.saveTLKMaterial(toKeychain: self.manateeZoneID!) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -452,7 +655,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - // Peer 2 attempts to join via preapprovalh + // Peer 2 attempts to join via preapproval let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") let peer2contextID = "peer2" let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) @@ -495,7 +698,6 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { updateTrustExpectation2.fulfill() return nil - } updateTrustExpectation1.fulfill() @@ -517,9 +719,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { func testSOSJoinUponNotificationOfPreapprovalRetryFail() throws { // Peer 1 becomes SOS+Octagon - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID!) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID!) - self.saveTLKMaterial(toKeychain: self.manateeZoneID!) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -536,7 +738,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - // Peer 2 attempts to join via preapprovalh + // Peer 2 attempts to join via preapproval let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") let peer2contextID = "peer2" let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) @@ -658,6 +860,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.cuttlefishContext.incompleteNotificationOfMachineIDListChange() self.wait(for: [updateTrustExpectation], timeout: 10) + self.verifyDatabaseMocks() assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } @@ -686,16 +889,21 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { // Now, the circle status changes self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.mockSOSAdapter.trustedPeers.add(originalPeerSOSMockPeer) self.cuttlefishContext.startOctagonStateMachine() // Peer1 should upload TLKShares for SOS Peer2 via CK CRUD. We should probably fix that someday? - self.assertAllCKKSViewsUpload(tlkShares: 1) + self.assertAllCKKSViewsUpload(tlkShares: 2) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 40 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() + + // Also, CKKS should be configured with the prevailing policy version + XCTAssertNotNil(self.injectedManager?.policy, "Should have given CKKS a TPPolicy during SOS upgrade") + XCTAssertEqual(self.injectedManager?.policy?.version, prevailingPolicyVersion, "Policy given to CKKS should be prevailing policy") } func testSOSDoNotAttemptUpgradeWhenPlatformDoesntSupport() throws { @@ -704,9 +912,12 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.mockSOSAdapter.sosEnabled = false self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCNotInCircle) - let everEnteredSOSUpgrade: CKKSCondition = self.cuttlefishContext.stateMachine.stateConditions[OctagonStateAttemptSOSUpgrade] as! CKKSCondition + let everEnteredSOSUpgrade: CKKSCondition = self.cuttlefishContext.stateMachine.stateConditions[OctagonStateAttemptSOSUpgrade]! self.cuttlefishContext.startOctagonStateMachine() + + // Cheat and even turn on CDP for the account + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) @@ -727,9 +938,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } func testSosUpgradeAndReady() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() @@ -743,7 +954,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) let upgradeExpectation = self.expectation(description: "waitForOctagonUpgrade") - self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: self.otcliqueContext.context ?? "defaultContext") { error in + self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: self.otcliqueContext.context) { error in XCTAssertNil(error, "operation should not fail") upgradeExpectation.fulfill() } @@ -756,6 +967,92 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + } + + func testNotInSOSCircleAndWaitForUpgrade() throws { + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() + + self.startCKAccountStatusMock() + + self.mockSOSAdapter.sosEnabled = true + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCNotInCircle) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + let upgradeExpectation = self.expectation(description: "waitForOctagonUpgrade") + self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: self.otcliqueContext.context) { error in + XCTAssertNotNil(error, "error should not be nil") + XCTAssertEqual((error! as NSError).domain, "com.apple.security.sos.error", "domain should be com.apple.security.sos.error") + XCTAssertEqual((error! as NSError).code, 1037, "code should be 1037") + upgradeExpectation.fulfill() + } + self.wait(for: [upgradeExpectation], timeout: 2) + } + + func testSosUpgradeFromDisabledCDPStatus() throws { + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() + + self.startCKAccountStatusMock() + + self.mockSOSAdapter.sosEnabled = true + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + + // SOS arrives! + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + + // Attempting the upgrade succeeds, now that SOS is present + let upgradeExpectation = self.expectation(description: "waitForOctagonUpgrade") + self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: self.otcliqueContext.context) { error in + XCTAssertNil(error, "operation should not fail") + upgradeExpectation.fulfill() + } + self.wait(for: [upgradeExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 40 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .enabled, "CDP status should be 'enabled'") + + self.verifyDatabaseMocks() + + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + } + + func testSosUpgradeAPIWhenCDPStateOff() { + // this test checks that calling waitForOctagonUpgrade (when SOS is still absent) doesn't unconditionally set the CDP bit. + self.startCKAccountStatusMock() + + self.mockSOSAdapter.sosEnabled = true + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + + let upgradeExpectation = self.expectation(description: "waitForOctagonUpgrade") + self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: self.otcliqueContext.context) { error in + XCTAssertNotNil(error, "operation should have failed - SOS is absent and Octagon cannot upgrade from it") + XCTAssertEqual((error! as NSError).domain, "com.apple.security.sos.error", "domain should be com.apple.security.sos.error") + XCTAssertEqual((error! as NSError).code, kSOSErrorNoCircle, "code should be kSOSErrorNoCircle") + upgradeExpectation.fulfill() + } + self.wait(for: [upgradeExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) } func testDoNotAttemptUpgradeOnRestart() throws { @@ -772,12 +1069,11 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) self.verifyDatabaseMocks() self.waitForCKModifications() self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) let peerID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() XCTAssertNotNil(peerID, "Should have a peer ID after making new friends") @@ -786,15 +1082,11 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.assertAllCKKSViewsUpload(tlkShares: 1) self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) - self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - - self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() let restartedPeerID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() XCTAssertNotNil(restartedPeerID, "Should have a peer ID after restarting") @@ -803,7 +1095,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } func testSOSJoinAndBottle() throws { - if(!OctagonPerformSOSUpgrade()) { + if !OctagonPerformSOSUpgrade() { return } self.startCKAccountStatusMock() @@ -931,9 +1223,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } func testSOSPeerUpdatePreapprovesNewPeer() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() @@ -989,9 +1281,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } func testSOSPeerUpdateOnRestartAfterMissingNotification() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() @@ -1003,7 +1295,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() self.waitForCKModifications() @@ -1041,13 +1333,12 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) // But, SOS doesn't send this update. Let's test that the upload occurs on the next securityd restart - self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext.startOctagonStateMachine() + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) self.verifyDatabaseMocks() self.wait(for: [updateTrustExpectation], timeout: 10) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) // BUT, a second restart shouldn't hit the server @@ -1055,17 +1346,14 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { XCTFail("shouldn't have updateTrusted") return nil } - self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext.startOctagonStateMachine() - + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) } func testResetAndEstablishDoesNotReuploadSOSTLKShares() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -1125,9 +1413,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } func testResetAndEstablishReusesSOSKeys() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -1148,14 +1436,13 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { let dumpExpectation = self.expectation(description: "dump callback occurs") var encryptionPubKey = Data() var signingPubKey = Data() - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, error in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in XCTAssertNil(error, "Should be no error dumping data") XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let permanentInfo = egoSelf!["permanentInfo"] as? Dictionary + let permanentInfo = egoSelf!["permanentInfo"] as? [String: AnyObject] XCTAssertNotNil(permanentInfo, "should have a permanent info") let epk = permanentInfo!["encryption_pub_key"] as? Data @@ -1186,14 +1473,13 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { // And check that the pub keys are equivalent let dumpResetExpectation = self.expectation(description: "dump callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, error in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in XCTAssertNil(error, "Should be no error dumping data") XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let permanentInfo = egoSelf!["permanentInfo"] as? Dictionary + let permanentInfo = egoSelf!["permanentInfo"] as? [String: AnyObject] XCTAssertNotNil(permanentInfo, "should have a permanent info") let epk = permanentInfo!["encryption_pub_key"] as? Data @@ -1210,9 +1496,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } func testSOSUpgradeWithFailingAuthKit() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") @@ -1226,14 +1512,29 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateAttemptSOSUpgrade, within: 10 * NSEC_PER_SEC) + + let updateChangesExpectation = self.expectation(description: "fetchChanges") + self.fakeCuttlefishServer.fetchChangesListener = { request in + self.fakeCuttlefishServer.fetchChangesReturnEmptyResponse = true + updateChangesExpectation.fulfill() + self.fakeCuttlefishServer.fetchChangesListener = nil + self.mockAuthKit.machineIDFetchErrors.append(NSError(domain: AKAppleIDAuthenticationErrorDomain, + code: AKAppleIDAuthenticationError.authenticationErrorCannotFindServer.rawValue, + userInfo: nil)) + + return nil + } + self.wait(for: [updateChangesExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) } func testCliqueOctagonUpgrade () throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) @@ -1241,29 +1542,27 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { OctagonSetPlatformSupportsSOS(true) - var clique: OTClique? - XCTAssertNoThrow(clique = try OTClique(contextData: self.otcliqueContext)) + let clique = OTClique(contextData: self.otcliqueContext) XCTAssertNotNil(clique, "Clique should not be nil") - XCTAssertNoThrow(try clique!.waitForOctagonUpgrade(), "Upgrading should pass") + XCTAssertNoThrow(try clique.waitForOctagonUpgrade(), "Upgrading should pass") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) } func testCliqueOctagonUpgradeFail () throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putSelfTLKShares(inCloudKit: self.manateeZoneID) - self.saveTLKMaterial(toKeychain: self.manateeZoneID) + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") OctagonSetPlatformSupportsSOS(true) - var clique: OTClique? - XCTAssertNoThrow(clique = try OTClique(contextData: self.otcliqueContext)) + let clique = OTClique(contextData: self.otcliqueContext) XCTAssertNotNil(clique, "Clique should not be nil") - XCTAssertThrowsError(try clique!.waitForOctagonUpgrade(), "Upgrading should fail") + XCTAssertThrowsError(try clique.waitForOctagonUpgrade(), "Upgrading should fail") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) @@ -1323,7 +1622,6 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trustsByPreapproval, target: peer2ID)), "peer 1 should trust peer 3 by preapproval") - XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer1ID)), "peer 2 should trust peer 1") XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer3ID)), @@ -1359,7 +1657,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { // And if peer3 decides to reupgrade, but it shouldn't: there's no potentially-trusted peer that preapproves it let upgradeExpectation = self.expectation(description: "sosUpgrade call returns") - peer3.attemptSOSUpgrade() { error in + peer3.waitForOctagonUpgrade { error in XCTAssertNotNil(error, "should be an error performing an SOS upgrade (the second time)") upgradeExpectation.fulfill() } @@ -1371,12 +1669,86 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { // And "wait for upgrade" does something reasonable too let upgradeWaitExpectation = self.expectation(description: "sosWaitForUpgrade call returns") - peer3.waitForOctagonUpgrade() { error in + peer3.waitForOctagonUpgrade { error in XCTAssertNotNil(error, "should be an error waiting for an SOS upgrade (the second time)") upgradeWaitExpectation.fulfill() } self.wait(for: [upgradeWaitExpectation], timeout: 5) } + + func testSOSJoinByPreapprovalAfterUnknownState() throws { + self.startCKAccountStatusMock() + + // First, peer 1 establishes, preapproving both peer2 and peer3. Then, peer2 and peer3 join and harmonize. + // Peer1 is never told about the follow-on joins. + // Then, the test can begin. + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + let peer3SOSMockPeer = self.createSOSPeer(peerID: "peer3ID") + + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + self.mockSOSAdapter.trustedPeers.add(peer3SOSMockPeer) + + // Due to how everything is shaking out, SOS TLKShares will be uploaded in a second transaction after Octagon uploads its TLKShares + // This isn't great: Octagon: upload SOS TLKShares alongside initial key hierarchy + self.assertAllCKKSViewsUpload(tlkShares: 3) + + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + let peer1ID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // peer2 + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + let peer2ID = try peer2.accountMetadataStore.getEgoPeerID() + + // peer3 + let peer3mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer3SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let peer3 = self.makeInitiatorContext(contextID: "peer3", authKitAdapter: self.mockAuthKit3, sosAdapter: peer3mockSOS) + + peer3.startOctagonStateMachine() + self.assertEnters(context: peer3, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer3) + let peer3ID = try peer3.accountMetadataStore.getEgoPeerID() + + // Now, tell peer2 about peer3's join + self.sendContainerChangeWaitForFetch(context: peer2) + + // Peer 1 should preapprove both peers. + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trustsByPreapproval, target: peer2ID)), + "peer 1 should trust peer 2 by preapproval") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trustsByPreapproval, target: peer2ID)), + "peer 1 should trust peer 3 by preapproval") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer1ID)), + "peer 2 should trust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer3ID)), + "peer 2 should trust peer 3") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer3ID, opinion: .trusts, target: peer1ID)), + "peer 3 should trust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer3ID, opinion: .trusts, target: peer2ID)), + "peer 3 should trust peer 2") + + let container = try! self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: "peer3") + container.moc.performAndWait { + container.model.deletePeer(withID: peer3ID) + } + + // And we notify peer3 about this, and it should become sad + self.sendContainerChangeWaitForFetchForStates(context: peer3, states: [OctagonStateReadyUpdated, OctagonStateReady]) + self.assertConsidersSelfTrusted(context: peer3) + } } #endif // OCTAGON diff --git a/keychain/ot/tests/octagon/OctagonTests-BridgingHeader.h b/keychain/ot/tests/octagon/OctagonTests-BridgingHeader.h index 850a15b1..732a55ac 100644 --- a/keychain/ot/tests/octagon/OctagonTests-BridgingHeader.h +++ b/keychain/ot/tests/octagon/OctagonTests-BridgingHeader.h @@ -2,16 +2,20 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // +#import + #import #import #import +#import #import #import "KeychainCircle/KCJoiningSession.h" #import "KeychainCircle/KCJoiningRequestSession+Internal.h" #import "KeychainCircle/KCJoiningAcceptSession+Internal.h" #import +#import #import #import @@ -36,6 +40,7 @@ #import "keychain/ot/OT.h" #import "keychain/ot/OTClique.h" +#import "keychain/ot/OTClique+Private.h" #import "keychain/ot/OTControl.h" #import "keychain/ot/OTControlProtocol.h" #import "keychain/ot/OTManager.h" @@ -59,6 +64,8 @@ #import "keychain/ckks/CKKSTLKShare.h" #import "keychain/ckks/CKKSAnalytics.h" #import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/CKKSCurrentKeyPointer.h" +#import "keychain/ckks/CKKSReachabilityTracker.h" #import "keychain/ot/OctagonControlServer.h" @@ -66,6 +73,12 @@ #import "keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h" #import "keychain/ot/categories/OctagonEscrowRecoverer.h" +#import "KeychainCircle/generated_source/KCInitialMessageData.h" +#import "keychain/ot/proto/generated_source/OTPairingMessage.h" +#import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" +#import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" + #import "keychain/otctl/OTControlCLI.h" // Also, we're going to need whatever TPH needs. @@ -74,6 +87,7 @@ #import "keychain/SecureObjectSync/SOSControlServer.h" #import "KeychainCircle/Tests/FakeSOSControl.h" #import "keychain/escrowrequest/Framework/SecEscrowRequest.h" +#import "OSX/sec/ipc/server_security_helpers.h" //CDP #import @@ -92,3 +106,6 @@ #include #import "keychain/ot/OctagonCKKSPeerAdapter.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecord.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h" diff --git a/keychain/ot/tests/octagon/OctagonTests.swift b/keychain/ot/tests/octagon/OctagonTests.swift index de42b910..2f92ae6f 100644 --- a/keychain/ot/tests/octagon/OctagonTests.swift +++ b/keychain/ot/tests/octagon/OctagonTests.swift @@ -42,7 +42,7 @@ class OTMockDeviceInfoAdapter: OTDeviceInformationAdapter { return self.mockOsVersion } - func serialNumber() -> String { + func serialNumber() -> String? { return self.mockSerialNumber } @@ -51,10 +51,14 @@ class OTMockDeviceInfoAdapter: OTDeviceInformationAdapter { } class OTMockAuthKitAdapter: OTAuthKitAdapter { + // A nil altDSID means 'no authkit account' var altDSID: String? + var injectAuthErrorsAtFetchTime: Bool + var hsa2: Bool + var isDemoAccount: Bool let currentMachineID: String var otherDevices: Set @@ -74,7 +78,11 @@ class OTMockAuthKitAdapter: OTAuthKitAdapter { self.otherDevices = otherDevices self.excludeDevices = Set() self.hsa2 = true + self.isDemoAccount = false self.listeners = CKKSListenerCollection(name: "test-authkit") + + // By default, you can fetch a list you're not on + self.injectAuthErrorsAtFetchTime = false } func primaryiCloudAccountAltDSID() throws -> String { @@ -90,6 +98,9 @@ class OTMockAuthKitAdapter: OTAuthKitAdapter { // TODO: do we need to examine altDSID here? return self.hsa2 } + func accountIsDemoAccount(_ error: NSErrorPointer) -> Bool { + return self.isDemoAccount + } func machineID() throws -> String { // TODO: throw if !accountPresent @@ -104,6 +115,17 @@ class OTMockAuthKitAdapter: OTAuthKitAdapter { return } + // If this device is actively on the excluded list, return an error + // But demo accounts can do what they want + if !self.isDemoAccount && + self.injectAuthErrorsAtFetchTime && + self.excludeDevices.contains(self.currentMachineID) { + complete(nil, NSError(domain: AKAppleIDAuthenticationErrorDomain, + code: -7026, + userInfo: [NSLocalizedDescriptionKey: "Injected AKAuthenticationErrorNotPermitted error"])) + return + } + if let fetchCondition = self.fetchCondition { fetchCondition.fulfill() } @@ -183,8 +205,8 @@ class OTMockLogger: NSObject, SFAnalyticsProtocol { } let OTMockEscrowRequestNotification = Notification.Name("silent-escrow-request-triggered") -class OTMockSecEscrowRequest: NSObject, SecEscrowRequestable { +class OTMockSecEscrowRequest: NSObject, SecEscrowRequestable { static var populateStatuses = false var statuses: [String: String] = [:] @@ -213,8 +235,7 @@ class OTMockSecEscrowRequest: NSObject, SecEscrowRequestable { } } -class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { - +class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { var tmpPath: String! var tmpURL: URL! @@ -223,7 +244,11 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { var otcliqueContext: OTConfigurationContext! + var intendedCKKSZones: Set! var manateeZoneID: CKRecordZone.ID! + var limitedPeersAllowedZoneID: CKRecordZone.ID! + var passwordsZoneID: CKRecordZone.ID! + var fakeCuttlefishServer: FakeCuttlefishServer! var fakeCuttlefishCreator: FakeCuttlefishInvocableCreator! var tphClient: Client! @@ -240,6 +265,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { var otControl: OTControl! var otXPCProxy: ProxyXPCConnection! + var otControlEntitlementBearer: FakeOTControlEntitlementBearer! var otControlEntitlementChecker: OTControlProtocol! var otControlCLI: OTControlCLI! @@ -248,8 +274,6 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { override static func setUp() { UserDefaults.standard.register(defaults: ["com.apple.CoreData.ConcurrencyDebug": 1]) - OctagonSetShouldPerformInitialization(true) - SecCKKSEnable() super.setUp() @@ -261,38 +285,47 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { // Set the global bool to TRUE OctagonSetIsEnabled(true) + // Set the global CKKS bool to TRUE + SecCKKSEnable() + // Until we can reasonably run SOS in xctest, this must be off. Note that this makes our tests // not accurately reproduce what a real device would do. OctagonSetPlatformSupportsSOS(false) - // Tell SecDb not to initialize the manager (as we haven't made our fake one yet). - // Each test is responsible for initialization, to allow for pre-test setup - OctagonSetShouldPerformInitialization(false) + if self.mockDeviceInfo == nil { + let actualDeviceAdapter = OTDeviceInformationActualAdapter() + self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(), + deviceName: actualDeviceAdapter.deviceName(), + serialNumber: NSUUID().uuidString, + osVersion: actualDeviceAdapter.osVersion()) + } - let actualDeviceAdapter = OTDeviceInformationActualAdapter() - self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(), - deviceName: actualDeviceAdapter.deviceName(), - serialNumber: NSUUID().uuidString, - osVersion: actualDeviceAdapter.osVersion()) - - super.setUp() - - // Octagon must initialize the views - self.automaticallyBeginCKKSViewCloudKitOperation = false - - // The CKKStests use the "keychain" view heavily, but that causes issues in Octagon as it isn't in the Octagon policy. - // Replace it with the Manatee view, unless you're on an appleTV: in that case, make it the LimitedPeersAllowed view - self.injectedManager!.clearAllViews() - #if !os(tvOS) - self.ckksViews = NSMutableSet(array: [self.injectedManager!.findOrCreateView("Manatee")]) self.manateeZoneID = CKRecordZone.ID(zoneName: "Manatee") - #else - self.ckksViews = NSMutableSet(array: [self.injectedManager!.findOrCreateView("LimitedPeersAllowed")]) - self.manateeZoneID = CKRecordZone.ID(zoneName: "LimitedPeersAllowed") - #endif + self.limitedPeersAllowedZoneID = CKRecordZone.ID(zoneName: "LimitedPeersAllowed") + self.passwordsZoneID = CKRecordZone.ID(zoneName: "Passwords") - self.zones!.removeAllObjects() - self.zones![self.manateeZoneID!] = FakeCKZone(zone: self.manateeZoneID!) + // We'll use this set to limit the views that CKKS brings up in the tests (mostly for performance reasons) + if self.intendedCKKSZones == nil { + if self.mockDeviceInfo.mockModelID.contains("AppleTV") { + self.intendedCKKSZones = Set([ + self.limitedPeersAllowedZoneID!, + ]) + } else { + self.intendedCKKSZones = Set([ + self.limitedPeersAllowedZoneID!, + self.manateeZoneID!, + ]) + } + } + self.ckksZones = NSMutableSet(array: Array(self.intendedCKKSZones)) + + // Create the zones, so we can inject them into our fake cuttlefish server + self.zones = [:] + self.keys = [:] + self.ckksZones.forEach { obj in + let zoneID = obj as! CKRecordZone.ID + self.zones![zoneID] = FakeCKZone(zone: zoneID) + } // Asserting a type on self.zones seems to duplicate the dictionary, but not deep-copy the contents // We'll use them as NSMutableDictionaries, I guess @@ -303,35 +336,38 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { self.otFollowUpController = OTMockFollowUpController() - // Octagon requires the self peer keys to be persisted in the keychain - saveToKeychain(keyPair: self.mockSOSAdapter.selfPeer.signingKey, label: "com.apple.securityd.sossigningkey") - saveToKeychain(keyPair: self.mockSOSAdapter.selfPeer.encryptionKey, label: "com.apple.securityd.sosencryptionkey") - self.mockAuthKit = OTMockAuthKitAdapter(altDSID: UUID().uuidString, machineID: "MACHINE1", otherDevices: ["MACHINE2", "MACHINE3"]) self.mockAuthKit2 = OTMockAuthKitAdapter(altDSID: self.mockAuthKit.altDSID, machineID: "MACHINE2", otherDevices: ["MACHINE1", "MACHINE3"]) self.mockAuthKit3 = OTMockAuthKitAdapter(altDSID: self.mockAuthKit.altDSID, machineID: "MACHINE3", otherDevices: ["MACHINE1", "MACHINE2"]) + let tphInterface = TrustedPeersHelperSetupProtocol(NSXPCInterface(with: TrustedPeersHelperProtocol.self)) + self.tphXPCProxy = ProxyXPCConnection(self.tphClient!, interface: tphInterface) + + self.disableConfigureCKKSViewManagerWithViews = true + + // Now, perform further test initialization (including temporary keychain creation) + super.setUp() + + self.injectedManager!.setSyncingViewsAllowList(Set(self.intendedCKKSZones!.map { $0.zoneName })) + + // Octagon is responsible for creating CKKS views; so we don't create any in the test setup + + // Double-check that the world of zones and views looks like what we expect + XCTAssertEqual(self.ckksZones as? Set, self.intendedCKKSZones, "should still operate on our expected zones only") + XCTAssertEqual(self.ckksZones.count, self.zones!.count, "Should have the same number of fake zones as expected zones") + + // Octagon must initialize the views + self.automaticallyBeginCKKSViewCloudKitOperation = false + + // Octagon requires the self peer keys to be persisted in the keychain + saveToKeychain(keyPair: self.mockSOSAdapter.selfPeer.signingKey, label: "com.apple.securityd.sossigningkey") + saveToKeychain(keyPair: self.mockSOSAdapter.selfPeer.encryptionKey, label: "com.apple.securityd.sosencryptionkey") + // By default, not in SOS when test starts // And under octagon, SOS trust is not essential self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCNotInCircle) self.mockSOSAdapter.essential = false - let tphInterface = TrustedPeersHelperSetupProtocol(NSXPCInterface(with: TrustedPeersHelperProtocol.self)) - self.tphXPCProxy = ProxyXPCConnection(self.tphClient!, interface: tphInterface) - - self.manager = OTManager(sosAdapter: self.mockSOSAdapter, - authKitAdapter: self.mockAuthKit, - deviceInformationAdapter: self.mockDeviceInfo, - apsConnectionClass: FakeAPSConnection.self, - escrowRequestClass: OTMockSecEscrowRequest.self, - loggerClass: OTMockLogger.self, - lockStateTracker: self.lockStateTracker, - accountStateTracker: self.accountStateTracker, - cuttlefishXPCConnection: tphXPCProxy.connection(), - cdpd: self.otFollowUpController) - - OTManager.resetManager(true, to: self.manager) - self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) self.otControlEntitlementBearer = FakeOTControlEntitlementBearer() @@ -339,7 +375,6 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { self.otXPCProxy = ProxyXPCConnection(self.otControlEntitlementChecker!, interface: OTSetupControlProtocol(NSXPCInterface(with: OTControlProtocol.self))) self.otControl = OTControl(connection: self.otXPCProxy.connection(), sync: true) - self.otControlCLI = OTControlCLI(otControl: self.otControl) self.otcliqueContext = OTConfigurationContext() @@ -349,7 +384,25 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { self.otcliqueContext.otControl = self.otControl } + override func setUpOTManager(_ cloudKitClassDependencies: CKKSCloudKitClassDependencies) -> OTManager { + self.manager = OTManager(sosAdapter: self.mockSOSAdapter, + authKitAdapter: self.mockAuthKit, + deviceInformationAdapter: self.mockDeviceInfo, + apsConnectionClass: FakeAPSConnection.self, + escrowRequestClass: OTMockSecEscrowRequest.self, + loggerClass: OTMockLogger.self, + lockStateTracker: CKKSLockStateTracker(provider: self.lockStateProvider), + reachabilityTracker: CKKSReachabilityTracker(), + cloudKitClassDependencies: cloudKitClassDependencies, + cuttlefishXPCConnection: tphXPCProxy.connection(), + cdpd: self.otFollowUpController) + return self.manager + } + override func tearDown() { + // Just to be sure + self.verifyDatabaseMocks() + let statusExpectation = self.expectation(description: "status callback occurs") self.cuttlefishContext.rpcStatus { _, _ in statusExpectation.fulfill() @@ -368,21 +421,69 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { XCTAssertTrue(self.manager.allContextsPause(10 * NSEC_PER_SEC), "All cuttlefish contexts should pause") + do { + try self.tphClient.containerMap.deleteAllPersistentStores() + } catch { + XCTFail("Failed to clean up CoreData databases: \(error)") + } + self.tphClient.containerMap.removeAllContainers() + super.tearDown() + + self.cuttlefishContext = nil + self.manager = nil + + self.otcliqueContext = nil + + self.manateeZoneID = nil + self.limitedPeersAllowedZoneID = nil + + self.fakeCuttlefishServer = nil + self.fakeCuttlefishCreator = nil + self.tphClient = nil + self.tphXPCProxy = nil + + self.accountAltDSID = nil + + self.mockAuthKit = nil + self.mockAuthKit2 = nil + self.mockAuthKit3 = nil + + self.mockDeviceInfo = nil + + self.otControl = nil + self.otXPCProxy = nil + + self.otControlEntitlementBearer = nil + self.otControlEntitlementChecker = nil + self.otControlCLI = nil + + self.otFollowUpController = nil } override func managedViewList() -> Set { - #if !os(tvOS) - return Set(["Manatee"]) - #else - return Set(["LimitedPeersAllowed"]) - #endif + if self.overrideUseCKKSViewsFromPolicy { + let viewNames = self.ckksZones.map { ($0 as! CKRecordZone.ID).zoneName } + return Set(viewNames) + } else { + // We only want to return the 'base' set of views here; not the full set. + // This should go away when CKKS4A is enabled... + #if !os(tvOS) + return Set(["LimitedPeersAllowed", "Manatee"]) + #else + return Set(["LimitedPeersAllowed"]) + #endif + } } func fetchEgoPeerID() -> String { + return self.fetchEgoPeerID(context: self.cuttlefishContext) + } + + func fetchEgoPeerID(context: OTCuttlefishContext) -> String { var ret: String! let fetchPeerIDExpectation = self.expectation(description: "fetchPeerID callback occurs") - self.cuttlefishContext.rpcFetchEgoPeerID { peerID, fetchError in + context.rpcFetchEgoPeerID { peerID, fetchError in XCTAssertNil(fetchError, "should not error fetching ego peer ID") XCTAssertNotNil(peerID, "Should have a peer ID") ret = peerID @@ -392,13 +493,14 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { return ret } - func setAllowListToCurrentAuthKit(container: String, context: String) { + func setAllowListToCurrentAuthKit(container: String, context: String, accountIsDemo: Bool) { let allowListExpectation = self.expectation(description: "set allow list callback occurs") + let honorIDMSListChanges = accountIsDemo ? false : true self.tphClient.setAllowedMachineIDsWithContainer(container, context: context, - allowedMachineIDs: self.mockAuthKit.currentDeviceList()) { _, error in - XCTAssertNil(error, "Should be no error setting allow list") - allowListExpectation.fulfill() + allowedMachineIDs: self.mockAuthKit.currentDeviceList(), honorIDMSListChanges: honorIDMSListChanges) { _, error in + XCTAssertNil(error, "Should be no error setting allow list") + allowListExpectation.fulfill() } self.wait(for: [allowListExpectation], timeout: 10) } @@ -417,23 +519,22 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { } func assertEnters(context: OTCuttlefishContext, state: String, within: UInt64) { - XCTAssertEqual(0, (context.stateMachine.stateConditions[state] as! CKKSCondition).wait(within), "State machine should enter '\(state)'") - if(state == OctagonStateReady || state == OctagonStateUntrusted) { + XCTAssertEqual(0, (context.stateMachine.stateConditions[state]!).wait(within), "State machine should enter '\(state)'") + if state == OctagonStateReady || state == OctagonStateUntrusted { XCTAssertEqual(0, context.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should pause soon") } } - func assertPendingFlagHandled(context: OTCuttlefishContext, pendingFlag: String, within: UInt64) { - XCTAssertEqual(0, (context.stateMachine.flags.condition(forFlag: pendingFlag)).wait(within), "State machine should have handled '\(pendingFlag)'") - } - func assertConsidersSelfTrusted(context: OTCuttlefishContext, isLocked: Bool = false) { XCTAssertEqual(context.currentMemoizedTrustState(), .TRUSTED, "Trust state (for \(context)) should be trusted") + let accountMetadata = try! context.accountMetadataStore.loadOrCreateAccountMetadata() + XCTAssertEqual(accountMetadata.attemptedJoin, .ATTEMPTED, "Should have 'attempted a join'") + let statusexpectation = self.expectation(description: "trust status returns") let configuration = OTOperationConfiguration() configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, isLocked, _ in + context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, isLocked, _, _ in XCTAssertEqual(egoStatus, .in, "Self peer (for \(context)) should be trusted") XCTAssertNotNil(egoPeerID, "Should have a peerID") XCTAssertEqual(isLocked, isLocked, "should be \(isLocked)") @@ -450,7 +551,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { configuration.useCachedAccountStatus = true configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, _ in + context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, _, _ in XCTAssertEqual(egoStatus, .in, "Cached self peer (for \(context)) should be trusted") XCTAssertNotNil(egoPeerID, "Should have a (cached) peerID") cachedStatusexpectation.fulfill() @@ -462,14 +563,14 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { cliqueConfiguration.dsid = "1234" cliqueConfiguration.altDSID = self.mockAuthKit.altDSID! cliqueConfiguration.otControl = self.otControl - let otclique = try! OTClique(contextData: cliqueConfiguration) + let otclique = OTClique(contextData: cliqueConfiguration) let status = otclique.fetchStatus(nil) XCTAssertEqual(status, .in, "OTClique API should return (trusted)") configuration.useCachedAccountStatus = false let statusexpectation = self.expectation(description: "(cached) trust status returns") - context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, _ in + context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, _, _ in XCTAssertEqual(egoStatus, .in, "Self peer (for \(context)) should be trusted") XCTAssertNotNil(egoPeerID, "Should have a peerID") statusexpectation.fulfill() @@ -482,12 +583,27 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { let statusexpectation = self.expectation(description: "trust status returns") let configuration = OTOperationConfiguration() configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - context.rpcTrustStatus(configuration) { egoStatus, _, _, _, _ in + context.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, _ in + // TODO: separate 'untrusted' and 'no trusted peers for account yet' + XCTAssertTrue([.notIn, .absent].contains(egoStatus), "Self peer (for \(context)) should be distrusted or absent, is \(egoStatus)") + statusexpectation.fulfill() + } + self.wait(for: [statusexpectation], timeout: 10) + } + + func assertConsidersSelfWaitingForCDP(context: OTCuttlefishContext) { + XCTAssertEqual(context.currentMemoizedTrustState(), .UNKNOWN, "Trust state (for \(context)) should be unknown") + let statusexpectation = self.expectation(description: "trust status returns") + let configuration = OTOperationConfiguration() + configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC + context.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, _ in // TODO: separate 'untrusted' and 'no trusted peers for account yet' XCTAssertTrue([.notIn, .absent].contains(egoStatus), "Self peer (for \(context)) should be distrusted or absent") statusexpectation.fulfill() } self.wait(for: [statusexpectation], timeout: 10) + + XCTAssertEqual(self.fetchCDPStatus(context: context), .disabled, "CDP status should be 'disabled'") } func assertAccountAvailable(context: OTCuttlefishContext) { @@ -498,6 +614,18 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { XCTAssertEqual(context.currentMemoizedAccountState(), .NO_ACCOUNT, "Account state (for \(context)) should be no account") } + func fetchCDPStatus(context: OTCuttlefishContext) -> OTCDPStatus { + let config = OTConfigurationContext() + config.context = context.contextID + config.otControl = self.otControl + + var error: NSError? + let cdpstatus = OTClique.getCDPStatus(config, error: &error) + XCTAssertNil(error, "Should have no error fetching CDP status") + + return cdpstatus + } + func assertTrusts(context: OTCuttlefishContext, includedPeerIDCount: Int, excludedPeerIDCount: Int) { let dumpCallback = self.expectation(description: "dump callback occurs") self.tphClient.dumpEgoPeer(withContainer: context.containerName, context: context.contextID) { _, _, _, dynamicInfo, error in @@ -512,38 +640,80 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { } func restartCKKSViews() { - let viewNames = self.ckksViews.map { ($0 as! CKKSKeychainView).zoneName } - self.ckksViews.removeAllObjects() + let viewNames = self.intendedCKKSZones.map { $0.zoneName } + + self.injectedManager!.resetSyncingPolicy() + for view in viewNames { - self.ckksViews.add(self.injectedManager!.restartZone(view)) + self.injectedManager!.restartZone(view) } } func sendAllCKKSTrustedPeersChanged() { - self.ckksViews.forEach { view in + self.injectedManager!.views.forEach { _, view in (view as! CKKSKeychainView).trustedPeerSetChanged(nil) } } func assert(ckks: CKKSKeychainView, enters: String, within: UInt64) { - XCTAssertEqual(0, (ckks.keyHierarchyConditions[enters] as! CKKSCondition).wait(within), "CKKS state machine should enter '\(enters)' (currently '\(ckks.keyHierarchyState)')") + XCTAssertEqual(0, (ckks.stateMachine.stateConditions[enters]!).wait(within), "CKKS state machine should enter '\(enters)' (currently '\(ckks.stateMachine.currentState)')") } - func assertAllCKKSViews(enter: String, within: UInt64) { - for view in self.ckksViews { - self.assert(ckks: view as! CKKSKeychainView, enters: enter, within: within) + func assertAllCKKSViews(enter: String, within: UInt64, filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { expectedView in + let view = self.injectedManager?.findView((expectedView as! CKRecordZone.ID).zoneName) + XCTAssertNotNil(view, "Should have a view '\(expectedView)'") + self.assert(ckks: view!, enters: enter, within: within) } } func assertAllCKKSViewsUploadKeyHierarchy(tlkShares: UInt) { - self.ckksViews.forEach { view in - self.expectCKModifyKeyRecords(3, currentKeyPointerRecords: 3, tlkShareRecords: tlkShares, zoneID: (view as! CKKSKeychainView).zoneID) + for expectedView in self.ckksZones { + let view = self.injectedManager?.findView((expectedView as! CKRecordZone.ID).zoneName) + XCTAssertNotNil(view, "Should have a view '\(expectedView)'") + self.expectCKModifyKeyRecords(3, currentKeyPointerRecords: 3, tlkShareRecords: tlkShares, zoneID: view!.zoneID) } } - func assertAllCKKSViewsUpload(tlkShares: UInt) { - self.ckksViews.forEach { view in - self.expectCKModifyKeyRecords(0, currentKeyPointerRecords: 0, tlkShareRecords: tlkShares, zoneID: (view as! CKKSKeychainView).zoneID) + func assertAllCKKSViewsUpload(tlkShares: UInt, filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { expectedView in + self.expectCKModifyKeyRecords(0, currentKeyPointerRecords: 0, tlkShareRecords: tlkShares, zoneID: expectedView as! CKRecordZone.ID) + } + } + + func putFakeKeyHierarchiesInCloudKit(filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in + self.putFakeKeyHierarchy(inCloudKit: zone as! CKRecordZone.ID) + } + } + + func putSelfTLKSharesInCloudKit(filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in + self.putSelfTLKShares(inCloudKit: zone as! CKRecordZone.ID) + } + } + + func putFakeDeviceStatusesInCloudKit(filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in + self.putFakeDeviceStatus(inCloudKit: zone as! CKRecordZone.ID) + } + } + + func saveTLKMaterialToKeychain(filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in + self.saveTLKMaterial(toKeychain: zone as! CKRecordZone.ID) } } @@ -557,11 +727,67 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { self.wait(for: [resetExpectation], timeout: 30) } - func putSelfTLKShareInCloudKit(context: OTCuttlefishContext, zoneID: CKRecordZone.ID) throws { - let accountMetadata = try context.accountMetadataStore.loadOrCreateAccountMetadata() - let peerKeys: OctagonSelfPeerKeys = try loadEgoKeysSync(peerID: accountMetadata.peerID) + func putSelfTLKSharesInCloudKit(context: OTCuttlefishContext, filter: ((CKRecordZone.ID) -> Bool)? = nil) throws { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + try self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in + try self.putTLKShareInCloudKit(to: context, from: context, zoneID: zone as! CKRecordZone.ID) + } + } + + func putAllTLKSharesInCloudKit(to: OTCuttlefishContext, from: OTCuttlefishContext) throws { + try self.ckksZones.forEach { zone in + try self.putTLKShareInCloudKit(to: to, from: from, zoneID: zone as! CKRecordZone.ID) + } + } + + func putTLKShareInCloudKit(to: OTCuttlefishContext, from: OTCuttlefishContext, zoneID: CKRecordZone.ID) throws { + let fromAccountMetadata = try from.accountMetadataStore.loadOrCreateAccountMetadata() + let fromPeerKeys: OctagonSelfPeerKeys = try loadEgoKeysSync(peerID: fromAccountMetadata.peerID) + + let toAccountMetadata = try to.accountMetadataStore.loadOrCreateAccountMetadata() + let toPeerKeys: OctagonSelfPeerKeys = try loadEgoKeysSync(peerID: toAccountMetadata.peerID) + let zoneKeys = self.keys![zoneID] as! ZoneKeys - self.putTLKShare(inCloudKit: zoneKeys.tlk!, from: peerKeys, to: peerKeys, zoneID: zoneID) + self.putTLKShare(inCloudKit: zoneKeys.tlk!, from: fromPeerKeys, to: toPeerKeys, zoneID: zoneID) + } + + func putRecoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String) throws { + let recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) + + self.ckksZones.forEach { zone in + let zoneID = zone as! CKRecordZone.ID + let zoneKeys = self.keys![zoneID] as! ZoneKeys + self.putTLKShare(inCloudKit: zoneKeys.tlk!, from: recoveryKeys.peerKeys, to: recoveryKeys.peerKeys, zoneID: zoneID) + } + } + + func putRecoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String, sender: OTCuttlefishContext) throws { + let recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) + + let senderAccountMetadata = try sender.accountMetadataStore.loadOrCreateAccountMetadata() + let senderPeerKeys: OctagonSelfPeerKeys = try loadEgoKeysSync(peerID: senderAccountMetadata.peerID) + + self.ckksZones.forEach { zone in + let zoneID = zone as! CKRecordZone.ID + let zoneKeys = self.keys![zoneID] as! ZoneKeys + self.putTLKShare(inCloudKit: zoneKeys.tlk!, from: senderPeerKeys, to: recoveryKeys.peerKeys, zoneID: zoneID) + } + } + + func recoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String) throws -> Bool { + let recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) + + return self.tlkSharesInCloudKit(receiverPeerID: recoveryKeys.peerKeys.peerID, + senderPeerID: recoveryKeys.peerKeys.peerID) + } + + func recoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String, sender: OTCuttlefishContext) throws -> Bool { + let recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) + let senderAccountMetadata = try sender.accountMetadataStore.loadOrCreateAccountMetadata() + + return self.tlkSharesInCloudKit(receiverPeerID: recoveryKeys.peerKeys.peerID, + senderPeerID: senderAccountMetadata.peerID) } func assertSelfTLKSharesInCloudKit(context: OTCuttlefishContext) { @@ -582,24 +808,38 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { } func assertTLKSharesInCloudKit(receiverPeerID: String, senderPeerID: String) { - for case let view as CKKSKeychainView in self.ckksViews { - XCTAssertNoThrow(try self.assertTLKShareInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID, zoneID: view.zoneID), "view \(view) should have a self TLK uploaded") - } + XCTAssertTrue(self.tlkSharesInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID), "All views should have a self TLK uploaded") } - func assertTLKShareInCloudKit(receiverPeerID: String, senderPeerID: String, zoneID: CKRecordZone.ID) throws { - let zone = self.zones![zoneID] as! FakeCKZone + func tlkSharesInCloudKit(receiverPeerID: String, senderPeerID: String) -> Bool { + let tlkContains: [Bool] = self.ckksViews.map { + let view: CKKSKeychainView = $0 as! CKKSKeychainView + return self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID, zoneID: view.zoneID) + } + + // return true if all entries in tlkContains is true + return tlkContains.allSatisfy { $0 == true } + } + + func tlkShareInCloudKit(receiverPeerID: String, senderPeerID: String, zoneID: CKRecordZone.ID) -> Bool { + guard let zone = self.zones![zoneID] as? FakeCKZone else { + return false + } let tlkShares = zone.currentDatabase.allValues.filter { ($0 as? CKRecord)?.recordType == SecCKRecordTLKShareType }.map { CKKSTLKShareRecord(ckRecord: $0 as! CKRecord) } for share in tlkShares { if share.share.receiverPeerID == receiverPeerID && share.senderPeerID == senderPeerID { // Found one! - return + return true } } + return false + } - XCTFail("Unable to find a TLKShare for peer ID \(String(describing: receiverPeerID)) sent by \(String(describing: senderPeerID))") + func assertTLKShareInCloudKit(receiverPeerID: String, senderPeerID: String, zoneID: CKRecordZone.ID) { + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID, zoneID: zoneID), + "Should have found a TLKShare for peerID \(String(describing: receiverPeerID)) sent by \(String(describing: senderPeerID)) for \(zoneID)") } func assertMIDList(context: OTCuttlefishContext, @@ -615,22 +855,24 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { } for allowedMID in allowed { - var err : NSError? + var err: NSError? let onList = context.machineID(onMemoizedList: allowedMID, error: &err) XCTAssertNil(err, "Should not have failed determining memoized list state") XCTAssertTrue(onList, "MID on allowed list should return 'is on list'") do { - let number = try context.numberOfPeersInModel(withMachineID: allowedMID) - XCTAssert(number.intValue >= 0, "Should have a non-negative number for numberOfPeersInModel") + let egoPeerStatus = try context.egoPeerStatus() + + let numberOfPeersWithMID = egoPeerStatus.peerCountsByMachineID[allowedMID] ?? NSNumber(0) + XCTAssert(numberOfPeersWithMID.intValue >= 0, "Should have a non-negative number for number of peers with the allowed MID") } catch { XCTFail("Should not have failed fetching the number of peers with a mid: \(error)") } } for disallowedMID in disallowed { - var err : NSError? + var err: NSError? let onList = context.machineID(onMemoizedList: disallowedMID, error: &err) XCTAssertNil(err, "Should not have failed determining memoized list state") @@ -659,7 +901,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { } if result != nil { - if let dictionary = result as? Dictionary { + if let dictionary = result as? [CFString: Any] { secret = dictionary[kSecValueData] as? Data } else { throw ContainerError.failedToLoadSecretDueToType @@ -681,6 +923,14 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { ]) } + func waitForPushToArriveAtStateMachine(context: OTCuttlefishContext) throws { + let apsSender = try XCTUnwrap(self.cuttlefishContext.apsRateLimiter) + + let waitFor = apsSender.operationDependency.completionHandlerDidRunCondition + + XCTAssertEqual(0, waitFor.wait(10 * NSEC_PER_SEC)) + } + func sendTTRRequest(context: OTCuttlefishContext) { context.notifyContainerChange(userInfo: [ "aps": [ @@ -707,9 +957,11 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { // Please ensure that the first state in this list is not the state that the context is currently in func sendContainerChangeWaitForFetchForStates(context: OTCuttlefishContext, states: [String]) { - // Pull the first state out before sending the notification - let firstState = states.first! - let firstCondition = (context.stateMachine.stateConditions[firstState] as! CKKSCondition) + + // If we wait for each condition in order here, we might lose thread races and cause issues. + // Fetch every state we'll examine (note that this doesn't handle repeated checks for the same state) + + let stateConditions = states.map { ($0, context.stateMachine.stateConditions[$0]!) } let updateTrustExpectation = self.expectation(description: "fetchChanges") @@ -721,10 +973,11 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { context.notifyContainerChange(nil) self.wait(for: [updateTrustExpectation], timeout: 10) - // Wait for the previously acquired first state, then wait for each in turn - XCTAssertEqual(0, firstCondition.wait(10 * NSEC_PER_SEC), "State machine should enter '\(String(describing: firstState))'") - for state in states.dropFirst() { - self.assertEnters(context: context, state: state, within: 10 * NSEC_PER_SEC) + for (state, stateCondition) in stateConditions { + XCTAssertEqual(0, stateCondition.wait(10 * NSEC_PER_SEC), "State machine should enter '\(String(describing: state))'") + if state == OctagonStateReady || state == OctagonStateUntrusted { + XCTAssertEqual(0, context.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should pause soon") + } } } @@ -767,26 +1020,43 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { deviceInformationAdapter: self.makeInitiatorDeviceInfoAdapter()) } - @discardableResult func assertResetAndBecomeTrustedInDefaultContext() -> String { - self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + @discardableResult + func assertResetAndBecomeTrustedInDefaultContext() -> String { + let ret = self.assertResetAndBecomeTrusted(context: self.cuttlefishContext) + + // And, the default context runs CKKS: + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + + return ret + } + + @discardableResult + func assertResetAndBecomeTrusted(context: OTCuttlefishContext) -> String { + context.startOctagonStateMachine() + XCTAssertNoThrow(try context.setCDPEnabled()) + self.assertEnters(context: context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { - let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + let arguments = OTConfigurationContext() + arguments.altDSID = try context.authKitAdapter.primaryiCloudAccountAltDSID() + arguments.context = context.contextID + arguments.otControl = self.otControl + + let clique = try OTClique.newFriends(withContextData: arguments, resetReason: .testGenerated) XCTAssertNotNil(clique, "Clique should not be nil") } catch { XCTFail("Shouldn't have errored making new friends: \(error)") } - // Now, we should be in 'ready' - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - self.verifyDatabaseMocks() - self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) - return try! self.cuttlefishContext.accountMetadataStore.getEgoPeerID() + self.assertEnters(context: context, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: context) + + return try! context.accountMetadataStore.getEgoPeerID() } + @discardableResult func assertJoinViaEscrowRecovery(joiningContext: OTCuttlefishContext, sponsor: OTCuttlefishContext) -> String { do { joiningContext.startOctagonStateMachine() @@ -820,14 +1090,49 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { } } - func assertSelfOSVersion(_ osVersion: String) { + func assertJoinViaProximitySetup(joiningContext: OTCuttlefishContext, sponsor: OTCuttlefishContext) -> String { + do { + joiningContext.startOctagonStateMachine() + self.assertEnters(context: joiningContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + let (sponsorPairingChannel, initiatorPairingChannel) = self.setupPairingChannels(initiator: joiningContext, sponsor: sponsor) + + let firstInitiatorPacket = self.sendPairingExpectingReply(channel: initiatorPairingChannel, packet: nil, reason: "session initialization") + let sponsorEpochPacket = self.sendPairingExpectingReply(channel: sponsorPairingChannel, packet: firstInitiatorPacket, reason: "sponsor epoch") + let initiatorIdentityPacket = self.sendPairingExpectingReply(channel: initiatorPairingChannel, packet: sponsorEpochPacket, reason: "initiator identity") + let sponsorVoucherPacket = self.sendPairingExpectingCompletionAndReply(channel: sponsorPairingChannel, packet: initiatorIdentityPacket, reason: "sponsor voucher") + self.sendPairingExpectingCompletion(channel: initiatorPairingChannel, packet: sponsorVoucherPacket, reason: "initiator completion") + + self.assertEnters(context: joiningContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: joiningContext) + + return try joiningContext.accountMetadataStore.getEgoPeerID() + } catch { + XCTFail("Expected no error: \(error)") + return "failed" + } + } + + @discardableResult + func assertJoinViaEscrowRecoveryFromDefaultContextWithReciprocationAndTLKShares(joiningContext: OTCuttlefishContext) -> String { + let joinedPeerID = self.assertJoinViaEscrowRecovery(joiningContext: joiningContext, sponsor: self.cuttlefishContext) + + // And respond from the default context + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + return joinedPeerID + } + + func assertSelfOSVersion(_ osVersion: String) { let statusExpectation = self.expectation(description: "status callback occurs") - self.tphClient.dumpEgoPeer(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID, reply: { _, _, stableInfo, _, error in + self.tphClient.dumpEgoPeer(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { _, _, stableInfo, _, error in XCTAssertNil(error, "should be no error dumping ego peer") XCTAssertEqual(stableInfo?.osVersion, osVersion, "os version should be as required") statusExpectation.fulfill() - }) + } self.wait(for: [statusExpectation], timeout: 2) } @@ -835,6 +1140,8 @@ class OctagonTestsBase: CloudKitKeychainSyncingTestsBase { class OctagonTests: OctagonTestsBase { func testTPHPrepare() { + self.startCKAccountStatusMock() + let contextName = "asdf" let containerName = "test_container" @@ -845,28 +1152,40 @@ class OctagonTests: OctagonTestsBase { machineID: "asdf", bottleSalt: "123456789", bottleID: UUID().uuidString, - modelID: "asdf", + modelID: "iPhone9,1", deviceName: "asdf", serialNumber: "1234", osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in - XCTAssertNil(error, "Should be no error preparing identity") - XCTAssertNotNil(peerID, "Should be a peer ID") - XCTAssertNotNil(permanentInfo, "Should have a permenent info") - XCTAssertNotNil(permanentInfoSig, "Should have a permanent info signature") - XCTAssertNotNil(stableInfo, "Should have a stable info") - XCTAssertNotNil(stableInfoSig, "Should have a stable info signature") + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in + XCTAssertNil(error, "Should be no error preparing identity") + XCTAssertNotNil(peerID, "Should be a peer ID") + XCTAssertNotNil(permanentInfo, "Should have a permenent info") + XCTAssertNotNil(permanentInfoSig, "Should have a permanent info signature") + XCTAssertNotNil(stableInfo, "Should have a stable info") + XCTAssertNotNil(stableInfoSig, "Should have a stable info signature") - tphPrepareExpectation.fulfill() + let adapter = OctagonCKKSPeerAdapter(peerID: peerID!, containerName: containerName, contextID: contextName, cuttlefishXPC: CuttlefishXPCWrapper(cuttlefishXPCConnection: self.tphXPCProxy.connection())) + + do { + let selves = try adapter.fetchSelfPeers() + try TestsObjectiveC.testSecKey(selves) + } catch { + XCTFail("Test failed: \(error)") + } + + tphPrepareExpectation.fulfill() } self.wait(for: [tphPrepareExpectation], timeout: 10) } func testTPHMultiPrepare() throws { + self.startCKAccountStatusMock() + let contextName = OTDefaultContext let containerName = OTCKContainerName @@ -879,14 +1198,15 @@ class OctagonTests: OctagonTestsBase { machineID: "asdf", bottleSalt: "123456789", bottleID: UUID().uuidString, - modelID: "asdf", + modelID: "iPhone9,1", deviceName: "asdf", serialNumber: "1234", osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -907,14 +1227,15 @@ class OctagonTests: OctagonTestsBase { machineID: "asdf", bottleSalt: "123456789", bottleID: UUID().uuidString, - modelID: "asdf", + modelID: "iPhone9,1", deviceName: "asdf", serialNumber: "1234", osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -930,88 +1251,30 @@ class OctagonTests: OctagonTestsBase { self.wait(for: [tphPrepareExpectation2], timeout: 10) } - func testAccountSave() throws { - let contextName = OTDefaultContext - let containerName = OTCKContainerName - - self.startCKAccountStatusMock() - - // Before resetAndEstablish, there shouldn't be any stored account state - XCTAssertThrowsError(try OTAccountMetadataClassC.loadFromKeychain(forContainer: containerName, contextID: contextName), "Before doing anything, loading a non-existent account state should fail") - - let resetAndEstablishExpectation = self.expectation(description: "resetAndEstablish callback occurs") - self.manager.resetAndEstablish(containerName, - context: contextName, - altDSID: "new altDSID", - resetReason: .testGenerated) { resetError in - XCTAssertNil(resetError, "Should be no error calling resetAndEstablish") - resetAndEstablishExpectation.fulfill() - } - - self.wait(for: [resetAndEstablishExpectation], timeout: 10) - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - - let selfPeerID = try self.cuttlefishContext.accountMetadataStore.loadOrCreateAccountMetadata().peerID - - // After resetAndEstablish, you should be able to see the persisted account state - do { - let accountState = try OTAccountMetadataClassC.loadFromKeychain(forContainer: containerName, contextID: contextName) - XCTAssertEqual(selfPeerID, accountState.peerID, "Saved account state should have the same peer ID that prepare returned") - } catch { - XCTFail("error loading account state: \(error)") - } - } - - func testLoadToNoAccount() throws { - // No CloudKit account, either - self.accountStatus = .noAccount - self.startCKAccountStatusMock() - - // With no identity and AuthKit reporting no iCloud account, Octagon should go directly into 'no account' - self.mockAuthKit.altDSID = nil - - let asyncExpectation = self.expectation(description: "dispatch works") - let quiescentExpectation = self.expectation(description: "quiescence has been determined") - DispatchQueue.global(qos: .userInitiated).async { [weak self] in - asyncExpectation.fulfill() - - let c = self!.cuttlefishContext.stateMachine.paused - XCTAssertEqual(0, c.wait(10 * NSEC_PER_SEC), "State machine should become quiescent") - quiescentExpectation.fulfill() - } - // Wait for the block above to fire before continuing - self.wait(for: [asyncExpectation], timeout: 10) - - // Run initialization, like the real secd will do - OctagonInitialize() - - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - XCTAssertTrue(self.cuttlefishContext.stateMachine.isPaused(), "State machine should be stopped") - self.assertNoAccount(context: self.cuttlefishContext) - - XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should be quiescent") - - self.wait(for: [quiescentExpectation], timeout: 10) - - // CKKS should also be logged out, since Octagon believes there's no account - assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) - } - func testLoadToUntrusted() throws { self.startCKAccountStatusMock() + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + // With no identity but AuthKit reporting an existing iCloud account, Octagon should go directly into 'untrusted' - OctagonInitialize() + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) } func testLoadToUntrustedIfTPHHasPreparedIdentityOnly() throws { self.startCKAccountStatusMock() + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + // Prepare an identity, then pretend like securityd thought it was in the right account let containerName = OTCKContainerName let contextName = OTDefaultContext @@ -1024,14 +1287,15 @@ class OctagonTests: OctagonTestsBase { machineID: "asdf", bottleSalt: "123456789", bottleID: UUID().uuidString, - modelID: "asdf", + modelID: "iPhone9,1", deviceName: "asdf", serialNumber: "1234", osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -1051,7 +1315,10 @@ class OctagonTests: OctagonTestsBase { XCTAssertNoThrow(try account.saveToKeychain(forContainer: containerName, contextID: contextName), "Should be no error saving fake account metadata") - OctagonInitialize() + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) @@ -1060,79 +1327,14 @@ class OctagonTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) } - func testSignIn() throws { - self.startCKAccountStatusMock() - - // Device is signed out - self.mockAuthKit.altDSID = nil - self.mockAuthKit.hsa2 = false - - // With no account, Octagon should go directly into 'NoAccount' - self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - - // Sign in occurs - let newAltDSID = UUID().uuidString - self.mockAuthKit.altDSID = newAltDSID - self.mockAuthKit.hsa2 = true - XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") - - // Octagon should go into 'untrusted' - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 100 * NSEC_PER_SEC) - self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) - - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) - - // On sign-out, octagon should go back to 'no account' - self.mockAuthKit.altDSID = nil - XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "sign-out shouldn't error") - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - self.assertNoAccount(context: self.cuttlefishContext) - - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) - } - - func testSignInWithDelayedHSA2Status() throws { - self.startCKAccountStatusMock() - - // Device is signed out - self.mockAuthKit.altDSID = nil - self.mockAuthKit.hsa2 = false - - // With no account, Octagon should go directly into 'NoAccount' - self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - - // Sign in occurs, but HSA2 status isn't here yet - let newAltDSID = UUID().uuidString - self.mockAuthKit.altDSID = newAltDSID - XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") - - // Octagon should go into 'waitforhsa2' - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForHSA2, within: 10 * NSEC_PER_SEC) - - self.mockAuthKit.hsa2 = true - XCTAssertNoThrow(try self.cuttlefishContext.idmsTrustLevelChanged(), "Notification of IDMS trust level shouldn't error") - - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) - - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) - - // On sign-out, octagon should go back to 'no account' - self.mockAuthKit.altDSID = nil - XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "sign-out shouldn't error") - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - self.assertNoAccount(context: self.cuttlefishContext) - - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) - } - func testNewFriendsForEmptyAccount() throws { self.startCKAccountStatusMock() + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) do { let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) @@ -1146,12 +1348,19 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: self.cuttlefishContext) self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) + // and the act of calling newFriends should set the CDP bit + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .enabled, "CDP status should be 'enabled'") + // and all subCKKSes should enter ready... - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + // Also, CKKS should be configured with the prevailing policy version + XCTAssertNotNil(self.injectedManager?.policy, "Should have given CKKS a TPPolicy during initialization") + XCTAssertEqual(self.injectedManager?.policy?.version, prevailingPolicyVersion, "Policy given to CKKS should be prevailing policy") + // TODO: add a CKKS item } @@ -1196,7 +1405,7 @@ class OctagonTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - let clique = try OTClique(contextData: self.otcliqueContext) + let clique = OTClique(contextData: self.otcliqueContext) // Now, call requestToJoin. It should cause an establish to happen try clique.requestToJoinCircle() @@ -1227,6 +1436,7 @@ class OctagonTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -1255,6 +1465,7 @@ class OctagonTests: OctagonTestsBase { func testDeviceFetchRetry() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let ckError = FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .transactionalFailure) @@ -1281,36 +1492,22 @@ class OctagonTests: OctagonTestsBase { func testDeviceFetchRetryFail() throws { self.startCKAccountStatusMock() - self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + self.assertResetAndBecomeTrustedInDefaultContext() let ckError = FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .transactionalFailure) self.fakeCuttlefishServer.nextFetchErrors.append(ckError) self.fakeCuttlefishServer.nextFetchErrors.append(ckError) - self.cuttlefishContext.notifyContainerChange(nil) - do { - let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) - XCTAssertNotNil(clique, "Clique should not be nil") - } catch { - XCTFail("Shouldn't have errored making new friends: \(error)") - } - - // Now, we should be in 'ready' - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 20 * NSEC_PER_SEC) - self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - self.verifyDatabaseMocks() - self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) - - self.cuttlefishContext.notifyContainerChange(nil) - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 20 * NSEC_PER_SEC) + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, states: [OctagonStateReadyUpdated]) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 30 * NSEC_PER_SEC) } func testNewFriendsForEmptyAccountReturnsMoreChanges() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.fakeCuttlefishServer.nextEstablishReturnsMoreChanges = true @@ -1335,7 +1532,7 @@ class OctagonTests: OctagonTestsBase { } func testNewFriendsForEmptyAccountWithoutTLKsResetsZones() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID!) + self.putFakeKeyHierarchiesInCloudKit() // But do NOT add them to the keychain // CKKS+Octagon should reset the zones and be ready @@ -1343,6 +1540,7 @@ class OctagonTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) // CKKS should reset the zones after Octagon has entered @@ -1365,7 +1563,7 @@ class OctagonTests: OctagonTestsBase { } func testUploadTLKsRetry() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID!) + self.putFakeKeyHierarchiesInCloudKit() // But do NOT add them to the keychain // CKKS+Octagon should reset the zones and be ready @@ -1373,6 +1571,7 @@ class OctagonTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) // CKKS should reset the zones after Octagon has entered @@ -1406,6 +1605,7 @@ class OctagonTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -1437,28 +1637,23 @@ class OctagonTests: OctagonTestsBase { // these should be failures assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKUpload, within: 10 * NSEC_PER_SEC) self.cuttlefishContext.rpcStatus { _, _ in - } + } self.verifyDatabaseMocks() XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(60 * NSEC_PER_SEC), "Main cuttlefish context should quiesce before the test ends") } - func testNewFriendsForEmptyAccountWithTLKs() throws { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID!) - self.saveTLKMaterial(toKeychain: self.manateeZoneID!) + func testNewFriendsForEmptyAccountWithExistingTLKs() throws { + self.putFakeKeyHierarchiesInCloudKit() + self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() - // CKKS should go into 'logged out', as Octagon hasn't told it to go yet - assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) - self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) - - // CKKS should reset the zones after Octagon has entered - self.silentZoneDeletesAllowed = true + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) do { let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) @@ -1471,17 +1666,16 @@ class OctagonTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - // and all subCKKSes should enter ready upload... - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() } func testLoadToReadyOnRestart() throws { - let startDate = Date() self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -1493,21 +1687,27 @@ class OctagonTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + // Ensure CKKS has a policy after newFriends + XCTAssertNotNil(self.injectedManager?.policy, "Should have given CKKS a TPPolicy during initialization") + XCTAssertEqual(self.injectedManager?.policy?.version, prevailingPolicyVersion, "Policy given to CKKS should be prevailing policy") + let peerID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() XCTAssertNotNil(peerID, "Should have a peer ID after making new friends") var readyDate = CKKSAnalytics.logger().dateProperty(forKey: OctagonAnalyticsLastKeystateReady) XCTAssertNotNil(readyDate, "Should have a ready date") - XCTAssert(readyDate! > startDate, "ready date should be after startdate") + XCTAssert(try XCTUnwrap(readyDate) > startDate, "ready date should be after startdate") // Now restart the context self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) self.restartCKKSViews() self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + XCTAssertNil(self.injectedManager?.policy, "CKKS should not have a policy after 'restart'") + let restartDate = Date() self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) @@ -1518,16 +1718,42 @@ class OctagonTests: OctagonTestsBase { XCTAssertNotNil(restartedPeerID, "Should have a peer ID after restarting") XCTAssertEqual(peerID, restartedPeerID, "Should have the same peer ID after restarting") - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertNotNil(self.injectedManager?.policy, "Should have given CKKS a TPPolicy after restart") + XCTAssertEqual(self.injectedManager?.policy?.version, prevailingPolicyVersion, "Policy given to CKKS after restart should be prevailing policy") readyDate = CKKSAnalytics.logger().dateProperty(forKey: OctagonAnalyticsLastKeystateReady) XCTAssertNotNil(readyDate, "Should have a ready date") - XCTAssert(readyDate! > restartDate, "ready date should be after re-startdate") + XCTAssert(try XCTUnwrap(readyDate) > restartDate, "ready date should be after re-startdate") + } + + func testFillInUnknownAttemptedJoinState() throws { + self.startCKAccountStatusMock() + + _ = self.assertResetAndBecomeTrustedInDefaultContext() + + try self.cuttlefishContext.accountMetadataStore.persistAccountChanges { metadata in + metadata.attemptedJoin = .UNKNOWN + return metadata + } + + self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + self.restartCKKSViews() + self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + // And check that the metadata is fixed: + let metadata = try self.cuttlefishContext.accountMetadataStore.loadOrCreateAccountMetadata() + XCTAssertEqual(metadata.attemptedJoin, .ATTEMPTED, "Should have attempted a join") } func testLoadToUntrustedOnRestartIfKeysGone() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -1567,6 +1793,7 @@ class OctagonTests: OctagonTestsBase { func testLoadToUntrustedOnRestartIfTPHLosesAllData() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -1606,6 +1833,7 @@ class OctagonTests: OctagonTestsBase { func testLoadToTrustedOnRestartIfMismatchedPeerIDs() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -1641,70 +1869,6 @@ class OctagonTests: OctagonTestsBase { XCTAssertEqual(peerID, newPeerID, "Should now have TPH's peer ID") } - func testStatusRPCsWithUnknownCloudKitAccount() throws { - // If CloudKit isn't returning our calls, we should still return something reasonable... - let statusexpectation = self.expectation(description: "trust status returns") - let configuration = OTOperationConfiguration() - configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _ in - XCTAssertTrue([.absent].contains(egoStatus), "Self peer should be in the 'absent' state") - statusexpectation.fulfill() - } - self.wait(for: [statusexpectation], timeout: 10) - - // Now sign in to 'untrusted' - self.startCKAccountStatusMock() - - self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) - - // And restart, without any idea of the cloudkit state - self.ckaccountHoldOperation = BlockOperation() - self.injectedManager!.accountTracker = CKKSAccountStateTracker(self.injectedManager!.container, - nsnotificationCenterClass: FakeNSNotificationCenter.self as CKKSNSNotificationCenter.Type) - self.manager.accountStateTracker = self.injectedManager!.accountTracker - - self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.restartCKKSViews() - self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - - // Should know it's untrusted - self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) - self.startCKAccountStatusMock() - - // Now become ready - do { - let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) - XCTAssertNotNil(clique, "Clique should not be nil") - } catch { - XCTFail("Shouldn't have errored making new friends: \(error)") - } - - // Now, we should be in 'ready' - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) - - // and all subCKKSes should enter ready... - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - self.verifyDatabaseMocks() - - // Restart one more time: - - self.ckaccountHoldOperation = BlockOperation() - self.injectedManager!.accountTracker = CKKSAccountStateTracker(self.injectedManager!.container, - nsnotificationCenterClass: FakeNSNotificationCenter.self as CKKSNSNotificationCenter.Type) - self.manager.accountStateTracker = self.injectedManager!.accountTracker - - self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.restartCKKSViews() - self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - - self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) - } - func testRestoreToNewClique() throws { self.startCKAccountStatusMock() @@ -1734,18 +1898,20 @@ class OctagonTests: OctagonTestsBase { self.verifyDatabaseMocks() - let memberIdentifier = clique!.cliqueMemberIdentifier + let memberIdentifier = try XCTUnwrap(clique).cliqueMemberIdentifier let dumpExpectation = self.expectation(description: "dump callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, error in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, error in XCTAssertNil(error, "Should be no error dumping data") XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary - XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let peerID = egoSelf!["peerID"] as? String - XCTAssertNotNil(peerID, "peerID should not be nil") - XCTAssertEqual(memberIdentifier, peerID, "memberIdentifier should match tph's peer ID") + do { + let realDump = try XCTUnwrap(dump, "dump should not be nil") + let egoSelf = try XCTUnwrap(realDump["self"] as? [String: AnyObject], "egoSelf should not be nil") + let peerID = try XCTUnwrap(egoSelf["peerID"] as? String, "peerID should not be nil") + XCTAssertEqual(memberIdentifier, peerID, "memberIdentifier should match tph's peer ID") + } catch { + XCTFail("Test failed by exception: \(error)") + } dumpExpectation.fulfill() } @@ -1755,122 +1921,58 @@ class OctagonTests: OctagonTestsBase { func testLeaveClique() throws { self.startCKAccountStatusMock() - self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - - let clique: OTClique - do { - clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) - XCTAssertNotNil(clique, "Clique should not be nil") - } catch { - XCTFail("Shouldn't have errored making new friends: \(error)") - throw error - } + self.assertResetAndBecomeTrustedInDefaultContext() + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatusIsSet, "SOS adapter should have been told that CKKS4All is enabled") + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + self.mockSOSAdapter.ckks4AllStatusIsSet = false + // Octagon should refuse to leave + let clique = self.cliqueFor(context: self.cuttlefishContext) + XCTAssertThrowsError(try clique.leave(), "Should be an error departing clique when is only peer") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - self.verifyDatabaseMocks() - // Technically, it's a server-side cuttlefish error for the last signed-in peer to leave. But, for now, just go for it. - XCTAssertNoThrow(try clique.leave(), "Should be no error departing clique") + // until there's another peer around + let joiningContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit2) + self.assertJoinViaEscrowRecoveryFromDefaultContextWithReciprocationAndTLKShares(joiningContext: joiningContext) + + XCTAssertNoThrow(try clique.leave(), "Should be an error departing clique when is only peer") // securityd should now consider itself untrusted self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatusIsSet, "SOS adapter should have been told that CKKS4All is not enabled") + XCTAssertFalse(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is not enabled") // TODO: an item added here shouldn't sync } - func testSignOut() throws { + func testLeaveCliqueWhenNotInAccount() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - do { - let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) - XCTAssertNotNil(clique, "Clique should not be nil") - } catch { - XCTFail("Shouldn't have errored making new friends: \(error)") + let leaveExpectation = self.expectation(description: "leave callback occurs") + + self.cuttlefishContext.rpcLeaveClique { error in + XCTAssertNil(error, "error should be nil") + leaveExpectation.fulfill() } + self.wait(for: [leaveExpectation], timeout: 5) - // Now, we should be in 'ready' - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - self.verifyDatabaseMocks() - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - - // And 'dump' should show some information - let dumpExpectation = self.expectation(description: "dump callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, error in - XCTAssertNil(error, "Should be no error dumping data") - XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary - XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let peerID = egoSelf!["peerID"] as? String - XCTAssertNotNil(peerID, "peerID should not be nil") - - dumpExpectation.fulfill() - } - self.wait(for: [dumpExpectation], timeout: 10) - - // Turn off the CK account too - self.accountStatus = .noAccount - self.accountStateTracker.notifyCKAccountStatusChangeAndWaitForSignal() - - XCTAssertNoThrow(try self.cuttlefishContext.accountNoLongerAvailable(), "Should be no issue signing out") - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - self.assertNoAccount(context: self.cuttlefishContext) - - // And 'dump' should show nothing - let signedOutDumpExpectation = self.expectation(description: "dump callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, error in - XCTAssertNil(error, "Should be no error dumping data") - XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary - XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - XCTAssertEqual(egoSelf!.count, 0, "egoSelf should have zero elements") - - signedOutDumpExpectation.fulfill() - } - self.wait(for: [signedOutDumpExpectation], timeout: 10) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) - - //check trust status - let checkTrustExpectation = self.expectation(description: "checkTrustExpectation callback occurs") - let configuration = OTOperationConfiguration() - self.cuttlefishContext.rpcTrustStatus(configuration) { _, _, _, _, _ in - checkTrustExpectation.fulfill() - } - self.wait(for: [checkTrustExpectation], timeout: 10) - - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - - // And 'dump' should show nothing - let signedOutDumpExpectationAfterCheckTrustStatus = self.expectation(description: "dump callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, error in - XCTAssertNil(error, "Should be no error dumping data") - XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary - XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - XCTAssertEqual(egoSelf!.count, 0, "egoSelf should have zero elements") - - signedOutDumpExpectationAfterCheckTrustStatus.fulfill() - } - self.wait(for: [signedOutDumpExpectationAfterCheckTrustStatus], timeout: 10) - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - self.assertNoAccount(context: self.cuttlefishContext) + // securityd should still consider itself untrusted + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) } func testCliqueFriendAPI() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) @@ -1886,7 +1988,7 @@ class OctagonTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) self.verifyDatabaseMocks() - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) let peer1ID = fetchEgoPeerID() @@ -1915,7 +2017,7 @@ class OctagonTests: OctagonTestsBase { accountStateTracker: self.accountStateTracker, deviceInformationAdapter: peer2DeviceAdapter) - self.setAllowListToCurrentAuthKit(container: OTCKContainerName, context: peer2ContextID) + self.setAllowListToCurrentAuthKit(container: OTCKContainerName, context: peer2ContextID, accountIsDemo: false) var peer2ID: String! let joinExpectation = self.expectation(description: "join callback occurs") @@ -1931,8 +2033,9 @@ class OctagonTests: OctagonTestsBase { osVersion: peer2DeviceAdapter.osVersion(), policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(permanentInfo, "Should have a permanent identity") XCTAssertNotNil(permanentInfoSig, "Should have a permanent identity signature") @@ -1955,7 +2058,7 @@ class OctagonTests: OctagonTestsBase { voucherSig: voucherSig!, ckksKeys: [], tlkShares: [], - preapprovedKeys: []) { peerID, _, error in + preapprovedKeys: []) { peerID, _, _, error in XCTAssertNil(error, "Should be no error joining") XCTAssertNotNil(peerID, "Should have a peerID") peer2ID = peerID @@ -1970,6 +2073,7 @@ class OctagonTests: OctagonTestsBase { account.peerID = peer2ID account.icloudAccountState = .ACCOUNT_AVAILABLE account.trustState = .TRUSTED + account.attemptedJoin = . ATTEMPTED XCTAssertNoThrow(try account.saveToKeychain(forContainer: OTCKContainerName, contextID: peer2ContextID), "Should be no error saving fake account metadata") peer2.startOctagonStateMachine() @@ -1977,6 +2081,7 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: peer2) // Now that we've lied enough... + self.assertAllCKKSViewsUpload(tlkShares: 1, filter: { $0.zoneName == "LimitedPeersAllowed" }) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), @@ -1984,6 +2089,10 @@ class OctagonTests: OctagonTestsBase { XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer1ID)), "peer 2 should trust peer 1") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + // But does peer1 claim to know peer2? do { let peersByID = try clique.peerDeviceNamesByPeerID() @@ -2013,43 +2122,16 @@ class OctagonTests: OctagonTestsBase { } } - func testNoAccountLeadsToInitialize() throws { - self.startCKAccountStatusMock() - - // With no identity and AuthKit reporting no iCloud account, Octagon should go directly into 'no account' - self.mockAuthKit.altDSID = nil - - // Run initialization, like the real secd will do - OctagonInitialize() - - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - - self.mockAuthKit.altDSID = "1234" - let signinExpectation = self.expectation(description: "sign in returns") - self.otControl.sign(in: "1234", container: nil, context: OTDefaultContext) { error in - XCTAssertNil(error, "error should be nil") - signinExpectation.fulfill() - } - self.wait(for: [signinExpectation], timeout: 10) - - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - - } - func testOTCliqueOctagonAuthoritativeTrustResponse() throws { self.startCKAccountStatusMock() OctagonAuthoritativeTrustSetIsEnabled(true) - do { - let absentClique = try OTClique(contextData: self.otcliqueContext) - let absentStatus = absentClique.fetchStatus(nil) - XCTAssertEqual(absentStatus, CliqueStatus.absent, "clique should return Absent") - } catch { - XCTFail("Shouldn't have errored making new friends: \(error)") - throw error - } + let absentClique = OTClique(contextData: self.otcliqueContext) + let absentStatus = absentClique.fetchStatus(nil) + XCTAssertEqual(absentStatus, CliqueStatus.absent, "clique should return Absent") self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -2059,7 +2141,6 @@ class OctagonTests: OctagonTestsBase { let status = clique.fetchStatus(nil) XCTAssertEqual(status, CliqueStatus.in, "clique should return In") - } catch { XCTFail("Shouldn't have errored making new friends: \(error)") throw error @@ -2069,7 +2150,9 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: self.cuttlefishContext) self.verifyDatabaseMocks() - // Technically, it's a server-side cuttlefish error for the last signed-in peer to leave. But, for now, just go for it. + let joiningContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit2) + self.assertJoinViaEscrowRecoveryFromDefaultContextWithReciprocationAndTLKShares(joiningContext: joiningContext) + XCTAssertNoThrow(try clique.leave(), "Should be no error departing clique") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let status = clique.fetchStatus(nil) @@ -2089,12 +2172,11 @@ class OctagonTests: OctagonTestsBase { OctagonSetPlatformSupportsSOS(true) let status = newClique.fetchStatus(nil) XCTAssertEqual(status, CliqueStatus.in, "clique should return In") - } catch { XCTFail("Shouldn't have errored making new friends: \(error)") throw error } - let newContext = self.manager.context(forContainerName: OTCKContainerName, contextID: newOTCliqueContext.context!) + let newContext = self.manager.context(forContainerName: OTCKContainerName, contextID: newOTCliqueContext.context) self.assertEnters(context: newContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) } @@ -2119,54 +2201,32 @@ class OctagonTests: OctagonTestsBase { json: false) } - func testNoAccountTimeoutTransitionWatcher() throws { - self.startCKAccountStatusMock() - - // With no identity and AuthKit reporting no iCloud account, Octagon should go directly into 'no account' - self.mockAuthKit.altDSID = nil - - // Run initialization, like the real secd will do - OctagonInitialize() - self.cuttlefishContext.stateMachine.setWatcherTimeout(2 * NSEC_PER_SEC) - - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - XCTAssertTrue(self.cuttlefishContext.stateMachine.isPaused(), "State machine should be stopped") - self.assertNoAccount(context: self.cuttlefishContext) - XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should be quiescent") - - let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") - self.cuttlefishContext.join(withBottle: "bottleID", entropy: Data(), bottleSalt: "peer2AltDSID") { error in - XCTAssertNotNil(error, "error should not be nil") - joinWithBottleExpectation.fulfill() - } - self.wait(for: [joinWithBottleExpectation], timeout: 3) - } - func testFailingStateTransitionWatcher() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) // Set up a watcher that we expect to fail... let path = OctagonStateTransitionPath(from: [ OctagonStateResetAndEstablish: [ - OctagonStateInitiatorVouchWithBottle: [ + OctagonStateBottleJoinVouchWithBottle: [ OctagonStateResetAndEstablish: OctagonStateTransitionPathStep.success(), ], ], ]) let watcher = OctagonStateTransitionWatcher(named: "should-fail", serialQueue: self.cuttlefishContext.queue, - path: path!, + path: try XCTUnwrap(path), initialRequest: nil) self.cuttlefishContext.stateMachine.register(watcher) let watcherCompleteOperationExpectation = self.expectation(description: "watcherCompleteOperationExpectation returns") - let watcherFinishOp = CKKSResultOperation.named("should-fail-cleanup", with: { + let watcherFinishOp = CKKSResultOperation.named("should-fail-cleanup") { XCTAssertNotNil(watcher.result.error, "watcher should have errored") watcherCompleteOperationExpectation.fulfill() - }) + } watcherFinishOp.addDependency(watcher.result) self.operationQueue.addOperation(watcherFinishOp) @@ -2189,6 +2249,7 @@ class OctagonTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let stateTransitionOp = OctagonStateTransitionOperation(name: "will-never-run", @@ -2202,22 +2263,22 @@ class OctagonTests: OctagonTestsBase { // Set up a watcher that we expect to fail due to its initial transition op timing out... let path = OctagonStateTransitionPath(from: [ OctagonStateResetAndEstablish: [ - OctagonStateInitiatorVouchWithBottle: [ - OctagonStateResetAndEstablish: OctagonStateTransitionPathStep.success(), - ], + OctagonStateBottleJoinVouchWithBottle: [ + OctagonStateResetAndEstablish: OctagonStateTransitionPathStep.success(), ], - ]) + ], + ]) let watcher = OctagonStateTransitionWatcher(named: "should-fail", serialQueue: self.cuttlefishContext.queue, - path: path!, + path: try XCTUnwrap(path), initialRequest: (requestNever as! OctagonStateTransitionRequest)) self.cuttlefishContext.stateMachine.register(watcher) let watcherCompleteOperationExpectation = self.expectation(description: "watcherCompleteOperationExpectation returns") - let watcherFinishOp = CKKSResultOperation.named("should-fail-cleanup", with: { + let watcherFinishOp = CKKSResultOperation.named("should-fail-cleanup") { XCTAssertNotNil(watcher.result.error, "watcher should have errored") watcherCompleteOperationExpectation.fulfill() - }) + } watcherFinishOp.addDependency(watcher.result) self.operationQueue.addOperation(watcherFinishOp) @@ -2233,6 +2294,7 @@ class OctagonTests: OctagonTestsBase { OctagonAuthoritativeTrustSetIsEnabled(true) self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -2248,7 +2310,9 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: self.cuttlefishContext) self.verifyDatabaseMocks() - // Technically, it's a server-side cuttlefish error for the last signed-in peer to leave. But, for now, just go for it. + let joiningContext = self.makeInitiatorContext(contextID: "joiner", authKitAdapter: self.mockAuthKit2) + self.assertJoinViaEscrowRecoveryFromDefaultContextWithReciprocationAndTLKShares(joiningContext: joiningContext) + XCTAssertNoThrow(try clique.leave(), "Should be no error departing clique") // securityd should now consider itself untrusted @@ -2260,8 +2324,8 @@ class OctagonTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let cfuExpectation = self.expectation(description: "cfu callback occurs") - self.cuttlefishContext.setPostedBool(false) - self.cuttlefishContext.checkTrustStatusAndPostRepairCFUIfNecessary { _, posted, _, error in + self.cuttlefishContext.followupHandler.clearAllPostedFlags() + self.cuttlefishContext.checkTrustStatusAndPostRepairCFUIfNecessary { _, posted, _, _, error in #if !os(tvOS) XCTAssertTrue(posted, "posted should be true") #else @@ -2274,10 +2338,10 @@ class OctagonTests: OctagonTestsBase { } func testDeviceLockedDuringAccountRetrieval() throws { - self.startCKAccountStatusMock() + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) - self.aksLockState = true - self.lockStateTracker.recheck() + self.startCKAccountStatusMock() let initiatorContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext, @@ -2287,17 +2351,25 @@ class OctagonTests: OctagonTestsBase { accountStateTracker: self.accountStateTracker, deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iPhone9,1", deviceName: "test-SOS-iphone", serialNumber: "456", osVersion: "iOS (fake version)")) - let accountMetadataStoreActual = initiatorContext.accountMetadataStore //grab the previously instantiated account state holder + // Pre-create some Account metadata, so that Octagon will experience a keychain locked error when loading + try initiatorContext.accountMetadataStore.persistAccountChanges { metadata in + return metadata + } - initiatorContext.setAccountStateHolder(self.accountMetaDataStore) // set the mocked account state holder + // Lock all AKS classes + self.aksLockState = true + SecMockAKS.lockClassA_C() + self.lockStateTracker.recheck() initiatorContext.startOctagonStateMachine() - self.assertEnters(context: initiatorContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: initiatorContext, state: OctagonStateWaitForClassCUnlock, within: 10 * NSEC_PER_SEC) - initiatorContext.setAccountStateHolder(accountMetadataStoreActual) //re-set the actual store self.aksLockState = false self.lockStateTracker.recheck() + self.assertEnters(context: initiatorContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + + XCTAssertNoThrow(try initiatorContext.setCDPEnabled()) self.assertEnters(context: initiatorContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) } @@ -2305,6 +2377,7 @@ class OctagonTests: OctagonTestsBase { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -2333,6 +2406,7 @@ class OctagonTests: OctagonTestsBase { func testFetchViewList() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -2347,113 +2421,50 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: self.cuttlefishContext) #if !os(tvOS) - let expectedViews = Set(["ProtectedCloudStorage", - "AutoUnlock", - "LimitedPeersAllowed", - "SecureObjectSync", - "DevicePairing", - "Engram", - "Home", - "Applications", - "WiFi", - "Health", - "Manatee", - "CreditCards", - "Passwords", - "ApplePay", ]) + let expectedViews = Set([ + "ApplePay", + "Applications", + "AutoUnlock", + "Backstop", + "CreditCards", + "DevicePairing", + "Engram", + "Health", + "Home", + "LimitedPeersAllowed", + "Manatee", + "Passwords", + "ProtectedCloudStorage", + "SecureObjectSync", + "WiFi", + ]) #else let expectedViews = Set(["LimitedPeersAllowed", + "Home", "WiFi", ]) #endif let getViewsExpectation = self.expectation(description: "getViews callback happens") - self.tphClient.getViewsWithContainer(OTCKContainerName, context: OTDefaultContext, inViews: []) { outViews, error in + self.tphClient.fetchCurrentPolicy(withContainer: OTCKContainerName, context: OTDefaultContext, modelIDOverride: nil) { outPolicy, _, error in XCTAssertNil(error, "should not have failed") - XCTAssertEqual(expectedViews, Set(outViews!)) + XCTAssertEqual(expectedViews, outPolicy!.viewList) getViewsExpectation.fulfill() } self.wait(for: [getViewsExpectation], timeout: 10) } - func testMergedViewListOff() throws { - self.startCKAccountStatusMock() - self.cuttlefishContext.viewManager!.setOverrideCKKSViewsFromPolicy(false) - self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - - do { - let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) - XCTAssertNotNil(clique, "Clique should not be nil") - } catch { - XCTFail("Shouldn't have errored making new friends: \(error)") - } - - // Now, we should be in 'ready' - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - - let viewList = self.cuttlefishContext.viewManager!.viewList() - #if !os(tvOS) - let expected = Set(["Manatee"]) - #else - let expected = Set(["LimitedPeersAllowed"]) - #endif - XCTAssertEqual(expected, viewList) - } - - func testMergedViewListOn() throws { - /* - self.startCKAccountStatusMock() - self.cuttlefishContext.viewManager!.setOverrideCKKSViewsFromPolicy(true) - self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - - do { - let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, .testGenerated) - XCTAssertNotNil(clique, "Clique should not be nil") - } catch { - XCTFail("Shouldn't have errored making new friends: \(error)") - } - - // Now, we should be in 'ready' - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - - let viewList = self.cuttlefishContext.viewManager!.viewList() - let expected = Set([ - "ApplePay", - "Applications", - "AutoUnlock", - "Backstop", - "DevicePairing", - "Engram", - "Health", - "Home", - "LimitedPeersAllowed", - "Manatee", - "ProtectedCloudStorage", - "SafariCreditCards", - "SafariPasswords", - "SecureObjectSync", - "WiFi", - "keychain", - ]) - XCTAssertEqual(expected, viewList) - */ - } - let octagonNotificationName = "com.apple.security.octagon.trust-status-change" func testNotifications() throws { - let contextName = OTDefaultContext let containerName = OTCKContainerName let untrustedNotification = XCTDarwinNotificationExpectation(notificationName: octagonNotificationName) self.startCKAccountStatusMock() - self.cuttlefishContext.startOctagonStateMachine() + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.wait(for: [untrustedNotification], timeout: 2) @@ -2505,11 +2516,11 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: self.cuttlefishContext) let statusExpectation = self.expectation(description: "status callback occurs") - self.tphClient.dumpEgoPeer(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID, reply: { _, _, stableInfo, _, error in + self.tphClient.dumpEgoPeer(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { _, _, stableInfo, _, error in XCTAssertNil(error, "should be no error dumping ego peer") XCTAssertEqual(stableInfo?.deviceName, newDeviceName, "device name should be updated") statusExpectation.fulfill() - }) + } self.wait(for: [statusExpectation], timeout: 2) // Receiving a push shouldn't cause another update to be sent @@ -2612,15 +2623,31 @@ class OctagonTests: OctagonTestsBase { } func testAPSRateLimiter() throws { - let untrustedNotification = XCTDarwinNotificationExpectation(notificationName: octagonNotificationName) self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.cuttlefishContext.startOctagonStateMachine() + // Octagon will fetch once to determine its trust state + let trustStateFetchExpectation = self.expectation(description: "trust state fetch occurs") + self.fakeCuttlefishServer.fetchChangesListener = { [unowned self] _ in + self.fakeCuttlefishServer.fetchChangesListener = nil + trustStateFetchExpectation.fulfill() + return nil + } + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.wait(for: [untrustedNotification], timeout: 2) + self.wait(for: [trustStateFetchExpectation], timeout: 10) + + let fetchExpectation = self.expectation(description: "fetch occurs") + self.fakeCuttlefishServer.fetchChangesListener = { _ in + fetchExpectation.fulfill() + return nil + } + self.cuttlefishContext.notifyContainerChange(nil) self.cuttlefishContext.notifyContainerChange(nil) @@ -2631,7 +2658,8 @@ class OctagonTests: OctagonTestsBase { self.cuttlefishContext.notifyContainerChange(nil) - XCTAssertEqual(self.fakeCuttlefishServer.fetchChangesCalledCount, 1, "fetchChanges should have been called 1 times") + self.wait(for: [fetchExpectation], timeout: 10) + XCTAssertEqual(self.fakeCuttlefishServer.fetchChangesCalledCount, 2, "fetchChanges should have been called 1 times") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) @@ -2641,72 +2669,48 @@ class OctagonTests: OctagonTestsBase { let untrustedNotification = XCTDarwinNotificationExpectation(notificationName: octagonNotificationName) self.startCKAccountStatusMock() + + // Set the CDP bit before the test begins, so we don't have to fetch to discover CDP status + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.cuttlefishContext.startOctagonStateMachine() + // Octagon will fetch once to determine its trust state + let trustStateFetchExpectation = self.expectation(description: "trust state fetch occurs") + self.fakeCuttlefishServer.fetchChangesListener = { [unowned self] _ in + self.fakeCuttlefishServer.fetchChangesListener = nil + trustStateFetchExpectation.fulfill() + return nil + } + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.wait(for: [untrustedNotification], timeout: 2) - self.cuttlefishContext.notifyContainerChange(nil) + self.wait(for: [trustStateFetchExpectation], timeout: 10) + + let fetchExpectation = self.expectation(description: "fetch occurs") + self.fakeCuttlefishServer.fetchChangesListener = { _ in + fetchExpectation.fulfill() + return nil + } self.cuttlefishContext.notifyContainerChange(nil) - + self.cuttlefishContext.notifyContainerChange(nil) + self.cuttlefishContext.notifyContainerChange(nil) self.cuttlefishContext.notifyContainerChange(nil) - self.cuttlefishContext.notifyContainerChange(nil) - - XCTAssertEqual(self.fakeCuttlefishServer.fetchChangesCalledCount, 1, "fetchChanges should have been called 1 times") + self.wait(for: [fetchExpectation], timeout: 10) + XCTAssertEqual(self.fakeCuttlefishServer.fetchChangesCalledCount, 2, "fetchChanges should have been called 1 times") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) } - func testEnsureNonDefaultTimeOut() { - self.startCKAccountStatusMock() - OctagonSetPlatformSupportsSOS(true) - - let initiatorPiggybackingConfig = OTJoiningConfiguration(protocolType: OTProtocolPiggybacking, uniqueDeviceID: "initiator", uniqueClientID: "acceptor", containerName: OTCKContainerName, contextID: OTDefaultContext, epoch: 1, isInitiator: true) - - let resetAndEstablishExpectation = self.expectation(description: "resetAndEstablish callback occurs") - self.manager.resetAndEstablish(OTCKContainerName, - context: OTDefaultContext, - altDSID: "new altDSID", - resetReason: .testGenerated) { resetError in - XCTAssertNil(resetError, "Should be no error calling resetAndEstablish") - resetAndEstablishExpectation.fulfill() - } - - self.wait(for: [resetAndEstablishExpectation], timeout: 10) - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - - /*begin message passing*/ - let rpcFirstInitiatorJoiningMessageCallBack = self.expectation(description: "Creating prepare message callback") - self.manager.rpcPrepareIdentityAsApplicant(with: initiatorPiggybackingConfig) { pID, pI, pIS, sI, sIS, error in - XCTAssertNil(pID, "peerID should not be nil") - XCTAssertNil(pI, "permanentInfo should not be nil") - XCTAssertNil(pIS, "permanentInfoSig should not be nil") - XCTAssertNil(sI, "stableInfo should not be nil") - XCTAssertNil(sIS, "stableInfoSig should not be nil") - - XCTAssertNotNil(error, "error should not be nil") - rpcFirstInitiatorJoiningMessageCallBack.fulfill() - } - //default value for ops is 10 seconds, ensuring the rpc times out in 2 seconds which is the new value set on the request - self.wait(for: [rpcFirstInitiatorJoiningMessageCallBack], timeout: 3) - - //this call uses the default value and should timeout in 10 seconds - let upgradeCallback = self.expectation(description: "attempting sos upgrade callback") - self.manager.attemptSosUpgrade(OTCKContainerName, context: OTDefaultContext) { error in - XCTAssertNotNil(error, "error should not be nil") - upgradeCallback.fulfill() - } - self.wait(for: [upgradeCallback], timeout: 11) - } - - func testTTRTrusted() { - + func testTTRTrusted() throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { @@ -2732,7 +2736,7 @@ class OctagonTests: OctagonTestsBase { self.sendTTRRequest(context: self.cuttlefishContext) - self.wait(for: [self.ttrExpectation!], timeout: 10) + self.wait(for: [try XCTUnwrap(self.ttrExpectation)], timeout: 10) } } @@ -2740,12 +2744,27 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { struct TestCase { let model: String let success: Bool - let sendTLKs: Bool + let manateeTLKs: Bool + let limitedTLKs: Bool + } + + func assertTLKs(expectation: TestCase, receiverPeerID: String, senderPeerID: String) { + let haveManateeTLK = self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, + senderPeerID: senderPeerID, + zoneID: self.manateeZoneID) + let haveLimitedPeersAllowedTLK = self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, + senderPeerID: senderPeerID, + zoneID: self.limitedPeersAllowedZoneID) + + XCTAssertEqual(haveManateeTLK, expectation.manateeTLKs, "manatee should be what's expected: \(expectation)") + XCTAssertEqual(haveLimitedPeersAllowedTLK, expectation.limitedTLKs, "limited should be what's expected: \(expectation)") } func _testVouchers(expectations: [TestCase]) throws { self.startCKAccountStatusMock() + self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -2760,7 +2779,14 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - _ = fetchEgoPeerID() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + let ckksKeys: [CKKSKeychainBackedKeySet] = self.intendedCKKSZones.compactMap { zoneID in + let currentKeySet = CKKSCurrentKeySet.load(forZone: zoneID) + return try! currentKeySet.asKeychainBackedSet() + } + + let senderPeerID = fetchEgoPeerID() for testCase in expectations { let model = testCase.model @@ -2775,7 +2801,7 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { accountStateTracker: self.accountStateTracker, deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iPhone9,1", deviceName: "test-SOS-iphone", serialNumber: "456", osVersion: "iOS (fake version)")) - self.setAllowListToCurrentAuthKit(container: OTCKContainerName, context: peer2ContextID) + self.setAllowListToCurrentAuthKit(container: OTCKContainerName, context: peer2ContextID, accountIsDemo: false) let peer2DeviceName = "peer2-asdf" let joinExpectation = self.expectation(description: "join callback occurs") @@ -2791,8 +2817,9 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { osVersion: "something", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(permanentInfo, "Should have a permanent identity") XCTAssertNotNil(permanentInfoSig, "Should have a permanent identity signature") @@ -2806,17 +2833,22 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { permanentInfoSig: permanentInfoSig!, stableInfo: stableInfo!, stableInfoSig: stableInfoSig!, - ckksKeys: []) { voucher, voucherSig, error in + ckksKeys: ckksKeys) { voucher, voucherSig, error in XCTAssertNil(error, "Should be no error vouching") XCTAssertNotNil(voucher, "Should have a voucher") XCTAssertNotNil(voucherSig, "Should have a voucher signature") + + self.assertTLKs(expectation: testCase, + receiverPeerID: peerID!, + senderPeerID: senderPeerID) + self.tphClient.join(withContainer: OTCKContainerName, context: peer2ContextID, voucherData: voucher!, voucherSig: voucherSig!, ckksKeys: [], tlkShares: [], - preapprovedKeys: []) { peerID, _, error in + preapprovedKeys: []) { peerID, _, _, error in XCTAssertNil(error, "Should be no error joining") XCTAssertNotNil(peerID, "Should have a peerID") joinExpectation.fulfill() @@ -2834,6 +2866,11 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { XCTAssertNil(voucher, "voucher should be nil") XCTAssertNil(voucherSig, "voucherSig should be nil") XCTAssertNotNil(error, "error should be non nil") + + self.assertTLKs(expectation: testCase, + receiverPeerID: peerID!, + senderPeerID: senderPeerID) + joinExpectation.fulfill() } } @@ -2845,6 +2882,7 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { func _testJoin(expectations: [TestCase]) throws { self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let clique: OTClique @@ -2872,7 +2910,7 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { let peer2DeviceName = "peer2-device-name" var peer2ID: String! - self.setAllowListToCurrentAuthKit(container: OTCKContainerName, context: peer2ContextID) + self.setAllowListToCurrentAuthKit(container: OTCKContainerName, context: peer2ContextID, accountIsDemo: false) let joinExpectation = self.expectation(description: "join callback occurs") self.tphClient.prepare(withContainer: OTCKContainerName, @@ -2887,8 +2925,9 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { osVersion: "something", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(permanentInfo, "Should have a permanent identity") XCTAssertNotNil(permanentInfoSig, "Should have a permanent identity signature") @@ -2911,7 +2950,7 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { voucherSig: voucher!.sig, ckksKeys: [], tlkShares: [], - preapprovedKeys: []) { peerID, _, error in + preapprovedKeys: []) { peerID, _, _, error in if expectedSuccess { XCTAssertNil(error, "expected success") XCTAssertNotNil(peerID, "peerID should be set") @@ -2921,7 +2960,6 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { } joinExpectation.fulfill() } - } self.wait(for: [joinExpectation], timeout: 10) @@ -2939,9 +2977,11 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { return nil } - // Maybe send TLKs? - if testCase.sendTLKs { - self.assertAllCKKSViewsUpload(tlkShares: 1) + if testCase.manateeTLKs { + self.expectCKModifyKeyRecords(0, currentKeyPointerRecords: 0, tlkShareRecords: 1, zoneID: self.manateeZoneID) + } + if testCase.limitedTLKs { + self.expectCKModifyKeyRecords(0, currentKeyPointerRecords: 0, tlkShareRecords: 1, zoneID: self.limitedPeersAllowedZoneID) } self.cuttlefishContext.notifyContainerChange(nil) @@ -2950,69 +2990,59 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { self.fakeCuttlefishServer.updateListener = nil self.sendAllCKKSTrustedPeersChanged() - self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } + + self.assertTLKs(expectation: testCase, + receiverPeerID: peer2ID, + senderPeerID: peer1ID) } } } -class OctagonTestsOverrideModletV: OctagonTestsOverrideModelBase { - // If this test is running on a TV, we will send TLKs, since we're using the LimitedPeersAllowed view - #if !os(tvOS) - let sendTLKsToAllPeers = false - #else - let sendTLKsToAllPeers = true - #endif - +class OctagonTestsOverrideModelTV: OctagonTestsOverrideModelBase { override func setUp() { - super.setUp() + self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: "AppleTV5,3", + deviceName: "intro-TV", + serialNumber: "456", + osVersion: "tvOS (whatever TV version)") - self.mockDeviceInfo.mockModelID = "AppleTV5,3" - self.mockDeviceInfo.mockDeviceName = "intro-TV" - self.mockDeviceInfo.mockSerialNumber = "456" - self.mockDeviceInfo.mockOsVersion = "iOS (whatever TV version)" + super.setUp() } func testVoucherFromTV() throws { - try self._testVouchers(expectations: [TestCase(model: "AppleTV5,3", success: true, sendTLKs: sendTLKsToAllPeers), - TestCase(model: "MacFoo", success: false, sendTLKs: sendTLKsToAllPeers), - TestCase(model: "Watch17", success: false, sendTLKs: sendTLKsToAllPeers), ]) + try self._testVouchers(expectations: [TestCase(model: "AppleTV5,3", success: true, manateeTLKs: false, limitedTLKs: true), + TestCase(model: "MacFoo", success: false, manateeTLKs: false, limitedTLKs: false), + TestCase(model: "Watch17", success: false, manateeTLKs: false, limitedTLKs: false), ]) } func testJoinFromTV() throws { - try self._testJoin(expectations: [TestCase(model: "AppleTV5,3", success: true, sendTLKs: sendTLKsToAllPeers), - TestCase(model: "MacFoo", success: false, sendTLKs: sendTLKsToAllPeers), - TestCase(model: "Watch17", success: false, sendTLKs: sendTLKsToAllPeers), ]) + try self._testJoin(expectations: [TestCase(model: "AppleTV5,3", success: true, manateeTLKs: false, limitedTLKs: true), + TestCase(model: "MacFoo", success: false, manateeTLKs: false, limitedTLKs: false), + TestCase(model: "Watch17", success: false, manateeTLKs: false, limitedTLKs: false), ]) } } class OctagonTestsOverrideModelMac: OctagonTestsOverrideModelBase { - #if !os(tvOS) - let sendTLKsToAllPeers = false - #else - let sendTLKsToAllPeers = true - #endif - override func setUp() { + self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: "Mac17", + deviceName: "macbook", + serialNumber: "456", + osVersion: "OSX 11") super.setUp() - - self.mockDeviceInfo.mockModelID = "Mac17" - self.mockDeviceInfo.mockDeviceName = "macbook" - self.mockDeviceInfo.mockSerialNumber = "456" - self.mockDeviceInfo.mockOsVersion = "OSX 11" } func testVoucherFromMac() throws { - try self._testVouchers(expectations: [TestCase(model: "AppleTV5,3", success: true, sendTLKs: sendTLKsToAllPeers), - TestCase(model: "MacFoo", success: true, sendTLKs: sendTLKsToAllPeers), - TestCase(model: "Watch17", success: true, sendTLKs: sendTLKsToAllPeers), ]) + try self._testVouchers(expectations: [TestCase(model: "AppleTV5,3", success: true, manateeTLKs: false, limitedTLKs: true), + TestCase(model: "MacFoo", success: true, manateeTLKs: true, limitedTLKs: true), + TestCase(model: "Watch17", success: true, manateeTLKs: true, limitedTLKs: true), ]) } func testJoinFromMac() throws { - try self._testJoin(expectations: [TestCase(model: "AppleTV5,3", success: true, sendTLKs: sendTLKsToAllPeers), - TestCase(model: "MacFoo", success: true, sendTLKs: true), - TestCase(model: "Watch17", success: true, sendTLKs: true), ]) + try self._testJoin(expectations: [TestCase(model: "AppleTV5,3", success: true, manateeTLKs: false, limitedTLKs: true), + TestCase(model: "MacFoo", success: true, manateeTLKs: true, limitedTLKs: true), + TestCase(model: "Watch17", success: true, manateeTLKs: true, limitedTLKs: true), ]) } } diff --git a/keychain/ot/tests/octagon/OctagonTestsXPCConnections.swift b/keychain/ot/tests/octagon/OctagonTestsXPCConnections.swift index a972b584..bfb7d304 100644 --- a/keychain/ot/tests/octagon/OctagonTestsXPCConnections.swift +++ b/keychain/ot/tests/octagon/OctagonTestsXPCConnections.swift @@ -17,14 +17,14 @@ class ProxyXPCConnection: NSObject, NSXPCListenerDelegate { self.listener.resume() } - public func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool { + func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool { newConnection.exportedInterface = self.serverInterface newConnection.exportedObject = self.obj newConnection.resume() return true } - public func connection() -> NSXPCConnection { + func connection() -> NSXPCConnection { let connection = NSXPCConnection(listenerEndpoint: self.listener.endpoint) connection.remoteObjectInterface = self.serverInterface connection.resume() diff --git a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+Piggybacking.swift b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+Piggybacking.swift index 17901fea..9c45c969 100644 --- a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+Piggybacking.swift +++ b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+Piggybacking.swift @@ -77,7 +77,6 @@ let version0_txt: [UInt8] = [ let version0_txt_len = 395 extension OctagonPairingTests { - func testPiggybacking() { self.startCKAccountStatusMock() @@ -92,12 +91,10 @@ extension OctagonPairingTests { } self.wait(for: [rpcEpochCallbackOccurs], timeout: 10) - let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) - initiator1Context.startOctagonStateMachine() + self.cuttlefishContext.startOctagonStateMachine() - self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) var peerID: String = "" var permanentInfo = Data(count: 0) @@ -140,15 +137,15 @@ extension OctagonPairingTests { self.wait(for: [firstMessageAcceptorCallback], timeout: 10) let rpcJoinCallback = self.expectation(description: "joining callback") - self.manager.rpcJoin(with: self.initiatorPiggybackingConfig, vouchData: voucher, vouchSig: voucherSig, preapprovedKeys: nil) { error in + self.manager.rpcJoin(with: self.initiatorPiggybackingConfig, vouchData: voucher, vouchSig: voucherSig) { error in XCTAssertNil(error, "error should be nil") rpcJoinCallback.fulfill() } self.wait(for: [rpcJoinCallback], timeout: 10) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: self.cuttlefishContextForAcceptor, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) self.assertConsidersSelfTrusted(context: self.cuttlefishContextForAcceptor) @@ -156,14 +153,13 @@ extension OctagonPairingTests { clientStateMachine.notifyContainerChange() let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -172,14 +168,13 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -187,9 +182,11 @@ extension OctagonPairingTests { self.wait(for: [acceptorDumpCallback], timeout: 10) self.verifyDatabaseMocks() + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } - func testVersion2ofPiggybacking() { + func testVersion2ofPiggybacking() throws { KCSetJoiningOctagonPiggybackingEnabled(true) OctagonSetIsEnabled(true) self.startCKAccountStatusMock() @@ -216,6 +213,7 @@ extension OctagonPairingTests { XCTAssertNotNil(requestSession, "requestSession should not be nil") XCTAssertNotNil(requestDelegate, "requestDelegate should not be nil") XCTAssertNotNil(acceptDelegate, "acceptDelegate should not be nil") + OctagonSetPlatformSupportsSOS(false) do { initialMessageContainingOctagonVersion = try requestSession!.initialMessage() @@ -264,25 +262,27 @@ extension OctagonPairingTests { error: nil) XCTAssertNotNil(requestCircleSession, "No request secret session") - requestCircleSession.setJoiningConfigurationObject(self.initiatorPiggybackingConfig) + requestCircleSession.setContextIDOnJoiningConfiguration(self.initiatorPiggybackingConfig.contextID) requestCircleSession.setControlObject(self.otControl) var identityMessage: Data? do { identityMessage = try requestCircleSession.initialMessage() XCTAssertNotNil(identityMessage, "No identity message") - } catch { XCTAssertNil(error, "error retrieving identityMessage message") } + // Double-check that there's an Octagon message in the packet + let initiatorIdentityMessage = try self.unpackPiggybackingInitialMessage(identityMessage: identityMessage!, session: acceptSession!.accessSession()) + XCTAssertTrue(initiatorIdentityMessage.hasPrepare, "Pairing message should contain prepared information") + var voucherMessage: Data? do { voucherMessage = try acceptSession!.processMessage(identityMessage!) XCTAssertNotNil(voucherMessage, "No voucherMessage message") } catch { XCTAssertNil(error, "error retrieving voucherMessage message") - } var nothing: Data? @@ -291,7 +291,6 @@ extension OctagonPairingTests { XCTAssertNotNil(nothing, "No nothing message") } catch { XCTAssertNil(error, "error retrieving nothing message") - } XCTAssertTrue(requestSession!.isDone(), "requestor should be done") @@ -312,14 +311,13 @@ extension OctagonPairingTests { self.verifyDatabaseMocks() let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -328,14 +326,13 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -545,7 +542,44 @@ extension OctagonPairingTests { self.wait(for: [firstMessageWithNewJoiningConfigCallback], timeout: 10) } - func testVersion2ofPiggybackingWithSOS() { + func testPairingResetWithNoAccount() { + // no account + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + // no cloudkit account + self.accountStatus = .noAccount + self.startCKAccountStatusMock() + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + let joining = OTJoiningConfiguration(protocolType: "OctagonPiggybacking", + uniqueDeviceID: "requester", + uniqueClientID: "client", + pairingUUID: "3B99AE99-5FEB-4AF5-9992-DF042118B5FE", + containerName: self.cuttlefishContext.containerName, + contextID: self.cuttlefishContext.contextID, + epoch: 1, + isInitiator: true) + + self.cuttlefishContext.handlePairingRestart(joining) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + let joining2 = OTJoiningConfiguration(protocolType: "OctagonPiggybacking", + uniqueDeviceID: "requester", + uniqueClientID: "client", + pairingUUID: "3B99AE99-5FEB-4AF5-0000-DF042118B5FE", + containerName: self.cuttlefishContext.containerName, + contextID: self.cuttlefishContext.contextID, + epoch: 1, + isInitiator: true) + + self.cuttlefishContext.handlePairingRestart(joining2) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + } + + func testVersion2ofPiggybackingWithSOS() throws { KCSetJoiningOctagonPiggybackingEnabled(true) OctagonSetPlatformSupportsSOS(true) self.startCKAccountStatusMock() @@ -626,7 +660,7 @@ extension OctagonPairingTests { error: nil) XCTAssertNotNil(requestCircleSession, "No request secret session") - requestCircleSession.setJoiningConfigurationObject(self.initiatorPiggybackingConfig) + requestCircleSession.setContextIDOnJoiningConfiguration(self.initiatorPiggybackingConfig.contextID) requestCircleSession.setControlObject(self.otControl) var identityMessage: Data? @@ -636,11 +670,14 @@ extension OctagonPairingTests { XCTAssertNotNil(parsedMessage.firstData, "No octagon message") XCTAssertNotNil(parsedMessage.secondData, "No sos message") XCTAssertNotNil(identityMessage, "No identity message") - } catch { XCTAssertNil(error, "error retrieving identityMessage message") } + // Double-check that there's an Octagon message in the packet + let initiatorIdentityMessage = try self.unpackPiggybackingInitialMessage(identityMessage: identityMessage!, session: acceptSession!.accessSession()) + XCTAssertTrue(initiatorIdentityMessage.hasPrepare, "Pairing message should contain prepared information") + var voucherMessage: Data? do { voucherMessage = try acceptSession!.processMessage(identityMessage!) @@ -650,7 +687,6 @@ extension OctagonPairingTests { XCTAssertNotNil(voucherMessage, "No voucherMessage message") } catch { XCTAssertNil(error, "error retrieving voucherMessage message") - } var nothing: Data? @@ -680,14 +716,13 @@ extension OctagonPairingTests { self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContextForAcceptor, sender: self.cuttlefishContext) let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -696,14 +731,360 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + acceptorDumpCallback.fulfill() + } + self.wait(for: [acceptorDumpCallback], timeout: 10) + XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles") + } + + func testVersion2ofPiggybackingWithAcceptorOctagonOnly() throws { + KCSetJoiningOctagonPiggybackingEnabled(true) + OctagonSetPlatformSupportsSOS(true) + self.startCKAccountStatusMock() + + self.getAcceptorInCircle() + + let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + + var clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) + initiator1Context.startOctagonStateMachine() + + self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + // Note that in this strange situation, the join should create the CKKS TLKs + let (requestDelegate, acceptDelegate, acceptSession, requestSession) = self.setupKCJoiningSessionObjects() + var initialMessageContainingOctagonVersion: Data? + var challengeContainingEpoch: Data? + var response: Data? + var verification: Data? + var doneMessage: Data? + + XCTAssertNotNil(acceptSession, "acceptSession should not be nil") + XCTAssertNotNil(requestSession, "requestSession should not be nil") + XCTAssertNotNil(requestDelegate, "requestDelegate should not be nil") + XCTAssertNotNil(acceptDelegate, "acceptDelegate should not be nil") + + do { + initialMessageContainingOctagonVersion = try requestSession!.initialMessage() + } catch { + XCTAssertNil(error, "error retrieving initialMessageContainingOctagonVersion message") + } + + XCTAssertNotNil(initialMessageContainingOctagonVersion, "initial message should not be nil") + + do { + OctagonSetPlatformSupportsSOS(false) + challengeContainingEpoch = try acceptSession!.processMessage(initialMessageContainingOctagonVersion!) + XCTAssertNotNil(challengeContainingEpoch, "challengeContainingEpoch should not be nil") + } catch { + XCTAssertNil(error, "error retrieving challengeContainingEpoch message") + } + + do { + OctagonSetPlatformSupportsSOS(true) + response = try requestSession!.processMessage(challengeContainingEpoch!) + XCTAssertNotNil(response, "response message should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + do { + OctagonSetPlatformSupportsSOS(false) + verification = try acceptSession!.processMessage(response!) + XCTAssertNotNil(verification, "verification should not be nil") + } catch { + XCTAssertNil(error, "error retrieving verification message") + } + + do { + OctagonSetPlatformSupportsSOS(true) + doneMessage = try requestSession!.processMessage(verification!) + XCTAssertNotNil(doneMessage, "doneMessage should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + let signInCallback = self.expectation(description: "trigger sign in") + self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in + XCTAssertNil(error, "error should be nil") + signInCallback.fulfill() + } + self.wait(for: [signInCallback], timeout: 10) + + XCTAssertTrue(requestSession!.isDone(), "SecretSession done") + XCTAssertFalse(acceptSession!.isDone(), "Unexpected accept session done") + + let aesSession = requestSession!.session + + let requestCircleSession = KCJoiningRequestCircleSession(circleDelegate: requestDelegate!, + session: aesSession!, + otcontrol: self.otControl, + error: nil) + XCTAssertNotNil(requestCircleSession, "No request secret session") + + requestCircleSession.setContextIDOnJoiningConfiguration(self.initiatorPiggybackingConfig.contextID) + requestCircleSession.setControlObject(self.otControl) + + var identityMessage: Data? + do { + identityMessage = try requestCircleSession.initialMessage() + let parsedMessage = try KCJoiningMessage(der: identityMessage!) + XCTAssertNotNil(parsedMessage.firstData, "No octagon message") + XCTAssertNotNil(parsedMessage.secondData, "No sos message") + XCTAssertNotNil(identityMessage, "No identity message") + } catch { + XCTAssertNil(error, "error retrieving identityMessage message") + } + + // Double-check that there's an Octagon message in the packet + let initiatorIdentityMessage = try self.unpackPiggybackingInitialMessage(identityMessage: identityMessage!, session: acceptSession!.accessSession()) + XCTAssertTrue(initiatorIdentityMessage.hasPrepare, "Pairing message should contain prepared information") + + var voucherMessage: Data? + do { + OctagonSetPlatformSupportsSOS(false) + voucherMessage = try acceptSession!.processMessage(identityMessage!) + let parsedMessage = try KCJoiningMessage(der: identityMessage!) + XCTAssertNotNil(parsedMessage.firstData, "No octagon message") + XCTAssertNotNil(parsedMessage.secondData, "No sos message") + XCTAssertNotNil(voucherMessage, "No voucherMessage message") + } catch { + XCTAssertNil(error, "error retrieving voucherMessage message") + } + + var nothing: Data? + do { + OctagonSetPlatformSupportsSOS(true) + nothing = try requestCircleSession.processMessage(voucherMessage!) + XCTAssertNotNil(nothing, "No nothing message") + } catch { + XCTAssertNil(error, "error retrieving nothing message") + } + + assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(requestSession!.isDone(), "requestor should be done") + XCTAssertTrue(acceptSession!.isDone(), "acceptor should be done") + + clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) + + clientStateMachine.notifyContainerChange() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: self.cuttlefishContextForAcceptor, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrusted(context: self.cuttlefishContextForAcceptor) + self.verifyDatabaseMocks() + + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContextForAcceptor, sender: self.cuttlefishContext) + + let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + + initiatorDumpCallback.fulfill() + } + self.wait(for: [initiatorDumpCallback], timeout: 10) + + let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + acceptorDumpCallback.fulfill() + } + self.wait(for: [acceptorDumpCallback], timeout: 10) + XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles") + } + + func testVersion2ofPiggybackingWithRequesterOctagonOnly() throws { + KCSetJoiningOctagonPiggybackingEnabled(true) + OctagonSetPlatformSupportsSOS(true) + self.startCKAccountStatusMock() + + self.getAcceptorInCircle() + + let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + + var clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) + initiator1Context.startOctagonStateMachine() + + self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + // Note that in this strange situation, the join should create the CKKS TLKs + let (requestDelegate, acceptDelegate, acceptSession, requestSession) = self.setupKCJoiningSessionObjects() + var initialMessageContainingOctagonVersion: Data? + var challengeContainingEpoch: Data? + var response: Data? + var verification: Data? + var doneMessage: Data? + + XCTAssertNotNil(acceptSession, "acceptSession should not be nil") + XCTAssertNotNil(requestSession, "requestSession should not be nil") + XCTAssertNotNil(requestDelegate, "requestDelegate should not be nil") + XCTAssertNotNil(acceptDelegate, "acceptDelegate should not be nil") + + do { + initialMessageContainingOctagonVersion = try requestSession!.initialMessage() + } catch { + XCTAssertNil(error, "error retrieving initialMessageContainingOctagonVersion message") + } + + XCTAssertNotNil(initialMessageContainingOctagonVersion, "initial message should not be nil") + + do { + OctagonSetPlatformSupportsSOS(true) + challengeContainingEpoch = try acceptSession!.processMessage(initialMessageContainingOctagonVersion!) + XCTAssertNotNil(challengeContainingEpoch, "challengeContainingEpoch should not be nil") + } catch { + XCTAssertNil(error, "error retrieving challengeContainingEpoch message") + } + + do { + OctagonSetPlatformSupportsSOS(false) + response = try requestSession!.processMessage(challengeContainingEpoch!) + XCTAssertNotNil(response, "response message should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + do { + OctagonSetPlatformSupportsSOS(true) + verification = try acceptSession!.processMessage(response!) + XCTAssertNotNil(verification, "verification should not be nil") + } catch { + XCTAssertNil(error, "error retrieving verification message") + } + + do { + OctagonSetPlatformSupportsSOS(false) + doneMessage = try requestSession!.processMessage(verification!) + XCTAssertNotNil(doneMessage, "doneMessage should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + let signInCallback = self.expectation(description: "trigger sign in") + self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in + XCTAssertNil(error, "error should be nil") + signInCallback.fulfill() + } + self.wait(for: [signInCallback], timeout: 10) + + XCTAssertTrue(requestSession!.isDone(), "SecretSession done") + XCTAssertFalse(acceptSession!.isDone(), "Unexpected accept session done") + + let aesSession = requestSession!.session + + let requestCircleSession = KCJoiningRequestCircleSession(circleDelegate: requestDelegate!, + session: aesSession!, + otcontrol: self.otControl, + error: nil) + XCTAssertNotNil(requestCircleSession, "No request secret session") + + requestCircleSession.setContextIDOnJoiningConfiguration(self.initiatorPiggybackingConfig.contextID) + requestCircleSession.setControlObject(self.otControl) + + var identityMessage: Data? + do { + OctagonSetPlatformSupportsSOS(false) + identityMessage = try requestCircleSession.initialMessage() + let parsedMessage = try KCJoiningMessage(der: identityMessage!) + XCTAssertNotNil(parsedMessage.firstData, "No octagon message") + XCTAssertNil(parsedMessage.secondData, "sos message is populated") + XCTAssertNotNil(identityMessage, "No identity message") + } catch { + XCTAssertNil(error, "error retrieving identityMessage message") + } + + // Double-check that there's an Octagon message in the packet + let initiatorIdentityMessage = try self.unpackPiggybackingInitialMessage(identityMessage: identityMessage!, session: acceptSession!.accessSession()) + XCTAssertTrue(initiatorIdentityMessage.hasPrepare, "Pairing message should contain prepared information") + + var voucherMessage: Data? + do { + OctagonSetPlatformSupportsSOS(true) + voucherMessage = try acceptSession!.processMessage(identityMessage!) + let parsedMessage = try KCJoiningMessage(der: identityMessage!) + XCTAssertNotNil(parsedMessage.firstData, "No octagon message") + XCTAssertNil(parsedMessage.secondData, "sos message is populated") + XCTAssertNotNil(voucherMessage, "No voucherMessage message") + } catch { + XCTAssertNil(error, "error retrieving voucherMessage message") + } + + var nothing: Data? + do { + OctagonSetPlatformSupportsSOS(false) + nothing = try requestCircleSession.processMessage(voucherMessage!) + XCTAssertNotNil(nothing, "No nothing message") + } catch { + XCTAssertNil(error, "error retrieving nothing message") + } + + assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(requestSession!.isDone(), "requestor should be done") + XCTAssertTrue(acceptSession!.isDone(), "acceptor should be done") + + clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) + + clientStateMachine.notifyContainerChange() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: self.cuttlefishContextForAcceptor, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrusted(context: self.cuttlefishContextForAcceptor) + self.verifyDatabaseMocks() + + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContextForAcceptor, sender: self.cuttlefishContext) + + let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + + initiatorDumpCallback.fulfill() + } + self.wait(for: [initiatorDumpCallback], timeout: 10) + + let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -791,14 +1172,13 @@ extension OctagonPairingTests { error: nil) XCTAssertNotNil(requestCircleSession, "No request secret session") - requestCircleSession.setJoiningConfigurationObject(self.initiatorPiggybackingConfig) + requestCircleSession.setContextIDOnJoiningConfiguration(self.initiatorPiggybackingConfig.contextID) requestCircleSession.setControlObject(self.otControl) var identityMessage: Data? do { identityMessage = try requestCircleSession.initialMessage() XCTAssertNotNil(identityMessage, "No identity message") - } catch { XCTAssertNil(error, "error retrieving identityMessage message") } @@ -809,7 +1189,6 @@ extension OctagonPairingTests { XCTAssertNotNil(voucherMessage, "No voucherMessage message") } catch { XCTAssertNil(error, "error retrieving voucherMessage message") - } var nothing: Data? @@ -818,13 +1197,125 @@ extension OctagonPairingTests { XCTAssertNotNil(nothing, "No nothing message") } catch { XCTAssertNil(error, "error retrieving nothing message") - } XCTAssertTrue(requestSession!.isDone(), "requestor should be done") XCTAssertTrue(acceptSession!.isDone(), "acceptor should be done") } + func testPiggybackingForTLKRequest() throws { + KCSetJoiningOctagonPiggybackingEnabled(true) + OctagonSetIsEnabled(true) + self.startCKAccountStatusMock() + + self.assertResetAndBecomeTrustedInDefaultContext() + + let (requestDelegate, acceptDelegate, acceptSession, requestSession) = self.setupKCJoiningSessionObjects() + var initialMessageContainingOctagonVersion: Data? + var challengeContainingEpoch: Data? + var response: Data? + var verification: Data? + var doneMessage: Data? + + XCTAssertNotNil(acceptSession, "acceptSession should not be nil") + XCTAssertNotNil(requestSession, "requestSession should not be nil") + XCTAssertNotNil(requestDelegate, "requestDelegate should not be nil") + XCTAssertNotNil(acceptDelegate, "acceptDelegate should not be nil") + + do { + initialMessageContainingOctagonVersion = try requestSession!.initialMessage() + } catch { + XCTAssertNil(error, "error retrieving initialMessageContainingOctagonVersion message") + } + + XCTAssertNotNil(initialMessageContainingOctagonVersion, "initial message should not be nil") + + do { + challengeContainingEpoch = try acceptSession!.processMessage(initialMessageContainingOctagonVersion!) + XCTAssertNotNil(challengeContainingEpoch, "challengeContainingEpoch should not be nil") + } catch { + XCTAssertNil(error, "error retrieving challengeContainingEpoch message") + } + + do { + response = try requestSession!.processMessage(challengeContainingEpoch!) + XCTAssertNotNil(response, "response message should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + do { + verification = try acceptSession!.processMessage(response!) + XCTAssertNotNil(verification, "verification should not be nil") + } catch { + XCTAssertNil(error, "error retrieving verification message") + } + + do { + doneMessage = try requestSession!.processMessage(verification!) + XCTAssertNotNil(doneMessage, "doneMessage should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + XCTAssertTrue(requestSession!.isDone(), "SecretSession should be done") + XCTAssertFalse(acceptSession!.isDone(), "Accept session should not be done") + + let aesSession = requestSession!.session + + let requestCircleSession = KCJoiningRequestCircleSession(circleDelegate: requestDelegate!, + session: aesSession!, + otcontrol: self.otControl, + error: nil) + XCTAssertNotNil(requestCircleSession, "Should have a request secret session") + + var tlkResponseMessage: Data? + do { + let tlkRequestMessage = try KCJoiningMessage(type: kTLKRequest, data: Data()) + tlkResponseMessage = try acceptSession!.processMessage(tlkRequestMessage.der) + XCTAssertNotNil(tlkResponseMessage, "Should have a TLK response") + } catch { + XCTAssertNil(error, "error retrieving voucherMessage message") + } + + XCTAssertTrue(acceptSession!.isDone(), "Accept session should be done after responding to a TLK request") + // Note that we no longer care about the joiningSession, because this software stack doesn't receive tlkrequest messages. + + let tlkResponseMessageCiphertext = try KCJoiningMessage(der: tlkResponseMessage!) + let tlkResponseMessageDER = try requestCircleSession.accessSession().decryptAndVerify(tlkResponseMessageCiphertext.firstData) + + let piggybackedPlist = TestsObjectiveC.copyPiggybackingInitialSyncData(tlkResponseMessageDER) + XCTAssertNotNil(piggybackedPlist, "Should have something piggybacked across the channel") + + let tlks = piggybackedPlist?["tlks"] as? [Any] + XCTAssertNotNil(tlks, "Should have some tlk contents") + #if !os(tvOS) + // TVs don't have the Passwords view, and so won't send it via piggybacking + XCTAssertEqual(tlks?.count, 1, "Should have one tlk transferred") + + if let tlk = tlks?.first as? [AnyHashable: Any] { + let view = tlk["srvr"] as? String + XCTAssertEqual(view, "Passwords", "Should have the TLK for the passwords view") + + let uuid = tlk["acct"] as? String + if let keyset = self.keys?[self.passwordsZoneID!] as? ZoneKeys { + XCTAssertEqual(uuid, keyset.currentTLKPointer?.currentKeyUUID, "Piggybacked TLK should match zone's TLK") + } else { + XCTFail("CKKS should have made keys for the passwords view") + } + print(tlk) + } else { + XCTFail("Unable to extract TLK as plist") + } + #else + XCTAssertEqual(tlks?.count, 0, "Should have zero tlks transferred (from a TV)") + #endif + + // The plist might also have some idents. Check that there aren't any + let idents = piggybackedPlist?["idents"] as? [Any] + XCTAssertNotNil(idents, "Should have some idents array") + XCTAssertEqual(idents?.count, 0, "Should have no idents contents") + } } #endif diff --git a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProxMultiClients.swift b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProxMultiClients.swift index e6b28859..53a656af 100644 --- a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProxMultiClients.swift +++ b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProxMultiClients.swift @@ -1,9 +1,7 @@ #if OCTAGON extension OctagonPairingTests { - func test2ClientsBothOctagonAndSOS() { - OctagonSetPlatformSupportsSOS(true) self.startCKAccountStatusMock() @@ -145,14 +143,13 @@ extension OctagonPairingTests { clientStateMachine.notifyContainerChange() let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -161,14 +158,13 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -285,14 +281,13 @@ extension OctagonPairingTests { clientStateMachine2.notifyContainerChange() let pair2InitiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -301,14 +296,13 @@ extension OctagonPairingTests { self.wait(for: [pair2InitiatorDumpCallback], timeout: 10) let pair2AcceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 3, "should be 3 peer ids") pair2AcceptorDumpCallback.fulfill() @@ -437,14 +431,13 @@ extension OctagonPairingTests { clientStateMachine.notifyContainerChange() let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -453,14 +446,13 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -549,14 +541,13 @@ extension OctagonPairingTests { clientStateMachine2.notifyContainerChange() let pair2InitiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -565,14 +556,13 @@ extension OctagonPairingTests { self.wait(for: [pair2InitiatorDumpCallback], timeout: 10) let pair2AcceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 3, "should be 3 peer ids") pair2AcceptorDumpCallback.fulfill() @@ -586,7 +576,6 @@ extension OctagonPairingTests { } func test2ClientsSOSOnly() { - OctagonSetPlatformSupportsSOS(true) OctagonSetIsEnabled(false) self.startCKAccountStatusMock() @@ -973,14 +962,13 @@ extension OctagonPairingTests { clientStateMachine.notifyContainerChange() let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -989,14 +977,13 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -1036,14 +1023,13 @@ extension OctagonPairingTests { clientStateMachine.notifyContainerChange() let pair2InitiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -1052,14 +1038,13 @@ extension OctagonPairingTests { self.wait(for: [pair2InitiatorDumpCallback], timeout: 10) let pair2AcceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 3, "should be 3 peer ids") pair2AcceptorDumpCallback.fulfill() @@ -1263,14 +1248,13 @@ extension OctagonPairingTests { clientStateMachine.notifyContainerChange() let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -1279,14 +1263,13 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -1327,14 +1310,13 @@ extension OctagonPairingTests { clientStateMachine.notifyContainerChange() let pair2InitiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -1343,14 +1325,13 @@ extension OctagonPairingTests { self.wait(for: [pair2InitiatorDumpCallback], timeout: 10) let pair2AcceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 3, "should be 3 peer ids") pair2AcceptorDumpCallback.fulfill() diff --git a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProximitySetup.swift b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProximitySetup.swift index 1103b6a9..b2910fa8 100644 --- a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProximitySetup.swift +++ b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProximitySetup.swift @@ -1,7 +1,6 @@ #if OCTAGON extension OctagonPairingTests { - func assertSOSSuccess() { XCTAssertNotNil(self.fcInitiator?.accountPrivateKey, "no accountPrivateKey in fcInitiator") XCTAssertNotNil(self.fcAcceptor?.accountPrivateKey, "no accountPrivateKey in fcAcceptor") @@ -11,6 +10,28 @@ extension OctagonPairingTests { // XCTAssert(SOSCircleHasPeer(self.circle, self.fcAcceptor.peerInfo(), nil), "HasPeer 2") } + func tlkInPairingChannel(packet: Data) throws -> Bool { + let plist = try self.pairingPacketToPlist(packet: packet) + + guard let arrayOfItems = (plist["d"] as? [[String: Any]]) else { + return false + } + + var foundTLK = false + arrayOfItems.forEach { item in + guard let agrp = (item["agrp"] as? String) else { + return + } + guard let cls = (item["class"] as? String) else { + return + } + if cls == "inet" && agrp == "com.apple.security.ckks" { + foundTLK = true + } + } + return foundTLK + } + func testJoin() { self.startCKAccountStatusMock() @@ -99,7 +120,7 @@ extension OctagonPairingTests { /* calling Join */ let rpcJoinCallbackOccurs = self.expectation(description: "rpcJoin callback occurs") - self.cuttlefishContext.rpcJoin(v, vouchSig: vS, preapprovedKeys: nil) { error in + self.cuttlefishContext.rpcJoin(v, vouchSig: vS) { error in XCTAssertNil(error, "error should be nil") rpcJoinCallbackOccurs.fulfill() } @@ -214,7 +235,7 @@ extension OctagonPairingTests { let rpcJoinCallbackOccurs = self.expectation(description: "rpcJoin callback occurs") - self.cuttlefishContext.rpcJoin(v, vouchSig: vS, preapprovedKeys: nil) { error in + self.cuttlefishContext.rpcJoin(v, vouchSig: vS) { error in XCTAssertNil(error, "error should be nil") rpcJoinCallbackOccurs.fulfill() } @@ -333,7 +354,7 @@ extension OctagonPairingTests { let rpcJoinCallbackOccurs = self.expectation(description: "rpcJoin callback occurs") - self.cuttlefishContext.rpcJoin(v, vouchSig: vS, preapprovedKeys: nil) { error in + self.cuttlefishContext.rpcJoin(v, vouchSig: vS) { error in XCTAssertNotNil(error, "error should be set") rpcJoinCallbackOccurs.fulfill() } @@ -350,11 +371,11 @@ extension OctagonPairingTests { let clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) self.silentFetchesAllowed = false - self.expectCKFetchAndRun(beforeFinished: { - self.putFakeKeyHierarchy(inCloudKit: self.manateeZoneID) - self.putFakeDeviceStatus(inCloudKit: self.manateeZoneID) + self.expectCKFetchAndRun { + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() self.silentFetchesAllowed = true - }) + } clientStateMachine.startOctagonStateMachine() self.cuttlefishContext.startOctagonStateMachine() @@ -433,7 +454,7 @@ extension OctagonPairingTests { /* calling Join */ let rpcJoinCallbackOccurs = self.expectation(description: "rpcJoin callback occurs") - self.cuttlefishContext.rpcJoin(v, vouchSig: vS, preapprovedKeys: nil) { error in + self.cuttlefishContext.rpcJoin(v, vouchSig: vS) { error in XCTAssertNil(error, "error should be nil") rpcJoinCallbackOccurs.fulfill() } @@ -519,7 +540,7 @@ extension OctagonPairingTests { self.wait(for: [voucherCallback], timeout: 10) let rpcJoinCallback = self.expectation(description: "joining octagon callback") - self.manager.rpcJoin(with: self.initiatorPairingConfig, vouchData: voucher, vouchSig: voucherSig, preapprovedKeys: nil) { error in + self.manager.rpcJoin(with: self.initiatorPairingConfig, vouchData: voucher, vouchSig: voucherSig) { error in XCTAssertNil(error, "error should be nil") rpcJoinCallback.fulfill() } @@ -689,73 +710,28 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") /* ACCEPTOR FIRST RTT EPOCH*/ - var acceptorFirstPacket = Data() - let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorFirstPacket = packet! - firstAcceptorCallback.fulfill() - } - self.wait(for: [firstAcceptorCallback], timeout: 10) + let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return") /* INITIATOR SECOND RTT PREPARE*/ - var initiatorSecondPacket = Data() - let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorSecondPacket = packet! - secondInitiatorCallback.fulfill() - } - - self.wait(for: [secondInitiatorCallback], timeout: 10) + let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity") /* ACCEPTOR SECOND RTT */ - var acceptorSecondPacket = Data() - let SecondAcceptorCallback = self.expectation(description: "SecondAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorSecondPacket = packet! - SecondAcceptorCallback.fulfill() - } - self.wait(for: [SecondAcceptorCallback], timeout: 10) - XCTAssertNotNil(acceptorSecondPacket, "acceptor second packet should not be nil") + let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return") /* INITIATOR THIRD STEP*/ - var initiatorThirdPacket: Data? - let thirdInitiatorCallback = self.expectation(description: "thirdInitiatorCallback callback occurs") + let initiatorThirdPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet") - initiator.exchangePacket(acceptorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorThirdPacket = packet! - thirdInitiatorCallback.fulfill() - } - self.wait(for: [thirdInitiatorCallback], timeout: 10) - XCTAssertNotNil(initiatorThirdPacket, "acceptor second packet should not be nil") + /* ACCEPTOR THIRD STEP */ + let acceptorThirdPacket = self.sendPairingExpectingCompletionAndReply(channel: acceptor, packet: initiatorThirdPacket, reason: "acceptor third packet") + XCTAssertFalse(try self.tlkInPairingChannel(packet: acceptorThirdPacket), "pairing channel should NOT transport TLKs for SOS+Octagon") + + /* INITIATOR FOURTH STEP*/ + self.sendPairingExpectingCompletion(channel: initiator, packet: acceptorThirdPacket, reason: "final packet receipt") + + // pairing completes here assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) @@ -767,14 +743,13 @@ extension OctagonPairingTests { self.verifyDatabaseMocks() let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -783,14 +758,13 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -802,7 +776,7 @@ extension OctagonPairingTests { self.assertSOSSuccess() } - func testProximitySetupUsingCliqueOctagonOnly() { + func testProximitySetupUsingCliqueOctagonOnly() throws { OctagonSetPlatformSupportsSOS(false) OctagonSetIsEnabled(true) self.startCKAccountStatusMock() @@ -831,73 +805,22 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") /* ACCEPTOR FIRST RTT EPOCH*/ - var acceptorFirstPacket = Data() - let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorFirstPacket = packet! - firstAcceptorCallback.fulfill() - } - self.wait(for: [firstAcceptorCallback], timeout: 10) + let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return") /* INITIATOR SECOND RTT PREPARE*/ - var initiatorSecondPacket = Data() - let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorSecondPacket = packet! - secondInitiatorCallback.fulfill() - } - - self.wait(for: [secondInitiatorCallback], timeout: 10) + let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity") /* ACCEPTOR SECOND RTT */ - var acceptorSecondPacket = Data() - let SecondAcceptorCallback = self.expectation(description: "SecondAcceptorCallback callback occurs") + let acceptorVoucherPacket = self.sendPairingExpectingCompletionAndReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "acceptor third packet") - acceptor.exchangePacket(initiatorSecondPacket) { complete, packet, error in - XCTAssertTrue(complete, "should be true") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorSecondPacket = packet! - SecondAcceptorCallback.fulfill() - } - self.wait(for: [SecondAcceptorCallback], timeout: 10) - XCTAssertNotNil(acceptorSecondPacket, "acceptor second packet should not be nil") + // the tlks are in the 3rd roundtrip, but lets check here too + XCTAssertFalse(try self.tlkInPairingChannel(packet: acceptorVoucherPacket), "pairing channel should not transport TLKs for octagon") /* INITIATOR THIRD STEP*/ - var initiatorThirdPacket: Data? - let thirdInitiatorCallback = self.expectation(description: "thirdInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorSecondPacket) { complete, packet, error in - XCTAssertTrue(complete, "should be true") - XCTAssertNil(packet, "packet should be nil") - XCTAssertNil(error, "error should be nil") - initiatorThirdPacket = (packet) - thirdInitiatorCallback.fulfill() - } - self.wait(for: [thirdInitiatorCallback], timeout: 10) - XCTAssertNil(initiatorThirdPacket, "acceptor second packet should be nil") + self.sendPairingExpectingCompletion(channel: initiator, packet: acceptorVoucherPacket, reason: "final packet receipt") assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) @@ -909,14 +832,13 @@ extension OctagonPairingTests { self.verifyDatabaseMocks() let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -925,14 +847,13 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -958,7 +879,11 @@ extension OctagonPairingTests { self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", initiatorContextID: OTDefaultContext, acceptorContextID: self.contextForAcceptor, initiatorUniqueID: self.initiatorName, acceptorUniqueID: "acceptor-2") + let (acceptor, initiator) = self.setupPairingEndpoints(withPairNumber: "1", + initiatorContextID: OTDefaultContext, + acceptorContextID: self.contextForAcceptor, + initiatorUniqueID: self.initiatorName, + acceptorUniqueID: "acceptor-2") XCTAssertNotNil(acceptor, "acceptor should not be nil") XCTAssertNotNil(initiator, "initiator should not be nil") @@ -971,73 +896,30 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") /* ACCEPTOR FIRST RTT EPOCH*/ - var acceptorFirstPacket = Data() - let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorFirstPacket = packet! - firstAcceptorCallback.fulfill() - } - self.wait(for: [firstAcceptorCallback], timeout: 10) + let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return") /* INITIATOR SECOND RTT PREPARE*/ - var initiatorSecondPacket = Data() - let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorSecondPacket = packet! - secondInitiatorCallback.fulfill() - } - - self.wait(for: [secondInitiatorCallback], timeout: 10) + let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity") /* ACCEPTOR SECOND RTT */ - var acceptorSecondPacket = Data() - let SecondAcceptorCallback = self.expectation(description: "SecondAcceptorCallback callback occurs") + let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return") - acceptor.exchangePacket(initiatorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorSecondPacket = packet! - SecondAcceptorCallback.fulfill() - } - self.wait(for: [SecondAcceptorCallback], timeout: 10) - XCTAssertNotNil(acceptorSecondPacket, "acceptor second packet should not be nil") + // the tlks are in the 3rd roundtrip, but lets check here too + XCTAssertFalse(try self.tlkInPairingChannel(packet: acceptorVoucherPacket), "pairing channel should transport TLKs for SOS not 2nd step though") /* INITIATOR THIRD STEP*/ - var initiatorThirdPacket: Data? - let thirdInitiatorCallback = self.expectation(description: "thirdInitiatorCallback callback occurs") + let initiatorThirdPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet") - initiator.exchangePacket(acceptorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorThirdPacket = packet! - thirdInitiatorCallback.fulfill() - } - self.wait(for: [thirdInitiatorCallback], timeout: 10) - XCTAssertNotNil(initiatorThirdPacket, "acceptor second packet should not be nil") + /* ACCEPTOR THIRD STEP */ + let acceptorThirdPacket = self.sendPairingExpectingCompletionAndReply(channel: acceptor, packet: initiatorThirdPacket, reason: "acceptor third packet") + + XCTAssertTrue(try self.tlkInPairingChannel(packet: acceptorThirdPacket), "pairing channel should transport TLKs for SOS") + + /* INITIATOR FORTH STEP*/ + self.sendPairingExpectingCompletion(channel: initiator, packet: acceptorThirdPacket, reason: "final packet receipt") self.assertSOSSuccess() } @@ -1075,73 +957,19 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") /* ACCEPTOR FIRST RTT EPOCH*/ - var acceptorFirstPacket = Data() - let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorFirstPacket = packet! - firstAcceptorCallback.fulfill() - } - self.wait(for: [firstAcceptorCallback], timeout: 10) + let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return") /* INITIATOR SECOND RTT PREPARE*/ - var initiatorSecondPacket = Data() - let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorSecondPacket = packet! - secondInitiatorCallback.fulfill() - } - - self.wait(for: [secondInitiatorCallback], timeout: 10) + let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity") /* ACCEPTOR SECOND RTT */ - var acceptorSecondPacket = Data() - let SecondAcceptorCallback = self.expectation(description: "SecondAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorSecondPacket = packet! - SecondAcceptorCallback.fulfill() - } - self.wait(for: [SecondAcceptorCallback], timeout: 10) - XCTAssertNotNil(acceptorSecondPacket, "acceptor second packet should not be nil") + let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return") /* INITIATOR THIRD STEP*/ - var initiatorThirdPacket: Data? - let thirdInitiatorCallback = self.expectation(description: "thirdInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorThirdPacket = packet! - thirdInitiatorCallback.fulfill() - } - self.wait(for: [thirdInitiatorCallback], timeout: 10) - XCTAssertNotNil(initiatorThirdPacket, "acceptor second packet should not be nil") + _ = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet") assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) @@ -1153,14 +981,13 @@ extension OctagonPairingTests { self.verifyDatabaseMocks() let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") @@ -1169,14 +996,13 @@ extension OctagonPairingTests { self.wait(for: [initiatorDumpCallback], timeout: 10) let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") - self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { - dump, _ in + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") - let egoSelf = dump!["self"] as? Dictionary + let egoSelf = dump!["self"] as? [String: AnyObject] XCTAssertNotNil(egoSelf, "egoSelf should not be nil") - let dynamicInfo = egoSelf!["dynamicInfo"] as? Dictionary + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") - let included = dynamicInfo!["included"] as? Array + let included = dynamicInfo!["included"] as? [String] XCTAssertNotNil(included, "included should not be nil") XCTAssertEqual(included!.count, 2, "should be 2 peer ids") acceptorDumpCallback.fulfill() @@ -1218,16 +1044,7 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertNil(error, "should be no error") - XCTAssertTrue(complete, "should be true") - XCTAssertNil(packet, "packet should be nil") - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + self.sendPairingExpectingCompletion(channel: initiator, packet: nil, reason: "error on first message") } func testProximitySetupOctagonAndSOSWithOctagonAcceptorMessage1Failure() { @@ -1260,18 +1077,7 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") acceptor.setOctagonMessageFailForTesting(true) @@ -1286,8 +1092,8 @@ extension OctagonPairingTests { } self.wait(for: [firstAcceptorCallback], timeout: 10) } - func testProximitySetupOctagonAndSOSWithOctagonInitiatorMessage2Failure() { + func testProximitySetupOctagonAndSOSWithOctagonInitiatorMessage2Failure() { OctagonSetPlatformSupportsSOS(true) OctagonSetIsEnabled(true) self.startCKAccountStatusMock() @@ -1316,31 +1122,10 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") /* ACCEPTOR FIRST RTT EPOCH*/ - var acceptorFirstPacket = Data() - let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorFirstPacket = packet! - firstAcceptorCallback.fulfill() - } - self.wait(for: [firstAcceptorCallback], timeout: 10) + let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return") /* INITIATOR SECOND RTT PREPARE*/ let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs") @@ -1348,7 +1133,7 @@ extension OctagonPairingTests { //set up initiator's message 2 to fail initiator.setOctagonMessageFailForTesting(true) - initiator.exchangePacket(acceptorFirstPacket) { complete, packet, error in + initiator.exchangePacket(acceptorEpochPacket) { complete, packet, error in XCTAssertNil(error, "should be no error") XCTAssertTrue(complete, "should be true") XCTAssertNil(packet, "packet should not be nil") @@ -1387,52 +1172,20 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") /* ACCEPTOR FIRST RTT EPOCH*/ - var acceptorFirstPacket = Data() - let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorFirstPacket = packet! - firstAcceptorCallback.fulfill() - } - self.wait(for: [firstAcceptorCallback], timeout: 10) + let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return") /* INITIATOR SECOND RTT PREPARE*/ - var initiatorSecondPacket = Data() - let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorSecondPacket = packet! - secondInitiatorCallback.fulfill() - } - - self.wait(for: [secondInitiatorCallback], timeout: 10) + let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity") /* ACCEPTOR SECOND RTT */ let SecondAcceptorCallback = self.expectation(description: "SecondAcceptorCallback callback occurs") acceptor.setOctagonMessageFailForTesting(true) - acceptor.exchangePacket(initiatorSecondPacket) { complete, packet, error in + acceptor.exchangePacket(initiatorPreparedIdentityPacket) { complete, packet, error in XCTAssertNil(error, "should be no error") XCTAssertTrue(complete, "should be true") XCTAssertNil(packet, "packet should be nil") @@ -1470,66 +1223,23 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") /* ACCEPTOR FIRST RTT EPOCH*/ - var acceptorFirstPacket = Data() - let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorFirstPacket = packet! - firstAcceptorCallback.fulfill() - } - self.wait(for: [firstAcceptorCallback], timeout: 10) + let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return") /* INITIATOR SECOND RTT PREPARE*/ - var initiatorSecondPacket = Data() - let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorSecondPacket = packet! - secondInitiatorCallback.fulfill() - } - - self.wait(for: [secondInitiatorCallback], timeout: 10) + let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity") /* ACCEPTOR SECOND RTT */ - var acceptorSecondPacket = Data() - let SecondAcceptorCallback = self.expectation(description: "SecondAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorSecondPacket = packet! - SecondAcceptorCallback.fulfill() - } - self.wait(for: [SecondAcceptorCallback], timeout: 10) - XCTAssertNotNil(acceptorSecondPacket, "acceptor second packet should not be nil") + let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return") /* INITIATOR THIRD STEP*/ let thirdInitiatorCallback = self.expectation(description: "thirdInitiatorCallback callback occurs") initiator.setOctagonMessageFailForTesting(true) - initiator.exchangePacket(acceptorSecondPacket) { complete, packet, error in + initiator.exchangePacket(acceptorVoucherPacket) { complete, packet, error in XCTAssertNil(error, "should be no error") XCTAssertTrue(complete, "should be true") XCTAssertNil(packet, "packet should be nil") @@ -1611,75 +1321,19 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") /* ACCEPTOR FIRST RTT EPOCH*/ - var acceptorFirstPacket = Data() - let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorFirstPacket = packet! - firstAcceptorCallback.fulfill() - } - self.wait(for: [firstAcceptorCallback], timeout: 10) - - initiator.setSessionSupportsOctagonForTesting(false) + let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return") /* INITIATOR SECOND RTT PREPARE*/ - var initiatorSecondPacket = Data() - let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorSecondPacket = packet! - secondInitiatorCallback.fulfill() - } - - self.wait(for: [secondInitiatorCallback], timeout: 10) + let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity") /* ACCEPTOR SECOND RTT */ - var acceptorSecondPacket = Data() - let SecondAcceptorCallback = self.expectation(description: "SecondAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorSecondPacket = packet! - SecondAcceptorCallback.fulfill() - } - self.wait(for: [SecondAcceptorCallback], timeout: 10) - XCTAssertNotNil(acceptorSecondPacket, "acceptor second packet should not be nil") + let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return") /* INITIATOR THIRD STEP*/ - var initiatorThirdPacket: Data? - let thirdInitiatorCallback = self.expectation(description: "thirdInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorThirdPacket = packet! - thirdInitiatorCallback.fulfill() - } - self.wait(for: [thirdInitiatorCallback], timeout: 10) - XCTAssertNotNil(initiatorThirdPacket, "acceptor second packet should not be nil") + _ = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet") /* need to fix attempting sos upgrade in the tests when pairing/piggybacking and then kicking off an upgrade let initiatorContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) @@ -1721,73 +1375,19 @@ extension OctagonPairingTests { self.wait(for: [signInCallback], timeout: 10) /* INITIATOR FIRST RTT JOINING MESSAGE*/ - var initiatorFirstPacket = Data() - let firstInitiatorCallback = self.expectation(description: "firstInitiatorCallback callback occurs") - - initiator.exchangePacket(nil) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorFirstPacket = packet! - firstInitiatorCallback.fulfill() - } - - self.wait(for: [firstInitiatorCallback], timeout: 10) + let initiatorFirstPacket = self.sendPairingExpectingReply(channel: initiator, packet: nil, reason: "session initiation") /* ACCEPTOR FIRST RTT EPOCH*/ - var acceptorFirstPacket = Data() - let firstAcceptorCallback = self.expectation(description: "firstAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorFirstPacket = packet! - firstAcceptorCallback.fulfill() - } - self.wait(for: [firstAcceptorCallback], timeout: 10) + let acceptorEpochPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorFirstPacket, reason: "epoch return") /* INITIATOR SECOND RTT PREPARE*/ - var initiatorSecondPacket = Data() - let secondInitiatorCallback = self.expectation(description: "secondInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorFirstPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorSecondPacket = packet! - secondInitiatorCallback.fulfill() - } - - self.wait(for: [secondInitiatorCallback], timeout: 10) + let initiatorPreparedIdentityPacket = self.sendPairingExpectingReply(channel: initiator, packet: acceptorEpochPacket, reason: "prepared identity") /* ACCEPTOR SECOND RTT */ - var acceptorSecondPacket = Data() - let SecondAcceptorCallback = self.expectation(description: "SecondAcceptorCallback callback occurs") - - acceptor.exchangePacket(initiatorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - acceptorSecondPacket = packet! - SecondAcceptorCallback.fulfill() - } - self.wait(for: [SecondAcceptorCallback], timeout: 10) - XCTAssertNotNil(acceptorSecondPacket, "acceptor second packet should not be nil") + let acceptorVoucherPacket = self.sendPairingExpectingReply(channel: acceptor, packet: initiatorPreparedIdentityPacket, reason: "epoch return") /* INITIATOR THIRD STEP*/ - var initiatorThirdPacket: Data? - let thirdInitiatorCallback = self.expectation(description: "thirdInitiatorCallback callback occurs") - - initiator.exchangePacket(acceptorSecondPacket) { complete, packet, error in - XCTAssertFalse(complete, "should be false") - XCTAssertNotNil(packet, "packet should not be nil") - XCTAssertNil(error, "error should be nil") - initiatorThirdPacket = packet! - thirdInitiatorCallback.fulfill() - } - self.wait(for: [thirdInitiatorCallback], timeout: 10) - XCTAssertNotNil(initiatorThirdPacket, "acceptor second packet should not be nil") + _ = self.sendPairingExpectingReply(channel: initiator, packet: acceptorVoucherPacket, reason: "intitiator third packet") /* need to fix attempting sos upgrade in the tests when pairing/piggybacking and then kicking off an upgrade @@ -1797,7 +1397,6 @@ extension OctagonPairingTests { self.assertConsidersSelfTrusted(context: initiatorContext) */ } - } #endif diff --git a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests.swift b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests.swift index ea84fc76..0345fac2 100644 --- a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests.swift +++ b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests.swift @@ -1,10 +1,9 @@ #if OCTAGON func GenerateFullECKey(keySize: Int) -> (SecKey) { - let keyPair = _SFECKeyPair.init(randomKeyPairWith: _SFECKeySpecifier.init(curve: SFEllipticCurve.nistp384))! - var keyAttributes: Dictionary = [:] + var keyAttributes: [String: String] = [:] keyAttributes[kSecAttrKeyClass as String] = kSecAttrKeyClassPrivate as String keyAttributes[kSecAttrKeyType as String] = kSecAttrKeyTypeEC as String @@ -35,10 +34,10 @@ class KCJoiningRequestTestDelegate: NSObject, KCJoiningRequestSecretDelegate, KC XCTAssertNotNil(octagonSigningKey, "signing key should not be nil") XCTAssertNotNil(octagonEncryptionKey, "encryption key should not be nil") - var gestalt: Dictionary = [:] + var gestalt: [String: String] = [:] gestalt[kPIUserDefinedDeviceNameKey as String] = "Fakey" - let newPeerInfo = SOSPeerInfoCreate(nil, gestalt as CFDictionary, nil, signingKey, octagonSigningKey, octagonEncryptionKey, nil) + let newPeerInfo = SOSPeerInfoCreate(nil, gestalt as CFDictionary, nil, signingKey, octagonSigningKey, octagonEncryptionKey, true, nil) self.peerInfo = newPeerInfo self.sharedSecret = secret @@ -47,7 +46,7 @@ class KCJoiningRequestTestDelegate: NSObject, KCJoiningRequestSecretDelegate, KC } func nextSecret() -> String { - if (self.incorrectTries > 0) { + if self.incorrectTries > 0 { self.incorrectTries -= 1 return self.incorrectSecret } @@ -78,8 +77,7 @@ class KCJoiningRequestTestDelegate: NSObject, KCJoiningRequestSecretDelegate, KC } class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJoiningAcceptCircleDelegate { - - var secrets: Array = [] + var secrets: [String] = [] var currentSecret: Int = 0 var retriesLeft: Int = 0 var retriesPerSecret: Int = 0 @@ -87,7 +85,7 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo var circleJoinData = Data() var peerInfo: SOSPeerInfoRef? - class func acceptDelegateWithSecrets(secrets: Array, retries: Int, code: String) -> KCJoiningAcceptTestDelegate { + class func acceptDelegateWithSecrets(secrets: [String], retries: Int, code: String) -> KCJoiningAcceptTestDelegate { return KCJoiningAcceptTestDelegate(withSecrets: secrets, retries: retries, code: code) } @@ -96,13 +94,12 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo } class func initWithSecret(secret: String, code: String) -> KCJoiningAcceptTestDelegate { - var secretArray: Array = Array() + var secretArray: [String] = Array() secretArray.append(secret) return KCJoiningAcceptTestDelegate(withSecrets: secretArray, retries: 3, code: code) } - init(withSecrets secrets: Array, retries: Int, code: String) { - + init(withSecrets secrets: [String], retries: Int, code: String) { self.secrets = secrets self.currentSecret = 0 self.retriesPerSecret = retries @@ -119,9 +116,9 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo } func advanceSecret() -> KCRetryOrNot { - if (self.retriesLeft == 0) { + if self.retriesLeft == 0 { self.currentSecret += 1 - if (self.currentSecret >= self.secrets.count) { + if self.currentSecret >= self.secrets.count { self.currentSecret = self.secrets.count - 1 } self.retriesLeft = self.retriesPerSecret @@ -159,12 +156,210 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo } func circleGetInitialSyncViews(_ flags: SOSInitialSyncFlags, error: NSErrorPointer) -> Data { - return Data() + + // Skip the XPC and just call the server method + let possibleData = try? TestsObjectiveC.copyInitialSyncData(flags) + return possibleData ?? Data() } } -@objcMembers class OctagonPairingTests: OctagonTestsBase { +// Similar to the helpers below, but more accessible +extension OctagonTestsBase { + func joiningConfigurations(initiator: OTCuttlefishContext, initiatorDeviceID: String, sponsor: OTCuttlefishContext, sponsorDeviceID: String) -> (OTJoiningConfiguration, OTJoiningConfiguration) { + let acceptorConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, + uniqueDeviceID: sponsorDeviceID, + uniqueClientID: initiatorDeviceID, + pairingUUID: UUID().uuidString, + containerName: OTCKContainerName, + contextID: sponsor.contextID, + epoch: 1, + isInitiator: false) + let initiatorConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, + uniqueDeviceID: initiatorDeviceID, + uniqueClientID: initiatorDeviceID, + pairingUUID: UUID().uuidString, + containerName: OTCKContainerName, + contextID: initiator.contextID, + epoch: 1, + isInitiator: true) + + return (acceptorConfig, initiatorConfig) + } + + func setupPairingChannels(initiator: OTCuttlefishContext, sponsor: OTCuttlefishContext) -> (KCPairingChannel, KCPairingChannel) { + let sponsorChannelContext = KCPairingChannelContext() + sponsorChannelContext.model = sponsor.deviceAdapter.modelID() + sponsorChannelContext.osVersion = sponsor.deviceAdapter.osVersion() + sponsorChannelContext.modelClass = "AcceptorModelClass" + + sponsorChannelContext.uniqueDeviceID = UUID().uuidString + sponsorChannelContext.uniqueClientID = UUID().uuidString + + let initiatorChannelContext = KCPairingChannelContext() + initiatorChannelContext.model = initiator.deviceAdapter.modelID() + initiatorChannelContext.osVersion = initiator.deviceAdapter.osVersion() + initiatorChannelContext.modelClass = "InitiatorModelClass" + + // The initiator's client ID is equivalent to the sponsor's client ID + initiatorChannelContext.uniqueDeviceID = sponsorChannelContext.uniqueClientID + + let sponsorPairingChannel = KCPairingChannel(acceptor: sponsorChannelContext) + let initiatorPairingChannel = KCPairingChannel(initiator: initiatorChannelContext) + + XCTAssertNotNil(sponsorPairingChannel, "Should have a sponsor pairing channel") + XCTAssertNotNil(initiatorPairingChannel, "Should have a initiator pairing channel") + + sponsorPairingChannel?.setControlObject(self.otControl) + initiatorPairingChannel?.setControlObject(self.otControl) + + let (acceptorPairingConfig, initiatorPairingConfig) = self.joiningConfigurations(initiator: initiator, + initiatorDeviceID: initiatorChannelContext.uniqueDeviceID, + sponsor: sponsor, + sponsorDeviceID: sponsorChannelContext.uniqueDeviceID) + + sponsorPairingChannel?.setConfiguration(acceptorPairingConfig) + initiatorPairingChannel?.setConfiguration(initiatorPairingConfig) + + let fakeCircle = SOSCircleCreate(kCFAllocatorDefault, "TEST DOMAIN" as CFString, nil) as SOSCircleRef + + sponsorPairingChannel?.setXPCConnectionObject(FakeNSXPCConnectionSOS(withSOSControl: FCPairingFakeSOSControl(randomAccountKey: true, circle: fakeCircle))) + initiatorPairingChannel?.setXPCConnectionObject(FakeNSXPCConnectionSOS(withSOSControl: FCPairingFakeSOSControl(randomAccountKey: true, circle: fakeCircle))) + + return (sponsorPairingChannel!, initiatorPairingChannel!) + } + + func setupPiggybackingSessions(initiator: OTCuttlefishContext, + sponsor: OTCuttlefishContext) throws -> (KCJoiningRequestTestDelegate, KCJoiningAcceptTestDelegate, KCJoiningAcceptSession, KCJoiningRequestSecretSession) { + let (acceptorJoiningConfig, _) = self.joiningConfigurations(initiator: initiator, + initiatorDeviceID: UUID().uuidString, + sponsor: sponsor, + sponsorDeviceID: UUID().uuidString) + + return try self.setupKCJoiningSessionObjects(dsid: 0x123456, + sponsorConfiguration: acceptorJoiningConfig) + } + + func setupKCJoiningSessionObjects(dsid: UInt64, + sponsorConfiguration: OTJoiningConfiguration) throws -> (KCJoiningRequestTestDelegate, KCJoiningAcceptTestDelegate, KCJoiningAcceptSession, KCJoiningRequestSecretSession) { + let secret = "123456" + let code = "987654" + + let requestDelegate = KCJoiningRequestTestDelegate.requestDelegate(withSecret: secret) + let acceptDelegate = KCJoiningAcceptTestDelegate.acceptDelegateWithSecret(secret: secret, code: code) + + let requestSession = try KCJoiningRequestSecretSession(secretDelegate: requestDelegate as KCJoiningRequestSecretDelegate, dsid: dsid, rng: ccDRBGGetRngState()) + + let acceptSession = try KCJoiningAcceptSession(secretDelegate: acceptDelegate as KCJoiningAcceptSecretDelegate, + circleDelegate: acceptDelegate as KCJoiningAcceptCircleDelegate, + dsid: dsid, + rng: ccrng(nil)) + requestSession.setControlObject(self.otControl) + acceptSession.setControlObject(self.otControl) + + // requestSessions don't need control objects + acceptSession.setConfiguration(sponsorConfiguration) + + return (requestDelegate, acceptDelegate, acceptSession, requestSession) + } + + func octagonPiggypackingMessage(in message: KCJoiningMessage) throws -> OTPairingMessage { + guard let octagonData = message.secondData else { + throw NSError(domain: "missing octagon data" as String, code: -1, userInfo: nil) + } + + return OTPairingMessage(data: octagonData) + } + + func unpackPiggybackingInitialMessage(identityMessage: Data, session: KCAESGCMDuplexSession) throws -> OTPairingMessage { + let encryptedJoiningIdentityMessage = try KCJoiningMessage(der: identityMessage) + let joiningIdentityMessage = try session.decryptAndVerify(encryptedJoiningIdentityMessage.firstData) + + let initialMessageProtobuf = KCInitialMessageData(data: joiningIdentityMessage) + XCTAssertNotNil(initialMessageProtobuf, "should have an initial message container") + let initiatorIdentityMessageOpt = OTPairingMessage(data: initialMessageProtobuf!.prepareMessage) + XCTAssertNotNil(initiatorIdentityMessageOpt, "should have an Octagon message container") + return initiatorIdentityMessageOpt! + } + + func makePiggybackingPacket(combining currentMessage: KCJoiningMessage, octagonMessage: OTPairingMessage) throws -> Data { + let newMessage = try KCJoiningMessage(type: currentMessage.type, + data: currentMessage.firstData, + payload: octagonMessage.data) + return newMessage.der + } + + func pairingPacketToPlist(packet: Data) throws -> [String: Any] { + let binaryPlist = KCPairingChannel.pairingChannelDecompressData(packet)! + let plist = (try PropertyListSerialization.propertyList(from: binaryPlist, options: [], format: nil)) as! [String: Any] + return plist + } + + func octagonPairingMessage(in packet: Data) throws -> OTPairingMessage { + let plist = try self.pairingPacketToPlist(packet: packet) + + guard let octagonData = plist["o"] as? Data else { + throw NSError(domain: "missing octagon data" as String, code: -1, userInfo: nil) + } + + return OTPairingMessage(data: octagonData) + } + + func makePairingPacket(combining currentPacket: Data, octagonMessage: OTPairingMessage) throws -> Data { + var plist = try self.pairingPacketToPlist(packet: currentPacket) + plist["o"] = octagonMessage.data + + return KCPairingChannel.pairingChannelCompressData(try PropertyListSerialization.data(fromPropertyList: plist, format: .binary, options: 0)) + } + + func sendPairingExpectingReply(channel: KCPairingChannel, packet: Data?, reason: String) -> Data { + var packetResponse = Data() + let callback = self.expectation(description: "callback occurs (\(reason))") + + channel.exchangePacket(packet) { complete, response, error in + XCTAssertNil(error, "error should be nil (\(reason))") + + XCTAssertFalse(complete, "Expected no completion (\(reason))") + XCTAssertNotNil(response, "packet should not be nil (\(reason))") + packetResponse = response! + callback.fulfill() + } + self.wait(for: [callback], timeout: 10) + return packetResponse + } + + func sendPairingExpectingCompletionAndReply(channel: KCPairingChannel, packet: Data?, reason: String) -> Data { + var packetResponse = Data() + let callback = self.expectation(description: "callback occurs (\(reason))") + + channel.exchangePacket(packet) { complete, response, error in + XCTAssertNil(error, "error should be nil (\(reason))") + + XCTAssertTrue(complete, "Expected channel completion (\(reason))") + XCTAssertNotNil(response, "response should be present (\(reason))") + packetResponse = response! + callback.fulfill() + } + self.wait(for: [callback], timeout: 10) + return packetResponse + } + + func sendPairingExpectingCompletion(channel: KCPairingChannel, packet: Data?, reason: String) { + let callback = self.expectation(description: "callback occurs (\(reason))") + + channel.exchangePacket(packet) { complete, response, error in + XCTAssertNil(error, "error should be nil (\(reason))") + + XCTAssertTrue(complete, "Expected channel completion (\(reason))") + XCTAssertNil(response, "response should be nil (\(reason))") + callback.fulfill() + } + self.wait(for: [callback], timeout: 10) + } +} + +@objcMembers +class OctagonPairingTests: OctagonTestsBase { var sosAdapterForAcceptor: CKKSMockSOSPresentAdapter! var cuttlefishContextForAcceptor: OTCuttlefishContext! var contextForAcceptor = "defaultContextForAcceptor" @@ -181,6 +376,27 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo var fcAcceptor: FCPairingFakeSOSControl! override func setUp() { + // We want the Passwords view to exist, so that we can check the piggybacking TLK channel + if self.mockDeviceInfo == nil { + let actualDeviceAdapter = OTDeviceInformationActualAdapter() + self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(), + deviceName: actualDeviceAdapter.deviceName(), + serialNumber: NSUUID().uuidString, + osVersion: actualDeviceAdapter.osVersion()) + } + + if self.mockDeviceInfo.mockModelID.contains("AppleTV") { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + ]) + } else { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + CKRecordZone.ID(zoneName: "Manatee"), + CKRecordZone.ID(zoneName: "Passwords"), + ]) + } + super.setUp() // The acceptor should have its own SOS state @@ -190,18 +406,46 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo self.sosAdapterForAcceptor.circleStatus = SOSCCStatus(kSOSCCInCircle) self.cuttlefishContextForAcceptor = self.manager.context(forContainerName: OTCKContainerName, - contextID: self.contextForAcceptor, - sosAdapter: self.sosAdapterForAcceptor, - authKitAdapter: self.mockAuthKit3, - lockStateTracker: self.lockStateTracker, - accountStateTracker: self.accountStateTracker, - deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iPhone9,1", deviceName: "test-SOS-iphone", serialNumber: "456", osVersion: "iOS (fake version)")) + contextID: self.contextForAcceptor, + sosAdapter: self.sosAdapterForAcceptor, + authKitAdapter: self.mockAuthKit3, + lockStateTracker: self.lockStateTracker, + accountStateTracker: self.accountStateTracker, + deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iPhone9,1", deviceName: "test-SOS-iphone", serialNumber: "456", osVersion: "iOS (fake version)")) - self.acceptorPiggybackingConfig = OTJoiningConfiguration(protocolType: OTProtocolPiggybacking, uniqueDeviceID: "acceptor", uniqueClientID: self.initiatorName, containerName: OTCKContainerName, contextID: self.contextForAcceptor, epoch: 1, isInitiator: false) - self.initiatorPiggybackingConfig = OTJoiningConfiguration(protocolType: OTProtocolPiggybacking, uniqueDeviceID: "initiator", uniqueClientID: "acceptor", containerName: OTCKContainerName, contextID: OTDefaultContext, epoch: 1, isInitiator: true) + self.acceptorPiggybackingConfig = OTJoiningConfiguration(protocolType: OTProtocolPiggybacking, + uniqueDeviceID: "acceptor", + uniqueClientID: self.initiatorName, + pairingUUID: UUID().uuidString, + containerName: OTCKContainerName, + contextID: self.contextForAcceptor, + epoch: 1, + isInitiator: false) + self.initiatorPiggybackingConfig = OTJoiningConfiguration(protocolType: OTProtocolPiggybacking, + uniqueDeviceID: "initiator", + uniqueClientID: "acceptor", + pairingUUID: UUID().uuidString, + containerName: OTCKContainerName, + contextID: OTDefaultContext, + epoch: 1, + isInitiator: true) - self.acceptorPairingConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, uniqueDeviceID: "acceptor", uniqueClientID: self.initiatorName, containerName: OTCKContainerName, contextID: self.contextForAcceptor, epoch: 1, isInitiator: false) - self.initiatorPairingConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, uniqueDeviceID: "initiator", uniqueClientID: "acceptor", containerName: OTCKContainerName, contextID: OTDefaultContext, epoch: 1, isInitiator: true) + self.acceptorPairingConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, + uniqueDeviceID: "acceptor", + uniqueClientID: self.initiatorName, + pairingUUID: UUID().uuidString, + containerName: OTCKContainerName, + contextID: self.contextForAcceptor, + epoch: 1, + isInitiator: false) + self.initiatorPairingConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, + uniqueDeviceID: "initiator", + uniqueClientID: "acceptor", + pairingUUID: UUID().uuidString, + containerName: OTCKContainerName, + contextID: OTDefaultContext, + epoch: 1, + isInitiator: true) } func getAcceptorInCircle() { @@ -220,7 +464,6 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo } func setupPairingEndpoints(withPairNumber pairNumber: String, initiatorContextID: String, acceptorContextID: String, initiatorUniqueID: String, acceptorUniqueID: String) -> (KCPairingChannel, KCPairingChannel) { - let (acceptorClique, initiatorClique) = self.setupOTCliquePair(withNumber: pairNumber) XCTAssertNotNil(acceptorClique, "acceptorClique should not be nil") XCTAssertNotNil(initiatorClique, "initiatorClique should not be nil") @@ -237,7 +480,6 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo initiatorContext.osVersion = "InitiatorOsVersion" initiatorContext.modelClass = "InitiatorModelClass" initiatorContext.uniqueDeviceID = initiatorUniqueID - initiatorContext.uniqueDeviceID = initiatorUniqueID let acceptor = acceptorClique!.setupPairingChannel(asAcceptor: acceptorContext) let initiator = initiatorClique!.setupPairingChannel(asInitiator: initiatorContext) @@ -248,8 +490,22 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo acceptor.setControlObject(self.otControl) initiator.setControlObject(self.otControl) - let acceptorPairingConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, uniqueDeviceID: acceptorUniqueID, uniqueClientID: initiatorUniqueID, containerName: OTCKContainerName, contextID: acceptorContextID, epoch: 1, isInitiator: false) - let initiatorPairingConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, uniqueDeviceID: initiatorUniqueID, uniqueClientID: initiatorUniqueID, containerName: OTCKContainerName, contextID: initiatorContextID, epoch: 1, isInitiator: true) + let acceptorPairingConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, + uniqueDeviceID: acceptorUniqueID, + uniqueClientID: initiatorUniqueID, + pairingUUID: UUID().uuidString, + containerName: OTCKContainerName, + contextID: acceptorContextID, + epoch: 1, + isInitiator: false) + let initiatorPairingConfig = OTJoiningConfiguration(protocolType: OTProtocolPairing, + uniqueDeviceID: initiatorUniqueID, + uniqueClientID: initiatorUniqueID, + pairingUUID: UUID().uuidString, + containerName: OTCKContainerName, + contextID: initiatorContextID, + epoch: 1, + isInitiator: true) acceptor.setConfiguration(acceptorPairingConfig) initiator.setConfiguration(initiatorPairingConfig) @@ -268,63 +524,32 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo } func setupOTCliquePair(withNumber count: String) -> (OTClique?, OTClique?) { - let secondAcceptorData = OTConfigurationContext() secondAcceptorData.context = "secondAcceptor" secondAcceptorData.dsid = "a-"+count secondAcceptorData.altDSID = "alt-a-"+count - let acceptorAnalytics = SFSignInAnalytics(signInUUID: "uuid", category: "com.apple.cdp", eventName: "signed in") - XCTAssertNotNil(acceptorAnalytics, "acceptorAnalytics should not be nil") - secondAcceptorData.analytics = acceptorAnalytics + let acceptor = OTClique(contextData: secondAcceptorData) + XCTAssertNotNil(acceptor, "Clique should not be nil") + acceptor.setPairingDefault(true) - do { - let acceptor = try OTClique(contextData: secondAcceptorData) - XCTAssertNotNil(acceptor, "Clique should not be nil") - acceptor.setPairingDefault(true) + let secondInitiatorData = OTConfigurationContext() + secondInitiatorData.context = "secondInitiator" + secondInitiatorData.dsid = "i-"+count + secondInitiatorData.altDSID = "alt-i-"+count - let secondInitiatorData = OTConfigurationContext() - secondInitiatorData.context = "secondInitiator" - secondInitiatorData.dsid = "i-"+count - secondInitiatorData.altDSID = "alt-i-"+count + let initiator = OTClique(contextData: secondInitiatorData) + XCTAssertNotNil(initiator, "Clique should not be nil") + initiator.setPairingDefault(true) - let initiatorAnalytics = SFSignInAnalytics(signInUUID: "uuid", category: "com.apple.cdp", eventName: "signed in") - XCTAssertNotNil(initiatorAnalytics, "initiatorAnalytics should not be nil") - secondInitiatorData.analytics = initiatorAnalytics - let initiator = try OTClique(contextData: secondInitiatorData) - XCTAssertNotNil(initiator, "Clique should not be nil") - initiator.setPairingDefault(true) - - return (acceptor, initiator) - - } catch { - XCTFail("error creating test clique: \(error)") - } - return(nil, nil) + return (acceptor, initiator) } func setupKCJoiningSessionObjects() -> (KCJoiningRequestTestDelegate?, KCJoiningAcceptTestDelegate?, KCJoiningAcceptSession?, KCJoiningRequestSecretSession?) { - - let secret = "123456" - let code = "987654" let dsid: UInt64 = 0x1234567887654321 - let requestDelegate = KCJoiningRequestTestDelegate.requestDelegate(withSecret: secret) - let acceptDelegate = KCJoiningAcceptTestDelegate.acceptDelegateWithSecret(secret: secret, code: code) - do { - let requestSession = try KCJoiningRequestSecretSession(secretDelegate: requestDelegate as KCJoiningRequestSecretDelegate, dsid: dsid, rng: ccDRBGGetRngState()) - - let acceptSession = try KCJoiningAcceptSession(secretDelegate: acceptDelegate as KCJoiningAcceptSecretDelegate, - circleDelegate: acceptDelegate as KCJoiningAcceptCircleDelegate, - dsid: dsid, - rng: ccDRBGGetRngState()) - requestSession.setControlObject(self.otControl) - acceptSession.setControlObject(self.otControl) - requestSession.setConfiguration(self.initiatorPiggybackingConfig) - acceptSession.setConfiguration(self.acceptorPiggybackingConfig) - - return (requestDelegate, acceptDelegate, acceptSession, requestSession) + return try self.setupKCJoiningSessionObjects(dsid: dsid, sponsorConfiguration: self.acceptorPiggybackingConfig) } catch { XCTFail("error creating test clique: \(error)") return (nil, nil, nil, nil) diff --git a/keychain/ot/tests/octagon/TestsObjcTranslation.h b/keychain/ot/tests/octagon/TestsObjcTranslation.h index 413ad8e3..9a2901c9 100644 --- a/keychain/ot/tests/octagon/TestsObjcTranslation.h +++ b/keychain/ot/tests/octagon/TestsObjcTranslation.h @@ -5,6 +5,8 @@ #import #import #import +#include +#include "keychain/ckks/CKKSPeer.h" NS_ASSUME_NONNULL_BEGIN @@ -23,6 +25,12 @@ NS_ASSUME_NONNULL_BEGIN + (BOOL)saveCoruptDataToKeychainForContainer:(NSString*)containerName contextID:(NSString*)contextID error:(NSError**)error; + ++ (NSData* _Nullable)copyInitialSyncData:(SOSInitialSyncFlags)flags error:(NSError**)error; + ++ (NSDictionary* _Nullable)copyPiggybackingInitialSyncData:(NSData*)data; + ++ (BOOL)testSecKey:(CKKSSelves*)octagonSelf error:(NSError**)error; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/tests/octagon/TestsObjcTranslation.m b/keychain/ot/tests/octagon/TestsObjcTranslation.m index 51021194..d89c6741 100644 --- a/keychain/ot/tests/octagon/TestsObjcTranslation.m +++ b/keychain/ot/tests/octagon/TestsObjcTranslation.m @@ -2,10 +2,12 @@ #import #import -#import #import "keychain/ot/OTCuttlefishContext.h" #import +#import #import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/securityd/SOSCloudCircleServer.h" +#import "keychain/SecureObjectSync/SOSAccountPriv.h" static const uint8_t signingKey_384[] = { 0x04, 0xe4, 0x1b, 0x3e, 0x88, 0x81, 0x9f, 0x3b, 0x80, 0xd0, 0x28, 0x1c, @@ -106,4 +108,115 @@ static const uint8_t signingKey_384[] = { } } ++ (NSData* _Nullable)copyInitialSyncData:(SOSInitialSyncFlags)flags error:(NSError**)error +{ + CFErrorRef cferror = NULL; + NSData* result = CFBridgingRelease(SOSCCCopyInitialSyncData_Server(flags, &cferror)); + + if(cferror && error) { + *error = CFBridgingRelease(cferror); + } + + return result; +} + ++ (NSDictionary* _Nullable)copyPiggybackingInitialSyncData:(NSData*)data +{ + const uint8_t* der = [data bytes]; + const uint8_t *der_end = der + [data length]; + + NSDictionary* results = SOSPiggyCopyInitialSyncData(&der, der_end); + return results; +} + ++ (BOOL)testSecKey:(CKKSSelves*)octagonSelf error:(NSError**)error +{ + id currentSelfPeer = octagonSelf.currentSelf; + + NSData* signingFullKey = currentSelfPeer.signingKey.keyData; + + SecKeyRef octagonSigningPubSecKey = CFRetainSafe(currentSelfPeer.publicSigningKey.secKey); + SecKeyRef octagonEncryptionPubSecKey = CFRetainSafe(currentSelfPeer.publicEncryptionKey.secKey); + + NSError* localerror = nil; + + bool savedSigningKey = SOSCCSaveOctagonKeysToKeychain(@"Octagon Peer Signing ID for Test-ak", + signingFullKey, + 384, + octagonSigningPubSecKey, + &localerror); + if(!savedSigningKey) { + if(error) { + *error = localerror; + } + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + // Okay, can we load this key pair? + + // Try the SPI route first + CFErrorRef cferror = NULL; + SecKeyRef signingPrivateKey = SecKeyCopyMatchingPrivateKey(octagonSigningPubSecKey, &cferror); + if(!signingPrivateKey) { + if(error) { + *error = CFBridgingRelease(cferror); + } else { + CFReleaseNull(cferror); + } + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + // and can you get the persistent ref from that private key? + CFDataRef pref = NULL; + OSStatus status = SecKeyCopyPersistentRef(signingPrivateKey, &pref); + if(status != errSecSuccess) { + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + description:@"Failed to copy persistent ref"]; + } + CFReleaseNull(pref); + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + + SFECKeyPair *signingFullKeyPair = [[SFECKeyPair alloc] initWithData:signingFullKey + specifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384] + error:&localerror]; + if(!signingFullKey) { + if(error) { + *error = localerror; + } + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + CFDataRef prefFromSF = NULL; + OSStatus statusFromSF = SecKeyCopyPersistentRef(signingFullKeyPair.secKey, &prefFromSF); + if(statusFromSF != errSecSuccess) { + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:statusFromSF + description:@"Failed to copy persistent ref"]; + } + CFReleaseNull(pref); + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + CFReleaseNull(pref); + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + + return YES; +} + @end diff --git a/keychain/otctl/OTControlCLI.h b/keychain/otctl/OTControlCLI.h index a62f3bce..71a61523 100644 --- a/keychain/otctl/OTControlCLI.h +++ b/keychain/otctl/OTControlCLI.h @@ -11,34 +11,58 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithOTControl:(OTControl*)control; -- (long)startOctagonStateMachine:(NSString*)container context:(NSString*)contextID; +- (long)startOctagonStateMachine:(NSString *)container context:(NSString *)contextID; -- (long)signIn:(NSString*)altDSID container:(NSString* _Nullable)container context:(NSString*)contextID; +- (long)signIn:(NSString *)altDSID container:(NSString * _Nullable)container context:(NSString *)contextID; -- (long)signOut:(NSString* _Nullable)container context:(NSString*)contextID; +- (long)signOut:(NSString * _Nullable)container context:(NSString *)contextID; -- (long)depart:(NSString* _Nullable)container context:(NSString*)contextID; +- (long)depart:(NSString * _Nullable)container context:(NSString *)contextID; -- (long)resetOctagon:(NSString*)container context:(NSString*)contextID altDSID:(NSString*)altDSID; +- (long)resetOctagon:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID; -- (long)status:(NSString* _Nullable)container context:(NSString*)contextID json:(bool)json; +- (long)resetProtectedData:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID appleID:(NSString *)appleID dsid:(NSString *)dsid; -- (long)recoverUsingBottleID:(NSString*)bottleID - entropy:(NSData*)entropy - altDSID:(NSString*)altDSID - containerName:(NSString*)containerName - context:(NSString*)context - control:(OTControl*)control; +- (long)status:(NSString * _Nullable)container context:(NSString *)contextID json:(bool)json; -- (long)fetchAllBottles:(NSString*)altDSID - containerName:(NSString*)containerName - context:(NSString*)context - control:(OTControl*)control; +- (long)recoverUsingBottleID:(NSString *)bottleID + entropy:(NSData *)entropy + altDSID:(NSString *)altDSID + containerName:(NSString *)containerName + context:(NSString *)context + control:(OTControl *)control; -- (long)healthCheck:(NSString* _Nullable)container context:(NSString*)contextID skipRateLimitingCheck:(BOOL)skipRateLimitingCheck; +- (long)fetchAllBottles:(NSString *)altDSID + containerName:(NSString *)containerName + context:(NSString *)context + control:(OTControl *)control; + +- (long)fetchEscrowRecords:(NSString * _Nullable)container context:(NSString *)contextID; +- (long)fetchAllEscrowRecords:(NSString* _Nullable)container context:(NSString*)contextID; + +- (long)healthCheck:(NSString * _Nullable)container context:(NSString *)contextID skipRateLimitingCheck:(BOOL)skipRateLimitingCheck; +- (long)refetchCKKSPolicy:(NSString *)container context:(NSString *)contextID; - (long)tapToRadar:(NSString *)action description:(NSString *)description radar:(NSString *)radar; +- (long)performEscrowRecovery:(NSString * _Nullable)container + context:(NSString *)contextID + recordID:(NSString *)recordID + appleID:(NSString *)appleID + secret:(NSString *)secret; + +- (long)performSilentEscrowRecovery:(NSString * _Nullable)container context:(NSString *)contextID appleID:(NSString *)appleID secret:(NSString *)secret; + +- (long)setUserControllableViewsSyncStatus:(NSString * _Nullable)containerName + contextID:(NSString *)contextID + enabled:(BOOL)enabled; + +- (long)fetchUserControllableViewsSyncStatus:(NSString * _Nullable)containerName + contextID:(NSString *)contextID; + +- (long)resetAccountCDPContentsWithContainerName:(NSString *)containerName + contextID:(NSString *)contextID; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/otctl/OTControlCLI.m b/keychain/otctl/OTControlCLI.m index 5fa418c4..828fed15 100644 --- a/keychain/otctl/OTControlCLI.m +++ b/keychain/otctl/OTControlCLI.m @@ -10,11 +10,52 @@ #include "utilities/SecInternalReleasePriv.h" #import "utilities/debugging.h" +#import "keychain/ot/OTClique.h" #import "keychain/ot/OT.h" #import "keychain/ot/OTConstants.h" #import "keychain/ot/OTControl.h" + #import "keychain/otctl/OTControlCLI.h" +#import "keychain/OctagonTrust/OctagonTrust.h" + +#import +#import +#import + +static NSString * fetch_pet(NSString * appleID, NSString * dsid) +{ + if(!appleID && !dsid) { + NSLog(@"Must provide either an AppleID or a DSID to fetch a PET"); + exit(1); + } + + AKAppleIDAuthenticationContext* authContext = [[AKAppleIDAuthenticationContext alloc] init]; + authContext.username = appleID; + + authContext.authenticationType = AKAppleIDAuthenticationTypeSilent; + authContext.isUsernameEditable = NO; + + __block NSString * pet = nil; + + dispatch_semaphore_t s = dispatch_semaphore_create(0); + + AKAppleIDAuthenticationController *authenticationController = [[AKAppleIDAuthenticationController alloc] init]; + [authenticationController authenticateWithContext:authContext + completion:^(AKAuthenticationResults authenticationResults, NSError *error) { + if(error) { + NSLog(@"error fetching PET: %@", error); + exit(1); + } + + pet = authenticationResults[AKAuthenticationPasswordKey]; + dispatch_semaphore_signal(s); + }]; + dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER); + + return pet; +} + // Mutual recursion to set up an object for jsonification static NSDictionary* cleanDictionaryForJSON(NSDictionary* dict); @@ -91,7 +132,7 @@ static void print_json(NSDictionary* dict) return self; } -- (long)startOctagonStateMachine:(NSString*)container context:(NSString*)contextID { +- (long)startOctagonStateMachine:(NSString *)container context:(NSString *)contextID { #if OCTAGON __block long ret = -1; @@ -113,7 +154,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)signIn:(NSString*)altDSID container:(NSString* _Nullable)container context:(NSString*)contextID { +- (long)signIn:(NSString *)altDSID container:(NSString * _Nullable)container context:(NSString *)contextID { #if OCTAGON __block long ret = -1; @@ -136,7 +177,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)signOut:(NSString* _Nullable)container context:(NSString*)contextID { +- (long)signOut:(NSString * _Nullable)container context:(NSString *)contextID { #if OCTAGON __block long ret = -1; [self.control signOut:container @@ -156,7 +197,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)depart:(NSString* _Nullable)container context:(NSString*)contextID { +- (long)depart:(NSString * _Nullable)container context:(NSString *)contextID { #if OCTAGON __block long ret = -1; @@ -177,7 +218,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)resetOctagon:(NSString*)container context:(NSString*)contextID altDSID:(NSString*)altDSID { +- (long)resetOctagon:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID { #if OCTAGON __block long ret = -1; @@ -201,13 +242,38 @@ static void print_json(NSDictionary* dict) #endif } -- (void)printPeer:(NSDictionary*)peerInformation prefix:(NSString* _Nullable)prefix { - NSString* peerID = peerInformation[@"peerID"]; - NSString* model = peerInformation[@"permanentInfo"][@"model_id"]; + +- (long)resetProtectedData:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID appleID:(NSString *)appleID dsid:(NSString *)dsid +{ +#if OCTAGON + __block long ret = -1; + + NSError* error = nil; + OTConfigurationContext *data = [[OTConfigurationContext alloc] init]; + data.passwordEquivalentToken = fetch_pet(appleID, dsid); + data.authenticationAppleID = appleID; + data.altDSID = altDSID; + data.context = contextID; + data.containerName = container; + + OTClique* clique = [OTClique resetProtectedData:data error:&error]; + if(clique != nil && error == nil) { + ret = 0; + } + return ret; +#else + printf("Unimplemented.\n"); + return -1; +#endif +} + +- (void)printPeer:(NSDictionary*)peerInformation prefix:(NSString * _Nullable)prefix { + NSString * peerID = peerInformation[@"peerID"]; + NSString * model = peerInformation[@"permanentInfo"][@"model_id"]; NSNumber* epoch = peerInformation[@"permanentInfo"][@"epoch"]; - NSString* deviceName = peerInformation[@"stableInfo"][@"device_name"]; - NSString* serialNumber = peerInformation[@"stableInfo"][@"serial_number"]; - NSString* os = peerInformation[@"stableInfo"][@"os_version"]; + NSString * deviceName = peerInformation[@"stableInfo"][@"device_name"]; + NSString * serialNumber = peerInformation[@"stableInfo"][@"serial_number"]; + NSString * os = peerInformation[@"stableInfo"][@"os_version"]; printf("%s%s hw:'%s' name:'%s' serial: '%s' os:'%s' epoch:%d\n", (prefix ? [prefix UTF8String] : ""), @@ -219,10 +285,10 @@ static void print_json(NSDictionary* dict) [epoch intValue]); } -- (void)printPeers:(NSArray*)peerIDs - egoPeerID:(NSString* _Nullable)egoPeerID - informationOnPeers:(NSDictionary*)informationOnPeers { - for(NSString* peerID in peerIDs) { +- (void)printPeers:(NSArray*)peerIDs + egoPeerID:(NSString * _Nullable)egoPeerID + informationOnPeers:(NSDictionary*)informationOnPeers { + for(NSString * peerID in peerIDs) { NSDictionary* peerInformation = informationOnPeers[peerID]; if(!peerInformation) { @@ -238,7 +304,156 @@ static void print_json(NSDictionary* dict) } } -- (long)status:(NSString* _Nullable)container context:(NSString*)contextID json:(bool)json { +- (long)fetchEscrowRecords:(NSString * _Nullable)container context:(NSString *)contextID { +#if OCTAGON + __block long ret = -1; + + NSError* error = nil; + OTConfigurationContext *data = [[OTConfigurationContext alloc] init]; + data.context = contextID; + data.containerName = container; + + NSArray* records = [OTClique fetchEscrowRecords:data error:&error]; + if(records != nil && error == nil) { + printf("Successfully fetched %lu records.\n", (unsigned long)records.count); + ret = 0; + for(OTEscrowRecord* record in records){ + CFErrorRef* localError = NULL; + SOSPeerInfoRef peer = SOSPeerInfoCreateFromData(kCFAllocatorDefault, localError, (__bridge CFDataRef)record.escrowInformationMetadata.peerInfo); + CFStringRef peerID = SOSPeerInfoGetPeerID(peer); + printf("fetched record id: %s\n", [(__bridge NSString *)peerID UTF8String]); + } + } + return ret; +#else + printf("Unimplemented.\n"); + return -1; +#endif +} + +- (long)fetchAllEscrowRecords:(NSString* _Nullable)container context:(NSString*)contextID { +#if OCTAGON + __block long ret = -1; + + NSError* error = nil; + OTConfigurationContext *data = [[OTConfigurationContext alloc] init]; + data.context = contextID; + data.containerName = container; + + NSArray* records = [OTClique fetchAllEscrowRecords:data error:&error]; + if(records != nil && error == nil) { + printf("Successfully fetched %lu records.\n", (unsigned long)records.count); + ret = 0; + for(OTEscrowRecord* record in records){ + CFErrorRef* localError = NULL; + SOSPeerInfoRef peer = SOSPeerInfoCreateFromData(kCFAllocatorDefault, localError, (__bridge CFDataRef)record.escrowInformationMetadata.peerInfo); + CFStringRef peerID = SOSPeerInfoGetPeerID(peer); + printf("fetched record id: %s\n", [(__bridge NSString*)peerID UTF8String]); + } + } + return ret; +#else + printf("Unimplemented.\n"); + return -1; +#endif +} + +- (long)performEscrowRecovery:(NSString * _Nullable)container context:(NSString *)contextID recordID:(NSString *)recordID appleID:(NSString *)appleID secret:(NSString *)secret +{ +#if OCTAGON + __block long ret = -1; + + NSError* error = nil; + OTConfigurationContext *data = [[OTConfigurationContext alloc] init]; + data.context = contextID; + + OTICDPRecordContext* cdpContext = [[OTICDPRecordContext alloc] init]; + cdpContext.cdpInfo = [[OTCDPRecoveryInformation alloc] init]; + cdpContext.cdpInfo.recoverySecret = secret; + cdpContext.cdpInfo.containsIcdpData = true; + cdpContext.cdpInfo.usesMultipleIcsc = true; + cdpContext.authInfo = [[OTEscrowAuthenticationInformation alloc] init]; + cdpContext.authInfo.authenticationAppleid = appleID; + cdpContext.authInfo.authenticationPassword = fetch_pet(appleID, nil); + + NSArray* escrowRecords = [OTClique fetchEscrowRecords:data error:&error]; + if (escrowRecords == nil || error != nil) { + printf("Failed to fetch escrow records.\n"); + ret = -1; + } + OTEscrowRecord* record = nil; + + for (OTEscrowRecord* r in escrowRecords) { + CFErrorRef* localError = NULL; + SOSPeerInfoRef peer = SOSPeerInfoCreateFromData(kCFAllocatorDefault, localError, (__bridge CFDataRef)r.escrowInformationMetadata.peerInfo); + CFStringRef peerID = SOSPeerInfoGetPeerID(peer); + + if ([(__bridge NSString *)peerID isEqualToString:recordID]) { + record = r; + break; + } + } + if (record == nil){ + printf("Failed to find escrow record to restore. \n"); + return -1; + } + + OTClique* clique = [OTClique performEscrowRecovery:data cdpContext:cdpContext escrowRecord:record error:&error]; + if (clique != nil && error == nil) { + printf("Successfully performed escrow recovery.\n"); + ret = 0; + } else { + fprintf(stderr, "Escrow recovery failed: %s\n", error.description.UTF8String); + } + return ret; +#else + printf("Unimplemented.\n"); + return -1; +#endif +} + +- (long)performSilentEscrowRecovery:(NSString * _Nullable)container context:(NSString *)contextID appleID:(NSString *)appleID secret:(NSString *)secret { +#if OCTAGON + __block long ret = -1; + + NSError* error = nil; + OTConfigurationContext *data = [[OTConfigurationContext alloc] init]; + data.context = contextID; + + OTICDPRecordContext* cdpContext = [[OTICDPRecordContext alloc] init]; + cdpContext.cdpInfo = [[OTCDPRecoveryInformation alloc] init]; + + cdpContext.cdpInfo.recoverySecret = secret; + cdpContext.cdpInfo.containsIcdpData = true; + cdpContext.cdpInfo.silentRecoveryAttempt = true; + cdpContext.cdpInfo.usesMultipleIcsc = true; + + cdpContext.authInfo = [[OTEscrowAuthenticationInformation alloc] init]; + cdpContext.authInfo.authenticationAppleid = appleID; + cdpContext.authInfo.authenticationPassword = fetch_pet(appleID, nil); + + + NSArray* records = [OTClique fetchEscrowRecords:data error:&error]; + if (records == nil || error != nil) { + printf("Failed to fetch escrow records.\n"); + ret = -1; + } + OTClique* clique = [OTClique performSilentEscrowRecovery:data cdpContext:cdpContext allRecords:records error:&error]; + if (clique != nil && error == nil) { + printf("Successfully performed escrow recovery.\n"); + ret = 0; + } else { + fprintf(stderr, "Escrow recovery failed: %s\n", error.description.UTF8String); + } + return ret; +#else + printf("Unimplemented.\n"); + return -1; +#endif +} + + +- (long)status:(NSString * _Nullable)container context:(NSString *)contextID json:(bool)json { #if OCTAGON __block long ret = 0; @@ -267,10 +482,10 @@ static void print_json(NSDictionary* dict) NSDictionary* contextDump = result[@"contextDump"]; // Make it easy to find peer information - NSMutableDictionary* peers = [NSMutableDictionary dictionary]; - NSMutableArray* allPeerIDs = [NSMutableArray array]; + NSMutableDictionary* peers = [NSMutableDictionary dictionary]; + NSMutableArray* allPeerIDs = [NSMutableArray array]; for(NSDictionary* peerInformation in contextDump[@"peers"]) { - NSString* peerID = peerInformation[@"peerID"]; + NSString * peerID = peerInformation[@"peerID"]; if(peerID) { peers[peerID] = peerInformation; [allPeerIDs addObject:peerID]; @@ -278,7 +493,7 @@ static void print_json(NSDictionary* dict) } NSDictionary* egoInformation = contextDump[@"self"]; - NSString* egoPeerID = egoInformation[@"peerID"]; + NSString * egoPeerID = egoInformation[@"peerID"]; NSDictionary* egoDynamicInfo = egoInformation[@"dynamicInfo"]; if(egoPeerID) { @@ -289,7 +504,7 @@ static void print_json(NSDictionary* dict) // The self peer is technically a peer, so, shove it on in there peers[egoPeerID] = egoInformation; - NSArray* includedPeers = egoDynamicInfo[@"included"]; + NSArray* includedPeers = egoDynamicInfo[@"included"]; printf("Trusted peers (by me):\n"); if(includedPeers && includedPeers.count > 0) { [self printPeers:includedPeers egoPeerID:egoPeerID informationOnPeers:peers]; @@ -299,7 +514,7 @@ static void print_json(NSDictionary* dict) } printf("\n"); - NSArray* excludedPeers = egoDynamicInfo[@"excluded"]; + NSArray* excludedPeers = egoDynamicInfo[@"excluded"]; printf("Excluded peers (by me):\n"); if(excludedPeers && excludedPeers.count > 0) { [self printPeers:excludedPeers egoPeerID:egoPeerID informationOnPeers:peers]; @@ -340,11 +555,11 @@ static void print_json(NSDictionary* dict) #endif } -- (long)recoverUsingBottleID:(NSString*)bottleID +- (long)recoverUsingBottleID:(NSString *)bottleID entropy:(NSData*)entropy - altDSID:(NSString*)altDSID - containerName:(NSString*)containerName - context:(NSString*)context + altDSID:(NSString *)altDSID + containerName:(NSString *)containerName + context:(NSString *)context control:(OTControl*)control { __block long ret = 0; @@ -378,24 +593,24 @@ static void print_json(NSDictionary* dict) #endif } -- (long)fetchAllBottles:(NSString*)altDSID - containerName:(NSString*)containerName - context:(NSString*)context +- (long)fetchAllBottles:(NSString *)altDSID + containerName:(NSString *)containerName + context:(NSString *)context control:(OTControl*)control { __block long ret = 0; #if OCTAGON __block NSError* localError = nil; - __block NSArray* localViableBottleIDs = nil; - __block NSArray* localPartiallyViableBottleIDs = nil; + __block NSArray* localViableBottleIDs = nil; + __block NSArray* localPartiallyViableBottleIDs = nil; dispatch_semaphore_t sema = dispatch_semaphore_create(0); [control fetchAllViableBottles:containerName context:context - reply:^(NSArray* _Nullable sortedBottleIDs, - NSArray* _Nullable sortedPartialBottleIDs, + reply:^(NSArray* _Nullable sortedBottleIDs, + NSArray* _Nullable sortedPartialBottleIDs, NSError* _Nullable controlError) { if(controlError) { secnotice("clique", "findOptimalBottleIDsWithContextData errored: %@\n", controlError); @@ -413,11 +628,11 @@ static void print_json(NSDictionary* dict) return -1; } - [localViableBottleIDs enumerateObjectsUsingBlock:^(NSString* obj, NSUInteger idx, BOOL* stop) { + [localViableBottleIDs enumerateObjectsUsingBlock:^(NSString * obj, NSUInteger idx, BOOL* stop) { printf("preferred bottleID: %s\n", [obj UTF8String]); }]; - [localPartiallyViableBottleIDs enumerateObjectsUsingBlock:^(NSString* obj, NSUInteger idx, BOOL* stop) { + [localPartiallyViableBottleIDs enumerateObjectsUsingBlock:^(NSString * obj, NSUInteger idx, BOOL* stop) { printf("partial recovery bottleID: %s\n", [obj UTF8String]); }]; @@ -428,7 +643,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)healthCheck:(NSString* _Nullable)container context:(NSString*)contextID skipRateLimitingCheck:(BOOL)skipRateLimitingCheck +- (long)healthCheck:(NSString * _Nullable)container context:(NSString *)contextID skipRateLimitingCheck:(BOOL)skipRateLimitingCheck { #if OCTAGON __block long ret = -1; @@ -451,6 +666,28 @@ static void print_json(NSDictionary* dict) #endif } +- (long)refetchCKKSPolicy:(NSString *)container context:(NSString *)contextID +{ + #if OCTAGON + __block long ret = 1; + + [self.control refetchCKKSPolicy:container + contextID:contextID + reply:^(NSError * _Nullable error) { + if(error) { + printf("Error refetching CKKS policy: %s\n", [[error description] UTF8String]); + } else { + printf("CKKS refetch completed.\n"); + ret = 0; + } + }]; + return ret; + #else + printf("Unimplemented.\n"); + return 1; + #endif +} + - (long)tapToRadar:(NSString *)action description:(NSString *)description radar:(NSString *)radar { #if OCTAGON @@ -474,4 +711,80 @@ static void print_json(NSDictionary* dict) #endif } +- (long)setUserControllableViewsSyncStatus:(NSString * _Nullable)containerName + contextID:(NSString *)contextID + enabled:(BOOL)enabled +{ + #if OCTAGON + __block long ret = 1; + + [self.control setUserControllableViewsSyncStatus:containerName + contextID:contextID + enabled:enabled + reply:^(BOOL nowSyncing, NSError * _Nullable error) { + if(error) { + printf("Error setting user controllable views: %s\n", [[error description] UTF8String]); + } else { + printf("User controllable views are now %s.", [(nowSyncing ? @"enabled" : @"paused") UTF8String]); + ret = 0; + } + }]; + return ret; + #else + printf("Unimplemented.\n"); + return 1; + #endif +} + +- (long)fetchUserControllableViewsSyncStatus:(NSString * _Nullable)containerName + contextID:(NSString *)contextID +{ + #if OCTAGON + __block long ret = 1; + + [self.control fetchUserControllableViewsSyncStatus:containerName + contextID:contextID + reply:^(BOOL nowSyncing, NSError * _Nullable error) { + if(error) { + printf("Error setting user controllable views: %s\n", [[error description] UTF8String]); + } else { + printf("User controllable views are currently %s.", [(nowSyncing ? @"enabled" : @"paused") UTF8String]); + ret = 0; + } + }]; + return ret; + #else + printf("Unimplemented.\n"); + return 1; + #endif +} + +- (long)resetAccountCDPContentsWithContainerName:(NSString *)containerName + contextID:(NSString *)contextID { + __block long ret = 0; + +#if OCTAGON + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + [self.control resetAccountCDPContents:containerName contextID:contextID reply:^(NSError * _Nullable error) { + if(error) { + ret = -1; + printf("Error resetting account cdp content: %s\n", [[error description] UTF8String]); + } else { + printf("Succeeded resetting account cdp content"); + } + dispatch_semaphore_signal(sema); + }]; + + if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60)) != 0) { + printf("timed out waiting for restore/recover\n"); + ret = -1; + } + + return ret; +#else + ret = -1; + return ret; +#endif +} @end diff --git a/keychain/otctl/otctl-Entitlements.plist b/keychain/otctl/otctl-Entitlements.plist index 472e6b42..311579d3 100644 --- a/keychain/otctl/otctl-Entitlements.plist +++ b/keychain/otctl/otctl-Entitlements.plist @@ -2,6 +2,14 @@ + com.apple.securebackupd.access + + keychain-cloud-circle + + com.apple.private.ckks + + com.apple.authkit.client.private + com.apple.private.octagon com.apple.private.escrow-update diff --git a/keychain/otctl/otctl.m b/keychain/otctl/otctl.m index d569f7ea..b1bf5fca 100644 --- a/keychain/otctl/otctl.m +++ b/keychain/otctl/otctl.m @@ -7,6 +7,7 @@ #import #import #import +#import #import "keychain/otctl/OTControlCLI.h" #import "keychain/otctl/EscrowRequestCLI.h" @@ -22,6 +23,8 @@ static int start = false; static int signIn = false; static int signOut = false; static int resetoctagon = false; +static int resetProtectedData = false; +static int userControllableViewsSyncStatus = false; static int fetchAllBottles = false; static int recover = false; @@ -33,9 +36,18 @@ static int er_trigger = false; static int er_status = false; static int er_reset = false; static int er_store = false; +static int ckks_policy_flag = false; static int ttr_flag = false; +static int fetch_escrow_records = false; +static int fetch_all_escrow_records = false; + +static int recoverRecord = false; +static int recoverSilentRecord = false; + +static int resetAccountCDPContent = false; + static int health = false; #if TARGET_OS_WATCH @@ -46,11 +58,18 @@ static char* bottleIDArg = NULL; static char* contextNameArg = NULL; static char* secretArg = NULL; static char* skipRateLimitingCheckArg = NULL; +static char* recordID = NULL; + +static int argEnable = false; +static int argPause = false; + static int json = false; static char* altDSIDArg = NULL; static char* containerStr = NULL; static char* radarNumber = NULL; +static char* appleIDArg = NULL; +static char* dsidArg = NULL; static void internalOnly(void) { @@ -67,10 +86,17 @@ int main(int argc, char** argv) {.shortname = 'e', .longname = "bottleID", .argument = &bottleIDArg, .description = "bottle record id"}, {.shortname = 'r', .longname = "skipRateLimiting", .argument = &skipRateLimitingCheckArg, .description = " enter values YES or NO, option defaults to NO, This gives you the opportunity to skip the rate limiting check when performing the cuttlefish health check"}, {.shortname = 'j', .longname = "json", .flag = &json, .flagval = true, .description = "Output in JSON"}, + {.shortname = 'i', .longname = "recordID", .argument = &recordID, .flagval = true, .description = "recordID"}, + + {.shortname = 'E', .longname = "enable", .flag = &argEnable, .flagval = true, .description = "Enable something (pair with a modification command)"}, + {.shortname = 'P', .longname = "pause", .flag = &argPause, .flagval = true, .description = "Pause something (pair with a modification command)"}, {.longname = "altDSID", .argument = &altDSIDArg, .description = "altDSID (for sign-in/out)"}, {.longname = "entropy", .argument = &secretArg, .description = "escrowed entropy in JSON"}, + {.longname = "appleID", .argument = &appleIDArg, .description = "AppleID"}, + {.longname = "dsid", .argument = &dsidArg, .description = "DSID"}, + {.longname = "container", .argument = &containerStr, .description = "CloudKit container name"}, {.longname = "radar", .argument = &radarNumber, .description = "Radar number"}, @@ -78,7 +104,12 @@ int main(int argc, char** argv) {.command = "sign-in", .flag = &signIn, .flagval = true, .description = "Inform Cuttlefish container of sign in"}, {.command = "sign-out", .flag = &signOut, .flagval = true, .description = "Inform Cuttlefish container of sign out"}, {.command = "status", .flag = &status, .flagval = true, .description = "Report Octagon status"}, + {.command = "resetoctagon", .flag = &resetoctagon, .flagval = true, .description = "Reset and establish new Octagon trust"}, + {.command = "resetProtectedData", .flag = &resetProtectedData, .flagval = true, .description = "Reset ProtectedData"}, + + {.command = "user-controllable-views", .flag = &userControllableViewsSyncStatus, .flagval = true, .description = "Modify or view user-controllable views status (If one of --enable or --pause is passed, will modify status)"}, + {.command = "allBottles", .flag = &fetchAllBottles, .flagval = true, .description = "Fetch all viable bottles"}, {.command = "recover", .flag = &recover, .flagval = true, .description = "Recover using this bottle"}, {.command = "depart", .flag = &depart, .flagval = true, .description = "Depart from Octagon Trust"}, @@ -89,9 +120,19 @@ int main(int argc, char** argv) {.command = "er-store", .flag = &er_store, .flagval = true, .description = "Store any pending Escrow Request prerecords"}, {.command = "health", .flag = &health, .flagval = true, .description = "Check Octagon Health status"}, + {.command = "ckks-policy", .flag = &ckks_policy_flag, .flagval = true, .description = "Trigger a refetch of the CKKS policy"}, {.command = "taptoradar", .flag = &ttr_flag, .flagval = true, .description = "Trigger a TapToRadar"}, + {.command = "fetchEscrowRecords", .flag = &fetch_escrow_records, .flagval = true, .description = "Fetch Escrow Records"}, + {.command = "fetchAllEscrowRecords", .flag = &fetch_all_escrow_records, .flagval = true, .description = "Fetch All Escrow Records"}, + + {.command = "recover-record", .flag = &recoverRecord, .flagval = true, .description = "Recover record"}, + {.command = "recover-record-silent", .flag = &recoverSilentRecord, .flagval = true, .description = "Silent record recovery"}, + + {.command = "reset-account-cdp-contents", .flag = &resetAccountCDPContent, .flagval = true, .description = "Reset an account's CDP contents (escrow records, kvs data, cuttlefish)"}, + + #if TARGET_OS_WATCH {.command = "pairme", .flag = &pairme, .flagval = true, .description = "Perform pairing (watchOS only)"}, #endif /* TARGET_OS_WATCH */ @@ -121,6 +162,9 @@ int main(int argc, char** argv) NSString* context = contextNameArg ? [NSString stringWithCString:contextNameArg encoding:NSUTF8StringEncoding] : OTDefaultContext; NSString* container = containerStr ? [NSString stringWithCString:containerStr encoding:NSUTF8StringEncoding] : nil; NSString* altDSID = altDSIDArg ? [NSString stringWithCString:altDSIDArg encoding:NSUTF8StringEncoding] : nil; + NSString* dsid = dsidArg ? [NSString stringWithCString:dsidArg encoding:NSUTF8StringEncoding] : nil; + NSString* appleID = appleIDArg ? [NSString stringWithCString:appleIDArg encoding:NSUTF8StringEncoding] : nil; + NSString* skipRateLimitingCheck = skipRateLimitingCheckArg ? [NSString stringWithCString:skipRateLimitingCheckArg encoding:NSUTF8StringEncoding] : @"NO"; OTControlCLI* ctl = [[OTControlCLI alloc] initWithOTControl:rpc]; @@ -134,6 +178,27 @@ int main(int argc, char** argv) long ret = [ctl resetOctagon:container context:context altDSID:altDSID]; return (int)ret; } + if(resetProtectedData) { + internalOnly(); + long ret = [ctl resetProtectedData:container context:context altDSID:altDSID appleID:appleID dsid:dsid]; + return (int)ret; + } + if(userControllableViewsSyncStatus) { + internalOnly(); + + if(argEnable && argPause) { + print_usage(&args); + return -1; + } + + if(argEnable == false && argPause == false) { + return (int)[ctl fetchUserControllableViewsSyncStatus:container contextID:context]; + } + + // At this point, we're sure that either argEnabled or argPause is set; so the value of argEnabled captures the user's intention + return (int)[ctl setUserControllableViewsSyncStatus:container contextID:context enabled:argEnable]; + } + if(fetchAllBottles) { return (int)[ctl fetchAllBottles:altDSID containerName:container context:context control:rpc]; } @@ -178,7 +243,33 @@ int main(int argc, char** argv) if(status) { return (int)[ctl status:container context:context json:json]; } + if(fetch_escrow_records) { + return (int)[ctl fetchEscrowRecords:container context:context]; + } + if(fetch_all_escrow_records) { + return (int)[ctl fetchAllEscrowRecords:container context:context]; + } + if(recoverRecord) { + NSString* recordIDString = recordID ? [NSString stringWithCString:recordID encoding:NSUTF8StringEncoding] : nil; + NSString* secret = secretArg ? [NSString stringWithCString:secretArg encoding:NSUTF8StringEncoding] : nil; + if(!recordIDString || !secret || !appleID) { + print_usage(&args); + return -1; + } + + return (int)[ctl performEscrowRecovery:container context:context recordID:recordIDString appleID:appleID secret:secret]; + } + if(recoverSilentRecord){ + NSString* secret = secretArg ? [NSString stringWithCString:secretArg encoding:NSUTF8StringEncoding] : nil; + + if(!secret || !appleID) { + print_usage(&args); + return -1; + } + + return (int)[ctl performSilentEscrowRecovery:container context:context appleID:appleID secret:secret]; + } if(health) { BOOL skip = NO; if([skipRateLimitingCheck isEqualToString:@"YES"]) { @@ -188,12 +279,19 @@ int main(int argc, char** argv) } return (int)[ctl healthCheck:container context:context skipRateLimitingCheck:skip]; } + if(ckks_policy_flag) { + return (int)[ctl refetchCKKSPolicy:container context:context]; + } if (ttr_flag) { if (radarNumber == NULL) { radarNumber = "1"; } return (int)[ctl tapToRadar:@"action" description:@"description" radar:[NSString stringWithUTF8String:radarNumber]]; } + if(resetAccountCDPContent){ + return (int)[ctl resetAccountCDPContentsWithContainerName:container contextID:context]; + } + if(er_trigger) { internalOnly(); return (int)[escrowctl trigger]; @@ -208,7 +306,6 @@ int main(int argc, char** argv) return (int)[escrowctl storePrerecordsInEscrow]; } - #if TARGET_OS_WATCH if (pairme) { dispatch_semaphore_t sema = dispatch_semaphore_create(0); diff --git a/keychain/otpaird/OTPairingConstants.h b/keychain/otpaird/OTPairingConstants.h index 309ee32a..71f20133 100644 --- a/keychain/otpaird/OTPairingConstants.h +++ b/keychain/otpaird/OTPairingConstants.h @@ -3,10 +3,9 @@ #define OTPairingIDSServiceName @"com.apple.private.alloy.octagon" #define OTPairingIDSKeyMessageType @"m" -#define OTPairingIDSKeyError @"e" #define OTPairingIDSKeySession @"session" #define OTPairingIDSKeyPacket @"packet" -#define OTPairingIDSKeyErrorDeprecated @"error" +#define OTPairingIDSKeyErrorDescription @"error" enum OTPairingIDSMessageType { OTPairingIDSMessageTypePacket = 1, diff --git a/keychain/otpaird/OTPairingPacketContext.m b/keychain/otpaird/OTPairingPacketContext.m index 7fbbef9a..e8854f26 100644 --- a/keychain/otpaird/OTPairingPacketContext.m +++ b/keychain/otpaird/OTPairingPacketContext.m @@ -1,7 +1,6 @@ #import #import #import -#import #import "keychain/categories/NSError+UsefulConstructors.h" @@ -23,8 +22,7 @@ - (instancetype)initWithMessage:(NSDictionary *)message fromID:(NSString *)fromID context:(IDSMessageContext *)context { - self = [super init]; - if (self != nil) { + if ((self = [super init])) { self.message = message; self.fromID = fromID; self.context = context; @@ -69,15 +67,8 @@ } if (!self->_error) { - NSData *errorData = self.message[OTPairingIDSKeyError]; - if (errorData != NULL) { - self->_error = [SecXPCHelper errorFromEncodedData:errorData]; - } else { - // Key from older iOS builds; remove soon - // When this is removed, it will still be useful to have a fallback in case errorData is missing or errorFromEncodedData fails - NSString *errorString = self.message[OTPairingIDSKeyErrorDeprecated]; - self->_error = [NSError errorWithDomain:OTPairingErrorDomain code:OTPairingErrorTypeRemote description:errorString]; - } + NSString *errorString = self.message[OTPairingIDSKeyErrorDescription]; + self->_error = [NSError errorWithDomain:OTPairingErrorDomain code:OTPairingErrorTypeRemote description:errorString]; } return self->_error; diff --git a/keychain/otpaird/OTPairingService.m b/keychain/otpaird/OTPairingService.m index c1b70852..826230c0 100644 --- a/keychain/otpaird/OTPairingService.m +++ b/keychain/otpaird/OTPairingService.m @@ -3,7 +3,6 @@ #import #import #import -#import #import #if TARGET_OS_WATCH @@ -49,8 +48,7 @@ - (instancetype)init { - self = [super init]; - if (self != nil) { + if ((self = [super init])) { self.queue = dispatch_queue_create("com.apple.security.otpaird", DISPATCH_QUEUE_SERIAL); self.service = [[IDSService alloc] initWithService:OTPairingIDSServiceName]; [self.service addDelegate:self queue:self.queue]; @@ -159,8 +157,7 @@ NSMutableDictionary *message = [[NSMutableDictionary alloc] init]; message[OTPairingIDSKeyMessageType] = @(OTPairingIDSMessageTypeError); message[OTPairingIDSKeySession] = self.session.identifier; - message[OTPairingIDSKeyError] = [SecXPCHelper encodedDataFromError:unlockError]; - message[OTPairingIDSKeyErrorDeprecated] = unlockError.localizedDescription; // For older watchOS builds; remove soon + message[OTPairingIDSKeyErrorDescription] = unlockError.description; NSString *toID = packet.fromID; NSString *responseIdentifier = packet.outgoingResponseIdentifier; [self _sendMessage:message to:toID identifier:responseIdentifier]; @@ -194,12 +191,10 @@ if (channelError != nil) { #if TARGET_OS_IOS - NSError *cleansedError = [SecXPCHelper cleanseErrorForXPC:channelError]; NSMutableDictionary *message = [[NSMutableDictionary alloc] init]; message[OTPairingIDSKeyMessageType] = @(OTPairingIDSMessageTypeError); message[OTPairingIDSKeySession] = self.session.identifier; - message[OTPairingIDSKeyError] = cleansedError ? [SecXPCHelper encodedDataFromError:cleansedError] : nil; - message[OTPairingIDSKeyErrorDeprecated] = channelError.description; + message[OTPairingIDSKeyErrorDescription] = channelError.description; os_assert(packet != nil); // the acceptor always responds to a request packet, it's never initiating toID = packet.fromID; responseIdentifier = packet.outgoingResponseIdentifier; @@ -260,7 +255,10 @@ identifier:&identifier error:&error]; if (sendResult) { - self.session.sentMessageIdentifier = identifier; + /* sentMessageIdentifier is used to validate the next reply; do not set if no reply is expected. */ + if (expectReply) { + self.session.sentMessageIdentifier = identifier; + } } else { os_log(OS_LOG_DEFAULT, "send message failed (%@): %@", identifier, error); // On iOS, do nothing; watch will time out waiting for response. diff --git a/keychain/otpaird/OTPairingSession.m b/keychain/otpaird/OTPairingSession.m index 9444f1ca..3d4cf579 100644 --- a/keychain/otpaird/OTPairingSession.m +++ b/keychain/otpaird/OTPairingSession.m @@ -22,8 +22,7 @@ { KCPairingChannelContext *channelContext = nil; - self = [super init]; - if (self != nil) { + if ((self = [super init])) { self.identifier = identifier; channelContext = [KCPairingChannelContext new]; diff --git a/keychain/otpaird/otpaird.iphoneos.entitlements b/keychain/otpaird/otpaird.iphoneos.entitlements index 687c9a25..55994f03 100644 --- a/keychain/otpaird/otpaird.iphoneos.entitlements +++ b/keychain/otpaird/otpaird.iphoneos.entitlements @@ -10,28 +10,13 @@ com.apple.private.octagon - com.apple.security.exception.files.absolute-path.read-only - - /usr/libexec - - com.apple.security.exception.iokit-user-client-class - - AppleKeyStoreUserClient - - com.apple.security.exception.mach-lookup.global-name - - com.apple.security.octagon - com.apple.securityd.sos - - com.apple.security.ts.identity-services-client - keychain-cloud-circle platform-application seatbelt-profiles - temporary-sandbox + otpaird diff --git a/keychain/otpaird/otpaird.watchos.entitlements b/keychain/otpaird/otpaird.watchos.entitlements index 32082d1c..4749b51b 100644 --- a/keychain/otpaird/otpaird.watchos.entitlements +++ b/keychain/otpaird/otpaird.watchos.entitlements @@ -10,25 +10,11 @@ com.apple.private.octagon - com.apple.security.exception.files.absolute-path.read-only - - /usr/libexec - - com.apple.security.exception.iokit-user-client-class - - AppleKeyStoreUserClient - - com.apple.security.exception.mach-lookup.global-name - - com.apple.security.octagon - - com.apple.security.ts.identity-services-client - platform-application seatbelt-profiles - temporary-sandbox + otpaird diff --git a/keychain/securityd/PolicyReporter.m b/keychain/securityd/PolicyReporter.m index c5b42c66..69aecb43 100644 --- a/keychain/securityd/PolicyReporter.m +++ b/keychain/securityd/PolicyReporter.m @@ -172,6 +172,13 @@ static void oneReport(void) { NSLog(@"policy is nil"); return; } + TPSyncingPolicy* syncingPolicy = [policy syncingPolicyForModel:@"iPhone" + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_UNKNOWN + error:&error]; + if(syncingPolicy == nil || error != nil) { + NSLog(@"syncing policy is nil: %@", error); + return; + } unsigned real_mismatches = 0; unsigned expected_mismatches = 0; @@ -219,7 +226,7 @@ static void oneReport(void) { NSMutableDictionary* mutA = [a mutableCopy]; mutA[(id)kSecClass] = (id)itemClass; - NSString* newView = [policy mapKeyToView:mutA]; + NSString* newView = [syncingPolicy mapDictionaryToView:mutA]; if (newView != nil) { NSLog(@"new: %@", newView); } diff --git a/keychain/securityd/Regressions/SOSAccountTesting.h b/keychain/securityd/Regressions/SOSAccountTesting.h index f2d431ee..66528288 100644 --- a/keychain/securityd/Regressions/SOSAccountTesting.h +++ b/keychain/securityd/Regressions/SOSAccountTesting.h @@ -90,6 +90,14 @@ static inline void SOSAccountPeerGotInSync_wTxn(SOSAccount* acct, SOSPeerInfoRef }]; } +static inline CFArrayRef SOSAccountCopyViewUnawarePeers_wTxn(SOSAccount* acct, CFErrorRef* error) { + __block CFArrayRef result = false; + [acct performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + result = SOSAccountCopyViewUnaware(txn.account, error); + }]; + return result; +} + static inline bool SOSAccountSetBackupPublicKey_wTxn(SOSAccount* acct, CFDataRef backupKey, CFErrorRef* error) { __block bool result = false; @@ -116,6 +124,41 @@ static inline SOSViewResultCode SOSAccountUpdateView_wTxn(SOSAccount* acct, CFSt return result; } +static inline bool SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(SOSAccount *account, CFStringRef viewname) { + __block bool result = false; + [account performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + result = SOSAccountIsMyPeerInBackupAndCurrentInView(account, viewname); + }]; + return result; +} + +static inline bool SOSAccountIsPeerInBackupAndCurrentInView_wTxn(SOSAccount *account, SOSPeerInfoRef peerInfo, CFStringRef viewname) { + __block bool result = false; + [account performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + result = SOSAccountIsPeerInBackupAndCurrentInView(account, peerInfo, viewname); + }]; + return result; +} + +static inline bool SOSAccountRecoveryKeyIsInBackupAndCurrentInView_wTxn(SOSAccount *account, CFStringRef viewname) { + __block bool result = false; + [account performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + result = SOSAccountRecoveryKeyIsInBackupAndCurrentInView(account, viewname); + }]; + return result; +} + +static inline SOSBackupSliceKeyBagRef SOSAccountBackupSliceKeyBagForView_wTxn(SOSAccount *account, CFStringRef viewname, CFErrorRef *error) { + __block SOSBackupSliceKeyBagRef result = NULL; + [account performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + result = SOSAccountBackupSliceKeyBagForView(account, viewname, error); + }]; + return result; +} + + + + // // Account comparison // @@ -141,7 +184,9 @@ static void SOSAccountResetToTest(SOSAccount* a, CFStringRef accountName) { a.key_transport = nil; a.kvs_message_transport = nil; - SOSAccountEnsureFactoryCirclesTest(a, accountName); + [a performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + SOSAccountEnsureFactoryCirclesTest(a, accountName); + }]; } @@ -619,17 +664,6 @@ static inline int ProcessChangesUntilNoChange(CFMutableDictionaryRef changes, .. // MARK: Account creation // -static CFStringRef modelFromType(SOSPeerInfoDeviceClass cls) { - switch(cls) { - case SOSPeerInfo_macOS: return CFSTR("Mac Pro"); - case SOSPeerInfo_iOS: return CFSTR("iPhone"); - case SOSPeerInfo_iCloud: return CFSTR("iCloud"); - case SOSPeerInfo_watchOS: return CFSTR("needWatchOSDeviceName"); - case SOSPeerInfo_tvOS: return CFSTR("needTVOSDeviceName"); - default: return CFSTR("GENERICOSTHING"); - } -} - static inline SOSAccount* CreateAccountForLocalChangesWithStartingAttributes(CFStringRef name, CFStringRef data_source_name, SOSPeerInfoDeviceClass devclass, CFStringRef serial, CFBooleanRef preferIDS, CFBooleanRef preferIDSFragmentation, CFBooleanRef preferIDSACKModel, CFStringRef transportType, CFStringRef deviceID) { SOSDataSourceFactoryRef factory = SOSTestDataSourceFactoryCreate(); @@ -640,7 +674,7 @@ static inline SOSAccount* CreateAccountForLocalChangesWithStartingAttributes(CFS CFMutableDictionaryRef gestalt = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); CFDictionaryAddValue(gestalt, kPIUserDefinedDeviceNameKey, name); - CFDictionaryAddValue(gestalt, kPIDeviceModelNameKey, modelFromType(devclass)); + CFDictionaryAddValue(gestalt, kPIDeviceModelNameKey, SOSModelFromType(devclass)); CFDictionaryAddValue(gestalt, kPIOSVersionKey, CFSTR("TESTRUN")); CFMutableDictionaryRef testV2dict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); @@ -810,7 +844,10 @@ static inline bool testAccountPersistence(SOSAccount* account) { SOSAccount* reinflatedAccount = NULL; NSError* error = nil; - require(retval, errOut); + if(!retval) { + error = nil; + return retval; + } // Re-inflate to "inflated" reinflatedAccount = [SOSAccount accountFromData:accountDER @@ -822,16 +859,20 @@ static inline bool testAccountPersistence(SOSAccount* account) { ok(CFEqualSafe((__bridge CFTypeRef)reinflatedAccount, (__bridge CFTypeRef)account), "Compares"); // Repeat through SOSAccountCopyEncodedData() interface - this is the normally called combined interface - accountDER = [account encodedData:&error]; + [account performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + NSError* error = nil; + accountDER = [account encodedData:&error]; + }]; + error = nil; - reinflatedAccount = [SOSAccount accountFromData:accountDER factory:test_factory error:&error]; - ok(reinflatedAccount, "inflated2: %@", error); - ok(CFEqual((__bridge CFTypeRef)account, (__bridge CFTypeRef)reinflatedAccount), "Compares"); + SOSAccount* reinflatedAccount2 = NULL; + + reinflatedAccount2 = [SOSAccount accountFromData:accountDER factory:test_factory error:&error]; + ok(reinflatedAccount2, "inflated2: %@", error); + ok(CFEqual((__bridge CFTypeRef)account, (__bridge CFTypeRef)reinflatedAccount2), "Compares"); retval = true; -errOut: error = nil; - return retval; } diff --git a/keychain/securityd/Regressions/SOSTransportTestTransports.m b/keychain/securityd/Regressions/SOSTransportTestTransports.m index e354c55f..24b0050f 100644 --- a/keychain/securityd/Regressions/SOSTransportTestTransports.m +++ b/keychain/securityd/Regressions/SOSTransportTestTransports.m @@ -29,8 +29,7 @@ CFMutableArrayRef message_transports = NULL; -(id) initWithAccount:(SOSAccount*) acct andName:(CFStringRef) n andCircleName:(CFStringRef) cN { - self = [super init]; - if(self){ + if ((self = [super init])) { self.name = CFRetainSafe(n); self.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); self.account = acct; @@ -142,8 +141,7 @@ void SOSTransportCircleTestClearChanges(SOSCircleStorageTransportTest* transport -(id) initWithAccount:(SOSAccount *)acct andWithAccountName:(CFStringRef)acctName andCircleName:(CFStringRef)cName { - self = [super init]; - if(self){ + if ((self = [super init])) { self.account = acct; self.accountName = (__bridge NSString *)(acctName); self.circleName = (__bridge NSString*)cName; @@ -313,8 +311,7 @@ SOSAccount* SOSTransportCircleTestGetAccount(SOSCircleStorageTransportTest* tran -(id) initWithAccount:(SOSAccount*)acct andName:(CFStringRef)n andCircleName:(CFStringRef) cN { - self = [super init]; - if(self){ + if ((self = [super init])) { self.engine = SOSDataSourceFactoryGetEngineForDataSourceName(acct.factory, cN, NULL); self.account = acct; self.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); @@ -513,12 +510,12 @@ void SOSAccountUpdateTestTransports(SOSAccount* account, CFDictionaryRef gestalt SOSTransportMessageKVSTestSetName((SOSMessageKVSTest*)account.kvs_message_transport, new_name); } -static CF_RETURNS_RETAINED SOSCircleRef SOSAccountEnsureCircleTest(SOSAccount* a, CFStringRef name, CFStringRef accountName) +static CF_RETURNS_RETAINED SOSCircleRef SOSAccountEnsureCircleTest(SOSAccount* account, CFStringRef name, CFStringRef accountName) { CFErrorRef localError = NULL; - SOSAccountTrustClassic *trust = a.trust; + SOSAccountTrustClassic *trust = account.trust; - SOSCircleRef circle = CFRetainSafe([a.trust getCircle:&localError]); + SOSCircleRef circle = CFRetainSafe([account.trust getCircle:&localError]); if(!circle || isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle)){ secnotice("circle", "Error retrieving the circle: %@", localError); CFReleaseNull(localError); @@ -534,7 +531,7 @@ static CF_RETURNS_RETAINED SOSCircleRef SOSAccountEnsureCircleTest(SOSAccount* a CFReleaseNull(localError); } - if(![trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)(a.gestalt) deviceID:(__bridge CFStringRef)(a.deviceID) backupKey:(__bridge CFDataRef)(a.backup_key) err:&localError]) + if(![trust ensureFullPeerAvailable:account err:&localError]) { secnotice("circle", "had an error building full peer: %@", localError); CFReleaseNull(localError); diff --git a/keychain/securityd/Regressions/SecdTestKeychainUtilities.h b/keychain/securityd/Regressions/SecdTestKeychainUtilities.h index e11ed683..5218fcd3 100644 --- a/keychain/securityd/Regressions/SecdTestKeychainUtilities.h +++ b/keychain/securityd/Regressions/SecdTestKeychainUtilities.h @@ -30,6 +30,7 @@ #define kSecdTestSetupTestCount 1 void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_before_reset); +bool secd_test_teardown_delete_temp_keychain(const char* test_prefix); extern CFStringRef kTestView1; extern CFStringRef kTestView2; diff --git a/keychain/securityd/Regressions/SecdTestKeychainUtilities.c b/keychain/securityd/Regressions/SecdTestKeychainUtilities.m similarity index 64% rename from keychain/securityd/Regressions/SecdTestKeychainUtilities.c rename to keychain/securityd/Regressions/SecdTestKeychainUtilities.m index b5700649..b197965a 100644 --- a/keychain/securityd/Regressions/SecdTestKeychainUtilities.c +++ b/keychain/securityd/Regressions/SecdTestKeychainUtilities.m @@ -30,6 +30,10 @@ #include "keychain/securityd/SecItemServer.h" #include +#include "keychain/securityd/SecItemDataSource.h" + +#import "Analytics/Clients/SOSAnalytics.h" + #include @@ -42,6 +46,7 @@ void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_ { CFStringRef tmp_dir = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("/tmp/%s.%X/"), test_prefix, arc4random()); CFStringRef keychain_dir = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@Library/Keychains"), tmp_dir); + secnotice("secdtest", "Keychain path: %@", keychain_dir); CFStringPerformWithCString(keychain_dir, ^(const char *keychain_dir_string) { errno_t err = mkpath_np(keychain_dir_string, 0755); @@ -50,7 +55,7 @@ void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_ /* set custom keychain dir, reset db */ - SetCustomHomeURLString(tmp_dir); + SecSetCustomHomeURLString(tmp_dir); SecKeychainDbReset(do_in_reset); @@ -58,6 +63,38 @@ void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_ CFReleaseNull(keychain_dir); } +bool secd_test_teardown_delete_temp_keychain(const char* test_prefix) +{ + NSURL* keychainDir = (NSURL*)CFBridgingRelease(SecCopyHomeURL()); + + // Drop analytics dbs here + [[SOSAnalytics logger] removeState]; + + secd_test_clear_testviews(); + SecItemDataSourceFactoryReleaseAll(); + SecKeychainDbForceClose(); + SecKeychainDbReset(NULL); + + // Only perform the desctructive step if the url matches what we expect! + NSString* testName = [NSString stringWithUTF8String:test_prefix]; + + if([keychainDir.path hasPrefix:[NSString stringWithFormat:@"/tmp/%@.", testName]]) { + secnotice("secd_tests", "Removing test-specific keychain directory at %@", keychainDir); + + NSError* removeError = nil; + [[NSFileManager defaultManager] removeItemAtURL:keychainDir error:&removeError]; + if(removeError) { + secnotice("secd_tests", "Failed to remove directory: %@", removeError); + return false; + } + + return true; + } else { + secnotice("secd_tests", "Not removing keychain directory (%@), as it doesn't appear to be test-specific (for test %@)", keychainDir.path, testName); + return false; + } +} + CFStringRef kTestView1 = CFSTR("TestView1"); CFStringRef kTestView2 = CFSTR("TestView2"); diff --git a/keychain/securityd/Regressions/secd-01-items.m b/keychain/securityd/Regressions/secd-01-items.m index a84b48b5..c7266457 100644 --- a/keychain/securityd/Regressions/secd-01-items.m +++ b/keychain/securityd/Regressions/secd-01-items.m @@ -140,15 +140,14 @@ int secd_01_items(int argc, char *const *argv) /* Reset keybag and custom $HOME */ SecItemServerResetKeychainKeybag(); - SetCustomHomePath(NULL); - SecKeychainDbReset(NULL); - + secd_test_teardown_delete_temp_keychain("secd_01_items"); CFReleaseNull(pwdata); CFReleaseNull(eighty); CFReleaseSafe(item); CFReleaseSafe(query); + return 0; } diff --git a/keychain/securityd/Regressions/secd-02-upgrade-while-locked.m b/keychain/securityd/Regressions/secd-02-upgrade-while-locked.m index e57931b1..a46c4eec 100644 --- a/keychain/securityd/Regressions/secd-02-upgrade-while-locked.m +++ b/keychain/securityd/Regressions/secd-02-upgrade-while-locked.m @@ -185,6 +185,8 @@ int secd_02_upgrade_while_locked(int argc, char *const *argv) CFReleaseNull(old_ag); CFReleaseSafe(test_ag); + secd_test_teardown_delete_temp_keychain("secd_02_upgrade_while_locked"); + return 0; } diff --git a/keychain/securityd/Regressions/secd-03-corrupted-items.m b/keychain/securityd/Regressions/secd-03-corrupted-items.m index 7addd192..a6fc8dff 100644 --- a/keychain/securityd/Regressions/secd-03-corrupted-items.m +++ b/keychain/securityd/Regressions/secd-03-corrupted-items.m @@ -115,7 +115,7 @@ static const char *corrupt_item_sql = "UPDATE inet SET data=X'12345678' WHERE ro int secd_03_corrupted_items(int argc, char *const *argv) { - plan_tests(4 + N_THREADS*21 + kSecdTestSetupTestCount); + plan_tests(5 + N_THREADS*21 + kSecdTestSetupTestCount); /* custom keychain dir */ secd_test_setup_temp_keychain("secd_03_corrupted_items", NULL); @@ -146,6 +146,8 @@ int secd_03_corrupted_items(int argc, char *const *argv) is(sqlite3_exec(db, corrupt_item_sql, NULL, NULL, NULL), SQLITE_OK, "corrupting keychain item1"); + is(sqlite3_close_v2(db), SQLITE_OK, + "Should be able to close db");; }); pthread_t add_thread[N_THREADS]; @@ -166,6 +168,8 @@ int secd_03_corrupted_items(int argc, char *const *argv) CFReleaseNull(eighty); CFReleaseNull(pwdata); CFReleaseNull(keychain_path_cf); + + secd_test_teardown_delete_temp_keychain("secd_03_corrupted_items"); return 0; } diff --git a/keychain/securityd/Regressions/secd-04-corrupted-items.m b/keychain/securityd/Regressions/secd-04-corrupted-items.m index 2c7db55c..b00ff30b 100644 --- a/keychain/securityd/Regressions/secd-04-corrupted-items.m +++ b/keychain/securityd/Regressions/secd-04-corrupted-items.m @@ -48,7 +48,7 @@ static const char *corrupt_item_sql = "UPDATE inet SET data=X'12345678' WHERE ro int secd_04_corrupted_items(int argc, char *const *argv) { - plan_tests(11 + kSecdTestSetupTestCount); + plan_tests(12 + kSecdTestSetupTestCount); /* custom keychain dir */ secd_test_setup_temp_keychain("secd_04_corrupted_items", NULL); @@ -105,6 +105,8 @@ int secd_04_corrupted_items(int argc, char *const *argv) is(sqlite3_exec(db, corrupt_item_sql, NULL, NULL, NULL), SQLITE_OK, "corrupting keychain items"); + is(sqlite3_close_v2(db), SQLITE_OK, + "Should be able to close db");; }); /* Try the update again */ @@ -137,5 +139,7 @@ int secd_04_corrupted_items(int argc, char *const *argv) CFReleaseNull(eighty_one); CFReleaseNull(eighty_two); + secd_test_teardown_delete_temp_keychain("secd_04_corrupted_items"); + return 0; } diff --git a/keychain/securityd/Regressions/secd-05-corrupted-items.m b/keychain/securityd/Regressions/secd-05-corrupted-items.m index 7e190934..ff984f67 100644 --- a/keychain/securityd/Regressions/secd-05-corrupted-items.m +++ b/keychain/securityd/Regressions/secd-05-corrupted-items.m @@ -99,7 +99,7 @@ static void *do_add(void *arg) int secd_05_corrupted_items(int argc, char *const *argv) { - plan_tests(1 + N_THREADS*(N_ADDS+1) + N_ITEMS*4 + kSecdTestSetupTestCount); + plan_tests(2 + N_THREADS*(N_ADDS+1) + N_ITEMS*4 + kSecdTestSetupTestCount); /* custom keychain dir */ secd_test_setup_temp_keychain("secd_05_corrupted_items", NULL); @@ -123,8 +123,7 @@ int secd_05_corrupted_items(int argc, char *const *argv) CFReleaseNull(port); } - - + SecKeychainDbForceClose(); SecKeychainDbReset(^{ /* corrupt all the password */ NSString *keychain_path = CFBridgingRelease(__SecKeychainCopyPath()); @@ -137,6 +136,9 @@ int secd_05_corrupted_items(int argc, char *const *argv) ok_unix(snprintf(corrupt_item_sql, sizeof(corrupt_item_sql), "UPDATE inet SET data=X'12345678' WHERE rowid=%d", i)); is(sqlite3_exec(db, corrupt_item_sql, NULL, NULL, NULL), SQLITE_OK, "corrupting keychain item"); } + + is(sqlite3_close_v2(db), SQLITE_OK, + "Should be able to close db");; }); /* start the adder threads */ @@ -166,5 +168,7 @@ int secd_05_corrupted_items(int argc, char *const *argv) CFReleaseNull(pwdata); CFReleaseNull(query); + + secd_test_teardown_delete_temp_keychain("secd_05_corrupted_items"); return 0; } diff --git a/keychain/securityd/Regressions/secd-100-initialsync.m b/keychain/securityd/Regressions/secd-100-initialsync.m index 64557741..5fb8c08d 100644 --- a/keychain/securityd/Regressions/secd-100-initialsync.m +++ b/keychain/securityd/Regressions/secd-100-initialsync.m @@ -51,6 +51,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void tests(void) { @@ -96,6 +97,8 @@ static void tests(void) ok(SOSAccountJoinCircles_wTxn(alice_account, &error), "Join circle: %@", error); ok(SOSAccountCheckHasBeenInSync_wTxn(alice_account), "Alice account initial sync done"); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); + ok(SOSAccountAssertUserCredentialsAndUpdate(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); CFReleaseNull(error); CFReleaseNull(cfpassword); @@ -105,7 +108,7 @@ static void tests(void) ok(SOSAccountJoinCircles_wTxn(bob_account, &error), "Bob Applies (%@)", error); CFReleaseNull(error); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 4, "updates"); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); { CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); @@ -148,14 +151,17 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_100_initialsync(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(33); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-130-other-peer-views.m b/keychain/securityd/Regressions/secd-130-other-peer-views.m index 8fe1cb2c..33b984c6 100644 --- a/keychain/securityd/Regressions/secd-130-other-peer-views.m +++ b/keychain/securityd/Regressions/secd-130-other-peer-views.m @@ -20,6 +20,7 @@ #include "SOSAccountTesting.h" #include "keychain/SecureObjectSync/SOSAccount.h" +#if SOS_ENABLED #define kAccountPasswordString ((uint8_t*) "FooFooFoo") #define kAccountPasswordStringLen 10 @@ -165,14 +166,18 @@ static void tests(void) { SOSTestCleanup(); } +#endif int secd_130_other_peer_views(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(72); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_clear_testviews(); tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-154-engine-backoff.m b/keychain/securityd/Regressions/secd-154-engine-backoff.m index e75660d4..78010ff5 100644 --- a/keychain/securityd/Regressions/secd-154-engine-backoff.m +++ b/keychain/securityd/Regressions/secd-154-engine-backoff.m @@ -28,6 +28,9 @@ #include "SOSTestDataSource.h" #include "SOSRegressionUtilities.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static int kTestTestCount = 10; static int MAX_PENALTY_TIME = 32; @@ -268,12 +271,15 @@ static void tests(void) ok(successful_writes == 12, "successfull writes should have only reached 10"); ok(monitor->penalty_box == 0, "penalty box should reset back to 0"); } +#endif int secd_154_engine_backoff(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-155-otr-negotiation-monitor.m b/keychain/securityd/Regressions/secd-155-otr-negotiation-monitor.m index 446afdce..17acd87c 100644 --- a/keychain/securityd/Regressions/secd-155-otr-negotiation-monitor.m +++ b/keychain/securityd/Regressions/secd-155-otr-negotiation-monitor.m @@ -38,6 +38,7 @@ #include "SOSTestDevice.h" #include "SOSTestDataSource.h" #include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" +#if SOS_ENABLED static void tests(void) @@ -144,6 +145,7 @@ static void tests(void) SOSTestDeviceAddGenericItem(device, CFSTR("Bob"), CFSTR("Bob-add")); } + SOSTestDeviceForceCloseDatabase(device); CFReleaseNull(device); } CFReleaseNull(deviceIDs); @@ -158,14 +160,17 @@ static void tests(void) // ids_test_sync(alice_account, bob_account); } +#endif int secd_155_otr_negotiation_monitor(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(44); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-156-timers.m b/keychain/securityd/Regressions/secd-156-timers.m index f63e2dd2..a0e979ae 100644 --- a/keychain/securityd/Regressions/secd-156-timers.m +++ b/keychain/securityd/Regressions/secd-156-timers.m @@ -95,6 +95,8 @@ int secd_156_timers(int argc, char *const *argv) secd_test_setup_temp_keychain(__FUNCTION__, NULL); tests(); + + secd_test_teardown_delete_temp_keychain(__FUNCTION__); return 0; } diff --git a/keychain/securityd/Regressions/secd-20-keychain_upgrade.m b/keychain/securityd/Regressions/secd-20-keychain_upgrade.m index 5bb2d5f2..c68a5354 100644 --- a/keychain/securityd/Regressions/secd-20-keychain_upgrade.m +++ b/keychain/securityd/Regressions/secd-20-keychain_upgrade.m @@ -105,6 +105,7 @@ keychain_upgrade(bool musr, const char *dbname) is(sqlite3_exec(db, "INSERT into ckmirror VALUES(\"ckzone\", \"importantuuid\", \"keyuuid\", 0, \"asdf\", \"qwer\", \"ckrecord\", 0, 0, NULL, NULL, NULL);", NULL, NULL, NULL), SQLITE_OK, "row added to ckmirror table"); is(sqlite3_close(db), SQLITE_OK, "close db"); + SecKeychainDbForceClose(); SecKeychainDbReset(^{ /* Create a new keychain sqlite db */ @@ -142,6 +143,8 @@ keychain_upgrade(bool musr, const char *dbname) if (musr) SecSecuritySetMusrMode(false, 501, -1); #endif + + secd_test_teardown_delete_temp_keychain(dbname); } int diff --git a/keychain/securityd/Regressions/secd-200-logstate.m b/keychain/securityd/Regressions/secd-200-logstate.m index 55d926f9..eeccb277 100644 --- a/keychain/securityd/Regressions/secd-200-logstate.m +++ b/keychain/securityd/Regressions/secd-200-logstate.m @@ -56,6 +56,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED #define HOW_MANY_MINIONS 4 @@ -223,14 +224,17 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_200_logstate(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(((HOW_MANY_MINIONS+1)*10 + 1)); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-201-coders.m b/keychain/securityd/Regressions/secd-201-coders.m index d851ca17..a20fb831 100644 --- a/keychain/securityd/Regressions/secd-201-coders.m +++ b/keychain/securityd/Regressions/secd-201-coders.m @@ -58,6 +58,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void tests(void) { @@ -143,7 +144,7 @@ static void tests(void) bob_account.factory = device->dsf; SOSTestDeviceAddGenericItem(device, CFSTR("Bob"), CFSTR("Bob-add")); } - + SOSTestDeviceForceCloseDatabase(device); CFReleaseNull(device); } CFReleaseNull(deviceIDs); @@ -164,14 +165,17 @@ static void tests(void) CFReleaseNull(changes); } +#endif int secd_201_coders(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(38); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-202-recoverykey.m b/keychain/securityd/Regressions/secd-202-recoverykey.m index e00d57af..f06af887 100644 --- a/keychain/securityd/Regressions/secd-202-recoverykey.m +++ b/keychain/securityd/Regressions/secd-202-recoverykey.m @@ -22,6 +22,9 @@ #import #import "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED const int kTestRecoveryKeyCount = 3; @@ -52,16 +55,18 @@ static void testRecoveryKeyBasic(void) } } +#endif int secd_202_recoverykey(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestRecoveryKeyCount + kTestRecoveryKeyBasicCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - testRecoveryKeyBasic(); - testRecoveryKey(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-21-transmogrify.m b/keychain/securityd/Regressions/secd-21-transmogrify.m index 26b900f9..a71933e1 100644 --- a/keychain/securityd/Regressions/secd-21-transmogrify.m +++ b/keychain/securityd/Regressions/secd-21-transmogrify.m @@ -195,6 +195,8 @@ secd_21_transmogrify(int argc, char *const *argv) CFReleaseNull(currentACL); CFRelease(musr); + + secd_test_teardown_delete_temp_keychain("secd_21_transmogrify"); #else plan_skip_all("not support on non TARGET_OS_IOS"); #endif diff --git a/keychain/securityd/Regressions/secd-210-keyinterest.m b/keychain/securityd/Regressions/secd-210-keyinterest.m index 82e7c890..13d14f80 100644 --- a/keychain/securityd/Regressions/secd-210-keyinterest.m +++ b/keychain/securityd/Regressions/secd-210-keyinterest.m @@ -15,8 +15,11 @@ #import "CKDSimulatedStore.h" #import "CKDSimulatedAccount.h" #import "CKDAKSLockMonitor.h" - #include "SOSCloudKeychainConstants.h" +#include "SOSAccountTesting.h" + + +#if SOS_ENABLED @interface CKDSimulatedLockMonitor : NSObject @@ -47,8 +50,7 @@ } - (instancetype) init { - self = [super init]; - if (self) { + if ((self = [super init])) { _locked = true; _unlockedSinceBoot = false; } @@ -189,12 +191,15 @@ static void tests(void) { } +#endif int secd_210_keyinterest(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(12); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-230-keybagtable.m b/keychain/securityd/Regressions/secd-230-keybagtable.m index 38107987..6d941370 100644 --- a/keychain/securityd/Regressions/secd-230-keybagtable.m +++ b/keychain/securityd/Regressions/secd-230-keybagtable.m @@ -137,6 +137,7 @@ static int keychainTestEnvironment(const char *environmentName, dispatch_block_t SecAccessGroupsSetCurrent(old_ag); CFReleaseSafe(test_ag); // Reset custom $HOME + secd_test_teardown_delete_temp_keychain(environmentName); SetCustomHomePath(NULL); SecKeychainDbReset(NULL); return 0; diff --git a/keychain/securityd/Regressions/secd-231-v0Peers.m b/keychain/securityd/Regressions/secd-231-v0Peers.m new file mode 100644 index 00000000..bdab5b57 --- /dev/null +++ b/keychain/securityd/Regressions/secd-231-v0Peers.m @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + + +#include +#include + +#include + +#include "keychain/SecureObjectSync/SOSAccount.h" +#include +#include "keychain/SecureObjectSync/SOSInternal.h" +#include "keychain/SecureObjectSync/SOSUserKeygen.h" +#include "keychain/SecureObjectSync/SOSTransport.h" +#include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include "keychain/securityd/SOSCloudCircleServer.h" + +#include "SOSAccountTesting.h" + +#include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + +static void tests(void) +{ + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + CFStringRef cfaccount = CFSTR("test@test.org"); + + CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + SOSAccount* alice_account = CreateAccountForLocalChanges( CFSTR("Alice"), CFSTR("TestSource")); + + is(ProcessChangesUntilNoChange(changes, alice_account, NULL), 1, "updates"); + + ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, NULL), 1, "updates"); + + // this is going to construct a V0 peer, and have alice plant it into the circle. + SecKeyRef correctUserKey = alice_account.accountPrivateKey; + SOSFullPeerInfoRef bobsV0FPI = SOSTestV0FullPeerInfo(CFSTR("Bob"), correctUserKey, CFSTR("12A365"), SOSPeerInfo_iOS); + SOSCircleRef aliceAccountCircle = alice_account.trust.trustedCircle; + SOSCircleRequestAdmission(aliceAccountCircle, correctUserKey, bobsV0FPI, &error); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, NULL), 1, "updates"); + + CFArrayRef peers = SOSAccountCopyViewUnawarePeers_wTxn(alice_account, &error); + ok(peers, "peers should not be nil"); + is(CFArrayGetCount(peers), 1, "count should be 1"); + if(CFArrayGetCount(peers) > 0) { + SOSPeerInfoRef bobPeer = (SOSPeerInfoRef)CFArrayGetValueAtIndex(peers, 0); + ok(CFStringCompare(SOSPeerInfoGetPeerID(bobPeer), SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(bobsV0FPI)), 0) == kCFCompareEqualTo, "PeerInfo's should be equal"); + + [alice_account removeV0Peers:^(bool removedV0Peer, NSError *error) { + is(removedV0Peer, true, "v0 peer should be removed"); + }]; + + is(ProcessChangesUntilNoChange(changes, alice_account, NULL), 1, "updates"); + } + + + is(SOSCircleCountPeers(alice_account.trust.trustedCircle), 1, "Bob should not be in the circle"); + + CFReleaseNull(changes); + CFReleaseNull(error); + CFReleaseNull(cfpassword); + CFReleaseNull(bobsV0FPI); + + alice_account = nil; + SOSTestCleanup(); +} +#endif + +int secd_231_v0Peers(int argc, char *const *argv) +{ +#if SOS_ENABLED + plan_tests(41); + secd_test_setup_temp_keychain(__FUNCTION__, NULL); + tests(); + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif + return 0; +} diff --git a/keychain/securityd/Regressions/secd-30-keychain-upgrade.m b/keychain/securityd/Regressions/secd-30-keychain-upgrade.m index fef6e75d..17fa2d48 100644 --- a/keychain/securityd/Regressions/secd-30-keychain-upgrade.m +++ b/keychain/securityd/Regressions/secd-30-keychain-upgrade.m @@ -86,7 +86,9 @@ static void tests(void) is(sqlite3_open(keychain_path, &db), SQLITE_OK, "create keychain"); is(sqlite3_exec(db, create_db_sql, NULL, NULL, NULL), SQLITE_OK, "populate keychain"); - + + is(sqlite3_close_v2(db), SQLITE_OK, + "Should be able to close db");; }); CFReleaseSafe(keychain_path_cf); @@ -116,13 +118,12 @@ static void tests(void) CFReleaseSafe(pwdata); CFReleaseSafe(query); - - + secd_test_teardown_delete_temp_keychain("secd_30_keychain_upgrade"); } int secd_30_keychain_upgrade(int argc, char *const *argv) { - plan_tests(6 + kSecdTestSetupTestCount); + plan_tests(7 + kSecdTestSetupTestCount); tests(); diff --git a/keychain/securityd/Regressions/secd-31-keychain-unreadable.m b/keychain/securityd/Regressions/secd-31-keychain-unreadable.m index d0f07f5e..818fea1c 100644 --- a/keychain/securityd/Regressions/secd-31-keychain-unreadable.m +++ b/keychain/securityd/Regressions/secd-31-keychain-unreadable.m @@ -113,6 +113,8 @@ int secd_31_keychain_unreadable(int argc, char *const *argv) CFReleaseNull(eighty); CFReleaseNull(pwdata); CFReleaseNull(query); + + secd_test_teardown_delete_temp_keychain("secd_31_keychain_unreadable"); #endif // !(TARGET_OS_IOS && TARGET_OS_SIMULATOR) return 0; } diff --git a/keychain/securityd/Regressions/secd-32-restore-bad-backup.m b/keychain/securityd/Regressions/secd-32-restore-bad-backup.m index 6e2f4754..91d92412 100644 --- a/keychain/securityd/Regressions/secd-32-restore-bad-backup.m +++ b/keychain/securityd/Regressions/secd-32-restore-bad-backup.m @@ -222,6 +222,8 @@ static void tests(void) diag("This still fails - don't be alarmed"); CFRelease(update); CFRelease(query); + + secd_test_teardown_delete_temp_keychain("secd_32_restore_bad_backup"); } int secd_32_restore_bad_backup(int argc, char *const *argv) diff --git a/keychain/securityd/Regressions/secd-33-keychain-backup.m b/keychain/securityd/Regressions/secd-33-keychain-backup.m index ead14bdd..7e661df6 100644 --- a/keychain/securityd/Regressions/secd-33-keychain-backup.m +++ b/keychain/securityd/Regressions/secd-33-keychain-backup.m @@ -629,6 +629,8 @@ int secd_33_keychain_backup(int argc, char *const *argv) tests(); + secd_test_teardown_delete_temp_keychain("secd_33_keychain_backup"); + SecAccessGroupsSetCurrent(currentACL); CFReleaseNull(currentACL); diff --git a/keychain/securityd/Regressions/secd-33-keychain-ctk.m b/keychain/securityd/Regressions/secd-33-keychain-ctk.m index 4aa765e0..f1c7f069 100644 --- a/keychain/securityd/Regressions/secd-33-keychain-ctk.m +++ b/keychain/securityd/Regressions/secd-33-keychain-ctk.m @@ -39,8 +39,11 @@ #include #include #include +#include #include +#include + #include #include @@ -216,7 +219,7 @@ static void test_item_query() { (id)kSecReturnPersistentRef : @YES }, &result)); is(phase, 0); NSData *persistentRef = (__bridge NSData *)result; - is(CFDataCompare((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), kCFCompareEqualTo); + is(CFEqual((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), TRUE); CFReleaseSafe(result); phase = 0; @@ -226,7 +229,7 @@ static void test_item_query() { (id)kSecReturnPersistentRef : @YES }, &result)); is(phase, 2); persistentRef = ((__bridge NSDictionary *)result)[(id)kSecValuePersistentRef]; - is(CFDataCompare((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), kCFCompareEqualTo); + is(CFEqual((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), TRUE); CFReleaseSafe(result); phase = 0; @@ -236,7 +239,7 @@ static void test_item_query() { (id)kSecReturnPersistentRef : @YES }, &result)); is(phase, 0); persistentRef = ((__bridge NSDictionary *)result)[(id)kSecValuePersistentRef]; - is(CFDataCompare((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), kCFCompareEqualTo); + is(CFEqual((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), TRUE); CFReleaseSafe(result); phase = 0; @@ -247,7 +250,7 @@ static void test_item_query() { (id)kSecReturnPersistentRef : @YES }, &result)); is(phase, 2); persistentRef = ((__bridge NSDictionary *)result)[(id)kSecValuePersistentRef]; - is(CFDataCompare((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), kCFCompareEqualTo); + is(CFEqual((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), TRUE); CFReleaseSafe(result); CFRelease(query); @@ -775,37 +778,44 @@ static CFMutableDictionaryRef copy_certificate_attributes(const char *base64Cert return result; } -static CFDictionaryRef copy_certificate_query(const char *base64cert, CFStringRef label, CFStringRef oid, CFStringRef tokenID) +static CFDictionaryRef copy_certificate_query(const char *base64cert, CFStringRef label, CFDataRef oid, CFStringRef tokenID) { CFMutableDictionaryRef certAttributes = copy_certificate_attributes(base64cert); CFDictionarySetValue(certAttributes, kSecAttrLabel, label); CFDictionarySetValue(certAttributes, kSecAttrAccessible, kSecAttrAccessibleAlwaysPrivate); - CFDictionarySetValue(certAttributes, kSecAttrTokenOID, oid); + if (oid != NULL) { + CFDictionarySetValue(certAttributes, kSecAttrTokenOID, oid); + } CFDictionaryRemoveValue(certAttributes, kSecValueData); - SecAccessControlRef acl = SecAccessControlCreate(kCFAllocatorDefault, NULL); - ok(acl); - CFTypeRef key[] = { kSecAttrTokenID }; - CFTypeRef value[] = { tokenID }; - CFDictionaryRef protection = CFDictionaryCreate(kCFAllocatorDefault, key, value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - ok(SecAccessControlSetProtection(acl, protection, NULL)); - CFRelease(protection); - ok(SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL)); - CFDataRef aclData = SecAccessControlCopyData(acl); - ok(aclData); - if (aclData) { - CFDictionarySetValue(certAttributes, kSecAttrAccessControl, aclData); - CFRelease(aclData); - } + if (tokenID != NULL) { + SecAccessControlRef acl = SecAccessControlCreate(kCFAllocatorDefault, NULL); + ok(acl); + CFTypeRef key[] = { kSecAttrTokenID }; + CFTypeRef value[] = { tokenID }; + CFDictionaryRef protection = CFDictionaryCreate(kCFAllocatorDefault, key, value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + ok(SecAccessControlSetProtection(acl, protection, NULL)); + CFRelease(protection); + ok(SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL)); + CFDataRef aclData = SecAccessControlCopyData(acl); + ok(aclData); + if (aclData) { + CFDictionarySetValue(certAttributes, kSecAttrAccessControl, aclData); + CFRelease(aclData); + } - if (acl) - CFRelease(acl); + if (acl) + CFRelease(acl); + } else { + NSData *certData = CFBridgingRelease(copy_certificate_data(base64cert)); + CFDictionarySetValue(certAttributes, kSecValueData, (__bridge CFDataRef)certData); + } return certAttributes; } -static CFDictionaryRef copy_key_query(CFDictionaryRef certAttributes, CFStringRef label, CFStringRef oid, CFStringRef tokenID) +static CFDictionaryRef copy_key_query(CFDictionaryRef certAttributes, CFStringRef label, CFDataRef oid, CFStringRef tokenID) { CFMutableDictionaryRef keyAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) ; @@ -859,20 +869,25 @@ static void check_array_for_type_id(CFArrayRef array, CFTypeID typeID) static void test_propagate_token_items() { - CFStringRef cert1OID = CFSTR("oid1"); - CFStringRef cert2OID = CFSTR("oid2"); - CFStringRef key1OID = CFSTR("oid3"); - CFStringRef key2OID = CFSTR("oid4"); + if (!os_feature_enabled(CryptoTokenKit, UseTokens)) { + // This test does not work if tokens cannot be used by keychain. + return; + } + + NSData *cert1OID = [@"oid1" dataUsingEncoding:NSUTF8StringEncoding]; + NSData *cert2OID = [@"oid2" dataUsingEncoding:NSUTF8StringEncoding]; + NSData *key1OID = [@"oid3" dataUsingEncoding:NSUTF8StringEncoding]; + NSData *key2OID = [@"oid4" dataUsingEncoding:NSUTF8StringEncoding]; TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) { blocks->copyObjectData = ^CFTypeRef(CFDataRef oid, CFErrorRef *error) { - if (CFEqual(oid, cert1OID)) { + if (CFEqual(oid, (__bridge CFDataRef)cert1OID)) { return copy_certificate_data(cert1); } - else if (CFEqual(oid, cert2OID)) { + else if (CFEqual(oid, (__bridge CFDataRef)cert2OID)) { return copy_certificate_data(cert2); } - else if (CFEqual(oid, key1OID) || CFEqual(oid, key2OID)) { + else if (CFEqual(oid, (__bridge CFDataRef)key1OID) || CFEqual(oid, (__bridge CFDataRef)key2OID)) { return kCFNull; } else { @@ -885,9 +900,9 @@ static void test_propagate_token_items() CFMutableArrayRef items = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFDictionaryRef certQuery = copy_certificate_query(cert1, CFSTR("test_cert1"), cert1OID, tokenID); + CFDictionaryRef certQuery = copy_certificate_query(cert1, CFSTR("test_cert1"), (__bridge CFDataRef)cert1OID, tokenID); ok(certQuery); - CFDictionaryRef keyQuery = copy_key_query(certQuery, CFSTR("test_key1"), key1OID, tokenID); + CFDictionaryRef keyQuery = copy_key_query(certQuery, CFSTR("test_key1"), (__bridge CFDataRef)key1OID, tokenID); ok(keyQuery); CFArrayAppendValue(items, certQuery); @@ -895,9 +910,9 @@ static void test_propagate_token_items() CFReleaseSafe(certQuery); CFReleaseSafe(keyQuery); - certQuery = copy_certificate_query(cert2, CFSTR("test_cert2"), cert2OID, tokenID); + certQuery = copy_certificate_query(cert2, CFSTR("test_cert2"), (__bridge CFDataRef)cert2OID, tokenID); ok(certQuery); - keyQuery = copy_key_query(certQuery, CFSTR("test_key2"), key2OID, tokenID); + keyQuery = copy_key_query(certQuery, CFSTR("test_key2"), (__bridge CFDataRef)key2OID, tokenID); ok(keyQuery); CFArrayAppendValue(items, certQuery); @@ -906,9 +921,9 @@ static void test_propagate_token_items() CFReleaseSafe(keyQuery); OSStatus result; - ok_status(result = SecItemUpdateTokenItems(tokenID, NULL), "Failed to delete items."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups(tokenID, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL), "Failed to delete items."); - ok_status(result = SecItemUpdateTokenItems(tokenID, items), "Failed to propagate items."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups(tokenID, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], items), "Failed to propagate items."); CFRelease(items); CFMutableDictionaryRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -957,7 +972,7 @@ static void test_propagate_token_items() ok(queryResult && CFGetTypeID(queryResult) == CFArrayGetTypeID() && CFArrayGetCount(queryResult) == 0, "Expect empty array"); CFReleaseNull(queryResult); - ok_status(result = SecItemUpdateTokenItems(tokenID, NULL), "Failed to delete items."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups(tokenID, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL), "Failed to delete items."); CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); CFDictionarySetValue(query, kSecReturnData, kCFBooleanFalse); @@ -967,17 +982,10 @@ static void test_propagate_token_items() } static void test_identity_on_two_tokens() { - CFStringRef cert3OID = CFSTR("oid1"); - TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) { - - blocks->copyObjectData = ^CFTypeRef(CFDataRef oid, CFErrorRef *error) { - if (CFEqual(oid, cert3OID)) - return copy_certificate_data(cert3); - else - return kCFNull; - }; - - }); + if (!os_feature_enabled(CryptoTokenKit, UseTokens)) { + // This test does not work if tokens cannot be used by keychains. + return; + } @autoreleasepool { NSString *tokenID1 = @"com.apple.secdtest:identity_test_token1"; @@ -989,6 +997,25 @@ static void test_identity_on_two_tokens() { id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)privKey)); NSData *pubKeyHash = CFBridgingRelease(SecKeyCopyPublicKeyHash((__bridge SecKeyRef)publicKey)); + NSData *cert3OID = [@"oid1" dataUsingEncoding:NSUTF8StringEncoding]; + TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) { + + blocks->copyObjectData = ^CFTypeRef(CFDataRef oid, CFErrorRef *error) { + if (CFEqual(oid, (__bridge CFDataRef)cert3OID)) + return copy_certificate_data(cert3); + else + return kCFNull; + }; + + blocks->copyPublicKeyData = ^CFDataRef(CFDataRef oid, CFErrorRef *error) { + if ([privKeyData isEqualToData:(__bridge NSData *)oid]) { + return SecKeyCopyExternalRepresentation((SecKeyRef)publicKey, error); + } + return NULL; + }; + + }); + id ac = CFBridgingRelease(SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlocked, 0, NULL)); id acData = CFBridgingRelease(SecAccessControlCopyData((__bridge SecAccessControlRef)ac)); NSDictionary *keyQuery = @{ (id)kSecClass: (id)kSecClassKey, @@ -1002,15 +1029,15 @@ static void test_identity_on_two_tokens() { (id)kSecAttrApplicationLabel : pubKeyHash, }; OSStatus result; - ok_status(result = SecItemUpdateTokenItems((__bridge CFStringRef)tokenID1, (__bridge CFArrayRef)@[keyQuery]), "Failed to propagate key item."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups((__bridge CFStringRef)tokenID1, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], (__bridge CFArrayRef)@[keyQuery]), "Failed to propagate key item."); id privateKey; ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)@{(id)kSecClass: (id)kSecClassKey, (id)kSecAttrTokenID: tokenID1, (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, (id)kSecReturnRef: @YES}, (void *)&privateKey)); - NSDictionary *certQuery = CFBridgingRelease(copy_certificate_query(cert3, CFSTR("test_cert3"), cert3OID, (__bridge CFStringRef)tokenID2)); + NSDictionary *certQuery = CFBridgingRelease(copy_certificate_query(cert3, CFSTR("test_cert3"), (__bridge CFDataRef)cert3OID, (__bridge CFStringRef)tokenID2)); ok(certQuery); - ok_status(result = SecItemUpdateTokenItems((__bridge CFStringRef)tokenID2, (__bridge CFArrayRef)@[certQuery]), "Failed to propagate cert item."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups((__bridge CFStringRef)tokenID2, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], (__bridge CFArrayRef)@[certQuery]), "Failed to propagate cert item."); CFTypeRef resultRef; NSDictionary *query = @{ (id)kSecClass : (id)kSecClassKey, (id)kSecAttrApplicationLabel : pubKeyHash, (id)kSecReturnRef : @YES, (id)kSecReturnAttributes : @YES, (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken }; @@ -1024,6 +1051,97 @@ static void test_identity_on_two_tokens() { query = @{ (id)kSecClass : (id)kSecClassIdentity, (id)kSecAttrApplicationLabel : pubKeyHash, (id)kSecReturnRef : @YES, (id)kSecReturnAttributes : @YES, (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken }; ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&resultRef)); CFReleaseNull(resultRef); + + NSData *persRef, *persRef2; + id newRef; + + // Query persistent reference for key and verify that we can get key back using it. + query = @{ (id)kSecValueRef: privateKey, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef)); + query = @{ (id)kSecClass: (id)kSecClassKey, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef2)); + eq_cf((__bridge CFTypeRef)persRef, (__bridge CFTypeRef)persRef2); + query = @{ (id)kSecValuePersistentRef: persRef, (id)kSecReturnRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&newRef)); + eq_cf((__bridge CFTypeRef)privateKey, (__bridge CFTypeRef)newRef); + + // Query persistent reference for certificate and verify that we can get certificate back using it. + id certRef; + query = @{ (id)kSecClass: (id)kSecClassCertificate, (id)kSecAttrPublicKeyHash: pubKeyHash, (id)kSecReturnRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&certRef)); + + persRef = nil; + persRef2 = nil; + newRef = nil; + query = @{ (id)kSecValueRef: certRef, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef)); + query = @{ (id)kSecClass: (id)kSecClassCertificate, (id)kSecAttrPublicKeyHash: pubKeyHash, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef2)); + eq_cf((__bridge CFTypeRef)persRef, (__bridge CFTypeRef)persRef2); + query = @{ (id)kSecValuePersistentRef: persRef, (id)kSecReturnRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&newRef)); + eq_cf((__bridge CFTypeRef)certRef, (__bridge CFTypeRef)newRef); + + // Query persistent reference for identity and verify that we can get identity back using it. + id identityRef; + NSDictionary *attrs; + query = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnRef: @YES, (id)kSecReturnAttributes: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&attrs)); + identityRef = attrs[(id)kSecValueRef]; + eq_cf((__bridge CFTypeRef)attrs[(id)kSecAttrTokenID], (__bridge CFTypeRef)tokenID1); + + persRef = nil; + persRef2 = nil; + attrs = nil; + query = @{ (id)kSecValueRef: identityRef, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef)); + query = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef2)); + eq_cf((__bridge CFTypeRef)persRef, (__bridge CFTypeRef)persRef2); + query = @{ (id)kSecValuePersistentRef: persRef2, (id)kSecReturnRef: @YES, (id)kSecReturnAttributes: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&attrs)); + eq_cf((__bridge CFTypeRef)identityRef, (__bridge CFTypeRef)attrs[(id)kSecValueRef]); + eq_cf((__bridge CFTypeRef)attrs[(id)kSecAttrTokenID], (__bridge CFTypeRef)tokenID1); + + // Remove certificate from token and add it as regular keychain item (non-token) one. Following tests + // repeat identity test for key-on-token, certificate-non-token hybrid identities. + ok_status(result = SecItemUpdateTokenItemsForAccessGroups((__bridge CFStringRef)tokenID2, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL)); + certQuery = CFBridgingRelease(copy_certificate_query(cert3, CFSTR("reg_cert3"), NULL, NULL)); + ok_status(result = SecItemAdd((__bridge CFDictionaryRef)certQuery, NULL)); + + query = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&identityRef)); + isnt(identityRef, NULL); + + persRef = nil; + persRef2 = nil; + attrs = nil; + query = @{ (id)kSecValueRef: identityRef, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef)); + query = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef2)); + eq_cf((__bridge CFTypeRef)persRef, (__bridge CFTypeRef)persRef2); + query = @{ (id)kSecValuePersistentRef: persRef, (id)kSecReturnRef: @YES, (id)kSecReturnAttributes: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&attrs)); + eq_cf((__bridge CFTypeRef)identityRef, (__bridge CFTypeRef)attrs[(id)kSecValueRef]); + eq_cf((__bridge CFTypeRef)attrs[(id)kSecAttrTokenID], (__bridge CFTypeRef)tokenID1); + + // After removing token with key, getting identity from persistent reference must fail gracefully. + ok_status(result = SecItemUpdateTokenItemsForAccessGroups((__bridge CFStringRef)tokenID1, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL)); + query = @{ (id)kSecValuePersistentRef: persRef, (id)kSecReturnRef: @YES }; + is_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&newRef), errSecItemNotFound); + + // Getting persistent reference to non-token item with token-like (but malformed) data must not crash. + NSData *data = CFBridgingRelease(CFPropertyListCreateDERData(kCFAllocatorDefault, (__bridge CFPropertyListRef)@[], NULL)); + query = @{ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"probe", (id)kSecValueData: data}; + ok_status(result = SecItemAdd((__bridge CFDictionaryRef)query, NULL)); + NSDictionary *dict; + query = @{ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"probe", (id)kSecReturnPersistentRef: @YES, (id)kSecReturnData: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&dict)); + NSData *newData; + query = @{ (id)kSecValuePersistentRef: dict[(id)kSecValuePersistentRef], (id)kSecReturnData: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&newData)); + eq_cf((__bridge CFTypeRef)data, (__bridge CFTypeRef)newData); } } @@ -1093,7 +1211,7 @@ static void test_ies(SecKeyRef privateKey, SecKeyAlgorithm algorithm) { NSDictionary *params = @{ (id)kSecAttrKeyType : privateParams[(id)kSecAttrKeyType], (id)kSecAttrKeySizeInBits : privateParams[(id)kSecAttrKeySizeInBits], (id)kSecAttrTokenID : @"tid-ies", - (id)kSecPrivateKeyAttrs : @{ (id)kSecAttrIsPermanent : @YES } + (id)kSecPrivateKeyAttrs : @{ (id)kSecAttrIsPermanent : @NO } }; NSError *error; SecKeyRef tokenKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)params, (void *)&error); @@ -1162,10 +1280,17 @@ static void tests(void) { test_identity_on_two_tokens(); test_rsawrap(); test_ecies(); + + secd_test_teardown_delete_temp_keychain("secd_33_keychain_ctk"); } int secd_33_keychain_ctk(int argc, char *const *argv) { - plan_tests(491); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + plan_tests(539); + } else { + plan_tests(403); + } + tests(); return 0; diff --git a/keychain/securityd/Regressions/secd-34-backup-der-parse.m b/keychain/securityd/Regressions/secd-34-backup-der-parse.m index 352b832d..9b0d6722 100644 --- a/keychain/securityd/Regressions/secd-34-backup-der-parse.m +++ b/keychain/securityd/Regressions/secd-34-backup-der-parse.m @@ -427,7 +427,7 @@ static void secd_perform_with_data_in_file(const char* test_prefix, void(^with)( }); /* set custom keychain dir, reset db */ - SetCustomHomeURLString(tmp_dir); + SecSetCustomHomeURLString(tmp_dir); if(do_before_reset) do_before_reset(); @@ -495,6 +495,8 @@ static void tests(void) diag("This still fails - don't be alarmed"); CFRelease(update); CFRelease(query); + + secd_test_teardown_delete_temp_keychain("secd_34_backup_der_parse"); #endif } diff --git a/keychain/securityd/Regressions/secd-35-keychain-migrate-inet.m b/keychain/securityd/Regressions/secd-35-keychain-migrate-inet.m index 71c789f8..8b260974 100644 --- a/keychain/securityd/Regressions/secd-35-keychain-migrate-inet.m +++ b/keychain/securityd/Regressions/secd-35-keychain-migrate-inet.m @@ -126,6 +126,8 @@ int secd_35_keychain_migrate_inet(int argc, char *const *argv) CFReleaseSafe(results); CFReleaseSafe(query); + + secd_test_teardown_delete_temp_keychain("secd_35_keychain_migrate_inet"); return 0; } diff --git a/keychain/securityd/Regressions/secd-36-ks-encrypt.m b/keychain/securityd/Regressions/secd-36-ks-encrypt.m index ff85cb8f..05c06c3e 100644 --- a/keychain/securityd/Regressions/secd-36-ks-encrypt.m +++ b/keychain/securityd/Regressions/secd-36-ks-encrypt.m @@ -24,6 +24,7 @@ #include "secd_regressions.h" +#import #include #include @@ -66,7 +67,8 @@ int secd_36_ks_encrypt(int argc, char *const *argv) ok(ac = SecAccessControlCreate(NULL, &error), "SecAccessControlCreate: %@", error); ok(SecAccessControlSetProtection(ac, kSecAttrAccessibleWhenUnlocked, &error), "SecAccessControlSetProtection: %@", error); - ret = ks_encrypt_data(keybag, ac, NULL, data, (__bridge CFDictionaryRef)@{@"persistref" : @"aaa-bbb-ccc"}, NULL, &enc, true, &error); + CFDictionaryRef empty = (__bridge CFDictionaryRef)@{}; + ret = ks_encrypt_data(keybag, ac, NULL, data, (__bridge CFDictionaryRef)@{@"persistref" : @"aaa-bbb-ccc"}, empty, &enc, true, &error); is(true, ret); CFReleaseNull(ac); @@ -75,7 +77,11 @@ int secd_36_ks_encrypt(int argc, char *const *argv) CFMutableDictionaryRef attributes = NULL; uint32_t version = 0; - ret = ks_decrypt_data(keybag, kAKSKeyOpDecrypt, &ac, NULL, enc, NULL, NULL, &attributes, &version, true, NULL, &error); + NSData* dummyACM = [NSData dataWithBytes:"dummy" length:5]; + const SecDbClass* class = kc_class_with_name(kSecClassGenericPassword); + NSArray* dummyArray = [NSArray array]; + + ret = ks_decrypt_data(keybag, kAKSKeyOpDecrypt, &ac, (__bridge CFDataRef _Nonnull)dummyACM, enc, class, (__bridge CFArrayRef)dummyArray, &attributes, &version, true, NULL, &error); is(true, ret, "ks_decrypt_data: %@", error); CFTypeRef aclProtection = ac ? SecAccessControlGetProtection(ac) : NULL; @@ -87,6 +93,8 @@ int secd_36_ks_encrypt(int argc, char *const *argv) CFReleaseNull(error); CFReleaseNull(enc); + secd_test_teardown_delete_temp_keychain("secd_36_ks_encrypt"); + return 0; } diff --git a/keychain/securityd/Regressions/secd-37-pairing-initial-sync.m b/keychain/securityd/Regressions/secd-37-pairing-initial-sync.m index 1e2d001d..8196be75 100644 --- a/keychain/securityd/Regressions/secd-37-pairing-initial-sync.m +++ b/keychain/securityd/Regressions/secd-37-pairing-initial-sync.m @@ -153,6 +153,7 @@ int secd_37_pairing_initial_sync(int argc, char *const *argv) SecAccessGroupsSetCurrent(currentACL); CFReleaseNull(currentACL); + secd_test_teardown_delete_temp_keychain("secd_37_pairing_initial_sync"); return 0; } diff --git a/keychain/securityd/Regressions/secd-50-account.m b/keychain/securityd/Regressions/secd-50-account.m index 70ff2f44..2ffd4c0e 100644 --- a/keychain/securityd/Regressions/secd-50-account.m +++ b/keychain/securityd/Regressions/secd-50-account.m @@ -45,6 +45,8 @@ #include "SecdTestKeychainUtilities.h" #include "SOSAccountTesting.h" +#if SOS_ENABLED + static int kTestTestCount = 9 + kSecdTestSetupTestCount; static void tests(void) { @@ -96,6 +98,15 @@ static void tests(void) is([account getCircleStatus:&cfError], kSOSCCInCircle, "Still in Circle (%@)", error); CFReleaseNull(cfError); + SecKeyRef userKey = SOSAccountCopyStashedUserPrivateKey(account, &cfError); + ok(userKey, "retrieved userKey"); + CFReleaseNull(userKey); + + SecKeyRef deviceKey = SOSAccountCopyDevicePrivateKey(account, &cfError); + ok(deviceKey, "retrieved deviceKey"); + CFReleaseNull(deviceKey); + + CFReleaseNull(new_gestalt); SOSDataSourceFactoryRelease(test_factory); @@ -107,13 +118,17 @@ static void tests(void) SOSTestCleanup(); } +#endif + int secd_50_account(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-50-message.m b/keychain/securityd/Regressions/secd-50-message.m index 67f198c1..826b302d 100644 --- a/keychain/securityd/Regressions/secd-50-message.m +++ b/keychain/securityd/Regressions/secd-50-message.m @@ -31,6 +31,9 @@ #include #include "keychain/SecureObjectSync/SOSDigestVector.h" #include "keychain/securityd/SecDbItem.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static void testNullMessage(uint64_t msgid) { @@ -241,12 +244,15 @@ static void tests(void) testFlaggedMessage(test_directive, test_reason, ++msgid, 0x865); testFlaggedMessage(test_directive, test_reason, ++msgid, 0xdeadbeef); } +#endif int secd_50_message(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(26); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-51-account-inflate.m b/keychain/securityd/Regressions/secd-51-account-inflate.m index 08ee55e8..d795fb28 100644 --- a/keychain/securityd/Regressions/secd-51-account-inflate.m +++ b/keychain/securityd/Regressions/secd-51-account-inflate.m @@ -46,158 +46,7 @@ #include "SOSAccountTesting.h" #include "SOSTransportTestTransports.h" -#if 0 -const uint8_t v6_der[] = { - 0x30, 0x82, 0x06, 0xee, 0x02, 0x01, 0x06, 0x31, 0x4e, 0x30, 0x11, 0x0c, - 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x04, - 0x69, 0x50, 0x61, 0x64, 0x30, 0x1b, 0x0c, 0x16, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x0c, - 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, - 0x65, 0x0c, 0x0c, 0x4d, 0x69, 0x74, 0x63, 0x68, 0x27, 0x73, 0x20, 0x69, - 0x50, 0x61, 0x64, 0x30, 0x82, 0x05, 0xe0, 0x30, 0x82, 0x05, 0xdc, 0x04, - 0x82, 0x04, 0x1c, 0x30, 0x82, 0x04, 0x18, 0x02, 0x01, 0x01, 0x0c, 0x02, - 0x61, 0x6b, 0x02, 0x08, 0x0d, 0x4f, 0xc4, 0x65, 0x00, 0x00, 0x00, 0x03, - 0x30, 0x82, 0x03, 0x2c, 0x30, 0x82, 0x01, 0xa2, 0x31, 0x82, 0x01, 0x56, - 0x30, 0x14, 0x0c, 0x0f, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, 0x00, 0x30, 0x2b, - 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x44, 0x61, 0x74, 0x65, 0x04, 0x18, 0x18, 0x16, 0x32, 0x30, 0x31, - 0x35, 0x30, 0x32, 0x32, 0x36, 0x31, 0x37, 0x30, 0x30, 0x35, 0x39, 0x2e, - 0x39, 0x31, 0x35, 0x33, 0x35, 0x38, 0x5a, 0x30, 0x55, 0x0c, 0x10, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, - 0x4b, 0x65, 0x79, 0x04, 0x41, 0x04, 0xd9, 0x02, 0x0e, 0x16, 0x03, 0x13, - 0xfb, 0xf8, 0x29, 0xbf, 0x83, 0xbd, 0x6b, 0x5a, 0xc4, 0xf0, 0x47, 0x52, - 0xc7, 0x87, 0x81, 0xe9, 0xda, 0xe0, 0xb4, 0x8b, 0x06, 0x73, 0x23, 0x72, - 0xba, 0xba, 0xc4, 0x1a, 0x35, 0xa2, 0xc6, 0x46, 0x61, 0xc9, 0x08, 0x43, - 0x4f, 0x89, 0x08, 0x9d, 0xe1, 0xd5, 0x3d, 0x83, 0x49, 0xe3, 0x0c, 0x8e, - 0xfb, 0x33, 0x37, 0xd7, 0x6d, 0x03, 0xe0, 0x39, 0x11, 0xe1, 0x30, 0x59, - 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x55, 0x73, 0x69, 0x67, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x66, - 0x9e, 0xd0, 0x80, 0x11, 0xa4, 0x17, 0x94, 0x66, 0x5f, 0x75, 0xee, 0x65, - 0xbf, 0xd0, 0x49, 0x8f, 0xe6, 0x22, 0xf6, 0x3c, 0x2c, 0xdb, 0x46, 0xe5, - 0x3f, 0x4f, 0x85, 0xb9, 0x8a, 0x6c, 0x8a, 0x02, 0x20, 0x0a, 0x37, 0xf0, - 0xf1, 0x9f, 0x13, 0xfd, 0xae, 0x5f, 0xb7, 0xd0, 0xb4, 0x4a, 0x45, 0x02, - 0x8a, 0x2f, 0xdc, 0x8b, 0xd3, 0xfb, 0x09, 0xeb, 0xcf, 0x6b, 0x0b, 0x6b, - 0x18, 0x9c, 0xcf, 0x6c, 0x55, 0x30, 0x5f, 0x0c, 0x0d, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x47, 0x65, 0x73, 0x74, 0x61, 0x6c, 0x74, 0x31, 0x4e, - 0x30, 0x11, 0x0c, 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x61, 0x6d, - 0x65, 0x0c, 0x04, 0x69, 0x50, 0x61, 0x64, 0x30, 0x1b, 0x0c, 0x16, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, 0x00, - 0x30, 0x1c, 0x0c, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x0c, 0x4d, 0x69, 0x74, 0x63, 0x68, 0x27, - 0x73, 0x20, 0x69, 0x50, 0x61, 0x64, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, - 0x72, 0x06, 0xdb, 0xf8, 0x06, 0xff, 0x7f, 0xac, 0xcf, 0xd2, 0xfb, 0x1e, - 0x86, 0x0d, 0x87, 0x4e, 0xb9, 0x1b, 0x26, 0x1e, 0x47, 0x4b, 0xfe, 0xd0, - 0x54, 0x0c, 0xdf, 0x88, 0x5a, 0x27, 0x92, 0x1d, 0x02, 0x20, 0x6b, 0xcf, - 0x7f, 0xb5, 0xfe, 0x19, 0x16, 0xd2, 0x7f, 0xb1, 0x7b, 0xad, 0xf5, 0xb9, - 0xea, 0x23, 0x69, 0x37, 0x19, 0x5e, 0xd3, 0x8c, 0x9e, 0x80, 0xef, 0xb5, - 0x65, 0x9a, 0xd5, 0x42, 0x51, 0x13, 0x30, 0x82, 0x01, 0x82, 0x31, 0x82, - 0x01, 0x35, 0x30, 0x12, 0x0c, 0x0d, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x01, 0x01, 0x01, 0x30, 0x14, - 0x0c, 0x0f, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, 0x00, 0x30, 0x29, 0x0c, 0x0d, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x73, 0x74, 0x61, 0x6c, - 0x74, 0x31, 0x18, 0x30, 0x16, 0x0c, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x06, 0x69, 0x43, 0x6c, - 0x6f, 0x75, 0x64, 0x30, 0x2b, 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x65, 0x04, 0x18, - 0x18, 0x16, 0x32, 0x30, 0x31, 0x35, 0x30, 0x32, 0x32, 0x36, 0x31, 0x37, - 0x30, 0x30, 0x35, 0x39, 0x2e, 0x39, 0x36, 0x30, 0x38, 0x33, 0x35, 0x5a, - 0x30, 0x55, 0x0c, 0x10, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x69, - 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x04, 0x41, 0x04, 0x53, - 0x1d, 0x77, 0x7c, 0x1b, 0x8a, 0x53, 0xad, 0x88, 0xdf, 0x56, 0xf9, 0x11, - 0xfd, 0x40, 0x69, 0x7c, 0x0b, 0xbb, 0x2a, 0xf7, 0x48, 0x7e, 0x69, 0x3d, - 0x0c, 0xfb, 0xc8, 0x90, 0x27, 0xb5, 0x18, 0x88, 0x09, 0x3f, 0x06, 0x37, - 0xca, 0x5d, 0x9c, 0x64, 0x34, 0x13, 0x89, 0x09, 0xe9, 0x0e, 0x99, 0xa3, - 0xc8, 0xc1, 0x86, 0xb3, 0x6e, 0x30, 0xf1, 0x20, 0x38, 0x78, 0x56, 0x40, - 0xf4, 0xd7, 0x36, 0x30, 0x5a, 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x69, 0x67, 0x04, 0x47, - 0x30, 0x45, 0x02, 0x20, 0x45, 0x47, 0xbf, 0x5b, 0x4d, 0x57, 0x77, 0x90, - 0x7b, 0x74, 0x90, 0x2f, 0x5d, 0x7b, 0x02, 0x3c, 0x21, 0xe8, 0x5c, 0x24, - 0x0c, 0x77, 0xd8, 0x19, 0xff, 0xce, 0x28, 0x45, 0x76, 0x50, 0xb1, 0xee, - 0x02, 0x21, 0x00, 0xe3, 0xea, 0x0f, 0xcb, 0x72, 0xd7, 0x88, 0x15, 0xa4, - 0x71, 0xbe, 0x9e, 0xa6, 0xf2, 0x9c, 0xa8, 0x9b, 0x93, 0xec, 0x31, 0x7a, - 0xe3, 0x92, 0x8a, 0xf2, 0x2f, 0xfd, 0x98, 0xc9, 0xe1, 0xc4, 0x7c, 0x04, - 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xce, 0x5f, 0x67, 0x9d, 0x78, 0x9f, - 0xc6, 0x3b, 0xb3, 0x51, 0xde, 0x6d, 0x9e, 0xff, 0xf5, 0xab, 0xda, 0xf4, - 0x7e, 0xb2, 0xe9, 0x1a, 0xf2, 0xd9, 0x0d, 0x48, 0x30, 0x07, 0xbc, 0x06, - 0xf5, 0x42, 0x02, 0x20, 0x64, 0x1d, 0x7d, 0x43, 0xc1, 0x3b, 0x50, 0xd6, - 0x7b, 0x3b, 0xce, 0x6f, 0xec, 0x23, 0x21, 0x8a, 0x9b, 0x06, 0x3f, 0x64, - 0xfe, 0xd6, 0x29, 0xaf, 0x5b, 0x0c, 0x69, 0x8f, 0x48, 0x88, 0x08, 0x1e, - 0x30, 0x00, 0x30, 0x00, 0x31, 0x81, 0xd0, 0x30, 0x66, 0x0c, 0x1a, 0x30, - 0x56, 0x4f, 0x73, 0x47, 0x76, 0x56, 0x72, 0x51, 0x46, 0x4e, 0x46, 0x6b, - 0x52, 0x35, 0x37, 0x71, 0x59, 0x73, 0x4c, 0x47, 0x6f, 0x33, 0x49, 0x50, - 0x51, 0x04, 0x48, 0x30, 0x46, 0x02, 0x21, 0x00, 0xf9, 0xc9, 0x69, 0xda, - 0x69, 0xe7, 0x32, 0xeb, 0x14, 0xc1, 0xbd, 0x56, 0xb7, 0x3e, 0xab, 0x08, - 0x6d, 0xe2, 0x16, 0xd9, 0x0a, 0xa8, 0x67, 0x7a, 0x56, 0xdc, 0x64, 0xf2, - 0x2f, 0x2e, 0xe8, 0xb9, 0x02, 0x21, 0x00, 0xac, 0x5c, 0x29, 0x80, 0x60, - 0x57, 0xd7, 0x51, 0x23, 0x1f, 0x00, 0x09, 0x70, 0xf3, 0xd5, 0x1a, 0x49, - 0xad, 0xaf, 0x35, 0x77, 0x07, 0xf4, 0x85, 0x1f, 0x63, 0xe0, 0xea, 0x67, - 0x36, 0xb5, 0x3b, 0x30, 0x66, 0x0c, 0x1a, 0x6e, 0x6b, 0x62, 0x77, 0x33, - 0x2f, 0x57, 0x72, 0x39, 0x4f, 0x33, 0x6a, 0x45, 0x68, 0x4f, 0x48, 0x46, - 0x67, 0x32, 0x34, 0x67, 0x62, 0x4d, 0x61, 0x6a, 0x76, 0x04, 0x48, 0x30, - 0x46, 0x02, 0x21, 0x00, 0x9f, 0x4f, 0x60, 0x2f, 0x54, 0x5e, 0x9f, 0x6a, - 0x7d, 0x37, 0xd9, 0x9f, 0x62, 0x69, 0xd7, 0x8c, 0xfc, 0xf5, 0x78, 0x54, - 0x7d, 0xb6, 0x91, 0x4b, 0x48, 0x88, 0x3d, 0x59, 0x05, 0x70, 0x09, 0xbf, - 0x02, 0x21, 0x00, 0xe2, 0xaf, 0xc9, 0x27, 0x12, 0xfa, 0x64, 0x51, 0x19, - 0x13, 0x1d, 0x57, 0x56, 0x6b, 0x93, 0xa3, 0xc6, 0x31, 0xf8, 0x70, 0x97, - 0x9e, 0x79, 0xf5, 0xc0, 0x2d, 0xf3, 0x3c, 0x8b, 0x86, 0x92, 0x28, 0x04, - 0x82, 0x01, 0xb8, 0x30, 0x82, 0x01, 0xb4, 0x30, 0x82, 0x01, 0xa2, 0x31, - 0x82, 0x01, 0x56, 0x30, 0x14, 0x0c, 0x0f, 0x43, 0x6f, 0x6e, 0x66, 0x6c, - 0x69, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, - 0x00, 0x30, 0x2b, 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x65, 0x04, 0x18, 0x18, 0x16, - 0x32, 0x30, 0x31, 0x35, 0x30, 0x32, 0x32, 0x36, 0x31, 0x37, 0x30, 0x30, - 0x35, 0x39, 0x2e, 0x39, 0x31, 0x35, 0x33, 0x35, 0x38, 0x5a, 0x30, 0x55, - 0x0c, 0x10, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x69, 0x67, 0x6e, - 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x04, 0x41, 0x04, 0xd9, 0x02, 0x0e, - 0x16, 0x03, 0x13, 0xfb, 0xf8, 0x29, 0xbf, 0x83, 0xbd, 0x6b, 0x5a, 0xc4, - 0xf0, 0x47, 0x52, 0xc7, 0x87, 0x81, 0xe9, 0xda, 0xe0, 0xb4, 0x8b, 0x06, - 0x73, 0x23, 0x72, 0xba, 0xba, 0xc4, 0x1a, 0x35, 0xa2, 0xc6, 0x46, 0x61, - 0xc9, 0x08, 0x43, 0x4f, 0x89, 0x08, 0x9d, 0xe1, 0xd5, 0x3d, 0x83, 0x49, - 0xe3, 0x0c, 0x8e, 0xfb, 0x33, 0x37, 0xd7, 0x6d, 0x03, 0xe0, 0x39, 0x11, - 0xe1, 0x30, 0x59, 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x69, 0x67, 0x04, 0x46, 0x30, 0x44, - 0x02, 0x20, 0x66, 0x9e, 0xd0, 0x80, 0x11, 0xa4, 0x17, 0x94, 0x66, 0x5f, - 0x75, 0xee, 0x65, 0xbf, 0xd0, 0x49, 0x8f, 0xe6, 0x22, 0xf6, 0x3c, 0x2c, - 0xdb, 0x46, 0xe5, 0x3f, 0x4f, 0x85, 0xb9, 0x8a, 0x6c, 0x8a, 0x02, 0x20, - 0x0a, 0x37, 0xf0, 0xf1, 0x9f, 0x13, 0xfd, 0xae, 0x5f, 0xb7, 0xd0, 0xb4, - 0x4a, 0x45, 0x02, 0x8a, 0x2f, 0xdc, 0x8b, 0xd3, 0xfb, 0x09, 0xeb, 0xcf, - 0x6b, 0x0b, 0x6b, 0x18, 0x9c, 0xcf, 0x6c, 0x55, 0x30, 0x5f, 0x0c, 0x0d, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x73, 0x74, 0x61, 0x6c, - 0x74, 0x31, 0x4e, 0x30, 0x11, 0x0c, 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, - 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x04, 0x69, 0x50, 0x61, 0x64, 0x30, 0x1b, - 0x0c, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x02, 0x01, 0x00, 0x30, 0x1c, 0x0c, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x0c, 0x4d, 0x69, 0x74, - 0x63, 0x68, 0x27, 0x73, 0x20, 0x69, 0x50, 0x61, 0x64, 0x04, 0x46, 0x30, - 0x44, 0x02, 0x20, 0x72, 0x06, 0xdb, 0xf8, 0x06, 0xff, 0x7f, 0xac, 0xcf, - 0xd2, 0xfb, 0x1e, 0x86, 0x0d, 0x87, 0x4e, 0xb9, 0x1b, 0x26, 0x1e, 0x47, - 0x4b, 0xfe, 0xd0, 0x54, 0x0c, 0xdf, 0x88, 0x5a, 0x27, 0x92, 0x1d, 0x02, - 0x20, 0x6b, 0xcf, 0x7f, 0xb5, 0xfe, 0x19, 0x16, 0xd2, 0x7f, 0xb1, 0x7b, - 0xad, 0xf5, 0xb9, 0xea, 0x23, 0x69, 0x37, 0x19, 0x5e, 0xd3, 0x8c, 0x9e, - 0x80, 0xef, 0xb5, 0x65, 0x9a, 0xd5, 0x42, 0x51, 0x13, 0x04, 0x0c, 0x6b, - 0x65, 0x79, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x41, 0x04, 0x78, 0xea, 0x03, 0x41, - 0x94, 0x6d, 0x46, 0x38, 0xde, 0x37, 0xe0, 0xb6, 0xc8, 0xfa, 0x94, 0x86, - 0xbe, 0xd5, 0x78, 0x08, 0x2f, 0x1f, 0x5e, 0xa4, 0x0c, 0x93, 0xc2, 0x5f, - 0x1e, 0xca, 0x05, 0x21, 0x51, 0xc2, 0xce, 0x7c, 0xcf, 0x58, 0x2f, 0x46, - 0x53, 0x7e, 0x49, 0x97, 0xb8, 0x06, 0x98, 0x9b, 0xe2, 0x12, 0xa9, 0x92, - 0xdd, 0x30, 0xe2, 0x4d, 0xd4, 0x32, 0x09, 0x62, 0x5f, 0xea, 0x0c, 0x0c, - 0x04, 0x41, 0x04, 0x78, 0xea, 0x03, 0x41, 0x94, 0x6d, 0x46, 0x38, 0xde, - 0x37, 0xe0, 0xb6, 0xc8, 0xfa, 0x94, 0x86, 0xbe, 0xd5, 0x78, 0x08, 0x2f, - 0x1f, 0x5e, 0xa4, 0x0c, 0x93, 0xc2, 0x5f, 0x1e, 0xca, 0x05, 0x21, 0x51, - 0xc2, 0xce, 0x7c, 0xcf, 0x58, 0x2f, 0x46, 0x53, 0x7e, 0x49, 0x97, 0xb8, - 0x06, 0x98, 0x9b, 0xe2, 0x12, 0xa9, 0x92, 0xdd, 0x30, 0xe2, 0x4d, 0xd4, - 0x32, 0x09, 0x62, 0x5f, 0xea, 0x0c, 0x0c, 0x04, 0x27, 0x30, 0x25, 0x04, - 0x10, 0x48, 0xd4, 0x7b, 0x6a, 0x50, 0xfb, 0x84, 0xf8, 0xb5, 0x8d, 0x13, - 0x62, 0xcc, 0x42, 0xa5, 0x42, 0x02, 0x03, 0x00, 0xc3, 0x50, 0x02, 0x02, - 0x01, 0x00, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x07, - 0x31, 0x00 }; -#endif +#if SOS_ENABLED #define kCompatibilityTestCount 0 #if 0 @@ -252,16 +101,19 @@ static void tests(void) SOSDataSourceRelease(test_source, NULL); } +#endif + int secd_51_account_inflate(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount + kCompatibilityTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_clear_testviews(); tests(); - - /* we can't re-inflate the v6 DER since we don't have a viable private key for it. */ - // test_v6(); + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-52-account-changed.m b/keychain/securityd/Regressions/secd-52-account-changed.m index 37b1cf8b..34eb8588 100644 --- a/keychain/securityd/Regressions/secd-52-account-changed.m +++ b/keychain/securityd/Regressions/secd-52-account-changed.m @@ -46,6 +46,7 @@ #include "SecdTestKeychainUtilities.h" #include "SOSAccountTesting.h" +#if SOS_ENABLED static void tests(void) { @@ -201,15 +202,17 @@ static void tests(void) SOSTestCleanup(); } - +#endif int secd_52_account_changed(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(113); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-52-offering-gencount-reset.m b/keychain/securityd/Regressions/secd-52-offering-gencount-reset.m index bb2f6a74..14979ffb 100644 --- a/keychain/securityd/Regressions/secd-52-offering-gencount-reset.m +++ b/keychain/securityd/Regressions/secd-52-offering-gencount-reset.m @@ -52,6 +52,7 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void tests(void) { @@ -128,7 +129,7 @@ static void tests(void) SOSCircleSetGeneration(carolTrust.trustedCircle, gencount); - SecKeyRef user_privkey = SOSUserKeygen(cfpassword, (__bridge CFDataRef)(carol_account.accountKeyDerivationParamters), &error); + SecKeyRef user_privkey = SOSUserKeygen(cfpassword, (__bridge CFDataRef)(carol_account.accountKeyDerivationParameters), &error); CFNumberRef genCountTest = SOSCircleGetGeneration(carolTrust.trustedCircle); CFIndex testPtr; CFNumberGetValue(genCountTest, kCFNumberCFIndexType, &testPtr); @@ -158,7 +159,11 @@ static void tests(void) is([alice_account getCircleStatus:&error],kSOSCCNotInCircle,"alice is not in the account (%@)", error); is([bob_account getCircleStatus:&error], kSOSCCNotInCircle,"bob is not in the account (%@)", error); is([carol_account getCircleStatus:&error], kSOSCCInCircle,"carol is in the account (%@)", error); - + secLogEnable(); + [carol_account iCloudIdentityStatus:^(NSData *json, NSError *error) { + diag("icloud identity JSON\n%s\n", [[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding] UTF8String]); + }]; + secLogDisable(); CFReleaseNull(gencount); CFReleaseNull(cfpassword); CFReleaseNull(user_privkey); @@ -168,14 +173,17 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_52_offering_gencount_reset(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(63); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-55-account-circle.m b/keychain/securityd/Regressions/secd-55-account-circle.m index d8035f97..93695d61 100644 --- a/keychain/securityd/Regressions/secd-55-account-circle.m +++ b/keychain/securityd/Regressions/secd-55-account-circle.m @@ -53,6 +53,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + static int kTestTestCount = 257; static void tests(void) @@ -343,14 +345,17 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_55_account_circle(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-55-account-incompatibility.m b/keychain/securityd/Regressions/secd-55-account-incompatibility.m index da6aabca..9a3a8b14 100644 --- a/keychain/securityd/Regressions/secd-55-account-incompatibility.m +++ b/keychain/securityd/Regressions/secd-55-account-incompatibility.m @@ -53,6 +53,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + static int kTestTestCount = 10; static void tests(void) @@ -101,14 +103,17 @@ static void tests(void) carol_account = nil; SOSTestCleanup(); } +#endif int secd_55_account_incompatibility(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-56-account-apply.m b/keychain/securityd/Regressions/secd-56-account-apply.m index 50748a08..d244dd61 100644 --- a/keychain/securityd/Regressions/secd-56-account-apply.m +++ b/keychain/securityd/Regressions/secd-56-account-apply.m @@ -51,6 +51,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + #define kAccountPasswordString ((uint8_t*) "FooFooFoo") #define kAccountPasswordStringLen 10 @@ -209,14 +211,17 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_56_account_apply(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(181); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-57-1-account-last-standing.m b/keychain/securityd/Regressions/secd-57-1-account-last-standing.m index d455b327..7ebebf6a 100644 --- a/keychain/securityd/Regressions/secd-57-1-account-last-standing.m +++ b/keychain/securityd/Regressions/secd-57-1-account-last-standing.m @@ -55,7 +55,9 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" +#if SOS_ENABLED static bool acceptApplicants(SOSAccount* account, CFIndex count) { bool retval = false; @@ -148,14 +150,17 @@ static void tests(void) alice_account = nil; SOSTestCleanup(); } +#endif int secd_57_1_account_last_standing(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(45); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-57-account-leave.m b/keychain/securityd/Regressions/secd-57-account-leave.m index 6e1710d1..248e0cc1 100644 --- a/keychain/securityd/Regressions/secd-57-account-leave.m +++ b/keychain/securityd/Regressions/secd-57-account-leave.m @@ -52,6 +52,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + /* static void trim_retirements_from_circle(SOSAccount* account) { @@ -250,14 +252,18 @@ static void tests(void) SOSTestCleanup(); } +#endif + int secd_57_account_leave(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(191); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_clear_testviews(); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-58-password-change.m b/keychain/securityd/Regressions/secd-58-password-change.m index 3135d5b7..975951aa 100644 --- a/keychain/securityd/Regressions/secd-58-password-change.m +++ b/keychain/securityd/Regressions/secd-58-password-change.m @@ -50,6 +50,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static bool AssertCreds(SOSAccount* account,CFStringRef acct_name, CFDataRef password) { CFErrorRef error = NULL; @@ -213,21 +214,40 @@ static void tests(void) is(countPeers(alice_account), 3, "There are three peers - Alice, Carol, Bob"); is(countActivePeers(alice_account), 4, "There are four active peers - bob, alice, carol and iCloud"); is(countActiveValidPeers(alice_account), 3, "There are three active valid peers - alice, bob, and icloud"); + + /* Change Password 4 - new peer changes the password and joins ----------------------------------------------------*/ + CFReleaseNull(cfnewpassword); + cfnewpassword = CFDataCreate(NULL, (uint8_t *) "dodododod", 10); + + SOSAccount* david_account = CreateAccountForLocalChanges(CFSTR("David"), CFSTR("TestSource")); + ok(AssertCreds(david_account , cfaccount, cfnewpassword), "Credential resetting for David"); + is(ProcessChangesUntilNoChange(changes, david_account, NULL), 2, "updates"); + is(countPeers(david_account), 3, "Still 3 peers"); + + ok(JoinCircle(david_account), "David Applies"); + is(ProcessChangesUntilNoChange(changes, david_account, NULL), 2, "updates"); + is(countPeers(david_account), 1, "Only David is in circle"); + + CFReleaseNull(cfnewpassword); alice_account = nil; bob_account = nil; carol_account = nil; + david_account = nil; SOSTestCleanup(); } +#endif int secd_58_password_change(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(211); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-59-account-cleanup.m b/keychain/securityd/Regressions/secd-59-account-cleanup.m index dcdb0699..329fff7d 100644 --- a/keychain/securityd/Regressions/secd-59-account-cleanup.m +++ b/keychain/securityd/Regressions/secd-59-account-cleanup.m @@ -52,6 +52,7 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void tests(void) { @@ -146,14 +147,17 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_59_account_cleanup(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(91); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd60-account-cloud-exposure.m b/keychain/securityd/Regressions/secd-60-account-cloud-exposure.m similarity index 96% rename from keychain/securityd/Regressions/secd60-account-cloud-exposure.m rename to keychain/securityd/Regressions/secd-60-account-cloud-exposure.m index a9979d44..b7e76dde 100644 --- a/keychain/securityd/Regressions/secd60-account-cloud-exposure.m +++ b/keychain/securityd/Regressions/secd-60-account-cloud-exposure.m @@ -22,7 +22,7 @@ */ // -// secd60-account-cloud-exposure.c +// secd-60-account-cloud-exposure.c // sec // @@ -46,7 +46,7 @@ #include #include "secd_regressions.h" -#include "SOSTestDataSource.h" +#include "keychain/SecureObjectSync/Regressions/SOSTestDataSource.h" #include "SOSRegressionUtilities.h" #include @@ -57,6 +57,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static bool SOSAccountResetCircleToNastyOffering(SOSAccount* account, SecKeyRef userPriv, SOSPeerInfoRef pi, CFErrorRef *error) { bool result = false; @@ -66,7 +67,7 @@ static bool SOSAccountResetCircleToNastyOffering(SOSAccount* account, SecKeyRef CFReleaseNull(userPub); return result; } - if(![account.trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)(account.gestalt) deviceID:(__bridge CFStringRef)(account.deviceID) backupKey:(__bridge CFDataRef)(account.backup_key) err:error]){ + if(![account.trust ensureFullPeerAvailable:account err:error]){ CFReleaseNull(userPub); return result; } @@ -219,14 +220,17 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_60_account_cloud_exposure(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(41); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-60-account-cloud-identity.m b/keychain/securityd/Regressions/secd-60-account-cloud-identity.m index 3fbb31d2..58d97b69 100644 --- a/keychain/securityd/Regressions/secd-60-account-cloud-identity.m +++ b/keychain/securityd/Regressions/secd-60-account-cloud-identity.m @@ -51,6 +51,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static bool purgeICloudIdentity(SOSAccount* account) { @@ -283,14 +284,17 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_60_account_cloud_identity(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(159); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.m b/keychain/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.m index ac6b75c1..a21d600a 100644 --- a/keychain/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.m +++ b/keychain/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.m @@ -51,6 +51,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + /* static void trim_retirements_from_circle(SOSAccount* account) { SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { @@ -178,13 +180,17 @@ static void tests(void) SOSTestCleanup(); } +#endif + int secd_61_account_leave_not_in_kansas_anymore(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(82); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-62-account-backup.m b/keychain/securityd/Regressions/secd-62-account-backup.m index f62cc022..4fa3312d 100644 --- a/keychain/securityd/Regressions/secd-62-account-backup.m +++ b/keychain/securityd/Regressions/secd-62-account-backup.m @@ -53,12 +53,10 @@ #include "keychain/securityd/SOSCloudCircleServer.h" -#if !TARGET_OS_SIMULATOR -#include "SOSAccountTesting.h" -#endif -#include "SecdTestKeychainUtilities.h" -#if !TARGET_OS_SIMULATOR +#include "SOSAccountTesting.h" +#include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static CFDataRef CopyBackupKeyForString(CFStringRef string, CFErrorRef *error) { @@ -68,12 +66,9 @@ static CFDataRef CopyBackupKeyForString(CFStringRef string, CFErrorRef *error) }); return result; } -#endif static void tests(void) { -#if !TARGET_OS_SIMULATOR - __block CFErrorRef error = NULL; CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); CFStringRef cfaccount = CFSTR("test@test.org"); @@ -156,7 +151,7 @@ static void tests(void) ok([bob_account.trust checkForRings:&error], "Alice_account is good"); CFReleaseNull(error); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 5, "updates"); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 4, "updates"); ok([alice_account.trust checkForRings:&error], "Alice_account is good"); @@ -165,9 +160,6 @@ static void tests(void) ok(SOSAccountIsMyPeerInBackupAndCurrentInView(alice_account, kTestView1), "Is alice in backup after sync?"); ok(SOSAccountIsMyPeerInBackupAndCurrentInView(bob_account, kTestView1), "IS bob in the backup after sync"); - - ok(!SOSAccountIsLastBackupPeer(alice_account, &error), "Alice is not last backup peer"); - CFReleaseNull(error); // //Bob leaves the circle @@ -179,11 +171,6 @@ static void tests(void) is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); ok(SOSAccountIsMyPeerInBackupAndCurrentInView(alice_account, kTestView1), "Bob left the circle, Alice is not in the backup"); - - ok(SOSAccountIsLastBackupPeer(alice_account, &error), "Alice is last backup peer"); - CFReleaseNull(error); - ok(!SOSAccountIsLastBackupPeer(bob_account, &error), "Bob is not last backup peer"); - CFReleaseNull(error); ok(testAccountPersistence(alice_account), "Test Account->DER->Account Equivalence"); @@ -211,16 +198,10 @@ static void tests(void) ok(!SOSAccountIsMyPeerInBackupAndCurrentInView(bob_account, kTestView1), "Bob isn't in the backup yet"); - ok(!SOSAccountIsLastBackupPeer(alice_account, &error), "Alice is the not the last backup peer - Bob still registers as one"); - CFReleaseNull(error); - ok(SOSAccountSetBackupPublicKey_wTxn(bob_account, bob_backup_key, &error), "Set backup public key, bob (%@)", error); is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates"); - ok(!SOSAccountIsLastBackupPeer(alice_account, &error), "Alice is not last backup peer"); - CFReleaseNull(error); - // //removing backup key for bob account // @@ -262,22 +243,19 @@ static void tests(void) alice_account = nil; bob_account = nil; SOSTestCleanup(); -#endif - } +#endif int secd_62_account_backup(int argc, char *const *argv) { -#if !TARGET_OS_SIMULATOR +#if SOS_ENABLED plan_tests(98); -#else - plan_tests(1); -#endif - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_setup_testviews(); // for running this test solo - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-63-account-resurrection.m b/keychain/securityd/Regressions/secd-63-account-resurrection.m index 5e0ef6d0..873c28dc 100644 --- a/keychain/securityd/Regressions/secd-63-account-resurrection.m +++ b/keychain/securityd/Regressions/secd-63-account-resurrection.m @@ -51,6 +51,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED typedef void (^stir_block)(int expected_iterations); @@ -198,14 +199,17 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_63_account_resurrection(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(73); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-64-circlereset.m b/keychain/securityd/Regressions/secd-64-circlereset.m index 6c905c29..130c2273 100644 --- a/keychain/securityd/Regressions/secd-64-circlereset.m +++ b/keychain/securityd/Regressions/secd-64-circlereset.m @@ -35,6 +35,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static int64_t getCurrentGenCount(SOSAccount* account) { SOSAccountTrustClassic* trust = account.trust; @@ -131,14 +132,17 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_64_circlereset(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(35); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-65-account-retirement-reset.m b/keychain/securityd/Regressions/secd-65-account-retirement-reset.m index a406f2ab..8eb68cba 100644 --- a/keychain/securityd/Regressions/secd-65-account-retirement-reset.m +++ b/keychain/securityd/Regressions/secd-65-account-retirement-reset.m @@ -52,6 +52,7 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED typedef void (^stir_block)(int expected_iterations); typedef int (^execute_block)(void); @@ -122,10 +123,12 @@ static void tests(void) return 2; }, ^{ - NSError *ns_error = nil; - frozen_alice = (CFDataRef) CFBridgingRetain([alice_account encodedData:&ns_error]); - ok(frozen_alice, "Copy encoded %@", ns_error); - ns_error = nil; + [alice_account performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + NSError *ns_error = nil; + frozen_alice = (CFDataRef) CFBridgingRetain([alice_account encodedData:&ns_error]); + ok(frozen_alice, "Copy encoded %@", ns_error); + ns_error = nil; + }]; SOSAccountPurgePrivateCredential(alice_account); @@ -169,14 +172,17 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_65_account_retirement_reset(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(28); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-66-account-recovery.m b/keychain/securityd/Regressions/secd-66-account-recovery.m index 2a2fa0ba..f2981360 100644 --- a/keychain/securityd/Regressions/secd-66-account-recovery.m +++ b/keychain/securityd/Regressions/secd-66-account-recovery.m @@ -51,7 +51,7 @@ #include #include "secd_regressions.h" -#include "SOSTestDataSource.h" +#include "keychain/SecureObjectSync/Regressions/SOSTestDataSource.h" #include "SOSRegressionUtilities.h" #include @@ -62,15 +62,7 @@ #include "keychain/securityd/SOSCloudCircleServer.h" #include "SecdTestKeychainUtilities.h" -#if TARGET_OS_SIMULATOR - -int secd_66_account_recovery(int argc, char *const *argv) { - plan_tests(1); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - return 0; -} - -#else +#if SOS_ENABLED #include "SOSAccountTesting.h" @@ -209,10 +201,10 @@ static void tests(bool recKeyFirst) ok([bob_account.trust checkForRings:&error], "Bob_account is good"); CFReleaseNull(error); - ok(SOSAccountIsMyPeerInBackupAndCurrentInView(alice_account, kTestView1), "Is alice is in backup before sync?"); + ok(SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(alice_account, kTestView1), "Is alice is in backup before sync?"); if(!recKeyFirst) { - SOSBackupSliceKeyBagRef bskb = SOSAccountBackupSliceKeyBagForView(alice_account, kTestView1, &error); + SOSBackupSliceKeyBagRef bskb = SOSAccountBackupSliceKeyBagForView_wTxn(alice_account, kTestView1, &error); CFReleaseNull(error); ok(!SOSBSKBHasRecoveryKey(bskb), "BSKB should not have recovery key"); CFReleaseNull(bskb); @@ -221,7 +213,7 @@ static void tests(bool recKeyFirst) ok([alice_account.trust checkForRings:&error], "Alice_account is good"); CFReleaseNull(error); - ok(SOSAccountIsMyPeerInBackupAndCurrentInView(bob_account, kTestView1), "Is bob in the backup after sync? - 1"); + ok(SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(bob_account, kTestView1), "Is bob in the backup after sync? - 1"); ok([bob_account.trust checkForRings:&error], "Alice_account is good"); CFReleaseNull(error); @@ -232,12 +224,9 @@ static void tests(bool recKeyFirst) ok([alice_account.trust checkForRings:&error], "Alice_account is good"); CFReleaseNull(error); - ok(SOSAccountIsMyPeerInBackupAndCurrentInView(alice_account, kTestView1), "Is alice is in backup after sync?"); + ok(SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(alice_account, kTestView1), "Is alice is in backup after sync?"); - ok(SOSAccountIsMyPeerInBackupAndCurrentInView(bob_account, kTestView1), "IS bob in the backup after sync"); - - ok(!SOSAccountIsLastBackupPeer(alice_account, &error), "Alice is not last backup peer"); - CFReleaseNull(error); + ok(SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(bob_account, kTestView1), "IS bob in the backup after sync"); // //Bob leaves the circle @@ -248,16 +237,11 @@ static void tests(bool recKeyFirst) //Alice should kick Bob out of the backup! is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - ok(SOSAccountIsMyPeerInBackupAndCurrentInView(alice_account, kTestView1), "Bob left the circle, Alice is in the backup"); - - ok(SOSAccountIsLastBackupPeer(alice_account, &error), "Alice is last backup peer"); - CFReleaseNull(error); - ok(!SOSAccountIsLastBackupPeer(bob_account, &error), "Bob is not last backup peer"); - CFReleaseNull(error); - + ok(SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(alice_account, kTestView1), "Bob left the circle, Alice is in the backup"); + //ok(testAccountPersistence(alice_account), "Test Account->DER->Account Equivalence"); SOSAccountTrustClassic* bobTrust = bob_account.trust; - ok(!SOSAccountIsPeerInBackupAndCurrentInView(alice_account, bobTrust.peerInfo, kTestView1), "Bob is still in the backup!"); + ok(!SOSAccountIsPeerInBackupAndCurrentInView_wTxn(alice_account, bobTrust.peerInfo, kTestView1), "Bob is still in the backup!"); //Bob gets back into the circle ok(SOSTestJoinWithApproval(cfpassword, cfaccount, changes, alice_account, bob_account, KEEP_USERKEY, 2, false), "Bob Re-Joins"); @@ -266,18 +250,12 @@ static void tests(bool recKeyFirst) is([bob_account.trust updateView:bob_account name:kTestView1 code:kSOSCCViewEnable err:&error], kSOSCCViewMember, "Enable view (%@)", error); CFReleaseNull(error); - ok(!SOSAccountIsMyPeerInBackupAndCurrentInView(bob_account, kTestView1), "Bob isn't in the backup yet"); - - ok(!SOSAccountIsLastBackupPeer(alice_account, &error), "Alice is the not the last backup peer - Bob still registers as one"); - CFReleaseNull(error); - + ok(!SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(bob_account, kTestView1), "Bob isn't in the backup yet"); + ok(SOSAccountSetBackupPublicKey_wTxn(bob_account, bob_backup_key, &error), "Set backup public key, alice (%@)", error); is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates"); - ok(!SOSAccountIsLastBackupPeer(alice_account, &error), "Alice is not last backup peer"); - CFReleaseNull(error); - // //removing backup key for bob account // @@ -286,8 +264,8 @@ static void tests(bool recKeyFirst) int nchanges = (recKeyFirst) ? 2: 2; is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), nchanges, "updates"); - ok(!SOSAccountIsMyPeerInBackupAndCurrentInView(bob_account, kTestView1), "Bob's backup key is in the backup - should not be so!"); - ok(!SOSAccountIsPeerInBackupAndCurrentInView(alice_account, bobTrust.peerInfo, kTestView1), "Bob is up to date in the backup!"); + ok(!SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(bob_account, kTestView1), "Bob's backup key is in the backup - should not be so!"); + ok(!SOSAccountIsPeerInBackupAndCurrentInView_wTxn(alice_account, bobTrust.peerInfo, kTestView1), "Bob is up to date in the backup!"); // // Setting new backup public key for Bob @@ -300,21 +278,21 @@ static void tests(bool recKeyFirst) ok(SOSAccountNewBKSBForView(bob_account, kTestView1, &error), "Setting new backup public key for bob account failed: (%@)", error); //bob is in his own backup - ok(SOSAccountIsMyPeerInBackupAndCurrentInView(bob_account, kTestView1), "Bob's backup key is not in the backup"); + ok(SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(bob_account, kTestView1), "Bob's backup key is not in the backup"); //alice does not have bob in her backup - ok(!SOSAccountIsPeerInBackupAndCurrentInView(alice_account, bobTrust.peerInfo, kTestView1), "Bob is up to date in the backup - should not be so!"); + ok(!SOSAccountIsPeerInBackupAndCurrentInView_wTxn(alice_account, bobTrust.peerInfo, kTestView1), "Bob is up to date in the backup - should not be so!"); is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 5, "updates"); - ok(SOSAccountIsMyPeerInBackupAndCurrentInView(bob_account, kTestView1), "Bob's backup key should be in the backup"); - ok(SOSAccountIsMyPeerInBackupAndCurrentInView(alice_account, kTestView1), "Alice is in the backup"); + ok(SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(bob_account, kTestView1), "Bob's backup key should be in the backup"); + ok(SOSAccountIsMyPeerInBackupAndCurrentInView_wTxn(alice_account, kTestView1), "Alice is in the backup"); if(!recKeyFirst) registerRecoveryKeyNow(changes, alice_account, bob_account, pubKeyBytes, recKeyFirst); - ok(SOSAccountRecoveryKeyIsInBackupAndCurrentInView(alice_account, kTestView1), "Recovery Key is also in the backup"); - ok(SOSAccountRecoveryKeyIsInBackupAndCurrentInView(bob_account, kTestView1), "Recovery Key is also in the backup"); + ok(SOSAccountRecoveryKeyIsInBackupAndCurrentInView_wTxn(alice_account, kTestView1), "Recovery Key is also in the backup"); + ok(SOSAccountRecoveryKeyIsInBackupAndCurrentInView_wTxn(bob_account, kTestView1), "Recovery Key is also in the backup"); - SOSBackupSliceKeyBagRef bskb = SOSAccountBackupSliceKeyBagForView(alice_account, kTestView1, &error); + SOSBackupSliceKeyBagRef bskb = SOSAccountBackupSliceKeyBagForView_wTxn(alice_account, kTestView1, &error); CFReleaseNull(error); ok(SOSBSKBHasRecoveryKey(bskb), "BSKB should have recovery key"); @@ -332,13 +310,13 @@ static void tests(bool recKeyFirst) registerRecoveryKeyNow(changes, alice_account, bob_account, NULL, recKeyFirst); - ok(!SOSAccountRecoveryKeyIsInBackupAndCurrentInView(alice_account, kTestView1), "Recovery Key is not in the backup"); - ok(!SOSAccountRecoveryKeyIsInBackupAndCurrentInView(bob_account, kTestView1), "Recovery Key is not in the backup"); + ok(!SOSAccountRecoveryKeyIsInBackupAndCurrentInView_wTxn(alice_account, kTestView1), "Recovery Key is not in the backup"); + ok(!SOSAccountRecoveryKeyIsInBackupAndCurrentInView_wTxn(bob_account, kTestView1), "Recovery Key is not in the backup"); - bskb = SOSAccountBackupSliceKeyBagForView(alice_account, kTestView1, &error); + bskb = SOSAccountBackupSliceKeyBagForView_wTxn(alice_account, kTestView1, &error); CFReleaseNull(error); - ok(!SOSBSKBHasRecoveryKey(bskb), "BSKB should not have recovery key"); + ok(SOSBSKBHasRecoveryKey(bskb), "BSKB will still have recovery key"); //========= @@ -360,16 +338,17 @@ static void tests(bool recKeyFirst) SOSTestCleanup(); } +#endif int secd_66_account_recovery(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(281); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(true); tests(false); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } - -#endif diff --git a/keychain/securityd/Regressions/secd-668-ghosts.m b/keychain/securityd/Regressions/secd-668-ghosts.m deleted file mode 100644 index 957c30ae..00000000 --- a/keychain/securityd/Regressions/secd-668-ghosts.m +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -// -// secd-668-ghosts.c -// sec -// - -#include -#include - -#include "keychain/SecureObjectSync/SOSAccount.h" -#include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" - -#include "secd_regressions.h" -#include "SOSAccountTesting.h" -#include "SecdTestKeychainUtilities.h" - -/* - Make a circle with two peers - alice and bob(bob is iOS and serial#"abababababab") - have alice leave the circle - release bob, make a new bob - iOS and same serial number - try to join the circle - it should resetToOffering with ghost fix - - For phase 1 we expect the ghostfix to work with iOS devices, but not with MacOSX devices. - */ - -#if 0 -static void hauntedCircle(SOSPeerInfoDeviceClass devClass, bool expectGhostBusted) -{ - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - CFStringRef ghostSerialID = CFSTR("abababababab"); - CFStringRef ghostIdsID = CFSTR("targetIDS"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("TestSource")); - SOSAccount* bob_account = SOSTestCreateAccountAsSerialClone(CFSTR("Bob"), devClass, ghostSerialID, ghostIdsID); - - // Start Circle - ok(SOSTestStartCircleWithAccount(alice_account, changes, cfaccount, cfpassword), "Have Alice start a circle"); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); - ok(SOSTestJoinWithApproval(cfpassword, cfaccount, changes, alice_account, bob_account, KEEP_USERKEY, 2, false), "Bob Joins"); - - // Alice Leaves - ok( [alice_account.trust leaveCircle:alice_account err:&error], "Alice Leaves (%@)", error); - CFReleaseNull(error); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - accounts_agree("Alice bails", bob_account, alice_account); - is(countPeers(bob_account), 1, "There should only be 1 valid peer"); - // We're dropping all peers that are in the circle - leaving a circle with only one peer - and that's a ghost - - // Make new bob - same as the old bob except peerID - - SOSAccount* bobFinal = SOSTestCreateAccountAsSerialClone(CFSTR("BobFinal"), devClass, ghostSerialID, ghostIdsID); - is(ProcessChangesUntilNoChange(changes, bobFinal, NULL), 1, "updates"); - - ok(SOSTestJoinWith(cfpassword, cfaccount, changes, bobFinal), "Application Made"); - CFReleaseNull(cfpassword); - - // Did ghostbuster work? - is(ProcessChangesUntilNoChange(changes, bobFinal, NULL), 2, "updates"); - if(expectGhostBusted) { // ghostbusting is currently disabled for MacOSX Peers - ok([bobFinal isInCircle:NULL], "Bob is in"); - } else { - ok(![bobFinal isInCircle:NULL], "Bob is not in"); - } - - is(countPeers(bobFinal), 1, "There should only be 1 valid peer"); - - CFReleaseNull(changes); - - bob_account = nil; - alice_account = nil; - bobFinal = nil; - SOSTestCleanup(); -} - -static void multiBob(SOSPeerInfoDeviceClass devClass, bool expectGhostBusted, bool delayedPrivKey, bool pairJoin) { - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - CFStringRef ghostSerialID = CFSTR("abababababab"); - CFStringRef ghostIdsID = CFSTR("targetIDS"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("TestSource")); - - // Start Circle - ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - is(ProcessChangesUntilNoChange(changes, alice_account, NULL), 1, "updates"); - - ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - is(ProcessChangesUntilNoChange(changes, alice_account, NULL), 1, "updates"); - - SOSTestMakeGhostInCircle(CFSTR("Bob1"), devClass, ghostSerialID, ghostIdsID, cfpassword, cfaccount, changes, alice_account, 2); - SOSTestMakeGhostInCircle(CFSTR("Bob2"), devClass, ghostSerialID, ghostIdsID, cfpassword, cfaccount, changes, alice_account, 3); - SOSTestMakeGhostInCircle(CFSTR("Bob3"), devClass, ghostSerialID, ghostIdsID, cfpassword, cfaccount, changes, alice_account, 4); - SOSTestMakeGhostInCircle(CFSTR("Bob4"), devClass, ghostSerialID, ghostIdsID, cfpassword, cfaccount, changes, alice_account, 5); - - SOSAccount* bobFinal_account = SOSTestCreateAccountAsSerialClone(CFSTR("BobFinal"), devClass, ghostSerialID, ghostIdsID); - - if(pairJoin) { - SOSTestJoinThroughPiggyBack(cfpassword, cfaccount, changes, alice_account, bobFinal_account, KEEP_USERKEY, 6, true); - is(countPeers(bobFinal_account), 6, "Expect ghosts still in circle"); - } else if(delayedPrivKey) { - SOSTestJoinWithApproval(cfpassword, cfaccount, changes, alice_account, bobFinal_account, DROP_USERKEY, 6, true); - is(countPeers(bobFinal_account), 6, "Expect ghosts still in circle"); - } else { - SOSTestJoinWithApproval(cfpassword, cfaccount, changes, alice_account, bobFinal_account, KEEP_USERKEY, 2, true); - } - - if(pairJoin || delayedPrivKey) { // this allows the ghostbusting to be done in a delayed fashion for the instances where that is proper - SOSAccountTryUserCredentials(bobFinal_account, cfaccount, cfpassword, &error); - ok(SOSTestChangeAccountDeviceName(bobFinal_account, CFSTR("ThereCanBeOnlyOneBob")), "force an unrelated circle change"); - is(ProcessChangesUntilNoChange(changes, alice_account, bobFinal_account, NULL), 3, "updates"); - } - - CFReleaseNull(cfpassword); - - - ok([bobFinal_account isInCircle:NULL], "bobFinal_account is in"); - - is(countPeers(bobFinal_account), 2, "Expect ghostBobs to be gone"); - is(countPeers(alice_account), 2, "Expect ghostBobs to be gone"); - accounts_agree_internal("Alice and ThereCanBeOnlyOneBob are the only circle peers and they agree", alice_account, bobFinal_account, false); - - CFReleaseNull(changes); - - alice_account = nil; - bobFinal_account = nil; - - SOSTestCleanup(); -} - -static void iosICloudIdentity() { - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - CFStringRef ghostIdsID = CFSTR("targetIDS"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("TestSource")); - - // Start Circle - ok(SOSTestStartCircleWithAccount(alice_account, changes, cfaccount, cfpassword), "Have Alice start a circle"); - - SOSCircleRef circle = [alice_account.trust getCircle:NULL]; - __block CFStringRef serial = NULL; - SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { - if(SOSPeerInfoIsCloudIdentity(peer)) { - serial = SOSPeerInfoCopySerialNumber(peer); - } - }); - - SOSAccount* bob_account = SOSTestCreateAccountAsSerialClone(CFSTR("Bob"), SOSPeerInfo_iOS, serial, ghostIdsID); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); - ok(SOSTestJoinWithApproval(cfpassword, cfaccount, changes, alice_account, bob_account, KEEP_USERKEY, 2, false), "Bob Joins"); - CFReleaseNull(cfpassword); - - circle = [alice_account.trust getCircle:&error]; - __block bool hasiCloudIdentity = false; - SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { - if(SOSPeerInfoIsCloudIdentity(peer)) { - hasiCloudIdentity = true; - } - }); - - ok(hasiCloudIdentity, "GhostBusting didn't mess with the iCloud Identity"); - - CFReleaseNull(changes); - alice_account = nil; - SOSTestCleanup(); -} -#endif // 0 - -int secd_68_ghosts(int argc, char *const *argv) -{ - plan_tests(1); - - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - -#if 0 - // changing ghostbusting. handleUpdateCircle version is going away. - hauntedCircle(SOSPeerInfo_iOS, true); - hauntedCircle(SOSPeerInfo_macOS, false); - multiBob(SOSPeerInfo_iOS, true, false, false); - multiBob(SOSPeerInfo_iOS, false, true, false); - multiBob(SOSPeerInfo_iOS, false, false, true); // piggyback join case - - iosICloudIdentity(); -#endif - return 0; -} diff --git a/keychain/securityd/Regressions/secd-67-prefixedKeyIDs.m b/keychain/securityd/Regressions/secd-67-prefixedKeyIDs.m index 93809dfd..b4de05d8 100644 --- a/keychain/securityd/Regressions/secd-67-prefixedKeyIDs.m +++ b/keychain/securityd/Regressions/secd-67-prefixedKeyIDs.m @@ -61,6 +61,8 @@ #include "SOSAccountTesting.h" +#if SOS_ENABLED + static void tests() { CFErrorRef error = NULL; int keySizeInBits = 256; @@ -119,11 +121,15 @@ static void tests() { } +#endif int secd_67_prefixedKeyIDs(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(12); - tests(); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-68-fullPeerInfoIntegrity.m b/keychain/securityd/Regressions/secd-68-fullPeerInfoIntegrity.m new file mode 100644 index 00000000..cd5a3bbb --- /dev/null +++ b/keychain/securityd/Regressions/secd-68-fullPeerInfoIntegrity.m @@ -0,0 +1,122 @@ +// +// secd-68-fullPeerInfoIntegrity.m +// secdRegressions +// +// Created by Richard Murphy on 4/30/20. +// + +#import + +#include +#include + +#include + +#include "keychain/SecureObjectSync/SOSAccount.h" +#include +#include "keychain/SecureObjectSync/SOSInternal.h" +#include "keychain/SecureObjectSync/SOSUserKeygen.h" +#include "keychain/SecureObjectSync/SOSTransport.h" +#include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include "keychain/securityd/SOSCloudCircleServer.h" + +#include "SOSAccountTesting.h" + +#include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + +static NSString *makeCircle(SOSAccount* testaccount, CFMutableDictionaryRef changes) { + CFErrorRef error = NULL; + + // Every time we resetToOffering should result in a new fpi + NSString *lastPeerID = testaccount.peerID; + ok(SOSAccountResetToOffering_wTxn(testaccount, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + NSString *currentPeerID = testaccount.peerID; + ok(![lastPeerID isEqualToString:currentPeerID], "peerID changed on circle reset"); + return currentPeerID; +} + +static void tests(void) { + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + CFStringRef cfaccount = CFSTR("test@test.org"); + + CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + SOSAccount* testaccount = CreateAccountForLocalChanges(CFSTR("TestDev"), CFSTR("TestSource")); + + // Just making an account object to mess with + ok(SOSAccountAssertUserCredentialsAndUpdate(testaccount, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + CFReleaseNull(error); + + // make a circle then make sure fpi isn't reset just for a normal ensureFullPeerAvailable + NSString *lastPeerID = makeCircle(testaccount, changes); + ok([testaccount.trust ensureFullPeerAvailable:testaccount err:&error], "fullPeer is available"); + NSString *currentPeerID = testaccount.peerID; + ok([lastPeerID isEqualToString: currentPeerID], "peerID did not alter in trip through ensureFullPeerAvailable"); + + + // leaving a circle should reset the fpi + lastPeerID = makeCircle(testaccount, changes); + ok([testaccount.trust leaveCircle:testaccount err:&error], "leave the circle %@", error); + CFReleaseNull(error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + currentPeerID = testaccount.peerID; + ok(![lastPeerID isEqualToString:currentPeerID], "peerID changed on leaving circle"); + + // break the fullpeerinfo by purging the private key - then fix in ensureFullPeerAvailable + lastPeerID = makeCircle(testaccount, changes); + ok(SOSFullPeerInfoPurgePersistentKey(testaccount.fullPeerInfo, &error), "purging persistent key %@", error); + currentPeerID = testaccount.peerID; + ok([lastPeerID isEqualToString:currentPeerID], "pre-ensuring peerID remains the same"); + lastPeerID = currentPeerID; + ok([testaccount.trust ensureFullPeerAvailable:testaccount err:&error], "fullPeer is available"); + currentPeerID = testaccount.peerID; + ok(![lastPeerID isEqualToString: currentPeerID], "peerID changed because fullPeerInfo fixed in ensureFullPeerAvailable"); + lastPeerID = currentPeerID; + + // If that last thing worked this peer won't be in the circle any more - changing fpi changes "me" + ok(SOSAccountAssertUserCredentialsAndUpdate(testaccount, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + CFReleaseNull(error); + ok(![testaccount isInCircle: &error], "No longer in circle"); + + // This join should work because the peer we left in the circle will be a ghost and there are no other peers + ok(SOSAccountJoinCircles_wTxn(testaccount, &error), "Apply to circle (%@)", error); + CFReleaseNull(error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + ok([testaccount isInCircle: &error], "Is in circle"); + currentPeerID = testaccount.peerID; + ok(![lastPeerID isEqualToString: currentPeerID], "peerID changed because fullPeerInfo changed during join"); + + CFReleaseNull(cfpassword); + testaccount = nil; + SOSTestCleanup(); +} +#endif + +int secd_68_fullPeerInfoIntegrity(int argc, char *const *argv) +{ +#if SOS_ENABLED + plan_tests(29); + secd_test_setup_temp_keychain(__FUNCTION__, NULL); + tests(); + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif + return 0; +} diff --git a/keychain/securityd/Regressions/secd-70-engine-corrupt.m b/keychain/securityd/Regressions/secd-70-engine-corrupt.m index a229bcaa..167e5979 100644 --- a/keychain/securityd/Regressions/secd-70-engine-corrupt.m +++ b/keychain/securityd/Regressions/secd-70-engine-corrupt.m @@ -42,9 +42,11 @@ #include #include #include +#include "SOSAccountTesting.h" #include #include +#if SOS_ENABLED static int kTestTestCount = 121; @@ -242,23 +244,24 @@ TODO: { }, CFSTR("Alice"), CFSTR("Bob"), NULL); } } +#endif int secd_70_engine_corrupt(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - __security_simulatecrash_enable(false); - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - nosha1(); drop_item(); drop_manifest(); add_sha1(); change_sha1(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); __security_simulatecrash_enable(true); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-70-engine-smash.m b/keychain/securityd/Regressions/secd-70-engine-smash.m index 62be20d5..65c6c1f5 100644 --- a/keychain/securityd/Regressions/secd-70-engine-smash.m +++ b/keychain/securityd/Regressions/secd-70-engine-smash.m @@ -25,6 +25,9 @@ #include "keychain/SecureObjectSync/Regressions/SOSTestDevice.h" #include "secd_regressions.h" #include "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static int kTestTestCount = 581; @@ -48,15 +51,18 @@ static void smash(void) { return false; }, CFSTR("alice"), CFSTR("bob"), NULL); } +#endif int secd_70_engine_smash(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - smash(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-70-engine.m b/keychain/securityd/Regressions/secd-70-engine.m index 87ac71fd..dcc9b481 100644 --- a/keychain/securityd/Regressions/secd-70-engine.m +++ b/keychain/securityd/Regressions/secd-70-engine.m @@ -43,43 +43,9 @@ #include #include +#include "SOSAccountTesting.h" -__unused static bool SOSCircleHandleCircleWithLock(SOSEngineRef engine, CFStringRef myID, CFDataRef message, CFErrorRef *error) { - - CFMutableArrayRef trustedPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFMutableArrayRef untrustedPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFStringRef peerID = NULL; - const uint8_t expected[20] = { 0xea, 0x6c, 0x01, 0x4d, - 0xc7, 0x2d, 0x6f, 0x8c, - 0xcd, 0x1e, 0xd9, 0x2a, - 0xce, 0x1d, 0x41, 0xf0, - 0xd8, 0xde, 0x89, 0x57 }; - - const char resultSize = sizeof(expected); - - CFDataRef coder = CFDataCreate(kCFAllocatorDefault, expected, resultSize); - CFArrayForEachC(SOSEngineGetPeerIDs(engine), peerID){ - CFArrayAppendValue(trustedPeers, peerID); - }; - CFReleaseNull(coder); - - CFShow(trustedPeers); - // all trusted - SOSEngineCircleChanged(engine, myID,trustedPeers, untrustedPeers); - - // make first peer untrusted - peerID = (CFStringRef)CFArrayGetValueAtIndex(trustedPeers, 0); - CFArrayAppendValue(untrustedPeers, peerID); - CFArrayRemoveAllValue(trustedPeers, peerID); - //we should see peerState cleared out except for the coder! - SOSEngineCircleChanged(engine, myID, trustedPeers, untrustedPeers); - - CFArrayAppendValue(trustedPeers, peerID); - CFArrayRemoveAllValue(untrustedPeers, peerID); - - - return true; -} +#if SOS_ENABLED static void testsync3(const char *name, const char *test_directive, const char *test_reason) { __block int iteration=0; @@ -163,8 +129,6 @@ static void testsync(const char *name, const char *test_directive, const char * } } CFReleaseSafe(messageDigestStr); - //SOSCircleHandleCircleWithLock(source->ds->engine, SOSEngineGetMyID(source->ds->engine), CFDataCreate(kCFAllocatorDefault, 0, 0), NULL); - } return false; }, CFSTR("alice"), CFSTR("bob"), NULL); @@ -198,6 +162,7 @@ static void testsyncempty(void) { SOSTestDeviceListSync("syncempty", test_directive, test_reason, testDevices, NULL, NULL); SOSTestDeviceListInSync("syncempty", test_directive, test_reason, testDevices); SOSTestDeviceDestroyEngine(testDevices); + SOSTestDeviceForceCloseDatabases(testDevices); CFReleaseSafe(testDevices); } } @@ -245,7 +210,8 @@ static void testsyncmany(const char *name, const char *test_directive, const cha return false; }); SOSTestDeviceListInSync(name, test_directive, test_reason, testDevices); - SOSTestDeviceDestroyEngine(testDevices); + SOSTestDeviceDestroyEngine(testDevices); + SOSTestDeviceForceCloseDatabases(testDevices); CFReleaseSafe(testDevices); } } @@ -503,15 +469,18 @@ SKIP: testsyncmany("v2syncmany", test_directive, test_reason, 9, 10, 2, syncmany_add); testsync2p(); } +#endif int secd_70_engine(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(1172); - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - synctests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-70-otr-remote.m b/keychain/securityd/Regressions/secd-70-otr-remote.m index 88735ab4..accf7c17 100644 --- a/keychain/securityd/Regressions/secd-70-otr-remote.m +++ b/keychain/securityd/Regressions/secd-70-otr-remote.m @@ -48,6 +48,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void RegressionsLogError(CFErrorRef error) { @@ -180,14 +181,17 @@ static void tests(void) CFReleaseNull(bobSideSession); CFReleaseNull(testError); } +#endif int secd_70_otr_remote(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-71-engine-save.m b/keychain/securityd/Regressions/secd-71-engine-save.m index 1f9eabf1..f3087db5 100644 --- a/keychain/securityd/Regressions/secd-71-engine-save.m +++ b/keychain/securityd/Regressions/secd-71-engine-save.m @@ -40,9 +40,11 @@ #include #include #include +#include "SOSAccountTesting.h" #include #include +#if SOS_ENABLED static int kTestTestCount = 8; @@ -176,16 +178,20 @@ static void testSaveRestore(void) { ok(bx,"SOSTestDeviceEngineSave v2: %@",error); SOSTestDeviceDestroyEngine(testDevices); + SOSTestDeviceForceCloseDatabases(testDevices); CFReleaseSafe(deviceIDs); CFReleaseSafe(testDevices); CFReleaseSafe(error); } - +#endif + int secd_71_engine_save(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - testSaveRestore(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-74-engine-beer-servers.m b/keychain/securityd/Regressions/secd-74-engine-beer-servers.m index d814afdf..fd1f6179 100644 --- a/keychain/securityd/Regressions/secd-74-engine-beer-servers.m +++ b/keychain/securityd/Regressions/secd-74-engine-beer-servers.m @@ -25,6 +25,9 @@ #include "keychain/SecureObjectSync/Regressions/SOSTestDevice.h" #include "secd_regressions.h" #include "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static int kTestTestCount = 646; @@ -79,15 +82,18 @@ static void beer_servers(void) { CFRelease(objectNames); CFRelease(itemData); } +#endif int secd_74_engine_beer_servers(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - beer_servers(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-75-engine-views.m b/keychain/securityd/Regressions/secd-75-engine-views.m index 6e65d3c3..2de38478 100644 --- a/keychain/securityd/Regressions/secd-75-engine-views.m +++ b/keychain/securityd/Regressions/secd-75-engine-views.m @@ -27,6 +27,9 @@ #include "SecdTestKeychainUtilities.h" #include #include "keychain/SecureObjectSync/SOSPeer.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static int kTestTestCount = 53; @@ -109,21 +112,24 @@ static void test_engine_views(void) { SOSTestDeviceListSync(name, test_directive, test_reason, testDevices, pre, post); SOSTestDeviceListInSync(name, test_directive, test_reason, testDevices); SOSTestDeviceDestroyEngine(testDevices); + SOSTestDeviceForceCloseDatabases(testDevices); CFReleaseNull(testDevices); CFReleaseNull(views); CFReleaseNull(objectNames); CFReleaseNull(itemData); } +#endif int secd_75_engine_views(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - test_engine_views(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-76-idstransport.m b/keychain/securityd/Regressions/secd-76-idstransport.m deleted file mode 100644 index 164c56f0..00000000 --- a/keychain/securityd/Regressions/secd-76-idstransport.m +++ /dev/null @@ -1,315 +0,0 @@ -// -// secd-76-idstransport.c -// sec -// -// - -/* - * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include - -#include -#include "SecdTestKeychainUtilities.h" -#import "SOSAccountTesting.h" -#import "SOSTransportTestTransports.h" -#include -#include -#include "SOSTestDevice.h" - - - -static int kTestTestCount = 73; - -static void tests() -{ - CFErrorRef error = NULL; - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - - SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("ak")); - SOSAccount* bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), CFSTR("ak")); - SOSAccountTrustClassic *aliceTrust = alice_account.trust; - SOSAccountTrustClassic *bobTrust = bob_account.trust; - - ok(SOSAccountAssertUserCredentialsAndUpdate(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); - - ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(cfpassword); - CFReleaseNull(error); - - ok(NULL != alice_account, "Alice Created"); - ok(NULL != bob_account, "Bob Created"); - - ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - ok(SOSAccountJoinCircles_wTxn(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates"); - - accounts_agree("bob&alice pair", bob_account, alice_account); - - CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); - ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); - CFReleaseNull(peers); - - //creating test devices - CFIndex version = 0; - - // Optionally prefix each peer with name to make them more unique. - CFArrayRef deviceIDs = CFArrayCreateForCFTypes(kCFAllocatorDefault,alice_account.peerID, bob_account.peerID, NULL); - CFSetRef views = SOSViewsCopyTestV2Default(); - CFMutableArrayRef peerMetas = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFStringRef deviceID; - CFArrayForEachC(deviceIDs, deviceID) { - SOSPeerMetaRef peerMeta = SOSPeerMetaCreateWithComponents(deviceID, views, NULL); - CFArrayAppendValue(peerMetas, peerMeta); - CFReleaseNull(peerMeta); - } - - CFReleaseNull(views); - CFArrayForEachC(deviceIDs, deviceID) { - SOSTestDeviceRef device = SOSTestDeviceCreateWithDbNamed(kCFAllocatorDefault, deviceID, deviceID); - SOSTestDeviceSetPeerIDs(device, peerMetas, version, NULL); - - if(CFEqualSafe(deviceID, (__bridge CFTypeRef)(alice_account.peerID))){ - alice_account.factory = device->dsf; - SOSTestDeviceAddGenericItem(device, CFSTR("Alice"), CFSTR("Alice-add")); - } - else{ - bob_account.factory = device->dsf; - SOSTestDeviceAddGenericItem(device, CFSTR("Bob"), CFSTR("Bob-add")); - } - CFReleaseNull(device); - } - CFReleaseNull(deviceIDs); - CFReleaseNull(peerMetas); - - SOSUnregisterAllTransportMessages(); - CFArrayRemoveAllValues(message_transports); - - alice_account.ids_message_transport = (SOSMessageIDS*)[[SOSMessageIDSTest alloc] initWithAccount:alice_account andAccountName:CFSTR("Alice") andCircleName:SOSCircleGetName(aliceTrust.trustedCircle) err:&error]; - - - bob_account.ids_message_transport = (SOSMessageIDS*)[[SOSMessageIDSTest alloc] initWithAccount:bob_account andAccountName:CFSTR("Bob") andCircleName:SOSCircleGetName(bobTrust.trustedCircle) err:&error]; - ok(alice_account.ids_message_transport != NULL, "Alice Account, Created IDS Test Transport"); - ok(bob_account.ids_message_transport != NULL, "Bob Account, Created IDS Test Transport"); - - bool result = [alice_account.trust modifyCircle:alice_account.circle_transport err:&error action:^(SOSCircleRef circle) { - CFErrorRef localError = NULL; - - SOSFullPeerInfoUpdateTransportType(aliceTrust.fullPeerInfo, SOSTransportMessageTypeIDSV2, &localError); - SOSFullPeerInfoUpdateTransportPreference(aliceTrust.fullPeerInfo, kCFBooleanFalse, &localError); - SOSFullPeerInfoUpdateTransportFragmentationPreference(aliceTrust.fullPeerInfo, kCFBooleanTrue, &localError); - SOSFullPeerInfoUpdateTransportAckModelPreference(aliceTrust.fullPeerInfo, kCFBooleanTrue, &localError); - - return SOSCircleHasPeer(circle, aliceTrust.peerInfo, NULL); - }]; - - ok(result, "Alice account update circle with transport type"); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - result &= [bob_account.trust modifyCircle:bob_account.circle_transport err:&error action:^(SOSCircleRef circle) { - CFErrorRef localError = NULL; - - SOSFullPeerInfoUpdateTransportType(bobTrust.fullPeerInfo, SOSTransportMessageTypeIDSV2, &localError); - SOSFullPeerInfoUpdateTransportPreference(bobTrust.fullPeerInfo, kCFBooleanFalse, &localError); - SOSFullPeerInfoUpdateTransportFragmentationPreference(bobTrust.fullPeerInfo, kCFBooleanTrue, &localError); - SOSFullPeerInfoUpdateTransportAckModelPreference(bobTrust.fullPeerInfo, kCFBooleanTrue, &localError); - - return SOSCircleHasPeer(circle, bobTrust.peerInfo, NULL); - }]; - - ok(result, "Bob account update circle with transport type"); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - CFStringRef alice_transportType =SOSPeerInfoCopyTransportType(alice_account.peerInfo); - CFStringRef bob_accountTransportType = SOSPeerInfoCopyTransportType(bob_account.peerInfo); - ok(CFEqualSafe(alice_transportType, CFSTR("IDS2.0")), "Alice transport type not IDS"); - ok(CFEqualSafe(bob_accountTransportType, CFSTR("IDS2.0")), "Bob transport type not IDS"); - - CFReleaseNull(alice_transportType); - CFReleaseNull(bob_accountTransportType); - - SOSTransportMessageIDSTestSetName((SOSMessageIDSTest*)alice_account.ids_message_transport, CFSTR("Alice Account")); - ok(SOSTransportMessageIDSTestGetName((SOSMessageIDSTest*)alice_account.ids_message_transport) != NULL, "retrieved getting account name"); - ok(SOSAccountRetrieveDeviceIDFromKeychainSyncingOverIDSProxy(alice_account, &error) != false, "device ID from KeychainSyncingOverIDSProxy"); - - SOSTransportMessageIDSTestSetName((SOSMessageIDSTest*)bob_account.ids_message_transport, CFSTR("Bob Account")); - ok(SOSTransportMessageIDSTestGetName((SOSMessageIDSTest*)bob_account.ids_message_transport) != NULL, "retrieved getting account name"); - ok(SOSAccountRetrieveDeviceIDFromKeychainSyncingOverIDSProxy(bob_account, &error) != false, "device ID from KeychainSyncingOverIDSProxy"); - - ok(SOSAccountSetMyDSID_wTxn(alice_account, CFSTR("Alice"),&error), "Setting IDS device ID"); - CFStringRef alice_dsid = SOSAccountCopyDeviceID(alice_account, &error); - ok(CFEqualSafe(alice_dsid, CFSTR("Alice")), "Getting IDS device ID"); - - ok(SOSAccountSetMyDSID_wTxn(bob_account, CFSTR("Bob"),&error), "Setting IDS device ID"); - CFStringRef bob_dsid = SOSAccountCopyDeviceID(bob_account, &error); - ok(CFEqualSafe(bob_dsid, CFSTR("Bob")), "Getting IDS device ID"); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates"); - - SOSTransportMessageIDSTestSetName((SOSMessageIDSTest*)alice_account.ids_message_transport, CFSTR("Alice Account")); - ok(SOSTransportMessageIDSTestGetName((SOSMessageIDSTest*)alice_account.ids_message_transport) != NULL, "retrieved getting account name"); - ok(SOSAccountRetrieveDeviceIDFromKeychainSyncingOverIDSProxy(alice_account, &error) != false, "device ID from KeychainSyncingOverIDSProxy"); - - ok(SOSAccountSetMyDSID_wTxn(alice_account, CFSTR("DSID"),&error), "Setting IDS device ID"); - CFStringRef dsid = SOSAccountCopyDeviceID(alice_account, &error); - ok(CFEqualSafe(dsid, CFSTR("DSID")), "Getting IDS device ID"); - CFReleaseNull(dsid); - - ok(SOSAccountStartPingTest(alice_account, CFSTR("hai there!"), &error), "Ping test"); - ok(CFDictionaryGetCount(SOSTransportMessageIDSTestGetChanges((SOSMessageIDSTest*)alice_account.ids_message_transport)) != 0, "ping message made it to transport"); - SOSTransportMessageIDSTestClearChanges((SOSMessageIDSTest*)alice_account.ids_message_transport); - - ok(SOSAccountSendIDSTestMessage(alice_account, CFSTR("hai again!"), &error), "Send Test Message"); - ok(CFDictionaryGetCount(SOSTransportMessageIDSTestGetChanges((SOSMessageIDSTest*)alice_account.ids_message_transport)) != 0, "ping message made it to transport"); - - CFStringRef dataKey = CFStringCreateWithCString(kCFAllocatorDefault, kMessageKeyIDSDataMessage, kCFStringEncodingASCII); - CFStringRef deviceIDKey = CFStringCreateWithCString(kCFAllocatorDefault, kMessageKeyDeviceID, kCFStringEncodingASCII); - CFStringRef sendersPeerIDKey = CFStringCreateWithCString(kCFAllocatorDefault, kMessageKeySendersPeerID, kCFStringEncodingASCII); - - //test IDS message handling - CFMutableDictionaryRef messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - ok([alice_account.ids_message_transport SOSTransportMessageIDSHandleMessage:alice_account m:messageDict err:&error] - == kHandleIDSMessageDontHandle, "sending empty message dictionary"); - - CFDictionaryAddValue(messageDict, deviceIDKey, CFSTR("Alice Account")); - ok([alice_account.ids_message_transport SOSTransportMessageIDSHandleMessage:alice_account m:messageDict err:&error] == kHandleIDSMessageDontHandle, "sending device ID only"); - - CFReleaseNull(messageDict); - messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDictionaryAddValue(messageDict, sendersPeerIDKey, CFSTR("Alice Account")); - ok([alice_account.ids_message_transport SOSTransportMessageIDSHandleMessage:alice_account m:messageDict err:&error] == kHandleIDSMessageDontHandle, "sending peer ID only"); - - CFReleaseNull(messageDict); - messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDataRef data = CFDataCreate(kCFAllocatorDefault, 0, 0); - CFDictionaryAddValue(messageDict, dataKey, data); - ok( [alice_account.ids_message_transport SOSTransportMessageIDSHandleMessage:alice_account m:messageDict err:&error] == kHandleIDSMessageDontHandle, "sending data only"); - - CFReleaseNull(messageDict); - CFReleaseNull(data); - messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - data = CFDataCreate(kCFAllocatorDefault, 0, 0); - CFDictionaryAddValue(messageDict, dataKey, data); - CFDictionaryAddValue(messageDict, sendersPeerIDKey, CFSTR("Alice Account")); - ok([(SOSMessageIDS*)alice_account.ids_message_transport SOSTransportMessageIDSHandleMessage:alice_account m:messageDict err:&error]== kHandleIDSMessageDontHandle, "sending data and peerid only"); - - CFReleaseNull(messageDict); - CFReleaseNull(data); - messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - data = CFDataCreate(kCFAllocatorDefault, 0, 0); - CFDictionaryAddValue(messageDict, dataKey, data); - CFDictionaryAddValue(messageDict, deviceIDKey, CFSTR("Alice Account")); - ok([(SOSMessageIDS*)alice_account.ids_message_transport SOSTransportMessageIDSHandleMessage:alice_account m:messageDict err:&error] == kHandleIDSMessageDontHandle, "sending data and deviceid only"); - - CFReleaseNull(messageDict); - CFReleaseNull(data); - messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDictionaryAddValue(messageDict, deviceIDKey, CFSTR("Alice Account")); - CFDictionaryAddValue(messageDict, sendersPeerIDKey, CFSTR("Alice Account")); - ok([(SOSMessageIDS*)alice_account.ids_message_transport SOSTransportMessageIDSHandleMessage:alice_account m:messageDict err:&error] == kHandleIDSMessageDontHandle, "sending peerid and deviceid only"); - - CFReleaseNull(messageDict); - CFReleaseNull(data); - messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - data = CFDataCreate(kCFAllocatorDefault, 0, 0); - CFDictionaryAddValue(messageDict, dataKey, data); - CFDictionaryAddValue(messageDict, deviceIDKey, CFSTR("Alice Account")); - CFDictionaryAddValue(messageDict, sendersPeerIDKey, SOSPeerInfoGetPeerID(bob_account.peerInfo)); - ok([(SOSMessageIDS*)alice_account.ids_message_transport SOSTransportMessageIDSHandleMessage:alice_account m:messageDict err:&error]== kHandleIDSMessageDontHandle, "sending peerid and deviceid and data"); - - CFReleaseNull(messageDict); - CFReleaseNull(data); - - messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - data = CFDataCreate(kCFAllocatorDefault, 0, 0); - CFDictionaryAddValue(messageDict, dataKey, data); - CFStringRef BobDeviceID = SOSPeerInfoCopyDeviceID(bob_account.peerInfo); - CFDictionaryAddValue(messageDict, deviceIDKey, BobDeviceID); - CFReleaseNull(BobDeviceID); - CFDictionaryAddValue(messageDict, sendersPeerIDKey, CFSTR("Alice Account")); - ok([(SOSMessageIDS*)alice_account.ids_message_transport SOSTransportMessageIDSHandleMessage:alice_account m:messageDict err:&error]== kHandleIDSMessageDontHandle, "sending peerid and deviceid and data"); - - CFReleaseNull(data); - CFReleaseNull(dataKey); - CFReleaseNull(deviceIDKey); - CFReleaseNull(sendersPeerIDKey); - - CFReleaseNull(alice_dsid); - CFReleaseNull(bob_dsid); - CFReleaseNull(changes); - - SOSTestCleanup(); -} -int secd_76_idstransport(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - - tests(); - - return 0; -} diff --git a/keychain/securityd/Regressions/secd-80-views-alwayson.m b/keychain/securityd/Regressions/secd-80-views-alwayson.m index 57bc8d44..0d10cb5c 100644 --- a/keychain/securityd/Regressions/secd-80-views-alwayson.m +++ b/keychain/securityd/Regressions/secd-80-views-alwayson.m @@ -37,6 +37,7 @@ #include "secd_regressions.h" #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void testView(SOSAccount* account, SOSViewResultCode expected, CFStringRef view, SOSViewActionCode action, char *label) { CFErrorRef error = NULL; @@ -94,12 +95,18 @@ static void alwaysOnTest() SOSTestCleanup(); } +#endif int secd_80_views_alwayson(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(35); secd_test_clear_testviews(); secd_test_setup_temp_keychain(__FUNCTION__, NULL); alwaysOnTest(); + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-80-views-basic.m b/keychain/securityd/Regressions/secd-80-views-basic.m index db10961b..09ea8516 100644 --- a/keychain/securityd/Regressions/secd-80-views-basic.m +++ b/keychain/securityd/Regressions/secd-80-views-basic.m @@ -54,6 +54,7 @@ #include "keychain/securityd/SOSCloudCircleServer.h" #include "SecdTestKeychainUtilities.h" #include "SOSAccountTesting.h" +#if SOS_ENABLED static void testView(SOSAccount* account, SOSViewResultCode expected, CFStringRef view, SOSViewActionCode action, char *label) { @@ -143,10 +144,10 @@ static void tests(void) testView(account, kSOSCCViewNotMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected view capability for kSOSViewKeychainV0"); testView(account, kSOSCCViewMember, kSOSViewAppleTV, kSOSCCViewQuery, "Expected view capability for kSOSViewAppleTV"); - ok([account.trust updateViewSetsWithAnalytics:account enabled:SOSViewsGetV0ViewSet() disabled:nullSet parentEvent: NULL], "Expect not accepting kSOSKeychainV0"); + ok([account.trust updateViewSets:account enabled:SOSViewsGetV0ViewSet() disabled:nullSet], "Expect not accepting kSOSKeychainV0"); testView(account, kSOSCCViewNotMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected no addition of kSOSKeychainV0"); - ok([account.trust updateViewSetsWithAnalytics:account enabled:SOSViewsGetV0ViewSet() disabled:nullSet parentEvent: NULL], "Expect not accepting kSOSKeychainV0"); + ok([account.trust updateViewSets:account enabled:SOSViewsGetV0ViewSet() disabled:nullSet], "Expect not accepting kSOSKeychainV0"); testView(account, kSOSCCViewNotMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected no addition of kSOSKeychainV0"); SOSPeerInfoRef pi = account.peerInfo; @@ -155,10 +156,10 @@ static void tests(void) ok(vr == kSOSCCViewMember, "Set Virtual View manually"); - ok(![account.trust updateViewSetsWithAnalytics:account enabled:nullSet disabled:SOSViewsGetV0ViewSet() parentEvent: NULL], "Expect not removing kSOSKeychainV0"); + ok(![account.trust updateViewSets:account enabled:nullSet disabled:SOSViewsGetV0ViewSet()], "Expect not removing kSOSKeychainV0"); testView(account, kSOSCCViewMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected kSOSKeychainV0 is still there"); - ok(![account.trust updateViewSetsWithAnalytics:account enabled:nullSet disabled:SOSViewsGetV0ViewSet() parentEvent: NULL], "Expect not removing kSOSKeychainV0"); + ok(![account.trust updateViewSets:account enabled:nullSet disabled:SOSViewsGetV0ViewSet()], "Expect not removing kSOSKeychainV0"); testView(account, kSOSCCViewMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected kSOSKeychainV0 is still there"); SOSDataSourceRelease(test_source, NULL); @@ -166,15 +167,19 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_80_views_basic(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_clear_testviews(); testViewLists(); tests(); - + secd_test_teardown_delete_temp_keychain(__FUNCTION__); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-81-item-acl-stress.m b/keychain/securityd/Regressions/secd-81-item-acl-stress.m index 59d4d9a9..fa226314 100644 --- a/keychain/securityd/Regressions/secd-81-item-acl-stress.m +++ b/keychain/securityd/Regressions/secd-81-item-acl-stress.m @@ -361,6 +361,7 @@ int secd_81_item_acl_stress(int argc, char *const *argv) #if LA_CONTEXT_IMPLEMENTED SecItemServerResetKeychainKeybag(); #endif + secd_test_teardown_delete_temp_keychain(__FUNCTION__); return 0; } diff --git a/keychain/securityd/Regressions/secd-81-item-acl.m b/keychain/securityd/Regressions/secd-81-item-acl.m index 30eddba5..c8abadfe 100644 --- a/keychain/securityd/Regressions/secd-81-item-acl.m +++ b/keychain/securityd/Regressions/secd-81-item-acl.m @@ -465,6 +465,25 @@ static void item_with_skip_auth_ui(uint32_t *item_num) CFRelease(item); } +#if LA_CONTEXT_IMPLEMENTED +static void item_forbidden_delete(uint32_t *item_num) { + CFMutableDictionaryRef item = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecClass, kSecClassInternetPassword, NULL); + fillItem(item, (*item_num)++); + + SecAccessControlRef aclRef = SecAccessControlCreate(kCFAllocatorDefault, NULL); + ok(aclRef, "Create SecAccessControlRef"); + ok(SecAccessControlSetProtection(aclRef, kSecAttrAccessibleAlwaysPrivate, NULL)); + ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpEncrypt, kCFBooleanTrue, NULL)); + + CFDictionarySetValue(item, kSecAttrAccessControl, aclRef); + ok_status(SecItemAdd(item, NULL), "add undeletable"); + is_status(SecItemDelete(item), errSecAuthFailed, "delete local - authentication failed"); + + CFReleaseNull(aclRef); + CFRelease(item); +} +#endif + int secd_81_item_acl(int argc, char *const *argv) { uint32_t item_num = 1; @@ -479,15 +498,16 @@ int secd_81_item_acl(int argc, char *const *argv) SecItemServerSetKeychainKeybag(test_keybag); }); #if TARGET_OS_IPHONE - plan_tests(70); + plan_tests(75); #else - plan_tests(29); + plan_tests(34); #endif item_with_skip_auth_ui(&item_num); item_with_invalid_acl(&item_num); item_with_application_password(&item_num); item_with_acl_caused_maxauth(&item_num); item_with_akpu(&item_num); + item_forbidden_delete(&item_num); #else plan_tests(3); item_with_skip_auth_ui(&item_num); @@ -496,6 +516,7 @@ int secd_81_item_acl(int argc, char *const *argv) #if LA_CONTEXT_IMPLEMENTED SecItemServerResetKeychainKeybag(); #endif + secd_test_teardown_delete_temp_keychain(__FUNCTION__); return 0; } diff --git a/keychain/securityd/Regressions/secd-82-persistent-ref.m b/keychain/securityd/Regressions/secd-82-persistent-ref.m index 3d033767..f6cd1212 100644 --- a/keychain/securityd/Regressions/secd-82-persistent-ref.m +++ b/keychain/securityd/Regressions/secd-82-persistent-ref.m @@ -67,6 +67,7 @@ int secd_82_persistent_ref(int argc, char *const *argv) } CFReleaseNull( result ); + secd_test_teardown_delete_temp_keychain("secd_82_persistent_ref"); return 0; } diff --git a/keychain/securityd/Regressions/secd-83-item-match-policy.m b/keychain/securityd/Regressions/secd-83-item-match-policy.m index 76040252..e3a13dfe 100644 --- a/keychain/securityd/Regressions/secd-83-item-match-policy.m +++ b/keychain/securityd/Regressions/secd-83-item-match-policy.m @@ -230,5 +230,7 @@ int secd_83_item_match_policy(int argc, char *const *argv) test(returnKeyName); } + secd_test_teardown_delete_temp_keychain(__FUNCTION__); + return 0; } diff --git a/keychain/securityd/Regressions/secd-83-item-match-trusted.m b/keychain/securityd/Regressions/secd-83-item-match-trusted.m index 0231610b..c61b9e33 100644 --- a/keychain/securityd/Regressions/secd-83-item-match-trusted.m +++ b/keychain/securityd/Regressions/secd-83-item-match-trusted.m @@ -46,6 +46,8 @@ int secd_83_item_match_trusted(int argc, char *const *argv) for (id returnKeyName in returnKeyNames) test(returnKeyName); } + + secd_test_teardown_delete_temp_keychain(__FUNCTION__); return 0; } diff --git a/keychain/securityd/Regressions/secd-83-item-match-valid-on-date.m b/keychain/securityd/Regressions/secd-83-item-match-valid-on-date.m index 7922de7a..cac60523 100644 --- a/keychain/securityd/Regressions/secd-83-item-match-valid-on-date.m +++ b/keychain/securityd/Regressions/secd-83-item-match-valid-on-date.m @@ -64,5 +64,7 @@ int secd_83_item_match_valid_on_date(int argc, char *const *argv) test(returnKeyName); } + secd_test_teardown_delete_temp_keychain(__FUNCTION__); + return 0; } diff --git a/keychain/securityd/Regressions/secd-95-escrow-persistence.m b/keychain/securityd/Regressions/secd-95-escrow-persistence.m deleted file mode 100644 index 80c23aea..00000000 --- a/keychain/securityd/Regressions/secd-95-escrow-persistence.m +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include -#include - -#include - -#include "keychain/SecureObjectSync/SOSAccount.h" -#include -#include "keychain/SecureObjectSync/SOSInternal.h" -#include "keychain/SecureObjectSync/SOSUserKeygen.h" -#include "keychain/SecureObjectSync/SOSTransport.h" - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include -#include - -#include "keychain/securityd/SOSCloudCircleServer.h" - -#include "SOSAccountTesting.h" - -#include "SecdTestKeychainUtilities.h" - -static void tests(void) -{ - CFErrorRef error = NULL; - - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("TestSource")); - SOSAccount* bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), CFSTR("TestSource")); - - ok(SOSAccountAssertUserCredentialsAndUpdate(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); - - ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - CFReleaseNull(cfpassword); - CFReleaseNull(error); - - ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - ok(SOSAccountJoinCircles_wTxn(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicants %@ (%@)", applicants, error); - CFReleaseNull(error); - CFReleaseSafe(applicants); - } - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); - CFMutableStringRef timeDescription = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("[")); - CFAbsoluteTime currentTimeAndDate = CFAbsoluteTimeGetCurrent(); - - withStringOfAbsoluteTime(currentTimeAndDate, ^(CFStringRef decription) { - CFStringAppend(timeDescription, decription); - }); - CFStringAppend(timeDescription, CFSTR("]")); - - int tries = 5; - - CFNumberRef attempts = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &tries); - - CFMutableArrayRef escrowTimeAndTries = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFArrayAppendValue(escrowTimeAndTries, timeDescription); - CFArrayAppendValue(escrowTimeAndTries, attempts); - CFDictionaryRef escrowRecord = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("account label"), escrowTimeAndTries, NULL); - - CFMutableDictionaryRef record = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDictionaryAddValue(record, CFSTR("12345"), escrowRecord); - - SOSFullPeerInfoRef alice_fpi = alice_account.fullPeerInfo; - ok(SOSFullPeerInfoAddEscrowRecord(alice_fpi, CFSTR("12345"), escrowRecord, &error), "Adding Escrow records to Alice FPI(%@)", error); - CFDictionaryRef fpi_escrow = SOSPeerInfoCopyEscrowRecord(SOSFullPeerInfoGetPeerInfo(alice_fpi)); - ok(CFEqualSafe(CFDictionaryGetValue(fpi_escrow, CFSTR("12345")), escrowRecord), "Alice's FPI has escrow (%@)", error); - - ok(SOSAccountAddEscrowRecords(bob_account, CFSTR("12345"), escrowRecord, &error), "Adding escrow to Bob's account (%@)", error); - CFReleaseNull(fpi_escrow); - - fpi_escrow = (CFDictionaryRef)SOSAccountGetValue(bob_account, kSOSEscrowRecord, NULL); - ok(CFEqualSafe(CFDictionaryGetValue(fpi_escrow, CFSTR("12345")), escrowRecord), "Bob has escrow records in account (%@)", error); - ok(SOSAccountHasPublicKey(alice_account, &error), "Has Public Key" ); - - ok([alice_account.trust resetAccountToEmpty:alice_account transport:alice_account.circle_transport err:&error], "Reset to offering (%@)", error); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - ok(SOSAccountHasPublicKey(bob_account, &error), "Has Public Key" ); - - ok([bob_account.trust resetAccountToEmpty:bob_account transport:bob_account.circle_transport err:&error], "Reset to offering (%@)", error); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - ok(SOSAccountAddEscrowRecords(bob_account, CFSTR("12345"), escrowRecord, &error), "Adding escrow to Bob's account (%@)", error); - - ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Reset to offering (%@)", error); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - SOSAccountTrustClassic *bobTrust = bob_account.trust; - CFDictionaryRef bob_fpi_escrow = SOSPeerInfoCopyEscrowRecord(SOSFullPeerInfoGetPeerInfo(bobTrust.fullPeerInfo)); - ok(bob_fpi_escrow == NULL, "Bob's FPI escrow should be null"); - CFReleaseNull(bob_fpi_escrow); - - ok(SOSAccountJoinCircles_wTxn(bob_account, &error), "Bob Applies (%@)", error); - bob_fpi_escrow = SOSPeerInfoCopyEscrowRecord(SOSFullPeerInfoGetPeerInfo(bobTrust.fullPeerInfo)); - ok(bob_fpi_escrow && CFEqualSafe(CFDictionaryGetValue(bob_fpi_escrow, CFSTR("12345")), escrowRecord), "Bob has escrow records in account (%@)", error); - CFReleaseNull(bob_fpi_escrow); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicants %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Accept bob into the fold"); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates"); - - fpi_escrow = (CFDictionaryRef)SOSAccountGetValue(bob_account, kSOSEscrowRecord, NULL); - ok(isNull(fpi_escrow), "Bob's escrow records in the account object should be gone"); - - CFReleaseNull(record); - CFReleaseNull(escrowRecord); - CFReleaseNull(timeDescription); - CFReleaseNull(attempts); - SOSTestCleanup(); - -} - -int secd_95_escrow_persistence(int argc, char *const *argv) -{ - plan_tests(41); - - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - - tests(); - - return 0; -} diff --git a/keychain/securityd/Regressions/secd_77_ids_messaging.m b/keychain/securityd/Regressions/secd_77_ids_messaging.m deleted file mode 100644 index a23cdabb..00000000 --- a/keychain/securityd/Regressions/secd_77_ids_messaging.m +++ /dev/null @@ -1,296 +0,0 @@ -// -// secd_77_ids_messaging.c -// sec -// - -/* - * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include - -#include -#include "SecdTestKeychainUtilities.h" -#include "SOSAccountTesting.h" -#import "SOSTransportTestTransports.h" -#include "SOSTestDevice.h" -#include "SOSTestDataSource.h" -#include -#include - -static bool SOSAccountIsThisPeerIDMe(SOSAccount* account, CFStringRef peerID) { - SOSAccountTrustClassic* trust = account.trust; - SOSPeerInfoRef mypi = trust.peerInfo; - CFStringRef myPeerID = SOSPeerInfoGetPeerID(mypi); - - return myPeerID && CFEqualSafe(myPeerID, peerID); -} - -__unused static void ids_test_sync(SOSAccount* alice_account, SOSAccount* bob_account){ - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - __block bool SyncingCompletedOverIDS = false; - __block CFErrorRef localError = NULL; - __block bool done = false; - SOSAccountTrustClassic* aliceTrust = alice_account.trust; - SOSAccountTrustClassic* bobTrust = bob_account.trust; - - do{ - SOSCircleForEachValidPeer(aliceTrust.trustedCircle, alice_account.accountKey, ^(SOSPeerInfoRef peer) { - if (!SOSAccountIsThisPeerIDMe(alice_account, SOSPeerInfoGetPeerID(peer))) { - if(SOSPeerInfoShouldUseIDSTransport(aliceTrust.peerInfo, peer) && - SOSPeerInfoShouldUseIDSMessageFragmentation(aliceTrust.peerInfo, peer)){ - secnotice("IDS Transport","Syncing with IDS capable peers using IDS!"); - - CFMutableSetRef ids = CFSetCreateMutableForCFTypes(kCFAllocatorDefault); - CFSetAddValue(ids, SOSPeerInfoGetPeerID(peer)); - - SyncingCompletedOverIDS = [alice_account.ids_message_transport SOSTransportMessageSyncWithPeers:alice_account.ids_message_transport p:ids err:&localError]; - CFReleaseNull(ids); - } - } - }); - - ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL); - - SOSCircleForEachValidPeer(bobTrust.trustedCircle, bob_account.accountKey, ^(SOSPeerInfoRef peer) { - if (!SOSAccountIsThisPeerIDMe(bob_account, SOSPeerInfoGetPeerID(peer))) { - if(SOSPeerInfoShouldUseIDSTransport(bobTrust.peerInfo, peer) && - SOSPeerInfoShouldUseIDSMessageFragmentation(bobTrust.peerInfo, peer)){ - secnotice("IDS Transport","Syncing with IDS capable peers using IDS!"); - - CFMutableSetRef ids = CFSetCreateMutableForCFTypes(kCFAllocatorDefault); - CFSetAddValue(ids, SOSPeerInfoGetPeerID(peer)); - - SyncingCompletedOverIDS = [(SOSMessageIDSTest*)bob_account.ids_message_transport SOSTransportMessageSyncWithPeers:(SOSMessageIDSTest*)bob_account.ids_message_transport p:ids err:&localError]; - CFReleaseNull(ids); - } - } - }); - - ok(SyncingCompletedOverIDS, "synced items over IDS"); - if(CFDictionaryGetCount(SOSTransportMessageIDSTestGetChanges((SOSMessageIDSTest*)alice_account.ids_message_transport)) == 0 && CFDictionaryGetCount(SOSTransportMessageIDSTestGetChanges((SOSMessageIDSTest*)bob_account.ids_message_transport)) == 0){ - done = true; - break; - } - - ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL); - - }while(done == false); - CFReleaseNull(changes); -} - -static void tests() -{ - CFErrorRef error = NULL; - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - CFStringRef dsName = CFSTR("Test"); - - SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), dsName); - SOSAccount* bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), dsName); - - ok(SOSAccountAssertUserCredentialsAndUpdate(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); - - ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(cfpassword); - CFReleaseNull(error); - - ok(NULL != alice_account, "Alice Created"); - ok(NULL != bob_account, "Bob Created"); - - ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - ok(SOSAccountJoinCircles_wTxn(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates"); - - accounts_agree("bob&alice pair", bob_account, alice_account); - - CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); - ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); - CFReleaseNull(peers); - - //creating test devices - CFIndex version = 0; - - // Optionally prefix each peer with name to make them more unique. - CFArrayRef deviceIDs = CFArrayCreateForCFTypes(kCFAllocatorDefault,alice_account.peerID, bob_account.peerID, NULL); - CFSetRef views = SOSViewsCopyTestV2Default(); - CFMutableArrayRef peerMetas = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFStringRef deviceID; - CFArrayForEachC(deviceIDs, deviceID) { - SOSPeerMetaRef peerMeta = SOSPeerMetaCreateWithComponents(deviceID, views, NULL); - CFArrayAppendValue(peerMetas, peerMeta); - CFReleaseNull(peerMeta); - } - - CFReleaseNull(views); - CFArrayForEachC(deviceIDs, deviceID) { - SOSTestDeviceRef device = SOSTestDeviceCreateWithDbNamed(kCFAllocatorDefault, deviceID, deviceID); - SOSTestDeviceSetPeerIDs(device, peerMetas, version, NULL); - - if([alice_account.peerID isEqual: (__bridge id)(deviceID)]){ - alice_account.factory = device->dsf; - SOSTestDeviceAddGenericItem(device, CFSTR("Alice"), CFSTR("Alice-add")); - } - else{ - bob_account.factory = device->dsf; - SOSTestDeviceAddGenericItem(device, CFSTR("Bob"), CFSTR("Bob-add")); - } - - CFReleaseNull(device); - } - CFReleaseNull(deviceIDs); - CFReleaseNull(peerMetas); - - SOSUnregisterAllTransportMessages(); - CFArrayRemoveAllValues(message_transports); - - SOSAccountTrustClassic* aliceTrust = alice_account.trust; - SOSAccountTrustClassic* bobTrust = bob_account.trust; - - alice_account.ids_message_transport = (SOSMessageIDS*)[[SOSMessageIDSTest alloc] initWithAccount:alice_account andAccountName:CFSTR("Alice") andCircleName:SOSCircleGetName(aliceTrust.trustedCircle) err:&error ]; - - bob_account.ids_message_transport = (SOSMessageIDS*)[[SOSMessageIDSTest alloc] initWithAccount:bob_account andAccountName:CFSTR("Bob") andCircleName:SOSCircleGetName(bobTrust.trustedCircle) err:&error]; - - ok(alice_account.ids_message_transport != NULL, "Alice Account, Created IDS Test Transport"); - ok(bob_account.ids_message_transport != NULL, "Bob Account, Created IDS Test Transport"); - - bool result = [alice_account.trust modifyCircle:alice_account.circle_transport err:&error action:^bool(SOSCircleRef circle) { - CFErrorRef localError = NULL; - - SOSFullPeerInfoUpdateTransportType(aliceTrust.fullPeerInfo, SOSTransportMessageTypeIDSV2, &localError); - SOSFullPeerInfoUpdateTransportPreference(aliceTrust.fullPeerInfo, kCFBooleanFalse, &localError); - SOSFullPeerInfoUpdateTransportFragmentationPreference(aliceTrust.fullPeerInfo, kCFBooleanTrue, &localError); - SOSFullPeerInfoUpdateTransportAckModelPreference(aliceTrust.fullPeerInfo, kCFBooleanTrue, &localError); - - return SOSCircleHasPeer(circle, aliceTrust.peerInfo, NULL); - }]; - - ok(result, "Alice account update circle with transport type"); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - result = [bob_account.trust modifyCircle:bob_account.circle_transport err:&error action:^bool(SOSCircleRef circle) { - CFErrorRef localError = NULL; - - SOSFullPeerInfoUpdateTransportType(bobTrust.fullPeerInfo, SOSTransportMessageTypeIDSV2, &localError); - SOSFullPeerInfoUpdateTransportPreference(bobTrust.fullPeerInfo, kCFBooleanFalse, &localError); - SOSFullPeerInfoUpdateTransportFragmentationPreference(bobTrust.fullPeerInfo, kCFBooleanTrue, &localError); - SOSFullPeerInfoUpdateTransportAckModelPreference(bobTrust.fullPeerInfo, kCFBooleanTrue, &localError); - - return SOSCircleHasPeer(circle, bobTrust.peerInfo, NULL); - }]; - - ok(result, "Bob account update circle with transport type"); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - - CFStringRef alice_transportType =SOSPeerInfoCopyTransportType(alice_account.peerInfo); - CFStringRef bob_accountTransportType = SOSPeerInfoCopyTransportType(bob_account.peerInfo); - ok(CFEqualSafe(alice_transportType, CFSTR("IDS2.0")), "Alice transport type not IDS"); - ok(CFEqualSafe(bob_accountTransportType, CFSTR("IDS2.0")), "Bob transport type not IDS"); - - CFReleaseNull(alice_transportType); - CFReleaseNull(bob_accountTransportType); - - SOSTransportMessageIDSTestSetName((SOSMessageIDSTest*)alice_account.ids_message_transport, CFSTR("Alice Account")); - ok(SOSTransportMessageIDSTestGetName((SOSMessageIDSTest*)alice_account.ids_message_transport) != NULL, "retrieved getting account name"); - ok(SOSAccountRetrieveDeviceIDFromKeychainSyncingOverIDSProxy(alice_account, &error) != false, "device ID from KeychainSyncingOverIDSProxy"); - - SOSTransportMessageIDSTestSetName((SOSMessageIDSTest*)bob_account.ids_message_transport, CFSTR("Bob Account")); - ok(SOSTransportMessageIDSTestGetName((SOSMessageIDSTest*)bob_account.ids_message_transport) != NULL, "retrieved getting account name"); - ok(SOSAccountRetrieveDeviceIDFromKeychainSyncingOverIDSProxy(bob_account, &error) != false, "device ID from KeychainSyncingOverIDSProxy"); - - - ok(SOSAccountSetMyDSID_wTxn(alice_account, CFSTR("Alice"),&error), "Setting IDS device ID"); - CFStringRef alice_dsid = SOSAccountCopyDeviceID(alice_account, &error); - ok(CFEqualSafe(alice_dsid, CFSTR("Alice")), "Getting IDS device ID"); - - ok(SOSAccountSetMyDSID_wTxn(bob_account, CFSTR("Bob"),&error), "Setting IDS device ID"); - CFStringRef bob_dsid = SOSAccountCopyDeviceID(bob_account, &error); - ok(CFEqualSafe(bob_dsid, CFSTR("Bob")), "Getting IDS device ID"); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 3, "updates"); - - - ok(SOSAccountEnsurePeerRegistration(alice_account, NULL), "ensure peer registration - alice"); - - ok(SOSAccountEnsurePeerRegistration(bob_account, NULL), "ensure peer registration - bob"); - - - //ids_test_sync(alice_account, bob_account); - - CFReleaseNull(bob_dsid); - CFReleaseNull(alice_dsid); - CFReleaseNull(changes); - - SOSTestCleanup(); -} - -int secd_77_ids_messaging(int argc, char *const *argv) -{ - plan_tests(100); - - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - - tests(); - - return 0; -} diff --git a/keychain/securityd/Regressions/secd_regressions.h b/keychain/securityd/Regressions/secd_regressions.h index d3de4a06..7b5f983a 100644 --- a/keychain/securityd/Regressions/secd_regressions.h +++ b/keychain/securityd/Regressions/secd_regressions.h @@ -63,12 +63,13 @@ ONE_TEST(secd_64_circlereset) ONE_TEST(secd_65_account_retirement_reset) ONE_TEST(secd_66_account_recovery) ONE_TEST(secd_67_prefixedKeyIDs) +ONE_TEST(secd_68_fullPeerInfoIntegrity) ONE_TEST(secd_70_engine) ONE_TEST(secd_70_engine_corrupt) ONE_TEST(secd_70_engine_smash) ONE_TEST(secd_71_engine_save) -ONE_TEST(secd_68_ghosts) ONE_TEST(secd_155_otr_negotiation_monitor) +ONE_TEST(secd_231_v0Peers) DISABLED_ONE_TEST(secd_70_otr_remote) ONE_TEST(secd_74_engine_beer_servers) @@ -86,7 +87,6 @@ ONE_TEST(secd_82_persistent_ref) ONE_TEST(secd_83_item_match_policy) ONE_TEST(secd_83_item_match_valid_on_date) ONE_TEST(secd_83_item_match_trusted) -ONE_TEST(secd_95_escrow_persistence) ONE_TEST(secd_154_engine_backoff) ONE_TEST(secd_100_initialsync) ONE_TEST(secd_130_other_peer_views) diff --git a/keychain/securityd/SFKeychainControlManager.m b/keychain/securityd/SFKeychainControlManager.m index 89e1ae5c..ee4768c2 100644 --- a/keychain/securityd/SFKeychainControlManager.m +++ b/keychain/securityd/SFKeychainControlManager.m @@ -28,6 +28,7 @@ #import #import #import +#import NSString* kSecEntitlementKeychainControl = @"com.apple.private.keychain.keychaincontrol"; @@ -75,9 +76,11 @@ XPC_RETURNS_RETAINED xpc_endpoint_t SecServerCreateKeychainControlEndpoint(void) return NO; } + NSSet* errorClasses = [SecXPCHelper safeErrorClasses]; + NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(SFKeychainControl)]; - [interface setClass:[NSError class] forSelector:@selector(rpcFindCorruptedItemsWithReply:) argumentIndex:1 ofReply:YES]; - [interface setClass:[NSError class] forSelector:@selector(rpcDeleteCorruptedItemsWithReply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcFindCorruptedItemsWithReply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcDeleteCorruptedItemsWithReply:) argumentIndex:1 ofReply:YES]; newConnection.exportedInterface = interface; newConnection.exportedObject = self; [newConnection resume]; diff --git a/keychain/securityd/SFKeychainServer.m b/keychain/securityd/SFKeychainServer.m index fb9c07b2..c37085a1 100644 --- a/keychain/securityd/SFKeychainServer.m +++ b/keychain/securityd/SFKeychainServer.m @@ -37,6 +37,7 @@ #import "SecTask.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "SecEntitlements.h" +#import #import #import #import @@ -104,6 +105,16 @@ static NSString* const SFCredentialSecretPassword = @"password"; // wait a bit for shared function from SecurityFoundation to get to SDK, then addopt that NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(SFKeychainServerProtocol)]; + + NSSet *errorClasses = [SecXPCHelper safeErrorClasses]; + + [interface setClasses:errorClasses forSelector:@selector(rpcAddCredential:withAccessPolicy:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcFetchPasswordCredentialForPersistentIdentifier:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcLookupCredentialsForServiceIdentifiers:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcRemoveCredentialWithPersistentIdentifier:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcReplaceOldCredential:withNewCredential:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcReplaceCredential:withNewCredential:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:[NSSet setWithObjects:[NSArray class], [SFServiceIdentifier class], nil] forSelector:@selector(rpcLookupCredentialsForServiceIdentifiers:reply:) argumentIndex:0 ofReply:NO]; [interface setClasses:[NSSet setWithObjects:[NSArray class], [SFPasswordCredential class], nil] forSelector:@selector(rpcLookupCredentialsForServiceIdentifiers:reply:) argumentIndex:0 ofReply:YES]; newConnection.exportedInterface = interface; diff --git a/keychain/securityd/SOSCloudCircleServer.h b/keychain/securityd/SOSCloudCircleServer.h index 3adf34eb..1c249e86 100644 --- a/keychain/securityd/SOSCloudCircleServer.h +++ b/keychain/securityd/SOSCloudCircleServer.h @@ -35,35 +35,26 @@ __BEGIN_DECLS // // MARK: Server versions of our SPI // + bool SOSCCTryUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); bool SOSCCSetUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); bool SOSCCSetUserCredentialsAndDSID_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); -bool SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error); bool SOSCCCanAuthenticate_Server(CFErrorRef *error); bool SOSCCPurgeUserCredentials_Server(CFErrorRef *error); SOSCCStatus SOSCCThisDeviceIsInCircle_Server(CFErrorRef *error); bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error); -bool SOSCCRequestToJoinCircleWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error); -bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); bool SOSCCRemoveThisDeviceFromCircle_Server(CFErrorRef* error); -bool SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); bool SOSCCRemovePeersFromCircle_Server(CFArrayRef peers, CFErrorRef* error); -bool SOSCCRemovePeersFromCircleWithAnalytics_Server(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error); + +// This will async off the notification, so it does not return a value. +void SOSCCNotifyLoggedIntoAccount_Server(void); + bool SOSCCLoggedOutOfAccount_Server(CFErrorRef *error); bool SOSCCBailFromCircle_Server(uint64_t limit_in_seconds, CFErrorRef* error); -bool SOSCCRequestEnsureFreshParameters_Server(CFErrorRef* error); - - -bool SOSCCApplyToARing_Server(CFStringRef ringName, CFErrorRef *error); -bool SOSCCWithdrawlFromARing_Server(CFStringRef ringName, CFErrorRef *error); -SOSRingStatus SOSCCRingStatus_Server(CFStringRef ringName, CFErrorRef *error); -CF_RETURNS_RETAINED CFStringRef SOSCCGetAllTheRings_Server(CFErrorRef *error); -bool SOSCCEnableRing_Server(CFStringRef ringName, CFErrorRef *error); - CFArrayRef SOSCCCopyGenerationPeerInfo_Server(CFErrorRef* error); CFArrayRef SOSCCCopyApplicantPeerInfo_Server(CFErrorRef* error); @@ -81,20 +72,15 @@ CFArrayRef SOSCCCopyEngineState_Server(CFErrorRef* error); CFArrayRef SOSCCCopyPeerPeerInfo_Server(CFErrorRef* error); CFArrayRef SOSCCCopyConcurringPeerPeerInfo_Server(CFErrorRef* error); -bool SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(CFErrorRef *error); -bool SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(CFErrorRef *error); bool SOSCCAccountSetToNew_Server(CFErrorRef *error); bool SOSCCResetToOffering_Server(CFErrorRef* error); bool SOSCCResetToEmpty_Server(CFErrorRef* error); -bool SOSCCResetToEmptyWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); CFBooleanRef SOSCCPeersHaveViewsEnabled_Server(CFArrayRef viewNames, CFErrorRef *error); SOSViewResultCode SOSCCView_Server(CFStringRef view, SOSViewActionCode action, CFErrorRef *error); -bool SOSCCViewSetWithAnalytics_Server(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent); bool SOSCCViewSet_Server(CFSetRef enabledViews, CFSetRef disabledViews); -CFStringRef SOSCCCopyIncompatibilityInfo_Server(CFErrorRef* error); enum DepartureReason SOSCCGetLastDepartureReason_Server(CFErrorRef* error); bool SOSCCSetLastDepartureReason_Server(enum DepartureReason reason, CFErrorRef *error); @@ -107,13 +93,6 @@ SOSPeerInfoRef SOSCCSetNewPublicBackupKey_Server(CFDataRef newPublicBackup, CFEr bool SOSCCRegisterSingleRecoverySecret_Server(CFDataRef backupSlice, bool setupV0Only, CFErrorRef *error); bool SOSCCWaitForInitialSync_Server(CFErrorRef*); -bool SOSCCWaitForInitialSyncWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); -CFArrayRef SOSCCCopyYetToSyncViewsList_Server(CFErrorRef*); - -bool SOSWrapToBackupSliceKeyBagForView_Server(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error); - -SOSBackupSliceKeyBagRef SOSBackupSliceKeyBagForView(CFStringRef viewName, CFErrorRef* error); -CF_RETURNS_RETAINED CFDataRef SOSWrapToBackupSliceKeyBag(SOSBackupSliceKeyBagRef bskb, CFDataRef input, CFErrorRef* error); // // MARK: Internal kicks. @@ -147,11 +126,6 @@ CFTypeRef SOSKeychainAccountGetSharedAccount(void); void SOSCCSetGestalt_Server(CFStringRef name, CFStringRef version, CFStringRef model, CFStringRef serial); CFStringRef SOSCCCopyOSVersion(void); -CFDataRef SOSCCCopyAccountState_Server(CFErrorRef* error); -CFDataRef SOSCCCopyEngineData_Server(CFErrorRef* error); -bool SOSCCDeleteEngineState_Server(CFErrorRef* error); -bool SOSCCDeleteAccountState_Server(CFErrorRef* error); - // // MARK: Testing operations, dangerous to call in normal operation. @@ -168,13 +142,9 @@ extern CFStringRef kSOSPeerDataLabel; CFDataRef SOSItemCopy(CFStringRef label, CFErrorRef* error); bool SOSItemUpdateOrAdd(CFStringRef label, CFStringRef accessibility, CFDataRef data, CFErrorRef *error); -bool SOSCCSetEscrowRecord_Server(CFStringRef escrow_label, uint64_t tries, CFErrorRef *error); -CFDictionaryRef SOSCCCopyEscrowRecord_Server(CFErrorRef *error); bool SOSCCRegisterRecoveryPublicKey_Server(CFDataRef recovery_key, CFErrorRef *error); CFDataRef SOSCCCopyRecoveryPublicKey_Server(CFErrorRef *error); -CFDictionaryRef SOSCCCopyBackupInformation_Server(CFErrorRef *error); - SOSPeerInfoRef SOSCCCopyApplication_Server(CFErrorRef *error); CFDataRef SOSCCCopyCircleJoiningBlob_Server(SOSPeerInfoRef applicant, CFErrorRef *error); bool SOSCCJoinWithCircleJoiningBlob_Server(CFDataRef joiningBlob, PiggyBackProtocolVersion version, CFErrorRef *error); @@ -182,8 +152,6 @@ CFDataRef SOSCCCopyInitialSyncData_Server(uint32_t flags, CFErrorRef *error); bool SOSCCCleanupKVSKeys_Server(CFErrorRef *error); bool SOSCCAccountHasPublicKey_Server(CFErrorRef *error); -bool SOSCCAccountIsNew_Server(CFErrorRef *error); -bool SOSCCTestPopulateKVSWithBadKeys_Server(CFErrorRef *error); void sync_the_last_data_to_kvs(CFTypeRef account, bool waitForeverForSynchronization); @@ -201,10 +169,21 @@ void SOSCCPerformUpdateOfAllOctagonKeys(CFDataRef octagonSigningFullKey, CFDataR CFDataRef signingPublicKey, CFDataRef encryptionPublicKey, SecKeyRef octagonSigningPublicKeyRef, SecKeyRef octagonEncryptionPublicKeyRef, void (^action)(CFErrorRef error)); +void SOSCCPerformPreloadOfAllOctagonKeys(CFDataRef octagonSigningFullKey, CFDataRef octagonEncryptionFullKey, + SecKeyRef octagonSigningFullKeyRef, SecKeyRef octagonEncryptionFullKeyRef, + SecKeyRef octagonSigningPublicKeyRef, SecKeyRef octagonEncryptionPublicKeyRef, + void (^action)(CFErrorRef error)); + +bool SOSCCSetCKKS4AllStatus(bool status, CFErrorRef* error); void SOSCCResetOTRNegotiation_Server(CFStringRef peerid); void SOSCCPeerRateLimiterSendNextMessage_Server(CFStringRef peerid, CFStringRef accessGroup); +#if __OBJC2__ +bool SOSCCSaveOctagonKeysToKeychain(NSString* keyLabel, NSData* keyDataToSave, __unused int keySize, SecKeyRef octagonPublicKey, NSError** error); +void SOSCCEnsureAccessGroupOfKey(SecKeyRef publicKey, NSString* oldAgrp, NSString* newAgrp); +#endif + __END_DECLS #endif diff --git a/keychain/securityd/SOSCloudCircleServer.m b/keychain/securityd/SOSCloudCircleServer.m index 51bccb51..05a7b0b1 100644 --- a/keychain/securityd/SOSCloudCircleServer.m +++ b/keychain/securityd/SOSCloudCircleServer.m @@ -45,7 +45,6 @@ #include "keychain/SecureObjectSync/SOSInternal.h" #include "keychain/SecureObjectSync/SOSUserKeygen.h" #include "keychain/SecureObjectSync/SOSMessage.h" -#include "keychain/SecureObjectSync/SOSBackupInformation.h" #include "keychain/SecureObjectSync/SOSDataSource.h" #include "keychain/SecureObjectSync/SOSKVSKeys.h" #import "keychain/SecureObjectSync/SOSAccountTrustClassic.h" @@ -54,9 +53,9 @@ #import "keychain/SecureObjectSync/SOSAuthKitHelpers.h" #import "keychain/ot/OTManager.h" #import "keychain/SigninMetrics/OctagonSignPosts.h" -#import "NSError+UsefulConstructors.h" +#import "keychain/categories/NSError+UsefulConstructors.h" -#include +#import "utilities/SecCoreAnalytics.h" #include #include @@ -72,7 +71,6 @@ #include #include #include -#include #include #include @@ -225,7 +223,7 @@ exit: static SOSAccount* SOSKeychainAccountCreateSharedAccount(CFDictionaryRef our_gestalt) { - secdebug("account", "Created account"); + secdebug("account", "Create account for UID %d EUID %d", getuid(), geteuid()); CFDataRef savedAccount = SOSKeychainCopySavedAccountData(); SOSAccount* account = NULL; @@ -245,7 +243,7 @@ static SOSAccount* SOSKeychainAccountCreateSharedAccount(CFDictionaryRef our_ges if (account){ [account.trust updateGestalt:account newGestalt:our_gestalt]; } else { - secerror("Got error inflating account: %@", inflationError); + secnotice("account", "Got error inflating account: %@", inflationError); } } @@ -255,9 +253,8 @@ static SOSAccount* SOSKeychainAccountCreateSharedAccount(CFDictionaryRef our_ges account = SOSAccountCreate(kCFAllocatorDefault, our_gestalt, factory); if (!account) - secerror("Got NULL creating account"); + secnotice("account", "Got NULL creating account"); } - [account startStateMachine]; done: @@ -467,7 +464,7 @@ static SOSAccount* GetSharedAccount(bool onlyIfItExists) { dispatch_once(&onceToken, ^{ secdebug("account", "Account Creation start"); - CFDictionaryRef gestalt = CreateDeviceGestaltDictionaryAndRegisterForUpdate(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + CFDictionaryRef gestalt = CreateDeviceGestaltDictionaryAndRegisterForUpdate(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), NULL); if (!gestalt) { #if TARGET_OS_IPHONE && TARGET_OS_SIMULATOR @@ -497,7 +494,7 @@ static SOSAccount* GetSharedAccount(bool onlyIfItExists) { // TODO: Figure out why peer_additions isn't right in some cases (like when joining a v2 circle with a v0 peer. if (CFSetGetCount(peer_additions) != 0) { secnotice("updates", "Requesting Ensure Peer Registration."); - SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), NULL); } else { secinfo("updates", "Not requesting Ensure Peer Registration, since it's not needed"); } @@ -565,8 +562,9 @@ static SOSAccount* GetSharedAccount(bool onlyIfItExists) { secerror("Failed to transform account into data, error: %@", flattenFailError); } }; + // TODO: We should not be doing extra work whenever securityd is launched, let's see if we can eliminate this call - SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), NULL); // provide state handler to sysdiagnose and logging os_state_add_handler(dispatch_get_global_queue(0, 0), accountStateBlock); @@ -687,9 +685,20 @@ static bool do_with_account_while_unlocked(CFErrorRef *error, bool (^action)(SOS // Get ramp settings from the Cloud if(ghostbustnow) { gbOptions = [SOSAccount ghostBustGetRampSettings]; + gbOptions += SOSGhostBustiCloudIdentities; } } #endif + // Enforce MDM profile Restrictions + do_with_account(^(SOSAccountTransaction* txn) { + if(SOSVisibleKeychainNotAllowed()) { + SOSAccount *account = txn.account; + if([account isInCircle:(NULL)] && SOSPeerInfoV0ViewsEnabled(txn.account.peerInfo)) { + secnotice("views", "Cannot have visible keychain views due to profile restrictions"); + [txn.account.trust updateViewSets:txn.account enabled:nil disabled:SOSViewsGetV0ViewSet()]; + } + } + }); do_with_account(^(SOSAccountTransaction* txn) { SOSAccount *account = txn.account; @@ -705,8 +714,17 @@ static bool do_with_account_while_unlocked(CFErrorRef *error, bool (^action)(SOS [account ghostBustPeriodic:gbOptions complete:^(bool ghostBusted, NSError *error) { secnotice("ghostbust", "GhostBusting: %@", ghostBusted ? CFSTR("true"): CFSTR("false")); }]; + + [account removeV0Peers:^(bool removedV0Peers, NSError *error) { + if (!removedV0Peers || error) { + secnotice("removeV0Peers", "Did not remove any v0 peers, error: %@", error); + } else { + secnotice("removeV0Peers", "Removed v0 Peers"); + } + }]; } #endif + attempted_action = true; action_result = action(txn, error); }); @@ -819,22 +837,21 @@ SOSViewResultCode SOSCCView_Server(CFStringRef viewname, SOSViewActionCode actio return status; } -bool SOSCCViewSetWithAnalytics_Server(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent) { - __block bool status = false; +bool SOSCCViewSet_Server(CFSetRef enabledViews, CFSetRef disabledViews) { OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCViewSet); + __block bool status = false; do_with_account_if_after_first_unlock(NULL, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - status = [txn.account.trust updateViewSetsWithAnalytics:txn.account enabled:enabledViews disabled:disabledViews parentEvent:(__bridge NSData*)parentEvent]; + // Block enabling V0 views if managed preferences doesn't allow it. + if(SOSVisibleKeychainNotAllowed() && enabledViews && CFSetGetCount(enabledViews) && SOSViewSetIntersectsV0(enabledViews)) { + secnotice("views", "Cannot enable visible keychain views due to profile restrictions"); + return false; + } + status = [txn.account.trust updateViewSets:txn.account enabled:enabledViews disabled:disabledViews]; return true; }); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCViewSet, OctagonSignpostNumber1(SOSSignpostNameSOSCCViewSet), (int)status); - return status; -} - - -bool SOSCCViewSet_Server(CFSetRef enabledViews, CFSetRef disabledViews) { - return SOSCCViewSetWithAnalytics_Server(enabledViews, disabledViews, NULL); -} + return status;} void sync_the_last_data_to_kvs(CFTypeRef account, bool waitForeverForSynchronization){ @@ -845,7 +862,7 @@ void sync_the_last_data_to_kvs(CFTypeRef account, bool waitForeverForSynchroniza secnoticeq("force-push", "calling SOSCloudKeychainSynchronizeAndWait"); - SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { if (sync_error) { secerrorq("SOSCloudKeychainSynchronizeAndWait: %@", sync_error); localError = sync_error; @@ -878,7 +895,7 @@ static bool SyncKVSAndWait(CFErrorRef *error) { secnoticeq("fresh", "EFP calling SOSCloudKeychainSynchronizeAndWait"); os_activity_initiate("CloudCircle EFRESH", OS_ACTIVITY_FLAG_DEFAULT, ^(void) { - SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(__unused CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(__unused CFDictionaryRef returnedValues, CFErrorRef sync_error) { secnotice("fresh", "EFP returned, callback error: %@", sync_error); success = (sync_error == NULL); @@ -905,7 +922,7 @@ static bool Flush(CFErrorRef *error) { dispatch_semaphore_t wait_for = dispatch_semaphore_create(0); secnotice("flush", "Starting"); - SOSCloudKeychainFlush(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainFlush(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { success = (sync_error == NULL); if (error) { CFRetainAssign(*error, sync_error); @@ -924,131 +941,90 @@ static bool Flush(CFErrorRef *error) { } bool SOSCCTryUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) { + __block bool result = false; secnotice("updates", "Trying credentials and dsid (%@) for %@", dsid, user_label); - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCTryUserCredentials); + + dispatch_sync(SOSCCCredentialQueue(), ^{ + OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCTryUserCredentials); - bool result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - if (dsid != NULL && CFStringCompare(dsid, CFSTR(""), 0) != 0) { - SOSAccountAssertDSID(txn.account, dsid); + // Try the password with no EFRESH - attempting to get through this faster for rdar://problem/57242044 + result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + bool retval = false; + if (dsid != NULL && CFStringCompare(dsid, CFSTR(""), 0) != 0) { + SOSAccountAssertDSID(txn.account, dsid); + } + if(txn.account.accountKeyDerivationParameters) { + retval = SOSAccountTryUserCredentials(txn.account, user_label, user_password, block_error); + } + return retval; + }); + + // If that fails - either lacking parameters to begin with or failed to construct the correct key try with EFRESH + if(result == false) { + if(SyncKVSAndWait(error) && Flush(error)) { + result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) { + return SOSAccountTryUserCredentials(txn.account, user_label, user_password, block_error); + }); + } } - return true; + + // if either key constructions passed do a flush to bring through anything we weren't "interested" in before. + if(result) { + Flush(error); + } + OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCTryUserCredentials, OctagonSignpostNumber1(SOSSignpostNameSOSCCTryUserCredentials), (int)result); }); - - require_quiet(result, done); - - require_quiet(SyncKVSAndWait(error), done); // Make sure we've seen what the server has - require_quiet(Flush(error), done); // And processed it already...before asserting - - result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) { - return SOSAccountTryUserCredentials(txn.account, user_label, user_password, block_error); - }); - - require_quiet(result, done); - require_quiet(Flush(error), done); - -done: - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCTryUserCredentials, OctagonSignpostNumber1(SOSSignpostNameSOSCCTryUserCredentials), (int)result); - return result; } static bool SOSCCAssertUserCredentialsAndOptionalDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) { + __block bool result = false; secnotice("updates", "Setting credentials and dsid (%@) for %@", dsid, user_label); - - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameAssertUserCredentialsAndOptionalDSID); - - bool result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - if (dsid != NULL && CFStringCompare(dsid, CFSTR(""), 0) != 0) { - SOSAccountAssertDSID(txn.account, dsid); + + dispatch_sync(SOSCCCredentialQueue(), ^{ + OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameAssertUserCredentialsAndOptionalDSID); + + // Shortcut if we're talking to the same account and can construct the same trusted key + result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + bool retval = false; + CFStringRef accountDSID = SOSAccountGetValue(txn.account, kSOSDSIDKey, NULL); + if(CFEqualSafe(accountDSID, dsid) && txn.account.accountKeyDerivationParameters && txn.account.accountKeyIsTrusted) { + retval = SOSAccountTryUserCredentials(txn.account, user_label, user_password, block_error); + } + return retval; + }); + if(result) { + return; // shortcut to not do the following work if we're duping a setcreds operation. } - return true; - }); - require_quiet(result, done); + result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + if (dsid != NULL && CFStringCompare(dsid, CFSTR(""), 0) != 0) { + SOSAccountAssertDSID(txn.account, dsid); + } + return true; + }); - require_quiet(SyncKVSAndWait(error), done); // Make sure we've seen what the server has - require_quiet(Flush(error), done); // And processed it already...before asserting - - result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) { - return SOSAccountAssertUserCredentials(txn.account, user_label, user_password, block_error); - }); - - require_quiet(result, done); - require_quiet(Flush(error), done); // Process any incoming information..circles et.al. before fixing our signature - - result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - return SOSAccountGenerationSignatureUpdate(txn.account, error); - }); - - secnotice("updates", "Complete credentials and dsid (%@) for %@: %d %@", - dsid, user_label, result, error ? *error : NULL); -done: - OctagonSignpostEnd(signPost, SOSSignpostNameAssertUserCredentialsAndOptionalDSID, OctagonSignpostNumber1(SOSSignpostNameAssertUserCredentialsAndOptionalDSID), (int)result); - return result; -} - -static bool SOSCCAssertUserCredentialsAndOptionalDSIDWithAnalytics(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, NSData* parentEvent, CFErrorRef *error) { - secnotice("updates", "Setting credentials and dsid (%@) for %@", dsid, user_label); - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameAssertUserCredentialsAndOptionalDSID); - - NSError* localError = nil; - SFSignInAnalytics* parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - - SFSignInAnalytics *syncAndWaitEvent = nil; - SFSignInAnalytics *flushEvent = nil; - SFSignInAnalytics *secondFlushEvent = nil; - SFSignInAnalytics *generationSignatureUpdateEvent = nil; - - bool result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - if (dsid != NULL && CFStringCompare(dsid, CFSTR(""), 0) != 0) { - SOSAccountAssertDSID(txn.account, dsid); + if(result && SyncKVSAndWait(error) && Flush(error)) { + result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) { + return SOSAccountAssertUserCredentials(txn.account, user_label, user_password, block_error); + }); } - return true; + + // if either key constructions passed do a flush to bring through anything we weren't "interested" in before. + if(result) { + Flush(error); + } + + result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + return SOSAccountGenerationSignatureUpdate(txn.account, error); + }); + + secnotice("updates", "Complete credentials and dsid (%@) for %@: %d %@", + dsid, user_label, result, error ? *error : NULL); + + OctagonSignpostEnd(signPost, SOSSignpostNameAssertUserCredentialsAndOptionalDSID, OctagonSignpostNumber1(SOSSignpostNameAssertUserCredentialsAndOptionalDSID), (int)result); }); - require_quiet(result, done); - syncAndWaitEvent = [parent newSubTaskForEvent:@"syncAndWaitEvent"]; - require_quiet(SyncKVSAndWait(error), done); // Make sure we've seen what the server has - [syncAndWaitEvent stopWithAttributes:nil]; - - flushEvent = [parent newSubTaskForEvent:@"flushEvent"]; - require_quiet(Flush(error), done); // And processed it already...before asserting - [flushEvent stopWithAttributes:nil]; - - result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) { - return SOSAccountAssertUserCredentials(txn.account, user_label, user_password, block_error); - }); - - require_quiet(result, done); - secondFlushEvent = [parent newSubTaskForEvent:@"secondFlushEvent"]; - require_quiet(Flush(error), done); // Process any incoming information..circles et.al. before fixing our signature - [secondFlushEvent stopWithAttributes:nil]; - - generationSignatureUpdateEvent = [parent newSubTaskForEvent:@"generationSignatureUpdateEvent"]; - result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - return SOSAccountGenerationSignatureUpdate(txn.account, error); - }); - [generationSignatureUpdateEvent stopWithAttributes:nil]; - - -done: - if(syncAndWaitEvent){ - [syncAndWaitEvent stopWithAttributes:nil]; - } - if(flushEvent){ - [flushEvent stopWithAttributes:nil]; - } - if(secondFlushEvent){ - [secondFlushEvent stopWithAttributes:nil]; - } - if(generationSignatureUpdateEvent){ - [generationSignatureUpdateEvent stopWithAttributes:nil]; - } - secnotice("updates", "Complete credentials and dsid (%@) for %@: %d %@", - dsid, user_label, result, error ? *error : NULL); - - OctagonSignpostEnd(signPost, SOSSignpostNameAssertUserCredentialsAndOptionalDSID, OctagonSignpostNumber1(SOSSignpostNameAssertUserCredentialsAndOptionalDSID), (int)result); - return result; } @@ -1058,10 +1034,6 @@ bool SOSCCSetUserCredentialsAndDSID_Server(CFStringRef user_label, CFDataRef use return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, dsid, error); } -bool SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error) -{ - return SOSCCAssertUserCredentialsAndOptionalDSIDWithAnalytics(user_label, user_password, dsid, (__bridge NSData*)parentEvent, error); -} bool SOSCCSetUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error) { return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, NULL, error); @@ -1114,22 +1086,8 @@ bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error) __block bool result = true; OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRequestToJoinCircle); - bool joined = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - result = SOSAccountJoinCircles(txn, block_error); - return result; - }); - - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestToJoinCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestToJoinCircle), (int)joined); - return joined; -} - -bool SOSCCRequestToJoinCircleWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) -{ - __block bool result = true; - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRequestToJoinCircle); - bool requested = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - result = SOSAccountJoinCirclesWithAnalytics(txn, (__bridge NSData*)parentEvent, block_error); + result = SOSAccountJoinCircles(txn, block_error); return result; }); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestToJoinCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestToJoinCircle), (int)requested); @@ -1152,21 +1110,6 @@ bool SOSCCAccountHasPublicKey_Server(CFErrorRef *error) return hasPublicKey; } -bool SOSCCAccountIsNew_Server(CFErrorRef *error) -{ - __block bool result = true; - __block CFErrorRef localError = NULL; - - (void) do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - result = SOSAccountIsNew(txn.account, &localError); - return result; - }); - - if(error != NULL && localError != NULL) - *error = localError; - - return result; -} bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error) { __block bool result = true; @@ -1174,132 +1117,17 @@ bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error) OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore); returned = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { SOSAccountEnsurePeerRegistration(txn.account, block_error); + if(block_error && *block_error){ + NSError* blockError = (__bridge NSError*)*block_error; + if (blockError) { + secerror("ensure peer registration error: %@", blockError); + } + } result = SOSAccountJoinCirclesAfterRestore(txn, block_error); return result; }); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore), (int)result); return returned; - -} - -bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) -{ - __block bool result = true; - bool returned = false; - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore); - returned = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - NSError* localError = nil; - SFSignInAnalytics* parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:(__bridge NSData*)parentEvent error:&localError]; - - SFSignInAnalytics *ensurePeerRegistrationEvent = [parent newSubTaskForEvent:@"ensurePeerRegistrationEvent"]; - SOSAccountEnsurePeerRegistration(txn.account, block_error); - if(block_error && *block_error){ - NSError* blockError = (__bridge NSError*)*block_error; - if(blockError){ - [ensurePeerRegistrationEvent logRecoverableError:blockError]; - secerror("ensure peer registration error: %@", blockError); - } - } - [ensurePeerRegistrationEvent stopWithAttributes:nil]; - result = SOSAccountJoinCirclesAfterRestoreWithAnalytics(txn, (__bridge NSData*)parentEvent, block_error); - return result; - }); - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore), (int)result); - return returned; - -} - -bool SOSCCRequestEnsureFreshParameters_Server(CFErrorRef* error) -{ - bool returned = false; - returned = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - return SyncKVSAndWait(block_error); - }); - if (returned) { - returned = Flush(error); - } - return returned; -} - -bool SOSCCApplyToARing_Server(CFStringRef ringName, CFErrorRef *error){ - __block bool result = true; - bool returned = false; - returned = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - SOSFullPeerInfoRef fpi = txn.account.fullPeerInfo; - SOSRingRef ring = [txn.account.trust copyRing:ringName err:error]; - - if(fpi && ring) { - result = SOSRingApply(ring, txn.account.accountKey, fpi , error); - } - CFReleaseNull(ring); - return result; - }); - return returned; -} - -bool SOSCCWithdrawlFromARing_Server(CFStringRef ringName, CFErrorRef *error){ - __block bool result = true; - bool returned = false; - returned = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - SOSFullPeerInfoRef fpi = txn.account.fullPeerInfo; - SOSRingRef ring = [txn.account.trust copyRing:ringName err:error]; - if(fpi && ring) { - result = SOSRingWithdraw(ring, txn.account.accountKey, fpi , error); - } - CFReleaseNull(ring); - return result; - }); - return returned; -} - -bool SOSCCEnableRing_Server(CFStringRef ringName, CFErrorRef *error){ - __block bool result = true; - bool returned = false; - returned = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - SOSFullPeerInfoRef fpi = txn.account.fullPeerInfo; - SOSRingRef ring = [txn.account.trust copyRing:ringName err:error]; - if(fpi && ring) { - result = SOSRingResetToOffering(ring, NULL, fpi, error); - } - CFReleaseNull(ring); - return result; - }); - return returned; -} - -CFStringRef SOSCCGetAllTheRings_Server(CFErrorRef *error){ - __block CFMutableDictionaryRef result = NULL; - __block CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0); - - (void) do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *error) { - SOSAccountForEachRing(txn.account, ^SOSRingRef(CFStringRef name, SOSRingRef ring) { - CFStringAppendFormat(description, NULL, CFSTR("%@\n"), ring); - return NULL; - }); - if(result) - return true; - return false; - }); - - return description; -} - -SOSRingStatus SOSCCRingStatus_Server(CFStringRef ringName, CFErrorRef *error){ - __block bool result = true; - SOSRingStatus returned; - returned = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - SOSFullPeerInfoRef fpi = txn.account.fullPeerInfo; - SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(fpi); - - SOSRingRef ring = [txn.account.trust copyRing:ringName err:error]; - if(myPeer && ring) { - result = SOSRingDeviceIsInRing(ring, SOSPeerInfoGetPeerID(myPeer)); - } - CFReleaseNull(ring); - - return result; - }); - return returned; } bool SOSCCAccountSetToNew_Server(CFErrorRef *error) @@ -1345,36 +1173,6 @@ bool SOSCCResetToEmpty_Server(CFErrorRef* error) return resetResult; } -bool SOSCCResetToEmptyWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) -{ - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCResetToEmpty); - - bool resetResult = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - bool result = false; - - if (!SOSAccountHasPublicKey(txn.account, error)) { - return result; - } - result = [txn.account.trust resetAccountToEmptyWithAnalytics:txn.account transport:txn.account.circle_transport parentEvent:(__bridge NSData*)parentEvent err:block_error]; - return result; - }); - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCResetToEmpty, OctagonSignpostNumber1(SOSSignpostNameSOSCCResetToEmpty), (int)resetResult); - return resetResult; -} - -bool SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) -{ - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRemoveThisDeviceFromCircle); - - bool removeResult = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - bool result = [txn.account.trust leaveCircleWithAccount:txn.account withAnalytics:(__bridge NSData*)parentEvent err:error]; - return result; - }); - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRemoveThisDeviceFromCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRemoveThisDeviceFromCircle), (int)removeResult); - - return removeResult; -} - bool SOSCCRemoveThisDeviceFromCircle_Server(CFErrorRef* error) { OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRemoveThisDeviceFromCircle); @@ -1399,16 +1197,22 @@ bool SOSCCRemovePeersFromCircle_Server(CFArrayRef peers, CFErrorRef* error) return removeResult; } -bool SOSCCRemovePeersFromCircleWithAnalytics_Server(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error) -{ - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRemovePeersFromCircle); +void SOSCCNotifyLoggedIntoAccount_Server() { + // This call is mixed in with SOSCCSetUserCredentialsAndDSID calls from our accountsd plugin + dispatch_async(SOSCCCredentialQueue(), ^{ + CFErrorRef error = NULL; + bool loggedInResult = do_with_account_while_unlocked(&error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + secinfo("circleOps", "Signed into account!"); + txn.account.accountIsChanging = false; // we've changed + return true; + }); - bool removeResult = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - bool result = SOSAccountRemovePeersFromCircleWithAnalytics(txn.account, peers, (__bridge NSData*)parentEvent, block_error); - return result; + if(!loggedInResult || error != NULL) { + secerror("circleOps: error delivering account-sign-in notification: %@", error); + } + + CFReleaseNull(error); }); - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRemovePeersFromCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRemovePeersFromCircle), (int)removeResult); - return removeResult; } bool SOSCCLoggedOutOfAccount_Server(CFErrorRef *error) @@ -1428,7 +1232,7 @@ bool SOSCCLoggedOutOfAccount_Server(CFErrorRef *error) sync_the_last_data_to_kvs((__bridge CFTypeRef)(txn.account), waitForeverForSynchronization); SOSAccountSetToNew(txn.account); - + txn.account.accountIsChanging = true; return result; }); @@ -1440,7 +1244,7 @@ bool SOSCCBailFromCircle_Server(uint64_t limit_in_seconds, CFErrorRef* error) { return do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { bool waitForeverForSynchronization = false; - + bool result = SOSAccountBail(txn.account, limit_in_seconds, block_error); [txn restart]; // Make sure this gets finished before we set to new. @@ -1591,99 +1395,6 @@ static uint64_t initialSyncTimeoutFromDefaultsWrite(void) return timeout; } -bool SOSCCWaitForInitialSyncWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) { - __block dispatch_semaphore_t inSyncSema = NULL; - __block bool result = false; - __block bool synced = false; - bool timed_out = false; - __block CFStringRef inSyncCallID = NULL; - __block time_t start; - __block CFBooleanRef shouldUseInitialSyncV0 = false; - SFSignInAnalytics* syncingEvent = nil; - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCWaitForInitialSync); - - NSError* localError = nil; - SFSignInAnalytics* parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:(__bridge NSData*)parentEvent error:&localError]; - - secnotice("initial sync", "Wait for initial sync start!"); - - result = do_with_account_if_after_first_unlock(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - shouldUseInitialSyncV0 = (CFBooleanRef)SOSAccountGetValue(txn.account, kSOSInitialSyncTimeoutV0, error); - bool alreadyInSync = (SOSAccountHasCompletedInitialSync(txn.account)); - - if (!alreadyInSync) { - start = time(NULL); - inSyncSema = dispatch_semaphore_create(0); - - SFSignInAnalytics* callWhenInSyncEvent = [parent newSubTaskForEvent:@"callWhenInSync"]; - inSyncCallID = SOSAccountCallWhenInSync(txn.account, ^bool(SOSAccount* mightBeSynced) { - synced = true; - - if(inSyncSema){ - dispatch_semaphore_signal(inSyncSema); - NSDictionary* attributes = @{@"finishedSyncing" : @YES}; - [syncingEvent stopWithAttributes:attributes]; - } - return true; - }); - NSDictionary* attributes = @{}; - [callWhenInSyncEvent stopWithAttributes:attributes]; - } - else{ - synced = true; - } - return true; - }); - - require_quiet(result, fail); - - - if(inSyncSema){ - syncingEvent = [parent newSubTaskForEvent:@"initialSyncEvent"]; - if(shouldUseInitialSyncV0){ - secnotice("piggy","setting initial sync timeout to 5 minutes"); - timed_out = dispatch_semaphore_wait(inSyncSema, dispatch_time(DISPATCH_TIME_NOW, 300ull * NSEC_PER_SEC)); - } - else{ - uint64_t timeoutFromDefaultsWrite = initialSyncTimeoutFromDefaultsWrite(); - secnotice("piggy","setting initial sync timeout to %llu seconds", timeoutFromDefaultsWrite); - timed_out = dispatch_semaphore_wait(inSyncSema, dispatch_time(DISPATCH_TIME_NOW, timeoutFromDefaultsWrite * NSEC_PER_SEC)); - } - } - if (timed_out && shouldUseInitialSyncV0) { - do_with_account(^(SOSAccountTransaction* txn) { - if (SOSAccountUnregisterCallWhenInSync(txn.account, inSyncCallID)) { - if(inSyncSema){ - inSyncSema = NULL; // We've canceled the timeout so we must be the last. - } - } - }); - NSError* error = [NSError errorWithDomain:@"securityd" code:errSecTimedOut userInfo:@{NSLocalizedDescriptionKey: @"timed out waiting for initial sync"}]; - [syncingEvent logUnrecoverableError:error]; - NSDictionary* attributes = @{@"finishedSyncing" : @NO, @"legacyPiggybacking" : @YES}; - [syncingEvent stopWithAttributes:attributes]; - } - - require_quiet(result, fail); - - if(result) - { - SecADClientPushValueForDistributionKey(SOSAggdSyncCompletionKey, getTimeDifference(start)); - } - else if(!result) - { - SecADAddValueForScalarKey(SOSAggdSyncTimeoutKey, 1); - } - - secnotice("initial sync", "Finished!: %d", result); - -fail: - CFReleaseNull(inSyncCallID); - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCWaitForInitialSync, OctagonSignpostNumber1(SOSSignpostNameSOSCCWaitForInitialSync), (int)result); - - return result; -} - bool SOSCCWaitForInitialSync_Server(CFErrorRef* error) { __block dispatch_semaphore_t inSyncSema = NULL; @@ -1743,18 +1454,14 @@ bool SOSCCWaitForInitialSync_Server(CFErrorRef* error) { } }); } - - require_quiet(result, fail); - if(result) - { - SecADClientPushValueForDistributionKey(SOSAggdSyncCompletionKey, getTimeDifference(start)); + if(result) { + [SecCoreAnalytics sendEvent:(__bridge id)SOSAggdSyncCompletionKey + event:@{SecCoreAnalyticsValue: [NSNumber numberWithLong:getTimeDifference(start)]}]; + } else { + [SecCoreAnalytics sendEvent:(__bridge id)SOSAggdSyncTimeoutKey + event:@{SecCoreAnalyticsValue: @1}]; } - else if(!result) - { - SecADAddValueForScalarKey(SOSAggdSyncTimeoutKey, 1); - } - secnotice("initial sync", "Finished!: %d", result); fail: @@ -1764,220 +1471,6 @@ fail: return result; } - -static CFArrayRef SOSAccountCopyYetToSyncViews(SOSAccount* account, CFErrorRef *error) { - __block CFArrayRef result = NULL; - - CFTypeRef valueFetched = SOSAccountGetValue(account, kSOSUnsyncedViewsKey, error); - if (valueFetched == kCFBooleanTrue) { - SOSPeerInfoRef myPI = account.peerInfo; - if (myPI) { - SOSPeerInfoWithEnabledViewSet(myPI, ^(CFSetRef enabled) { - result = CFSetCopyValues(enabled); - }); - } - } else if (isSet(valueFetched)) { - result = CFSetCopyValues((CFSetRef)valueFetched); - } - - if (result == NULL) { - result = CFArrayCreateForCFTypes(kCFAllocatorDefault, NULL); - } - - return result; -} - -CFArrayRef SOSCCCopyYetToSyncViewsList_Server(CFErrorRef* error) { - - __block CFArrayRef views = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - views = SOSAccountCopyYetToSyncViews(txn.account, error); - - return true; - }); - - return views; -} - -bool SOSWrapToBackupSliceKeyBagForView_Server(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error) { - CFErrorRef localerror = NULL; - SOSBackupSliceKeyBagRef bskb = SOSBackupSliceKeyBagForView(viewName, &localerror); - - if(bskbEncoded && bskb) { - *bskbEncoded = SOSBSKBCopyEncoded(bskb, &localerror); - } - - if(output) { - *output = SOSWrapToBackupSliceKeyBag(bskb, input, &localerror); - } - - if(error) { - *error = localerror; - } - return localerror == NULL; -} - -SOSBackupSliceKeyBagRef SOSBackupSliceKeyBagForView(CFStringRef viewName, CFErrorRef* error){ - __block SOSBackupSliceKeyBagRef bskb = NULL; - (void) do_with_account(^ (SOSAccountTransaction* txn) { - bskb = SOSAccountBackupSliceKeyBagForView(txn.account, viewName, error); - }); - return bskb; -} - -CFDataRef SOSWrapToBackupSliceKeyBag(SOSBackupSliceKeyBagRef bskb, CFDataRef input, CFErrorRef* error) { - CFDataRef encrypted = NULL; - bskb_keybag_handle_t bskb_handle = 0; - - require_quiet(bskb, exit); - - bskb_handle = SOSBSKBLoadLocked(bskb, error); - require_quiet(bskb_handle, exit); - - SecAccessControlRef access = NULL; - require_quiet(access = SecAccessControlCreate(kCFAllocatorDefault, error), exit); - require_quiet(SecAccessControlSetProtection(access, kSecAttrAccessibleWhenUnlocked, error), exit); - - // ks_encrypt_data takes a dictionary as its plaintext. - CFMutableDictionaryRef plaintext = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionarySetValue(plaintext, CFSTR("data"), input); - - require_quiet(ks_encrypt_data_legacy(bskb_handle, access, NULL, plaintext, NULL, &encrypted, false, error), exit); - -exit: - CFReleaseNull(bskb); - if(bskb_handle != 0) { - ks_close_keybag(bskb_handle, error); - } - if(error && *error) { - secnotice("backup", "Failed to wrap to a BKSB: %@", *error); - } - return encrypted; - -} - -CFDictionaryRef SOSCCCopyEscrowRecord_Server(CFErrorRef *error){ - - __block CFDictionaryRef result = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *error) { - CFErrorRef localError = NULL; - SOSCCStatus status = [txn.account getCircleStatus:&localError]; - - CFStringRef dsid = SOSAccountGetValue(txn.account, kSOSDSIDKey, error); - CFDictionaryRef escrowRecords = NULL; - CFDictionaryRef record = NULL; - switch(status) { - case kSOSCCInCircle: - //get the escrow record in the peer info! - escrowRecords = SOSPeerInfoCopyEscrowRecord(txn.account.peerInfo); - if(escrowRecords){ - record = CFDictionaryGetValue(escrowRecords, dsid); - if(record) - result = CFRetainSafe(record); - } - CFReleaseNull(escrowRecords); - break; - case kSOSCCRequestPending: - //set the escrow record in the peer info/application? - break; - case kSOSCCNotInCircle: - case kSOSCCCircleAbsent: - //set the escrow record in the account expansion! - escrowRecords = SOSAccountGetValue(txn.account, kSOSEscrowRecord, error); - if(escrowRecords){ - record = CFDictionaryGetValue(escrowRecords, dsid); - if(record) - result = CFRetainSafe(record); - } - break; - default: - secdebug("account", "no circle status!"); - break; - } - return true; - }); - - return result; -} - -CFDictionaryRef SOSCCCopyBackupInformation_Server(CFErrorRef *error) { - __block CFDictionaryRef result = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *error) { - result = SOSBackupInformation(txn, error); - return true; - }); - return result; -} - -bool SOSCCSetEscrowRecord_Server(CFStringRef escrow_label, uint64_t tries, CFErrorRef *error){ - - if (escrow_label == NULL) { - return false; - } - - __block bool result = true; - __block CFErrorRef block_error = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *error) { - SOSCCStatus status = [txn.account getCircleStatus:&block_error]; - - CFStringRef dsid = SOSAccountGetValue(txn.account, kSOSDSIDKey, error); - - CFMutableStringRef timeDescription = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("[")); - CFAbsoluteTime currentTimeAndDate = CFAbsoluteTimeGetCurrent(); - - withStringOfAbsoluteTime(currentTimeAndDate, ^(CFStringRef decription) { - CFStringAppend(timeDescription, decription); - }); - CFStringAppend(timeDescription, CFSTR("]")); - - CFNumberRef attempts = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, (const void*)&tries); - - CFMutableDictionaryRef escrowTimeAndTries = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDictionaryAddValue(escrowTimeAndTries, kSOSBurnedRecoveryAttemptCount, attempts); - CFDictionaryAddValue(escrowTimeAndTries, kSOSBurnedRecoveryAttemptAttestationDate, timeDescription); - - CFMutableDictionaryRef escrowRecord = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDictionaryAddValue(escrowRecord, escrow_label, escrowTimeAndTries); - - switch(status) { - case kSOSCCInCircle: - //set the escrow record in the peer info! - if(!SOSFullPeerInfoAddEscrowRecord(txn.account.fullPeerInfo, dsid, escrowRecord, error)){ - secdebug("accout", "Could not set escrow record in the full peer info"); - result = false; - } - break; - case kSOSCCRequestPending: - //set the escrow record in the peer info/application? - break; - case kSOSCCNotInCircle: - case kSOSCCCircleAbsent: - //set the escrow record in the account expansion! - - if(!SOSAccountAddEscrowRecords(txn.account, dsid, escrowRecord, error)) { - secdebug("account", "Could not set escrow record in expansion data"); - result = false; - } - break; - default: - secdebug("account", "no circle status!"); - break; - } - CFReleaseNull(attempts); - CFReleaseNull(timeDescription); - CFReleaseNull(escrowTimeAndTries); - CFReleaseNull(escrowRecord); - - return true; - }); - - return result; -} - bool SOSCCAcceptApplicants_Server(CFArrayRef applicants, CFErrorRef* error) { OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCAcceptApplicants); @@ -2043,60 +1536,6 @@ SOSPeerInfoRef SOSCCCopyMyPeerInfo_Server(CFErrorRef* error) return result; } -CFDataRef SOSCCCopyAccountState_Server(CFErrorRef* error) -{ - __block CFDataRef accountState = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - // Copy account state from the keychain - accountState = SOSAccountCopyAccountStateFromKeychain(block_error); - return accountState != NULL; - }); - - return accountState; -} - -bool SOSCCDeleteAccountState_Server(CFErrorRef* error) -{ - __block bool result = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - // Delete account state from the keychain - result = SOSAccountDeleteAccountStateFromKeychain(block_error); - return result; - }); - - return result; -} - -CFDataRef SOSCCCopyEngineData_Server(CFErrorRef* error) -{ - __block CFDataRef engineState = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - // Copy engine state from the keychain - engineState = SOSAccountCopyEngineStateFromKeychain(block_error); - return engineState != NULL; - }); - - return engineState; -} - -bool SOSCCDeleteEngineState_Server(CFErrorRef* error) -{ - __block bool result = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - // Delete engine state from the keychain - result = SOSAccountDeleteEngineStateFromKeychain(block_error); - return result; - }); - - return result; -} - - - SOSPeerInfoRef SOSCCSetNewPublicBackupKey_Server(CFDataRef newPublicBackup, CFErrorRef *error){ __block SOSPeerInfoRef result = NULL; OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCSetNewPublicBackupKey); @@ -2134,25 +1573,6 @@ bool SOSCCRegisterSingleRecoverySecret_Server(CFDataRef aks_bag, bool setupV0Onl return registerResult; } -CFStringRef SOSCCCopyIncompatibilityInfo_Server(CFErrorRef* error) -{ - __block CFStringRef result = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - result = SOSAccountCopyIncompatibilityInfo(txn.account, block_error); - return result != NULL; - }); - - return result; -} - -bool SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(CFErrorRef *error) { - bool result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - return SOSAccountIsLastBackupPeer(txn.account, block_error); - }); - return result; -} - enum DepartureReason SOSCCGetLastDepartureReason_Server(CFErrorRef* error) { __block enum DepartureReason result = kSOSDepartureReasonError; @@ -2185,20 +1605,87 @@ bool SOSCCProcessEnsurePeerRegistration_Server(CFErrorRef* error) return processResult; } -CF_RETURNS_RETAINED CFSetRef SOSCCProcessSyncWithPeers_Server(CFSetRef peers, CFSetRef backupPeers, CFErrorRef *error) { - __block CFSetRef result = NULL; - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCProcessSyncWithPeers); +static bool internalSyncWithPeers(CFSetRef peers, CFSetRef backupPeers, CFMutableSetRef handled, CFErrorRef *error) { + return do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *error) { + CFSetRef addedResult = SOSAccountProcessSyncWithPeers(txn, peers, backupPeers, error); + CFSetUnion(handled, addedResult); + bool retval = (addedResult != NULL); + CFReleaseNull(addedResult); + return retval; + }); +} - if (!do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *error) { - result = SOSAccountProcessSyncWithPeers(txn, peers, backupPeers, error); - return result != NULL; - })) { - // Be sure we don't return a result if we got an error - CFReleaseNull(result); +#define MAXPEERS 7 + +static bool SOSCFSubsetOfN(CFSetRef peers, size_t n, CFErrorRef* error, bool (^action)(CFSetRef subset, CFErrorRef* error)) { + __block bool retval = true; + __block size_t ready = 0; + __block CFMutableSetRef subset = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); + + CFSetForEach(peers, ^(const void *value) { + CFSetAddValue(subset, value); + ready++; + if(ready >= n) { + retval &= action(subset, error); + ready = 0; + CFSetRemoveAllValues(subset); + } + }); + if(CFSetGetCount(subset)) { + retval &= action(subset, error); } - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCProcessSyncWithPeers, OctagonSignpostNumber1(SOSSignpostNameSOSCCProcessSyncWithPeers), (int)(result != NULL)); + CFReleaseNull(subset); + return retval; +} - return result; +CF_RETURNS_RETAINED CFSetRef SOSCCProcessSyncWithPeers_Server(CFSetRef peers, CFSetRef backupPeers, CFErrorRef *error) { + static dispatch_queue_t swpQueue = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + swpQueue = dispatch_queue_create("syncWithPeers", DISPATCH_QUEUE_SERIAL); + }); + + __block CFMutableSetRef handled = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); + __block CFSetRef noPeers = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); + + if(!peers) { + peers = noPeers; + } + + if(!backupPeers) { + backupPeers = noPeers; + } + + dispatch_sync(swpQueue, ^{ + OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCProcessSyncWithPeers); + + if((CFSetGetCount(peers) + CFSetGetCount(backupPeers)) < MAXPEERS) { + internalSyncWithPeers(peers, backupPeers, handled, error); + } else { + // sync any backupPeers + if(backupPeers && CFSetGetCount(backupPeers)) { + SOSCFSubsetOfN(backupPeers, MAXPEERS, error, ^bool(CFSetRef subset, CFErrorRef *error) { + return internalSyncWithPeers(noPeers, subset, handled, error); + }); + } + + // sync any device peers + if(peers && CFSetGetCount(peers)) { + SOSCFSubsetOfN(peers, MAXPEERS, error, ^bool(CFSetRef subset, CFErrorRef *error) { + return internalSyncWithPeers(subset, noPeers, handled, error); + }); + } + } + + OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCProcessSyncWithPeers, OctagonSignpostNumber1(SOSSignpostNameSOSCCProcessSyncWithPeers), (int)(CFSetGetCount(handled) != 0)); + + if(CFSetGetCount(handled) == 0) { + CFReleaseNull(handled); + } + CFReleaseNull(noPeers); + }); + + return handled; } SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers_Server(CFErrorRef* error) @@ -2275,7 +1762,7 @@ void SOSCCRequestSyncWithPeersList(CFArrayRef /*CFStringRef*/ peerIDs) { }); SOSCloudKeychainRequestSyncWithPeers(peerIDs, empty, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + dispatch_get_global_queue(SOS_ENGINE_PRIORITY, 0), NULL); CFReleaseNull(empty); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestSyncWithPeersList, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestSyncWithPeersList), (int)true); }); @@ -2292,7 +1779,7 @@ void SOSCCRequestSyncWithBackupPeerList(CFArrayRef /* CFStringRef */ backupPeerI }); SOSCloudKeychainRequestSyncWithPeers(empty, backupPeerIDs, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + dispatch_get_global_queue(SOS_ENGINE_PRIORITY, 0), NULL); CFReleaseNull(empty); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestSyncWithBackupPeerList, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestSyncWithBackupPeerList), (int)true); @@ -2308,7 +1795,7 @@ void SOSCCEnsurePeerRegistration(void) { os_activity_initiate("CloudCircle EnsurePeerRegistration", OS_ACTIVITY_FLAG_DEFAULT, ^(void) { OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCEnsurePeerRegistration); - SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(SOS_ENGINE_PRIORITY, 0), NULL); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCEnsurePeerRegistration, OctagonSignpostNumber1(SOSSignpostNameSOSCCEnsurePeerRegistration), (int)true); }); @@ -2351,14 +1838,6 @@ bool SOSCCCleanupKVSKeys_Server(CFErrorRef *error) { return result; } -bool SOSCCTestPopulateKVSWithBadKeys_Server(CFErrorRef *error) -{ - __block bool result = false; - do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *error) { - return SOSAccountPopulateKVSWithBadKeys(txn.account, error); - }); - return result; -} CFDataRef SOSCCCopyCircleJoiningBlob_Server(SOSPeerInfoRef applicant, CFErrorRef *error) { __block CFDataRef pbblob = NULL; OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCCopyCircleJoiningBlob); @@ -2575,28 +2054,23 @@ void SOSCCPerformWithAllOctagonKeys(void (^action)(SecKeyRef octagonEncryptionKe CFReleaseNull(localError); } -static bool saveOctagonKeysToKeychain(NSString* keyLabel, NSData* keyDataToSave, int keySize, SecKeyRef octagonPublicKey, NSError** error) { +bool SOSCCSaveOctagonKeysToKeychain(NSString* keyLabel, NSData* keyDataToSave, __unused int keySize, SecKeyRef octagonPublicKey, NSError** error) { NSError* localerror = nil; - CFDataRef publicKeyHash = SecKeyCopyPublicKeyHash(octagonPublicKey); - NSMutableDictionary* query = [@{ - (id)kSecClass : (id)kSecClassKey, - (id)kSecAttrKeyType : (id)kSecAttrKeyTypeEC, - (id)kSecAttrKeyClass : (id)kSecAttrKeyClassPrivate, - (id)kSecAttrAccessGroup : (id)kSOSInternalAccessGroup, - (id)kSecAttrLabel : keyLabel, - (id)kSecAttrApplicationLabel : (__bridge NSData*)(publicKeyHash), - (id)kSecAttrSynchronizable : (id)kCFBooleanFalse, - (id)kSecUseDataProtectionKeychain : @YES, - (id)kSecValueData : keyDataToSave, - } mutableCopy]; + NSMutableDictionary* query = [((NSDictionary*)CFBridgingRelease(SecKeyGeneratePrivateAttributeDictionary(octagonPublicKey, + kSecAttrKeyTypeEC, + (__bridge CFDataRef)keyDataToSave))) mutableCopy]; + + query[(id)kSecAttrLabel] = keyLabel; + query[(id)kSecUseDataProtectionKeychain] = @YES; + query[(id)kSecAttrSynchronizable] = (id)kCFBooleanFalse; + query[(id)kSecAttrAccessGroup] = (id)kSOSInternalAccessGroup; CFTypeRef result = NULL; OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, &result); if(status == errSecSuccess) { - CFReleaseNull(publicKeyHash); return true; } if(status == errSecDuplicateItem) { @@ -2631,11 +2105,28 @@ static bool saveOctagonKeysToKeychain(NSString* keyLabel, NSData* keyDataToSave, *error = localerror; } - CFReleaseNull(publicKeyHash); - return (status == errSecSuccess); } +void SOSCCEnsureAccessGroupOfKey(SecKeyRef publicKey, NSString* oldAgrp, NSString* newAgrp) +{ + NSData* publicKeyHash = CFBridgingRelease(SecKeyCopyPublicKeyHash(publicKey)); + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassKey, + (id)kSecAttrSynchronizable: (id)kSecAttrSynchronizableAny, + (id)kSecAttrApplicationLabel: publicKeyHash, + (id)kSecAttrAccessGroup: oldAgrp, + }; + + OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)query, + (__bridge CFDictionaryRef)@{ + (id)kSecAttrAccessGroup: newAgrp, + }); + + secnotice("octagon", "Ensuring key agrp ('%@' from '%@') status: %d", newAgrp, oldAgrp, (int)status); +}; + static NSString* createKeyLabel(NSDictionary *gestalt, NSString* circleName, NSString* prefix) { NSString *keyName = [NSString stringWithFormat:@"ID for %@-%@",SOSPeerGestaltGetName((__bridge CFDictionaryRef)(gestalt)), circleName]; @@ -2650,18 +2141,19 @@ static NSError* saveKeysToKeychain(SOSAccount* account, NSData* octagonSigningFu NSError* saveToKeychainError = nil; NSString* circleName = (__bridge NSString*)(SOSCircleGetName(account.trust.trustedCircle)); + NSString* signingPrefix = @"Octagon Peer Signing "; NSString* encryptionPrefix = @"Octagon Peer Encryption "; NSString* octagonSigningKeyName = createKeyLabel(account.gestalt, circleName, signingPrefix); NSString* octagonEncryptionKeyName = createKeyLabel(account.gestalt, circleName, encryptionPrefix); /* behavior mimics GeneratePermanentFullECKey_internal */ - saveOctagonKeysToKeychain(octagonSigningKeyName, octagonSigningFullKey, 384, octagonSigningPublicKeyRef, &saveToKeychainError); + SOSCCSaveOctagonKeysToKeychain(octagonSigningKeyName, octagonSigningFullKey, 384, octagonSigningPublicKeyRef, &saveToKeychainError); if(saveToKeychainError) { secerror("octagon: could not save signing key: %@", saveToKeychainError); return saveToKeychainError; } - saveOctagonKeysToKeychain(octagonEncryptionKeyName, octagonEncryptionFullKey, 384, octagonEncryptionPublicKeyRef, &saveToKeychainError); + SOSCCSaveOctagonKeysToKeychain(octagonEncryptionKeyName, octagonEncryptionFullKey, 384, octagonEncryptionPublicKeyRef, &saveToKeychainError); if(saveToKeychainError) { secerror("octagon: could not save encryption key: %@", saveToKeychainError); return saveToKeychainError; @@ -2717,6 +2209,57 @@ void SOSCCPerformUpdateOfAllOctagonKeys(CFDataRef octagonSigningFullKey, CFDataR CFReleaseNull(localError); } +void SOSCCPerformPreloadOfAllOctagonKeys(CFDataRef octagonSigningFullKey, CFDataRef octagonEncryptionFullKey, + SecKeyRef octagonSigningFullKeyRef, SecKeyRef octagonEncryptionFullKeyRef, + SecKeyRef octagonSigningPublicKeyRef, SecKeyRef octagonEncryptionPublicKeyRef, + void (^action)(CFErrorRef error)) +{ + CFErrorRef localError = NULL; + do_with_account_if_after_first_unlock(&localError, ^bool(SOSAccountTransaction *txn, CFErrorRef *err) { + + //save octagon key set to the keychain + NSError* saveError = nil; + saveError = saveKeysToKeychain(txn.account, (__bridge NSData*)octagonSigningFullKey, (__bridge NSData*)octagonEncryptionFullKey, + octagonSigningPublicKeyRef, octagonEncryptionPublicKeyRef); + + if(saveError) { + secerror("octagon-preload-keys: failed to save Octagon keys to the keychain: %@", saveError); + action((__bridge CFErrorRef)saveError); + return false; + } + + //now update the sos account to contain octagon keys + if(txn.account){ + txn.account.octagonSigningFullKeyRef = CFRetainSafe(octagonSigningFullKeyRef); + txn.account.octagonEncryptionFullKeyRef = CFRetainSafe(octagonEncryptionFullKeyRef); + } else { + secnotice("octagon-preload-keys", "No SOSAccount to update?"); + NSError *noAccountError = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:kSOSErrorNoAccount userInfo:@{NSLocalizedDescriptionKey : @"Device has no SOSAccount"}]; + action((__bridge CFErrorRef)noAccountError); + return false; + } + + secnotice("octagon-preload-keys", "Success! Octagon Keys Preloaded!"); + + action(nil); + return true; + }); + CFReleaseNull(localError); +} + +bool SOSCCSetCKKS4AllStatus(bool supports, CFErrorRef* error) +{ + CFErrorRef cfAccountError = NULL; + bool ret = do_with_account_if_after_first_unlock(&cfAccountError, ^bool(SOSAccountTransaction *txn, CFErrorRef *cferror) { + SOSAccountUpdatePeerInfo(txn.account, CFSTR("CKKS4All update"), cferror, ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *blockError) { + return SOSFullPeerInfoSetCKKS4AllSupport(fpi, supports, blockError); + }); + return true; + }); + CFErrorPropagate(cfAccountError, error); + return ret; +} + void SOSCCPerformWithTrustedPeers(void (^action)(CFSetRef sosPeerInfoRefs, CFErrorRef error)) { CFErrorRef cfAccountError = NULL; diff --git a/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupKeyClassSigningKey.m b/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupKeyClassSigningKey.m index b86f63cb..bfdd3c2c 100644 --- a/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupKeyClassSigningKey.m +++ b/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupKeyClassSigningKey.m @@ -25,7 +25,7 @@ } - (BOOL)hasKeyClass { - return _has.keyClass; + return _has.keyClass != 0; } - (BOOL)hasPublicKey { diff --git a/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupMetadataClassKey.m b/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupMetadataClassKey.m index eae21ba4..0da4f8ec 100644 --- a/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupMetadataClassKey.m +++ b/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupMetadataClassKey.m @@ -25,7 +25,7 @@ } - (BOOL)hasKeyClass { - return _has.keyClass; + return _has.keyClass != 0; } - (BOOL)hasBackupWrappedMetadataKey { diff --git a/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupRecoverySet.m b/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupRecoverySet.m index 1621b0d2..9dd58a5e 100644 --- a/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupRecoverySet.m +++ b/keychain/securityd/SecDbBackupManager-protobufs/generated_source/SecDbBackupRecoverySet.m @@ -27,7 +27,7 @@ } - (BOOL)hasRecoveryType { - return _has.recoveryType; + return _has.recoveryType != 0; } - (BOOL)hasBagIdentity { diff --git a/keychain/securityd/SecDbBackupManager.h b/keychain/securityd/SecDbBackupManager.h index 2459ad75..5e6de4f9 100644 --- a/keychain/securityd/SecDbBackupManager.h +++ b/keychain/securityd/SecDbBackupManager.h @@ -21,14 +21,18 @@ * @APPLE_LICENSE_HEADER_END@ */ +#import + // For now at least, we'll support backups only on iOS and macOS -#define SECDB_BACKUPS_ENABLED ((TARGET_OS_OSX || TARGET_OS_IOS || TARGET_OS_IOSMAC) && !TARGET_OS_SIMULATOR && !TARGET_DARWINOS) +#if (TARGET_OS_OSX || TARGET_OS_IOS || TARGET_OS_MACCATALYST) && !TARGET_OS_SIMULATOR && !(defined(TARGET_DARWINOS) && TARGET_DARWINOS) +#define SECDB_BACKUPS_ENABLED 1 +#else +#define SECDB_BACKUPS_ENABLED 0 +#endif #if __OBJC2__ #import -#if !TARGET_OS_BRIDGE // Specifically needed until rdar://problem/40583882 lands #import -#endif #import "SecAKSObjCWrappers.h" #import "CheckV12DevEnabled.h" @@ -69,22 +73,20 @@ typedef NS_ENUM(NSInteger, SecDbBackupErrorCode) { SecDbBackupTestCodeFailure = 255, // support code for testing is falling over somehow }; -@interface SecDbBackupWrappedItemKey : NSObject +@interface SecDbBackupWrappedKey : NSObject @property (nonatomic) NSData* wrappedKey; @property (nonatomic) NSData* baguuid; @end @interface SecDbBackupManager : NSObject -+ (instancetype)manager; +// Nullable to make analyzer not complain in the case where the stub returns nil ++ (instancetype _Nullable)manager; - (instancetype)init NS_UNAVAILABLE; -#if !TARGET_OS_BRIDGE // Specifically needed until rdar://problem/40583882 lands -- (SecDbBackupWrappedItemKey* _Nullable)wrapItemKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error; -#else -- (SecDbBackupWrappedItemKey* _Nullable)wrapItemKey:(id)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error; -#endif - +- (NSData* _Nullable)currentBackupBagUUID; +- (SecDbBackupWrappedKey* _Nullable)wrapItemKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error; +- (SecDbBackupWrappedKey* _Nullable)wrapMetadataKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error; - (void)verifyBackupIntegrity:(bool)lightweight completion:(void (^)(NSDictionary* results, NSError* _Nullable error))completion; @@ -96,3 +98,4 @@ NS_ASSUME_NONNULL_END // Declare C functions here bool SecDbBackupCreateOrLoadBackupInfrastructure(CFErrorRef _Nullable * _Nonnull error); +void SecDbResetBackupManager(void); // For testing. Here so SecKeychainDbReset can use it. diff --git a/keychain/securityd/SecDbBackupManager.m b/keychain/securityd/SecDbBackupManager.m index ff4dc45a..b2a5c420 100644 --- a/keychain/securityd/SecDbBackupManager.m +++ b/keychain/securityd/SecDbBackupManager.m @@ -22,11 +22,12 @@ */ #import "SecDbBackupManager.h" +#import "sec_action.h" NSString* const KeychainBackupsErrorDomain = @"com.apple.security.keychain.backups"; // oink oink -@implementation SecDbBackupWrappedItemKey +@implementation SecDbBackupWrappedKey + (BOOL)supportsSecureCoding { return YES; } @@ -44,36 +45,7 @@ NSString* const KeychainBackupsErrorDomain = @"com.apple.security.keychain.backu } @end -#if !SECDB_BACKUPS_ENABLED - -@implementation SecDbBackupManager - -+ (instancetype)manager -{ - return nil; -} - -- (void)verifyBackupIntegrity:(bool)lightweight - completion:(void (^)(NSDictionary* results, NSError* _Nullable error))completion -{ - completion(nil, [NSError errorWithDomain:KeychainBackupsErrorDomain - code:SecDbBackupNotSupported - userInfo:@{NSLocalizedDescriptionKey : @"platform doesn't do backups"}]); -} - -- (SecDbBackupWrappedItemKey* _Nullable)wrapItemKey:(id)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error -{ - return nil; -} - -@end - -bool SecDbBackupCreateOrLoadBackupInfrastructure(CFErrorRef* error) -{ - return true; -} - -#else // SECDB_BACKUPS_ENABLED is true, roll out the code +#if SECDB_BACKUPS_ENABLED // The bottom of this file contains stubs in case the feature is disabled #import "SecDbBackupManager_Internal.h" #include @@ -101,6 +73,11 @@ bool SecDbBackupCreateOrLoadBackupInfrastructure(CFErrorRef* error) return ok; } +void SecDbResetBackupManager() { + secnotice("SecDbBackup", "Resetting backup manager"); + [SecDbBackupManager resetManager]; +} + // Reading from disk is relatively expensive. Keep wrapped key in memory and just delete the unwrapped copy on lock @interface InMemoryKCSK : NSObject @property aks_ref_key_t refKey; @@ -190,7 +167,8 @@ static SecDbBackupManager* staticManager; + (void)resetManager { if (staticManager) { - staticManager = [SecDbBackupManager new]; + secnotice("SecDbBackup", "Resetting backup manager"); + staticManager = [[SecDbBackupManager alloc] init]; } } @@ -215,7 +193,7 @@ static SecDbBackupManager* staticManager; } CFTypeRef cftype = NULL; CFErrorRef cferr = NULL; - const uint8_t* derp = der_decode_plist(kCFAllocatorDefault, NSPropertyListImmutable, &cftype, &cferr, bytes, bytes + len); + const uint8_t* derp = der_decode_plist(kCFAllocatorDefault, &cftype, &cferr, bytes, bytes + len); free(bytes); if (derp == NULL || derp != (bytes + len) || cftype == NULL) { [self fillError:error code:SecDbBackupMalformedKCSKDataOnDisk underlying:CFBridgingRelease(cferr) description:@"Unable to parse der data"]; @@ -227,6 +205,11 @@ static SecDbBackupManager* staticManager; error:error]; } +- (NSData*)currentBackupBagUUID +{ + return [_bagIdentity.baguuid copy]; +} + #pragma mark - Fixup And Verification - (void)verifyBackupIntegrity:(bool)lightweight @@ -438,8 +421,6 @@ static SecDbBackupManager* staticManager; return bad_keybag_handle; } - // TODO: verify that bag is still signed, rdar://problem/46702467 - secnotice("SecDbBackup", "Backup bag loaded and verified."); // Must load readBag's identity because the hash from AKS is unstable. @@ -451,6 +432,7 @@ static SecDbBackupManager* staticManager; - (BOOL)onQueueReloadDefaultBackupBagWithError:(NSError**)error { + dispatch_assert_queue(_queue); if (_handle != bad_keybag_handle) { aks_unload_bag(_handle); } @@ -541,6 +523,7 @@ static SecDbBackupManager* staticManager; - (InMemoryKCSK*)onQueueReadKCSKFromDiskForClass:(keyclass_t)keyclass error:(NSError**)error { + dispatch_assert_queue(_queue); __block bool ok = true; __block CFErrorRef cfError = NULL; __block NSData* readUUID; @@ -610,6 +593,7 @@ static SecDbBackupManager* staticManager; - (SFECKeyPair*)onQueueFetchKCSKForKeyclass:(keyclass_t)keyclass error:(NSError**)error { + dispatch_assert_queue(_queue); assert(error); assert(_bagIdentity); assert(_handle != bad_keybag_handle); @@ -889,9 +873,23 @@ static SecDbBackupManager* staticManager; #pragma mark - Item Encryption -- (SecDbBackupWrappedItemKey*)wrapItemKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error +- (SecDbBackupWrappedKey*)wrapItemKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error { assert(error); + // We don't care about rolled keyclasses; we care about semantic classes + if (keyclass > key_class_last) { + static dispatch_once_t rolledkeyclassnotifytoken; + static sec_action_t rolledkeyclassnotifyaction; + dispatch_once(&rolledkeyclassnotifytoken, ^{ + rolledkeyclassnotifyaction = sec_action_create("rolledkeyclassnotifyaction", 300); + sec_action_set_handler(rolledkeyclassnotifyaction, ^{ + secnotice("SecDbBackup", "Rolled keyclass for item wrap, %d -> %d", keyclass, SecAKSSanitizedKeyclass(keyclass)); + }); + }); + sec_action_perform(rolledkeyclassnotifyaction); + keyclass = SecAKSSanitizedKeyclass(keyclass); + } + if (keyclass == key_class_akpu) { secwarning("SecDbBackup: Don't tempt me Frodo!"); [self fillError:error code:SecDbBackupInvalidArgument underlying:nil description:@"Do not call wrapItemKey with class akpu"]; @@ -905,7 +903,7 @@ static SecDbBackupManager* staticManager; return nil; } - __block SecDbBackupWrappedItemKey* backupWrappedKey; + __block SecDbBackupWrappedKey* backupWrappedKey; __block NSMutableData* wrappedKey = [NSMutableData dataWithLength:APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN]; __block NSError* localError; @@ -928,7 +926,7 @@ static SecDbBackupManager* staticManager; return; } } - backupWrappedKey = [SecDbBackupWrappedItemKey new]; + backupWrappedKey = [SecDbBackupWrappedKey new]; backupWrappedKey.wrappedKey = [NSKeyedArchiver archivedDataWithRootObject:wrappedAndSigned requiringSecureCoding:YES error:&localError]; backupWrappedKey.baguuid = self->_bagIdentity.baguuid; }); @@ -944,6 +942,7 @@ static SecDbBackupManager* staticManager; - (SFSignedData*)onQueueSignData:(NSMutableData*)data withKCSKForKeyclass:(keyclass_t)keyclass error:(NSError**)error { + dispatch_assert_queue(_queue); SFECKeyPair* kcsk = [self onQueueFetchKCSKForKeyclass:keyclass error:error]; if (!kcsk) { return nil; @@ -953,6 +952,19 @@ static SecDbBackupManager* staticManager; return [op sign:data withKey:kcsk error:error]; } +#pragma mark - Metadata Key Encryption + +- (SecDbBackupWrappedKey*)wrapMetadataKey:(_SFAESKey *)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error +{ + // We don't care about rolled keyclasses; we care about semantic classes + if (keyclass > key_class_last) { + secnotice("SecDbBackup", "Rolled keyclass for metadata wrap, %d -> %d", keyclass, SecAKSSanitizedKeyclass(keyclass)); + keyclass = SecAKSSanitizedKeyclass(keyclass); + } + // For now, this is identical to item encryption. This will likely change when ACLs are implemented + return [self wrapItemKey:key forKeyclass:keyclass error:error]; +} + #pragma mark - Testing Helpers - (keybag_handle_t)createBackupBagWithSecret:(NSData*)secret error:(NSError**)error @@ -1052,4 +1064,30 @@ static SecDbBackupManager* staticManager; @end -#endif // SECDB_BACKUPS_ENABLED +#else // SECDB_BACKUPS_ENABLED is false +#pragma mark - Stubs for when backups are disabled + +@implementation SecDbBackupManager + ++ (instancetype)manager +{ + return nil; +} + +- (NSData* _Nullable)currentBackupBagUUID {return nil;} +- (SecDbBackupWrappedKey* _Nullable)wrapItemKey:(id)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error {return nil;} +- (SecDbBackupWrappedKey* _Nullable)wrapMetadataKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error {return nil;} +- (void)verifyBackupIntegrity:(bool)lightweight + completion:(void (^)(NSDictionary* results, NSError* _Nullable error))completion +{ + completion(nil, [NSError errorWithDomain:KeychainBackupsErrorDomain + code:SecDbBackupNotSupported + userInfo:@{NSLocalizedDescriptionKey : @"platform doesn't do backups"}]); +} + +@end + +bool SecDbBackupCreateOrLoadBackupInfrastructure(CFErrorRef* error) {return true;} +void SecDbResetBackupManager() {} + +#endif // SECDB_BACKUPS_ENABLED diff --git a/keychain/securityd/SecDbBackupManager_Internal.h b/keychain/securityd/SecDbBackupManager_Internal.h index 71a3b3eb..24b7499e 100644 --- a/keychain/securityd/SecDbBackupManager_Internal.h +++ b/keychain/securityd/SecDbBackupManager_Internal.h @@ -63,7 +63,7 @@ // Pure utilities - (NSData*)getSHA256OfData:(NSData*)data; -- (SFECKeyPair*)ECKeyPairFromDerBytes:(void*)bytes length:(size_t)len error:(NSError**)error; +- (SFECKeyPair*)getECKeyPairFromDERBytes:(void*)bytes length:(size_t)len error:(NSError**)error; @end diff --git a/keychain/securityd/SecDbItem.c b/keychain/securityd/SecDbItem.c index 5b63b41a..2d84908b 100644 --- a/keychain/securityd/SecDbItem.c +++ b/keychain/securityd/SecDbItem.c @@ -26,7 +26,7 @@ * database items (certificates, keys, identities, and passwords.) */ -#if TARGET_DARWINOS +#if defined(TARGET_DARWINOS) && TARGET_DARWINOS #undef OCTAGON #undef SECUREOBJECTSYNC #undef SHAREDWEBCREDENTIALS @@ -337,8 +337,20 @@ static CFTypeRef SecDbItemGetCachedValue(SecDbItemRef item, const SecDbAttr *des } CFMutableDictionaryRef SecDbItemCopyPListWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error) { + return SecDbItemCopyPListWithFlagAndSkip(item, mask, 0, error); +} + +CFMutableDictionaryRef SecDbItemCopyPListWithFlagAndSkip(SecDbItemRef item, + CFOptionFlags mask, + CFOptionFlags flagsToSkip, + CFErrorRef *error) +{ CFMutableDictionaryRef dict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); SecDbForEachAttrWithMask(item->class, desc, mask) { + if((desc->flags & flagsToSkip) != 0) { + break; + } + CFTypeRef value = SecDbItemGetValue(item, desc, error); if (value) { if (!CFEqual(kCFNull, value)) { @@ -559,28 +571,62 @@ static bool SecDbItemGetBoolValue(SecDbItemRef item, const SecDbAttr *desc, bool return true; } +static void SecDbItemAppendAttributeToDescription(SecDbItemRef item, const SecDbAttr *attr, CFMutableStringRef mdesc) +{ + // In non-debug builds, the following attributes aren't very useful. +#ifndef DEBUG + if (CFEqual(CFSTR("data"), attr->name)|| + CFEqual(CFSTR("v_pk"), attr->name)) { + return; + } +#endif + + CFTypeRef value = SecDbItemGetValue(item, attr, NULL); + if (value && value != kCFNull) { + CFStringAppend(mdesc, CFSTR(",")); + CFStringAppend(mdesc, attr->name); + CFStringAppend(mdesc, CFSTR("=")); + if (CFEqual(CFSTR("data"), attr->name)) { + CFStringAppendEncryptedData(mdesc, value); + } else if (CFEqual(CFSTR("v_Data"), attr->name)) { + CFStringAppend(mdesc, CFSTR("")); + } else if (isData(value)) { + CFStringAppendHexData(mdesc, value); + } else { + CFStringAppendFormat(mdesc, 0, CFSTR("%@"), value); + } + } +} + static CFStringRef SecDbItemCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { CFStringRef desc; if (isDictionary(formatOptions) && CFDictionaryContainsKey(formatOptions, kSecDebugFormatOption)) { SecDbItemRef item = (SecDbItemRef)cf; CFMutableStringRef mdesc = CFStringCreateMutable(CFGetAllocator(cf), 0); CFStringAppendFormat(mdesc, NULL, CFSTR("<%@"), item->class->name); + + // First, the primary key attributes + SecDbForEachAttrWithMask(item->class, attr, kSecDbPrimaryKeyFlag) { + SecDbItemAppendAttributeToDescription(item, attr, mdesc); + } + + CFStringAppend(mdesc, CFSTR(", |otherAttr")); + // tombstone values are very important, and should print next SecDbForEachAttr(item->class, attr) { - CFTypeRef value = SecDbItemGetValue(item, attr, NULL); - if (value) { - CFStringAppend(mdesc, CFSTR(",")); - CFStringAppend(mdesc, attr->name); - CFStringAppend(mdesc, CFSTR("=")); - if (CFEqual(CFSTR("data"), attr->name)) { - CFStringAppendEncryptedData(mdesc, value); - } else if (CFEqual(CFSTR("v_Data"), attr->name)) { - CFStringAppend(mdesc, CFSTR("")); - } else if (isData(value)) { - CFStringAppendHexData(mdesc, value); - } else { - CFStringAppendFormat(mdesc, 0, CFSTR("%@"), value); - } - } + if(CFEqualSafe(CFSTR("tomb"), attr->name)) { + SecDbItemAppendAttributeToDescription(item, attr, mdesc); + } + } + + // And finally, everything else + SecDbForEachAttr(item->class, attr) { + if((attr->flags & kSecDbPrimaryKeyFlag) != 0) { + continue; + } + if(CFEqualSafe(CFSTR("tomb"), attr->name)) { + continue; + } + SecDbItemAppendAttributeToDescription(item, attr, mdesc); } CFStringAppend(mdesc, CFSTR(">")); desc = mdesc; @@ -886,6 +932,28 @@ bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef va return false; } +bool SecItemPreserveAttribute(SecDbItemRef target, SecDbItemRef source, const SecDbAttr* attr) { + CFErrorRef cferror = nil; + CFTypeRef v = SecDbItemGetValue(source, attr, &cferror); + if(cferror) { + secnotice("secitem", "Merging: unable to get attribute (%@) : %@", attr->name, cferror); + CFReleaseNull(cferror); + return false; + } + if(!v || CFEqualSafe(v, kCFNull)) { + return true; + } + secnotice("secitem", "Preserving existing data for %@", attr->name); + SecDbItemSetValue(target, attr, v, &cferror); + if(cferror) { + secnotice("secitem", "Unable to set attribute (%@) : %@", attr->name, cferror); + CFReleaseNull(cferror); + return false; + } + return true; +} + + bool SecDbItemSetAccessControl(SecDbItemRef item, SecAccessControlRef access_control, CFErrorRef *error) { bool ok = true; if (item->_edataState == kSecDbItemClean) @@ -1058,7 +1126,7 @@ static bool SecDbItemMakeYounger(SecDbItemRef new_item, SecDbItemRef old_item, C return attr && SecDbItemMakeAttrYounger(new_item, old_item, attr, error); } -static SecDbItemRef SecDbItemCopyTombstone(SecDbItemRef item, CFBooleanRef makeTombStone, CFErrorRef *error) { +static SecDbItemRef SecDbItemCopyTombstone(SecDbItemRef item, CFBooleanRef makeTombStone, bool tombstone_time_from_item, CFErrorRef *error) { SecDbItemRef new_item = SecDbItemCreate(CFGetAllocator(item), item->class, item->keybag); SecDbForEachAttr(item->class, attr) { if (attr->kind == kSecDbTombAttr) { @@ -1075,6 +1143,10 @@ static SecDbItemRef SecDbItemCopyTombstone(SecDbItemRef item, CFBooleanRef makeT break; } } else if (attr->kind == kSecDbModificationDateAttr) { + if(tombstone_time_from_item) { + SecItemPreserveAttribute(new_item, item, attr); + } + if (!SecDbItemMakeAttrYounger(new_item, item, attr, error)) { CFReleaseNull(new_item); break; @@ -1296,7 +1368,7 @@ static SecDbQueryRef SecDbQueryCreateWithItemPrimaryKey(SecDbItemRef item, CFErr if (!dict) return NULL; - SecDbQueryRef query = query_create(item->class, NULL, NULL, error); + SecDbQueryRef query = query_create(item->class, NULL, NULL, NULL, error); if (query) { CFReleaseSafe(query->q_item); query->q_item = dict; @@ -1343,7 +1415,8 @@ static bool SecDbItemIsCorrupt(SecDbItemRef item, bool *is_corrupt, CFErrorRef * if (storedSHA1 && computedSHA1 && !CFEqual(storedSHA1, computedSHA1)) { CFStringRef storedHex = CFDataCopyHexString(storedSHA1), computedHex = CFDataCopyHexString(computedSHA1); secerror("error %@ %@ != %@ item %@ (corrupted)", sha1attr->name, storedHex, computedHex, item); - __security_simulatecrash(CFSTR("Corrupted item (sha1 mismatch) found in keychain"), __sec_exception_code_CorruptItem); + // Do not simulate crash for this condition. + // The keychain hashes floating point numbers which causes many false positives, this is not fixable except by major surgery CFReleaseSafe(storedHex); CFReleaseSafe(computedHex); *is_corrupt = true; @@ -1472,11 +1545,21 @@ bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFEr return ok & SecErrorPropagate(localError, error); // Don't use && here! } -bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error) { +bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, bool always_use_uuid_from_new_item, CFErrorRef *error) { return SecDbItemInsertOrReplace(item, dbconn, error, ^(SecDbItemRef old_item, SecDbItemRef *replace) { if (SecDbItemIsTombstone(old_item)) { CFRetain(item); *replace = item; + + // If the caller doesn't care about the UUID, then use old_item's UUID + // Note: this will modify item! + if(!always_use_uuid_from_new_item) { + SecDbForEachAttr(SecDbItemGetClass(item), attr) { + if(CFEqual(attr->name, v10itemuuid.name)) { + SecItemPreserveAttribute(item, old_item, attr); + } + } + } } }); } @@ -1700,7 +1783,7 @@ bool SecDbItemUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnecti if (ok && !pk_equal && !CFEqualSafe(makeTombstone, kCFBooleanFalse)) { /* The primary key of new_item is different than that of old_item, we have been asked to make a tombstone so leave one for the old_item. */ - SecDbItemRef tombstone = SecDbItemCopyTombstone(old_item, makeTombstone, error); + SecDbItemRef tombstone = SecDbItemCopyTombstone(old_item, makeTombstone, false, error); ok = tombstone; if (tombstone) { ok = (SecDbItemClearRowId(tombstone, error) && @@ -1713,10 +1796,10 @@ bool SecDbItemUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnecti } // Replace the object with a tombstone -bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, CFErrorRef *error) { +bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, bool tombstone_time_from_item, CFErrorRef *error) { bool ok = false; if (!CFEqualSafe(makeTombstone, kCFBooleanFalse)) { - SecDbItemRef tombstone = SecDbItemCopyTombstone(item, makeTombstone, error); + SecDbItemRef tombstone = SecDbItemCopyTombstone(item, makeTombstone, tombstone_time_from_item, error); if (tombstone) { ok = SecDbItemDoUpdate(item, tombstone, dbconn, error, ^bool(const SecDbAttr *attr) { return attr->kind == kSecDbRowIdAttr; diff --git a/keychain/securityd/SecDbItem.h b/keychain/securityd/SecDbItem.h index 586b8c00..1d9966cd 100644 --- a/keychain/securityd/SecDbItem.h +++ b/keychain/securityd/SecDbItem.h @@ -81,6 +81,7 @@ enum { kSecDbSyncPrimaryKeyV0 = (1 << 14), kSecDbSyncPrimaryKeyV2 = (1 << 15), kSecDbSyncFlag = (1 << 16), + kSecDbSyncSOSCannotSyncFlag= (1 << 17), }; #define SecVersionDbFlag(v) ((v & 0xFF) << 8) @@ -176,6 +177,10 @@ bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value bool SecDbItemSetValues(SecDbItemRef item, CFDictionaryRef values, CFErrorRef *error); bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef value, CFErrorRef *error); +// Copies a given attribute from source to target. If source does not have that atttribute, +// doesn't modify target. +bool SecItemPreserveAttribute(SecDbItemRef target, SecDbItemRef source, const SecDbAttr* attr); + sqlite3_int64 SecDbItemGetRowId(SecDbItemRef item, CFErrorRef *error); bool SecDbItemSetRowId(SecDbItemRef item, sqlite3_int64 rowid, CFErrorRef *error); bool SecDbItemClearRowId(SecDbItemRef item, CFErrorRef *error); @@ -189,6 +194,14 @@ bool SecDbItemIsTombstone(SecDbItemRef item); CFMutableDictionaryRef SecDbItemCopyPListWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error); +/* + * Note that "mask" requires a single option, but flagsToSkip can have any number combined. + */ +CFMutableDictionaryRef SecDbItemCopyPListWithFlagAndSkip(SecDbItemRef item, + CFOptionFlags mask, + CFOptionFlags flagsToSkip, + CFErrorRef *error); + CFDataRef SecDbItemGetPrimaryKey(SecDbItemRef item, CFErrorRef *error); CFDataRef SecDbItemGetSHA1(SecDbItemRef item, CFErrorRef *error); @@ -214,9 +227,10 @@ bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFEr // SecDbItemInsertOrReplace returns an error even when it succeeds; use this to determine if it's spurious bool SecErrorIsSqliteDuplicateItemError(CFErrorRef error); -bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error); +// Note: this function might modify item, unless always_use_uuid_from_new_item is true +bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, bool always_use_uuid_from_new_item, CFErrorRef *error); -bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, CFErrorRef *error); +bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, bool tombstone_time_from_item, CFErrorRef *error); bool SecDbItemDoDeleteSilently(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error); diff --git a/keychain/securityd/SecDbKeychainItem.h b/keychain/securityd/SecDbKeychainItem.h index ce889868..83aaaa5d 100644 --- a/keychain/securityd/SecDbKeychainItem.h +++ b/keychain/securityd/SecDbKeychainItem.h @@ -32,34 +32,38 @@ #include "keychain/securityd/SecDbItem.h" #include "keychain/securityd/SecDbQuery.h" +CF_ASSUME_NONNULL_BEGIN + __BEGIN_DECLS -bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, bool useDefaultIV, CFErrorRef *error); -bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, CFDataRef *bkUUID, bool useDefaultIV, CFErrorRef *error); -bool ks_encrypt_data_legacy(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, bool useDefaultIV, CFErrorRef *error); // used for backup -bool ks_decrypt_data(keybag_handle_t keybag, CFTypeRef cryptoOp, SecAccessControlRef *paccess_control, CFDataRef acm_context, +bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef _Nullable *_Nonnull pBlob, bool useDefaultIV, CFErrorRef _Nullable *_Nullable error); +bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef _Nullable *_Nonnull pBlob, CFDataRef _Nullable *_Nullable bkUUID, bool useDefaultIV, CFErrorRef _Nullable *_Nullable error); +bool ks_encrypt_data_legacy(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef _Nullable *_Nonnull pBlob, bool useDefaultIV, CFErrorRef _Nullable *_Nullable error); // used for backup +bool ks_decrypt_data(keybag_handle_t keybag, CFTypeRef cryptoOp, SecAccessControlRef _Nullable *_Nullable paccess_control, CFDataRef acm_context, CFDataRef blob, const SecDbClass *db_class, CFArrayRef caller_access_groups, - CFMutableDictionaryRef *attributes_p, uint32_t *version_p, bool decryptSecretData, keyclass_t* outKeyclass, CFErrorRef *error); + CFMutableDictionaryRef _Nullable *_Nullable attributes_p, uint32_t *_Nullable version_p, bool decryptSecretData, keyclass_t*_Nullable outKeyclass, CFErrorRef _Nullable *_Nullable error); bool s3dl_item_from_data(CFDataRef edata, Query *q, CFArrayRef accessGroups, - CFMutableDictionaryRef *item, SecAccessControlRef *access_control, keyclass_t* keyclass, CFErrorRef *error); -SecDbItemRef SecDbItemCreateWithBackupDictionary(CFAllocatorRef allocator, const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error); -bool SecDbItemExtractRowIdFromBackupDictionary(SecDbItemRef item, CFDictionaryRef dict, CFErrorRef *error); -bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef *error); + CFMutableDictionaryRef _Nonnull *_Nonnull item, SecAccessControlRef _Nullable *_Nullable access_control, keyclass_t *_Nullable keyclass, CFErrorRef _Nullable *_Nullable error); +SecDbItemRef _Nullable SecDbItemCreateWithBackupDictionary(const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef _Nullable *_Nullable error); +bool SecDbItemExtractRowIdFromBackupDictionary(SecDbItemRef item, CFDictionaryRef dict, CFErrorRef _Nullable *_Nullable error); +bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef _Nullable *_Nullable error); -CFTypeRef SecDbKeychainItemCopyPrimaryKey(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error); -CFTypeRef SecDbKeychainItemCopySHA256PrimaryKey(SecDbItemRef item, CFErrorRef *error); -CFTypeRef SecDbKeychainItemCopySHA1(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error); -CFTypeRef SecDbKeychainItemCopyCurrentDate(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error); -CFTypeRef SecDbKeychainItemCopyEncryptedData(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error); +CFTypeRef _Nullable SecDbKeychainItemCopyPrimaryKey(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef _Nullable *_Nullable error); +CFTypeRef _Nullable SecDbKeychainItemCopySHA256PrimaryKey(SecDbItemRef item, CFErrorRef _Nullable *_Nullable error); +CFTypeRef _Nullable SecDbKeychainItemCopySHA1(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef _Nullable *_Nullable error); +CFTypeRef _Nullable SecDbKeychainItemCopyCurrentDate(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef _Nullable *_Nullable error); +CFTypeRef _Nullable SecDbKeychainItemCopyEncryptedData(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef _Nullable *_Nullable error); -SecAccessControlRef SecDbItemCopyAccessControl(SecDbItemRef item, CFErrorRef *error); -bool SecDbItemSetAccessControl(SecDbItemRef item, SecAccessControlRef access_control, CFErrorRef *error); +SecAccessControlRef _Nullable SecDbItemCopyAccessControl(SecDbItemRef item, CFErrorRef _Nullable *_Nullable error); +bool SecDbItemSetAccessControl(SecDbItemRef item, SecAccessControlRef access_control, CFErrorRef _Nullable *_Nullable error); void SecDbResetMetadataKeys(void); __END_DECLS +CF_ASSUME_NONNULL_END + #endif /* _SECURITYD_SECKEYCHAINITEM_H_ */ diff --git a/keychain/securityd/SecDbKeychainItem.m b/keychain/securityd/SecDbKeychainItem.m index 7e52fc36..cd7032e0 100644 --- a/keychain/securityd/SecDbKeychainItem.m +++ b/keychain/securityd/SecDbKeychainItem.m @@ -71,32 +71,32 @@ static CFDataRef kc_copy_protection_data(SecAccessControlRef access_control); static CFTypeRef kc_copy_protection_from(const uint8_t *der, const uint8_t *der_end); static CF_RETURNS_RETAINED CFMutableDictionaryRef s3dl_item_v2_decode(CFDataRef plain, CFErrorRef *error); static CF_RETURNS_RETAINED CFMutableDictionaryRef s3dl_item_v3_decode(CFDataRef plain, CFErrorRef *error); -#if USE_KEYSTORE +#if USE_KEYSTORE && !TARGET_OS_SIMULATOR static bool kc_attribs_key_encrypted_data_from_blob(keybag_handle_t keybag, const SecDbClass *class, const void *blob_data, size_t blob_data_len, SecAccessControlRef access_control, uint32_t version, CFMutableDictionaryRef *authenticated_attributes, aks_ref_key_t *ref_key, CFDataRef *encrypted_data, CFErrorRef *error); static CFDataRef kc_create_auth_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes); static CFDataRef kc_copy_access_groups_data(CFArrayRef access_groups, CFErrorRef *error); #endif -static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef pl, CFOptionFlags mutability, CFPropertyListRef* cf, CFErrorRef *error, +static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef pl, CFPropertyListRef* cf, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); -static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFDictionaryRef* dictionary, CFErrorRef *error, +static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFDictionaryRef* dictionary, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); -static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error, +static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); -static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFArrayRef* array, CFErrorRef *error, +static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFArrayRef* array, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); -static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFSetRef* set, CFErrorRef *error, +static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); const uint32_t kUseDefaultIVMask = 1<<31; @@ -155,7 +155,7 @@ bool ks_encrypt_data_legacy(keybag_handle_t keybag, SecAccessControlRef access_c CFRelease(attributes_dict); } } else { -#if USE_KEYSTORE +#if USE_KEYSTORE && !TARGET_OS_SIMULATOR if (attributes) { plainText = CFPropertyListCreateDERData(kCFAllocatorDefault, attributes, error); } @@ -195,7 +195,7 @@ bool ks_encrypt_data_legacy(keybag_handle_t keybag, SecAccessControlRef access_c if (!keyclass) goto out; -#if USE_KEYSTORE +#if USE_KEYSTORE && !TARGET_OS_SIMULATOR if (version >= 4) { auth_data = kc_create_auth_data(access_control, authenticated_attributes); require_quiet(ok = ks_encrypt_acl(keybag, keyclass, bulkKeySize, bulkKey, bulkKeyWrapped, auth_data, acm_context, access_control, error), out); @@ -305,13 +305,13 @@ ks_warn_non_device_keybag(void) sec_action_perform(action); } -bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, bool useDefaultIV, CFErrorRef *error) { +bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef _Nonnull secretData, CFDictionaryRef _Nonnull attributes, CFDictionaryRef _Nonnull authenticated_attributes, CFDataRef _Nonnull *pBlob, bool useDefaultIV, CFErrorRef *error) { return ks_encrypt_data_with_backupuuid(keybag, access_control, acm_context, secretData, attributes, authenticated_attributes, pBlob, NULL, useDefaultIV, error); } -bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, CFDataRef *bkUUID, bool useDefaultIV, CFErrorRef *error) { +bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef _Nonnull secretData, CFDictionaryRef _Nonnull attributes, CFDictionaryRef _Nonnull authenticated_attributes, CFDataRef _Nonnull *pBlob, CFDataRef _Nullable *bkUUID, bool useDefaultIV, CFErrorRef *error) { if (keybag != KEYBAG_DEVICE) { ks_warn_non_device_keybag(); @@ -331,8 +331,8 @@ bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef if (SecAccessControlGetConstraints(access_control)) { NSMutableDictionary* allAttributes = [(__bridge NSDictionary*)attributes mutableCopy]; - [allAttributes addEntriesFromDictionary:(__bridge NSDictionary*)secretData]; - return ks_encrypt_data_legacy(keybag, access_control, acm_context, (__bridge CFDictionaryRef)allAttributes, authenticated_attributes, pBlob, useDefaultIV, error); + [allAttributes addEntriesFromDictionary:(__bridge NSDictionary*_Nonnull)secretData]; + return ks_encrypt_data_legacy(keybag, access_control, acm_context, (__bridge CFDictionaryRef _Nonnull)allAttributes, authenticated_attributes, pBlob, useDefaultIV, error); } bool success = false; @@ -342,7 +342,7 @@ bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef metadataAttributes[@"SecAccessControl"] = (__bridge_transfer NSData*)SecAccessControlCopyData(access_control); NSString* tamperCheck = [[NSUUID UUID] UUIDString]; // can use the item persistent reference when that starts getting filled in - SecDbKeychainItemV7* item = [[SecDbKeychainItemV7 alloc] initWithSecretAttributes:(__bridge NSDictionary*)secretData metadataAttributes:metadataAttributes tamperCheck:tamperCheck keyclass:key_class]; + SecDbKeychainItemV7* item = [[SecDbKeychainItemV7 alloc] initWithSecretAttributes:(__bridge NSDictionary*_Nonnull)secretData metadataAttributes:metadataAttributes tamperCheck:tamperCheck keyclass:key_class]; NSError* localError = nil; NSData* encryptedBlob = [item encryptedBlobWithKeybag:keybag accessControl:access_control acmContext:(__bridge NSData*)acm_context error:&localError]; @@ -603,7 +603,7 @@ bool ks_decrypt_data(keybag_handle_t keybag, CFTypeRef cryptoOp, SecAccessContro } } -#if USE_KEYSTORE +#if USE_KEYSTORE && !TARGET_OS_SIMULATOR if (hasProtectionData) { if (caller_access_groups) { caller_access_groups_data = kc_copy_access_groups_data(caller_access_groups, error); @@ -777,7 +777,8 @@ static CFTypeRef kc_encode_keyclass(keyclass_t keyclass) { } } -#if USE_KEYSTORE +// Simulator fakes security, this code is unused on it +#if USE_KEYSTORE && !TARGET_OS_SIMULATOR static bool kc_attribs_key_encrypted_data_from_blob(keybag_handle_t keybag, const SecDbClass *class, const void *blob_data, size_t blob_data_len, SecAccessControlRef access_control, uint32_t version, CFMutableDictionaryRef *authenticated_attributes, aks_ref_key_t *ref_key, CFDataRef *encrypted_data, CFErrorRef *error) { @@ -788,7 +789,7 @@ static bool kc_attribs_key_encrypted_data_from_blob(keybag_handle_t keybag, cons CFDataRef ed = NULL; bool ok = false; - der_decode_plist(NULL, kCFPropertyListImmutable, (CFPropertyListRef*)&blob_dict, NULL, blob_data, blob_data + blob_data_len); + der_decode_plist(NULL, (CFPropertyListRef*)&blob_dict, NULL, blob_data, blob_data + blob_data_len); require_action_quiet(blob_dict, out, SecError(errSecDecode, error, CFSTR("kc_attribs_key_encrypted_data_from_blob: failed to decode 'blob data'"))); if (!ks_separate_data_and_key(blob_dict, &ed, &key_data)) { @@ -803,7 +804,7 @@ static bool kc_attribs_key_encrypted_data_from_blob(keybag_handle_t keybag, cons require_quiet(external_data = ks_ref_key_get_external_data(keybag, key_data, &tmp_ref_key, &external_data_len, error), out); CFPropertyListRef external_data_dict = NULL; - der_decode_plist(NULL, kCFPropertyListImmutable, &external_data_dict, NULL, external_data, external_data + external_data_len); + der_decode_plist(NULL, &external_data_dict, NULL, external_data, external_data + external_data_len); require_action_quiet(external_data_dict, out, SecError(errSecDecode, error, CFSTR("kc_attribs_key_encrypted_data_from_blob: failed to decode 'encrypted data dictionary'"))); acl = CFDictionaryCreateMutableCopy(NULL, 0, external_data_dict); SecDbForEachAttrWithMask(class, attr_desc, kSecDbInAuthenticatedDataFlag) { @@ -901,7 +902,7 @@ static CFDataRef kc_copy_protection_data(SecAccessControlRef access_control) static CFTypeRef kc_copy_protection_from(const uint8_t *der, const uint8_t *der_end) { CFTypeRef result = NULL; - der_decode_plist(NULL, kCFPropertyListImmutable, &result, NULL, der, der_end); + der_decode_plist(NULL, &result, NULL, der, der_end); return result; } @@ -924,8 +925,8 @@ CFMutableDictionaryRef s3dl_item_v2_decode(CFDataRef plain, CFErrorRef *error) { return dictionaryFromPlist(item, error); } -static const uint8_t* (^s3dl_item_v3_decode_repair_date)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*) = - ^const uint8_t*(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { +static const uint8_t* (^s3dl_item_v3_decode_repair_date)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*) = + ^const uint8_t*(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { if (error && CFEqualSafe(CFErrorGetDomain(*error), sSecDERErrorDomain) && CFErrorGetCode(*error) == kSecDERErrorUnknownEncoding) { CFAbsoluteTime date = 0; CFCalendarRef calendar = CFCalendarCreateWithIdentifier(allocator, kCFGregorianCalendar); @@ -949,10 +950,10 @@ CFMutableDictionaryRef s3dl_item_v3_decode(CFDataRef plain, CFErrorRef *error) { CFPropertyListRef item = NULL; const uint8_t *der_beg = CFDataGetBytePtr(plain); const uint8_t *der_end = der_beg + CFDataGetLength(plain); - const uint8_t *der = der_decode_plist(0, kCFPropertyListMutableContainers, &item, error, der_beg, der_end); + const uint8_t *der = der_decode_plist(0, &item, error, der_beg, der_end); if (!der && error && CFEqualSafe(CFErrorGetDomain(*error), sSecDERErrorDomain) && CFErrorGetCode(*error) == kSecDERErrorUnknownEncoding) { CFReleaseNull(*error); - der = der_decode_plist_with_repair(0, kCFPropertyListMutableContainers, &item, error, der_beg, der_end, s3dl_item_v3_decode_repair_date); + der = der_decode_plist_with_repair(0, &item, error, der_beg, der_end, s3dl_item_v3_decode_repair_date); } if (der && der != der_end) { SecCFCreateError(errSecDecode, kSecErrorDomain, CFSTR("trailing garbage at end of decrypted item"), NULL, error); @@ -1144,7 +1145,7 @@ bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef *error) src_keybag is normally the backup keybag. dst_keybag is normally the device keybag. */ -SecDbItemRef SecDbItemCreateWithBackupDictionary(CFAllocatorRef allocator, const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error) +SecDbItemRef SecDbItemCreateWithBackupDictionary(const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error) { CFDataRef edata = CFDictionaryGetValue(dict, CFSTR("v_Data")); SecDbItemRef item = NULL; @@ -1321,10 +1322,10 @@ out: return result; } -static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { if (NULL == der) { @@ -1340,38 +1341,38 @@ static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef allocator, CFO switch (tag) { case CCDER_NULL: - return der_decode_null(allocator, mutability, (CFNullRef*)pl, error, der, der_end); + return der_decode_null(allocator, (CFNullRef*)pl, error, der, der_end); case CCDER_BOOLEAN: - return der_decode_boolean(allocator, mutability, (CFBooleanRef*)pl, error, der, der_end); + return der_decode_boolean(allocator, (CFBooleanRef*)pl, error, der, der_end); case CCDER_OCTET_STRING: - return der_decode_data(allocator, mutability, (CFDataRef*)pl, error, der, der_end); + return der_decode_data(allocator, (CFDataRef*)pl, error, der, der_end); case CCDER_GENERALIZED_TIME: { - const uint8_t* der_result = der_decode_date(allocator, mutability, (CFDateRef*)pl, error, der, der_end); + const uint8_t* der_result = der_decode_date(allocator, (CFDateRef*)pl, error, der, der_end); if (!der_result) { - der_result = repairBlock(allocator, mutability, pl, error, der, der_end); + der_result = repairBlock(allocator, pl, error, der, der_end); } return der_result; } case CCDER_CONSTRUCTED_SEQUENCE: - return der_decode_array_with_repair(allocator, mutability, (CFArrayRef*)pl, error, der, der_end, repairBlock); + return der_decode_array_with_repair(allocator, (CFArrayRef*)pl, error, der, der_end, repairBlock); case CCDER_UTF8_STRING: - return der_decode_string(allocator, mutability, (CFStringRef*)pl, error, der, der_end); + return der_decode_string(allocator, (CFStringRef*)pl, error, der, der_end); case CCDER_INTEGER: - return der_decode_number(allocator, mutability, (CFNumberRef*)pl, error, der, der_end); + return der_decode_number(allocator, (CFNumberRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_SET: - return der_decode_dictionary_with_repair(allocator, mutability, (CFDictionaryRef*)pl, error, der, der_end, repairBlock); + return der_decode_dictionary_with_repair(allocator, (CFDictionaryRef*)pl, error, der, der_end, repairBlock); case CCDER_CONSTRUCTED_CFSET: - return der_decode_set_with_repair(allocator, mutability, (CFSetRef*)pl, error, der, der_end, repairBlock); + return der_decode_set_with_repair(allocator, (CFSetRef*)pl, error, der, der_end, repairBlock); default: SecCFDERCreateError(kSecDERErrorUnsupportedDERType, CFSTR("Unsupported DER Type"), NULL, error); return NULL; } } -static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFDictionaryRef* dictionary, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { if (NULL == der) { @@ -1400,7 +1401,7 @@ static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator CFTypeRef key = NULL; CFTypeRef value = NULL; - payload = der_decode_key_value_with_repair(allocator, mutability, &key, &value, error, payload, payload_end, repairBlock); + payload = der_decode_key_value_with_repair(allocator, &key, &value, error, payload, payload_end, repairBlock); if (payload) { CFDictionaryAddValue(dict, key, value); @@ -1422,10 +1423,10 @@ exit: return payload; } -static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { const uint8_t *payload_end = 0; @@ -1440,8 +1441,8 @@ static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFTypeRef valueObject = NULL; - payload = der_decode_plist_with_repair(allocator, mutability, &keyObject, error, payload, payload_end, repairBlock); - payload = der_decode_plist_with_repair(allocator, mutability, &valueObject, error, payload, payload_end, repairBlock); + payload = der_decode_plist_with_repair(allocator, &keyObject, error, payload, payload_end, repairBlock); + payload = der_decode_plist_with_repair(allocator, &valueObject, error, payload, payload_end, repairBlock); if (payload != NULL) { *key = keyObject; @@ -1453,10 +1454,10 @@ static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, return payload; } -static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFArrayRef* array, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { if (NULL == der) { @@ -1471,7 +1472,7 @@ static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFO while (current_element != NULL && current_element < elements_end) { CFPropertyListRef element = NULL; - current_element = der_decode_plist_with_repair(allocator, mutability, &element, error, current_element, elements_end, repairBlock); + current_element = der_decode_plist_with_repair(allocator, &element, error, current_element, elements_end, repairBlock); if (current_element) { CFArrayAppendValue(result, element); CFReleaseNull(element); @@ -1487,10 +1488,10 @@ static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFO return current_element; } -static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { if (NULL == der) { @@ -1518,7 +1519,7 @@ static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFOpt while (payload != NULL && payload < payload_end) { CFTypeRef value = NULL; - payload = der_decode_plist_with_repair(allocator, mutability, &value, error, payload, payload_end, repairBlock); + payload = der_decode_plist_with_repair(allocator, &value, error, payload, payload_end, repairBlock); if (payload) { CFSetAddValue(theSet, value); diff --git a/keychain/securityd/SecDbKeychainItemV7.m b/keychain/securityd/SecDbKeychainItemV7.m index 90ccbe00..2d3372a8 100644 --- a/keychain/securityd/SecDbKeychainItemV7.m +++ b/keychain/securityd/SecDbKeychainItemV7.m @@ -109,7 +109,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { @property (readonly) NSData* serializedRepresentation; - (instancetype)initWithData:(NSData*)data; -- (instancetype)initWithCiphertext:(SFAuthenticatedCiphertext*)ciphertext wrappedKey:(SecDbKeychainAKSWrappedKey*)wrappedKey tamperCheck:(NSString*)tamperCheck backupWrappedKey:(SecDbBackupWrappedItemKey*)backupWrappedKey error:(NSError**)error; +- (instancetype)initWithCiphertext:(SFAuthenticatedCiphertext*)ciphertext wrappedKey:(SecDbKeychainAKSWrappedKey*)wrappedKey tamperCheck:(NSString*)tamperCheck backupWrappedKey:(SecDbBackupWrappedKey*)backupWrappedKey error:(NSError**)error; @end @@ -249,7 +249,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { - (instancetype)initWithCiphertext:(SFAuthenticatedCiphertext*)ciphertext wrappedKey:(SecDbKeychainAKSWrappedKey*)wrappedKey tamperCheck:(NSString*)tamperCheck - backupWrappedKey:(SecDbBackupWrappedItemKey*)backupWrappedKey + backupWrappedKey:(SecDbBackupWrappedKey*)backupWrappedKey error:(NSError**)error { if (self = [super init]) { @@ -412,8 +412,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { { if (!_metadataAttributes) { SFAESKey* metadataClassKey = [self metadataClassKeyWithKeybag:_keybag - createKeyIfMissing:false - overwriteCorruptKey:false + allowWrites:false error:error]; if (metadataClassKey) { NSError* localError = nil; @@ -569,8 +568,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { SFAuthenticatedCiphertext* ciphertext = [encryptionOperation encrypt:metadata withKey:key error:error]; SFAESKey* metadataClassKey = [self metadataClassKeyWithKeybag:keybag - createKeyIfMissing:true - overwriteCorruptKey:true + allowWrites:true error:error]; if (metadataClassKey) { SFAuthenticatedCiphertext* wrappedKey = [encryptionOperation encrypt:key.keyData withKey:metadataClassKey error:error]; @@ -607,7 +605,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { SFAuthenticatedCiphertext* ciphertext = [encryptionOperation encrypt:secretData withKey:key error:error]; SecDbKeychainAKSWrappedKey* wrappedKey = [self wrapToAKS:key withKeybag:keybag accessControl:accessControl acmContext:acmContext error:error]; - SecDbBackupWrappedItemKey* backupWrappedKey; + SecDbBackupWrappedKey* backupWrappedKey; if (checkV12DevEnabled()) { backupWrappedKey = [[SecDbBackupManager manager] wrapItemKey:key forKeyclass:_keyclass error:error]; if (backupWrappedKey) { @@ -629,15 +627,13 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { } - (SFAESKey*)metadataClassKeyWithKeybag:(keybag_handle_t)keybag - createKeyIfMissing:(bool)createIfMissing - overwriteCorruptKey:(bool)force + allowWrites:(bool)allowWrites error:(NSError**)error { return [[SecDbKeychainMetadataKeyStore sharedStore] keyForKeyclass:_keyclass keybag:keybag keySpecifier:[self.class keySpecifier] - createKeyIfMissing:(bool)createIfMissing - overwriteCorruptKey:force + allowWrites:allowWrites error:error]; } @@ -698,17 +694,17 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { size_t refKeyBlobLength = 0; const void* refKeyBlobBytes = aks_ref_key_get_blob(refKey, &refKeyBlobLength); - NSData* refKeyBlob = [[NSData alloc] initWithBytesNoCopy:(void*)refKeyBlobBytes length:refKeyBlobLength]; + NSData* refKeyBlob = [[NSData alloc] initWithBytes:(void*)refKeyBlobBytes length:refKeyBlobLength]; aks_ref_key_free(&refKey); return [[SecDbKeychainAKSWrappedKey alloc] initRefKeyWrappedKeyWithData:wrappedKey refKeyBlob:refKeyBlob]; } else { - NSMutableData* wrappedKey = [[NSMutableData alloc] initWithLength:(size_t)keyData.length + 40]; + NSMutableData* wrappedKey = [[NSMutableData alloc] initWithLength:APPLE_KEYSTORE_MAX_SYM_WRAPPED_KEY_LEN]; bool success = [SecAKSObjCWrappers aksEncryptWithKeybag:keybag keyclass:_keyclass plaintext:keyData outKeyclass:&_keyclass ciphertext:wrappedKey error:error]; return success ? [[SecDbKeychainAKSWrappedKey alloc] initRegularWrappedKeyWithData:wrappedKey] : nil; } #else - NSMutableData* wrappedKey = [[NSMutableData alloc] initWithLength:(size_t)keyData.length + 40]; + NSMutableData* wrappedKey = [[NSMutableData alloc] initWithLength:APPLE_KEYSTORE_MAX_SYM_WRAPPED_KEY_LEN]; bool success = [SecAKSObjCWrappers aksEncryptWithKeybag:keybag keyclass:_keyclass plaintext:keyData outKeyclass:&_keyclass ciphertext:wrappedKey error:error]; return success ? [[SecDbKeychainAKSWrappedKey alloc] initRegularWrappedKeyWithData:wrappedKey] : nil; #endif @@ -719,8 +715,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { NSData* wrappedKeyData = wrappedKey.wrappedKey; if (wrappedKey.type == SecDbKeychainAKSWrappedKeyTypeRegular) { - NSMutableData* unwrappedKey = [NSMutableData dataWithCapacity:wrappedKeyData.length + 40]; - unwrappedKey.length = wrappedKeyData.length + 40; + NSMutableData* unwrappedKey = [NSMutableData dataWithLength:APPLE_KEYSTORE_MAX_KEY_LEN]; bool result = [SecAKSObjCWrappers aksDecryptWithKeybag:_keybag keyclass:_keyclass ciphertext:wrappedKeyData outKeyclass:&_keyclass plaintext:unwrappedKey error:error]; if (result) { return [[SFAESKey alloc] initWithData:unwrappedKey specifier:[self.class keySpecifier] error:error]; @@ -742,7 +737,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { return nil; } NSDictionary* aclDict = nil; - der_decode_plist(NULL, kCFPropertyListImmutable, (CFPropertyListRef*)(void*)&aclDict, &cfError, refKeyExternalDataBytes, refKeyExternalDataBytes + refKeyExternalDataLength); + der_decode_plist(NULL, (CFPropertyListRef*)(void*)&aclDict, &cfError, refKeyExternalDataBytes, refKeyExternalDataBytes + refKeyExternalDataLength); if (!aclDict) { SecError(errSecDecode, &cfError, CFSTR("SecDbKeychainItemV7: failed to decode acl dict")); } @@ -779,14 +774,15 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { } CFPropertyListRef unwrappedKeyData = NULL; - der_decode_plist(NULL, kCFPropertyListImmutable, &unwrappedKeyData, &cfError, unwrappedKeyDERData, unwrappedKeyDERData + unwrappedKeyDERLength); + der_decode_plist(NULL, &unwrappedKeyData, &cfError, unwrappedKeyDERData, unwrappedKeyDERData + unwrappedKeyDERLength); SFAESKey* result = nil; if ([(__bridge NSData*)unwrappedKeyData isKindOfClass:[NSData class]]) { result = [[SFAESKey alloc] initWithData:(__bridge NSData*)unwrappedKeyData specifier:[self.class keySpecifier] error:error]; - CFReleaseNull(unwrappedKeyDERData); + CFReleaseNull(unwrappedKeyData); } else { SecError(errSecDecode, &cfError, CFSTR("SecDbKeychainItemV7: failed to decrypt item, Item can't be decrypted due to failed decode der, so drop the item.")); + CFReleaseNull(unwrappedKeyData); aks_ref_key_free(&refKey); free(aksParams); free(unwrappedKeyDERData); diff --git a/keychain/securityd/SecDbKeychainMetadataKeyStore.h b/keychain/securityd/SecDbKeychainMetadataKeyStore.h index 5c35094a..f49ee4d6 100644 --- a/keychain/securityd/SecDbKeychainMetadataKeyStore.h +++ b/keychain/securityd/SecDbKeychainMetadataKeyStore.h @@ -41,12 +41,11 @@ NS_ASSUME_NONNULL_BEGIN - (void)dropClassAKeys; -- (SFAESKey*)keyForKeyclass:(keyclass_t)keyClass - keybag:(keybag_handle_t)keybag - keySpecifier:(SFAESKeySpecifier*)keySpecifier - createKeyIfMissing:(bool)createIfMissing - overwriteCorruptKey:(bool)overwriteCorruptKey - error:(NSError**)error; +- (SFAESKey* _Nullable)keyForKeyclass:(keyclass_t)keyClass + keybag:(keybag_handle_t)keybag + keySpecifier:(SFAESKeySpecifier*)keySpecifier + allowWrites:(BOOL)allowWrites // (re)create keys if missing, corrupt or outdated format + error:(NSError**)error; @end diff --git a/keychain/securityd/SecDbKeychainMetadataKeyStore.m b/keychain/securityd/SecDbKeychainMetadataKeyStore.m index 860529cf..cd7a321a 100644 --- a/keychain/securityd/SecDbKeychainMetadataKeyStore.m +++ b/keychain/securityd/SecDbKeychainMetadataKeyStore.m @@ -27,9 +27,15 @@ #import #import "SecItemServer.h" #import "SecAKSObjCWrappers.h" +#import "SecDbBackupManager.h" +#import "SecDbKeychainSerializedMetadataKey.h" +#include "SecItemDb.h" // kc_transaction +#include "CheckV12DevEnabled.h" #import "sec_action.h" -static SecDbKeychainMetadataKeyStore* sharedStore = nil; +NS_ASSUME_NONNULL_BEGIN + +static SecDbKeychainMetadataKeyStore*_Nullable sharedStore = nil; static dispatch_queue_t sharedMetadataStoreQueue; static void initializeSharedMetadataStoreQueue(void) { static dispatch_once_t onceToken; @@ -51,9 +57,7 @@ static void initializeSharedMetadataStoreQueue(void) { initializeSharedMetadataStoreQueue(); dispatch_sync(sharedMetadataStoreQueue, ^{ if(sharedStore) { - dispatch_sync(sharedStore->_queue, ^{ - [sharedStore _onQueueDropAllKeys]; - }); + [sharedStore dropAllKeys]; } sharedStore = nil; }); @@ -128,6 +132,13 @@ static void initializeSharedMetadataStoreQueue(void) { _keysDict[@(key_class_akpu)] = nil; } +- (void)dropAllKeys +{ + dispatch_sync(_queue, ^{ + [self _onQueueDropAllKeys]; + }); +} + - (void)_onQueueDropAllKeys { dispatch_assert_queue(_queue); @@ -136,254 +147,350 @@ static void initializeSharedMetadataStoreQueue(void) { [_keysDict removeAllObjects]; } -- (void)_updateActualKeyclassIfNeeded:(keyclass_t)actualKeyclassToWriteBackToDB keyclass:(keyclass_t)keyclass +// Return SFAESKey and actual keyclass if NSData decrypts, or nil if it does not and populate error +- (SFAESKey* _Nullable)validateWrappedKey:(NSData*)wrapped + forKeyClass:(keyclass_t)keyclass + actualKeyClass:(keyclass_t*)outKeyclass + keybag:(keybag_handle_t)keybag + keySpecifier:(SFAESKeySpecifier*)specifier + error:(NSError**)error { - __block CFErrorRef cfError = NULL; - - secnotice("SecDbKeychainItemV7", "saving actualKeyclass %d for metadata keyclass %d", actualKeyclassToWriteBackToDB, keyclass); - - kc_with_dbt_non_item_tables(true, &cfError, ^bool(SecDbConnectionRef dbt) { - __block bool actualKeyWriteBackOk = true; - - // we did not find an actualKeyclass entry in the db, so let's add one in now. - NSString *sql = @"UPDATE metadatakeys SET actualKeyclass = ? WHERE keyclass = ? AND actualKeyclass IS NULL"; - __block CFErrorRef actualKeyWriteBackError = NULL; - actualKeyWriteBackOk &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &actualKeyWriteBackError, ^(sqlite3_stmt* stmt) { - actualKeyWriteBackOk &= SecDbBindInt(stmt, 1, actualKeyclassToWriteBackToDB, &actualKeyWriteBackError); - actualKeyWriteBackOk &= SecDbBindInt(stmt, 2, keyclass, &actualKeyWriteBackError); - actualKeyWriteBackOk &= SecDbStep(dbt, stmt, &actualKeyWriteBackError, ^(bool* stop) { - // woohoo - }); - }); - - if (actualKeyWriteBackOk) { - secnotice("SecDbKeychainItemV7", "successfully saved actualKeyclass %d for metadata keyclass %d", actualKeyclassToWriteBackToDB, keyclass); - - } - else { - // we can always try this again in the future if it failed - secerror("SecDbKeychainItemV7: failed to save actualKeyclass %d for metadata keyclass %d; error: %@", actualKeyclassToWriteBackToDB, keyclass, actualKeyWriteBackError); - } - return actualKeyWriteBackOk; - }); -} - -- (SFAESKey*)keyForKeyclass:(keyclass_t)keyclass - keybag:(keybag_handle_t)keybag - keySpecifier:(SFAESKeySpecifier*)keySpecifier - createKeyIfMissing:(bool)createIfMissing - overwriteCorruptKey:(bool)overwriteCorruptKey - error:(NSError**)error -{ - __block SFAESKey* key = nil; - __block NSError* nsErrorLocal = nil; - __block CFErrorRef cfError = NULL; - static __thread BOOL reentrant = NO; - - NSAssert(!reentrant, @"re-entering -[%@ %@] - that shouldn't happen!", NSStringFromClass(self.class), NSStringFromSelector(_cmd)); - reentrant = YES; - - keyclass = SecAKSSanitizedKeyclass(keyclass); - - dispatch_sync(_queue, ^{ - // if we think we're locked, it's possible AKS will still give us access to keys, such as during backup, - // but we should force AKS to be the truth and not used cached class A keys while locked - bool allowKeyCaching = [SecDbKeychainMetadataKeyStore cachingEnabled]; - - // However, we must not cache a newly-created key, just in case someone above us in the stack rolls back our database transaction and the stored key is lost. - __block bool keyIsNewlyCreated = false; -#if 0 - // Fix keychain lock state check to be both secure and fast for EDU mode - if (![SecDbKeychainItemV7 isKeychainUnlocked]) { - [self _onQueueDropClassAKeys]; - allowKeyCaching = !(keyclass == key_class_ak || keyclass == key_class_aku || keyclass == key_class_akpu); - } -#endif - - key = allowKeyCaching ? self->_keysDict[@(keyclass)] : nil; - if (!key) { - __block bool ok = true; - __block bool metadataKeyDoesntAuthenticate = false; - ok &= kc_with_dbt_non_item_tables(createIfMissing, &cfError, ^bool(SecDbConnectionRef dbt) { - __block NSString* sql = [NSString stringWithFormat:@"SELECT data, actualKeyclass FROM metadatakeys WHERE keyclass = %d", keyclass]; - ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &cfError, ^(sqlite3_stmt *stmt) { - ok &= SecDbStep(dbt, stmt, &cfError, ^(bool *stop) { - NSData* wrappedKeyData = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; - NSMutableData* unwrappedKeyData = [NSMutableData dataWithLength:wrappedKeyData.length]; - - keyclass_t actualKeyclass = sqlite3_column_int(stmt, 1); - - keyclass_t actualKeyclassToWriteBackToDB = 0; - keyclass_t keyclassForUnwrapping = actualKeyclass == 0 ? keyclass : actualKeyclass; - ok &= [SecAKSObjCWrappers aksDecryptWithKeybag:keybag keyclass:keyclassForUnwrapping ciphertext:wrappedKeyData outKeyclass:NULL plaintext:unwrappedKeyData error:&nsErrorLocal]; - if (ok) { - key = [[SFAESKey alloc] initWithData:unwrappedKeyData specifier:keySpecifier error:&nsErrorLocal]; - - if(!key) { - if (__security_simulatecrash_enabled()) { - os_log_fault(secLogObjForScope("SecDbKeychainItemV7"), "Metadata class key (%d) decrypted, but didn't become a key: %@", keyclass, nsErrorLocal); - } - } - - if (actualKeyclass == 0) { - actualKeyclassToWriteBackToDB = keyclassForUnwrapping; - } - } -#if USE_KEYSTORE - else if (actualKeyclass == 0 && keyclass <= key_class_last) { - // in this case we might have luck decrypting with a key-rolled keyclass - keyclass_t keyrolledKeyclass = keyclass | (key_class_last + 1); - secerror("SecDbKeychainItemV7: failed to decrypt metadata key for class %d, but trying keyrolled keyclass (%d); error: %@", keyclass, keyrolledKeyclass, nsErrorLocal); - - // we don't want to pollute subsequent error-handling logic with what happens on our retry - // we'll give it a shot, and if it works, great - if it doesn't work, we'll just report that error in the log and move on - NSError* retryError = nil; - ok = [SecAKSObjCWrappers aksDecryptWithKeybag:keybag keyclass:keyrolledKeyclass ciphertext:wrappedKeyData outKeyclass:NULL plaintext:unwrappedKeyData error:&retryError]; - - if (ok) { - secerror("SecDbKeychainItemV7: successfully decrypted metadata key using keyrolled keyclass %d", keyrolledKeyclass); - key = [[SFAESKey alloc] initWithData:unwrappedKeyData specifier:keySpecifier error:&retryError]; - - if(!key) { - if (__security_simulatecrash_enabled()) { - os_log_fault(secLogObjForScope("SecDbKeychainItemV7"), - "Metadata class key (%d) decrypted using keyrolled keyclass %d, but didn't become a key: %@", - keyclass, keyrolledKeyclass, retryError); - } - nsErrorLocal = retryError; - } - } - else { - secerror("SecDbKeychainItemV7: failed to decrypt metadata key with keyrolled keyclass %d; error: %@", keyrolledKeyclass, retryError); - } - } -#endif - - if (ok && key) { - if (actualKeyclassToWriteBackToDB > 0) { - // check if we have updated this keyclass or not already - static NSMutableDictionary* updated = NULL; - if (!updated) { - updated = [NSMutableDictionary dictionary]; - } - if (!updated[@(keyclass)]) { - updated[@(keyclass)] = @YES; - dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{ - [self _updateActualKeyclassIfNeeded:actualKeyclassToWriteBackToDB keyclass:keyclass]; - }); - } - } - } - else { - if (nsErrorLocal && [nsErrorLocal.domain isEqualToString:(__bridge NSString*)kSecErrorDomain] && nsErrorLocal.code == errSecInteractionNotAllowed) { - static dispatch_once_t kclockedtoken; - static sec_action_t kclockedaction; - dispatch_once(&kclockedtoken, ^{ - kclockedaction = sec_action_create("keychainlockedlogmessage", 1); - sec_action_set_handler(kclockedaction, ^{ - secerror("SecDbKeychainItemV7: failed to decrypt metadata key because the keychain is locked (%d)", (int)errSecInteractionNotAllowed); - }); - }); - sec_action_perform(kclockedaction); - } else { - secerror("SecDbKeychainItemV7: failed to decrypt and create metadata key for class %d; error: %@", keyclass, nsErrorLocal); - - // If this error is errSecDecode, then it's failed authentication and likely will forever. Other errors are scary. - metadataKeyDoesntAuthenticate = [nsErrorLocal.domain isEqualToString:NSOSStatusErrorDomain] && nsErrorLocal.code == errSecDecode; - if(metadataKeyDoesntAuthenticate) { - if (__security_simulatecrash_enabled()) { - os_log_fault(secLogObjForScope("SecDbKeychainItemV7"), "Metadata class key (%d) failed to decrypt: %@", keyclass, nsErrorLocal); - } - } - } - } - }); - }); - - bool keyNotYetCreated = ok && !key; - bool forceOverwriteBadKey = !key && metadataKeyDoesntAuthenticate && overwriteCorruptKey; - - if (createIfMissing && (keyNotYetCreated || forceOverwriteBadKey)) { - // we completed the database query, but no key exists or it's broken - we should create one - if(forceOverwriteBadKey) { - secerror("SecDbKeychainItemV7: metadata key is irreparably corrupt; throwing away forever"); - // TODO: track this in LocalKeychainAnalytics - } - - ok = true; // Reset 'ok': we have a second chance - - key = [[SFAESKey alloc] initRandomKeyWithSpecifier:keySpecifier error:&nsErrorLocal]; - keyIsNewlyCreated = true; - - if (key) { - NSMutableData* wrappedKey = [NSMutableData dataWithLength:key.keyData.length + 40]; - keyclass_t outKeyclass = keyclass; - ok &= [SecAKSObjCWrappers aksEncryptWithKeybag:keybag keyclass:keyclass plaintext:key.keyData outKeyclass:&outKeyclass ciphertext:wrappedKey error:&nsErrorLocal]; - if (ok) { - secinfo("SecDbKeychainItemV7", "attempting to save new metadata key for keyclass %d with actualKeyclass %d", keyclass, outKeyclass); - NSString* insertString = forceOverwriteBadKey ? @"INSERT OR REPLACE" : @"INSERT"; - sql = [NSString stringWithFormat:@"%@ into metadatakeys (keyclass, actualKeyclass, data) VALUES (?, ?, ?)", insertString]; - ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &cfError, ^(sqlite3_stmt* stmt) { - ok &= SecDbBindInt(stmt, 1, keyclass, &cfError); - ok &= SecDbBindInt(stmt, 2, outKeyclass, &cfError); - ok &= SecDbBindBlob(stmt, 3, wrappedKey.bytes, wrappedKey.length, SQLITE_TRANSIENT, NULL); - ok &= SecDbStep(dbt, stmt, &cfError, ^(bool *stop) { - // woohoo - }); - }); - - if (ok) { - secnotice("SecDbKeychainItemV7", "successfully saved new metadata key for keyclass %d", keyclass); - } - else { - secerror("SecDbKeychainItemV7: failed to save new metadata key for keyclass %d - probably there is already one in the database: %@", keyclass, cfError); - } - } else { - secerror("SecDbKeychainItemV7: unable to encrypt new metadata key(%d) with keybag(%d): %@", keyclass, keybag, nsErrorLocal); - } - } - else { - ok = false; - } - } else if(!key) { - // No key, but we're not supposed to make one. Make an error if one doesn't yet exist. - ok = false; - if(!nsErrorLocal) { - nsErrorLocal = [NSError errorWithDomain:(id)kSecErrorDomain code:errSecDecode userInfo:@{NSLocalizedDescriptionKey: @"Unable to find or create a suitable metadata key"}]; - } - } - - return ok; - }); - - if (ok && key) { - // We can't cache a newly-created key, just in case this db transaction is rolled back and we lose the persisted key. - // Don't worry, we'll cache it as soon as it's used again. - if (allowKeyCaching && !keyIsNewlyCreated) { - self->_keysDict[@(keyclass)] = key; - __weak __typeof(self) weakSelf = self; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60 * 5 * NSEC_PER_SEC)), self->_queue, ^{ - [weakSelf _onQueueDropClassAKeys]; - }); - } - } - else { - key = nil; - } - } - }); - - reentrant = NO; - - if (error && nsErrorLocal) { - *error = nsErrorLocal; - CFReleaseNull(cfError); + keyclass_t classToUse = keyclass; + if (*outKeyclass != key_class_none && *outKeyclass != keyclass) { + classToUse = *outKeyclass; } - else { - BridgeCFErrorToNSErrorOut(error, cfError); + + NSMutableData* unwrapped = [NSMutableData dataWithLength:APPLE_KEYSTORE_MAX_KEY_LEN]; + SFAESKey* key = NULL; + NSError *localError = nil; + if ([SecAKSObjCWrappers aksDecryptWithKeybag:keybag keyclass:classToUse ciphertext:wrapped outKeyclass:NULL plaintext:unwrapped error:&localError]) { + key = [[SFAESKey alloc] initWithData:unwrapped specifier:specifier error:&localError]; + if (!key) { + secerror("SecDbKeychainItemV7: AKS decrypted metadata blob for class %d but could not turn it into a key: %@", classToUse, localError); + } + } +#if USE_KEYSTORE + else if (classToUse < key_class_last && *outKeyclass == key_class_none) { + *outKeyclass = classToUse | (key_class_last + 1); + if ([SecAKSObjCWrappers aksDecryptWithKeybag:keybag keyclass:*outKeyclass ciphertext:wrapped outKeyclass:NULL plaintext:unwrapped error:&localError]) { + key = [[SFAESKey alloc] initWithData:unwrapped specifier:specifier error:&localError]; + } + } +#endif + if (!key) { + // Don't be noisy for mundane error + if (!([localError.domain isEqualToString:(__bridge NSString*)kSecErrorDomain] && localError.code == errSecInteractionNotAllowed)) { + secerror("SecDbKeychainItemV7: Unable to create key from retrieved data: %@", localError); + } + if (error) { + *error = localError; + } } return key; } +- (SFAESKey* _Nullable)newKeyForKeyclass:(keyclass_t)keyclass + withKeybag:(keybag_handle_t)keybag + keySpecifier:(SFAESKeySpecifier*)specifier + database:(SecDbConnectionRef)dbt + error:(NSError**)error +{ + NSError *localError = nil; + SFAESKey* key = [[SFAESKey alloc] initRandomKeyWithSpecifier:specifier error:&localError]; + if (!key) { + if (error) { + *error = localError; + } + return nil; + } + return [self writeKey:key ForKeyclass:keyclass withKeybag:keybag keySpecifier:specifier database:dbt error:error]; +} + +- (SFAESKey* _Nullable)writeKey:(SFAESKey*)key + ForKeyclass:(keyclass_t)keyclass + withKeybag:(keybag_handle_t)keybag + keySpecifier:(SFAESKeySpecifier*)specifier + database:(SecDbConnectionRef)dbt + error:(NSError**)error +{ + NSError *localError = nil; + dispatch_assert_queue(_queue); + + NSMutableData* wrappedKey = [NSMutableData dataWithLength:APPLE_KEYSTORE_MAX_SYM_WRAPPED_KEY_LEN]; + keyclass_t outKeyclass = keyclass; + + if (![SecAKSObjCWrappers aksEncryptWithKeybag:keybag keyclass:keyclass plaintext:key.keyData outKeyclass:&outKeyclass ciphertext:wrappedKey error:&localError]) { + secerror("SecDbMetadataKeyStore: Unable to encrypt new metadata key to keybag: %@", localError); + if (error) { + *error = localError; + } + return nil; + } + + NSData* mdkdatablob; + if (checkV12DevEnabled()) { + SecDbBackupWrappedKey* backupWrappedKey; + if (SecAKSSanitizedKeyclass(keyclass) != key_class_akpu) { + backupWrappedKey = [[SecDbBackupManager manager] wrapMetadataKey:key forKeyclass:keyclass error:&localError]; + if (!backupWrappedKey) { + secerror("SecDbMetadataKeyStore: Unable to encrypt new metadata key to backup infrastructure: %@", localError); + if (error) { + *error = localError; + } + return nil; + } + } + + SecDbKeychainSerializedMetadataKey* metadatakeydata = [SecDbKeychainSerializedMetadataKey new]; + metadatakeydata.keyclass = keyclass; + metadatakeydata.actualKeyclass = outKeyclass; + metadatakeydata.baguuid = backupWrappedKey.baguuid; + metadatakeydata.akswrappedkey = wrappedKey; + metadatakeydata.backupwrappedkey = backupWrappedKey.wrappedKey; + mdkdatablob = [metadatakeydata data]; + } + + __block bool ok = true; + __block CFErrorRef cfErr = NULL; + NSString* sql; + if (checkV12DevEnabled()) { + sql = @"INSERT OR REPLACE INTO metadatakeys (keyclass, actualKeyclass, data, metadatakeydata) VALUES (?,?,?,?)"; + } else { + sql = @"INSERT OR REPLACE INTO metadatakeys (keyclass, actualKeyclass, data) VALUES (?,?,?)"; + } + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &cfErr, ^(sqlite3_stmt *stmt) { + ok &= SecDbBindObject(stmt, 1, (__bridge CFNumberRef)@(keyclass), &cfErr); + ok &= SecDbBindObject(stmt, 2, (__bridge CFNumberRef)@(outKeyclass), &cfErr); + if (!checkV12DevEnabled()) { + ok &= SecDbBindBlob(stmt, 3, wrappedKey.bytes, wrappedKey.length, SQLITE_TRANSIENT, &cfErr); + } else { + // Leave stmt param 3 unbound so SQLite will NULL it out + ok &= SecDbBindBlob(stmt, 4, mdkdatablob.bytes, mdkdatablob.length, SQLITE_TRANSIENT, &cfErr); + } + ok &= SecDbStep(dbt, stmt, &cfErr, NULL); + }); + + if (!ok) { + secerror("Failed to write new metadata key for %d: %@", keyclass, cfErr); + BridgeCFErrorToNSErrorOut(error, cfErr); + return nil; + } + + return key; +} + +- (BOOL)readKeyDataForClass:(keyclass_t)keyclass + fromDb:(SecDbConnectionRef)dbt + actualKeyclass:(keyclass_t*)actualKeyclass + oldFormatData:(NSData**)oldFmt + newFormatData:(NSData**)newFmt + error:(NSError**)error +{ + dispatch_assert_queue(_queue); + + NSString* sql; + if (checkV12DevEnabled()) { + sql = @"SELECT data, actualKeyclass, metadatakeydata FROM metadatakeys WHERE keyclass = ?"; + } else { + sql = @"SELECT data, actualKeyclass FROM metadatakeys WHERE keyclass = ?"; + } + + __block NSData* wrappedKey; + __block NSData* mdkdatablob; + __block bool ok = true; + __block bool found = false; + __block CFErrorRef cfError = NULL; + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &cfError, ^(sqlite3_stmt *stmt) { + ok &= SecDbBindObject(stmt, 1, (__bridge CFNumberRef)@(keyclass), &cfError); + ok &= SecDbStep(dbt, stmt, &cfError, ^(bool *stop) { + wrappedKey = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; + *actualKeyclass = sqlite3_column_int(stmt, 1); + mdkdatablob = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 2) length:sqlite3_column_bytes(stmt, 2)]; + found = true; + }); + }); + + // ok && !found means no error is passed back, which is specifically handled in keyForKeyclass + if (!ok || !found) { + BridgeCFErrorToNSErrorOut(error, cfError); + *actualKeyclass = key_class_none; + return NO; + } + + *oldFmt = wrappedKey; + *newFmt = mdkdatablob; + return YES; +} + +- (SFAESKey* _Nullable)fetchKeyForClass:(keyclass_t)keyclass + fromDb:(SecDbConnectionRef)dbt + keybag:(keybag_handle_t)keybag + specifier:(SFAESKeySpecifier*)keySpecifier + allowWrites:(BOOL)allowWrites + error:(NSError**)error +{ + dispatch_assert_queue(_queue); + + NSData* wrappedKey; + NSData* mdkdatablob; + keyclass_t actualKeyClass = key_class_none; + if (![self readKeyDataForClass:keyclass fromDb:dbt actualKeyclass:&actualKeyClass oldFormatData:&wrappedKey newFormatData:&mdkdatablob error:error]) { + return nil; + } + + // each entry should be either old format or new format. Otherwise this is a bug. + if (!(wrappedKey.length == 0 ^ mdkdatablob.length == 0)) { + if (error) { + *error = [NSError errorWithDomain:(id)kSecErrorDomain code:errSecInternal userInfo:@{NSLocalizedDescriptionKey: @"Metadata key blob both old-world and new-world"}]; + } + return nil; + } + + SFAESKey* key; + BOOL rewrite = NO; + keyclass_t classFromDisk = key_class_none; + if (wrappedKey.length > 0) { // old format read + classFromDisk = actualKeyClass; + key = [self validateWrappedKey:wrappedKey forKeyClass:keyclass actualKeyClass:&actualKeyClass keybag:keybag keySpecifier:keySpecifier error:error]; + if (!key) { + return nil; + } + if (checkV12DevEnabled()) { + rewrite = YES; + } + } else if (mdkdatablob.length > 0) { // new format read + SecDbKeychainSerializedMetadataKey* mdkdata = [[SecDbKeychainSerializedMetadataKey alloc] initWithData:mdkdatablob]; + if (!mdkdata) { + // bad read, key corrupt? + if (error) { + *error = [NSError errorWithDomain:(id)kSecErrorDomain code:errSecDecode userInfo:@{NSLocalizedDescriptionKey: @"New-format metadata key blob didn't deserialize"}]; + } + return nil; + } + + // Ignore the old-read actualKeyClass and use blob + actualKeyClass = mdkdata.actualKeyclass; + classFromDisk = mdkdata.actualKeyclass; + key = [self validateWrappedKey:mdkdata.akswrappedkey forKeyClass:keyclass actualKeyClass:&actualKeyClass keybag:keybag keySpecifier:keySpecifier error:error]; + if (!key) { + return nil; + } + + if (!mdkdata.backupwrappedkey || ![mdkdata.baguuid isEqual:[[SecDbBackupManager manager] currentBackupBagUUID]]) { + rewrite = YES; + secnotice("SecDbMetadataKeyStore", "Metadata key for %d has no or mismatching backup data; will rewrite.", keyclass); + } + + } else { // Wait, there's a row for this class but not something which might be a key? + secnotice("SecDbMetadataKeyStore", "No metadata key found on disk despite existing row. That's odd."); + return nil; + } + + if (allowWrites && (rewrite || classFromDisk != actualKeyClass)) { + NSError* localError; + if (![self writeKey:key ForKeyclass:keyclass withKeybag:keybag keySpecifier:keySpecifier database:dbt error:&localError]) { + // if this fails we can try again in future + secwarning("SecDbMetadataKeyStore: Unable to rewrite metadata key for %d to new format: %@", keyclass, localError); + localError = nil; + } + } + + return key; +} + +- (SFAESKey* _Nullable)keyForKeyclass:(keyclass_t)keyclass + keybag:(keybag_handle_t)keybag + keySpecifier:(SFAESKeySpecifier*)keySpecifier + allowWrites:(BOOL)allowWrites + error:(NSError**)error +{ + if (!error) { + secerror("keyForKeyclass called without error param, this is a bug"); + return nil; + } + + static __thread BOOL reentrant = NO; + NSAssert(!reentrant, @"re-entering -[%@ %@] - that shouldn't happen!", NSStringFromClass(self.class), NSStringFromSelector(_cmd)); + reentrant = YES; + + keyclass = SecAKSSanitizedKeyclass(keyclass); + + __block SFAESKey* key = nil; + __block NSError* nsErrorLocal = nil; + __block CFErrorRef cfError = NULL; + __block bool ok = true; + dispatch_sync(_queue, ^{ + // try our cache first and rejoice if that succeeds + bool allowCaching = [SecDbKeychainMetadataKeyStore cachingEnabled]; + + key = allowCaching ? self->_keysDict[@(keyclass)] : nil; + if (key) { + return; // Cache contains validated key for class, excellent! + } + + // Key not in cache. Open a transaction to find or optionally (re)create key. Transactions can be nested, so this is fine. + ok &= kc_with_dbt_non_item_tables(true, &cfError, ^bool(SecDbConnectionRef dbt) { + key = [self fetchKeyForClass:keyclass + fromDb:dbt + keybag:keybag + specifier:keySpecifier + allowWrites:allowWrites + error:&nsErrorLocal]; + + // The code for this conditional is a little convoluted because I want the "keychain locked" message to take precedence over the "not allowed to create one" message. + if (!key && ([nsErrorLocal.domain isEqualToString:(__bridge NSString*)kSecErrorDomain] && nsErrorLocal.code == errSecInteractionNotAllowed)) { + static sec_action_t logKeychainLockedMessageAction; + static dispatch_once_t keychainLockedMessageOnceToken; + dispatch_once(&keychainLockedMessageOnceToken, ^{ + logKeychainLockedMessageAction = sec_action_create("keychainlockedlogmessage", 1); + sec_action_set_handler(logKeychainLockedMessageAction, ^{ + secerror("SecDbKeychainItemV7: cannot decrypt metadata key because the keychain is locked (%ld)", (long)nsErrorLocal.code); + }); + }); + sec_action_perform(logKeychainLockedMessageAction); + } else if (!key && !allowWrites) { + secwarning("SecDbMetadataKeyStore: Unable to load metadatakey for class %d from disk (%@) and not allowed to create new one", keyclass, nsErrorLocal); + if (!nsErrorLocal) { + // If this is at creation time we are allowed to create so won't be here + // If this is at fetch time and we have a missing or bad key then the item /is/ dead + nsErrorLocal = [NSError errorWithDomain:(id)kSecErrorDomain code:errSecDecode userInfo:@{NSLocalizedDescriptionKey: @"Unable to find a suitable metadata key and not permitted to create one"}]; + } + return false; + // If this error is errSecDecode, then it's failed authentication and likely will forever. Other errors are scary. If !key and !error then no key existed. + } else if ((!key && !nsErrorLocal) || (!key && [nsErrorLocal.domain isEqualToString:NSOSStatusErrorDomain] && nsErrorLocal.code == errSecDecode)) { + secwarning("SecDbMetadataKeyStore: unable to use key (%ld), will attempt to create new one", (long)nsErrorLocal.code); + nsErrorLocal = nil; + key = [self newKeyForKeyclass:keyclass withKeybag:keybag keySpecifier:keySpecifier database:dbt error:&nsErrorLocal]; + if (!key) { + secerror("SecDbMetadataKeyStore: unable to create or save new key: %@", nsErrorLocal); + return false; + } + } else if (!key) { + secerror("SecDbMetadataKeyStore: scary error encountered: %@", nsErrorLocal); + } else if (allowCaching) { + self->_keysDict[@(keyclass)] = key; // Only cache keys fetched from disk + } + return !!key; + }); // kc_with_dbt + }); // our queue + + if (!ok || !key) { + if (nsErrorLocal) { + *error = nsErrorLocal; + CFReleaseNull(cfError); + } else { + BridgeCFErrorToNSErrorOut(error, cfError); + } + assert(*error); // Triggers only in testing, which is by design not to break production + key = nil; + } + + reentrant = NO; + + return key; +} + @end + +NS_ASSUME_NONNULL_END diff --git a/keychain/securityd/SecDbKeychainV7-protobufs/SecDbKeychainSerializedMetadataKey.proto b/keychain/securityd/SecDbKeychainV7-protobufs/SecDbKeychainSerializedMetadataKey.proto new file mode 100644 index 00000000..0e4f960e --- /dev/null +++ b/keychain/securityd/SecDbKeychainV7-protobufs/SecDbKeychainSerializedMetadataKey.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; + +message SecDbKeychainSerializedMetadataKey { + optional int32 keyclass = 1; + optional int32 actualKeyclass = 2; + optional bytes baguuid = 3; + optional bytes akswrappedkey = 4; + optional bytes backupwrappedkey = 5; +} diff --git a/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.h b/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.h new file mode 100644 index 00000000..9ff7f68d --- /dev/null +++ b/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.h @@ -0,0 +1,55 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from SecDbKeychainSerializedMetadataKey.proto + +#import +#import + +#ifdef __cplusplus +#define SECDBKEYCHAINSERIALIZEDMETADATAKEY_FUNCTION extern "C" +#else +#define SECDBKEYCHAINSERIALIZEDMETADATAKEY_FUNCTION extern +#endif + +@interface SecDbKeychainSerializedMetadataKey : PBCodable +{ + int32_t _actualKeyclass; + NSData *_akswrappedkey; + NSData *_backupwrappedkey; + NSData *_baguuid; + int32_t _keyclass; + struct { + int actualKeyclass:1; + int keyclass:1; + } _has; +} + + +@property (nonatomic) BOOL hasKeyclass; +@property (nonatomic) int32_t keyclass; + +@property (nonatomic) BOOL hasActualKeyclass; +@property (nonatomic) int32_t actualKeyclass; + +@property (nonatomic, readonly) BOOL hasBaguuid; +@property (nonatomic, retain) NSData *baguuid; + +@property (nonatomic, readonly) BOOL hasAkswrappedkey; +@property (nonatomic, retain) NSData *akswrappedkey; + +@property (nonatomic, readonly) BOOL hasBackupwrappedkey; +@property (nonatomic, retain) NSData *backupwrappedkey; + +// Performs a shallow copy into other +- (void)copyTo:(SecDbKeychainSerializedMetadataKey *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(SecDbKeychainSerializedMetadataKey *)other; + +SECDBKEYCHAINSERIALIZEDMETADATAKEY_FUNCTION BOOL SecDbKeychainSerializedMetadataKeyReadFrom(__unsafe_unretained SecDbKeychainSerializedMetadataKey *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.m b/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.m new file mode 100644 index 00000000..b16f7a51 --- /dev/null +++ b/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.m @@ -0,0 +1,294 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from SecDbKeychainSerializedMetadataKey.proto + +#import "SecDbKeychainSerializedMetadataKey.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation SecDbKeychainSerializedMetadataKey + +@synthesize keyclass = _keyclass; +- (void)setKeyclass:(int32_t)v +{ + _has.keyclass = YES; + _keyclass = v; +} +- (void)setHasKeyclass:(BOOL)f +{ + _has.keyclass = f; +} +- (BOOL)hasKeyclass +{ + return _has.keyclass != 0; +} +@synthesize actualKeyclass = _actualKeyclass; +- (void)setActualKeyclass:(int32_t)v +{ + _has.actualKeyclass = YES; + _actualKeyclass = v; +} +- (void)setHasActualKeyclass:(BOOL)f +{ + _has.actualKeyclass = f; +} +- (BOOL)hasActualKeyclass +{ + return _has.actualKeyclass != 0; +} +- (BOOL)hasBaguuid +{ + return _baguuid != nil; +} +@synthesize baguuid = _baguuid; +- (BOOL)hasAkswrappedkey +{ + return _akswrappedkey != nil; +} +@synthesize akswrappedkey = _akswrappedkey; +- (BOOL)hasBackupwrappedkey +{ + return _backupwrappedkey != nil; +} +@synthesize backupwrappedkey = _backupwrappedkey; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.keyclass) + { + [dict setObject:[NSNumber numberWithInt:self->_keyclass] forKey:@"keyclass"]; + } + if (self->_has.actualKeyclass) + { + [dict setObject:[NSNumber numberWithInt:self->_actualKeyclass] forKey:@"actualKeyclass"]; + } + if (self->_baguuid) + { + [dict setObject:self->_baguuid forKey:@"baguuid"]; + } + if (self->_akswrappedkey) + { + [dict setObject:self->_akswrappedkey forKey:@"akswrappedkey"]; + } + if (self->_backupwrappedkey) + { + [dict setObject:self->_backupwrappedkey forKey:@"backupwrappedkey"]; + } + return dict; +} + +BOOL SecDbKeychainSerializedMetadataKeyReadFrom(__unsafe_unretained SecDbKeychainSerializedMetadataKey *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* keyclass */: + { + self->_has.keyclass = YES; + self->_keyclass = PBReaderReadInt32(reader); + } + break; + case 2 /* actualKeyclass */: + { + self->_has.actualKeyclass = YES; + self->_actualKeyclass = PBReaderReadInt32(reader); + } + break; + case 3 /* baguuid */: + { + NSData *new_baguuid = PBReaderReadData(reader); + self->_baguuid = new_baguuid; + } + break; + case 4 /* akswrappedkey */: + { + NSData *new_akswrappedkey = PBReaderReadData(reader); + self->_akswrappedkey = new_akswrappedkey; + } + break; + case 5 /* backupwrappedkey */: + { + NSData *new_backupwrappedkey = PBReaderReadData(reader); + self->_backupwrappedkey = new_backupwrappedkey; + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return SecDbKeychainSerializedMetadataKeyReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* keyclass */ + { + if (self->_has.keyclass) + { + PBDataWriterWriteInt32Field(writer, self->_keyclass, 1); + } + } + /* actualKeyclass */ + { + if (self->_has.actualKeyclass) + { + PBDataWriterWriteInt32Field(writer, self->_actualKeyclass, 2); + } + } + /* baguuid */ + { + if (self->_baguuid) + { + PBDataWriterWriteDataField(writer, self->_baguuid, 3); + } + } + /* akswrappedkey */ + { + if (self->_akswrappedkey) + { + PBDataWriterWriteDataField(writer, self->_akswrappedkey, 4); + } + } + /* backupwrappedkey */ + { + if (self->_backupwrappedkey) + { + PBDataWriterWriteDataField(writer, self->_backupwrappedkey, 5); + } + } +} + +- (void)copyTo:(SecDbKeychainSerializedMetadataKey *)other +{ + if (self->_has.keyclass) + { + other->_keyclass = _keyclass; + other->_has.keyclass = YES; + } + if (self->_has.actualKeyclass) + { + other->_actualKeyclass = _actualKeyclass; + other->_has.actualKeyclass = YES; + } + if (_baguuid) + { + other.baguuid = _baguuid; + } + if (_akswrappedkey) + { + other.akswrappedkey = _akswrappedkey; + } + if (_backupwrappedkey) + { + other.backupwrappedkey = _backupwrappedkey; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + SecDbKeychainSerializedMetadataKey *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.keyclass) + { + copy->_keyclass = _keyclass; + copy->_has.keyclass = YES; + } + if (self->_has.actualKeyclass) + { + copy->_actualKeyclass = _actualKeyclass; + copy->_has.actualKeyclass = YES; + } + copy->_baguuid = [_baguuid copyWithZone:zone]; + copy->_akswrappedkey = [_akswrappedkey copyWithZone:zone]; + copy->_backupwrappedkey = [_backupwrappedkey copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + SecDbKeychainSerializedMetadataKey *other = (SecDbKeychainSerializedMetadataKey *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.keyclass && other->_has.keyclass && self->_keyclass == other->_keyclass) || (!self->_has.keyclass && !other->_has.keyclass)) + && + ((self->_has.actualKeyclass && other->_has.actualKeyclass && self->_actualKeyclass == other->_actualKeyclass) || (!self->_has.actualKeyclass && !other->_has.actualKeyclass)) + && + ((!self->_baguuid && !other->_baguuid) || [self->_baguuid isEqual:other->_baguuid]) + && + ((!self->_akswrappedkey && !other->_akswrappedkey) || [self->_akswrappedkey isEqual:other->_akswrappedkey]) + && + ((!self->_backupwrappedkey && !other->_backupwrappedkey) || [self->_backupwrappedkey isEqual:other->_backupwrappedkey]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.keyclass ? PBHashInt((NSUInteger)self->_keyclass) : 0) + ^ + (self->_has.actualKeyclass ? PBHashInt((NSUInteger)self->_actualKeyclass) : 0) + ^ + [self->_baguuid hash] + ^ + [self->_akswrappedkey hash] + ^ + [self->_backupwrappedkey hash] + ; +} + +- (void)mergeFrom:(SecDbKeychainSerializedMetadataKey *)other +{ + if (other->_has.keyclass) + { + self->_keyclass = other->_keyclass; + self->_has.keyclass = YES; + } + if (other->_has.actualKeyclass) + { + self->_actualKeyclass = other->_actualKeyclass; + self->_has.actualKeyclass = YES; + } + if (other->_baguuid) + { + [self setBaguuid:other->_baguuid]; + } + if (other->_akswrappedkey) + { + [self setAkswrappedkey:other->_akswrappedkey]; + } + if (other->_backupwrappedkey) + { + [self setBackupwrappedkey:other->_backupwrappedkey]; + } +} + +@end + diff --git a/keychain/securityd/SecDbQuery.c b/keychain/securityd/SecDbQuery.c index 88d72177..f6d32354 100644 --- a/keychain/securityd/SecDbQuery.c +++ b/keychain/securityd/SecDbQuery.c @@ -412,11 +412,6 @@ void query_add_not_attribute(const void *key, const void *value, Query *q) } } - -/* AUDIT[securityd](done): - key (ok) is a caller provided, string starting with 'm'. - value (ok) is a caller provided, non NULL CFTypeRef. - */ static void query_add_match(const void *key, const void *value, Query *q) { /* Record the match key, value in q_pairs. */ @@ -874,6 +869,7 @@ bool query_notify_and_destroy(Query *q, bool ok, CFErrorRef *error) { Query *query_create(const SecDbClass *qclass, CFDataRef musr, CFDictionaryRef query, + SecurityClient* client, CFErrorRef *error) { if (!qclass) { @@ -926,6 +922,16 @@ Query *query_create(const SecDbClass *qclass, q->q_match_begin = q->q_match_end = key_count; q->q_item = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (client) { + // If not, don't do anything. Parent apps, schema migration, etc. all need access to all items, clip or no + if (client->isAppClip) { + secdebug("query", "Client is app clip, adding restriction to query attribute"); + CFDictionaryAddValue(q->q_item, kSecAttrAppClipItem, kCFBooleanTrue); + } + } else { + secdebug("query", "no client information specified so not tweaking query attributes"); + } + return q; } @@ -949,9 +955,9 @@ bool query_update_parse(Query *q, CFDictionaryRef update, return query_parse_with_applier(q, update, query_update_applier, error); } -Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, CFErrorRef *error) { +Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, SecurityClient* client, CFErrorRef *error) { Query *q; - q = query_create(query_get_class(query, error), musr, query, error); + q = query_create(query_get_class(query, error), musr, query, client, error); if (q) { q->q_limit = limit; if (!query_parse(q, query, error)) { diff --git a/keychain/securityd/SecDbQuery.h b/keychain/securityd/SecDbQuery.h index 820090bf..861c3ca3 100644 --- a/keychain/securityd/SecDbQuery.h +++ b/keychain/securityd/SecDbQuery.h @@ -30,6 +30,7 @@ #include "keychain/securityd/SecKeybagSupport.h" #include "keychain/securityd/SecDbItem.h" +#include "ipc/securityd_client.h" // be able to create queries which restrict API __BEGIN_DECLS @@ -116,9 +117,16 @@ typedef struct Query // instead of reporting them to the client as an error. bool q_skip_acl_items; + // Some queries (e.g. backups) explicitly do not want to deal with clip-created items + bool q_skip_app_clip_items; + // Set to true if any UUIDs generated by this query should be generated from the SHA2 digest of the item in question bool q_uuid_from_primary_key; + // Set to true if you'd like any Tombstones created by this query to have an mdat that is one second after the non-tombstone's mdat. + // This is used if you're deleting an item, but are unsure when the item deletion occurred (e.g., you receive an item delete via CloudKit). + bool q_tombstone_use_mdat_from_item; + // Set this to a callback that, on an add query, will get passed along with the CKKS subsystem and called when the item makes it off-device (or doesn't) __unsafe_unretained SecBoolCFErrorCallback q_add_sync_callback; @@ -146,10 +154,10 @@ typedef struct Query Pair q_pairs[]; } Query; -Query *query_create(const SecDbClass *qclass, CFDataRef musr, CFDictionaryRef query, CFErrorRef *error); +Query *query_create(const SecDbClass *qclass, CFDataRef musr, CFDictionaryRef query, SecurityClient* client, CFErrorRef *error); bool query_destroy(Query *q, CFErrorRef *error); bool query_error(Query *q, CFErrorRef *error); -Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, CFErrorRef *error); +Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, SecurityClient* client, CFErrorRef *error); void query_add_attribute(const void *key, const void *value, Query *q); void query_add_or_attribute(const void *key, const void *value, Query *q); void query_add_not_attribute(const void *key, const void *value, Query *q); diff --git a/keychain/securityd/SecItemBackupServer.c b/keychain/securityd/SecItemBackupServer.c index 78591837..605cfd19 100644 --- a/keychain/securityd/SecItemBackupServer.c +++ b/keychain/securityd/SecItemBackupServer.c @@ -78,6 +78,16 @@ CFArrayRef SecServerItemBackupCopyNames(CFErrorRef *error) { return names; } +CFStringRef SecServerItemBackupEnsureCopyView(CFStringRef viewName, CFErrorRef *error) { + __block CFStringRef name = NULL; + if(!withDataSourceAndEngine(error, ^(SOSDataSourceRef ds, SOSEngineRef engine) { + name = SOSEngineEnsureCopyBackupPeerForView(engine, viewName, error); + })) { + CFReleaseNull(name); + } + return name; +} + // TODO Move to datasource and remove dsRestoreObject static bool SOSDataSourceWithBackup(SOSDataSourceRef ds, CFDataRef backup, keybag_handle_t bag_handle, CFErrorRef *error, void(^with)(SOSObjectRef item)) { __block bool ok = true; diff --git a/keychain/securityd/SecItemBackupServer.h b/keychain/securityd/SecItemBackupServer.h index 04607c60..87156d28 100644 --- a/keychain/securityd/SecItemBackupServer.h +++ b/keychain/securityd/SecItemBackupServer.h @@ -37,6 +37,7 @@ __BEGIN_DECLS int SecServerItemBackupHandoffFD(CFStringRef backupName, CFErrorRef *error); bool SecServerItemBackupSetConfirmedManifest(CFStringRef backupName, CFDataRef keybagDigest, CFDataRef manifest, CFErrorRef *error); CFArrayRef SecServerItemBackupCopyNames(CFErrorRef *error); +CFStringRef SecServerItemBackupEnsureCopyView(CFStringRef peerID, CFErrorRef *error); bool SecServerItemBackupRestore(CFStringRef backupName, CFStringRef peerID, CFDataRef keybag, CFDataRef secret, CFDataRef backup, CFErrorRef *error); __END_DECLS diff --git a/keychain/securityd/SecItemDataSource.c b/keychain/securityd/SecItemDataSource.c index d2630a70..9f6232e2 100644 --- a/keychain/securityd/SecItemDataSource.c +++ b/keychain/securityd/SecItemDataSource.c @@ -43,9 +43,6 @@ #include #include #include -#ifdef DARLING -#include -#endif /* * @@ -161,7 +158,7 @@ static SOSManifestRef SecItemDataSourceCopyManifestWithQueries(SecItemDataSource } static Query *SecItemDataSourceAppendQuery(CFMutableArrayRef queries, const SecDbClass *qclass, bool noTombstones, CFErrorRef *error) { - Query *q = query_create(qclass, NULL, NULL, error); + Query *q = query_create(qclass, NULL, NULL, NULL, error); if (q) { q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; q->q_limit = kSecMatchUnlimited; @@ -307,6 +304,7 @@ static SOSManifestRef SecItemDataSourceCopyManifestWithViewNameSet(SecItemDataSo } // Return the newest object (conflict resolver) +// Any fields marked as "kSecDbSyncSOSCannotSyncFlag" that are in item2 will be present in the returned item. static SecDbItemRef SecItemDataSourceCopyMergedItem(SecDbItemRef item1, SecDbItemRef item2, CFErrorRef *error) { CFErrorRef localError = NULL; SecDbItemRef result = NULL; @@ -326,7 +324,7 @@ static SecDbItemRef SecItemDataSourceCopyMergedItem(SecDbItemRef item1, SecDbIte // Return the item with the smallest digest. CFDataRef digest1 = SecDbItemGetSHA1(item1, &localError); CFDataRef digest2 = SecDbItemGetSHA1(item2, &localError); - if (digest1 && digest2) switch (CFDataCompare(digest1, digest2)) { + if (digest1 && digest2) switch (CFDataCompareDERData(digest1, digest2)) { case kCFCompareGreaterThan: case kCFCompareEqualTo: result = item2; @@ -353,6 +351,22 @@ static SecDbItemRef SecItemDataSourceCopyMergedItem(SecDbItemRef item1, SecDbIte else CFRelease(localError); } + + // Note, if we chose item2 as result above, there's no need to move attributes from item2 to item2 + if(result && item2 && result != item2) { + // We'd like to preserve our local UUID, no matter what. UUIDs are not sent across SOS channels, and so items + // arriving via SOS have randomly generated UUIDs. + SecDbForEachAttr(SecDbItemGetClass(result), attr) { + if(CFEqualSafe(attr->name, v10itemuuid.name)) { + SecItemPreserveAttribute(result, item2, attr); + } + } + + SecDbForEachAttrWithMask(SecDbItemGetClass(result), attr, kSecDbSyncSOSCannotSyncFlag) { + SecItemPreserveAttribute(result, item2, attr); + } + } + return CFRetainSafe(result); } @@ -389,19 +403,9 @@ static bool dsForEachObject(SOSDataSourceRef data_source, SOSTransactionRef txn, bool (^use_attr_in_where)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { return attr->kind == kSecDbSHA1Attr; }; -#ifdef DARLING - Query *select_queries[dsSyncedClassesSize]; - CFStringRef select_sql[dsSyncedClassesSize]; - sqlite3_stmt *select_stmts[dsSyncedClassesSize]; - - memset(select_queries, 0, sizeof(select_queries)); - memset(select_sql, 0, sizeof(select_sql)); - memset(select_stmts, 0, sizeof(select_stmts)); -#else Query *select_queries[dsSyncedClassesSize] = {}; CFStringRef select_sql[dsSyncedClassesSize] = {}; sqlite3_stmt *select_stmts[dsSyncedClassesSize] = {}; -#endif __block Query **queries = select_queries; __block CFStringRef *sqls = select_sql; @@ -412,7 +416,7 @@ static bool dsForEachObject(SOSDataSourceRef data_source, SOSTransactionRef txn, // Setup for (size_t class_ix = 0; class_ix < dsSyncedClassesSize; ++class_ix) { result = (result - && (queries[class_ix] = query_create(dsSyncedClasses()[class_ix], NULL, NULL, error)) + && (queries[class_ix] = query_create(dsSyncedClasses()[class_ix], NULL, NULL, NULL, error)) && (sqls[class_ix] = SecDbItemCopySelectSQL(queries[class_ix], return_attr, use_attr_in_where, NULL)) && (stmts[class_ix] = SecDbCopyStmt(dbconn, sqls[class_ix], NULL, error))); } @@ -493,9 +497,9 @@ static CFDateRef copyObjectModDate(SOSObjectRef object, CFErrorRef *error) { static CFDictionaryRef objectCopyPropertyList(SOSObjectRef object, CFErrorRef *error) { SecDbItemRef item = (SecDbItemRef) object; - CFMutableDictionaryRef secretDataDict = SecDbItemCopyPListWithMask(item, kSecDbReturnDataFlag, error); - CFMutableDictionaryRef cryptoDataDict = SecDbItemCopyPListWithMask(item, kSecDbInCryptoDataFlag, error); - CFMutableDictionaryRef authDataDict = SecDbItemCopyPListWithMask(item, kSecDbInAuthenticatedDataFlag, error); + CFMutableDictionaryRef secretDataDict = SecDbItemCopyPListWithFlagAndSkip(item, kSecDbReturnDataFlag, kSecDbSyncSOSCannotSyncFlag, error); + CFMutableDictionaryRef cryptoDataDict = SecDbItemCopyPListWithFlagAndSkip(item, kSecDbInCryptoDataFlag, kSecDbSyncSOSCannotSyncFlag, error); + CFMutableDictionaryRef authDataDict = SecDbItemCopyPListWithFlagAndSkip(item, kSecDbInAuthenticatedDataFlag, kSecDbSyncSOSCannotSyncFlag, error); if (cryptoDataDict) { if (authDataDict) { @@ -678,7 +682,7 @@ static CFDataRef dsCopyStateWithKey(SOSDataSourceRef data_source, CFStringRef ke NULL); CFReleaseSafe(dataSourceID); __block CFDataRef data = NULL; - SecDbQueryRef query = query_create(genp_class(), NULL, dict, error); + SecDbQueryRef query = query_create(genp_class(), NULL, dict, NULL, error); if (query) { if (query->q_item) CFReleaseSafe(query->q_item); query->q_item = dict; @@ -723,7 +727,7 @@ static CFDataRef dsCopyItemDataWithKeys(SOSDataSourceRef data_source, CFDictiona SecItemDataSourceRef ds = (SecItemDataSourceRef)data_source; CFMutableDictionaryRef dict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, keys); __block CFDataRef data = NULL; - SecDbQueryRef query = query_create(genp_class(), NULL, dict, error); + SecDbQueryRef query = query_create(genp_class(), NULL, dict, NULL, error); if (query) { if (query->q_item) CFReleaseSafe(query->q_item); query->q_item = dict; @@ -907,10 +911,23 @@ static SOSDataSourceFactoryRef SecItemDataSourceFactoryCreate(SecDbRef db) { return &dsf->factory; } + +static dispatch_once_t sDSFQueueOnce; +static dispatch_queue_t sDSFQueue; +static CFMutableDictionaryRef sDSTable = NULL; + +void SecItemDataSourceFactoryReleaseAll() { + // Ensure that the queue is set up + (void) SecItemDataSourceFactoryGetShared(nil); + + dispatch_sync(sDSFQueue, ^{ + if(sDSTable) { + CFDictionaryRemoveAllValues(sDSTable); + } + }); +} + SOSDataSourceFactoryRef SecItemDataSourceFactoryGetShared(SecDbRef db) { - static dispatch_once_t sDSFQueueOnce; - static dispatch_queue_t sDSFQueue; - static CFMutableDictionaryRef sDSTable = NULL; dispatch_once(&sDSFQueueOnce, ^{ sDSFQueue = dispatch_queue_create("dataSourceFactory queue", DISPATCH_QUEUE_SERIAL); diff --git a/keychain/securityd/SecItemDataSource.h b/keychain/securityd/SecItemDataSource.h index fab2678e..3ba61dd7 100644 --- a/keychain/securityd/SecItemDataSource.h +++ b/keychain/securityd/SecItemDataSource.h @@ -44,6 +44,8 @@ SOSManifestRef SOSCreateManifestWithBackup(CFDictionaryRef backup, CFErrorRef *e // Hack to log objects from inside SOS code void SecItemServerAppendItemDescription(CFMutableStringRef desc, CFDictionaryRef object); +// Are you a test? Call this to drop all data sources. +void SecItemDataSourceFactoryReleaseAll(void); __END_DECLS diff --git a/keychain/securityd/SecItemDb.c b/keychain/securityd/SecItemDb.c index c5258625..b1fc2150 100644 --- a/keychain/securityd/SecItemDb.c +++ b/keychain/securityd/SecItemDb.c @@ -27,7 +27,7 @@ passwords.) */ -#if TARGET_DARWINOS +#if defined(TARGET_DARWINOS) && TARGET_DARWINOS #undef OCTAGON #undef SECUREOBJECTSYNC #undef SHAREDWEBCREDENTIALS @@ -183,7 +183,7 @@ bool SecItemDbCreateSchema(SecDbConnectionRef dbt, const SecDbSchema *schema, CF if (classIndexesForNewTables) { CFArrayForEach(classIndexesForNewTables, ^(const void* index) { - const SecDbClass* class = schema->classes[(int)index]; + const SecDbClass* class = schema->classes[(int)(long) index]; SecDbAppendCreateTableWithClass(sql, class); }); } @@ -313,8 +313,11 @@ s3dl_query_add(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, CFErrorRef * } #endif - if (ok) - ok = SecDbItemInsert(item, dbt, error); + if (ok) { + // We care about the new item's UUID only when we just made it from the primary key. + // Otherwise, we just made a random one, and don't mind if it changes. + ok = SecDbItemInsert(item, dbt, q->q_uuid_from_primary_key, error); + } if (ok) { if (result && q->q_return_type) { @@ -535,39 +538,22 @@ decode: // errSecDecode means the item is corrupted, stash it for delete. if (status == errSecDecode) { secwarning("ignoring corrupt %@,rowid=%" PRId64 " %@", q->q_class->name, rowid, q->q_error); - { - CFStringRef tablename = CFStringCreateCopy(kCFAllocatorDefault, q->q_class->name); - // Can't get rid of this item on the read path. Let's come back from elsewhere. - dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ - __block CFErrorRef localErr = NULL; - __block bool ok = true; - ok &= kc_with_dbt(true, &localErr, ^bool(SecDbConnectionRef dbt) { - CFStringRef sql = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DELETE FROM %@ WHERE rowid=%lli"), tablename, rowid); - ok &= SecDbPrepare(dbt, sql, &localErr, ^(sqlite3_stmt *stmt) { - ok &= SecDbStep(dbt, stmt, &localErr, NULL); - }); - if (!ok || localErr) { - secerror("Failed to delete corrupt item, %@ row %lli: %@", tablename, rowid, localErr); - } else { - secnotice("item", "Deleted corrupt rowid %lli from table %@", rowid, tablename); - } - CFReleaseNull(localErr); - CFReleaseNull(sql); - CFReleaseSafe(tablename); - return ok; - }); - }); + // Can't get rid of this item on the read path. Let's come back from elsewhere. + CFStringRef tablename = CFStringCreateCopy(kCFAllocatorDefault, q->q_class->name); + deleteCorruptedItemAsync(c->dbt, tablename, rowid); + CFReleaseNull(tablename); - CFDataRef edata = s3dl_copy_data_from_col(stmt, 1, NULL); - CFMutableStringRef edatastring = CFStringCreateMutable(kCFAllocatorDefault, 0); - if(edatastring) { - CFStringAppendEncryptedData(edatastring, edata); - secnotice("item", "corrupted edata=%@", edatastring); - } - CFReleaseSafe(edata); - CFReleaseSafe(edatastring); + // provide helpful logging statement + CFDataRef edata = s3dl_copy_data_from_col(stmt, 1, NULL); + CFMutableStringRef edatastring = CFStringCreateMutable(kCFAllocatorDefault, 0); + if(edatastring) { + CFStringAppendEncryptedData(edatastring, edata); + secnotice("item", "corrupted edata=%@", edatastring); } + CFReleaseSafe(edata); + CFReleaseSafe(edatastring); + CFReleaseNull(q->q_error); // This item was never here, keep going } else if (status == errSecAuthNeeded) { secwarning("Authentication is needed for %@,rowid=%" PRId64 " (%" PRIdOSStatus "): %@", q->q_class->name, rowid, status, q->q_error); @@ -731,6 +717,19 @@ SecDbAppendWhereMusr(CFMutableStringRef sql, } } +static void +SecDbAppendWhereAppClip(CFMutableStringRef sql, + const Query* q, + bool* needWhere) +{ + if (!q->q_skip_app_clip_items) { + return; + } + + SecDbAppendWhereOrAnd(sql, needWhere); + CFStringAppend(sql, CFSTR("clip = 0")); +} + static void SecDbAppendWhereClause(CFMutableStringRef sql, const Query *q, CFArrayRef accessGroups) { bool needWhere = true; @@ -738,6 +737,7 @@ static void SecDbAppendWhereClause(CFMutableStringRef sql, const Query *q, SecDbAppendWhereAttrs(sql, q, &needWhere); SecDbAppendWhereMusr(sql, q, &needWhere); SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); + SecDbAppendWhereAppClip(sql, q, &needWhere); } static void SecDbAppendLimit(CFMutableStringRef sql, CFIndex limit) { @@ -748,14 +748,14 @@ static void SecDbAppendLimit(CFMutableStringRef sql, CFIndex limit) { static CFStringRef s3dl_create_select_sql(Query *q, CFArrayRef accessGroups) { CFMutableStringRef sql = CFStringCreateMutable(NULL, 0); if (q->q_class == identity_class()) { - CFStringAppendFormat(sql, NULL, CFSTR("SELECT crowid, %@" - ", rowid,data FROM " - "(SELECT cert.rowid AS crowid, cert.labl AS labl," - " cert.issr AS issr, cert.slnr AS slnr, cert.skid AS skid," - " keys.*,cert.data AS %@" - " FROM keys, cert" - " WHERE keys.priv == 1 AND cert.pkhh == keys.klbl"), - kSecAttrIdentityCertificateData, kSecAttrIdentityCertificateData); + CFStringAppend(sql, CFSTR("SELECT crowid, certdata" + ", rowid,data FROM " + "(SELECT cert.rowid AS crowid, cert.labl AS labl," + " cert.issr AS issr, cert.slnr AS slnr, cert.skid AS skid," + " cert.tkid AS tkid," + " keys.*,cert.data AS certdata" + " FROM keys, cert" + " WHERE keys.priv == 1 AND cert.pkhh == keys.klbl")); SecDbAppendWhereAccessGroups(sql, CFSTR("cert.agrp"), accessGroups, 0); /* The next 3 SecDbAppendWhere calls are in the same order as in SecDbAppendWhereClause(). This makes sqlBindWhereClause() work, @@ -766,8 +766,10 @@ static CFStringRef s3dl_create_select_sql(Query *q, CFArrayRef accessGroups) { SecDbAppendWhereAttrs(sql, q, &needWhere); SecDbAppendWhereMusr(sql, q, &needWhere); SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); + SecDbAppendWhereAppClip(sql, q, &needWhere); } else { - CFStringAppend(sql, CFSTR("SELECT rowid, data FROM ")); + // Most of the time we don't need agrp, but if an item fails to decode and we want to know more then this is helpful + CFStringAppend(sql, CFSTR("SELECT rowid, data, agrp FROM ")); CFStringAppend(sql, q->q_class->name); SecDbAppendWhereClause(sql, q, accessGroups); } @@ -975,7 +977,7 @@ s3dl_copy_matching(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, CFSTR("attributes to query illegal; both row_id and other attributes can't be searched at the same time")); if (q->q_token_object_id && query_attr_count(q) != 1) return SecError(errSecItemIllegalQuery, error, - CFSTR("attributes to query illegal; both token persitent ref and other attributes can't be searched at the same time")); + CFSTR("attributes to query illegal; both token persistent ref and other attributes can't be searched at the same time")); // Only copy things that aren't tombstones unless the client explicitly asks otherwise. if (!CFDictionaryContainsKey(q->q_item, kSecAttrTombstone)) @@ -1128,10 +1130,7 @@ static CFBooleanRef s3dl_should_make_tombstone(Query *q, bool item_is_syncable, else return kCFBooleanFalse; } -/* AUDIT[securityd](done): - attributesToUpdate (ok) is a caller provided dictionary, - only its cf types have been checked. - */ + bool s3dl_query_update(SecDbConnectionRef dbt, Query *q, CFDictionaryRef attributesToUpdate, CFArrayRef accessGroups, CFErrorRef *error) @@ -1147,7 +1146,7 @@ s3dl_query_update(SecDbConnectionRef dbt, Query *q, return SecError(errSecItemIllegalQuery, error, CFSTR("attributes to update illegal; both token persistent ref and other attributes can't be updated at the same time")); __block bool result = true; - Query *u = query_create(q->q_class, NULL, attributesToUpdate, error); + Query *u = query_create(q->q_class, NULL, attributesToUpdate, NULL, error); if (u == NULL) return false; require_action_quiet(query_update_parse(u, attributesToUpdate, error), errOut, result = false); query_pre_update(u); @@ -1174,7 +1173,7 @@ s3dl_query_update(SecDbConnectionRef dbt, Query *q, // We just ignore this, and treat as if item is not found. secwarning("deleting corrupt %@,rowid=%" PRId64 " %@", q->q_class->name, SecDbItemGetRowId(item, NULL), localError); CFReleaseNull(localError); - if (!SecDbItemDelete(item, dbt, false, &localError)) { + if (!SecDbItemDelete(item, dbt, false, false, &localError)) { secerror("failed to delete corrupt %@,rowid=%" PRId64 " %@", q->q_class->name, SecDbItemGetRowId(item, NULL), localError); CFReleaseNull(localError); } @@ -1254,7 +1253,7 @@ s3dl_query_delete(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFE bool item_is_sync = SecDbItemIsSyncable(item); SecDbItemSetValue(item, sha1attr, storedSHA1, NULL); CFReleaseSafe(storedSHA1); - ok = SecDbItemDelete(item, dbt, s3dl_should_make_tombstone(q, item_is_sync, item), error); + ok = SecDbItemDelete(item, dbt, s3dl_should_make_tombstone(q, item_is_sync, item), q->q_tombstone_use_mdat_from_item, error); if (ok) { q->q_changed = true; if (item_is_sync) @@ -1502,8 +1501,9 @@ fail: if (stmt) { ok = SecDbFinalize(stmt, error); } - if (!ok) + if (!ok) { secwarning("DeleteAllFromTableForMUSRView failed for %@ for musr: %@: %@", sql2, musr, error ? *error : NULL); + } CFReleaseNull(sql2); @@ -1526,6 +1526,34 @@ bool SecServerDeleteAllForUser(SecDbConnectionRef dbt, CFDataRef musrView, bool } #endif +OSStatus SecServerDeleteForAppClipApplicationIdentifier(CFStringRef identifier) { + secnotice("item", "Request to delete app clip keychain items for identifier '%@'", identifier); + + __block CFErrorRef cfError = NULL; + __block bool ok = true; + ok &= kc_with_dbt(true, &cfError, ^bool(SecDbConnectionRef dbt) { + return kc_transaction(dbt, &cfError, ^bool{ + const SecDbSchema* schema = current_schema(); + for (const SecDbClass *const * class = schema->classes; *class != NULL; ++class) { + if ((*class)->itemclass) { + CFStringRef sqlStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DELETE FROM %@ WHERE agrp = ? AND clip = 1"), (*class)->name); + ok &= SecDbPrepare(dbt, sqlStr, &cfError, ^(sqlite3_stmt *stmt) { + ok &= SecDbBindObject(stmt, 1, identifier, &cfError); + ok &= SecDbStep(dbt, stmt, &cfError, NULL); + }); + CFReleaseNull(sqlStr); + } + } + return ok; + }); + }); + + OSStatus status = ok ? errSecSuccess : errSecInternal; + secnotice("item", "Finished request to delete app clip keychain items for identifier '%@' with status %i: %@", identifier, (int)status, cfError); + CFReleaseNull(cfError); + + return status; +} struct s3dl_export_row_ctx { struct s3dl_query_ctx qc; @@ -1540,9 +1568,6 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { SecAccessControlRef access_control = NULL; CFErrorRef localError = NULL; - /* Skip akpu items when backing up, those are intentionally lost across restores. The same applies to SEP-based keys */ - bool skip_akpu_or_token = c->filter == kSecBackupableItemFilter; - sqlite_int64 rowid = sqlite3_column_int64(stmt, 0); CFMutableDictionaryRef allAttributes = NULL; CFMutableDictionaryRef metadataAttributes = NULL; @@ -1561,12 +1586,14 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { } } + /* Skip akpu items when backing up, those are intentionally lost across restores. The same applies to SEP-based keys */ bool is_akpu = access_control ? CFEqualSafe(SecAccessControlGetProtection(access_control), kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly) // Mask generation, only look at class per se : (keyclass & key_class_last) == key_class_akpu; bool is_token = (ok && allAttributes != NULL) ? CFDictionaryContainsKey(allAttributes, kSecAttrTokenID) : false; + bool skip_akpu_or_token = (is_akpu || is_token) && c->filter == kSecBackupableItemFilter; - if (ok && allAttributes && !(skip_akpu_or_token && (is_akpu || is_token))) { + if (ok && allAttributes && !skip_akpu_or_token) { /* Only export sysbound items if do_sys_bound is true, only export non sysbound items otherwise. */ bool do_sys_bound = c->filter == kSecSysBoundItemFilter; if (c->filter == kSecNoItemFilter || @@ -1607,7 +1634,7 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { CFReleaseSafe(pref); } } - } else { + } else if (!ok || !allAttributes) { OSStatus status = SecErrorGetOSStatus(localError); if (status == errSecInteractionNotAllowed && is_akpu) { @@ -1615,13 +1642,15 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { secdebug("item", "Skipping akpu item for backup"); } else { // Probably failed to decrypt sysbound item. Should never be an akpu item in backup. secerror("Encountered akpu item we cannot export (filter %d), skipping. %@", c->filter, localError); - CFDictionaryRef payload = NULL; - CFTypeRef agrp = CFDictionaryGetValue(allAttributes, CFSTR("agrp")); - if (agrp) { - payload = CFDictionaryCreateForCFTypes(NULL, CFSTR("agrp"), agrp, NULL); + if (sqlite3_column_count(stmt) > 2) { // Should have rowid,data,agrp from s3dl_create_select_sql + CFStringRef agrp = CFStringCreateWithCString(kCFAllocatorDefault, (const char*)sqlite3_column_text(stmt, 2), kCFStringEncodingUTF8); + if (agrp) { + CFDictionaryRef payload = CFDictionaryCreateForCFTypes(NULL, CFSTR("agrp"), agrp, NULL); + SecABCTrigger(CFSTR("keychain"), CFSTR("invalid-akpu+sysbound"), NULL, payload); + CFReleaseNull(payload); + } + CFReleaseNull(agrp); } - SecABCTrigger(CFSTR("keychain"), CFSTR("invalid-akpu+sysbound"), NULL, payload); - CFReleaseNull(payload); } // We expect akpu items to be inaccessible when the device is locked. CFReleaseNull(localError); @@ -1637,7 +1666,10 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { q->q_error = localError; } } + } else { + secnotice("item", "export rowid %llu skipped. akpu/token: %i", rowid, skip_akpu_or_token); } + CFReleaseNull(access_control); CFReleaseNull(allAttributes); CFReleaseNull(metadataAttributes); @@ -1659,7 +1691,6 @@ SecCreateKeybagUUID(keybag_handle_t keybag) #endif } - CFDictionaryRef SecServerCopyKeychainPlist(SecDbConnectionRef dbt, SecurityClient *client, @@ -1689,7 +1720,7 @@ SecServerCopyKeychainPlist(SecDbConnectionRef dbt, kSecReturnPersistentRefMask; q.q_limit = kSecMatchUnlimited; q.q_skip_acl_items = true; - + q.q_skip_app_clip_items = true; #if TARGET_OS_IPHONE if (client && client->inMultiUser) { @@ -1808,7 +1839,7 @@ SecServerImportItem(const void *value, void *context) if (state->s->src_keybag == KEYBAG_NONE) { item = SecDbItemCreateWithAttributes(kCFAllocatorDefault, state->class, dict, state->s->dest_keybag, &state->s->error); } else { - item = SecDbItemCreateWithBackupDictionary(kCFAllocatorDefault, state->class, dict, state->s->src_keybag, state->s->dest_keybag, &state->s->error); + item = SecDbItemCreateWithBackupDictionary(state->class, dict, state->s->src_keybag, state->s->dest_keybag, &state->s->error); } /* If item is NULL here, control flow ends up at the end where error is cleared. */ @@ -1906,7 +1937,7 @@ SecServerImportItem(const void *value, void *context) SecDbItemExtractRowIdFromBackupDictionary(item, dict, &state->s->error); } SecDbItemInferSyncable(item, &state->s->error); - insertStatus = SecDbItemInsert(item, state->s->dbt, &state->s->error); + insertStatus = SecDbItemInsert(item, state->s->dbt, false, &state->s->error); if (!insertStatus) { /* When running in EduMode, multiple users share the same @@ -1920,7 +1951,7 @@ SecServerImportItem(const void *value, void *context) again to insert the record. */ SecDbItemClearRowId(item, NULL); - SecDbItemInsert(item, state->s->dbt, &state->s->error); + SecDbItemInsert(item, state->s->dbt, false, &state->s->error); } } @@ -2158,7 +2189,7 @@ bool s3dl_dbt_keys_current(SecDbConnectionRef dbt, uint32_t current_generation, }; for (size_t class_ix = 0; class_ix < array_size(classes); ++class_ix) { - Query *q = query_create(classes[class_ix], NULL, NULL, &localError); + Query *q = query_create(classes[class_ix], NULL, NULL, NULL, &localError); if (!q) return false; diff --git a/keychain/securityd/SecItemDb.h b/keychain/securityd/SecItemDb.h index 3a07bb65..3f8efb9e 100644 --- a/keychain/securityd/SecItemDb.h +++ b/keychain/securityd/SecItemDb.h @@ -95,6 +95,7 @@ SecServerBackupGetKeybagUUID(CFDictionaryRef keychain, CFErrorRef *error); #if TARGET_OS_IPHONE bool SecServerDeleteAllForUser(SecDbConnectionRef dbt, CFDataRef musrView, bool keepU, CFErrorRef *error); #endif +OSStatus SecServerDeleteForAppClipApplicationIdentifier(CFStringRef identifier); bool kc_transaction(SecDbConnectionRef dbt, CFErrorRef *error, bool(^perform)(void)); bool kc_transaction_type(SecDbConnectionRef dbt, SecDbTransactionType type, CFErrorRef *error, bool(^perform)(void)); diff --git a/keychain/securityd/SecItemSchema.c b/keychain/securityd/SecItemSchema.c index 9a58ef42..b49cb54e 100644 --- a/keychain/securityd/SecItemSchema.c +++ b/keychain/securityd/SecItemSchema.c @@ -58,23 +58,25 @@ #define __FLAGS_V0 kSecDbSyncPrimaryKeyV0 #define __FLAGS_V2 (kSecDbSyncPrimaryKeyV0 | kSecDbSyncPrimaryKeyV2) #define __FLAGS_Y kSecDbSyncFlag +#define __FLAGS_X kSecDbSyncFlag | kSecDbSyncSOSCannotSyncFlag // ,----------------- P : Part of primary key // / ,---------------- L : Stored in local database // / / ,--------------- I : Attribute wants an index in the database // / / / ,-------------- S : SHA1 hashed attribute value in database (implies L) -// / / / / ,------------- A : Returned to client as attribute in queries -// / / / / / ,------------ D : Returned to client as data in queries +// / / / / ,------------- A : Returned to client as attribute in queries (implied by C) +// / / / / / ,------------ D : Returned to client as data in queries (implied by C) // / / / / / / ,----------- R : Returned to client as ref/persistent ref in queries // / / / / / / / ,---------- C : Part of encrypted blob -// / / / / / / / / ,--------- H : Attribute is part of item SHA1 hash (Implied by C) +// / / / / / / / / ,--------- H : Attribute is part of item SHA1 hash // / / / / / / / / / ,-------- B : Attribute is part of iTunes/iCloud backup bag // / / / / / / / / / / ,------- Z : Attribute has a default value of 0 // / / / / / / / / / / / ,------ E : Attribute has a default value of "" or empty data // / / / / / / / / / / / / ,----- N : Attribute must have a value // / / / / / / / / / / / / / ,---- U : Attribute is stored in authenticated, but not necessarily encrypted data // / / / / / / / / / / / / / / ,--- V0: Sync primary key version -// / / / / / / / / / / / / / / / ,- Y : Attribute should be synced +// / / / / / / / / / / / / / / / ,- Y : Attribute should be synced, or +// | | | | | | | | | | | | | | | | X : Attribute should be synced in CKKS, and ignored in SOS // | | | | | | | | | | | | | | | | // common to all | | | | | | | | | | | | | | | | SECDB_ATTR(v6rowid, "rowid", RowId, SecDbFlags( ,L, , , , ,R, , ,B, , , , , , ), NULL, NULL); @@ -82,9 +84,9 @@ SECDB_ATTR(v6cdat, "cdat", CreationDate, SecDbFlags( ,L, , ,A, , ,C,H, , , , , SECDB_ATTR(v6mdat, "mdat",ModificationDate,SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ,Y), SecDbKeychainItemCopyCurrentDate, NULL); SECDB_ATTR(v6labl, "labl", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ,Y), NULL, NULL); SECDB_ATTR(v6data, "data", EncryptedData, SecDbFlags( ,L, , , , , , , ,B, , , , , , ), SecDbKeychainItemCopyEncryptedData, NULL); -SECDB_ATTR(v6agrp, "agrp", String, SecDbFlags(P,L,I, ,A, , , ,H, , , ,N,U,V0,Y), NULL, NULL); +SECDB_ATTR(v6agrp, "agrp", String, SecDbFlags(P,L, , ,A, , , ,H, , , ,N,U,V0,Y), NULL, NULL); SECDB_ATTR(v6pdmn, "pdmn", Access, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ,Y), NULL, NULL); -SECDB_ATTR(v6sync, "sync", Sync, SecDbFlags(P,L,I, ,A, , , ,H, ,Z, ,N,U,V0, ), NULL, NULL); +SECDB_ATTR(v6sync, "sync", Sync, SecDbFlags(P,L, , ,A, , , ,H, ,Z, ,N,U,V0, ), NULL, NULL); SECDB_ATTR(v6tomb, "tomb", Tomb, SecDbFlags( ,L, , , , , , ,H, ,Z, ,N,U, ,Y), NULL, NULL); SECDB_ATTR(v6sha1, "sha1", SHA1, SecDbFlags( ,L,I, ,A, ,R, , , , , , , , ,Y), SecDbKeychainItemCopySHA1, NULL); SECDB_ATTR(v6accc, "accc", AccessControl, SecDbFlags( , , , ,A, , , , , , , , , , , ), NULL, NULL); @@ -93,7 +95,8 @@ SECDB_ATTR(v6v_pk, "v_pk", PrimaryKey, SecDbFlags( , , , , , , , , , , , , , SECDB_ATTR(v7vwht, "vwht", String, SecDbFlags(P,L,I, ,A, , , ,H, , , , ,U,V2,Y), NULL, NULL); SECDB_ATTR(v7tkid, "tkid", String, SecDbFlags(P,L,I, ,A, , , ,H, , , , ,U,V2,Y), NULL, NULL); SECDB_ATTR(v7utomb, "u_Tomb", UTomb, SecDbFlags( , , , , , , , , , , , , , , , ), NULL, NULL); -SECDB_ATTR(v8musr, "musr", UUID, SecDbFlags(P,L,I, , , , , , , , , ,N,U, ,Y), NULL, NULL); +SECDB_ATTR(v8musr, "musr", UUID, SecDbFlags(P,L, , , , , , , , , , ,N,U, ,Y), NULL, NULL); +SECDB_ATTR(v11_7appclip, "clip", Number, SecDbFlags( ,L, , , , , , , , ,Z, ,N, , , ), NULL, NULL); // genp and inet and keys | | | | | | | | | | | | | | | | SECDB_ATTR(v6crtr, "crtr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ,Y), NULL, NULL); SECDB_ATTR(v6alis, "alis", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ,Y), NULL, NULL); @@ -245,6 +248,16 @@ SECDB_ATTR(v11_5octagonStatus, "octagonstatus", String, SecDbFlags( ,L, , , , SECDB_ATTR(v11_6moreComing, "morecoming", Number, SecDbFlags( ,L, , , , , , , , , , , , , , ), NULL, NULL); +SECDB_ATTR(v11_8_bin_notes, "binn", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_history, "bini", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_client0, "bin0", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_client1, "bin1", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_client2, "bin2", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_client3, "bin3", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); + +SECDB_ATTR(v11_9_lastscan, "lastscan", String, SecDbFlags( ,L, , , , , , , , , , , , , , ), NULL, NULL); +SECDB_ATTR(v11_9_extra, "extra", Blob, SecDbFlags( ,L, , , , , , , , , , , , , , ), NULL, NULL); + SECDB_ATTR(v12_backupUUIDPrimary, "backupUUID", UUID, SecDbFlags(P,L,I, , , , , , , , , ,N, , , ), NULL, NULL); SECDB_ATTR(v12_backupUUID, "backupUUID", UUID, SecDbFlags( ,L,I, , , , , , , , ,E, , , , ), NULL, NULL); SECDB_ATTR(v12_backupBag, "backupbag", Blob, SecDbFlags( ,L, , , , , , , , , , ,N, , , ), NULL, NULL); @@ -339,6 +352,7 @@ const SecDbClass v12_genp_class = { &v10_1pcspublickey, &v10_1pcspublicidentity, &v10_1itempersistentref, + &v11_7appclip, &v12_backupUUID, 0 }, @@ -388,6 +402,13 @@ const SecDbClass v12_inet_class = { &v10_1pcspublickey, &v10_1pcspublicidentity, &v10_1itempersistentref, + &v11_7appclip, + &v11_8_bin_notes, + &v11_8_bin_history, + &v11_8_bin_client0, + &v11_8_bin_client1, + &v11_8_bin_client2, + &v11_8_bin_client3, &v12_backupUUID, 0 }, @@ -428,6 +449,7 @@ const SecDbClass v12_cert_class = { &v10_1pcspublickey, &v10_1pcspublicidentity, &v10_1itempersistentref, + &v11_7appclip, &v12_backupUUID, 0 }, @@ -486,11 +508,277 @@ const SecDbClass v12_keys_class = { &v10_1pcspublickey, &v10_1pcspublicidentity, &v10_1itempersistentref, + &v11_7appclip, &v12_backupUUID, 0 } }; +const SecDbClass v11_9_ckstate_class = { + .name = CFSTR("ckstate"), + .itemclass = false, + .attrs = { + &v10ckzone, + &v10ckzonecreated, + &v10ckzonesubscribed, + &v10lastfetchtime, + &v10changetoken, + &v10ratelimiter, + &v10_4lastFixup, + &v11_6moreComing, + &v11_9_lastscan, + &v11_9_extra, + 0 + } +}; + +const SecDbClass v11_8_inet_class = { + .name = CFSTR("inet"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6sdmn, + &v6srvr, + &v6ptcl, + &v6atyp, + &v6port, + &v6path, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + &v11_8_bin_notes, + &v11_8_bin_history, + &v11_8_bin_client0, + &v11_8_bin_client1, + &v11_8_bin_client2, + &v11_8_bin_client3, + 0 + }, +}; + +const SecDbClass v11_7_genp_class = { + .name = CFSTR("genp"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6svce, + &v6gena, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + 0 + }, +}; + +const SecDbClass v11_7_inet_class = { + .name = CFSTR("inet"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6sdmn, + &v6srvr, + &v6ptcl, + &v6atyp, + &v6port, + &v6path, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + 0 + }, +}; + +const SecDbClass v11_7_cert_class = { + .name = CFSTR("cert"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6ctyp, + &v6cenc, + &v6labl, + &v6certalis, + &v6subj, + &v6issr, + &v6slnr, + &v6skid, + &v6pkhh, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + 0 + }, +}; + +const SecDbClass v11_7_keys_class = { + .name = CFSTR("keys"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6kcls, + &v6labl, + &v6alis, + &v6perm, + &v6priv, + &v6modi, + &v6klbl, + &v6atag, + &v6keycrtr, + &v6keytype, + &v6bsiz, + &v6esiz, + &v6sdat, + &v6edat, + &v6sens, + &v6asen, + &v6extr, + &v6next, + &v6encr, + &v6decr, + &v6drve, + &v6sign, + &v6vrfy, + &v6snrc, + &v6vyrc, + &v6wrap, + &v6unwp, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + 0 + } +}; + const SecDbClass v11_6_ckstate_class = { .name = CFSTR("ckstate"), .itemclass = false, @@ -1248,7 +1536,7 @@ const SecDbSchema v12_0_schema = { &v10_0_sync_key_class, &v10_1_ckmirror_class, &v10_0_current_key_class, - &v11_6_ckstate_class, + &v11_9_ckstate_class, &v10_0_item_backup_class, &v10_0_backup_keybag_class, &v10_2_ckmanifest_class, @@ -1269,6 +1557,114 @@ const SecDbSchema v12_0_schema = { } }; +/* + * Version 11.9 + * Add extra columns for CKState + */ +const SecDbSchema v11_9_schema = { + .majorVersion = 11, + .minorVersion = 9, + .classes = { + &v11_7_genp_class, + &v11_8_inet_class, + &v11_7_cert_class, + &v11_7_keys_class, + &v10_0_tversion_class, + &v10_2_outgoing_queue_class, + &v10_2_incoming_queue_class, + &v10_0_sync_key_class, + &v10_1_ckmirror_class, + &v10_0_current_key_class, + &v11_9_ckstate_class, + &v10_0_item_backup_class, + &v10_0_backup_keybag_class, + &v10_2_ckmanifest_class, + &v10_2_pending_manifest_class, + &v10_1_ckmanifest_leaf_class, + &v10_1_backup_keyarchive_class, + &v10_1_current_keyarchive_class, + &v10_1_current_archived_keys_class, + &v10_1_pending_manifest_leaf_class, + &v10_4_current_item_class, + &v11_5_ckdevicestate_class, + &v10_5_tlkshare_class, + &v11_2_metadatakeys_class, + 0 + } +}; + +/* + * Version 11.8 + * Add extra binary columns to inet + */ +const SecDbSchema v11_8_schema = { + .majorVersion = 11, + .minorVersion = 8, + .classes = { + &v11_7_genp_class, + &v11_8_inet_class, + &v11_7_cert_class, + &v11_7_keys_class, + &v10_0_tversion_class, + &v10_2_outgoing_queue_class, + &v10_2_incoming_queue_class, + &v10_0_sync_key_class, + &v10_1_ckmirror_class, + &v10_0_current_key_class, + &v11_6_ckstate_class, + &v10_0_item_backup_class, + &v10_0_backup_keybag_class, + &v10_2_ckmanifest_class, + &v10_2_pending_manifest_class, + &v10_1_ckmanifest_leaf_class, + &v10_1_backup_keyarchive_class, + &v10_1_current_keyarchive_class, + &v10_1_current_archived_keys_class, + &v10_1_pending_manifest_leaf_class, + &v10_4_current_item_class, + &v11_5_ckdevicestate_class, + &v10_5_tlkshare_class, + &v11_2_metadatakeys_class, + 0 + } +}; + +/* + * Version 11.7 + * Add 'clip' column to denote item was made by App Clip + */ +const SecDbSchema v11_7_schema = { + .majorVersion = 11, + .minorVersion = 7, + .classes = { + &v11_7_genp_class, + &v11_7_inet_class, + &v11_7_cert_class, + &v11_7_keys_class, + &v10_0_tversion_class, + &v10_2_outgoing_queue_class, + &v10_2_incoming_queue_class, + &v10_0_sync_key_class, + &v10_1_ckmirror_class, + &v10_0_current_key_class, + &v11_6_ckstate_class, + &v10_0_item_backup_class, + &v10_0_backup_keybag_class, + &v10_2_ckmanifest_class, + &v10_2_pending_manifest_class, + &v10_1_ckmanifest_leaf_class, + &v10_1_backup_keyarchive_class, + &v10_1_current_keyarchive_class, + &v10_1_current_archived_keys_class, + &v10_1_pending_manifest_leaf_class, + &v10_4_current_item_class, + &v11_5_ckdevicestate_class, + &v10_5_tlkshare_class, + &v11_2_metadatakeys_class, + 0 + } +}; + /* * Version 11.6 (Add 'moreComing' field to zone state) */ @@ -2920,6 +3316,9 @@ SecDbSchema const * const * kc_schemas = NULL; const SecDbSchema *v10_kc_schemas_dev[] = { &v12_0_schema, + &v11_9_schema, + &v11_8_schema, + &v11_7_schema, &v11_6_schema, &v11_5_schema, &v11_4_schema, @@ -2943,6 +3342,9 @@ const SecDbSchema *v10_kc_schemas_dev[] = { }; const SecDbSchema *v10_kc_schemas[] = { + &v11_9_schema, + &v11_8_schema, + &v11_7_schema, &v11_6_schema, &v11_5_schema, &v11_4_schema, diff --git a/keychain/securityd/SecItemServer+SWC.h b/keychain/securityd/SecItemServer+SWC.h new file mode 100644 index 00000000..d970c894 --- /dev/null +++ b/keychain/securityd/SecItemServer+SWC.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2007-2019 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include + +#if TARGET_OS_IOS && !TARGET_OS_BRIDGE +#include + +// Compatibility wrappers for SWC Objective-C interface. +typedef enum SecSWCFlags { + kSecSWCFlags_None = 0, + kSecSWCFlag_UserApproved = (1 << 0), + kSecSWCFlag_UserDenied = (1 << 1), + kSecSWCFlag_SiteApproved = (1 << 2), + kSecSWCFlag_SiteDenied = (1 << 3), +} SecSWCFlags; + +extern SecSWCFlags _SecAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFErrorRef *error); +extern void _SecSetAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFBooleanRef approved); + +extern CFTypeRef _SecCopyFQDNObjectFromString(CFStringRef entitlementValue); +extern CFStringRef _SecGetFQDNFromFQDNObject(CFTypeRef fqdnObject, SInt32 *outPort); +#if !TARGET_OS_SIMULATOR +extern bool _SecEntitlementContainsDomainForService(CFArrayRef domains, CFStringRef domain, SInt32 port); +#endif /* !TARGET_OS_SIMULATOR */ +#endif // TARGET_OS_IOS && !TARGET_OS_BRIDGE diff --git a/keychain/securityd/SecItemServer+SWC.m b/keychain/securityd/SecItemServer+SWC.m new file mode 100644 index 00000000..0c601a36 --- /dev/null +++ b/keychain/securityd/SecItemServer+SWC.m @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2007-2019 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import "SecItemServer+SWC.h" + +#if TARGET_OS_IOS && !TARGET_OS_BRIDGE +#import + +#import "utilities/debugging.h" +#import "utilities/SecCFError.h" + +// Methods in this category are here temporarily until I can add SPI in +// _SWCServiceSpecifier for the function below to consume. +@interface NSObject (Workaround61065225) +- (NSString *)domainHost; +@end + +SecSWCFlags _SecAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFErrorRef *error) +{ + __block SecSWCFlags flags = kSecSWCFlags_None; + + @autoreleasepool { + secnotice("swc", "Application %@ is requesting approval for %@", appID, fqdn); + + _SWCServiceSpecifier *specifier = [[_SWCServiceSpecifier alloc] initWithServiceType:_SWCServiceTypeWebCredentials + applicationIdentifier:(__bridge NSString *)appID + domain:(__bridge NSString *)fqdn]; + NSError *err = nil; + NSArray<_SWCServiceDetails *> *allDetails = [_SWCServiceDetails serviceDetailsWithServiceSpecifier:specifier error:&err]; + if (allDetails) { + _SWCServiceDetails *details = allDetails.firstObject; + if (details) { + switch (details.userApprovalState) { + case SWCServiceApprovalStateApproved: + flags |= kSecSWCFlag_UserApproved; + break; + + case SWCServiceApprovalStateDenied: + flags |= kSecSWCFlag_UserDenied; + break; + + default: + break; + } + switch (details.siteApprovalState) { + case SWCServiceApprovalStateApproved: + flags |= kSecSWCFlag_SiteApproved; + break; + + case SWCServiceApprovalStateDenied: + flags |= kSecSWCFlag_SiteDenied; + break; + + default: + break; + } + } + + } else { + // An error occurred. + secerror("+[_SWCServiceDetails serviceDetailsWithServiceSpecifier:error:] failed with %@", err); + } + } + + if (error) { + if (!(flags & kSecSWCFlag_SiteApproved)) { + SecError(errSecAuthFailed, error, CFSTR("\"%@\" failed to approve \"%@\""), fqdn, appID); + } else if (flags & kSecSWCFlag_UserDenied) { + SecError(errSecAuthFailed, error, CFSTR("User denied access to \"%@\" by \"%@\""), fqdn, appID); + } + } + + return flags; +} + +void _SecSetAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFBooleanRef approved) +{ + _SWCServiceSpecifier *specifier = [[_SWCServiceSpecifier alloc] initWithServiceType:_SWCServiceTypeWebCredentials + applicationIdentifier:(__bridge NSString *)appID + domain:(__bridge NSString *)fqdn]; + NSError *err = nil; + NSArray<_SWCServiceDetails *> *allDetails = [_SWCServiceDetails serviceDetailsWithServiceSpecifier:specifier error:&err]; + if (allDetails) { + _SWCServiceDetails *details = allDetails.firstObject; + if (details) { + SWCServiceApprovalState state = SWCServiceApprovalStateUnspecified; + if (approved == kCFBooleanTrue) { + state = SWCServiceApprovalStateApproved; + } else if (approved == kCFBooleanFalse) { + state = SWCServiceApprovalStateDenied; + } + if (![details setUserApprovalState:state error:&err]) { + secerror("-[_SWCServiceDetails setUserApprovalState:error:] failed with %@", err); + } + } + + } else { + secerror("+[_SWCServiceDetails serviceDetailsWithServiceSpecifier:error:] failed with %@", err); + } +} + +CFTypeRef _SecCopyFQDNObjectFromString(CFStringRef entitlementValue) +{ + CFTypeRef result = NULL; + + @autoreleasepool { + _SWCServiceSpecifier *serviceSpecifier = [_SWCServiceSpecifier serviceSpecifiersWithEntitlementValue:@[ (__bridge NSString *)entitlementValue ] error:NULL].firstObject; + if (!serviceSpecifier) { + serviceSpecifier = [[_SWCServiceSpecifier alloc] initWithServiceType:nil applicationIdentifier:nil domain:(__bridge NSString *)entitlementValue]; + } + if (serviceSpecifier) { + // Hiding an ObjC reference in a CFTypeRef since the caller is pure C. + result = CFBridgingRetain(serviceSpecifier); + } + } + + return result; +} + +CFStringRef _SecGetFQDNFromFQDNObject(CFTypeRef fqdnObject, SInt32 *outPort) +{ + CFStringRef result = NULL; + SInt32 port = -1; + + // Extracting an ObjC reference from a CFTypeRef since the caller is pure C. + _SWCServiceSpecifier *serviceSpecifier = (__bridge _SWCServiceSpecifier *)fqdnObject; + result = (__bridge CFStringRef)serviceSpecifier.domainHost; + if (outPort) { + NSNumber *portNumber = serviceSpecifier.domainPort; + if (portNumber) { + port = portNumber.unsignedShortValue; + } + + *outPort = port; + } + + return result; +} + +#if !TARGET_OS_SIMULATOR +bool _SecEntitlementContainsDomainForService(CFArrayRef domains, CFStringRef domain, SInt32 port) +{ + bool result = false; + + @autoreleasepool { + NSArray<_SWCServiceSpecifier *> *serviceSpecifiers; + serviceSpecifiers = [_SWCServiceSpecifier serviceSpecifiersWithEntitlementValue:(__bridge NSArray *)domains + serviceType:_SWCServiceTypeWebCredentials + error:NULL]; + for (_SWCServiceSpecifier *serviceSpecifier in serviceSpecifiers) { + // Check if the hostname matches. + NSString *specifierDomain = [serviceSpecifier domainHost]; + if (NSOrderedSame == [specifierDomain caseInsensitiveCompare:(__bridge NSString *)domain]) { + result = true; + + // Also check the port if specified by the caller. + if (result && port >= 0) { + NSNumber *specifierPort = serviceSpecifier.domainPort; + result = [specifierPort isEqualToNumber:@(port)]; + } + + if (result) { + break; + } + } + } + } + + return result; +} +#endif /* !TARGET_OS_SIMULATOR */ +#endif // TARGET_OS_IOS && !TARGET_OS_BRIDGE diff --git a/keychain/securityd/SecItemServer.c b/keychain/securityd/SecItemServer.c index 039b8252..b16d8652 100644 --- a/keychain/securityd/SecItemServer.c +++ b/keychain/securityd/SecItemServer.c @@ -27,7 +27,7 @@ passwords.) */ -#if TARGET_DARWINOS +#if defined(TARGET_DARWINOS) && TARGET_DARWINOS #undef OCTAGON #undef SECUREOBJECTSYNC #undef SHAREDWEBCREDENTIALS @@ -40,6 +40,8 @@ #include "keychain/securityd/SecItemDb.h" #include "keychain/securityd/SecItemSchema.h" #include +#include +#import #include "keychain/securityd/SecDbKeychainItem.h" #include "keychain/securityd/SOSCloudCircleServer.h" #include @@ -78,7 +80,6 @@ #endif #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR -#include #include #include #endif @@ -91,10 +92,8 @@ #include #include "swcagent_client.h" #include "SecPLWrappers.h" - -#if TARGET_OS_IOS && !TARGET_OS_BRIDGE -#include -#endif +#include "SecItemServer+SWC.h" +#include #include @@ -175,6 +174,7 @@ bool SecKeychainDbGetVersion(SecDbConnectionRef dbt, int *version, CFErrorRef *e } out: secnotice("upgr", "database version is: 0x%08x : %d : %@", *version, ok, localError); + secnotice("upgr", "UID: %d EUID: %d", getuid(), geteuid()); CFReleaseSafe(localError); @@ -213,11 +213,11 @@ measureUpgradePhase1(struct timeval *start, bool success, int64_t itemsMigrated) int64_t duration = measureDuration(start); if (success) { - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-items-success"), itemsMigrated); - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-time-success"), duration); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase1.migrated-items-success"), itemsMigrated); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase1.migrated-time-success"), duration); } else { - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-items-fail"), itemsMigrated); - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-time-fail"), duration); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase1.migrated-items-fail"), itemsMigrated); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase1.migrated-time-fail"), duration); } } @@ -226,8 +226,8 @@ measureUpgradePhase2(struct timeval *start, int64_t itemsMigrated) { int64_t duration = measureDuration(start); - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase2.migrated-items"), itemsMigrated); - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase2.migrated-time"), duration); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase2.migrated-items"), itemsMigrated); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase2.migrated-time"), duration); } #endif /* TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR */ @@ -372,7 +372,7 @@ static bool UpgradeSchemaPhase1(SecDbConnectionRef dbt, const SecDbSchema *oldSc // Prepare query to iterate through all items in cur_class. if (query != NULL) query_destroy(query, NULL); - require_quiet(query = query_create(renamedOldClass, SecMUSRGetAllViews(), NULL, error), out); + require_quiet(query = query_create(renamedOldClass, SecMUSRGetAllViews(), NULL, NULL, error), out); ok &= SecDbItemSelect(query, dbt, error, ^bool(const SecDbAttr *attr) { // We are interested in all attributes which are physically present in the DB. @@ -410,7 +410,7 @@ static bool UpgradeSchemaPhase1(SecDbConnectionRef dbt, const SecDbSchema *oldSc secnotice("upgr", "dropping item during schema upgrade due to agrp=com.apple.token: %@", item); } else { // Insert new item into the new table. - if (!SecDbItemInsert(item, dbt, &localError)) { + if (!SecDbItemInsert(item, dbt, false, &localError)) { secerror("item: %@ insert during upgrade: %@", item, localError); ok = false; } @@ -554,7 +554,7 @@ static bool UpgradeItemPhase2(SecDbConnectionRef inDbt, bool *inProgress, int ol if (query != NULL) { query_destroy(query, NULL); } - require_action_quiet(query = query_create(*class, SecMUSRGetAllViews(), NULL, error), out, ok = false); + require_action_quiet(query = query_create(*class, SecMUSRGetAllViews(), NULL, NULL, error), out, ok = false); ok &= SecDbItemSelect(query, threadDbt, error, NULL, ^bool(const SecDbAttr *attr) { // No simple per-attribute filtering. return false; @@ -586,7 +586,7 @@ static bool UpgradeItemPhase2(SecDbConnectionRef inDbt, bool *inProgress, int ol if (CFEqualSafe(SecDbItemGetCachedValueWithName(item, kSecAttrAccessGroup), kSecAttrAccessGroupToken) && SecDbItemGetCachedValueWithName(item, kSecAttrTokenID) == NULL) { secnotice("upgr", "dropping item during item upgrade due to agrp=com.apple.token: %@", item); - ok = SecDbItemDelete(item, threadDbt, kCFBooleanFalse, &localError); + ok = SecDbItemDelete(item, threadDbt, kCFBooleanFalse, false, &localError); } else { // Replace item with the new value in the table; this will cause the item to be decoded and recoded back, // incl. recalculation of item's hash. @@ -603,7 +603,7 @@ static bool UpgradeItemPhase2(SecDbConnectionRef inDbt, bool *inProgress, int ol // make sure we use a local error so that this error is not proppaged upward and cause a // migration failure. CFErrorRef deleteError = NULL; - (void)SecDbItemDelete(item, threadDbt, false, &deleteError); + (void)SecDbItemDelete(item, threadDbt, false, false, &deleteError); CFReleaseNull(deleteError); ok = true; break; @@ -670,6 +670,42 @@ out: return ok; } +// There's no data-driven approach for this. Let's think about it more if it gets unwieldy +static void performCustomIndexProcessing(SecDbConnectionRef dbt) { + CFErrorRef cfErr = NULL; + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS genpagrp; DROP INDEX IF EXISTS genpsync;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS inetagrp; DROP INDEX IF EXISTS inetsync;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS certagrp; DROP INDEX IF EXISTS certsync;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS keysagrp; DROP INDEX IF EXISTS keyssync;"), &cfErr), errhandler); + + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS genpsync0;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS inetsync0;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS certsync0;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS keyssync0;"), &cfErr), errhandler); + + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS genpmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS inetmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS certmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS keysmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS item_backupmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS backup_keybagmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS backup_keyarchivemusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS archived_key_backupmusr;"), &cfErr), errhandler); + + require(SecDbExec(dbt, CFSTR("CREATE INDEX IF NOT EXISTS agrp_musr_tomb_svce ON genp(agrp, musr, tomb, svce);"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("CREATE INDEX IF NOT EXISTS agrp_musr_tomb_srvr ON inet(agrp, musr, tomb, srvr);"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("CREATE INDEX IF NOT EXISTS agrp_musr_tomb_subj ON cert(agrp, musr, tomb, subj);"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("CREATE INDEX IF NOT EXISTS agrp_musr_tomb_atag ON keys(agrp, musr, tomb, atag);"), &cfErr), errhandler); + + secnotice("upgr", "processed custom indexes (now or in the past)"); + CFReleaseNull(cfErr); // Should be nil but belt and suspenders + return; + +errhandler: + secerror("upgr: failed to process custom indexes: %@", cfErr); + CFReleaseNull(cfErr); +} + static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, bool *inProgress, CFErrorRef *error) { __block bool didPhase2 = false; __block bool ok = true; @@ -707,6 +743,7 @@ static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, // If this is empty database, just create table according to schema and be done with it. require_action_quiet(version2 != 0, out, ok = SecItemDbCreateSchema(dbt, newSchema, NULL, true, &localError); + performCustomIndexProcessing(dbt); LKAReportKeychainUpgradeOutcomeWithError(version2, newVersion, LKAKeychainUpgradeOutcomeNewDb, localError)); int oldVersion = VERSION_OLD(version2); @@ -796,7 +833,7 @@ static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, if (ok && didPhase2) { #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.migration-success"), 1); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.migration-success"), 1); #endif } @@ -839,7 +876,7 @@ out: secerror("upgrade: marking database as corrupt"); SecDbCorrupt(dbt, localError); #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.migration-failure"), 1); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.migration-failure"), 1); #endif } } else { @@ -851,19 +888,13 @@ out: //If we're done here, we should opportunistically re-add all indices (just in case) if(skipped_upgrade || didPhase2) { // Create indices, ignoring all errors + performCustomIndexProcessing(dbt); for (SecDbClass const* const* newClass = newSchema->classes; *newClass; ++newClass) { SecDbForEachAttrWithMask((*newClass), desc, kSecDbIndexFlag | kSecDbInFlag) { CFStringRef sql = NULL; CFErrorRef classLocalError = NULL; bool localOk = true; - - if (desc->kind == kSecDbSyncAttr) { - // Replace the complete sync index with a partial index for sync=0. Most items are sync=1, so the complete index isn't helpful for sync=1 queries. - sql = CFStringCreateWithFormat(NULL, NULL, CFSTR("DROP INDEX IF EXISTS %@%@; CREATE INDEX IF NOT EXISTS %@%@0 on %@(%@) WHERE %@=0;"), - (*newClass)->name, desc->name, (*newClass)->name, desc->name, (*newClass)->name, desc->name, desc->name); - } else { - sql = CFStringCreateWithFormat(NULL, NULL, CFSTR("CREATE INDEX IF NOT EXISTS %@%@ ON %@(%@);"), (*newClass)->name, desc->name, (*newClass)->name, desc->name); - } + sql = CFStringCreateWithFormat(NULL, NULL, CFSTR("CREATE INDEX IF NOT EXISTS %@%@ ON %@(%@);"), (*newClass)->name, desc->name, (*newClass)->name, desc->name); localOk &= SecDbExec(dbt, sql, &classLocalError); CFReleaseNull(sql); @@ -1157,19 +1188,16 @@ SecDbRef SecKeychainDbCreate(CFStringRef path, CFErrorRef* error) { SecDbRef SecKeychainDbInitialize(SecDbRef db) { #if OCTAGON - if(SecCKKSIsEnabled()) { - // This needs to be async, otherwise we get hangs between securityd, cloudd, and apsd - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - SecCKKSInitialize(db); - - }); - } - - if(OctagonIsEnabled() && OctagonShouldPerformInitialization()) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + // This needs to be async, otherwise we get hangs between securityd, cloudd, and apsd + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + if(OctagonIsEnabled() && OctagonShouldPerformInitialization()) { OctagonInitialize(); - }); - } + } + + if(SecCKKSIsEnabled()) { + SecCKKSInitialize(db); + } + }); if(EscrowRequestServerIsEnabled()) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @@ -1221,13 +1249,39 @@ static SecDbRef kc_dbhandle(CFErrorRef* error) return _kc_dbhandle; } +static dispatch_queue_t _async_db_dispatch = NULL; +static dispatch_once_t _async_db_dispatch_onceToken = 0; +static dispatch_queue_t get_async_db_dispatch() { + dispatch_once(&_async_db_dispatch_onceToken, ^{ + _async_db_dispatch = dispatch_queue_create("sec_async_db", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + }); + + return _async_db_dispatch; +} + +/* whitebox testing only, and I really hope you call DbReset soon */ +void SecKeychainDbForceClose(void) +{ + // Wait for any async blocks to finish... + dispatch_group_t g = dispatch_group_create(); + dispatch_group_async(g, get_async_db_dispatch(), ^{}); + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); + + dispatch_sync(get_kc_dbhandle_dispatch(), ^{ + if(_kc_dbhandle) { + SecDbForceClose(_kc_dbhandle); + } + }); + LKAForceClose(); +} + /* For whitebox testing only */ void SecKeychainDbReset(dispatch_block_t inbetween) { dispatch_sync(get_kc_dbhandle_dispatch(), ^{ CFReleaseNull(_kc_dbhandle); SecDbResetMetadataKeys(); - + SecDbResetBackupManager(); if (inbetween) inbetween(); }); @@ -1279,12 +1333,12 @@ bool kc_with_custom_db(bool writeAndRead, bool usesItemTables, SecDbRef db, CFEr // The kc_with_dbt upthread will clean this up when it's done. return perform(threadDbt); } - - if (writeAndRead && usesItemTables) { + #if SECUREOBJECTSYNC + if (writeAndRead && usesItemTables) { SecItemDataSourceFactoryGetDefault(); -#endif } +#endif bool ok = false; if (kc_acquire_dbt(writeAndRead, &threadDbt, error)) { @@ -1316,7 +1370,7 @@ items_matching_issuer_parent(SecDbConnectionRef dbt, CFArrayRef accessGroups, CF return false; CFErrorRef localError = NULL; - q = query_create_with_limit(query, musrView, kSecMatchUnlimited, &localError); + q = query_create_with_limit(query, musrView, kSecMatchUnlimited, NULL, &localError); CFRelease(query); if (q) { s3dl_copy_matching(dbt, q, (CFTypeRef*)&results, accessGroups, &localError); @@ -1537,6 +1591,46 @@ out: return ok; } +//Mark: - + +void deleteCorruptedItemAsync(SecDbConnectionRef dbt, CFStringRef tablename, sqlite_int64 rowid) +{ + // should really get db from dbt, but I don't know much much we should poke holes thought the boundaries. + SecDbRef db = kc_dbhandle(NULL); + if (db == NULL) { + return; + } + + CFRetain(db); + CFRetain(tablename); + + dispatch_async(get_async_db_dispatch(), ^{ + __block CFErrorRef localErr = NULL; + kc_with_custom_db(true, true, db, &localErr, ^bool(SecDbConnectionRef dbt) { + CFStringRef sql = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DELETE FROM %@ WHERE rowid=%lli"), tablename, rowid); + __block bool ok = true; + ok &= SecDbPrepare(dbt, sql, &localErr, ^(sqlite3_stmt *stmt) { + ok &= SecDbStep(dbt, stmt, &localErr, NULL); + }); + + if (!ok || localErr) { + secerror("Failed to delete corrupt item, %@ row %lli: %@", tablename, rowid, localErr); + } else { + secnotice("item", "Deleted corrupt rowid %lli from table %@", rowid, tablename); + } + CFReleaseNull(localErr); + CFReleaseNull(sql); + return true; + }); + + CFRelease(tablename); // can't be a CFReleaseNull() because of scope + CFRelease(db); + }); + +} + + + /**************************************************************************** **************** Beginning of Externally Callable Interface **************** ****************************************************************************/ @@ -1545,7 +1639,7 @@ static bool SecEntitlementError(CFErrorRef *error) { #if TARGET_OS_OSX #define SEC_ENTITLEMENT_WARNING CFSTR("com.apple.application-identifier nor com.apple.security.application-groups nor keychain-access-groups") -#elif TARGET_OS_IOSMAC +#elif TARGET_OS_MACCATALYST #define SEC_ENTITLEMENT_WARNING CFSTR("com.apple.developer.associated-application-identifier nor application-identifier nor com.apple.security.application-groups nor keychain-access-groups") #else #define SEC_ENTITLEMENT_WARNING CFSTR("application-identifier nor keychain-access-groups") @@ -1589,13 +1683,43 @@ static CFStringRef CopyAccessGroupForRowID(sqlite_int64 rowID, CFStringRef itemC } } -/* AUDIT[securityd](done): - query (ok) is a caller provided dictionary, only its cf type has been checked. - */ +// Expand this, rdar://problem/59297616 +// Known attributes which are not API/SPI should not be permitted in queries +static bool nonAPIAttributesInDictionary(CFDictionaryRef attrs) { + return CFDictionaryContainsKey(attrs, kSecAttrAppClipItem); +} + +static bool appClipHasSaneAccessGroups(SecurityClient* client) { + if (!client || !client->applicationIdentifier || !client->accessGroups) { + secerror("item: no app clip client or attributes not set, cannot verify restrictions"); + return false; + } + + CFIndex count = CFArrayGetCount(client->accessGroups); + if (count == 1 && CFEqualSafe(client->applicationIdentifier, CFArrayGetValueAtIndex(client->accessGroups, 0))) { + return true; + } + + // sigh, alright is the _other_ access group the application identifier? + if (count == 2) { + CFIndex tokenIdx = CFArrayGetFirstIndexOfValue(client->accessGroups, CFRangeMake(0, count), kSecAttrAccessGroupToken); + if (tokenIdx != kCFNotFound) { + return CFEqualSafe(client->applicationIdentifier, CFArrayGetValueAtIndex(client->accessGroups, tokenIdx == 0 ? 1 : 0)); + } + } + + return false; +} + static bool SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, SecurityClient *client, CFErrorRef *error) { + if (nonAPIAttributesInDictionary(query)) { + SecError(errSecParam, error, CFSTR("Non-API attributes present in query")); + return false; + } + CFArrayRef accessGroups = CFRetainSafe(client->accessGroups); CFIndex ag_count; @@ -1628,7 +1752,7 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, } bool ok = false; - Query *q = query_create_with_limit(query, client->musr, 1, error); + Query *q = query_create_with_limit(query, client->musr, 1, client, error); if (q) { CFStringRef agrp = CFDictionaryGetValue(q->q_item, kSecAttrAccessGroup); if (agrp) { @@ -1642,18 +1766,6 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, query_destroy(q, NULL); return false; } - } else { -#if !TARGET_OS_OSX - if (accessGroups != NULL) { - // On iOS, drop 'com.apple.token' AG from allowed accessGroups, to avoid inserting token elements into - // unsuspecting application's keychain. If the application on iOS wants to access token items, it needs - // explicitly specify kSecAttrAccessGroup=kSecAttrAccessGroupToken in its query. - CFMutableArrayRef mutableGroups = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, accessGroups); - CFArrayRemoveAllValue(mutableGroups, kSecAttrAccessGroupToken); - CFReleaseNull(accessGroups); - accessGroups = mutableGroups; - } -#endif } #if TARGET_OS_IPHONE @@ -1672,9 +1784,9 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, #endif query_set_caller_access_groups(q, accessGroups); - - /* Sanity check the query. */ - if (q->q_system_keychain && !client->allowSystemKeychain) { + if (client->isAppClip && !appClipHasSaneAccessGroups(client)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to use access groups other than application identifier")); + } else if (q->q_system_keychain && !client->allowSystemKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); @@ -1696,8 +1808,9 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, }); } - if (!query_destroy(q, error)) + if (!query_destroy(q, error)) { ok = false; + } } CFReleaseNull(accessGroups); @@ -1744,14 +1857,14 @@ SecurityClientCopyWritableAccessGroups(SecurityClient *client) { } } - -/* AUDIT[securityd](done): - attributes (ok) is a caller provided dictionary, only its cf type has - been checked. - */ bool _SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *result, CFErrorRef *error) { + if (nonAPIAttributesInDictionary(attributes)) { + SecError(errSecParam, error, CFSTR("Non-API attributes present")); + return false; + } + CFArrayRef accessGroups = SecurityClientCopyWritableAccessGroups(client); bool ok = true; @@ -1763,20 +1876,22 @@ _SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *resul SecSignpostStart(SecSignpostSecItemAdd); - Query *q = query_create_with_limit(attributes, client->musr, 0, error); + Query *q = query_create_with_limit(attributes, client->musr, 0, client, error); if (q) { /* Access group sanity checking. */ CFStringRef agrp = (CFStringRef)CFDictionaryGetValue(attributes, kSecAttrAccessGroup); /* Having the special accessGroup "*" allows access to all accessGroups. */ - if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) + if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) { CFReleaseNull(accessGroups); + } if (agrp) { /* The user specified an explicit access group, validate it. */ - if (!accessGroupsAllows(accessGroups, agrp, client)) + if (!accessGroupsAllows(accessGroups, agrp, client)) { ok = SecEntitlementErrorForExplicitAccessGroup(agrp, accessGroups, error); + } } else { agrp = (CFStringRef)CFArrayGetValueAtIndex(client->accessGroups, 0); @@ -1813,8 +1928,11 @@ _SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *resul q->q_add_sync_callback = add_sync_callback; } #endif - - if (q->q_system_keychain && !client->allowSystemKeychain) { + if (client->isAppClip && !appClipHasSaneAccessGroups(client)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to use access groups other than application identifier")); + } else if (client->isAppClip && CFEqualSafe(CFDictionaryGetValue(attributes, kSecAttrSynchronizable), kCFBooleanTrue)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to add synchronizable items to the keychain")); + } else if (q->q_system_keychain && !client->allowSystemKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); @@ -1844,14 +1962,15 @@ _SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *resul return ok; } -/* AUDIT[securityd](done): - query (ok) and attributesToUpdate (ok) are a caller provided dictionaries, - only their cf types have been checked. - */ bool _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, SecurityClient *client, CFErrorRef *error) { + if (nonAPIAttributesInDictionary(query) || nonAPIAttributesInDictionary(attributesToUpdate)) { + SecError(errSecParam, error, CFSTR("Non-API attributes present")); + return false; + } + CFArrayRef accessGroups = SecurityClientCopyWritableAccessGroups(client); CFIndex ag_count; @@ -1886,7 +2005,7 @@ _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, } bool ok = true; - Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, error); + Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, client, error); if (!q) { ok = false; } @@ -1899,10 +2018,14 @@ _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, q->q_system_keychain = false; } #endif - - /* Sanity check the query. */ query_set_caller_access_groups(q, accessGroups); - if (q->q_system_keychain && !client->allowSystemKeychain) { + if (client->isAppClip && !appClipHasSaneAccessGroups(client)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to use access groups other than application identifier")); + } else if (client->isAppClip && (CFEqualSafe(CFDictionaryGetValue(query, kSecAttrSynchronizable), kCFBooleanTrue) || + CFEqualSafe(CFDictionaryGetValue(attributesToUpdate, kSecAttrSynchronizable), kCFBooleanTrue))) + { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to make items synchronizable")); + } else if (q->q_system_keychain && !client->allowSystemKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); @@ -1952,13 +2075,14 @@ _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, return ok; } - -/* AUDIT[securityd](done): - query (ok) is a caller provided dictionary, only its cf type has been checked. - */ bool _SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error) { + if (nonAPIAttributesInDictionary(query)) { + SecError(errSecParam, error, CFSTR("Non-API attributes present")); + return false; + } + CFArrayRef accessGroups = SecurityClientCopyWritableAccessGroups(client); CFIndex ag_count; @@ -1990,7 +2114,7 @@ _SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error) CFReleaseNull(accessGroups); } - Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, error); + Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, client, error); bool ok; if (q) { #if TARGET_OS_IPHONE @@ -2003,8 +2127,9 @@ _SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error) #endif query_set_caller_access_groups(q, accessGroups); - /* Sanity check the query. */ - if (q->q_system_keychain && !client->allowSystemKeychain) { + if (client->isAppClip && !appClipHasSaneAccessGroups(client)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to use access groups other than application identifier")); + } else if (q->q_system_keychain && !client->allowSystemKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); @@ -2037,11 +2162,8 @@ _SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error) } static bool SecItemDeleteTokenItems(SecDbConnectionRef dbt, CFTypeRef classToDelete, CFTypeRef tokenID, CFArrayRef accessGroups, SecurityClient *client, CFErrorRef *error) { - CFTypeRef keys[] = { kSecClass, kSecAttrTokenID }; - CFTypeRef values[] = { classToDelete, tokenID }; - - CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, error); + CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecClass, classToDelete, kSecAttrTokenID, tokenID, NULL); + Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, client, error); CFRelease(query); bool ok; if (q) { @@ -2055,73 +2177,55 @@ static bool SecItemDeleteTokenItems(SecDbConnectionRef dbt, CFTypeRef classToDel return ok; } -static bool SecItemAddTokenItem(SecDbConnectionRef dbt, CFDictionaryRef attributes, CFArrayRef accessGroups, SecurityClient *client, CFErrorRef *error) { - bool ok = true; - Query *q = query_create_with_limit(attributes, client->musr, 0, error); - if (q) { - CFStringRef agrp = kSecAttrAccessGroupToken; +static bool SecItemAddTokenItemToAccessGroups(SecDbConnectionRef dbt, CFDictionaryRef attributes, CFArrayRef accessGroups, SecurityClient *client, CFErrorRef *error) { + Query *q; + bool ok = false; + for (CFIndex i = 0; i < CFArrayGetCount(accessGroups); ++i) { + require_quiet(q = query_create_with_limit(attributes, client->musr, 0, client, error), out); + CFStringRef agrp = CFArrayGetValueAtIndex(accessGroups, i); query_add_attribute(kSecAttrAccessGroup, agrp, q); - - if (ok) { - query_ensure_access_control(q, agrp); - if (q->q_system_keychain && !client->allowSystemKeychain) { - ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); - } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { - ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); - } else if (q->q_row_id || q->q_token_object_id) { - ok = SecError(errSecValuePersistentRefUnsupported, error, CFSTR("q_row_id")); // TODO: better error string - } else if (!q->q_error) { - query_pre_add(q, true); - ok = s3dl_query_add(dbt, q, NULL, error); - } + query_ensure_access_control(q, agrp); + bool added = false; + if (!q->q_error) { + query_pre_add(q, true); + added = s3dl_query_add(dbt, q, NULL, error); } - ok = query_notify_and_destroy(q, ok, error); - } else { - return false; + require_quiet(query_notify_and_destroy(q, added, error), out); } + ok = true; +out: return ok; } -bool _SecItemUpdateTokenItems(CFStringRef tokenID, CFArrayRef items, SecurityClient *client, CFErrorRef *error) { - bool ok = true; - CFArrayRef accessGroups = client->accessGroups; - CFIndex ag_count; - if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { - return SecEntitlementError(error); +bool _SecItemUpdateTokenItemsForAccessGroups(CFStringRef tokenID, CFArrayRef accessGroups, CFArrayRef items, SecurityClient *client, CFErrorRef *error) { + // This is SPI for CTK only, don't even listen to app clips. + if (client->isAppClip) { + return SecError(errSecRestrictedAPI, error, CFSTR("App Clips may not call this API")); } - ok = kc_with_dbt(true, error, ^bool (SecDbConnectionRef dbt) { + return kc_with_dbt(true, error, ^bool (SecDbConnectionRef dbt) { return kc_transaction(dbt, error, ^bool { - if (items) { - const CFTypeRef classToDelete[] = { kSecClassGenericPassword, kSecClassInternetPassword, kSecClassCertificate, kSecClassKey }; - for (size_t i = 0; i < sizeof(classToDelete) / sizeof(classToDelete[0]); ++i) { - SecItemDeleteTokenItems(dbt, classToDelete[i], tokenID, accessGroups, client, NULL); + bool ok = false; + CFErrorRef localError = NULL; + const CFTypeRef classToDelete[] = { kSecClassGenericPassword, kSecClassInternetPassword, kSecClassCertificate, kSecClassKey }; + for (size_t i = 0; i < sizeof(classToDelete) / sizeof(classToDelete[0]); ++i) { + if (!SecItemDeleteTokenItems(dbt, classToDelete[i], tokenID, accessGroups, client, &localError)) { + require_action_quiet(CFErrorGetCode(localError) == errSecItemNotFound, out, CFErrorPropagate(localError, error)); + CFReleaseNull(localError); } + } + if (items) { for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { - if (!SecItemAddTokenItem(dbt, CFArrayGetValueAtIndex(items, i), accessGroups, client, error)) - return false; + require_quiet(SecItemAddTokenItemToAccessGroups(dbt, CFArrayGetValueAtIndex(items, i), accessGroups, client, error), out); } - return true; - } - else { - const CFTypeRef classToDelete[] = { kSecClassGenericPassword, kSecClassInternetPassword, kSecClassCertificate, kSecClassKey }; - bool deleted = true; - for (size_t i = 0; i < sizeof(classToDelete) / sizeof(classToDelete[0]); ++i) { - if (!SecItemDeleteTokenItems(dbt, classToDelete[i], tokenID, accessGroups, client, error) && error && CFErrorGetCode(*error) != errSecItemNotFound) { - deleted = false; - break; - } - else if (error && *error) { - CFReleaseNull(*error); - } - } - return deleted; } + + ok = true; + out: + return ok; }); }); - - return ok; } static bool deleteNonSysboundItemsForItemClass(SecDbConnectionRef dbt, SecDbClass const* class, CFErrorRef* error) { @@ -2129,7 +2233,7 @@ static bool deleteNonSysboundItemsForItemClass(SecDbConnectionRef dbt, SecDbClas CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll); __block CFErrorRef localError = NULL; - SecDbQueryRef q = query_create(class, NULL, query, &localError); + SecDbQueryRef q = query_create(class, NULL, query, NULL, &localError); if (q == NULL) { // illegal query or out of memory secerror("SecItemServerDeleteAll: aborting because failed to initialize Query: %@", localError); abort(); @@ -2141,7 +2245,7 @@ static bool deleteNonSysboundItemsForItemClass(SecDbConnectionRef dbt, SecDbClas if (!SecItemIsSystemBound(item->attributes, class, false) && !CFEqual(CFDictionaryGetValue(item->attributes, kSecAttrAccessGroup), CFSTR("com.apple.bluetooth"))) { - SecDbItemDelete(item, dbt, kCFBooleanFalse, &localError); + SecDbItemDelete(item, dbt, kCFBooleanFalse, false, &localError); } }); query_destroy(q, &localError); @@ -2253,7 +2357,7 @@ _SecItemServerDeleteAllWithAccessGroups(CFArrayRef accessGroups, SecurityClient for (n = 0; n < sizeof(qclasses)/sizeof(qclasses[0]) && ok1; n++) { Query *q; - q = query_create(qclasses[n], client->musr, NULL, error); + q = query_create(qclasses[n], client->musr, NULL, client, error); require(q, fail2); (void)s3dl_query_delete(dbt, q, accessGroups, &localError); @@ -2275,82 +2379,15 @@ fail: #if SHAREDWEBCREDENTIALS +// OSX now has SWC enabled, but cannot link SharedWebCredentials framework: rdar://59958701 +#if TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_WATCH && !TARGET_OS_TV + /* constants */ #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v); SEC_CONST_DECL (kSecSafariAccessGroup, "com.apple.cfnetwork"); SEC_CONST_DECL (kSecSafariDefaultComment, "default"); SEC_CONST_DECL (kSecSafariPasswordsNotSaved, "Passwords not saved"); -SEC_CONST_DECL (kSecSharedCredentialUrlScheme, "https://"); -SEC_CONST_DECL (kSecSharedWebCredentialsService, "webcredentials"); - -#if !TARGET_OS_SIMULATOR -static SWCFlags -_SecAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFErrorRef *error) -{ - __block SWCFlags flags = kSWCFlags_None; - OSStatus status; - - secnotice("swc", "Application %@ is requesting approval for %@", appID, fqdn); - - dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - if (semaphore == NULL) - return 0; - - status = SWCCheckService(kSecSharedWebCredentialsService, appID, fqdn, ^void (OSStatus inStatus, SWCFlags inFlags, CFDictionaryRef inDetails) - { - if (inStatus == 0) { - flags = inFlags; - } else { - secerror("SWCCheckService failed with %d", (int)inStatus); - } - dispatch_semaphore_signal(semaphore); - }); - - if (status == 0) { - dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); - } else { - secerror("SWCCheckService: failed to queue"); - } - dispatch_release(semaphore); - - if (error) { - if (!(flags & kSWCFlag_SiteApproved)) { - SecError(errSecAuthFailed, error, CFSTR("\"%@\" failed to approve \"%@\""), fqdn, appID); - } else if (flags & kSWCFlag_UserDenied) { - SecError(errSecAuthFailed, error, CFSTR("User denied access to \"%@\" by \"%@\""), fqdn, appID); - } - } - return flags; -} - -static bool -_SecEntitlementContainsDomainForService(CFArrayRef domains, CFStringRef domain, CFStringRef service) -{ - bool result = false; - CFIndex idx, count = (domains) ? CFArrayGetCount(domains) : (CFIndex) 0; - if (!count || !domain || !service) { - return result; - } - for (idx=0; idx < count; idx++) { - CFStringRef str = (CFStringRef) CFArrayGetValueAtIndex(domains, idx); - if (str && CFStringHasPrefix(str, kSecSharedWebCredentialsService)) { - CFIndex prefix_len = CFStringGetLength(kSecSharedWebCredentialsService)+1; - CFIndex substr_len = CFStringGetLength(str) - prefix_len; - CFRange range = { prefix_len, substr_len }; - CFStringRef substr = CFStringCreateWithSubstring(kCFAllocatorDefault, str, range); - if (substr && CFEqual(substr, domain)) { - result = true; - } - CFReleaseSafe(substr); - if (result) { - break; - } - } - } - return result; -} -#endif /* !TARGET_OS_SIMULATOR */ static bool _SecAddNegativeWebCredential(SecurityClient *client, CFStringRef fqdn, CFStringRef appID, bool forSafari) @@ -2360,21 +2397,7 @@ _SecAddNegativeWebCredential(SecurityClient *client, CFStringRef fqdn, CFStringR if (!fqdn) { return result; } // update our database - CFRetainSafe(appID); - CFRetainSafe(fqdn); - if (0 == SWCSetServiceFlags(kSecSharedWebCredentialsService, appID, fqdn, kSWCFlag_ExternalMask, kSWCFlag_UserDenied, - ^void(OSStatus inStatus, SWCFlags inNewFlags){ - CFReleaseSafe(appID); - CFReleaseSafe(fqdn); - })) - { - result = true; - } - else // didn't queue the block - { - CFReleaseSafe(appID); - CFReleaseSafe(fqdn); - } + _SecSetAppDomainApprovalStatus(appID, fqdn, kCFBooleanFalse); if (!forSafari) { return result; } @@ -2468,20 +2491,13 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, // parse fqdn with CFURL here, since it could be specified as domain:port if (fqdn) { - CFStringRef urlStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), kSecSharedCredentialUrlScheme, fqdn); - if (urlStr) { - CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, urlStr, nil); - if (url) { - CFStringRef hostname = CFURLCopyHostName(url); - if (hostname) { - CFReleaseSafe(fqdn); - fqdn = hostname; - port = CFURLGetPortNumber(url); - } - CFReleaseSafe(url); - } - CFReleaseSafe(urlStr); - } + CFTypeRef fqdnObject = _SecCopyFQDNObjectFromString(fqdn); + if (fqdnObject) { + CFReleaseSafe(fqdn); + fqdn = _SecGetFQDNFromFQDNObject(fqdnObject, &port); + CFRetainSafe(fqdn); + CFReleaseSafe(fqdnObject); + } } if (!account) { @@ -2502,7 +2518,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, SecError(status, error, CFSTR("Missing application-identifier entitlement")); goto cleanup; } - if (_SecEntitlementContainsDomainForService(domains, fqdn, kSecSharedWebCredentialsService)) { + if (_SecEntitlementContainsDomainForService(domains, fqdn, port)) { status = errSecSuccess; } if (errSecSuccess != status) { @@ -2521,8 +2537,8 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, secerror("Ignoring app/site approval state in the Simulator."); #else // get approval status for this app/domain pair - SWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); - if (!(flags & kSWCFlag_SiteApproved)) { + SecSWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); + if (!(flags & kSecSWCFlag_SiteApproved)) { goto cleanup; } #endif @@ -2582,7 +2598,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, bool samePassword = result && *result && CFEqual(*result, credential); CFReleaseSafe(credential); CFDictionaryAddValue(attrs, kSecAttrComment, kSecSafariDefaultComment); - + ok = samePassword || swca_confirm_operation(swca_update_request_id, clientAuditToken, query, error, ^void (CFStringRef confirm_fqdn) { _SecAddNegativeWebCredential(client, confirm_fqdn, appID, false); @@ -2602,7 +2618,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, ok = _SecItemDelete(query, &swcclient, error); } } - + if(result) CFReleaseNull(*result); if(error) CFReleaseNull(*error); @@ -2672,9 +2688,7 @@ _SecCopySharedWebCredential(CFDictionaryRef query, CFMutableArrayRef credentials = NULL; CFMutableArrayRef foundItems = NULL; CFMutableArrayRef fqdns = NULL; - CFStringRef fqdn = NULL; CFStringRef account = NULL; - SInt32 port = -1; bool ok = false; require_quiet(result, cleanup); @@ -2694,7 +2708,6 @@ _SecCopySharedWebCredential(CFDictionaryRef query, }; // On input, the query dictionary contains optional fqdn and account entries. - fqdn = CFDictionaryGetValue(query, kSecAttrServer); account = CFDictionaryGetValue(query, kSecAttrAccount); // Check autofill enabled status @@ -2704,28 +2717,30 @@ _SecCopySharedWebCredential(CFDictionaryRef query, } // Check fqdn; if NULL, add domains from caller's entitlement. - if (fqdn) { - CFArrayAppendValue(fqdns, fqdn); - } - else if (domains) { - CFIndex idx, count = CFArrayGetCount(domains); - for (idx=0; idx < count; idx++) { - CFStringRef str = (CFStringRef) CFArrayGetValueAtIndex(domains, idx); - // Parse the entry for our service label prefix - if (str && CFStringHasPrefix(str, kSecSharedWebCredentialsService)) { - CFIndex prefix_len = CFStringGetLength(kSecSharedWebCredentialsService)+1; - CFIndex substr_len = CFStringGetLength(str) - prefix_len; - CFRange range = { prefix_len, substr_len }; - fqdn = CFStringCreateWithSubstring(kCFAllocatorDefault, str, range); - if (fqdn) { - CFArrayAppendValue(fqdns, fqdn); - CFRelease(fqdn); + { + CFStringRef fqdn = CFDictionaryGetValue(query, kSecAttrServer); + if (fqdn) { + CFTypeRef fqdnObject = _SecCopyFQDNObjectFromString(fqdn); + if (fqdnObject) { + CFArrayAppendValue(fqdns, fqdnObject); + CFReleaseSafe(fqdnObject); + } + } + else if (domains) { + CFIndex idx, count = CFArrayGetCount(domains); + for (idx=0; idx < count; idx++) { + CFStringRef str = (CFStringRef) CFArrayGetValueAtIndex(domains, idx); + // Parse the entry for our service label prefix + CFTypeRef fqdnObject = _SecCopyFQDNObjectFromString(str); + if (fqdnObject) { + CFArrayAppendValue(fqdns, fqdnObject); + CFReleaseSafe(fqdnObject); } } } } CFIndex count, idx; - + count = CFArrayGetCount(fqdns); if (count < 1) { SecError(errSecParam, error, CFSTR("No domain provided")); @@ -2736,27 +2751,10 @@ _SecCopySharedWebCredential(CFDictionaryRef query, for (idx = 0; idx < count; idx++) { CFMutableArrayRef items = NULL; CFMutableDictionaryRef attrs = NULL; - fqdn = (CFStringRef) CFArrayGetValueAtIndex(fqdns, idx); - CFRetainSafe(fqdn); - port = -1; - // Parse the fqdn for a possible port specifier. - if (fqdn) { - CFStringRef urlStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), kSecSharedCredentialUrlScheme, fqdn); - if (urlStr) { - CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, urlStr, nil); - if (url) { - CFStringRef hostname = CFURLCopyHostName(url); - if (hostname) { - CFReleaseSafe(fqdn); - fqdn = hostname; - port = CFURLGetPortNumber(url); - } - CFReleaseSafe(url); - } - CFReleaseSafe(urlStr); - } - } + CFTypeRef fqdnObject = CFArrayGetValueAtIndex(fqdns, idx); + SInt32 port = -1; + CFStringRef fqdn = _SecGetFQDNFromFQDNObject(fqdnObject, &port); #if TARGET_OS_SIMULATOR secerror("app/site association entitlements not checked in Simulator"); @@ -2764,11 +2762,10 @@ _SecCopySharedWebCredential(CFDictionaryRef query, OSStatus status = errSecMissingEntitlement; if (!appID) { SecError(status, error, CFSTR("Missing application-identifier entitlement")); - CFReleaseSafe(fqdn); goto cleanup; } // validate that fqdn is part of caller's entitlement - if (_SecEntitlementContainsDomainForService(domains, fqdn, kSecSharedWebCredentialsService)) { + if (_SecEntitlementContainsDomainForService(domains, fqdn, port)) { status = errSecSuccess; } if (errSecSuccess != status) { @@ -2779,7 +2776,6 @@ _SecCopySharedWebCredential(CFDictionaryRef query, } SecError(status, error, CFSTR("%@"), msg); CFReleaseSafe(msg); - CFReleaseSafe(fqdn); goto cleanup; } #endif @@ -2787,7 +2783,6 @@ _SecCopySharedWebCredential(CFDictionaryRef query, attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!attrs) { SecError(errSecAllocate, error, CFSTR("Unable to create query dictionary")); - CFReleaseSafe(fqdn); goto cleanup; } CFDictionaryAddValue(attrs, kSecClass, kSecClassInternetPassword); @@ -2820,12 +2815,12 @@ _SecCopySharedWebCredential(CFDictionaryRef query, bool approved = true; #else // get approval status for this app/domain pair - SWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); + SecSWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); if (count > 1) { // ignore interim error since we have multiple domains to check CFReleaseNull(*error); } - bool approved = (flags & kSWCFlag_SiteApproved); + bool approved = (flags & kSecSWCFlag_SiteApproved); #endif if (approved) { CFArrayAppendArray(foundItems, items, CFRangeMake(0, CFArrayGetCount(items))); @@ -2833,7 +2828,6 @@ _SecCopySharedWebCredential(CFDictionaryRef query, } CFReleaseSafe(items); CFReleaseSafe(attrs); - CFReleaseSafe(fqdn); } // If matching credentials are found, the credentials provided to the completionHandler @@ -2939,29 +2933,13 @@ _SecCopySharedWebCredential(CFDictionaryRef query, CFArrayRemoveAllValues(credentials); if (selected && ok) { #if TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_SIMULATOR - fqdn = CFDictionaryGetValue(selected, kSecAttrServer); + // register confirmation with database + CFStringRef fqdn = CFDictionaryGetValue(selected, kSecAttrServer); + _SecSetAppDomainApprovalStatus(appID, fqdn, kCFBooleanTrue); #endif CFArrayAppendValue(credentials, selected); } - if (ok) { -#if TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_SIMULATOR - // register confirmation with database - CFRetainSafe(appID); - CFRetainSafe(fqdn); - if (0 != SWCSetServiceFlags(kSecSharedWebCredentialsService, - appID, fqdn, kSWCFlag_ExternalMask, kSWCFlag_UserApproved, - ^void(OSStatus inStatus, SWCFlags inNewFlags){ - CFReleaseSafe(appID); - CFReleaseSafe(fqdn); - })) - { - // we didn't queue the block - CFReleaseSafe(appID); - CFReleaseSafe(fqdn); - } -#endif - } CFReleaseSafe(selected); } else if (NULL == *error) { @@ -2982,6 +2960,23 @@ cleanup: return ok; } +#else /* !(TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_WATCH && !TARGET_OS_TV) */ + +bool _SecAddSharedWebCredential(CFDictionaryRef attributes, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error) { + if (error) { + SecError(errSecUnimplemented, error, CFSTR("_SecAddSharedWebCredential not supported on this platform")); + } + return false; +} + +bool _SecCopySharedWebCredential(CFDictionaryRef query, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error) { + if (error) { + SecError(errSecUnimplemented, error, CFSTR("_SecCopySharedWebCredential not supported on this platform")); + } + return false; +} + +#endif /* !(TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_WATCH && !TARGET_OS_TV) */ #endif /* SHAREDWEBCREDENTIALS */ @@ -3262,6 +3257,13 @@ _SecServerRestoreSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef pa errOut: return ok; } + +#else /* SECUREOBJECTSYNC */ + +SOSDataSourceFactoryRef SecItemDataSourceFactoryGetDefault(void) { + return NULL; +} + #endif /* SECUREOBJECTSYNC */ bool _SecServerRollKeysGlue(bool force, CFErrorRef *error) { @@ -3301,7 +3303,7 @@ InitialSyncItems(CFMutableArrayRef items, bool limitToCurrent, CFStringRef agrp, bool result = false; Query *q = NULL; - q = query_create(qclass, NULL, NULL, error); + q = query_create(qclass, NULL, NULL, NULL, error); require(q, fail); q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; @@ -3445,7 +3447,7 @@ _SecServerImportInitialSyncCredentials(CFArrayRef array, CFErrorRef *error) continue; } - if (!SecDbItemInsert(dbi, dbt, &cferror)) { + if (!SecDbItemInsert(dbi, dbt, false, &cferror)) { secinfo("ImportInitialSyncItems", "Item store failed with: %@: %@", cferror, dbi); CFReleaseNull(cferror); } @@ -3499,7 +3501,7 @@ TransmogrifyItemsToSyncBubble(SecurityClient *client, uid_t uid, secnotice("syncbubble", "cleaning out old items"); - q = query_create(qclass, NULL, NULL, error); + q = query_create(qclass, NULL, NULL, client, error); require(q, fail); q->q_limit = kSecMatchUnlimited; @@ -3531,7 +3533,7 @@ TransmogrifyItemsToSyncBubble(SecurityClient *client, uid_t uid, secnotice("syncbubble", "migrating sync bubble items"); - q = query_create(qclass, NULL, NULL, error); + q = query_create(qclass, NULL, NULL, client, error); require(q, fail); q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; @@ -3571,7 +3573,7 @@ TransmogrifyItemsToSyncBubble(SecurityClient *client, uid_t uid, return; } - if (!SecDbItemInsert(new_item, dbt, &error3)) { + if (!SecDbItemInsert(new_item, dbt, false, &error3)) { secnotice("syncbubble", "migration failed with %@ for item %@", error3, new_item); } CFRelease(new_item); @@ -3813,7 +3815,7 @@ _SecServerTransmogrifyToSystemKeychain(SecurityClient *client, CFErrorRef *error continue; } - q = query_create(*kcClass, SecMUSRGetSingleUserKeychainUUID(), NULL, error); + q = query_create(*kcClass, SecMUSRGetSingleUserKeychainUUID(), NULL, client, error); if (q == NULL) continue; diff --git a/keychain/securityd/SecItemServer.h b/keychain/securityd/SecItemServer.h index 91fcda27..b8f82e3a 100644 --- a/keychain/securityd/SecItemServer.h +++ b/keychain/securityd/SecItemServer.h @@ -56,7 +56,7 @@ CFStringRef _SecServerBackupCopyUUID(CFDataRef backup, CFErrorRef *error); bool _SecServerBackupKeybagAdd(SecurityClient *client, CFDataRef passcode, CFDataRef *identifier, CFDataRef *pathinfo, CFErrorRef *error); bool _SecServerBackupKeybagDelete(CFDictionaryRef attributes, bool deleteAll, CFErrorRef *error); -bool _SecItemUpdateTokenItems(CFStringRef tokenID, CFArrayRef items, SecurityClient *client, CFErrorRef *error); +bool _SecItemUpdateTokenItemsForAccessGroups(CFStringRef tokenID, CFArrayRef accessGroups, CFArrayRef items, SecurityClient *client, CFErrorRef *error); CF_RETURNS_RETAINED CFArrayRef _SecServerKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error); CF_RETURNS_RETAINED CFDictionaryRef _SecServerBackupSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error); @@ -71,10 +71,10 @@ bool _SecServerTransmogrifyToSyncBubble(CFArrayRef services, uid_t uid, Security bool _SecServerDeleteMUSERViews(SecurityClient *client, uid_t uid, CFErrorRef *error); #endif -#if TARGET_OS_IOS && !TARGET_OS_BRIDGE +#if SHAREDWEBCREDENTIALS bool _SecAddSharedWebCredential(CFDictionaryRef attributes, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error); bool _SecCopySharedWebCredential(CFDictionaryRef query, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error); -#endif /* TARGET_OS_IOS */ +#endif /* SHAREDWEBCREDENTIALS */ // Hack to log objects from inside SOS code void SecItemServerAppendItemDescription(CFMutableStringRef desc, CFDictionaryRef object); @@ -87,9 +87,10 @@ bool kc_with_dbt_non_item_tables(bool writeAndRead, CFErrorRef* error, bool (^pe bool kc_with_custom_db(bool writeAndRead, bool usesItemTables, SecDbRef db, CFErrorRef *error, bool (^perform)(SecDbConnectionRef dbt)); -/* For whitebox testing only */ -void SecKeychainDbReset(dispatch_block_t inbetween); +/* For whitebox testing only */ +void SecKeychainDbForceClose(void); +void SecKeychainDbReset(dispatch_block_t inbetween); SOSDataSourceFactoryRef SecItemDataSourceFactoryGetDefault(void); @@ -127,6 +128,8 @@ bool accessGroupsAllows(CFArrayRef accessGroups, CFStringRef accessGroup, Securi bool itemInAccessGroup(CFDictionaryRef item, CFArrayRef accessGroups); void SecKeychainChanged(void); +void deleteCorruptedItemAsync(SecDbConnectionRef dbt, CFStringRef tablename, sqlite_int64 rowid); + __END_DECLS #endif /* _SECURITYD_SECITEMSERVER_H_ */ diff --git a/keychain/securityd/SecKeybagSupport.c b/keychain/securityd/SecKeybagSupport.c index d526c73f..ee88f5d9 100644 --- a/keychain/securityd/SecKeybagSupport.c +++ b/keychain/securityd/SecKeybagSupport.c @@ -337,7 +337,7 @@ bool ks_decrypt_acl(aks_ref_key_t ref_key, CFDataRef encrypted_data, CFMutableDa aks_return, "decrypt")); CFPropertyListRef decoded_data = NULL; - der_decode_plist(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_data, NULL, der, der + der_len); + der_decode_plist(kCFAllocatorDefault, &decoded_data, NULL, der, der + der_len); require_action_quiet(decoded_data, out, SecError(errSecDecode, error, CFSTR("ks_crypt_acl: %x failed to '%s' item, Item can't be decrypted due to failed decode der, so drop the item."), aks_return, "decrypt")); if (CFGetTypeID(decoded_data) == CFDataGetTypeID()) { @@ -370,7 +370,7 @@ bool ks_delete_acl(aks_ref_key_t ref_key, CFDataRef encrypted_data, int aks_return = kAKSReturnSuccess; bool ok = false; - nrequire_action_quiet(CFEqual(SecAccessControlGetConstraint(access_control, kAKSKeyOpDelete), kCFBooleanTrue), out, ok = true); + nrequire_action_quiet(CFEqualSafe(SecAccessControlGetConstraint(access_control, kAKSKeyOpDelete), kCFBooleanTrue), out, ok = true); /* Verify that we have credential handle, otherwise generate proper error containing ACL and operation requested. */ if (!acm_context) { diff --git a/keychain/securityd/SecOTRRemote.m b/keychain/securityd/SecOTRRemote.m index cef0caf1..fcc4e564 100644 --- a/keychain/securityd/SecOTRRemote.m +++ b/keychain/securityd/SecOTRRemote.m @@ -64,7 +64,7 @@ CFDataRef SecOTRSessionCreateRemote_internal(CFDataRef publicAccountData, CFData privateKeyRef = SOSAccountCopyDeviceKey(privateAccount, error); require_quiet(privateKeyRef, fail); - privateIdentity = SecOTRFullIdentityCreateFromSecKeyRef(kCFAllocatorDefault, privateKeyRef, error); + privateIdentity = SecOTRFullIdentityCreateFromSecKeyRefSOS(kCFAllocatorDefault, privateKeyRef, error); require_quiet(privateIdentity, fail); CFReleaseNull(privateKeyRef); diff --git a/keychain/securityd/com.apple.secd.sb b/keychain/securityd/com.apple.secd.sb index 21f50f45..eb7ab1f7 100644 --- a/keychain/securityd/com.apple.secd.sb +++ b/keychain/securityd/com.apple.secd.sb @@ -4,6 +4,9 @@ (import "system.sb") +(allow file-write-data + (literal "/dev/random")) + (allow file-read* file-write* (subpath "/private/var/db/mds") (regex #"^/private/var/folders/[^/]+/[^/]+/T(/|$)") @@ -61,6 +64,7 @@ (global-name "com.apple.windowserver.active") (global-name "com.apple.powerlog.plxpclogger.xpc") (global-name "com.apple.SecureBackupDaemon") + (global-name "com.apple.SecureBackupDaemon.concurrent") ) ;; Used to send logs for MoiC. diff --git a/keychain/securityd/entitlements.plist b/keychain/securityd/entitlements.plist index 02625012..05391bd2 100644 --- a/keychain/securityd/entitlements.plist +++ b/keychain/securityd/entitlements.plist @@ -2,6 +2,8 @@ + com.apple.private.cloudkit.notifyOnAccountWarmup + com.apple.private.dark-wake-push com.apple.private.accounts.allaccounts @@ -36,6 +38,8 @@ com.apple.private.cloudkit.supportservice + com.apple.private.cloudkit.spi + com.apple.private.appleaccount.app-hidden-from-icloud-settings com.apple.private.tcc.allow @@ -92,5 +96,7 @@ com.apple.symptom_diagnostics.report + com.apple.private.security.storage.Keychains + diff --git a/keychain/securityd/spi.c b/keychain/securityd/spi.c index 80b10d3f..2d4ca31e 100644 --- a/keychain/securityd/spi.c +++ b/keychain/securityd/spi.c @@ -21,7 +21,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#if TARGET_DARWINOS +#if defined(TARGET_DARWINOS) && TARGET_DARWINOS #undef OCTAGON #undef SECUREOBJECTSYNC #undef SHAREDWEBCREDENTIALS @@ -62,7 +62,7 @@ static struct securityd securityd_spi = { .sec_item_copy_parent_certificates = _SecItemCopyParentCertificates, .sec_item_certificate_exists = _SecItemCertificateExists, .sec_roll_keys = _SecServerRollKeysGlue, - .sec_item_update_token_items = _SecItemUpdateTokenItems, + .sec_item_update_token_items_for_access_groups = _SecItemUpdateTokenItemsForAccessGroups, .sec_delete_items_with_access_groups = _SecItemServerDeleteAllWithAccessGroups, #if SHAREDWEBCREDENTIALS .sec_add_shared_web_credential = _SecAddSharedWebCredential, @@ -72,6 +72,7 @@ static struct securityd securityd_spi = { .sec_keychain_backup_syncable = _SecServerBackupSyncable, .sec_keychain_restore_syncable = _SecServerRestoreSyncable, .sec_item_backup_copy_names = SecServerItemBackupCopyNames, + .sec_item_backup_ensure_copy_view = SecServerItemBackupEnsureCopyView, .sec_item_backup_handoff_fd = SecServerItemBackupHandoffFD, .sec_item_backup_set_confirmed_manifest = SecServerItemBackupSetConfirmedManifest, .sec_item_backup_restore = SecServerItemBackupRestore, @@ -80,30 +81,18 @@ static struct securityd securityd_spi = { .soscc_TryUserCredentials = SOSCCTryUserCredentials_Server, .soscc_SetUserCredentials = SOSCCSetUserCredentials_Server, .soscc_SetUserCredentialsAndDSID = SOSCCSetUserCredentialsAndDSID_Server, - .soscc_SetUserCredentialsAndDSIDWithAnalytics = SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server, .soscc_CanAuthenticate = SOSCCCanAuthenticate_Server, .soscc_PurgeUserCredentials = SOSCCPurgeUserCredentials_Server, .soscc_ThisDeviceIsInCircle = SOSCCThisDeviceIsInCircle_Server, .soscc_RequestToJoinCircle = SOSCCRequestToJoinCircle_Server, .soscc_RequestToJoinCircleAfterRestore = SOSCCRequestToJoinCircleAfterRestore_Server, - .soscc_RequestToJoinCircleAfterRestoreWithAnalytics = SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server, - .soscc_RequestEnsureFreshParameters = SOSCCRequestEnsureFreshParameters_Server, - .soscc_GetAllTheRings = SOSCCGetAllTheRings_Server, - .soscc_ApplyToARing = SOSCCApplyToARing_Server, - .soscc_WithdrawlFromARing = SOSCCWithdrawlFromARing_Server, - .soscc_EnableRing = SOSCCEnableRing_Server, - .soscc_RingStatus = SOSCCRingStatus_Server, .soscc_SetToNew = SOSCCAccountSetToNew_Server, .soscc_ResetToOffering = SOSCCResetToOffering_Server, .soscc_ResetToEmpty = SOSCCResetToEmpty_Server, - .soscc_ResetToEmptyWithAnalytics = SOSCCResetToEmptyWithAnalytics_Server, .soscc_View = SOSCCView_Server, .soscc_ViewSet = SOSCCViewSet_Server, - .soscc_ViewSetWithAnalytics = SOSCCViewSetWithAnalytics_Server, .soscc_RemoveThisDeviceFromCircle = SOSCCRemoveThisDeviceFromCircle_Server, - .soscc_RemoveThisDeviceFromCircleWithAnalytics = SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server, .soscc_RemovePeersFromCircle = SOSCCRemovePeersFromCircle_Server, - .soscc_RemovePeersFromCircleWithAnalytics = SOSCCRemovePeersFromCircleWithAnalytics_Server, .soscc_LoggedOutOfAccount = SOSCCLoggedOutOfAccount_Server, .soscc_BailFromCircle = SOSCCBailFromCircle_Server, .soscc_AcceptApplicants = SOSCCAcceptApplicants_Server, @@ -130,22 +119,10 @@ static struct securityd securityd_spi = { .soscc_SetNewPublicBackupKey = SOSCCSetNewPublicBackupKey_Server, .soscc_RegisterSingleRecoverySecret = SOSCCRegisterSingleRecoverySecret_Server, .soscc_WaitForInitialSync = SOSCCWaitForInitialSync_Server, - .soscc_WaitForInitialSyncWithAnalytics = SOSCCWaitForInitialSyncWithAnalytics_Server, - .soscc_CopyYetToSyncViewsList = SOSCCCopyYetToSyncViewsList_Server, - .soscc_SetEscrowRecords = SOSCCSetEscrowRecord_Server, - .soscc_CopyEscrowRecords = SOSCCCopyEscrowRecord_Server, - .sosbskb_WrapToBackupSliceKeyBagForView = SOSWrapToBackupSliceKeyBagForView_Server, - .soscc_CopyAccountState = SOSCCCopyAccountState_Server, - .soscc_DeleteAccountState = SOSCCDeleteAccountState_Server, - .soscc_CopyEngineData = SOSCCCopyEngineData_Server, - .soscc_DeleteEngineState = SOSCCDeleteEngineState_Server, .soscc_AccountHasPublicKey = SOSCCAccountHasPublicKey_Server, - .soscc_AccountIsNew = SOSCCAccountIsNew_Server, - .soscc_IsThisDeviceLastBackup = SOSCCkSecXPCOpIsThisDeviceLastBackup_Server, .soscc_SOSCCPeersHaveViewsEnabled = SOSCCPeersHaveViewsEnabled_Server, .soscc_RegisterRecoveryPublicKey = SOSCCRegisterRecoveryPublicKey_Server, .soscc_CopyRecoveryPublicKey = SOSCCCopyRecoveryPublicKey_Server, - .soscc_CopyBackupInformation = SOSCCCopyBackupInformation_Server, .soscc_SOSCCMessageFromPeerIsPending = SOSCCMessageFromPeerIsPending_Server, .soscc_SOSCCSendToPeerIsPending = SOSCCSendToPeerIsPending_Server, #endif /* SECUREOBJECTSYNC */ @@ -189,7 +166,7 @@ void securityd_init_server(void) { void securityd_init(CFURLRef home_path) { if (home_path) { - SetCustomHomeURL(home_path); + SecSetCustomHomeURL(home_path); } securityd_init_server(); diff --git a/keychain/tpctl/main.swift b/keychain/tpctl/main.swift index fd98b353..6f6e8833 100644 --- a/keychain/tpctl/main.swift +++ b/keychain/tpctl/main.swift @@ -1,7 +1,7 @@ import Foundation import os -let tplogDebug = OSLog(subsystem: "com.apple.security.trustedpeers", category: "debug") +let logger = Logger(subsystem: "com.apple.security.trustedpeers", category: "tpctl") // This should definitely use the ArgumentParser library from the Utility package. // However, right now that's not accessible from this code due to build system issues. @@ -24,7 +24,6 @@ var preapprovedKeys: [Data]? var deviceName: String? var serialNumber: String? var osVersion: String? -var policyVersion: NSNumber? var policySecrets: [String: Data]? enum Command { @@ -209,11 +208,11 @@ while let arg = argIterator.next() { osVersion = newOsVersion case "--policy-version": - guard let newPolicyVersion = UInt64(argIterator.next() ?? "") else { + guard let _ = UInt64(argIterator.next() ?? "") else { print("Error: --policy-version takes an integer argument") exitUsage(1) } - policyVersion = NSNumber(value: newPolicyVersion) + // Option ignored for now case "--policy-secret": guard let name = argIterator.next(), let dataBase64 = argIterator.next() else { @@ -224,7 +223,7 @@ while let arg = argIterator.next() { print("Error: --policy-secret data must be base-64") exitUsage(1) } - if nil == policySecrets { + if policySecrets == nil { policySecrets = [:] } policySecrets![name] = data @@ -271,7 +270,6 @@ while let arg = argIterator.next() { } voucher = voucherData voucherSig = voucherSigData - } else { guard let voucherBase64 = argIterator.next() else { print("Error: join needs a voucher") @@ -361,9 +359,7 @@ while let arg = argIterator.next() { permanentInfoSig = permanentInfoSigData stableInfo = stableInfoData stableInfoSig = stableInfoSigData - } else { - guard let peerIDString = argIterator.next() else { print("Error: vouch needs a peerID") print() @@ -451,7 +447,7 @@ while let arg = argIterator.next() { var machineIDs = Set() var performIDMS = false while let arg = argIterator.next() { - if(arg == "--idms") { + if arg == "--idms" { performIDMS = true } else { machineIDs.insert(arg) @@ -465,7 +461,7 @@ while let arg = argIterator.next() { } } -if commands.count == 0 { +if commands.isEmpty { exitUsage(0) } @@ -489,14 +485,16 @@ func cleanDictionaryForJSON(_ d: [AnyHashable: Any]) -> [AnyHashable: Any] { // Bring up a connection to TrustedPeersHelper let connection = NSXPCConnection(serviceName: "com.apple.TrustedPeersHelper") + connection.remoteObjectInterface = TrustedPeersHelperSetupProtocol(NSXPCInterface(with: TrustedPeersHelperProtocol.self)) connection.resume() + let tpHelper = connection.synchronousRemoteObjectProxyWithErrorHandler { error in print("Unable to connect to TPHelper:", error) } as! TrustedPeersHelperProtocol for command in commands { switch command { case .dump: - os_log("dumping (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("dumping (\(container), \(context))") tpHelper.dump(withContainer: container, context: context) { reply, error in guard error == nil else { print("Error dumping:", error!) @@ -515,7 +513,7 @@ for command in commands { } case .depart: - os_log("departing (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("departing (\(container), \(context))") tpHelper.departByDistrustingSelf(withContainer: container, context: context) { error in guard error == nil else { print("Error departing:", error!) @@ -526,7 +524,7 @@ for command in commands { } case .distrust(let peerIDs): - os_log("distrusting %@ for (%@, %@)", log: tplogDebug, type: .default, peerIDs, container, context) + logger.log("distrusting \(peerIDs.description) for (\(container), \(context))") tpHelper.distrustPeerIDs(withContainer: container, context: context, peerIDs: peerIDs) { error in guard error == nil else { print("Error distrusting:", error!) @@ -535,15 +533,15 @@ for command in commands { print("Distrust successful") } - case .join(let voucher, let voucherSig): - os_log("joining (%@, %@)", log: tplogDebug, type: .default, container, context) + case let .join(voucher, voucherSig): + logger.log("joining (\(container), \(context))") tpHelper.join(withContainer: container, context: context, voucherData: voucher, voucherSig: voucherSig, ckksKeys: [], tlkShares: [], - preapprovedKeys: preapprovedKeys ?? []) { peerID, _, error in + preapprovedKeys: preapprovedKeys ?? []) { peerID, _, _, error in guard error == nil else { print("Error joining:", error!) return @@ -552,12 +550,12 @@ for command in commands { } case .establish: - os_log("establishing (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("establishing (\(container), \(context))") tpHelper.establish(withContainer: container, context: context, ckksKeys: [], tlkShares: [], - preapprovedKeys: preapprovedKeys ?? []) { peerID, _, error in + preapprovedKeys: preapprovedKeys ?? []) { peerID, _, _, error in guard error == nil else { print("Error establishing:", error!) return @@ -566,7 +564,7 @@ for command in commands { } case .healthInquiry: - os_log("healthInquiry (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("healthInquiry (\(container), \(context))") tpHelper.pushHealthInquiry(withContainer: container, context: context) { error in guard error == nil else { print("Error healthInquiry: \(String(describing: error))") @@ -576,19 +574,19 @@ for command in commands { } case .localReset: - os_log("local-reset (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("local-reset (\(container), \(context))") tpHelper.localReset(withContainer: container, context: context) { error in guard error == nil else { print("Error resetting:", error!) return } - os_log("local-reset (%@, %@): successful", log: tplogDebug, type: .default, container, context) + logger.log("local-reset (\(container), \(context)): successful") print("Local reset successful") } case .supportApp: - os_log("supportApp (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("supportApp (\(container), \(context))") tpHelper.getSupportAppInfo(withContainer: container, context: context) { data, error in guard error == nil else { @@ -609,7 +607,7 @@ for command in commands { } case .prepare: - os_log("preparing (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("preparing (\(container), \(context))") if machineID == nil { let anisetteController = AKAnisetteProvisioningController() @@ -624,6 +622,12 @@ for command in commands { let deviceInfo = OTDeviceInformationActualAdapter() + serialNumber = serialNumber ?? deviceInfo.serialNumber() + guard let serialNumber = serialNumber else { + print("failed to get serial number") + abort() + } + tpHelper.prepare(withContainer: container, context: context, epoch: epoch, @@ -632,13 +636,13 @@ for command in commands { bottleID: UUID().uuidString, modelID: modelID ?? deviceInfo.modelID(), deviceName: deviceName ?? deviceInfo.deviceName(), - serialNumber: serialNumber ?? deviceInfo.serialNumber(), + serialNumber: serialNumber, osVersion: osVersion ?? deviceInfo.osVersion(), - policyVersion: policyVersion, + policyVersion: nil, policySecrets: policySecrets, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { - peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, syncingPolicy, error in guard error == nil else { print("Error preparing:", error!) return @@ -651,7 +655,8 @@ for command in commands { "stableInfo": stableInfo!.base64EncodedString(), "stableInfoSig": stableInfoSig!.base64EncodedString(), "machineID": machineID!, - ] + "views": Array(syncingPolicy?.viewList ?? Set()), + ] as [String: Any] do { print(try TPCTLObjectiveC.jsonSerialize(cleanDictionaryForJSON(result))) } catch { @@ -660,14 +665,15 @@ for command in commands { } case .update: - os_log("updating (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("updating (\(container), \(context))") tpHelper.update(withContainer: container, context: context, deviceName: deviceName, serialNumber: serialNumber, osVersion: osVersion, - policyVersion: policyVersion, - policySecrets: policySecrets) { _, error in + policyVersion: nil, + policySecrets: policySecrets, + syncUserControllableViews: nil) { _, _, error in guard error == nil else { print("Error updating:", error!) return @@ -677,7 +683,7 @@ for command in commands { } case .reset: - os_log("resetting (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("resetting (\(container), \(context))") tpHelper.reset(withContainer: container, context: context, resetReason: .userInitiatedReset) { error in guard error == nil else { print("Error during reset:", error!) @@ -688,7 +694,7 @@ for command in commands { } case .validate: - os_log("validate (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("validate (\(container), \(context))") tpHelper.validatePeers(withContainer: container, context: context) { reply, error in guard error == nil else { print("Error validating:", error!) @@ -707,7 +713,7 @@ for command in commands { } case .viableBottles: - os_log("viableBottles (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("viableBottles (\(container), \(context))") tpHelper.fetchViableBottles(withContainer: container, context: context) { sortedBottleIDs, partialBottleIDs, error in guard error == nil else { print("Error fetching viable bottles:", error!) @@ -723,8 +729,8 @@ for command in commands { } } - case .vouch(let peerID, let permanentInfo, let permanentInfoSig, let stableInfo, let stableInfoSig): - os_log("vouching (%@, %@)", log: tplogDebug, type: .default, container, context) + case let .vouch(peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig): + logger.log("vouching (\(container), \(context))") tpHelper.vouch(withContainer: container, context: context, peerID: peerID, @@ -747,14 +753,14 @@ for command in commands { } } - case .vouchWithBottle(let bottleID, let entropy, let salt): - os_log("vouching with bottle (%@, %@)", log: tplogDebug, type: .default, container, context) + case let .vouchWithBottle(bottleID, entropy, salt): + logger.log("vouching with bottle (\(container), \(context))") tpHelper.vouchWithBottle(withContainer: container, context: context, bottleID: bottleID, entropy: entropy, bottleSalt: salt, - tlkShares: []) { voucher, voucherSig, error in + tlkShares: []) { voucher, voucherSig, _, _, error in guard error == nil else { print("Error during vouchWithBottle", error!) return @@ -767,12 +773,13 @@ for command in commands { } } - case .allow(let machineIDs, let performIDMS): - os_log("allow-listing (%@, %@)", log: tplogDebug, type: .default, container, context) + case let .allow(machineIDs, performIDMS): + logger.log("allow-listing (\(container), \(context))") var idmsDeviceIDs: Set = Set() + var accountIsDemo: Bool = false - if(performIDMS) { + if performIDMS { let store = ACAccountStore() guard let account = store.aa_primaryAppleAccount() else { print("Unable to fetch primary Apple account!") @@ -783,6 +790,12 @@ for command in commands { requestArguments.altDSID = account.aa_altDSID requestArguments.services = [AKServiceNameiCloud] + let akManager = AKAccountManager.sharedInstance + let authKitAccount = akManager.authKitAccount(withAltDSID: account.aa_altDSID) + if let account = authKitAccount { + accountIsDemo = akManager.demoAccount(for: account) + } + guard let controller = AKAppleIDAuthenticationController() else { print("Unable to create AKAppleIDAuthenticationController!") abort() @@ -804,10 +817,9 @@ for command in commands { } semaphore.wait() } - let allMachineIDs = machineIDs.union(idmsDeviceIDs) print("Setting allowed machineIDs to \(allMachineIDs)") - tpHelper.setAllowedMachineIDsWithContainer(container, context: context, allowedMachineIDs: allMachineIDs) { listChanged, error in + tpHelper.setAllowedMachineIDsWithContainer(container, context: context, allowedMachineIDs: allMachineIDs, honorIDMSListChanges: accountIsDemo) { listChanged, error in guard error == nil else { print("Error during allow:", error!) return diff --git a/libDER/.gitignore b/libDER/.gitignore deleted file mode 100644 index 35cfb4d3..00000000 --- a/libDER/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.DS_Store -xcuserdata -project.xcworkspace diff --git a/libDER/CMakeLists.txt b/libDER/CMakeLists.txt deleted file mode 100644 index 83dbec22..00000000 --- a/libDER/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -project(libDER) - -add_security_library(DER - FAT - SOURCES - libDER/DER_CertCrl.c - libDER/DER_Decode.c - libDER/DER_Digest.c - libDER/DER_Encode.c - libDER/DER_Keys.c - libDER/oids.c -) diff --git a/libDER/README.txt b/libDER/README.txt deleted file mode 100644 index e3e6fb18..00000000 --- a/libDER/README.txt +++ /dev/null @@ -1,34 +0,0 @@ - libDER Library Notes - Last update to this file Jan. 26 2006 by dmitch - -This module is a very lightweight implementation of a DER encoder and -decoder. Unlike most other DER packages, this one does no malloc or -copies when it encodes or decodes; decoding an item yields a pointer -and a byte count which refer to memory inside of the "thing" being -decoded. Likewise, when encoding, the caller mustsupply a target buffer -to which the encoded item is written. - -Support for encoding sequences and for decoding sequences and sets of -known items is also included; when you decode a sequence, you get a -sequence of pointers and byte counts - again, no mallocs or copies occur. - -The directory libDER contains the DER decoding library proper. The main -API is in DER_Decode.h. Support for RSA keys, X509 certs, X509 CRLs, and -miscellaneous OIDs can also be found in libDER. - -Command line programs to parse and display the contents of X509 certificates -and CRLs, using libDER, can be found in the Tests directory. - -Revision History ----------------- - - Date svk tag Changes --------- ----------- ---------------------------------------- -01/26/06 libDER-5 Avoid varargs macros for portability. -01/03/06 libDER-4 Initial distribution in RSACertLib. -12/23/05 libDER-3 Fix DER_DECODE_ENABLE ifdef for DER_Decode.c. - Add MD2, MD5 OID and DigestInfo capabilities. -12/13/05 libDER-2 Added Apple Custom RSA public key formats. - Added PKCS1 RSA private keys. -11/28/05 libDER-1 Initial tag. - diff --git a/libDER/Tests/AppleMobilePersonalizedTicket.h b/libDER/Tests/AppleMobilePersonalizedTicket.h deleted file mode 100644 index 37b4033b..00000000 --- a/libDER/Tests/AppleMobilePersonalizedTicket.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2009,2012,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#ifndef APPLEMOBILEPERSONALIZEDTICKET_H -#define APPLEMOBILEPERSONALIZEDTICKET_H - -const unsigned kApECIDTag = 1; -const unsigned kApChipIDTag = 2; -const unsigned kApBoardIDTag = 3; -const unsigned kApProductionModeTag = 4; -const unsigned kApSecurityDomainTag = 5; -const unsigned kLLBBuildStringTag = 6; -const unsigned kiBootDigestTag = 7; -const unsigned kAppleLogoDigestTag = 8; -const unsigned kDeviceTreeDigestTag = 9; -const unsigned kKernelCacheDigestTag = 10; -const unsigned kDiagsDigestTag = 11; -const unsigned kBatteryChargingDigestTag = 12; -const unsigned kBatteryPluginDigestTag = 13; -const unsigned kBatteryLow0DigestTag = 14; -const unsigned kBatteryLow1DigestTag = 15; -const unsigned kRecoveryModeDigestTag = 16; -const unsigned kNeedServiceDigestTag = 17; -const unsigned kApNonceTag = 18; -const unsigned kApPriorTicketIDTag = 19; -const unsigned kiBSSBuildStringTag = 20; -const unsigned kHostiBootTag = 21; -const unsigned kiBECBuildStringTag = 22; -const unsigned kRestoreLogoDigestTag = 23; -const unsigned kRestoreDeviceTreeDigestTag = 24; -const unsigned kRestoreKernelCacheDigestTag = 25; -const unsigned kRestoreRamDiskDigestTag = 26; -const unsigned kOSDigestTag = 27; -const unsigned kApBindingDigestTag = 28; -const unsigned kApServerNonceTag = 29; -const unsigned kLLBPartialDigestTag = 30; -const unsigned kiBootPartialDigestTag = 31; -const unsigned kAppleLogoPartialDigestTag = 32; -const unsigned kDeviceTreePartialDigestTag = 33; -const unsigned kKernelCachePartialDigestTag = 34; -const unsigned kDiagsPartialDigestTag = 35; -const unsigned kBatteryChargingPartialDigestTag = 36; -const unsigned kBatteryPluginPartialDigestTag = 37; -const unsigned kBatteryLow0PartialDigestTag = 38; -const unsigned kBatteryLow1PartialDigestTag = 39; -const unsigned kRecoveryModePartialDigestTag = 40; -const unsigned kNeedServicePartialDigestTag = 41; -const unsigned kiBSSPartialDigestTag = 42; -const unsigned kiBECPartialDigestTag = 43; -const unsigned kRestoreLogoPartialDigestTag = 44; -const unsigned kRestoreDeviceTreePartialDigestTag = 45; -const unsigned kRestoreKernelCachePartialDigestTag = 46; -const unsigned kRestoreRamDiskPartialDigestTag = 47; -const unsigned kiBootTrustedTag = 48; -const unsigned kAppleLogoTrustedTag = 49; -const unsigned kDeviceTreeTrustedTag = 50; -const unsigned kKernelCacheTrustedTag = 51; -const unsigned kDiagsTrustedTag = 52; -const unsigned kBatteryChargingTrustedTag = 53; -const unsigned kBatteryPluginTrustedTag = 54; -const unsigned kBatteryLow0TrustedTag = 55; -const unsigned kBatteryLow1TrustedTag = 56; -const unsigned kRecoveryModeTrustedTag = 57; -const unsigned kNeedServiceTrustedTag = 58; -const unsigned kRestoreLogoTrustedTag = 59; -const unsigned kRestoreDeviceTreeTrustedTag = 60; -const unsigned kRestoreKernelCacheTrustedTag = 61; -const unsigned kRestoreRamDiskTrustedTag = 62; -const unsigned kBbSNUMTag = 63; -const unsigned kBbChipIDTag = 64; -const unsigned kBbProductionModeTag = 65; -const unsigned kFlashPSIBuildStringTag = 66; -const unsigned kModemStackDigestTag = 67; -const unsigned kBbNonceTag = 68; -const unsigned kBbPriorTicketIdTag = 69; -const unsigned kRamPSIBuildStringTag = 70; -const unsigned kHostFlashPSITag = 71; -const unsigned kEBLDigestTag = 72; -const unsigned kStaticEEPDigestTag = 73; -const unsigned kBbApBindingDigestTag = 74; -const unsigned kBbServerNonceTag = 75; -const unsigned kRamPSIPartialDigestTag = 76; -const unsigned kFlashPSIPartialDigestTag = 77; -const unsigned kBatteryCharging0DigestTag = 78; -const unsigned kBatteryCharging1DigestTag = 79; -const unsigned kBatteryFullDigestTag = 80; -const unsigned kBatteryCharging0PartialDigestTag = 81; -const unsigned kBatteryCharging1PartialDigestTag = 82; -const unsigned kBatteryFullPartialDigestTag = 83; -const unsigned kBatteryCharging0TrustedTag = 84; -const unsigned kBatteryCharging1TrustedTag = 85; -const unsigned kBatteryFullTrustedTag = 86; -const unsigned kUniqueBuildIDTag = 87; -const unsigned kBbGoldCertIdTag = 88; -const unsigned kBbSkeyIdTag = 89; -const unsigned kBasebandFirmwareFlashPSIVersionTag = 90; -const unsigned kBasebandFirmwareModemStackDigestTag = 91; -const unsigned kBasebandFirmwareRamPSIVersionTag = 92; -const unsigned kBasebandFirmwareEBLDigestTag = 93; -const unsigned kBasebandFirmwareFlashPSISecPackDigestTag = 94; -const unsigned kBasebandFirmwareModemStackSecPackDigestTag= 95; -const unsigned kBasebandFirmwareFlashPSIDigestTag = 96; -const unsigned kBasebandFirmwareRamPSIPartialDigestTag = 97; -const unsigned kBasebandFirmwareFlashPSIPartialDigestTag = 98; -const unsigned kBbJtagEnableTag = 99; - - -#endif /* APPLEMOBILEPERSONALIZEDTICKET_H */ diff --git a/libDER/Tests/DER_Ticket.c b/libDER/Tests/DER_Ticket.c deleted file mode 100644 index c5be4816..00000000 --- a/libDER/Tests/DER_Ticket.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2009,2012,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include "DER_Ticket.h" - -#include -#include -#include -#include - -/* Application Processor Ticket */ -const DERItemSpec DERApTicketItemSpecs[] = -{ - { DER_OFFSET(DERApTicket, signatureAlgorithm), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS | DER_ENC_WRITE_DER }, - { DER_OFFSET(DERApTicket, body), - ASN1_CONSTR_SET, - DER_DEC_NO_OPTS | DER_DEC_SAVE_DER | DER_ENC_WRITE_DER }, - { DER_OFFSET(DERApTicket, signature), - ASN1_OCTET_STRING, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERApTicket, certificates), - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1, - DER_DEC_NO_OPTS | DER_ENC_WRITE_DER } -}; -const DERSize DERNumApTicketItemSpecs = - sizeof(DERApTicketItemSpecs) / sizeof(DERItemSpec); - -/* Baseband Ticket */ -const DERItemSpec DERBbTicketItemSpecs[] = -{ - { DER_OFFSET(DERBbTicket, signatureAlgorithm), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS | DER_ENC_WRITE_DER }, - { DER_OFFSET(DERBbTicket, body), - ASN1_CONSTR_SET, - DER_DEC_NO_OPTS | DER_DEC_SAVE_DER | DER_ENC_WRITE_DER }, - { DER_OFFSET(DERBbTicket, signature), - ASN1_OCTET_STRING, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERBbTicket, gpuk), - ASN1_CONTEXT_SPECIFIC | 2, - DER_DEC_NO_OPTS } -}; -const DERSize DERNumBbTicketItemSpecs = - sizeof(DERBbTicketItemSpecs) / sizeof(DERItemSpec); - -#if 0 -/* We need to verify this value and use it here. */ -const DERByte rsaWithSha1Algorithm[] = { - 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05 -}; -#endif - -#ifdef FAST_SET_LOOKUP -/* Iterates over all the tags in the set to build an index returned in - derSet. */ -DERReturn DERDecodeSetContentInit( - const DERItem *content, /* data to decode */ - DERSet *derSet) /* IN/OUT, to use in DERDecodeSetTag */ -{ - DERReturn drtn; - DERSequence derSeq; - memset(derSet->byTag, 0, derSet->capacity); - drtn = DERDecodeSeqContentInit(content, &derSeq); - if (drtn == DR_Success) { - DERDecodedInfo element; - while ((drtn = DERDecodeSeqNext(&derSeq, &element)) == DR_Success) { - if (element.tag >= derSet->capacity) return DR_UnexpectedTag; - derSet->byTag[element.tag] = element.content.data; - } - if (drtn == DR_EndOfSequence) drtn = DR_Success; - } - derSet->end = content->data + content->length; - - return drtn; -} - -DERReturn DERDecodeSetTag( - DERSet *derSet, /* data to decode */ - DERTag tag, /* tag in sequence/set we are looking for. */ - DERItem *content) /* RETURNED */ -{ - DERReturn drtn; - DERTag tagNumber = tag & ASN1_TAGNUM_MASK; - if (tagNumber > derSet->capacity) - return DR_UnexpectedTag; - DERByte *start = derSet->byTag[tagNumber]; - if (!start) return DR_UnexpectedTag; - DERItem derItem = { .data = start, .length = derSet->end - start }; - DERDecodedInfo element; - drtn = DERDecodeItem(&derItem, &element); - if (drtn) return drtn; - if (tag != element.tag) return DR_UnexpectedTag; - *content = element.content; - - return drtn; -} -#endif /* FAST_SET_LOOKUP */ - -/* Returns the item with tag from the sequence or set pointed to by der. - result DR_EndOfSequence if the tag was not found. */ -DERReturn DERSetDecodeItemWithTag( - const DERItem *der, /* data to decode */ - DERTag tag, /* tag in sequence/set we are looking for. */ - DERItem *content) /* RETURNED */ -{ - DERReturn drtn; - DERSequence derSeq; - DERTag topTag; - drtn = DERDecodeSeqInit(der, &topTag, &derSeq); - if (drtn == DR_Success) { - DERDecodedInfo info; - while ((drtn = DERDecodeSeqNext(&derSeq, &info)) == DR_Success) { - if (info.tag == tag) { - *content = info.content; - return DR_Success; - } - } - } - - return drtn; -} - -DERReturn DERDecodeApTicket( - const DERItem *contents, - DERApTicket *ticket, /* RETURNED */ - DERSize *numUsedBytes) /* RETURNED */ -{ - DERReturn drtn; - DERDecodedInfo decodedTicket; - drtn = DERDecodeItem(contents, &decodedTicket); - if (drtn != DR_Success) goto badTicket; - drtn = DERParseSequenceContent(&decodedTicket.content, - DERNumApTicketItemSpecs, DERApTicketItemSpecs, ticket, 0); - if (drtn != DR_Success) goto badTicket; - - /* Decode the algorithm sequence. */ - DERAlgorithmId algorithm = {}; - drtn = DERParseSequenceContent(&ticket->signatureAlgorithm, - DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, &algorithm, 0); - if (drtn != DR_Success) goto badTicket; - /* TODO Check algorithm oid and ensure there are no params. - Alternatively replace the code above with a simple memcmp with - an already ASN.1 encoded algorithm parms block. */ - -badTicket: - *numUsedBytes = decodedTicket.content.length + - decodedTicket.content.data - contents->data; - - return drtn; -} - -DERReturn DERDecodeBbTicket( - const DERItem *contents, - DERBbTicket *ticket, /* RETURNED */ - DERSize *numUsedBytes) /* RETURNED */ -{ - DERReturn drtn; - DERDecodedInfo decodedTicket; - drtn = DERDecodeItem(contents, &decodedTicket); - if (drtn != DR_Success) goto badTicket; - drtn = DERParseSequenceContent(&decodedTicket.content, - DERNumBbTicketItemSpecs, DERBbTicketItemSpecs, ticket, 0); - if (drtn != DR_Success) goto badTicket; - - /* Decode the algorithm sequence. */ - DERAlgorithmId algorithm = {}; - drtn = DERParseSequenceContent(&ticket->signatureAlgorithm, - DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, &algorithm, 0); - if (drtn != DR_Success) goto badTicket; - /* TODO Check algorithm oid and ensure there are no params. - Alternatively replace the code above with a simple memcmp with - an already ASN.1 encoded algorithm parms block. */ - -badTicket: - *numUsedBytes = decodedTicket.content.length + - decodedTicket.content.data - contents->data; - - return drtn; -} diff --git a/libDER/Tests/DER_Ticket.h b/libDER/Tests/DER_Ticket.h deleted file mode 100644 index 080b98ff..00000000 --- a/libDER/Tests/DER_Ticket.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2009,2012,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include - - -#define FAST_SET_LOOKUP 1 - -#ifdef FAST_SET_LOOKUP -/* state representing a fast by tag set accessor, the caller needs to provide - a set large enough to hold all */ -typedef struct { - DERTag capacity; /* should be large enough to hold all encountered tags. - otherwise DR_UnexpectedTag will be returned, note - that only one tag per tag number can exist. */ - DERByte *end; - DERByte *byTag[]; /* maxTag element array of pointers to tag + length - of items in set indexed by tagNumber. */ -} DERSet; - -/* Iterates over all the tags in the set to build an index returned in - derSet. */ -DERReturn DERDecodeSetContentInit( - const DERItem *der, /* data to decode */ - DERSet *derSet); /* IN/OUT, to use in DERDecodeSetTag */ - -/* Returns DR_UnexpectedTag if the requested tag is not in derSet, returns - the content of the decoded item in content otherwise. */ -DERReturn DERDecodeSetTag( - DERSet *derSeq, /* data to decode */ - DERTag tag, /* tag in sequence/set we are looking for. */ - DERItem *content); /* RETURNED */ -#endif /* FAST_SET_LOOKUP */ - - -DERReturn DERSetDecodeItemWithTag( - const DERItem *der, /* data to decode */ - DERTag tag, /* tag in sequence/set we are looking for. */ - DERItem *content); /* RETURNED */ - - -/* Application Processor Ticket */ -typedef struct { - DERItem signatureAlgorithm; /* AlgorithmId */ - DERItem body; /* SET OF OCTECT STRING, DER_DEC_SAVE_DER */ - DERItem signature; /* OCTET STRING */ - DERItem certificates; /* SEQUENCE of CERTIFICATE */ -} DERApTicket; - -/* DERItemSpecs to decode into a DERApTicket */ -extern const DERItemSpec DERApTicketItemSpecs[]; -extern const DERSize DERNumApTicketItemSpecs; - -DERReturn DERDecodeApTicket( - const DERItem *contents, - DERApTicket *ticket, /* RETURNED */ - DERSize *numUsedBytes); /* RETURNED */ - - -/* Baseband Ticket */ -typedef struct { - DERItem signatureAlgorithm; /* AlgorithmId */ - DERItem body; /* SET OF OCTECT STRING, DER_DEC_SAVE_DER */ - DERItem signature; /* OCTET STRING */ - DERItem gpuk; /* OCTET STRING */ -} DERBbTicket; - -/* DERItemSpecs to decode into a DERBbTicket */ -extern const DERItemSpec DERBbTicketItemSpecs[]; -extern const DERSize DERNumBbTicketItemSpecs; - -DERReturn DERDecodeBbTicket( - const DERItem *contents, - DERBbTicket *ticket, /* RETURNED */ - DERSize *numUsedBytes); /* RETURNED */ diff --git a/libDER/Tests/certsCrls/EndCertificateCP.01.01.crt b/libDER/Tests/certsCrls/EndCertificateCP.01.01.crt deleted file mode 100644 index d7e64d6d..00000000 Binary files a/libDER/Tests/certsCrls/EndCertificateCP.01.01.crt and /dev/null differ diff --git a/libDER/Tests/certsCrls/Test_CRL_CA1.crl b/libDER/Tests/certsCrls/Test_CRL_CA1.crl deleted file mode 100644 index 66510d35..00000000 Binary files a/libDER/Tests/certsCrls/Test_CRL_CA1.crl and /dev/null differ diff --git a/libDER/Tests/certsCrls/Test_CRL_CA1.crl.pem b/libDER/Tests/certsCrls/Test_CRL_CA1.crl.pem deleted file mode 100644 index 6a4ed3f1..00000000 --- a/libDER/Tests/certsCrls/Test_CRL_CA1.crl.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN X509 CRL----- -MIIB3zCByDANBgkqhkiG9w0BAQQFADBvMQswCQYDVQQGEwJkZTEgMB4GA1UEChMX -SW5zZWN1cmVUZXN0Q2VydGlmaWNhdGUxFzAVBgNVBAMTDkZvciBUZXN0cyBPbmx5 -MSUwIwYJKoZIhvcNAQkBFhZpbnNlY3VyZUB0ZXN0Lmluc2VjdXJlFw0wMTA4MTcx -MTEyMDNaFw0wNjA4MTYxMTEyMDNaMCgwEgIBAxcNMDEwODE3MTExMDM5WjASAgEF -Fw0wMTA4MTcxMTExNTlaMA0GCSqGSIb3DQEBBAUAA4IBAQB47lMVCKlPoBAgLway -76eNRq1749jt/7g/Ouh06isNM66/CgzVL2xKSC3s2FX4xKg320niWI6Dvm4H3M6I -7RvuoCvZBVpu1MA8z2No89g2UPWlSxUAvuvo2GOGRgo+8nc/84g8biLUxTSF8Vs4 -T1Hngo1qrfePM4ou1uu7LhRnR8tuIVoQT6W3RSlEsQRBRM3y+VkOPAf0GBGyl6WG -WiymXHqsqis80WbX50tr859Cltqbu2yaFAX++IEBBDB7JoVi1blumgarqfXYkoUW -n9d3F8qySNjsfhOV613fXpmfXFZ33uTFsLSoihP8f6+Cusx2rfuGap7jOPv7j7sj -l2Y1 ------END X509 CRL----- diff --git a/libDER/Tests/certsCrls/TrustAnchorCP.01.01.crt b/libDER/Tests/certsCrls/TrustAnchorCP.01.01.crt deleted file mode 100644 index d7dfd9d4..00000000 Binary files a/libDER/Tests/certsCrls/TrustAnchorCP.01.01.crt and /dev/null differ diff --git a/libDER/Tests/certsCrls/TrustAnchorCRLCP.01.01.crl b/libDER/Tests/certsCrls/TrustAnchorCRLCP.01.01.crl deleted file mode 100644 index de65024a..00000000 Binary files a/libDER/Tests/certsCrls/TrustAnchorCRLCP.01.01.crl and /dev/null differ diff --git a/libDER/Tests/certsCrls/apple_v3.000.cer b/libDER/Tests/certsCrls/apple_v3.000.cer deleted file mode 100644 index f8705ff1..00000000 Binary files a/libDER/Tests/certsCrls/apple_v3.000.cer and /dev/null differ diff --git a/libDER/Tests/certsCrls/apple_v3.001.cer b/libDER/Tests/certsCrls/apple_v3.001.cer deleted file mode 100644 index 1c84d8b5..00000000 Binary files a/libDER/Tests/certsCrls/apple_v3.001.cer and /dev/null differ diff --git a/libDER/Tests/certsCrls/entrust_v3.100.cer b/libDER/Tests/certsCrls/entrust_v3.100.cer deleted file mode 100644 index 6956bf38..00000000 Binary files a/libDER/Tests/certsCrls/entrust_v3.100.cer and /dev/null differ diff --git a/libDER/Tests/certsCrls/entrust_v3.101.cer b/libDER/Tests/certsCrls/entrust_v3.101.cer deleted file mode 100644 index 4e45016b..00000000 Binary files a/libDER/Tests/certsCrls/entrust_v3.101.cer and /dev/null differ diff --git a/libDER/Tests/certsCrls/keybank_v3.100.cer b/libDER/Tests/certsCrls/keybank_v3.100.cer deleted file mode 100644 index 21f98293..00000000 Binary files a/libDER/Tests/certsCrls/keybank_v3.100.cer and /dev/null differ diff --git a/libDER/Tests/certsCrls/keybank_v3.101.cer b/libDER/Tests/certsCrls/keybank_v3.101.cer deleted file mode 100644 index 1c84d8b5..00000000 Binary files a/libDER/Tests/certsCrls/keybank_v3.101.cer and /dev/null differ diff --git a/libDER/Tests/certsCrls/keybank_v3.102.cer b/libDER/Tests/certsCrls/keybank_v3.102.cer deleted file mode 100644 index c61d2958..00000000 Binary files a/libDER/Tests/certsCrls/keybank_v3.102.cer and /dev/null differ diff --git a/libDER/Tests/parseCert.c b/libDER/Tests/parseCert.c deleted file mode 100644 index 2ad3a914..00000000 --- a/libDER/Tests/parseCert.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2005-2007,2010-2011 Apple Inc. All Rights Reserved. - * - * parseCert.c - parse a DER-encoded X509 certificate using libDER. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void usage(char **argv) -{ - printf("usage: %s certFile [options]\n", argv[0]); - printf("Options:\n"); - printf(" -v -- verbose \n"); - /* etc. */ - exit(1); -} - -static void printValidity( - DERItem *validity, - int verbose) -{ - DERReturn drtn; - DERValidity derv; - - drtn = DERParseSequenceContent(validity, - DERNumValidityItemSpecs, DERValidityItemSpecs, - &derv, sizeof(derv)); - if(drtn) { - DERPerror("DERParseSequenceContent(validity)", drtn); - return; - } - decodePrintItem("notBefore", IT_Leaf, verbose, &derv.notBefore); - decodePrintItem("notAfter", IT_Leaf, verbose, &derv.notAfter); - -} - -int main(int argc, char **argv) -{ - unsigned char *certData = NULL; - unsigned certDataLen = 0; - DERSignedCertCrl signedCert; - DERTBSCert tbs; - DERReturn drtn; - DERItem item; - int verbose = 0; - extern char *optarg; - int arg; - extern int optind; - - if(argc < 2) { - usage(argv); - } - if(readFile(argv[1], &certData, &certDataLen)) { - printf("***Error reading cert from %s. Aborting.\n", argv[1]); - exit(1); - } - - optind = 2; - while ((arg = getopt(argc, argv, "vh")) != -1) { - switch (arg) { - case 'v': - verbose = 1; - break; - case 'h': - usage(argv); - } - } - if(optind != argc) { - usage(argv); - } - - /* Top level decode of signed cert into 3 components */ - item.data = certData; - item.length = certDataLen; - drtn = DERParseSequence(&item, DERNumSignedCertCrlItemSpecs, DERSignedCertCrlItemSpecs, - &signedCert, sizeof(signedCert)); - if(drtn) { - DERPerror("DERParseSequence(SignedCert)", drtn); - exit(1); - } - printItem("TBSCert", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &signedCert.tbs); - - incrIndent(); - - /* decode the TBSCert - it was saved in full DER form */ - drtn = DERParseSequence(&signedCert.tbs, - DERNumTBSCertItemSpecs, DERTBSCertItemSpecs, - &tbs, sizeof(tbs)); - if(drtn) { - DERPerror("DERParseSequenceContent(TBSCert)", drtn); - exit(1); - } - if(tbs.version.data) { - /* unwrap the explicitly tagged integer.... */ - decodePrintItem("version", IT_Leaf, verbose, &tbs.version); - } - printItem("serialNum", IT_Leaf, verbose, ASN1_INTEGER, &tbs.serialNum); - - printItem("tbsSigAlg", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &tbs.tbsSigAlg); - incrIndent(); - printAlgId(&tbs.tbsSigAlg, verbose); - decrIndent(); - - printItem("issuer", IT_Leaf, verbose, ASN1_CONSTR_SEQUENCE, &tbs.issuer); - printItem("subject", IT_Leaf, verbose, ASN1_CONSTR_SEQUENCE, &tbs.subject); - - printItem("validity", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &tbs.validity); - incrIndent(); - printValidity(&tbs.validity, verbose); - decrIndent(); - - printItem("subjectPubKey", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, - &tbs.subjectPubKey); - incrIndent(); - printSubjPubKeyInfo(&tbs.subjectPubKey, verbose); - decrIndent(); - - if(tbs.issuerID.data) { - /* found tag is implicit context specific: tell printItem what it really is */ - printItem("issuerID", IT_Leaf, verbose, ASN1_BIT_STRING, &tbs.issuerID); - } - if(tbs.subjectID.data) { - printItem("subjectID", IT_Leaf, verbose, ASN1_BIT_STRING, &tbs.subjectID); - } - if(tbs.extensions.data) { - printItem("extensions", IT_Leaf, verbose, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 3, - &tbs.extensions); - } - decrIndent(); - - printItem("sigAlg", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &signedCert.sigAlg); - incrIndent(); - printAlgId(&signedCert.sigAlg, verbose); - decrIndent(); - - printItem("sig", IT_Leaf, verbose, ASN1_BIT_STRING, &signedCert.sig); - - return 0; -} diff --git a/libDER/Tests/parseCrl.c b/libDER/Tests/parseCrl.c deleted file mode 100644 index 4eabc130..00000000 --- a/libDER/Tests/parseCrl.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2005-2007,2010-2011 Apple Inc. All Rights Reserved. - * - * parseCrl.c - parse a DER-encoded X509 CRL using libDER. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void usage(char **argv) -{ - printf("usage: %s crlFile [options]\n", argv[0]); - printf("Options:\n"); - printf(" -v -- verbose \n"); - /* etc. */ - exit(1); -} - -/* - * This is a SEQUENCE OF so we use the low-level DERDecodeSeq* routines to snag one entry - * at a time. - */ -static void printRevokedCerts( - DERItem *revokedCerts, - int verbose) -{ - DERReturn drtn; - DERDecodedInfo currItem; - DERSequence seq; - unsigned certNum; - DERRevokedCert revoked; - - drtn = DERDecodeSeqContentInit(revokedCerts, &seq); - if(drtn) { - DERPerror("DERDecodeSeqContentInit(revokedCerts)", drtn); - return; - } - - for(certNum=0; ; certNum++) { - drtn = DERDecodeSeqNext(&seq, &currItem); - switch(drtn) { - case DR_EndOfSequence: - /* normal termination */ - return; - default: - DERPerror("DERDecodeSeqNext", drtn); - return; - case DR_Success: - doIndent(); - printf("revoked cert %u\n", certNum); - incrIndent(); - drtn = DERParseSequenceContent(&currItem.content, - DERNumRevokedCertItemSpecs, DERRevokedCertItemSpecs, - &revoked, sizeof(revoked)); - if(drtn) { - DERPerror("DERParseSequenceContent(RevokedCert)", drtn); - decrIndent(); - return; - } - printItem("serialNum", IT_Leaf, verbose, ASN1_INTEGER, &revoked.serialNum); - decodePrintItem("revocationDate", IT_Leaf, verbose, &revoked.revocationDate); - printItem("extensions", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &revoked.extensions); - decrIndent(); - } - } -} - -int main(int argc, char **argv) -{ - unsigned char *crlData = NULL; - unsigned crlDataLen = 0; - DERSignedCertCrl signedCrl; - DERTBSCrl tbs; - DERReturn drtn; - DERItem item; - int verbose = 0; - extern char *optarg; - int arg; - extern int optind; - - if(argc < 2) { - usage(argv); - } - if(readFile(argv[1], &crlData, &crlDataLen)) { - printf("***Error reading CRL from %s. Aborting.\n", argv[1]); - exit(1); - } - - optind = 2; - while ((arg = getopt(argc, argv, "vh")) != -1) { - switch (arg) { - case 'v': - verbose = 1; - break; - case 'h': - usage(argv); - } - } - if(optind != argc) { - usage(argv); - } - - /* Top level decode of signed CRL into 3 components */ - item.data = crlData; - item.length = crlDataLen; - drtn = DERParseSequence(&item, DERNumSignedCertCrlItemSpecs, DERSignedCertCrlItemSpecs, - &signedCrl, sizeof(signedCrl)); - if(drtn) { - DERPerror("DERParseSequence(SignedCrl)", drtn); - exit(1); - } - printItem("TBSCrl", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &signedCrl.tbs); - - incrIndent(); - - /* decode the TBSCrl - it was saved in full DER form */ - drtn = DERParseSequence(&signedCrl.tbs, - DERNumTBSCrlItemSpecs, DERTBSCrlItemSpecs, - &tbs, sizeof(tbs)); - if(drtn) { - DERPerror("DERParseSequenceContent(TBSCrl)", drtn); - exit(1); - } - if(tbs.version.data) { - printItem("version", IT_Leaf, verbose, ASN1_INTEGER, &tbs.version); - } - - printItem("tbsSigAlg", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &tbs.tbsSigAlg); - incrIndent(); - printAlgId(&tbs.tbsSigAlg, verbose); - decrIndent(); - - printItem("issuer", IT_Leaf, verbose, ASN1_CONSTR_SEQUENCE, &tbs.issuer); - - decodePrintItem("thisUpdate", IT_Leaf, verbose, &tbs.thisUpdate); - decodePrintItem("nextUpdate", IT_Leaf, verbose, &tbs.nextUpdate); - - if(tbs.revokedCerts.data) { - printItem("version", IT_Leaf, verbose, ASN1_CONSTR_SEQUENCE, &tbs.revokedCerts); - incrIndent(); - printRevokedCerts(&tbs.revokedCerts, verbose); - decrIndent(); - } - - if(tbs.extensions.data) { - printItem("extensions", IT_Leaf, verbose, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 3, - &tbs.extensions); - } - - printItem("sigAlg", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &signedCrl.sigAlg); - incrIndent(); - printAlgId(&signedCrl.sigAlg, verbose); - decrIndent(); - - printItem("sig", IT_Leaf, verbose, ASN1_BIT_STRING, &signedCrl.sig); - - return 0; -} diff --git a/libDER/Tests/parseTicket.c b/libDER/Tests/parseTicket.c deleted file mode 100644 index 1d707341..00000000 --- a/libDER/Tests/parseTicket.c +++ /dev/null @@ -1,563 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "AppleMobilePersonalizedTicket.h" -#include -#include -#include -#include -#include -#include -#include "DER_Ticket.h" - -const unsigned char GoldKeyCert[] = { -0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, -0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, -0x03, 0x00, 0x00, 0x00, 0x31, 0x6e, 0xc6, 0x4f, -0xf1, 0xe8, 0x7d, 0x81, 0x38, 0x6d, 0xd8, 0xb3, -0x2b, 0xe4, 0xb5, 0xa0, 0x09, 0xaf, 0x74, 0xdd, -0xe9, 0x60, 0x27, 0x42, 0x07, 0xa3, 0xac, 0xef, -0xe5, 0x75, 0x07, 0xa8, 0xc2, 0x2c, 0x25, 0x56, -0x91, 0x37, 0xea, 0xdb, 0xdb, 0x68, 0x4a, 0x1c, -0xe3, 0x29, 0x61, 0x85, 0xd7, 0xd8, 0x66, 0x86, -0x66, 0xbf, 0xbf, 0x98, 0xae, 0xb4, 0xe9, 0x6c, -0x13, 0x81, 0x97, 0x78, 0x2a, 0x8d, 0xdc, 0x37, -0x9a, 0xf1, 0xa4, 0x0a, 0x9d, 0x74, 0xd5, 0x72, -0xbc, 0xb5, 0x64, 0xa6, 0x1a, 0x62, 0xd5, 0x39, -0xfb, 0x6f, 0xc0, 0xd1, 0xc7, 0x93, 0xc3, 0x20, -0xda, 0x84, 0x69, 0x1e, 0xd9, 0x96, 0x2e, 0xc1, -0x4f, 0x28, 0x96, 0x14, 0xa4, 0x68, 0x0a, 0x40, -0xe5, 0x17, 0xe7, 0xd6, 0x76, 0x4d, 0x81, 0xd8, -0xd2, 0xa6, 0x18, 0x82, 0x36, 0x40, 0x97, 0x31, -0xd9, 0x88, 0xdf, 0xaf, 0x05, 0x3a, 0x4b, 0x4e, -0x1b, 0x4a, 0x76, 0x6f, 0xb9, 0x6c, 0x18, 0x5d, -0xd5, 0x98, 0xf0, 0xf1, 0xbe, 0x0a, 0xd9, 0x57, -0x85, 0xc6, 0xc9, 0x63, 0xb3, 0xf5, 0x21, 0x26, -0x07, 0xba, 0x6a, 0x05, 0xfb, 0x5a, 0x06, 0x87, -0x2a, 0x30, 0x3f, 0xa9, 0xea, 0xab, 0x0e, 0x50, -0x70, 0x3b, 0x7e, 0xd4, 0xd2, 0x8c, 0xf3, 0xa1, -0xcf, 0x9a, 0x6c, 0x6b, 0xcf, 0x9b, 0x1b, 0x2a, -0x97, 0x6a, 0x3c, 0x38, 0x40, 0x43, 0xb1, 0x97, -0x19, 0x07, 0x64, 0x11, 0x94, 0x73, 0x14, 0xc9, -0xa3, 0xfe, 0x7f, 0xf6, 0x64, 0x23, 0x73, 0xe3, -0x76, 0xce, 0xf7, 0xf4, 0x2f, 0x6c, 0x9d, 0x0a, -0xf6, 0x39, 0xe6, 0x1d, 0xb2, 0x17, 0x29, 0x39, -0x98, 0x52, 0xda, 0xe0, 0x31, 0xa1, 0xfa, 0x85, -0x52, 0xc2, 0x60, 0xb5, 0x11, 0x42, 0xc6, 0x9b, -0x55, 0xd8, 0x40, 0x37, 0xf7, 0xdb, 0x01, 0x6a, -0xd5, 0x26, 0x3b, 0x27, 0x07, 0x20, 0xf7, 0x58, -0xd5, 0xa4, 0x1c, 0xe6, 0x2f, 0x74, 0x14, 0x6e, -0xa4, 0xe8, 0xc8, 0xe8, 0x9a, 0x39, 0x6d, 0xde, -0x7f, 0x67, 0x65, 0x40, 0x68, 0x26, 0x65, 0x62, -0x95, 0x87, 0x45, 0x62, 0x0d, 0x8d, 0x42, 0xad, -0x3b, 0x4f, 0xd3, 0x8f, 0x58, 0xcb, 0x61, 0x46, -0xc9, 0x3d, 0x7d, 0x75, 0x3c, 0x6d, 0xac, 0xdf, -0x53, 0xf4, 0x66, 0x9e, 0x14, 0x82, 0xc7, 0xd1, -0xd0, 0xec, 0x92, 0x24, 0x97, 0x1e, 0xc9, 0x7a, -0xfd, 0x8f, 0x75, 0xe2, 0xfd, 0x7e, 0x07, 0x44, -0x46, 0x56, 0x64, 0x9b, 0x1b, 0x17, 0xfa, 0xd6, -0xf5, 0xdb, 0xc9, 0x27, 0x3b, 0x60, 0x27, 0x2f, -0x84, 0xd7, 0xac, 0x7f, 0xf3, 0xa7, 0x16, 0x31, -0xfa, 0x19, 0x54, 0x57, 0x98, 0xb5, 0xdb, 0x9c, -0xc3, 0xb5, 0x55, 0x72, 0x98, 0x2f, 0x56, 0x33, -0x7c, 0x38, 0x1f, 0xb4, 0x8c, 0x94, 0x1a, 0x6a, -0x26, 0x8a, 0x84, 0xfc, 0x8d, 0xb1, 0x49, 0xbb, -0x6d, 0x11, 0x36, 0xc9, 0x05, 0x57, 0x87, 0xd2, -0xdb, 0xd3, 0xe3, 0xea, 0x08, 0xb2, 0x9f, 0x44, -0x85, 0xd7, 0xd4, 0x96, 0x25, 0xeb, 0x2b, 0xca, -0x86, 0x0f, 0x33, 0x69, 0xc4, 0xda, 0x98, 0x68, -0x21, 0xad, 0xd8, 0xc4, 0x4e, 0x46, 0x33, 0x43, -0xad, 0xe7, 0xfe, 0x58, 0x10, 0x00, 0x76, 0x3c, -0xd4, 0x14, 0x5a, 0x74, 0x43, 0x04, 0xc3, 0xdd, -0x46, 0xc3, 0xe0, 0x4b, 0x46, 0xb5, 0x84, 0xcb, -0xe6, 0x40, 0x71, 0xdf, 0x50, 0x16, 0x5f, 0xf0, -0x0f, 0xc5, 0x9c, 0x50, 0x64, 0xe0, 0x64, 0x1c, -0x58, 0x87, 0xae, 0x91, 0x9c, 0xb6, 0x57, 0x77, -0xf0, 0xc4, 0x3e, 0xcf, 0xb6, 0xc5, 0x10, 0x0c, -0xea, 0x5b, 0xcc, 0xaf, 0xee, 0x7b, 0x15, 0x4e, -0x4e, 0x3c, 0x29, 0x9c, 0xf8, 0xe6, 0x59, 0xca, -0xaf, 0x48, 0x12, 0x99, 0x76, 0xde, 0x54, 0xe2, -0x75, 0x62, 0x31, 0x17, -}; - -#define SIG_LEN 128 -#define HASH_LEN 20 - -const unsigned char fakeAlgOID[] = { -0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05 -}; - -const unsigned char fakeG3Cert[] = { -0x01,0x00,0x00,0x00, -0x1c,0x00,0x00,0x00, -0x01,0x08,0x00,0x00, -0x10,0x0a,0x00,0x00, -0x00,0x00,0x00,0x00, -0x00,0x04,0x00,0x00, -0x01,0x00,0x01,0x00, -0x19,0xfc,0xb6,0x7b,0x4e,0xa8,0xd7,0xb1,0xeb,0xf9,0x19,0x28,0x07,0x7f,0x47,0x4c, -0xe1,0x9f,0xbe,0x01,0x15,0x5c,0xea,0xda,0xc3,0xd1,0x59,0x3c,0x75,0xed,0x00,0x7b, -0x22,0x67,0x22,0xd6,0xd3,0xee,0xc2,0x04,0xdf,0x47,0xc4,0x85,0xc0,0x56,0xa4,0x8d, -0xf3,0xf0,0xcf,0x00,0x9d,0xd2,0x03,0xc1,0x23,0x3f,0xc8,0x9f,0xef,0xfe,0xea,0x50, -0x33,0x6b,0xbe,0x74,0x1a,0xa3,0x3c,0x13,0xa2,0xc5,0xf6,0x75,0x88,0x1d,0x3f,0xba, -0xff,0x0d,0x47,0xab,0xbe,0xfe,0x42,0xd3,0xea,0xe2,0xe2,0xb0,0x06,0xd7,0x88,0xf8, -0x1d,0x93,0xdf,0x86,0xbd,0xd8,0xa8,0x5f,0x2b,0xe3,0x97,0x41,0xa1,0xc6,0x1d,0x69, -0xe9,0x88,0xdf,0x87,0xbb,0x1b,0xff,0x31,0x82,0xae,0x8a,0x69,0x31,0xca,0xc3,0x90, -0x0f,0x0d,0x22,0xa3,0xcf,0x8d,0xcc,0x23,0x03,0x10,0xed,0x74,0x8e,0x13,0x74,0x49, -0x9d,0x9a,0x1c,0xf2,0x57,0x2d,0x18,0x89,0x6d,0xb8,0xcc,0xab,0xcf,0xd9,0xd8,0x0e, -0x46,0x68,0x98,0xa3,0x81,0x5d,0x18,0xe8,0x4d,0x03,0x96,0x14,0xc5,0xaf,0x21,0x91, -0xb7,0x8c,0x97,0xa1,0x85,0xde,0x85,0x78,0xa8,0xd7,0x25,0x20,0x9b,0x2b,0x98,0x36, -0xd5,0xfe,0x14,0x9b,0x5d,0xe3,0x78,0xf4,0xd6,0xb2,0x15,0xc9,0xfd,0x13,0x77,0x7b, -0x8a,0x5e,0x9e,0x85,0xff,0x53,0x6d,0x24,0x5d,0xc9,0x52,0x16,0x98,0x18,0xb1,0xaf, -0xe1,0x6a,0xd6,0xe8,0xa9,0x7c,0x78,0x8e,0x9f,0x79,0x21,0xa1,0xde,0xf4,0xaf,0x9c, -0xd4,0x61,0x52,0xf9,0xe7,0xfc,0xd7,0x10,0x1b,0x91,0x66,0x14,0x26,0xfd,0xda,0xee, -0xe5,0xd9,0x4c,0xb7,0x9d,0x6d,0x17,0xf8,0xc2,0x21,0xb4,0x34,0x08,0x0c,0x44,0x79, -0x53,0x9c,0x81,0xbf,0x1f,0x22,0x0a,0xa6,0xe7,0x22,0x5f,0x5c,0xcb,0x31,0x2e,0xf5, -0x0c,0x1a,0xf1,0x67,0x13,0x7f,0xe6,0xb3,0xb2,0xfe,0x6b,0x09,0xac,0xa6,0xd4,0x14, -0xe7,0xe9,0x11,0x0e,0x49,0x99,0x06,0x04,0xa4,0x43,0x22,0xec,0x9f,0x59,0x83,0xfb, -0xef,0xa3,0x8f,0x6b,0xde,0x70,0x0c,0xbb,0x89,0xe9,0x88,0xbc,0xeb,0x36,0x42,0x42, -0x50,0x84,0xf5,0x93,0x98,0x93,0xed,0xa2,0x1f,0x13,0x60,0x36,0xc8,0x2f,0x9f,0xd1, -0xc4,0x23,0xf6,0xd0,0x49,0x40,0xab,0xbe,0xf7,0x43,0x02,0x96,0xf0,0x74,0xa5,0x7d, -0x68,0x89,0xfa,0x58, 0xad, 0x7b, 0x2f, 0x7d, 0xe8, 0x21, 0x34, 0x5e, 0x6c, 0x20, -0x97, 0x9e -}; - -const unsigned char fakeSig[] = { -0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, -0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, -0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, -0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, -0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, -0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, -0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, -0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10 -}; - -static void -dumpBytes( const char *title, const unsigned char *data, int len, int nonewline ); - -static int -rsa_sign( - const char *keyFile, - unsigned char *plain, - unsigned plainLength, - unsigned char signature[SIG_LEN] ) -{ - int rc = -1; - FILE *fp = NULL; - RSA *rsa = NULL; - unsigned signatureLength = 0; - - fp = fopen ( (char*) keyFile, "r" ); - if ( !fp ) { - fprintf( stderr, "failed to open file=%s\n", keyFile ); - goto cleanup; - } - rsa = RSA_new(); - if ( !rsa ) { - fprintf( stderr, "RSA_new() failed\n" ); - goto cleanup; - } - rsa = (RSA*)PEM_read_RSAPrivateKey( fp, &rsa, NULL, NULL ); - if ( !rsa ) { - fprintf( stderr, "PEM_read_RSAPrivateKey() failed\n" ); - goto cleanup; - } - signatureLength = SIG_LEN; - char sha1[20] = {}; - (void) SHA1( plain, plainLength, (unsigned char*)sha1 ); - rc = RSA_sign( NID_sha1, (unsigned char*)sha1, sizeof( sha1), - signature, &signatureLength, rsa ); - if ( rc != 1 ) { - fprintf(stderr, "RSA_sign failed=%d\n", rc ); - rc = -1; - goto cleanup; - } else { - rc = 0; - } - -cleanup: - if ( fp ) fclose( fp ); - RSA_free( rsa ); - return rc; -} - -static int -rsa_verify( - const char *keyFile, - unsigned char *plain, - unsigned plainLength, - unsigned char signature[SIG_LEN] ) -{ - int rc = -1; - FILE *fp = NULL; - RSA *rsa = NULL; - unsigned signatureLength = 0; - - fp = fopen ( (char*) keyFile, "r" ); - if ( !fp ) { - fprintf( stderr, "failed to open file=%s\n", keyFile ); - goto cleanup; - } - rsa = RSA_new(); - if ( !rsa ) { - fprintf( stderr, "RSA_new() failed\n" ); - goto cleanup; - } - rsa = (RSA*)PEM_read_RSAPrivateKey( fp, &rsa, NULL, NULL ); - if ( !rsa ) { - fprintf( stderr, "PEM_read_RSAPrivateKey() failed\n" ); - goto cleanup; - } - signatureLength = SIG_LEN; - char sha1[20] = {}; - (void) SHA1( plain, plainLength, (unsigned char*)sha1 ); - rc = RSA_verify( NID_sha1, (unsigned char*)sha1, sizeof( sha1 ), - signature, signatureLength, rsa ); - if ( rc != 1 ) { - fprintf(stderr, "RSA_verify failed=%d\n", rc ); - rc = -1; - goto cleanup; - } else { - rc = 0; - } - -cleanup: - if ( fp ) fclose( fp ); - RSA_free( rsa ); - return rc; - return rc; -} - -static void -dumpBytes( const char *title, const unsigned char *data, int len, int nonewline ) -{ - int width = 16; - int line = 0; - int multiple = 0; - - multiple = ( len % width == 0 ); - - printf( "[%s: %d bytes]\n", title, len ); - while ( len-- > 0 ) { - line++; - printf( "%02X ", *data++ ); - if ( line % width == 0 && len > 0 && !nonewline ) { - printf( "\n" ); - } - } - - printf("\n"); -} - -static void -writeFile( char* filename, unsigned char* buf, int len ) -{ - FILE *file = NULL; - file = fopen( filename, "w" ); - if ( file ) { - fwrite( buf, len, 1, file ); - fclose( file ); - } -} - - -static void -verify_bb_ticket( - unsigned char *ticketData, - unsigned ticketLength, - const char *keyFile, - bool doPrint ) -{ - if ( doPrint ) { - dumpBytes( "Ticket (whole)", ticketData, ticketLength, 0 ); - printf( "\nBreakdown:\n" ); - } - - DERItem derTicket = { .data = ticketData, .length = ticketLength }; - DERReturn drtn; - DERBbTicket ticket = {}; - DERSize ticketSize; - drtn = DERDecodeBbTicket(&derTicket, &ticket, &ticketSize); - if (drtn != DR_Success) goto badTicket; - fprintf( stderr, "ticketSize=%u\n", ticketSize ); - - // Verify signature if key file exists (we should really use the certificate or GPUK in the ticket here. */ - if ( keyFile ) { - int status = rsa_verify( - keyFile, - (unsigned char *)ticket.body.data, - ticket.body.length, - (unsigned char *)ticket.signature.data ); - if ( status ) { - fprintf( stderr, "rsa_verify failed=%d\n", status ); - } else { - fprintf( stdout, "Signature verified successfully\n"); - } - } - - /* Example of how to retrive fields from ticket. */ - DERItem snum; - drtn = DERSetDecodeItemWithTag(&ticket.body, - ASN1_CONTEXT_SPECIFIC | kBbSNUMTag, &snum); - if (drtn != DR_Success) goto badTicket; - DERItem chipId; - drtn = DERSetDecodeItemWithTag(&ticket.body, - ASN1_CONTEXT_SPECIFIC | kBbChipIDTag, &chipId); - if (drtn != DR_Success) goto badTicket; - - return; -badTicket: - fprintf( stdout, "Bad ticket\n"); - return; -} - -static void -verify_ticket_file( - const char *ticketFile, - const char *keyFile ) -{ - unsigned char *ticket = NULL; - unsigned ticketLength = 0; - readFile( (char*)ticketFile, &ticket, &ticketLength ); - verify_bb_ticket( ticket, ticketLength, keyFile, false ); -} - -static void -make_sample_ap_ticket( void ) -{ - unsigned char chipId[] = { 0x01, 0x02, 0x03, 0x04 }; - unsigned char ecid[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; - - DERApTicket ticket = { }; - - /* Encode the signatureAlgorithm field of the ticket. */ - DERAlgorithmId algorithmId = { .oid = oidSha1Rsa, .params = {} }; - ticket.signatureAlgorithm.length = DERLengthOfEncodedSequence( - ASN1_CONSTR_SEQUENCE, &algorithmId, DERNumAlgorithmIdItemSpecs, - DERAlgorithmIdItemSpecs); - ticket.signatureAlgorithm.data = malloc(ticket.signatureAlgorithm.length); - DEREncodeSequence(ASN1_CONSTR_SEQUENCE, &algorithmId, DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, ticket.signatureAlgorithm.data, &ticket.signatureAlgorithm.length); - - /* Construct ticket body. */ - DERSize numBodyItemSpecs = 0; - DERItemSpec bodyItemSpecs[50] = {}; - DERItem bodyItems[50] = {}; - - /* Add tags in sorted order. */ - bodyItemSpecs[numBodyItemSpecs].offset = numBodyItemSpecs * sizeof(DERItem); - bodyItemSpecs[numBodyItemSpecs].tag = ASN1_CONTEXT_SPECIFIC | kApECIDTag; - bodyItemSpecs[numBodyItemSpecs].options = DER_ENC_NO_OPTS; - bodyItems[numBodyItemSpecs].data = ecid; - bodyItems[numBodyItemSpecs].length = sizeof(ecid); - numBodyItemSpecs++; - - bodyItemSpecs[numBodyItemSpecs].offset = numBodyItemSpecs * sizeof(DERItem); - bodyItemSpecs[numBodyItemSpecs].tag = ASN1_CONTEXT_SPECIFIC | kApChipIDTag; - bodyItemSpecs[numBodyItemSpecs].options = DER_ENC_NO_OPTS; - bodyItems[numBodyItemSpecs].data = chipId; - bodyItems[numBodyItemSpecs].length = sizeof(chipId); - numBodyItemSpecs++; - - /* Encode ticket body. */ - ticket.body.length = DERLengthOfEncodedSequence(ASN1_CONSTR_SET, - &bodyItems, numBodyItemSpecs, bodyItemSpecs); - ticket.body.data = malloc(ticket.body.length); - DEREncodeSequence(ASN1_CONSTR_SET, &bodyItems, numBodyItemSpecs, - bodyItemSpecs, ticket.body.data, &ticket.body.length); - - // Signature - ticket.signature.data = (DERByte *)fakeSig; - ticket.signature.length = sizeof(fakeSig); - - // Certificates - DERItemSpec certItemSpecs[1]; - DERItem certItems[1]; - certItemSpecs[0].offset = 0; - certItemSpecs[0].tag = ASN1_CONSTR_SEQUENCE; - certItemSpecs[0].options = DER_ENC_WRITE_DER; - - // NOTE: The Certificate should be added to the ticket by the host. I'm just simulating that here - // to generate the final ticket blob. - readFile("S5L8920_TATSU_FAC_DARWIN_DEV_CHAIN.der", &certItems[0].data, &certItems[0].length); - - ticket.certificates.length = DERLengthOfEncodedSequence( - ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 1, &certItems, - 1, certItemSpecs); - ticket.certificates.data = malloc(ticket.certificates.length); - DEREncodeSequence(ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 1, &certItems, - 1, certItemSpecs, ticket.certificates.data, &ticket.certificates.length); - - /* Encode the entire ticket. */ - DERSize ticketLength = DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE, - &ticket, DERNumApTicketItemSpecs, DERApTicketItemSpecs); - DERByte *ticketBytes = malloc(ticketLength); - DEREncodeSequence(ASN1_CONSTR_SEQUENCE, &ticket, DERNumApTicketItemSpecs, DERApTicketItemSpecs, - ticketBytes, &ticketLength); - - // save ticket to file - writeFile("ApTicket.bin", ticketBytes, ticketLength); - -//cleanup: - free(ticket.body.data); - free(ticket.signatureAlgorithm.data); - free(ticket.certificates.data); - free(ticketBytes); -} - -static void -make_sample_bb_ticket( void ) -{ - int status = 0; - unsigned char chipId[] = { 0x01, 0x02, 0x03, 0x04 }; - unsigned char snum[] = { 0x01, 0x02, 0x03, 0x04 }; - unsigned char signature[SIG_LEN] = {}; - DERByte *ticketBytes = NULL; - - DERBbTicket ticket = {}; - - /* Encode the signatureAlgorithm field of the ticket. */ - DERAlgorithmId algorithmId = { .oid = oidSha1Rsa }; - ticket.signatureAlgorithm.length = DERLengthOfEncodedSequence( - ASN1_CONSTR_SEQUENCE, &algorithmId, DERNumAlgorithmIdItemSpecs, - DERAlgorithmIdItemSpecs); - ticket.signatureAlgorithm.data = malloc(ticket.signatureAlgorithm.length); - DEREncodeSequence(ASN1_CONSTR_SEQUENCE, &algorithmId, - DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, - ticket.signatureAlgorithm.data, &ticket.signatureAlgorithm.length); - - /* Construct ticket body. */ - DERSize numBodyItemSpecs = 0; - DERItemSpec bodyItemSpecs[50] = {}; - DERItem bodyItems[50] = {}; - - /* Add tags in sorted order. */ - bodyItemSpecs[numBodyItemSpecs].offset = numBodyItemSpecs * sizeof(DERItem); - bodyItemSpecs[numBodyItemSpecs].tag = ASN1_CONTEXT_SPECIFIC | kBbSNUMTag; - bodyItemSpecs[numBodyItemSpecs].options = DER_ENC_NO_OPTS; - bodyItems[numBodyItemSpecs].data = snum; - bodyItems[numBodyItemSpecs].length = sizeof(snum); - numBodyItemSpecs++; - - bodyItemSpecs[numBodyItemSpecs].offset = numBodyItemSpecs * sizeof(DERItem); - bodyItemSpecs[numBodyItemSpecs].tag = ASN1_CONTEXT_SPECIFIC | kBbChipIDTag; - bodyItemSpecs[numBodyItemSpecs].options = DER_ENC_NO_OPTS; - bodyItems[numBodyItemSpecs].data = chipId; - bodyItems[numBodyItemSpecs].length = sizeof(chipId); - numBodyItemSpecs++; - - /* Encode ticket body. */ - ticket.body.length = DERLengthOfEncodedSequence(ASN1_CONSTR_SET, - &bodyItems, numBodyItemSpecs, bodyItemSpecs); - ticket.body.data = malloc(ticket.body.length); - DEREncodeSequence(ASN1_CONSTR_SET, &bodyItems, numBodyItemSpecs, bodyItemSpecs, - ticket.body.data, &ticket.body.length); - - // NOTE: In the SEE machine, the Body above will then be hashed/signed to generate signature - status = rsa_sign( - "G1_GPrK.pem", - ticket.body.data, - ticket.body.length, - (unsigned char *)signature ); - if ( status ) { - fprintf( stderr, "rsa_sign failed=%d\n", status ); - goto cleanup; - } else { - fprintf( stdout, "Signed successfully\n"); - } - - status = rsa_verify( - "G1_GPrK.pem", - ticket.body.data, - ticket.body.length, - (unsigned char *)signature ); - if ( status ) { - fprintf( stderr, "rsa_verify failed=%d\n", status ); - goto cleanup; - } else { - fprintf( stdout, "Signature verified successfully\n"); - } - - // Signature - ticket.signature.data = signature; - ticket.signature.length = SIG_LEN; - - // Certificates - ticket.gpuk.length = sizeof(GoldKeyCert); - ticket.gpuk.data = (DERByte *)GoldKeyCert; - - /* Encode the entire ticket. */ - DERSize ticketLength = DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE, - &ticket, DERNumBbTicketItemSpecs, DERBbTicketItemSpecs); - ticketBytes = malloc(ticketLength); - DEREncodeSequence(ASN1_CONSTR_SEQUENCE, &ticket, DERNumBbTicketItemSpecs, - DERBbTicketItemSpecs, ticketBytes, &ticketLength); - - // save ticket to file - writeFile("BbTicket.bin", ticketBytes, ticketLength); - -cleanup: - free(ticket.body.data); - free(ticket.signatureAlgorithm.data); - free(ticketBytes); -} - -static void -long_tag_test(void) -{ - printf("ASN1_TAG_MASK 0x%.016qx\n", (uint64_t)ASN1_TAG_MASK); - printf("ASN1_TAGNUM_MASK 0x%.016qx\n", (uint64_t)ASN1_TAGNUM_MASK); - printf("ASN1_METHOD_MASK 0x%.016qx\n", (uint64_t)ASN1_METHOD_MASK); - printf("ASN1_PRIMITIVE 0x%.016qx\n", (uint64_t)ASN1_PRIMITIVE); - printf("ASN1_CONSTRUCTED 0x%.016qx\n", (uint64_t)ASN1_CONSTRUCTED); - printf("ASN1_CLASS_MASK 0x%.016qx\n", (uint64_t)ASN1_CLASS_MASK); - printf("ASN1_UNIVERSAL 0x%.016qx\n", (uint64_t)ASN1_UNIVERSAL); - printf("ASN1_APPLICATION 0x%.016qx\n", (uint64_t)ASN1_APPLICATION); - printf("ASN1_CONTEXT_SPECIFIC 0x%.016qx\n", (uint64_t)ASN1_CONTEXT_SPECIFIC); - printf("ASN1_PRIVATE 0x%.016qx\n", (uint64_t)ASN1_PRIVATE); - - DERByte buf[10]; - DERSize len = sizeof(buf); - DERReturn drtn; - DERTag tag = ASN1_CONTEXT_SPECIFIC | ASN1_TAGNUM_MASK; - drtn = DEREncodeItem(tag, 0, 0, buf, &len); - if (drtn) - { - printf("DEREncodeItem: %u\n", drtn); - } - DERItem der = { .data = buf, .length = len }; - - dumpBytes("tlv", buf, len, 0); - - DERDecodedInfo decoded; - drtn = DERDecodeItem(&der, &decoded); - if (drtn) - { - printf("DERDecodeItem: %u\n", drtn); - } - if (decoded.tag != tag) - { - printf("DERDecodeItem tag: 0x%qx != 0x%qx\n", (uint64_t)decoded.tag, (uint64_t)tag); - } - printf("DERDecodeItem tag: 0x%qx encoded in %u bytes, decoded length: %u\n", - (uint64_t)tag, len, decoded.content.length); -} - -int main(int argc, char **argv) -{ - long_tag_test(); - printf( "=> Making sample BB ticket...\n"); - make_sample_bb_ticket(); - printf( "=> Making sample AP ticket...\n"); - make_sample_ap_ticket(); - printf( "=> Verifying signature in bb_ticket.bin ...\n"); - verify_ticket_file( "bb_ticket.bin", "G1_GPrK.pem" ); - return 0; -} diff --git a/libDER/libDER/DER_CertCrl.c b/libDER/libDER/DER_CertCrl.c deleted file mode 100644 index d971650b..00000000 --- a/libDER/libDER/DER_CertCrl.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2005-2009,2011,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * DER_Cert.c - support for decoding X509 certificates - * - */ - -#include -#include -#include -#include - -/* - * DERItemSpecs for X509 certificates. - */ - -/* top level cert with three components */ -const DERItemSpec DERSignedCertCrlItemSpecs[] = -{ - { DER_OFFSET(DERSignedCertCrl, tbs), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS | DER_DEC_SAVE_DER}, - { DER_OFFSET(DERSignedCertCrl, sigAlg), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERSignedCertCrl, sig), - ASN1_BIT_STRING, - DER_DEC_NO_OPTS } -}; - -const DERSize DERNumSignedCertCrlItemSpecs = - sizeof(DERSignedCertCrlItemSpecs) / sizeof(DERItemSpec); - -/* TBS cert */ -const DERItemSpec DERTBSCertItemSpecs[] = -{ - { DER_OFFSET(DERTBSCert, version), - ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 0, - DER_DEC_OPTIONAL }, /* version - EXPLICIT */ - { DER_OFFSET(DERTBSCert, serialNum), - ASN1_INTEGER, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERTBSCert, tbsSigAlg), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERTBSCert, issuer), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERTBSCert, validity), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERTBSCert, subject), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERTBSCert, subjectPubKey), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS | DER_DEC_SAVE_DER | DER_ENC_WRITE_DER }, - /* libsecurity_asn1 has these two as CONSTRUCTED, but the ASN.1 spec - * doesn't look that way to me. I don't have any certs that have these - * fields.... */ - { DER_OFFSET(DERTBSCert, issuerID), - ASN1_CONTEXT_SPECIFIC | 1, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERTBSCert, subjectID), - ASN1_CONTEXT_SPECIFIC | 2, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERTBSCert, extensions), - ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 3, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumTBSCertItemSpecs = sizeof(DERTBSCertItemSpecs) / sizeof(DERItemSpec); - -/* DERValidity */ -const DERItemSpec DERValidityItemSpecs[] = -{ - { DER_OFFSET(DERValidity, notBefore), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER }, - { DER_OFFSET(DERValidity, notAfter), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER } -}; -const DERSize DERNumValidityItemSpecs = - sizeof(DERValidityItemSpecs) / sizeof(DERItemSpec); - -/* DERAttributeTypeAndValue */ -const DERItemSpec DERAttributeTypeAndValueItemSpecs[] = { - { DER_OFFSET(DERAttributeTypeAndValue, type), - ASN1_OBJECT_ID, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERAttributeTypeAndValue, value), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER } -}; - -const DERSize DERNumAttributeTypeAndValueItemSpecs = - sizeof(DERAttributeTypeAndValueItemSpecs) / sizeof(DERItemSpec); - -/* DERExtension */ -const DERItemSpec DERExtensionItemSpecs[] = -{ - { DER_OFFSET(DERExtension, extnID), - ASN1_OBJECT_ID, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERExtension, critical), - ASN1_BOOLEAN, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERExtension, extnValue), - ASN1_OCTET_STRING, - DER_DEC_NO_OPTS } -}; -const DERSize DERNumExtensionItemSpecs = - sizeof(DERExtensionItemSpecs) / sizeof(DERItemSpec); - -/* DERBasicConstraints */ -const DERItemSpec DERBasicConstraintsItemSpecs[] = -{ - { DER_OFFSET(DERBasicConstraints, cA), - ASN1_BOOLEAN, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERBasicConstraints, pathLenConstraint), - ASN1_INTEGER, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumBasicConstraintsItemSpecs = - sizeof(DERBasicConstraintsItemSpecs) / sizeof(DERItemSpec); - -/* DERNameConstraints. */ -const DERItemSpec DERNameConstraintsItemSpecs[] = -{ - { DER_OFFSET(DERNameConstraints, permittedSubtrees), - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERNameConstraints, excludedSubtrees), - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumNameConstraintsItemSpecs = -sizeof(DERNameConstraintsItemSpecs) /sizeof(DERItemSpec); - -/* DERGeneralSubtree. */ -const DERItemSpec DERGeneralSubtreeItemSpecs[] = -{ - { DER_OFFSET(DERGeneralSubtree, generalName), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER}, - { DER_OFFSET(DERGeneralSubtree, minimum), - ASN1_CONTEXT_SPECIFIC | 0, - DER_DEC_OPTIONAL}, - { DER_OFFSET(DERGeneralSubtree, maximum), - ASN1_CONTEXT_SPECIFIC | 1, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumGeneralSubtreeItemSpecs = -sizeof(DERGeneralSubtreeItemSpecs) /sizeof(DERItemSpec); - -/* DERPrivateKeyUsagePeriod. */ -const DERItemSpec DERPrivateKeyUsagePeriodItemSpecs[] = -{ - { DER_OFFSET(DERPrivateKeyUsagePeriod, notBefore), - ASN1_CONTEXT_SPECIFIC | 0, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERPrivateKeyUsagePeriod, notAfter), - ASN1_CONTEXT_SPECIFIC | 1, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumPrivateKeyUsagePeriodItemSpecs = - sizeof(DERPrivateKeyUsagePeriodItemSpecs) / sizeof(DERItemSpec); - -/* DERDistributionPoint. */ -const DERItemSpec DERDistributionPointItemSpecs[] = -{ - { DER_OFFSET(DERDistributionPoint, distributionPoint), - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERDistributionPoint, reasons), - ASN1_CONTEXT_SPECIFIC | 1, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERDistributionPoint, cRLIssuer), - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumDistributionPointItemSpecs = - sizeof(DERDistributionPointItemSpecs) / sizeof(DERItemSpec); - -/* DERPolicyInformation. */ -const DERItemSpec DERPolicyInformationItemSpecs[] = -{ - { DER_OFFSET(DERPolicyInformation, policyIdentifier), - ASN1_OBJECT_ID, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERPolicyInformation, policyQualifiers), - ASN1_CONSTR_SEQUENCE, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumPolicyInformationItemSpecs = - sizeof(DERPolicyInformationItemSpecs) / sizeof(DERItemSpec); - -/* DERPolicyQualifierInfo. */ -const DERItemSpec DERPolicyQualifierInfoItemSpecs[] = -{ - { DER_OFFSET(DERPolicyQualifierInfo, policyQualifierID), - ASN1_OBJECT_ID, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERPolicyQualifierInfo, qualifier), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER } -}; -const DERSize DERNumPolicyQualifierInfoItemSpecs = - sizeof(DERPolicyQualifierInfoItemSpecs) / sizeof(DERItemSpec); - -/* DERUserNotice. */ -const DERItemSpec DERUserNoticeItemSpecs[] = -{ - { DER_OFFSET(DERUserNotice, noticeRef), - ASN1_CONSTR_SEQUENCE, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERUserNotice, explicitText), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_OPTIONAL | DER_DEC_SAVE_DER } -}; -const DERSize DERNumUserNoticeItemSpecs = - sizeof(DERUserNoticeItemSpecs) / sizeof(DERItemSpec); - -/* DERNoticeReference. */ -const DERItemSpec DERNoticeReferenceItemSpecs[] = -{ - { DER_OFFSET(DERNoticeReference, organization), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER }, - { DER_OFFSET(DERNoticeReference, noticeNumbers), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS } -}; -const DERSize DERNumNoticeReferenceItemSpecs = - sizeof(DERNoticeReferenceItemSpecs) / sizeof(DERItemSpec); - -/* DERPolicyMapping. */ -const DERItemSpec DERPolicyMappingItemSpecs[] = -{ - { DER_OFFSET(DERPolicyMapping, issuerDomainPolicy), - ASN1_OBJECT_ID, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERPolicyMapping, subjectDomainPolicy), - ASN1_OBJECT_ID, - DER_DEC_NO_OPTS } -}; -const DERSize DERNumPolicyMappingItemSpecs = - sizeof(DERPolicyMappingItemSpecs) / sizeof(DERItemSpec); - -/* DERAccessDescription. */ -const DERItemSpec DERAccessDescriptionItemSpecs[] = -{ - { DER_OFFSET(DERAccessDescription, accessMethod), - ASN1_OBJECT_ID, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERAccessDescription, accessLocation), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER } -}; -const DERSize DERNumAccessDescriptionItemSpecs = - sizeof(DERAccessDescriptionItemSpecs) / sizeof(DERItemSpec); - -/* DERAuthorityKeyIdentifier. */ -const DERItemSpec DERAuthorityKeyIdentifierItemSpecs[] = -{ - { DER_OFFSET(DERAuthorityKeyIdentifier, keyIdentifier), - ASN1_CONTEXT_SPECIFIC | 0, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERAuthorityKeyIdentifier, authorityCertIssuer), - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERAuthorityKeyIdentifier, authorityCertSerialNumber), - ASN1_CONTEXT_SPECIFIC | 2, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumAuthorityKeyIdentifierItemSpecs = - sizeof(DERAuthorityKeyIdentifierItemSpecs) / sizeof(DERItemSpec); - -/* DEROtherName. */ -const DERItemSpec DEROtherNameItemSpecs[] = -{ - { DER_OFFSET(DEROtherName, typeIdentifier), - ASN1_OBJECT_ID, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DEROtherName, value), - ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0, - DER_DEC_NO_OPTS }, -}; -const DERSize DERNumOtherNameItemSpecs = - sizeof(DEROtherNameItemSpecs) / sizeof(DERItemSpec); - -/* DERPolicyConstraints. */ -const DERItemSpec DERPolicyConstraintsItemSpecs[] = -{ - { DER_OFFSET(DERPolicyConstraints, requireExplicitPolicy), - ASN1_CONTEXT_SPECIFIC | 0, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERPolicyConstraints, inhibitPolicyMapping), - ASN1_CONTEXT_SPECIFIC | 1, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumPolicyConstraintsItemSpecs = - sizeof(DERPolicyConstraintsItemSpecs) / sizeof(DERItemSpec); - -/* DERTBSCrl */ -const DERItemSpec DERTBSCrlItemSpecs[] = -{ - { DER_OFFSET(DERTBSCrl, version), - ASN1_INTEGER, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERTBSCrl, tbsSigAlg), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERTBSCrl, issuer), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERTBSCrl, thisUpdate), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER }, - { DER_OFFSET(DERTBSCrl, nextUpdate), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER }, - { DER_OFFSET(DERTBSCrl, revokedCerts), - ASN1_CONSTR_SEQUENCE, - DER_DEC_OPTIONAL }, - { DER_OFFSET(DERTBSCrl, extensions), - ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 0, - DER_DEC_OPTIONAL } -}; -const DERSize DERNumTBSCrlItemSpecs = sizeof(DERTBSCrlItemSpecs) / sizeof(DERItemSpec); - -/* DERRevokedCert */ -const DERItemSpec DERRevokedCertItemSpecs[] = -{ - { DER_OFFSET(DERRevokedCert, serialNum), - ASN1_INTEGER, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERRevokedCert, revocationDate), - 0, /* no tag - ANY */ - DER_DEC_ASN_ANY | DER_DEC_SAVE_DER }, - { DER_OFFSET(DERRevokedCert, extensions), - ASN1_CONSTR_SEQUENCE, - DER_DEC_OPTIONAL } -}; - -const DERSize DERNumRevokedCertItemSpecs = - sizeof(DERRevokedCertItemSpecs) / sizeof(DERItemSpec); diff --git a/libDER/libDER/DER_CertCrl.h b/libDER/libDER/DER_CertCrl.h deleted file mode 100644 index db36e5cc..00000000 --- a/libDER/libDER/DER_CertCrl.h +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * DER_CertCrl.h - support for decoding X509 certificates and CRLs - * - */ - -#ifndef _DER_CERT_CRL_H_ -#define _DER_CERT_CRL_H_ - -#include -#include - -__BEGIN_DECLS - -/* - * Top level cert or CRL - the two are identical at this level - three - * components. The tbs field is saved in full DER form for sig verify. - */ -typedef struct { - DERItem tbs; /* sequence, DERTBSCert, DER_DEC_SAVE_DER */ - DERItem sigAlg; /* sequence, DERAlgorithmId */ - DERItem sig; /* bit string */ -} DERSignedCertCrl; - -/* DERItemSpecs to decode into a DERSignedCertCrl */ -extern const DERItemSpec DERSignedCertCrlItemSpecs[]; -extern const DERSize DERNumSignedCertCrlItemSpecs; - -/* TBS cert components */ -typedef struct { - DERItem version; /* integer, optional, EXPLICIT */ - DERItem serialNum; /* integer */ - DERItem tbsSigAlg; /* sequence, DERAlgorithmId */ - DERItem issuer; /* sequence, TBD */ - DERItem validity; /* sequence, DERValidity */ - DERItem subject; /* sequence, TBD */ - DERItem subjectPubKey; /* sequence, DERSubjPubKeyInfo */ - DERItem issuerID; /* bit string, optional */ - DERItem subjectID; /* bit string, optional */ - DERItem extensions; /* sequence, optional, EXPLICIT */ -} DERTBSCert; - -/* DERItemSpecs to decode into a DERTBSCert */ -extern const DERItemSpec DERTBSCertItemSpecs[]; -extern const DERSize DERNumTBSCertItemSpecs; - -/* - * validity - components can be either UTC or generalized time. - * Both are ASN_ANY with DER_DEC_SAVE_DER. - */ -typedef struct { - DERItem notBefore; - DERItem notAfter; -} DERValidity; - -/* DERItemSpecs to decode into a DERValidity */ -extern const DERItemSpec DERValidityItemSpecs[]; -extern const DERSize DERNumValidityItemSpecs; - -/* AttributeTypeAndValue components. */ -typedef struct { - DERItem type; - DERItem value; -} DERAttributeTypeAndValue; - -/* DERItemSpecs to decode into DERAttributeTypeAndValue */ -extern const DERItemSpec DERAttributeTypeAndValueItemSpecs[]; -extern const DERSize DERNumAttributeTypeAndValueItemSpecs; - -/* Extension components */ -typedef struct { - DERItem extnID; - DERItem critical; - DERItem extnValue; -} DERExtension; - -/* DERItemSpecs to decode into DERExtension */ -extern const DERItemSpec DERExtensionItemSpecs[]; -extern const DERSize DERNumExtensionItemSpecs; - -/* BasicConstraints components. */ -typedef struct { - DERItem cA; - DERItem pathLenConstraint; -} DERBasicConstraints; - -/* DERItemSpecs to decode into DERBasicConstraints */ -extern const DERItemSpec DERBasicConstraintsItemSpecs[]; -extern const DERSize DERNumBasicConstraintsItemSpecs; - -/* NameConstraints components. */ -typedef struct { - DERItem permittedSubtrees; - DERItem excludedSubtrees; -} DERNameConstraints; - -/* DERItemSpecs to decode into a DERNameConstraints */ -extern const DERItemSpec DERNameConstraintsItemSpecs[]; -extern const DERSize DERNumNameConstraintsItemSpecs; - -/* GeneralSubtree components. */ -typedef struct { - DERItem generalName; - DERItem minimum; - DERItem maximum; -} DERGeneralSubtree; - -/* DERItemSpecs to decode into a DERGeneralSubtree */ -extern const DERItemSpec DERGeneralSubtreeItemSpecs[]; -extern const DERSize DERNumGeneralSubtreeItemSpecs; - -/* PrivateKeyUsagePeriod components. */ -typedef struct { - DERItem notBefore; - DERItem notAfter; -} DERPrivateKeyUsagePeriod; - -/* DERItemSpecs to decode into a DERPrivateKeyUsagePeriod */ -extern const DERItemSpec DERPrivateKeyUsagePeriodItemSpecs[]; -extern const DERSize DERNumPrivateKeyUsagePeriodItemSpecs; - -/* DistributionPoint components. */ -typedef struct { - DERItem distributionPoint; - DERItem reasons; - DERItem cRLIssuer; -} DERDistributionPoint; - -/* DERItemSpecs to decode into a DERDistributionPoint */ -extern const DERItemSpec DERDistributionPointItemSpecs[]; -extern const DERSize DERNumDistributionPointItemSpecs; - -/* PolicyInformation components. */ -typedef struct { - DERItem policyIdentifier; - DERItem policyQualifiers; -} DERPolicyInformation; - -/* DERItemSpecs to decode into a DERPolicyInformation */ -extern const DERItemSpec DERPolicyInformationItemSpecs[]; -extern const DERSize DERNumPolicyInformationItemSpecs; - -/* PolicyQualifierInfo components. */ -typedef struct { - DERItem policyQualifierID; - DERItem qualifier; -} DERPolicyQualifierInfo; - -/* DERItemSpecs to decode into a DERPolicyQualifierInfo */ -extern const DERItemSpec DERPolicyQualifierInfoItemSpecs[]; -extern const DERSize DERNumPolicyQualifierInfoItemSpecs; - -/* UserNotice components. */ -typedef struct { - DERItem noticeRef; - DERItem explicitText; -} DERUserNotice; - -/* DERItemSpecs to decode into a DERUserNotice */ -extern const DERItemSpec DERUserNoticeItemSpecs[]; -extern const DERSize DERNumUserNoticeItemSpecs; - -/* NoticeReference components. */ -typedef struct { - DERItem organization; - DERItem noticeNumbers; -} DERNoticeReference; - -/* DERItemSpecs to decode into a DERNoticeReference */ -extern const DERItemSpec DERNoticeReferenceItemSpecs[]; -extern const DERSize DERNumNoticeReferenceItemSpecs; - -/* PolicyMapping components. */ -typedef struct { - DERItem issuerDomainPolicy; - DERItem subjectDomainPolicy; -} DERPolicyMapping; - -/* DERItemSpecs to decode into a DERPolicyMapping */ -extern const DERItemSpec DERPolicyMappingItemSpecs[]; -extern const DERSize DERNumPolicyMappingItemSpecs; - -/* AccessDescription components. */ -typedef struct { - DERItem accessMethod; - DERItem accessLocation; -} DERAccessDescription; - -/* DERItemSpecs to decode into a DERAccessDescription */ -extern const DERItemSpec DERAccessDescriptionItemSpecs[]; -extern const DERSize DERNumAccessDescriptionItemSpecs; - -/* AuthorityKeyIdentifier components. */ -typedef struct { - DERItem keyIdentifier; - DERItem authorityCertIssuer; - DERItem authorityCertSerialNumber; -} DERAuthorityKeyIdentifier; - -/* DERItemSpecs to decode into a DERAuthorityKeyIdentifier */ -extern const DERItemSpec DERAuthorityKeyIdentifierItemSpecs[]; -extern const DERSize DERNumAuthorityKeyIdentifierItemSpecs; - -/* OtherName components. */ -typedef struct { - DERItem typeIdentifier; - DERItem value; -} DEROtherName; - -/* DERItemSpecs to decode into a DEROtherName */ -extern const DERItemSpec DEROtherNameItemSpecs[]; -extern const DERSize DERNumOtherNameItemSpecs; - -/* PolicyConstraints components. */ -typedef struct { - DERItem requireExplicitPolicy; - DERItem inhibitPolicyMapping; -} DERPolicyConstraints; - -/* DERItemSpecs to decode into a DERPolicyConstraints */ -extern const DERItemSpec DERPolicyConstraintsItemSpecs[]; -extern const DERSize DERNumPolicyConstraintsItemSpecs; - -/* TBS CRL */ -typedef struct { - DERItem version; /* integer, optional */ - DERItem tbsSigAlg; /* sequence, DERAlgorithmId */ - DERItem issuer; /* sequence, TBD */ - DERItem thisUpdate; /* ASN_ANY, SAVE_DER */ - DERItem nextUpdate; /* ASN_ANY, SAVE_DER */ - DERItem revokedCerts; /* sequence of DERRevokedCert, optional */ - DERItem extensions; /* sequence, optional, EXPLICIT */ -} DERTBSCrl; - -/* DERItemSpecs to decode into a DERTBSCrl */ -extern const DERItemSpec DERTBSCrlItemSpecs[]; -extern const DERSize DERNumTBSCrlItemSpecs; - -typedef struct { - DERItem serialNum; /* integer */ - DERItem revocationDate; /* time - ASN_ANY, SAVE_DER */ - DERItem extensions; /* sequence, optional, EXPLICIT */ -} DERRevokedCert; - -/* DERItemSpecs to decode into a DERRevokedCert */ -extern const DERItemSpec DERRevokedCertItemSpecs[]; -extern const DERSize DERNumRevokedCertItemSpecs; - -__END_DECLS - -#endif /* _DER_CERT_CRL_H_ */ - diff --git a/libDER/libDER/DER_Decode.c b/libDER/libDER/DER_Decode.c deleted file mode 100644 index 04374a35..00000000 --- a/libDER/libDER/DER_Decode.c +++ /dev/null @@ -1,759 +0,0 @@ -/* - * Copyright (c) 2005-2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * DER_Decode.c - DER decoding routines - */ - -#include -#include - -#include - -#ifndef DER_DECODE_ENABLE -#error Please define DER_DECODE_ENABLE. -#endif - -#if DER_DECODE_ENABLE - -#define DER_DECODE_DEBUG 0 -#if DER_DECODE_DEBUG -#include -#define derDecDbg(a) printf(a) -#define derDecDbg1(a, b) printf(a, b) -#define derDecDbg2(a, b, c) printf(a, b, c) -#define derDecDbg3(a, b, c, d) printf(a, b, c, d) -#else -#define derDecDbg(a) -#define derDecDbg1(a, b) -#define derDecDbg2(a, b, c) -#define derDecDbg3(a, b, c, d) -#endif /* DER_DECODE_DEBUG */ - -/* - * Basic decoding primitive. Only works with: - * - * -- definite length encoding - * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined) - * -- max content length fits in a DERSize - * - * No malloc or copy of the contents is performed; the returned - * content->content.data is a pointer into the incoming der data. - */ -DERReturn DERDecodeItem( - const DERItem *der, /* data to decode */ - DERDecodedInfo *decoded) /* RETURNED */ -{ - return DERDecodeItemPartialBufferGetLength(der, decoded, NULL); -} - -/* - * Basic decoding primitive. Allows for decoding with a partial buffer. - * if allowPartialBuffer is true. A partial buffer would normally fail - * because the encoded length would be greater than the size of the buffer passed in. - * Only works with: - * - * -- definite length encoding - * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined) - * -- max content length fits in a DERSize - * - * No malloc or copy of the contents is performed; the returned - * content->content.data is a pointer into the incoming der data. - * - * WARNING: Using a partial buffer can return a DERDecodedInfo object with - * a length larger than the buffer. It is recommended to instead use - * DERDecodeItemPartialBufferGetLength if you need partial buffers. - * - */ -DERReturn DERDecodeItemPartialBuffer( - const DERItem *der, /* data to decode */ - DERDecodedInfo *decoded, /* RETURNED */ - bool allowPartialBuffer) -{ - DERByte tag1; /* first tag byte */ - DERByte len1; /* first length byte */ - DERTag tagNumber; /* tag number without class and method bits */ - DERByte *derPtr = der->data; - DERSize derLen = der->length; - - /* The tag decoding below is fully BER complient. We support a max tag - value of 2 ^ ((sizeof(DERTag) * 8) - 3) - 1 so for tag size 1 byte we - support tag values from 0 - 0x1F. For tag size 2 tag values - from 0 - 0x1FFF and for tag size 4 values from 0 - 0x1FFFFFFF. */ - if(derLen < 2) { - return DR_DecodeError; - } - /* Grab the first byte of the tag. */ - tag1 = *derPtr++; - derLen--; - tagNumber = tag1 & 0x1F; - if(tagNumber == 0x1F) { -#ifdef DER_MULTIBYTE_TAGS - /* Long tag form: bit 8 of each octet shall be set to one unless it is - the last octet of the tag */ - const DERTag overflowMask = ((DERTag)0x7F << (sizeof(DERTag) * 8 - 7)); - DERByte tagByte; - tagNumber = 0; - if (*derPtr == 0x80 || *derPtr < 0x1F) - return DR_DecodeError; - do { - if(derLen < 2 || (tagNumber & overflowMask) != 0) { - return DR_DecodeError; - } - tagByte = *derPtr++; - derLen--; - tagNumber = (tagNumber << 7) | (tagByte & 0x7F); - } while((tagByte & 0x80) != 0); - - /* Check for any of the top 3 reserved bits being set. */ - if ((tagNumber & (overflowMask << 4)) != 0) -#endif - return DR_DecodeError; - } - /* Returned tag, top 3 bits are class/method remaining bits are number. */ - decoded->tag = ((DERTag)(tag1 & 0xE0) << ((sizeof(DERTag) - 1) * 8)) | tagNumber; - - /* Tag decoding above ensured we have at least one more input byte left. */ - len1 = *derPtr++; - derLen--; - if(len1 & 0x80) { - /* long length form - first byte is length of length */ - DERSize longLen = 0; /* long form length */ - - unsigned dex; - len1 &= 0x7f; - if((len1 > sizeof(DERSize)) || (len1 > derLen) || len1 == 0 || *derPtr == 0) { - /* no can do */ - return DR_DecodeError; - } - for(dex=0; dex derLen && !allowPartialBuffer) { - /* not enough data left for this encoding */ - return DR_DecodeError; - } - decoded->content.data = derPtr; - decoded->content.length = longLen; - } - else { - /* short length form, len1 is the length */ - if(len1 > derLen && !allowPartialBuffer) { - /* not enough data left for this encoding */ - return DR_DecodeError; - } - decoded->content.data = derPtr; - decoded->content.length = len1; - } - - return DR_Success; -} - -/* - * Same as above, but returns a DERDecodedInfo with a length no larger than the buffer. - * The actual encoded length can be retrieved from encodedLength parameter. - * encodedLength can be NULL to achieve the same behavior as DERDecodeItemPartialBuffer, - * with allowPartialBuffer=false - * - * NOTE: The DERDecoded length will never be larger than the input buffer. - * This is a key difference from DERDecodeItemPartialBuffer which could return invalid length. - * - */ -DERReturn DERDecodeItemPartialBufferGetLength( - const DERItem *der, /* data to decode */ - DERDecodedInfo *decoded, /* RETURNED */ - DERSize *encodedLength) -{ - DERByte tag1; /* first tag byte */ - DERByte len1; /* first length byte */ - DERTag tagNumber; /* tag number without class and method bits */ - DERByte *derPtr = der->data; - DERSize derLen = der->length; - - /* The tag decoding below is fully BER complient. We support a max tag - value of 2 ^ ((sizeof(DERTag) * 8) - 3) - 1 so for tag size 1 byte we - support tag values from 0 - 0x1F. For tag size 2 tag values - from 0 - 0x1FFF and for tag size 4 values from 0 - 0x1FFFFFFF. */ - if(derLen < 2) { - return DR_DecodeError; - } - /* Grab the first byte of the tag. */ - tag1 = *derPtr++; - derLen--; - tagNumber = tag1 & 0x1F; - if(tagNumber == 0x1F) { -#ifdef DER_MULTIBYTE_TAGS - /* Long tag form: bit 8 of each octet shall be set to one unless it is - the last octet of the tag */ - const DERTag overflowMask = ((DERTag)0x7F << (sizeof(DERTag) * 8 - 7)); - DERByte tagByte; - tagNumber = 0; - if (*derPtr == 0x80 || *derPtr < 0x1F) - return DR_DecodeError; - do { - if(derLen < 2 || (tagNumber & overflowMask) != 0) { - return DR_DecodeError; - } - tagByte = *derPtr++; - derLen--; - tagNumber = (tagNumber << 7) | (tagByte & 0x7F); - } while((tagByte & 0x80) != 0); - - /* Check for any of the top 3 reserved bits being set. */ - if ((tagNumber & (overflowMask << 4)) != 0) -#endif - return DR_DecodeError; - } - /* Returned tag, top 3 bits are class/method remaining bits are number. */ - decoded->tag = ((DERTag)(tag1 & 0xE0) << ((sizeof(DERTag) - 1) * 8)) | tagNumber; - - /* Tag decoding above ensured we have at least one more input byte left. */ - len1 = *derPtr++; - derLen--; - if(len1 & 0x80) { - /* long length form - first byte is length of length */ - DERSize longLen = 0; /* long form length */ - unsigned dex; - - len1 &= 0x7f; - if((len1 > sizeof(DERSize)) || (len1 > derLen) || len1 == 0 || *derPtr == 0) { - /* no can do */ - return DR_DecodeError; - } - for(dex=0; dex derLen && !encodedLength) { - /* not enough data left for this encoding */ - return DR_DecodeError; - } - if (longLencontent.data = derPtr; - decoded->content.length = derLen; - if (encodedLength) { - *encodedLength = longLen; - } - } - else { - /* short length form, len1 is the length */ - if(len1 > derLen && !encodedLength) { - /* not enough data left for this encoding */ - return DR_DecodeError; - } - if (len1content.data = derPtr; - decoded->content.length = derLen; - if (encodedLength) { - *encodedLength = len1; - } - } - - return DR_Success; -} - -/* - * Given a BIT_STRING, in the form of its raw content bytes, - * obtain the number of unused bits and the raw bit string bytes. - */ -DERReturn DERParseBitString( - const DERItem *contents, - DERItem *bitStringBytes, /* RETURNED */ - DERByte *numUnusedBits) /* RETURNED */ -{ - if(contents->length < 2) { - /* not enough room for actual bits after the unused bits field */ - *numUnusedBits = 0; - bitStringBytes->data = NULL; - bitStringBytes->length = 0; - return DR_Success; - } - *numUnusedBits = contents->data[0]; - bitStringBytes->data = contents->data + 1; - bitStringBytes->length = contents->length - 1; - return DR_Success; -} - -/* - * Given a BOOLEAN, in the form of its raw content bytes, - * obtain it's value. - */ -DERReturn DERParseBoolean( - const DERItem *contents, - bool *value) { /* RETURNED */ - if (contents->length != 1 || - (contents->data[0] != 0 && contents->data[0] != 0xFF)) - return DR_DecodeError; - - *value = contents->data[0] != 0; - return DR_Success; -} - -/* - * Given a BOOLEAN, in the form of its raw content bytes, - * obtain it's value. - */ -DERReturn DERParseBooleanWithDefault( - const DERItem *contents, - bool defaultValue, - bool *value) { /* RETURNED */ - if (contents->length == 0) { - *value = defaultValue; - return DR_Success; - } - return DERParseBoolean(contents, value); -} - - -DERReturn DERParseInteger( - const DERItem *contents, - uint32_t *result) { /* RETURNED */ - uint64_t value; - DERReturn drtn = DERParseInteger64(contents, &value); - if (drtn == DR_Success) { - if (value > UINT32_MAX) - drtn = DR_BufOverflow; - else - *result = (uint32_t)value; - } - return drtn; -} - -DERReturn DERParseInteger64( - const DERItem *contents, - uint64_t *result) { /* RETURNED */ - DERSize ix, length = contents->length; - if (length == 0) - return DR_DecodeError; - if (contents->data[0] & 0x80) - return DR_DecodeError; - if (contents->data[0] == 0) { - if (length > 1 && (contents->data[1] & 0x80) == 0) - return DR_DecodeError; - if (length > sizeof(*result) + 1) - return DR_BufOverflow; - } else if (length > sizeof(*result)) { - return DR_BufOverflow; - } - uint64_t value = 0; - for (ix = 0; ix < length; ++ix) { - value <<= 8; - value += contents->data[ix]; - } - *result = value; - return DR_Success; -} - -/* Sequence/set support */ - -/* - * To decode a set or sequence, call DERDecodeSeqInit once, then - * call DERDecodeSeqNext to get each enclosed item. - * DERDecodeSeqNext returns DR_EndOfSequence when no more - * items are available. - */ -DERReturn DERDecodeSeqInit( - const DERItem *der, /* data to decode */ - DERTag *tag, /* RETURNED tag of sequence/set. This will be - * either ASN1_CONSTR_SEQUENCE or ASN1_CONSTR_SET. */ - DERSequence *derSeq) /* RETURNED, to use in DERDecodeSeqNext */ -{ - DERDecodedInfo decoded; - DERReturn drtn; - - drtn = DERDecodeItem(der, &decoded); - if(drtn) { - return drtn; - } - *tag = decoded.tag; - switch(decoded.tag) { - case ASN1_CONSTR_SEQUENCE: - case ASN1_CONSTR_SET: - break; - default: - return DR_UnexpectedTag; - } - derSeq->nextItem = decoded.content.data; - derSeq->end = decoded.content.data + decoded.content.length; - return DR_Success; -} - -/* - * Use this to start in on decoding a sequence's content, when - * the top-level tag and content have already been decoded. - */ -DERReturn DERDecodeSeqContentInit( - const DERItem *content, - DERSequence *derSeq) /* RETURNED, to use in DERDecodeSeqNext */ -{ - /* just prepare for decoding items in content */ - derSeq->nextItem = content->data; - derSeq->end = content->data + content->length; - return DR_Success; -} - -DERReturn DERDecodeSeqNext( - DERSequence *derSeq, - DERDecodedInfo *decoded) /* RETURNED */ -{ - DERReturn drtn; - DERItem item; - - if(derSeq->nextItem >= derSeq->end) { - /* normal termination, contents all used up */ - return DR_EndOfSequence; - } - - /* decode next item */ - item.data = derSeq->nextItem; - item.length = (DERSize) (derSeq->end - derSeq->nextItem); - drtn = DERDecodeItem(&item, decoded); - if(drtn) { - return drtn; - } - - /* skip over the item we just decoded */ - derSeq->nextItem = decoded->content.data + decoded->content.length; - return DR_Success; -} - -/* - * High level sequence parse, starting with top-level tag and content. - * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's - * OK, use DERParseSequenceContent(). - */ -DERReturn DERParseSequence( - const DERItem *der, - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs, - void *dest, /* DERDecodedInfo(s) here RETURNED */ - DERSize sizeToZero) /* optional */ -{ - DERReturn drtn; - DERDecodedInfo topDecode; - - drtn = DERDecodeItem(der, &topDecode); - if(drtn) { - return drtn; - } - if(topDecode.tag != ASN1_CONSTR_SEQUENCE) { - return DR_UnexpectedTag; - } - return DERParseSequenceContent(&topDecode.content, - numItems, itemSpecs, dest, sizeToZero); -} - -/* high level sequence parse, starting with sequence's content */ -DERReturn DERParseSequenceContent( - const DERItem *content, - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs, - void *dest, /* DERDecodedInfo(s) here RETURNED */ - DERSize sizeToZero) /* optional */ -{ - DERSequence derSeq; - DERReturn drtn; - DERShort itemDex; - DERByte *currDER; /* full DER encoding of current item */ - - if(sizeToZero) { - DERMemset(dest, 0, sizeToZero); - } - - drtn = DERDecodeSeqContentInit(content, &derSeq); - if(drtn) { - return drtn; - } - - /* main loop */ - for(itemDex=0 ; itemDexoptions; - derDecDbg3("--- currItem %u expectTag 0x%llx currOptions 0x%x\n", - i, currItemSpec->tag, currOptions); - - if((currOptions & DER_DEC_ASN_ANY) || - (foundTag == currItemSpec->tag)) { - /* - * We're good with this one. Cook up destination address - * as appropriate. - */ - if(!(currOptions & DER_DEC_SKIP)) { - derDecDbg1("--- MATCH at currItem %u\n", i); - DERByte *byteDst = (DERByte *)dest + currItemSpec->offset; - DERItem *dst = (DERItem *)byteDst; - *dst = currDecoded.content; - if(currOptions & DER_DEC_SAVE_DER) { - /* recreate full DER encoding of this item */ - derDecDbg1("--- SAVE_DER at currItem %u\n", i); - dst->data = currDER; - dst->length += (currDecoded.content.data - currDER); - } - } - - /* on to next item */ - itemDex = i + 1; - - /* is this the end? */ - if(itemDex == numItems) { - /* normal termination if we consumed everything */ - if (currDecoded.content.data + currDecoded.content.length == content->data + content->length) - return DR_Success; - else - return DR_DecodeError; - } - else { - /* on to next item */ - foundMatch = 1; - break; - } - } /* ASN_ANY, or match */ - - /* - * If current itemSpec isn't optional, abort - else on to - * next item - */ - if(!(currOptions & DER_DEC_OPTIONAL)) { - derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i); - return DR_UnexpectedTag; - } - - /* else this was optional, on to next item */ - } /* searching for tag match */ - - if(foundMatch == 0) { - /* - * Found an item we couldn't match to any tag spec and we're at - * the end. - */ - derDecDbg("--- TAG NOT FOUND, abort\n"); - return DR_UnexpectedTag; - } - - /* else on to next item */ - } /* main loop */ - - /* Template has 0 items if we get here. */ - /* normal termination if we consumed everything, (the sequence was empty) */ - if (derSeq.nextItem == derSeq.end) - return DR_Success; - else - return DR_DecodeError; -} - -#if 0 -/* - * High level sequence parse, starting with top-level tag and content. - * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's - * OK, use DERParseSequenceContent(). - */ -DERReturn DERParseSequenceOf( - const DERItem *der, - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs, - void *dest, /* DERDecodedInfo(s) here RETURNED */ - DERSize *numDestItems) /* output */ -{ - DERReturn drtn; - DERDecodedInfo topDecode; - - drtn = DERDecodeItem(der, &topDecode); - if(drtn) { - return drtn; - } - if(topDecode.tag != ASN1_CONSTR_SEQUENCE) { - return DR_UnexpectedTag; - } - return DERParseSequenceContent(&topDecode.content, - numItems, itemSpecs, dest, sizeToZero); -} - -/* - * High level set of parse, starting with top-level tag and content. - * Top level tag must be ASN1_CONSTR_SET - if it's not, and that's - * OK, use DERParseSetOrSequenceOfContent(). - */ -DERReturn DERParseSetOf( - const DERItem *der, - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs, - void *dest, /* DERDecodedInfo(s) here RETURNED */ - DERSize *numDestItems) /* output */ -{ - DERReturn drtn; - DERDecodedInfo topDecode; - - drtn = DERDecodeItem(der, &topDecode); - if(drtn) { - return drtn; - } - if(topDecode.tag != ASN1_CONSTR_SET) { - return DR_UnexpectedTag; - } - return DERParseSetOrSequenceOfContent(&topDecode.content, - numItems, itemSpecs, dest, numDestItems); -} - -/* High level set of or sequence of parse, starting with set or - sequence's content */ -DERReturn DERParseSetOrSequenceOfContent( - const DERItem *content, - void(*itemHandeler)(void *, const DERDecodedInfo *) - void *itemHandelerContext); -{ - DERSequence derSeq; - DERShort itemDex; - - drtn = DERDecodeSeqContentInit(content, &derSeq); - require_noerr_quiet(drtn, badCert); - - /* main loop */ - for (;;) { - DERDecodedInfo currDecoded; - DERShort i; - DERByte foundTag; - char foundMatch = 0; - - drtn = DERDecodeSeqNext(&derSeq, &currDecoded); - if(drtn) { - /* The only legal error here is DR_EndOfSequence. */ - if(drtn == DR_EndOfSequence) { - /* no more items left in the sequence; success */ - return DR_Success; - } - else { - /* any other error is fatal */ - require_noerr_quiet(drtn, badCert); - } - } /* decode error */ - - /* Each element can be anything. */ - foundTag = currDecoded.tag; - - /* - * We're good with this one. Cook up destination address - * as appropriate. - */ - DERByte *byteDst = (DERByte *)dest + currItemSpec->offset; - DERItem *dst = (DERItem *)byteDst; - *dst = currDecoded.content; - if(currOptions & DER_DEC_SAVE_DER) { - /* recreate full DER encoding of this item */ - derDecDbg1("--- SAVE_DER at currItem %u\n", i); - dst->data = currDER; - dst->length += (currDecoded.content.data - currDER); - } - - /* on to next item */ - itemDex = i + 1; - - /* is this the end? */ - if(itemDex == numItems) { - /* normal termination */ - return DR_Success; - } - else { - /* on to next item */ - foundMatch = 1; - break; - } - - /* - * If current itemSpec isn't optional, abort - else on to - * next item - */ - if(!(currOptions & DER_DEC_OPTIONAL)) { - derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i); - return DR_UnexpectedTag; - } - - /* else this was optional, on to next item */ - } /* searching for tag match */ - - if(foundMatch == 0) { - /* - * Found an item we couldn't match to any tag spec and we're at - * the end. - */ - derDecDbg("--- TAG NOT FOUND, abort\n"); - return DR_UnexpectedTag; - } - - /* else on to next item */ - } /* main loop */ - - /* - * If we get here, there appears to be more to process, but we've - * given the caller everything they want. - */ - return DR_Success; - } -} -#endif - -#endif /* DER_DECODE_ENABLE */ diff --git a/libDER/libDER/DER_Decode.h b/libDER/libDER/DER_Decode.h deleted file mode 100644 index 4f2c915c..00000000 --- a/libDER/libDER/DER_Decode.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2005-2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * DER_Decode.h - DER decoding routines - */ - -#ifndef _DER_DECODE_H_ -#define _DER_DECODE_H_ - -#include -#include - -__BEGIN_DECLS - -/* - * Decoding one item consists of extracting its tag, a pointer - * to the actual content, and the length of the content. Those - * three are represented by a DERDecodedInfo. - */ -typedef struct { - DERTag tag; - DERItem content; -} DERDecodedInfo; - -/* - * Basic decoding primitive. Only works with: - * - * -- definite length encoding - * -- one-byte tags - * -- max content length fits in a DERSize - * - * No malloc or copy of the contents is performed; the returned - * content->content.data is a pointer into the incoming der data. - */ -DERReturn DERDecodeItem( - const DERItem *der, /* data to decode */ - DERDecodedInfo *decoded); /* RETURNED */ - -/* - * Basic decoding primitive. Allows for decoding with a partial buffer. - * if allowPartialBuffer is true. A partial buffer would normally fail - * because the encoded length would be greater than the size of the buffer passed in. - * Only works with: - * - * -- definite length encoding - * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined) - * -- max content length fits in a DERSize - * - * No malloc or copy of the contents is performed; the returned - * content->content.data is a pointer into the incoming der data. - * - * WARNING: Using a partial buffer can return a DERDecodedInfo object with - * a length larger than the buffer. It is recommended to instead use - * DERDecodeItemPartialBufferGetLength if you need partial buffers. - * - */ -DERReturn DERDecodeItemPartialBuffer( - const DERItem *der, /* data to decode */ - DERDecodedInfo *decoded, /* RETURNED */ - bool allowPartialBuffer); - -/* - * Same as above, but returns a DERDecodedInfo with a length no larger than the buffer. - * The actual encoded length can be retrieved from encodedLength parameter. - * encodedLength can be NULL to achieve the same behavior as DERDecodeItemPartialBuffer, - * with allowPartialBuffer=false - * - * NOTE: The DERDecoded length will never be larger than the input buffer. - * This is a key difference from DERDecodeItemPartialBuffer which could return invalid length. - * - */ -DERReturn DERDecodeItemPartialBufferGetLength( - const DERItem *der, /* data to decode */ - DERDecodedInfo *decoded, /* RETURNED */ - DERSize *encodedLength); - -/* - * Given a BIT_STRING, in the form of its raw content bytes, - * obtain the number of unused bits and the raw bit string bytes. - */ -DERReturn DERParseBitString( - const DERItem *contents, - DERItem *bitStringBytes, /* RETURNED */ - DERByte *numUnusedBits); /* RETURNED */ - -/* - * Given a BOOLEAN, in the form of its raw content bytes, - * obtain it's value. - */ -DERReturn DERParseBoolean( - const DERItem *contents, - bool *value); /* RETURNED */ - -DERReturn DERParseBooleanWithDefault( - const DERItem *contents, - bool defaultValue, - bool *value); /* RETURNED */ -/* - * Given a positive INTEGER, in the form of its raw content bytes, - * obtain it's value as a 32 bit or 64 bit quantity. - * Returns DR_BufOverflow if the value is too large to fit in the return type - */ - -DERReturn DERParseInteger( - const DERItem *contents, - uint32_t *value); /* RETURNED */ - -DERReturn DERParseInteger64( - const DERItem *contents, - uint64_t *value); /* RETURNED */ - -/* - * Sequence/set decode support. - */ - -/* state representing a sequence or set being decoded */ -typedef struct { - DERByte *nextItem; - DERByte *end; -} DERSequence; - -/* - * To decode a set or sequence, call DERDecodeSeqInit or - * DERDecodeSeqContentInit once, then call DERDecodeSeqNext to - * get each enclosed item. - * - * DERDecodeSeqNext returns DR_EndOfSequence when no more - * items are available. - */ - -/* - * Use this to parse the top level sequence's tag and content length. - */ -DERReturn DERDecodeSeqInit( - const DERItem *der, /* data to decode */ - DERTag *tag, /* RETURNED tag of sequence/set. This will be - * either ASN1_CONSTR_SEQUENCE or - * ASN1_CONSTR_SET. */ - DERSequence *derSeq); /* RETURNED, to use in DERDecodeSeqNext */ - -/* - * Use this to start in on decoding a sequence's content, when - * the top-level tag and content have already been decoded. - */ -DERReturn DERDecodeSeqContentInit( - const DERItem *content, - DERSequence *derSeq); /* RETURNED, to use in DERDecodeSeqNext */ - -/* obtain the next decoded item in a sequence or set */ -DERReturn DERDecodeSeqNext( - DERSequence *derSeq, - DERDecodedInfo *decoded); /* RETURNED */ - -/* - * High level sequence decode. - */ - -/* - * Per-item decode options. - */ - -/* Explicit default, no options */ -#define DER_DEC_NO_OPTS 0x0000 - -/* This item optional, can be skipped during decode */ -#define DER_DEC_OPTIONAL 0x0001 - -/* Skip the tag check; accept anything. */ -#define DER_DEC_ASN_ANY 0x0002 - -/* Skip item, no write to DERDecodedInfo (but tag check still performed) */ -#define DER_DEC_SKIP 0x0004 - -/* Save full DER encoding in DERDecodedInfo, including tag and length. Normally - * only the content is saved. */ -#define DER_DEC_SAVE_DER 0x0008 - -/* - * High level sequence parse, starting with top-level tag and content. - * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's - * OK, use DERParseSequenceContent(). - * - * These never return DR_EndOfSequence - if an *unexpected* end of sequence - * occurs, return DR_IncompleteSeq. - * - * Results of the decoding of one item are placed in a DERItem whose address - * is the dest arg plus the offset value in the associated DERItemSpec. - * - * Items which are optional (DER_DEC_OPTIONAL) and which are not found, - * leave their associated DERDecodedInfos unmodified. - * - * Processing of a sequence ends on detection of any error or after the - * last DERItemSpec is processed. - * - * The sizeToZero argument, if nonzero, indicates the number of bytes - * starting at dest to zero before processing the sequence. This is - * generally desirable, particularly if there are any DER_DEC_OPTIONAL - * items in the sequence; skipped optional items are detected by the - * caller via a NULL DERDecodedInfo.content.data; if this hasn't been - * explicitly zeroed (generally, by passing a nonzero value of sizeToZero), - * skipped items can't be detected. - */ -DERReturn DERParseSequence( - const DERItem *der, - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs, - void *dest, /* DERDecodedInfo(s) here RETURNED */ - DERSize sizeToZero); /* optional */ - -/* high level sequence parse, starting with sequence's content */ -DERReturn DERParseSequenceContent( - const DERItem *content, - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs, - void *dest, /* DERDecodedInfo(s) here RETURNED */ - DERSize sizeToZero); /* optional */ - -__END_DECLS - -#endif /* _DER_DECODE_H_ */ - diff --git a/libDER/libDER/DER_Digest.c b/libDER/libDER/DER_Digest.c deleted file mode 100644 index 86e67c18..00000000 --- a/libDER/libDER/DER_Digest.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2005-2008,2010-2011,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * DER_Digest.h - DER encode a DigestInfo - * - */ - -#include - -/* - * Create an encoded DigestInfo based on the specified SHA1 digest. - * The digest must be 20 bytes long. - * - * Result is placed in caller's buffer, which must be at least of - * length DER_DIGEST_INFO_LEN bytes. - * - * The *resultLen parameter is the available size in the result - * buffer on input, and the actual length of the encoded DigestInfo - * on output. - * - * In the interest of saving code space, this just drops the caller's - * digest into an otherwise hard-coded, fixed, encoded SHA1 DigestInfo. - * Nothing is variable so we know the whole thing. It looks like this: - * - * SEQUENCE OF <33> { - * SEQUENCE OF <9> { - * OID <5>: OID : < 06 05 2B 0E 03 02 1A > - * NULL - * } - * OCTET STRING <20>: - * 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 - * 55 55 55 55 - * } - * - * - * tower.local:digestInfo> hexdump -x /tmp/encodedDigest - * 0000000 3021 3009 0605 2b0e 0302 1a05 0004 1455 - * 0000010 5555 5555 5555 5555 5555 5555 5555 5555 - * * - * 0000020 - */ - -static const unsigned char encodedSha1Digest[] = -{ - 0x30, 0x21, /* top level sequence length 33 */ - 0x30, 0x09, /* algorithm ID, sequence length 9 */ - 0x06, 0x05, /* alg OID, length 5, SHA1 */ - 0x2b, 0x0e, 0x03, 0x02, 0x1a, - 0x05, 0x00, /* NULL parameters */ - 0x04, 0x14 /* integer length 20 */ - /* digest follows */ -}; - -DERReturn DEREncodeSHA1DigestInfo( - const DERByte *sha1Digest, - DERSize sha1DigestLen, - DERByte *result, /* encoded result RETURNED here */ - DERSize *resultLen) /* IN/OUT */ -{ - DERSize totalLen = sizeof(encodedSha1Digest) + DER_SHA1_DIGEST_LEN; - - if((sha1Digest == NULL) || (sha1DigestLen != DER_SHA1_DIGEST_LEN) || - (result == NULL) || (resultLen == NULL)) { - return DR_ParamErr; - } - if(*resultLen < DER_SHA1_DIGEST_INFO_LEN) { - return DR_BufOverflow; - } - DERMemmove(result, encodedSha1Digest, sizeof(encodedSha1Digest)); - DERMemmove(result + sizeof(encodedSha1Digest), sha1Digest, DER_SHA1_DIGEST_LEN); - *resultLen = totalLen; - return DR_Success; -} - -/* - joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) - csor(3) nistalgorithm(4) hashAlgs(2) sha256(1) - - future ones to add: sha384(2) sha512(3) sha224(4) -*/ -static const unsigned char encodedSha256Digest[] = -{ - 0x30, 0x31, /* top level sequence length 49 */ - 0x30, 0x0d, /* algorithm ID, sequence length 13 */ - 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, - 0x05, 0x00, /* NULL parameters */ - 0x04, 0x20 /* integer length 32 */ - /* digest follows */ -}; - -DERReturn DEREncodeSHA256DigestInfo( - const DERByte *sha256Digest, - DERSize sha256DigestLen, - DERByte *result, /* encoded result RETURNED here */ - DERSize *resultLen) /* IN/OUT */ -{ - DERSize totalLen = sizeof(encodedSha256Digest) + DER_SHA256_DIGEST_LEN; - - if((sha256Digest == NULL) || (sha256DigestLen != DER_SHA256_DIGEST_LEN) || - (result == NULL) || (resultLen == NULL)) { - return DR_ParamErr; - } - if(*resultLen < DER_SHA256_DIGEST_INFO_LEN) { - return DR_BufOverflow; - } - DERMemmove(result, encodedSha256Digest, sizeof(encodedSha256Digest)); - DERMemmove(result + sizeof(encodedSha256Digest), sha256Digest, DER_SHA256_DIGEST_LEN); - *resultLen = totalLen; - return DR_Success; -} - - -/* Same thing, MD5/MD2 */ -static const unsigned char encodedMdDigest[] = -{ - 0x30, 0x20, /* top level sequence length 32 */ - 0x30, 0x0c, /* algorithm ID, sequence length 12 */ - 0x06, 0x08, /* alg OID, length 8, MD2/MD5 */ - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, - 0x05, /* 5 = MD5, 2 = MD2 */ - 0x05, 0x00, /* NULL parameters */ - 0x04, 0x10 /* integer length 16 */ - /* digest follows */ -}; - -#define WHICH_DIGEST_INDEX 13 -#define WHICH_DIGEST_MD2 2 -#define WHICH_DIGEST_MD5 5 - -DERReturn DEREncodeMDDigestInfo( - WhichDigest whichDigest, - const DERByte *mdDigest, - DERSize mdDigestLen, - DERByte *result, /* encoded result RETURNED here */ - DERSize *resultLen) /* IN/OUT */ -{ - DERSize totalLen = sizeof(encodedMdDigest) + DER_MD_DIGEST_LEN; - - if((mdDigest == NULL) || (mdDigestLen != DER_MD_DIGEST_LEN) || - (result == NULL) || (resultLen == NULL)) { - return DR_ParamErr; - } - if(*resultLen < totalLen) { - return DR_BufOverflow; - } - DERMemmove(result, encodedMdDigest, sizeof(encodedMdDigest)); - DERMemmove(result + sizeof(encodedMdDigest), mdDigest, DER_MD_DIGEST_LEN); - switch(whichDigest) { - case WD_MD2: - result[WHICH_DIGEST_INDEX] = WHICH_DIGEST_MD2; - break; - case WD_MD5: - result[WHICH_DIGEST_INDEX] = WHICH_DIGEST_MD5; - break; - default: - return DR_ParamErr; - } - *resultLen = totalLen; - return DR_Success; -} diff --git a/libDER/libDER/DER_Digest.h b/libDER/libDER/DER_Digest.h deleted file mode 100644 index 734d752c..00000000 --- a/libDER/libDER/DER_Digest.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * DER_Digest.h - DER encode a DigestInfo - * - */ - -#ifndef _DER_DIGEST_H_ -#define _DER_DIGEST_H_ - -#include - -__BEGIN_DECLS - -/* - * Create an encoded DigestInfo based on the specified SHA1 digest. - * The incoming digest must be 20 bytes long. - * - * Result is placed in caller's buffer, which must be at least of - * length DER_SHA1_DIGEST_INFO_LEN bytes. - * - * The *resultLen parameter is the available size in the result - * buffer on input, and the actual length of the encoded DigestInfo - * on output. - */ -#define DER_SHA1_DIGEST_LEN 20 -#define DER_SHA1_DIGEST_INFO_LEN 35 - -DERReturn DEREncodeSHA1DigestInfo( - const DERByte *sha1Digest, - DERSize sha1DigestLen, - DERByte *result, /* encoded result RETURNED here */ - DERSize *resultLen); /* IN/OUT */ - -#define DER_SHA256_DIGEST_LEN 32 -#define DER_SHA256_DIGEST_INFO_LEN 51 - -DERReturn DEREncodeSHA256DigestInfo( - const DERByte *sha256Digest, - DERSize sha256DigestLen, - DERByte *result, /* encoded result RETURNED here */ - DERSize *resultLen); /* IN/OUT */ - -/* - * Likewise, create an encoded DIgestInfo for specified MD5 or MD2 digest. - */ -#define DER_MD_DIGEST_LEN 16 -#define DER_MD_DIGEST_INFO_LEN 34 - -typedef enum { - WD_MD2 = 1, - WD_MD5 = 2 -} WhichDigest; - -DERReturn DEREncodeMDDigestInfo( - WhichDigest whichDigest, - const DERByte *mdDigest, - DERSize mdDigestLen, - DERByte *result, /* encoded result RETURNED here */ - DERSize *resultLen); /* IN/OUT */ - -/* max sizes you'll need in the general cases */ -#define DER_MAX_DIGEST_LEN DER_SHA256_DIGEST_LEN -#define DER_MAX_ENCODED_INFO_LEN DER_SHA256_DIGEST_INFO_LEN - -__END_DECLS - -#endif /* _DER_DIGEST_H_ */ - diff --git a/libDER/libDER/DER_Encode.c b/libDER/libDER/DER_Encode.c deleted file mode 100644 index bd8e607a..00000000 --- a/libDER/libDER/DER_Encode.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * DER_Encode.h - DER encoding routines - * - */ - -#include -#include -#include -#include - -#ifndef DER_ENCODE_ENABLE -#error Please define DER_ENCODE_ENABLE. -#endif - -#if DER_ENCODE_ENABLE - -/* calculate size of encoded tag */ -static DERSize DERLengthOfTag( - DERTag tag) -{ - DERSize rtn = 1; - - tag &= ASN1_TAGNUM_MASK; - if (tag >= 0x1F) { - /* Shift 7-bit digits out of the tag integer until it's zero. */ - while(tag != 0) { - rtn++; - tag >>= 7; - } - } - - return rtn; -} - -/* encode tag */ -static DERReturn DEREncodeTag( - DERTag tag, - DERByte *buf, /* encoded length goes here */ - DERSize *inOutLen) /* IN/OUT */ -{ - DERSize outLen = DERLengthOfTag(tag); - DERTag tagNumber = tag & ASN1_TAGNUM_MASK; - DERByte tag1 = (tag >> (sizeof(DERTag) * 8 - 8)) & 0xE0; - - if(outLen > *inOutLen) { - return DR_BufOverflow; - } - - if(outLen == 1) { - /* short form */ - *buf = (DERByte)(tag1 | tagNumber); - } - else { - /* long form */ - DERByte *tagBytes = buf + outLen; // l.s. digit of tag - *buf = tag1 | 0x1F; // tag class / method indicator - *--tagBytes = tagNumber & 0x7F; - tagNumber >>= 7; - while(tagNumber != 0) { - *--tagBytes = (tagNumber & 0x7F) | 0x80; - tagNumber >>= 7; - } - } - *inOutLen = outLen; - return DR_Success; -} - -/* calculate size of encoded length */ -DERSize DERLengthOfLength( - DERSize length) -{ - DERSize rtn; - - if(length < 0x80) { - /* short form length */ - return 1; - } - - /* long form - one length-of-length byte plus length bytes */ - rtn = 1; - while(length != 0) { - rtn++; - length >>= 8; - } - return rtn; -} - -/* encode length */ -DERReturn DEREncodeLength( - DERSize length, - DERByte *buf, /* encoded length goes here */ - DERSize *inOutLen) /* IN/OUT */ -{ - DERByte *lenBytes; - DERSize outLen = DERLengthOfLength(length); - - if(outLen > *inOutLen) { - return DR_BufOverflow; - } - - if(length < 0x80) { - /* short form */ - *buf = (DERByte)length; - *inOutLen = 1; - return DR_Success; - } - - /* long form */ - *buf = (outLen - 1) | 0x80; // length of length, long form indicator - lenBytes = buf + outLen - 1; // l.s. digit of length - while(length != 0) { - *lenBytes-- = (DERByte)length; - length >>= 8; - } - *inOutLen = outLen; - return DR_Success; -} - -DERSize DERLengthOfItem( - DERTag tag, - DERSize length) -{ - return DERLengthOfTag(tag) + DERLengthOfLength(length) + length; -} - -DERReturn DEREncodeItem( - DERTag tag, - DERSize length, - const DERByte *src, - DERByte *derOut, /* encoded item goes here */ - DERSize *inOutLen) /* IN/OUT */ -{ - DERReturn drtn; - DERSize itemLen; - DERByte *currPtr = derOut; - DERSize bytesLeft = DERLengthOfItem(tag, length); - if(bytesLeft > *inOutLen) { - return DR_BufOverflow; - } - *inOutLen = bytesLeft; - - /* top level tag */ - itemLen = bytesLeft; - drtn = DEREncodeTag(tag, currPtr, &itemLen); - if(drtn) { - return drtn; - } - currPtr += itemLen; - bytesLeft -= itemLen; - itemLen = bytesLeft; - drtn = DEREncodeLength(length, currPtr, &itemLen); - if(drtn) { - return drtn; - } - currPtr += itemLen; - bytesLeft -= itemLen; - DERMemmove(currPtr, src, length); - - // Silence unused variable warning. - (void) bytesLeft; - - return DR_Success; -} - -static /* calculate the content length of an encoded sequence */ -DERSize DERContentLengthOfEncodedSequence( - const void *src, /* generally a ptr to a struct full of - * DERItems */ - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs) -{ - DERSize contentLen = 0; - unsigned dex; - DERSize thisContentLen; - - /* find length of each item */ - for(dex=0; dexoptions; - const DERByte *byteSrc = (const DERByte *)src + currItemSpec->offset; - const DERItem *itemSrc = (const DERItem *)byteSrc; - - if(currOptions & DER_ENC_WRITE_DER) { - /* easy case - no encode */ - contentLen += itemSrc->length; - continue; - } - - if ((currOptions & DER_DEC_OPTIONAL) && itemSrc->length == 0) { - /* If an optional item isn't present we don't encode a - tag and len. */ - continue; - } - - /* - * length of this item = - * tag (one byte) + - * length of length + - * content length + - * optional zero byte for signed integer - */ - contentLen += DERLengthOfTag(currItemSpec->tag); - - /* check need for pad byte before calculating lengthOfLength... */ - thisContentLen = itemSrc->length; - if((currOptions & DER_ENC_SIGNED_INT) && - (itemSrc->length != 0)) { - if(itemSrc->data[0] & 0x80) { - /* insert zero keep it positive */ - thisContentLen++; - } - } - contentLen += DERLengthOfLength(thisContentLen); - contentLen += thisContentLen; - } - return contentLen; -} - -DERReturn DEREncodeSequence( - DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */ - const void *src, /* generally a ptr to a struct full of - * DERItems */ - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs, - DERByte *derOut, /* encoded data written here */ - DERSize *inOutLen) /* IN/OUT */ -{ - const DERByte *endPtr = derOut + *inOutLen; - DERByte *currPtr = derOut; - DERSize bytesLeft = *inOutLen; - DERSize contentLen; - DERReturn drtn; - DERSize itemLen; - unsigned dex; - - /* top level tag */ - itemLen = bytesLeft; - drtn = DEREncodeTag(topTag, currPtr, &itemLen); - if(drtn) { - return drtn; - } - currPtr += itemLen; - bytesLeft -= itemLen; - if(currPtr >= endPtr) { - return DR_BufOverflow; - } - - /* content length */ - contentLen = DERContentLengthOfEncodedSequence(src, numItems, itemSpecs); - itemLen = bytesLeft; - drtn = DEREncodeLength(contentLen, currPtr, &itemLen); - if(drtn) { - return drtn; - } - currPtr += itemLen; - bytesLeft -= itemLen; - if(currPtr + contentLen > endPtr) { - return DR_BufOverflow; - } - /* we don't have to check for overflow any more */ - - /* grind thru the items */ - for(dex=0; dexoptions; - const DERByte *byteSrc = (const DERByte *)src + currItemSpec->offset; - const DERItem *itemSrc = (const DERItem *)byteSrc; - int prependZero = 0; - - if(currOptions & DER_ENC_WRITE_DER) { - /* easy case */ - DERMemmove(currPtr, itemSrc->data, itemSrc->length); - currPtr += itemSrc->length; - bytesLeft -= itemSrc->length; - continue; - } - - if ((currOptions & DER_DEC_OPTIONAL) && itemSrc->length == 0) { - /* If an optional item isn't present we skip it. */ - continue; - } - - /* encode one item: first the tag */ - itemLen = bytesLeft; - drtn = DEREncodeTag(currItemSpec->tag, currPtr, &itemLen); - if(drtn) { - return drtn; - } - currPtr += itemLen; - bytesLeft -= itemLen; - - /* do we need to prepend a zero to content? */ - contentLen = itemSrc->length; - if((currOptions & DER_ENC_SIGNED_INT) && - (itemSrc->length != 0)) { - if(itemSrc->data[0] & 0x80) { - /* insert zero keep it positive */ - contentLen++; - prependZero = 1; - } - } - - /* encode content length */ - itemLen = bytesLeft; - drtn = DEREncodeLength(contentLen, currPtr, &itemLen); - if(drtn) { - return drtn; - } - currPtr += itemLen; - bytesLeft -= itemLen; - - /* now the content, with possible leading zero added */ - if(prependZero) { - *currPtr++ = 0; - bytesLeft--; - } - DERMemmove(currPtr, itemSrc->data, itemSrc->length); - currPtr += itemSrc->length; - bytesLeft -= itemSrc->length; - } - *inOutLen = (DERSize)(currPtr - derOut); - return DR_Success; -} - -/* calculate the length of an encoded sequence. */ -DERSize DERLengthOfEncodedSequence( - DERTag topTag, - const void *src, /* generally a ptr to a struct full of - * DERItems */ - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs) -{ - DERSize contentLen = DERContentLengthOfEncodedSequence( - src, numItems, itemSpecs); - - return DERLengthOfTag(topTag) + - DERLengthOfLength(contentLen) + - contentLen; -} - -#endif /* DER_ENCODE_ENABLE */ - diff --git a/libDER/libDER/DER_Encode.h b/libDER/libDER/DER_Encode.h deleted file mode 100644 index bcde9757..00000000 --- a/libDER/libDER/DER_Encode.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * DER_Encode.h - DER encoding routines - * - */ - -#ifndef _DER_ENCODE_H_ -#define _DER_ENCODE_H_ - -#include - -__BEGIN_DECLS - -/* - * Max size of an encoded item given its length. - * This includes a possible leading zero prepended to a signed integer - * (see DER_ENC_SIGNED_INT below). - */ -#define DER_MAX_ENCODED_SIZE(len) \ - ( 1 + /* tag */ \ - 5 + /* max length */ \ - 1 + /* possible prepended zero */ \ - len) - -/* calculate size of encoded length */ -DERSize DERLengthOfLength( - DERSize length); - -/* encode length */ -DERReturn DEREncodeLength( - DERSize length, - DERByte *buf, /* encoded length goes here */ - DERSize *inOutLen); /* IN/OUT */ - -/* calculate size of encoded length */ -DERSize DERLengthOfItem( - DERTag tag, - DERSize length); - -/* encode item */ -DERReturn DEREncodeItem( - DERTag tag, - DERSize length, - const DERByte *src, - DERByte *derOut, /* encoded item goes here */ - DERSize *inOutLen); /* IN/OUT */ - -/* - * Per-item encode options. - */ - -/* explicit default, no options */ -#define DER_ENC_NO_OPTS 0x0000 - -/* signed integer check: if incoming m.s. bit is 1, prepend a zero */ -#define DER_ENC_SIGNED_INT 0x0100 - -/* DERItem contains fully encoded item - copy, don't encode */ -#define DER_ENC_WRITE_DER 0x0200 - - -/* - * High-level sequence or set encode support. - * - * The outgoing sequence is expressed as an array of DERItemSpecs, each - * of which corresponds to one item in the encoded sequence. - * - * Normally the tag of the encoded item comes from the associated - * DERItemSpec, and the content comes from the DERItem whose address is - * the src arg plus the offset value in the associated DERItemSpec. - * - * If the DER_ENC_WRITE_DER option is true for a given DERItemSpec then - * no per-item encoding is done; the DER - with tag, length, and content - - * is taken en masse from the associated DERItem. - */ -DERReturn DEREncodeSequence( - DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */ - const void *src, /* generally a ptr to a struct full of - * DERItems */ - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs, - DERByte *derOut, /* encoded data written here */ - DERSize *inOutLen); /* IN/OUT */ - -/* precalculate the length of an encoded sequence. */ -DERSize DERLengthOfEncodedSequence( - DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */ - const void *src, /* generally a ptr to a struct full of - * DERItems */ - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs); - - -__END_DECLS - -#endif /* _DER_ENCODE_H_ */ diff --git a/libDER/libDER/DER_Keys.c b/libDER/libDER/DER_Keys.c deleted file mode 100644 index 0d41496f..00000000 --- a/libDER/libDER/DER_Keys.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * DER_Cert.c - support for decoding RSA keys - * - */ - -#include -#include -#include -#include -#include - -#ifndef DER_DECODE_ENABLE -#error Please define DER_DECODE_ENABLE. -#endif -#if DER_DECODE_ENABLE - -/* - * DERItemSpecs for decoding RSA keys. - */ - -/* Algorithm Identifier */ -const DERItemSpec DERAlgorithmIdItemSpecs[] = -{ - { DER_OFFSET(DERAlgorithmId, oid), - ASN1_OBJECT_ID, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERAlgorithmId, params), - 0, /* no tag - any */ - DER_DEC_ASN_ANY | DER_DEC_OPTIONAL | DER_DEC_SAVE_DER } -}; -const DERSize DERNumAlgorithmIdItemSpecs = - sizeof(DERAlgorithmIdItemSpecs) / sizeof(DERItemSpec); - -/* X509 SubjectPublicKeyInfo */ -const DERItemSpec DERSubjPubKeyInfoItemSpecs[] = -{ - { DER_OFFSET(DERSubjPubKeyInfo, algId), - ASN1_CONSTR_SEQUENCE, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERSubjPubKeyInfo, pubKey), - ASN1_BIT_STRING, - DER_DEC_NO_OPTS }, - -}; -const DERSize DERNumSubjPubKeyInfoItemSpecs = - sizeof(DERSubjPubKeyInfoItemSpecs) / sizeof(DERItemSpec); - -/* - * RSA private key in CRT format - */ -const DERItemSpec DERRSAPrivKeyCRTItemSpecs[] = -{ - /* version, n, e, d - skip */ - { 0, - ASN1_INTEGER, - DER_DEC_SKIP }, - { 0, - ASN1_INTEGER, - DER_DEC_SKIP }, - { 0, - ASN1_INTEGER, - DER_DEC_SKIP }, - { 0, - ASN1_INTEGER, - DER_DEC_SKIP }, - { DER_OFFSET(DERRSAPrivKeyCRT, p), - ASN1_INTEGER, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERRSAPrivKeyCRT, q), - ASN1_INTEGER, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERRSAPrivKeyCRT, dp), - ASN1_INTEGER, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERRSAPrivKeyCRT, dq), - ASN1_INTEGER, - DER_DEC_NO_OPTS }, - { DER_OFFSET(DERRSAPrivKeyCRT, qInv), - ASN1_INTEGER, - DER_DEC_NO_OPTS }, - /* ignore the (optional) rest */ -}; -const DERSize DERNumRSAPrivKeyCRTItemSpecs = - sizeof(DERRSAPrivKeyCRTItemSpecs) / sizeof(DERItemSpec); - -#endif /* DER_DECODE_ENABLE */ - -#if DER_DECODE_ENABLE || DER_ENCODE_ENABLE - -/* RSA public key in PKCS1 format - encode and decode */ -const DERItemSpec DERRSAPubKeyPKCS1ItemSpecs[] = -{ - { DER_OFFSET(DERRSAPubKeyPKCS1, modulus), - ASN1_INTEGER, - DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAPubKeyPKCS1, pubExponent), - ASN1_INTEGER, - DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, -}; -const DERSize DERNumRSAPubKeyPKCS1ItemSpecs = - sizeof(DERRSAPubKeyPKCS1ItemSpecs) / sizeof(DERItemSpec); - -/* RSA public key in Apple custome format with reciprocal - encode and decode */ -const DERItemSpec DERRSAPubKeyAppleItemSpecs[] = -{ - { DER_OFFSET(DERRSAPubKeyApple, modulus), - ASN1_INTEGER, - DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAPubKeyApple, reciprocal), - ASN1_INTEGER, - DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAPubKeyApple, pubExponent), - ASN1_INTEGER, - DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, -}; -const DERSize DERNumRSAPubKeyAppleItemSpecs = - sizeof(DERRSAPubKeyAppleItemSpecs) / sizeof(DERItemSpec); - - -#endif /* DER_DECODE_ENABLE || DER_ENCODE_ENABLE */ - -#ifndef DER_ENCODE_ENABLE -#error Please define DER_ENCODE_ENABLE. -#endif - -#if DER_ENCODE_ENABLE - -/* RSA Key Pair, encode only */ -const DERItemSpec DERRSAKeyPairItemSpecs[] = -{ - { DER_OFFSET(DERRSAKeyPair, version), - ASN1_INTEGER, - DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAKeyPair, n), - ASN1_INTEGER, - DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAKeyPair, e), - ASN1_INTEGER, - DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAKeyPair, d), - ASN1_INTEGER, - DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAKeyPair, p), - ASN1_INTEGER, - DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAKeyPair, q), - ASN1_INTEGER, - DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAKeyPair, dp), - ASN1_INTEGER, - DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAKeyPair, dq), - ASN1_INTEGER, - DER_ENC_SIGNED_INT }, - { DER_OFFSET(DERRSAKeyPair, qInv), - ASN1_INTEGER, - DER_ENC_SIGNED_INT }, -}; - -const DERSize DERNumRSAKeyPairItemSpecs = - sizeof(DERRSAKeyPairItemSpecs) / sizeof(DERItemSpec); - -#endif /* DER_ENCODE_ENABLE */ - diff --git a/libDER/libDER/DER_Keys.h b/libDER/libDER/DER_Keys.h deleted file mode 100644 index 41f24d67..00000000 --- a/libDER/libDER/DER_Keys.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * DER_Keys.h - support for decoding RSA keys - * - */ - -#ifndef _DER_KEYS_H_ -#define _DER_KEYS_H_ - -#include -#include - -__BEGIN_DECLS - -/* Algorithm Identifier components */ -typedef struct { - DERItem oid; /* OID */ - DERItem params; /* ASN_ANY, optional, DER_DEC_SAVE_DER */ -} DERAlgorithmId; - -/* DERItemSpecs to decode into a DERAlgorithmId */ -extern const DERItemSpec DERAlgorithmIdItemSpecs[]; -extern const DERSize DERNumAlgorithmIdItemSpecs; - -/* X509 SubjectPublicKeyInfo */ -typedef struct { - DERItem algId; /* sequence, DERAlgorithmId */ - DERItem pubKey; /* BIT STRING */ -} DERSubjPubKeyInfo; - -/* DERItemSpecs to decode into a DERSubjPubKeyInfo */ -extern const DERItemSpec DERSubjPubKeyInfoItemSpecs[]; -extern const DERSize DERNumSubjPubKeyInfoItemSpecs; - -/* - * RSA public key in PKCS1 format; this is inside the BIT_STRING in - * DERSubjPubKeyInfo.pubKey. - */ -typedef struct { - DERItem modulus; /* n - INTEGER */ - DERItem pubExponent; /* e - INTEGER */ -} DERRSAPubKeyPKCS1; - -/* DERItemSpecs to decode/encode into/from a DERRSAPubKeyPKCS1 */ -extern const DERItemSpec DERRSAPubKeyPKCS1ItemSpecs[]; -extern const DERSize DERNumRSAPubKeyPKCS1ItemSpecs; - -/* - * RSA public key in custom (to this library) format, including - * the reciprocal. All fields are integers. - */ -typedef struct { - DERItem modulus; /* n */ - DERItem reciprocal; /* reciprocal of modulus */ - DERItem pubExponent; /* e */ -} DERRSAPubKeyApple; - -/* DERItemSpecs to decode/encode into/from a DERRSAPubKeyApple */ -extern const DERItemSpec DERRSAPubKeyAppleItemSpecs[]; -extern const DERSize DERNumRSAPubKeyAppleItemSpecs; - -/* - * RSA Private key, PKCS1 format, CRT option. - * All fields are integers. - */ -typedef struct { - DERItem p; /* p * q = n */ - DERItem q; - DERItem dp; /* d mod (p-1) */ - DERItem dq; /* d mod (q-1) */ - DERItem qInv; -} DERRSAPrivKeyCRT; - -/* DERItemSpecs to decode into a DERRSAPrivKeyCRT */ -extern const DERItemSpec DERRSAPrivKeyCRTItemSpecs[]; -extern const DERSize DERNumRSAPrivKeyCRTItemSpecs; - -/* Fully formed RSA key pair, for generating a PKCS1 private key */ -typedef struct { - DERItem version; - DERItem n; /* modulus */ - DERItem e; /* public exponent */ - DERItem d; /* private exponent */ - DERItem p; /* n = p*q */ - DERItem q; - DERItem dp; /* d mod (p-1) */ - DERItem dq; /* d mod (q-1) */ - DERItem qInv; /* q^(-1) mod p */ -} DERRSAKeyPair; - -/* DERItemSpecs to encode a DERRSAKeyPair */ -extern const DERItemSpec DERRSAKeyPairItemSpecs[]; -extern const DERSize DERNumRSAKeyPairItemSpecs; - -__END_DECLS - -#endif /* _DER_KEYS_H_ */ - diff --git a/libDER/libDER/asn1Types.h b/libDER/libDER/asn1Types.h deleted file mode 100644 index db992d79..00000000 --- a/libDER/libDER/asn1Types.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * asn1Types.h - ASN.1/DER #defines - strictly hard coded per the real world - * - */ - -#ifndef _ASN1_TYPES_H_ -#define _ASN1_TYPES_H_ - -#if !defined(__WIN32__) -#include -#endif - -#include - -__BEGIN_DECLS - -/* copied from libsecurity_asn1 project */ - -/* Type tag numbers */ -#define ASN1_BOOLEAN 0x01 -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_OCTET_STRING 0x04 -#define ASN1_NULL 0x05 -#define ASN1_OBJECT_ID 0x06 -#define ASN1_OBJECT_DESCRIPTOR 0x07 -/* External type and instance-of type 0x08 */ -#define ASN1_REAL 0x09 -#define ASN1_ENUMERATED 0x0a -#define ASN1_EMBEDDED_PDV 0x0b -#define ASN1_UTF8_STRING 0x0c -/* 0x0d */ -/* 0x0e */ -/* 0x0f */ -#define ASN1_SEQUENCE 0x10 -#define ASN1_SET 0x11 -#define ASN1_NUMERIC_STRING 0x12 -#define ASN1_PRINTABLE_STRING 0x13 -#define ASN1_T61_STRING 0x14 -#define ASN1_VIDEOTEX_STRING 0x15 -#define ASN1_IA5_STRING 0x16 -#define ASN1_UTC_TIME 0x17 -#define ASN1_GENERALIZED_TIME 0x18 -#define ASN1_GRAPHIC_STRING 0x19 -#define ASN1_VISIBLE_STRING 0x1a -#define ASN1_GENERAL_STRING 0x1b -#define ASN1_UNIVERSAL_STRING 0x1c -/* 0x1d */ -#define ASN1_BMP_STRING 0x1e -#define ASN1_HIGH_TAG_NUMBER 0x1f -#define ASN1_TELETEX_STRING ASN1_T61_STRING - -/* Tag modifiers */ -#define ASN1_TAG_MASK ((DERTag)~0) -#define ASN1_TAGNUM_MASK ((DERTag)~((DERTag)7 << (sizeof(DERTag) * 8 - 3))) - -#define ASN1_METHOD_MASK ((DERTag)1 << (sizeof(DERTag) * 8 - 3)) -#define ASN1_PRIMITIVE ((DERTag)0 << (sizeof(DERTag) * 8 - 3)) -#define ASN1_CONSTRUCTED ((DERTag)1 << (sizeof(DERTag) * 8 - 3)) - -#define ASN1_CLASS_MASK ((DERTag)3 << (sizeof(DERTag) * 8 - 2)) -#define ASN1_UNIVERSAL ((DERTag)0 << (sizeof(DERTag) * 8 - 2)) -#define ASN1_APPLICATION ((DERTag)1 << (sizeof(DERTag) * 8 - 2)) -#define ASN1_CONTEXT_SPECIFIC ((DERTag)2 << (sizeof(DERTag) * 8 - 2)) -#define ASN1_PRIVATE ((DERTag)3 << (sizeof(DERTag) * 8 - 2)) - -/* One-byte tag modifiers */ -#define ONE_BYTE_ASN1_TAG_MASK 0xff -#define ONE_BYTE_ASN1_TAGNUM_MASK 0x1f -#define ONE_BYTE_ASN1_METHOD_MASK 0x20 -#define ONE_BYTE_ASN1_PRIMITIVE 0x00 -#define ONE_BYTE_ASN1_CONSTRUCTED 0x20 - -#define ONE_BYTE_ASN1_CLASS_MASK 0xc0 -#define ONE_BYTE_ASN1_UNIVERSAL 0x00 -#define ONE_BYTE_ASN1_APPLICATION 0x40 -#define ONE_BYTE_ASN1_CONTEXT_SPECIFIC 0x80 -#define ONE_BYTE_ASN1_PRIVATE 0xc0 - -/* sequence and set appear as the following */ -#define ASN1_CONSTR_SEQUENCE ((DERTag)(ASN1_CONSTRUCTED | ASN1_SEQUENCE)) -#define ASN1_CONSTR_SET ((DERTag)(ASN1_CONSTRUCTED | ASN1_SET)) - -#define ONE_BYTE_ASN1_CONSTR_SEQUENCE ((uint8_t)(ONE_BYTE_ASN1_CONSTRUCTED | ASN1_SEQUENCE)) -#define ONE_BYTE_ASN1_CONSTR_SET ((uint8_t)(ONE_BYTE_ASN1_CONSTRUCTED | ASN1_SET)) - -__END_DECLS - -#endif /* _ASN1_TYPES_H_ */ diff --git a/libDER/libDER/libDER.h b/libDER/libDER/libDER.h deleted file mode 100644 index e5e4b127..00000000 --- a/libDER/libDER/libDER.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * libDER.h - main header for libDER, a ROM-capable DER decoding library. - * - */ - -#ifndef _LIB_DER_H_ -#define _LIB_DER_H_ - -#include - -__BEGIN_DECLS - -/* - * Error returns generated by this library. - */ -typedef enum { - DR_Success = 0, - DR_EndOfSequence, /* end of sequence or set */ - DR_UnexpectedTag, /* unexpected tag found while decoding */ - DR_DecodeError, /* misc. decoding error (badly formatted DER) */ - DR_Unimplemented, /* function not implemented in this configuration */ - DR_IncompleteSeq, /* incomplete sequence */ - DR_ParamErr, /* incoming parameter error */ - DR_BufOverflow /* buffer overflow */ - /* etc. */ -} DERReturn; - -/* - * The structure of a sequence during decode or encode is expressed as - * an array of DERItemSpecs. While decoding or encoding a sequence, - * each item in the sequence corresponds to one DERItemSpec. - */ -typedef struct { - DERSize offset; /* offset of destination DERItem */ - DERTag tag; /* DER tag */ - DERShort options; /* DER_DEC_xxx or DER_ENC_xxx */ -} DERItemSpec; - -/* - * Macro to obtain offset of a DERDecodedInfo within a struct. - * FIXME this is going to need reworking to avoid compiler warnings - * on 64-bit compiles. It'll work OK as long as an offset can't be larger - * than a DERSize, but the cast from a pointer to a DERSize may - * provoke compiler warnings. - */ -#define DER_OFFSET(type, field) ((DERSize)(&((type *)0)->field)) - -__END_DECLS - -#endif /* _LIB_DER_H_ */ - diff --git a/libDER/libDER/libDER_config.h b/libDER/libDER/libDER_config.h deleted file mode 100644 index 6280ee3f..00000000 --- a/libDER/libDER/libDER_config.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2005-2007,2011-2012,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * libDER_config.h - platform dependent #defines and typedefs for libDER - * - */ - -#ifndef _LIB_DER_CONFIG_H_ -#define _LIB_DER_CONFIG_H_ - -#include -#include - -/* include defintion of DERSize and DERByte */ -#include "libDER/oids.h" - -__BEGIN_DECLS - -/* - * Basic data types: unsigned 8-bit integer, unsigned 32-bit integer - */ -typedef uint16_t DERShort; - - -/* - * Use these #defines of you have memset, memmove, and memcmp; else - * write your own equivalents. - */ - -#define DERMemset(ptr, c, len) memset(ptr, c, len) -#define DERMemmove(dst, src, len) memmove(dst, src, len) -#define DERMemcmp(b1, b2, len) memcmp(b1, b2, len) - - -/*** - *** Compile time options to trim size of the library. - ***/ - -/* enable general DER encode */ -#define DER_ENCODE_ENABLE 1 - -/* enable general DER decode */ -#define DER_DECODE_ENABLE 1 - -#ifndef DER_MULTIBYTE_TAGS -/* enable multibyte tag support. */ -#define DER_MULTIBYTE_TAGS 1 -#endif - -#ifndef DER_TAG_SIZE -/* Iff DER_MULTIBYTE_TAGS is 1 this is the sizeof(DERTag) in bytes. Note that - tags are still encoded and decoded from a minimally encoded DER - represantation. This value maintains compatibility with libImg4Decode/Encode. */ -#define DER_TAG_SIZE 8 -#endif - - -/* ---------------------- Do not edit below this line ---------------------- */ - -/* - * Logical representation of a tag (the encoded representation is always in - * the minimal number of bytes). The top 3 bits encode class and method - * The remaining bits encode the tag value. To obtain smaller DERItemSpecs - * sizes, choose the smallest type that fits your needs. Most standard ASN.1 - * usage only needs single byte tags, but ocasionally custom applications - * require a larger tag namespace. - */ -#if DER_MULTIBYTE_TAGS - -#if DER_TAG_SIZE == 1 -typedef uint8_t DERTag; -#elif DER_TAG_SIZE == 2 -typedef uint16_t DERTag; -#elif DER_TAG_SIZE == 4 -typedef uint32_t DERTag; -#elif DER_TAG_SIZE == 8 -typedef uint64_t DERTag; -#else -#error DER_TAG_SIZE invalid -#endif - -#else /* DER_MULTIBYTE_TAGS */ -typedef DERByte DERTag; -#endif /* !DER_MULTIBYTE_TAGS */ - -__END_DECLS - -#endif /* _LIB_DER_CONFIG_H_ */ diff --git a/libDER/libDER/module.modulemap b/libDER/libDER/module.modulemap deleted file mode 100644 index af2d15b0..00000000 --- a/libDER/libDER/module.modulemap +++ /dev/null @@ -1,3 +0,0 @@ -module libDER [extern_c] { - header "libDER.h" -} diff --git a/libDER/libDER/oids.c b/libDER/libDER/oids.c deleted file mode 100644 index cc7899d9..00000000 --- a/libDER/libDER/oids.c +++ /dev/null @@ -1,856 +0,0 @@ -/* - * Copyright (c) 2005-2009,2011-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * oids.c - OID consts - * - */ - -#include -#include - -#define OID_ISO_CCITT_DIR_SERVICE 85 -#define OID_DS OID_ISO_CCITT_DIR_SERVICE -#define OID_ATTR_TYPE OID_DS, 4 -#define OID_EXTENSION OID_DS, 29 -#define OID_ISO_STANDARD 40 -#define OID_ISO_MEMBER 42 -#define OID_US OID_ISO_MEMBER, 134, 72 - -#define OID_ISO_IDENTIFIED_ORG 43 -#define OID_OSINET OID_ISO_IDENTIFIED_ORG, 4 -#define OID_GOSIP OID_ISO_IDENTIFIED_ORG, 5 -#define OID_DOD OID_ISO_IDENTIFIED_ORG, 6 -#define OID_OIW OID_ISO_IDENTIFIED_ORG, 14 - -/* From the PKCS Standards */ -#define OID_RSA OID_US, 134, 247, 13 -#define OID_RSA_HASH OID_RSA, 2 -#define OID_RSA_ENCRYPT OID_RSA, 3 -#define OID_PKCS OID_RSA, 1 -#define OID_PKCS_1 OID_PKCS, 1 -#define OID_PKCS_2 OID_PKCS, 2 -#define OID_PKCS_3 OID_PKCS, 3 -#define OID_PKCS_4 OID_PKCS, 4 -#define OID_PKCS_5 OID_PKCS, 5 -#define OID_PKCS_6 OID_PKCS, 6 -#define OID_PKCS_7 OID_PKCS, 7 -#define OID_PKCS_8 OID_PKCS, 8 -#define OID_PKCS_9 OID_PKCS, 9 -#define OID_PKCS_10 OID_PKCS, 10 -#define OID_PKCS_11 OID_PKCS, 11 -#define OID_PKCS_12 OID_PKCS, 12 - -/* ANSI X9.62 */ -#define OID_ANSI_X9_62 OID_US, 206, 61 -#define OID_PUBLIC_KEY_TYPE OID_ANSI_X9_62, 2 -#define OID_EC_CURVE OID_ANSI_X9_62, 3, 1 -#define OID_EC_SIG_TYPE OID_ANSI_X9_62, 4 -#define OID_ECDSA_WITH_SHA2 OID_EC_SIG_TYPE, 3 - -/* Certicom */ -#define OID_CERTICOM OID_ISO_IDENTIFIED_ORG, 132 -#define OID_CERTICOM_EC_CURVE OID_CERTICOM, 0 - -/* ANSI X9.42 */ -#define OID_ANSI_X9_42 OID_US, 206, 62, 2 -#define OID_ANSI_X9_42_SCHEME OID_ANSI_X9_42, 3 -#define OID_ANSI_X9_42_NAMED_SCHEME OID_ANSI_X9_42, 4 - -/* ANSI X9.57 */ -#define OID_ANSI_X9_57 OID_US, 206, 56 -#define OID_ANSI_X9_57_ALGORITHM OID_ANSI_X9_57, 4 - -/* DOD IANA Security related objects. */ -#define OID_IANA OID_DOD, 1, 5 - -/* Kerberos PKINIT */ -#define OID_KERBv5 OID_IANA, 2 -#define OID_KERBv5_PKINIT OID_KERBv5, 3 - -/* DOD IANA Mechanisms. */ -#define OID_MECHANISMS OID_IANA, 5 - -/* PKIX */ -#define OID_PKIX OID_MECHANISMS, 7 -#define OID_PE OID_PKIX, 1 -#define OID_QT OID_PKIX, 2 -#define OID_KP OID_PKIX, 3 -#define OID_OTHER_NAME OID_PKIX, 8 -#define OID_PDA OID_PKIX, 9 -#define OID_QCS OID_PKIX, 11 -#define OID_AD OID_PKIX, 48 -#define OID_AD_OCSP OID_AD, 1 -#define OID_AD_CAISSUERS OID_AD, 2 - -/* ISAKMP */ -#define OID_ISAKMP OID_MECHANISMS, 8 - -/* ETSI */ -#define OID_ETSI 0x04, 0x00 -#define OID_ETSI_QCS 0x04, 0x00, 0x8E, 0x46, 0x01 - -#define OID_OIW_SECSIG OID_OIW, 3 - -#define OID_OIW_ALGORITHM OID_OIW_SECSIG, 2 - -/* NIST defined digest algorithm arc (2, 16, 840, 1, 101, 3, 4, 2) */ -#define OID_NIST_HASHALG 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02 - -/* - * Apple-specific OID bases - */ - -/* - * apple OBJECT IDENTIFIER ::= - * { iso(1) member-body(2) US(840) 113635 } - * - * BER = 06 06 2A 86 48 86 F7 63 - */ -#define APPLE_OID OID_US, 0x86, 0xf7, 0x63 - -/* appleDataSecurity OBJECT IDENTIFIER ::= - * { apple 100 } - * { 1 2 840 113635 100 } - * - * BER = 06 07 2A 86 48 86 F7 63 64 - */ -#define APPLE_ADS_OID APPLE_OID, 0x64 - -/* - * appleTrustPolicy OBJECT IDENTIFIER ::= - * { appleDataSecurity 1 } - * { 1 2 840 113635 100 1 } - * - * BER = 06 08 2A 86 48 86 F7 63 64 01 - */ -#define APPLE_TP_OID APPLE_ADS_OID, 1 - -/* - * appleSecurityAlgorithm OBJECT IDENTIFIER ::= - * { appleDataSecurity 2 } - * { 1 2 840 113635 100 2 } - * - * BER = 06 08 2A 86 48 86 F7 63 64 02 - */ -#define APPLE_ALG_OID APPLE_ADS_OID, 2 - -/* - * appleDotMacCertificate OBJECT IDENTIFIER ::= - * { appleDataSecurity 3 } - * { 1 2 840 113635 100 3 } - */ -#define APPLE_DOTMAC_CERT_OID APPLE_ADS_OID, 3 - -/* - * Basis of Policy OIDs for .mac TP requests - * - * dotMacCertificateRequest OBJECT IDENTIFIER ::= - * { appleDotMacCertificate 1 } - * { 1 2 840 113635 100 3 1 } - */ -#define APPLE_DOTMAC_CERT_REQ_OID APPLE_DOTMAC_CERT_OID, 1 - -/* - * Basis of .mac Certificate Extensions - * - * dotMacCertificateExtension OBJECT IDENTIFIER ::= - * { appleDotMacCertificate 2 } - * { 1 2 840 113635 100 3 2 } - */ -#define APPLE_DOTMAC_CERT_EXTEN_OID APPLE_DOTMAC_CERT_OID, 2 - -/* - * Basis of .mac Certificate request OID/value identitifiers - * - * dotMacCertificateRequestValues OBJECT IDENTIFIER ::= - * { appleDotMacCertificate 3 } - * { 1 2 840 113635 100 3 3 } - */ -#define APPLE_DOTMAC_CERT_REQ_VALUE_OID APPLE_DOTMAC_CERT_OID, 3 - -/* - * Basis of Apple-specific extended key usages - * - * appleExtendedKeyUsage OBJECT IDENTIFIER ::= - * { appleDataSecurity 4 } - * { 1 2 840 113635 100 4 } - */ -#define APPLE_EKU_OID APPLE_ADS_OID, 4 - -/* - * Basis of Apple Code Signing extended key usages - * appleCodeSigning OBJECT IDENTIFIER ::= - * { appleExtendedKeyUsage 1 } - * { 1 2 840 113635 100 4 1} - */ -#define APPLE_EKU_CODE_SIGNING APPLE_EKU_OID, 1 -#define APPLE_EKU_APPLE_ID APPLE_EKU_OID, 7 -#define APPLE_EKU_PASSBOOK APPLE_EKU_OID, 14 -#define APPLE_EKU_PROFILE_SIGNING APPLE_EKU_OID, 16 -#define APPLE_EKU_QA_PROFILE_SIGNING APPLE_EKU_OID, 17 - - -/* - * Basis of Apple-specific Certificate Policy IDs. - * appleCertificatePolicies OBJECT IDENTIFIER ::= - * { appleDataSecurity 5 } - * { 1 2 840 113635 100 5 } - */ -#define APPLE_CERT_POLICIES APPLE_ADS_OID, 5 - -#define APPLE_CERT_POLICY_MOBILE_STORE APPLE_CERT_POLICIES, 12 - -#define APPLE_CERT_POLICY_MOBILE_STORE_PRODQA APPLE_CERT_POLICY_MOBILE_STORE, 1 - -/* - * Basis of Apple-specific Signing extensions - * { appleDataSecurity 6 } - */ -#define APPLE_CERT_EXT APPLE_ADS_OID, 6 - -/* Apple Intermediate Marker OIDs */ -#define APPLE_CERT_EXT_INTERMEDIATE_MARKER APPLE_CERT_EXT, 2 - -/* Apple Worldwide Developer Relations Certification Authority */ -/* 1.2.840.113635.100.6.2.1 */ -#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_WWDR APPLE_CERT_EXT_INTERMEDIATE_MARKER, 1 - -/* Apple Apple ID Intermediate Marker */ -#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID APPLE_CERT_EXT_INTERMEDIATE_MARKER, 3 - -/* - * Apple Apple ID Intermediate Marker (New subCA, no longer shared with push notification server cert issuer - * - * appleCertificateExtensionAppleIDIntermediate ::= - * { appleCertificateExtensionIntermediateMarker 7 } - * { 1 2 840 113635 100 6 2 7 } - */ -#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_2 APPLE_CERT_EXT_INTERMEDIATE_MARKER, 7 - -#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_SYSTEM_INTEGRATION_2 APPLE_CERT_EXT_INTERMEDIATE_MARKER, 10 - -#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_SYSTEM_INTEGRATION_G3 APPLE_CERT_EXT_INTERMEDIATE_MARKER, 13 - -#define APPLE_CERT_EXT_APPLE_PUSH_MARKER APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID, 2 - - -#define APPLE_CERT_EXTENSION_CODESIGNING APPLE_CERT_EXT, 1 - -/* Secure Boot Embedded Image3 value, - co-opted by desktop for "Apple Released Code Signature", without value */ -#define APPLE_SBOOT_CERT_EXTEN_SBOOT_SPEC_OID APPLE_CERT_EXTENSION_CODESIGNING, 1 -#define APPLE_SBOOT_CERT_EXTEN_SBOOT_TICKET_SPEC_OID APPLE_CERT_EXTENSION_CODESIGNING, 11 -#define APPLE_SBOOT_CERT_EXTEN_IMG4_MANIFEST_SPEC_OID APPLE_CERT_EXTENSION_CODESIGNING, 15 - -/* iPhone Provisioning Profile Signing leaf - on the intermediate marker arc? */ -#define APPLE_PROVISIONING_PROFILE_OID APPLE_CERT_EXT_INTERMEDIATE_MARKER, 1 -/* iPhone Application Signing leaf */ -#define APPLE_APP_SIGNING_OID APPLE_CERT_EXTENSION_CODESIGNING, 3 - -#define APPLE_INSTALLER_PACKAGE_SIGNING_EXTERNAL_OID APPLE_CERT_EXTENSION_CODESIGNING, 16 - -/* Apple TVOS Application Signing leaf, production */ -/* 1.2.840.113635.100.6.1.24 */ -#define APPLE_TVOS_APP_SIGNING_PROD_OID APPLE_CERT_EXTENSION_CODESIGNING, 24 - -/* Apple TVOS Application Signing leaf, QA */ -/* 1.2.840.113635.100.6.1.24.1 */ - -#define APPLE_TVOS_APP_SIGNING_PRODQA_OID APPLE_CERT_EXTENSION_CODESIGNING, 24, 1 - -#define APPLE_ESCROW_ARC APPLE_CERT_EXT, 23 - -#define APPLE_ESCROW_POLICY_OID APPLE_ESCROW_ARC, 1 - -#define APPLE_CERT_EXT_APPLE_ID_VALIDATION_RECORD_SIGNING APPLE_CERT_EXT, 25 - -#define APPLE_SERVER_AUTHENTICATION APPLE_CERT_EXT, 27 -#define APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION APPLE_SERVER_AUTHENTICATION, 1 -#define APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_PPQ_PRODQA APPLE_SERVER_AUTHENTICATION, 3, 1 -#define APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_PPQ_PROD APPLE_SERVER_AUTHENTICATION, 3, 2 -#define APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_IDS_PRODQA APPLE_SERVER_AUTHENTICATION, 4, 1 -#define APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_IDS_PROD APPLE_SERVER_AUTHENTICATION, 4, 2 -#define APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_APN_PRODQA APPLE_SERVER_AUTHENTICATION, 5, 1 -#define APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_APN_PROD APPLE_SERVER_AUTHENTICATION, 5, 2 - -#define APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_GS APPLE_SERVER_AUTHENTICATION, 2 - - -#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLE_SERVER_AUTHENTICATION APPLE_CERT_EXT_INTERMEDIATE_MARKER, 12 - -#define APPLE_CERT_EXT_APPLE_SMP_ENCRYPTION APPLE_CERT_EXT, 30 - -/* UPP fraud detection (Provisioning Profile Query) CMS signing */ - -#define APPLE_CERT_EXT_APPLE_PPQ_SIGNING_PRODQA APPLE_CERT_EXT, 38, 1 -#define APPLE_CERT_EXT_APPLE_PPQ_SIGNING_PROD APPLE_CERT_EXT, 38, 2 - -/* AppleTVOS Application Signing */ -#define APPLE_ATV_APP_SIGNING_OID APPLE_CERT_EXTENSION_CODESIGNING, 24 -#define APPLE_ATV_APP_SIGNING_OID_PRODQA APPLE_ATV_APP_SIGNING_OID, 1 - -/* Apple Pay Issuer Encryption */ -#define APPLE_CERT_EXT_CRYPTO_SERVICES_EXT_ENCRYPTION APPLE_CERT_EXT, 39 - -/* Apple OS X Provisioning Profile Signing */ -/* (note this OID is unfortunately used as a cert extension even though it's under the EKU arc) */ -#define APPLE_CERT_EXT_OSX_PROVISIONING_PROFILE_SIGNING APPLE_EKU_OID, 11 - -/* AppleTV VPN Profile Signing 1.2.840.113635.100.6.43 */ -#define APPLE_CERT_EXT_APPLE_ATV_VPN_PROFILE_SIGNING APPLE_CERT_EXT, 43 - -/* AST2 Diagnostics Server Authentication - * QA Marker OID 1.2.840.113635.100.6.27.8.1 - * Prod Marker OID 1.2.840.113635.100.6.27.8.2 - */ -#define APPLE_CERT_EXT_AST2_DIAGNOSTICS_SERVER_AUTH_PRODQA APPLE_SERVER_AUTHENTICATION, 8, 1 -#define APPLE_CERT_EXT_AST2_DIAGNOSTICS_SERVER_AUTH_PROD APPLE_SERVER_AUTHENTICATION, 8, 2 - -/* Escrow Proxy Server Authentication - * QA Marker OID 1.2.840.113635.100.6.27.7.1 - * Prod Marker OID 1.2.840.113635.100.6.27.7.2 - */ -#define APPLE_CERT_EXT_ESCROW_PROXY_SERVER_AUTH_PRODQA APPLE_SERVER_AUTHENTICATION, 7, 1 -#define APPLE_CERT_EXT_ESCROW_PROXY_SERVER_AUTH_PROD APPLE_SERVER_AUTHENTICATION, 7, 2 - -/* FMiP Server Authentication - * QA Marker OID 1.2.840.113635.100.6.27.6.1 - * Prod Marker OID 1.2.840.113635.100.6.27.6.2 - */ -#define APPLE_CERT_EXT_FMIP_SERVER_AUTH_PRODQA APPLE_SERVER_AUTHENTICATION, 6, 1 -#define APPLE_CERT_EXT_FMIP_SERVER_AUTH_PROD APPLE_SERVER_AUTHENTICATION, 6, 2 - -/* HomeKit Server Authentication - * Intermediate Marker OID: 1.2.840.113635.100.6.2.16 - * Leaf Marker OID: 1.2.840.113635.100.6.27.9 - */ -#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLE_HOME_KIT_SERVER_AUTH APPLE_CERT_EXT_INTERMEDIATE_MARKER, 16 -#define APPLE_CERT_EXT_HOME_KIT_SERVER_AUTH APPLE_SERVER_AUTHENTICATION, 9 - -/* MMCS Server Authentication - * QA Marker OID 1.2.840.113635.100.6.27.11.1 - * Prod Marker OID 1.2.840.113635.100.6.27.11.2 - */ -#define APPLE_CERT_EXT_MMCS_SERVER_AUTH_PRODQA APPLE_SERVER_AUTHENTICATION, 11, 1 -#define APPLE_CERT_EXT_MMCS_SERVER_AUTH_PROD APPLE_SERVER_AUTHENTICATION, 11, 2 - -/* iCloud Setup Authentication - * QA Marker OID 1.2.840.113635.100.6.27.15.1 - * Prod Marker OID 1.2.840.113635.100.6.27.15.2 - */ -#define APPLE_CERT_EXT_ICLOUD_SETUP_SERVER_AUTH_PRODQA APPLE_SERVER_AUTHENTICATION, 15, 1 -#define APPLE_CERT_EXT_ICLOUD_SETUP_SERVER_AUTH_PROD APPLE_SERVER_AUTHENTICATION, 15, 2 - -/* - * Netscape OIDs. - */ -#define NETSCAPE_BASE_OID 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42 - -/* - * Netscape cert extension. - * - * netscape-cert-extension OBJECT IDENTIFIER ::= - * { 2 16 840 1 113730 1 } - * - * BER = 06 08 60 86 48 01 86 F8 42 01 - */ -#define NETSCAPE_CERT_EXTEN NETSCAPE_BASE_OID, 0x01 - -#define NETSCAPE_CERT_POLICY NETSCAPE_BASE_OID, 0x04 - -/* Entrust OIDs. */ -#define ENTRUST_BASE_OID OID_US, 0x86, 0xf6, 0x7d - -/* - * Entrust cert extension. - * - * entrust-cert-extension OBJECT IDENTIFIER ::= - * { 1 2 840 113533 7 65 } - * - * BER = 06 08 2A 86 48 86 F6 7D 07 41 - */ -#define ENTRUST_CERT_EXTEN ENTRUST_BASE_OID, 0x07, 0x41 - -/* Microsoft OIDs. */ -#define MICROSOFT_BASE_OID OID_DOD, 0x01, 0x04, 0x01, 0x82, 0x37 -#define MICROSOFT_ENROLLMENT_OID MICROSOFT_BASE_OID, 0x14 - -/* Google OIDs: 1.3.6.1.4.1.11129. - */ -#define GOOGLE_BASE_OID OID_DOD, 0x01, 0x04, 0x01, 0xD6, 0x79 -#define GOOGLE_EMBEDDED_SCT_OID GOOGLE_BASE_OID, 0x02, 0x04, 0x02 -#define GOOGLE_OCSP_SCT_OID GOOGLE_BASE_OID, 0x02, 0x04, 0x05 - - -/* Algorithm OIDs. */ -static const DERByte - _oidRsa[] = { OID_PKCS_1, 1 }, - _oidMd2Rsa[] = { OID_PKCS_1, 2 }, - _oidMd4Rsa[] = { OID_PKCS_1, 3 }, - _oidMd5Rsa[] = { OID_PKCS_1, 4 }, - _oidSha1Rsa[] = { OID_PKCS_1, 5 }, - _oidSha256Rsa[] = { OID_PKCS_1, 11 }, /* rfc5754 */ - _oidSha384Rsa[] = { OID_PKCS_1, 12 }, /* rfc5754 */ - _oidSha512Rsa[] = { OID_PKCS_1, 13 }, /* rfc5754 */ - _oidSha224Rsa[] = { OID_PKCS_1, 14 }, /* rfc5754 */ - _oidEcPubKey[] = { OID_PUBLIC_KEY_TYPE, 1 }, - _oidSha1Ecdsa[] = { OID_EC_SIG_TYPE, 1 }, /* rfc3279 */ - _oidSha224Ecdsa[] = { OID_ECDSA_WITH_SHA2, 1 }, /* rfc5758 */ - _oidSha256Ecdsa[] = { OID_ECDSA_WITH_SHA2, 2 }, /* rfc5758 */ - _oidSha384Ecdsa[] = { OID_ECDSA_WITH_SHA2, 3 }, /* rfc5758 */ - _oidSha512Ecdsa[] = { OID_ECDSA_WITH_SHA2, 4 }, /* rfc5758 */ - _oidSha1Dsa[] = { OID_ANSI_X9_57_ALGORITHM, 3 }, - _oidMd2[] = { OID_RSA_HASH, 2 }, - _oidMd4[] = { OID_RSA_HASH, 4 }, - _oidMd5[] = { OID_RSA_HASH, 5 }, - _oidSha1[] = { OID_OIW_ALGORITHM, 26 }, - _oidSha1DsaOIW[] = { OID_OIW_ALGORITHM, 27 }, - _oidSha1DsaCommonOIW[] = { OID_OIW_ALGORITHM, 28 }, - _oidSha1RsaOIW[] = { OID_OIW_ALGORITHM, 29 }, - _oidSha256[] = { OID_NIST_HASHALG, 1 }, - _oidSha384[] = { OID_NIST_HASHALG, 2 }, - _oidSha512[] = { OID_NIST_HASHALG, 3 }, - _oidSha224[] = { OID_NIST_HASHALG, 4 }, - _oidFee[] = { APPLE_ALG_OID, 1 }, - _oidMd5Fee[] = { APPLE_ALG_OID, 3 }, - _oidSha1Fee[] = { APPLE_ALG_OID, 4 }, - _oidEcPrime192v1[] = { OID_EC_CURVE, 1 }, - _oidEcPrime256v1[] = { OID_EC_CURVE, 7 }, - _oidAnsip384r1[] = { OID_CERTICOM_EC_CURVE, 34 }, - _oidAnsip521r1[] = { OID_CERTICOM_EC_CURVE, 35 }; - -const DERItem - oidRsa = { (DERByte *)_oidRsa, - sizeof(_oidRsa) }, - oidMd2Rsa = { (DERByte *)_oidMd2Rsa, - sizeof(_oidMd2Rsa) }, - oidMd4Rsa = { (DERByte *)_oidMd4Rsa, - sizeof(_oidMd4Rsa) }, - oidMd5Rsa = { (DERByte *)_oidMd5Rsa, - sizeof(_oidMd5Rsa) }, - oidSha1Rsa = { (DERByte *)_oidSha1Rsa, - sizeof(_oidSha1Rsa) }, - oidSha256Rsa = { (DERByte *)_oidSha256Rsa, - sizeof(_oidSha256Rsa) }, - oidSha384Rsa = { (DERByte *)_oidSha384Rsa, - sizeof(_oidSha384Rsa) }, - oidSha512Rsa = { (DERByte *)_oidSha512Rsa, - sizeof(_oidSha512Rsa) }, - oidSha224Rsa = { (DERByte *)_oidSha224Rsa, - sizeof(_oidSha224Rsa) }, - oidEcPubKey = { (DERByte *)_oidEcPubKey, - sizeof(_oidEcPubKey) }, - oidSha1Ecdsa = { (DERByte *)_oidSha1Ecdsa, - sizeof(_oidSha1Ecdsa) }, - oidSha224Ecdsa = { (DERByte *)_oidSha224Ecdsa, - sizeof(_oidSha224Ecdsa) }, - oidSha256Ecdsa = { (DERByte *)_oidSha256Ecdsa, - sizeof(_oidSha256Ecdsa) }, - oidSha384Ecdsa = { (DERByte *)_oidSha384Ecdsa, - sizeof(_oidSha384Ecdsa) }, - oidSha512Ecdsa = { (DERByte *)_oidSha512Ecdsa, - sizeof(_oidSha512Ecdsa) }, - oidSha1Dsa = { (DERByte *)_oidSha1Dsa, - sizeof(_oidSha1Dsa) }, - oidMd2 = { (DERByte *)_oidMd2, - sizeof(_oidMd2) }, - oidMd4 = { (DERByte *)_oidMd4, - sizeof(_oidMd4) }, - oidMd5 = { (DERByte *)_oidMd5, - sizeof(_oidMd5) }, - oidSha1 = { (DERByte *)_oidSha1, - sizeof(_oidSha1) }, - oidSha1RsaOIW = { (DERByte *)_oidSha1RsaOIW, - sizeof(_oidSha1RsaOIW) }, - oidSha1DsaOIW = { (DERByte *)_oidSha1DsaOIW, - sizeof(_oidSha1DsaOIW) }, - oidSha1DsaCommonOIW = { (DERByte *)_oidSha1DsaCommonOIW, - sizeof(_oidSha1DsaCommonOIW) }, - oidSha256 = { (DERByte *)_oidSha256, - sizeof(_oidSha256) }, - oidSha384 = { (DERByte *)_oidSha384, - sizeof(_oidSha384) }, - oidSha512 = { (DERByte *)_oidSha512, - sizeof(_oidSha512) }, - oidSha224 = { (DERByte *)_oidSha224, - sizeof(_oidSha224) }, - oidFee = { (DERByte *)_oidFee, - sizeof(_oidFee) }, - oidMd5Fee = { (DERByte *)_oidMd5Fee, - sizeof(_oidMd5Fee) }, - oidSha1Fee = { (DERByte *)_oidSha1Fee, - sizeof(_oidSha1Fee) }, - oidEcPrime192v1 = { (DERByte *)_oidEcPrime192v1, - sizeof(_oidEcPrime192v1) }, - oidEcPrime256v1 = { (DERByte *)_oidEcPrime256v1, - sizeof(_oidEcPrime256v1) }, - oidAnsip384r1 = { (DERByte *)_oidAnsip384r1, - sizeof(_oidAnsip384r1) }, - oidAnsip521r1 = { (DERByte *)_oidAnsip521r1, - sizeof(_oidAnsip521r1) }; - - -/* Extension OIDs. */ -__unused static const DERByte - _oidSubjectKeyIdentifier[] = { OID_EXTENSION, 14 }, - _oidKeyUsage[] = { OID_EXTENSION, 15 }, - _oidPrivateKeyUsagePeriod[] = { OID_EXTENSION, 16 }, - _oidSubjectAltName[] = { OID_EXTENSION, 17 }, - _oidIssuerAltName[] = { OID_EXTENSION, 18 }, - _oidBasicConstraints[] = { OID_EXTENSION, 19 }, - _oidNameConstraints[] = { OID_EXTENSION, 30 }, - _oidCrlDistributionPoints[] = { OID_EXTENSION, 31 }, - _oidCertificatePolicies[] = { OID_EXTENSION, 32 }, - _oidAnyPolicy[] = { OID_EXTENSION, 32, 0 }, - _oidPolicyMappings[] = { OID_EXTENSION, 33 }, - _oidAuthorityKeyIdentifier[] = { OID_EXTENSION, 35 }, - _oidPolicyConstraints[] = { OID_EXTENSION, 36 }, - _oidExtendedKeyUsage[] = { OID_EXTENSION, 37 }, - _oidAnyExtendedKeyUsage[] = { OID_EXTENSION, 37, 0 }, - _oidInhibitAnyPolicy[] = { OID_EXTENSION, 54 }, - _oidAuthorityInfoAccess[] = { OID_PE, 1 }, - _oidSubjectInfoAccess[] = { OID_PE, 11 }, - _oidAdOCSP[] = { OID_AD_OCSP }, - _oidAdCAIssuer[] = { OID_AD_CAISSUERS }, - _oidNetscapeCertType[] = { NETSCAPE_CERT_EXTEN, 1 }, - _oidEntrustVersInfo[] = { ENTRUST_CERT_EXTEN, 0 }, - _oidMSNTPrincipalName[] = { MICROSOFT_ENROLLMENT_OID, 2, 3 }, - _oidOCSPNoCheck[] = { OID_AD_OCSP, 5 }, - /* Policy Qualifier IDs for Internet policy qualifiers. */ - _oidQtCps[] = { OID_QT, 1 }, - _oidQtUNotice[] = { OID_QT, 2 }, - /* X.501 Name IDs. */ - _oidCommonName[] = { OID_ATTR_TYPE, 3 }, - _oidCountryName[] = { OID_ATTR_TYPE, 6 }, - _oidLocalityName[] = { OID_ATTR_TYPE, 7 }, - _oidStateOrProvinceName[] = { OID_ATTR_TYPE, 8 }, - _oidOrganizationName[] = { OID_ATTR_TYPE, 10 }, - _oidOrganizationalUnitName[] = { OID_ATTR_TYPE, 11 }, - _oidDescription[] = { OID_ATTR_TYPE, 13 }, - _oidEmailAddress[] = { OID_PKCS_9, 1 }, - _oidFriendlyName[] = { OID_PKCS_9, 20 }, - _oidLocalKeyId[] = { OID_PKCS_9, 21 }, - _oidExtendedKeyUsageServerAuth[] = { OID_KP, 1 }, - _oidExtendedKeyUsageClientAuth[] = { OID_KP, 2 }, - _oidExtendedKeyUsageCodeSigning[] = { OID_KP, 3 }, - _oidExtendedKeyUsageEmailProtection[] = { OID_KP, 4 }, - _oidExtendedKeyUsageTimeStamping[] = { OID_KP, 8 }, - _oidExtendedKeyUsageOCSPSigning[] = { OID_KP, 9 }, - _oidExtendedKeyUsageIPSec[] = { OID_ISAKMP, 2, 2 }, - _oidExtendedKeyUsageMicrosoftSGC[] = { MICROSOFT_BASE_OID, 10, 3, 3 }, - _oidExtendedKeyUsageNetscapeSGC[] = { NETSCAPE_CERT_POLICY, 1 }, - _oidAppleSecureBootCertSpec[] = { APPLE_SBOOT_CERT_EXTEN_SBOOT_SPEC_OID }, - _oidAppleSecureBootTicketCertSpec[] = { APPLE_SBOOT_CERT_EXTEN_SBOOT_TICKET_SPEC_OID }, - _oidAppleImg4ManifestCertSpec[] = { APPLE_SBOOT_CERT_EXTEN_IMG4_MANIFEST_SPEC_OID }, - _oidAppleProvisioningProfile[] = {APPLE_PROVISIONING_PROFILE_OID }, - _oidAppleApplicationSigning[] = { APPLE_APP_SIGNING_OID }, - _oidAppleInstallerPackagingSigningExternal[] = { APPLE_INSTALLER_PACKAGE_SIGNING_EXTERNAL_OID }, - _oidAppleTVOSApplicationSigningProd[] = { APPLE_TVOS_APP_SIGNING_PROD_OID }, - _oidAppleTVOSApplicationSigningProdQA[] = { APPLE_TVOS_APP_SIGNING_PRODQA_OID }, - _oidAppleExtendedKeyUsageCodeSigning[] = { APPLE_EKU_CODE_SIGNING }, - _oidAppleExtendedKeyUsageCodeSigningDev[] = { APPLE_EKU_CODE_SIGNING, 1 }, - _oidAppleExtendedKeyUsageAppleID[] = { APPLE_EKU_APPLE_ID }, - _oidAppleExtendedKeyUsagePassbook[] = { APPLE_EKU_PASSBOOK }, - _oidAppleExtendedKeyUsageProfileSigning[] = { APPLE_EKU_PROFILE_SIGNING }, - _oidAppleExtendedKeyUsageQAProfileSigning[] = { APPLE_EKU_QA_PROFILE_SIGNING }, - _oidAppleIntmMarkerAppleWWDR[] = { APPLE_CERT_EXT_INTERMEDIATE_MARKER_WWDR }, - _oidAppleIntmMarkerAppleID[] = { APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID }, - _oidAppleIntmMarkerAppleID2[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_2 }, - _oidApplePushServiceClient[] = { APPLE_CERT_EXT_APPLE_PUSH_MARKER, 2 }, - _oidApplePolicyMobileStore[] = { APPLE_CERT_POLICY_MOBILE_STORE }, - _oidApplePolicyMobileStoreProdQA[] = { APPLE_CERT_POLICY_MOBILE_STORE_PRODQA }, - _oidApplePolicyEscrowService[] = { APPLE_ESCROW_POLICY_OID }, - _oidAppleCertExtensionAppleIDRecordValidationSigning[] = { APPLE_CERT_EXT_APPLE_ID_VALIDATION_RECORD_SIGNING }, - _oidAppleCertExtOSXProvisioningProfileSigning[] = { APPLE_CERT_EXT_OSX_PROVISIONING_PROFILE_SIGNING }, - _oidAppleIntmMarkerAppleSystemIntg2[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_SYSTEM_INTEGRATION_2}, - _oidAppleIntmMarkerAppleSystemIntgG3[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_SYSTEM_INTEGRATION_G3}, - _oidAppleCertExtAppleSMPEncryption[] = {APPLE_CERT_EXT_APPLE_SMP_ENCRYPTION}, - _oidAppleCertExtAppleServerAuthentication[] = {APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION}, - _oidAppleCertExtAppleServerAuthenticationPPQProdQA[] = {APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_PPQ_PRODQA}, - _oidAppleCertExtAppleServerAuthenticationPPQProd[] = {APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_PPQ_PROD}, - _oidAppleCertExtAppleServerAuthenticationIDSProdQA[] = {APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_IDS_PRODQA}, - _oidAppleCertExtAppleServerAuthenticationIDSProd[] = {APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_IDS_PROD}, - _oidAppleCertExtAppleServerAuthenticationAPNProdQA[] = {APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_APN_PRODQA}, - _oidAppleCertExtAppleServerAuthenticationAPNProd[] = {APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_APN_PROD}, - _oidAppleCertExtAppleServerAuthenticationGS[] = {APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION_GS}, - _oidAppleIntmMarkerAppleServerAuthentication[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLE_SERVER_AUTHENTICATION}, - _oidAppleCertExtApplePPQSigningProdQA[] = {APPLE_CERT_EXT_APPLE_PPQ_SIGNING_PRODQA}, - _oidAppleCertExtApplePPQSigningProd[] = {APPLE_CERT_EXT_APPLE_PPQ_SIGNING_PROD}, - _oidGoogleEmbeddedSignedCertificateTimestamp[] = {GOOGLE_EMBEDDED_SCT_OID}, - _oidGoogleOCSPSignedCertificateTimestamp[] = {GOOGLE_OCSP_SCT_OID}, - _oidAppleCertExtATVAppSigningProdQA[] = {APPLE_ATV_APP_SIGNING_OID_PRODQA}, - _oidAppleCertExtATVAppSigningProd[] = {APPLE_ATV_APP_SIGNING_OID}, - _oidAppleCertExtATVVPNProfileSigning[] = {APPLE_CERT_EXT_APPLE_ATV_VPN_PROFILE_SIGNING}, - _oidAppleCertExtCryptoServicesExtEncryption[] = {APPLE_CERT_EXT_CRYPTO_SERVICES_EXT_ENCRYPTION}, - _oidAppleCertExtAST2DiagnosticsServerAuthProdQA[] = {APPLE_CERT_EXT_AST2_DIAGNOSTICS_SERVER_AUTH_PRODQA}, - _oidAppleCertExtAST2DiagnosticsServerAuthProd[] = {APPLE_CERT_EXT_AST2_DIAGNOSTICS_SERVER_AUTH_PROD}, - _oidAppleCertExtEscrowProxyServerAuthProdQA[] = {APPLE_CERT_EXT_ESCROW_PROXY_SERVER_AUTH_PRODQA}, - _oidAppleCertExtEscrowProxyServerAuthProd[] = {APPLE_CERT_EXT_ESCROW_PROXY_SERVER_AUTH_PROD}, - _oidAppleCertExtFMiPServerAuthProdQA[] = {APPLE_CERT_EXT_FMIP_SERVER_AUTH_PRODQA}, - _oidAppleCertExtFMiPServerAuthProd[] = {APPLE_CERT_EXT_FMIP_SERVER_AUTH_PROD}, - _oidAppleCertExtHomeKitServerAuth[] = {APPLE_CERT_EXT_HOME_KIT_SERVER_AUTH}, - _oidAppleIntmMarkerAppleHomeKitServerCA[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLE_HOME_KIT_SERVER_AUTH}, - _oidAppleCertExtMMCSServerAuthProdQA[] = {APPLE_CERT_EXT_MMCS_SERVER_AUTH_PRODQA}, - _oidAppleCertExtMMCSServerAuthProd[] = {APPLE_CERT_EXT_MMCS_SERVER_AUTH_PROD}, - _oidAppleCertExtiCloudSetupServerAuthProdQA[] = {APPLE_CERT_EXT_ICLOUD_SETUP_SERVER_AUTH_PRODQA}, - _oidAppleCertExtiCloudSetupServerAuthProd[] = {APPLE_CERT_EXT_ICLOUD_SETUP_SERVER_AUTH_PROD}; - -__unused const DERItem - oidSubjectKeyIdentifier = { (DERByte *)_oidSubjectKeyIdentifier, - sizeof(_oidSubjectKeyIdentifier) }, - oidKeyUsage = { (DERByte *)_oidKeyUsage, - sizeof(_oidKeyUsage) }, - oidPrivateKeyUsagePeriod = { (DERByte *)_oidPrivateKeyUsagePeriod, - sizeof(_oidPrivateKeyUsagePeriod) }, - oidSubjectAltName = { (DERByte *)_oidSubjectAltName, - sizeof(_oidSubjectAltName) }, - oidIssuerAltName = { (DERByte *)_oidIssuerAltName, - sizeof(_oidIssuerAltName) }, - oidBasicConstraints = { (DERByte *)_oidBasicConstraints, - sizeof(_oidBasicConstraints) }, - oidNameConstraints = { (DERByte *)_oidNameConstraints, - sizeof(_oidNameConstraints) }, - oidCrlDistributionPoints = { (DERByte *)_oidCrlDistributionPoints, - sizeof(_oidCrlDistributionPoints) }, - oidCertificatePolicies = { (DERByte *)_oidCertificatePolicies, - sizeof(_oidCertificatePolicies) }, - oidAnyPolicy = { (DERByte *)_oidAnyPolicy, - sizeof(_oidAnyPolicy) }, - oidPolicyMappings = { (DERByte *)_oidPolicyMappings, - sizeof(_oidPolicyMappings) }, - oidAuthorityKeyIdentifier = { (DERByte *)_oidAuthorityKeyIdentifier, - sizeof(_oidAuthorityKeyIdentifier) }, - oidPolicyConstraints = { (DERByte *)_oidPolicyConstraints, - sizeof(_oidPolicyConstraints) }, - oidExtendedKeyUsage = { (DERByte *)_oidExtendedKeyUsage, - sizeof(_oidExtendedKeyUsage) }, - oidAnyExtendedKeyUsage = { (DERByte *)_oidAnyExtendedKeyUsage, - sizeof(_oidAnyExtendedKeyUsage) }, - oidInhibitAnyPolicy = { (DERByte *)_oidInhibitAnyPolicy, - sizeof(_oidInhibitAnyPolicy) }, - oidAuthorityInfoAccess = { (DERByte *)_oidAuthorityInfoAccess, - sizeof(_oidAuthorityInfoAccess) }, - oidSubjectInfoAccess = { (DERByte *)_oidSubjectInfoAccess, - sizeof(_oidSubjectInfoAccess) }, - oidAdOCSP = { (DERByte *)_oidAdOCSP, - sizeof(_oidAdOCSP) }, - oidAdCAIssuer = { (DERByte *)_oidAdCAIssuer, - sizeof(_oidAdCAIssuer) }, - oidNetscapeCertType = { (DERByte *)_oidNetscapeCertType, - sizeof(_oidNetscapeCertType) }, - oidEntrustVersInfo = { (DERByte *)_oidEntrustVersInfo, - sizeof(_oidEntrustVersInfo) }, - oidMSNTPrincipalName = { (DERByte *)_oidMSNTPrincipalName, - sizeof(_oidMSNTPrincipalName) }, - oidOCSPNoCheck = { (DERByte *)_oidOCSPNoCheck, - sizeof(_oidOCSPNoCheck) }, - /* Policy Qualifier IDs for Internet policy qualifiers. */ - oidQtCps = { (DERByte *)_oidQtCps, - sizeof(_oidQtCps) }, - oidQtUNotice = { (DERByte *)_oidQtUNotice, - sizeof(_oidQtUNotice) }, - /* X.501 Name IDs. */ - oidCommonName = { (DERByte *)_oidCommonName, - sizeof(_oidCommonName) }, - oidCountryName = { (DERByte *)_oidCountryName, - sizeof(_oidCountryName) }, - oidLocalityName = { (DERByte *)_oidLocalityName, - sizeof(_oidLocalityName) }, - oidStateOrProvinceName = { (DERByte *)_oidStateOrProvinceName, - sizeof(_oidStateOrProvinceName) }, - oidOrganizationName = { (DERByte *)_oidOrganizationName, - sizeof(_oidOrganizationName) }, - oidOrganizationalUnitName = { (DERByte *)_oidOrganizationalUnitName, - sizeof(_oidOrganizationalUnitName) }, - oidDescription = { (DERByte *)_oidDescription, - sizeof(_oidDescription) }, - oidEmailAddress = { (DERByte *)_oidEmailAddress, - sizeof(_oidEmailAddress) }, - oidFriendlyName = { (DERByte *)_oidFriendlyName, - sizeof(_oidFriendlyName) }, - oidLocalKeyId = { (DERByte *)_oidLocalKeyId, - sizeof(_oidLocalKeyId) }, - oidExtendedKeyUsageServerAuth = { (DERByte *)_oidExtendedKeyUsageServerAuth, - sizeof(_oidExtendedKeyUsageServerAuth) }, - oidExtendedKeyUsageClientAuth = { (DERByte *)_oidExtendedKeyUsageClientAuth, - sizeof(_oidExtendedKeyUsageClientAuth) }, - oidExtendedKeyUsageCodeSigning = { (DERByte *)_oidExtendedKeyUsageCodeSigning, - sizeof(_oidExtendedKeyUsageCodeSigning) }, - oidExtendedKeyUsageEmailProtection = { (DERByte *)_oidExtendedKeyUsageEmailProtection, - sizeof(_oidExtendedKeyUsageEmailProtection) }, - oidExtendedKeyUsageTimeStamping = { (DERByte *)_oidExtendedKeyUsageTimeStamping, - sizeof(_oidExtendedKeyUsageTimeStamping) }, - oidExtendedKeyUsageOCSPSigning = { (DERByte *)_oidExtendedKeyUsageOCSPSigning, - sizeof(_oidExtendedKeyUsageOCSPSigning) }, - oidExtendedKeyUsageIPSec = { (DERByte *)_oidExtendedKeyUsageIPSec, - sizeof(_oidExtendedKeyUsageIPSec) }, - oidExtendedKeyUsageMicrosoftSGC = { (DERByte *)_oidExtendedKeyUsageMicrosoftSGC, - sizeof(_oidExtendedKeyUsageMicrosoftSGC) }, - oidExtendedKeyUsageNetscapeSGC = { (DERByte *)_oidExtendedKeyUsageNetscapeSGC, - sizeof(_oidExtendedKeyUsageNetscapeSGC) }, - oidAppleSecureBootCertSpec = { (DERByte *)_oidAppleSecureBootCertSpec, - sizeof(_oidAppleSecureBootCertSpec) }, - oidAppleSecureBootTicketCertSpec = { (DERByte *)_oidAppleSecureBootTicketCertSpec, - sizeof(_oidAppleSecureBootTicketCertSpec) }, - oidAppleImg4ManifestCertSpec = { (DERByte *)_oidAppleImg4ManifestCertSpec, - sizeof(_oidAppleImg4ManifestCertSpec) }, - oidAppleProvisioningProfile = { (DERByte *)_oidAppleProvisioningProfile, - sizeof(_oidAppleProvisioningProfile) }, - oidAppleApplicationSigning = { (DERByte *)_oidAppleApplicationSigning, - sizeof(_oidAppleApplicationSigning) }, - oidAppleInstallerPackagingSigningExternal = { (DERByte *)_oidAppleInstallerPackagingSigningExternal, - sizeof(_oidAppleInstallerPackagingSigningExternal) }, - oidAppleTVOSApplicationSigningProd = { (DERByte *)_oidAppleTVOSApplicationSigningProd, - sizeof(_oidAppleTVOSApplicationSigningProd) }, - oidAppleTVOSApplicationSigningProdQA = { (DERByte *)_oidAppleTVOSApplicationSigningProdQA, - sizeof(_oidAppleTVOSApplicationSigningProdQA) }, - oidAppleExtendedKeyUsageCodeSigning = { (DERByte *)_oidAppleExtendedKeyUsageCodeSigning, - sizeof(_oidAppleExtendedKeyUsageCodeSigning) }, - oidAppleExtendedKeyUsageCodeSigningDev = { (DERByte *)_oidAppleExtendedKeyUsageCodeSigningDev, - sizeof(_oidAppleExtendedKeyUsageCodeSigningDev) }, - oidAppleExtendedKeyUsageAppleID = { (DERByte *)_oidAppleExtendedKeyUsageAppleID, - sizeof(_oidAppleExtendedKeyUsageAppleID) }, - oidAppleExtendedKeyUsagePassbook = { (DERByte *)_oidAppleExtendedKeyUsagePassbook, - sizeof(_oidAppleExtendedKeyUsagePassbook) }, - oidAppleExtendedKeyUsageProfileSigning - = { (DERByte *)_oidAppleExtendedKeyUsageProfileSigning, - sizeof(_oidAppleExtendedKeyUsageProfileSigning) }, - oidAppleExtendedKeyUsageQAProfileSigning - = { (DERByte *)_oidAppleExtendedKeyUsageQAProfileSigning, - sizeof(_oidAppleExtendedKeyUsageQAProfileSigning) }, - oidAppleIntmMarkerAppleWWDR = { (DERByte *)_oidAppleIntmMarkerAppleWWDR, - sizeof(_oidAppleIntmMarkerAppleWWDR) }, - oidAppleIntmMarkerAppleID = { (DERByte *)_oidAppleIntmMarkerAppleID, - sizeof(_oidAppleIntmMarkerAppleID) }, - oidAppleIntmMarkerAppleID2 = { (DERByte *)_oidAppleIntmMarkerAppleID2, - sizeof(_oidAppleIntmMarkerAppleID2) }, - oidApplePushServiceClient = { (DERByte *)_oidAppleIntmMarkerAppleID2, - sizeof(_oidAppleIntmMarkerAppleID2) }, - oidApplePolicyMobileStore = { (DERByte *)_oidApplePolicyMobileStore, - sizeof(_oidApplePolicyMobileStore)}, - oidApplePolicyMobileStoreProdQA = { (DERByte *)_oidApplePolicyMobileStoreProdQA, - sizeof(_oidApplePolicyMobileStoreProdQA)}, - oidApplePolicyEscrowService = { (DERByte *)_oidApplePolicyEscrowService, - sizeof(_oidApplePolicyEscrowService)}, - oidAppleCertExtensionAppleIDRecordValidationSigning = { (DERByte *)_oidAppleCertExtensionAppleIDRecordValidationSigning, - sizeof(_oidAppleCertExtensionAppleIDRecordValidationSigning)}, - oidAppleCertExtOSXProvisioningProfileSigning = { (DERByte *)_oidAppleCertExtOSXProvisioningProfileSigning, - sizeof(_oidAppleCertExtOSXProvisioningProfileSigning) }, - oidAppleIntmMarkerAppleSystemIntg2 = { (DERByte *) _oidAppleIntmMarkerAppleSystemIntg2, - sizeof(_oidAppleIntmMarkerAppleSystemIntg2)}, - oidAppleIntmMarkerAppleSystemIntgG3 = { (DERByte *) _oidAppleIntmMarkerAppleSystemIntgG3, - sizeof(_oidAppleIntmMarkerAppleSystemIntgG3)}, - oidAppleCertExtAppleSMPEncryption = { (DERByte *)_oidAppleCertExtAppleSMPEncryption, - sizeof(_oidAppleCertExtAppleSMPEncryption)}, - oidAppleCertExtAppleServerAuthentication - = { (DERByte *)_oidAppleCertExtAppleServerAuthentication, - sizeof(_oidAppleCertExtAppleServerAuthentication) }, - oidAppleCertExtAppleServerAuthenticationIDSProdQA - = { (DERByte *)_oidAppleCertExtAppleServerAuthenticationIDSProdQA, - sizeof(_oidAppleCertExtAppleServerAuthenticationIDSProdQA) }, - oidAppleCertExtAppleServerAuthenticationIDSProd - = { (DERByte *)_oidAppleCertExtAppleServerAuthenticationIDSProd, - sizeof(_oidAppleCertExtAppleServerAuthenticationIDSProd) }, - oidAppleCertExtAppleServerAuthenticationAPNProdQA - = { (DERByte *)_oidAppleCertExtAppleServerAuthenticationAPNProdQA, - sizeof(_oidAppleCertExtAppleServerAuthenticationAPNProdQA) }, - oidAppleCertExtAppleServerAuthenticationAPNProd - = { (DERByte *)_oidAppleCertExtAppleServerAuthenticationAPNProd, - sizeof(_oidAppleCertExtAppleServerAuthenticationAPNProd) }, - oidAppleCertExtAppleServerAuthenticationGS - = { (DERByte *)_oidAppleCertExtAppleServerAuthenticationGS, - sizeof(_oidAppleCertExtAppleServerAuthenticationGS) }, - oidAppleCertExtAppleServerAuthenticationPPQProdQA - = { (DERByte *)_oidAppleCertExtAppleServerAuthenticationPPQProdQA, - sizeof(_oidAppleCertExtAppleServerAuthenticationPPQProdQA) }, - oidAppleCertExtAppleServerAuthenticationPPQProd - = { (DERByte *)_oidAppleCertExtAppleServerAuthenticationPPQProd, - sizeof(_oidAppleCertExtAppleServerAuthenticationPPQProd) }, - oidAppleIntmMarkerAppleServerAuthentication - = { (DERByte *)_oidAppleIntmMarkerAppleServerAuthentication, - sizeof(_oidAppleIntmMarkerAppleServerAuthentication) }, - oidAppleCertExtApplePPQSigningProd = { (DERByte *)_oidAppleCertExtApplePPQSigningProd, - sizeof(_oidAppleCertExtApplePPQSigningProd)}, - oidAppleCertExtApplePPQSigningProdQA = { (DERByte *)_oidAppleCertExtApplePPQSigningProdQA, - sizeof(_oidAppleCertExtApplePPQSigningProdQA)}, - oidGoogleEmbeddedSignedCertificateTimestamp - = { (DERByte *)_oidGoogleEmbeddedSignedCertificateTimestamp, - sizeof(_oidGoogleEmbeddedSignedCertificateTimestamp) }, - oidGoogleOCSPSignedCertificateTimestamp - = { (DERByte *)_oidGoogleOCSPSignedCertificateTimestamp, - sizeof(_oidGoogleOCSPSignedCertificateTimestamp) }, - oidAppleCertExtATVAppSigningProd = { (DERByte *)_oidAppleCertExtATVAppSigningProd, - sizeof(_oidAppleCertExtATVAppSigningProd)}, - oidAppleCertExtATVAppSigningProdQA = { (DERByte *)_oidAppleCertExtATVAppSigningProdQA, - sizeof(_oidAppleCertExtATVAppSigningProdQA)}, - oidAppleCertExtATVVPNProfileSigning = { (DERByte *) _oidAppleCertExtATVVPNProfileSigning, - sizeof(_oidAppleCertExtATVVPNProfileSigning)}, - oidAppleCertExtCryptoServicesExtEncryption = { (DERByte *)_oidAppleCertExtCryptoServicesExtEncryption, - sizeof(_oidAppleCertExtCryptoServicesExtEncryption)}, - oidAppleCertExtAST2DiagnosticsServerAuthProdQA = { (DERByte *)_oidAppleCertExtAST2DiagnosticsServerAuthProdQA, - sizeof(_oidAppleCertExtAST2DiagnosticsServerAuthProdQA)}, - oidAppleCertExtAST2DiagnosticsServerAuthProd = { (DERByte *)_oidAppleCertExtAST2DiagnosticsServerAuthProd, - sizeof(_oidAppleCertExtAST2DiagnosticsServerAuthProd)}, - oidAppleCertExtEscrowProxyServerAuthProdQA = { (DERByte *)_oidAppleCertExtEscrowProxyServerAuthProdQA, - sizeof(_oidAppleCertExtEscrowProxyServerAuthProdQA)}, - oidAppleCertExtEscrowProxyServerAuthProd = { (DERByte *)_oidAppleCertExtEscrowProxyServerAuthProd, - sizeof(_oidAppleCertExtEscrowProxyServerAuthProd)}, - oidAppleCertExtFMiPServerAuthProdQA = { (DERByte *)_oidAppleCertExtFMiPServerAuthProdQA, - sizeof(_oidAppleCertExtFMiPServerAuthProdQA)}, - oidAppleCertExtFMiPServerAuthProd = { (DERByte *)_oidAppleCertExtFMiPServerAuthProd, - sizeof(_oidAppleCertExtFMiPServerAuthProd)}, - oidAppleCertExtHomeKitServerAuth = { (DERByte *)_oidAppleCertExtHomeKitServerAuth, - sizeof(_oidAppleCertExtHomeKitServerAuth)}, - oidAppleIntmMarkerAppleHomeKitServerCA = { (DERByte *)_oidAppleIntmMarkerAppleHomeKitServerCA, - sizeof(_oidAppleIntmMarkerAppleHomeKitServerCA) }, - oidAppleCertExtAppleServerAuthenticationMMCSProdQA - = { (DERByte *)_oidAppleCertExtMMCSServerAuthProdQA, - sizeof(_oidAppleCertExtMMCSServerAuthProdQA) }, - oidAppleCertExtAppleServerAuthenticationMMCSProd - = { (DERByte *)_oidAppleCertExtMMCSServerAuthProd, - sizeof(_oidAppleCertExtMMCSServerAuthProd) }, - oidAppleCertExtAppleServerAuthenticationiCloudSetupProdQA - = { (DERByte *)_oidAppleCertExtiCloudSetupServerAuthProdQA, - sizeof(_oidAppleCertExtiCloudSetupServerAuthProdQA) }, - oidAppleCertExtAppleServerAuthenticationiCloudSetupProd - = { (DERByte *)_oidAppleCertExtiCloudSetupServerAuthProd, - sizeof(_oidAppleCertExtiCloudSetupServerAuthProd) }; - - - - -bool DEROidCompare(const DERItem *oid1, const DERItem *oid2) { - if ((oid1 == NULL) || (oid2 == NULL)) { - return false; - } - if (oid1->length != oid2->length) { - return false; - } - if (!DERMemcmp(oid1->data, oid2->data, oid1->length)) { - return true; - } else { - return false; - } -} diff --git a/libDER/libDER/oids.h b/libDER/libDER/oids.h deleted file mode 100644 index 472b07ba..00000000 --- a/libDER/libDER/oids.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2005-2009,2011-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * oids.h - declaration of OID consts - * - */ - -#ifndef _LIB_DER_OIDS_H_ -#define _LIB_DER_OIDS_H_ - -#include -#include - -__BEGIN_DECLS - -// Security's new `oids.h` checks for the main `libder.h` header being already included, -// but doesn't check for LibDER's `oids.h` (which is the one that actually defines -// the conflicting types) -// Both this file and that one define the same exact types, so if the other file has already been included, -// been included, it's okay, just don't redefine anything -#if !defined(_SECURITY_OIDS_H_) -/* - * Basic data types - */ -typedef uint8_t DERByte; -typedef size_t DERSize; - -/* - * Primary representation of a block of memory. - */ -typedef struct { - DERByte *data; - DERSize length; -} DERItem; -#endif - -/* Algorithm oids. */ -extern const DERItem - oidRsa, /* PKCS1 RSA encryption, used to identify RSA keys */ - oidMd2Rsa, /* PKCS1 md2withRSAEncryption signature alg */ - oidMd4Rsa, /* PKCS1 md4withRSAEncryption signature alg */ - oidMd5Rsa, /* PKCS1 md5withRSAEncryption signature alg */ - oidSha1Rsa, /* PKCS1 sha1withRSAEncryption signature alg */ - oidSha256Rsa, /* PKCS1 sha256WithRSAEncryption signature alg */ - oidSha384Rsa, /* PKCS1 sha384WithRSAEncryption signature alg */ - oidSha512Rsa, /* PKCS1 sha512WithRSAEncryption signature alg */ - oidSha224Rsa, /* PKCS1 sha224WithRSAEncryption signature alg */ - oidEcPubKey, /* ECDH or ECDSA public key in a certificate */ - oidSha1Ecdsa, /* ECDSA with SHA1 signature alg */ - oidSha224Ecdsa, /* ECDSA with SHA224 signature alg */ - oidSha256Ecdsa, /* ECDSA with SHA256 signature alg */ - oidSha384Ecdsa, /* ECDSA with SHA384 signature alg */ - oidSha512Ecdsa, /* ECDSA with SHA512 signature alg */ - oidSha1Dsa, /* ANSI X9.57 DSA with SHA1 signature alg */ - oidMd2, /* OID_RSA_HASH 2 */ - oidMd4, /* OID_RSA_HASH 4 */ - oidMd5, /* OID_RSA_HASH 5 */ - oidSha1, /* OID_OIW_ALGORITHM 26 */ - oidSha1DsaOIW, /* OID_OIW_ALGORITHM 27 */ - oidSha1DsaCommonOIW,/* OID_OIW_ALGORITHM 28 */ - oidSha1RsaOIW, /* OID_OIW_ALGORITHM 29 */ - oidSha256, /* OID_NIST_HASHALG 1 */ - oidSha384, /* OID_NIST_HASHALG 2 */ - oidSha512, /* OID_NIST_HASHALG 3 */ - oidSha224, /* OID_NIST_HASHALG 4 */ - oidFee, /* APPLE_ALG_OID 1 */ - oidMd5Fee, /* APPLE_ALG_OID 3 */ - oidSha1Fee, /* APPLE_ALG_OID 4 */ - oidEcPrime192v1, /* OID_EC_CURVE 1 prime192v1/secp192r1/ansiX9p192r1*/ - oidEcPrime256v1, /* OID_EC_CURVE 7 prime256v1/secp256r1*/ - oidAnsip384r1, /* OID_CERTICOM_EC_CURVE 34 ansip384r1/secp384r1*/ - oidAnsip521r1; /* OID_CERTICOM_EC_CURVE 35 ansip521r1/secp521r1*/ - -/* Standard X.509 Cert and CRL extensions. */ -extern const DERItem - oidSubjectKeyIdentifier, - oidKeyUsage, - oidPrivateKeyUsagePeriod, - oidSubjectAltName, - oidIssuerAltName, - oidBasicConstraints, - oidNameConstraints, - oidCrlDistributionPoints, - oidCertificatePolicies, - oidAnyPolicy, - oidPolicyMappings, - oidAuthorityKeyIdentifier, - oidPolicyConstraints, - oidExtendedKeyUsage, - oidAnyExtendedKeyUsage, - oidInhibitAnyPolicy, - oidAuthorityInfoAccess, - oidSubjectInfoAccess, - oidAdOCSP, - oidAdCAIssuer, - oidNetscapeCertType, - oidEntrustVersInfo, - oidMSNTPrincipalName, - // added for Darling update of the library (after Apple stopped publishing new releases) - oidOCSPNoCheck; - -/* Policy Qualifier IDs for Internet policy qualifiers. */ -extern const DERItem - oidQtCps, - oidQtUNotice; - -/* X.501 Name IDs. */ -extern const DERItem - oidCommonName, - oidCountryName, - oidLocalityName, - oidStateOrProvinceName, - oidOrganizationName, - oidOrganizationalUnitName, - oidDescription, - oidEmailAddress, - oidFriendlyName, - oidLocalKeyId; - -/* X.509 Extended Key Usages */ -extern const DERItem - oidExtendedKeyUsageServerAuth, - oidExtendedKeyUsageClientAuth, - oidExtendedKeyUsageCodeSigning, - oidExtendedKeyUsageEmailProtection, - oidExtendedKeyUsageTimeStamping, - oidExtendedKeyUsageOCSPSigning, - oidExtendedKeyUsageIPSec, - oidExtendedKeyUsageMicrosoftSGC, - oidExtendedKeyUsageNetscapeSGC; - -/* Google Certificate Transparency OIDs */ -extern const DERItem - oidGoogleEmbeddedSignedCertificateTimestamp, - oidGoogleOCSPSignedCertificateTimestamp; - -__END_DECLS - -#endif /* _LIB_DER_OIDS_H_ */ diff --git a/libDER/libDER/oidsPriv.h b/libDER/libDER/oidsPriv.h deleted file mode 100644 index 3d64f628..00000000 --- a/libDER/libDER/oidsPriv.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2005-2009,2011-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * oids.h - declaration of OID consts - * - */ - -#ifndef _LIB_DER_OIDSPRIV_H_ -#define _LIB_DER_OIDSPRIV_H_ - -#include -#include - -__BEGIN_DECLS - -/* Apple Oids */ -extern const DERItem - oidAppleSecureBootCertSpec, - oidAppleSecureBootTicketCertSpec, - oidAppleImg4ManifestCertSpec, - oidAppleProvisioningProfile, - oidAppleApplicationSigning, - oidAppleTVOSApplicationSigningProd, - oidAppleTVOSApplicationSigningProdQA, - oidAppleInstallerPackagingSigningExternal, - oidAppleExtendedKeyUsageCodeSigning, - oidAppleExtendedKeyUsageCodeSigningDev, - oidAppleExtendedKeyUsageAppleID, - oidAppleExtendedKeyUsagePassbook, - oidAppleExtendedKeyUsageProfileSigning, - oidAppleExtendedKeyUsageQAProfileSigning, - oidAppleIntmMarkerAppleWWDR, - oidAppleIntmMarkerAppleID, - oidAppleIntmMarkerAppleID2, - oidApplePushServiceClient, - oidApplePolicyMobileStore, - oidApplePolicyMobileStoreProdQA, - oidApplePolicyEscrowService, - oidAppleCertExtensionAppleIDRecordValidationSigning, - oidAppleCertExtOSXProvisioningProfileSigning, - oidAppleIntmMarkerAppleSystemIntg2, - oidAppleIntmMarkerAppleSystemIntgG3, - oidAppleCertExtAppleSMPEncryption, - oidAppleCertExtAppleServerAuthentication, - oidAppleCertExtAppleServerAuthenticationIDSProdQA, - oidAppleCertExtAppleServerAuthenticationIDSProd, - oidAppleCertExtAppleServerAuthenticationAPNProdQA, - oidAppleCertExtAppleServerAuthenticationAPNProd, - oidAppleCertExtAppleServerAuthenticationGS, - oidAppleCertExtAppleServerAuthenticationPPQProdQA, - oidAppleCertExtAppleServerAuthenticationPPQProd, - oidAppleIntmMarkerAppleServerAuthentication, - oidAppleCertExtApplePPQSigningProd, - oidAppleCertExtApplePPQSigningProdQA, - oidAppleCertExtATVAppSigningProd, - oidAppleCertExtATVAppSigningProdQA, - oidAppleCertExtATVVPNProfileSigning, - oidAppleCertExtCryptoServicesExtEncryption, - oidAppleCertExtAST2DiagnosticsServerAuthProdQA, - oidAppleCertExtAST2DiagnosticsServerAuthProd, - oidAppleCertExtEscrowProxyServerAuthProdQA, - oidAppleCertExtEscrowProxyServerAuthProd, - oidAppleCertExtFMiPServerAuthProdQA, - oidAppleCertExtFMiPServerAuthProd, - oidAppleCertExtHomeKitServerAuth, - oidAppleIntmMarkerAppleHomeKitServerCA, - oidAppleCertExtAppleServerAuthenticationMMCSProdQA, - oidAppleCertExtAppleServerAuthenticationMMCSProd, - oidAppleCertExtAppleServerAuthenticationiCloudSetupProdQA, - oidAppleCertExtAppleServerAuthenticationiCloudSetupProd; - - /* Compare two decoded OIDs. Returns true iff they are equivalent. */ - bool DEROidCompare(const DERItem *oid1, const DERItem *oid2); - -__END_DECLS - -#endif /* _LIB_DER_UTILS_H_ */ diff --git a/libDER/libDERUtils/fileIo.c b/libDER/libDERUtils/fileIo.c deleted file mode 100644 index a050fe5a..00000000 --- a/libDER/libDERUtils/fileIo.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2005-2007,2010-2012 Apple Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "fileIo.h" - -int writeFile( - const char *fileName, - const unsigned char *bytes, - unsigned numBytes) -{ - int rtn; - int fd; - - fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); - if(fd == -1) { - return errno; - } - rtn = (int)write(fd, bytes, (size_t)numBytes); - if(rtn != (int)numBytes) { - if(rtn >= 0) { - fprintf(stderr, "writeFile: short write\n"); - } - rtn = EIO; - } - else { - rtn = 0; - } - close(fd); - return rtn; -} - -/* - * Read entire file. - */ -int readFile( - const char *fileName, - unsigned char **bytes, // mallocd and returned - unsigned *numBytes) // returned -{ - int rtn; - int fd; - char *buf; - struct stat sb; - unsigned size; - - *numBytes = 0; - *bytes = NULL; - fd = open(fileName, O_RDONLY, 0); - if(fd == -1) { - return errno; - } - rtn = fstat(fd, &sb); - if(rtn) { - goto errOut; - } - size = (unsigned) sb.st_size; - buf = (char *)malloc(size); - if(buf == NULL) { - rtn = ENOMEM; - goto errOut; - } - rtn = (int)read(fd, buf, size); - if(rtn != size) { - if(rtn >= 0) { - fprintf(stderr, "readFile: short read\n"); - } - rtn = EIO; - } - else { - rtn = 0; - *bytes = (unsigned char *)buf; - *numBytes = size; - } -errOut: - close(fd); - return rtn; -} diff --git a/libDER/libDERUtils/fileIo.h b/libDER/libDERUtils/fileIo.h deleted file mode 100644 index 26e31f71..00000000 --- a/libDER/libDERUtils/fileIo.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2005-2007,2010-2011 Apple Inc. All Rights Reserved. - */ - -#ifndef _DER_FILE_IO_H_ -#define _DER_FILE_IO_H_ - -/* - * Read entire file. - */ -#ifdef __cplusplus -extern "C" { -#endif - -int readFile( - const char *fileName, - unsigned char **bytes, // mallocd and returned - unsigned *numBytes); // returned - -int writeFile( - const char *fileName, - const unsigned char *bytes, - unsigned numBytes); - -#ifdef __cplusplus -} -#endif - -#endif /* _DER_FILE_IO_H_ */ diff --git a/libDER/libDERUtils/libDERUtils.c b/libDER/libDERUtils/libDERUtils.c deleted file mode 100644 index 62cfe717..00000000 --- a/libDER/libDERUtils/libDERUtils.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * libDERUtils.c - support routines for libDER tests & examples - * - */ - -#include -#include - -const char *DERReturnString( - DERReturn drtn) -{ - static char unknown[128]; - - switch(drtn) { - case DR_Success: return "DR_Success"; - case DR_EndOfSequence: return "DR_EndOfSequence"; - case DR_UnexpectedTag: return "DR_UnexpectedTag"; - case DR_DecodeError: return "DR_DecodeError"; - case DR_Unimplemented: return "DR_Unimplemented"; - case DR_IncompleteSeq: return "DR_IncompleteSeq"; - default: - sprintf(unknown, "Unknown error (%d)", (int)drtn); - return unknown; - } -} - -void DERPerror( - const char *op, - DERReturn drtn) -{ - fprintf(stderr, "*** %s: %s\n", op, DERReturnString(drtn)); -} - diff --git a/libDER/libDERUtils/printFields.c b/libDER/libDERUtils/printFields.c deleted file mode 100644 index 4df3133a..00000000 --- a/libDER/libDERUtils/printFields.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (c) 2005-2007,2011-2012,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * printFeilds.h - print various DER objects - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static int indentLevel = 0; - -void doIndent(void) -{ - int i; - for (i = 0; ilength; - - printf("<%lu> ", item->length); - if(toPrint > TO_PRINT_MAX) { - toPrint = TO_PRINT_MAX; - } - for(dex=0; dexdata[dex]); - } - if(item->length > TO_PRINT_MAX) { - printf("..."); - } - printf("\n"); -} - -void printBitString( - DERItem *item) -{ - DERSize dex; - DERSize toPrint = item->length; - DERItem bitStringBytes; - DERByte numUnused; - DERReturn drtn; - - drtn = DERParseBitString(item, &bitStringBytes, &numUnused); - if(drtn) { - DERPerror("DERParseBitString", drtn); - return; - } - - printf("<%lu, %lu> ", (unsigned long)bitStringBytes.length, (unsigned long)numUnused); - toPrint = bitStringBytes.length; - if(toPrint > TO_PRINT_MAX) { - toPrint = TO_PRINT_MAX; - } - for(dex=0; dexlength > TO_PRINT_MAX) { - printf("..."); - } - printf("\n"); -} - -void printString( - DERItem *item) -{ - unsigned dex; - char *cp = (char *)item->data; - printf("'"); - for(dex=0; dexlength; dex++) { - putchar(*cp++); - } - printf("'\n"); - -} - -#define COLON_COLUMN 20 - -/* - * Print line header, with current indent, followed by specified label, followed - * by a ':' in column COLON_COLUMN, followed by one space. - */ -void printHeader( - const char *label) -{ - size_t numPrinted; - - doIndent(); - printf("%s", label); - numPrinted = indentLevel + strlen(label); - if(numPrinted < COLON_COLUMN) { - size_t numSpaces = COLON_COLUMN - numPrinted; - size_t dex; - for(dex=0; dex - -#ifdef __cplusplus -extern "C" { -#endif - -void doIndent(void); -void incrIndent(void); -void decrIndent(void); -void printHex(DERItem *item); -void printBitString(DERItem *item); -void printString(DERItem *item); -void printHeader(const char *label); - -typedef enum { - IT_Leaf, // leaf; always print contents - IT_Branch // branch; print contents iff verbose -} ItemType; - -void printItem( - const char *label, - ItemType itemType, - int verbose, - DERTag tag, // maybe from decoding, maybe the real tag underlying - // an implicitly tagged item - DERItem *item); // content - -void printAlgId( - const DERItem *content, - int verbose); -void printSubjPubKeyInfo( - const DERItem *content, - int verbose); - -/* decode one item and print it */ -void decodePrintItem( - const char *label, - ItemType itemType, - int verbose, - DERItem *derItem); - -#ifdef __cplusplus -} -#endif - -#endif /* _PRINT_FIELDS_H_ */ diff --git a/libsecurity_smime/Security b/libsecurity_smime/Security deleted file mode 120000 index 7951405f..00000000 --- a/libsecurity_smime/Security +++ /dev/null @@ -1 +0,0 @@ -lib \ No newline at end of file diff --git a/libsecurity_smime/lib/CMSDecoder.c b/libsecurity_smime/lib/CMSDecoder.c index 8ac1228c..513932d2 100644 --- a/libsecurity_smime/lib/CMSDecoder.c +++ b/libsecurity_smime/lib/CMSDecoder.c @@ -223,7 +223,6 @@ OSStatus CMSDecoderUpdateMessage( case DS_Init: /* First time through; set up */ ASSERT(cmsDecoder->decoder == NULL); - ASSERT(cmsDecoder->arena == NULL); ortn = SecCmsDecoderCreate(NULL, NULL, NULL, NULL, NULL, NULL, &cmsDecoder->decoder); if(ortn) { ortn = cmsRtnToOSStatus(ortn); diff --git a/libsecurity_smime/lib/CMSEncoder.c b/libsecurity_smime/lib/CMSEncoder.c index 8fc6d1d9..1cc87e39 100644 --- a/libsecurity_smime/lib/CMSEncoder.c +++ b/libsecurity_smime/lib/CMSEncoder.c @@ -363,7 +363,7 @@ static OSStatus cmsSetupEncoder( { OSStatus ortn; - ASSERT(cmsEncoder->arena == NULL); + ASSERT(cmsEncoder->cmsMsg != NULL); ASSERT(cmsEncoder->encoder == NULL); cmsEncoder->encoderOut = CFDataCreateMutable(NULL, 0); diff --git a/libsecurity_smime/lib/CMSUtils.h b/libsecurity_smime/lib/CMSUtils.h index 25d5d8fd..bb34dd3c 100644 --- a/libsecurity_smime/lib/CMSUtils.h +++ b/libsecurity_smime/lib/CMSUtils.h @@ -30,7 +30,6 @@ #include #include -#include __BEGIN_DECLS @@ -62,13 +61,14 @@ OSStatus cmsRtnToOSStatusDefault(OSStatus smimeRtn, OSStatus defaultRtn); #define CFRELEASE(cfr) if(cfr != NULL) { CFRelease(cfr); } +#include +#define ASSERT(s) assert(s) + #define CMS_DEBUG 0 #if CMS_DEBUG -#define ASSERT(s) assert(s) #define CSSM_PERROR(s, r) cssmPerror(s, r) #define dprintf(args...) printf(args) #else -#define ASSERT(s) #define CSSM_PERROR(s, r) #define dprintf(args...) #endif diff --git a/libsecurity_smime/lib/cmsdigest.c b/libsecurity_smime/lib/cmsdigest.c index e31f88f6..b511e686 100644 --- a/libsecurity_smime/lib/cmsdigest.c +++ b/libsecurity_smime/lib/cmsdigest.c @@ -34,7 +34,7 @@ /* * CMS digesting. */ -#include +#include #include "cmslocal.h" @@ -44,11 +44,7 @@ #include #include -#if USE_CDSA_CRYPTO -#include -#else #include -#endif #include @@ -60,11 +56,7 @@ struct SecCmsDigestContextStr { PLArenaPool * poolp; Boolean saw_contents; int digcnt; -#if USE_CDSA_CRYPTO - CSSM_CC_HANDLE * digobjs; -#else void ** digobjs; -#endif SECAlgorithmID ** digestalgs; }; @@ -77,17 +69,14 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) { PLArenaPool *poolp; SecCmsDigestContextRef cmsdigcx; -#if USE_CDSA_CRYPTO - CSSM_CC_HANDLE digobj; -#else void * digobj; -#endif int digcnt; int i; poolp = PORT_NewArena(1024); - if (poolp == NULL) - goto loser; + if (poolp == NULL) { + goto loser; + } digcnt = (digestalgs == NULL) ? 0 : SecCmsArrayCount((void **)digestalgs); @@ -98,27 +87,18 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) cmsdigcx->poolp = poolp; if (digcnt > 0) { -#if USE_CDSA_CRYPTO - /* Security check to prevent under-allocation */ - if (digcnt >= (int)((INT_MAX/(MAX(sizeof(CSSM_CC_HANDLE),sizeof(SECAlgorithmID *))))-1)) { - goto loser; - } - cmsdigcx->digobjs = (CSSM_CC_HANDLE *)PORT_ArenaAlloc(poolp, digcnt * sizeof(CSSM_CC_HANDLE)); - if (cmsdigcx->digobjs == NULL) - goto loser; -#else - /* Security check to prevent under-allocation */ - if (digcnt >= (int)((INT_MAX/(MAX(sizeof(void *),sizeof(SECAlgorithmID *))))-1)) { - goto loser; - } - cmsdigcx->digobjs = (void**)PORT_ArenaAlloc(poolp, digcnt * sizeof(void *)); - if (cmsdigcx->digobjs == NULL) - goto loser; -#endif - cmsdigcx->digestalgs = (SECAlgorithmID **)PORT_ArenaZAlloc(poolp, - (digcnt + 1) * sizeof(SECAlgorithmID *)); - if (cmsdigcx->digestalgs == NULL) - goto loser; + /* Security check to prevent under-allocation */ + if (digcnt >= (int)((INT_MAX/(MAX(sizeof(void *),sizeof(SECAlgorithmID *))))-1)) { + goto loser; + } + cmsdigcx->digobjs = (void**)PORT_ArenaAlloc(poolp, digcnt * sizeof(void *)); + if (cmsdigcx->digobjs == NULL) { + goto loser; + } + cmsdigcx->digestalgs = (SECAlgorithmID **)PORT_ArenaZAlloc(poolp, (digcnt + 1) * sizeof(SECAlgorithmID *)); + if (cmsdigcx->digestalgs == NULL) { + goto loser; + } } cmsdigcx->digcnt = 0; @@ -127,31 +107,27 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) * Create a digest object context for each algorithm. */ for (i = 0; i < digcnt; i++) { - digobj = SecCmsUtilGetHashObjByAlgID(digestalgs[i]); - /* - * Skip any algorithm we do not even recognize; obviously, - * this could be a problem, but if it is critical then the - * result will just be that the signature does not verify. - * We do not necessarily want to error out here, because - * the particular algorithm may not actually be important, - * but we cannot know that until later. - */ -#if USE_CDSA_CRYPTO - if (digobj) - if (CSSM_DigestDataInit(digobj)) - goto loser; -#endif + digobj = SecCmsUtilGetHashObjByAlgID(digestalgs[i]); + /* + * Skip any algorithm we do not even recognize; obviously, + * this could be a problem, but if it is critical then the + * result will just be that the signature does not verify. + * We do not necessarily want to error out here, because + * the particular algorithm may not actually be important, + * but we cannot know that until later. + */ - cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj; - cmsdigcx->digestalgs[cmsdigcx->digcnt] = PORT_ArenaAlloc(poolp, sizeof(SECAlgorithmID)); - if (SECITEM_CopyItem(poolp, - &(cmsdigcx->digestalgs[cmsdigcx->digcnt]->algorithm), - &(digestalgs[i]->algorithm)) - || SECITEM_CopyItem(poolp, - &(cmsdigcx->digestalgs[cmsdigcx->digcnt]->parameters), - &(digestalgs[i]->parameters))) - goto loser; - cmsdigcx->digcnt++; + cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj; + cmsdigcx->digestalgs[cmsdigcx->digcnt] = PORT_ArenaAlloc(poolp, sizeof(SECAlgorithmID)); + if (SECITEM_CopyItem(poolp, + &(cmsdigcx->digestalgs[cmsdigcx->digcnt]->algorithm), + &(digestalgs[i]->algorithm)) + || SECITEM_CopyItem(poolp, + &(cmsdigcx->digestalgs[cmsdigcx->digcnt]->parameters), + &(digestalgs[i]->parameters))) { + goto loser; + } + cmsdigcx->digcnt++; } cmsdigcx->saw_contents = PR_FALSE; @@ -159,8 +135,9 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) return cmsdigcx; loser: - if (poolp) - PORT_FreeArena(poolp, PR_FALSE); + if (poolp) { + PORT_FreeArena(poolp, PR_FALSE); + } return NULL; } @@ -191,35 +168,31 @@ SecCmsDigestContextUpdate(SecCmsDigestContextRef cmsdigcx, const unsigned char * dataBuf.Data = (uint8_t *)data; cmsdigcx->saw_contents = PR_TRUE; for (i = 0; i < cmsdigcx->digcnt; i++) { - if (cmsdigcx->digobjs[i]) { -#if USE_CDSA_CRYPTO - CSSM_DigestDataUpdate(cmsdigcx->digobjs[i], &dataBuf, 1); -#else + if (cmsdigcx->digobjs[i]) { /* 64 bits cast: worst case is we truncate the length and we dont hash all the data. - This may cause an invalid CMS blob larger than 4GB to be validated. Unlikely, but - possible security issue. There is no way to return an error here, but a check at - the upper level may happen. */ - /* - rdar://problem/20642513 - Let's just die a horrible death rather than have the security issue. - CMS blob over 4GB? Oh well. - */ - if (len > UINT32_MAX) { - /* Ugh. */ - abort(); - } + This may cause an invalid CMS blob larger than 4GB to be validated. Unlikely, but + possible security issue. There is no way to return an error here, but a check at + the upper level may happen. */ + /* + rdar://problem/20642513 + Let's just die a horrible death rather than have the security issue. + CMS blob over 4GB? Oh well. + */ + if (len > UINT32_MAX) { + /* Ugh. */ + abort(); + } assert(len<=UINT32_MAX); /* Debug check. Correct as long as CC_LONG is uint32_t */ switch (SECOID_GetAlgorithmTag(cmsdigcx->digestalgs[i])) { - case SEC_OID_SHA1: CC_SHA1_Update((CC_SHA1_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; - case SEC_OID_MD5: CC_MD5_Update((CC_MD5_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; - case SEC_OID_SHA224: CC_SHA224_Update((CC_SHA256_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; - case SEC_OID_SHA256: CC_SHA256_Update((CC_SHA256_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; - case SEC_OID_SHA384: CC_SHA384_Update((CC_SHA512_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; - case SEC_OID_SHA512: CC_SHA512_Update((CC_SHA512_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; - default: - break; + case SEC_OID_SHA1: CC_SHA1_Update((CC_SHA1_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_MD5: CC_MD5_Update((CC_MD5_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA224: CC_SHA224_Update((CC_SHA256_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA256: CC_SHA256_Update((CC_SHA256_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA384: CC_SHA384_Update((CC_SHA512_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA512: CC_SHA512_Update((CC_SHA512_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + default: + break; } -#endif } } } @@ -232,13 +205,12 @@ SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx) { int i; - for (i = 0; i < cmsdigcx->digcnt; i++) - if (cmsdigcx->digobjs[i]) -#if USE_CDSA_CRYPTO - CSSM_DeleteContext(cmsdigcx->digobjs[i]); -#else + for (i = 0; i < cmsdigcx->digcnt; i++) { + if (cmsdigcx->digobjs && cmsdigcx->digobjs[i]) { free(cmsdigcx->digobjs[i]); -#endif + cmsdigcx->digobjs[i] = NULL; + } + } PORT_FreeArena(cmsdigcx->poolp, PR_TRUE); } @@ -254,17 +226,16 @@ SecCmsDigestContextDestroy(SecCmsDigestContextRef cmsdigcx) /* * SecCmsDigestContextFinishMultiple - finish the digests + * Note that on iOS, this call only frees the digest objects and requires a call to SecCmsDisgestContextDestroy + * or SecCmsDisgestContextCancel (because the digests are allocated out of the context's pool). + * The macOS version cancels and frees the digest context (because the digests are allocated from an input arena pool). */ OSStatus SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, - SECAlgorithmID ***digestalgsp, - SecAsn1Item * **digestsp) + SECAlgorithmID ***digestalgsp, + SecAsn1Item * **digestsp) { -#if USE_CDSA_CRYPTO - CSSM_CC_HANDLE digboj; -#else void * digobj; -#endif SecAsn1Item **digests, *digest; SECAlgorithmID **digestalgs; int i; @@ -277,17 +248,16 @@ SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, #if 0 /* no contents? do not update digests */ if (digestsp == NULL || !cmsdigcx->saw_contents) { - for (i = 0; i < cmsdigcx->digcnt; i++) - if (cmsdigcx->digobjs[i]) -#if USE_CDSA_CRYPTO - CSSM_DeleteContext(cmsdigcx->digobjs[i]); -#else + for (i = 0; i < cmsdigcx->digcnt; i++) { + if (cmsdigcx->digobjs[i]) { free(cmsdigcx->digobjs[i]); -#endif - rv = SECSuccess; - if (digestsp) - *digestsp = NULL; - goto cleanup; + } + } + rv = SECSuccess; + if (digestsp) { + *digestsp = NULL; + } + goto cleanup; } #endif @@ -305,14 +275,13 @@ SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, digests = (SecAsn1Item * *)PORT_ArenaZAlloc(cmsdigcx->poolp, (cmsdigcx->digcnt+1) * sizeof(SecAsn1Item *)); digest = (SecAsn1Item *)PORT_ArenaZAlloc(cmsdigcx->poolp, cmsdigcx->digcnt * sizeof(SecAsn1Item)); if (digestalgs == NULL || digests == NULL || digest == NULL) { - goto loser; + goto loser; } for (i = 0; i < cmsdigcx->digcnt; i++, digest++) { - SECOidTag hash_alg = SECOID_GetAlgorithmTag(cmsdigcx->digestalgs[i]); - int diglength = 0; - + int diglength = 0; + switch (hash_alg) { case SEC_OID_SHA1: diglength = CC_SHA1_DIGEST_LENGTH; break; case SEC_OID_MD5: diglength = CC_MD5_DIGEST_LENGTH; break; @@ -323,17 +292,12 @@ SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, default: goto loser; } - digobj = cmsdigcx->digobjs[i]; - if (digobj) - { - digest->Data = (unsigned char*)PORT_ArenaAlloc(cmsdigcx->poolp, diglength); - if (digest->Data == NULL) - goto loser; - digest->Length = diglength; -#if USE_CDSA_CRYPTO - CSSM_DigestDataFinal(digobj, digest); - CSSM_DeleteContext(digobj); -#else + digobj = cmsdigcx->digobjs[i]; + if (digobj) { + digest->Data = (unsigned char*)PORT_ArenaAlloc(cmsdigcx->poolp, diglength); + if (digest->Data == NULL) + goto loser; + digest->Length = diglength; switch (hash_alg) { case SEC_OID_SHA1: CC_SHA1_Final(digest->Data, digobj); break; case SEC_OID_MD5: CC_MD5_Final(digest->Data, digobj); break; @@ -345,15 +309,12 @@ SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, } free(digobj); -#endif - digestalgs[i] = cmsdigcx->digestalgs[i]; - digests[i] = digest; - } - else - { - digest->Data = NULL; - digest->Length = 0; - } + digestalgs[i] = cmsdigcx->digestalgs[i]; + digests[i] = digest; + } else { + digest->Data = NULL; + digest->Length = 0; + } } digestalgs[i] = NULL; digests[i] = NULL; @@ -363,13 +324,14 @@ SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, rv = SECSuccess; loser: - if (rv == SECSuccess) - PORT_ArenaUnmark(cmsdigcx->poolp, mark); - else - PORT_ArenaRelease(cmsdigcx->poolp, mark); + if (rv == SECSuccess) { + PORT_ArenaUnmark(cmsdigcx->poolp, mark); + } else { + PORT_ArenaRelease(cmsdigcx->poolp, mark); + } -/*cleanup:*/ - /* Set things up so SecCmsDigestContextDestroy won't call CSSM_DeleteContext again. */ + /*cleanup:*/ + /* Set things up so SecCmsDigestContextDestroy won't call CSSM_DeleteContext again. */ cmsdigcx->digcnt = 0; return rv; @@ -381,15 +343,16 @@ loser: */ OSStatus SecCmsDigestContextFinishSingle(SecCmsDigestContextRef cmsdigcx, - SecAsn1Item * digest) + SecAsn1Item * digest) { OSStatus rv = SECFailure; SecAsn1Item * *dp; SECAlgorithmID **ap; /* get the digests into arena, then copy the first digest into poolp */ - if (SecCmsDigestContextFinishMultiple(cmsdigcx, &ap, &dp) != SECSuccess) - goto loser; + if (SecCmsDigestContextFinishMultiple(cmsdigcx, &ap, &dp) != SECSuccess) { + goto loser; + } /* Return the first element in the digest array. */ if (digest) { diff --git a/libsecurity_smime/lib/cmspriv.h b/libsecurity_smime/lib/cmspriv.h index 1c309f03..9d2597a5 100644 --- a/libsecurity_smime/lib/cmspriv.h +++ b/libsecurity_smime/lib/cmspriv.h @@ -95,11 +95,8 @@ SecCmsAlgArrayGetIndexByAlgID(SECAlgorithmID **algorithmArray, SECAlgorithmID *a extern int SecCmsAlgArrayGetIndexByAlgTag(SECAlgorithmID **algorithmArray, SECOidTag algtag); -#if USE_CDSA_CRYPTO -extern CSSM_CC_HANDLE -#else + extern void * -#endif SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid); /* diff --git a/libsecurity_smime/lib/cmssiginfo.c b/libsecurity_smime/lib/cmssiginfo.c index c0d70ea9..2edf9680 100644 --- a/libsecurity_smime/lib/cmssiginfo.c +++ b/libsecurity_smime/lib/cmssiginfo.c @@ -469,7 +469,8 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAs SECITEM_FreeItem(&signature, PR_FALSE); - if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), pubkAlgTag, + SECOidTag sigAlgTag = SecCmsUtilMakeSignatureAlgorithm(digestalgtag, pubkAlgTag); + if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), sigAlgTag, NULL) != SECSuccess) goto loser; @@ -1131,21 +1132,18 @@ SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo) SecCertificateRef signercert; CFStringRef emailAddress = NULL; - if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) - return NULL; + if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) { + return NULL; + } -#if USE_CDSA_CRYPTO - SecCertificateGetEmailAddress(signercert, &emailAddress); -#else CFArrayRef names = SecCertificateCopyRFC822Names(signercert); if (names) { - if (CFArrayGetCount(names) > 0) + if (CFArrayGetCount(names) > 0) { emailAddress = (CFStringRef)CFArrayGetValueAtIndex(names, 0); - if (emailAddress) - CFRetain(emailAddress); + } + CFRetainSafe(emailAddress); CFRelease(names); } -#endif return emailAddress; } diff --git a/libsecurity_smime/lib/cmsutil.c b/libsecurity_smime/lib/cmsutil.c index 9ed5d173..e462cab5 100644 --- a/libsecurity_smime/lib/cmsutil.c +++ b/libsecurity_smime/lib/cmsutil.c @@ -227,58 +227,42 @@ SecCmsAlgArrayGetIndexByAlgTag(SECAlgorithmID **algorithmArray, return i; } -#if USE_CDSA_CRYPTO -CSSM_CC_HANDLE -#else void * -#endif SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid) { SECOidData *oidData = SECOID_FindOID(&(algid->algorithm)); if (oidData) { -#if USE_CDSA_CRYPTO - CSSM_ALGORITHMS alg = oidData->cssmAlgorithm; - if (alg) - { - CSSM_CC_HANDLE digobj; - CSSM_CSP_HANDLE cspHandle = SecCspHandleForAlgorithm(alg); - - if (!CSSM_CSP_CreateDigestContext(cspHandle, alg, &digobj)) - return digobj; - } -#else void *digobj = NULL; switch (oidData->offset) { - case SEC_OID_SHA1: - digobj = calloc(1, sizeof(CC_SHA1_CTX)); - CC_SHA1_Init(digobj); - break; - case SEC_OID_MD5: - digobj = calloc(1, sizeof(CC_MD5_CTX)); - CC_MD5_Init(digobj); - break; - case SEC_OID_SHA224: - digobj = calloc(1, sizeof(CC_SHA256_CTX)); - CC_SHA224_Init(digobj); - break; - case SEC_OID_SHA256: - digobj = calloc(1, sizeof(CC_SHA256_CTX)); - CC_SHA256_Init(digobj); - break; - case SEC_OID_SHA384: - digobj = calloc(1, sizeof(CC_SHA512_CTX)); - CC_SHA384_Init(digobj); - break; - case SEC_OID_SHA512: - digobj = calloc(1, sizeof(CC_SHA512_CTX)); - CC_SHA512_Init(digobj); - break; - default: - break; + case SEC_OID_SHA1: + digobj = calloc(1, sizeof(CC_SHA1_CTX)); + CC_SHA1_Init(digobj); + break; + case SEC_OID_MD5: + digobj = calloc(1, sizeof(CC_MD5_CTX)); + CC_MD5_Init(digobj); + break; + case SEC_OID_SHA224: + digobj = calloc(1, sizeof(CC_SHA256_CTX)); + CC_SHA224_Init(digobj); + break; + case SEC_OID_SHA256: + digobj = calloc(1, sizeof(CC_SHA256_CTX)); + CC_SHA256_Init(digobj); + break; + case SEC_OID_SHA384: + digobj = calloc(1, sizeof(CC_SHA512_CTX)); + CC_SHA384_Init(digobj); + break; + case SEC_OID_SHA512: + digobj = calloc(1, sizeof(CC_SHA512_CTX)); + CC_SHA512_Init(digobj); + break; + default: + break; } return digobj; -#endif } return 0; diff --git a/libsecurity_smime/lib/crypto-embedded.c b/libsecurity_smime/lib/crypto-embedded.c index c816df52..8e9a4b9b 100644 --- a/libsecurity_smime/lib/crypto-embedded.c +++ b/libsecurity_smime/lib/crypto-embedded.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -231,35 +232,40 @@ SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef ce void *mark; mark = PORT_ArenaMark(pl); - CFDataRef serial_data = NULL; CFDataRef issuer_data = SecCertificateCopyIssuerSequence(cert); - if (!issuer_data) + CFDataRef serial_data = SecCertificateCopySerialNumberData(cert, NULL); + if (!issuer_data || !serial_data) { goto loser; - serial_data = SecCertificateCopySerialNumberData(cert, NULL); - if (!serial_data) - goto loser; - - SecAsn1Item serialNumber = { CFDataGetLength(serial_data), - (uint8_t *)CFDataGetBytePtr(serial_data) }; - SecAsn1Item issuer = { CFDataGetLength(issuer_data), - (uint8_t *)CFDataGetBytePtr(issuer_data) }; - - /* Allocate the SecCmsIssuerAndSN struct. */ + } + + SecAsn1Item serialNumber = { + .Length = CFDataGetLength(serial_data), + .Data = (uint8_t *)CFDataGetBytePtr(serial_data) + }; + SecAsn1Item issuer = { + .Length = CFDataGetLength(issuer_data), + .Data = (uint8_t *)CFDataGetBytePtr(issuer_data) + }; + + /* Allocate the SecCmsIssuerAndSN struct. */ certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN)); - if (certIssuerAndSN == NULL) - goto loser; + if (certIssuerAndSN == NULL) { + goto loser; + } /* Copy the issuer. */ certIssuerAndSN->derIssuer.Data = (uint8_t *) PORT_ArenaAlloc(pl, issuer.Length); - if (!certIssuerAndSN->derIssuer.Data) - goto loser; + if (!certIssuerAndSN->derIssuer.Data) { + goto loser; + } PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer.Data, issuer.Length); certIssuerAndSN->derIssuer.Length = issuer.Length; /* Copy the serialNumber. */ certIssuerAndSN->serialNumber.Data = (uint8_t *) PORT_ArenaAlloc(pl, serialNumber.Length); - if (!certIssuerAndSN->serialNumber.Data) - goto loser; + if (!certIssuerAndSN->serialNumber.Data) { + goto loser; + } PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length); certIssuerAndSN->serialNumber.Length = serialNumber.Length; @@ -267,14 +273,12 @@ SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef ce CFRelease(issuer_data); PORT_ArenaUnmark(pl, mark); - + return certIssuerAndSN; loser: - if (serial_data) - CFRelease(serial_data); - if (issuer_data) - CFRelease(issuer_data); + CFReleaseNull(serial_data); + CFReleaseNull(issuer_data); PORT_ArenaRelease(pl, mark); PORT_SetError(SEC_INTERNAL_ONLY); diff --git a/libsecurity_smime/lib/testcms b/libsecurity_smime/lib/testcms old mode 100644 new mode 100755 diff --git a/libsecurity_smime/security_smime b/libsecurity_smime/security_smime deleted file mode 120000 index 7951405f..00000000 --- a/libsecurity_smime/security_smime +++ /dev/null @@ -1 +0,0 @@ -lib \ No newline at end of file diff --git a/ntlm/NtlmGenerator.c b/ntlm/NtlmGenerator.c index 90762e16..f8fb24e2 100644 --- a/ntlm/NtlmGenerator.c +++ b/ntlm/NtlmGenerator.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include /* @@ -662,13 +662,15 @@ OSStatus _NtlmGeneratePasswordHashes( unsigned char hash[NTLM_DIGEST_LENGTH]; result = ntlmPasswordHash(password, hash); - if (result) + if (result) { return result; - - *ntlmHash = CFDataCreate(alloc, hash, sizeof(hash)); + } + + *ntlmHash = CFDataCreate(alloc, hash, sizeof(hash)); memset(hash, 0, sizeof(hash)); - if (*ntlmHash == NULL) + if (*ntlmHash == NULL) { result = errSecAllocate; + } static const UInt8 zero[NTLM_DIGEST_LENGTH] = { 0 }; *lmHash = CFDataCreate(NULL, zero, sizeof(zero)); diff --git a/ntlm/ntlmBlobPriv.c b/ntlm/ntlmBlobPriv.c index 5866c307..e6a28592 100644 --- a/ntlm/ntlmBlobPriv.c +++ b/ntlm/ntlmBlobPriv.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -183,12 +183,14 @@ OSStatus ntlmStringToLE( unsigned *ucodeLen) // RETURNED { CFIndex len = CFStringGetLength(pwd); - if (len > NTLM_MAX_STRING_LEN) + if (len > NTLM_MAX_STRING_LEN) { return errSecAllocate; - unsigned char *data = (unsigned char *)malloc(len * 2); - if (data == NULL) + } + unsigned char *data = (unsigned char *)malloc(len * 2); + if (data == NULL) { return errSecAllocate; - unsigned char *cp = data; + } + unsigned char *cp = data; CFIndex dex; for(dex=0; dexenable_ech; + + return true; + }); + + return enable_ech; +} + void sec_protocol_options_add_tls_application_protocol(sec_protocol_options_t options, const char *application_protocol) { @@ -502,6 +520,78 @@ sec_protocol_options_add_tls_application_protocol(sec_protocol_options_t options }); } +void +sec_protocol_options_add_transport_specific_application_protocol(sec_protocol_options_t options, const char *application_protocol, sec_protocol_transport_t specific_transport) +{ + SEC_PROTOCOL_OPTIONS_VALIDATE(options,); + SEC_PROTOCOL_OPTIONS_VALIDATE(application_protocol,); + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + if (content->application_protocols == NULL) { + content->application_protocols = xpc_array_create(NULL, 0); + } + xpc_object_t tuple = xpc_array_create(NULL, 0); + if (tuple != NULL) { + xpc_array_set_string(tuple, XPC_ARRAY_APPEND, application_protocol); + xpc_array_set_uint64(tuple, XPC_ARRAY_APPEND, (uint64_t)specific_transport); + + xpc_array_append_value(content->application_protocols, tuple); + xpc_release(tuple); + } + return true; + }); +} + +xpc_object_t +sec_protocol_options_copy_transport_specific_application_protocol(sec_protocol_options_t options, sec_protocol_transport_t specific_transport) +{ + SEC_PROTOCOL_OPTIONS_VALIDATE(options, NULL); + + xpc_object_t filtered_application_protocols = xpc_array_create(NULL, 0); + + bool success = sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + xpc_object_t application_protocols = content->application_protocols; + if (application_protocols == NULL) { + return false; + } + + size_t application_protocol_count = xpc_array_get_count(application_protocols); + for (size_t i = 0; i < application_protocol_count; i++) { + xpc_object_t application_protocol = xpc_array_get_value(application_protocols, i); + + if (xpc_get_type(application_protocol) == XPC_TYPE_STRING) { + xpc_array_set_string(filtered_application_protocols, XPC_ARRAY_APPEND, xpc_string_get_string_ptr(application_protocol)); + continue; + } + + if (xpc_get_type(application_protocol) == XPC_TYPE_ARRAY) { + uint64_t application_protocol_transport = xpc_array_get_uint64(application_protocol, 1); + if (application_protocol_transport != (uint64_t)specific_transport && specific_transport != sec_protocol_transport_any) { + continue; + } + + xpc_array_set_string(filtered_application_protocols, XPC_ARRAY_APPEND, xpc_array_get_string(application_protocol, 0)); + continue; + } + } + + return xpc_array_get_count(filtered_application_protocols) != 0; + }); + + if (!success) { + xpc_release(filtered_application_protocols); + filtered_application_protocols = NULL; + } + + return filtered_application_protocols; +} + void sec_protocol_options_set_tls_server_name(sec_protocol_options_t options, const char *server_name) { @@ -512,17 +602,7 @@ sec_protocol_options_set_tls_server_name(sec_protocol_options_t options, const c sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); - CFStringRef serverName = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingUTF8); - if (serverName == NULL) { - return false; - } - if (!SecFrameworkIsDNSName(serverName)) { - CFRelease(serverName); - return false; - } - CFRelease(serverName); - - free(content->server_name); + free(content->server_name); content->server_name = strdup(server_name); return true; }); @@ -787,6 +867,33 @@ sec_protocol_options_set_peer_authentication_required(sec_protocol_options_t opt }); } +void +sec_protocol_options_set_peer_authentication_optional(sec_protocol_options_t options, bool peer_authentication_optional) { + SEC_PROTOCOL_OPTIONS_VALIDATE(options,); + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + content->peer_authentication_optional = peer_authentication_optional; + content->peer_authentication_override = true; + return true; + }); +} + +void +sec_protocol_options_set_enable_encrypted_client_hello(sec_protocol_options_t options, bool enable_encrypted_client_hello) { + SEC_PROTOCOL_OPTIONS_VALIDATE(options,); + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + content->enable_ech = enable_encrypted_client_hello; + return true; + }); +} + void sec_protocol_options_set_key_update_block(sec_protocol_options_t options, sec_protocol_key_update_t update_block, dispatch_queue_t update_queue) { @@ -909,6 +1016,31 @@ sec_protocol_options_set_tls_encryption_secret_update_block(sec_protocol_options }); } +void +sec_protocol_options_set_tls_encryption_level_update_block(sec_protocol_options_t options, sec_protocol_tls_encryption_level_update_t update_block, dispatch_queue_t update_queue) +{ + SEC_PROTOCOL_OPTIONS_VALIDATE(options,); + SEC_PROTOCOL_OPTIONS_VALIDATE(update_block,); + SEC_PROTOCOL_OPTIONS_VALIDATE(update_queue,); + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + if (content->tls_encryption_level_update_block != NULL) { + Block_release(content->tls_encryption_level_update_block); + } + if (content->tls_encryption_level_update_queue != NULL) { + dispatch_release(content->tls_encryption_level_update_queue); + } + + content->tls_encryption_level_update_block = Block_copy(update_block); + content->tls_encryption_level_update_queue = update_queue; + dispatch_retain(content->tls_encryption_level_update_queue); + return true; + }); +} + void sec_protocol_options_set_session_state(sec_protocol_options_t options, dispatch_data_t session_state) { @@ -1130,34 +1262,6 @@ sec_protocol_options_tls_handshake_message_callback(sec_protocol_options_t optio }); } -void -sec_protocol_options_set_tls_SIKE503_exchange_enabled(sec_protocol_options_t options, bool tls_SIKE503_exchange_enabled) -{ - SEC_PROTOCOL_OPTIONS_VALIDATE(options,); - - (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { - sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; - SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); - - content->tls_SIKE503_exchange_enabled = tls_SIKE503_exchange_enabled; - return true; - }); -} - -void -sec_protocol_options_set_tls_HRSS_exchange_enabled(sec_protocol_options_t options, bool tls_HRSS_exchange_enabled) -{ - SEC_PROTOCOL_OPTIONS_VALIDATE(options,); - - (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { - sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; - SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); - - content->tls_HRSS_exchange_enabled = tls_HRSS_exchange_enabled; - return true; - }); -} - void sec_protocol_options_set_eddsa_enabled(sec_protocol_options_t options, bool eddsa_enabled) { @@ -1200,6 +1304,21 @@ sec_protocol_options_set_tls_grease_enabled(sec_protocol_options_t options, bool }); } +void +sec_protocol_options_set_allow_unknown_alpn_protos(sec_protocol_options_t options, bool allow_unknown_alpn_protos) +{ + SEC_PROTOCOL_OPTIONS_VALIDATE(options,); + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + content->allow_unknown_alpn_protos = allow_unknown_alpn_protos; + content->allow_unknown_alpn_protos_override = true; + return true; + }); +} + void sec_protocol_options_set_experiment_identifier(sec_protocol_options_t options, const char *experiment_identifier) { @@ -2122,9 +2241,8 @@ static const char *_options_bool_keys[] = { SEC_PROTOCOL_OPTIONS_KEY_enable_renegotiation, SEC_PROTOCOL_OPTIONS_KEY_enable_early_data, SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_required, + SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_optional, SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled, - SEC_PROTOCOL_OPTIONS_KEY_tls_SIKE503_exchange_enabled, - SEC_PROTOCOL_OPTIONS_KEY_tls_HRSS_exchange_enabled, SEC_PROTOCOL_OPTIONS_KEY_eddsa_enabled, SEC_PROTOCOL_OPTIONS_KEY_tls_delegated_credentials_enabled, SEC_PROTOCOL_OPTIONS_KEY_tls_grease_enabled, @@ -2214,9 +2332,8 @@ _serialize_options(xpc_object_t dictionary, sec_protocol_options_content_t optio xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_renegotiation)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_early_data)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(peer_authentication_required)); + xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(peer_authentication_optional)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(certificate_compression_enabled)); - xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_SIKE503_exchange_enabled)); - xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_HRSS_exchange_enabled)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(eddsa_enabled)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_delegated_credentials_enabled)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_grease_enabled)); @@ -2290,18 +2407,14 @@ static struct _options_bool_key_setter { .key = SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_required, .setter_pointer = sec_protocol_options_set_peer_authentication_required, }, + { + .key = SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_optional, + .setter_pointer = sec_protocol_options_set_peer_authentication_optional, + }, { .key = SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled, .setter_pointer = sec_protocol_options_set_tls_certificate_compression_enabled, }, - { - .key = SEC_PROTOCOL_OPTIONS_KEY_tls_SIKE503_exchange_enabled, - .setter_pointer = sec_protocol_options_set_tls_SIKE503_exchange_enabled, - }, - { - .key = SEC_PROTOCOL_OPTIONS_KEY_tls_HRSS_exchange_enabled, - .setter_pointer = sec_protocol_options_set_tls_HRSS_exchange_enabled, - }, { .key = SEC_PROTOCOL_OPTIONS_KEY_eddsa_enabled, .setter_pointer = sec_protocol_options_set_eddsa_enabled, @@ -2711,3 +2824,17 @@ sec_protocol_options_apply_config(sec_protocol_options_t options, xpc_object_t c return _apply_config_options(options, config); } + +bool +sec_protocol_options_set_tls_block_length_padding(sec_protocol_options_t options, sec_protocol_block_length_padding_t block_length_padding) +{ + SEC_PROTOCOL_METADATA_VALIDATE(options, false); + + return sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + content->tls_block_length_padding = block_length_padding; + return true; + }); +} diff --git a/protocol/SecProtocolConfiguration.h b/protocol/SecProtocolConfiguration.h index 6d8694d3..c57ebf5c 100644 --- a/protocol/SecProtocolConfiguration.h +++ b/protocol/SecProtocolConfiguration.h @@ -143,11 +143,14 @@ sec_protocol_configuration_tls_required(sec_protocol_configuration_t config); * @param host * A NULL-terminated C string containing the host endpoint to examine. * + * @param is_direct + * A flag which indicates if the given hostname is local (direct). + * * @return True if connections to the endpoint require TLS, and false otherwise. */ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) bool -sec_protocol_configuration_tls_required_for_host(sec_protocol_configuration_t config, const char *host); +sec_protocol_configuration_tls_required_for_host(sec_protocol_configuration_t config, const char *host, bool is_direct); /*! * @function sec_protocol_configuration_tls_required_for_address diff --git a/protocol/SecProtocolConfiguration.m b/protocol/SecProtocolConfiguration.m index a88816f1..5f31e234 100644 --- a/protocol/SecProtocolConfiguration.m +++ b/protocol/SecProtocolConfiguration.m @@ -11,7 +11,7 @@ #import #define MINIMUM_RSA_KEY_SIZE 2048 -#define MINIMUM_ECDSA_KEY_SIZE 2048 +#define MINIMUM_ECDSA_KEY_SIZE 256 #define MINIMUM_HASH_ALGORITHM kSecSignatureHashAlgorithmSHA256 #define MINIMUM_PROTOCOL kTLSProtocol12 @@ -187,7 +187,7 @@ sec_protocol_configuration_tls_required(sec_protocol_configuration_t config) } static bool -sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configuration_t config, const char *host, bool parent_domain) +sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configuration_t config, const char *host, bool parent_domain, bool is_direct) { xpc_object_t map = sec_protocol_configuration_get_map(config); if (map == nil) { @@ -195,6 +195,11 @@ sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configura return true; } + if (is_direct && xpc_dictionary_get_bool(map, kAllowsLocalNetworking)) { + // Local domains do not require TLS if the kAllowsLocalNetworking flag is set. + return false; + } + xpc_object_t domain_map = xpc_dictionary_get_dictionary(map, kExceptionDomains); if (domain_map == nil) { // Absent per-domain exceptions, use the default. @@ -205,7 +210,7 @@ sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configura if (entry == nil) { const char *parent_host = _find_parent_domain(host); if (parent_host != NULL) { - return sec_protocol_configuration_tls_required_for_host_internal(config, parent_host, true); + return sec_protocol_configuration_tls_required_for_host_internal(config, parent_host, true, is_direct); } return sec_protocol_configuration_tls_required(config); } @@ -222,9 +227,9 @@ sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configura } bool -sec_protocol_configuration_tls_required_for_host(sec_protocol_configuration_t config, const char *host) +sec_protocol_configuration_tls_required_for_host(sec_protocol_configuration_t config, const char *host, bool is_direct) { - return sec_protocol_configuration_tls_required_for_host_internal(config, host, false); + return sec_protocol_configuration_tls_required_for_host_internal(config, host, false, is_direct); } bool @@ -332,17 +337,21 @@ sec_protocol_configuration_set_ats_overrides(sec_protocol_configuration_t config #define BOOLEAN_FOR_KEY(dictionary, key, value, default) \ bool value = default; \ { \ - NSNumber *nsValue = [dictionary valueForKey:[[NSString alloc] initWithFormat:@"%s", key]]; \ - if (nsValue) { \ - value = [nsValue boolValue]; \ + if (dictionary[[[NSString alloc] initWithFormat:@"%s", key]]) { \ + NSNumber *nsValue = [dictionary valueForKey:[[NSString alloc] initWithFormat:@"%s", key]]; \ + if (nsValue) { \ + value = [nsValue boolValue]; \ + } \ } \ } #define STRING_FOR_KEY(dictionary, key, value, default) \ NSString *value = default; \ { \ - NSString *nsValue = [dictionary valueForKey:[[NSString alloc] initWithFormat:@"%s", key]]; \ - if (nsValue) { \ - value = nsValue; \ + if (dictionary[[[NSString alloc] initWithFormat:@"%s", key]]) { \ + NSString *nsValue = [dictionary valueForKey:[[NSString alloc] initWithFormat:@"%s", key]]; \ + if (nsValue) { \ + value = nsValue; \ + } \ } \ } @@ -381,13 +390,12 @@ sec_protocol_configuration_set_ats_overrides(sec_protocol_configuration_t config *stop = YES; } + BOOLEAN_FOR_KEY(entry, kExceptionAllowsInsecureHTTPLoads, allows_http, false); + BOOLEAN_FOR_KEY(entry, kIncludesSubdomains, includes_subdomains, false); + BOOLEAN_FOR_KEY(entry, kExceptionRequiresForwardSecrecy, requires_pfs, false); + STRING_FOR_KEY(entry, kExceptionMinimumTLSVersion, minimum_tls, @"TLSv1.2"); + xpc_object_t entry_map = xpc_dictionary_create(NULL, NULL, 0); - - BOOLEAN_FOR_KEY(entry_map, kExceptionAllowsInsecureHTTPLoads, allows_http, false); - BOOLEAN_FOR_KEY(entry_map, kIncludesSubdomains, includes_subdomains, false); - BOOLEAN_FOR_KEY(entry_map, kExceptionRequiresForwardSecrecy, requires_pfs, false); - STRING_FOR_KEY(entry_map, kExceptionMinimumTLSVersion, minimum_tls, @"TLSv1.2"); - xpc_dictionary_set_bool(entry_map, kIncludesSubdomains, includes_subdomains); xpc_dictionary_set_bool(entry_map, kExceptionAllowsInsecureHTTPLoads, allows_http); xpc_dictionary_set_bool(entry_map, kExceptionRequiresForwardSecrecy, requires_pfs); diff --git a/protocol/SecProtocolConfigurationTest.m b/protocol/SecProtocolConfigurationTest.m index ef0b8aac..56a59317 100644 --- a/protocol/SecProtocolConfigurationTest.m +++ b/protocol/SecProtocolConfigurationTest.m @@ -350,16 +350,23 @@ protocol_string_to_version(const char *protocol) return (sec_protocol_options_t)_nw_protocol_create_options(mock_protocol_copy_definition()); } +static bool +isLocalTLD(NSString *host) +{ + if ([host length] == 0) { + return false; + } + if ([host hasSuffix:@".local"] || [host hasSuffix:@".local."]) { + return true; + } + if ([host rangeOfString:@"."].location == NSNotFound) { + return true; + } + return false; +} + - (void)testExampleFile:(NSURL *)path { - NSDictionary *dictionary = [[NSDictionary alloc] init]; - sec_protocol_configuration_builder_t builder = sec_protocol_configuration_builder_create((__bridge CFDictionaryRef)dictionary, true); - sec_protocol_configuration_t configuration = sec_protocol_configuration_create_with_builder(builder); - XCTAssertTrue(configuration != nil, @"failed to build configuration"); - if (!configuration) { - return; - } - NSData *exampleData = [[NSData alloc] initWithContentsOfURL:path]; NSDictionary *exampleATS = [NSJSONSerialization JSONObjectWithData:exampleData options:kNilOptions error:nil]; XCTAssertNotNil(exampleATS, @"Loading %@ failed", path); @@ -367,6 +374,24 @@ protocol_string_to_version(const char *protocol) return; } + sec_protocol_configuration_builder_t builder = sec_protocol_configuration_builder_create((__bridge CFDictionaryRef)exampleATS, true); + sec_protocol_configuration_t configuration = sec_protocol_configuration_create_with_builder(builder); + XCTAssertTrue(configuration != nil, @"failed to build configuration"); + if (!configuration) { + return; + } + + __block bool allows_local_networking = false; + [exampleATS enumerateKeysAndObjectsUsingBlock:^(id _key, id _obj, BOOL *stop) { + NSString *key = (NSString *)_key; + if ([key isEqualToString:@"NSAllowsLocalNetworking"]) { + NSNumber *value = (NSNumber *)_obj; + if (value) { + allows_local_networking = [value boolValue]; + } + } + }]; + [exampleATS enumerateKeysAndObjectsUsingBlock:^(id _key, id _obj, BOOL *stop) { NSString *key = (NSString *)_key; if ([key isEqualToString:@"NSExceptionDomains"]) { @@ -415,7 +440,15 @@ protocol_string_to_version(const char *protocol) } }); - XCTAssertTrue(allows_http != sec_protocol_configuration_tls_required_for_host(configuration, [domain cStringUsingEncoding:NSUTF8StringEncoding])); + bool is_direct = isLocalTLD(domain); + bool tls_required = sec_protocol_configuration_tls_required_for_host(configuration, [domain cStringUsingEncoding:NSUTF8StringEncoding], is_direct); + if (is_direct) { + // If the hostname is direct, then we permit it if the NSAllowsLocalNetworking exception is set. + XCTAssertTrue(allows_local_networking != tls_required); + } else { + // Otherwise, we require TLS it the NSExceptionAllowsInsecureHTTPLoads flag is set. + XCTAssertTrue(allows_http != tls_required); + } }]; } }]; diff --git a/protocol/SecProtocolHelper.m b/protocol/SecProtocolHelper.m index 307ea379..23736e46 100644 --- a/protocol/SecProtocolHelper.m +++ b/protocol/SecProtocolHelper.m @@ -98,16 +98,6 @@ static const struct tls_ciphersuite_definition tls_ciphersuite_definitions[] = { static const size_t tls_ciphersuite_definitions_length = \ sizeof(tls_ciphersuite_definitions) / sizeof(struct tls_ciphersuite_definition); -// Remove macro definitions -#undef CiphersuitesTLS13 -#undef CiphersuitesPFS -#undef CiphersuitesNonPFS -#undef CiphersuitesTLS10_3DES -#undef CiphersuitesTLS10 -#undef CiphersuitesDHE -#undef DefineTLSCiphersuiteGroupList -#undef DefineTLSCiphersuiteDefinition - const tls_ciphersuite_t * sec_protocol_helper_ciphersuite_group_to_ciphersuite_list(tls_ciphersuite_group_t group, size_t *list_count) { diff --git a/protocol/SecProtocolInternal.h b/protocol/SecProtocolInternal.h index 97fd5c0e..e97cfecb 100644 --- a/protocol/SecProtocolInternal.h +++ b/protocol/SecProtocolInternal.h @@ -27,18 +27,18 @@ #define CiphersuitesPFS \ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \ + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, \ + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, \ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, \ + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, \ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, \ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, \ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, \ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, \ - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, \ - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, \ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, \ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, \ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, \ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, \ - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, \ - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA #define CiphersuitesNonPFS \ TLS_RSA_WITH_AES_256_GCM_SHA384, \ @@ -115,18 +115,6 @@ sec_protocol_configuration_populate_secure_defaults(sec_protocol_configuration_t void sec_protocol_configuration_register_builtin_exceptions(sec_protocol_configuration_t configuration); -bool -sec_protocol_helper_ciphersuite_group_contains_ciphersuite(tls_ciphersuite_group_t group, tls_ciphersuite_t suite); - -tls_protocol_version_t -sec_protocol_helper_ciphersuite_minimum_TLS_version(tls_ciphersuite_t ciphersuite); - -tls_protocol_version_t -sec_protocol_helper_ciphersuite_maximum_TLS_version(tls_ciphersuite_t ciphersuite); - -const char * -sec_protocol_helper_get_ciphersuite_name(tls_ciphersuite_t ciphersuite); - const tls_key_exchange_group_t * sec_protocol_helper_tls_key_exchange_group_set_to_key_exchange_group_list(tls_key_exchange_group_set_t set, size_t *listSize); diff --git a/protocol/SecProtocolMetadata.h b/protocol/SecProtocolMetadata.h index 3a67ddb3..5b7448d0 100644 --- a/protocol/SecProtocolMetadata.h +++ b/protocol/SecProtocolMetadata.h @@ -135,7 +135,7 @@ sec_protocol_metadata_get_negotiated_protocol_version(sec_protocol_metadata_t me * * @return A `tls_ciphersuite_t`. */ -API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)) +API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) tls_ciphersuite_t sec_protocol_metadata_get_negotiated_tls_ciphersuite(sec_protocol_metadata_t metadata); @@ -151,8 +151,7 @@ sec_protocol_metadata_get_negotiated_tls_ciphersuite(sec_protocol_metadata_t met * @return A SSLCipherSuite. */ API_DEPRECATED_WITH_REPLACEMENT("sec_protocol_metadata_get_negotiated_tls_ciphersuite", - macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) + macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) SSLCipherSuite sec_protocol_metadata_get_negotiated_ciphersuite(sec_protocol_metadata_t metadata); diff --git a/protocol/SecProtocolOptions.h b/protocol/SecProtocolOptions.h index 616dac53..68911275 100644 --- a/protocol/SecProtocolOptions.h +++ b/protocol/SecProtocolOptions.h @@ -129,8 +129,7 @@ sec_protocol_options_append_tls_ciphersuite(sec_protocol_options_t options, tls_ * @param ciphersuite * A SSLCipherSuite value. */ -API_DEPRECATED("Use sec_protocol_options_append_tls_ciphersuite", macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) +API_DEPRECATED("Use sec_protocol_options_append_tls_ciphersuite", macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) void sec_protocol_options_add_tls_ciphersuite(sec_protocol_options_t options, SSLCipherSuite ciphersuite); @@ -162,8 +161,7 @@ sec_protocol_options_append_tls_ciphersuite_group(sec_protocol_options_t options * @param group * A SSLCipherSuiteGroup value. */ -API_DEPRECATED("Use sec_protocol_options_append_tls_ciphersuite_group", macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) +API_DEPRECATED("Use sec_protocol_options_append_tls_ciphersuite_group", macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) void sec_protocol_options_add_tls_ciphersuite_group(sec_protocol_options_t options, SSLCiphersuiteGroup group); @@ -180,8 +178,7 @@ sec_protocol_options_add_tls_ciphersuite_group(sec_protocol_options_t options, S * A SSLProtocol enum value. */ API_DEPRECATED_WITH_REPLACEMENT("sec_protocol_options_set_min_tls_protocol_version", - macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) + macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) void sec_protocol_options_set_tls_min_version(sec_protocol_options_t options, SSLProtocol version); @@ -238,8 +235,7 @@ sec_protocol_options_get_default_min_dtls_protocol_version(void); * A SSLProtocol enum value. */ API_DEPRECATED_WITH_REPLACEMENT("sec_protocol_options_set_max_tls_protocol_version", - macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) + macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) void sec_protocol_options_set_tls_max_version(sec_protocol_options_t options, SSLProtocol version); @@ -283,6 +279,18 @@ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) tls_protocol_version_t sec_protocol_options_get_default_max_dtls_protocol_version(void); +/*! + * @function sec_protocol_options_get_enable_encrypted_client_hello + * + * @abstract + * For experimental use only. Find out whether Encrypted Client Hello has been enabled. + * + * @return A boolean that indicates whether or not Encrypted Client Hello has been enabled. + */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +bool +sec_protocol_options_get_enable_encrypted_client_hello(sec_protocol_options_t options); + /*! * @function sec_protocol_options_add_tls_application_protocol * @@ -303,14 +311,14 @@ sec_protocol_options_add_tls_application_protocol(sec_protocol_options_t options * @function sec_protocol_options_set_tls_server_name * * @abstract - * Set the server (domain) name to be used in the TLS SNI. This will override + * Set the server name to be used when verifying the peer's certificate. This will override * the server name obtained from the endpoint. * * @param options * A `sec_protocol_options_t` instance. * * @param server_name - * A NULL-terminated string carrying the server (domain) name. + * A NULL-terminated string carrying the server name. */ API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)) void @@ -553,6 +561,44 @@ API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)) void sec_protocol_options_set_peer_authentication_required(sec_protocol_options_t options, bool peer_authentication_required); +/*! + * @function sec_protocol_options_set_peer_authentication_optional + * + * @abstract + * When this is enabled, the endpoint requests the peer certificate, but if none is provided, the + * endpoint still proceeds with the connection. Default false for servers; always false for clients (clients ignore + * this option). If peer_authentication_required is set to true via + * sec_protocol_options_set_peer_authentication_required(), peer_authentication_optional will be disregarded + * and the peer certificate will be required. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param peer_authentication_optional + * Flag to enable or disable requested peer authentication. + */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +void +sec_protocol_options_set_peer_authentication_optional(sec_protocol_options_t options, bool peer_authentication_optional); + +/*! + * @function sec_protocol_options_set_enable_encrypted_client_hello + * + * @abstract + * For experimental use only. When this is enabled, the Encrypted Client Hello extension will be sent on the Client + * Hello if TLS 1.3 is among the supported TLS versions. Default false for clients; always false for servers (servers + * ignore this option). + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param peer_authentication_optional + * Flag to enable or disable Encrypted Client Hello. + */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +void +sec_protocol_options_set_enable_encrypted_client_hello(sec_protocol_options_t options, bool enable_encrypted_client_hello); + #ifdef __BLOCKS__ /*! diff --git a/protocol/SecProtocolPriv.h b/protocol/SecProtocolPriv.h index b209bc6f..4f24868e 100644 --- a/protocol/SecProtocolPriv.h +++ b/protocol/SecProtocolPriv.h @@ -231,6 +231,59 @@ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) void sec_protocol_options_set_quic_transport_parameters(sec_protocol_options_t options, dispatch_data_t transport_parameters); +/*! + * @enum sec_protocol_transport_t + * + * @abstract An enumeration of the different transport protocols that can have specific security options. + */ +typedef enum { + sec_protocol_transport_any = 0, + sec_protocol_transport_tcp, + sec_protocol_transport_quic, +} sec_protocol_transport_t; + +#define SEC_PROTOCOL_HAS_TRANSPORT_SPECIFIC_ALPN 1 + +/*! + * @function sec_protocol_options_add_transport_specific_application_protocol + * + * @abstract + * Add an application protocol supported by clients of this protocol instance, specific + * to a transport protocol. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param application_protocol + * A NULL-terminated string defining the application protocol. + * + * @param specific_transport + * A specific transport to which to bind the application protocol. + */ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +void +sec_protocol_options_add_transport_specific_application_protocol(sec_protocol_options_t options, const char *application_protocol, sec_protocol_transport_t specific_transport); + +/*! + * @function sec_protocol_options_copy_transport_specific_application_protocol + * + * @abstract + * Return the application protocols configured by clients of this protocol instance, specific + * to a transport protocol if applicable. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param specific_transport + * A specific transport to which to bind the application protocol. + * + * @return An `xpc_object_t` instance carrying an array of application protocol strings, or nil. + */ +#define SEC_PROTOCOL_HAS_TRANSPORT_SPECIFIC_ALPN_GETTER 1 /* rdar://problem/63987477 */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +SEC_RETURNS_RETAINED __nullable xpc_object_t +sec_protocol_options_copy_transport_specific_application_protocol(sec_protocol_options_t options, sec_protocol_transport_t specific_transport); + /*! * @enum sec_protocol_tls_encryption_level_t * @@ -282,6 +335,43 @@ sec_protocol_options_set_tls_encryption_secret_update_block(sec_protocol_options sec_protocol_tls_encryption_secret_update_t update_block, dispatch_queue_t update_queue); +/*! + * @block sec_protocol_tls_encryption_level_update_t + * + * @abstract + * Block to be invoked when the encryption level is updated. + * + * @param level + * The new `sec_protocol_tls_encryption_level_t`. + * + * @param is_write + * True if this is a write level and false if it's a read. + * + */ +typedef void (^sec_protocol_tls_encryption_level_update_t)(sec_protocol_tls_encryption_level_t level, bool is_write); + +/*! + * @function sec_protocol_options_set_tls_encryption_level_update_block + * + * @abstract + * Set the TLS encryption level update block. It is invoked whenever the encryption level is updated. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param update_block + * A `sec_protocol_tls_encryption_level_update_t` instance. + * + * @params update_queue + * A `dispatch_queue_t` on which the update block should be called. + */ +#define SEC_PROTOCOL_HAS_TLS_ENCRYPTION_LEVEL_UPDATE_BLOCK 1 /* rdar://problem/63986462 */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +void +sec_protocol_options_set_tls_encryption_level_update_block(sec_protocol_options_t options, + sec_protocol_tls_encryption_level_update_t update_block, + dispatch_queue_t update_queue); + /*! * @block sec_protocol_private_key_complete_t * @@ -468,45 +558,6 @@ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) void sec_protocol_options_add_tls_key_exchange_group_set(sec_protocol_options_t options, SSLKeyExchangeGroupSet set); -/*! - * @function sec_protocol_options_set_tls_SIKE503_exchange_enabled - * - * @abstract - * Enable SIKE using P503 for TLS 1.3 key exchange. - * - * DO NOT DEPEND ON THIS SPI. IT IS FOR EXPERIMENTAL PURPOSES AND SUBJECT TO REMOVAL WITHOUT ADVANCE NOTICE. - * BUILD BREAKAGE ISSUES WILL BE SENT TO THE CALLING PROJECT. - * - * @param options - * A `sec_protocol_options_t` instance. - * - * @param tls_SIKE503_exchange_enabled - * Flag to enable SIKE with P503. - */ -#define SEC_PROTOCOL_HAS_PQ_TLS_HANDLES 1 -API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) -void -sec_protocol_options_set_tls_SIKE503_exchange_enabled(sec_protocol_options_t options, bool tls_SIKE503_exchange_enabled); - -/*! - * @function sec_protocol_options_set_tls_HRSS_exchange_enabled - * - * @abstract - * Enable HRSS for TLS 1.3 key exchange. - * - * DO NOT DEPEND ON THIS SPI. IT IS FOR EXPERIMENTAL PURPOSES AND SUBJECT TO REMOVAL WITHOUT ADVANCE NOTICE. - * BUILD BREAKAGE ISSUES WILL BE SENT TO THE CALLING PROJECT. - * - * @param options - * A `sec_protocol_options_t` instance. - * - * @param tls_HRSS_exchange_enabled - * Flag to enable HRSS. - */ -API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) -void -sec_protocol_options_set_tls_HRSS_exchange_enabled(sec_protocol_options_t options, bool tls_HRSS_exchange_enabled); - /*! * @function sec_protocol_options_set_eddsa_enabled * @@ -581,6 +632,23 @@ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) void sec_protocol_options_set_tls_grease_enabled(sec_protocol_options_t options, bool tls_grease_enabled); +/*! + * @function sec_protocol_options_set_allow_unknown_alpn_protos + * + * @abstract + * Configure clients to accept server ALPN values they did not advertise. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param allow_unknown_alpn_protos + * Flag to enable or disable the use of unknown ALPN values. + */ +#define SEC_PROTOCOL_HAS_ALLOW_UNKNOWN_ALPN_PROTOS_SETTER 1 /* rdar://problem/64449512 */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +void +sec_protocol_options_set_allow_unknown_alpn_protos(sec_protocol_options_t options, bool allow_unknown_alpn_protos); + /*! * @function sec_protocol_options_set_experiment_identifier * @@ -690,7 +758,7 @@ sec_protocol_metadata_get_tls_negotiated_group(sec_protocol_metadata_t metadata) * * Note: this SPI is meant to be called by libnetcore. It should not be called in any other circumstances. * - * @param options + * @param metadata * A `sec_protocol_metadata_t` instance. * * @return The identifier for a secure connection experiment, or NULL if none was specified. @@ -1171,6 +1239,92 @@ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) const tls_ciphersuite_t * __nullable sec_protocol_helper_ciphersuite_group_to_ciphersuite_list(tls_ciphersuite_group_t group, size_t *list_count); +typedef CF_ENUM(uint16_t, sec_protocol_block_length_padding_t) { + SEC_PROTOCOL_BLOCK_LENGTH_PADDING_NONE = 0, + SEC_PROTOCOL_BLOCK_LENGTH_PADDING_DEFAULT = 16, +}; + +/*! + * @function sec_protocol_options_set_tls_block_length_padding + * + * @abstract + * Pad TLS messages to a multiple of the specified block length. By default, padding is disabled. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param block_length_padding + * A sec_protocol_block_length_padding_t variable specifying the block length padding. Setting the block length padding to 0 disables padding. + * + * @return True if the padding policy has been successfully set, false otherwise. + */ +API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) +bool +sec_protocol_options_set_tls_block_length_padding(sec_protocol_options_t options, sec_protocol_block_length_padding_t block_length_padding); + +/*! + * @function sec_protocol_helper_ciphersuite_group_contains_ciphersuite + * + * @abstract + * This function is exposed for testing purposes only. It MUST NOT be called by clients. + * + * @param group + * A `tls_ciphersuite_group_t` instance. + * + * @param suite + * A `tls_ciphersuite_t` instance. + * + * @return True if the ciphersuite group contains the given ciphersuite, false otherwise. +*/ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +bool +sec_protocol_helper_ciphersuite_group_contains_ciphersuite(tls_ciphersuite_group_t group, tls_ciphersuite_t suite); + +/*! + * @function sec_protocol_helper_ciphersuite_minimum_TLS_version + * + * @abstract + * This function is exposed for testing purposes only. It MUST NOT be called by clients. + * + * @param ciphersuite + * A `tls_ciphersuite_t` instance. + * + * @return The `tls_protocol_version_t` pertaining to the minimum TLS version designated for the given ciphersuite. +*/ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +tls_protocol_version_t +sec_protocol_helper_ciphersuite_minimum_TLS_version(tls_ciphersuite_t ciphersuite); + +/*! + * @function sec_protocol_helper_ciphersuite_maximum_TLS_version + * + * @abstract + * This function is exposed for testing purposes only. It MUST NOT be called by clients. + * + * @param ciphersuite + * A `tls_ciphersuite_t` instance. + * + * @return The `tls_protocol_version_t` pertaining to the maximum TLS version designated for the given ciphersuite. +*/ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +tls_protocol_version_t +sec_protocol_helper_ciphersuite_maximum_TLS_version(tls_ciphersuite_t ciphersuite); + +/*! + * @function sec_protocol_helper_get_ciphersuite_name + * + * @abstract + * This function is exposed for testing purposes only. It MUST NOT be called by clients. + * + * @param ciphersuite + * A `tls_ciphersuite_t` instance. + * + * @return A string representation of the given ciphersuite, or NULL if it does not exist. +*/ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +const char * __nullable +sec_protocol_helper_get_ciphersuite_name(tls_ciphersuite_t ciphersuite); + #define SEC_PROTOCOL_HAS_MULTI_PSK_SUPPORT 1 struct sec_protocol_options_content { @@ -1195,6 +1349,8 @@ struct sec_protocol_options_content { dispatch_data_t quic_transport_parameters; sec_protocol_tls_encryption_secret_update_t tls_secret_update_block; dispatch_queue_t tls_secret_update_queue; + sec_protocol_tls_encryption_level_update_t tls_encryption_level_update_block; + dispatch_queue_t tls_encryption_level_update_queue; sec_protocol_session_update_t session_update_block; dispatch_queue_t session_update_queue; dispatch_data_t session_state; @@ -1245,14 +1401,18 @@ struct sec_protocol_options_content { unsigned enable_renegotiation_override : 1; unsigned enable_early_data : 1; unsigned enable_early_data_override : 1; + unsigned enable_ech : 1; unsigned peer_authentication_required : 1; + unsigned peer_authentication_optional : 1; unsigned peer_authentication_override : 1; unsigned certificate_compression_enabled : 1; - unsigned tls_SIKE503_exchange_enabled : 1; - unsigned tls_HRSS_exchange_enabled : 1; unsigned eddsa_enabled : 1; unsigned tls_delegated_credentials_enabled : 1; unsigned tls_grease_enabled : 1; + unsigned allow_unknown_alpn_protos : 1; + unsigned allow_unknown_alpn_protos_override : 1; + + sec_protocol_block_length_padding_t tls_block_length_padding; }; struct sec_protocol_metadata_content { diff --git a/protocol/SecProtocolTest.m b/protocol/SecProtocolTest.m index 4ae69401..9dddf49d 100644 --- a/protocol/SecProtocolTest.m +++ b/protocol/SecProtocolTest.m @@ -682,6 +682,24 @@ _sec_protocol_test_metadata_session_exporter(void *handle) }); } +- (void)test_sec_protocol_options_set_tls_encryption_level_update_block { + void (^update_block)(sec_protocol_tls_encryption_level_t, bool) = ^(__unused sec_protocol_tls_encryption_level_t level, __unused bool is_write) { + // pass + }; + + dispatch_queue_t update_queue = dispatch_queue_create("test_sec_protocol_options_set_tls_encryption_level_update_block_queue", DISPATCH_QUEUE_SERIAL); + + sec_protocol_options_t options = [self create_sec_protocol_options]; + sec_protocol_options_set_tls_encryption_level_update_block(options, update_block, update_queue); + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertTrue(content->tls_encryption_level_update_block == update_block); + XCTAssertTrue(content->tls_encryption_level_update_queue != nil); + return false; + }); +} + - (void)test_sec_protocol_options_set_local_certificates { sec_protocol_options_t options = [self create_sec_protocol_options]; @@ -730,6 +748,30 @@ _sec_protocol_test_metadata_session_exporter(void *handle) }); } +- (void)test_sec_protocol_options_set_peer_authentication_required { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + sec_protocol_options_set_peer_authentication_required(options, true); + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertTrue(content->peer_authentication_required); + return true; + }); +} + +- (void)test_sec_protocol_options_set_peer_authentication_optional { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + sec_protocol_options_set_peer_authentication_optional(options, true); + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertTrue(content->peer_authentication_optional); + return true; + }); +} + - (void)test_sec_protocol_options_are_equal { sec_protocol_options_t optionsA = [self create_sec_protocol_options]; sec_protocol_options_t optionsB = [self create_sec_protocol_options]; @@ -860,23 +902,95 @@ _sec_protocol_test_metadata_session_exporter(void *handle) XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); const char *application_protocolA = "h2"; - const char *application_protocolB = "h3"; sec_protocol_options_add_tls_application_protocol(optionsA, application_protocolA); XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB)); - sec_protocol_options_add_tls_application_protocol(optionsB, application_protocolB); + sec_protocol_options_add_tls_application_protocol(optionsB, application_protocolA); + XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); + + const char *application_protocolB = "h3"; + sec_protocol_options_add_transport_specific_application_protocol(optionsA, application_protocolB, + sec_protocol_transport_quic); XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB)); + sec_protocol_options_add_transport_specific_application_protocol(optionsB, application_protocolB, + sec_protocol_transport_quic); + XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); + sec_protocol_options_append_tls_ciphersuite(optionsB, 7331); XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB)); } +- (void)test_sec_protocol_options_copy_transport_specific_application_protocol { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + const char *application_protocol_dummy = "dummy"; + const char *application_protocol_h2 = "h2"; + const char *application_protocol_h3 = "h3"; + + sec_protocol_options_add_transport_specific_application_protocol(options, application_protocol_h2, sec_protocol_transport_tcp); + xpc_object_t protocols = sec_protocol_options_copy_transport_specific_application_protocol(options, sec_protocol_transport_quic); + XCTAssertFalse(protocols != NULL); + if (protocols != NULL) { + return; + } + + sec_protocol_options_add_tls_application_protocol(options, application_protocol_dummy); + sec_protocol_options_add_transport_specific_application_protocol(options, application_protocol_h3, sec_protocol_transport_quic); + + for (sec_protocol_transport_t t = sec_protocol_transport_any; t <= sec_protocol_transport_quic; t++) { + protocols = sec_protocol_options_copy_transport_specific_application_protocol(options, t); + XCTAssertFalse(protocols == NULL); + if (protocols == NULL) { + return; + } + + const char *application_protocols_for_any[] = { application_protocol_h2, application_protocol_dummy, application_protocol_h3, }; + // application_protocols_for_tcp includes application_protocol_dummy because "dummy" isn't tied to any transport. + const char *application_protocols_for_tcp[] = { application_protocol_h2, application_protocol_dummy, }; + const char *application_protocols_for_quic[] = { application_protocol_dummy, application_protocol_h3, }; + + size_t count_of_application_protocols_for_transport[] = { + [sec_protocol_transport_any] = sizeof(application_protocols_for_any)/sizeof(application_protocols_for_any[0]), + [sec_protocol_transport_tcp] = sizeof(application_protocols_for_tcp)/sizeof(application_protocols_for_tcp[0]), + [sec_protocol_transport_quic] = sizeof(application_protocols_for_quic)/sizeof(application_protocols_for_quic[0]), + }; + + XCTAssertFalse(xpc_get_type(protocols) != XPC_TYPE_ARRAY); + if (xpc_get_type(protocols) != XPC_TYPE_ARRAY) { + return; + } + + size_t protocols_count = xpc_array_get_count(protocols); + XCTAssertFalse(protocols_count != count_of_application_protocols_for_transport[t]); + if (protocols_count != count_of_application_protocols_for_transport[t]) { + return; + } + + const char **application_protocols_for_transport[] = { + [sec_protocol_transport_any] = application_protocols_for_any, + [sec_protocol_transport_tcp] = application_protocols_for_tcp, + [sec_protocol_transport_quic] = application_protocols_for_quic, + }; + + for (size_t i = 0; i < protocols_count; i++) { + const char *protocol_name = xpc_array_get_string(protocols, i); + const char *expected_protocol_name = application_protocols_for_transport[t][i]; + bool protocol_match = (strcmp(protocol_name, expected_protocol_name) == 0); + + XCTAssertFalse(protocol_match == false); + if (protocol_match == false) { + return; + } + } + } +} + - (void)test_sec_protocol_options_set_tls_server_name { sec_protocol_options_t optionsA = [self create_sec_protocol_options]; sec_protocol_options_t optionsB = [self create_sec_protocol_options]; const char *server_nameA = "apple.com"; - const char *server_nameB = "127.0.0.1"; - const char *server_nameC = "example.com"; + const char *server_nameB = "example.com"; /* * Empty options should be equal. @@ -897,19 +1011,11 @@ _sec_protocol_test_metadata_session_exporter(void *handle) sec_protocol_options_set_tls_server_name(optionsB, server_nameA); XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); - /* - * Try to set the name to nameB in optionsB. - * It should fail since nameB is invalid. - * Options A, B should still be equal. - */ - sec_protocol_options_set_tls_server_name(optionsB, server_nameB); - XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); - /* * Change the current name in B. * Comparison should fail. */ - sec_protocol_options_set_tls_server_name(optionsB, server_nameC); + sec_protocol_options_set_tls_server_name(optionsB, server_nameB); XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB)); } @@ -1009,6 +1115,16 @@ _sec_protocol_test_metadata_session_exporter(void *handle) XCTAssertTrue(sec_protocol_options_get_default_min_dtls_protocol_version() == tls_protocol_version_DTLSv10); } +- (void)test_enable_ech { + XCTAssertFalse(sec_protocol_options_get_enable_encrypted_client_hello(nil), "ECH enabled even with no sec_protocol_options"); + sec_protocol_options_t options = [self create_sec_protocol_options]; + XCTAssertFalse(sec_protocol_options_get_enable_encrypted_client_hello(options), "enable_ech initialized to true"); + sec_protocol_options_set_enable_encrypted_client_hello(options, true); + XCTAssertTrue(sec_protocol_options_get_enable_encrypted_client_hello(options), "ECH still disabled after set to true"); + sec_protocol_options_set_enable_encrypted_client_hello(options, false); + XCTAssertFalse(sec_protocol_options_get_enable_encrypted_client_hello(options), "ECH still enabled after changed back to false"); +} + - (void)test_sec_protocol_options_set_psk_hint { __block dispatch_data_t hint = [self create_random_dispatch_data]; sec_protocol_options_t options = [self create_sec_protocol_options]; @@ -1082,6 +1198,24 @@ _sec_protocol_test_metadata_session_exporter(void *handle) XCTAssertTrue(accessed, @"Expected sec_protocol_metadata_access_pre_shared_keys to traverse PSK list"); } +- (void)test_sec_protocol_options_set_tls_block_length_padding { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + sec_protocol_block_length_padding_t expected_block_length_padding = SEC_PROTOCOL_BLOCK_LENGTH_PADDING_DEFAULT; + sec_protocol_options_set_tls_block_length_padding(options, expected_block_length_padding); + + __block sec_protocol_block_length_padding_t current_block_length_padding = SEC_PROTOCOL_BLOCK_LENGTH_PADDING_NONE; + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + current_block_length_padding = content->tls_block_length_padding; + return true; + }); + + XCTAssertTrue(current_block_length_padding == expected_block_length_padding); +} + - (void)test_sec_protocol_experiment_identifier { sec_protocol_options_t options = [self create_sec_protocol_options]; @@ -1152,4 +1286,24 @@ _sec_protocol_test_metadata_session_exporter(void *handle) XCTAssertTrue(memcmp(uuid, copied_metadata, sizeof(copied_metadata)) == 0); } +- (void)test_sec_protocol_options_set_allow_unknown_alpn_protos { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertFalse(content->allow_unknown_alpn_protos_override); + return true; + }); + + sec_protocol_options_set_allow_unknown_alpn_protos(options, true); + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertTrue(content->allow_unknown_alpn_protos); + XCTAssertTrue(content->allow_unknown_alpn_protos_override); + return true; + }); +} + @end diff --git a/protocol/SecProtocolTypes.m b/protocol/SecProtocolTypes.m index b5258fff..558bb46a 100644 --- a/protocol/SecProtocolTypes.m +++ b/protocol/SecProtocolTypes.m @@ -84,11 +84,11 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_array, - (instancetype)init { - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->xpc_array = xpc_array_create(NULL, 0); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->xpc_array = xpc_array_create(NULL, 0); return self; } @@ -166,11 +166,11 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_identity, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity)); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity)); return self; } @@ -180,12 +180,12 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_identity, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity)); + self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates)); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity)); - self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates)); return self; } @@ -202,16 +202,14 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_identity, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates)); + self->sign_block = sign; + self->decrypt_block = decrypt; + self->operation_queue = queue; + } else { return SEC_NIL_OUT_OF_MEMORY; } - - self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates)); - self->sign_block = sign; - self->decrypt_block = decrypt; - self->operation_queue = queue; - return self; } @@ -354,11 +352,11 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_certificate, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->certificate = __DECONST(SecCertificateRef, CFRetainSafe(_certificate)); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->certificate = __DECONST(SecCertificateRef, CFRetainSafe(_certificate)); return self; } @@ -403,11 +401,11 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_trust, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->trust = __DECONST(SecTrustRef, CFRetainSafe(_trust)); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->trust = __DECONST(SecTrustRef, CFRetainSafe(_trust)); return self; } @@ -461,9 +459,9 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_protocol_configuration_builder, @implementation SEC_CONCRETE_CLASS_NAME(sec_protocol_configuration_builder) -- (id)init { - self = [super init]; - if (self) { +- (id)init +{ + if (self = [super init]) { CFBundleRef bundle = CFBundleGetMainBundle(); if (bundle != NULL) { CFTypeRef rawATS = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR(kATSInfoKey)); @@ -475,9 +473,10 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_protocol_configuration_builder, return self; } -- (id)initWithDictionary:(CFDictionaryRef)dict andInternalFlag:(bool)flag { - self = [super init]; - if (self) { +- (id)initWithDictionary:(CFDictionaryRef)dict + andInternalFlag:(bool)flag +{ + if ((self = [super init])) { self->dictionary = dict; CFRetainSafe(dict); self->is_apple = flag; @@ -519,8 +518,7 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_protocol_configuration, @implementation SEC_CONCRETE_CLASS_NAME(sec_protocol_configuration) - (id)init { - self = [super init]; - if (self) { + if ((self = [super init])) { self->dictionary = xpc_dictionary_create(NULL, NULL, 0); } return self; diff --git a/protocol/test_data/example1.json b/protocol/test_data/example1.json index aa62c08e..1930362b 100644 --- a/protocol/test_data/example1.json +++ b/protocol/test_data/example1.json @@ -2,7 +2,7 @@ "NSAllowsArbitraryLoads": false, "NSAllowsArbitraryLoadsForMedia": false, "NSAllowsArbitraryLoadsInWebContent": false, - "NSAllowsLocalNetworking": false, + "NSAllowsLocalNetworking": true, "NSExceptionDomains": { "apple.com": { "NSIncludesSubdomains": true, @@ -45,6 +45,8 @@ "NSExceptionAllowsInsecureHTTPLoads": true, "NSExceptionMinimumTLSVersion": "TLSv1.2", "NSExceptionRequiresForwardSecrecy": false - } + }, + "example.local": { + } } -} \ No newline at end of file +} diff --git a/rio.yml b/rio.yml deleted file mode 100644 index e69de29b..00000000 diff --git a/secacltests/secacltests-entitlements.plist b/secacltests/secacltests-entitlements.plist index c635aaf3..846bd4e3 100644 --- a/secacltests/secacltests-entitlements.plist +++ b/secacltests/secacltests-entitlements.plist @@ -18,5 +18,7 @@ com.apple.security.sos + com.apple.private.security.storage.Keychains + diff --git a/secdtests/secdtests-entitlements.plist b/secdtests/secdtests-entitlements.plist index d9ca668f..403823d9 100644 --- a/secdtests/secdtests-entitlements.plist +++ b/secdtests/secdtests-entitlements.plist @@ -16,13 +16,15 @@ com.apple.private.security.no-sandbox + com.apple.security.app-sandbox + keychain-cloud-circle com.apple.keystore.access-keychain-keys com.apple.keystore.device - com.apple.private.applecredentialmanager.allow + com.apple.keystore.lockassertion restore-keychain @@ -51,5 +53,7 @@ com.apple.ProtectedCloudStorage com.apple.security.ckks + com.apple.private.security.storage.Keychains + diff --git a/secdxctests/CDKeychainTests.m b/secdxctests/CDKeychainTests.m index 1a736d23..488deaba 100644 --- a/secdxctests/CDKeychainTests.m +++ b/secdxctests/CDKeychainTests.m @@ -90,7 +90,7 @@ _connection = [[SFKeychainServerFakeConnection alloc] init]; self.keychainPartialMock = OCMPartialMock(_keychain); - [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; + [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataWithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; [_keychain _registerItemTypeForTesting:[TestItemType itemType]]; } @@ -472,7 +472,7 @@ XCTAssertNotNil(keychain, @"should have been able to create a keychain instance"); self.keychainPartialMock = OCMPartialMock(keychain); - [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; + [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataWithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; SecCDKeychainAccessControlEntity* owner = [SecCDKeychainAccessControlEntity accessControlEntityWithType:SecCDKeychainAccessControlEntityTypeAccessGroup stringRepresentation:@"com.apple.token"]; diff --git a/secdxctests/KeychainAPITests.m b/secdxctests/KeychainAPITests.m index a68d4f2d..d306018b 100644 --- a/secdxctests/KeychainAPITests.m +++ b/secdxctests/KeychainAPITests.m @@ -27,6 +27,7 @@ #import "CKKS.h" #import "SecDbKeychainItemV7.h" #import "SecItemPriv.h" +#include "SecItemInternal.h" #import "SecItemServer.h" #import "spi.h" #import "SecDbKeychainSerializedItemV7.h" @@ -41,8 +42,11 @@ #include #include #include - -void* testlist = NULL; +#include "der_plist.h" +#import "SecItemRateLimit_tests.h" +#include "ipc/server_security_helpers.h" +#include +#include "keychain/securityd/SecItemDb.h" #if USE_KEYSTORE @@ -54,8 +58,6 @@ void* testlist = NULL; + (void)setUp { [super setUp]; - SecCKKSDisable(); - securityd_init(NULL); } - (NSString*)nameOfTest @@ -152,6 +154,52 @@ void* testlist = NULL; XCTAssertEqual(errSecParam, SecItemDelete((CFDictionaryRef)attrs)); } +- (BOOL)passInternalAttributeToKeychainAPIsWithKey:(id)key value:(id)value { + NSDictionary* badquery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + key : value, + }; + NSDictionary* badupdate = @{key : value}; + + NSDictionary* okquery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + }; + NSDictionary* okupdate = @{(id)kSecAttrService : @"DifferentService"}; + + if (SecItemAdd((__bridge CFDictionaryRef)badquery, NULL) != errSecParam) { + XCTFail("SecItemAdd did not return errSecParam"); + return NO; + } + if (SecItemCopyMatching((__bridge CFDictionaryRef)badquery, NULL) != errSecParam) { + XCTFail("SecItemCopyMatching did not return errSecParam"); + return NO; + } + if (SecItemUpdate((__bridge CFDictionaryRef)badquery, (__bridge CFDictionaryRef)okupdate) != errSecParam) { + XCTFail("SecItemUpdate with bad query did not return errSecParam"); + return NO; + } + if (SecItemUpdate((__bridge CFDictionaryRef)okquery, (__bridge CFDictionaryRef)badupdate) != errSecParam) { + XCTFail("SecItemUpdate with bad update did not return errSecParam"); + return NO; + } + if (SecItemDelete((__bridge CFDictionaryRef)badquery) != errSecParam) { + XCTFail("SecItemDelete did not return errSecParam"); + return NO; + } + return YES; +} + +// Expand this, rdar://problem/59297616 +- (void)testNotAllowedToPassInternalAttributes { + XCTAssert([self passInternalAttributeToKeychainAPIsWithKey:(__bridge NSString*)kSecAttrAppClipItem value:@YES], @"Expect errSecParam for 'clip' attribute"); +} + #pragma mark - Corruption Tests const uint8_t keychain_data[] = { @@ -187,7 +235,16 @@ static void SecDbTestCorruptionHandler(void) SecDbCorruptionExitHandler = SecDbTestCorruptionHandler; sema = dispatch_semaphore_create(0); - secd_test_setup_temp_keychain([[NSString stringWithFormat:@"%@-bad", [self nameOfTest]] UTF8String], ^{ + // Test teardown will want to delete this keychain. Make sure it knows where to look... + NSString* corruptedKeychainPath = [NSString stringWithFormat:@"%@-bad", [self nameOfTest]]; + + if(self.keychainDirectoryPrefix) { + XCTAssertTrue(secd_test_teardown_delete_temp_keychain([self.keychainDirectoryPrefix UTF8String]), "Should be able to delete the temp keychain"); + } + + self.keychainDirectoryPrefix = corruptedKeychainPath; + + secd_test_setup_temp_keychain([corruptedKeychainPath UTF8String], ^{ CFStringRef keychain_path_cf = __SecKeychainCopyPath(); CFStringPerformWithCString(keychain_path_cf, ^(const char *keychain_path) { @@ -280,6 +337,556 @@ static void SecDbTestCorruptionHandler(void) } } +- (void)testInetBinaryFields { + NSData* note = [@"OBVIOUS_NOTES_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* history = [@"OBVIOUS_HISTORY_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* client0 = [@"OBVIOUS_CLIENT0_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* client1 = [@"OBVIOUS_CLIENT1_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* client2 = [@"OBVIOUS_CLIENT2_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* client3 = [@"OBVIOUS_CLIENT3_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + + NSData* originalPassword = [@"asdf" dataUsingEncoding:NSUTF8StringEncoding]; + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrDescription : @"desc", + (id)kSecAttrServer : @"server", + (id)kSecAttrAccount : @"test-account", + (id)kSecValueData : originalPassword, + (id)kSecDataInetExtraNotes : note, + (id)kSecDataInetExtraHistory : history, + (id)kSecDataInetExtraClientDefined0 : client0, + (id)kSecDataInetExtraClientDefined1 : client1, + (id)kSecDataInetExtraClientDefined2 : client2, + (id)kSecDataInetExtraClientDefined3 : client3, + + (id)kSecReturnAttributes : @YES, + } mutableCopy]; + + CFTypeRef cfresult = nil; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, &cfresult), errSecSuccess, "Should be able to add an item using new binary fields"); + NSDictionary* result = (NSDictionary*)CFBridgingRelease(cfresult); + XCTAssertNotNil(result, "Should have some sort of result"); + + XCTAssertNil(result[(id)kSecDataInetExtraNotes], "Notes field should not be returned as an attribute from add"); + XCTAssertNil(result[(id)kSecDataInetExtraHistory], "Notes field should not be returned as an attribute from add"); + + NSDictionary* queryFind = @{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrAccount : @"test-account", + }; + + NSMutableDictionary* queryFindOneWithJustAttributes = [[NSMutableDictionary alloc] initWithDictionary:queryFind]; + queryFindOneWithJustAttributes[(id)kSecReturnAttributes] = @YES; + + NSMutableDictionary* queryFindAllWithJustAttributes = [[NSMutableDictionary alloc] initWithDictionary:queryFindOneWithJustAttributes]; + queryFindAllWithJustAttributes[(id)kSecMatchLimit] = (id)kSecMatchLimitAll; + + NSDictionary* queryFindOneWithAttributesAndData = @{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnAttributes : @YES, + (id)kSecReturnData: @YES, + (id)kSecAttrAccount : @"test-account", + }; + + NSDictionary* queryFindAllWithAttributesAndData = @{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnAttributes : @YES, + (id)kSecReturnData: @YES, + (id)kSecMatchLimit : (id)kSecMatchLimitAll, + (id)kSecAttrAccount : @"test-account", + }; + + /* Copy with a single record limite, but with attributes only */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindOneWithJustAttributes, &cfresult), errSecSuccess, "Should be able to find an item"); + + result = (NSDictionary*)CFBridgingRelease(cfresult); + XCTAssertNotNil(result, "Should have some sort of result"); + + XCTAssertNil(result[(id)kSecDataInetExtraNotes], "Notes field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraHistory], "Notes field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined0], "ClientDefined0 field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined1], "ClientDefined1 field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined2], "ClientDefined2 field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined3], "ClientDefined3 field should not be returned as an attribute from copymatching when finding a single item"); + + /* Copy with no limit, but with attributes only */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindAllWithJustAttributes, &cfresult), errSecSuccess, "Should be able to find an item"); + NSArray* arrayResult = (NSArray*)CFBridgingRelease(cfresult); + XCTAssertNotNil(arrayResult, "Should have some sort of result"); + XCTAssertTrue([arrayResult isKindOfClass:[NSArray class]], "Should have received an array back from copymatching"); + XCTAssertEqual(arrayResult.count, 1, "Array should have one element"); + + result = arrayResult[0]; + XCTAssertNil(result[(id)kSecDataInetExtraNotes], "Notes field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraHistory], "Notes field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined0], "ClientDefined0 field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined1], "ClientDefined1 field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined2], "ClientDefined2 field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined3], "ClientDefined3 field should not be returned as an attribute from copymatching when finding all items"); + + /* Copy with single-record limit, but with attributes and data */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindOneWithAttributesAndData, &cfresult), errSecSuccess, "Should be able to find an item"); + result = (NSDictionary*)CFBridgingRelease(cfresult); + XCTAssertNotNil(result, "Should have some sort of result"); + + XCTAssertEqualObjects(note, result[(id)kSecDataInetExtraNotes], "Notes field should be returned as data"); + XCTAssertEqualObjects(history, result[(id)kSecDataInetExtraHistory], "History field should be returned as data"); + XCTAssertEqualObjects(client0, result[(id)kSecDataInetExtraClientDefined0], "Client Defined 0 field should be returned as data"); + XCTAssertEqualObjects(client1, result[(id)kSecDataInetExtraClientDefined1], "Client Defined 1 field should be returned as data"); + XCTAssertEqualObjects(client2, result[(id)kSecDataInetExtraClientDefined2], "Client Defined 2 field should be returned as data"); + XCTAssertEqualObjects(client3, result[(id)kSecDataInetExtraClientDefined3], "Client Defined 3 field should be returned as data"); + + /* Copy with no limit, but with attributes and data */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindAllWithAttributesAndData, &cfresult), errSecSuccess, "Should be able to find an item"); + arrayResult = (NSArray*)CFBridgingRelease(cfresult); + XCTAssertNotNil(arrayResult, "Should have some sort of result"); + XCTAssertTrue([arrayResult isKindOfClass:[NSArray class]], "Should have received an array back from copymatching"); + XCTAssertEqual(arrayResult.count, 1, "Array should have one element"); + result = arrayResult[0]; + XCTAssertEqualObjects(note, result[(id)kSecDataInetExtraNotes], "Notes field should be returned as data"); + XCTAssertEqualObjects(history, result[(id)kSecDataInetExtraHistory], "History field should be returned as data"); + XCTAssertEqualObjects(client0, result[(id)kSecDataInetExtraClientDefined0], "Client Defined 0 field should be returned as data"); + XCTAssertEqualObjects(client1, result[(id)kSecDataInetExtraClientDefined1], "Client Defined 1 field should be returned as data"); + XCTAssertEqualObjects(client2, result[(id)kSecDataInetExtraClientDefined2], "Client Defined 2 field should be returned as data"); + XCTAssertEqualObjects(client3, result[(id)kSecDataInetExtraClientDefined3], "Client Defined 3 field should be returned as data"); + + /* Copy just looking for the password */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnData: @YES, + (id)kSecAttrAccount : @"test-account", + }, &cfresult), errSecSuccess, "Should be able to find an item"); + + NSData* password = (NSData*)CFBridgingRelease(cfresult); + XCTAssertNotNil(password, "Should have some sort of password"); + XCTAssertTrue([password isKindOfClass:[NSData class]], "Password is a data"); + XCTAssertEqualObjects(originalPassword, password, "Should still be able to fetch the original password"); + + NSData* newHistoryContents = [@"gone" dataUsingEncoding:NSUTF8StringEncoding]; + + NSDictionary* updateQuery = @{ + (id)kSecDataInetExtraHistory : newHistoryContents, + }; + + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)queryFind, (__bridge CFDictionaryRef)updateQuery), errSecSuccess, "Should be able to update a history field"); + + // And find it again + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindOneWithAttributesAndData, &cfresult), errSecSuccess, "Should be able to find an item"); + result = (NSDictionary*)CFBridgingRelease(cfresult); + XCTAssertNotNil(result, "Should have some sort of result"); + + XCTAssertEqualObjects(note, result[(id)kSecDataInetExtraNotes], "Notes field should be returned as data"); + XCTAssertEqualObjects(newHistoryContents, result[(id)kSecDataInetExtraHistory], "History field should be updated"); + XCTAssertEqualObjects(client0, result[(id)kSecDataInetExtraClientDefined0], "Client Defined 0 field should be returned as data"); + XCTAssertEqualObjects(client1, result[(id)kSecDataInetExtraClientDefined1], "Client Defined 1 field should be returned as data"); + XCTAssertEqualObjects(client2, result[(id)kSecDataInetExtraClientDefined2], "Client Defined 2 field should be returned as data"); + XCTAssertEqualObjects(client3, result[(id)kSecDataInetExtraClientDefined3], "Client Defined 3 field should be returned as data"); +} + +// When this test starts failing, hopefully rdar://problem/60332379 got fixed +- (void)testBadDateCausesDERDecodeValidationError { + // Wonky time calculation hastily stolen from SecGregorianDateGetAbsoluteTime and tweaked + // As of right now this causes CFCalendarDecomposeAbsoluteTime with Zulu calendar to give a seemingly incorrect date which then causes DER date validation issues + CFAbsoluteTime absTime = (CFAbsoluteTime)(((-(1902 * 365) + -38) * 24 + 0) * 60 + -1) * 60 + 1; + absTime -= 0.0004; // Just to make sure the nanoseconds keep getting encoded/decoded properly + CFDateRef date = CFDateCreate(NULL, absTime); + + CFErrorRef error = NULL; + size_t plistSize = der_sizeof_plist(date, &error); + XCTAssert(error == NULL); + XCTAssertGreaterThan(plistSize, 0); + + // Encode without repair does not validate dates because that changes behavior I do not want to fiddle with + uint8_t* der = calloc(1, plistSize); + uint8_t* der_end = der + plistSize; + uint8_t* result = der_encode_plist(date, &error, der, der_end); + XCTAssert(error == NULL); + XCTAssertEqual(der, result); + + // ...but decoding does and will complain + CFPropertyListRef decoded = NULL; + XCTAssert(der_decode_plist(NULL, &decoded, &error, der, der_end) == NULL); + XCTAssert(error != NULL); + XCTAssertEqual(CFErrorGetDomain(error), kCFErrorDomainOSStatus); + NSString* description = CFBridgingRelease(CFErrorCopyDescription(error)); + XCTAssert([description containsString:@"Invalid date"]); + + CFReleaseNull(error); + free(der); +} + +// When this test starts failing, hopefully rdar://problem/60332379 got fixed +- (void)testBadDateWithDEREncodingRepairProducesDefaultValue { + // Wonky time calculation hastily stolen from SecGregorianDateGetAbsoluteTime and tweaked + // As of right now this causes CFCalendarDecomposeAbsoluteTime with Zulu calendar to give a seemingly incorrect date which then causes DER date validation issues + CFAbsoluteTime absTime = (CFAbsoluteTime)(((-(1902 * 365) + -38) * 24 + 0) * 60 + -1) * 60 + 1; + absTime -= 0.0004; // Just to make sure the nanoseconds keep getting encoded/decoded properly + CFDateRef date = CFDateCreate(NULL, absTime); + + CFErrorRef error = NULL; + size_t plistSize = der_sizeof_plist(date, &error); + XCTAssert(error == NULL); + XCTAssertGreaterThan(plistSize, 0); + + uint8_t* der = calloc(1, plistSize); + uint8_t* der_end = der + plistSize; + uint8_t* encoderesult = der_encode_plist_repair(date, &error, true, der, der_end); + XCTAssert(error == NULL); + XCTAssertEqual(der, encoderesult); + + CFPropertyListRef decoded = NULL; + const uint8_t* decoderesult = der_decode_plist(NULL, &decoded, &error, der, der_end); + XCTAssertEqual(der_end, decoderesult); + XCTAssertEqual(CFGetTypeID(decoded), CFDateGetTypeID()); + XCTAssertEqualWithAccuracy(CFDateGetAbsoluteTime(decoded), 0, 60 * 60 * 24); +} + +- (void)testContainersWithBadDateWithDEREncodingRepairProducesDefaultValue { + // Wonky time calculation hastily stolen from SecGregorianDateGetAbsoluteTime and tweaked + // As of right now this causes CFCalendarDecomposeAbsoluteTime with Zulu calendar to give a seemingly incorrect date which then causes DER date validation issues + CFAbsoluteTime absTime = (CFAbsoluteTime)(((-(1902 * 365) + -38) * 24 + 0) * 60 + -1) * 60 + 1; + absTime -= 0.0004; + CFDateRef date = CFDateCreate(NULL, absTime); + + NSDictionary* dict = @{ + @"dateset": [NSSet setWithObject:(__bridge id)date], + @"datearray": @[(__bridge id)date], + }; + + CFErrorRef error = NULL; + size_t plistSize = der_sizeof_plist((__bridge CFTypeRef)dict, &error); + XCTAssertNil((__bridge NSError*)error, "Should be no error checking the size of the plist"); + XCTAssertGreaterThan(plistSize, 0); + + uint8_t* der = calloc(1, plistSize); + uint8_t* der_end = der + plistSize; + uint8_t* encoderesult = der_encode_plist_repair((__bridge CFTypeRef)dict, &error, true, der, der_end); + XCTAssertNil((__bridge NSError*)error, "Should be no error encoding the plist"); + XCTAssertEqual(der, encoderesult); + + CFPropertyListRef decoded = NULL; + const uint8_t* decoderesult = der_decode_plist(NULL, &decoded, &error, der, der_end); + XCTAssertNil((__bridge NSError*)error, "Should be no error decoding the plist"); + XCTAssertEqual(der_end, decoderesult); + + XCTAssertNotNil((__bridge NSDictionary*)decoded, "Should have decoded some dictionary"); + if(decoded == nil) { + return; + } + + XCTAssertEqual(CFGetTypeID(decoded), CFDictionaryGetTypeID()); + CFDictionaryRef decodedCFDictionary = decoded; + + { + CFSetRef decodedCFSet = CFDictionaryGetValue(decodedCFDictionary, CFSTR("dateset")); + XCTAssertNotNil((__bridge NSSet*)decodedCFSet, "Should have some CFSet"); + + if(decodedCFSet != NULL) { + XCTAssertEqual(CFGetTypeID(decodedCFSet), CFSetGetTypeID()); + XCTAssertEqual(CFSetGetCount(decodedCFSet), 1, "Should have one item in set"); + + __block bool dateprocessed = false; + CFSetForEach(decodedCFSet, ^(const void *value) { + XCTAssertEqual(CFGetTypeID(value), CFDateGetTypeID()); + XCTAssertEqualWithAccuracy(CFDateGetAbsoluteTime(value), 0, 60 * 60 * 24); + dateprocessed = true; + }); + + XCTAssertTrue(dateprocessed, "Should have processed at least one date in the set"); + } + } + + { + CFArrayRef decodedCFArray = CFDictionaryGetValue(decodedCFDictionary, CFSTR("datearray")); + XCTAssertNotNil((__bridge NSArray*)decodedCFArray, "Should have some CFArray"); + + if(decodedCFArray != NULL) { + XCTAssertEqual(CFGetTypeID(decodedCFArray), CFArrayGetTypeID()); + XCTAssertEqual(CFArrayGetCount(decodedCFArray), 1, "Should have one item in array"); + + __block bool dateprocessed = false; + CFArrayForEach(decodedCFArray, ^(const void *value) { + XCTAssertEqual(CFGetTypeID(value), CFDateGetTypeID()); + XCTAssertEqualWithAccuracy(CFDateGetAbsoluteTime(value), 0, 60 * 60 * 24); + dateprocessed = true; + }); + + XCTAssertTrue(dateprocessed, "Should have processed at least one date in the array"); + } + } + + CFReleaseNull(decoded); +} + +- (void)testSecItemCopyMatchingWithBadDateInItem { + // Wonky time calculation hastily stolen from SecGregorianDateGetAbsoluteTime and tweaked + // As of right now this causes CFCalendarDecomposeAbsoluteTime with Zulu calendar to give a seemingly incorrect date which then causes DER date validation issues + CFAbsoluteTime absTime = (CFAbsoluteTime)(((-(1902 * 365) + -38) * 24 + 0) * 60 + -1) * 60 + 1; + absTime -= 0.0004; + CFDateRef date = CFDateCreate(NULL, absTime); + + NSDictionary* addQuery = @{ + //(id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrCreationDate : (__bridge id)date, + (id)kSecAttrModificationDate : (__bridge id)date, + + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrAccount : @"TestAccount", + (id)kSecAttrService : @"TestService", + (id)kSecAttrAccessGroup : @"com.apple.security.securityd", + + (id)kSecAttrAccessible : @"ak", + (id)kSecAttrTombstone : [NSNumber numberWithInt: 0], + (id)kSecAttrMultiUser : [[NSData alloc] init], + }; + + __block CFErrorRef cferror = NULL; + kc_with_dbt(true, &cferror, ^bool(SecDbConnectionRef dbt) { + return kc_transaction_type(dbt, kSecDbExclusiveTransactionType, &cferror, ^bool { + SecDbItemRef item = SecDbItemCreateWithAttributes(NULL, kc_class_with_name(kSecClassGenericPassword), (__bridge CFDictionaryRef)addQuery, KEYBAG_DEVICE, &cferror); + + bool ret = SecDbItemInsert(item, dbt, false, &cferror); + + XCTAssertTrue(ret, "Should be able to add an item"); + CFReleaseNull(item); + + return ret; + }); + }); + + NSDictionary* findQuery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrAccount : @"TestAccount", + (id)kSecAttrService : @"TestService", + (id)kSecAttrAccessGroup : @"com.apple.security.securityd", + + (id)kSecReturnAttributes : @YES, + (id)kSecReturnData: @YES, + (id)kSecMatchLimit: (id)kSecMatchLimitAll, + }; + + CFTypeRef result = NULL; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)findQuery, &result), errSecItemNotFound, @"Should not be able to find our misdated item"); + + // This is a bit of a mystery: how do these items have a bad date that's not in the item? + + CFReleaseNull(result); + CFReleaseNull(date); +} + +- (void)testSecItemCopyMatchingWithBadDateInSQLColumn { + NSDictionary* addQuery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrAccount : @"TestAccount", + (id)kSecAttrService : @"TestService", + (id)kSecAttrAccessGroup : @"com.apple.security.securityd", + + (id)kSecAttrAccessible : @"ak", + (id)kSecAttrService : @"", + + (id)kSecUseDataProtectionKeychain: @YES, + }; + + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addQuery, NULL); + XCTAssertEqual(status, errSecSuccess, "Should be able to add an item to the keychain"); + + // Modify the cdat/mdat columns in the keychain db + __block CFErrorRef cferror = NULL; + kc_with_dbt(true, &cferror, ^bool(SecDbConnectionRef dbt) { + return kc_transaction_type(dbt, kSecDbExclusiveTransactionType, &cferror, ^bool { + CFErrorRef updateError = NULL; + + // Magic number extracted from testSecItemCopyMatchingWithBadDateInItem + SecDbExec(dbt, + (__bridge CFStringRef)@"UPDATE genp SET cdat = -59984755259.0004, mdat = -59984755259.0004;", + &updateError); + + XCTAssertNil((__bridge NSError*)updateError, "Should be no error updating the table"); + CFReleaseNull(updateError); + + return true; + }); + }); + + // Can we find the item? + NSDictionary* findQuery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrAccount : @"TestAccount", + (id)kSecAttrService : @"TestService", + (id)kSecAttrAccessGroup : @"com.apple.security.securityd", + + (id)kSecReturnAttributes : @YES, + (id)kSecReturnData: @YES, + (id)kSecMatchLimit: (id)kSecMatchLimitAll, + }; + + CFTypeRef result = NULL; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)findQuery, &result), errSecSuccess, @"Should be able to find our misdated item"); + + CFReleaseNull(result); +} + +- (void)testDurableWriteAPI +{ + NSDictionary* addQuery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrAccount : @"TestAccount", + (id)kSecAttrService : @"TestService", + (id)kSecUseDataProtectionKeychain : @(YES), + (id)kSecReturnAttributes : @(YES), + }; + + NSDictionary* updateQuery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"TestAccount", + (id)kSecAttrService : @"TestService", + (id)kSecUseDataProtectionKeychain : @(YES), + }; + + CFTypeRef result = NULL; + + // Add the item + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)addQuery, &result), errSecSuccess, @"Should have succeeded in adding test item to keychain"); + XCTAssertNotNil((__bridge id)result, @"Should have received a dictionary back from SecItemAdd"); + CFReleaseNull(result); + + // Using the API without the entitlement should fail + CFErrorRef cferror = NULL; + XCTAssertEqual(SecItemPersistKeychainWritesAtHighPerformanceCost(&cferror), errSecMissingEntitlement, @"Should not be able to persist keychain writes without the entitlement"); + XCTAssertNotNil((__bridge NSError*)cferror, "Should be an error persisting keychain writes without the entitlement"); + CFReleaseNull(cferror); + + // But with the entitlement, you're good + SecResetLocalSecuritydXPCFakeEntitlements(); + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementPrivatePerformanceImpactingAPI, kCFBooleanTrue); + + XCTAssertEqual(SecItemPersistKeychainWritesAtHighPerformanceCost(&cferror), errSecSuccess, @"Should be able to persist keychain writes"); + XCTAssertNil((__bridge NSError*)cferror, "Should be no error persisting keychain writes"); + + // And we can update the item + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)updateQuery, + (__bridge CFDictionaryRef)@{ + (id)kSecValueData: [@"otherpassword" dataUsingEncoding:NSUTF8StringEncoding], + }), + errSecSuccess, "should be able to update item with clean update query"); + + XCTAssertEqual(SecItemPersistKeychainWritesAtHighPerformanceCost(&cferror), errSecSuccess, @"Should be able to persist keychain writes after an update"); + XCTAssertNil((__bridge NSError*)cferror, "Should be no error persisting keychain writes"); + + XCTAssertEqual(SecItemDelete((__bridge CFDictionaryRef)updateQuery), errSecSuccess, "Should be able to delete item"); + XCTAssertEqual(SecItemPersistKeychainWritesAtHighPerformanceCost(&cferror), errSecSuccess, @"Should be able to persist keychain writes after a delete"); + XCTAssertNil((__bridge NSError*)cferror, "Should be no error persisting keychain writes"); +} + + +#pragma mark - SecItemRateLimit + +// This is not super accurate in BATS, so put some margin around what you need +- (void)sleepAlternativeForXCTest:(double)interval +{ + dispatch_semaphore_t localsema = dispatch_semaphore_create(0); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * interval), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + dispatch_semaphore_signal(localsema); + }); + dispatch_semaphore_wait(localsema, DISPATCH_TIME_FOREVER); +} + +- (void)testSecItemRateLimitTimePasses { + SecItemRateLimit* rl = [SecItemRateLimit getStaticRateLimit]; + [rl forceEnabled: true]; + + for (int idx = 0; idx < rl.roCapacity; ++idx) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + } + + for (int idx = 0; idx < rl.rwCapacity; ++idx) { + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + + [self sleepAlternativeForXCTest: 2]; + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + + [SecItemRateLimit resetStaticRateLimit]; +} + +- (void)testSecItemRateLimitResetAfterExceed { + SecItemRateLimit* rl = [SecItemRateLimit getStaticRateLimit]; + [rl forceEnabled: true]; + + for (int idx = 0; idx < rl.roCapacity; ++idx) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + } + XCTAssertFalse(isReadOnlyAPIRateWithinLimits()); + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + + for (int idx = 0; idx < rl.rwCapacity; ++idx) { + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + XCTAssertFalse(isModifyingAPIRateWithinLimits()); + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + + [SecItemRateLimit resetStaticRateLimit]; +} + +- (void)testSecItemRateLimitMultiplier { + SecItemRateLimit* rl = [SecItemRateLimit getStaticRateLimit]; + [rl forceEnabled: true]; + + int ro_iterations_before = 0; + for (; ro_iterations_before < rl.roCapacity; ++ro_iterations_before) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + } + XCTAssertFalse(isReadOnlyAPIRateWithinLimits()); + + int rw_iterations_before = 0; + for (; rw_iterations_before < rl.rwCapacity; ++rw_iterations_before) { + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + XCTAssertFalse(isModifyingAPIRateWithinLimits()); + + + int ro_iterations_after = 0; + for (; ro_iterations_after < rl.roCapacity; ++ro_iterations_after) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + } + XCTAssertFalse(isReadOnlyAPIRateWithinLimits()); + + int rw_iterations_after = 0; + for (; rw_iterations_after < rl.rwCapacity; ++rw_iterations_after) { + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + XCTAssertFalse(isModifyingAPIRateWithinLimits()); + + XCTAssertEqualWithAccuracy(rl.limitMultiplier * ro_iterations_before, ro_iterations_after, 1); + XCTAssertEqualWithAccuracy(rl.limitMultiplier * rw_iterations_before, rw_iterations_after, 1); + [SecItemRateLimit resetStaticRateLimit]; +} + +// We stipulate that this test is run on an internal release. +// If this were a platform binary limits would be enforced, but it should not be so they should not. +- (void)testSecItemRateLimitInternalPlatformBinariesOnly { + SecItemRateLimit* rl = [SecItemRateLimit getStaticRateLimit]; + + for (int idx = 0; idx < 3 * MAX(rl.roCapacity, rl.rwCapacity); ++idx) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + + [SecItemRateLimit resetStaticRateLimit]; +} + @end #endif diff --git a/secdxctests/KeychainAppClipTests.m b/secdxctests/KeychainAppClipTests.m new file mode 100644 index 00000000..2bbefecf --- /dev/null +++ b/secdxctests/KeychainAppClipTests.m @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import +#include +#include + +#import "KeychainXCTest.h" + +#if USE_KEYSTORE +@interface KeychainAppClipTests : KeychainXCTest +@end + +@implementation KeychainAppClipTests { + // App Clips are only permitted to store items with agrp == appID, so we set and track it + NSString* _applicationIdentifier; +} + ++ (void)setUp { + [super setUp]; +} + +- (void)setUp { + [super setUp]; + SecSecurityClientAppClipToRegular(); + _applicationIdentifier = @"com.apple.security.appcliptests"; + SecSecurityClientSetApplicationIdentifier((__bridge CFStringRef)_applicationIdentifier); +} + ++ (void)tearDown { + SecSecurityClientAppClipToRegular(); + SecSecurityClientSetApplicationIdentifier(NULL); + [super tearDown]; +} + +# pragma mark - Test App Clip API Restrictions (SecItemAdd) + +- (void)testAppclipCanAddItem { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + }; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); +} + +- (void)testAppClipAddNoSyncAllowed { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrSynchronizable : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + }; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecRestrictedAPI); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +- (void)testAppClipAddNoAgrpAllowed { + SecSecurityClientRegularToAppClip(); + // By not explicitly setting entitlements we get the default set which is not permitted for an app clip + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + }; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecRestrictedAPI); + + SecSecurityClientAppClipToRegular(); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +# pragma mark - Test App Clip API Restrictions (SecItemUpdate) + +- (void)testAppClipCanUpdateItem { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + SecItemAdd((__bridge CFDictionaryRef)query, NULL); + + NSDictionary* update = @{ + (id)kSecValueData : [@"different" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrService : @"DifferentAppClipTestService", + }; + + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update), errSecSuccess); + query[(id)kSecAttrService] = @"DifferentAppClipTestService"; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); +} + +- (void)testAppClipUpdateNoSyncAllowed { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + SecItemAdd((__bridge CFDictionaryRef)query, NULL); + + NSDictionary* update = @{ + (id)kSecValueData : [@"different" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrSynchronizable : @YES, + }; + + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update), errSecRestrictedAPI); + query[(id)kSecAttrSynchronizable] = @YES; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +- (void)testAppClipUpdateNoAgrpAllowed { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + SecItemAdd((__bridge CFDictionaryRef)query, NULL); + + NSDictionary* update = @{ + (id)kSecValueData : [@"different" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrAccessGroup : @"someotheraccessgroup", + }; + + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update), errSecMissingEntitlement); + query[(id)kSecAttrAccessGroup] = @"someotheraccessgroup"; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecMissingEntitlement); +} + +# pragma mark - Test App Clip API Restrictions (SecItemCopyMatching) +// For now SICM doesn't care about sync, because there shouldn't be any items where (clip == 1 && sync == 1) + +- (void)testAppClipCopyMatchingNoAgrpsAllowed { + SecSecurityClientRegularToAppClip(); + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnAttributes : @YES, + }; + + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecRestrictedAPI); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +# pragma mark - Test App Clip API Restrictions (SecItemDelete) + +- (void)testAppClipDeleteNoAgrpsAllowed { + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + }; + + XCTAssertEqual(SecItemDelete((__bridge CFDictionaryRef)query), errSecItemNotFound); + SecSecurityClientRegularToAppClip(); + XCTAssertEqual(SecItemDelete((__bridge CFDictionaryRef)query), errSecRestrictedAPI); +} + +# pragma mark - Test App Clip API Restrictions (Misc) + +- (void)testAppClipNoSecItemUpdateTokenItemsAllowed { + SecSecurityClientRegularToAppClip(); + // Don't bother setting it up, app clips aren't even welcome at the door. + XCTAssertEqual(SecItemUpdateTokenItemsForAccessGroups(NULL, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL), errSecRestrictedAPI); +} + +- (void)testAppClipCanPassAppIDAccessGroup { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnAttributes : @YES, + (id)kSecAttrAccessGroup : _applicationIdentifier, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + + NSDictionary* update = @{ + (id)kSecValueData : [@"betterpassword" dataUsingEncoding:NSUTF8StringEncoding], + }; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + query[(id)kSecValueData] = nil; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + query[(id)kSecReturnAttributes] = nil; + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update), errSecSuccess); + XCTAssertEqual(SecItemDelete((__bridge CFDictionaryRef)query), errSecSuccess); +} + +# pragma mark - Test Item Deletion SPI + +- (void)testDeletionSPINoEntitlement { + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)@"nonexistent"), errSecMissingEntitlement); +} + +- (void)testDeletionSPINoItems { + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementPrivateAppClipDeletion, kCFBooleanTrue); + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)@"nonexistent"), errSecSuccess); +} + +- (void)testDeletionSPIDeleteAppClipItem { + // The SPI does not check if app clip, and the API does not check private entitlement + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementPrivateAppClipDeletion, kCFBooleanTrue); + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecReturnAttributes : @YES, + }; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)_applicationIdentifier), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +- (void)testDeletionSPILeaveRegularItemsAlone { + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementPrivateAppClipDeletion, kCFBooleanTrue); + NSString* agrp = @"com.apple.keychain.test.notanappclip"; + [self setEntitlements:@{ @"keychain-access-groups": @[agrp] } validated:YES]; + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrAccessGroup : agrp, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding] + }; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)agrp), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); +} + +- (void)testDeletionSPILeaveOtherAppClipItemsAlone { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSString* otherAppID = @"not-the-same-application-identifier"; + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementPrivateAppClipDeletion, kCFBooleanTrue); + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecReturnAttributes : @YES, + }; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + [self setEntitlements:@{@"com.apple.application-identifier" : otherAppID} validated:YES]; + SecSecurityClientSetApplicationIdentifier((__bridge CFStringRef)otherAppID); + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)_applicationIdentifier), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + SecSecurityClientSetApplicationIdentifier((__bridge CFStringRef)_applicationIdentifier); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +@end +#endif diff --git a/secdxctests/KeychainBackupTests.m b/secdxctests/KeychainBackupTests.m new file mode 100644 index 00000000..94c22372 --- /dev/null +++ b/secdxctests/KeychainBackupTests.m @@ -0,0 +1,118 @@ +#import "KeychainXCTest.h" +#import +#import +#include +#include + +@interface KeychainBackupTests : KeychainXCTest +@end + + +@implementation KeychainBackupTests { + NSString* _applicationIdentifier; +} + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. + [super setUp]; + _applicationIdentifier = @"com.apple.security.backuptests"; + SecSecurityClientSetApplicationIdentifier((__bridge CFStringRef)_applicationIdentifier); +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +# pragma mark - Test OTA Backups + +// Code lovingly adapted from si-33-keychain-backup +#if USE_KEYSTORE +- (NSData*)createKeybagWithType:(keybag_handle_t)bag_type password:(NSData*)password +{ + keybag_handle_t handle = bad_keybag_handle; + kern_return_t bag_created = aks_create_bag(password ? password.bytes : NULL, password ? (int)password.length : 0, bag_type, &handle); + XCTAssertEqual(bag_created, kAKSReturnSuccess, @"Unable to create keybag"); + + void *bag = NULL; + int bagLen = 0; + kern_return_t bag_saved = aks_save_bag(handle, &bag, &bagLen); + XCTAssertEqual(bag_saved, kAKSReturnSuccess, @"Unable to save keybag"); + + NSData* bagData = [NSData dataWithBytes:bag length:bagLen]; + XCTAssertNotNil(bagData, @"Unable to create NSData from bag bytes"); + + return bagData; +} +#endif + +// All backup paths ultimately lead to SecServerCopyKeychainPlist which does the actual exporting, +// so this test ought to suffice for all backup configurations +- (void)testAppClipDoesNotBackup { + + // First add a "regular" item for each class, which we expect to be in the backup later + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassInternetPassword; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassCertificate; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassKey; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + // Switch to being an app clip, add another item for each class, which we expect not to find in the backup + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + + query[(id)kSecClass] = (id)kSecClassGenericPassword; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassInternetPassword; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassCertificate; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassKey; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + SecSecurityClientAppClipToRegular(); + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementRestoreKeychain, kCFBooleanTrue); + + // Code lovingly adapted from si-33-keychain-backup + NSData* keybag; +#if USE_KEYSTORE + keybag = [self createKeybagWithType:kAppleKeyStoreBackupBag password:nil]; +#else + keybag = [NSData new]; +#endif + + NSData* data = CFBridgingRelease(_SecKeychainCopyBackup((__bridge CFDataRef)keybag, nil)); + + XCTAssert(data); + XCTAssertGreaterThan([data length], 42, @"Got empty dictionary"); + NSDictionary* keychain = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:nil error:nil]; + + // Only one item should be here for each class, which is the regular one. + XCTAssertEqual([keychain[@"genp"] count], 1); + XCTAssertEqual([keychain[@"inet"] count], 1); + XCTAssertEqual([keychain[@"cert"] count], 1); + XCTAssertEqual([keychain[@"keys"] count], 1); +} + +@end diff --git a/secdxctests/KeychainCryptoTests.m b/secdxctests/KeychainCryptoTests.m index bdf33b1b..3165c667 100644 --- a/secdxctests/KeychainCryptoTests.m +++ b/secdxctests/KeychainCryptoTests.m @@ -32,6 +32,7 @@ #import "spi.h" #import "SecDbKeychainSerializedItemV7.h" #import "SecDbKeychainSerializedMetadata.h" +#import "SecDbKeychainSerializedMetadataKey.h" #import "SecDbKeychainSerializedSecretData.h" #import "SecDbKeychainSerializedAKSWrappedKey.h" #import @@ -138,6 +139,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { SecAccessControlRef ac = NULL; NSDictionary* secretData = @{(id)kSecValueData : @"secret here"}; + CFDictionaryRef emptyDict = (__bridge CFDictionaryRef)@{}; ac = SecAccessControlCreate(NULL, &error); XCTAssertNotNil((__bridge id)ac, @"failed to create access control with error: %@", (__bridge id)error); @@ -145,16 +147,19 @@ static keyclass_t parse_keyclass(CFTypeRef value) { XCTAssertTrue(SecAccessControlSetProtection(ac, kSecAttrAccessibleWhenUnlocked, &error), @"failed to set access control protection with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to set access control protection: %@", (__bridge id)error); - XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, (__bridge CFDictionaryRef)@{}, NULL, &enc, true, &error), @"failed to encrypt data with error: %@", error); + XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, emptyDict, emptyDict, &enc, true, &error), @"failed to encrypt data with error: %@", error); XCTAssertTrue(enc != NULL, @"failed to get encrypted data from encryption function"); XCTAssertNil((__bridge id)error, @"encountered error attempting to encrypt data: %@", (__bridge id)error); CFReleaseNull(ac); CFMutableDictionaryRef attributes = NULL; uint32_t version = 0; + NSData* dummyACM = [NSData dataWithBytes:"dummy" length:5]; + const SecDbClass* class = kc_class_with_name(kSecClassGenericPassword); + NSArray* dummyArray = [NSArray array]; keyclass_t keyclass = 0; - XCTAssertTrue(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, NULL, enc, NULL, NULL, &attributes, &version, true, &keyclass, &error), @"failed to decrypt data with error: %@", error); + XCTAssertTrue(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, (__bridge CFDataRef _Nonnull)dummyACM, enc, class, (__bridge CFArrayRef)dummyArray, &attributes, &version, true, &keyclass, &error), @"failed to decrypt data with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to decrypt data: %@", (__bridge id)error); XCTAssertEqual(keyclass, key_class_ak, @"failed to get back the keyclass from decryption"); @@ -277,9 +282,9 @@ static keyclass_t parse_keyclass(CFTypeRef value) { NSError* error; SecDbKeychainItemV7* item = [[SecDbKeychainItemV7 alloc] initWithSecretAttributes:@{(id)kSecValueData : password} metadataAttributes:metadata tamperCheck:[[NSUUID UUID] UUIDString] keyclass:9]; [item encryptMetadataWithKeybag:0 error:&error]; - XCTAssertNil(error, @"Successfully encrypted metadata"); + XCTAssertNil(error, "error encrypting metadata with keybag 0"); [item encryptSecretDataWithKeybag:0 accessControl:SecAccessControlCreate(NULL, NULL) acmContext:nil error:&error]; - XCTAssertNil(error, @"Successfully encrypted secret data"); + XCTAssertNil(error, "error encrypting secret data with keybag 0"); SecDbKeychainSerializedItemV7* serializedItem = [[SecDbKeychainSerializedItemV7 alloc] init]; serializedItem.encryptedMetadata = item.encryptedMetadataBlob; serializedItem.encryptedSecretData = item.encryptedSecretDataBlob; @@ -341,6 +346,26 @@ static keyclass_t parse_keyclass(CFTypeRef value) { } - (void)trashMetadataClassAKey +{ + __block CFErrorRef cferror = NULL; + kc_with_dbt(true, &cferror, ^bool(SecDbConnectionRef dbt) { + CFStringRef sql = CFSTR("UPDATE metadatakeys SET data = ? WHERE keyclass = '6'"); + NSData* garbage = [@"super bad key" dataUsingEncoding:NSUTF8StringEncoding]; + SecDbPrepare(dbt, sql, &cferror, ^(sqlite3_stmt *stmt) { + SecDbBindObject(stmt, 1, (__bridge CFDataRef)garbage, &cferror); + SecDbStep(dbt, stmt, &cferror, NULL); + XCTAssertEqual(cferror, NULL, "Should be no error trashing class A metadatakey"); + CFReleaseNull(cferror); + }); + XCTAssertEqual(cferror, NULL, "Should be no error completing SecDbPrepare for trashing class A metadatakey"); + return true; + }); + CFReleaseNull(cferror); + + [[SecDbKeychainMetadataKeyStore sharedStore] dropClassAKeys]; +} + +- (void)deleteMetadataClassAKey { CFErrorRef cferror = NULL; @@ -356,32 +381,31 @@ static keyclass_t parse_keyclass(CFTypeRef value) { [[SecDbKeychainMetadataKeyStore sharedStore] dropClassAKeys]; } -- (void)checkDatabaseExistenceOfMetadataKey:(keyclass_t)keyclass shouldExist:(bool)shouldExist +- (void)checkDatabaseExistenceOfMetadataKey:(keyclass_t)keyclass shouldExist:(bool)shouldExist value:(NSData*)expectedData { CFErrorRef cferror = NULL; - + __block NSData* wrappedKey; kc_with_dbt(true, &cferror, ^bool(SecDbConnectionRef dbt) { __block CFErrorRef errref = NULL; NSString* sql = [NSString stringWithFormat:@"SELECT data, actualKeyclass FROM metadatakeys WHERE keyclass = %d", keyclass]; __block bool ok = true; - __block bool keyExists = false; ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &errref, ^(sqlite3_stmt *stmt) { ok &= SecDbStep(dbt, stmt, &errref, ^(bool *stop) { - NSData* wrappedKeyData = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; - NSMutableData* unwrappedKeyData = [NSMutableData dataWithLength:wrappedKeyData.length]; - - keyExists = !!unwrappedKeyData; + wrappedKey = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; }); }); XCTAssertTrue(ok, "Should have completed all operations correctly"); - XCTAssertEqual(errref, NULL, "Should be no error deleting class A metadatakey"); + XCTAssertEqual(errref, NULL, "Should be no error trying to find class A metadatakey"); if(shouldExist) { - XCTAssertTrue(keyExists, "Metadata class key should exist"); + XCTAssertNotNil(wrappedKey, "Metadata class key should exist"); + if (expectedData) { + XCTAssertEqualObjects(wrappedKey, expectedData); + } } else { - XCTAssertFalse(keyExists, "Metadata class key should not exist"); + XCTAssertNil(wrappedKey, "Metadata class key should not exist"); } CFReleaseNull(errref); return true; @@ -400,7 +424,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { OSStatus result = SecItemAdd((__bridge CFDictionaryRef)item, NULL); XCTAssertEqual(result, 0, @"failed to add test item to keychain"); - [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true value:nil]; NSMutableDictionary* dataQuery = item.mutableCopy; [dataQuery removeObjectForKey:(id)kSecValueData]; @@ -413,7 +437,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { CFReleaseNull(foundItem); [self trashMetadataClassAKey]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:false]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true value:[@"super bad key" dataUsingEncoding:NSUTF8StringEncoding]]; /* when metadata corrupted, we should not find the item */ result = SecItemCopyMatching((__bridge CFDictionaryRef)dataQuery, &foundItem); @@ -421,7 +445,46 @@ static keyclass_t parse_keyclass(CFTypeRef value) { CFReleaseNull(foundItem); // Just calling SecItemCopyMatching shouldn't have created a new metadata key - [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:false]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true value:[@"super bad key" dataUsingEncoding:NSUTF8StringEncoding]]; + + /* CopyMatching will delete corrupt pre-emptively */ + result = SecItemDelete((__bridge CFDictionaryRef)dataQuery); + XCTAssertEqual(result, -25300, @"corrupt item was not deleted for us"); +} + +- (void)testKeychainDeletionCopyMatching +{ + NSDictionary* item = @{ (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrAccount : @"TestAccount", + (id)kSecAttrService : @"TestService", + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked, + (id)kSecUseDataProtectionKeychain : @YES }; + + OSStatus result = SecItemAdd((__bridge CFDictionaryRef)item, NULL); + XCTAssertEqual(result, 0, @"failed to add test item to keychain"); + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true value:nil]; + + NSMutableDictionary* dataQuery = item.mutableCopy; + [dataQuery removeObjectForKey:(id)kSecValueData]; + dataQuery[(id)kSecReturnData] = @(YES); + + CFTypeRef foundItem = NULL; + + result = SecItemCopyMatching((__bridge CFDictionaryRef)dataQuery, &foundItem); + XCTAssertEqual(result, 0, @"failed to find the data for the item we just added in the keychain"); + CFReleaseNull(foundItem); + + [self deleteMetadataClassAKey]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:false value:nil]; + + /* when metadata corrupted, we should not find the item */ + result = SecItemCopyMatching((__bridge CFDictionaryRef)dataQuery, &foundItem); + XCTAssertEqual(result, errSecItemNotFound, @"failed to find the data for the item we just added in the keychain"); + CFReleaseNull(foundItem); + + // Just calling SecItemCopyMatching shouldn't have created a new metadata key + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:false value:nil]; /* CopyMatching will delete corrupt pre-emptively */ result = SecItemDelete((__bridge CFDictionaryRef)dataQuery); @@ -508,6 +571,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { self.allowDecryption = NO; NSDictionary* secretData = @{(id)kSecValueData : @"secret here"}; + CFDictionaryRef emptyDict = (__bridge CFDictionaryRef)@{}; ac = SecAccessControlCreate(NULL, &error); XCTAssertNotNil((__bridge id)ac, @"failed to create access control with error: %@", (__bridge id)error); @@ -515,16 +579,19 @@ static keyclass_t parse_keyclass(CFTypeRef value) { XCTAssertTrue(SecAccessControlSetProtection(ac, kSecAttrAccessibleWhenUnlocked, &error), @"failed to set access control protection with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to set access control protection: %@", (__bridge id)error); - XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, (__bridge CFDictionaryRef)@{}, NULL, &enc, true, &error), @"failed to encrypt data with error: %@", error); + XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, emptyDict, emptyDict, &enc, true, &error), @"failed to encrypt data with error: %@", error); XCTAssertTrue(enc != NULL, @"failed to get encrypted data from encryption function"); XCTAssertNil((__bridge id)error, @"encountered error attempting to encrypt data: %@", (__bridge id)error); CFReleaseNull(ac); CFMutableDictionaryRef attributes = NULL; uint32_t version = 0; + NSData* dummyACM = [NSData dataWithBytes:"dummy" length:5]; + const SecDbClass* class = kc_class_with_name(kSecClassGenericPassword); + NSArray* dummyArray = [NSArray array]; keyclass_t keyclass = 0; - XCTAssertNoThrow(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, NULL, enc, NULL, NULL, &attributes, &version, true, &keyclass, &error), @"unexpected exception when decryption fails"); + XCTAssertNoThrow(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, (__bridge CFDataRef _Nonnull)dummyACM, enc, class, (__bridge CFArrayRef)dummyArray, &attributes, &version, true, &keyclass, &error), @"unexpected exception when decryption fails"); XCTAssertEqual(keyclass, key_class_ak, @"failed to get back the keyclass when decryption failed"); self.allowDecryption = YES; @@ -744,18 +811,18 @@ static keyclass_t parse_keyclass(CFTypeRef value) { NSString* otherAccount = @"OtherAccount"; NSString* thirdAccount = @"ThirdAccount"; [self addTestItemExpecting:errSecSuccess account:testAccount accessible:(id)kSecAttrAccessibleAfterFirstUnlock]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true]; - [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:false]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true value:nil]; + [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:false value:nil]; // This should fail, and not create a CKU metadata key [self addTestItemExpecting:errSecDuplicateItem account:testAccount accessible:(id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true]; - [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:false]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true value:nil]; + [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:false value:nil]; // But successfully creating a new CKU item should create the key [self addTestItemExpecting:errSecSuccess account:otherAccount accessible:(id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true]; - [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:true]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true value:nil]; + [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:true value:nil]; // Drop all metadata key caches [SecDbKeychainMetadataKeyStore resetSharedStore]; @@ -765,8 +832,8 @@ static keyclass_t parse_keyclass(CFTypeRef value) { // Adding another CKU item now should be fine [self addTestItemExpecting:errSecSuccess account:thirdAccount accessible:(id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true]; - [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:true]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true value:nil]; + [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:true value:nil]; // Drop all metadata key caches once more, to ensure we can find all three items from the persisted keys [SecDbKeychainMetadataKeyStore resetSharedStore]; @@ -796,6 +863,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { CFErrorRef error = NULL; NSDictionary* secretData = @{(id)kSecValueData : @"secret here"}; + CFDictionaryRef emptyDict = (__bridge CFDictionaryRef)@{}; ac = SecAccessControlCreate(NULL, &error); XCTAssertNotNil((__bridge id)ac, @"failed to create access control with error: %@", (__bridge id)error); @@ -803,7 +871,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { XCTAssertTrue(SecAccessControlSetProtection(ac, accessibility, &error), @"failed to set access control protection with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to set access control protection: %@", (__bridge id)error); - XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, (__bridge CFDictionaryRef)@{}, NULL, &enc, true, &error), @"failed to encrypt data with error: %@", error); + XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, emptyDict, emptyDict, &enc, true, &error), @"failed to encrypt data with error: %@", error); XCTAssertTrue(enc != NULL, @"failed to get encrypted data from encryption function"); XCTAssertNil((__bridge id)error, @"encountered error attempting to encrypt data: %@", (__bridge id)error); CFReleaseNull(ac); @@ -824,7 +892,11 @@ static keyclass_t parse_keyclass(CFTypeRef value) { XCTAssertNil((__bridge id)error, @"encountered error attempting to set access control protection: %@", (__bridge id)error); keyclass_t keyclass = 0; - XCTAssertTrue(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, NULL, (__bridge CFDataRef)encryptedData, NULL, NULL, &attributes, &version, false, &keyclass, &error), @"failed to decrypt data with error: %@", error); + NSData* dummyACM = [NSData dataWithBytes:"dummy" length:5]; + const SecDbClass* class = kc_class_with_name(kSecClassGenericPassword); + NSArray* dummyArray = [NSArray array]; + + XCTAssertTrue(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, (__bridge CFDataRef _Nonnull)dummyACM, (__bridge CFDataRef)encryptedData, class, (__bridge CFArrayRef)dummyArray, &attributes, &version, false, &keyclass, &error), @"failed to decrypt data with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to decrypt data: %@", (__bridge id)error); XCTAssertEqual(keyclass & key_class_last, parse_keyclass(accessibility), @"failed to get back the keyclass from decryption"); @@ -881,13 +953,27 @@ static keyclass_t parse_keyclass(CFTypeRef value) { __block CFErrorRef error = NULL; __block bool ok = true; ok &= kc_with_dbt(true, &error, ^bool(SecDbConnectionRef dbt) { - NSString* sql = [NSString stringWithFormat:@"UPDATE metadatakeys SET actualKeyclass = %d WHERE keyclass = %d", 0, key_class_ak]; - ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &error, ^(sqlite3_stmt* stmt) { - ok &= SecDbStep(dbt, stmt, &error, ^(bool* stop) { - // woohoo + if (checkV12DevEnabled()) { // item is in new format, turn it into an old format item + NSString* sql = [NSString stringWithFormat:@"SELECT metadatakeydata FROM metadatakeys WHERE keyclass = %d", key_class_ak]; + __block NSData* key; + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &error, ^(sqlite3_stmt* stmt) { + ok &= SecDbStep(dbt, stmt, &error, ^(bool *stop) { + NSData* wrappedKey = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; + SecDbKeychainSerializedMetadataKey* mdkdata = [[SecDbKeychainSerializedMetadataKey alloc] initWithData:wrappedKey]; + key = mdkdata.akswrappedkey; + }); }); - }); - + sql = [NSString stringWithFormat:@"UPDATE metadatakeys SET actualKeyclass = 0, data = ?, metadatakeydata = ? WHERE keyclass = %d", key_class_ak]; + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &error, ^(sqlite3_stmt *stmt) { + ok &= SecDbBindBlob(stmt, 1, key.bytes, key.length, SQLITE_TRANSIENT, &error); + ok &= SecDbStep(dbt, stmt, &error, NULL); + }); + } else { + NSString* sql = [NSString stringWithFormat:@"UPDATE metadatakeys SET actualKeyclass = %d WHERE keyclass = %d", 0, key_class_ak]; + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &error, ^(sqlite3_stmt* stmt) { + ok &= SecDbStep(dbt, stmt, &error, NULL); + }); + } return ok; }); diff --git a/secdxctests/KeychainEntitlementsTest.m b/secdxctests/KeychainEntitlementsTest.m index d5be9242..b72a6c5d 100644 --- a/secdxctests/KeychainEntitlementsTest.m +++ b/secdxctests/KeychainEntitlementsTest.m @@ -23,6 +23,7 @@ #import #import +#import #import "KeychainXCTest.h" @@ -39,7 +40,18 @@ // Application with no keychain-related entitlements at all, but CopyMatching must work in order to support // backward compatibility with smart-card-enabled macos applications (com.apple.token AG is added automatically in this case). [self setEntitlements:@{} validated:false]; - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { +#if TARGET_OS_OSX + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); +#else + // On non-macOS targets, token items must be explicitly enabled, and that requires entitlements. + // But since this test has no entitlements, it will always fail with errSecMissingEntitlement. + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); +#endif + } else { + // If tokens are not enabled, this situation really means that there is an entitlement problem. + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); + } // However, write access is declined for such application. XCTAssertEqual(SecItemAdd((CFDictionaryRef)params, NULL), errSecMissingEntitlement); @@ -120,8 +132,12 @@ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"label", (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, }; - [self setEntitlements:@{ @"com.apple.application-identifier": (id)kSecAttrAccessGroupToken } validated:YES]; - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + [self setEntitlements:@{ @"keychain-access-groups": @[ (id)kSecAttrAccessGroupToken ] } validated:YES]; + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + } else { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); + } XCTAssertEqual(SecItemAdd((CFDictionaryRef)params, NULL), errSecMissingEntitlement); XCTAssertEqual(SecItemDelete((CFDictionaryRef)params), errSecMissingEntitlement); } @@ -134,8 +150,12 @@ (id)kSecAttrLabel: @"label", }; [self setEntitlements:@{ @"com.apple.security.application-groups": @[@"com.apple.test-app-groups"] } validated:NO]; - // Invalid access group entitlement should still allow querying com.apple.token - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + // Invalid access group entitlement should still allow querying com.apple.token, if tokens are enabled + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + } else { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); + } // But write-access is forbidden, XCTAssertEqual(SecItemAdd((CFDictionaryRef)params, NULL), errSecMissingEntitlement); @@ -150,47 +170,66 @@ XCTAssertEqual(SecItemAdd((CFDictionaryRef)params, NULL), errSecMissingEntitlement); XCTAssertEqual(SecItemDelete((CFDictionaryRef)params), errSecMissingEntitlement); - // Explicitly referring to com.apple.token should work fine too. params = @{ (id)kSecUseDataProtectionKeychain: @YES, (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"label", (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, }; - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + } else { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); + } } #endif // TARGET_OS_OSX - (void)testTokenItemsGroup { NSDictionary *params; + [self setEntitlements:@{ +#if TARGET_OS_OSX + @"com.apple.application-identifier": @"com.apple.test-app-identifier", +#else + @"application-identifier": @"com.apple.test-app-identifier", +#endif + @"keychain-access-groups": @[ @"com.apple.token" ], + } validated:YES]; + // Add token items for testing into the keychain. NSArray *tokenItems = @[ @{ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, (id)kSecAttrLabel: @"label", } ]; - XCTAssertEqual(SecItemUpdateTokenItems(@"com.apple.testtoken", (__bridge CFArrayRef)tokenItems), errSecSuccess); + XCTAssertEqual(SecItemUpdateTokenItemsForAccessGroups(@"com.apple.testtoken", (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], (__bridge CFArrayRef)tokenItems), errSecSuccess); - [self setEntitlements:@{ @"com.apple.application-identifier": @"com.apple.test-app-identifier" } validated:YES]; - - // Query without explicit access group, should find item on macOS and not find it on iOS. + // Query should find items, because we have token access group in entitlements. params = @{ (id)kSecUseDataProtectionKeychain: @YES, (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"label", }; + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecSuccess); + } else { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + } + #if TARGET_OS_IPHONE + // Not having access group in entitlements will not find items. + [self setEntitlements:@{ + @"application-identifier": @"com.apple.test-app-identifier", + } validated:YES]; XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); -#else - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecSuccess); #endif - // Query with explicit AG should work the same on both platforms. - params = @{ (id)kSecUseDataProtectionKeychain: @YES, - (id)kSecClass: (id)kSecClassGenericPassword, - (id)kSecAttrLabel: @"label", - (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, }; - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecSuccess); - // Delete all test token items. - SecItemUpdateTokenItems(@"com.apple.testtoken", (__bridge CFArrayRef)@[]); + [self setEntitlements:@{ +#if TARGET_OS_OSX + @"com.apple.application-identifier": @"com.apple.test-app-identifier", +#else + @"application-identifier": @"com.apple.test-app-identifier", +#endif + @"keychain-access-groups": @[ @"com.apple.token" ], + } validated:YES]; + SecItemUpdateTokenItemsForAccessGroups(@"com.apple.testtoken", (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], (__bridge CFArrayRef)@[]); } - (void)testEntitlementForExplicitAccessGroupLacking { diff --git a/secdxctests/KeychainXCTest.h b/secdxctests/KeychainXCTest.h index 4e1e27d9..ee84d823 100644 --- a/secdxctests/KeychainXCTest.h +++ b/secdxctests/KeychainXCTest.h @@ -37,6 +37,9 @@ typedef enum { LockStateLockedAndAllowAKS // this state matches how backup works while locked } LockState; +@interface KeychainXCTestFailureLogger : NSObject +@end + @interface KeychainXCTest : XCTestCase @property LockState lockState; @@ -47,8 +50,10 @@ typedef enum { @property BOOL simulateRolledAKSKey; @property keyclass_t keyclassUsedForAKSDecryption; +@property NSString* keychainDirectoryPrefix; + @property SFAESKeySpecifier* keySpecifier; -@property SFAESKey* fakeAKSKey; +@property NSData* fakeAKSKey; @property id keychainPartialMock; @@ -56,7 +61,7 @@ typedef enum { - (void)setEntitlements:(NSDictionary *)entitlements validated:(BOOL)validated; -- (NSData*)getDatabaseKeyDataithError:(NSError**)error; +- (NSData*)getDatabaseKeyDataWithError:(NSError**)error; @end diff --git a/secdxctests/KeychainXCTest.m b/secdxctests/KeychainXCTest.m index bab2a47c..fcc06c6d 100644 --- a/secdxctests/KeychainXCTest.m +++ b/secdxctests/KeychainXCTest.m @@ -27,6 +27,7 @@ #import "CKKS.h" #import "SecDbKeychainItemV7.h" #import "SecDbKeychainMetadataKeyStore.h" +#import "SecDbBackupManager_Internal.h" #import "SecAKSObjCWrappers.h" #import "SecItemPriv.h" #import "SecTaskPriv.h" @@ -44,6 +45,37 @@ #import #import #import +#include +#include +#include +#include +#include +#include "CheckV12DevEnabled.h" + +void* testlist = NULL; + +// TODO: Switch to '1' closer to deployment, but leave at '0' for now to test not breaking people +static int testCheckV12DevEnabled(void) { + return 0; +} + +@implementation KeychainXCTestFailureLogger +- (instancetype)init { + if((self = [super init])) { + } + return self; +} + +- (void)testCase:(XCTestCase *)testCase didRecordIssue:(XCTIssue *)issue { + secnotice("keychainxctest", "XCTest failure: (%@)%@:%lu error: %@ -- %@\n%@", + testCase.name, + issue.sourceCodeContext.location.fileURL, + (unsigned long)issue.sourceCodeContext.location.lineNumber, + issue.compactDescription, + issue.detailedDescription, + issue.sourceCodeContext.callStack); +} +@end #if USE_KEYSTORE @@ -118,21 +150,30 @@ @implementation KeychainXCTest { id _keychainPartialMock; CFArrayRef _originalAccessGroups; + bool _simcrashenabled; } +static KeychainXCTestFailureLogger* _testFailureLoggerVariable; + @synthesize keychainPartialMock = _keychainPartialMock; + (void)setUp { [super setUp]; - SecCKKSDisable(); + + self.testFailureLogger = [[KeychainXCTestFailureLogger alloc] init]; + [[XCTestObservationCenter sharedTestObservationCenter] addTestObserver:self.testFailureLogger]; + + // Do not want test code to be allowed to init real keychain! + secd_test_setup_temp_keychain("keychaintestthrowaway", NULL); securityd_init(NULL); } - (void)setUp { - __security_simulatecrash_enable(true); + _simcrashenabled = __security_simulatecrash_enabled(); + __security_simulatecrash_enable(false); [super setUp]; @@ -140,14 +181,13 @@ self.allowDecryption = true; self.didAKSDecrypt = NO; self.simulateRolledAKSKey = NO; - + + secnotice("keychainxctest", "Beginning test %@", self.name); self.keyclassUsedForAKSDecryption = 0; self.keySpecifier = [[SFAESKeySpecifier alloc] initWithBitSize:SFAESKeyBitSize256]; [self setNewFakeAKSKey:[NSData dataWithBytes:"1234567890123456789012345678901" length:32]]; - - [SecDbKeychainMetadataKeyStore resetSharedStore]; self.mockSecDbKeychainItemV7 = OCMClassMock([SecDbKeychainItemV7 class]); [[[self.mockSecDbKeychainItemV7 stub] andCall:@selector(decryptionOperation) onObject:self] decryptionOperation]; @@ -162,21 +202,52 @@ id refKeyMock = OCMClassMock([SecAKSRefKey class]); [[[refKeyMock stub] andCall:@selector(alloc) onObject:[FakeAKSRefKey class]] alloc]; + checkV12DevEnabled = testCheckV12DevEnabled; NSArray* partsOfName = [self.name componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" ]"]]; - secd_test_setup_temp_keychain([partsOfName[1] UTF8String], NULL); + self.keychainDirectoryPrefix = partsOfName[1]; + + // Calls SecKeychainDbReset which also resets metadata keys and backup manager + secd_test_setup_temp_keychain([self.keychainDirectoryPrefix UTF8String], NULL); _originalAccessGroups = SecAccessGroupsGetCurrent(); + SecResetLocalSecuritydXPCFakeEntitlements(); } - (void)tearDown { [self.mockSecDbKeychainItemV7 stopMocking]; [self.mockSecAKSObjCWrappers stopMocking]; + [self resetEntitlements]; SecAccessGroupsSetCurrent(_originalAccessGroups); + __security_simulatecrash_enable(_simcrashenabled); + + if(self.keychainDirectoryPrefix) { + XCTAssertTrue(secd_test_teardown_delete_temp_keychain([self.keychainDirectoryPrefix UTF8String]), "Should be able to delete the temp keychain"); + } else { + XCTFail("Should have had a keychain directory to remove"); + } + + secnotice("keychainxctest", "Ending test %@", self.name); [super tearDown]; } ++ (void)tearDown { + secd_test_teardown_delete_temp_keychain("keychaintestthrowaway"); + SecResetLocalSecuritydXPCFakeEntitlements(); + [super tearDown]; + + [[XCTestObservationCenter sharedTestObservationCenter] removeTestObserver:self.testFailureLogger]; +} + ++ (KeychainXCTestFailureLogger*)testFailureLogger { + return _testFailureLoggerVariable; +} + ++ (void)setTestFailureLogger:(KeychainXCTestFailureLogger*)logger { + _testFailureLoggerVariable = logger; +} + - (bool)isKeychainUnlocked { return self.lockState == LockStateUnlocked; @@ -189,13 +260,52 @@ - (bool)setNewFakeAKSKey:(NSData*)newKeyData { - NSError* error = nil; - self.fakeAKSKey = [[SFAESKey alloc] initWithData:newKeyData specifier:self.keySpecifier error:&error]; - XCTAssertNil(error, "Should be no error making a fake AKS key"); - XCTAssertNotNil(self.fakeAKSKey, "Should have received a fake AKS key"); + self.fakeAKSKey = newKeyData; return true; } +- (NSData*)wrapKey:(NSData*)plaintextKey withKey:(NSData*)wrappingKey +{ + const struct ccmode_ecb *ecb_mode = ccaes_ecb_encrypt_mode(); + ccecb_ctx_decl(ccecb_context_size(ecb_mode), key); + NSMutableData* wrappedKey = [NSMutableData dataWithLength:ccwrap_wrapped_size(plaintextKey.length)]; + + ccecb_init(ecb_mode, key, wrappingKey.length, wrappingKey.bytes); + + size_t obytes = 0; + int wrap_status = ccwrap_auth_encrypt(ecb_mode, key, plaintextKey.length, plaintextKey.bytes, + &obytes, wrappedKey.mutableBytes); + if (wrap_status == 0) { + assert(obytes == wrappedKey.length); + } else { + wrappedKey = nil; + } + + ccecb_ctx_clear(ccecb_context_size(ecb_mode), key); + return wrappedKey; +} + +- (NSData*)unwrapKey:(NSData*)ciphertextKey withKey:(NSData*)wrappingKey +{ + const struct ccmode_ecb *ecb_mode = ccaes_ecb_decrypt_mode(); + ccecb_ctx_decl(ccecb_context_size(ecb_mode), key); + NSMutableData *unwrappedKey = [NSMutableData dataWithLength:ccwrap_unwrapped_size(ciphertextKey.length)]; + + ccecb_init(ecb_mode, key, wrappingKey.length, wrappingKey.bytes); + + size_t obytes = 0; + int status = ccwrap_auth_decrypt(ecb_mode, key, ciphertextKey.length, ciphertextKey.bytes, + &obytes, unwrappedKey.mutableBytes); + if (status == 0) { + assert(obytes == (size_t)[unwrappedKey length]); + } else { + unwrappedKey = nil; + } + + ccecb_ctx_clear(ccecb_context_size(ecb_mode), key); + return unwrappedKey; +} + - (bool)fakeAKSEncryptWithKeybag:(keybag_handle_t)keybag keyclass:(keyclass_t)keyclass plaintext:(NSData*)plaintext @@ -209,36 +319,25 @@ } return false; } - - uint32_t keyLength = (uint32_t)plaintext.length; - const uint8_t* keyBytes = plaintext.bytes; - - NSData* dataToEncrypt = [NSData dataWithBytes:keyBytes length:keyLength]; - NSError* localError = nil; - - SFAuthenticatedEncryptionOperation* encryptionOperation = [[SFAuthenticatedEncryptionOperation alloc] initWithKeySpecifier:self.keySpecifier]; - encryptionOperation.authenticationCodeLength = 8; - SFAuthenticatedCiphertext* ciphertext = [encryptionOperation encrypt:dataToEncrypt withKey:self.fakeAKSKey error:&localError]; - - if (error) { - *error = localError; + + if (keybag == KEYBAG_DEVICE) { + XCTAssertLessThanOrEqual(ciphertextOut.length, APPLE_KEYSTORE_MAX_SYM_WRAPPED_KEY_LEN); + } else { // this'll do for now: assume non-device bags are asymmetric backup bags + XCTAssertLessThanOrEqual(ciphertextOut.length, APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN); } - if (ciphertext) { - void* wrappedKeyMutableBytes = ciphertextOut.mutableBytes; - memcpy(wrappedKeyMutableBytes, ciphertext.ciphertext.bytes, 32); - memcpy(wrappedKeyMutableBytes + 32, ciphertext.initializationVector.bytes, 32); - memcpy(wrappedKeyMutableBytes + 64, ciphertext.authenticationCode.bytes, 8); - + NSData* wrappedKey = [self wrapKey:plaintext withKey:self.fakeAKSKey]; + if (ciphertextOut.length >= wrappedKey.length) { + memcpy(ciphertextOut.mutableBytes, wrappedKey.bytes, wrappedKey.length); + ciphertextOut.length = wrappedKey.length; // simulate ks_crypt behavior if (self.simulateRolledAKSKey && outKeyclass) { *outKeyclass = keyclass | (key_class_last + 1); } else if (outKeyclass) { *outKeyclass = keyclass; } - return true; - } - else { + } else { + XCTFail(@"output buffer too small for wrapped key"); return false; } } @@ -261,49 +360,30 @@ // let's make decryption fail like it would if this were an old metadata key entry made with a generational AKS key, but we didn't store that info in the database return false; } - - const uint8_t* wrappedKeyBytes = ciphertextIn.bytes; - - NSData* ciphertextData = [NSData dataWithBytes:wrappedKeyBytes length:32]; - NSData* ivData = [NSData dataWithBytes:wrappedKeyBytes + 32 length:32]; - NSData* authCodeData = [NSData dataWithBytes:wrappedKeyBytes + 64 length:8]; - SFAuthenticatedCiphertext* ciphertext = [[SFAuthenticatedCiphertext alloc] initWithCiphertext:ciphertextData authenticationCode:authCodeData initializationVector:ivData]; - - NSError* localError = nil; - - SFAuthenticatedEncryptionOperation* encryptionOperation = [[SFAuthenticatedEncryptionOperation alloc] initWithKeySpecifier:self.keySpecifier]; - encryptionOperation.authenticationCodeLength = 8; - NSData* decryptedData = [encryptionOperation decrypt:ciphertext withKey:self.fakeAKSKey error:&localError]; - // in real securityd, we go through AKS rather than SFCryptoServices - // we need to translate the error for proper handling - if ([localError.domain isEqualToString:SFCryptoServicesErrorDomain] && localError.code == SFCryptoServicesErrorDecryptionFailed) { - if (!self.simulateRolledAKSKey && keyclass > key_class_last) { - // for this case we want to simulate what happens when we try decrypting with a rolled keyclass on a device which has never been rolled, which is it ends up with a NotPermitted error from AKS which the security layer translates as locked keybag - localError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecInteractionNotAllowed userInfo:nil]; - } - else { - localError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecDecode userInfo:nil]; - } - } - - if (error) { - *error = localError; - } - self.keyclassUsedForAKSDecryption = keyclass; - if (decryptedData && decryptedData.length <= plaintext.length) { - memcpy(plaintext.mutableBytes, decryptedData.bytes, decryptedData.length); - plaintext.length = decryptedData.length; + NSData* unwrappedKey = [self unwrapKey:ciphertextIn withKey:self.fakeAKSKey]; + if (unwrappedKey && plaintext.length >= unwrappedKey.length) { + memcpy(plaintext.mutableBytes, unwrappedKey.bytes, unwrappedKey.length); + plaintext.length = unwrappedKey.length; // simulate ks_crypt behavior self.didAKSDecrypt = YES; return true; - } - else { + } else if (unwrappedKey) { + XCTFail(@"output buffer too small for unwrapped key"); + return false; + } else { + if (error && !self.simulateRolledAKSKey && keyclass > key_class_last) { + // for this case we want to simulate what happens when we try decrypting with a rolled keyclass on a device which has never been rolled, which is it ends up with a NotPermitted error from AKS which the security layer translates as locked keybag + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecInteractionNotAllowed userInfo:nil]; + } + else if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecDecode userInfo:nil]; + } return false; } } -- (NSData*)getDatabaseKeyDataithError:(NSError**)error +- (NSData*)getDatabaseKeyDataWithError:(NSError**)error { if (_lockState == LockStateUnlocked) { return [NSData dataWithBytes:"1234567890123456789012345678901" length:32]; @@ -319,8 +399,7 @@ // Mock SecTask entitlement retrieval API, so that we can test access group entitlement parsing code in SecTaskCopyAccessGroups() static NSDictionary *currentEntitlements = nil; -static BOOL currentEntitlementsValidated = false; -static NSArray *currentAccessGroups = nil; +static BOOL currentEntitlementsValidated = YES; CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error) { id value = currentEntitlements[(__bridge id)entitlement]; @@ -338,8 +417,13 @@ Boolean SecTaskEntitlementsValidated(SecTaskRef task) { currentEntitlements = entitlements; currentEntitlementsValidated = validated; id task = CFBridgingRelease(SecTaskCreateFromSelf(kCFAllocatorDefault)); - currentAccessGroups = CFBridgingRelease(SecTaskCopyAccessGroups((__bridge SecTaskRef)task)); - SecAccessGroupsSetCurrent((__bridge CFArrayRef)currentAccessGroups); + NSArray *currentAccessGroups = CFBridgingRelease(SecTaskCopyAccessGroups((__bridge SecTaskRef)task)); + SecAccessGroupsSetCurrent((__bridge CFArrayRef)currentAccessGroups); // SetCurrent retains the access groups +} + +- (void)resetEntitlements { + currentEntitlements = nil; + currentEntitlementsValidated = YES; } @end diff --git a/secdxctests/SFCredentialStoreTests.m b/secdxctests/SFCredentialStoreTests.m index 62aa116e..cda02311 100644 --- a/secdxctests/SFCredentialStoreTests.m +++ b/secdxctests/SFCredentialStoreTests.m @@ -121,7 +121,7 @@ { [super setUp]; self.keychainPartialMock = OCMPartialMock([(SFKeychainServer*)[[self.class serverProxyWithError:nil] server] _keychain]); - [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; + [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataWithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; _credentialStore = [[SFCredentialStore alloc] _init]; } diff --git a/secdxctests/secdxctests-entitlements.plist b/secdxctests/secdxctests-entitlements.plist new file mode 100644 index 00000000..0614e949 --- /dev/null +++ b/secdxctests/secdxctests-entitlements.plist @@ -0,0 +1,33 @@ + + + + + com.apple.application-identifier + com.apple.secdxctests + application-identifier + com.apple.secdxctests + com.apple.keystore.access-keychain-keys + + com.apple.keystore.lockassertion + + com.apple.private.associated-domains + + com.apple.private.necp.match + + com.apple.mkb.usersession.info + + seatbelt-profiles + + securityd + + com.apple.security.app-sandbox + + com.apple.security.get-task-allow + + keychain-access-groups + + SecDbBackupManager-UnitTests + + + + diff --git a/sectask/SecEntitlements.h b/sectask/SecEntitlements.h index 9dd2005d..a772373f 100644 --- a/sectask/SecEntitlements.h +++ b/sectask/SecEntitlements.h @@ -47,10 +47,11 @@ __BEGIN_DECLS Note that iOS and macOS uses different value for the same constant. */ -#if TARGET_OS_IPHONE -#define kSecEntitlementApplicationIdentifier CFSTR("application-identifier") -#else #define kSecEntitlementAppleApplicationIdentifier CFSTR("com.apple.application-identifier") +#define kSecEntitlementBasicApplicationIdentifier CFSTR("application-identifier") +#if TARGET_OS_IPHONE +#define kSecEntitlementApplicationIdentifier kSecEntitlementBasicApplicationIdentifier +#else #define kSecEntitlementApplicationIdentifier kSecEntitlementAppleApplicationIdentifier #endif @@ -151,6 +152,9 @@ __BEGIN_DECLS /* Entitlement to allow use of CKKS plaintext fields */ #define kSecEntitlementPrivateCKKSPlaintextFields CFSTR("com.apple.private.ckks.plaintextfields") +/* Entitlement to allow use of inet expansion fields */ +#define kSecEntitlementPrivateInetExpansionFields CFSTR("com.apple.private.keychain.inet_expansion_fields") + /* Entitlement to allow use of CKKS 'current item' changing SPI */ #define kSecEntitlementPrivateCKKSWriteCurrentItemPointers CFSTR("com.apple.private.ckks.currentitempointers_write") @@ -165,12 +169,27 @@ __BEGIN_DECLS /* Entitlement to allow executing keychain control actions */ #define kSecEntitlementKeychainControl CFSTR("com.apple.private.keychain.keychaincontrol") +/* Entitlement to allow deletion of app clip keychain items */ +#define kSecEntitlementPrivateAppClipDeletion CFSTR("com.apple.private.keychain.appclipdeletion") + +/* Entitlement to allow use of performance-impacting API */ +#define kSecEntitlementPrivatePerformanceImpactingAPI CFSTR("com.apple.private.keychain.performance_impacting_api") + +/* Entitlements to allow executing SecItemUpdateTokenItemsForAccessGroups SPI */ +#define kSecEntitlementUpdateTokenItems CFSTR("com.apple.private.keychain.allow-update-tokens") + +/* Entitlement to control access to login keychain master key stashing (loginwindow) */ +#define kSecEntitlementPrivateStash CFSTR("com.apple.private.securityd.stash") + #if __OBJC__ /* Entitlement to control use of OT */ #define kSecEntitlementPrivateOctagon @"com.apple.private.octagon" /* Entitlement to control use of Escrow Update */ #define kSecEntitlementPrivateEscrowRequest @"com.apple.private.escrow-update" + +/* Entitlement for macOS securityd to connect to stash agent */ +#define kSecEntitlementPrivateStashService @"com.apple.private.securityd.stash-agent-client" #endif __END_DECLS diff --git a/sectask/SecTask.c b/sectask/SecTask.c index a73416c7..4b38f13d 100644 --- a/sectask/SecTask.c +++ b/sectask/SecTask.c @@ -25,6 +25,7 @@ #include "SecTaskPriv.h" #include +#include #include #include @@ -237,46 +238,44 @@ static bool SecTaskLoadEntitlements(SecTaskRef task, CFErrorRef *error) uint32_t bufferlen; int ret; - ret = csops_task(task, CS_OPS_ENTITLEMENTS_BLOB, &header, sizeof(header)); /* Any other combination means no entitlements */ - if (ret == -1) { - if (errno != ERANGE) { + if (ret == -1) { + if (errno != ERANGE) { int entitlementErrno = errno; - uint32_t cs_flags = -1; + uint32_t cs_flags = -1; if (-1 == csops_task(task, CS_OPS_STATUS, &cs_flags, sizeof(cs_flags))) { syslog(LOG_NOTICE, "Failed to get cs_flags, error=%d", errno); } - if (cs_flags != 0) { // was signed + if (cs_flags != 0) { // was signed + pid_t pid; + audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL); + syslog(LOG_NOTICE, "SecTaskLoadEntitlements failed error=%d cs_flags=%x, pid=%d", entitlementErrno, cs_flags, pid); // to ease diagnostics - pid_t pid; - audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL); - syslog(LOG_NOTICE, "SecTaskLoadEntitlements failed error=%d cs_flags=%x, pid=%d", entitlementErrno, cs_flags, pid); // to ease diagnostics + CFStringRef description = SecTaskCopyDebugDescription(task); + char *descriptionBuf = NULL; + CFIndex descriptionSize = CFStringGetLength(description) * 4; + descriptionBuf = (char *)malloc(descriptionSize); + if (!CFStringGetCString(description, descriptionBuf, descriptionSize, kCFStringEncodingUTF8)) { + descriptionBuf[0] = 0; + } - CFStringRef description = SecTaskCopyDebugDescription(task); - char *descriptionBuf = NULL; - CFIndex descriptionSize = CFStringGetLength(description) * 4; - descriptionBuf = (char *)malloc(descriptionSize); - if (!CFStringGetCString(description, descriptionBuf, descriptionSize, kCFStringEncodingUTF8)) { - descriptionBuf[0] = 0; - } + syslog(LOG_NOTICE, "SecTaskCopyDebugDescription: %s", descriptionBuf); + CFReleaseNull(description); + free(descriptionBuf); + } + task->lastFailure = entitlementErrno; // was overwritten by csops_task(CS_OPS_STATUS) above - syslog(LOG_NOTICE, "SecTaskCopyDebugDescription: %s", descriptionBuf); - CFReleaseNull(description); - free(descriptionBuf); - } - task->lastFailure = entitlementErrno; // was overwritten by csops_task(CS_OPS_STATUS) above - - // EINVAL is what the kernel says for unsigned code, so we'll have to let that pass - if (entitlementErrno == EINVAL) { - task->entitlementsLoaded = true; - return true; - } - ret = entitlementErrno; // what really went wrong - goto out; // bail out - } + // EINVAL is what the kernel says for unsigned code, so we'll have to let that pass + if (entitlementErrno == EINVAL) { + task->entitlementsLoaded = true; + return true; + } + ret = entitlementErrno; // what really went wrong + goto out; // bail out + } bufferlen = ntohl(header.length); /* check for insane values */ if (bufferlen > 1024 * 1024 || bufferlen < 8) { @@ -298,10 +297,17 @@ static bool SecTaskLoadEntitlements(SecTaskRef task, CFErrorRef *error) entitlements = (CFMutableDictionaryRef) CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListMutableContainers, NULL, error); CFReleaseNull(data); - if((entitlements==NULL) || (CFGetTypeID(entitlements)!=CFDictionaryGetTypeID())){ + if ((entitlements==NULL) || (CFGetTypeID(entitlements)!=CFDictionaryGetTypeID())){ ret = EDOM; // don't use EINVAL here; it conflates problems with syscall error returns goto out; } + + bool entitlementsModified = updateCatalystEntitlements(entitlements); + if (entitlementsModified) { + pid_t pid; + audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL); + secinfo("SecTask", "Fixed catalyst entitlements for process %d", pid); + } } task->entitlements = entitlements ? CFRetain(entitlements) : NULL; diff --git a/sectask/SecTask.h b/sectask/SecTask.h index c1bf28a0..5a14de3c 100644 --- a/sectask/SecTask.h +++ b/sectask/SecTask.h @@ -127,7 +127,7 @@ CFStringRef SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error); */ uint32_t SecTaskGetCodeSignStatus(SecTaskRef task) - API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0), iosmac(11.0)) SPI_AVAILABLE(macos(10.5)); + API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0), macCatalyst(11.0)) SPI_AVAILABLE(macos(10.5)); CF_IMPLICIT_BRIDGING_DISABLED diff --git a/sectask/SystemEntitlements.h b/sectask/SystemEntitlements.h new file mode 100644 index 00000000..c8544290 --- /dev/null +++ b/sectask/SystemEntitlements.h @@ -0,0 +1,17 @@ +#ifndef SystemEntitlements_h +#define SystemEntitlements_h + +/* + This file collects entitlements defined on the platform and in use by Security. + */ + +#include + +__BEGIN_DECLS + +/* Entitlement denoting client task is an App Clip */ +#define kSystemEntitlementOnDemandInstallCapable CFSTR("com.apple.developer.on-demand-install-capable") + +__END_DECLS + +#endif /* SystemEntitlements_h */ diff --git a/security-sysdiagnose/security-sysdiagnose.entitlements.plist b/security-sysdiagnose/security-sysdiagnose.entitlements.plist index 2b46d229..7ea60bb9 100644 --- a/security-sysdiagnose/security-sysdiagnose.entitlements.plist +++ b/security-sysdiagnose/security-sysdiagnose.entitlements.plist @@ -9,6 +9,7 @@ com.apple.hap.pairing com.apple.hap.metadata com.apple.continuity.unlock + com.apple.rapport keychain-cloud-circle diff --git a/security-sysdiagnose/security-sysdiagnose.m b/security-sysdiagnose/security-sysdiagnose.m index 23ffdc0c..7d84f24e 100644 --- a/security-sysdiagnose/security-sysdiagnose.m +++ b/security-sysdiagnose/security-sysdiagnose.m @@ -76,9 +76,11 @@ static NSString *dictionaryToString(NSDictionary *dict) { NSMutableString *result = [NSMutableString stringWithCapacity:0]; - [dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { - [result appendFormat:@"%@=%@,", key, obj]; - }]; + + NSArray* keys = [[dict allKeys] sortedArrayUsingSelector:@selector(compare:)]; + for(NSString* key in keys) { + [result appendFormat:@"%@=%@,", key, dict[key]]; + } return [result substringToIndex:result.length-(result.length>0)]; } @@ -197,6 +199,29 @@ unlock_sysdiagnose(void) CFReleaseNull(result); } +static void +rapport_sysdiagnose(void) +{ + NSString *kAccessGroupRapport = @"com.apple.rapport"; + + [@"Rapport keychain state:\n" writeToStdOut]; + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : kAccessGroupRapport, + (id)kSecAttrSynchronizable: (id)kCFBooleanTrue, + (id)kSecMatchLimit : (id)kSecMatchLimitAll, + (id)kSecReturnAttributes: @YES, + (id)kSecReturnData: @NO, + }; + + CFTypeRef result = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &result); + if (status == noErr) { + printSecItems(@"rapport", result); + } + CFReleaseNull(result); +} static void analytics_sysdiagnose(void) @@ -241,6 +266,7 @@ main(int argc, const char ** argv) engine_sysdiagnose(); homekit_sysdiagnose(); unlock_sysdiagnose(); + rapport_sysdiagnose(); analytics_sysdiagnose(); // Keep this one last diff --git a/securityd/dtrace/securityd-watch.d b/securityd/dtrace/securityd-watch.d old mode 100644 new mode 100755 diff --git a/securityd/etc/com.apple.securityd.sb b/securityd/etc/com.apple.securityd.sb index c59ca4d2..1045cdb8 100644 --- a/securityd/etc/com.apple.securityd.sb +++ b/securityd/etc/com.apple.securityd.sb @@ -49,7 +49,9 @@ (global-name "com.apple.ocspd") (global-name "com.apple.PowerManagement.control") (global-name "com.apple.security.syspolicy") - (global-name "com.apple.security.agent")) + (global-name "com.apple.security.agent") + (global-name "com.apple.security.agent.login") + (global-name "com.apple.security.KeychainStasher")) (allow ipc-posix-shm (ipc-posix-name "com.apple.AppleDatabaseChanged") diff --git a/securityd/mig/self.defs b/securityd/mig/self.defs index b2e8f87c..5e61f7d8 100644 --- a/securityd/mig/self.defs +++ b/securityd/mig/self.defs @@ -36,8 +36,13 @@ userprefix self_client_; // Sent to ourselves upon receipt of a signal (so we get out from under // the dreaded "can't do anything useful in a signal handler" problem). // -simpleroutine handleSignal(requestport sport: mach_port_make_send_once_t; - in task_port: mach_port_t; in signal_number: int); +simpleroutine handleSignal( + requestport sport: mach_port_make_send_once_t; + ServerAuditToken token: audit_token_t; + in signal_number: int); -simpleroutine handleSession(requestport sport: mach_port_make_send_once_t; - in task_port: mach_port_t; in events: uint32_t; in ident: uint64_t); +simpleroutine handleSession( + requestport sport: mach_port_make_send_once_t; + ServerAuditToken token: audit_token_t; + in events: uint32_t; + in ident: uint64_t); diff --git a/securityd/securityd_dtrace.h b/securityd/securityd_dtrace.h deleted file mode 100644 index f1f221f7..00000000 --- a/securityd/securityd_dtrace.h +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Generated by dtrace(1M). - */ - -#ifndef _SECURITYD_DTRACE_H -#define _SECURITYD_DTRACE_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define SECURITYD_STABILITY "___dtrace_stability$securityd$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0" - -#define SECURITYD_TYPEDEFS "___dtrace_typedefs$securityd$v2$626f6f6c$4454506f7274$44544775657374$445448616e646c65" - -#if !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED - -#define SECURITYD_AUTH_ALLOW(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__allow$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_ALLOW_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__allow$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_CREATE(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__create$v1$445448616e646c65$766f6964202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_CREATE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__create$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_DENY(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__deny$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_DENY_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__deny$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_EVALRIGHT(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__evalright$v1$445448616e646c65$63686172202a$696e7433325f74(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_EVALRIGHT_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__evalright$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_KOFN(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__kofn$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_KOFN_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__kofn$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_MECH(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__mech$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_MECH_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__mech$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_MECHRULE(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__mechrule$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_MECHRULE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__mechrule$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_RULES(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__rules$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_RULES_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__rules$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_USER(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__user$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_USER_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__user$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_USER_ALLOWROOT(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__user__allowroot$v1$445448616e646c65(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_USER_ALLOWROOT_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__user__allowroot$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_AUTH_USER_ALLOWSESSIONOWNER(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$auth__user__allowsessionowner$v1$445448616e646c65(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_AUTH_USER_ALLOWSESSIONOWNER_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$auth__user__allowsessionowner$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CHILD_CHECKIN(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$child__checkin$v1$696e74$4454506f7274(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CHILD_CHECKIN_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$child__checkin$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CHILD_DYING(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$child__dying$v1$696e74(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CHILD_DYING_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$child__dying$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CHILD_READY(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$child__ready$v1$696e74(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CHILD_READY_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$child__ready$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CHILD_STILLBORN(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$child__stillborn$v1$696e74(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CHILD_STILLBORN_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$child__stillborn$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CLIENT_CHANGE_SESSION(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$client__change_session$v1$445448616e646c65$445448616e646c65(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CLIENT_CHANGE_SESSION_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$client__change_session$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CLIENT_CONNECTION_NEW(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$client__connection__new$v1$445448616e646c65$4454506f7274$445448616e646c65(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CLIENT_CONNECTION_NEW_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$client__connection__new$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CLIENT_CONNECTION_RELEASE(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$client__connection__release$v1$445448616e646c65(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CLIENT_CONNECTION_RELEASE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$client__connection__release$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CLIENT_NEW(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$client__new$v1$445448616e646c65$696e74$445448616e646c65$63686172202a$4454506f7274$696e74$696e74$626f6f6c(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CLIENT_NEW_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$client__new$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CLIENT_RELEASE(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$client__release$v1$445448616e646c65$696e74(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CLIENT_RELEASE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$client__release$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CLIENT_RESET_AMNESIA(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$client__reset__amnesia$v1$445448616e646c65(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CLIENT_RESET_AMNESIA_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$client__reset__amnesia$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_CLIENT_RESET_FULL(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$client__reset__full$v1$445448616e646c65(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_CLIENT_RESET_FULL_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$client__reset__full$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_ENTROPY_COLLECT() \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$entropy__collect$v1(); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_ENTROPY_COLLECT_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$entropy__collect$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_ENTROPY_SAVE(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$entropy__save$v1$63686172202a(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_ENTROPY_SAVE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$entropy__save$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_ENTROPY_SEED(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$entropy__seed$v1$766f6964202a$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_ENTROPY_SEED_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$entropy__seed$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_GUEST_CDHASH(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$guest__cdhash$v1$445448616e646c65$44544775657374$766f6964202a$756e7369676e6564(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_GUEST_CDHASH_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$guest__cdhash$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_GUEST_CHANGE(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$guest__change$v1$445448616e646c65$44544775657374$756e7369676e6564(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_GUEST_CHANGE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$guest__change$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_GUEST_CREATE(arg0, arg1, arg2, arg3, arg4, arg5) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$guest__create$v1$445448616e646c65$44544775657374$44544775657374$756e7369676e6564$756e7369676e6564$63686172202a(arg0, arg1, arg2, arg3, arg4, arg5); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_GUEST_CREATE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$guest__create$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_GUEST_DESTROY(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$guest__destroy$v1$445448616e646c65$44544775657374(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_GUEST_DESTROY_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$guest__destroy$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_HOST_PROXY(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$host__proxy$v1$445448616e646c65$4454506f7274(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_HOST_PROXY_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$host__proxy$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_HOST_REGISTER(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$host__register$v1$445448616e646c65$4454506f7274(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_HOST_REGISTER_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$host__register$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_HOST_UNREGISTER(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$host__unregister$v1$445448616e646c65(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_HOST_UNREGISTER_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$host__unregister$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_INITIALIZED(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$initialized$v1$63686172202a(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_INITIALIZED_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$initialized$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_INSTALLMODE() \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$installmode$v1(); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_INSTALLMODE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$installmode$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_KEYCHAIN_CREATE(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$keychain__create$v1$445448616e646c65$63686172202a$445448616e646c65(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_KEYCHAIN_CREATE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$keychain__create$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_KEYCHAIN_JOIN(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$keychain__join$v1$445448616e646c65$63686172202a$445448616e646c65(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_KEYCHAIN_JOIN_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$keychain__join$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_KEYCHAIN_LOCK(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$keychain__lock$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_KEYCHAIN_LOCK_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$keychain__lock$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_KEYCHAIN_MAKE(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$keychain__make$v1$445448616e646c65$63686172202a$445448616e646c65(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_KEYCHAIN_MAKE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$keychain__make$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_KEYCHAIN_RELEASE(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$keychain__release$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_KEYCHAIN_RELEASE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$keychain__release$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_KEYCHAIN_UNLOCK(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$keychain__unlock$v1$445448616e646c65$63686172202a(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_KEYCHAIN_UNLOCK_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$keychain__unlock$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_PORTS_DEAD_CONNECTION(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$ports__dead__connection$v1$4454506f7274(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_PORTS_DEAD_CONNECTION_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$ports__dead__connection$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_PORTS_DEAD_ORPHAN(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$ports__dead__orphan$v1$4454506f7274(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_PORTS_DEAD_ORPHAN_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$ports__dead__orphan$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_PORTS_DEAD_PROCESS(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$ports__dead__process$v1$4454506f7274(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_PORTS_DEAD_PROCESS_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$ports__dead__process$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_PORTS_DEAD_SESSION(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$ports__dead__session$v1$4454506f7274(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_PORTS_DEAD_SESSION_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$ports__dead__session$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_POWER_ON() \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$power__on$v1(); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_POWER_ON_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$power__on$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_POWER_SLEEP() \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$power__sleep$v1(); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_POWER_SLEEP_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$power__sleep$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_POWER_WAKE() \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$power__wake$v1(); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_POWER_WAKE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$power__wake$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_REQUEST_ENTRY(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$request__entry$v1$63686172202a$445448616e646c65$445448616e646c65(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_REQUEST_ENTRY_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$request__entry$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_REQUEST_RETURN(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$request__return$v1$756e7369676e6564(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_REQUEST_RETURN_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$request__return$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_SESSION_CREATE(arg0, arg1, arg2, arg3) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$session__create$v1$445448616e646c65$756e7369676e6564$766f6964202a$756e7369676e6564(arg0, arg1, arg2, arg3); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_SESSION_CREATE_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$session__create$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_SESSION_DESTROY(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$session__destroy$v1$445448616e646c65$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_SESSION_DESTROY_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$session__destroy$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_SESSION_KILL(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$session__kill$v1$445448616e646c65$756e7369676e6564(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_SESSION_KILL_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$session__kill$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_SESSION_NOTIFY(arg0, arg1, arg2) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$session__notify$v1$75696e7436345f74$756e7369676e6564$696e74(arg0, arg1, arg2); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_SESSION_NOTIFY_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$session__notify$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_SHUTDOWN_BEGIN() \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$shutdown__begin$v1(); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_SHUTDOWN_BEGIN_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$shutdown__begin$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_SHUTDOWN_COUNT(arg0, arg1) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$shutdown__count$v1$696e74$696e74(arg0, arg1); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_SHUTDOWN_COUNT_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$shutdown__count$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_SHUTDOWN_NOW() \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$shutdown__now$v1(); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_SHUTDOWN_NOW_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$shutdown__now$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_SIGNAL_HANDLED(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$signal__handled$v1$696e74(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_SIGNAL_HANDLED_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$signal__handled$v1(); \ - __asm__ volatile(""); \ - _r; }) -#define SECURITYD_SIGNAL_RECEIVED(arg0) \ -do { \ - __asm__ volatile(".reference " SECURITYD_TYPEDEFS); \ - __dtrace_probe$securityd$signal__received$v1$696e74(arg0); \ - __asm__ volatile(".reference " SECURITYD_STABILITY); \ -} while (0) -#define SECURITYD_SIGNAL_RECEIVED_ENABLED() \ - ({ int _r = __dtrace_isenabled$securityd$signal__received$v1(); \ - __asm__ volatile(""); \ - _r; }) - - -extern void __dtrace_probe$securityd$auth__allow$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$auth__allow$v1(void); -extern void __dtrace_probe$securityd$auth__create$v1$445448616e646c65$766f6964202a(DTHandle, const void *); -extern int __dtrace_isenabled$securityd$auth__create$v1(void); -extern void __dtrace_probe$securityd$auth__deny$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$auth__deny$v1(void); -extern void __dtrace_probe$securityd$auth__evalright$v1$445448616e646c65$63686172202a$696e7433325f74(DTHandle, const char *, int32_t); -extern int __dtrace_isenabled$securityd$auth__evalright$v1(void); -extern void __dtrace_probe$securityd$auth__kofn$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$auth__kofn$v1(void); -extern void __dtrace_probe$securityd$auth__mech$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$auth__mech$v1(void); -extern void __dtrace_probe$securityd$auth__mechrule$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$auth__mechrule$v1(void); -extern void __dtrace_probe$securityd$auth__rules$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$auth__rules$v1(void); -extern void __dtrace_probe$securityd$auth__user$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$auth__user$v1(void); -extern void __dtrace_probe$securityd$auth__user__allowroot$v1$445448616e646c65(DTHandle); -extern int __dtrace_isenabled$securityd$auth__user__allowroot$v1(void); -extern void __dtrace_probe$securityd$auth__user__allowsessionowner$v1$445448616e646c65(DTHandle); -extern int __dtrace_isenabled$securityd$auth__user__allowsessionowner$v1(void); -extern void __dtrace_probe$securityd$child__checkin$v1$696e74$4454506f7274(int, DTPort); -extern int __dtrace_isenabled$securityd$child__checkin$v1(void); -extern void __dtrace_probe$securityd$child__dying$v1$696e74(int); -extern int __dtrace_isenabled$securityd$child__dying$v1(void); -extern void __dtrace_probe$securityd$child__ready$v1$696e74(int); -extern int __dtrace_isenabled$securityd$child__ready$v1(void); -extern void __dtrace_probe$securityd$child__stillborn$v1$696e74(int); -extern int __dtrace_isenabled$securityd$child__stillborn$v1(void); -extern void __dtrace_probe$securityd$client__change_session$v1$445448616e646c65$445448616e646c65(DTHandle, DTHandle); -extern int __dtrace_isenabled$securityd$client__change_session$v1(void); -extern void __dtrace_probe$securityd$client__connection__new$v1$445448616e646c65$4454506f7274$445448616e646c65(DTHandle, DTPort, DTHandle); -extern int __dtrace_isenabled$securityd$client__connection__new$v1(void); -extern void __dtrace_probe$securityd$client__connection__release$v1$445448616e646c65(DTHandle); -extern int __dtrace_isenabled$securityd$client__connection__release$v1(void); -extern void __dtrace_probe$securityd$client__new$v1$445448616e646c65$696e74$445448616e646c65$63686172202a$4454506f7274$696e74$696e74$626f6f6c(DTHandle, int, DTHandle, const char *, DTPort, int, int, bool); -extern int __dtrace_isenabled$securityd$client__new$v1(void); -extern void __dtrace_probe$securityd$client__release$v1$445448616e646c65$696e74(DTHandle, int); -extern int __dtrace_isenabled$securityd$client__release$v1(void); -extern void __dtrace_probe$securityd$client__reset__amnesia$v1$445448616e646c65(DTHandle); -extern int __dtrace_isenabled$securityd$client__reset__amnesia$v1(void); -extern void __dtrace_probe$securityd$client__reset__full$v1$445448616e646c65(DTHandle); -extern int __dtrace_isenabled$securityd$client__reset__full$v1(void); -extern void __dtrace_probe$securityd$entropy__collect$v1(void); -extern int __dtrace_isenabled$securityd$entropy__collect$v1(void); -extern void __dtrace_probe$securityd$entropy__save$v1$63686172202a(const char *); -extern int __dtrace_isenabled$securityd$entropy__save$v1(void); -extern void __dtrace_probe$securityd$entropy__seed$v1$766f6964202a$756e7369676e6564(const void *, unsigned); -extern int __dtrace_isenabled$securityd$entropy__seed$v1(void); -extern void __dtrace_probe$securityd$guest__cdhash$v1$445448616e646c65$44544775657374$766f6964202a$756e7369676e6564(DTHandle, DTGuest, const void *, unsigned); -extern int __dtrace_isenabled$securityd$guest__cdhash$v1(void); -extern void __dtrace_probe$securityd$guest__change$v1$445448616e646c65$44544775657374$756e7369676e6564(DTHandle, DTGuest, unsigned); -extern int __dtrace_isenabled$securityd$guest__change$v1(void); -extern void __dtrace_probe$securityd$guest__create$v1$445448616e646c65$44544775657374$44544775657374$756e7369676e6564$756e7369676e6564$63686172202a(DTHandle, DTGuest, DTGuest, unsigned, unsigned, const char *); -extern int __dtrace_isenabled$securityd$guest__create$v1(void); -extern void __dtrace_probe$securityd$guest__destroy$v1$445448616e646c65$44544775657374(DTHandle, DTGuest); -extern int __dtrace_isenabled$securityd$guest__destroy$v1(void); -extern void __dtrace_probe$securityd$host__proxy$v1$445448616e646c65$4454506f7274(DTHandle, DTPort); -extern int __dtrace_isenabled$securityd$host__proxy$v1(void); -extern void __dtrace_probe$securityd$host__register$v1$445448616e646c65$4454506f7274(DTHandle, DTPort); -extern int __dtrace_isenabled$securityd$host__register$v1(void); -extern void __dtrace_probe$securityd$host__unregister$v1$445448616e646c65(DTHandle); -extern int __dtrace_isenabled$securityd$host__unregister$v1(void); -extern void __dtrace_probe$securityd$initialized$v1$63686172202a(const char *); -extern int __dtrace_isenabled$securityd$initialized$v1(void); -extern void __dtrace_probe$securityd$installmode$v1(void); -extern int __dtrace_isenabled$securityd$installmode$v1(void); -extern void __dtrace_probe$securityd$keychain__create$v1$445448616e646c65$63686172202a$445448616e646c65(DTHandle, const char *, DTHandle); -extern int __dtrace_isenabled$securityd$keychain__create$v1(void); -extern void __dtrace_probe$securityd$keychain__join$v1$445448616e646c65$63686172202a$445448616e646c65(DTHandle, const char *, DTHandle); -extern int __dtrace_isenabled$securityd$keychain__join$v1(void); -extern void __dtrace_probe$securityd$keychain__lock$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$keychain__lock$v1(void); -extern void __dtrace_probe$securityd$keychain__make$v1$445448616e646c65$63686172202a$445448616e646c65(DTHandle, const char *, DTHandle); -extern int __dtrace_isenabled$securityd$keychain__make$v1(void); -extern void __dtrace_probe$securityd$keychain__release$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$keychain__release$v1(void); -extern void __dtrace_probe$securityd$keychain__unlock$v1$445448616e646c65$63686172202a(DTHandle, const char *); -extern int __dtrace_isenabled$securityd$keychain__unlock$v1(void); -extern void __dtrace_probe$securityd$ports__dead__connection$v1$4454506f7274(DTPort); -extern int __dtrace_isenabled$securityd$ports__dead__connection$v1(void); -extern void __dtrace_probe$securityd$ports__dead__orphan$v1$4454506f7274(DTPort); -extern int __dtrace_isenabled$securityd$ports__dead__orphan$v1(void); -extern void __dtrace_probe$securityd$ports__dead__process$v1$4454506f7274(DTPort); -extern int __dtrace_isenabled$securityd$ports__dead__process$v1(void); -extern void __dtrace_probe$securityd$ports__dead__session$v1$4454506f7274(DTPort); -extern int __dtrace_isenabled$securityd$ports__dead__session$v1(void); -extern void __dtrace_probe$securityd$power__on$v1(void); -extern int __dtrace_isenabled$securityd$power__on$v1(void); -extern void __dtrace_probe$securityd$power__sleep$v1(void); -extern int __dtrace_isenabled$securityd$power__sleep$v1(void); -extern void __dtrace_probe$securityd$power__wake$v1(void); -extern int __dtrace_isenabled$securityd$power__wake$v1(void); -extern void __dtrace_probe$securityd$request__entry$v1$63686172202a$445448616e646c65$445448616e646c65(const char *, DTHandle, DTHandle); -extern int __dtrace_isenabled$securityd$request__entry$v1(void); -extern void __dtrace_probe$securityd$request__return$v1$756e7369676e6564(unsigned); -extern int __dtrace_isenabled$securityd$request__return$v1(void); -extern void __dtrace_probe$securityd$session__create$v1$445448616e646c65$756e7369676e6564$766f6964202a$756e7369676e6564(DTHandle, unsigned, const void *, unsigned); -extern int __dtrace_isenabled$securityd$session__create$v1(void); -extern void __dtrace_probe$securityd$session__destroy$v1$445448616e646c65$756e7369676e6564(DTHandle, unsigned); -extern int __dtrace_isenabled$securityd$session__destroy$v1(void); -extern void __dtrace_probe$securityd$session__kill$v1$445448616e646c65$756e7369676e6564(DTHandle, unsigned); -extern int __dtrace_isenabled$securityd$session__kill$v1(void); -extern void __dtrace_probe$securityd$session__notify$v1$75696e7436345f74$756e7369676e6564$696e74(uint64_t, unsigned, int); -extern int __dtrace_isenabled$securityd$session__notify$v1(void); -extern void __dtrace_probe$securityd$shutdown__begin$v1(void); -extern int __dtrace_isenabled$securityd$shutdown__begin$v1(void); -extern void __dtrace_probe$securityd$shutdown__count$v1$696e74$696e74(int, int); -extern int __dtrace_isenabled$securityd$shutdown__count$v1(void); -extern void __dtrace_probe$securityd$shutdown__now$v1(void); -extern int __dtrace_isenabled$securityd$shutdown__now$v1(void); -extern void __dtrace_probe$securityd$signal__handled$v1$696e74(int); -extern int __dtrace_isenabled$securityd$signal__handled$v1(void); -extern void __dtrace_probe$securityd$signal__received$v1$696e74(int); -extern int __dtrace_isenabled$securityd$signal__received$v1(void); - -#else - -#define SECURITYD_AUTH_ALLOW(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_AUTH_ALLOW_ENABLED() (0) -#define SECURITYD_AUTH_CREATE(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_AUTH_CREATE_ENABLED() (0) -#define SECURITYD_AUTH_DENY(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_AUTH_DENY_ENABLED() (0) -#define SECURITYD_AUTH_EVALRIGHT(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITYD_AUTH_EVALRIGHT_ENABLED() (0) -#define SECURITYD_AUTH_KOFN(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_AUTH_KOFN_ENABLED() (0) -#define SECURITYD_AUTH_MECH(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_AUTH_MECH_ENABLED() (0) -#define SECURITYD_AUTH_MECHRULE(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_AUTH_MECHRULE_ENABLED() (0) -#define SECURITYD_AUTH_RULES(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_AUTH_RULES_ENABLED() (0) -#define SECURITYD_AUTH_USER(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_AUTH_USER_ENABLED() (0) -#define SECURITYD_AUTH_USER_ALLOWROOT(arg0) \ -do { \ - } while (0) -#define SECURITYD_AUTH_USER_ALLOWROOT_ENABLED() (0) -#define SECURITYD_AUTH_USER_ALLOWSESSIONOWNER(arg0) \ -do { \ - } while (0) -#define SECURITYD_AUTH_USER_ALLOWSESSIONOWNER_ENABLED() (0) -#define SECURITYD_CHILD_CHECKIN(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_CHILD_CHECKIN_ENABLED() (0) -#define SECURITYD_CHILD_DYING(arg0) \ -do { \ - } while (0) -#define SECURITYD_CHILD_DYING_ENABLED() (0) -#define SECURITYD_CHILD_READY(arg0) \ -do { \ - } while (0) -#define SECURITYD_CHILD_READY_ENABLED() (0) -#define SECURITYD_CHILD_STILLBORN(arg0) \ -do { \ - } while (0) -#define SECURITYD_CHILD_STILLBORN_ENABLED() (0) -#define SECURITYD_CLIENT_CHANGE_SESSION(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_CLIENT_CHANGE_SESSION_ENABLED() (0) -#define SECURITYD_CLIENT_CONNECTION_NEW(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITYD_CLIENT_CONNECTION_NEW_ENABLED() (0) -#define SECURITYD_CLIENT_CONNECTION_RELEASE(arg0) \ -do { \ - } while (0) -#define SECURITYD_CLIENT_CONNECTION_RELEASE_ENABLED() (0) -#define SECURITYD_CLIENT_NEW(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ -do { \ - } while (0) -#define SECURITYD_CLIENT_NEW_ENABLED() (0) -#define SECURITYD_CLIENT_RELEASE(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_CLIENT_RELEASE_ENABLED() (0) -#define SECURITYD_CLIENT_RESET_AMNESIA(arg0) \ -do { \ - } while (0) -#define SECURITYD_CLIENT_RESET_AMNESIA_ENABLED() (0) -#define SECURITYD_CLIENT_RESET_FULL(arg0) \ -do { \ - } while (0) -#define SECURITYD_CLIENT_RESET_FULL_ENABLED() (0) -#define SECURITYD_ENTROPY_COLLECT() \ -do { \ - } while (0) -#define SECURITYD_ENTROPY_COLLECT_ENABLED() (0) -#define SECURITYD_ENTROPY_SAVE(arg0) \ -do { \ - } while (0) -#define SECURITYD_ENTROPY_SAVE_ENABLED() (0) -#define SECURITYD_ENTROPY_SEED(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_ENTROPY_SEED_ENABLED() (0) -#define SECURITYD_GUEST_CDHASH(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define SECURITYD_GUEST_CDHASH_ENABLED() (0) -#define SECURITYD_GUEST_CHANGE(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITYD_GUEST_CHANGE_ENABLED() (0) -#define SECURITYD_GUEST_CREATE(arg0, arg1, arg2, arg3, arg4, arg5) \ -do { \ - } while (0) -#define SECURITYD_GUEST_CREATE_ENABLED() (0) -#define SECURITYD_GUEST_DESTROY(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_GUEST_DESTROY_ENABLED() (0) -#define SECURITYD_HOST_PROXY(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_HOST_PROXY_ENABLED() (0) -#define SECURITYD_HOST_REGISTER(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_HOST_REGISTER_ENABLED() (0) -#define SECURITYD_HOST_UNREGISTER(arg0) \ -do { \ - } while (0) -#define SECURITYD_HOST_UNREGISTER_ENABLED() (0) -#define SECURITYD_INITIALIZED(arg0) \ -do { \ - } while (0) -#define SECURITYD_INITIALIZED_ENABLED() (0) -#define SECURITYD_INSTALLMODE() \ -do { \ - } while (0) -#define SECURITYD_INSTALLMODE_ENABLED() (0) -#define SECURITYD_KEYCHAIN_CREATE(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITYD_KEYCHAIN_CREATE_ENABLED() (0) -#define SECURITYD_KEYCHAIN_JOIN(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITYD_KEYCHAIN_JOIN_ENABLED() (0) -#define SECURITYD_KEYCHAIN_LOCK(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_KEYCHAIN_LOCK_ENABLED() (0) -#define SECURITYD_KEYCHAIN_MAKE(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITYD_KEYCHAIN_MAKE_ENABLED() (0) -#define SECURITYD_KEYCHAIN_RELEASE(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_KEYCHAIN_RELEASE_ENABLED() (0) -#define SECURITYD_KEYCHAIN_UNLOCK(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_KEYCHAIN_UNLOCK_ENABLED() (0) -#define SECURITYD_PORTS_DEAD_CONNECTION(arg0) \ -do { \ - } while (0) -#define SECURITYD_PORTS_DEAD_CONNECTION_ENABLED() (0) -#define SECURITYD_PORTS_DEAD_ORPHAN(arg0) \ -do { \ - } while (0) -#define SECURITYD_PORTS_DEAD_ORPHAN_ENABLED() (0) -#define SECURITYD_PORTS_DEAD_PROCESS(arg0) \ -do { \ - } while (0) -#define SECURITYD_PORTS_DEAD_PROCESS_ENABLED() (0) -#define SECURITYD_PORTS_DEAD_SESSION(arg0) \ -do { \ - } while (0) -#define SECURITYD_PORTS_DEAD_SESSION_ENABLED() (0) -#define SECURITYD_POWER_ON() \ -do { \ - } while (0) -#define SECURITYD_POWER_ON_ENABLED() (0) -#define SECURITYD_POWER_SLEEP() \ -do { \ - } while (0) -#define SECURITYD_POWER_SLEEP_ENABLED() (0) -#define SECURITYD_POWER_WAKE() \ -do { \ - } while (0) -#define SECURITYD_POWER_WAKE_ENABLED() (0) -#define SECURITYD_REQUEST_ENTRY(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITYD_REQUEST_ENTRY_ENABLED() (0) -#define SECURITYD_REQUEST_RETURN(arg0) \ -do { \ - } while (0) -#define SECURITYD_REQUEST_RETURN_ENABLED() (0) -#define SECURITYD_SESSION_CREATE(arg0, arg1, arg2, arg3) \ -do { \ - } while (0) -#define SECURITYD_SESSION_CREATE_ENABLED() (0) -#define SECURITYD_SESSION_DESTROY(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_SESSION_DESTROY_ENABLED() (0) -#define SECURITYD_SESSION_KILL(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_SESSION_KILL_ENABLED() (0) -#define SECURITYD_SESSION_NOTIFY(arg0, arg1, arg2) \ -do { \ - } while (0) -#define SECURITYD_SESSION_NOTIFY_ENABLED() (0) -#define SECURITYD_SHUTDOWN_BEGIN() \ -do { \ - } while (0) -#define SECURITYD_SHUTDOWN_BEGIN_ENABLED() (0) -#define SECURITYD_SHUTDOWN_COUNT(arg0, arg1) \ -do { \ - } while (0) -#define SECURITYD_SHUTDOWN_COUNT_ENABLED() (0) -#define SECURITYD_SHUTDOWN_NOW() \ -do { \ - } while (0) -#define SECURITYD_SHUTDOWN_NOW_ENABLED() (0) -#define SECURITYD_SIGNAL_HANDLED(arg0) \ -do { \ - } while (0) -#define SECURITYD_SIGNAL_HANDLED_ENABLED() (0) -#define SECURITYD_SIGNAL_RECEIVED(arg0) \ -do { \ - } while (0) -#define SECURITYD_SIGNAL_RECEIVED_ENABLED() (0) - -#endif /* !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _SECURITYD_DTRACE_H */ diff --git a/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj b/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj index ad6cc5e7..4d89a2bc 100644 --- a/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj +++ b/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj @@ -347,7 +347,7 @@ 189D462D166AC95C001D8533 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1000; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = Apple; }; buildConfigurationList = 189D4630166AC95C001D8533 /* Build configuration list for PBXProject "securityd_service" */; @@ -355,6 +355,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 189D462C166AC95C001D8533; @@ -432,7 +433,7 @@ 1843240F1714797D00196B52 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++2a"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -440,7 +441,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; COMBINE_HIDPI_IMAGES = YES; EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu2x; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -454,7 +455,7 @@ 184324101714797D00196B52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++2a"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -463,7 +464,7 @@ COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu2x; GCC_WARN_UNDECLARED_SELECTOR = YES; INSTALL_PATH = /usr/local/lib; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -475,6 +476,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPRESSION = lossless; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -532,6 +534,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -616,14 +619,14 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = /usr/libexec/UserEventAgent; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++2a"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu2x; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -641,7 +644,7 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = /usr/libexec/UserEventAgent; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++2a"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -649,7 +652,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu2x; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; diff --git a/securityd/securityd_service/securityd_service/main.c b/securityd/securityd_service/securityd_service/main.c index 496e3a05..be7d6e0e 100644 --- a/securityd/securityd_service/securityd_service/main.c +++ b/securityd/securityd_service/securityd_service/main.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -1356,9 +1356,7 @@ bool check_signature(xpc_connection_t connection) { #if !(DEBUG || RC_BUILDIT_YES) audit_token_t token; - xpc_connection_get_audit_token(connection, &token); - SecTaskRef task = SecTaskCreateWithAuditToken(NULL, token); if (task == NULL) { os_log(OS_LOG_DEFAULT, "failed getting SecTaskRef of the client"); @@ -1368,7 +1366,6 @@ bool check_signature(xpc_connection_t connection) uint32_t flags = SecTaskGetCodeSignStatus(task); /* check if valid and platform binary, but not platform path */ - if ((flags & (CS_VALID | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) != (CS_VALID | CS_PLATFORM_BINARY)) { if (SecIsInternalRelease()) { if ((flags & (CS_DEBUGGED | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) != (CS_DEBUGGED | CS_PLATFORM_BINARY)) { @@ -1383,18 +1380,19 @@ bool check_signature(xpc_connection_t connection) } } - CFStringRef signingIdentity = SecTaskCopySigningIdentifier(task, NULL); + CFStringRef signingIdentifier = SecTaskCopySigningIdentifier(task, NULL); CFRelease(task); - if (signingIdentity == NULL) { - os_log(OS_LOG_DEFAULT, "client have no code sign identity"); + if (signingIdentifier == NULL) { + os_log(OS_LOG_DEFAULT, "client has no code signing identifier"); return false; } - bool res = CFEqual(signingIdentity, CFSTR("com.apple.securityd")); - CFRelease(signingIdentity); + bool res = CFEqual(signingIdentifier, CFSTR("com.apple.securityd")); + CFRelease(signingIdentifier); - if (!res) - os_log(OS_LOG_DEFAULT, "client is not not securityd"); + if (!res) { + os_log(OS_LOG_DEFAULT, "client is not securityd"); + } return res; #else diff --git a/securityd/securityd_service/securityd_service/securityd_service_client.c b/securityd/securityd_service/securityd_service/securityd_service_client.c index fa8f8a10..ab0c1b1c 100644 --- a/securityd/securityd_service/securityd_service/securityd_service_client.c +++ b/securityd/securityd_service/securityd_service/securityd_service_client.c @@ -325,7 +325,7 @@ done: } int -service_client_stash_get_key(service_context_t *context, void ** key, int * key_len) +service_client_stash_get_key(service_context_t *context, void ** key, size_t * key_len) { int rc = KB_GeneralError; xpc_object_t message = NULL; @@ -347,7 +347,7 @@ service_client_stash_get_key(service_context_t *context, void ** key, int * key_ if (data) { *key = calloc(1u, data_len); memcpy(*key, data, data_len); - *key_len = (int)data_len; + *key_len = data_len; } } diff --git a/securityd/securityd_service/securityd_service/securityd_service_client.h b/securityd/securityd_service/securityd_service/securityd_service_client.h index 293216fc..bd8f8c4d 100644 --- a/securityd/securityd_service/securityd_service/securityd_service_client.h +++ b/securityd/securityd_service/securityd_service/securityd_service_client.h @@ -44,7 +44,7 @@ int service_client_kb_unwrap_key(service_context_t *context, const void *wrapped int service_client_stash_set_key(service_context_t *context, const void * key, int key_len); int service_client_stash_load_key(service_context_t *context, const void * key, int key_len); -int service_client_stash_get_key(service_context_t *context, void ** key, int * key_len); +int service_client_stash_get_key(service_context_t *context, void ** key, size_t * key_len); #if defined(__cplusplus) } diff --git a/securityd/src/auditevents.cpp b/securityd/src/auditevents.cpp index 9cedad36..9688cd08 100644 --- a/securityd/src/auditevents.cpp +++ b/securityd/src/auditevents.cpp @@ -25,6 +25,7 @@ // // auditevents - monitor and act upon audit subsystem events // +#include #include "auditevents.h" #include "dtrace.h" #include @@ -35,7 +36,7 @@ using namespace MachPlusPlus; AuditMonitor::AuditMonitor(Port relay) - : mRelay(relay) + : Thread("AuditMonitor"), mRelay(relay) { } @@ -49,24 +50,31 @@ AuditMonitor::~AuditMonitor() // (The current version of MachServer cannot receive FileDesc-based events, // so we need a monitor thread for this.) // -void AuditMonitor::action() +void AuditMonitor::threadAction() { - au_sdev_handle_t *dev = au_sdev_open(AU_SDEVF_ALLSESSIONS); + au_sdev_handle_t *dev; int event; auditinfo_addr_t aia; - if (NULL == dev) { - Syslog::error("This is bad, man. I've got bad vibes here. Could not open %s: %d", AUDIT_SDEV_PATH, errno); - return; - } + // This retries forever since securityd can't functions correctly without getting audit sessions events + while (1) { + dev = au_sdev_open(AU_SDEVF_ALLSESSIONS); + if (NULL == dev) { + os_log_fault(OS_LOG_DEFAULT, "auditevents count not open audit device: %d, retrying in a bit", errno); + sleep(10); + continue; + } - for (;;) { - if (0 != au_sdev_read_aia(dev, &event, &aia)) { - Syslog::error("au_sdev_read_aia failed: %d\n", errno); - continue; - } - secinfo("SecServer", "%p session notify %d %d %d", this, aia.ai_asid, event, aia.ai_auid); - if (kern_return_t rc = self_client_handleSession(mRelay, mach_task_self(), event, aia.ai_asid)) - Syslog::error("self-send failed (mach error %d)", rc); - } + for (;;) { + if (0 != au_sdev_read_aia(dev, &event, &aia)) { + secerror("au_sdev_read_aia failed: %d\n", errno); + break; + } + secinfo("SecServer", "%p session notify %d %d %d", this, aia.ai_asid, event, aia.ai_auid); + if (kern_return_t rc = self_client_handleSession(mRelay, event, aia.ai_asid)) { + secerror("self-send failed (mach error %d)", rc); + } + } + au_sdev_close(dev); + } } diff --git a/securityd/src/auditevents.h b/securityd/src/auditevents.h index e108f8ed..675e208b 100644 --- a/securityd/src/auditevents.h +++ b/securityd/src/auditevents.h @@ -40,7 +40,7 @@ public: AuditMonitor(MachPlusPlus::Port relay); ~AuditMonitor(); - void action(); + void threadAction(); private: MachPlusPlus::Port mRelay; diff --git a/securityd/src/ccaudit_extensions.cpp b/securityd/src/ccaudit_extensions.cpp index 155c8072..eb061d35 100644 --- a/securityd/src/ccaudit_extensions.cpp +++ b/securityd/src/ccaudit_extensions.cpp @@ -8,7 +8,7 @@ */ #include -#include +#include #include // vsnprintf() #include // va_start(), et al. #include diff --git a/securityd/src/credential.cpp b/securityd/src/credential.cpp index fbd703a1..3da55c7f 100644 --- a/securityd/src/credential.cpp +++ b/securityd/src/credential.cpp @@ -132,10 +132,11 @@ CredentialImpl::merge(const CredentialImpl &other) { // try to ensure that the credentials are the same type assert(mRight == other.mRight); - if (mRight) + if (mRight) { assert(mName == other.mName); - else + } else { assert(mUid == other.mUid); + } if (other.mValid && (!mValid || mCreationTime < other.mCreationTime)) { diff --git a/securityd/src/kcdatabase.cpp b/securityd/src/kcdatabase.cpp index 170a43cf..bcdec021 100644 --- a/securityd/src/kcdatabase.cpp +++ b/securityd/src/kcdatabase.cpp @@ -37,6 +37,10 @@ // is locked or when the Session dies, whichever happens earlier. // There is (as yet) no global-scope Database object for Keychain databases. // + +#define __STDC_WANT_LIB_EXT1__ 1 +#include + #include "kcdatabase.h" #include "agentquery.h" #include "kckey.h" @@ -44,6 +48,7 @@ #include "session.h" #include "notifications.h" #include "SecRandom.h" +#include "keychainstasherinterface.h" #include // @@@ 4003540 workaround #include // for default owner ACLs #include @@ -875,32 +880,66 @@ void KeychainDatabase::makeUnlocked(const AccessCredentials *cred, bool unlockKe assert(mValidData); } -// -// Invoke the securityd_service to retrieve the keychain master -// key from the AppleFDEKeyStore. -// +/** + Invoke securityd_service to load the keybag and retrieve the masterkey. + Also load masterkey from KeychainStasher and compare to make sure new stash works properly + */ void KeychainDatabase::stashDbCheck() -{ +{ + secnotice("KCdb", "Loading stashed key"); CssmAutoData masterKey(Allocator::standard(Allocator::sensitive)); CssmAutoData encKey(Allocator::standard(Allocator::sensitive)); - // Fetch the key - int rc = 0; - void * stash_key = NULL; - int stash_key_len = 0; + // We're going to double-load during transition + void* s_key = NULL; + size_t s_keylen = 0; service_context_t context = common().session().get_current_service_context(); - rc = service_client_stash_get_key(&context, &stash_key, &stash_key_len); - if (rc == 0) { - if (stash_key) { - masterKey.copy(CssmData((void *)stash_key,stash_key_len)); - memset(stash_key, 0, stash_key_len); - free(stash_key); - } + // SIDE EFFECT: loads the user's keybag + int servicerc = service_client_stash_get_key(&context, &s_key, &s_keylen); + if (servicerc != KB_Success) { + secerror("KCdb: failed to load stash from securityd_service: %d", servicerc); } else { - secnotice("KCdb", "failed to get stash from securityd_service: %d", (int)rc); - CssmError::throwMe(rc); + secnotice("KCdb", "securityd_service claims get_key success"); } - + + void* a_key = NULL; + size_t a_keylen = 0; + OSStatus agentrc = loadKeyFromStashAgent(common().session().originatorUid(), &a_key, &a_keylen); + if (agentrc != errSecSuccess) { + secerror("KCdb: failed to load stash from KeychainStasher: %d", (int)agentrc); + } else { + secnotice("KCdb", "KeychainStasher claims loadKey success"); + } + + void* key = NULL; + size_t keylen = 0; + if (servicerc != KB_Success && agentrc != errSecSuccess) { + __security_simulatecrash(CFSTR("Both old and new stashes failed to load"), __sec_exception_code_BadStash); + CssmError::throwMe(servicerc); // For now + } else if (servicerc == KB_Success && agentrc == errSecSuccess) { + if (s_keylen != a_keylen || a_keylen == 0) { + __security_simulatecrash(CFSTR("Stashed key lengths disagree or are zero"), __sec_exception_code_BadStash); + } else if (cc_cmp_safe(a_keylen, a_key, s_key) != 0) { + __security_simulatecrash(CFSTR("Keybytes disagree"), __sec_exception_code_BadStash); + } + + key = a_key; + keylen = a_keylen; + memset_s(s_key, s_keylen, 0, s_keylen); + free(s_key); + } else if (servicerc == KB_Success) { + key = s_key; + keylen = s_keylen; + } else if (agentrc == errSecSuccess) { + key = a_key; + keylen = a_keylen; + } + + masterKey.copy(CssmData(key, keylen)); + memset_s(key, keylen, 0, keylen); + free(key); + + secnotice("KCdb", "Retrieved stashed key, will establish"); { StLock _(common()); @@ -914,8 +953,9 @@ void KeychainDatabase::stashDbCheck() hdr.blobFormat(CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING); common().setup(mBlob, key); - if (!decode()) + if (!decode()) { CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + } common().get_encryption_key(encKey); } @@ -934,11 +974,11 @@ void KeychainDatabase::stashDbCheck() // void KeychainDatabase::stashDb() { + secnotice("KCdb", "Let's stash a key"); CssmAutoData data(Allocator::standard(Allocator::sensitive)); { StLock _(common()); - if (!common().isValid()) { CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); } @@ -946,10 +986,28 @@ void KeychainDatabase::stashDb() CssmKey key = common().masterKey(); data.copy(key.keyData()); } - + + // We're going to double-stash during transition service_context_t context = common().session().get_current_service_context(); - int rc = service_client_stash_set_key(&context, data.data(), (int)data.length()); - if (rc != 0) CssmError::throwMe(rc); + int servicerc = service_client_stash_set_key(&context, data.data(), (int)data.length()); + if (servicerc != KB_Success) { + secerror("KCdb: securityd_service stash failed: %d", servicerc); + } else { + secnotice("KCdb", "securityd_service claims successful stash"); + } + + OSStatus agentrc = stashKeyWithStashAgent(common().session().originatorUid(), data.data(), data.length()); + if (agentrc != errSecSuccess) { + secerror("KCdb: KeychainStasher stash failed: %d", (int)agentrc); + } else { + secnotice("KCdb", "KeychainStasher claims successful stash"); + } + + if (servicerc != KB_Success && agentrc != errSecSuccess) { + __security_simulatecrash(CFSTR("Both old and new stash mechanisms failed"), __sec_exception_code_BadStash); + CssmError::throwMe(servicerc); // For now + } + secnotice("KCdb", "Key stashed"); } // diff --git a/securityd/src/kckey.cpp b/securityd/src/kckey.cpp index fc35bbc1..943df371 100644 --- a/securityd/src/kckey.cpp +++ b/securityd/src/kckey.cpp @@ -40,7 +40,9 @@ KeychainKey::KeychainKey(Database &db, const KeyBlob *blob) : LocalKey(db, n2h(blob->header.attributes())) { // perform basic validation on the incoming blob - assert(blob); + if (blob == NULL) { + CssmError::throwMe(CSSMERR_APPLEDL_INVALID_KEY_BLOB); + } blob->validate(CSSMERR_APPLEDL_INVALID_KEY_BLOB); if (blob->startCryptoBlob > blob->totalLength) { CssmError::throwMe(CSSMERR_APPLEDL_INVALID_KEY_BLOB); diff --git a/securityd/src/keychainstasherinterface.h b/securityd/src/keychainstasherinterface.h new file mode 100644 index 00000000..bac7bb55 --- /dev/null +++ b/securityd/src/keychainstasherinterface.h @@ -0,0 +1,15 @@ +#ifndef keychainstasherinterface_h +#define keychainstasherinterface_h + +#ifdef __cplusplus +extern "C" { +#endif + +OSStatus stashKeyWithStashAgent(uid_t client, void const* keybytes, size_t keylen); +OSStatus loadKeyFromStashAgent(uid_t client, void** keybytes, size_t* keylen); + +#ifdef __cplusplus +} +#endif + +#endif /* keychainstasherinterface_h */ diff --git a/securityd/src/keychainstasherinterface.m b/securityd/src/keychainstasherinterface.m new file mode 100644 index 00000000..dfb30b0e --- /dev/null +++ b/securityd/src/keychainstasherinterface.m @@ -0,0 +1,88 @@ +#import +#import +#import + +#include "utilities/debugging.h" + +#import "KeychainStasherProtocol.h" +#import "keychainstasherinterface.h" + +NSString* const KeychainStasherMachServiceName = @"com.apple.security.KeychainStasher"; + +OSStatus stashKeyWithStashAgent(uid_t client, void const* keybytes, size_t keylen) { + if (!keybytes || keylen == 0) { + secerror("KeychainStasherInterface: No or truncated key, won't stash"); + return errSecParam; + } + + secnotice("KeychainStasherInterface", "Reaching out to agent to stash key"); + __block OSStatus result = errSecInternalError; + @autoreleasepool { + NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:KeychainStasherMachServiceName options:0]; + [connection _setTargetUserIdentifier: client]; + connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)]; + [connection resume]; + + id proxy = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + secerror("KeychainStasherInterface: errorhandler for agent called: %@", error); + result = errSecIO; + }]; + + NSData* key = [NSData _newZeroingDataWithBytes:keybytes length:keylen]; + [proxy stashKey:key withReply:^(NSError* error) { + if (error) { + secerror("KeychainStasherInterface: agent failed to stash key: %@", error); + result = (int)error.code; + } else { + result = errSecSuccess; + } + }]; + + [connection invalidate]; + } + + if (result == errSecSuccess) { + secnotice("KeychainStasherInterface", "Successfully stashed key"); + } + return result; +} + +OSStatus loadKeyFromStashAgent(uid_t client, void** keybytes, size_t* keylen) { + if (!keybytes || !keylen) { + secerror("KeychainStasherInterface: No outparams for key, won't load"); + return errSecParam; + } + + secnotice("KeychainStasherInterface", "Reaching out to agent to retrieve key"); + __block OSStatus result = errSecInternalError; + @autoreleasepool { + NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:KeychainStasherMachServiceName options:0]; + [connection _setTargetUserIdentifier: client]; + connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)]; + [connection resume]; + + id proxy = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + secerror("KeychainStasherInterface: errorhandler for agent called: %@", error); + result = errSecIO; + }]; + + [proxy loadKeyWithReply:^(NSData *key, NSError *error) { + if (!key) { + secerror("KeychainStasherInterface: agent failed to load key: %@", error); + result = (int)error.code; + return; + } + *keybytes = calloc(1, key.length); + memcpy(*keybytes, key.bytes, key.length); + *keylen = key.length; + result = errSecSuccess; + }]; + + [connection invalidate]; + } + + if (result == errSecSuccess) { + secnotice("KeychainStasherInterface", "Successfully loaded key"); + } + return result; +} diff --git a/securityd/src/main.cpp b/securityd/src/main.cpp index 5eb758a8..7d3d7d49 100644 --- a/securityd/src/main.cpp +++ b/securityd/src/main.cpp @@ -30,7 +30,6 @@ #include "server.h" #include "session.h" #include "notifications.h" -#include "pcscmonitor.h" #include "auditevents.h" #include "self.h" #include "util.h" @@ -66,11 +65,8 @@ // static void usage(const char *me) __attribute__((noreturn)); static void handleSignals(int sig); -static PCSCMonitor::ServiceLevel scOptions(const char *optionString); -static bool legacyTokensEnabled(void); static Port gMainServerPort; -PCSCMonitor *gPCSC; // @@ -87,7 +83,7 @@ int main(int argc, char *argv[]) // tell the keychain (client) layer to turn off the server interface SecKeychainSetServerMode(); - const char *params[] = {"LEGACY_TOKENS_ENABLED", legacyTokensEnabled() ? "YES" : "NO", NULL}; + const char *params[] = {"LEGACY_TOKENS_ENABLED", "NO", NULL}; char* errorbuf = NULL; if (sandbox_init_with_parameters("com.apple.securityd", SANDBOX_NAMED, params, &errorbuf)) { seccritical("SecServer: unable to enter sandbox: %{public}s", errorbuf); @@ -101,34 +97,24 @@ int main(int argc, char *argv[]) // program arguments (preset to defaults) bool debugMode = false; - const char *bootstrapName = NULL; - const char* messagingName = SharedMemoryCommon::kDefaultSecurityMessagesName; - bool doFork = false; - bool reExecute = false; int workerTimeout = 0; int maxThreads = 0; bool waitForClients = true; bool mdsIsInstalled = false; - const char *tokenCacheDir = "/var/db/TokenCache"; - const char *smartCardOptions = getenv("SMARTCARDS"); uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED; unsigned int verbose = 0; // check for the Installation-DVD environment and modify some default arguments if found if (access("/etc/rc.cdrom", F_OK) == 0) { // /etc/rc.cdrom exists secnotice("SecServer", "starting in installmode"); - smartCardOptions = "off"; // needs writable directories that aren't } // parse command line arguments extern char *optarg; extern int optind; int arg; - while ((arg = getopt(argc, argv, "c:dE:imN:s:t:T:uvWX")) != -1) { + while ((arg = getopt(argc, argv, ":dE:im:t:T:uvW")) != -1) { switch (arg) { - case 'c': - tokenCacheDir = optarg; - break; case 'd': debugMode = true; break; @@ -141,12 +127,6 @@ int main(int argc, char *argv[]) case 'm': mdsIsInstalled = true; break; - case 'N': - bootstrapName = optarg; - break; - case 's': - smartCardOptions = optarg; - break; case 't': if ((maxThreads = atoi(optarg)) < 0) maxThreads = 0; @@ -164,40 +144,19 @@ int main(int argc, char *argv[]) case 'v': verbose++; break; - case 'X': - doFork = true; - reExecute = true; - break; default: usage(argv[0]); } } // take no non-option arguments - if (optind < argc) + if (optind < argc) { usage(argv[0]); - - // figure out the bootstrap name - if (!bootstrapName) { - bootstrapName = getenv(SECURITYSERVER_BOOTSTRAP_ENV); - if (!bootstrapName) - { - bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME; - } - else - { -#ifndef __clang_analyzer__ - messagingName = bootstrapName; -#endif - } } - else - { -#ifndef __clang_analyzer__ - messagingName = bootstrapName; -#endif - } - + + const char *bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME; + const char* messagingName = SharedMemoryCommon::kDefaultSecurityMessagesName; + // configure logging first if (debugMode) { Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR); @@ -219,12 +178,8 @@ int main(int argc, char *argv[]) } // turn into a properly diabolical daemon unless debugMode is on - if (!debugMode && getppid() != 1) { - if (!Daemon::incarnate(doFork)) - exit(1); // can't daemonize - - if (reExecute && !Daemon::executeSelf(argv)) - exit(1); // can't self-execute + if (!debugMode && getppid() != 1 && !Daemon::incarnate(false)) { + exit(1); // can't daemonize } // arm signal handlers; code below may generate signals we want to see @@ -275,16 +230,13 @@ int main(int argc, char *argv[]) server.floatingThread(true); server.waitForClients(waitForClients); server.verbosity(verbose); - - // create a smartcard monitor to manage external token devices - gPCSC = new PCSCMonitor(server, tokenCacheDir, scOptions(smartCardOptions)); - + // create the RootSession object (if -d, give it graphics and tty attributes) RootSession rootSession(debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0, server); // create a monitor thread to watch for audit session events AuditMonitor audits(gMainServerPort); - audits.run(); + audits.threadRun(); // install MDS (if needed) and initialize the local CSSM server.loadCssm(mdsIsInstalled); @@ -314,10 +266,7 @@ int main(int argc, char *argv[]) static void usage(const char *me) { fprintf(stderr, "Usage: %s [-dwX]" - "\n\t[-c tokencache] smartcard token cache directory" "\n\t[-e equivDatabase] path to code equivalence database" - "\n\t[-N serviceName] MACH service name" - "\n\t[-s off|on|conservative|aggressive] smartcard operation level" "\n\t[-t maxthreads] [-T threadTimeout] server thread control" "\n", me); exit(2); @@ -326,44 +275,6 @@ static void usage(const char *me) const CFStringRef kTKSmartCardPreferencesDomain = CFSTR("com.apple.security.smartcard"); const CFStringRef kTKLegacyTokendPreferencesKey = CFSTR("Legacy"); -static bool legacyTokensEnabled() { - bool result = false; - CFPropertyListRef value = CFPreferencesCopyValue(kTKLegacyTokendPreferencesKey, kTKSmartCardPreferencesDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (value) { - if (CFEqual(value, kCFBooleanTrue)) { - result = true; - } - CFRelease(value); - } - return result; -} - -// -// Translate strings (e.g. "conservative") into PCSCMonitor service levels -// -static PCSCMonitor::ServiceLevel scOptions(const char *optionString) -{ - if (!legacyTokensEnabled()) - return PCSCMonitor::forcedOff; - - if (optionString) - if (!strcmp(optionString, "off")) - return PCSCMonitor::forcedOff; - else if (!strcmp(optionString, "on")) - return PCSCMonitor::externalDaemon; - else if (!strcmp(optionString, "conservative")) - return PCSCMonitor::externalDaemon; - else if (!strcmp(optionString, "aggressive")) - return PCSCMonitor::externalDaemon; - else if (!strcmp(optionString, "external")) - return PCSCMonitor::externalDaemon; - else - usage("securityd"); - else - return PCSCMonitor::externalDaemon; -} - - // // Handle signals. // We send ourselves a message (through the "self" service), so actual @@ -372,5 +283,5 @@ static PCSCMonitor::ServiceLevel scOptions(const char *optionString) // static void handleSignals(int sig) { - (void)self_client_handleSignal(gMainServerPort, mach_task_self(), sig); + (void)self_client_handleSignal(gMainServerPort, sig); } diff --git a/securityd/src/notifications.cpp b/securityd/src/notifications.cpp index 1efed3a5..2b846445 100644 --- a/securityd/src/notifications.cpp +++ b/securityd/src/notifications.cpp @@ -109,33 +109,6 @@ void Listener::sendNotification(Notification *message) } } - -// -// Handle a port death or deallocation by removing all Listeners using that port. -// Returns true iff we had one. -// -bool Listener::remove(Port port) -{ - typedef ListenerMap::iterator Iterator; - StLock _(setLock); - pair range = listeners.equal_range(port); - if (range.first == range.second) - return false; // not one of ours - - assert(range.first != listeners.end()); - secinfo("notify", "remove port %d", port.port()); -#if !defined(NDEBUG) - for (Iterator it = range.first; it != range.second; it++) { - assert(it->first == port); - secinfo("notify", "%p listener removed", it->second.get()); - } -#endif //NDEBUG - listeners.erase(range.first, range.second); - port.destroy(); - return true; // got it -} - - // // Notification message objects // diff --git a/securityd/src/notifications.h b/securityd/src/notifications.h index 4fd7f303..0097f34d 100644 --- a/securityd/src/notifications.h +++ b/securityd/src/notifications.h @@ -74,7 +74,6 @@ public: NotificationEvent event, const CssmData &data); static void notify(NotificationDomain domain, NotificationEvent event, uint32 sequence, const CssmData &data, audit_token_t auditToken); - static bool remove(Port port); const NotificationDomain domain; const NotificationMask events; diff --git a/securityd/src/pcscmonitor.cpp b/securityd/src/pcscmonitor.cpp index 5730e08f..826d72b1 100644 --- a/securityd/src/pcscmonitor.cpp +++ b/securityd/src/pcscmonitor.cpp @@ -54,7 +54,7 @@ PCSCMonitor::PCSCMonitor(Server &server, const char* pathToCache, ServiceLevel l } PCSCMonitor::Watcher::Watcher(Server &server, TokenCache &tokenCache, ReaderMap& readers) - : mServer(server), mTokenCache(tokenCache), mReaders(readers) + : Thread("PCSCMonitor::Watcher"), mServer(server), mTokenCache(tokenCache), mReaders(readers) {} // diff --git a/securityd/src/pcscmonitor.h b/securityd/src/pcscmonitor.h index 1a8ec1af..47805516 100644 --- a/securityd/src/pcscmonitor.h +++ b/securityd/src/pcscmonitor.h @@ -84,7 +84,7 @@ private: Watcher(Server &server, TokenCache &tokenCache, ReaderMap& readers); protected: - void action(); + void threadAction(); private: Server &mServer; diff --git a/securityd/src/process.cpp b/securityd/src/process.cpp index 9ab05df8..496bff88 100644 --- a/securityd/src/process.cpp +++ b/securityd/src/process.cpp @@ -69,6 +69,9 @@ Process::Process(TaskPort taskPort, const ClientSetupInfo *info, const CommonCri CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); } + // This is a "retain", matched by the deallocate call in ~Process + mTaskPort.modRefs(MACH_PORT_RIGHT_SEND, 1); + // NB: ServerChild::find() should only be used to determine // *existence*. Don't use the returned Child object for anything else, // as it is not protected against its underlying process's destruction. diff --git a/securityd/src/securityd.entitlements b/securityd/src/securityd.entitlements index ec8b2bc0..eb5b2a54 100644 --- a/securityd/src/securityd.entitlements +++ b/securityd/src/securityd.entitlements @@ -8,5 +8,11 @@ kTCCServiceSystemPolicyAllFiles + com.apple.private.security.storage.SystemKeychain + + com.apple.private.securityd.stash-agent-client + + com.apple.system-task-ports.token.control + diff --git a/securityd/src/securityd_dtrace.h b/securityd/src/securityd_dtrace.h deleted file mode 100644 index 8d5a99e5..00000000 --- a/securityd/src/securityd_dtrace.h +++ /dev/null @@ -1,7 +0,0 @@ -// fake DTrace probes for Darling -#ifndef _SECURITYD_SECURITYD_DTRACE_H -#define _SECURITYD_SECURITYD_DTRACE_H - - - -#endif // _SECURITYD_SECURITYD_DTRACE_H diff --git a/securityd/src/server.cpp b/securityd/src/server.cpp index 4410fc1d..194d8f41 100644 --- a/securityd/src/server.cpp +++ b/securityd/src/server.cpp @@ -37,7 +37,6 @@ #include #include #include -#include "pcscmonitor.h" #include "agentquery.h" @@ -58,10 +57,8 @@ Server::Server(CodeSignatures &signatures, const char *bootstrapName) // make me eternal (in the object mesh) ref(); -#ifndef DARLING // engage the subsidiary port handler for sleep notifications add(sleepWatcher); -#endif } @@ -301,13 +298,12 @@ void Server::notifyNoSenders(Port port, mach_port_mscount_t) // the signal handler environment. // kern_return_t self_server_handleSignal(mach_port_t sport, - mach_port_t taskPort, int sig) + audit_token_t auditToken, int sig) { try { secnotice("SecServer", "signal handled %d", sig); - if (taskPort != mach_task_self()) { + if (audit_token_to_pid(auditToken) != getpid()) { Syslog::error("handleSignal: received from someone other than myself"); - mach_port_deallocate(mach_task_self(), taskPort); return KERN_SUCCESS; } switch (sig) { @@ -332,11 +328,8 @@ kern_return_t self_server_handleSignal(mach_port_t sport, #endif //DEBUGDUMP case SIGUSR2: - { - extern PCSCMonitor *gPCSC; - gPCSC->startSoftTokens(); - break; - } + fprintf(stderr, "securityd ignoring SIGUSR2 received"); + break; default: assert(false); @@ -344,18 +337,16 @@ kern_return_t self_server_handleSignal(mach_port_t sport, } catch(...) { secnotice("SecServer", "exception handling a signal (ignored)"); } - mach_port_deallocate(mach_task_self(), taskPort); return KERN_SUCCESS; } kern_return_t self_server_handleSession(mach_port_t sport, - mach_port_t taskPort, uint32_t event, uint64_t ident) + audit_token_t auditToken, uint32_t event, uint64_t ident) { try { - if (taskPort != mach_task_self()) { + if (audit_token_to_pid(auditToken) != getpid()) { Syslog::error("handleSession: received from someone other than myself"); - mach_port_deallocate(mach_task_self(), taskPort); return KERN_SUCCESS; } if (event == AUE_SESSION_END) @@ -363,7 +354,6 @@ kern_return_t self_server_handleSession(mach_port_t sport, } catch(...) { secnotice("SecServer", "exception handling a signal (ignored)"); } - mach_port_deallocate(mach_task_self(), taskPort); return KERN_SUCCESS; } @@ -511,6 +501,8 @@ bool Server::inDarkWake() // void Server::loadCssm(bool mdsIsInstalled) { + try { + if (!mCssm->isActive()) { StLock _(*this); xpc_transaction_begin(); @@ -527,6 +519,23 @@ void Server::loadCssm(bool mdsIsInstalled) } xpc_transaction_end(); } + } catch (const UnixError& err) { + secerror("load cssm failed: %s", err.what()); + if (err.unixError() == ENOSPC) { + _exit(1); + } else { + abort(); + } + } catch (const MacOSError& err) { + secerror("load cssm failed: %s", err.what()); + abort(); + } catch (const CommonError& err) { + secerror("load cssm failed: %d/%d", (int)err.osStatus(), err.unixError()); + abort(); + } catch (const std::exception& err) { + secerror("load cssm failed: %s", err.what()); + abort(); + } } diff --git a/securityd/src/server.h b/securityd/src/server.h index c11fabe7..01bd448d 100644 --- a/securityd/src/server.h +++ b/securityd/src/server.h @@ -223,7 +223,7 @@ public: // These are sent as Mach messages from ourselves to escape the limitations of // the signal handler environment. // -kern_return_t self_server_handleSignal(mach_port_t sport, mach_port_t taskPort, int sig); -kern_return_t self_server_handleSession(mach_port_t sport, mach_port_t taskPort, uint32_t event, uint64_t ident); +kern_return_t self_server_handleSignal(mach_port_t sport, audit_token_t auditToken, int sig); +kern_return_t self_server_handleSession(mach_port_t sport, audit_token_t auditToken, uint32_t event, uint64_t ident); #endif //_H_SERVER diff --git a/securityd/src/token.cpp b/securityd/src/token.cpp index c9d2f5d5..f6aaaf05 100644 --- a/securityd/src/token.cpp +++ b/securityd/src/token.cpp @@ -41,7 +41,6 @@ #include #include #include -#include using namespace MDSClient; @@ -436,15 +435,6 @@ void Token::notify(NotificationEvent event) free (data.data()); } -static void mt_log_ctk_tokend(const char *signature, const char *signature2) -{ - msgtracer_log_with_keys("com.apple.ctk.tokend", ASL_LEVEL_NOTICE, - "com.apple.message.signature", signature, - "com.apple.message.signature2", signature2, - "com.apple.message.summarize", "YES", - NULL); -} - // // Choose a token daemon for our card. // @@ -503,7 +493,6 @@ RefPointer Token::chooseTokend() identifiers.append(";"); identifiers.append(*i); } - mt_log_ctk_tokend(identifiers.c_str(), chosenIdentifier.c_str()); return leader; } diff --git a/securityd/src/transition.cpp b/securityd/src/transition.cpp index ff606b4c..8d0110f0 100644 --- a/securityd/src/transition.cpp +++ b/securityd/src/transition.cpp @@ -49,8 +49,11 @@ #include #include #include +#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 #include #include +#include +#include #include #include @@ -65,7 +68,7 @@ #define BEGIN_IPCN *rcode = CSSM_OK; try { #define BEGIN_IPC(name) BEGIN_IPCN RefPointer connRef(&Server::connection(replyPort, auditToken)); \ Connection &connection __attribute__((unused)) = *connRef; \ - secinfo("SecServer", "request entry " #name " (pid:%d ession:%d)", connection.process().pid(), connection.session().sessionId()); + secinfo("SecServer", "request entry " #name " (pid:%d session:%d)", connection.process().pid(), connection.session().sessionId()); #define END_IPC(base) END_IPCN(base) Server::requestComplete(*rcode); return KERN_SUCCESS; #define END_IPCN(base) secinfo("SecServer", "request return: %d", *(rcode)); \ @@ -235,27 +238,37 @@ static void checkPathLength(char const *str) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmissing-prototypes" -kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo info, const char *identity) +kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskToken, ClientSetupInfo info, const char *identity) { + mach_port_t taskPort = MACH_PORT_NULL; BEGIN_IPCN secinfo("SecServer", "request entry: setup"); + kern_return_t kr = task_identity_token_get_task_port(taskToken, TASK_FLAVOR_CONTROL, &taskPort); + MachPlusPlus::check(kr); Server::active().setupConnection(Server::connectNewProcess, replyPort, taskPort, auditToken, &info); END_IPCN(CSSM) if (*rcode) Syslog::notice("setup(%s) failed rcode=%d", identity ? identity : "", *rcode); + mach_port_deallocate(mach_task_self(), taskPort); + mach_port_deallocate(mach_task_self(), taskToken); return KERN_SUCCESS; } -kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskPort) +kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskToken) { + mach_port_t taskPort = MACH_PORT_NULL; secinfo("SecServer", "request entry: setupThread"); BEGIN_IPCN + kern_return_t kr = task_identity_token_get_task_port(taskToken, TASK_FLAVOR_CONTROL, &taskPort); + MachPlusPlus::check(kr); Server::active().setupConnection(Server::connectNewThread, replyPort, taskPort, auditToken); END_IPCN(CSSM) if (*rcode) Syslog::notice("setupThread failed rcode=%d", *rcode); + mach_port_deallocate(mach_task_self(), taskPort); + mach_port_deallocate(mach_task_self(), taskToken); return KERN_SUCCESS; } @@ -726,16 +739,16 @@ static void check_stash_entitlement(Process & proc) bool entitled = false; status = proc.copySigningInfo(kSecCSRequirementInformation, &code_info); - require_noerr(status, done); + __Require_noErr(status, done); if (CFDictionaryGetValueIfPresent(code_info, kSecCodeInfoEntitlementsDict, &value)) { if (CFGetTypeID(value) == CFDictionaryGetTypeID()) { entitlements = (CFDictionaryRef)value; } } - require(entitlements != NULL, done); + __Require(entitlements != NULL, done); - if (CFDictionaryGetValueIfPresent(entitlements, CFSTR("com.apple.private.securityd.stash"), &value)) { + if (CFDictionaryGetValueIfPresent(entitlements, kSecEntitlementPrivateStash, &value)) { if (CFGetTypeID(value) && CFBooleanGetTypeID()) { entitled = CFBooleanGetValue((CFBooleanRef)value); } diff --git a/sslViewer/SSLViewer.c b/sslViewer/SSLViewer.c index 3cd0381e..a9d405d8 100644 --- a/sslViewer/SSLViewer.c +++ b/sslViewer/SSLViewer.c @@ -778,23 +778,26 @@ static void showPeerTrust(SecTrustRef peerTrust, bool verbose) { if (info && CFDictionaryGetCount(info)) { showInfo(info); } - if (info) + if (info) { CFRelease(info); + } - numCerts = SecTrustGetCertificateCount(peerTrust); - for(i=0; i #import +#import "SFAnalytics+Internal.h" #import "SFAnalyticsDefines.h" #import "SFAnalyticsSQLiteStore.h" #import "NSDate+SFAnalytics.h" @@ -68,6 +69,7 @@ static NSString* _path; static NSInteger _testnum; static NSString* build = NULL; static NSString* product = NULL; +static NSString* modelID = nil; // MARK: Test helper methods @@ -153,6 +155,7 @@ static NSString* product = NULL; XCTAssertTrue([rowdata[SFAnalyticsEventClassKey] isKindOfClass:[NSNumber class]] && [rowdata[SFAnalyticsEventClassKey] intValue] == class, @"eventClass is %ld", (long)class); XCTAssertTrue([rowdata[@"build"] isEqualToString:build], @"event row includes build"); XCTAssertTrue([rowdata[@"product"] isEqualToString:product], @"event row includes product"); + XCTAssertTrue([rowdata[@"modelid"] isEqualToString:modelID], @"event row includes modelid"); XCTAssertTrue(rowdata[@"internal"], @"event row includes internal"); } @@ -222,6 +225,8 @@ static NSString* product = NULL; NSLog(@"could not get build version/product, tests should fail"); } + modelID = [SFAnalytics hwModelID]; + [TestResourceUsage monitorTestResourceUsage]; } diff --git a/supd/Tests/SupdTests.m b/supd/Tests/SupdTests.m index 0b869500..acac5a99 100644 --- a/supd/Tests/SupdTests.m +++ b/supd/Tests/SupdTests.m @@ -39,6 +39,7 @@ #import #import "SFAnalyticsDefines.h" #import +#import static NSString* _path; static NSInteger _testnum; @@ -294,7 +295,7 @@ static NSInteger _reporterWrites; { dispatch_semaphore_t sema = dispatch_semaphore_create(0); __block NSDictionary* data; - [_supd getLoggingJSON:YES topic:topic reply:^(NSData *json, NSError *error) { + [_supd createLoggingJSON:YES topic:topic reply:^(NSData *json, NSError *error) { XCTAssertNil(error); XCTAssertNotNil(json); if (!error) { @@ -348,17 +349,22 @@ static NSInteger _reporterWrites; OCMStub([mockTopic databasePathForCKKS]).andReturn(ckksPath); OCMStub([mockTopic databasePathForSOS]).andReturn(sosPath); OCMStub([mockTopic databasePathForPCS]).andReturn(pcsPath); - OCMStub([mockTopic databasePathForTLS]).andReturn(tlsPath); + OCMStub([mockTopic databasePathForTrust]).andReturn(tlsPath); OCMStub([mockTopic databasePathForSignIn]).andReturn(signInPath); OCMStub([mockTopic databasePathForCloudServices]).andReturn(cloudServicesPath); // These are not used for testing, but real data can pollute tests so point to empty DBs NSString *localpath = [_path stringByAppendingFormat:@"/local_empty_%ld.db", (long)_testnum]; - NSString *trustPath = [_path stringByAppendingFormat:@"/trust_empty_%ld.db", (long)_testnum]; - NSString *trustdhealthPath = [_path stringByAppendingFormat:@"/trustdhealth_empty_%ld.db", (long)_testnum]; + NSString *networkingPath = [_path stringByAppendingFormat:@"/networking_empty_%ld.db", (long)_testnum]; OCMStub([mockTopic databasePathForLocal]).andReturn(localpath); - OCMStub([mockTopic databasePathForTrust]).andReturn(trustPath); - OCMStub([mockTopic databasePathForTrustdHealth]).andReturn(trustdhealthPath); + OCMStub([mockTopic databasePathForNetworking]).andReturn(networkingPath); + +#if TARGET_OS_OSX + NSString *rootTrustPath = [_path stringByAppendingFormat:@"/root_trust_empty_%ld.db", (long)_testnum]; + NSString *rootNetworkingPath = [_path stringByAppendingFormat:@"/root_networking_empty_%ld.db", (long)_testnum]; + OCMStub([mockTopic databasePathForRootTrust]).andReturn(rootTrustPath); + OCMStub([mockTopic databasePathForRootNetworking]).andReturn(rootNetworkingPath); +#endif _reporterWrites = 0; mockReporter = OCMClassMock([SFAnalyticsReporter class]); @@ -366,8 +372,10 @@ static NSInteger _reporterWrites; _reporterWrites++; }).andReturn(YES); - [supd removeInstance]; - _supd = [[supd alloc] initWithReporter:mockReporter]; + NSXPCConnection* mockConnection = OCMClassMock([NSXPCConnection class]); + OCMStub([mockConnection valueForEntitlement:@"com.apple.private.securityuploadd"]).andReturn(@(YES)); + + _supd = [[supd alloc] initWithConnection:mockConnection reporter:mockReporter]; _ckksAnalytics = [FakeCKKSAnalytics new]; _sosAnalytics = [FakeSOSAnalytics new]; _pcsAnalytics = [FakePCSAnalytics new]; @@ -448,7 +456,8 @@ static NSInteger _reporterWrites; [_sosAnalytics logHardFailureForEventNamed:@"unittestevent" withAttributes:utAttrs]; [_sosAnalytics logSoftFailureForEventNamed:@"unittestevent" withAttributes:utAttrs]; - NSDictionary* data = [self getJSONDataFromSupd]; + NSDictionary *data = [self getJSONDataFromSupd]; + [self inspectDataBlobStructure:data]; // TODO: inspect health summaries @@ -763,6 +772,106 @@ static NSInteger _reporterWrites; XCTAssertEqual(foundErrorEvents, 1); } +- (void)testUploadSizeLimits +{ + SFAnalyticsTopic *trustTopic = [self TrustTopic]; + XCTAssertEqual(1000000, trustTopic.uploadSizeLimit); + + SFAnalyticsTopic *keySyncTopic = [self keySyncTopic]; + XCTAssertEqual(1000000, keySyncTopic.uploadSizeLimit); +} + +- (NSArray *)createRandomEventList:(size_t)count +{ + NSMutableArray *eventSet = [[NSMutableArray alloc] init]; + + const size_t dataSize = 100; + uint8_t backingBuffer[dataSize] = {}; + for (size_t i = 0; i < count; i++) { + NSData *data = [[NSData alloc] initWithBytes:backingBuffer length:dataSize]; + NSDictionary *entry = @{@"key" : [data base64EncodedStringWithOptions:0]}; + [eventSet addObject:entry]; + } + + return eventSet; +} + +- (void)testCreateLoggingJSON +{ + NSArray *summaries = [self createRandomEventList:5]; + NSArray *failures = [self createRandomEventList:100]; + NSMutableArray *visitedEvents = [[NSMutableArray alloc] init]; + + SFAnalyticsTopic *topic = [self TrustTopic]; + const size_t sizeLimit = 10000; // total size of the encoded data + topic.uploadSizeLimit = sizeLimit; + + NSError *error = nil; + NSArray *eventSet = [topic createChunkedLoggingJSON:summaries failures:failures error:&error]; + XCTAssertNil(error); + + for (NSDictionary *event in eventSet) { + XCTAssertNotNil([event objectForKey:@"events"]); + XCTAssertNotNil([event objectForKey:SFAnalyticsPostTime]); + NSArray *events = [event objectForKey:@"events"]; + for (NSDictionary *summary in summaries) { + BOOL foundSummary = NO; + for (NSDictionary *innerEvent in events) { + if ([summary isEqualToDictionary:innerEvent]) { + foundSummary = YES; + break; + } + } + XCTAssertTrue(foundSummary); + } + + // Record the events we've seen so far + for (NSDictionary *innerEvent in events) { + [visitedEvents addObject:innerEvent]; + } + } + + // Check that each summary and failure is in the visitedEvents + for (NSDictionary *summary in summaries) { + BOOL foundSummary = NO; + for (NSDictionary *innerEvent in visitedEvents) { + if ([summary isEqualToDictionary:innerEvent]) { + foundSummary = YES; + break; + } + } + XCTAssertTrue(foundSummary); + } + for (NSDictionary *failure in failures) { + BOOL foundFailure = NO; + for (NSDictionary *innerEvent in visitedEvents) { + if ([failure isEqualToDictionary:innerEvent]) { + foundFailure = YES; + break; + } + } + XCTAssertTrue(foundFailure); + } +} + +- (void)testEventSetChunking +{ + NSArray *eventSet = [self createRandomEventList:100]; + SFAnalyticsTopic *topic = [self TrustTopic]; + + const size_t sizeLimit = 10000; // total size of the encoded data + size_t encodedEventSize = [topic serializedEventSize:eventSet[0] error:nil]; + topic.uploadSizeLimit = sizeLimit; // fix the upload limit + + // Chunk up the set, assuming that each chunk already has one event in it. + // In practice, this is the health summary. + NSError *error = nil; + NSArray *chunkedEvents = [topic chunkFailureSet:(sizeLimit - encodedEventSize) events:eventSet error:nil]; + XCTAssertNil(error); + + // There should be two resulting chunks, since the set of chunks overflows. + XCTAssertEqual(2, [chunkedEvents count]); +} // TODO - (void)testGetSysdiagnoseDump diff --git a/supd/com.apple.securityuploadd.sb b/supd/com.apple.securityuploadd.sb new file mode 100644 index 00000000..fa68f507 --- /dev/null +++ b/supd/com.apple.securityuploadd.sb @@ -0,0 +1,81 @@ +(version 1) + +(deny default) +(deny file-map-executable iokit-get-properties process-info* nvram*) +(deny dynamic-code-generation) +(deny mach-priv-host-port) + +(import "system.sb") +(import "com.apple.corefoundation.sb") +(corefoundation) + +;;; Homedir-relative path filters +(define (home-regex home-relative-regex) + (regex (string-append "^" (regex-quote (param "HOME")) home-relative-regex))) + +(define (home-subpath home-relative-subpath) + (subpath (string-append (param "HOME") home-relative-subpath))) + +(define (home-prefix home-relative-prefix) + (prefix (string-append (param "HOME") home-relative-prefix))) + +(define (home-literal home-relative-literal) + (literal (string-append (param "HOME") home-relative-literal))) + +(allow process-info* (target self)) + +;; For resolving symlinks, realpath(3), and equivalents. +(allow file-read-metadata) + +;; For validating the entitlements of clients. +(allow process-info-codesignature) + +(allow user-preference-read user-preference-write + (preference-domain "com.apple.security.analytics") + (preference-domain ".GlobalPreferences") + (preference-domain "com.apple.CFNetwork") + (preference-domain "com.apple.nsurlcache") + (preference-domain "kCFPreferencesAnyApplication")) + +(allow file-read* + (literal "/usr/libexec") + (literal "/usr/libexec/securityuploadd") + (subpath "/private/var/protected/trustd/SupplementalsAssets/") + (literal "/Library/Application Support/CrashReporter/DiagnosticMessagesHistory.plist") + (regex "/private/var/db/mds/messages/([A-Za-z0-9]+/)?se_SecurityMessages")) + +;; Read/write access to analytics DBs and reports directories +(allow file-read* file-write* + (subpath "/private/var/protected/") + (home-regex #"/Library/Keychains/[0-9A-F-]+/Analytics(/|$)") + (home-subpath #"/Library/Logs/DiagnosticReports/") + (home-subpath #"/Library/Application Support/com.apple.ProtectedCloudStorage/")) + +;; Read/write cache access +(let ((cache-path-filter (home-subpath "/Library/Caches/com.apple.securityuploadd"))) + (allow file-read* file-write* cache-path-filter) + (allow file-issue-extension + (require-all + (extension-class "com.apple.app-sandbox.read" "com.apple.app-sandbox.read-write") + cache-path-filter))) + +(allow mach-lookup + (global-name "com.apple.securityd.ckks") + (global-name "com.apple.accountsd.accountmanager") + (global-name "com.apple.SystemConfiguration.configd") + (global-name "com.apple.AppSSO.service-xpc") + (global-name "com.apple.dnssd.service") + (global-name "com.apple.usymptomsd") + (global-name "com.apple.ak.auth.xpc")) + +;; Legacy SecKey operations +(allow file-read* file-write* + (regex #"^/private/var/folders/[^/]+/[^/]+/C/mds/mdsDirectory\.db$") + (regex #"^/private/var/folders/[^/]+/[^/]+/C/mds/mdsObject\.db$") + (regex #"^/private/var/folders/[^/]+/[^/]+/C/mds/mds\.lock$")) +(allow mach-lookup + (global-name "com.apple.SecurityServer")) + +;; allow network +(allow network-outbound) +(allow system-socket) diff --git a/supd/main.m b/supd/main.m index b4d4a38e..b7c70195 100644 --- a/supd/main.m +++ b/supd/main.m @@ -22,6 +22,14 @@ */ #include +#import +#import + +#if TARGET_OS_OSX +#include +#include +#include +#endif #if TARGET_OS_SIMULATOR @@ -44,16 +52,26 @@ int main(int argc, char** argv) @implementation ServiceDelegate - (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection { - NSNumber *num = [newConnection valueForEntitlement:@"com.apple.private.securityuploadd"]; - if (![num isKindOfClass:[NSNumber class]] || ![num boolValue]) { + /* Client must either have the supd entitlement or the trustd file helping entitlement. + * Each method of the protocol will additionally check for the entitlement it needs. */ + NSNumber *supdEntitlement = [newConnection valueForEntitlement:@"com.apple.private.securityuploadd"]; + BOOL hasSupdEntitlement = [supdEntitlement isKindOfClass:[NSNumber class]] && [supdEntitlement boolValue]; + NSNumber *trustdHelperEntitlement = [newConnection valueForEntitlement:@"com.apple.private.trustd.FileHelp"]; + BOOL hasTrustdHelperEntitlement = [trustdHelperEntitlement isKindOfClass:[NSNumber class]] && [trustdHelperEntitlement boolValue]; + + /* expose the protocol based the client's entitlement (a client can't do both) */ + if (hasSupdEntitlement) { + secinfo("xpc", "Client (pid: %d) properly entitled for supd interface, let's go", [newConnection processIdentifier]); + newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(supdProtocol)]; + } else if (hasTrustdHelperEntitlement) { + secinfo("xpc", "Client (pid: %d) properly entitled for trustd file helper interface, let's go", [newConnection processIdentifier]); + newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(TrustdFileHelper_protocol)]; + } else { secerror("xpc: Client (pid: %d) doesn't have entitlement", [newConnection processIdentifier]); return NO; - } else { - secinfo("xpc", "Client (pid: %d) properly entitled, let's go", [newConnection processIdentifier]); } - newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(supdProtocol)]; - supd *exportedObject = [supd instance]; + supd *exportedObject = [[supd alloc] initWithConnection:newConnection]; newConnection.exportedObject = exportedObject; [newConnection resume]; return YES; @@ -61,13 +79,46 @@ int main(int argc, char** argv) @end +static void securityuploadd_sandbox(void) +{ +#if TARGET_OS_OSX + // Enter the sandbox on macOS + char homeDir[PATH_MAX] = {}; + struct passwd* pwd = getpwuid(getuid()); + if (pwd == NULL) { + secerror("Failed to get home directory for user: %d", errno); + exit(EXIT_FAILURE); + } + + if (realpath(pwd->pw_dir, homeDir) == NULL) { + strlcpy(homeDir, pwd->pw_dir, sizeof(homeDir)); + } + + const char *sandbox_params[] = { + "HOME", homeDir, + NULL + }; + + char *sberror = NULL; + secerror("initializing securityuploadd sandbox with HOME=%s", homeDir); + if (sandbox_init_with_parameters("com.apple.securityuploadd", SANDBOX_NAMED, sandbox_params, &sberror) != 0) { + secerror("Failed to enter securityuploadd sandbox: %{public}s", sberror); + exit(EXIT_FAILURE); + } +#endif +} + int main(int argc, const char *argv[]) { secnotice("lifecycle", "supd lives!"); + [NSError _setFileNameLocalizationEnabled:NO]; + securityuploadd_sandbox(); + ServiceDelegate *delegate = [ServiceDelegate new]; - // kick the singleton so it can register its xpc activity handler - [supd instantiate]; + // Always create a supd instance to register for the background activity that doesn't check entitlements + static supd *activity_supd = nil; + activity_supd = [[supd alloc] initWithConnection:nil]; NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:@"com.apple.securityuploadd"]; listener.delegate = delegate; diff --git a/supd/securityuploadd-Entitlements.plist b/supd/securityuploadd-Entitlements.plist index ee1cb751..b359175e 100644 --- a/supd/securityuploadd-Entitlements.plist +++ b/supd/securityuploadd-Entitlements.plist @@ -14,5 +14,7 @@ com.apple.security.network.client + com.apple.private.security.storage.SFAnalytics + diff --git a/supd/supd.h b/supd/supd.h index f9fdce96..e924cb8d 100644 --- a/supd/supd.h +++ b/supd/supd.h @@ -23,6 +23,7 @@ #import #import "supdProtocol.h" +#import "trust/trustd/trustdFileLocations.h" @interface SFAnalyticsClient: NSObject @property (nonatomic) NSString* storePath; @@ -35,6 +36,7 @@ @property NSString* splunkTopicName; @property NSURL* splunkBagURL; @property NSString *internalTopicName; +@property NSUInteger uploadSizeLimit; @property NSArray* topicClients; @@ -42,15 +44,22 @@ // Things below are for unit testing - (instancetype)initWithDictionary:(NSDictionary *)dictionary name:(NSString *)topicName samplingRates:(NSDictionary *)rates; - (BOOL)haveEligibleClients; +- (NSArray *)createChunkedLoggingJSON:(NSArray *)healthSummaries failures:(NSArray *)failures error:(NSError **)error; +- (NSArray *)chunkFailureSet:(size_t)sizeCapacity events:(NSArray *)events error:(NSError **)error; +- (size_t)serializedEventSize:(NSObject *)event error:(NSError**)error; + (NSString*)databasePathForCKKS; + (NSString*)databasePathForSOS; + (NSString*)databasePathForPCS; + (NSString*)databasePathForLocal; + (NSString*)databasePathForTrust; -+ (NSString*)databasePathForTrustdHealth; -+ (NSString*)databasePathForTLS; ++ (NSString*)databasePathForNetworking; + (NSString*)databasePathForSignIn; + (NSString*)databasePathForCloudServices; + +#if TARGET_OS_OSX ++ (NSString*)databasePathForRootTrust; ++ (NSString*)databasePathForRootNetworking; +#endif @end @interface SFAnalyticsReporter : NSObject @@ -64,18 +73,15 @@ typedef NS_ENUM(NSInteger, SupdError) { SupdInvalidJSONError, }; -@interface supd : NSObject -+ (instancetype)instance; -+ (void)removeInstance; -+ (void)instantiate; -- (instancetype)initWithReporter:(SFAnalyticsReporter *)reporter; +@interface supd : NSObject +- (instancetype)initWithConnection:(NSXPCConnection *)connection; // -------------------------------- // Things below are for unit testing -@property (readonly) dispatch_queue_t queue; @property (readonly) NSArray* analyticsTopics; @property (readonly) SFAnalyticsReporter *reporter; - (void)sendNotificationForOncePerReportSamplers; +- (instancetype)initWithConnection:(NSXPCConnection *)connection reporter:(SFAnalyticsReporter *)reporter; @end // -------------------------------- diff --git a/supd/supd.m b/supd/supd.m index 194e1591..5bbaec95 100644 --- a/supd/supd.m +++ b/supd/supd.m @@ -22,6 +22,7 @@ */ #import "supd.h" +#import #if !TARGET_OS_SIMULATOR @@ -43,6 +44,7 @@ #if TARGET_OS_OSX #include "dirhelper_priv.h" +#include #endif #if TARGET_OS_OSX @@ -59,9 +61,10 @@ #import #import +#import "utilities/simulatecrash_assert.h" +#import "trust/trustd/trustdFileHelper/trustdFileHelper.h" NSString* const SFAnalyticsSplunkTopic = @"topic"; -NSString* const SFAnalyticsSplunkPostTime = @"postTime"; NSString* const SFAnalyticsClientId = @"clientId"; NSString* const SFAnalyticsInternal = @"internal"; @@ -69,6 +72,8 @@ NSString* const SFAnalyticsMetricsBase = @"metricsBase"; NSString* const SFAnalyticsDeviceID = @"ckdeviceID"; NSString* const SFAnalyticsAltDSID = @"altDSID"; +NSString* const SFAnalyticsEventCorrelationID = @"eventLinkID"; + NSString* const SFAnalyticsSecondsCustomerKey = @"SecondsBetweenUploadsCustomer"; NSString* const SFAnalyticsSecondsInternalKey = @"SecondsBetweenUploadsInternal"; NSString* const SFAnalyticsSecondsSeedKey = @"SecondsBetweenUploadsSeed"; @@ -116,8 +121,6 @@ NSUInteger const secondsBetweenUploadsSeed = (60 * 60 * 24); #define DEFAULT_SPLUNK_MAX_EVENTS_TO_REPORT 1000 #define DEFAULT_SPLUNK_DEVICE_PERCENTAGE 100 -static supd *_supdInstance = nil; - BOOL runningTests = NO; BOOL deviceAnalyticsOverride = NO; BOOL deviceAnalyticsEnabled = NO; @@ -340,18 +343,18 @@ _isiCloudAnalyticsEnabled() deviceAnalytics:YES iCloudAnalytics:NO]]; } else if ([topicName isEqualToString:SFAnalyticsTopicTrust]) { -#if TARGET_OS_OSX - _set_user_dir_suffix("com.apple.trustd"); // supd needs to read trustd's cache dir for these -#endif [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForTrust] name:@"trust" deviceAnalytics:YES iCloudAnalytics:NO]]; - [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForTrustdHealth] - name:@"trustdHealth" deviceAnalytics:YES iCloudAnalytics:NO]]; - [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForTLS] - name:@"tls" deviceAnalytics:YES iCloudAnalytics:NO]]; - #if TARGET_OS_OSX - _set_user_dir_suffix(NULL); // set back to the default cache dir + [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForRootTrust] + name:@"rootTrust" deviceAnalytics:YES iCloudAnalytics:NO]]; +#endif + } else if ([topicName isEqualToString:SFAnalyticsTopicNetworking]) { + [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForNetworking] + name:@"networking" deviceAnalytics:YES iCloudAnalytics:NO]]; +#if TARGET_OS_OSX + [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForRootNetworking] + name:@"rootNetworking" deviceAnalytics:YES iCloudAnalytics:NO]]; #endif } else if ([topicName isEqualToString:SFAnalyticsTopicTransparency]) { [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForTransparency] @@ -369,6 +372,8 @@ _isiCloudAnalyticsEnabled() __splunkUploadURL = [NSURL URLWithString:dictionary[@"splunk_uploadURL"]]; _splunkBagURL = [NSURL URLWithString:dictionary[@"splunk_bagURL"]]; _allowInsecureSplunkCert = [[dictionary valueForKey:@"splunk_allowInsecureCertificate"] boolValue]; + _uploadSizeLimit = [[dictionary valueForKey:@"uploadSizeLimit"] unsignedIntegerValue]; + NSString* splunkEndpoint = dictionary[@"splunk_endpointDomain"]; if (dictionary[@"disableClientId"]) { _disableClientId = YES; @@ -390,6 +395,11 @@ _isiCloudAnalyticsEnabled() _splunkBagURL = userDefaultsSplunkBagURL; } + NSInteger userDefaultsUploadSizeLimit = [defaults integerForKey:@"uploadSizeLimit"]; + if (userDefaultsUploadSizeLimit > 0) { + _uploadSizeLimit = userDefaultsUploadSizeLimit; + } + BOOL userDefaultsAllowInsecureSplunkCert = [defaults boolForKey:@"splunk_allowInsecureCertificate"]; _allowInsecureSplunkCert |= userDefaultsAllowInsecureSplunkCert; @@ -536,7 +546,8 @@ _isiCloudAnalyticsEnabled() }]; } -- (BOOL)prepareEventForUpload:(NSMutableDictionary*)event { +- (BOOL)prepareEventForUpload:(NSMutableDictionary*)event + linkedUUID:(NSUUID *)linkedUUID { if ([self eventIsBlacklisted:event]) { return NO; } @@ -547,10 +558,13 @@ _isiCloudAnalyticsEnabled() event[SFAnalyticsClientId] = @(0); } event[SFAnalyticsSplunkTopic] = self->_splunkTopicName ?: [NSNull null]; + if (linkedUUID) { + event[SFAnalyticsEventCorrelationID] = [linkedUUID UUIDString]; + } return YES; } -- (void)addFailures:(NSMutableArray*)failures toUploadRecords:(NSMutableArray*)records threshold:(NSUInteger)threshold +- (void)addFailures:(NSMutableArray*)failures toUploadRecords:(NSMutableArray*)records threshold:(NSUInteger)threshold linkedUUID:(NSUUID *)linkedUUID { // The first 0 through 'threshold' items are getting uploaded in any case (which might be 0 for lower priority data) @@ -561,7 +575,7 @@ _isiCloudAnalyticsEnabled() *stop = YES; return; } - if ([self prepareEventForUpload:event]) { + if ([self prepareEventForUpload:event linkedUUID:linkedUUID]) { if ([NSJSONSerialization isValidJSONObject:event]) { [records addObject:event]; } else { @@ -594,7 +608,7 @@ _isiCloudAnalyticsEnabled() NSRange range = NSMakeRange(threshold, (client.count - threshold) * scale); NSArray* sub = [client subarrayWithRange:range]; [sub enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { - if ([self prepareEventForUpload:obj]) { + if ([self prepareEventForUpload:obj linkedUUID:linkedUUID]) { [records addObject:obj]; } }]; @@ -651,7 +665,7 @@ _isiCloudAnalyticsEnabled() return statistics; } -- (NSMutableDictionary*)healthSummaryWithName:(NSString*)name store:(SFAnalyticsSQLiteStore*)store +- (NSMutableDictionary*)healthSummaryWithName:(NSString*)name store:(SFAnalyticsSQLiteStore*)store uuid:(NSUUID *)uuid { __block NSMutableDictionary* summary = [NSMutableDictionary new]; @@ -703,7 +717,7 @@ _isiCloudAnalyticsEnabled() }]; // Should always return yes because we already checked for event blacklisting specifically (unless summary itself is blacklisted) - if (![self prepareEventForUpload:summary]) { + if (![self prepareEventForUpload:summary linkedUUID:uuid]) { secwarning("supd: health summary for %@ blacklisted", name); return nil; } @@ -731,67 +745,197 @@ _isiCloudAnalyticsEnabled() } } -- (NSData*)getLoggingJSON:(bool)pretty - forUpload:(BOOL)upload - participatingClients:(NSMutableArray**)clients - force:(BOOL)force // supdctl uploads ignore privacy settings and recency - error:(NSError**)error +- (size_t)serializedEventSize:(NSObject *)event + error:(NSError**)error { - NSMutableArray* localClients = [NSMutableArray new]; - __block NSMutableArray* uploadRecords = [NSMutableArray arrayWithCapacity:_maxEventsToReport]; - __block NSError *localError; - __block NSMutableArray* hardFailures = [NSMutableArray new]; - __block NSMutableArray* softFailures = [NSMutableArray new]; - NSString* ckdeviceID = nil; - NSString* accountID = nil; + if (![NSJSONSerialization isValidJSONObject:event]) { + secnotice("serializedEventSize", "invalid JSON object"); + return 0; + } + + NSData *json = [NSJSONSerialization dataWithJSONObject:event + options:0 + error:error]; + if (json) { + return [json length]; + } else { + secnotice("serializedEventSize", "failed to serialize event"); + return 0; + } +} + +- (NSArray *)chunkFailureSet:(size_t)sizeCapacity + events:(NSArray *)events + error:(NSError **)error +{ + const size_t postBodyLimit = 1000; // 1000 events in a single upload + size_t currentSize = 0; + size_t currentEventCount = 0; + + NSMutableArray *> *eventChunks = [[NSMutableArray *> alloc] init]; + NSMutableArray *currentEventChunk = [[NSMutableArray alloc] init]; + for (NSDictionary *event in events) { + NSError *localError = nil; + size_t eventSize = [self serializedEventSize:event error:&localError]; + if (localError != nil) { + if (error) { + *error = localError; + } + secemergency("Unable to serialize event JSON: %@", [localError localizedDescription]); + return nil; + } + + BOOL countLessThanLimit = currentEventCount < postBodyLimit; + BOOL sizeLessThanCapacity = (currentSize + eventSize) <= sizeCapacity; + if (!countLessThanLimit || !sizeLessThanCapacity) { + [eventChunks addObject:currentEventChunk]; + currentEventChunk = [[NSMutableArray alloc] init]; + currentEventCount = 0; + currentSize = 0; + } + + [currentEventChunk addObject:event]; + currentEventCount++; + currentSize += eventSize; + } + + if ([currentEventChunk count] > 0) { + [eventChunks addObject:currentEventChunk]; + } + + return eventChunks; +} + +- (NSDictionary *)createEventDictionary:(NSArray *)healthSummaries + failures:(NSArray *)failures + error:(NSError **)error +{ + NSMutableArray *events = [[NSMutableArray alloc] init]; + [events addObjectsFromArray:healthSummaries]; + if (failures) { + [events addObjectsFromArray:failures]; + } + + NSDictionary *eventDictionary = @{ + SFAnalyticsPostTime : @([[NSDate date] timeIntervalSince1970] * 1000), + @"events" : events, + }; + + if (![NSJSONSerialization isValidJSONObject:eventDictionary]) { + secemergency("json: final dictionary invalid JSON."); + if (error) { + *error = [NSError errorWithDomain:SupdErrorDomain code:SupdInvalidJSONError + userInfo:@{NSLocalizedDescriptionKey : [NSString localizedStringWithFormat:@"Final dictionary for upload is invalid JSON: %@", eventDictionary]}]; + } + return nil; + } + + return eventDictionary; +} + +- (NSArray *)createChunkedLoggingJSON:(NSArray *)healthSummaries + failures:(NSArray *)failures + error:(NSError **)error +{ + NSError *localError = nil; + size_t baseSize = [self serializedEventSize:healthSummaries error:&localError]; + if (localError != nil) { + secemergency("Unable to serialize health summary JSON"); + if (error) { + *error = localError; + } + return nil; + } + + NSArray *chunkedEvents = [self chunkFailureSet:(self.uploadSizeLimit - baseSize) events:failures error:&localError]; + + NSMutableArray *jsonResults = [[NSMutableArray alloc] init]; + for (NSArray *failureSet in chunkedEvents) { + NSDictionary *eventDictionary = [self createEventDictionary:healthSummaries failures:failureSet error:error]; + if (eventDictionary) { + [jsonResults addObject:eventDictionary]; + } else { + return nil; + } + } + + if ([jsonResults count] == 0) { + NSDictionary *eventDictionary = [self createEventDictionary:healthSummaries failures:nil error:error]; + if (eventDictionary) { + [jsonResults addObject:eventDictionary]; + } else { + return nil; + } + } + + return jsonResults; +} + +- (BOOL)copyEvents:(NSMutableArray **)healthSummaries + failures:(NSMutableArray **)failures + forUpload:(BOOL)upload +participatingClients:(NSMutableArray**)clients + force:(BOOL)force + linkedUUID:(NSUUID *)linkedUUID + error:(NSError**)error +{ + NSMutableArray *localClients = [[NSMutableArray alloc] init]; + NSMutableArray *localHealthSummaries = [[NSMutableArray alloc] init]; + NSMutableArray *localFailures = [[NSMutableArray alloc] init]; + NSMutableArray *hardFailures = [[NSMutableArray alloc] init]; + NSMutableArray *softFailures = [[NSMutableArray alloc] init]; + NSString *ckdeviceID = nil; + NSString *accountID = nil; if (os_variant_has_internal_diagnostics("com.apple.security") && [_internalTopicName isEqualToString:SFAnalyticsTopicKeySync]) { ckdeviceID = [self askSecurityForCKDeviceID]; accountID = accountAltDSID(); } for (SFAnalyticsClient* client in self->_topicClients) { - if (!force && [client requireDeviceAnalytics] && !_isDeviceAnalyticsEnabled()) { - // Client required device analytics, yet the user did not opt in. - secnotice("getLoggingJSON", "Client '%@' requires device analytics yet user did not opt in.", [client name]); - continue; - } - if (!force && [client requireiCloudAnalytics] && !_isiCloudAnalyticsEnabled()) { - // Client required iCloud analytics, yet the user did not opt in. - secnotice("getLoggingJSON", "Client '%@' requires iCloud analytics yet user did not opt in.", [client name]); - continue; - } - - SFAnalyticsSQLiteStore* store = [SFAnalyticsSQLiteStore storeWithPath:client.storePath schema:SFAnalyticsTableSchema]; - - if (upload) { - NSDate* uploadDate = store.uploadDate; - if (!force && uploadDate && [[NSDate date] timeIntervalSinceDate:uploadDate] < _secondsBetweenUploads) { - secnotice("json", "ignoring client '%@' for %@ because last upload too recent: %@", - client.name, _internalTopicName, uploadDate); + @autoreleasepool { + if (!force && [client requireDeviceAnalytics] && !_isDeviceAnalyticsEnabled()) { + // Client required device analytics, yet the user did not opt in. + secnotice("getLoggingJSON", "Client '%@' requires device analytics yet user did not opt in.", [client name]); + continue; + } + if (!force && [client requireiCloudAnalytics] && !_isiCloudAnalyticsEnabled()) { + // Client required iCloud analytics, yet the user did not opt in. + secnotice("getLoggingJSON", "Client '%@' requires iCloud analytics yet user did not opt in.", [client name]); continue; } - if (force) { - secnotice("json", "client '%@' for topic '%@' force-included", client.name, _internalTopicName); - } else { - secnotice("json", "including client '%@' for topic '%@' for upload", client.name, _internalTopicName); - } - [localClients addObject:client]; - } + SFAnalyticsSQLiteStore* store = [SFAnalyticsSQLiteStore storeWithPath:client.storePath schema:SFAnalyticsTableSchema]; - NSMutableDictionary* healthSummary = [self healthSummaryWithName:client.name store:store]; - if (healthSummary) { - if (ckdeviceID) { - healthSummary[SFAnalyticsDeviceID] = ckdeviceID; - } - if (accountID) { - healthSummary[SFAnalyticsAltDSID] = accountID; - } - [uploadRecords addObject:healthSummary]; - } + if (upload) { + NSDate* uploadDate = store.uploadDate; + if (!force && uploadDate && [[NSDate date] timeIntervalSinceDate:uploadDate] < _secondsBetweenUploads) { + secnotice("json", "ignoring client '%@' for %@ because last upload too recent: %@", + client.name, _internalTopicName, uploadDate); + continue; + } - [hardFailures addObject:store.hardFailures]; - [softFailures addObject:store.softFailures]; + if (force) { + secnotice("json", "client '%@' for topic '%@' force-included", client.name, _internalTopicName); + } else { + secnotice("json", "including client '%@' for topic '%@' for upload", client.name, _internalTopicName); + } + [localClients addObject:client]; + } + + NSMutableDictionary* healthSummary = [self healthSummaryWithName:client.name store:store uuid:linkedUUID]; + if (healthSummary) { + if (ckdeviceID) { + healthSummary[SFAnalyticsDeviceID] = ckdeviceID; + } + if (accountID) { + healthSummary[SFAnalyticsAltDSID] = accountID; + } + [localHealthSummaries addObject:healthSummary]; + } + + [hardFailures addObject:store.hardFailures]; + [softFailures addObject:store.softFailures]; + } } if (upload && [localClients count] == 0) { @@ -801,40 +945,93 @@ _isiCloudAnalyticsEnabled() code:-10 userInfo:@{NSLocalizedDescriptionKey : description}]; } - return nil; + return NO; } if (clients) { *clients = localClients; } - [self addFailures:hardFailures toUploadRecords:uploadRecords threshold:_maxEventsToReport/10]; - [self addFailures:softFailures toUploadRecords:uploadRecords threshold:0]; + if (failures) { + [self addFailures:hardFailures toUploadRecords:localFailures threshold:_maxEventsToReport/10 linkedUUID:linkedUUID]; + [self addFailures:softFailures toUploadRecords:localFailures threshold:0 linkedUUID:linkedUUID]; + [*failures addObjectsFromArray:localFailures]; + } - NSDictionary* jsonDict = @{ - SFAnalyticsSplunkPostTime : @([[NSDate date] timeIntervalSince1970] * 1000), - @"events" : uploadRecords - }; + if (healthSummaries) { + [*healthSummaries addObjectsFromArray:localHealthSummaries]; + } - // This check is "belt and suspenders" because we already checked each event separately - if (![NSJSONSerialization isValidJSONObject:jsonDict]) { - secemergency("json: final dictionary invalid JSON. This is terrible!"); + return YES; +} + +- (NSArray *)createChunkedLoggingJSON:(bool)pretty + forUpload:(BOOL)upload + participatingClients:(NSMutableArray**)clients + force:(BOOL)force // supdctl uploads ignore privacy settings and recency + error:(NSError**)error +{ + NSUUID *linkedUUID = [NSUUID UUID]; + NSError *localError = nil; + NSMutableArray *failures = [[NSMutableArray alloc] init]; + NSMutableArray *healthSummaries = [[NSMutableArray alloc] init]; + BOOL copied = [self copyEvents:&healthSummaries + failures:&failures + forUpload:upload + participatingClients:clients + force:force + linkedUUID:linkedUUID + error:&localError]; + if (!copied || localError) { if (error) { - *error = [NSError errorWithDomain:SupdErrorDomain code:SupdInvalidJSONError - userInfo:@{NSLocalizedDescriptionKey : [NSString localizedStringWithFormat:@"Final dictionary for upload is invalid JSON: %@", jsonDict]}]; + *error = localError; } return nil; } - NSData *json = [NSJSONSerialization dataWithJSONObject:jsonDict - options:(pretty ? NSJSONWritingPrettyPrinted : 0) - error:&localError]; - - if (error) { - *error = localError; + // Trim failures to the max count, based on health summary count + if ([failures count] > (_maxEventsToReport - [healthSummaries count])) { + NSRange range; + range.location = 0; + range.length = _maxEventsToReport - [healthSummaries count]; + failures = [[failures subarrayWithRange:range] mutableCopy]; } - return json; + return [self createChunkedLoggingJSON:healthSummaries failures:failures error:error]; +} + +- (NSDictionary *)createLoggingJSON:(bool)pretty + forUpload:(BOOL)upload + participatingClients:(NSMutableArray**)clients + force:(BOOL)force // supdctl uploads ignore privacy settings and recency + error:(NSError**)error +{ + NSError *localError = nil; + NSMutableArray *failures = [[NSMutableArray alloc] init]; + NSMutableArray *healthSummaries = [[NSMutableArray alloc] init]; + BOOL copied = [self copyEvents:&healthSummaries + failures:&failures + forUpload:upload + participatingClients:clients + force:force + linkedUUID:nil + error:&localError]; + if (!copied || localError) { + if (error) { + *error = localError; + } + return nil; + } + + // Trim failures to the max count, based on health summary count + if ([failures count] > (_maxEventsToReport - [healthSummaries count])) { + NSRange range; + range.location = 0; + range.length = _maxEventsToReport - [healthSummaries count]; + failures = [[failures subarrayWithRange:range] mutableCopy]; + } + + return [self createEventDictionary:healthSummaries failures:failures error:error]; } // Is at least one client eligible for data collection based on user consent? Otherwise callers should NOT reach off-device. @@ -1062,33 +1259,52 @@ _isiCloudAnalyticsEnabled() return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)@"Analytics/localkeychain.db") path]; } -+ (NSString*)databasePathForTrustdHealth -{ -#if TARGET_OS_IPHONE - return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/trustd_health_analytics.db")) path]; -#else - return [(__bridge_transfer NSURL*)SecCopyURLForFileInUserCacheDirectory(CFSTR("Analytics/trustd_health_analytics.db")) path]; -#endif -} - + (NSString*)databasePathForTrust { #if TARGET_OS_IPHONE return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/trust_analytics.db")) path]; #else - return [(__bridge_transfer NSURL*)SecCopyURLForFileInUserCacheDirectory(CFSTR("Analytics/trust_analytics.db")) path]; + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:@"trust_analytics"]; #endif } -+ (NSString*)databasePathForTLS +#if TARGET_OS_OSX +#define TRUSTD_ROLE_ACCOUNT 282 + ++ (NSUUID *)trustdUUID +{ + uuid_t rootUuid; + int ret = mbr_uid_to_uuid(282, rootUuid); + if (ret != 0) { + return nil; + } + return [[NSUUID alloc] initWithUUIDBytes:rootUuid]; +} +#endif + +#if TARGET_OS_OSX ++ (NSString*)databasePathForRootTrust +{ + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:@"trust_analytics" uuid:[SFAnalyticsTopic trustdUUID]]; +} +#endif + ++ (NSString*)databasePathForNetworking { #if TARGET_OS_IPHONE - return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/TLS_analytics.db")) path]; + return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/networking_analytics.db")) path]; #else - return [(__bridge_transfer NSURL*)SecCopyURLForFileInUserCacheDirectory(CFSTR("Analytics/TLS_analytics.db")) path]; + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:@"networking_analytics"]; #endif } +#if TARGET_OS_OSX ++ (NSString*)databasePathForRootNetworking +{ + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:@"networking_analytics" uuid:[SFAnalyticsTopic trustdUUID]]; +} +#endif + + (NSString*)databasePathForSignIn { return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/signin_metrics.db")) path]; @@ -1108,6 +1324,7 @@ _isiCloudAnalyticsEnabled() @interface supd () @property NSDictionary *topicsSamplingRates; +@property NSXPCConnection *connection; @end @implementation supd @@ -1123,23 +1340,6 @@ _isiCloudAnalyticsEnabled() _analyticsTopics = [NSArray arrayWithArray:topics]; } -+ (void)instantiate { - [supd instance]; -} - -+ (instancetype)instance { - if (!_supdInstance) { - _supdInstance = [self new]; - } - return _supdInstance; -} - -// Use this for testing to get rid of any state -+ (void)removeInstance { - _supdInstance = nil; -} - - static NSString *SystemTrustStorePath = @"/System/Library/Security/Certificates.bundle"; static NSString *AnalyticsSamplingRatesFilename = @"AnalyticsSamplingRates"; static NSString *ContentVersionKey = @"MobileAssetContentVersion"; @@ -1186,8 +1386,8 @@ static bool ShouldInitializeWithAsset(NSBundle *trustStoreBundle, NSURL *directo - (void)setupSamplingRates { NSBundle *trustStoreBundle = [NSBundle bundleWithPath:SystemTrustStorePath]; - NSURL *keychainsDirectory = CFBridgingRelease(SecCopyURLForFileInSystemKeychainDirectory(nil)); - NSURL *directory = [keychainsDirectory URLByAppendingPathComponent:@"SupplementalsAssets/" isDirectory:YES]; + NSURL *protectedDirectory = CFBridgingRelease(SecCopyURLForFileInProtectedDirectory(CFSTR("trustd/"))); + NSURL *directory = [protectedDirectory URLByAppendingPathComponent:@"SupplementalsAssets/" isDirectory:YES]; NSDictionary *analyticsSamplingRates = nil; if (ShouldInitializeWithAsset(trustStoreBundle, directory)) { @@ -1211,29 +1411,32 @@ static bool ShouldInitializeWithAsset(NSBundle *trustStoreBundle, NSURL *directo } } -- (instancetype)initWithReporter:(SFAnalyticsReporter *)reporter +- (instancetype)initWithConnection:(NSXPCConnection *)connection reporter:(SFAnalyticsReporter *)reporter { - if (self = [super init]) { + if ((self = [super init])) { + _connection = connection; + _reporter = reporter; [self setupSamplingRates]; [self setupTopics]; - _reporter = reporter; - xpc_activity_register("com.apple.securityuploadd.triggerupload", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { - xpc_activity_state_t activityState = xpc_activity_get_state(activity); - secnotice("supd", "hit xpc activity trigger, state: %ld", activityState); - if (activityState == XPC_ACTIVITY_STATE_RUN) { - // Run our regularly scheduled scan - [self performRegularlyScheduledUpload]; - } + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + xpc_activity_register("com.apple.securityuploadd.triggerupload", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { + xpc_activity_state_t activityState = xpc_activity_get_state(activity); + secnotice("supd", "hit xpc activity trigger, state: %ld", activityState); + if (activityState == XPC_ACTIVITY_STATE_RUN) { + // Run our regularly scheduled scan + [self performRegularlyScheduledUpload]; + } + }); }); } - return self; } -- (instancetype)init { +- (instancetype)initWithConnection:(NSXPCConnection *)connection { SFAnalyticsReporter *reporter = [[SFAnalyticsReporter alloc] init]; - return [self initWithReporter:reporter]; + return [self initWithConnection:connection reporter:reporter]; } - (void)sendNotificationForOncePerReportSamplers @@ -1252,6 +1455,30 @@ static bool ShouldInitializeWithAsset(NSBundle *trustStoreBundle, NSURL *directo } } +- (NSArray *)serializeLoggingEvents:(NSArray *)events + error:(NSError **)error +{ + if (!events) { + return nil; + } + + NSMutableArray *serializedEvents = [[NSMutableArray alloc] init]; + for (NSDictionary *event in events) { + NSError *serializationError = nil; + NSData* serializedEvent = [NSJSONSerialization dataWithJSONObject:event + options:0 + error:&serializationError]; + if (serializedEvent && !serializationError) { + [serializedEvents addObject:serializedEvent]; + } else if (error) { + *error = serializationError; + return nil; + } + } + + return serializedEvents; +} + - (BOOL)uploadAnalyticsWithError:(NSError**)error force:(BOOL)force { [self sendNotificationForOncePerReportSamplers]; @@ -1272,9 +1499,32 @@ static bool ShouldInitializeWithAsset(NSBundle *trustStoreBundle, NSURL *directo } NSMutableArray* clients = [NSMutableArray new]; - NSData* json = [topic getLoggingJSON:false forUpload:YES participatingClients:&clients force:force error:&localError]; - if (json) { - if ([topic isSampledUpload]) { + NSArray *jsonEvents = [topic createChunkedLoggingJSON:false forUpload:YES participatingClients:&clients force:force error:&localError]; + if (!jsonEvents || localError) { + if ([[localError domain] isEqualToString:SupdErrorDomain] && [localError code] == SupdInvalidJSONError) { + // Pretend this was a success because at least we'll get rid of bad data. + // If someone keeps logging bad data and we only catch it here then + // this causes sustained data loss for the entire topic. + [topic updateUploadDateForClients:clients date:[NSDate date] clearData:YES]; + } + secerror("upload: failed to create chunked log events for logging topic %@: %@", [topic internalTopicName], localError); + continue; + } + + NSArray *serializedEvents = [self serializeLoggingEvents:jsonEvents error:&localError]; + if (!serializedEvents || localError) { + if ([[localError domain] isEqualToString:SupdErrorDomain] && [localError code] == SupdInvalidJSONError) { + // Pretend this was a success because at least we'll get rid of bad data. + // If someone keeps logging bad data and we only catch it here then + // this causes sustained data loss for the entire topic. + [topic updateUploadDateForClients:clients date:[NSDate date] clearData:YES]; + } + secerror("upload: failed to serialized chunked log events for logging topic %@: %@", [topic internalTopicName], localError); + continue; + } + + if ([topic isSampledUpload]) { + for (NSData *json in serializedEvents) { if (![self->_reporter saveReport:json fileName:[topic internalTopicName]]) { secerror("upload: failed to write analytics data to log"); } @@ -1285,20 +1535,12 @@ static bool ShouldInitializeWithAsset(NSBundle *trustStoreBundle, NSURL *directo } else { secerror("upload: Failed to post JSON for %@: %@", [topic internalTopicName], localError); } - } else { - /* If we didn't sample this report, update date to prevent trying to upload again sooner - * than we should. Clear data so that per-day calculations remain consistent. */ - secnotice("upload", "skipping unsampled upload for %@ and clearing data", [topic internalTopicName]); - [topic updateUploadDateForClients:clients date:[NSDate date] clearData:YES]; } } else { - if ([[localError domain] isEqualToString:SupdErrorDomain] && [localError code] == SupdInvalidJSONError) { - // Pretend this was a success because at least we'll get rid of bad data. - // If someone keeps logging bad data and we only catch it here then - // this causes sustained data loss for the entire topic. - [topic updateUploadDateForClients:clients date:[NSDate date] clearData:YES]; - } - secerror("upload: failed to get logging JSON for topic %@: %@", [topic internalTopicName], localError); + /* If we didn't sample this report, update date to prevent trying to upload again sooner + * than we should. Clear data so that per-day calculations remain consistent. */ + secnotice("upload", "skipping unsampled upload for %@ and clearing data", [topic internalTopicName]); + [topic updateUploadDateForClients:clients date:[NSDate date] clearData:YES]; } } if (error && localError) { @@ -1358,32 +1600,6 @@ static bool ShouldInitializeWithAsset(NSBundle *trustStoreBundle, NSURL *directo return sysdiagnose; } -- (void)setUploadDateWith:(NSDate *)date reply:(void (^)(BOOL, NSError*))reply -{ - for (SFAnalyticsTopic* topic in _analyticsTopics) { - [topic updateUploadDateForClients:topic.topicClients date:date clearData:NO]; - } - reply(YES, nil); -} - -- (void)clientStatus:(void (^)(NSDictionary *, NSError *))reply -{ - NSMutableDictionary *info = [NSMutableDictionary dictionary]; - for (SFAnalyticsTopic* topic in _analyticsTopics) { - for (SFAnalyticsClient *client in topic.topicClients) { - SFAnalyticsSQLiteStore* store = [SFAnalyticsSQLiteStore storeWithPath:client.storePath schema:SFAnalyticsTableSchema]; - - NSMutableDictionary *clientInfo = [NSMutableDictionary dictionary]; - clientInfo[@"uploadDate"] = store.uploadDate; - info[client.name] = clientInfo; - } - } - - reply(info, nil); -} - - - - (NSString*)stringForEventClass:(SFAnalyticsEventClass)eventClass { if (eventClass == SFAnalyticsEventClassNote) { @@ -1404,28 +1620,88 @@ static bool ShouldInitializeWithAsset(NSBundle *trustStoreBundle, NSURL *directo } // MARK: XPC Procotol Handlers - -- (void)getSysdiagnoseDumpWithReply:(void (^)(NSString*))reply { - reply([self getSysdiagnoseDump]); +- (BOOL)checkSupdEntitlement { + NSNumber *supdEntitlement = [self.connection valueForEntitlement:@"com.apple.private.securityuploadd"]; + if (![supdEntitlement isKindOfClass:[NSNumber class]] || ![supdEntitlement boolValue]) { + return NO; + } + return YES; } -- (void)getLoggingJSON:(bool)pretty topic:(NSString *)topicName reply:(void (^)(NSData*, NSError*))reply { - secnotice("rpcGetLoggingJSON", "Building a JSON blob resembling the one we would have uploaded"); +- (void)getSysdiagnoseDumpWithReply:(void (^)(NSString*))reply { + if ([self checkSupdEntitlement]) { + reply([self getSysdiagnoseDump]); + } else { + reply(@"client not entitled"); + } +} + +- (void)createLoggingJSON:(bool)pretty topic:(NSString *)topicName reply:(void (^)(NSData *, NSError*))reply { + if (![self checkSupdEntitlement]) { + NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecMissingEntitlement userInfo:nil]; + reply(nil, error); + return; + } + + secnotice("rpcCreateLoggingJSON", "Building a JSON blob resembling the one we would have uploaded"); NSError* error = nil; [self sendNotificationForOncePerReportSamplers]; - NSData* json = nil; + NSDictionary *eventDictionary = nil; for (SFAnalyticsTopic* topic in self->_analyticsTopics) { if ([topic.internalTopicName isEqualToString:topicName]) { - json = [topic getLoggingJSON:pretty forUpload:NO participatingClients:nil force:!runningTests error:&error]; + eventDictionary = [topic createLoggingJSON:pretty forUpload:NO participatingClients:nil force:!runningTests error:&error]; } } - if (!json) { + + NSData *data = nil; + if (!eventDictionary) { secerror("Unable to obtain JSON: %@", error); + } else { + data = [NSJSONSerialization dataWithJSONObject:eventDictionary + options:(pretty ? NSJSONWritingPrettyPrinted : 0) + error:&error]; } - reply(json, error); + + reply(data, error); +} + +- (void)createChunkedLoggingJSON:(bool)pretty topic:(NSString *)topicName reply:(void (^)(NSData *, NSError*))reply +{ + if (![self checkSupdEntitlement]) { + NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecMissingEntitlement userInfo:nil]; + reply(nil, error); + return; + } + + secnotice("rpcCreateChunkedLoggingJSON", "Building an array of JSON blobs resembling the one we would have uploaded"); + NSError* error = nil; + [self sendNotificationForOncePerReportSamplers]; + NSArray *events = nil; + for (SFAnalyticsTopic* topic in self->_analyticsTopics) { + if ([topic.internalTopicName isEqualToString:topicName]) { + events = [topic createChunkedLoggingJSON:pretty forUpload:NO participatingClients:nil force:!runningTests error:&error]; + } + } + + NSData *data = nil; + if (!events) { + secerror("Unable to obtain JSON: %@", error); + } else { + data = [NSJSONSerialization dataWithJSONObject:events + options:(pretty ? NSJSONWritingPrettyPrinted : 0) + error:&error]; + } + + reply(data, error); } - (void)forceUploadWithReply:(void (^)(BOOL, NSError*))reply { + if (![self checkSupdEntitlement]) { + NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecMissingEntitlement userInfo:nil]; + reply(NO, error); + return; + } + secnotice("upload", "Performing upload in response to rpc message"); NSError* error = nil; BOOL result = [self uploadAnalyticsWithError:&error force:YES]; @@ -1433,6 +1709,55 @@ static bool ShouldInitializeWithAsset(NSBundle *trustStoreBundle, NSURL *directo reply(result, error); } +- (void)setUploadDateWith:(NSDate *)date reply:(void (^)(BOOL, NSError*))reply +{ + if (![self checkSupdEntitlement]) { + NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecMissingEntitlement userInfo:nil]; + reply(NO, error); + return; + } + + for (SFAnalyticsTopic* topic in _analyticsTopics) { + [topic updateUploadDateForClients:topic.topicClients date:date clearData:NO]; + } + reply(YES, nil); +} + +- (void)clientStatus:(void (^)(NSDictionary *, NSError *))reply +{ + if (![self checkSupdEntitlement]) { + NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecMissingEntitlement userInfo:nil]; + reply(nil, error); + return; + } + + NSMutableDictionary *info = [NSMutableDictionary dictionary]; + for (SFAnalyticsTopic* topic in _analyticsTopics) { + for (SFAnalyticsClient *client in topic.topicClients) { + SFAnalyticsSQLiteStore* store = [SFAnalyticsSQLiteStore storeWithPath:client.storePath schema:SFAnalyticsTableSchema]; + + NSMutableDictionary *clientInfo = [NSMutableDictionary dictionary]; + clientInfo[@"uploadDate"] = store.uploadDate; + info[client.name] = clientInfo; + } + } + + reply(info, nil); +} + +- (void)fixFiles:(void (^)(BOOL, NSError*))reply +{ + if (![[self.connection valueForEntitlement:@"com.apple.private.trustd.FileHelp"] boolValue]) { + reply(NO, [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecMissingEntitlement userInfo:nil]); + } +#if TARGET_OS_IPHONE + TrustdFileHelper *helper = [[TrustdFileHelper alloc] init]; + [helper fixFiles:reply]; +#else + reply(NO, [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]); +#endif +} + @end #endif // !TARGET_OS_SIMULATOR diff --git a/supd/supdProtocol.h b/supd/supdProtocol.h index 98371ac2..b190a34b 100644 --- a/supd/supdProtocol.h +++ b/supd/supdProtocol.h @@ -25,7 +25,8 @@ @protocol supdProtocol - (void)getSysdiagnoseDumpWithReply:(void (^)(NSString*))reply; -- (void)getLoggingJSON:(bool)pretty topic:(NSString *)topicName reply:(void (^)(NSData*, NSError*))reply; +- (void)createLoggingJSON:(bool)pretty topic:(NSString *)topicName reply:(void (^)(NSData *, NSError*))reply; +- (void)createChunkedLoggingJSON:(bool)pretty topic:(NSString *)topicName reply:(void (^)(NSData *, NSError*))reply; - (void)forceUploadWithReply:(void (^)(BOOL, NSError*))reply; - (void)setUploadDateWith:(NSDate *)date reply:(void (^)(BOOL, NSError*))reply; - (void)clientStatus:(void (^)(NSDictionary *, NSError *))reply; diff --git a/supdctl/main.m b/supdctl/main.m index 3c920bdf..5ce0e43d 100644 --- a/supdctl/main.m +++ b/supdctl/main.m @@ -30,8 +30,6 @@ /* Internal Topic Names */ NSString* const SFAnalyticsTopicKeySync = @"KeySyncTopic"; -NSString* const SFAnalyticsTopicTrust = @"TrustTopic"; -NSString* const SFAnalyticsTopicTransparency = @"TransparencyTopic"; static void nsprintf(NSString *fmt, ...) NS_FORMAT_FUNCTION(1, 2); static void nsprintf(NSString *fmt, ...) @@ -73,7 +71,7 @@ static void getSysdiagnoseDump(void) [connection invalidate]; } -static void getLoggingJSON(char *topicName) +static void createLoggingJSON(char *topicName) { NSString *topic = topicName ? [NSString stringWithUTF8String:topicName] : SFAnalyticsTopicKeySync; dispatch_semaphore_t sema = dispatch_semaphore_create(0); @@ -81,7 +79,31 @@ static void getLoggingJSON(char *topicName) [[connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { nsprintf(@"Could not communicate with supd: %@", error); dispatch_semaphore_signal(sema); - }] getLoggingJSON:YES topic:topic reply:^(NSData* data, NSError* error) { + }] createLoggingJSON:YES topic:topic reply:^(NSData* data, NSError* error) { + if (data) { + // Success! Only print the JSON blob to make output easier to parse + nsprintf(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); + } else { + nsprintf(@"supd gave us an error: %@", error); + } + dispatch_semaphore_signal(sema); + }]; + + if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 20)) != 0) { + printf("\n\nError: timed out waiting for response from supd\n"); + } + [connection invalidate]; +} + +static void createChunkedLoggingJSON(char *topicName) +{ + NSString *topic = topicName ? [NSString stringWithUTF8String:topicName] : SFAnalyticsTopicKeySync; + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + NSXPCConnection* connection = getConnection(); + [[connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + nsprintf(@"Could not communicate with supd: %@", error); + dispatch_semaphore_signal(sema); + }] createChunkedLoggingJSON:YES topic:topic reply:^(NSData* data, NSError* error) { if (data) { // Success! Only print the JSON blob to make output easier to parse nsprintf(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); @@ -168,6 +190,7 @@ forceOldUploadDate(void) static int forceUpload = false; static int getJSON = false; +static int getChunkedJSON = false; static int getSysdiagnose = false; static int getInfo = false; static int setOldUploadDate = false; @@ -177,9 +200,9 @@ int main(int argc, char **argv) { static struct argument options[] = { { .shortname='t', .longname="topicName", .argument=&topicName, .description="Operate on a non-default topic"}, - { .command="sysdiagnose", .flag=&getSysdiagnose, .flagval=true, .description="Retrieve the current sysdiagnose dump for security analytics"}, { .command="get", .flag=&getJSON, .flagval=true, .description="Get the JSON blob we would upload to the server if an upload were due"}, + { .command="getChunked", .flag=&getChunkedJSON, .flagval=true, .description="Chunk the JSON blob"}, { .command="upload", .flag=&forceUpload, .flagval=true, .description="Force an upload of analytics data to server (ignoring privacy settings)"}, { .command="info", .flag=&getInfo, .flagval=true, .description="Request info about clients"}, { .command="set-old-upload-date", .flag=&setOldUploadDate, .flagval=true, .description="Clear last upload date"}, @@ -206,7 +229,9 @@ int main(int argc, char **argv) if (forceUpload) { forceUploadAnalytics(); } else if (getJSON) { - getLoggingJSON(topicName); + createLoggingJSON(topicName); + } else if (getChunkedJSON) { + createChunkedLoggingJSON(topicName); } else if (getSysdiagnose) { getSysdiagnoseDump(); } else if (getInfo) { diff --git a/tests/SecDbBackupTests/Entitlements.plist b/tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist similarity index 93% rename from tests/SecDbBackupTests/Entitlements.plist rename to tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist index f63472fe..7f63b7f3 100644 --- a/tests/SecDbBackupTests/Entitlements.plist +++ b/tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist @@ -28,5 +28,7 @@ SecDbBackupManager-UnitTests + com.apple.private.security.storage.Keychains + diff --git a/tests/SecDbBackupTests/SecDbBackupTests.m b/tests/SecDbBackupTests/SecDbBackupTests.m index cb8d0e72..ad5f3e41 100644 --- a/tests/SecDbBackupTests/SecDbBackupTests.m +++ b/tests/SecDbBackupTests/SecDbBackupTests.m @@ -1,11 +1,4 @@ -// -// SecDbBackupTests.m -// Security -// -// Created by Wouter de Groot on 2018-12-12. -// - -#import +#import "SecDbBackupTestsBase.h" #import "keychain/securityd/SecDbBackupManager.h" #if !SECDB_BACKUPS_ENABLED @@ -20,77 +13,29 @@ #import "keychain/securityd/SecDbBackupManager_Internal.h" -#import "CKKS.h" -#import -#import "spi.h" -#import "SecItemServer.h" + #import #include "utilities/der_plist.h" #include -@interface SecDbBackupTests : XCTestCase +@interface SecDbBackupTests : SecDbBackupTestsBase @end SecDbBackupManager* _manager; -NSString* _uuidstring; -@implementation SecDbBackupTests { - NSString* _testHomeDirectory; -} - -static int testCheckV12DevEnabled(void) { - return 1; -} +@implementation SecDbBackupTests + (void)setUp { [super setUp]; - checkV12DevEnabled = testCheckV12DevEnabled; - SecCKKSDisable(); -#if OCTAGON - SecCKKSTestSetDisableSOS(true); -#endif - _uuidstring = [[NSUUID UUID] UUIDString]; } + (void)tearDown { - SetCustomHomeURL(NULL); - SecKeychainDbReset(NULL); - resetCheckV12DevEnabled(); + [super tearDown]; } - (void)setUp { [super setUp]; - - NSString* testName = [self.name componentsSeparatedByString:@" "][1]; - testName = [testName stringByReplacingOccurrencesOfString:@"]" withString:@""]; - secnotice("secdbbackuptest", "Beginning test %@", testName); - - // Make a new fake keychain - NSError* error; - _testHomeDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@/%@/", _uuidstring, testName]]; - - NSLog(@"%@", _testHomeDirectory); - - [[NSFileManager defaultManager] createDirectoryAtPath:_testHomeDirectory - withIntermediateDirectories:YES - attributes:nil - error:&error]; - // No XCTAssert in class method - if (error) { - NSLog(@"Could not make directory at %@", _testHomeDirectory); - } - - SetCustomHomeURLString((__bridge CFStringRef)_testHomeDirectory); - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - securityd_init(NULL); - }); - SecKeychainDbReset(NULL); - - // Actually load the database. - kc_with_dbt(true, NULL, ^bool (SecDbConnectionRef dbt) { return false; }); - [SecDbBackupManager resetManager]; _manager = [SecDbBackupManager manager]; } @@ -359,9 +304,9 @@ static int testCheckV12DevEnabled(void) { void* aksunwrappedbytes = NULL; size_t aksunwrappedlen = 0; XCTAssertEqual(aks_ref_key_decrypt(refkey, NULL, 0, kcsk.aksWrappedKey.bytes, kcsk.aksWrappedKey.length, &aksunwrappedbytes, &aksunwrappedlen), kAKSReturnSuccess, @"Successfully unwrapped KCSK private key"); - SFECKeyPair* aksunwrapped = [_manager ECKeyPairFromDerBytes:aksunwrappedbytes length:aksunwrappedlen error:&error]; + SFECKeyPair* aksunwrapped = [_manager getECKeyPairFromDERBytes:aksunwrappedbytes length:aksunwrappedlen error:&error]; XCTAssertNil(error, @"No error reconstructing AKS backup key"); - XCTAssert(aksunwrapped, @"Got key from ECKeyPairFromDerBytes"); + XCTAssert(aksunwrapped, @"Got key from getECKeyPairFromDERBytes"); aks_ref_key_free(&refkey); // Verify backupWrappedKey @@ -428,7 +373,7 @@ static int testCheckV12DevEnabled(void) { - (void)testWrapItemKey { SFAESKey* randomKey = [self randomAESKey]; NSError* error; - SecDbBackupWrappedItemKey* itemKey = [_manager wrapItemKey:randomKey forKeyclass:key_class_akpu error:&error]; + SecDbBackupWrappedKey* itemKey = [_manager wrapItemKey:randomKey forKeyclass:key_class_akpu error:&error]; XCTAssertNil(itemKey, @"Do not expect result wrapping to akpu"); XCTAssertEqual(error.code, SecDbBackupInvalidArgument, @"Expect invalid argument error wrapping to akpu"); @@ -437,7 +382,22 @@ static int testCheckV12DevEnabled(void) { XCTAssertNil(error, @"No error wrapping item to ak"); XCTAssertEqualObjects(itemKey.baguuid, _manager.bagIdentity.baguuid, @"item wrapped under expected bag uuid"); - // TODO: implement decryption and test it here + // TODO: implement decryption and test it +} + +- (void)testWrapMetadataKey { + SFAESKey* randomKey = [self randomAESKey]; + NSError* error; + SecDbBackupWrappedKey* itemKey = [_manager wrapMetadataKey:randomKey forKeyclass:key_class_akpu error:&error]; + XCTAssertNil(itemKey, @"Do not expect result wrapping to akpu"); + XCTAssertEqual(error.code, SecDbBackupInvalidArgument, @"Expect invalid argument error wrapping to akpu"); + + error = nil; + itemKey = [_manager wrapMetadataKey:randomKey forKeyclass:key_class_ak error:&error]; + XCTAssertNil(error, @"No error wrapping item to ak"); + XCTAssertEqualObjects(itemKey.baguuid, _manager.bagIdentity.baguuid, @"item wrapped under expected bag uuid"); + + // TODO: implement decryption and test it } // Does not inspect the item because it's encrypted and no code yet built to do recovery. diff --git a/tests/SecDbBackupTests/SecDbBackupTests.plist b/tests/SecDbBackupTests/SecDbBackupTests.plist deleted file mode 100644 index 817e23d9..00000000 --- a/tests/SecDbBackupTests/SecDbBackupTests.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - - BATSConfigVersion - 0.1.0 - Project - Security - Tests - - - TestName - SecDbBackupTests - WorkingDirectory - /AppleInternal/XCTests/com.apple.security/ - ShowSubtestResults - - Timeout - 1200 - Command - - BATS_XCTEST_CMD SecDbBackupTests.xctest - - - - - diff --git a/tests/SecDbBackupTests/SecDbBackupTestsBase.h b/tests/SecDbBackupTests/SecDbBackupTestsBase.h new file mode 100644 index 00000000..c356c5ed --- /dev/null +++ b/tests/SecDbBackupTests/SecDbBackupTestsBase.h @@ -0,0 +1,19 @@ +#ifndef SecDbBackupTestsBase_h +#define SecDbBackupTestsBase_h + +#import + +// This isn't inheritance-based data hiding, this whole class is for convenience building tests +#import "keychain/securityd/CheckV12DevEnabled.h" +#import "CKKS.h" +#import +#import "spi.h" +#import "SecItemServer.h" + +@interface SecDbBackupTestsBase : XCTestCase + ++ (void)setV12Development:(BOOL)newState; + +@end + +#endif /* SecDbBackupTestsBase_h */ diff --git a/tests/SecDbBackupTests/SecDbBackupTestsBase.m b/tests/SecDbBackupTests/SecDbBackupTestsBase.m new file mode 100644 index 00000000..58f6e675 --- /dev/null +++ b/tests/SecDbBackupTests/SecDbBackupTestsBase.m @@ -0,0 +1,74 @@ +#import "SecDbBackupTestsBase.h" + +static int checkV12DevEnabledOn(void) { + return 1; +} + +static int checkV12DevEnabledOff(void) { + return 0; +} + +NSString* _uuidstring; + +@implementation SecDbBackupTestsBase { + NSString* _testHomeDirectory; +} + ++ (void)setV12Development:(BOOL)newState { + if (newState) { + checkV12DevEnabled = checkV12DevEnabledOn; + } else { + checkV12DevEnabled = checkV12DevEnabledOff; + } +} + ++ (void)setUp { + [super setUp]; + checkV12DevEnabled = checkV12DevEnabledOn; + SecCKKSDisable(); +#if OCTAGON + SecCKKSTestSetDisableSOS(true); +#endif + _uuidstring = [[NSUUID UUID] UUIDString]; +} + +- (void)setUp { + NSString* testName = [self.name componentsSeparatedByString:@" "][1]; + testName = [testName stringByReplacingOccurrencesOfString:@"]" withString:@""]; + secnotice("secdbbackuptest", "Beginning test %@", testName); + + // Make a new fake keychain + NSError* error; + _testHomeDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@/%@/", _uuidstring, testName]]; + + NSLog(@"%@", _testHomeDirectory); + + [[NSFileManager defaultManager] createDirectoryAtPath:_testHomeDirectory + withIntermediateDirectories:YES + attributes:nil + error:&error]; + + XCTAssertNil(error, "Could not make directory at %@", _testHomeDirectory); + + SecSetCustomHomeURLString((__bridge CFStringRef)_testHomeDirectory); + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + securityd_init(NULL); + }); + SecKeychainDbReset(NULL); + + // Actually load the database. + kc_with_dbt(true, NULL, ^bool (SecDbConnectionRef dbt) { return false; }); +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + ++ (void)tearDown { + SecSetCustomHomeURL(NULL); + SecKeychainDbReset(NULL); + resetCheckV12DevEnabled(); +} + +@end diff --git a/tests/SecLegacyCodeRegressions/Info.plist b/tests/SecLegacyCodeRegressions/Info.plist new file mode 100644 index 00000000..64d65ca4 --- /dev/null +++ b/tests/SecLegacyCodeRegressions/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/tests/SecLegacyCodeRegressions/legacyCodeRegressions.mm b/tests/SecLegacyCodeRegressions/legacyCodeRegressions.mm new file mode 100644 index 00000000..aa45703c --- /dev/null +++ b/tests/SecLegacyCodeRegressions/legacyCodeRegressions.mm @@ -0,0 +1,30 @@ +// DANGER Objective C++ + + +#import +#include + +struct ThreadTestClass : public Thread { + XCTestExpectation *expectation; + + ThreadTestClass(XCTestExpectation *e): Thread("test"), expectation(e) { } + void threadAction() { + [expectation fulfill]; + } +}; + +@interface legacyCodeRegressions : XCTestCase +@end + +@implementation legacyCodeRegressions + +- (void)testThread { + XCTestExpectation *e = [self expectationWithDescription:@"wait"]; + + auto t = new ThreadTestClass(e); + t->threadRun(); + [self waitForExpectations:@[e] timeout:10.0]; + delete t; +} + +@end diff --git a/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.h b/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.h new file mode 100644 index 00000000..25b7f009 --- /dev/null +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.h @@ -0,0 +1,16 @@ +#import + +#if TARGET_OS_OSX + +#import +@interface AppDelegate : NSObject +@end + +#else + +#import +@interface AppDelegate : UIResponder +@property (strong, nonatomic) UIWindow *window; +@end + +#endif diff --git a/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.m b/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.m new file mode 100644 index 00000000..febafd36 --- /dev/null +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.m @@ -0,0 +1,25 @@ +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + +#if TARGET_OS_OSX + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {} +- (void)applicationWillTerminate:(NSNotification *)aNotification {} + +#else + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {return YES;} +- (void)applicationWillResignActive:(UIApplication *)application {} +- (void)applicationDidEnterBackground:(UIApplication *)application {} +- (void)applicationWillEnterForeground:(UIApplication *)application {} +- (void)applicationDidBecomeActive:(UIApplication *)application {} +- (void)applicationWillTerminate:(UIApplication *)application {} + +#endif + +@end diff --git a/KeychainEntitledTestApp_mac/Assets.xcassets/AppIcon.appiconset/Contents.json b/tests/TestHostBinaries/KeychainEntitledTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from KeychainEntitledTestApp_mac/Assets.xcassets/AppIcon.appiconset/Contents.json rename to tests/TestHostBinaries/KeychainEntitledTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/KeychainEntitledTestApp_mac/Info.plist b/tests/TestHostBinaries/KeychainEntitledTestApp/Info.plist similarity index 89% rename from KeychainEntitledTestApp_mac/Info.plist rename to tests/TestHostBinaries/KeychainEntitledTestApp/Info.plist index 8a4ebbf1..5315cf87 100644 --- a/KeychainEntitledTestApp_mac/Info.plist +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/Info.plist @@ -20,9 +20,14 @@ 1.0 CFBundleVersion 1 + UIRequiresFullScreen + +#import +#if TARGET_OS_OSX LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSPrincipalClass NSApplication +#endif diff --git a/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.h b/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.h new file mode 100644 index 00000000..8f765126 --- /dev/null +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.h @@ -0,0 +1,15 @@ +#import + +#if TARGET_OS_OSX + +#import +@interface ViewController : NSViewController +@end + +#else + +#import +@interface ViewController : UIViewController +@end + +#endif diff --git a/KeychainEntitledTestApp_mac/ViewController.m b/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.m similarity index 50% rename from KeychainEntitledTestApp_mac/ViewController.m rename to tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.m index 452e7570..ab623ad2 100644 --- a/KeychainEntitledTestApp_mac/ViewController.m +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.m @@ -1,27 +1,25 @@ -// -// ViewController.m -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - #import "ViewController.h" -@implementation ViewController +#if TARGET_OS_OSX +@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; - - // Do any additional setup after loading the view. } - - - (void)setRepresentedObject:(id)representedObject { [super setRepresentedObject:representedObject]; - - // Update the view, if already loaded. } - - @end + +#else + +@implementation ViewController +- (void)viewDidLoad { + [super viewDidLoad]; +} +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + } +@end + +#endif diff --git a/KeychainEntitledTestApp_ios/main.m b/tests/TestHostBinaries/KeychainEntitledTestApp/main.m similarity index 54% rename from KeychainEntitledTestApp_ios/main.m rename to tests/TestHostBinaries/KeychainEntitledTestApp/main.m index d553ece5..80e84daa 100644 --- a/KeychainEntitledTestApp_ios/main.m +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/main.m @@ -1,10 +1,14 @@ -// -// main.m -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// +#import + +#if TARGET_OS_OSX + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} + +#else #import #import "AppDelegate.h" @@ -14,3 +18,5 @@ int main(int argc, char * argv[]) { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } + +#endif diff --git a/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist b/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements similarity index 65% rename from keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist rename to tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements index 46c3d41e..8e213a9f 100644 --- a/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist +++ b/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements @@ -22,11 +22,26 @@ aps-environment serverPreferred - keychain-access-groups + keychain-access-groups com.apple.security.ckks + SecDbBackupManager-UnitTests keychain-cloud-circle + com.apple.security.app-sandbox + + com.apple.security.get-task-allow + + com.apple.keystore.access-keychain-keys + + com.apple.keystore.lockassertion + + com.apple.private.associated-domains + + com.apple.private.necp.match + + com.apple.mkb.usersession.info + diff --git a/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner.m b/tests/TestHostBinaries/KeychainEntitledTestRunner/KeychainEntitledTestRunner.m similarity index 91% rename from keychain/ckks/tests/testrunner/KeychainEntitledTestRunner.m rename to tests/TestHostBinaries/KeychainEntitledTestRunner/KeychainEntitledTestRunner.m index cf5cbc56..98d37667 100644 --- a/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner.m +++ b/tests/TestHostBinaries/KeychainEntitledTestRunner/KeychainEntitledTestRunner.m @@ -26,8 +26,7 @@ @implementation TestRunner - (instancetype)initWithBundlePath:(NSString *)path andTestNames:(NSArray *)names { - self = [super init]; - if (self) { + if ((self = [super init])) { NSError *error = nil; _bundle = [NSBundle bundleWithPath:path]; @@ -115,9 +114,9 @@ [self testLogWithFormat:@"Test Suite '%@' started at %@\n", testSuite.name, [self.dateFormatter stringFromDate:testSuite.testRun.startDate]]; } -- (void)testSuite:(XCTestSuite *)testSuite didFailWithDescription:(NSString *)description inFile:(nullable NSString *)filePath atLine:(NSUInteger)lineNumber -{ - [self testLogWithFormat:@"%@:%lu: error: %@ : %@\n", ((nil != filePath) ? filePath : @""), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testSuite.name, description]; +- (void)testSuite:(XCTestSuite *)testSuite didRecordIssue:(XCTIssue *)issue { + [self testLogWithFormat:@"(%@)%@:%lu: error: %@", testSuite.name, issue.sourceCodeContext.location.fileURL, + issue.sourceCodeContext.location.lineNumber, issue.compactDescription]; } - (void)testSuiteDidFinish:(XCTestSuite *)testSuite @@ -139,9 +138,8 @@ [self testLogWithFormat:@"Test Case '%@' started.\n", testCase.name]; } -- (void)testCase:(XCTestCase *)testCase didFailWithDescription:(NSString *)description inFile:(nullable NSString *)filePath atLine:(NSUInteger)lineNumber -{ - [self testLogWithFormat:@"%@:%lu: error: %@ : %@\n", ((nil != filePath) ? filePath : @""), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testCase.name, description]; +- (void)testCase:(XCTestCase *)testCase didRecordIssue:(XCTIssue *)issue { + [self testLogWithFormat:@"(%@)%@:%lu error: %@\n%@", testCase.name, issue.sourceCodeContext.location.fileURL, issue.sourceCodeContext.location.lineNumber, issue.detailedDescription, issue.sourceCodeContext.callStack]; } - (void)testCaseDidFinish:(XCTestCase *)testCase diff --git a/tests/TrustTests/DaemonTests/CertificateServerTests.m b/tests/TrustTests/DaemonTests/CertificateServerTests.m new file mode 100644 index 00000000..4a9ffe16 --- /dev/null +++ b/tests/TrustTests/DaemonTests/CertificateServerTests.m @@ -0,0 +1,164 @@ +/* +* Copyright (c) 2021 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +* +*/ + +#include +#import +#import +#import "trust/trustd/SecCertificateServer.h" +#import "trust/trustd/SecRevocationServer.h" + +#import "TrustDaemonTestCase.h" +#import "CertificateServerTests_data.h" + +@interface CertificateServerTests : TrustDaemonTestCase +@end + +@implementation CertificateServerTests + +- (SecCertificatePathVCRef)createPath { + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _path_leaf_cert, sizeof(_path_leaf_cert)); + SecCertificateRef ca = SecCertificateCreateWithBytes(NULL, _path_ca_cert, sizeof(_path_ca_cert)); + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _path_root_cert, sizeof(_path_root_cert)); + SecCertificatePathVCRef path = SecCertificatePathVCCreate(NULL, leaf, NULL); + SecCertificatePathVCRef path2 = SecCertificatePathVCCreate(path, ca, NULL); + CFRelease(path); + SecCertificatePathVCRef result = SecCertificatePathVCCreate(path2, root, NULL); + CFRelease(path2); + CFRelease(root); + CFRelease(ca); + CFRelease(leaf); + return result; +} + +- (SecCertificatePathVCRef)createReversePath { + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _path_leaf_cert, sizeof(_path_leaf_cert)); + SecCertificateRef ca = SecCertificateCreateWithBytes(NULL, _path_ca_cert, sizeof(_path_ca_cert)); + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _path_root_cert, sizeof(_path_root_cert)); + SecCertificatePathVCRef path = SecCertificatePathVCCreate(NULL, root, NULL); + SecCertificatePathVCRef path2 = SecCertificatePathVCCreate(path, ca, NULL); + CFRelease(path); + SecCertificatePathVCRef result = SecCertificatePathVCCreate(path2, leaf, NULL); + CFRelease(path2); + CFRelease(root); + CFRelease(ca); + CFRelease(leaf); + return result; +} + +- (void)testGetMaximumNotBefore { + SecCertificatePathVCRef path = [self createPath]; + CFAbsoluteTime notBefore = SecCertificatePathVCGetMaximumNotBefore(path); + XCTAssertEqualObjects([NSDate dateWithTimeIntervalSinceReferenceDate:notBefore], + [NSDate dateWithTimeIntervalSinceReferenceDate:626290914.0]); // November 5, 2020 at 9:41:54 AM PST + CFRelease(path); + + // Reverse path should produce same result + path = [self createReversePath]; + notBefore = SecCertificatePathVCGetMaximumNotBefore(path); + XCTAssertEqualObjects([NSDate dateWithTimeIntervalSinceReferenceDate:notBefore], + [NSDate dateWithTimeIntervalSinceReferenceDate:626290914.0]); // November 5, 2020 at 9:41:54 AM PST + CFRelease(path); +} + +- (void)testGetMinimumNotAfter { + SecCertificatePathVCRef path = [self createPath]; + CFAbsoluteTime notAfter = SecCertificatePathVCGetMinimumNotAfter(path); + XCTAssertEqualObjects([NSDate dateWithTimeIntervalSinceReferenceDate:notAfter], + [NSDate dateWithTimeIntervalSinceReferenceDate:660418914.0]); // December 5, 2021 at 9:41:54 AM PST + CFRelease(path); + + // Reverse path should produce same result + path = [self createReversePath]; + notAfter = SecCertificatePathVCGetMinimumNotAfter(path); + XCTAssertEqualObjects([NSDate dateWithTimeIntervalSinceReferenceDate:notAfter], + [NSDate dateWithTimeIntervalSinceReferenceDate:660418914.0]); // December 5, 2021 at 9:41:54 AM PST + CFRelease(path); +} + +/* Mock OCSP behaviors in the validation context */ +- (void)createAndPopulateRVCs:(SecCertificatePathVCRef)path +{ + SecCertificatePathVCAllocateRVCs(path, 2); + SecOCSPResponseRef response_leaf = SecOCSPResponseCreate((__bridge CFDataRef)[NSData dataWithBytes:_ocsp_response_leaf + length:sizeof(_ocsp_response_leaf)]); + SecOCSPResponseRef response_ca = SecOCSPResponseCreate((__bridge CFDataRef)[NSData dataWithBytes:_ocsp_response_ca + length:sizeof(_ocsp_response_ca)]); + + // Set expire time on responses + (void)SecOCSPResponseCalculateValidity(response_leaf, 0.0, 0.0, 632104000.0); // January 11, 2021 at 4:26:40 PM PST + (void)SecOCSPResponseCalculateValidity(response_ca, 0.0, 0.0, 632104000.0); + for (int i = 0; i < 2; i++) { + SecRVCRef rvc = SecCertificatePathVCGetRVCAtIndex(path, i); + rvc->certIX = i; + rvc->done = false; + + SecORVCRef orvc = NULL; + orvc = malloc(sizeof(struct OpaqueSecORVC)); + memset(orvc, 0, sizeof(struct OpaqueSecORVC)); + orvc->rvc = rvc; + orvc->certIX = i; + + rvc->orvc = orvc; + + if (i == 0) { + orvc->thisUpdate = SecOCSPResponseProducedAt(response_leaf); + orvc->nextUpdate = SecOCSPResponseGetExpirationTime(response_leaf); + } else { + orvc->thisUpdate = SecOCSPResponseProducedAt(response_ca); + orvc->nextUpdate = SecOCSPResponseGetExpirationTime(response_ca); + } + } + + SecOCSPResponseFinalize(response_leaf); + SecOCSPResponseFinalize(response_ca); +} + +// Earliest next update is from the leaf response +- (void)testEarliestNextUpdate { + SecCertificatePathVCRef path = [self createPath]; + [self createAndPopulateRVCs:path]; + + CFAbsoluteTime enu = SecCertificatePathVCGetEarliestNextUpdate(path); + XCTAssertEqualObjects([NSDate dateWithTimeIntervalSinceReferenceDate:enu], + [NSDate dateWithTimeIntervalSinceReferenceDate:632142381.0]); // January 12, 2021 at 3:06:21 AM PST + + SecCertificatePathVCDeleteRVCs(path); + + CFRelease(path); +} + +// Latest this update is from the CA response +- (void)testLatestThisUpdate { + SecCertificatePathVCRef path = [self createPath]; + [self createAndPopulateRVCs:path]; + + CFAbsoluteTime ltu = SecCertificatePathVCGetLatestThisUpdate(path); + XCTAssertEqualObjects([NSDate dateWithTimeIntervalSinceReferenceDate:ltu], + [NSDate dateWithTimeIntervalSinceReferenceDate:632103361.0]); // January 11, 2021 at 4:16:01 PM PST + + SecCertificatePathVCDeleteRVCs(path); + CFRelease(path); +} + +@end diff --git a/tests/TrustTests/DaemonTests/CertificateServerTests_data.h b/tests/TrustTests/DaemonTests/CertificateServerTests_data.h new file mode 100644 index 00000000..a50805a5 --- /dev/null +++ b/tests/TrustTests/DaemonTests/CertificateServerTests_data.h @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2021 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#ifndef _TRUSTTESTS_DAEMON_CERTIFICATE_SERVER_TESTS_H_ +#define _TRUSTTESTS_DAEMON_CERTIFICATE_SERVER_TESTS_H_ + +/* subject:/CN=Prio Statistics Facilitator: XX/O=External Entity */ +/* issuer :/CN=Test Apple Application Integration CA 6 - G1/O=Apple Inc./C=US */ +/* Not Before: Nov 5 17:41:54 2020 GMT; Not After : Dec 5 17:41:54 2021 GMT */ +const uint8_t _path_leaf_cert[]={ + 0x30,0x82,0x03,0x99,0x30,0x82,0x03,0x3F,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x55, + 0x43,0x08,0x3F,0x5B,0xCF,0x39,0x69,0xB7,0x46,0x8C,0xE3,0x99,0xBF,0x2A,0x63,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x59,0x31,0x35,0x30, + 0x33,0x06,0x03,0x55,0x04,0x03,0x0C,0x2C,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x41,0x70,0x70,0x6C,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x49, + 0x6E,0x74,0x65,0x67,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x43,0x41,0x20,0x36,0x20, + 0x2D,0x20,0x47,0x31,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x35, + 0x31,0x37,0x34,0x31,0x35,0x34,0x5A,0x17,0x0D,0x32,0x31,0x31,0x32,0x30,0x35,0x31, + 0x37,0x34,0x31,0x35,0x34,0x5A,0x30,0x44,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x1F,0x50,0x72,0x69,0x6F,0x20,0x53,0x74,0x61,0x74,0x69,0x73,0x74,0x69, + 0x63,0x73,0x20,0x46,0x61,0x63,0x69,0x6C,0x69,0x74,0x61,0x74,0x6F,0x72,0x3A,0x20, + 0x58,0x58,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0F,0x45,0x78,0x74, + 0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x6E,0x74,0x69,0x74,0x79,0x30,0x59,0x30,0x13, + 0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x45,0x72,0x96,0xD1,0x93,0xED,0xF6,0xEB,0xD2, + 0xB8,0x80,0xFF,0xA3,0x05,0x1D,0x26,0xCB,0x62,0x98,0x9C,0x6C,0x03,0x98,0x16,0x3F, + 0xAE,0xE2,0x2F,0x6D,0x5F,0xD5,0x66,0x49,0xFB,0xA8,0xF7,0x61,0xF9,0xD7,0xBE,0xB5, + 0x73,0x32,0xDA,0xCD,0xFB,0xE1,0x10,0x5B,0xC2,0xDC,0xC4,0x70,0xEC,0x22,0x4A,0x29, + 0x02,0x19,0x05,0xB8,0xDD,0x8E,0x1F,0xA3,0x82,0x01,0xFC,0x30,0x82,0x01,0xF8,0x30, + 0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06, + 0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xA9,0x85,0xC1,0x1A,0x0A,0xE5, + 0xD8,0x79,0xCD,0xF0,0x7B,0x46,0xFA,0x99,0xEF,0x4B,0x61,0x47,0x73,0x84,0x30,0x50, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x44,0x30,0x42,0x30,0x40, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x34,0x68,0x74,0x74,0x70, + 0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70, + 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30, + 0x33,0x2D,0x74,0x65,0x73,0x74,0x61,0x61,0x69,0x63,0x61,0x36,0x67,0x31,0x30,0x32, + 0x30,0x82,0x01,0x1D,0x06,0x03,0x55,0x1D,0x20,0x04,0x82,0x01,0x14,0x30,0x82,0x01, + 0x10,0x30,0x82,0x01,0x0C,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x05,0x01, + 0x30,0x81,0xFE,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02, + 0x30,0x81,0xB6,0x0C,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65,0x20,0x6F, + 0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, + 0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72,0x74,0x79,0x20, + 0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74,0x61,0x6E, + 0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65,0x6E,0x20,0x61, + 0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61,0x6E,0x64,0x61, + 0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E, + 0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x2C,0x20, + 0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70,0x6F,0x6C,0x69, + 0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,0x73,0x74, + 0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x36,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x02,0x01,0x16,0x2A,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77, + 0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x65,0x72, + 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x61,0x75,0x74,0x68,0x6F,0x72,0x69,0x74, + 0x79,0x30,0x14,0x06,0x03,0x55,0x1D,0x25,0x04,0x0D,0x30,0x0B,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x63,0x64,0x04,0x12,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0x41,0xF3,0x3A,0x81,0xF6,0x13,0x85,0xD4,0xF6,0xE7,0x07,0x77,0x47,0x16, + 0xD2,0x9A,0xE5,0xFD,0x21,0xCF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF, + 0x04,0x04,0x03,0x02,0x03,0x08,0x30,0x0F,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63, + 0x64,0x0F,0x02,0x04,0x02,0x05,0x00,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x20,0x3E,0x4D,0x6A,0xFB,0xE1,0xE0, + 0x32,0x8A,0xC0,0x79,0x6C,0xB1,0x26,0xB0,0x13,0x07,0x2A,0x0C,0x50,0x2A,0x45,0x18, + 0x18,0x60,0x3F,0x7F,0xC8,0x74,0x2C,0xA1,0xBF,0xE4,0x02,0x21,0x00,0xB5,0xE3,0xE4, + 0x4E,0x14,0x20,0xFC,0x7D,0x54,0x52,0xBE,0xD2,0x7C,0x22,0x9B,0xF1,0x89,0x1D,0xB5, + 0x7F,0x71,0xDF,0x43,0xBD,0xA1,0xC1,0xC1,0xF6,0xDE,0x31,0x05,0x42, +}; + +/* subject:/CN=Test Apple Application Integration CA 6 - G1/O=Apple Inc./C=US */ +/* issuer :/CN=Test Apple Root CA - G3/OU=Apple Certification Authority/O=Apple Inc./C=US */ +/* Not Before: Jun 25 23:41:27 2020 GMT; Not After : Jun 22 23:41:27 2035 GMT */ +const uint8_t _path_ca_cert[]={ + 0x30,0x82,0x02,0xEF,0x30,0x82,0x02,0x75,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x4E, + 0x44,0x86,0xF9,0xD8,0x8C,0x9E,0x99,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x03,0x30,0x6C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C,0x17, + 0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20, + 0x43,0x41,0x20,0x2D,0x20,0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x1E,0x17,0x0D,0x32,0x30,0x30,0x36,0x32,0x35,0x32,0x33,0x34,0x31,0x32, + 0x37,0x5A,0x17,0x0D,0x33,0x35,0x30,0x36,0x32,0x32,0x32,0x33,0x34,0x31,0x32,0x37, + 0x5A,0x30,0x59,0x31,0x35,0x30,0x33,0x06,0x03,0x55,0x04,0x03,0x0C,0x2C,0x54,0x65, + 0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x70,0x70,0x6C,0x69,0x63,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x49,0x6E,0x74,0x65,0x67,0x72,0x61,0x74,0x69,0x6F,0x6E, + 0x20,0x43,0x41,0x20,0x36,0x20,0x2D,0x20,0x47,0x31,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x59,0x30,0x13, + 0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x13,0xCF,0x5B,0x49,0xCA,0x59,0x56,0x92,0x3D, + 0x5C,0x46,0xD5,0x7A,0x95,0xE4,0xA0,0xB0,0x84,0x1E,0x68,0x3E,0x2C,0x13,0xB1,0xDC, + 0x4E,0x26,0xAC,0x72,0x6A,0x11,0x93,0x77,0xE3,0xA0,0xE3,0x6F,0x48,0x0B,0x96,0xF5, + 0xFE,0xD5,0xBD,0xA5,0xBC,0x4F,0x74,0x03,0xF1,0x09,0xF3,0xBF,0xC3,0x0D,0xB8,0x9B, + 0x62,0x2B,0xC0,0xD3,0x4A,0x06,0x95,0xA3,0x82,0x01,0x12,0x30,0x82,0x01,0x0E,0x30, + 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xFC,0x46,0xD8, + 0x83,0x6C,0x1F,0xE6,0xF2,0xDC,0xDF,0xA7,0x99,0x17,0xAE,0x0B,0x44,0x67,0x17,0x1B, + 0x46,0x30,0x53,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x47,0x30, + 0x45,0x30,0x43,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x37,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D,0x75,0x61,0x74,0x2E,0x63, + 0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63, + 0x73,0x70,0x30,0x33,0x2D,0x74,0x65,0x73,0x74,0x61,0x70,0x70,0x6C,0x65,0x72,0x6F, + 0x6F,0x74,0x63,0x61,0x67,0x33,0x30,0x44,0x06,0x03,0x55,0x1D,0x1F,0x04,0x3D,0x30, + 0x3B,0x30,0x39,0xA0,0x37,0xA0,0x35,0x86,0x33,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x63,0x72,0x6C,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70, + 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65,0x73,0x74,0x61,0x70,0x70,0x6C,0x65, + 0x72,0x6F,0x6F,0x74,0x63,0x61,0x67,0x33,0x2E,0x63,0x72,0x6C,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xA9,0x85,0xC1,0x1A,0x0A,0xE5,0xD8,0x79,0xCD, + 0xF0,0x7B,0x46,0xFA,0x99,0xEF,0x4B,0x61,0x47,0x73,0x84,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x10,0x06,0x0A,0x2A, + 0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x02,0x1A,0x04,0x02,0x05,0x00,0x30,0x0A,0x06, + 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x68,0x00,0x30,0x65,0x02,0x30, + 0x28,0xB1,0x65,0x9C,0x8F,0xFC,0x4E,0xF9,0xF3,0x18,0x21,0xF0,0x00,0xB7,0x76,0x23, + 0x57,0x78,0xB1,0x1A,0x71,0x15,0xD0,0xEF,0x7B,0x3C,0xAF,0x4F,0xC6,0x1C,0x4D,0x55, + 0x16,0x5D,0x1B,0x92,0xDE,0x97,0x4C,0x88,0xE4,0x8A,0x2D,0x86,0xD8,0x79,0x2D,0xB5, + 0x02,0x31,0x00,0xF4,0xBC,0xB0,0x78,0xE1,0x0E,0xF5,0x8A,0x4F,0xB9,0x23,0xD7,0x75, + 0x6B,0x88,0x23,0xDD,0xED,0xCA,0xD1,0xA0,0x27,0xC4,0x86,0xED,0x4B,0x8C,0x24,0x22, + 0x61,0x6C,0x56,0x42,0x5F,0xFA,0x2B,0x10,0x43,0xFA,0xA0,0xE8,0x27,0xB0,0xCB,0x5F, + 0xEA,0xCB,0xFB, +}; + +/* subject:/CN=Test Apple Root CA - G3/OU=Apple Certification Authority/O=Apple Inc./C=US */ +/* issuer :/CN=Test Apple Root CA - G3/OU=Apple Certification Authority/O=Apple Inc./C=US */ +/* Not Before: Apr 22 03:17:44 2015 GMT; Not After : Dec 26 03:13:37 2040 GMT*/ +const uint8_t _path_root_cert[]={ + 0x30,0x82,0x02,0x4C,0x30,0x82,0x01,0xD3,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x78, + 0x36,0x0B,0xF4,0xB7,0xC8,0xB6,0xB0,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x03,0x30,0x6C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C,0x17, + 0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20, + 0x43,0x41,0x20,0x2D,0x20,0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x1E,0x17,0x0D,0x31,0x35,0x30,0x34,0x32,0x32,0x30,0x33,0x31,0x37,0x34, + 0x34,0x5A,0x17,0x0D,0x34,0x30,0x31,0x32,0x32,0x36,0x30,0x33,0x31,0x33,0x33,0x37, + 0x5A,0x30,0x6C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C,0x17,0x54,0x65, + 0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41, + 0x20,0x2D,0x20,0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, + 0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x05,0x2B,0x81, + 0x04,0x00,0x22,0x03,0x62,0x00,0x04,0xA9,0x1A,0x63,0x34,0xEF,0xBC,0xA6,0x8A,0xD6, + 0x2A,0x6A,0x38,0x22,0xE9,0x25,0xAD,0xDA,0x28,0xA0,0x49,0xC5,0x64,0xFE,0x5D,0x91, + 0xC3,0x6C,0xF7,0x99,0xE4,0xBA,0xE4,0x2A,0x5F,0x61,0xD2,0xBF,0x3B,0x6C,0xA8,0x61, + 0x11,0xB5,0xE0,0x66,0xF7,0x22,0x11,0x86,0x97,0x5D,0xC3,0xBA,0x1B,0x6D,0x55,0x7F, + 0xD0,0xF9,0x80,0xE0,0xFF,0xD9,0x05,0xAD,0x5A,0x5B,0xBF,0x3A,0x7A,0xA7,0x09,0x52, + 0x1A,0x31,0x7F,0x0C,0xA2,0xE8,0x10,0xF5,0x36,0xD3,0xC8,0xEA,0xA0,0x5B,0x0A,0x28, + 0x85,0x30,0x28,0x5F,0x94,0xF6,0x94,0xA3,0x42,0x30,0x40,0x30,0x1D,0x06,0x03,0x55, + 0x1D,0x0E,0x04,0x16,0x04,0x14,0xFC,0x46,0xD8,0x83,0x6C,0x1F,0xE6,0xF2,0xDC,0xDF, + 0xA7,0x99,0x17,0xAE,0x0B,0x44,0x67,0x17,0x1B,0x46,0x30,0x0F,0x06,0x03,0x55,0x1D, + 0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0A,0x06,0x08,0x2A, + 0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x67,0x00,0x30,0x64,0x02,0x30,0x1A,0x14, + 0x38,0x24,0xFF,0xB4,0x08,0xCB,0xEA,0xC9,0x3B,0xDA,0xCC,0x82,0xF3,0xD9,0x0D,0xD1, + 0x2B,0x6E,0xBF,0x1F,0xC4,0x15,0x14,0x44,0xDF,0x98,0x9B,0xD7,0xDD,0xBA,0x1B,0xBE, + 0x4F,0x9F,0x17,0xA4,0xD2,0x02,0x75,0x90,0x7D,0x76,0xCC,0x93,0x16,0x2F,0x02,0x30, + 0x02,0xD7,0xDA,0x0B,0xBE,0xDD,0x3D,0xED,0xF9,0xA3,0x06,0x90,0xA9,0x58,0xBD,0x6B, + 0x7C,0x7C,0xE5,0xC5,0x4E,0x0E,0x44,0xA2,0x94,0x2F,0xB4,0x04,0x9A,0xCD,0x9B,0x69, + 0x8D,0x2A,0xC6,0x1D,0x58,0xFF,0xE3,0x32,0xB6,0xDB,0x3E,0x34,0xFF,0x67,0x70,0xF1, +}; + +/* + Prio Statistics Facilitator_ XX.cert.pem: good + This Update: Jan 11 23:06:21 2021 GMT + Next Update: Jan 12 11:06:21 2021 GMT + */ +const uint8_t _ocsp_response_leaf[] = { + 0x30, 0x82, 0x06, 0x68, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x06, 0x61, 0x30, 0x82, 0x06, 0x5d, 0x06, + 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x06, 0x4e, 0x30, 0x82, + 0x06, 0x4a, 0x30, 0x81, 0xc3, 0xa2, 0x16, 0x04, 0x14, 0x0f, 0x64, 0x14, 0xe3, 0x20, 0x35, 0x7c, + 0xf3, 0x68, 0x5d, 0x07, 0x6d, 0x66, 0xca, 0xe7, 0xf6, 0x01, 0x1f, 0x6c, 0x89, 0x18, 0x0f, 0x32, + 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x31, 0x32, 0x33, 0x30, 0x36, 0x32, 0x31, 0x5a, 0x30, 0x73, + 0x30, 0x71, 0x30, 0x49, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, + 0x14, 0x62, 0x9f, 0xbd, 0x59, 0x5a, 0x10, 0x15, 0xb0, 0xd6, 0x4b, 0x2e, 0xe6, 0xb5, 0x64, 0xa6, + 0x6f, 0x14, 0x83, 0x9e, 0x9e, 0x04, 0x14, 0xa9, 0x85, 0xc1, 0x1a, 0x0a, 0xe5, 0xd8, 0x79, 0xcd, + 0xf0, 0x7b, 0x46, 0xfa, 0x99, 0xef, 0x4b, 0x61, 0x47, 0x73, 0x84, 0x02, 0x10, 0x55, 0x43, 0x08, + 0x3f, 0x5b, 0xcf, 0x39, 0x69, 0xb7, 0x46, 0x8c, 0xe3, 0x99, 0xbf, 0x2a, 0x63, 0x80, 0x00, 0x18, + 0x0f, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x31, 0x32, 0x33, 0x30, 0x36, 0x32, 0x31, 0x5a, + 0xa0, 0x11, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x32, 0x31, 0x31, 0x30, 0x36, + 0x32, 0x31, 0x5a, 0xa1, 0x23, 0x30, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x30, 0x01, 0x02, 0x04, 0x12, 0x04, 0x10, 0x3c, 0xa4, 0x90, 0x70, 0x92, 0x6f, 0x7a, 0xfc, + 0x27, 0x20, 0x49, 0x67, 0x3a, 0x37, 0x5e, 0x32, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xcc, 0x5c, 0x68, 0xf1, + 0x78, 0xa4, 0xe1, 0x40, 0x12, 0x43, 0x4f, 0x7f, 0x48, 0xa8, 0x18, 0x07, 0x66, 0x2d, 0x34, 0x54, + 0x74, 0x68, 0x04, 0xe6, 0x1f, 0x6b, 0x50, 0x94, 0xed, 0xb7, 0xf1, 0xf4, 0x02, 0x20, 0x33, 0x93, + 0x03, 0x0c, 0x97, 0xdc, 0x54, 0x06, 0xb2, 0xed, 0x92, 0xbc, 0x7d, 0x6f, 0x84, 0x45, 0x7b, 0x05, + 0x67, 0x2d, 0x29, 0xd4, 0xa8, 0xfc, 0xfb, 0xf0, 0xc7, 0x3e, 0xe4, 0xb2, 0xaf, 0x4e, 0xa0, 0x82, + 0x05, 0x2a, 0x30, 0x82, 0x05, 0x26, 0x30, 0x82, 0x02, 0x2f, 0x30, 0x82, 0x01, 0xd5, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x3f, 0x6c, 0xe2, 0x71, 0xae, 0xbc, 0x4f, 0xd3, 0x53, 0x70, 0xa8, + 0xe9, 0x67, 0xff, 0xcd, 0x44, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, + 0x02, 0x30, 0x59, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2c, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x43, 0x41, 0x20, 0x36, 0x20, 0x2d, 0x20, 0x47, 0x31, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, + 0x32, 0x30, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x31, 0x38, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x32, + 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x31, 0x38, 0x31, 0x32, 0x5a, 0x30, 0x50, 0x31, 0x2c, + 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x23, 0x61, 0x61, 0x69, 0x63, 0x61, 0x36, 0x67, + 0x31, 0x20, 0x4f, 0x43, 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, + 0x20, 0x47, 0x31, 0x20, 0x32, 0x30, 0x32, 0x30, 0x31, 0x32, 0x31, 0x37, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, + 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x59, + 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x63, 0x0e, 0x59, 0xae, 0x69, 0x58, 0x2e, + 0x0f, 0x07, 0x87, 0x08, 0xf8, 0x95, 0xe5, 0x76, 0x7a, 0xc9, 0x28, 0x50, 0x12, 0x70, 0x78, 0x99, + 0x99, 0x8c, 0x05, 0x0f, 0xd3, 0x0e, 0xe7, 0xb5, 0x59, 0xb0, 0x73, 0x82, 0x7f, 0xbd, 0xc7, 0xef, + 0x3f, 0x33, 0xa1, 0x64, 0x5b, 0x96, 0x46, 0x8e, 0x81, 0xf9, 0x38, 0x9d, 0x0a, 0xeb, 0x31, 0x0f, + 0x9f, 0x5a, 0x6c, 0x1a, 0x52, 0x7f, 0xf4, 0x4c, 0x98, 0xa3, 0x81, 0x87, 0x30, 0x81, 0x84, 0x30, + 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xa9, 0x85, 0xc1, 0x1a, 0x0a, 0xe5, + 0xd8, 0x79, 0xcd, 0xf0, 0x7b, 0x46, 0xfa, 0x99, 0xef, 0x4b, 0x61, 0x47, 0x73, 0x84, 0x30, 0x0f, + 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x05, 0x04, 0x02, 0x05, 0x00, 0x30, + 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x03, 0x09, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x0f, + 0x64, 0x14, 0xe3, 0x20, 0x35, 0x7c, 0xf3, 0x68, 0x5d, 0x07, 0x6d, 0x66, 0xca, 0xe7, 0xf6, 0x01, + 0x1f, 0x6c, 0x89, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, + 0x02, 0x07, 0x80, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, + 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x71, 0x81, 0xc8, 0xaf, 0x54, 0xf9, 0x81, 0x48, 0x8e, 0x7d, + 0xf5, 0x45, 0xd2, 0x66, 0x19, 0x36, 0xf0, 0xe9, 0xf6, 0xb0, 0xd1, 0x58, 0xfb, 0x9a, 0xbc, 0x80, + 0x62, 0xaa, 0xfd, 0xed, 0x7b, 0xb5, 0x02, 0x21, 0x00, 0x8f, 0x65, 0xfc, 0xce, 0x02, 0xeb, 0xd9, + 0xd2, 0x3e, 0x9a, 0x37, 0x43, 0x34, 0x61, 0x05, 0x0b, 0xf0, 0x4a, 0x2d, 0xe6, 0x20, 0x33, 0xa7, + 0x06, 0xd2, 0xbe, 0xe4, 0x08, 0xf0, 0x52, 0x50, 0xb1, 0x30, 0x82, 0x02, 0xef, 0x30, 0x82, 0x02, + 0x75, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e, 0x44, 0x86, 0xf9, 0xd8, 0x8c, 0x9e, 0x99, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x6c, 0x31, 0x20, + 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, + 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, + 0x30, 0x36, 0x32, 0x35, 0x32, 0x33, 0x34, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, + 0x36, 0x32, 0x32, 0x32, 0x33, 0x34, 0x31, 0x32, 0x37, 0x5a, 0x30, 0x59, 0x31, 0x35, 0x30, 0x33, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x41, 0x20, 0x36, 0x20, 0x2d, + 0x20, 0x47, 0x31, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, + 0x13, 0xcf, 0x5b, 0x49, 0xca, 0x59, 0x56, 0x92, 0x3d, 0x5c, 0x46, 0xd5, 0x7a, 0x95, 0xe4, 0xa0, + 0xb0, 0x84, 0x1e, 0x68, 0x3e, 0x2c, 0x13, 0xb1, 0xdc, 0x4e, 0x26, 0xac, 0x72, 0x6a, 0x11, 0x93, + 0x77, 0xe3, 0xa0, 0xe3, 0x6f, 0x48, 0x0b, 0x96, 0xf5, 0xfe, 0xd5, 0xbd, 0xa5, 0xbc, 0x4f, 0x74, + 0x03, 0xf1, 0x09, 0xf3, 0xbf, 0xc3, 0x0d, 0xb8, 0x9b, 0x62, 0x2b, 0xc0, 0xd3, 0x4a, 0x06, 0x95, + 0xa3, 0x82, 0x01, 0x12, 0x30, 0x82, 0x01, 0x0e, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfc, 0x46, 0xd8, 0x83, 0x6c, 0x1f, 0xe6, 0xf2, 0xdc, 0xdf, + 0xa7, 0x99, 0x17, 0xae, 0x0b, 0x44, 0x67, 0x17, 0x1b, 0x46, 0x30, 0x53, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x47, 0x30, 0x45, 0x30, 0x43, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x37, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, + 0x63, 0x73, 0x70, 0x2d, 0x75, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x61, 0x70, 0x70, + 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x33, 0x2d, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x72, 0x6f, 0x6f, 0x74, 0x63, 0x61, 0x67, 0x33, 0x30, + 0x44, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x3d, 0x30, 0x3b, 0x30, 0x39, 0xa0, 0x37, 0xa0, 0x35, + 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2d, 0x75, 0x61, 0x74, + 0x2e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x72, 0x6f, 0x6f, 0x74, 0x63, 0x61, 0x67, + 0x33, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0xa9, 0x85, 0xc1, 0x1a, 0x0a, 0xe5, 0xd8, 0x79, 0xcd, 0xf0, 0x7b, 0x46, 0xfa, 0x99, 0xef, 0x4b, + 0x61, 0x47, 0x73, 0x84, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, + 0x03, 0x02, 0x01, 0x06, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, + 0x02, 0x1a, 0x04, 0x02, 0x05, 0x00, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, + 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x30, 0x28, 0xb1, 0x65, 0x9c, 0x8f, 0xfc, 0x4e, + 0xf9, 0xf3, 0x18, 0x21, 0xf0, 0x00, 0xb7, 0x76, 0x23, 0x57, 0x78, 0xb1, 0x1a, 0x71, 0x15, 0xd0, + 0xef, 0x7b, 0x3c, 0xaf, 0x4f, 0xc6, 0x1c, 0x4d, 0x55, 0x16, 0x5d, 0x1b, 0x92, 0xde, 0x97, 0x4c, + 0x88, 0xe4, 0x8a, 0x2d, 0x86, 0xd8, 0x79, 0x2d, 0xb5, 0x02, 0x31, 0x00, 0xf4, 0xbc, 0xb0, 0x78, + 0xe1, 0x0e, 0xf5, 0x8a, 0x4f, 0xb9, 0x23, 0xd7, 0x75, 0x6b, 0x88, 0x23, 0xdd, 0xed, 0xca, 0xd1, + 0xa0, 0x27, 0xc4, 0x86, 0xed, 0x4b, 0x8c, 0x24, 0x22, 0x61, 0x6c, 0x56, 0x42, 0x5f, 0xfa, 0x2b, + 0x10, 0x43, 0xfa, 0xa0, 0xe8, 0x27, 0xb0, 0xcb, 0x5f, 0xea, 0xcb, 0xfb +}; + +/* Prio Statistics Facilitator_ XX.issuer.pem: good + This Update: Jan 12 00:16:01 2021 GMT + Next Update: Jan 13 00:16:01 2021 GMT */ +const uint8_t _ocsp_response_ca[] = { + 0x30, 0x82, 0x03, 0xa1, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x03, 0x9a, 0x30, 0x82, 0x03, 0x96, 0x06, + 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x03, 0x87, 0x30, 0x82, + 0x03, 0x83, 0x30, 0x81, 0xbb, 0xa2, 0x16, 0x04, 0x14, 0xcd, 0x9a, 0x25, 0x8d, 0xfc, 0x76, 0x41, + 0x28, 0xd4, 0x41, 0x2b, 0x56, 0xc9, 0x98, 0xec, 0x84, 0x0a, 0xa9, 0x94, 0xfa, 0x18, 0x0f, 0x32, + 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x31, 0x36, 0x30, 0x31, 0x5a, 0x30, 0x6b, + 0x30, 0x69, 0x30, 0x41, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, + 0x14, 0x39, 0x9b, 0x6b, 0xd0, 0x5c, 0xd0, 0xe8, 0xad, 0x41, 0x5c, 0x2e, 0x5e, 0x9d, 0xe4, 0x60, + 0xce, 0x12, 0x54, 0xa3, 0x75, 0x04, 0x14, 0xfc, 0x46, 0xd8, 0x83, 0x6c, 0x1f, 0xe6, 0xf2, 0xdc, + 0xdf, 0xa7, 0x99, 0x17, 0xae, 0x0b, 0x44, 0x67, 0x17, 0x1b, 0x46, 0x02, 0x08, 0x4e, 0x44, 0x86, + 0xf9, 0xd8, 0x8c, 0x9e, 0x99, 0x80, 0x00, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, + 0x32, 0x30, 0x30, 0x31, 0x36, 0x30, 0x31, 0x5a, 0xa0, 0x11, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, + 0x30, 0x31, 0x31, 0x33, 0x30, 0x30, 0x31, 0x36, 0x30, 0x31, 0x5a, 0xa1, 0x23, 0x30, 0x21, 0x30, + 0x1f, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02, 0x04, 0x12, 0x04, 0x10, + 0xe1, 0x9a, 0x54, 0x08, 0xd5, 0x2d, 0x52, 0x09, 0xdc, 0xe5, 0x6f, 0x0c, 0xd2, 0xe8, 0x83, 0xad, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, + 0x45, 0x02, 0x21, 0x00, 0x8f, 0xe7, 0xa5, 0xc7, 0x5d, 0x6b, 0x99, 0xea, 0x6d, 0xe6, 0x4d, 0xfd, + 0xe7, 0x54, 0x92, 0x20, 0x25, 0x4e, 0x0e, 0x5f, 0xb9, 0x0e, 0x89, 0xd5, 0x0c, 0xc5, 0x28, 0xae, + 0x1d, 0x1c, 0x0a, 0xdc, 0x02, 0x20, 0x59, 0xce, 0xfe, 0x85, 0xe9, 0x8c, 0xec, 0x4d, 0xa1, 0x2b, + 0x02, 0x8d, 0x94, 0xff, 0xa1, 0xf0, 0xc2, 0xfd, 0xb7, 0x22, 0xdf, 0x9f, 0x43, 0x95, 0x36, 0x6f, + 0x00, 0x21, 0x95, 0xe2, 0x6a, 0x50, 0xa0, 0x82, 0x02, 0x6b, 0x30, 0x82, 0x02, 0x67, 0x30, 0x82, + 0x02, 0x63, 0x30, 0x82, 0x01, 0xe9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x0d, 0x83, 0xd0, + 0x68, 0x12, 0x2a, 0xf0, 0xd6, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, + 0x02, 0x30, 0x6c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, + 0x20, 0x2d, 0x20, 0x47, 0x33, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, + 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x31, 0x36, 0x35, 0x35, 0x5a, + 0x17, 0x0d, 0x32, 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x31, 0x36, 0x35, 0x35, 0x5a, 0x30, + 0x59, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2c, 0x54, 0x65, 0x73, 0x74, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x47, 0x33, 0x20, 0x4f, 0x43, + 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x47, 0x31, 0x20, + 0x32, 0x30, 0x32, 0x30, 0x31, 0x32, 0x31, 0x37, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, + 0x07, 0x03, 0x42, 0x00, 0x04, 0x4c, 0xb8, 0xfc, 0x81, 0x45, 0x6a, 0x1e, 0x89, 0xdd, 0x43, 0xfe, + 0xf2, 0x42, 0xc7, 0xed, 0xa2, 0xb1, 0xe6, 0xda, 0xfd, 0x22, 0x49, 0x23, 0xb2, 0x5a, 0xf5, 0xe7, + 0x6e, 0xbd, 0x36, 0xd5, 0x4e, 0x1a, 0x72, 0x72, 0x12, 0x0d, 0xcd, 0xd6, 0x9a, 0x66, 0xe2, 0xfd, + 0x7b, 0x17, 0x05, 0x7a, 0x94, 0x95, 0x54, 0x6b, 0xeb, 0xdd, 0x29, 0x7c, 0xee, 0x69, 0x08, 0xb7, + 0x27, 0x13, 0x7b, 0xdd, 0x07, 0xa3, 0x81, 0x87, 0x30, 0x81, 0x84, 0x30, 0x0c, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfc, 0x46, 0xd8, 0x83, 0x6c, 0x1f, 0xe6, 0xf2, 0xdc, 0xdf, + 0xa7, 0x99, 0x17, 0xae, 0x0b, 0x44, 0x67, 0x17, 0x1b, 0x46, 0x30, 0x0f, 0x06, 0x09, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x05, 0x04, 0x02, 0x05, 0x00, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xcd, 0x9a, 0x25, 0x8d, 0xfc, + 0x76, 0x41, 0x28, 0xd4, 0x41, 0x2b, 0x56, 0xc9, 0x98, 0xec, 0x84, 0x0a, 0xa9, 0x94, 0xfa, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, + 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x68, 0x00, 0x30, 0x65, + 0x02, 0x30, 0x7b, 0x29, 0x81, 0xb5, 0xe8, 0x66, 0xfe, 0xe7, 0x54, 0x6a, 0x33, 0xc2, 0x01, 0xa7, + 0xd4, 0xb4, 0x76, 0xbf, 0x9a, 0x08, 0x5a, 0x42, 0xea, 0xcb, 0xeb, 0xbd, 0xce, 0x2b, 0x22, 0x71, + 0x32, 0x36, 0xa5, 0xc4, 0xb8, 0xc2, 0xd6, 0x84, 0xff, 0x8b, 0x15, 0x6b, 0xdd, 0xab, 0x6e, 0x64, + 0x10, 0xc7, 0x02, 0x31, 0x00, 0xbd, 0x3a, 0x29, 0x96, 0x44, 0xe4, 0x2d, 0xee, 0x6e, 0xe0, 0x9d, + 0x37, 0x26, 0xab, 0x86, 0x9d, 0x8f, 0xb6, 0xfd, 0x8c, 0xe7, 0xf8, 0x76, 0x4c, 0xad, 0xf2, 0x9b, + 0xea, 0x53, 0xa2, 0x7e, 0x48, 0xd6, 0x66, 0xed, 0xd2, 0x43, 0xc8, 0xe1, 0xa3, 0x3c, 0x68, 0xa3, + 0xde, 0xfd, 0xd3, 0x8a, 0x79 +}; + +#endif /* _TRUSTTESTS_DAEMON_REVOCATION_SERVER_TESTS_H_ */ diff --git a/tests/TrustTests/DaemonTests/LoggingServerTests.m b/tests/TrustTests/DaemonTests/LoggingServerTests.m index 6f7b6f53..bbcbd5b1 100644 --- a/tests/TrustTests/DaemonTests/LoggingServerTests.m +++ b/tests/TrustTests/DaemonTests/LoggingServerTests.m @@ -2,7 +2,6 @@ // LoggingServerTests.m // Security // -// Created by Bailey Basile on 6/11/19. // #include @@ -10,7 +9,9 @@ #import "trust/trustd/SecTrustLoggingServer.h" -@interface LoggingServerTests : XCTestCase +#import "TrustDaemonTestCase.h" + +@interface LoggingServerTests : TrustDaemonTestCase @end @implementation LoggingServerTests diff --git a/tests/TrustTests/DaemonTests/OCSPCacheTests.m b/tests/TrustTests/DaemonTests/OCSPCacheTests.m new file mode 100644 index 00000000..1261412b --- /dev/null +++ b/tests/TrustTests/DaemonTests/OCSPCacheTests.m @@ -0,0 +1,184 @@ +// +// OCSPCacheUpgradeTests.m +// Security +// +// + +#include +#import +#import +#include +#include +#import "trust/trustd/SecOCSPRequest.h" +#import "trust/trustd/SecOCSPResponse.h" +#import "trust/trustd/SecOCSPCache.h" + +#import "TrustDaemonTestCase.h" +#import "OCSPCacheTests_data.h" + +@interface OCSPCacheTests : TrustDaemonTestCase +@end + +@implementation OCSPCacheTests + +- (void)setUp +{ + /* Delete the OCSP cache DB so we can start fresh */ + SecOCSPCacheDeleteCache(); +} + +- (BOOL)canReadDB +{ + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _leaf_cert, sizeof(_leaf_cert)); + SecCertificateRef issuer = SecCertificateCreateWithBytes(NULL, _issuer, sizeof(_issuer)); + SecOCSPRequestRef request = SecOCSPRequestCreate(leaf, issuer); + SecOCSPResponseRef response = SecOCSPCacheCopyMatching(request, NULL); + CFReleaseNull(leaf); + CFReleaseNull(issuer); + SecOCSPRequestFinalize(request); + + if (response) { + SecOCSPResponseFinalize(response); + return YES; + } + return NO; +} + +- (void)writeResponse1ToDB +{ + NSData *responseData = [NSData dataWithBytes:_ocsp_response1 length:sizeof(_ocsp_response1)]; + SecOCSPResponseRef response = SecOCSPResponseCreate((__bridge CFDataRef)responseData); + /* use a verifyTime within the validity of the ocsp response */ + (void)SecOCSPResponseCalculateValidity(response, 0, 60, 595602000.0); // as a side effect, populates the expire time + SecOCSPCacheReplaceResponse(NULL, response, NULL, 595602000.0); + SecOCSPResponseFinalize(response); +} + +- (void)writeResponse2ToDB +{ + NSData *responseData = [NSData dataWithBytes:_ocsp_response2 length:sizeof(_ocsp_response2)]; + SecOCSPResponseRef response = SecOCSPResponseCreate((__bridge CFDataRef)responseData); + (void)SecOCSPResponseCalculateValidity(response, 0, 60, 596180000.0); // as a side effect, populates the expire time + SecOCSPCacheReplaceResponse(NULL, response, NULL,596180000.0); + SecOCSPResponseFinalize(response); +} + +- (void)replaceResponse +{ + NSData *responseData = [NSData dataWithBytes:_ocsp_response1 length:sizeof(_ocsp_response1)]; + SecOCSPResponseRef response1 = SecOCSPResponseCreate((__bridge CFDataRef)responseData); + (void)SecOCSPResponseCalculateValidity(response1, 0, 60, 595602000.0); // populate the expire time + + responseData = [NSData dataWithBytes:_ocsp_response2 length:sizeof(_ocsp_response2)]; + SecOCSPResponseRef response2 = SecOCSPResponseCreate((__bridge CFDataRef)responseData); + (void)SecOCSPResponseCalculateValidity(response2, 0, 60, 596180000.0); // populate the expire time + + SecOCSPCacheReplaceResponse(response1, response2, NULL, 596180000.0); + SecOCSPResponseFinalize(response1); + SecOCSPResponseFinalize(response2); +} + +- (void)createDBFromSQL:(NSString *)sql +{ + CFStringRef cf_path = SecOCSPCacheCopyPath(); + CFStringPerformWithCString(cf_path, ^(const char *path) { + /* Create ocsp cahche */ + sqlite3 *db; + XCTAssertEqual(sqlite3_open(path, &db), SQLITE_OK, "create ocsp cache"); + XCTAssertEqual(sqlite3_exec(db, [sql cStringUsingEncoding:NSUTF8StringEncoding], NULL, NULL, NULL), SQLITE_OK, + "populate ocsp cache"); + XCTAssertEqual(sqlite3_close_v2(db), SQLITE_OK); + + }); + CFReleaseNull(cf_path); +} + +- (int)countEntries +{ + CFStringRef cf_path = SecOCSPCacheCopyPath(); + __block int result = 0; + CFStringPerformWithCString(cf_path, ^(const char *path) { + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + XCTAssertEqual(sqlite3_open(path, &db), SQLITE_OK); + NSString *countResponses = @"SELECT COUNT(responseId) FROM responses;"; + XCTAssertEqual(sqlite3_prepare_v2(db, [countResponses cStringUsingEncoding:NSUTF8StringEncoding], + (int)[countResponses length], &stmt, NULL), + SQLITE_OK); + XCTAssertEqual(sqlite3_step(stmt), SQLITE_ROW); + result = sqlite3_column_int(stmt, 0); + XCTAssertEqual(sqlite3_finalize(stmt), SQLITE_OK); + XCTAssertEqual(sqlite3_close_v2(db), SQLITE_OK); + }); + CFReleaseNull(cf_path); + return result; +} + +- (void)testNewDatabase +{ + [self writeResponse1ToDB]; + XCTAssert([self canReadDB]); +} + +- (void)testNewDatabaseReOpen +{ + [self writeResponse1ToDB]; + XCTAssert([self canReadDB]); + SecOCSPCacheCloseDB(); + XCTAssert([self canReadDB]); + [self replaceResponse]; + XCTAssert([self canReadDB]); +} + +- (void)testOldDatabaseUpgradeNoContent +{ + [self createDBFromSQL:_oldDBSchema]; + [self writeResponse1ToDB]; + XCTAssert([self canReadDB]); +} + +- (void)testOldDatabaseUpgradeWithContent +{ + [self createDBFromSQL:_oldDBSchemaWithContent]; + XCTAssert([self canReadDB]); + [self replaceResponse]; + XCTAssert([self canReadDB]); +} + +- (void)testUpgradedDatabaseNoContent +{ + [self createDBFromSQL:_oldDBSchema]; + XCTAssertFalse([self canReadDB]); // should upgrade the DB + SecOCSPCacheCloseDB(); + [self writeResponse1ToDB]; + XCTAssert([self canReadDB]); +} + +- (void)testUpgradedDatabaseWithContent +{ + [self createDBFromSQL:_oldDBSchemaWithContent]; + XCTAssert([self canReadDB]); // should upgrade the DB + SecOCSPCacheCloseDB(); + [self replaceResponse]; + XCTAssert([self canReadDB]); +} + +- (void)testGCExpiredResponses +{ + [self createDBFromSQL:_oldDBSchemaWithContent]; // since this is an old schema, the certStatus will be CS_NotParsed + /* don't replace response 1, just add response 2 a week after response 1 expired */ + [self writeResponse2ToDB]; // as a side effect, should GC the expired non-revoked response + SecOCSPCacheCloseDB(); + XCTAssertEqual([self countEntries], 1); +} + +- (void)testNoGCExpiredRevokedResponses +{ + [self writeResponse1ToDB]; + /* don't replace response 1, just add response 2 a week after response 1 expired */ + [self writeResponse2ToDB]; // should not GC the expired revoked response 1 + SecOCSPCacheCloseDB(); + XCTAssertEqual([self countEntries], 2); +} + +@end diff --git a/tests/TrustTests/DaemonTests/OCSPCacheTests_data.h b/tests/TrustTests/DaemonTests/OCSPCacheTests_data.h new file mode 100644 index 00000000..ef56050a --- /dev/null +++ b/tests/TrustTests/DaemonTests/OCSPCacheTests_data.h @@ -0,0 +1,476 @@ +/* +* Copyright (c) 2019 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +* +*/ + +#ifndef _TRUSTTESTS_DAEMON_OCSP_CACHE_TESTS_H_ +#define _TRUSTTESTS_DAEMON_OCSP_CACHE_TESTS_H_ + +const uint8_t _ocsp_response1[] = { + 0x30,0x82,0x09,0xcb,0x0a,0x01,0x00,0xa0,0x82,0x09,0xc4,0x30,0x82,0x09,0xc0,0x06,0x09,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x30,0x01,0x01,0x04,0x82,0x09,0xb1,0x30,0x82,0x09,0xad,0x30,0x81,0xb2,0xa2,0x16,0x04, + 0x14,0xd5,0x02,0x45,0x68,0xa0,0x3d,0x2c,0x63,0x40,0x22,0x62,0xb7,0x9c,0x0e,0x85,0x69,0x74,0xb4,0x30, + 0xe8,0x18,0x0f,0x32,0x30,0x31,0x39,0x31,0x31,0x31,0x36,0x30,0x31,0x31,0x32,0x32,0x31,0x5a,0x30,0x81, + 0x86,0x30,0x81,0x83,0x30,0x41,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0x33, + 0x81,0xd1,0xef,0xdb,0x68,0xb0,0x85,0x21,0x4d,0x2e,0xef,0xaf,0x8c,0x4a,0x69,0x64,0x3c,0x2a,0x6c,0x04, + 0x14,0x57,0x17,0xed,0xa2,0xcf,0xdc,0x7c,0x98,0xa1,0x10,0xe0,0xfc,0xbe,0x87,0x2d,0x2c,0xf2,0xe3,0x17, + 0x54,0x02,0x08,0x03,0xb5,0x01,0x60,0xcb,0x4d,0x00,0xde,0xa1,0x16,0x18,0x0f,0x32,0x30,0x31,0x37,0x30, + 0x36,0x31,0x36,0x30,0x34,0x35,0x34,0x30,0x30,0x5a,0xa0,0x03,0x0a,0x01,0x04,0x18,0x0f,0x32,0x30,0x31, + 0x39,0x31,0x31,0x31,0x36,0x30,0x31,0x31,0x32,0x32,0x31,0x5a,0xa0,0x11,0x18,0x0f,0x32,0x30,0x31,0x39, + 0x31,0x31,0x31,0x36,0x31,0x33,0x31,0x32,0x32,0x31,0x5a,0xa1,0x02,0x30,0x00,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x83,0x4f,0x47,0x06,0xe9, + 0x00,0x22,0xf6,0x8c,0xed,0xea,0x79,0xc3,0xa3,0xb5,0xcd,0x9d,0xbf,0x49,0xec,0xea,0x78,0xff,0xda,0xcd, + 0xa8,0xd0,0xdd,0xeb,0x0c,0x4d,0x6d,0x68,0x6a,0x98,0xb4,0xaf,0x6c,0x35,0x1b,0xcb,0x7e,0xf2,0x99,0x24, + 0x88,0x87,0xce,0x2b,0x6e,0xba,0x97,0xfe,0x01,0xc9,0x14,0x5e,0xac,0x69,0x9b,0xb8,0x99,0x6c,0x4b,0xe1, + 0x9e,0x6b,0xe3,0x3f,0xd7,0xf5,0xc7,0x9b,0x49,0x37,0x6a,0xa8,0x63,0x24,0x12,0x2d,0xd0,0xf8,0x2f,0xb3, + 0x59,0xe8,0x77,0xb0,0x2b,0x83,0x04,0x7f,0x77,0x38,0x72,0x13,0x1a,0xa1,0xfc,0x53,0x28,0x50,0xc1,0x21, + 0x9c,0xba,0xf0,0xd0,0xee,0xb2,0x13,0xd9,0x72,0xee,0x89,0xd6,0x78,0xdd,0x42,0x0b,0x62,0xf5,0x6c,0x8a, + 0xdd,0x11,0xf6,0x55,0x69,0x35,0xf9,0x9b,0x4c,0x36,0x39,0x37,0xf7,0xe5,0x4a,0x91,0x9a,0x8e,0x84,0x59, + 0x2a,0xbb,0x20,0xd3,0x1d,0xce,0x95,0x5c,0x77,0xd5,0x15,0x5a,0x1f,0x86,0xec,0xa9,0xaf,0xaa,0x34,0xda, + 0xa7,0xb7,0x7d,0xc1,0x61,0xb2,0x45,0xd9,0xc2,0x79,0x55,0x6c,0xe1,0xba,0xfd,0x47,0x44,0x27,0xc3,0x74, + 0xfd,0x1e,0xeb,0x90,0xb6,0xe6,0x49,0x0f,0x28,0xa8,0x88,0x8c,0xcb,0x4a,0x87,0xaa,0x05,0xf7,0x9b,0x05, + 0xe0,0xd2,0xca,0xb7,0x72,0x20,0x46,0x97,0xb5,0x37,0xd8,0x20,0x4d,0x3e,0x56,0x45,0x93,0xf1,0xe6,0x83, + 0x89,0xd6,0x3c,0x53,0x7c,0xea,0xcb,0xb1,0x3e,0x99,0x05,0x8e,0xa3,0x1a,0x98,0x88,0x95,0xe7,0x04,0xcc, + 0xb3,0x8f,0x57,0x0b,0x4a,0x67,0x2f,0xc2,0x93,0x52,0xe2,0xa0,0x82,0x07,0xe0,0x30,0x82,0x07,0xdc,0x30, + 0x82,0x03,0xd0,0x30,0x82,0x02,0xb8,0xa0,0x03,0x02,0x01,0x02,0x02,0x08,0x6f,0x0d,0x6c,0x67,0x66,0x49, + 0x04,0xc5,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x79,0x31, + 0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x0c,0x24,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x20, + 0x49,0x44,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74, + 0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x0c,0x1d,0x41,0x70,0x70, + 0x6c,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74, + 0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70, + 0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 0x30,0x1e,0x17,0x0d,0x31,0x39,0x31,0x30,0x31,0x38,0x30,0x35,0x32,0x39,0x31,0x36,0x5a,0x17,0x0d,0x31, + 0x39,0x31,0x31,0x32,0x39,0x30,0x35,0x32,0x39,0x31,0x36,0x5a,0x30,0x4d,0x31,0x29,0x30,0x27,0x06,0x03, + 0x55,0x04,0x03,0x0c,0x20,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x20,0x49,0x44,0x20,0x4f,0x43, + 0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6f,0x6e,0x64,0x65,0x72,0x20,0x4e,0x4c,0x30,0x37,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x0b, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02, + 0x82,0x01,0x01,0x00,0xa0,0xb8,0xae,0xe4,0x5b,0xe6,0xdd,0x9e,0x87,0xd6,0x27,0x4b,0xbc,0x8e,0xcf,0x79, + 0x34,0x49,0xa5,0xea,0xf0,0x72,0x4d,0xdc,0xe7,0x5e,0x07,0xc2,0x0a,0xd0,0xd1,0xab,0x36,0xe1,0x37,0x91, + 0x9c,0x60,0xc0,0xd1,0xff,0x4a,0x84,0x13,0xec,0xf1,0x11,0x1b,0x3f,0xb9,0x94,0x83,0xe5,0x22,0x22,0xdf, + 0x31,0x79,0xf8,0x3f,0x41,0xc6,0xfe,0x76,0xb0,0x68,0xe1,0x6d,0xb8,0x2f,0xb0,0x62,0x64,0xef,0xf4,0x9b, + 0xcc,0xd1,0xea,0x8f,0xd4,0xdf,0x2e,0x8f,0xc1,0x8e,0xff,0x02,0x67,0xdb,0xc6,0xd8,0x12,0x42,0x87,0x34, + 0x37,0x6d,0xbd,0xdc,0x7c,0xb7,0xfe,0xd5,0x3e,0x7e,0x0a,0x7e,0x82,0x9d,0x07,0x87,0x28,0xf7,0x9b,0xbd, + 0x0f,0x27,0x9c,0xbf,0xfb,0x39,0xd9,0xd5,0x3c,0xf6,0x63,0xae,0xc8,0xe8,0x19,0x27,0x28,0xab,0x94,0xc5, + 0x15,0x53,0xad,0x61,0x77,0xb2,0x5d,0x85,0x1b,0x21,0x80,0x4a,0xae,0x48,0xdb,0x7d,0xd0,0x74,0xd4,0xde, + 0x84,0xa4,0x50,0xd4,0x69,0x04,0x3f,0xee,0x17,0x8b,0x69,0x21,0x9f,0xe4,0x0b,0x80,0x43,0xb6,0x92,0x8d, + 0x87,0x83,0xdd,0xa7,0x12,0x63,0x34,0x47,0xea,0xfb,0x6b,0x7b,0x47,0xfb,0x28,0x17,0x5c,0x4b,0x01,0x8f, + 0x56,0x5f,0x35,0xc1,0x00,0xef,0x92,0x57,0x81,0x4b,0x2e,0x62,0x61,0xe8,0x14,0x5a,0x6b,0x44,0xf7,0x43, + 0x7e,0x88,0x61,0xd2,0xf7,0xd0,0x4f,0x39,0x2f,0xdc,0xa2,0x21,0x28,0xd3,0x43,0x22,0xf1,0x7a,0xed,0x36, + 0x0c,0x4e,0xf5,0xfb,0x64,0x10,0x95,0xb9,0x2b,0x91,0xb9,0xec,0x20,0xda,0x92,0x5d,0xf9,0xf5,0x61,0x1d, + 0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0x87,0x30,0x81,0x84,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01, + 0xff,0x04,0x02,0x30,0x00,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x57,0x17, + 0xed,0xa2,0xcf,0xdc,0x7c,0x98,0xa1,0x10,0xe0,0xfc,0xbe,0x87,0x2d,0x2c,0xf2,0xe3,0x17,0x54,0x30,0x0f, + 0x06,0x09,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x05,0x04,0x02,0x05,0x00,0x30,0x13,0x06,0x03,0x55, + 0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x09,0x30,0x1d,0x06,0x03, + 0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xd5,0x02,0x45,0x68,0xa0,0x3d,0x2c,0x63,0x40,0x22,0x62,0xb7,0x9c, + 0x0e,0x85,0x69,0x74,0xb4,0x30,0xe8,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03, + 0x02,0x07,0x80,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x65,0x0c,0x41,0xf8,0xe1,0x16,0xb7,0xd7,0x61,0xe1,0x6a,0xaf,0x12,0x2e,0x70,0xef,0x0a, + 0x40,0xa4,0xd0,0xe2,0x91,0x70,0xbd,0xdb,0xda,0x65,0x62,0x8b,0x40,0x45,0x23,0xc9,0xe8,0xa4,0xd0,0x33, + 0xf7,0xd1,0xa5,0x80,0x4a,0x3a,0xc8,0x76,0x2d,0x20,0xfe,0x27,0x4b,0x30,0xdf,0xa4,0x00,0x35,0x3d,0x1c, + 0x80,0x7c,0xc5,0x09,0x89,0x47,0xd4,0x78,0x7d,0x14,0xdf,0xa1,0xef,0x16,0xad,0xb1,0xca,0xf4,0xf6,0x09, + 0xab,0xc4,0xdc,0x4d,0x72,0x69,0x87,0x9b,0x5b,0x82,0xbb,0xa7,0x68,0x5e,0xfd,0x80,0x29,0x68,0x2d,0xd5, + 0xa0,0x78,0x04,0x57,0x77,0xd0,0x69,0x57,0xfa,0x83,0xb9,0xf0,0x42,0x42,0x71,0xae,0xfe,0xff,0x0b,0xbd, + 0xd3,0xfb,0x3c,0x17,0x01,0x71,0xe2,0x5e,0x81,0xbe,0x72,0xe0,0x75,0xba,0x41,0x0d,0xf0,0x10,0x71,0x02, + 0x36,0xf3,0x26,0x4a,0x01,0x5c,0xa8,0x21,0xe0,0xb2,0x86,0x27,0x1b,0x5e,0xc1,0xb0,0xb0,0x4f,0xdc,0x77, + 0x89,0xe5,0x5c,0x15,0x9a,0x72,0x39,0xaf,0x57,0xe1,0x94,0x2c,0xa3,0x46,0x44,0xce,0x0d,0xe9,0xf1,0xe6, + 0xfa,0xd9,0x6f,0x1e,0x01,0x28,0x1a,0x0e,0x68,0xf4,0x6c,0xf3,0xbd,0x4a,0xf8,0x3a,0xdf,0x93,0x72,0x05, + 0x4f,0x88,0x4b,0x7e,0x13,0xb6,0x92,0xe3,0x28,0xd0,0x14,0x3c,0x13,0x28,0x6d,0x11,0x27,0x36,0xbc,0x73, + 0x27,0xab,0xfc,0x3f,0xb1,0x00,0xab,0x9b,0x35,0x7a,0x87,0x71,0x0e,0x54,0x03,0x68,0x02,0xb2,0xfc,0x8c, + 0x17,0xf3,0x73,0x7e,0xea,0x75,0x64,0x19,0x56,0x9c,0xac,0xb8,0xe6,0x50,0x7c,0x48,0x94,0xec,0x0e,0x30, + 0x82,0x04,0x04,0x30,0x82,0x02,0xec,0xa0,0x03,0x02,0x01,0x02,0x02,0x08,0x18,0x7a,0xa9,0xa8,0xc2,0x96, + 0x21,0x0c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x62,0x31, + 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0a,0x13,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x26,0x30,0x24,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x1d,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, + 0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0d,0x41,0x70,0x70,0x6c,0x65,0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x41,0x30,0x1e,0x17, + 0x0d,0x31,0x32,0x30,0x32,0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5a,0x17,0x0d,0x32,0x37,0x30,0x32, + 0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5a,0x30,0x79,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03, + 0x0c,0x24,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x20,0x49,0x44,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x26, + 0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x0c,0x1d,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31, + 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09, + 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a, + 0x02,0x82,0x01,0x01,0x00,0x89,0x76,0x4f,0x06,0x5b,0x9a,0x41,0xee,0xa5,0x23,0x2b,0x02,0xa3,0x5f,0xd7, + 0x73,0x3f,0xc0,0x35,0xb0,0x8b,0x84,0x0a,0x3f,0x06,0x24,0x7f,0xa7,0x95,0x3f,0xeb,0x4f,0x0e,0x93,0xaf, + 0xb4,0x0e,0xd0,0xc8,0x3e,0xe5,0x6d,0x18,0xb3,0x1f,0xe8,0x89,0x47,0xbf,0xd7,0x09,0x08,0xe4,0xff,0x56, + 0x98,0x29,0x15,0xe7,0x94,0x9d,0xb9,0x35,0xa3,0x0a,0xcd,0xb4,0xc0,0xe1,0xe2,0x60,0xf4,0xca,0xec,0x29, + 0x78,0x45,0x69,0x69,0x60,0x6b,0x5f,0x8a,0x92,0xfc,0x9e,0x23,0xe6,0x3a,0xc2,0x22,0xb3,0x31,0x4f,0x1c, + 0xba,0xf2,0xb6,0x34,0x59,0x42,0xee,0xb0,0xa9,0x02,0x03,0x18,0x91,0x04,0xb6,0xb3,0x78,0x2e,0x33,0x1f, + 0x80,0x45,0x0d,0x45,0x6f,0xbb,0x0e,0x5a,0x5b,0x7f,0x3a,0xe7,0xd8,0x08,0xd7,0x0b,0x0e,0x32,0x6d,0xfb, + 0x86,0x36,0xe4,0x6c,0xab,0xc4,0x11,0x8a,0x70,0x84,0x26,0xaa,0x9f,0x44,0xd1,0xf1,0xb8,0xc6,0x7b,0x94, + 0x17,0x9b,0x48,0xf7,0x0b,0x58,0x16,0xba,0x23,0xc5,0x9f,0x15,0x39,0x7e,0xca,0x5d,0xc3,0x32,0x5f,0x0f, + 0xe0,0x52,0x7f,0x40,0xea,0xbe,0xac,0x08,0x64,0x95,0x5b,0xc9,0x1a,0x9c,0xe5,0x80,0xca,0x1f,0x6a,0x44, + 0x1c,0x6c,0x3e,0xc4,0xb0,0x26,0x1f,0x1d,0xec,0x7b,0xaf,0x5e,0xa0,0x6a,0x3d,0x47,0xa9,0x58,0x12,0x31, + 0x3f,0x20,0x76,0x28,0x6d,0x1d,0x1c,0xb0,0xc2,0x4e,0x11,0x69,0x26,0x8b,0xcb,0xd6,0xd0,0x11,0x82,0xc9, + 0x4e,0x0f,0xf1,0x56,0x74,0xd0,0xd9,0x08,0x4b,0x66,0x78,0xa2,0xab,0xac,0xa7,0xe2,0xd2,0x4c,0x87,0x59, + 0xc9,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xa6,0x30,0x81,0xa3,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04, + 0x16,0x04,0x14,0x57,0x17,0xed,0xa2,0xcf,0xdc,0x7c,0x98,0xa1,0x10,0xe0,0xfc,0xbe,0x87,0x2d,0x2c,0xf2, + 0xe3,0x17,0x54,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x2b,0xd0,0x69,0x47,0x94,0x76,0x09, + 0xfe,0xf4,0x6b,0x8d,0x2e,0x40,0xa6,0xf7,0x47,0x4d,0x7f,0x08,0x5e,0x30,0x2e,0x06,0x03,0x55,0x1d,0x1f, + 0x04,0x27,0x30,0x25,0x30,0x23,0xa0,0x21,0xa0,0x1f,0x86,0x1d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x6c,0x2e,0x61,0x70,0x70,0x6c,0x65,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x6f,0x6f,0x74,0x2e,0x63,0x72, + 0x6c,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x10,0x06, + 0x0a,0x2a,0x86,0x48,0x86,0xf7,0x63,0x64,0x06,0x02,0x06,0x04,0x02,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x42,0x39,0x74,0x6b,0xa1, + 0xdc,0xc6,0xa4,0x8f,0x37,0x2a,0x8c,0xb3,0x1d,0x0a,0x44,0xbc,0x95,0x2c,0x7f,0xbc,0x59,0xb8,0xac,0x61, + 0xfb,0x07,0x90,0x92,0x32,0xb9,0xd4,0xbf,0x3b,0xc1,0x50,0x39,0x6a,0x44,0x74,0xa2,0xec,0x5b,0x1f,0x70, + 0xe5,0xaa,0xdd,0x4b,0x6c,0x1c,0x23,0x71,0x2d,0x5f,0xd1,0xc5,0x93,0xbe,0xee,0x9b,0x8a,0x70,0x65,0x82, + 0x9d,0x16,0xe3,0x1a,0x10,0x17,0x89,0x2d,0xa8,0xcd,0xfd,0x0c,0x78,0x58,0x49,0x0c,0x28,0x7f,0x33,0xee, + 0x00,0x7a,0x1b,0xb4,0x76,0xac,0xb6,0xb5,0xbb,0x4f,0xdf,0xa8,0x1b,0x9d,0xc8,0x19,0x97,0x4a,0x0b,0x56, + 0x67,0x2f,0xc2,0x3e,0xb6,0xb3,0xc4,0x83,0x3a,0xf0,0x77,0x6d,0x74,0xc4,0x2e,0x23,0x51,0xee,0x9a,0xa5, + 0x03,0x6f,0x60,0xf4,0xa5,0x48,0xa7,0x06,0xc2,0xbb,0x5a,0xe2,0x1f,0x1f,0x46,0x45,0x7e,0xe4,0x97,0xf5, + 0x27,0x10,0xb7,0x20,0x22,0x72,0x6f,0x72,0xda,0xc6,0x50,0x75,0xc5,0x3d,0x25,0x8f,0x5d,0xa3,0x00,0xe9, + 0x9f,0x36,0x8c,0x48,0x39,0x8f,0xb3,0x3b,0xea,0x90,0x80,0x2e,0x95,0x9a,0x60,0xf4,0x78,0xce,0xf4,0x0e, + 0x0a,0x53,0x3e,0xa2,0xfa,0x4f,0xd8,0x1e,0xae,0x84,0x95,0x8d,0x32,0xbc,0x56,0x4d,0x89,0xe9,0x78,0x18, + 0xe0,0xac,0x9a,0x42,0xba,0x7a,0x46,0x1b,0x84,0xa2,0x89,0xce,0x14,0xe8,0x88,0xd1,0x58,0x8b,0xf6,0xae, + 0x56,0xc4,0x2c,0x05,0x2a,0x45,0xaf,0x0b,0xd9,0x4b,0xa9,0x02,0x0f,0x34,0xac,0x88,0xc7,0x61,0x55,0x89, + 0x44,0xc9,0x27,0x73,0x07,0xee,0x82,0xe5,0x4e,0xf5,0x70 +}; + +const uint8_t _ocsp_response2[] = { + 0x30,0x82,0x09,0xcb,0x0a,0x01,0x00,0xa0,0x82,0x09,0xc4,0x30,0x82,0x09,0xc0,0x06,0x09,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x30,0x01,0x01,0x04,0x82,0x09,0xb1,0x30,0x82,0x09,0xad,0x30,0x81,0xb2,0xa2,0x16,0x04, + 0x14,0x5d,0xbe,0xc7,0xf0,0xf1,0x0e,0x9e,0x8c,0x06,0xce,0xad,0xa6,0x49,0xfb,0xc1,0xfc,0x01,0x90,0x27, + 0x97,0x18,0x0f,0x32,0x30,0x31,0x39,0x31,0x31,0x32,0x32,0x31,0x39,0x30,0x30,0x32,0x36,0x5a,0x30,0x81, + 0x86,0x30,0x81,0x83,0x30,0x41,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0x33, + 0x81,0xd1,0xef,0xdb,0x68,0xb0,0x85,0x21,0x4d,0x2e,0xef,0xaf,0x8c,0x4a,0x69,0x64,0x3c,0x2a,0x6c,0x04, + 0x14,0x57,0x17,0xed,0xa2,0xcf,0xdc,0x7c,0x98,0xa1,0x10,0xe0,0xfc,0xbe,0x87,0x2d,0x2c,0xf2,0xe3,0x17, + 0x54,0x02,0x08,0x03,0xb5,0x01,0x60,0xcb,0x4d,0x00,0xde,0xa1,0x16,0x18,0x0f,0x32,0x30,0x31,0x37,0x30, + 0x36,0x31,0x36,0x30,0x34,0x35,0x34,0x30,0x30,0x5a,0xa0,0x03,0x0a,0x01,0x04,0x18,0x0f,0x32,0x30,0x31, + 0x39,0x31,0x31,0x32,0x32,0x31,0x39,0x30,0x30,0x32,0x36,0x5a,0xa0,0x11,0x18,0x0f,0x32,0x30,0x31,0x39, + 0x31,0x31,0x32,0x33,0x30,0x37,0x30,0x30,0x32,0x36,0x5a,0xa1,0x02,0x30,0x00,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x00,0xb2,0x91,0x33,0x70, + 0xd3,0xb5,0x9d,0x66,0x76,0xdc,0xea,0x78,0x1c,0x80,0xfa,0x9c,0x5b,0x16,0x7e,0xb2,0xeb,0x7b,0xd7,0x3f, + 0xeb,0x55,0xfc,0x1a,0xa3,0xea,0xfb,0xc0,0xc2,0x89,0x94,0x48,0xee,0x8c,0xd2,0xbc,0xa2,0x67,0xe9,0xff, + 0x89,0x6f,0x31,0x6d,0x6b,0x59,0x93,0xdf,0x01,0xda,0x74,0x35,0x39,0x55,0x8b,0x62,0x28,0x2f,0xfa,0x76, + 0x46,0x5c,0x4a,0xce,0x9f,0x27,0x84,0x83,0x7b,0xae,0xcd,0xa3,0x0c,0x5b,0x2d,0xbe,0x43,0x5b,0x8f,0xf7, + 0x8c,0xb1,0x5a,0x45,0xce,0x65,0x93,0x84,0xbd,0x26,0x79,0x5a,0xf6,0x0c,0x65,0x2b,0xf0,0xf5,0xe1,0x1f, + 0xeb,0xfd,0x22,0x8a,0xcd,0xaa,0x3d,0xd8,0x5e,0xf8,0xd2,0x3f,0xdb,0xd6,0x4f,0xb6,0xa9,0x01,0xfe,0x1b, + 0x63,0xb5,0xbe,0x55,0x28,0xf8,0xa3,0x07,0x5c,0xd4,0x8e,0x45,0xbf,0x36,0xe9,0x23,0xa8,0x06,0xfa,0xe2, + 0x4a,0x2f,0x09,0x18,0x8b,0x90,0x3e,0x1f,0xba,0x11,0x52,0x10,0xed,0x69,0xa9,0xbb,0xe4,0x94,0xa0,0x10, + 0x4b,0xf4,0xb5,0xad,0xc6,0x26,0xee,0xee,0x81,0xa8,0x61,0xe6,0x1a,0xbf,0x6b,0xbd,0x76,0xcc,0xfb,0xa1, + 0xa1,0xcb,0x97,0x6b,0xe6,0x39,0xad,0x57,0xa3,0xeb,0x94,0x43,0x8a,0x26,0x5e,0x89,0x2c,0xd9,0x19,0x52, + 0xe7,0x85,0x54,0xaf,0x9d,0xa7,0x44,0xf5,0xf0,0xef,0x07,0x38,0x2a,0x75,0x3a,0x4d,0xb0,0xd4,0xc7,0xe0, + 0xa2,0x39,0x24,0x75,0x30,0x2b,0xac,0x12,0x7e,0x01,0xcf,0x29,0x09,0x83,0x96,0xe3,0xbe,0x7e,0x06,0x53, + 0x02,0x49,0x16,0xca,0xa5,0xc3,0xfc,0x6e,0x2a,0xed,0xf6,0xa0,0x82,0x07,0xe0,0x30,0x82,0x07,0xdc,0x30, + 0x82,0x03,0xd0,0x30,0x82,0x02,0xb8,0xa0,0x03,0x02,0x01,0x02,0x02,0x08,0x26,0xfa,0xf5,0x12,0x8f,0xf8, + 0x97,0x82,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x79,0x31, + 0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x0c,0x24,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x20, + 0x49,0x44,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74, + 0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x0c,0x1d,0x41,0x70,0x70, + 0x6c,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74, + 0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70, + 0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 0x30,0x1e,0x17,0x0d,0x31,0x39,0x31,0x31,0x32,0x31,0x32,0x32,0x34,0x31,0x30,0x39,0x5a,0x17,0x0d,0x32, + 0x30,0x30,0x31,0x30,0x32,0x32,0x32,0x34,0x31,0x30,0x39,0x5a,0x30,0x4d,0x31,0x29,0x30,0x27,0x06,0x03, + 0x55,0x04,0x03,0x0c,0x20,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x20,0x49,0x44,0x20,0x4f,0x43, + 0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6f,0x6e,0x64,0x65,0x72,0x20,0x4e,0x4c,0x30,0x37,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x0b, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02, + 0x82,0x01,0x01,0x00,0xb0,0xd4,0x51,0x76,0xdb,0xd6,0xb8,0xee,0x65,0x96,0x19,0x3f,0x9e,0xa0,0x30,0x23, + 0xfa,0xbf,0x31,0x48,0x44,0x6a,0x8c,0x1e,0xcb,0x4d,0x2a,0x1c,0x6f,0x31,0x24,0x9c,0x72,0x4e,0x1f,0xab, + 0xe8,0xde,0x6a,0xaa,0x90,0x07,0x9c,0x38,0xcb,0x7a,0x22,0x6c,0xec,0x0d,0x6d,0x56,0x69,0x69,0x87,0xd3, + 0x59,0xc2,0x03,0x17,0xb1,0x9f,0xb0,0x40,0x4b,0xfe,0x12,0x46,0xc4,0xc1,0xa2,0x8c,0x11,0x4f,0x46,0x81, + 0xf3,0x12,0x68,0x66,0xd9,0xa1,0x0d,0x73,0x69,0xca,0x27,0xe4,0x30,0xbd,0xaa,0x1f,0x16,0xf9,0x7c,0x40, + 0x38,0xbc,0x1b,0x6b,0x31,0xf1,0xc8,0xc1,0x4a,0x69,0x0e,0x38,0xb5,0xda,0x66,0x37,0xc3,0x85,0xfd,0x34, + 0x16,0x0f,0xdd,0x0f,0x2d,0x85,0xf3,0xf7,0xe8,0x48,0x65,0xbc,0xd0,0x44,0xa2,0x1d,0x48,0x41,0xd1,0x40, + 0x2c,0xdd,0x71,0xf4,0x9d,0xd3,0x2f,0xf3,0xe1,0xca,0xe5,0x1b,0x24,0xb5,0x54,0xac,0x1f,0x16,0x62,0x24, + 0x62,0xbe,0xe4,0x5f,0x90,0x63,0xc3,0xf0,0xcd,0x68,0xd4,0x51,0x94,0x96,0x4d,0x96,0x40,0x18,0x18,0xd6, + 0x50,0xa9,0x77,0xb9,0x04,0x79,0xf2,0x6f,0xe4,0x0e,0x3e,0xd6,0xbf,0xaf,0xe6,0x70,0x6d,0x2d,0x6a,0x15, + 0x05,0x95,0x35,0xb3,0x1d,0x97,0xa0,0x4e,0xd8,0xb1,0x27,0xfe,0xf8,0xc2,0x3f,0x02,0xa4,0x2c,0xe7,0x73, + 0x29,0x9b,0x24,0x28,0x59,0x24,0x38,0x69,0x07,0xa7,0x55,0x63,0x90,0x46,0xf8,0xae,0x64,0xe7,0x09,0x88, + 0xce,0x47,0xe8,0x50,0x52,0x87,0xbc,0x5f,0xec,0xa4,0xc0,0x2d,0x8d,0x5e,0xbd,0xa5,0x16,0xf7,0x73,0xdb, + 0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0x87,0x30,0x81,0x84,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01, + 0xff,0x04,0x02,0x30,0x00,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x57,0x17, + 0xed,0xa2,0xcf,0xdc,0x7c,0x98,0xa1,0x10,0xe0,0xfc,0xbe,0x87,0x2d,0x2c,0xf2,0xe3,0x17,0x54,0x30,0x0f, + 0x06,0x09,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x05,0x04,0x02,0x05,0x00,0x30,0x13,0x06,0x03,0x55, + 0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x09,0x30,0x1d,0x06,0x03, + 0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0x5d,0xbe,0xc7,0xf0,0xf1,0x0e,0x9e,0x8c,0x06,0xce,0xad,0xa6,0x49, + 0xfb,0xc1,0xfc,0x01,0x90,0x27,0x97,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03, + 0x02,0x07,0x80,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x16,0x9d,0x0a,0x5f,0xca,0x08,0xec,0xb8,0xaa,0xb0,0x43,0xaf,0x74,0xd9,0xac,0x0d,0xd0, + 0x09,0x24,0x10,0x31,0x94,0x73,0x77,0xb0,0xbc,0x9d,0xfd,0x52,0x18,0xf2,0x88,0xdc,0x7e,0xfd,0x47,0x69, + 0xf3,0x5f,0xb7,0x51,0xc7,0xe9,0xd1,0x2e,0x1b,0x7b,0x71,0xc3,0x88,0xaf,0xe4,0x45,0xbd,0x24,0xea,0x7f, + 0xeb,0xe6,0x4d,0x8b,0xe7,0xc7,0xfa,0xf7,0xe6,0xa3,0xbb,0x40,0x0d,0xfe,0xf7,0x08,0xe0,0x8f,0xce,0xd0, + 0x9c,0x4d,0xb4,0x75,0xe4,0xac,0xe8,0x32,0xe0,0x3e,0xd9,0x4a,0xf2,0x95,0xa9,0xc3,0xe1,0x4f,0xf4,0x39, + 0x55,0x76,0xdf,0xc5,0x01,0x73,0xb6,0x99,0x5b,0x4a,0x20,0xd8,0xe2,0x5a,0xa0,0xcb,0x11,0xaa,0xb9,0x4b, + 0x6c,0x6d,0xcf,0x01,0x7e,0x21,0x32,0xd3,0x06,0x84,0x48,0xe4,0xc9,0xfc,0x72,0xe0,0xc1,0xff,0x58,0x93, + 0xec,0x31,0x81,0x50,0x16,0x6e,0x5c,0xde,0x87,0x99,0x60,0x57,0xa6,0x2b,0xac,0x2f,0x7d,0x74,0x2e,0x4d, + 0x97,0x5d,0xe3,0xe3,0xe8,0x76,0x95,0xc1,0xeb,0x25,0x29,0xd5,0xc1,0x03,0x85,0x2d,0x11,0xb0,0xdf,0xb1, + 0x29,0x55,0x56,0x00,0xda,0xe0,0xf6,0x95,0xd2,0x8b,0xf4,0x44,0x5d,0xf5,0xbc,0x22,0xc1,0x71,0x02,0x03, + 0x16,0xf0,0x77,0xd9,0x29,0xa8,0xe8,0xdf,0x75,0x13,0x1b,0xb6,0x76,0x8c,0x1d,0x37,0x1f,0x68,0xb7,0xa0, + 0x7f,0xaa,0x41,0x96,0x80,0xf6,0x1b,0x97,0x0e,0x64,0x9e,0x19,0xb7,0x27,0x78,0x1e,0x8b,0x8c,0x31,0x79, + 0xa6,0xb8,0x99,0x57,0xc8,0x6d,0x5d,0x80,0x50,0xd4,0x60,0xec,0xac,0xdb,0x35,0x05,0x8a,0xe2,0xa0,0x30, + 0x82,0x04,0x04,0x30,0x82,0x02,0xec,0xa0,0x03,0x02,0x01,0x02,0x02,0x08,0x18,0x7a,0xa9,0xa8,0xc2,0x96, + 0x21,0x0c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x62,0x31, + 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0a,0x13,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x26,0x30,0x24,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x1d,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, + 0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0d,0x41,0x70,0x70,0x6c,0x65,0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x41,0x30,0x1e,0x17, + 0x0d,0x31,0x32,0x30,0x32,0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5a,0x17,0x0d,0x32,0x37,0x30,0x32, + 0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5a,0x30,0x79,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03, + 0x0c,0x24,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x20,0x49,0x44,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x26, + 0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x0c,0x1d,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31, + 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09, + 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a, + 0x02,0x82,0x01,0x01,0x00,0x89,0x76,0x4f,0x06,0x5b,0x9a,0x41,0xee,0xa5,0x23,0x2b,0x02,0xa3,0x5f,0xd7, + 0x73,0x3f,0xc0,0x35,0xb0,0x8b,0x84,0x0a,0x3f,0x06,0x24,0x7f,0xa7,0x95,0x3f,0xeb,0x4f,0x0e,0x93,0xaf, + 0xb4,0x0e,0xd0,0xc8,0x3e,0xe5,0x6d,0x18,0xb3,0x1f,0xe8,0x89,0x47,0xbf,0xd7,0x09,0x08,0xe4,0xff,0x56, + 0x98,0x29,0x15,0xe7,0x94,0x9d,0xb9,0x35,0xa3,0x0a,0xcd,0xb4,0xc0,0xe1,0xe2,0x60,0xf4,0xca,0xec,0x29, + 0x78,0x45,0x69,0x69,0x60,0x6b,0x5f,0x8a,0x92,0xfc,0x9e,0x23,0xe6,0x3a,0xc2,0x22,0xb3,0x31,0x4f,0x1c, + 0xba,0xf2,0xb6,0x34,0x59,0x42,0xee,0xb0,0xa9,0x02,0x03,0x18,0x91,0x04,0xb6,0xb3,0x78,0x2e,0x33,0x1f, + 0x80,0x45,0x0d,0x45,0x6f,0xbb,0x0e,0x5a,0x5b,0x7f,0x3a,0xe7,0xd8,0x08,0xd7,0x0b,0x0e,0x32,0x6d,0xfb, + 0x86,0x36,0xe4,0x6c,0xab,0xc4,0x11,0x8a,0x70,0x84,0x26,0xaa,0x9f,0x44,0xd1,0xf1,0xb8,0xc6,0x7b,0x94, + 0x17,0x9b,0x48,0xf7,0x0b,0x58,0x16,0xba,0x23,0xc5,0x9f,0x15,0x39,0x7e,0xca,0x5d,0xc3,0x32,0x5f,0x0f, + 0xe0,0x52,0x7f,0x40,0xea,0xbe,0xac,0x08,0x64,0x95,0x5b,0xc9,0x1a,0x9c,0xe5,0x80,0xca,0x1f,0x6a,0x44, + 0x1c,0x6c,0x3e,0xc4,0xb0,0x26,0x1f,0x1d,0xec,0x7b,0xaf,0x5e,0xa0,0x6a,0x3d,0x47,0xa9,0x58,0x12,0x31, + 0x3f,0x20,0x76,0x28,0x6d,0x1d,0x1c,0xb0,0xc2,0x4e,0x11,0x69,0x26,0x8b,0xcb,0xd6,0xd0,0x11,0x82,0xc9, + 0x4e,0x0f,0xf1,0x56,0x74,0xd0,0xd9,0x08,0x4b,0x66,0x78,0xa2,0xab,0xac,0xa7,0xe2,0xd2,0x4c,0x87,0x59, + 0xc9,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xa6,0x30,0x81,0xa3,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04, + 0x16,0x04,0x14,0x57,0x17,0xed,0xa2,0xcf,0xdc,0x7c,0x98,0xa1,0x10,0xe0,0xfc,0xbe,0x87,0x2d,0x2c,0xf2, + 0xe3,0x17,0x54,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x2b,0xd0,0x69,0x47,0x94,0x76,0x09, + 0xfe,0xf4,0x6b,0x8d,0x2e,0x40,0xa6,0xf7,0x47,0x4d,0x7f,0x08,0x5e,0x30,0x2e,0x06,0x03,0x55,0x1d,0x1f, + 0x04,0x27,0x30,0x25,0x30,0x23,0xa0,0x21,0xa0,0x1f,0x86,0x1d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x6c,0x2e,0x61,0x70,0x70,0x6c,0x65,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x6f,0x6f,0x74,0x2e,0x63,0x72, + 0x6c,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x10,0x06, + 0x0a,0x2a,0x86,0x48,0x86,0xf7,0x63,0x64,0x06,0x02,0x06,0x04,0x02,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x42,0x39,0x74,0x6b,0xa1, + 0xdc,0xc6,0xa4,0x8f,0x37,0x2a,0x8c,0xb3,0x1d,0x0a,0x44,0xbc,0x95,0x2c,0x7f,0xbc,0x59,0xb8,0xac,0x61, + 0xfb,0x07,0x90,0x92,0x32,0xb9,0xd4,0xbf,0x3b,0xc1,0x50,0x39,0x6a,0x44,0x74,0xa2,0xec,0x5b,0x1f,0x70, + 0xe5,0xaa,0xdd,0x4b,0x6c,0x1c,0x23,0x71,0x2d,0x5f,0xd1,0xc5,0x93,0xbe,0xee,0x9b,0x8a,0x70,0x65,0x82, + 0x9d,0x16,0xe3,0x1a,0x10,0x17,0x89,0x2d,0xa8,0xcd,0xfd,0x0c,0x78,0x58,0x49,0x0c,0x28,0x7f,0x33,0xee, + 0x00,0x7a,0x1b,0xb4,0x76,0xac,0xb6,0xb5,0xbb,0x4f,0xdf,0xa8,0x1b,0x9d,0xc8,0x19,0x97,0x4a,0x0b,0x56, + 0x67,0x2f,0xc2,0x3e,0xb6,0xb3,0xc4,0x83,0x3a,0xf0,0x77,0x6d,0x74,0xc4,0x2e,0x23,0x51,0xee,0x9a,0xa5, + 0x03,0x6f,0x60,0xf4,0xa5,0x48,0xa7,0x06,0xc2,0xbb,0x5a,0xe2,0x1f,0x1f,0x46,0x45,0x7e,0xe4,0x97,0xf5, + 0x27,0x10,0xb7,0x20,0x22,0x72,0x6f,0x72,0xda,0xc6,0x50,0x75,0xc5,0x3d,0x25,0x8f,0x5d,0xa3,0x00,0xe9, + 0x9f,0x36,0x8c,0x48,0x39,0x8f,0xb3,0x3b,0xea,0x90,0x80,0x2e,0x95,0x9a,0x60,0xf4,0x78,0xce,0xf4,0x0e, + 0x0a,0x53,0x3e,0xa2,0xfa,0x4f,0xd8,0x1e,0xae,0x84,0x95,0x8d,0x32,0xbc,0x56,0x4d,0x89,0xe9,0x78,0x18, + 0xe0,0xac,0x9a,0x42,0xba,0x7a,0x46,0x1b,0x84,0xa2,0x89,0xce,0x14,0xe8,0x88,0xd1,0x58,0x8b,0xf6,0xae, + 0x56,0xc4,0x2c,0x05,0x2a,0x45,0xaf,0x0b,0xd9,0x4b,0xa9,0x02,0x0f,0x34,0xac,0x88,0xc7,0x61,0x55,0x89, + 0x44,0xc9,0x27,0x73,0x07,0xee,0x82,0xe5,0x4e,0xf5,0x70 +}; + +/* subject:/UID=398C878YJ2/ */ +/* issuer :/CN=Developer ID Certification Authority/OU=Apple Certification Authority/O=Apple Inc./C=US */ +uint8_t _leaf_cert[]={ + 0x30,0x82,0x05,0x7A,0x30,0x82,0x04,0x62,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x03, + 0xB5,0x01,0x60,0xCB,0x4D,0x00,0xDE,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x79,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x24,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x20,0x49,0x44,0x20, + 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75, + 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x1E,0x17,0x0D,0x31,0x37,0x30,0x31,0x31,0x36,0x31,0x30,0x31,0x30,0x30, + 0x30,0x5A,0x17,0x0D,0x32,0x32,0x30,0x31,0x31,0x37,0x31,0x30,0x31,0x30,0x30,0x30, + 0x5A,0x30,0x81,0x9B,0x31,0x1A,0x30,0x18,0x06,0x0A,0x09,0x92,0x26,0x89,0x93,0xF2, + 0x2C,0x64,0x01,0x01,0x0C,0x0A,0x33,0x39,0x38,0x43,0x38,0x37,0x38,0x59,0x4A,0x32, + 0x31,0x40,0x30,0x3E,0x06,0x03,0x55,0x04,0x03,0x0C,0x37,0x44,0x65,0x76,0x65,0x6C, + 0x6F,0x70,0x65,0x72,0x20,0x49,0x44,0x20,0x41,0x70,0x70,0x6C,0x69,0x63,0x61,0x74, + 0x69,0x6F,0x6E,0x3A,0x20,0x52,0x75,0x73,0x6C,0x61,0x6E,0x20,0x47,0x61,0x72,0x69, + 0x66,0x75,0x6C,0x69,0x6E,0x20,0x28,0x33,0x39,0x38,0x43,0x38,0x37,0x38,0x59,0x4A, + 0x32,0x29,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0A,0x33,0x39,0x38, + 0x43,0x38,0x37,0x38,0x59,0x4A,0x32,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x10,0x52,0x75,0x73,0x6C,0x61,0x6E,0x20,0x47,0x61,0x72,0x69,0x66,0x75,0x6C, + 0x69,0x6E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, + 0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00, + 0xC3,0xDB,0x84,0xA2,0xF1,0x89,0xA3,0x17,0xC6,0xF0,0x96,0xAA,0xE3,0xCF,0x16,0x71, + 0x7F,0x97,0x96,0xEF,0x95,0x27,0x73,0x49,0xCC,0x53,0xF0,0x1D,0x73,0x67,0xA7,0x58, + 0xC5,0x27,0xA9,0xEC,0x40,0x41,0xF6,0x6F,0x87,0x65,0x9D,0xD9,0xE1,0x16,0xF5,0xB5, + 0xBA,0xAF,0x39,0xC8,0xA0,0xA5,0x10,0x9D,0x6F,0x9A,0xD7,0xED,0x1F,0xB4,0xF6,0x90, + 0x55,0x73,0x60,0x0B,0xD4,0xEE,0xC6,0x39,0x33,0x02,0xAE,0xD9,0xEE,0x7F,0xFE,0x49, + 0x82,0x05,0x7D,0x0D,0x6E,0xA6,0x2C,0xF6,0x75,0xBD,0xBA,0xB4,0x5F,0x5E,0x9B,0x4F, + 0x85,0x3A,0x02,0x37,0xA8,0xB5,0xE1,0x42,0x57,0x97,0xA3,0x20,0xC3,0xFF,0xF5,0xC7, + 0x2F,0x0A,0xC2,0x06,0xA4,0x4E,0x24,0x7E,0xE2,0x72,0x20,0xC7,0x0E,0xC4,0x32,0xE8, + 0x0C,0x69,0xD7,0x99,0xF5,0xC5,0xDB,0xB7,0x4F,0x84,0xFB,0xAB,0x97,0x90,0x0A,0x6A, + 0x17,0xAD,0xD9,0x41,0xDD,0xE1,0x35,0x06,0x50,0x5B,0x79,0x6E,0x3A,0xC3,0x2C,0x92, + 0xE1,0x14,0x6F,0xAE,0xEC,0xC2,0xA6,0x5A,0x7F,0xB8,0x9D,0xE8,0x3A,0x6B,0x59,0x36, + 0xC3,0x56,0xA7,0x16,0x77,0xF3,0x91,0x61,0x33,0x05,0x23,0x04,0x96,0xAF,0x14,0x5F, + 0x2F,0x82,0x87,0xCE,0xDC,0x39,0x4E,0xD5,0xC5,0x1A,0x29,0xF9,0xE6,0xB8,0xAB,0xB8, + 0x62,0x39,0x2E,0x55,0x8E,0xA1,0x70,0xF9,0xE9,0x6D,0xA9,0x96,0xB9,0x59,0x22,0x1C, + 0x6E,0x8E,0x7D,0x30,0xB7,0xEA,0x1C,0xB2,0x1F,0x8D,0x59,0xF1,0x94,0x40,0x95,0xEA, + 0x4F,0xFE,0x53,0x50,0xA1,0xE0,0xC4,0x79,0x91,0x40,0x49,0x23,0x8D,0x96,0x4F,0x6D, + 0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0xE1,0x30,0x82,0x01,0xDD,0x30,0x3E,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x32,0x30,0x30,0x30,0x2E,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x22,0x68,0x74,0x74,0x70,0x3A, + 0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x2F,0x6F,0x63,0x73,0x70,0x2D,0x64,0x65,0x76,0x69,0x64,0x30,0x31,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x79,0x35,0xB6,0x17,0xF0,0x11,0x85,0x00, + 0xFE,0xBA,0x56,0xF3,0x0C,0xA0,0x03,0xBE,0x71,0x64,0x0C,0x9C,0x30,0x0C,0x06,0x03, + 0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D, + 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x57,0x17,0xED,0xA2,0xCF,0xDC,0x7C,0x98,0xA1, + 0x10,0xE0,0xFC,0xBE,0x87,0x2D,0x2C,0xF2,0xE3,0x17,0x54,0x30,0x82,0x01,0x0E,0x06, + 0x03,0x55,0x1D,0x20,0x04,0x82,0x01,0x05,0x30,0x82,0x01,0x01,0x30,0x81,0xFE,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF0,0x30,0x28,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70,0x3A, + 0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, + 0x61,0x70,0x70,0x6C,0x65,0x63,0x61,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x02,0x02,0x30,0x81,0xB6,0x0C,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E, + 0x63,0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61, + 0x72,0x74,0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65, + 0x70,0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68, + 0x65,0x6E,0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74, + 0x61,0x6E,0x64,0x61,0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64, + 0x20,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75, + 0x73,0x65,0x2C,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20, + 0x70,0x6F,0x6C,0x69,0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63, + 0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x16,0x06, + 0x03,0x55,0x1D,0x25,0x01,0x01,0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x03,0x03,0x30,0x13,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64, + 0x06,0x01,0x0D,0x01,0x01,0xFF,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x3F,0x66, + 0xE8,0xD2,0x30,0x23,0x41,0x7A,0xD9,0x4E,0x3E,0xCF,0xFE,0x89,0x30,0xB2,0x7C,0x32, + 0x84,0xE1,0xAE,0x95,0x8C,0xBE,0xA7,0x7A,0x42,0x67,0x4B,0x27,0x13,0x0A,0xA7,0x31, + 0xE7,0xEF,0x8F,0x6C,0xBD,0x26,0x09,0x75,0xC6,0xF1,0xD6,0x6D,0xCC,0x55,0x43,0x1E, + 0x80,0xC0,0x7B,0x31,0x42,0x72,0x80,0xA3,0x94,0xC2,0xB8,0x68,0xC6,0x5E,0xD6,0x10, + 0xFB,0x8C,0x52,0xE8,0xAD,0x0A,0xCE,0x11,0x20,0x5D,0xF4,0xFC,0xFA,0xE5,0x3F,0x96, + 0x02,0xDF,0xA7,0x22,0x11,0xF6,0xE6,0xF2,0xCE,0x5F,0x42,0xCF,0x13,0xED,0xCB,0xEE, + 0xEC,0xB0,0x01,0x76,0x4F,0xDC,0xD6,0x84,0x37,0x82,0x18,0x43,0x9F,0x17,0x61,0x88, + 0xBD,0x4B,0xEE,0xB8,0x2B,0xF8,0x37,0xC2,0x64,0x79,0xF5,0x63,0xBC,0x3A,0x41,0x80, + 0x2B,0x92,0x91,0x3D,0x4E,0x86,0x48,0xFE,0x66,0x4D,0xC0,0xCA,0xFB,0x77,0x68,0x3D, + 0x18,0xFA,0x5C,0xD2,0x4F,0xBC,0x23,0xC5,0xF2,0x8C,0xA6,0xAA,0x55,0x0B,0xDE,0xF7, + 0xD5,0x6E,0x88,0xBC,0x22,0x8E,0x45,0x8A,0x14,0x73,0xCF,0x69,0xAC,0xDE,0x2E,0xB8, + 0x24,0xEB,0x5C,0xC3,0x4C,0xC4,0xF0,0xCE,0xFC,0x94,0x9F,0x22,0x73,0x57,0x30,0x33, + 0x7A,0xB3,0x6C,0x43,0x1A,0x6C,0x79,0xFA,0x8E,0x14,0xF4,0x68,0x12,0x6F,0xCC,0xE8, + 0x2B,0x77,0xA5,0x6A,0xFE,0x9A,0xD4,0x3A,0x57,0x66,0x49,0x37,0x97,0xC8,0x38,0x91, + 0x14,0x4B,0x46,0x50,0xCF,0xF1,0x61,0x46,0x8C,0x9C,0xEB,0x99,0xD3,0x85,0x1B,0x53, + 0xED,0x60,0x88,0x79,0xEB,0xEA,0x2B,0xE3,0x33,0xEF,0x0D,0x58,0xEF,0xF5, +}; + +/* subject:/CN=Developer ID Certification Authority/OU=Apple Certification Authority/O=Apple Inc./C=US */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA */ +uint8_t _issuer[] ={ + 0x30,0x82,0x04,0x04,0x30,0x82,0x02,0xEC,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x18, + 0x7A,0xA9,0xA8,0xC2,0x96,0x21,0x0C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x32, + 0x30,0x32,0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5A,0x17,0x0D,0x32,0x37,0x30, + 0x32,0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5A,0x30,0x79,0x31,0x2D,0x30,0x2B, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x24,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72, + 0x20,0x49,0x44,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x26,0x30,0x24,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74, + 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72, + 0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, + 0x0A,0x02,0x82,0x01,0x01,0x00,0x89,0x76,0x4F,0x06,0x5B,0x9A,0x41,0xEE,0xA5,0x23, + 0x2B,0x02,0xA3,0x5F,0xD7,0x73,0x3F,0xC0,0x35,0xB0,0x8B,0x84,0x0A,0x3F,0x06,0x24, + 0x7F,0xA7,0x95,0x3F,0xEB,0x4F,0x0E,0x93,0xAF,0xB4,0x0E,0xD0,0xC8,0x3E,0xE5,0x6D, + 0x18,0xB3,0x1F,0xE8,0x89,0x47,0xBF,0xD7,0x09,0x08,0xE4,0xFF,0x56,0x98,0x29,0x15, + 0xE7,0x94,0x9D,0xB9,0x35,0xA3,0x0A,0xCD,0xB4,0xC0,0xE1,0xE2,0x60,0xF4,0xCA,0xEC, + 0x29,0x78,0x45,0x69,0x69,0x60,0x6B,0x5F,0x8A,0x92,0xFC,0x9E,0x23,0xE6,0x3A,0xC2, + 0x22,0xB3,0x31,0x4F,0x1C,0xBA,0xF2,0xB6,0x34,0x59,0x42,0xEE,0xB0,0xA9,0x02,0x03, + 0x18,0x91,0x04,0xB6,0xB3,0x78,0x2E,0x33,0x1F,0x80,0x45,0x0D,0x45,0x6F,0xBB,0x0E, + 0x5A,0x5B,0x7F,0x3A,0xE7,0xD8,0x08,0xD7,0x0B,0x0E,0x32,0x6D,0xFB,0x86,0x36,0xE4, + 0x6C,0xAB,0xC4,0x11,0x8A,0x70,0x84,0x26,0xAA,0x9F,0x44,0xD1,0xF1,0xB8,0xC6,0x7B, + 0x94,0x17,0x9B,0x48,0xF7,0x0B,0x58,0x16,0xBA,0x23,0xC5,0x9F,0x15,0x39,0x7E,0xCA, + 0x5D,0xC3,0x32,0x5F,0x0F,0xE0,0x52,0x7F,0x40,0xEA,0xBE,0xAC,0x08,0x64,0x95,0x5B, + 0xC9,0x1A,0x9C,0xE5,0x80,0xCA,0x1F,0x6A,0x44,0x1C,0x6C,0x3E,0xC4,0xB0,0x26,0x1F, + 0x1D,0xEC,0x7B,0xAF,0x5E,0xA0,0x6A,0x3D,0x47,0xA9,0x58,0x12,0x31,0x3F,0x20,0x76, + 0x28,0x6D,0x1D,0x1C,0xB0,0xC2,0x4E,0x11,0x69,0x26,0x8B,0xCB,0xD6,0xD0,0x11,0x82, + 0xC9,0x4E,0x0F,0xF1,0x56,0x74,0xD0,0xD9,0x08,0x4B,0x66,0x78,0xA2,0xAB,0xAC,0xA7, + 0xE2,0xD2,0x4C,0x87,0x59,0xC9,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xA6,0x30,0x81, + 0xA3,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x57,0x17,0xED,0xA2, + 0xCF,0xDC,0x7C,0x98,0xA1,0x10,0xE0,0xFC,0xBE,0x87,0x2D,0x2C,0xF2,0xE3,0x17,0x54, + 0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01, + 0xFF,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x2B,0xD0, + 0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6,0xF7,0x47,0x4D,0x7F, + 0x08,0x5E,0x30,0x2E,0x06,0x03,0x55,0x1D,0x1F,0x04,0x27,0x30,0x25,0x30,0x23,0xA0, + 0x21,0xA0,0x1F,0x86,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x72,0x6F,0x6F,0x74,0x2E,0x63, + 0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02, + 0x01,0x86,0x30,0x10,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x02,0x06, + 0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x42,0x39,0x74,0x6B,0xA1,0xDC,0xC6,0xA4, + 0x8F,0x37,0x2A,0x8C,0xB3,0x1D,0x0A,0x44,0xBC,0x95,0x2C,0x7F,0xBC,0x59,0xB8,0xAC, + 0x61,0xFB,0x07,0x90,0x92,0x32,0xB9,0xD4,0xBF,0x3B,0xC1,0x50,0x39,0x6A,0x44,0x74, + 0xA2,0xEC,0x5B,0x1F,0x70,0xE5,0xAA,0xDD,0x4B,0x6C,0x1C,0x23,0x71,0x2D,0x5F,0xD1, + 0xC5,0x93,0xBE,0xEE,0x9B,0x8A,0x70,0x65,0x82,0x9D,0x16,0xE3,0x1A,0x10,0x17,0x89, + 0x2D,0xA8,0xCD,0xFD,0x0C,0x78,0x58,0x49,0x0C,0x28,0x7F,0x33,0xEE,0x00,0x7A,0x1B, + 0xB4,0x76,0xAC,0xB6,0xB5,0xBB,0x4F,0xDF,0xA8,0x1B,0x9D,0xC8,0x19,0x97,0x4A,0x0B, + 0x56,0x67,0x2F,0xC2,0x3E,0xB6,0xB3,0xC4,0x83,0x3A,0xF0,0x77,0x6D,0x74,0xC4,0x2E, + 0x23,0x51,0xEE,0x9A,0xA5,0x03,0x6F,0x60,0xF4,0xA5,0x48,0xA7,0x06,0xC2,0xBB,0x5A, + 0xE2,0x1F,0x1F,0x46,0x45,0x7E,0xE4,0x97,0xF5,0x27,0x10,0xB7,0x20,0x22,0x72,0x6F, + 0x72,0xDA,0xC6,0x50,0x75,0xC5,0x3D,0x25,0x8F,0x5D,0xA3,0x00,0xE9,0x9F,0x36,0x8C, + 0x48,0x39,0x8F,0xB3,0x3B,0xEA,0x90,0x80,0x2E,0x95,0x9A,0x60,0xF4,0x78,0xCE,0xF4, + 0x0E,0x0A,0x53,0x3E,0xA2,0xFA,0x4F,0xD8,0x1E,0xAE,0x84,0x95,0x8D,0x32,0xBC,0x56, + 0x4D,0x89,0xE9,0x78,0x18,0xE0,0xAC,0x9A,0x42,0xBA,0x7A,0x46,0x1B,0x84,0xA2,0x89, + 0xCE,0x14,0xE8,0x88,0xD1,0x58,0x8B,0xF6,0xAE,0x56,0xC4,0x2C,0x05,0x2A,0x45,0xAF, + 0x0B,0xD9,0x4B,0xA9,0x02,0x0F,0x34,0xAC,0x88,0xC7,0x61,0x55,0x89,0x44,0xC9,0x27, + 0x73,0x07,0xEE,0x82,0xE5,0x4E,0xF5,0x70, +}; + +NSString * _oldDBSchema = +@"PRAGMA foreign_keys=OFF;" +"BEGIN TRANSACTION;" +"CREATE TABLE ocsp(issuerNameHash BLOB NOT NULL,issuerPubKeyHash BLOB NOT NULL,serialNum BLOB NOT NULL,hashAlgorithm BLOB NOT NULL,responseId INTEGER NOT NULL);" +"CREATE TABLE responses(responseId INTEGER PRIMARY KEY,ocspResponse BLOB NOT NULL,responderURI BLOB,expires DOUBLE NOT NULL,lastUsed DOUBLE NOT NULL);" +"CREATE INDEX iResponseId ON ocsp(responseId);" +"CREATE INDEX iserialNum ON ocsp(serialNum);" +"CREATE INDEX iSNumDAlg ON ocsp(serialNum,hashAlgorithm);" +"CREATE INDEX iexpires ON responses(expires);" +"CREATE TRIGGER tocspdel BEFORE DELETE ON responses FOR EACH ROW BEGIN DELETE FROM ocsp WHERE responseId=OLD.responseId; END;" +"COMMIT;"; + +NSString * _oldDBSchemaWithContent = +@"PRAGMA foreign_keys=OFF;" +"BEGIN TRANSACTION;" +"CREATE TABLE ocsp(issuerNameHash BLOB NOT NULL,issuerPubKeyHash BLOB NOT NULL,serialNum BLOB NOT NULL,hashAlgorithm BLOB NOT NULL,responseId INTEGER NOT NULL);" +"INSERT INTO ocsp VALUES(X'3381d1efdb68b085214d2eefaf8c4a69643c2a6c',X'5717eda2cfdc7c98a110e0fcbe872d2cf2e31754',X'03b50160cb4d00de',X'2b0e03021a',1);" +"CREATE TABLE responses(responseId INTEGER PRIMARY KEY,ocspResponse BLOB NOT NULL,responderURI BLOB,expires DOUBLE NOT NULL,lastUsed DOUBLE NOT NULL);" +"INSERT INTO responses VALUES(1,X'308209cb0a0100a08209c4308209c006092b0601050507300101048209b1308209ad3081b2a2160414d5024568a03d2c63402262b79c0e856974b430e8180f32303139313131363031313232315a3081863081833041300906052b0e03021a050004143381d1efdb68b085214d2eefaf8c4a69643c2a6c04145717eda2cfdc7c98a110e0fcbe872d2cf2e31754020803b50160cb4d00dea116180f32303137303631363034353430305aa0030a0104180f32303139313131363031313232315aa011180f32303139313131363133313232315aa1023000300d06092a864886f70d01010b05000382010100834f4706e90022f68cedea79c3a3b5cd9dbf49ecea78ffdacda8d0ddeb0c4d6d686a98b4af6c351bcb7ef299248887ce2b6eba97fe01c9145eac699bb8996c4be19e6be33fd7f5c79b49376aa86324122dd0f82fb359e877b02b83047f773872131aa1fc532850c1219cbaf0d0eeb213d972ee89d678dd420b62f56c8add11f6556935f99b4c363937f7e54a919a8e84592abb20d31dce955c77d5155a1f86eca9afaa34daa7b77dc161b245d9c279556ce1bafd474427c374fd1eeb90b6e6490f28a8888ccb4a87aa05f79b05e0d2cab772204697b537d8204d3e564593f1e68389d63c537ceacbb13e99058ea31a988895e704ccb38f570b4a672fc29352e2a08207e0308207dc308203d0308202b8a00302010202086f0d6c67664904c5300d06092a864886f70d01010b05003079312d302b06035504030c24446576656c6f7065722049442043657274696669636174696f6e20417574686f7269747931263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b3009060355040613025553301e170d3139313031383035323931365a170d3139313132393035323931365a304d3129302706035504030c20446576656c6f706572204944204f43535020526573706f6e646572204e4c303731133011060355040a0c0a4170706c6520496e632e310b300906035504061302555330820122300d06092a864886f70d01010105000382010f003082010a0282010100a0b8aee45be6dd9e87d6274bbc8ecf793449a5eaf0724ddce75e07c20ad0d1ab36e137919c60c0d1ff4a8413ecf1111b3fb99483e52222df3179f83f41c6fe76b068e16db82fb06264eff49bccd1ea8fd4df2e8fc18eff0267dbc6d812428734376dbddc7cb7fed53e7e0a7e829d078728f79bbd0f279cbffb39d9d53cf663aec8e8192728ab94c51553ad6177b25d851b21804aae48db7dd074d4de84a450d469043fee178b69219fe40b8043b6928d8783dda712633447eafb6b7b47fb28175c4b018f565f35c100ef9257814b2e6261e8145a6b44f7437e8861d2f7d04f392fdca22128d34322f17aed360c4ef5fb641095b92b91b9ec20da925df9f5611d0203010001a38187308184300c0603551d130101ff04023000301f0603551d230418301680145717eda2cfdc7c98a110e0fcbe872d2cf2e31754300f06092b06010505073001050402050030130603551d25040c300a06082b06010505070309301d0603551d0e04160414d5024568a03d2c63402262b79c0e856974b430e8300e0603551d0f0101ff040403020780300d06092a864886f70d01010b05000382010100650c41f8e116b7d761e16aaf122e70ef0a40a4d0e29170bddbda65628b404523c9e8a4d033f7d1a5804a3ac8762d20fe274b30dfa400353d1c807cc5098947d4787d14dfa1ef16adb1caf4f609abc4dc4d7269879b5b82bba7685efd8029682dd5a078045777d06957fa83b9f0424271aefeff0bbdd3fb3c170171e25e81be72e075ba410df010710236f3264a015ca821e0b286271b5ec1b0b04fdc7789e55c159a7239af57e1942ca34644ce0de9f1e6fad96f1e01281a0e68f46cf3bd4af83adf9372054f884b7e13b692e328d0143c13286d112736bc7327abfc3fb100ab9b357a87710e54036802b2fc8c17f3737eea756419569cacb8e6507c4894ec0e30820404308202eca0030201020208187aa9a8c296210c300d06092a864886f70d01010b05003062310b300906035504061302555331133011060355040a130a4170706c6520496e632e31263024060355040b131d4170706c652043657274696669636174696f6e20417574686f72697479311630140603550403130d4170706c6520526f6f74204341301e170d3132303230313232313231355a170d3237303230313232313231355a3079312d302b06035504030c24446576656c6f7065722049442043657274696669636174696f6e20417574686f7269747931263024060355040b0c1d4170706c652043657274696669636174696f6e20417574686f7269747931133011060355040a0c0a4170706c6520496e632e310b300906035504061302555330820122300d06092a864886f70d01010105000382010f003082010a028201010089764f065b9a41eea5232b02a35fd7733fc035b08b840a3f06247fa7953feb4f0e93afb40ed0c83ee56d18b31fe88947bfd70908e4ff56982915e7949db935a30acdb4c0e1e260f4caec2978456969606b5f8a92fc9e23e63ac222b3314f1cbaf2b6345942eeb0a90203189104b6b3782e331f80450d456fbb0e5a5b7f3ae7d808d70b0e326dfb8636e46cabc4118a708426aa9f44d1f1b8c67b94179b48f70b5816ba23c59f15397eca5dc3325f0fe0527f40eabeac0864955bc91a9ce580ca1f6a441c6c3ec4b0261f1dec7baf5ea06a3d47a95812313f2076286d1d1cb0c24e1169268bcbd6d01182c94e0ff15674d0d9084b6678a2abaca7e2d24c8759c90203010001a381a63081a3301d0603551d0e041604145717eda2cfdc7c98a110e0fcbe872d2cf2e31754300f0603551d130101ff040530030101ff301f0603551d230418301680142bd06947947609fef46b8d2e40a6f7474d7f085e302e0603551d1f042730253023a021a01f861d687474703a2f2f63726c2e6170706c652e636f6d2f726f6f742e63726c300e0603551d0f0101ff0404030201863010060a2a864886f7636406020604020500300d06092a864886f70d01010b050003820101004239746ba1dcc6a48f372a8cb31d0a44bc952c7fbc59b8ac61fb07909232b9d4bf3bc150396a4474a2ec5b1f70e5aadd4b6c1c23712d5fd1c593beee9b8a7065829d16e31a1017892da8cdfd0c7858490c287f33ee007a1bb476acb6b5bb4fdfa81b9dc819974a0b56672fc23eb6b3c4833af0776d74c42e2351ee9aa5036f60f4a548a706c2bb5ae21f1f46457ee497f52710b72022726f72dac65075c53d258f5da300e99f368c48398fb33bea90802e959a60f478cef40e0a533ea2fa4fd81eae84958d32bc564d89e97818e0ac9a42ba7a461b84a289ce14e888d1588bf6ae56c42c052a45af0bd94ba9020f34ac88c761558944c9277307ee82e54ef570',NULL,595602740.99999999108,595601999.99999996478);" +"CREATE INDEX iResponseId ON ocsp(responseId);" +"CREATE INDEX iserialNum ON ocsp(serialNum);" +"CREATE INDEX iSNumDAlg ON ocsp(serialNum,hashAlgorithm);" +"CREATE INDEX iexpires ON responses(expires);" +"CREATE TRIGGER tocspdel BEFORE DELETE ON responses FOR EACH ROW BEGIN DELETE FROM ocsp WHERE responseId=OLD.responseId; END;" +"COMMIT;"; + + +#endif /* _TRUSTTESTS_DAEMON_OCSP_CACHE_TESTS_H_ */ diff --git a/tests/TrustTests/DaemonTests/PersonalizationTests.m b/tests/TrustTests/DaemonTests/PersonalizationTests.m new file mode 100644 index 00000000..b73d06d4 --- /dev/null +++ b/tests/TrustTests/DaemonTests/PersonalizationTests.m @@ -0,0 +1,19 @@ +// +// PersonalizationTests.m +// Security +// +// + +#import +#import +#import "trust/trustd/personalization.h" + +#import "TrustDaemonTestCase.h" + +@interface PersonalizationTests: TrustDaemonTestCase +@end + +@implementation PersonalizationTests + + +@end diff --git a/tests/TrustTests/DaemonTests/PinningDbTests.m b/tests/TrustTests/DaemonTests/PinningDbTests.m new file mode 100644 index 00000000..ed3df8d4 --- /dev/null +++ b/tests/TrustTests/DaemonTests/PinningDbTests.m @@ -0,0 +1,79 @@ +// +// PinningDbTests.m +// + +#import +#import +#import +#import "trust/trustd/SecPinningDb.h" + +#import "TrustDaemonTestCase.h" + +@interface PinningDbInitializationTests : TrustDaemonInitializationTestCase +@end + +@implementation PinningDbInitializationTests + +#if !TARGET_OS_BRIDGE +- (void)testSchemaUpgrade +{ + /* Create a "pinningDB" with a large content version number but older schema version */ + char *schema_v2 = "PRAGMA foreign_keys=OFF; " + "PRAGMA user_version=2; " + "BEGIN TRANSACTION; " + "CREATE TABLE admin(key TEXT PRIMARY KEY NOT NULL,ival INTEGER NOT NULL,value BLOB); " + "INSERT INTO admin VALUES('version',2147483647,NULL); " // Version as INT_MAX + "CREATE TABLE rules( policyName TEXT NOT NULL," + "domainSuffix TEXT NOT NULL," + "labelRegex TEXT NOT NULL," + "policies BLOB NOT NULL," + "UNIQUE(policyName, domainSuffix, labelRegex)); " + "COMMIT;"; + NSURL *pinningDbPath = [SecPinningDb pinningDbPath]; + sqlite3 *handle = nil; + int sqlite_result = sqlite3_open_v2([pinningDbPath fileSystemRepresentation], &handle, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); + XCTAssertEqual(sqlite_result, SQLITE_OK); + XCTAssert(SQLITE_OK == sqlite3_exec(handle, schema_v2, NULL, NULL, NULL)); + XCTAssert(SQLITE_OK == sqlite3_close(handle)); + + /* Initialize the Pinning DB -- schema should get upgraded and populated with system content version */ + SecPinningDb *pinningDb = [[SecPinningDb alloc] init]; + XCTAssert(SecDbPerformRead([pinningDb db], NULL, ^(SecDbConnectionRef dbconn) { + NSNumber *contentVersion = [pinningDb getContentVersion:dbconn error:NULL]; + NSNumber *schemaVersion = [pinningDb getSchemaVersion:dbconn error:NULL]; + XCTAssert([contentVersion intValue] < INT_MAX && [contentVersion intValue] > 0); + XCTAssertEqualObjects(schemaVersion, @(PinningDbSchemaVersion)); + })); +} + +- (void)testContentUpgradeFromFile +{ + /* initialize a DB with the system content version */ + SecPinningDb *pinningDb = [[SecPinningDb alloc] init]; + XCTAssert(SecDbPerformRead([pinningDb db], NULL, ^(SecDbConnectionRef dbconn) { + NSNumber *contentVersion = [pinningDb getContentVersion:dbconn error:NULL]; + XCTAssert([contentVersion intValue] < INT_MAX && [contentVersion intValue] > 0); + })); + + /* update it using a test plist with INT_MAX version */ + NSURL *pinningPlist = [[NSBundle bundleForClass:[self class]] URLForResource:@"PinningDB_vINT_MAX" withExtension:nil + subdirectory:@"TestTrustdInitialization-data"]; + XCTAssert([pinningDb installDbFromURL:pinningPlist error:nil]); + XCTAssert(SecDbPerformRead([pinningDb db], NULL, ^(SecDbConnectionRef dbconn) { + NSNumber *contentVersion = [pinningDb getContentVersion:dbconn error:NULL]; + XCTAssertEqual([contentVersion intValue], INT_MAX); + })); + + /* update one more time with the same content version */ + XCTAssert([pinningDb installDbFromURL:pinningPlist error:nil]); +} +#else // !TARGET_OS_BRIDGE +/* BridgeOS doesn't have security_certificates project so there is no baseline pinning plist */ +- (void)testSkipTests +{ + XCTAssert(true); +} +#endif // !TARGET_OS_BRIDGE + +@end diff --git a/tests/TrustTests/DaemonTests/TrustDaemonTestCase.h b/tests/TrustTests/DaemonTests/TrustDaemonTestCase.h new file mode 100644 index 00000000..a0c9b0d7 --- /dev/null +++ b/tests/TrustTests/DaemonTests/TrustDaemonTestCase.h @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2019 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +* +*/ +#ifndef _TRUSTTESTS_DAEMON_TESTCASE_H_ +#define _TRUSTTESTS_DAEMON_TESTCASE_H_ + +#import + +/* Use this one to "be" the daemon, after intialization */ +@interface TrustDaemonTestCase : XCTestCase +@end + +/* Use this one to test the initialization of the daemon */ +@interface TrustDaemonInitializationTestCase : XCTestCase +@end + +#endif /* _TRUSTTESTS_DAEMON_TESTCASE_H_ */ diff --git a/tests/TrustTests/DaemonTests/TrustDaemonTestCase.m b/tests/TrustTests/DaemonTests/TrustDaemonTestCase.m new file mode 100644 index 00000000..9b3ea2c3 --- /dev/null +++ b/tests/TrustTests/DaemonTests/TrustDaemonTestCase.m @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#import +#include +#include +#include +#include "ipc/securityd_client.h" +#include "trust/trustd/trustd_spi.h" + +#import "../TrustEvaluationTestHelpers.h" +#import "TrustDaemonTestCase.h" + +@implementation TrustDaemonInitializationTestCase + +/* make a new directory for each test case */ +static int testNumber = 0; +- (void) setUp { + NSURL *tmpDirURL = setUpTmpDir(); + tmpDirURL = [tmpDirURL URLByAppendingPathComponent:[NSString stringWithFormat:@"case-%d", testNumber]]; + + NSError *error = nil; + BOOL ok = [[NSFileManager defaultManager] createDirectoryAtURL:tmpDirURL + withIntermediateDirectories:YES + attributes:NULL + error:&error]; + if (ok && tmpDirURL) { + SecSetCustomHomeURL((__bridge CFURLRef)tmpDirURL); + } + testNumber++; + gTrustd = &trustd_spi; // Signal that we're running as (uninitialized) trustd + + /* Because each test case gets a new "home" directory but we only create the data vault hierarchy once per + * launch, we need to initialize those directories for each test case. */ + WithPathInProtectedDirectory(CFSTR("trustd"), ^(const char *path) { + mode_t permissions = 0755; // Non-system trustd's create directory with expansive permissions + int ret = mkpath_np(path, permissions); + chmod(path, permissions); + if (!(ret == 0 || ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + } + }); +} +@end + +@implementation TrustDaemonTestCase + +/* Build in trustd functionality to the tests */ ++ (void) setUp { + NSURL *tmpDirURL = setUpTmpDir(); + trustd_init((__bridge CFURLRef) tmpDirURL); + + // "Disable" evaluation analytics (by making the sampling rate as low as possible) + NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.apple.security"]; + [defaults setInteger:UINT32_MAX forKey:@"TrustEvaluationEventAnalyticsRate"]; + [defaults setInteger:UINT32_MAX forKey:@"PinningEventAnalyticsRate"]; + [defaults setInteger:UINT32_MAX forKey:@"SystemRootUsageEventAnalyticsRate"]; + [defaults setInteger:UINT32_MAX forKey:@"TrustFailureEventAnalyticsRate"]; +} + +@end diff --git a/tests/TrustTests/DaemonTests/TrustServerTests.m b/tests/TrustTests/DaemonTests/TrustServerTests.m new file mode 100644 index 00000000..affe0ee7 --- /dev/null +++ b/tests/TrustTests/DaemonTests/TrustServerTests.m @@ -0,0 +1,281 @@ +/* +* Copyright (c) 2021 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +* +*/ + +#include +#import +#import +#import +#import "trust/trustd/SecCertificateServer.h" +#import "trust/trustd/SecRevocationServer.h" + +#import "TrustDaemonTestCase.h" +#import "TrustServerTests_data.h" + +@interface TrustServerTests : TrustDaemonTestCase +@end + +@implementation TrustServerTests + +- (SecCertificatePathVCRef)createPath { + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _trust_server_leaf_cert, sizeof(_trust_server_leaf_cert)); + SecCertificateRef ca = SecCertificateCreateWithBytes(NULL, _trust_server_ca_cert, sizeof(_trust_server_ca_cert)); + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _trust_server_root_cert, sizeof(_trust_server_root_cert)); + SecCertificatePathVCRef path = SecCertificatePathVCCreate(NULL, leaf, NULL); + SecCertificatePathVCRef path2 = SecCertificatePathVCCreate(path, ca, NULL); + CFRelease(path); + SecCertificatePathVCRef result = SecCertificatePathVCCreate(path2, root, NULL); + CFRelease(path2); + CFRelease(root); + CFRelease(ca); + CFRelease(leaf); + return result; +} + +- (SecPathBuilderRef)createBuilderForPath:(SecCertificatePathVCRef)path { + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _trust_server_leaf_cert, sizeof(_trust_server_leaf_cert)); + NSArray *certs = @[(__bridge id)leaf]; + CFRelease(leaf); + SecPathBuilderRef builder = SecPathBuilderCreate(NULL, NULL, (__bridge CFArrayRef)certs, NULL, false, false, NULL, NULL, NULL, NULL, 0.0, NULL, NULL, NULL, NULL); + // Set path + SecPathBuilderSetPath(builder, path); + + // Set result + SecPVCRef pvc = SecPathBuilderGetPVCAtIndex(builder, 0); + pvc->result = kSecTrustResultProceed; + + // Set the best path for reporting + SecPathBuilderDidValidatePath(builder); + + return builder; +} + +/* Mock OCSP behaviors in the validation context */ +- (void)createAndPopulateRVCs:(SecCertificatePathVCRef)path +{ + SecCertificatePathVCAllocateRVCs(path, 2); + SecOCSPResponseRef response_leaf = SecOCSPResponseCreate((__bridge CFDataRef)[NSData dataWithBytes:_trust_server_ocsp_response_leaf + length:sizeof(_trust_server_ocsp_response_leaf)]); + SecOCSPResponseRef response_ca = SecOCSPResponseCreate((__bridge CFDataRef)[NSData dataWithBytes:_trust_server_ocsp_response_ca + length:sizeof(_trust_server_ocsp_response_ca)]); + + // Set expire time on responses + (void)SecOCSPResponseCalculateValidity(response_leaf, 0.0, 0.0, 632104000.0); // January 11, 2021 at 4:26:40 PM PST + (void)SecOCSPResponseCalculateValidity(response_ca, 0.0, 0.0, 632104000.0); + for (int i = 0; i < 2; i++) { + SecRVCRef rvc = SecCertificatePathVCGetRVCAtIndex(path, i); + rvc->certIX = i; + rvc->done = false; + + SecORVCRef orvc = NULL; + orvc = malloc(sizeof(struct OpaqueSecORVC)); + memset(orvc, 0, sizeof(struct OpaqueSecORVC)); + orvc->rvc = rvc; + orvc->certIX = i; + + rvc->orvc = orvc; + + if (i == 0) { + orvc->thisUpdate = SecOCSPResponseProducedAt(response_leaf); + orvc->nextUpdate = SecOCSPResponseGetExpirationTime(response_leaf); + } else { + orvc->thisUpdate = SecOCSPResponseProducedAt(response_ca); + orvc->nextUpdate = SecOCSPResponseGetExpirationTime(response_ca); + } + } + + SecOCSPResponseFinalize(response_leaf); + SecOCSPResponseFinalize(response_ca); +} + +- (void)createAndPopulateRVCs:(SecCertificatePathVCRef)path notBefore:(CFAbsoluteTime)notBefore notAfter:(CFAbsoluteTime)notAfter +{ + NSLog(@"thisUpdate: %f, nextUpdate: %f", notBefore, notAfter); + SecCertificatePathVCAllocateRVCs(path, 2); + for (int i = 0; i < 2; i++) { + SecRVCRef rvc = SecCertificatePathVCGetRVCAtIndex(path, i); + rvc->certIX = i; + rvc->done = false; + + SecORVCRef orvc = NULL; + orvc = malloc(sizeof(struct OpaqueSecORVC)); + memset(orvc, 0, sizeof(struct OpaqueSecORVC)); + orvc->rvc = rvc; + orvc->certIX = i; + orvc->thisUpdate = notBefore; + orvc->nextUpdate = notAfter; + + rvc->orvc = orvc; + } +} + +- (void)testReportResult_NoRevocationResults { + SecCertificatePathVCRef path = [self createPath]; + SecPathBuilderRef builder = [self createBuilderForPath:path]; + XCTAssertFalse(SecPathBuilderReportResult(builder)); + NSDictionary *info = (__bridge NSDictionary*)SecPathBuilderGetInfo(builder); + XCTAssertNotNil(info); + + // For a non-EV, non-CT, no-revocation builder, only the trust result validity should be set + XCTAssertEqual(info.count, 2); + + /* NotBefore inputs: leaf cert notBefore at 626290914.0; now - leeway; no latest thisUpdate + * Maximum of these will be now - leeway */ + NSTimeInterval notBefore = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotBefore] timeIntervalSinceReferenceDate]; + XCTAssertEqualWithAccuracy(notBefore, CFAbsoluteTimeGetCurrent() - TRUST_TIME_LEEWAY, 0.5); // to within 1/2 second accuracy + + /* NotAfter inputs: leaf cert notAfter at 660418914.0; now + leeway; no earliest nextUpdate + * Minimum of these will be (now + leeway) until current time is (notAfter - leeway) where it will switch to the notAfter. + * Then after the cert expires, it will change back to (now + leeway) as we correct for an inverted validity period. */ + NSTimeInterval notAfter = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotAfter] timeIntervalSinceReferenceDate]; + if (CFAbsoluteTimeGetCurrent() < (660418914.0 - TRUST_TIME_LEEWAY)) { + // Well before leaf expiry + XCTAssertEqualWithAccuracy(notAfter, CFAbsoluteTimeGetCurrent() + TRUST_TIME_LEEWAY, 0.5); + } else if (CFAbsoluteTimeGetCurrent() < 660418914.0 + TRUST_TIME_LEEWAY) { + // Until the cert has expired, the notAfter date bounds the trust result + XCTAssertEqualWithAccuracy(notAfter, 660418914.0, 0.1); + } else { + // Once the cert expires we just use the leeway again + XCTAssertEqualWithAccuracy(notAfter, CFAbsoluteTimeGetCurrent() + TRUST_TIME_LEEWAY, 0.5); + } + + SecPathBuilderDestroy(builder); + free(builder); + CFRelease(path); +} + +- (void)testReportResult_RevocationResults_InvertedWindows_Expired { + SecCertificatePathVCRef path = [self createPath]; + [self createAndPopulateRVCs:path]; + SecPathBuilderRef builder = [self createBuilderForPath:path]; + XCTAssertFalse(SecPathBuilderReportResult(builder)); + NSDictionary *info = (__bridge NSDictionary*)SecPathBuilderGetInfo(builder); + XCTAssertNotNil(info); + + // For a non-EV, non-CT builder with revocation checked, so we should have the trust result validity and revocation keys + XCTAssertEqual(info.count, 6); + + /* NotBefore inputs: leaf cert notBefore at 626290914.0; now - 1:15; OCSP response latest thisUpdate at 632103361.0 + * Maximum of these will be now - 1:15 */ + NSTimeInterval notBefore = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotBefore] timeIntervalSinceReferenceDate]; + XCTAssertEqualWithAccuracy(notBefore, CFAbsoluteTimeGetCurrent() - TRUST_TIME_LEEWAY, 0.5); // to within 1/2 second accuracy + + /* NotAfter inputs: leaf cert notAfter at 660418914.0; now + 1:15; OCSP response earliest nextUpdate at 632142381.0 + * Minimum of these will be the earliest next update, but because the notBefore is after that, we'll adjust + * the notAfter to now + 1:15 */ + NSTimeInterval notAfter = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotAfter] timeIntervalSinceReferenceDate]; + XCTAssertEqualWithAccuracy(notAfter, CFAbsoluteTimeGetCurrent() + TRUST_TIME_LEEWAY, 0.5); + + XCTAssert([(NSNumber*)info[(__bridge NSString*)kSecTrustInfoRevocationKey] boolValue]); + XCTAssert([(NSNumber*)info[(__bridge NSString*)kSecTrustRevocationChecked] boolValue]); + + XCTAssertEqualObjects((NSDate*)info[(__bridge NSString*)kSecTrustInfoRevocationValidUntilKey], [NSDate dateWithTimeIntervalSinceReferenceDate:632142381.0]); + XCTAssertEqualObjects((NSDate*)info[(__bridge NSString*)kSecTrustRevocationValidUntilDate], [NSDate dateWithTimeIntervalSinceReferenceDate:632142381.0]); + + SecPathBuilderDestroy(builder); + free(builder); + CFRelease(path); +} + +- (void)testReportResult_RevocationResults_InvertedWindows_FutureValidity { + SecCertificatePathVCRef path = [self createPath]; + CFAbsoluteTime thisUpdate = CFAbsoluteTimeGetCurrent() + 400; + CFAbsoluteTime nextUpdate = CFAbsoluteTimeGetCurrent() + 100; + [self createAndPopulateRVCs:path + notBefore:thisUpdate + notAfter:nextUpdate]; + SecPathBuilderRef builder = [self createBuilderForPath:path]; + XCTAssertFalse(SecPathBuilderReportResult(builder)); + NSDictionary *info = (__bridge NSDictionary*)SecPathBuilderGetInfo(builder); + XCTAssertNotNil(info); + + // For a non-EV, non-CT builder with revocation checked, so we should have the trust result validity and revocation keys + XCTAssertEqual(info.count, 6); + + /* Because thisUpdate and nextUpdate are flipped and both in the future, we should keep the nextUpdate as notAfter + * and use "now" as the notBefore */ + NSTimeInterval notBefore = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotBefore] timeIntervalSinceReferenceDate]; + XCTAssertEqualWithAccuracy(notBefore, CFAbsoluteTimeGetCurrent(), 0.5); // to within 1/2 second accuracy + NSTimeInterval notAfter = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotAfter] timeIntervalSinceReferenceDate]; + XCTAssertEqualWithAccuracy(notAfter, nextUpdate, 0.1); + + SecPathBuilderDestroy(builder); + free(builder); + CFRelease(path); +} + +- (void)testReportResult_RevocationResults_InvertedWindows_Between { + SecCertificatePathVCRef path = [self createPath]; + CFAbsoluteTime thisUpdate = CFAbsoluteTimeGetCurrent() + 400; + CFAbsoluteTime nextUpdate = CFAbsoluteTimeGetCurrent() - 100; + [self createAndPopulateRVCs:path + notBefore:thisUpdate + notAfter:nextUpdate]; + SecPathBuilderRef builder = [self createBuilderForPath:path]; + XCTAssertFalse(SecPathBuilderReportResult(builder)); + NSDictionary *info = (__bridge NSDictionary*)SecPathBuilderGetInfo(builder); + XCTAssertNotNil(info); + + // For a non-EV, non-CT builder with revocation checked, so we should have the trust result validity and revocation keys + XCTAssertEqual(info.count, 6); + + /* Because thisUpdate and nextUpdate are flipped, with notBefore in the future but notAfter in the past, + * we should flip the two */ + NSTimeInterval notBefore = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotBefore] timeIntervalSinceReferenceDate]; + XCTAssertEqualWithAccuracy(notBefore, nextUpdate, 0.1); // to within 1/2 second accuracy + NSTimeInterval notAfter = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotAfter] timeIntervalSinceReferenceDate]; + XCTAssertEqualWithAccuracy(notAfter, thisUpdate, 0.1); + + SecPathBuilderDestroy(builder); + free(builder); + CFRelease(path); +} + +- (void)testReportResult_RevocationResults_Expired { + SecCertificatePathVCRef path = [self createPath]; + CFAbsoluteTime thisUpdate = CFAbsoluteTimeGetCurrent() - 400; + CFAbsoluteTime nextUpdate = CFAbsoluteTimeGetCurrent() - 100; + [self createAndPopulateRVCs:path + notBefore:thisUpdate + notAfter:nextUpdate]; + SecPathBuilderRef builder = [self createBuilderForPath:path]; + XCTAssertFalse(SecPathBuilderReportResult(builder)); + NSDictionary *info = (__bridge NSDictionary*)SecPathBuilderGetInfo(builder); + XCTAssertNotNil(info); + + // For a non-EV, non-CT builder with revocation checked, so we should have the trust result validity and revocation keys + XCTAssertEqual(info.count, 6); + + /* thisUpdate and nextUpdate are both in the recent past, so we should adjust the validity period to + * be in the present */ + NSTimeInterval notBefore = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotBefore] timeIntervalSinceReferenceDate]; + XCTAssertEqualWithAccuracy(notBefore, nextUpdate, 0.1); + NSTimeInterval notAfter = [(NSDate *)info[(__bridge NSString*)kSecTrustInfoResultNotAfter] timeIntervalSinceReferenceDate]; + XCTAssertEqualWithAccuracy(notAfter, CFAbsoluteTimeGetCurrent() + TRUST_TIME_LEEWAY, 0.5); + + SecPathBuilderDestroy(builder); + free(builder); + CFRelease(path); +} + +@end diff --git a/tests/TrustTests/DaemonTests/TrustServerTests_data.h b/tests/TrustTests/DaemonTests/TrustServerTests_data.h new file mode 100644 index 00000000..1860a980 --- /dev/null +++ b/tests/TrustTests/DaemonTests/TrustServerTests_data.h @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2021 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#ifndef _TRUSTTESTS_DAEMON_TRUST_SERVER_TESTS_H_ +#define _TRUSTTESTS_DAEMON_TRUST_SERVER_TESTS_H_ + +/* subject:/CN=Prio Statistics Facilitator: XX/O=External Entity */ +/* issuer :/CN=Test Apple Application Integration CA 6 - G1/O=Apple Inc./C=US */ +/* Not Before: Nov 5 17:41:54 2020 GMT; Not After : Dec 5 17:41:54 2021 GMT */ +const uint8_t _trust_server_leaf_cert[]={ + 0x30,0x82,0x03,0x99,0x30,0x82,0x03,0x3F,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x55, + 0x43,0x08,0x3F,0x5B,0xCF,0x39,0x69,0xB7,0x46,0x8C,0xE3,0x99,0xBF,0x2A,0x63,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x59,0x31,0x35,0x30, + 0x33,0x06,0x03,0x55,0x04,0x03,0x0C,0x2C,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x41,0x70,0x70,0x6C,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x49, + 0x6E,0x74,0x65,0x67,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x43,0x41,0x20,0x36,0x20, + 0x2D,0x20,0x47,0x31,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x35, + 0x31,0x37,0x34,0x31,0x35,0x34,0x5A,0x17,0x0D,0x32,0x31,0x31,0x32,0x30,0x35,0x31, + 0x37,0x34,0x31,0x35,0x34,0x5A,0x30,0x44,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x1F,0x50,0x72,0x69,0x6F,0x20,0x53,0x74,0x61,0x74,0x69,0x73,0x74,0x69, + 0x63,0x73,0x20,0x46,0x61,0x63,0x69,0x6C,0x69,0x74,0x61,0x74,0x6F,0x72,0x3A,0x20, + 0x58,0x58,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0F,0x45,0x78,0x74, + 0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x6E,0x74,0x69,0x74,0x79,0x30,0x59,0x30,0x13, + 0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x45,0x72,0x96,0xD1,0x93,0xED,0xF6,0xEB,0xD2, + 0xB8,0x80,0xFF,0xA3,0x05,0x1D,0x26,0xCB,0x62,0x98,0x9C,0x6C,0x03,0x98,0x16,0x3F, + 0xAE,0xE2,0x2F,0x6D,0x5F,0xD5,0x66,0x49,0xFB,0xA8,0xF7,0x61,0xF9,0xD7,0xBE,0xB5, + 0x73,0x32,0xDA,0xCD,0xFB,0xE1,0x10,0x5B,0xC2,0xDC,0xC4,0x70,0xEC,0x22,0x4A,0x29, + 0x02,0x19,0x05,0xB8,0xDD,0x8E,0x1F,0xA3,0x82,0x01,0xFC,0x30,0x82,0x01,0xF8,0x30, + 0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06, + 0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xA9,0x85,0xC1,0x1A,0x0A,0xE5, + 0xD8,0x79,0xCD,0xF0,0x7B,0x46,0xFA,0x99,0xEF,0x4B,0x61,0x47,0x73,0x84,0x30,0x50, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x44,0x30,0x42,0x30,0x40, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x34,0x68,0x74,0x74,0x70, + 0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70, + 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30, + 0x33,0x2D,0x74,0x65,0x73,0x74,0x61,0x61,0x69,0x63,0x61,0x36,0x67,0x31,0x30,0x32, + 0x30,0x82,0x01,0x1D,0x06,0x03,0x55,0x1D,0x20,0x04,0x82,0x01,0x14,0x30,0x82,0x01, + 0x10,0x30,0x82,0x01,0x0C,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x05,0x01, + 0x30,0x81,0xFE,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02, + 0x30,0x81,0xB6,0x0C,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65,0x20,0x6F, + 0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, + 0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72,0x74,0x79,0x20, + 0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74,0x61,0x6E, + 0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65,0x6E,0x20,0x61, + 0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61,0x6E,0x64,0x61, + 0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E, + 0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x2C,0x20, + 0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70,0x6F,0x6C,0x69, + 0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,0x73,0x74, + 0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x36,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x02,0x01,0x16,0x2A,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77, + 0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x65,0x72, + 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x61,0x75,0x74,0x68,0x6F,0x72,0x69,0x74, + 0x79,0x30,0x14,0x06,0x03,0x55,0x1D,0x25,0x04,0x0D,0x30,0x0B,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x63,0x64,0x04,0x12,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0x41,0xF3,0x3A,0x81,0xF6,0x13,0x85,0xD4,0xF6,0xE7,0x07,0x77,0x47,0x16, + 0xD2,0x9A,0xE5,0xFD,0x21,0xCF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF, + 0x04,0x04,0x03,0x02,0x03,0x08,0x30,0x0F,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63, + 0x64,0x0F,0x02,0x04,0x02,0x05,0x00,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x20,0x3E,0x4D,0x6A,0xFB,0xE1,0xE0, + 0x32,0x8A,0xC0,0x79,0x6C,0xB1,0x26,0xB0,0x13,0x07,0x2A,0x0C,0x50,0x2A,0x45,0x18, + 0x18,0x60,0x3F,0x7F,0xC8,0x74,0x2C,0xA1,0xBF,0xE4,0x02,0x21,0x00,0xB5,0xE3,0xE4, + 0x4E,0x14,0x20,0xFC,0x7D,0x54,0x52,0xBE,0xD2,0x7C,0x22,0x9B,0xF1,0x89,0x1D,0xB5, + 0x7F,0x71,0xDF,0x43,0xBD,0xA1,0xC1,0xC1,0xF6,0xDE,0x31,0x05,0x42, +}; + +/* subject:/CN=Test Apple Application Integration CA 6 - G1/O=Apple Inc./C=US */ +/* issuer :/CN=Test Apple Root CA - G3/OU=Apple Certification Authority/O=Apple Inc./C=US */ +/* Not Before: Jun 25 23:41:27 2020 GMT; Not After : Jun 22 23:41:27 2035 GMT */ +const uint8_t _trust_server_ca_cert[]={ + 0x30,0x82,0x02,0xEF,0x30,0x82,0x02,0x75,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x4E, + 0x44,0x86,0xF9,0xD8,0x8C,0x9E,0x99,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x03,0x30,0x6C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C,0x17, + 0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20, + 0x43,0x41,0x20,0x2D,0x20,0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x1E,0x17,0x0D,0x32,0x30,0x30,0x36,0x32,0x35,0x32,0x33,0x34,0x31,0x32, + 0x37,0x5A,0x17,0x0D,0x33,0x35,0x30,0x36,0x32,0x32,0x32,0x33,0x34,0x31,0x32,0x37, + 0x5A,0x30,0x59,0x31,0x35,0x30,0x33,0x06,0x03,0x55,0x04,0x03,0x0C,0x2C,0x54,0x65, + 0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x70,0x70,0x6C,0x69,0x63,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x49,0x6E,0x74,0x65,0x67,0x72,0x61,0x74,0x69,0x6F,0x6E, + 0x20,0x43,0x41,0x20,0x36,0x20,0x2D,0x20,0x47,0x31,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x59,0x30,0x13, + 0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x13,0xCF,0x5B,0x49,0xCA,0x59,0x56,0x92,0x3D, + 0x5C,0x46,0xD5,0x7A,0x95,0xE4,0xA0,0xB0,0x84,0x1E,0x68,0x3E,0x2C,0x13,0xB1,0xDC, + 0x4E,0x26,0xAC,0x72,0x6A,0x11,0x93,0x77,0xE3,0xA0,0xE3,0x6F,0x48,0x0B,0x96,0xF5, + 0xFE,0xD5,0xBD,0xA5,0xBC,0x4F,0x74,0x03,0xF1,0x09,0xF3,0xBF,0xC3,0x0D,0xB8,0x9B, + 0x62,0x2B,0xC0,0xD3,0x4A,0x06,0x95,0xA3,0x82,0x01,0x12,0x30,0x82,0x01,0x0E,0x30, + 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xFC,0x46,0xD8, + 0x83,0x6C,0x1F,0xE6,0xF2,0xDC,0xDF,0xA7,0x99,0x17,0xAE,0x0B,0x44,0x67,0x17,0x1B, + 0x46,0x30,0x53,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x47,0x30, + 0x45,0x30,0x43,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x37,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D,0x75,0x61,0x74,0x2E,0x63, + 0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63, + 0x73,0x70,0x30,0x33,0x2D,0x74,0x65,0x73,0x74,0x61,0x70,0x70,0x6C,0x65,0x72,0x6F, + 0x6F,0x74,0x63,0x61,0x67,0x33,0x30,0x44,0x06,0x03,0x55,0x1D,0x1F,0x04,0x3D,0x30, + 0x3B,0x30,0x39,0xA0,0x37,0xA0,0x35,0x86,0x33,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x63,0x72,0x6C,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70, + 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65,0x73,0x74,0x61,0x70,0x70,0x6C,0x65, + 0x72,0x6F,0x6F,0x74,0x63,0x61,0x67,0x33,0x2E,0x63,0x72,0x6C,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xA9,0x85,0xC1,0x1A,0x0A,0xE5,0xD8,0x79,0xCD, + 0xF0,0x7B,0x46,0xFA,0x99,0xEF,0x4B,0x61,0x47,0x73,0x84,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x10,0x06,0x0A,0x2A, + 0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x02,0x1A,0x04,0x02,0x05,0x00,0x30,0x0A,0x06, + 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x68,0x00,0x30,0x65,0x02,0x30, + 0x28,0xB1,0x65,0x9C,0x8F,0xFC,0x4E,0xF9,0xF3,0x18,0x21,0xF0,0x00,0xB7,0x76,0x23, + 0x57,0x78,0xB1,0x1A,0x71,0x15,0xD0,0xEF,0x7B,0x3C,0xAF,0x4F,0xC6,0x1C,0x4D,0x55, + 0x16,0x5D,0x1B,0x92,0xDE,0x97,0x4C,0x88,0xE4,0x8A,0x2D,0x86,0xD8,0x79,0x2D,0xB5, + 0x02,0x31,0x00,0xF4,0xBC,0xB0,0x78,0xE1,0x0E,0xF5,0x8A,0x4F,0xB9,0x23,0xD7,0x75, + 0x6B,0x88,0x23,0xDD,0xED,0xCA,0xD1,0xA0,0x27,0xC4,0x86,0xED,0x4B,0x8C,0x24,0x22, + 0x61,0x6C,0x56,0x42,0x5F,0xFA,0x2B,0x10,0x43,0xFA,0xA0,0xE8,0x27,0xB0,0xCB,0x5F, + 0xEA,0xCB,0xFB, +}; + +/* subject:/CN=Test Apple Root CA - G3/OU=Apple Certification Authority/O=Apple Inc./C=US */ +/* issuer :/CN=Test Apple Root CA - G3/OU=Apple Certification Authority/O=Apple Inc./C=US */ +/* Not Before: Apr 22 03:17:44 2015 GMT; Not After : Dec 26 03:13:37 2040 GMT*/ +const uint8_t _trust_server_root_cert[]={ + 0x30,0x82,0x02,0x4C,0x30,0x82,0x01,0xD3,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x78, + 0x36,0x0B,0xF4,0xB7,0xC8,0xB6,0xB0,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x03,0x30,0x6C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C,0x17, + 0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20, + 0x43,0x41,0x20,0x2D,0x20,0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x1E,0x17,0x0D,0x31,0x35,0x30,0x34,0x32,0x32,0x30,0x33,0x31,0x37,0x34, + 0x34,0x5A,0x17,0x0D,0x34,0x30,0x31,0x32,0x32,0x36,0x30,0x33,0x31,0x33,0x33,0x37, + 0x5A,0x30,0x6C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C,0x17,0x54,0x65, + 0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41, + 0x20,0x2D,0x20,0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, + 0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x05,0x2B,0x81, + 0x04,0x00,0x22,0x03,0x62,0x00,0x04,0xA9,0x1A,0x63,0x34,0xEF,0xBC,0xA6,0x8A,0xD6, + 0x2A,0x6A,0x38,0x22,0xE9,0x25,0xAD,0xDA,0x28,0xA0,0x49,0xC5,0x64,0xFE,0x5D,0x91, + 0xC3,0x6C,0xF7,0x99,0xE4,0xBA,0xE4,0x2A,0x5F,0x61,0xD2,0xBF,0x3B,0x6C,0xA8,0x61, + 0x11,0xB5,0xE0,0x66,0xF7,0x22,0x11,0x86,0x97,0x5D,0xC3,0xBA,0x1B,0x6D,0x55,0x7F, + 0xD0,0xF9,0x80,0xE0,0xFF,0xD9,0x05,0xAD,0x5A,0x5B,0xBF,0x3A,0x7A,0xA7,0x09,0x52, + 0x1A,0x31,0x7F,0x0C,0xA2,0xE8,0x10,0xF5,0x36,0xD3,0xC8,0xEA,0xA0,0x5B,0x0A,0x28, + 0x85,0x30,0x28,0x5F,0x94,0xF6,0x94,0xA3,0x42,0x30,0x40,0x30,0x1D,0x06,0x03,0x55, + 0x1D,0x0E,0x04,0x16,0x04,0x14,0xFC,0x46,0xD8,0x83,0x6C,0x1F,0xE6,0xF2,0xDC,0xDF, + 0xA7,0x99,0x17,0xAE,0x0B,0x44,0x67,0x17,0x1B,0x46,0x30,0x0F,0x06,0x03,0x55,0x1D, + 0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0A,0x06,0x08,0x2A, + 0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x67,0x00,0x30,0x64,0x02,0x30,0x1A,0x14, + 0x38,0x24,0xFF,0xB4,0x08,0xCB,0xEA,0xC9,0x3B,0xDA,0xCC,0x82,0xF3,0xD9,0x0D,0xD1, + 0x2B,0x6E,0xBF,0x1F,0xC4,0x15,0x14,0x44,0xDF,0x98,0x9B,0xD7,0xDD,0xBA,0x1B,0xBE, + 0x4F,0x9F,0x17,0xA4,0xD2,0x02,0x75,0x90,0x7D,0x76,0xCC,0x93,0x16,0x2F,0x02,0x30, + 0x02,0xD7,0xDA,0x0B,0xBE,0xDD,0x3D,0xED,0xF9,0xA3,0x06,0x90,0xA9,0x58,0xBD,0x6B, + 0x7C,0x7C,0xE5,0xC5,0x4E,0x0E,0x44,0xA2,0x94,0x2F,0xB4,0x04,0x9A,0xCD,0x9B,0x69, + 0x8D,0x2A,0xC6,0x1D,0x58,0xFF,0xE3,0x32,0xB6,0xDB,0x3E,0x34,0xFF,0x67,0x70,0xF1, +}; + +/* + Prio Statistics Facilitator_ XX.cert.pem: good + This Update: Jan 11 23:06:21 2021 GMT + Next Update: Jan 12 11:06:21 2021 GMT + */ +const uint8_t _trust_server_ocsp_response_leaf[] = { + 0x30, 0x82, 0x06, 0x68, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x06, 0x61, 0x30, 0x82, 0x06, 0x5d, 0x06, + 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x06, 0x4e, 0x30, 0x82, + 0x06, 0x4a, 0x30, 0x81, 0xc3, 0xa2, 0x16, 0x04, 0x14, 0x0f, 0x64, 0x14, 0xe3, 0x20, 0x35, 0x7c, + 0xf3, 0x68, 0x5d, 0x07, 0x6d, 0x66, 0xca, 0xe7, 0xf6, 0x01, 0x1f, 0x6c, 0x89, 0x18, 0x0f, 0x32, + 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x31, 0x32, 0x33, 0x30, 0x36, 0x32, 0x31, 0x5a, 0x30, 0x73, + 0x30, 0x71, 0x30, 0x49, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, + 0x14, 0x62, 0x9f, 0xbd, 0x59, 0x5a, 0x10, 0x15, 0xb0, 0xd6, 0x4b, 0x2e, 0xe6, 0xb5, 0x64, 0xa6, + 0x6f, 0x14, 0x83, 0x9e, 0x9e, 0x04, 0x14, 0xa9, 0x85, 0xc1, 0x1a, 0x0a, 0xe5, 0xd8, 0x79, 0xcd, + 0xf0, 0x7b, 0x46, 0xfa, 0x99, 0xef, 0x4b, 0x61, 0x47, 0x73, 0x84, 0x02, 0x10, 0x55, 0x43, 0x08, + 0x3f, 0x5b, 0xcf, 0x39, 0x69, 0xb7, 0x46, 0x8c, 0xe3, 0x99, 0xbf, 0x2a, 0x63, 0x80, 0x00, 0x18, + 0x0f, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x31, 0x32, 0x33, 0x30, 0x36, 0x32, 0x31, 0x5a, + 0xa0, 0x11, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x32, 0x31, 0x31, 0x30, 0x36, + 0x32, 0x31, 0x5a, 0xa1, 0x23, 0x30, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x30, 0x01, 0x02, 0x04, 0x12, 0x04, 0x10, 0x3c, 0xa4, 0x90, 0x70, 0x92, 0x6f, 0x7a, 0xfc, + 0x27, 0x20, 0x49, 0x67, 0x3a, 0x37, 0x5e, 0x32, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xcc, 0x5c, 0x68, 0xf1, + 0x78, 0xa4, 0xe1, 0x40, 0x12, 0x43, 0x4f, 0x7f, 0x48, 0xa8, 0x18, 0x07, 0x66, 0x2d, 0x34, 0x54, + 0x74, 0x68, 0x04, 0xe6, 0x1f, 0x6b, 0x50, 0x94, 0xed, 0xb7, 0xf1, 0xf4, 0x02, 0x20, 0x33, 0x93, + 0x03, 0x0c, 0x97, 0xdc, 0x54, 0x06, 0xb2, 0xed, 0x92, 0xbc, 0x7d, 0x6f, 0x84, 0x45, 0x7b, 0x05, + 0x67, 0x2d, 0x29, 0xd4, 0xa8, 0xfc, 0xfb, 0xf0, 0xc7, 0x3e, 0xe4, 0xb2, 0xaf, 0x4e, 0xa0, 0x82, + 0x05, 0x2a, 0x30, 0x82, 0x05, 0x26, 0x30, 0x82, 0x02, 0x2f, 0x30, 0x82, 0x01, 0xd5, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x3f, 0x6c, 0xe2, 0x71, 0xae, 0xbc, 0x4f, 0xd3, 0x53, 0x70, 0xa8, + 0xe9, 0x67, 0xff, 0xcd, 0x44, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, + 0x02, 0x30, 0x59, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2c, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x43, 0x41, 0x20, 0x36, 0x20, 0x2d, 0x20, 0x47, 0x31, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, + 0x32, 0x30, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x31, 0x38, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x32, + 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x31, 0x38, 0x31, 0x32, 0x5a, 0x30, 0x50, 0x31, 0x2c, + 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x23, 0x61, 0x61, 0x69, 0x63, 0x61, 0x36, 0x67, + 0x31, 0x20, 0x4f, 0x43, 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, + 0x20, 0x47, 0x31, 0x20, 0x32, 0x30, 0x32, 0x30, 0x31, 0x32, 0x31, 0x37, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, + 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x59, + 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x63, 0x0e, 0x59, 0xae, 0x69, 0x58, 0x2e, + 0x0f, 0x07, 0x87, 0x08, 0xf8, 0x95, 0xe5, 0x76, 0x7a, 0xc9, 0x28, 0x50, 0x12, 0x70, 0x78, 0x99, + 0x99, 0x8c, 0x05, 0x0f, 0xd3, 0x0e, 0xe7, 0xb5, 0x59, 0xb0, 0x73, 0x82, 0x7f, 0xbd, 0xc7, 0xef, + 0x3f, 0x33, 0xa1, 0x64, 0x5b, 0x96, 0x46, 0x8e, 0x81, 0xf9, 0x38, 0x9d, 0x0a, 0xeb, 0x31, 0x0f, + 0x9f, 0x5a, 0x6c, 0x1a, 0x52, 0x7f, 0xf4, 0x4c, 0x98, 0xa3, 0x81, 0x87, 0x30, 0x81, 0x84, 0x30, + 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xa9, 0x85, 0xc1, 0x1a, 0x0a, 0xe5, + 0xd8, 0x79, 0xcd, 0xf0, 0x7b, 0x46, 0xfa, 0x99, 0xef, 0x4b, 0x61, 0x47, 0x73, 0x84, 0x30, 0x0f, + 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x05, 0x04, 0x02, 0x05, 0x00, 0x30, + 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x03, 0x09, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x0f, + 0x64, 0x14, 0xe3, 0x20, 0x35, 0x7c, 0xf3, 0x68, 0x5d, 0x07, 0x6d, 0x66, 0xca, 0xe7, 0xf6, 0x01, + 0x1f, 0x6c, 0x89, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, + 0x02, 0x07, 0x80, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, + 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x71, 0x81, 0xc8, 0xaf, 0x54, 0xf9, 0x81, 0x48, 0x8e, 0x7d, + 0xf5, 0x45, 0xd2, 0x66, 0x19, 0x36, 0xf0, 0xe9, 0xf6, 0xb0, 0xd1, 0x58, 0xfb, 0x9a, 0xbc, 0x80, + 0x62, 0xaa, 0xfd, 0xed, 0x7b, 0xb5, 0x02, 0x21, 0x00, 0x8f, 0x65, 0xfc, 0xce, 0x02, 0xeb, 0xd9, + 0xd2, 0x3e, 0x9a, 0x37, 0x43, 0x34, 0x61, 0x05, 0x0b, 0xf0, 0x4a, 0x2d, 0xe6, 0x20, 0x33, 0xa7, + 0x06, 0xd2, 0xbe, 0xe4, 0x08, 0xf0, 0x52, 0x50, 0xb1, 0x30, 0x82, 0x02, 0xef, 0x30, 0x82, 0x02, + 0x75, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e, 0x44, 0x86, 0xf9, 0xd8, 0x8c, 0x9e, 0x99, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x6c, 0x31, 0x20, + 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, + 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, + 0x30, 0x36, 0x32, 0x35, 0x32, 0x33, 0x34, 0x31, 0x32, 0x37, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, + 0x36, 0x32, 0x32, 0x32, 0x33, 0x34, 0x31, 0x32, 0x37, 0x5a, 0x30, 0x59, 0x31, 0x35, 0x30, 0x33, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x41, 0x20, 0x36, 0x20, 0x2d, + 0x20, 0x47, 0x31, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, + 0x13, 0xcf, 0x5b, 0x49, 0xca, 0x59, 0x56, 0x92, 0x3d, 0x5c, 0x46, 0xd5, 0x7a, 0x95, 0xe4, 0xa0, + 0xb0, 0x84, 0x1e, 0x68, 0x3e, 0x2c, 0x13, 0xb1, 0xdc, 0x4e, 0x26, 0xac, 0x72, 0x6a, 0x11, 0x93, + 0x77, 0xe3, 0xa0, 0xe3, 0x6f, 0x48, 0x0b, 0x96, 0xf5, 0xfe, 0xd5, 0xbd, 0xa5, 0xbc, 0x4f, 0x74, + 0x03, 0xf1, 0x09, 0xf3, 0xbf, 0xc3, 0x0d, 0xb8, 0x9b, 0x62, 0x2b, 0xc0, 0xd3, 0x4a, 0x06, 0x95, + 0xa3, 0x82, 0x01, 0x12, 0x30, 0x82, 0x01, 0x0e, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfc, 0x46, 0xd8, 0x83, 0x6c, 0x1f, 0xe6, 0xf2, 0xdc, 0xdf, + 0xa7, 0x99, 0x17, 0xae, 0x0b, 0x44, 0x67, 0x17, 0x1b, 0x46, 0x30, 0x53, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x47, 0x30, 0x45, 0x30, 0x43, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x37, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, + 0x63, 0x73, 0x70, 0x2d, 0x75, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x61, 0x70, 0x70, + 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x33, 0x2d, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x72, 0x6f, 0x6f, 0x74, 0x63, 0x61, 0x67, 0x33, 0x30, + 0x44, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x3d, 0x30, 0x3b, 0x30, 0x39, 0xa0, 0x37, 0xa0, 0x35, + 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2d, 0x75, 0x61, 0x74, + 0x2e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x72, 0x6f, 0x6f, 0x74, 0x63, 0x61, 0x67, + 0x33, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0xa9, 0x85, 0xc1, 0x1a, 0x0a, 0xe5, 0xd8, 0x79, 0xcd, 0xf0, 0x7b, 0x46, 0xfa, 0x99, 0xef, 0x4b, + 0x61, 0x47, 0x73, 0x84, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, + 0x03, 0x02, 0x01, 0x06, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, + 0x02, 0x1a, 0x04, 0x02, 0x05, 0x00, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, + 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x30, 0x28, 0xb1, 0x65, 0x9c, 0x8f, 0xfc, 0x4e, + 0xf9, 0xf3, 0x18, 0x21, 0xf0, 0x00, 0xb7, 0x76, 0x23, 0x57, 0x78, 0xb1, 0x1a, 0x71, 0x15, 0xd0, + 0xef, 0x7b, 0x3c, 0xaf, 0x4f, 0xc6, 0x1c, 0x4d, 0x55, 0x16, 0x5d, 0x1b, 0x92, 0xde, 0x97, 0x4c, + 0x88, 0xe4, 0x8a, 0x2d, 0x86, 0xd8, 0x79, 0x2d, 0xb5, 0x02, 0x31, 0x00, 0xf4, 0xbc, 0xb0, 0x78, + 0xe1, 0x0e, 0xf5, 0x8a, 0x4f, 0xb9, 0x23, 0xd7, 0x75, 0x6b, 0x88, 0x23, 0xdd, 0xed, 0xca, 0xd1, + 0xa0, 0x27, 0xc4, 0x86, 0xed, 0x4b, 0x8c, 0x24, 0x22, 0x61, 0x6c, 0x56, 0x42, 0x5f, 0xfa, 0x2b, + 0x10, 0x43, 0xfa, 0xa0, 0xe8, 0x27, 0xb0, 0xcb, 0x5f, 0xea, 0xcb, 0xfb +}; + +/* Prio Statistics Facilitator_ XX.issuer.pem: good + This Update: Jan 12 00:16:01 2021 GMT + Next Update: Jan 13 00:16:01 2021 GMT */ +const uint8_t _trust_server_ocsp_response_ca[] = { + 0x30, 0x82, 0x03, 0xa1, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x03, 0x9a, 0x30, 0x82, 0x03, 0x96, 0x06, + 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x03, 0x87, 0x30, 0x82, + 0x03, 0x83, 0x30, 0x81, 0xbb, 0xa2, 0x16, 0x04, 0x14, 0xcd, 0x9a, 0x25, 0x8d, 0xfc, 0x76, 0x41, + 0x28, 0xd4, 0x41, 0x2b, 0x56, 0xc9, 0x98, 0xec, 0x84, 0x0a, 0xa9, 0x94, 0xfa, 0x18, 0x0f, 0x32, + 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x31, 0x36, 0x30, 0x31, 0x5a, 0x30, 0x6b, + 0x30, 0x69, 0x30, 0x41, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, + 0x14, 0x39, 0x9b, 0x6b, 0xd0, 0x5c, 0xd0, 0xe8, 0xad, 0x41, 0x5c, 0x2e, 0x5e, 0x9d, 0xe4, 0x60, + 0xce, 0x12, 0x54, 0xa3, 0x75, 0x04, 0x14, 0xfc, 0x46, 0xd8, 0x83, 0x6c, 0x1f, 0xe6, 0xf2, 0xdc, + 0xdf, 0xa7, 0x99, 0x17, 0xae, 0x0b, 0x44, 0x67, 0x17, 0x1b, 0x46, 0x02, 0x08, 0x4e, 0x44, 0x86, + 0xf9, 0xd8, 0x8c, 0x9e, 0x99, 0x80, 0x00, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, + 0x32, 0x30, 0x30, 0x31, 0x36, 0x30, 0x31, 0x5a, 0xa0, 0x11, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, + 0x30, 0x31, 0x31, 0x33, 0x30, 0x30, 0x31, 0x36, 0x30, 0x31, 0x5a, 0xa1, 0x23, 0x30, 0x21, 0x30, + 0x1f, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02, 0x04, 0x12, 0x04, 0x10, + 0xe1, 0x9a, 0x54, 0x08, 0xd5, 0x2d, 0x52, 0x09, 0xdc, 0xe5, 0x6f, 0x0c, 0xd2, 0xe8, 0x83, 0xad, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, + 0x45, 0x02, 0x21, 0x00, 0x8f, 0xe7, 0xa5, 0xc7, 0x5d, 0x6b, 0x99, 0xea, 0x6d, 0xe6, 0x4d, 0xfd, + 0xe7, 0x54, 0x92, 0x20, 0x25, 0x4e, 0x0e, 0x5f, 0xb9, 0x0e, 0x89, 0xd5, 0x0c, 0xc5, 0x28, 0xae, + 0x1d, 0x1c, 0x0a, 0xdc, 0x02, 0x20, 0x59, 0xce, 0xfe, 0x85, 0xe9, 0x8c, 0xec, 0x4d, 0xa1, 0x2b, + 0x02, 0x8d, 0x94, 0xff, 0xa1, 0xf0, 0xc2, 0xfd, 0xb7, 0x22, 0xdf, 0x9f, 0x43, 0x95, 0x36, 0x6f, + 0x00, 0x21, 0x95, 0xe2, 0x6a, 0x50, 0xa0, 0x82, 0x02, 0x6b, 0x30, 0x82, 0x02, 0x67, 0x30, 0x82, + 0x02, 0x63, 0x30, 0x82, 0x01, 0xe9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x0d, 0x83, 0xd0, + 0x68, 0x12, 0x2a, 0xf0, 0xd6, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, + 0x02, 0x30, 0x6c, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, + 0x20, 0x2d, 0x20, 0x47, 0x33, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, + 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x31, 0x36, 0x35, 0x35, 0x5a, + 0x17, 0x0d, 0x32, 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x31, 0x36, 0x35, 0x35, 0x5a, 0x30, + 0x59, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2c, 0x54, 0x65, 0x73, 0x74, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x41, 0x47, 0x33, 0x20, 0x4f, 0x43, + 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x47, 0x31, 0x20, + 0x32, 0x30, 0x32, 0x30, 0x31, 0x32, 0x31, 0x37, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, + 0x07, 0x03, 0x42, 0x00, 0x04, 0x4c, 0xb8, 0xfc, 0x81, 0x45, 0x6a, 0x1e, 0x89, 0xdd, 0x43, 0xfe, + 0xf2, 0x42, 0xc7, 0xed, 0xa2, 0xb1, 0xe6, 0xda, 0xfd, 0x22, 0x49, 0x23, 0xb2, 0x5a, 0xf5, 0xe7, + 0x6e, 0xbd, 0x36, 0xd5, 0x4e, 0x1a, 0x72, 0x72, 0x12, 0x0d, 0xcd, 0xd6, 0x9a, 0x66, 0xe2, 0xfd, + 0x7b, 0x17, 0x05, 0x7a, 0x94, 0x95, 0x54, 0x6b, 0xeb, 0xdd, 0x29, 0x7c, 0xee, 0x69, 0x08, 0xb7, + 0x27, 0x13, 0x7b, 0xdd, 0x07, 0xa3, 0x81, 0x87, 0x30, 0x81, 0x84, 0x30, 0x0c, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfc, 0x46, 0xd8, 0x83, 0x6c, 0x1f, 0xe6, 0xf2, 0xdc, 0xdf, + 0xa7, 0x99, 0x17, 0xae, 0x0b, 0x44, 0x67, 0x17, 0x1b, 0x46, 0x30, 0x0f, 0x06, 0x09, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x05, 0x04, 0x02, 0x05, 0x00, 0x30, 0x13, 0x06, 0x03, 0x55, + 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xcd, 0x9a, 0x25, 0x8d, 0xfc, + 0x76, 0x41, 0x28, 0xd4, 0x41, 0x2b, 0x56, 0xc9, 0x98, 0xec, 0x84, 0x0a, 0xa9, 0x94, 0xfa, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, + 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x68, 0x00, 0x30, 0x65, + 0x02, 0x30, 0x7b, 0x29, 0x81, 0xb5, 0xe8, 0x66, 0xfe, 0xe7, 0x54, 0x6a, 0x33, 0xc2, 0x01, 0xa7, + 0xd4, 0xb4, 0x76, 0xbf, 0x9a, 0x08, 0x5a, 0x42, 0xea, 0xcb, 0xeb, 0xbd, 0xce, 0x2b, 0x22, 0x71, + 0x32, 0x36, 0xa5, 0xc4, 0xb8, 0xc2, 0xd6, 0x84, 0xff, 0x8b, 0x15, 0x6b, 0xdd, 0xab, 0x6e, 0x64, + 0x10, 0xc7, 0x02, 0x31, 0x00, 0xbd, 0x3a, 0x29, 0x96, 0x44, 0xe4, 0x2d, 0xee, 0x6e, 0xe0, 0x9d, + 0x37, 0x26, 0xab, 0x86, 0x9d, 0x8f, 0xb6, 0xfd, 0x8c, 0xe7, 0xf8, 0x76, 0x4c, 0xad, 0xf2, 0x9b, + 0xea, 0x53, 0xa2, 0x7e, 0x48, 0xd6, 0x66, 0xed, 0xd2, 0x43, 0xc8, 0xe1, 0xa3, 0x3c, 0x68, 0xa3, + 0xde, 0xfd, 0xd3, 0x8a, 0x79 +}; + +#endif /* _TRUSTTESTS_DAEMON_REVOCATION_SERVER_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m b/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m new file mode 100644 index 00000000..49348b34 --- /dev/null +++ b/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m @@ -0,0 +1,434 @@ +/* +* Copyright (c) 2011-2019 Apple Inc. All Rights Reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +#include +#import +#import +#include +#include +#include +#include +#include +#include +#include + +#import "../TestMacroConversions.h" +#import "TrustEvaluationTestCase.h" + +#import "AllowlistBlocklistTests_data.h" + +@interface BlocklistTests :TrustEvaluationTestCase +@end + +@implementation BlocklistTests + +- (void)validate_one_cert:(uint8_t *)data length:(size_t)len chain_length:(int)chain_length trustResult:(SecTrustResultType)trust_result +{ + SecTrustRef trust = NULL; + SecCertificateRef cert = NULL, root = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); + CFArrayRef certs = NULL; + + isnt(cert = SecCertificateCreateWithBytes(NULL, data, len), + NULL, "create cert"); + isnt(root = SecCertificateCreateWithBytes(NULL, UTNHardware_cer, sizeof(UTNHardware_cer)), NULL); + certs = CFArrayCreate(NULL, (const void **)&cert, 1, NULL); + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "create trust with single cert"); + ok_status(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)@[(__bridge id)root])); + + SecTrustResultType trustResult; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is(SecTrustGetCertificateCount(trust), chain_length, "cert count"); + is_status(trustResult, trust_result, "correct trustResult"); + CFRelease(trust); + CFRelease(policy); + CFRelease(certs); + CFRelease(cert); + CFReleaseNull(root); +} + +- (void)testBlocklistedCerts +{ + [self validate_one_cert:Global_Trustee_cer length:sizeof(Global_Trustee_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:login_yahoo_com_1_cer length:sizeof(login_yahoo_com_1_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + + /* this is the root, which isn't ok for ssl and fails here, but at the + same time it proves that kSecTrustResultFatalTrustFailure isn't + returned for policy failures that aren't blocklisting */ + [self validate_one_cert:login_yahoo_com_2_cer length:sizeof(login_yahoo_com_2_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:addons_mozilla_org_cer length:sizeof(addons_mozilla_org_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:login_yahoo_com_cer length:sizeof(login_yahoo_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:login_live_com_cer length:sizeof(login_live_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:mail_google_com_cer length:sizeof(mail_google_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:login_skype_com_cer length:sizeof(login_skype_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:www_google_com_cer length:sizeof(www_google_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; +} + +- (void)testDigicertMalaysia { + SecPolicyRef sslPolicy = SecPolicyCreateSSL(false, 0); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + + /* Run the tests. */ + [self runCertificateTestForDirectory:sslPolicy subDirectory:@"DigicertMalaysia" verifyDate:testDate]; + + CFReleaseSafe(sslPolicy); +} + +#if !TARGET_OS_BRIDGE +/* BridgeOS doesn't have Valid -- the other Blocklist tests happen to pass because the certs fail for other + * reasons (no root store, missing EKU, disallowed hash or key size). */ +- (void)testDigiNotar { + SecPolicyRef sslPolicy = SecPolicyCreateSSL(false, 0); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + + /* Run the tests. */ + [self runCertificateTestForDirectory:sslPolicy subDirectory:@"DigiNotar" verifyDate:testDate]; + + CFReleaseSafe(sslPolicy); +} +#endif // !TARGET_OS_BRIDGE + +@end + +@interface AllowlistTests : TrustEvaluationTestCase +@end + +@implementation AllowlistTests + +#if !TARGET_OS_BRIDGE +static SecCertificateRef createCertFromStaticData(const UInt8 *certData, CFIndex certLength) +{ + SecCertificateRef cert = NULL; + CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, certData, certLength, kCFAllocatorNull); + if (data) { + cert = SecCertificateCreateWithData(NULL, data); + CFRelease(data); + } + return cert; +} + +- (void)testLeafOnAllowList +{ + SecCertificateRef certs[3]; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFDateRef date = NULL; + CFArrayRef certArray = NULL; + CFArrayRef anchorsArray = NULL; + + isnt(certs[0] = createCertFromStaticData(leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)), + NULL, "allowlist: create leaf cert"); + isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)), + NULL, "allowlist: create intermediate ca 1"); + isnt(certs[2] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), + NULL, "allowlist: create root"); + + isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 3, &kCFTypeArrayCallBacks), + NULL, "allowlist: create cert array"); + + /* create a trust reference with ssl policy */ + isnt(policy = SecPolicyCreateBasicX509(), NULL, "allowlist: create policy"); + ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "allowlist: create trust"); + + /* set evaluate date: January 6, 2020 at 2:40:00 AM PST */ + isnt(date = CFDateCreate(NULL, 600000000.0), NULL, "allowlist: create date"); + ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "allowlist: set verify date"); + + /* use a known root CA at this point in time to anchor the chain */ + isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[2], 1, &kCFTypeArrayCallBacks), + NULL, "allowlist: create anchors array"); + ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "allowlist: set anchors"); + + SecTrustResultType trustResult = kSecTrustResultInvalid; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "allowlist: evaluate"); + + /* expected result is kSecTrustResultUnspecified since cert is on allow list and its issuer chains to a trusted root */ + ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", + (int)trustResult); + + /* clean up */ + for(CFIndex idx=0; idx < 3; idx++) { + if (certs[idx]) { CFRelease(certs[idx]); } + } + if (policy) { CFRelease(policy); } + if (trust) { CFRelease(trust); } + if (date) { CFRelease(date); } + if (certArray) { CFRelease(certArray); } + if (anchorsArray) { CFRelease(anchorsArray); } +} + +- (void)testLeafNotOnAllowList +{ + SecCertificateRef certs[3]; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFDateRef date = NULL; + CFArrayRef certArray = NULL; + CFArrayRef anchorsArray = NULL; + + isnt(certs[0] = createCertFromStaticData(leafNotOnAllowList_Cert, sizeof(leafNotOnAllowList_Cert)), + NULL, "!allowlist: create leaf cert"); + isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)), + NULL, "!allowlist: create intermediate ca 1"); + isnt(certs[2] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), + NULL, "!allowlist: create root"); + + isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 3, &kCFTypeArrayCallBacks), + NULL, "!allowlist: create cert array"); + + /* create a trust reference with basic policy */ + isnt(policy = SecPolicyCreateBasicX509(), NULL, "!allowlist: create policy"); + ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "!allowlist: create trust"); + + /* set evaluate date: January 6, 2020 at 2:40:00 AM PST */ + isnt(date = CFDateCreate(NULL, 600000000.0), NULL, "allowlist: create date"); + ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "!allowlist: set verify date"); + + /* use a known root CA at this point in time to anchor the chain */ + isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[2], 1, &kCFTypeArrayCallBacks), + NULL, "allowlist: create anchors array"); + ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "!allowlist: set anchors"); + + SecTrustResultType trustResult = kSecTrustResultInvalid; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "!allowlist: evaluate"); + + /* expected result is kSecTrustResultFatalTrustFailure, since cert is not on allow list */ + ok(trustResult == kSecTrustResultFatalTrustFailure, + "trustResult 6 expected (got %d)", (int)trustResult); + + /* clean up */ + for(CFIndex idx=0; idx < 3; idx++) { + if (certs[idx]) { CFRelease(certs[idx]); } + } + if (policy) { CFRelease(policy); } + if (trust) { CFRelease(trust); } + if (date) { CFRelease(date); } + if (certArray) { CFRelease(certArray); } + if (anchorsArray) { CFRelease(anchorsArray); } +} + +- (void)testAllowListForRootCA +{ + SecCertificateRef certs[3]; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFDateRef date = NULL; + CFArrayRef certArray = NULL; + CFArrayRef anchorsArray = NULL; + + isnt(certs[0] = createCertFromStaticData(leaf_subCANotOnAllowlist_Cert, sizeof(leaf_subCANotOnAllowlist_Cert)), + NULL, "!allowlist: create leaf cert"); + isnt(certs[1] = createCertFromStaticData(subCANotOnAllowlist_Cert, sizeof(subCANotOnAllowlist_Cert)), + NULL, "!allowlist: create intermediate ca 1"); + isnt(certs[2] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), + NULL, "!allowlist: create root"); + + isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 3, &kCFTypeArrayCallBacks), + NULL, "!allowlist: create cert array"); + + /* create a trust reference with basic policy */ + isnt(policy = SecPolicyCreateBasicX509(), NULL, "!allowlist: create policy"); + ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "!allowlist: create trust"); + + /* set evaluate date: January 6, 2020 at 2:40:00 AM PST */ + isnt(date = CFDateCreate(NULL, 600000000.0), NULL, "allowlist: create date"); + ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "!allowlist: set verify date"); + + /* use a known root CA at this point in time to anchor the chain */ + isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[2], 1, &kCFTypeArrayCallBacks), + NULL, "allowlist: create anchors array"); + ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "!allowlist: set anchors"); + + SecTrustResultType trustResult = kSecTrustResultInvalid; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "!allowlist: evaluate"); + + /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) + or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ + ok(trustResult == kSecTrustResultFatalTrustFailure, + "trustResult 6 expected (got %d)", (int)trustResult); + + /* clean up */ + for(CFIndex idx=0; idx < 3; idx++) { + if (certs[idx]) { CFRelease(certs[idx]); } + } + if (policy) { CFRelease(policy); } + if (trust) { CFRelease(trust); } + if (date) { CFRelease(date); } + if (certArray) { CFRelease(certArray); } + if (anchorsArray) { CFRelease(anchorsArray); } +} + +- (void)testDateBasedAllowListForRootCA +{ + SecCertificateRef root = NULL, beforeInt = NULL, afterInt = NULL, + beforeLeaf = NULL, afterLeaf = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + NSArray *anchors = nil, *certs = nil; + NSDate *verifyDate = nil; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + require(root = SecCertificateCreateWithBytes(NULL, _datetest_root, sizeof(_datetest_root)), out); + require(beforeInt = SecCertificateCreateWithBytes(NULL, _datetest_before_int, sizeof(_datetest_before_int)), out); + require(afterInt = SecCertificateCreateWithBytes(NULL, _datetest_after_int, sizeof(_datetest_after_int)), out); + require(beforeLeaf = SecCertificateCreateWithBytes(NULL, _datetest_before_leaf, sizeof(_datetest_before_leaf)), out); + require(afterLeaf = SecCertificateCreateWithBytes(NULL, _datetest_after_leaf, sizeof(_datetest_after_leaf)), out); + + anchors = @[(__bridge id)root]; + require(policy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com")), out); + verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:504000000.0]; /* 21 Dec 2016 */ + + /* Leaf issued before cutoff should pass */ + certs = @[(__bridge id)beforeLeaf, (__bridge id)beforeInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* Leaf issued after cutoff should fail */ + certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* Intermediate issued after cutoff should fail (even for leaf issued before) */ + certs = @[(__bridge id)beforeLeaf, (__bridge id)afterInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued after cutoff succeeded evaluation"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* Intermediate issued after cutoff should fail */ + certs = @[(__bridge id)afterLeaf, (__bridge id)afterInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued before cutoff succeeded evaluation"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* Leaf issued before cutoff should choose acceptable path */ + certs = @[(__bridge id)beforeLeaf, (__bridge id) afterInt, (__bridge id)beforeInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation (multi-path)"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* No good path for leaf issued after cutoff */ + certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt, (__bridge id)afterInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation (multi-path)"); + +out: + CFReleaseNull(root); + CFReleaseNull(beforeInt); + CFReleaseNull(afterInt); + CFReleaseNull(beforeLeaf); + CFReleaseNull(afterLeaf); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + +- (void)testLeafOnAllowListOtherFailures +{ + SecCertificateRef certs[3]; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + NSArray *anchors = nil, *certArray = nil; + NSDate *verifyDate = nil; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + memset(certs, 0, 3 * sizeof(SecCertificateRef)); + + require(certs[0] = SecCertificateCreateWithBytes(NULL, leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)), out); + require(certs[1] = SecCertificateCreateWithBytes(NULL, ca1_Cert, sizeof(ca1_Cert)), out); + require(certs[2] = SecCertificateCreateWithBytes(NULL, root_Cert, sizeof(root_Cert)), out); + + anchors = @[(__bridge id)certs[2]]; + certArray = @[(__bridge id)certs[0], (__bridge id)certs[1], (__bridge id)certs[2]]; + verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]; // January 6, 2020 at 2:40:00 AM PST + + /* Mismatched policy, should fail */ + require(policy = SecPolicyCreateSSL(true, (__bridge CFStringRef)@"example.com"), out); + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certArray, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, + "hostname failure with cert on allow list succeeded evaluation"); + CFReleaseNull(policy); + trustResult = kSecTrustResultInvalid; + + /* Expired, should fail */ + verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:500000000.0]; // November 4, 2016 at 5:53:20 PM PDT + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustSetPolicies(trust, policy), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, + "EKU failure with cert on allow list succeeded evaluation"); + CFReleaseNull(policy); + trustResult = kSecTrustResultInvalid; + + /* Apple pinning policy, should fail */ + require(policy = SecPolicyCreateAppleSSLPinned((__bridge CFStringRef)@"aPolicy", + (__bridge CFStringRef)@"example.com", NULL, + (__bridge CFStringRef)@"1.2.840.113635.100.6.27.12"), out); + require_noerr(SecTrustSetPolicies(trust, policy), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, + "Apple pinning policy with cert on allow list succeeded evaluation"); + +out: + CFReleaseNull(certs[0]); + CFReleaseNull(certs[1]); + CFReleaseNull(certs[2]); + CFReleaseNull(policy); + CFReleaseNull(trust); +} +#else /* TARGET_OS_BRIDGE */ +/* Allowlists are provided by Valid, which is not supported on bridgeOS */ +- (void)testSkipTests +{ + XCTAssert(true); +} +#endif + +@end diff --git a/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h b/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h new file mode 100644 index 00000000..d52467c7 --- /dev/null +++ b/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h @@ -0,0 +1,1691 @@ +// +// AllowlistBlocklistTests_data.h +// Security +// + +#ifndef _TRUSTTESTS_ALLOWLIST_BLOCKLIST_TESTS_ +#define _TRUSTTESTS_ALLOWLIST_BLOCKLIST_TESTS_ + +/* subject:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware */ +/* issuer :/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware */ +const uint8_t UTNHardware_cer[] = { + 0x30,0x82,0x04,0x74,0x30,0x82,0x03,0x5C,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x44, + 0xBE,0x0C,0x8B,0x50,0x00,0x24,0xB4,0x11,0xD3,0x36,0x2A,0xFE,0x65,0x0A,0xFD,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81, + 0x97,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0E,0x53,0x61,0x6C,0x74,0x20,0x4C,0x61,0x6B,0x65,0x20, + 0x43,0x69,0x74,0x79,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x0A,0x13,0x15,0x54, + 0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54,0x52,0x55,0x53,0x54,0x20,0x4E,0x65,0x74, + 0x77,0x6F,0x72,0x6B,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x0B,0x13,0x18,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2E,0x63,0x6F,0x6D,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03, + 0x13,0x16,0x55,0x54,0x4E,0x2D,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2D, + 0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x30,0x1E,0x17,0x0D,0x39,0x39,0x30,0x37, + 0x30,0x39,0x31,0x38,0x31,0x30,0x34,0x32,0x5A,0x17,0x0D,0x31,0x39,0x30,0x37,0x30, + 0x39,0x31,0x38,0x31,0x39,0x32,0x32,0x5A,0x30,0x81,0x97,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x07,0x13,0x0E, + 0x53,0x61,0x6C,0x74,0x20,0x4C,0x61,0x6B,0x65,0x20,0x43,0x69,0x74,0x79,0x31,0x1E, + 0x30,0x1C,0x06,0x03,0x55,0x04,0x0A,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45, + 0x52,0x54,0x52,0x55,0x53,0x54,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x21, + 0x30,0x1F,0x06,0x03,0x55,0x04,0x0B,0x13,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x77,0x77,0x77,0x2E,0x75,0x73,0x65,0x72,0x74,0x72,0x75,0x73,0x74,0x2E,0x63,0x6F, + 0x6D,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54,0x4E,0x2D, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2D,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82, + 0x01,0x01,0x00,0xB1,0xF7,0xC3,0x38,0x3F,0xB4,0xA8,0x7F,0xCF,0x39,0x82,0x51,0x67, + 0xD0,0x6D,0x9F,0xD2,0xFF,0x58,0xF3,0xE7,0x9F,0x2B,0xEC,0x0D,0x89,0x54,0x99,0xB9, + 0x38,0x99,0x16,0xF7,0xE0,0x21,0x79,0x48,0xC2,0xBB,0x61,0x74,0x12,0x96,0x1D,0x3C, + 0x6A,0x72,0xD5,0x3C,0x10,0x67,0x3A,0x39,0xED,0x2B,0x13,0xCD,0x66,0xEB,0x95,0x09, + 0x33,0xA4,0x6C,0x97,0xB1,0xE8,0xC6,0xEC,0xC1,0x75,0x79,0x9C,0x46,0x5E,0x8D,0xAB, + 0xD0,0x6A,0xFD,0xB9,0x2A,0x55,0x17,0x10,0x54,0xB3,0x19,0xF0,0x9A,0xF6,0xF1,0xB1, + 0x5D,0xB6,0xA7,0x6D,0xFB,0xE0,0x71,0x17,0x6B,0xA2,0x88,0xFB,0x00,0xDF,0xFE,0x1A, + 0x31,0x77,0x0C,0x9A,0x01,0x7A,0xB1,0x32,0xE3,0x2B,0x01,0x07,0x38,0x6E,0xC3,0xA5, + 0x5E,0x23,0xBC,0x45,0x9B,0x7B,0x50,0xC1,0xC9,0x30,0x8F,0xDB,0xE5,0x2B,0x7A,0xD3, + 0x5B,0xFB,0x33,0x40,0x1E,0xA0,0xD5,0x98,0x17,0xBC,0x8B,0x87,0xC3,0x89,0xD3,0x5D, + 0xA0,0x8E,0xB2,0xAA,0xAA,0xF6,0x8E,0x69,0x88,0x06,0xC5,0xFA,0x89,0x21,0xF3,0x08, + 0x9D,0x69,0x2E,0x09,0x33,0x9B,0x29,0x0D,0x46,0x0F,0x8C,0xCC,0x49,0x34,0xB0,0x69, + 0x51,0xBD,0xF9,0x06,0xCD,0x68,0xAD,0x66,0x4C,0xBC,0x3E,0xAC,0x61,0xBD,0x0A,0x88, + 0x0E,0xC8,0xDF,0x3D,0xEE,0x7C,0x04,0x4C,0x9D,0x0A,0x5E,0x6B,0x91,0xD6,0xEE,0xC7, + 0xED,0x28,0x8D,0xAB,0x4D,0x87,0x89,0x73,0xD0,0x6E,0xA4,0xD0,0x1E,0x16,0x8B,0x14, + 0xE1,0x76,0x44,0x03,0x7F,0x63,0xAC,0xE4,0xCD,0x49,0x9C,0xC5,0x92,0xF4,0xAB,0x32, + 0xA1,0x48,0x5B,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xB9,0x30,0x81,0xB6,0x30,0x0B, + 0x06,0x03,0x55,0x1D,0x0F,0x04,0x04,0x03,0x02,0x01,0xC6,0x30,0x0F,0x06,0x03,0x55, + 0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xA1,0x72,0x5F,0x26,0x1B,0x28,0x98,0x43,0x95, + 0x5D,0x07,0x37,0xD5,0x85,0x96,0x9D,0x4B,0xD2,0xC3,0x45,0x30,0x44,0x06,0x03,0x55, + 0x1D,0x1F,0x04,0x3D,0x30,0x3B,0x30,0x39,0xA0,0x37,0xA0,0x35,0x86,0x33,0x68,0x74, + 0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x75,0x73,0x65,0x72,0x74,0x72,0x75, + 0x73,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x55,0x54,0x4E,0x2D,0x55,0x53,0x45,0x52,0x46, + 0x69,0x72,0x73,0x74,0x2D,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2E,0x63,0x72, + 0x6C,0x30,0x31,0x06,0x03,0x55,0x1D,0x25,0x04,0x2A,0x30,0x28,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x05, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x06,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x07,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x47,0x19,0x0F,0xDE,0x74,0xC6,0x99,0x97, + 0xAF,0xFC,0xAD,0x28,0x5E,0x75,0x8E,0xEB,0x2D,0x67,0xEE,0x4E,0x7B,0x2B,0xD7,0x0C, + 0xFF,0xF6,0xDE,0xCB,0x55,0xA2,0x0A,0xE1,0x4C,0x54,0x65,0x93,0x60,0x6B,0x9F,0x12, + 0x9C,0xAD,0x5E,0x83,0x2C,0xEB,0x5A,0xAE,0xC0,0xE4,0x2D,0xF4,0x00,0x63,0x1D,0xB8, + 0xC0,0x6C,0xF2,0xCF,0x49,0xBB,0x4D,0x93,0x6F,0x06,0xA6,0x0A,0x22,0xB2,0x49,0x62, + 0x08,0x4E,0xFF,0xC8,0xC8,0x14,0xB2,0x88,0x16,0x5D,0xE7,0x01,0xE4,0x12,0x95,0xE5, + 0x45,0x34,0xB3,0x8B,0x69,0xBD,0xCF,0xB4,0x85,0x8F,0x75,0x51,0x9E,0x7D,0x3A,0x38, + 0x3A,0x14,0x48,0x12,0xC6,0xFB,0xA7,0x3B,0x1A,0x8D,0x0D,0x82,0x40,0x07,0xE8,0x04, + 0x08,0x90,0xA1,0x89,0xCB,0x19,0x50,0xDF,0xCA,0x1C,0x01,0xBC,0x1D,0x04,0x19,0x7B, + 0x10,0x76,0x97,0x3B,0xEE,0x90,0x90,0xCA,0xC4,0x0E,0x1F,0x16,0x6E,0x75,0xEF,0x33, + 0xF8,0xD3,0x6F,0x5B,0x1E,0x96,0xE3,0xE0,0x74,0x77,0x74,0x7B,0x8A,0xA2,0x6E,0x2D, + 0xDD,0x76,0xD6,0x39,0x30,0x82,0xF0,0xAB,0x9C,0x52,0xF2,0x2A,0xC7,0xAF,0x49,0x5E, + 0x7E,0xC7,0x68,0xE5,0x82,0x81,0xC8,0x6A,0x27,0xF9,0x27,0x88,0x2A,0xD5,0x58,0x50, + 0x95,0x1F,0xF0,0x3B,0x1C,0x57,0xBB,0x7D,0x14,0x39,0x62,0x2B,0x9A,0xC9,0x94,0x92, + 0x2A,0xA3,0x22,0x0C,0xFF,0x89,0x26,0x7D,0x5F,0x23,0x2B,0x47,0xD7,0x15,0x1D,0xA9, + 0x6A,0x9E,0x51,0x0D,0x2A,0x51,0x9E,0x81,0xF9,0xD4,0x3B,0x5E,0x70,0x12,0x7F,0x10, + 0x32,0x9C,0x1E,0xBB,0x9D,0xF8,0x66,0xA8, +}; + +unsigned char Global_Trustee_cer[] = { + 0x30,0x82,0x06,0xdd,0x30,0x82,0x05,0xc5,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xd8,0xf3,0x5f,0x4e, + 0xb7,0x87,0x2b,0x2d,0xab,0x06,0x92,0xe3,0x15,0x38,0x2f,0xb0,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xe3,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x07,0x13,0x05,0x54,0x61,0x6d,0x70,0x61,0x31, + 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c,0x61,0x67, + 0x65,0x20,0x31,0x30,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x47,0x6c,0x6f,0x62,0x61, + 0x6c,0x20,0x54,0x72,0x75,0x73,0x74,0x65,0x65,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0b,0x13,0x0e, + 0x47,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x54,0x72,0x75,0x73,0x74,0x65,0x65,0x31,0x28,0x30,0x26,0x06,0x03, + 0x55,0x04,0x0b,0x13,0x1f,0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47, + 0x72,0x6f,0x75,0x70,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12, + 0x06,0x03,0x55,0x04,0x0b,0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x17, + 0x30,0x15,0x06,0x03,0x55,0x04,0x03,0x13,0x0e,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x74,0x72,0x75,0x73, + 0x74,0x65,0x65,0x30,0x82,0x02,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, + 0x05,0x00,0x03,0x82,0x02,0x0f,0x00,0x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xd9,0x74,0xf2,0xaa, + 0x41,0x1d,0xdf,0xf5,0xc2,0x16,0x43,0x49,0x5c,0x29,0xbf,0xb6,0x89,0x74,0x29,0xbc,0x9c,0x8d,0x0c,0x46, + 0x4f,0x59,0x7e,0xb2,0x41,0x17,0x66,0x34,0x0c,0x65,0x89,0xe1,0x6c,0x25,0xe3,0x86,0x0a,0x9e,0x22,0x45, + 0x22,0x8c,0xdd,0x9d,0xe6,0xa3,0x95,0xde,0xdc,0x88,0x02,0x55,0x5c,0xe3,0x5b,0x91,0x75,0xeb,0x26,0x69, + 0x63,0xb9,0x2e,0xc6,0xca,0x2e,0x27,0xdf,0x88,0xba,0x02,0x20,0x6e,0xfe,0xb9,0x0b,0x29,0xd7,0xa7,0xd6, + 0xd7,0x48,0x1a,0x1c,0xce,0xdd,0x1f,0xa9,0x27,0x0e,0x62,0x4f,0xa1,0x96,0x1e,0xdd,0x54,0x3a,0x34,0x63, + 0x4a,0x76,0xf5,0x77,0x7d,0x59,0x67,0xd8,0x10,0xd4,0xb5,0x0f,0x3a,0x43,0x22,0x98,0xdb,0xf4,0x09,0xc4, + 0x0a,0x70,0xce,0xdd,0x90,0xd4,0x2f,0xef,0x74,0x13,0xc3,0xcd,0xc2,0x89,0x39,0x62,0x15,0x9d,0xe6,0x74, + 0xa8,0xe8,0x9b,0xf0,0x63,0x6e,0x9c,0x89,0xb6,0x0e,0xad,0x9b,0xf7,0xcc,0x82,0xe8,0xe8,0x2d,0xb8,0x0b, + 0xda,0x22,0xec,0x49,0x85,0x07,0x88,0x99,0x98,0x3f,0xf4,0x74,0xa9,0x09,0xf7,0x81,0x7c,0x97,0x0b,0x59, + 0x99,0x18,0x72,0x8b,0xdb,0x94,0x82,0x2b,0xa7,0xe8,0xaa,0x6b,0x97,0xbf,0x88,0x7e,0x75,0xb0,0x8b,0x45, + 0x45,0x0c,0xc7,0xa8,0x09,0xea,0x1b,0x41,0x58,0x30,0x3b,0x5f,0x78,0x65,0x15,0x34,0xd2,0xe4,0x3c,0x34, + 0x0d,0x1d,0xd8,0x64,0x3c,0x8a,0xa5,0x56,0x49,0x99,0x28,0x2d,0x4b,0xf2,0xcf,0xcd,0xd9,0x6e,0x49,0x64, + 0x9b,0xa9,0x79,0x90,0x77,0x55,0xa9,0x08,0x1b,0xad,0x1a,0x74,0x9e,0xe0,0x03,0x93,0x0a,0x09,0xb7,0xad, + 0xa7,0xb4,0x5c,0xef,0x83,0x6c,0xb7,0x9a,0xb4,0xc6,0x68,0x40,0x80,0x1d,0x42,0xd1,0x6e,0x79,0x9b,0xa9, + 0x19,0x21,0x9a,0x9c,0xf9,0x86,0x2d,0x00,0xd1,0x34,0xfe,0xe0,0xb6,0xf9,0x55,0xb6,0xf5,0x26,0xc5,0x95, + 0x16,0xa5,0x7c,0x73,0x9f,0x0a,0x29,0x89,0xac,0x3a,0x98,0xf7,0x9b,0x74,0x67,0xb7,0x90,0xb7,0x5d,0x09, + 0x23,0x6a,0x6a,0xed,0x2c,0x10,0xee,0x53,0x0a,0x10,0xf0,0x16,0x1f,0x57,0xb3,0xb1,0x0d,0x79,0x91,0x19, + 0xb0,0xeb,0xcd,0x30,0x3f,0xa0,0x14,0x5f,0xb3,0xc6,0xfd,0x5c,0x33,0xa7,0xb0,0xff,0x98,0xb0,0x55,0x8c, + 0xb9,0xa5,0xf2,0x6f,0x47,0x24,0x49,0x21,0x69,0xcc,0x42,0xa2,0x51,0x00,0x40,0x85,0x8c,0x82,0x82,0xab, + 0x32,0xa5,0xcb,0x9a,0xdc,0xd0,0xd9,0x18,0x0d,0xdf,0x19,0xf4,0xaf,0x83,0x0d,0xc1,0x3e,0x31,0xdb,0x24, + 0x48,0xb6,0x75,0x80,0xa1,0xe1,0xc9,0x77,0x64,0x1e,0xa7,0xe5,0x8b,0x7f,0x15,0x4d,0x4b,0xa7,0xc2,0xd0, + 0xed,0x79,0x95,0x5e,0x91,0x31,0xec,0x18,0xff,0x4e,0x9f,0x48,0x14,0xea,0x75,0xba,0x21,0xce,0x29,0x76, + 0xe9,0x1f,0x4e,0x51,0x87,0x2e,0xb3,0xcc,0x04,0x60,0xba,0x23,0x1f,0x1f,0x65,0xb2,0x0a,0xb8,0xd5,0x6e, + 0x8f,0x4b,0x42,0x89,0x47,0xa9,0x81,0x90,0x5b,0x2b,0xb2,0xb6,0xae,0xe6,0xa0,0x70,0x7b,0x78,0x90,0x0a, + 0x7a,0xc5,0xe5,0xe7,0xc5,0xfb,0x0a,0xf6,0x2f,0x69,0x8c,0x8c,0x1f,0x57,0xe0,0x06,0x99,0xff,0x11,0xd5, + 0x52,0x32,0x20,0x97,0x27,0x98,0xee,0x65,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xd4,0x30,0x82,0x01, + 0xd0,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28, + 0x98,0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x0e,0x04,0x16,0x04,0x14,0xb7,0xc3,0xde,0x1a,0x43,0xed,0x41,0x97,0xa9,0x8f,0x29,0x78,0x9c,0x03,0xb9, + 0xac,0x40,0x42,0x00,0xac,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05, + 0xa0,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55, + 0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06, + 0x0c,0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b, + 0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63, + 0x75,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b, + 0x06,0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d, + 0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77, + 0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a, + 0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e, + 0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e, + 0x63,0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30, + 0x3b,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x63,0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e, + 0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74, + 0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x19, + 0x06,0x03,0x55,0x1d,0x11,0x04,0x12,0x30,0x10,0x82,0x0e,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x74,0x72, + 0x75,0x73,0x74,0x65,0x65,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x8f,0xba,0x75,0xba,0x39,0xd4,0x26,0xd3,0x70,0x0f,0xc4,0xb3,0x02,0xa7,0xc5, + 0x12,0x23,0x71,0xc9,0xfe,0x63,0xe9,0xa3,0x62,0x78,0x24,0x44,0x4f,0xd4,0xb9,0x11,0x3e,0x1f,0xc7,0x28, + 0xe7,0x55,0x6b,0xee,0xf4,0xe1,0x00,0x91,0x86,0x8a,0xc9,0x09,0x6b,0x9f,0x2e,0xa4,0x45,0x39,0xd1,0x61, + 0x62,0x5e,0x93,0xa5,0x05,0x45,0x78,0x9f,0x60,0x12,0x2c,0xf4,0x6c,0x65,0x65,0x0d,0xcc,0x46,0x34,0x8b, + 0x28,0xba,0xa0,0xc6,0xf4,0x99,0x71,0x64,0xf3,0x22,0x76,0xac,0x4f,0xf3,0x62,0xc9,0xa7,0x33,0x5a,0x07, + 0x1f,0x3d,0xc9,0x86,0x80,0xdc,0xdb,0x04,0x2f,0x87,0x27,0xe8,0xbf,0x48,0x44,0x81,0xc0,0xf0,0x49,0x23, + 0x6e,0x1f,0xe5,0xe4,0x03,0x86,0x24,0x13,0xa2,0x85,0x62,0x7c,0x58,0x04,0xca,0xe6,0x8d,0x13,0x72,0x0a, + 0xba,0x56,0x44,0xa2,0x0f,0xbc,0xfb,0xa0,0x3d,0x0d,0x2a,0x7f,0xfb,0x9e,0xa9,0x09,0x3d,0xb7,0x5a,0xd4, + 0x8a,0x8d,0xe1,0x25,0xe8,0xa4,0x09,0x84,0x70,0xad,0x12,0x44,0xb9,0xcf,0xb9,0x33,0x7a,0xba,0x5c,0xe6, + 0x4b,0xa6,0xbb,0x05,0x06,0x98,0xff,0xf2,0x98,0x52,0x7b,0x77,0x80,0x27,0x4a,0xd9,0xe2,0xfa,0xb9,0x52, + 0xd4,0xfb,0xfb,0xe6,0xd6,0x2d,0x9e,0x8f,0xc1,0x15,0x44,0x8d,0x9b,0x74,0x2f,0xee,0x94,0x5a,0x4e,0xd3, + 0xc4,0x8b,0x8a,0xac,0x43,0x9d,0x73,0xf6,0xae,0x0c,0x87,0x89,0xad,0x87,0xc9,0xc9,0xc7,0xdd,0xba,0x14, + 0x60,0x7a,0xf8,0xb5,0x35,0x9d,0xc2,0x8d,0xc6,0x96,0x81,0x0d,0xa9,0x52,0x8a,0x29,0x40,0x04,0xe9,0x19, + 0xb4 +}; +unsigned int Global_Trustee_cer_len = 1761; + +unsigned char UTN_USERFirst_Hardware_cer[] = { + 0x30,0x82,0x04,0x74,0x30,0x82,0x03,0x5c,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x44,0xbe,0x0c,0x8b,0x50, + 0x00,0x24,0xb4,0x11,0xd3,0x36,0x2a,0xfe,0x65,0x0a,0xfd,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74,0x79, + 0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54, + 0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55,0x04, + 0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54, + 0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65, + 0x30,0x1e,0x17,0x0d,0x39,0x39,0x30,0x37,0x30,0x39,0x31,0x38,0x31,0x30,0x34,0x32,0x5a,0x17,0x0d,0x31, + 0x39,0x30,0x37,0x30,0x39,0x31,0x38,0x31,0x39,0x32,0x32,0x5a,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55, + 0x54,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b, + 0x65,0x20,0x43,0x69,0x74,0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65, + 0x20,0x55,0x53,0x45,0x52,0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21, + 0x30,0x1f,0x06,0x03,0x55,0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e, + 0x75,0x73,0x65,0x72,0x74,0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55, + 0x04,0x03,0x13,0x16,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61, + 0x72,0x64,0x77,0x61,0x72,0x65,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, + 0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xb1, + 0xf7,0xc3,0x38,0x3f,0xb4,0xa8,0x7f,0xcf,0x39,0x82,0x51,0x67,0xd0,0x6d,0x9f,0xd2,0xff,0x58,0xf3,0xe7, + 0x9f,0x2b,0xec,0x0d,0x89,0x54,0x99,0xb9,0x38,0x99,0x16,0xf7,0xe0,0x21,0x79,0x48,0xc2,0xbb,0x61,0x74, + 0x12,0x96,0x1d,0x3c,0x6a,0x72,0xd5,0x3c,0x10,0x67,0x3a,0x39,0xed,0x2b,0x13,0xcd,0x66,0xeb,0x95,0x09, + 0x33,0xa4,0x6c,0x97,0xb1,0xe8,0xc6,0xec,0xc1,0x75,0x79,0x9c,0x46,0x5e,0x8d,0xab,0xd0,0x6a,0xfd,0xb9, + 0x2a,0x55,0x17,0x10,0x54,0xb3,0x19,0xf0,0x9a,0xf6,0xf1,0xb1,0x5d,0xb6,0xa7,0x6d,0xfb,0xe0,0x71,0x17, + 0x6b,0xa2,0x88,0xfb,0x00,0xdf,0xfe,0x1a,0x31,0x77,0x0c,0x9a,0x01,0x7a,0xb1,0x32,0xe3,0x2b,0x01,0x07, + 0x38,0x6e,0xc3,0xa5,0x5e,0x23,0xbc,0x45,0x9b,0x7b,0x50,0xc1,0xc9,0x30,0x8f,0xdb,0xe5,0x2b,0x7a,0xd3, + 0x5b,0xfb,0x33,0x40,0x1e,0xa0,0xd5,0x98,0x17,0xbc,0x8b,0x87,0xc3,0x89,0xd3,0x5d,0xa0,0x8e,0xb2,0xaa, + 0xaa,0xf6,0x8e,0x69,0x88,0x06,0xc5,0xfa,0x89,0x21,0xf3,0x08,0x9d,0x69,0x2e,0x09,0x33,0x9b,0x29,0x0d, + 0x46,0x0f,0x8c,0xcc,0x49,0x34,0xb0,0x69,0x51,0xbd,0xf9,0x06,0xcd,0x68,0xad,0x66,0x4c,0xbc,0x3e,0xac, + 0x61,0xbd,0x0a,0x88,0x0e,0xc8,0xdf,0x3d,0xee,0x7c,0x04,0x4c,0x9d,0x0a,0x5e,0x6b,0x91,0xd6,0xee,0xc7, + 0xed,0x28,0x8d,0xab,0x4d,0x87,0x89,0x73,0xd0,0x6e,0xa4,0xd0,0x1e,0x16,0x8b,0x14,0xe1,0x76,0x44,0x03, + 0x7f,0x63,0xac,0xe4,0xcd,0x49,0x9c,0xc5,0x92,0xf4,0xab,0x32,0xa1,0x48,0x5b,0x02,0x03,0x01,0x00,0x01, + 0xa3,0x81,0xb9,0x30,0x81,0xb6,0x30,0x0b,0x06,0x03,0x55,0x1d,0x0f,0x04,0x04,0x03,0x02,0x01,0xc6,0x30, + 0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1d,0x06,0x03, + 0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98,0x43,0x95,0x5d,0x07,0x37,0xd5, + 0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x44,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3d,0x30,0x3b,0x30,0x39, + 0xa0,0x37,0xa0,0x35,0x86,0x33,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x75,0x73,0x65, + 0x72,0x74,0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46, + 0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x31,0x06, + 0x03,0x55,0x1d,0x25,0x04,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08, + 0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x05,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x06,0x06,0x08, + 0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x07,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01, + 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x47,0x19,0x0f,0xde,0x74,0xc6,0x99,0x97,0xaf,0xfc,0xad,0x28, + 0x5e,0x75,0x8e,0xeb,0x2d,0x67,0xee,0x4e,0x7b,0x2b,0xd7,0x0c,0xff,0xf6,0xde,0xcb,0x55,0xa2,0x0a,0xe1, + 0x4c,0x54,0x65,0x93,0x60,0x6b,0x9f,0x12,0x9c,0xad,0x5e,0x83,0x2c,0xeb,0x5a,0xae,0xc0,0xe4,0x2d,0xf4, + 0x00,0x63,0x1d,0xb8,0xc0,0x6c,0xf2,0xcf,0x49,0xbb,0x4d,0x93,0x6f,0x06,0xa6,0x0a,0x22,0xb2,0x49,0x62, + 0x08,0x4e,0xff,0xc8,0xc8,0x14,0xb2,0x88,0x16,0x5d,0xe7,0x01,0xe4,0x12,0x95,0xe5,0x45,0x34,0xb3,0x8b, + 0x69,0xbd,0xcf,0xb4,0x85,0x8f,0x75,0x51,0x9e,0x7d,0x3a,0x38,0x3a,0x14,0x48,0x12,0xc6,0xfb,0xa7,0x3b, + 0x1a,0x8d,0x0d,0x82,0x40,0x07,0xe8,0x04,0x08,0x90,0xa1,0x89,0xcb,0x19,0x50,0xdf,0xca,0x1c,0x01,0xbc, + 0x1d,0x04,0x19,0x7b,0x10,0x76,0x97,0x3b,0xee,0x90,0x90,0xca,0xc4,0x0e,0x1f,0x16,0x6e,0x75,0xef,0x33, + 0xf8,0xd3,0x6f,0x5b,0x1e,0x96,0xe3,0xe0,0x74,0x77,0x74,0x7b,0x8a,0xa2,0x6e,0x2d,0xdd,0x76,0xd6,0x39, + 0x30,0x82,0xf0,0xab,0x9c,0x52,0xf2,0x2a,0xc7,0xaf,0x49,0x5e,0x7e,0xc7,0x68,0xe5,0x82,0x81,0xc8,0x6a, + 0x27,0xf9,0x27,0x88,0x2a,0xd5,0x58,0x50,0x95,0x1f,0xf0,0x3b,0x1c,0x57,0xbb,0x7d,0x14,0x39,0x62,0x2b, + 0x9a,0xc9,0x94,0x92,0x2a,0xa3,0x22,0x0c,0xff,0x89,0x26,0x7d,0x5f,0x23,0x2b,0x47,0xd7,0x15,0x1d,0xa9, + 0x6a,0x9e,0x51,0x0d,0x2a,0x51,0x9e,0x81,0xf9,0xd4,0x3b,0x5e,0x70,0x12,0x7f,0x10,0x32,0x9c,0x1e,0xbb, + 0x9d,0xf8,0x66,0xa8 +}; +unsigned int UTN_USERFirst_Hardware_cer_len = 1144; + +unsigned char addons_mozilla_org_cer[] = { + 0x30,0x82,0x05,0xf8,0x30,0x82,0x04,0xe0,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0x92,0x39,0xd5,0x34, + 0x8f,0x40,0xd1,0x69,0x5a,0x74,0x54,0x70,0xe1,0xf2,0x3f,0x43,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xe2,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x1b,0x30,0x19,0x06,0x03,0x55, + 0x04,0x03,0x13,0x12,0x61,0x64,0x64,0x6f,0x6e,0x73,0x2e,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f, + 0x72,0x67,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05, + 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xab,0xc6,0x6d,0x36,0xf3, + 0x15,0x73,0x78,0x83,0x73,0xce,0x74,0x85,0xd5,0xae,0xec,0xb2,0xf0,0xe0,0x24,0x1f,0x13,0x83,0xb8,0x20, + 0xac,0xbb,0x9a,0xfe,0x88,0xbb,0xab,0xa1,0x1d,0x0b,0x1f,0x45,0x00,0xaa,0x49,0xb7,0x35,0x37,0x0c,0x6a, + 0xef,0x47,0x4c,0xb9,0xd1,0xbe,0xe3,0x57,0x12,0x04,0x8d,0x92,0xc7,0xb6,0xec,0x01,0xbc,0xb6,0xda,0xc7, + 0x81,0x38,0x20,0xad,0x72,0x85,0xe6,0x0e,0xfc,0x81,0x6c,0x07,0xad,0x68,0x76,0x38,0xc5,0x44,0xd7,0xcc, + 0xc6,0x4a,0xc5,0x97,0x3e,0x64,0xf4,0x51,0xe6,0xf0,0x7e,0xb2,0xec,0x56,0xf7,0x25,0x82,0x4d,0x49,0x98, + 0xcb,0x16,0x98,0xdd,0x23,0xf1,0x89,0x91,0xd1,0x17,0x97,0x40,0x99,0x26,0xd6,0xe2,0xa2,0x2b,0x5e,0xdf, + 0xbd,0x89,0xf2,0x1b,0x1a,0x53,0x2d,0xcc,0x50,0x41,0x7a,0xd0,0x3d,0x2a,0x0c,0x55,0x70,0x14,0x01,0xe9, + 0x58,0x49,0x10,0x7a,0x0b,0x93,0x82,0x8b,0xe1,0x1e,0xed,0x3a,0x80,0x10,0x82,0xce,0x96,0x8a,0x34,0xf0, + 0xcc,0xd7,0xd3,0xb9,0xb4,0x50,0x87,0x55,0x54,0x09,0xb8,0x9d,0x42,0x28,0x55,0x00,0xe5,0x8c,0x35,0x54, + 0xbf,0xdd,0x25,0x91,0x46,0xb7,0x0d,0xe5,0x5d,0x83,0xa8,0xe5,0x8b,0xfb,0x84,0xe4,0x3c,0xae,0x76,0xda, + 0xc4,0x43,0x2b,0x5b,0x74,0x0b,0xf8,0xbe,0x5d,0x68,0xf1,0x78,0x5b,0xb5,0xce,0x7d,0xf1,0x5d,0x99,0x40, + 0xda,0xca,0xee,0x38,0x81,0x50,0xbe,0x98,0xa1,0x6c,0xb8,0x24,0xad,0xf3,0xaf,0x8c,0x0f,0xd7,0x11,0x28, + 0x2c,0x84,0x18,0x4c,0x7d,0xb5,0xd9,0x8f,0x30,0xb5,0x1b,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xf0, + 0x30,0x82,0x01,0xec,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f, + 0x26,0x1b,0x28,0x98,0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06, + 0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xdd,0x80,0xd2,0x54,0x3d,0xf7,0x4c,0x70,0xca,0xa3,0xb0,0xdd, + 0x34,0x7a,0x32,0xe4,0xe8,0x3b,0x5a,0x3b,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04, + 0x03,0x02,0x05,0xa0,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d, + 0x06,0x03,0x55,0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06, + 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d, + 0x30,0x3b,0x06,0x0c,0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f, + 0x73,0x65,0x63,0x75,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50, + 0x53,0x30,0x7b,0x06,0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32, + 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e, + 0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61, + 0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74, + 0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65, + 0x30,0x63,0x30,0x3b,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e, + 0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f, + 0x6d,0x30,0x35,0x06,0x03,0x55,0x1d,0x11,0x04,0x2e,0x30,0x2c,0x82,0x12,0x61,0x64,0x64,0x6f,0x6e,0x73, + 0x2e,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x82,0x16,0x77,0x77,0x77,0x2e,0x61,0x64, + 0x64,0x6f,0x6e,0x73,0x2e,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x30,0x0d,0x06,0x09, + 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x33,0x3b,0x63,0x15, + 0xfc,0xb1,0xec,0x14,0x2c,0x93,0xdd,0x75,0x94,0xde,0x81,0x5a,0xd9,0x4e,0x99,0xbe,0xfb,0x4a,0xa4,0x39, + 0x55,0x4d,0xa1,0x40,0x7a,0xde,0x13,0x2a,0x87,0xa9,0x37,0xcf,0xe8,0xd5,0xfb,0xad,0xd1,0x7b,0x6d,0x6f, + 0x8c,0x20,0x87,0x82,0x54,0xe6,0x57,0x49,0xbc,0x20,0x28,0x84,0xcd,0xd6,0x01,0xd9,0x93,0x8b,0x17,0x6e, + 0x23,0x66,0xe5,0x84,0xc8,0x80,0x3f,0xc6,0xa1,0x70,0x80,0xe4,0xec,0x4d,0x1d,0xf9,0xfc,0x91,0x5a,0x73, + 0x62,0x29,0x9a,0xf7,0x20,0x1c,0x61,0xe0,0x8b,0x39,0x9f,0xca,0xbc,0x7e,0x8d,0xdd,0xbc,0xd9,0xb1,0xe3, + 0x9f,0x9e,0xdf,0x15,0x53,0x91,0x21,0x52,0x0b,0xd9,0x1a,0x23,0x0f,0x66,0x36,0xdb,0xac,0x93,0x96,0x4a, + 0xa3,0xa5,0x22,0xcf,0x29,0xf7,0xa2,0x99,0xa8,0xf6,0xb6,0xd9,0x40,0xae,0xd9,0x7e,0xb6,0xf6,0x58,0x2e, + 0x9b,0xac,0x36,0xca,0x64,0x8f,0x65,0x52,0xdc,0x86,0x9c,0x82,0xab,0x6e,0x50,0x4b,0xda,0x5f,0xfa,0x05, + 0x00,0x88,0x30,0x0e,0xde,0x8d,0x56,0xbf,0x81,0x47,0x8d,0x3d,0x06,0xe2,0xb2,0x62,0x92,0x67,0x8f,0x9e, + 0xc8,0x9a,0xb2,0xe5,0x06,0xb8,0x70,0x24,0xb8,0x77,0x7c,0x23,0x0a,0x38,0xc3,0x79,0x08,0xd8,0xb1,0x51, + 0x9d,0xac,0x95,0x11,0xc7,0x40,0x17,0x9e,0xa3,0x1c,0x8f,0xf2,0x11,0xa7,0x68,0x27,0xda,0x49,0x05,0x84, + 0x18,0x7c,0x58,0x2d,0x01,0x67,0x5c,0xe5,0x9f,0xa1,0x29,0xbb,0x4a,0x39,0x45,0x2f,0xbf,0x11,0xaa,0x79, + 0xa2,0xed,0xb4,0xd4,0xb5,0x65,0x43,0xb7,0x93,0x46,0x8a,0xd3 +}; +unsigned int addons_mozilla_org_cer_len = 1532; + +unsigned char login_live_com_cer[] = { + 0x30,0x82,0x05,0xec,0x30,0x82,0x04,0xd4,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xb0,0xb7,0x13,0x3e, + 0xd0,0x96,0xf9,0xb5,0x6f,0xae,0x91,0xc8,0x74,0xbd,0x3a,0xc0,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xde,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x17,0x30,0x15,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x6c,0x69,0x76,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x82, + 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01, + 0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xf3,0xfc,0x2b,0x2f,0xef,0xe1,0xad,0x59,0xf0, + 0x42,0x3c,0xc2,0xf1,0x82,0xbf,0x2c,0x41,0x93,0xd1,0xf6,0x98,0x33,0x95,0x4c,0xbc,0x62,0xf1,0x95,0x58, + 0x08,0xb6,0xe9,0x7b,0x77,0x48,0xb0,0xd3,0xdc,0x17,0x3f,0xbc,0x6e,0xe6,0xec,0x1e,0xec,0x8d,0x17,0xfe, + 0x1c,0x24,0xc6,0x3e,0x67,0x3d,0x92,0x95,0xa2,0x30,0xc0,0xa7,0x57,0x20,0xcf,0x70,0x88,0x97,0x4a,0x05, + 0x93,0x79,0x93,0x42,0x97,0x2f,0x3e,0xff,0xc4,0x14,0x14,0x28,0xa2,0x13,0x36,0xb4,0xf8,0xee,0xbe,0x1d, + 0xbc,0x78,0x5d,0x61,0x93,0x5f,0xeb,0x88,0xd7,0xd1,0xe4,0x2b,0x9a,0xcd,0x58,0xe2,0x07,0x45,0x9f,0x4f, + 0xb8,0xb9,0x40,0x6a,0x33,0x2c,0x5b,0x21,0x03,0x5a,0x4a,0x94,0xf2,0x7a,0x97,0x59,0x1b,0xa8,0xb5,0x42, + 0xd8,0x83,0x00,0xaa,0x34,0xcc,0xa7,0x76,0xd0,0x47,0x03,0x5f,0x05,0xaf,0x3b,0xe1,0xb9,0xa1,0x34,0x25, + 0xb7,0x6c,0x5f,0x9a,0x30,0x84,0x98,0xc2,0xc2,0xd7,0xf2,0xb8,0x42,0x4a,0x10,0x55,0xbd,0xfa,0x53,0x81, + 0x5d,0x8d,0x68,0x66,0x45,0x2c,0x52,0x7e,0xe5,0xc4,0x04,0xc3,0x54,0xe7,0xc3,0x39,0xda,0x7a,0x4a,0xc5, + 0xb9,0x98,0x82,0x20,0xe1,0x2c,0x60,0x57,0xbf,0xba,0xf2,0x46,0x00,0xbc,0x5f,0x3a,0xdc,0xe3,0x33,0x97, + 0xf8,0x4a,0x98,0xb9,0xec,0x33,0x4f,0x2d,0x60,0x6c,0x15,0x92,0xa6,0x81,0x4a,0x0b,0xe9,0xec,0x76,0x70, + 0x34,0x31,0x17,0x70,0xe6,0x70,0x4b,0x8e,0x8b,0xd3,0x75,0xcb,0x78,0x49,0xab,0x66,0x9b,0x86,0x9f,0x8f, + 0xa9,0xc4,0x01,0xe8,0xca,0x1b,0xe7,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xe8,0x30,0x82,0x01,0xe4, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0xd4,0x64,0xf6,0xa9,0xe8,0xa5,0x7e,0xd7,0xbf,0x63,0x52,0x03,0x83,0x53,0xdb,0xc5, + 0x41,0x8d,0xea,0x80,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x2d,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x26,0x30,0x24,0x82,0x0e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x6c,0x69,0x76,0x65, + 0x2e,0x63,0x6f,0x6d,0x82,0x12,0x77,0x77,0x77,0x2e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x6c,0x69,0x76,0x65, + 0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x54,0xe3,0xa4,0x9a,0x24,0xd2,0xf3,0x1d,0x42,0xad,0x1b,0xf0,0x1e,0xab,0xfb,0xda, + 0xd5,0xaa,0xe9,0xcf,0x5a,0xb3,0x1e,0x57,0x7b,0x31,0xf2,0x6e,0x57,0x4b,0x31,0xaf,0x33,0xbb,0xb6,0x0d, + 0x15,0xc7,0x5e,0x59,0x01,0xce,0x44,0xb5,0xb7,0xbf,0x09,0xc9,0xd5,0xdc,0x69,0x84,0xe9,0xc5,0x1a,0xb7, + 0xf0,0x3e,0xd4,0xc0,0x24,0xbd,0x29,0x5f,0xb4,0xe9,0xd6,0x58,0xeb,0x45,0x11,0x89,0x34,0x34,0xd3,0x11, + 0xeb,0x34,0xce,0x2a,0x4f,0x00,0x3d,0xf6,0x72,0xef,0x69,0x66,0xc0,0x9f,0x9a,0xac,0x7e,0x70,0x50,0xac, + 0x55,0x47,0xda,0xbe,0x43,0x5b,0xec,0x8b,0xc8,0xc5,0x23,0x84,0xc9,0x9f,0xb6,0x52,0x08,0xcf,0x91,0x1b, + 0x2f,0x80,0x69,0xe6,0x34,0x33,0xe6,0xb3,0x9f,0xa4,0xe5,0x0d,0x9a,0x15,0xf9,0x57,0xfc,0x0b,0xa9,0x41, + 0x0b,0xf5,0xff,0x58,0x41,0x92,0x22,0x27,0x66,0x12,0x06,0xc7,0x2a,0xd8,0x59,0xa7,0xc6,0xdf,0x44,0x12, + 0x4f,0xc0,0xa8,0x7f,0xa7,0x41,0xc8,0xc8,0x69,0xff,0xba,0x05,0x2e,0x97,0xad,0x3b,0xd0,0xeb,0xf3,0x15, + 0x6d,0x7e,0x1b,0xe5,0xba,0xdd,0x34,0xbe,0x22,0x11,0xec,0x68,0x98,0x33,0x81,0x02,0x6a,0x0b,0x13,0x55, + 0x79,0x31,0x75,0x4e,0x3a,0xc8,0xb6,0x13,0xbd,0x97,0x6f,0x37,0x0a,0x0b,0x2d,0x88,0x0e,0xde,0x67,0x90, + 0xc2,0xb3,0xca,0x20,0xca,0x9a,0x51,0xf4,0x64,0x3e,0xdb,0xf4,0x2e,0x45,0xf2,0xc7,0x47,0x17,0xa8,0xf4, + 0xfa,0x90,0x5a,0x7f,0x80,0xa6,0x82,0xac,0xe4,0x6c,0x81,0x46,0xbb,0x52,0x85,0x20,0x24,0xf8,0x80,0xea +}; +unsigned int login_live_com_cer_len = 1520; + +unsigned char login_skype_com_cer[] = { + 0x30,0x82,0x05,0xef,0x30,0x82,0x04,0xd7,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xe9,0x02,0x8b,0x95, + 0x78,0xe4,0x15,0xdc,0x1a,0x71,0x0a,0x2b,0x88,0x15,0x44,0x47,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x73,0x6b,0x79,0x70,0x65,0x2e,0x63,0x6f,0x6d,0x30, + 0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82, + 0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xb0,0x78,0x99,0x86,0x0e,0xa2,0x73,0x23, + 0xd4,0x5a,0xc3,0x49,0xeb,0xb1,0x36,0x8c,0x7c,0xca,0x84,0xae,0x3c,0xaf,0x38,0x88,0x28,0x99,0x8d,0x2d, + 0x58,0x13,0xb1,0x97,0x78,0x3e,0x52,0x20,0x67,0xac,0x5b,0x73,0x98,0x6c,0x32,0x55,0xc9,0x70,0xd1,0xd9, + 0xaa,0x15,0xe8,0x2e,0x26,0x85,0x81,0xbc,0x56,0xe4,0xbc,0x80,0x63,0xdb,0x4e,0xd7,0xf5,0x02,0xbe,0x51, + 0x63,0x1e,0x3c,0xdb,0xdf,0xd7,0x00,0x5d,0x5a,0xb9,0xe5,0x7b,0x6a,0xea,0x38,0x20,0xb2,0x3b,0xb6,0xee, + 0x75,0x54,0x84,0xf9,0xa6,0xca,0x38,0x70,0xdd,0xbf,0xb0,0xff,0xa5,0x85,0x5d,0xb4,0x41,0xfe,0xdd,0x3d, + 0xd9,0x2a,0xe1,0x30,0x43,0x1a,0x98,0x79,0x93,0xa0,0x5f,0xe0,0x67,0x6c,0x95,0xfa,0x3e,0x7a,0xae,0x71, + 0x7b,0xe3,0x6d,0x88,0x42,0x3f,0x25,0xd4,0xee,0xbe,0x68,0x68,0xac,0xad,0xac,0x60,0xe0,0x20,0xa3,0x39, + 0x83,0xb9,0x5b,0x28,0xa3,0x93,0x6d,0xa1,0xbd,0x76,0x0a,0xe3,0xeb,0xae,0x87,0x27,0x0e,0x54,0x8f,0xb4, + 0x48,0x0c,0x9a,0x54,0xf4,0x5d,0x8e,0x37,0x50,0xdc,0x5e,0xa4,0x8b,0x6b,0x4b,0xdc,0xa6,0xf3,0x34,0xbe, + 0x77,0x59,0x22,0x88,0xff,0x19,0x2b,0x6d,0x76,0x64,0x73,0xda,0x0c,0x87,0x07,0x2b,0x9a,0x37,0x3a,0xd0, + 0xe2,0x8c,0xf6,0x36,0x32,0x6b,0x9a,0x79,0xcc,0xd2,0x3b,0x93,0x6f,0x1a,0x4d,0x6c,0xe6,0xc1,0x9d,0x40, + 0xac,0x2d,0x74,0xc3,0xbe,0xea,0x5c,0x73,0x65,0x01,0x29,0xb1,0x2a,0xbf,0x70,0x59,0xc1,0xce,0xc6,0xc3, + 0xa2,0xc8,0x45,0x5f,0xba,0x67,0x3d,0x0f,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xea,0x30,0x82,0x01, + 0xe6,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28, + 0x98,0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x0e,0x04,0x16,0x04,0x14,0xd5,0x8e,0x5a,0x51,0x13,0xb4,0x29,0x0d,0x31,0xb6,0x1c,0x8d,0x3e,0x51,0x51, + 0x31,0x0a,0x33,0xaa,0x81,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05, + 0xa0,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55, + 0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06, + 0x0c,0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b, + 0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63, + 0x75,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b, + 0x06,0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d, + 0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77, + 0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a, + 0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e, + 0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e, + 0x63,0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30, + 0x3b,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x63,0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e, + 0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74, + 0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x2f, + 0x06,0x03,0x55,0x1d,0x11,0x04,0x28,0x30,0x26,0x82,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x73,0x6b,0x79, + 0x70,0x65,0x2e,0x63,0x6f,0x6d,0x82,0x13,0x77,0x77,0x77,0x2e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x73,0x6b, + 0x79,0x70,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05, + 0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x08,0xf2,0x81,0x75,0x91,0xbb,0xce,0x12,0x04,0x18,0xc2,0x4d,0x5a, + 0xfb,0x46,0x90,0x0a,0x54,0x44,0xf4,0xf2,0xdd,0x07,0x81,0xf0,0x1f,0xa6,0x7a,0x6f,0x9f,0xcf,0xb8,0x0e, + 0x2c,0x4f,0x9c,0xc4,0x9a,0xf5,0xa8,0xf6,0xba,0xa4,0xc9,0x7a,0x5d,0xb1,0xe2,0x5a,0xca,0x3c,0xfa,0x60, + 0xa8,0x68,0x3e,0xcb,0xba,0x2d,0xe2,0xcd,0xd6,0xb6,0xe4,0x92,0x3c,0x69,0xad,0x57,0xea,0xa8,0x2f,0x38, + 0x10,0x84,0x72,0xe5,0x68,0x71,0xed,0xbe,0xeb,0x6e,0x18,0xef,0x63,0x7a,0xbe,0xe7,0x24,0xff,0xc0,0x63, + 0xfd,0x58,0x3b,0x4c,0x81,0x92,0xd8,0x29,0xab,0x8e,0x35,0x5d,0xd7,0xd3,0x09,0x6b,0x85,0xd3,0xd5,0x73, + 0x05,0x44,0xe2,0xe5,0xbb,0x83,0x53,0x10,0xcb,0xf2,0xcf,0xb7,0x6e,0xe1,0x69,0xb7,0xa1,0x92,0x64,0xc5, + 0xcf,0xcd,0x82,0xbb,0x36,0xa0,0x38,0xad,0xd7,0x24,0xdf,0x53,0xfc,0x3f,0x62,0xb7,0xb7,0xd5,0xc7,0x57, + 0xe3,0x93,0x31,0x70,0x8e,0x24,0x89,0x86,0xca,0x63,0x2b,0x39,0xba,0x5d,0xd9,0x6a,0x60,0xec,0xa1,0x4e, + 0x8a,0xfe,0x53,0xf8,0x5e,0x92,0xdf,0x2f,0x5c,0x26,0x17,0x6d,0x03,0x7d,0x02,0x0f,0x0f,0xaa,0x43,0x67, + 0x6d,0xb0,0x62,0xbf,0x7e,0x53,0xdd,0xcc,0xec,0x78,0x73,0x95,0xe5,0xa5,0xf6,0x00,0xa3,0x04,0xfd,0x3f, + 0x04,0x2a,0xb3,0x98,0xc5,0xb7,0x03,0x1c,0xdb,0xc9,0x50,0xab,0xb0,0x05,0x1d,0x1e,0xbe,0x56,0xb4,0xcf, + 0x3e,0x42,0x13,0x94,0x9e,0xf9,0xe7,0x01,0x81,0xa5,0x78,0x6f,0x0c,0x7a,0x76,0xac,0x05,0x86,0xec,0xac, + 0xc2,0x11,0xac +}; +unsigned int login_skype_com_cer_len = 1523; + +unsigned char login_yahoo_com_1_cer[] = { + 0x30,0x82,0x05,0xd9,0x30,0x82,0x04,0xc1,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x39,0x2a,0x43,0x4f,0x0e, + 0x07,0xdf,0x1f,0x8a,0xa3,0x05,0xde,0x34,0xe0,0xc2,0x29,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74,0x79, + 0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54, + 0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55,0x04, + 0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54, + 0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65, + 0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31, + 0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05,0x33, + 0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72,0x69, + 0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73,0x68, + 0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c,0x61, + 0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f,0x67, + 0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54,0x65, + 0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f,0x48, + 0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20,0x43, + 0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b,0x13, + 0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04, + 0x03,0x13,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f,0x6f,0x2e,0x63,0x6f,0x6d,0x30,0x82, + 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01, + 0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa1,0xa4,0x05,0x3d,0xed,0x85,0x45,0x93,0x8a, + 0x18,0x4d,0xc6,0x03,0x00,0x57,0xe2,0x40,0x77,0xf0,0x1c,0xeb,0xd0,0x19,0xdf,0x22,0x5d,0x08,0x7f,0xd1, + 0x07,0x3c,0x41,0x89,0x46,0x17,0xa3,0x09,0xfa,0xfc,0xf8,0xa9,0x04,0xd1,0x96,0x8f,0xab,0xd7,0x4f,0x3c, + 0xf9,0xad,0x18,0xa9,0x74,0x81,0xc4,0x57,0x0a,0x3a,0x26,0x16,0xce,0x62,0x3e,0xbc,0x3f,0x6c,0x21,0xee, + 0x93,0x8d,0xcb,0x0d,0xa0,0x1f,0x9a,0x96,0xd0,0x8f,0xad,0xf5,0x93,0x93,0x82,0xee,0x72,0x0c,0xa1,0x75, + 0x15,0xa3,0x7b,0x84,0x56,0xb8,0xad,0xff,0x52,0x11,0x71,0x84,0xbc,0x3a,0x30,0x0b,0x7e,0x98,0xa8,0xe1, + 0xa8,0x3f,0x37,0x52,0xd0,0xf1,0x7c,0x6f,0x90,0xd8,0x45,0x0a,0xac,0x39,0x72,0x6a,0x61,0xd5,0xbb,0xc3, + 0x8c,0xf9,0xc2,0xcc,0xdf,0xfd,0x3a,0x71,0xb9,0xaf,0xbc,0xdc,0x3a,0xdc,0x0c,0xb6,0xb1,0xd2,0xd1,0x89, + 0xbb,0x41,0xb6,0xf2,0xde,0x57,0xd5,0x15,0xdf,0xfc,0xfd,0xe2,0x31,0xc5,0xdf,0xca,0xc1,0xd8,0x8f,0x2c, + 0xbf,0xf0,0x0e,0x5b,0x71,0xe0,0x34,0x71,0xc3,0xc5,0x4d,0x7d,0x7a,0xd4,0xfa,0xed,0x30,0x4b,0x2f,0xea, + 0xb6,0x2e,0x9e,0x93,0x3c,0xe2,0x3a,0xf8,0x42,0xa2,0x1a,0xee,0xdc,0xdf,0xcd,0x0f,0xa9,0xf6,0x79,0x84, + 0x1a,0x8e,0x6c,0x02,0xb6,0x86,0xe5,0xbf,0x51,0x6a,0x66,0xf8,0xf3,0x9c,0xd3,0x59,0x0c,0x7b,0xa5,0x99, + 0x78,0xcd,0x7c,0x99,0xfa,0xc6,0x96,0x47,0xd8,0x32,0xd4,0x74,0x76,0x0e,0x77,0x4b,0x20,0x74,0xa4,0xb7, + 0x89,0x75,0x92,0x4a,0xb4,0x5b,0x55,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xd5,0x30,0x82,0x01,0xd1, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0x86,0x49,0x45,0xfc,0x33,0x19,0x33,0xd4,0x04,0xed,0x27,0x61,0xee,0xe8,0x01,0xc9, + 0x0c,0x7f,0x2f,0x7e,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x1a,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x13,0x30,0x11,0x82,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f, + 0x6f,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x57,0x62,0xe1,0x77,0xeb,0xfc,0x1f,0xbf,0x88,0x53,0xaf,0x58,0xd3,0xd4,0xd6, + 0x6d,0x67,0x30,0x17,0x40,0xbe,0xe0,0x1f,0x64,0xde,0x87,0x15,0xcc,0xe0,0xa4,0x56,0xa9,0xd1,0x9f,0xf9, + 0x01,0xfe,0x02,0xb1,0xb1,0xea,0xe2,0x5f,0xee,0x71,0x16,0x31,0xf9,0x08,0xd5,0xc2,0xd7,0x9a,0x9b,0xb2, + 0x5a,0x38,0xd7,0xa9,0x7f,0xe9,0x87,0x6b,0x31,0xf9,0x0b,0xac,0xd9,0xfd,0x50,0x71,0xe0,0xdb,0x82,0x92, + 0x0f,0x81,0x9c,0x8d,0x77,0xe9,0xeb,0x2e,0xea,0xd4,0x23,0x41,0x87,0xec,0x2d,0xb2,0x78,0xb3,0x8e,0xb1, + 0x67,0xd2,0xee,0x71,0x03,0x08,0x12,0x99,0xb3,0x02,0x29,0x6f,0xde,0x8b,0xde,0xc1,0xa9,0x03,0x0a,0x5a, + 0x33,0x1c,0x3d,0x11,0x03,0xc6,0x48,0x0c,0x98,0x9c,0x15,0x2e,0xd9,0xa6,0x85,0x52,0xe7,0x05,0x8a,0xae, + 0x30,0x23,0xeb,0xed,0x28,0x6c,0x60,0xe9,0x2d,0x7f,0x8f,0x47,0x8b,0x2f,0xd0,0xdc,0xe6,0xbb,0x0f,0x7e, + 0x5f,0xf2,0x48,0x81,0x8e,0x50,0x04,0x63,0xb1,0x51,0x80,0x75,0x9a,0xa9,0xb6,0x10,0x1c,0x10,0x5f,0x6f, + 0x18,0x6f,0xe0,0x0e,0x96,0x45,0xce,0xee,0xf1,0xb5,0x20,0xdb,0xef,0xda,0x6e,0xc8,0x95,0xe3,0xf6,0x45, + 0xfd,0xca,0xfc,0xa5,0x5f,0x49,0x6d,0x06,0x1e,0xd2,0xde,0x61,0x3d,0x15,0x7d,0x37,0xe5,0x1c,0x35,0x8e, + 0x06,0xc2,0x6b,0xf7,0xb4,0xa8,0x28,0x2c,0x31,0xcb,0xaa,0xb4,0xa7,0x97,0x4f,0x9d,0x8a,0xf6,0xaf,0x7e, + 0x37,0xb9,0x7b,0x3d,0xdf,0x92,0x66,0x8b,0x8f,0x4e,0x9d,0xc6,0x36,0xe7,0x5c,0xa6,0xab,0x12,0x0f,0xd6, + 0xcf +}; +unsigned int login_yahoo_com_1_cer_len = 1501; + +unsigned char login_yahoo_com_2_cer[] = { + 0x30,0x82,0x05,0xd9,0x30,0x82,0x04,0xc1,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x3e,0x75,0xce,0xd4,0x6b, + 0x69,0x30,0x21,0x21,0x88,0x30,0xae,0x86,0xa8,0x2a,0x71,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74,0x79, + 0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54, + 0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55,0x04, + 0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54, + 0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65, + 0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31, + 0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05,0x33, + 0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72,0x69, + 0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73,0x68, + 0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c,0x61, + 0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f,0x67, + 0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54,0x65, + 0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f,0x48, + 0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20,0x43, + 0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b,0x13, + 0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04, + 0x03,0x13,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f,0x6f,0x2e,0x63,0x6f,0x6d,0x30,0x82, + 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01, + 0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa1,0xa4,0x05,0x3d,0xed,0x85,0x45,0x93,0x8a, + 0x18,0x4d,0xc6,0x03,0x00,0x57,0xe2,0x40,0x77,0xf0,0x1c,0xeb,0xd0,0x19,0xdf,0x22,0x5d,0x08,0x7f,0xd1, + 0x07,0x3c,0x41,0x89,0x46,0x17,0xa3,0x09,0xfa,0xfc,0xf8,0xa9,0x04,0xd1,0x96,0x8f,0xab,0xd7,0x4f,0x3c, + 0xf9,0xad,0x18,0xa9,0x74,0x81,0xc4,0x57,0x0a,0x3a,0x26,0x16,0xce,0x62,0x3e,0xbc,0x3f,0x6c,0x21,0xee, + 0x93,0x8d,0xcb,0x0d,0xa0,0x1f,0x9a,0x96,0xd0,0x8f,0xad,0xf5,0x93,0x93,0x82,0xee,0x72,0x0c,0xa1,0x75, + 0x15,0xa3,0x7b,0x84,0x56,0xb8,0xad,0xff,0x52,0x11,0x71,0x84,0xbc,0x3a,0x30,0x0b,0x7e,0x98,0xa8,0xe1, + 0xa8,0x3f,0x37,0x52,0xd0,0xf1,0x7c,0x6f,0x90,0xd8,0x45,0x0a,0xac,0x39,0x72,0x6a,0x61,0xd5,0xbb,0xc3, + 0x8c,0xf9,0xc2,0xcc,0xdf,0xfd,0x3a,0x71,0xb9,0xaf,0xbc,0xdc,0x3a,0xdc,0x0c,0xb6,0xb1,0xd2,0xd1,0x89, + 0xbb,0x41,0xb6,0xf2,0xde,0x57,0xd5,0x15,0xdf,0xfc,0xfd,0xe2,0x31,0xc5,0xdf,0xca,0xc1,0xd8,0x8f,0x2c, + 0xbf,0xf0,0x0e,0x5b,0x71,0xe0,0x34,0x71,0xc3,0xc5,0x4d,0x7d,0x7a,0xd4,0xfa,0xed,0x30,0x4b,0x2f,0xea, + 0xb6,0x2e,0x9e,0x93,0x3c,0xe2,0x3a,0xf8,0x42,0xa2,0x1a,0xee,0xdc,0xdf,0xcd,0x0f,0xa9,0xf6,0x79,0x84, + 0x1a,0x8e,0x6c,0x02,0xb6,0x86,0xe5,0xbf,0x51,0x6a,0x66,0xf8,0xf3,0x9c,0xd3,0x59,0x0c,0x7b,0xa5,0x99, + 0x78,0xcd,0x7c,0x99,0xfa,0xc6,0x96,0x47,0xd8,0x32,0xd4,0x74,0x76,0x0e,0x77,0x4b,0x20,0x74,0xa4,0xb7, + 0x89,0x75,0x92,0x4a,0xb4,0x5b,0x55,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xd5,0x30,0x82,0x01,0xd1, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0x86,0x49,0x45,0xfc,0x33,0x19,0x33,0xd4,0x04,0xed,0x27,0x61,0xee,0xe8,0x01,0xc9, + 0x0c,0x7f,0x2f,0x7e,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x1a,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x13,0x30,0x11,0x82,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f, + 0x6f,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x53,0x69,0x98,0x8e,0x28,0x4e,0x9c,0x2b,0x5b,0x1d,0xcc,0x6b,0x77,0x28,0x3d, + 0xbb,0xfa,0xa5,0x4e,0x7e,0x56,0x29,0xa4,0xea,0x10,0xe2,0xf4,0xe6,0x2d,0x06,0xd1,0x84,0xdb,0x23,0xce, + 0x97,0xf3,0x68,0xb6,0x0f,0x3a,0xde,0x15,0x0b,0x24,0x1d,0x91,0xe3,0x6c,0x2e,0x30,0xb7,0xe9,0x70,0xb0, + 0xc3,0x46,0x80,0xf0,0xd3,0xb1,0x51,0xbf,0x4f,0xd6,0x78,0xa0,0xfc,0xac,0xc6,0xcf,0x31,0x04,0x63,0xe2, + 0x34,0x55,0x05,0x4a,0x3d,0xf6,0x30,0xba,0xf3,0x33,0xe5,0xba,0xd2,0x96,0xf3,0xd5,0xb1,0xb6,0x93,0x89, + 0x1a,0xa4,0x68,0xbe,0x7e,0xed,0x63,0xb4,0x1a,0x48,0xc0,0x53,0xe4,0xa3,0xf0,0x39,0x0c,0x32,0x92,0xc7, + 0x43,0x0d,0x1a,0x71,0xed,0xd0,0x46,0x93,0xbf,0x93,0x62,0x6c,0x33,0x4b,0xcd,0x36,0x0d,0x69,0x5e,0xbb, + 0x6c,0x96,0x99,0x21,0x69,0xc4,0x4b,0x67,0x72,0xdb,0x6c,0x6a,0xb8,0xf7,0x68,0xed,0xc5,0x8f,0xad,0x63, + 0x65,0x95,0x0a,0x4c,0xe0,0xf9,0x0f,0x7e,0x37,0x3d,0xaa,0xd4,0x93,0xba,0x67,0x09,0xc3,0xa5,0xa4,0x0d, + 0x03,0x5a,0x6d,0xd5,0x0b,0xfe,0xf0,0x40,0x14,0xb4,0xf6,0xb8,0x69,0x7c,0x6d,0xc2,0x32,0x4b,0x9f,0xb5, + 0x1a,0xe7,0x46,0xae,0x4c,0x5a,0x2b,0xaa,0x7a,0x5e,0x90,0x57,0x95,0xfa,0xdb,0x66,0x02,0x20,0x1e,0x6a, + 0x69,0x66,0x15,0x9c,0xc2,0xb6,0xf5,0xbc,0x50,0xb5,0xfd,0x45,0xc7,0x1f,0x68,0xb4,0x47,0x59,0xac,0xc4, + 0x1b,0x28,0x93,0x4e,0x52,0x53,0x12,0x03,0x58,0x4b,0x71,0x83,0x9f,0x66,0xe6,0xac,0x79,0x48,0xfe,0xfe, + 0x47 +}; +unsigned int login_yahoo_com_2_cer_len = 1501; + +unsigned char login_yahoo_com_cer[] = { + 0x30,0x82,0x05,0xef,0x30,0x82,0x04,0xd7,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xd7,0x55,0x8f,0xda, + 0xf5,0xf1,0x10,0x5b,0xb2,0x13,0x28,0x2b,0x70,0x77,0x29,0xa3,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f,0x6f,0x2e,0x63,0x6f,0x6d,0x30, + 0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82, + 0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa1,0xa4,0x05,0x3d,0xed,0x85,0x45,0x93, + 0x8a,0x18,0x4d,0xc6,0x03,0x00,0x57,0xe2,0x40,0x77,0xf0,0x1c,0xeb,0xd0,0x19,0xdf,0x22,0x5d,0x08,0x7f, + 0xd1,0x07,0x3c,0x41,0x89,0x46,0x17,0xa3,0x09,0xfa,0xfc,0xf8,0xa9,0x04,0xd1,0x96,0x8f,0xab,0xd7,0x4f, + 0x3c,0xf9,0xad,0x18,0xa9,0x74,0x81,0xc4,0x57,0x0a,0x3a,0x26,0x16,0xce,0x62,0x3e,0xbc,0x3f,0x6c,0x21, + 0xee,0x93,0x8d,0xcb,0x0d,0xa0,0x1f,0x9a,0x96,0xd0,0x8f,0xad,0xf5,0x93,0x93,0x82,0xee,0x72,0x0c,0xa1, + 0x75,0x15,0xa3,0x7b,0x84,0x56,0xb8,0xad,0xff,0x52,0x11,0x71,0x84,0xbc,0x3a,0x30,0x0b,0x7e,0x98,0xa8, + 0xe1,0xa8,0x3f,0x37,0x52,0xd0,0xf1,0x7c,0x6f,0x90,0xd8,0x45,0x0a,0xac,0x39,0x72,0x6a,0x61,0xd5,0xbb, + 0xc3,0x8c,0xf9,0xc2,0xcc,0xdf,0xfd,0x3a,0x71,0xb9,0xaf,0xbc,0xdc,0x3a,0xdc,0x0c,0xb6,0xb1,0xd2,0xd1, + 0x89,0xbb,0x41,0xb6,0xf2,0xde,0x57,0xd5,0x15,0xdf,0xfc,0xfd,0xe2,0x31,0xc5,0xdf,0xca,0xc1,0xd8,0x8f, + 0x2c,0xbf,0xf0,0x0e,0x5b,0x71,0xe0,0x34,0x71,0xc3,0xc5,0x4d,0x7d,0x7a,0xd4,0xfa,0xed,0x30,0x4b,0x2f, + 0xea,0xb6,0x2e,0x9e,0x93,0x3c,0xe2,0x3a,0xf8,0x42,0xa2,0x1a,0xee,0xdc,0xdf,0xcd,0x0f,0xa9,0xf6,0x79, + 0x84,0x1a,0x8e,0x6c,0x02,0xb6,0x86,0xe5,0xbf,0x51,0x6a,0x66,0xf8,0xf3,0x9c,0xd3,0x59,0x0c,0x7b,0xa5, + 0x99,0x78,0xcd,0x7c,0x99,0xfa,0xc6,0x96,0x47,0xd8,0x32,0xd4,0x74,0x76,0x0e,0x77,0x4b,0x20,0x74,0xa4, + 0xb7,0x89,0x75,0x92,0x4a,0xb4,0x5b,0x55,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xea,0x30,0x82,0x01, + 0xe6,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28, + 0x98,0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x0e,0x04,0x16,0x04,0x14,0x86,0x49,0x45,0xfc,0x33,0x19,0x33,0xd4,0x04,0xed,0x27,0x61,0xee,0xe8,0x01, + 0xc9,0x0c,0x7f,0x2f,0x7e,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05, + 0xa0,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55, + 0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06, + 0x0c,0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b, + 0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63, + 0x75,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b, + 0x06,0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d, + 0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77, + 0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a, + 0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e, + 0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e, + 0x63,0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30, + 0x3b,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x63,0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e, + 0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74, + 0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x2f, + 0x06,0x03,0x55,0x1d,0x11,0x04,0x28,0x30,0x26,0x82,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68, + 0x6f,0x6f,0x2e,0x63,0x6f,0x6d,0x82,0x13,0x77,0x77,0x77,0x2e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61, + 0x68,0x6f,0x6f,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05, + 0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x3d,0x57,0xc9,0x48,0x24,0x5c,0xee,0x64,0x81,0xf5,0xae,0xbe,0x55, + 0x29,0x16,0xff,0x2a,0x2f,0x84,0xed,0xd9,0xf8,0xa3,0x03,0xc8,0x30,0x66,0xbb,0xc8,0xd4,0x81,0x2d,0x21, + 0xf7,0x08,0xf7,0xac,0x96,0x42,0x9a,0x41,0x75,0x7a,0xba,0x5d,0x10,0x23,0xcb,0x92,0x42,0x61,0xfa,0x8a, + 0xda,0x6d,0x65,0x34,0x19,0xe5,0xa9,0xd6,0x2d,0x13,0x78,0xd7,0x81,0x44,0x92,0xa9,0x6e,0x80,0x63,0x15, + 0xcb,0xfe,0x35,0x1f,0x02,0xd1,0x8a,0x14,0xb0,0xa8,0xcc,0x94,0x20,0x3b,0xa8,0x1a,0xf0,0x5d,0x36,0x50, + 0xdb,0x0d,0xae,0xe9,0x64,0xe4,0xf6,0x8d,0x69,0x7d,0x30,0xc8,0x14,0x17,0x00,0x4a,0xe5,0xa6,0x35,0xfb, + 0x7d,0x0d,0x22,0x9d,0x79,0x76,0x52,0x2c,0xbc,0x97,0x06,0x88,0x9a,0x15,0xf4,0x73,0xe6,0xf1,0xf5,0x98, + 0xa5,0xcd,0x07,0x44,0x91,0xb8,0xa7,0x68,0x67,0x45,0xd2,0x72,0x11,0x60,0xe2,0x71,0xb7,0x50,0x55,0xe2, + 0x8a,0xa9,0x0d,0xd6,0x92,0xee,0x04,0x2a,0x8b,0x30,0xa0,0xa2,0x05,0x46,0x34,0x6d,0x92,0xc6,0x3b,0xaa, + 0x4d,0xa0,0xd0,0xab,0x01,0x19,0x0a,0x32,0xb7,0xe8,0xe3,0xcf,0xf1,0xd2,0x97,0x49,0x7b,0xac,0xa4,0x97, + 0xf7,0xf0,0x57,0xae,0x63,0x77,0x9a,0x7f,0x96,0xda,0x4d,0xfd,0xbe,0xdc,0x07,0x36,0xe3,0x25,0xbd,0x89, + 0x79,0x8e,0x29,0x12,0x13,0x8b,0x88,0x07,0xfb,0x6b,0xdb,0xa4,0xcd,0xb3,0x2d,0x27,0xe9,0xd4,0xca,0x60, + 0xd7,0x85,0x53,0xfb,0x74,0xc6,0x5c,0x35,0x8c,0x70,0x1f,0xf9,0xb2,0xb7,0x92,0x27,0x20,0xc7,0x94,0xd5, + 0x67,0x14,0x30 +}; +unsigned int login_yahoo_com_cer_len = 1523; + +unsigned char mail_google_com_cer[] = { + 0x30,0x82,0x05,0xee,0x30,0x82,0x04,0xd6,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x04,0x7e,0xcb,0xe9,0xfc, + 0xa5,0x5f,0x7b,0xd0,0x9e,0xae,0x36,0xe1,0x0c,0xae,0x1e,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74,0x79, + 0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54, + 0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55,0x04, + 0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54, + 0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65, + 0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31, + 0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05,0x33, + 0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72,0x69, + 0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73,0x68, + 0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c,0x61, + 0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f,0x67, + 0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54,0x65, + 0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f,0x48, + 0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20,0x43, + 0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b,0x13, + 0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04, + 0x03,0x13,0x0f,0x6d,0x61,0x69,0x6c,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x82, + 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01, + 0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xb0,0x73,0xf0,0xf2,0x04,0xee,0xc2,0xa2,0x46, + 0xca,0x34,0x2a,0xaa,0xbb,0x60,0x23,0xd1,0x11,0x76,0x1f,0x1f,0x3a,0xd0,0x65,0x83,0x4e,0x9a,0x45,0xa8, + 0x43,0x70,0x85,0x76,0xf0,0x1f,0x87,0x00,0x02,0x1f,0x6e,0x3b,0x17,0x17,0xc4,0xb5,0xe9,0x19,0x46,0xa2, + 0x92,0x25,0x8d,0x62,0x2a,0xb4,0x63,0x30,0x1f,0xb9,0x85,0xf8,0x35,0xe1,0x16,0x5a,0x76,0x49,0xcc,0x50, + 0x48,0x53,0x39,0x59,0x89,0xd6,0x84,0x02,0xfb,0x9a,0xec,0x1b,0xc7,0x51,0xd5,0x76,0x95,0x90,0xd4,0x3a, + 0x2a,0xb8,0xa6,0xde,0x02,0x4d,0x06,0xfb,0xcd,0xed,0xa5,0x46,0x41,0x5f,0x55,0x74,0xe5,0xec,0x7e,0x40, + 0xdc,0x50,0x9c,0xb5,0xe4,0x35,0x5d,0x1e,0x68,0x20,0xf8,0xe9,0xde,0xa3,0x6a,0x28,0xbf,0x41,0xd2,0xa1, + 0xb3,0xe2,0x25,0x8d,0x0c,0x1b,0xca,0x3d,0x93,0x0c,0x18,0xae,0xdf,0xc5,0xbc,0xfd,0xbc,0x82,0xba,0x68, + 0x00,0xd7,0x16,0x32,0x71,0x9f,0x65,0xb5,0x11,0xda,0x68,0x59,0xd0,0xa6,0x57,0x64,0x1b,0xc9,0xfe,0x98, + 0xe5,0xf5,0xa5,0x65,0xea,0xe1,0xdb,0xee,0xf4,0xb3,0x9d,0xb3,0x8e,0xea,0x87,0xae,0x16,0xd2,0x1e,0xa0, + 0x7c,0x7c,0x69,0x3f,0x29,0x16,0x85,0x01,0x53,0xa7,0x6c,0xf1,0x60,0xab,0xdd,0xa2,0xfc,0x25,0x47,0xd4, + 0x32,0xd1,0x12,0xdd,0xf7,0x48,0x12,0xe0,0xfc,0x9c,0xa2,0x77,0x98,0xe9,0x89,0x99,0xb8,0xf8,0x38,0xf1, + 0x8c,0x06,0xc2,0x7a,0x23,0x36,0x6d,0x9b,0x9d,0xcd,0x30,0xc8,0xc7,0x34,0x17,0x1e,0xbb,0x7d,0x42,0xc8, + 0xab,0xe7,0x15,0x16,0xf6,0x73,0xb5,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xea,0x30,0x82,0x01,0xe6, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0x18,0x2a,0xa2,0xc8,0xd4,0x7a,0x3f,0x7b,0xad,0x04,0x8b,0xbd,0x6f,0x9e,0x10,0x46, + 0x13,0x78,0x71,0x9d,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x2f,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x28,0x30,0x26,0x82,0x0f,0x6d,0x61,0x69,0x6c,0x2e,0x67,0x6f,0x6f,0x67,0x6c, + 0x65,0x2e,0x63,0x6f,0x6d,0x82,0x13,0x77,0x77,0x77,0x2e,0x6d,0x61,0x69,0x6c,0x2e,0x67,0x6f,0x6f,0x67, + 0x6c,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05, + 0x00,0x03,0x82,0x01,0x01,0x00,0x67,0x06,0x08,0x0a,0x27,0xc5,0x93,0x6e,0x02,0xf2,0xde,0x17,0x3f,0xd0, + 0xd3,0x1b,0x7c,0xff,0xb5,0xcd,0x7a,0xc7,0x77,0xc7,0xbe,0xdf,0x12,0xca,0x19,0xde,0xb0,0x13,0x57,0x0c, + 0x03,0x91,0xc4,0x79,0x52,0xcf,0x7f,0xb7,0x5e,0x55,0x20,0x84,0x49,0xdd,0xf5,0xd0,0x29,0x2f,0x0e,0x04, + 0xda,0x59,0x9e,0x0e,0x13,0x9f,0xf4,0xc0,0x32,0x9b,0xff,0xa1,0x11,0x24,0x2a,0x97,0xa3,0xf2,0x3f,0x3d, + 0x2a,0x6b,0xa8,0xad,0x8c,0x19,0x75,0x95,0x0e,0x1d,0x25,0xfd,0x4f,0xc4,0x7a,0x15,0xc3,0x1d,0xc7,0x13, + 0x40,0xc8,0x0d,0xbe,0x97,0x60,0x72,0xa6,0xfe,0x25,0xbe,0x8f,0xec,0xd5,0xa6,0x86,0xc3,0x21,0x5c,0x59, + 0x52,0xd9,0x6a,0x0b,0x5c,0x9f,0x4b,0xde,0xb5,0xf9,0xec,0xe2,0xf4,0xc5,0xcc,0x62,0x53,0x76,0x89,0x65, + 0xe4,0x29,0xda,0xb7,0xbf,0x96,0xe0,0x60,0x8d,0x0d,0xb7,0x09,0x55,0xd6,0x40,0x55,0x1d,0xc1,0xf2,0x96, + 0x21,0x75,0xaf,0x89,0x86,0x1f,0x5d,0x81,0x97,0x29,0x28,0x1e,0x29,0xd7,0x96,0xc1,0x20,0x03,0x32,0x7b, + 0x00,0x3b,0x6a,0x37,0x17,0x5a,0xa3,0xb3,0x1a,0x6f,0x32,0x3b,0x6e,0xf1,0xa3,0x5d,0xab,0xab,0xcc,0x2a, + 0xcb,0x30,0x0c,0x1f,0x35,0x23,0x8b,0x69,0x44,0x5c,0xea,0xac,0x28,0x60,0xed,0xab,0x6b,0x63,0x9e,0xf6, + 0x92,0xbc,0xbd,0x9a,0x5a,0x26,0x4c,0xc5,0x98,0xb8,0x0e,0x19,0x3e,0xfc,0x05,0x31,0xe3,0x16,0xd9,0xfd, + 0x90,0x05,0x03,0x86,0xc6,0x57,0x01,0x1f,0x7f,0x78,0xa0,0xcf,0x33,0x6a,0xaa,0x66,0x6b,0x22,0xd0,0xa7, + 0x49,0x23 +}; +unsigned int mail_google_com_cer_len = 1522; + +unsigned char www_google_com_cer[] = { + 0x30,0x82,0x05,0xe4,0x30,0x82,0x04,0xcc,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xf5,0xc8,0x6a,0xf3, + 0x61,0x62,0xf1,0x3a,0x64,0xf5,0x4f,0x6d,0xc9,0x58,0x7c,0x06,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xde,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x17,0x30,0x15,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0e,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x82, + 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01, + 0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xb0,0x73,0xf0,0xf2,0x04,0xee,0xc2,0xa2,0x46, + 0xca,0x34,0x2a,0xaa,0xbb,0x60,0x23,0xd1,0x11,0x76,0x1f,0x1f,0x3a,0xd0,0x65,0x83,0x4e,0x9a,0x45,0xa8, + 0x43,0x70,0x85,0x76,0xf0,0x1f,0x87,0x00,0x02,0x1f,0x6e,0x3b,0x17,0x17,0xc4,0xb5,0xe9,0x19,0x46,0xa2, + 0x92,0x25,0x8d,0x62,0x2a,0xb4,0x63,0x30,0x1f,0xb9,0x85,0xf8,0x35,0xe1,0x16,0x5a,0x76,0x49,0xcc,0x50, + 0x48,0x53,0x39,0x59,0x89,0xd6,0x84,0x02,0xfb,0x9a,0xec,0x1b,0xc7,0x51,0xd5,0x76,0x95,0x90,0xd4,0x3a, + 0x2a,0xb8,0xa6,0xde,0x02,0x4d,0x06,0xfb,0xcd,0xed,0xa5,0x46,0x41,0x5f,0x55,0x74,0xe5,0xec,0x7e,0x40, + 0xdc,0x50,0x9c,0xb5,0xe4,0x35,0x5d,0x1e,0x68,0x20,0xf8,0xe9,0xde,0xa3,0x6a,0x28,0xbf,0x41,0xd2,0xa1, + 0xb3,0xe2,0x25,0x8d,0x0c,0x1b,0xca,0x3d,0x93,0x0c,0x18,0xae,0xdf,0xc5,0xbc,0xfd,0xbc,0x82,0xba,0x68, + 0x00,0xd7,0x16,0x32,0x71,0x9f,0x65,0xb5,0x11,0xda,0x68,0x59,0xd0,0xa6,0x57,0x64,0x1b,0xc9,0xfe,0x98, + 0xe5,0xf5,0xa5,0x65,0xea,0xe1,0xdb,0xee,0xf4,0xb3,0x9d,0xb3,0x8e,0xea,0x87,0xae,0x16,0xd2,0x1e,0xa0, + 0x7c,0x7c,0x69,0x3f,0x29,0x16,0x85,0x01,0x53,0xa7,0x6c,0xf1,0x60,0xab,0xdd,0xa2,0xfc,0x25,0x47,0xd4, + 0x32,0xd1,0x12,0xdd,0xf7,0x48,0x12,0xe0,0xfc,0x9c,0xa2,0x77,0x98,0xe9,0x89,0x99,0xb8,0xf8,0x38,0xf1, + 0x8c,0x06,0xc2,0x7a,0x23,0x36,0x6d,0x9b,0x9d,0xcd,0x30,0xc8,0xc7,0x34,0x17,0x1e,0xbb,0x7d,0x42,0xc8, + 0xab,0xe7,0x15,0x16,0xf6,0x73,0xb5,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xe0,0x30,0x82,0x01,0xdc, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0x18,0x2a,0xa2,0xc8,0xd4,0x7a,0x3f,0x7b,0xad,0x04,0x8b,0xbd,0x6f,0x9e,0x10,0x46, + 0x13,0x78,0x71,0x9d,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x25,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x1e,0x30,0x1c,0x82,0x0e,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65, + 0x2e,0x63,0x6f,0x6d,0x82,0x0a,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09, + 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x71,0xc0,0x99,0x3f, + 0x5e,0xf6,0xbd,0x33,0xff,0x9e,0x16,0xcb,0xa8,0xbf,0xdd,0x70,0xf9,0xd2,0x53,0x3b,0x36,0xae,0xc9,0x17, + 0xc8,0xae,0x5e,0x4d,0xdd,0x62,0xf7,0xb7,0xd3,0x3e,0x77,0xa3,0xfe,0xc0,0x7b,0x32,0xb5,0xc9,0x94,0x05, + 0x52,0x50,0xf2,0x5f,0x3d,0x79,0x84,0x49,0x4f,0x5d,0x6c,0xb0,0xd7,0x59,0xbd,0xd4,0x6c,0x88,0xfa,0xfc, + 0xc5,0x65,0x86,0xeb,0x28,0x52,0xa2,0x42,0xf6,0x7c,0xbc,0x6a,0xc7,0x07,0x2e,0x25,0xd1,0x90,0x62,0x20, + 0xc6,0x8d,0x51,0xc2,0x2c,0x45,0x39,0x4e,0x03,0xda,0xf7,0x18,0xe8,0xcc,0x0a,0x3a,0xd9,0x45,0xd8,0x6c, + 0x6e,0x34,0x8b,0x62,0x9c,0x4e,0x15,0xf9,0x43,0xee,0xe5,0x97,0xc0,0x3f,0xad,0x35,0x13,0xc5,0x2b,0x06, + 0xc7,0x41,0xfd,0xe2,0xf7,0x7e,0x45,0xad,0x9b,0xd1,0xe1,0x66,0xed,0xf8,0x7a,0x4b,0x94,0x39,0x7a,0x2f, + 0xeb,0xe8,0x3f,0x43,0xd8,0x35,0xd6,0x56,0xfa,0x74,0xe7,0x6d,0xe6,0xed,0xac,0x65,0x84,0xfe,0xd0,0x4d, + 0x06,0x12,0xde,0xda,0x59,0x00,0x3c,0x09,0x5c,0xcf,0x88,0x4b,0xe8,0x3d,0xb4,0x15,0x21,0x92,0xcc,0x6d, + 0xa6,0x51,0xe2,0x8e,0x97,0xf1,0xf4,0x82,0x46,0xcb,0xc4,0x53,0x5e,0xda,0x5c,0x9d,0x65,0x92,0x01,0x65, + 0x89,0x00,0xe5,0xb6,0x99,0xff,0x26,0x40,0xf1,0x2f,0x19,0x31,0x08,0x1a,0xb1,0x67,0x55,0x86,0x0d,0xae, + 0x35,0x33,0x86,0xbc,0x97,0x48,0x92,0xd7,0x96,0x60,0xf8,0xce,0xfc,0x96,0xeb,0x87,0xc4,0x73,0xcc,0x94, + 0x9b,0x58,0x5b,0xf3,0x7a,0xa4,0x27,0x13,0xd6,0x4f,0xf4,0x69 +}; +unsigned int www_google_com_cer_len = 1512; + +/* subject:/CN=Leaf revoked ok1/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=CA revoked/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char leaf_subCANotOnAllowlist_Cert[] = { + 0x30,0x82,0x04,0x41,0x30,0x82,0x03,0x29,0xA0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0xFA,0x6B,0x46,0x67,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x30,0x7C,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x0C,0x0A, + 0x43,0x41,0x20,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x31,0x22,0x30,0x20,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65, + 0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x20,0x17,0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30, + 0x37,0x5A,0x18,0x0F,0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30, + 0x30,0x37,0x5A,0x30,0x81,0x82,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x10,0x4C,0x65,0x61,0x66,0x20,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x20,0x6F,0x6B, + 0x31,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69, + 0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43, + 0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03, + 0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00, + 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC0,0x08,0xBA,0xCA,0x52,0x4C,0x3F, + 0xD7,0x80,0x14,0x2A,0x58,0xD7,0x3B,0xC2,0xB3,0x30,0xF5,0xA9,0x91,0xCA,0x28,0xE0, + 0xA3,0xF3,0x4B,0xB3,0x5F,0x10,0xBF,0x15,0x48,0xB0,0xE2,0xD7,0x60,0x57,0xC6,0xEA, + 0x9D,0x08,0x57,0xF7,0x1F,0x54,0x63,0xEB,0x8F,0x33,0x9D,0xD1,0xB0,0xFE,0x5D,0x28, + 0x99,0xA4,0xCC,0xBB,0xF3,0x07,0x3D,0xED,0xC3,0x07,0x4A,0x0B,0x92,0x66,0xA1,0x06, + 0xAC,0xA6,0x89,0xCC,0xCD,0x48,0xC5,0x34,0x54,0xB0,0x68,0x9D,0x50,0xAC,0xC6,0x3A, + 0x6C,0x5E,0xC7,0x4C,0x11,0xC5,0x43,0x4A,0x59,0xB4,0x74,0xE5,0xC3,0x5D,0xA7,0xB8, + 0x4C,0x55,0x6D,0x84,0x66,0x63,0xEE,0xAA,0xDC,0xF0,0x4B,0x7B,0x90,0xCE,0xA2,0x8D, + 0x5A,0x58,0x7B,0xC0,0x12,0xF6,0xA5,0x4F,0x79,0xAD,0x06,0x22,0xDA,0xA0,0xE7,0xD5, + 0xBE,0x2E,0x46,0xF2,0x4C,0x6B,0x1E,0x0A,0xED,0xF9,0x5E,0xBB,0x73,0x6F,0x8B,0xE6, + 0xAC,0xDB,0x18,0x2B,0x01,0xFB,0x58,0x7A,0xB2,0x9B,0x52,0x0D,0x41,0xCA,0xD4,0x18, + 0x0C,0x84,0x42,0xE8,0x70,0x12,0x99,0xC8,0x95,0xF3,0x19,0x0C,0xF0,0x75,0xB3,0x49, + 0xFC,0x9A,0x7A,0x58,0xE9,0xD1,0xFB,0xCD,0x39,0x3B,0x27,0x58,0xED,0x14,0xF9,0x47, + 0x1F,0xCE,0x31,0x2D,0x5B,0xA1,0x1E,0x2A,0x78,0x83,0x5F,0x18,0x55,0x66,0xAE,0xAA, + 0x47,0x50,0xB2,0x42,0x7C,0x6D,0xA6,0x63,0x75,0x32,0x32,0x3E,0xBD,0xA3,0x2F,0x7D, + 0xE8,0x69,0xD1,0x61,0xD9,0x02,0x86,0x60,0xBF,0xC7,0x5E,0x0B,0xDE,0x87,0x9D,0x18, + 0xAF,0x42,0x37,0x98,0x2F,0x56,0x19,0xB7,0xF1,0x02,0x03,0x01,0x00,0x01,0xA3,0x81, + 0xC0,0x30,0x81,0xBD,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, + 0x03,0x02,0x07,0x80,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02, + 0x30,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xF8, + 0xA6,0xB9,0x3E,0xE8,0xBA,0x5A,0xED,0x7C,0x5C,0x96,0x07,0xFE,0x75,0x0C,0x79,0xE8, + 0xBF,0xB6,0x12,0x30,0x41,0x06,0x03,0x55,0x1D,0x1F,0x04,0x3A,0x30,0x38,0x30,0x36, + 0xA0,0x34,0xA0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61,0x6C, + 0x69,0x64,0x74,0x65,0x73,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65,0x6F, + 0x66,0x66,0x6B,0x2E,0x6E,0x65,0x74,0x2F,0x76,0x32,0x2D,0x72,0x65,0x76,0x6F,0x6B, + 0x65,0x64,0x2E,0x63,0x72,0x6C,0x30,0x39,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x01,0x01,0x04,0x2D,0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x30,0x01,0x86,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6B,0x6E,0x6F,0x77,0x6E, + 0x2D,0x61,0x6E,0x73,0x77,0x65,0x72,0x2D,0x6F,0x63,0x73,0x70,0x2F,0x6F,0x63,0x73, + 0x70,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x90,0x28,0xA2,0xBF,0x5B,0x3F,0x46,0xFB,0xF1,0x6D,0xDF, + 0x7B,0xED,0x92,0x2C,0xCA,0xB3,0x38,0xF9,0xE3,0x7F,0xA6,0xD6,0xBA,0x22,0x5A,0x06, + 0x27,0x21,0xBA,0xC6,0x1C,0xDA,0x64,0x3B,0xB8,0x70,0x89,0x06,0xF8,0x04,0x8F,0x69, + 0xC2,0x69,0x46,0xF5,0x22,0x8A,0x91,0xE3,0x77,0x21,0x46,0xF7,0x8E,0xDF,0xDE,0x46, + 0xD4,0x19,0x62,0xDC,0xC7,0x02,0x9E,0xE6,0x31,0x0A,0x13,0xA1,0x54,0x3B,0xE6,0x5C, + 0x17,0x3F,0xAB,0xDC,0x29,0x0F,0x93,0x74,0xC0,0xD9,0xA3,0xD4,0x76,0xA2,0x1D,0x7E, + 0x79,0xDF,0x8D,0xFC,0xAE,0x11,0xBD,0x83,0x95,0x12,0x70,0xA3,0xE9,0x39,0xCF,0x06, + 0x49,0x93,0xD8,0x05,0x53,0x07,0xB9,0xCF,0xD9,0x8E,0x1D,0xA2,0xBB,0x79,0x54,0x94, + 0xF8,0x9D,0xB4,0x38,0xE6,0x98,0x65,0x3C,0xD0,0x7E,0x16,0x8F,0x11,0x84,0x76,0xA4, + 0x4A,0x55,0xC3,0x09,0xED,0x68,0xA8,0x62,0xD1,0x97,0x51,0x8C,0x64,0x33,0xFD,0xFA, + 0x3F,0xD7,0xA5,0x3B,0xD1,0x0B,0xC0,0xCF,0x34,0x77,0x66,0x9F,0x15,0x0D,0xB0,0x0C, + 0x8C,0x5F,0x57,0x72,0xFC,0xB9,0xB6,0x5A,0x34,0xF3,0xC4,0x78,0x5D,0x9F,0xAC,0xD1, + 0x99,0x6D,0x98,0xBE,0x80,0x68,0x1F,0xAA,0xF6,0xEE,0x3C,0x1D,0x8B,0xBF,0x59,0x2A, + 0xC5,0x67,0xAA,0x52,0x9A,0xFD,0x8A,0x14,0x65,0x3C,0x71,0xB8,0xE9,0x0E,0xAF,0x20, + 0x6A,0x42,0x90,0x22,0xCB,0xE5,0x79,0x99,0xAC,0x91,0xAE,0x63,0x1A,0xDB,0x4E,0xD9, + 0xCC,0x2A,0x52,0xD4,0x02,0x51,0x42,0xAF,0x27,0x0C,0xA8,0x41,0xFE,0x33,0xBC,0xF5, + 0x91,0x7E,0x15,0x6A,0x5A, +}; + +/* subject:/CN=CA revoked/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=Valid Test CA Root V2/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char subCANotOnAllowlist_Cert[] = { + 0x30,0x82,0x04,0x2C,0x30,0x82,0x03,0x14,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x3E, + 0x1D,0x6A,0x98,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, + 0x05,0x00,0x30,0x81,0x87,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15, + 0x56,0x61,0x6C,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x20,0x52,0x6F, + 0x6F,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19, + 0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65, + 0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, + 0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x20,0x17,0x0D, + 0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30,0x36,0x5A,0x18,0x0F,0x32, + 0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30,0x30,0x36,0x5A,0x30,0x7C, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x0C,0x0A,0x43,0x41,0x20,0x72,0x65, + 0x76,0x6F,0x6B,0x65,0x64,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19, + 0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65, + 0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, + 0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03, + 0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xCA,0x23,0x02, + 0x7B,0x12,0x84,0x9C,0x8D,0x0E,0x43,0x70,0xD8,0xAB,0x93,0x8D,0x20,0xB0,0xF0,0xC0, + 0xDA,0xE6,0xFB,0xBD,0x96,0x26,0x1A,0x5B,0x74,0x24,0x21,0x97,0x90,0xFF,0x7F,0x75, + 0xF6,0x47,0x3C,0x7C,0x79,0xD9,0x0A,0x9A,0xA3,0x84,0x1C,0x3A,0x3E,0x63,0xC0,0xA7, + 0x3C,0x0A,0xB6,0xD1,0x16,0x8D,0x3E,0x5F,0xEF,0x97,0x11,0x91,0x18,0x19,0x42,0xA7, + 0xC5,0xCA,0x81,0xB2,0xD7,0xE4,0x8F,0x18,0x65,0xAC,0x42,0xB1,0xE1,0x43,0x1D,0x46, + 0xF0,0x80,0x45,0xFC,0x10,0xE5,0x7B,0xE1,0x7C,0xF7,0x49,0xC1,0x8D,0x8F,0xF2,0x2D, + 0xE6,0x28,0x51,0x45,0xA8,0xBB,0x83,0x5B,0xAD,0xB8,0x95,0xBF,0x92,0xD2,0xF8,0x9A, + 0xB3,0x31,0x50,0x58,0x4A,0xBA,0xA5,0xC7,0x3F,0x54,0xCC,0x3A,0xE0,0x58,0xCA,0xA2, + 0x3D,0x76,0x41,0xE5,0x5A,0x6F,0x7D,0xD6,0xD0,0x74,0xBC,0xE5,0x99,0xCD,0xBD,0x11, + 0x1C,0x28,0x24,0x96,0xDE,0x63,0x3B,0xDC,0xF8,0xE9,0x22,0x9E,0xCD,0x3D,0x82,0xE7, + 0x3C,0x5A,0x03,0xFA,0xE6,0x01,0x7B,0xA4,0xB6,0x4D,0x37,0xCE,0x18,0x2C,0xF1,0xFA, + 0xE1,0xB8,0x86,0x45,0x1E,0xAA,0x61,0xD2,0x89,0xF2,0x43,0x8E,0x8D,0x70,0x64,0x3F, + 0x1A,0x45,0x7C,0x9C,0xA6,0x1B,0x75,0xB6,0x44,0x81,0x0A,0xBA,0x90,0x00,0x54,0xDB, + 0x62,0xE1,0xC5,0x4B,0x2E,0x0D,0x49,0x9F,0xDC,0x4E,0xCF,0xE1,0xB1,0xC1,0xDD,0x88, + 0xA1,0xBA,0x8F,0x96,0x13,0xAB,0x14,0x6C,0xF7,0x2E,0xE4,0x46,0x49,0xE1,0x07,0xFF, + 0xA1,0xBC,0x85,0x3C,0x56,0x83,0x40,0x32,0xE4,0x4B,0xC6,0x80,0x43,0x02,0x03,0x01, + 0x00,0x01,0xA3,0x81,0xA7,0x30,0x81,0xA4,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, + 0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01, + 0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xF8,0xA6,0xB9,0x3E,0xE8,0xBA,0x5A,0xED,0x7C, + 0x5C,0x96,0x07,0xFE,0x75,0x0C,0x79,0xE8,0xBF,0xB6,0x12,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xBA,0x56,0xD8,0x57,0x66,0xBD,0xFC,0x5B, + 0xE2,0x10,0xF2,0x39,0xB3,0xAF,0xB2,0x72,0xED,0x55,0x0F,0x1C,0x30,0x3E,0x06,0x03, + 0x55,0x1D,0x1F,0x04,0x37,0x30,0x35,0x30,0x33,0xA0,0x31,0xA0,0x2F,0x86,0x2D,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61,0x6C,0x69,0x64,0x74,0x65,0x73,0x74,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65,0x6F,0x66,0x66,0x6B,0x2E,0x6E,0x65,0x74, + 0x2F,0x76,0x32,0x2D,0x72,0x6F,0x6F,0x74,0x2E,0x63,0x72,0x6C,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00, + 0xBF,0xC5,0x46,0x37,0x47,0x5A,0x47,0xE9,0x14,0xB8,0xDC,0x68,0x1C,0xF1,0xAA,0x2E, + 0x5B,0x2B,0xF0,0xEE,0x7A,0x7D,0xF2,0x6B,0x44,0x77,0x57,0x56,0x58,0xEB,0xFC,0x9A, + 0x19,0x9B,0xDF,0xE7,0x58,0x98,0xF0,0x5C,0xC7,0x3A,0x22,0x85,0x84,0x46,0xFB,0x71, + 0x09,0x2F,0xFC,0x22,0x51,0x49,0xF6,0x28,0xEF,0xC5,0xB6,0x5C,0x71,0xFC,0x61,0x12, + 0xC1,0xA3,0xE1,0xD4,0x77,0x71,0xCC,0xDF,0x12,0x85,0xB4,0x7D,0x43,0xCF,0x7D,0x2A, + 0x4F,0xF1,0x3A,0x09,0x6E,0xE4,0xC4,0xD5,0xB6,0x8D,0xC7,0x03,0xEB,0x07,0xBC,0x1C, + 0x0A,0xB4,0x17,0x3E,0xBF,0xC7,0x3E,0xE7,0x9F,0x98,0x51,0xC1,0xA4,0x69,0x09,0x58, + 0x88,0xD9,0xA4,0xAE,0xB2,0xE7,0x53,0x5F,0xCA,0x8E,0xE9,0x1B,0x84,0x04,0xEA,0x4F, + 0xFD,0xE2,0x86,0x6F,0xF4,0x1E,0xD3,0x3F,0xF7,0x2D,0x40,0xDF,0x22,0x0E,0x9F,0x76, + 0x91,0xC8,0x99,0x6F,0x79,0x54,0x23,0xFE,0xBC,0xE7,0xD8,0xDF,0xD9,0x86,0x55,0x1D, + 0x9B,0xF8,0x67,0xF4,0xD0,0xC3,0x8D,0xF3,0x47,0xAC,0xD2,0x04,0x7B,0xCC,0x4D,0x0A, + 0xF9,0x1E,0xEF,0x5C,0x1D,0x0F,0x55,0x28,0x73,0x59,0x5F,0x91,0x84,0x2E,0xE3,0xBA, + 0x59,0xA1,0x66,0x5F,0x62,0x3E,0x5C,0x26,0xBF,0x1C,0x5E,0xBA,0x51,0x9B,0xCB,0x08, + 0x59,0x3D,0xDD,0xF7,0xFF,0x8D,0x02,0xAB,0xC2,0x15,0x8D,0x61,0x54,0x9A,0xFB,0xBB, + 0x89,0x92,0x58,0x3A,0x27,0xBE,0xB1,0xE5,0xDF,0x91,0x16,0x94,0x8F,0x16,0x88,0x8D, + 0xDD,0x64,0xC4,0xF9,0x9B,0x7C,0x19,0x4B,0x9E,0x4F,0x6C,0xFC,0xBF,0x2A,0x7A,0x1D, +}; + +/* subject:/CN=Leaf sha256 valid complete ok1/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=CA sha256 valid complete/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char leafOnAllowList_Cert[] = { + 0x30,0x82,0x04,0x6C,0x30,0x82,0x03,0x54,0xA0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0xC9,0x44,0x22,0x78,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x30,0x81,0x8A,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x18,0x43,0x41,0x20,0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69,0x64, + 0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x31,0x22,0x30,0x20,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63, + 0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70, + 0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 0x30,0x20,0x17,0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30,0x37, + 0x5A,0x18,0x0F,0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30,0x30, + 0x37,0x5A,0x30,0x81,0x90,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x03,0x0C,0x1E, + 0x4C,0x65,0x61,0x66,0x20,0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69, + 0x64,0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x20,0x6F,0x6B,0x31,0x31,0x22, + 0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50, + 0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20, + 0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07, + 0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, + 0x0A,0x02,0x82,0x01,0x01,0x00,0xB4,0x45,0x14,0x8C,0x97,0x75,0x09,0xD1,0x43,0x55, + 0x8F,0x80,0x19,0x11,0x13,0x83,0xB2,0x6C,0x38,0x23,0xCE,0x1C,0x61,0xFE,0x41,0xD7, + 0xB4,0x78,0x98,0xF9,0xE9,0x72,0xCA,0x45,0xB4,0x0F,0xEB,0x32,0x57,0x45,0x93,0x6F, + 0x7F,0xC8,0xDC,0xEC,0xE1,0x2D,0x77,0x8A,0x8C,0x8D,0x9E,0x65,0xE0,0xE9,0x09,0x02, + 0xA1,0x1E,0x5F,0xDA,0x00,0xED,0xDD,0x49,0x34,0xCA,0xD8,0xA2,0x8E,0x3F,0xF3,0x5F, + 0x3E,0x6C,0x86,0x31,0x83,0x01,0xB4,0xCA,0x95,0xD3,0x5F,0x5A,0xBF,0x09,0x7E,0x3D, + 0x2A,0xBC,0x03,0x96,0xB7,0xC5,0x66,0x04,0x77,0xB7,0x37,0x43,0xA3,0x08,0x3B,0x0C, + 0x39,0x7D,0x98,0xAD,0x97,0xF3,0x69,0x65,0x07,0x4A,0x0E,0xF3,0xB9,0xD1,0xD5,0xE2, + 0xB8,0x91,0x39,0xBB,0xBE,0x3C,0xE7,0x37,0xCD,0xB4,0x22,0x3A,0x22,0xE8,0xFB,0x65, + 0xC8,0x52,0x88,0x30,0xFC,0x84,0x00,0xE0,0x17,0xB7,0x46,0xF0,0xF1,0x14,0xC3,0x7B, + 0x10,0x6A,0x26,0x5A,0xD8,0x09,0x86,0x91,0xC7,0x2A,0xEE,0xC7,0xA6,0x12,0x30,0x32, + 0x38,0x6D,0x78,0x38,0x59,0x72,0xC8,0x5A,0xC9,0x9E,0x3C,0xB5,0xAD,0x82,0xD7,0x83, + 0xC4,0xC3,0x30,0x15,0x46,0x2F,0x24,0xE0,0x9B,0xDD,0x12,0x97,0x6E,0x54,0x6C,0x8C, + 0x31,0x30,0xD4,0x24,0x40,0x48,0x46,0x58,0x51,0xF9,0x86,0x2B,0xA4,0x8E,0x16,0x63, + 0xAE,0x35,0x8E,0xCD,0x64,0x4B,0xA8,0x9D,0x68,0xD5,0x8C,0xBE,0xCF,0x06,0x4C,0x91, + 0xAC,0x77,0x81,0xCE,0x16,0x6C,0x92,0xCE,0x30,0x03,0x51,0x79,0xDF,0xA4,0x11,0xC0, + 0x4F,0xAC,0xF7,0x28,0x8F,0x09,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xCE,0x30,0x81, + 0xCB,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, + 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x49,0x96,0xB4,0x72, + 0xB2,0x4C,0x90,0x9B,0xA3,0x22,0x66,0x52,0x66,0x72,0x25,0x3A,0x51,0x93,0xE6,0xC7, + 0x30,0x4F,0x06,0x03,0x55,0x1D,0x1F,0x04,0x48,0x30,0x46,0x30,0x44,0xA0,0x42,0xA0, + 0x40,0x86,0x3E,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61,0x6C,0x69,0x64,0x74, + 0x65,0x73,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65,0x6F,0x66,0x66,0x6B, + 0x2E,0x6E,0x65,0x74,0x2F,0x76,0x32,0x2D,0x73,0x68,0x61,0x32,0x35,0x36,0x2D,0x76, + 0x61,0x6C,0x69,0x64,0x2D,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x2E,0x63,0x72, + 0x6C,0x30,0x39,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x2D,0x30, + 0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x1D,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6B,0x6E,0x6F,0x77,0x6E,0x2D,0x61,0x6E,0x73,0x77, + 0x65,0x72,0x2D,0x6F,0x63,0x73,0x70,0x2F,0x6F,0x63,0x73,0x70,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00, + 0x2F,0x35,0xE8,0xE8,0xF5,0x5C,0x7E,0x48,0x81,0xC9,0xCF,0xF5,0x45,0x08,0xB9,0x47, + 0x08,0xCD,0x5C,0x4A,0xD5,0xD3,0xB2,0x4C,0x9E,0x9F,0xDD,0x7F,0xC6,0xF1,0x76,0xFC, + 0xCB,0xC0,0x7C,0x50,0xCC,0x63,0xA8,0xE3,0xB3,0x79,0xA7,0x80,0xE4,0x77,0xC3,0x8A, + 0x9E,0x25,0x93,0xB2,0x51,0x00,0x5C,0x4D,0xE1,0x9F,0x16,0xFD,0xC7,0x30,0x28,0xA7, + 0x91,0x5E,0xE5,0x33,0x2A,0xE7,0xB3,0x19,0x12,0x0D,0x6B,0xC6,0x09,0xA9,0xF9,0x2C, + 0x32,0x4A,0xB6,0x3F,0x8E,0xBB,0x5F,0x14,0x39,0x32,0x87,0xBB,0x23,0xDF,0x81,0x72, + 0x40,0xEB,0x54,0xF6,0xA8,0x33,0x1E,0xE2,0xB7,0x54,0xD8,0x80,0xB4,0xFA,0x74,0xA2, + 0xC2,0xEB,0x26,0x11,0x60,0xFD,0x0B,0x37,0x83,0x7F,0x1C,0x14,0xE6,0xCA,0x45,0x8A, + 0xA7,0xF9,0x47,0x94,0xA8,0xCD,0xCE,0x0D,0x5E,0x14,0x63,0x0A,0xCB,0x6D,0xE6,0x7C, + 0xED,0xF0,0x57,0xFD,0x0F,0x29,0xB7,0x47,0x3A,0x7A,0xE6,0x62,0x58,0xD9,0x55,0x80, + 0x5B,0xF6,0xD7,0x98,0x5B,0xE4,0x47,0xAE,0x60,0xC5,0x79,0x1D,0x53,0x94,0x81,0x87, + 0x20,0xC8,0x27,0x95,0xF2,0x41,0xE7,0xA3,0xA4,0xB8,0xE5,0x7E,0x59,0xDD,0xFF,0xA3, + 0x79,0x64,0x4A,0x65,0x0A,0x42,0x29,0xD0,0x0A,0x35,0x41,0xF6,0xCA,0x05,0x5A,0x72, + 0xBE,0xAA,0x4A,0x77,0x9A,0xC5,0x1B,0x59,0x46,0x40,0xF7,0x9D,0x75,0xAE,0xAF,0x92, + 0x12,0xF6,0x82,0xEA,0xCF,0xF9,0x6E,0x4F,0x94,0xB7,0x17,0x90,0xA9,0xAF,0x45,0xEA, + 0xAE,0x76,0xB4,0x52,0x2E,0x10,0x4C,0x74,0x7C,0x92,0x70,0xD4,0xEA,0x4D,0x65,0x6B, +}; + +/* subject:/CN=Leaf sha256 valid complete revoked1/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=CA sha256 valid complete/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char leafNotOnAllowList_Cert[] = { + 0x30,0x82,0x04,0x70,0x30,0x82,0x03,0x58,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x20, + 0x11,0x11,0xF5,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, + 0x05,0x00,0x30,0x81,0x8A,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18, + 0x43,0x41,0x20,0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69,0x64,0x20, + 0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04, + 0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74, + 0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65, + 0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02, + 0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x20,0x17,0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30,0x37,0x5A, + 0x18,0x0F,0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30,0x30,0x37, + 0x5A,0x30,0x81,0x95,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04,0x03,0x0C,0x23,0x4C, + 0x65,0x61,0x66,0x20,0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69,0x64, + 0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x20,0x72,0x65,0x76,0x6F,0x6B,0x65, + 0x64,0x31,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C, + 0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20, + 0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06, + 0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F, + 0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xB1,0x1D,0xC6,0x90,0xDB,0xE4, + 0x97,0x45,0x2E,0xBB,0x6C,0x70,0x6D,0x89,0xE6,0x98,0x0D,0xA7,0x3C,0x7D,0x9C,0x36, + 0xE6,0xEC,0x96,0xA7,0xBE,0xC3,0xE0,0x3F,0x73,0xA7,0xCB,0xDA,0xE9,0xEA,0x56,0xE1, + 0xE8,0x55,0x9E,0xFF,0x72,0x43,0x37,0x88,0x1C,0x79,0x8B,0xA6,0xCD,0x3B,0xFB,0xDC, + 0x00,0xA2,0xB1,0xF6,0xF9,0x01,0x6B,0x2F,0xD7,0xA3,0x9A,0x31,0xC6,0xD2,0x94,0x48, + 0x34,0x01,0x4C,0x20,0x5A,0x4B,0xBE,0xDB,0x4D,0xDD,0xB2,0xB3,0x0F,0xEC,0x5A,0x94, + 0x08,0x19,0x77,0x6C,0xE0,0x46,0x87,0xD8,0x07,0x63,0x72,0x06,0x7B,0x42,0x82,0xEA, + 0x18,0xCE,0x43,0x10,0xC6,0xD2,0xB6,0x6A,0x51,0xF0,0x19,0xBD,0xF3,0x1B,0xB0,0x78, + 0x92,0x97,0x25,0xDF,0x16,0xA4,0x99,0xE0,0x36,0x50,0x37,0x67,0x47,0xCE,0x7D,0x62, + 0x07,0xFB,0x94,0x37,0xA6,0x29,0xF7,0x1F,0x3F,0x63,0x70,0x26,0x81,0x06,0x57,0x23, + 0x74,0x2B,0x16,0xA3,0x3A,0x1C,0xE7,0xF6,0x2E,0x51,0x3B,0x38,0x7B,0x3F,0x43,0xE4, + 0xEC,0xC1,0x35,0x43,0x66,0xC1,0x32,0x7D,0xB2,0x91,0xB7,0x40,0x1E,0x80,0xFD,0x39, + 0x25,0xF8,0xDB,0x4A,0x57,0xBE,0x41,0x97,0xF5,0xF8,0xA3,0xFA,0xC5,0xC1,0xF0,0xDF, + 0x6F,0x9F,0x07,0x41,0xA0,0xFB,0x21,0x7C,0x35,0x64,0xA3,0xB5,0xD6,0xE1,0xFF,0x0E, + 0x34,0x22,0xD8,0xD8,0x84,0x75,0x5A,0xDD,0xC3,0xCB,0x33,0x6F,0x98,0x82,0xF6,0x69, + 0x1A,0x4C,0x3E,0x50,0x3D,0x35,0xE6,0xA9,0xE2,0x64,0x7C,0x0F,0x3E,0xD8,0xC0,0x93, + 0x52,0xDB,0x87,0xA1,0x0B,0x4C,0x36,0x57,0x91,0x67,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x81,0xCE,0x30,0x81,0xCB,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x07,0x80,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, + 0x49,0x96,0xB4,0x72,0xB2,0x4C,0x90,0x9B,0xA3,0x22,0x66,0x52,0x66,0x72,0x25,0x3A, + 0x51,0x93,0xE6,0xC7,0x30,0x4F,0x06,0x03,0x55,0x1D,0x1F,0x04,0x48,0x30,0x46,0x30, + 0x44,0xA0,0x42,0xA0,0x40,0x86,0x3E,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61, + 0x6C,0x69,0x64,0x74,0x65,0x73,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65, + 0x6F,0x66,0x66,0x6B,0x2E,0x6E,0x65,0x74,0x2F,0x76,0x32,0x2D,0x73,0x68,0x61,0x32, + 0x35,0x36,0x2D,0x76,0x61,0x6C,0x69,0x64,0x2D,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74, + 0x65,0x2E,0x63,0x72,0x6C,0x30,0x39,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01, + 0x01,0x04,0x2D,0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30, + 0x01,0x86,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6B,0x6E,0x6F,0x77,0x6E,0x2D, + 0x61,0x6E,0x73,0x77,0x65,0x72,0x2D,0x6F,0x63,0x73,0x70,0x2F,0x6F,0x63,0x73,0x70, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x65,0xFD,0x30,0xA6,0x32,0x7D,0x2A,0xB7,0xB7,0xC3,0xD8,0x66, + 0x49,0x91,0x9C,0x39,0x17,0xB2,0x3F,0x9F,0x62,0xB4,0x8A,0x07,0x9A,0xA8,0xE5,0x1C, + 0x6A,0x62,0xEA,0x77,0x4B,0x7A,0xC0,0xE6,0x24,0x2C,0xAE,0xAE,0x0F,0xE6,0xE6,0x82, + 0x7F,0x02,0xA2,0x3B,0xC8,0x4C,0xB3,0x7C,0x0E,0x7B,0x3C,0x2E,0x52,0x95,0xDB,0x29, + 0xBF,0xFE,0x11,0x5D,0xE2,0xEE,0xE2,0xFC,0xE2,0x48,0x10,0xDE,0xF2,0xD6,0x24,0x66, + 0xD8,0x81,0x76,0xDF,0x0F,0xA5,0x26,0x82,0x8D,0xEB,0xA0,0xDE,0xD8,0x59,0x53,0x69, + 0x0D,0x47,0x9A,0xB2,0xFE,0xB4,0x1D,0xFB,0x32,0x56,0x49,0x09,0xA4,0x52,0xB4,0xB9, + 0x19,0x54,0x4E,0xEC,0x29,0x8A,0x59,0x5D,0x63,0x1B,0xB9,0x09,0x4D,0xF1,0xB0,0x85, + 0xF2,0x91,0xE8,0x7A,0x76,0x38,0x28,0x5C,0x08,0x36,0x9E,0xAC,0x74,0x31,0xD5,0xFF, + 0xDA,0x15,0xCE,0x80,0x15,0x6F,0x23,0xDC,0xB6,0x93,0x01,0xC7,0x12,0x8A,0x06,0xD4, + 0x42,0xE9,0x81,0x29,0xB9,0x2A,0xC7,0xD0,0xA9,0xFA,0xD6,0x6C,0xA4,0x26,0x4D,0x54, + 0x16,0xA7,0x65,0x52,0xB9,0xEF,0x4A,0x68,0xDF,0x14,0xFF,0x73,0x4B,0xED,0x18,0x9B, + 0xDB,0x27,0x66,0x38,0xBF,0x03,0x13,0xCC,0xBC,0xE5,0xBA,0x1C,0x7F,0x62,0x36,0x04, + 0x39,0xA2,0x6E,0x32,0x65,0xA1,0x03,0x7A,0x63,0xC8,0x3C,0x01,0x85,0xE3,0x60,0xAF, + 0x3D,0x1B,0xA9,0x86,0xB6,0xBA,0xD0,0x23,0xDC,0x82,0x05,0x0B,0x6A,0x4F,0x7B,0x82, + 0xC1,0xF6,0xC7,0x23,0xB3,0x6C,0xBC,0x10,0x88,0x89,0xFF,0xBE,0x45,0xF6,0x5A,0xA1, + 0x00,0x0F,0xD9,0x83, +}; + +/* subject:/CN=CA sha256 valid complete/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=Valid Test CA Root V2/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char ca1_Cert[] = { + 0x30,0x82,0x04,0x3C,0x30,0x82,0x03,0x24,0xA0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0xE4,0xF5,0x4B,0x6E,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x30,0x81,0x87,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x15,0x56,0x61,0x6C,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x20,0x52, + 0x6F,0x6F,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54, + 0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74, + 0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x20,0x17, + 0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30,0x35,0x5A,0x18,0x0F, + 0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30,0x30,0x35,0x5A,0x30, + 0x81,0x8A,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x43,0x41,0x20, + 0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69,0x64,0x20,0x63,0x6F,0x6D, + 0x70,0x6C,0x65,0x74,0x65,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19, + 0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65, + 0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, + 0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03, + 0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xDE,0x13,0x51, + 0x00,0x15,0x31,0xFE,0x34,0x3D,0x25,0x3F,0x63,0x7B,0x77,0x40,0x41,0x67,0xFE,0xD4, + 0xEF,0xE2,0xE1,0x83,0x3C,0x27,0x29,0x76,0x41,0x55,0xBE,0x00,0x71,0xEA,0x78,0x5B, + 0x60,0xA5,0x6B,0xD7,0xE8,0xD3,0x20,0x49,0xDA,0xED,0xD8,0x55,0xA5,0x5A,0xDF,0x01, + 0x0C,0x7E,0x41,0x0B,0xAA,0x61,0xCF,0xBD,0xBF,0x87,0x2F,0xCC,0x02,0x79,0x92,0x51, + 0x00,0x29,0x1E,0x6F,0x09,0x9F,0x1D,0xA9,0x85,0xA8,0xB6,0x0B,0xF6,0x8F,0x07,0x46, + 0x08,0xD2,0x0F,0x92,0x70,0x25,0x82,0xA4,0x73,0xA8,0xF4,0xE6,0x8F,0x5D,0x6D,0x49, + 0x0F,0xE4,0x05,0xD2,0xEF,0xA5,0xE8,0x49,0xAD,0xA5,0x08,0xC0,0x89,0x4F,0xEF,0xA7, + 0x36,0xA1,0xF2,0x0D,0xBD,0x41,0xAD,0x63,0x6B,0xC4,0x65,0xD1,0x79,0x94,0xAF,0x3A, + 0x35,0xA3,0x7A,0x5B,0xE7,0xA0,0x78,0x16,0x4E,0xB7,0x0A,0x1A,0x3A,0xF5,0xC6,0xA5, + 0x6B,0x9C,0x14,0x0F,0x15,0xEB,0xBE,0xA1,0x29,0xA6,0xA7,0xB2,0x92,0x3A,0xD6,0xFA, + 0x91,0xEF,0xCB,0xC4,0x7C,0xDB,0x49,0x11,0x73,0x0D,0x94,0xCA,0x0C,0xEA,0x53,0xAE, + 0x9C,0xCA,0x07,0xC7,0x48,0xC2,0xC0,0xE3,0x0C,0x58,0x1C,0xA5,0xE0,0x27,0x45,0xE3, + 0xCD,0xEC,0x17,0x50,0xE7,0xC5,0xD1,0x58,0x5A,0x19,0x3E,0xA5,0xDA,0xE3,0x19,0xB0, + 0x63,0x53,0x0B,0x53,0xDB,0xF0,0x40,0xF2,0xAF,0xBA,0x20,0xA5,0x96,0xB2,0x5E,0xD0, + 0x0F,0x28,0xED,0x5F,0xCC,0xEB,0x69,0x16,0xF0,0xCD,0x22,0xDF,0x7B,0xBF,0x8F,0x32, + 0x11,0x9F,0xF8,0x29,0x48,0x5D,0x6A,0x0A,0xDB,0x46,0x70,0x80,0x19,0x02,0x03,0x01, + 0x00,0x01,0xA3,0x81,0xA7,0x30,0x81,0xA4,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, + 0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01, + 0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x49,0x96,0xB4,0x72,0xB2,0x4C,0x90,0x9B,0xA3, + 0x22,0x66,0x52,0x66,0x72,0x25,0x3A,0x51,0x93,0xE6,0xC7,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xBA,0x56,0xD8,0x57,0x66,0xBD,0xFC,0x5B, + 0xE2,0x10,0xF2,0x39,0xB3,0xAF,0xB2,0x72,0xED,0x55,0x0F,0x1C,0x30,0x3E,0x06,0x03, + 0x55,0x1D,0x1F,0x04,0x37,0x30,0x35,0x30,0x33,0xA0,0x31,0xA0,0x2F,0x86,0x2D,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61,0x6C,0x69,0x64,0x74,0x65,0x73,0x74,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65,0x6F,0x66,0x66,0x6B,0x2E,0x6E,0x65,0x74, + 0x2F,0x76,0x32,0x2D,0x72,0x6F,0x6F,0x74,0x2E,0x63,0x72,0x6C,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00, + 0x75,0xDE,0xCF,0x34,0xBD,0xF4,0xAF,0x9C,0x50,0xDA,0x36,0x78,0xE1,0xE1,0xCD,0x54, + 0x35,0x61,0xB0,0x4C,0x46,0x17,0x55,0x7D,0x9F,0x1E,0x69,0xCD,0x66,0x62,0x2B,0xF5, + 0x30,0xD9,0xAE,0x36,0xD2,0xF6,0x21,0x03,0x59,0x3B,0xAB,0xFF,0x79,0xA7,0xF8,0x16, + 0xF3,0x79,0x49,0x19,0xF5,0x05,0x4F,0x70,0xB5,0x26,0xA8,0x41,0xB0,0x66,0x33,0xA1, + 0x3C,0xF9,0xF9,0x61,0x77,0x5F,0x52,0xA7,0x5A,0xC1,0xA1,0x1D,0xA9,0x2B,0x7A,0x44, + 0x8C,0x01,0x4C,0x8A,0x5B,0x2C,0xF0,0x10,0xB8,0x17,0xEF,0x45,0xAA,0x1E,0xC9,0x46, + 0xF8,0x19,0x0A,0xE0,0x25,0x9D,0xC1,0xBF,0x6D,0x34,0x1F,0xFA,0xC9,0xFF,0x62,0x5C, + 0x44,0x96,0x01,0x2B,0x4B,0xBF,0xD0,0xD5,0x56,0x07,0xA9,0x43,0x0D,0xF6,0x85,0x7C, + 0x49,0x0B,0x43,0xA9,0xD7,0xAA,0xC2,0xBF,0x0A,0x5B,0xC0,0xD1,0xA1,0x82,0x9F,0x5F, + 0xB8,0xF4,0x0B,0xC5,0x9A,0x40,0x0B,0xC2,0x2D,0xC9,0xF0,0x4A,0x76,0xA9,0x9B,0x58, + 0x25,0xCA,0x13,0x48,0x63,0xE7,0xD5,0x58,0x58,0x91,0x4D,0xEE,0x21,0x14,0x83,0x5E, + 0x2E,0x9B,0xBF,0x74,0x9E,0x03,0x8C,0x86,0xAF,0xB0,0xCC,0xD8,0xC1,0xC2,0x3D,0xFE, + 0xF8,0x2F,0x6E,0x9E,0x42,0xEF,0x8E,0x20,0xE7,0x94,0x56,0xB6,0xDA,0xC1,0x84,0xC6, + 0x77,0xF1,0x27,0x8B,0xA7,0x68,0x0F,0x8A,0x43,0xD5,0xC6,0x99,0x37,0x43,0x4D,0xAF, + 0xAD,0x9C,0xDC,0x3D,0x10,0x7E,0xDF,0xBF,0xDD,0x76,0xE5,0xE6,0xD7,0x90,0x94,0x9D, + 0xCE,0x46,0x27,0xD7,0x10,0xB7,0xC6,0x07,0xA7,0x6D,0xC9,0x9A,0x8E,0xE3,0x71,0xA6, +}; + +/* subject:/CN=Valid Test CA Root V2/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=Valid Test CA Root V2/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char root_Cert[] = { + 0x30,0x82,0x03,0xD7,0x30,0x82,0x02,0xBF,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0x8C,0x0C,0x8D,0x50,0x34,0x29,0x1D,0xB6,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x87,0x31,0x1E,0x30,0x1C,0x06,0x03, + 0x55,0x04,0x03,0x0C,0x15,0x56,0x61,0x6C,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20, + 0x43,0x41,0x20,0x52,0x6F,0x6F,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65, + 0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x20,0x17,0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x33,0x35,0x33, + 0x32,0x5A,0x18,0x0F,0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x33,0x35, + 0x33,0x32,0x5A,0x30,0x81,0x87,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x15,0x56,0x61,0x6C,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x20,0x52, + 0x6F,0x6F,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54, + 0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74, + 0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01, + 0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, + 0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC3,0x6D, + 0x14,0x60,0xB3,0xD3,0x0A,0x8A,0xF6,0xBE,0xA7,0x42,0xBF,0xC7,0x11,0xC2,0x6C,0x8A, + 0x94,0xF1,0x0E,0x3D,0x67,0x1C,0x9D,0x4A,0xD6,0x2E,0xC1,0xEA,0x77,0xA2,0x6E,0xAA, + 0x99,0x67,0xBE,0x9F,0xA7,0xBE,0xBD,0x24,0xD1,0x43,0xC8,0x3A,0x88,0x77,0x70,0x24, + 0x9D,0xC6,0x5E,0x53,0x59,0x31,0xA9,0xB1,0x1B,0x1F,0xBA,0x67,0xA7,0x57,0x55,0x0D, + 0xB3,0xD4,0x01,0xAE,0xE4,0xA8,0xC4,0xE7,0x29,0x1C,0xA1,0x39,0x6F,0x1A,0x1C,0x2D, + 0xC1,0x56,0x0A,0x16,0x3F,0x26,0x2F,0x20,0x49,0x33,0x35,0xD2,0xF9,0x6D,0x3B,0x5E, + 0x98,0x59,0x4A,0x70,0xCE,0xFF,0xA4,0x23,0xE6,0x23,0x43,0x23,0xE5,0x8B,0x2F,0xEE, + 0x6A,0x28,0x28,0x4B,0x31,0xA0,0xC8,0x08,0x6C,0x0F,0x38,0x11,0xBC,0x27,0x7F,0x61, + 0xCF,0xB0,0x36,0xB9,0x8C,0xBA,0xBA,0x3E,0x00,0x1E,0xD0,0xFF,0x71,0x92,0xDB,0xA1, + 0x8C,0x1F,0x03,0x29,0x13,0x7C,0xAF,0x87,0xA2,0x41,0x2A,0x5E,0x07,0xFE,0xEF,0x37, + 0xC8,0xB4,0x72,0xC7,0x89,0x03,0x81,0x69,0x01,0xC8,0x7B,0xBE,0x82,0x0A,0x45,0xE2, + 0x88,0xD6,0x63,0x80,0x54,0x29,0x00,0xF6,0xAF,0x58,0xB7,0x65,0x4A,0xD0,0x1A,0x7F, + 0x75,0x01,0x06,0xF6,0xB2,0x94,0x2D,0x5E,0x1D,0x02,0xB8,0xEE,0xFA,0x55,0xC8,0xDD, + 0x84,0x29,0xE7,0x59,0xAA,0xD6,0xEB,0x6C,0x11,0x26,0x16,0xEF,0xF4,0xDA,0x73,0xD8, + 0x39,0xD8,0xEC,0xF1,0x8F,0x1C,0x13,0xD6,0x2C,0x7A,0xD9,0x8A,0x12,0xF1,0xE1,0x3D, + 0xAB,0x81,0x6F,0x7D,0x95,0x74,0x20,0x6A,0xC0,0x1D,0xF4,0x5B,0x7C,0xDD,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x42,0x30,0x40,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, + 0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, + 0x16,0x04,0x14,0xBA,0x56,0xD8,0x57,0x66,0xBD,0xFC,0x5B,0xE2,0x10,0xF2,0x39,0xB3, + 0xAF,0xB2,0x72,0xED,0x55,0x0F,0x1C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xB6,0x57,0xE2,0x6C,0x23, + 0x90,0x87,0xD5,0x40,0xF4,0xE2,0x39,0x35,0x2F,0x1B,0xFB,0x31,0x0E,0x14,0xF9,0xFF, + 0x97,0x5C,0xED,0x7A,0x6D,0x5F,0x80,0x1F,0x98,0x93,0x0A,0x13,0xA5,0x8F,0x9B,0x2B, + 0x20,0x0E,0xAF,0x62,0x1B,0xB0,0xF8,0xBB,0x00,0xBD,0xDC,0x56,0x3B,0xD9,0x4B,0x6C, + 0x7B,0x80,0xEA,0x18,0xC7,0x32,0x8A,0x38,0xAE,0x9F,0xEE,0x1F,0x17,0x0D,0x1C,0x82, + 0xEB,0x92,0xE5,0x87,0x1B,0x9E,0x3E,0xE2,0x32,0x7B,0xB5,0x9F,0xBC,0x52,0x1F,0x07, + 0xB1,0x77,0x16,0xA9,0xC2,0xB6,0x9F,0xC1,0xE4,0xCA,0x27,0x45,0x18,0xF7,0x07,0x7F, + 0x74,0x95,0x5E,0x8C,0x67,0x3D,0xEA,0x20,0x39,0x4A,0x4A,0x79,0xB6,0xEC,0xCE,0x98, + 0x3F,0x60,0x51,0x26,0xF3,0x37,0x0E,0x0C,0xFC,0x3E,0x14,0xBF,0xEA,0x75,0xA7,0x68, + 0x0F,0xA4,0x1C,0x57,0x04,0xF8,0xC1,0x11,0x6D,0xD0,0x1F,0x93,0x30,0x5C,0xB4,0x99, + 0x91,0x67,0x3C,0x72,0x95,0x63,0x7F,0x2D,0x66,0xE0,0x32,0x11,0xC4,0x76,0xF5,0xC0, + 0x36,0x23,0x20,0xBC,0xE4,0x4F,0xDA,0xE7,0xDC,0x10,0x62,0x49,0xC0,0xC7,0x91,0xFE, + 0x4C,0xCC,0x09,0x40,0xB9,0x33,0x0D,0xD5,0x90,0x4E,0xD9,0x83,0x54,0x2C,0x42,0x81, + 0x17,0xFA,0xDF,0x57,0x3A,0x15,0x76,0x05,0x1F,0x11,0x40,0xCE,0x85,0xEC,0xA2,0xA3, + 0xF6,0xAC,0xB6,0x67,0xA6,0x78,0xD0,0xA9,0xA7,0xF2,0x60,0xF4,0xFC,0xD1,0x78,0x9E, + 0x00,0x00,0xD9,0xE7,0xE7,0xE5,0xED,0xE4,0x10,0x8D,0x8E,0x5B,0xCC,0x8E,0xB6,0xD6, + 0x71,0xCF,0x54,0x16,0xD4,0x99,0xCD,0x6D,0x40,0x2A,0x8A, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Test CA */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Test CA */ +/* SHA256: 51a0f31fc01dec8732b6fd136a434d6c87cd62e038b4fbd640b0fd624d1fcf6d */ +unsigned char _datetest_root[994]={ + 0x30,0x82,0x03,0xDE,0x30,0x82,0x02,0xC6,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xAB,0x16,0xC1,0x56,0x85,0x86,0xE5,0xC8,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x44, + 0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44,0x61,0x74,0x65,0x20,0x54,0x65,0x73, + 0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x36,0x31,0x30,0x31,0x32,0x31,0x38, + 0x31,0x35,0x34,0x39,0x5A,0x17,0x0D,0x32,0x36,0x31,0x30,0x31,0x30,0x31,0x38,0x31, + 0x35,0x34,0x39,0x5A,0x30,0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43, + 0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55, + 0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63, + 0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E, + 0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x44,0x65,0x6E,0x79, + 0x6C,0x69,0x73,0x74,0x20,0x44,0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x20,0x43, + 0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, + 0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01, + 0x01,0x00,0xF0,0x5A,0x62,0x0B,0xEA,0xD6,0xD6,0x78,0x94,0xEE,0x71,0xB5,0xF8,0x42, + 0xBB,0xF2,0x2F,0xC6,0xFB,0x53,0x7E,0xE4,0xF5,0xC9,0x8F,0x94,0xBC,0x02,0xB9,0x12, + 0x8E,0x5D,0xB4,0x12,0xE3,0x73,0xBD,0xD8,0x1A,0x3F,0x2D,0xBC,0x39,0x31,0x42,0x02, + 0x74,0xE7,0x93,0xB4,0x2B,0x6F,0xA9,0x42,0x8A,0xD4,0x0E,0xC9,0x96,0x90,0xE5,0xF6, + 0xAD,0xD7,0x7E,0x58,0xBA,0x6B,0xBD,0xBF,0xFC,0x8F,0x1E,0xD4,0xBE,0xD1,0x11,0x4B, + 0x7D,0x8A,0xD0,0x36,0xAD,0x2A,0x9A,0x37,0x5B,0xDF,0xCB,0x66,0x85,0x85,0x4F,0xD6, + 0x6F,0xEB,0xB3,0xC8,0xF7,0x6C,0x42,0x2E,0xE9,0xD6,0x84,0xD7,0x0F,0xD5,0x97,0xFD, + 0x4F,0x31,0x33,0x1B,0x5B,0x23,0x56,0x1B,0x7C,0x1E,0x11,0x51,0xE8,0x14,0x22,0x50, + 0x15,0x3D,0x01,0x1F,0x02,0x36,0x44,0x64,0x70,0xB3,0x7A,0xF7,0xF6,0xDA,0x14,0x9E, + 0x39,0xC3,0xD1,0x9E,0xED,0x70,0x2C,0x4E,0xA5,0xA5,0x1C,0xB7,0xEE,0xEF,0x4E,0x90, + 0x5D,0xF9,0x34,0xBB,0xA7,0xDF,0xD4,0xC5,0xEB,0x84,0xC4,0x3B,0x3D,0xCA,0x9A,0x9C, + 0xAD,0xB1,0x24,0xD4,0xD1,0x82,0xCC,0x1A,0xC4,0xEF,0xAE,0xB1,0xF0,0x12,0x28,0x37, + 0x40,0x45,0x83,0xBF,0x39,0xC7,0x90,0xB6,0x23,0x63,0xAD,0xC8,0xB9,0xF4,0x80,0x4B, + 0x91,0x91,0x64,0xDD,0x05,0x5E,0x0A,0x36,0xAB,0x7A,0x32,0xBA,0x05,0xBC,0x62,0x93, + 0xDE,0x5D,0xBA,0x2B,0x91,0xF2,0xD6,0x49,0x61,0x08,0x98,0xA2,0xD2,0x6E,0xF2,0x2D, + 0x4D,0x90,0x65,0x51,0x9C,0xC0,0x79,0x33,0x08,0xE1,0x7F,0xC0,0x09,0xCF,0x4D,0xB3, + 0x25,0x1F,0x02,0x03,0x01,0x00,0x01,0xA3,0x45,0x30,0x43,0x30,0x12,0x06,0x03,0x55, + 0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x02,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x4D,0xA5,0xDB,0xEF,0x4F,0xCD, + 0x74,0xE6,0x2A,0xB1,0xDC,0x5C,0xBE,0x12,0x04,0x94,0xEC,0x4A,0x66,0xD3,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01, + 0x01,0x00,0x06,0x5E,0xFD,0x98,0x73,0xA7,0x69,0xE2,0xAE,0x1C,0x06,0x00,0xD1,0x7C, + 0x59,0x70,0xB9,0x85,0xAF,0xB8,0xC0,0xAB,0x3B,0x60,0x64,0x0B,0x1B,0x81,0xA7,0x7D, + 0x5A,0xC4,0xDA,0x94,0x2B,0xBC,0xA7,0xDA,0x24,0x4E,0x83,0x21,0x12,0xFA,0x93,0x3E, + 0x67,0x38,0x37,0xBD,0x2B,0xEB,0x19,0xA4,0x08,0x73,0xB1,0x27,0x84,0x67,0x10,0x48, + 0x50,0x94,0x4C,0x55,0x0D,0x23,0x9F,0x0A,0xB2,0x18,0x6F,0xC1,0xE0,0x13,0xC2,0x2D, + 0x29,0x52,0xBA,0x4F,0x01,0x2C,0xD6,0x9E,0x73,0x5B,0x74,0x8A,0x0D,0x8C,0x1E,0x15, + 0x70,0x7E,0x9B,0xE0,0xCC,0xB2,0x6E,0xFE,0x44,0xD4,0xD0,0x76,0x41,0x95,0xFE,0x11, + 0xAA,0x4E,0x07,0xC6,0xBA,0x4B,0x46,0x02,0x0E,0xFC,0x4A,0xB9,0x15,0x2D,0x80,0xB5, + 0x33,0xE3,0x4E,0x41,0x46,0x05,0xEB,0x0A,0x15,0x43,0xC6,0x6A,0xC5,0x2B,0x53,0x49, + 0x49,0x61,0x57,0x0D,0x8D,0x42,0x63,0xB2,0xA6,0xC5,0xA5,0x23,0x3B,0xAC,0x50,0xDC, + 0x05,0x41,0x53,0x74,0xC5,0x67,0xA1,0x69,0xA6,0x66,0x4D,0x0F,0xF8,0x94,0x54,0x4B, + 0xA5,0x31,0x81,0xE8,0x3A,0x5C,0x02,0x84,0x56,0xFF,0xBE,0x13,0x15,0x95,0xC9,0xAF, + 0x17,0x77,0xD0,0x38,0x38,0x12,0xF9,0xA8,0x93,0x77,0x2F,0xCD,0x40,0x60,0xBC,0xCF, + 0x35,0x1C,0xE4,0xBD,0x5E,0x8D,0x96,0x19,0xB7,0x50,0x7E,0xED,0x44,0x1C,0x8C,0x08, + 0x6B,0xEE,0xEE,0xC9,0x8C,0xD6,0xDC,0x61,0x2C,0xD2,0x35,0x5E,0xB7,0x4C,0x58,0xFC, + 0x5D,0x62,0xEA,0xED,0x68,0xE8,0x1F,0xB1,0x0A,0x39,0x5C,0x29,0xBC,0x42,0x09,0xBA, + 0x4F,0x35, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Testing Intermediate CA 1 */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Test CA */ +/* Not Before: Oct 15 00:00:00 2016 GMT */ +/* X509v3 Subject Key Identifier: E7:C3:06:5B:22:E0:EC:DA:8C:80:00:D9:0C:AC:0B:78:D4:68:C5:B7 */ +unsigned char _datetest_before_int[1050]={ + 0x30,0x82,0x04,0x16,0x30,0x82,0x02,0xFE,0xA0,0x03,0x02,0x01,0x02,0x02,0x11,0x00, + 0x9A,0x17,0xF8,0x6F,0x33,0x3D,0xAB,0x4C,0xD3,0xFB,0x3A,0x6D,0xCF,0x05,0x94,0xEC, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30, + 0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20, + 0x44,0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, + 0x31,0x36,0x31,0x30,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31, + 0x37,0x31,0x30,0x31,0x32,0x31,0x38,0x32,0x38,0x31,0x38,0x5A,0x30,0x81,0x9C,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69, + 0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65, + 0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E, + 0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x30,0x30,0x2E,0x06,0x03,0x55, + 0x04,0x03,0x0C,0x27,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44,0x61,0x74, + 0x65,0x20,0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0x20,0x49,0x6E,0x74,0x65,0x72,0x6D, + 0x65,0x64,0x69,0x61,0x74,0x65,0x20,0x43,0x41,0x20,0x31,0x30,0x82,0x01,0x22,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, + 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xF0,0xCB,0x1D,0x6C, + 0x7D,0xC1,0x90,0xB7,0xD9,0xB5,0x66,0x61,0x5E,0x34,0x76,0x14,0xFA,0xF8,0xB4,0xE1, + 0x6D,0x67,0xB0,0x9E,0xB9,0x93,0xB0,0xBE,0x15,0xA4,0xAB,0x76,0x23,0x0D,0x5C,0xC0, + 0x4D,0xB6,0x9F,0xCC,0x9B,0x3A,0x7E,0x50,0x13,0xE6,0x46,0x39,0xB1,0xE9,0x5F,0xB3, + 0xD7,0x86,0xA4,0x23,0xA5,0x27,0xDC,0x20,0x6A,0x64,0xD8,0x0A,0xCD,0x5F,0xEE,0x40, + 0x16,0xCE,0x4D,0xB9,0xCF,0xA2,0x62,0xC8,0x01,0x70,0x7F,0x8D,0x42,0x46,0xB1,0xF2, + 0x80,0x57,0xD5,0x82,0x53,0xEF,0xF2,0x16,0xA4,0xD5,0x07,0xE2,0xA7,0x7A,0x5E,0xD5, + 0x5A,0x4F,0x58,0x88,0xF7,0xEB,0x1B,0x58,0x91,0x6D,0x4E,0xD8,0xCC,0x9F,0xA6,0x98, + 0x05,0xE6,0xFB,0xC2,0x55,0xCA,0xD9,0x7E,0xC8,0xAA,0xC2,0x92,0xC1,0x73,0xBB,0xEC, + 0x89,0x51,0x1C,0x6B,0x0C,0xE5,0x7D,0xF8,0x54,0xBE,0xF7,0x67,0x8C,0xEE,0xE4,0xBB, + 0xFF,0xB9,0x15,0x4F,0xD7,0x1B,0x76,0xF7,0x37,0xEF,0xB0,0xA0,0x2A,0x22,0x4D,0x4B, + 0x2A,0xDE,0x3D,0x37,0x28,0x4A,0x79,0xF6,0xC7,0xE3,0x51,0xEC,0xC4,0x2F,0xDA,0xC1, + 0xBA,0x1A,0xFF,0xDD,0x43,0x2A,0x44,0xD4,0x94,0xDC,0xEE,0xDB,0xC3,0xF2,0xB4,0x76, + 0x01,0xF7,0x69,0x48,0x11,0x67,0xAC,0x3C,0x1C,0xE0,0xEF,0x88,0x77,0x70,0x66,0x39, + 0x17,0xAA,0xD8,0x2C,0x67,0xE3,0xC3,0x2B,0xCD,0xC4,0xB9,0xC8,0xCD,0xA9,0xA4,0xC1, + 0x24,0xDF,0x8E,0x4D,0xE0,0x03,0x1E,0x40,0xAB,0xDD,0x10,0xE7,0xB5,0x93,0x1F,0xF2, + 0xC9,0xCC,0x91,0x3A,0x8D,0x52,0xC9,0x3D,0x7D,0x4D,0xA0,0xBB,0x02,0x03,0x01,0x00, + 0x01,0xA3,0x63,0x30,0x61,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF, + 0x04,0x04,0x03,0x02,0x02,0x04,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0xE7,0xC3,0x06,0x5B,0x22,0xE0,0xEC,0xDA,0x8C,0x80,0x00,0xD9,0x0C,0xAC,0x0B, + 0x78,0xD4,0x68,0xC5,0xB7,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0x4D,0xA5,0xDB,0xEF,0x4F,0xCD,0x74,0xE6,0x2A,0xB1,0xDC,0x5C,0xBE,0x12, + 0x04,0x94,0xEC,0x4A,0x66,0xD3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x08,0xDC,0x9E,0xA4,0x60,0xDF, + 0x04,0x27,0xB5,0x01,0x63,0xDA,0xE3,0x6C,0x58,0x1D,0xB8,0xE8,0x17,0x06,0x4F,0x86, + 0xC8,0x97,0x65,0xF5,0x6D,0x39,0x51,0x0F,0xD4,0xF9,0xAD,0xCF,0x8C,0x08,0x7C,0xAC, + 0x26,0xD1,0x43,0xB2,0x79,0x7E,0x13,0xCD,0xF2,0x9D,0x30,0xC4,0x63,0xF2,0x5E,0x72, + 0x1A,0x0F,0x41,0x47,0x69,0x98,0x00,0xF0,0x4D,0x93,0x44,0x8A,0x26,0xDE,0x24,0xC0, + 0x66,0xA3,0xB0,0x20,0xAD,0x33,0xEB,0xF2,0x0A,0xDD,0x65,0xF4,0x9D,0x29,0x10,0x88, + 0x5B,0xFF,0x1C,0x76,0x71,0x42,0xE9,0x6F,0xBD,0xAE,0xA6,0xBB,0x4B,0xFF,0x30,0xA0, + 0x6E,0x47,0x85,0x12,0x6E,0x81,0xFC,0xB0,0x51,0x5F,0xB4,0xE9,0xCC,0x83,0x0E,0xC5, + 0xEC,0x41,0x6F,0x28,0x28,0xF0,0x51,0x4A,0x42,0x7C,0xCF,0xAE,0x8B,0xD8,0x09,0x44, + 0x32,0x27,0x07,0x57,0x86,0x1B,0xB6,0xF3,0xAF,0xCA,0x1C,0x2F,0xDD,0x1C,0x58,0x17, + 0xF4,0x13,0xA3,0x4F,0x72,0x60,0x71,0x39,0xEE,0x8E,0xF2,0x9D,0x40,0xCA,0x39,0x63, + 0xFD,0x1F,0x8C,0x2C,0xFD,0x62,0xA8,0x0E,0xC3,0x04,0x62,0x9D,0x79,0x11,0xD2,0x5C, + 0x09,0xE5,0x27,0x50,0x3A,0x62,0x93,0xC5,0xA5,0x60,0xFB,0xE5,0x7F,0xB6,0x46,0xD5, + 0xA8,0xF8,0x38,0x05,0x94,0xCD,0x47,0x5B,0xA0,0xA4,0x67,0xB8,0x81,0x99,0xA2,0x92, + 0xEB,0x13,0x37,0x56,0xD6,0xAC,0x80,0xA6,0x7F,0x1A,0xBB,0x14,0x68,0x72,0x04,0xBD, + 0xD7,0xEE,0x8F,0x48,0x56,0xC7,0xDF,0x86,0xBB,0x76,0xE4,0xE3,0xE3,0x46,0xF3,0x8B, + 0x51,0x22,0xD6,0xD2,0xB9,0xAA,0x15,0xA2,0xB4,0xAC, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Testing Intermediate CA 1 */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Test CA */ +/* Not Before: Dec 1 00:01:00 2016 GMT */ +/* X509v3 Subject Key Identifier: E7:C3:06:5B:22:E0:EC:DA:8C:80:00:D9:0C:AC:0B:78:D4:68:C5:B7 */ +unsigned char _datetest_after_int[1050]={ + 0x30,0x82,0x04,0x16,0x30,0x82,0x02,0xFE,0xA0,0x03,0x02,0x01,0x02,0x02,0x11,0x00, + 0x9A,0x17,0xF8,0x6F,0x33,0x3D,0xAB,0x4C,0xD3,0xFB,0x3A,0x6D,0xCF,0x05,0x94,0xEE, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30, + 0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20, + 0x44,0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, + 0x31,0x36,0x31,0x32,0x30,0x31,0x30,0x30,0x30,0x31,0x30,0x30,0x5A,0x17,0x0D,0x31, + 0x37,0x31,0x30,0x31,0x32,0x32,0x30,0x33,0x34,0x34,0x38,0x5A,0x30,0x81,0x9C,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69, + 0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65, + 0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E, + 0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x30,0x30,0x2E,0x06,0x03,0x55, + 0x04,0x03,0x0C,0x27,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44,0x61,0x74, + 0x65,0x20,0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0x20,0x49,0x6E,0x74,0x65,0x72,0x6D, + 0x65,0x64,0x69,0x61,0x74,0x65,0x20,0x43,0x41,0x20,0x31,0x30,0x82,0x01,0x22,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, + 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xF0,0xCB,0x1D,0x6C, + 0x7D,0xC1,0x90,0xB7,0xD9,0xB5,0x66,0x61,0x5E,0x34,0x76,0x14,0xFA,0xF8,0xB4,0xE1, + 0x6D,0x67,0xB0,0x9E,0xB9,0x93,0xB0,0xBE,0x15,0xA4,0xAB,0x76,0x23,0x0D,0x5C,0xC0, + 0x4D,0xB6,0x9F,0xCC,0x9B,0x3A,0x7E,0x50,0x13,0xE6,0x46,0x39,0xB1,0xE9,0x5F,0xB3, + 0xD7,0x86,0xA4,0x23,0xA5,0x27,0xDC,0x20,0x6A,0x64,0xD8,0x0A,0xCD,0x5F,0xEE,0x40, + 0x16,0xCE,0x4D,0xB9,0xCF,0xA2,0x62,0xC8,0x01,0x70,0x7F,0x8D,0x42,0x46,0xB1,0xF2, + 0x80,0x57,0xD5,0x82,0x53,0xEF,0xF2,0x16,0xA4,0xD5,0x07,0xE2,0xA7,0x7A,0x5E,0xD5, + 0x5A,0x4F,0x58,0x88,0xF7,0xEB,0x1B,0x58,0x91,0x6D,0x4E,0xD8,0xCC,0x9F,0xA6,0x98, + 0x05,0xE6,0xFB,0xC2,0x55,0xCA,0xD9,0x7E,0xC8,0xAA,0xC2,0x92,0xC1,0x73,0xBB,0xEC, + 0x89,0x51,0x1C,0x6B,0x0C,0xE5,0x7D,0xF8,0x54,0xBE,0xF7,0x67,0x8C,0xEE,0xE4,0xBB, + 0xFF,0xB9,0x15,0x4F,0xD7,0x1B,0x76,0xF7,0x37,0xEF,0xB0,0xA0,0x2A,0x22,0x4D,0x4B, + 0x2A,0xDE,0x3D,0x37,0x28,0x4A,0x79,0xF6,0xC7,0xE3,0x51,0xEC,0xC4,0x2F,0xDA,0xC1, + 0xBA,0x1A,0xFF,0xDD,0x43,0x2A,0x44,0xD4,0x94,0xDC,0xEE,0xDB,0xC3,0xF2,0xB4,0x76, + 0x01,0xF7,0x69,0x48,0x11,0x67,0xAC,0x3C,0x1C,0xE0,0xEF,0x88,0x77,0x70,0x66,0x39, + 0x17,0xAA,0xD8,0x2C,0x67,0xE3,0xC3,0x2B,0xCD,0xC4,0xB9,0xC8,0xCD,0xA9,0xA4,0xC1, + 0x24,0xDF,0x8E,0x4D,0xE0,0x03,0x1E,0x40,0xAB,0xDD,0x10,0xE7,0xB5,0x93,0x1F,0xF2, + 0xC9,0xCC,0x91,0x3A,0x8D,0x52,0xC9,0x3D,0x7D,0x4D,0xA0,0xBB,0x02,0x03,0x01,0x00, + 0x01,0xA3,0x63,0x30,0x61,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF, + 0x04,0x04,0x03,0x02,0x02,0x04,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0xE7,0xC3,0x06,0x5B,0x22,0xE0,0xEC,0xDA,0x8C,0x80,0x00,0xD9,0x0C,0xAC,0x0B, + 0x78,0xD4,0x68,0xC5,0xB7,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0x4D,0xA5,0xDB,0xEF,0x4F,0xCD,0x74,0xE6,0x2A,0xB1,0xDC,0x5C,0xBE,0x12, + 0x04,0x94,0xEC,0x4A,0x66,0xD3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x82,0xDE,0x0F,0x06,0xD4,0xC3, + 0x55,0xD1,0xC9,0x9A,0xDF,0x87,0x69,0xA8,0xA2,0x11,0x12,0x73,0xF4,0x8B,0x98,0x02, + 0xA6,0xE0,0xB1,0x11,0x0E,0xEB,0xC3,0x3B,0x1D,0x8B,0xBF,0x45,0x4B,0x24,0xEA,0x7A, + 0xEF,0x70,0x2A,0xAB,0xE4,0xB6,0xA1,0xB1,0x66,0x5E,0x12,0x09,0x49,0x93,0x6A,0x4B, + 0x3A,0x10,0xD1,0xEE,0xA0,0x6D,0xC7,0x19,0x5B,0xE0,0x75,0x2F,0x3F,0xFB,0x66,0x1F, + 0x91,0x86,0x30,0x5A,0xC6,0x77,0xED,0x06,0x85,0xF8,0x65,0x96,0x48,0x30,0x32,0x25, + 0x93,0x59,0x51,0x2D,0x7D,0x20,0x12,0x9A,0x87,0x07,0x40,0x8C,0x8F,0x81,0xD8,0xF8, + 0xF2,0xF2,0x3E,0xF3,0xF3,0xC8,0x7D,0x7A,0xAA,0xE3,0xF7,0xCD,0x9D,0x69,0x6F,0x85, + 0x15,0xCD,0x18,0xC0,0xBB,0x6E,0x27,0xAD,0xD3,0x9A,0xD2,0x6A,0x42,0x02,0x0C,0xDB, + 0xF5,0x0C,0x85,0xC3,0xB3,0xDB,0x4C,0x28,0x61,0x82,0xC8,0x88,0x44,0x95,0x08,0xBE, + 0x24,0x07,0xEA,0xD2,0x4C,0x0A,0xA9,0x2E,0x47,0x28,0xDE,0xF3,0x24,0xDC,0x22,0x57, + 0xA4,0x5D,0x04,0x22,0x28,0xC6,0x4F,0xBD,0x2E,0xB7,0xD4,0x2C,0x06,0x0E,0x22,0xF5, + 0x05,0xA6,0x76,0x8E,0x77,0xFD,0x1C,0xA1,0x4E,0x10,0x1D,0x82,0x74,0x73,0x06,0x47, + 0xC2,0xD2,0xF7,0x59,0xD5,0xBF,0x64,0x77,0xBB,0x47,0x15,0x23,0x4B,0x78,0x7C,0x51, + 0x34,0xF0,0xF7,0x04,0xE1,0x5C,0xED,0x28,0x55,0x7B,0xC1,0x07,0x52,0x2A,0x86,0x48, + 0xEB,0x8C,0xC2,0x55,0x56,0xDA,0x98,0xF3,0x5C,0x8F,0x21,0x70,0xDD,0xFB,0xA4,0x61, + 0x2F,0x57,0xE7,0x0B,0x70,0x2F,0x00,0x72,0x79,0x3C, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Testing Before Leaf */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Testing Intermediate CA 1 */ +/* Not Before: Oct 15 00:00:00 2016 GMT */ +unsigned char _datetest_before_leaf[1109]={ + 0x30,0x82,0x04,0x51,0x30,0x82,0x03,0x39,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x4C, + 0x3E,0x59,0xB4,0xB4,0x96,0x67,0xC6,0x13,0xB0,0xB4,0x67,0x03,0xB9,0x27,0xAE,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81, + 0x9C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x30,0x30,0x2E,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x27,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44, + 0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0x20,0x49,0x6E,0x74,0x65, + 0x72,0x6D,0x65,0x64,0x69,0x61,0x74,0x65,0x20,0x43,0x41,0x20,0x31,0x30,0x1E,0x17, + 0x0D,0x31,0x36,0x31,0x30,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D, + 0x31,0x37,0x31,0x30,0x31,0x32,0x31,0x38,0x33,0x38,0x30,0x38,0x5A,0x30,0x81,0x91, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E, + 0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70, + 0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45, + 0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x25,0x30,0x23,0x06,0x03, + 0x55,0x04,0x03,0x0C,0x1C,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x54,0x65, + 0x73,0x74,0x69,0x6E,0x67,0x20,0x42,0x65,0x66,0x6F,0x72,0x65,0x20,0x4C,0x65,0x61, + 0x66,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, + 0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01, + 0x01,0x00,0xB5,0x10,0x30,0xBE,0xE6,0x80,0x11,0x8B,0x5B,0xD8,0xDD,0xFE,0x66,0x19, + 0x8A,0xBC,0x01,0x29,0xA8,0x85,0x25,0xDB,0xF0,0x33,0xA9,0x5F,0x34,0xFC,0x7A,0xB7, + 0x19,0xD1,0x4A,0x7C,0xC9,0xBE,0x9C,0x8E,0xD3,0xB6,0xAA,0x48,0x97,0x53,0xBF,0x20, + 0x1D,0x81,0xAC,0x87,0xCA,0x60,0xC0,0xD5,0xC5,0x9E,0x86,0x48,0xA4,0xBD,0xB2,0x9E, + 0x88,0x92,0x2C,0x6C,0x8D,0xAC,0xC5,0x65,0x6C,0x5C,0x38,0x4E,0x1A,0xDC,0x00,0x70, + 0xCA,0x68,0x33,0x38,0x10,0xE0,0x5F,0xAC,0x8C,0x47,0x73,0xA5,0xC6,0xC7,0x2C,0x4C, + 0xB8,0xBB,0xE7,0x6C,0x42,0x6C,0x11,0x8C,0x2C,0x5E,0xBC,0x4C,0x87,0x1E,0xDE,0x2C, + 0xDE,0x40,0x7E,0xB9,0x32,0x7D,0x73,0x5B,0xF8,0x59,0x50,0x71,0x1E,0x43,0x06,0x89, + 0x09,0xC3,0x3B,0xC2,0xEB,0xD5,0x26,0x50,0x0D,0x98,0x09,0xE7,0x50,0x39,0x87,0x3C, + 0x06,0x5E,0xFF,0x4E,0xD4,0x9C,0x53,0xF9,0xBD,0x3E,0x5E,0x73,0x8B,0xBC,0xE5,0x3E, + 0xD2,0x96,0x4D,0xE5,0x1E,0x24,0x3D,0x34,0xA8,0x7C,0xB9,0x55,0xC0,0xA6,0x61,0x69, + 0xC2,0xCF,0x1F,0x67,0x45,0xC6,0x3A,0x56,0x1F,0xD2,0x93,0x32,0x3F,0x1A,0x60,0x6B, + 0x5B,0xCD,0x1A,0x6D,0x54,0x8C,0xF4,0x3F,0x4D,0x2B,0xA8,0xE7,0x2D,0xF8,0x12,0x39, + 0xCC,0xE6,0x41,0x35,0xD0,0x27,0xE5,0x20,0x15,0xFD,0xF0,0xC4,0xDF,0x7C,0x13,0x65, + 0x1B,0xD8,0x54,0x9D,0x68,0xDC,0xAA,0x51,0xD3,0x6C,0x4F,0x6C,0x16,0x83,0xC6,0x3F, + 0xF9,0x95,0xFF,0xE6,0x4B,0x23,0x4B,0xE1,0x5D,0x02,0xC5,0x14,0x03,0x3A,0x0A,0xFB, + 0xAB,0x1B,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x97,0x30,0x81,0x94,0x30,0x0C,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x13,0x06,0x03,0x55, + 0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16,0x82,0x14,0x74,0x65,0x73, + 0x74,0x73,0x65,0x72,0x76,0x65,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, + 0x6D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x52,0xBB,0x5E,0x78, + 0x5F,0x54,0xE6,0xD9,0x56,0x8B,0xE9,0x31,0xE7,0x9A,0x68,0xF2,0x96,0xB5,0x34,0xA4, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xE7,0xC3,0x06, + 0x5B,0x22,0xE0,0xEC,0xDA,0x8C,0x80,0x00,0xD9,0x0C,0xAC,0x0B,0x78,0xD4,0x68,0xC5, + 0xB7,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x2B,0x8A,0xFF,0xC4,0x3F,0x5C,0x0C,0x98,0x78,0x65,0xC2, + 0x5C,0x41,0x26,0xA1,0x1F,0x08,0xAB,0x6C,0xB2,0xF9,0xF3,0x6C,0x71,0xDA,0xD6,0xCB, + 0x40,0x2C,0xE8,0xA2,0x06,0x66,0xF0,0xD0,0x93,0x7B,0x0A,0x29,0xBB,0x9C,0x12,0xF5, + 0xE0,0xFF,0xC5,0x58,0xB2,0x95,0x25,0x29,0x1E,0x8B,0xFE,0xCC,0x8F,0xC7,0x5E,0x76, + 0x58,0x5E,0x27,0x29,0x47,0xC4,0x1B,0xC1,0xEB,0x22,0x2E,0xDB,0xE2,0x7F,0x38,0x09, + 0x14,0xAC,0x94,0xF6,0xFB,0x16,0x21,0x08,0x11,0x20,0x2B,0x2A,0xB5,0x22,0xD3,0x31, + 0x43,0xB0,0x4E,0xE8,0x33,0x3B,0xDC,0x10,0x56,0xDE,0x55,0xC8,0x9A,0x31,0x6C,0x52, + 0x6D,0xE9,0x79,0x70,0xEB,0xCD,0xD8,0x27,0x32,0xF6,0x30,0x7D,0x48,0xAF,0xB5,0xD8, + 0xBD,0xF3,0x68,0xEC,0xB0,0x7F,0x5A,0x52,0x9A,0x5A,0xF1,0x8E,0xCD,0x94,0x37,0x16, + 0xA2,0x75,0x3C,0x0E,0xDA,0xDE,0x12,0x33,0xAE,0x04,0xAB,0x27,0xDE,0xD1,0x60,0x13, + 0x0C,0x67,0x07,0x2A,0x7C,0xF2,0x46,0x74,0x3C,0x79,0x9B,0x6D,0xF3,0x2D,0x2E,0x69, + 0xDD,0xF4,0xEA,0xEC,0xD2,0xDD,0x85,0x79,0x77,0xCD,0x20,0xA9,0x19,0x3F,0x99,0xBB, + 0xA4,0x8A,0x78,0xBE,0x0E,0xEC,0xB9,0x91,0xAD,0xB6,0xFC,0xFB,0xCF,0xCF,0x71,0xBF, + 0x3C,0x13,0x2F,0xEB,0xD8,0xC8,0x22,0xC3,0x07,0xBB,0xCB,0x95,0x39,0xD4,0x61,0xDF, + 0x4F,0x87,0x41,0xCA,0xDD,0xD8,0x54,0xD7,0xDE,0x9C,0x13,0xF6,0x69,0x90,0xEE,0xE8, + 0xF8,0x0B,0x83,0x38,0x31,0x4C,0x67,0x96,0xF6,0x4A,0x77,0x00,0x41,0x11,0x91,0x77, + 0xC2,0x05,0x60,0x30,0x8C, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Testing After Leaf */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Testing Intermediate CA 1 */ +/* Not Before: Dec 1 00:01:00 2016 GMT */ +unsigned char _datetest_after_leaf[1108]={ + 0x30,0x82,0x04,0x50,0x30,0x82,0x03,0x38,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x4C, + 0x3E,0x59,0xB4,0xB4,0x96,0x67,0xC6,0x13,0xB0,0xB4,0x67,0x03,0xB9,0x27,0xAF,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81, + 0x9C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x30,0x30,0x2E,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x27,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44, + 0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0x20,0x49,0x6E,0x74,0x65, + 0x72,0x6D,0x65,0x64,0x69,0x61,0x74,0x65,0x20,0x43,0x41,0x20,0x31,0x30,0x1E,0x17, + 0x0D,0x31,0x36,0x31,0x32,0x30,0x31,0x30,0x30,0x30,0x31,0x30,0x30,0x5A,0x17,0x0D, + 0x31,0x37,0x31,0x30,0x31,0x32,0x31,0x38,0x33,0x38,0x34,0x37,0x5A,0x30,0x81,0x90, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E, + 0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70, + 0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45, + 0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x24,0x30,0x22,0x06,0x03, + 0x55,0x04,0x03,0x0C,0x1B,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x54,0x65, + 0x73,0x74,0x69,0x6E,0x67,0x20,0x41,0x66,0x74,0x65,0x72,0x20,0x4C,0x65,0x61,0x66, + 0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, + 0x00,0xE9,0xD1,0x18,0x04,0x41,0x52,0x27,0x4F,0x91,0x31,0xBD,0xF2,0x9F,0x11,0x8F, + 0x50,0xF6,0x5C,0xD2,0x6F,0x8B,0x7F,0xDA,0x20,0x50,0x92,0x7F,0x7D,0x61,0x6E,0x52, + 0x74,0xE1,0x66,0x14,0x70,0xAD,0x9E,0x84,0xF2,0x71,0x23,0xC7,0xC6,0xFD,0x58,0xE3, + 0x5B,0x37,0xFF,0x8F,0x72,0xC9,0x4D,0x71,0x20,0xA0,0x7F,0x23,0xD5,0xF5,0xC1,0x37, + 0x01,0x57,0x1C,0x8F,0x8E,0xD1,0x59,0xED,0x26,0x41,0xED,0xE7,0x47,0x86,0xCE,0xBB, + 0x27,0x45,0xAC,0x08,0x51,0xAB,0x3E,0xD8,0x92,0x98,0x6D,0x88,0x24,0xD1,0x56,0x8D, + 0xED,0x81,0xCE,0xBA,0x8F,0x9E,0x8E,0x9E,0x81,0x29,0xC5,0x9C,0x32,0x75,0xC6,0x5D, + 0xDE,0x1E,0x61,0x38,0xD7,0x89,0x41,0x17,0xAC,0xDC,0xB9,0x98,0xC4,0x7E,0xA7,0xC0, + 0x3B,0xB9,0xF2,0xA0,0xB0,0x88,0x3E,0x84,0xBC,0x28,0x1D,0x5B,0x35,0x92,0xCC,0xCB, + 0x9B,0x4E,0xD3,0xF2,0x2F,0x9B,0x77,0xC5,0xB1,0x08,0x18,0x86,0xF1,0x1E,0x47,0xDD, + 0x9A,0x94,0x5E,0xEF,0xE7,0x32,0xAD,0xD0,0x3C,0x65,0x81,0x5D,0xD7,0x94,0x56,0xCA, + 0x95,0xEA,0x4C,0x87,0xE1,0x48,0xC0,0xB9,0xA7,0x23,0xED,0x0F,0xFC,0x56,0x38,0x10, + 0x4E,0x7F,0xB3,0x73,0x0B,0x3A,0xCB,0xB9,0x89,0x15,0xA9,0xBD,0x81,0xB9,0x9F,0xD9, + 0x53,0x2E,0x73,0x95,0x2D,0xA9,0x81,0x85,0xA7,0xC2,0x0B,0xA2,0xDE,0x6F,0x41,0x72, + 0x05,0x50,0xE5,0xB4,0x10,0xD4,0xE7,0xF2,0x76,0x48,0xCC,0x2A,0x2C,0x44,0x74,0xF1, + 0x5E,0x0A,0xB5,0x02,0x55,0x25,0x54,0x29,0x92,0x6F,0x0A,0x78,0x33,0xBB,0x8C,0x01, + 0x1F,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x97,0x30,0x81,0x94,0x30,0x0C,0x06,0x03, + 0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D, + 0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x13,0x06,0x03,0x55,0x1D, + 0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30, + 0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16,0x82,0x14,0x74,0x65,0x73,0x74, + 0x73,0x65,0x72,0x76,0x65,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x1F,0xBA,0x32,0x4F,0x63, + 0xBA,0x31,0x1E,0xA3,0x91,0xFC,0x59,0x84,0x62,0xA9,0x52,0x22,0xC6,0xF1,0xAB,0x30, + 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xE7,0xC3,0x06,0x5B, + 0x22,0xE0,0xEC,0xDA,0x8C,0x80,0x00,0xD9,0x0C,0xAC,0x0B,0x78,0xD4,0x68,0xC5,0xB7, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x86,0xFF,0xC5,0xB6,0xB6,0x57,0x9A,0x6B,0xA3,0x83,0xFA,0x97, + 0xA3,0xCB,0x4F,0xA3,0x44,0xB9,0x0A,0x89,0xC7,0x09,0xE3,0x9F,0x61,0x45,0x80,0x11, + 0x1C,0x8F,0x81,0x12,0x96,0x55,0x91,0xD7,0x93,0x70,0x7A,0x24,0x1D,0xA5,0xFE,0x8C, + 0xD9,0x0C,0x74,0x2A,0xB8,0x0C,0xF9,0xBC,0xA7,0xFE,0xC8,0x03,0x1F,0xC8,0x55,0xEF, + 0xC2,0x54,0x81,0x4D,0xA1,0x88,0x1F,0x88,0x74,0x12,0xE3,0xA2,0x58,0x9D,0x66,0x89, + 0x8F,0xBB,0x0F,0xB7,0xE5,0x9F,0xF0,0x81,0x0E,0xFC,0x0E,0x3D,0x33,0xB1,0x9D,0xDD, + 0x82,0x3E,0xF8,0xF2,0x10,0x50,0x1B,0xEB,0x19,0x44,0x5F,0x74,0x2E,0x98,0x68,0x3C, + 0xF7,0x08,0x2F,0x8B,0xB7,0x67,0x14,0xC5,0xC1,0x33,0xBB,0xA8,0xDF,0x47,0xFE,0x3D, + 0x24,0x36,0xD3,0xA7,0x8F,0xAC,0x9E,0x2E,0x49,0xFC,0xB1,0x68,0x93,0x9E,0x10,0x99, + 0x35,0x7F,0xC6,0xBF,0xFD,0x90,0x32,0xCB,0x73,0x57,0x65,0x11,0xDF,0xEB,0x64,0x23, + 0xDD,0x67,0xCC,0x8A,0x00,0xDA,0x0F,0x09,0x66,0xEE,0x72,0xCC,0x73,0x93,0x92,0xC5, + 0x53,0xF4,0x60,0xF1,0xAB,0x3E,0x8B,0x4B,0xEF,0x2C,0xCF,0xDA,0x70,0x4D,0x50,0xB0, + 0x10,0x87,0x97,0x87,0x26,0xA2,0x39,0x16,0xD2,0xEA,0xDC,0x42,0xE7,0xF0,0xED,0x53, + 0xD5,0xFF,0x61,0x1E,0x93,0x22,0xD7,0x59,0xDA,0xAC,0xCD,0x81,0x9E,0xD8,0x72,0x13, + 0x52,0x6B,0xEE,0x86,0xA1,0x37,0x6C,0xBA,0xA2,0x60,0xB2,0xCC,0xA1,0x51,0xA8,0x57, + 0x80,0xCA,0x9C,0xAF,0x03,0xAB,0xBD,0xC3,0x13,0xAA,0x46,0xBD,0x3B,0x99,0xE6,0x6F, + 0x7B,0x93,0x90,0xB6, +}; + +#endif /* _TRUSTTESTS_ALLOWLIST_BLOCKLIST_TESTS_ */ diff --git a/tests/TrustTests/EvaluationTests/CAIssuerTests.m b/tests/TrustTests/EvaluationTests/CAIssuerTests.m new file mode 100644 index 00000000..da4d364f --- /dev/null +++ b/tests/TrustTests/EvaluationTests/CAIssuerTests.m @@ -0,0 +1,176 @@ +/* +* Copyright (c) 2006-2019 Apple Inc. All Rights Reserved. +*/ + +#include +#import +#include +#include +#include +#include +#include +#include +#include + +#import "../TestMacroConversions.h" +#import "../TrustEvaluationTestHelpers.h" +#import "TrustEvaluationTestCase.h" + +#import "CAIssuerTests_data.h" + +@interface CAIssuerTests: TrustEvaluationTestCase +@end + +@implementation CAIssuerTests + +#if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE +- (void) test_aia +{ + if (!ping_host("crt.comodoca.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + + SecCertificateRef ovh = NULL, comodo_ev = NULL, comodo_aia = NULL; + CFMutableArrayRef certs = NULL, policies = NULL; + SecPolicyRef sslPolicy = NULL, revPolicy = NULL; + CFDateRef verifyDate = NULL; + SecTrustRef trust = NULL; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + /* Initialize common variables */ + isnt(ovh = SecCertificateCreateWithBytes(NULL, ovh_certificate, + sizeof(ovh_certificate)), NULL, "create ovh cert"); + isnt(comodo_ev = SecCertificateCreateWithBytes(NULL, comodo_ev_certificate, + sizeof(comodo_ev_certificate)), NULL, "create comodo_ev cert"); + isnt(comodo_aia = SecCertificateCreateWithBytes(NULL, + comodo_aia_certificate, sizeof(comodo_aia_certificate)), NULL, + "create comodo_aia cert"); + certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + policies = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + sslPolicy = SecPolicyCreateSSL(false, NULL); // For now, use SSL client policy to avoid SHA-1 deprecation + revPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); + CFArrayAppendValue(policies, sslPolicy); + CFArrayAppendValue(policies, revPolicy); + /* May 9th 2018. */ + verifyDate = CFDateCreate(NULL, 547600500); + + /* First run with no intermediate and disallow network fetching. + * Evaluation should fail because it couldn't get the intermediate. */ + CFArrayAppendValue(certs, ovh); + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), + "create trust"); + ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); + ok_status(SecTrustSetNetworkFetchAllowed(trust, false), "set no network"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, + "trust is kSecTrustResultRecoverableTrustFailure"); + + /* Now allow networking. Evaluation should succeed after fetching + * the intermediate. */ + ok_status(SecTrustSetNetworkFetchAllowed(trust, true), "set allow network"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultUnspecified, + "trust is kSecTrustResultUnspecified"); + CFReleaseNull(trust); + + /* Common variable cleanup. */ + CFReleaseSafe(sslPolicy); + CFReleaseSafe(revPolicy); + CFReleaseSafe(certs); + CFReleaseSafe(policies); + CFReleaseSafe(comodo_aia); + CFReleaseSafe(comodo_ev); + CFReleaseSafe(ovh); + CFReleaseSafe(verifyDate); +} + +- (void) test_aia_https { + SecCertificateRef leaf = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFArrayRef certs = NULL; + CFDateRef verifyDate = NULL; + CFErrorRef error = NULL; + + leaf = SecCertificateCreateWithBytes(NULL, _caissuer_https, sizeof(_caissuer_https)); + const void *v_certs[] = { leaf }; + + certs = CFArrayCreate(NULL, v_certs, 1, &kCFTypeArrayCallBacks); + policy = SecPolicyCreateSSL(true, CFSTR("example.com")); + require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); + + verifyDate = CFDateCreate(NULL, 546700000.0); // April 29, 2018 at 6:06:40 AM PDT + require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); + + /* Evaluate trust. This cert does not chain to anything trusted and we can't fetch an + * intermediate because the URI is https. */ + is(SecTrustEvaluateWithError(trust, &error), false, "leaf with missing intermediate and https CAIssuer URI succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecCreateChainFailed, "got wrong error code for revoked cert, got %ld, expected %d", + (long)CFErrorGetCode(error), errSecCreateChainFailed); + } else { + fail("expected trust evaluation to fail and it did not."); + } + +errOut: + CFReleaseNull(leaf); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(certs); + CFReleaseNull(verifyDate); + CFReleaseNull(error); +} +#else /* TARGET_OS_WATCH || TARGET_OS_BRIDGE */ +- (void) testNoNetworking +{ + SecCertificateRef ovh = NULL, comodo_ev = NULL, comodo_aia = NULL; + CFMutableArrayRef certs = NULL, policies = NULL; + SecPolicyRef sslPolicy = NULL, revPolicy = NULL; + CFDateRef verifyDate = NULL; + SecTrustRef trust = NULL; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + /* Initialize common variables */ + isnt(ovh = SecCertificateCreateWithBytes(NULL, ovh_certificate, + sizeof(ovh_certificate)), NULL, "create ovh cert"); + isnt(comodo_ev = SecCertificateCreateWithBytes(NULL, comodo_ev_certificate, + sizeof(comodo_ev_certificate)), NULL, "create comodo_ev cert"); + isnt(comodo_aia = SecCertificateCreateWithBytes(NULL, + comodo_aia_certificate, sizeof(comodo_aia_certificate)), NULL, + "create comodo_aia cert"); + certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + policies = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + sslPolicy = SecPolicyCreateSSL(false, NULL); // For now, use SSL client policy to avoid SHA-1 deprecation + revPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); + CFArrayAppendValue(policies, sslPolicy); + CFArrayAppendValue(policies, revPolicy); + /* May 9th 2018. */ + verifyDate = CFDateCreate(NULL, 547600500); + + /* Evaluation should fail because it couldn't get the intermediate. */ + CFArrayAppendValue(certs, ovh); + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), + "create trust"); + ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, + "trust is kSecTrustResultRecoverableTrustFailure"); + + /* Common variable cleanup. */ + CFReleaseSafe(sslPolicy); + CFReleaseSafe(revPolicy); + CFReleaseSafe(certs); + CFReleaseSafe(policies); + CFReleaseSafe(comodo_aia); + CFReleaseSafe(comodo_ev); + CFReleaseSafe(ovh); + CFReleaseSafe(verifyDate); +} +#endif + +@end diff --git a/tests/TrustTests/EvaluationTests/CAIssuerTests_data.h b/tests/TrustTests/EvaluationTests/CAIssuerTests_data.h new file mode 100644 index 00000000..5ccd431a --- /dev/null +++ b/tests/TrustTests/EvaluationTests/CAIssuerTests_data.h @@ -0,0 +1,413 @@ +/* +* Copyright (c) 2006-2019 Apple Inc. All Rights Reserved. +*/ + +#ifndef _TRUSTTESTS_CA_ISSUER_TESTS_H_ +#define _TRUSTTESTS_CA_ISSUER_TESTS_H_ + +/* subject:/serialNumber=424761419/jurisdictionC=FR/businessCategory=Private Organization/C=FR/postalCode=59100/ST=Nord/L=Roubaix/street=2 rue Kellermann/O=OVH SAS/OU=IT/OU=COMODO EV SSL/CN=ovh.com */ +/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ +static unsigned char ovh_certificate[1884]={ + 0x30,0x82,0x07,0x58,0x30,0x82,0x06,0x40,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x40, + 0x46,0x47,0xDC,0xC2,0x4B,0x04,0x42,0xD4,0x89,0x8D,0x08,0x4D,0x4B,0xC2,0x01,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81, + 0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, + 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, + 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, + 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, + 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, + 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55, + 0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45, + 0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, + 0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x37,0x30,0x34,0x32,0x38,0x30,0x30,0x30, + 0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x39,0x30,0x34,0x32,0x38,0x32,0x33,0x35,0x39, + 0x35,0x39,0x5A,0x30,0x81,0xEA,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x05,0x13, + 0x09,0x34,0x32,0x34,0x37,0x36,0x31,0x34,0x31,0x39,0x31,0x13,0x30,0x11,0x06,0x0B, + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,0x13,0x02,0x46,0x52,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0F,0x13,0x14,0x50,0x72,0x69,0x76,0x61,0x74, + 0x65,0x20,0x4F,0x72,0x67,0x61,0x6E,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x46,0x52,0x31,0x0E,0x30,0x0C,0x06, + 0x03,0x55,0x04,0x11,0x13,0x05,0x35,0x39,0x31,0x30,0x30,0x31,0x0D,0x30,0x0B,0x06, + 0x03,0x55,0x04,0x08,0x13,0x04,0x4E,0x6F,0x72,0x64,0x31,0x10,0x30,0x0E,0x06,0x03, + 0x55,0x04,0x07,0x13,0x07,0x52,0x6F,0x75,0x62,0x61,0x69,0x78,0x31,0x19,0x30,0x17, + 0x06,0x03,0x55,0x04,0x09,0x13,0x10,0x32,0x20,0x72,0x75,0x65,0x20,0x4B,0x65,0x6C, + 0x6C,0x65,0x72,0x6D,0x61,0x6E,0x6E,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0A, + 0x13,0x07,0x4F,0x56,0x48,0x20,0x53,0x41,0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x0B,0x13,0x02,0x49,0x54,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x0B,0x13, + 0x0D,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x45,0x56,0x20,0x53,0x53,0x4C,0x31,0x10, + 0x30,0x0E,0x06,0x03,0x55,0x04,0x03,0x13,0x07,0x6F,0x76,0x68,0x2E,0x63,0x6F,0x6D, + 0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, + 0x00,0x93,0xA1,0x5D,0x05,0x5F,0x1A,0x26,0x56,0x3D,0xDC,0xC2,0x7C,0x1B,0xA1,0x7A, + 0x63,0x16,0x4F,0xBD,0xE0,0x77,0x85,0x04,0xB0,0x9B,0x49,0xE9,0x2B,0x5C,0xB1,0x51, + 0xFD,0x8A,0x14,0x51,0xC7,0xD9,0x50,0xDE,0x64,0x2F,0xFE,0x8C,0x27,0xC3,0x01,0x48, + 0x64,0x7C,0x85,0x3F,0x93,0xD4,0x09,0xE6,0x42,0xDF,0xC1,0xE4,0xEB,0x6A,0xC0,0x87, + 0x90,0xA5,0xF6,0x9C,0xD4,0x6B,0x08,0x77,0xFB,0x56,0x44,0x2B,0x8A,0xE0,0x05,0x73, + 0x14,0x6B,0x02,0x7D,0x76,0x44,0x7B,0x3E,0xA6,0xE5,0x23,0xA9,0xE1,0x8F,0x99,0xDD, + 0x15,0xCD,0xD9,0xD9,0x6D,0xB9,0x95,0x5B,0xE8,0xB6,0xE2,0x52,0xDD,0xF0,0xB0,0x80, + 0x1B,0xC1,0x95,0x4B,0x2C,0x9D,0x5E,0x8D,0x02,0x6B,0x59,0x6C,0x26,0x8B,0xC3,0x19, + 0x0D,0x3E,0xA8,0x34,0xD0,0x43,0x81,0xD7,0xBD,0xB3,0xA7,0x04,0xE1,0x05,0x82,0xA6, + 0x1F,0x4D,0x70,0x67,0x05,0x96,0x88,0xE8,0xE9,0x2E,0x95,0xD2,0x36,0x75,0xD6,0xC8, + 0x0C,0x59,0xBF,0x9F,0x1F,0x9F,0xB4,0xFF,0xF0,0x10,0x8C,0xC3,0xE6,0x8B,0x9F,0xE2, + 0x8E,0x00,0x60,0x58,0xCB,0x6F,0xAD,0x84,0x7B,0xA5,0x36,0xDB,0xB2,0xA4,0xEB,0xC6, + 0xC8,0xD8,0x61,0x6E,0x4A,0xDC,0x5C,0x3E,0x2C,0x33,0xCB,0x1E,0x16,0x8B,0x8C,0xA3, + 0x5F,0x0F,0x30,0x4E,0x0A,0x5D,0xA0,0x53,0x7C,0xCE,0xAB,0x29,0x9A,0xC6,0x64,0xC5, + 0x5A,0xD7,0x94,0x3D,0x81,0xB1,0x05,0x3F,0x2A,0x6D,0xD7,0xB8,0x9D,0xF1,0x6D,0x13, + 0xFD,0x82,0xB4,0xF9,0x88,0x77,0xAB,0xB8,0x2C,0x7A,0x81,0x6E,0x68,0xFF,0x6E,0x04, + 0xC1,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x03,0x4E,0x30,0x82,0x03,0x4A,0x30,0x1F, + 0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x39,0xDA,0xFF,0xCA,0x28, + 0x14,0x8A,0xA8,0x74,0x13,0x08,0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x0B,0x0F,0xAD,0xA6,0xC3,0xBF, + 0x98,0xA1,0xEC,0xCD,0x20,0xB3,0x2C,0x75,0x03,0x56,0x3A,0xA6,0xD3,0xE6,0x30,0x0E, + 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x0C, + 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03, + 0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55, + 0x1D,0x20,0x04,0x3F,0x30,0x3D,0x30,0x3B,0x06,0x0C,0x2B,0x06,0x01,0x04,0x01,0xB2, + 0x31,0x01,0x02,0x01,0x05,0x01,0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x02,0x01,0x16,0x1D,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65, + 0x63,0x75,0x72,0x65,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F, + 0x43,0x50,0x53,0x30,0x56,0x06,0x03,0x55,0x1D,0x1F,0x04,0x4F,0x30,0x4D,0x30,0x4B, + 0xA0,0x49,0xA0,0x47,0x86,0x45,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C, + 0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F, + 0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x56, + 0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x63,0x75,0x72,0x65,0x53, + 0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x6C,0x30,0x81,0x87,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x7B,0x30,0x79,0x30,0x51,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x45,0x68,0x74,0x74,0x70,0x3A,0x2F, + 0x2F,0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F, + 0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x45,0x78,0x74,0x65,0x6E, + 0x64,0x65,0x64,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x63, + 0x75,0x72,0x65,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74, + 0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63, + 0x61,0x2E,0x63,0x6F,0x6D,0x30,0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16, + 0x82,0x07,0x6F,0x76,0x68,0x2E,0x63,0x6F,0x6D,0x82,0x0B,0x77,0x77,0x77,0x2E,0x6F, + 0x76,0x68,0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01,0x7E,0x06,0x0A,0x2B,0x06,0x01,0x04, + 0x01,0xD6,0x79,0x02,0x04,0x02,0x04,0x82,0x01,0x6E,0x04,0x82,0x01,0x6A,0x01,0x68, + 0x00,0x76,0x00,0xA4,0xB9,0x09,0x90,0xB4,0x18,0x58,0x14,0x87,0xBB,0x13,0xA2,0xCC, + 0x67,0x70,0x0A,0x3C,0x35,0x98,0x04,0xF9,0x1B,0xDF,0xB8,0xE3,0x77,0xCD,0x0E,0xC8, + 0x0D,0xDC,0x10,0x00,0x00,0x01,0x5B,0xB5,0x7B,0xC8,0x2D,0x00,0x00,0x04,0x03,0x00, + 0x47,0x30,0x45,0x02,0x21,0x00,0xD5,0x1B,0x6C,0xAE,0x75,0x46,0x62,0x0C,0x8B,0x2E, + 0x14,0xB1,0xDE,0x7C,0xA5,0xFE,0x5C,0x4F,0x3E,0xB0,0xFF,0xFF,0x33,0xA2,0x84,0x58, + 0x51,0x57,0x97,0x09,0xAF,0x09,0x02,0x20,0x49,0xD7,0x12,0x12,0x6C,0x2A,0x00,0x21, + 0x5E,0x48,0xF8,0xD0,0xF2,0xA5,0x81,0x2A,0x4E,0xE9,0x22,0x0A,0x4E,0x46,0x8F,0xDB, + 0xA5,0x9C,0x4B,0x43,0x7E,0x51,0x24,0xE4,0x00,0x76,0x00,0x56,0x14,0x06,0x9A,0x2F, + 0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC,0x99, + 0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x5B,0xB5, + 0x7B,0xC5,0xC8,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x36,0xA9,0x1D, + 0x52,0x63,0x04,0x11,0x1F,0x65,0xC6,0x97,0x7C,0x17,0xFC,0x17,0x8D,0xDB,0x9D,0xA7, + 0xB7,0x84,0x66,0x03,0x55,0x95,0x7D,0x42,0x39,0x98,0x60,0xDE,0x19,0x02,0x21,0x00, + 0x8B,0xB7,0x16,0xC0,0x20,0x17,0xBF,0x31,0x36,0xBD,0xBC,0x1C,0x12,0x61,0x42,0xC0, + 0x5C,0x19,0x97,0x0A,0xFA,0x85,0xDB,0x5D,0xC3,0x65,0xBE,0x18,0xBF,0x89,0x6F,0xB9, + 0x00,0x76,0x00,0xEE,0x4B,0xBD,0xB7,0x75,0xCE,0x60,0xBA,0xE1,0x42,0x69,0x1F,0xAB, + 0xE1,0x9E,0x66,0xA3,0x0F,0x7E,0x5F,0xB0,0x72,0xD8,0x83,0x00,0xC4,0x7B,0x89,0x7A, + 0xA8,0xFD,0xCB,0x00,0x00,0x01,0x5B,0xB5,0x7B,0xC7,0xFA,0x00,0x00,0x04,0x03,0x00, + 0x47,0x30,0x45,0x02,0x21,0x00,0xF8,0xFE,0x02,0xC9,0xAF,0x02,0x18,0xF4,0x12,0x00, + 0x39,0x3C,0x15,0xE0,0x9C,0x78,0x04,0x19,0x55,0xAE,0x8F,0xB4,0x22,0xB9,0x08,0x66, + 0x9E,0x21,0x3E,0xF0,0x7D,0xC6,0x02,0x20,0x47,0x45,0x31,0xC7,0x2C,0xC3,0xBE,0xC7, + 0x5B,0xD8,0x31,0x0A,0xD6,0xAF,0x9D,0xAF,0x04,0x45,0xAA,0x51,0x7D,0x43,0xEF,0x35, + 0x4D,0x81,0xB3,0x0A,0x2F,0x8D,0xD8,0x61,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6C,0x8E,0xB5,0x58, + 0x8A,0xC5,0x66,0xAC,0x99,0x68,0xF9,0x80,0x68,0x8E,0xC5,0x10,0xF7,0xD7,0x37,0x5E, + 0x09,0x8C,0x6B,0xCF,0x30,0x2B,0x98,0x3F,0x76,0x4D,0x69,0xBA,0xE8,0x61,0x1D,0xDE, + 0x1A,0x14,0x4F,0x5A,0x0B,0x54,0x0F,0x66,0xEF,0xB9,0xB3,0x51,0x6C,0x9B,0x86,0x1D, + 0xB9,0x13,0xC8,0x54,0x24,0x6C,0x82,0x6E,0x4B,0x3C,0x53,0xC7,0x7D,0x0B,0x40,0x4A, + 0x7E,0x23,0xF2,0x79,0x6B,0xC3,0xFF,0x9D,0xDF,0xC0,0x16,0x7B,0xFF,0x7B,0x04,0xC9, + 0xE0,0xEB,0x3F,0x28,0xC6,0xD2,0x79,0xEE,0xAE,0x7E,0x38,0x5F,0x0D,0xDF,0x71,0xE7, + 0xAA,0x38,0x7E,0xF3,0x28,0xE8,0xB2,0xAC,0x69,0xB9,0x69,0xD4,0x05,0x8E,0xF1,0x00, + 0x71,0x77,0x97,0x7F,0x94,0x36,0x45,0xE5,0x9C,0x15,0xA3,0xF1,0x40,0xD7,0xB5,0xEA, + 0x95,0x56,0x75,0x60,0x86,0xFB,0xCD,0xB7,0x81,0x5A,0x34,0x1A,0x83,0x1E,0xC2,0x50, + 0xA2,0x57,0x16,0x13,0x53,0x95,0xFA,0x95,0xD0,0x64,0x1E,0x09,0x45,0x50,0x05,0x63, + 0x3A,0x86,0xB2,0x1D,0x9B,0x19,0x0E,0x89,0x7E,0x75,0x17,0xDA,0xC5,0x4D,0x4F,0x71, + 0x55,0x82,0x3E,0x5F,0x41,0x25,0x2F,0x86,0x9E,0x3D,0xF1,0x32,0xFA,0x77,0x7C,0x30, + 0x6C,0x50,0x2F,0xE7,0x11,0x7B,0xE1,0x3F,0xA8,0x2E,0xEF,0xAC,0x36,0x94,0x8F,0xF0, + 0x92,0xB4,0xCA,0x1A,0x53,0x8E,0x12,0x26,0x48,0xC4,0xA8,0x25,0x19,0x96,0x19,0x11, + 0xA2,0xA2,0x48,0xEB,0x8C,0x12,0x59,0x7F,0xCE,0xFC,0x4B,0xC9,0x19,0x10,0x61,0x2B, + 0xB3,0xA6,0x6B,0xB4,0xBA,0x68,0xB9,0x22,0x58,0xE4,0x82,0x27, +}; + +/* This is the cert the ssl server returns to us. */ +/* subject:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ +/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority */ +static unsigned char comodo_ev_certificate[1554]={ + 0x30,0x82,0x06,0x0E,0x30,0x82,0x03,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x06, + 0xA7,0x43,0x80,0xD4,0xEB,0xFE,0xD4,0x35,0xB5,0xA3,0xF7,0xE1,0x6A,0xBD,0xD8,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x30,0x81, + 0x85,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, + 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, + 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, + 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, + 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, + 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x2B,0x30,0x29,0x06,0x03,0x55, + 0x04,0x03,0x13,0x22,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x43, + 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74, + 0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x31,0x32,0x30,0x32,0x31,0x32, + 0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x37,0x30,0x32,0x31,0x31,0x32, + 0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13, + 0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72,0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73, + 0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61, + 0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11, + 0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43,0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65, + 0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F, + 0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20, + 0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72, + 0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, + 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0x95,0x56,0xDE,0x54, + 0xB4,0xDF,0xD5,0x02,0x49,0x7B,0xD1,0x5B,0x5C,0xA2,0xB2,0x1E,0x8F,0x9C,0x2B,0x62, + 0x4C,0x2B,0x8D,0x12,0x28,0xF3,0x1A,0x95,0xA3,0xC6,0x10,0xFD,0x29,0xDE,0xE1,0x9F, + 0x0B,0x38,0x40,0x93,0xD1,0xEF,0x6E,0x95,0x10,0xFC,0xE1,0x90,0x17,0x77,0x2C,0xEE, + 0x75,0x3E,0x7B,0x63,0xEC,0x61,0x92,0x6E,0x4F,0x3B,0xAB,0x80,0x49,0x6B,0xDF,0x00, + 0xEA,0x03,0x00,0x7F,0x2F,0x75,0xD5,0x28,0x2F,0xEC,0x56,0x67,0x8F,0x80,0x83,0xA3, + 0xBD,0xDC,0x03,0x99,0x93,0x8B,0x94,0x91,0x56,0x5B,0xA1,0xB8,0x6A,0x3A,0x3F,0x06, + 0xBD,0x0E,0x92,0xCC,0x60,0x9C,0xFD,0xB5,0xE0,0x9F,0x66,0x30,0x5F,0xDB,0xE6,0x94, + 0xF0,0x95,0x6A,0xAF,0xC8,0x8A,0xAF,0x80,0xD9,0xE6,0x88,0x39,0x01,0x7C,0x1C,0xC0, + 0xC5,0x2A,0xF7,0x7B,0x95,0xA0,0xF2,0x76,0xAB,0x6D,0x9B,0x72,0x39,0x30,0xEB,0xD1, + 0x57,0x55,0x01,0x9D,0x58,0x11,0x9D,0x7C,0x6D,0x84,0x8F,0x49,0xE8,0x9D,0x09,0xFC, + 0x3C,0xFD,0x0A,0x4A,0x76,0x14,0x21,0x5C,0x16,0x73,0x40,0x23,0x19,0x74,0xC3,0xBA, + 0x58,0x0A,0xA6,0x96,0x2E,0xDE,0x36,0xE5,0x9F,0xD0,0xC2,0xF0,0xE1,0xE0,0xC1,0x62, + 0xE3,0xC2,0x18,0x45,0x19,0x51,0xAA,0x17,0x1E,0xE8,0x23,0x75,0xD4,0xC8,0xD0,0x96, + 0x13,0xFF,0xC7,0x24,0xD1,0x8C,0x0B,0x27,0xAE,0x9E,0x7A,0xDC,0x3A,0x61,0x63,0x60, + 0x88,0x97,0x2D,0x5D,0x05,0x0B,0xE5,0x3B,0xEB,0xAE,0xCE,0x3A,0x47,0x73,0x76,0xA8, + 0xFA,0x2C,0xDD,0xC0,0x87,0x17,0xE9,0xAC,0x30,0x99,0xF8,0x1F,0x02,0x03,0x01,0x00, + 0x01,0xA3,0x82,0x01,0x69,0x30,0x82,0x01,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, + 0x04,0x18,0x30,0x16,0x80,0x14,0xBB,0xAF,0x7E,0x02,0x3D,0xFA,0xA6,0xF1,0x3C,0x84, + 0x8E,0xAD,0xEE,0x38,0x98,0xEC,0xD9,0x32,0x32,0xD4,0x30,0x1D,0x06,0x03,0x55,0x1D, + 0x0E,0x04,0x16,0x04,0x14,0x39,0xDA,0xFF,0xCA,0x28,0x14,0x8A,0xA8,0x74,0x13,0x08, + 0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, + 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13, + 0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3E,0x06, + 0x03,0x55,0x1D,0x20,0x04,0x37,0x30,0x35,0x30,0x33,0x06,0x04,0x55,0x1D,0x20,0x00, + 0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1D, + 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65,0x63,0x75,0x72,0x65,0x2E,0x63, + 0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x4C,0x06, + 0x03,0x55,0x1D,0x1F,0x04,0x45,0x30,0x43,0x30,0x41,0xA0,0x3F,0xA0,0x3D,0x86,0x3B, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x63,0x6F,0x6D,0x6F,0x64, + 0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53, + 0x41,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x41,0x75, + 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2E,0x63,0x72,0x6C,0x30,0x71,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3B,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D, + 0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x41,0x64,0x64,0x54,0x72,0x75, + 0x73,0x74,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, + 0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x03,0x82,0x02, + 0x01,0x00,0x44,0x42,0x9D,0x41,0x51,0x2B,0x48,0x88,0x5D,0x97,0x9B,0x79,0x5E,0x11, + 0x01,0x4A,0x52,0x19,0x7B,0x41,0x2C,0xC7,0x89,0x3C,0xD0,0x72,0xDC,0x85,0xFA,0x58, + 0xAF,0xD5,0x25,0xE4,0x13,0xF8,0x58,0x65,0x67,0x9F,0x0D,0xFF,0x57,0x8B,0xA9,0x85, + 0x5E,0xCA,0xA6,0x4B,0xB0,0xA7,0xB2,0x2D,0xE0,0x8C,0x22,0xCD,0xFB,0xFF,0x79,0xA4, + 0x8C,0x2B,0x8D,0xFE,0x02,0x3D,0x24,0xDE,0xA9,0x5D,0x5F,0xE4,0x0F,0x47,0xD0,0xDB, + 0x66,0x25,0x3E,0x87,0x47,0x0C,0xAE,0x22,0xC5,0x50,0x22,0x84,0xD7,0xED,0x4A,0x59, + 0x1A,0xF6,0x93,0xA5,0x93,0xB0,0xE0,0x1B,0x81,0xF2,0x56,0xC4,0xC8,0x10,0x53,0xE4, + 0xD4,0x76,0xB1,0xD1,0x5B,0x69,0x4B,0x77,0xB2,0xE0,0x4F,0xC4,0x84,0xE7,0xD4,0xA0, + 0x50,0xEE,0x3C,0xFA,0x44,0xFC,0xD0,0x57,0xB9,0xE1,0x28,0x53,0xFD,0x53,0xCD,0xDC, + 0xB9,0x1F,0x7A,0x40,0xBD,0x30,0x3F,0xD8,0x6C,0xD2,0xF3,0xE7,0x07,0x9F,0x1F,0x22, + 0xB5,0xEA,0x22,0x71,0xCB,0x2A,0xF0,0x56,0x7C,0xFE,0xAC,0xA8,0xD1,0x06,0x0F,0x14, + 0x14,0x52,0x4C,0xFE,0x64,0x2B,0x0C,0x69,0x2A,0xB8,0x0D,0x50,0x6E,0x3E,0x04,0x07, + 0xBF,0x7A,0x20,0x8B,0xF8,0xEE,0x65,0x09,0xE1,0xC7,0x49,0x08,0x32,0x3D,0x0D,0x28, + 0x7E,0x49,0x1D,0xB7,0x4A,0xEF,0x02,0xE7,0x0D,0x80,0x17,0xC8,0x5C,0xE0,0x61,0x62, + 0xCB,0xEC,0xB3,0x60,0x79,0x25,0xDA,0x1A,0x65,0x73,0x9C,0x38,0x10,0xA0,0x26,0x3A, + 0xB0,0xC8,0x16,0x7D,0x93,0x31,0x22,0xEE,0x74,0x0B,0x88,0xC0,0x5C,0x89,0x41,0x00, + 0x28,0xA9,0x47,0x31,0xDF,0x7D,0x49,0x45,0x9A,0xF5,0xE6,0xA7,0x45,0x1A,0xD2,0x8E, + 0x13,0x10,0xDF,0x83,0xAF,0x9B,0x0D,0xAD,0x7E,0x7E,0x9D,0x35,0x50,0x34,0x04,0xCE, + 0xE9,0x20,0xD6,0x9E,0xDB,0x9D,0xD4,0xA8,0xDA,0x64,0xB4,0xD1,0x2F,0x59,0x2E,0x5E, + 0xA2,0x36,0x61,0xD4,0x24,0xA0,0x82,0x33,0x33,0x8A,0xA1,0xD1,0x6C,0xEF,0x61,0x68, + 0xA3,0xE5,0xD2,0x56,0xAD,0xC5,0xFD,0x5E,0x62,0xEB,0x15,0xA8,0x74,0x12,0x4C,0x2F, + 0x31,0x8C,0xE9,0xC1,0xDF,0x10,0x4B,0x01,0xEA,0xF6,0x54,0x1B,0xCD,0x7F,0x3B,0xBD, + 0x5C,0x9F,0xC1,0xDB,0xCF,0x01,0xCA,0xF2,0xBA,0x60,0x12,0x21,0x31,0xED,0xA9,0x64, + 0xB8,0xB2,0x49,0x58,0x17,0x6D,0x5A,0xD7,0xCD,0x8C,0x6D,0xBE,0x9E,0x7F,0xE2,0x02, + 0x58,0xA7,0xDB,0xC3,0x2D,0x58,0xF6,0x74,0x06,0x6A,0x9A,0xF6,0x61,0xF9,0xF6,0x00, + 0xB6,0x69,0xD8,0x3A,0x8B,0x31,0x59,0xDD,0x91,0xE6,0x7C,0x27,0x23,0x87,0xDD,0x03, + 0x0F,0x8F,0x2A,0x8C,0x1E,0x83,0x01,0x4E,0x01,0x61,0x0C,0x52,0x73,0x6D,0xFC,0x08, + 0xA2,0xB9,0x2A,0x66,0xE4,0x76,0x4D,0x31,0xA0,0x56,0x9B,0xD9,0x53,0x8D,0xA2,0xB6, + 0x8F,0x02,0xC8,0xE6,0x3A,0xA6,0x04,0xD1,0x48,0xFB,0xC3,0x4A,0x02,0x76,0xFD,0x2F, + 0xD2,0xBC,0x13,0xB6,0xE8,0x6D,0x34,0x24,0xFA,0x9D,0x29,0x8A,0xC7,0xA1,0x2B,0x14, + 0xF1,0x96,0x00,0x73,0xB9,0x13,0xE9,0xC0,0xB9,0x3A,0x47,0x56,0x02,0x71,0x80,0x27, + 0xA4,0xBC,0x25,0xB6,0xE9,0xBD,0xE4,0xE9,0x98,0x74,0x16,0xF1,0x37,0x84,0x81,0x07, + 0xB4,0x82, +}; + +/* This is the cert we get when we get the url in the AIA extension of the ovh leaf. */ +/* subject:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ +/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority */ +static unsigned char comodo_aia_certificate[1554]={ + 0x30,0x82,0x06,0x0E,0x30,0x82,0x03,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x06, + 0xA7,0x43,0x80,0xD4,0xEB,0xFE,0xD4,0x35,0xB5,0xA3,0xF7,0xE1,0x6A,0xBD,0xD8,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x30,0x81, + 0x85,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, + 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, + 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, + 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, + 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, + 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x2B,0x30,0x29,0x06,0x03,0x55, + 0x04,0x03,0x13,0x22,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x43, + 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74, + 0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x31,0x32,0x30,0x32,0x31,0x32, + 0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x37,0x30,0x32,0x31,0x31,0x32, + 0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13, + 0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72,0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73, + 0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61, + 0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11, + 0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43,0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65, + 0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F, + 0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20, + 0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72, + 0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, + 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0x95,0x56,0xDE,0x54, + 0xB4,0xDF,0xD5,0x02,0x49,0x7B,0xD1,0x5B,0x5C,0xA2,0xB2,0x1E,0x8F,0x9C,0x2B,0x62, + 0x4C,0x2B,0x8D,0x12,0x28,0xF3,0x1A,0x95,0xA3,0xC6,0x10,0xFD,0x29,0xDE,0xE1,0x9F, + 0x0B,0x38,0x40,0x93,0xD1,0xEF,0x6E,0x95,0x10,0xFC,0xE1,0x90,0x17,0x77,0x2C,0xEE, + 0x75,0x3E,0x7B,0x63,0xEC,0x61,0x92,0x6E,0x4F,0x3B,0xAB,0x80,0x49,0x6B,0xDF,0x00, + 0xEA,0x03,0x00,0x7F,0x2F,0x75,0xD5,0x28,0x2F,0xEC,0x56,0x67,0x8F,0x80,0x83,0xA3, + 0xBD,0xDC,0x03,0x99,0x93,0x8B,0x94,0x91,0x56,0x5B,0xA1,0xB8,0x6A,0x3A,0x3F,0x06, + 0xBD,0x0E,0x92,0xCC,0x60,0x9C,0xFD,0xB5,0xE0,0x9F,0x66,0x30,0x5F,0xDB,0xE6,0x94, + 0xF0,0x95,0x6A,0xAF,0xC8,0x8A,0xAF,0x80,0xD9,0xE6,0x88,0x39,0x01,0x7C,0x1C,0xC0, + 0xC5,0x2A,0xF7,0x7B,0x95,0xA0,0xF2,0x76,0xAB,0x6D,0x9B,0x72,0x39,0x30,0xEB,0xD1, + 0x57,0x55,0x01,0x9D,0x58,0x11,0x9D,0x7C,0x6D,0x84,0x8F,0x49,0xE8,0x9D,0x09,0xFC, + 0x3C,0xFD,0x0A,0x4A,0x76,0x14,0x21,0x5C,0x16,0x73,0x40,0x23,0x19,0x74,0xC3,0xBA, + 0x58,0x0A,0xA6,0x96,0x2E,0xDE,0x36,0xE5,0x9F,0xD0,0xC2,0xF0,0xE1,0xE0,0xC1,0x62, + 0xE3,0xC2,0x18,0x45,0x19,0x51,0xAA,0x17,0x1E,0xE8,0x23,0x75,0xD4,0xC8,0xD0,0x96, + 0x13,0xFF,0xC7,0x24,0xD1,0x8C,0x0B,0x27,0xAE,0x9E,0x7A,0xDC,0x3A,0x61,0x63,0x60, + 0x88,0x97,0x2D,0x5D,0x05,0x0B,0xE5,0x3B,0xEB,0xAE,0xCE,0x3A,0x47,0x73,0x76,0xA8, + 0xFA,0x2C,0xDD,0xC0,0x87,0x17,0xE9,0xAC,0x30,0x99,0xF8,0x1F,0x02,0x03,0x01,0x00, + 0x01,0xA3,0x82,0x01,0x69,0x30,0x82,0x01,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, + 0x04,0x18,0x30,0x16,0x80,0x14,0xBB,0xAF,0x7E,0x02,0x3D,0xFA,0xA6,0xF1,0x3C,0x84, + 0x8E,0xAD,0xEE,0x38,0x98,0xEC,0xD9,0x32,0x32,0xD4,0x30,0x1D,0x06,0x03,0x55,0x1D, + 0x0E,0x04,0x16,0x04,0x14,0x39,0xDA,0xFF,0xCA,0x28,0x14,0x8A,0xA8,0x74,0x13,0x08, + 0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, + 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13, + 0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3E,0x06, + 0x03,0x55,0x1D,0x20,0x04,0x37,0x30,0x35,0x30,0x33,0x06,0x04,0x55,0x1D,0x20,0x00, + 0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1D, + 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65,0x63,0x75,0x72,0x65,0x2E,0x63, + 0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x4C,0x06, + 0x03,0x55,0x1D,0x1F,0x04,0x45,0x30,0x43,0x30,0x41,0xA0,0x3F,0xA0,0x3D,0x86,0x3B, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x63,0x6F,0x6D,0x6F,0x64, + 0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53, + 0x41,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x41,0x75, + 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2E,0x63,0x72,0x6C,0x30,0x71,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3B,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D, + 0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x41,0x64,0x64,0x54,0x72,0x75, + 0x73,0x74,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, + 0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x03,0x82,0x02, + 0x01,0x00,0x44,0x42,0x9D,0x41,0x51,0x2B,0x48,0x88,0x5D,0x97,0x9B,0x79,0x5E,0x11, + 0x01,0x4A,0x52,0x19,0x7B,0x41,0x2C,0xC7,0x89,0x3C,0xD0,0x72,0xDC,0x85,0xFA,0x58, + 0xAF,0xD5,0x25,0xE4,0x13,0xF8,0x58,0x65,0x67,0x9F,0x0D,0xFF,0x57,0x8B,0xA9,0x85, + 0x5E,0xCA,0xA6,0x4B,0xB0,0xA7,0xB2,0x2D,0xE0,0x8C,0x22,0xCD,0xFB,0xFF,0x79,0xA4, + 0x8C,0x2B,0x8D,0xFE,0x02,0x3D,0x24,0xDE,0xA9,0x5D,0x5F,0xE4,0x0F,0x47,0xD0,0xDB, + 0x66,0x25,0x3E,0x87,0x47,0x0C,0xAE,0x22,0xC5,0x50,0x22,0x84,0xD7,0xED,0x4A,0x59, + 0x1A,0xF6,0x93,0xA5,0x93,0xB0,0xE0,0x1B,0x81,0xF2,0x56,0xC4,0xC8,0x10,0x53,0xE4, + 0xD4,0x76,0xB1,0xD1,0x5B,0x69,0x4B,0x77,0xB2,0xE0,0x4F,0xC4,0x84,0xE7,0xD4,0xA0, + 0x50,0xEE,0x3C,0xFA,0x44,0xFC,0xD0,0x57,0xB9,0xE1,0x28,0x53,0xFD,0x53,0xCD,0xDC, + 0xB9,0x1F,0x7A,0x40,0xBD,0x30,0x3F,0xD8,0x6C,0xD2,0xF3,0xE7,0x07,0x9F,0x1F,0x22, + 0xB5,0xEA,0x22,0x71,0xCB,0x2A,0xF0,0x56,0x7C,0xFE,0xAC,0xA8,0xD1,0x06,0x0F,0x14, + 0x14,0x52,0x4C,0xFE,0x64,0x2B,0x0C,0x69,0x2A,0xB8,0x0D,0x50,0x6E,0x3E,0x04,0x07, + 0xBF,0x7A,0x20,0x8B,0xF8,0xEE,0x65,0x09,0xE1,0xC7,0x49,0x08,0x32,0x3D,0x0D,0x28, + 0x7E,0x49,0x1D,0xB7,0x4A,0xEF,0x02,0xE7,0x0D,0x80,0x17,0xC8,0x5C,0xE0,0x61,0x62, + 0xCB,0xEC,0xB3,0x60,0x79,0x25,0xDA,0x1A,0x65,0x73,0x9C,0x38,0x10,0xA0,0x26,0x3A, + 0xB0,0xC8,0x16,0x7D,0x93,0x31,0x22,0xEE,0x74,0x0B,0x88,0xC0,0x5C,0x89,0x41,0x00, + 0x28,0xA9,0x47,0x31,0xDF,0x7D,0x49,0x45,0x9A,0xF5,0xE6,0xA7,0x45,0x1A,0xD2,0x8E, + 0x13,0x10,0xDF,0x83,0xAF,0x9B,0x0D,0xAD,0x7E,0x7E,0x9D,0x35,0x50,0x34,0x04,0xCE, + 0xE9,0x20,0xD6,0x9E,0xDB,0x9D,0xD4,0xA8,0xDA,0x64,0xB4,0xD1,0x2F,0x59,0x2E,0x5E, + 0xA2,0x36,0x61,0xD4,0x24,0xA0,0x82,0x33,0x33,0x8A,0xA1,0xD1,0x6C,0xEF,0x61,0x68, + 0xA3,0xE5,0xD2,0x56,0xAD,0xC5,0xFD,0x5E,0x62,0xEB,0x15,0xA8,0x74,0x12,0x4C,0x2F, + 0x31,0x8C,0xE9,0xC1,0xDF,0x10,0x4B,0x01,0xEA,0xF6,0x54,0x1B,0xCD,0x7F,0x3B,0xBD, + 0x5C,0x9F,0xC1,0xDB,0xCF,0x01,0xCA,0xF2,0xBA,0x60,0x12,0x21,0x31,0xED,0xA9,0x64, + 0xB8,0xB2,0x49,0x58,0x17,0x6D,0x5A,0xD7,0xCD,0x8C,0x6D,0xBE,0x9E,0x7F,0xE2,0x02, + 0x58,0xA7,0xDB,0xC3,0x2D,0x58,0xF6,0x74,0x06,0x6A,0x9A,0xF6,0x61,0xF9,0xF6,0x00, + 0xB6,0x69,0xD8,0x3A,0x8B,0x31,0x59,0xDD,0x91,0xE6,0x7C,0x27,0x23,0x87,0xDD,0x03, + 0x0F,0x8F,0x2A,0x8C,0x1E,0x83,0x01,0x4E,0x01,0x61,0x0C,0x52,0x73,0x6D,0xFC,0x08, + 0xA2,0xB9,0x2A,0x66,0xE4,0x76,0x4D,0x31,0xA0,0x56,0x9B,0xD9,0x53,0x8D,0xA2,0xB6, + 0x8F,0x02,0xC8,0xE6,0x3A,0xA6,0x04,0xD1,0x48,0xFB,0xC3,0x4A,0x02,0x76,0xFD,0x2F, + 0xD2,0xBC,0x13,0xB6,0xE8,0x6D,0x34,0x24,0xFA,0x9D,0x29,0x8A,0xC7,0xA1,0x2B,0x14, + 0xF1,0x96,0x00,0x73,0xB9,0x13,0xE9,0xC0,0xB9,0x3A,0x47,0x56,0x02,0x71,0x80,0x27, + 0xA4,0xBC,0x25,0xB6,0xE9,0xBD,0xE4,0xE9,0x98,0x74,0x16,0xF1,0x37,0x84,0x81,0x07, + 0xB4,0x82, +}; + +uint8_t _caissuer_https[] = { + 0x30,0x82,0x04,0x68,0x30,0x82,0x03,0x50,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x7A, + 0x22,0xA1,0x88,0x18,0x9E,0x75,0x77,0xE6,0xEF,0x7E,0xC0,0x33,0x8E,0xE8,0x90,0xE8, + 0x7B,0xC4,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x30,0x81,0x81,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C, + 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, + 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x15, + 0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x0C,0x0C,0x54,0x65,0x73,0x74,0x20,0x52,0x6F, + 0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x38,0x30,0x34,0x32,0x38,0x32, + 0x30,0x32,0x31,0x34,0x31,0x5A,0x17,0x0D,0x31,0x39,0x30,0x34,0x32,0x38,0x32,0x30, + 0x32,0x31,0x34,0x31,0x5A,0x30,0x81,0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A, + 0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03, + 0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65, + 0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69, + 0x6E,0x67,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x48,0x54,0x54, + 0x50,0x53,0x20,0x43,0x41,0x49,0x73,0x73,0x75,0x65,0x72,0x20,0x54,0x65,0x73,0x74, + 0x20,0x43,0x65,0x72,0x74,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, + 0x0A,0x02,0x82,0x01,0x01,0x00,0xC1,0x68,0xC2,0x47,0x1E,0x07,0x82,0x66,0x47,0xC9, + 0x5C,0x22,0xDD,0x8B,0x93,0x6A,0xA7,0x22,0x00,0xB8,0xDA,0x8C,0x3C,0x52,0xA7,0x47, + 0x73,0xBB,0x7A,0xD7,0x8C,0x1E,0xAE,0xDA,0x34,0x25,0x4E,0xEB,0x1F,0x33,0x0B,0x8A, + 0xC7,0x6D,0x2A,0x93,0xDB,0x0D,0xD0,0x47,0x85,0x9C,0x14,0xD5,0x23,0xE3,0xE4,0x94, + 0xE0,0x17,0x9F,0x56,0x64,0x8E,0xE0,0x08,0xE9,0x1B,0x4C,0x7C,0x77,0xF9,0x35,0x74, + 0x52,0x43,0x90,0x13,0xFA,0x51,0x9A,0xA2,0x93,0x47,0x94,0xE7,0xBD,0x07,0xE5,0xFB, + 0x67,0x8B,0xF0,0xE2,0x0C,0x97,0xFD,0x29,0x51,0xBD,0x85,0x6C,0xBE,0x36,0xFD,0xDD, + 0xCC,0x99,0x4D,0x68,0x37,0x96,0xB2,0x20,0x85,0x55,0xA5,0x99,0xA4,0x7E,0xD7,0x19, + 0x06,0x15,0x20,0x10,0x50,0x51,0x2E,0x74,0x5C,0x43,0x49,0x94,0x6B,0x0E,0x9E,0xFB, + 0xDF,0xB2,0xEB,0xD9,0x28,0xA8,0xF1,0x25,0x49,0xC8,0xFE,0x3B,0xE1,0x45,0x95,0x47, + 0xD1,0x53,0xCD,0x34,0x9A,0x6F,0xC4,0x3F,0x63,0xC2,0x60,0xC6,0x40,0xBB,0xF7,0x20, + 0x8A,0xB8,0xB7,0xD7,0xC2,0xBB,0x48,0x24,0x64,0xA2,0x4A,0xE4,0x2A,0x17,0x68,0xE2, + 0xAC,0x47,0x2D,0xCC,0xBD,0xB7,0xCE,0x73,0xDF,0x96,0x8C,0x12,0x56,0xE3,0x29,0xE3, + 0x4D,0xB4,0x55,0x28,0xAB,0x28,0x24,0x45,0x7F,0x55,0x66,0xCD,0x46,0x29,0x89,0x58, + 0xFF,0xA6,0xD1,0x67,0xAC,0x50,0xEE,0x55,0x6D,0x6A,0x2A,0xCF,0xD6,0x09,0xE9,0xDA, + 0x22,0xB0,0xAF,0x90,0xD7,0x02,0xB2,0xCE,0x5F,0x09,0x96,0x5E,0x88,0xAE,0xB5,0xB6, + 0xA1,0xC3,0x9D,0x1A,0x2F,0x2D,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xCA,0x30,0x81, + 0xC7,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30, + 0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x01,0x30,0x16,0x06,0x03,0x55,0x1D,0x11,0x04,0x0F,0x30,0x0D,0x82, + 0x0B,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xDF,0xC7,0x68,0x26,0x64,0x95,0x5D,0x73,0x36, + 0x84,0xE8,0xE3,0x1D,0xC8,0x28,0x5E,0xA8,0x27,0x73,0x8C,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xB5,0xA9,0x53,0x08,0x10,0x38,0x1A,0xA5, + 0xB3,0x84,0xC9,0xEE,0xC4,0xAB,0x0F,0xB8,0x5F,0x68,0x10,0xA2,0x30,0x3A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x2E,0x30,0x2C,0x30,0x2A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A, + 0x2F,0x2F,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65, + 0x73,0x74,0x43,0x41,0x2E,0x64,0x65,0x72,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xC4,0x48,0xDF,0x5E, + 0x73,0xD1,0x43,0x28,0x7D,0x69,0x71,0x32,0x1F,0xCC,0x1A,0xEB,0x5B,0x98,0x9D,0xCE, + 0xFF,0xCA,0x16,0xA9,0x96,0xE7,0x4D,0xC4,0xAE,0x53,0xE2,0x5D,0xDB,0xDA,0x40,0x80, + 0xE5,0xFB,0xF3,0xD7,0x21,0x9A,0x77,0x1D,0x67,0xFC,0x04,0x62,0x18,0xFF,0x10,0x59, + 0xF4,0xDD,0xF4,0xC6,0x8F,0xB4,0xEF,0x9F,0x05,0xA6,0xF1,0xCB,0x44,0x24,0x02,0x19, + 0x75,0xF9,0x3C,0x28,0x8A,0xAA,0x57,0x6B,0xFF,0x64,0xFF,0xD7,0xE2,0x62,0x67,0x70, + 0x20,0x4D,0xAE,0xD2,0x67,0xED,0x92,0xA4,0xFA,0x8A,0xC3,0x24,0x9C,0x2F,0x4D,0x2C, + 0xA9,0xA5,0x92,0x5E,0x5C,0x6F,0xDB,0xAB,0x96,0xA6,0xB1,0x5B,0xF1,0x8D,0x97,0x08, + 0xBC,0x5B,0x27,0xD5,0x9E,0x2D,0xF0,0x49,0x68,0xA6,0x92,0x00,0x13,0xAD,0x60,0x9E, + 0x78,0x72,0xC2,0x18,0xB8,0xE5,0x9D,0x72,0xA5,0x87,0x61,0xA8,0x95,0x8A,0x2B,0xB2, + 0xCC,0xCA,0x7F,0x1E,0x1E,0xC5,0xFB,0x5A,0x0C,0x77,0x17,0xB0,0xBE,0x7B,0x5A,0x50, + 0x05,0x32,0x40,0x98,0x3A,0x8B,0x22,0x3F,0x3B,0xA5,0xA8,0xA9,0x59,0x3B,0x55,0x92, + 0xD1,0x8A,0x34,0x73,0xA6,0xD6,0x5D,0x5E,0x85,0x59,0x00,0xD5,0x55,0x94,0x80,0xC1, + 0xB9,0xF1,0xCA,0x2B,0xC5,0x96,0xEE,0x49,0x6A,0x2C,0xDD,0x62,0x98,0xB3,0x74,0x09, + 0x09,0xDE,0x3D,0x59,0x5B,0x21,0x76,0x6E,0x27,0x66,0xED,0x7B,0x74,0x7F,0xE7,0xA9, + 0xAE,0xEB,0x40,0x83,0xB9,0xBC,0xE6,0x0C,0x1E,0x53,0xB2,0xEA,0x79,0xC4,0xA9,0x30, + 0x2B,0x1F,0xC4,0x34,0x82,0x3E,0xFC,0x1E,0x2D,0x66,0x75,0xD0, +}; + +#endif /* _TRUSTTESTS_CA_ISSUER_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/CARevocationTests.m b/tests/TrustTests/EvaluationTests/CARevocationTests.m new file mode 100644 index 00000000..d839cee7 --- /dev/null +++ b/tests/TrustTests/EvaluationTests/CARevocationTests.m @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#include +#import +#include +#include +#include +#include "OSX/utilities/SecCFWrappers.h" +#include +#include +#include +#include "trust/trustd/OTATrustUtilities.h" +#include "trust/trustd/SecOCSPCache.h" + +#import "TrustEvaluationTestCase.h" +#import "CARevocationTests_data.h" +#include "../TestMacroConversions.h" + +@interface CARevocationTests : TrustEvaluationTestCase + +@end + +@implementation CARevocationTests + ++ (id) CF_RETURNS_RETAINED SecCertificateCreateFromData:(uint8_t *)data length:(size_t)length +{ + if (!data || !length) { return NULL; } + SecCertificateRef cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, data, length); + return (__bridge id)cert; +} + +static NSArray *s_anchors = nil; +static NSDate *s_date_20201020 = nil; + +- (void)setUp +{ + // Delete the OCSP cache between each test + [super setUp]; + SecOCSPCacheDeleteContent(nil); + + SecCertificateRef root = (__bridge SecCertificateRef)[CARevocationTests SecCertificateCreateFromData:_acrootca length:sizeof(_acrootca)]; + s_anchors = @[ (__bridge id)root ]; + CFReleaseNull(root); + s_date_20201020 = [NSDate dateWithTimeIntervalSinceReferenceDate:624900000.0]; +} + +/* Evaluate the given chain for SSL and return the trust results dictionary. */ +- (NSDictionary *)eval_ca_trust:(NSArray *)certs + anchors:(NSArray *)anchors + hostname:(NSString *)hostname + verifyDate:(NSDate *)date +{ + /* Create the trust wrapper object */ + TestTrustEvaluation *trust = nil; + SecPolicyRef policy = SecPolicyCreateSSL(true, (__bridge CFStringRef)hostname); + XCTAssertNotNil(trust = [[TestTrustEvaluation alloc] initWithCertificates:certs policies:@[(__bridge id)policy]], "create trust failed"); + CFReleaseNull(policy); + if (!trust) { return nil; } + + /* Set the optional properties */ + if (anchors) { trust.anchors = anchors; } + if (date) { trust.verifyDate = date; } + + /* Evaluate */ + NSError *error = nil; + XCTAssert([trust evaluate:&error], "failed trust evaluation: %@", error); + return trust.resultDictionary; +} + +#if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE +/* watchOS and bridgeOS don't support networking in trustd */ +- (void)testCARevocationAdditions +{ + /* Verify that the revocation server is potentially reachable */ + if (!ping_host("ocsp.apple.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + + const CFStringRef TrustTestsAppID = CFSTR("com.apple.trusttests"); + //%%% TBD: add namespace tests using AnotherAppID + //const CFStringRef AnotherAppID = CFSTR("com.apple.security.not-this-one"); + CFDictionaryRef copiedAdditions = NULL; + CFErrorRef error = NULL; + + /* Verify no additions set initially */ + is(copiedAdditions = SecTrustStoreCopyCARevocationAdditions(NULL, NULL), NULL, "no revocation additions set"); + if (copiedAdditions) { + CFReleaseNull(copiedAdditions); + return; + } + + NSDictionary *results = nil; + SecCertificateRef leaf = NULL, ca = NULL; + + leaf = (__bridge SecCertificateRef)[CARevocationTests SecCertificateCreateFromData:_acleaf length:sizeof(_acleaf)]; + XCTAssertNotNil((__bridge id)leaf, "create leaf"); + ca = (__bridge SecCertificateRef)[CARevocationTests SecCertificateCreateFromData:_acserverca1 length:sizeof(_acserverca1)]; + XCTAssertNotNil((__bridge id)ca, "create ca"); + + /* We do not expect a revocation check for this CA until explicitly set up */ + results = [self eval_ca_trust:@[(__bridge id)leaf, (__bridge id)ca] anchors:s_anchors hostname:@"radar.apple.com" verifyDate:s_date_20201020]; + XCTAssertNotNil(results, "failed to obtain trust results"); + XCTAssertNil(results[(__bridge NSString*)kSecTrustRevocationChecked], "revocation checked when not expected"); + + /* Set addition for intermediate CA with implied AppID */ + CFDataRef caSPKIHash = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(ca); + NSDictionary *caAddition = @{ + (__bridge NSString*)kSecCARevocationHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecCARevocationSPKIHashKey : (__bridge NSData*)caSPKIHash, + }; + NSDictionary *additions1 = @{ + (__bridge NSString*)kSecCARevocationAdditionsKey : @[ caAddition ] + }; + ok(SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)additions1, &error), "failed to set ca addition for this app: %@", error); + CFReleaseNull(caSPKIHash); + + /* Check that the additions were saved and can be retrieved */ + ok(copiedAdditions = SecTrustStoreCopyCARevocationAdditions(TrustTestsAppID, &error), "failed to copy ca additions for TrustTests app id: %@", error); + /* Same as what we saved? */ + ok([additions1 isEqualToDictionary:(__bridge NSDictionary*)copiedAdditions], "got wrong additions back"); + CFReleaseNull(copiedAdditions); + + /* This time, the revocation check should take place on the leaf. */ + results = [self eval_ca_trust:@[(__bridge id)leaf, (__bridge id)ca] anchors:s_anchors hostname:@"radar.apple.com" verifyDate:s_date_20201020]; + XCTAssertNotNil(results, "failed to obtain trust results"); + // %%% This check should be replaced with a different key: rdar://70669949 + XCTAssertNil(results[(__bridge NSString*)kSecTrustRevocationChecked], "revocation not checked"); + + /* Set empty array to clear the previously-set additions */ + NSDictionary *emptyAdditions = @{ + (__bridge NSString*)kSecCARevocationAdditionsKey : @[] + }; + ok(SecTrustStoreSetCARevocationAdditions(TrustTestsAppID, (__bridge CFDictionaryRef)emptyAdditions, &error), "failed to set empty additions"); + /* Did the additions get cleared? */ + is(copiedAdditions = SecTrustStoreCopyCARevocationAdditions(TrustTestsAppID, &error), NULL, "additions still present after being cleared"); + CFReleaseNull(copiedAdditions); + + /* Set addition for root CA with implied AppID */ + CFDataRef rootSPKIHash = SecSHA256DigestCreate(NULL, _acrootca_spki, sizeof(_acrootca_spki)); + NSDictionary *rootAddition = @{ + (__bridge NSString*)kSecCARevocationHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecCARevocationSPKIHashKey : (__bridge NSData*)rootSPKIHash, + }; + NSDictionary *additions2 = @{ + (__bridge NSString*)kSecCARevocationAdditionsKey : @[ rootAddition ] + }; + ok(SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)additions2, &error), "failed to set root addition for this app: %@", error); + + /* Check that the additions were saved and can be retrieved */ + ok(copiedAdditions = SecTrustStoreCopyCARevocationAdditions(TrustTestsAppID, &error), "failed to copy root additions for TrustTests app id: %@", error); + /* Same as what we saved? */ + ok([additions2 isEqualToDictionary:(__bridge NSDictionary*)copiedAdditions], "got wrong additions back"); + CFReleaseNull(copiedAdditions); + + /* Clear OCSP cache so we know whether next evaluation attempts to check */ + SecOCSPCacheDeleteContent(nil); + + /* Revocation check should take place with a CA addition set for the root. */ + results = [self eval_ca_trust:@[(__bridge id)leaf, (__bridge id)ca] anchors:s_anchors hostname:@"radar.apple.com" verifyDate:s_date_20201020]; + XCTAssertNotNil(results, "failed to obtain trust results"); + // %%% This check should be replaced with a different key: rdar://70669949 + XCTAssertNotNil(results[(__bridge NSString*)kSecTrustRevocationChecked], "revocation not checked"); + + CFReleaseNull(leaf); + CFReleaseNull(ca); +} + +#else // TARGET_OS_BRIDGE || TARGET_OS_WATCH +- (void)testSkipTests +{ + XCTAssert(true); +} +#endif // TARGET_OS_BRIDGE || TARGET_OS_WATCH +@end + diff --git a/tests/TrustTests/EvaluationTests/CARevocationTests_data.h b/tests/TrustTests/EvaluationTests/CARevocationTests_data.h new file mode 100644 index 00000000..7bac453b --- /dev/null +++ b/tests/TrustTests/EvaluationTests/CARevocationTests_data.h @@ -0,0 +1,461 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ +#ifndef _TRUSTTESTS_CA_REVOCATION_TESTS_H_ +#define _TRUSTTESTS_CA_REVOCATION_TESTS_H_ + +uint8_t _acleaf[] = { + 0x30,0x82,0x06,0x18,0x30,0x82,0x05,0x00,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x10,0x5A,0xB9,0xC3,0x64,0xE1, + 0xC2,0x69,0xF3,0x2C,0x5A,0x20,0x36,0x31,0x3B,0x73, + 0x74,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6A,0x31,0x24, + 0x30,0x22,0x06,0x03,0x55,0x04,0x03,0x0C,0x1B,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x72,0x70,0x6F, + 0x72,0x61,0x74,0x65,0x20,0x53,0x65,0x72,0x76,0x65, + 0x72,0x20,0x43,0x41,0x20,0x31,0x31,0x20,0x30,0x1E, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72, + 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, + 0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x32,0x30, + 0x30,0x36,0x31,0x35,0x32,0x32,0x35,0x32,0x31,0x34, + 0x5A,0x17,0x0D,0x32,0x32,0x30,0x37,0x31,0x35,0x32, + 0x32,0x35,0x32,0x31,0x34,0x5A,0x30,0x79,0x31,0x18, + 0x30,0x16,0x06,0x03,0x55,0x04,0x03,0x0C,0x0F,0x72, + 0x61,0x64,0x61,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65, + 0x2E,0x63,0x6F,0x6D,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x1D,0x6D,0x61,0x6E,0x61,0x67, + 0x65,0x6D,0x65,0x6E,0x74,0x3A,0x69,0x64,0x6D,0x73, + 0x2E,0x67,0x72,0x6F,0x75,0x70,0x2E,0x31,0x30,0x34, + 0x32,0x39,0x33,0x36,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, + 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01, + 0x01,0x00,0xE4,0xFD,0xE1,0xE3,0x80,0x9A,0xC6,0xC4, + 0x77,0xA9,0x7F,0xC5,0xBA,0xA4,0xA9,0x46,0x46,0x89, + 0x3E,0x74,0x6E,0x50,0x06,0xA5,0x36,0x02,0x24,0xED, + 0xAF,0x4A,0xAC,0xBD,0x7C,0x1F,0x01,0x3B,0xF5,0xD5, + 0xCF,0xC2,0xDB,0xC3,0x13,0xF0,0xB3,0x71,0x0B,0xC1, + 0x99,0xB3,0xF8,0xAE,0x29,0xD0,0x8D,0xCD,0x4C,0x09, + 0x4E,0x04,0x9A,0x43,0x0D,0x96,0x06,0x3F,0xF2,0xC3, + 0xD8,0xC8,0xAB,0x54,0xC1,0x82,0x64,0xEF,0xB2,0x14, + 0x77,0xB9,0xA8,0xE6,0x29,0xE9,0x0A,0xF2,0xB1,0x44, + 0x1A,0x93,0xA3,0x3E,0xAB,0xF2,0xC0,0x78,0x0A,0xF9, + 0x9C,0x1D,0xB5,0xB6,0x86,0x33,0x0C,0xB3,0x62,0xD1, + 0x6B,0x18,0xB1,0xD1,0x3C,0x84,0x9A,0x2D,0xB3,0x6C, + 0x91,0x09,0x19,0x60,0xCF,0xEA,0x63,0x8B,0xAC,0xF4, + 0xCB,0x79,0xB4,0x10,0x42,0xD4,0x7B,0xCB,0x8D,0x86, + 0xD2,0x13,0xB9,0xE5,0x21,0x8B,0xDE,0x0D,0x20,0x5F, + 0x99,0x1A,0xD1,0x57,0xF9,0xBF,0xF6,0x90,0x25,0x97, + 0x84,0xCF,0x64,0xC1,0x3A,0x6D,0x50,0x2C,0xFD,0x02, + 0x51,0x47,0x0F,0xE6,0xE5,0x4D,0x19,0x10,0xB9,0xA5, + 0xDA,0x53,0x69,0x09,0xE2,0x51,0x31,0xAF,0x41,0x23, + 0x80,0x3B,0x65,0xDE,0x9C,0x9B,0xBD,0x9B,0xF2,0x69, + 0xDC,0xB9,0x73,0x88,0x16,0x30,0xB2,0x7A,0x0B,0xC2, + 0xDA,0xE6,0x3F,0x9B,0x65,0x9B,0x53,0xE7,0x17,0xCF, + 0x09,0x98,0xA8,0x72,0x49,0xAB,0x59,0x13,0x6E,0x41, + 0x94,0xF1,0xA4,0x4A,0xC8,0x05,0xEA,0x13,0xE5,0x78, + 0x47,0x0D,0xC1,0xD7,0x6D,0xAD,0x39,0x96,0x35,0x82, + 0x76,0xB2,0x8A,0x90,0xFF,0xF3,0xF3,0x4D,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x82,0x02,0xA9,0x30,0x82,0x02, + 0xA5,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, + 0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xB6,0x23, + 0xB5,0x5A,0xEB,0x7E,0xEB,0xB6,0xF3,0x28,0x1E,0x04, + 0xD0,0xAD,0x5C,0x93,0xA9,0xA4,0x9A,0x6D,0x30,0x81, + 0x83,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01, + 0x01,0x04,0x77,0x30,0x75,0x30,0x39,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2D,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x65,0x72,0x74, + 0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, + 0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x63,0x6F,0x72, + 0x70,0x73,0x65,0x72,0x76,0x65,0x72,0x63,0x61,0x31, + 0x2E,0x64,0x65,0x72,0x30,0x38,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x2C,0x68,0x74, + 0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, + 0x6F,0x63,0x73,0x70,0x30,0x33,0x2D,0x63,0x6F,0x72, + 0x70,0x73,0x65,0x72,0x76,0x65,0x72,0x63,0x61,0x31, + 0x30,0x34,0x30,0x4C,0x06,0x03,0x55,0x1D,0x11,0x04, + 0x45,0x30,0x43,0x82,0x0F,0x72,0x61,0x64,0x61,0x72, + 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x82,0x17,0x72,0x61,0x64,0x61,0x72,0x2D,0x69,0x6E, + 0x74,0x2D,0x72,0x6E,0x6F,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x82,0x17,0x72,0x61,0x64, + 0x61,0x72,0x2D,0x69,0x6E,0x74,0x2D,0x6D,0x64,0x6E, + 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x30,0x82,0x01,0x12,0x06,0x03,0x55,0x1D,0x20,0x04, + 0x82,0x01,0x09,0x30,0x82,0x01,0x05,0x30,0x82,0x01, + 0x01,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64, + 0x05,0x0F,0x02,0x30,0x81,0xF2,0x30,0x81,0xA4,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30, + 0x81,0x97,0x0C,0x81,0x94,0x52,0x65,0x6C,0x69,0x61, + 0x6E,0x63,0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69, + 0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79, + 0x20,0x70,0x61,0x72,0x74,0x79,0x20,0x61,0x73,0x73, + 0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70, + 0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x61, + 0x6E,0x79,0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61, + 0x62,0x6C,0x65,0x20,0x74,0x65,0x72,0x6D,0x73,0x20, + 0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x64,0x69,0x74, + 0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73, + 0x65,0x20,0x61,0x6E,0x64,0x2F,0x6F,0x72,0x20,0x63, + 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63, + 0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E, + 0x74,0x73,0x2E,0x30,0x49,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x02,0x01,0x16,0x3D,0x68,0x74,0x74, + 0x70,0x73,0x3A,0x2F,0x2F,0x63,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x65,0x6D,0x61,0x6E,0x61, + 0x67,0x65,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, + 0x63,0x6F,0x6D,0x2F,0x23,0x68,0x65,0x6C,0x70,0x2F, + 0x70,0x6F,0x6C,0x69,0x63,0x69,0x65,0x73,0x2F,0x63, + 0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x65,0x30,0x1D, + 0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30, + 0x3C,0x06,0x03,0x55,0x1D,0x1F,0x04,0x35,0x30,0x33, + 0x30,0x31,0xA0,0x2F,0xA0,0x2D,0x86,0x2B,0x68,0x74, + 0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61, + 0x70,0x70,0x6C,0x65,0x63,0x6F,0x72,0x70,0x73,0x65, + 0x72,0x76,0x65,0x72,0x63,0x61,0x31,0x2E,0x63,0x72, + 0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0x9E,0xD4,0xB9,0x32,0xC7,0x63,0xBA,0xEF, + 0x4B,0x99,0xE4,0x2F,0xDD,0x35,0x8A,0xD1,0x2B,0xF8, + 0xB8,0xF4,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, + 0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x39,0x1C, + 0x08,0xE9,0x55,0x6E,0x60,0xB5,0xC9,0x41,0x5B,0xE9, + 0xC3,0x5E,0xA3,0xE9,0x4C,0xF2,0xCA,0xAB,0x4A,0xB9, + 0xE1,0x83,0xE8,0xFE,0x1B,0xCA,0x9C,0xE0,0xBE,0xE7, + 0xDE,0x37,0xA0,0xE1,0x0B,0xDB,0xAC,0x29,0x13,0x9F, + 0x9B,0x0E,0x3F,0xCA,0x60,0xC4,0x7E,0x95,0x6C,0x41, + 0xA8,0xF5,0x7A,0x7B,0x92,0xB6,0xC9,0xB8,0xAA,0x7D, + 0x7E,0xD5,0xF4,0x6E,0x33,0xFC,0x8F,0xDA,0x2A,0x2B, + 0xEF,0x31,0x9C,0x43,0x5D,0x45,0x25,0x65,0xE3,0x65, + 0x4D,0x14,0x04,0x85,0x72,0x51,0x9B,0x40,0x69,0x41, + 0xCC,0x93,0xE7,0x73,0xC6,0xF3,0x63,0x77,0x91,0x27, + 0x1F,0x2B,0xB2,0x3E,0x15,0x51,0x23,0x49,0x34,0x11, + 0x1D,0xB3,0x7F,0x8B,0x75,0xB2,0xC4,0xA0,0x7A,0x3B, + 0xF7,0x62,0x1C,0x64,0xFA,0x11,0x03,0xE7,0x84,0xAE, + 0xF4,0x8B,0x35,0xA7,0x5D,0x8D,0x11,0x0E,0x0B,0xD7, + 0x36,0x14,0xC4,0xD4,0x3C,0x99,0x5D,0xF2,0x96,0x97, + 0x31,0x32,0xBD,0xF3,0x87,0x56,0xE5,0x9B,0x25,0xCA, + 0x48,0xE9,0x2F,0xF1,0x93,0x98,0x8F,0xDF,0xD3,0x6E, + 0x1A,0x99,0x51,0xF9,0x55,0x52,0xE6,0xBF,0x61,0x8D, + 0xAB,0x26,0xDD,0x5F,0x2A,0x6F,0x61,0x02,0x28,0x0F, + 0x92,0x41,0x76,0xD2,0xFA,0x05,0x79,0xB6,0xBE,0x7B, + 0xB1,0xAE,0xCC,0x89,0xF1,0x5F,0x1F,0x27,0x79,0x30, + 0xAB,0x0F,0x31,0xE0,0x1C,0x40,0x05,0x16,0xAF,0x41, + 0x8C,0x7A,0x4D,0x26,0x5A,0x8C,0x98,0xEC,0x57,0xCF, + 0x94,0xFB,0x3D,0x56,0xB2,0xF5,0x10,0x76,0x4B,0x2D, + 0x77,0x9C,0x4B,0x34,0xC0,0x04,0xAE,0xD0,0xC1,0xAB, + 0x0E,0x61,0xF8,0x74 +}; + +uint8_t _acserverca1[] = { + 0x30,0x82,0x04,0x40,0x30,0x82,0x03,0x28,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x08,0x0D,0x5D,0xDF,0x69,0x27, + 0x9B,0x23,0x11,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x66, + 0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x17,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x72, + 0x70,0x6F,0x72,0x61,0x74,0x65,0x20,0x52,0x6F,0x6F, + 0x74,0x20,0x43,0x41,0x31,0x20,0x30,0x1E,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x33, + 0x32,0x36,0x31,0x36,0x35,0x33,0x33,0x37,0x5A,0x17, + 0x0D,0x32,0x39,0x30,0x33,0x32,0x36,0x31,0x36,0x35, + 0x33,0x33,0x37,0x5A,0x30,0x6A,0x31,0x24,0x30,0x22, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x1B,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61, + 0x74,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20, + 0x43,0x41,0x20,0x31,0x31,0x20,0x30,0x1E,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05, + 0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A, + 0x02,0x82,0x01,0x01,0x00,0xE3,0xE9,0x68,0xA1,0xE7, + 0x9B,0xBC,0xF7,0x87,0x48,0x22,0x9B,0x09,0x5F,0xC8, + 0xC9,0xA6,0x9A,0xCC,0xCD,0x40,0x16,0xF8,0xA1,0xD0, + 0xF6,0x27,0x15,0x4C,0xE7,0xD3,0xC1,0x6E,0xDF,0x11, + 0x06,0x9A,0x63,0xC5,0x87,0x55,0xDA,0xDF,0xAF,0x15, + 0x31,0x98,0x45,0xF4,0x8C,0xC2,0x3C,0x93,0xA2,0x1C, + 0xC0,0xF0,0x2A,0x77,0xF4,0x19,0x94,0x96,0xF4,0x7B, + 0x52,0x74,0x84,0x86,0x5A,0x66,0x7D,0x68,0x92,0xA1, + 0x5E,0xE1,0xA9,0x21,0xE0,0x14,0x38,0x84,0x21,0x32, + 0x8B,0x21,0x95,0x47,0x27,0x17,0xA0,0xBA,0x7B,0xD7, + 0xD8,0xD7,0x25,0x20,0x77,0xCB,0x62,0x8B,0xC6,0x0F, + 0xC1,0x49,0xC6,0x2B,0x42,0xE9,0x02,0x70,0x9E,0x99, + 0x44,0x77,0x51,0x05,0x62,0x78,0xBC,0xB0,0xD2,0xA7, + 0xA6,0x91,0x71,0x25,0x58,0x13,0x8D,0x8A,0xC8,0x46, + 0x41,0xDB,0x89,0x41,0xC5,0x23,0x7D,0x84,0xE9,0x02, + 0xB0,0x1A,0xF8,0x5D,0x66,0xD0,0xE1,0xE1,0x72,0xF4, + 0xA4,0x65,0x79,0x97,0x0A,0x7B,0xC0,0xE3,0x24,0x74, + 0x83,0x4A,0x81,0x5E,0xC3,0xA2,0xBF,0x51,0x32,0x96, + 0x8F,0x28,0x32,0x08,0x49,0xFB,0x02,0x43,0x62,0x42, + 0xB3,0x84,0x84,0x30,0x1B,0x28,0xE4,0x05,0xB9,0xBB, + 0xD6,0xB5,0xC4,0xA2,0xAB,0x8E,0x57,0x53,0x29,0xBC, + 0x0B,0x4F,0xD6,0x1E,0xA4,0x52,0xDC,0x16,0x1C,0x95, + 0xC2,0x8D,0x97,0x6B,0xBB,0x3E,0xC8,0x93,0xC7,0x01, + 0x97,0x1E,0x18,0x09,0x59,0x39,0x0F,0x5D,0x73,0x4E, + 0xA9,0x8F,0x49,0xFD,0x49,0x16,0xBD,0x25,0xEC,0xD9, + 0x05,0xEA,0xE3,0xB0,0x04,0x0E,0xD9,0x09,0x9E,0xC0, + 0xB7,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xED,0x30, + 0x81,0xEA,0x30,0x41,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x01,0x01,0x04,0x35,0x30,0x33,0x30,0x31, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, + 0x86,0x25,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F, + 0x63,0x73,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, + 0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30,0x34, + 0x2D,0x63,0x6F,0x72,0x70,0x72,0x6F,0x6F,0x74,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, + 0xB6,0x23,0xB5,0x5A,0xEB,0x7E,0xEB,0xB6,0xF3,0x28, + 0x1E,0x04,0xD0,0xAD,0x5C,0x93,0xA9,0xA4,0x9A,0x6D, + 0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, + 0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1F,0x06, + 0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, + 0x35,0x20,0x26,0xCE,0x85,0xBE,0x49,0x26,0x20,0x01, + 0xDD,0xC8,0xEE,0xFF,0x3D,0x68,0xC8,0xD0,0xDF,0xF5, + 0x30,0x32,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2B,0x30, + 0x29,0x30,0x27,0xA0,0x25,0xA0,0x23,0x86,0x21,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, + 0x63,0x6F,0x72,0x70,0x72,0x6F,0x6F,0x74,0x2E,0x63, + 0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, + 0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x10, + 0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06, + 0x18,0x04,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x03,0x82,0x01,0x01,0x00,0x0D,0x34,0x2F,0xB2, + 0xC2,0xF1,0xF0,0xDC,0xA2,0x9F,0x8F,0x41,0x9C,0x84, + 0xCA,0x66,0xDC,0x90,0x9C,0xC4,0x90,0xC9,0xDA,0xD9, + 0x37,0x4F,0xAE,0xC9,0xD9,0xCF,0xE2,0x4B,0x8E,0x59, + 0x47,0x9A,0x83,0x32,0xDF,0xA7,0x97,0x45,0x9D,0x1E, + 0x46,0x58,0x5D,0xD7,0x1C,0x17,0xC5,0x1C,0x9E,0xA2, + 0x74,0xF6,0x73,0x77,0xF9,0x35,0xAD,0x67,0xC3,0x3C, + 0xD5,0x87,0x1E,0x96,0x16,0x3D,0x8B,0x40,0x51,0xA8, + 0x16,0xA0,0x53,0x1C,0xF5,0xCB,0x32,0xC4,0xA8,0xC5, + 0x2A,0x3A,0x21,0xD9,0xFD,0x51,0x81,0x59,0x6F,0x1B, + 0xF9,0x40,0x86,0x96,0xCF,0xA0,0x73,0xA3,0x5B,0x60, + 0x02,0xB6,0x21,0xAD,0x39,0xF5,0xFA,0xFC,0xA8,0x6E, + 0x34,0x01,0x7C,0x59,0xF3,0x73,0xFC,0xBA,0xBE,0xF4, + 0x4E,0x16,0x36,0x9E,0x51,0x77,0x80,0xF5,0xA1,0xC7, + 0xAE,0xFF,0x04,0x71,0x6B,0xB3,0xBE,0x3E,0xA7,0xD1, + 0x74,0x2B,0x4D,0x58,0x58,0x3B,0x94,0x74,0xA3,0x65, + 0x27,0xC1,0x74,0xA9,0xD2,0xF9,0x8A,0x81,0xB3,0x47, + 0xB3,0x06,0x8E,0x9C,0xE6,0x42,0x86,0x77,0xF8,0x96, + 0x99,0x1F,0xED,0x30,0x8F,0x4B,0xD5,0x0F,0x5E,0x71, + 0x6C,0xAC,0xDB,0x48,0xE3,0x3C,0x58,0x2B,0xE8,0x9B, + 0x9E,0x24,0x8A,0x5D,0xCD,0x56,0x5F,0xA9,0x07,0xEA, + 0xCD,0x2C,0x94,0x3D,0xA7,0x7F,0x1B,0xE8,0x10,0xB8, + 0xD2,0x1E,0x43,0x5A,0x0D,0x13,0xDA,0xF5,0x3F,0x10, + 0x9D,0x2D,0x1F,0xE6,0x94,0x11,0x2F,0x40,0xFF,0x5F, + 0x21,0x96,0x02,0xF0,0x5F,0x54,0x56,0x32,0x90,0xD5, + 0x67,0xAE,0x29,0x0E,0x22,0x70,0xE3,0x2B,0x7A,0x95, + 0xC0,0xC7 +}; + +uint8_t _acrootca[] = { + 0x30,0x82,0x03,0xB1,0x30,0x82,0x02,0x99,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x08,0x14,0x99,0x6B,0x4A,0x6A, + 0xE4,0x40,0xA0,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x66, + 0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x17,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x72, + 0x70,0x6F,0x72,0x61,0x74,0x65,0x20,0x52,0x6F,0x6F, + 0x74,0x20,0x43,0x41,0x31,0x20,0x30,0x1E,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x33,0x30,0x37, + 0x31,0x36,0x31,0x39,0x32,0x30,0x34,0x35,0x5A,0x17, + 0x0D,0x32,0x39,0x30,0x37,0x31,0x37,0x31,0x39,0x32, + 0x30,0x34,0x35,0x5A,0x30,0x66,0x31,0x20,0x30,0x1E, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x17,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61, + 0x74,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41, + 0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F, + 0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82, + 0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01, + 0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, + 0x00,0xB5,0x3B,0xE3,0x9F,0x6A,0x1D,0x0E,0x46,0x51, + 0x1E,0xD0,0xB5,0x17,0x6B,0x06,0x4B,0x92,0xAF,0x38, + 0x10,0x25,0xA1,0xEE,0x1E,0x4E,0xEF,0x19,0xE0,0x73, + 0xB5,0x37,0x33,0x72,0x21,0x21,0xCB,0x62,0x4A,0x3D, + 0xA9,0x68,0xD8,0x07,0xB4,0xEB,0x8D,0x0A,0xDB,0x30, + 0x33,0x21,0x2F,0x6F,0xD3,0xF7,0x5D,0xCE,0x20,0x0A, + 0x04,0xDB,0xFF,0xBF,0x75,0x08,0x42,0x3F,0x3E,0xD8, + 0xC8,0xEF,0xA4,0xF8,0x56,0x7B,0x13,0x64,0x6B,0xF3, + 0xA2,0x38,0x10,0xFA,0xEE,0x9D,0x83,0x93,0x1D,0xFB, + 0xEF,0x13,0x6C,0x38,0x49,0xDD,0xEB,0x71,0xA6,0x92, + 0x58,0x04,0xDE,0x01,0x41,0x2B,0x99,0x5E,0xBD,0x24, + 0x3F,0x69,0xA8,0x44,0xF2,0xAA,0x01,0x78,0xB9,0x38, + 0x06,0x10,0x77,0x36,0xF8,0xF2,0xA3,0x3E,0xD9,0x5F, + 0xEA,0xF5,0x8B,0x6A,0xA6,0x5F,0xE6,0x51,0xD0,0x9B, + 0x50,0xA0,0x1E,0xF5,0x85,0x9E,0x49,0x50,0x4A,0x61, + 0x78,0xDA,0x29,0xA7,0x33,0x72,0x8B,0x83,0xEE,0x7B, + 0xA7,0x79,0x4E,0x8E,0x02,0x6F,0x9D,0x25,0x97,0x26, + 0x86,0x0C,0x82,0xC5,0x8C,0x16,0x7E,0x49,0x61,0xFD, + 0xFF,0x1A,0xA0,0x0D,0x28,0xE1,0x68,0xF5,0xAE,0x85, + 0x72,0xF3,0xAB,0xE0,0x74,0x75,0xCC,0x57,0x64,0x3C, + 0x2C,0x55,0x05,0xC9,0x8D,0xAA,0xB3,0xEC,0xC8,0x62, + 0x88,0x15,0x2A,0xC4,0x59,0x60,0x37,0xC1,0xED,0x6B, + 0xCE,0xE9,0xCA,0xAF,0xB0,0xA5,0x45,0xBA,0xFF,0x16, + 0x32,0xAA,0x92,0x86,0xD9,0xB9,0xA1,0x13,0x75,0x95, + 0x9B,0x97,0x5C,0x2D,0xB5,0x12,0xCA,0x6B,0x6B,0x39, + 0xD6,0x9B,0x4B,0x34,0x47,0xAB,0x35,0x02,0x03,0x01, + 0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x35,0x20,0x26, + 0xCE,0x85,0xBE,0x49,0x26,0x20,0x01,0xDD,0xC8,0xEE, + 0xFF,0x3D,0x68,0xC8,0xD0,0xDF,0xF5,0x30,0x0F,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30, + 0x03,0x01,0x01,0xFF,0x30,0x1F,0x06,0x03,0x55,0x1D, + 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x35,0x20,0x26, + 0xCE,0x85,0xBE,0x49,0x26,0x20,0x01,0xDD,0xC8,0xEE, + 0xFF,0x3D,0x68,0xC8,0xD0,0xDF,0xF5,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, + 0x02,0x01,0x06,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x73,0x02,0x4A,0xA6,0x77,0x02,0xA7, + 0xE1,0xCB,0x52,0x97,0x9D,0x89,0x11,0xA0,0x8F,0xBC, + 0xF3,0x8F,0x14,0x01,0x29,0xF3,0xA5,0x45,0x17,0x06, + 0xF8,0x04,0xF2,0x6D,0xD5,0xC3,0x77,0xB8,0x00,0xC2, + 0x0A,0x1A,0x09,0x32,0x36,0x36,0x69,0xC1,0x2A,0xF0, + 0x44,0x37,0xBC,0x7E,0x5F,0x15,0xF7,0x08,0x9C,0x19, + 0x27,0x1D,0x70,0x4F,0xDC,0x17,0x94,0x3C,0xBB,0x24, + 0xB4,0xE6,0xFC,0x71,0x9A,0xD4,0xCF,0x2C,0x12,0xBA, + 0xF0,0xB6,0x8F,0x78,0x99,0xAA,0x8C,0x17,0x7E,0x94, + 0x0C,0x6A,0x37,0x5B,0x35,0x91,0x52,0xFA,0x64,0xA3, + 0x33,0x34,0x99,0x37,0x00,0x3C,0xB4,0x4E,0x6E,0x63, + 0xED,0xC3,0x1D,0x37,0x5B,0x45,0xB4,0xDF,0x82,0xCD, + 0xFE,0xAA,0x92,0x64,0xC8,0x2F,0xD6,0x2D,0x2E,0xB1, + 0xED,0x6A,0x04,0xF1,0xC2,0x48,0x8D,0x4B,0xB4,0x84, + 0x39,0xA3,0x31,0x4D,0xF6,0x63,0xB4,0xC3,0x6E,0xA1, + 0xA5,0x2F,0xD2,0x1E,0xB0,0xC6,0x0C,0xD1,0x04,0x3A, + 0x31,0xBC,0x87,0x49,0xF8,0x26,0x0B,0xD3,0x0C,0x08, + 0x29,0xBB,0x9F,0x4D,0x08,0xF0,0x9C,0x11,0xD3,0xA5, + 0x2C,0x8D,0x98,0xB1,0x1B,0xB1,0x57,0xD3,0x69,0xAE, + 0x9E,0x2D,0xD5,0x64,0x38,0x58,0xC9,0xB2,0x84,0x04, + 0xAB,0x10,0x1D,0xCA,0x6B,0x29,0xA5,0xAB,0xCC,0xFE, + 0xBB,0x74,0xF4,0x35,0x03,0x8F,0x65,0x2A,0x0B,0xBB, + 0xC7,0x17,0x6A,0x49,0x34,0x83,0x30,0x92,0x8D,0xD7, + 0xAE,0x95,0xD0,0xD7,0x23,0xA7,0xE3,0x29,0x09,0xA1, + 0xB1,0x34,0xC3,0x95,0x49,0xC3,0xA4,0xF1,0x36,0x00, + 0x09,0xD3,0xA4,0x09,0xAD,0xF2,0x5C,0x97,0xB2 +}; + +uint8_t _acserverca1_spki[] = { + 0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00, + 0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xe3,0xe9,0x68, + 0xa1,0xe7,0x9b,0xbc,0xf7,0x87,0x48,0x22,0x9b,0x09,0x5f,0xc8, + 0xc9,0xa6,0x9a,0xcc,0xcd,0x40,0x16,0xf8,0xa1,0xd0,0xf6,0x27, + 0x15,0x4c,0xe7,0xd3,0xc1,0x6e,0xdf,0x11,0x06,0x9a,0x63,0xc5, + 0x87,0x55,0xda,0xdf,0xaf,0x15,0x31,0x98,0x45,0xf4,0x8c,0xc2, + 0x3c,0x93,0xa2,0x1c,0xc0,0xf0,0x2a,0x77,0xf4,0x19,0x94,0x96, + 0xf4,0x7b,0x52,0x74,0x84,0x86,0x5a,0x66,0x7d,0x68,0x92,0xa1, + 0x5e,0xe1,0xa9,0x21,0xe0,0x14,0x38,0x84,0x21,0x32,0x8b,0x21, + 0x95,0x47,0x27,0x17,0xa0,0xba,0x7b,0xd7,0xd8,0xd7,0x25,0x20, + 0x77,0xcb,0x62,0x8b,0xc6,0x0f,0xc1,0x49,0xc6,0x2b,0x42,0xe9, + 0x02,0x70,0x9e,0x99,0x44,0x77,0x51,0x05,0x62,0x78,0xbc,0xb0, + 0xd2,0xa7,0xa6,0x91,0x71,0x25,0x58,0x13,0x8d,0x8a,0xc8,0x46, + 0x41,0xdb,0x89,0x41,0xc5,0x23,0x7d,0x84,0xe9,0x02,0xb0,0x1a, + 0xf8,0x5d,0x66,0xd0,0xe1,0xe1,0x72,0xf4,0xa4,0x65,0x79,0x97, + 0x0a,0x7b,0xc0,0xe3,0x24,0x74,0x83,0x4a,0x81,0x5e,0xc3,0xa2, + 0xbf,0x51,0x32,0x96,0x8f,0x28,0x32,0x08,0x49,0xfb,0x02,0x43, + 0x62,0x42,0xb3,0x84,0x84,0x30,0x1b,0x28,0xe4,0x05,0xb9,0xbb, + 0xd6,0xb5,0xc4,0xa2,0xab,0x8e,0x57,0x53,0x29,0xbc,0x0b,0x4f, + 0xd6,0x1e,0xa4,0x52,0xdc,0x16,0x1c,0x95,0xc2,0x8d,0x97,0x6b, + 0xbb,0x3e,0xc8,0x93,0xc7,0x01,0x97,0x1e,0x18,0x09,0x59,0x39, + 0x0f,0x5d,0x73,0x4e,0xa9,0x8f,0x49,0xfd,0x49,0x16,0xbd,0x25, + 0xec,0xd9,0x05,0xea,0xe3,0xb0,0x04,0x0e,0xd9,0x09,0x9e,0xc0, + 0xb7,0x02,0x03,0x01,0x00,0x01 +}; + +uint8_t _acrootca_spki[] = { + 0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00, + 0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xb5,0x3b,0xe3, + 0x9f,0x6a,0x1d,0x0e,0x46,0x51,0x1e,0xd0,0xb5,0x17,0x6b,0x06, + 0x4b,0x92,0xaf,0x38,0x10,0x25,0xa1,0xee,0x1e,0x4e,0xef,0x19, + 0xe0,0x73,0xb5,0x37,0x33,0x72,0x21,0x21,0xcb,0x62,0x4a,0x3d, + 0xa9,0x68,0xd8,0x07,0xb4,0xeb,0x8d,0x0a,0xdb,0x30,0x33,0x21, + 0x2f,0x6f,0xd3,0xf7,0x5d,0xce,0x20,0x0a,0x04,0xdb,0xff,0xbf, + 0x75,0x08,0x42,0x3f,0x3e,0xd8,0xc8,0xef,0xa4,0xf8,0x56,0x7b, + 0x13,0x64,0x6b,0xf3,0xa2,0x38,0x10,0xfa,0xee,0x9d,0x83,0x93, + 0x1d,0xfb,0xef,0x13,0x6c,0x38,0x49,0xdd,0xeb,0x71,0xa6,0x92, + 0x58,0x04,0xde,0x01,0x41,0x2b,0x99,0x5e,0xbd,0x24,0x3f,0x69, + 0xa8,0x44,0xf2,0xaa,0x01,0x78,0xb9,0x38,0x06,0x10,0x77,0x36, + 0xf8,0xf2,0xa3,0x3e,0xd9,0x5f,0xea,0xf5,0x8b,0x6a,0xa6,0x5f, + 0xe6,0x51,0xd0,0x9b,0x50,0xa0,0x1e,0xf5,0x85,0x9e,0x49,0x50, + 0x4a,0x61,0x78,0xda,0x29,0xa7,0x33,0x72,0x8b,0x83,0xee,0x7b, + 0xa7,0x79,0x4e,0x8e,0x02,0x6f,0x9d,0x25,0x97,0x26,0x86,0x0c, + 0x82,0xc5,0x8c,0x16,0x7e,0x49,0x61,0xfd,0xff,0x1a,0xa0,0x0d, + 0x28,0xe1,0x68,0xf5,0xae,0x85,0x72,0xf3,0xab,0xe0,0x74,0x75, + 0xcc,0x57,0x64,0x3c,0x2c,0x55,0x05,0xc9,0x8d,0xaa,0xb3,0xec, + 0xc8,0x62,0x88,0x15,0x2a,0xc4,0x59,0x60,0x37,0xc1,0xed,0x6b, + 0xce,0xe9,0xca,0xaf,0xb0,0xa5,0x45,0xba,0xff,0x16,0x32,0xaa, + 0x92,0x86,0xd9,0xb9,0xa1,0x13,0x75,0x95,0x9b,0x97,0x5c,0x2d, + 0xb5,0x12,0xca,0x6b,0x6b,0x39,0xd6,0x9b,0x4b,0x34,0x47,0xab, + 0x35,0x02,0x03,0x01,0x00,0x01 +}; + +uint8_t _acrootca_hash[] = { + 0x50,0x41,0x69,0xc1,0x76,0xa2,0xc3,0x0d,0xa2,0xe9,0x0e,0xa9, + 0x8a,0x53,0x5d,0x78,0xef,0x42,0xf3,0x1a,0x90,0xfa,0x48,0xb6, + 0xce,0xc2,0x45,0xa4,0x72,0x12,0x7a,0xd3 +}; + + +#endif /* _TRUSTTESTS_EVALUATION_CT_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/CTTests.m b/tests/TrustTests/EvaluationTests/CTTests.m index 7d058ee7..f69fce00 100644 --- a/tests/TrustTests/EvaluationTests/CTTests.m +++ b/tests/TrustTests/EvaluationTests/CTTests.m @@ -34,7 +34,10 @@ #include "trust/trustd/OTATrustUtilities.h" #if !TARGET_OS_BRIDGE +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" #import +#pragma clang diagnostic pop #endif #if TARGET_OS_IPHONE @@ -596,7 +599,7 @@ errOut: ok(SecTrustStoreSetCTExceptions(TrustTestsAppID, (__bridge CFDictionaryRef)empty, &error), "failed to set empty exceptions"); - /* Copy exceptiosn to ensure no change */ + /* Copy exceptions to ensure no change */ ok(copiedExceptions = SecTrustStoreCopyCTExceptions(TrustTestsAppID, &error), "failed to copy TrustTests' exceptions: %@", error); ok([exceptions2 isEqualToDictionary:(__bridge NSDictionary*)copiedExceptions], @@ -628,6 +631,7 @@ errOut: #define check_errSecParam \ if (error) { \ is(CFErrorGetCode(error), errSecParam, "bad input produced unxpected error code: %ld", (long)CFErrorGetCode(error)); \ +CFReleaseNull(error); \ } else { \ fail("expected failure to set NULL exceptions"); \ } @@ -1181,13 +1185,13 @@ static NSArray *keychainCerts = nil; withExtension:@"plist" subdirectory:@"si-82-sectrust-ct-data"]; trustedCTLogs = [NSArray arrayWithContentsOfURL:trustedLogsURL]; +} +- (void)setUp { // set test root to be a fake system root - SecCertificateRef system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"]; NSData *rootHash = [NSData dataWithBytes:_system_root_hash length:sizeof(_system_root_hash)]; CFPreferencesSetAppValue(CFSTR("TestCTRequiredSystemRoot"), (__bridge CFDataRef)rootHash, CFSTR("com.apple.security")); CFPreferencesAppSynchronize(CFSTR("com.apple.security")); - CFReleaseNull(system_root); } #if !TARGET_OS_BRIDGE @@ -1894,4 +1898,320 @@ errOut: CFReleaseNull(trust); } +- (void) testCheckCTRequired { + SecCertificateRef system_root = NULL, system_server_after = NULL; + SecTrustRef trust = NULL; + NSArray *enforce_anchors = nil; + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT + CFErrorRef error = nil; + + // A policy with CTRequired set + SecPolicyRef policy = SecPolicyCreateBasicX509(); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCTRequired, kCFBooleanTrue); + + require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"], + errOut, fail("failed to create system root")); + require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"], + errOut, fail("failed to create system server cert issued after flag day")); + + enforce_anchors = @[ (__bridge id)system_root ]; + require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust")); + require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors")); + require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); + + require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); + + // test system cert without CT fails (with trusted logs) +#if !TARGET_OS_BRIDGE + is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag-date non-CT cert with trusted logs succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecNotTrusted, "got wrong error code for non-ct cert, got %ld, expected %d", + (long)CFErrorGetCode(error), (int)errSecNotTrusted); + } else { + fail("expected trust evaluation to fail and it did not."); + } +#else + /* BridgeOS doesn't enforce */ + ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert with trusted logs failed"); +#endif + +errOut: + CFReleaseNull(system_root); + CFReleaseNull(system_server_after); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(error); + +} + +- (void)testCTPolicyV2 { + SecCertificateRef system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"policyv2_root"]; + SecCertificateRef six_month_leaf_1 = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"policyv2_six_months_1_sct"]; + SecCertificateRef six_month_leaf_2 = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"policyv2_six_months_2_scts"]; + SecCertificateRef one_year_leaf_2_before = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"policyv2_one_year_2_scts_before"]; + SecCertificateRef one_year_leaf_2_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"policyv2_one_year_2_scts_after"]; + SecCertificateRef one_year_leaf_3_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"policyv2_one_year_3_scts_after"]; + + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("example.com")); + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:641000000.0]; // April 24, 2021 at 4:33:20 PM PDT + + // Set root as system root + CFDataRef rootHash = SecCertificateCopySHA256Digest(system_root); + CFPreferencesSetAppValue(CFSTR("TestCTRequiredSystemRoot"), rootHash, CFSTR("com.apple.security")); + CFPreferencesAppSynchronize(CFSTR("com.apple.security")); + CFReleaseNull(rootHash); + + // < 180 days, after, 1 SCT -> fail + TestTrustEvaluation *test = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)six_month_leaf_1] + policies:@[(__bridge id)policy]]; + [test setAnchors:@[(__bridge id)system_root]]; + [test setVerifyDate:date]; + [test setTrustedCTLogs:trustedCTLogs]; +#if !TARGET_OS_BRIDGE + XCTAssertFalse([test evaluate:nil]); +#else + XCTAssertTrue([test evaluate:nil]); +#endif + + // < 180 days, after, 2 SCTs -> success + test = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)six_month_leaf_2] + policies:@[(__bridge id)policy]]; + [test setAnchors:@[(__bridge id)system_root]]; + [test setVerifyDate:date]; + [test setTrustedCTLogs:trustedCTLogs]; + XCTAssertTrue([test evaluate:nil]); + + // > 180 days, < 15 months, before, 2 SCTs -> success + test = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)one_year_leaf_2_before] + policies:@[(__bridge id)policy]]; + [test setAnchors:@[(__bridge id)system_root]]; + [test setVerifyDate:date]; + [test setTrustedCTLogs:trustedCTLogs]; + XCTAssertTrue([test evaluate:nil]); + + // > 180 days, < 15 months, after, 2 SCTs -> success + test = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)one_year_leaf_2_after] + policies:@[(__bridge id)policy]]; + [test setAnchors:@[(__bridge id)system_root]]; + [test setVerifyDate:date]; + [test setTrustedCTLogs:trustedCTLogs]; +#if !TARGET_OS_BRIDGE + XCTAssertFalse([test evaluate:nil]); +#else + XCTAssertTrue([test evaluate:nil]); +#endif + + // > 180 days, < 15 months, before, 3 SCTs -> success + test = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)one_year_leaf_3_after] + policies:@[(__bridge id)policy]]; + [test setAnchors:@[(__bridge id)system_root]]; + [test setVerifyDate:date]; + [test setTrustedCTLogs:trustedCTLogs]; + XCTAssertTrue([test evaluate:nil]); + + CFReleaseNull(system_root); + CFReleaseNull(six_month_leaf_1); + CFReleaseNull(six_month_leaf_2); + CFReleaseNull(one_year_leaf_2_before); + CFReleaseNull(one_year_leaf_2_after); + CFReleaseNull(one_year_leaf_3_after); + CFReleaseNull(policy); +} + +@end + +// MARK: - +// MARK: Non-TLS CT tests + +@interface NonTlsCTTests : TrustEvaluationTestCase +@end + +@implementation NonTlsCTTests ++ (void)setUp { + [super setUp]; + NSURL *trustedLogsURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"CTlogs" + withExtension:@"plist" + subdirectory:@"si-82-sectrust-ct-data"]; + trustedCTLogs = [NSArray arrayWithContentsOfURL:trustedLogsURL]; +} + +- (SecPolicyRef)nonTlsCTRequiredPolicy +{ + SecPolicyRef policy = SecPolicyCreateBasicX509(); + SecPolicySetOptionsValue(policy, kSecPolicyCheckNonTlsCTRequired, kCFBooleanTrue); + return policy; +} + +#if !TARGET_OS_BRIDGE +/* Skip tests on bridgeOS where we don't do MobileAsset updates */ +- (void)testNoMACheckIn { + SecCertificateRef system_root = NULL, system_server_after = NULL; + SecTrustRef trust = NULL; + SecPolicyRef policy = [self nonTlsCTRequiredPolicy]; + NSArray *enforce_anchors = nil; + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT + + /* Mock a failing MobileAsset so we don't enforce via MobileAsset */ + id mockFailedMA = OCMClassMock([MAAsset class]); + OCMStub([mockFailedMA startCatalogDownload:[OCMArg any] + options:[OCMArg any] + then:([OCMArg invokeBlockWithArgs:OCMOCK_VALUE((NSInteger){MADownloadFailed}), nil])]); + SecOTAPKIResetCurrentAssetVersion(NULL); + + require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"], + errOut, fail("failed to create system root")); + require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"], + errOut, fail("failed to create server cert")); + + enforce_anchors = @[ (__bridge id)system_root ]; + require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust")); + require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors")); + require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); + + // Out-of-date asset, test cert without CT passes + ok(SecTrustEvaluateWithError(trust, NULL), "non-CT cert failed with out-of-date asset"); + +errOut: + CFReleaseNull(system_root); + CFReleaseNull(system_server_after); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + +- (void)testKillSwitch { + SecCertificateRef system_root = NULL, system_server_after = NULL; + SecTrustRef trust = NULL; + SecPolicyRef policy = [self nonTlsCTRequiredPolicy]; + NSArray *enforce_anchors = nil; + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT + + /* Mock setting a kill switch */ + UpdateKillSwitch((__bridge NSString *)kOTAPKIKillSwitchNonTLSCT, true); + + require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"], + errOut, fail("failed to create system root")); + require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"], + errOut, fail("failed to create system server cert")); + + enforce_anchors = @[ (__bridge id)system_root ]; + require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust")); + require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors")); + require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); + + // CT kill switch enabled so test cert without CT passes + ok(SecTrustEvaluateWithError(trust, NULL), "non-CT cert failed with kill switch enabled"); + + /* Remove the kill switch */ + UpdateKillSwitch((__bridge NSString *)kOTAPKIKillSwitchNonTLSCT, false); + +errOut: + CFReleaseNull(system_root); + CFReleaseNull(system_server_after); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + +- (void) testWithMACheckIn { + SecCertificateRef system_root = NULL, system_server_after = NULL; + SecTrustRef trust = NULL; + SecPolicyRef policy = [self nonTlsCTRequiredPolicy]; + NSArray *enforce_anchors = nil; + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT + CFErrorRef error = nil; + + /* Mock a successful mobile asset check-in so that we enforce CT */ + XCTAssertTrue(UpdateOTACheckInDate(), "failed to set check-in date as now"); + + require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"], + errOut, fail("failed to create system root")); + require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"], + errOut, fail("failed to create system server cert")); + + enforce_anchors = @[ (__bridge id)system_root ]; + require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust")); + require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors")); + require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); + + // test system cert after date without CT fails (with check-in) + is(SecTrustEvaluateWithError(trust, &error), false, "non-CT cert with in-date asset succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d", + (long)CFErrorGetCode(error), (int)errSecVerifyActionFailed); + } else { + fail("expected trust evaluation to fail and it did not."); + } + +errOut: + CFReleaseNull(system_root); + CFReleaseNull(system_server_after); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(error); +} +#endif // !TARGET_OS_BRIDGE + +- (void)testWithTrustedLogs { + SecCertificateRef system_root = NULL, system_server_after = NULL; + SecTrustRef trust = NULL; + SecPolicyRef policy = [self nonTlsCTRequiredPolicy]; + NSArray *enforce_anchors = nil; + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT + CFErrorRef error = nil; + + require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"], + errOut, fail("failed to create system root")); + require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"], + errOut, fail("failed to create system server cert")); + + enforce_anchors = @[ (__bridge id)system_root ]; + require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust")); + require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors")); + require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); + + // set trusted logs to trigger enforcing behavior + require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); + + // test system cert without CT fails (with trusted logs) + is(SecTrustEvaluateWithError(trust, &error), false, "non-CT cert with trusted logs succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecVerifyActionFailed, "got wrong error code for non-ct cert, got %ld, expected %d", + (long)CFErrorGetCode(error), (int)errSecVerifyActionFailed); + } else { + fail("expected trust evaluation to fail and it did not."); + } + +errOut: + CFReleaseNull(system_root); + CFReleaseNull(system_server_after); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(error); +} + +- (void) testSuccess { + SecCertificateRef system_root = NULL, leaf = NULL; + SecTrustRef trust = NULL; + SecPolicyRef policy = [self nonTlsCTRequiredPolicy]; + NSArray *enforce_anchors = nil; + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT + + require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"], + errOut, fail("failed to create system root")); + require_action(leaf = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after_scts"], + errOut, fail("failed to create system server cert")); + + enforce_anchors = @[ (__bridge id)system_root ]; + require_noerr_action(SecTrustCreateWithCertificates(leaf, policy, &trust), errOut, fail("failed to create trust")); + require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors")); + require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); + require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); + ok(SecTrustEvaluateWithError(trust, NULL), "CT cert failed"); + +errOut: + CFReleaseNull(system_root); + CFReleaseNull(leaf); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + @end diff --git a/tests/TrustTests/EvaluationTests/ECTests_data.h b/tests/TrustTests/EvaluationTests/ECTests_data.h index dcdee64f..a4224def 100644 --- a/tests/TrustTests/EvaluationTests/ECTests_data.h +++ b/tests/TrustTests/EvaluationTests/ECTests_data.h @@ -698,43 +698,48 @@ unsigned char End_P521_combined_SHA512_cer[733]={ 0x4F,0x29,0xC3,0xA9,0x04,0xE3,0xB9,0xCB,0xA3,0xF7,0xF0,0x80,0x5C,0x61,0xCF,0x1F, 0x8B,0xEE,0x79,0xBD,0x16,0x2D,0x5B,0xF3,0xBD,0xF2,0x84,0x49,0xF8, }; + +/* The signature of this root has been invalidated in order to add Basic Constraints + * in support of . Because the root is treated as an anchor by the tests, + * the invalid signature does not cause the tests to fail. */ /* subject:/CN=\x00R\x00O\x00O\x00T\x00_\x00P\x002\x005\x006 */ /* issuer :/CN=\x00R\x00O\x00O\x00T\x00_\x00P\x002\x005\x006 */ -unsigned char RootP256_cer[539]={ - 0x30,0x82,0x02,0x17,0x30,0x82,0x01,0xB0,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x8F, - 0x92,0x09,0xDB,0xA4,0xFC,0xDA,0xA1,0x45,0xC2,0xFA,0x59,0x87,0xC6,0xEA,0xE6,0x30, - 0x18,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x30,0x0D,0x06,0x09,0x60,0x86, - 0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x30,0x1D,0x31,0x1B,0x30,0x19,0x06, - 0x03,0x55,0x04,0x03,0x1E,0x12,0x00,0x52,0x00,0x4F,0x00,0x4F,0x00,0x54,0x00,0x5F, - 0x00,0x50,0x00,0x32,0x00,0x35,0x00,0x36,0x30,0x1E,0x17,0x0D,0x30,0x31,0x30,0x34, - 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x30,0x31,0x32,0x33, - 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x1D,0x31,0x1B,0x30,0x19,0x06,0x03, - 0x55,0x04,0x03,0x1E,0x12,0x00,0x52,0x00,0x4F,0x00,0x4F,0x00,0x54,0x00,0x5F,0x00, - 0x50,0x00,0x32,0x00,0x35,0x00,0x36,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42, - 0x00,0x04,0x85,0x59,0x2A,0x87,0x8E,0x6A,0x9B,0xB9,0x19,0xD4,0x73,0x82,0x24,0xC1, - 0x03,0x15,0xB3,0xF1,0x70,0x88,0x1B,0xAA,0xBA,0x57,0xE8,0x76,0x9F,0xC0,0xCE,0xF6, - 0xA9,0xBB,0x19,0xF5,0x6B,0x09,0x63,0xFB,0x69,0xA1,0x3D,0x88,0x67,0x3E,0x7E,0x1F, - 0x7B,0x18,0xC8,0xF2,0x31,0xE6,0xD7,0x54,0xD5,0xA7,0xAA,0x09,0x9C,0x15,0xD1,0x8D, - 0x37,0x7F,0xA3,0x81,0xC3,0x30,0x81,0xC0,0x30,0x81,0xBD,0x06,0x0F,0x2B,0x06,0x01, - 0x04,0x01,0x82,0x37,0x13,0x82,0xDF,0x67,0x86,0xA3,0x53,0x01,0x04,0x81,0xA9,0x30, - 0x81,0xA6,0x04,0x12,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x53, - 0x61,0x6D,0x70,0x6C,0x65,0x00,0x04,0x0A,0x52,0x4F,0x4F,0x54,0x5F,0x50,0x32,0x35, - 0x36,0x00,0x02,0x01,0x00,0x02,0x01,0x00,0x04,0x14,0x45,0x00,0x43,0x00,0x44,0x00, - 0x53,0x00,0x41,0x00,0x5F,0x00,0x50,0x00,0x32,0x00,0x35,0x00,0x36,0x00,0x04,0x68, - 0x45,0x43,0x53,0x32,0x20,0x00,0x00,0x00,0x85,0x59,0x2A,0x87,0x8E,0x6A,0x9B,0xB9, - 0x19,0xD4,0x73,0x82,0x24,0xC1,0x03,0x15,0xB3,0xF1,0x70,0x88,0x1B,0xAA,0xBA,0x57, - 0xE8,0x76,0x9F,0xC0,0xCE,0xF6,0xA9,0xBB,0x19,0xF5,0x6B,0x09,0x63,0xFB,0x69,0xA1, - 0x3D,0x88,0x67,0x3E,0x7E,0x1F,0x7B,0x18,0xC8,0xF2,0x31,0xE6,0xD7,0x54,0xD5,0xA7, - 0xAA,0x09,0x9C,0x15,0xD1,0x8D,0x37,0x7F,0x61,0x97,0x7D,0x85,0xBF,0x7E,0x4E,0xD5, - 0x70,0x08,0xF2,0xE8,0xB5,0xBC,0x39,0x59,0xB3,0x23,0x97,0x5F,0xD4,0xCB,0x63,0x74, - 0xB9,0x88,0x6D,0xD6,0xF4,0xB8,0x20,0xA8,0x30,0x18,0x06,0x07,0x2A,0x86,0x48,0xCE, - 0x3D,0x04,0x03,0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01, - 0x05,0x00,0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x44,0xC4,0xBD,0x7A,0xDE,0x6F,0x41, - 0xA6,0x78,0x82,0xFD,0x32,0xB7,0x55,0xCA,0xE3,0x21,0x01,0x1C,0xD5,0x6A,0x0B,0x19, - 0xA4,0xA9,0x4D,0x06,0x6F,0xB2,0xE8,0xBF,0x9E,0x02,0x20,0x20,0x1C,0x24,0xEA,0x39, - 0x24,0xEB,0x91,0xBE,0x73,0x76,0xAF,0xFC,0x99,0x60,0xEC,0x22,0xFD,0x43,0xBF,0xDA, - 0xF3,0x7F,0xE4,0x8E,0x6C,0xA5,0x46,0xBF,0x64,0x01,0x3D, +unsigned char RootP256_cer[]={ + 0x30, 0x82, 0x02, 0x28, 0x30, 0x82, 0x01, 0xc1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x8f, + 0x92, 0x09, 0xdb, 0xa4, 0xfc, 0xda, 0xa1, 0x45, 0xc2, 0xfa, 0x59, 0x87, 0xc6, 0xea, 0xe6, 0x30, + 0x18, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x1e, 0x12, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x5f, + 0x00, 0x50, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x34, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x30, 0x31, 0x32, 0x33, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x1e, 0x12, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x5f, 0x00, + 0x50, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, + 0x00, 0x04, 0x85, 0x59, 0x2a, 0x87, 0x8e, 0x6a, 0x9b, 0xb9, 0x19, 0xd4, 0x73, 0x82, 0x24, 0xc1, + 0x03, 0x15, 0xb3, 0xf1, 0x70, 0x88, 0x1b, 0xaa, 0xba, 0x57, 0xe8, 0x76, 0x9f, 0xc0, 0xce, 0xf6, + 0xa9, 0xbb, 0x19, 0xf5, 0x6b, 0x09, 0x63, 0xfb, 0x69, 0xa1, 0x3d, 0x88, 0x67, 0x3e, 0x7e, 0x1f, + 0x7b, 0x18, 0xc8, 0xf2, 0x31, 0xe6, 0xd7, 0x54, 0xd5, 0xa7, 0xaa, 0x09, 0x9c, 0x15, 0xd1, 0x8d, + 0x37, 0x7f, 0xa3, 0x81, 0xd4, 0x30, 0x81, 0xd1, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x81, 0xbd, 0x06, 0x0f, 0x2b, 0x06, + 0x01, 0x04, 0x01, 0x82, 0x37, 0x13, 0x82, 0xdf, 0x67, 0x86, 0xa3, 0x53, 0x01, 0x04, 0x81, 0xa9, + 0x30, 0x81, 0xa6, 0x04, 0x12, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00, 0x04, 0x0a, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x32, + 0x35, 0x36, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x04, 0x14, 0x45, 0x00, 0x43, 0x00, 0x44, + 0x00, 0x53, 0x00, 0x41, 0x00, 0x5f, 0x00, 0x50, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x04, + 0x68, 0x45, 0x43, 0x53, 0x32, 0x20, 0x00, 0x00, 0x00, 0x85, 0x59, 0x2a, 0x87, 0x8e, 0x6a, 0x9b, + 0xb9, 0x19, 0xd4, 0x73, 0x82, 0x24, 0xc1, 0x03, 0x15, 0xb3, 0xf1, 0x70, 0x88, 0x1b, 0xaa, 0xba, + 0x57, 0xe8, 0x76, 0x9f, 0xc0, 0xce, 0xf6, 0xa9, 0xbb, 0x19, 0xf5, 0x6b, 0x09, 0x63, 0xfb, 0x69, + 0xa1, 0x3d, 0x88, 0x67, 0x3e, 0x7e, 0x1f, 0x7b, 0x18, 0xc8, 0xf2, 0x31, 0xe6, 0xd7, 0x54, 0xd5, + 0xa7, 0xaa, 0x09, 0x9c, 0x15, 0xd1, 0x8d, 0x37, 0x7f, 0x61, 0x97, 0x7d, 0x85, 0xbf, 0x7e, 0x4e, + 0xd5, 0x70, 0x08, 0xf2, 0xe8, 0xb5, 0xbc, 0x39, 0x59, 0xb3, 0x23, 0x97, 0x5f, 0xd4, 0xcb, 0x63, + 0x74, 0xb9, 0x88, 0x6d, 0xd6, 0xf4, 0xb8, 0x20, 0xa8, 0x30, 0x18, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x04, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x01, 0x05, 0x00, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x44, 0xc4, 0xbd, 0x7a, 0xde, 0x6f, + 0x41, 0xa6, 0x78, 0x82, 0xfd, 0x32, 0xb7, 0x55, 0xca, 0xe3, 0x21, 0x01, 0x1c, 0xd5, 0x6a, 0x0b, + 0x19, 0xa4, 0xa9, 0x4d, 0x06, 0x6f, 0xb2, 0xe8, 0xbf, 0x9e, 0x02, 0x20, 0x20, 0x1c, 0x24, 0xea, + 0x39, 0x24, 0xeb, 0x91, 0xbe, 0x73, 0x76, 0xaf, 0xfc, 0x99, 0x60, 0xec, 0x22, 0xfd, 0x43, 0xbf, + 0xda, 0xf3, 0x7f, 0xe4, 0x8e, 0x6c, 0xa5, 0x46, 0xbf, 0x64, 0x01, 0x3d }; /* subject:/C=US/ST=CA/L=Mountain View/O=Sun Microsystems Laboratories/OU=Test CA (secp256r1)/CN=dev.experimentalstuff.com */ diff --git a/tests/TrustTests/EvaluationTests/ExceptionTests.m b/tests/TrustTests/EvaluationTests/ExceptionTests.m new file mode 100644 index 00000000..a997538d --- /dev/null +++ b/tests/TrustTests/EvaluationTests/ExceptionTests.m @@ -0,0 +1,330 @@ +/* +* Copyright (c) 2006-2010,2012-2019 Apple Inc. All Rights Reserved. +*/ + +#include +#import +#import +#include +#include +#include "OSX/utilities/array_size.h" +#include "OSX/utilities/SecCFWrappers.h" + +#import "../TestMacroConversions.h" +#import "TrustEvaluationTestCase.h" + +#import "ExceptionTests_data.h" + +@interface TrustExceptionTests : TrustEvaluationTestCase +@end + +@implementation TrustExceptionTests + +static NSArray *certs = nil; +static NSDate *date = nil; + ++ (void)setUp +{ + [super setUp]; + SecCertificateRef cert0 = SecCertificateCreateWithBytes(NULL, _exception_cert0, sizeof(_exception_cert0)); + SecCertificateRef cert1 = SecCertificateCreateWithBytes(NULL, _exception_cert1, sizeof(_exception_cert1)); + certs = @[ (__bridge id)cert0, (__bridge id)cert1 ]; + date = [NSDate dateWithTimeIntervalSinceReferenceDate:545000000.0]; /* April 9, 2018 at 1:53:20 PM PDT */ + + CFReleaseNull(cert0); + CFReleaseNull(cert1); +} + +#if !TARGET_OS_BRIDGE +// bridgeOS doesn't have a system root store +- (void)testPassingTrust +{ + SecTrustRef trust = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("store.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + + SecTrustResultType trustResult; + ok(SecTrustEvaluateWithError(trust, NULL), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult)); + is_status(trustResult, kSecTrustResultUnspecified, + "trust is kSecTrustResultUnspecified"); + CFDataRef exceptions; + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + CFReleaseNull(trust); + CFReleaseNull(policy); + CFReleaseNull(exceptions); +} +#endif + +- (void)testFailingTrust +{ + SecTrustRef trust = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("badstore.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + + SecTrustResultType trustResult; + XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult)); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure); + CFDataRef exceptions; + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + CFReleaseNull(trust); + CFReleaseNull(policy); + CFReleaseNull(exceptions); +} + +- (void)testNewTrustObjectSameFailure +{ + SecTrustRef trust = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("badstore.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + + SecTrustResultType trustResult; + XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult)); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure); + CFDataRef exceptions; + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + /* new trust with the same failing policy and certs should pass */ + CFReleaseNull(trust); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + CFReleaseNull(trust); + CFReleaseNull(policy); + CFReleaseNull(exceptions); +} + +#if !TARGET_OS_BRIDGE +// bridgeOS always has an AnchorTrusted error due to lack of a system root store +- (void)testIntroduceNewAnchorTrustedFailure +{ + SecTrustRef trust = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("badstore.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + + SecTrustResultType trustResult; + XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult)); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure); + CFDataRef exceptions; + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + // new AnchorTrusted failure + ok_status(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)@[]), "set empty anchor list"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); + + // fix AnchorTrusted failure + ok_status(SecTrustSetAnchorCertificatesOnly(trust, false), "trust passed in anchors and system anchors"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + CFReleaseNull(trust); + CFReleaseNull(policy); + CFReleaseNull(exceptions); +} +#endif + +- (void)testIntroduceNewExpiredFailure +{ + SecTrustRef trust = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("badstore.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + + SecTrustResultType trustResult; + XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult)); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure); + CFDataRef exceptions; + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + // new expiry failure + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)[NSDate dateWithTimeIntervalSinceReferenceDate:667680000.0]), + "set date to far future so certs are expired"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); + + CFReleaseNull(trust); + CFReleaseNull(policy); + CFReleaseNull(exceptions); +} + +- (void)testNewTrustObjectNewHostnameFailure +{ + SecTrustRef trust = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("store.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + CFDataRef exceptions; + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + + CFReleaseNull(trust); + CFReleaseNull(policy); + policy = SecPolicyCreateSSL(true, CFSTR("badstore.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust with hostname mismatch"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + + /* exceptions from the old trust evaluation should fail */ + SecTrustResultType trustResult; + ok(SecTrustSetExceptions(trust, exceptions), "set old exceptions"); + XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult)); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure); + + /* we should be able to get new exceptions and pass */ + CFReleaseNull(exceptions); + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + CFReleaseNull(trust); + CFReleaseNull(policy); + CFReleaseNull(exceptions); +} + +- (void)testClearExceptions +{ + SecTrustRef trust = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("badstore.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + + SecTrustResultType trustResult; + XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult)); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure); + CFDataRef exceptions; + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + XCTAssertFalse(SecTrustSetExceptions(trust, NULL)); + ok_status(SecTrustGetTrustResult(trust, &trustResult)); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure); + + CFReleaseNull(trust); + CFReleaseNull(policy); + CFReleaseNull(exceptions); +} + +- (void)testWrongCertForExceptions +{ + SecTrustRef trust = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("badstore.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + + SecTrustResultType trustResult; + XCTAssertFalse(SecTrustEvaluateWithError(trust, NULL), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult)); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure); + CFDataRef exceptions; + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + /* new trust with the same failing policy and certs should pass */ + CFReleaseNull(trust); + CFReleaseNull(policy); + SecCertificateRef sscert0 = SecCertificateCreateWithBytes(NULL, _exception_self_signed, sizeof(_exception_self_signed)); + policy = SecPolicyCreateSSL(false, CFSTR("self-signed.ssltest.apple.com")); + ok_status(SecTrustCreateWithCertificates(sscert0, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + XCTAssertFalse(SecTrustSetExceptions(trust, exceptions), "set exceptions fails for other cert"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure); + + CFReleaseNull(trust); + CFReleaseNull(policy); + CFReleaseNull(exceptions); +} + +- (void)testExtensionsEpoch +{ + SecTrustRef trust = NULL; + SecTrustResultType trustResult; + CFDataRef exceptions = NULL; + + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("badstore.apple.com")); + ok_status(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), "set date"); + ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); + + /* Test the uninitialized extensions epoch. */ + CFErrorRef exceptionResetCountError = NULL; + uint64_t exceptionResetCount = SecTrustGetExceptionResetCount(&exceptionResetCountError); + ok(exceptionResetCount == 0, "exception reset count is uninitialized"); + CFReleaseNull(exceptionResetCountError); + is(SecTrustGetExceptionResetCount(&exceptionResetCountError), exceptionResetCount, "SecTrustGetExceptionResetCount is idempotent"); + ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); + + /* Test increasing the extensions epoch. */ + CFReleaseNull(exceptionResetCountError); + ok_status(SecTrustIncrementExceptionResetCount(&exceptionResetCountError), "increase exception reset count"); + CFReleaseNull(exceptionResetCountError); + is(SecTrustGetExceptionResetCount(&exceptionResetCountError), 1 + exceptionResetCount, "exception reset count is 1 + previous count"); + + /* Test trust evaluation under a future extensions epoch. */ + ok(!SecTrustSetExceptions(trust, exceptions), "set exceptions"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); + + CFReleaseNull(trust); + CFReleaseNull(policy); + CFReleaseNull(exceptions); +} + +#if !TARGET_OS_BRIDGE +// bridgeOS doesn't support Valid +- (void)testFatalResultsNonOverride +{ + id root = [self SecCertificateCreateFromPEMResource:@"ca-ki" subdirectory:@"si-88-sectrust-valid-data"]; + id revokedLeaf = [self SecCertificateCreateFromPEMResource:@"leaf-ki-revoked1" subdirectory:@"si-88-sectrust-valid-data"]; + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[revokedLeaf, root] policies:nil]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:542400000.0]]; // March 10, 2018 at 10:40:00 AM PST + [eval setAnchors:@[root]]; + XCTAssertFalse([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultFatalTrustFailure); + + /* try to set exceptions on the trust and ensure it still fails */ + NSData *exceptions = CFBridgingRelease(SecTrustCopyExceptions(eval.trust)); + XCTAssertNotNil(exceptions); + XCTAssert(SecTrustSetExceptions(eval.trust, (__bridge CFDataRef)exceptions)); + XCTAssertFalse([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultFatalTrustFailure); +} +#endif + +@end diff --git a/OSX/sec/Security/Regressions/secitem/si-27-sectrust-exceptions.c b/tests/TrustTests/EvaluationTests/ExceptionTests_data.h similarity index 58% rename from OSX/sec/Security/Regressions/secitem/si-27-sectrust-exceptions.c rename to tests/TrustTests/EvaluationTests/ExceptionTests_data.h index fffb493d..e6dc309c 100644 --- a/OSX/sec/Security/Regressions/secitem/si-27-sectrust-exceptions.c +++ b/tests/TrustTests/EvaluationTests/ExceptionTests_data.h @@ -1,17 +1,9 @@ /* - * Copyright (c) 2006-2010,2012-2018 Apple Inc. All Rights Reserved. - */ +* Copyright (c) 2019 Apple Inc. All Rights Reserved. +*/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" +#ifndef _TRUSTTESTS_EXCEPTION_TESTS_H_ +#define _TRUSTTESTS_EXCEPTION_TESTS_H_ /* Serial Number: @@ -23,7 +15,7 @@ Not After : Mar 23 12:00:00 2019 GMT Subject: businessCategory=Private Organization/jurisdictionC=US/jurisdictionST=California/serialNumber=C0806592, C=US, ST=California, L=Cupertino, O=Apple Inc., OU=Internet Services for Akamai, CN=store.apple.com */ -static unsigned char _c0[]={ +static unsigned char _exception_cert0[]={ 0x30,0x82,0x06,0xF7,0x30,0x82,0x05,0xDF,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x01, 0xF1,0xEB,0xDB,0xEE,0xD3,0x1D,0x7A,0xB5,0x72,0x54,0x7D,0x34,0x43,0x4B,0x87,0x30, 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x75, @@ -140,7 +132,7 @@ static unsigned char _c0[]={ /* subject:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA */ /* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA */ -static unsigned char _c1[]={ +static unsigned char _exception_cert1[]={ 0x30,0x82,0x04,0xB6,0x30,0x82,0x03,0x9E,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x0C, 0x79,0xA9,0x44,0xB0,0x8C,0x11,0x95,0x20,0x92,0x61,0x5F,0xE2,0x6B,0x1D,0x83,0x30, 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6C, @@ -221,211 +213,57 @@ static unsigned char _c1[]={ /* subject:/CN=self-signed.ssltest.apple.com/C=US */ /* issuer :/CN=self-signed.ssltest.apple.com/C=US */ - -static unsigned char _ss0[]={ - 0x30,0x82,0x03,0x0F,0x30,0x82,0x01,0xF7,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x01, - 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30, - 0x35,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x0C,0x1D,0x73,0x65,0x6C,0x66, - 0x2D,0x73,0x69,0x67,0x6E,0x65,0x64,0x2E,0x73,0x73,0x6C,0x74,0x65,0x73,0x74,0x2E, - 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x36,0x30,0x37, - 0x32,0x31,0x35,0x33,0x30,0x38,0x5A,0x17,0x0D,0x31,0x37,0x30,0x36,0x30,0x37,0x32, - 0x31,0x35,0x33,0x30,0x38,0x5A,0x30,0x35,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04, - 0x03,0x0C,0x1D,0x73,0x65,0x6C,0x66,0x2D,0x73,0x69,0x67,0x6E,0x65,0x64,0x2E,0x73, - 0x73,0x6C,0x74,0x65,0x73,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01, - 0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, - 0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xCC,0x72, - 0x7D,0x09,0x36,0x5A,0x6A,0xED,0xC1,0x7A,0x2C,0xF4,0x7C,0x58,0x63,0x05,0x3E,0x91, - 0x68,0x55,0xB1,0x2A,0x5D,0x57,0xF3,0xA4,0xA7,0x80,0x05,0x41,0x74,0xB2,0xAD,0x5A, - 0x7F,0x38,0xF6,0xF7,0xFD,0xF9,0x64,0x4D,0xDE,0xF9,0x7A,0xD3,0x8C,0x78,0xE9,0x71, - 0xCF,0x1D,0x3E,0xF0,0xDB,0x12,0x48,0x74,0x22,0xA8,0x1F,0x3F,0xB9,0xDD,0xB0,0xAD, - 0x8C,0x10,0x64,0x05,0x0E,0xE2,0x59,0x9A,0xEB,0x3F,0xBF,0xA9,0x48,0x07,0xD9,0x2C, - 0x07,0x44,0x70,0x14,0x16,0x56,0x9C,0x73,0x01,0x2E,0x0B,0xF1,0x2A,0x9F,0x1C,0xC6, - 0x78,0x56,0xB7,0x0B,0xDA,0xA6,0xE6,0x99,0x87,0x2D,0x49,0xFB,0xF0,0x47,0x22,0xA6, - 0x8B,0xF0,0x02,0x37,0x31,0xD0,0x34,0x9F,0x43,0xD1,0x24,0x49,0x94,0x7F,0xFD,0x48, - 0x9C,0xBA,0x5D,0x6B,0xD4,0xF9,0x9E,0xB5,0x18,0xE4,0xB2,0x06,0x46,0xC3,0xD9,0xE7, - 0x80,0xD8,0x61,0xA9,0x09,0x5E,0xBA,0x2E,0x58,0x56,0xAE,0x37,0x31,0x6E,0x87,0x98, - 0xD5,0xC9,0x2B,0x31,0x5C,0x40,0x01,0xDF,0xD5,0x63,0x9E,0x05,0x18,0x21,0x53,0x70, - 0x62,0x36,0x44,0xCD,0x02,0xC0,0xCC,0x6A,0x58,0xC6,0xF6,0xA4,0xDC,0x89,0x94,0xBD, - 0x4E,0xC4,0xEE,0xEE,0x40,0x31,0x59,0xC3,0x43,0xAD,0x34,0x30,0xDE,0xA9,0xA7,0x0D, - 0x85,0xF7,0x96,0x8C,0x45,0xC1,0x6E,0x85,0x39,0x97,0xA6,0x4F,0xEA,0xE8,0x2F,0x01, - 0x3D,0xC0,0x3B,0x34,0x9F,0x8F,0xCB,0xD6,0x22,0x79,0x2C,0x8C,0x8C,0xE6,0xBB,0x1F, - 0x89,0x87,0x93,0x3B,0x39,0x4E,0x64,0x7D,0xDA,0x4D,0x52,0x4C,0x97,0xE5,0x02,0x03, - 0x01,0x00,0x01,0xA3,0x2A,0x30,0x28,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, - 0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01, - 0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, - 0x01,0x01,0x00,0x36,0x06,0xC9,0xE6,0x98,0xC2,0x84,0x1D,0x13,0x1E,0x54,0x35,0x6D, - 0xE5,0xCB,0xC5,0xFD,0xD9,0x54,0x45,0x83,0x53,0xB3,0x3B,0xE7,0x30,0x6F,0xAE,0xEA, - 0x63,0x3F,0xA8,0xFA,0xD9,0x6D,0x0F,0x7D,0xD4,0xB6,0x28,0x66,0xF9,0x57,0x87,0x3E, - 0x57,0x27,0xB6,0x9A,0x56,0xAE,0xD7,0xE0,0x11,0x20,0x71,0xC1,0xEA,0xF6,0xED,0x74, - 0x1A,0x5A,0xB1,0x74,0x6C,0xBE,0xAC,0x0E,0x3C,0xD9,0x3E,0xEC,0x17,0x6E,0xF0,0x69, - 0xC9,0x4D,0xD2,0x7E,0xAE,0x8B,0x01,0xCC,0x1A,0x23,0x7C,0x58,0x07,0x30,0xE4,0x2A, - 0x12,0xE8,0xA0,0x25,0x65,0x66,0xB5,0xC7,0x5D,0xD8,0x47,0xDF,0xD7,0x51,0xBC,0xA2, - 0xAA,0xF0,0x2F,0xB5,0x9E,0x20,0x6D,0x1F,0x84,0x00,0xF0,0xD0,0xB8,0x42,0x6A,0x9A, - 0xE7,0xCA,0x7B,0xE5,0x39,0x09,0x91,0xBF,0xCB,0x4D,0x7A,0x32,0x1E,0x00,0x6E,0xE5, - 0xF7,0x44,0x80,0x82,0x38,0x53,0x64,0xB7,0x26,0x81,0xCB,0xCE,0xA1,0xAF,0x0C,0x67, - 0x32,0xC6,0xE4,0x5D,0x09,0x7B,0x37,0xD7,0xC8,0x43,0x44,0xEF,0xC6,0xF8,0x72,0xFF, - 0x65,0xD4,0x39,0x3D,0xEC,0x72,0xA5,0x28,0xFF,0x70,0x47,0x38,0xA3,0xC7,0xCC,0x5E, - 0x0F,0xFF,0x43,0x83,0x78,0x49,0x68,0x90,0x48,0x89,0xAD,0xE1,0x2E,0xFA,0x8F,0x59, - 0xB6,0x08,0x2A,0x72,0x2F,0x52,0x3F,0x73,0x84,0xCA,0xD8,0x18,0x6C,0xDA,0xA3,0x2E, - 0xF2,0xD7,0x4C,0x21,0xD9,0xF8,0xB1,0x86,0xE9,0x35,0x78,0xE4,0x4F,0xD0,0x93,0x11, - 0x8F,0xF4,0xB1,0x17,0x4F,0xDE,0xAC,0xBD,0xA9,0xBC,0x94,0xFC,0x2E,0x7D,0xF9,0x05, - 0x26,0x90,0xF1, +static unsigned char _exception_self_signed[]={ + 0x30,0x82,0x03,0x0F,0x30,0x82,0x01,0xF7,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x01, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30, + 0x35,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x0C,0x1D,0x73,0x65,0x6C,0x66, + 0x2D,0x73,0x69,0x67,0x6E,0x65,0x64,0x2E,0x73,0x73,0x6C,0x74,0x65,0x73,0x74,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x36,0x30,0x37, + 0x32,0x31,0x35,0x33,0x30,0x38,0x5A,0x17,0x0D,0x31,0x37,0x30,0x36,0x30,0x37,0x32, + 0x31,0x35,0x33,0x30,0x38,0x5A,0x30,0x35,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x1D,0x73,0x65,0x6C,0x66,0x2D,0x73,0x69,0x67,0x6E,0x65,0x64,0x2E,0x73, + 0x73,0x6C,0x74,0x65,0x73,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01, + 0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, + 0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xCC,0x72, + 0x7D,0x09,0x36,0x5A,0x6A,0xED,0xC1,0x7A,0x2C,0xF4,0x7C,0x58,0x63,0x05,0x3E,0x91, + 0x68,0x55,0xB1,0x2A,0x5D,0x57,0xF3,0xA4,0xA7,0x80,0x05,0x41,0x74,0xB2,0xAD,0x5A, + 0x7F,0x38,0xF6,0xF7,0xFD,0xF9,0x64,0x4D,0xDE,0xF9,0x7A,0xD3,0x8C,0x78,0xE9,0x71, + 0xCF,0x1D,0x3E,0xF0,0xDB,0x12,0x48,0x74,0x22,0xA8,0x1F,0x3F,0xB9,0xDD,0xB0,0xAD, + 0x8C,0x10,0x64,0x05,0x0E,0xE2,0x59,0x9A,0xEB,0x3F,0xBF,0xA9,0x48,0x07,0xD9,0x2C, + 0x07,0x44,0x70,0x14,0x16,0x56,0x9C,0x73,0x01,0x2E,0x0B,0xF1,0x2A,0x9F,0x1C,0xC6, + 0x78,0x56,0xB7,0x0B,0xDA,0xA6,0xE6,0x99,0x87,0x2D,0x49,0xFB,0xF0,0x47,0x22,0xA6, + 0x8B,0xF0,0x02,0x37,0x31,0xD0,0x34,0x9F,0x43,0xD1,0x24,0x49,0x94,0x7F,0xFD,0x48, + 0x9C,0xBA,0x5D,0x6B,0xD4,0xF9,0x9E,0xB5,0x18,0xE4,0xB2,0x06,0x46,0xC3,0xD9,0xE7, + 0x80,0xD8,0x61,0xA9,0x09,0x5E,0xBA,0x2E,0x58,0x56,0xAE,0x37,0x31,0x6E,0x87,0x98, + 0xD5,0xC9,0x2B,0x31,0x5C,0x40,0x01,0xDF,0xD5,0x63,0x9E,0x05,0x18,0x21,0x53,0x70, + 0x62,0x36,0x44,0xCD,0x02,0xC0,0xCC,0x6A,0x58,0xC6,0xF6,0xA4,0xDC,0x89,0x94,0xBD, + 0x4E,0xC4,0xEE,0xEE,0x40,0x31,0x59,0xC3,0x43,0xAD,0x34,0x30,0xDE,0xA9,0xA7,0x0D, + 0x85,0xF7,0x96,0x8C,0x45,0xC1,0x6E,0x85,0x39,0x97,0xA6,0x4F,0xEA,0xE8,0x2F,0x01, + 0x3D,0xC0,0x3B,0x34,0x9F,0x8F,0xCB,0xD6,0x22,0x79,0x2C,0x8C,0x8C,0xE6,0xBB,0x1F, + 0x89,0x87,0x93,0x3B,0x39,0x4E,0x64,0x7D,0xDA,0x4D,0x52,0x4C,0x97,0xE5,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x2A,0x30,0x28,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01, + 0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x36,0x06,0xC9,0xE6,0x98,0xC2,0x84,0x1D,0x13,0x1E,0x54,0x35,0x6D, + 0xE5,0xCB,0xC5,0xFD,0xD9,0x54,0x45,0x83,0x53,0xB3,0x3B,0xE7,0x30,0x6F,0xAE,0xEA, + 0x63,0x3F,0xA8,0xFA,0xD9,0x6D,0x0F,0x7D,0xD4,0xB6,0x28,0x66,0xF9,0x57,0x87,0x3E, + 0x57,0x27,0xB6,0x9A,0x56,0xAE,0xD7,0xE0,0x11,0x20,0x71,0xC1,0xEA,0xF6,0xED,0x74, + 0x1A,0x5A,0xB1,0x74,0x6C,0xBE,0xAC,0x0E,0x3C,0xD9,0x3E,0xEC,0x17,0x6E,0xF0,0x69, + 0xC9,0x4D,0xD2,0x7E,0xAE,0x8B,0x01,0xCC,0x1A,0x23,0x7C,0x58,0x07,0x30,0xE4,0x2A, + 0x12,0xE8,0xA0,0x25,0x65,0x66,0xB5,0xC7,0x5D,0xD8,0x47,0xDF,0xD7,0x51,0xBC,0xA2, + 0xAA,0xF0,0x2F,0xB5,0x9E,0x20,0x6D,0x1F,0x84,0x00,0xF0,0xD0,0xB8,0x42,0x6A,0x9A, + 0xE7,0xCA,0x7B,0xE5,0x39,0x09,0x91,0xBF,0xCB,0x4D,0x7A,0x32,0x1E,0x00,0x6E,0xE5, + 0xF7,0x44,0x80,0x82,0x38,0x53,0x64,0xB7,0x26,0x81,0xCB,0xCE,0xA1,0xAF,0x0C,0x67, + 0x32,0xC6,0xE4,0x5D,0x09,0x7B,0x37,0xD7,0xC8,0x43,0x44,0xEF,0xC6,0xF8,0x72,0xFF, + 0x65,0xD4,0x39,0x3D,0xEC,0x72,0xA5,0x28,0xFF,0x70,0x47,0x38,0xA3,0xC7,0xCC,0x5E, + 0x0F,0xFF,0x43,0x83,0x78,0x49,0x68,0x90,0x48,0x89,0xAD,0xE1,0x2E,0xFA,0x8F,0x59, + 0xB6,0x08,0x2A,0x72,0x2F,0x52,0x3F,0x73,0x84,0xCA,0xD8,0x18,0x6C,0xDA,0xA3,0x2E, + 0xF2,0xD7,0x4C,0x21,0xD9,0xF8,0xB1,0x86,0xE9,0x35,0x78,0xE4,0x4F,0xD0,0x93,0x11, + 0x8F,0xF4,0xB1,0x17,0x4F,0xDE,0xAC,0xBD,0xA9,0xBC,0x94,0xFC,0x2E,0x7D,0xF9,0x05, + 0x26,0x90,0xF1, }; -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } -#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } - -/* Test basic add delete update copy matching stuff. */ -static void tests(void) -{ - SecTrustRef trust; - SecCertificateRef cert0, cert1, sscert0; - CFArrayRef anchors = NULL; - isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), - NULL, "create cert0"); - isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), - NULL, "create cert1"); - isnt(sscert0 = SecCertificateCreateWithBytes(NULL, _ss0, sizeof(_ss0)), - NULL, "create sscert0"); - const void *v_certs[] = { - cert0, - cert1 - }; - SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("store.apple.com")); - CFArrayRef certs = CFArrayCreate(NULL, v_certs, - array_size(v_certs), NULL); - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); - CFDateRef date = CFDateCreate(NULL, 545000000.0); /* April 9, 2018 at 1:53:20 PM PDT */ - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - - SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - CFDataRef exceptions; - ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); - if (!exceptions) { goto errOut; } - ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); - - CFReleaseNull(trust); - CFReleaseNull(policy); - policy = SecPolicyCreateSSL(true, CFSTR("badstore.apple.com")); - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust with hostname mismatch"); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - ok(SecTrustSetExceptions(trust, exceptions), "set old exceptions"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); - CFReleaseNull(exceptions); - ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); - if (!exceptions) { goto errOut; } - ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); - - CFReleaseNull(trust); - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); - anchors = CFArrayCreate(kCFAllocatorDefault, NULL, 0, &kCFTypeArrayCallBacks); - ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set empty anchor list"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); - - ok_status(SecTrustSetAnchorCertificatesOnly(trust, false), "trust passed in anchors and system anchors"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultProceed, "trust is now kSecTrustResultProceed"); - - ok_status(SecTrustSetAnchorCertificatesOnly(trust, true), "only trust passed in anchors (default)"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure again"); - - CFReleaseNull(exceptions); - ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); - if (!exceptions) { goto errOut; } - ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); - CFReleaseNull(date); - date = CFDateCreate(NULL, 667680000.0); - ok_status(SecTrustSetVerifyDate(trust, date), "set date to far future so certs are expired"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); - - CFReleaseNull(trust); - CFReleaseNull(policy); - policy = SecPolicyCreateSSL(true, CFSTR("self-signed.ssltest.apple.com")); - ok_status(SecTrustCreateWithCertificates(sscert0, policy, &trust), "create trust"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); - CFReleaseNull(exceptions); - ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); - if (!exceptions) { goto errOut; } - ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); - CFReleaseNull(exceptions); - ok(!SecTrustSetExceptions(trust, NULL), "clear exceptions"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); - -#if TARGET_OS_IPHONE - /* Test the extenions epoch feature. */ - CFReleaseNull(exceptions); - CFReleaseNull(trust); - CFReleaseNull(policy); - policy = SecPolicyCreateSSL(false, CFSTR("self-signed.ssltest.apple.com")); - ok_status(SecTrustCreateWithCertificates(sscert0, policy, &trust), "create trust"); - ok(exceptions = SecTrustCopyExceptions(trust), "create exceptions"); - if (!exceptions) { goto errOut; } - - /* Test the uninitialized extensions epoch. */ - CFErrorRef exceptionResetCountError = NULL; - uint64_t exceptionResetCount = SecTrustGetExceptionResetCount(&exceptionResetCountError); - ok(exceptionResetCount == 0, "exception reset count is not set yet"); - ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); - - /* Test increasing the extensions epoch. */ - exceptionResetCountError = NULL; - ok_status(SecTrustIncrementExceptionResetCount(&exceptionResetCountError), "increase exception reset count"); - exceptionResetCountError = NULL; - is(SecTrustGetExceptionResetCount(&exceptionResetCountError), 1 + exceptionResetCount, "exception reset count is 1 + previous count"); - - /* Test trust evaluation under a future extensions epoch. */ - ok(!SecTrustSetExceptions(trust, exceptions), "set exceptions"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); -#endif - -errOut: - CFReleaseSafe(anchors); - CFReleaseSafe(exceptions); - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(certs); - CFReleaseSafe(cert0); - CFReleaseSafe(cert1); - CFReleaseSafe(sscert0); - CFReleaseSafe(date); -} - -int si_27_sectrust_exceptions(int argc, char *const *argv) -{ -#if TARGET_OS_IPHONE - plan_tests(62); -#else - plan_tests(51); -#endif - - tests(); - - return 0; -} +#endif /* _TRUSTTESTS_EXCEPTION_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/KeySizeTests.m b/tests/TrustTests/EvaluationTests/KeySizeTests.m index e905b822..f0aae4b9 100644 --- a/tests/TrustTests/EvaluationTests/KeySizeTests.m +++ b/tests/TrustTests/EvaluationTests/KeySizeTests.m @@ -108,7 +108,7 @@ errOut: ok_status(SecTrustSetVerifyDate(trust, date), "set owa.prt-forest.fi trust date to May 2013"); - SecKeyRef pubkey = SecTrustCopyPublicKey(trust); + SecKeyRef pubkey = SecTrustCopyKey(trust); isnt(pubkey, NULL, "pubkey returned"); CFReleaseNull(certs); diff --git a/tests/TrustTests/EvaluationTests/NISTTests.m b/tests/TrustTests/EvaluationTests/NISTTests.m index 094fb916..7c192713 100644 --- a/tests/TrustTests/EvaluationTests/NISTTests.m +++ b/tests/TrustTests/EvaluationTests/NISTTests.m @@ -49,4 +49,108 @@ CFReleaseSafe(basicPolicy); } +- (void)testNoBasicConstraintsAnchor_UserTrusted { + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"InvalidMissingbasicConstraintsTest1EE" + subdirectory:@"nist-certs"]; + SecCertificateRef ca = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"MissingbasicConstraintsCACert" + subdirectory:@"nist-certs"]; + SecTrustRef trust = NULL; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)ca]; + + XCTAssertEqual(errSecSuccess, SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, NULL, &trust)); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + XCTAssertEqual(errSecSuccess, SecTrustSetVerifyDate(trust, (__bridge CFDateRef)testDate)); + + id persistentRef = [self addTrustSettingsForCert:ca]; + CFErrorRef error = nil; + XCTAssertFalse(SecTrustEvaluateWithError(trust, &error)); + XCTAssertNotEqual(error, NULL); + if (error) { + XCTAssertEqual(CFErrorGetCode(error), errSecNoBasicConstraints); + } + + [self removeTrustSettingsForCert:ca persistentRef:persistentRef]; + CFReleaseNull(leaf); + CFReleaseNull(ca); + CFReleaseNull(error); +} + +- (void)testNoBasicConstraintsAnchor_AppTrusted { + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"InvalidMissingbasicConstraintsTest1EE" + subdirectory:@"nist-certs"]; + SecCertificateRef ca = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"MissingbasicConstraintsCACert" + subdirectory:@"nist-certs"]; + SecTrustRef trust = NULL; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)ca]; + NSArray *anchor = @[(__bridge id)ca]; + + XCTAssertEqual(errSecSuccess, SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, NULL, &trust)); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + XCTAssertEqual(errSecSuccess, SecTrustSetVerifyDate(trust, (__bridge CFDateRef)testDate)); + XCTAssertEqual(errSecSuccess, SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchor)); + + CFErrorRef error = nil; + XCTAssertFalse(SecTrustEvaluateWithError(trust, &error)); + XCTAssertNotEqual(error, NULL); + if (error) { + XCTAssertEqual(CFErrorGetCode(error), errSecNoBasicConstraints); + } + + CFReleaseNull(leaf); + CFReleaseNull(ca); + CFReleaseNull(error); +} + +- (void)testNotCABasicConstraintsAnchor_UserTrusted { + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"InvalidcAFalseTest2EE" + subdirectory:@"nist-certs"]; + SecCertificateRef ca = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"basicConstraintsCriticalcAFalseCACert" + subdirectory:@"nist-certs"]; + SecTrustRef trust = NULL; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)ca]; + + XCTAssertEqual(errSecSuccess, SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, NULL, &trust)); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + XCTAssertEqual(errSecSuccess, SecTrustSetVerifyDate(trust, (__bridge CFDateRef)testDate)); + + id persistentRef = [self addTrustSettingsForCert:ca]; + CFErrorRef error = nil; + XCTAssertFalse(SecTrustEvaluateWithError(trust, &error)); + XCTAssertNotEqual(error, NULL); + if (error) { + XCTAssertEqual(CFErrorGetCode(error), errSecNoBasicConstraintsCA); + } + + [self removeTrustSettingsForCert:ca persistentRef:persistentRef]; + CFReleaseNull(leaf); + CFReleaseNull(ca); + CFReleaseNull(error); +} + +- (void)testNotCABasicConstraintsAnchor_AppTrusted { + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"InvalidcAFalseTest2EE" + subdirectory:@"nist-certs"]; + SecCertificateRef ca = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"basicConstraintsCriticalcAFalseCACert" + subdirectory:@"nist-certs"]; + SecTrustRef trust = NULL; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)ca]; + NSArray *anchor = @[(__bridge id)ca]; + + XCTAssertEqual(errSecSuccess, SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, NULL, &trust)); + NSDate *testDate = CFBridgingRelease(CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1)); + XCTAssertEqual(errSecSuccess, SecTrustSetVerifyDate(trust, (__bridge CFDateRef)testDate)); + XCTAssertEqual(errSecSuccess, SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchor)); + + CFErrorRef error = nil; + XCTAssertFalse(SecTrustEvaluateWithError(trust, &error)); + XCTAssertNotEqual(error, NULL); + if (error) { + XCTAssertEqual(CFErrorGetCode(error), errSecNoBasicConstraintsCA); + } + + CFReleaseNull(leaf); + CFReleaseNull(ca); + CFReleaseNull(error); +} + @end diff --git a/tests/TrustTests/EvaluationTests/NameConstraintsTests.m b/tests/TrustTests/EvaluationTests/NameConstraintsTests.m index 7f6a8d75..f0871ab7 100644 --- a/tests/TrustTests/EvaluationTests/NameConstraintsTests.m +++ b/tests/TrustTests/EvaluationTests/NameConstraintsTests.m @@ -493,6 +493,8 @@ exit: return result; } +#if !TARGET_OS_WATCH +// Skip test on watchOS due to size constraints (rdar://66792084) - (void) testBetterTLS { NSArray *testsArray = [self getTestsArray]; if([self untar_test_certs]) { @@ -539,5 +541,6 @@ exit: [[NSFileManager defaultManager] removeItemAtURL:tmpCertsDir error:nil]; } +#endif //!TARGET_OS_WATCH @end diff --git a/tests/TrustTests/EvaluationTests/PathParseTests.m b/tests/TrustTests/EvaluationTests/PathParseTests.m index 2d65d23f..10364389 100644 --- a/tests/TrustTests/EvaluationTests/PathParseTests.m +++ b/tests/TrustTests/EvaluationTests/PathParseTests.m @@ -76,20 +76,17 @@ const NSString *kSecTestPathFailureResources = @"si-18-certificate-parse/PathFai - (void)testUnparseableExtensions { SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _bad_extension_leaf, sizeof(_bad_extension_leaf)); - SecCertificateRef root = NULL; + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _bad_extension_root, sizeof(_bad_extension_root)); SecTrustRef trust = NULL; SecPolicyRef policy = SecPolicyCreateBasicX509(); CFErrorRef error = NULL; - - NSURL *rootURL = [[NSBundle bundleForClass:[self class]]URLForResource:@"root" withExtension:@".cer" subdirectory:@"si-18-certificate-parse"]; - XCTAssert(root = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)[NSData dataWithContentsOfURL:rootURL]), "Unable to create root cert"); NSArray *anchors = @[(__bridge id)root]; require_noerr_action(SecTrustCreateWithCertificates(leaf, policy, &trust), errOut, fail("Unable to create trust with certificate with unparseable extension")); require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("Unable to set trust anchors")); - require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)[NSDate dateWithTimeIntervalSinceReferenceDate:507200000.0]), + require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)[NSDate dateWithTimeIntervalSinceReferenceDate:620000000.0]), errOut, fail("Unable to set verify date")); XCTAssertFalse(SecTrustEvaluateWithError(trust, &error), "Got wrong trust result cert"); XCTAssert(error != NULL); diff --git a/tests/TrustTests/EvaluationTests/PathParseTests_data.h b/tests/TrustTests/EvaluationTests/PathParseTests_data.h index 507cb672..af473be4 100644 --- a/tests/TrustTests/EvaluationTests/PathParseTests_data.h +++ b/tests/TrustTests/EvaluationTests/PathParseTests_data.h @@ -5,50 +5,90 @@ #ifndef _TRUSTTESTS_EVALUATION_PATH_PARSE_TESTS_H_ #define _TRUSTTESTS_EVALUATION_PATH_PARSE_TESTS_H_ -/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=CoreTrust Test Leaf 1 */ -/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=CoreTrust Test CA */ +const uint8_t _bad_extension_root[] = { + 0x30,0x82,0x02,0x55,0x30,0x82,0x01,0xFD,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xA7,0x97,0x3B,0x17,0xE9,0x68,0x62,0x01,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE, + 0x3D,0x04,0x01,0x30,0x81,0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61, + 0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04, + 0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67, + 0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x4F,0x43,0x53,0x50,0x20, + 0x52,0x65,0x73,0x70,0x6F,0x6E,0x64,0x65,0x72,0x20,0x54,0x65,0x73,0x74,0x20,0x52, + 0x6F,0x6F,0x74,0x30,0x1E,0x17,0x0D,0x32,0x30,0x30,0x37,0x31,0x33,0x32,0x30,0x31, + 0x30,0x31,0x37,0x5A,0x17,0x0D,0x33,0x30,0x30,0x37,0x31,0x31,0x32,0x30,0x31,0x30, + 0x31,0x37,0x5A,0x30,0x81,0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61, + 0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04, + 0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67, + 0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x4F,0x43,0x53,0x50,0x20, + 0x52,0x65,0x73,0x70,0x6F,0x6E,0x64,0x65,0x72,0x20,0x54,0x65,0x73,0x74,0x20,0x52, + 0x6F,0x6F,0x74,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, + 0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x45,0xA3, + 0x6E,0x77,0x59,0x2B,0x7D,0xD4,0x9D,0x44,0xD7,0xDA,0x3E,0x5C,0xE1,0xB3,0xF8,0x34, + 0xE8,0xE8,0xEC,0x53,0x5A,0x5B,0x88,0x79,0x62,0x20,0x00,0xE1,0x82,0x42,0x3F,0x9D, + 0x78,0xCD,0x6D,0x1C,0xF2,0xF6,0x7A,0x66,0xCA,0x1B,0xEA,0x40,0xFD,0x9B,0x9D,0x8B, + 0x31,0x63,0xE7,0x95,0x10,0xB8,0x91,0x24,0xAE,0xF3,0x30,0xE4,0x1F,0x35,0xA3,0x45, + 0x30,0x43,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06, + 0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF, + 0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0x59,0xB5,0xB1,0x6E,0x89,0x9B,0xAC,0x7E,0x19,0x13,0x2C,0x75,0x68,0x3D,0x9F, + 0x05,0x15,0x54,0x05,0x16,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01, + 0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x48,0x3A,0xED,0x1D,0x9A,0xA1,0x82,0x4B,0x49, + 0x7D,0x92,0xF0,0xAD,0x8E,0x04,0x8E,0x0C,0x95,0x02,0x7A,0x7D,0x93,0xFD,0xDD,0x4D, + 0xDA,0x00,0xDA,0xBA,0x85,0x8A,0x6F,0x02,0x20,0x38,0xB0,0x4B,0x32,0xD0,0x61,0x6A, + 0x3A,0xBB,0x4C,0x24,0x6B,0x73,0x7A,0x97,0x44,0x63,0xEA,0x77,0xAB,0xB9,0x55,0xBF, + 0x40,0x96,0xEC,0xD5,0x2C,0x30,0x47,0x4E,0x2C, +}; + const uint8_t _bad_extension_leaf[] = { - 0x30,0x82,0x02,0x85,0x30,0x82,0x02,0x2C,0xA0,0x03,0x02,0x01,0x02,0x02,0x15,0x00, - 0xD5,0xEC,0xDB,0x27,0x18,0xA7,0xEC,0x88,0x42,0xBA,0xC8,0xCD,0xE6,0xFC,0x34,0x9A, - 0x4D,0x36,0xD3,0x4C,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x30, - 0x81,0x86,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, - 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, - 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, - 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, - 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, - 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1A,0x30,0x18, - 0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x43,0x6F,0x72,0x65,0x54,0x72,0x75,0x73,0x74, - 0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x37,0x30,0x31, - 0x32,0x36,0x32,0x33,0x32,0x33,0x33,0x32,0x5A,0x17,0x0D,0x31,0x37,0x30,0x31,0x32, - 0x37,0x32,0x33,0x32,0x33,0x33,0x32,0x5A,0x30,0x81,0x8A,0x31,0x0B,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30, - 0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E, - 0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, - 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, - 0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15, - 0x43,0x6F,0x72,0x65,0x54,0x72,0x75,0x73,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x4C, - 0x65,0x61,0x66,0x20,0x31,0x30,0x56,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, - 0x02,0x01,0x06,0x05,0x2B,0x81,0x04,0x00,0x0A,0x03,0x42,0x00,0x04,0xFA,0x43,0x00, - 0x5E,0xEF,0xEF,0x33,0xBA,0x03,0x5F,0x7B,0x42,0xE2,0xCF,0x7D,0x2A,0x61,0x69,0xE2, - 0xEB,0x7A,0xE1,0x98,0x49,0x60,0x0D,0xD8,0xCB,0x99,0x09,0x91,0x4E,0x8B,0x12,0xA4, - 0x7F,0x19,0xAE,0xF4,0x62,0x8D,0x36,0x1A,0x34,0x9C,0x64,0xFE,0xE9,0xB2,0x02,0x3E, - 0xFD,0x83,0x9D,0x7E,0x40,0x7D,0x21,0x0E,0xD4,0xDA,0x97,0x12,0xE2,0xA3,0x75,0x30, - 0x73,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, - 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30, - 0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x31,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x03,0x02,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xBB, - 0x3E,0xCE,0xF4,0xBA,0x9A,0xBC,0x9F,0x1E,0xF9,0x73,0xDB,0x11,0xEB,0x55,0x93,0xA3, - 0x59,0x5B,0x6C,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, - 0xEC,0xC0,0x39,0x7A,0xDF,0x66,0x7B,0x15,0xB1,0x13,0x9E,0x8D,0xD6,0xB2,0x77,0xA6, - 0xBA,0xEE,0x2A,0xA1,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x03, - 0x48,0x00,0x30,0x45,0x02,0x20,0x2B,0x9C,0xC9,0xD3,0x86,0x66,0x7A,0xCD,0x58,0xFC, - 0x48,0x06,0xF6,0xC6,0xCC,0xE2,0x0F,0xA8,0xE4,0x66,0x16,0x2C,0xA8,0xCC,0x51,0xB6, - 0x1B,0x56,0xAC,0xBB,0x9F,0xD4,0x02,0x21,0x00,0xA2,0x51,0xAC,0x76,0xE6,0x3B,0x3B, - 0x0D,0x79,0xCD,0xB6,0x71,0x66,0x9E,0xEF,0x3C,0xB8,0x56,0xEA,0xBF,0x64,0x48,0x5B, - 0x0B,0x9B,0x38,0x06,0xBE,0xBA,0xE5,0xC9,0x17, + 0x30,0x82,0x02,0x94,0x30,0x82,0x02,0x3A,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x25, + 0xF3,0xFF,0xBB,0x76,0x44,0x44,0x8A,0xC2,0xC2,0xF6,0xC6,0x0D,0xEF,0x53,0x19,0xBE, + 0x01,0x1F,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81, + 0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x21,0x30,0x1F,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x18,0x4F,0x43,0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6F, + 0x6E,0x64,0x65,0x72,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x30,0x1E, + 0x17,0x0D,0x32,0x30,0x30,0x37,0x31,0x34,0x30,0x30,0x30,0x34,0x30,0x37,0x5A,0x17, + 0x0D,0x32,0x31,0x30,0x37,0x31,0x34,0x30,0x30,0x30,0x34,0x30,0x37,0x5A,0x30,0x81, + 0x8F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x23,0x30,0x21,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x1A,0x4F,0x43,0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6F, + 0x6E,0x64,0x65,0x72,0x20,0x54,0x65,0x73,0x74,0x3A,0x20,0x56,0x61,0x6C,0x69,0x64, + 0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A, + 0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x4D,0xFC,0xED,0x57,0xD8, + 0xEA,0x29,0xC6,0xE5,0x25,0x87,0x51,0xAA,0x73,0x6A,0x5F,0x00,0x4C,0x64,0x42,0xE0, + 0x53,0xAE,0xEE,0x9E,0x3F,0x4B,0xBC,0x2B,0x7B,0xFB,0x24,0x33,0x53,0x9F,0x42,0x33, + 0x99,0xC4,0x1A,0x33,0xC8,0x09,0xCC,0x8E,0x50,0x74,0xC1,0x3E,0x9A,0x42,0x9E,0x6F, + 0x46,0x4E,0x73,0x34,0xE4,0xF1,0x7A,0x7E,0xE1,0x40,0x61,0xA3,0x75,0x30,0x73,0x30, + 0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x82,0x30,0x13,0x06, + 0x03,0x55,0x1D,0x25,0x04,0x0C,0x31,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x03,0x09,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x09,0x35,0xC3, + 0xB1,0x7D,0x12,0x8D,0xBC,0xB0,0x3C,0xF7,0xC4,0xA9,0x7D,0xA1,0x2A,0x84,0x9C,0xEE, + 0x67,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x59,0xB5, + 0xB1,0x6E,0x89,0x9B,0xAC,0x7E,0x19,0x13,0x2C,0x75,0x68,0x3D,0x9F,0x05,0x15,0x54, + 0x05,0x16,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48, + 0x00,0x30,0x45,0x02,0x20,0x13,0x00,0x46,0x93,0x44,0x1D,0x80,0x74,0x0A,0x59,0xE3, + 0x79,0x43,0xFD,0x04,0x2A,0x6C,0x19,0x5A,0x79,0x53,0x46,0x9E,0x8F,0x3A,0x31,0x47, + 0x05,0x9F,0xF8,0xE0,0xB4,0x02,0x21,0x00,0xAA,0x3D,0xBC,0x3E,0x68,0x47,0x71,0xCC, + 0x36,0x90,0x33,0xF3,0xC4,0xEA,0x12,0xF4,0x4C,0x96,0x65,0xE3,0x65,0xB4,0x7E,0x24, + 0xAB,0x6C,0x64,0xFA,0x13,0x6C,0xF9,0x4C, }; diff --git a/tests/TrustTests/EvaluationTests/PolicyTests.m b/tests/TrustTests/EvaluationTests/PolicyTests.m index e844ab74..50c15db1 100644 --- a/tests/TrustTests/EvaluationTests/PolicyTests.m +++ b/tests/TrustTests/EvaluationTests/PolicyTests.m @@ -22,7 +22,7 @@ */ -/* INSTRUCTIONS FOR ADDING NEW SUBTESTS: +/* INSTRUCTIONS FOR ADDING NEW SUBTESTS TO testPolicies: * 1. Add the certificates, as DER-encoded files with the 'cer' extension, to OSX/shared_regressions/si-20-sectrust-policies-data/ * NOTE: If your cert needs to be named with "(i[Pp]hone|i[Pp]ad|i[Pp]od)", you need to make two copies -- one named properly * and another named such that it doesn't match that regex. Use the regex trick below for TARGET_OS_TV to make sure your test @@ -50,17 +50,23 @@ #include #include +#include #include #include #include +#include #include #include +#include +#include #import "TrustEvaluationTestCase.h" #include "../TestMacroConversions.h" #include "../TrustEvaluationTestHelpers.h" +#include "PolicyTests_data.h" const NSString *kSecTrustTestPinningPolicyResources = @"si-20-sectrust-policies-data"; +const NSString *kSecTrustTestPinnningTest = @"PinningPolicyTrustTest"; @interface PolicyTests : TrustEvaluationTestCase @end @@ -74,8 +80,8 @@ const NSString *kSecTrustTestPinningPolicyResources = @"si-20-sectrust-policies- testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:@"debugging" withExtension:@"plist" subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; if (!testPlist) { - testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:nil withExtension:@"plist" - subdirectory:(NSString *)kSecTrustTestPinningPolicyResources ]; + testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:(NSString *)kSecTrustTestPinnningTest withExtension:@"plist" + subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; } if (!testPlist) { fail("Failed to get tests plist from %@", kSecTrustTestPinningPolicyResources); @@ -142,4 +148,736 @@ errOut: CFReleaseNull(trust); } +- (void)testSecPolicyReconcilePinningRequiredIfInfoSpecified +{ + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("www.example.org")); + CFMutableArrayRef emptySPKISHA256 = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + + CFMutableArrayRef nonemtpySPKISHA256 = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + uint8_t _random_data256[256/sizeof(uint8_t)]; + (void)SecRandomCopyBytes(NULL, sizeof(_random_data256), _random_data256); + CFDataRef random_data256 = CFDataCreate(kCFAllocatorDefault, _random_data256, sizeof(_random_data256)); + CFArrayAppendValue(nonemtpySPKISHA256, random_data256); + CFReleaseNull(random_data256); + + // kSecPolicyCheckPinningRequired should be unset after reconciliation. + // Empty values for both SPKI policies signal a pinning exception. + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + SecPolicySetOptionsValue(policy, kSecPolicyCheckLeafSPKISHA256, emptySPKISHA256); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCAspkiSHA256, emptySPKISHA256); + CFDictionaryRef policyOptions = SecPolicyGetOptions(policy); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + SecPolicyReconcilePinningRequiredIfInfoSpecified((CFMutableDictionaryRef)policyOptions); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), false); + + // kSecPolicyCheckPinningRequired overrules the other two policies. + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + SecPolicySetOptionsValue(policy, kSecPolicyCheckLeafSPKISHA256, nonemtpySPKISHA256); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCAspkiSHA256, emptySPKISHA256); + policyOptions = SecPolicyGetOptions(policy); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + SecPolicyReconcilePinningRequiredIfInfoSpecified((CFMutableDictionaryRef)policyOptions); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), false); + + // kSecPolicyCheckPinningRequired overrules the other two policies. + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + SecPolicySetOptionsValue(policy, kSecPolicyCheckLeafSPKISHA256, emptySPKISHA256); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCAspkiSHA256, nonemtpySPKISHA256); + policyOptions = SecPolicyGetOptions(policy); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + SecPolicyReconcilePinningRequiredIfInfoSpecified((CFMutableDictionaryRef)policyOptions); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), false); + + // In the absence of kSecPolicyCheckPinningRequired there is nothing to reconcile. + CFReleaseNull(policy); + policy = SecPolicyCreateSSL(true, CFSTR("www.example.org")); + SecPolicySetOptionsValue(policy, kSecPolicyCheckLeafSPKISHA256, emptySPKISHA256); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCAspkiSHA256, emptySPKISHA256); + policyOptions = SecPolicyGetOptions(policy); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + SecPolicyReconcilePinningRequiredIfInfoSpecified((CFMutableDictionaryRef)policyOptions); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + + CFReleaseNull(policy); + CFReleaseNull(emptySPKISHA256); + CFReleaseNull(nonemtpySPKISHA256); +} + +- (CFDictionaryRef)getNSPinnedDomainsFromDictionaryInfoFile:(NSString *)fileName +{ + NSURL *infoPlist = [[NSBundle bundleForClass:[self class]] URLForResource:fileName withExtension:@"plist" + subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; + if (!infoPlist) { + fail("Failed to access plist file \"%@\"", fileName); + return NULL; + } + + NSDictionary *infoDictionary = [NSDictionary dictionaryWithContentsOfURL:infoPlist]; + if (!infoDictionary) { + fail("Failed to create dictionary from plist file \"%@\"", fileName); + return NULL; + } + + CFTypeRef nsAppTransportSecurityDict = CFDictionaryGetValue((__bridge CFDictionaryRef)infoDictionary, CFSTR("NSAppTransportSecurity")); + if (!isDictionary(nsAppTransportSecurityDict)) { + fail("NSAppTransportSecurity dictionary entry is missing from plist file \"%@\"", fileName); + return NULL; + } + + CFDictionaryRef nsPinnedDomainsDict = CFDictionaryGetValue(nsAppTransportSecurityDict, CFSTR("NSPinnedDomains")); + if (!isDictionary(nsPinnedDomainsDict)) { + fail("NSPinnedDomains dictionary entry is missing from plist file \"%@\"", fileName); + return NULL; + } + + return nsPinnedDomainsDict; +} + +- (void)testParseNSPinnedDomains +{ + NSURL *testPlist = nil; + NSArray *testsArray = nil; + + + testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:@"NSPinnedDomainsParsingTest_debugging" withExtension:@"plist" + subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; + if (!testPlist) { + testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:@"NSPinnedDomainsParsingTest" withExtension:@"plist" + subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; + } + if (!testPlist) { + fail("Failed to get tests plist from \"%@\"", kSecTrustTestPinningPolicyResources); + return; + } + + testsArray = [NSArray arrayWithContentsOfURL: testPlist]; + if (!testsArray) { + fail("Failed to create array from plist"); + return; + } + + [testsArray enumerateObjectsUsingBlock:^(NSDictionary *testDict, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *plistFileName = testDict[@"PlistFileName"]; + if (!plistFileName) { + fail("Failed to read plist file name from \"%@\":%lu", plistFileName, (unsigned long)idx); + return; + } + + NSDictionary *expectedProperties = testDict[@"ExpectedProperties"]; + if (!expectedProperties) { + fail("Missing the expected results in \"%@\"", plistFileName); + return; + } + bool hasNSPinnedLeafIdentities = [expectedProperties[@"NSPinnedLeafIdentities"] boolValue]; + int NSPinnedLeafIdentitiesCount = [expectedProperties[@"NSPinnedLeafIdentitiesCount"] intValue]; + bool hasNSPinnedCAIdentities = [expectedProperties[@"NSPinnedCAIdentities"] boolValue]; + int NSPinnedCAIdentitiesCount = [expectedProperties[@"NSPinnedCAIdentitiesCount"] intValue]; + bool hasNSIncludesSubdomains = [expectedProperties[@"NSIncludesSubdomains"] boolValue]; + + CFDictionaryRef nsPinnedDomainsDict = [self getNSPinnedDomainsFromDictionaryInfoFile:plistFileName]; + if (!isDictionary(nsPinnedDomainsDict)) { + fail("Unable to read %@", plistFileName); + return; + } + CFArrayRef leafSPKISHA256 = parseNSPinnedDomains(nsPinnedDomainsDict, CFSTR("example.org"), CFSTR("NSPinnedLeafIdentities")); + is(leafSPKISHA256 != NULL, hasNSPinnedLeafIdentities, "leafSPKISHA256 test failed in \"%@\"", plistFileName); + is(leafSPKISHA256 != NULL && CFArrayGetCount(leafSPKISHA256) != 0, NSPinnedLeafIdentitiesCount != 0, "leafSPKISHA256 count test failed in \"%@\"", plistFileName); + + CFArrayRef caSPKISHA256 = parseNSPinnedDomains(nsPinnedDomainsDict, CFSTR("example.org"), CFSTR("NSPinnedCAIdentities")); + is(caSPKISHA256 != NULL, hasNSPinnedCAIdentities, "caSPKISHA256 test failed in \"%@\"", plistFileName); + is(caSPKISHA256 != NULL && CFArrayGetCount(caSPKISHA256) != 0, NSPinnedCAIdentitiesCount != 0, "caSPKISHA256 count test failed in \"%@\"", plistFileName); + + caSPKISHA256 = parseNSPinnedDomains(nsPinnedDomainsDict, CFSTR("subdomain.example.org."), CFSTR("NSPinnedCAIdentities")); + is(caSPKISHA256 != NULL, hasNSIncludesSubdomains, "caSPKISHA256 subdomain test failed in \"%@\"", plistFileName); + }]; +} + +#if !TARGET_OS_BRIDGE +- (NSData *)random +{ + uint8_t random[32]; + (void)SecRandomCopyBytes(kSecRandomDefault, sizeof(random), random); + return [[NSData alloc] initWithBytes:random length:sizeof(random)]; +} + +- (void)testSetTransparentConnectionPins +{ + CFErrorRef error = NULL; + const CFStringRef TrustTestsAppID = CFSTR("com.apple.trusttests"); + const CFStringRef AnotherAppID = CFSTR("com.apple.security.not-this-one"); + CFArrayRef copiedPins = NULL; + + /* Verify no pins set */ + copiedPins = SecTrustStoreCopyTransparentConnectionPins(NULL, NULL); + XCTAssertEqual(copiedPins, NULL); + if (copiedPins) { + /* If we're startign out with pins set, a lot of the following will also fail, so just skip them */ + CFReleaseNull(copiedPins); + return; + } + + NSArray *pin1 = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : [self random] + }]; + /* Set pin with specified AppID */ + XCTAssert(SecTrustStoreSetTransparentConnectionPins(TrustTestsAppID, (__bridge CFArrayRef)pin1, &error), + "failed to set pins: %@", error); + + /* Copy all pins (with only one set) */ + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(NULL, &error), + "failed to copy all pins: %@", error); + XCTAssertEqualObjects(pin1, (__bridge NSArray*)copiedPins); + CFReleaseNull(copiedPins); + + /* Copy this app's pins */ + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(TrustTestsAppID, &error), + "failed to copy this app's pins: %@", error); + XCTAssertEqualObjects(pin1, (__bridge NSArray*)copiedPins); + CFReleaseNull(copiedPins); + + /* Copy a different app's pins */ + XCTAssertEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(AnotherAppID, &error), + "failed to copy another app's pins: %@", error); + CFReleaseNull(copiedPins); + + /* Set a different pin with implied AppID and ensure pins are replaced */ + NSArray *pin2 = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : [self random] + }]; + XCTAssert(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)pin2, &error), + "failed to set pins: %@", error); + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(TrustTestsAppID, &error), + "failed to copy this app's pins: %@", error); + XCTAssertEqualObjects(pin2, (__bridge NSArray*)copiedPins); + CFReleaseNull(copiedPins); + + /* Set pins for a different AppID */ + NSArray *pin3 = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : [self random] + }, @{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : [self random] + } + ]; + XCTAssert(SecTrustStoreSetTransparentConnectionPins(AnotherAppID, (__bridge CFArrayRef)pin3, &error), + "failed to set pins: %@", error); + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(AnotherAppID, &error), + "failed to copy another app's pins: %@", error); + XCTAssertEqualObjects(pin3, (__bridge NSArray*)copiedPins); + CFReleaseNull(copiedPins); + + /* Set empty pins, and ensure no change */ + XCTAssert(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)@[], &error), + "failed to set empty pins: %@", error); + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(TrustTestsAppID, &error), + "failed to copy this app's pins: %@", error); + XCTAssertEqualObjects(pin2, (__bridge NSArray*)copiedPins); + CFReleaseNull(copiedPins); + + /* Copy all pins */ + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(NULL, &error), + "failed to copy all pins: %@", error); + NSArray *nsCopiedPins = CFBridgingRelease(copiedPins); + XCTAssertNotNil(nsCopiedPins); + XCTAssertEqual([nsCopiedPins count], 3); + + /* Reset other app's pins (this app remains) */ + XCTAssert(SecTrustStoreSetTransparentConnectionPins(AnotherAppID, NULL, &error), + "failed to reset pins: %@", error); + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(NULL, &error), + "failed to copy this app's pins: %@", error); + XCTAssertEqualObjects(pin2, (__bridge NSArray*)copiedPins); + CFReleaseNull(copiedPins); + + /* Reset remaining pins */ + XCTAssert(SecTrustStoreSetTransparentConnectionPins(TrustTestsAppID, NULL, &error), + "failed to reset pins: %@", error); + XCTAssertEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(NULL, &error), + "failed to copy all pins: %@", error); + CFReleaseNull(copiedPins); +} + +- (void)testSetTransparentConnectionPins_InputValidation +{ + CFErrorRef error = NULL; +#define check_errSecParam \ +if (error) { \ +is(CFErrorGetCode(error), errSecParam, "bad input produced unxpected error code: %ld", (long)CFErrorGetCode(error)); \ +CFReleaseNull(error); \ +} else { \ +fail("expected failure to set NULL exceptions"); \ +} + NSArray *badPins = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + @"not a key" : @"not a value" + }]; + XCTAssertFalse(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)badPins, &error)); + check_errSecParam + + badPins = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + @"not a key" : [self random] + }]; + XCTAssertFalse(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)badPins, &error)); + check_errSecParam + + badPins = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + }]; + XCTAssertFalse(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)badPins, &error)); + check_errSecParam + + badPins = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : [self random], + @"not a key" : @"not a value" + }]; + XCTAssertFalse(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)badPins, &error)); + check_errSecParam + + badPins = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha3", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : [self random], + }]; + XCTAssertFalse(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)badPins, &error)); + check_errSecParam + + badPins = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : @"sha256", + }]; + XCTAssertFalse(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)badPins, &error)); + check_errSecParam + + badPins = @[[self random]]; + XCTAssertFalse(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)badPins, &error)); + check_errSecParam + + NSDictionary *dictionary = @{ @"aKey": @"aValue" }; + XCTAssertFalse(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)dictionary[@"aKey"], &error)); + check_errSecParam + +#undef check_errSecParam + + /* Remove pins */ + XCTAssert(SecTrustStoreSetTransparentConnectionPins(NULL, NULL, &error), + "failed to reset pins: %@", error); + XCTAssertEqual(NULL, SecTrustStoreCopyTransparentConnectionPins(NULL, &error)); +} + +- (void)testTransparentConnections { + SecCertificateRef pallasLeaf = SecCertificateCreateWithBytes(NULL, _pallas_leaf, sizeof(_pallas_leaf)); + SecCertificateRef pallasCA = SecCertificateCreateWithBytes(NULL, _pallas_ca, sizeof(_pallas_ca)); + SecCertificateRef tcLeaf = SecCertificateCreateWithBytes(NULL, _transparent_connection_leaf, sizeof(_transparent_connection_leaf)); + SecCertificateRef tcCA = SecCertificateCreateWithBytes(NULL, _transparent_connection_ca, sizeof(_transparent_connection_ca)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("gdmf.apple.com")); + + /* Transparent Connection Pins not configured */ + // TC policy accepts apple pins + NSArray *appleCerts = @[ (__bridge id) pallasLeaf, (__bridge id)pallasCA ]; + TestTrustEvaluation *trustTest = [[TestTrustEvaluation alloc] initWithCertificates:appleCerts policies:@[(__bridge id)policy]]; + [trustTest setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:624000000.0]]; // October 9, 2020 at 10:20:00 PM PDT + XCTAssert([trustTest evaluate:nil]); + + // TC policy doesn't accept TC pins + trustTest = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)tcLeaf] policies:@[(__bridge id)policy]]; + [trustTest setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:624000000.0]]; + [trustTest addAnchor:tcCA]; + XCTAssertFalse([trustTest evaluate:nil]); + + /* Transparent Connection pins configured */ + NSArray *pin = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(tcCA)) + }, + @{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : [self random] + } + ]; + XCTAssert(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)pin, NULL)); + + // TC policy accepts TC pins if set + [trustTest setNeedsEvaluation]; + XCTAssert([trustTest evaluate:nil]); + + // non TC policy doesn't accept TC pins if set + [trustTest setNeedsEvaluation]; + SecTrustSetPinningPolicyName([trustTest trust], kSecPolicyNameAppleMMCSService); + XCTAssertFalse([trustTest evaluate:nil]); + + // TC policy always accepts apple pin + CFReleaseNull(policy); // reset policy so to remove policy name + policy = SecPolicyCreateSSL(true, CFSTR("gdmf.apple.com")); + trustTest = [[TestTrustEvaluation alloc] initWithCertificates:appleCerts policies:@[(__bridge id)policy]]; + [trustTest setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:624000000.0]]; // October 9, 2020 at 10:20:00 PM PDT + XCTAssert([trustTest evaluate:nil]); + + XCTAssert(SecTrustStoreSetTransparentConnectionPins(NULL, NULL, NULL)); + CFReleaseNull(pallasLeaf); + CFReleaseNull(pallasCA); + CFReleaseNull(tcLeaf); + CFReleaseNull(tcCA); + CFReleaseNull(policy); +} +#endif // !TARGET_OS_BRIDGE + +static SecTrustResultType test_with_policy_exception(SecPolicyRef CF_CONSUMED policy, bool set_exception) +{ + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _ids_test, sizeof(_ids_test)); + SecCertificateRef intermediate = SecCertificateCreateWithBytes(NULL, _TestAppleServerAuth, sizeof(_TestAppleServerAuth)); + SecCertificateRef rootcert = SecCertificateCreateWithBytes(NULL, _TestAppleRootCA, sizeof(_TestAppleRootCA)); + + SecTrustRef trust = NULL; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + NSArray *certs = @[(__bridge id)leaf,(__bridge id)intermediate]; + NSArray *root = @[(__bridge id)rootcert]; + NSDate *verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:622000000.0]; //September 16, 2020 at 6:46:40 PM PDT + + require_noerr_quiet(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), cleanup); + require_noerr_quiet(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)root), cleanup); + require_noerr_quiet(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), cleanup); + if (set_exception) { + SecTrustSetPinningException(trust); + } + require_noerr_quiet(SecTrustGetTrustResult(trust, &trustResult), cleanup); + +cleanup: + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(leaf); + CFReleaseNull(intermediate); + CFReleaseNull(rootcert); + return trustResult; +} + +static SecTrustResultType test_with_policy(SecPolicyRef CF_CONSUMED policy) { + return test_with_policy_exception(policy, false); +} + +/* Technically, this feature works by reading the info plist of the caller. We'll fake it here by + * setting the policy option for requiring pinning. */ +- (void)testPinningRequired { + SecPolicyRef policy = NULL; + + // init domains are excluded from IDS pinning rules + policy = SecPolicyCreateSSL(true, CFSTR("init.ess.apple.com")); + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + is(test_with_policy(policy), kSecTrustResultRecoverableTrustFailure, "Unpinned connection succeeeded when pinning required"); + + policy = SecPolicyCreateAppleIDSServiceContext(CFSTR("init.ess.apple.com"), NULL); + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + is(test_with_policy(policy), kSecTrustResultUnspecified, "Policy pinned connection failed when pinning required"); + +#if !TARGET_OS_BRIDGE + /* BridgeOS doesn't have pinning DB */ + policy = SecPolicyCreateSSL(true, CFSTR("profile.ess.apple.com")); + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + is(test_with_policy(policy), kSecTrustResultUnspecified, "Systemwide hostname pinned connection failed when pinning required"); +#endif + + NSDictionary *policy_properties = @{ + (__bridge NSString *)kSecPolicyName : @"init.ess.apple.com", + (__bridge NSString *)kSecPolicyPolicyName : @"IDS", + }; + policy = SecPolicyCreateWithProperties(kSecPolicyAppleSSL, (__bridge CFDictionaryRef)policy_properties); + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + is(test_with_policy(policy), kSecTrustResultUnspecified, "Systemwide policy name pinned connection failed when pinning required"); + + policy = SecPolicyCreateSSL(true, CFSTR("init.ess.apple.com")); + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + is(test_with_policy_exception(policy, true), kSecTrustResultUnspecified, "Unpinned connection failed when pinning exception set"); +} + +static void test_escrow_with_anchor_roots(CFArrayRef anchors) +{ + SecCertificateRef escrowLeafCert = NULL; + SecTrustResultType trustResult = kSecTrustResultUnspecified; + SecPolicyRef policy = NULL; + CFArrayRef certs = NULL; + SecTrustRef trust = NULL; + + isnt(escrowLeafCert = SecCertificateCreateWithBytes(NULL, kEscrowLeafCert, sizeof(kEscrowLeafCert)), + NULL, "could not create aCert from kEscrowLeafCert"); + + certs = CFArrayCreate(NULL, (const void **)&escrowLeafCert, 1, NULL); + + isnt(policy = SecPolicyCreateWithProperties(kSecPolicyAppleEscrowService, NULL), + NULL, "could not create Escrow policy for GM Escrow Leaf cert"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "could not create trust for escrow service test GM Escrow Leaf cert"); + + SecTrustSetAnchorCertificates(trust, anchors); + + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate escrow service trust for GM Escrow Leaf cert"); + + is_status(trustResult, kSecTrustResultUnspecified, + "trust is not kSecTrustResultUnspecified for GM Escrow Leaf cert"); + + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(certs); + CFReleaseSafe(escrowLeafCert); + +} + +static void test_pcs_escrow_with_anchor_roots(CFArrayRef anchors) +{ + SecCertificateRef leafCert = NULL; + SecTrustResultType trustResult = kSecTrustResultUnspecified; + SecPolicyRef policy = NULL; + CFArrayRef certs = NULL; + CFDateRef date = NULL; + SecTrustRef trust = NULL; + OSStatus status; + + isnt(leafCert = SecCertificateCreateWithBytes(NULL, kPCSEscrowLeafCert, sizeof(kPCSEscrowLeafCert)), + NULL, "could not create leafCert from kPCSEscrowLeafCert"); + + certs = CFArrayCreate(NULL, (const void **)&leafCert, 1, NULL); + + isnt(policy = SecPolicyCreateWithProperties(kSecPolicyApplePCSEscrowService, NULL), + NULL, "could not create PCS Escrow policy for GM PCS Escrow Leaf cert"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "could not create trust for PCS escrow service test GM PCS Escrow Leaf cert"); + + /* Set explicit verify date: Mar 18 2016. */ + isnt(date = CFDateCreate(NULL, 480000000.0), NULL, "create verify date"); + status = (date) ? SecTrustSetVerifyDate(trust, date) : errSecParam; + ok_status(status, "set date"); + + SecTrustSetAnchorCertificates(trust, anchors); + + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate PCS escrow service trust for GM PCS Escrow Leaf cert"); + + is_status(trustResult, kSecTrustResultUnspecified, + "trust is not kSecTrustResultUnspecified for GM PCS Escrow Leaf cert"); + + CFReleaseSafe(date); + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(certs); + CFReleaseSafe(leafCert); + +} + +#if !TARGET_OS_BRIDGE +/* Bridge OS doesn't have certificates bundle */ +- (void)test_escrow +{ + CFArrayRef anchors = NULL; + isnt(anchors = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot), NULL, "unable to get production anchors"); + test_escrow_with_anchor_roots(anchors); + CFReleaseSafe(anchors); +} + +- (void)test_pcs_escrow +{ + CFArrayRef anchors = NULL; + isnt(anchors = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot), NULL, "unable to get production PCS roots"); + test_pcs_escrow_with_anchor_roots(anchors); + CFReleaseSafe(anchors); +} + +- (void)test_escrow_roots +{ + CFArrayRef baselineRoots = NULL; + isnt(baselineRoots = SecCertificateCopyEscrowRoots(kSecCertificateBaselineEscrowRoot), NULL, "unable to get baseline roots"); + ok(baselineRoots && CFArrayGetCount(baselineRoots) > 0, "baseline roots array empty"); + CFReleaseSafe(baselineRoots); + + CFArrayRef productionRoots = NULL; + isnt(productionRoots = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot), NULL, "unable to get production roots"); + ok(productionRoots && CFArrayGetCount(productionRoots) > 0, "production roots array empty"); + CFReleaseSafe(productionRoots); + + CFArrayRef baselinePCSRoots = NULL; + isnt(baselinePCSRoots = SecCertificateCopyEscrowRoots(kSecCertificateBaselinePCSEscrowRoot), NULL, "unable to get baseline PCS roots"); + ok(baselinePCSRoots && CFArrayGetCount(baselinePCSRoots) > 0, "baseline PCS roots array empty"); + CFReleaseSafe(baselinePCSRoots); + + CFArrayRef productionPCSRoots = NULL; + isnt(productionPCSRoots = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot), NULL, "unable to get production PCS roots"); + ok(productionPCSRoots && CFArrayGetCount(productionPCSRoots) > 0, "production PCS roots array empty"); + CFReleaseSafe(productionPCSRoots); +} +#endif // !TARGET_OS_BRIDGE + +- (void)testPassbook { + SecPolicyRef policy; + + CFDataRef goodSig = CFDataCreate(NULL, (const UInt8*) _USAirwaysCorrect_signature, + sizeof(_USAirwaysCorrect_signature)); + CFDataRef goodManifest = CFDataCreate(NULL, (const UInt8*) _USAirwaysCorrect_manifest_json, + sizeof(_USAirwaysCorrect_manifest_json)); + CFDataRef badSig = CFDataCreate(NULL, (const UInt8*) _USAirwaysWrongTeamID_signature, + sizeof(_USAirwaysWrongTeamID_signature)); + CFDataRef badManifest = CFDataCreate(NULL, (const UInt8*) _USAirwaysWrongTeamID_manifest_json, + sizeof(_USAirwaysWrongTeamID_manifest_json)); + + /* + OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents, + SecPolicyRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates, + CFDataRef *attached_contents, CFDictionaryRef *message_attributes) + */ + + /* Case 1: verify signature with good values */ + isnt(policy = SecFrameworkPolicyCreatePassbookCardSigner(CFSTR("pass.com.apple.cardman"), CFSTR("A1B2C3D4E5")), + NULL, "create policy"); + ok_status(SecCMSVerifySignedData(goodSig, goodManifest, policy, NULL, NULL, NULL, NULL), "verify signed data 1"); + CFReleaseNull(policy); + CFRelease(goodManifest); + CFRelease(goodSig); + policy = NULL; + + /* Case 2: verify signature with bad values */ + isnt(policy = SecFrameworkPolicyCreatePassbookCardSigner(CFSTR("pass.com.apple.cardman"), CFSTR("IAMBOGUS")), + NULL, "create policy"); + isnt(SecCMSVerifySignedData(badSig, badManifest, policy, NULL, NULL, NULL, NULL), errSecSuccess, "verify signed data 2"); + CFReleaseNull(policy); + policy = NULL; + + + /* Case 3: get trust reference back from SecCMSVerifySignedData and verify it ourselves */ + SecTrustRef trust = NULL; + SecTrustResultType trustResult; + isnt(policy = SecFrameworkPolicyCreatePassbookCardSigner(CFSTR("pass.com.apple.cardman"), CFSTR("IAMBOGUS")), + NULL, "create policy"); + ok_status(SecCMSVerifySignedData(badSig, badManifest, policy, &trust, NULL, NULL, NULL), "verify signed data 3"); + isnt(trust, NULL, "get trust"); + if (!trust) { goto errOut; } + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultRecoverableTrustFailure, "recoverable trustResult expected (ok)"); + + /* Case 4: set test policy on the trust and evaluate */ + CFReleaseNull(policy); + policy = SecPolicyCreatePassbookCardSigner(CFSTR("pass.com.apple.cardman"), CFSTR("IAMBOGUS")); + ok_status(SecTrustSetPolicies(trust, policy)); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultRecoverableTrustFailure, "recoverable trustResult expected (ok)"); + +errOut: + CFReleaseNull(trust); + CFReleaseNull(policy); + CFRelease(badManifest); + CFRelease(badSig); + trust = NULL; +} + +- (void)testiTunesStoreURLBag +{ + SecTrustRef trust; + SecCertificateRef leaf, root; + SecPolicyRef policy; + CFDataRef urlBagData; + CFDictionaryRef urlBagDict; + + isnt(urlBagData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, url_bag, sizeof(url_bag), kCFAllocatorNull), NULL, + "load url bag"); + isnt(urlBagDict = CFPropertyListCreateWithData(kCFAllocatorDefault, urlBagData, kCFPropertyListImmutable, NULL, NULL), NULL, + "parse url bag"); + CFReleaseSafe(urlBagData); + CFArrayRef certs_data = CFDictionaryGetValue(urlBagDict, CFSTR("certs")); + CFDataRef cert_data = CFArrayGetValueAtIndex(certs_data, 0); + isnt(leaf = SecCertificateCreateWithData(kCFAllocatorDefault, cert_data), NULL, "create leaf"); + isnt(root = SecCertificateCreateWithBytes(kCFAllocatorDefault, sITunesStoreRootCertificate, sizeof(sITunesStoreRootCertificate)), NULL, "create root"); + + CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **)&leaf, 1, NULL); + CFArrayRef anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&root, 1, NULL); + CFDataRef signature = CFDictionaryGetValue(urlBagDict, CFSTR("signature")); + CFDataRef bag = CFDictionaryGetValue(urlBagDict, CFSTR("bag")); + + isnt(policy = SecPolicyCreateiTunesStoreURLBag(), NULL, "create policy instance"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for leaf"); + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set iTMS anchor for evaluation"); + + /* it'll have just expired */ + CFDateRef date = CFDateCreateForGregorianZuluMoment(NULL, 2008, 11, 7, 22, 0, 0); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + + SecTrustResultType trustResult; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultUnspecified, + "trust is kSecTrustResultUnspecified"); + is(SecTrustGetCertificateCount(trust), 2, "cert count is 2"); + SecKeyRef pub_key_leaf; + isnt(pub_key_leaf = SecTrustCopyKey(trust), NULL, "get leaf pub key"); + if (!pub_key_leaf) { goto errOut; } + CFErrorRef error = NULL; + ok(SecKeyVerifySignature(pub_key_leaf, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, bag, signature, &error), + "verify signature on bag"); + CFReleaseNull(error); + +errOut: + CFReleaseSafe(pub_key_leaf); + CFReleaseSafe(urlBagDict); + CFReleaseSafe(certs); + CFReleaseSafe(anchors); + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(leaf); + CFReleaseSafe(root); +} + +- (void)testSetSHA256Pins +{ + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _pallas_leaf, sizeof(_pallas_leaf)); + SecCertificateRef ca = SecCertificateCreateWithBytes(NULL, _pallas_ca, sizeof(_pallas_ca)); + SecPolicyRef policy = SecPolicyCreateBasicX509(); + NSArray *certs = @[ (__bridge id)leaf, (__bridge id)ca]; + TestTrustEvaluation *test = [[TestTrustEvaluation alloc] initWithCertificates:certs + policies:@[(__bridge id)policy]]; + [test setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:630000000]]; // December 18, 2020 at 8:00:00 AM PST + + // Baseline verification with no pins + XCTAssert([test evaluate:nil]); + + // Bad leaf pin + NSArray *pins = @[]; + SecPolicySetSHA256Pins(policy, (__bridge CFArrayRef)pins, NULL); + SecTrustSetPolicies(test.trust, policy); + XCTAssertFalse([test evaluate:nil]); + + // Bad CA pin + SecPolicySetSHA256Pins(policy, NULL, (__bridge CFArrayRef)pins); + SecTrustSetPolicies(test.trust, policy); + XCTAssertFalse([test evaluate:nil]); + + // Correct leaf pin + pins = @[ (__bridge_transfer NSData*)SecCertificateCopySubjectPublicKeyInfoSHA256Digest(leaf)]; + SecPolicySetSHA256Pins(policy, (__bridge CFArrayRef)pins, NULL); + SecTrustSetPolicies(test.trust, policy); + XCTAssert([test evaluate:nil]); + + // Correct CA pin + pins = @[ (__bridge_transfer NSData*)SecCertificateCopySubjectPublicKeyInfoSHA256Digest(ca)]; + SecPolicySetSHA256Pins(policy, NULL, (__bridge CFArrayRef)pins); + SecTrustSetPolicies(test.trust, policy); + XCTAssert([test evaluate:nil]); +} + @end diff --git a/tests/TrustTests/EvaluationTests/PolicyTests_data.h b/tests/TrustTests/EvaluationTests/PolicyTests_data.h new file mode 100644 index 00000000..55726666 --- /dev/null +++ b/tests/TrustTests/EvaluationTests/PolicyTests_data.h @@ -0,0 +1,1363 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + */ + +#ifndef _TRUSTTESTS_EVALUATION_POLICY_TESTS_H_ +#define _TRUSTTESTS_EVALUATION_POLICY_TESTS_H_ + +/* subject:/CN=gdmf.apple.com/O=Apple Inc./ST=California/C=US */ +/* issuer :/CN=Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ +const uint8_t _pallas_leaf[] = { + 0x30,0x82,0x04,0x77,0x30,0x82,0x03,0x5F,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x6A, + 0x93,0xEB,0xB6,0x5F,0xC5,0x64,0xFD,0x96,0xB7,0xA5,0xB5,0xB4,0x0F,0x79,0xF8,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6D, + 0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x03,0x0C,0x1E,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x41,0x75,0x74,0x68,0x65,0x6E,0x74,0x69, + 0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x43,0x41,0x31,0x20,0x30,0x1E,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17, + 0x0D,0x31,0x39,0x30,0x37,0x32,0x34,0x32,0x32,0x35,0x34,0x34,0x37,0x5A,0x17,0x0D, + 0x32,0x31,0x30,0x38,0x32,0x32,0x32,0x32,0x35,0x34,0x34,0x37,0x5A,0x30,0x50,0x31, + 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x03,0x0C,0x0E,0x67,0x64,0x6D,0x66,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E, + 0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, + 0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00, + 0xB4,0xE9,0xCE,0x10,0x5C,0x5B,0xC1,0xA9,0x0C,0xBD,0x3F,0x6D,0xC8,0xC9,0x93,0xE9, + 0x00,0xC4,0xC0,0xB1,0xBB,0x94,0x3A,0x6D,0xAA,0x46,0xF0,0xBC,0x38,0x16,0xDA,0x93, + 0xD7,0x3A,0x79,0x44,0xE1,0x7B,0x1F,0x67,0x37,0xE5,0x2D,0x84,0x31,0xB1,0x7D,0x76, + 0x02,0x34,0x05,0xC8,0xF1,0x5C,0x1E,0xB2,0x83,0xAE,0xB0,0x90,0x81,0xC2,0xB2,0x36, + 0x2A,0xF2,0x93,0xDA,0xD6,0x58,0xAA,0xEF,0x78,0x5A,0xA3,0xEA,0x6C,0xA0,0x57,0xED, + 0x2A,0x5B,0xA6,0xE8,0x6B,0x0F,0xE8,0xE9,0xD5,0x4D,0x82,0x1F,0x4A,0xAF,0x3F,0x4E, + 0x60,0xF7,0xFF,0x7A,0x21,0x91,0x52,0x55,0x6B,0x8A,0x42,0xB0,0x9B,0x9F,0xE6,0x78, + 0xBB,0x75,0x63,0xDB,0xDA,0x53,0x51,0xDD,0x05,0xB6,0xDE,0x30,0x39,0xDD,0x3C,0x21, + 0xD1,0x54,0x5E,0x13,0x0F,0x7B,0x0D,0x0F,0x64,0x90,0x7F,0xFD,0x58,0x2C,0x07,0xEE, + 0x4C,0xFA,0x59,0xDE,0xC0,0xE4,0xCC,0x7B,0xB0,0x3C,0xAA,0xB7,0x58,0x7A,0x72,0x7C, + 0xE2,0xEF,0xFC,0x21,0xE2,0x4A,0xCD,0x89,0xDE,0x1C,0xE9,0x5D,0x5D,0x54,0x2B,0x58, + 0x59,0xE5,0x60,0x09,0x3D,0x6D,0x15,0x59,0x7B,0xAC,0x81,0x03,0x8C,0xD1,0x32,0x5E, + 0x96,0xC4,0xD2,0x41,0x5B,0xE6,0xD7,0x6C,0xB3,0x0B,0x57,0x69,0x12,0x01,0xED,0x0B, + 0x56,0xB8,0x72,0xF3,0xCA,0x2F,0x0B,0x0C,0xCA,0x3D,0x9A,0x92,0x16,0x6D,0x19,0xE1, + 0x1B,0xFD,0x44,0xDF,0xAC,0x09,0xC1,0xFD,0x6D,0x22,0x3E,0x0F,0x37,0x53,0x1B,0x3F, + 0x8F,0x51,0x5E,0x00,0x06,0x7C,0x37,0x00,0xF5,0x71,0x1A,0x9D,0x8A,0x93,0xE5,0x7D, + 0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x2E,0x30,0x82,0x01,0x2A,0x30,0x0C,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x2C,0xC5,0x6D,0x52,0xDD,0x31,0xEF,0x8C, + 0xEC,0x08,0x81,0xED,0xDF,0xDC,0xCA,0x43,0x00,0x45,0x01,0xD0,0x30,0x4A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x3E,0x30,0x3C,0x30,0x3A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x2E,0x68,0x74,0x74,0x70,0x3A,0x2F, + 0x2F,0x6F,0x63,0x73,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, + 0x6F,0x63,0x73,0x70,0x30,0x33,0x2D,0x61,0x70,0x70,0x6C,0x65,0x73,0x65,0x72,0x76, + 0x65,0x72,0x61,0x75,0x74,0x68,0x31,0x32,0x30,0x19,0x06,0x03,0x55,0x1D,0x11,0x04, + 0x12,0x30,0x10,0x82,0x0E,0x67,0x64,0x6D,0x66,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, + 0x63,0x6F,0x6D,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x3C,0x06,0x03,0x55,0x1D,0x1F,0x04, + 0x35,0x30,0x33,0x30,0x31,0xA0,0x2F,0xA0,0x2D,0x86,0x2B,0x68,0x74,0x74,0x70,0x3A, + 0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, + 0x61,0x70,0x70,0x6C,0x65,0x73,0x65,0x72,0x76,0x65,0x72,0x61,0x75,0x74,0x68,0x63, + 0x61,0x31,0x2E,0x63,0x72,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0xDA,0x78,0xB9,0xD3,0x23,0x4C,0x27,0x6B,0x3B,0x32,0xD5,0xFF,0xCC,0x52,0x9C, + 0xE3,0x90,0xC6,0x9D,0x05,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x05,0xA0,0x30,0x10,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64, + 0x06,0x1B,0x10,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x4F,0x63,0x02,0x8C,0x73, + 0x94,0x55,0xA7,0xBE,0x70,0x12,0x3C,0x3C,0xD7,0x90,0xE6,0x75,0xE0,0x0A,0xAD,0x76, + 0xFB,0x2D,0xA0,0xB9,0x0E,0x47,0x80,0x16,0x97,0x7E,0x99,0xCC,0xA3,0x88,0xE1,0x6D, + 0xA7,0xCC,0xE0,0xEF,0xD4,0x70,0x42,0x77,0x60,0xA0,0x87,0x0E,0xDD,0x6F,0x96,0x27, + 0x59,0x5F,0x21,0x9E,0x61,0x9E,0x84,0xAB,0x7B,0x7C,0x67,0xEC,0x5D,0xB7,0xEA,0xBD, + 0x1C,0x2F,0xD2,0x17,0xF0,0xFD,0xBE,0x72,0xE9,0xC6,0x9B,0xEA,0x85,0x1F,0xB7,0x24, + 0x37,0x34,0x28,0x5F,0xB0,0x2E,0x3D,0xCC,0xF8,0xA0,0x27,0x86,0xDC,0x16,0x47,0xFB, + 0xB1,0x2A,0xCC,0x9A,0x2B,0x5C,0xDC,0x9D,0x56,0x48,0x3E,0x7D,0x24,0xE9,0x8C,0xAE, + 0xD2,0x2F,0xA1,0x0B,0x68,0xB8,0x0E,0x6F,0x94,0x6A,0x2F,0xAA,0xBC,0xC9,0x17,0x2A, + 0x0A,0x1A,0x53,0x5D,0xAF,0x44,0x3D,0x5C,0xA6,0x01,0x38,0x8C,0x91,0xD4,0x24,0x5C, + 0x0B,0xDF,0xF3,0x92,0x04,0xAD,0x1A,0x08,0xC0,0x97,0x17,0x1C,0x0D,0x98,0x9F,0xA8, + 0xBF,0x75,0x07,0x9E,0x0F,0xBA,0x74,0x45,0x0E,0x66,0xB0,0xF8,0x46,0x33,0x13,0x7C, + 0x4A,0x58,0x66,0x04,0x94,0xC3,0x3B,0x39,0xF0,0x40,0x6A,0x43,0x69,0x0D,0x48,0xAD, + 0x37,0xA4,0xC8,0x14,0x0B,0x9F,0x9E,0x5A,0x9F,0x00,0xC1,0x0D,0x5C,0xEE,0xA1,0xEA, + 0xDC,0xC9,0x8B,0xB7,0x4C,0x33,0xF9,0x5A,0x53,0x92,0x1E,0xA6,0x33,0xE2,0xD9,0x0F, + 0x33,0xB0,0x37,0x34,0x73,0xBC,0x4E,0xE7,0xDC,0xB4,0x2C,0x3F,0xD7,0x1C,0xB8,0x4A, + 0xD5,0xED,0x9D,0x1E,0x0A,0xAE,0xFC,0xFC,0xC6,0xC6,0x11, +}; + +/* subject:/CN=Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA */ +const uint8_t _pallas_ca[] = { + 0x30,0x82,0x03,0xF8,0x30,0x82,0x02,0xE0,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x23, + 0x69,0x74,0x04,0xAD,0xCB,0x83,0x14,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x34, + 0x30,0x33,0x30,0x38,0x30,0x31,0x35,0x33,0x30,0x34,0x5A,0x17,0x0D,0x32,0x39,0x30, + 0x33,0x30,0x38,0x30,0x31,0x35,0x33,0x30,0x34,0x5A,0x30,0x6D,0x31,0x27,0x30,0x25, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x1E,0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x65,0x72, + 0x76,0x65,0x72,0x20,0x41,0x75,0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x43,0x41,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x0C,0x17, + 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75, + 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F, + 0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xB9,0x26,0x16,0xB0,0xCB,0x87, + 0xAB,0x71,0x15,0x92,0x8E,0xDF,0xAA,0x3E,0xE1,0x80,0xD7,0x53,0xBA,0xA4,0x60,0xCC, + 0x7C,0x85,0x72,0xF7,0x30,0x7C,0x09,0x4F,0x57,0x0D,0x4A,0xFF,0xE1,0x5E,0xC9,0x4B, + 0x50,0x13,0x02,0x64,0xB1,0xBD,0x39,0x35,0xD1,0xD7,0x04,0x51,0xC1,0x18,0xFA,0x22, + 0xFA,0xAE,0xDF,0x98,0x18,0xD6,0xBF,0x4E,0x4D,0x43,0x10,0xFA,0x25,0x88,0x9F,0xD3, + 0x40,0x85,0x76,0xE5,0x22,0x81,0xB6,0x54,0x45,0x73,0x9A,0x8B,0xE3,0x9C,0x48,0x1A, + 0x86,0x7A,0xC3,0x51,0xE2,0xDA,0x95,0xF8,0xA4,0x7D,0xDB,0x30,0xDE,0x6C,0x0E,0xC4, + 0xC5,0xF5,0x6C,0x98,0xE7,0xA6,0xFA,0x57,0x20,0x1D,0x19,0x73,0x7A,0x0E,0xCD,0x63, + 0x0F,0xB7,0x27,0x88,0x2E,0xE1,0x9A,0x68,0x82,0xB8,0x40,0x6C,0x63,0x16,0x24,0x66, + 0x2B,0xE7,0xB2,0xE2,0x54,0x7D,0xE7,0x88,0x39,0xA2,0x1B,0x81,0x3E,0x02,0xD3,0x39, + 0xD8,0x97,0x77,0x4A,0x32,0x0C,0xD6,0x0A,0x0A,0xB3,0x04,0x9B,0xF1,0x72,0x6F,0x63, + 0xA8,0x15,0x1E,0x6C,0x37,0xE8,0x0F,0xDB,0x53,0x90,0xD6,0x29,0x5C,0xBC,0x6A,0x57, + 0x9B,0x46,0x78,0x0A,0x3E,0x24,0xEA,0x9A,0x3F,0xA1,0xD8,0x3F,0xF5,0xDB,0x6E,0xA8, + 0x6C,0x82,0xB5,0xDD,0x99,0x38,0xEC,0x92,0x56,0x94,0xA6,0xC5,0x73,0x26,0xD1,0xAE, + 0x08,0xB2,0xC6,0x52,0xE7,0x8E,0x76,0x4B,0x89,0xB8,0x54,0x0F,0x6E,0xE0,0xD9,0x42, + 0xDB,0x2A,0x65,0x87,0x46,0x14,0xBB,0x96,0xB8,0x57,0xBB,0x51,0xE6,0x84,0x13,0xF7, + 0x0D,0xA1,0xB6,0x89,0xAC,0x7C,0xD1,0x21,0x74,0xAB,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x81,0xA6,0x30,0x81,0xA3,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, + 0x2C,0xC5,0x6D,0x52,0xDD,0x31,0xEF,0x8C,0xEC,0x08,0x81,0xED,0xDF,0xDC,0xCA,0x43, + 0x00,0x45,0x01,0xD0,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05, + 0x30,0x03,0x01,0x01,0xFF,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6, + 0xF7,0x47,0x4D,0x7F,0x08,0x5E,0x30,0x2E,0x06,0x03,0x55,0x1D,0x1F,0x04,0x27,0x30, + 0x25,0x30,0x23,0xA0,0x21,0xA0,0x1F,0x86,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x63,0x72,0x6C,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x72,0x6F, + 0x6F,0x74,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF, + 0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x10,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63, + 0x64,0x06,0x02,0x0C,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x23,0xF1,0x06,0x7E, + 0x50,0x41,0x81,0xA2,0x5E,0xD3,0x70,0xA4,0x49,0x91,0xAF,0xD8,0xCC,0x67,0x8C,0xA1, + 0x25,0x7D,0xC4,0x9A,0x93,0x39,0x2F,0xD8,0x69,0xFB,0x1B,0x41,0x5B,0x44,0xD7,0xD9, + 0x6B,0xCB,0x3B,0x25,0x09,0x1A,0xF2,0xF4,0xE3,0xC7,0x9C,0xE8,0xB0,0x5B,0xF0,0xDF, + 0xDD,0x22,0x25,0x11,0x15,0x93,0xB9,0x49,0x5E,0xDA,0x0C,0x66,0x7A,0x5E,0xD7,0x6F, + 0xF0,0x63,0xD4,0x65,0x8C,0xC4,0x7A,0x54,0x7D,0x56,0x4F,0x65,0x9A,0xFD,0xDA,0xC4, + 0xB2,0xC8,0xB0,0xB8,0xA1,0xCB,0x7D,0xE0,0x47,0xA8,0x40,0x15,0xB8,0x16,0x19,0xED, + 0x5B,0x61,0x8E,0xDF,0xAA,0xD0,0xCD,0xD2,0x3A,0xC0,0x7E,0x3A,0x9F,0x22,0x4E,0xDF, + 0xDF,0xF4,0x4E,0x1A,0xCD,0x93,0xFF,0xD0,0xF0,0x45,0x55,0x64,0x33,0x3E,0xD4,0xE5, + 0xDA,0x68,0xA0,0x13,0x8A,0x76,0x30,0x27,0xD4,0xBF,0xF8,0x1E,0x76,0xF6,0xF9,0xC3, + 0x00,0xEF,0xB1,0x83,0xEA,0x53,0x6D,0x5C,0x35,0xC7,0x0D,0x07,0x01,0xBA,0xF8,0x61, + 0xB9,0xFE,0xC5,0x9A,0x6B,0x43,0x61,0x81,0x03,0xEB,0xBA,0x5F,0x70,0x9D,0xE8,0x6F, + 0x94,0x24,0x4B,0xDC,0xCE,0x92,0xA8,0x2E,0xA2,0x35,0x3C,0xE3,0x49,0xE0,0x16,0x77, + 0xA2,0xDC,0x6B,0xB9,0x8D,0x18,0x42,0xB9,0x36,0x96,0x43,0x32,0xC6,0xCB,0x76,0x99, + 0x35,0x36,0xD8,0x56,0xC6,0x98,0x5D,0xC3,0x6F,0xA5,0x7E,0x95,0xC2,0xD5,0x7A,0x0A, + 0x02,0x20,0x66,0x78,0x92,0xF2,0x67,0xA4,0x23,0x0D,0xE8,0x09,0xBD,0xCC,0x21,0x31, + 0x10,0xA0,0xBD,0xBE,0xB5,0xDD,0x4C,0xDD,0x46,0x03,0x99,0x99, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Transparent Connection Test CA */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Transparent Connection Test CA */ +const uint8_t _transparent_connection_ca[] = { + 0x30,0x82,0x03,0xF0,0x30,0x82,0x02,0xD8,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xAB,0xC7,0x95,0xF5,0xB3,0x94,0xBB,0x6F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x93,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x03,0x0C,0x1E,0x54, + 0x72,0x61,0x6E,0x73,0x70,0x61,0x72,0x65,0x6E,0x74,0x20,0x43,0x6F,0x6E,0x6E,0x65, + 0x63,0x74,0x69,0x6F,0x6E,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x30,0x1E,0x17, + 0x0D,0x32,0x30,0x31,0x30,0x30,0x39,0x30,0x30,0x34,0x36,0x35,0x35,0x5A,0x17,0x0D, + 0x32,0x31,0x31,0x30,0x30,0x39,0x30,0x30,0x34,0x36,0x35,0x35,0x5A,0x30,0x81,0x93, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E, + 0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70, + 0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45, + 0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x27,0x30,0x25,0x06,0x03, + 0x55,0x04,0x03,0x0C,0x1E,0x54,0x72,0x61,0x6E,0x73,0x70,0x61,0x72,0x65,0x6E,0x74, + 0x20,0x43,0x6F,0x6E,0x6E,0x65,0x63,0x74,0x69,0x6F,0x6E,0x20,0x54,0x65,0x73,0x74, + 0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, + 0x82,0x01,0x01,0x00,0xB7,0x94,0x65,0x27,0x10,0xC3,0x9E,0xFB,0xBD,0x8E,0x4D,0x94, + 0x76,0x0C,0x73,0x96,0xF7,0x2D,0xB1,0x99,0x52,0xE3,0x7F,0x5D,0x70,0xE8,0x52,0x2E, + 0x38,0xCB,0x2A,0xF9,0x60,0x8E,0x97,0x26,0x56,0x6F,0x5D,0xC5,0x19,0x6F,0xD0,0xB8, + 0xE0,0x4A,0x4A,0x84,0x52,0x49,0x68,0x38,0x34,0xA4,0xA7,0x7B,0xDE,0xD3,0xDD,0xEC, + 0x07,0x0E,0xFF,0x98,0x48,0x4B,0x92,0xA1,0x7C,0x3F,0xEE,0x91,0x02,0xDD,0xD9,0x7E, + 0x54,0xD6,0xCF,0x29,0xC5,0xAE,0x3E,0xF1,0x58,0x8E,0xDA,0x39,0x40,0xDF,0x34,0xBA, + 0x99,0x49,0x65,0x4D,0x94,0x49,0xB1,0xC6,0xE1,0x84,0x1A,0x25,0x54,0x21,0xB0,0xE3, + 0xAF,0x98,0xC9,0xDB,0x83,0xE2,0x03,0x2D,0x58,0x13,0xB5,0xAB,0x35,0xBE,0x9B,0xF1, + 0x6F,0xC1,0x68,0x0E,0x69,0xE2,0x00,0x3E,0x27,0xC6,0xCE,0xBE,0xAD,0xF5,0x5E,0x86, + 0xDD,0x74,0xFF,0x69,0xD8,0xA9,0x6A,0x4F,0x31,0x41,0xC6,0xD7,0x4F,0xBE,0x8F,0x2F, + 0xB4,0x5B,0x07,0x41,0x6A,0x70,0x59,0xD9,0x4E,0xA8,0x4E,0x3B,0x2D,0xAE,0x5F,0x94, + 0xF7,0x34,0x36,0xC3,0xBC,0x5D,0xC0,0x5D,0x27,0x8B,0xDF,0x77,0x79,0xB3,0x73,0xB0, + 0x38,0x7B,0x1C,0xEE,0x87,0x36,0x75,0x03,0x9B,0x1C,0x69,0x17,0x71,0x25,0x63,0xED, + 0x5A,0xEF,0x97,0xF5,0xDC,0xB4,0x24,0xE3,0xDF,0xB3,0xE9,0xE1,0x09,0x4F,0x55,0xE6, + 0x9B,0x87,0xD5,0xAD,0x95,0x05,0xFB,0xF8,0xE9,0xEF,0x0E,0x20,0xDE,0x84,0xC6,0xC6, + 0x75,0x1B,0x11,0x69,0xAC,0xE3,0xF1,0xC9,0x7C,0x43,0x59,0x15,0xA0,0x98,0xD9,0x1B, + 0x6D,0x3C,0x53,0xD7,0x02,0x03,0x01,0x00,0x01,0xA3,0x45,0x30,0x43,0x30,0x12,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01, + 0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x3E,0xFB,0x2A,0x15, + 0xF2,0xF9,0x02,0x00,0x54,0x55,0x83,0x7B,0x9D,0x6F,0x60,0x6B,0x1F,0xFE,0xE8,0x85, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x0E,0x70,0x52,0x31,0x66,0x33,0x1E,0xCE,0x75,0xCA,0x6B,0x0D, + 0xE3,0x3C,0x50,0x5F,0xB5,0x55,0x48,0x9A,0xF2,0x5E,0x1C,0x3B,0x8D,0x62,0xA1,0xDF, + 0xF3,0x3C,0x3B,0x25,0x49,0x26,0xF6,0x36,0x5B,0x4D,0x76,0xDA,0xEA,0x5C,0x89,0xDF, + 0x1F,0xB8,0x46,0x89,0x69,0x7D,0xF2,0x99,0x50,0x7B,0xD0,0x4C,0x98,0x54,0xA8,0x83, + 0x42,0x91,0x61,0x27,0x18,0x00,0x92,0x96,0xE4,0x18,0xA0,0x23,0xB6,0xF3,0x36,0xEB, + 0x77,0x67,0xA9,0x90,0xDF,0x8F,0x7F,0xFD,0x13,0xCA,0xEA,0x1D,0xA0,0xDD,0xB2,0xB2, + 0x40,0x44,0x26,0xAC,0xA1,0x56,0x94,0xDB,0x09,0x97,0x6B,0x3C,0xB2,0x58,0xE5,0xB8, + 0x22,0x16,0x58,0x79,0x6F,0x5A,0x19,0x31,0xB1,0x8D,0xDB,0xCA,0x9A,0x4B,0xF5,0xAE, + 0xAF,0xE5,0x51,0x4F,0x22,0xFF,0x03,0x28,0xE7,0xD5,0x39,0xB4,0x53,0x87,0x31,0x5E, + 0x19,0xAB,0xD9,0xEA,0x14,0xF2,0x48,0x08,0x2F,0xB6,0x80,0x9B,0x90,0x4F,0x04,0xF1, + 0xA6,0x32,0x86,0x87,0x7B,0x82,0x65,0x6E,0xFB,0x05,0x25,0x8A,0x0A,0x5D,0xE8,0x15, + 0x32,0x80,0x7A,0x60,0xE3,0xC1,0x90,0xF3,0xFF,0xB3,0x02,0xFD,0x1E,0x66,0x8B,0xA0, + 0xD7,0x6A,0xE9,0x32,0x12,0x37,0xBA,0x37,0x8A,0xA8,0xEF,0x6A,0x96,0x4C,0xE6,0x21, + 0x20,0x99,0x69,0x1B,0xE8,0xEF,0xD4,0xCF,0x7D,0x5C,0x1A,0x7A,0x1D,0xA9,0xD3,0xC1, + 0x18,0x59,0xDA,0xD6,0x8B,0xB1,0x47,0xCD,0x08,0xC9,0xB5,0x99,0xFD,0x69,0xCB,0x25, + 0xC8,0xD1,0xA1,0x6F,0x5F,0xC9,0x5F,0x89,0x9B,0xC4,0x66,0xC3,0x8F,0x14,0x4E,0xDC, + 0x99,0x88,0xEF,0xC4, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=gdmf.apple.com */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Transparent Connection Test CA */ +const uint8_t _transparent_connection_leaf[] = { + 0x30,0x82,0x04,0x37,0x30,0x82,0x03,0x1F,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x54, + 0xC3,0x41,0x86,0xC5,0x63,0xA6,0x51,0x8E,0x3E,0x4B,0x54,0x9F,0xD3,0x9C,0xEF,0xB9, + 0x05,0xF7,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x30,0x81,0x93,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C, + 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, + 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x27, + 0x30,0x25,0x06,0x03,0x55,0x04,0x03,0x0C,0x1E,0x54,0x72,0x61,0x6E,0x73,0x70,0x61, + 0x72,0x65,0x6E,0x74,0x20,0x43,0x6F,0x6E,0x6E,0x65,0x63,0x74,0x69,0x6F,0x6E,0x20, + 0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x32,0x30,0x31,0x30,0x30, + 0x39,0x30,0x30,0x34,0x39,0x30,0x38,0x5A,0x17,0x0D,0x32,0x31,0x31,0x30,0x30,0x39, + 0x30,0x30,0x34,0x39,0x30,0x38,0x5A,0x30,0x81,0x83,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x03,0x0C,0x0E,0x67, + 0x64,0x6D,0x66,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01, + 0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, + 0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xEA,0x50, + 0x86,0xA8,0x19,0x0D,0x1A,0x50,0x7E,0x62,0x86,0x5B,0xDD,0xB7,0xE3,0x5E,0x87,0xB4, + 0x49,0x42,0x35,0x92,0xA5,0x14,0x33,0x04,0x4E,0xDF,0xA0,0x2A,0x4A,0xA0,0x8E,0x23, + 0x1B,0x2F,0x81,0x5B,0x49,0xF2,0x03,0xDA,0x2E,0xDC,0x6F,0xCA,0x62,0x6B,0x32,0x36, + 0xCD,0xFA,0x5F,0x21,0xE0,0xD9,0xAC,0x6B,0xA1,0x6B,0x63,0xD4,0xF6,0x61,0x15,0x14, + 0xF1,0x76,0x1A,0xBF,0x3F,0x43,0x00,0xF5,0x18,0x9B,0x7D,0x5A,0xAA,0x88,0x9E,0x20, + 0xAE,0x0E,0x1E,0x0F,0xF7,0x9B,0xB9,0xD0,0x45,0x3E,0xD6,0xED,0xE7,0x1B,0x62,0xD0, + 0x0C,0x76,0xF1,0xC9,0xC6,0xCF,0xE7,0xE1,0x0E,0xF4,0x71,0xDE,0xD4,0xF3,0x20,0x25, + 0x47,0x11,0x30,0xBE,0x5A,0x33,0x5D,0x60,0xD8,0x6E,0xE4,0x38,0x21,0x51,0xC5,0x17, + 0xA7,0x8E,0x2B,0xB1,0x30,0xC9,0xD7,0xEE,0x7B,0xEF,0x31,0x30,0x82,0x45,0x5F,0x2D, + 0xAA,0xE8,0x81,0x10,0xCB,0xE6,0xB0,0xB0,0xF6,0xE9,0x9B,0xE5,0xE6,0x05,0xAB,0x73, + 0x12,0x08,0x19,0x4F,0x6B,0xA2,0x74,0x38,0x4D,0x9B,0xBF,0xF4,0xD6,0x2D,0x16,0x1B, + 0x99,0xDD,0x0D,0x4A,0x74,0xBB,0x4B,0x35,0x47,0xEC,0xCE,0xAA,0x1A,0x36,0x78,0xDB, + 0x99,0x50,0xAE,0xCC,0x95,0xBC,0x7C,0xCA,0x66,0x1E,0xEC,0xDE,0x0D,0x96,0x44,0x02, + 0xFE,0xC9,0xAC,0x28,0xFD,0xB0,0x6D,0x83,0x26,0xFC,0xA9,0xF2,0x2B,0x5A,0x32,0x34, + 0xFB,0xB6,0x3B,0x30,0x1B,0x08,0x3B,0xA6,0x9D,0x83,0xA8,0xE6,0x12,0x10,0x2C,0xBA, + 0x85,0x9D,0xC5,0xFC,0x76,0x8A,0x0B,0x96,0xF7,0x2A,0x02,0x58,0xF2,0x75,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x81,0x91,0x30,0x81,0x8E,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13, + 0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C, + 0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x19,0x06,0x03, + 0x55,0x1D,0x11,0x04,0x12,0x30,0x10,0x82,0x0E,0x67,0x64,0x6D,0x66,0x2E,0x61,0x70, + 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0x19,0x54,0xAC,0x65,0x01,0x0B,0x92,0xA3,0x07,0xCF,0xDD,0x14,0x4B,0x51, + 0xB8,0x2F,0xA1,0x38,0xC9,0xC5,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, + 0x16,0x80,0x14,0x3E,0xFB,0x2A,0x15,0xF2,0xF9,0x02,0x00,0x54,0x55,0x83,0x7B,0x9D, + 0x6F,0x60,0x6B,0x1F,0xFE,0xE8,0x85,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x17,0xAE,0xAA,0x8A,0x22, + 0xC7,0x74,0x42,0x49,0xE4,0x81,0xE9,0xB6,0x50,0xCE,0xD7,0x72,0xB9,0x21,0x94,0x9D, + 0xBE,0x76,0xBE,0x2A,0x68,0x38,0x7A,0xC5,0x7D,0x37,0xBC,0xCF,0x7C,0x00,0xFE,0x6C, + 0xEB,0x2F,0xFC,0x2D,0x77,0x0B,0xC2,0x0D,0x2C,0x58,0x8C,0x66,0xF6,0x02,0x97,0x5F, + 0xC4,0xEA,0x25,0xA4,0x85,0xC3,0xAD,0x22,0x3E,0x78,0xBE,0x84,0x50,0xC2,0x28,0xD5, + 0x69,0x62,0x42,0x9D,0xEC,0x88,0xFC,0x86,0x6E,0x80,0xA7,0xAE,0xDF,0xE6,0x66,0x19, + 0x1C,0x7F,0x40,0xC9,0xD0,0x43,0xA1,0xD1,0x25,0x6D,0xA8,0x42,0xFC,0x84,0xB6,0xBC, + 0x43,0x31,0xF7,0x92,0xDB,0x20,0x99,0xAA,0x77,0x33,0xCA,0xA0,0xB4,0x1B,0x0F,0x2F, + 0x8F,0xC7,0x14,0x69,0x4D,0x39,0x0D,0x4A,0xEC,0xF5,0x08,0x58,0xCF,0x97,0x84,0x24, + 0x7D,0x04,0x2A,0x3D,0x99,0xA6,0x36,0xF7,0x92,0x12,0x1B,0x6C,0xE0,0x26,0xC8,0x1D, + 0x3A,0xEE,0xD7,0xE0,0xB6,0x4F,0xFE,0xF7,0x19,0x15,0xAA,0x41,0x13,0xE4,0xA9,0xD5, + 0xB1,0x0A,0x10,0x24,0x30,0xCB,0xF3,0x32,0x99,0xFB,0x1F,0x0C,0xE6,0x97,0xDC,0x2A, + 0xF8,0x6F,0x5E,0x31,0xFE,0x0F,0x46,0x06,0xF0,0xCC,0xCB,0x16,0x9F,0x09,0x20,0xAF, + 0x88,0x21,0xAD,0xDA,0xFE,0xBB,0x3A,0x46,0xD1,0x7E,0x0A,0xBA,0x04,0xFF,0x76,0xBB, + 0x7D,0x74,0xBD,0xCB,0x1B,0x50,0x85,0x46,0xB1,0x86,0x9E,0x36,0x96,0x90,0xC8,0x98, + 0xBF,0xE1,0x18,0xA3,0xD3,0xC0,0x04,0x0D,0x42,0xF9,0xEF,0x83,0x4D,0xFE,0x61,0x6F, + 0xF4,0xF6,0x6E,0xF8,0x05,0x2B,0xA8,0x52,0x3B,0x4E,0x0C, +}; + +/* subject:/CN=init.ess.apple.com/O=Apple Inc./ST=California/C=US */ +/* issuer :/CN=Test Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ +uint8_t _ids_test[]={ + 0x30,0x82,0x04,0x87,0x30,0x82,0x03,0x6F,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x72, + 0xA1,0xD2,0xCA,0x8B,0x32,0x32,0xCB,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x72,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x23,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x65, + 0x72,0x76,0x65,0x72,0x20,0x41,0x75,0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74, + 0x69,0x6F,0x6E,0x20,0x43,0x41,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x32,0x30, + 0x30,0x39,0x31,0x33,0x32,0x33,0x34,0x30,0x31,0x37,0x5A,0x17,0x0D,0x32,0x31,0x31, + 0x30,0x31,0x33,0x32,0x33,0x34,0x30,0x31,0x37,0x5A,0x30,0x54,0x31,0x1B,0x30,0x19, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x69,0x6E,0x69,0x74,0x2E,0x65,0x73,0x73,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, + 0x00,0xA0,0x86,0xAC,0xB1,0xE9,0xAE,0xD2,0x94,0x23,0x46,0x80,0x95,0x7E,0x25,0x89, + 0x43,0x0F,0x8B,0xA2,0x60,0x49,0xCB,0x1C,0xA4,0x33,0x3C,0x7E,0x27,0x7C,0xA2,0x04, + 0x88,0x90,0xD0,0x1D,0xCA,0x67,0x6F,0xFE,0xF0,0xB9,0x68,0xF9,0x7A,0x7E,0xD3,0xA2, + 0x96,0x27,0xFD,0x42,0x1F,0x67,0x27,0x72,0x31,0x68,0x71,0x98,0x71,0x58,0x62,0x05, + 0x83,0xCC,0xC8,0x48,0x96,0x3C,0x96,0x73,0x13,0x4C,0x5B,0x22,0x12,0xBF,0x42,0xEB, + 0x1F,0x4B,0x7F,0x2F,0xC9,0x92,0x08,0x41,0x2A,0xFD,0xF9,0xA7,0xF2,0x36,0xC6,0x7D, + 0xAB,0x25,0xA1,0x5B,0x26,0x30,0x7F,0x4A,0x19,0xEE,0xDB,0x26,0x5C,0x22,0x68,0x1D, + 0xFC,0x81,0x7D,0x1B,0x76,0xFA,0x98,0x16,0xDE,0x3B,0xC3,0x6F,0x8B,0x14,0x01,0xDF, + 0xD8,0x34,0x37,0x4A,0x2A,0x2A,0xE9,0xCE,0x78,0x58,0x40,0x41,0x14,0x1F,0xDD,0x86, + 0x30,0xD3,0xBD,0xA5,0x02,0x5E,0xFD,0x40,0xDF,0x2D,0xDA,0x6C,0x1C,0xD8,0x7F,0x92, + 0xBB,0xA4,0xF9,0x8B,0x3A,0xDE,0xAE,0xA7,0x23,0x5C,0x2B,0x9C,0x2F,0x9A,0xFD,0x0E, + 0xF5,0xFE,0x40,0x7F,0x5C,0x7C,0xA9,0x01,0xE2,0x11,0x21,0x96,0xFA,0xEF,0x2B,0x0C, + 0x95,0x7E,0x96,0x2D,0xA0,0xA9,0x15,0x7A,0x82,0x25,0x83,0x12,0xD6,0x83,0x0A,0x91, + 0xA5,0xD7,0xF2,0xCB,0xC3,0x18,0x4E,0xF4,0xA1,0xA1,0x0A,0xD1,0x7E,0x88,0x1C,0xB1, + 0x10,0xA9,0x83,0xE3,0xAD,0xF7,0xFF,0xEA,0xDC,0x20,0xEB,0x74,0x94,0xE0,0x89,0xDF, + 0x34,0x25,0x28,0x58,0xE9,0xC8,0x93,0x84,0x2D,0x24,0xB0,0xDC,0xD2,0x46,0x09,0x63, + 0x5F,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x3D,0x30,0x82,0x01,0x39,0x30,0x0C, + 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06,0x03, + 0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xA8,0xCA,0x7A,0x9B,0xA8,0x37,0x71, + 0x9E,0x3D,0xEC,0x5A,0xAB,0x66,0x2E,0xDC,0xD7,0x14,0x3D,0x7B,0xF2,0x30,0x66,0x06, + 0x03,0x55,0x1D,0x11,0x04,0x5F,0x30,0x5D,0x82,0x15,0x70,0x72,0x6F,0x66,0x69,0x6C, + 0x65,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x82, + 0x18,0x6F,0x70,0x65,0x6E,0x6D,0x61,0x72,0x6B,0x65,0x74,0x2E,0x65,0x73,0x73,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x82,0x16,0x69,0x64,0x65,0x6E,0x74, + 0x69,0x74,0x79,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, + 0x6D,0x82,0x12,0x69,0x6E,0x69,0x74,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x49,0x06,0x03,0x55,0x1D, + 0x1F,0x04,0x42,0x30,0x40,0x30,0x3E,0xA0,0x3C,0xA0,0x3A,0x86,0x38,0x68,0x74,0x74, + 0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70, + 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65,0x73,0x74,0x61, + 0x70,0x70,0x6C,0x65,0x73,0x65,0x72,0x76,0x65,0x72,0x61,0x75,0x74,0x68,0x63,0x61, + 0x31,0x2E,0x63,0x72,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, + 0x74,0x05,0xFF,0xDB,0xBE,0x4A,0xC9,0x3B,0x54,0x77,0xAE,0x4E,0x60,0xB2,0xD1,0x47, + 0x70,0xCE,0x35,0xDB,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, + 0x03,0x02,0x05,0xA0,0x30,0x11,0x06,0x0B,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06, + 0x1B,0x04,0x02,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xAB,0x83,0x22,0x06,0x14, + 0x92,0x90,0x4F,0xFF,0x87,0x9F,0xF5,0x69,0xFE,0x87,0x14,0xAD,0x58,0x47,0x86,0x17, + 0x48,0x90,0xAA,0x34,0x37,0x23,0x7E,0x37,0x93,0x5D,0xCA,0xFF,0xEF,0x97,0x13,0x2B, + 0xFF,0x82,0x51,0xCA,0x87,0xF0,0xE1,0x1C,0x8C,0x95,0xE3,0x96,0x2D,0x69,0x6B,0x8C, + 0xFA,0xCC,0x57,0x20,0x35,0x98,0x31,0x83,0x30,0xF3,0x62,0xE8,0xD0,0xAB,0xBE,0xE3, + 0xFB,0x68,0xB4,0xBD,0x10,0xFC,0xDD,0x4B,0x5A,0x07,0x51,0x91,0x29,0xA6,0x6F,0x84, + 0x42,0xD8,0xAE,0xF2,0x3A,0xD2,0xA2,0xB4,0xB6,0xAB,0x32,0x24,0xE3,0xFD,0x57,0x8E, + 0x53,0xDD,0x53,0x7D,0x6E,0xE4,0x76,0x80,0x13,0xB9,0xF4,0x12,0x03,0xB4,0xB6,0x6D, + 0x3C,0xCA,0x9C,0x08,0x37,0xF2,0xD8,0x97,0x62,0x1C,0xC9,0xFF,0x4B,0x8E,0x7A,0xA4, + 0x07,0x66,0x98,0xB9,0x95,0xB2,0xA2,0xD4,0xF1,0x4E,0x0B,0xC9,0xC1,0xEB,0x10,0x21, + 0xA3,0xFD,0x69,0xF4,0x64,0xF0,0x55,0x7E,0xFB,0x3C,0x5D,0x4A,0xF2,0x65,0xB1,0x67, + 0x68,0x59,0xE6,0xE1,0x9F,0x93,0xDD,0x2A,0x44,0x76,0x85,0x16,0x82,0x6A,0x1E,0xA6, + 0x37,0xE8,0xD0,0x16,0x73,0x03,0xBE,0x88,0xBC,0x50,0x97,0xA3,0xC2,0xB9,0x65,0xF1, + 0x64,0x92,0x57,0x04,0xAD,0xE6,0x77,0x3F,0x1B,0xA4,0xE3,0xF2,0xBE,0x41,0xA6,0x66, + 0x9E,0xC6,0xF5,0x07,0xE8,0x9B,0x13,0x34,0x06,0x55,0x45,0x37,0x88,0x65,0x4F,0x4C, + 0x11,0xE0,0x02,0xD7,0xE8,0xC3,0x1B,0x4D,0xCD,0x31,0x59,0x55,0x90,0xA3,0x6A,0x40, + 0x31,0xAD,0x92,0x86,0xFE,0x53,0xC5,0xB8,0x5E,0xA3,0x02, +}; + +/* subject:/CN=Test Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Test Apple Root CA */ +uint8_t _TestAppleServerAuth[]={ + 0x30,0x82,0x04,0x0F,0x30,0x82,0x02,0xF7,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x4B, + 0x28,0xA9,0x3B,0x57,0x8B,0xF6,0x26,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x67,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x54,0x65,0x73, + 0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30, + 0x1E,0x17,0x0D,0x31,0x35,0x30,0x36,0x30,0x38,0x30,0x37,0x35,0x38,0x34,0x35,0x5A, + 0x17,0x0D,0x32,0x39,0x30,0x33,0x30,0x38,0x30,0x31,0x35,0x33,0x30,0x34,0x5A,0x30, + 0x72,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04,0x03,0x0C,0x23,0x54,0x65,0x73,0x74, + 0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x41,0x75, + 0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x43,0x41,0x31, + 0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74, + 0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, + 0x82,0x01,0x01,0x00,0xC5,0x7B,0x3F,0x48,0xD3,0x62,0x93,0x93,0x7C,0x0C,0x37,0x69, + 0xDB,0x28,0x05,0x40,0x12,0xD7,0x1F,0x0A,0xB8,0xC3,0xBA,0x24,0x39,0x22,0xDC,0x39, + 0x42,0x1F,0xFD,0x93,0x45,0x3C,0x23,0x0B,0x3E,0xB4,0x96,0xA6,0x55,0x59,0xBA,0xC4, + 0x99,0xE7,0x8A,0x5F,0x8F,0xAE,0x66,0xA7,0x28,0xE2,0x9E,0x68,0xD9,0xEC,0x52,0x67, + 0xFE,0xDD,0xBE,0x59,0xB4,0xAD,0x97,0x63,0x64,0xB0,0x08,0x3C,0xBB,0x6E,0xD1,0x29, + 0xD8,0x58,0xA1,0x99,0x6C,0x2F,0x2F,0xB3,0xF5,0x5C,0x59,0xCA,0xA1,0xE6,0x67,0x44, + 0x3C,0x13,0xB4,0xAE,0x0D,0x00,0xC7,0x53,0xB7,0xF5,0x61,0x58,0xD5,0xC8,0x42,0xFC, + 0xE2,0xFD,0xD5,0x39,0x18,0x80,0xE2,0x72,0xBC,0xF8,0xC3,0x9F,0xCB,0xD8,0x2F,0x83, + 0x40,0x9A,0x3E,0x55,0x5E,0x61,0xA9,0xC4,0x81,0x14,0x2B,0x7B,0x19,0x15,0xAD,0x84, + 0x5E,0x80,0xA8,0x67,0x79,0x05,0x16,0x48,0x5C,0xAE,0x1A,0x2B,0x59,0x9F,0xAA,0x62, + 0x0B,0x2F,0x57,0xCD,0xE8,0xA8,0x5D,0x38,0xAD,0x7C,0x90,0x79,0x50,0xAC,0x4D,0x13, + 0xA4,0xA7,0xF3,0x73,0xED,0xD6,0x93,0x45,0xDD,0xA8,0xC6,0xFE,0x03,0x28,0x4D,0x58, + 0xC1,0x8B,0xC1,0x03,0x0E,0xE7,0xDF,0x78,0xDD,0x21,0xC6,0x6D,0x1E,0xA0,0x38,0xD7, + 0xA7,0xD7,0x04,0x8C,0x7F,0xCA,0x15,0xEA,0x88,0xE9,0xAE,0x8D,0x46,0xE0,0x87,0x94, + 0x3E,0x8F,0x53,0x11,0x88,0x23,0x99,0x7B,0x9D,0xD8,0x69,0x1A,0x22,0xAE,0xB5,0x18, + 0xA5,0x9F,0xEA,0x71,0x31,0x0B,0x27,0x93,0x85,0x1D,0xF7,0xA0,0xC3,0x82,0x0A,0x3F, + 0xEE,0xD2,0xD4,0xEF,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xB3,0x30,0x81,0xB0,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xA8,0xCA,0x7A,0x9B,0xA8,0x37, + 0x71,0x9E,0x3D,0xEC,0x5A,0xAB,0x66,0x2E,0xDC,0xD7,0x14,0x3D,0x7B,0xF2,0x30,0x0F, + 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30, + 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x59,0xB8,0x2B,0x94, + 0x3A,0x1B,0xBA,0xF1,0x00,0xAE,0xEE,0x50,0x52,0x23,0x33,0xC9,0x59,0xC3,0x54,0x98, + 0x30,0x3B,0x06,0x03,0x55,0x1D,0x1F,0x04,0x34,0x30,0x32,0x30,0x30,0xA0,0x2E,0xA0, + 0x2C,0x86,0x2A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61, + 0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x2F,0x74,0x65,0x73,0x74,0x72,0x6F,0x6F,0x74,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x10,0x06, + 0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x02,0x0C,0x04,0x02,0x05,0x00,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x11,0x24,0x61,0x2B,0x7C,0x5E,0x67,0x29,0x94,0x14,0x19,0x16,0xD5, + 0xD4,0x7A,0xEE,0x53,0x1A,0x64,0xA2,0x6A,0x2B,0x04,0xE6,0x2C,0xA1,0x08,0xBA,0xCA, + 0x81,0xF5,0x28,0x2A,0xCE,0xD5,0x6B,0x52,0xAC,0xE7,0xBD,0xB3,0x23,0xB9,0x67,0x2C, + 0xC7,0x9E,0x61,0xA1,0xD9,0x6C,0x3F,0x4F,0x55,0xD4,0x75,0xAF,0x44,0xAD,0xF8,0xCE, + 0x58,0xA7,0x2E,0xF8,0x6A,0xF0,0x76,0x51,0x31,0x75,0x4C,0xCA,0xF6,0xC3,0x59,0xC7, + 0xE6,0xAE,0x4A,0x20,0x4E,0x5F,0xB9,0xAB,0x1C,0xB6,0x36,0x25,0x60,0x02,0x32,0x47, + 0x7D,0xA0,0xE2,0x36,0xB3,0x3B,0x40,0x20,0x9E,0x38,0x40,0x1C,0x7E,0x83,0x35,0x9C, + 0x9D,0x8B,0xD1,0xF9,0xEA,0xD4,0xF2,0x83,0xE0,0x30,0xEA,0xC3,0xEE,0x3D,0x76,0x98, + 0x9E,0x0A,0x07,0xB5,0xB6,0xFC,0x38,0x32,0xF6,0x41,0xEF,0x8E,0x25,0x2C,0xE3,0xC7, + 0xA7,0xAD,0x88,0x77,0x4D,0x10,0x1D,0x67,0x50,0x64,0xB0,0x02,0x04,0x2C,0xEA,0x4C, + 0x81,0x33,0xBE,0xF3,0xCD,0x43,0x63,0x97,0x44,0xDF,0xBB,0xC6,0xE2,0x37,0x32,0xF1, + 0xE4,0x19,0x1F,0xF5,0xAE,0xDA,0x05,0xC4,0x0B,0xFA,0x30,0xCA,0x77,0x78,0x65,0xD6, + 0x4F,0x2D,0xFE,0x63,0xD3,0x4C,0x3D,0xA9,0x0E,0xC4,0x0F,0xD6,0xCC,0x2A,0x2D,0x06, + 0x9B,0xDE,0x94,0xF6,0x22,0x2E,0x89,0xCB,0x68,0x4E,0xDE,0x79,0xE5,0x83,0xDE,0x64, + 0x63,0xE9,0x77,0x88,0xF1,0x57,0xF2,0x5C,0xB4,0x77,0x3A,0xC8,0x1F,0x6D,0x80,0x4C, + 0x8B,0x68,0xA5,0xFA,0xAD,0x1F,0x5C,0x8C,0x50,0x27,0xED,0xF7,0x43,0x68,0xAD,0x34, + 0x5E,0xF6,0x74, +}; + +/* subject:/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Test Apple Root CA */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Test Apple Root CA */ +uint8_t _TestAppleRootCA[]={ + 0x30,0x82,0x04,0xCC,0x30,0x82,0x03,0xB4,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x3D, + 0x00,0x4B,0x90,0x3E,0xDE,0xE0,0xD0,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x67,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x54,0x65,0x73, + 0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30, + 0x1E,0x17,0x0D,0x31,0x35,0x30,0x34,0x32,0x32,0x30,0x32,0x31,0x35,0x34,0x38,0x5A, + 0x17,0x0D,0x33,0x35,0x30,0x32,0x30,0x39,0x32,0x31,0x34,0x30,0x33,0x36,0x5A,0x30, + 0x67,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x1B,0x30,0x19,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x12,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00, + 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC7,0xD1,0x43,0x53,0x7F,0x0D,0x88, + 0x6B,0xE6,0xB1,0x67,0x9D,0xEE,0x67,0xB6,0xE7,0x77,0x12,0x81,0xC4,0xDF,0x24,0x6B, + 0x7A,0x75,0x24,0xF7,0x01,0x09,0xCE,0x34,0x92,0xF5,0x38,0x08,0x42,0x7E,0xEC,0x9D, + 0xF2,0x5D,0x38,0x91,0xB4,0x93,0x98,0x35,0x11,0x3C,0x98,0x00,0x77,0xD9,0xD7,0xF3, + 0x4A,0xF8,0xF0,0xBC,0xEB,0x97,0x5D,0x4B,0x61,0x2E,0xFB,0xC5,0xCC,0x68,0xB7,0x6D, + 0x69,0x10,0xCC,0xA5,0x61,0x78,0xA8,0x81,0x02,0x9E,0xE7,0x63,0xC5,0xFF,0x29,0x22, + 0x82,0x68,0xAA,0xAA,0x0E,0xFB,0xA9,0xD8,0x16,0x73,0x25,0xBF,0x9D,0x08,0x62,0x2F, + 0x78,0x04,0xF6,0xF6,0x44,0x07,0x37,0x6E,0x99,0x1B,0x93,0xD8,0x7F,0xEE,0x72,0xDE, + 0xE8,0x32,0xF6,0x6D,0x78,0x04,0xA0,0xA8,0x21,0x26,0x8A,0x32,0xE3,0xB1,0x65,0x85, + 0xA1,0x7B,0x1A,0xA9,0x02,0xB2,0xBB,0xEE,0xDD,0xDD,0x8F,0x41,0x49,0xC8,0x3F,0xDC, + 0x1E,0xDF,0x21,0xA3,0x95,0x99,0xBB,0xFC,0x29,0xBA,0x40,0x43,0xB9,0x1C,0xCD,0xC9, + 0x21,0x45,0x73,0xAD,0xFF,0xFD,0xA2,0x6C,0x5C,0x3B,0x1C,0x37,0x91,0x34,0x8E,0x5C, + 0xD3,0xD5,0x03,0x58,0x28,0xC7,0xF2,0x76,0x6F,0x11,0xC0,0xB5,0xBD,0x7E,0xEF,0x23, + 0xB3,0x3D,0xB8,0xBD,0x38,0x66,0x8C,0xF2,0x78,0x95,0xC1,0x8B,0x32,0x65,0x3A,0x9B, + 0x49,0x1A,0x5C,0x41,0x3C,0xC6,0x85,0x50,0xEC,0x85,0xF0,0x59,0x17,0x81,0xE8,0x96, + 0xE8,0x6A,0xCC,0xB3,0xC7,0x46,0xBF,0x81,0x48,0xD1,0x09,0x1B,0xBC,0x73,0x1E,0xD7, + 0xE8,0x27,0xA8,0x49,0x48,0xA2,0x1C,0x41,0x1D,0x02,0x03,0x01,0x00,0x01,0xA3,0x82, + 0x01,0x7A,0x30,0x82,0x01,0x76,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0x59,0xB8,0x2B,0x94,0x3A,0x1B,0xBA,0xF1,0x00,0xAE,0xEE,0x50,0x52,0x23,0x33, + 0xC9,0x59,0xC3,0x54,0x98,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, + 0x16,0x80,0x14,0x59,0xB8,0x2B,0x94,0x3A,0x1B,0xBA,0xF1,0x00,0xAE,0xEE,0x50,0x52, + 0x23,0x33,0xC9,0x59,0xC3,0x54,0x98,0x30,0x82,0x01,0x11,0x06,0x03,0x55,0x1D,0x20, + 0x04,0x82,0x01,0x08,0x30,0x82,0x01,0x04,0x30,0x82,0x01,0x00,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF2,0x30,0x2A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F, + 0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70, + 0x70,0x6C,0x65,0x63,0x61,0x2F,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05, + 0x07,0x02,0x02,0x30,0x81,0xB6,0x0C,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63, + 0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72, + 0x74,0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70, + 0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65, + 0x6E,0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61, + 0x6E,0x64,0x61,0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20, + 0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73, + 0x65,0x2C,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70, + 0x6F,0x6C,0x69,0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65, + 0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x0E,0x06,0x03, + 0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00, + 0x10,0x5E,0x6C,0x69,0xFC,0xA6,0x0F,0xE2,0x09,0xD5,0x94,0x90,0xA6,0x7C,0x22,0xDC, + 0xEE,0xB0,0x8F,0x24,0x22,0x4F,0xB3,0x67,0xDB,0x32,0xB0,0xD6,0x24,0x87,0xE6,0xF3, + 0xEA,0x9E,0xD0,0x95,0x75,0xAA,0xA7,0x08,0xFF,0xB0,0x35,0xD7,0x1F,0xA3,0xBF,0x89, + 0x55,0x0C,0x1C,0xA4,0xD0,0xF8,0x00,0x17,0x44,0x94,0x36,0x63,0x3B,0x83,0xFE,0x4E, + 0xE5,0xB3,0xEC,0x7B,0x7D,0xCE,0xFE,0xA9,0x54,0xED,0xBB,0x12,0xA6,0x72,0x2B,0xB3, + 0x48,0x00,0xC7,0x8E,0xF5,0x5B,0x68,0xC9,0x24,0x22,0x7F,0xA1,0x4D,0xFC,0x54,0xD9, + 0xD0,0x5D,0x82,0x53,0x71,0x29,0x66,0xCF,0x0F,0x6D,0x32,0xA6,0x3F,0xAE,0x54,0x27, + 0xC2,0x8C,0x12,0x4C,0xF0,0xD6,0xC1,0x80,0x75,0xC3,0x33,0x19,0xD1,0x8B,0x58,0xE6, + 0x00,0x69,0x76,0xE7,0xE5,0x3D,0x47,0xF9,0xC0,0x9C,0xE7,0x19,0x1E,0x95,0xBC,0x52, + 0x15,0xCE,0x94,0xF8,0x30,0x14,0x0B,0x39,0x0E,0x8B,0xAF,0x29,0x30,0x56,0xAF,0x5A, + 0x28,0xAC,0xE1,0x0F,0x51,0x76,0x76,0x9A,0xE7,0xB9,0x7D,0xA3,0x30,0xE8,0xE3,0x71, + 0x15,0xE8,0xBF,0x0D,0x4F,0x12,0x9B,0x65,0xAB,0xEF,0xA4,0xE9,0x42,0xF0,0xD2,0x4D, + 0x20,0x55,0x29,0x88,0x58,0x5C,0x82,0x67,0x63,0x20,0x50,0xC6,0xCA,0x04,0xE8,0xBC, + 0x3D,0x93,0x06,0x21,0xB2,0xC0,0xBF,0x53,0x1E,0xE1,0x8B,0x48,0xA9,0xB9,0xD7,0xE6, + 0x5F,0x4E,0x5A,0x2F,0x43,0xAC,0x35,0xBD,0x26,0x60,0x2F,0x01,0xD5,0x86,0x6B,0x64, + 0xFA,0x67,0x05,0x44,0x55,0x83,0x5B,0x93,0x9C,0x7C,0xA7,0x26,0x4E,0x02,0x2B,0x48, +}; + +// Escrow Service Key F98EB04C6AA62F4022709406305387C61415DDD770A24039C1415F24BF918803 +const uint8_t kEscrowLeafCert[] = { + 0x30, 0x82, 0x04, 0x07, 0x30, 0x82, 0x02, 0xef, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x00, + 0x9b, 0x6e, 0xef, 0x8d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, 0x05, 0x00, 0x30, 0x79, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x03, + 0x31, 0x30, 0x30, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x45, 0x73, 0x63, 0x72, 0x6f, 0x77, 0x20, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x33, 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x38, 0x5a, 0x17, + 0x0d, 0x31, 0x35, 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x38, 0x5a, 0x30, 0x81, + 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x43, 0x41, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x03, 0x45, 0x54, 0x53, 0x31, 0x5c, + 0x30, 0x5a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x53, 0x45, 0x73, 0x63, 0x72, 0x6f, 0x77, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x39, 0x42, 0x36, 0x45, + 0x45, 0x46, 0x38, 0x44, 0x37, 0x42, 0x33, 0x43, 0x34, 0x39, 0x31, 0x32, 0x46, 0x35, 0x35, 0x35, + 0x32, 0x32, 0x32, 0x32, 0x42, 0x42, 0x34, 0x31, 0x44, 0x38, 0x34, 0x43, 0x43, 0x31, 0x39, 0x43, + 0x33, 0x35, 0x37, 0x37, 0x32, 0x35, 0x41, 0x36, 0x43, 0x35, 0x46, 0x34, 0x45, 0x35, 0x43, 0x43, + 0x36, 0x30, 0x37, 0x41, 0x32, 0x44, 0x37, 0x32, 0x31, 0x35, 0x41, 0x43, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc5, 0xc7, 0x51, + 0xf1, 0x3f, 0x9a, 0x5d, 0xd7, 0xc1, 0x03, 0x42, 0x30, 0x84, 0xdb, 0xbc, 0x6c, 0x00, 0x6c, 0xcc, + 0x57, 0x97, 0xaf, 0xfe, 0x9e, 0xa0, 0x06, 0x9f, 0xe8, 0xa9, 0x59, 0xe1, 0xf8, 0xed, 0x23, 0x05, + 0x57, 0xe3, 0xd8, 0xdf, 0xf8, 0x31, 0x80, 0x8b, 0x31, 0x08, 0x2a, 0xc3, 0x7b, 0x16, 0xba, 0x27, + 0x84, 0x4e, 0xbb, 0x55, 0x5b, 0xd2, 0xda, 0x2d, 0xea, 0xda, 0x5c, 0xf0, 0x21, 0x58, 0x63, 0x74, + 0xa9, 0x90, 0x99, 0xbe, 0x87, 0x19, 0x7d, 0x87, 0xfc, 0xcb, 0xb6, 0xc9, 0x39, 0x51, 0x6a, 0xa7, + 0x81, 0x05, 0x50, 0x2d, 0xa2, 0x10, 0x6d, 0x58, 0xa5, 0x62, 0x29, 0x53, 0xce, 0xa6, 0x53, 0xad, + 0x3f, 0x50, 0xda, 0x1a, 0x1e, 0x2c, 0xe3, 0xae, 0x24, 0x88, 0xa5, 0x4c, 0xa3, 0x3a, 0xe1, 0xc6, + 0xa9, 0xcf, 0xb5, 0x53, 0x30, 0xbf, 0x7b, 0xea, 0x77, 0x21, 0x24, 0xfd, 0x91, 0x4c, 0x6f, 0x60, + 0x9f, 0x78, 0xf9, 0xed, 0x84, 0xe5, 0xee, 0xab, 0x07, 0xc5, 0x34, 0xa9, 0xe2, 0x0a, 0xf5, 0xf5, + 0xfa, 0x66, 0x75, 0xc8, 0x3e, 0x9c, 0xdd, 0xea, 0x60, 0xf0, 0x83, 0x03, 0x19, 0x08, 0xa4, 0x85, + 0xb0, 0xf3, 0xb1, 0xf1, 0x7a, 0x3d, 0xb4, 0xc8, 0xdd, 0x25, 0x5a, 0x1b, 0xf5, 0xa0, 0x78, 0xf9, + 0xbb, 0x08, 0x27, 0x6f, 0xa9, 0xf9, 0x17, 0xe8, 0xcb, 0x01, 0xa3, 0x5a, 0xd0, 0x67, 0xfb, 0xb7, + 0xef, 0xb7, 0x5c, 0x20, 0x94, 0x17, 0x5d, 0x46, 0xbd, 0xd2, 0xfe, 0xb6, 0x68, 0x88, 0x9f, 0xa6, + 0x0b, 0x97, 0x0f, 0x2e, 0x10, 0x23, 0x52, 0x9e, 0x69, 0x8b, 0xf4, 0x80, 0x83, 0x0e, 0x5b, 0x04, + 0xfc, 0x4e, 0xa1, 0x32, 0x44, 0x8a, 0x63, 0x3e, 0x3b, 0x0b, 0x70, 0x15, 0xd4, 0x17, 0xc1, 0xbe, + 0xbb, 0x01, 0x37, 0xe8, 0xfb, 0x58, 0x8b, 0x3d, 0xec, 0xc4, 0x47, 0x82, 0xe5, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x73, 0x30, 0x71, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, + 0x03, 0x02, 0x05, 0x20, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, + 0x34, 0x54, 0x7b, 0x16, 0x2a, 0x38, 0x22, 0xd5, 0x79, 0x7b, 0xbf, 0x5c, 0x62, 0x16, 0x59, 0xc5, + 0x53, 0x9f, 0xac, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0xfd, 0x78, 0x96, 0x53, 0x80, 0xd6, 0xf6, 0xdc, 0xa6, 0xc3, 0x59, 0x06, 0x38, 0xed, 0x79, 0x3e, + 0x8f, 0x50, 0x1b, 0x50, 0x30, 0x11, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, + 0x17, 0x01, 0x04, 0x03, 0x02, 0x01, 0x0a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x41, 0x68, 0xd9, 0xd5, + 0xb5, 0xbe, 0x2d, 0xa1, 0xe7, 0x52, 0x28, 0x2c, 0x4f, 0xe7, 0x43, 0x39, 0x4d, 0x1f, 0xeb, 0x09, + 0xd9, 0xc7, 0xca, 0x6f, 0x63, 0x60, 0x7f, 0x7c, 0xb5, 0x7c, 0x5e, 0x4b, 0xab, 0xd5, 0x8b, 0x34, + 0x5b, 0x50, 0xda, 0x3e, 0x37, 0xa8, 0x26, 0xf5, 0xdb, 0x76, 0xc4, 0x4a, 0x48, 0x09, 0xcf, 0x04, + 0x0a, 0x17, 0x6c, 0x8d, 0x3c, 0x6e, 0x1e, 0x41, 0xfc, 0xef, 0x45, 0xbd, 0x72, 0x59, 0x5e, 0x10, + 0x61, 0x4e, 0xad, 0x0e, 0xe4, 0x76, 0x3c, 0xf7, 0x87, 0xef, 0x54, 0xdd, 0x61, 0xe9, 0x91, 0x0f, + 0x7e, 0x52, 0xd6, 0x9e, 0x02, 0xd7, 0xb6, 0xcc, 0xa4, 0x9e, 0x7d, 0xba, 0x5f, 0xb4, 0x40, 0xc9, + 0xe6, 0x95, 0x61, 0xae, 0xb9, 0x89, 0xba, 0x25, 0x1b, 0xb6, 0xde, 0x08, 0x7f, 0x88, 0xef, 0x7c, + 0x59, 0x4d, 0x73, 0xc7, 0xf5, 0x07, 0x94, 0x13, 0x7b, 0xfc, 0x9f, 0x75, 0x0d, 0x1a, 0x69, 0xf0, + 0x51, 0x36, 0x1e, 0x46, 0x76, 0xc8, 0x27, 0x4e, 0x65, 0x58, 0x66, 0x41, 0x5e, 0x9d, 0xfe, 0xf1, + 0x10, 0xd5, 0x3c, 0x5b, 0xea, 0xcd, 0x96, 0x37, 0x4d, 0x76, 0x88, 0x60, 0xfb, 0x3f, 0xb2, 0x7a, + 0x00, 0xb4, 0xe0, 0xb6, 0xb9, 0x76, 0x6e, 0x02, 0xb6, 0xf7, 0x8d, 0x8b, 0x3a, 0x5c, 0xde, 0x4e, + 0xb9, 0xa4, 0x05, 0xc6, 0x14, 0xa6, 0x3f, 0x6c, 0xbd, 0xfd, 0xee, 0x0b, 0xf5, 0x5c, 0x27, 0x56, + 0xc5, 0x48, 0x55, 0x78, 0x72, 0xdc, 0xca, 0x95, 0xb7, 0x02, 0xb2, 0xdc, 0x4e, 0xbd, 0xe2, 0x78, + 0x87, 0xcc, 0xb5, 0xb0, 0x7c, 0x22, 0x52, 0xc1, 0xb0, 0x5a, 0x09, 0x9d, 0xb6, 0xbe, 0xe7, 0x4b, + 0xa2, 0x0e, 0x20, 0x43, 0x28, 0x77, 0x88, 0x1f, 0xd6, 0xa4, 0xb9, 0x56, 0xd0, 0xd0, 0xa6, 0x0f, + 0xa3, 0xef, 0x2e, 0xb7, 0x1d, 0x40, 0x61, 0xf8, 0xb9, 0x17, 0x4c, +}; + +const uint8_t kPCSEscrowLeafCert[] = { + 0x30,0x82,0x04,0x0E,0x30,0x82,0x02,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x5B, + 0x57,0x9E,0xA2,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, + 0x05,0x00,0x30,0x7D,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31, + 0x30,0x30,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x23,0x30,0x21, + 0x06,0x03,0x55,0x04,0x03,0x13,0x1A,0x45,0x66,0x66,0x61,0x63,0x65,0x61,0x62,0x6C, + 0x65,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, + 0x41,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x37,0x32,0x39,0x30,0x30,0x31,0x31,0x34, + 0x33,0x5A,0x17,0x0D,0x31,0x36,0x30,0x37,0x32,0x39,0x30,0x30,0x31,0x31,0x34,0x33, + 0x5A,0x30,0x81,0x9F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x43,0x41,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x0B,0x13,0x03,0x45,0x54, + 0x53,0x31,0x60,0x30,0x5E,0x06,0x03,0x55,0x04,0x03,0x13,0x57,0x45,0x66,0x66,0x61, + 0x63,0x65,0x61,0x62,0x6C,0x65,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x20,0x4B, + 0x65,0x79,0x20,0x35,0x42,0x35,0x37,0x39,0x45,0x41,0x32,0x36,0x34,0x41,0x39,0x36, + 0x36,0x39,0x37,0x42,0x41,0x38,0x31,0x33,0x34,0x35,0x34,0x44,0x32,0x45,0x38,0x43, + 0x46,0x37,0x44,0x42,0x31,0x34,0x30,0x33,0x37,0x43,0x30,0x43,0x45,0x44,0x32,0x34, + 0x33,0x43,0x42,0x37,0x46,0x45,0x33,0x31,0x33,0x38,0x33,0x42,0x34,0x35,0x38,0x34, + 0x33,0x30,0x42,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, + 0x82,0x01,0x01,0x00,0xAD,0xAD,0x92,0x86,0x08,0xFF,0x27,0xF1,0xCC,0xB6,0x57,0x41, + 0xC9,0x1F,0x05,0xC2,0xC7,0xC5,0xFB,0x8C,0xE3,0xEE,0xBC,0xE0,0x07,0xA4,0x58,0xE0, + 0x9E,0x81,0x19,0xF9,0x81,0xDF,0xD6,0x1B,0x65,0x23,0x0E,0xAC,0x2A,0xB6,0x3F,0x32, + 0x66,0xBF,0x9E,0xF4,0x0D,0xEA,0xE8,0xE9,0x5E,0xCF,0xB6,0x84,0x61,0x03,0x26,0x92, + 0xC5,0xAC,0xB2,0x54,0xE0,0x5B,0x22,0x88,0xFB,0x9B,0x6F,0xEF,0xFE,0xC1,0x40,0x27, + 0xF3,0x35,0xF2,0xC4,0x4C,0xB1,0xB4,0x57,0x2D,0xE7,0xF0,0x26,0xC0,0xE8,0x5F,0x02, + 0x13,0x33,0x53,0x5F,0xC8,0x5B,0x6B,0x14,0x5B,0x37,0x2F,0x24,0xD6,0x39,0x0C,0x7C, + 0x0D,0x8E,0x4A,0x73,0x33,0xAF,0xA1,0x78,0x6F,0xE0,0xD8,0x42,0x40,0x33,0x58,0x12, + 0x76,0xFF,0xF2,0x1E,0xAE,0x0B,0x80,0x3F,0x63,0x52,0xED,0xCA,0x33,0x3A,0x8B,0x19, + 0x37,0xFF,0xAC,0xFF,0x4D,0xBF,0xD1,0x9D,0x55,0xD1,0x2A,0x17,0x28,0x0E,0x6B,0xC8, + 0x12,0xBF,0x79,0x22,0x6B,0x8F,0x3C,0x3B,0x5C,0xC7,0x66,0xA8,0x9C,0x65,0x68,0xB4, + 0x4B,0x37,0xCE,0xC9,0x2A,0x7E,0x36,0x6A,0x7A,0x76,0x5D,0x47,0x26,0xDE,0x70,0xC8, + 0xE5,0x6B,0xA1,0xC5,0xC8,0xBC,0xCF,0xD2,0x78,0xAF,0xDE,0x9A,0xF4,0x49,0xC7,0xFC, + 0x78,0xF2,0x37,0xC1,0xD1,0x40,0xFA,0x30,0x4C,0x96,0xC2,0x16,0xEC,0xEB,0xE0,0x33, + 0x94,0xE1,0x83,0xE8,0xF9,0xD6,0x58,0xEE,0xEE,0x7D,0x49,0x38,0xC7,0xD6,0x15,0xE6, + 0x00,0x7F,0x40,0x37,0x03,0x3F,0xF3,0x5F,0x38,0x63,0x93,0x87,0xF1,0xE2,0xB7,0x8C, + 0xFF,0x21,0x68,0x7B,0x02,0x03,0x01,0x00,0x01,0xA3,0x73,0x30,0x71,0x30,0x0C,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0x20,0x30,0x1D,0x06,0x03,0x55, + 0x1D,0x0E,0x04,0x16,0x04,0x14,0x3F,0x94,0xA6,0xB9,0xB6,0xAE,0x43,0xDA,0x66,0xF3, + 0xD3,0x38,0xF0,0xD0,0x96,0x59,0x79,0x1B,0x0A,0xC1,0x30,0x1F,0x06,0x03,0x55,0x1D, + 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x64,0x0B,0xE4,0x72,0x73,0x5C,0x54,0xB2,0x58, + 0x59,0xAE,0x42,0xDF,0x2B,0xB7,0xBA,0xB9,0xEB,0x86,0xAE,0x30,0x11,0x06,0x0A,0x2A, + 0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x17,0x01,0x04,0x03,0x02,0x01,0x0A,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01, + 0x01,0x00,0x83,0x4B,0x3D,0x4E,0xE0,0x17,0xB5,0x95,0xAE,0x90,0xA4,0xE0,0x41,0x01, + 0x5B,0x1A,0x1D,0x69,0x83,0xA9,0xA0,0xD8,0x58,0xCD,0x57,0xB8,0x8B,0x1D,0x00,0xD2, + 0xB4,0x27,0x65,0x34,0x83,0xAD,0x5B,0xCF,0xA8,0x2F,0xFC,0x6C,0x08,0x1B,0x2B,0x12, + 0x93,0xE5,0x68,0xE3,0x85,0xFA,0x87,0x28,0x31,0x7E,0x18,0xA9,0xB9,0xEF,0xF4,0xE3, + 0x1C,0x24,0x83,0xE6,0x01,0xDA,0x56,0x49,0x52,0xA1,0xBC,0x56,0xE4,0xFC,0xA6,0xAF, + 0xC7,0x8D,0xD8,0x41,0xD3,0xA8,0x10,0x99,0x0F,0xEE,0x93,0xF1,0x58,0x4C,0x43,0x8B, + 0x31,0xF8,0xA8,0x04,0xFD,0x88,0x7E,0x0C,0x0C,0xA6,0xB9,0x3C,0xEC,0x9B,0xCD,0x99, + 0xF5,0x38,0x35,0x76,0x63,0xBC,0x23,0x9A,0x8F,0xA3,0x0B,0xE2,0x8E,0x55,0xEF,0x71, + 0xD8,0x87,0xA8,0x62,0x2B,0x35,0x32,0x24,0x6C,0xEE,0x95,0x5C,0x74,0xB2,0x1B,0x8F, + 0xEF,0x4C,0x45,0x03,0x0B,0x35,0x97,0x7D,0x43,0x7F,0x1D,0x3E,0xB9,0xE9,0x9D,0xF1, + 0x96,0x3B,0x91,0xA6,0xDF,0x52,0x00,0xB3,0xC5,0xDC,0xD3,0x29,0xAC,0x17,0xE1,0x73, + 0xA9,0x15,0x14,0xBD,0x1E,0x4F,0x9F,0x09,0xF8,0x84,0xF8,0xB6,0x9C,0xFD,0xCD,0x09, + 0x6D,0xDD,0x39,0xC7,0x15,0x58,0x86,0xE8,0x6B,0x47,0x4F,0x5D,0x84,0x29,0x56,0x81, + 0xF1,0x7C,0x09,0xA5,0x50,0x5C,0x4B,0xD9,0xFF,0xDF,0xA5,0xA9,0x6E,0xFF,0x14,0x9F, + 0xE4,0x4C,0xE7,0xAA,0x83,0xEA,0x30,0xB4,0x0D,0x8D,0xF7,0x36,0x4B,0x8D,0x38,0xDC, + 0xF5,0xA9,0xCF,0x3F,0x85,0x6A,0xC3,0x7A,0x53,0x86,0x18,0x5D,0x4B,0x93,0x1A,0x0E, + 0x50,0x5D, +}; + +static const unsigned char _USAirwaysCorrect_signature[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x80, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00, 0x00, + 0xa0, 0x82, 0x0a, 0x1c, 0x30, 0x82, 0x04, 0x23, 0x30, 0x82, 0x03, 0x0b, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x19, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, + 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, + 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x32, 0x31, + 0x34, 0x31, 0x38, 0x35, 0x36, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x36, + 0x30, 0x32, 0x31, 0x34, 0x31, 0x38, 0x35, 0x36, 0x33, 0x35, 0x5a, 0x30, + 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x23, 0x41, + 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, + 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, + 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x31, 0x44, + 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, 0x64, 0x65, + 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x20, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xca, 0x38, 0x54, 0xa6, 0xcb, 0x56, 0xaa, + 0xc8, 0x24, 0x39, 0x48, 0xe9, 0x8c, 0xee, 0xec, 0x5f, 0xb8, 0x7f, 0x26, + 0x91, 0xbc, 0x34, 0x53, 0x7a, 0xce, 0x7c, 0x63, 0x80, 0x61, 0x77, 0x64, + 0x5e, 0xa5, 0x07, 0x23, 0xb6, 0x39, 0xfe, 0x50, 0x2d, 0x15, 0x56, 0x58, + 0x70, 0x2d, 0x7e, 0xc4, 0x6e, 0xc1, 0x4a, 0x85, 0x3e, 0x2f, 0xf0, 0xde, + 0x84, 0x1a, 0xa1, 0x57, 0xc9, 0xaf, 0x7b, 0x18, 0xff, 0x6a, 0xfa, 0x15, + 0x12, 0x49, 0x15, 0x08, 0x19, 0xac, 0xaa, 0xdb, 0x2a, 0x32, 0xed, 0x96, + 0x63, 0x68, 0x52, 0x15, 0x3d, 0x8c, 0x8a, 0xec, 0xbf, 0x6b, 0x18, 0x95, + 0xe0, 0x03, 0xac, 0x01, 0x7d, 0x97, 0x05, 0x67, 0xce, 0x0e, 0x85, 0x95, + 0x37, 0x6a, 0xed, 0x09, 0xb6, 0xae, 0x67, 0xcd, 0x51, 0x64, 0x9f, 0xc6, + 0x5c, 0xd1, 0xbc, 0x57, 0x6e, 0x67, 0x35, 0x80, 0x76, 0x36, 0xa4, 0x87, + 0x81, 0x6e, 0x38, 0x8f, 0xd8, 0x2b, 0x15, 0x4e, 0x7b, 0x25, 0xd8, 0x5a, + 0xbf, 0x4e, 0x83, 0xc1, 0x8d, 0xd2, 0x93, 0xd5, 0x1a, 0x71, 0xb5, 0x60, + 0x9c, 0x9d, 0x33, 0x4e, 0x55, 0xf9, 0x12, 0x58, 0x0c, 0x86, 0xb8, 0x16, + 0x0d, 0xc1, 0xe5, 0x77, 0x45, 0x8d, 0x50, 0x48, 0xba, 0x2b, 0x2d, 0xe4, + 0x94, 0x85, 0xe1, 0xe8, 0xc4, 0x9d, 0xc6, 0x68, 0xa5, 0xb0, 0xa3, 0xfc, + 0x67, 0x7e, 0x70, 0xba, 0x02, 0x59, 0x4b, 0x77, 0x42, 0x91, 0x39, 0xb9, + 0xf5, 0xcd, 0xe1, 0x4c, 0xef, 0xc0, 0x3b, 0x48, 0x8c, 0xa6, 0xe5, 0x21, + 0x5d, 0xfd, 0x6a, 0x6a, 0xbb, 0xa7, 0x16, 0x35, 0x60, 0xd2, 0xe6, 0xad, + 0xf3, 0x46, 0x29, 0xc9, 0xe8, 0xc3, 0x8b, 0xe9, 0x79, 0xc0, 0x6a, 0x61, + 0x67, 0x15, 0xb2, 0xf0, 0xfd, 0xe5, 0x68, 0xbc, 0x62, 0x5f, 0x6e, 0xcf, + 0x99, 0xdd, 0xef, 0x1b, 0x63, 0xfe, 0x92, 0x65, 0xab, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x81, 0xae, 0x30, 0x81, 0xab, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, + 0x04, 0x16, 0x04, 0x14, 0x88, 0x27, 0x17, 0x09, 0xa9, 0xb6, 0x18, 0x60, + 0x8b, 0xec, 0xeb, 0xba, 0xf6, 0x47, 0x59, 0xc5, 0x52, 0x54, 0xa3, 0xb7, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0x2b, 0xd0, 0x69, 0x47, 0x94, 0x76, 0x09, 0xfe, 0xf4, 0x6b, 0x8d, + 0x2e, 0x40, 0xa6, 0xf7, 0x47, 0x4d, 0x7f, 0x08, 0x5e, 0x30, 0x36, 0x06, + 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, + 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x72, 0x6f, 0x6f, + 0x74, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x63, 0x64, 0x06, 0x02, 0x01, 0x04, 0x02, 0x05, 0x00, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xda, 0x32, 0x00, 0x96, 0xc5, + 0x54, 0x94, 0xd3, 0x3b, 0x82, 0x37, 0x66, 0x7d, 0x2e, 0x68, 0xd5, 0xc3, + 0xc6, 0xb8, 0xcb, 0x26, 0x8c, 0x48, 0x90, 0xcf, 0x13, 0x24, 0x6a, 0x46, + 0x8e, 0x63, 0xd4, 0xf0, 0xd0, 0x13, 0x06, 0xdd, 0xd8, 0xc4, 0xc1, 0x37, + 0x15, 0xf2, 0x33, 0x13, 0x39, 0x26, 0x2d, 0xce, 0x2e, 0x55, 0x40, 0xe3, + 0x0b, 0x03, 0xaf, 0xfa, 0x12, 0xc2, 0xe7, 0x0d, 0x21, 0xb8, 0xd5, 0x80, + 0xcf, 0xac, 0x28, 0x2f, 0xce, 0x2d, 0xb3, 0x4e, 0xaf, 0x86, 0x19, 0x04, + 0xc6, 0xe9, 0x50, 0xdd, 0x4c, 0x29, 0x47, 0x10, 0x23, 0xfc, 0x6c, 0xbb, + 0x1b, 0x98, 0x6b, 0x48, 0x89, 0xe1, 0x5b, 0x9d, 0xde, 0x46, 0xdb, 0x35, + 0x85, 0x35, 0xef, 0x3e, 0xd0, 0xe2, 0x58, 0x4b, 0x38, 0xf4, 0xed, 0x75, + 0x5a, 0x1f, 0x5c, 0x70, 0x1d, 0x56, 0x39, 0x12, 0xe5, 0xe1, 0x0d, 0x11, + 0xe4, 0x89, 0x25, 0x06, 0xbd, 0xd5, 0xb4, 0x15, 0x8e, 0x5e, 0xd0, 0x59, + 0x97, 0x90, 0xe9, 0x4b, 0x81, 0xe2, 0xdf, 0x18, 0xaf, 0x44, 0x74, 0x1e, + 0x19, 0xa0, 0x3a, 0x47, 0xcc, 0x91, 0x1d, 0x3a, 0xeb, 0x23, 0x5a, 0xfe, + 0xa5, 0x2d, 0x97, 0xf7, 0x7b, 0xbb, 0xd6, 0x87, 0x46, 0x42, 0x85, 0xeb, + 0x52, 0x3d, 0x26, 0xb2, 0x63, 0xa8, 0xb4, 0xb1, 0xca, 0x8f, 0xf4, 0xcc, + 0xe2, 0xb3, 0xc8, 0x47, 0xe0, 0xbf, 0x9a, 0x59, 0x83, 0xfa, 0xda, 0x98, + 0x53, 0x2a, 0x82, 0xf5, 0x7c, 0x65, 0x2e, 0x95, 0xd9, 0x33, 0x5d, 0xf5, + 0xed, 0x65, 0xcc, 0x31, 0x37, 0xc5, 0x5a, 0x04, 0xe8, 0x6b, 0xe1, 0xe7, + 0x88, 0x03, 0x4a, 0x75, 0x9e, 0x9b, 0x28, 0xcb, 0x4a, 0x40, 0x88, 0x65, + 0x43, 0x75, 0xdd, 0xcb, 0x3a, 0x25, 0x23, 0xc5, 0x9e, 0x57, 0xf8, 0x2e, + 0xce, 0xd2, 0xa9, 0x92, 0x5e, 0x73, 0x2e, 0x2f, 0x25, 0x75, 0x15, 0x30, + 0x82, 0x05, 0xf1, 0x30, 0x82, 0x04, 0xd9, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x08, 0x29, 0xd6, 0x12, 0x53, 0x17, 0x20, 0x2d, 0x6a, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x23, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, + 0x77, 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, 0x41, + 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, + 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, + 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x32, 0x30, 0x35, 0x33, 0x30, 0x32, 0x33, 0x32, 0x30, + 0x31, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x35, 0x33, 0x30, 0x32, + 0x33, 0x32, 0x30, 0x31, 0x30, 0x5a, 0x30, 0x81, 0x9b, 0x31, 0x26, 0x30, + 0x24, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, + 0x01, 0x0c, 0x16, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, + 0x6e, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x24, + 0x50, 0x61, 0x73, 0x73, 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, 0x49, 0x44, + 0x3a, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, 0x6e, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0a, 0x41, + 0x31, 0x42, 0x32, 0x43, 0x33, 0x44, 0x34, 0x45, 0x35, 0x31, 0x20, 0x30, + 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x17, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x55, + 0x73, 0x65, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xbb, 0x6c, 0x6c, 0xd4, 0xcd, 0x0b, 0xd9, + 0x47, 0x49, 0xe1, 0xa3, 0xfe, 0x73, 0xe0, 0x15, 0xa6, 0x2e, 0x35, 0xc8, + 0xb7, 0xcd, 0xab, 0x5e, 0xd3, 0x87, 0x8a, 0x94, 0x8f, 0x4d, 0x94, 0x52, + 0x72, 0x27, 0x57, 0xb8, 0xf5, 0xa8, 0xe2, 0xf2, 0xb0, 0x46, 0xad, 0xb9, + 0x30, 0x9b, 0x6a, 0xd7, 0x0a, 0xff, 0x0e, 0x5e, 0x78, 0x4c, 0x97, 0x17, + 0x16, 0xa7, 0x03, 0xe1, 0x13, 0xe7, 0x97, 0x72, 0x24, 0xc8, 0x7f, 0x80, + 0x91, 0xd2, 0x45, 0xa3, 0xf8, 0x21, 0xce, 0x2d, 0xfa, 0xe4, 0x3a, 0x5e, + 0x04, 0x30, 0xe9, 0x48, 0xca, 0x32, 0xce, 0x52, 0x4c, 0xcf, 0x14, 0xf9, + 0x04, 0x58, 0x30, 0x4a, 0xf8, 0x49, 0xbb, 0x39, 0x18, 0x5c, 0x4b, 0x28, + 0x9e, 0x14, 0x16, 0x23, 0x73, 0x6e, 0x0d, 0xcd, 0xcd, 0xef, 0x98, 0xe7, + 0x90, 0x04, 0x0e, 0x4a, 0xc8, 0x16, 0x22, 0x76, 0x68, 0xc6, 0xdf, 0x5d, + 0x20, 0xa7, 0x49, 0x2e, 0x55, 0x9e, 0x50, 0x31, 0x56, 0x50, 0x29, 0xf9, + 0x56, 0x09, 0x38, 0x32, 0x25, 0x1b, 0x3a, 0x1c, 0x97, 0x3e, 0x04, 0xee, + 0x69, 0x3c, 0x68, 0x44, 0x54, 0x51, 0x27, 0x75, 0x70, 0xa2, 0x33, 0x86, + 0x7a, 0x9d, 0x71, 0xc0, 0x18, 0x2e, 0x37, 0xb5, 0x47, 0x8d, 0xbe, 0x57, + 0xb6, 0xaa, 0xda, 0x1d, 0xe8, 0x78, 0x23, 0x66, 0xc8, 0x6c, 0xe3, 0x7e, + 0xfd, 0xde, 0x6b, 0x70, 0x2f, 0x76, 0x1d, 0xa6, 0x2b, 0x97, 0xee, 0xad, + 0x5b, 0x8b, 0x8e, 0x00, 0x87, 0x27, 0xdf, 0x16, 0x54, 0x08, 0x97, 0x18, + 0x23, 0x31, 0x2c, 0xf5, 0x9d, 0x41, 0xd5, 0xbb, 0x60, 0x23, 0x92, 0x3d, + 0xcc, 0x9e, 0x2d, 0xff, 0xa5, 0x8b, 0xe0, 0xf9, 0x65, 0xdc, 0x94, 0x58, + 0xb0, 0x9d, 0x73, 0x05, 0x05, 0x21, 0xa1, 0xb3, 0x37, 0xa4, 0x8f, 0x5d, + 0xda, 0xce, 0x9c, 0xf6, 0x63, 0x9b, 0x6b, 0x9f, 0x77, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3a, 0x30, 0x82, 0x02, 0x36, 0x30, 0x3d, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x31, + 0x30, 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, + 0x63, 0x73, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2d, 0x77, 0x77, 0x64, 0x72, 0x30, + 0x33, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0x9b, 0xc2, 0x61, 0x59, 0x72, 0x23, 0xb6, 0x5f, 0x91, 0x0f, 0x04, 0x87, + 0x92, 0xf9, 0xa4, 0xf3, 0x6b, 0xe9, 0xbe, 0xab, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x88, 0x27, 0x17, 0x09, + 0xa9, 0xb6, 0x18, 0x60, 0x8b, 0xec, 0xeb, 0xba, 0xf6, 0x47, 0x59, 0xc5, + 0x52, 0x54, 0xa3, 0xb7, 0x30, 0x82, 0x01, 0x0f, 0x06, 0x03, 0x55, 0x1d, + 0x20, 0x04, 0x82, 0x01, 0x06, 0x30, 0x82, 0x01, 0x02, 0x30, 0x81, 0xff, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, + 0x81, 0xf1, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x30, 0x81, 0xc3, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x81, + 0xb6, 0x0c, 0x81, 0xb3, 0x52, 0x65, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, + 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x62, 0x79, 0x20, + 0x61, 0x6e, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x79, 0x20, 0x61, 0x73, + 0x73, 0x75, 0x6d, 0x65, 0x73, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x74, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x62, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, + 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, + 0x69, 0x63, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x29, + 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x61, 0x70, 0x70, + 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x77, 0x64, 0x72, 0x63, + 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x1d, + 0x25, 0x04, 0x17, 0x30, 0x15, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, + 0x04, 0x0e, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, + 0x64, 0x06, 0x03, 0x02, 0x04, 0x02, 0x05, 0x00, 0x30, 0x26, 0x06, 0x0a, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, 0x01, 0x10, 0x04, 0x18, + 0x0c, 0x16, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, 0x6e, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x9b, 0xef, 0x1e, 0xff, + 0xee, 0xd5, 0xfd, 0x71, 0x1a, 0xf5, 0x17, 0xfe, 0x05, 0xba, 0x30, 0xfc, + 0xbd, 0x6d, 0x01, 0xb0, 0x0b, 0x78, 0x41, 0x4b, 0x76, 0x71, 0xd1, 0x8c, + 0xf0, 0xcd, 0xed, 0xd9, 0xaa, 0xec, 0xad, 0x1d, 0x4a, 0x2d, 0xcc, 0x00, + 0x11, 0x5b, 0x1d, 0xd9, 0xef, 0x08, 0xa2, 0x3d, 0xea, 0xe9, 0xbd, 0x35, + 0x0b, 0x1c, 0x9f, 0xe7, 0xeb, 0xc9, 0xc9, 0xea, 0x99, 0xcc, 0x77, 0x27, + 0xb9, 0x01, 0x09, 0x72, 0x40, 0xba, 0xd4, 0x26, 0x54, 0x8f, 0x30, 0x84, + 0x7e, 0x03, 0x65, 0xda, 0x08, 0xb2, 0x92, 0xee, 0x61, 0x4e, 0x5f, 0x00, + 0x39, 0x48, 0x2d, 0x99, 0x83, 0xb5, 0xc4, 0x33, 0xb2, 0xf7, 0x62, 0xcf, + 0x6a, 0xbf, 0xbb, 0xb8, 0x40, 0x70, 0xbf, 0x11, 0xff, 0x7f, 0xc1, 0xc1, + 0x8d, 0x1d, 0x67, 0x6c, 0x87, 0x02, 0xe2, 0x93, 0x17, 0x16, 0xc3, 0xec, + 0x5e, 0x97, 0xe4, 0xdd, 0x12, 0xcc, 0xb2, 0xdd, 0x91, 0x51, 0xa8, 0x32, + 0x25, 0x6d, 0xf7, 0x55, 0xb7, 0x4a, 0x8e, 0x6b, 0x90, 0xcb, 0x0f, 0x4c, + 0x93, 0x87, 0x2a, 0xd9, 0x31, 0xb8, 0x1a, 0x16, 0x12, 0xbb, 0x6e, 0xfc, + 0xb0, 0xae, 0xfb, 0x93, 0x76, 0x63, 0x37, 0xb7, 0x36, 0x13, 0x11, 0xc5, + 0x53, 0x45, 0xe0, 0x0d, 0xff, 0xaf, 0x05, 0x5f, 0x67, 0x51, 0xe1, 0x54, + 0x29, 0xa2, 0x1a, 0x7c, 0x61, 0xe0, 0xc2, 0xcd, 0xac, 0xbe, 0xee, 0xa6, + 0x4a, 0xdc, 0x92, 0x95, 0x48, 0x41, 0x2f, 0x37, 0xc0, 0x64, 0x05, 0xaa, + 0x4f, 0x05, 0xee, 0xe0, 0x3f, 0xa0, 0x9f, 0x43, 0x6c, 0xcc, 0xd5, 0x97, + 0x64, 0x6d, 0x15, 0x5b, 0xb6, 0xcd, 0x2a, 0xbc, 0x18, 0xde, 0xc7, 0x94, + 0x80, 0x2d, 0x2b, 0x81, 0x14, 0xfc, 0x48, 0xf7, 0xdf, 0xce, 0x94, 0xb3, + 0xfd, 0xf5, 0x7e, 0x42, 0x4d, 0x33, 0x58, 0x4d, 0x7a, 0x62, 0x2e, 0x61, + 0x31, 0x82, 0x02, 0x2a, 0x30, 0x82, 0x02, 0x26, 0x02, 0x01, 0x01, 0x30, + 0x81, 0xa3, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x23, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, + 0x64, 0x77, 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, + 0x70, 0x65, 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, + 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, + 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x02, + 0x08, 0x29, 0xd6, 0x12, 0x53, 0x17, 0x20, 0x2d, 0x6a, 0x30, 0x09, 0x06, + 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0xa0, 0x5d, 0x30, 0x18, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, + 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, + 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37, 0x32, + 0x31, 0x32, 0x31, 0x35, 0x30, 0x5a, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0x97, + 0xab, 0x93, 0x47, 0x94, 0xc1, 0xdf, 0x9b, 0xf4, 0x8e, 0xf9, 0xec, 0x96, + 0x77, 0xf9, 0x35, 0x15, 0xe1, 0x75, 0x58, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x01, 0x00, 0x33, 0xdd, 0xcb, 0xf1, 0xa1, 0x74, 0xc2, 0xad, 0x44, 0xcd, + 0x49, 0x95, 0xad, 0xd4, 0xd5, 0xaf, 0x37, 0x98, 0x5e, 0x1b, 0x0e, 0xf7, + 0x49, 0xc5, 0x3a, 0x01, 0x99, 0x7e, 0xc2, 0x3b, 0x4f, 0x37, 0xd0, 0x8e, + 0x31, 0x7f, 0xcd, 0x7d, 0x9f, 0xfd, 0xb9, 0x6a, 0x8e, 0x43, 0xcf, 0xc0, + 0x94, 0xda, 0x2b, 0x1b, 0x98, 0x28, 0x0a, 0x34, 0x39, 0x1c, 0x3d, 0xf1, + 0x86, 0xad, 0x02, 0x7e, 0xdb, 0x02, 0x9b, 0xfc, 0x4a, 0x2e, 0x10, 0x82, + 0x50, 0xfe, 0x61, 0x18, 0xc4, 0x6f, 0x45, 0x30, 0x66, 0x7a, 0x44, 0x70, + 0x0d, 0x4c, 0x47, 0x04, 0xb4, 0x09, 0x02, 0x12, 0xa8, 0x61, 0x3c, 0xf7, + 0x24, 0x7c, 0xb3, 0xa8, 0x5b, 0xde, 0xe4, 0xa4, 0x5d, 0x98, 0x9e, 0x72, + 0x0a, 0xea, 0x36, 0x5c, 0xfa, 0xe1, 0x80, 0xd6, 0x93, 0xa2, 0xbc, 0x09, + 0x9c, 0xd6, 0xf9, 0x05, 0x53, 0x88, 0xe5, 0x24, 0x9f, 0x8f, 0x5e, 0x2f, + 0xfd, 0x2c, 0x9c, 0xd6, 0x69, 0xad, 0x22, 0x54, 0xa7, 0xc5, 0x27, 0x2f, + 0x35, 0x77, 0xda, 0x0e, 0x49, 0xd0, 0x0a, 0x75, 0xaa, 0x5e, 0x6e, 0xad, + 0xe9, 0x20, 0xff, 0xf8, 0x5a, 0x40, 0x03, 0xe4, 0x36, 0xf1, 0x88, 0x1a, + 0xf3, 0x81, 0xc6, 0xd7, 0x70, 0xc8, 0xa9, 0xd2, 0x93, 0x51, 0x81, 0x49, + 0xf0, 0xe2, 0xef, 0xdb, 0xbd, 0x1a, 0x33, 0xf8, 0x2e, 0xa4, 0xb7, 0x21, + 0x14, 0x57, 0x98, 0x0e, 0xab, 0xbd, 0xa4, 0xd7, 0xec, 0xfc, 0x7a, 0x8d, + 0xdd, 0xcc, 0xec, 0x22, 0x13, 0x8d, 0xa9, 0x43, 0x68, 0xda, 0x5f, 0x78, + 0xe1, 0x21, 0xeb, 0xb1, 0x25, 0xb5, 0x4f, 0x99, 0x29, 0x7d, 0xf1, 0x9c, + 0x11, 0x2a, 0xa6, 0xdf, 0x9c, 0xd3, 0x33, 0xdb, 0xff, 0xb4, 0xcb, 0x40, + 0x77, 0x4d, 0xa5, 0x5c, 0x9b, 0x6f, 0x11, 0xad, 0x98, 0x17, 0x3b, 0xdd, + 0x16, 0xad, 0x5e, 0x4f, 0xcb, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char _USAirwaysWrongTeamID_signature[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x80, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00, 0x00, + 0xa0, 0x82, 0x0a, 0x1c, 0x30, 0x82, 0x04, 0x23, 0x30, 0x82, 0x03, 0x0b, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x19, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, + 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, + 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x32, 0x31, + 0x34, 0x31, 0x38, 0x35, 0x36, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x36, + 0x30, 0x32, 0x31, 0x34, 0x31, 0x38, 0x35, 0x36, 0x33, 0x35, 0x5a, 0x30, + 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x23, 0x41, + 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, + 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, + 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x31, 0x44, + 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, 0x64, 0x65, + 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x20, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xca, 0x38, 0x54, 0xa6, 0xcb, 0x56, 0xaa, + 0xc8, 0x24, 0x39, 0x48, 0xe9, 0x8c, 0xee, 0xec, 0x5f, 0xb8, 0x7f, 0x26, + 0x91, 0xbc, 0x34, 0x53, 0x7a, 0xce, 0x7c, 0x63, 0x80, 0x61, 0x77, 0x64, + 0x5e, 0xa5, 0x07, 0x23, 0xb6, 0x39, 0xfe, 0x50, 0x2d, 0x15, 0x56, 0x58, + 0x70, 0x2d, 0x7e, 0xc4, 0x6e, 0xc1, 0x4a, 0x85, 0x3e, 0x2f, 0xf0, 0xde, + 0x84, 0x1a, 0xa1, 0x57, 0xc9, 0xaf, 0x7b, 0x18, 0xff, 0x6a, 0xfa, 0x15, + 0x12, 0x49, 0x15, 0x08, 0x19, 0xac, 0xaa, 0xdb, 0x2a, 0x32, 0xed, 0x96, + 0x63, 0x68, 0x52, 0x15, 0x3d, 0x8c, 0x8a, 0xec, 0xbf, 0x6b, 0x18, 0x95, + 0xe0, 0x03, 0xac, 0x01, 0x7d, 0x97, 0x05, 0x67, 0xce, 0x0e, 0x85, 0x95, + 0x37, 0x6a, 0xed, 0x09, 0xb6, 0xae, 0x67, 0xcd, 0x51, 0x64, 0x9f, 0xc6, + 0x5c, 0xd1, 0xbc, 0x57, 0x6e, 0x67, 0x35, 0x80, 0x76, 0x36, 0xa4, 0x87, + 0x81, 0x6e, 0x38, 0x8f, 0xd8, 0x2b, 0x15, 0x4e, 0x7b, 0x25, 0xd8, 0x5a, + 0xbf, 0x4e, 0x83, 0xc1, 0x8d, 0xd2, 0x93, 0xd5, 0x1a, 0x71, 0xb5, 0x60, + 0x9c, 0x9d, 0x33, 0x4e, 0x55, 0xf9, 0x12, 0x58, 0x0c, 0x86, 0xb8, 0x16, + 0x0d, 0xc1, 0xe5, 0x77, 0x45, 0x8d, 0x50, 0x48, 0xba, 0x2b, 0x2d, 0xe4, + 0x94, 0x85, 0xe1, 0xe8, 0xc4, 0x9d, 0xc6, 0x68, 0xa5, 0xb0, 0xa3, 0xfc, + 0x67, 0x7e, 0x70, 0xba, 0x02, 0x59, 0x4b, 0x77, 0x42, 0x91, 0x39, 0xb9, + 0xf5, 0xcd, 0xe1, 0x4c, 0xef, 0xc0, 0x3b, 0x48, 0x8c, 0xa6, 0xe5, 0x21, + 0x5d, 0xfd, 0x6a, 0x6a, 0xbb, 0xa7, 0x16, 0x35, 0x60, 0xd2, 0xe6, 0xad, + 0xf3, 0x46, 0x29, 0xc9, 0xe8, 0xc3, 0x8b, 0xe9, 0x79, 0xc0, 0x6a, 0x61, + 0x67, 0x15, 0xb2, 0xf0, 0xfd, 0xe5, 0x68, 0xbc, 0x62, 0x5f, 0x6e, 0xcf, + 0x99, 0xdd, 0xef, 0x1b, 0x63, 0xfe, 0x92, 0x65, 0xab, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x81, 0xae, 0x30, 0x81, 0xab, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, + 0x04, 0x16, 0x04, 0x14, 0x88, 0x27, 0x17, 0x09, 0xa9, 0xb6, 0x18, 0x60, + 0x8b, 0xec, 0xeb, 0xba, 0xf6, 0x47, 0x59, 0xc5, 0x52, 0x54, 0xa3, 0xb7, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0x2b, 0xd0, 0x69, 0x47, 0x94, 0x76, 0x09, 0xfe, 0xf4, 0x6b, 0x8d, + 0x2e, 0x40, 0xa6, 0xf7, 0x47, 0x4d, 0x7f, 0x08, 0x5e, 0x30, 0x36, 0x06, + 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, + 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x72, 0x6f, 0x6f, + 0x74, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x63, 0x64, 0x06, 0x02, 0x01, 0x04, 0x02, 0x05, 0x00, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xda, 0x32, 0x00, 0x96, 0xc5, + 0x54, 0x94, 0xd3, 0x3b, 0x82, 0x37, 0x66, 0x7d, 0x2e, 0x68, 0xd5, 0xc3, + 0xc6, 0xb8, 0xcb, 0x26, 0x8c, 0x48, 0x90, 0xcf, 0x13, 0x24, 0x6a, 0x46, + 0x8e, 0x63, 0xd4, 0xf0, 0xd0, 0x13, 0x06, 0xdd, 0xd8, 0xc4, 0xc1, 0x37, + 0x15, 0xf2, 0x33, 0x13, 0x39, 0x26, 0x2d, 0xce, 0x2e, 0x55, 0x40, 0xe3, + 0x0b, 0x03, 0xaf, 0xfa, 0x12, 0xc2, 0xe7, 0x0d, 0x21, 0xb8, 0xd5, 0x80, + 0xcf, 0xac, 0x28, 0x2f, 0xce, 0x2d, 0xb3, 0x4e, 0xaf, 0x86, 0x19, 0x04, + 0xc6, 0xe9, 0x50, 0xdd, 0x4c, 0x29, 0x47, 0x10, 0x23, 0xfc, 0x6c, 0xbb, + 0x1b, 0x98, 0x6b, 0x48, 0x89, 0xe1, 0x5b, 0x9d, 0xde, 0x46, 0xdb, 0x35, + 0x85, 0x35, 0xef, 0x3e, 0xd0, 0xe2, 0x58, 0x4b, 0x38, 0xf4, 0xed, 0x75, + 0x5a, 0x1f, 0x5c, 0x70, 0x1d, 0x56, 0x39, 0x12, 0xe5, 0xe1, 0x0d, 0x11, + 0xe4, 0x89, 0x25, 0x06, 0xbd, 0xd5, 0xb4, 0x15, 0x8e, 0x5e, 0xd0, 0x59, + 0x97, 0x90, 0xe9, 0x4b, 0x81, 0xe2, 0xdf, 0x18, 0xaf, 0x44, 0x74, 0x1e, + 0x19, 0xa0, 0x3a, 0x47, 0xcc, 0x91, 0x1d, 0x3a, 0xeb, 0x23, 0x5a, 0xfe, + 0xa5, 0x2d, 0x97, 0xf7, 0x7b, 0xbb, 0xd6, 0x87, 0x46, 0x42, 0x85, 0xeb, + 0x52, 0x3d, 0x26, 0xb2, 0x63, 0xa8, 0xb4, 0xb1, 0xca, 0x8f, 0xf4, 0xcc, + 0xe2, 0xb3, 0xc8, 0x47, 0xe0, 0xbf, 0x9a, 0x59, 0x83, 0xfa, 0xda, 0x98, + 0x53, 0x2a, 0x82, 0xf5, 0x7c, 0x65, 0x2e, 0x95, 0xd9, 0x33, 0x5d, 0xf5, + 0xed, 0x65, 0xcc, 0x31, 0x37, 0xc5, 0x5a, 0x04, 0xe8, 0x6b, 0xe1, 0xe7, + 0x88, 0x03, 0x4a, 0x75, 0x9e, 0x9b, 0x28, 0xcb, 0x4a, 0x40, 0x88, 0x65, + 0x43, 0x75, 0xdd, 0xcb, 0x3a, 0x25, 0x23, 0xc5, 0x9e, 0x57, 0xf8, 0x2e, + 0xce, 0xd2, 0xa9, 0x92, 0x5e, 0x73, 0x2e, 0x2f, 0x25, 0x75, 0x15, 0x30, + 0x82, 0x05, 0xf1, 0x30, 0x82, 0x04, 0xd9, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x08, 0x29, 0xd6, 0x12, 0x53, 0x17, 0x20, 0x2d, 0x6a, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x23, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, + 0x77, 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, 0x41, + 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, 0x69, + 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, + 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x32, 0x30, 0x35, 0x33, 0x30, 0x32, 0x33, 0x32, 0x30, + 0x31, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x35, 0x33, 0x30, 0x32, + 0x33, 0x32, 0x30, 0x31, 0x30, 0x5a, 0x30, 0x81, 0x9b, 0x31, 0x26, 0x30, + 0x24, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, + 0x01, 0x0c, 0x16, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, + 0x6e, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x24, + 0x50, 0x61, 0x73, 0x73, 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, 0x49, 0x44, + 0x3a, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, 0x6e, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0a, 0x41, + 0x31, 0x42, 0x32, 0x43, 0x33, 0x44, 0x34, 0x45, 0x35, 0x31, 0x20, 0x30, + 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x17, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x55, + 0x73, 0x65, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xbb, 0x6c, 0x6c, 0xd4, 0xcd, 0x0b, 0xd9, + 0x47, 0x49, 0xe1, 0xa3, 0xfe, 0x73, 0xe0, 0x15, 0xa6, 0x2e, 0x35, 0xc8, + 0xb7, 0xcd, 0xab, 0x5e, 0xd3, 0x87, 0x8a, 0x94, 0x8f, 0x4d, 0x94, 0x52, + 0x72, 0x27, 0x57, 0xb8, 0xf5, 0xa8, 0xe2, 0xf2, 0xb0, 0x46, 0xad, 0xb9, + 0x30, 0x9b, 0x6a, 0xd7, 0x0a, 0xff, 0x0e, 0x5e, 0x78, 0x4c, 0x97, 0x17, + 0x16, 0xa7, 0x03, 0xe1, 0x13, 0xe7, 0x97, 0x72, 0x24, 0xc8, 0x7f, 0x80, + 0x91, 0xd2, 0x45, 0xa3, 0xf8, 0x21, 0xce, 0x2d, 0xfa, 0xe4, 0x3a, 0x5e, + 0x04, 0x30, 0xe9, 0x48, 0xca, 0x32, 0xce, 0x52, 0x4c, 0xcf, 0x14, 0xf9, + 0x04, 0x58, 0x30, 0x4a, 0xf8, 0x49, 0xbb, 0x39, 0x18, 0x5c, 0x4b, 0x28, + 0x9e, 0x14, 0x16, 0x23, 0x73, 0x6e, 0x0d, 0xcd, 0xcd, 0xef, 0x98, 0xe7, + 0x90, 0x04, 0x0e, 0x4a, 0xc8, 0x16, 0x22, 0x76, 0x68, 0xc6, 0xdf, 0x5d, + 0x20, 0xa7, 0x49, 0x2e, 0x55, 0x9e, 0x50, 0x31, 0x56, 0x50, 0x29, 0xf9, + 0x56, 0x09, 0x38, 0x32, 0x25, 0x1b, 0x3a, 0x1c, 0x97, 0x3e, 0x04, 0xee, + 0x69, 0x3c, 0x68, 0x44, 0x54, 0x51, 0x27, 0x75, 0x70, 0xa2, 0x33, 0x86, + 0x7a, 0x9d, 0x71, 0xc0, 0x18, 0x2e, 0x37, 0xb5, 0x47, 0x8d, 0xbe, 0x57, + 0xb6, 0xaa, 0xda, 0x1d, 0xe8, 0x78, 0x23, 0x66, 0xc8, 0x6c, 0xe3, 0x7e, + 0xfd, 0xde, 0x6b, 0x70, 0x2f, 0x76, 0x1d, 0xa6, 0x2b, 0x97, 0xee, 0xad, + 0x5b, 0x8b, 0x8e, 0x00, 0x87, 0x27, 0xdf, 0x16, 0x54, 0x08, 0x97, 0x18, + 0x23, 0x31, 0x2c, 0xf5, 0x9d, 0x41, 0xd5, 0xbb, 0x60, 0x23, 0x92, 0x3d, + 0xcc, 0x9e, 0x2d, 0xff, 0xa5, 0x8b, 0xe0, 0xf9, 0x65, 0xdc, 0x94, 0x58, + 0xb0, 0x9d, 0x73, 0x05, 0x05, 0x21, 0xa1, 0xb3, 0x37, 0xa4, 0x8f, 0x5d, + 0xda, 0xce, 0x9c, 0xf6, 0x63, 0x9b, 0x6b, 0x9f, 0x77, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3a, 0x30, 0x82, 0x02, 0x36, 0x30, 0x3d, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x31, + 0x30, 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, + 0x63, 0x73, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2d, 0x77, 0x77, 0x64, 0x72, 0x30, + 0x33, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0x9b, 0xc2, 0x61, 0x59, 0x72, 0x23, 0xb6, 0x5f, 0x91, 0x0f, 0x04, 0x87, + 0x92, 0xf9, 0xa4, 0xf3, 0x6b, 0xe9, 0xbe, 0xab, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x88, 0x27, 0x17, 0x09, + 0xa9, 0xb6, 0x18, 0x60, 0x8b, 0xec, 0xeb, 0xba, 0xf6, 0x47, 0x59, 0xc5, + 0x52, 0x54, 0xa3, 0xb7, 0x30, 0x82, 0x01, 0x0f, 0x06, 0x03, 0x55, 0x1d, + 0x20, 0x04, 0x82, 0x01, 0x06, 0x30, 0x82, 0x01, 0x02, 0x30, 0x81, 0xff, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, + 0x81, 0xf1, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x30, 0x81, 0xc3, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x81, + 0xb6, 0x0c, 0x81, 0xb3, 0x52, 0x65, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, + 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x62, 0x79, 0x20, + 0x61, 0x6e, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x79, 0x20, 0x61, 0x73, + 0x73, 0x75, 0x6d, 0x65, 0x73, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x74, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x62, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, + 0x20, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, + 0x69, 0x63, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x29, + 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23, 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x61, 0x70, 0x70, + 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x77, 0x64, 0x72, 0x63, + 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x1d, + 0x25, 0x04, 0x17, 0x30, 0x15, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, + 0x04, 0x0e, 0x30, 0x10, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, + 0x64, 0x06, 0x03, 0x02, 0x04, 0x02, 0x05, 0x00, 0x30, 0x26, 0x06, 0x0a, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, 0x01, 0x10, 0x04, 0x18, + 0x0c, 0x16, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x72, 0x64, 0x6d, 0x61, 0x6e, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x9b, 0xef, 0x1e, 0xff, + 0xee, 0xd5, 0xfd, 0x71, 0x1a, 0xf5, 0x17, 0xfe, 0x05, 0xba, 0x30, 0xfc, + 0xbd, 0x6d, 0x01, 0xb0, 0x0b, 0x78, 0x41, 0x4b, 0x76, 0x71, 0xd1, 0x8c, + 0xf0, 0xcd, 0xed, 0xd9, 0xaa, 0xec, 0xad, 0x1d, 0x4a, 0x2d, 0xcc, 0x00, + 0x11, 0x5b, 0x1d, 0xd9, 0xef, 0x08, 0xa2, 0x3d, 0xea, 0xe9, 0xbd, 0x35, + 0x0b, 0x1c, 0x9f, 0xe7, 0xeb, 0xc9, 0xc9, 0xea, 0x99, 0xcc, 0x77, 0x27, + 0xb9, 0x01, 0x09, 0x72, 0x40, 0xba, 0xd4, 0x26, 0x54, 0x8f, 0x30, 0x84, + 0x7e, 0x03, 0x65, 0xda, 0x08, 0xb2, 0x92, 0xee, 0x61, 0x4e, 0x5f, 0x00, + 0x39, 0x48, 0x2d, 0x99, 0x83, 0xb5, 0xc4, 0x33, 0xb2, 0xf7, 0x62, 0xcf, + 0x6a, 0xbf, 0xbb, 0xb8, 0x40, 0x70, 0xbf, 0x11, 0xff, 0x7f, 0xc1, 0xc1, + 0x8d, 0x1d, 0x67, 0x6c, 0x87, 0x02, 0xe2, 0x93, 0x17, 0x16, 0xc3, 0xec, + 0x5e, 0x97, 0xe4, 0xdd, 0x12, 0xcc, 0xb2, 0xdd, 0x91, 0x51, 0xa8, 0x32, + 0x25, 0x6d, 0xf7, 0x55, 0xb7, 0x4a, 0x8e, 0x6b, 0x90, 0xcb, 0x0f, 0x4c, + 0x93, 0x87, 0x2a, 0xd9, 0x31, 0xb8, 0x1a, 0x16, 0x12, 0xbb, 0x6e, 0xfc, + 0xb0, 0xae, 0xfb, 0x93, 0x76, 0x63, 0x37, 0xb7, 0x36, 0x13, 0x11, 0xc5, + 0x53, 0x45, 0xe0, 0x0d, 0xff, 0xaf, 0x05, 0x5f, 0x67, 0x51, 0xe1, 0x54, + 0x29, 0xa2, 0x1a, 0x7c, 0x61, 0xe0, 0xc2, 0xcd, 0xac, 0xbe, 0xee, 0xa6, + 0x4a, 0xdc, 0x92, 0x95, 0x48, 0x41, 0x2f, 0x37, 0xc0, 0x64, 0x05, 0xaa, + 0x4f, 0x05, 0xee, 0xe0, 0x3f, 0xa0, 0x9f, 0x43, 0x6c, 0xcc, 0xd5, 0x97, + 0x64, 0x6d, 0x15, 0x5b, 0xb6, 0xcd, 0x2a, 0xbc, 0x18, 0xde, 0xc7, 0x94, + 0x80, 0x2d, 0x2b, 0x81, 0x14, 0xfc, 0x48, 0xf7, 0xdf, 0xce, 0x94, 0xb3, + 0xfd, 0xf5, 0x7e, 0x42, 0x4d, 0x33, 0x58, 0x4d, 0x7a, 0x62, 0x2e, 0x61, + 0x31, 0x82, 0x02, 0x2a, 0x30, 0x82, 0x02, 0x26, 0x02, 0x01, 0x01, 0x30, + 0x81, 0xa3, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x23, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, + 0x64, 0x77, 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, + 0x70, 0x65, 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x31, 0x44, 0x30, 0x42, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x3b, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x77, + 0x69, 0x64, 0x65, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, + 0x72, 0x20, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x02, + 0x08, 0x29, 0xd6, 0x12, 0x53, 0x17, 0x20, 0x2d, 0x6a, 0x30, 0x09, 0x06, + 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0xa0, 0x5d, 0x30, 0x18, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, + 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, + 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37, 0x32, + 0x31, 0x32, 0x33, 0x30, 0x35, 0x5a, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0x3e, + 0xa0, 0x0a, 0xb8, 0x8c, 0x99, 0x95, 0xbc, 0x08, 0x28, 0xfc, 0x76, 0x6c, + 0xcc, 0xb7, 0x75, 0x57, 0x82, 0x6f, 0x81, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x01, 0x00, 0x1a, 0x4c, 0x93, 0x84, 0xe5, 0x8a, 0x68, 0x26, 0x7f, 0xb2, + 0xf7, 0xa4, 0x69, 0x66, 0x3a, 0xfa, 0xad, 0x77, 0x30, 0xa7, 0x21, 0xa7, + 0xbb, 0x01, 0x17, 0xb4, 0x88, 0x4a, 0x58, 0x37, 0x2b, 0xf5, 0x92, 0x79, + 0xce, 0xb2, 0x89, 0xbb, 0xb3, 0x52, 0x80, 0xa3, 0x10, 0x6f, 0x58, 0xcb, + 0x03, 0x80, 0xb9, 0x32, 0x12, 0x76, 0xe6, 0x79, 0xc1, 0xcc, 0x3c, 0x7b, + 0xf6, 0x69, 0x31, 0x9a, 0xe1, 0x59, 0xd4, 0x15, 0x8a, 0x1d, 0xbd, 0xb0, + 0xc9, 0xc3, 0xe7, 0x55, 0x24, 0xcc, 0x42, 0x5c, 0x01, 0x1d, 0xd7, 0x1b, + 0x3a, 0x6e, 0x26, 0xda, 0x56, 0xd1, 0xaf, 0x44, 0x2c, 0x41, 0x6f, 0x26, + 0x36, 0xb0, 0x2d, 0x43, 0x04, 0xb8, 0x05, 0xd1, 0xe3, 0xe4, 0xa0, 0x9d, + 0x98, 0x5b, 0x52, 0x7d, 0xd2, 0x8b, 0x78, 0x27, 0x1f, 0x8e, 0xd0, 0xb0, + 0x09, 0x8a, 0x7d, 0x09, 0xd9, 0xc2, 0x7b, 0x09, 0x1e, 0xd8, 0x92, 0x1f, + 0x3f, 0x0f, 0x52, 0x10, 0x13, 0x9c, 0x0a, 0x4c, 0x9d, 0x4e, 0x55, 0x32, + 0x67, 0xc0, 0x46, 0x64, 0x8c, 0x89, 0x77, 0x6a, 0x6a, 0x60, 0xe2, 0x4d, + 0xb2, 0x9e, 0x4d, 0x18, 0xc9, 0x77, 0x74, 0xf1, 0x41, 0xf5, 0xb7, 0xfa, + 0x4b, 0x0f, 0xb7, 0x51, 0xf4, 0x59, 0x4d, 0xfa, 0x7a, 0x07, 0xba, 0xab, + 0xd5, 0x90, 0xa6, 0xbd, 0x61, 0x05, 0xde, 0x8b, 0x46, 0xbf, 0x8b, 0x5a, + 0xf8, 0xbf, 0xd8, 0x6c, 0x87, 0x0e, 0xc0, 0xfd, 0xc4, 0x63, 0xdd, 0xd9, + 0xb1, 0x52, 0xca, 0x64, 0x68, 0x87, 0xab, 0x27, 0x41, 0x41, 0xb8, 0x02, + 0xa2, 0xb7, 0xde, 0xda, 0x84, 0x15, 0x0e, 0xc6, 0x49, 0x5d, 0xd2, 0xc9, + 0xf1, 0x4a, 0x44, 0xa4, 0x1a, 0xf8, 0x5f, 0x70, 0x52, 0x67, 0xb3, 0x6f, + 0x59, 0x9a, 0x9a, 0xea, 0x1d, 0xfa, 0x6e, 0x06, 0xf3, 0xdc, 0x60, 0x28, + 0x97, 0xc3, 0x78, 0x04, 0x17, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char _USAirwaysCorrect_manifest_json[] = { + 0x7b, 0x0a, 0x20, 0x20, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x40, 0x32, 0x78, + 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x38, 0x31, 0x38, + 0x64, 0x32, 0x37, 0x64, 0x33, 0x65, 0x66, 0x61, 0x39, 0x35, 0x37, 0x31, + 0x62, 0x61, 0x30, 0x66, 0x66, 0x31, 0x65, 0x36, 0x32, 0x34, 0x33, 0x62, + 0x30, 0x39, 0x34, 0x35, 0x62, 0x63, 0x63, 0x36, 0x39, 0x33, 0x65, 0x62, + 0x37, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x2e, + 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x62, 0x65, 0x64, 0x66, + 0x30, 0x30, 0x61, 0x61, 0x62, 0x32, 0x32, 0x31, 0x61, 0x63, 0x37, 0x31, + 0x64, 0x33, 0x66, 0x66, 0x65, 0x64, 0x64, 0x33, 0x32, 0x63, 0x33, 0x63, + 0x64, 0x36, 0x63, 0x32, 0x35, 0x30, 0x33, 0x32, 0x62, 0x61, 0x34, 0x30, + 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x6a, + 0x73, 0x6f, 0x6e, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x61, 0x65, 0x33, 0x38, + 0x39, 0x35, 0x39, 0x36, 0x30, 0x62, 0x34, 0x64, 0x61, 0x31, 0x65, 0x64, + 0x35, 0x38, 0x33, 0x66, 0x64, 0x37, 0x31, 0x66, 0x66, 0x32, 0x36, 0x31, + 0x36, 0x65, 0x34, 0x39, 0x65, 0x36, 0x34, 0x64, 0x36, 0x36, 0x65, 0x66, + 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x6c, 0x6f, 0x67, 0x6f, 0x2e, 0x70, + 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x39, 0x30, 0x62, 0x63, 0x62, + 0x39, 0x34, 0x62, 0x62, 0x30, 0x66, 0x31, 0x30, 0x33, 0x66, 0x36, 0x63, + 0x32, 0x63, 0x32, 0x36, 0x35, 0x35, 0x33, 0x36, 0x66, 0x65, 0x61, 0x63, + 0x37, 0x61, 0x38, 0x38, 0x33, 0x36, 0x37, 0x30, 0x34, 0x34, 0x33, 0x22, + 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x2e, 0x44, 0x53, 0x5f, 0x53, 0x74, 0x6f, + 0x72, 0x65, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x64, 0x66, 0x32, 0x66, 0x62, + 0x65, 0x62, 0x31, 0x34, 0x30, 0x30, 0x61, 0x63, 0x64, 0x61, 0x30, 0x39, + 0x30, 0x39, 0x61, 0x33, 0x32, 0x63, 0x31, 0x63, 0x66, 0x36, 0x62, 0x66, + 0x34, 0x39, 0x32, 0x66, 0x31, 0x31, 0x32, 0x31, 0x65, 0x30, 0x37, 0x22, + 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x6c, 0x6f, 0x67, 0x6f, 0x40, 0x32, 0x78, + 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x39, 0x30, 0x62, + 0x63, 0x62, 0x39, 0x34, 0x62, 0x62, 0x30, 0x66, 0x31, 0x30, 0x33, 0x66, + 0x36, 0x63, 0x32, 0x63, 0x32, 0x36, 0x35, 0x35, 0x33, 0x36, 0x66, 0x65, + 0x61, 0x63, 0x37, 0x61, 0x38, 0x38, 0x33, 0x36, 0x37, 0x30, 0x34, 0x34, + 0x33, 0x22, 0x0a, 0x7d +}; + +unsigned char _USAirwaysWrongTeamID_manifest_json[] = { + 0x7b, 0x0a, 0x20, 0x20, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x40, 0x32, 0x78, + 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x38, 0x31, 0x38, + 0x64, 0x32, 0x37, 0x64, 0x33, 0x65, 0x66, 0x61, 0x39, 0x35, 0x37, 0x31, + 0x62, 0x61, 0x30, 0x66, 0x66, 0x31, 0x65, 0x36, 0x32, 0x34, 0x33, 0x62, + 0x30, 0x39, 0x34, 0x35, 0x62, 0x63, 0x63, 0x36, 0x39, 0x33, 0x65, 0x62, + 0x37, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x2e, + 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x62, 0x65, 0x64, 0x66, + 0x30, 0x30, 0x61, 0x61, 0x62, 0x32, 0x32, 0x31, 0x61, 0x63, 0x37, 0x31, + 0x64, 0x33, 0x66, 0x66, 0x65, 0x64, 0x64, 0x33, 0x32, 0x63, 0x33, 0x63, + 0x64, 0x36, 0x63, 0x32, 0x35, 0x30, 0x33, 0x32, 0x62, 0x61, 0x34, 0x30, + 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x70, 0x61, 0x73, 0x73, 0x2e, 0x6a, + 0x73, 0x6f, 0x6e, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x32, 0x61, 0x35, 0x66, + 0x38, 0x66, 0x34, 0x37, 0x66, 0x34, 0x61, 0x33, 0x38, 0x37, 0x35, 0x35, + 0x36, 0x62, 0x31, 0x65, 0x61, 0x30, 0x65, 0x64, 0x64, 0x36, 0x39, 0x65, + 0x64, 0x31, 0x64, 0x62, 0x61, 0x39, 0x37, 0x39, 0x64, 0x32, 0x66, 0x33, + 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x6c, 0x6f, 0x67, 0x6f, 0x2e, 0x70, + 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x39, 0x30, 0x62, 0x63, 0x62, + 0x39, 0x34, 0x62, 0x62, 0x30, 0x66, 0x31, 0x30, 0x33, 0x66, 0x36, 0x63, + 0x32, 0x63, 0x32, 0x36, 0x35, 0x35, 0x33, 0x36, 0x66, 0x65, 0x61, 0x63, + 0x37, 0x61, 0x38, 0x38, 0x33, 0x36, 0x37, 0x30, 0x34, 0x34, 0x33, 0x22, + 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x2e, 0x44, 0x53, 0x5f, 0x53, 0x74, 0x6f, + 0x72, 0x65, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x64, 0x66, 0x32, 0x66, 0x62, + 0x65, 0x62, 0x31, 0x34, 0x30, 0x30, 0x61, 0x63, 0x64, 0x61, 0x30, 0x39, + 0x30, 0x39, 0x61, 0x33, 0x32, 0x63, 0x31, 0x63, 0x66, 0x36, 0x62, 0x66, + 0x34, 0x39, 0x32, 0x66, 0x31, 0x31, 0x32, 0x31, 0x65, 0x30, 0x37, 0x22, + 0x2c, 0x0a, 0x20, 0x20, 0x22, 0x6c, 0x6f, 0x67, 0x6f, 0x40, 0x32, 0x78, + 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x3a, 0x20, 0x22, 0x39, 0x30, 0x62, + 0x63, 0x62, 0x39, 0x34, 0x62, 0x62, 0x30, 0x66, 0x31, 0x30, 0x33, 0x66, + 0x36, 0x63, 0x32, 0x63, 0x32, 0x36, 0x35, 0x35, 0x33, 0x36, 0x66, 0x65, + 0x61, 0x63, 0x37, 0x61, 0x38, 0x38, 0x33, 0x36, 0x37, 0x30, 0x34, 0x34, + 0x33, 0x22, 0x0a, 0x7d +}; + +static const UInt8 sITunesStoreRootCertificate[] = +{ + 0x30, 0x82, 0x04, 0x65, 0x30, 0x82, 0x03, 0x4d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, + 0xcb, 0x06, 0xa3, 0x3b, 0x30, 0xc3, 0x24, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x7e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, + 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, + 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x52, 0x6f, 0x6f, + 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, + 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, + 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x31, 0x30, 0x30, + 0x39, 0x31, 0x37, 0x35, 0x31, 0x33, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x32, 0x31, 0x30, 0x30, 0x32, + 0x31, 0x37, 0x35, 0x31, 0x33, 0x30, 0x5a, 0x30, 0x7e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, + 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, + 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x52, 0x6f, 0x6f, + 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, + 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, + 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, + 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa9, 0x78, 0xc0, 0xaf, 0x1a, 0x96, 0x59, 0xad, + 0xf8, 0x3c, 0x16, 0xe1, 0xfc, 0xc4, 0x7a, 0xaf, 0xf0, 0x80, 0xed, 0x7f, 0x3a, 0xff, 0xf2, 0x2a, + 0xb6, 0xf3, 0x1a, 0xdd, 0xbd, 0x14, 0xb1, 0x5d, 0x9d, 0x66, 0xaf, 0xc7, 0xaf, 0x2b, 0x26, 0x78, + 0x9c, 0xb8, 0x0b, 0x41, 0x9c, 0xdc, 0x17, 0xf1, 0x40, 0x18, 0x09, 0xa1, 0x0a, 0xbc, 0x01, 0x9a, + 0x0c, 0xbe, 0x89, 0xdb, 0x9d, 0x34, 0xc7, 0x52, 0x8a, 0xf2, 0xbf, 0x35, 0x2b, 0x24, 0x04, 0xb0, + 0x0c, 0x9d, 0x41, 0x7d, 0x63, 0xe3, 0xad, 0xcf, 0x8b, 0x34, 0xbf, 0x5c, 0x42, 0x82, 0x9b, 0x78, + 0x7f, 0x00, 0x10, 0x88, 0xd9, 0xfd, 0xf8, 0xbf, 0x63, 0x2c, 0x91, 0x87, 0x03, 0xda, 0xbc, 0xc6, + 0x71, 0x2b, 0x9a, 0x21, 0x30, 0x95, 0xd6, 0x88, 0xe8, 0xbd, 0x0a, 0x74, 0xa4, 0xa6, 0x39, 0xd0, + 0x61, 0xd3, 0xb6, 0xe0, 0x2b, 0x1e, 0xe4, 0x78, 0x5c, 0x70, 0x32, 0x66, 0x97, 0x34, 0xa9, 0x79, + 0xfc, 0x96, 0xaf, 0x4b, 0x8a, 0xd5, 0x12, 0x07, 0x8c, 0x1c, 0xf6, 0x3e, 0x5f, 0xdc, 0x8f, 0x92, + 0x10, 0xe8, 0x7e, 0xa0, 0x14, 0x1e, 0x61, 0x28, 0xfa, 0xcc, 0xcf, 0x3c, 0xdb, 0x2b, 0xe3, 0xe9, + 0x44, 0x4a, 0x9d, 0x5f, 0x92, 0x3d, 0xa3, 0xfd, 0x1a, 0x63, 0xb4, 0xbb, 0xab, 0x67, 0x45, 0xc6, + 0x4d, 0x84, 0x4a, 0xaa, 0x33, 0xe4, 0xde, 0xd3, 0x04, 0x92, 0xbf, 0xf7, 0x00, 0x48, 0x76, 0xc6, + 0x4e, 0x17, 0xea, 0x70, 0xdb, 0x09, 0xbc, 0x22, 0x07, 0x7b, 0x97, 0x49, 0xe5, 0x29, 0xa7, 0x1a, + 0x04, 0xd2, 0x0d, 0x0e, 0x73, 0xf1, 0x49, 0x43, 0x34, 0x35, 0x61, 0xe5, 0x67, 0xdf, 0x3c, 0x58, + 0x42, 0x51, 0xfb, 0xc3, 0xa4, 0x15, 0x6d, 0x39, 0x6b, 0x2a, 0x22, 0xde, 0xdd, 0xe2, 0x36, 0x5b, + 0xd7, 0x37, 0x53, 0x96, 0x9d, 0x3a, 0x9f, 0x4b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe5, + 0x30, 0x81, 0xe2, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb0, 0xda, + 0xe1, 0x7f, 0xa8, 0x8b, 0x4a, 0x6a, 0x81, 0x5d, 0x0c, 0xa1, 0x84, 0x56, 0x46, 0x1e, 0x6a, 0xef, + 0xe5, 0xcf, 0x30, 0x81, 0xb2, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xaa, 0x30, 0x81, 0xa7, + 0x80, 0x14, 0xb0, 0xda, 0xe1, 0x7f, 0xa8, 0x8b, 0x4a, 0x6a, 0x81, 0x5d, 0x0c, 0xa1, 0x84, 0x56, + 0x46, 0x1e, 0x6a, 0xef, 0xe5, 0xcf, 0xa1, 0x81, 0x83, 0xa4, 0x81, 0x80, 0x30, 0x7e, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, + 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x11, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, + 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, + 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x82, 0x09, 0x00, 0xcb, + 0x06, 0xa3, 0x3b, 0x30, 0xc3, 0x24, 0x03, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0xcc, 0xfb, 0x34, 0x4e, 0xec, 0x27, + 0x05, 0xf9, 0x10, 0xc9, 0xdf, 0x8e, 0x22, 0x21, 0x94, 0x70, 0xe9, 0x74, 0x64, 0x11, 0xce, 0x07, + 0x91, 0xc2, 0x58, 0x0d, 0xff, 0x51, 0x6d, 0x97, 0x64, 0x32, 0x1a, 0x1c, 0xdf, 0x4a, 0x93, 0xdb, + 0x94, 0x62, 0x14, 0xcb, 0x00, 0x13, 0x37, 0x98, 0x0e, 0x3d, 0x96, 0x19, 0x5f, 0x44, 0xc9, 0x11, + 0xd2, 0xc9, 0x8c, 0xa3, 0x19, 0x2f, 0x88, 0x4f, 0x5f, 0x3c, 0x46, 0x56, 0xe2, 0xbd, 0x78, 0x4f, + 0xfe, 0x8e, 0x39, 0xb5, 0xed, 0x37, 0x3e, 0xfb, 0xf6, 0xae, 0x56, 0x2c, 0x49, 0x37, 0x4a, 0x94, + 0x05, 0x4b, 0x8f, 0x67, 0xdb, 0xe6, 0x24, 0xa6, 0x75, 0xae, 0xc8, 0xa2, 0x26, 0x87, 0x70, 0xb8, + 0x1d, 0xc2, 0xfc, 0x8d, 0xff, 0x41, 0x23, 0x8a, 0x01, 0x8a, 0xc3, 0x78, 0x5a, 0x61, 0x4a, 0xed, + 0x48, 0x96, 0xb5, 0x82, 0xa7, 0xaa, 0x2e, 0xb5, 0xed, 0xdd, 0xf4, 0xe6, 0xb5, 0xa1, 0x27, 0x3b, + 0xda, 0xf9, 0x18, 0x26, 0x7e, 0x8e, 0xec, 0xef, 0xe1, 0x00, 0x7d, 0x3d, 0xf7, 0x3d, 0x01, 0x68, + 0x14, 0x92, 0xfc, 0x9c, 0xbb, 0x0a, 0xa1, 0xc3, 0x60, 0x31, 0x16, 0x08, 0x9b, 0xef, 0x4d, 0xaf, + 0x46, 0xc7, 0xcc, 0x4e, 0x05, 0x34, 0xa8, 0x44, 0xb2, 0x85, 0x03, 0x67, 0x6c, 0x31, 0xae, 0xa3, + 0x18, 0xb5, 0x5f, 0x75, 0xae, 0xe0, 0x5a, 0xbf, 0x64, 0x32, 0x2b, 0x28, 0x99, 0x24, 0xcd, 0x01, + 0x34, 0xc2, 0xfc, 0xf1, 0x88, 0xba, 0x8c, 0x9b, 0x90, 0x85, 0x56, 0x6d, 0xaf, 0xd5, 0x2e, 0x88, + 0x12, 0x61, 0x7c, 0x76, 0x33, 0x6b, 0xc4, 0xf7, 0x31, 0x77, 0xe4, 0x02, 0xb7, 0x9e, 0x9c, 0x8c, + 0xbe, 0x04, 0x2e, 0x51, 0xa3, 0x04, 0x4c, 0xcd, 0xe2, 0x71, 0x5e, 0x36, 0xfb, 0xf1, 0x68, 0xf0, + 0xad, 0x37, 0x80, 0x98, 0x26, 0xc0, 0xef, 0x9b, 0x3c +}; + +static const unsigned char url_bag[] = +"" +"" +"" +"" +" signaturePXlOzELnbcmmd6zbfl/CfXhx4lUKpH7exmCIMQXbwLzGCEjy2g1ekpMopSZZ+OeizHJDPrgfMf3mzhPsagguGNVan8Y335wF0iT5zh4dR/POso9mj1HOvoU5JmqjVXpNVWoflfkIyHZUiQafXitKda7DWXOrNpP92LplPtBzLIg=" +" certs" +" " +" MIIDRjCCAi6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADB+MRMwEQYDVQQKEwpBcHBsZSBJbmMuMRUwEwYDVQQLEwxpVHVuZXMgU3RvcmUxGjAYBgNVBAMTEWlUdW5lcyBTdG9yZSBSb290MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAGA1UEBxMJQ3VwZXJ0aW5vMB4XDTExMDYwNjIyMTkxOFoXDTEzMDYwNTIyMTkxOFowgYExEzARBgNVBAoTCkFwcGxlIEluYy4xFTATBgNVBAsTDGlUdW5lcyBTdG9yZTEdMBsGA1UEAxMUaVR1bmVzIFN0b3JlIFVSTCBCYWcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlDdXBlcnRpbm8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALucax5drB+v1stVZDaqk/kyW1zcZ9Va8lKAXzsDXpkt4gvzhSJX1bQ3Z6qNMhbVT1nvkDHONGsnCyqOkRfI6Py19gRAoQO3XtfAqrZ5Sh7Spxsznm8GCUBBNRtSUzYa+StvwOWiXdPX3D9X5dZTetatpsLL5t5FeedaAW7Baan7AgMBAAGjTzBNMB0GA1UdDgQWBBTI704/Bfpw+vAHyPMVdbk/gT3xpjAfBgNVHSMEGDAWgBSw2uF/qItKaoFdDKGEVkYeau/lzzALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEFBQADggEBAIF7O5xNidy+EE3/skB0Erwy0358vboeowqkSPYzYaNWhK2UCyUiERN61hkaZFFIDqjchND3h7y67kJDCyGviRzRlFiMAEb56rKFzAwlT5w1btOoQjbKgl5MnqYIC9GtUWKC5gH4Qx6lgmIR90qQ/7gEykivZ/IkIvYpXHCYvOStEPqN//u1oiAAVmJpmMN1MHCrhJeZebtMu8zgS9i1rv/e+YaxQJcdJ5COg0GD8i5RI3VCCWqRGl3aGvLx5TzzetnQlRvglnfzsSuXR7gB6oENnOjPGnarccN1qdwPCd8lw+hxfzG8/2LWLUooH2tWXC1Qi9dU9yxCgjgTwzmol3I=" +" " +" bagPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlIENvbXB1dGVyLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q+CiAgPGtleT50aW1lc3RhbXA8L2tleT48ZGF0ZT4yMDExLTA3LTIyVDE0OjIyOjE4WjwvZGF0ZT4KICA8a2V5PnN0b3JlRnJvbnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evc3RvcmVGcm9udDwvc3RyaW5nPgogIDxrZXk+bmV3VXNlclN0b3JlRnJvbnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvZmlyc3RMYXVuY2g8L3N0cmluZz4KICA8a2V5Pm5ld0lQb2RVc2VyU3RvcmVGcm9udDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9uZXdJUG9kVXNlcj9uZXdJUG9kVXNlcj10cnVlPC9zdHJpbmc+CiAgPGtleT5uZXdQaG9uZVVzZXI8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvcGhvbmVMYW5kaW5nUGFnZTwvc3RyaW5nPgogIDxrZXk+c2VhcmNoPC9rZXk+PHN0cmluZz5odHRwOi8vYXguc2VhcmNoLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlNlYXJjaC53b2Evd2Evc2VhcmNoPC9zdHJpbmc+CiAgPGtleT5hZHZhbmNlZFNlYXJjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2gud29hL3dhL2FkdmFuY2VkU2VhcmNoPC9zdHJpbmc+CiAgPGtleT5zZWFyY2hIaW50czwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2hIaW50cy53b2Evd2EvaGludHM8L3N0cmluZz4KICA8a2V5PnBhcmVudGFsQWR2aXNvcnk8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvcGFyZW50YWxBZHZpc29yeTwvc3RyaW5nPgogIDxrZXk+YnJvd3NlPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2Jyb3dzZTwvc3RyaW5nPgogIDxrZXk+dmlld0FsYnVtPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdBbGJ1bTwvc3RyaW5nPgogIDxrZXk+dmlld0Jvb2s8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0Jvb2s8L3N0cmluZz4KICA8a2V5PnZpZXdBcnRpc3Q8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0FydGlzdDwvc3RyaW5nPgogIDxrZXk+dmlld0NvbXBvc2VyPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdDb21wb3Nlcjwvc3RyaW5nPgogIDxrZXk+dmlld0dlbnJlPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdHZW5yZTwvc3RyaW5nPgogIDxrZXk+dmlld1BvZGNhc3Q8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1BvZGNhc3Q8L3N0cmluZz4KICA8a2V5PnZpZXdQdWJsaXNoZWRQbGF5bGlzdDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3UHVibGlzaGVkUGxheWxpc3Q8L3N0cmluZz4KICA8a2V5PnZpZXdWaWRlbzwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VmlkZW88L3N0cmluZz4KICA8a2V5PmFwcHM8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0FwcHNNYWluPC9zdHJpbmc+CiAgPGtleT5hdWRpb2Jvb2tzPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdBdWRpb2Jvb2tzTWFpbjwvc3RyaW5nPgogIDxrZXk+aXR1bmVzLXU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0dlbnJlP2lkPTQwMDAwMDAwPC9zdHJpbmc+CiAgPGtleT5tb3ZpZXM8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld01vdmllc01haW48L3N0cmluZz4KICA8a2V5Pm11c2ljPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdNdXNpY01haW48L3N0cmluZz4KICA8a2V5PnBvZGNhc3RzPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdQb2RjYXN0RGlyZWN0b3J5PC9zdHJpbmc+CiAgPGtleT5yaW5ndG9uZXM8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1Jpbmd0b25lczwvc3RyaW5nPgogIDxrZXk+dHYtc2hvd3M8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1RWU2hvd3NNYWluPC9zdHJpbmc+CiAgPGtleT5leHRlcm5hbFVSTFNlYXJjaEtleTwva2V5PjxzdHJpbmc+aXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogIDxrZXk+ZXh0ZXJuYWxVUkxSZXBsYWNlS2V5PC9rZXk+PHN0cmluZz5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgPGtleT5zb25nTWV0YURhdGE8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evc29uZ01ldGFEYXRhPC9zdHJpbmc+CiAgPGtleT5zZWxlY3RlZEl0ZW1zUGFnZTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9zZWxlY3RlZEl0ZW1zUGFnZTwvc3RyaW5nPgogIDxrZXk+c3dpc2gtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdSb29tP2ZjSWQ9Mjk3NDgwODcyJmFtcDtpZD0zNzwvc3RyaW5nPgogIDxrZXk+dXBsb2FkUHVibGlzaGVkUGxheWxpc3Q8L2tleT48c3RyaW5nPmh0dHA6Ly9jLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkNvbm5lY3Rpb25zLndvYS93YS9jcmVhdGVJTWl4P3M9MTQzNDQxPC9zdHJpbmc+CiAgPGtleT5taW5pLXN0b3JlPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL21pbmlzdG9yZVJldGlyZWQ8L3N0cmluZz4KICA8a2V5Pm1pbmktc3RvcmUtZmllbGRzPC9rZXk+PHN0cmluZz48L3N0cmluZz4KICA8a2V5Pm1pbmktc3RvcmUtbWF0Y2g8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvbWluaXN0b3JlUmV0aXJlZDwvc3RyaW5nPgogIDxrZXk+bWluaS1zdG9yZS1tYXRjaC1maWVsZHM8L2tleT48c3RyaW5nPjwvc3RyaW5nPgogIDxrZXk+bWluaS1zdG9yZS13ZWxjb21lPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL21pbmlzdG9yZVJldGlyZWQ8L3N0cmluZz4KICA8a2V5Pm1heFB1Ymxpc2hlZFBsYXlsaXN0SXRlbXM8L2tleT48aW50ZWdlcj4xMDA8L2ludGVnZXI+CiAgPGtleT5hdmFpbGFibGUtcmluZ3RvbmVzPC9rZXk+PHN0cmluZz5odHRwOi8vbXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aUGVyc29uYWxpemVyLndvYS93YS9hdmFpbGFibGVSaW5ndG9uZXM8L3N0cmluZz4KICA8a2V5PmFib3V0LXJpbmd0b25lczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9SaW5ndG9uZUxlYXJuTW9yZVBhZ2U8L3N0cmluZz4KICA8a2V5PnJpbmd0b25lLWluZm8tZmllbGRzLWxpc3Q8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPmlkLHMsZHNpZDwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5jb3Zlci1hcnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9jb3ZlckFydE1hdGNoPC9zdHJpbmc+CiAgPGtleT5jb3Zlci1hcnQtbWF0Y2g8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9jb3ZlckFydE1hdGNoPC9zdHJpbmc+CiAgPGtleT5jb3Zlci1hcnQtZmllbGRzPC9rZXk+PHN0cmluZz5hLHA8L3N0cmluZz4KICA8a2V5PmNvdmVyLWFydC1jZC1maWVsZHM8L2tleT48c3RyaW5nPmNkZGI8L3N0cmluZz4KICA8a2V5PmNvdmVyLWFydC1tYXRjaC1maWVsZHM8L2tleT48c3RyaW5nPmNkZGItdHVpZCxjZGRiLGFuLGFhbixwbjwvc3RyaW5nPgogIDxrZXk+Y292ZXItYXJ0LWZpZWxkcy1saXN0PC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5hLHA8L3N0cmluZz4KICAgIDxzdHJpbmc+aWQsY2RkYi10dWlkLGNkZGIsYW4sYWFuLHBuPC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PmNvdmVyLWFydC11c2VyPC9rZXk+PHN0cmluZz5odHRwOi8vbXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aUGVyc29uYWxpemVyLndvYS93YS9jb3ZlckFydFVzZXI8L3N0cmluZz4KICA8a2V5Pm1hdGNoVVJMczwva2V5PgogIDxhcnJheT4KICAgIDxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vPC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHA6Ly9zZWFyY2guaXR1bmVzLmFwcGxlLmNvbS88L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cDovL2J1eS5pdHVuZXMuYXBwbGUuY29tLzwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5saWJyYXJ5LWxpbms8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9saWJyYXJ5TGluazwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS1saW5rLWZpZWxkcy1saXN0PC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5pZCxhLHAsZyxjZGRiLXR1aWQsYW4sY24sZ24sa2luZCxuLHBuLHBvZGNhc3QtdXJsPC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PmxpYnJhcnlMaW5rPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd2EvbGlicmFyeUxpbms8L3N0cmluZz4KICA8a2V5Pm1heENvbXB1dGVyczwva2V5PjxzdHJpbmc+NTwvc3RyaW5nPgogIDxrZXk+dHJ1c3RlZERvbWFpbnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPmFsYmVydC1zby5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+YWIyLXNvLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5hbGJlcnQuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPmJ1eWlwaG9uZS5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+MmdhY3RpdmF0aW9uLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4qLmlwcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+d3d3LmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz50cmFpbGVycy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+cGhvYm9zLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4uaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4ubXpzdGF0aWMuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+bWV0cmljcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+c2VjdXJlLm1lLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4uYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQ8L3N0cmluZz4KICAgIDxzdHJpbmc+c3VwcG9ydC5tYWMuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPi5pdHVuZXMuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0dW5lcy5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+ZGVpbW9zLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5kZWltb3MyLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5kZWltb3MzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5pbmRpZ28wMS5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+aW5kaWdvLWVkZ2UuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPm53ay11bmJyaWNrMy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+bXpzdXBwb3J0LmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5zdG9yZXByZXZpZXcuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPi5jb3JwLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4uYXNpYS5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+LmV1cm8uYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPmFpdXN3LmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5zb2Z0ZGVwb3QuZmlsZW1ha2VyLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5pc3RkZXYxLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5pc3R3ZWJkZXYxLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4ucnRsY2RuLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5pc3R3ZWIuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+ZHNpZC1kb21haW5zPC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5idXkuaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4qLWJ1eS5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPnN1Lml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+YXguc3UuaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5teS5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPnNlLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+bXlhcHAuaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz51c2VycHViLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+Yy5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPnNjLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+ZHUuaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5zaWRlYmFyLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+YXguc2lkZWJhci5pdHVuZXMuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8c3RyaW5nPiotaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz4qLWl0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cGx1cy1pbmZvPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2lUdW5lc1BsdXNMZWFybk1vcmVQYWdlPC9zdHJpbmc+CiAgPGtleT5oZC1pbmZvPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL0hEVFZMZWFybk1vcmVQYWdlPC9zdHJpbmc+CiAgPGtleT5hcHBsZXR2LXJlbGF0ZWQtY29udGVudC11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9teS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpQZXJzb25hbGl6ZXIud29hL3dhL3JlbGF0ZWRJdGVtc1NoZWxmPC9zdHJpbmc+CiAgPGtleT5hcHBsZXR2LXlvdXR1YmUtYXV0aC11cmw8L2tleT48c3RyaW5nPmh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vPC9zdHJpbmc+CiAgPGtleT5hcHBsZXR2LXlvdXR1YmUtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vZ2RhdGEueW91dHViZS5jb20vPC9zdHJpbmc+CiAgPGtleT5hdmFpbGFibGUtc3RvcmVmcm9udHM8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvYXZhaWxhYmxlU3RvcmVGcm9udHM8L3N0cmluZz4KICA8a2V5PmFwcGxldHYtdmlldy10b3AtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdUb3A8L3N0cmluZz4KICA8a2V5PmFwcGxldHYtdXNlLXBlcnNvbmFsaXplZC1tZW51LWNvbnRlbnQ8L2tleT48c3RyaW5nPk5PPC9zdHJpbmc+CiAgPGtleT5HaG9zdHJpZGVyPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICA8a2V5Pml0dW5lcy1wcmVzZW50cy1kaXJlY3RvcnktdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd3MvUlNTL2RpcmVjdG9yeTwvc3RyaW5nPgogIDxrZXk+cDItdG9wLXRlbjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VG9wVGVuc0xpc3Q8L3N0cmluZz4KICA8a2V5PnAyLXNlcnZpY2UtdGVybXMtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vd3d3LmFwcGxlLmNvbS9sZWdhbC9pdHVuZXMvd3cvPC9zdHJpbmc+CiAgPGtleT5tb2JpbGUtY29ubmVjdGlvbi10eXBlLWFsbG93czwva2V5PgogIDxkaWN0PgogICAgPGtleT4zRzwva2V5PgogICAgPGRpY3Q+CiAgICAgIDxrZXk+ZUJvb2stc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5lQm9vay1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+ZUJvb2stc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWVib29rPC9zdHJpbmc+CiAgICAgIDxrZXk+cDItbXVzaWMtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5tdXNpYy1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+cDItc3RvcmUtc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWFsbDwvc3RyaW5nPgogICAgICA8a2V5PnAyLXN0b3JlLW5zLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1hbGxXaXRoUmluZ3RvbmU8L3N0cmluZz4KICAgICAgPGtleT5wMi1wb2RjYXN0cy1lbmFibGVkPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5wb2RjYXN0LWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4yMDk3MTUyMDwvaW50ZWdlcj4KICAgICAgPGtleT5wMi1tdXNpYy1zZWFyY2gtcGFyYW1ldGVyczwva2V5PjxzdHJpbmc+bWVkaWE9bXVzaWNBbmRQb2RjYXN0PC9zdHJpbmc+CiAgICAgIDxrZXk+cDItc29mdHdhcmUtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5zb2Z0d2FyZS1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+dmlkZW8tZG93bmxvYWQtc2l6ZS1saW1pdC1pbi1ieXRlczwva2V5PjxpbnRlZ2VyPjIwOTcxNTIwPC9pbnRlZ2VyPgogICAgPC9kaWN0PgogICAgPGtleT4yRzwva2V5PgogICAgPGRpY3Q+CiAgICAgIDxrZXk+ZUJvb2stc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5lQm9vay1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+ZUJvb2stc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWVib29rPC9zdHJpbmc+CiAgICAgIDxrZXk+cDItbXVzaWMtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5tdXNpYy1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+cDItc3RvcmUtc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWFsbDwvc3RyaW5nPgogICAgICA8a2V5PnAyLXN0b3JlLW5zLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1hbGxXaXRoUmluZ3RvbmU8L3N0cmluZz4KICAgICAgPGtleT5wMi1wb2RjYXN0cy1lbmFibGVkPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5wb2RjYXN0LWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4yMDk3MTUyMDwvaW50ZWdlcj4KICAgICAgPGtleT5wMi1tdXNpYy1zZWFyY2gtcGFyYW1ldGVyczwva2V5PjxzdHJpbmc+bWVkaWE9bXVzaWNBbmRQb2RjYXN0PC9zdHJpbmc+CiAgICAgIDxrZXk+cDItc29mdHdhcmUtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5zb2Z0d2FyZS1kb3dubG9hZC1zaXplLWxpbWl0LWluLWJ5dGVzPC9rZXk+PGludGVnZXI+MjA5NzE1MjA8L2ludGVnZXI+CiAgICAgIDxrZXk+dmlkZW8tZG93bmxvYWQtc2l6ZS1saW1pdC1pbi1ieXRlczwva2V5PjxpbnRlZ2VyPjIwOTcxNTIwPC9pbnRlZ2VyPgogICAgPC9kaWN0PgogICAgPGtleT5XaUZpPC9rZXk+CiAgICA8ZGljdD4KICAgICAgPGtleT5lQm9vay1zdG9yZS1hdmFpbGFibGU8L2tleT48c3RyaW5nPllFUzwvc3RyaW5nPgogICAgICA8a2V5PmVCb29rLWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4wPC9pbnRlZ2VyPgogICAgICA8a2V5PmVCb29rLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1lYm9vazwvc3RyaW5nPgogICAgICA8a2V5PnAyLW11c2ljLXN0b3JlLWF2YWlsYWJsZTwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgICAgIDxrZXk+bXVzaWMtZG93bmxvYWQtc2l6ZS1saW1pdC1pbi1ieXRlczwva2V5PjxpbnRlZ2VyPjA8L2ludGVnZXI+CiAgICAgIDxrZXk+cDItc3RvcmUtc2VhcmNoLXBhcmFtZXRlcnM8L2tleT48c3RyaW5nPm1lZGlhPWFsbDwvc3RyaW5nPgogICAgICA8a2V5PnAyLXN0b3JlLW5zLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1hbGxXaXRoUmluZ3RvbmU8L3N0cmluZz4KICAgICAgPGtleT5wMi1wb2RjYXN0cy1lbmFibGVkPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT5wb2RjYXN0LWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4wPC9pbnRlZ2VyPgogICAgICA8a2V5PnAyLW11c2ljLXNlYXJjaC1wYXJhbWV0ZXJzPC9rZXk+PHN0cmluZz5tZWRpYT1tdXNpY0FuZFBvZGNhc3Q8L3N0cmluZz4KICAgICAgPGtleT5wMi1zb2Z0d2FyZS1zdG9yZS1hdmFpbGFibGU8L2tleT48c3RyaW5nPllFUzwvc3RyaW5nPgogICAgICA8a2V5PnNvZnR3YXJlLWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4wPC9pbnRlZ2VyPgogICAgICA8a2V5PnZpZGVvLWRvd25sb2FkLXNpemUtbGltaXQtaW4tYnl0ZXM8L2tleT48aW50ZWdlcj4wPC9pbnRlZ2VyPgogICAgPC9kaWN0PgogIDwvZGljdD4KICA8a2V5PnAyLW11c2ljLXNlYXJjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2gud29hL3dhL3NlYXJjaDwvc3RyaW5nPgogIDxrZXk+cDItbXVzaWMtc2VhcmNoSGludHM8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zZWFyY2guaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU2VhcmNoSGludHMud29hL3dhL2hpbnRzPC9zdHJpbmc+CiAgPGtleT5wMi1ib29rLXNlYXJjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2gud29hL3dhL3NlYXJjaD9tZWRpYT1lYm9vazwvc3RyaW5nPgogIDxrZXk+cDItYm9vay1zZWFyY2hIaW50czwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNlYXJjaC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTZWFyY2hIaW50cy53b2Evd2EvaGludHM/bWVkaWE9ZWJvb2s8L3N0cmluZz4KICA8a2V5Pm1vYmlsZS10YWItYmFyczwva2V5PgogIDxkaWN0PgogICAgPGtleT5XaUZpLU11c2ljPC9rZXk+CiAgICA8ZGljdD4KICAgICAgPGtleT52ZXJzaW9uPC9rZXk+PHN0cmluZz4zMy0xNDM0NDE8L3N0cmluZz4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvZm9vdGVyU2VjdGlvbnM/YXBwPXdpZmk8L3N0cmluZz4KICAgIDwvZGljdD4KICAgIDxrZXk+U29mdHdhcmU8L2tleT4KICAgIDxkaWN0PgogICAgICA8a2V5PnZlcnNpb248L2tleT48c3RyaW5nPjEyLTE0MzQ0MTwvc3RyaW5nPgogICAgICA8a2V5PnVybDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9mb290ZXJTZWN0aW9ucz9hcHA9YXBwPC9zdHJpbmc+CiAgICA8L2RpY3Q+CiAgICA8a2V5PmVCb29rczwva2V5PgogICAgPGRpY3Q+CiAgICAgIDxrZXk+dmVyc2lvbjwva2V5PjxzdHJpbmc+Ny0xNDM0NDE8L3N0cmluZz4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvZm9vdGVyU2VjdGlvbnM/YXBwPWVCb29rczwvc3RyaW5nPgogICAgPC9kaWN0PgogIDwvZGljdD4KICA8a2V5PnAyLWxhdW5jaC1ob3N0LXN1ZmZpeC13aGl0ZWxpc3Q8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPi5hcHBsZS5jb208L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLW1vYmlsZXN0b3JlLWhvc3QtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPigoYnV5fG15fHNlYXJjaHxjKVwuKT9pdHVuZXNcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICA8c3RyaW5nPnBob2Jvc1wuYXBwbGVcLmNvbSQ8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLW1vYmlsZXN0b3JlLXBhdGgtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9tenN0b3JlLndvYS93YS8oc3RvcmVmcm9udHx2aWV3dG9wdGVuc2xpc3R8dmlld3RvcGZpZnR5fHZpZXd0b3B8dmlld2F1ZGlvYm9va3x2aWV3Z3JvdXBpbmd8dmlld2dlbnJlfHZpZXdwbGF5bGlzdHNwYWdlfHZpZXdyb29tfHZpZXdhbGJ1bXx2aWV3cG9kY2FzdHx2aWV3bWl4fHN0b3JlZnJvbnRzfHZpZXdjb250ZW50c3VzZXJyZXZpZXdzfHZpZXdldWxhfHZpZXd0dnNob3d8dmlld3R2c2Vhc29ufHZpZXdtb3ZpZXx2aWV3dmlkZW98Zm9vdGVyc2VjdGlvbnN8bGlicmFyeWxpbmt8dmlld2ZlYXR1cmV8dmlld2FydGlzdCk8L3N0cmluZz4KICAgIDxzdHJpbmc+Xi93ZWJvYmplY3RzL216c2VhcmNoLndvYS93YS8oc2VhcmNofGFkdmFuY2Vkc2VhcmNoKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXooZmFzdCk/ZmluYW5jZS53b2Evd2EvKGNvbS5hcHBsZS5qaW5nbGUuYXBwLmZpbmFuY2UuZGlyZWN0YWN0aW9uLyk/KHJlZGVlbWxhbmRpbmdwYWdlfGZyZWVwcm9kdWN0Y29kZXdpemFyZHxjaGVja2ZvcnByZW9yZGVyc3xzaG93ZGlhbG9nZm9ycmVkZWVtfGJ1eW9uZWdldG9uZXxjaGVja2ZvcnB1cmNoYXNlc2F1dGh8YXJ0aXN0Y29ubmVjdHxyZWpvaW5hcnRpc3Rjb25uZWN0fG9wdGludG9jb25uZWN0aW9uc3xyZWpvaW5vcHRpbnRvY29ubmVjdGlvbnN8b3B0aW50b3BpbmcpPC9zdHJpbmc+CiAgICA8c3RyaW5nPl4vKFthLXpdW2Etel0vKT8oYWxidW18YXJ0aXN0fGF1ZGlvYm9va3xhdWRpb2Jvb2tzfGF1dGhvcnxib29rfGJyb3dzZXxjYXRlZ29yeXxjZWxlYnJpdHktcGxheWxpc3RzfGNoYXJ0c3xjb2xsYWJvcmF0aW9ufGNvbGxlY3Rpb258Y29sbGVjdGlvbnN8Y29tcG9zZXJ8Y3VzdG9tZXItcmV2aWV3c3xkaXJlY3Rvcnxlc3NlbnRpYWx8ZXNzZW50aWFsc3xmYXF8Z2VucmV8aW1peHxpbWl4ZXN8bW92aWV8bW92aWUtcmVudGFsc3xtb3ZpZXN8bXVzaWN8bXVzaWMtdmlkZW98cGxheWxpc3R8cG9kY2FzdHxwb2RjYXN0c3xwcmVvcmRlcnxwcm9tb3Rpb258cmV2aWV3fHJldmlld3N8c3RvcmV8c3R1ZGlvfHR2LXNlYXNvbnx0di1zaG93fHR2LXNob3dzfHZpZGVvfGl0dW5lcy11fGluc3RpdHV0aW9ufG9wdGludG9jb25uZWN0aW9uc3xvcHRpbnRvcGluZykoL3xcP3wkKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpjb250ZW50bGluay53b2Evd2EvbGluayhcP3wkKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpjb25uZWN0aW9ucy53b2Evd2EvPC9zdHJpbmc+CiAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9tenVzZXJwdWJsaXNoaW5nLndvYS93YS8obWFuYWdlYXJ0aXN0YWxlcnRzKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpwZXJzb25hbGl6ZXIud29hL3dhLyhteWFsZXJ0cyk8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLWFwcHN0b3JlLWhvc3QtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPigoYnV5fG15fHNlYXJjaHxjKVwuKT9pdHVuZXNcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICA8c3RyaW5nPnBob2Jvc1wuYXBwbGVcLmNvbSQ8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLWFwcHN0b3JlLXBhdGgtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPlsmYW1wOz9dKG10PTh8bWVkaWE9c29mdHdhcmUpKCZhbXA7fCQpPC9zdHJpbmc+CiAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9tenNvZnR3YXJldXBkYXRlLndvYS93YS8oYXZhaWxhYmxlc29mdHdhcmV1cGRhdGVzKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHZpZXdzb2Z0d2FyZXxwYW5kYXN0b3JlZnJvbnR8dmlld2ZlYXR1cmVkc29mdHdhcmVjYXRlZ29yaWVzKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpmaW5hbmNlLndvYS93YS8oY29tLmFwcGxlLmppbmdsZS5hcHAuZmluYW5jZS5kaXJlY3RhY3Rpb24vKT8odmVyaWZ5YWNjb3VudGVtYWlsKTwvc3RyaW5nPgogICAgPHN0cmluZz5eLyhbYS16XVthLXpdLyk/KGFwcHxhcHBzLXN0b3JlfGRldmVsb3BlcikoL3xcP3wkKTwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5wMi1sYXVuY2gtZWJvb2tzdG9yZS1ob3N0LXBhdHRlcm5zPC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz4oKGJ1eXxteXxzZWFyY2h8YylcLik/aXR1bmVzXC5hcHBsZVwuY29tJDwvc3RyaW5nPgogICAgPHN0cmluZz5waG9ib3NcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PnAyLWxhdW5jaC1lYm9va3N0b3JlLXBhdGgtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPlsmYW1wOz9dKG10PTExfG1lZGlhPWVib29rKSgmYW1wO3wkKTwvc3RyaW5nPgogICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHZpZXdib29rKTwvc3RyaW5nPgogICAgPHN0cmluZz5eLyhbYS16XVthLXpdLyk/KGJvb2spKC98XD98JCk8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLWFwcGxlLXN0b3JlLWhvc3QtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPl4oc3RvcmV8cmVzZXJ2ZSlbLl1hcHBsZVsuXWNvbSQ8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+cDItbGF1bmNoLWFwcGxlLXN0b3JlLXBhdGgtcGF0dGVybnM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPl4vKFteL10rLyk/eGMvPC9zdHJpbmc+CiAgICA8c3RyaW5nPl5bXj9dKi9yZXNlcnZlcHJvZHVjdChcP3wkKTwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5wMi11cmwtcmVzb2x1dGlvbjwva2V5PgogIDxhcnJheT4KICAgIDxkaWN0PgogICAgICA8a2V5PnAyLXVybC1zZWN0aW9uLW5hbWU8L2tleT48c3RyaW5nPkVCb29rczwvc3RyaW5nPgogICAgICA8a2V5Pmhvc3Qtc3VmZml4LXdoaXRlbGlzdDwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz4uYXBwbGUuY29tPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+aG9zdC1wYXR0ZXJuczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz4oKGJ1eXxteXxzZWFyY2h8YylcLik/aXR1bmVzXC5hcHBsZVwuY29tJDwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+cGhvYm9zXC5hcHBsZVwuY29tJDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnBhdGgtcGF0dGVybnM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+WyZhbXA7P10obXQ9MTF8bWVkaWE9ZWJvb2spKCZhbXA7fCQpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHZpZXdib29rKTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+Xi8oW2Etel1bYS16XS8pPyhib29rKSgvfFw/fCQpPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+c2NoZW1lLW1hcHBpbmc8L2tleT4KICAgICAgPGRpY3Q+CiAgICAgICAgPGtleT5odHRwPC9rZXk+PHN0cmluZz5pdG1zLWJvb2s8L3N0cmluZz4KICAgICAgICA8a2V5Pmh0dHBzPC9rZXk+PHN0cmluZz5pdG1zLWJvb2tzPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgIDwvZGljdD4KICAgIDxkaWN0PgogICAgICA8a2V5PnAyLXVybC1zZWN0aW9uLW5hbWU8L2tleT48c3RyaW5nPk1vYmlsZVNvZnR3YXJlQXBwbGljYXRpb25zPC9zdHJpbmc+CiAgICAgIDxrZXk+aG9zdC1zdWZmaXgtd2hpdGVsaXN0PC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPi5hcHBsZS5jb208L3N0cmluZz4KICAgICAgPC9hcnJheT4KICAgICAgPGtleT5ob3N0LXBhdHRlcm5zPC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPigoYnV5fG15fHNlYXJjaHxjKVwuKT9pdHVuZXNcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5waG9ib3NcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+cGF0aC1wYXR0ZXJuczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5bJmFtcDs/XShtdD04fG1lZGlhPXNvZnR3YXJlKSgmYW1wO3wkKTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+Xi93ZWJvYmplY3RzL216c29mdHdhcmV1cGRhdGUud29hL3dhLyhhdmFpbGFibGVzb2Z0d2FyZXVwZGF0ZXMpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHZpZXdzb2Z0d2FyZXxwYW5kYXN0b3JlZnJvbnR8dmlld2ZlYXR1cmVkc29mdHdhcmVjYXRlZ29yaWVzKTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+Xi93ZWJvYmplY3RzL216ZmluYW5jZS53b2Evd2EvKGNvbS5hcHBsZS5qaW5nbGUuYXBwLmZpbmFuY2UuZGlyZWN0YWN0aW9uLyk/KHZlcmlmeWFjY291bnRlbWFpbCk8L3N0cmluZz4KICAgICAgICA8c3RyaW5nPl4vKFthLXpdW2Etel0vKT8oYXBwfGFwcHMtc3RvcmV8ZGV2ZWxvcGVyKSgvfFw/fCQpPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+c2NoZW1lLW1hcHBpbmc8L2tleT4KICAgICAgPGRpY3Q+CiAgICAgICAgPGtleT5odHRwPC9rZXk+PHN0cmluZz5pdG1zLWFwcHM8L3N0cmluZz4KICAgICAgICA8a2V5Pmh0dHBzPC9rZXk+PHN0cmluZz5pdG1zLWFwcHNzPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgIDwvZGljdD4KICAgIDxkaWN0PgogICAgICA8a2V5PnAyLXVybC1zZWN0aW9uLW5hbWU8L2tleT48c3RyaW5nPk11c2ljPC9zdHJpbmc+CiAgICAgIDxrZXk+aG9zdC1zdWZmaXgtd2hpdGVsaXN0PC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPi5hcHBsZS5jb208L3N0cmluZz4KICAgICAgPC9hcnJheT4KICAgICAgPGtleT5ob3N0LXBhdHRlcm5zPC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPigoYnV5fG15fHNlYXJjaHxjKVwuKT9pdHVuZXNcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5waG9ib3NcLmFwcGxlXC5jb20kPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICAgIDxrZXk+cGF0aC1wYXR0ZXJuczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzdG9yZS53b2Evd2EvKHN0b3JlZnJvbnR8dmlld3RvcHRlbnNsaXN0fHZpZXd0b3BmaWZ0eXx2aWV3dG9wfHZpZXdhdWRpb2Jvb2t8dmlld2dyb3VwaW5nfHZpZXdnZW5yZXx2aWV3cGxheWxpc3RzcGFnZXx2aWV3cm9vbXx2aWV3YWxidW18dmlld3BvZGNhc3R8dmlld21peHxzdG9yZWZyb250c3x2aWV3Y29udGVudHN1c2VycmV2aWV3c3x2aWV3ZXVsYXx2aWV3dHZzaG93fHZpZXd0dnNlYXNvbnx2aWV3bW92aWV8dmlld3ZpZGVvfGZvb3RlcnNlY3Rpb25zfGxpYnJhcnlsaW5rfHZpZXdmZWF0dXJlfHZpZXdhcnRpc3QpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpzZWFyY2gud29hL3dhLyhzZWFyY2h8YWR2YW5jZWRzZWFyY2gpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXooZmFzdCk/ZmluYW5jZS53b2Evd2EvKGNvbS5hcHBsZS5qaW5nbGUuYXBwLmZpbmFuY2UuZGlyZWN0YWN0aW9uLyk/KHJlZGVlbWxhbmRpbmdwYWdlfGZyZWVwcm9kdWN0Y29kZXdpemFyZHxjaGVja2ZvcnByZW9yZGVyc3xzaG93ZGlhbG9nZm9ycmVkZWVtfGJ1eW9uZWdldG9uZXxjaGVja2ZvcnB1cmNoYXNlc2F1dGh8YXJ0aXN0Y29ubmVjdHxyZWpvaW5hcnRpc3Rjb25uZWN0fG9wdGludG9jb25uZWN0aW9uc3xyZWpvaW5vcHRpbnRvY29ubmVjdGlvbnN8b3B0aW50b3BpbmcpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eLyhbYS16XVthLXpdLyk/KGFsYnVtfGFydGlzdHxhdWRpb2Jvb2t8YXVkaW9ib29rc3xhdXRob3J8Ym9va3xicm93c2V8Y2F0ZWdvcnl8Y2VsZWJyaXR5LXBsYXlsaXN0c3xjaGFydHN8Y29sbGFib3JhdGlvbnxjb2xsZWN0aW9ufGNvbGxlY3Rpb25zfGNvbXBvc2VyfGN1c3RvbWVyLXJldmlld3N8ZGlyZWN0b3J8ZXNzZW50aWFsfGVzc2VudGlhbHN8ZmFxfGdlbnJlfGltaXh8aW1peGVzfG1vdmllfG1vdmllLXJlbnRhbHN8bW92aWVzfG11c2ljfG11c2ljLXZpZGVvfHBsYXlsaXN0fHBvZGNhc3R8cG9kY2FzdHN8cHJlb3JkZXJ8cHJvbW90aW9ufHJldmlld3xyZXZpZXdzfHN0b3JlfHN0dWRpb3x0di1zZWFzb258dHYtc2hvd3x0di1zaG93c3x2aWRlb3xpdHVuZXMtdXxpbnN0aXR1dGlvbnxvcHRpbnRvY29ubmVjdGlvbnN8b3B0aW50b3BpbmcpKC98XD98JCk8L3N0cmluZz4KICAgICAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9temNvbnRlbnRsaW5rLndvYS93YS9saW5rKFw/fCQpPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXpjb25uZWN0aW9ucy53b2Evd2EvPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5eL3dlYm9iamVjdHMvbXp1c2VycHVibGlzaGluZy53b2Evd2EvKG1hbmFnZWFydGlzdGFsZXJ0cyk8L3N0cmluZz4KICAgICAgICA8c3RyaW5nPl4vd2Vib2JqZWN0cy9tenBlcnNvbmFsaXplci53b2Evd2EvKG15YWxlcnRzKTwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnNjaGVtZS1tYXBwaW5nPC9rZXk+CiAgICAgIDxkaWN0PgogICAgICAgIDxrZXk+aHR0cDwva2V5PjxzdHJpbmc+aXRtczwvc3RyaW5nPgogICAgICAgIDxrZXk+aHR0cHM8L2tleT48c3RyaW5nPml0bXNzPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgIDwvZGljdD4KICA8L2FycmF5PgogIDxrZXk+cDItbXVzaWMtc3RvcmUtYXZhaWxhYmxlPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICA8a2V5PnAyLXNvZnR3YXJlLXN0b3JlLWF2YWlsYWJsZTwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5wMi1wYW5kYS1zdG9yZWZyb250PC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3BhbmRhU3RvcmVGcm9udDwvc3RyaW5nPgogIDxrZXk+cDItcGFuZGEtZ2VucmVzPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdGZWF0dXJlZFNvZnR3YXJlQ2F0ZWdvcmllczwvc3RyaW5nPgogIDxrZXk+cDItcGFuZGEtdG9wLWNoYXJ0czwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VG9wP2dlbnJlSWQ9MzY8L3N0cmluZz4KICA8a2V5PnAyLXBhbmRhLXRvcC1maWZ0eTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VG9wRmlmdHk/Z2VucmVJZD0zNjwvc3RyaW5nPgogIDxrZXk+cDItcGFuZGEtdXBkYXRlczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3UGFuZGFVcGRhdGVzPC9zdHJpbmc+CiAgPGtleT5wMi1wYW5kYS1zZWFyY2g8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zZWFyY2guaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU2VhcmNoLndvYS93YS9zZWFyY2g/bWVkaWE9c29mdHdhcmU8L3N0cmluZz4KICA8a2V5PnAyLXBhbmRhLXNlYXJjaEhpbnRzPC9rZXk+PHN0cmluZz5odHRwOi8vYXguc2VhcmNoLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlNlYXJjaEhpbnRzLndvYS93YS9oaW50cz9tZWRpYT1zb2Z0d2FyZTwvc3RyaW5nPgogIDxrZXk+YXZhaWxhYmxlLXNvZnR3YXJlLXVwZGF0ZXM8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zdS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTb2Z0d2FyZVVwZGF0ZS53b2Evd2EvYXZhaWxhYmxlU29mdHdhcmVVcGRhdGVzPC9zdHJpbmc+CiAgPGtleT5hdmFpbGFibGUtc29mdHdhcmUtdXBkYXRlcy1odG1sPC9rZXk+PHN0cmluZz5odHRwOi8vYXguc3UuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU29mdHdhcmVVcGRhdGUud29hL3dhL3ZpZXdTb2Z0d2FyZVVwZGF0ZXM8L3N0cmluZz4KICA8a2V5PmF2YWlsYWJsZS1zb2Z0d2FyZS1jaGVjay1vbi1sYXVuY2g8L2tleT48c3RyaW5nPllFUzwvc3RyaW5nPgogIDxrZXk+YXZhaWxhYmxlLXNvZnR3YXJlLXVwZGF0ZXMtcmVsb2FkLWZyZXF1ZW5jeTwva2V5PjxpbnRlZ2VyPjg0PC9pbnRlZ2VyPgogIDxrZXk+YXZhaWxhYmxlLXNvZnR3YXJlLXVwZGF0ZXMtY29tcHJlc3MtcmVxdWVzdDwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5wMi1hcHBsaWNhdGlvbi11c2VyLXJldmlldy1pbmZvPC9rZXk+PHN0cmluZz5odHRwczovL3VzZXJwdWIuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aVXNlclB1Ymxpc2hpbmcud29hL3dhL3VzZXJSZXZpZXdJbmZvP3R5cGU9UHVycGxlK1NvZnR3YXJlJmFtcDthbXA7ZGlzcGxheWFibGUta2luZD0xMTwvc3RyaW5nPgogIDxrZXk+cDItY2FwYWJpbGl0aWVzLWRpYWxvZzwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9jYXBhYmlsaXRpZXNEaWFsb2c8L3N0cmluZz4KICA8a2V5PnAyLWFjY2Vzc29yeS1yb29tPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdBY2Nlc3NvcnlSb29tPC9zdHJpbmc+CiAgPGtleT5wMi1wcm9kdWN0LW9mZmVyczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9mZXRjaFNvZnR3YXJlQWRkT25zPC9zdHJpbmc+CiAgPGtleT5wMi1wcm9kdWN0LW9mZmVycy1iYXRjaC1saW1pdDwva2V5PjxpbnRlZ2VyPjEwMDwvaW50ZWdlcj4KICA8a2V5PnAyLWFwcC1nZW5pdXMtc3RhdGlzdGljczwva2V5PgogIDxkaWN0PgogICAgPGtleT5hbGxvd2VkLWNvbm5lY3Rpb24tdHlwZXM8L2tleT4KICAgIDxkaWN0PgogICAgICA8a2V5PjNHPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KICAgICAgPGtleT4yRzwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgICAgIDxrZXk+V2lGaTwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgICA8L2RpY3Q+CiAgICA8a2V5PnVybDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9nZW5pdXMuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL1VDQXBwQ2hhbm5lbC53b2Evd2EvYXBwU3RhdHM8L3N0cmluZz4KICAgIDxrZXk+cG9zdC1pbnRlcnZhbDwva2V5PjxpbnRlZ2VyPjE0NDAwPC9pbnRlZ2VyPgogICAgPGtleT5zZW5kLWRhdGEtdXNhZ2U8L2tleT48c3RyaW5nPk5PPC9zdHJpbmc+CiAgPC9kaWN0PgogIDxrZXk+Y2xpZW50LWNhY2hlLWRlZmluaXRpb25zPC9rZXk+CiAgPGRpY3Q+CiAgICA8a2V5PmNhY2hlczwva2V5PgogICAgPGFycmF5PgogICAgICA8ZGljdD4KICAgICAgICA8a2V5PnR5cGU8L2tleT48c3RyaW5nPmNsaWVudC1jYWNoZS1kZWZpbml0aW9uPC9zdHJpbmc+CiAgICAgICAgPGtleT5tZW1vcnktc2l6ZTwva2V5PjxpbnRlZ2VyPjE1NzI4NjQ8L2ludGVnZXI+CiAgICAgICAgPGtleT5kaXNrLXNpemU8L2tleT48aW50ZWdlcj4xNTcyODY0PC9pbnRlZ2VyPgogICAgICAgIDxrZXk+cGVyc2lzdGVudC1pZDwva2V5PjxzdHJpbmc+QjNDQnNjcmlwdENhY2hlPC9zdHJpbmc+CiAgICAgICAgPGtleT5jbGllbnRzPC9rZXk+CiAgICAgICAgPGFycmF5PgogICAgICAgICAgPHN0cmluZz5Tb2Z0d2FyZTwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5lQm9va3M8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+V2lGaS1NdXNpYzwvc3RyaW5nPgogICAgICAgIDwvYXJyYXk+CiAgICAgICAgPGtleT5maWxlLWV4dGVuc2lvbnM8L2tleT4KICAgICAgICA8YXJyYXk+CiAgICAgICAgICA8c3RyaW5nPmNzczwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5jc3N6PC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPmpzPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPmpzejwvc3RyaW5nPgogICAgICAgIDwvYXJyYXk+CiAgICAgIDwvZGljdD4KICAgICAgPGRpY3Q+CiAgICAgICAgPGtleT50eXBlPC9rZXk+PHN0cmluZz5jbGllbnQtY2FjaGUtZGVmaW5pdGlvbjwvc3RyaW5nPgogICAgICAgIDxrZXk+bWVtb3J5LXNpemU8L2tleT48aW50ZWdlcj4yMDk3MTUyPC9pbnRlZ2VyPgogICAgICAgIDxrZXk+ZGlzay1zaXplPC9rZXk+PGludGVnZXI+MjA5NzE1MjwvaW50ZWdlcj4KICAgICAgICA8a2V5PnBlcnNpc3RlbnQtaWQ8L2tleT48c3RyaW5nPkIzQ0JpbWFnZUNhY2hlPC9zdHJpbmc+CiAgICAgICAgPGtleT5jbGllbnRzPC9rZXk+CiAgICAgICAgPGFycmF5PgogICAgICAgICAgPHN0cmluZz5Tb2Z0d2FyZTwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5lQm9va3M8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+V2lGaS1NdXNpYzwvc3RyaW5nPgogICAgICAgIDwvYXJyYXk+CiAgICAgICAgPGtleT51cmwtcGF0dGVybnM8L2tleT4KICAgICAgICA8YXJyYXk+CiAgICAgICAgICA8c3RyaW5nPnNwcml0ZXMtazItc3RvcmVmcm9udC5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX2JsdWVfcHJlc3NlZC5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX2JsdWUucG5nPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPm1pZGRsZV9ncmF5X3ByZXNzZWQucG5nPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPm1pZGRsZV9ncmF5LnBuZzwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5taWRkbGVfZ3JlZW5fcHJlc3NlZC5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX2dyZWVuLnBuZzwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5taWRkbGVfZGFya2dyYXlfcHJlc3NlZC5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX3NpbHZlcl9wcmVzc2VkLnBuZzwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5hY3Rpb24tYnV0dG9uLWJnLnBuZzwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5hY3Rpb24tYnV0dG9uLWJnLXByZXNzZWQucG5nPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPm1pZGRsZV9kYXJrZ3JheS5wbmc8L3N0cmluZz4KICAgICAgICAgIDxzdHJpbmc+bWlkZGxlX3NpbHZlci5wbmc8L3N0cmluZz4KICAgICAgICA8L2FycmF5PgogICAgICA8L2RpY3Q+CiAgICAgIDxkaWN0PgogICAgICAgIDxrZXk+dHlwZTwva2V5PjxzdHJpbmc+Y2xpZW50LWNhY2hlLWRlZmluaXRpb248L3N0cmluZz4KICAgICAgICA8a2V5Pm1lbW9yeS1zaXplPC9rZXk+PGludGVnZXI+MjA5NzE1MjwvaW50ZWdlcj4KICAgICAgICA8a2V5PnBlcnNpc3RlbnQtaWQ8L2tleT48c3RyaW5nPkIzQ0JtaXNjQ2FjaGU8L3N0cmluZz4KICAgICAgICA8a2V5PmNsaWVudHM8L2tleT4KICAgICAgICA8YXJyYXk+CiAgICAgICAgICA8c3RyaW5nPlNvZnR3YXJlPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPmVCb29rczwvc3RyaW5nPgogICAgICAgICAgPHN0cmluZz5XaUZpLU11c2ljPC9zdHJpbmc+CiAgICAgICAgPC9hcnJheT4KICAgICAgPC9kaWN0PgogICAgPC9hcnJheT4KICA8L2RpY3Q+CiAgPGtleT5wbGF0Zm9ybS1ncmFkaWVudHM8L2tleT4KICA8ZGljdD4KICAgIDxrZXk+ZUJvb2tzPC9rZXk+CiAgICA8ZGljdD4KICAgICAgPGtleT5wYWdlPC9rZXk+CiAgICAgIDxkaWN0PgogICAgICAgIDxrZXk+dG9wLWNvbG9yPC9rZXk+PHN0cmluZz5yZ2IoMjExLDIxNSwyMTgpPC9zdHJpbmc+CiAgICAgICAgPGtleT5ib3R0b20tY29sb3I8L2tleT48c3RyaW5nPnJnYigyMTEsMjE1LDIxOCk8L3N0cmluZz4KICAgICAgPC9kaWN0PgogICAgPC9kaWN0PgogIDwvZGljdD4KICA8a2V5PnZpZXctbW9iaWxlLXNvZnR3YXJlLXVwZGF0ZXM8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zdS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTb2Z0d2FyZVVwZGF0ZS53b2Evd2Evdmlld0FsbEF2YWlsYWJsZVNvZnR3YXJlVXBkYXRlczwvc3RyaW5nPgogIDxrZXk+bm93LXBsYXlpbmctdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL25vd1BsYXlpbmc8L3N0cmluZz4KICA8a2V5Pm5vdy1wbGF5aW5nLW5ldHdvcmstZGV0ZWN0LXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9ub3dQbGF5aW5nPC9zdHJpbmc+CiAgPGtleT5hZGFtaWQtbG9va3VwLXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9hZGFtSWRMb29rdXA8L3N0cmluZz4KICA8a2V5PnJlbnRhbC1yZWNvbW1lbmRhdGlvbnM8L2tleT48c3RyaW5nPmh0dHA6Ly9teS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpQZXJzb25hbGl6ZXIud29hL3dhL3JlbnRhbFJlY29tbWVuZGF0aW9uczwvc3RyaW5nPgogIDxrZXk+cmVudGFsLW1haW48L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1JlbnRhbE1haW48L3N0cmluZz4KICA8a2V5PnR2LXJlbnRhbC1tYWluPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdUdlJlbnRhbE1haW4/cz0xNDM0NDE8L3N0cmluZz4KICA8a2V5PnZpZXdUVlNlYXNvbjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VFZTZWFzb248L3N0cmluZz4KICA8a2V5PnZpZXdUVlNob3c8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1RWU2hvdzwvc3RyaW5nPgogIDxrZXk+dmlld01vdmllPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdNb3ZpZTwvc3RyaW5nPgogIDxrZXk+dmlld0dhbWU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0dhbWU8L3N0cmluZz4KICA8a2V5PnZpZXdQcmVvcmRlcjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3UHJlb3JkZXI8L3N0cmluZz4KICA8a2V5Pm5pa2UtcGx1cy1sYW5kaW5nLXBhZ2U8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0N1c3RvbVBhZ2U/bmFtZT1wYWdlTmlrZTwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtYWNjZXB0aW5nLXJlcXVlc3RzPC9rZXk+PHN0cmluZz5odHRwczovL2dlbml1cy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvVUNHb3Zlcm5vci53b2Evd2EvbGlicmFyeVVwZGF0ZUFjY2VwdGluZ1JlcXVlc3RzPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1yZXF1ZXN0PC9rZXk+PHN0cmluZz5odHRwczovL2dlbml1cy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvVUNHb3Zlcm5vci53b2Evd2EvcmVxdWVzdExpYnJhcnlVcGRhdGU8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLWNoZWNrPC9rZXk+PHN0cmluZz5odHRwczovL2dlbml1cy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvVUNHb3Zlcm5vci53b2Evd2EvY2hlY2tVcGRhdGVQcm9jZXNzaW5nU3RhdHVzPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1tZWRpYS10eXBlczwva2V5PjxzdHJpbmc+Ym9vayxmZWF0dXJlLW1vdmllLG11c2ljLXZpZGVvLHBvZGNhc3QtZmVlZCxwb2RjYXN0LWVwaXNvZGUsc29uZyx0di1lcGlzb2RlPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1maWVsZHM8L2tleT48c3RyaW5nPmFkZGVkLWRhdGUsYWxidW0tcmF0aW5nLGFsYnVtLXJhdGluZy1jb21wdXRlZCxhcnRpc3QtaWQsYXJ0aXN0LW5hbWUsY2RkYi1maW5nZXJwcmludCxjZGRiLWZpbmdlcnByaW50LW5vdC1hdmFpbCxjZGRiLW1lZGlhLWlkLGNkZGItbXVpZCxjZGRiLXRvYyxjZGRiLXR1aWQsY2RkYi10dWlkLXRhZyxjb21wb3Nlci1uYW1lLGR1cmF0aW9uLGVpZCxlcGlzb2RlLWlkLGVwaXNvZGUtbnVtYmVyLGV4Y2x1ZGUtZnJvbS1zaHVmZmxlLGZlZWQtdXJsLGZpbGVuYW1lLGdlbml1cy1wbGF5LWNvdW50LGdlbnJlLW5hbWUsZ3JhbmRwYXJlbnQtZGlyLGl0ZW0tY2hlY2tlZCxpdGVtLWlkLGl0ZW0tbmFtZSxraW5kLGxhY2tzLWNvdmVyLWFydCxsYXN0LXBsYXllZC1kYXRlLGxhc3Qtc2tpcHBlZC1kYXRlLGxvbmctZGVzY3JpcHRpb24sbWF0Y2gtaWQscGFyZW50LWRpcixwZXJzaXN0ZW50LWlkLHBsYXktY291bnQscGxheWxpc3QtaWQscGxheWxpc3QtbmFtZSxwb2RjYXN0LWNhdGVnb3J5LHBvZGNhc3QtZ3VpZCxwb2RjYXN0LWlkLHByb3RlY3RlZCxyZW50YWwsc2Vhc29uLW51bWJlcixzaG93LHNraXAtY291bnQsdHJhY2stbnVtYmVyLHRyYWNrLWNvdW50LHVzZXItcmF0aW5nLHVzZXItcmF0aW5nLWNvbXB1dGVkLHZhbGlkLWZpZWxkcyx5ZWFyPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1jb3JyZWxhdGlvbi1maWVsZHM8L2tleT48c3RyaW5nPmFkZGVkLWRhdGUsYWxidW0tcmF0aW5nLGFsYnVtLXJhdGluZy1jb21wdXRlZCxsYXN0LXBsYXllZC1kYXRlLGxhc3Qtc2tpcHBlZC1kYXRlLHBsYXktY291bnQsc2tpcC1jb3VudCx1c2VyLXJhdGluZyx1c2VyLXJhdGluZy1jb21wdXRlZDwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtbWF0Y2hpbmctZmllbGRzPC9rZXk+PHN0cmluZz5hcnRpc3QtbmFtZSxjZGRiLWZpbmdlcnByaW50LGNkZGItZmluZ2VycHJpbnQtbm90LWF2YWlsLCBjZGRiLW1lZGlhLWlkLGNkZGItbXVpZCxjZGRiLXRvYyxjZGRiLXR1aWQsY2RkYi10dWlkLXRhZyxjb21wb3Nlci1uYW1lLGR1cmF0aW9uLGVpZCxmaWxlbmFtZSxnZW5yZS1uYW1lLGdyYW5kcGFyZW50LWRpcixpdGVtLWNoZWNrZWQsaXRlbS1pZCxpdGVtLW5hbWUsa2luZCxtYXRjaC1pZCxwYXJlbnQtZGlyLHBlcnNpc3RlbnQtaWQscGxheWxpc3QtbmFtZSxwcm90ZWN0ZWQsdHJhY2stbnVtYmVyLHRyYWNrLWNvdW50LHllYXI8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLW1pbmltdW0tZmllbGRzPC9rZXk+PHN0cmluZz5hcnRpc3QtbmFtZSxjZGRiLWZpbmdlcnByaW50LGNkZGItZmluZ2VycHJpbnQtbm90LWF2YWlsLCBjZGRiLW1lZGlhLWlkLGNkZGItbXVpZCxjZGRiLXRvYyxjZGRiLXR1aWQsY2RkYi10dWlkLXRhZyxjb21wb3Nlci1uYW1lLGR1cmF0aW9uLGVpZCxmaWxlbmFtZSxnZW5yZS1uYW1lLGdyYW5kcGFyZW50LWRpcixpdGVtLWNoZWNrZWQsaXRlbS1pZCxpdGVtLW5hbWUsa2luZCxtYXRjaC1pZCxwYXJlbnQtZGlyLHBlcnNpc3RlbnQtaWQscGxheWxpc3QtbmFtZSxwcm90ZWN0ZWQsdHJhY2stbnVtYmVyLHRyYWNrLWNvdW50LHllYXI8L3N0cmluZz4KICA8a2V5PnVjLXNlcnZlci1kaXNhYmxlZDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNFcnJvcj9lcnJvcj1zZXJ2ZXJEaXNhYmxlZDwvc3RyaW5nPgogIDxrZXk+dWMtc2VydmVyLW5vdC1hY2NlcHRpbmctc2lnbnVwczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNFcnJvcj9lcnJvcj1zZXJ2ZXJOb3RBY2NlcHRpbmdTaWdudXBzPC9zdHJpbmc+CiAgPGtleT51Yy1nb3Zlcm5vci1lcnJvcjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNQcm9ncmVzcz9zdGF0ZT1lcnJvciZhbXA7c3RlcD0yPC9zdHJpbmc+CiAgPGtleT51Yy1wcm9ncmVzcy1zdG9wcGVkPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc1Byb2dyZXNzP3N0YXRlPXN0b3BwZWQ8L3N0cmluZz4KICA8a2V5PnVjLXN0ZXAtb25lPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc1Byb2dyZXNzP3N0ZXA9MTwvc3RyaW5nPgogIDxrZXk+dWMtc3RlcC10d28tc2VydmVyLXByb2Nlc3Npbmc8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RhdGU9c2VydmVycHJvY2Vzc2luZyZhbXA7c3RlcD0yPC9zdHJpbmc+CiAgPGtleT51Yy1zdGVwLXR3by11cGxvYWQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RhdGU9dXBsb2FkJmFtcDtzdGVwPTI8L3N0cmluZz4KICA8a2V5PnVjLXN0ZXAtdGhyZWU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RlcD0zPC9zdHJpbmc+CiAgPGtleT51Yy1zdWNjZXNzLXBhZ2U8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zSG93VG8/c3RhdGU9c3VjY2Vzczwvc3RyaW5nPgogIDxrZXk+dWMtaG93LXRvLXBhZ2U8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zSG93VG88L3N0cmluZz4KICA8a2V5Pmdlbml1cy1vcHQtb3V0PC9rZXk+PHN0cmluZz5odHRwczovL2dlbml1cy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvVUNHb3Zlcm5vci53b2Evd2Evb3B0T3V0TGlicmFyeTwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtc2VydmVyLWRpc2FibGVkPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc0Vycm9yP2Vycm9yPXNlcnZlckRpc2FibGVkPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1zZXJ2ZXItbm90LWFjY2VwdGluZy1zaWdudXBzPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc0Vycm9yP2Vycm9yPXNlcnZlck5vdEFjY2VwdGluZ1NpZ251cHM8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLWdvdmVybm9yLWVycm9yPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3VzZXJDb2xsZWN0aW9uc1Byb2dyZXNzP3N0YXRlPWVycm9yJmFtcDtzdGVwPTI8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLXN0b3BwZWQ8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RhdGU9c3RvcHBlZDwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtc3RlcC1vbmU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvdXNlckNvbGxlY3Rpb25zUHJvZ3Jlc3M/c3RlcD0xPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1zdGVwLXR3by1zZXJ2ZXItcHJvY2Vzc2luZzwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNQcm9ncmVzcz9zdGF0ZT1zZXJ2ZXJwcm9jZXNzaW5nJmFtcDtzdGVwPTI8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLXN0ZXAtdHdvLXVwbG9hZDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNQcm9ncmVzcz9zdGF0ZT11cGxvYWQmYW1wO3N0ZXA9Mjwvc3RyaW5nPgogIDxrZXk+bGlicmFyeS11cGRhdGUtc3RlcC10aHJlZTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNQcm9ncmVzcz9zdGVwPTM8L3N0cmluZz4KICA8a2V5PmxpYnJhcnktdXBkYXRlLXN1Y2Nlc3MtcGFnZTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNIb3dUbz9zdGF0ZT1zdWNjZXNzPC9zdHJpbmc+CiAgPGtleT5saWJyYXJ5LXVwZGF0ZS1ob3ctdG8tcGFnZTwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS91c2VyQ29sbGVjdGlvbnNIb3dUbzwvc3RyaW5nPgogIDxrZXk+c2lkZWJhci1mYWxsYmFjazwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9zaWRlYmFyRGVmYXVsdDwvc3RyaW5nPgogIDxrZXk+c2lkZWJhci10aW1lb3V0PC9rZXk+PGludGVnZXI+NTwvaW50ZWdlcj4KICA8a2V5PnNpZGViYXItd2VsY29tZTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnNpZGViYXIuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU2lkZWJhci53b2Evd2Evc2lkZWJhcldlbGNvbWU8L3N0cmluZz4KICA8a2V5PnNpZGViYXItbWF0Y2gtcnVsZXM8L2tleT4KICA8YXJyYXk+CiAgICA8ZGljdD4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9zaWRlYmFyTWF0Y2g8L3N0cmluZz4KICAgICAgPGtleT5vcHRpb25hbC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+cDwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+YTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+a2luZDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnJlcXVpcmVkLWZpZWxkczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5pZDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgPC9kaWN0PgogICAgPGRpY3Q+CiAgICAgIDxrZXk+dXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd2Evc2lkZWJhck1hdGNoPC9zdHJpbmc+CiAgICAgIDxrZXk+b3B0aW9uYWwtZmllbGRzPC9rZXk+CiAgICAgIDxhcnJheT4KICAgICAgICA8c3RyaW5nPmtpbmQ8L3N0cmluZz4KICAgICAgPC9hcnJheT4KICAgICAgPGtleT5yZXF1aXJlZC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+Y2RkYi10dWlkPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICA8L2RpY3Q+CiAgICA8ZGljdD4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9zaWRlYmFyTWF0Y2g8L3N0cmluZz4KICAgICAgPGtleT5vcHRpb25hbC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+dG51bTwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+a2luZDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnJlcXVpcmVkLWZpZWxkczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5jZGRiPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICA8L2RpY3Q+CiAgICA8ZGljdD4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9zaWRlYmFyTWF0Y2g8L3N0cmluZz4KICAgICAgPGtleT5vcHRpb25hbC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+YW48L3N0cmluZz4KICAgICAgICA8c3RyaW5nPmduPC9zdHJpbmc+CiAgICAgICAgPHN0cmluZz5wbjwvc3RyaW5nPgogICAgICAgIDxzdHJpbmc+a2luZDwvc3RyaW5nPgogICAgICA8L2FycmF5PgogICAgICA8a2V5PnJlcXVpcmVkLWZpZWxkczwva2V5PgogICAgICA8YXJyYXk+CiAgICAgICAgPHN0cmluZz5uPC9zdHJpbmc+CiAgICAgIDwvYXJyYXk+CiAgICA8L2RpY3Q+CiAgICA8ZGljdD4KICAgICAgPGtleT5vcHRpb25hbC1maWVsZHM8L2tleT4KICAgICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+ZHA8L3N0cmluZz4KICAgICAgICA8c3RyaW5nPmtpbmQ8L3N0cmluZz4KICAgICAgPC9hcnJheT4KICAgICAgPGtleT51cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5zaWRlYmFyLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlNpZGViYXIud29hL3dhL3NpZGViYXI8L3N0cmluZz4KICAgIDwvZGljdD4KICA8L2FycmF5PgogIDxrZXk+c2lkZWJhci1kaXN0aW5ndWlzaGVkLXBsYXlsaXN0czwva2V5PgogIDxkaWN0PgogICAgPGtleT4yPC9rZXk+CiAgICA8ZGljdD4KICAgIDwvZGljdD4KICAgIDxrZXk+Mzwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5PjQ8L2tleT4KICAgIDxkaWN0PgogICAgPC9kaWN0PgogICAgPGtleT4yNjwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5Pjc8L2tleT4KICAgIDxkaWN0PgogICAgPC9kaWN0PgogICAgPGtleT4xOTwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5PjIwPC9rZXk+CiAgICA8ZGljdD4KICAgIDwvZGljdD4KICA8L2RpY3Q+CiAgPGtleT5zaWRlYmFyLWZhbGxiYWNrMjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9zaWRlYmFyRGVmYXVsdDwvc3RyaW5nPgogIDxrZXk+c2lkZWJhci10aW1lb3V0Mjwva2V5PjxpbnRlZ2VyPjA8L2ludGVnZXI+CiAgPGtleT5zaWRlYmFyLWRpc3Rpbmd1aXNoZWQtcGxheWxpc3RzMjwva2V5PgogIDxkaWN0PgogICAgPGtleT4xOTwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5PjQ8L2tleT4KICAgIDxkaWN0PgogICAgPC9kaWN0PgogICAgPGtleT4yNjwva2V5PgogICAgPGRpY3Q+CiAgICA8L2RpY3Q+CiAgICA8a2V5PjIwPC9rZXk+CiAgICA8ZGljdD4KICAgIDwvZGljdD4KICA8L2RpY3Q+CiAgPGtleT5wb2RjYXN0LWdldC1lcGlzb2RlPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9tZXRyaWNzL3BvZGNhc3QvZ2V0RXBpc29kZTwvc3RyaW5nPgogIDxrZXk+cG9kY2FzdC1wbGF5LWVwaXNvZGU8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL21ldHJpY3MvcG9kY2FzdC9wbGF5RXBpc29kZTwvc3RyaW5nPgogIDxrZXk+ZG93bmxvYWQtc3BlZWR0ZXN0LXBvc3QtcmVzdWx0cy11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL3VwbG9hZC9kaWFnL2F0di88L3N0cmluZz4KICA8a2V5PmRvd25sb2FkLXNwZWVkdGVzdC11cmxzPC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5odHRwOi8vYTU2OC5waG9ib3MuYXBwbGUuY29tL3VzL3IxMDAwLzAwMC9EaWFnL3Rlc3RfOE1CLm00dj9uby1zdG9yZT10cnVlPC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHA6Ly9hNTY4LnBob2Jvcy5hcHBsZS5jb20vdXMvcjEwMDAvMDAwL0RpYWcvdGVzdF84TUIubTR2PC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHA6Ly9hNTY4LnBob2Jvcy5hcHBsZS5jb20vdXMvcjEwMDAvMDAwL0RpYWcvdGVzdF84TUIubTR2PC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PmRvd25sb2FkLW1vdmllLXNwZWVkdGVzdC11cmxzPC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5odHRwOi8vYTEudi5waG9ib3MuYXBwbGUuY29tL3VzL3IxMDAwLzAwMC9EaWFnL1NURU1faGQubTR2P25vLXN0b3JlPXRydWU8L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cDovL2ExLnYucGhvYm9zLmFwcGxlLmNvbS91cy9yMTAwMC8wMDAvRGlhZy9TVEVNX2hkLm00djwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwOi8vYTEudi5waG9ib3MuYXBwbGUuY29tL3VzL3IxMDAwLzAwMC9EaWFnL1NURU1faGQubTR2PC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PnRndDwva2V5PjxzdHJpbmc+MTwvc3RyaW5nPgogIDxrZXk+ZW5kLW9mLWJvb2stdXBzZWxsLWVuYWJsZWQ8L2tleT48c3RyaW5nPllFUzwvc3RyaW5nPgogIDxrZXk+ZW5kLW9mLXBpY3R1cmUtYm9vay11cHNlbGwtZW5hYmxlZDwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5ib29rLXVwc2VsbDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9ib29rVXBzZWxsPC9zdHJpbmc+CiAgPGtleT5ib29rLWxpYnJhcnktdGl0bGU8L2tleT48c3RyaW5nPkxpYnJhcnk8L3N0cmluZz4KICA8a2V5Pmlib29rczwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3U29mdHdhcmU/aWQ9MzY0NzA5MTkzPC9zdHJpbmc+CiAgPGtleT5maW4tcG9zdHM8L2tleT48c3RyaW5nPjE8L3N0cmluZz4KICA8a2V5PnRpbWVCZXR3ZWVuSG9tZVNoYXJpbmdDb3B5QXBwcm92YWxzPC9rZXk+PGludGVnZXI+ODY0MDA8L2ludGVnZXI+CiAgPGtleT5wMi1wYW5kYS1hcHBSZWNvbW1lbmRhdGlvbnM8L2tleT48c3RyaW5nPmh0dHA6Ly9teWFwcC5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpBcHBQZXJzb25hbGl6ZXIud29hL3dhL2FwcFJlY29tbWVuZGF0aW9ucz9tdD04PC9zdHJpbmc+CiAgPGtleT5hZGtpdC1wcm9kdWN0LXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9hZGtpdFByb2R1Y3Q8L3N0cmluZz4KICA8a2V5PmNyb3NzLW1lcmNoYW5kaXNpbmctdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdDcm9zc01lcmNoYW5kaXNpbmc8L3N0cmluZz4KICA8a2V5Pmdob3N0LXJpZGluZy10aGUtd2hpcDwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5uZXRmbGl4LXRvcC1zaGVsZjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vbmV0ZmxpeC1nZW5lcmljLXNoZWxmLnhtbDwvc3RyaW5nPgogIDxrZXk+Z2hvc3QtcmlkaW5nLXRoZS13aGlwMjwva2V5PjxzdHJpbmc+WUVTPC9zdHJpbmc+CiAgPGtleT5jb25uZWN0aW9ucy11cmwtcHJlZml4ZXM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPmh0dHA6Ly9jLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cHM6Ly9jLml0dW5lcy5hcHBsZS5jb208L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cDovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpVc2VyUHJvZmlsZS53b2E8L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aVXNlclByb2ZpbGUud29hPC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHA6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evb3B0SW50b0Nvbm5lY3Rpb25zPC9zdHJpbmc+CiAgICA8c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL29wdEludG9Db25uZWN0aW9uczwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3Jlam9pbk9wdEludG9Db25uZWN0aW9uczwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9yZWpvaW5PcHRJbnRvQ29ubmVjdGlvbnM8L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cDovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9zb2NpYWxPcHRPdXQ8L3N0cmluZz4KICAgIDxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evc29jaWFsT3B0T3V0PC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PmNvbm5lY3Rpb25zLW1haW48L2tleT48c3RyaW5nPmh0dHA6Ly9pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvY29ubmVjdGlvbnNIb21lP3M9MTQzNDQxPC9zdHJpbmc+CiAgPGtleT5wMi1zb2NpYWwtbGluazwva2V5PgogIDxkaWN0PgogICAgPGtleT5saWtlLXVybDwva2V5PjxzdHJpbmc+aHR0cHM6Ly91c2VycHViLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlVzZXJQdWJsaXNoaW5nLndvYS93YS9yYXRlP2NkPXQmYW1wO3I9LTImYW1wO3BsaXN0PXQ8L3N0cmluZz4KICAgIDxrZXk+cG9zdC11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9jLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkNvbm5lY3Rpb25zLndvYS93YS92aWV3RHZQb3N0U2hlZXQ/cz0xNDM0NDE8L3N0cmluZz4KICAgIDxrZXk+aGlzdG9yeS11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly9teS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpQZXJzb25hbGl6ZXIud29hL3dhL3NvY2lhbEhpc3Rvcnk/cz0xNDM0NDE8L3N0cmluZz4KICA8L2RpY3Q+CiAgPGtleT5waW5nLW1hdGNoPC9rZXk+PHN0cmluZz5odHRwOi8vYy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpDb25uZWN0aW9ucy53b2Evd2EvcGluZ01hdGNoP3M9MTQzNDQxPC9zdHJpbmc+CiAgPGtleT5waW5nLW1hdGNoLWZpZWxkcy1saXN0PC9rZXk+CiAgPGFycmF5PgogICAgPHN0cmluZz5pZCxhLHAsZyxjZGRiLXR1aWQsYW4sY24sZ24sa2luZCxuLHBuPC9zdHJpbmc+CiAgPC9hcnJheT4KICA8a2V5PnBpbmctYWN0aW9uPC9rZXk+PHN0cmluZz5odHRwOi8vYy5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpDb25uZWN0aW9ucy53b2Evd2EvcGluZ0FjdGlvbj9zPTE0MzQ0MTwvc3RyaW5nPgogIDxrZXk+ZGEtc29vbjwva2V5PjxzdHJpbmc+aHR0cDovL2l0dW5lcy5hcHBsZS5jb20vc3RhdGljL3BhZ2VzL2FwcF9zdG9yZV9jb21pbmdfc29vbi5odG1sPC9zdHJpbmc+CiAgPGtleT51c2VyeHAtdXJsPC9rZXk+PHN0cmluZz5odHRwczovL21ldHJpY3MubXpzdGF0aWMuY29tLzwvc3RyaW5nPgogIDxrZXk+dXNlcnhwLXB1bnQtcmF0aW88L2tleT48aW50ZWdlcj4xMDAwPC9pbnRlZ2VyPgogIDxrZXk+bW9iaWxlLXVybC1oYW5kbGVyczwva2V5PgogIDxhcnJheT4KICAgIDxzdHJpbmc+aHR0cDwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwczwvc3RyaW5nPgogICAgPHN0cmluZz5pdG1zPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0bXNzPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0bXMtYXBwczwvc3RyaW5nPgogICAgPHN0cmluZz5pdG1zLWFwcHNzPC9zdHJpbmc+CiAgICA8c3RyaW5nPml0bXMtYm9va3M8L3N0cmluZz4KICAgIDxzdHJpbmc+aXRtcy1ib29rc3M8L3N0cmluZz4KICAgIDxzdHJpbmc+bWFpbHRvPC9zdHJpbmc+CiAgICA8c3RyaW5nPmxpdmVuYXRpb248L3N0cmluZz4KICAgIDxzdHJpbmc+cHJlZnM8L3N0cmluZz4KICA8L2FycmF5PgogIDxrZXk+ZHQtcHVyY2hhc2VzLXBhZ2U8L2tleT48c3RyaW5nPmh0dHBzOi8vc2UuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aU3RvcmVFbGVtZW50cy53b2Evd2EvcHVyY2hhc2VzP3M9MTQzNDQxPC9zdHJpbmc+CiAgPGtleT5taW50LW9mZmVyczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcHJlc2VudE9mZmVyczwvc3RyaW5nPgogIDxrZXk+cGVyc29uYWxpemVkLWJ1eS1idXR0b25zPC9rZXk+CiAgPGRpY3Q+CiAgICA8a2V5PmVCb29rPC9rZXk+PHN0cmluZz5odHRwczovL3NlLml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlRWxlbWVudHMud29hL3dhL2J1eUJ1dHRvbk1ldGFEYXRhP3BsaXN0UGFnZT10cnVlJmFtcDtzPTE0MzQ0MTwvc3RyaW5nPgogICAgPGtleT5zb2Z0d2FyZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9zZS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpTdG9yZUVsZW1lbnRzLndvYS93YS9idXlCdXR0b25NZXRhRGF0YT9wbGlzdFBhZ2U9dHJ1ZSZhbXA7cz0xNDM0NDE8L3N0cmluZz4KICA8L2RpY3Q+CiAgPGtleT5hdXRoZW50aWNhdGVBY2NvdW50PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9hdXRoZW50aWNhdGU8L3N0cmluZz4KICA8a2V5PmlQaG9uZUFjdGl2YXRpb248L2tleT48c3RyaW5nPmh0dHBzOi8vYWxiZXJ0LmFwcGxlLmNvbS9XZWJPYmplY3RzL0FMVW5icmljay53b2Evd2EvZGV2aWNlQWN0aXZhdGlvbjwvc3RyaW5nPgogIDxrZXk+ZGV2aWNlLWFjdGl2YXRpb248L2tleT48c3RyaW5nPmh0dHBzOi8vYWxiZXJ0LmFwcGxlLmNvbS9XZWJPYmplY3RzL0FMVW5icmljay53b2Evd2EvZGV2aWNlQWN0aXZhdGlvbjwvc3RyaW5nPgogIDxrZXk+Y2hlY2tVbmJyaWNrSGVhbHRoPC9rZXk+PHN0cmluZz5odHRwczovL2FsYmVydC5hcHBsZS5jb20vV2ViT2JqZWN0cy9BTFVuYnJpY2sud29hL3dhL0FMQWN0aXZhdGlvbk1vbml0b3IvY2hlY2tVbmJyaWNrSGVhbHRoPC9zdHJpbmc+CiAgPGtleT5hdXRob3JpemVNYWNoaW5lPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9hdXRob3JpemVNYWNoaW5lPC9zdHJpbmc+CiAgPGtleT5idXlQcm9kdWN0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpCdXkud29hL3dhL2J1eVByb2R1Y3Q8L3N0cmluZz4KICA8a2V5PmJ1eUNhcnQ8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2J1eUNhcnQ8L3N0cmluZz4KICA8a2V5PmRlYXV0aG9yaXplTWFjaGluZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvZGVhdXRob3JpemVNYWNoaW5lPC9zdHJpbmc+CiAgPGtleT5tYWNoaW5lQXV0aG9yaXphdGlvbkluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL21hY2hpbmVBdXRob3JpemF0aW9uSW5mbzwvc3RyaW5nPgogIDxrZXk+bW9kaWZ5QWNjb3VudDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYWNjb3VudFN1bW1hcnk8L3N0cmluZz4KICA8a2V5PnBlbmRpbmdTb25nczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcGVuZGluZ1NvbmdzPC9zdHJpbmc+CiAgPGtleT5zaWdudXA8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3NpZ251cFdpemFyZDwvc3RyaW5nPgogIDxrZXk+c29uZ0Rvd25sb2FkRG9uZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmFzdEZpbmFuY2Uud29hL3dhL3NvbmdEb3dubG9hZERvbmU8L3N0cmluZz4KICA8a2V5PmZvcmdvdHRlblBhc3N3b3JkPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9pRm9yZ290PC9zdHJpbmc+CiAgPGtleT5teUluZm88L2tleT48c3RyaW5nPmh0dHA6Ly9teWluZm8uY29ycC5hcHBsZS5jb20vPC9zdHJpbmc+CiAgPGtleT5ub0FPTEFjY291bnRzPC9rZXk+PGZhbHNlLz4KICA8a2V5Pm1pbnQtYWNjb3VudDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYWNjb3VudFN1bW1hcnk8L3N0cmluZz4KICA8a2V5Pm1pbnQtYWNjb3VudC1mcmFnbWVudDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYWNjb3VudFN1bW1hcnlGcmFnbWVudDwvc3RyaW5nPgogIDxrZXk+bG9nb3V0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9sb2dvdXQ8L3N0cmluZz4KICA8a2V5PmFkZFRvQ2FydDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYWRkVG9DYXJ0PC9zdHJpbmc+CiAgPGtleT5yZW1vdmVGcm9tQ2FydDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVtb3ZlRnJvbUNhcnQ8L3N0cmluZz4KICA8a2V5PnNob3BwaW5nQ2FydDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evc2hvcHBpbmdDYXJ0PC9zdHJpbmc+CiAgPGtleT5iY1VSTHM8L2tleT4KICA8YXJyYXk+CiAgICA8c3RyaW5nPmh0dHA6Ly8uaXR1bmVzLmFwcGxlLmNvbTwvc3RyaW5nPgogICAgPHN0cmluZz5odHRwOi8vd3d3LmF0ZG10LmNvbTwvc3RyaW5nPgogIDwvYXJyYXk+CiAgPGtleT5yZXBvcnRQb2RjYXN0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9yZXBvcnRQb2RjYXN0PC9zdHJpbmc+CiAgPGtleT5jaGVjay1kb3dubG9hZC1xdWV1ZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvY2hlY2tEb3dubG9hZFF1ZXVlPC9zdHJpbmc+CiAgPGtleT5zZXQtYXV0by1kb3dubG9hZDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evc2V0QXV0b0Rvd25sb2FkPC9zdHJpbmc+CiAgPGtleT5uZXctaXBvZC11c2VyPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9pUG9kUmVnaXN0cmF0aW9uPC9zdHJpbmc+CiAgPGtleT5uZXctaXBvZC11c2VyLTI8L2tleT48c3RyaW5nPmh0dHBzOi8vc2VjdXJlLm1lLmNvbS9zaWdudXAvaXR1bmVzPC9zdHJpbmc+CiAgPGtleT5uZXctdHYtdXNlcjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaVRWUmVnaXN0cmF0aW9uPC9zdHJpbmc+CiAgPGtleT5tZDUtbWlzbWF0Y2g8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL21kNU1pc21hdGNoPC9zdHJpbmc+CiAgPGtleT5yZXBvcnQtZXJyb3I8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3JlcG9ydEVycm9yRnJvbUNsaWVudDwvc3RyaW5nPgogIDxrZXk+dXBkYXRlQXNzZXQ8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3VwZGF0ZUFzc2V0PC9zdHJpbmc+CiAgPGtleT5jcmVhdGUtdG9rZW48L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NyZWF0ZVRva2VuPC9zdHJpbmc+CiAgPGtleT5jcmVhdGUtc2Vzc2lvbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvY3JlYXRlU2Vzc2lvbjwvc3RyaW5nPgogIDxrZXk+ZGlnaXRhbC1jb3B5PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9kaWdpdGFsQ29weVdpemFyZDwvc3RyaW5nPgogIDxrZXk+cDItcmVkZW1wdGlvbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcDJSZWRlZW1Db2RlPC9zdHJpbmc+CiAgPGtleT5wMi1oZWFkbGVzcy1yZWRlbXB0aW9uPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9wMkhlYWRsZXNzUmVkZWVtQ29kZTwvc3RyaW5nPgogIDxrZXk+cDItcmVkZWVtLXNlcnZpY2UtdGVybXMtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vd3d3LmFwcGxlLmNvbS9sZWdhbC9pdHVuZXMvd3cvPC9zdHJpbmc+CiAgPGtleT5wZW5kaW5nQXBwczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcGVuZGluZ0FwcHM8L3N0cmluZz4KICA8a2V5PmNoZWNrQXBwUXVldWU8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NoZWNrQXBwRG93bmxvYWRRdWV1ZTwvc3RyaW5nPgogIDxrZXk+bWFya2V0aW5nLWFjdGlvbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2Evdmlld01hcmtldGluZ1BhZ2U8L3N0cmluZz4KICA8a2V5Pm1hcmtldGluZy1hY3Rpb24tMjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9zZWN1cmUubWUuY29tL2l0dW5lc3NpZ251cDwvc3RyaW5nPgogIDxrZXk+Z2lmdFBsYXlsaXN0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9naWZ0U29uZ3NXaXphcmQ8L3N0cmluZz4KICA8a2V5PmdpdmUtcGxheWxpc3Q8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2dpZnRTb25nc1dpemFyZDwvc3RyaW5nPgogIDxrZXk+bmV3VG91Y2hVc2VyPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS90b3VjaExhbmRpbmdQYWdlP2lzRGV2aWNlU2VsZWN0ZWQ9dHJ1ZTwvc3RyaW5nPgogIDxrZXk+cmVudGFsLWNoZWNraW48L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NoZWNraW5SZW50YWw8L3N0cmluZz4KICA8a2V5PnJlbnRhbC1hY2stY2hlY2tpbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvY2hlY2tpbkFja1JlbnRhbDwvc3RyaW5nPgogIDxrZXk+cmVudGFsLWNoZWNrb3V0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jaGVja291dFJlbnRhbDwvc3RyaW5nPgogIDxrZXk+Z2V0LW5pa2l0YS1kcGluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2lQb2RUcmFuc2Zlcjwvc3RyaW5nPgogIDxrZXk+YXBwLXJlY2VpcHQtY3JlYXRlPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jcmVhdGVBcHBSZWNlaXB0PC9zdHJpbmc+CiAgPGtleT5jcmVhdGUtcmluZ3RvbmU8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NyZWF0ZVJpbmd0b25lPC9zdHJpbmc+CiAgPGtleT5yaW5ndG9uZS1pbmZvPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9pc1Jpbmd0b25lYWJsZTwvc3RyaW5nPgogIDxrZXk+cDItY29uY2Vybi1saXN0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9wMkdldFJlcG9ydEFDb25jZXJuTGlzdDwvc3RyaW5nPgogIDxrZXk+cDItcmVwb3J0LWNvbmNlcm48L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3AyUmVwb3J0QVByb2JsZW08L3N0cmluZz4KICA8a2V5Pmdlbml1cy13ZWxjb21lPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS91c2VyQ29sbGVjdGlvbnNXZWxjb21lPC9zdHJpbmc+CiAgPGtleT5wMi1jaGVjay1wcmUtb3JkZXItcXVldWU8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2dldFByZW9yZGVyUXVldWVDb3VudDwvc3RyaW5nPgogIDxrZXk+cDItcHJlLW9yZGVyLXF1ZXVlPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9nZXRQcmVvcmRlclF1ZXVlPC9zdHJpbmc+CiAgPGtleT5wMi1vcmRlci1wcmUtb3JkZXI8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL29yZGVyUHJlb3JkZXI8L3N0cmluZz4KICA8a2V5PnAyLWNhbmNlbC1wcmUtb3JkZXI8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NhbmNlbFByZW9yZGVyPC9zdHJpbmc+CiAgPGtleT5wMi1wcm9kdWN0LW9mZmVyPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9vZmZlckF2YWlsYWJpbGl0eUFuZEluZm9EaWFsb2c8L3N0cmluZz4KICA8a2V5PnAyLWluLWFwcC1idXk8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkJ1eS53b2Evd2EvaW5BcHBCdXk8L3N0cmluZz4KICA8a2V5PnAyLWluLWFwcC1jaGVjay1kb3dubG9hZC1xdWV1ZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaW5BcHBDaGVja0Rvd25sb2FkUXVldWU8L3N0cmluZz4KICA8a2V5PnAyLWluLWFwcC1wZW5kaW5nLXRyYW5zYWN0aW9uczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaW5BcHBQZW5kaW5nVHJhbnNhY3Rpb25zPC9zdHJpbmc+CiAgPGtleT5wMi1pbi1hcHAtY2hlY2stcmVjdXJyaW5nLWRvd25sb2FkLXF1ZXVlPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9pbkFwcENoZWNrUmVjdXJyaW5nRG93bmxvYWRRdWV1ZTwvc3RyaW5nPgogIDxrZXk+cDItaW4tYXBwLXJlY3VycmluZy10cmFuc2FjdGlvbnM8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2luQXBwUmVjdXJyaW5nVHJhbnNhY3Rpb25zPC9zdHJpbmc+CiAgPGtleT5wMi1pbi1hcHAtdHJhbnNhY3Rpb24tZG9uZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaW5BcHBUcmFuc2FjdGlvbkRvbmU8L3N0cmluZz4KICA8a2V5PnAyLWluLWFwcC1yZWdyYW50LXB1cmNoYXNlLWhpc3Rvcnk8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2luQXBwUmVncmFudFB1cmNoYXNlSGlzdG9yeTwvc3RyaW5nPgogIDxrZXk+Z2V0U2hhcmVJZGVudGlmaWVyczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aSG9tZVNoYXJpbmcud29hL3dhL2dldFNoYXJlSWRlbnRpZmllcnM8L3N0cmluZz4KICA8a2V5PmFwcHJvdmVDb250ZW50VHJhbnNmZXI8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkhvbWVTaGFyaW5nLndvYS93YS9hcHByb3ZlQ29udGVudFRyYW5zZmVyPC9zdHJpbmc+CiAgPGtleT5wZW5kaW5nQm9va3M8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3BlbmRpbmdCb29rczwvc3RyaW5nPgogIDxrZXk+Y2hlY2tCb29rUXVldWU8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NoZWNrRUJvb2tEb3dubG9hZFF1ZXVlPC9zdHJpbmc+CiAgPGtleT5rdnMtZ2V0PC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpCb29ra2VlcGVyLndvYS93YS9nZXQ8L3N0cmluZz4KICA8a2V5Pmt2cy1nZXRhbGw8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkJvb2trZWVwZXIud29hL3dhL2dldEFsbDwvc3RyaW5nPgogIDxrZXk+a3ZzLXB1dDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aQm9va2tlZXBlci53b2Evd2EvcHV0PC9zdHJpbmc+CiAgPGtleT5rdnMtcHV0YWxsPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpCb29ra2VlcGVyLndvYS93YS9wdXRBbGw8L3N0cmluZz4KICA8a2V5PmdldC1wbGF5LWluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2dldFBsYXlJbmZvPC9zdHJpbmc+CiAgPGtleT5wdXNoLW5vdGlmaWNhdGlvbnM8L2tleT4KICA8ZGljdD4KICAgIDxrZXk+cmVnaXN0ZXItc3VjY2Vzczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVnaXN0ZXJTdWNjZXNzPC9zdHJpbmc+CiAgICA8a2V5PmVudmlyb25tZW50PC9rZXk+PHN0cmluZz5wcm9kdWN0aW9uPC9zdHJpbmc+CiAgPC9kaWN0PgogIDxrZXk+YXV0b21hdGljLWRvd25sb2FkczI8L2tleT4KICA8ZGljdD4KICAgIDxrZXk+ZG93bmxvYWRzLXVybDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvZ2V0QXV0b0Rvd25sb2FkUXVldWU8L3N0cmluZz4KICAgIDxrZXk+cmVnaXN0ZXItbWVkaWEtdHlwZXM8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3JlZ2lzdGVyTWVkaWFUeXBlczwvc3RyaW5nPgogICAgPGtleT5jb25maWd1cmF0aW9uczwva2V5PgogICAgPGFycmF5PgogICAgICA8ZGljdD4KICAgICAgICA8a2V5Pm1lZGlhLXR5cGVzPC9rZXk+CiAgICAgICAgPGFycmF5PgogICAgICAgICAgPHN0cmluZz5zb25nPC9zdHJpbmc+CiAgICAgICAgICA8c3RyaW5nPm11c2ljLXZpZGVvPC9zdHJpbmc+CiAgICAgICAgPC9hcnJheT4KICAgICAgICA8a2V5PmNhbm9uaWNhbC1uYW1lPC9rZXk+PHN0cmluZz5BVVRPX0RPV05MT0FEX01VU0lDPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgICAgPGRpY3Q+CiAgICAgICAgPGtleT5tZWRpYS10eXBlczwva2V5PgogICAgICAgIDxhcnJheT4KICAgICAgICAgIDxzdHJpbmc+c29mdHdhcmU8L3N0cmluZz4KICAgICAgICA8L2FycmF5PgogICAgICAgIDxrZXk+Y2Fub25pY2FsLW5hbWU8L2tleT48c3RyaW5nPkFVVE9fRE9XTkxPQURfQVBQUzwvc3RyaW5nPgogICAgICA8L2RpY3Q+CiAgICAgIDxkaWN0PgogICAgICAgIDxrZXk+bWVkaWEtdHlwZXM8L2tleT4KICAgICAgICA8YXJyYXk+CiAgICAgICAgICA8c3RyaW5nPmVib29rPC9zdHJpbmc+CiAgICAgICAgPC9hcnJheT4KICAgICAgICA8a2V5PmNhbm9uaWNhbC1uYW1lPC9rZXk+PHN0cmluZz5BVVRPX0RPV05MT0FEX0JPT0tTPC9zdHJpbmc+CiAgICAgIDwvZGljdD4KICAgIDwvYXJyYXk+CiAgPC9kaWN0PgogIDxrZXk+ZW5hYmxlZC1tZWRpYS10eXBlczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvZW5hYmxlZE1lZGlhVHlwZXM8L3N0cmluZz4KICA8a2V5PnAyLWNvbnRlbnQtcmVzdG9yZTwva2V5PgogIDxkaWN0PgogICAgPGtleT5nemlwPC9rZXk+PGZhbHNlLz4KICAgIDxrZXk+bWF4LWl0ZW0tY291bnQ8L2tleT48aW50ZWdlcj41MDwvaW50ZWdlcj4KICAgIDxrZXk+dXJsPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jb250ZW50UmVzdG9yZTwvc3RyaW5nPgogICAgPGtleT5hbGxvd2VkLWtpbmRzPC9rZXk+CiAgICA8YXJyYXk+CiAgICAgIDxzdHJpbmc+c29uZzwvc3RyaW5nPgogICAgICA8c3RyaW5nPm11c2ljLXZpZGVvPC9zdHJpbmc+CiAgICAgIDxzdHJpbmc+c29mdHdhcmU8L3N0cmluZz4KICAgICAgPHN0cmluZz5lYm9vazwvc3RyaW5nPgogICAgPC9hcnJheT4KICA8L2RpY3Q+CiAgPGtleT5wcmVmbGlnaHQtbG9va3VwPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9nZXRQcmVmbGlnaHQ8L3N0cmluZz4KICA8a2V5PmJ1bmRsZS1vd25zLWNoZWNrPC9rZXk+PHN0cmluZz5odHRwczovL2J1eS5pdHVuZXMuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9vd25zQ2hlY2s8L3N0cmluZz4KICA8a2V5PnJlY292ZXJ5LWJ1eTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9idXkuaXR1bmVzLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVjb3ZlcnlCdXk8L3N0cmluZz4KICA8a2V5PmFkb3B0LXByb2R1Y3Q8L2tleT48c3RyaW5nPmh0dHBzOi8vYnV5Lml0dW5lcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2Fkb3B0UHJvZHVjdDwvc3RyaW5nPgo8L2RpY3Q+CjwvcGxpc3Q+Cg==" +"" +"" +; + +#endif /* _TRUSTTESTS_EVALUATION_POLICY_TESTS_H_ */ diff --git a/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c b/tests/TrustTests/EvaluationTests/RevocationTests.m similarity index 52% rename from OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c rename to tests/TrustTests/EvaluationTests/RevocationTests.m index 95761683..bf733fc2 100644 --- a/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c +++ b/tests/TrustTests/EvaluationTests/RevocationTests.m @@ -1,8 +1,9 @@ /* - * Copyright (c) 2006-2018 Apple Inc. All Rights Reserved. - */ +* Copyright (c) 2006-2019 Apple Inc. All Rights Reserved. +*/ #include +#import #include #include #include @@ -10,27 +11,41 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "trust/trustd/SecOCSPCache.h" -#include "shared_regressions.h" +#import "../TestMacroConversions.h" +#import "../TrustEvaluationTestHelpers.h" +#import "TrustEvaluationTestCase.h" -#include "si-23-sectrust-ocsp.h" +#include "RevocationTests_data.h" -static void tests(void) +@interface RevocationTests : TrustEvaluationTestCase +@end + +@implementation RevocationTests + +- (void)setUp { + // Delete the OCSP cache between each test + [super setUp]; + SecOCSPCacheDeleteContent(nil); +} + +#if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE +/* watchOS and bridgeOS don't support networking in trustd */ +- (void)testRevocation +{ + if (!ping_host("ocsp.digicert.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + SecTrustRef trust; SecCertificateRef cert0, cert1; isnt(cert0 = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0)), - NULL, "create cert0"); + NULL, "create cert0"); isnt(cert1 = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1)), - NULL, "create cert1"); + NULL, "create cert1"); CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); CFArrayAppendValue(certs, cert0); @@ -40,21 +55,20 @@ static void tests(void) SecPolicyRef ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod); const void *v_policies[] = { sslPolicy, ocspPolicy }; CFArrayRef policies = CFArrayCreate(NULL, v_policies, - array_size(v_policies), &kCFTypeArrayCallBacks); + array_size(v_policies), &kCFTypeArrayCallBacks); CFRelease(sslPolicy); CFRelease(ocspPolicy); ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); - /* April 14, 2019 at 10:46:40 PM PDT */ - CFDateRef date = CFDateCreate(NULL, 577000000.0); + CFDateRef date = CFDateCreate(NULL, _ocsp_c0_eval_abs_time); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - is(SecTrustGetVerifyTime(trust), 577000000.0, "get date"); + is(SecTrustGetVerifyTime(trust), _ocsp_c0_eval_abs_time, "get date"); SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); + "trust is kSecTrustResultUnspecified"); /* Certificates are only EV if they are also CT. */ CFDictionaryRef info = SecTrustCopyInfo(trust); @@ -71,7 +85,8 @@ static void tests(void) CFReleaseSafe(date); } -static void test_ocsp_responder_policy() { +- (void) test_ocsp_responder_policy +{ SecCertificateRef leaf = NULL, subCA = NULL, responderCert = NULL; CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); @@ -79,13 +94,13 @@ static void test_ocsp_responder_policy() { SecPolicyRef ocspSignerPolicy = NULL; SecTrustResultType trustResult = kSecTrustResultInvalid; - /* August 14, 2018 at 9:26:40 PM PDT */ - CFDateRef date = CFDateCreate(NULL, 556000000.0); + CFDateRef date = CFDateCreate(NULL, _valid_ist_eval_abs_time); + CFDateRef responderDate = CFDateCreate(NULL, _responder_eval_abs_time); - isnt(leaf = SecCertificateCreateWithBytes(NULL, valid_ist_certificate, - sizeof(valid_ist_certificate)), NULL, "create ist leaf"); - isnt(subCA = SecCertificateCreateWithBytes(NULL, ist_intermediate_certificate, - sizeof(ist_intermediate_certificate)), NULL, "create ist subCA"); + isnt(leaf = SecCertificateCreateWithBytes(NULL, _valid_ist_certificate, + sizeof(_valid_ist_certificate)), NULL, "create ist leaf"); + isnt(subCA = SecCertificateCreateWithBytes(NULL, _ist_intermediate_certificate, + sizeof(_ist_intermediate_certificate)), NULL, "create ist subCA"); CFArrayAppendValue(certs, leaf); CFArrayAppendValue(certs, subCA); @@ -95,7 +110,7 @@ static void test_ocsp_responder_policy() { ok_status(SecTrustCreateWithCertificates(certs, ocspSignerPolicy, &trust), "create trust for c0 -> c1"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); @@ -104,8 +119,8 @@ static void test_ocsp_responder_policy() { CFArraySetValueAtIndex(certs, 0, responderCert); ok_status(SecTrustCreateWithCertificates(certs, ocspSignerPolicy, &trust), "create trust for ocspResponder -> c1"); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok_status(SecTrustSetVerifyDate(trust, responderDate), "set date"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); @@ -116,16 +131,22 @@ static void test_ocsp_responder_policy() { CFReleaseNull(trust); CFReleaseSafe(ocspSignerPolicy); CFReleaseNull(date); + CFReleaseNull(responderDate); } -static void test_revocation() { +- (void)test_always_honor_cached_revoked_responses { + if (!ping_host("ocsp.apple.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + SecTrustRef trust; SecCertificateRef rcert0, rcert1; isnt(rcert0 = SecCertificateCreateWithBytes(NULL, - revoked_ist_certificate, sizeof(revoked_ist_certificate)), + _revoked_ist_certificate, sizeof(_revoked_ist_certificate)), NULL, "create rcert0"); isnt(rcert1 = SecCertificateCreateWithBytes(NULL, - ist_intermediate_certificate, sizeof(ist_intermediate_certificate)), + _ist_intermediate_certificate, sizeof(_ist_intermediate_certificate)), NULL, "create rcert1"); CFMutableArrayRef rcerts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); @@ -149,9 +170,8 @@ static void test_revocation() { is(SecTrustGetVerifyTime(trust), 444900000, "get date"); SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is((trustResult > kSecTrustResultUnspecified), true, - "trust is %d, expected value greater than 4", (int)trustResult); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is(trustResult, kSecTrustResultFatalTrustFailure); CFDictionaryRef results = SecTrustCopyResult(trust); CFTypeRef revoked = NULL; if (results) { @@ -180,9 +200,8 @@ static void test_revocation() { is(SecTrustGetVerifyTime(trust), 440000000, "get date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is((trustResult > kSecTrustResultUnspecified), true, - "trust is %d, expected value greater than 4", (int)trustResult); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is(trustResult, kSecTrustResultFatalTrustFailure); results = SecTrustCopyResult(trust); revoked = NULL; if (results) { @@ -204,295 +223,83 @@ static void test_revocation() { CFReleaseSafe(rcert1); } -static void test_forced_revocation() +- (void) test_require_positive_response { - /* - * Test verification requiring a positive response from the revocation server - */ - - OSStatus status; - SecCertificateRef smime_leaf_cert; - SecCertificateRef smime_CA_cert; - SecCertificateRef smime_root_cert; - - // Import certificates from byte array above - isnt(smime_leaf_cert = SecCertificateCreateWithBytes(NULL, ocsp_smime_leaf_certificate, sizeof(ocsp_smime_leaf_certificate)), - NULL, "SMIME Leaf Cert"); - isnt(smime_CA_cert = SecCertificateCreateWithBytes(NULL, ocsp_smime_CA_certificate, sizeof(ocsp_smime_CA_certificate)), - NULL, "SMIME CA Cert"); - isnt(smime_root_cert = SecCertificateCreateWithBytes(NULL, ocsp_smime_root_certificate, sizeof(ocsp_smime_root_certificate)), - NULL, "SMIME Root Cert"); - - SecPolicyRef smimePolicy = SecPolicyCreateWithProperties(kSecPolicyAppleSMIME, NULL); - SecPolicyRef revocPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod | kSecRevocationRequirePositiveResponse); - isnt(smimePolicy, NULL, "SMIME Policy"); - isnt(revocPolicy, NULL, "SMIME Revocation Policy"); - - // Default Policies - CFMutableArrayRef SMIMEDefaultPolicy = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMEDefaultPolicy, smimePolicy); - - // Default Policies + explicit revocation - CFMutableArrayRef SMIMEDefaultPolicyWithRevocation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, smimePolicy); - CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, revocPolicy); - - // Valid chain of Cert (leaf + CA) - CFMutableArrayRef SMIMECertChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMECertChain, smime_leaf_cert); - CFArrayAppendValue(SMIMECertChain, smime_CA_cert); - - // Valid anchor certs - CFMutableArrayRef SMIMEAnchors = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMEAnchors, smime_root_cert); - - // Free Resources contained in arrays - CFReleaseSafe(smime_leaf_cert); - CFReleaseSafe(smime_CA_cert); - CFReleaseSafe(smime_root_cert); - CFReleaseSafe(smimePolicy); - CFReleaseSafe(revocPolicy); - - CFDateRef VerifyDate; - isnt(VerifyDate = CFDateCreate(NULL, 332900000.0), NULL, "Create verify date"); - if (!VerifyDate) { goto errOut; } - - // Standard evaluation for the given verify date - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - ok_status(status = SecTrustCreateWithCertificates(SMIMECertChain, SMIMEDefaultPolicy, &trust), - "SecTrustCreateWithCertificates"); - ok_status(SecTrustSetVerifyDate(trust, VerifyDate), "Set date"); - ok_status(SecTrustSetAnchorCertificates(trust, SMIMEAnchors), "Set anchors"); - - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - // NOTE: We now expect a fatal error, since the "TC TrustCenter Class 1 L1 CA IX" CA - // is revoked. That CA is no longer present in Valid since the TC root was removed - // from the trust store, and as of May 2018, its OCSP server no longer resolves in DNS. - // However, the OCSP URI for the CA's issuer is still active and reports the CA as revoked. - // - is_status(trust_result, kSecTrustResultFatalTrustFailure, "trust is kSecTrustResultFatalTrustFailure"); - - CFReleaseNull(trust); + if (!ping_host("ocsp.apple.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; } - // Revocation-required evaluation should fail, since this CA's servers no longer exist - // and no valid responses are available - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - ok_status(status = SecTrustCreateWithCertificates(SMIMECertChain, SMIMEDefaultPolicyWithRevocation, &trust), - "SecTrustCreateWithCertificates"); - ok_status(SecTrustSetVerifyDate(trust, VerifyDate), "Set date"); - ok_status(SecTrustSetAnchorCertificates(trust, SMIMEAnchors), "Set anchors"); - - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - // NOTE: We now expect a fatal error, since the "TC TrustCenter Class 1 L1 CA IX" CA - // is revoked. That CA is no longer present in Valid since the TC root was removed - // from the trust store, and as of May 2018, its OCSP server no longer resolves in DNS. - // However, the OCSP URI for the CA's issuer is still active and reports the CA as revoked. - // - is_status(trust_result, kSecTrustResultFatalTrustFailure, "trust is kSecTrustResultFatalTrustFailure"); - - CFReleaseNull(trust); - } - - // Free remaining resources -errOut: - CFReleaseSafe(VerifyDate); - CFReleaseSafe(SMIMEDefaultPolicy); - CFReleaseSafe(SMIMEDefaultPolicyWithRevocation); - CFReleaseSafe(SMIMECertChain); - CFReleaseSafe(SMIMEAnchors); -} - -#if 0 -static void hexdump(const uint8_t *bytes, size_t len) { - size_t ix; - printf("#anchor-sha1: "); - for (ix = 0; ix < len; ++ix) { - printf("%02X", bytes[ix]); - } - printf("\n"); -} - -static void datadump(const uint8_t *bytes, size_t len) { - size_t ix; - printf("#anchor-sha1: "); - for (ix = 0; ix < len; ++ix) { - printf("%c", bytes[ix]); - } - printf("\n"); -} - -static void display_anchor_digest(SecTrustRef trust) { - CFIndex count = SecTrustGetCertificateCount(trust); - SecCertificateRef anchor = SecTrustGetCertificateAtIndex(trust, count - 1); - CFDataRef digest = SecCertificateGetSHA1Digest(anchor); - CFDataRef xml = CFPropertyListCreateXMLData(NULL, digest); - datadump(CFDataGetBytePtr(xml), CFDataGetLength(xml)); -} -#endif - -static void test_aia(void) { - SecCertificateRef ovh = NULL, comodo_ev = NULL, comodo_aia = NULL; - CFMutableArrayRef certs = NULL, policies = NULL; - SecPolicyRef sslPolicy = NULL, revPolicy = NULL; - CFDateRef verifyDate = NULL; - CFDictionaryRef info = NULL; + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; + SecPolicyRef policy = NULL, revocationPolicy = NULL; SecTrustRef trust = NULL; - SecTrustResultType trustResult = kSecTrustResultInvalid; - CFBooleanRef ev = NULL; - - /* Initialize common variables */ - isnt(ovh = SecCertificateCreateWithBytes(NULL, ovh_certificate, - sizeof(ovh_certificate)), NULL, "create ovh cert"); - isnt(comodo_ev = SecCertificateCreateWithBytes(NULL, comodo_ev_certificate, - sizeof(comodo_ev_certificate)), NULL, "create comodo_ev cert"); - isnt(comodo_aia = SecCertificateCreateWithBytes(NULL, - comodo_aia_certificate, sizeof(comodo_aia_certificate)), NULL, - "create comodo_aia cert"); - certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - policies = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - sslPolicy = SecPolicyCreateSSL(false, NULL); // For now, use SSL client policy to avoid SHA-1 deprecation - revPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); - CFArrayAppendValue(policies, sslPolicy); - CFArrayAppendValue(policies, revPolicy); - /* May 9th 2018. */ - verifyDate = CFDateCreate(NULL, 547600500); - - /* First run with no intermediate and disallow network fetching. - * Evaluation should fail because it couldn't get the intermediate. */ - CFArrayAppendValue(certs, ovh); - ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), - "create trust"); - ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); - ok_status(SecTrustSetNetworkFetchAllowed(trust, false), "set no network"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, - "trust is kSecTrustResultRecoverableTrustFailure"); - - /* Now allow networking. Evaluation should succeed after fetching - * the intermediate. */ - ok_status(SecTrustSetNetworkFetchAllowed(trust, true), "set allow network"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - CFReleaseNull(trust); - - /* Now run with the intermediate returned by the ssl server. */ - CFArrayAppendValue(certs, comodo_ev); - ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust), - "create trust"); - ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - info = SecTrustCopyInfo(trust); - ev = (CFBooleanRef)CFDictionaryGetValue(info, - kSecTrustInfoExtendedValidationKey); - ok(ev, "extended validation succeeded due to caissuers fetch"); - //display_anchor_digest(trust); - CFReleaseSafe(info); - CFReleaseSafe(trust); - - /* Now run with the intermediate returned by following the url in the - Certificate Access Information Authority (AIA) extension of the ovh - leaf certificate. */ - CFArrayAppendValue(certs, comodo_aia); - ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust), - "re-create trust with aia intermediate"); - ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - info = SecTrustCopyInfo(trust); - ev = (CFBooleanRef)CFDictionaryGetValue(info, - kSecTrustInfoExtendedValidationKey); - ok(ev, "extended validation succeeded"); - //display_anchor_digest(trust); - CFReleaseSafe(info); - CFReleaseSafe(trust); - - /* Now run with the intermediate returned by following the url in the - Certificate Access Information Authority (AIA) extension of the ovh - leaf certificate. */ - CFArrayRemoveValueAtIndex(certs, 1); - ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust), - "re-create trust with aia intermediate"); - ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - info = SecTrustCopyInfo(trust); - ev = (CFBooleanRef)CFDictionaryGetValue(info, - kSecTrustInfoExtendedValidationKey); - ok(ev, "extended validation succeeded"); - //display_anchor_digest(trust); - CFReleaseSafe(info); - CFReleaseSafe(trust); - - /* Common variable cleanup. */ - CFReleaseSafe(sslPolicy); - CFReleaseSafe(revPolicy); - CFReleaseSafe(certs); - CFReleaseSafe(policies); - CFReleaseSafe(comodo_aia); - CFReleaseSafe(comodo_ev); - CFReleaseSafe(ovh); - CFReleaseSafe(verifyDate); -} - -static void test_aia_https(void) { - SecCertificateRef leaf = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFArrayRef certs = NULL; + CFArrayRef certs = NULL, anchors = NULL; CFDateRef verifyDate = NULL; CFErrorRef error = NULL; - leaf = SecCertificateCreateWithBytes(NULL, _caissuer_https, sizeof(_caissuer_https)); - const void *v_certs[] = { leaf }; + leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf)); + subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA)); + root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot)); - certs = CFArrayCreate(NULL, v_certs, 1, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateSSL(true, CFSTR("example.com")); - require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); + const void *v_certs[] = { leaf, subCA }; + const void *v_anchors[] = { root }; - verifyDate = CFDateCreate(NULL, 546700000.0); // April 29, 2018 at 6:06:40 AM PDT + certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); + policy = SecPolicyCreateAppleExternalDeveloper(); + revocationPolicy = SecPolicyCreateRevocation(kSecRevocationRequirePositiveResponse | kSecRevocationOCSPMethod); + NSArray *policies = @[ (__bridge id)policy, (__bridge id)revocationPolicy ]; + require_noerr_action(SecTrustCreateWithCertificates(certs, (__bridge CFArrayRef)policies, &trust), errOut, + fail("failed to create trust object")); + + anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); + require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors")); + + verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - /* Evaluate trust. This cert does not chain to anything trusted and we can't fetch an - * intermediate because the URI is https. */ - is(SecTrustEvaluateWithError(trust, &error), false, "leaf with missing intermediate and https CAIssuer URI succeeded"); + /* Set no fetch allowed */ + require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed")); + + /* Evaluate trust. Since we required a response but disabled networking, should fail. */ + is(SecTrustEvaluateWithError(trust, &error), false, "non-definitive revoked cert without network failed"); if (error) { - is(CFErrorGetCode(error), errSecCreateChainFailed, "got wrong error code for revoked cert, got %ld, expected %d", - (long)CFErrorGetCode(error), errSecCreateChainFailed); + is(CFErrorGetCode(error), errSecIncompleteCertRevocationCheck, "got wrong error code for revoked cert, got %ld, expected %d", + (long)CFErrorGetCode(error), errSecIncompleteCertRevocationCheck); + } else { + fail("expected trust evaluation to fail and it did not."); + } + CFReleaseNull(error); + + /* Set fetch allowed */ + require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, true), errOut, fail("failed to set network fetch allowed")); + + /* Evaluate trust. We should re-do the evaluation and get a revoked failure from the OCSP check. */ + is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d", + (long)CFErrorGetCode(error), errSecCertificateRevoked); } else { fail("expected trust evaluation to fail and it did not."); } -#pragma clang diagnostic pop errOut: CFReleaseNull(leaf); + CFReleaseNull(subCA); + CFReleaseNull(root); CFReleaseNull(policy); CFReleaseNull(trust); CFReleaseNull(certs); + CFReleaseNull(anchors); CFReleaseNull(verifyDate); CFReleaseNull(error); } -static void test_set_fetch_allowed(void) { +- (void) test_set_fetch_allowed { + if (!ping_host("ocsp.apple.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; SecPolicyRef policy = NULL; SecTrustRef trust = NULL; @@ -500,15 +307,15 @@ static void test_set_fetch_allowed(void) { CFDateRef verifyDate = NULL; CFErrorRef error = NULL; - leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf)); - subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA)); - root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot)); + leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf)); + subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA)); + root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot)); const void *v_certs[] = { leaf, subCA }; const void *v_anchors[] = { root }; certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com")); + policy = SecPolicyCreateAppleExternalDeveloper(); require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); @@ -517,16 +324,10 @@ static void test_set_fetch_allowed(void) { verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); - /* Clear the OCSP cache in case there are old responses for this cert. */ - ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed"); - CFReleaseNull(error); - /* Set no fetch allowed */ require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed")); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com. + /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com. * Since network fetch is not allowed and we fail open, this cert should come back as trusted. */ ok(SecTrustEvaluateWithError(trust, &error), "non-definitive revoked cert without network failed"); CFReleaseNull(error); @@ -543,8 +344,6 @@ static void test_set_fetch_allowed(void) { fail("expected trust evaluation to fail and it did not."); } -#pragma clang diagnostic pop - errOut: CFReleaseNull(leaf); CFReleaseNull(subCA); @@ -557,24 +356,29 @@ errOut: CFReleaseNull(error); } -static void test_check_if_trusted(void) { +- (void) test_check_if_trusted { + if (!ping_host("ocsp.apple.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; - SecPolicyRef sslPolicy = NULL, revocationPolicy = NULL; + SecPolicyRef codesigningPolicy = NULL, revocationPolicy = NULL; SecTrustRef trust = NULL; CFArrayRef certs = NULL, anchors = NULL, policies = NULL; CFDateRef verifyDate = NULL, badVerifyDate = NULL; CFErrorRef error = NULL; - leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf)); - subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA)); - root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot)); + leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf)); + subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA)); + root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot)); - sslPolicy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com")); + codesigningPolicy = SecPolicyCreateAppleExternalDeveloper(); revocationPolicy = SecPolicyCreateRevocation(kSecRevocationCheckIfTrusted); const void *v_certs[] = { leaf, subCA }; const void *v_anchors[] = { root }; - const void *v_policies[] = { sslPolicy, revocationPolicy }; + const void *v_policies[] = { codesigningPolicy, revocationPolicy }; certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); policies = CFArrayCreate(NULL, v_policies, 2, &kCFTypeArrayCallBacks); @@ -585,16 +389,10 @@ static void test_check_if_trusted(void) { badVerifyDate = CFDateCreate(NULL, 490000000.0); // July 12, 2016 at 12:06:40 AM PDT (before cert issued) require_noerr_action(SecTrustSetVerifyDate(trust, badVerifyDate), errOut, fail("failed to set verify date")); - /* Clear the OCSP cache in case there are old responses for this cert. */ - ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed"); - CFReleaseNull(error); - /* Set no fetch allowed */ require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed")); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com. + /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com. * Since we are evaluating it at a time before it was issued, it should come back as untrusted * due to the temporal validity failure, but not due to revocation since we couldn't check for this * untrusted chain. */ @@ -618,13 +416,12 @@ static void test_check_if_trusted(void) { } else { fail("expected trust evaluation to fail and it did not."); } -#pragma clang diagnostic pop errOut: CFReleaseNull(leaf); CFReleaseNull(subCA); CFReleaseNull(root); - CFReleaseNull(sslPolicy); + CFReleaseNull(codesigningPolicy); CFReleaseNull(revocationPolicy); CFReleaseNull(trust); CFReleaseNull(certs); @@ -635,7 +432,12 @@ errOut: CFReleaseNull(error); } -static void test_cache(void) { +- (void) test_cache { + if (!ping_host("ocsp.apple.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; SecPolicyRef policy = NULL; SecTrustRef trust = NULL; @@ -643,15 +445,15 @@ static void test_cache(void) { CFDateRef verifyDate = NULL; CFErrorRef error = NULL; - leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf)); - subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA)); - root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot)); + leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf)); + subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA)); + root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot)); const void *v_certs[] = { leaf, subCA }; const void *v_anchors[] = { root }; certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com")); + policy = SecPolicyCreateAppleExternalDeveloper(); require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); @@ -660,13 +462,7 @@ static void test_cache(void) { verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); - /* Clear the OCSP cache in case there are old responses for this cert. */ - ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed"); - CFReleaseNull(error); - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com. + /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com. * This cert should come back as revoked after a network-based fetch. */ is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded"); if (error) { @@ -688,8 +484,6 @@ static void test_cache(void) { fail("expected trust evaluation to fail and it did not."); } -#pragma clang diagnostic pop - errOut: CFReleaseNull(leaf); CFReleaseNull(subCA); @@ -702,24 +496,29 @@ errOut: CFReleaseNull(error); } -static void test_stapled_revoked_response(void) { +- (void)test_revoked_responses_not_flushed_from_cache +{ + if (!ping_host("ocsp.apple.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; SecPolicyRef policy = NULL; SecTrustRef trust = NULL; CFArrayRef certs = NULL, anchors = NULL; CFDateRef verifyDate = NULL; CFErrorRef error = NULL; - CFDataRef ocspResponse = NULL; - leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf)); - subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA)); - root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot)); + leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf)); + subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA)); + root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot)); const void *v_certs[] = { leaf, subCA }; const void *v_anchors[] = { root }; certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com")); + policy = SecPolicyCreateAppleExternalDeveloper(); require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); @@ -728,22 +527,21 @@ static void test_stapled_revoked_response(void) { verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); - /* Set the stapled response */ - ocspResponse = CFDataCreate(NULL, _digicertOCSPResponse, sizeof(_digicertOCSPResponse)); - ok_status(SecTrustSetOCSPResponse(trust, ocspResponse), "failed to set OCSP response"); + /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com. + * This cert should come back as revoked after a network-based fetch. */ + is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with network succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d", + (long)CFErrorGetCode(error), errSecCertificateRevoked); + } else { + fail("expected trust evaluation to fail and it did not."); + } - /* Clear the OCSP cache in case there are old responses for this cert. */ - ok(SecTrustFlushResponseCache(&error), "OCSP cache flush failed"); - CFReleaseNull(error); - - /* Set no fetch allowed, so we're relying on the stapled response from above */ + /* Set no fetch allowed, so we're relying on the cached response from above */ require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed")); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com. - * This cert should come back as revoked because of the stapled revoked response. */ - is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with stapled response succeeded"); + /* Evaluate trust. Cached response should tell us that it's revoked. */ + is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded"); if (error) { is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d", (long)CFErrorGetCode(error), errSecCertificateRevoked); @@ -751,7 +549,17 @@ static void test_stapled_revoked_response(void) { fail("expected trust evaluation to fail and it did not."); } -#pragma clang diagnostic pop + /* flush the cache and reset the turst, the revoked response should still be present afterwards */ + XCTAssert(SecTrustFlushResponseCache(NULL)); + SecTrustSetNeedsEvaluation(trust); + + is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with cached response succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d", + (long)CFErrorGetCode(error), errSecCertificateRevoked); + } else { + fail("expected trust evaluation to fail and it did not."); + } errOut: CFReleaseNull(leaf); @@ -763,77 +571,14 @@ errOut: CFReleaseNull(anchors); CFReleaseNull(verifyDate); CFReleaseNull(error); - CFReleaseNull(ocspResponse); } -static void test_results_dictionary_revocation_reason(void) { - SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFArrayRef certs = NULL, anchors = NULL; - CFDateRef verifyDate = NULL; - CFErrorRef error = NULL; - CFDataRef ocspResponse = NULL; - - leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf)); - subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA)); - root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot)); - - const void *v_certs[] = { leaf, subCA }; - const void *v_anchors[] = { root }; - - certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com")); - require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); - - anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); - require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors")); - - verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT - require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); - - /* Set the stapled response */ - ocspResponse = CFDataCreate(NULL, _digicertOCSPResponse, sizeof(_digicertOCSPResponse)); - ok_status(SecTrustSetOCSPResponse(trust, ocspResponse), "failed to set OCSP response"); - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com. - * This cert should come back as revoked. */ - is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert succeeded"); - if (error) { - is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d", - (long)CFErrorGetCode(error), errSecCertificateRevoked); - - /* Verify that the results dictionary contains all the right keys for a revoked cert */ - CFDictionaryRef result = SecTrustCopyResult(trust); - isnt(result, NULL, "failed to copy result dictionary"); - if (result) { - int64_t reason = -1; - CFNumberRef cfreason = CFNumberCreate(NULL, kCFNumberSInt64Type, &reason); - is(CFNumberCompare(cfreason, CFDictionaryGetValue(result, kSecTrustRevocationReason), NULL), kCFCompareEqualTo, "expected revocation reason -1"); - CFReleaseNull(cfreason); - } - CFReleaseNull(result); - } else { - fail("expected trust evaluation to fail and it did not."); +- (void) test_results_dictionary_revocation_checked { + if (!ping_host("ocsp.digicert.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; } -#pragma clang diagnostic pop -errOut: - CFReleaseNull(leaf); - CFReleaseNull(subCA); - CFReleaseNull(root); - CFReleaseNull(policy); - CFReleaseNull(trust); - CFReleaseNull(certs); - CFReleaseNull(anchors); - CFReleaseNull(verifyDate); - CFReleaseNull(error); - CFReleaseNull(ocspResponse); -} - -static void test_results_dictionary_revocation_checked(void) { SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; SecPolicyRef sslPolicy = NULL, ocspPolicy = NULL; SecTrustRef trust = NULL; @@ -859,11 +604,9 @@ static void test_results_dictionary_revocation_checked(void) { anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors")); - verifyDate = CFDateCreate(NULL, 577000000.0); // April 14, 2019 at 10:46:40 PM PDT + verifyDate = CFDateCreate(NULL, _ocsp_c0_eval_abs_time); require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" is(SecTrustEvaluateWithError(trust, &error), true, "valid cert failed"); /* Verify that the results dictionary contains all the right keys for a valid cert where revocation checked */ @@ -880,7 +623,6 @@ static void test_results_dictionary_revocation_checked(void) { } } CFReleaseNull(result); -#pragma clang diagnostic pop errOut: CFReleaseNull(leaf); @@ -896,79 +638,318 @@ errOut: CFReleaseNull(error); } -static int ping_host(char *host_name){ - - struct sockaddr_in pin; - struct hostent *nlp_host; - int sd; - int port; - int retries = 5; - - port=80; - - //tries 5 times then give up - while ((nlp_host=gethostbyname(host_name))==0 && retries--){ - printf("Resolve Error! (%s) %d\n", host_name, h_errno); - sleep(1); +- (void) test_revocation_checked_via_cache { + if (!ping_host("ocsp.digicert.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; } - if(nlp_host==0) - return 0; + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; + SecPolicyRef sslPolicy = NULL, ocspPolicy = NULL; + SecTrustRef trust = NULL; + CFArrayRef certs = NULL, anchors = NULL, policies = NULL; + CFDateRef verifyDate = NULL; + CFErrorRef error = NULL; - bzero(&pin,sizeof(pin)); - pin.sin_family=AF_INET; - pin.sin_addr.s_addr=htonl(INADDR_ANY); - pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; - pin.sin_port=htons(port); + leaf = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0)); + subCA = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1)); + root = SecCertificateCreateWithBytes(NULL, _ocsp_c2, sizeof(_ocsp_c2)); - sd=socket(AF_INET,SOCK_STREAM,0); + sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.apple.com")); + ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod); - if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){ - printf("connect error! (%s) %d\n", host_name, errno); - close(sd); - return 0; - } - else{ - close(sd); - return 1; + const void *v_certs[] = { leaf, subCA }; + const void *v_anchors[] = { root }; + const void *v_policies[] = { sslPolicy, ocspPolicy }; + + certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); + policies = CFArrayCreate(NULL, v_policies, 2, &kCFTypeArrayCallBacks); + require_noerr_action(SecTrustCreateWithCertificates(certs, policies, &trust), errOut, fail("failed to create trust object")); + + anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); + require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors")); + + verifyDate = CFDateCreate(NULL, _ocsp_c0_eval_abs_time); + require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); + + is(SecTrustEvaluateWithError(trust, &error), true, "valid cert failed"); + + /* Set no fetch allowed, so we're relying on the cached response from above */ + require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed")); + + /* Evaluate trust. Cached response should tell us that it's revoked. */ + is(SecTrustEvaluateWithError(trust, &error), true, "valid cert failed"); + + /* Verify that the results dictionary contains the kSecTrustRevocationChecked key for a valid cert where revocation checked */ + CFDictionaryRef result = SecTrustCopyResult(trust); + isnt(result, NULL, "failed to copy result dictionary"); + if (result) { + is(CFDictionaryGetValue(result, kSecTrustRevocationChecked), kCFBooleanTrue, "expected revocation checked flag"); } + CFReleaseNull(result); + +errOut: + CFReleaseNull(leaf); + CFReleaseNull(subCA); + CFReleaseNull(root); + CFReleaseNull(ocspPolicy); + CFReleaseNull(sslPolicy); + CFReleaseNull(trust); + CFReleaseNull(certs); + CFReleaseNull(anchors); + CFReleaseNull(policies); + CFReleaseNull(verifyDate); + CFReleaseNull(error); } -int si_23_sectrust_ocsp(int argc, char *const *argv) +#else /* TARGET_OS_WATCH || TARGET_OS_BRIDGE */ +- (void)testNoNetworking { - char *hosts[] = { - "EVSecure-ocsp.verisign.com", - "EVIntl-ocsp.verisign.com", - "EVIntl-aia.verisign.com", - "ocsp.comodoca.com", - "crt.comodoca.com", - "ocsp.entrust.net", - "ocsp.digicert.com", - }; + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFArrayRef certs = NULL, anchors = NULL; + CFDateRef verifyDate = NULL; + CFErrorRef error = NULL; - unsigned host_cnt = 0; + leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf)); + subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA)); + root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot)); - plan_tests(105); + const void *v_certs[] = { leaf, subCA }; + const void *v_anchors[] = { root }; - for (host_cnt = 0; host_cnt < sizeof(hosts)/sizeof(hosts[0]); host_cnt ++) { - if(!ping_host(hosts[host_cnt])) { - printf("Accessing specific server (%s) failed, check the network!\n", hosts[host_cnt]); - return 0; - } + certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); + policy = SecPolicyCreateAppleExternalDeveloper(); + require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); + + anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); + require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors")); + + verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT + require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); + + /* Evaluate trust. Since we aren't allowed to do networking (and this cert is only "Probably Not Revoked" in Valid), + * we shouldn't see this cert as revoked */ + is(SecTrustEvaluateWithError(trust, &error), true, "revoked cert with no network failed"); + +errOut: + CFReleaseNull(leaf); + CFReleaseNull(subCA); + CFReleaseNull(root); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(certs); + CFReleaseNull(anchors); + CFReleaseNull(verifyDate); + CFReleaseNull(error); +} +#endif /* !TARGET_OS_WATCH && !TARGET_OS_BRIDGE */ + +#if !TARGET_OS_BRIDGE +/* bridgeOS doesn't use Valid */ +- (NSNumber *)runRevocationCheckNoNetwork:(SecCertificateRef)leaf + subCA:(SecCertificateRef)subCA +{ + CFArrayRef anchors = NULL; + SecPolicyRef smimePolicy = NULL, revocationPolicy = NULL; + CFArrayRef certs = NULL; + SecTrustRef trust = NULL; + CFDateRef date = NULL; + CFErrorRef error = NULL; + NSArray *policies = nil; + NSDictionary *result = nil; + NSNumber *revocationChecked = nil; + + const void *v_certs[] = { leaf }; + require_action(certs = CFArrayCreate(NULL, v_certs, array_size(v_certs), &kCFTypeArrayCallBacks), errOut, + fail("unable to create certificates array")); + require_action(anchors = CFArrayCreate(NULL, (const void **)&subCA, 1, &kCFTypeArrayCallBacks), errOut, + fail("unable to create anchors array")); + + require_action(smimePolicy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, NULL), errOut, fail("unable to create policy")); + revocationPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod | kSecRevocationCheckIfTrusted); + policies = @[(__bridge id)smimePolicy, (__bridge id)revocationPolicy]; + ok_status(SecTrustCreateWithCertificates(certs, (__bridge CFArrayRef)policies, &trust), "failed to create trust"); + ok_status(SecTrustSetNetworkFetchAllowed(trust, false), "SecTrustSetNetworkFetchAllowed failed"); + + require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, + fail("unable to set anchors")); + ok(SecTrustEvaluateWithError(trust, &error), "Not trusted"); + result = CFBridgingRelease(SecTrustCopyResult(trust)); + revocationChecked = result[(__bridge NSString *)kSecTrustRevocationChecked]; + +errOut: + CFReleaseNull(anchors); + CFReleaseNull(smimePolicy); + CFReleaseNull(revocationPolicy); + CFReleaseNull(certs); + CFReleaseNull(trust); + CFReleaseNull(date); + CFReleaseNull(error); + + return revocationChecked; +} + +- (void) test_revocation_checked_via_valid { + SecCertificateRef leaf = NULL, subCA = NULL; + NSNumber *revocationChecked = NULL; + + require_action(leaf = SecCertificateCreateWithBytes(NULL, _leaf_sha256_valid_cav2_complete_ok1, sizeof(_leaf_sha256_valid_cav2_complete_ok1)), errOut, + fail("unable to create cert")); + require_action(subCA = SecCertificateCreateWithBytes(NULL, _ca_sha256_valid_cav2_complete, sizeof(_ca_sha256_valid_cav2_complete)), errOut, fail("unable to create cert")); + + revocationChecked = [self runRevocationCheckNoNetwork:leaf + subCA:subCA]; + /* assume false if value not present, pending resolution of */ + if (!revocationChecked) { revocationChecked = @NO; } + + XCTAssert(revocationChecked != NULL, "kSecTrustRevocationChecked is not in the result dictionary"); + +errOut: + CFReleaseNull(leaf); + CFReleaseNull(subCA); +} + +- (void) test_revocation_not_checked_no_network { + /* The intermediate does not have the noCAv2 flag and is "probably not revoked,", so + kSecTrustRevocationChecked should not be in the results dictionary */ + SecCertificateRef leaf = NULL, subCA = NULL; + NSNumber *revocationChecked = NULL; + + require_action(leaf = SecCertificateCreateWithBytes(NULL, _leaf_serial_invalid_incomplete_ok1, sizeof(_leaf_serial_invalid_incomplete_ok1)), errOut, + fail("unable to create cert")); + require_action(subCA = SecCertificateCreateWithBytes(NULL, _ca_serial_invalid_incomplete, sizeof(_ca_serial_invalid_incomplete)), errOut, fail("unable to create cert")); + + revocationChecked = [self runRevocationCheckNoNetwork:leaf + subCA:subCA]; + XCTAssert(revocationChecked == NULL, "kSecTrustRevocationChecked is in the result dictionary"); + +errOut: + CFReleaseNull(leaf); + CFReleaseNull(subCA); +} +#endif /* !TARGET_OS_BRIDGE */ + +/* bridgeOS and watchOS do not support networked OCSP but do support stapling */ +- (void) test_stapled_revoked_response { + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFArrayRef certs = NULL, anchors = NULL; + CFDateRef verifyDate = NULL; + CFErrorRef error = NULL; + CFDataRef ocspResponse = NULL; + + leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf)); + subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA)); + root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot)); + + const void *v_certs[] = { leaf, subCA }; + const void *v_anchors[] = { root }; + + certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); + policy = SecPolicyCreateAppleExternalDeveloper(); + require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); + + anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); + require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors")); + + verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT + require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); + + /* Set the stapled response */ + ocspResponse = CFDataCreate(NULL, _devID_OCSPResponse, sizeof(_devID_OCSPResponse)); + ok_status(SecTrustSetOCSPResponse(trust, ocspResponse), "failed to set OCSP response"); + + /* Set no fetch allowed, so we're relying on the stapled response from above */ + require_noerr_action(SecTrustSetNetworkFetchAllowed(trust, false), errOut, fail("failed to set network fetch disallowed")); + + /* Evaluate trust. This cert is revoked, but is only listed as "probably not revoked" by valid.apple.com. + * This cert should come back as revoked because of the stapled revoked response. */ + is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert with stapled response succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d", + (long)CFErrorGetCode(error), errSecCertificateRevoked); + } else { + fail("expected trust evaluation to fail and it did not."); } - tests(); - test_ocsp_responder_policy(); - test_aia(); - test_aia_https(); - test_revocation(); - test_forced_revocation(); - test_set_fetch_allowed(); - test_check_if_trusted(); - test_cache(); - test_stapled_revoked_response(); - test_results_dictionary_revocation_reason(); - test_results_dictionary_revocation_checked(); - - return 0; +errOut: + CFReleaseNull(leaf); + CFReleaseNull(subCA); + CFReleaseNull(root); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(certs); + CFReleaseNull(anchors); + CFReleaseNull(verifyDate); + CFReleaseNull(error); + CFReleaseNull(ocspResponse); } + +- (void) test_results_dictionary_revocation_reason { + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFArrayRef certs = NULL, anchors = NULL; + CFDateRef verifyDate = NULL; + CFErrorRef error = NULL; + CFDataRef ocspResponse = NULL; + + leaf = SecCertificateCreateWithBytes(NULL, _probablyNotRevokedLeaf, sizeof(_probablyNotRevokedLeaf)); + subCA = SecCertificateCreateWithBytes(NULL, _devIDCA, sizeof(_devIDCA)); + root = SecCertificateCreateWithBytes(NULL, _appleRoot, sizeof(_appleRoot)); + + const void *v_certs[] = { leaf, subCA }; + const void *v_anchors[] = { root }; + + certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); + policy = SecPolicyCreateAppleExternalDeveloper(); + require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); + + anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); + require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors")); + + verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT + require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); + + /* Set the stapled response */ + ocspResponse = CFDataCreate(NULL, _devID_OCSPResponse, sizeof(_devID_OCSPResponse)); + ok_status(SecTrustSetOCSPResponse(trust, ocspResponse), "failed to set OCSP response"); + + /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com. + * This cert should come back as revoked. */ + is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d", + (long)CFErrorGetCode(error), errSecCertificateRevoked); + + /* Verify that the results dictionary contains all the right keys for a revoked cert */ + CFDictionaryRef result = SecTrustCopyResult(trust); + isnt(result, NULL, "failed to copy result dictionary"); + if (result) { + int64_t reason = 4; // superceded + CFNumberRef cfreason = CFNumberCreate(NULL, kCFNumberSInt64Type, &reason); + is(CFNumberCompare(cfreason, CFDictionaryGetValue(result, kSecTrustRevocationReason), NULL), kCFCompareEqualTo, "expected revocation reason 4"); + CFReleaseNull(cfreason); + } + CFReleaseNull(result); + } else { + fail("expected trust evaluation to fail and it did not."); + } + +errOut: + CFReleaseNull(leaf); + CFReleaseNull(subCA); + CFReleaseNull(root); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(certs); + CFReleaseNull(anchors); + CFReleaseNull(verifyDate); + CFReleaseNull(error); + CFReleaseNull(ocspResponse); +} + +@end diff --git a/tests/TrustTests/EvaluationTests/RevocationTests_data.h b/tests/TrustTests/EvaluationTests/RevocationTests_data.h new file mode 100644 index 00000000..d29eb54d --- /dev/null +++ b/tests/TrustTests/EvaluationTests/RevocationTests_data.h @@ -0,0 +1,1993 @@ +/* + * Copyright (c) 2018-2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _TRUSTTESTS_REVOCATION_TESTS_H_ +#define _TRUSTTESTS_REVOCATION_TESTS_H_ + +/* ----- IMPORTANT ----- + When replacing the _ocsp_c0 certificate, the value of _ocsp_c0_eval_abs_time + must also be changed to a CFAbsoluteTime value that falls within the validity + period of the certificate. +*/ +static const CFAbsoluteTime _ocsp_c0_eval_abs_time = 626262626; /* Nov 05, 2020 */ + +/* + * Subject: businessCategory = Private Organization,jurisdictionC = US, + * jurisdictionST = California,serialNumber = C0806592,C = US,ST = California, + * L = Cupertino,O = Apple Inc.,CN = www.apple.com + * Issuer: C = US,O = "DigiCert,Inc.",OU = www.digicert.com, + * CN = DigiCert SHA2 Extended Validation Server CA-3 + */ +static const uint8_t _ocsp_c0[] = { + 0x30,0x82,0x08,0x05,0x30,0x82,0x06,0xED,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x10,0x03,0x8E,0x3F,0x9E,0x09, + 0xD7,0xED,0xC7,0xB1,0x80,0x3F,0x74,0xA7,0x4C,0x35, + 0xAB,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x79,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0A, + 0x13,0x0E,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, + 0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x19,0x30,0x17, + 0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77,0x77,0x77, + 0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E, + 0x63,0x6F,0x6D,0x31,0x36,0x30,0x34,0x06,0x03,0x55, + 0x04,0x03,0x13,0x2D,0x44,0x69,0x67,0x69,0x43,0x65, + 0x72,0x74,0x20,0x53,0x48,0x41,0x32,0x20,0x45,0x78, + 0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56,0x61,0x6C, + 0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65, + 0x72,0x76,0x65,0x72,0x20,0x43,0x41,0x2D,0x33,0x30, + 0x1E,0x17,0x0D,0x32,0x30,0x31,0x30,0x30,0x37,0x30, + 0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x31, + 0x31,0x30,0x30,0x38,0x31,0x32,0x30,0x30,0x30,0x30, + 0x5A,0x30,0x81,0xC7,0x31,0x1D,0x30,0x1B,0x06,0x03, + 0x55,0x04,0x0F,0x0C,0x14,0x50,0x72,0x69,0x76,0x61, + 0x74,0x65,0x20,0x4F,0x72,0x67,0x61,0x6E,0x69,0x7A, + 0x61,0x74,0x69,0x6F,0x6E,0x31,0x13,0x30,0x11,0x06, + 0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02, + 0x01,0x03,0x13,0x02,0x55,0x53,0x31,0x1B,0x30,0x19, + 0x06,0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C, + 0x02,0x01,0x02,0x13,0x0A,0x43,0x61,0x6C,0x69,0x66, + 0x6F,0x72,0x6E,0x69,0x61,0x31,0x11,0x30,0x0F,0x06, + 0x03,0x55,0x04,0x05,0x13,0x08,0x43,0x30,0x38,0x30, + 0x36,0x35,0x39,0x32,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0A,0x43,0x61, + 0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D, + 0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, + 0x63,0x6F,0x6D,0x30,0x82,0x01,0x22,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, + 0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, + 0x0A,0x02,0x82,0x01,0x01,0x00,0xCA,0x1B,0x1C,0x21, + 0x78,0x15,0x3D,0x40,0xCF,0xA3,0x79,0x3F,0x9D,0xCF, + 0xB2,0x53,0xAB,0xA9,0x41,0xFF,0x3E,0x06,0xA1,0x29, + 0x69,0x8A,0x04,0x46,0x9E,0xFB,0xC4,0x0D,0x56,0x7A, + 0xCA,0xE6,0x80,0xE7,0xAF,0xC6,0xC0,0xBF,0x8B,0x60, + 0x71,0xCA,0x9A,0xE8,0x76,0x0C,0x06,0xC8,0x9B,0x77, + 0xB8,0xF3,0x1B,0xEA,0x7E,0xE7,0x3A,0x84,0xCB,0xA3, + 0x88,0xA5,0x93,0x04,0x3F,0x69,0x66,0x77,0xCF,0xAE, + 0x06,0xD1,0xD9,0xE1,0x10,0x08,0x7A,0xE0,0x24,0x98, + 0xE7,0x56,0x97,0x0F,0x73,0x68,0x7B,0x4D,0x69,0x46, + 0x28,0x26,0xFF,0x05,0x81,0x0C,0xC0,0xDA,0xFC,0x21, + 0x71,0x81,0x65,0x9A,0x39,0xC9,0xE9,0x68,0x36,0x36, + 0x02,0x5F,0x81,0x80,0xB7,0x7E,0x8A,0x5B,0xFE,0x34, + 0xD0,0xCE,0x76,0x2D,0xD9,0x8B,0x3E,0xD4,0x13,0xC0, + 0xEC,0xEB,0x0F,0x2C,0x77,0xAD,0x1E,0x7B,0x20,0xF6, + 0xDA,0x92,0x98,0xFD,0x89,0xF3,0xA7,0xCB,0x53,0x16, + 0x2E,0xB0,0xB9,0x62,0xBE,0xC8,0xC3,0x28,0x40,0xCF, + 0x8C,0x5C,0x61,0x77,0x8F,0x92,0x3D,0x2F,0x23,0xF2, + 0x0A,0xAB,0x65,0x82,0x22,0xB8,0x98,0xCE,0xBA,0xC8, + 0x00,0x95,0xE4,0x67,0x34,0x6E,0x76,0xE5,0xD1,0xD3, + 0x2D,0x51,0x91,0xBC,0xEF,0xC0,0xC8,0xDE,0xF8,0x7B, + 0xCC,0x46,0x45,0x00,0x76,0xD9,0xCB,0x30,0x31,0xE9, + 0x56,0xFD,0x0E,0x68,0xF4,0x36,0xF9,0x1B,0x5F,0x88, + 0x61,0x62,0x8F,0x60,0xA8,0xDE,0x43,0x7B,0x5C,0xC1, + 0x15,0x73,0xD4,0x06,0x12,0x6E,0x85,0x9B,0x50,0x9C, + 0x24,0xBF,0x5F,0xFC,0xF4,0x68,0x95,0x67,0xD5,0xBF, + 0x44,0x71,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x04, + 0x38,0x30,0x82,0x04,0x34,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xCF,0x85, + 0xF1,0xBC,0x38,0x18,0x78,0x3A,0x55,0x33,0xF4,0x56, + 0xCA,0xC0,0x69,0xAD,0x77,0x6E,0xBB,0x93,0x30,0x1D, + 0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x26, + 0x1F,0xBB,0x67,0xD2,0xB9,0x41,0xED,0x57,0x12,0xE7, + 0x8F,0x2C,0x73,0x4D,0x17,0x8B,0x6B,0x70,0x8E,0x30, + 0x3C,0x06,0x03,0x55,0x1D,0x11,0x04,0x35,0x30,0x33, + 0x82,0x10,0x69,0x6D,0x61,0x67,0x65,0x73,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x82,0x0D, + 0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, + 0x63,0x6F,0x6D,0x82,0x10,0x77,0x77,0x77,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2E,0x63, + 0x6E,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x81, + 0xA5,0x06,0x03,0x55,0x1D,0x1F,0x04,0x81,0x9D,0x30, + 0x81,0x9A,0x30,0x4B,0xA0,0x49,0xA0,0x47,0x86,0x45, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C, + 0x33,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74, + 0x2E,0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43, + 0x65,0x72,0x74,0x53,0x48,0x41,0x32,0x45,0x78,0x74, + 0x65,0x6E,0x64,0x65,0x64,0x56,0x61,0x6C,0x69,0x64, + 0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x72,0x76,0x65, + 0x72,0x43,0x41,0x2D,0x33,0x2E,0x63,0x72,0x6C,0x30, + 0x4B,0xA0,0x49,0xA0,0x47,0x86,0x45,0x68,0x74,0x74, + 0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x34,0x2E,0x64, + 0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F, + 0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, + 0x53,0x48,0x41,0x32,0x45,0x78,0x74,0x65,0x6E,0x64, + 0x65,0x64,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69, + 0x6F,0x6E,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41, + 0x2D,0x33,0x2E,0x63,0x72,0x6C,0x30,0x4B,0x06,0x03, + 0x55,0x1D,0x20,0x04,0x44,0x30,0x42,0x30,0x37,0x06, + 0x09,0x60,0x86,0x48,0x01,0x86,0xFD,0x6C,0x02,0x01, + 0x30,0x2A,0x30,0x28,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70, + 0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x64,0x69, + 0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D, + 0x2F,0x43,0x50,0x53,0x30,0x07,0x06,0x05,0x67,0x81, + 0x0C,0x01,0x01,0x30,0x81,0x8A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x7E,0x30,0x7C, + 0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F, + 0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69,0x67,0x69, + 0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x54, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02, + 0x86,0x48,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63, + 0x61,0x63,0x65,0x72,0x74,0x73,0x2E,0x64,0x69,0x67, + 0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F, + 0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x53,0x48, + 0x41,0x32,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64, + 0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E, + 0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2D,0x33, + 0x2E,0x63,0x72,0x74,0x30,0x09,0x06,0x03,0x55,0x1D, + 0x13,0x04,0x02,0x30,0x00,0x30,0x82,0x01,0xF6,0x06, + 0x0A,0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04, + 0x02,0x04,0x82,0x01,0xE6,0x04,0x82,0x01,0xE2,0x01, + 0xE0,0x00,0x77,0x00,0xF6,0x5C,0x94,0x2F,0xD1,0x77, + 0x30,0x22,0x14,0x54,0x18,0x08,0x30,0x94,0x56,0x8E, + 0xE3,0x4D,0x13,0x19,0x33,0xBF,0xDF,0x0C,0x2F,0x20, + 0x0B,0xCC,0x4E,0xF1,0x64,0xE3,0x00,0x00,0x01,0x75, + 0x04,0xE5,0x12,0x30,0x00,0x00,0x04,0x03,0x00,0x48, + 0x30,0x46,0x02,0x21,0x00,0xDF,0xC0,0x23,0xC6,0x95, + 0x84,0xB9,0x17,0x39,0x79,0x13,0xDA,0x92,0x25,0xF5, + 0xC4,0x25,0x92,0xA4,0xDC,0x1A,0x1C,0xCB,0x78,0x11, + 0x67,0x75,0x67,0x49,0xEB,0x50,0xF7,0x02,0x21,0x00, + 0x94,0xD5,0x5B,0xB3,0x69,0xC3,0x13,0x2F,0x82,0x37, + 0xBA,0x7F,0x70,0x65,0xE2,0x90,0xFF,0xF0,0xB3,0x8D, + 0xBD,0xD3,0x4E,0x7D,0x08,0x40,0xFD,0x14,0x5F,0xFE, + 0x66,0x60,0x00,0x75,0x00,0x5C,0xDC,0x43,0x92,0xFE, + 0xE6,0xAB,0x45,0x44,0xB1,0x5E,0x9A,0xD4,0x56,0xE6, + 0x10,0x37,0xFB,0xD5,0xFA,0x47,0xDC,0xA1,0x73,0x94, + 0xB2,0x5E,0xE6,0xF6,0xC7,0x0E,0xCA,0x00,0x00,0x01, + 0x75,0x04,0xE5,0x12,0x84,0x00,0x00,0x04,0x03,0x00, + 0x46,0x30,0x44,0x02,0x20,0x72,0x9B,0xA1,0x26,0x17, + 0x58,0x3A,0x08,0x39,0xAA,0x39,0xA2,0x99,0x2E,0x23, + 0xA9,0x28,0x9D,0xF5,0xD3,0x05,0x60,0x59,0xF7,0xB3, + 0x55,0x26,0x68,0xA9,0x90,0x94,0x4D,0x02,0x20,0x6C, + 0xC9,0x29,0xDD,0x9A,0xB0,0x20,0x99,0x71,0x10,0x25, + 0x22,0x14,0xD0,0x9C,0x5A,0xF3,0xAF,0x5C,0x39,0xD1, + 0x8D,0x39,0x99,0x44,0xD9,0xD4,0x82,0x5F,0x70,0x16, + 0x3F,0x00,0x76,0x00,0x56,0x14,0x06,0x9A,0x2F,0xD7, + 0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7, + 0x46,0x76,0xB9,0xBC,0x99,0x11,0x5C,0xC0,0xEF,0x94, + 0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x75, + 0x04,0xE5,0x14,0x16,0x00,0x00,0x04,0x03,0x00,0x47, + 0x30,0x45,0x02,0x21,0x00,0xED,0xBC,0x09,0x34,0x16, + 0xCE,0x90,0x3A,0x87,0x43,0x45,0x65,0xC6,0xF2,0x9C, + 0x2F,0x88,0xE0,0x03,0xD0,0x0D,0xCF,0xF0,0xCA,0xDE, + 0xA6,0x58,0xE5,0x9A,0xF0,0x82,0xF8,0x02,0x20,0x69, + 0x83,0xDC,0x74,0x0D,0xA0,0xC1,0x06,0xCC,0x47,0xE9, + 0xAE,0x20,0x72,0x30,0xEB,0x3C,0xE9,0x0C,0x4D,0xAB, + 0x80,0x16,0x14,0x9A,0x68,0xAB,0x19,0xF1,0x97,0x1A, + 0xAF,0x00,0x76,0x00,0xA4,0xB9,0x09,0x90,0xB4,0x18, + 0x58,0x14,0x87,0xBB,0x13,0xA2,0xCC,0x67,0x70,0x0A, + 0x3C,0x35,0x98,0x04,0xF9,0x1B,0xDF,0xB8,0xE3,0x77, + 0xCD,0x0E,0xC8,0x0D,0xDC,0x10,0x00,0x00,0x01,0x75, + 0x04,0xE5,0x14,0xE1,0x00,0x00,0x04,0x03,0x00,0x47, + 0x30,0x45,0x02,0x21,0x00,0xD5,0x25,0x88,0x86,0xB9, + 0x7F,0x7A,0x59,0xA2,0x36,0xAF,0x2F,0xCF,0xB8,0x28, + 0x53,0x26,0xC9,0xA9,0x89,0x3C,0x4F,0xC0,0x92,0x2D, + 0x1C,0xBD,0x18,0x30,0x9F,0x87,0x99,0x02,0x20,0x6B, + 0xAD,0x0B,0x89,0xC5,0xF9,0xB0,0x8C,0x40,0xEE,0x35, + 0x56,0x2D,0xED,0x6C,0x91,0x94,0x2F,0x03,0xC4,0x8C, + 0xF1,0xD4,0xD8,0xF6,0x68,0xDF,0xE6,0xAA,0x4F,0xF5, + 0x4F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01, + 0x00,0x22,0xC0,0x83,0xA8,0x41,0x64,0x68,0xDC,0xDA, + 0x6D,0xEF,0x07,0x46,0x32,0x32,0x57,0x25,0x9E,0xFE, + 0x5D,0x43,0x4B,0xF2,0x17,0xC2,0x5F,0x1E,0x86,0xE4, + 0xAC,0x54,0x3B,0x3B,0xE9,0x96,0xDF,0x92,0xE2,0x0D, + 0x8F,0xD9,0x20,0x5F,0x4A,0x04,0xB1,0x98,0xE5,0xE3, + 0xAD,0x1D,0x26,0x17,0xF3,0xE2,0xAD,0xB7,0x56,0xDC, + 0x46,0x29,0x70,0xAB,0xD5,0x63,0x8A,0x9F,0x34,0x02, + 0xD6,0xF8,0x5A,0x9C,0xEA,0xF6,0xD3,0x3A,0xCC,0x5C, + 0x7E,0xA3,0x15,0x46,0xBF,0x56,0x2C,0x39,0x67,0x42, + 0x8A,0xBF,0x78,0xF3,0x7F,0x2D,0x3F,0x47,0x74,0x20, + 0xBA,0xA8,0xCA,0xA5,0x16,0x56,0xEE,0x87,0x83,0x22, + 0x41,0xBB,0x76,0x44,0x00,0x16,0x92,0x65,0xC2,0x31, + 0xE1,0x38,0xC9,0xF4,0xB8,0x4E,0xB7,0x3C,0x8E,0xE3, + 0x89,0x9C,0x1E,0xA8,0x0D,0x5E,0x20,0x3B,0x21,0xD2, + 0xB7,0x4C,0xFB,0x37,0xF6,0x20,0x26,0x57,0x1D,0xFE, + 0xDC,0xF4,0x26,0xC2,0x36,0xC6,0x1A,0x32,0xA0,0x47, + 0x4A,0xCE,0x44,0x81,0x94,0xB8,0x26,0xBA,0x61,0x5A, + 0x91,0xD1,0xA7,0x75,0xC1,0x61,0xB8,0x33,0x6E,0x07, + 0x81,0x34,0x7F,0xF9,0xDE,0x34,0x0B,0x82,0x4D,0x55, + 0x8D,0xC5,0x16,0x9B,0x54,0xBC,0x20,0xB0,0xE3,0x20, + 0xF9,0x27,0x39,0x36,0x76,0xE1,0x6C,0x02,0x60,0xBD, + 0x6D,0x9C,0x69,0x4D,0xBC,0xDC,0x86,0x83,0x90,0x21, + 0x6D,0xC2,0x12,0xDF,0x21,0x52,0xAB,0xA2,0xA8,0x10, + 0x6F,0x3A,0xFF,0xBB,0x60,0x8D,0xC9,0xAC,0xC1,0xC1, + 0xB0,0xBB,0x7D,0x4F,0x8E,0x18,0x62,0x22,0x82,0xF9, + 0x79,0x05,0x9E,0x1E,0xF2,0x1B,0xD1 +}; + +/* + * Subject: C = US,O = "DigiCert,Inc.",OU = www.digicert.com, + * CN = DigiCert SHA2 Extended Validation Server CA-3 + * Issuer: C = US,O = DigiCert Inc,OU = www.digicert.com, + * CN = DigiCert High Assurance EV Root CA + */ +static const uint8_t _ocsp_c1[] = { + 0x30,0x82,0x04,0xC8,0x30,0x82,0x03,0xB0,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x10,0x08,0x11,0x40,0x56,0x4B, + 0xAB,0xCE,0x94,0xCB,0xEE,0x09,0x0A,0x28,0x68,0xF4, + 0x9D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6C,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0A, + 0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, + 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03, + 0x55,0x04,0x0B,0x13,0x10,0x77,0x77,0x77,0x2E,0x64, + 0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F, + 0x6D,0x31,0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x03, + 0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, + 0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73,0x73,0x75, + 0x72,0x61,0x6E,0x63,0x65,0x20,0x45,0x56,0x20,0x52, + 0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, + 0x31,0x39,0x31,0x31,0x31,0x32,0x31,0x32,0x31,0x30, + 0x32,0x38,0x5A,0x17,0x0D,0x32,0x39,0x31,0x31,0x31, + 0x32,0x31,0x32,0x31,0x30,0x32,0x38,0x5A,0x30,0x79, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55, + 0x04,0x0A,0x13,0x0E,0x44,0x69,0x67,0x69,0x43,0x65, + 0x72,0x74,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x19, + 0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, + 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72, + 0x74,0x2E,0x63,0x6F,0x6D,0x31,0x36,0x30,0x34,0x06, + 0x03,0x55,0x04,0x03,0x13,0x2D,0x44,0x69,0x67,0x69, + 0x43,0x65,0x72,0x74,0x20,0x53,0x48,0x41,0x32,0x20, + 0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56, + 0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20, + 0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,0x2D, + 0x33,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, + 0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, + 0x82,0x01,0x01,0x00,0xAC,0xE8,0x94,0x25,0x7B,0x53, + 0x6C,0x98,0x68,0x2E,0x3C,0x9D,0xAB,0xE6,0x03,0x17, + 0x6C,0xAE,0x72,0x16,0x48,0x08,0x82,0x44,0x98,0xC4, + 0xFA,0x3D,0xBE,0x02,0x62,0x1C,0x8F,0x75,0xCD,0xC6, + 0xD8,0x56,0x4A,0xED,0x5C,0xB6,0xAD,0xE2,0xCC,0x67, + 0x22,0x18,0x46,0x10,0x52,0xC7,0x8E,0x14,0xCB,0x01, + 0xC7,0xC3,0x15,0xF5,0xD3,0xBB,0x99,0x7A,0x26,0x5A, + 0x8E,0x54,0xF1,0xB4,0xEA,0x30,0xA0,0x55,0xDB,0x75, + 0xD6,0xD2,0x42,0x4E,0x37,0x81,0x37,0x83,0x9E,0x6B, + 0xF0,0xE7,0xCE,0x35,0x3C,0x95,0x6C,0xF2,0xDE,0x04, + 0x76,0x04,0xFB,0x1C,0x7B,0x92,0xAB,0xE3,0x88,0x72, + 0x25,0x27,0x7A,0x4D,0x38,0x11,0x27,0x8C,0xC0,0x9D, + 0x5F,0x34,0xE7,0x50,0xC3,0x4F,0xBC,0x03,0x11,0x87, + 0xC2,0xFC,0x13,0x59,0x43,0x5C,0xF1,0xCA,0x33,0xDB, + 0x3F,0xEA,0x6A,0x0C,0xDE,0x0B,0x2E,0xE0,0xD1,0x73, + 0xF8,0xC3,0xE6,0xA3,0xA8,0xA4,0xB7,0x0C,0x4B,0xD7, + 0x38,0x49,0x4D,0x4E,0xF7,0xB7,0xDA,0xE9,0xAC,0xC2, + 0x6E,0x97,0x91,0xF2,0x64,0x19,0x74,0x1B,0x3F,0xDF, + 0x76,0xB5,0x5F,0xF4,0x19,0xAE,0xD5,0x17,0x17,0x8C, + 0xA4,0x68,0xBD,0x0B,0xAC,0xC5,0x6D,0xA9,0x1F,0xA0, + 0xB4,0xF0,0xC3,0x38,0x3C,0xB1,0x16,0xE3,0xCA,0xA8, + 0x15,0x63,0x59,0x08,0x53,0x37,0xA5,0xB0,0xD0,0x66, + 0xE0,0xBB,0x17,0x3D,0x9B,0xA4,0x32,0x7D,0xFB,0x22, + 0xB3,0x45,0x91,0x31,0x33,0x6A,0x22,0x48,0x04,0x8D, + 0x53,0x5D,0x18,0x6E,0x01,0x8D,0x9B,0xAE,0xF1,0x52, + 0x4C,0x11,0x8F,0x67,0x9B,0x9E,0x65,0xEB,0x06,0xCB, + 0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x57,0x30, + 0x82,0x01,0x53,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, + 0x04,0x16,0x04,0x14,0xCF,0x85,0xF1,0xBC,0x38,0x18, + 0x78,0x3A,0x55,0x33,0xF4,0x56,0xCA,0xC0,0x69,0xAD, + 0x77,0x6E,0xBB,0x93,0x30,0x1F,0x06,0x03,0x55,0x1D, + 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xB1,0x3E,0xC3, + 0x69,0x03,0xF8,0xBF,0x47,0x01,0xD4,0x98,0x26,0x1A, + 0x08,0x02,0xEF,0x63,0x64,0x2B,0xC3,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, + 0x02,0x01,0x86,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25, + 0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x02,0x30,0x12,0x06,0x03,0x55,0x1D, + 0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01, + 0xFF,0x02,0x01,0x00,0x30,0x34,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26, + 0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F, + 0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69,0x67,0x69, + 0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x4B, + 0x06,0x03,0x55,0x1D,0x1F,0x04,0x44,0x30,0x42,0x30, + 0x40,0xA0,0x3E,0xA0,0x3C,0x86,0x3A,0x68,0x74,0x74, + 0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x33,0x2E,0x64, + 0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F, + 0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, + 0x48,0x69,0x67,0x68,0x41,0x73,0x73,0x75,0x72,0x61, + 0x6E,0x63,0x65,0x45,0x56,0x52,0x6F,0x6F,0x74,0x43, + 0x41,0x2E,0x63,0x72,0x6C,0x30,0x4B,0x06,0x03,0x55, + 0x1D,0x20,0x04,0x44,0x30,0x42,0x30,0x37,0x06,0x09, + 0x60,0x86,0x48,0x01,0x86,0xFD,0x6C,0x02,0x01,0x30, + 0x2A,0x30,0x28,0x06,0x08,0x2B,0x06,0x01,0x05,0x05, + 0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70,0x73, + 0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x64,0x69,0x67, + 0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F, + 0x43,0x50,0x53,0x30,0x07,0x06,0x05,0x67,0x81,0x0C, + 0x01,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01, + 0x01,0x00,0xC2,0x18,0x20,0xCA,0x83,0x5E,0x57,0x30, + 0xC7,0x4C,0x48,0xC8,0x39,0xA0,0xBC,0x0B,0x5D,0x9F, + 0xA9,0x44,0xF5,0x81,0x28,0xED,0xB4,0x33,0x60,0xBD, + 0x93,0x1F,0xE8,0xEA,0x58,0x34,0x6E,0xE5,0x13,0xA5, + 0x1C,0xEC,0xD2,0x77,0xC2,0x17,0x88,0x21,0xB8,0xC7, + 0x73,0x02,0xA4,0xD8,0xCF,0x16,0x39,0xF6,0x91,0x15, + 0xFD,0x9A,0x62,0xD4,0x70,0x07,0x17,0x56,0x98,0x13, + 0x75,0x15,0xAB,0x27,0xFC,0xAF,0x90,0x5D,0x8A,0xAA, + 0x55,0xD8,0x04,0xF3,0xD5,0xDB,0x82,0x40,0x12,0x80, + 0x24,0xFC,0xAE,0x15,0xDB,0x4E,0xD3,0x1C,0xA5,0x10, + 0xE6,0x29,0xDD,0xBF,0xD9,0xE1,0x42,0xFE,0xB9,0x00, + 0xF0,0xF7,0x34,0xB5,0x9E,0x40,0xEC,0x4E,0x3D,0x11, + 0x0D,0x3F,0xEC,0x9D,0x36,0x58,0x7C,0x76,0x66,0x9A, + 0x87,0x99,0x88,0x49,0x93,0xC6,0xD0,0xA6,0x0F,0xC3, + 0x7B,0xC9,0x71,0xEB,0xD1,0x16,0xFF,0xBA,0xAC,0x34, + 0xB9,0xC1,0x82,0xD3,0xF8,0xD7,0xD7,0x0A,0x50,0x16, + 0xA3,0x46,0x9C,0x48,0x55,0x6E,0x5A,0xDF,0x9C,0xDF, + 0xFB,0x30,0xB1,0x7C,0x11,0xF6,0xFA,0xF4,0xF5,0x1E, + 0xA2,0x85,0xB1,0x3E,0xF1,0x68,0x68,0xA2,0xBB,0xB7, + 0x80,0xBB,0x2A,0xD5,0x40,0xC7,0x3A,0x4C,0xC8,0xFA, + 0x8B,0x65,0x4E,0x72,0x8F,0xC7,0xCA,0x93,0xA4,0x4A, + 0xCF,0xBA,0x8B,0xB1,0x55,0xBC,0x2E,0x05,0xC5,0x32, + 0x63,0x34,0x0D,0xB3,0x87,0xEC,0xF7,0xA0,0xBD,0xFF, + 0x96,0x3F,0x07,0x3E,0xB2,0x4B,0xA6,0xAE,0x8E,0x50, + 0xE7,0x4F,0x53,0x9D,0x72,0xB0,0x0C,0x71,0x79,0x60, + 0x34,0x6B,0x3D,0xD9,0x9F,0xE6,0x87,0xFB +}; + +/* + * Subject: C = US,O = DigiCert Inc,OU = www.digicert.com, + * CN = DigiCert High Assurance EV Root CA + * Issuer: C = US,O = DigiCert Inc,OU = www.digicert.com, + * CN = DigiCert High Assurance EV Root CA + */ +static const uint8_t _ocsp_c2[] = { + 0x30,0x82,0x03,0xC5,0x30,0x82,0x02,0xAD,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x10,0x02,0xAC,0x5C,0x26,0x6A, + 0x0B,0x40,0x9B,0x8F,0x0B,0x79,0xF2,0xAE,0x46,0x25, + 0x77,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x6C,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0A, + 0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, + 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03, + 0x55,0x04,0x0B,0x13,0x10,0x77,0x77,0x77,0x2E,0x64, + 0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F, + 0x6D,0x31,0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x03, + 0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, + 0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73,0x73,0x75, + 0x72,0x61,0x6E,0x63,0x65,0x20,0x45,0x56,0x20,0x52, + 0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, + 0x30,0x36,0x31,0x31,0x31,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x5A,0x17,0x0D,0x33,0x31,0x31,0x31,0x31, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x6C, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55, + 0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65, + 0x72,0x74,0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17, + 0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77,0x77,0x77, + 0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E, + 0x63,0x6F,0x6D,0x31,0x2B,0x30,0x29,0x06,0x03,0x55, + 0x04,0x03,0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65, + 0x72,0x74,0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73, + 0x73,0x75,0x72,0x61,0x6E,0x63,0x65,0x20,0x45,0x56, + 0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82, + 0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01, + 0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, + 0x00,0xC6,0xCC,0xE5,0x73,0xE6,0xFB,0xD4,0xBB,0xE5, + 0x2D,0x2D,0x32,0xA6,0xDF,0xE5,0x81,0x3F,0xC9,0xCD, + 0x25,0x49,0xB6,0x71,0x2A,0xC3,0xD5,0x94,0x34,0x67, + 0xA2,0x0A,0x1C,0xB0,0x5F,0x69,0xA6,0x40,0xB1,0xC4, + 0xB7,0xB2,0x8F,0xD0,0x98,0xA4,0xA9,0x41,0x59,0x3A, + 0xD3,0xDC,0x94,0xD6,0x3C,0xDB,0x74,0x38,0xA4,0x4A, + 0xCC,0x4D,0x25,0x82,0xF7,0x4A,0xA5,0x53,0x12,0x38, + 0xEE,0xF3,0x49,0x6D,0x71,0x91,0x7E,0x63,0xB6,0xAB, + 0xA6,0x5F,0xC3,0xA4,0x84,0xF8,0x4F,0x62,0x51,0xBE, + 0xF8,0xC5,0xEC,0xDB,0x38,0x92,0xE3,0x06,0xE5,0x08, + 0x91,0x0C,0xC4,0x28,0x41,0x55,0xFB,0xCB,0x5A,0x89, + 0x15,0x7E,0x71,0xE8,0x35,0xBF,0x4D,0x72,0x09,0x3D, + 0xBE,0x3A,0x38,0x50,0x5B,0x77,0x31,0x1B,0x8D,0xB3, + 0xC7,0x24,0x45,0x9A,0xA7,0xAC,0x6D,0x00,0x14,0x5A, + 0x04,0xB7,0xBA,0x13,0xEB,0x51,0x0A,0x98,0x41,0x41, + 0x22,0x4E,0x65,0x61,0x87,0x81,0x41,0x50,0xA6,0x79, + 0x5C,0x89,0xDE,0x19,0x4A,0x57,0xD5,0x2E,0xE6,0x5D, + 0x1C,0x53,0x2C,0x7E,0x98,0xCD,0x1A,0x06,0x16,0xA4, + 0x68,0x73,0xD0,0x34,0x04,0x13,0x5C,0xA1,0x71,0xD3, + 0x5A,0x7C,0x55,0xDB,0x5E,0x64,0xE1,0x37,0x87,0x30, + 0x56,0x04,0xE5,0x11,0xB4,0x29,0x80,0x12,0xF1,0x79, + 0x39,0x88,0xA2,0x02,0x11,0x7C,0x27,0x66,0xB7,0x88, + 0xB7,0x78,0xF2,0xCA,0x0A,0xA8,0x38,0xAB,0x0A,0x64, + 0xC2,0xBF,0x66,0x5D,0x95,0x84,0xC1,0xA1,0x25,0x1E, + 0x87,0x5D,0x1A,0x50,0x0B,0x20,0x12,0xCC,0x41,0xBB, + 0x6E,0x0B,0x51,0x38,0xB8,0x4B,0xCB,0x02,0x03,0x01, + 0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x0E,0x06,0x03, + 0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02, + 0x01,0x86,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01, + 0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, + 0xB1,0x3E,0xC3,0x69,0x03,0xF8,0xBF,0x47,0x01,0xD4, + 0x98,0x26,0x1A,0x08,0x02,0xEF,0x63,0x64,0x2B,0xC3, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, + 0x16,0x80,0x14,0xB1,0x3E,0xC3,0x69,0x03,0xF8,0xBF, + 0x47,0x01,0xD4,0x98,0x26,0x1A,0x08,0x02,0xEF,0x63, + 0x64,0x2B,0xC3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x1C,0x1A,0x06,0x97,0xDC,0xD7,0x9C, + 0x9F,0x3C,0x88,0x66,0x06,0x08,0x57,0x21,0xDB,0x21, + 0x47,0xF8,0x2A,0x67,0xAA,0xBF,0x18,0x32,0x76,0x40, + 0x10,0x57,0xC1,0x8A,0xF3,0x7A,0xD9,0x11,0x65,0x8E, + 0x35,0xFA,0x9E,0xFC,0x45,0xB5,0x9E,0xD9,0x4C,0x31, + 0x4B,0xB8,0x91,0xE8,0x43,0x2C,0x8E,0xB3,0x78,0xCE, + 0xDB,0xE3,0x53,0x79,0x71,0xD6,0xE5,0x21,0x94,0x01, + 0xDA,0x55,0x87,0x9A,0x24,0x64,0xF6,0x8A,0x66,0xCC, + 0xDE,0x9C,0x37,0xCD,0xA8,0x34,0xB1,0x69,0x9B,0x23, + 0xC8,0x9E,0x78,0x22,0x2B,0x70,0x43,0xE3,0x55,0x47, + 0x31,0x61,0x19,0xEF,0x58,0xC5,0x85,0x2F,0x4E,0x30, + 0xF6,0xA0,0x31,0x16,0x23,0xC8,0xE7,0xE2,0x65,0x16, + 0x33,0xCB,0xBF,0x1A,0x1B,0xA0,0x3D,0xF8,0xCA,0x5E, + 0x8B,0x31,0x8B,0x60,0x08,0x89,0x2D,0x0C,0x06,0x5C, + 0x52,0xB7,0xC4,0xF9,0x0A,0x98,0xD1,0x15,0x5F,0x9F, + 0x12,0xBE,0x7C,0x36,0x63,0x38,0xBD,0x44,0xA4,0x7F, + 0xE4,0x26,0x2B,0x0A,0xC4,0x97,0x69,0x0D,0xE9,0x8C, + 0xE2,0xC0,0x10,0x57,0xB8,0xC8,0x76,0x12,0x91,0x55, + 0xF2,0x48,0x69,0xD8,0xBC,0x2A,0x02,0x5B,0x0F,0x44, + 0xD4,0x20,0x31,0xDB,0xF4,0xBA,0x70,0x26,0x5D,0x90, + 0x60,0x9E,0xBC,0x4B,0x17,0x09,0x2F,0xB4,0xCB,0x1E, + 0x43,0x68,0xC9,0x07,0x27,0xC1,0xD2,0x5C,0xF7,0xEA, + 0x21,0xB9,0x68,0x12,0x9C,0x3C,0x9C,0xBF,0x9E,0xFC, + 0x80,0x5C,0x9B,0x63,0xCD,0xEC,0x47,0xAA,0x25,0x27, + 0x67,0xA0,0x37,0xF3,0x00,0x82,0x7D,0x54,0xD7,0xA9, + 0xF8,0xE9,0x2E,0x13,0xA3,0x77,0xE8,0x1F,0x4A +}; + + +/* ----- IMPORTANT ----- + When replacing the _responderCert certificate, the value of + _responder_eval_abs_time must also be changed to a CFAbsoluteTime value + that falls within the validity period of the certificate. +*/ +static const CFAbsoluteTime _responder_eval_abs_time = 556000000; /* Aug 14, 2018 */ + +/* subject:/CN=Apple IST CA 2 OCSP Responder NL01/O=Apple Inc./C=US */ +/* issuer :/CN=Apple IST CA 2 - G1/OU=Certification Authority/O=Apple Inc./C=US */ +static const uint8_t _responderCert[] = { + 0x30,0x82,0x03,0xBB,0x30,0x82,0x02,0xA3,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x5B, + 0x1B,0xA7,0xF8,0x9D,0xF4,0x7B,0x7C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04, + 0x03,0x13,0x13,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20, + 0x32,0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13, + 0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x38, + 0x30,0x38,0x31,0x31,0x30,0x30,0x34,0x36,0x35,0x33,0x5A,0x17,0x0D,0x31,0x38,0x30, + 0x39,0x32,0x32,0x30,0x30,0x34,0x36,0x35,0x33,0x5A,0x30,0x4F,0x31,0x2B,0x30,0x29, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x22,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54, + 0x20,0x43,0x41,0x20,0x32,0x20,0x4F,0x43,0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6F, + 0x6E,0x64,0x65,0x72,0x20,0x4E,0x4C,0x30,0x31,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82, + 0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xA5,0x35,0xB2,0xC4, + 0xF2,0xAB,0x4C,0xFE,0xAA,0x5D,0xC7,0x23,0x52,0x68,0x42,0xC7,0x77,0x27,0x78,0x4E, + 0x80,0xFD,0x06,0xA3,0x51,0xA2,0x4F,0xF7,0x7A,0xD0,0x19,0x78,0xFD,0xEA,0x94,0xD8, + 0xE3,0x0C,0x3C,0x50,0x17,0x30,0xDB,0x84,0x38,0x13,0xE1,0xCF,0x6C,0xA0,0x1F,0x01, + 0xC7,0x12,0xC7,0x96,0x64,0x09,0x45,0x2F,0xA2,0x83,0xFE,0x4E,0x2C,0xF2,0x39,0x6F, + 0x20,0x34,0x6D,0xEC,0xBE,0xF9,0x86,0xA3,0xEF,0x40,0x1B,0x61,0x2D,0xE1,0xA4,0xB9, + 0xD4,0x3E,0x8E,0x65,0x7B,0x2F,0x26,0xD5,0x54,0xA6,0x12,0xC7,0x50,0xC8,0x89,0x94, + 0x86,0xFA,0x41,0x48,0xCF,0xE2,0xF1,0xF8,0xF2,0x0E,0xCC,0x25,0x43,0x0C,0x66,0x85, + 0xDC,0x88,0xA0,0x76,0x90,0x45,0xFC,0x4E,0x95,0x8F,0xA2,0x17,0x2F,0xAF,0x7C,0x41, + 0x59,0xA0,0xA1,0x36,0x98,0x18,0x20,0x4D,0x07,0xF5,0x7F,0xD1,0x66,0x65,0xC6,0x74, + 0xEA,0xBE,0xB8,0x20,0x88,0x29,0x27,0x5D,0x06,0x55,0xD0,0xB2,0x11,0xAF,0x52,0x58, + 0xD1,0x8A,0x57,0x6E,0x85,0x8D,0x0C,0xBD,0x6A,0xD3,0x87,0x09,0xF6,0x0F,0x07,0x7B, + 0x5C,0x8F,0x96,0x16,0xB5,0x89,0xB7,0x63,0xC4,0x33,0xDA,0x67,0x63,0xA3,0xC4,0x4B, + 0x73,0xEF,0x57,0x96,0x4F,0x15,0x2F,0x1B,0xF7,0x8E,0x35,0x24,0x18,0x68,0x87,0x16, + 0x0A,0x76,0x71,0x8B,0x94,0x11,0xB9,0xCC,0x02,0x97,0x2D,0x6F,0x94,0x00,0x1A,0x31, + 0xA6,0x9A,0x6B,0x4A,0xD3,0x64,0xB0,0x0F,0xA2,0xB0,0x5E,0xC0,0x2A,0x13,0xD6,0x7C, + 0x90,0xA6,0x5C,0xEE,0x7F,0x78,0xCA,0x7F,0x62,0x2F,0xF9,0x47,0x02,0x03,0x01,0x00, + 0x01,0xA3,0x81,0x87,0x30,0x81,0x84,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, + 0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0xD8,0x7A,0x94,0x44,0x7C,0x90,0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C,0x01, + 0x44,0x03,0x86,0xD6,0x2A,0x29,0x30,0x0F,0x06,0x09,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x30,0x01,0x05,0x04,0x02,0x05,0x00,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C, + 0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x09,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x75,0xDB,0x74,0x13,0x4A,0xCB,0xCB,0x5A,0x6B, + 0x78,0x40,0x5A,0x81,0x67,0x42,0xA5,0xD9,0xD0,0x4E,0x38,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x3A, + 0x7E,0x84,0xE2,0x58,0xED,0x07,0xDD,0xE5,0xBD,0x5E,0x88,0x55,0x06,0x23,0x16,0x20, + 0xD1,0x85,0x89,0x60,0x83,0x19,0x21,0x04,0x9C,0x57,0xFE,0x91,0x30,0xBD,0x7C,0x83, + 0x45,0xA3,0xA1,0x11,0x0A,0x29,0xCF,0x6C,0x55,0x47,0xC3,0x7B,0x8C,0xEE,0x43,0xFE, + 0x42,0x0F,0xE6,0xCE,0xC7,0x24,0xAF,0x21,0x2E,0xC7,0xFD,0xFA,0xBA,0x7E,0xCE,0xA3, + 0x9D,0x92,0x5B,0x54,0x4C,0x4F,0x14,0x55,0xD6,0x5F,0xB0,0xB0,0x73,0xFD,0x78,0x61, + 0xDC,0xF6,0xA1,0xB6,0xFF,0xAF,0x3B,0x49,0x6F,0x62,0x95,0xD0,0x4E,0xA9,0x3F,0xE8, + 0x5C,0xCD,0x36,0xEA,0xED,0x57,0x04,0x32,0xB6,0xB0,0x91,0xDC,0x32,0xA6,0xC7,0x84, + 0x9C,0x3F,0x24,0x3A,0x64,0x56,0x62,0xA2,0x02,0x15,0xC9,0x63,0x96,0x8E,0x6C,0xF5, + 0x3E,0xB1,0xE4,0x3C,0x79,0x63,0xE0,0x94,0xE8,0xD0,0x73,0x31,0x7B,0x3C,0x99,0x66, + 0x82,0x2D,0x47,0x49,0x22,0x33,0xD4,0xD1,0x80,0x35,0xF1,0xB1,0xFD,0x01,0x92,0x07, + 0x6B,0x1E,0xF1,0xD0,0x02,0x84,0x24,0xD6,0xDF,0x2F,0x10,0x06,0x0F,0x36,0x5D,0x4B, + 0x1A,0xE3,0xDB,0x1F,0x8C,0x54,0x07,0x63,0x41,0x9E,0x74,0x6E,0x6F,0x9D,0xCE,0xCC, + 0x36,0x7B,0xE0,0xC5,0xCB,0x04,0x12,0xFF,0xF3,0x09,0xD7,0x36,0x5D,0x09,0xD0,0xCD, + 0xF2,0x73,0xAA,0x10,0x5D,0x0D,0xC2,0x12,0x21,0x00,0x89,0xE5,0x34,0x17,0x6C,0x76, + 0xE2,0x2F,0xDA,0xBD,0xCA,0xFB,0x9D,0xF2,0x1C,0x3B,0x62,0xCA,0xC0,0x97,0x82,0x54, + 0x92,0x4E,0x0C,0xD0,0x3B,0x79,0xD0,0x41,0x29,0x84,0xF5,0x75,0x40,0xB4,0xE8, +}; + + +/* ----- IMPORTANT ----- + When replacing the valid_ist_certificate, the value of _valid_ist_eval_abs_time + must also be changed to a CFAbsoluteTime value that falls within the validity + period of the certificate. +*/ +static const CFAbsoluteTime _valid_ist_eval_abs_time = 626262626; /* Nov 05, 2020 */ + +/* + * Subject: CN = valid.apple.com,OU = management:idms.group.665035, + * O = Apple Inc.,ST = California,C = US + * Issuer: CN = Apple IST CA 2 - G1,OU = Certification Authority, + * O = Apple Inc.,C = US + */ +static const uint8_t _valid_ist_certificate[] = { + 0x30,0x82,0x08,0x30,0x30,0x82,0x07,0x18,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x10,0x66,0x63,0xAD,0xE6,0x3A, + 0xBE,0xEC,0xE8,0x78,0xFB,0xF3,0x55,0x82,0x49,0x0A, + 0xAC,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x1C, + 0x30,0x1A,0x06,0x03,0x55,0x04,0x03,0x13,0x13,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43, + 0x41,0x20,0x32,0x20,0x2D,0x20,0x47,0x31,0x31,0x20, + 0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13,0x17,0x43, + 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D, + 0x31,0x39,0x30,0x33,0x31,0x31,0x32,0x31,0x34,0x32, + 0x33,0x31,0x5A,0x17,0x0D,0x32,0x31,0x30,0x34,0x30, + 0x39,0x32,0x31,0x34,0x32,0x33,0x31,0x5A,0x30,0x78, + 0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x0F,0x76,0x61,0x6C,0x69,0x64,0x2E,0x61,0x70,0x70, + 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x25,0x30,0x23, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x1C,0x6D,0x61,0x6E, + 0x61,0x67,0x65,0x6D,0x65,0x6E,0x74,0x3A,0x69,0x64, + 0x6D,0x73,0x2E,0x67,0x72,0x6F,0x75,0x70,0x2E,0x36, + 0x36,0x35,0x30,0x33,0x35,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C, + 0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03, + 0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82, + 0x01,0x01,0x00,0xD4,0xF7,0xFA,0x5D,0x57,0x79,0xFE, + 0x5B,0xBD,0x8E,0x56,0x75,0x2E,0x12,0x3B,0xAB,0xEC, + 0xF3,0xA2,0x3D,0xD5,0x87,0x74,0xC4,0xD3,0xA9,0xD1, + 0x42,0xCA,0x28,0xFF,0x54,0x90,0xE1,0x0F,0xD7,0x2A, + 0x23,0xE7,0x82,0xC0,0x68,0x83,0x5F,0xDB,0x44,0x25, + 0xFD,0x60,0xFD,0xE6,0xE1,0x51,0xD3,0x72,0x42,0xE6, + 0x9D,0x7F,0x50,0xB8,0x5F,0xD6,0x56,0x46,0x52,0x0B, + 0x75,0xE3,0x0C,0x66,0x96,0xB7,0xAB,0xC0,0xCE,0x98, + 0x5E,0xB7,0x0C,0xBF,0x50,0x6D,0x35,0x70,0x55,0x76, + 0x57,0xF6,0x9B,0x37,0x7F,0x4E,0xDD,0x8B,0x31,0x4A, + 0x9B,0xD7,0xDA,0xEA,0x7F,0x34,0x92,0x85,0xA7,0x57, + 0x94,0xB7,0xB7,0xC5,0x7B,0x69,0xFA,0xC1,0x66,0xF0, + 0x9B,0x0B,0x64,0xE5,0x37,0x10,0x4C,0x1C,0x6F,0x10, + 0xDA,0xC5,0x17,0xBF,0x93,0x95,0x5F,0x21,0x81,0xA9, + 0xB6,0xE3,0x77,0x37,0xEB,0x39,0x44,0x52,0x3B,0xD6, + 0x92,0x73,0x16,0x2E,0xDB,0xC8,0x49,0x38,0xBB,0xAC, + 0x77,0x2E,0x00,0x96,0xF0,0xB3,0x45,0x62,0x69,0x8C, + 0x9D,0x80,0x06,0x98,0xAC,0x46,0xF3,0x28,0x14,0x90, + 0x2A,0x90,0x0F,0x05,0x32,0x62,0xA3,0xEC,0x0A,0x2F, + 0x1D,0x6C,0x86,0x73,0xA4,0x94,0x4C,0xDF,0xFE,0xEB, + 0xFB,0x49,0x6C,0xE3,0xA8,0x71,0x3C,0x39,0x20,0x7E, + 0x2C,0x31,0x3C,0xC5,0xB0,0x44,0x36,0xC9,0x7C,0xCE, + 0xFE,0x1E,0x2F,0xD4,0xEB,0x27,0x8D,0xEF,0x64,0x7D, + 0xE9,0xED,0x61,0x43,0x8E,0x07,0x6C,0x7B,0x24,0xFA, + 0xFD,0xAD,0x9A,0xB6,0xC9,0xC1,0x60,0x29,0x1C,0x6F, + 0x1F,0xD1,0x79,0x6E,0x0C,0x88,0x0F,0x6A,0x07,0x02, + 0x03,0x01,0x00,0x01,0xA3,0x82,0x04,0xCA,0x30,0x82, + 0x04,0xC6,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01, + 0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06,0x03, + 0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xD8, + 0x7A,0x94,0x44,0x7C,0x90,0x70,0x90,0x16,0x9E,0xDD, + 0x17,0x9C,0x01,0x44,0x03,0x86,0xD6,0x2A,0x29,0x30, + 0x7E,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01, + 0x01,0x04,0x72,0x30,0x70,0x30,0x34,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x28,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x65,0x72,0x74, + 0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, + 0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74, + 0x63,0x61,0x32,0x67,0x31,0x2E,0x64,0x65,0x72,0x30, + 0x38,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30, + 0x01,0x86,0x2C,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x6F,0x63,0x73,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65, + 0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30, + 0x33,0x2D,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74, + 0x63,0x61,0x32,0x67,0x31,0x32,0x30,0x30,0x1A,0x06, + 0x03,0x55,0x1D,0x11,0x04,0x13,0x30,0x11,0x82,0x0F, + 0x76,0x61,0x6C,0x69,0x64,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x30,0x81,0xFF,0x06,0x03, + 0x55,0x1D,0x20,0x04,0x81,0xF7,0x30,0x81,0xF4,0x30, + 0x81,0xF1,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63, + 0x64,0x05,0x0B,0x04,0x30,0x81,0xE2,0x30,0x81,0xA4, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02, + 0x30,0x81,0x97,0x0C,0x81,0x94,0x52,0x65,0x6C,0x69, + 0x61,0x6E,0x63,0x65,0x20,0x6F,0x6E,0x20,0x74,0x68, + 0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69, + 0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E, + 0x79,0x20,0x70,0x61,0x72,0x74,0x79,0x20,0x61,0x73, + 0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65, + 0x70,0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20, + 0x61,0x6E,0x79,0x20,0x61,0x70,0x70,0x6C,0x69,0x63, + 0x61,0x62,0x6C,0x65,0x20,0x74,0x65,0x72,0x6D,0x73, + 0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x64,0x69, + 0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75, + 0x73,0x65,0x20,0x61,0x6E,0x64,0x2F,0x6F,0x72,0x20, + 0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, + 0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69, + 0x63,0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65, + 0x6E,0x74,0x73,0x2E,0x30,0x39,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x2D,0x68,0x74, + 0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x63, + 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65, + 0x61,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2F, + 0x72,0x70,0x61,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25, + 0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x02,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x01,0x30,0x37,0x06,0x03,0x55,0x1D, + 0x1F,0x04,0x30,0x30,0x2E,0x30,0x2C,0xA0,0x2A,0xA0, + 0x28,0x86,0x26,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x63,0x72,0x6C,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, + 0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x69, + 0x73,0x74,0x63,0x61,0x32,0x67,0x31,0x2E,0x63,0x72, + 0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0xDC,0x4F,0x6B,0xFD,0x6C,0x63,0x1E,0x86, + 0xD6,0x8E,0x74,0x3B,0xE5,0x41,0xDA,0x4C,0xAB,0x09, + 0x01,0x5B,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, + 0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x82, + 0x02,0x6E,0x06,0x0A,0x2B,0x06,0x01,0x04,0x01,0xD6, + 0x79,0x02,0x04,0x02,0x04,0x82,0x02,0x5E,0x04,0x82, + 0x02,0x5A,0x02,0x58,0x00,0x76,0x00,0xBB,0xD9,0xDF, + 0xBC,0x1F,0x8A,0x71,0xB5,0x93,0x94,0x23,0x97,0xAA, + 0x92,0x7B,0x47,0x38,0x57,0x95,0x0A,0xAB,0x52,0xE8, + 0x1A,0x90,0x96,0x64,0x36,0x8E,0x1E,0xD1,0x85,0x00, + 0x00,0x01,0x69,0x6E,0xBE,0x30,0xE2,0x00,0x00,0x04, + 0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x50,0x92,0x0B, + 0xF7,0xE0,0xEA,0x60,0x63,0x26,0x09,0x23,0x40,0x83, + 0x95,0x50,0xF1,0x05,0x49,0x26,0x6D,0x47,0x65,0xD6, + 0x2B,0x48,0x0E,0xC9,0x19,0xDB,0x96,0x05,0x49,0x02, + 0x21,0x00,0xC5,0x3F,0x5B,0xE0,0x21,0x70,0xC8,0xA6, + 0xD7,0xE2,0xF7,0xE2,0xF5,0xD0,0x9A,0x8F,0xBF,0x90, + 0xFD,0x74,0x92,0x09,0xBD,0x07,0x9F,0x75,0x34,0xC1, + 0x81,0x91,0x33,0xC7,0x00,0x76,0x00,0xA4,0xB9,0x09, + 0x90,0xB4,0x18,0x58,0x14,0x87,0xBB,0x13,0xA2,0xCC, + 0x67,0x70,0x0A,0x3C,0x35,0x98,0x04,0xF9,0x1B,0xDF, + 0xB8,0xE3,0x77,0xCD,0x0E,0xC8,0x0D,0xDC,0x10,0x00, + 0x00,0x01,0x69,0x6E,0xBE,0x30,0xE4,0x00,0x00,0x04, + 0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x50,0x97,0x7E, + 0x7B,0x6F,0x34,0xB6,0x59,0x1E,0xB6,0x85,0x1F,0xF5, + 0x79,0x7C,0x81,0x7A,0xA9,0x27,0xAB,0xF9,0x5B,0xC8, + 0x98,0xF6,0x35,0xAA,0x64,0x38,0x3A,0x8E,0x53,0x02, + 0x21,0x00,0xA0,0x85,0xE3,0xE9,0x52,0x6A,0xC7,0x6B, + 0x63,0x03,0x64,0x3C,0x09,0x9F,0x57,0x45,0x70,0xA7, + 0xC3,0x3C,0xC6,0x9E,0x3F,0xC0,0xEE,0x0B,0x62,0x76, + 0xB6,0xB6,0x76,0x7F,0x00,0x76,0x00,0x55,0x81,0xD4, + 0xC2,0x16,0x90,0x36,0x01,0x4A,0xEA,0x0B,0x9B,0x57, + 0x3C,0x53,0xF0,0xC0,0xE4,0x38,0x78,0x70,0x25,0x08, + 0x17,0x2F,0xA3,0xAA,0x1D,0x07,0x13,0xD3,0x0C,0x00, + 0x00,0x01,0x69,0x6E,0xBE,0x30,0xFC,0x00,0x00,0x04, + 0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x22,0x95,0x3C, + 0x5A,0x32,0xA9,0x0A,0x73,0xA4,0xBA,0x7D,0xA1,0x7B, + 0x62,0xF1,0x3B,0xD8,0x49,0xA6,0x3C,0x39,0xD3,0x6A, + 0x74,0x85,0x5A,0x1B,0xA3,0x39,0x15,0xB0,0x69,0x02, + 0x21,0x00,0x8F,0xD5,0x56,0x18,0x1D,0xBE,0x6B,0xD3, + 0xA5,0x3E,0xB6,0xEA,0xB6,0x09,0xAF,0xF3,0xF8,0xE9, + 0x22,0x5F,0x20,0x89,0x8F,0x9A,0x4C,0xD5,0x5B,0x22, + 0x23,0x72,0x5D,0x2A,0x00,0x77,0x00,0x6F,0x53,0x76, + 0xAC,0x31,0xF0,0x31,0x19,0xD8,0x99,0x00,0xA4,0x51, + 0x15,0xFF,0x77,0x15,0x1C,0x11,0xD9,0x02,0xC1,0x00, + 0x29,0x06,0x8D,0xB2,0x08,0x9A,0x37,0xD9,0x13,0x00, + 0x00,0x01,0x69,0x6E,0xBE,0x31,0x1F,0x00,0x00,0x04, + 0x03,0x00,0x48,0x30,0x46,0x02,0x21,0x00,0xE7,0x8F, + 0x9A,0xC4,0x8B,0xA1,0x16,0x85,0x30,0x3E,0x8A,0xD7, + 0x6F,0x34,0x9E,0x68,0x43,0x6C,0x50,0xE1,0x1B,0xF6, + 0xCE,0x2E,0xFF,0x7D,0x26,0x27,0x17,0xC4,0x6C,0xB4, + 0x02,0x21,0x00,0xA0,0x32,0xCF,0x08,0xA2,0xA7,0xDA, + 0xE4,0xD2,0x6D,0x24,0x3B,0x96,0xA3,0x4B,0x9A,0xAC, + 0xEC,0xA2,0x7E,0x19,0xAB,0xB7,0xEC,0xE0,0xDA,0x2F, + 0xD9,0xD1,0xEE,0x00,0xBC,0x00,0x75,0x00,0x44,0x94, + 0x65,0x2E,0xB0,0xEE,0xCE,0xAF,0xC4,0x40,0x07,0xD8, + 0xA8,0xFE,0x28,0xC0,0xDA,0xE6,0x82,0xBE,0xD8,0xCB, + 0x31,0xB5,0x3F,0xD3,0x33,0x96,0xB5,0xB6,0x81,0xA8, + 0x00,0x00,0x01,0x69,0x6E,0xBE,0x31,0x00,0x00,0x00, + 0x04,0x03,0x00,0x46,0x30,0x44,0x02,0x20,0x09,0xB4, + 0xC7,0x34,0x94,0x87,0x95,0x05,0xAA,0xE8,0xF1,0x07, + 0x6C,0x83,0xD7,0x68,0x7C,0x71,0x94,0xBD,0x39,0x6E, + 0x63,0xA5,0x05,0x39,0x15,0x99,0x3F,0xC1,0xE8,0x1E, + 0x02,0x20,0x20,0xD1,0x40,0xAB,0x36,0x6B,0x98,0x9E, + 0x44,0x9C,0x83,0x8C,0x08,0xE0,0x89,0x17,0x17,0x81, + 0x9B,0x80,0x3C,0xB9,0xE4,0x4F,0xA0,0x47,0x3D,0xC3, + 0x16,0x01,0x0E,0x2E,0x30,0x0D,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x8C,0x47,0x9E,0xD7,0x8B,0x52, + 0xB6,0x6F,0x27,0x35,0xBC,0xF1,0x49,0x0D,0xC0,0xA6, + 0x1C,0x9F,0xD8,0x2B,0xAD,0x55,0xCD,0x2E,0x6F,0x86, + 0x08,0x29,0x55,0xAC,0x7C,0x91,0xFE,0xC0,0xA0,0xC6, + 0xC8,0x02,0x98,0xB1,0x93,0xBA,0xC2,0x2B,0xCD,0x2D, + 0x3F,0xF9,0x94,0x8F,0x5F,0x7F,0xC5,0x9F,0xA3,0xC0, + 0x69,0x08,0x48,0xB9,0x3A,0x2E,0xB4,0x40,0xA2,0x41, + 0x26,0x4B,0x5C,0xE5,0xF0,0x0E,0xF7,0x9E,0x6A,0x41, + 0x1C,0xAD,0x84,0x62,0xA5,0x5A,0x63,0xD5,0x0C,0xD5, + 0x5A,0x43,0x07,0xFD,0x00,0x72,0xFD,0x6C,0xFD,0xF4, + 0xB9,0xC0,0x1C,0x57,0x32,0xBC,0x4B,0x46,0x35,0xC5, + 0xBE,0x40,0x6F,0x52,0xEB,0x4B,0xD5,0xBB,0xD6,0x74, + 0xB8,0x36,0x3E,0x25,0x6B,0xC4,0xE5,0xB9,0xE1,0x16, + 0xAF,0xD3,0x38,0x59,0x5E,0x54,0x6B,0x14,0x7E,0xA1, + 0x9B,0x43,0xAA,0x51,0xF6,0x65,0xB8,0x95,0x38,0x81, + 0x8B,0xA2,0x34,0x53,0x73,0xF2,0xE5,0xC1,0x4D,0x89, + 0xA4,0xC1,0x2B,0x9B,0x61,0x1B,0xDE,0x88,0xDC,0xAE, + 0xFD,0xE9,0xBD,0xFC,0x3D,0x98,0x5B,0x7D,0x5B,0xFC, + 0xDD,0x90,0xD2,0x21,0xBD,0x12,0x6B,0x06,0x14,0xEE, + 0xC3,0xDD,0x77,0x24,0xE4,0x57,0xBC,0x23,0xCE,0x15, + 0xA4,0x40,0x5A,0x3D,0x63,0x64,0x70,0x63,0x5D,0x04, + 0x46,0xEA,0xA5,0x8D,0x17,0x5E,0x75,0xF6,0x0C,0x0C, + 0xBE,0x14,0xB3,0xA9,0xF4,0x79,0xD9,0x04,0x7A,0x78, + 0x12,0xF1,0x64,0xB7,0xD0,0x3F,0x64,0xBD,0xC1,0xD7, + 0x28,0xDD,0xF9,0x54,0x7B,0x9B,0x1C,0xA5,0xE4,0x15, + 0x3F,0xF1,0xFA,0x4E,0x47,0xFB,0xEC,0xAF,0x38,0x0E +}; + +/* + * Subject: CN = test-pages.certificatemanager.apple.com, + * OU = management:idms.group.864859,O = Apple Inc.,ST = California,C = US + * Issuer: CN = Apple IST CA 2 - G1,OU = Certification Authority, + * O = Apple Inc.,C = US + */ +static const uint8_t _revoked_ist_certificate[] = { + 0x30,0x82,0x06,0x33,0x30,0x82,0x05,0x1B,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x10,0x52,0x98,0xD4,0x52,0x20, + 0x81,0x67,0xE7,0xAD,0xBC,0x55,0xE3,0xC7,0x9F,0x88, + 0xFC,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x1C, + 0x30,0x1A,0x06,0x03,0x55,0x04,0x03,0x13,0x13,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43, + 0x41,0x20,0x32,0x20,0x2D,0x20,0x47,0x31,0x31,0x20, + 0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13,0x17,0x43, + 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D, + 0x31,0x39,0x30,0x35,0x31,0x35,0x31,0x37,0x33,0x36, + 0x30,0x35,0x5A,0x17,0x0D,0x32,0x30,0x31,0x32,0x31, + 0x33,0x31,0x37,0x34,0x36,0x30,0x30,0x5A,0x30,0x81, + 0x90,0x31,0x30,0x30,0x2E,0x06,0x03,0x55,0x04,0x03, + 0x0C,0x27,0x74,0x65,0x73,0x74,0x2D,0x70,0x61,0x67, + 0x65,0x73,0x2E,0x63,0x65,0x72,0x74,0x69,0x66,0x69, + 0x63,0x61,0x74,0x65,0x6D,0x61,0x6E,0x61,0x67,0x65, + 0x72,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, + 0x6D,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B, + 0x0C,0x1C,0x6D,0x61,0x6E,0x61,0x67,0x65,0x6D,0x65, + 0x6E,0x74,0x3A,0x69,0x64,0x6D,0x73,0x2E,0x67,0x72, + 0x6F,0x75,0x70,0x2E,0x38,0x36,0x34,0x38,0x35,0x39, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E, + 0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, + 0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30, + 0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xD9,0x85, + 0x63,0x69,0x86,0x6A,0x37,0x5C,0xDD,0x89,0x1F,0x9C, + 0xED,0x3B,0xC6,0x35,0xFC,0x80,0x5B,0x05,0xF3,0xC7, + 0xCD,0xCD,0x39,0xF7,0x98,0x26,0x5E,0x5D,0x06,0x12, + 0x39,0xD2,0x1B,0xC3,0x93,0xAD,0xD2,0xB8,0xD7,0x48, + 0x5B,0x5C,0x38,0x0E,0x34,0xB7,0x6A,0x37,0xFC,0xBC, + 0x67,0x33,0x1C,0xDA,0x5F,0x1C,0x1B,0x11,0x7B,0xBC, + 0x8C,0x0A,0xCD,0x81,0xA1,0x73,0xC7,0x6A,0xBF,0x1C, + 0xE0,0x7B,0x0B,0xDC,0xF5,0x1E,0xFB,0x69,0xCB,0xE6, + 0x4C,0x73,0xFE,0xAF,0xF2,0x36,0xE2,0x6B,0xC5,0xC2, + 0xF1,0xD1,0x45,0x63,0x8A,0xA7,0x55,0x56,0xCC,0xD7, + 0xEB,0x25,0xB0,0x2D,0xC9,0xA6,0x70,0x01,0x31,0xBE, + 0xFE,0xD0,0xFE,0x60,0xE6,0x31,0x23,0x76,0x22,0x07, + 0xFD,0x2D,0x17,0xA8,0x89,0x48,0x77,0x32,0x63,0xFB, + 0x8D,0x5B,0x63,0xED,0x43,0xB6,0x21,0xC8,0x01,0x74, + 0xD7,0xF9,0xD9,0x05,0x0C,0x6B,0x97,0xF0,0x39,0x42, + 0x50,0x69,0x2B,0x54,0xBE,0x86,0x0A,0xB5,0x99,0x7D, + 0xCC,0xEC,0x6C,0xC2,0xE8,0x06,0x14,0xAD,0x3A,0x48, + 0xF2,0x92,0x3F,0x23,0x14,0x49,0x74,0xA5,0x40,0x4F, + 0x3A,0xA5,0x08,0x37,0x4A,0x09,0x6F,0xD7,0x1F,0x97, + 0xC1,0xB3,0xD9,0x49,0xF0,0x3B,0x7C,0x97,0xB7,0x62, + 0x1F,0xF5,0x86,0xFA,0xC2,0xF2,0xB7,0xE5,0xDF,0x01, + 0xBB,0x5A,0x41,0x40,0xEC,0x7A,0x96,0x6B,0xC3,0x55, + 0x28,0x2B,0x04,0x8C,0xE9,0x46,0xAD,0x53,0xFF,0x3C, + 0x26,0x4E,0xD3,0xA4,0x1D,0x2A,0xBF,0x27,0x89,0x60, + 0x2E,0x9B,0xF2,0xC5,0x6F,0x3D,0xC3,0xE7,0x68,0x21, + 0xE1,0xC9,0xA4,0xCD,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x82,0x02,0xB4,0x30,0x82,0x02,0xB0,0x30,0x0C,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18, + 0x30,0x16,0x80,0x14,0xD8,0x7A,0x94,0x44,0x7C,0x90, + 0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C,0x01,0x44,0x03, + 0x86,0xD6,0x2A,0x29,0x30,0x7E,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x72,0x30,0x70, + 0x30,0x34,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x30,0x02,0x86,0x28,0x68,0x74,0x74,0x70,0x3A,0x2F, + 0x2F,0x63,0x65,0x72,0x74,0x73,0x2E,0x61,0x70,0x70, + 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70, + 0x6C,0x65,0x69,0x73,0x74,0x63,0x61,0x32,0x67,0x31, + 0x2E,0x64,0x65,0x72,0x30,0x38,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x2C,0x68,0x74, + 0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, + 0x6F,0x63,0x73,0x70,0x30,0x33,0x2D,0x61,0x70,0x70, + 0x6C,0x65,0x69,0x73,0x74,0x63,0x61,0x32,0x67,0x31, + 0x30,0x31,0x30,0x76,0x06,0x03,0x55,0x1D,0x11,0x04, + 0x6F,0x30,0x6D,0x82,0x27,0x74,0x65,0x73,0x74,0x2D, + 0x70,0x61,0x67,0x65,0x73,0x2E,0x63,0x65,0x72,0x74, + 0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x6D,0x61,0x6E, + 0x61,0x67,0x65,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65, + 0x2E,0x63,0x6F,0x6D,0x82,0x42,0x72,0x65,0x76,0x6F, + 0x6B,0x65,0x64,0x2E,0x67,0x65,0x6F,0x74,0x72,0x75, + 0x73,0x74,0x2D,0x67,0x6C,0x6F,0x62,0x61,0x6C,0x2D, + 0x63,0x61,0x2E,0x74,0x65,0x73,0x74,0x2D,0x70,0x61, + 0x67,0x65,0x73,0x2E,0x63,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x65,0x6D,0x61,0x6E,0x61,0x67, + 0x65,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63, + 0x6F,0x6D,0x30,0x81,0xFF,0x06,0x03,0x55,0x1D,0x20, + 0x04,0x81,0xF7,0x30,0x81,0xF4,0x30,0x81,0xF1,0x06, + 0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x05,0x0B, + 0x04,0x30,0x81,0xE2,0x30,0x81,0xA4,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x81,0x97, + 0x0C,0x81,0x94,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63, + 0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20, + 0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, + 0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70, + 0x61,0x72,0x74,0x79,0x20,0x61,0x73,0x73,0x75,0x6D, + 0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74,0x61, + 0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x61,0x6E,0x79, + 0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C, + 0x65,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E, + 0x64,0x20,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F, + 0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x20, + 0x61,0x6E,0x64,0x2F,0x6F,0x72,0x20,0x63,0x65,0x72, + 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, + 0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20, + 0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73, + 0x2E,0x30,0x39,0x06,0x08,0x2B,0x06,0x01,0x05,0x05, + 0x07,0x02,0x01,0x16,0x2D,0x68,0x74,0x74,0x70,0x3A, + 0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x65,0x72,0x74, + 0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x61,0x75,0x74, + 0x68,0x6F,0x72,0x69,0x74,0x79,0x2F,0x72,0x70,0x61, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30, + 0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03, + 0x02,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03, + 0x01,0x30,0x37,0x06,0x03,0x55,0x1D,0x1F,0x04,0x30, + 0x30,0x2E,0x30,0x2C,0xA0,0x2A,0xA0,0x28,0x86,0x26, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C, + 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x2F,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74,0x63, + 0x61,0x32,0x67,0x31,0x2E,0x63,0x72,0x6C,0x30,0x1D, + 0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xBF, + 0xDE,0xD1,0xF9,0x91,0x1B,0x01,0x51,0xC0,0x82,0xAD, + 0x6E,0xB2,0x10,0x15,0x87,0x17,0x2A,0xC8,0x41,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x05,0xA0,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x84,0x1B,0x66,0x0E,0xFF, + 0x5C,0x8C,0x99,0x66,0xF0,0x2C,0x08,0xEF,0x1C,0xF1, + 0x7C,0xDB,0x13,0x73,0x34,0xA4,0x63,0x07,0xD3,0xE5, + 0xC6,0xFA,0xC8,0x20,0x19,0x95,0xDA,0x95,0xDA,0x8D, + 0x18,0x68,0xFC,0xC2,0xEB,0x09,0xBE,0x51,0x3A,0xAA, + 0x8D,0xAC,0x64,0x67,0xAC,0x58,0x07,0x1A,0xA2,0xF8, + 0xB3,0x78,0x1E,0xF9,0x85,0x05,0xDD,0x52,0xC6,0xDE, + 0x00,0x78,0x39,0x9A,0xE8,0x2D,0xE6,0xF9,0x5F,0xDC, + 0xF5,0x0B,0x6D,0xE5,0xF5,0x6F,0xC1,0x4A,0x87,0xCA, + 0x30,0x62,0x42,0x65,0x37,0x54,0xD8,0x9C,0xB8,0x54, + 0x80,0x55,0xE5,0xB4,0xC7,0x70,0x0F,0x11,0x6B,0x4D, + 0x16,0x38,0x10,0x15,0x61,0x7A,0xD8,0x6D,0x7B,0xAC, + 0xF5,0x0B,0xE2,0xF1,0x98,0xA8,0xE6,0x84,0x8A,0xB3, + 0xB8,0x1C,0x6B,0xFC,0x4D,0xF4,0x8D,0x5B,0xAA,0xE5, + 0xCC,0x9A,0x9D,0x6B,0x08,0x45,0xF8,0x89,0x87,0xDF, + 0xB7,0x19,0x70,0xED,0x34,0xC4,0x79,0x1E,0x88,0x2E, + 0x19,0x65,0x17,0x11,0xF4,0xAD,0x96,0xE2,0x1B,0x15, + 0x9F,0x5A,0xF0,0xC6,0xDB,0x5C,0x93,0x65,0x26,0x82, + 0x04,0xE7,0xC1,0x72,0x44,0xA6,0x70,0xAB,0x66,0xC1, + 0x13,0x43,0x34,0x3A,0xBA,0xD1,0xBB,0x8C,0x92,0x6D, + 0x18,0x45,0xC3,0xFB,0xC7,0x6D,0x93,0xE3,0xEB,0x6A, + 0xD0,0x9F,0xD5,0xC7,0x5F,0x25,0x35,0x45,0x5A,0x58, + 0x15,0x69,0x7C,0x1D,0x47,0x7C,0x24,0x16,0x99,0xB9, + 0x84,0x3A,0xBF,0x77,0x67,0xE3,0xAD,0x35,0x78,0xC4, + 0xCC,0xD0,0x91,0x29,0x50,0xE1,0x82,0xC1,0x8C,0x0F, + 0x41,0x3D,0x19,0x5B,0x2C,0xD4,0x85,0x45,0xCF,0x26, + 0x39 +}; + +/* + * Subject: CN = Apple IST CA 2 - G1,OU = Certification Authority, + * O = Apple Inc.,C = US + * Issuer: C = US,O = GeoTrust Inc.,CN = GeoTrust Global CA + */ +static const uint8_t _ist_intermediate_certificate[] = { + 0x30,0x82,0x04,0x40,0x30,0x82,0x03,0x28,0xA0,0x03, + 0x02,0x01,0x02,0x02,0x03,0x02,0x3A,0x74,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x30,0x42,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x16, + 0x30,0x14,0x06,0x03,0x55,0x04,0x0A,0x13,0x0D,0x47, + 0x65,0x6F,0x54,0x72,0x75,0x73,0x74,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04, + 0x03,0x13,0x12,0x47,0x65,0x6F,0x54,0x72,0x75,0x73, + 0x74,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x43, + 0x41,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x36,0x31, + 0x36,0x31,0x35,0x34,0x32,0x30,0x32,0x5A,0x17,0x0D, + 0x32,0x32,0x30,0x35,0x32,0x30,0x31,0x35,0x34,0x32, + 0x30,0x32,0x5A,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06, + 0x03,0x55,0x04,0x03,0x13,0x13,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20,0x32, + 0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06, + 0x03,0x55,0x04,0x0B,0x13,0x17,0x43,0x65,0x72,0x74, + 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20, + 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, + 0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, + 0x0A,0x02,0x82,0x01,0x01,0x00,0xD0,0x93,0xA1,0x1D, + 0x47,0x43,0x20,0x16,0xB2,0x0B,0x6B,0xEB,0xC3,0xD5, + 0xB4,0xE8,0xC7,0x98,0xCD,0xF3,0xDE,0xBF,0xE8,0x4D, + 0xE9,0xE3,0x36,0x80,0x07,0xFC,0x45,0x1B,0x6A,0x7C, + 0x45,0x86,0xAE,0x56,0xD3,0xA4,0x09,0x7F,0x61,0x0D, + 0x6B,0x5D,0x7E,0x52,0x6B,0x7D,0xB4,0xC8,0x39,0xC4, + 0xF4,0x67,0x3A,0xF7,0x83,0xCE,0x19,0x6F,0x86,0x2F, + 0x7E,0x45,0x7E,0x47,0x1C,0x67,0x52,0xCA,0x95,0x05, + 0x5D,0xE2,0x36,0x51,0x85,0xC0,0xD4,0x67,0x80,0x35, + 0x6F,0x15,0xDD,0x3E,0xFD,0x1D,0xD2,0xFD,0x8F,0x34, + 0x50,0xD8,0xEC,0x76,0x2A,0xBE,0xE3,0xD3,0xDA,0xE4, + 0xFD,0xC8,0xEB,0x28,0x02,0x96,0x11,0x97,0x17,0x61, + 0x1C,0xE9,0xC4,0x59,0x3B,0x42,0xDC,0x32,0xD1,0x09, + 0x1D,0xDA,0xA6,0xD1,0x43,0x86,0xFF,0x5E,0xB2,0xBC, + 0x8C,0xCF,0x66,0xDB,0x01,0x8B,0x02,0xAE,0x94,0x48, + 0xF3,0x38,0x8F,0xFD,0xEA,0x32,0xA8,0x08,0xEC,0x86, + 0x97,0x51,0x94,0x24,0x3E,0x49,0x49,0x96,0x53,0xE8, + 0x79,0xA1,0x40,0x81,0xE9,0x05,0xBB,0x93,0x95,0x51, + 0xFC,0xE3,0xFD,0x7C,0x11,0x4B,0xF7,0x9E,0x08,0xB3, + 0x15,0x49,0x15,0x07,0xF9,0xD1,0x37,0xA0,0x9B,0x4B, + 0x32,0xF6,0xB5,0xC4,0xDC,0x6A,0xD1,0xFC,0x0A,0xED, + 0xF6,0xE0,0xC5,0x29,0xA0,0xA8,0x8B,0x71,0xFE,0x0D, + 0x92,0xBC,0xFE,0x54,0x70,0x18,0x0A,0x6D,0xC7,0xED, + 0x0C,0xFB,0xC9,0x2D,0x06,0xC3,0x8C,0x85,0xFC,0xCB, + 0x86,0x5C,0xD6,0x36,0x8E,0x12,0x8B,0x09,0x7F,0xFB, + 0x19,0x1A,0x38,0xD5,0xF0,0x94,0x30,0x7A,0x0F,0xA6, + 0x8C,0xF3,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01, + 0x1D,0x30,0x82,0x01,0x19,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xC0,0x7A, + 0x98,0x68,0x8D,0x89,0xFB,0xAB,0x05,0x64,0x0C,0x11, + 0x7D,0xAA,0x7D,0x65,0xB8,0xCA,0xCC,0x4E,0x30,0x1D, + 0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xD8, + 0x7A,0x94,0x44,0x7C,0x90,0x70,0x90,0x16,0x9E,0xDD, + 0x17,0x9C,0x01,0x44,0x03,0x86,0xD6,0x2A,0x29,0x30, + 0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x01,0x06,0x30,0x35,0x06,0x03,0x55, + 0x1D,0x1F,0x04,0x2E,0x30,0x2C,0x30,0x2A,0xA0,0x28, + 0xA0,0x26,0x86,0x24,0x68,0x74,0x74,0x70,0x3A,0x2F, + 0x2F,0x67,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E,0x63, + 0x6F,0x6D,0x2F,0x63,0x72,0x6C,0x73,0x2F,0x67,0x74, + 0x67,0x6C,0x6F,0x62,0x61,0x6C,0x2E,0x63,0x72,0x6C, + 0x30,0x2E,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x01,0x01,0x04,0x22,0x30,0x20,0x30,0x1E,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x12, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x67,0x2E,0x73, + 0x79,0x6D,0x63,0x64,0x2E,0x63,0x6F,0x6D,0x30,0x4C, + 0x06,0x03,0x55,0x1D,0x20,0x04,0x45,0x30,0x43,0x30, + 0x41,0x06,0x0A,0x60,0x86,0x48,0x01,0x86,0xF8,0x45, + 0x01,0x07,0x36,0x30,0x33,0x30,0x31,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x25,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E, + 0x67,0x65,0x6F,0x74,0x72,0x75,0x73,0x74,0x2E,0x63, + 0x6F,0x6D,0x2F,0x72,0x65,0x73,0x6F,0x75,0x72,0x63, + 0x65,0x73,0x2F,0x63,0x70,0x73,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x03,0x82,0x01,0x01,0x00,0x16,0x47,0x73,0x6F, + 0x85,0xA2,0x62,0xE1,0xE7,0x2A,0x76,0xBB,0x89,0x95, + 0x42,0x26,0x97,0xBC,0x4A,0xAC,0xAC,0x70,0x53,0x3A, + 0x3F,0x31,0x83,0x3D,0x3C,0x1C,0xAB,0x9A,0xE2,0xB1, + 0x5D,0x1C,0x76,0x1A,0xA0,0x3C,0x0C,0x72,0x57,0xBE, + 0xD3,0x9E,0x50,0xE0,0xC8,0x99,0xD6,0x58,0xD7,0x02, + 0xEA,0xCE,0x0D,0x29,0x54,0x7C,0xCD,0xF5,0xC2,0xC6, + 0x90,0x29,0x55,0xA3,0x6F,0x14,0xA8,0x0B,0x42,0x0D, + 0x3A,0x98,0x6D,0x06,0x78,0x9E,0xF0,0x6A,0xA3,0x1D, + 0x02,0x0A,0xA2,0x28,0xA4,0x8D,0xC2,0x81,0x46,0x3E, + 0x6D,0x67,0xDA,0xDE,0x3F,0xFE,0x85,0x0E,0x42,0x2A, + 0x12,0xDE,0xB5,0xB7,0xFB,0xB8,0x1B,0xA7,0x96,0xEC, + 0x77,0x9F,0xEC,0xD4,0x53,0x95,0x7A,0xFF,0x07,0xF4, + 0xF2,0x0A,0x14,0xC0,0x51,0x52,0xB1,0xD6,0x8E,0x50, + 0x0B,0x1A,0x99,0x5C,0xBC,0x0B,0xC9,0xBD,0xED,0xED, + 0xF8,0x5E,0xC1,0x56,0xDB,0x4D,0x7E,0x23,0xA4,0x11, + 0xA1,0x2C,0xD4,0x1B,0x05,0x9A,0xE4,0x1B,0x52,0xF6, + 0x7C,0x38,0x99,0x05,0x4B,0xBA,0x72,0x8D,0x42,0x89, + 0x60,0x04,0x66,0x2A,0xF4,0xFD,0x68,0xD7,0x6B,0xF7, + 0x99,0x41,0x28,0xD6,0x6C,0x24,0xAB,0xE6,0x25,0x53, + 0x2E,0xC8,0x82,0x99,0xE2,0xA2,0x8F,0x23,0xBE,0x30, + 0x83,0xB1,0x27,0x8B,0xFA,0x68,0x7F,0x01,0x49,0xE8, + 0xC6,0x98,0x6B,0x10,0x2E,0x98,0x5E,0x8A,0xD7,0xCA, + 0x4B,0xB1,0xC7,0xC9,0x58,0x9A,0xD0,0x36,0xDB,0x96, + 0x95,0xEC,0xB6,0x81,0xE4,0xF2,0xCD,0x6F,0x1B,0x79, + 0x87,0x4C,0x10,0x3C,0x89,0xE4,0x4D,0xFA,0x54,0xDC, + 0xAA,0xA6 +}; + +unsigned char ocsp_smime_leaf_certificate[1338]={ + 0x30,0x82,0x05,0x36,0x30,0x82,0x04,0x1E,0xA0,0x03,0x02,0x01,0x02,0x02,0x0D,0x14, + 0x00,0x01,0x00,0x02,0x9C,0xE1,0xB9,0xE0,0x7C,0xD1,0x7B,0xEC,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x7C,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03, + 0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E, + 0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04, + 0x0B,0x13,0x1C,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65, + 0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20,0x43,0x41,0x31, + 0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1F,0x54,0x43,0x20,0x54,0x72,0x75, + 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31, + 0x20,0x4C,0x31,0x20,0x43,0x41,0x20,0x49,0x58,0x30,0x1E,0x17,0x0D,0x31,0x30,0x31, + 0x31,0x31,0x32,0x30,0x36,0x33,0x36,0x34,0x35,0x5A,0x17,0x0D,0x31,0x31,0x31,0x31, + 0x31,0x33,0x30,0x36,0x33,0x36,0x34,0x35,0x5A,0x30,0x24,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04, + 0x03,0x13,0x0C,0x51,0x75,0x69,0x6E,0x6E,0x20,0x54,0x61,0x79,0x6C,0x6F,0x72,0x30, + 0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, + 0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00, + 0xC1,0x11,0xAA,0x04,0xCF,0x04,0xA0,0x07,0xF3,0x43,0x2A,0xB2,0x27,0x1A,0x13,0x35, + 0x97,0x9A,0xBA,0x34,0xE5,0x84,0xF3,0xD5,0xE5,0xD9,0xAB,0x23,0x8D,0xB4,0x7E,0x68, + 0x5C,0xF2,0x9A,0xF1,0x08,0x9B,0x04,0x34,0xC1,0x09,0x14,0x68,0xD8,0x9C,0xC1,0x6C, + 0x27,0xF5,0x92,0x54,0xAF,0x66,0x65,0xF1,0x50,0xAA,0x7E,0xE3,0xFC,0xC1,0xB0,0x3E, + 0xEF,0xAA,0x86,0x58,0x4F,0xE7,0x86,0x0A,0x74,0xA6,0x97,0xBD,0x7D,0xF6,0xCE,0xA6, + 0x8B,0xF7,0xC0,0x90,0x6E,0x50,0x69,0x36,0x65,0x82,0x0F,0x65,0xA7,0x2C,0x16,0xFA, + 0x6C,0xCA,0x54,0x45,0x7C,0x06,0x20,0x72,0xF0,0x00,0x7B,0xD7,0x17,0xCD,0x94,0x64, + 0x6A,0xB7,0x28,0xF3,0x62,0xB1,0x29,0xAE,0x0C,0x8A,0x2F,0x3C,0x06,0x89,0xE8,0x81, + 0x77,0xAD,0x1F,0x65,0xED,0x6F,0x51,0x64,0x65,0x68,0x76,0xD8,0xEE,0xEC,0xA6,0x28, + 0xA9,0x1C,0x4F,0x98,0x4A,0x6D,0xD0,0xC8,0x5C,0x59,0x17,0x9B,0xF8,0x6D,0xF5,0x93, + 0xD3,0x4C,0x2A,0x37,0x80,0x65,0xB4,0x34,0xBA,0x64,0x2F,0xA1,0x8E,0x1C,0x6A,0x88, + 0x7C,0xA3,0xDB,0xDD,0x00,0x9B,0x78,0x51,0x7B,0xA6,0x8D,0xDD,0x43,0x9B,0xB2,0x2E, + 0x4B,0x1E,0xB3,0x34,0x37,0x3F,0x63,0x08,0x8C,0xC8,0xCF,0xD0,0xB0,0x8C,0xBF,0x8F, + 0xA7,0x49,0xBD,0x48,0x1D,0xB5,0x1E,0x6A,0x42,0x48,0x16,0x9A,0x7C,0xD3,0x55,0x6B, + 0xFF,0xD6,0xBA,0x70,0xF3,0x5F,0x1F,0x57,0x16,0xE0,0x1C,0xF1,0x73,0x22,0xD9,0x33, + 0xA7,0x20,0xE8,0xED,0x52,0x2A,0xE9,0x6F,0xCF,0xFB,0x76,0xAC,0xB8,0x5D,0x9B,0xAB, + 0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x02,0x0D,0x30,0x82,0x02,0x09,0x30,0x81,0xA5, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x81,0x98,0x30,0x81,0x95, + 0x30,0x51,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x45,0x68,0x74, + 0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65, + 0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x65,0x72,0x74,0x73,0x65,0x72,0x76, + 0x69,0x63,0x65,0x73,0x2F,0x63,0x61,0x63,0x65,0x72,0x74,0x73,0x2F,0x74,0x63,0x5F, + 0x63,0x6C,0x61,0x73,0x73,0x31,0x5F,0x4C,0x31,0x5F,0x43,0x41,0x5F,0x49,0x58,0x2E, + 0x63,0x72,0x74,0x30,0x40,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86, + 0x34,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x69,0x78,0x2E, + 0x74,0x63,0x63,0x6C,0x61,0x73,0x73,0x31,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65, + 0x72,0x73,0x61,0x6C,0x2D,0x69,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, + 0x65,0x72,0x2E,0x64,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0xE9,0xB8,0x28,0x1D,0x46,0xCF,0xFC,0xCD,0xF8,0x4E,0x9B,0xC5,0xEE,0x4B, + 0x60,0xEB,0xD8,0x3B,0x3F,0xD1,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, + 0x04,0x02,0x30,0x00,0x30,0x4A,0x06,0x03,0x55,0x1D,0x20,0x04,0x43,0x30,0x41,0x30, + 0x3F,0x06,0x09,0x2A,0x82,0x14,0x00,0x2C,0x01,0x01,0x01,0x01,0x30,0x32,0x30,0x30, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x24,0x68,0x74,0x74,0x70, + 0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, + 0x65,0x72,0x2E,0x64,0x65,0x2F,0x67,0x75,0x69,0x64,0x65,0x6C,0x69,0x6E,0x65,0x73, + 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x04,0xF0, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xF8,0x4D,0x7F,0xDE,0xFA, + 0x21,0x2E,0xAF,0x96,0xBB,0xAA,0x9B,0x22,0x56,0x80,0xF0,0x8E,0xD4,0x6A,0x52,0x30, + 0x62,0x06,0x03,0x55,0x1D,0x1F,0x04,0x5B,0x30,0x59,0x30,0x57,0xA0,0x55,0xA0,0x53, + 0x86,0x51,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x69,0x78,0x2E, + 0x74,0x63,0x63,0x6C,0x61,0x73,0x73,0x31,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65, + 0x72,0x73,0x61,0x6C,0x2D,0x69,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, + 0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x72,0x6C,0x2F,0x76,0x32,0x2F,0x74,0x63,0x5F, + 0x43,0x6C,0x61,0x73,0x73,0x31,0x5F,0x4C,0x31,0x5F,0x43,0x41,0x5F,0x49,0x58,0x2E, + 0x63,0x72,0x6C,0x30,0x33,0x06,0x03,0x55,0x1D,0x25,0x04,0x2C,0x30,0x2A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x03,0x04,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x07,0x06,0x0A,0x2B,0x06, + 0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02,0x30,0x1C,0x06,0x03,0x55,0x1D,0x11,0x04, + 0x15,0x30,0x13,0x81,0x11,0x71,0x74,0x61,0x79,0x6C,0x6F,0x72,0x40,0x61,0x70,0x70, + 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x0D,0xCF,0x33,0xAB,0x3D,0xD3, + 0xD2,0x06,0x2C,0x20,0x3C,0xEC,0x0C,0xE4,0xA5,0x19,0x86,0xB3,0xA7,0xA9,0xA6,0xE9, + 0xDC,0xB4,0x35,0xBB,0x0D,0x67,0xD5,0xBD,0x5F,0x93,0xD9,0x2E,0xA0,0x05,0x2A,0xED, + 0xAE,0x41,0xD9,0xEE,0x30,0xA8,0x82,0x50,0xD0,0x4B,0x04,0x6B,0x37,0xAE,0xC0,0x10, + 0x89,0x05,0x68,0x82,0x91,0x2B,0x5B,0xE2,0x7D,0xA6,0x87,0xF7,0x26,0x96,0xBA,0x2A, + 0x52,0x03,0x97,0xF6,0x2E,0x0D,0x81,0x65,0x24,0x10,0xD5,0x8C,0xB3,0xCD,0x19,0x58, + 0xAF,0x3A,0x3D,0x2F,0x10,0x30,0x79,0x6A,0xD6,0x08,0x8F,0x8B,0x9D,0x1D,0xF8,0x19, + 0xE4,0x24,0x2B,0xE0,0x7F,0x73,0xE1,0x50,0x9C,0x53,0xE1,0x46,0xC7,0xA7,0xBD,0x71, + 0xCD,0xFF,0x39,0xA0,0x50,0xA5,0xA8,0xD9,0x50,0x39,0x6C,0x36,0x1C,0x13,0x89,0x8A, + 0x0D,0x9D,0x06,0x1B,0xAA,0x59,0x40,0xC1,0xAF,0xED,0x66,0x31,0xB8,0xA0,0x9F,0xCF, + 0xA6,0x8A,0x2E,0xC2,0x1A,0x4B,0xDB,0x62,0x15,0x6E,0x10,0x2F,0x82,0x3C,0xF8,0xA2, + 0x18,0x63,0xCC,0x67,0x13,0x42,0x07,0x43,0xDB,0x20,0x13,0xC7,0xAC,0xCE,0xCB,0xEA, + 0x7E,0x53,0xA6,0x01,0x81,0xB2,0x6E,0x92,0x2B,0x0C,0xF9,0x01,0x2C,0x11,0xC9,0x00, + 0x10,0x58,0x64,0x56,0x91,0xAC,0xAA,0xF6,0xE0,0x73,0xC7,0x59,0xEC,0xCE,0x51,0x7E, + 0xAD,0x9F,0x04,0xA4,0x38,0x74,0x65,0xD0,0x23,0xBD,0x6E,0xDF,0x64,0x79,0xE2,0xA3, + 0x37,0x19,0x2F,0x8C,0x41,0x8B,0x5F,0x6D,0x84,0x61,0x54,0xD1,0x26,0x18,0x70,0xAD, + 0xE5,0xF4,0xCD,0x59,0xED,0x9E,0xE0,0xC9,0x9F,0xD3, +}; + +unsigned char ocsp_smime_CA_certificate[1500]={ + 0x30,0x82,0x05,0xD8,0x30,0x82,0x04,0xC0,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x06, + 0xE8,0x00,0x01,0x00,0x02,0x4A,0x96,0x2D,0x24,0x0C,0xFE,0xC5,0xC9,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x79,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06, + 0x03,0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, + 0x6E,0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55, + 0x04,0x0B,0x13,0x1B,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74, + 0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31, + 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75, + 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73, + 0x61,0x6C,0x20,0x43,0x41,0x20,0x49,0x30,0x1E,0x17,0x0D,0x30,0x39,0x31,0x31,0x30, + 0x33,0x31,0x34,0x30,0x38,0x31,0x39,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x33,0x31, + 0x32,0x31,0x35,0x39,0x35,0x39,0x5A,0x30,0x7C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0A,0x13, + 0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20, + 0x47,0x6D,0x62,0x48,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C,0x54, + 0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x43,0x6C, + 0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20,0x43,0x41,0x31,0x28,0x30,0x26,0x06, + 0x03,0x55,0x04,0x03,0x13,0x1F,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, + 0x6E,0x74,0x65,0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20, + 0x43,0x41,0x20,0x49,0x58,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, + 0x0A,0x02,0x82,0x01,0x01,0x00,0xBB,0xE6,0x90,0x6E,0xCF,0x62,0xE9,0xE9,0x0B,0xAA, + 0xB6,0x10,0xD5,0x47,0xE5,0x7C,0x5D,0x2B,0x27,0x71,0x9A,0x68,0xCD,0x55,0x6D,0xE4, + 0xA2,0xEF,0xE4,0xFE,0xF2,0x7A,0x63,0x11,0xC2,0x57,0x8A,0xC8,0x7D,0xCF,0x8E,0x66, + 0x1F,0x65,0x45,0x4B,0xEB,0x80,0x62,0x69,0xBD,0x46,0x8E,0x8B,0xC5,0x6E,0x5A,0x95, + 0x18,0x2A,0xDE,0xA7,0xF1,0x1F,0x75,0x1A,0x27,0xAB,0x6D,0x32,0x53,0xE3,0xFB,0x4D, + 0x58,0x62,0x2C,0xFF,0x19,0xE5,0xC7,0xA0,0x0D,0x9A,0x2D,0x21,0x88,0x59,0x84,0xCD, + 0x1D,0xF1,0xC3,0xC8,0x8A,0x3E,0xB0,0xE5,0xDE,0x08,0x24,0xCF,0xFC,0x40,0x2C,0xBA, + 0x41,0x23,0x94,0xBB,0x80,0x12,0x89,0x35,0x48,0xB6,0x86,0x04,0xE0,0x01,0x4F,0x8C, + 0xBA,0xA9,0x98,0xFC,0x1C,0x89,0xED,0x1F,0x8A,0xA1,0xC7,0x86,0x98,0x26,0x1E,0x72, + 0x65,0x6B,0xFE,0xCF,0x65,0xD9,0x0C,0x64,0x4B,0x1A,0x09,0xF5,0x43,0x11,0x60,0x66, + 0x26,0xE3,0x33,0x56,0x9A,0xC9,0x3D,0x3E,0x34,0x6A,0x78,0xC6,0xE5,0x50,0x4B,0xC8, + 0xCD,0x88,0xE4,0x39,0x6C,0x50,0x26,0x9E,0x40,0x2C,0xB6,0x3B,0x7C,0x37,0xB2,0xA7, + 0xF5,0xDD,0xDC,0xB3,0x51,0xCB,0xF4,0xDC,0x82,0x02,0xB8,0xD7,0x3A,0xDE,0xDA,0x30, + 0x5C,0x0D,0xF5,0x42,0xDD,0x13,0x69,0x53,0x54,0xE9,0x80,0x26,0x42,0x33,0x1E,0xA5, + 0xD7,0xCC,0x6E,0xCA,0x66,0x09,0x9F,0x86,0xF0,0x3D,0xBE,0xC6,0x8A,0x61,0x10,0xF3, + 0xD1,0xFF,0x5B,0xE4,0xB2,0xDB,0x2D,0xB2,0x65,0x0C,0xA9,0x7D,0x17,0xAC,0xBA,0x27, + 0x4D,0x42,0x5C,0xCE,0x09,0x4F,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x02,0x59,0x30, + 0x82,0x02,0x55,0x30,0x81,0x9A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, + 0x04,0x81,0x8D,0x30,0x81,0x8A,0x30,0x52,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x30,0x02,0x86,0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74, + 0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x65, + 0x72,0x74,0x73,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x2F,0x63,0x61,0x63,0x65,0x72, + 0x74,0x73,0x2F,0x74,0x63,0x5F,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x5F, + 0x72,0x6F,0x6F,0x74,0x5F,0x49,0x2E,0x63,0x72,0x74,0x30,0x34,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x28,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F, + 0x63,0x73,0x70,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x2D, + 0x49,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x92,0xA4,0x75, + 0x2C,0xA4,0x9E,0xBE,0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75, + 0x73,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01, + 0x01,0xFF,0x02,0x01,0x00,0x30,0x52,0x06,0x03,0x55,0x1D,0x20,0x04,0x4B,0x30,0x49, + 0x30,0x06,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x3F,0x06,0x09,0x2A,0x82,0x14,0x00, + 0x2C,0x01,0x01,0x01,0x01,0x30,0x32,0x30,0x30,0x06,0x08,0x2B,0x06,0x01,0x05,0x05, + 0x07,0x02,0x01,0x16,0x24,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E, + 0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x67, + 0x75,0x69,0x64,0x65,0x6C,0x69,0x6E,0x65,0x73,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, + 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, + 0x04,0x16,0x04,0x14,0xE9,0xB8,0x28,0x1D,0x46,0xCF,0xFC,0xCD,0xF8,0x4E,0x9B,0xC5, + 0xEE,0x4B,0x60,0xEB,0xD8,0x3B,0x3F,0xD1,0x30,0x81,0xFD,0x06,0x03,0x55,0x1D,0x1F, + 0x04,0x81,0xF5,0x30,0x81,0xF2,0x30,0x81,0xEF,0xA0,0x81,0xEC,0xA0,0x81,0xE9,0x86, + 0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x74,0x63,0x75,0x6E, + 0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x2D,0x49,0x2E,0x74,0x72,0x75,0x73,0x74,0x63, + 0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x72,0x6C,0x2F,0x76,0x32,0x2F, + 0x74,0x63,0x5F,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x5F,0x72,0x6F,0x6F, + 0x74,0x5F,0x49,0x2E,0x63,0x72,0x6C,0x86,0x81,0x9E,0x6C,0x64,0x61,0x70,0x3A,0x2F, + 0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72, + 0x2E,0x64,0x65,0x2F,0x43,0x4E,0x3D,0x54,0x43,0x25,0x32,0x30,0x54,0x72,0x75,0x73, + 0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x25,0x32,0x30,0x55,0x6E,0x69,0x76,0x65,0x72, + 0x73,0x61,0x6C,0x25,0x32,0x30,0x43,0x41,0x25,0x32,0x30,0x49,0x2C,0x4F,0x3D,0x54, + 0x43,0x25,0x32,0x30,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x25, + 0x32,0x30,0x47,0x6D,0x62,0x48,0x2C,0x4F,0x55,0x3D,0x72,0x6F,0x6F,0x74,0x63,0x65, + 0x72,0x74,0x73,0x2C,0x44,0x43,0x3D,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, + 0x65,0x72,0x2C,0x44,0x43,0x3D,0x64,0x65,0x3F,0x63,0x65,0x72,0x74,0x69,0x66,0x69, + 0x63,0x61,0x74,0x65,0x52,0x65,0x76,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x4C,0x69, + 0x73,0x74,0x3F,0x62,0x61,0x73,0x65,0x3F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x39,0xC8,0xC4,0x9B, + 0xEE,0xBE,0x98,0xEE,0x48,0x72,0x6F,0x8D,0xE7,0x71,0xB6,0x0E,0x90,0x8C,0xD3,0xB2, + 0xC1,0x15,0x21,0xA8,0x46,0x90,0x68,0x5F,0x4A,0x04,0xF1,0x3A,0xC9,0x68,0x84,0x21, + 0xD8,0xA5,0xE6,0x04,0x75,0x5D,0x9F,0xD2,0xD4,0xF2,0x4B,0x77,0x43,0x32,0xDC,0x95, + 0xCB,0x60,0xBF,0x02,0x55,0xD0,0xAC,0x1C,0xB0,0xC5,0x14,0x97,0x9B,0x65,0x0A,0xC3, + 0x0F,0xA5,0x1D,0xEC,0xD8,0x49,0x39,0x95,0xB5,0xA9,0xBE,0xFA,0xF4,0x1E,0xAB,0x56, + 0xE7,0xA6,0xE5,0x01,0x08,0x88,0x35,0x5F,0x67,0x05,0xDD,0x44,0x24,0x50,0x12,0x22, + 0x44,0x63,0x79,0xF1,0x9B,0x57,0x69,0xCE,0xAB,0xD6,0x33,0x51,0x4F,0x8D,0xF0,0x70, + 0x3B,0x8E,0xAD,0x51,0x3A,0x17,0x7F,0x35,0x96,0x6B,0x68,0x68,0x63,0xB6,0x1C,0x0A, + 0xC9,0xF8,0xDF,0x1D,0x5E,0xCF,0x2B,0x11,0xA5,0x63,0xED,0xCC,0xD0,0xC6,0xD3,0x20, + 0x6F,0xAA,0xFC,0x68,0x48,0x7E,0x6D,0x1E,0xB8,0x3A,0x45,0xAA,0x12,0x86,0xF3,0xC7, + 0xBD,0x00,0xB5,0xEB,0xFE,0xEA,0x12,0x9F,0x73,0x33,0x78,0xE7,0x28,0x39,0x68,0xD3, + 0xA5,0x6D,0xDA,0x76,0xD1,0x4E,0xE1,0x55,0x95,0x80,0xA6,0xE0,0x1B,0xB8,0xCD,0xAC, + 0x56,0xEF,0x45,0x59,0x47,0x98,0x52,0xDB,0x3A,0x6E,0x26,0xB2,0x31,0x39,0x69,0x75, + 0xB1,0x2E,0x24,0xF0,0xA4,0x9D,0x97,0x88,0x5E,0x33,0x29,0xC6,0xB5,0xBC,0x07,0x40, + 0x3A,0x0C,0x3D,0xBA,0xCF,0x74,0x8C,0x4B,0x4E,0x7A,0x21,0xFA,0x1B,0x38,0xCD,0xC4, + 0x43,0x2F,0x6F,0xB4,0xDF,0x78,0xEE,0x99,0x92,0xE7,0x3A,0x1C, +}; + +unsigned char ocsp_smime_root_certificate[993]={ + 0x30,0x82,0x03,0xDD,0x30,0x82,0x02,0xC5,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x1D, + 0xA2,0x00,0x01,0x00,0x02,0xEC,0xB7,0x60,0x80,0x78,0x8D,0xB6,0x06,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x79,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06, + 0x03,0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, + 0x6E,0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55, + 0x04,0x0B,0x13,0x1B,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74, + 0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31, + 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75, + 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73, + 0x61,0x6C,0x20,0x43,0x41,0x20,0x49,0x30,0x1E,0x17,0x0D,0x30,0x36,0x30,0x33,0x32, + 0x32,0x31,0x35,0x35,0x34,0x32,0x38,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x33,0x31, + 0x32,0x32,0x35,0x39,0x35,0x39,0x5A,0x30,0x79,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0A,0x13, + 0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20, + 0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x0B,0x13,0x1B,0x54, + 0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E, + 0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E, + 0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41, + 0x20,0x49,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82, + 0x01,0x01,0x00,0xA4,0x77,0x23,0x96,0x44,0xAF,0x90,0xF4,0x31,0xA7,0x10,0xF4,0x26, + 0x87,0x9C,0xF3,0x38,0xD9,0x0F,0x5E,0xDE,0xCF,0x41,0xE8,0x31,0xAD,0xC6,0x74,0x91, + 0x24,0x96,0x78,0x1E,0x09,0xA0,0x9B,0x9A,0x95,0x4A,0x4A,0xF5,0x62,0x7C,0x02,0xA8, + 0xCA,0xAC,0xFB,0x5A,0x04,0x76,0x39,0xDE,0x5F,0xF1,0xF9,0xB3,0xBF,0xF3,0x03,0x58, + 0x55,0xD2,0xAA,0xB7,0xE3,0x04,0x22,0xD1,0xF8,0x94,0xDA,0x22,0x08,0x00,0x8D,0xD3, + 0x7C,0x26,0x5D,0xCC,0x77,0x79,0xE7,0x2C,0x78,0x39,0xA8,0x26,0x73,0x0E,0xA2,0x5D, + 0x25,0x69,0x85,0x4F,0x55,0x0E,0x9A,0xEF,0xC6,0xB9,0x44,0xE1,0x57,0x3D,0xDF,0x1F, + 0x54,0x22,0xE5,0x6F,0x65,0xAA,0x33,0x84,0x3A,0xF3,0xCE,0x7A,0xBE,0x55,0x97,0xAE, + 0x8D,0x12,0x0F,0x14,0x33,0xE2,0x50,0x70,0xC3,0x49,0x87,0x13,0xBC,0x51,0xDE,0xD7, + 0x98,0x12,0x5A,0xEF,0x3A,0x83,0x33,0x92,0x06,0x75,0x8B,0x92,0x7C,0x12,0x68,0x7B, + 0x70,0x6A,0x0F,0xB5,0x9B,0xB6,0x77,0x5B,0x48,0x59,0x9D,0xE4,0xEF,0x5A,0xAD,0xF3, + 0xC1,0x9E,0xD4,0xD7,0x45,0x4E,0xCA,0x56,0x34,0x21,0xBC,0x3E,0x17,0x5B,0x6F,0x77, + 0x0C,0x48,0x01,0x43,0x29,0xB0,0xDD,0x3F,0x96,0x6E,0xE6,0x95,0xAA,0x0C,0xC0,0x20, + 0xB6,0xFD,0x3E,0x36,0x27,0x9C,0xE3,0x5C,0xCF,0x4E,0x81,0xDC,0x19,0xBB,0x91,0x90, + 0x7D,0xEC,0xE6,0x97,0x04,0x1E,0x93,0xCC,0x22,0x49,0xD7,0x97,0x86,0xB6,0x13,0x0A, + 0x3C,0x43,0x23,0x77,0x7E,0xF0,0xDC,0xE6,0xCD,0x24,0x1F,0x3B,0x83,0x9B,0x34,0x3A, + 0x83,0x34,0xE3,0x02,0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x1F,0x06,0x03, + 0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x92,0xA4,0x75,0x2C,0xA4,0x9E,0xBE, + 0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75,0x73,0x30,0x0F,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E, + 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x1D, + 0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x92,0xA4,0x75,0x2C,0xA4,0x9E,0xBE, + 0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75,0x73,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01, + 0x00,0x28,0xD2,0xE0,0x86,0xD5,0xE6,0xF8,0x7B,0xF0,0x97,0xDC,0x22,0x6B,0x3B,0x95, + 0x14,0x56,0x0F,0x11,0x30,0xA5,0x9A,0x4F,0x3A,0xB0,0x3A,0xE0,0x06,0xCB,0x65,0xF5, + 0xED,0xC6,0x97,0x27,0xFE,0x25,0xF2,0x57,0xE6,0x5E,0x95,0x8C,0x3E,0x64,0x60,0x15, + 0x5A,0x7F,0x2F,0x0D,0x01,0xC5,0xB1,0x60,0xFD,0x45,0x35,0xCF,0xF0,0xB2,0xBF,0x06, + 0xD9,0xEF,0x5A,0xBE,0xB3,0x62,0x21,0xB4,0xD7,0xAB,0x35,0x7C,0x53,0x3E,0xA6,0x27, + 0xF1,0xA1,0x2D,0xDA,0x1A,0x23,0x9D,0xCC,0xDD,0xEC,0x3C,0x2D,0x9E,0x27,0x34,0x5D, + 0x0F,0xC2,0x36,0x79,0xBC,0xC9,0x4A,0x62,0x2D,0xED,0x6B,0xD9,0x7D,0x41,0x43,0x7C, + 0xB6,0xAA,0xCA,0xED,0x61,0xB1,0x37,0x82,0x15,0x09,0x1A,0x8A,0x16,0x30,0xD8,0xEC, + 0xC9,0xD6,0x47,0x72,0x78,0x4B,0x10,0x46,0x14,0x8E,0x5F,0x0E,0xAF,0xEC,0xC7,0x2F, + 0xAB,0x10,0xD7,0xB6,0xF1,0x6E,0xEC,0x86,0xB2,0xC2,0xE8,0x0D,0x92,0x73,0xDC,0xA2, + 0xF4,0x0F,0x3A,0xBF,0x61,0x23,0x10,0x89,0x9C,0x48,0x40,0x6E,0x70,0x00,0xB3,0xD3, + 0xBA,0x37,0x44,0x58,0x11,0x7A,0x02,0x6A,0x88,0xF0,0x37,0x34,0xF0,0x19,0xE9,0xAC, + 0xD4,0x65,0x73,0xF6,0x69,0x8C,0x64,0x94,0x3A,0x79,0x85,0x29,0xB0,0x16,0x2B,0x0C, + 0x82,0x3F,0x06,0x9C,0xC7,0xFD,0x10,0x2B,0x9E,0x0F,0x2C,0xB6,0x9E,0xE3,0x15,0xBF, + 0xD9,0x36,0x1C,0xBA,0x25,0x1A,0x52,0x3D,0x1A,0xEC,0x22,0x0C,0x1C,0xE0,0xA4,0xA2, + 0x3D,0xF0,0xE8,0x39,0xCF,0x81,0xC0,0x7B,0xED,0x5D,0x1F,0x6F,0xC5,0xD0,0x0B,0xD7, + 0x98, +}; + +/* subject:/UID=398C878YJ2/ */ +/* issuer :/CN=Developer ID Certification Authority/OU=Apple Certification Authority/O=Apple Inc./C=US */ +uint8_t _probablyNotRevokedLeaf[]={ + 0x30,0x82,0x05,0x7A,0x30,0x82,0x04,0x62,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x03, + 0xB5,0x01,0x60,0xCB,0x4D,0x00,0xDE,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x79,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x24,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x20,0x49,0x44,0x20, + 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75, + 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x1E,0x17,0x0D,0x31,0x37,0x30,0x31,0x31,0x36,0x31,0x30,0x31,0x30,0x30, + 0x30,0x5A,0x17,0x0D,0x32,0x32,0x30,0x31,0x31,0x37,0x31,0x30,0x31,0x30,0x30,0x30, + 0x5A,0x30,0x81,0x9B,0x31,0x1A,0x30,0x18,0x06,0x0A,0x09,0x92,0x26,0x89,0x93,0xF2, + 0x2C,0x64,0x01,0x01,0x0C,0x0A,0x33,0x39,0x38,0x43,0x38,0x37,0x38,0x59,0x4A,0x32, + 0x31,0x40,0x30,0x3E,0x06,0x03,0x55,0x04,0x03,0x0C,0x37,0x44,0x65,0x76,0x65,0x6C, + 0x6F,0x70,0x65,0x72,0x20,0x49,0x44,0x20,0x41,0x70,0x70,0x6C,0x69,0x63,0x61,0x74, + 0x69,0x6F,0x6E,0x3A,0x20,0x52,0x75,0x73,0x6C,0x61,0x6E,0x20,0x47,0x61,0x72,0x69, + 0x66,0x75,0x6C,0x69,0x6E,0x20,0x28,0x33,0x39,0x38,0x43,0x38,0x37,0x38,0x59,0x4A, + 0x32,0x29,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0A,0x33,0x39,0x38, + 0x43,0x38,0x37,0x38,0x59,0x4A,0x32,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x10,0x52,0x75,0x73,0x6C,0x61,0x6E,0x20,0x47,0x61,0x72,0x69,0x66,0x75,0x6C, + 0x69,0x6E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, + 0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00, + 0xC3,0xDB,0x84,0xA2,0xF1,0x89,0xA3,0x17,0xC6,0xF0,0x96,0xAA,0xE3,0xCF,0x16,0x71, + 0x7F,0x97,0x96,0xEF,0x95,0x27,0x73,0x49,0xCC,0x53,0xF0,0x1D,0x73,0x67,0xA7,0x58, + 0xC5,0x27,0xA9,0xEC,0x40,0x41,0xF6,0x6F,0x87,0x65,0x9D,0xD9,0xE1,0x16,0xF5,0xB5, + 0xBA,0xAF,0x39,0xC8,0xA0,0xA5,0x10,0x9D,0x6F,0x9A,0xD7,0xED,0x1F,0xB4,0xF6,0x90, + 0x55,0x73,0x60,0x0B,0xD4,0xEE,0xC6,0x39,0x33,0x02,0xAE,0xD9,0xEE,0x7F,0xFE,0x49, + 0x82,0x05,0x7D,0x0D,0x6E,0xA6,0x2C,0xF6,0x75,0xBD,0xBA,0xB4,0x5F,0x5E,0x9B,0x4F, + 0x85,0x3A,0x02,0x37,0xA8,0xB5,0xE1,0x42,0x57,0x97,0xA3,0x20,0xC3,0xFF,0xF5,0xC7, + 0x2F,0x0A,0xC2,0x06,0xA4,0x4E,0x24,0x7E,0xE2,0x72,0x20,0xC7,0x0E,0xC4,0x32,0xE8, + 0x0C,0x69,0xD7,0x99,0xF5,0xC5,0xDB,0xB7,0x4F,0x84,0xFB,0xAB,0x97,0x90,0x0A,0x6A, + 0x17,0xAD,0xD9,0x41,0xDD,0xE1,0x35,0x06,0x50,0x5B,0x79,0x6E,0x3A,0xC3,0x2C,0x92, + 0xE1,0x14,0x6F,0xAE,0xEC,0xC2,0xA6,0x5A,0x7F,0xB8,0x9D,0xE8,0x3A,0x6B,0x59,0x36, + 0xC3,0x56,0xA7,0x16,0x77,0xF3,0x91,0x61,0x33,0x05,0x23,0x04,0x96,0xAF,0x14,0x5F, + 0x2F,0x82,0x87,0xCE,0xDC,0x39,0x4E,0xD5,0xC5,0x1A,0x29,0xF9,0xE6,0xB8,0xAB,0xB8, + 0x62,0x39,0x2E,0x55,0x8E,0xA1,0x70,0xF9,0xE9,0x6D,0xA9,0x96,0xB9,0x59,0x22,0x1C, + 0x6E,0x8E,0x7D,0x30,0xB7,0xEA,0x1C,0xB2,0x1F,0x8D,0x59,0xF1,0x94,0x40,0x95,0xEA, + 0x4F,0xFE,0x53,0x50,0xA1,0xE0,0xC4,0x79,0x91,0x40,0x49,0x23,0x8D,0x96,0x4F,0x6D, + 0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0xE1,0x30,0x82,0x01,0xDD,0x30,0x3E,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x32,0x30,0x30,0x30,0x2E,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x22,0x68,0x74,0x74,0x70,0x3A, + 0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x2F,0x6F,0x63,0x73,0x70,0x2D,0x64,0x65,0x76,0x69,0x64,0x30,0x31,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x79,0x35,0xB6,0x17,0xF0,0x11,0x85,0x00, + 0xFE,0xBA,0x56,0xF3,0x0C,0xA0,0x03,0xBE,0x71,0x64,0x0C,0x9C,0x30,0x0C,0x06,0x03, + 0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D, + 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x57,0x17,0xED,0xA2,0xCF,0xDC,0x7C,0x98,0xA1, + 0x10,0xE0,0xFC,0xBE,0x87,0x2D,0x2C,0xF2,0xE3,0x17,0x54,0x30,0x82,0x01,0x0E,0x06, + 0x03,0x55,0x1D,0x20,0x04,0x82,0x01,0x05,0x30,0x82,0x01,0x01,0x30,0x81,0xFE,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF0,0x30,0x28,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70,0x3A, + 0x2F,0x2F,0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, + 0x61,0x70,0x70,0x6C,0x65,0x63,0x61,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x02,0x02,0x30,0x81,0xB6,0x0C,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E, + 0x63,0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61, + 0x72,0x74,0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65, + 0x70,0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68, + 0x65,0x6E,0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74, + 0x61,0x6E,0x64,0x61,0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64, + 0x20,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75, + 0x73,0x65,0x2C,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20, + 0x70,0x6F,0x6C,0x69,0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63, + 0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x16,0x06, + 0x03,0x55,0x1D,0x25,0x01,0x01,0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x03,0x03,0x30,0x13,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64, + 0x06,0x01,0x0D,0x01,0x01,0xFF,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x3F,0x66, + 0xE8,0xD2,0x30,0x23,0x41,0x7A,0xD9,0x4E,0x3E,0xCF,0xFE,0x89,0x30,0xB2,0x7C,0x32, + 0x84,0xE1,0xAE,0x95,0x8C,0xBE,0xA7,0x7A,0x42,0x67,0x4B,0x27,0x13,0x0A,0xA7,0x31, + 0xE7,0xEF,0x8F,0x6C,0xBD,0x26,0x09,0x75,0xC6,0xF1,0xD6,0x6D,0xCC,0x55,0x43,0x1E, + 0x80,0xC0,0x7B,0x31,0x42,0x72,0x80,0xA3,0x94,0xC2,0xB8,0x68,0xC6,0x5E,0xD6,0x10, + 0xFB,0x8C,0x52,0xE8,0xAD,0x0A,0xCE,0x11,0x20,0x5D,0xF4,0xFC,0xFA,0xE5,0x3F,0x96, + 0x02,0xDF,0xA7,0x22,0x11,0xF6,0xE6,0xF2,0xCE,0x5F,0x42,0xCF,0x13,0xED,0xCB,0xEE, + 0xEC,0xB0,0x01,0x76,0x4F,0xDC,0xD6,0x84,0x37,0x82,0x18,0x43,0x9F,0x17,0x61,0x88, + 0xBD,0x4B,0xEE,0xB8,0x2B,0xF8,0x37,0xC2,0x64,0x79,0xF5,0x63,0xBC,0x3A,0x41,0x80, + 0x2B,0x92,0x91,0x3D,0x4E,0x86,0x48,0xFE,0x66,0x4D,0xC0,0xCA,0xFB,0x77,0x68,0x3D, + 0x18,0xFA,0x5C,0xD2,0x4F,0xBC,0x23,0xC5,0xF2,0x8C,0xA6,0xAA,0x55,0x0B,0xDE,0xF7, + 0xD5,0x6E,0x88,0xBC,0x22,0x8E,0x45,0x8A,0x14,0x73,0xCF,0x69,0xAC,0xDE,0x2E,0xB8, + 0x24,0xEB,0x5C,0xC3,0x4C,0xC4,0xF0,0xCE,0xFC,0x94,0x9F,0x22,0x73,0x57,0x30,0x33, + 0x7A,0xB3,0x6C,0x43,0x1A,0x6C,0x79,0xFA,0x8E,0x14,0xF4,0x68,0x12,0x6F,0xCC,0xE8, + 0x2B,0x77,0xA5,0x6A,0xFE,0x9A,0xD4,0x3A,0x57,0x66,0x49,0x37,0x97,0xC8,0x38,0x91, + 0x14,0x4B,0x46,0x50,0xCF,0xF1,0x61,0x46,0x8C,0x9C,0xEB,0x99,0xD3,0x85,0x1B,0x53, + 0xED,0x60,0x88,0x79,0xEB,0xEA,0x2B,0xE3,0x33,0xEF,0x0D,0x58,0xEF,0xF5, +}; + +/* subject:/CN=Developer ID Certification Authority/OU=Apple Certification Authority/O=Apple Inc./C=US */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA */ +uint8_t _devIDCA[] ={ + 0x30,0x82,0x04,0x04,0x30,0x82,0x02,0xEC,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x18, + 0x7A,0xA9,0xA8,0xC2,0x96,0x21,0x0C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x32, + 0x30,0x32,0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5A,0x17,0x0D,0x32,0x37,0x30, + 0x32,0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5A,0x30,0x79,0x31,0x2D,0x30,0x2B, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x24,0x44,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72, + 0x20,0x49,0x44,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x26,0x30,0x24,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74, + 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72, + 0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, + 0x0A,0x02,0x82,0x01,0x01,0x00,0x89,0x76,0x4F,0x06,0x5B,0x9A,0x41,0xEE,0xA5,0x23, + 0x2B,0x02,0xA3,0x5F,0xD7,0x73,0x3F,0xC0,0x35,0xB0,0x8B,0x84,0x0A,0x3F,0x06,0x24, + 0x7F,0xA7,0x95,0x3F,0xEB,0x4F,0x0E,0x93,0xAF,0xB4,0x0E,0xD0,0xC8,0x3E,0xE5,0x6D, + 0x18,0xB3,0x1F,0xE8,0x89,0x47,0xBF,0xD7,0x09,0x08,0xE4,0xFF,0x56,0x98,0x29,0x15, + 0xE7,0x94,0x9D,0xB9,0x35,0xA3,0x0A,0xCD,0xB4,0xC0,0xE1,0xE2,0x60,0xF4,0xCA,0xEC, + 0x29,0x78,0x45,0x69,0x69,0x60,0x6B,0x5F,0x8A,0x92,0xFC,0x9E,0x23,0xE6,0x3A,0xC2, + 0x22,0xB3,0x31,0x4F,0x1C,0xBA,0xF2,0xB6,0x34,0x59,0x42,0xEE,0xB0,0xA9,0x02,0x03, + 0x18,0x91,0x04,0xB6,0xB3,0x78,0x2E,0x33,0x1F,0x80,0x45,0x0D,0x45,0x6F,0xBB,0x0E, + 0x5A,0x5B,0x7F,0x3A,0xE7,0xD8,0x08,0xD7,0x0B,0x0E,0x32,0x6D,0xFB,0x86,0x36,0xE4, + 0x6C,0xAB,0xC4,0x11,0x8A,0x70,0x84,0x26,0xAA,0x9F,0x44,0xD1,0xF1,0xB8,0xC6,0x7B, + 0x94,0x17,0x9B,0x48,0xF7,0x0B,0x58,0x16,0xBA,0x23,0xC5,0x9F,0x15,0x39,0x7E,0xCA, + 0x5D,0xC3,0x32,0x5F,0x0F,0xE0,0x52,0x7F,0x40,0xEA,0xBE,0xAC,0x08,0x64,0x95,0x5B, + 0xC9,0x1A,0x9C,0xE5,0x80,0xCA,0x1F,0x6A,0x44,0x1C,0x6C,0x3E,0xC4,0xB0,0x26,0x1F, + 0x1D,0xEC,0x7B,0xAF,0x5E,0xA0,0x6A,0x3D,0x47,0xA9,0x58,0x12,0x31,0x3F,0x20,0x76, + 0x28,0x6D,0x1D,0x1C,0xB0,0xC2,0x4E,0x11,0x69,0x26,0x8B,0xCB,0xD6,0xD0,0x11,0x82, + 0xC9,0x4E,0x0F,0xF1,0x56,0x74,0xD0,0xD9,0x08,0x4B,0x66,0x78,0xA2,0xAB,0xAC,0xA7, + 0xE2,0xD2,0x4C,0x87,0x59,0xC9,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xA6,0x30,0x81, + 0xA3,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x57,0x17,0xED,0xA2, + 0xCF,0xDC,0x7C,0x98,0xA1,0x10,0xE0,0xFC,0xBE,0x87,0x2D,0x2C,0xF2,0xE3,0x17,0x54, + 0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01, + 0xFF,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x2B,0xD0, + 0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6,0xF7,0x47,0x4D,0x7F, + 0x08,0x5E,0x30,0x2E,0x06,0x03,0x55,0x1D,0x1F,0x04,0x27,0x30,0x25,0x30,0x23,0xA0, + 0x21,0xA0,0x1F,0x86,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x72,0x6F,0x6F,0x74,0x2E,0x63, + 0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02, + 0x01,0x86,0x30,0x10,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x02,0x06, + 0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x42,0x39,0x74,0x6B,0xA1,0xDC,0xC6,0xA4, + 0x8F,0x37,0x2A,0x8C,0xB3,0x1D,0x0A,0x44,0xBC,0x95,0x2C,0x7F,0xBC,0x59,0xB8,0xAC, + 0x61,0xFB,0x07,0x90,0x92,0x32,0xB9,0xD4,0xBF,0x3B,0xC1,0x50,0x39,0x6A,0x44,0x74, + 0xA2,0xEC,0x5B,0x1F,0x70,0xE5,0xAA,0xDD,0x4B,0x6C,0x1C,0x23,0x71,0x2D,0x5F,0xD1, + 0xC5,0x93,0xBE,0xEE,0x9B,0x8A,0x70,0x65,0x82,0x9D,0x16,0xE3,0x1A,0x10,0x17,0x89, + 0x2D,0xA8,0xCD,0xFD,0x0C,0x78,0x58,0x49,0x0C,0x28,0x7F,0x33,0xEE,0x00,0x7A,0x1B, + 0xB4,0x76,0xAC,0xB6,0xB5,0xBB,0x4F,0xDF,0xA8,0x1B,0x9D,0xC8,0x19,0x97,0x4A,0x0B, + 0x56,0x67,0x2F,0xC2,0x3E,0xB6,0xB3,0xC4,0x83,0x3A,0xF0,0x77,0x6D,0x74,0xC4,0x2E, + 0x23,0x51,0xEE,0x9A,0xA5,0x03,0x6F,0x60,0xF4,0xA5,0x48,0xA7,0x06,0xC2,0xBB,0x5A, + 0xE2,0x1F,0x1F,0x46,0x45,0x7E,0xE4,0x97,0xF5,0x27,0x10,0xB7,0x20,0x22,0x72,0x6F, + 0x72,0xDA,0xC6,0x50,0x75,0xC5,0x3D,0x25,0x8F,0x5D,0xA3,0x00,0xE9,0x9F,0x36,0x8C, + 0x48,0x39,0x8F,0xB3,0x3B,0xEA,0x90,0x80,0x2E,0x95,0x9A,0x60,0xF4,0x78,0xCE,0xF4, + 0x0E,0x0A,0x53,0x3E,0xA2,0xFA,0x4F,0xD8,0x1E,0xAE,0x84,0x95,0x8D,0x32,0xBC,0x56, + 0x4D,0x89,0xE9,0x78,0x18,0xE0,0xAC,0x9A,0x42,0xBA,0x7A,0x46,0x1B,0x84,0xA2,0x89, + 0xCE,0x14,0xE8,0x88,0xD1,0x58,0x8B,0xF6,0xAE,0x56,0xC4,0x2C,0x05,0x2A,0x45,0xAF, + 0x0B,0xD9,0x4B,0xA9,0x02,0x0F,0x34,0xAC,0x88,0xC7,0x61,0x55,0x89,0x44,0xC9,0x27, + 0x73,0x07,0xEE,0x82,0xE5,0x4E,0xF5,0x70, +}; + +/* subject:/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA */ +uint8_t _appleRoot[] ={ + 0x30,0x82,0x04,0xBB,0x30,0x82,0x03,0xA3,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x02, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30, + 0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06, + 0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74, + 0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x36,0x30,0x34,0x32,0x35,0x32,0x31,0x34, + 0x30,0x33,0x36,0x5A,0x17,0x0D,0x33,0x35,0x30,0x32,0x30,0x39,0x32,0x31,0x34,0x30, + 0x33,0x36,0x5A,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, + 0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30, + 0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xE4,0x91,0xA9,0x09,0x1F,0x91,0xDB,0x1E, + 0x47,0x50,0xEB,0x05,0xED,0x5E,0x79,0x84,0x2D,0xEB,0x36,0xA2,0x57,0x4C,0x55,0xEC, + 0x8B,0x19,0x89,0xDE,0xF9,0x4B,0x6C,0xF5,0x07,0xAB,0x22,0x30,0x02,0xE8,0x18,0x3E, + 0xF8,0x50,0x09,0xD3,0x7F,0x41,0xA8,0x98,0xF9,0xD1,0xCA,0x66,0x9C,0x24,0x6B,0x11, + 0xD0,0xA3,0xBB,0xE4,0x1B,0x2A,0xC3,0x1F,0x95,0x9E,0x7A,0x0C,0xA4,0x47,0x8B,0x5B, + 0xD4,0x16,0x37,0x33,0xCB,0xC4,0x0F,0x4D,0xCE,0x14,0x69,0xD1,0xC9,0x19,0x72,0xF5, + 0x5D,0x0E,0xD5,0x7F,0x5F,0x9B,0xF2,0x25,0x03,0xBA,0x55,0x8F,0x4D,0x5D,0x0D,0xF1, + 0x64,0x35,0x23,0x15,0x4B,0x15,0x59,0x1D,0xB3,0x94,0xF7,0xF6,0x9C,0x9E,0xCF,0x50, + 0xBA,0xC1,0x58,0x50,0x67,0x8F,0x08,0xB4,0x20,0xF7,0xCB,0xAC,0x2C,0x20,0x6F,0x70, + 0xB6,0x3F,0x01,0x30,0x8C,0xB7,0x43,0xCF,0x0F,0x9D,0x3D,0xF3,0x2B,0x49,0x28,0x1A, + 0xC8,0xFE,0xCE,0xB5,0xB9,0x0E,0xD9,0x5E,0x1C,0xD6,0xCB,0x3D,0xB5,0x3A,0xAD,0xF4, + 0x0F,0x0E,0x00,0x92,0x0B,0xB1,0x21,0x16,0x2E,0x74,0xD5,0x3C,0x0D,0xDB,0x62,0x16, + 0xAB,0xA3,0x71,0x92,0x47,0x53,0x55,0xC1,0xAF,0x2F,0x41,0xB3,0xF8,0xFB,0xE3,0x70, + 0xCD,0xE6,0xA3,0x4C,0x45,0x7E,0x1F,0x4C,0x6B,0x50,0x96,0x41,0x89,0xC4,0x74,0x62, + 0x0B,0x10,0x83,0x41,0x87,0x33,0x8A,0x81,0xB1,0x30,0x58,0xEC,0x5A,0x04,0x32,0x8C, + 0x68,0xB3,0x8F,0x1D,0xDE,0x65,0x73,0xFF,0x67,0x5E,0x65,0xBC,0x49,0xD8,0x76,0x9F, + 0x33,0x14,0x65,0xA1,0x77,0x94,0xC9,0x2D,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01, + 0x7A,0x30,0x82,0x01,0x76,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x01,0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6,0xF7, + 0x47,0x4D,0x7F,0x08,0x5E,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6, + 0xF7,0x47,0x4D,0x7F,0x08,0x5E,0x30,0x82,0x01,0x11,0x06,0x03,0x55,0x1D,0x20,0x04, + 0x82,0x01,0x08,0x30,0x82,0x01,0x04,0x30,0x82,0x01,0x00,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF2,0x30,0x2A,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x02,0x01,0x16,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77, + 0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70, + 0x6C,0x65,0x63,0x61,0x2F,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x02,0x02,0x30,0x81,0xB6,0x1A,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65, + 0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69, + 0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72,0x74, + 0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74, + 0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65,0x6E, + 0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61,0x6E, + 0x64,0x61,0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20,0x63, + 0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65, + 0x2C,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70,0x6F, + 0x6C,0x69,0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69, + 0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20, + 0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x5C, + 0x36,0x99,0x4C,0x2D,0x78,0xB7,0xED,0x8C,0x9B,0xDC,0xF3,0x77,0x9B,0xF2,0x76,0xD2, + 0x77,0x30,0x4F,0xC1,0x1F,0x85,0x83,0x85,0x1B,0x99,0x3D,0x47,0x37,0xF2,0xA9,0x9B, + 0x40,0x8E,0x2C,0xD4,0xB1,0x90,0x12,0xD8,0xBE,0xF4,0x73,0x9B,0xEE,0xD2,0x64,0x0F, + 0xCB,0x79,0x4F,0x34,0xD8,0xA2,0x3E,0xF9,0x78,0xFF,0x6B,0xC8,0x07,0xEC,0x7D,0x39, + 0x83,0x8B,0x53,0x20,0xD3,0x38,0xC4,0xB1,0xBF,0x9A,0x4F,0x0A,0x6B,0xFF,0x2B,0xFC, + 0x59,0xA7,0x05,0x09,0x7C,0x17,0x40,0x56,0x11,0x1E,0x74,0xD3,0xB7,0x8B,0x23,0x3B, + 0x47,0xA3,0xD5,0x6F,0x24,0xE2,0xEB,0xD1,0xB7,0x70,0xDF,0x0F,0x45,0xE1,0x27,0xCA, + 0xF1,0x6D,0x78,0xED,0xE7,0xB5,0x17,0x17,0xA8,0xDC,0x7E,0x22,0x35,0xCA,0x25,0xD5, + 0xD9,0x0F,0xD6,0x6B,0xD4,0xA2,0x24,0x23,0x11,0xF7,0xA1,0xAC,0x8F,0x73,0x81,0x60, + 0xC6,0x1B,0x5B,0x09,0x2F,0x92,0xB2,0xF8,0x44,0x48,0xF0,0x60,0x38,0x9E,0x15,0xF5, + 0x3D,0x26,0x67,0x20,0x8A,0x33,0x6A,0xF7,0x0D,0x82,0xCF,0xDE,0xEB,0xA3,0x2F,0xF9, + 0x53,0x6A,0x5B,0x64,0xC0,0x63,0x33,0x77,0xF7,0x3A,0x07,0x2C,0x56,0xEB,0xDA,0x0F, + 0x21,0x0E,0xDA,0xBA,0x73,0x19,0x4F,0xB5,0xD9,0x36,0x7F,0xC1,0x87,0x55,0xD9,0xA7, + 0x99,0xB9,0x32,0x42,0xFB,0xD8,0xD5,0x71,0x9E,0x7E,0xA1,0x52,0xB7,0x1B,0xBD,0x93, + 0x42,0x24,0x12,0x2A,0xC7,0x0F,0x1D,0xB6,0x4D,0x9C,0x5E,0x63,0xC8,0x4B,0x80,0x17, + 0x50,0xAA,0x8A,0xD5,0xDA,0xE4,0xFC,0xD0,0x09,0x07,0x37,0xB0,0x75,0x75,0x21, +}; + +uint8_t _devID_OCSPResponse[] = { + 0x30,0x82,0x09,0xcb,0x0a,0x01,0x00,0xa0,0x82,0x09,0xc4,0x30,0x82,0x09,0xc0,0x06,0x09,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x30,0x01,0x01,0x04,0x82,0x09,0xb1,0x30,0x82,0x09,0xad,0x30,0x81,0xb2,0xa2,0x16,0x04, + 0x14,0xd5,0x02,0x45,0x68,0xa0,0x3d,0x2c,0x63,0x40,0x22,0x62,0xb7,0x9c,0x0e,0x85,0x69,0x74,0xb4,0x30, + 0xe8,0x18,0x0f,0x32,0x30,0x31,0x39,0x31,0x31,0x31,0x36,0x30,0x31,0x31,0x32,0x32,0x31,0x5a,0x30,0x81, + 0x86,0x30,0x81,0x83,0x30,0x41,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0x33, + 0x81,0xd1,0xef,0xdb,0x68,0xb0,0x85,0x21,0x4d,0x2e,0xef,0xaf,0x8c,0x4a,0x69,0x64,0x3c,0x2a,0x6c,0x04, + 0x14,0x57,0x17,0xed,0xa2,0xcf,0xdc,0x7c,0x98,0xa1,0x10,0xe0,0xfc,0xbe,0x87,0x2d,0x2c,0xf2,0xe3,0x17, + 0x54,0x02,0x08,0x03,0xb5,0x01,0x60,0xcb,0x4d,0x00,0xde,0xa1,0x16,0x18,0x0f,0x32,0x30,0x31,0x37,0x30, + 0x36,0x31,0x36,0x30,0x34,0x35,0x34,0x30,0x30,0x5a,0xa0,0x03,0x0a,0x01,0x04,0x18,0x0f,0x32,0x30,0x31, + 0x39,0x31,0x31,0x31,0x36,0x30,0x31,0x31,0x32,0x32,0x31,0x5a,0xa0,0x11,0x18,0x0f,0x32,0x30,0x31,0x39, + 0x31,0x31,0x31,0x36,0x31,0x33,0x31,0x32,0x32,0x31,0x5a,0xa1,0x02,0x30,0x00,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x83,0x4f,0x47,0x06,0xe9, + 0x00,0x22,0xf6,0x8c,0xed,0xea,0x79,0xc3,0xa3,0xb5,0xcd,0x9d,0xbf,0x49,0xec,0xea,0x78,0xff,0xda,0xcd, + 0xa8,0xd0,0xdd,0xeb,0x0c,0x4d,0x6d,0x68,0x6a,0x98,0xb4,0xaf,0x6c,0x35,0x1b,0xcb,0x7e,0xf2,0x99,0x24, + 0x88,0x87,0xce,0x2b,0x6e,0xba,0x97,0xfe,0x01,0xc9,0x14,0x5e,0xac,0x69,0x9b,0xb8,0x99,0x6c,0x4b,0xe1, + 0x9e,0x6b,0xe3,0x3f,0xd7,0xf5,0xc7,0x9b,0x49,0x37,0x6a,0xa8,0x63,0x24,0x12,0x2d,0xd0,0xf8,0x2f,0xb3, + 0x59,0xe8,0x77,0xb0,0x2b,0x83,0x04,0x7f,0x77,0x38,0x72,0x13,0x1a,0xa1,0xfc,0x53,0x28,0x50,0xc1,0x21, + 0x9c,0xba,0xf0,0xd0,0xee,0xb2,0x13,0xd9,0x72,0xee,0x89,0xd6,0x78,0xdd,0x42,0x0b,0x62,0xf5,0x6c,0x8a, + 0xdd,0x11,0xf6,0x55,0x69,0x35,0xf9,0x9b,0x4c,0x36,0x39,0x37,0xf7,0xe5,0x4a,0x91,0x9a,0x8e,0x84,0x59, + 0x2a,0xbb,0x20,0xd3,0x1d,0xce,0x95,0x5c,0x77,0xd5,0x15,0x5a,0x1f,0x86,0xec,0xa9,0xaf,0xaa,0x34,0xda, + 0xa7,0xb7,0x7d,0xc1,0x61,0xb2,0x45,0xd9,0xc2,0x79,0x55,0x6c,0xe1,0xba,0xfd,0x47,0x44,0x27,0xc3,0x74, + 0xfd,0x1e,0xeb,0x90,0xb6,0xe6,0x49,0x0f,0x28,0xa8,0x88,0x8c,0xcb,0x4a,0x87,0xaa,0x05,0xf7,0x9b,0x05, + 0xe0,0xd2,0xca,0xb7,0x72,0x20,0x46,0x97,0xb5,0x37,0xd8,0x20,0x4d,0x3e,0x56,0x45,0x93,0xf1,0xe6,0x83, + 0x89,0xd6,0x3c,0x53,0x7c,0xea,0xcb,0xb1,0x3e,0x99,0x05,0x8e,0xa3,0x1a,0x98,0x88,0x95,0xe7,0x04,0xcc, + 0xb3,0x8f,0x57,0x0b,0x4a,0x67,0x2f,0xc2,0x93,0x52,0xe2,0xa0,0x82,0x07,0xe0,0x30,0x82,0x07,0xdc,0x30, + 0x82,0x03,0xd0,0x30,0x82,0x02,0xb8,0xa0,0x03,0x02,0x01,0x02,0x02,0x08,0x6f,0x0d,0x6c,0x67,0x66,0x49, + 0x04,0xc5,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x79,0x31, + 0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x0c,0x24,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x20, + 0x49,0x44,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74, + 0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x0c,0x1d,0x41,0x70,0x70, + 0x6c,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74, + 0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70, + 0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 0x30,0x1e,0x17,0x0d,0x31,0x39,0x31,0x30,0x31,0x38,0x30,0x35,0x32,0x39,0x31,0x36,0x5a,0x17,0x0d,0x31, + 0x39,0x31,0x31,0x32,0x39,0x30,0x35,0x32,0x39,0x31,0x36,0x5a,0x30,0x4d,0x31,0x29,0x30,0x27,0x06,0x03, + 0x55,0x04,0x03,0x0c,0x20,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x20,0x49,0x44,0x20,0x4f,0x43, + 0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6f,0x6e,0x64,0x65,0x72,0x20,0x4e,0x4c,0x30,0x37,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x0b, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02, + 0x82,0x01,0x01,0x00,0xa0,0xb8,0xae,0xe4,0x5b,0xe6,0xdd,0x9e,0x87,0xd6,0x27,0x4b,0xbc,0x8e,0xcf,0x79, + 0x34,0x49,0xa5,0xea,0xf0,0x72,0x4d,0xdc,0xe7,0x5e,0x07,0xc2,0x0a,0xd0,0xd1,0xab,0x36,0xe1,0x37,0x91, + 0x9c,0x60,0xc0,0xd1,0xff,0x4a,0x84,0x13,0xec,0xf1,0x11,0x1b,0x3f,0xb9,0x94,0x83,0xe5,0x22,0x22,0xdf, + 0x31,0x79,0xf8,0x3f,0x41,0xc6,0xfe,0x76,0xb0,0x68,0xe1,0x6d,0xb8,0x2f,0xb0,0x62,0x64,0xef,0xf4,0x9b, + 0xcc,0xd1,0xea,0x8f,0xd4,0xdf,0x2e,0x8f,0xc1,0x8e,0xff,0x02,0x67,0xdb,0xc6,0xd8,0x12,0x42,0x87,0x34, + 0x37,0x6d,0xbd,0xdc,0x7c,0xb7,0xfe,0xd5,0x3e,0x7e,0x0a,0x7e,0x82,0x9d,0x07,0x87,0x28,0xf7,0x9b,0xbd, + 0x0f,0x27,0x9c,0xbf,0xfb,0x39,0xd9,0xd5,0x3c,0xf6,0x63,0xae,0xc8,0xe8,0x19,0x27,0x28,0xab,0x94,0xc5, + 0x15,0x53,0xad,0x61,0x77,0xb2,0x5d,0x85,0x1b,0x21,0x80,0x4a,0xae,0x48,0xdb,0x7d,0xd0,0x74,0xd4,0xde, + 0x84,0xa4,0x50,0xd4,0x69,0x04,0x3f,0xee,0x17,0x8b,0x69,0x21,0x9f,0xe4,0x0b,0x80,0x43,0xb6,0x92,0x8d, + 0x87,0x83,0xdd,0xa7,0x12,0x63,0x34,0x47,0xea,0xfb,0x6b,0x7b,0x47,0xfb,0x28,0x17,0x5c,0x4b,0x01,0x8f, + 0x56,0x5f,0x35,0xc1,0x00,0xef,0x92,0x57,0x81,0x4b,0x2e,0x62,0x61,0xe8,0x14,0x5a,0x6b,0x44,0xf7,0x43, + 0x7e,0x88,0x61,0xd2,0xf7,0xd0,0x4f,0x39,0x2f,0xdc,0xa2,0x21,0x28,0xd3,0x43,0x22,0xf1,0x7a,0xed,0x36, + 0x0c,0x4e,0xf5,0xfb,0x64,0x10,0x95,0xb9,0x2b,0x91,0xb9,0xec,0x20,0xda,0x92,0x5d,0xf9,0xf5,0x61,0x1d, + 0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0x87,0x30,0x81,0x84,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01, + 0xff,0x04,0x02,0x30,0x00,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x57,0x17, + 0xed,0xa2,0xcf,0xdc,0x7c,0x98,0xa1,0x10,0xe0,0xfc,0xbe,0x87,0x2d,0x2c,0xf2,0xe3,0x17,0x54,0x30,0x0f, + 0x06,0x09,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x05,0x04,0x02,0x05,0x00,0x30,0x13,0x06,0x03,0x55, + 0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x09,0x30,0x1d,0x06,0x03, + 0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xd5,0x02,0x45,0x68,0xa0,0x3d,0x2c,0x63,0x40,0x22,0x62,0xb7,0x9c, + 0x0e,0x85,0x69,0x74,0xb4,0x30,0xe8,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03, + 0x02,0x07,0x80,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x65,0x0c,0x41,0xf8,0xe1,0x16,0xb7,0xd7,0x61,0xe1,0x6a,0xaf,0x12,0x2e,0x70,0xef,0x0a, + 0x40,0xa4,0xd0,0xe2,0x91,0x70,0xbd,0xdb,0xda,0x65,0x62,0x8b,0x40,0x45,0x23,0xc9,0xe8,0xa4,0xd0,0x33, + 0xf7,0xd1,0xa5,0x80,0x4a,0x3a,0xc8,0x76,0x2d,0x20,0xfe,0x27,0x4b,0x30,0xdf,0xa4,0x00,0x35,0x3d,0x1c, + 0x80,0x7c,0xc5,0x09,0x89,0x47,0xd4,0x78,0x7d,0x14,0xdf,0xa1,0xef,0x16,0xad,0xb1,0xca,0xf4,0xf6,0x09, + 0xab,0xc4,0xdc,0x4d,0x72,0x69,0x87,0x9b,0x5b,0x82,0xbb,0xa7,0x68,0x5e,0xfd,0x80,0x29,0x68,0x2d,0xd5, + 0xa0,0x78,0x04,0x57,0x77,0xd0,0x69,0x57,0xfa,0x83,0xb9,0xf0,0x42,0x42,0x71,0xae,0xfe,0xff,0x0b,0xbd, + 0xd3,0xfb,0x3c,0x17,0x01,0x71,0xe2,0x5e,0x81,0xbe,0x72,0xe0,0x75,0xba,0x41,0x0d,0xf0,0x10,0x71,0x02, + 0x36,0xf3,0x26,0x4a,0x01,0x5c,0xa8,0x21,0xe0,0xb2,0x86,0x27,0x1b,0x5e,0xc1,0xb0,0xb0,0x4f,0xdc,0x77, + 0x89,0xe5,0x5c,0x15,0x9a,0x72,0x39,0xaf,0x57,0xe1,0x94,0x2c,0xa3,0x46,0x44,0xce,0x0d,0xe9,0xf1,0xe6, + 0xfa,0xd9,0x6f,0x1e,0x01,0x28,0x1a,0x0e,0x68,0xf4,0x6c,0xf3,0xbd,0x4a,0xf8,0x3a,0xdf,0x93,0x72,0x05, + 0x4f,0x88,0x4b,0x7e,0x13,0xb6,0x92,0xe3,0x28,0xd0,0x14,0x3c,0x13,0x28,0x6d,0x11,0x27,0x36,0xbc,0x73, + 0x27,0xab,0xfc,0x3f,0xb1,0x00,0xab,0x9b,0x35,0x7a,0x87,0x71,0x0e,0x54,0x03,0x68,0x02,0xb2,0xfc,0x8c, + 0x17,0xf3,0x73,0x7e,0xea,0x75,0x64,0x19,0x56,0x9c,0xac,0xb8,0xe6,0x50,0x7c,0x48,0x94,0xec,0x0e,0x30, + 0x82,0x04,0x04,0x30,0x82,0x02,0xec,0xa0,0x03,0x02,0x01,0x02,0x02,0x08,0x18,0x7a,0xa9,0xa8,0xc2,0x96, + 0x21,0x0c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x62,0x31, + 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0a,0x13,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x26,0x30,0x24,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x1d,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, + 0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0d,0x41,0x70,0x70,0x6c,0x65,0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x41,0x30,0x1e,0x17, + 0x0d,0x31,0x32,0x30,0x32,0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5a,0x17,0x0d,0x32,0x37,0x30,0x32, + 0x30,0x31,0x32,0x32,0x31,0x32,0x31,0x35,0x5a,0x30,0x79,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03, + 0x0c,0x24,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x20,0x49,0x44,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x26, + 0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x0c,0x1d,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31, + 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09, + 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a, + 0x02,0x82,0x01,0x01,0x00,0x89,0x76,0x4f,0x06,0x5b,0x9a,0x41,0xee,0xa5,0x23,0x2b,0x02,0xa3,0x5f,0xd7, + 0x73,0x3f,0xc0,0x35,0xb0,0x8b,0x84,0x0a,0x3f,0x06,0x24,0x7f,0xa7,0x95,0x3f,0xeb,0x4f,0x0e,0x93,0xaf, + 0xb4,0x0e,0xd0,0xc8,0x3e,0xe5,0x6d,0x18,0xb3,0x1f,0xe8,0x89,0x47,0xbf,0xd7,0x09,0x08,0xe4,0xff,0x56, + 0x98,0x29,0x15,0xe7,0x94,0x9d,0xb9,0x35,0xa3,0x0a,0xcd,0xb4,0xc0,0xe1,0xe2,0x60,0xf4,0xca,0xec,0x29, + 0x78,0x45,0x69,0x69,0x60,0x6b,0x5f,0x8a,0x92,0xfc,0x9e,0x23,0xe6,0x3a,0xc2,0x22,0xb3,0x31,0x4f,0x1c, + 0xba,0xf2,0xb6,0x34,0x59,0x42,0xee,0xb0,0xa9,0x02,0x03,0x18,0x91,0x04,0xb6,0xb3,0x78,0x2e,0x33,0x1f, + 0x80,0x45,0x0d,0x45,0x6f,0xbb,0x0e,0x5a,0x5b,0x7f,0x3a,0xe7,0xd8,0x08,0xd7,0x0b,0x0e,0x32,0x6d,0xfb, + 0x86,0x36,0xe4,0x6c,0xab,0xc4,0x11,0x8a,0x70,0x84,0x26,0xaa,0x9f,0x44,0xd1,0xf1,0xb8,0xc6,0x7b,0x94, + 0x17,0x9b,0x48,0xf7,0x0b,0x58,0x16,0xba,0x23,0xc5,0x9f,0x15,0x39,0x7e,0xca,0x5d,0xc3,0x32,0x5f,0x0f, + 0xe0,0x52,0x7f,0x40,0xea,0xbe,0xac,0x08,0x64,0x95,0x5b,0xc9,0x1a,0x9c,0xe5,0x80,0xca,0x1f,0x6a,0x44, + 0x1c,0x6c,0x3e,0xc4,0xb0,0x26,0x1f,0x1d,0xec,0x7b,0xaf,0x5e,0xa0,0x6a,0x3d,0x47,0xa9,0x58,0x12,0x31, + 0x3f,0x20,0x76,0x28,0x6d,0x1d,0x1c,0xb0,0xc2,0x4e,0x11,0x69,0x26,0x8b,0xcb,0xd6,0xd0,0x11,0x82,0xc9, + 0x4e,0x0f,0xf1,0x56,0x74,0xd0,0xd9,0x08,0x4b,0x66,0x78,0xa2,0xab,0xac,0xa7,0xe2,0xd2,0x4c,0x87,0x59, + 0xc9,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xa6,0x30,0x81,0xa3,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04, + 0x16,0x04,0x14,0x57,0x17,0xed,0xa2,0xcf,0xdc,0x7c,0x98,0xa1,0x10,0xe0,0xfc,0xbe,0x87,0x2d,0x2c,0xf2, + 0xe3,0x17,0x54,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x2b,0xd0,0x69,0x47,0x94,0x76,0x09, + 0xfe,0xf4,0x6b,0x8d,0x2e,0x40,0xa6,0xf7,0x47,0x4d,0x7f,0x08,0x5e,0x30,0x2e,0x06,0x03,0x55,0x1d,0x1f, + 0x04,0x27,0x30,0x25,0x30,0x23,0xa0,0x21,0xa0,0x1f,0x86,0x1d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x6c,0x2e,0x61,0x70,0x70,0x6c,0x65,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x6f,0x6f,0x74,0x2e,0x63,0x72, + 0x6c,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x10,0x06, + 0x0a,0x2a,0x86,0x48,0x86,0xf7,0x63,0x64,0x06,0x02,0x06,0x04,0x02,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x42,0x39,0x74,0x6b,0xa1, + 0xdc,0xc6,0xa4,0x8f,0x37,0x2a,0x8c,0xb3,0x1d,0x0a,0x44,0xbc,0x95,0x2c,0x7f,0xbc,0x59,0xb8,0xac,0x61, + 0xfb,0x07,0x90,0x92,0x32,0xb9,0xd4,0xbf,0x3b,0xc1,0x50,0x39,0x6a,0x44,0x74,0xa2,0xec,0x5b,0x1f,0x70, + 0xe5,0xaa,0xdd,0x4b,0x6c,0x1c,0x23,0x71,0x2d,0x5f,0xd1,0xc5,0x93,0xbe,0xee,0x9b,0x8a,0x70,0x65,0x82, + 0x9d,0x16,0xe3,0x1a,0x10,0x17,0x89,0x2d,0xa8,0xcd,0xfd,0x0c,0x78,0x58,0x49,0x0c,0x28,0x7f,0x33,0xee, + 0x00,0x7a,0x1b,0xb4,0x76,0xac,0xb6,0xb5,0xbb,0x4f,0xdf,0xa8,0x1b,0x9d,0xc8,0x19,0x97,0x4a,0x0b,0x56, + 0x67,0x2f,0xc2,0x3e,0xb6,0xb3,0xc4,0x83,0x3a,0xf0,0x77,0x6d,0x74,0xc4,0x2e,0x23,0x51,0xee,0x9a,0xa5, + 0x03,0x6f,0x60,0xf4,0xa5,0x48,0xa7,0x06,0xc2,0xbb,0x5a,0xe2,0x1f,0x1f,0x46,0x45,0x7e,0xe4,0x97,0xf5, + 0x27,0x10,0xb7,0x20,0x22,0x72,0x6f,0x72,0xda,0xc6,0x50,0x75,0xc5,0x3d,0x25,0x8f,0x5d,0xa3,0x00,0xe9, + 0x9f,0x36,0x8c,0x48,0x39,0x8f,0xb3,0x3b,0xea,0x90,0x80,0x2e,0x95,0x9a,0x60,0xf4,0x78,0xce,0xf4,0x0e, + 0x0a,0x53,0x3e,0xa2,0xfa,0x4f,0xd8,0x1e,0xae,0x84,0x95,0x8d,0x32,0xbc,0x56,0x4d,0x89,0xe9,0x78,0x18, + 0xe0,0xac,0x9a,0x42,0xba,0x7a,0x46,0x1b,0x84,0xa2,0x89,0xce,0x14,0xe8,0x88,0xd1,0x58,0x8b,0xf6,0xae, + 0x56,0xc4,0x2c,0x05,0x2a,0x45,0xaf,0x0b,0xd9,0x4b,0xa9,0x02,0x0f,0x34,0xac,0x88,0xc7,0x61,0x55,0x89, + 0x44,0xc9,0x27,0x73,0x07,0xee,0x82,0xe5,0x4e,0xf5,0x70 +}; + +uint8_t _leaf_sha256_valid_cav2_complete_ok1[] = { + 0x30,0x82,0x04,0x7b,0x30,0x82,0x03,0x63,0xa0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0xa4,0x37,0x10,0xc8,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01, + 0x0b,0x05,0x00,0x30,0x81,0x8f,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x0c, + 0x1d,0x43,0x41,0x20,0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6c,0x69,0x64, + 0x20,0x63,0x61,0x76,0x32,0x20,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x31,0x22, + 0x30,0x20,0x06,0x03,0x55,0x04,0x0b,0x0c,0x19,0x56,0x61,0x6c,0x69,0x64,0x20,0x50, + 0x72,0x6f,0x6a,0x65,0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20, + 0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70, + 0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07, + 0x0c,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6e,0x6f,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x08,0x0c,0x02,0x43,0x41,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x30,0x20,0x17,0x0d,0x31,0x38,0x30,0x36,0x31,0x32,0x32, + 0x33,0x32,0x38,0x32,0x32,0x5a,0x18,0x0f,0x32,0x31,0x31,0x38,0x30,0x35,0x31,0x39, + 0x32,0x33,0x32,0x38,0x32,0x32,0x5a,0x30,0x81,0x95,0x31,0x2c,0x30,0x2a,0x06,0x03, + 0x55,0x04,0x03,0x0c,0x23,0x4c,0x65,0x61,0x66,0x20,0x73,0x68,0x61,0x32,0x35,0x36, + 0x20,0x76,0x61,0x6c,0x69,0x64,0x20,0x63,0x61,0x76,0x32,0x20,0x63,0x6f,0x6d,0x70, + 0x6c,0x65,0x74,0x65,0x20,0x6f,0x6b,0x31,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04, + 0x0b,0x0c,0x19,0x56,0x61,0x6c,0x69,0x64,0x20,0x50,0x72,0x6f,0x6a,0x65,0x63,0x74, + 0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63, + 0x2e,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0c,0x09,0x43,0x75,0x70,0x65, + 0x72,0x74,0x69,0x6e,0x6f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0c,0x02, + 0x43,0x41,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, + 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00, + 0xc3,0x8b,0xfa,0x6c,0xa7,0x18,0xd3,0xbc,0x41,0x58,0x47,0x9c,0xa0,0x5a,0x21,0xb0, + 0xaa,0x28,0xd3,0x2b,0xb3,0x57,0xdf,0x5b,0x0f,0x18,0xa8,0xa9,0x5a,0x01,0x9a,0x15, + 0x0b,0x62,0x7f,0x51,0x7d,0x85,0x98,0x48,0x74,0xdf,0xa4,0xb7,0xf2,0x4c,0x88,0x10, + 0xe0,0x41,0x31,0x77,0x64,0x2f,0xe2,0x47,0x3a,0x9b,0xf9,0xf4,0xf3,0xf9,0x3f,0x09, + 0xbc,0x33,0xbb,0xbc,0xf9,0x75,0x7c,0xc8,0x4c,0x95,0xd2,0xa2,0xc3,0xc0,0x0a,0x5f, + 0xf4,0x3b,0x50,0x95,0x53,0xf8,0xf2,0x77,0xce,0x02,0x06,0xbf,0x9e,0x74,0x2e,0x58, + 0x6e,0xff,0x29,0xb6,0x80,0x6a,0xe4,0x07,0xaf,0x41,0x5b,0x91,0x49,0x30,0x3f,0x5b, + 0x1b,0x2d,0xab,0x6a,0xf5,0x48,0x44,0x87,0xf0,0xaf,0xa4,0xb3,0x41,0x28,0x9f,0xf6, + 0xae,0x35,0x0c,0xf6,0x09,0x17,0x34,0x55,0x35,0x50,0xf1,0x57,0xe7,0x6d,0x18,0x24, + 0x35,0x40,0xc3,0xf5,0x41,0xe7,0x9d,0x76,0x33,0xcc,0xaa,0x85,0x3f,0x80,0x6e,0x7f, + 0x55,0x62,0xf3,0x6d,0x61,0x26,0x90,0x4f,0x7d,0x73,0xc1,0x0b,0xae,0xf5,0xf8,0x04, + 0x1a,0xbb,0x88,0x50,0x79,0xfd,0x59,0xe3,0xfc,0x58,0x4b,0xb6,0x20,0x5f,0x26,0xc6, + 0x50,0x31,0x06,0x84,0x8a,0xa9,0xd4,0x1d,0x9b,0x7a,0x55,0x2e,0x52,0xfe,0x5b,0x95, + 0xdf,0x0b,0x03,0xf3,0xcc,0xca,0x9b,0xb5,0x75,0x66,0x16,0x67,0x11,0x63,0x39,0xf9, + 0x77,0x95,0x30,0x0a,0x74,0x9c,0xd4,0xc8,0x81,0x75,0xd3,0x3f,0x59,0x8a,0xea,0x17, + 0x06,0xb3,0xc1,0x20,0x81,0xef,0xbe,0xde,0x91,0x44,0x7c,0x6a,0x49,0xae,0xf2,0x25, + 0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xd3,0x30,0x81,0xd0,0x30,0x0e,0x06,0x03,0x55, + 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x0c,0x06,0x03,0x55, + 0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23, + 0x04,0x18,0x30,0x16,0x80,0x14,0x39,0xbb,0x91,0xb5,0x14,0x54,0x76,0x0c,0x1c,0x0c, + 0xf4,0x4b,0xbc,0xd9,0xf6,0x51,0xc8,0xe2,0x03,0xfc,0x30,0x54,0x06,0x03,0x55,0x1d, + 0x1f,0x04,0x4d,0x30,0x4b,0x30,0x49,0xa0,0x47,0xa0,0x45,0x86,0x43,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x76,0x61,0x6c,0x69,0x64,0x74,0x65,0x73,0x74,0x2e,0x61,0x70, + 0x70,0x6c,0x65,0x2e,0x67,0x65,0x6f,0x66,0x66,0x6b,0x2e,0x6e,0x65,0x74,0x2f,0x76, + 0x32,0x2d,0x73,0x68,0x61,0x32,0x35,0x36,0x2d,0x76,0x61,0x6c,0x69,0x64,0x2d,0x63, + 0x61,0x76,0x32,0x2d,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x2e,0x63,0x72,0x6c, + 0x30,0x39,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x2d,0x30,0x2b, + 0x30,0x29,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x1d,0x68,0x74, + 0x74,0x70,0x3a,0x2f,0x2f,0x6b,0x6e,0x6f,0x77,0x6e,0x2d,0x61,0x6e,0x73,0x77,0x65, + 0x72,0x2d,0x6f,0x63,0x73,0x70,0x2f,0x6f,0x63,0x73,0x70,0x30,0x0d,0x06,0x09,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x02, + 0xc7,0x2c,0xec,0x13,0xcc,0x7c,0x54,0xc6,0xe5,0x00,0x83,0x9b,0xc4,0xe5,0x4e,0xc3, + 0xb1,0x3c,0x1d,0x95,0x2f,0x45,0xe7,0x75,0xaf,0x04,0x89,0xdb,0x05,0x21,0x13,0x12, + 0x75,0x1a,0x52,0xc1,0x31,0x74,0x89,0x87,0xd4,0xfa,0xea,0x6b,0x6f,0x61,0xb1,0xb1, + 0x21,0x49,0xd7,0x25,0xfd,0x31,0xc5,0xf7,0x31,0x1a,0xa5,0x9f,0x08,0xc3,0x16,0x84, + 0x3e,0x93,0x7a,0xdd,0xc4,0x28,0xe2,0xec,0x90,0x70,0x6b,0x58,0x8f,0xdf,0x1f,0x1d, + 0x46,0xf2,0x23,0xa2,0x2f,0x29,0xd4,0xe2,0xd1,0xa2,0x6e,0x20,0x94,0x91,0xa2,0x03, + 0x81,0x04,0xf9,0x4e,0x36,0x4b,0x75,0x2e,0x3a,0x13,0x0a,0x94,0xf8,0x29,0x79,0x0d, + 0xac,0x4a,0xff,0xb6,0x60,0x59,0xa4,0x10,0xea,0x39,0xdd,0x39,0x06,0x7c,0xbc,0x91, + 0x5f,0xbd,0xa7,0x8c,0x9b,0xf5,0xbd,0x17,0x80,0xde,0x8f,0x71,0x22,0x6d,0xef,0xfe, + 0x01,0x04,0xf2,0x7c,0xe1,0x35,0xd1,0x21,0x64,0x4d,0xd7,0xf0,0x43,0x26,0x0b,0x18, + 0x78,0xc0,0xe8,0xad,0x0e,0xc5,0x38,0xb5,0xcc,0xaf,0x04,0x7a,0x78,0xbc,0x1b,0x89, + 0x15,0x1f,0x1e,0x61,0x41,0xb6,0x46,0x8e,0x8b,0xd9,0xae,0x69,0x5c,0x9d,0x2b,0x83, + 0x71,0x25,0xd4,0x48,0x8d,0xfc,0x48,0x51,0x60,0xb3,0xa9,0xf7,0x53,0xf2,0x9b,0xa7, + 0x32,0x56,0x5f,0xea,0xd6,0x99,0xd0,0xef,0x2c,0x41,0x9d,0xe0,0x68,0x9f,0x8e,0xad, + 0x86,0x90,0xaa,0x24,0x5e,0xef,0xb0,0xc7,0x15,0xf2,0xce,0x2d,0x54,0x0c,0x8e,0x5e, + 0x3f,0x63,0xdc,0x74,0x35,0x0e,0x35,0x0d,0xfc,0x0b,0x45,0x56,0x5b,0xb1,0xe2 +}; + +uint8_t _ca_sha256_valid_cav2_complete[] = { + 0x30,0x82,0x04,0x41,0x30,0x82,0x03,0x29,0xa0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0xd3,0x18,0x1d,0xb8,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01, + 0x0b,0x05,0x00,0x30,0x81,0x87,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x03,0x0c, + 0x15,0x56,0x61,0x6c,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x20,0x52, + 0x6f,0x6f,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0b,0x0c, + 0x19,0x56,0x61,0x6c,0x69,0x64,0x20,0x50,0x72,0x6f,0x6a,0x65,0x63,0x74,0x20,0x54, + 0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31, + 0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0c,0x09,0x43,0x75,0x70,0x65,0x72,0x74, + 0x69,0x6e,0x6f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0c,0x02,0x43,0x41, + 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x20,0x17, + 0x0d,0x31,0x38,0x30,0x36,0x31,0x32,0x32,0x33,0x32,0x38,0x32,0x31,0x5a,0x18,0x0f, + 0x32,0x31,0x31,0x38,0x30,0x35,0x31,0x39,0x32,0x33,0x32,0x38,0x32,0x31,0x5a,0x30, + 0x81,0x8f,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x0c,0x1d,0x43,0x41,0x20, + 0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6c,0x69,0x64,0x20,0x63,0x61,0x76, + 0x32,0x20,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x31,0x22,0x30,0x20,0x06,0x03, + 0x55,0x04,0x0b,0x0c,0x19,0x56,0x61,0x6c,0x69,0x64,0x20,0x50,0x72,0x6f,0x6a,0x65, + 0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49, + 0x6e,0x63,0x2e,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0c,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6e,0x6f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08, + 0x0c,0x02,0x43,0x41,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, + 0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01, + 0x01,0x00,0xb6,0xfb,0x13,0xd4,0x51,0x5a,0xe0,0x4e,0x35,0xb6,0xe0,0xc9,0xc3,0x78, + 0x5f,0xec,0x24,0x23,0xf2,0x40,0x0e,0xf8,0x6c,0x7f,0x9a,0xc8,0x71,0xd8,0x0a,0x3e, + 0xdb,0xf4,0x85,0xa5,0x11,0x0e,0x5e,0x89,0xd8,0xd9,0x86,0x5f,0xec,0x85,0xc1,0x36, + 0x4c,0xa5,0x40,0x8b,0x2a,0x66,0xe2,0x41,0x07,0x08,0x74,0xb2,0xe0,0x75,0x5e,0x7b, + 0xe0,0x10,0xf0,0x7f,0x69,0x44,0xa5,0xe5,0xfc,0xd4,0x00,0xc7,0x7e,0xe7,0xc5,0x50, + 0xcf,0xc0,0xe1,0xac,0x84,0xe9,0x08,0x2a,0xba,0x36,0xc4,0x60,0x37,0x07,0x91,0xe0, + 0xcd,0x55,0xef,0x3a,0xcf,0x73,0xb6,0xd6,0x60,0x46,0xa4,0x8a,0x65,0x6d,0xfc,0x77, + 0xa1,0xa0,0x12,0xef,0x20,0xc3,0xc3,0xf5,0x82,0x88,0x36,0x42,0x61,0xec,0x3d,0x3a, + 0xaf,0x73,0x55,0xda,0x4c,0xca,0x86,0x3d,0xbf,0x47,0x1d,0xdf,0x1f,0x41,0xbf,0x2a, + 0x97,0x84,0x85,0x13,0x1e,0x63,0xc5,0x7e,0x2a,0xb4,0xd4,0x56,0x2b,0xa1,0x93,0xc3, + 0xb8,0xb7,0x15,0x71,0xee,0xdc,0xe6,0x8b,0x08,0xe5,0xc9,0x04,0x9f,0xf6,0x87,0xd1, + 0xbf,0x78,0xf8,0x91,0x38,0x43,0x57,0x4b,0x8a,0x12,0x66,0xd6,0xae,0xf2,0xf1,0xa8, + 0x0b,0x1a,0x81,0xf6,0xfd,0x20,0x28,0x5f,0xaf,0xa8,0xe7,0xbc,0x90,0x09,0x85,0xd4, + 0xae,0x21,0x02,0x52,0x41,0xa8,0x03,0x61,0x89,0x11,0x86,0xf1,0xe7,0x49,0x3d,0x14, + 0x63,0x8a,0x69,0x5c,0x53,0x55,0xfe,0x25,0xbd,0xd0,0x2a,0xe8,0xe2,0x19,0xea,0x6f, + 0x20,0x6e,0xb3,0x85,0xa7,0x49,0xe7,0xcc,0x96,0xd8,0x3f,0x4d,0xad,0xe9,0x22,0x03, + 0x65,0x25,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xa7,0x30,0x81,0xa4,0x30,0x0e,0x06, + 0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06, + 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01, + 0x00,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0x39,0xbb,0x91,0xb5, + 0x14,0x54,0x76,0x0c,0x1c,0x0c,0xf4,0x4b,0xbc,0xd9,0xf6,0x51,0xc8,0xe2,0x03,0xfc, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xba,0x56,0xd8, + 0x57,0x66,0xbd,0xfc,0x5b,0xe2,0x10,0xf2,0x39,0xb3,0xaf,0xb2,0x72,0xed,0x55,0x0f, + 0x1c,0x30,0x3e,0x06,0x03,0x55,0x1d,0x1f,0x04,0x37,0x30,0x35,0x30,0x33,0xa0,0x31, + 0xa0,0x2f,0x86,0x2d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x76,0x61,0x6c,0x69,0x64, + 0x74,0x65,0x73,0x74,0x2e,0x61,0x70,0x70,0x6c,0x65,0x2e,0x67,0x65,0x6f,0x66,0x66, + 0x6b,0x2e,0x6e,0x65,0x74,0x2f,0x76,0x32,0x2d,0x72,0x6f,0x6f,0x74,0x2e,0x63,0x72, + 0x6c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x58,0xc7,0x67,0x96,0xb5,0x7a,0x36,0x26,0x63,0xe8,0xc1, + 0x7d,0xd9,0x0b,0x26,0xa4,0x2c,0x09,0xec,0x1e,0x67,0xfd,0x26,0xe4,0x5b,0x73,0x11, + 0x1d,0xfc,0xaf,0xa5,0x70,0x05,0x19,0xdb,0xb7,0x42,0x1b,0xd0,0x36,0x6f,0x8e,0x01, + 0xd3,0x19,0x72,0xff,0x36,0xa5,0x06,0x62,0x8b,0xd6,0x9b,0x40,0x24,0x54,0x48,0x4c, + 0x3f,0xeb,0x8d,0x36,0x9b,0x56,0x2e,0x27,0xf6,0x19,0xbf,0xae,0x07,0x20,0x7c,0x64, + 0x79,0xe3,0x4e,0x1d,0x44,0x26,0x79,0x4f,0x21,0x12,0x6e,0xe6,0x33,0xe3,0xd3,0x23, + 0x55,0xfb,0x49,0x8b,0x7b,0x5d,0xce,0xf5,0x58,0x3b,0x3f,0xb5,0xc6,0x33,0xc2,0x6f, + 0xf5,0xc5,0x0f,0x25,0xf9,0x65,0x79,0x67,0x5d,0xab,0xe8,0xe5,0x59,0x55,0xd3,0x62, + 0xf4,0xfa,0xee,0x65,0xfa,0x55,0x4e,0xc7,0x0e,0x5c,0xa9,0x48,0xc1,0x10,0x30,0x73, + 0xbd,0x5b,0xe3,0x75,0x2b,0xc3,0x20,0x10,0xc7,0x7d,0x3a,0x1d,0x8d,0x17,0x39,0xb5, + 0x58,0xae,0x91,0x32,0xe1,0xd2,0x98,0xfe,0x9a,0xdf,0x4b,0x0e,0x79,0x7b,0x8a,0x7a, + 0x32,0xc7,0x69,0xec,0xe4,0x8e,0xc5,0x4f,0x45,0x00,0x89,0xe6,0x53,0xa0,0x3d,0xee, + 0x1c,0x5a,0xee,0x4d,0x49,0xf2,0x54,0x3b,0xc0,0x4d,0xb4,0xa1,0x47,0x65,0x65,0x7a, + 0xbc,0x3d,0xda,0x54,0xee,0x56,0x74,0x22,0xa9,0x68,0x8e,0x70,0x48,0x2c,0x83,0x1e, + 0x35,0x08,0xb0,0xf2,0x9a,0xb1,0x43,0x88,0x07,0x5e,0xd6,0x94,0x0b,0x4a,0xa5,0x5b, + 0x17,0x47,0x8e,0xcc,0xfa,0xa0,0x24,0xd9,0x1a,0xad,0xad,0x23,0x4f,0xa3,0x59,0xf1, + 0x58,0x45,0x12,0x48,0xdc +}; + +uint8_t _leaf_serial_invalid_incomplete_ok1[] = { + 0x30,0x82,0x04,0x78,0x30,0x82,0x03,0x60,0xa0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0xcd,0xfb,0x60,0x2b,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01, + 0x0b,0x05,0x00,0x30,0x81,0x8e,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x03,0x0c, + 0x1c,0x43,0x41,0x20,0x73,0x65,0x72,0x69,0x61,0x6c,0x20,0x69,0x6e,0x76,0x61,0x6c, + 0x69,0x64,0x20,0x69,0x6e,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x31,0x22,0x30, + 0x20,0x06,0x03,0x55,0x04,0x0b,0x0c,0x19,0x56,0x61,0x6c,0x69,0x64,0x20,0x50,0x72, + 0x6f,0x6a,0x65,0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56, + 0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c, + 0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0c, + 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6e,0x6f,0x31,0x0b,0x30,0x09,0x06,0x03, + 0x55,0x04,0x08,0x0c,0x02,0x43,0x41,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x30,0x20,0x17,0x0d,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32, + 0x34,0x30,0x30,0x37,0x5a,0x18,0x0f,0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32, + 0x32,0x34,0x30,0x30,0x37,0x5a,0x30,0x81,0x94,0x31,0x2b,0x30,0x29,0x06,0x03,0x55, + 0x04,0x03,0x0c,0x22,0x4c,0x65,0x61,0x66,0x20,0x73,0x65,0x72,0x69,0x61,0x6c,0x20, + 0x69,0x6e,0x76,0x61,0x6c,0x69,0x64,0x20,0x69,0x6e,0x63,0x6f,0x6d,0x70,0x6c,0x65, + 0x74,0x65,0x20,0x6f,0x6b,0x31,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0b,0x0c, + 0x19,0x56,0x61,0x6c,0x69,0x64,0x20,0x50,0x72,0x6f,0x6a,0x65,0x63,0x74,0x20,0x54, + 0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31, + 0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0c,0x09,0x43,0x75,0x70,0x65,0x72,0x74, + 0x69,0x6e,0x6f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0c,0x02,0x43,0x41, + 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01, + 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00, + 0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xc0,0x12, + 0xf8,0x4e,0x54,0xd5,0x0a,0xf6,0x43,0x16,0x4d,0xe2,0xe9,0x4c,0xb8,0x1c,0x05,0x6d, + 0x1b,0x0c,0xd5,0x7c,0x29,0x1e,0x82,0x5e,0x6a,0xb6,0x85,0x03,0x72,0x13,0x60,0x94, + 0xee,0x8d,0x56,0x03,0xd1,0x41,0x84,0x7c,0xf0,0xc1,0xd2,0x60,0xda,0x2e,0x56,0x8a, + 0xca,0x01,0xf6,0xbe,0x89,0x7a,0x27,0x44,0x6d,0x28,0x2c,0xfa,0x02,0x36,0xf7,0xa7, + 0x0d,0x4b,0x27,0x83,0x90,0x3c,0x14,0x1e,0x73,0xa5,0x61,0xc0,0xf4,0x05,0x43,0xed, + 0x36,0x34,0x14,0x7a,0xe0,0x9b,0x4e,0xbb,0x0f,0x12,0x97,0xcb,0x1b,0x99,0x46,0x41, + 0x3e,0xcb,0xa1,0xc3,0xab,0x43,0x27,0x45,0x37,0x61,0x94,0xe3,0xe8,0x60,0xd3,0x94, + 0x21,0x6f,0xd8,0x61,0x28,0x81,0xb5,0xe3,0x0f,0xfd,0x2f,0x61,0xe4,0xa4,0x5c,0x25, + 0x91,0x58,0xa0,0x55,0x5e,0xae,0x44,0x61,0x92,0x2b,0x99,0x13,0x1a,0xba,0x7c,0x1e, + 0xa1,0x2d,0xd2,0x02,0x78,0x9d,0xf2,0xfb,0x1a,0xd8,0xc2,0x01,0x19,0x76,0x30,0xf1, + 0x6a,0x65,0xd3,0x76,0xc7,0x67,0xb0,0xe8,0xa0,0x15,0xce,0x8d,0x90,0x45,0xe8,0x71, + 0x68,0x9f,0x56,0x91,0x22,0xe4,0xf4,0x16,0x69,0x2d,0x87,0x23,0x52,0x51,0x27,0x13, + 0x6e,0x7e,0xdf,0xf1,0x7e,0x67,0x5d,0x56,0xb8,0x8b,0x5d,0x75,0x09,0xb2,0x4a,0x3b, + 0x5e,0xac,0x8e,0x42,0xf4,0xb6,0xc2,0xf6,0x5c,0xde,0x9d,0xeb,0xf5,0x82,0xed,0x71, + 0xfa,0x23,0x94,0xd6,0x1c,0x19,0x65,0xa5,0xae,0x38,0xbd,0x57,0x27,0xfd,0x7c,0x2b, + 0x30,0x71,0xb1,0xa0,0x4a,0xac,0xbe,0xcb,0xe7,0x17,0x81,0x20,0xe9,0x8f,0x02,0x03, + 0x01,0x00,0x01,0xa3,0x81,0xd2,0x30,0x81,0xcf,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f, + 0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13, + 0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18, + 0x30,0x16,0x80,0x14,0xa2,0xee,0xae,0x1f,0x41,0x28,0x69,0x40,0x55,0xdf,0xc5,0x33, + 0x56,0xab,0xfc,0x23,0x68,0x17,0xcb,0x39,0x30,0x53,0x06,0x03,0x55,0x1d,0x1f,0x04, + 0x4c,0x30,0x4a,0x30,0x48,0xa0,0x46,0xa0,0x44,0x86,0x42,0x68,0x74,0x74,0x70,0x3a, + 0x2f,0x2f,0x76,0x61,0x6c,0x69,0x64,0x74,0x65,0x73,0x74,0x2e,0x61,0x70,0x70,0x6c, + 0x65,0x2e,0x67,0x65,0x6f,0x66,0x66,0x6b,0x2e,0x6e,0x65,0x74,0x2f,0x76,0x32,0x2d, + 0x73,0x65,0x72,0x69,0x61,0x6c,0x2d,0x69,0x6e,0x76,0x61,0x6c,0x69,0x64,0x2d,0x69, + 0x6e,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x2e,0x63,0x72,0x6c,0x30,0x39,0x06, + 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x2d,0x30,0x2b,0x30,0x29,0x06, + 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x1d,0x68,0x74,0x74,0x70,0x3a, + 0x2f,0x2f,0x6b,0x6e,0x6f,0x77,0x6e,0x2d,0x61,0x6e,0x73,0x77,0x65,0x72,0x2d,0x6f, + 0x63,0x73,0x70,0x2f,0x6f,0x63,0x73,0x70,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6c,0x93,0x89,0x44, + 0x96,0x48,0x63,0xa2,0x3c,0x68,0x26,0x3c,0xb5,0x36,0x4a,0x4c,0x3e,0xc4,0xd2,0x7c, + 0x2a,0x62,0xed,0x48,0x61,0x60,0x7f,0xe0,0x90,0xe9,0x31,0xf0,0x12,0xa3,0xdd,0x51, + 0x20,0xf2,0x4b,0xec,0x1c,0x0e,0x1c,0xd5,0xdc,0xbf,0x79,0x1a,0x4b,0xc4,0xd8,0x50, + 0x9d,0x9d,0x17,0xcb,0x0b,0x13,0x12,0x5f,0x54,0x20,0x05,0x5a,0x36,0x27,0x6b,0xef, + 0x89,0x34,0x96,0x73,0xae,0x9d,0xd2,0x1c,0x0a,0x98,0x39,0xec,0x83,0x2d,0xcd,0x47, + 0x50,0x41,0x5e,0xac,0x03,0x02,0x43,0x05,0xdd,0x34,0xbe,0x64,0x97,0xe3,0x2f,0xa0, + 0x70,0xc8,0xbd,0xc9,0x3e,0x6b,0x58,0x84,0x87,0xa5,0xea,0xbe,0xcc,0x7a,0xf8,0xe6, + 0xe4,0xa7,0x57,0x32,0xc0,0x3e,0x5a,0x38,0xdb,0xf9,0x95,0xdb,0xb2,0x18,0x09,0xab, + 0xbc,0x5c,0x22,0xe4,0x08,0xd7,0xd1,0xdf,0xd0,0xf6,0xef,0x02,0x0d,0xbc,0x9b,0xce, + 0x0e,0xcd,0x13,0x60,0x48,0xcc,0x5f,0x0e,0xef,0x38,0x13,0x3b,0x88,0x51,0xca,0xea, + 0x7e,0xb7,0xf9,0x53,0xa5,0xe2,0xe3,0x79,0xc5,0xe3,0x3f,0x3d,0x7b,0xfb,0x16,0xd8, + 0xcf,0xed,0x8e,0x02,0x4a,0x60,0xa2,0x2e,0x00,0x16,0xd6,0x1b,0x8a,0xbe,0x0b,0xb3, + 0x6b,0x91,0x10,0x97,0xf4,0xf0,0x39,0xa8,0x35,0xb8,0xc8,0x51,0x09,0x34,0x9e,0x0f, + 0xc8,0x52,0xad,0x72,0xb1,0xe8,0x39,0x64,0xa4,0xa2,0x96,0xa2,0x85,0xff,0xc9,0x63, + 0x45,0xe0,0xad,0xf0,0x15,0x91,0x66,0xd0,0x05,0x7b,0x39,0xbd,0x39,0x33,0xf8,0xd1, + 0x46,0x21,0x02,0xe7,0xc3,0x73,0xda,0x65,0xe8,0xa7,0x64,0xbd +}; + +uint8_t _ca_serial_invalid_incomplete[] = { + 0x30,0x82,0x04,0x40,0x30,0x82,0x03,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0x80,0x00,0x46,0x45,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01, + 0x0b,0x05,0x00,0x30,0x81,0x87,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x03,0x0c, + 0x15,0x56,0x61,0x6c,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x20,0x52, + 0x6f,0x6f,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0b,0x0c, + 0x19,0x56,0x61,0x6c,0x69,0x64,0x20,0x50,0x72,0x6f,0x6a,0x65,0x63,0x74,0x20,0x54, + 0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31, + 0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0c,0x09,0x43,0x75,0x70,0x65,0x72,0x74, + 0x69,0x6e,0x6f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0c,0x02,0x43,0x41, + 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x20,0x17, + 0x0d,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30,0x36,0x5a,0x18,0x0f, + 0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30,0x30,0x36,0x5a,0x30, + 0x81,0x8e,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x03,0x0c,0x1c,0x43,0x41,0x20, + 0x73,0x65,0x72,0x69,0x61,0x6c,0x20,0x69,0x6e,0x76,0x61,0x6c,0x69,0x64,0x20,0x69, + 0x6e,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x31,0x22,0x30,0x20,0x06,0x03,0x55, + 0x04,0x0b,0x0c,0x19,0x56,0x61,0x6c,0x69,0x64,0x20,0x50,0x72,0x6f,0x6a,0x65,0x63, + 0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0a,0x0c,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e, + 0x63,0x2e,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0c,0x09,0x43,0x75,0x70, + 0x65,0x72,0x74,0x69,0x6e,0x6f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0c, + 0x02,0x43,0x41,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01, + 0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01, + 0x00,0xcd,0x06,0x79,0xc3,0xeb,0x86,0x31,0x75,0xe7,0xb5,0x9d,0xe3,0x20,0xd3,0x13, + 0x7c,0x90,0xfb,0xfe,0x51,0xd0,0x17,0x04,0x61,0x64,0x92,0xd2,0x63,0xe2,0x91,0x17, + 0x90,0x2e,0xb0,0xa6,0x03,0x8f,0xb2,0xc2,0x8c,0x32,0xf2,0xbe,0x51,0xad,0xee,0x72, + 0xf5,0x1f,0x15,0x94,0x72,0x8c,0x17,0xc1,0x47,0x3c,0x74,0xa2,0xb0,0x89,0x7d,0x96, + 0xa3,0x01,0xf7,0x14,0x21,0x80,0x0d,0x6e,0x5d,0x56,0x2a,0xcc,0xdc,0x7b,0xfc,0x83, + 0xe9,0xb4,0xbc,0x46,0x41,0x14,0xfb,0xb6,0xcc,0x4b,0x5a,0xa0,0x11,0x14,0x4c,0x92, + 0x2f,0x47,0xd5,0x3c,0xc9,0xe9,0xfa,0xb5,0x66,0x6b,0x3a,0xdf,0x1b,0x62,0x1a,0x44, + 0xa3,0x63,0xf3,0x1a,0x2f,0x46,0xdb,0xd0,0x9e,0x0d,0x9a,0xed,0xcd,0xf3,0xa0,0xb0, + 0xd9,0xf0,0xb0,0x58,0xe8,0xfe,0xb7,0x34,0x6c,0x87,0xfa,0xf6,0x96,0xe3,0x2d,0xc1, + 0xd5,0x54,0x56,0x88,0x61,0xa6,0xd6,0x58,0xbd,0x58,0x0d,0xc7,0x6f,0xe6,0x84,0xf8, + 0x2a,0x24,0xf2,0x97,0xca,0x8c,0xae,0xf9,0xa5,0xe2,0x5e,0x4a,0x9f,0xbf,0xd2,0x4b, + 0xe6,0x53,0x72,0xfc,0x05,0x93,0x72,0x40,0x0f,0xc5,0x26,0xda,0x00,0x35,0xe6,0x57, + 0xef,0xc2,0x28,0xcf,0x62,0xe9,0x27,0x05,0x1c,0x47,0x33,0x92,0x14,0x87,0xcb,0x8a, + 0x34,0xb3,0xb2,0xf8,0x88,0xe5,0x8c,0x44,0xdf,0x1b,0x62,0xbc,0xaa,0x9a,0x49,0x5b, + 0xff,0x4c,0x37,0x33,0xad,0x6f,0x98,0x61,0xce,0xc5,0xb5,0x02,0xe0,0x12,0x24,0xc1, + 0x59,0x28,0xd8,0x2b,0xea,0x94,0x82,0x2d,0x28,0x37,0xcc,0xf3,0x60,0x9f,0x08,0xe1, + 0x3f,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xa7,0x30,0x81,0xa4,0x30,0x0e,0x06,0x03, + 0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03, + 0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x00, + 0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xa2,0xee,0xae,0x1f,0x41, + 0x28,0x69,0x40,0x55,0xdf,0xc5,0x33,0x56,0xab,0xfc,0x23,0x68,0x17,0xcb,0x39,0x30, + 0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xba,0x56,0xd8,0x57, + 0x66,0xbd,0xfc,0x5b,0xe2,0x10,0xf2,0x39,0xb3,0xaf,0xb2,0x72,0xed,0x55,0x0f,0x1c, + 0x30,0x3e,0x06,0x03,0x55,0x1d,0x1f,0x04,0x37,0x30,0x35,0x30,0x33,0xa0,0x31,0xa0, + 0x2f,0x86,0x2d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x76,0x61,0x6c,0x69,0x64,0x74, + 0x65,0x73,0x74,0x2e,0x61,0x70,0x70,0x6c,0x65,0x2e,0x67,0x65,0x6f,0x66,0x66,0x6b, + 0x2e,0x6e,0x65,0x74,0x2f,0x76,0x32,0x2d,0x72,0x6f,0x6f,0x74,0x2e,0x63,0x72,0x6c, + 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x43,0xa4,0x08,0x47,0x8c,0x5c,0x79,0x0b,0x5f,0xe2,0xe7,0xec, + 0x0e,0x70,0x69,0xee,0xd1,0xbb,0xda,0x02,0x06,0xcf,0x75,0xbe,0xe9,0xbf,0xfd,0xf7, + 0xa0,0x3b,0x8e,0xf0,0x01,0x6c,0x1b,0x82,0x7d,0xeb,0x6f,0xaa,0x7a,0x3c,0xef,0x7b, + 0xd9,0x9c,0x74,0x48,0x2a,0x2a,0xd1,0xa3,0x0d,0xee,0xe8,0xa3,0x55,0x83,0xd6,0xa4, + 0x3a,0xb1,0x2b,0xf1,0x44,0x8e,0x3d,0xec,0xc7,0x74,0x73,0x1b,0xaf,0xf1,0xee,0xea, + 0x69,0x8a,0xa2,0x88,0xf6,0x82,0x6a,0x2d,0x21,0xfd,0x0c,0xf2,0x50,0x6a,0x34,0x81, + 0x43,0x8e,0x81,0x0a,0xfa,0x26,0xc4,0x4a,0x10,0x60,0x85,0xb7,0xf3,0xdc,0xd2,0xc7, + 0xe2,0xe7,0x17,0x94,0x82,0x68,0x33,0xa3,0xd4,0x19,0xcb,0x10,0x16,0x65,0x4c,0x6b, + 0xe7,0x3f,0x3a,0xbe,0x1b,0x3b,0x08,0x0c,0x16,0x0e,0xe0,0x7f,0x75,0x44,0xa9,0xfa, + 0x6e,0x2f,0xd1,0x27,0x9b,0xc5,0x4e,0xec,0xac,0xb5,0xaf,0x2b,0xdf,0x10,0xbc,0x38, + 0x85,0x4c,0x00,0x18,0x86,0x30,0x40,0x2d,0xab,0xf4,0xc3,0x1e,0xfb,0x3b,0xdf,0xa6, + 0x72,0xb9,0x5e,0x24,0x81,0x39,0x92,0x02,0xf9,0xc9,0xc1,0xfc,0x35,0x1a,0x0a,0x0c, + 0x2c,0xd4,0x4e,0xae,0x03,0x79,0x22,0xd5,0x97,0x29,0xf6,0x13,0x2f,0xce,0xb6,0x69, + 0x5e,0x4f,0xc6,0x0c,0x06,0x00,0x28,0x7c,0x14,0x3e,0xab,0x32,0xaf,0xd6,0x02,0x04, + 0x18,0xc8,0xdc,0x9c,0xaf,0x23,0x08,0xc3,0xca,0x3e,0xbc,0xf1,0x44,0xc5,0x43,0x91, + 0x00,0x39,0x46,0x15,0x88,0xce,0xe9,0xe3,0xf5,0xae,0xdc,0x5b,0x63,0x77,0xd5,0xc8, + 0xf9,0x35,0x0b,0xe1 +}; + +#endif /* _TRUSTTESTS_REVOCATION_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/SMIMEPolicyTests.m b/tests/TrustTests/EvaluationTests/SMIMEPolicyTests.m new file mode 100644 index 00000000..5f95a8ff --- /dev/null +++ b/tests/TrustTests/EvaluationTests/SMIMEPolicyTests.m @@ -0,0 +1,439 @@ +// +// SMIMEPolicyTests.m +// Security +// +// Created by Bailey Basile on 11/5/19. +// + +#import + +#include +#include + +#import "../TrustEvaluationTestHelpers.h" +#import "TrustEvaluationTestCase.h" + +@interface SMIMEPolicyTests : TrustEvaluationTestCase +@end + +NSString *testDir = @"SMIMEPolicyTests-data"; +const CFStringRef emailAddr = CFSTR("test@example.com"); + +@implementation SMIMEPolicyTests + +- (NSArray *)anchors +{ + id root = [self SecCertificateCreateFromResource:@"root" subdirectory:testDir]; + NSArray *anchors = @[root]; + CFRelease((SecCertificateRef)root); + return anchors; +} + +- (NSDate *)verifyDate +{ + return [NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]; // January 6, 2020 at 2:40:00 AM PST +} + +- (bool)runTrustEvalForLeaf:(id)leaf policy:(SecPolicyRef)policy +{ + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[leaf] policies:@[(__bridge id)policy]]; + XCTAssertNotNil(eval); + [eval setAnchors:[self anchors]]; + [eval setVerifyDate:[self verifyDate]]; + return [eval evaluate:nil]; +} + +// MARK: Expiration tests + +- (void)testCheckExpiration +{ + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + id leaf = [self SecCertificateCreateFromResource:@"email_protection" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Within validity + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[leaf] policies:@[(__bridge id)policy]]; + XCTAssertNotNil(eval); + [eval setAnchors:[self anchors]]; + [eval setVerifyDate:[self verifyDate]]; + XCTAssert([eval evaluate:nil]); + + // Expired + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:630000000.0]]; // December 18, 2020 at 8:00:00 AM PST + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testIgnoreExpiration +{ + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage | kSecIgnoreExpirationSMIMEUsage, emailAddr); + id leaf = [self SecCertificateCreateFromResource:@"email_protection" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Within validity + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[leaf] policies:@[(__bridge id)policy]]; + XCTAssertNotNil(eval); + [eval setAnchors:[self anchors]]; + [eval setVerifyDate:[self verifyDate]]; + XCTAssert([eval evaluate:nil]); + + // Expired + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:630000000.0]]; // December 18, 2020 at 8:00:00 AM PST + XCTAssert([eval evaluate:nil]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +// MARK: Name tests + +- (void)testNoEmailName +{ + id leaf = [self SecCertificateCreateFromResource:@"no_name" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Check Email name + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Skip email name check + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, NULL); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testEmailNameSAN +{ + id leaf = [self SecCertificateCreateFromResource:@"san_name" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Address match + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Address mismatch + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, CFSTR("wrong@example.com")); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Case-insensitive match + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, CFSTR("TEST@example.com")); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testEmailCommonName +{ + id leaf = [self SecCertificateCreateFromResource:@"common_name" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Address match but common name matches not supported + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testEmailAddressField +{ + id leaf = [self SecCertificateCreateFromResource:@"email_field" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Address match but subject name matches not supported + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Address mismatch + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, CFSTR("wrong@example.com")); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Case-insensitive match + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, CFSTR("TEST@example.com")); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +// MARK: KU tests +- (void)testNoKU +{ + id leaf = [self SecCertificateCreateFromResource:@"san_name" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for sign KU (which allows unspecified KU) + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for sign KU or any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Don't look at KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(0, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testSignKU +{ + id leaf = [self SecCertificateCreateFromResource:@"digital_signature" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for sign KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for sign KU or any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testNonRepudiationKU +{ + id leaf = [self SecCertificateCreateFromResource:@"non_repudiation" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for sign KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for sign KU or any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // No KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(0, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyEncipherKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_encipher" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Encipher KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Data Encipher KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecDataEncryptSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testDataEncipherKU +{ + id leaf = [self SecCertificateCreateFromResource:@"data_encipher" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Data Encipher KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecDataEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Encipher KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyEncryptSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyAgreementKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_agreement" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Agreement Encrypt KU /* */ + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyExchangeEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Decrypt KU /* */ + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeDecryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Both KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Digital Signature KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyAgreementEncipherOnlyKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_agreement_encipher_only" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Agreement Encrypt KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyExchangeEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Decrypt KU /* */ + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeDecryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Both KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Digital Signature KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyAgreementDecipherOnlyKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_agreement_decipher_only" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Agreement Encrypt KU /* */ + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyExchangeEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Decrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeDecryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Both KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Digital Signature KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyAgreementBothKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_agreement_encipher_decipher" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Agreement Encrypt KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyExchangeEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Decrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeDecryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Both KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Digital Signature KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +// MARK: EKU tests +- (void)testNoEKU +{ + id leaf = [self SecCertificateCreateFromResource:@"digital_signature" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testAnyEKU +{ + id leaf = [self SecCertificateCreateFromResource:@"any_eku" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testEmailEKU +{ + id leaf = [self SecCertificateCreateFromResource:@"email_protection" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +@end diff --git a/tests/TrustTests/EvaluationTests/SSLPolicyTests.m b/tests/TrustTests/EvaluationTests/SSLPolicyTests.m index 79f32b67..df056ea2 100644 --- a/tests/TrustTests/EvaluationTests/SSLPolicyTests.m +++ b/tests/TrustTests/EvaluationTests/SSLPolicyTests.m @@ -36,6 +36,8 @@ #include "SSLPolicyTests_data.h" #import "TrustEvaluationTestCase.h" +NSString * const testDirectory = @"ssl-policy-certs"; + @interface SSLPolicyTests : TrustEvaluationTestCase @end @@ -43,7 +45,7 @@ - (void)testSSLPolicyCerts { - NSArray *testPlistURLs = [[NSBundle bundleForClass:[self class]] URLsForResourcesWithExtension:@"plist" subdirectory:@"ssl-policy-certs"]; + NSArray *testPlistURLs = [[NSBundle bundleForClass:[self class]] URLsForResourcesWithExtension:@"plist" subdirectory:testDirectory]; if (testPlistURLs.count != 1) { fail("failed to find the test plist"); return; @@ -75,7 +77,7 @@ require_action_quiet(file, cleanup, fail("%@: Unable to load filename from plist", test_name)); /* get leaf certificate from file */ - cert_file_url = [[NSBundle bundleForClass:[self class]] URLForResource:(__bridge NSString *)file withExtension:@"cer" subdirectory:@"ssl-policy-certs"]; + cert_file_url = [[NSBundle bundleForClass:[self class]] URLForResource:(__bridge NSString *)file withExtension:@"cer" subdirectory:testDirectory]; require_action_quiet(cert_file_url, cleanup, fail("%@: Unable to get url for cert file %@", test_name, file)); @@ -153,9 +155,14 @@ } - (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors error:(NSError **)error +{ + return [self runTrustEvaluation:certs anchors:anchors date:590000000.0 error:error]; // September 12, 2019 at 9:53:20 AM PDT +} + +- (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors date:(NSTimeInterval)evalTime error:(NSError **)error { SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("example.com")); - NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:590000000.0]; // September 12, 2019 at 9:53:20 AM PDT + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:evalTime]; SecTrustRef trustRef = NULL; BOOL result = NO; CFErrorRef cferror = NULL; @@ -224,6 +231,116 @@ errOut: CFReleaseNull(root); } +- (void)testSystemTrust_subCAMissingEKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + NSData *rootHash = CFBridgingRelease(SecCertificateCopySHA256Digest(systemRoot)); + [self setTestRootAsSystem:(const uint8_t *)[rootHash bytes]]; + + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_noEKU_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_noEKU_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "system-trusted no EKU subCA cert failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + +- (void)testSystemTrust_subCAAnyEKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + NSData *rootHash = CFBridgingRelease(SecCertificateCopySHA256Digest(systemRoot)); + [self setTestRootAsSystem:(const uint8_t *)[rootHash bytes]]; + + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_anyEKU_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_anyEKU_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "system-trusted anyEKU subCA cert failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + +- (void)testSystemTrust_subCAServerAuthEKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + NSData *rootHash = CFBridgingRelease(SecCertificateCopySHA256Digest(systemRoot)); + [self setTestRootAsSystem:(const uint8_t *)[rootHash bytes]]; + + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_ssl_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_ssl_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "system-trusted SSL EKU subCA cert failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + +- (void)testSystemTrust_subCA_SMIME_EKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + NSData *rootHash = CFBridgingRelease(SecCertificateCopySHA256Digest(systemRoot)); + [self setTestRootAsSystem:(const uint8_t *)[rootHash bytes]]; + + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_smime_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_smime_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertFalse([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "system-trusted SMIME subCA cert succeeded"); + XCTAssertNotNil(error); + if (error) { + XCTAssertEqual(error.code, errSecInvalidExtendedKeyUsage); + } + + [self removeTestRootAsSystem]; + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + +- (void)testAppTrust_subCA_SMIME_EKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_smime_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_smime_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "app-trusted smime subCA cert failed: %@", error); + + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + // Other app trust of root SSL EKU tests of certs issued before July 2019 occur in testSSLPolicyCerts (Test4, Test17) - (void)testAppTrustRoot_AnyEKU_BeforeJul2019 @@ -396,4 +513,74 @@ errOut: } #endif // !TARGET_OS_BRIDGE +- (void)testIPAddressInDNSField +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_dnsField, sizeof(_ipAddress_dnsField)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.1")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + +- (void)testIPAddressInSAN_Match +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_SAN, sizeof(_ipAddress_SAN)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.1")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssert([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + +- (void)testIPAddressInSAN_Mismatch +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_SAN, sizeof(_ipAddress_SAN)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.2")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + +- (void)testIPAddressInCN +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_CN, sizeof(_ipAddress_CN)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.1")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + +- (void)testBadIPAddressInSAN +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_bad, sizeof(_ipAddress_bad)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.1")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + @end diff --git a/tests/TrustTests/EvaluationTests/SSLPolicyTests_data.h b/tests/TrustTests/EvaluationTests/SSLPolicyTests_data.h index 3a03abbf..52fcd7ca 100644 --- a/tests/TrustTests/EvaluationTests/SSLPolicyTests_data.h +++ b/tests/TrustTests/EvaluationTests/SSLPolicyTests_data.h @@ -619,4 +619,294 @@ const uint8_t _anyEKU_AfterJul2019[] = { 0x49,0x64,0x81,0x31,0x5C,0x52,0x1A,0x7C,0x32,0x4A,0xB8,0xA6,0xE7,0xDD,0x95,0xD3, 0x2A,0x2C,0x2D,0x1C,0x57,0xC2,0x69,0xA2,0x3F,0xF9,0x6D,0xD3,0x0B, }; + +/* X509v3 Subject Alternative Name: + DNS:10.0.0.1 */ +const uint8_t _ipAddress_dnsField[] = { + 0x30,0x82,0x04,0x4D,0x30,0x82,0x03,0x35,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xD6,0xAF,0xD0,0x9F,0x40,0x03,0x75,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x9E,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x0C,0x29,0x53, + 0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A, + 0x20,0x49,0x50,0x20,0x61,0x64,0x64,0x72,0x65,0x73,0x73,0x20,0x69,0x6E,0x20,0x44, + 0x4E,0x53,0x20,0x66,0x69,0x65,0x6C,0x64,0x30,0x1E,0x17,0x0D,0x31,0x39,0x31,0x31, + 0x30,0x38,0x30,0x30,0x30,0x32,0x30,0x39,0x5A,0x17,0x0D,0x32,0x30,0x31,0x31,0x30, + 0x37,0x30,0x30,0x30,0x32,0x30,0x39,0x5A,0x30,0x81,0x9E,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30, + 0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E, + 0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x0C,0x29, + 0x53,0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73, + 0x3A,0x20,0x49,0x50,0x20,0x61,0x64,0x64,0x72,0x65,0x73,0x73,0x20,0x69,0x6E,0x20, + 0x44,0x4E,0x53,0x20,0x66,0x69,0x65,0x6C,0x64,0x30,0x82,0x01,0x22,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F, + 0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xCD,0x1E,0x25,0xBC,0xE6,0xAA, + 0x54,0x69,0x1C,0xA2,0x0F,0x2F,0x25,0xA5,0xFB,0xB3,0x05,0xAB,0x88,0x6A,0x8E,0x0C, + 0x00,0xC7,0x5C,0x1A,0x3C,0x2A,0xBA,0xCE,0xEA,0x0B,0xEC,0x20,0xA4,0xC1,0xEB,0x80, + 0xDB,0x04,0xE5,0x17,0xFA,0x9C,0x6A,0x3C,0xE1,0xB5,0x29,0x74,0x43,0x49,0x6C,0xAB, + 0x11,0x10,0xB9,0xF3,0xB4,0x8C,0x62,0xA0,0x26,0x9B,0x54,0xDA,0x5F,0x6C,0x09,0x95, + 0xFB,0xE3,0xBA,0x3E,0xB4,0x68,0x28,0x19,0x36,0xB4,0x7C,0x13,0x48,0xE8,0x68,0xA5, + 0x15,0x3B,0xBD,0x57,0xD7,0x21,0x2C,0xC1,0x26,0x82,0xC1,0x66,0x96,0x71,0xF8,0x72, + 0xBD,0xB5,0x8A,0x93,0x9A,0xF2,0x26,0xC8,0xEE,0x15,0x1F,0xBF,0x82,0x5D,0x14,0x52, + 0x69,0x12,0x14,0x2A,0x6F,0x0E,0x2C,0xEE,0x67,0x6A,0xEB,0xC0,0xF9,0x38,0x27,0xD1, + 0x4E,0xF3,0x94,0x2E,0x0B,0x93,0xB9,0x0F,0x81,0xA0,0x1E,0x6E,0x0D,0x6E,0x35,0x82, + 0x96,0x1F,0x1A,0x76,0xEA,0x5C,0x89,0x09,0xFE,0x6F,0x8B,0x56,0x82,0xB6,0x02,0x5A, + 0x38,0x31,0x87,0x15,0xE0,0x55,0xFF,0xE9,0xF4,0x39,0xF7,0xFA,0xC0,0xE5,0xA2,0x1B, + 0x2A,0xAF,0x53,0xF0,0x4F,0xB8,0xE8,0xA6,0x01,0xF9,0x84,0xFE,0x6F,0xAE,0xFF,0xFD, + 0x65,0x7C,0x7A,0xFF,0xC4,0xB4,0xA5,0x69,0xD0,0x6F,0xDF,0x19,0xC6,0xEC,0x42,0x1C, + 0x2D,0x5D,0xCC,0x71,0x3E,0x02,0xE3,0x5A,0xCA,0xDB,0x62,0x06,0x19,0xBE,0xCB,0x1E, + 0xDD,0x27,0x7D,0x00,0x8F,0x31,0x73,0x43,0x27,0x0A,0x5B,0x5C,0x9B,0xDF,0x20,0x5F, + 0xF1,0x76,0x31,0xAB,0x34,0xA9,0x20,0x1A,0xCB,0xE7,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x81,0x8B,0x30,0x81,0x88,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, + 0x02,0x07,0x80,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x13,0x06,0x03,0x55,0x1D,0x11,0x04, + 0x0C,0x30,0x0A,0x82,0x08,0x31,0x30,0x2E,0x30,0x2E,0x30,0x2E,0x31,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x83,0xE0,0x4A,0x14,0xAD,0x61,0x5B,0xD2, + 0x79,0xA2,0x5E,0x9C,0x45,0xAC,0xD8,0x35,0x8B,0xF4,0x43,0x09,0x30,0x1F,0x06,0x03, + 0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x83,0xE0,0x4A,0x14,0xAD,0x61,0x5B, + 0xD2,0x79,0xA2,0x5E,0x9C,0x45,0xAC,0xD8,0x35,0x8B,0xF4,0x43,0x09,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01, + 0x00,0x45,0x79,0xD6,0x5F,0x71,0x88,0x20,0x8C,0x6D,0x5C,0x89,0x7D,0xD8,0x6E,0x48, + 0x21,0x8B,0xA7,0x14,0xD3,0xC5,0xA7,0xE1,0xFE,0xB4,0x9A,0x6A,0x72,0xD5,0x40,0xFF, + 0xBE,0x02,0x49,0x89,0x13,0x4D,0xAE,0xCD,0x9E,0x27,0xA2,0x0E,0xD1,0xBA,0xA5,0xB9, + 0x08,0x30,0xEB,0x8E,0xE9,0xCF,0xD5,0x80,0xA0,0x0A,0x0D,0x38,0x71,0x2B,0x31,0x02, + 0x14,0x42,0x98,0x41,0x3F,0x26,0x32,0x8D,0x1B,0x56,0xAB,0x9F,0x3D,0x94,0xFD,0xBB, + 0xD2,0xF7,0x2E,0xE2,0xA9,0xD3,0xFF,0x0C,0xDA,0x8D,0x8B,0x56,0x55,0x80,0x9A,0xF3, + 0xA2,0x44,0xB8,0x23,0xD5,0x03,0x27,0x11,0xC9,0x03,0x64,0xE9,0x24,0xAA,0x60,0x4A, + 0x93,0x04,0xF8,0xEA,0x66,0x9C,0x7A,0xE9,0x99,0x7E,0xA2,0x22,0x72,0x37,0xA7,0xCC, + 0xD5,0x0A,0xFA,0xC2,0xEA,0x25,0x0A,0xD0,0x7A,0xAD,0x60,0xD6,0x81,0xA3,0x80,0xD6, + 0xE6,0xB2,0xA9,0x6E,0x88,0xC2,0x58,0xD0,0xC7,0x0B,0xBD,0xD8,0xF6,0xD0,0x51,0x08, + 0x00,0x93,0x07,0x35,0x35,0x29,0x7B,0xA7,0x59,0x4E,0xD8,0x17,0x15,0x50,0xE6,0xEA, + 0xA2,0xB6,0x94,0x78,0xE9,0x76,0x3A,0xFF,0xB0,0xD5,0x9E,0xE8,0xBE,0xD5,0xD8,0x3F, + 0xA1,0xA0,0xC6,0x79,0x54,0x4A,0x1A,0xE0,0xAA,0xFE,0x51,0x82,0x3B,0x75,0xC8,0x03, + 0xD9,0x02,0x98,0xE9,0x30,0x79,0x58,0x93,0xD1,0x27,0x1F,0x11,0x58,0x49,0x33,0x82, + 0xE5,0x09,0x6F,0xE2,0xD0,0xA2,0x9D,0x29,0x49,0x85,0xAF,0x5E,0xB2,0xE7,0x9C,0x56, + 0x4E,0x73,0x5E,0x85,0x64,0x58,0x7D,0xE6,0xB4,0x07,0x8B,0x7B,0x12,0x80,0x6F,0x7A, + 0x3C, +}; + +/* X509v3 Subject Alternative Name: + IP Address:10.0.0.1 */ +const uint8_t _ipAddress_SAN[] = { + 0x30,0x82,0x04,0x37,0x30,0x82,0x03,0x1F,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xC7,0x90,0xC5,0x69,0xCA,0xE3,0xB4,0x07,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27,0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53, + 0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A, + 0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72,0x65,0x73,0x73,0x20,0x53,0x41,0x4E,0x30, + 0x1E,0x17,0x0D,0x31,0x39,0x31,0x31,0x30,0x38,0x30,0x30,0x31,0x34,0x32,0x31,0x5A, + 0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x37,0x30,0x30,0x31,0x34,0x32,0x31,0x5A,0x30, + 0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53,0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63, + 0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A,0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72, + 0x65,0x73,0x73,0x20,0x53,0x41,0x4E,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30, + 0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC1,0x80,0xDE,0x51,0x33,0xB8,0x28,0xA8, + 0x7D,0x94,0x12,0x73,0x6F,0x0E,0xFC,0xF5,0xF0,0xC6,0x18,0xD2,0x87,0xB8,0x37,0xEE, + 0xF9,0xB1,0x69,0x1D,0xF9,0xE1,0x65,0x8D,0x47,0x34,0x50,0xBD,0x72,0x41,0x32,0x7A, + 0x02,0x0F,0x72,0x85,0xB8,0xE1,0x3D,0x7C,0x78,0x90,0x0A,0x81,0x06,0x25,0x9B,0x13, + 0xCA,0xD6,0xAA,0x77,0xDC,0x4A,0x9B,0x32,0xB7,0x1D,0xF1,0xEF,0x52,0x33,0xE3,0x5D, + 0x80,0xE0,0xE1,0xBB,0xF2,0x5E,0x91,0x55,0xA1,0xF8,0xE4,0x25,0x62,0xAB,0xBA,0x3D, + 0x42,0xEB,0x9B,0xD7,0x95,0x92,0x18,0x26,0x5F,0xB1,0x28,0x9B,0x01,0xDB,0x52,0x18, + 0xFE,0xF4,0x4F,0xD6,0x3A,0x49,0x13,0xE2,0xB0,0x06,0xEF,0x28,0x6C,0x89,0xFD,0x23, + 0x19,0x56,0xF7,0x1A,0x51,0x89,0x5C,0x13,0xDD,0xD6,0x55,0x70,0x17,0xCA,0x05,0x59, + 0x77,0xEA,0x75,0xA4,0x44,0x05,0x49,0xD3,0xD6,0xE4,0x04,0x74,0xC8,0x5F,0xF9,0x19, + 0x75,0x27,0xB2,0x17,0x6B,0x2E,0x45,0xE5,0x07,0xBD,0x17,0x70,0xFD,0xA2,0x6A,0xF7, + 0xF1,0xD8,0x43,0xBC,0xF6,0xCD,0xD1,0x2D,0xE0,0xF0,0x55,0xE7,0x60,0xA5,0x09,0x42, + 0xE6,0x67,0xB6,0x40,0x56,0x4E,0x3E,0xDF,0x7B,0x89,0x44,0x36,0x78,0x83,0x30,0x25, + 0x12,0xFF,0x48,0x97,0xC1,0x04,0x87,0xC7,0xA3,0x06,0xCE,0x06,0xCE,0x2F,0xAE,0x01, + 0x42,0x57,0x62,0x3B,0xDA,0xEB,0xD8,0xDB,0x96,0x5E,0xFC,0x1E,0x30,0x4B,0xE4,0x80, + 0xE1,0xD9,0x34,0x03,0x9C,0xD4,0x92,0x39,0x17,0xA8,0xCD,0xCA,0x96,0x54,0xEB,0x2D, + 0x12,0x77,0xE3,0x96,0x09,0x6D,0xBB,0x93,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x87, + 0x30,0x81,0x84,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x0F,0x06,0x03,0x55,0x1D,0x11,0x04,0x08,0x30, + 0x06,0x87,0x04,0x0A,0x00,0x00,0x01,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0xE0,0xA6,0x7D,0x62,0x28,0x6C,0xC0,0xCE,0x46,0xC8,0x04,0xB0,0xBA,0xB9, + 0x9B,0xF6,0x4A,0x60,0xBF,0xA9,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, + 0x16,0x80,0x14,0xE0,0xA6,0x7D,0x62,0x28,0x6C,0xC0,0xCE,0x46,0xC8,0x04,0xB0,0xBA, + 0xB9,0x9B,0xF6,0x4A,0x60,0xBF,0xA9,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x55,0xBB,0x48,0x72,0x61, + 0x8F,0xAF,0x7F,0x18,0x2F,0x31,0xF9,0xAA,0xFF,0x4A,0xC1,0x5B,0xBF,0x45,0xFE,0x82, + 0x3C,0xBE,0xFC,0xBB,0x58,0xA7,0x4A,0xF3,0x84,0xF8,0x10,0xB4,0x51,0x33,0x91,0xA0, + 0x58,0x1C,0x5F,0x67,0x91,0x31,0xD8,0xEC,0xA0,0x6A,0x85,0x84,0x71,0xBE,0xB5,0x18, + 0xAC,0xB8,0x7E,0xC3,0xFC,0x1C,0x74,0x84,0x48,0x2C,0x99,0xE9,0x52,0xBB,0x36,0x00, + 0x35,0x8C,0x50,0xC8,0x13,0x2A,0xFA,0x1E,0xF8,0x15,0x72,0xEF,0xF0,0x20,0x28,0xA0, + 0xCD,0xC7,0x85,0xEF,0x48,0x8C,0x27,0xF9,0x0E,0x15,0x9F,0xB8,0x54,0xD1,0x44,0x08, + 0x31,0xB0,0xC8,0x24,0x53,0x4A,0x63,0x97,0xB5,0xB3,0x83,0x07,0xCD,0x6D,0xC5,0x10, + 0xDD,0xC0,0x90,0xA2,0xFF,0x8E,0xD5,0x2F,0xC4,0xBC,0x8A,0xE0,0x90,0xAA,0x79,0x09, + 0xB5,0x23,0x72,0x6A,0xFB,0x9B,0xE5,0x0E,0xD9,0x30,0x41,0x70,0xF1,0x17,0x9C,0x5F, + 0xD7,0x0A,0x10,0x8E,0x77,0xD9,0x2F,0x59,0xE4,0xB4,0xF6,0x8D,0x16,0x90,0x84,0xBB, + 0xB6,0xAF,0xEE,0x86,0x4D,0x21,0xAE,0x3E,0x7B,0x2F,0xAD,0xBD,0xC4,0x38,0x9C,0x9E, + 0xB5,0x7C,0x8D,0x36,0x72,0x2C,0x78,0xC7,0xD4,0x54,0xD9,0x93,0x18,0xC8,0x00,0x5E, + 0xFE,0x12,0xE4,0x50,0x90,0x88,0xFB,0x82,0xFE,0x94,0xA5,0x4C,0xEB,0x7F,0xB7,0x39, + 0x99,0x24,0x0B,0x23,0xF9,0xB4,0x92,0xA8,0x6F,0xA6,0x46,0xBB,0xFB,0xDA,0xCD,0x8F, + 0xB9,0x14,0xE8,0x9B,0xBB,0x1B,0x80,0x9E,0x9D,0x9A,0x16,0xFF,0xF1,0x55,0xFF,0xDF, + 0x3E,0x32,0x73,0x16,0x9D,0xEA,0xF0,0xB1,0x5A,0x12,0xAB, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=10.0.0.1 */ +const uint8_t _ipAddress_CN[] = { + 0x30,0x82,0x03,0xF2,0x30,0x82,0x02,0xDA,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xD8,0xED,0xBE,0x22,0x56,0xD4,0x12,0x16,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x7D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06, + 0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53, + 0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72, + 0x69,0x6E,0x67,0x31,0x11,0x30,0x0F,0x06,0x03,0x55,0x04,0x03,0x0C,0x08,0x31,0x30, + 0x2E,0x30,0x2E,0x30,0x2E,0x31,0x30,0x1E,0x17,0x0D,0x31,0x39,0x31,0x31,0x30,0x38, + 0x30,0x31,0x32,0x32,0x32,0x32,0x5A,0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x37,0x30, + 0x31,0x32,0x32,0x32,0x32,0x5A,0x30,0x7D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A, + 0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03, + 0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65, + 0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69, + 0x6E,0x67,0x31,0x11,0x30,0x0F,0x06,0x03,0x55,0x04,0x03,0x0C,0x08,0x31,0x30,0x2E, + 0x30,0x2E,0x30,0x2E,0x31,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, + 0x0A,0x02,0x82,0x01,0x01,0x00,0xF3,0x54,0x35,0x8B,0xF0,0x54,0x65,0xA4,0x26,0x6D, + 0xFE,0x08,0x28,0x12,0x36,0x03,0x05,0xD7,0x23,0x92,0x7A,0xEB,0x61,0x9D,0xEE,0x67, + 0x5E,0x48,0x86,0x1F,0x2F,0x66,0x6B,0x71,0x56,0xC3,0xA0,0x20,0x13,0x76,0xEC,0x6A, + 0x53,0x59,0xAE,0xD3,0x61,0x1E,0xE7,0xEC,0x15,0xBD,0xB7,0x46,0x6C,0x8D,0x65,0x1F, + 0xAA,0x1C,0x7C,0x9A,0xB6,0xFD,0xEF,0x94,0x63,0xDC,0x12,0x0A,0x65,0x86,0x6D,0x1B, + 0xAC,0xD7,0xD0,0x47,0x92,0x10,0x9E,0x21,0x50,0xD5,0x2D,0x2F,0xA3,0xB8,0x1F,0xA3, + 0xB4,0xB6,0xA9,0x5C,0xED,0x3B,0x49,0xB7,0x3B,0xEA,0x02,0x9F,0xFB,0xE3,0x1C,0x6A, + 0xBB,0xE4,0x10,0x64,0x77,0xF9,0x8A,0x7B,0x4D,0x3E,0xC7,0xFF,0xE4,0x41,0x10,0xDE, + 0xB5,0xDD,0xB9,0xFA,0x02,0x3B,0xBA,0x10,0x83,0x0C,0x82,0x5C,0x6D,0xEF,0x64,0xEC, + 0xA8,0x12,0xAA,0x0B,0xC9,0x48,0x43,0xD0,0x6F,0x06,0x6E,0x8F,0xB6,0x87,0xBC,0x57, + 0x01,0xB7,0xD0,0x2F,0xC7,0x6F,0xAC,0x95,0xDA,0xE0,0xD7,0x64,0x9B,0xD5,0xE0,0xFD, + 0x62,0xF8,0xD1,0x46,0x20,0xD8,0x67,0x45,0xD3,0xC0,0x48,0x54,0xFD,0x0E,0x0D,0xBE, + 0x05,0xAB,0x81,0x23,0x25,0x90,0x51,0xB8,0x4D,0xA8,0x97,0xDE,0x2F,0xD3,0x7B,0x1B, + 0x24,0xEF,0x83,0x0B,0xC1,0x25,0x9C,0x7D,0x6E,0x47,0x1D,0x3A,0xE0,0x4D,0x64,0x03, + 0x11,0x79,0x15,0xB4,0xB2,0x88,0x29,0x37,0x02,0x71,0xF4,0x3A,0x73,0xB2,0x03,0x4F, + 0xD6,0x5B,0xEB,0x2E,0xB5,0xF6,0x1B,0x0E,0x14,0xD5,0x89,0x79,0xBC,0x38,0xA2,0xF1, + 0x9F,0x26,0xB5,0xC1,0x26,0xC7,0x02,0x03,0x01,0x00,0x01,0xA3,0x75,0x30,0x73,0x30, + 0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x13,0x06, + 0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x03,0x01,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x40,0x73,0xD8, + 0x0F,0xE3,0xF0,0x6B,0x0A,0x00,0x5B,0x94,0x31,0x23,0x56,0xC1,0xC2,0x12,0xF6,0xA8, + 0x33,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x40,0x73, + 0xD8,0x0F,0xE3,0xF0,0x6B,0x0A,0x00,0x5B,0x94,0x31,0x23,0x56,0xC1,0xC2,0x12,0xF6, + 0xA8,0x33,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x03,0x82,0x01,0x01,0x00,0xBA,0x76,0xA7,0x28,0x46,0xFD,0x2A,0x5A,0x96,0x51, + 0xEC,0xC7,0x5A,0x6A,0x98,0x76,0x7C,0x41,0x2B,0xE0,0xF5,0xD6,0x85,0x59,0x5F,0xCA, + 0x5F,0x10,0xC0,0xE9,0x23,0x58,0x89,0xCB,0x89,0xCD,0x8F,0xB7,0x37,0xA0,0x47,0x28, + 0x70,0x3A,0x17,0x0A,0x87,0x87,0x10,0x61,0xB1,0xBD,0x57,0x32,0x1F,0x03,0xD6,0x14, + 0x5D,0x53,0xB0,0xBA,0x91,0x2E,0x86,0x62,0xB9,0xB7,0xC8,0xFF,0x5A,0xC7,0xF9,0xA3, + 0x6D,0x9F,0x12,0x1B,0x9C,0x7B,0xB6,0x0B,0x9D,0x12,0xE6,0x1A,0x2A,0xD3,0x9C,0x2E, + 0x1C,0x75,0x0C,0xC3,0xAC,0xD6,0x4F,0x41,0x31,0xDB,0x2D,0x62,0x39,0xE7,0xB6,0x2B, + 0xFC,0xA8,0x21,0x15,0xEF,0xD3,0x8A,0xB8,0x1E,0xD9,0x5C,0xB6,0x04,0xE0,0xCB,0x0F, + 0x0C,0xC1,0xE5,0x91,0xAB,0x3A,0x30,0xBA,0xD5,0x0A,0xE0,0x88,0x2B,0x97,0x7C,0x79, + 0x50,0xBC,0x8F,0xB5,0x3D,0xA2,0x70,0xC8,0xB4,0x30,0xC4,0xDE,0x12,0x25,0x14,0xAA, + 0x82,0xAB,0x36,0x9A,0x24,0xA5,0x16,0xE0,0xB2,0x47,0xA6,0x5E,0x7E,0xD0,0xDA,0x95, + 0xA2,0xEF,0x46,0x6B,0xEB,0xD3,0x30,0xD8,0xC1,0xEC,0x92,0x21,0xD0,0x54,0x8D,0x12, + 0xD1,0x27,0x5F,0xA6,0x3D,0x9F,0x92,0x3A,0x81,0x66,0xB4,0xF0,0x54,0xD0,0xED,0xC7, + 0xC1,0x88,0x68,0xC3,0xD8,0x63,0xD0,0x3C,0x11,0x46,0x31,0x70,0xC1,0x88,0xC1,0x37, + 0x7C,0x84,0x7E,0xCA,0xF9,0x6F,0x97,0x47,0x1D,0x4C,0x09,0x1C,0x36,0xF9,0x89,0x11, + 0x1D,0x89,0x48,0xB0,0x23,0x2F,0x58,0xE6,0x8F,0xB7,0xED,0x69,0xF2,0xAD,0x45,0xD7, + 0x03,0x4E,0xAB,0xB6,0x81,0x0C, +}; + +/* subjectAltName=DER:30:07:87:05:0a:00:00:00:01 + * (IP address with 5 bytes) */ +const uint8_t _ipAddress_bad[] = { + 0x30,0x82,0x04,0x38,0x30,0x82,0x03,0x20,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xD5,0x17,0xAC,0x1D,0x94,0x23,0xB1,0x70,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27,0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53, + 0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A, + 0x20,0x42,0x61,0x64,0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72,0x65,0x73,0x73,0x30, + 0x1E,0x17,0x0D,0x31,0x39,0x31,0x31,0x30,0x38,0x30,0x32,0x35,0x34,0x32,0x33,0x5A, + 0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x37,0x30,0x32,0x35,0x34,0x32,0x33,0x5A,0x30, + 0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53,0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63, + 0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A,0x20,0x42,0x61,0x64,0x20,0x49,0x50,0x20, + 0x41,0x64,0x64,0x72,0x65,0x73,0x73,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30, + 0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xBB,0x94,0xF8,0x59,0x6D,0x04,0x9E,0x53, + 0x0C,0xC2,0x96,0x89,0x7A,0xE8,0x66,0x9B,0x1D,0x1A,0x5A,0x12,0x86,0x61,0xAB,0x5D, + 0x00,0xC9,0x40,0x2D,0x1F,0x4C,0x5F,0x76,0xFF,0xD4,0xBE,0xD0,0x08,0xD6,0x0C,0x1C, + 0xE5,0xC6,0xE3,0xA5,0xDC,0x65,0x2A,0x53,0xAB,0xC9,0x64,0x27,0x0C,0xAF,0x56,0x00, + 0x93,0x53,0x99,0x16,0x59,0x29,0xD8,0x7A,0x89,0x0B,0x11,0xCD,0x47,0xFD,0xD3,0xBD, + 0xF0,0x8A,0x4E,0x97,0xFA,0xA1,0x0F,0xCD,0xBA,0xD3,0x18,0x29,0x44,0xBD,0x27,0x59, + 0x3C,0xF6,0x43,0x30,0xB8,0xB2,0x0F,0xE4,0xE5,0x2A,0x77,0x6A,0xC1,0x35,0x96,0x2E, + 0x9A,0x0D,0x75,0x23,0x09,0xDF,0x37,0x30,0x76,0xAC,0xF2,0x30,0x5E,0x38,0xC9,0x96, + 0x53,0x6B,0x78,0xB7,0xCF,0x23,0x34,0xA4,0x79,0xEC,0xFD,0x23,0x93,0xB2,0x92,0x24, + 0x7E,0x84,0xB4,0x09,0x84,0x4F,0xD6,0x99,0x06,0x60,0x52,0xE7,0x3C,0x13,0x27,0x72, + 0x34,0x5F,0x8D,0xE3,0x0E,0x81,0xCF,0x6E,0x66,0x79,0xBA,0xA2,0x2B,0x62,0xE1,0xBF, + 0x5D,0xFA,0x66,0x47,0x26,0x7A,0x2A,0xAC,0x89,0x2D,0x44,0x35,0x40,0x60,0xA5,0x92, + 0xA0,0xF5,0x8C,0x86,0xF1,0x04,0x55,0xAB,0xF1,0x1E,0xEA,0x42,0x26,0x0D,0x5D,0x80, + 0x20,0x8F,0xF7,0x2A,0xF8,0x73,0x6F,0x7B,0xED,0xBA,0x9B,0xFB,0xB4,0x57,0x13,0xC2, + 0xB5,0x11,0x8B,0x29,0x37,0x52,0xCD,0x86,0x47,0xE0,0x80,0xB4,0x7B,0xF8,0x92,0xA4, + 0xCC,0x52,0x29,0x52,0xB1,0xC9,0x5A,0x12,0xE4,0x70,0xFB,0xB2,0x29,0xAF,0xC5,0x8A, + 0x00,0xDF,0xD1,0xEC,0x16,0xDE,0x41,0x4D,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x88, + 0x30,0x81,0x85,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x10,0x06,0x03,0x55,0x1D,0x11,0x04,0x09,0x30, + 0x07,0x87,0x05,0x0A,0x00,0x00,0x00,0x01,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, + 0x16,0x04,0x14,0x5B,0xE9,0x2F,0x45,0xBA,0x5B,0x72,0x64,0x55,0x96,0x5B,0xB9,0x29, + 0x94,0x08,0xB9,0x4E,0x79,0x8C,0x28,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18, + 0x30,0x16,0x80,0x14,0x5B,0xE9,0x2F,0x45,0xBA,0x5B,0x72,0x64,0x55,0x96,0x5B,0xB9, + 0x29,0x94,0x08,0xB9,0x4E,0x79,0x8C,0x28,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xB5,0xA9,0xF0,0x60, + 0xC1,0xD6,0xC5,0x35,0xA2,0x01,0x7B,0xBD,0x0F,0x3D,0x19,0xFE,0xED,0x51,0xCA,0x2B, + 0xCE,0x3C,0xB2,0x0B,0xFF,0x33,0xD2,0x72,0x74,0x93,0xD1,0x93,0xB6,0xA3,0xCF,0x61, + 0x4B,0x18,0xA5,0x07,0x71,0xCF,0x9D,0xA9,0xDC,0x20,0xA5,0xD2,0x71,0x77,0x4A,0xAC, + 0x66,0x08,0x3D,0x6C,0x0E,0x6F,0x4E,0xFE,0x85,0x4F,0xF1,0xE2,0xFD,0x44,0x06,0xA2, + 0xA0,0x02,0xCA,0x33,0x09,0x40,0xBA,0xCE,0xD6,0xAB,0xBA,0x07,0x79,0x20,0x81,0x7A, + 0x12,0x89,0x19,0x82,0x5C,0xFB,0xDC,0x3F,0x8C,0x72,0x31,0x2D,0x08,0x1A,0x19,0x2F, + 0xF2,0x13,0x89,0x7A,0xF3,0xCD,0x93,0x29,0x1C,0x76,0xBF,0x7A,0xE1,0x94,0xE9,0xBF, + 0xF0,0xC7,0x8A,0x63,0xA9,0x90,0x0F,0xDA,0x2C,0x6B,0x49,0x14,0x8D,0xCC,0x30,0x40, + 0xEC,0xD3,0x6B,0x07,0x12,0x0E,0x63,0x21,0x79,0xD3,0x52,0x23,0xA9,0x2F,0xA9,0xA6, + 0x72,0x60,0x83,0x2F,0xED,0xB9,0xFC,0x77,0x2B,0xD8,0xAD,0x3C,0x6F,0x9B,0x67,0x48, + 0x69,0x35,0x26,0xF0,0xEA,0x9D,0x29,0xD6,0x96,0x68,0x53,0xA9,0xB7,0x87,0x5E,0xFE, + 0xCA,0x0D,0xAA,0x17,0x4C,0x8E,0x7C,0xEA,0x50,0x9E,0xB5,0xE2,0x92,0xC4,0x4B,0x8E, + 0x93,0x26,0x0F,0x65,0xCF,0x3A,0x65,0xB8,0x39,0x73,0xD7,0x6C,0x49,0x8C,0x94,0xD5, + 0x80,0x1F,0xE2,0xAD,0x16,0xF7,0xE9,0xCB,0xED,0x61,0xEB,0xD5,0xA2,0x69,0x3E,0xDD, + 0x17,0xF6,0x52,0x8A,0x33,0x7C,0x8A,0xDD,0x51,0x3F,0x15,0x09,0x96,0x0B,0x6C,0x79, + 0xC1,0xF3,0x86,0x30,0xB9,0xDB,0x5A,0x70,0x6B,0xE8,0x23,0xF2, +}; + #endif /* _TRUSTTESTS_EVALUATION_SSL_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.h b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.h index 14836b9f..9aa3fc2d 100644 --- a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.h +++ b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.h @@ -39,9 +39,10 @@ NS_ASSUME_NONNULL_BEGIN - (void)removeTestRootAsSystem; // ported from regressionBase -- (void)runCertificateTestForDirectory:(SecPolicyRef)policy subDirectory:(NSString *)resourceSubDirectory verifyDate:(NSDate*)date; +- (void)runCertificateTestForDirectory:(SecPolicyRef)policy subDirectory:(NSString *)resourceSubDirectory verifyDate:(NSDate* _Nullable)date; - (id _Nullable) CF_RETURNS_RETAINED SecCertificateCreateFromResource:(NSString * )name subdirectory:(NSString *)dir; +- (id _Nullable) CF_RETURNS_RETAINED SecCertificateCreateFromPEMResource:(NSString *)name subdirectory:(NSString *)dir; @end /* Use this interface to get a SecCertificateRef that has the same CFTypeID @@ -50,6 +51,14 @@ CF_RETURNS_RETAINED _Nullable SecCertificateRef SecFrameworkCertificateCreate(const uint8_t * der_bytes, CFIndex der_length); CF_RETURNS_RETAINED _Nullable SecCertificateRef SecFrameworkCertificateCreateFromTestCert(SecCertificateRef cert); +CF_RETURNS_RETAINED +SecPolicyRef SecFrameworkPolicyCreateSSL(Boolean server, CFStringRef __nullable hostname); +CF_RETURNS_RETAINED +SecPolicyRef SecFrameworkPolicyCreateBasicX509(void); +CF_RETURNS_RETAINED +SecPolicyRef SecFrameworkPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef __nullable email); +CF_RETURNS_RETAINED +SecPolicyRef SecFrameworkPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, CFStringRef teamIdentifier); NS_ASSUME_NONNULL_END diff --git a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m index 76dfe001..082de34f 100644 --- a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m +++ b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m @@ -23,9 +23,11 @@ */ #import #include "trust/trustd/trustd_spi.h" +#include "trust/trustd/SecRevocationDb.h" #include #include #include +#include #include #include #include "OSX/utilities/SecCFWrappers.h" @@ -44,47 +46,14 @@ @implementation TrustEvaluationTestCase -static int current_dir = -1; -static char *home_var = NULL; - /* Build in trustd functionality to the tests */ + (void) setUp { - /* Set up TMP directory for trustd's files */ - int ok = 0; - NSError* error = nil; - NSString* pid = [NSString stringWithFormat: @"tst-%d", [[NSProcessInfo processInfo] processIdentifier]]; - NSURL* tmpDirURL = [[NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES] URLByAppendingPathComponent:pid]; - ok = (bool)tmpDirURL; + /* Use the production Valid DB by default (so we'll have data to test against) */ + CFPreferencesSetAppValue(CFSTR("ValidUpdateServer"), kValidUpdateProdServer, kSecurityPreferencesDomain); + CFPreferencesAppSynchronize(kSecurityPreferencesDomain); - if (current_dir == -1 && home_var == NULL) { - ok = ok && [[NSFileManager defaultManager] createDirectoryAtURL:tmpDirURL - withIntermediateDirectories:NO - attributes:NULL - error:&error]; - - NSURL* libraryURL = [tmpDirURL URLByAppendingPathComponent:@"Library"]; - NSURL* preferencesURL = [tmpDirURL URLByAppendingPathComponent:@"Preferences"]; - - ok = (ok && (current_dir = open(".", O_RDONLY) >= 0) - && (chdir([tmpDirURL fileSystemRepresentation]) >= 0) - && (setenv("HOME", [tmpDirURL fileSystemRepresentation], 1) >= 0) - && (bool)(home_var = getenv("HOME"))); - - ok = ok && [[NSFileManager defaultManager] createDirectoryAtURL:libraryURL - withIntermediateDirectories:NO - attributes:NULL - error:&error]; - - ok = ok && [[NSFileManager defaultManager] createDirectoryAtURL:preferencesURL - withIntermediateDirectories:NO - attributes:NULL - error:&error]; - } - - if (ok > 0) { - /* Be trustd */ - trustd_init((__bridge CFURLRef) tmpDirURL); - } + NSURL *tmpDirURL = setUpTmpDir(); + trustd_init((__bridge CFURLRef) tmpDirURL); } - (id)addTrustSettingsForCert:(SecCertificateRef)cert trustSettings:(id)trustSettings @@ -176,8 +145,29 @@ const CFStringRef kTestSystemRootKey = CFSTR("TestSystemRoot"); { NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:name withExtension:@".cer" subdirectory:dir]; + if (!url) { + url = [[NSBundle bundleForClass:[self class]] URLForResource:name withExtension:@".crt" + subdirectory:dir]; + } NSData *certData = [NSData dataWithContentsOfURL:url]; - SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData); + if (!certData) { + return nil; + } + SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certData); + return (__bridge id)cert; +} + +- (id _Nullable) CF_RETURNS_RETAINED SecCertificateCreateFromPEMResource:(NSString *)name + subdirectory:(NSString *)dir +{ + NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:name withExtension:@".pem" + subdirectory:dir]; + NSData *certData = [NSData dataWithContentsOfURL:url]; + if (!certData) { + return nil; + } + + SecCertificateRef cert = SecCertificateCreateWithPEM(kCFAllocatorDefault, (__bridge CFDataRef)certData); return (__bridge id)cert; } @@ -244,8 +234,10 @@ const CFStringRef kTestSystemRootKey = CFSTR("TestSystemRoot"); ok_status(err, "SecTrustCreateWithCertificates"); goto exit; } - if ([anchors count]) + if ([anchors count]) { SecTrustSetAnchorCertificates(trustRef, (CFArrayRef)anchors); + SecTrustSetAnchorCertificatesOnly(trustRef, false); + } SecTrustSetVerifyDate(trustRef, (__bridge CFDateRef)date); @@ -313,11 +305,13 @@ exit: @end -typedef SecCertificateRef (*create_f)(CFAllocatorRef allocator, +/* MARK: Framework type conversion functions */ + +typedef SecCertificateRef (*cert_create_f)(CFAllocatorRef allocator, const UInt8 *der_bytes, CFIndex der_length); CF_RETURNS_RETAINED _Nullable SecCertificateRef SecFrameworkCertificateCreate(const uint8_t * _Nonnull der_bytes, CFIndex der_length) { - static create_f FrameworkCertCreateFunctionPtr = NULL; + static cert_create_f FrameworkCertCreateFunctionPtr = NULL; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -338,3 +332,83 @@ SecCertificateRef SecFrameworkCertificateCreate(const uint8_t * _Nonnull der_byt SecCertificateRef SecFrameworkCertificateCreateFromTestCert(SecCertificateRef cert) { return SecFrameworkCertificateCreate(SecCertificateGetBytePtr(cert), SecCertificateGetLength(cert)); } + +typedef SecPolicyRef (*ssl_policy_create_f)(Boolean server, CFStringRef hostname); +SecPolicyRef SecFrameworkPolicyCreateSSL(Boolean server, CFStringRef __nullable hostname) { + static ssl_policy_create_f FrameworkPolicyCreateFunctionPtr = NULL; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + void *framework = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY); + if (framework) { + FrameworkPolicyCreateFunctionPtr = dlsym(framework, "SecPolicyCreateSSL"); + } + }); + + if (FrameworkPolicyCreateFunctionPtr) { + return FrameworkPolicyCreateFunctionPtr(server, hostname); + } else { + NSLog(@"WARNING: not using Security framework policy"); + return SecPolicyCreateSSL(server, hostname); + } +} + +typedef SecPolicyRef (*basic_policy_create_f)(void); +SecPolicyRef SecFrameworkPolicyCreateBasicX509(void) { + static basic_policy_create_f FrameworkPolicyCreateFunctionPtr = NULL; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + void *framework = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY); + if (framework) { + FrameworkPolicyCreateFunctionPtr = dlsym(framework, "SecPolicyCreateBasicX509"); + } + }); + + if (FrameworkPolicyCreateFunctionPtr) { + return FrameworkPolicyCreateFunctionPtr(); + } else { + NSLog(@"WARNING: not using Security framework policy"); + return SecPolicyCreateBasicX509(); + } +} + +typedef SecPolicyRef (*smime_policy_create_f)(CFIndex smimeUsage, CFStringRef email); +SecPolicyRef SecFrameworkPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email) { + static smime_policy_create_f FrameworkPolicyCreateFunctionPtr = NULL; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + void *framework = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY); + if (framework) { + FrameworkPolicyCreateFunctionPtr = dlsym(framework, "SecPolicyCreateSMIME"); + } + }); + + if (FrameworkPolicyCreateFunctionPtr) { + return FrameworkPolicyCreateFunctionPtr(smimeUsage, email); + } else { + NSLog(@"WARNING: not using Security framework policy"); + return SecPolicyCreateSMIME(smimeUsage, email); + } +} + +typedef SecPolicyRef (*passbook_policy_create_f)(CFStringRef cardIssuer, CFStringRef teamIdentifier); +SecPolicyRef SecFrameworkPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, CFStringRef teamIdentifier) { + static passbook_policy_create_f FrameworkPolicyCreateFunctionPtr = NULL; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + void *framework = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY); + if (framework) { + FrameworkPolicyCreateFunctionPtr = dlsym(framework, "SecPolicyCreatePassbookCardSigner"); + } + }); + + if (FrameworkPolicyCreateFunctionPtr) { + return FrameworkPolicyCreateFunctionPtr(cardIssuer, teamIdentifier); + } else { + NSLog(@"WARNING: not using Security framework policy"); + return SecPolicyCreatePassbookCardSigner(cardIssuer, teamIdentifier); + } +} diff --git a/OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.m b/tests/TrustTests/EvaluationTests/TrustSettingsTests.m similarity index 74% rename from OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.m rename to tests/TrustTests/EvaluationTests/TrustSettingsTests.m index 3e24ded8..2646efe7 100644 --- a/OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.m +++ b/tests/TrustTests/EvaluationTests/TrustSettingsTests.m @@ -13,23 +13,25 @@ #include #include #include +#include #include #include #include -#if TARGET_OS_IPHONE -#include -#else +#if !TARGET_OS_IPHONE #include #endif -#include "shared_regressions.h" +#include "../TestMacroConversions.h" +#include "TrustSettingsTests_data.h" +#import "TrustEvaluationTestCase.h" -#include "si-28-sectrustsettings.h" +@interface TrustSettingsTests : TrustEvaluationTestCase +@end + +/* bridgeOS doesn't support trust settings */ +#if !TARGET_OS_BRIDGE -/* Of course, the interface is different for OS X and iOS. */ -/* each call is 1 test */ -#define kNumberSetTSTests 1 #if TARGET_OS_IPHONE #define setTS(cert, settings) \ { \ @@ -38,11 +40,14 @@ } #else /* Use admin store on OS X to avoid user prompts. + * Need a framework cert since we're interacting with keychain and trust settings. * Sleep a little so trustd has time to get the KeychainEvent. */ #define setTS(cert, settings) \ { \ - ok_status(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin, \ + SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \ + ok_status(SecTrustSettingsSetTrustSettings(frameworkCert, kSecTrustSettingsDomainAdmin, \ settings), "set trust settings"); \ + CFReleaseNull(frameworkCert); \ usleep(20000); \ } #endif @@ -56,13 +61,13 @@ #else #define setTSFail(cert, settings) \ { \ - is(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin, \ + SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \ + is(SecTrustSettingsSetTrustSettings(frameworkCert, kSecTrustSettingsDomainAdmin, \ settings), errSecParam, "set trust settings"); \ + CFReleaseNull(frameworkCert); \ } #endif -/* each call is 1 test */ -#define kNumberRemoveTSTests 1 #if TARGET_OS_IPHONE #define removeTS(cert) \ { \ @@ -72,13 +77,13 @@ #else #define removeTS(cert) \ { \ + SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \ ok_status(SecTrustSettingsRemoveTrustSettings(cert, kSecTrustSettingsDomainAdmin), \ "remove trust settings"); \ + CFReleaseNull(frameworkCert); \ } #endif -/* each call is 4 tests */ -#define kNumberCheckTrustTests 4 #define check_trust(certs, policy, valid_date, expected) \ { \ SecTrustRef trust = NULL; \ @@ -87,7 +92,8 @@ "create trust with " #policy " policy"); \ ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)valid_date), \ "set trust verify date"); \ - ok_status(SecTrustEvaluate(trust, &trust_result), "evaluate trust"); \ + (void)SecTrustEvaluateWithError(trust, nil); \ + ok_status(SecTrustGetTrustResult(trust, &trust_result), "get trust result"); \ is(trust_result, expected, \ "check trust result for " #policy " policy"); \ CFReleaseSafe(trust); \ @@ -106,14 +112,18 @@ static NSDate *verify_date = nil; #if TARGET_OS_IPHONE static SecTrustStoreRef defaultStore = NULL; +#define sslFrameworkPolicy sslPolicy #else #define kSystemLoginKeychainPath "/Library/Keychains/System.keychain" static NSMutableArray *deleteMeCertificates = NULL; +static SecPolicyRef sslFrameworkPolicy = NULL; #endif +@implementation TrustSettingsTests -static void setup_globals(void) { - ++ (void)setUp +{ + [super setUp]; cert0 = SecCertificateCreateWithBytes(NULL, _trustSettingsRoot, sizeof(_trustSettingsRoot)); cert1 = SecCertificateCreateWithBytes(NULL, _trustSettingsInt, sizeof(_trustSettingsInt)); cert2 = SecCertificateCreateWithBytes(NULL, _trustSettingsSSLLeaf, sizeof(_trustSettingsSSLLeaf)); @@ -134,53 +144,66 @@ static void setup_globals(void) { #if TARGET_OS_IPHONE defaultStore = SecTrustStoreForDomain(kSecTrustStoreDomainUser); #else + /* We need a framework version of the policies in order to set policies in the trust settings */ + sslFrameworkPolicy = SecFrameworkPolicyCreateSSL(true, CFSTR("testserver.apple.com")); + /* Since we're putting trust settings in the admin domain, - * we need to add the certs to the system keychain. */ + * we need to add the certs to the system keychain. + * Need a framework cert since we're interacting with keychain. */ SecKeychainRef kcRef = NULL; CFArrayRef certRef = NULL; NSDictionary *attrs = nil; + SecCertificateRef frameworkCert = NULL; SecKeychainOpen(kSystemLoginKeychainPath, &kcRef); if (!kcRef) { - goto out; + return; } deleteMeCertificates = [[NSMutableArray alloc] init]; - attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert0, + frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert0); + attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert, (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef, (__bridge NSString*)kSecReturnPersistentRef: @YES}; if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0) [deleteMeCertificates addObject:(__bridge NSArray *)certRef]; CFReleaseNull(certRef); + CFReleaseNull(frameworkCert); - attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert1, + frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert1); + attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert, (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef, (__bridge NSString*)kSecReturnPersistentRef: @YES}; if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0) [deleteMeCertificates addObject:(__bridge NSArray *)certRef]; CFReleaseNull(certRef); + CFReleaseNull(frameworkCert); - attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert2, + frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert2); + attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert, (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef, (__bridge NSString*)kSecReturnPersistentRef: @YES}; if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0) [deleteMeCertificates addObject:(__bridge NSArray *)certRef]; CFReleaseNull(certRef); + CFReleaseNull(frameworkCert); - attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert3, + frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert3); + attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert, (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef, (__bridge NSString*)kSecReturnPersistentRef: @YES}; if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0) [deleteMeCertificates addObject:(__bridge NSArray *)certRef]; CFReleaseNull(certRef); + CFReleaseNull(frameworkCert); - out: CFReleaseNull(kcRef); #endif } -static void cleanup_globals(void) { ++ (void)tearDown +{ #if !TARGET_OS_IPHONE [deleteMeCertificates enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { SecItemDelete((CFDictionaryRef)@{ (__bridge NSString*)kSecValuePersistentRef: [obj objectAtIndex:0]}); @@ -192,14 +215,16 @@ static void cleanup_globals(void) { CFReleaseNull(cert2); CFReleaseNull(cert3); CFReleaseNull(sslPolicy); + CFReleaseNull(sslFrameworkPolicy); CFReleaseNull(smimePolicy); CFReleaseNull(basicPolicy); CFReleaseNull(sslChain); CFReleaseNull(smimeChain); + [super tearDown]; } -#define kNumberNoConstraintsTests (17+7*4) -static void test_no_constraints(void) { +- (void)test_no_constraints +{ /* root with the default TrustRoot result succeeds */ setTS(cert0, NULL); check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed); @@ -247,10 +272,10 @@ static void test_no_constraints(void) { removeTS(cert2); } -#define kNumberPolicyConstraintsTests (2+3*4) -static void test_policy_constraints(void) { +- (void)test_policy_constraints +{ /* Trust only for SSL server. SSL server policy succeeds. */ - NSDictionary *sslServerAllowed = @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + NSDictionary *sslServerAllowed = @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) }; setTS(cert1, (__bridge CFDictionaryRef)sslServerAllowed); check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed); @@ -265,12 +290,12 @@ static void test_policy_constraints(void) { removeTS(cert1); } -#define kNumberPolicyStringConstraintsTests (4+6*4) -static void test_policy_string_constraints(void) { - NSArray *hostnameAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, +- (void)test_policy_string_constraints +{ + NSArray *hostnameAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongname.apple.com"), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) }, - @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("testserver.apple.com"), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) } ]; @@ -289,10 +314,16 @@ static void test_policy_string_constraints(void) { CFReleaseNull(wrongnamePolicy); removeTS(cert2); - NSArray *emailAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimePolicy, +#if TARGET_OS_IPHONE + #define smimeFrameworkPolicy smimePolicy +#else + SecPolicyRef smimeFrameworkPolicy= SecFrameworkPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("username@apple.com")); +#endif + + NSArray *emailAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimeFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongemail@apple.com"), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) }, - @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimePolicy, + @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimeFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("username@apple.com"), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) } ]; @@ -310,21 +341,25 @@ static void test_policy_string_constraints(void) { check_trust(smimeChain, wrongemailPolicy, verify_date, kSecTrustResultDeny); CFReleaseNull(wrongemailPolicy); removeTS(cert3); + +#if TARGET_OS_OSX + CFReleaseNull(smimeFrameworkPolicy); +#endif } -#if TARGET_OS_IPHONE -#define kNumberApplicationsConstraintsTests 0 -static void test_application_constraints(void) {} -#else +#if TARGET_OS_OSX #include -#define kNumberApplicationsConstraintsTests (2+4+2*4) -static void test_application_constraints(void) { +- (void)test_application_constraints +{ SecTrustedApplicationRef thisApp = NULL, someOtherApp = NULL; - ok_status(SecTrustedApplicationCreateFromPath(NULL, &thisApp), + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + ok_status(SecTrustedApplicationCreateFromPath("/AppleInternal/CoreOS/tests/Security/TrustTests", &thisApp), "create TrustedApplicationRef for this app"); ok_status(SecTrustedApplicationCreateFromPath("/Applications/Safari.app", &someOtherApp), "create TrustedApplicationRef for Safari"); + #pragma clang diagnostic pop NSDictionary *thisAppTS = @{ (__bridge NSString*)kSecTrustSettingsApplication: (__bridge id)thisApp, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)}; @@ -345,10 +380,9 @@ static void test_application_constraints(void) { CFReleaseNull(thisApp); CFReleaseNull(someOtherApp); } -#endif +#endif // TARGET_OS_OSX -#define kNumberKeyUsageConstraintsTests (14+11*4) -static void test_key_usage_constraints(void) { +- (void)test_key_usage_constraints { /* any key usage succeeds */ NSDictionary *anyKeyUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseAny), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)}; @@ -423,8 +457,8 @@ static void test_key_usage_constraints(void) { CFReleaseNull(smimeMultiple); } -#define kNumberAllowedErrorsTests (14+8*4) -static void test_allowed_errors(void) { +- (void)test_allowed_errors +{ setTS(cert0, NULL); /* allow expired errors */ @@ -467,7 +501,7 @@ static void test_allowed_errors(void) { /* allowed error with a policy constraint */ NSDictionary *allowExpiredConstrained = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147409654), - (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)}; setTS(cert1, (__bridge CFDictionaryRef)allowExpiredConstrained) setTS(cert2, (__bridge CFDictionaryRef)allowExpiredConstrained); @@ -479,11 +513,11 @@ static void test_allowed_errors(void) { removeTS(cert0); } -#define kNumberMultipleConstraintsTests (8+9*4) -static void test_multiple_constraints(void) { +- (void)test_multiple_constraints +{ /* deny all but */ NSArray *denyAllBut = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy , + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy , (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)}, @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) } ]; @@ -494,7 +528,7 @@ static void test_multiple_constraints(void) { /* allow all but */ NSArray *allowAllBut = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy , + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy , (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)}, @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) } ]; @@ -503,11 +537,17 @@ static void test_multiple_constraints(void) { check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure); removeTS(cert0); +#if TARGET_OS_IPHONE +#define basicFrameworkPolicy basicPolicy +#else + SecPolicyRef basicFrameworkPolicy = SecFrameworkPolicyCreateBasicX509(); +#endif + /* different results for specific policies */ NSArray *specifyPolicyResult = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)}, - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)basicPolicy, + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)basicFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) } ]; setTS(cert0, (__bridge CFArrayRef)specifyPolicyResult); @@ -518,11 +558,11 @@ static void test_multiple_constraints(void) { /* different results for additional constraint with same policy */ NSArray *policyConstraintResult = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongname.apple.com"), (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408896), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)}, - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) } ]; SecPolicyRef wrongNameSSL = NULL; @@ -534,13 +574,16 @@ static void test_multiple_constraints(void) { removeTS(cert2); CFReleaseNull(wrongNameSSL); +#if TARGET_OS_OSX + CFReleaseNull(basicFrameworkPolicy); +#endif } -#define kNumberChangeConstraintsTests (2*kNumberSetTSTests + kNumberRemoveTSTests + 4*kNumberCheckTrustTests) -static void test_change_constraints(void) { +- (void)test_change_constraints +{ /* allow all but */ NSArray *allowAllBut = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy , + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy , (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)}, @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) } ]; @@ -557,62 +600,117 @@ static void test_change_constraints(void) { removeTS(cert0); } -#define kNumberPolicyNamePinnningConstraintsTests (kNumberSetTSTests + kNumberRemoveTSTests + 5) -static void test_policy_name_pinning_constraints(void) { +- (void)test_policy_name_pinning_constraints +{ + /* need a new policy object for this test so we don't mess up the policy used by the other tests */ + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com")); +#if TARGET_OS_IPHONE +#define frameworkPolicy policy +#else + SecPolicyRef frameworkPolicy = SecFrameworkPolicyCreateSSL(true, CFSTR("testserver.apple.com")); +#endif + /* allow all but */ NSArray *allowAllBut = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy , + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)frameworkPolicy , (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)}, @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) } ]; setTS(cert0, (__bridge CFArrayRef)allowAllBut); SecTrustRef trust = NULL; - SecTrustResultType trust_result; - ok_status(SecTrustCreateWithCertificates(sslChain, sslPolicy, &trust), "create trust with ssl policy"); + ok_status(SecTrustCreateWithCertificates(sslChain, policy, &trust), "create trust with ssl policy"); ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verify_date), "set trust verify date"); ok_status(SecTrustSetPinningPolicyName(trust, CFSTR("not-a-db-policy-name")), "set policy name"); - ok_status(SecTrustEvaluate(trust, &trust_result), "evaluate trust"); - is(trust_result, kSecTrustResultRecoverableTrustFailure, "check trust result for sslServer policy with policy name"); + XCTAssertFalse(SecTrustEvaluateWithError(trust, nil), "evaluate trust"); CFReleaseSafe(trust); + CFReleaseNull(policy); + CFReleaseNull(frameworkPolicy); removeTS(cert0); } -int si_28_sectrustsettings(int argc, char *const *argv) +- (void)testDistrustSystemRoot { - plan_tests(kNumberNoConstraintsTests - + kNumberPolicyConstraintsTests - + kNumberPolicyStringConstraintsTests - + kNumberApplicationsConstraintsTests - + kNumberKeyUsageConstraintsTests - + kNumberAllowedErrorsTests - + kNumberMultipleConstraintsTests - + kNumberChangeConstraintsTests - + kNumberPolicyNamePinnningConstraintsTests - ); - -#if !TARGET_OS_IPHONE - if (getuid() != 0) { - printf("Test must be run as root on OS X"); - return 0; - } -#endif - - @autoreleasepool { - setup_globals(); - test_no_constraints(); - test_policy_constraints(); - test_policy_string_constraints(); - test_application_constraints(); - test_key_usage_constraints(); - test_allowed_errors(); - test_multiple_constraints(); - test_change_constraints(); - test_policy_name_pinning_constraints(); - cleanup_globals(); - } - - return 0; + // Users can distrust system roots + id systemRoot = [self SecCertificateCreateFromResource:@"DigiCertGlobalRootG3" subdirectory:@"si-20-sectrust-policies-data"]; + NSDictionary *deny = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)}; + id persistentRef = [self addTrustSettingsForCert:(__bridge SecCertificateRef)systemRoot trustSettings:deny]; + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[systemRoot] policies:nil]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; // January 6, 2020 at 2:40:00 AM PST + XCTAssertFalse([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultDeny); + [self removeTrustSettingsForCert:(__bridge SecCertificateRef)systemRoot persistentRef:persistentRef]; } + +- (void)testDistrustAppleRoot +{ + // Users cannot distrust the Apple Roots + id appleRoot = [self SecCertificateCreateFromResource:@"AppleRootCA" subdirectory:@"si-20-sectrust-policies-data"]; + NSDictionary *deny = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)}; + id persistentRef = [self addTrustSettingsForCert:(__bridge SecCertificateRef)appleRoot trustSettings:deny]; + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[appleRoot] policies:nil]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; // January 6, 2020 at 2:40:00 AM PST + XCTAssert([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultProceed); + [self removeTrustSettingsForCert:(__bridge SecCertificateRef)appleRoot persistentRef:persistentRef]; +} + +- (void)testFatalResultsNonOverride +{ + id root = [self SecCertificateCreateFromPEMResource:@"ca-ki" subdirectory:@"si-88-sectrust-valid-data"]; + id revokedLeaf = [self SecCertificateCreateFromPEMResource:@"leaf-ki-revoked1" subdirectory:@"si-88-sectrust-valid-data"]; + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[revokedLeaf, root] policies:nil]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:542400000.0]]; // March 10, 2018 at 10:40:00 AM PST + [eval setAnchors:@[root]]; + XCTAssertFalse([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultFatalTrustFailure); + + /* still fatal failure if trust settings on root */ + id persistentRef = [self addTrustSettingsForCert:(__bridge SecCertificateRef)root]; + [eval setNeedsEvaluation]; + XCTAssertFalse([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultFatalTrustFailure); + [self removeTrustSettingsForCert:(__bridge SecCertificateRef)root persistentRef:persistentRef]; +} + +- (void)testSystemTrustStore +{ + SecTrustStoreRef systemTS = SecTrustStoreForDomain(kSecTrustStoreDomainSystem); + id appleRoot = [self SecCertificateCreateFromResource:@"AppleRootCA" subdirectory:@"si-20-sectrust-policies-data"]; + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _trustSettingsRoot, sizeof(_trustSettingsRoot)); + + /* system trust store is read-only */ + XCTAssertEqual(errSecReadOnly, SecTrustStoreSetTrustSettings(systemTS, root, NULL)); + XCTAssertEqual(errSecReadOnly, SecTrustStoreRemoveCertificate(systemTS, root)); + + /* Can't enumerate the trust store */ + CFArrayRef store = NULL; + XCTAssertEqual(errSecUnimplemented, SecTrustStoreCopyAll(systemTS, &store)); + XCTAssert(store == NULL); + + /* returns correct results for contains */ + XCTAssert(SecTrustStoreContains(systemTS, (__bridge SecCertificateRef)appleRoot)); + XCTAssertFalse(SecTrustStoreContains(systemTS, root)); + + /* returns constraints for contained CAs */ + CFArrayRef usageConstraints = NULL; + XCTAssertEqual(errSecSuccess, SecTrustStoreCopyUsageConstraints(systemTS, (__bridge SecCertificateRef)appleRoot, &usageConstraints)); + XCTAssert(usageConstraints != NULL); + + CFReleaseNull(usageConstraints); + CFReleaseNull(root); +} + +@end + +#else // TARGET_OS_BRIDGE +@implementation TrustSettingsTests +- (void)testSkipTests +{ + XCTAssert(true); +} +@end + +#endif diff --git a/OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.h b/tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h similarity index 99% rename from OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.h rename to tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h index e379eb34..19d7ad82 100644 --- a/OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.h +++ b/tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2016-2019 Apple Inc. All Rights Reserved. */ -#ifndef si_28_sectrustsettings_h -#define si_28_sectrustsettings_h +#ifndef _TRUSTTESTS_EVALUATION_TRUST_SETTINGS_TESTS_H_ +#define _TRUSTTESTS_EVALUATION_TRUST_SETTINGS_TESTS_H_ /* subject:/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Root CA */ /* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Root CA */ @@ -525,4 +525,4 @@ uint8_t _corporateServerCert[] = { 0x05,0x15,0xA6,0xD5,0x1E,0x23,0xB7,0xC2, }; -#endif /* si_28_sectrustsettings_h */ +#endif /* _TRUSTTESTS_EVALUATION_TRUST_SETTINGS_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/ValidTests.m b/tests/TrustTests/EvaluationTests/ValidTests.m new file mode 100644 index 00000000..016b53ff --- /dev/null +++ b/tests/TrustTests/EvaluationTests/ValidTests.m @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2017-2019 Apple Inc. All Rights Reserved. + * + */ + +#import +#import + +#include +#include +#include +#include +#include +#include "trust/trustd/OTATrustUtilities.h" + +#import "../TestMacroConversions.h" +#import "TrustEvaluationTestCase.h" + +enum { + kBasicPolicy = 0, + kSSLServerPolicy = 1, +}; + +@interface ValidTests : TrustEvaluationTestCase +@end + +@implementation ValidTests + +#if !TARGET_OS_BRIDGE +- (void) run_valid_trust_test:(SecCertificateRef)leaf + ca:(SecCertificateRef)ca + subca:(SecCertificateRef)subca + anchors:(CFArrayRef)anchors + date:(CFDateRef)date + policyID:(CFIndex)policyID + expected:(SecTrustResultType)expected + test_name:(const char *)test_name +{ + CFArrayRef policies=NULL; + SecPolicyRef policy=NULL; + SecTrustRef trust=NULL; + SecTrustResultType trustResult; + CFMutableArrayRef certs=NULL; + + printf("Starting %s\n", test_name); + isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array"); + if (certs) { + if (leaf) { + CFArrayAppendValue(certs, leaf); + } + if (ca) { + CFArrayAppendValue(certs, ca); + } + if (subca) { + CFArrayAppendValue(certs, subca); + } + } + + if (policyID == kSSLServerPolicy) { + isnt(policy = SecPolicyCreateSSL(true, NULL), NULL, "create ssl policy"); + } else { + isnt(policy = SecPolicyCreateBasicX509(), NULL, "create basic policy"); + } + isnt(policies = CFArrayCreate(kCFAllocatorDefault, (const void **)&policy, 1, &kCFTypeArrayCallBacks), NULL, "create policies"); + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); + + assert(trust); // silence analyzer + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + ok(trustResult == expected, "trustResult %d expected (got %d) for %s", + (int)expected, (int)trustResult, test_name); + + CFReleaseSafe(certs); + CFReleaseSafe(policy); + CFReleaseSafe(policies); + CFReleaseSafe(trust); +} + +- (SecCertificateRef) CF_RETURNS_RETAINED createCertFromResource:(NSString *)name +{ + id cert = [self SecCertificateCreateFromPEMResource:name subdirectory:@"si-88-sectrust-valid-data"]; + return (__bridge SecCertificateRef)cert; +} + +- (void)test_date_constraints +{ + SecCertificateRef ca_na=NULL, ca_nb=NULL, root=NULL; + SecCertificateRef leaf_na_ok1=NULL, leaf_na_ok2=NULL; + SecCertificateRef leaf_nb_ok1=NULL, leaf_nb_ok2=NULL, leaf_nb_revoked1=NULL; + + isnt(ca_na = [self createCertFromResource:@"ca-na"], NULL, "create ca-na cert"); + isnt(ca_nb = [self createCertFromResource:@"ca-nb"], NULL, "create ca-nb cert"); + isnt(root = [self createCertFromResource:@"root"], NULL, "create root cert"); + isnt(leaf_na_ok1 = [self createCertFromResource:@"leaf-na-ok1"], NULL, "create leaf-na-ok1 cert"); + isnt(leaf_na_ok2 = [self createCertFromResource:@"leaf-na-ok2"], NULL, "create leaf-na-ok2 cert"); + isnt(leaf_nb_ok1 = [self createCertFromResource:@"leaf-nb-ok1"], NULL, "create leaf-nb-ok1 cert"); + isnt(leaf_nb_ok2 = [self createCertFromResource:@"leaf-nb-ok2"], NULL, "create leaf-nb-ok2 cert"); + isnt(leaf_nb_revoked1 = [self createCertFromResource:@"leaf-nb-revoked1"], NULL, "create leaf-nb-revoked1 cert"); + + CFMutableArrayRef anchors=NULL; + isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array"); + if (anchors && root) { + CFArrayAppendValue(anchors, root); + } + CFCalendarRef cal = NULL; + CFAbsoluteTime at; + CFDateRef date_20180102 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info + + isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar"); + ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 1, 2), "create verify absolute time 20180102"); + isnt(date_20180102 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180102"); + + /* Case 0: leaf_na_ok1 (not revoked) */ + /* -- OK: cert issued 2017-10-20, before the CA not-after date of 2017-10-21 */ + /* test cert has no SCT, but is expected to be OK since we now only apply the CT restriction for SSL. */ + [self run_valid_trust_test:leaf_na_ok1 ca:ca_na subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultUnspecified + test_name:"leaf_na_ok1 basic"]; + + /* Case 1: leaf_na_ok1 (not revoked) */ + /* -- BAD: since a not-after date now requires CT (for SSL) and the test cert has no SCT, this is fatal. */ + /* Mock a successful mobile asset check-in so that we enforce CT */ + XCTAssertTrue(UpdateOTACheckInDate(), "failed to set check-in date as now"); + [self run_valid_trust_test:leaf_na_ok1 ca:ca_na subca:NULL anchors:anchors date:date_20180102 + policyID:kSSLServerPolicy expected:kSecTrustResultFatalTrustFailure + test_name:"leaf_na_ok1 ssl"]; + + /* Case 2: leaf_na_ok2 (revoked) */ + /* -- BAD: cert issued 2017-10-26, after the CA not-after date of 2017-10-21 */ + [self run_valid_trust_test:leaf_na_ok2 ca:ca_na subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure + test_name:"leaf_na_ok2 basic"]; + + /* Case 3: leaf_nb_ok1 (revoked) */ + /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */ + [self run_valid_trust_test:leaf_nb_ok1 ca:ca_nb subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure + test_name:"leaf_nb_ok1 basic"]; + + /* Case 4: leaf_nb_ok2 (not revoked) */ + /* -- OK: cert issued 2017-10-26, after the CA not-before date of 2017-10-22 */ + [self run_valid_trust_test:leaf_nb_ok2 ca:ca_nb subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultUnspecified + test_name:"leaf_nb_ok2 basic"]; + + /* Case 5: leaf_nb_revoked1 (revoked) */ + /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */ + [self run_valid_trust_test:leaf_nb_revoked1 ca:ca_nb subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure + test_name:"leaf_nb_revoked1 basic"]; + + CFReleaseSafe(ca_na); + CFReleaseSafe(ca_nb); + CFReleaseSafe(leaf_na_ok1); + CFReleaseSafe(leaf_na_ok2); + CFReleaseSafe(leaf_nb_ok1); + CFReleaseSafe(leaf_nb_ok2); + CFReleaseSafe(leaf_nb_revoked1); + CFReleaseSafe(root); + CFReleaseSafe(anchors); + CFReleaseSafe(cal); + CFReleaseSafe(date_20180102); +} + +- (void)test_known_intermediate +{ + SecCertificateRef ca_ki=NULL, root=NULL; + SecCertificateRef leaf_ki_ok1=NULL, leaf_ki_revoked1=NULL; + SecCertificateRef leaf_unknown=NULL, ca_unknown=NULL; + + isnt(ca_ki = [self createCertFromResource:@"ca-ki"], NULL, "create ca-ki cert"); + isnt(root = [self createCertFromResource:@"root"], NULL, "create root cert"); + isnt(leaf_ki_ok1 = [self createCertFromResource:@"leaf-ki-ok1"], NULL, "create leaf-ki-ok1 cert"); + isnt(leaf_ki_revoked1 = [self createCertFromResource:@"leaf-ki-revoked1"], NULL, "create leaf-ki-revoked1 cert"); + isnt(ca_unknown = [self createCertFromResource:@"ca-unknown"], NULL, "create ca-unknown cert"); + isnt(leaf_unknown = [self createCertFromResource:@"leaf-unknown"], NULL, "create leaf-unknown cert"); + + CFMutableArrayRef anchors=NULL; + isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array"); + if (anchors && root) { + CFArrayAppendValue(anchors, root); + } + CFCalendarRef cal = NULL; + CFAbsoluteTime at; + CFDateRef date_20180310 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info + + isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar"); + ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 3, 10), "create verify absolute time 20180310"); + isnt(date_20180310 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180310"); + + /* Case 1: leaf_ki_ok1 */ + /* -- OK: cert issued by a known intermediate */ + [self run_valid_trust_test:leaf_ki_ok1 ca:ca_ki subca:NULL anchors:anchors date:date_20180310 policyID:kBasicPolicy expected:kSecTrustResultUnspecified test_name:"leaf_ki_ok1"]; + + /* Case 2: leaf_ki_revoked1 */ + /* -- BAD: CA specifies known-only+complete serial blocklist; this cert is on the blocklist. */ + [self run_valid_trust_test:leaf_ki_revoked1 ca:ca_ki subca:NULL anchors:anchors date:date_20180310 policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure test_name:"leaf_ki_revoked"]; + + /* Case 3: leaf_unknown */ + /* -- BAD: ca_unknown issued from ca_ki, but is not a known intermediate. + * ca_ki has a path len of 0 which would normally result in kSecTrustResultRecoverableTrustFailure; + * however, since known-intermediates is asserted for ca_ki (non-overridable), we expect a fatal failure. */ + [self run_valid_trust_test:leaf_unknown ca:ca_unknown subca:ca_ki anchors:anchors date:date_20180310 policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure test_name:"leaf_unknown test"]; + + CFReleaseSafe(ca_ki); + CFReleaseSafe(leaf_ki_ok1); + CFReleaseSafe(leaf_ki_revoked1); + CFReleaseSafe(ca_unknown); + CFReleaseSafe(leaf_unknown); + CFReleaseSafe(root); + CFReleaseSafe(anchors); + CFReleaseSafe(cal); + CFReleaseSafe(date_20180310); +} +#else /* TARGET_OS_BRIDGE */ +/* Valid is not supported on bridgeOS */ +- (void)testSkipTests +{ + XCTAssert(true); +} +#endif + +@end diff --git a/tests/TrustTests/EvaluationTests/VerifyDateTests.m b/tests/TrustTests/EvaluationTests/VerifyDateTests.m index d102547e..b980d64a 100644 --- a/tests/TrustTests/EvaluationTests/VerifyDateTests.m +++ b/tests/TrustTests/EvaluationTests/VerifyDateTests.m @@ -102,10 +102,10 @@ static SecTrustRef trust = nil; @implementation ValidityPeriodRestrictionTests // Note that the dates described in the test names are the issuance date not the VerifyDate -- (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors error:(NSError **)error +- (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors verifyTime:(NSTimeInterval)time error:(NSError **)error { SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("example.com")); - NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:590000000.0]; // September 12, 2019 at 9:53:20 AM PDT + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:time]; SecTrustRef trustRef = NULL; BOOL result = NO; CFErrorRef cferror = NULL; @@ -129,6 +129,11 @@ errOut: return result; } +- (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors error:(NSError **)error +{ + return [self runTrustEvaluation:certs anchors:anchors verifyTime:590000000.0 error:error]; // September 12, 2019 at 9:53:20 AM PDT +} + - (void)testSystemTrust_MoreThan5Years { [self setTestRootAsSystem:_testValidityPeriodsRootHash]; @@ -220,6 +225,42 @@ errOut: CFReleaseNull(leaf); } +- (void)testSystemTrust_MoreThan398Days_AfterSep2020 +{ + [self setTestRootAsSystem:_testValidityPeriodsRootHash]; + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _testValidityPeriodsRoot, sizeof(_testValidityPeriodsRoot)); + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _testLeaf_2Years, sizeof(_testLeaf_2Years)); + + NSError *error = nil; + XCTAssertFalse([self runTrustEvaluation:@[(__bridge id)leaf] + anchors:@[(__bridge id)root] + verifyTime:621000000.0 // September 5, 2020 at 5:00:00 AM PDT + error:&error], + "system-trusted 2 year cert issued after 1 Sept 2020 failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(root); + CFReleaseNull(leaf); +} + +- (void)testSystemTrust_398Days_AfterSep2020 +{ + [self setTestRootAsSystem:_testValidityPeriodsRootHash]; + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _testValidityPeriodsRoot, sizeof(_testValidityPeriodsRoot)); + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _testLeaf_398Days, sizeof(_testLeaf_398Days)); + + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:@[(__bridge id)leaf] + anchors:@[(__bridge id)root] + verifyTime:621000000.0 // September 5, 2020 at 5:00:00 AM PDT + error:&error], + "system-trusted 398 day cert issued after 1 Sept 2020 failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(root); + CFReleaseNull(leaf); +} + - (void)testAppTrustRoot_MoreThan825Days_AfterJul2019 { SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _testValidityPeriodsRoot, sizeof(_testValidityPeriodsRoot)); diff --git a/tests/TrustTests/EvaluationTests/VerifyDateTests_data.h b/tests/TrustTests/EvaluationTests/VerifyDateTests_data.h index 3948974f..a03e8a08 100644 --- a/tests/TrustTests/EvaluationTests/VerifyDateTests_data.h +++ b/tests/TrustTests/EvaluationTests/VerifyDateTests_data.h @@ -825,4 +825,191 @@ const uint8_t _testLeaf_825Days[] = { 0x2B,0x61,0x37,0x1B,0x25,0xFF,0xC6,0x02,0x2F,0x83,0xEE,0xF3,0x27,0x00,0xE9,0x73, 0xC8,0xDC,0x49,0xDE,0x0B,0x80,0x4B,0x17,0x17,0x7B,0x13,0x79,0x56, }; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Validity Period Maximums 2 Year Leaf */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Validity Period Maximums Test Root */ +/* Not Before: Sep 1 00:05:55 2020 GMT + Not After : Sep 1 00:05:55 2022 GMT */ +const uint8_t _testLeaf_2Years[] = { + 0x30,0x82,0x05,0x58,0x30,0x82,0x03,0x40,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x4B, + 0x8D,0xD7,0x1D,0x8B,0x58,0x14,0x25,0xFD,0x5A,0xF1,0xBF,0xD9,0xA3,0x44,0x41,0x38, + 0xBA,0xF1,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x30,0x81,0x97,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C, + 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, + 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x2B, + 0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x0C,0x22,0x56,0x61,0x6C,0x69,0x64,0x69,0x74, + 0x79,0x20,0x50,0x65,0x72,0x69,0x6F,0x64,0x20,0x4D,0x61,0x78,0x69,0x6D,0x75,0x6D, + 0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x30,0x1E,0x17,0x0D,0x32, + 0x30,0x30,0x39,0x30,0x31,0x30,0x30,0x30,0x35,0x35,0x35,0x5A,0x17,0x0D,0x32,0x32, + 0x30,0x39,0x30,0x31,0x30,0x30,0x30,0x35,0x35,0x35,0x5A,0x30,0x81,0x99,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, + 0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72, + 0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67, + 0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x24,0x56,0x61,0x6C,0x69,0x64,0x69,0x74,0x79,0x20,0x50,0x65,0x72,0x69, + 0x6F,0x64,0x20,0x4D,0x61,0x78,0x69,0x6D,0x75,0x6D,0x73,0x20,0x32,0x20,0x59,0x65, + 0x61,0x72,0x20,0x4C,0x65,0x61,0x66,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30, + 0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC8,0xF2,0x3C,0xD6,0x71,0xC6,0xD7,0x8A, + 0xC1,0xC9,0xC4,0x99,0xD6,0x51,0x52,0x64,0xCB,0x8A,0x92,0x48,0x7C,0x83,0x15,0x82, + 0xE3,0x35,0x9E,0x2C,0x43,0xC3,0x38,0x7F,0xC0,0xF1,0xC9,0x44,0xC0,0x9D,0x52,0x3B, + 0x4A,0x0F,0x8A,0xD3,0x8E,0xA9,0xE9,0xA1,0x5D,0x93,0xA7,0xB3,0xD0,0x20,0x9C,0x53, + 0x62,0xE5,0x8D,0xBF,0xD8,0x3C,0x33,0x49,0x2C,0x82,0x65,0xF5,0x48,0xAA,0xF3,0xD7, + 0x8F,0x23,0x4B,0x3F,0x89,0xC3,0x8E,0xD2,0xAB,0xF6,0xFA,0x56,0x51,0xD2,0x42,0xBD, + 0x88,0x9D,0x43,0x75,0xE4,0xE8,0x6D,0xB7,0xF3,0xD1,0xEC,0x9F,0xD8,0xAB,0x23,0xEC, + 0xFC,0x5F,0x87,0xCB,0xB8,0xC4,0xD5,0xE5,0xDD,0x2B,0x79,0x53,0xCF,0x43,0x2A,0x57, + 0x10,0x19,0xA5,0x57,0x92,0x9A,0xD0,0xB7,0xF0,0xE8,0x7C,0xAA,0xCB,0xF1,0xB8,0xC3, + 0xC0,0x53,0x5C,0xDE,0x5D,0xB0,0x47,0x38,0xC2,0x81,0xE5,0xD3,0x39,0x84,0xB5,0x64, + 0xB0,0x59,0xE7,0x7C,0xEB,0x92,0x5B,0xB1,0xF9,0x82,0x95,0x45,0x14,0x5D,0x17,0x5C, + 0x4F,0x49,0x54,0x36,0xF0,0xCB,0xF5,0x7E,0x3E,0xAF,0x14,0x00,0x06,0x73,0x77,0x59, + 0xD7,0xB4,0xA8,0x49,0xCE,0x7C,0x55,0x1C,0xC4,0x79,0x6E,0x0D,0xD1,0x04,0xF0,0x2E, + 0xC5,0xF3,0x8A,0xA7,0xC5,0x9F,0xB0,0xED,0x3D,0x13,0x80,0x94,0x1E,0xDC,0xF3,0x81, + 0x97,0x52,0x4F,0x62,0x83,0xD6,0x02,0xFB,0x9B,0x03,0xE1,0x29,0xD0,0x7D,0x18,0x4B, + 0xDB,0xEE,0x69,0xF4,0xC7,0x98,0xA1,0xBB,0x62,0xCE,0xD2,0x7B,0x2E,0x0F,0xD5,0x06, + 0xE8,0x5E,0x47,0x00,0x20,0x00,0xC5,0x11,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x98, + 0x30,0x81,0x95,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02, + 0x30,0x16,0x06,0x03,0x55,0x1D,0x11,0x04,0x0F,0x30,0x0D,0x82,0x0B,0x65,0x78,0x61, + 0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, + 0x16,0x04,0x14,0xD3,0x39,0x1B,0x96,0x50,0xE7,0x23,0x59,0x7C,0x88,0xF9,0x64,0x2B, + 0xF9,0x60,0x70,0x72,0xE7,0x78,0xE6,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18, + 0x30,0x16,0x80,0x14,0xDE,0xEB,0xFD,0x98,0xFD,0xCA,0x44,0xC1,0xFA,0xB7,0xF9,0x2B, + 0xF5,0x96,0x67,0x08,0x11,0x35,0x27,0x75,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x02,0x01,0x00,0x37,0x45,0x43,0xE5, + 0x3A,0x7C,0xFC,0xFF,0x49,0xE2,0xC6,0x70,0xD8,0xB6,0x51,0x7D,0x61,0x6D,0x1A,0x87, + 0x5F,0x86,0x2B,0xE4,0xFF,0x30,0x5B,0xBB,0xD5,0x2D,0x4B,0x95,0x9C,0x7B,0xDA,0x57, + 0xC8,0xA7,0x12,0x12,0x55,0x48,0x16,0x04,0xBD,0xE2,0x2A,0xC1,0xE0,0x34,0x0D,0xC3, + 0x18,0x25,0xD1,0xA7,0x1E,0x74,0xF6,0x0A,0xB0,0x70,0x41,0xF3,0x80,0xDA,0xBC,0xF0, + 0xE3,0x84,0x5E,0x8A,0xFA,0x9C,0x2E,0x00,0x41,0x1B,0xB6,0x1D,0x82,0x3D,0x40,0xF4, + 0x00,0xF1,0x88,0xCC,0x00,0x06,0xFC,0x61,0x94,0x93,0x55,0xD2,0x21,0x9B,0x3D,0xFE, + 0xF7,0x82,0xE6,0x86,0xF6,0x39,0x4E,0xFA,0x3C,0x37,0x4E,0x25,0x7F,0x0A,0x5E,0x05, + 0x43,0x4D,0x4E,0x22,0xED,0xB0,0xAA,0xAC,0x81,0x29,0xD4,0x6C,0xE1,0x21,0x2D,0x8E, + 0x21,0x29,0x8A,0x44,0x29,0xD6,0x95,0x55,0x75,0x74,0x66,0xAB,0xC7,0xF2,0xC3,0xA6, + 0x9B,0xE5,0x55,0x80,0x84,0xB5,0x9F,0x0C,0x2F,0x89,0x8E,0x35,0x26,0xDC,0x0C,0xA0, + 0x72,0x1F,0xC2,0xCA,0x04,0x15,0x4D,0x4F,0xC6,0x01,0x25,0xDF,0xB4,0x76,0x8B,0x0F, + 0xF0,0xC3,0xE0,0x76,0x02,0x01,0x6B,0x84,0x9D,0xC2,0xE3,0x3B,0x7A,0x9F,0x54,0x0E, + 0xA0,0x0A,0x2A,0xC5,0x72,0x66,0x94,0x88,0x55,0xEC,0xCA,0x69,0x44,0x05,0x00,0x6C, + 0x03,0xF6,0xCB,0x73,0xD5,0xE9,0xAE,0xE0,0x85,0x92,0x39,0x62,0xEB,0xDB,0xCC,0xDD, + 0x89,0x82,0x07,0xA1,0xAB,0x60,0x97,0x4D,0x7A,0xC4,0xA1,0xA1,0x47,0xCA,0xA7,0xCC, + 0xB5,0xE7,0xB4,0xB6,0x01,0x38,0xF9,0x4C,0x2F,0xC2,0xC1,0x44,0xC6,0xAF,0x5C,0xDD, + 0x82,0xD8,0x8D,0xEE,0x42,0x8D,0xB5,0xE8,0x58,0x73,0x0E,0x0A,0xFC,0x0C,0xCC,0x35, + 0xFE,0x5E,0x09,0x12,0x70,0xD0,0xA5,0xD2,0x38,0x27,0xBB,0xD0,0xA0,0xF6,0x61,0x44, + 0xEA,0x2D,0xCE,0x54,0xEB,0xA4,0x57,0x52,0xF4,0x81,0xE2,0xFD,0x7B,0x0D,0x08,0x53, + 0xD4,0x0D,0x6E,0x8B,0x4F,0xA2,0xD4,0xCF,0xBF,0x01,0xB4,0x0B,0x34,0x37,0xEE,0x89, + 0x81,0xBD,0x36,0x87,0x39,0x5D,0x2D,0xE0,0x0E,0x19,0x28,0x26,0xDC,0x80,0xDB,0x22, + 0x49,0x4B,0x5E,0xAF,0x17,0xB8,0x83,0xC5,0x32,0x66,0xF3,0x81,0x01,0x36,0x95,0xC5, + 0xF2,0x49,0x81,0xDC,0xD8,0x07,0xF7,0x01,0xEE,0x8D,0x0F,0xDD,0x6A,0xDE,0x9E,0xDD, + 0x5D,0x98,0x82,0xCD,0x2C,0x2B,0x02,0xD4,0xEC,0x55,0x9F,0x95,0x63,0x4C,0x2B,0x58, + 0x16,0x8B,0x52,0x24,0x98,0x51,0x7C,0x0D,0xA9,0x47,0xE9,0xAA,0x70,0x94,0xC7,0xC1, + 0x41,0x55,0x44,0x71,0x55,0x1D,0x05,0x4C,0xF3,0xCE,0xEB,0x40,0x4A,0xED,0x40,0x3D, + 0xD1,0xAD,0x8A,0xF7,0xBF,0x0E,0x30,0xE0,0x20,0x60,0x64,0x0A,0xEB,0x9C,0x89,0x60, + 0xC8,0x8D,0xF3,0x3A,0xE4,0x76,0x50,0xE2,0x2B,0x92,0xB1,0x0D,0xCD,0x66,0xCC,0x48, + 0x16,0x84,0x26,0x54,0xF4,0x9F,0x0F,0x1C,0xC6,0x53,0x37,0xC9,0x11,0x18,0xAE,0x41, + 0xED,0xE4,0x17,0xBE,0x5D,0x54,0xF1,0x9E,0x10,0x34,0x5E,0x28,0x32,0x65,0xB2,0x46, + 0x25,0x63,0x5E,0x43,0xCB,0x6D,0x5E,0xEA,0xAC,0x4A,0x50,0x75,0x7E,0x6C,0x61,0xF4, + 0xE6,0x5B,0xB6,0x7B,0xF6,0x6B,0xAD,0x96,0xD7,0xF3,0xF8,0x44, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Validity Period Maximums 398 Day Leaf */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Validity Period Maximums Test Root */ +/* Not Before: Sep 1 00:06:20 2020 GMT + Not After : Oct 4 00:06:20 2021 GMT */ +const uint8_t _testLeaf_398Days[] = { + 0x30,0x82,0x05,0x59,0x30,0x82,0x03,0x41,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x4B, + 0x8D,0xD7,0x1D,0x8B,0x58,0x14,0x25,0xFD,0x5A,0xF1,0xBF,0xD9,0xA3,0x44,0x41,0x38, + 0xBA,0xF2,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x30,0x81,0x97,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C, + 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, + 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x2B, + 0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x0C,0x22,0x56,0x61,0x6C,0x69,0x64,0x69,0x74, + 0x79,0x20,0x50,0x65,0x72,0x69,0x6F,0x64,0x20,0x4D,0x61,0x78,0x69,0x6D,0x75,0x6D, + 0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x30,0x1E,0x17,0x0D,0x32, + 0x30,0x30,0x39,0x30,0x31,0x30,0x30,0x30,0x36,0x32,0x30,0x5A,0x17,0x0D,0x32,0x31, + 0x31,0x30,0x30,0x34,0x30,0x30,0x30,0x36,0x32,0x30,0x5A,0x30,0x81,0x9A,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, + 0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72, + 0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67, + 0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x2E,0x30,0x2C,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x25,0x56,0x61,0x6C,0x69,0x64,0x69,0x74,0x79,0x20,0x50,0x65,0x72,0x69, + 0x6F,0x64,0x20,0x4D,0x61,0x78,0x69,0x6D,0x75,0x6D,0x73,0x20,0x33,0x39,0x38,0x20, + 0x44,0x61,0x79,0x20,0x4C,0x65,0x61,0x66,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00, + 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xA4,0xDD,0xA6,0x75,0x21,0xFC,0x44, + 0x4D,0xF9,0x5D,0x69,0x5D,0xCF,0xE7,0xD1,0x88,0x37,0xAA,0x9A,0x60,0x25,0x0C,0x2C, + 0x65,0xAA,0xF2,0x2A,0xDF,0x2F,0xA9,0x0C,0x61,0x40,0xCE,0xF1,0x87,0x81,0x74,0xA9, + 0xCE,0xAE,0x2E,0x6E,0x4D,0x9E,0x72,0x34,0x51,0x9B,0x0A,0xD2,0x6F,0x46,0xEE,0xB1, + 0x9B,0xAA,0xCF,0x2D,0xBA,0x32,0x4F,0x86,0x04,0x54,0x27,0x3C,0x95,0xEC,0xD2,0xC7, + 0x26,0xD1,0x9B,0x02,0x33,0x90,0x38,0x7F,0x92,0xF9,0x1B,0x15,0xA4,0x19,0x83,0xBB, + 0x51,0x38,0x2D,0x6C,0x4B,0x7A,0x68,0x54,0xCD,0x30,0x2F,0xC1,0x26,0x01,0xA0,0x60, + 0xBB,0x79,0x9F,0xAD,0x28,0x2F,0xA5,0x17,0x69,0xA7,0xCD,0xEE,0xE3,0x61,0x83,0xB5, + 0xBC,0xC2,0x6C,0xFA,0x85,0x75,0x7C,0x06,0x4D,0xEA,0xCB,0x39,0x42,0x21,0xB4,0x2F, + 0x9C,0x81,0xAA,0x39,0x3F,0xAA,0xEC,0xF8,0xA1,0x65,0xF5,0x64,0x0A,0xB2,0xA3,0x71, + 0x29,0xA2,0x74,0x12,0xE7,0x66,0xB5,0x1F,0xED,0xDF,0x2C,0xA8,0x0C,0xB7,0xD3,0x96, + 0x33,0x92,0x1D,0xF4,0xA8,0x94,0xD7,0x08,0x58,0x65,0xDD,0x6C,0x99,0x52,0x05,0x31, + 0xB6,0x0E,0x88,0xE2,0xE5,0xEB,0xCA,0x5A,0x30,0x9D,0x0C,0x68,0xC6,0x2B,0xB4,0x36, + 0xF2,0xA0,0xD1,0x97,0xDB,0x49,0x78,0xAB,0x79,0x90,0xE5,0x7B,0xA5,0xAD,0xE5,0xB0, + 0x13,0x85,0x74,0x75,0x15,0x82,0xC6,0x04,0x27,0x18,0x7C,0xE8,0x91,0x36,0x6E,0xF2, + 0x64,0xE3,0x37,0x2E,0x0B,0x8D,0x4D,0x8D,0x6B,0xC2,0x44,0x18,0x01,0x95,0xDE,0x08, + 0xAC,0x8D,0x00,0x5A,0xE9,0x09,0xEA,0xD1,0x0D,0x02,0x03,0x01,0x00,0x01,0xA3,0x81, + 0x98,0x30,0x81,0x95,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02, + 0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02, + 0x07,0x80,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03, + 0x02,0x30,0x16,0x06,0x03,0x55,0x1D,0x11,0x04,0x0F,0x30,0x0D,0x82,0x0B,0x65,0x78, + 0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, + 0x04,0x16,0x04,0x14,0x81,0xE5,0x84,0xC1,0xB3,0x5E,0x70,0xD8,0x3A,0xF2,0x45,0x17, + 0x92,0x8B,0x24,0xD5,0x07,0xB1,0x5D,0x96,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04, + 0x18,0x30,0x16,0x80,0x14,0xDE,0xEB,0xFD,0x98,0xFD,0xCA,0x44,0xC1,0xFA,0xB7,0xF9, + 0x2B,0xF5,0x96,0x67,0x08,0x11,0x35,0x27,0x75,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x02,0x01,0x00,0x1B,0x19,0xDC, + 0x50,0x5C,0x92,0x48,0x4F,0x0B,0x3D,0xAF,0x1B,0x9C,0x22,0x36,0xB2,0x24,0x2F,0xBB, + 0xCB,0x05,0x5D,0xC8,0xA5,0x5F,0x43,0x47,0x0C,0x9A,0xCF,0xB5,0x1F,0x01,0x3F,0xE0, + 0x84,0xCE,0xA9,0xC7,0x05,0xFD,0x6E,0xE7,0xD2,0xF6,0x07,0x7B,0xDF,0x57,0xD6,0x0F, + 0x03,0x33,0xFE,0xB1,0xB6,0xBF,0x73,0xDF,0x69,0xEA,0x04,0xEA,0xFF,0x7C,0xBB,0x9E, + 0xC4,0x01,0x9A,0xE5,0x6A,0x10,0x45,0x42,0xB2,0xDB,0xA2,0xC3,0x85,0xF4,0x82,0x1A, + 0xE9,0x7B,0xDB,0xF4,0x53,0x3D,0x6B,0x2B,0xA0,0x1E,0x92,0x50,0x89,0x66,0xF3,0xF2, + 0x58,0x8E,0x61,0xBC,0x1D,0x33,0xE8,0x13,0xAA,0xBF,0x2B,0x17,0x36,0x95,0x51,0xA1, + 0x5C,0x9E,0x6B,0x3F,0xEF,0xBA,0x45,0x32,0x84,0xB1,0x81,0xEF,0x10,0xCA,0x05,0xB3, + 0xD7,0x31,0x79,0x76,0x28,0x38,0xB0,0x2E,0x30,0xAC,0x74,0xFF,0xF4,0xFB,0x8F,0x08, + 0x22,0x08,0x41,0x1B,0x67,0xB4,0x72,0x82,0x84,0x6E,0xC3,0x12,0x93,0x65,0xD4,0x9B, + 0xD4,0x2E,0x55,0x6C,0x22,0x6A,0x22,0x36,0x26,0x2C,0x9F,0x5C,0xFC,0x85,0xB2,0x71, + 0x0E,0x58,0x79,0x83,0x75,0x7E,0x65,0x50,0x18,0x05,0x95,0x2F,0xB6,0x05,0x6A,0xA8, + 0x9F,0x1C,0x66,0xFC,0x6F,0x30,0xBE,0xC6,0x20,0x7A,0xF8,0xFC,0xB4,0x24,0x5E,0x4A, + 0x26,0x4C,0xEC,0x48,0xF2,0x5A,0x7D,0x83,0xB1,0x86,0x69,0x48,0x69,0xC7,0xF3,0x2A, + 0xFA,0xB1,0x58,0x69,0x77,0x96,0x67,0xE5,0x7E,0xE6,0xE9,0x07,0xFC,0xA4,0x24,0xC6, + 0xC1,0x64,0x69,0xB4,0x36,0x59,0x81,0xA7,0xD4,0x14,0xEE,0xA5,0xDE,0x44,0x46,0x72, + 0x52,0xB6,0x28,0xF7,0x33,0x5B,0xFA,0x71,0x8F,0xC9,0x9F,0xBE,0xBB,0xEF,0xB4,0x4B, + 0x6A,0xA0,0x01,0xF1,0xA2,0x06,0x41,0xA4,0x8E,0x75,0xC8,0xAF,0x6C,0x31,0xCD,0xCB, + 0x6E,0xB3,0xD1,0x4F,0x46,0x39,0x74,0xD1,0x82,0x75,0x3D,0x71,0x8C,0xD8,0xDE,0xD6, + 0xDE,0x25,0x8A,0xD7,0x77,0xA7,0xD4,0xCA,0xCF,0x2A,0x35,0xA9,0xF4,0x19,0x81,0x98, + 0x81,0x64,0x16,0xBD,0x0C,0xE7,0xED,0xAA,0x05,0xEB,0xED,0x4B,0x1B,0xEE,0x78,0xC4, + 0x6C,0x93,0xDB,0x81,0xB2,0xD0,0x78,0x9D,0x66,0x41,0x91,0xF7,0xCD,0x82,0x45,0x8A, + 0x81,0x3D,0xC3,0x79,0x15,0x9E,0x1D,0xE8,0x25,0xB8,0x8D,0xA7,0xA7,0xA7,0x74,0x43, + 0xF7,0x43,0x80,0xF9,0x01,0xD3,0x81,0xDD,0xE4,0xFF,0x4A,0xC0,0x7C,0x44,0x30,0xB4, + 0xFA,0x9E,0xA3,0x5E,0xE2,0x2B,0x23,0xFB,0x68,0xE9,0x1C,0xA2,0xA9,0xF1,0xD0,0x45, + 0x50,0x3B,0xEC,0xEB,0x22,0xAC,0xBF,0x4E,0xE2,0x64,0xD7,0x0B,0xFE,0xB9,0xBE,0x28, + 0xC2,0xFB,0xA8,0xC5,0x93,0xD9,0x35,0x88,0x48,0x0A,0x24,0x22,0xAF,0x85,0x21,0xC3, + 0x9D,0x02,0x6E,0x9E,0x03,0xF6,0x78,0x66,0xCB,0x16,0x9E,0x74,0xF7,0xEB,0x85,0x63, + 0x9B,0xD8,0x11,0xAF,0x60,0x9E,0xF8,0x9E,0x4E,0x8E,0xEC,0xAD,0x99,0x65,0xEE,0x57, + 0x9C,0x59,0x53,0x7E,0xFE,0x1D,0xCA,0xED,0x17,0xAA,0x1C,0xF3,0xD9,0xC4,0x76,0xDF, + 0x9A,0x64,0x77,0xD6,0x41,0x2D,0x16,0xE7,0xAD,0x7E,0xBF,0x0B,0xF1,0x87,0x6A,0xCF, + 0x2A,0x7B,0x2B,0x8F,0x96,0xFF,0xA2,0xDC,0xE2,0x07,0xF0,0x0C,0x31, +}; + #endif /* _TRUSTTESTS_EVALUATION_VERIFY_DATE_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/iAPTests.m b/tests/TrustTests/EvaluationTests/iAPTests.m index 53735931..f655778b 100644 --- a/tests/TrustTests/EvaluationTests/iAPTests.m +++ b/tests/TrustTests/EvaluationTests/iAPTests.m @@ -22,11 +22,13 @@ * */ +#include #import #include "SecCertificatePriv.h" #include "SecPolicyPriv.h" #include "SecTrustPriv.h" #include "OSX/utilities/SecCFWrappers.h" +#include #include "../TestMacroConversions.h" #include "TrustEvaluationTestCase.h" @@ -69,4 +71,308 @@ errOut: CFReleaseNull(policy); } +- (void)testiAPv1 { + SecTrustRef trust; + SecCertificateRef iAP1CA, iAP2CA, leaf0, leaf1; + isnt(iAP1CA = SecCertificateCreateWithBytes(NULL, _iAP1CA, sizeof(_iAP1CA)), + NULL, "create iAP1CA"); + isnt(iAP2CA = SecCertificateCreateWithBytes(NULL, _iAP2CA, sizeof(_iAP2CA)), + NULL, "create iAP2CA"); + isnt(leaf0 = SecCertificateCreateWithBytes(NULL, _leaf0, sizeof(_leaf0)), + NULL, "create leaf0"); + isnt(leaf1 = SecCertificateCreateWithBytes(NULL, _leaf1, sizeof(_leaf1)), + NULL, "create leaf1"); + { + // temporarily grab some stack space and fill it with 0xFF; + // when we exit this scope, the stack pointer should shrink but leave the memory filled. + // this tests for a stack overflow bug inside SecPolicyCreateiAP (rdar://16056248) + char buf[2048]; + memset(buf, 0xFF, sizeof(buf)); + } + SecPolicyRef policy = SecPolicyCreateiAP(); + const void *v_anchors[] = { + iAP1CA, + iAP2CA + }; + CFArrayRef anchors = CFArrayCreate(NULL, v_anchors, + array_size(v_anchors), NULL); + CFArrayRef certs0 = CFArrayCreate(NULL, (const void **)&leaf0, 1, &kCFTypeArrayCallBacks); + CFArrayRef certs1 = CFArrayCreate(NULL, (const void **)&leaf1, 1, &kCFTypeArrayCallBacks); + ok_status(SecTrustCreateWithCertificates(certs0, policy, &trust), "create trust for leaf0"); + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); + + /* Jan 1st 2008. */ + CFDateRef date = CFDateCreate(NULL, 220752000.0); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + + SecTrustResultType trustResult; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultUnspecified, + "trust is kSecTrustResultUnspecified"); + + is(SecTrustGetCertificateCount(trust), 2, "cert count is 2"); + + CFReleaseSafe(trust); + ok_status(SecTrustCreateWithCertificates(certs1, policy, &trust), "create trust for leaf1"); + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); + + CFReleaseSafe(anchors); + CFReleaseSafe(certs1); + CFReleaseSafe(certs0); + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(leaf0); + CFReleaseSafe(leaf1); + CFReleaseSafe(iAP1CA); + CFReleaseSafe(iAP2CA); + CFReleaseSafe(date); +} + +- (void)testiAPv3 { + SecCertificateRef v3CA = NULL, v3leaf = NULL; + isnt(v3CA = SecCertificateCreateWithBytes(NULL, _v3ca, sizeof(_v3ca)), + NULL, "create v3 CA"); + isnt(v3leaf = SecCertificateCreateWithBytes(NULL, _v3leaf, sizeof(_v3leaf)), + NULL, "create v3leaf"); + + /* Test v3 certs meet iAP policy */ + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFArrayRef certs = NULL, anchors = NULL; + CFDateRef date = NULL; + SecTrustResultType trustResult; + + certs = CFArrayCreate(NULL, (const void **)&v3leaf, 1, &kCFTypeArrayCallBacks); + anchors = CFArrayCreate(NULL, (const void **)&v3CA, 1, &kCFTypeArrayCallBacks); + policy = SecPolicyCreateiAP(); + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust ref"); + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchor"); + ok(date = CFDateCreate(NULL, 484000000.0), "create date"); /* 3 May 2016 */ + if (!date) { goto trustFail; } + ok_status(SecTrustSetVerifyDate(trust, date), "set verify date"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate"); + is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); + + /* Test v3 certs fail iAP SW Auth policy */ + CFReleaseNull(policy); + CFReleaseNull(trust); + policy = SecPolicyCreateiAPSWAuth(); + require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); + require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); + require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), trustFail); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); + +trustFail: + CFReleaseSafe(policy); + CFReleaseSafe(trust); + CFReleaseSafe(certs); + CFReleaseSafe(anchors); + CFReleaseSafe(date); + + /* Test interface for determining iAuth version */ + SecCertificateRef leaf0 = NULL, leaf1 = NULL; + isnt(leaf0 = SecCertificateCreateWithBytes(NULL, _leaf0, sizeof(_leaf0)), + NULL, "create leaf0"); + isnt(leaf1 = SecCertificateCreateWithBytes(NULL, _leaf1, sizeof(_leaf1)), + NULL, "create leaf1"); + + is_status(SecCertificateGetiAuthVersion(leaf0), kSeciAuthVersion2, "v2 certificate"); + is_status(SecCertificateGetiAuthVersion(leaf1), kSeciAuthVersion2, "v2 certificate"); + is_status(SecCertificateGetiAuthVersion(v3leaf), kSeciAuthVersion3, "v3 certificate"); + + CFReleaseSafe(leaf0); + CFReleaseSafe(leaf1); + + /* Test the extension-copying interface */ + CFDataRef extensionData = NULL; + uint8_t extensionValue[32] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A, + }; + ok(extensionData = SecCertificateCopyiAPAuthCapabilities(v3leaf), + "copy iAuthv3 extension data"); + is(CFDataGetLength(extensionData), 32, "compare expected size"); + is(memcmp(extensionValue, CFDataGetBytePtr(extensionData), 32), 0, + "compare expected output"); + CFReleaseNull(extensionData); + + /* Test extension-copying interface with a malformed extension. */ + uint8_t extensionValue2[32] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + }; + SecCertificateRef malformedV3leaf = NULL; + isnt(malformedV3leaf = SecCertificateCreateWithBytes(NULL, _malformedV3Leaf, sizeof(_malformedV3Leaf)), + NULL, "create malformed v3 leaf"); + ok(extensionData = SecCertificateCopyiAPAuthCapabilities(malformedV3leaf), + "copy iAuthv3 extension data for malformed leaf"); + is(CFDataGetLength(extensionData), 32, "compare expected size"); + is(memcmp(extensionValue2, CFDataGetBytePtr(extensionData), 32), 0, + "compare expected output"); + CFReleaseNull(extensionData); + CFReleaseNull(malformedV3leaf); + CFReleaseSafe(v3leaf); + CFReleaseSafe(v3CA); +} + +- (void)testMFiSWAuthTrust { + SecCertificateRef sw_auth_test_CA = NULL, sw_auth_test_leaf = NULL; + isnt(sw_auth_test_CA = SecCertificateCreateWithBytes(NULL, _iAPSWAuthTestRoot, sizeof(_iAPSWAuthTestRoot)), + NULL, "create sw auth test ca"); + isnt(sw_auth_test_leaf = SecCertificateCreateWithBytes(NULL, _iAPSWAuth_leaf, sizeof(_iAPSWAuth_leaf)), + NULL, "create sw auth leaf"); + + /* Test SW Auth certs meet iAP SW Auth policy */ + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFArrayRef certs = NULL, anchors = NULL; + CFDateRef date = NULL; + SecTrustResultType trustResult; + + certs = CFArrayCreate(NULL, (const void **)&sw_auth_test_leaf, 1, &kCFTypeArrayCallBacks); + anchors = CFArrayCreate(NULL, (const void **)&sw_auth_test_CA, 1, &kCFTypeArrayCallBacks); + policy = SecPolicyCreateiAPSWAuth(); + require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); + require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); + require(date = CFDateCreate(NULL, 530000000.0), trustFail); /* 17 Oct 2017, BEFORE issuance */ + require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), trustFail); + is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); + + /* Test SW Auth certs fail iAP policy */ + CFReleaseNull(policy); + CFReleaseNull(trust); + policy = SecPolicyCreateiAP(); + require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); + require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); + require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), trustFail); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); + + /* Test SW Auth certs fail when not-yet-valid with expiration check */ + CFReleaseNull(policy); + CFReleaseNull(trust); + policy = SecPolicyCreateiAPSWAuthWithExpiration(true); + require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); + require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); + require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), trustFail); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); + +trustFail: + CFReleaseSafe(policy); + CFReleaseSafe(trust); + CFReleaseSafe(certs); + CFReleaseSafe(anchors); + CFReleaseSafe(date); + CFReleaseSafe(sw_auth_test_CA); + CFReleaseSafe(sw_auth_test_leaf); +} + +- (void)testMFiSWAuthCert { + SecCertificateRef good_leaf = NULL, bad_leaf = NULL; + isnt(good_leaf = SecCertificateCreateWithBytes(NULL, _iAPSWAuth_leaf, sizeof(_iAPSWAuth_leaf)), + NULL, "create good iAP SW Auth cert"); + isnt(bad_leaf = SecCertificateCreateWithBytes(NULL, _malformed_iAPSWAuth_leaf, sizeof(_malformed_iAPSWAuth_leaf)), + NULL, "create bad iAP SW Auth cert"); + + /* Test Auth version interface */ + ok(SecCertificateGetiAuthVersion(good_leaf) == kSeciAuthVersionSW, "Get version of well-formed SW Auth cert"); + ok(SecCertificateGetiAuthVersion(bad_leaf) == kSeciAuthVersionSW, "Get version of malformed SW Auth cert"); + + /* Test extension copying with malformed extensions */ + is(SecCertificateCopyiAPSWAuthCapabilities(bad_leaf, kSeciAPSWAuthGeneralCapabilities), NULL, + "Fail to get capabilities of malformed SW auth cert"); + is(SecCertificateCopyiAPSWAuthCapabilities(bad_leaf, kSeciAPSWAuthAirPlayCapabilities), NULL, + "Fail to get AirPlay capabilities of malformed SW auth cert"); + is(SecCertificateCopyiAPSWAuthCapabilities(bad_leaf, kSeciAPSWAuthHomeKitCapabilities), NULL, + "Fail to get HomeKit capabilities of malformed SW auth cert"); + + uint8_t byte0 = 0x00; + uint8_t byte1 = 0x01; + CFDataRef data0 = CFDataCreate(NULL, &byte0, 1); + CFDataRef data1 = CFDataCreate(NULL, &byte1, 1); + + /* Test extension copying with well-formed extensions */ + CFDataRef extensionValue = NULL; + isnt(extensionValue = SecCertificateCopyiAPSWAuthCapabilities(good_leaf, kSeciAPSWAuthGeneralCapabilities), NULL, + "Get capabilities of well-formed SW auth cert"); + ok(CFEqual(extensionValue, data1), "Got correct general extension value"); + CFReleaseNull(extensionValue); + + isnt(extensionValue = SecCertificateCopyiAPSWAuthCapabilities(good_leaf, kSeciAPSWAuthAirPlayCapabilities), NULL, + "Get AirPlay capabilities of well-formed SW auth cert"); + ok(CFEqual(extensionValue, data0), "Got correct AirPlay extension value"); + CFReleaseNull(extensionValue); + + isnt(extensionValue = SecCertificateCopyiAPSWAuthCapabilities(good_leaf, kSeciAPSWAuthHomeKitCapabilities), NULL, + "Get capabilities of well-formed SW auth cert"); + ok(CFEqual(extensionValue, data1), "Got correct HomeKit extension value"); + CFReleaseNull(extensionValue); + + CFReleaseNull(good_leaf); + CFReleaseNull(bad_leaf); + CFReleaseNull(data0); + CFReleaseNull(data1); +} + +- (void) testComponentTypeCerts { + SecCertificateRef batteryCA = NULL, nonComponent = NULL; + isnt(batteryCA = SecCertificateCreateWithBytes(NULL, _componentCABattery, sizeof(_componentCABattery)), + NULL, "create battery component CA cert"); + isnt(nonComponent = SecCertificateCreateWithBytes(NULL, _iAP2CA, sizeof(_iAP2CA)), + NULL, "create non-component cert"); + + CFStringRef componentType = NULL; + isnt(componentType = SecCertificateCopyComponentType(batteryCA), NULL, "Get component type"); + ok(CFEqual(componentType, CFSTR("Battery")), "Got correct component type"); + CFReleaseNull(componentType); + + is(componentType = SecCertificateCopyComponentType(nonComponent), NULL, "Get component type"); + + CFReleaseNull(batteryCA); + CFReleaseNull(nonComponent); +} + +- (void)testComponentTypeTrust { + SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFMutableArrayRef certs = NULL; + CFArrayRef anchors = NULL; + CFDateRef date = NULL; + SecTrustResultType trustResult; + + isnt(leaf = SecCertificateCreateWithBytes(NULL, _batteryLeaf, sizeof(_batteryLeaf)), + NULL, "create battery leaf"); + isnt(subCA = SecCertificateCreateWithBytes(NULL, _componentCABattery, sizeof(_componentCABattery)), + NULL, "create battery subCA"); + isnt(root = SecCertificateCreateWithBytes(NULL, _componentRoot, sizeof(_componentRoot)), + NULL, "create component root"); + + /* Test Battery component certs meet component policy */ + certs = CFArrayCreateMutable(NULL, 2, &kCFTypeArrayCallBacks); + CFArrayAppendValue(certs, leaf); + CFArrayAppendValue(certs, subCA); + anchors = CFArrayCreate(NULL, (const void **)&root, 1, &kCFTypeArrayCallBacks); + policy = SecPolicyCreateAppleComponentCertificate(NULL); + require_noerr(SecTrustCreateWithCertificates(certs, policy, &trust), trustFail); + require_noerr(SecTrustSetAnchorCertificates(trust, anchors), trustFail); + require(date = CFDateCreate(NULL, 576000000.0), trustFail); /* April 3, 2019 at 9:00:00 AM PDT */ + require_noerr(SecTrustSetVerifyDate(trust, date), trustFail); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), trustFail); + is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); + +trustFail: + CFReleaseNull(leaf); + CFReleaseNull(subCA); + CFReleaseNull(root); + CFReleaseNull(date); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + @end diff --git a/tests/TrustTests/EvaluationTests/iAPTests_data.h b/tests/TrustTests/EvaluationTests/iAPTests_data.h index c4631978..5748b965 100644 --- a/tests/TrustTests/EvaluationTests/iAPTests_data.h +++ b/tests/TrustTests/EvaluationTests/iAPTests_data.h @@ -108,4 +108,667 @@ unsigned char _root_AACA2[618]={ 0x13,0xB5,0x2A,0xAE,0x3B,0x83,0x2B,0xB2,0x7E,0xB3, }; +/* + subject= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple iPod Accessories Certification Authority + issuer= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA + serial=16 + */ +const uint8_t _iAP1CA[] = { + 0x30, 0x82, 0x04, 0x3F, 0x30, 0x82, 0x03, 0x27, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x0D, + 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x81, 0x86, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x14, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, + 0x43, 0x6F, 0x6D, 0x70, 0x75, 0x74, 0x65, 0x72, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x2D, + 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x24, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x43, + 0x6F, 0x6D, 0x70, 0x75, 0x74, 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x29, 0x30, + 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x36, 0x30, 0x35, + 0x31, 0x32, 0x32, 0x30, 0x35, 0x33, 0x30, 0x39, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x35, 0x31, + 0x32, 0x32, 0x30, 0x35, 0x33, 0x30, 0x39, 0x5A, 0x30, 0x81, 0x92, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x14, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x75, 0x74, 0x65, + 0x72, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x13, 0x24, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x75, 0x74, 0x65, 0x72, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x35, 0x30, 0x33, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x2C, 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x69, 0x50, 0x6F, 0x64, 0x20, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x6F, 0x72, 0x69, 0x65, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, + 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9F, 0x2B, + 0x5A, 0x43, 0x27, 0x3A, 0x1B, 0x7E, 0xC4, 0xB8, 0x4A, 0x36, 0x45, 0x0E, 0x61, 0x4F, 0xA4, 0x51, + 0xD7, 0x9F, 0xCD, 0x22, 0x63, 0x09, 0x86, 0x50, 0xAE, 0xB2, 0xD6, 0x49, 0xEF, 0xE6, 0xBF, 0x2E, + 0xD7, 0x4D, 0x56, 0x03, 0xF5, 0x4F, 0x39, 0x26, 0x86, 0xF5, 0xF2, 0xD9, 0xB3, 0xDF, 0x11, 0x57, + 0x93, 0x51, 0xB7, 0x3A, 0x06, 0x63, 0xCD, 0x9B, 0x99, 0x37, 0xB9, 0x69, 0x8D, 0x03, 0x7F, 0xDE, + 0xA3, 0xB8, 0x38, 0x69, 0xF4, 0x41, 0x04, 0x40, 0xEB, 0x2F, 0x95, 0xEC, 0x1B, 0x21, 0x25, 0xE9, + 0x6A, 0xBB, 0x2E, 0x88, 0xB6, 0x0F, 0x20, 0x89, 0xF4, 0x13, 0x39, 0x3E, 0x29, 0x17, 0x69, 0xC8, + 0x6B, 0xBC, 0xF3, 0xE7, 0xDA, 0x65, 0x9C, 0xF9, 0x9E, 0x34, 0x0B, 0xE6, 0x60, 0x28, 0xFB, 0x80, + 0x80, 0x0C, 0x6A, 0x5E, 0xDA, 0x1D, 0x8D, 0x38, 0xE6, 0xD4, 0x61, 0xD5, 0x66, 0x82, 0x7C, 0x3E, + 0xF8, 0x30, 0xA6, 0xE1, 0xAA, 0x1E, 0xB0, 0xA0, 0x1E, 0x77, 0xD7, 0xA7, 0xED, 0x97, 0x9E, 0xA3, + 0xFD, 0x6F, 0xA1, 0x68, 0xBB, 0xC5, 0x89, 0x75, 0xE3, 0x65, 0x43, 0x67, 0x4E, 0x11, 0x77, 0x40, + 0x5F, 0xA1, 0x48, 0x3F, 0x9E, 0x23, 0xB0, 0x0F, 0x45, 0x68, 0x52, 0x0B, 0x8A, 0x73, 0x2B, 0x01, + 0x35, 0x2B, 0xAC, 0xFA, 0x9B, 0x1B, 0x9B, 0xA2, 0x46, 0xAE, 0x78, 0x05, 0xE8, 0xAC, 0xB7, 0xB4, + 0x01, 0xD0, 0x3D, 0x5A, 0x76, 0x4F, 0x8D, 0x89, 0x94, 0x61, 0x9D, 0xBC, 0xA0, 0xD6, 0xF9, 0x48, + 0xF1, 0x0F, 0xF9, 0x89, 0x4A, 0xCD, 0xAB, 0x53, 0x86, 0x4D, 0x4E, 0xF4, 0x35, 0x8B, 0x57, 0x64, + 0x5A, 0x5F, 0x52, 0xD3, 0xF7, 0x1F, 0x17, 0xC0, 0xA2, 0x8C, 0x21, 0x69, 0x4A, 0x2B, 0x30, 0x3F, + 0x0F, 0x37, 0x56, 0xE8, 0xE3, 0x6E, 0x5C, 0xEA, 0x98, 0x71, 0x12, 0xF0, 0x28, 0xAD, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xA3, 0x81, 0xA9, 0x30, 0x81, 0xA6, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, + 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, + 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, + 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC9, 0xAA, 0x84, 0x6B, 0x06, 0xB8, 0x76, 0xE2, 0x96, 0x4F, 0xE7, + 0x27, 0x02, 0xD7, 0x2E, 0x3B, 0xDA, 0xF7, 0xB0, 0x18, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x2B, 0xD0, 0x69, 0x47, 0x94, 0x76, 0x09, 0xFE, 0xF4, 0x6B, + 0x8D, 0x2E, 0x40, 0xA6, 0xF7, 0x47, 0x4D, 0x7F, 0x08, 0x5E, 0x30, 0x43, 0x06, 0x03, 0x55, 0x1D, + 0x1F, 0x04, 0x3C, 0x30, 0x3A, 0x30, 0x38, 0xA0, 0x36, 0xA0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, + 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x61, 0x70, 0x70, 0x6C, 0x65, 0x2E, 0x63, 0x6F, + 0x6D, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x61, 0x75, 0x74, + 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x2F, 0x72, 0x6F, 0x6F, 0x74, 0x2E, 0x63, 0x72, 0x6C, 0x30, + 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x01, 0x00, 0xC5, 0x74, 0x7A, 0x7E, 0x5C, 0x75, 0x0E, 0xD3, 0x8A, 0x1C, 0x8D, 0x26, 0x20, + 0xDF, 0x1F, 0xC3, 0x04, 0x0E, 0x81, 0x1E, 0xE2, 0x13, 0x85, 0xB7, 0x64, 0xE3, 0x97, 0x5D, 0x46, + 0x27, 0x1D, 0x08, 0x98, 0x77, 0xA5, 0xC3, 0x9F, 0x63, 0x84, 0xD1, 0x66, 0x4F, 0x0A, 0xE8, 0x13, + 0xF6, 0xE5, 0x94, 0x07, 0xB0, 0x06, 0xC5, 0x56, 0xEB, 0x04, 0x4B, 0xD2, 0xD0, 0x1D, 0xB4, 0xE1, + 0xB6, 0x2D, 0x30, 0x8C, 0x61, 0xCE, 0xC2, 0x54, 0xC5, 0xAD, 0xE2, 0x43, 0x33, 0x1F, 0x23, 0x21, + 0xCB, 0xBD, 0xFD, 0x35, 0x7F, 0x5F, 0xEC, 0x31, 0x0D, 0x03, 0xA6, 0x39, 0x28, 0x55, 0xBC, 0x23, + 0x78, 0xB4, 0x03, 0xF8, 0x24, 0xEB, 0x0D, 0x24, 0xB7, 0xAA, 0x3A, 0xCB, 0x7C, 0x02, 0x8F, 0xD5, + 0x86, 0x96, 0xA3, 0xE7, 0x8A, 0xF4, 0x8F, 0x84, 0xF7, 0x57, 0xF7, 0x8C, 0xA0, 0xF5, 0xAE, 0x9F, + 0x8F, 0x31, 0x62, 0x4F, 0xA7, 0xB3, 0x5E, 0x4B, 0xC3, 0x20, 0xA3, 0x40, 0xFA, 0xED, 0x13, 0x70, + 0x77, 0xAB, 0x59, 0x65, 0x89, 0x6B, 0xFD, 0xA9, 0x92, 0x9B, 0xFB, 0x54, 0xB1, 0x25, 0x37, 0xE0, + 0x7C, 0x49, 0x8F, 0x86, 0x3C, 0x99, 0xF4, 0x17, 0x11, 0x3D, 0x2E, 0x41, 0x7D, 0x00, 0x98, 0xB4, + 0x1A, 0xA4, 0xEC, 0x5F, 0xE7, 0xC6, 0xC9, 0xE8, 0x90, 0x01, 0x2F, 0xB5, 0xF3, 0x4C, 0x6E, 0x4F, + 0x36, 0xBC, 0x7D, 0xCF, 0x56, 0x6C, 0x9B, 0xEB, 0xEB, 0x8B, 0xCE, 0x02, 0xE1, 0x82, 0xA0, 0x00, + 0x0A, 0x10, 0x33, 0x06, 0xEB, 0xD5, 0x5E, 0xC3, 0x62, 0xE2, 0xBA, 0xF5, 0x25, 0x7D, 0xFC, 0xDA, + 0xE1, 0x49, 0x3D, 0x9F, 0xE9, 0x9F, 0x12, 0xDA, 0xF9, 0x7D, 0x22, 0x7C, 0x8F, 0x13, 0xCA, 0x06, + 0x34, 0xD7, 0x4C, 0xF6, 0x40, 0x71, 0x78, 0xB1, 0xAF, 0xEC, 0xC1, 0x66, 0xDF, 0xAE, 0xAD, 0x3B, + 0xCC, 0x0E, 0xC0 +}; + +/* + subject= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple iPod Accessories Certification Authority + issuer= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA + serial=16 + */ +const uint8_t _iAP2CA[] = { + 0x30, 0x82, 0x03, 0xfe, 0x30, 0x82, 0x02, 0xe6, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x16, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, + 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x32, 0x31, 0x34, 0x32, 0x32, 0x31, + 0x38, 0x30, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x32, 0x31, 0x34, 0x32, 0x32, 0x31, 0x38, + 0x30, 0x38, 0x5a, 0x30, 0x81, 0x83, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x13, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x20, 0x69, 0x50, 0x6f, 0x64, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x69, 0x65, + 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, + 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa1, 0xf6, 0xca, 0xdb, 0x3d, 0x4a, + 0x5a, 0x3e, 0xef, 0x74, 0x78, 0xf1, 0xb7, 0xb0, 0x32, 0x82, 0x1f, 0x90, 0xc6, 0x08, 0xdf, 0xaa, + 0x3b, 0xd2, 0xcb, 0x0f, 0xe6, 0x37, 0x13, 0xf8, 0xff, 0x71, 0xfc, 0x28, 0x86, 0x24, 0x36, 0x85, + 0x3f, 0xd0, 0x1d, 0x9c, 0xd0, 0x9c, 0xb2, 0x5d, 0x20, 0x41, 0xdc, 0xb0, 0xd8, 0xa8, 0x86, 0x3c, + 0x42, 0x3c, 0xbe, 0x5a, 0x48, 0xdf, 0x34, 0x74, 0x9a, 0x61, 0x05, 0x0d, 0xce, 0xc8, 0x25, 0x14, + 0xc8, 0x0a, 0xcd, 0xbd, 0xba, 0x12, 0x1b, 0x3b, 0x41, 0x13, 0x8e, 0x38, 0x65, 0x1d, 0xac, 0x1d, + 0xd5, 0x38, 0x95, 0x9d, 0x3a, 0xd0, 0x79, 0x5c, 0x66, 0x9c, 0x47, 0x4b, 0x2c, 0xb8, 0x44, 0x3b, + 0x7e, 0x8b, 0x68, 0x39, 0x3e, 0x46, 0xc1, 0xb8, 0xc0, 0x85, 0xd6, 0x84, 0xfb, 0x0e, 0xa6, 0xdd, + 0x34, 0x06, 0xda, 0x1c, 0x78, 0xd9, 0xc4, 0x63, 0x11, 0x1b, 0xcf, 0x20, 0x15, 0xd2, 0x7a, 0xef, + 0x60, 0x40, 0xdf, 0xba, 0xe0, 0x05, 0x45, 0x41, 0x82, 0x0e, 0x9b, 0x78, 0x2d, 0x2a, 0xb4, 0x94, + 0xb5, 0xca, 0x79, 0xcd, 0xdb, 0xb5, 0x95, 0x02, 0xbe, 0x55, 0x2c, 0x36, 0x21, 0xaf, 0x6e, 0x39, + 0xb6, 0x76, 0x5a, 0xec, 0x5d, 0x6a, 0xf3, 0xcc, 0xfa, 0x90, 0x8a, 0x15, 0x77, 0xbb, 0xba, 0x5c, + 0x2b, 0xa1, 0x87, 0xf8, 0x0e, 0x70, 0x5d, 0x23, 0x01, 0x08, 0x79, 0xef, 0xab, 0xd7, 0x91, 0x38, + 0x81, 0x35, 0xb3, 0x07, 0xd4, 0x79, 0xa2, 0x25, 0xa7, 0xf7, 0x90, 0x75, 0xeb, 0xeb, 0x71, 0xa2, + 0xd0, 0xc1, 0xab, 0x02, 0x06, 0xf9, 0x07, 0x08, 0x97, 0x35, 0xda, 0x7e, 0x4d, 0x61, 0x51, 0x75, + 0x92, 0xf6, 0x19, 0xf5, 0xdf, 0xfb, 0xc9, 0xa5, 0x4e, 0x9b, 0x8a, 0x14, 0x11, 0x4c, 0x10, 0x74, + 0x83, 0xaf, 0x2f, 0xfc, 0xb6, 0xd6, 0x6b, 0x57, 0x46, 0x1d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, + 0x81, 0x9c, 0x30, 0x81, 0x99, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, + 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, + 0x14, 0xff, 0x4b, 0x1a, 0x43, 0x9a, 0xf5, 0x19, 0x96, 0xab, 0x18, 0x00, 0x2b, 0x61, 0xc9, 0xee, + 0x40, 0x9d, 0x8e, 0xc7, 0x04, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, + 0x80, 0x14, 0x2b, 0xd0, 0x69, 0x47, 0x94, 0x76, 0x09, 0xfe, 0xf4, 0x6b, 0x8d, 0x2e, 0x40, 0xa6, + 0xf7, 0x47, 0x4d, 0x7f, 0x08, 0x5e, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2f, 0x30, + 0x2d, 0x30, 0x2b, 0xa0, 0x29, 0xa0, 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x63, 0x61, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x01, 0x00, 0x9e, 0xb4, 0xaf, 0x3d, 0xb7, 0x61, 0xe0, 0x64, 0xc3, 0x86, 0x27, 0xd2, 0x3f, 0xe9, + 0xe4, 0x08, 0x50, 0x77, 0xa2, 0x81, 0x09, 0x8c, 0x7d, 0xb7, 0xd0, 0x54, 0x52, 0xde, 0xfe, 0x8d, + 0x48, 0xf2, 0x86, 0xc1, 0x17, 0xe5, 0x1a, 0x5d, 0x29, 0x20, 0xd3, 0x81, 0xca, 0xee, 0xc8, 0xa3, + 0x61, 0xb3, 0x90, 0x9f, 0x73, 0xe8, 0xe3, 0xc8, 0xbc, 0xa7, 0x12, 0xb4, 0x8c, 0x2d, 0xaa, 0xf5, + 0x39, 0x27, 0x19, 0xf5, 0xfb, 0xf9, 0x14, 0x7b, 0x3a, 0xb4, 0x78, 0x1a, 0x9a, 0x4c, 0x96, 0xeb, + 0x36, 0xc7, 0xfe, 0xb5, 0xe7, 0x14, 0x7e, 0x6c, 0x4f, 0xa8, 0x22, 0xba, 0x23, 0x82, 0xf0, 0xce, + 0xfa, 0x09, 0x7b, 0x8a, 0x0d, 0x5a, 0x61, 0x21, 0x74, 0x7a, 0xca, 0xc2, 0xca, 0x6b, 0xc2, 0x63, + 0x40, 0x77, 0x23, 0x2b, 0x8f, 0xa0, 0x29, 0x5c, 0xeb, 0xad, 0xfc, 0xcc, 0xdc, 0x5a, 0x42, 0x42, + 0x2e, 0xc8, 0x4f, 0xb4, 0x90, 0xd2, 0x6e, 0xfc, 0x4f, 0x8a, 0x0e, 0xa8, 0xb7, 0x83, 0x5c, 0x5c, + 0x12, 0x02, 0x15, 0x17, 0xa8, 0x65, 0x7d, 0x5a, 0x28, 0x2b, 0x69, 0x5f, 0x76, 0x9e, 0x2f, 0xe0, + 0x9e, 0xec, 0x41, 0x57, 0x97, 0xc5, 0x0f, 0x9a, 0xa0, 0x70, 0xb8, 0x2c, 0x8f, 0x6d, 0x80, 0xb5, + 0x46, 0xec, 0xe8, 0x58, 0xb0, 0x04, 0x40, 0x3c, 0xc3, 0x62, 0x8a, 0x0a, 0xb7, 0xa9, 0x5b, 0x58, + 0x7d, 0xea, 0x7b, 0x8c, 0xff, 0xf7, 0xf8, 0xbf, 0xd2, 0xc1, 0x95, 0x76, 0x05, 0xd7, 0x5d, 0x16, + 0x4d, 0xf1, 0x1e, 0x7d, 0xb2, 0x81, 0x10, 0xe8, 0x47, 0x74, 0x12, 0xf1, 0xe6, 0x60, 0x3f, 0xe3, + 0x6f, 0xb6, 0xa4, 0xc6, 0xe1, 0x08, 0xb3, 0xe4, 0x7d, 0x98, 0xf1, 0xfb, 0xd0, 0x42, 0xb2, 0x59, + 0x26, 0x17, 0xfb, 0x72, 0x6b, 0x05, 0xa9, 0xac, 0x94, 0xbf, 0x88, 0x0a, 0x09, 0xef, 0xd2, 0xa5, + 0x25, 0xae +}; + +/* + subject= /C=US/O=Apple Inc./OU=Apple iPod Accessories/CN=IPA_3333AA070313AA06AA0007AA000001 + issuer= /C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple iPod Accessories Certification Authority + serial=3333AA070313AA06AA0007AA000001 + */ +const uint8_t _leaf0[] = { + 0x30,0x82,0x03,0x59,0x30,0x82,0x02,0x41,0xA0,0x03,0x02,0x01,0x02,0x02,0x0F,0x33, + 0x33,0xAA,0x07,0x03,0x13,0xAA,0x06,0xAA,0x00,0x07,0xAA,0x00,0x00,0x01,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x83, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, + 0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x37,0x30,0x35,0x06,0x03, + 0x55,0x04,0x03,0x13,0x2E,0x41,0x70,0x70,0x6C,0x65,0x20,0x69,0x50,0x6F,0x64,0x20, + 0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72,0x74, + 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72, + 0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x30,0x37,0x30,0x33,0x31,0x33,0x32,0x31,0x31, + 0x37,0x32,0x36,0x5A,0x17,0x0D,0x31,0x35,0x30,0x33,0x31,0x33,0x32,0x31,0x31,0x37, + 0x32,0x36,0x5A,0x30,0x70,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x0B, + 0x13,0x16,0x41,0x70,0x70,0x6C,0x65,0x20,0x69,0x50,0x6F,0x64,0x20,0x41,0x63,0x63, + 0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x31,0x2B,0x30,0x29,0x06,0x03,0x55,0x04, + 0x03,0x14,0x22,0x49,0x50,0x41,0x5F,0x33,0x33,0x33,0x33,0x41,0x41,0x30,0x37,0x30, + 0x33,0x31,0x33,0x41,0x41,0x30,0x36,0x41,0x41,0x30,0x30,0x30,0x37,0x41,0x41,0x30, + 0x30,0x30,0x30,0x30,0x31,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81,0x89,0x02,0x81, + 0x81,0x00,0xCB,0x76,0xE3,0xA7,0x3B,0xF0,0x42,0xD5,0x48,0x93,0x62,0x0A,0x10,0x17, + 0x37,0xB9,0xC8,0x52,0xDD,0xDE,0x8A,0x40,0xA0,0xF8,0xDA,0xE8,0x64,0x0A,0x67,0xF5, + 0x8F,0x91,0xA6,0xB5,0x93,0xE8,0xC2,0x28,0xB3,0xAC,0xF4,0xAF,0x40,0xC6,0xBB,0x49, + 0x85,0x5A,0x7C,0x1B,0x42,0xC3,0x3C,0xC8,0x95,0x36,0x0B,0x85,0xBE,0x36,0x85,0xB7, + 0x0D,0x04,0x0E,0x4E,0x4C,0x3C,0x28,0xFB,0x03,0x78,0x42,0xAC,0xF1,0x9E,0xAD,0x22, + 0x7C,0x86,0xD3,0xA6,0x0E,0xC8,0x42,0xBD,0x9C,0x7C,0xD9,0x2C,0xE4,0x1F,0xD5,0x91, + 0x4E,0x9D,0xB7,0xFF,0x83,0x2E,0x06,0x3E,0xD4,0x95,0xE4,0x0E,0x8E,0x2D,0x46,0x8F, + 0xCF,0xE6,0x32,0xCE,0x47,0x56,0x57,0x97,0x1A,0x87,0xC8,0xD4,0xF3,0x32,0xF9,0xD6, + 0x80,0x83,0x02,0x03,0x01,0x00,0x01,0xA3,0x60,0x30,0x5E,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x03,0xB8,0x30,0x0C,0x06,0x03,0x55, + 0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, + 0x04,0x16,0x04,0x14,0x71,0x53,0x3F,0x7F,0x72,0x47,0xBB,0xE3,0x60,0xD9,0xD9,0xD8, + 0x39,0x6D,0x8D,0x33,0xA3,0x74,0xC3,0x59,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04, + 0x18,0x30,0x16,0x80,0x14,0xFF,0x4B,0x1A,0x43,0x9A,0xF5,0x19,0x96,0xAB,0x18,0x00, + 0x2B,0x61,0xC9,0xEE,0x40,0x9D,0x8E,0xC7,0x04,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x0F,0xD9,0x40, + 0x27,0x1C,0x00,0x01,0x2D,0x4C,0x67,0xA6,0x0D,0x74,0xA8,0xBD,0xF6,0x97,0x16,0x46, + 0xB1,0x02,0xD7,0x51,0xF6,0x02,0xC1,0x0F,0xB1,0x34,0x8A,0xCB,0xB7,0x81,0x29,0xBD, + 0x7B,0x67,0xA3,0xE6,0x49,0x3D,0xBB,0x3E,0x0D,0x26,0x75,0x1D,0xDC,0x37,0xA7,0x38, + 0x86,0xD8,0x81,0x5A,0xC5,0xAF,0xCD,0xD6,0xCB,0x0E,0xBA,0x53,0x28,0x57,0x83,0x16, + 0x23,0xCC,0x11,0x01,0x0E,0x18,0x4D,0xFE,0x29,0x1B,0x7C,0x3F,0x33,0xD5,0x4B,0x7C, + 0x74,0xB5,0xFD,0x62,0xC5,0x45,0xEC,0x08,0xE4,0xC0,0xD3,0xCE,0xBA,0xB0,0x04,0x0D, + 0x7C,0xEF,0x5C,0x3F,0x92,0xDC,0x45,0x24,0xA3,0x02,0xFE,0xA4,0x60,0x15,0x28,0x43, + 0x1B,0x46,0x51,0x1F,0x9F,0x0D,0x89,0x62,0x6C,0x30,0xE2,0x2B,0xF7,0x8C,0x7B,0xD6, + 0xE3,0x71,0x11,0xD1,0xE5,0xF5,0x83,0xAE,0xD8,0xEB,0x5A,0x40,0xB6,0x09,0x00,0x53, + 0x8F,0xAF,0x4D,0xA7,0x3D,0x50,0xB0,0x1B,0x88,0x6B,0x9D,0x18,0x79,0x1E,0xCB,0xBF, + 0x86,0xBA,0xDE,0x48,0x28,0x3A,0x53,0x17,0x59,0x2D,0xC2,0x98,0xE0,0xE7,0x54,0x03, + 0xD0,0x1D,0xFB,0xC1,0xCA,0x68,0x43,0x2D,0x23,0xC3,0xA3,0x12,0x04,0x89,0x77,0x41, + 0xB8,0x96,0x3F,0xDC,0x00,0x73,0x07,0xD0,0xA6,0x8C,0x35,0x45,0xB4,0x07,0x69,0xF8, + 0x79,0x6E,0x7B,0x04,0x6D,0x0F,0x95,0x20,0x5B,0x76,0x17,0x78,0x91,0x91,0xA4,0xBE, + 0x6D,0x5C,0xE9,0x71,0x12,0x68,0x6C,0xB7,0xA4,0x36,0xC3,0x82,0xCF,0x65,0x7D,0xE3, + 0x50,0x92,0x02,0x54,0x3D,0xFE,0x16,0x8D,0x4F,0xE0,0x11,0xE0,0xB5, +}; + +/* + subject= /C=US/O=Apple Computer, Inc./OU=Apple Computer iPod Accessories/CN=IPA_3333AA070313AA06AA0011AA000001 + issuer= /C=US/O=Apple Computer, Inc./OU=Apple Computer Certificate Authority/CN=Apple iPod Accessories Certificate Authority + serial=3333AA070313AA06AA0011AA000001 + */ +const uint8_t _leaf1[] = { + 0x30,0x82,0x03,0x7C,0x30,0x82,0x02,0x64,0xA0,0x03,0x02,0x01,0x02,0x02,0x0F,0x33, + 0x33,0xAA,0x07,0x03,0x13,0xAA,0x06,0xAA,0x00,0x11,0xAA,0x00,0x00,0x01,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x92, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0A,0x13,0x14,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F, + 0x6D,0x70,0x75,0x74,0x65,0x72,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x2D,0x30,0x2B, + 0x06,0x03,0x55,0x04,0x0B,0x13,0x24,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x6D, + 0x70,0x75,0x74,0x65,0x72,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, + 0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x35,0x30,0x33,0x06, + 0x03,0x55,0x04,0x03,0x13,0x2C,0x41,0x70,0x70,0x6C,0x65,0x20,0x69,0x50,0x6F,0x64, + 0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72, + 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x30,0x1E,0x17,0x0D,0x30,0x37,0x30,0x33,0x31,0x33,0x32,0x31,0x32,0x37, + 0x33,0x35,0x5A,0x17,0x0D,0x31,0x35,0x30,0x33,0x31,0x33,0x32,0x31,0x32,0x37,0x33, + 0x35,0x5A,0x30,0x81,0x83,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0A,0x13,0x14,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x43,0x6F,0x6D,0x70,0x75,0x74,0x65,0x72,0x2C,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0B,0x13,0x1F,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x43,0x6F,0x6D,0x70,0x75,0x74,0x65,0x72,0x20,0x69,0x50,0x6F,0x64,0x20, + 0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x31,0x2B,0x30,0x29,0x06, + 0x03,0x55,0x04,0x03,0x14,0x22,0x49,0x50,0x41,0x5F,0x33,0x33,0x33,0x33,0x41,0x41, + 0x30,0x37,0x30,0x33,0x31,0x33,0x41,0x41,0x30,0x36,0x41,0x41,0x30,0x30,0x31,0x31, + 0x41,0x41,0x30,0x30,0x30,0x30,0x30,0x31,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81, + 0x89,0x02,0x81,0x81,0x00,0x91,0x66,0xDB,0x40,0x0E,0xC4,0xE5,0x8D,0xB3,0x86,0xFD, + 0x36,0x06,0x38,0xCC,0x83,0xA4,0xD7,0xFF,0x14,0xA6,0x77,0x3B,0x63,0x7A,0xAE,0xE8, + 0x76,0xDB,0xD8,0x2F,0x7C,0x70,0x84,0xE8,0x0A,0x63,0x33,0xA7,0xCB,0x0E,0x17,0x94, + 0x80,0x39,0xB7,0xE6,0x16,0x0C,0xA7,0x1F,0x7D,0x11,0x02,0x76,0xDA,0x1D,0x0B,0xED, + 0x8D,0x2A,0xEB,0x60,0xCF,0x55,0x85,0xBD,0x92,0x32,0xC9,0xC9,0xB2,0x16,0xEA,0xBA, + 0xA8,0xC8,0x8C,0xE4,0x93,0x7A,0x0A,0xAA,0x40,0x24,0x0F,0x96,0xC7,0xC5,0x95,0x21, + 0xD9,0xB0,0x98,0x51,0x8D,0xE4,0xC6,0x63,0x6E,0x73,0x92,0xAB,0x77,0xE9,0x71,0xAF, + 0x0E,0x50,0xA3,0xB4,0x68,0xA8,0x82,0x67,0x88,0xF9,0xA5,0xC8,0x68,0x7B,0x49,0x36, + 0x72,0xEE,0x06,0x1A,0x95,0x02,0x03,0x01,0x00,0x01,0xA3,0x60,0x30,0x5E,0x30,0x0E, + 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x03,0xB8,0x30,0x0C, + 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xDE,0x6A,0x9D,0x5E,0x83,0x77,0xA6,0xFE,0xA9, + 0x65,0x30,0x5F,0x98,0xE8,0xA4,0x7C,0xDE,0x0A,0xB3,0x48,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xC9,0xAA,0x84,0x6B,0x06,0xB8,0x76,0xE2, + 0x96,0x4F,0xE7,0x27,0x02,0xD7,0x2E,0x3B,0xDA,0xF7,0xB0,0x18,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00, + 0x96,0x07,0x3B,0x68,0xE8,0x2F,0x97,0xA5,0x42,0xFF,0x9D,0x34,0xFD,0x3A,0xD2,0x01, + 0x69,0xD7,0x67,0x46,0x9A,0x7D,0x56,0xE0,0x7F,0x91,0xEE,0xC3,0x5C,0xD2,0x51,0x54, + 0xE3,0xD2,0x17,0x08,0xB2,0xBC,0xCD,0x85,0xF8,0x8E,0xAD,0x49,0x53,0xE1,0x07,0x5A, + 0x9B,0x03,0xA2,0x35,0xCA,0xCF,0xC6,0xB6,0xC9,0x71,0x53,0xBC,0x2E,0xA3,0x1B,0x03, + 0x5C,0x55,0x57,0xA3,0x10,0xBC,0x15,0x81,0xD5,0xE6,0xA3,0xB8,0x21,0x50,0x2E,0x44, + 0xD4,0xEA,0x71,0x17,0xE5,0xFC,0x71,0xC3,0xF9,0xE8,0x99,0x98,0xF3,0x5F,0xFF,0xB2, + 0x8E,0xC7,0x56,0x74,0x46,0xEC,0x63,0x3F,0x4A,0xA6,0x9C,0x85,0x7C,0x08,0x61,0x32, + 0xB7,0x35,0x36,0x01,0x0C,0xCE,0xD8,0xE3,0xC4,0x6A,0x0D,0xF2,0x25,0x56,0x59,0xBA, + 0x88,0x1B,0xB4,0x21,0x80,0xB9,0x69,0x9E,0x93,0xF7,0xB1,0x22,0x19,0x8B,0x8B,0xD8, + 0xBD,0xDC,0x0C,0xA7,0x69,0x4B,0x5B,0xE9,0xD7,0x7A,0x1D,0xEF,0x37,0x0D,0x24,0xDC, + 0xA7,0x67,0xBC,0x0D,0xE1,0x0D,0x28,0xA0,0xB8,0x83,0x28,0x6A,0x8A,0xD6,0x59,0x40, + 0x4A,0xF1,0x06,0x0D,0x75,0xB9,0x81,0x4B,0x4C,0x2D,0xCB,0x57,0xE0,0x7A,0x32,0x5B, + 0xE0,0xEA,0xDD,0x0C,0xDC,0xFD,0x5E,0x7E,0xB0,0x77,0x07,0x0D,0xA7,0x14,0x0B,0x41, + 0x94,0x4F,0x10,0x3E,0xA5,0x0C,0x68,0x3F,0x8C,0x70,0x5C,0x29,0xB7,0xE9,0xFC,0x09, + 0x35,0x5C,0x2D,0xB3,0xA9,0x4F,0x51,0xB0,0xA7,0xD5,0xAD,0x3F,0xE2,0xA2,0x4C,0x73, + 0xFC,0x2F,0x6E,0x21,0x38,0xE5,0xBB,0x8B,0x57,0x51,0xE5,0x9B,0x8B,0xA6,0xAA,0x0B +}; + +/* subject:/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Accessories Certification Authority - 00000000 */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Accessories Certification Authority - 00000000 */ +const uint8_t _v3ca[618]={ + 0x30,0x82,0x02,0x66,0x30,0x82,0x02,0x0C,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x00, + 0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x89,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20, + 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x3D,0x30,0x3B,0x06,0x03,0x55, + 0x04,0x03,0x13,0x34,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65,0x73,0x73, + 0x6F,0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74, + 0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x2D,0x20, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x32, + 0x32,0x34,0x30,0x30,0x31,0x39,0x33,0x33,0x5A,0x17,0x0D,0x34,0x36,0x30,0x32,0x32, + 0x34,0x30,0x30,0x31,0x39,0x33,0x33,0x5A,0x30,0x81,0x89,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30, + 0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65, + 0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68, + 0x6F,0x72,0x69,0x74,0x79,0x31,0x3D,0x30,0x3B,0x06,0x03,0x55,0x04,0x03,0x13,0x34, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65, + 0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20, + 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x2D,0x20,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02, + 0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xF3, + 0xA9,0x19,0x0B,0xFA,0xF5,0xAB,0x2A,0x99,0xC0,0x6A,0x08,0x7E,0x6C,0x21,0x88,0x88, + 0x3C,0xDC,0xE0,0xB1,0x80,0x11,0x00,0x35,0xF5,0x03,0x6B,0x82,0x81,0xAD,0x73,0x8B, + 0x76,0xE7,0xD5,0x6B,0x7E,0x6A,0xE4,0xF6,0x10,0x7A,0x30,0x32,0xC9,0xBE,0x75,0x28, + 0xBA,0x7C,0xF7,0x02,0x19,0x1C,0x18,0x68,0xBB,0x2F,0xEC,0xEC,0x06,0x66,0xF9,0xA3, + 0x63,0x30,0x61,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30, + 0x03,0x01,0x01,0xFF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, + 0x03,0x02,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x69, + 0x96,0xE3,0x5B,0x36,0x2A,0xAE,0x8B,0xB1,0x02,0x94,0x1D,0xA6,0x13,0x5B,0xB2,0x6E, + 0xE9,0x9B,0x31,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, + 0x69,0x96,0xE3,0x5B,0x36,0x2A,0xAE,0x8B,0xB1,0x02,0x94,0x1D,0xA6,0x13,0x5B,0xB2, + 0x6E,0xE9,0x9B,0x31,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02, + 0x03,0x48,0x00,0x30,0x45,0x02,0x20,0x7B,0x11,0x63,0x57,0xFE,0x7B,0xA3,0xF7,0xF2, + 0x32,0x4D,0x04,0x21,0x8F,0x97,0xDB,0xF5,0xE8,0x74,0x3E,0x2A,0x3F,0x18,0x1A,0xCC, + 0xE4,0x7A,0xB5,0x73,0x68,0x9C,0xB3,0x02,0x21,0x00,0xEC,0x33,0xC9,0xF9,0xE8,0xC1, + 0x40,0x10,0xD8,0x88,0xF7,0x2B,0xC3,0x30,0x8F,0xF1,0x22,0xFF,0x66,0x32,0xB4,0x69, + 0x05,0xFA,0x92,0x9C,0xB6,0xEF,0x6C,0x61,0xE7,0xFA, +}; + +/* subject:/C=US/O=Apple Inc./OU=Apple Accessories/CN=IPA_019256C98E8DCE6074DEE81A0002A756 */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Accessories Certification Authority - 00000000 */ +const unsigned char _v3leaf[558]={ + 0x30,0x82,0x02,0x2A,0x30,0x82,0x01,0xD1,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x01, + 0x92,0x56,0xC9,0x8E,0x8D,0xCE,0x60,0x74,0xDE,0xE8,0x1A,0x00,0x02,0xA7,0x56,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x89,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x3D,0x30,0x3B,0x06,0x03,0x55,0x04, + 0x03,0x13,0x34,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F, + 0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x2D,0x20,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x34,0x31, + 0x34,0x32,0x30,0x34,0x30,0x33,0x31,0x5A,0x17,0x0D,0x34,0x39,0x31,0x32,0x33,0x31, + 0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x6D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1A,0x30,0x18,0x06, + 0x03,0x55,0x04,0x0B,0x13,0x11,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65, + 0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04,0x03, + 0x14,0x24,0x49,0x50,0x41,0x5F,0x30,0x31,0x39,0x32,0x35,0x36,0x43,0x39,0x38,0x45, + 0x38,0x44,0x43,0x45,0x36,0x30,0x37,0x34,0x44,0x45,0x45,0x38,0x31,0x41,0x30,0x30, + 0x30,0x32,0x41,0x37,0x35,0x36,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE, + 0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00, + 0x04,0xD7,0x21,0x4D,0x08,0x7F,0xEA,0x11,0x15,0xEA,0xF3,0x4D,0x9D,0x86,0x79,0x42, + 0xE0,0xA2,0x72,0x68,0x08,0xD5,0xF4,0xD2,0x8F,0x79,0x20,0x45,0xE5,0xFD,0xE8,0x8E, + 0xFE,0x08,0xD0,0x72,0x0B,0x88,0x9F,0xDD,0x8B,0xC3,0x55,0x91,0x09,0xD1,0xFB,0x9E, + 0x8B,0xFA,0x7A,0x64,0xD5,0x70,0xD6,0x33,0xB4,0xAF,0x80,0xA4,0xAB,0x0A,0xE3,0x3D, + 0x23,0xA3,0x36,0x30,0x34,0x30,0x32,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64, + 0x06,0x24,0x01,0x01,0xFF,0x04,0x22,0x04,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48, + 0xCE,0x3D,0x04,0x03,0x02,0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x5E,0xDD,0x00,0x88, + 0x4C,0x1F,0x58,0xF1,0x44,0xC9,0x0C,0xE1,0x9B,0x54,0x1F,0xB9,0x20,0xC1,0xDE,0x00, + 0x9F,0xEC,0xA8,0xDD,0x5E,0xDC,0x2A,0xF4,0xFC,0xFC,0x36,0x8A,0x02,0x20,0x0A,0x4C, + 0x2F,0x9D,0xA0,0x4C,0xEB,0xA0,0xF1,0xAF,0xAE,0xDA,0x0F,0x2C,0x93,0x22,0x0B,0x74, + 0xD5,0x2B,0x80,0x3D,0x81,0x33,0x33,0xB6,0x6C,0xFB,0xC0,0xB5,0x70,0x9B, +}; + +/* subject:/C=US/O=Apple Inc./OU=Apple Accessories/CN=IPA_204E6F2CB683A518F7726D190000C5DA */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Accessories Certification Authority - 00000002 */ +const unsigned char _malformedV3Leaf[] = { + 0x30,0x82,0x02,0x2B,0x30,0x82,0x01,0xD1,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x20, + 0x4E,0x6F,0x2C,0xB6,0x83,0xA5,0x18,0xF7,0x72,0x6D,0x19,0x00,0x00,0xC5,0xDA,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x89,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x3D,0x30,0x3B,0x06,0x03,0x55,0x04, + 0x03,0x13,0x34,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F, + 0x72,0x69,0x65,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x20,0x2D,0x20,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x32,0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x33, + 0x31,0x31,0x31,0x35,0x31,0x31,0x37,0x5A,0x17,0x0D,0x34,0x39,0x31,0x32,0x33,0x31, + 0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x6D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1A,0x30,0x18,0x06, + 0x03,0x55,0x04,0x0B,0x13,0x11,0x41,0x70,0x70,0x6C,0x65,0x20,0x41,0x63,0x63,0x65, + 0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04,0x03, + 0x14,0x24,0x49,0x50,0x41,0x5F,0x32,0x30,0x34,0x45,0x36,0x46,0x32,0x43,0x42,0x36, + 0x38,0x33,0x41,0x35,0x31,0x38,0x46,0x37,0x37,0x32,0x36,0x44,0x31,0x39,0x30,0x30, + 0x30,0x30,0x43,0x35,0x44,0x41,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE, + 0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00, + 0x04,0x9A,0x21,0x88,0x3D,0x3B,0xCD,0xA9,0x9F,0x1B,0xC6,0x5F,0x47,0x5D,0xA8,0xEB, + 0x52,0x18,0x9F,0x1E,0xF3,0xD8,0x7C,0xB6,0x1D,0x39,0x7A,0x8C,0xE0,0xDB,0x79,0xB4, + 0x9D,0x37,0x16,0xB8,0x6F,0x1C,0x29,0x42,0x59,0xA5,0x4E,0xA2,0x9A,0xB1,0x0E,0xC4, + 0x55,0xCC,0x89,0x79,0x4A,0x9E,0xDB,0x95,0x7A,0xF3,0x3D,0x7F,0x58,0xAD,0xF7,0x61, + 0xB3,0xA3,0x36,0x30,0x34,0x30,0x32,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64, + 0x06,0x24,0x01,0x01,0xFF,0x04,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48, + 0xCE,0x3D,0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x20,0x80,0x6B,0x96,0x6C, + 0x83,0x04,0x29,0x68,0x52,0xF9,0x74,0x42,0x7C,0x49,0x81,0x39,0x53,0x91,0x53,0x0D, + 0x95,0xB7,0x4F,0x18,0xFC,0xA5,0x38,0x9A,0x55,0x68,0x53,0x02,0x02,0x21,0x00,0xF5, + 0xE4,0xF2,0xB7,0x0B,0x7F,0x43,0xFA,0xDB,0xC2,0x1A,0x05,0xEF,0xF9,0x0E,0x31,0xFC, + 0x0A,0xCB,0xCD,0x6C,0x03,0x8A,0x73,0x95,0x74,0xB1,0x57,0x03,0x09,0x55,0x8D, +}; + +/* subject:/CN=Test Accessories Software Authentication Root CA/OU=Apple Certification Authority/O=Apple Inc./C=US */ +/* issuer :/CN=Test Accessories Software Authentication Root CA/OU=Apple Certification Authority/O=Apple Inc./C=US */ +const uint8_t _iAPSWAuthTestRoot[584]={ + 0x30,0x82,0x02,0x44,0x30,0x82,0x01,0xEA,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x59, + 0x29,0x18,0xB6,0x20,0x80,0x90,0x94,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x30,0x81,0x85,0x31,0x39,0x30,0x37,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x30,0x54,0x65,0x73,0x74,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65, + 0x73,0x20,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x41,0x75,0x74,0x68,0x65, + 0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, + 0x41,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20, + 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31, + 0x37,0x31,0x31,0x30,0x39,0x30,0x30,0x31,0x35,0x31,0x32,0x5A,0x17,0x0D,0x33,0x37, + 0x31,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x81,0x85,0x31,0x39, + 0x30,0x37,0x06,0x03,0x55,0x04,0x03,0x0C,0x30,0x54,0x65,0x73,0x74,0x20,0x41,0x63, + 0x63,0x65,0x73,0x73,0x6F,0x72,0x69,0x65,0x73,0x20,0x53,0x6F,0x66,0x74,0x77,0x61, + 0x72,0x65,0x20,0x41,0x75,0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74, + 0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, + 0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x00,0x28, + 0x4C,0xD4,0xFA,0x57,0x5C,0xB5,0x62,0xE6,0x10,0x30,0x60,0xBB,0x4E,0x8E,0xE9,0x34, + 0x52,0xFC,0xAB,0x74,0x4C,0x62,0xDA,0xEE,0x66,0x47,0x5E,0x5D,0x0D,0x04,0x2A,0x22, + 0x49,0xC4,0xF0,0x2C,0x93,0xC6,0xA8,0x5E,0x26,0x69,0xAA,0x3C,0x43,0xF8,0x49,0xCC, + 0x89,0x03,0x98,0xB3,0x7A,0x90,0xC8,0x79,0xFD,0x5A,0x13,0xE7,0x26,0x8C,0xA3,0x42, + 0x30,0x40,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03, + 0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x6F,0x79, + 0x89,0xE2,0x11,0xB0,0x49,0xE2,0xC1,0x5C,0xC4,0xDC,0xC7,0xE0,0x62,0x9F,0x3B,0x0A, + 0xC6,0x8C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02, + 0x01,0x06,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48, + 0x00,0x30,0x45,0x02,0x21,0x00,0x9A,0x4F,0xA8,0xC3,0xC2,0x06,0x7D,0x86,0x3D,0x6F, + 0x9B,0x02,0xD7,0xBC,0xD6,0x28,0xE2,0x22,0xAA,0x90,0x62,0x73,0xED,0x91,0x34,0xD7, + 0x62,0xF0,0x4D,0xD7,0xD4,0x38,0x02,0x20,0x23,0x7B,0x01,0x88,0xBB,0xB9,0xF2,0x00, + 0x04,0x20,0x9B,0xC7,0x69,0x97,0x4B,0xAE,0xC6,0xB0,0x2E,0x93,0xE3,0x9B,0x50,0x8B, + 0xC8,0x1E,0xA4,0x94,0xF6,0x97,0x78,0x78, +}; + +/* subject:/CN=0/O=TestPPID1234 */ +/* issuer :/CN=Test Accessories Software Authentication Root CA/OU=Apple Certification Authority/O=Apple Inc./C=US */ +const uint8_t _malformed_iAPSWAuth_leaf[739]={ + 0x30,0x82,0x02,0xDF,0x30,0x82,0x02,0x85,0xA0,0x03,0x02,0x01,0x02,0x02,0x0A,0x12, + 0x34,0x56,0x78,0x90,0x12,0x34,0x56,0x78,0x90,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48, + 0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x85,0x31,0x39,0x30,0x37,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x30,0x54,0x65,0x73,0x74,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F,0x72, + 0x69,0x65,0x73,0x20,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x41,0x75,0x74, + 0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x52,0x6F,0x6F,0x74, + 0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17, + 0x0D,0x31,0x37,0x31,0x31,0x31,0x35,0x32,0x30,0x34,0x33,0x35,0x38,0x5A,0x17,0x0D, + 0x32,0x37,0x31,0x32,0x31,0x33,0x32,0x30,0x34,0x33,0x35,0x38,0x5A,0x30,0x23,0x31, + 0x0A,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x0C,0x01,0x30,0x31,0x15,0x30,0x13,0x06, + 0x03,0x55,0x04,0x0A,0x0C,0x0C,0x54,0x65,0x73,0x74,0x50,0x50,0x49,0x44,0x31,0x32, + 0x33,0x34,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06, + 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xC1,0xBD,0x0B, + 0x4E,0xBA,0xD3,0xC6,0x8F,0x70,0x39,0x73,0xBF,0x58,0xB7,0x75,0x02,0x41,0x60,0x62, + 0x70,0x6A,0x4D,0xA6,0x5C,0xF6,0xE7,0x5B,0xA9,0xAF,0x50,0x60,0x35,0x90,0xED,0x7D, + 0x28,0xF1,0x3C,0xF5,0x1D,0x4B,0xF4,0x32,0x41,0x3E,0x05,0x79,0x0B,0xEB,0xDD,0x89, + 0xA0,0x30,0x11,0xC9,0xB0,0x3F,0x83,0x77,0xC4,0xB3,0x2B,0x0A,0xE4,0xA3,0x82,0x01, + 0x3C,0x30,0x82,0x01,0x38,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x02,0x30,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, + 0x6F,0x79,0x89,0xE2,0x11,0xB0,0x49,0xE2,0xC1,0x5C,0xC4,0xDC,0xC7,0xE0,0x62,0x9F, + 0x3B,0x0A,0xC6,0x8C,0x30,0x57,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, + 0x04,0x4B,0x30,0x49,0x30,0x47,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, + 0x86,0x3B,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D,0x75,0x61, + 0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x2F,0x6F,0x63,0x73,0x70,0x30,0x33,0x2D,0x74,0x65,0x73,0x74,0x61,0x63,0x63,0x73, + 0x77,0x61,0x75,0x74,0x68,0x72,0x6F,0x6F,0x74,0x63,0x61,0x30,0x31,0x30,0x46,0x06, + 0x03,0x55,0x1D,0x1F,0x04,0x3F,0x30,0x3D,0x30,0x3B,0xA0,0x39,0xA0,0x37,0x86,0x35, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61,0x74,0x2E,0x63, + 0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65, + 0x73,0x74,0x61,0x63,0x63,0x73,0x77,0x61,0x75,0x74,0x68,0x72,0x6F,0x6F,0x74,0x63, + 0x61,0x2E,0x63,0x72,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, + 0x95,0x87,0xEF,0xFB,0xDF,0x1F,0x26,0x48,0x67,0x29,0xEC,0x94,0x70,0xD6,0x29,0x5D, + 0x9A,0x95,0xC8,0x88,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, + 0x03,0x02,0x07,0x80,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06, + 0x3B,0x01,0x04,0x03,0x0C,0x01,0x30,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7, + 0x63,0x64,0x06,0x3B,0x02,0x04,0x03,0x0C,0x01,0x30,0x30,0x11,0x06,0x0A,0x2A,0x86, + 0x48,0x86,0xF7,0x63,0x64,0x06,0x3B,0x03,0x04,0x03,0x0C,0x01,0x30,0x30,0x0A,0x06, + 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x21, + 0x00,0x9B,0xF6,0xD2,0x7D,0x61,0x1F,0xFD,0x73,0x9C,0x1D,0x54,0x3F,0x3C,0x9A,0xDF, + 0xAA,0x1D,0xEA,0x35,0xF6,0x41,0xF8,0xB5,0xC5,0x0E,0x92,0x14,0xA3,0x87,0xED,0xE6, + 0xD2,0x02,0x20,0x60,0xDA,0x7A,0x30,0xC3,0xEB,0x24,0x58,0xE2,0xBF,0x83,0xFC,0x41, + 0x51,0xF3,0xFB,0x50,0xE1,0x0F,0x53,0x6A,0x41,0x7A,0x59,0xA9,0x04,0x01,0x84,0xF9, + 0x81,0x89,0x87, +}; + +/* subject:/CN=0/O=PPID1234 */ +/* issuer :/CN=Test Accessories Software Authentication Root CA/OU=Apple Certification Authority/O=Apple Inc./C=US */ +const uint8_t _iAPSWAuth_leaf[735]={ + 0x30,0x82,0x02,0xDB,0x30,0x82,0x02,0x82,0xA0,0x03,0x02,0x01,0x02,0x02,0x0B,0x00, + 0x8A,0x71,0xFE,0xCD,0xA2,0xF3,0x00,0x00,0x00,0x00,0x30,0x0A,0x06,0x08,0x2A,0x86, + 0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81,0x85,0x31,0x39,0x30,0x37,0x06,0x03,0x55, + 0x04,0x03,0x0C,0x30,0x54,0x65,0x73,0x74,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x6F, + 0x72,0x69,0x65,0x73,0x20,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x41,0x75, + 0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x52,0x6F,0x6F, + 0x74,0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E, + 0x17,0x0D,0x31,0x37,0x31,0x32,0x31,0x32,0x30,0x32,0x35,0x36,0x35,0x30,0x5A,0x17, + 0x0D,0x32,0x38,0x30,0x31,0x30,0x39,0x30,0x32,0x35,0x36,0x35,0x30,0x5A,0x30,0x1F, + 0x31,0x0A,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x0C,0x01,0x30,0x31,0x11,0x30,0x0F, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x08,0x50,0x50,0x49,0x44,0x31,0x32,0x33,0x34,0x30, + 0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86, + 0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x64,0xFA,0xB0,0xFD,0xAF,0xD3, + 0xBF,0x9A,0xF6,0x48,0x03,0x9D,0x6B,0xBB,0x55,0x81,0x5E,0x6C,0x47,0x7D,0x2E,0xD4, + 0xF2,0xAE,0xA9,0xD3,0xA7,0x13,0xFA,0x69,0x16,0x16,0xC9,0x46,0x16,0xA2,0x38,0xB7, + 0x39,0xAC,0xFE,0x0B,0x9B,0x01,0x81,0x8A,0x94,0xA5,0x49,0x44,0x48,0x22,0x50,0x13, + 0x6B,0x06,0x28,0x6E,0x2D,0x09,0x1A,0x40,0x62,0x35,0xA3,0x82,0x01,0x3C,0x30,0x82, + 0x01,0x38,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x6F,0x79,0x89, + 0xE2,0x11,0xB0,0x49,0xE2,0xC1,0x5C,0xC4,0xDC,0xC7,0xE0,0x62,0x9F,0x3B,0x0A,0xC6, + 0x8C,0x30,0x57,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x4B,0x30, + 0x49,0x30,0x47,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x3B,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D,0x75,0x61,0x74,0x2E,0x63, + 0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63, + 0x73,0x70,0x30,0x33,0x2D,0x74,0x65,0x73,0x74,0x61,0x63,0x63,0x73,0x77,0x61,0x75, + 0x74,0x68,0x72,0x6F,0x6F,0x74,0x63,0x61,0x30,0x31,0x30,0x46,0x06,0x03,0x55,0x1D, + 0x1F,0x04,0x3F,0x30,0x3D,0x30,0x3B,0xA0,0x39,0xA0,0x37,0x86,0x35,0x68,0x74,0x74, + 0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70, + 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65,0x73,0x74,0x61, + 0x63,0x63,0x73,0x77,0x61,0x75,0x74,0x68,0x72,0x6F,0x6F,0x74,0x63,0x61,0x2E,0x63, + 0x72,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xE3,0xA0,0x9F, + 0x50,0x4D,0x31,0xB6,0xB3,0xED,0x16,0x5B,0xA3,0x91,0x68,0xB8,0xC2,0x65,0x40,0x73, + 0x4D,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x3B,0x01,0x04, + 0x03,0x04,0x01,0x01,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06, + 0x3B,0x02,0x04,0x03,0x04,0x01,0x00,0x30,0x11,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7, + 0x63,0x64,0x06,0x3B,0x03,0x04,0x03,0x04,0x01,0x01,0x30,0x0A,0x06,0x08,0x2A,0x86, + 0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x39,0x57,0x87, + 0x0B,0x53,0xB3,0x24,0x14,0x96,0x26,0xD2,0xA5,0x06,0xC2,0xA8,0x4C,0x5C,0x40,0xD4, + 0xC4,0x8D,0xEC,0x2D,0x2F,0x80,0xFB,0x2B,0xAF,0x56,0xF1,0x10,0x32,0x02,0x20,0x6D, + 0xCC,0xA8,0x41,0x92,0x89,0xD4,0xB8,0xEF,0xE5,0xB3,0x30,0xF7,0x94,0xBE,0x85,0x52, + 0xFE,0x75,0x5E,0xB2,0xEF,0x34,0x2F,0x71,0x8B,0xCD,0xD2,0xF0,0x9F,0xF7,0x63, +}; + +/* subject:/CN=Component Root CA/O=Apple Inc./ST=California */ +/* issuer :/CN=Component Root CA/O=Apple Inc./ST=California */ +const uint8_t _componentRoot[] = { + 0x30,0x82,0x02,0x01,0x30,0x82,0x01,0x87,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x60, + 0x38,0x41,0xE4,0xE2,0xE9,0x38,0x31,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x03,0x30,0x46,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11, + 0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, + 0x41,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x30,0x1E,0x17,0x0D,0x31, + 0x38,0x31,0x32,0x31,0x39,0x31,0x39,0x33,0x31,0x35,0x34,0x5A,0x17,0x0D,0x34,0x33, + 0x31,0x32,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x46,0x31,0x1A,0x30, + 0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E, + 0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x30,0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, + 0x06,0x05,0x2B,0x81,0x04,0x00,0x22,0x03,0x62,0x00,0x04,0x98,0x15,0xB6,0x3A,0x39, + 0xC0,0xBA,0x4D,0xC6,0x27,0xE2,0xB1,0x74,0x1E,0x99,0x0B,0xEB,0x2D,0x37,0xC5,0x3F, + 0x20,0xA9,0x8E,0xB3,0xFC,0x42,0x2E,0x33,0x07,0x40,0x47,0xF1,0x27,0xEC,0x02,0xC4, + 0x46,0xEC,0x2F,0x3C,0xC0,0xF8,0xAE,0xD7,0x0C,0x95,0xA9,0x90,0x3C,0x39,0x8C,0xAD, + 0x2F,0x20,0x8F,0x57,0xD9,0x96,0x6C,0xAD,0x89,0x6D,0x2B,0x10,0x06,0x00,0x5E,0x1C, + 0xD3,0xC2,0xD0,0x3F,0xDC,0x4E,0x89,0x1A,0xCC,0x41,0xC4,0xC1,0x75,0x37,0xC6,0xCB, + 0xFB,0xA2,0x6C,0xB5,0xCE,0x90,0x77,0x1D,0xC7,0x2C,0x9C,0xA3,0x42,0x30,0x40,0x30, + 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x90,0xD1,0x56,0xA9,0x3E, + 0xB4,0xEE,0x8C,0xD0,0x10,0x4B,0x9F,0x17,0x1C,0x5B,0x55,0xF2,0x12,0xF6,0x4C,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x02,0x04,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x68,0x00,0x30,0x65, + 0x02,0x31,0x00,0x9D,0x5A,0xE3,0x17,0xA8,0x56,0xB4,0x3C,0xB1,0x61,0x30,0x01,0xDC, + 0x03,0x3D,0xD4,0xEC,0xA4,0xAA,0xA4,0x2D,0xF9,0xE5,0x79,0x59,0x88,0xF7,0xE3,0xAC, + 0x3C,0xD0,0x68,0x76,0x79,0xCC,0x81,0x64,0xEC,0x34,0x2F,0x94,0x7D,0xF0,0x70,0x5D, + 0x65,0x8D,0xFC,0x02,0x30,0x71,0x6A,0x4F,0xE9,0x2E,0x38,0x87,0xDE,0x90,0x89,0x3B, + 0x1B,0x75,0xAD,0xED,0xE2,0x5C,0x53,0x75,0x71,0x1E,0x5A,0x2A,0xF2,0xD7,0x95,0xF7, + 0x32,0x1B,0xB6,0x0A,0x09,0x12,0x60,0x94,0xAE,0x55,0x2C,0xBE,0xCE,0x3F,0x4B,0xF4, + 0x4C,0x02,0xFB,0x9B,0x8C, +}; + +/* subject:/CN=Battery CA M1/OU=Component CA/O=Apple Inc./ST=California */ +/* issuer :/CN=Component Root CA/O=Apple Inc./ST=California */ +const uint8_t _componentCABattery[] = { + 0x30,0x82,0x02,0x36,0x30,0x82,0x01,0xBD,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x6A, + 0x22,0x01,0x3F,0xEB,0x2B,0x0D,0xA2,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x03,0x30,0x46,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11, + 0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, + 0x41,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x30,0x1E,0x17,0x0D,0x31, + 0x39,0x30,0x31,0x32,0x33,0x31,0x38,0x35,0x39,0x35,0x31,0x5A,0x17,0x0D,0x33,0x38, + 0x31,0x32,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x59,0x31,0x16,0x30, + 0x14,0x06,0x03,0x55,0x04,0x03,0x0C,0x0D,0x42,0x61,0x74,0x74,0x65,0x72,0x79,0x20, + 0x43,0x41,0x20,0x4D,0x31,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0C, + 0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x20,0x43,0x41,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE, + 0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00, + 0x04,0xAF,0x9C,0xF2,0x4B,0x8C,0xBD,0xA3,0x47,0xDF,0xA6,0x18,0x58,0x11,0xA0,0xF9, + 0x54,0xEE,0x5C,0x1E,0xA6,0x49,0x6B,0x74,0x6E,0x79,0xB5,0x36,0x36,0xB6,0x44,0x04, + 0x91,0x0E,0x4C,0x15,0xBD,0x8B,0xA1,0x7D,0x61,0x28,0xB8,0x6A,0x0F,0xE4,0x4C,0x39, + 0x57,0x1B,0x72,0x5B,0xBE,0x5C,0x1D,0x88,0x87,0xBD,0x37,0x3A,0xBC,0x0C,0x10,0x69, + 0x12,0xA3,0x81,0x81,0x30,0x7F,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, + 0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x1F,0x06,0x03,0x55,0x1D, + 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x90,0xD1,0x56,0xA9,0x3E,0xB4,0xEE,0x8C,0xD0, + 0x10,0x4B,0x9F,0x17,0x1C,0x5B,0x55,0xF2,0x12,0xF6,0x4C,0x30,0x1D,0x06,0x03,0x55, + 0x1D,0x0E,0x04,0x16,0x04,0x14,0x8C,0x3D,0xFA,0x31,0xF4,0x32,0x17,0x69,0x22,0xA3, + 0x4F,0x5F,0xC1,0x91,0x8E,0xF8,0x07,0xDA,0x84,0xD2,0x30,0x0E,0x06,0x03,0x55,0x1D, + 0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x19,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x63,0x64,0x0B,0x01,0x01,0x01,0xFF,0x04,0x09,0x16,0x07,0x42,0x61, + 0x74,0x74,0x65,0x72,0x79,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03, + 0x03,0x03,0x67,0x00,0x30,0x64,0x02,0x30,0x6D,0x3D,0xD2,0x6F,0x08,0xEA,0xA3,0x4B, + 0xBD,0x62,0xFA,0x33,0xCC,0xE6,0xD7,0xD8,0x99,0xD7,0x5E,0x34,0x26,0x9B,0x7C,0x92, + 0x1D,0xF2,0x78,0x41,0xED,0x34,0x1E,0x38,0x56,0x27,0xB4,0x41,0xCE,0xBE,0xFC,0x64, + 0x0B,0x12,0x17,0x4D,0xE0,0x26,0xC6,0xCA,0x02,0x30,0x7A,0x0D,0xC5,0x67,0xA7,0x9D, + 0xA9,0xFA,0x72,0x66,0x8E,0xF8,0xAD,0x40,0x68,0xC4,0xDB,0xE4,0xDB,0x57,0xBF,0x10, + 0x86,0x60,0x14,0x5F,0x4F,0x50,0x01,0x66,0xDB,0x45,0x89,0x8D,0xBC,0x13,0xA8,0x33, + 0xA1,0x26,0xCB,0x84,0x3B,0x2B,0xDB,0xA3,0xE6,0x4E, +}; + +/* subject:/C=US/O=Apple Inc./OU=Components/CN=F5D91143R5LMCRH1P-6A2E0F00 */ +/* issuer :/CN=Battery CA M1/OU=Component CA/O=Apple Inc./ST=California */ +const uint8_t _batteryLeaf[] = { + 0x30,0x82,0x02,0x0E,0x30,0x82,0x01,0xB4,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x2D, + 0x95,0x4B,0x3A,0x9B,0x74,0x5C,0x9A,0xA6,0x8E,0x45,0xD6,0x99,0xC2,0x30,0x0A,0x06, + 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x59,0x31,0x16,0x30,0x14,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x0D,0x42,0x61,0x74,0x74,0x65,0x72,0x79,0x20,0x43,0x41, + 0x20,0x4D,0x31,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0C,0x43,0x6F, + 0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x20,0x43,0x41,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x30,0x1E,0x17,0x0D,0x31,0x39,0x30,0x33,0x32,0x36,0x32,0x30, + 0x32,0x34,0x31,0x34,0x5A,0x17,0x0D,0x32,0x39,0x30,0x33,0x32,0x33,0x32,0x32,0x32, + 0x34,0x31,0x34,0x5A,0x30,0x5C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0B,0x0C,0x0A,0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x73,0x31,0x23,0x30, + 0x21,0x06,0x03,0x55,0x04,0x03,0x0C,0x1A,0x46,0x35,0x44,0x39,0x31,0x31,0x34,0x33, + 0x52,0x35,0x4C,0x4D,0x43,0x52,0x48,0x31,0x50,0x2D,0x36,0x41,0x32,0x45,0x30,0x46, + 0x30,0x30,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06, + 0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xBB,0x20,0x19, + 0xBF,0x3F,0xDC,0x9A,0xA6,0x8F,0xEF,0x94,0x34,0x82,0x29,0x01,0xB3,0xA8,0xF4,0x47, + 0xFA,0x51,0xEC,0x77,0x68,0x1C,0xC1,0xF6,0xD1,0xFE,0x79,0xD0,0xCC,0xEC,0x2D,0xF7, + 0x8D,0xF6,0x07,0xD1,0xDE,0x13,0xF5,0x39,0x4B,0xBF,0xBF,0x11,0x81,0x7F,0x73,0x99, + 0x2A,0x6F,0x6C,0x88,0x2C,0xF7,0x4F,0xA9,0x8B,0x4C,0x72,0x3E,0x5D,0xA3,0x5D,0x30, + 0x5B,0x30,0x2E,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x11,0x04,0x21, + 0x0C,0x1F,0x36,0x38,0x3A,0x66,0x65,0x3A,0x66,0x37,0x3A,0x30,0x34,0x3A,0x62,0x35, + 0x3A,0x34,0x34,0x2F,0x31,0x37,0x32,0x2E,0x31,0x38,0x2E,0x32,0x37,0x2E,0x31,0x36, + 0x37,0x30,0x14,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x0B,0x01,0x04,0x07, + 0x42,0x61,0x74,0x74,0x65,0x72,0x79,0x30,0x13,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x63,0x64,0x0B,0x02,0x04,0x06,0x66,0x33,0x36,0x66,0x38,0x64,0x30,0x0A,0x06,0x08, + 0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x21,0x00, + 0xA1,0x7A,0xC9,0x6B,0xB1,0xC5,0x75,0x80,0x91,0x6C,0xBB,0xF3,0x39,0xC0,0xE1,0xFF, + 0x9C,0xA8,0x9E,0x3D,0xA6,0xA6,0x3A,0x57,0xCD,0x57,0x72,0xA6,0x4C,0x63,0xFD,0x43, + 0x02,0x20,0x33,0xB5,0x9E,0x7C,0x52,0x29,0xDD,0x9A,0xB8,0x10,0x34,0xB8,0x53,0xD4, + 0xAA,0x69,0x6B,0x4E,0xDF,0x69,0xA9,0x56,0x9F,0xBA,0xED,0x66,0xDA,0xD5,0x81,0x67, + 0xE0,0x3D, +}; + #endif /* _TRUSTTESTS_EVALUATION_IAP_TESTS_H_ */ diff --git a/tests/TrustTests/FrameworkTests/CertificateInterfaceTests.m b/tests/TrustTests/FrameworkTests/CertificateInterfaceTests.m index 2e5c8dea..9e73e2f5 100644 --- a/tests/TrustTests/FrameworkTests/CertificateInterfaceTests.m +++ b/tests/TrustTests/FrameworkTests/CertificateInterfaceTests.m @@ -38,6 +38,7 @@ #include #include "../TestMacroConversions.h" #include "TrustFrameworkTestCase.h" +#include #include "CertificateInterfaceTests_data.h" @@ -501,4 +502,121 @@ errOut: CFRelease(result6); } +- (void)testCopyIPAddresses { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _IPAddressCert, sizeof(_IPAddressCert)); + NSArray *ipAddresses = CFBridgingRelease(SecCertificateCopyIPAddresses(cert)); + XCTAssertNotNil(ipAddresses); + XCTAssertEqual(ipAddresses.count, 1); + XCTAssertEqualObjects(ipAddresses[0], @"10.0.0.1"); + CFReleaseNull(cert); + + cert = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)); + ipAddresses = CFBridgingRelease(SecCertificateCopyIPAddresses(cert)); + XCTAssertNil(ipAddresses); + CFReleaseNull(cert); +} + +- (void)testCopySubjectAttributeValue { + // ATV not present + SecCertificateRef devCert = SecCertificateCreateWithBytes(NULL, _new_developer_cert, sizeof(_new_developer_cert)); + NSString *locality = CFBridgingRelease(SecCertificateCopySubjectAttributeValue(devCert, (DERItem *)&oidLocalityName)); + XCTAssertNil(locality); + + // ATV present + NSString *ou = CFBridgingRelease(SecCertificateCopySubjectAttributeValue(devCert, (DERItem *)&oidOrganizationalUnitName)); + XCTAssertNotNil(ou); + XCTAssert([ou isEqualToString:@"PV45XFU466"]); + CFReleaseNull(devCert); + + // pick the last value for multiple attributes + SecCertificateRef multipleValues = SecCertificateCreateWithBytes(NULL, two_common_names, sizeof(two_common_names)); + NSString *commonName = CFBridgingRelease(SecCertificateCopySubjectAttributeValue(multipleValues, (DERItem *)&oidCommonName)); + XCTAssertNotNil(commonName); + XCTAssert([commonName isEqualToString:@"certxauthsplit"]); + CFReleaseNull(multipleValues); +} + +- (void)testCopyProperties { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)); + + NSArray *properties = CFBridgingRelease(SecCertificateCopyProperties(cert)); + XCTAssertNotNil(properties); + + NSArray *localizedProperties = CFBridgingRelease(SecCertificateCopyLocalizedProperties(cert, true)); + XCTAssertNotNil(localizedProperties); + + // If we're on a en-us device, these should match + XCTAssertEqualObjects(properties, localizedProperties); + + CFReleaseNull(cert); +} + +- (void)testSignatureHashAlgorithm +{ + SecCertificateRef cert=NULL; + SecSignatureHashAlgorithm alg=0; + + isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_MD2, sizeof(RSA_MD2)), + NULL, "create RSA_MD2"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmMD2, "expected kSecSignatureHashAlgorithmMD2 (got %d)", (int)alg); + CFReleaseNull(cert); + + isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_MD5, sizeof(RSA_MD5)), + NULL, "create RSA_MD5"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmMD5, "expected kSecSignatureHashAlgorithmMD5 (got %d)", (int)alg); + CFReleaseNull(cert); + + isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_SHA1, sizeof(RSA_SHA1)), + NULL, "create RSA_SHA1"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmSHA1, "expected kSecSignatureHashAlgorithmSHA1 (got %d)", (int)alg); + CFReleaseNull(cert); + + isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_SHA256, sizeof(RSA_SHA256)), + NULL, "create RSA_SHA256"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmSHA256, "expected kSecSignatureHashAlgorithmSHA256 (got %d)", (int)alg); + CFReleaseNull(cert); + + isnt(cert = SecCertificateCreateWithBytes(NULL, RSA_SHA512, sizeof(RSA_SHA512)), + NULL, "create RSA_SHA512"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmSHA512, "expected kSecSignatureHashAlgorithmSHA512 (got %d)", (int)alg); + CFReleaseNull(cert); + + isnt(cert = SecCertificateCreateWithBytes(NULL, DSA_SHA1, sizeof(DSA_SHA1)), + NULL, "create DSA_SHA1"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmSHA1, "expected kSecSignatureHashAlgorithmSHA1 (got %d)", (int)alg); + CFReleaseNull(cert); + + isnt(cert = SecCertificateCreateWithBytes(NULL, ECDSA_SHA1, sizeof(ECDSA_SHA1)), + NULL, "create ECDSA_SHA1"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmSHA1, "expected kSecSignatureHashAlgorithmSHA1 (got %d)", (int)alg); + CFReleaseNull(cert); + + isnt(cert = SecCertificateCreateWithBytes(NULL, ECDSA_SHA256, sizeof(ECDSA_SHA256)), + NULL, "create ECDSA_SHA256"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmSHA256, "expected kSecSignatureHashAlgorithmSHA256 (got %d)", (int)alg); + CFReleaseNull(cert); + + isnt(cert = SecCertificateCreateWithBytes(NULL, ECDSA_SHA384, sizeof(ECDSA_SHA384)), + NULL, "create ECDSA_SHA384"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmSHA384, "expected kSecSignatureHashAlgorithmSHA384 (got %d)", (int)alg); + CFReleaseNull(cert); + + /* %%% RSAPSS is not yet supported; change this test when it is. */ + isnt(cert = SecCertificateCreateWithBytes(NULL, RSAPSS_SHA256, sizeof(RSAPSS_SHA256)), + NULL, "create RSAPSS_SHA256"); + alg = SecCertificateGetSignatureHashAlgorithm(cert); + ok(alg == kSecSignatureHashAlgorithmUnknown, "expected kSecSignatureHashAlgorithmUnknown (got %d)", (int)alg); + CFReleaseNull(cert); +} + + @end diff --git a/tests/TrustTests/FrameworkTests/CertificateInterfaceTests_data.h b/tests/TrustTests/FrameworkTests/CertificateInterfaceTests_data.h index 50f227e3..96acd9ea 100644 --- a/tests/TrustTests/FrameworkTests/CertificateInterfaceTests_data.h +++ b/tests/TrustTests/FrameworkTests/CertificateInterfaceTests_data.h @@ -994,4 +994,617 @@ const uint8_t _new_developer_cert[] = { 0xA4,0x85,0x74, }; +/* X509v3 Subject Alternative Name: + IP Address:10.0.0.1 */ +const uint8_t _IPAddressCert[] = { + 0x30,0x82,0x04,0x37,0x30,0x82,0x03,0x1F,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xC7,0x90,0xC5,0x69,0xCA,0xE3,0xB4,0x07,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27,0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53, + 0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A, + 0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72,0x65,0x73,0x73,0x20,0x53,0x41,0x4E,0x30, + 0x1E,0x17,0x0D,0x31,0x39,0x31,0x31,0x30,0x38,0x30,0x30,0x31,0x34,0x32,0x31,0x5A, + 0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x37,0x30,0x30,0x31,0x34,0x32,0x31,0x5A,0x30, + 0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53,0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63, + 0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A,0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72, + 0x65,0x73,0x73,0x20,0x53,0x41,0x4E,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30, + 0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC1,0x80,0xDE,0x51,0x33,0xB8,0x28,0xA8, + 0x7D,0x94,0x12,0x73,0x6F,0x0E,0xFC,0xF5,0xF0,0xC6,0x18,0xD2,0x87,0xB8,0x37,0xEE, + 0xF9,0xB1,0x69,0x1D,0xF9,0xE1,0x65,0x8D,0x47,0x34,0x50,0xBD,0x72,0x41,0x32,0x7A, + 0x02,0x0F,0x72,0x85,0xB8,0xE1,0x3D,0x7C,0x78,0x90,0x0A,0x81,0x06,0x25,0x9B,0x13, + 0xCA,0xD6,0xAA,0x77,0xDC,0x4A,0x9B,0x32,0xB7,0x1D,0xF1,0xEF,0x52,0x33,0xE3,0x5D, + 0x80,0xE0,0xE1,0xBB,0xF2,0x5E,0x91,0x55,0xA1,0xF8,0xE4,0x25,0x62,0xAB,0xBA,0x3D, + 0x42,0xEB,0x9B,0xD7,0x95,0x92,0x18,0x26,0x5F,0xB1,0x28,0x9B,0x01,0xDB,0x52,0x18, + 0xFE,0xF4,0x4F,0xD6,0x3A,0x49,0x13,0xE2,0xB0,0x06,0xEF,0x28,0x6C,0x89,0xFD,0x23, + 0x19,0x56,0xF7,0x1A,0x51,0x89,0x5C,0x13,0xDD,0xD6,0x55,0x70,0x17,0xCA,0x05,0x59, + 0x77,0xEA,0x75,0xA4,0x44,0x05,0x49,0xD3,0xD6,0xE4,0x04,0x74,0xC8,0x5F,0xF9,0x19, + 0x75,0x27,0xB2,0x17,0x6B,0x2E,0x45,0xE5,0x07,0xBD,0x17,0x70,0xFD,0xA2,0x6A,0xF7, + 0xF1,0xD8,0x43,0xBC,0xF6,0xCD,0xD1,0x2D,0xE0,0xF0,0x55,0xE7,0x60,0xA5,0x09,0x42, + 0xE6,0x67,0xB6,0x40,0x56,0x4E,0x3E,0xDF,0x7B,0x89,0x44,0x36,0x78,0x83,0x30,0x25, + 0x12,0xFF,0x48,0x97,0xC1,0x04,0x87,0xC7,0xA3,0x06,0xCE,0x06,0xCE,0x2F,0xAE,0x01, + 0x42,0x57,0x62,0x3B,0xDA,0xEB,0xD8,0xDB,0x96,0x5E,0xFC,0x1E,0x30,0x4B,0xE4,0x80, + 0xE1,0xD9,0x34,0x03,0x9C,0xD4,0x92,0x39,0x17,0xA8,0xCD,0xCA,0x96,0x54,0xEB,0x2D, + 0x12,0x77,0xE3,0x96,0x09,0x6D,0xBB,0x93,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x87, + 0x30,0x81,0x84,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x0F,0x06,0x03,0x55,0x1D,0x11,0x04,0x08,0x30, + 0x06,0x87,0x04,0x0A,0x00,0x00,0x01,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0xE0,0xA6,0x7D,0x62,0x28,0x6C,0xC0,0xCE,0x46,0xC8,0x04,0xB0,0xBA,0xB9, + 0x9B,0xF6,0x4A,0x60,0xBF,0xA9,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, + 0x16,0x80,0x14,0xE0,0xA6,0x7D,0x62,0x28,0x6C,0xC0,0xCE,0x46,0xC8,0x04,0xB0,0xBA, + 0xB9,0x9B,0xF6,0x4A,0x60,0xBF,0xA9,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x55,0xBB,0x48,0x72,0x61, + 0x8F,0xAF,0x7F,0x18,0x2F,0x31,0xF9,0xAA,0xFF,0x4A,0xC1,0x5B,0xBF,0x45,0xFE,0x82, + 0x3C,0xBE,0xFC,0xBB,0x58,0xA7,0x4A,0xF3,0x84,0xF8,0x10,0xB4,0x51,0x33,0x91,0xA0, + 0x58,0x1C,0x5F,0x67,0x91,0x31,0xD8,0xEC,0xA0,0x6A,0x85,0x84,0x71,0xBE,0xB5,0x18, + 0xAC,0xB8,0x7E,0xC3,0xFC,0x1C,0x74,0x84,0x48,0x2C,0x99,0xE9,0x52,0xBB,0x36,0x00, + 0x35,0x8C,0x50,0xC8,0x13,0x2A,0xFA,0x1E,0xF8,0x15,0x72,0xEF,0xF0,0x20,0x28,0xA0, + 0xCD,0xC7,0x85,0xEF,0x48,0x8C,0x27,0xF9,0x0E,0x15,0x9F,0xB8,0x54,0xD1,0x44,0x08, + 0x31,0xB0,0xC8,0x24,0x53,0x4A,0x63,0x97,0xB5,0xB3,0x83,0x07,0xCD,0x6D,0xC5,0x10, + 0xDD,0xC0,0x90,0xA2,0xFF,0x8E,0xD5,0x2F,0xC4,0xBC,0x8A,0xE0,0x90,0xAA,0x79,0x09, + 0xB5,0x23,0x72,0x6A,0xFB,0x9B,0xE5,0x0E,0xD9,0x30,0x41,0x70,0xF1,0x17,0x9C,0x5F, + 0xD7,0x0A,0x10,0x8E,0x77,0xD9,0x2F,0x59,0xE4,0xB4,0xF6,0x8D,0x16,0x90,0x84,0xBB, + 0xB6,0xAF,0xEE,0x86,0x4D,0x21,0xAE,0x3E,0x7B,0x2F,0xAD,0xBD,0xC4,0x38,0x9C,0x9E, + 0xB5,0x7C,0x8D,0x36,0x72,0x2C,0x78,0xC7,0xD4,0x54,0xD9,0x93,0x18,0xC8,0x00,0x5E, + 0xFE,0x12,0xE4,0x50,0x90,0x88,0xFB,0x82,0xFE,0x94,0xA5,0x4C,0xEB,0x7F,0xB7,0x39, + 0x99,0x24,0x0B,0x23,0xF9,0xB4,0x92,0xA8,0x6F,0xA6,0x46,0xBB,0xFB,0xDA,0xCD,0x8F, + 0xB9,0x14,0xE8,0x9B,0xBB,0x1B,0x80,0x9E,0x9D,0x9A,0x16,0xFF,0xF1,0x55,0xFF,0xDF, + 0x3E,0x32,0x73,0x16,0x9D,0xEA,0xF0,0xB1,0x5A,0x12,0xAB, +}; + +const UInt8 RSA_MD2[]={ + 0x30,0x82,0x02,0x3D,0x30,0x82,0x01,0xA6,0x02,0x11,0x00,0xCD,0xBA,0x7F,0x56,0xF0, + 0xDF,0xE4,0xBC,0x54,0xFE,0x22,0xAC,0xB3,0x72,0xAA,0x55,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02,0x05,0x00,0x30,0x5F,0x31,0x0B,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55, + 0x04,0x0A,0x13,0x0E,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x2C,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,0x0B,0x13,0x2E,0x43,0x6C,0x61, + 0x73,0x73,0x20,0x31,0x20,0x50,0x75,0x62,0x6C,0x69,0x63,0x20,0x50,0x72,0x69,0x6D, + 0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x39, + 0x36,0x30,0x31,0x32,0x39,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x38, + 0x30,0x38,0x30,0x31,0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x5F,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03, + 0x55,0x04,0x0A,0x13,0x0E,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x2C,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,0x0B,0x13,0x2E,0x43,0x6C, + 0x61,0x73,0x73,0x20,0x31,0x20,0x50,0x75,0x62,0x6C,0x69,0x63,0x20,0x50,0x72,0x69, + 0x6D,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x81,0x9F,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81, + 0x8D,0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xE5,0x19,0xBF,0x6D,0xA3,0x56,0x61, + 0x2D,0x99,0x48,0x71,0xF6,0x67,0xDE,0xB9,0x8D,0xEB,0xB7,0x9E,0x86,0x80,0x0A,0x91, + 0x0E,0xFA,0x38,0x25,0xAF,0x46,0x88,0x82,0xE5,0x73,0xA8,0xA0,0x9B,0x24,0x5D,0x0D, + 0x1F,0xCC,0x65,0x6E,0x0C,0xB0,0xD0,0x56,0x84,0x18,0x87,0x9A,0x06,0x9B,0x10,0xA1, + 0x73,0xDF,0xB4,0x58,0x39,0x6B,0x6E,0xC1,0xF6,0x15,0xD5,0xA8,0xA8,0x3F,0xAA,0x12, + 0x06,0x8D,0x31,0xAC,0x7F,0xB0,0x34,0xD7,0x8F,0x34,0x67,0x88,0x09,0xCD,0x14,0x11, + 0xE2,0x4E,0x45,0x56,0x69,0x1F,0x78,0x02,0x80,0xDA,0xDC,0x47,0x91,0x29,0xBB,0x36, + 0xC9,0x63,0x5C,0xC5,0xE0,0xD7,0x2D,0x87,0x7B,0xA1,0xB7,0x32,0xB0,0x7B,0x30,0xBA, + 0x2A,0x2F,0x31,0xAA,0xEE,0xA3,0x67,0xDA,0xDB,0x02,0x03,0x01,0x00,0x01,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02,0x05,0x00,0x03,0x81,0x81, + 0x00,0x4C,0x3F,0xB8,0x8B,0xC6,0x68,0xDF,0xEE,0x43,0x33,0x0E,0x5D,0xE9,0xA6,0xCB, + 0x07,0x84,0x4D,0x7A,0x33,0xFF,0x92,0x1B,0xF4,0x36,0xAD,0xD8,0x95,0x22,0x36,0x68, + 0x11,0x6C,0x7C,0x42,0xCC,0xF3,0x9C,0x2E,0xC4,0x07,0x3F,0x14,0xB0,0x0F,0x4F,0xFF, + 0x90,0x92,0x76,0xF9,0xE2,0xBC,0x4A,0xE9,0x8F,0xCD,0xA0,0x80,0x0A,0xF7,0xC5,0x29, + 0xF1,0x82,0x22,0x5D,0xB8,0xB1,0xDD,0x81,0x23,0xA3,0x7B,0x25,0x15,0x46,0x30,0x79, + 0x16,0xF8,0xEA,0x05,0x4B,0x94,0x7F,0x1D,0xC2,0x1C,0xC8,0xE3,0xB7,0xF4,0x10,0x40, + 0x3C,0x13,0xC3,0x5F,0x1F,0x53,0xE8,0x48,0xE4,0x86,0xB4,0x7B,0xA1,0x35,0xB0,0x7B, + 0x25,0xBA,0xB8,0xD3,0x8E,0xAB,0x3F,0x38,0x9D,0x00,0x34,0x00,0x98,0xF3,0xD1,0x71, + 0x94, +}; + +const UInt8 RSA_MD5[]={ + 0x30,0x82,0x02,0x5A,0x30,0x82,0x01,0xC3,0x02,0x02,0x01,0xA5,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,0x05,0x00,0x30,0x75,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x18,0x30,0x16,0x06,0x03, + 0x55,0x04,0x0A,0x13,0x0F,0x47,0x54,0x45,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61, + 0x74,0x69,0x6F,0x6E,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x0B,0x13,0x1E,0x47, + 0x54,0x45,0x20,0x43,0x79,0x62,0x65,0x72,0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x6F, + 0x6C,0x75,0x74,0x69,0x6F,0x6E,0x73,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x23,0x30, + 0x21,0x06,0x03,0x55,0x04,0x03,0x13,0x1A,0x47,0x54,0x45,0x20,0x43,0x79,0x62,0x65, + 0x72,0x54,0x72,0x75,0x73,0x74,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F, + 0x6F,0x74,0x30,0x1E,0x17,0x0D,0x39,0x38,0x30,0x38,0x31,0x33,0x30,0x30,0x32,0x39, + 0x30,0x30,0x5A,0x17,0x0D,0x31,0x38,0x30,0x38,0x31,0x33,0x32,0x33,0x35,0x39,0x30, + 0x30,0x5A,0x30,0x75,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04,0x0A,0x13,0x0F,0x47,0x54,0x45,0x20, + 0x43,0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x69,0x6F,0x6E,0x31,0x27,0x30,0x25,0x06, + 0x03,0x55,0x04,0x0B,0x13,0x1E,0x47,0x54,0x45,0x20,0x43,0x79,0x62,0x65,0x72,0x54, + 0x72,0x75,0x73,0x74,0x20,0x53,0x6F,0x6C,0x75,0x74,0x69,0x6F,0x6E,0x73,0x2C,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x23,0x30,0x21,0x06,0x03,0x55,0x04,0x03,0x13,0x1A,0x47, + 0x54,0x45,0x20,0x43,0x79,0x62,0x65,0x72,0x54,0x72,0x75,0x73,0x74,0x20,0x47,0x6C, + 0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F,0x6F,0x74,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30, + 0x81,0x89,0x02,0x81,0x81,0x00,0x95,0x0F,0xA0,0xB6,0xF0,0x50,0x9C,0xE8,0x7A,0xC7, + 0x88,0xCD,0xDD,0x17,0x0E,0x2E,0xB0,0x94,0xD0,0x1B,0x3D,0x0E,0xF6,0x94,0xC0,0x8A, + 0x94,0xC7,0x06,0xC8,0x90,0x97,0xC8,0xB8,0x64,0x1A,0x7A,0x7E,0x6C,0x3C,0x53,0xE1, + 0x37,0x28,0x73,0x60,0x7F,0xB2,0x97,0x53,0x07,0x9F,0x53,0xF9,0x6D,0x58,0x94,0xD2, + 0xAF,0x8D,0x6D,0x88,0x67,0x80,0xE6,0xED,0xB2,0x95,0xCF,0x72,0x31,0xCA,0xA5,0x1C, + 0x72,0xBA,0x5C,0x02,0xE7,0x64,0x42,0xE7,0xF9,0xA9,0x2C,0xD6,0x3A,0x0D,0xAC,0x8D, + 0x42,0xAA,0x24,0x01,0x39,0xE6,0x9C,0x3F,0x01,0x85,0x57,0x0D,0x58,0x87,0x45,0xF8, + 0xD3,0x85,0xAA,0x93,0x69,0x26,0x85,0x70,0x48,0x80,0x3F,0x12,0x15,0xC7,0x79,0xB4, + 0x1F,0x05,0x2F,0x3B,0x62,0x99,0x02,0x03,0x01,0x00,0x01,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,0x05,0x00,0x03,0x81,0x81,0x00,0x6D,0xEB, + 0x1B,0x09,0xE9,0x5E,0xD9,0x51,0xDB,0x67,0x22,0x61,0xA4,0x2A,0x3C,0x48,0x77,0xE3, + 0xA0,0x7C,0xA6,0xDE,0x73,0xA2,0x14,0x03,0x85,0x3D,0xFB,0xAB,0x0E,0x30,0xC5,0x83, + 0x16,0x33,0x81,0x13,0x08,0x9E,0x7B,0x34,0x4E,0xDF,0x40,0xC8,0x74,0xD7,0xB9,0x7D, + 0xDC,0xF4,0x76,0x55,0x7D,0x9B,0x63,0x54,0x18,0xE9,0xF0,0xEA,0xF3,0x5C,0xB1,0xD9, + 0x8B,0x42,0x1E,0xB9,0xC0,0x95,0x4E,0xBA,0xFA,0xD5,0xE2,0x7C,0xF5,0x68,0x61,0xBF, + 0x8E,0xEC,0x05,0x97,0x5F,0x5B,0xB0,0xD7,0xA3,0x85,0x34,0xC4,0x24,0xA7,0x0D,0x0F, + 0x95,0x93,0xEF,0xCB,0x94,0xD8,0x9E,0x1F,0x9D,0x5C,0x85,0x6D,0xC7,0xAA,0xAE,0x4F, + 0x1F,0x22,0xB5,0xCD,0x95,0xAD,0xBA,0xA7,0xCC,0xF9,0xAB,0x0B,0x7A,0x7F, +}; + +const UInt8 RSA_SHA1[]={ + 0x30,0x82,0x04,0xBB,0x30,0x82,0x03,0xA3,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x02, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30, + 0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x16,0x30,0x14,0x06, + 0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74, + 0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x36,0x30,0x34,0x32,0x35,0x32,0x31,0x34, + 0x30,0x33,0x36,0x5A,0x17,0x0D,0x33,0x35,0x30,0x32,0x30,0x39,0x32,0x31,0x34,0x30, + 0x33,0x36,0x5A,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31, + 0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30, + 0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xE4,0x91,0xA9,0x09,0x1F,0x91,0xDB,0x1E, + 0x47,0x50,0xEB,0x05,0xED,0x5E,0x79,0x84,0x2D,0xEB,0x36,0xA2,0x57,0x4C,0x55,0xEC, + 0x8B,0x19,0x89,0xDE,0xF9,0x4B,0x6C,0xF5,0x07,0xAB,0x22,0x30,0x02,0xE8,0x18,0x3E, + 0xF8,0x50,0x09,0xD3,0x7F,0x41,0xA8,0x98,0xF9,0xD1,0xCA,0x66,0x9C,0x24,0x6B,0x11, + 0xD0,0xA3,0xBB,0xE4,0x1B,0x2A,0xC3,0x1F,0x95,0x9E,0x7A,0x0C,0xA4,0x47,0x8B,0x5B, + 0xD4,0x16,0x37,0x33,0xCB,0xC4,0x0F,0x4D,0xCE,0x14,0x69,0xD1,0xC9,0x19,0x72,0xF5, + 0x5D,0x0E,0xD5,0x7F,0x5F,0x9B,0xF2,0x25,0x03,0xBA,0x55,0x8F,0x4D,0x5D,0x0D,0xF1, + 0x64,0x35,0x23,0x15,0x4B,0x15,0x59,0x1D,0xB3,0x94,0xF7,0xF6,0x9C,0x9E,0xCF,0x50, + 0xBA,0xC1,0x58,0x50,0x67,0x8F,0x08,0xB4,0x20,0xF7,0xCB,0xAC,0x2C,0x20,0x6F,0x70, + 0xB6,0x3F,0x01,0x30,0x8C,0xB7,0x43,0xCF,0x0F,0x9D,0x3D,0xF3,0x2B,0x49,0x28,0x1A, + 0xC8,0xFE,0xCE,0xB5,0xB9,0x0E,0xD9,0x5E,0x1C,0xD6,0xCB,0x3D,0xB5,0x3A,0xAD,0xF4, + 0x0F,0x0E,0x00,0x92,0x0B,0xB1,0x21,0x16,0x2E,0x74,0xD5,0x3C,0x0D,0xDB,0x62,0x16, + 0xAB,0xA3,0x71,0x92,0x47,0x53,0x55,0xC1,0xAF,0x2F,0x41,0xB3,0xF8,0xFB,0xE3,0x70, + 0xCD,0xE6,0xA3,0x4C,0x45,0x7E,0x1F,0x4C,0x6B,0x50,0x96,0x41,0x89,0xC4,0x74,0x62, + 0x0B,0x10,0x83,0x41,0x87,0x33,0x8A,0x81,0xB1,0x30,0x58,0xEC,0x5A,0x04,0x32,0x8C, + 0x68,0xB3,0x8F,0x1D,0xDE,0x65,0x73,0xFF,0x67,0x5E,0x65,0xBC,0x49,0xD8,0x76,0x9F, + 0x33,0x14,0x65,0xA1,0x77,0x94,0xC9,0x2D,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01, + 0x7A,0x30,0x82,0x01,0x76,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x01,0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6,0xF7, + 0x47,0x4D,0x7F,0x08,0x5E,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6, + 0xF7,0x47,0x4D,0x7F,0x08,0x5E,0x30,0x82,0x01,0x11,0x06,0x03,0x55,0x1D,0x20,0x04, + 0x82,0x01,0x08,0x30,0x82,0x01,0x04,0x30,0x82,0x01,0x00,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF2,0x30,0x2A,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x02,0x01,0x16,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77, + 0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70, + 0x6C,0x65,0x63,0x61,0x2F,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x02,0x02,0x30,0x81,0xB6,0x1A,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65, + 0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69, + 0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72,0x74, + 0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74, + 0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65,0x6E, + 0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61,0x6E, + 0x64,0x61,0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20,0x63, + 0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65, + 0x2C,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70,0x6F, + 0x6C,0x69,0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69, + 0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20, + 0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x5C, + 0x36,0x99,0x4C,0x2D,0x78,0xB7,0xED,0x8C,0x9B,0xDC,0xF3,0x77,0x9B,0xF2,0x76,0xD2, + 0x77,0x30,0x4F,0xC1,0x1F,0x85,0x83,0x85,0x1B,0x99,0x3D,0x47,0x37,0xF2,0xA9,0x9B, + 0x40,0x8E,0x2C,0xD4,0xB1,0x90,0x12,0xD8,0xBE,0xF4,0x73,0x9B,0xEE,0xD2,0x64,0x0F, + 0xCB,0x79,0x4F,0x34,0xD8,0xA2,0x3E,0xF9,0x78,0xFF,0x6B,0xC8,0x07,0xEC,0x7D,0x39, + 0x83,0x8B,0x53,0x20,0xD3,0x38,0xC4,0xB1,0xBF,0x9A,0x4F,0x0A,0x6B,0xFF,0x2B,0xFC, + 0x59,0xA7,0x05,0x09,0x7C,0x17,0x40,0x56,0x11,0x1E,0x74,0xD3,0xB7,0x8B,0x23,0x3B, + 0x47,0xA3,0xD5,0x6F,0x24,0xE2,0xEB,0xD1,0xB7,0x70,0xDF,0x0F,0x45,0xE1,0x27,0xCA, + 0xF1,0x6D,0x78,0xED,0xE7,0xB5,0x17,0x17,0xA8,0xDC,0x7E,0x22,0x35,0xCA,0x25,0xD5, + 0xD9,0x0F,0xD6,0x6B,0xD4,0xA2,0x24,0x23,0x11,0xF7,0xA1,0xAC,0x8F,0x73,0x81,0x60, + 0xC6,0x1B,0x5B,0x09,0x2F,0x92,0xB2,0xF8,0x44,0x48,0xF0,0x60,0x38,0x9E,0x15,0xF5, + 0x3D,0x26,0x67,0x20,0x8A,0x33,0x6A,0xF7,0x0D,0x82,0xCF,0xDE,0xEB,0xA3,0x2F,0xF9, + 0x53,0x6A,0x5B,0x64,0xC0,0x63,0x33,0x77,0xF7,0x3A,0x07,0x2C,0x56,0xEB,0xDA,0x0F, + 0x21,0x0E,0xDA,0xBA,0x73,0x19,0x4F,0xB5,0xD9,0x36,0x7F,0xC1,0x87,0x55,0xD9,0xA7, + 0x99,0xB9,0x32,0x42,0xFB,0xD8,0xD5,0x71,0x9E,0x7E,0xA1,0x52,0xB7,0x1B,0xBD,0x93, + 0x42,0x24,0x12,0x2A,0xC7,0x0F,0x1D,0xB6,0x4D,0x9C,0x5E,0x63,0xC8,0x4B,0x80,0x17, + 0x50,0xAA,0x8A,0xD5,0xDA,0xE4,0xFC,0xD0,0x09,0x07,0x37,0xB0,0x75,0x75,0x21, +}; + +const UInt8 RSA_SHA256[]={ + 0x30,0x82,0x03,0x5F,0x30,0x82,0x02,0x47,0xA0,0x03,0x02,0x01,0x02,0x02,0x0B,0x04, + 0x00,0x00,0x00,0x00,0x01,0x21,0x58,0x53,0x08,0xA2,0x30,0x0D,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x4C,0x31,0x20,0x30,0x1E,0x06, + 0x03,0x55,0x04,0x0B,0x13,0x17,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E, + 0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x52,0x33,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69, + 0x67,0x6E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F, + 0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x30,0x1E,0x17,0x0D,0x30,0x39,0x30,0x33,0x31, + 0x38,0x31,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x39,0x30,0x33,0x31,0x38, + 0x31,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x4C,0x31,0x20,0x30,0x1E,0x06,0x03,0x55, + 0x04,0x0B,0x13,0x17,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x20,0x52, + 0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x52,0x33,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x0A,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61, + 0x6C,0x53,0x69,0x67,0x6E,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, + 0x0A,0x02,0x82,0x01,0x01,0x00,0xCC,0x25,0x76,0x90,0x79,0x06,0x78,0x22,0x16,0xF5, + 0xC0,0x83,0xB6,0x84,0xCA,0x28,0x9E,0xFD,0x05,0x76,0x11,0xC5,0xAD,0x88,0x72,0xFC, + 0x46,0x02,0x43,0xC7,0xB2,0x8A,0x9D,0x04,0x5F,0x24,0xCB,0x2E,0x4B,0xE1,0x60,0x82, + 0x46,0xE1,0x52,0xAB,0x0C,0x81,0x47,0x70,0x6C,0xDD,0x64,0xD1,0xEB,0xF5,0x2C,0xA3, + 0x0F,0x82,0x3D,0x0C,0x2B,0xAE,0x97,0xD7,0xB6,0x14,0x86,0x10,0x79,0xBB,0x3B,0x13, + 0x80,0x77,0x8C,0x08,0xE1,0x49,0xD2,0x6A,0x62,0x2F,0x1F,0x5E,0xFA,0x96,0x68,0xDF, + 0x89,0x27,0x95,0x38,0x9F,0x06,0xD7,0x3E,0xC9,0xCB,0x26,0x59,0x0D,0x73,0xDE,0xB0, + 0xC8,0xE9,0x26,0x0E,0x83,0x15,0xC6,0xEF,0x5B,0x8B,0xD2,0x04,0x60,0xCA,0x49,0xA6, + 0x28,0xF6,0x69,0x3B,0xF6,0xCB,0xC8,0x28,0x91,0xE5,0x9D,0x8A,0x61,0x57,0x37,0xAC, + 0x74,0x14,0xDC,0x74,0xE0,0x3A,0xEE,0x72,0x2F,0x2E,0x9C,0xFB,0xD0,0xBB,0xBF,0xF5, + 0x3D,0x00,0xE1,0x06,0x33,0xE8,0x82,0x2B,0xAE,0x53,0xA6,0x3A,0x16,0x73,0x8C,0xDD, + 0x41,0x0E,0x20,0x3A,0xC0,0xB4,0xA7,0xA1,0xE9,0xB2,0x4F,0x90,0x2E,0x32,0x60,0xE9, + 0x57,0xCB,0xB9,0x04,0x92,0x68,0x68,0xE5,0x38,0x26,0x60,0x75,0xB2,0x9F,0x77,0xFF, + 0x91,0x14,0xEF,0xAE,0x20,0x49,0xFC,0xAD,0x40,0x15,0x48,0xD1,0x02,0x31,0x61,0x19, + 0x5E,0xB8,0x97,0xEF,0xAD,0x77,0xB7,0x64,0x9A,0x7A,0xBF,0x5F,0xC1,0x13,0xEF,0x9B, + 0x62,0xFB,0x0D,0x6C,0xE0,0x54,0x69,0x16,0xA9,0x03,0xDA,0x6E,0xE9,0x83,0x93,0x71, + 0x76,0xC6,0x69,0x85,0x82,0x17,0x02,0x03,0x01,0x00,0x01,0xA3,0x42,0x30,0x40,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30, + 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x8F,0xF0,0x4B,0x7F,0xA8, + 0x2E,0x45,0x24,0xAE,0x4D,0x50,0xFA,0x63,0x9A,0x8B,0xDE,0xE2,0xDD,0x1B,0xBC,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x4B,0x40,0xDB,0xC0,0x50,0xAA,0xFE,0xC8,0x0C,0xEF,0xF7,0x96,0x54, + 0x45,0x49,0xBB,0x96,0x00,0x09,0x41,0xAC,0xB3,0x13,0x86,0x86,0x28,0x07,0x33,0xCA, + 0x6B,0xE6,0x74,0xB9,0xBA,0x00,0x2D,0xAE,0xA4,0x0A,0xD3,0xF5,0xF1,0xF1,0x0F,0x8A, + 0xBF,0x73,0x67,0x4A,0x83,0xC7,0x44,0x7B,0x78,0xE0,0xAF,0x6E,0x6C,0x6F,0x03,0x29, + 0x8E,0x33,0x39,0x45,0xC3,0x8E,0xE4,0xB9,0x57,0x6C,0xAA,0xFC,0x12,0x96,0xEC,0x53, + 0xC6,0x2D,0xE4,0x24,0x6C,0xB9,0x94,0x63,0xFB,0xDC,0x53,0x68,0x67,0x56,0x3E,0x83, + 0xB8,0xCF,0x35,0x21,0xC3,0xC9,0x68,0xFE,0xCE,0xDA,0xC2,0x53,0xAA,0xCC,0x90,0x8A, + 0xE9,0xF0,0x5D,0x46,0x8C,0x95,0xDD,0x7A,0x58,0x28,0x1A,0x2F,0x1D,0xDE,0xCD,0x00, + 0x37,0x41,0x8F,0xED,0x44,0x6D,0xD7,0x53,0x28,0x97,0x7E,0xF3,0x67,0x04,0x1E,0x15, + 0xD7,0x8A,0x96,0xB4,0xD3,0xDE,0x4C,0x27,0xA4,0x4C,0x1B,0x73,0x73,0x76,0xF4,0x17, + 0x99,0xC2,0x1F,0x7A,0x0E,0xE3,0x2D,0x08,0xAD,0x0A,0x1C,0x2C,0xFF,0x3C,0xAB,0x55, + 0x0E,0x0F,0x91,0x7E,0x36,0xEB,0xC3,0x57,0x49,0xBE,0xE1,0x2E,0x2D,0x7C,0x60,0x8B, + 0xC3,0x41,0x51,0x13,0x23,0x9D,0xCE,0xF7,0x32,0x6B,0x94,0x01,0xA8,0x99,0xE7,0x2C, + 0x33,0x1F,0x3A,0x3B,0x25,0xD2,0x86,0x40,0xCE,0x3B,0x2C,0x86,0x78,0xC9,0x61,0x2F, + 0x14,0xBA,0xEE,0xDB,0x55,0x6F,0xDF,0x84,0xEE,0x05,0x09,0x4D,0xBD,0x28,0xD8,0x72, + 0xCE,0xD3,0x62,0x50,0x65,0x1E,0xEB,0x92,0x97,0x83,0x31,0xD9,0xB3,0xB5,0xCA,0x47, + 0x58,0x3F,0x5F, +}; + +const UInt8 RSA_SHA512[]={ + 0x30,0x82,0x05,0xD3,0x30,0x82,0x03,0xBB,0xA0,0x03,0x02,0x01,0x02,0x02,0x15,0x00, + 0xB8,0x59,0x14,0x71,0x3F,0x57,0xDF,0x8F,0x31,0xC0,0x33,0x3D,0xD2,0xD6,0x19,0x7A, + 0x23,0x17,0xB4,0xEB,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0D,0x05,0x00,0x30,0x81,0x80,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x50,0x4C,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0A,0x13,0x19,0x55,0x6E, + 0x69,0x7A,0x65,0x74,0x6F,0x20,0x54,0x65,0x63,0x68,0x6E,0x6F,0x6C,0x6F,0x67,0x69, + 0x65,0x73,0x20,0x53,0x2E,0x41,0x2E,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x0B, + 0x13,0x1E,0x43,0x65,0x72,0x74,0x75,0x6D,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69, + 0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79, + 0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x03,0x13,0x1B,0x43,0x65,0x72,0x74,0x75, + 0x6D,0x20,0x54,0x72,0x75,0x73,0x74,0x65,0x64,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72, + 0x6B,0x20,0x43,0x41,0x20,0x32,0x30,0x1E,0x17,0x0D,0x31,0x31,0x31,0x30,0x30,0x36, + 0x30,0x38,0x33,0x39,0x35,0x36,0x5A,0x17,0x0D,0x34,0x36,0x31,0x30,0x30,0x36,0x30, + 0x38,0x33,0x39,0x35,0x36,0x5A,0x30,0x81,0x80,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x50,0x4C,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0A,0x13, + 0x19,0x55,0x6E,0x69,0x7A,0x65,0x74,0x6F,0x20,0x54,0x65,0x63,0x68,0x6E,0x6F,0x6C, + 0x6F,0x67,0x69,0x65,0x73,0x20,0x53,0x2E,0x41,0x2E,0x31,0x27,0x30,0x25,0x06,0x03, + 0x55,0x04,0x0B,0x13,0x1E,0x43,0x65,0x72,0x74,0x75,0x6D,0x20,0x43,0x65,0x72,0x74, + 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72, + 0x69,0x74,0x79,0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x03,0x13,0x1B,0x43,0x65, + 0x72,0x74,0x75,0x6D,0x20,0x54,0x72,0x75,0x73,0x74,0x65,0x64,0x20,0x4E,0x65,0x74, + 0x77,0x6F,0x72,0x6B,0x20,0x43,0x41,0x20,0x32,0x30,0x82,0x02,0x22,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x02,0x0F, + 0x00,0x30,0x82,0x02,0x0A,0x02,0x82,0x02,0x01,0x00,0xBD,0xF9,0x78,0xF8,0xE6,0xD5, + 0x80,0x0C,0x64,0x9D,0x86,0x1B,0x96,0x64,0x67,0x3F,0x22,0x3A,0x1E,0x75,0x01,0x7D, + 0xEF,0xFB,0x5C,0x67,0x8C,0xC9,0xCC,0x5C,0x6B,0xA9,0x91,0xE6,0xB9,0x42,0xE5,0x20, + 0x4B,0x9B,0xDA,0x9B,0x7B,0xB9,0x99,0x5D,0xD9,0x9B,0x80,0x4B,0xD7,0x84,0x40,0x2B, + 0x27,0xD3,0xE8,0xBA,0x30,0xBB,0x3E,0x09,0x1A,0xA7,0x49,0x95,0xEF,0x2B,0x40,0x24, + 0xC2,0x97,0xC7,0xA7,0xEE,0x9B,0x25,0xEF,0xA8,0x0A,0x00,0x97,0x85,0x5A,0xAA,0x9D, + 0xDC,0x29,0xC9,0xE2,0x35,0x07,0xEB,0x70,0x4D,0x4A,0xD6,0xC1,0xB3,0x56,0xB8,0xA1, + 0x41,0x38,0x9B,0xD1,0xFB,0x31,0x7F,0x8F,0xE0,0x5F,0xE1,0xB1,0x3F,0x0F,0x8E,0x16, + 0x49,0x60,0xD7,0x06,0x8D,0x18,0xF9,0xAA,0x26,0x10,0xAB,0x2A,0xD3,0xD0,0xD1,0x67, + 0x8D,0x1B,0x46,0xBE,0x47,0x30,0xD5,0x2E,0x72,0xD1,0xC5,0x63,0xDA,0xE7,0x63,0x79, + 0x44,0x7E,0x4B,0x63,0x24,0x89,0x86,0x2E,0x34,0x3F,0x29,0x4C,0x52,0x8B,0x2A,0xA7, + 0xC0,0xE2,0x91,0x28,0x89,0xB9,0xC0,0x5B,0xF9,0x1D,0xD9,0xE7,0x27,0xAD,0xFF,0x9A, + 0x02,0x97,0xC1,0xC6,0x50,0x92,0x9B,0x02,0x2C,0xBD,0xA9,0xB9,0x34,0x59,0x0A,0xBF, + 0x84,0x4A,0xFF,0xDF,0xFE,0xB3,0x9F,0xEB,0xD9,0x9E,0xE0,0x98,0x23,0xEC,0xA6,0x6B, + 0x77,0x16,0x2A,0xDB,0xCC,0xAD,0x3B,0x1C,0xA4,0x87,0xDC,0x46,0x73,0x5E,0x19,0x62, + 0x68,0x45,0x57,0xE4,0x90,0x82,0x42,0xBB,0x42,0xD6,0xF0,0x61,0xE0,0xC1,0xA3,0x3D, + 0x66,0xA3,0x5D,0xF4,0x18,0xEE,0x88,0xC9,0x8D,0x17,0x45,0x29,0x99,0x32,0x75,0x02, + 0x31,0xEE,0x29,0x26,0xC8,0x6B,0x02,0xE6,0xB5,0x62,0x45,0x7F,0x37,0x15,0x5A,0x23, + 0x68,0x89,0xD4,0x3E,0xDE,0x4E,0x27,0xB0,0xF0,0x40,0x0C,0xBC,0x4D,0x17,0xCB,0x4D, + 0xA2,0xB3,0x1E,0xD0,0x06,0x5A,0xDD,0xF6,0x93,0xCF,0x57,0x75,0x99,0xF5,0xFA,0x86, + 0x1A,0x67,0x78,0xB3,0xBF,0x96,0xFE,0x34,0xDC,0xBD,0xE7,0x52,0x56,0xE5,0xB3,0xE5, + 0x75,0x7B,0xD7,0x41,0x91,0x05,0xDC,0x5D,0x69,0xE3,0x95,0x0D,0x43,0xB9,0xFC,0x83, + 0x96,0x39,0x95,0x7B,0x6C,0x80,0x5A,0x4F,0x13,0x72,0xC6,0xD7,0x7D,0x29,0x7A,0x44, + 0xBA,0x52,0xA4,0x2A,0xD5,0x41,0x46,0x09,0x20,0xFE,0x22,0xA0,0xB6,0x5B,0x30,0x8D, + 0xBC,0x89,0x0C,0xD5,0xD7,0x70,0xF8,0x87,0x52,0xFD,0xDA,0xEF,0xAC,0x51,0x2E,0x07, + 0xB3,0x4E,0xFE,0xD0,0x09,0xDA,0x70,0xEF,0x98,0xFA,0x56,0xE6,0x6D,0xDB,0xB5,0x57, + 0x4B,0xDC,0xE5,0x2C,0x25,0x15,0xC8,0x9E,0x2E,0x78,0x4E,0xF8,0xDA,0x9C,0x9E,0x86, + 0x2C,0xCA,0x57,0xF3,0x1A,0xE5,0xC8,0x92,0x8B,0x1A,0x82,0x96,0x7A,0xC3,0xBC,0x50, + 0x12,0x69,0xD8,0x0E,0x5A,0x46,0x8B,0x3A,0xEB,0x26,0xFA,0x23,0xC9,0xB6,0xB0,0x81, + 0xBE,0x42,0x00,0xA4,0xF8,0xD6,0xFE,0x30,0x2E,0xC7,0xD2,0x46,0xF6,0xE5,0x8E,0x75, + 0xFD,0xF2,0xCC,0xB9,0xD0,0x87,0x5B,0xCC,0x06,0x10,0x60,0xBB,0x83,0x35,0xB7,0x5E, + 0x67,0xDE,0x47,0xEC,0x99,0x48,0xF1,0xA4,0xA1,0x15,0xFE,0xAD,0x8C,0x62,0x8E,0x39, + 0x55,0x4F,0x39,0x16,0xB9,0xB1,0x63,0x9D,0xFF,0xB7,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x42,0x30,0x40,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30, + 0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xB6, + 0xA1,0x54,0x39,0x02,0xC3,0xA0,0x3F,0x8E,0x8A,0xBC,0xFA,0xD4,0xF8,0x1C,0xA6,0xD1, + 0x3A,0x0E,0xFD,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, + 0x02,0x01,0x06,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0D, + 0x05,0x00,0x03,0x82,0x02,0x01,0x00,0x9D,0x53,0xC2,0x81,0x25,0xDC,0x35,0x2C,0xAE, + 0x0A,0xDD,0x5A,0x9B,0x46,0x30,0x56,0xBB,0xD4,0xB4,0x6C,0x4B,0x86,0xE6,0x0A,0xA5, + 0xD2,0x92,0x8A,0x9A,0x8D,0xDC,0x8F,0xB4,0xEE,0x76,0xF4,0x03,0xCB,0xEB,0x9B,0x01, + 0x78,0xAB,0x2A,0x6B,0xB5,0xBA,0x23,0x4E,0x31,0x7C,0xB5,0x2C,0xDD,0x2D,0x69,0x67, + 0x33,0x6E,0x63,0x5D,0x39,0x18,0x12,0xF8,0xA0,0x28,0x53,0x44,0x87,0xAB,0x6A,0xC4, + 0x92,0x96,0x1F,0x2A,0xA2,0x1C,0xBA,0x9D,0xDD,0x27,0xFB,0x52,0x4D,0xB0,0x8F,0x5A, + 0xE8,0xED,0x8D,0xC3,0x68,0xE3,0x92,0xA0,0x26,0x0C,0x87,0x90,0xB0,0x03,0xEA,0x6A, + 0x65,0x28,0x08,0xC4,0x46,0x78,0xE0,0x5B,0xBA,0x0E,0xF0,0x33,0xDC,0x27,0xB6,0x7E, + 0x88,0x3D,0xBD,0x92,0xA4,0x96,0x7E,0x41,0xA8,0x80,0x08,0x7B,0xD6,0x36,0x12,0xBC, + 0x10,0x15,0x9B,0x24,0xBC,0xAB,0xAD,0x7D,0x11,0x89,0x2F,0x31,0xED,0xF8,0xD2,0xCF, + 0x53,0x8E,0xEB,0xB4,0x53,0xA7,0xE7,0x04,0xCA,0x2F,0xA6,0x22,0xC4,0x11,0xDC,0xEB, + 0x98,0xC9,0x22,0x5D,0x41,0x6A,0xDC,0x0A,0x52,0x04,0x5B,0xBC,0x2E,0xA0,0x7D,0xC7, + 0xB6,0x92,0xBB,0x24,0xA0,0xF3,0x37,0xD1,0x2B,0x43,0xA8,0xCC,0xF1,0x68,0x78,0x1A, + 0x7E,0x6F,0x63,0x90,0x7B,0x9F,0x74,0xC8,0x6B,0xD9,0x0B,0x55,0xF6,0x79,0x03,0x3D, + 0x83,0xC7,0x41,0x40,0x92,0xFB,0x76,0x0B,0x37,0x25,0x17,0x3C,0xAF,0x3E,0xFA,0x3C, + 0x5C,0x1B,0x86,0xF9,0x4A,0x0C,0x3F,0x8A,0xC4,0x5E,0x0E,0x98,0xF1,0xAD,0xEE,0xCF, + 0xE0,0xFD,0x21,0x35,0xC7,0x33,0x61,0xCC,0xA2,0x37,0x18,0x43,0x7C,0x33,0xE9,0xAE, + 0x76,0x82,0x82,0x07,0x45,0x48,0x3B,0xC9,0x67,0x6E,0xAD,0xA3,0x85,0xE8,0x96,0x56, + 0xCF,0xBC,0xBB,0xFA,0xAB,0xCB,0xB7,0x57,0x27,0x8D,0x1A,0x2F,0x99,0xF3,0x23,0x33, + 0x34,0x8E,0xCA,0x53,0x63,0xD3,0x57,0x34,0x50,0x4F,0xCF,0x49,0xC1,0x05,0xBA,0xC5, + 0xA8,0x87,0x7B,0xE3,0x86,0x8F,0xFB,0x43,0xA2,0x12,0xE9,0xAC,0x51,0xEC,0x04,0x76, + 0x4C,0xF0,0xFA,0x8F,0xB9,0x31,0x13,0xE9,0x08,0xB7,0x24,0x09,0xF9,0xA0,0xB7,0x07, + 0x36,0x58,0x57,0xCF,0xC4,0xBB,0x7E,0x49,0x66,0x95,0x35,0x04,0xB6,0x77,0x35,0xB8, + 0xA9,0x53,0x29,0x5F,0x92,0x85,0xF8,0x52,0xC4,0x5A,0x4E,0xFD,0x06,0x61,0x39,0xFB, + 0x7D,0xD0,0x76,0x47,0x92,0xCC,0xEC,0x2B,0xBD,0x84,0x6E,0xE6,0x9B,0x45,0xC1,0x7D, + 0x62,0xB1,0x53,0x2D,0x9E,0x75,0xA0,0xE7,0xC9,0x28,0x50,0xD7,0xE5,0xBC,0xA8,0xAA, + 0x07,0x78,0x6A,0xB9,0x74,0xB4,0x60,0xF3,0x84,0x8D,0x03,0xDC,0xAE,0x91,0xDA,0x74, + 0x44,0x0D,0x7B,0x42,0xA9,0x77,0xD6,0x2B,0x7C,0xA1,0xC6,0x6C,0x13,0x53,0x22,0xA9, + 0x12,0x9A,0xA5,0xF9,0x4F,0x28,0x45,0x35,0xB0,0x97,0x4F,0x46,0x65,0x85,0xC5,0xF4, + 0xFD,0x62,0xA2,0xA2,0x6A,0xFC,0x34,0x30,0x06,0x7E,0xDF,0x0C,0xE0,0x73,0x81,0x96, + 0xC9,0x44,0x2A,0xDE,0x1F,0x82,0xEC,0x6C,0x72,0x57,0xAD,0x29,0x64,0xA4,0xF1,0xC6, + 0x29,0x8E,0x35,0x60,0x53,0xCE,0x6B,0xD9,0x02,0xBE,0x39,0x30,0x75,0xE0,0xF7,0x5C, + 0x63,0x6A,0xF0,0x40,0xC1,0x2C,0x8D, +}; + +const UInt8 ECDSA_SHA1[]={ + 0x30,0x82,0x02,0x40,0x30,0x82,0x01,0xE7,0xA0,0x03,0x02,0x01,0x02,0x02,0x02,0x04, + 0x19,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x30,0x81,0x9B,0x31, + 0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B,0x13,0x0B,0x53,0x41,0x4D,0x50,0x4C,0x45, + 0x20,0x4F,0x4E,0x4C,0x59,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0A,0x13,0x0E, + 0x43,0x65,0x72,0x74,0x69,0x63,0x6F,0x6D,0x20,0x43,0x6F,0x72,0x70,0x2E,0x31,0x10, + 0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x54,0x6F,0x72,0x6F,0x6E,0x74,0x6F, + 0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x04,0x13,0x07,0x4F,0x6E,0x74,0x61,0x72, + 0x69,0x6F,0x31,0x39,0x30,0x37,0x06,0x03,0x55,0x04,0x03,0x13,0x30,0x74,0x6C,0x73, + 0x2E,0x73,0x65,0x63,0x67,0x2E,0x6F,0x72,0x67,0x20,0x45,0x43,0x43,0x20,0x73,0x65, + 0x63,0x70,0x32,0x35,0x36,0x72,0x31,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63, + 0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x36, + 0x30,0x35,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x35,0x30, + 0x35,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x81,0x8B,0x31,0x14,0x30, + 0x12,0x06,0x03,0x55,0x04,0x0B,0x13,0x0B,0x53,0x41,0x4D,0x50,0x4C,0x45,0x20,0x4F, + 0x4E,0x4C,0x59,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0A,0x13,0x0E,0x43,0x65, + 0x72,0x74,0x69,0x63,0x6F,0x6D,0x20,0x43,0x6F,0x72,0x70,0x2E,0x31,0x10,0x30,0x0E, + 0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x54,0x6F,0x72,0x6F,0x6E,0x74,0x6F,0x31,0x10, + 0x30,0x0E,0x06,0x03,0x55,0x04,0x04,0x13,0x07,0x4F,0x6E,0x74,0x61,0x72,0x69,0x6F, + 0x31,0x36,0x30,0x34,0x06,0x03,0x55,0x04,0x03,0x13,0x2D,0x74,0x6C,0x73,0x2E,0x73, + 0x65,0x63,0x67,0x2E,0x6F,0x72,0x67,0x20,0x45,0x43,0x43,0x20,0x73,0x65,0x63,0x70, + 0x32,0x35,0x36,0x72,0x31,0x20,0x43,0x6C,0x69,0x65,0x6E,0x74,0x20,0x43,0x65,0x72, + 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86, + 0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03, + 0x42,0x00,0x04,0x36,0x48,0x98,0xF8,0xB3,0xD0,0xC4,0x2E,0xCA,0x99,0x3D,0x14,0xBB, + 0x14,0x24,0xF5,0x89,0x82,0x36,0xE3,0x34,0xB2,0xF5,0x35,0x07,0xD0,0xA8,0xDE,0x14, + 0x84,0xD7,0x78,0xA4,0x62,0x01,0x77,0xEA,0xBD,0xA9,0xA3,0x9F,0x8B,0x48,0x5F,0x3C, + 0x7A,0xA1,0x96,0x40,0xD1,0x2C,0xB6,0xDD,0xEA,0x21,0xF8,0xED,0x29,0x70,0x44,0x80, + 0x49,0x2E,0x77,0xA3,0x2A,0x30,0x28,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x03,0x88,0x30,0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01, + 0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30, + 0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x03,0x48,0x00,0x30,0x45,0x02, + 0x20,0x45,0xA2,0x99,0x2C,0xE0,0x08,0xB2,0xEE,0x09,0xCD,0x1D,0x51,0x42,0x60,0x3F, + 0x56,0x4D,0x2D,0xA1,0x7D,0xAB,0xD0,0xF5,0x6D,0xF7,0xF0,0xE2,0x23,0x33,0xBC,0xBD, + 0xB3,0x02,0x21,0x00,0xCD,0xFB,0x57,0x1C,0x3A,0x32,0xD1,0xBC,0x67,0xBB,0x0F,0x1D, + 0x12,0xEB,0x63,0x12,0x1F,0x50,0x37,0x67,0x77,0x66,0x2B,0xE1,0x37,0xD4,0x8F,0xDD, + 0xE0,0xAA,0xE4,0x22, +}; + +const UInt8 ECDSA_SHA256[] = { + 0x30,0x82,0x01,0xE1,0x30,0x82,0x01,0x87,0xA0,0x03,0x02,0x01,0x02,0x02,0x11,0x2A, + 0x38,0xA4,0x1C,0x96,0x0A,0x04,0xDE,0x42,0xB2,0x28,0xA5,0x0B,0xE8,0x34,0x98,0x02, + 0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x50,0x31,0x24, + 0x30,0x22,0x06,0x03,0x55,0x04,0x0B,0x13,0x1B,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53, + 0x69,0x67,0x6E,0x20,0x45,0x43,0x43,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20, + 0x2D,0x20,0x52,0x34,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x47, + 0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x30,0x1E, + 0x17,0x0D,0x31,0x32,0x31,0x31,0x31,0x33,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17, + 0x0D,0x33,0x38,0x30,0x31,0x31,0x39,0x30,0x33,0x31,0x34,0x30,0x37,0x5A,0x30,0x50, + 0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x0B,0x13,0x1B,0x47,0x6C,0x6F,0x62,0x61, + 0x6C,0x53,0x69,0x67,0x6E,0x20,0x45,0x43,0x43,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, + 0x41,0x20,0x2D,0x20,0x52,0x34,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13, + 0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x03,0x13,0x0A,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x53,0x69,0x67,0x6E, + 0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A, + 0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xB8,0xC6,0x79,0xD3,0x8F, + 0x6C,0x25,0x0E,0x9F,0x2E,0x39,0x19,0x1C,0x03,0xA4,0xAE,0x9A,0xE5,0x39,0x07,0x09, + 0x16,0xCA,0x63,0xB1,0xB9,0x86,0xF8,0x8A,0x57,0xC1,0x57,0xCE,0x42,0xFA,0x73,0xA1, + 0xF7,0x65,0x42,0xFF,0x1E,0xC1,0x00,0xB2,0x6E,0x73,0x0E,0xFF,0xC7,0x21,0xE5,0x18, + 0xA4,0xAA,0xD9,0x71,0x3F,0xA8,0xD4,0xB9,0xCE,0x8C,0x1D,0xA3,0x42,0x30,0x40,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30, + 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x54,0xB0,0x7B,0xAD,0x45, + 0xB8,0xE2,0x40,0x7F,0xFB,0x0A,0x6E,0xFB,0xBE,0x33,0xC9,0x3C,0xA3,0x84,0xD5,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48,0x00,0x30,0x45, + 0x02,0x21,0x00,0xDC,0x92,0xA1,0xA0,0x13,0xA6,0xCF,0x03,0xB0,0xE6,0xC4,0x21,0x97, + 0x90,0xFA,0x14,0x57,0x2D,0x03,0xEC,0xEE,0x3C,0xD3,0x6E,0xCA,0xA8,0x6C,0x76,0xBC, + 0xA2,0xDE,0xBB,0x02,0x20,0x27,0xA8,0x85,0x27,0x35,0x9B,0x56,0xC6,0xA3,0xF2,0x47, + 0xD2,0xB7,0x6E,0x1B,0x02,0x00,0x17,0xAA,0x67,0xA6,0x15,0x91,0xDE,0xFA,0x94,0xEC, + 0x7B,0x0B,0xF8,0x9F,0x84, +}; + +const UInt8 ECDSA_SHA384[] = { + 0x30,0x82,0x02,0x43,0x30,0x82,0x01,0xC9,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x2D, + 0xC5,0xFC,0x88,0xD2,0xC5,0x4B,0x95,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x03,0x30,0x67,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20, + 0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, + 0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D, + 0x31,0x34,0x30,0x34,0x33,0x30,0x31,0x38,0x31,0x39,0x30,0x36,0x5A,0x17,0x0D,0x33, + 0x39,0x30,0x34,0x33,0x30,0x31,0x38,0x31,0x39,0x30,0x36,0x5A,0x30,0x67,0x31,0x1B, + 0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x41,0x70,0x70,0x6C,0x65,0x20,0x52, + 0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x47,0x33,0x31,0x26,0x30,0x24,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74, + 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72, + 0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x30,0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, + 0x02,0x01,0x06,0x05,0x2B,0x81,0x04,0x00,0x22,0x03,0x62,0x00,0x04,0x98,0xE9,0x2F, + 0x3D,0x40,0x72,0xA4,0xED,0x93,0x22,0x72,0x81,0x13,0x1C,0xDD,0x10,0x95,0xF1,0xC5, + 0xA3,0x4E,0x71,0xDC,0x14,0x16,0xD9,0x0E,0xE5,0xA6,0x05,0x2A,0x77,0x64,0x7B,0x5F, + 0x4E,0x38,0xD3,0xBB,0x1C,0x44,0xB5,0x7F,0xF5,0x1F,0xB6,0x32,0x62,0x5D,0xC9,0xE9, + 0x84,0x5B,0x4F,0x30,0x4F,0x11,0x5A,0x00,0xFD,0x58,0x58,0x0C,0xA5,0xF5,0x0F,0x2C, + 0x4D,0x07,0x47,0x13,0x75,0xDA,0x97,0x97,0x97,0x6F,0x31,0x5C,0xED,0x2B,0x9D,0x7B, + 0x20,0x3B,0xD8,0xB9,0x54,0xD9,0x5E,0x99,0xA4,0x3A,0x51,0x0A,0x31,0xA3,0x42,0x30, + 0x40,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xBB,0xB0,0xDE,0xA1, + 0x58,0x33,0x88,0x9A,0xA4,0x8A,0x99,0xDE,0xBE,0xBD,0xEB,0xAF,0xDA,0xCB,0x24,0xAB, + 0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01, + 0xFF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01, + 0x06,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x03,0x68,0x00, + 0x30,0x65,0x02,0x31,0x00,0x83,0xE9,0xC1,0xC4,0x16,0x5E,0x1A,0x5D,0x34,0x18,0xD9, + 0xED,0xEF,0xF4,0x6C,0x0E,0x00,0x46,0x4B,0xB8,0xDF,0xB2,0x46,0x11,0xC5,0x0F,0xFD, + 0xE6,0x7A,0x8C,0xA1,0xA6,0x6B,0xCE,0xC2,0x03,0xD4,0x9C,0xF5,0x93,0xC6,0x74,0xB8, + 0x6A,0xDF,0xAA,0x23,0x15,0x02,0x30,0x6D,0x66,0x8A,0x10,0xCA,0xD4,0x0D,0xD4,0x4F, + 0xCD,0x8D,0x43,0x3E,0xB4,0x8A,0x63,0xA5,0x33,0x6E,0xE3,0x6D,0xDA,0x17,0xB7,0x64, + 0x1F,0xC8,0x53,0x26,0xF9,0x88,0x62,0x74,0x39,0x0B,0x17,0x5B,0xCB,0x51,0xA8,0x0C, + 0xE8,0x18,0x03,0xE7,0xA2,0xB2,0x28, +}; + +const UInt8 DSA_SHA1[] = { + 0x30,0x82,0x02,0x1E,0x30,0x82,0x01,0xDD,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x02, + 0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x38,0x04,0x03,0x30,0x3F,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1F,0x30,0x1D,0x06,0x03, + 0x55,0x04,0x0A,0x13,0x16,0x54,0x65,0x73,0x74,0x20,0x43,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x65,0x73,0x20,0x32,0x30,0x31,0x31,0x31,0x0F,0x30,0x0D,0x06, + 0x03,0x55,0x04,0x03,0x13,0x06,0x44,0x53,0x41,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, + 0x31,0x30,0x30,0x31,0x30,0x31,0x30,0x38,0x33,0x30,0x30,0x30,0x5A,0x17,0x0D,0x33, + 0x30,0x31,0x32,0x33,0x31,0x30,0x38,0x33,0x30,0x30,0x30,0x5A,0x30,0x54,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1F,0x30,0x1D,0x06, + 0x03,0x55,0x04,0x0A,0x13,0x16,0x54,0x65,0x73,0x74,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x65,0x73,0x20,0x32,0x30,0x31,0x31,0x31,0x24,0x30,0x22, + 0x06,0x03,0x55,0x04,0x03,0x13,0x1B,0x44,0x53,0x41,0x20,0x50,0x61,0x72,0x61,0x6D, + 0x65,0x74,0x65,0x72,0x73,0x20,0x49,0x6E,0x68,0x65,0x72,0x69,0x74,0x65,0x64,0x20, + 0x43,0x41,0x30,0x81,0x92,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x38,0x04,0x01, + 0x03,0x81,0x84,0x00,0x02,0x81,0x80,0x74,0x2F,0x4F,0x75,0xD0,0x81,0x57,0x23,0x6F, + 0x2D,0x66,0x63,0x90,0xD1,0x42,0x20,0xCB,0x43,0x9F,0x4E,0xE2,0xF5,0x3A,0x14,0xD2, + 0xD8,0xC7,0xEA,0xDD,0xF3,0xB2,0x1E,0x81,0x9A,0x61,0x10,0x40,0x09,0xB2,0x7A,0x51, + 0xF3,0x66,0xF9,0x36,0x23,0x70,0x54,0xE8,0xE9,0x66,0x7A,0x94,0xA5,0xB1,0xF4,0x1B, + 0x31,0x18,0x56,0x5D,0xBF,0x8A,0x19,0x16,0x47,0x91,0x60,0xAA,0xF9,0x8D,0x45,0x5C, + 0x02,0x4B,0x7F,0x67,0xB3,0x02,0xF6,0x8F,0x6D,0x14,0xB9,0xCD,0x64,0x90,0xDD,0x0C, + 0x88,0xC7,0xC4,0x4B,0x12,0xD1,0xB8,0xBE,0x32,0xA0,0x9F,0xB9,0x4A,0x84,0x33,0xC3, + 0xAB,0xB6,0x42,0x4B,0x4B,0x32,0xED,0x29,0x3D,0x07,0xF8,0x07,0x7E,0xA2,0xF7,0xD8, + 0xA2,0x56,0x53,0x71,0x2A,0x53,0x7B,0xA3,0x7C,0x30,0x7A,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x8F,0x90,0xC6,0x8C,0x74,0xE8,0x7B,0x0C, + 0xC8,0x59,0xC7,0x7D,0x3C,0x5B,0x54,0x59,0x60,0x25,0x0B,0xB1,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x65,0x81,0x9F,0x70,0x3A,0x8C,0xAD,0xF6,0x43, + 0x1D,0xC8,0xE7,0x8F,0x55,0x8E,0xE8,0x4B,0xDB,0x87,0xE2,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x17,0x06,0x03,0x55, + 0x1D,0x20,0x04,0x10,0x30,0x0E,0x30,0x0C,0x06,0x0A,0x60,0x86,0x48,0x01,0x65,0x03, + 0x02,0x01,0x30,0x01,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05, + 0x30,0x03,0x01,0x01,0xFF,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x38,0x04,0x03, + 0x03,0x30,0x00,0x30,0x2D,0x02,0x14,0x47,0xF0,0x98,0xC9,0xBB,0x05,0xA9,0x82,0xC5, + 0x11,0x2B,0x7A,0x5F,0xC9,0x11,0xE5,0x83,0x90,0xB7,0xD9,0x02,0x15,0x00,0x93,0xE1, + 0x0B,0xBE,0xAD,0x25,0x08,0x00,0x07,0x88,0x70,0xDF,0xC3,0x59,0x4F,0x22,0x9C,0xEA, + 0xD4,0x0F, +}; + +const UInt8 RSAPSS_SHA256[] = { + 0x30,0x82,0x04,0x51,0x30,0x82,0x03,0x05,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x7B, + 0x20,0x9C,0x9D,0xDF,0x9C,0xED,0x93,0x43,0x73,0x51,0x0D,0x1B,0xD2,0x8A,0xDC,0x30, + 0x41,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0A,0x30,0x34,0xA0,0x0F, + 0x30,0x0D,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xA1, + 0x1C,0x30,0x1A,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x08,0x30,0x0D, + 0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xA2,0x03,0x02, + 0x01,0x20,0x30,0x31,0x31,0x2F,0x30,0x2D,0x06,0x03,0x55,0x04,0x03,0x13,0x26,0x54, + 0x75,0x63,0x73,0x6F,0x6E,0x20,0x55,0x6E,0x69,0x66,0x69,0x65,0x64,0x20,0x53,0x63, + 0x68,0x6F,0x6F,0x6C,0x20,0x44,0x69,0x73,0x74,0x72,0x69,0x63,0x74,0x20,0x52,0x6F, + 0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x39,0x30,0x32,0x30, + 0x37,0x31,0x36,0x32,0x39,0x5A,0x17,0x0D,0x33,0x34,0x30,0x39,0x30,0x32,0x30,0x37, + 0x32,0x38,0x33,0x33,0x5A,0x30,0x31,0x31,0x2F,0x30,0x2D,0x06,0x03,0x55,0x04,0x03, + 0x13,0x26,0x54,0x75,0x63,0x73,0x6F,0x6E,0x20,0x55,0x6E,0x69,0x66,0x69,0x65,0x64, + 0x20,0x53,0x63,0x68,0x6F,0x6F,0x6C,0x20,0x44,0x69,0x73,0x74,0x72,0x69,0x63,0x74, + 0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00, + 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC7,0x5F,0x0B,0x3D,0x69,0x0B,0x4F, + 0x05,0x0A,0xD9,0x2F,0xFC,0x06,0xD7,0x7E,0x16,0xD2,0x36,0x9E,0x97,0x24,0x4A,0x1B, + 0xCE,0x8E,0x39,0xE6,0x4E,0x2F,0xF3,0x42,0x52,0x61,0x35,0x5F,0x97,0xD5,0x3C,0x06, + 0x85,0x2E,0x39,0xD2,0xE9,0x4D,0x5C,0xEA,0xB9,0xE7,0x04,0x22,0x40,0xE1,0x30,0x61, + 0xD6,0xCC,0x4C,0x0F,0x3B,0xE5,0x25,0x3B,0x21,0x33,0xB7,0x5F,0xA6,0x33,0xC0,0x08, + 0x18,0xD9,0x4A,0xF7,0xC8,0x1C,0xEE,0x16,0xF5,0x7C,0xB1,0xBF,0x9A,0x01,0x7E,0x21, + 0x9F,0x0A,0xD7,0xAC,0x63,0xBA,0xA8,0x9B,0x21,0x64,0x6F,0x2B,0x42,0xFA,0x97,0x8B, + 0xCC,0xF9,0x04,0x91,0x79,0xE1,0xB9,0xFA,0xC2,0xBD,0x2F,0x54,0x02,0x67,0xB1,0xDF, + 0xB8,0x78,0x76,0x06,0x2B,0xC4,0x2E,0xBA,0x62,0xDB,0x70,0x49,0x59,0x8A,0x64,0xD0, + 0x71,0xCC,0x60,0x1F,0xC4,0x89,0xE7,0xE2,0x95,0x05,0x39,0x88,0x43,0x21,0x45,0xAE, + 0x80,0x72,0x2C,0xF6,0x70,0xE1,0xA6,0x65,0x52,0x4F,0x67,0x18,0x7C,0x80,0x4F,0xD3, + 0xE1,0x6C,0x39,0xAB,0x58,0x6F,0x4A,0x7B,0xB1,0xFB,0x21,0xF5,0xF6,0x26,0xCB,0x15, + 0x22,0xEF,0x63,0x1E,0x0E,0xBF,0x92,0xB2,0x3D,0x52,0x79,0xBC,0xE9,0xFE,0x62,0x18, + 0x83,0x0A,0x1D,0x97,0xF0,0x8E,0xE9,0x11,0x77,0x8F,0xDF,0xE5,0x0B,0xB8,0x0D,0xDB, + 0x6B,0x27,0x21,0xE0,0x12,0xB9,0xF4,0xB5,0xA2,0xD9,0x80,0xF4,0x64,0x66,0x5C,0x61, + 0xB6,0x16,0xC8,0x21,0x8B,0xDC,0x66,0x4F,0xEE,0x22,0x7F,0x07,0xA8,0x19,0x05,0x9E, + 0x83,0x0F,0x1E,0xC1,0x93,0x58,0x6C,0xEF,0xB3,0x02,0x03,0x01,0x00,0x01,0xA3,0x81, + 0xFC,0x30,0x81,0xF9,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04,0x04,0x03,0x02,0x01, + 0x86,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01, + 0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xFC,0xEE,0x66, + 0x3B,0xB0,0xC7,0xD4,0x6F,0x68,0x37,0xBA,0x99,0x27,0x73,0xEE,0x4F,0x8D,0x9B,0xE3, + 0xF4,0x30,0x10,0x06,0x09,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x15,0x01,0x04,0x03, + 0x02,0x01,0x01,0x30,0x81,0x82,0x06,0x03,0x55,0x1D,0x20,0x04,0x7B,0x30,0x79,0x30, + 0x77,0x06,0x08,0x2A,0x03,0x04,0x8B,0x2F,0x43,0x59,0x05,0x30,0x6B,0x30,0x3A,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x2E,0x1E,0x2C,0x00,0x4C,0x00, + 0x65,0x00,0x67,0x00,0x61,0x00,0x6C,0x00,0x20,0x00,0x50,0x00,0x6F,0x00,0x6C,0x00, + 0x69,0x00,0x63,0x00,0x79,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x61,0x00,0x74,0x00, + 0x65,0x00,0x6D,0x00,0x65,0x00,0x6E,0x00,0x74,0x30,0x2D,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x02,0x01,0x16,0x21,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72, + 0x6C,0x2E,0x74,0x75,0x73,0x64,0x31,0x2E,0x6F,0x72,0x67,0x2F,0x70,0x6B,0x69,0x2F, + 0x63,0x70,0x73,0x2E,0x74,0x78,0x74,0x00,0x30,0x23,0x06,0x09,0x2B,0x06,0x01,0x04, + 0x01,0x82,0x37,0x15,0x02,0x04,0x16,0x04,0x14,0x10,0xF3,0x7D,0x95,0x8D,0xB7,0x2F, + 0x44,0x17,0xD7,0xED,0x56,0xC3,0x7E,0x64,0xAA,0x4F,0xEF,0x26,0xEA,0x30,0x41,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0A,0x30,0x34,0xA0,0x0F,0x30,0x0D, + 0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xA1,0x1C,0x30, + 0x1A,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x08,0x30,0x0D,0x06,0x09, + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xA2,0x03,0x02,0x01,0x20, + 0x03,0x82,0x01,0x01,0x00,0x03,0x1F,0xF8,0x3C,0x15,0x37,0xA7,0xBB,0xB1,0x6A,0x27, + 0xDB,0x27,0x7F,0xF8,0x23,0xAD,0x51,0xEE,0x87,0x61,0xC8,0xAB,0x56,0x83,0x1C,0x11, + 0xA9,0xAC,0x79,0xB4,0x7E,0x2E,0x33,0x3F,0xBD,0x98,0x7B,0xE4,0x28,0xAB,0xB1,0xCB, + 0x00,0xEE,0xB3,0x2D,0x6B,0x8D,0x15,0xAD,0x4B,0x51,0x29,0xFE,0x05,0xE6,0x5C,0x1C, + 0xBA,0x70,0xAF,0x30,0x13,0x2C,0xAE,0xDD,0x8D,0x95,0xF5,0x56,0x13,0x2B,0x43,0x07, + 0x0F,0xC3,0xCB,0xDA,0x2B,0x46,0x44,0x8E,0x12,0xE3,0x9E,0x14,0xE2,0x5E,0x74,0x07, + 0x0C,0x92,0xDE,0x99,0x45,0x37,0x51,0xFB,0xDB,0x75,0xFE,0x16,0x37,0x58,0x05,0xB3, + 0xDE,0x3E,0xD1,0x77,0x57,0x6A,0x56,0xF1,0xF6,0xC1,0x9F,0xA8,0x93,0xCF,0xA8,0x67, + 0x32,0xE1,0xDB,0x65,0x12,0x39,0x76,0x91,0xB7,0x85,0xDD,0xF0,0x30,0xEF,0x6E,0x68, + 0x41,0xCD,0x72,0x0B,0x8D,0x85,0x50,0x26,0xC1,0x0B,0x93,0x2B,0x9F,0x07,0x44,0x57, + 0x84,0x55,0x3F,0x28,0x75,0x05,0x12,0x04,0x58,0x27,0x24,0x5D,0x21,0x68,0xB5,0xF4, + 0xB9,0xFA,0xE6,0xC1,0xCB,0x99,0x7C,0x85,0x45,0x01,0xFE,0x43,0x8C,0xCA,0x9E,0x44, + 0x32,0x46,0x23,0xFC,0xBD,0x2D,0xCA,0x19,0xF8,0xDB,0x1C,0x9F,0x85,0x3D,0x7C,0xAA, + 0xCC,0x42,0x16,0x4D,0x61,0x7D,0xA1,0x67,0xD5,0xC0,0x25,0x62,0xDB,0xE2,0x61,0xB0, + 0xDD,0xB6,0xD6,0x07,0x03,0x1B,0xD0,0x0E,0xB2,0xBA,0xC2,0xBF,0x24,0x7C,0x2B,0x82, + 0xEB,0xEE,0xB0,0x29,0xE5,0x8E,0xDD,0x55,0xF6,0x3B,0x5E,0x46,0x0D,0xCE,0x55,0xEA, + 0x70,0x2F,0xFF,0xF8,0x74, +}; + #endif /* _TRUSTTESTS_CERTIFICATE_INTERFACE_H_ */ diff --git a/tests/TrustTests/FrameworkTests/CertificateParseTests.m b/tests/TrustTests/FrameworkTests/CertificateParseTests.m index a1a30b67..d65c9113 100644 --- a/tests/TrustTests/FrameworkTests/CertificateParseTests.m +++ b/tests/TrustTests/FrameworkTests/CertificateParseTests.m @@ -38,6 +38,7 @@ const NSString *kSecTestParseSuccessResources = @"si-18-certificate-parse/ParseS const NSString *kSecTestKeyFailureResources = @"si-18-certificate-parse/KeyFailureCerts"; const NSString *kSecTestTODOFailureResources = @"si-18-certificate-parse/TODOFailureCerts"; const NSString *kSecTestExtensionFailureResources = @"si-18-certificate-parse/ExtensionFailureCerts"; +const NSString *kSecTestNameFailureResources = @"si-18-certificate-parse/NameFailureCerts"; @interface CertificateParseTests : TrustFrameworkTestCase @@ -129,4 +130,20 @@ const NSString *kSecTestExtensionFailureResources = @"si-18-certificate-parse/Ex } } +- (void)testUnparseableSubjectName { + /* A bunch of certificates with different parsing errors the subject name */ + NSArray * certURLs = [[NSBundle bundleForClass:[self class]]URLsForResourcesWithExtension:@".cer" subdirectory:(NSString *)kSecTestNameFailureResources]; + XCTAssertTrue([certURLs count] > 0, "Unable to find parse test name failure certs in bundle."); + + if ([certURLs count] > 0) { + [certURLs enumerateObjectsUsingBlock:^(NSURL *url, __unused NSUInteger idx, __unused BOOL *stop) { + NSData *certData = [NSData dataWithContentsOfURL:url]; + SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData); + isnt(cert, NULL, "Failed to parse bad cert with unparseable name: %@", url); + is(CFBridgingRelease(SecCertificateCopyCountry(cert)), nil, "Success parsing name for failure cert: %@", url); + CFReleaseNull(cert); + }]; + } +} + @end diff --git a/tests/TrustTests/FrameworkTests/PolicyInterfaceTests.m b/tests/TrustTests/FrameworkTests/PolicyInterfaceTests.m new file mode 100644 index 00000000..902cb9ce --- /dev/null +++ b/tests/TrustTests/FrameworkTests/PolicyInterfaceTests.m @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#include +#import +#include +#include +#include +#include + +#include "../TestMacroConversions.h" +#include "../TrustEvaluationTestHelpers.h" +#include "TrustFrameworkTestCase.h" + +@interface PolicyInterfaceTests : TrustFrameworkTestCase +@end + +@implementation PolicyInterfaceTests + +- (void)testCreateWithProperties +{ + const void *keys[] = { kSecPolicyName, kSecPolicyClient }; + const void *values[] = { CFSTR("www.google.com"), kCFBooleanFalse }; + CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, + array_size(keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + SecPolicyRef policy = SecPolicyCreateWithProperties(kSecPolicyAppleSSL, properties); + isnt(policy, NULL, "SecPolicyCreateWithProperties"); + CFReleaseSafe(properties); +} + +- (void)testCopyProperties +{ + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("www.google.com")); + CFDictionaryRef properties = NULL; + isnt(properties = SecPolicyCopyProperties(policy), NULL, "copy policy properties"); + CFTypeRef value = NULL; + is(CFDictionaryGetValueIfPresent(properties, kSecPolicyName, (const void **)&value) && + kCFCompareEqualTo == CFStringCompare((CFStringRef)value, CFSTR("www.google.com"), 0), + true, "has policy name"); + is(CFDictionaryGetValueIfPresent(properties, kSecPolicyOid, (const void **)&value) && + CFEqual(value, kSecPolicyAppleSSL) , true, "has SSL policy"); + CFReleaseSafe(properties); +} + +- (void)testSetSHA256Pins +{ + SecPolicyRef policy = SecPolicyCreateBasicX509(); + CFDictionaryRef options = SecPolicyGetOptions(policy); + XCTAssertEqual(CFDictionaryGetValue(options, kSecPolicyCheckLeafSPKISHA256), NULL); + XCTAssertEqual(CFDictionaryGetValue(options, kSecPolicyCheckCAspkiSHA256), NULL); + + NSArray *pins = @[ ]; + SecPolicySetSHA256Pins(policy, (__bridge CFArrayRef)pins, (__bridge CFArrayRef)pins); + XCTAssertEqualObjects((__bridge NSArray *)CFDictionaryGetValue(options, kSecPolicyCheckLeafSPKISHA256), pins); + XCTAssertEqualObjects((__bridge NSArray *)CFDictionaryGetValue(options, kSecPolicyCheckCAspkiSHA256), pins); + + SecPolicySetSHA256Pins(policy, NULL, (__bridge CFArrayRef)pins); + XCTAssertEqual(CFDictionaryGetValue(options, kSecPolicyCheckLeafSPKISHA256), NULL); + XCTAssertEqualObjects((__bridge NSArray *)CFDictionaryGetValue(options, kSecPolicyCheckCAspkiSHA256), pins); + + SecPolicySetSHA256Pins(policy, (__bridge CFArrayRef)pins, NULL); + XCTAssertEqualObjects((__bridge NSArray *)CFDictionaryGetValue(options, kSecPolicyCheckLeafSPKISHA256), pins); + XCTAssertEqual(CFDictionaryGetValue(options, kSecPolicyCheckCAspkiSHA256), NULL); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + SecPolicySetSHA256Pins(NULL, NULL, NULL); + XCTAssertEqualObjects((__bridge NSArray *)CFDictionaryGetValue(options, kSecPolicyCheckLeafSPKISHA256), pins); + XCTAssertEqual(CFDictionaryGetValue(options, kSecPolicyCheckCAspkiSHA256), NULL); +#pragma clang diagnostic pop +} + +@end diff --git a/tests/TrustTests/FrameworkTests/TrustInterfaceTests.m b/tests/TrustTests/FrameworkTests/TrustInterfaceTests.m index e44c6c2d..788146ef 100644 --- a/tests/TrustTests/FrameworkTests/TrustInterfaceTests.m +++ b/tests/TrustTests/FrameworkTests/TrustInterfaceTests.m @@ -145,7 +145,7 @@ is_status(trustResult, kSecTrustResultInvalid, "trustResult is kSecTrustResultInvalid"); is(SecTrustGetCertificateCount(trust), 1, "cert count is 1 without securityd running"); SecKeyRef pubKey = NULL; - ok(pubKey = SecTrustCopyPublicKey(trust), "copy public key without securityd running"); + ok(pubKey = SecTrustCopyKey(trust), "copy public key without securityd running"); CFReleaseNull(pubKey); SecServerSetTrustdMachServiceName("com.apple.trustd"); // End of Restore OS environment tests @@ -158,6 +158,55 @@ errOut: CFReleaseNull(policy); } +- (void)testRestoreOSBag { + SecTrustRef trust; + SecCertificateRef leaf, root; + SecPolicyRef policy; + CFDataRef urlBagData; + CFDictionaryRef urlBagDict; + + isnt(urlBagData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, url_bag, sizeof(url_bag), kCFAllocatorNull), NULL, + "load url bag"); + isnt(urlBagDict = CFPropertyListCreateWithData(kCFAllocatorDefault, urlBagData, kCFPropertyListImmutable, NULL, NULL), NULL, + "parse url bag"); + CFReleaseSafe(urlBagData); + CFArrayRef certs_data = CFDictionaryGetValue(urlBagDict, CFSTR("certs")); + CFDataRef cert_data = CFArrayGetValueAtIndex(certs_data, 0); + isnt(leaf = SecCertificateCreateWithData(kCFAllocatorDefault, cert_data), NULL, "create leaf"); + isnt(root = SecCertificateCreateWithBytes(kCFAllocatorDefault, sITunesStoreRootCertificate, sizeof(sITunesStoreRootCertificate)), NULL, "create root"); + + CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **)&leaf, 1, NULL); + CFDataRef signature = CFDictionaryGetValue(urlBagDict, CFSTR("signature")); + CFDataRef bag = CFDictionaryGetValue(urlBagDict, CFSTR("bag")); + + isnt(policy = SecPolicyCreateBasicX509(), NULL, "create policy instance"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for leaf"); + + // Test Restore OS environment bag signing verification + SecServerSetTrustdMachServiceName("com.apple.security.doesn't-exist"); + SecTrustResultType trustResult; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + SecKeyRef pub_key_leaf; + isnt(pub_key_leaf = SecTrustCopyKey(trust), NULL, "get leaf pub key"); + if (!pub_key_leaf) { goto errOut; } + CFErrorRef error = NULL; + ok(SecKeyVerifySignature(pub_key_leaf, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, bag, signature, &error), + "verify signature on bag"); + CFReleaseNull(error); + SecServerSetTrustdMachServiceName("com.apple.trustd"); + // End of Restore OS environment tests + +errOut: + CFReleaseSafe(pub_key_leaf); + CFReleaseSafe(urlBagDict); + CFReleaseSafe(certs); + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(leaf); + CFReleaseSafe(root); +} + - (void)testAnchorCerts { SecTrustRef trust = NULL; CFArrayRef certs = NULL, anchors = NULL; @@ -371,7 +420,8 @@ errOut: ok_status(SecTrustEvaluateAsync(trust, queue, ^(SecTrustRef _Nonnull trustRef, SecTrustResultType trustResult) { if ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified)) { // Evaluation succeeded! - SecKeyRef publicKey = SecTrustCopyPublicKey(trustRef); + SecKeyRef publicKey = SecTrustCopyKey(trustRef); + XCTAssert(publicKey != NULL); CFReleaseSafe(publicKey); } else if (trustResult == kSecTrustResultRecoverableTrustFailure) { // Evaluation failed, but may be able to recover . . . @@ -891,4 +941,115 @@ errOut: }]; } +- (void)testCopyKey +{ + SecTrustRef trust = NULL; + CFArrayRef certs = NULL; + SecCertificateRef cert0 = NULL, cert1 = NULL; + SecPolicyRef policy = NULL; + + isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), + NULL, "create cert0"); + isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), + NULL, "create cert1"); + const void *v_certs[] = { cert0, cert1 }; + + certs = CFArrayCreate(NULL, v_certs, array_size(v_certs), &kCFTypeArrayCallBacks); + policy = SecPolicyCreateSSL(false, NULL); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); + + SecKeyRef trustPubKey = NULL, certPubKey = NULL; + ok(trustPubKey = SecTrustCopyKey(trust), "copy public key without securityd running"); + ok(certPubKey = SecCertificateCopyKey(cert0)); + XCTAssert(CFEqualSafe(trustPubKey, certPubKey)); + + + CFReleaseNull(trustPubKey); + CFReleaseNull(certPubKey); + CFReleaseNull(trust); + CFReleaseNull(cert0); + CFReleaseNull(cert1); + CFReleaseNull(certs); + CFReleaseNull(policy); +} + +- (void)testSetNetworkFetchAllowed +{ + SecCertificateRef cert0 = NULL, cert1 = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + + require(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), errOut); + require(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), errOut); + require(policy = SecPolicyCreateSSL(true, CFSTR("example.com")), errOut); + require_noerr(SecTrustCreateWithCertificates(cert0, policy, &trust), errOut); + + Boolean curAllow, allow; + ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); + allow = !curAllow; /* flip it and see if the setting sticks */ + ok_status(SecTrustSetNetworkFetchAllowed(trust, allow)); + ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); + is((allow == curAllow), true, "network fetch toggle"); + + /* ensure trust with revocation policy returns the correct status */ + SecPolicyRef revocation = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); + ok_status(SecTrustSetPolicies(trust, revocation)); + ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); + is(curAllow, true, "network fetch set for revocation policy"); + + SecPolicyRef basic = SecPolicyCreateBasicX509(); + CFMutableArrayRef policies = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(policies, basic); + CFArrayAppendValue(policies, revocation); + ok_status(SecTrustSetPolicies(trust, policies)); + ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); + is(curAllow, true, "network fetch set for basic+revocation policy"); + CFReleaseNull(revocation); + CFReleaseNull(basic); + CFReleaseNull(policies); + + revocation = SecPolicyCreateRevocation(kSecRevocationNetworkAccessDisabled); + ok_status(SecTrustSetPolicies(trust, revocation)); + ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); + is(curAllow, false, "network fetch not set for revocation policy"); + CFReleaseNull(revocation); + +errOut: + CFReleaseNull(cert0); + CFReleaseNull(cert1); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + +- (void)testSetOCSPResponses +{ + SecCertificateRef cert0 = NULL, cert1 = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + + require(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), errOut); + require(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), errOut); + require(policy = SecPolicyCreateSSL(true, CFSTR("example.com")), errOut); + require_noerr(SecTrustCreateWithCertificates(cert0, policy, &trust), errOut); + + CFDataRef resp = (CFDataRef) CFDataCreateMutable(NULL, 0); + CFDataIncreaseLength((CFMutableDataRef)resp, 64); /* arbitrary length, zero-filled data */ + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + // NULL passed as 'trust' newly generates a warning, we need to suppress it in order to compile + is_status(SecTrustSetOCSPResponse(NULL, resp), errSecParam, "SecTrustSetOCSPResponse param 1 check OK"); +#pragma clang diagnostic pop + is_status(SecTrustSetOCSPResponse(trust, NULL), errSecSuccess, "SecTrustSetOCSPResponse param 2 check OK"); + is_status(SecTrustSetOCSPResponse(trust, resp), errSecSuccess, "SecTrustSetOCSPResponse OK"); + CFReleaseSafe(resp); + +errOut: + CFReleaseNull(cert0); + CFReleaseNull(cert1); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + @end diff --git a/tests/TrustTests/FrameworkTests/TrustInterfaceTests_data.h b/tests/TrustTests/FrameworkTests/TrustInterfaceTests_data.h index e9a884fe..fb3eb7ee 100644 --- a/tests/TrustTests/FrameworkTests/TrustInterfaceTests_data.h +++ b/tests/TrustTests/FrameworkTests/TrustInterfaceTests_data.h @@ -534,4 +534,95 @@ unsigned char _comodo_rsa_root[1500]={ 0x35,0x53,0x85,0x06,0x4A,0x5D,0x9F,0xAD,0xBB,0x1B,0x5F,0x74, }; +// MARK: Restore URL Bag + +static const UInt8 sITunesStoreRootCertificate[] = +{ + 0x30, 0x82, 0x04, 0x65, 0x30, 0x82, 0x03, 0x4d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, + 0xcb, 0x06, 0xa3, 0x3b, 0x30, 0xc3, 0x24, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x7e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, + 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, + 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x52, 0x6f, 0x6f, + 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, + 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, + 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x37, 0x31, 0x30, 0x30, + 0x39, 0x31, 0x37, 0x35, 0x31, 0x33, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x32, 0x31, 0x30, 0x30, 0x32, + 0x31, 0x37, 0x35, 0x31, 0x33, 0x30, 0x5a, 0x30, 0x7e, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, + 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, + 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x52, 0x6f, 0x6f, + 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, + 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, + 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, + 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa9, 0x78, 0xc0, 0xaf, 0x1a, 0x96, 0x59, 0xad, + 0xf8, 0x3c, 0x16, 0xe1, 0xfc, 0xc4, 0x7a, 0xaf, 0xf0, 0x80, 0xed, 0x7f, 0x3a, 0xff, 0xf2, 0x2a, + 0xb6, 0xf3, 0x1a, 0xdd, 0xbd, 0x14, 0xb1, 0x5d, 0x9d, 0x66, 0xaf, 0xc7, 0xaf, 0x2b, 0x26, 0x78, + 0x9c, 0xb8, 0x0b, 0x41, 0x9c, 0xdc, 0x17, 0xf1, 0x40, 0x18, 0x09, 0xa1, 0x0a, 0xbc, 0x01, 0x9a, + 0x0c, 0xbe, 0x89, 0xdb, 0x9d, 0x34, 0xc7, 0x52, 0x8a, 0xf2, 0xbf, 0x35, 0x2b, 0x24, 0x04, 0xb0, + 0x0c, 0x9d, 0x41, 0x7d, 0x63, 0xe3, 0xad, 0xcf, 0x8b, 0x34, 0xbf, 0x5c, 0x42, 0x82, 0x9b, 0x78, + 0x7f, 0x00, 0x10, 0x88, 0xd9, 0xfd, 0xf8, 0xbf, 0x63, 0x2c, 0x91, 0x87, 0x03, 0xda, 0xbc, 0xc6, + 0x71, 0x2b, 0x9a, 0x21, 0x30, 0x95, 0xd6, 0x88, 0xe8, 0xbd, 0x0a, 0x74, 0xa4, 0xa6, 0x39, 0xd0, + 0x61, 0xd3, 0xb6, 0xe0, 0x2b, 0x1e, 0xe4, 0x78, 0x5c, 0x70, 0x32, 0x66, 0x97, 0x34, 0xa9, 0x79, + 0xfc, 0x96, 0xaf, 0x4b, 0x8a, 0xd5, 0x12, 0x07, 0x8c, 0x1c, 0xf6, 0x3e, 0x5f, 0xdc, 0x8f, 0x92, + 0x10, 0xe8, 0x7e, 0xa0, 0x14, 0x1e, 0x61, 0x28, 0xfa, 0xcc, 0xcf, 0x3c, 0xdb, 0x2b, 0xe3, 0xe9, + 0x44, 0x4a, 0x9d, 0x5f, 0x92, 0x3d, 0xa3, 0xfd, 0x1a, 0x63, 0xb4, 0xbb, 0xab, 0x67, 0x45, 0xc6, + 0x4d, 0x84, 0x4a, 0xaa, 0x33, 0xe4, 0xde, 0xd3, 0x04, 0x92, 0xbf, 0xf7, 0x00, 0x48, 0x76, 0xc6, + 0x4e, 0x17, 0xea, 0x70, 0xdb, 0x09, 0xbc, 0x22, 0x07, 0x7b, 0x97, 0x49, 0xe5, 0x29, 0xa7, 0x1a, + 0x04, 0xd2, 0x0d, 0x0e, 0x73, 0xf1, 0x49, 0x43, 0x34, 0x35, 0x61, 0xe5, 0x67, 0xdf, 0x3c, 0x58, + 0x42, 0x51, 0xfb, 0xc3, 0xa4, 0x15, 0x6d, 0x39, 0x6b, 0x2a, 0x22, 0xde, 0xdd, 0xe2, 0x36, 0x5b, + 0xd7, 0x37, 0x53, 0x96, 0x9d, 0x3a, 0x9f, 0x4b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe5, + 0x30, 0x81, 0xe2, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb0, 0xda, + 0xe1, 0x7f, 0xa8, 0x8b, 0x4a, 0x6a, 0x81, 0x5d, 0x0c, 0xa1, 0x84, 0x56, 0x46, 0x1e, 0x6a, 0xef, + 0xe5, 0xcf, 0x30, 0x81, 0xb2, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xaa, 0x30, 0x81, 0xa7, + 0x80, 0x14, 0xb0, 0xda, 0xe1, 0x7f, 0xa8, 0x8b, 0x4a, 0x6a, 0x81, 0x5d, 0x0c, 0xa1, 0x84, 0x56, + 0x46, 0x1e, 0x6a, 0xef, 0xe5, 0xcf, 0xa1, 0x81, 0x83, 0xa4, 0x81, 0x80, 0x30, 0x7e, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x69, 0x54, + 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x11, 0x69, 0x54, 0x75, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x6f, 0x72, + 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, + 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x82, 0x09, 0x00, 0xcb, + 0x06, 0xa3, 0x3b, 0x30, 0xc3, 0x24, 0x03, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0xcc, 0xfb, 0x34, 0x4e, 0xec, 0x27, + 0x05, 0xf9, 0x10, 0xc9, 0xdf, 0x8e, 0x22, 0x21, 0x94, 0x70, 0xe9, 0x74, 0x64, 0x11, 0xce, 0x07, + 0x91, 0xc2, 0x58, 0x0d, 0xff, 0x51, 0x6d, 0x97, 0x64, 0x32, 0x1a, 0x1c, 0xdf, 0x4a, 0x93, 0xdb, + 0x94, 0x62, 0x14, 0xcb, 0x00, 0x13, 0x37, 0x98, 0x0e, 0x3d, 0x96, 0x19, 0x5f, 0x44, 0xc9, 0x11, + 0xd2, 0xc9, 0x8c, 0xa3, 0x19, 0x2f, 0x88, 0x4f, 0x5f, 0x3c, 0x46, 0x56, 0xe2, 0xbd, 0x78, 0x4f, + 0xfe, 0x8e, 0x39, 0xb5, 0xed, 0x37, 0x3e, 0xfb, 0xf6, 0xae, 0x56, 0x2c, 0x49, 0x37, 0x4a, 0x94, + 0x05, 0x4b, 0x8f, 0x67, 0xdb, 0xe6, 0x24, 0xa6, 0x75, 0xae, 0xc8, 0xa2, 0x26, 0x87, 0x70, 0xb8, + 0x1d, 0xc2, 0xfc, 0x8d, 0xff, 0x41, 0x23, 0x8a, 0x01, 0x8a, 0xc3, 0x78, 0x5a, 0x61, 0x4a, 0xed, + 0x48, 0x96, 0xb5, 0x82, 0xa7, 0xaa, 0x2e, 0xb5, 0xed, 0xdd, 0xf4, 0xe6, 0xb5, 0xa1, 0x27, 0x3b, + 0xda, 0xf9, 0x18, 0x26, 0x7e, 0x8e, 0xec, 0xef, 0xe1, 0x00, 0x7d, 0x3d, 0xf7, 0x3d, 0x01, 0x68, + 0x14, 0x92, 0xfc, 0x9c, 0xbb, 0x0a, 0xa1, 0xc3, 0x60, 0x31, 0x16, 0x08, 0x9b, 0xef, 0x4d, 0xaf, + 0x46, 0xc7, 0xcc, 0x4e, 0x05, 0x34, 0xa8, 0x44, 0xb2, 0x85, 0x03, 0x67, 0x6c, 0x31, 0xae, 0xa3, + 0x18, 0xb5, 0x5f, 0x75, 0xae, 0xe0, 0x5a, 0xbf, 0x64, 0x32, 0x2b, 0x28, 0x99, 0x24, 0xcd, 0x01, + 0x34, 0xc2, 0xfc, 0xf1, 0x88, 0xba, 0x8c, 0x9b, 0x90, 0x85, 0x56, 0x6d, 0xaf, 0xd5, 0x2e, 0x88, + 0x12, 0x61, 0x7c, 0x76, 0x33, 0x6b, 0xc4, 0xf7, 0x31, 0x77, 0xe4, 0x02, 0xb7, 0x9e, 0x9c, 0x8c, + 0xbe, 0x04, 0x2e, 0x51, 0xa3, 0x04, 0x4c, 0xcd, 0xe2, 0x71, 0x5e, 0x36, 0xfb, 0xf1, 0x68, 0xf0, + 0xad, 0x37, 0x80, 0x98, 0x26, 0xc0, 0xef, 0x9b, 0x3c +}; + +static const unsigned char url_bag[] = +"" +" " +" signature" +" IIHLRC69w8K+iJQYKEh5U1wo/H2+U27lFzQlLrUWZIqBkd2rvUOcxBJlAG/5rCnq/mNwfhvrRZjpBzC9FzzH4a1mImPPGBYQtkD2pw/deJ67jPymyDlseH85grcDBgbRYaTR4+pbr4XTsMyQ1wEEF8OExKw9pNfHu1XyLg4iS3A=" +" certs" +" " +" MIIDOTCCAiGgAwIBAgIBATANBgkqhkiG9w0BAQQFADB+MRMwEQYDVQQKEwpBcHBsZSBJbmMuMRUwEwYDVQQLEwxpVHVuZXMgU3RvcmUxGjAYBgNVBAMTEWlUdW5lcyBTdG9yZSBSb290MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAGA1UEBxMJQ3VwZXJ0aW5vMB4XDTA3MTAwOTIxNTkxNFoXDTA4MTEwNzIxNTkxNFowgYExEzARBgNVBAoTCkFwcGxlIEluYy4xFTATBgNVBAsTDGlUdW5lcyBTdG9yZTEdMBsGA1UEAxMUaVR1bmVzIFN0b3JlIFVSTCBCYWcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlDdXBlcnRpbm8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOLMu/eV+eSLVEGtn536FkXAsi/vtpXdHpTNS9muEVlvlkubKXdPDd5jV5WnQpAKY4GZrBn8azP9UKBd85nhIb5nqHQHCmH5DpBK9GZPFpoIdXguJSre8pZwQaYEXQGtTt3nXvk9k8OHs5W/9xFLuD7fpkKSIl+0KLPFULdyEtlvAgMBAAGjQjBAMB0GA1UdDgQWBBTd4gDjfN3LFr3b5G8dvUTpC56JZTAfBgNVHSMEGDAWgBSw2uF/qItKaoFdDKGEVkYeau/lzzANBgkqhkiG9w0BAQQFAAOCAQEAIDpkK1CqTNyl7SEZWvUTRYPdZzn9Y4QjnbSQ6hFkF/PClJkXn3TzMW3ojnxNLphKZxOY53s6D/Hf1B5UX2bJDAnfQ/W8d10SPubGJ1FnUZK8KaKeOzAgks5ob9dnOUe4CZKhZ5FyggIJfgd38Q0s8WF474j5OA/5XRPczgjt+OiIfzEVX5Xqpm1TU7T4013eHze5umqAsd9fFxUXdTC+bl9xdj5VOmqUUfOivoiqiBK2/6XAaDIFF/PEnxVou+BpqkdsyTZz/HiQApve+7NONqS58ciq3Ov+wivpVJKxMyFgcXFWb/d2ZTc04i+fGf0OA4QmkSRcAZOxQkv0oggtTw==" +" " +" bag" +" PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlIENvbXB1dGVyLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPiAKCiAgPHBsaXN0IHZlcnNpb249IjEuMCI+CiAgICA8ZGljdD4KICAgICAgCiAgICAgIAogICAgICAKICAgICAgCiAgICAgICAgPGtleT5zdG9yZUZyb250PC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evc3RvcmVGcm9udDwvc3RyaW5nPgogICAgPGtleT5uZXdVc2VyU3RvcmVGcm9udDwva2V5PjxzdHJpbmc+aHR0cDovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9maXJzdExhdW5jaDwvc3RyaW5nPgogICAgPGtleT5uZXdJUG9kVXNlclN0b3JlRnJvbnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9uZXdJUG9kVXNlcj9uZXdJUG9kVXNlcj10cnVlPC9zdHJpbmc+CiAgICA8a2V5Pm5ld1Bob25lVXNlcjwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3Bob25lTGFuZGluZ1BhZ2U8L3N0cmluZz4gICAgICAgICAgICAgICAgICAKICAgIDxrZXk+c2VhcmNoPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTZWFyY2gud29hL3dhL3NlYXJjaDwvc3RyaW5nPgogICAgPGtleT5hZHZhbmNlZFNlYXJjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU2VhcmNoLndvYS93YS9hZHZhbmNlZFNlYXJjaDwvc3RyaW5nPgogICAgPGtleT5zZWFyY2hIaW50czwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU2VhcmNoSGludHMud29hL3dhL2hpbnRzPC9zdHJpbmc+CiAgICA8a2V5PnBhcmVudGFsQWR2aXNvcnk8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9wYXJlbnRhbEFkdmlzb3J5PC9zdHJpbmc+CiAgICA8a2V5PnNvbmdNZXRhRGF0YTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3NvbmdNZXRhRGF0YTwvc3RyaW5nPgogICAgPGtleT5icm93c2U8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9icm93c2U8L3N0cmluZz4KICAgIDxrZXk+YnJvd3NlU3RvcmU8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9icm93c2VTdG9yZTwvc3RyaW5nPgogICAgPGtleT5icm93c2VHZW5yZTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2Jyb3dzZUdlbnJlPC9zdHJpbmc+CiAgICA8a2V5PmJyb3dzZUFydGlzdDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2Jyb3dzZUFydGlzdDwvc3RyaW5nPgogICAgPGtleT5icm93c2VBbGJ1bTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2Jyb3dzZUFsYnVtPC9zdHJpbmc+CiAgICA8a2V5PnZpZXdBbGJ1bTwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdBbGJ1bTwvc3RyaW5nPgogICAgPGtleT52aWV3QXJ0aXN0PC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0FydGlzdDwvc3RyaW5nPgogICAgPGtleT52aWV3Q29tcG9zZXI8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3Q29tcG9zZXI8L3N0cmluZz4KICAgIDxrZXk+dmlld0dlbnJlPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld0dlbnJlPC9zdHJpbmc+CiAgICA8a2V5PnZpZXdQb2RjYXN0PC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1BvZGNhc3Q8L3N0cmluZz4KICAgIDxrZXk+dmlld1B1Ymxpc2hlZFBsYXlsaXN0PC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evdmlld1B1Ymxpc2hlZFBsYXlsaXN0PC9zdHJpbmc+CiAgICA8a2V5PnZpZXdWaWRlbzwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdWaWRlbzwvc3RyaW5nPgogICAgPGtleT5wb2RjYXN0czwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL3ZpZXdQb2RjYXN0RGlyZWN0b3J5PC9zdHJpbmc+CiAgICA8a2V5PmV4dGVybmFsVVJMU2VhcmNoS2V5PC9rZXk+PHN0cmluZz5heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQ8L3N0cmluZz4KICAgIDxrZXk+ZXh0ZXJuYWxVUkxSZXBsYWNlS2V5PC9rZXk+PHN0cmluZz5waG9ib3MuYXBwbGUuY29tPC9zdHJpbmc+CiAgICA8a2V5PnNlbGVjdGVkSXRlbXNQYWdlPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evc2VsZWN0ZWRJdGVtc1BhZ2U8L3N0cmluZz4KCiAgICAKCiAgICAKCiAgICA8a2V5Pm1pbmktc3RvcmU8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9taW5pc3RvcmVWMjwvc3RyaW5nPgogICAgPGtleT5taW5pLXN0b3JlLWZpZWxkczwva2V5PjxzdHJpbmc+YSxraW5kLHA8L3N0cmluZz4KICAgIDxrZXk+bWluaS1zdG9yZS1tYXRjaDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd2EvbWluaXN0b3JlTWF0Y2hWMjwvc3RyaW5nPgogICAgPGtleT5taW5pLXN0b3JlLW1hdGNoLWZpZWxkczwva2V5PjxzdHJpbmc+YW4sZ24sa2luZCxwbjwvc3RyaW5nPgogICAgPGtleT5taW5pLXN0b3JlLXdlbGNvbWU8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS9taW5pc3RvcmVXZWxjb21lP3dpdGhDbGllbnRPcHRJbj0xPC9zdHJpbmc+CgogICAgPGtleT5jb3Zlci1hcnQ8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlU2VydmljZXMud29hL3dhL2NvdmVyQXJ0TWF0Y2g8L3N0cmluZz4KICAgIDxrZXk+Y292ZXItYXJ0LWZpZWxkczwva2V5PjxzdHJpbmc+YSxwPC9zdHJpbmc+CiAgICA8a2V5PmNvdmVyLWFydC1jZC1maWVsZHM8L2tleT48c3RyaW5nPmNkZGI8L3N0cmluZz4KICAgIDxrZXk+Y292ZXItYXJ0LW1hdGNoPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9jb3ZlckFydE1hdGNoPC9zdHJpbmc+CiAgICA8a2V5PmNvdmVyLWFydC1tYXRjaC1maWVsZHM8L2tleT48c3RyaW5nPmNkZGIsYW4scG48L3N0cmluZz4KICAgIDxrZXk+Y292ZXItYXJ0LXVzZXI8L2tleT48c3RyaW5nPmh0dHA6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpQZXJzb25hbGl6ZXIud29hL3dhL2NvdmVyQXJ0VXNlcjwvc3RyaW5nPgoKICAgIDxrZXk+bWF0Y2hVUkxzPC9rZXk+PGFycmF5PjxzdHJpbmc+aHR0cDovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy88L3N0cmluZz48L2FycmF5PgoKICAgIAogICAgPGtleT5saWJyYXJ5LWxpbms8L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlU2VydmljZXMud29hL3dhL2xpYnJhcnlMaW5rPC9zdHJpbmc+CiAgICAKICAgIDxrZXk+bGlicmFyeS1saW5rLWZpZWxkcy1saXN0PC9rZXk+CiAgICA8YXJyYXk+CiAgICAgIDxzdHJpbmc+YW4sY24sZ24sa2luZCxuLHBuPC9zdHJpbmc+CiAgICA8L2FycmF5PgogICAgCiAgICA8a2V5PmxpYnJhcnlMaW5rPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZVNlcnZpY2VzLndvYS93YS9saWJyYXJ5TGluazwvc3RyaW5nPgoKICAgIAogICAgPGtleT5hdmFpbGFibGUtcmluZ3RvbmVzPC9rZXk+PHN0cmluZz5odHRwOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aUGVyc29uYWxpemVyLndvYS93YS9hdmFpbGFibGVSaW5ndG9uZXM8L3N0cmluZz4KCiAgICAKICAgIDxrZXk+Y3JlYXRlLXJpbmd0b25lPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2NyZWF0ZVJpbmd0b25lPC9zdHJpbmc+CiAgICA8a2V5PnJpbmd0b25lLWluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaXNSaW5ndG9uZWFibGU8L3N0cmluZz4KICAgIDxrZXk+cmluZ3RvbmUtaW5mby1maWVsZHMtbGlzdDwva2V5PgogICAgPGFycmF5PgogICAgICAgIDxzdHJpbmc+aWQscyxkc2lkPC9zdHJpbmc+CiAgICA8L2FycmF5PgogICAgCgoKICAgIDxrZXk+bWF4Q29tcHV0ZXJzPC9rZXk+PHN0cmluZz41PC9zdHJpbmc+CiAgICA8a2V5Pm1heFB1Ymxpc2hlZFBsYXlsaXN0SXRlbXM8L2tleT48aW50ZWdlcj4xMDA8L2ludGVnZXI+CiAgICAKICAgIDxrZXk+dHJ1c3RlZERvbWFpbnM8L2tleT4KICAgIDxhcnJheT4KICAgICAgPHN0cmluZz4uYXBwbGUuY29tPC9zdHJpbmc+CiAgICAgIDxzdHJpbmc+LmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0PC9zdHJpbmc+CiAgICAgIDxzdHJpbmc+c3VwcG9ydC5tYWMuY29tPC9zdHJpbmc+CiAgICAgIDxzdHJpbmc+Lml0dW5lcy5jb208L3N0cmluZz4KICAgICAgPHN0cmluZz5pdHVuZXMuY29tPC9zdHJpbmc+CiAgICA8L2FycmF5PgoKICAgIDxrZXk+cGx1cy1pbmZvPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2EvaVR1bmVzUGx1c0xlYXJuTW9yZVBhZ2U8L3N0cmluZz4KCiAgICA8a2V5PmFwcGxldHYteW91dHViZS1hdXRoLXVybDwva2V5PjxzdHJpbmc+aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS88L3N0cmluZz4KICAgIDxrZXk+YXBwbGV0di15b3V0dWJlLXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2dkYXRhLnlvdXR1YmUuY29tLzwvc3RyaW5nPgogICAgPGtleT5pdHVuZXMtcHJlc2VudHMtZGlyZWN0b3J5LXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmVTZXJ2aWNlcy53b2Evd3MvUlNTL2RpcmVjdG9yeTwvc3RyaW5nPgogICAgPGtleT5HaG9zdHJpZGVyPC9rZXk+PHN0cmluZz5ZRVM8L3N0cmluZz4KCiAgICA8a2V5PnAyLXRvcC10ZW48L2tleT48c3RyaW5nPmh0dHA6Ly9heC5waG9ib3MuYXBwbGUuY29tLmVkZ2VzdWl0ZS5uZXQvV2ViT2JqZWN0cy9NWlN0b3JlLndvYS93YS92aWV3VG9wVGVuc0xpc3Q8L3N0cmluZz4KICAgIDxrZXk+cDItc2VydmljZS10ZXJtcy11cmw8L2tleT48c3RyaW5nPmh0dHA6Ly93d3cuYXBwbGUuY29tL3N1cHBvcnQvaXR1bmVzL2xlZ2FsL3Rlcm1zLmh0bWw8L3N0cmluZz4KCiAgICA8a2V5Pm5vdy1wbGF5aW5nLXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL25vd1BsYXlpbmc8L3N0cmluZz4KICAgIDxrZXk+bm93LXBsYXlpbmctbmV0d29yay1kZXRlY3QtdXJsPC9rZXk+PHN0cmluZz5odHRwOi8vYXgucGhvYm9zLmFwcGxlLmNvbS5lZGdlc3VpdGUubmV0L1dlYk9iamVjdHMvTVpTdG9yZS53b2Evd2Evbm93UGxheWluZzwvc3RyaW5nPgogICAgPGtleT5hZGFtaWQtbG9va3VwLXVybDwva2V5PjxzdHJpbmc+aHR0cDovL2F4LnBob2Jvcy5hcHBsZS5jb20uZWRnZXN1aXRlLm5ldC9XZWJPYmplY3RzL01aU3RvcmUud29hL3dhL2FkYW1JZExvb2t1cDwvc3RyaW5nPgoKICAgIAoKICAgIAoKICAgICAgICA8a2V5PmF1dGhlbnRpY2F0ZUFjY291bnQ8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYXV0aGVudGljYXRlPC9zdHJpbmc+CiAgICA8a2V5PmlQaG9uZUFjdGl2YXRpb248L2tleT48c3RyaW5nPmh0dHBzOi8vYWxiZXJ0LmFwcGxlLmNvbS9XZWJPYmplY3RzL0FMQWN0aXZhdGlvbi53b2Evd2EvaVBob25lUmVnaXN0cmF0aW9uPC9zdHJpbmc+CiAgICA8a2V5PmRldmljZS1hY3RpdmF0aW9uPC9rZXk+PHN0cmluZz5odHRwczovL2FsYmVydC5hcHBsZS5jb20vV2ViT2JqZWN0cy9BTEFjdGl2YXRpb24ud29hL3dhL2RldmljZUFjdGl2YXRpb248L3N0cmluZz4KICAgIDxrZXk+YXV0aG9yaXplTWFjaGluZTwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9hdXRob3JpemVNYWNoaW5lPC9zdHJpbmc+CiAgICA8a2V5PmJ1eVByb2R1Y3Q8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvYnV5UHJvZHVjdDwvc3RyaW5nPgogICAgPGtleT5idXlDYXJ0PC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2J1eUNhcnQ8L3N0cmluZz4KICAgIDxrZXk+ZGVhdXRob3JpemVNYWNoaW5lPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2RlYXV0aG9yaXplTWFjaGluZTwvc3RyaW5nPgogICAgPGtleT5tYWNoaW5lQXV0aG9yaXphdGlvbkluZm88L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmFzdEZpbmFuY2Uud29hL3dhL21hY2hpbmVBdXRob3JpemF0aW9uSW5mbzwvc3RyaW5nPgogICAgPGtleT5tb2RpZnlBY2NvdW50PC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2FjY291bnRTdW1tYXJ5PC9zdHJpbmc+CiAgICA8a2V5PnBlbmRpbmdTb25nczwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9wZW5kaW5nU29uZ3M8L3N0cmluZz4KICAgIDxrZXk+c2lnbnVwPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3NpZ251cFdpemFyZDwvc3RyaW5nPgogICAgPGtleT5zb25nRG93bmxvYWREb25lPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZhc3RGaW5hbmNlLndvYS93YS9zb25nRG93bmxvYWREb25lPC9zdHJpbmc+CiAgICA8a2V5PmZvcmdvdHRlblBhc3N3b3JkPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2lGb3Jnb3Q8L3N0cmluZz4KICAgIDxrZXk+bXlJbmZvPC9rZXk+PHN0cmluZz5odHRwczovL215aW5mby5hcHBsZS5jb20vPC9zdHJpbmc+CiAgICA8a2V5Pm5vQU9MQWNjb3VudHM8L2tleT48ZmFsc2UvPgogICAgPGtleT51cGxvYWRQdWJsaXNoZWRQbGF5bGlzdDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS91cGxvYWRQdWJsaXNoZWRQbGF5TGlzdDwvc3RyaW5nPgogICAgPGtleT5sb2dvdXQ8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvbG9nb3V0PC9zdHJpbmc+CiAgICA8a2V5PmFkZFRvQ2FydDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9hZGRUb0NhcnQ8L3N0cmluZz4KICAgIDxrZXk+cmVtb3ZlRnJvbUNhcnQ8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVtb3ZlRnJvbUNhcnQ8L3N0cmluZz4KICAgIDxrZXk+c2hvcHBpbmdDYXJ0PC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3Nob3BwaW5nQ2FydDwvc3RyaW5nPgogICAgPGtleT5iY1VSTHM8L2tleT48YXJyYXk+PHN0cmluZz5odHRwOi8vLnBob2Jvcy5hcHBsZS5jb208L3N0cmluZz48c3RyaW5nPmh0dHA6Ly93d3cuYXRkbXQuY29tPC9zdHJpbmc+PC9hcnJheT4KICAgIDxrZXk+dXBncmFkZVBob25lPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3VwZ3JhZGVQaG9uZTwvc3RyaW5nPgogICAgPGtleT51cGdyYWRlRHJtPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3VwZ3JhZGVEcm08L3N0cmluZz4KICAgIDxrZXk+cmVwb3J0UG9kY2FzdDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9yZXBvcnRQb2RjYXN0PC9zdHJpbmc+CiAgICA8a2V5PmdpZnRQbGF5bGlzdDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9naWZ0U29uZ3NXaXphcmQ8L3N0cmluZz4KICAgIDxrZXk+Z2l2ZS1wbGF5bGlzdDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9naWZ0U29uZ3NXaXphcmQ8L3N0cmluZz4KICAgIDxrZXk+Y2hlY2stZG93bmxvYWQtcXVldWU8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvY2hlY2tEb3dubG9hZFF1ZXVlPC9zdHJpbmc+CiAgICA8a2V5PnNldC1hdXRvLWRvd25sb2FkPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3NldEF1dG9Eb3dubG9hZDwvc3RyaW5nPgogICAgPGtleT5uZXctaXBvZC11c2VyPC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL2lQb2RSZWdpc3RyYXRpb248L3N0cmluZz4KICAgIDxrZXk+bmV3LXR2LXVzZXI8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvaVRWUmVnaXN0cmF0aW9uPC9zdHJpbmc+CiAgICA8a2V5Pm1kNS1taXNtYXRjaDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9tZDVNaXNtYXRjaDwvc3RyaW5nPgogICAgPGtleT5yZXBvcnQtZXJyb3I8L2tleT48c3RyaW5nPmh0dHBzOi8vcGhvYm9zLmFwcGxlLmNvbS9XZWJPYmplY3RzL01aRmluYW5jZS53b2Evd2EvcmVwb3J0RXJyb3JGcm9tQ2xpZW50PC9zdHJpbmc+CiAgICA8a2V5PnVwZGF0ZUFzc2V0PC9rZXk+PHN0cmluZz5odHRwczovL3Bob2Jvcy5hcHBsZS5jb20vV2ViT2JqZWN0cy9NWkZpbmFuY2Uud29hL3dhL3VwZGF0ZUFzc2V0PC9zdHJpbmc+CiAgICA8a2V5PmNyZWF0ZS10b2tlbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jcmVhdGVUb2tlbjwvc3RyaW5nPgogICAgPGtleT5jcmVhdGUtc2Vzc2lvbjwva2V5PjxzdHJpbmc+aHR0cHM6Ly9waG9ib3MuYXBwbGUuY29tL1dlYk9iamVjdHMvTVpGaW5hbmNlLndvYS93YS9jcmVhdGVTZXNzaW9uPC9zdHJpbmc+CiAgICAKCiAgICAgIAogICAgICAKICAgIDwvZGljdD4KICA8L3BsaXN0PgoKCg==" +" " +""; + #endif /* _TRUSTTESTS_TRUST_INTERFACE_H_ */ diff --git a/tests/TrustTests/FrameworkTests/TrustSettingsInterfaceTests.m b/tests/TrustTests/FrameworkTests/TrustSettingsInterfaceTests.m index 8228cb35..a3fc0e34 100644 --- a/tests/TrustTests/FrameworkTests/TrustSettingsInterfaceTests.m +++ b/tests/TrustTests/FrameworkTests/TrustSettingsInterfaceTests.m @@ -116,6 +116,81 @@ "failed to set empty array exceptions for this app: %@", error); is(copiedExceptions = SecTrustStoreCopyCTExceptions(NULL, NULL), NULL, "no exceptions set"); } + +- (NSData *)random +{ + uint8_t random[32]; + (void)SecRandomCopyBytes(kSecRandomDefault, sizeof(random), random); + return [[NSData alloc] initWithBytes:random length:sizeof(random)]; +} + +- (void)testSetTransparentConnections { + CFErrorRef error = NULL; + const CFStringRef TrustTestsAppID = CFSTR("com.apple.trusttests"); + CFArrayRef copiedPins = NULL; + + /* Verify no pins set */ + copiedPins = SecTrustStoreCopyTransparentConnectionPins(NULL, NULL); + XCTAssertEqual(copiedPins, NULL); + if (copiedPins) { + /* If we're startign out with pins set, a lot of the following will also fail, so just skip them */ + CFReleaseNull(copiedPins); + return; + } + + /* Set pin with specified AppID */ + NSArray *pin1 = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : [self random] + }]; + /* Set pin with specified AppID */ + XCTAssert(SecTrustStoreSetTransparentConnectionPins(TrustTestsAppID, (__bridge CFArrayRef)pin1, &error), + "failed to set pins: %@", error); + + /* Copy all pins (with only one set) */ + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(NULL, &error), + "failed to copy all pins: %@", error); + XCTAssertEqualObjects(pin1, (__bridge NSArray*)copiedPins); + CFReleaseNull(copiedPins); + + /* Copy this app's pins */ + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(TrustTestsAppID, &error), + "failed to copy this app's pins: %@", error); + XCTAssertEqualObjects(pin1, (__bridge NSArray*)copiedPins); + CFReleaseNull(copiedPins); + + /* Set a different pin with implied AppID and ensure pins are replaced */ + NSArray *pin2 = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + (__bridge NSString*)kSecTrustStoreSPKIHashKey : [self random] + }]; + XCTAssert(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)pin2, &error), + "failed to set pins: %@", error); + XCTAssertNotEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(TrustTestsAppID, &error), + "failed to copy this app's pins: %@", error); + XCTAssertEqualObjects(pin2, (__bridge NSArray*)copiedPins); + CFReleaseNull(copiedPins); + + /* Set exceptions with bad inputs */ + NSArray *badPins = @[@{ + (__bridge NSString*)kSecTrustStoreHashAlgorithmKey : @"sha256", + @"not a key" : @"not a value" + }]; + XCTAssertFalse(SecTrustStoreSetTransparentConnectionPins(NULL, (__bridge CFArrayRef)badPins, &error)); + if (error) { + is(CFErrorGetCode(error), errSecParam, "bad input produced unxpected error code: %ld", (long)CFErrorGetCode(error)); + } else { + fail("expected failure to set NULL pins"); + } + CFReleaseNull(error); + + /* Reset remaining pins */ + XCTAssert(SecTrustStoreSetTransparentConnectionPins(TrustTestsAppID, NULL, &error), + "failed to reset pins: %@", error); + XCTAssertEqual(NULL, copiedPins = SecTrustStoreCopyTransparentConnectionPins(NULL, &error), + "failed to copy all pins: %@", error); + CFReleaseNull(copiedPins); +} #else // TARGET_OS_BRIDGE - (void)testSkipTests { diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/any_eku.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/any_eku.cer new file mode 100644 index 00000000..3e16b5ec Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/any_eku.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/common_name.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/common_name.cer new file mode 100644 index 00000000..feb03000 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/common_name.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/data_encipher.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/data_encipher.cer new file mode 100644 index 00000000..b00612aa Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/data_encipher.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/digital_signature.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/digital_signature.cer new file mode 100644 index 00000000..4b03c9c8 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/digital_signature.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/email_field.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/email_field.cer new file mode 100644 index 00000000..56652999 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/email_field.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/email_protection.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/email_protection.cer new file mode 100644 index 00000000..94b86416 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/email_protection.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement.cer new file mode 100644 index 00000000..f40d920d Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_decipher_only.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_decipher_only.cer new file mode 100644 index 00000000..083b21c5 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_decipher_only.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_decipher.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_decipher.cer new file mode 100644 index 00000000..372ba025 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_decipher.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_only.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_only.cer new file mode 100644 index 00000000..67f81d04 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_only.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_encipher.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_encipher.cer new file mode 100644 index 00000000..2170c425 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_encipher.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/no_name.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/no_name.cer new file mode 100644 index 00000000..9959fafc Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/no_name.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/non_repudiation.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/non_repudiation.cer new file mode 100644 index 00000000..9033ce10 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/non_repudiation.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/root.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/root.cer new file mode 100644 index 00000000..579d3a45 Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/root.cer differ diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/san_name.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/san_name.cer new file mode 100644 index 00000000..ea9d74da Binary files /dev/null and b/tests/TrustTests/TestData/SMIMEPolicyTests-data/san_name.cer differ diff --git a/tests/TrustTests/TestData/TestCopyProperties_ios-data/TestCopyProperties_ios.plist b/tests/TrustTests/TestData/TestCopyProperties_ios-data/TestCopyProperties_ios.plist index 7305d055..b51f2ae4 100644 --- a/tests/TrustTests/TestData/TestCopyProperties_ios-data/TestCopyProperties_ios.plist +++ b/tests/TrustTests/TestData/TestCopyProperties_ios-data/TestCopyProperties_ios.plist @@ -154,11 +154,11 @@ Leaf googleapis Intermediates - GoogleInternetAuthorityG3 + GoogleTrustServicesCA101 Anchors GlobalSignRootCAR2 VerifyDate - 2018-04-14T19:00:00Z + 2019-11-14T20:00:00Z CertDirectory @@ -182,11 +182,11 @@ Leaf googleapis Intermediates - GoogleInternetAuthorityG3 + GoogleTrustServicesCA101 Anchors AppleRootCA VerifyDate - 2018-04-14T19:00:00Z + 2019-11-14T20:00:00Z ExpectedProperties @@ -219,11 +219,11 @@ Leaf googleapis Intermediates - GoogleInternetAuthorityG3 + GoogleTrustServicesCA101 Anchors AppleRootCA VerifyDate - 2018-04-14T19:00:00Z + 2019-11-14T20:00:00Z ExpectedProperties @@ -260,11 +260,11 @@ Leaf googleapis Intermediates - GoogleInternetAuthorityG3 + GoogleTrustServicesCA101 Anchors GlobalSignRootCAR2 VerifyDate - 2018-04-14T19:00:00Z + 2019-11-14T20:00:00Z ExpectedProperties @@ -295,11 +295,11 @@ Leaf googleapis Intermediates - GoogleInternetAuthorityG3 + GoogleTrustServicesCA101 Anchors GlobalSignRootCAR2 VerifyDate - 2019-04-14T19:00:00Z + 2018-11-14T20:00:00Z ExpectedProperties @@ -330,11 +330,11 @@ Leaf googleapis Intermediates - GoogleInternetAuthorityG3 + GoogleTrustServicesCA101 Anchors GlobalSignRootCAR2 VerifyDate - 2019-04-14T19:00:00Z + 2018-11-14T20:00:00Z ExpectedProperties @@ -368,7 +368,7 @@ Anchors GlobalSignRootCAR2 VerifyDate - 2018-04-14T19:00:00Z + 2019-11-14T20:00:00Z ExpectedProperties @@ -396,7 +396,7 @@ Anchors GlobalSignRootCAR2 VerifyDate - 2019-04-14T19:00:00Z + 2018-11-14T20:00:00Z ExpectedProperties @@ -413,36 +413,6 @@ - - CertDirectory - si-20-sectrust-policies-data - BridgeOSDisable - - MajorTestName - AnchorSHA1 - MinorTestName - OnlyFailure - Policies - - PolicyIdentifier - 1.2.840.113635.100.1.51 - - Leaf - escrow_service_key_049F9D11 - Intermediates - EscrowServiceRootCA101 - Anchors - EscrowServiceRootCA101 - ExpectedProperties - - - type - error - value - Root certificate is not trusted. - - - CertDirectory si-20-sectrust-policies-data diff --git a/tests/TrustTests/TestData/TestTrustdInitialization-data/PinningDB_vINT_MAX/CertificatePinning.plist b/tests/TrustTests/TestData/TestTrustdInitialization-data/PinningDB_vINT_MAX/CertificatePinning.plist new file mode 100644 index 00000000..7c9cee4c --- /dev/null +++ b/tests/TrustTests/TestData/TestTrustdInitialization-data/PinningDB_vINT_MAX/CertificatePinning.plist @@ -0,0 +1,104 @@ + + + + + 2147483647 + + domains + + + labelRegex + ^p..-content$|^p..-content-|^p..-ckdatabase$|^p..-ckdatabase-|^p..-ckshare$|^p..-ckshare-|^p..-ckdevice$|^p..-ckdevice-|^p..-ckcoderouter$|^p..-ckcoderouter-|^gateway|^p..-keyvalueservice$|^p..-keyvalueservice-|^keyvalueservice|^p..-pairingws$|^p..-pairingws-|^pairingws|^metrics + suffix + icloud.com + + + labelRegex + ^p..-content$|^p..-content-|^p..-ckdatabase$|^p..-ckdatabase-|^p..-ckshare$|^p..-ckshare-|^p..-ckdevice$|^p..-ckdevice-|^p..-ckcoderouter$|^p..-ckcoderouter-|^gateway|^p..-keyvalueservice$|^p..-keyvalueservice-|^keyvalueservice|^p..-pairingws$|^p..-pairingws-|^pairingws|^metrics + suffix + icloud.com.cn + + + labelRegex + ^api$ + suffix + apple-cloudkit.com + + + policyName + MMCS + rules + + + AnchorApple + + ChainLength + 3 + CheckIntermediateMarkerOid + 1.2.840.113635.100.6.2.12 + CheckLeafMarkersProdAndQA + + ProdMarker + + 1.2.840.113635.100.6.27.11.2 + + 1.2.840.113635.100.6.48.1 + 1.2.840.113635.100.6.27.11.2 + + + QAMarker + + 1.2.840.113635.100.6.27.11.1 + + 1.2.840.113635.100.6.48.1 + 1.2.840.113635.100.6.27.11.1 + + + + Revocation + AnyRevocationMethod + + + AnchorSHA256 + + /4VqLSUdzYjTZlb0UBJnmM+rqt5AeZxyLeTStds2pzo= + Fq9XqfZ2sKsSYJWqXrre8iqzERnWRKyVzUuT2/Pyaus= + Ma1mSPgQQTjHOPOepDIBMzk+OhjMAilu+Xwqye9nMdA= + Xtt6xDuCoGqHYejXvkl56/JhH33Xm/kcHGtWaiGe12Y= + yzzLt2Ax5eATj43TmiP53kf/w15DwRRM6ifUalqxy18= + 16eg+11+JzHXcelITrze9x1fDD4KKUh4K8g+4OppnvQ= + F5OSegYUVJeJrc4vjzT38LZtDzrjo7hNIewV27pPrcc= + 55PJsC/YqhPiHDEiisywgRlkO3SciYlksXRtRsPUy9I= + + ChainLength + 3 + CheckIntermediateCountry + US + CheckIntermediateOrganization + Apple Inc. + CheckLeafMarkersProdAndQA + + ProdMarker + + 1.2.840.113635.100.6.27.11.2 + + 1.2.840.113635.100.6.48.1 + 1.2.840.113635.100.6.27.11.2 + + + QAMarker + + 1.2.840.113635.100.6.27.11.1 + + 1.2.840.113635.100.6.48.1 + 1.2.840.113635.100.6.27.11.1 + + + + Revocation + AnyRevocationMethod + + + + + diff --git a/tests/TrustTests/TestRunners/Base.lproj/LaunchScreen.storyboard b/tests/TrustTests/TestRunners/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index bfa36129..00000000 --- a/tests/TrustTests/TestRunners/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/TrustTests/TestRunners/Base.lproj/Main.storyboard b/tests/TrustTests/TestRunners/Base.lproj/Main.storyboard deleted file mode 100644 index 942f0bc4..00000000 --- a/tests/TrustTests/TestRunners/Base.lproj/Main.storyboard +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/TrustTests/TestRunners/main.m b/tests/TrustTests/TestRunners/main.m index c34bf518..ab6c189b 100644 --- a/tests/TrustTests/TestRunners/main.m +++ b/tests/TrustTests/TestRunners/main.m @@ -23,8 +23,7 @@ @implementation TestRunner - (instancetype)initWithBundlePath:(NSString *)path andTestNames:(NSArray *)names { - self = [super init]; - if (self) { + if ((self = [super init])) { NSError *error = nil; _bundle = [NSBundle bundleWithPath:path]; @@ -112,8 +111,11 @@ [self testLogWithFormat:@"Test Suite '%@' started at %@\n", testSuite.name, [self.dateFormatter stringFromDate:testSuite.testRun.startDate]]; } -- (void)testSuite:(XCTestSuite *)testSuite didFailWithDescription:(NSString *)description inFile:(nullable NSString *)filePath atLine:(NSUInteger)lineNumber +- (void)testSuite:(XCTestSuite *)testSuite didRecordIssue:(XCTIssue *)issue { + NSString *filePath = [issue.sourceCodeContext.location.fileURL absoluteString]; + NSInteger lineNumber = issue.sourceCodeContext.location.lineNumber; + NSString *description = issue.description; [self testLogWithFormat:@"%@:%lu: error: %@ : %@\n", ((nil != filePath) ? filePath : @""), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testSuite.name, description]; } @@ -136,8 +138,11 @@ [self testLogWithFormat:@"Test Case '%@' started.\n", testCase.name]; } -- (void)testCase:(XCTestCase *)testCase didFailWithDescription:(NSString *)description inFile:(nullable NSString *)filePath atLine:(NSUInteger)lineNumber +- (void)testCase:(XCTestCase *)testCase didRecordIssue:(XCTIssue *)issue { + NSString *filePath = [issue.sourceCodeContext.location.fileURL absoluteString]; + NSInteger lineNumber = issue.sourceCodeContext.location.lineNumber; + NSString *description = issue.description; [self testLogWithFormat:@"%@:%lu: error: %@ : %@\n", ((nil != filePath) ? filePath : @""), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testCase.name, description]; } diff --git a/tests/TrustTests/TestRunners/trusttests_entitlements.plist b/tests/TrustTests/TestRunners/trusttests_entitlements.plist index 8df24b43..bac16a08 100644 --- a/tests/TrustTests/TestRunners/trusttests_entitlements.plist +++ b/tests/TrustTests/TestRunners/trusttests_entitlements.plist @@ -14,5 +14,15 @@ com.apple.MobileAsset.PKITrustSupplementals + com.apple.security.exception.files.absolute-path.read-only + + /System/Library/Caches/apticket.der + + com.apple.system.diagnostics.iokit-properties + + com.apple.private.AuthorizationServices + + com.apple.trust-settings.admin + diff --git a/tests/TrustTests/TrustEvaluationTestHelpers.h b/tests/TrustTests/TrustEvaluationTestHelpers.h index 7eabecd0..4b9b01d7 100644 --- a/tests/TrustTests/TrustEvaluationTestHelpers.h +++ b/tests/TrustTests/TrustEvaluationTestHelpers.h @@ -30,6 +30,9 @@ NS_ASSUME_NONNULL_BEGIN +NSURL * _Nullable setUpTmpDir(void); +int ping_host(char *host_name); + @interface TestTrustEvaluation : NSObject @property (assign, nonnull) SecTrustRef trust; @property NSString *fullTestName; @@ -54,6 +57,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype _Nullable) initWithTrustDictionary:(NSDictionary *)testDict; - (void)addAnchor:(SecCertificateRef)certificate; +- (void)setNeedsEvaluation; - (bool)evaluate:(out NSError * _Nullable __autoreleasing * _Nullable)outError; - (bool)evaluateForExpectedResults:(out NSError * _Nullable __autoreleasing *)outError; diff --git a/tests/TrustTests/TrustEvaluationTestHelpers.m b/tests/TrustTests/TrustEvaluationTestHelpers.m index 9bf277a0..7e309dd5 100644 --- a/tests/TrustTests/TrustEvaluationTestHelpers.m +++ b/tests/TrustTests/TrustEvaluationTestHelpers.m @@ -10,11 +10,20 @@ #include #include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include "TrustEvaluationTestHelpers.h" @@ -98,6 +107,10 @@ } } +- (void)setNeedsEvaluation { + SecTrustSetNeedsEvaluation(_trust); +} + - (bool)evaluate:(out NSError * _Nullable __autoreleasing *)outError { CFErrorRef localError = nil; _trustResult = kSecTrustResultInvalid; @@ -276,6 +289,50 @@ errOut: return false; } +- (bool)addThirdPartyPinningPolicyChecks:(CFDictionaryRef)properties + policy:(SecPolicyRef)policy +{ + if (!properties) { + return true; + } + + CFStringRef spkiSHA256Options[] = { + kSecPolicyCheckLeafSPKISHA256, + kSecPolicyCheckCAspkiSHA256, + }; + + for (size_t i = 0; i < sizeof(spkiSHA256Options)/sizeof(spkiSHA256Options[0]); i++) { + CFArrayRef spkiSHA256StringArray = CFDictionaryGetValue(properties, spkiSHA256Options[i]); + // Relevant property is not set. + if (!spkiSHA256StringArray) { + continue; + } + require_string(isArray(spkiSHA256StringArray), errOut, "SPKISHA256 property is not an array"); + + CFMutableArrayRef spkiSHA256DataArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + require_string(spkiSHA256DataArray, errOut, "failed to allocate memory for the SPKISHA256 data array"); + + for (CFIndex j = 0; j < CFArrayGetCount(spkiSHA256StringArray); j++) { + CFStringRef spkiSHA256String = CFArrayGetValueAtIndex(spkiSHA256StringArray, j); + require_string(isString(spkiSHA256String), errOut, "SPKISHA256 property array element is not a string"); + CFDataRef spkiSHA256Data = CreateCFDataFromBase64CFString(spkiSHA256String); + // 'spkiSHA256Data' is optional because we want to allow empty strings. + if (spkiSHA256Data) { + CFArrayAppendValue(spkiSHA256DataArray, spkiSHA256Data); + } + CFReleaseNull(spkiSHA256Data); + } + + SecPolicySetOptionsValue(policy, spkiSHA256Options[i], spkiSHA256DataArray); + CFReleaseNull(spkiSHA256DataArray); + } + + return true; + +errOut: + return false; +} + - (bool)addPolicy:(NSDictionary *)policyDict { SecPolicyRef policy = NULL; @@ -283,14 +340,17 @@ errOut: NSDictionary *policyProperties = [(NSDictionary *)policyDict objectForKey:kSecTrustTestPolicyProperties]; require_string(policyIdentifier, errOut, "failed to get policy OID"); + CFDictionaryRef properties = (__bridge CFDictionaryRef)policyProperties; policy = SecPolicyCreateWithProperties((__bridge CFStringRef)policyIdentifier, - (__bridge CFDictionaryRef)policyProperties); + properties); require_string(policy, errOut, "failed to create properties for policy OID"); + require_string([self addThirdPartyPinningPolicyChecks:properties policy:policy], errOut, "failed to parse properties for third-party-pinning policy checks"); [self.policies addObject:(__bridge id)policy]; CFReleaseNull(policy); return true; errOut: + CFReleaseNull(policy); return false; } @@ -502,3 +562,86 @@ errOut: } @end + +int ping_host(char *host_name) +{ + struct sockaddr_in pin; + struct hostent *nlp_host; + struct in_addr addr; + int sd = 0; + int port = 80; + int retries = 5; // we try 5 times, then give up + char **h_addr_list = NULL; + + while ((nlp_host=gethostbyname(host_name)) == 0 && retries--) { + printf("Resolve Error! (%s) %d\n", host_name, h_errno); + sleep(1); + } + if (nlp_host == 0) { + return 0; + } + + bzero(&pin,sizeof(pin)); + pin.sin_family=AF_INET; + pin.sin_addr.s_addr=htonl(INADDR_ANY); + h_addr_list = malloc(nlp_host->h_length * sizeof(char *)); + memcpy(h_addr_list, nlp_host->h_addr_list, nlp_host->h_length * sizeof(char *)); + memcpy(&addr, h_addr_list[0], sizeof(struct in_addr)); + pin.sin_addr.s_addr=addr.s_addr; + pin.sin_port=htons(port); + + sd=socket(AF_INET,SOCK_STREAM,0); + + if (connect(sd,(struct sockaddr*)&pin,sizeof(pin)) == -1) { + printf("connect error! (%s) %d\n", host_name, errno); + close(sd); + free(h_addr_list); + return 0; + } + close(sd); + free(h_addr_list); + return 1; +} + +static int current_dir = -1; +static char *home_var = NULL; + +NSURL *setUpTmpDir(void) { + /* Set up TMP directory for trustd's files */ + int ok = 0; + NSError* error = nil; + NSString* pid = [NSString stringWithFormat: @"tst-%d", [[NSProcessInfo processInfo] processIdentifier]]; + NSURL* tmpDirURL = [[NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES] URLByAppendingPathComponent:pid]; + ok = (bool)tmpDirURL; + + if (current_dir == -1 && home_var == NULL) { + ok = ok && [[NSFileManager defaultManager] createDirectoryAtURL:tmpDirURL + withIntermediateDirectories:NO + attributes:NULL + error:&error]; + + NSURL* libraryURL = [tmpDirURL URLByAppendingPathComponent:@"Library"]; + NSURL* preferencesURL = [tmpDirURL URLByAppendingPathComponent:@"Preferences"]; + + ok = (ok && (current_dir = open(".", O_RDONLY) >= 0) + && (chdir([tmpDirURL fileSystemRepresentation]) >= 0) + && (setenv("HOME", [tmpDirURL fileSystemRepresentation], 1) >= 0) + && (bool)(home_var = getenv("HOME"))); + + ok = ok && [[NSFileManager defaultManager] createDirectoryAtURL:libraryURL + withIntermediateDirectories:NO + attributes:NULL + error:&error]; + + ok = ok && [[NSFileManager defaultManager] createDirectoryAtURL:preferencesURL + withIntermediateDirectories:NO + attributes:NULL + error:&error]; + } + + if (ok > 0) { + return tmpDirURL; + } + + return nil; +} diff --git a/tests/TrustTests/gen_test_plist.py b/tests/TrustTests/gen_test_plist.py index ee7c7307..c6a37679 100644 --- a/tests/TrustTests/gen_test_plist.py +++ b/tests/TrustTests/gen_test_plist.py @@ -32,8 +32,10 @@ for filename in test_files: test_command = Foundation.NSMutableArray.array() test_command.append('/AppleInternal/CoreOS/tests/Security/TrustTests') - test_command.append('-c ' + match.group(1)) - test_command.append('-t TrustTests') + test_command.append('-c') + test_command.append(match.group(1)) + test_command.append('-t') + test_command.append('TrustTests') test_dictionary['Command'] = test_command diff --git a/tests/secdmockaks/mockaks.h b/tests/secdmockaks/mockaks.h index 068c33fb..a27a51ce 100644 --- a/tests/secdmockaks/mockaks.h +++ b/tests/secdmockaks/mockaks.h @@ -80,6 +80,8 @@ int MKBForegroundUserSessionID( CFErrorRef _Nullable * _Nullable error); + (void)failNextDecryptRefKey:(NSError* _Nonnull) decryptRefKeyError; + (NSError * _Nullable)popDecryptRefKeyFailure; ++ (void)setOperationsUntilUnlock:(int)val; + @end #endif // OBJC2 diff --git a/tests/secdmockaks/mockaks.m b/tests/secdmockaks/mockaks.m index 4bf815b8..ca4f9a56 100644 --- a/tests/secdmockaks/mockaks.m +++ b/tests/secdmockaks/mockaks.m @@ -52,6 +52,8 @@ #import "tests/secdmockaks/generated_source/MockAKSRefKey.h" #import "tests/secdmockaks/generated_source/MockAKSOptionalParameters.h" +#include "utilities/simulatecrash_assert.h" + bool hwaes_key_available(void) { return false; @@ -70,6 +72,8 @@ static NSMutableDictionary* _lockedStates = nil; static dispatch_queue_t _mutabilityQueue = nil; static keybag_state_t _keybag_state = keybag_state_unlocked | keybag_state_been_unlocked; static NSMutableArray* _decryptRefKeyErrors = nil; +static int _operationsUntilUnlock = -1; // -1: don't care, 0: be unlocked, posnum: decrement and be locked + /* * Method that limit where this rather in-secure version of AKS can run */ @@ -222,6 +226,24 @@ static NSMutableArray* _decryptRefKeyErrors = nil; return error; } ++ (void)setOperationsUntilUnlock:(int)val { + _operationsUntilUnlock = val; +} + ++ (void)updateOperationsUntilUnlock { + if (_operationsUntilUnlock == -1) { + return; + } + + if (_operationsUntilUnlock == 0) { + _operationsUntilUnlock = -1; + [SecMockAKS unlockAllClasses]; + return; + } + + --_operationsUntilUnlock; +} + @end @@ -309,6 +331,8 @@ aks_wrap_key(const void * key, int key_size, keyclass_t key_class, keybag_handle return kAKSReturnBusy; } + [SecMockAKS updateOperationsUntilUnlock]; + // Assumes non-device keybags are asym if ([SecMockAKS isLocked:key_class] && handle == KEYBAG_DEVICE) { return kAKSReturnNoPermission; @@ -349,6 +373,8 @@ aks_unwrap_key(const void * wrapped_key, int wrapped_key_size, keyclass_t key_cl return kAKSReturnBusy; } + [SecMockAKS updateOperationsUntilUnlock]; + if ([SecMockAKS isLocked:key_class]) { return kAKSReturnNoPermission; } @@ -408,7 +434,7 @@ aks_unwrap_key(const void * wrapped_key, int wrapped_key_size, keyclass_t key_cl CFTypeRef cf = NULL; CFErrorRef cferror = NULL; uint8_t *der = (uint8_t *)params.externalData.bytes; - der_decode_plist(NULL, false, &cf, &cferror, der, der + params.externalData.length); + der_decode_plist(NULL, &cf, &cferror, der, der + params.externalData.length); if (cf == NULL) { *error = [NSError errorWithDomain:@"foo" code:kAKSReturnBadArgument userInfo:nil]; return NULL; @@ -610,6 +636,14 @@ aks_ref_key_delete(aks_ref_key_t handle, const uint8_t *der_params, size_t der_p return kAKSReturnSuccess; } +const uint8_t * +aks_ref_key_get_public_key(aks_ref_key_t handle, size_t *pub_key_len) +{ + static const uint8_t dummy_key[0x41] = { 0 }; + *pub_key_len = sizeof(dummy_key); + return dummy_key; +} + int aks_operation_optional_params(const uint8_t * access_groups, size_t access_groups_len, const uint8_t * external_data, size_t external_data_len, const void * acm_handle, int acm_handle_len, void ** out_der, size_t * out_der_len) { @@ -720,6 +754,126 @@ aks_generation(keybag_handle_t handle, return kAKSReturnSuccess; } +kern_return_t +aks_get_device_state(keybag_handle_t handle, aks_device_state_s *device_state) +{ + // Probably not legal + return kAKSReturnError; +} + +int +aks_system_key_get_public(aks_system_key_type_t type, aks_system_key_generation_t generation, const uint8_t *der_params, size_t der_params_len, uint8_t **pub_out, size_t *pub_len_out) +{ + return kAKSReturnError; +} + +int +aks_system_key_operate(aks_system_key_type_t type, aks_system_key_operation_t operation, const uint8_t *der_params, size_t der_params_len) +{ + return kAKSReturnError; +} + +int +aks_system_key_collection(aks_system_key_type_t type, aks_system_key_generation_t generation, const uint8_t *der_params, size_t der_params_len, uint8_t **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} + +int +aks_system_key_attest(aks_system_key_type_t type, aks_system_key_generation_t generation, aks_ref_key_t ref_key, const uint8_t *der_params, size_t der_params_len, uint8_t **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} + +int +aks_gid_attest(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, void **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} + +int +aks_sik_attest(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, void **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} + +/* Unimplemented aks_ref_key functions */ + +int +aks_ref_key_compute_key(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, const uint8_t *pub_key, size_t pub_key_len, void **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} + +int +aks_ref_key_attest(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, aks_ref_key_t handle2, void **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} + +int +aks_ref_key_sign(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, const uint8_t *digest, size_t digest_len, void **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} + +int +aks_ref_key_ecies_transcode(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, const uint8_t *public_key, size_t public_key_len, const uint8_t *cipher_txt_in, size_t cipher_txt_in_len, uint8_t **cipher_txt_out, size_t *cipher_txt_out_len) +{ + return kAKSReturnError; +} + +keyclass_t +aks_ref_key_get_key_class(aks_ref_key_t handle) +{ + return key_class_a; +} + +aks_key_type_t +aks_ref_key_get_type(aks_ref_key_t handle) +{ + return key_type_sym; +} + +/* AKS Params (unimplemented) */ + +aks_params_t aks_params_create(const uint8_t *der_params, size_t der_params_len) +{ + return NULL; +} + +int aks_params_free(aks_params_t *params) +{ + return kAKSReturnSuccess; +} + +int +aks_params_set_data(aks_params_t params, aks_params_key_t key, const void *value, size_t length) +{ + return kAKSReturnError; +} + +int +aks_params_get_der(aks_params_t params, uint8_t **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} + +int +aks_params_set_number(aks_params_t params, aks_params_key_t key, int64_t *num) +{ + return kAKSReturnError; +} + +// This is in libaks_internal.h, which doesn't appear to be in the SDK. +int aks_ref_key_enable_test_keys(keybag_handle_t handle, const uint8_t *passcode, size_t passcode_len); +int +aks_ref_key_enable_test_keys(keybag_handle_t handle, const uint8_t *passcode, size_t passcode_len) +{ + abort(); + return kAKSReturnError; +} + CFStringRef kMKBDeviceModeMultiUser = CFSTR("kMKBDeviceModeMultiUser"); CFStringRef kMKBDeviceModeSingleUser = CFSTR("kMKBDeviceModeSingleUser"); CFStringRef kMKBDeviceModeKey = CFSTR("kMKBDeviceModeKey"); @@ -772,82 +926,6 @@ int MKBForegroundUserSessionID( CFErrorRef * error) return kMobileKeyBagSuccess; } -const CFTypeRef kAKSKeyAcl = (CFTypeRef)CFSTR("kAKSKeyAcl"); -const CFTypeRef kAKSKeyAclParamRequirePasscode = (CFTypeRef)CFSTR("kAKSKeyAclParamRequirePasscode"); - -const CFTypeRef kAKSKeyOpDefaultAcl = (CFTypeRef)CFSTR("kAKSKeyOpDefaultAcl"); -const CFTypeRef kAKSKeyOpEncrypt = (CFTypeRef)CFSTR("kAKSKeyOpEncrypt"); -const CFTypeRef kAKSKeyOpDecrypt = (CFTypeRef)CFSTR("kAKSKeyOpDecrypt"); -const CFTypeRef kAKSKeyOpSync = (CFTypeRef)CFSTR("kAKSKeyOpSync"); -const CFTypeRef kAKSKeyOpDelete = (CFTypeRef)CFSTR("kAKSKeyOpDelete"); -const CFTypeRef kAKSKeyOpCreate = (CFTypeRef)CFSTR("kAKSKeyOpCreate"); -const CFTypeRef kAKSKeyOpSign = (CFTypeRef)CFSTR("kAKSKeyOpSign"); -const CFTypeRef kAKSKeyOpSetKeyClass = (CFTypeRef)CFSTR("kAKSKeyOpSetKeyClass"); -const CFTypeRef kAKSKeyOpWrap = (CFTypeRef)CFSTR("kAKSKeyOpWrap"); -const CFTypeRef kAKSKeyOpUnwrap = (CFTypeRef)CFSTR("kAKSKeyOpUnwrap"); -const CFTypeRef kAKSKeyOpComputeKey = (CFTypeRef)CFSTR("kAKSKeyOpComputeKey"); -const CFTypeRef kAKSKeyOpAttest = (CFTypeRef)CFSTR("kAKSKeyOpAttest"); -const CFTypeRef kAKSKeyOpTranscrypt = (CFTypeRef)CFSTR("kAKSKeyOpTranscrypt"); -const CFTypeRef kAKSKeyOpECIESEncrypt = (CFTypeRef)CFSTR("kAKSKeyOpECIESEncrypt"); -const CFTypeRef kAKSKeyOpECIESDecrypt = (CFTypeRef)CFSTR("kAKSKeyOpECIESDecrypt"); -const CFTypeRef kAKSKeyOpECIESTranscode = (CFTypeRef)CFSTR("kAKSKeyOpECIESTranscode"); - - -TKTokenRef TKTokenCreate(CFDictionaryRef attributes, CFErrorRef *error) -{ - return NULL; -} - -CFTypeRef TKTokenCopyObjectData(TKTokenRef token, CFDataRef objectID, CFErrorRef *error) -{ - return NULL; -} - -CFDataRef TKTokenCreateOrUpdateObject(TKTokenRef token, CFDataRef objectID, CFMutableDictionaryRef attributes, CFErrorRef *error) -{ - return NULL; -} - -CFDataRef TKTokenCopyObjectAccessControl(TKTokenRef token, CFDataRef objectID, CFErrorRef *error) -{ - return NULL; -} -bool TKTokenDeleteObject(TKTokenRef token, CFDataRef objectID, CFErrorRef *error) -{ - return false; -} - -CFDataRef TKTokenCopyPublicKeyData(TKTokenRef token, CFDataRef objectID, CFErrorRef *error) -{ - return NULL; -} - -CFTypeRef TKTokenCopyOperationResult(TKTokenRef token, CFDataRef objectID, CFIndex secKeyOperationType, CFArrayRef algorithm, - CFIndex secKeyOperationMode, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) -{ - return NULL; -} - -CF_RETURNS_RETAINED CFDictionaryRef TKTokenControl(TKTokenRef token, CFDictionaryRef attributes, CFErrorRef *error) -{ - return NULL; -} - -CFTypeRef LACreateNewContextWithACMContext(CFDataRef acmContext, CFErrorRef *error) -{ - return NULL; -} - -CFDataRef LACopyACMContext(CFTypeRef context, CFErrorRef *error) -{ - return NULL; -} - -bool LAEvaluateAndUpdateACL(CFTypeRef context, CFDataRef acl, CFTypeRef operation, CFDictionaryRef hints, CFDataRef *updatedACL, CFErrorRef *error) -{ - return false; -} - ACMContextRef ACMContextCreateWithExternalForm(const void *externalForm, size_t dataLength) { diff --git a/tests/secdmockaks/mockaksKeychain.m b/tests/secdmockaks/mockaksKeychain.m index d69762fe..0f922675 100644 --- a/tests/secdmockaks/mockaksKeychain.m +++ b/tests/secdmockaks/mockaksKeychain.m @@ -31,6 +31,7 @@ #include "OSX/sec/Security/SecItemShim.h" #import "server_security_helpers.h" #import "spi.h" +#import "utilities/SecAKSWrappers.h" #import #import #import "utilities/der_plist.h" @@ -45,6 +46,10 @@ #import #import "mockaks.h" +#import + +#import + #import "secdmock_db_version_10_5.h" #import "secdmock_db_version_11_1.h" @@ -363,7 +368,8 @@ - (void)testCreateSampleDatabase { -#if USE_KEYSTORE + // The keychain code only does the right thing with generation count if TARGET_HAS_KEYSTORE +#if TARGET_HAS_KEYSTORE id mock = OCMClassMock([SecMockAKS class]); OCMStub([mock useGenerationCount]).andReturn(true); #endif @@ -383,16 +389,22 @@ */ [self findManyItems:50]; + +#if TARGET_HAS_KEYSTORE + [mock stopMocking]; +#endif } - (void)testTestAKSGenerationCount { -#if USE_KEYSTORE +#if TARGET_HAS_KEYSTORE id mock = OCMClassMock([SecMockAKS class]); OCMStub([mock useGenerationCount]).andReturn(true); [self createManyItems]; [self findManyItems:50]; + + [mock stopMocking]; #endif } @@ -403,7 +415,7 @@ unsigned n = 0; // We need a fresh directory to plop down our SQLite data - SetCustomHomeURLString((__bridge CFStringRef)[self createKeychainDirectoryWithSubPath:@"loadManualDB"]); + SecSetCustomHomeURLString((__bridge CFStringRef)[self createKeychainDirectoryWithSubPath:@"loadManualDB"]); NSString* path = CFBridgingRelease(__SecKeychainCopyPath()); // On macOS the full path gets created, on iOS not (yet?) [self createKeychainDirectoryWithSubPath:@"loadManualDB/Library/Keychains"]; @@ -694,7 +706,7 @@ XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, &output), errSecSuccess, "Found key in keychain"); XCTAssertNotNil((__bridge id)output, "got output from SICM"); XCTAssertEqual(CFGetTypeID(output), CFDictionaryGetTypeID(), "output is a dictionary"); - XCTAssertEqual(CFDictionaryGetValue(output, (id)kSecAttrKeyType), (__bridge CFNumberRef)[NSNumber numberWithUnsignedInt:0x80000001L], "keytype is unchanged"); + XCTAssertEqualObjects((__bridge NSNumber*)CFDictionaryGetValue(output, (id)kSecAttrKeyType), [NSNumber numberWithUnsignedInt:0x80000001L], "keytype is unchanged"); } - (NSData *)objectToDER:(NSDictionary *)dict @@ -717,7 +729,7 @@ } #if !TARGET_OS_WATCH -/* this should be enabled for watch too, but that cause a crash in the mock aks layer */ +/* this should be enabled for watch too, but that causes a crash in the mock aks layer */ - (void)testUpgradeWithBadACLKey { @@ -782,6 +794,7 @@ CFReleaseNull(localError); return true; }); + SecKeychainDbForceClose(); SecKeychainDbReset(NULL); XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound, "should successfully get item"); @@ -835,21 +848,30 @@ NSMutableData *mutatedData = [data mutableCopy]; - if (counter < mutatedData.length) { + // This used to loop over all (~850!) bytes of the data but that's too slow. We now do first 50, last 50 and 20 random bytes + if (counter < 50) { mutatedDatabase = true; ((uint8_t *)[mutatedData mutableBytes])[counter] = 'X'; - counter++; + ++counter; + } else if (counter < 70) { + mutatedDatabase = true; + size_t idx = 50 + arc4random_uniform((uint32_t)(mutatedData.length - 100)); + ((uint8_t *)[mutatedData mutableBytes])[idx] = 'X'; + ++counter; + } else if (counter < 120) { + mutatedDatabase = true; + size_t idx = mutatedData.length - (counter - 70 - 1); + ((uint8_t *)[mutatedData mutableBytes])[idx] = 'X'; + ++counter; } else { counter = 0; } - NSString *mutateString = [NSString stringWithFormat:@"UPDATE genp SET data=x'%@'", [mutatedData hexString]]; ok &= SecDbPrepare(dbt, (__bridge CFStringRef)mutateString, &localError2, ^(sqlite3_stmt *stmt) { - ok = SecDbStep(dbt, stmt, NULL, ^(bool *stop) { - }); + ok = SecDbStep(dbt, stmt, NULL, NULL); }); XCTAssertTrue(ok, "corruption should be successful: %@", localError2); CFReleaseNull(localError2); @@ -858,6 +880,7 @@ }); // force it to reload + SecKeychainDbForceClose(); SecKeychainDbReset(NULL); //dont care about result, we might have done a good number on this item @@ -907,7 +930,99 @@ XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess, "should successfully get item"); } +// This test fails before rdar://problem/60028419 because the keystore fails to check for errSecInteractionNotAllowed, +// tries to recreate the "broken" metadata key and if the keychain unlocks at the exact right moment succeeds and causes +// data loss. +- (void)testMetadataKeyRaceConditionFixed +{ + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"TestAccount-0", + (id)kSecAttrService : @"TestService", + (id)kSecValueData : [@"data" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecUseDataProtectionKeychain : @(YES), + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked, + } mutableCopy]; + // Create item 1 + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + // Drop metadata keys + SecKeychainDbForceClose(); + SecKeychainDbReset(NULL); + [SecMockAKS setOperationsUntilUnlock:1]; // The first call is the metadata key unwrap to allow encrypting the item + [SecMockAKS lockClassA]; + + query[(id)kSecAttrAccount] = @"TestAcount-1"; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecInteractionNotAllowed); + + query[(id)kSecAttrAccount] = @"TestAccount-0"; + query[(id)kSecValueData] = nil; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + [SecMockAKS setOperationsUntilUnlock:-1]; +} + +// A test for if LAContext can reasonably be used +// Note that this test can currently _only_ run on iOS in the simulator; on the actual platforms it tries to access +// real AKS/biometrics, which fails in automation environments. +#if TARGET_OS_OSX || TARGET_OS_SIMULATOR + - (void)testLAContext +{ + NSMutableDictionary* simplequery = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"TestAccount-0", + (id)kSecAttrService : @"TestService", + (id)kSecValueData : [@"data" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecUseDataProtectionKeychain : @(YES), + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked, + } mutableCopy]; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)simplequery, NULL), errSecSuccess, "Succeeded in adding simple item to keychain"); + + CFErrorRef cferror = NULL; + SecAccessControlRef access = SecAccessControlCreateWithFlags(nil, + kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, + kSecAccessControlUserPresence, + &cferror); + + XCTAssertNil((__bridge NSError*)cferror, "Should be no error creating an access control"); + + LAContext* context = [[LAContext alloc] init]; + +#if TARGET_OS_IOS || TARGET_OS_OSX + // This field is only usable on iPhone/macOS. It isn't stricly necessary for this test, though. + context.touchIDAuthenticationAllowableReuseDuration = 10; +#endif + + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"TestAccount-LAContext", + (id)kSecAttrService : @"TestService", + (id)kSecValueData : [@"data" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecUseDataProtectionKeychain : @(YES), + (id)kSecAttrAccessControl : (__bridge id)access, + (id)kSecUseAuthenticationContext : context, + } mutableCopy]; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess, "Succeeded in adding LA-protected item to keychain"); + + NSMutableDictionary* findquery = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"TestAccount-LAContext", + (id)kSecAttrService : @"TestService", + (id)kSecUseDataProtectionKeychain : @(YES), + (id)kSecUseAuthenticationContext : context, + (id)kSecReturnAttributes: @YES, + (id)kSecReturnData: @YES, + } mutableCopy]; + + CFTypeRef output = NULL; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)findquery, &output), errSecSuccess, "Found key in keychain"); + + XCTAssertNotNil((__bridge id)output, "Should have received something back from keychain"); + CFReleaseNull(output); +} +#endif // TARGET_OS_OSX || TARGET_OS_SIMULATOR #endif /* USE_KEYSTORE */ diff --git a/tests/secdmockaks/mockaksWatchDog.m b/tests/secdmockaks/mockaksWatchDog.m index 59bdc651..bfe1a3ff 100644 --- a/tests/secdmockaks/mockaksWatchDog.m +++ b/tests/secdmockaks/mockaksWatchDog.m @@ -7,7 +7,7 @@ #import #import "mockaksxcbase.h" -#import "SecdWatchdog.h" +#import "ipc/SecdWatchdog.h" @interface mockaksWatchDog : mockaksxcbase @property (assign) uint64_t diskusage; diff --git a/tests/secdmockaks/mockaksxcbase.m b/tests/secdmockaks/mockaksxcbase.m index 86670e17..58cfa863 100644 --- a/tests/secdmockaks/mockaksxcbase.m +++ b/tests/secdmockaks/mockaksxcbase.m @@ -84,12 +84,12 @@ NSString* homeDirUUID; NSString* testName = [self.name componentsSeparatedByString:@" "][1]; testName = [testName stringByReplacingOccurrencesOfString:@"]" withString:@""]; - secnotice("ckkstest", "Beginning test %@", testName); + secnotice("mockaks", "Beginning test %@", testName); self.testHomeDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@/%@/", homeDirUUID, testName]]; [self createKeychainDirectory]; - SetCustomHomeURLString((__bridge CFStringRef) self.testHomeDirectory); + SecSetCustomHomeURLString((__bridge CFStringRef) self.testHomeDirectory); SecKeychainDbReset(NULL); // Actually load the database. @@ -98,13 +98,29 @@ NSString* homeDirUUID; - (void)tearDown { + NSURL* keychainDir = (NSURL*)CFBridgingRelease(SecCopyHomeURL()); + + SecKeychainDbForceClose(); + + // Only perform the desctructive step if the url matches what we expect! + if([keychainDir.path hasPrefix:self.testHomeDirectory]) { + secnotice("mockaks", "Removing test-specific keychain directory at %@", keychainDir); + + NSError* removeError = nil; + [[NSFileManager defaultManager] removeItemAtURL:keychainDir error:&removeError]; + + XCTAssertNil(removeError, "Should have been able to remove temporary files"); + } else { + XCTFail("Unsure what happened to the keychain directory URL: %@", keychainDir); + } + SecAccessGroupsSetCurrent((__bridge CFArrayRef)self.originalAccessGroups); [super tearDown]; } + (void)tearDown { - SetCustomHomeURLString(NULL); + SecSetCustomHomeURLString(NULL); SecKeychainDbReset(NULL); } diff --git a/tests/stashtester/main.m b/tests/stashtester/main.m new file mode 100644 index 00000000..b75eb832 --- /dev/null +++ b/tests/stashtester/main.m @@ -0,0 +1,193 @@ +#import +#import +#include + +static void print(NSString* str) { + if (![str hasSuffix:@"\n"]) { + str = [str stringByAppendingString:@"\n"]; + } + [str writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:nil]; +} + +static void usage() { + print(@"Usage: stashtester [commands]"); + print(@""); + print(@"Commands:"); + print(@" -c Combine stash and load requests (equivalent to -s and -l)"); + print(@" -l Send stash login request to securityd (SecKeychainLogin)"); + print(@" -s Send stash request to securityd (SecKeychainStash)"); + print(@" -t Test the complete operation"); +} + +static bool performStash() { + NSLog(@"attempting stash"); + OSStatus result = SecKeychainStash(); + NSLog(@"result from stash: %ld", (long)result); + return result == errSecSuccess; +} + +static bool performLoad() { + NSLog(@"attempting load"); + OSStatus result = SecKeychainLogin(0, NULL, 0, NULL); + NSLog(@"result from load: %ld", (long)result); + return result == errSecSuccess; +} + +static NSMutableDictionary* makeQuery(bool includeData) { + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"stashtester", + (id)kSecUseDataProtectionKeychain : @NO, + } mutableCopy]; + if (includeData) { + query[(id)kSecValueData] = [@"sekrit" dataUsingEncoding:NSUTF8StringEncoding]; + } + return query; +} + +static bool performTest() { + NSLog(@"Begin test"); + NSLog(@"Adding item to keychain"); + NSMutableDictionary* addQ = makeQuery(true); + OSStatus result = SecItemAdd((__bridge CFDictionaryRef)addQ, NULL); + if (result != errSecSuccess) { + NSLog(@"Failed to add item pre-stash: %d; aborting test", (int)result); + return false; + } + + if (!performStash()) { + NSLog(@"Stash failed; aborting test"); + return false; + } + + NSLog(@"Locking legacy keychain"); + SecKeychainRef loginkc = NULL; + SecKeychainCopyLogin(&loginkc); + result = SecKeychainCopyLogin(&loginkc); + if (result != errSecSuccess) { + NSLog(@"Unable to obtain reference to login keychain; aborting test"); + return false; + } + result = SecKeychainLock(loginkc); + if (result != errSecSuccess) { + NSLog(@"Unable to lock login keychain; aborting test"); + return false; + } + + SecKeychainStatus status = 0; + result = SecKeychainGetStatus(loginkc, &status); + CFRelease(loginkc); + if (result != errSecSuccess) { + NSLog(@"Unable to get login keychain status; aborting test"); + return false; + } + + if (status & kSecUnlockStateStatus) { + NSLog(@"Login keychain not locked after locking; aborting test"); + return false; + } + + NSLog(@"Locking keybag"); + int rc = MKBLockDevice((__bridge CFDictionaryRef)@{(id)kKeyBagLockDeviceNow : @YES}); + if (rc != kIOReturnSuccess) { + NSLog(@"Failed to lock keybag (%d); aborting test", rc); + return false; + } + + // MKB asynchronously locks bag, make sure we don't race it + NSLog(@"Twiddling thumbs for 11 seconds"); + sleep(11); + + NSLog(@"Verifying keybag is locked"); + NSMutableDictionary* checkQ = makeQuery(false); + checkQ[(id)kSecUseDataProtectionKeychain] = @YES; + result = SecItemAdd((__bridge CFDictionaryRef)checkQ, NULL); + if (result != errSecInteractionNotAllowed) { + NSLog(@"Data protection keychain unexpectedly not locked; aborting test"); + return false; + } + + if (!performLoad()) { + NSLog(@"Failed to load stash (%d); aborting test", result); + return false; + } + + NSMutableDictionary* findQ = makeQuery(false); + findQ[(id)kSecReturnData] = @YES; + CFTypeRef object = NULL; + result = SecItemCopyMatching((__bridge CFDictionaryRef)findQ, &object); + NSData* password; + if (object) { + password = CFBridgingRelease(object); + } + if (result != errSecSuccess || !password || ![[@"sekrit" dataUsingEncoding:NSUTF8StringEncoding] isEqual:password]) { + NSLog(@"Unable to find item post-stashload (%d, %@); aborting test", result, password); + return false; + } + + NSLog(@"Test succeeded"); + return true; +} + +static bool cleanup() { + NSLog(@"Cleaning up"); + NSMutableDictionary* query = makeQuery(false); + OSStatus result = SecItemDelete((__bridge CFDictionaryRef)query); + if (result != errSecSuccess) { + NSLog(@"Cleanup: failed to delete item"); + return false; + } + return true; +} + +int main(int argc, const char * argv[]) { + @autoreleasepool { + bool stash = false; + bool load = false; + bool test = false; + int arg = 0; + char * const *gargv = (char * const *)argv; + while ((arg = getopt(argc, gargv, "clst")) != -1) { + switch (arg) { + case 'c': + stash = true; + load = true; + break; + case 'l': + load = true; + break; + case 's': + stash = true; + break; + case 't': + test = true; + break; + default: + usage(); + return 1; + } + } + + if ((!stash && !load && !test) || + (test && (stash || load))) + { + usage(); + return 1; + } + + if (test) { + bool testresult = performTest(); + bool cleanresult = cleanup(); + return (testresult && cleanresult) ? 0 : -1; + } + + if (stash && !performStash()) { + return -1; + } + + if (load && !performLoad()) { + return -1; + } + } + return 0; +} diff --git a/tests/stashtester/stashtester.entitlements b/tests/stashtester/stashtester.entitlements new file mode 100644 index 00000000..cac44722 --- /dev/null +++ b/tests/stashtester/stashtester.entitlements @@ -0,0 +1,12 @@ + + + + + application-identifier + com.apple.security.private.stashtester + com.apple.private.securityd.stash + + com.apple.keystore.device + + + diff --git a/trust/headers/SecCertificate.h b/trust/headers/SecCertificate.h index fcadd01d..bd29bac2 100644 --- a/trust/headers/SecCertificate.h +++ b/trust/headers/SecCertificate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -154,7 +154,13 @@ CFDataRef SecCertificateCopyNormalizedSubjectSequence(SecCertificateRef certific */ __nullable CF_RETURNS_RETAINED SecKeyRef SecCertificateCopyKey(SecCertificateRef certificate) - API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)); + API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0), bridgeos(3.0)); + +#if TARGET_OS_OSX && TARGET_CPU_ARM64 +#define SEC_SUFFIX_LEGACYMAC(symbol) __asm("_" __STRING(symbol) "$LEGACYMAC") +#else +#define SEC_SUFFIX_LEGACYMAC(symbol) /**/ +#endif #if TARGET_OS_IPHONE /*! @@ -166,7 +172,7 @@ SecKeyRef SecCertificateCopyKey(SecCertificateRef certificate) */ __nullable SecKeyRef SecCertificateCopyPublicKey(SecCertificateRef certificate) - API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopyKey", ios(10.3, 12.0)) API_UNAVAILABLE(macos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopyKey", ios(10.3, 12.0)) API_UNAVAILABLE(macos, macCatalyst); #endif #if TARGET_OS_OSX @@ -179,7 +185,8 @@ SecKeyRef SecCertificateCopyPublicKey(SecCertificateRef certificate) @discussion NOTE: Deprecated in macOS 10.14; use SecCertificateCopyKey instead for cross-platform availability. */ OSStatus SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef * __nonnull CF_RETURNS_RETAINED key) - API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopyKey", macos(10.3, 10.14)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); + SEC_SUFFIX_LEGACYMAC(SecCertificateCopyPublicKey) + API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopyKey", macos(10.3, 10.14)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); #endif /*! @@ -191,7 +198,7 @@ OSStatus SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef * */ __nullable CFDataRef SecCertificateCopySerialNumberData(SecCertificateRef certificate, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_13, __IPHONE_11_0); + API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0), bridgeos(3.0)); #if TARGET_OS_IPHONE /*! @@ -202,7 +209,7 @@ CFDataRef SecCertificateCopySerialNumberData(SecCertificateRef certificate, CFEr */ __nullable CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate) - API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopySerialNumberData", ios(10.3, 11.0)) API_UNAVAILABLE(macos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopySerialNumberData", ios(10.3, 11.0)) API_UNAVAILABLE(macos, macCatalyst); #endif #if TARGET_OS_OSX @@ -215,7 +222,8 @@ CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate) */ __nullable CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error) - API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopySerialNumberData", macos(10.7, 10.13)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); + SEC_SUFFIX_LEGACYMAC(SecCertificateCopySerialNumber) + API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopySerialNumberData", macos(10.7, 10.13)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); #endif /* @@ -463,8 +471,8 @@ extern const CFStringRef kSecPropertyTypeData __OSX_AVAILABLE_STARTING(__MAC_10_ extern const CFStringRef kSecPropertyTypeString __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPropertyTypeURL __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPropertyTypeDate __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFStringRef kSecPropertyTypeArray API_AVAILABLE(macos(10.15)) SPI_AVAILABLE(ios(13.0), watchos(6.0), tvos(13.0), iosmac(13.0)); -extern const CFStringRef kSecPropertyTypeNumber API_AVAILABLE(macos(10.15)) SPI_AVAILABLE(ios(13.0), watchos(6.0), tvos(13.0), iosmac(13.0)); +extern const CFStringRef kSecPropertyTypeArray API_AVAILABLE(macos(10.15)) SPI_AVAILABLE(ios(13.0), watchos(6.0), tvos(13.0), macCatalyst(13.0)); +extern const CFStringRef kSecPropertyTypeNumber API_AVAILABLE(macos(10.15)) SPI_AVAILABLE(ios(13.0), watchos(6.0), tvos(13.0), macCatalyst(13.0)); /*! @function SecCertificateCopyValues diff --git a/trust/headers/SecCertificatePriv.h b/trust/headers/SecCertificatePriv.h index 086f48ac..417e8ecd 100644 --- a/trust/headers/SecCertificatePriv.h +++ b/trust/headers/SecCertificatePriv.h @@ -463,6 +463,15 @@ bool SecCertificateGetDeveloperIDDate(SecCertificateRef certificate, CFAbsoluteT CFAbsoluteTime SecAbsoluteTimeFromDateContentWithError(DERTag tag, const uint8_t *bytes, size_t length, CFErrorRef *error); +/* Return the (last) attribute value from the Subject DN with the indicated Attribute OID. + * This suits as a replacement for SecCertificateCopySubjectComponent */ +CFStringRef SecCertificateCopySubjectAttributeValue(SecCertificateRef cert, DERItem *attributeOID) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); + +/* Return the external roots (for use with SecTrustSetAnchorCertificates) */ +CFArrayRef SecCertificateCopyAppleExternalRoots(void) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); + /* * Legacy functions (OS X only) */ @@ -579,7 +588,7 @@ OSStatus SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, con */ OSStatus SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result) - __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_10_0, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA, "SecCertificateCopySubjectComponent is deprecated. Use SecCertificateCopyCommonNames,SecCertificateCopyOrganization,SecCertificateCopyOrganizationalUnit, etc. instead."); + __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_10_0, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA, "SecCertificateCopySubjectComponent is deprecated. Use SecCertificateCopySubjectAttributeValue instead."); /* Convenience functions for searching. */ diff --git a/trust/headers/SecPolicy.h b/trust/headers/SecPolicy.h index 59e95b54..a3c19456 100644 --- a/trust/headers/SecPolicy.h +++ b/trust/headers/SecPolicy.h @@ -73,9 +73,9 @@ extern const CFStringRef kSecPolicyAppleiChat __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); #endif extern const CFStringRef kSecPolicyApplePKINITClient - API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); extern const CFStringRef kSecPolicyApplePKINITServer - API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); extern const CFStringRef kSecPolicyAppleCodeSigning __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); extern const CFStringRef kSecPolicyMacAppStoreReceipt diff --git a/trust/headers/SecPolicyPriv.h b/trust/headers/SecPolicyPriv.h index 781fb65f..432e18c6 100644 --- a/trust/headers/SecPolicyPriv.h +++ b/trust/headers/SecPolicyPriv.h @@ -59,12 +59,6 @@ extern const CFStringRef kSecPolicyAppleQAProfileSigner __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); extern const CFStringRef kSecPolicyAppleServerAuthentication __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); -extern const CFStringRef kSecPolicyAppleOTAPKISigner - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_12, __MAC_10_13_4, __IPHONE_7_0, __IPHONE_11_3); -extern const CFStringRef kSecPolicyAppleTestOTAPKISigner - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_12, __MAC_10_13_4, __IPHONE_7_0, __IPHONE_11_3); -extern const CFStringRef kSecPolicyAppleIDValidationRecordSigningPolicy - API_DEPRECATED_WITH_REPLACEMENT("kSecPolicyAppleIDValidationRecordSigning", ios(7.0,10.0), macos(10.9,10.12)); extern const CFStringRef kSecPolicyAppleIDValidationRecordSigning __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); extern const CFStringRef kSecPolicyAppleSMPEncryption @@ -187,6 +181,27 @@ extern const CFStringRef kSecPolicyAppleKeyTransparency API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)); extern const CFStringRef kSecPolicyAppleLegacySSL API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)); +extern const CFStringRef kSecPolicyAppleAlisha + API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); +extern const CFStringRef kSecPolicyAppleMeasuredBootPolicySigning + API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); +extern const CFStringRef kSecPolicyApplePayQRCodeEncryption + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); +extern const CFStringRef kSecPolicyApplePayQRCodeSigning + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); +extern const CFStringRef kSecPolicyAppleAccessoryUpdateSigning + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); +extern const CFStringRef kSecPolicyAppleEscrowServiceIdKeySigning + API_AVAILABLE(macos(10.15.6), ios(13.5.5)); +extern const CFStringRef kSecPolicyApplePCSEscrowServiceIdKeySigning + API_AVAILABLE(macos(10.15.6), ios(13.5.5)); +extern const CFStringRef kSecPolicyAppleAggregateMetricTransparency + API_AVAILABLE(macos(10.15.6), ios(13.6), watchos(6.2), tvos(13.4)); +extern const CFStringRef kSecPolicyAppleAggregateMetricEncryption + API_AVAILABLE(macos(11.1), ios(14.3), watchos(7.2), tvos(14.3)); +extern const CFStringRef kSecPolicyApplePayModelSigning + API_AVAILABLE(macos(11.3), ios(14.5), watchos(7.4), tvos(14.5)); + /*! @enum Policy Name Constants (Private) @@ -209,6 +224,8 @@ extern const CFStringRef kSecPolicyAppleLegacySSL @constant kSecPolicyNameAppleAMPService @constant kSecPolicyNameAppleSiriService @constant kSecPolicyNameAppleHomeAppClipUploadService + @constant kSecPolicyNameAppleUpdatesService + @constant kSecPolicyNameApplePushCertPortal */ extern const CFStringRef kSecPolicyNameAppleAST2Service __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0) __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0); @@ -244,6 +261,10 @@ extern const CFStringRef kSecPolicyNameAppleSiriService API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)); extern const CFStringRef kSecPolicyNameAppleHomeAppClipUploadService API_AVAILABLE(macos(10.15.1), ios(13.2), watchos(6.1), tvos(13.1)); +extern const CFStringRef kSecPolicyNameAppleUpdatesService + API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); +extern const CFStringRef kSecPolicyNameApplePushCertPortal + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); /*! @enum Policy Value Constants @@ -323,10 +344,7 @@ CF_ENUM(CFOptionFlags) { in the leaf certificate. @discussion The resulting policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if the value true is set for the key - "ApplePinningAllowTestCerts%@" (where %@ is the policyName parameter) in the - com.apple.security preferences for the user of the calling application. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID matching the intermediateMarkerOID parameter. @@ -353,16 +371,12 @@ SecPolicyRef SecPolicyCreateApplePinned(CFStringRef policyName, in the leaf certificate. @discussion The resulting policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if the value true is set for the key - "ApplePinningAllowTestCerts%@" (where %@ is the policyName parameter) in the - com.apple.security preferences for the user of the calling application. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID matching the intermediateMarkerOID parameter, or 1.2.840.113635.100.6.2.12 if NULL is passed. * The leaf has a marker extension with OID matching the leafMarkerOID parameter. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. @@ -380,8 +394,7 @@ SecPolicyRef SecPolicyCreateAppleSSLPinned(CFStringRef policyName, CFStringRef h certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "iPhone Activation". @@ -397,8 +410,7 @@ SecPolicyRef SecPolicyCreateiPhoneActivation(void); chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs * There are exactly 4 certs in chain. * The first intermediate has Common Name "Apple iPhone Device CA". @result A policy object. The caller is responsible for calling CFRelease @@ -490,8 +502,7 @@ SecPolicyRef SecPolicyCreateIPSec(Boolean server, CFStringRef __nullable hostna @abstract Returns a policy object for evaluating SW update signing certs. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate ExtendedKeyUsage Extension contains 1.2.840.113635.100.4.1. * The leaf ExtendedKeyUsage extension contains 1.2.840.113635.100.4.1. @@ -506,8 +517,7 @@ SecPolicyRef SecPolicyCreateAppleSWUpdateSigning(void); @abstract Returns a policy object for evaluating installer package signing certs. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The leaf KeyUsage extension has the digital signature bit set. * The leaf ExtendedKeyUsage extension has the CodeSigning OID. @@ -523,8 +533,7 @@ SecPolicyRef SecPolicyCreateApplePackageSigning(void); signatures. This is for apps signed directly by the app store. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "Apple iPhone OS Application Signing". @@ -544,8 +553,7 @@ SecPolicyRef SecPolicyCreateiPhoneApplicationSigning(void); signatures. This is for VPN plugins signed directly by the VPN team. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "Apple iPhone OS Application Signing". @@ -566,8 +574,7 @@ SecPolicyRef SecPolicyCreateiPhoneVPNApplicationSigning(void) profile. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID matching 1.2.840.113635.100.6.2.1 (WWDR CA). * The leaf has a marker extension with OID matching one of the following: @@ -590,8 +597,7 @@ SecPolicyRef SecPolicyCreateiPhoneProfileApplicationSigning(void); profile. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The leaf has a marker extension with OID matching one of the following: * 1.2.840.113635.100.6.1.7 ("3rd Party Mac Developer Application" leaf) @@ -612,8 +618,7 @@ SecPolicyRef SecPolicyCreateMacOSProfileApplicationSigning(void) @abstract Returns a policy object for evaluating provisioning profile signatures. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "Apple iPhone OS Provisioning Profile Signing". @@ -633,7 +638,7 @@ SecPolicyRef SecPolicyCreateiPhoneProvisioningProfileSigning(void); and allows for both the prod and the dev/test certs. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. Test roots are never permitted. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.1. @@ -681,8 +686,7 @@ enum { @discussion This policy uses the Basic X.509 policy with validity check and requires the leaf to have * a KeyUsage matching the smimeUsage, - * an ExtendedKeyUsage, if any, with the AnyExtendedKeyUsage OID or the - EmailProtection OID, and + * an ExtendedKeyUsage, if any, with the EmailProtection OID, and * if the email param is specified, the email address in the RFC822Name in the SubjectAlternativeName extension or in the Email Address field of the Subject Name. @@ -733,8 +737,7 @@ SecPolicyRef SecPolicyCreateURLBag(void); @abstract Returns a policy object for evaluating certificate chains for signing OTA Tasking. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "OTA Task Signing". @@ -749,8 +752,7 @@ SecPolicyRef SecPolicyCreateOTATasking(void); @abstract Returns a policy object for evaluating certificate chains for signing Mobile Assets. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "Asset Manifest Signing". @@ -766,8 +768,7 @@ SecPolicyRef SecPolicyCreateMobileAsset(void); Mobile Assets. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.18. * The leaf has a marker extension with OID 1.2.840.113635.100.6.55.1. @@ -783,8 +784,7 @@ SecPolicyRef SecPolicyCreateMobileAssetDevelopment(void) @abstract Returns a policy object for evaluating certificate chains for Apple ID Authority. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate(s) has(have) a marker extension with OID 1.2.840.113635.100.6.2.3 or OID 1.2.840.113635.100.6.2.7. * The leaf has a marker extension with OID 1.2.840.113635.100.4.7. @@ -801,8 +801,7 @@ SecPolicyRef SecPolicyCreateAppleIDAuthorityPolicy(void); Mac App Store Receipts. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.1. * The leaf has CertificatePolicy extension with OID 1.2.840.113635.100.5.6.1. @@ -822,8 +821,7 @@ SecPolicyRef SecPolicyCreateMacAppStoreReceipt(void); team ID to match the organizationalUnit field in the leaf certificate's subject. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The leaf has a marker extension with OID 1.2.840.113635.100.6.1.16 and containing the cardIssuer. * The leaf has ExtendedKeyUsage with OID 1.2.840.113635.100.4.14. @@ -840,8 +838,7 @@ SecPolicyRef SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, @abstract Returns a policy object for evaluating Mobile Store certificate chains. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple System Integration 2 Certification Authority". * The leaf has KeyUsage with the DigitalSignature bit set. @@ -857,8 +854,7 @@ SecPolicyRef SecPolicyCreateMobileStoreSigner(void); @abstract Returns a policy object for evaluating Test Mobile Store certificate chains. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple System Integration 2 Certification Authority". * The leaf has KeyUsage with the DigitalSignature bit set. @@ -874,7 +870,6 @@ SecPolicyRef SecPolicyCreateTestMobileStoreSigner(void); @abstract Returns a policy object for evaluating Escrow Service certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to the current Escrow Roots in the OTAPKI asset. * There are exactly 2 certs in the chain. * The leaf has KeyUsage with the KeyEncipherment bit set. @result A policy object. The caller is responsible for calling CFRelease @@ -888,7 +883,6 @@ SecPolicyRef SecPolicyCreateEscrowServiceSigner(void); @abstract Returns a policy object for evaluating PCS Escrow Service certificate chains. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to the current PCS Escrow Roots in the OTAPKI asset. * There are exactly 2 certs in the chain. * The leaf has KeyUsage with the KeyEncipherment bit set. @result A policy object. The caller is responsible for calling CFRelease @@ -903,8 +897,7 @@ SecPolicyRef SecPolicyCreatePCSEscrowServiceSigner(void); Provisioning Profiles. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.1. * The leaf has KeyUsage with the DigitalSignature bit set. * The leaf has a marker extension with OID 1.2.840.113635.100.4.11. @@ -921,11 +914,11 @@ SecPolicyRef SecPolicyCreateOSXProvisioningProfileSigning(void); Configuration Profiles. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.3. - * The leaf has ExtendedKeyUsage with OID 1.2.840.113635.100.4.16. + * The leaf has ExtendedKeyUsage with OID 1.2.840.113635.100.4.16, or on non-GM + builds only, OID 1.2.840.113635.100.4.17. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. */ @@ -935,12 +928,11 @@ SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void); /*! @function SecPolicyCreateQAConfigurationProfileSigner @abstract Returns a policy object for evaluating certificate chains for signing - QA Configuration Profiles. On customer builds, this function returns the same + QA Configuration Profiles. On GM builds, this function returns the same policy as SecPolicyCreateConfigurationProfileSigner. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.3. * The leaf has ExtendedKeyUsage with OID 1.2.840.113635.100.4.17. @result A policy object. The caller is responsible for calling CFRelease @@ -949,42 +941,13 @@ SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void); __nullable CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void); -/*! - @function SecPolicyCreateOTAPKISigner - @abstract Returns a policy object for evaluating OTA PKI certificate chains. - @discussion This policy uses the Basic X.509 policy with validity check - and pinning options: - * The chain is anchored to Apple PKI Settings CA. - * There are exactly 2 certs in the chain. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -__nullable CF_RETURNS_RETAINED -SecPolicyRef SecPolicyCreateOTAPKISigner(void) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_12, __MAC_10_13_4, __IPHONE_7_0, __IPHONE_11_3); - -/*! - @function SecPolicyCreateTestOTAPKISigner - @abstract Returns a policy object for evaluating OTA PKI certificate chains. - @discussion This policy uses the Basic X.509 policy with validity check - and pinning options: - * The chain is anchored to Apple Test PKI Settings CA. - * There are exactly 2 certs in the chain. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -__nullable CF_RETURNS_RETAINED -SecPolicyRef SecPolicyCreateTestOTAPKISigner(void) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_12, __MAC_10_13_4, __IPHONE_7_0, __IPHONE_11_3); - /*! @function SecPolicyCreateAppleIDValidationRecordSigningPolicy @abstract Returns a policy object for evaluating certificate chains for signing Apple ID Validation Records. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate(s) has(have) a marker extension with OID 1.2.840.113635.100.6.2.3 or OID 1.2.840.113635.100.6.2.10. * The leaf has a marker extension with OID 1.2.840.113635.100.6.25. @@ -1000,8 +963,7 @@ SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void); @abstract Returns a policy object for evaluating SMP certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.13. * The leaf has KeyUsage with the KeyEncipherment bit set. @@ -1034,8 +996,7 @@ SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void); @abstract Returns a policy object for verifying production PPQ Signing certificates. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple System Integration 2 Certification Authority". @@ -1054,8 +1015,7 @@ SecPolicyRef SecPolicyCreateApplePPQSigning(void); customer builds, this function returns the same policy as SecPolicyCreateApplePPQSigning. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple System Integration 2 Certification Authority". @@ -1071,7 +1031,16 @@ SecPolicyRef SecPolicyCreateTestApplePPQSigning(void); /*! @function SecPolicyCreateAppleIDSService @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) - @discussion This policy uses the SSL server policy. + @discussion This policy uses the Basic X.509 policy with validity check + and pinning options: + * The chain is anchored to any of the Apple Root CAs. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. + * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.4.2 or, + if Test Roots are allowed, OID 1.2.840.113635.100.6.27.4.1. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName + extension. + * The leaf has ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. */ @@ -1086,15 +1055,11 @@ SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef __nullable hostname); Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases either using the context dictionary or with - defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.4.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.4.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1111,15 +1076,11 @@ SecPolicyRef SecPolicyCreateAppleIDSServiceContext(CFStringRef hostname, CFDicti Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases either using the context dictionary or with - defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.5.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.5.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1135,9 +1096,7 @@ SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname, CFDictionaryR @discussion This policy uses the Basic X.509 policy with validity check and pinning options: * The chain is anchored to an Entrust Intermediate. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1154,12 +1113,11 @@ SecPolicyRef SecPolicyCreateApplePushServiceLegacy(CFStringRef hostname); Boolean true will allow Test Apple roots and test OIDs on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.11.2 or, if enabled, OID 1.2.840.113635.100.6.27.11.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1180,9 +1138,7 @@ SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname, CFDictionaryR * The chain length is 3. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.11.2 or OID 1.2.840.113635.100.6.27.11.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. @@ -1199,14 +1155,10 @@ SecPolicyRef SecPolicyCreateAppleCompatibilityMMCSService(CFStringRef hostname) Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases either using the context dictionary or with - defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.2. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1224,15 +1176,11 @@ SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases either using the context dictionary or with - defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.3.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.3.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1250,14 +1198,11 @@ SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRe Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted either using the context dictionary or with defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.8.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.8.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1275,15 +1220,11 @@ SecPolicyRef SecPolicyCreateAppleAST2Service(CFStringRef hostname, CFDictionaryR Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs via full certificate - comparison. Test Apple Root CAs are permitted only on internal releases either - using the context dictionary or with defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.7.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.7.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1306,9 +1247,7 @@ SecPolicyRef SecPolicyCreateAppleEscrowProxyService(CFStringRef hostname, CFDict * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.7.2 or, if UAT is enabled with a defaults write (internal devices only), OID 1.2.840.113635.100.6.27.7.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. @@ -1325,15 +1264,11 @@ __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs via full certificate - comparison. Test Apple Root CAs are permitted only on internal releases either - using the context dictionary or with defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.6.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.6.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1349,13 +1284,10 @@ SecPolicyRef SecPolicyCreateAppleFMiPService(CFStringRef hostname, CFDictionaryR @param hostname Optional; hostname to verify the certificate name against. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.1 - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage, if any, with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1380,8 +1312,7 @@ SecPolicyRef SecPolicyCreateAppleTimeStamping(void); @abstract Returns a policy object for evaluating Apple Pay Issuer Encryption certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple Worldwide Developer Relations CA - G2". * The leaf has KeyUsage with the KeyEncipherment bit set. @@ -1398,8 +1329,7 @@ SecPolicyRef SecPolicyCreateApplePayIssuerEncryption(void) @abstract Returns a policy object for evaluating Apple TV VPN Profile certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.10. * The leaf has a marker extension with OID 1.2.840.113635.100.6.43. @@ -1417,13 +1347,10 @@ SecPolicyRef SecPolicyCreateAppleATVVPNProfileSigning(void) @param hostname Required; hostname to verify the certificate name against. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs via full certificate - comparison. Test Apple Root CAs are permitted only on internal releases with defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.16 * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.9. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1439,8 +1366,7 @@ SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) certificates. @discussion The resulting policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID matching 1.2.840.113635.100.6.2.1 (WWDR CA) or 1.2.840.113635.100.6.2.6 (Developer ID CA). @@ -1472,8 +1398,7 @@ SecPolicyRef SecPolicyCreateAppleExternalDeveloper(void) @abstract Returns a policy object for verifying the Apple Software Signing certificate. @discussion The resulting policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has the Common Name "Apple Code Signing Certification Authority". * The leaf has a marker extension with OID matching 1.2.840.113635.100.6.22. @@ -1532,8 +1457,7 @@ SecPolicyRef SecPolicyCreateAppleUniqueDeviceCertificate(CFDataRef __nullable te @abstract Returns a policy object for verifying signed Warsaw assets. @discussion The resulting policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has an extension with OID matching 1.2.840.113635.100.6.2.14. * The leaf has a marker extension with OID matching 1.2.840.113635.100.6.29. @@ -1550,8 +1474,7 @@ SecPolicyRef SecPolicyCreateAppleWarsaw(void) @abstract Returns a policy object for verifying signed static assets for Secure IO. @discussion The resulting policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has an extension with OID matching 1.2.840.113635.100.6.2.10. * The leaf has a marker extension with OID matching 1.2.840.113635.100.6.50. @@ -1571,12 +1494,11 @@ SecPolicyRef SecPolicyCreateAppleSecureIOStaticAsset(void) Boolean true will allow Test Apple roots and test OIDs on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.15.2 or, if enabled, OID 1.2.840.113635.100.6.27.15.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1598,9 +1520,7 @@ SecPolicyRef SecPolicyCreateAppleiCloudSetupService(CFStringRef hostname, CFDict * The chain length is 3. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.15.2 or OID 1.2.840.113635.100.6.27.15.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. @@ -1627,8 +1547,7 @@ SecPolicyRef SecPolicyCreateAppleAppTransportSecurity(void) @abstract Returns a policy object for evaluating certificate chains for signing Mobile Software Updates. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.18. * The leaf has a marker extension with OID 1.2.840.113635.100.6.57.2, or on internal releases, @@ -1708,8 +1627,7 @@ SecPolicyRef SecPolicyCreateDemoDigitalCatalogSigning(void) @abstract Returns a policy object for evaluating certificate chains for signing Asset Receipts @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.10. * The leaf has a marker extension with OID 1.2.840.113635.100.6.61. @@ -1726,7 +1644,7 @@ SecPolicyRef SecPolicyCreateAppleAssetReceipt(void) @abstract Returns a policy object for evaluating certificate chains for signing Developer ID+ Tickets @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.17. * The leaf has a marker extension with OID 1.2.840.113635.100.6.1.30. @@ -1788,9 +1706,9 @@ SecPolicyRef SecPolicyCreateAppleComponentCertificate(CFDataRef __nullable testR @param applicationId A string that identifies the applicationId. @discussion The resulting policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. - * The intermediate has a marker extension with OID TBD. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.3". * The leaf has a marker extension with OID 1.2.840.113635.100.6.69.1 and value matching the applicationId. * Revocation is checked via any available method. @@ -1821,6 +1739,194 @@ __nullable CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateLegacySSL(Boolean server, CFStringRef __nullable hostname) SPI_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)); +/*! + @function SecPolicyCreateAlisha + @abstract Returns a policy object for verifying Alisha certificates. + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * EC key sizes are P-256 or larger. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAlisha(void) + API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); +extern const CFStringRef kSecPolicyAppleEscrowServiceIdKeySigning + API_AVAILABLE(macos(10.15.6), ios(13.5.5)); +extern const CFStringRef kSecPolicyApplePCSEscrowServiceIdKeySigning + API_AVAILABLE(macos(10.15.6), ios(13.5.5)); + +/*! + @function SecPolicyCreateMeasuredBootPolicySigning + @abstract Returns a policy object for verifying Measured Boot Policy Signing certificates. + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.24.17. + * The leaf has a marker extension with OID 1.2.840.113635.100.6.26.6.1 + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + Because this policy does not pin the anchors, the caller must use SecTrustSetAnchorCertificates with + the expected roots. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateMeasuredBootPolicySigning(void) + API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); + +/*! + @function SecPolicyCreateApplePayQRCodeEncryption + @abstract Returns a policy object for verifying ApplePay QRCode Encryption certificates + @discussion The resulting policy uses the Basic X.509 policy with validity check and + pinning options: + * The root matches the "Apple External EC Root", or on internal builds, "Test Apple External EC Root" + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.22. + * The leaf has a marker extension with OID 1.2.840.113635.100.13.3 + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + * Revocation is checked via any available method + Because the "Apple External" roots are not trusted by default, the caller must use + SecTrustSetAnchorCertificates with the expected roots. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateApplePayQRCodeEncryption(void) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); + +/*! + @function SecPolicyCreateApplePayQRCodeSigning + @abstract Returns a policy object for verifying ApplePay QRCode Signing certificates + @discussion The resulting policy uses the Basic X.509 policy with validity check and + pinning options: + * The root matches the "Apple External EC Root", or on internal builds, "Test Apple External EC Root" + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.22. + * The leaf has a marker extension with OID 1.2.840.113635.100.12.12 + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + * Revocation is checked via any available method + Because the "Apple External" roots are not trusted by default, the caller must use + SecTrustSetAnchorCertificates with the expected roots. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateApplePayQRCodeSigning(void) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); + +/*! + @function SecPolicyCreateAppleAccessoryUpdateSigning + @abstract Returns a policy object for verifying Accessory Firmware Update Signing certificates + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * The chain is anchored to any of the Apple Root CAs. + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.17. + * The leaf has a marker extension with OID 1.2.840.113635.100.12.9, or, if + "AllowAccessoryUpdateSigningBeta" is set to true in the com.apple.security + preference/defaults domain, OID 1.2.840.113635.100.12.10 + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + * Revocation is checked via any available method + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleAccessoryUpdateSigning(void) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); + +/*! + @function SecPolicyCreateAggregateMetricTransparency + @abstract Returns a policy object for verifying Aggregate Metric Transparency certificates + @param facilitator A boolean to indicate whether the facilitator or partner transparency + certificate is being checked. + @discussion The resulting policy uses the Basic X.509 policy with validity check and + pinning options: + * The chain is anchored to any of the Apple Root CAs. + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.26. + * The leaf has a marker extension with OID 1.2.840.113635.100.12.17 if facilitator is true or + 1.2.840.113635.100.12.18 if facilitator is false. The contents of this marker extension + are not checked. + * Revocation is checked via any available method. + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + * Require a positive CT verification result. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAggregateMetricTransparency(bool facilitator) + API_AVAILABLE(macos(10.15.6), ios(13.6), watchos(6.2), tvos(13.4)); + +/*! + @function SecPolicyCreateAggregateMetricEncryption + @abstract Returns a policy object for verifying Aggregate Metric Encryption certificates + @param facilitator A boolean to indicate whether the facilitator or partner encryption + certificate is being checked. + @discussion The resulting policy uses the Basic X.509 policy with validity check and + pinning options: + * The chain is anchored to any of the Apple Root CAs. + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.26. + * The leaf has a marker extension with OID 1.2.840.113635.100.15.2 if facilitator is true or + 1.2.840.113635.100.15.3 if facilitator is false. + * Revocation is checked via any available method. + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + * Require a positive CT verification result using the non-TLS CT log list + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAggregateMetricEncryption(bool facilitator) + API_AVAILABLE(macos(11.1), ios(14.3), watchos(7.2), tvos(14.3)); + +/*! + @function SecPolicyCreateSSLWithKeyUsage + @abstract Returns a policy object for evaluating SSL certificate chains (with key usage enforcement) + @param server Passing true for this parameter creates a policy for SSL + server certificates. + @param hostname (Optional) If present, the policy will require the specified + hostname to match the hostname in the leaf certificate. + @param keyUsage SecKeyUsage flags (see SecCertificatePriv.h) that the server certificate must have specified. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateSSLWithKeyUsage(Boolean server, CFStringRef __nullable hostname, uint32_t keyUsage) + API_AVAILABLE(macos(11.3), ios(14.5), watchos(7.4), tvos(14.5)); + +/*! + @function SecPolicySetSHA256Pins + @abstract Sets the SubjectPublicKeyInfo (SPKI) pins. + @param policy The policy to modify. + @param leafSPKISHA256 An array of SHA256 hashes of permitted leaf SPKIs. Passing NULL will remove any previous pins. + @param caSPKISHA256 An array of SHA256 hashes of CA SPKIs. Passing NULL will remove any previous pins. + @discussion Pins replace any existing pins set on the policy. + Setting leaf pins will require that the SPKI in the leaf certificate validated must match at least one of the array of leafSPKISHA256 pins. + Setting CA pins will require that at an SPKI in at least one CA certificate in the built chain from the leaf certificate to a trusted anchor certificate + matches at least one of the array of caSPKISHA256 pins. + */ +void SecPolicySetSHA256Pins(SecPolicyRef policy, CFArrayRef _Nullable leafSPKISHA256, CFArrayRef _Nullable caSPKISHA256) + API_AVAILABLE(macos(11.3), ios(14.5), watchos(7.4), tvos(14.5)); + +/*! + @function SecPolicyCreateApplayPayModelSigning + @abstract Returns a policy object for verifying Aggregate Metric Encryption certificates + @param checkExpiration A boolean to indicate whether the policy should check for expiration. + @discussion The resulting policy uses the Basic X.509 policy with optional validity check and + pinning options: + * The chain is anchored to any of the Apple Root CAs. + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.17. + * The leaf has a marker extension with OID 1.2.840.113635.100.12.20 + * Revocation is checked via any available method. + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateApplePayModelSigning(bool checkExpiration) + API_AVAILABLE(macos(11.3), ios(14.5), watchos(7.4), tvos(14.5)); + /* * Legacy functions (OS X only) */ @@ -1839,21 +1945,6 @@ SecPolicyRef SecPolicyCreateLegacySSL(Boolean server, CFStringRef __nullable hos OSStatus SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef * __nonnull CF_RETURNS_RETAINED policy) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); -/*! - @function SecPolicyCopyAll - @abstract Returns an array of all known policies based on certificate type. - @param certificateType A certificate type. This is a optional parameter. Pass CSSM_CERT_UNKNOWN if the certificate type is unknown. - @param policies The returned array of policies. This is a required parameter. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later; - to obtain a policy reference, use one of the SecPolicyCreate* functions in SecPolicy.h. (Note: there is normally - no reason to iterate over multiple disjointed policies, except to provide a way to edit trust settings for each - policy, as is done in certain certificate UI views. In that specific case, your code should call SecPolicyCreateWithOID - for each desired policy from the list of supported OID constants in SecPolicy.h.) - */ -OSStatus SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef * __nonnull CF_RETURNS_RETAINED policies) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - /* Given a unified SecPolicyRef, return a copy with a legacy C++ ItemImpl-based Policy instance. Only for internal use; legacy references cannot be used by SecPolicy API functions. */ @@ -1889,7 +1980,6 @@ CFArrayRef SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef polic policy. Use outside of the Security project at your own peril. */ extern const CFStringRef kSecPolicyCheckAnchorApple; -extern const CFStringRef kSecPolicyCheckAnchorSHA1; extern const CFStringRef kSecPolicyCheckAnchorSHA256; extern const CFStringRef kSecPolicyCheckAnchorTrusted; extern const CFStringRef kSecPolicyCheckBasicCertificateProcessing; @@ -1908,6 +1998,7 @@ extern const CFStringRef kSecPolicyCheckExtendedKeyUsage; extern const CFStringRef kSecPolicyCheckExtendedValidation; extern const CFStringRef kSecPolicyCheckGrayListedKey; extern const CFStringRef kSecPolicyCheckGrayListedLeaf; +extern const CFStringRef kSecPolicyCheckLeafSPKISHA256; extern const CFStringRef kSecPolicyCheckIdLinkage; extern const CFStringRef kSecPolicyCheckIntermediateCountry; extern const CFStringRef kSecPolicyCheckIntermediateEKU; @@ -1915,11 +2006,13 @@ extern const CFStringRef kSecPolicyCheckIntermediateMarkerOid; extern const CFStringRef kSecPolicyCheckIntermediateMarkerOidWithoutValueCheck; extern const CFStringRef kSecPolicyCheckIntermediateOrganization; extern const CFStringRef kSecPolicyCheckIntermediateSPKISHA256; +extern const CFStringRef kSecPolicyCheckCAspkiSHA256; extern const CFStringRef kSecPolicyCheckIssuerCommonName; extern const CFStringRef kSecPolicyCheckIssuerPolicyConstraints; extern const CFStringRef kSecPolicyCheckIssuerNameConstraints; extern const CFStringRef kSecPolicyCheckKeySize; extern const CFStringRef kSecPolicyCheckKeyUsage; +extern const CFStringRef kSecPolicyCheckKeyUsageReportOnly; extern const CFStringRef kSecPolicyCheckLeafMarkerOid; extern const CFStringRef kSecPolicyCheckLeafMarkerOidWithoutValueCheck; extern const CFStringRef kSecPolicyCheckLeafMarkersProdAndQA; @@ -1927,6 +2020,8 @@ extern const CFStringRef kSecPolicyCheckMissingIntermediate; extern const CFStringRef kSecPolicyCheckNameConstraints; extern const CFStringRef kSecPolicyCheckNoNetworkAccess; extern const CFStringRef kSecPolicyCheckNonEmptySubject; +extern const CFStringRef kSecPolicyCheckNonTlsCTRequired; +extern const CFStringRef kSecPolicyCheckNotCA; extern const CFStringRef kSecPolicyCheckNotValidBefore; extern const CFStringRef kSecPolicyCheckPinningRequired; extern const CFStringRef kSecPolicyCheckPolicyConstraints; @@ -1978,6 +2073,38 @@ extern const CFStringRef kSecPolicyNameCodeSigning; extern const CFStringRef kSecPolicyNameTimeStamping; extern const CFStringRef kSecPolicyNameOCSPSigner; +/*! + @function SecPolicyCreateEscrowServiceIdKeySigning + @abstract Returns a policy object for verifying Escrow Service ID keys. + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * The chain is anchored to the current Escrow Roots in the OTAPKI asset. + * There are exactly 2 certs in the chain. + * The leaf has KeyUsage with the DigitalSignature bit set. + * CN matching the name generated by escrow service. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateEscrowServiceIdKeySigning(void) + API_AVAILABLE(macos(10.15.6), ios(13.6)); + +/*! + @function SecPolicyCreatePCSEscrowServiceIdKeySigning + @abstract Returns a policy object for verifying PCS Escrow Service ID keys. + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * The chain is anchored to the current Escrow Roots in the OTAPKI asset. + * There are exactly 2 certs in the chain. + * The leaf has KeyUsage with the DigitalSignature bit set. + * CN matching the name generated by escrow service. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreatePCSEscrowServiceIdKeySigning(void) + API_AVAILABLE(macos(10.15.6), ios(13.6)); + /* * MARK: SecPolicyCheckCert functions */ @@ -2005,6 +2132,7 @@ bool SecPolicyCheckCertCertificatePolicy(SecCertificateRef cert, CFTypeRef pvcVa bool SecPolicyCheckCertCriticalExtensions(SecCertificateRef cert, CFTypeRef __nullable pvcValue); bool SecPolicyCheckCertSubjectCountry(SecCertificateRef cert, CFTypeRef pvcValue); bool SecPolicyCheckCertUnparseableExtension(SecCertificateRef cert, CFTypeRef pvcValue); +bool SecPolicyCheckCertNotCA(SecCertificateRef cert, CFTypeRef pvcValue); void SecPolicySetName(SecPolicyRef policy, CFStringRef policyName); __nullable CFArrayRef SecPolicyXPCArrayCopyArray(xpc_object_t xpc_policies, CFErrorRef *error); @@ -2013,6 +2141,10 @@ void SecPolicySetOptionsValue(SecPolicyRef policy, CFStringRef key, CFTypeRef va bool SecDNSIsTLD(CFStringRef reference); +CFDataRef CreateCFDataFromBase64CFString(CFStringRef base64string); +CFArrayRef parseNSPinnedDomains(CFDictionaryRef nsPinnedDomainsDict, CFStringRef hostName, CFStringRef nsPinnedIdentityType); +void SecPolicyReconcilePinningRequiredIfInfoSpecified(CFMutableDictionaryRef options); + CF_IMPLICIT_BRIDGING_DISABLED CF_ASSUME_NONNULL_END diff --git a/trust/headers/SecTrust.h b/trust/headers/SecTrust.h index a48083cd..a8c7f975 100644 --- a/trust/headers/SecTrust.h +++ b/trust/headers/SecTrust.h @@ -463,7 +463,22 @@ OSStatus SecTrustGetTrustResult(SecTrustRef trust, */ __nullable SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + API_DEPRECATED_WITH_REPLACEMENT("SecTrustCopyKey", macos(10.7, 10.16), ios(2.0, 14.0), watchos(1.0, 7.0), tvos(9.0, 14.0)); + +/*! + @function SecTrustCopyKey + @abstract Return the public key for a leaf certificate after it has + been evaluated. + @param trust A reference to the trust object which has been evaluated. + @result The certificate's public key, or NULL if it the public key could + not be extracted (this can happen if the public key algorithm is not + supported). The caller is responsible for calling CFRelease on the + returned key when it is no longer needed. + @discussion RSA and ECDSA public keys are supported. All other public key algorithms are unsupported. + */ +__nullable +SecKeyRef SecTrustCopyKey(SecTrustRef trust) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); /*! @function SecTrustGetCertificateCount diff --git a/trust/headers/SecTrustPriv.h b/trust/headers/SecTrustPriv.h index 5bf6e60b..9e575bb2 100644 --- a/trust/headers/SecTrustPriv.h +++ b/trust/headers/SecTrustPriv.h @@ -41,6 +41,8 @@ __BEGIN_DECLS CF_ASSUME_NONNULL_BEGIN CF_IMPLICIT_BRIDGING_ENABLED +#define TRUST_TIME_LEEWAY (4500.0) // 1h15m: 1 hour to address DST/time zone issues, 15 min for clock skew + /* Constants used as keys in property lists. See SecTrustCopySummaryPropertiesAtIndex for more information. */ extern const CFStringRef kSecPropertyKeyType; @@ -64,6 +66,8 @@ extern const CFStringRef kSecTrustInfoCompanyNameKey; extern const CFStringRef kSecTrustInfoRevocationKey; extern const CFStringRef kSecTrustInfoRevocationValidUntilKey; extern const CFStringRef kSecTrustInfoCertificateTransparencyKey; +extern const CFStringRef kSecTrustInfoResultNotBefore; +extern const CFStringRef kSecTrustInfoResultNotAfter; /* Constants used as keys in the certificate details dictionary. An array of per-certificate details is returned by SecTrustCopyResult @@ -296,6 +300,14 @@ uint64_t SecTrustOTASecExperimentGetUpdatedAsset(CFErrorRef _Nullable * _Nullabl */ CFDictionaryRef SecTrustOTASecExperimentCopyAsset(CFErrorRef _Nullable * _Nullable CF_RETURNS_RETAINED error); +/* + @function SecTrustTriggerValidUpdate + @abstract Trigger trustd to fetch a valid update. + @param error A returned error if trustd failed to trigger the update. + @result True if the update was triggered, false if not. + */ +bool SecTrustTriggerValidUpdate(CFErrorRef _Nullable * _Nullable CF_RETURNS_RETAINED error); + /*! @function SecTrustFlushResponseCache @abstract Removes all OCSP responses from the per-user response cache. @@ -433,7 +445,6 @@ OSStatus SecTrustSetPinningPolicyName(SecTrustRef trust, CFStringRef policyName) OSStatus SecTrustSetPinningException(SecTrustRef trust) __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0) __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0); -#if TARGET_OS_IPHONE /*! @function SecTrustGetExceptionResetCount @abstract Returns the current epoch of trusted exceptions. @@ -441,8 +452,8 @@ OSStatus SecTrustSetPinningException(SecTrustRef trust) @result An unsigned 64-bit integer representing the current epoch. @discussion Exceptions tagged with an older epoch are not trusted. */ -uint64_t SecTrustGetExceptionResetCount(CFErrorRef *error) - API_UNAVAILABLE(macos, iosmac) API_AVAILABLE(ios(12.0), tvos(12.0), watchos(5.0)); +uint64_t SecTrustGetExceptionResetCount(CFErrorRef _Nullable * _Nullable CF_RETURNS_RETAINED error) + API_AVAILABLE(macos(11.3), ios(12.0), tvos(12.0), watchos(5.0)); /*! @function SecTrustIncrementExceptionResetCount @@ -451,9 +462,8 @@ uint64_t SecTrustGetExceptionResetCount(CFErrorRef *error) @result A result code. See "Security Error Codes" (SecBase.h) @discussion By increasing the current epoch any existing exceptions, tagged with the old epoch, become distrusted. */ -OSStatus SecTrustIncrementExceptionResetCount(CFErrorRef *error) - __API_UNAVAILABLE(macos, iosmac) __API_AVAILABLE(ios(12.0), tvos(12.0), watchos(5.0)); -#endif +OSStatus SecTrustIncrementExceptionResetCount(CFErrorRef _Nullable * _Nullable CF_RETURNS_RETAINED error) + API_AVAILABLE(macos(11.3), ios(12.0), tvos(12.0), watchos(5.0)); #ifdef __BLOCKS__ /*! diff --git a/trust/headers/SecTrustSettingsPriv.h b/trust/headers/SecTrustSettingsPriv.h index 62b1c9b4..8f8ecfd9 100644 --- a/trust/headers/SecTrustSettingsPriv.h +++ b/trust/headers/SecTrustSettingsPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -50,6 +50,9 @@ __BEGIN_DECLS #define kSecTrustSettingsPolicyName CFSTR("kSecTrustSettingsPolicyName") #define kSecTrustSettingsPolicyOptions CFSTR("kSecTrustSettingsPolicyOptions") +extern const CFStringRef kSecTrustStoreSPKIHashKey; +extern const CFStringRef kSecTrustStoreHashAlgorithmKey; + extern const CFStringRef kSecCTExceptionsCAsKey; extern const CFStringRef kSecCTExceptionsDomainsKey; extern const CFStringRef kSecCTExceptionsHashAlgorithmKey; @@ -58,15 +61,15 @@ extern const CFStringRef kSecCTExceptionsSPKIHashKey; /* @function SecTrustStoreSetCTExceptions @abstract Set the certificate transparency enforcement exceptions - @param applicationIdentifier Identifier for the caller. If null, the application-identifier will be read from the callers entitlements. + @param applicationIdentifier Identifier for the caller. If null, the application-identifier will be read from the caller's entitlements. @param exceptions Dictionary of exceptions to set for this application. These exceptions replace existing exceptions for the keys in the dictionary. Exceptions for omitted keys are not affected. Null removes all exceptions for this application. See the discussion sections below for a complete overview of options. - @param error Upon failure describes cause of the failure. + @param error On failure, describes the cause of the failure; otherwise, null. @result boolean indicating success of the operation. If false, error will be filled in with a description of the error. @discussions An exceptions dictionary has two optional keys: kSecCTExceptionsDomainsKey takes an array of strings. These strings are the domains that are excluded from enforcing CT. A leading "." is supported to signify subdomains. Wildcard domains are not supported. kSecCTExceptionsCAsKey takes an array of dictionaries. Each dictionary has two required keys: - kSecCTExceptionsHashAlgorithmKey takes a string indicating the hash algorithm. Currenlty only "sha256" is supported. - kSecCTExceptionsSPKIHashKey takes a data containing hash of a certificates SubjectPublicKeyInfo. + kSecTrustStoreHashAlgorithmKey takes a string indicating the hash algorithm. Currently only "sha256" is supported. + kSecTrustStoreSPKIHashKey takes a data containing hash of a certificate's SubjectPublicKeyInfo. */ bool SecTrustStoreSetCTExceptions(CFStringRef applicationIdentifier, CFDictionaryRef exceptions, CFErrorRef *error); @@ -74,12 +77,65 @@ bool SecTrustStoreSetCTExceptions(CFStringRef applicationIdentifier, CFDictionar @function SecTrustStoreCopyCTExceptions @abstract Return the certificate transparency enforcement exceptions @param applicationIdentifier Identifier for the caller's exceptions to fetch. If null, all set exceptions will be returned (regardless of which caller set them). - @param error Upon failure describes cause of the failure. + @param error On failure, describes the cause of the failure; otherwise, null. @result The dictionary of currently set exceptions. Null if none exist or upon failure. @discussion The returned exceptions dictionary has the same options as input exceptions. See the discussion of SecTrustStoreSetCTExceptions. */ CF_RETURNS_RETAINED CFDictionaryRef SecTrustStoreCopyCTExceptions(CFStringRef applicationIdentifier, CFErrorRef *error); + +extern const CFStringRef kSecCARevocationAdditionsKey; +extern const CFStringRef kSecCARevocationHashAlgorithmKey; +extern const CFStringRef kSecCARevocationSPKIHashKey; + +/* + @function SecTrustStoreSetCARevocationAdditions + @abstract Set a list of certificate authorities (specified by subject public key info hash) for which revocation should be explicitly checked. + @param applicationIdentifier Identifier for the caller. If null, the application-identifier will be read from the caller's entitlements. + @param additions Dictionary of SPKI hashes for which revocation should be explicitly checked. Existing entries for the keys in the dictionary will be replaced. Null removes all CA revocation additions for this application. See the discussion sections below for a complete overview of options. + @param error On failure, describes the cause of the failure; otherwise, null. + @result boolean indicating success of the operation. If false, error will be filled in with a description of the error. + @discussions An additions dictionary currently has one defined key: + kSecCARevocationAdditionsKey takes an array of dictionaries. Each dictionary has two required keys: + kSecTrustStoreHashAlgorithmKey takes a string indicating the hash algorithm. Currently only "sha256" is supported. + kSecTrustStoreSPKIHashKey takes a data containing hash of a certificate's SubjectPublicKeyInfo. + */ +bool SecTrustStoreSetCARevocationAdditions(CFStringRef applicationIdentifier, CFDictionaryRef additions, CFErrorRef *error); + +/* + @function SecTrustStoreCopyCARevocationAdditions + @abstract Return the certificate authority SPKI hashes for which revocation should be explicitly checked. + @param applicationIdentifier Identifier for the caller's additions to fetch. If null, all set exceptions will be returned (regardless of which caller set them). + @param error On failure, describes cause of the failure; otherwise, null. + @result The dictionary of currently set CA revocation additions. Null if none exist or upon failure. + @discussion The returned additions dictionary has the same options as input additions. See the discussion of SecTrustStoreSetCARevocationAdditions. + */ +CF_RETURNS_RETAINED CFDictionaryRef SecTrustStoreCopyCARevocationAdditions(CFStringRef applicationIdentifier, CFErrorRef *error); + +/* + @function SecTrustStoreSetTransparentConnectionPins + @abstract Set a list of certificate authorities (specified by subject public key info hash) to which Transparent Connections should be pinned. + @param applicationIdentifier Identifier for the caller. If null, the application-identifier will be read from the caller's entitlements. + @param pins Array of dictionaries containing SPKI hashes to which Transparent Connections should be pinned. Existing entries for the keys in the dictionary will be replaced. Null removes all pins for this application. See the discussion sections below for a complete overview of options. + @param error On failure, describes the cause of the failure; otherwise, null. + @result boolean indicating success of the operation. If false, error will be filled in with a description of the error. + @discussion The pins dictionaries should each have the following keys and values + kSecTrustStoreHashAlgorithmKey takes a string indicating the hash algorithm. Currently only "sha256" is supported. + kSecTrustStoreSPKIHashKey takes a data containing hash of a certificate's SubjectPublicKeyInfo. + The device must be in HRN mode to honor these pins. + */ +bool SecTrustStoreSetTransparentConnectionPins(CFStringRef applicationIdentifier, CFArrayRef pins, CFErrorRef *error); + +/* + @function SecTrustStoreCopyTransparentConnectionPins + @abstract Return the certificate authority SPKI hashes to which Transparent Connections should be pinned. + @param applicationIdentifier Identifier for the caller's additions to fetch. If null, all set exceptions will be returned (regardless of which caller set them). + @param error On failure, describes cause of the failure; otherwise, null. + @result The array of currently set CA pins. Null if none exist or upon failure. + @discussion The returned pins array has the same options as input pins. See the discussion of SecTrustStoreSetTransparentConnectionPins. + */ +CF_RETURNS_RETAINED CFArrayRef SecTrustStoreCopyTransparentConnectionPins(CFStringRef applicationIdentifier, CFErrorRef *error); + #if SEC_OS_OSX /* @@ -211,6 +267,19 @@ void SecTrustSettingsPurgeUserAdminCertsCache(void); */ OSStatus SecTrustSettingsCopyCertificatesForUserAdminDomains( CFArrayRef CF_RETURNS_RETAINED *certArray); + +/* Just like the API version (SecTrustSettingsCopyTrustSettings) but + * uses the cached version of trust settings to avoid disk reads. */ +OSStatus SecTrustSettingsCopyTrustSettings_Cached( + SecCertificateRef certRef, + SecTrustSettingsDomain domain, + CFArrayRef CF_RETURNS_RETAINED *trustSettings); + +/* Purge the trust settings cache (used by the above) */ +void SecTrustSettingsPurgeCache(void); + +/* Determines if the given cert has any trust settings in the admin or user domains */ +bool SecTrustSettingsUserAdminDomainsContain(SecCertificateRef certRef); #endif /* SEC_OS_OSX_INCLUDES */ __END_DECLS diff --git a/trust/headers/oids.h b/trust/headers/oids.h index 4a1d490d..d524d573 100644 --- a/trust/headers/oids.h +++ b/trust/headers/oids.h @@ -27,6 +27,14 @@ * */ +/* We need to guard against the other copy of libDER. + * This is outside this header's guards because DERItem.h currently guards + * the DERItem type against this header (legacy from when this header also + * defined the type). */ +#ifndef _LIB_DER_H_ +#include +#endif /* _LIB_DER_H_ */ + #ifndef _SECURITY_OIDS_H_ #define _SECURITY_OIDS_H_ @@ -35,24 +43,6 @@ __BEGIN_DECLS -/* This is a subset of libDER's oids.h. If the types header has - * already been included, we should skip these typedef declarations. */ -#ifndef _LIB_DER_H_ -/* - * Basic data types - */ -typedef uint8_t DERByte; -typedef size_t DERSize; - -/* - * Primary representation of a block of memory. - */ -typedef struct { - DERByte *data; - DERSize length; -} DERItem; -#endif /* _LIB_DER_H_ */ - /* Algorithm oids. */ extern const DERItem oidRsa, /* PKCS1 RSA encryption, used to identify RSA keys */ diff --git a/keychain/SecureObjectSync/Tool/syncbackup.h b/trust/trustd/CertificateTransparency.h similarity index 66% rename from keychain/SecureObjectSync/Tool/syncbackup.h rename to trust/trustd/CertificateTransparency.h index ccacc3c3..b51c32e6 100644 --- a/keychain/SecureObjectSync/Tool/syncbackup.h +++ b/trust/trustd/CertificateTransparency.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,21 +21,12 @@ * @APPLE_LICENSE_HEADER_END@ */ -// -// syncbackup.h -// sec -// -// -// +#ifndef _SECURITY_CERTIFICATE_TRANSPARENCY_H_ +#define _SECURITY_CERTIFICATE_TRANSPARENCY_H_ +#include "trust/trustd/SecPolicyServer.h" -#include "SecurityTool/sharedTool/security_tool_commands.h" - -SECURITY_COMMAND( - "syncbackup", syncbackup, - "[options]\n" - " -i info (current status)\n" - " -l list backup slice keybag membership and recovery status" - "\n", - "iCloud Circle Backup Information") +void SecPolicyCheckCT(SecPVCRef pvc); +bool SecPolicyCheckNonTlsCT(SecPVCRef pvc); +#endif /* _SECURITY_CERTIFICATE_TRANSPARENCY_H_ */ diff --git a/trust/trustd/CertificateTransparency.m b/trust/trustd/CertificateTransparency.m new file mode 100644 index 00000000..10a53612 --- /dev/null +++ b/trust/trustd/CertificateTransparency.m @@ -0,0 +1,749 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "trust/trustd/SecTrustServer.h" +#include "trust/trustd/SecPolicyServer.h" +#include "trust/trustd/SecOCSPResponse.h" +#include "trust/trustd/OTATrustUtilities.h" +#include "trust/trustd/SecCertificateServer.h" +#include "trust/trustd/CertificateTransparency.h" + +const CFStringRef kSecCTRetirementDateKey = CFSTR("expiry"); // For backwards compatibility, retirement date is represented with the "expiry" key +const CFStringRef kSecCTReadOnlyDateKey = CFSTR("frozen"); // For backwards compatibility, read-only date is represented with the "frozen" key +const CFStringRef kSecCTShardStartDateKey = CFSTR("start_inclusive"); +const CFStringRef kSecCTShardEndDateKey = CFSTR("end_exclusive"); +const CFStringRef kSecCTPublicKeyKey = CFSTR("key"); + +enum { + kSecCTEntryTypeCert = 0, + kSecCTEntryTypePreCert = 1, +}; + +/*** + +struct { + Version sct_version; // 1 byte + LogID id; // 32 bytes + uint64 timestamp; // 8 bytes + CtExtensions extensions; // 2 bytes len field, + n bytes data + digitally-signed struct { // 1 byte hash alg, 1 byte sig alg, n bytes signature + Version sct_version; + SignatureType signature_type = certificate_timestamp; + uint64 timestamp; + LogEntryType entry_type; + select(entry_type) { + case x509_entry: ASN.1Cert; + case precert_entry: PreCert; + } signed_entry; + CtExtensions extensions; + }; +} SignedCertificateTimestamp; + +***/ + +static const +SecAsn1Oid *oidForSigAlg(SSL_HashAlgorithm hash, SSL_SignatureAlgorithm alg) +{ + switch(alg) { + case SSL_SignatureAlgorithmRSA: + switch (hash) { + case SSL_HashAlgorithmSHA1: + return &CSSMOID_SHA1WithRSA; + case SSL_HashAlgorithmSHA256: + return &CSSMOID_SHA256WithRSA; + case SSL_HashAlgorithmSHA384: + return &CSSMOID_SHA384WithRSA; + default: + break; + } + case SSL_SignatureAlgorithmECDSA: + switch (hash) { + case SSL_HashAlgorithmSHA1: + return &CSSMOID_ECDSA_WithSHA1; + case SSL_HashAlgorithmSHA256: + return &CSSMOID_ECDSA_WithSHA256; + case SSL_HashAlgorithmSHA384: + return &CSSMOID_ECDSA_WithSHA384; + default: + break; + } + default: + break; + } + + return NULL; +} + + +static size_t SSLDecodeUint16(const uint8_t *p) +{ + return (p[0]<<8 | p[1]); +} + +static uint8_t *SSLEncodeUint16(uint8_t *p, size_t len) +{ + p[0] = (len >> 8)&0xff; + p[1] = (len & 0xff); + return p+2; +} + +static uint8_t *SSLEncodeUint24(uint8_t *p, size_t len) +{ + p[0] = (len >> 16)&0xff; + p[1] = (len >> 8)&0xff; + p[2] = (len & 0xff); + return p+3; +} + + +static +uint64_t SSLDecodeUint64(const uint8_t *p) +{ + uint64_t u = 0; + for(int i=0; i<8; i++) { + u=(u<<8)|p[0]; + p++; + } + return u; +} + + +static CFDataRef copy_x509_entry_from_chain(SecPVCRef pvc) +{ + SecCertificateRef leafCert = SecPVCGetCertificateAtIndex(pvc, 0); + + CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 3+SecCertificateGetLength(leafCert)); + + CFDataSetLength(data, 3+SecCertificateGetLength(leafCert)); + + uint8_t *q = CFDataGetMutableBytePtr(data); + q = SSLEncodeUint24(q, SecCertificateGetLength(leafCert)); + memcpy(q, SecCertificateGetBytePtr(leafCert), SecCertificateGetLength(leafCert)); + + return data; +} + + +static CFDataRef copy_precert_entry_from_chain(SecPVCRef pvc) +{ + SecCertificateRef leafCert = NULL; + SecCertificateRef issuer = NULL; + CFDataRef issuerKeyHash = NULL; + CFDataRef tbs_precert = NULL; + CFMutableDataRef data= NULL; + + require_quiet(SecPVCGetCertificateCount(pvc)>=2, out); //we need the issuer key for precerts. + leafCert = SecPVCGetCertificateAtIndex(pvc, 0); + issuer = SecPVCGetCertificateAtIndex(pvc, 1); + + require(leafCert, out); + require(issuer, out); // Those two would likely indicate an internal error, since we already checked the chain length above. + issuerKeyHash = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(issuer); + tbs_precert = SecCertificateCopyPrecertTBS(leafCert); + + require(issuerKeyHash, out); + require(tbs_precert, out); + data = CFDataCreateMutable(kCFAllocatorDefault, CFDataGetLength(issuerKeyHash) + 3 + CFDataGetLength(tbs_precert)); + CFDataSetLength(data, CFDataGetLength(issuerKeyHash) + 3 + CFDataGetLength(tbs_precert)); + + uint8_t *q = CFDataGetMutableBytePtr(data); + memcpy(q, CFDataGetBytePtr(issuerKeyHash), CFDataGetLength(issuerKeyHash)); q += CFDataGetLength(issuerKeyHash); // issuer key hash + q = SSLEncodeUint24(q, CFDataGetLength(tbs_precert)); + memcpy(q, CFDataGetBytePtr(tbs_precert), CFDataGetLength(tbs_precert)); + +out: + CFReleaseSafe(issuerKeyHash); + CFReleaseSafe(tbs_precert); + return data; +} + +static +CFAbsoluteTime TimestampToCFAbsoluteTime(uint64_t ts) +{ + return (ts / 1000) - kCFAbsoluteTimeIntervalSince1970; +} + +static +uint64_t TimestampFromCFAbsoluteTime(CFAbsoluteTime at) +{ + return (uint64_t)(at + kCFAbsoluteTimeIntervalSince1970) * 1000; +} + +static bool isSCTValidForLogData(CFDictionaryRef logData, int entry_type, CFAbsoluteTime sct_time, CFAbsoluteTime cert_expiry_date) { + /* only embedded SCTs can be used from retired logs. */ + if(entry_type==kSecCTEntryTypeCert && CFDictionaryContainsKey(logData, kSecCTRetirementDateKey)) { + return false; + } + + /* SCTs from after the transition to read-only are not valid (and indicate a operator failure) */ + CFDateRef frozen_date = CFDictionaryGetValue(logData, kSecCTReadOnlyDateKey); + if (frozen_date && (sct_time > CFDateGetAbsoluteTime(frozen_date))) { + secerror("Frozen CT log issued SCT after freezing (log=%@)\n", logData); + return false; + } + + /* If the log is temporally sharded, the certificate expiry date must be within the temporal shard window */ + CFDateRef start_inclusive = CFDictionaryGetValue(logData, kSecCTShardStartDateKey); + CFDateRef end_exclusive = CFDictionaryGetValue(logData, kSecCTShardEndDateKey); + if (start_inclusive && (cert_expiry_date < CFDateGetAbsoluteTime(start_inclusive))) { + return false; + } + if (end_exclusive && (cert_expiry_date >= CFDateGetAbsoluteTime(end_exclusive))) { + return false; + } + + return true; +} + + +/* + If the 'sct' is valid, add it to the validatingLogs dictionary. + + Inputs: + - validatingLogs: mutable dictionary to which to add the log that validate this SCT. + - sct: the SCT date + - entry_type: 0 for x509 cert, 1 for precert. + - entry: the cert or precert data. + - vt: verification time timestamp (as used in SCTs: ms since 1970 Epoch) + - trustedLog: Dictionary contain the Trusted Logs. + + The SCT is valid if: + - It decodes properly. + - Its timestamp is less than 'verifyTime'. + - It is signed by a log in 'trustedLogs'. + - If entry_type = 0, the log must be currently qualified. + - If entry_type = 1, the log may be expired. + + If the SCT is valid, it's added to the validatinLogs dictionary using the log dictionary as the key, and the timestamp as value. + If an entry for the same log already existing in the dictionary, the entry is replaced only if the timestamp of this SCT is earlier. + + */ +static CFDictionaryRef getSCTValidatingLog(CFDataRef sct, int entry_type, CFDataRef entry, uint64_t vt, CFAbsoluteTime cert_expiry_date, CFDictionaryRef trustedLogs, CFAbsoluteTime *sct_at) +{ + uint8_t version; + const uint8_t *logID; + const uint8_t *timestampData; + uint64_t timestamp; + size_t extensionsLen; + const uint8_t *extensionsData; + uint8_t hashAlg; + uint8_t sigAlg; + size_t signatureLen; + const uint8_t *signatureData; + SecKeyRef pubKey = NULL; + uint8_t *signed_data = NULL; + const SecAsn1Oid *oid = NULL; + SecAsn1AlgId algId; + CFDataRef logIDData = NULL; + CFDictionaryRef result = 0; + + const uint8_t *p = CFDataGetBytePtr(sct); + size_t len = CFDataGetLength(sct); + + require(len>=43, out); + + version = p[0]; p++; len--; + logID = p; p+=32; len-=32; + timestampData = p; p+=8; len-=8; + extensionsLen = SSLDecodeUint16(p); p+=2; len-=2; + + require(len>=extensionsLen, out); + extensionsData = p; p+=extensionsLen; len-=extensionsLen; + + require(len>=4, out); + hashAlg=p[0]; p++; len--; + sigAlg=p[0]; p++; len--; + signatureLen = SSLDecodeUint16(p); p+=2; len-=2; + require(len==signatureLen, out); /* We do not tolerate any extra data after the signature */ + signatureData = p; + + /* verify version: only v1(0) is supported */ + if(version!=0) { + secerror("SCT version unsupported: %d\n", version); + goto out; + } + + /* verify timestamp not in the future */ + timestamp = SSLDecodeUint64(timestampData); + if(timestamp > vt) { + secerror("SCT is in the future: %llu > %llu\n", timestamp, vt); + goto out; + } + + uint8_t *q; + + /* signed entry */ + size_t signed_data_len = 12 + CFDataGetLength(entry) + 2 + extensionsLen ; + signed_data = malloc(signed_data_len); + require(signed_data, out); + q = signed_data; + *q++ = version; + *q++ = 0; // certificate_timestamp + memcpy(q, timestampData, 8); q+=8; + q = SSLEncodeUint16(q, entry_type); // logentry type: 0=cert 1=precert + memcpy(q, CFDataGetBytePtr(entry), CFDataGetLength(entry)); q += CFDataGetLength(entry); + q = SSLEncodeUint16(q, extensionsLen); + memcpy(q, extensionsData, extensionsLen); + + logIDData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, logID, 32, kCFAllocatorNull); + + CFDictionaryRef logData = CFDictionaryGetValue(trustedLogs, logIDData); + CFAbsoluteTime sct_time = TimestampToCFAbsoluteTime(timestamp); + require(logData && isSCTValidForLogData(logData, entry_type, sct_time, cert_expiry_date), out); + + CFDataRef logKeyData = CFDictionaryGetValue(logData, kSecCTPublicKeyKey); + require(logKeyData, out); // This failing would be an internal logic error + pubKey = SecKeyCreateFromSubjectPublicKeyInfoData(kCFAllocatorDefault, logKeyData); + require(pubKey, out); + + oid = oidForSigAlg(hashAlg, sigAlg); + require(oid, out); + + algId.algorithm = *oid; + algId.parameters.Data = NULL; + algId.parameters.Length = 0; + + if(SecKeyDigestAndVerify(pubKey, &algId, signed_data, signed_data_len, signatureData, signatureLen)==0) { + *sct_at = sct_time; + result = logData; + } else { + secerror("SCT signature failed (log=%@)\n", logData); + } + +out: + CFReleaseSafe(logIDData); + CFReleaseSafe(pubKey); + free(signed_data); + return result; +} + + +static void addValidatingLog(CFMutableDictionaryRef validatingLogs, CFDictionaryRef log, CFAbsoluteTime sct_at) +{ + CFDateRef validated_time = CFDictionaryGetValue(validatingLogs, log); + + if(validated_time==NULL || (sct_at < CFDateGetAbsoluteTime(validated_time))) { + CFDateRef sct_time = CFDateCreate(kCFAllocatorDefault, sct_at); + CFDictionarySetValue(validatingLogs, log, sct_time); + CFReleaseSafe(sct_time); + } +} + +static CFArrayRef copy_ocsp_scts(SecPVCRef pvc) +{ + CFMutableArrayRef SCTs = NULL; + SecCertificateRef leafCert = NULL; + SecCertificateRef issuer = NULL; + CFArrayRef ocspResponsesData = NULL; + SecOCSPRequestRef ocspRequest = NULL; + + ocspResponsesData = SecPathBuilderCopyOCSPResponses(pvc->builder); + require_quiet(ocspResponsesData, out); + + require_quiet(SecPVCGetCertificateCount(pvc)>=2, out); //we need the issuer key for precerts. + leafCert = SecPVCGetCertificateAtIndex(pvc, 0); + issuer = SecPVCGetCertificateAtIndex(pvc, 1); + + require(leafCert, out); + require(issuer, out); // not quiet: Those two would likely indicate an internal error, since we already checked the chain length above. + ocspRequest = SecOCSPRequestCreate(leafCert, issuer); + + SCTs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + require(SCTs, out); + + CFArrayForEach(ocspResponsesData, ^(const void *value) { + /* TODO: Should the builder already have the appropriate SecOCSPResponseRef ? */ + SecOCSPResponseRef ocspResponse = SecOCSPResponseCreate(value); + if(ocspResponse && SecOCSPGetResponseStatus(ocspResponse)==kSecOCSPSuccess) { + SecOCSPSingleResponseRef ocspSingleResponse = SecOCSPResponseCopySingleResponse(ocspResponse, ocspRequest); + if(ocspSingleResponse) { + CFArrayRef singleResponseSCTs = SecOCSPSingleResponseCopySCTs(ocspSingleResponse); + if(singleResponseSCTs) { + CFArrayAppendArray(SCTs, singleResponseSCTs, CFRangeMake(0, CFArrayGetCount(singleResponseSCTs))); + CFRelease(singleResponseSCTs); + } + SecOCSPSingleResponseDestroy(ocspSingleResponse); + } + } + if(ocspResponse) SecOCSPResponseFinalize(ocspResponse); + }); + + if(CFArrayGetCount(SCTs)==0) { + CFReleaseNull(SCTs); + } + +out: + CFReleaseSafe(ocspResponsesData); + if(ocspRequest) + SecOCSPRequestFinalize(ocspRequest); + + return SCTs; +} + +static bool find_validating_logs(SecPVCRef pvc, CFDictionaryRef trustedLogs, + CFDictionaryRef CF_RETURNS_RETAINED * _Nonnull outCurrentLogsValidatingScts, + CFDictionaryRef CF_RETURNS_RETAINED * _Nonnull outLogsValidatingEmbeddedScts, + bool * _Nonnull out_at_least_one_currently_valid_external, + bool * _Nonnull out_at_least_one_currently_valid_embedded) { + SecCertificateRef leafCert = SecPVCGetCertificateAtIndex(pvc, 0); + CFArrayRef embeddedScts = SecCertificateCopySignedCertificateTimestamps(leafCert); + CFArrayRef builderScts = SecPathBuilderCopySignedCertificateTimestamps(pvc->builder); + CFArrayRef ocspScts = copy_ocsp_scts(pvc); + CFDataRef precertEntry = copy_precert_entry_from_chain(pvc); + CFDataRef x509Entry = copy_x509_entry_from_chain(pvc); + __block CFAbsoluteTime certExpiry = SecCertificateNotValidAfter(leafCert); + bool result = NO; + + // This eventually contain list of logs who validated the SCT. + CFMutableDictionaryRef currentLogsValidatingScts = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFMutableDictionaryRef logsValidatingEmbeddedScts = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + uint64_t vt = TimestampFromCFAbsoluteTime(SecPVCGetVerifyTime(pvc)); + + __block bool at_least_one_currently_valid_external = 0; + __block bool at_least_one_currently_valid_embedded = 0; + + require(logsValidatingEmbeddedScts, out); + require(currentLogsValidatingScts, out); + + /* Skip if there are no SCTs. */ + bool no_scts = (embeddedScts && CFArrayGetCount(embeddedScts) > 0) || + (builderScts && CFArrayGetCount(builderScts) > 0) || + (ocspScts && CFArrayGetCount(ocspScts) > 0); + require_quiet(no_scts, out); + + if(trustedLogs && CFDictionaryGetCount(trustedLogs) > 0) { // Don't bother trying to validate SCTs if we don't have any trusted logs. + if(embeddedScts && precertEntry) { // Don't bother if we could not get the precert. + CFArrayForEach(embeddedScts, ^(const void *value){ + CFAbsoluteTime sct_at; + CFDictionaryRef log = getSCTValidatingLog(value, 1, precertEntry, vt, certExpiry, trustedLogs, &sct_at); + if(log) { + addValidatingLog(logsValidatingEmbeddedScts, log, sct_at); + if(!CFDictionaryContainsKey(log, kSecCTRetirementDateKey)) { + addValidatingLog(currentLogsValidatingScts, log, sct_at); + at_least_one_currently_valid_embedded = true; + } + } + }); + } + + if(builderScts && x509Entry) { // Don't bother if we could not get the cert. + CFArrayForEach(builderScts, ^(const void *value){ + CFAbsoluteTime sct_at; + CFDictionaryRef log = getSCTValidatingLog(value, 0, x509Entry, vt, certExpiry, trustedLogs, &sct_at); + if(log) { + addValidatingLog(currentLogsValidatingScts, log, sct_at); + at_least_one_currently_valid_external = true; + } + }); + } + + if(ocspScts && x509Entry) { + CFArrayForEach(ocspScts, ^(const void *value){ + CFAbsoluteTime sct_at; + CFDictionaryRef log = getSCTValidatingLog(value, 0, x509Entry, vt, certExpiry, trustedLogs, &sct_at); + if(log) { + addValidatingLog(currentLogsValidatingScts, log, sct_at); + at_least_one_currently_valid_external = true; + } + }); + } + } + + if (CFDictionaryGetCount(currentLogsValidatingScts) > 0) { + result = true; + *outCurrentLogsValidatingScts = CFRetainSafe(currentLogsValidatingScts); + *outLogsValidatingEmbeddedScts = CFRetainSafe(logsValidatingEmbeddedScts); + *out_at_least_one_currently_valid_embedded = at_least_one_currently_valid_embedded; + *out_at_least_one_currently_valid_external = at_least_one_currently_valid_external; + } + +out: + CFReleaseSafe(logsValidatingEmbeddedScts); + CFReleaseSafe(currentLogsValidatingScts); + CFReleaseSafe(builderScts); + CFReleaseSafe(embeddedScts); + CFReleaseSafe(ocspScts); + CFReleaseSafe(precertEntry); + CFReleaseSafe(x509Entry); + return result; +} + +/* For certificates issued before 4/21/2021: + * Certificate lifetime | # of SCTs from separate logs + *---------------------------------------------------- + * Less than 15 months | 2 + * 15 to 27 months | 3 + * 27 to 39 months | 4 + * More than 39 months | 5 + */ +static bool verify_embedded_sct_policy_v1(SecCertificateRef leafCert, unsigned once_or_current_qualified_embedded) { + __block bool result = false; + __block int lifetime = 60; // in Months + + SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) { + int _lifetime = lifetime; + CFCalendarGetComponentDifference(zuluCalendar, + SecCertificateNotValidBefore(leafCert), + SecCertificateNotValidAfter(leafCert), + 0, "M", &_lifetime); + lifetime = _lifetime; + }); + + unsigned requiredEmbeddedSctsCount = 5; + + if (lifetime < 15) { + requiredEmbeddedSctsCount = 2; + } else if (lifetime <= 27) { + requiredEmbeddedSctsCount = 3; + } else if (lifetime <= 39) { + requiredEmbeddedSctsCount = 4; + } + + if(once_or_current_qualified_embedded >= requiredEmbeddedSctsCount){ + result = true; + } + + return result; +} + +/* For certificates issued on or after 4/21/2021 00:00:00Z: + * Certificate lifetime | # of SCTs from | Maximum # of SCTs + * | separate logs | per log operator + *---------------------------------------------------- + * 180 days or less | 2 | 1 + * 181 to 825 days | 3 | 2 + * 826 to 1187 days | 4 | N/A + */ +static bool verify_embedded_sct_policy_v2(SecCertificateRef leafCert, unsigned once_or_current_qualified_embedded) { + bool result = false; + CFAbsoluteTime lifetime = SecCertificateNotValidAfter(leafCert) - SecCertificateNotValidBefore(leafCert); + + unsigned requiredEmbeddedSctsCount = 4; + if (lifetime <= 180*24*60*60) { + requiredEmbeddedSctsCount = 2; + } else if (lifetime <= 825*24*60*60) { + requiredEmbeddedSctsCount = 3; + } + + if (once_or_current_qualified_embedded >= requiredEmbeddedSctsCount){ + result = true; + } + + return result; +} + +static bool verify_tls_ct_policy(SecPVCRef pvc, CFDictionaryRef currentLogsValidatingScts, CFDictionaryRef logsValidatingEmbeddedScts, + bool at_least_one_currently_valid_external, bool at_least_one_currently_valid_embedded, + CFIndex * _Nonnull outTrustedSCTCount) +{ + if (!logsValidatingEmbeddedScts || !currentLogsValidatingScts) { + return false; + } + + __block CFAbsoluteTime issuanceTime = SecPVCGetVerifyTime(pvc); + SecCertificateRef leafCert = SecPVCGetCertificateAtIndex(pvc, 0); + __block CFIndex trustedSCTCount = CFDictionaryGetCount(currentLogsValidatingScts); + + /* We now have 2 sets of logs that validated those SCTS, count them and make a final decision. + + Current Policy: + is_ct = (A1 AND A2) OR (B1 AND B2). + + A1: embedded SCTs from 2+ to 5+ logs valid at issuance time + A2: At least one embedded SCT from a currently valid log. + + B1: SCTs from 2 currently valid logs (from any source) + B2: At least 1 external SCT from a currently valid log. + + */ + + bool hasValidExternalSCT = (at_least_one_currently_valid_external && CFDictionaryGetCount(currentLogsValidatingScts)>=2); + bool hasValidEmbeddedSCT = (at_least_one_currently_valid_embedded); + SecCertificatePathVCRef path = SecPathBuilderGetPath(pvc->builder); + bool result = false; + + if (hasValidEmbeddedSCT) { + /* Calculate issuance time based on timestamp of SCTs from current logs */ + CFDictionaryForEach(currentLogsValidatingScts, ^(const void *key, const void *value) { + CFDictionaryRef log = key; + if(!CFDictionaryContainsKey(log, kSecCTRetirementDateKey)) { + // Log is still qualified + CFDateRef ts = (CFDateRef) value; + CFAbsoluteTime timestamp = CFDateGetAbsoluteTime(ts); + if(timestamp < issuanceTime) { + issuanceTime = timestamp; + } + } + }); + SecCertificatePathVCSetIssuanceTime(path, issuanceTime); + } + if (hasValidExternalSCT) { + /* Note: since external SCT validates this cert, we do not need to + override issuance time here. If the cert also has a valid embedded + SCT, issuanceTime will be calculated and set in the block above. */ + result = true; + } else if (hasValidEmbeddedSCT) { + /* Count Logs */ + __block unsigned once_or_current_qualified_embedded = 0; + __block bool failed_once_check = false; + CFDictionaryForEach(logsValidatingEmbeddedScts, ^(const void *key, const void *value) { + CFDictionaryRef log = key; + CFDateRef ts = value; + CFDateRef expiry = CFDictionaryGetValue(log, kSecCTRetirementDateKey); + if (expiry == NULL) { // Currently qualified OR + once_or_current_qualified_embedded++; + } else if (CFDateCompare(ts, expiry, NULL) == kCFCompareLessThan && // Once qualified. That is, qualified at the time of SCT AND + issuanceTime < CFDateGetAbsoluteTime(expiry)) { // at the time of issuance.) + once_or_current_qualified_embedded++; + trustedSCTCount++; + } else { + failed_once_check = true; + } + }); + + CFAbsoluteTime apr_21_2021 = 640656000.0; // 21 April 2021 00:00:00 UTC + if (SecCertificateNotValidBefore(leafCert) < apr_21_2021) { + result = verify_embedded_sct_policy_v1(leafCert, once_or_current_qualified_embedded); + } else { + result = verify_embedded_sct_policy_v2(leafCert, once_or_current_qualified_embedded); + } + } + + *outTrustedSCTCount = trustedSCTCount; + return result; +} + +static void report_ct_analytics(SecPVCRef pvc, CFDictionaryRef currentLogsValidatingScts, CFIndex trustedSCTCount) +{ + /* Record analytics data for CT */ + TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(pvc->builder); + if (!analytics) { + return; + } + + SecCertificateRef leafCert = SecPVCGetCertificateAtIndex(pvc, 0); + CFArrayRef embeddedScts = SecCertificateCopySignedCertificateTimestamps(leafCert); + CFArrayRef builderScts = SecPathBuilderCopySignedCertificateTimestamps(pvc->builder); + CFArrayRef ocspScts = copy_ocsp_scts(pvc); + + uint32_t sctCount = 0; + /* Count the total number of SCTs we found and report where we got them */ + if (embeddedScts && CFArrayGetCount(embeddedScts) > 0) { + analytics->sct_sources |= TA_SCTEmbedded; + sctCount += CFArrayGetCount(embeddedScts); + } + if (builderScts && CFArrayGetCount(builderScts) > 0) { + analytics->sct_sources |= TA_SCT_TLS; + sctCount += CFArrayGetCount(builderScts); + } + if (ocspScts && CFArrayGetCount(ocspScts) > 0) { + analytics->sct_sources |= TA_SCT_OCSP; + sctCount += CFArrayGetCount(ocspScts); + } + /* Report how many of those SCTs were once or currently qualified */ + analytics->number_trusted_scts = (uint32_t)trustedSCTCount; + /* Report how many SCTs we got */ + analytics->number_scts = sctCount; + /* Only one current SCT -- close to failure */ + if (CFDictionaryGetCount(currentLogsValidatingScts) == 1) { + analytics->ct_one_current = true; + } + + CFReleaseNull(embeddedScts); + CFReleaseNull(builderScts); + CFReleaseNull(ocspScts); +} + +void SecPolicyCheckCT(SecPVCRef pvc) +{ + CFDictionaryRef trustedLogs = SecPathBuilderCopyTrustedLogs(pvc->builder); + if (!trustedLogs) { + SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef(); + trustedLogs = SecOTAPKICopyTrustedCTLogs(otapkiref); + CFReleaseSafe(otapkiref); + } + + CFDictionaryRef currentLogsValidatingScts = NULL; + CFDictionaryRef logsValidatingEmbeddedScts = NULL; + bool at_least_one_currently_valid_external = false; + bool at_least_one_currently_valid_embedded = false; + CFIndex trustedSCTCount = 0; + SecCertificatePathVCRef path = SecPathBuilderGetPath(pvc->builder); + + SecCertificatePathVCSetIsCT(path, false); + if (find_validating_logs(pvc, trustedLogs, ¤tLogsValidatingScts, &logsValidatingEmbeddedScts, &at_least_one_currently_valid_external, &at_least_one_currently_valid_embedded)) { + if (verify_tls_ct_policy(pvc, currentLogsValidatingScts, logsValidatingEmbeddedScts, at_least_one_currently_valid_external, at_least_one_currently_valid_embedded, &trustedSCTCount)) { + SecCertificatePathVCSetIsCT(path, true); + } + report_ct_analytics(pvc, currentLogsValidatingScts, trustedSCTCount); + } + + CFReleaseNull(currentLogsValidatingScts); + CFReleaseNull(logsValidatingEmbeddedScts); + CFReleaseNull(trustedLogs); +} + +bool SecPolicyCheckNonTlsCT(SecPVCRef pvc) +{ + CFDictionaryRef trustedLogs = SecPathBuilderCopyTrustedLogs(pvc->builder); + if (!trustedLogs) { + SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef(); + trustedLogs = SecOTAPKICopyNonTlsTrustedCTLogs(otapkiref); + CFReleaseSafe(otapkiref); + } + + CFDictionaryRef currentLogsValidatingScts = NULL; + CFDictionaryRef logsValidatingEmbeddedScts = NULL; + bool at_least_one_currently_valid_external = false; + bool at_least_one_currently_valid_embedded = false; + CFIndex trustedSCTCount = 0; + SecCertificatePathVCRef path = SecPathBuilderGetPath(pvc->builder); + bool result = false; + + SecCertificatePathVCSetIsCT(path, false); + if (find_validating_logs(pvc, trustedLogs, ¤tLogsValidatingScts, &logsValidatingEmbeddedScts, &at_least_one_currently_valid_external, &at_least_one_currently_valid_embedded)) { + if (verify_tls_ct_policy(pvc, currentLogsValidatingScts, logsValidatingEmbeddedScts, at_least_one_currently_valid_external, at_least_one_currently_valid_embedded, &trustedSCTCount)) { + result = true; + } + report_ct_analytics(pvc, currentLogsValidatingScts, trustedSCTCount); + } + + CFReleaseNull(currentLogsValidatingScts); + CFReleaseNull(logsValidatingEmbeddedScts); + CFReleaseNull(trustedLogs); + return result; +} diff --git a/trust/trustd/OTATrustUtilities.h b/trust/trustd/OTATrustUtilities.h index 4b770f9d..5848e2f4 100644 --- a/trust/trustd/OTATrustUtilities.h +++ b/trust/trustd/OTATrustUtilities.h @@ -36,9 +36,6 @@ __BEGIN_DECLS // Opaque type that holds the data for a specific version of the OTA PKI assets typedef struct _OpaqueSecOTAPKI *SecOTAPKIRef; -// Returns a boolean for whether the current instance is the system trustd -bool SecOTAPKIIsSystemTrustd(void); - // Returns the trust server workloop dispatch_queue_t SecTrustServerGetWorkloop(void); @@ -154,16 +151,21 @@ NSNumber *SecOTAPKIGetSamplingRateForEvent(SecOTAPKIRef otapkiRef, NSString *eve CFArrayRef SecOTAPKICopyAppleCertificateAuthorities(SecOTAPKIRef otapkiRef); extern const CFStringRef kOTAPKIKillSwitchCT; +extern const CFStringRef kOTAPKIKillSwitchNonTLSCT; bool SecOTAPKIKillSwitchEnabled(SecOTAPKIRef otapkiRef, CFStringRef switchKey); // SPI to return the array of currently trusted Escrow certificates CF_EXPORT CFArrayRef SecOTAPKICopyCurrentEscrowCertificates(uint32_t escrowRootType, CFErrorRef* error); -// SPI to return the array of currently trusted CT logs +// SPI to return the array of currently (TLS) trusted CT logs CF_EXPORT CFDictionaryRef SecOTAPKICopyCurrentTrustedCTLogs(CFErrorRef* error); +// SPI to return the array of currently non-TLS trusted CT logs +CF_EXPORT +CFDictionaryRef SecOTAPKICopyNonTlsTrustedCTLogs(SecOTAPKIRef otapkiRef); + // SPI to return dictionary of CT log matching specified key id */ CF_EXPORT CFDictionaryRef SecOTAPKICopyCTLogForKeyID(CFDataRef keyID, CFErrorRef* error); diff --git a/trust/trustd/OTATrustUtilities.m b/trust/trustd/OTATrustUtilities.m index fa430942..8c8d095e 100644 --- a/trust/trustd/OTATrustUtilities.m +++ b/trust/trustd/OTATrustUtilities.m @@ -54,6 +54,7 @@ #include #include #include "trust/trustd/SecPinningDb.h" +#include "trust/trustd/trustdFileLocations.h" #import #if !TARGET_OS_BRIDGE @@ -90,28 +91,6 @@ static inline bool isNSData(id nsType) { return nsType && [nsType isKindOfClass:[NSData class]]; } -#define SECURITYD_ROLE_ACCOUNT 64 -#define ROOT_ACCOUNT 0 - -bool SecOTAPKIIsSystemTrustd() { - static bool result = false; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ -#ifdef NO_SERVER - // Test app running as trustd -#elif TARGET_OS_IPHONE - if (getuid() == SECURITYD_ROLE_ACCOUNT || - (getuid() == ROOT_ACCOUNT && gTrustd)) // Test app running as trustd -#else - if (getuid() == ROOT_ACCOUNT) -#endif - { - result = true; - } - }); - return result; -} - dispatch_queue_t SecTrustServerGetWorkloop(void) { static dispatch_workloop_t workloop = NULL; static dispatch_once_t onceToken; @@ -206,11 +185,16 @@ NSString *kOTATrustContentVersionKey = @"MobileAssetContentVersion"; NSString *kOTATrustLastCheckInKey = @"MobileAssetLastCheckIn"; NSString *kOTATrustContextFilename = @"OTAPKIContext.plist"; NSString *kOTATrustTrustedCTLogsFilename = @"TrustedCTLogs.plist"; +NSString *kOTATrustTrustedCTLogsNonTLSFilename = @"TrustedCTLogs_nonTLS.plist"; NSString *kOTATrustAnalyticsSamplingRatesFilename = @"AnalyticsSamplingRates.plist"; NSString *kOTATrustAppleCertifcateAuthoritiesFilename = @"AppleCertificateAuthorities.plist"; NSString *kOTASecExperimentConfigFilename = @"SecExperimentAssets.plist"; +/* A device will honor a kill switch until it gets a new asset xml that sets the kill switch value to 0/false + * OR the asset is (completely) reset to shipping version. Such resets can happen if asset files cannot be + * read properly or if the OS is updated and contains a newer asset version or pinning DB version. */ const CFStringRef kOTAPKIKillSwitchCT = CFSTR("CTKillSwitch"); +const CFStringRef kOTAPKIKillSwitchNonTLSCT = CFSTR("CTKillSwitch_nonTLS"); #if !TARGET_OS_BRIDGE NSString *OTATrustMobileAssetType = @"com.apple.MobileAsset.PKITrustSupplementals"; @@ -272,9 +256,9 @@ static void LogRemotelyWithAttributes(OTATrustLogLevel level, NSError **error, N #if ENABLE_TRUSTD_ANALYTICS /* only report errors and notices */ if (error && level == OTATrustLogLevelError) { - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:YES result:*error withAttributes:attributes]; + [[TrustAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:YES result:*error withAttributes:attributes]; } else if (error && level == OTATrustLogLevelNotice) { - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:NO result:*error withAttributes:attributes]; + [[TrustAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:NO result:*error withAttributes:attributes]; } #endif // ENABLE_TRUSTD_ANALYTICS } @@ -380,18 +364,19 @@ static BOOL ShouldUpdateWithAsset(NSString *assetType, NSNumber *asset_version) // MARK: File management functions static bool verify_create_path(const char *path) { - int ret = mkpath_np(path, 0755); - if (!(ret == 0 || ret == EEXIST)) { - secerror("could not create path: %s (%s)", path, strerror(ret)); - return false; + if (SecOTAPKIIsSystemTrustd()) { + int ret = mkpath_np(path, 0755); + if (!(ret == 0 || ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + return false; + } + chmod(path, 0755); } return true; } static NSURL *GetAssetFileURL(NSString *filename) { - /* Make sure the /Library/Keychains directory is there */ - NSURL *keychainsDirectory = CFBridgingRelease(SecCopyURLForFileInSystemKeychainDirectory(nil)); - NSURL *directory = [keychainsDirectory URLByAppendingPathComponent:@"SupplementalsAssets/" isDirectory:YES]; + NSURL *directory = CFBridgingRelease(SecCopyURLForFileInProtectedTrustdDirectory(CFSTR("SupplementalsAssets"))); if (!verify_create_path([directory fileSystemRepresentation])) { return nil; } @@ -417,7 +402,12 @@ static BOOL UpdateOTAContextOnDisk(NSString *key, id value, NSError **error) { if (SecOTAPKIIsSystemTrustd()) { /* Get current context, if applicable, and update/add key/value */ NSURL *otaContextFile = GetAssetFileURL(kOTATrustContextFilename); - NSDictionary *currentContext = [NSDictionary dictionaryWithContentsOfURL:otaContextFile]; + NSDictionary *currentContext = nil; + if (otaContextFile) { + currentContext = [NSDictionary dictionaryWithContentsOfURL:otaContextFile]; + } else { + return NO; + } NSMutableDictionary *newContext = nil; if (currentContext) { newContext = [currentContext mutableCopy]; @@ -427,7 +417,7 @@ static BOOL UpdateOTAContextOnDisk(NSString *key, id value, NSError **error) { newContext[key] = value; /* Write dictionary to disk */ - if (![newContext writeToURL:otaContextFile error:error]) { + if (![newContext writeToClassDURL:otaContextFile permissions:0644 error:error]) { secerror("OTATrust: unable to write OTA Context to disk: %@", error ? *error : nil); LogRemotely(OTATrustLogLevelError, error); return NO; @@ -446,6 +436,7 @@ static void DeleteOldAssetData(void) { if (SecOTAPKIIsSystemTrustd()) { /* Delete the asset files, but keep the check-in time and version */ DeleteFileWithName(kOTATrustTrustedCTLogsFilename); + DeleteFileWithName(kOTATrustTrustedCTLogsNonTLSFilename); DeleteFileWithName(kOTATrustAnalyticsSamplingRatesFilename); DeleteFileWithName(kOTATrustAppleCertifcateAuthoritiesFilename); } @@ -482,6 +473,19 @@ static bool ChangeFileProtectionToClassD(NSURL *fileURL, NSError **error) { } #endif +static bool ChangeFilePermissions(NSURL *fileURL, mode_t permissions, NSError **error) { + const char *path = [fileURL fileSystemRepresentation]; + int ret = chmod(path, permissions); + if (!(ret == 0)) { + int localErrno = errno; + secerror("failed to change permissions of %s: %s", path, strerror(localErrno)); + MakeOTATrustError(OTATrustMobileAssetType, error, OTATrustLogLevelError, NSPOSIXErrorDomain, errno, + @"failed to change permissions of %s: %s", path, strerror(localErrno)); + return NO; + } + return YES; +} + static BOOL CopyFileToDisk(NSString *filename, NSURL *localURL, NSError **error) { if (SecOTAPKIIsSystemTrustd()) { NSURL *toFileURL = GetAssetFileURL(filename); @@ -495,17 +499,22 @@ static BOOL CopyFileToDisk(NSString *filename, NSURL *localURL, NSError **error) @"copyfile error for asset %d: %s", errno, strerror(errno)); return NO; } else { - /* make sure we can read this file before first unlock */ + /* make sure all processes can read this file before first unlock */ #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - return ChangeFileProtectionToClassD(toFileURL, error); + return ChangeFilePermissions(toFileURL, 0644, error) && ChangeFileProtectionToClassD(toFileURL, error); #else - return YES; + return ChangeFilePermissions(toFileURL, 0644, error); #endif } } return NO; } +static void DisableKillSwitches() { + UpdateOTAContextOnDisk((__bridge NSString*)kOTAPKIKillSwitchCT, @0, nil); + UpdateOTAContextOnDisk((__bridge NSString*)kOTAPKIKillSwitchNonTLSCT, @0, nil); +} + static void GetKillSwitchAttributes(NSDictionary *attributes) { bool killSwitchEnabled = false; @@ -519,6 +528,16 @@ static void GetKillSwitchAttributes(NSDictionary *attributes) { killSwitchEnabled = true; } + // Non-TLS CT Kill Switch + ctKillSwitch = [attributes objectForKey:(__bridge NSString*)kOTAPKIKillSwitchNonTLSCT]; + if (isNSNumber(ctKillSwitch)) { + NSError *error = nil; + UpdateOTAContextOnDisk((__bridge NSString*)kOTAPKIKillSwitchNonTLSCT, ctKillSwitch, &error); + UpdateKillSwitch((__bridge NSString*)kOTAPKIKillSwitchNonTLSCT, [ctKillSwitch boolValue]); + secnotice("OTATrust", "got non-TLS CT kill switch = %d", [ctKillSwitch boolValue]); + killSwitchEnabled = true; + } + /* Other kill switches TBD. * When adding one, make sure to add to the Analytics Samplers since these kill switches * are installed before the full asset is downloaded and installed. (A device can have the @@ -536,7 +555,7 @@ static NSNumber *PKIUpdateAndPurgeAsset(MAAsset *asset, NSNumber *asset_version, UpdateFromAsset([asset getLocalFileUrl], asset_version, error)) { secnotice("OTATrust", "finished update to version %@ from installed asset. purging asset.", asset_version); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logSuccessForEventNamed:TrustdHealthAnalyticsEventOTAPKIEvent]; + [[TrustAnalytics logger] logSuccessForEventNamed:TrustdHealthAnalyticsEventOTAPKIEvent]; #endif // ENABLE_TRUSTD_ANALYTICS [asset purge:^(MAPurgeResult purge_result) { if (purge_result != MAPurgeSucceeded) { @@ -846,6 +865,7 @@ static void InitializeOTATrustAsset(dispatch_queue_t queue) { int out_token3 = 0; notify_register_dispatch(kOTATrustKillSwitchNotification, &out_token3, queue, ^(int __unused token) { UpdateKillSwitch((__bridge NSString*)kOTAPKIKillSwitchCT, InitializeKillSwitch((__bridge NSString*)kOTAPKIKillSwitchCT)); + UpdateKillSwitch((__bridge NSString*)kOTAPKIKillSwitchNonTLSCT, InitializeKillSwitch((__bridge NSString*)kOTAPKIKillSwitchNonTLSCT)); }); } } @@ -1054,13 +1074,13 @@ CFDictionaryRef SecOTAPKICreateTrustedCTLogsDictionaryFromArray(CFArrayRef trust } } -static CF_RETURNS_RETAINED CFDictionaryRef InitializeTrustedCTLogs() { +static CF_RETURNS_RETAINED CFDictionaryRef InitializeTrustedCTLogs(NSString *filename) { @autoreleasepool { NSArray *trustedCTLogs = nil; NSError *error = nil; #if !TARGET_OS_BRIDGE if (ShouldInitializeWithAsset()) { - trustedCTLogs = [NSArray arrayWithContentsOfURL:GetAssetFileURL(kOTATrustTrustedCTLogsFilename) error:&error]; + trustedCTLogs = [NSArray arrayWithContentsOfURL:GetAssetFileURL(filename) error:&error]; if (!isNSArray(trustedCTLogs)) { secerror("OTATrust: failed to read CT list from asset data: %@", error); LogRemotely(OTATrustLogLevelError, &error); @@ -1071,7 +1091,7 @@ static CF_RETURNS_RETAINED CFDictionaryRef InitializeTrustedCTLogs() { } #endif if (!isNSArray(trustedCTLogs)) { - trustedCTLogs = [NSArray arrayWithContentsOfURL:SecSystemTrustStoreCopyResourceNSURL(kOTATrustTrustedCTLogsFilename)]; + trustedCTLogs = [NSArray arrayWithContentsOfURL:SecSystemTrustStoreCopyResourceNSURL(filename)]; } if (isNSArray(trustedCTLogs)) { return CFBridgingRetain(ConvertTrustedCTLogsArrayToDictionary(trustedCTLogs)); @@ -1456,6 +1476,7 @@ struct _OpaqueSecOTAPKI { CFSetRef _grayListSet; CFDictionaryRef _allowList; CFDictionaryRef _trustedCTLogs; + CFDictionaryRef _nonTlsTrustedCTLogs; CFURLRef _pinningList; CFArrayRef _escrowCertificates; CFArrayRef _escrowPCSCertificates; @@ -1473,6 +1494,7 @@ struct _OpaqueSecOTAPKI { CFDictionaryRef _secExperimentConfig; uint64_t _secExperimentAssetVersion; bool _ctKillSwitch; + bool _nonTlsCtKillSwitch; }; CFGiblisFor(SecOTAPKI) @@ -1495,6 +1517,7 @@ static void SecOTAPKIDestroy(CFTypeRef cf) { CFReleaseNull(otapkiref->_anchorLookupTable); CFReleaseNull(otapkiref->_trustedCTLogs); + CFReleaseNull(otapkiref->_nonTlsTrustedCTLogs); CFReleaseNull(otapkiref->_pinningList); CFReleaseNull(otapkiref->_eventSamplingRates); CFReleaseNull(otapkiref->_appleCAs); @@ -1547,6 +1570,7 @@ static uint64_t GetAssetVersion(CFErrorRef *error) { *error = CFRetainSafe((__bridge CFErrorRef)nserror); } DeleteOldAssetData(); + DisableKillSwitches(); } #endif return version; @@ -1610,7 +1634,8 @@ static SecOTAPKIRef SecOTACreate() { // (now loaded lazily in SecOTAPKICopyAllowList) // Get the trusted Certificate Transparency Logs - otapkiref->_trustedCTLogs = InitializeTrustedCTLogs(); + otapkiref->_trustedCTLogs = InitializeTrustedCTLogs(kOTATrustTrustedCTLogsFilename); + otapkiref->_nonTlsTrustedCTLogs = InitializeTrustedCTLogs(kOTATrustTrustedCTLogsNonTLSFilename); // Get the pinning list otapkiref->_pinningList = InitializePinningList(); @@ -1675,15 +1700,13 @@ static SecOTAPKIRef SecOTACreate() { #if !TARGET_OS_BRIDGE /* Initialize our update handling */ -#ifndef DARLING InitializeOTATrustAsset(kOTABackgroundQueue); -#endif otapkiref->_ctKillSwitch = InitializeKillSwitch((__bridge NSString*)kOTAPKIKillSwitchCT); -#ifndef DARLING + otapkiref->_nonTlsCtKillSwitch = InitializeKillSwitch((__bridge NSString*)kOTAPKIKillSwitchNonTLSCT); InitializeOTASecExperimentAsset(kOTABackgroundQueue); -#endif #else // TARGET_OS_BRIDGE otapkiref->_ctKillSwitch = true; // bridgeOS never enforces CT + otapkiref->_nonTlsCtKillSwitch = true; #endif // TARGET_OS_BRIDGE return otapkiref; @@ -1742,6 +1765,8 @@ void UpdateKillSwitch(NSString *key, bool value) { dispatch_sync(kOTAQueue, ^{ if ([key isEqualToString:(__bridge NSString*)kOTAPKIKillSwitchCT]) { kCurrentOTAPKIRef->_ctKillSwitch = value; + } else if ([key isEqualToString:(__bridge NSString*)kOTAPKIKillSwitchNonTLSCT]) { + kCurrentOTAPKIRef->_nonTlsCtKillSwitch = value; } }); } @@ -1753,6 +1778,7 @@ static BOOL UpdateFromAsset(NSURL *localURL, NSNumber *asset_version, NSError ** return NO; } __block NSArray *newTrustedCTLogs = NULL; + __block NSArray *newNonTlsTrustedCTLogs = NULL; __block uint64_t version = [asset_version unsignedLongLongValue]; __block NSDictionary *newAnalyticsSamplingRates = NULL; __block NSArray *newAppleCAs = NULL; @@ -1766,6 +1792,15 @@ static BOOL UpdateFromAsset(NSURL *localURL, NSNumber *asset_version, NSError ** return NO; } + NSURL *nonTLSTrustedCTLogsFileLoc = [NSURL URLWithString:kOTATrustTrustedCTLogsNonTLSFilename + relativeToURL:localURL]; + newNonTlsTrustedCTLogs = [NSArray arrayWithContentsOfURL:nonTLSTrustedCTLogsFileLoc error:error]; + if (!newNonTlsTrustedCTLogs) { + secerror("OTATrust: unable to create TrustedCTLogs_nonTLS from asset file: %@", error ? *error: nil); + LogRemotely(OTATrustLogLevelError, error); + return NO; + } + NSURL *AnalyticsSamplingRatesFileLoc = [NSURL URLWithString:kOTATrustAnalyticsSamplingRatesFilename relativeToURL:localURL]; newAnalyticsSamplingRates = [NSDictionary dictionaryWithContentsOfURL:AnalyticsSamplingRatesFileLoc error:error]; @@ -1788,14 +1823,21 @@ static BOOL UpdateFromAsset(NSURL *localURL, NSNumber *asset_version, NSError ** dispatch_sync(kOTAQueue, ^{ secnotice("OTATrust", "updating asset version from %llu to %llu", kCurrentOTAPKIRef->_assetVersion, version); CFRetainAssign(kCurrentOTAPKIRef->_trustedCTLogs, (__bridge CFDictionaryRef)ConvertTrustedCTLogsArrayToDictionary(newTrustedCTLogs)); + CFRetainAssign(kCurrentOTAPKIRef->_nonTlsTrustedCTLogs, (__bridge CFDictionaryRef)ConvertTrustedCTLogsArrayToDictionary(newNonTlsTrustedCTLogs)); CFRetainAssign(kCurrentOTAPKIRef->_eventSamplingRates, (__bridge CFDictionaryRef)newAnalyticsSamplingRates); CFRetainAssign(kCurrentOTAPKIRef->_appleCAs, (__bridge CFArrayRef)newAppleCAs); kCurrentOTAPKIRef->_assetVersion = version; }); - /* Write the data to disk (so that we don't have to re-download the asset on re-launch) */ - DeleteAssetFromDisk(); + /* Reset the current files, version, and checkin so that in the case of write failures, we'll re-try + * to update the data. We don't call DeleteAssetFromDisk() here to preserve any kill switches. */ + DeleteOldAssetData(); + UpdateOTAContext(@(0), nil); + UpdateOTAContextOnDisk(kOTATrustLastCheckInKey, [NSDate dateWithTimeIntervalSince1970:0], nil); + + /* Write the data to disk (so that we don't have to re-download the asset on re-launch). */ if (CopyFileToDisk(kOTATrustTrustedCTLogsFilename, TrustedCTLogsFileLoc, error) && + CopyFileToDisk(kOTATrustTrustedCTLogsNonTLSFilename, nonTLSTrustedCTLogsFileLoc, error) && CopyFileToDisk(kOTATrustAnalyticsSamplingRatesFilename, AnalyticsSamplingRatesFileLoc, error) && CopyFileToDisk(kOTATrustAppleCertifcateAuthoritiesFilename, AppleCAsFileLoc, error) && UpdateOTAContext(asset_version, error)) { // Set version and check-in time last (after success) @@ -1920,6 +1962,23 @@ CFDictionaryRef SecOTAPKICopyTrustedCTLogs(SecOTAPKIRef otapkiRef) { return result; } +CFDictionaryRef SecOTAPKICopyNonTlsTrustedCTLogs(SecOTAPKIRef otapkiRef) { + CFDictionaryRef result = NULL; + if (NULL == otapkiRef) { + return result; + } + +#if !TARGET_OS_BRIDGE + /* Trigger periodic background MA checks in system trustd + * We also check on trustd launch and listen for notifications. */ + TriggerPeriodicOTATrustAssetChecks(kOTABackgroundQueue); +#endif + + result = otapkiRef->_nonTlsTrustedCTLogs; + CFRetainSafe(result); + return result; +} + CFURLRef SecOTAPKICopyPinningList(SecOTAPKIRef otapkiRef) { if (NULL == otapkiRef) { return NULL; @@ -2084,7 +2143,7 @@ NSNumber *SecOTAPKIGetSamplingRateForEvent(SecOTAPKIRef otapkiRef, NSString *eve if (otapkiRef->_eventSamplingRates) { CFTypeRef value = CFDictionaryGetValue(otapkiRef->_eventSamplingRates, (__bridge CFStringRef)eventName); - if (isNumberOfType(value, kCFNumberSInt64Type)) { + if (isNumberOfType(value, kCFNumberSInt64Type) || isNumberOfType(value, kCFNumberSInt32Type)) { return (__bridge NSNumber *)value; } } @@ -2111,6 +2170,8 @@ bool SecOTAPKIKillSwitchEnabled(SecOTAPKIRef otapkiRef, CFStringRef key) { } if (CFEqualSafe(key, kOTAPKIKillSwitchCT)) { return otapkiRef->_ctKillSwitch; + } else if (CFEqualSafe(key, kOTAPKIKillSwitchNonTLSCT)) { + return otapkiRef->_nonTlsCtKillSwitch; } return false; } @@ -2170,14 +2231,24 @@ CFDictionaryRef SecOTAPKICopyCTLogForKeyID(CFDataRef keyID, CFErrorRef* error) { return NULL; } - CFDictionaryRef trustedLogs = SecOTAPKICopyTrustedCTLogs(otapkiref); + /* Get the log lists */ + CFDictionaryRef trustedTlsLogs = SecOTAPKICopyTrustedCTLogs(otapkiref); + CFDictionaryRef trustedNonTlsLogs = SecOTAPKICopyNonTlsTrustedCTLogs(otapkiref); CFReleaseNull(otapkiref); - if (!trustedLogs) { + if (!trustedTlsLogs || !trustedNonTlsLogs) { + CFReleaseNull(trustedTlsLogs); + CFReleaseNull(trustedNonTlsLogs); return NULL; } - CFDictionaryRef logDict = CFDictionaryGetValue(trustedLogs, keyID); + + /* Find the log */ + CFDictionaryRef logDict = CFDictionaryGetValue(trustedTlsLogs, keyID); + if (!logDict) { + logDict = CFDictionaryGetValue(trustedNonTlsLogs, keyID); + } CFRetainSafe(logDict); - CFReleaseSafe(trustedLogs); + CFReleaseNull(trustedTlsLogs); + CFReleaseNull(trustedNonTlsLogs); return logDict; } diff --git a/trust/trustd/SecCAIssuerCache.c b/trust/trustd/SecCAIssuerCache.c index 70175d40..bb232228 100644 --- a/trust/trustd/SecCAIssuerCache.c +++ b/trust/trustd/SecCAIssuerCache.c @@ -28,6 +28,7 @@ #include "trust/trustd/SecCAIssuerCache.h" #include "trust/trustd/SecTrustLoggingServer.h" +#include "trust/trustd/trustdFileLocations.h" #include #include #include @@ -46,7 +47,6 @@ #include "utilities/iOSforOSX.h" #include -#include #include static const char expireSQL[] = "DELETE FROM issuers WHERE expires #include "trust/trustd/SecTrustServer.h" #include "trust/trustd/TrustURLSessionDelegate.h" +#include "trust/trustd/TrustURLSessionCache.h" #include #include @@ -47,11 +48,16 @@ typedef void (*CompletionHandler)(void *context, CFArrayRef parents); -/* CA Issuer lookup code. */ @interface CAIssuerDelegate: TrustURLSessionDelegate +@end + +@interface CAIssuerContext : TrustURLSessionContext @property (assign) CompletionHandler callback; @end +@implementation CAIssuerContext +@end + static NSArray *certificatesFromData(NSData *data) { /* RFC5280 4.2.2.1: "accessLocation MUST be a uniformResourceIdentifier and the URI @@ -85,12 +91,12 @@ static NSArray *certificatesFromData(NSData *data) { } @implementation CAIssuerDelegate -- (BOOL)fetchNext:(NSURLSession *)session { - SecPathBuilderRef builder = (SecPathBuilderRef)self.context; +- (BOOL)fetchNext:(NSURLSession *)session context:(TrustURLSessionContext *)urlContext { + SecPathBuilderRef builder = (SecPathBuilderRef)urlContext.context; TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(builder); BOOL result = false; - if (!(result = [super fetchNext:session]) && analytics) { + if (!(result = [super fetchNext:session context:urlContext]) && analytics) { analytics->ca_issuer_fetches++; } return result; @@ -100,9 +106,17 @@ static NSArray *certificatesFromData(NSData *data) { /* call the superclass's method to set taskTime and expiration */ [super URLSession:session task:task didCompleteWithError:error]; - __block SecPathBuilderRef builder =(SecPathBuilderRef)self.context; + NSUUID *taskId = [task.originalRequest taskId]; + CAIssuerContext *urlContext = (CAIssuerContext *)[self contextForTask:taskId]; + if (!urlContext) { + secerror("failed to find context for %@", taskId); + return; + } + + __block SecPathBuilderRef builder =(SecPathBuilderRef)urlContext.context; if (!builder) { /* We already returned to the PathBuilder state machine. */ + [self removeTask:taskId]; return; } @@ -114,9 +128,9 @@ static NSArray *certificatesFromData(NSData *data) { if (analytics) { analytics->ca_issuer_fetch_failed++; } - } else if (self.response) { + } else if (urlContext.response) { /* Get the parent cert from the data */ - parents = certificatesFromData(self.response); + parents = certificatesFromData(urlContext.response); if (analytics && !parents) { analytics->ca_issuer_unsupported_data = true; } else if (analytics && [parents count] > 1) { @@ -127,29 +141,37 @@ static NSArray *certificatesFromData(NSData *data) { if (parents) { /* Found some parents, add to cache, close session, and return to SecPathBuilder */ secdebug("caissuer", "found parents for %@", task.originalRequest.URL); - SecCAIssuerCacheAddCertificates((__bridge CFArrayRef)parents, (__bridge CFURLRef)task.originalRequest.URL, self.expiration); - self.context = nil; // set the context to NULL before we call back because the callback may free the builder - [session invalidateAndCancel]; + SecCAIssuerCacheAddCertificates((__bridge CFArrayRef)parents, (__bridge CFURLRef)task.originalRequest.URL, urlContext.expiration); + urlContext.context = nil; // set the context to NULL before we call back because the callback may free the builder dispatch_async(SecPathBuilderGetQueue(builder), ^{ - self.callback(builder, (__bridge CFArrayRef)parents); + urlContext.callback(builder, (__bridge CFArrayRef)parents); }); } else { secdebug("caissuer", "no parents for %@", task.originalRequest.URL); - if ([self fetchNext:session]) { // Try the next CAIssuer URI - /* no fetch scheduled, close this session and jump back into the state machine on the builder's queue */ + if ([self fetchNext:session context:urlContext]) { // Try the next CAIssuer URI + /* no fetch scheduled, jump back into the state machine on the builder's queue */ secdebug("caissuer", "no more fetches. returning to builder"); - self.context = nil; // set the context to NULL before we call back because the callback may free the builder - [session invalidateAndCancel]; + urlContext.context = nil; // set the context to NULL before we call back because the callback may free the builder dispatch_async(SecPathBuilderGetQueue(builder), ^{ - self.callback(builder, NULL); + urlContext.callback(builder, NULL); }); } } + // We've either kicked off a new task or returned to the builder, so we're done with this task. + [self removeTask:taskId]; } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)taskMetrics { secdebug("caissuer", "got metrics with task interval %f", taskMetrics.taskInterval.duration); - SecPathBuilderRef builder =(SecPathBuilderRef)self.context; + + NSUUID *taskId = [task.originalRequest taskId]; + TrustURLSessionContext *urlContext = [self contextForTask:taskId]; + if (!urlContext) { + secerror("failed to find context for %@", taskId); + return; + } + + SecPathBuilderRef builder =(SecPathBuilderRef)urlContext.context; if (builder) { TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(builder); if (analytics) { @@ -236,32 +258,19 @@ bool SecCAIssuerCopyParents(SecCertificateRef certificate, void *context, void ( return true; } - NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; - config.timeoutIntervalForResource = TrustURLSessionGetResourceTimeout(); - config.HTTPAdditionalHeaders = @{@"User-Agent" : @"com.apple.trustd/2.0"}; + static TrustURLSessionCache *sessionCache = NULL; + static CAIssuerDelegate *delegate = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + delegate = [[CAIssuerDelegate alloc] init]; + sessionCache = [[TrustURLSessionCache alloc] initWithDelegate:delegate]; + }); NSData *auditToken = CFBridgingRelease(SecPathBuilderCopyClientAuditToken(builder)); - if (auditToken) { - config._sourceApplicationAuditTokenData = auditToken; - } - - CAIssuerDelegate *delegate = [[CAIssuerDelegate alloc] init]; - delegate.context = context; - delegate.callback = callback; - delegate.URIs = nsIssuers; - delegate.URIix = 0; - - NSOperationQueue *queue = [[NSOperationQueue alloc] init]; - - NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:delegate delegateQueue:queue]; - secdebug("caissuer", "created URLSession for %@", certificate); - - bool result = false; - if ((result = [delegate fetchNext:session])) { - /* no fetch scheduled, close the session */ - [session invalidateAndCancel]; - } - return result; + NSURLSession *session = [sessionCache sessionForAuditToken:auditToken]; + CAIssuerContext *urlContext = [[CAIssuerContext alloc] initWithContext:context uris:nsIssuers]; + urlContext.callback = callback; + return [delegate fetchNext:session context:urlContext]; } } diff --git a/trust/trustd/SecCertificateServer.c b/trust/trustd/SecCertificateServer.c index 6ddca031..012ac180 100644 --- a/trust/trustd/SecCertificateServer.c +++ b/trust/trustd/SecCertificateServer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2017-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,7 @@ #include "trust/trustd/SecPolicyServer.h" #include "trust/trustd/SecCertificateServer.h" #include "trust/trustd/SecRevocationServer.h" +#include "trust/trustd/SecTrustStoreServer.h" // MARK: - // MARK: SecCertificateVC @@ -254,6 +256,11 @@ struct SecCertificatePathVC { bool is_allowlisted; bool hasStrongHashes; + /* revocationCAIndex contains the index of the last CA with a SPKI-based + * revocation match, or -1 (kCFNotFound) if no CA match was found. + * A value of 0 means the path has not yet been checked for a match. */ + CFIndex revocationCAIndex; + void * rvcs; CFIndex rvcCount; @@ -718,6 +725,28 @@ bool SecCertificatePathVCIsValid(SecCertificatePathVCRef certificatePath, CFAbso return result; } +CFAbsoluteTime SecCertificatePathVCGetMaximumNotBefore(SecCertificatePathVCRef certificatePath) { + __block CFAbsoluteTime notBefore = -DBL_MAX; + SecCertificatePathVCForEachCertificate(certificatePath, ^(SecCertificateRef certificate, bool *stop) { + CFAbsoluteTime certNotBefore = SecCertificateNotValidBefore(certificate); + if (certNotBefore > notBefore) { + notBefore = certNotBefore; + } + }); + return notBefore; +} + +CFAbsoluteTime SecCertificatePathVCGetMinimumNotAfter(SecCertificatePathVCRef certificatePath) { + __block CFAbsoluteTime notAfter = DBL_MAX; + SecCertificatePathVCForEachCertificate(certificatePath, ^(SecCertificateRef certificate, bool *stop) { + CFAbsoluteTime certNotAfter = SecCertificateNotValidAfter(certificate); + if (certNotAfter < notAfter) { + notAfter = certNotAfter; + } + }); + return notAfter; +} + bool SecCertificatePathVCHasWeakHash(SecCertificatePathVCRef certificatePath) { CFIndex ix, count = certificatePath->count; @@ -757,7 +786,7 @@ bool SecCertificatePathVCHasWeakKeySize(SecCertificatePathVCRef certificatePath) *stop = true; } }); - + errOut: CFReleaseSafe(keySizes); CFReleaseSafe(rsaSize); @@ -768,19 +797,19 @@ errOut: /* Return a score for this certificate chain. */ CFIndex SecCertificatePathVCScore(SecCertificatePathVCRef certificatePath, CFAbsoluteTime verifyTime) { CFIndex score = 0; - + /* Paths that don't verify score terribly.c */ if (certificatePath->lastVerifiedSigner != certificatePath->count - 1) { secdebug("trust", "lvs: %" PRIdCFIndex " count: %" PRIdCFIndex, certificatePath->lastVerifiedSigner, certificatePath->count); score -= 100000; } - + if (certificatePath->isAnchored) { /* Anchored paths for the win! */ score += 10000; } - + if (certificatePath->isSelfSigned && (certificatePath->selfIssued == certificatePath->count - 1)) { /* Chains that terminate in a self-signed certificate are preferred, even if they don't end in an anchor. */ @@ -791,19 +820,19 @@ CFIndex SecCertificatePathVCScore(SecCertificatePathVCRef certificatePath, CFAbs /* Longer chains are preferred when the chain doesn't end in a self-signed cert. */ score += 1 * certificatePath->count; } - + if (SecCertificatePathVCIsValid(certificatePath, verifyTime)) { score += 100; } - + if (!SecCertificatePathVCHasWeakHash(certificatePath)) { score += 10; } - + if (!SecCertificatePathVCHasWeakKeySize(certificatePath)) { score += 10; } - + return score; } @@ -891,6 +920,44 @@ CFAbsoluteTime SecCertificatePathVCGetEarliestNextUpdate(SecCertificatePathVCRef return enu; } +CFAbsoluteTime SecCertificatePathVCGetLatestThisUpdate(SecCertificatePathVCRef path) { + CFIndex certIX, certCount = path->count; + CFAbsoluteTime ltu = -DBL_MAX; + if (certCount <= 1 || !path->rvcs) { + return ltu; + } + + for (certIX = 0; certIX < path->rvcCount; ++certIX) { + SecRVCRef rvc = SecCertificatePathVCGetRVCAtIndex(path, certIX); + CFAbsoluteTime thisCertThisUpdate = SecRVCGetLatestThisUpdate(rvc); + if (thisCertThisUpdate > ltu) { + ltu = thisCertThisUpdate; + } + } + + secdebug("rvc", "revocation valid starting: %lg", ltu); + return ltu; +} + +bool SecCertificatePathVCRevocationCheckedAllCerts(SecCertificatePathVCRef path) { + CFIndex certIX, certCount = path->count; + if (certCount <= 1 || !path->rvcs) { + /* If there is only one certificate, it's the root, so revocation checking is irrelevant. */ + return false; + } + + for (certIX = 0; certIX < path->rvcCount - 1; ++certIX) { + SecRVCRef rvc = &((SecRVCRef)path->rvcs)[certIX]; + if (!SecRVCRevocationChecked(rvc)) { + secdebug("rvc", "revocation has not been checked for all certs (not checked for cert %ld)", certIX); + return false; + } + } + + secdebug("rvc", "revocation has been checked for all certs"); + return true; +} + void SecCertificatePathVCSetRevocationReasonForCertificateAtIndex(SecCertificatePathVCRef certificatePath, CFIndex ix, CFNumberRef revocationReason) { if (ix > certificatePath->count - 1) { return; } @@ -982,6 +1049,63 @@ void SecCertificatePathVCSetRequiresCT(SecCertificatePathVCRef certificatePath, certificatePath->requiresCT = requiresCT; } +static bool has_ca_additions_key(SecCertificatePathVCRef path, CFDictionaryRef ca_entry) { + bool result = false; + CFDataRef hash = CFDictionaryGetValue(ca_entry, kSecCARevocationSPKIHashKey); + if (!hash) { + return false; + } + /* only check issuing CAs and not the leaf */ + for (CFIndex certIX = 1; certIX < SecCertificatePathVCGetCount(path); certIX++) { + SecCertificateRef ca = SecCertificatePathVCGetCertificateAtIndex(path, certIX); + CFDataRef spkiHash = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(ca); + bool matched = CFEqualSafe(hash, spkiHash); + CFReleaseNull(spkiHash); + if (!matched) { + continue; + } + /* this SPKI is a match; remember highest index */ + if (certIX > path->revocationCAIndex) { + path->revocationCAIndex = certIX; + } + result = true; + } + return result; +} + +static void SecCertificatePathVCCheckCARevocationAdditions(SecCertificatePathVCRef path) { + CFDictionaryRef additions = _SecTrustStoreCopyCARevocationAdditions(NULL, NULL); + path->revocationCAIndex = kCFNotFound; + if (!additions) { + return; + } + + __block bool result = false; + CFArrayRef ca_list = CFDictionaryGetValue(additions, kSecCARevocationAdditionsKey); + if (ca_list) { + CFArrayForEach(ca_list, ^(const void *value) { + result = result || has_ca_additions_key(path, value); + }); + } + + if (result) { + secinfo("ocsp", "key-based CA revocation applies at index %lld", + (long long)path->revocationCAIndex); + } + + CFReleaseNull(additions); + return; +} + +CFIndex SecCertificatePathVCIndexOfCAWithRevocationAdditions(SecCertificatePathVCRef certificatePath) { + if (!certificatePath) { return kCFNotFound; } + if (0 == certificatePath->revocationCAIndex) { + /* we haven't checked this path yet, do it now */ + SecCertificatePathVCCheckCARevocationAdditions(certificatePath); + } + return certificatePath->revocationCAIndex; +} + CFAbsoluteTime SecCertificatePathVCIssuanceTime(SecCertificatePathVCRef certificatePath) { if (!certificatePath) { return 0; } return certificatePath->issuanceTime; diff --git a/trust/trustd/SecCertificateServer.h b/trust/trustd/SecCertificateServer.h index 91486de4..a0c15869 100644 --- a/trust/trustd/SecCertificateServer.h +++ b/trust/trustd/SecCertificateServer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2017-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -116,6 +116,9 @@ bool SecCertificatePathVCHasWeakHash(SecCertificatePathVCRef certificatePath); bool SecCertificatePathVCHasWeakKeySize(SecCertificatePathVCRef certificatePath); +CFAbsoluteTime SecCertificatePathVCGetMaximumNotBefore(SecCertificatePathVCRef certificatePath); +CFAbsoluteTime SecCertificatePathVCGetMinimumNotAfter(SecCertificatePathVCRef certificatePath); + /* Score */ CFIndex SecCertificatePathVCScore(SecCertificatePathVCRef certificatePath, CFAbsoluteTime verifyTime); @@ -128,7 +131,9 @@ void SecCertificatePathVCDeleteRVCs(SecCertificatePathVCRef path); bool SecCertificatePathVCIsRevocationDone(SecCertificatePathVCRef certificatePath); void SecCertificatePathVCAllocateRVCs(SecCertificatePathVCRef certificatePath, CFIndex certCount); CFAbsoluteTime SecCertificatePathVCGetEarliestNextUpdate(SecCertificatePathVCRef path); +CFAbsoluteTime SecCertificatePathVCGetLatestThisUpdate(SecCertificatePathVCRef path); void *SecCertificatePathVCGetRVCAtIndex(SecCertificatePathVCRef certificatePath, CFIndex ix); // Returns a SecRVCRef +bool SecCertificatePathVCRevocationCheckedAllCerts(SecCertificatePathVCRef path); bool SecCertificatePathVCIsRevocationRequiredForCertificateAtIndex(SecCertificatePathVCRef certificatePath, CFIndex ix); void SecCertificatePathVCSetRevocationRequiredForCertificateAtIndex(SecCertificatePathVCRef certificatePath, @@ -165,6 +170,12 @@ void SecCertificatePathVCSetRequiresCT(SecCertificatePathVCRef certificatePath, CFAbsoluteTime SecCertificatePathVCIssuanceTime(SecCertificatePathVCRef certificatePath); void SecCertificatePathVCSetIssuanceTime(SecCertificatePathVCRef certificatePath, CFAbsoluteTime issuanceTime); +/* CA Revocation Additions */ +/* Returns the index of the highest issuing CA which has matching key-based + * revocation additions in the given path, or kCFNotFound if none is found. + */ +CFIndex SecCertificatePathVCIndexOfCAWithRevocationAdditions(SecCertificatePathVCRef certificatePath); + /* Allowlist */ bool SecCertificatePathVCIsAllowlisted(SecCertificatePathVCRef certificatePath); void SecCertificatePathVCSetIsAllowlisted(SecCertificatePathVCRef certificatePath, bool isAllowlisted); diff --git a/trust/trustd/SecCertificateSource.c b/trust/trustd/SecCertificateSource.c index 1c7932e7..4919cfc2 100644 --- a/trust/trustd/SecCertificateSource.c +++ b/trust/trustd/SecCertificateSource.c @@ -416,8 +416,6 @@ struct SecCertificateSource _kSecSystemAnchorSource = { const SecCertificateSourceRef kSecSystemAnchorSource = &_kSecSystemAnchorSource; - -#if TARGET_OS_IPHONE // MARK: - // MARK: SecUserAnchorSource /******************************************************** @@ -434,12 +432,9 @@ static bool SecUserAnchorSourceCopyParents(SecCertificateSourceRef source, SecCe static CFArrayRef SecUserAnchorSourceCopyUsageConstraints(SecCertificateSourceRef source, SecCertificateRef certificate) { - CFDataRef digest = SecCertificateGetSHA1Digest(certificate); - if (!digest) - return NULL; CFArrayRef usageConstraints = NULL; bool ok = _SecTrustStoreCopyUsageConstraints(SecTrustStoreForDomain(kSecTrustStoreDomainUser), - digest, &usageConstraints, NULL); + certificate, &usageConstraints, NULL); if (ok) { return usageConstraints; } else { @@ -461,7 +456,6 @@ struct SecCertificateSource _kSecUserAnchorSource = { }; const SecCertificateSourceRef kSecUserAnchorSource = &_kSecUserAnchorSource; -#endif // MARK: - // MARK: SecMemoryCertificateSource @@ -629,30 +623,33 @@ const SecCertificateSourceRef kSecLegacyCertificateSource = &_kSecLegacyCertific static bool SecLegacyAnchorSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate, void *context, SecCertificateSourceParents callback) { CFMutableArrayRef anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFArrayRef parents = SecItemCopyParentCertificates_osx(certificate, NULL); CFArrayRef trusted = NULL; - if (parents == NULL) { + CFDataRef normalizedIssuer = SecCertificateCopyNormalizedIssuerSequence(certificate); + if (!normalizedIssuer) { goto finish; } + /* Get the custom anchors which have been trusted in the user and admin domains. * We don't need system domain roots here, since SecSystemAnchorSource provides those. */ OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted); if (status == errSecSuccess && trusted) { - CFIndex index, count = CFArrayGetCount(parents); + CFIndex index, count = CFArrayGetCount(trusted); for (index = 0; index < count; index++) { - SecCertificateRef parent = (SecCertificateRef)CFArrayGetValueAtIndex(parents, index); - if (parent && CFArrayContainsValue(trusted, CFRangeMake(0, CFArrayGetCount(trusted)), parent)) { - CFArrayAppendValue(anchors, parent); + SecCertificateRef potentialParent = (SecCertificateRef)CFArrayGetValueAtIndex(trusted, index); + CFDataRef normalizedSubject = SecCertificateCopyNormalizedSubjectSequence(potentialParent); + if (CFEqualSafe(normalizedIssuer, normalizedSubject)) { + CFArrayAppendValue(anchors, potentialParent); } + CFReleaseSafe(normalizedSubject); } } finish: callback(context, anchors); CFReleaseSafe(anchors); - CFReleaseSafe(parents); CFReleaseSafe(trusted); + CFReleaseSafe(normalizedIssuer); return true; } @@ -661,19 +658,19 @@ static CFArrayRef SecLegacyAnchorSourceCopyUsageConstraints(SecCertificateSource CFArrayRef result = NULL; CFArrayRef userTrustSettings = NULL, adminTrustSettings = NULL; - OSStatus status = SecTrustSettingsCopyTrustSettings(certificate, - kSecTrustSettingsDomainUser, - &userTrustSettings); - if ((status == errSecSuccess) && (userTrustSettings != NULL)) { - result = CFRetain(userTrustSettings); + OSStatus status = SecTrustSettingsCopyTrustSettings_Cached(certificate, + kSecTrustSettingsDomainAdmin, + &adminTrustSettings); + if ((status == errSecSuccess) && (adminTrustSettings != NULL)) { + /* admin trust settings overrule user trust settings (rdar://37052515) */ + return adminTrustSettings; } - status = SecTrustSettingsCopyTrustSettings(certificate, - kSecTrustSettingsDomainAdmin, - &adminTrustSettings); - /* user trust settings overrule admin trust settings */ - if ((status == errSecSuccess) && (adminTrustSettings != NULL) && (result == NULL)) { - result = CFRetain(adminTrustSettings); + status = SecTrustSettingsCopyTrustSettings_Cached(certificate, + kSecTrustSettingsDomainUser, + &userTrustSettings); + if (status == errSecSuccess) { + result = CFRetainSafe(userTrustSettings); } CFReleaseNull(userTrustSettings); @@ -686,31 +683,39 @@ static bool SecLegacyAnchorSourceContains(SecCertificateSourceRef source, if (certificate == NULL) { return false; } - CFArrayRef trusted = NULL; - bool result = false; - OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted); - if ((status == errSecSuccess) && (trusted != NULL)) { - CFIndex index, count = CFArrayGetCount(trusted); - for (index = 0; index < count; index++) { - SecCertificateRef anchor = (SecCertificateRef)CFRetainSafe(CFArrayGetValueAtIndex(trusted, index)); - if (anchor && (CFGetTypeID(anchor) != CFGetTypeID(certificate))) { - /* This should only happen if trustd and the Security framework are using different SecCertificate TypeIDs. + + if (SecTrustSettingsUserAdminDomainsContain(certificate)) { + return true; + } else { + CFArrayRef trusted = NULL; + bool result = false; + OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted); + if ((status == errSecSuccess) && (trusted != NULL)) { + if ((CFArrayGetCount(trusted) > 0) && CFGetTypeID(CFArrayGetValueAtIndex(trusted, 0)) != CFGetTypeID(certificate)) { + /* This fallback should only happen if trustd and the Security framework are using different SecCertificate TypeIDs. * This occurs in TrustTests where we rebuild SecCertificate.c for code coverage purposes, so we end up with * two registered SecCertificate types. So we'll make a SecCertificate of our type. */ - SecCertificateRef temp = SecCertificateCreateWithBytes(NULL, SecCertificateGetBytePtr(anchor), SecCertificateGetLength(anchor)); - CFAssignRetained(anchor, temp); - } - if (anchor && CFEqual(anchor, certificate)) { - result = true; - } - CFReleaseNull(anchor); - if (result) { - break; + CFIndex index, count = CFArrayGetCount(trusted); + for (index = 0; index < count; index++) { + SecCertificateRef anchor = (SecCertificateRef)CFRetainSafe(CFArrayGetValueAtIndex(trusted, index)); + if (anchor && (CFGetTypeID(anchor) != CFGetTypeID(certificate))) { + SecCertificateRef temp = SecCertificateCreateWithBytes(NULL, SecCertificateGetBytePtr(anchor), SecCertificateGetLength(anchor)); + CFAssignRetained(anchor, temp); + } + if (anchor && CFEqual(anchor, certificate)) { + result = true; + } + CFReleaseNull(anchor); + if (result) { + break; + } + } } + CFReleaseSafe(trusted); + return result; } } - CFReleaseSafe(trusted); - return result; + return false; } struct SecCertificateSource _kSecLegacyAnchorSource = { diff --git a/trust/trustd/SecCertificateSource.h b/trust/trustd/SecCertificateSource.h index c2c99907..b99b822a 100644 --- a/trust/trustd/SecCertificateSource.h +++ b/trust/trustd/SecCertificateSource.h @@ -78,10 +78,8 @@ void SecMemoryCertificateSourceDestroy(SecCertificateSourceRef source); /* SecSystemAnchorSource */ extern const SecCertificateSourceRef kSecSystemAnchorSource; -#if TARGET_OS_IPHONE /* SecUserAnchorSource */ extern const SecCertificateSourceRef kSecUserAnchorSource; -#endif /* SecCAIssuerCertificateSource */ extern const SecCertificateSourceRef kSecCAIssuerSource; diff --git a/trust/trustd/SecOCSPCache.c b/trust/trustd/SecOCSPCache.c index c16d9e21..3f3e8e58 100644 --- a/trust/trustd/SecOCSPCache.c +++ b/trust/trustd/SecOCSPCache.c @@ -29,6 +29,7 @@ #include #include "trust/trustd/SecOCSPCache.h" #include "trust/trustd/SecTrustLoggingServer.h" +#include "trust/trustd/trustdFileLocations.h" #include #include #include @@ -40,18 +41,20 @@ #include #include "utilities/SecCFWrappers.h" #include "utilities/SecDb.h" -#include "utilities/SecFileLocations.h" #include "utilities/iOSforOSX.h" +#include /* Note that lastUsed is actually time of insert because we don't refresh lastUsed on each SELECT. */ -#define flushSQL CFSTR("DELETE FROM responses") -#define expireSQL CFSTR("DELETE FROM responses WHERE expires? AND responseId=(SELECT responseId FROM ocsp WHERE " \ "issuerNameHash=? AND issuerPubKeyHash=? AND serialNum=? AND hashAlgorithm=?)" \ " ORDER BY expires DESC") +#define hasCertStatusSQL CFSTR("SELECT issuerNameHash FROM ocsp WHERE certStatus=0 LIMIT 1") +#define alterOCSPTableSQL CFSTR("ALTER TABLE ocsp ADD COLUMN certStatus INTEGER NOT NULL DEFAULT 255") /* CS_NotParsed */ #define kSecOCSPCacheFileName CFSTR("ocspcache.sqlite3") @@ -66,6 +71,38 @@ // MARK; - // MARK: SecOCSPCacheDb +static bool SecOCSPCacheDbUpdateTables(SecDbRef db) { + __block bool ok = true; + __block CFErrorRef localError = NULL; + + ok &= SecDbPerformWrite(db, &localError, ^(SecDbConnectionRef dbconn) { + ok &= SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &localError, ^(bool *commit) { + CFErrorRef readColumnError = NULL; + if (!SecDbWithSQL(dbconn, hasCertStatusSQL, &readColumnError, NULL) && CFErrorGetCode(readColumnError) == SQLITE_ERROR) { + ok &= SecDbWithSQL(dbconn, alterOCSPTableSQL, &localError, ^bool(sqlite3_stmt *stmt) { + ok = SecDbStep(dbconn, stmt, &localError, NULL); + return ok; + }); + *commit = ok; + } + CFReleaseSafe(readColumnError); + }); + }); + + if (!ok) { + secerror("OCSP table update failed: %@", localError); + CFIndex errCode = errSecInternalComponent; + if (localError) { + errCode = CFErrorGetCode(localError); + } + TrustdHealthAnalyticsLogErrorCodeForDatabase(TAOCSPCache, + TAOperationWrite, + TAFatalError, errCode); + } + CFReleaseSafe(localError); + return ok; +} + static SecDbRef SecOCSPCacheDbCreate(CFStringRef path) { return SecDbCreate(path, 0600, true, true, true, true, 1, ^bool (SecDbRef db, SecDbConnectionRef dbconn, bool didCreate, bool *callMeAgainForNextConnection, CFErrorRef *error) { @@ -81,7 +118,8 @@ static SecDbRef SecOCSPCacheDbCreate(CFStringRef path) { "issuerPubKeyHash BLOB NOT NULL," "serialNum BLOB NOT NULL," "hashAlgorithm BLOB NOT NULL," - "responseId INTEGER NOT NULL" + "responseId INTEGER NOT NULL," + "certStatus INTEGER NOT NULL DEFAULT 255" // CS_NotParsed ");" "CREATE INDEX iResponseId ON ocsp(responseId);" "CREATE INDEX iserialNum ON ocsp(serialNum);" @@ -124,14 +162,12 @@ struct __SecOCSPCache { SecDbRef db; }; -static dispatch_once_t kSecOCSPCacheOnce; -static SecOCSPCacheRef kSecOCSPCache = NULL; - static SecOCSPCacheRef SecOCSPCacheCreate(CFStringRef db_name) { SecOCSPCacheRef this; require(this = (SecOCSPCacheRef)malloc(sizeof(struct __SecOCSPCache)), errOut); require(this->db = SecOCSPCacheDbCreate(db_name), errOut); + require(SecOCSPCacheDbUpdateTables(this->db), errOut); return this; @@ -144,17 +180,9 @@ errOut: return NULL; } -static CFStringRef SecOCSPCacheCopyPath(void) { +CFStringRef SecOCSPCacheCopyPath(void) { CFStringRef ocspRelPath = kSecOCSPCacheFileName; -#if TARGET_OS_IPHONE - CFURLRef ocspURL = SecCopyURLForFileInKeychainDirectory(ocspRelPath); - if (!ocspURL) { - ocspURL = SecCopyURLForFileInUserCacheDirectory(ocspRelPath); - } -#else - /* macOS caches should be in user cache dir */ - CFURLRef ocspURL = SecCopyURLForFileInUserCacheDirectory(ocspRelPath); -#endif + CFURLRef ocspURL = SecCopyURLForFileInPrivateUserTrustdDirectory(ocspRelPath); CFStringRef ocspPath = NULL; if (ocspURL) { ocspPath = CFURLCopyFileSystemPath(ocspURL, kCFURLPOSIXPathStyle); @@ -163,17 +191,57 @@ static CFStringRef SecOCSPCacheCopyPath(void) { return ocspPath; } +static SecOCSPCacheRef kSecOCSPCache = NULL; +static os_unfair_lock cacheLock = OS_UNFAIR_LOCK_INIT; + +void SecOCSPCacheCloseDB(void) { + os_unfair_lock_lock(&cacheLock); + if (kSecOCSPCache) { + // Release the DB + SecDbReleaseAllConnections(kSecOCSPCache->db); + CFReleaseSafe(kSecOCSPCache->db); + + // free the cache struct + free(kSecOCSPCache); + kSecOCSPCache = NULL; + } + os_unfair_lock_unlock(&cacheLock); +} + +void SecOCSPCacheDeleteCache(void) { + os_unfair_lock_lock(&cacheLock); + if (kSecOCSPCache) { + // Release the DB + SecDbReleaseAllConnections(kSecOCSPCache->db); + CFReleaseSafe(kSecOCSPCache->db); + + // free the cache struct + free(kSecOCSPCache); + kSecOCSPCache = NULL; + } + + // remove the file + CFStringRef path = SecOCSPCacheCopyPath(); + CFStringPerformWithCStringAndLength(path, ^(const char *utf8Str, size_t utf8Length) { + remove(utf8Str); + }); + CFReleaseSafe(path); + os_unfair_lock_unlock(&cacheLock); +} + static void SecOCSPCacheWith(void(^cacheJob)(SecOCSPCacheRef cache)) { - dispatch_once(&kSecOCSPCacheOnce, ^{ + os_unfair_lock_lock(&cacheLock); + if (!kSecOCSPCache) { CFStringRef dbPath = SecOCSPCacheCopyPath(); if (dbPath) { kSecOCSPCache = SecOCSPCacheCreate(dbPath); CFRelease(dbPath); } - }); - // Do pre job run work here (cancel idle timers etc.) - cacheJob(kSecOCSPCache); - // Do post job run work here (gc timer, etc.) + } + if (kSecOCSPCache) { + cacheJob(kSecOCSPCache); + } + os_unfair_lock_unlock(&cacheLock); } static bool _SecOCSPCacheExpireWithTransaction(SecDbConnectionRef dbconn, CFAbsoluteTime now, CFErrorRef *error) { @@ -259,6 +327,7 @@ static void _SecOCSPCacheReplaceResponse(SecOCSPCacheRef this, *responses; ++responses) { SecAsn1OCSPSingleResponse *resp = *responses; SecAsn1OCSPCertID *certId = &resp->certID; + SecAsn1OCSPCertStatusTag certStatus = (SecAsn1OCSPCertStatusTag)(resp->certStatus.Data[0] & SEC_ASN1_TAGNUM_MASK); ok &= SecDbBindBlob(insertLink, 1, certId->algId.algorithm.Data, certId->algId.algorithm.Length, @@ -276,6 +345,7 @@ static void _SecOCSPCacheReplaceResponse(SecOCSPCacheRef this, certId->serialNumber.Length, SQLITE_TRANSIENT, &localError); ok &= SecDbBindInt64(insertLink, 5, responseId, &localError); + ok &= SecDbBindInt(insertLink, 6, certStatus, &localError); /* Execute the insert statement. */ ok &= SecDbStep(dbconn, insertLink, &localError, NULL); @@ -328,42 +398,34 @@ static SecOCSPResponseRef _SecOCSPCacheCopyMatching(SecOCSPCacheRef this, CFDataRef issuerPubKeyHash = SecDigestCreate(kCFAllocatorDefault, &algorithm, NULL, publicKey->data, publicKey->length); - if (issuerNameHash && issuerPubKeyHash && ok) ok &= SecDbWithSQL(dbconn, selectResponseSQL, &localError, ^bool(sqlite3_stmt *selectResponse) { - /* Now we have the serial, algorithm, issuerNameHash and - issuerPubKeyHash so let's lookup the db entry. */ - ok &= SecDbBindDouble(selectResponse, 1, minInsertTime, &localError); - ok &= SecDbBindBlob(selectResponse, 2, CFDataGetBytePtr(issuerNameHash), - CFDataGetLength(issuerNameHash), SQLITE_TRANSIENT, &localError); - ok &= SecDbBindBlob(selectResponse, 3, CFDataGetBytePtr(issuerPubKeyHash), - CFDataGetLength(issuerPubKeyHash), SQLITE_TRANSIENT, &localError); - ok &= SecDbBindBlob(selectResponse, 4, CFDataGetBytePtr(serial), - CFDataGetLength(serial), SQLITE_TRANSIENT, &localError); - ok &= SecDbBindBlob(selectResponse, 5, algorithm.Data, - algorithm.Length, SQLITE_TRANSIENT, &localError); - ok &= SecDbStep(dbconn, selectResponse, &localError, ^(bool *stopResponse) { - /* Found an entry! */ - secdebug("ocspcache", "found cached response"); - CFDataRef resp = CFDataCreate(kCFAllocatorDefault, - sqlite3_column_blob(selectResponse, 0), - sqlite3_column_bytes(selectResponse, 0)); - sqlite3_int64 responseID = sqlite3_column_int64(selectResponse, 1); - if (resp) { - SecOCSPResponseRef new_response = SecOCSPResponseCreateWithID(resp, responseID); - if (response) { - if (SecOCSPResponseProducedAt(response) < SecOCSPResponseProducedAt(new_response)) { - SecOCSPResponseFinalize(response); - response = new_response; - } else { - SecOCSPResponseFinalize(new_response); - } - } else { - response = new_response; + if (issuerNameHash && issuerPubKeyHash && ok) { + ok &= SecDbWithSQL(dbconn, selectResponseSQL, &localError, ^bool(sqlite3_stmt *selectResponse) { + /* Now we have the serial, algorithm, issuerNameHash and + issuerPubKeyHash so let's lookup the db entry. */ + ok &= SecDbBindDouble(selectResponse, 1, minInsertTime, &localError); + ok &= SecDbBindBlob(selectResponse, 2, CFDataGetBytePtr(issuerNameHash), + CFDataGetLength(issuerNameHash), SQLITE_TRANSIENT, &localError); + ok &= SecDbBindBlob(selectResponse, 3, CFDataGetBytePtr(issuerPubKeyHash), + CFDataGetLength(issuerPubKeyHash), SQLITE_TRANSIENT, &localError); + ok &= SecDbBindBlob(selectResponse, 4, CFDataGetBytePtr(serial), + CFDataGetLength(serial), SQLITE_TRANSIENT, &localError); + ok &= SecDbBindBlob(selectResponse, 5, algorithm.Data, + algorithm.Length, SQLITE_TRANSIENT, &localError); + ok &= SecDbStep(dbconn, selectResponse, &localError, ^(bool *stopResponse) { + /* Found an entry! */ + secdebug("ocspcache", "found cached response"); + CFDataRef resp = CFDataCreate(kCFAllocatorDefault, + sqlite3_column_blob(selectResponse, 0), + sqlite3_column_bytes(selectResponse, 0)); + sqlite3_int64 responseID = sqlite3_column_int64(selectResponse, 1); + if (resp) { + response = SecOCSPResponseCreateWithID(resp, responseID); + CFRelease(resp); } - CFRelease(resp); - } + }); + return ok; }); - return ok; - }); + } CFReleaseSafe(issuerNameHash); CFReleaseSafe(issuerPubKeyHash); @@ -408,6 +470,22 @@ static bool _SecOCSPCacheFlush(SecOCSPCacheRef cache, CFErrorRef *error) { return ok; } +static bool _SecOCSPCacheDeleteContent(SecOCSPCacheRef cache, CFErrorRef *error) { + __block CFErrorRef localError = NULL; + __block bool ok = true; + + ok &= SecDbPerformWrite(cache->db, &localError, ^(SecDbConnectionRef dbconn) { + ok &= SecDbExec(dbconn, deleteAllSQL, &localError); + }); + if (!ok || localError) { + TrustdHealthAnalyticsLogErrorCodeForDatabase(TAOCSPCache, TAOperationWrite, TAFatalError, + localError ? CFErrorGetCode(localError) : errSecInternalComponent); + } + (void) CFErrorPropagate(localError, error); + + return ok; +} + /* Public API */ @@ -443,3 +521,11 @@ bool SecOCSPCacheFlush(CFErrorRef *error) { }); return result; } + +bool SecOCSPCacheDeleteContent(CFErrorRef *error) { + __block bool result = false; + SecOCSPCacheWith(^(SecOCSPCacheRef cache) { + result = _SecOCSPCacheDeleteContent(cache, error); + }); + return result; +} diff --git a/trust/trustd/SecOCSPCache.h b/trust/trustd/SecOCSPCache.h index 6fef3f36..7537c1c9 100644 --- a/trust/trustd/SecOCSPCache.h +++ b/trust/trustd/SecOCSPCache.h @@ -37,7 +37,6 @@ __BEGIN_DECLS - void SecOCSPCacheReplaceResponse(SecOCSPResponseRef old_response, SecOCSPResponseRef response, CFURLRef localResponderURI, CFAbsoluteTime verifyTime); @@ -49,184 +48,12 @@ SecOCSPResponseRef SecOCSPCacheCopyMatchingWithMinInsertTime(SecOCSPRequestRef r bool SecOCSPCacheFlush(CFErrorRef *error); +/* for testing purposes only */ +bool SecOCSPCacheDeleteContent(CFErrorRef *error); +void SecOCSPCacheDeleteCache(void); +void SecOCSPCacheCloseDB(void); +CFStringRef SecOCSPCacheCopyPath(void); + __END_DECLS #endif /* _SECURITY_SECOCSPCACHE_H_ */ - -#if 0 -/* -Experation policy assumptions: -- We never check revocation status of anchors, whether they be system anchors, - passed in anchors or anchors hardcoded in a policy. -- Revocation information is cached for positive reponses for a limited time. -- Revocation information can be cached for negative reponses for an unlimited time. -- Revocation information need never be kept around after the certificate has expired (unless we still check after the cert has expired like we were talking about for EERI). -- Revocation information records that are used and still valid should be kept longer. -- We can set an upper limit in number of records (or certificates) in the cache. -- We can set an upper limit on total space consumed by the cache. -Questions: -- Remember bad server responses too? some ocsp responders required signed requests which we don't support, so we could consider caching the 6 (Not Authorized or something) response. - -Data needed per type of revocation record to implement this policy. - -Caching policy: -- Deleting cache should not be user option. -- Cache should surrvive backups. -- Negative caching as long as possible. - -CRL certificate stati: -unspecified, keyCompromise, cACompromise, -affiliationChanged, superseded, cessationOfOperation, -certificateHold, removeFromCRL, privilegeWithdrawn, -aACompromise, the special value UNREVOKED, or the special -value UNDETERMINED. This variable is initialized to the -special value UNREVOKED. - -CRL Timestamp values: -- thisUpdate -- nextUpdate (optional but not really 5280 says CAs must provide it even though ASN.1 is optional) -(no producedAt in CRLs, that's what thisUpdate is by definition it seems). - - -OCSP Timestamp values: - thisUpdate = May 1, 2005 01:00:00 GMT - nextUpdate = May 3, 2005 01:00:00 GMT (optional abscence means update available any time) - productedAt = May 1, 2005 01:00:00 GMT - -PER CERTIFICATE RETURN in INFO - -Revocation object used: OCSP Response, mapping from -reasons-> (CRL + most current delta CRL), Error Object (with status code). - -- good - -- revoked - -- unknown - -other exceptions (unsigned responses): - -- malformedRequest - -- internalError - -- tryLater - -- sigRequired - -- unauthorized (5019 The response "unauthorized" is returned in cases where the client - is not authorized to make this query to this server or the server - is not capable of responding authoritatively. (Expired certs might get this answer too)) - - -CRL signer chain rules: -1) Must use same anchor as cert itself. -This implies that we can only cache the validity of a leaf or intermediate certificate for CRL checking based on the mapping: -(certificate, path anchor, use_deltas) -> Revocation_status (unspecified, keyCompromise, cACompromise, -affiliationChanged, superseded, cessationOfOperation,certificateHold, removeFromCRL, privilegeWithdrawn,aACompromise, UNREVOKED, UNDETERMINED). - -OCSP signer chain rules: -(Wikipedia confirmed in rfc): The key that signs a response need not be the same key that signed the certificate. The certificate's issuer may delegate another authority to be the OCSP responder. In this case, the responder's certificate (the one that is used to sign the response) must be issued by the issuer of the certificate in question, and must include a certain extension that marks it as an OCSP signing authority (more precisely, an extended key usage extension with the OID {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) keyPurpose(3) ocspSigning(9)}) - -rfc text of the wikipedia: Therefore, a certificate's issuer MUST either sign the OCSP - responses itself or it MUST explicitly designate this authority to - another entity. OCSP signing delegation SHALL be designated by the - inclusion of id-kp-OCSPSigning in an extendedKeyUsage certificate - extension included in the OCSP response signer's certificate. This - certificate MUST be issued directly by the CA that issued the - certificate in question. - -rfc: If ocsp signing cert has id-pkix-ocsp-nocheck extension we don't check it's revocation status. - -(certificate, direct issuer certificate) -> Revocation_status good (UNREVOKED) revoked revocationTime, CRLReason (unspecified, keyCompromise, cACompromise,affiliationChanged, superseded, cessationOfOperation,certificateHold, removeFromCRL, privilegeWithdrawn,aACompromise) unknown (UNDETERMINED). - -ocsp CertID ::= SEQUENCE { - hashAlgorithm AlgorithmIdentifier, - issuerNameHash OCTET STRING, -- Hash of Issuer's DN - issuerKeyHash OCTET STRING, -- Hash of Issuers public key - serialNumber CertificateSerialNumber } -) - -In order to accomadate the responder using a different hashAlgorithm than we used in the request we need to recalc these from the cert itself. - -If all we have is a list of ocspresponses without knowing where they came from, we have to calculate the hashes of our issuerName and issuerKey for each hashAlgorithm we have cached ocsp responses for (optionally after limiting our candidates to those with matching serialNumbers first). - -SELECT from ocsp_cache hashAlgorithm WHERE serialNumber = - -for hix = 0 hix < hashAlgorithms.count - ALG(hix).id = hashAlgorithms(hix) - -SELECT from ocsp_cache response WHERE serialNumber = hashAlgorithm = ALG(hix).id issuerNameHash = ALG(hix).hash(issuer) issuerKeyHash = ALG(hix).hash(key) - - - - - - -Notes for Matt: -- ttl in amfi cache (to force recheck when ocsp response is invalid)? -- Periodic check before launch to remove in band waiting for ocsp response? - -Notes on Nonces in ocsp request and responses. Only ask for nonce if we think server supports it (no way to know today). Fall back on time based validity checking if reponse has no nonce, even if we asked for one - -Note on CRL checking and experation and retries of OCSP checking. -Clients MAY attempt to retrieve the CRL if no - OCSPResponse is received from the responder after a locally - configured timeout and number of retries.. - - - -CRL/OCSP cache design idea: - -revocation status table: - -rowid certhash issuer-rowid lastUsed thisUpdate producedAt nextUpdate revocationTime revocationStatus - -cacheAddOCSP(path, index_of_cert_resp_is_for, ocspResp) -cacheAddCRLStatus(path, index_of_cert_in_path, nextUpdate, revocationTime, revocationStatus) -(revocationTime, revocationStatus) = cacheLookupStatus(path, ix) - -Return a list of parent certificate hashes for the current leaf. If a result is returned, we have a candiate path leading up to an anchor, for which we already trust the signature in the chain and revocation information has been checked. - -CFArrayRef cacheSuggestParentsHashesFor(cert) - -for crl based status root must match root of path. For ocsp status issuer must match issuer of leaf in path - -presence in the cache means cert chain leading to an anchor is valid, and signed properly and trusted by the ocsp or crl policy, revocation status for cert is valid until the time indicated by nextUpdate. Cert chain itself may or may not be valid but that's checked by the policy engine. - -If a chain isn't properly signed or fails to satisfy the crl policy, it should not be in the cache. - -ocsp cache - -rowid ocspResponse (responder) lastUsed nextUpdate - -hashAlgorithm->(issuerNameHash,issuerKeyHash,serialNumber)->response - - -crl cache () - -crlDistributionPoint (reasons) crl thisUpdate nextUpdate isDelta - - -crlEntry cache table -(certHash anchorHash) crlIssuer revocationStatus revocationTime expires lastUsed -crlTable -(crlIssuer anchorHash distributionPointURL?) crl sigVerified expires -ocspEntry cache table -(certHash parentHash ocspReponderID) hashAlg revocationStatus revocationTime expires lastUsed -ocspTable -((hashAlg, pubKeyHash, issuerHash, serialNum) anchorHash) ocspResponse sigVerified expires - -or -cert cache table -(certHash parentHash anchorHash) crlEntryID ocspID - -crlEntry cache table -(crlEntryID anchorHash) crlIssuer revocationStatus revocationTime - -crlIssuerTable -(crlIssuer anchorHash) crl sigVerified - -ocsp table -(ocspID) ocspResponse - - -but so does caching the raw response as a link to a blob table containing crls -and ocsp-responses -But also cache the revocationStatus for a (cert,parent) or (cert,anchor) via -a link to a cached ocspResponse or revocationStatus and revocationTime entry from crl -*/ - -#endif diff --git a/trust/trustd/SecOCSPResponse.c b/trust/trustd/SecOCSPResponse.c index 0d1995a6..04768fe5 100644 --- a/trust/trustd/SecOCSPResponse.c +++ b/trust/trustd/SecOCSPResponse.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -208,8 +209,6 @@ errOut: return NULL; } -#define LEEWAY (4500.0) - /* Calculate temporal validity; set latestNextUpdate and expireTime. Returns true if valid, else returns false. */ bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, @@ -218,7 +217,7 @@ bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, bool ok = false; this->latestNextUpdate = NULL_TIME; - if (this->producedAt > verifyTime + LEEWAY) { + if (this->producedAt > verifyTime + TRUST_TIME_LEEWAY) { secnotice("ocsp", "OCSPResponse: producedAt more than 1:15 from now"); goto exit; } @@ -231,7 +230,7 @@ bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, /* thisUpdate later than 'now' invalidates the whole response. */ CFAbsoluteTime thisUpdate = genTimeToCFAbsTime(&resp->thisUpdate); - if (thisUpdate > verifyTime + LEEWAY) { + if (thisUpdate > verifyTime + TRUST_TIME_LEEWAY) { secnotice("ocsp","OCSPResponse: thisUpdate more than 1:15 from now"); goto exit; } @@ -292,7 +291,7 @@ bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, /* See comment above on RFC 5019 section 2.2.4. */ /* Absolute expire time = current time plus defaultTTL */ this->expireTime = verifyTime + defaultTTL; - } else if (this->latestNextUpdate < verifyTime - LEEWAY) { + } else if (this->latestNextUpdate < verifyTime - TRUST_TIME_LEEWAY) { secnotice("ocsp", "OCSPResponse: latestNextUpdate more than 1:15 ago"); goto exit; } else if (maxAge > 0) { @@ -505,13 +504,13 @@ static CFAbsoluteTime SecOCSPSingleResponseComputedNextUpdate(SecOCSPSingleRespo } bool SecOCSPSingleResponseCalculateValidity(SecOCSPSingleResponseRef this, CFTimeInterval defaultTTL, CFAbsoluteTime verifyTime) { - if (this->thisUpdate > verifyTime + LEEWAY) { + if (this->thisUpdate > verifyTime + TRUST_TIME_LEEWAY) { ocspdErrorLog("OCSPSingleResponse: thisUpdate more than 1:15 from now"); return false; } CFAbsoluteTime cnu = SecOCSPSingleResponseComputedNextUpdate(this, defaultTTL); - if (verifyTime - LEEWAY > cnu) { + if (verifyTime - TRUST_TIME_LEEWAY > cnu) { ocspdErrorLog("OCSPSingleResponse: %s %.2f days ago", this->nextUpdate ? "nextUpdate" : "thisUpdate + defaultTTL", (verifyTime - cnu) / 86400); return false; } @@ -692,3 +691,20 @@ SecCertificateRef SecOCSPResponseCopySigner(SecOCSPResponseRef this, SecCertific /* We couldn't find who signed this ocspResponse, give up. */ return NULL; } + +bool SecOCSPResponseIsWeakHash(SecOCSPResponseRef response) { + SecAsn1AlgId algId = response->basicResponse.algId; + const DERItem algOid = { + .data = algId.algorithm.Data, + .length = algId.algorithm.Length, + }; + SecSignatureHashAlgorithm algorithm = SecSignatureHashAlgorithmForAlgorithmOid(&algOid); + if (algorithm == kSecSignatureHashAlgorithmUnknown || + algorithm == kSecSignatureHashAlgorithmMD2 || + algorithm == kSecSignatureHashAlgorithmMD4 || + algorithm == kSecSignatureHashAlgorithmMD5 || + algorithm == kSecSignatureHashAlgorithmSHA1) { + return true; + } + return false; +} diff --git a/trust/trustd/SecOCSPResponse.h b/trust/trustd/SecOCSPResponse.h index 91eec797..2bbaf3fc 100644 --- a/trust/trustd/SecOCSPResponse.h +++ b/trust/trustd/SecOCSPResponse.h @@ -160,6 +160,8 @@ void SecOCSPSingleResponseDestroy(SecOCSPSingleResponseRef this); SecCertificateRef SecOCSPResponseCopySigner(SecOCSPResponseRef this, SecCertificateRef issuerPath); +bool SecOCSPResponseIsWeakHash(SecOCSPResponseRef response); + __END_DECLS #endif /* !_SECURITY_SECOCSPRESPONSE_H_ */ diff --git a/trust/trustd/SecPinningDb.h b/trust/trustd/SecPinningDb.h index fc5a21d6..8c3f2655 100644 --- a/trust/trustd/SecPinningDb.h +++ b/trust/trustd/SecPinningDb.h @@ -32,24 +32,38 @@ #define _SECURITY_SECPINNINGDB_H_ #include +#include __BEGIN_DECLS CF_ASSUME_NONNULL_BEGIN CF_IMPLICIT_BRIDGING_ENABLED +extern const uint64_t PinningDbSchemaVersion; + extern const CFStringRef kSecPinningDbKeyHostname; extern const CFStringRef kSecPinningDbKeyPolicyName; extern const CFStringRef kSecPinningDbKeyRules; +extern const CFStringRef kSecPinningDbKeyTransparentConnection; CFDictionaryRef _Nullable SecPinningDbCopyMatching(CFDictionaryRef _Nonnull query); void SecPinningDbInitialize(void); -#if !TARGET_OS_BRIDGE && __OBJC__ +#if __OBJC__ +#if !TARGET_OS_BRIDGE /* Updating the pinning DB isn't supported on BridgeOS because we treat the disk as read-only. */ bool SecPinningDbUpdateFromURL(NSURL *url, NSError **error); #endif +@interface SecPinningDb : NSObject +@property (assign) SecDbRef db; ++ (NSURL *)pinningDbPath; +- (NSNumber *)getContentVersion:(SecDbConnectionRef)dbconn error:(CFErrorRef *)error; +- (NSNumber *)getSchemaVersion:(SecDbConnectionRef)dbconn error:(CFErrorRef *)error; +- (BOOL) installDbFromURL:(NSURL *)localURL error:(NSError **)nserror; +@end +#endif // __OBJC__ + CFNumberRef SecPinningDbCopyContentVersion(void); CF_IMPLICIT_BRIDGING_DISABLED diff --git a/trust/trustd/SecPinningDb.m b/trust/trustd/SecPinningDb.m index 9941000f..c33df091 100644 --- a/trust/trustd/SecPinningDb.m +++ b/trust/trustd/SecPinningDb.m @@ -47,6 +47,7 @@ #import "trust/trustd/OTATrustUtilities.h" #import "trust/trustd/SecPinningDb.h" #import "trust/trustd/SecTrustLoggingServer.h" +#import "trust/trustd/trustdFileLocations.h" #include "utilities/debugging.h" #include "utilities/sqlutils.h" @@ -60,19 +61,23 @@ #define kSecPinningDbFileName "pinningrules.sqlite3" -const uint64_t PinningDbSchemaVersion = 2; +const uint64_t PinningDbSchemaVersion = 3; + +/* Keys for pinning plist */ const NSString *PinningDbPolicyNameKey = @"policyName"; /* key for a string value */ const NSString *PinningDbDomainsKey = @"domains"; /* key for an array of dictionaries */ const NSString *PinningDbPoliciesKey = @"rules"; /* key for an array of dictionaries */ const NSString *PinningDbDomainSuffixKey = @"suffix"; /* key for a string */ const NSString *PinningDbLabelRegexKey = @"labelRegex"; /* key for a regex string */ +const NSString *PinningDbTransparentConnection = @"transparentConnection"; /* key for transparent connection */ +/* Keys for result/cached results */ const CFStringRef kSecPinningDbKeyHostname = CFSTR("PinningHostname"); const CFStringRef kSecPinningDbKeyPolicyName = CFSTR("PinningPolicyName"); const CFStringRef kSecPinningDbKeyRules = CFSTR("PinningRules"); +const CFStringRef kSecPinningDbKeyTransparentConnection = CFSTR("PinningTransparentConnection"); -@interface SecPinningDb : NSObject -@property (assign) SecDbRef db; +@interface SecPinningDb() @property dispatch_queue_t queue; @property NSURL *dbPath; @property (assign) os_unfair_lock regexCacheLock; @@ -98,9 +103,9 @@ static inline bool isNSDictionary(id nsType) { #define getSchemaVersionSQL CFSTR("PRAGMA user_version") #define selectVersionSQL CFSTR("SELECT ival FROM admin WHERE key='version'") #define insertAdminSQL CFSTR("INSERT OR REPLACE INTO admin (key,ival,value) VALUES (?,?,?)") -#define selectDomainSQL CFSTR("SELECT DISTINCT labelRegex,policyName,policies FROM rules WHERE domainSuffix=?") -#define selectPolicyNameSQL CFSTR("SELECT DISTINCT policies FROM rules WHERE policyName=?") -#define insertRuleSQL CFSTR("INSERT OR REPLACE INTO rules (policyName,domainSuffix,labelRegex,policies) VALUES (?,?,?,?) ") +#define selectDomainSQL CFSTR("SELECT DISTINCT labelRegex,policyName,policies,transparentConnection FROM rules WHERE domainSuffix=?") +#define selectPolicyNameSQL CFSTR("SELECT DISTINCT policies,transparentConnection FROM rules WHERE policyName=?") +#define insertRuleSQL CFSTR("INSERT OR REPLACE INTO rules (policyName,domainSuffix,labelRegex,policies,transparentConnection) VALUES (?,?,?,?,?) ") #define removeAllRulesSQL CFSTR("DELETE FROM rules;") - (NSNumber *)getSchemaVersion:(SecDbConnectionRef)dbconn error:(CFErrorRef *)error { @@ -160,7 +165,7 @@ static inline bool isNSDictionary(id nsType) { __block CFErrorRef error = NULL; __block BOOL ok = YES; __block BOOL newer = NO; - ok &= SecDbPerformRead(_db, &error, ^(SecDbConnectionRef dbconn) { + ok &= SecDbPerformRead(self.db, &error, ^(SecDbConnectionRef dbconn) { NSNumber *db_version = [self getContentVersion:dbconn error:&error]; if (!db_version || [new_version compare:db_version] == NSOrderedDescending) { newer = YES; @@ -179,6 +184,7 @@ static inline bool isNSDictionary(id nsType) { domainSuffix:(NSString *)domainSuffix labelRegex:(NSString *)labelRegex policies:(NSArray *)policies + transparentConnection:(NSNumber *)transparentConnection dbConnection:(SecDbConnectionRef)dbconn error:(CFErrorRef *)error{ /* @@@ This insertion mechanism assumes that the input is trusted -- namely, that the new rules @@ -200,6 +206,7 @@ static inline bool isNSDictionary(id nsType) { ok = false; } ok &= SecDbBindBlob(insertRule, 4, [xmlPolicies bytes], [xmlPolicies length], SQLITE_TRANSIENT, error); + ok &= SecDbBindInt(insertRule, 5, [transparentConnection intValue], error); ok &= SecDbStep(dbconn, insertRule, error, NULL); return ok; }); @@ -222,8 +229,12 @@ static inline bool isNSDictionary(id nsType) { __block NSString *policyName = [rule objectForKey:PinningDbPolicyNameKey]; NSArray *domains = [rule objectForKey:PinningDbDomainsKey]; __block NSArray *policies = [rule objectForKey:PinningDbPoliciesKey]; + NSNumber *transparentConnection = [rule objectForKey:PinningDbTransparentConnection]; + if (!transparentConnection) { + transparentConnection = @(0); + } - if (!policyName || !domains || !policies) { + if (!policyName || !domains || !policies || !transparentConnection) { secerror("SecPinningDb: failed to get required fields from rule entry %lu", (unsigned long)idx); ok = false; return; @@ -244,7 +255,11 @@ static inline bool isNSDictionary(id nsType) { ok = false; return; } - ok &= [self insertRuleWithName:policyName domainSuffix:suffix labelRegex:labelRegex policies:policies + ok &= [self insertRuleWithName:policyName + domainSuffix:suffix + labelRegex:labelRegex + policies:policies + transparentConnection:transparentConnection dbConnection:dbconn error:error]; }]; }]; @@ -290,18 +305,25 @@ static inline bool isNSDictionary(id nsType) { "domainSuffix TEXT NOT NULL," "labelRegex TEXT NOT NULL," "policies BLOB NOT NULL," + "transparentConnection INTEGER," "UNIQUE(policyName, domainSuffix, labelRegex)" ");"), error); ok &= SecDbExec(dbconn, CFSTR("CREATE INDEX IF NOT EXISTS idomain ON rules(domainSuffix);"), error); ok &= SecDbExec(dbconn, CFSTR("CREATE INDEX IF NOT EXISTS ipolicy ON rules(policyName);"), error); + + NSNumber *schemaVersion = [self getSchemaVersion:dbconn error:error]; + if (schemaVersion && ([schemaVersion intValue] > 0)) { // Not a new DB + if ([schemaVersion intValue] < 3) { + ok &= SecDbExec(dbconn, CFSTR("ALTER TABLE rules ADD COLUMN transparentConnection INTEGER"), error); + } + } if (!ok) { secerror("SecPinningDb: failed to create rules table: %@", error ? *error : nil); } return ok; } -#if !TARGET_OS_BRIDGE - (BOOL) installDbFromURL:(NSURL *)localURL error:(NSError **)nserror { if (!localURL) { secerror("SecPinningDb: missing url for downloaded asset"); @@ -341,7 +363,7 @@ static inline bool isNSDictionary(id nsType) { if (!ok || error) { secerror("SecPinningDb: error installing updated pinning list version %@: %@", [pinningList objectAtIndex:0], error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(__bridge NSError *)error + [[TrustAnalytics logger] logHardError:(__bridge NSError *)error withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : @(TAOperationWrite) }]; @@ -351,7 +373,6 @@ static inline bool isNSDictionary(id nsType) { return ok; } -#endif /* !TARGET_OS_BRIDGE */ - (NSArray *) copySystemPinningList { NSArray *pinningList = nil; @@ -363,6 +384,7 @@ static inline bool isNSDictionary(id nsType) { CFReleaseNull(otapkiref); if (!pinningListURL) { secerror("SecPinningDb: failed to get pinning plist URL"); + return nil; } NSError *error = nil; pinningList = [NSArray arrayWithContentsOfURL:pinningListURL error:&error]; @@ -460,6 +482,7 @@ static inline bool isNSDictionary(id nsType) { secnotice("pinningDb", "Updating pinning database schema from version %@ to version %@", schema_version, current_version); updateSchema = true; + updateContent = true; // Reload the content into the new schema } if (updateContent || updateSchema) { @@ -471,7 +494,7 @@ static inline bool isNSDictionary(id nsType) { if (!ok) { secerror("SecPinningDb: %s failed: %@", didCreate ? "Create" : "Open", error ? *error : NULL); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(error ? (__bridge NSError *)*error : nil) + [[TrustAnalytics logger] logHardError:(error ? (__bridge NSError *)*error : nil) withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : didCreate ? @(TAOperationCreate) : @(TAOperationOpen)}]; @@ -485,27 +508,14 @@ static inline bool isNSDictionary(id nsType) { return result; } -static void verify_create_path(const char *path) -{ - int ret = mkpath_np(path, 0755); - if (!(ret == 0 || ret == EEXIST)) { - secerror("could not create path: %s (%s)", path, strerror(ret)); - } -} - -- (NSURL *)pinningDbPath { - /* Make sure the /Library/Keychains directory is there */ - NSURL *directory = CFBridgingRelease(SecCopyURLForFileInSystemKeychainDirectory(nil)); - verify_create_path([directory fileSystemRepresentation]); - - /* Get the full path of the pinning DB */ - return [directory URLByAppendingPathComponent:@kSecPinningDbFileName]; ++ (NSURL *)pinningDbPath { + return CFBridgingRelease(SecCopyURLForFileInProtectedTrustdDirectory(CFSTR(kSecPinningDbFileName))); } - (void) initializedDb { dispatch_sync(_queue, ^{ if (!self->_db) { - self->_dbPath = [self pinningDbPath]; + self->_dbPath = [SecPinningDb pinningDbPath]; self->_db = [self createAtPath]; } }); @@ -643,6 +653,7 @@ static void verify_create_path(const char *path) __block CFErrorRef error = NULL; __block NSMutableArray *resultRules = [NSMutableArray array]; __block NSString *resultName = nil; + __block NSNumber *resultTC = @(0); #if !TARGET_OS_WATCH __block NSMutableDictionary *newCacheEntry = [NSMutableDictionary dictionary]; #endif @@ -669,11 +680,14 @@ static void verify_create_path(const char *path) verify_action(xmlPolicies, return); id policies = [NSPropertyListSerialization propertyListWithData:xmlPolicies options:0 format:nil error:nil]; verify_action(isNSArray(policies), return); + // TransparentConnection + bool transparentConnection = (sqlite3_column_int(selectDomain, 3) > 0) ? true : false; #if !TARGET_OS_WATCH /* Add to cache entry */ [newCacheEntry setObject:@{(__bridge NSString*)kSecPinningDbKeyPolicyName:policyNameStr, - (__bridge NSString*)kSecPinningDbKeyRules:policies} + (__bridge NSString*)kSecPinningDbKeyRules:policies, + (__bridge NSString*)kSecPinningDbKeyTransparentConnection:@(transparentConnection)} forKey:regularExpression]; #endif @@ -690,6 +704,7 @@ static void verify_create_path(const char *path) * @@@ Assumes there is only one rule with matching suffix/label pairs. */ [resultRules addObjectsFromArray:(NSArray *)policies]; resultName = policyNameStr; + resultTC = @(transparentConnection); } }); return ok; @@ -699,7 +714,7 @@ static void verify_create_path(const char *path) if (!ok || error) { secerror("SecPinningDb: error querying DB for hostname: %@", error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(__bridge NSError *)error + [[TrustAnalytics logger] logHardError:(__bridge NSError *)error withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : @(TAOperationRead)}]; @@ -725,7 +740,9 @@ static void verify_create_path(const char *path) } return @{(__bridge NSString*)kSecPinningDbKeyRules:resultRules, - (__bridge NSString*)kSecPinningDbKeyPolicyName:resultName}; + (__bridge NSString*)kSecPinningDbKeyPolicyName:resultName, + (__bridge NSString*)kSecPinningDbKeyTransparentConnection:resultTC, + }; } return nil; } @@ -750,6 +767,7 @@ static void verify_create_path(const char *path) __block bool ok = true; __block CFErrorRef error = NULL; __block NSMutableArray *resultRules = [NSMutableArray array]; + __block NSNumber *resultTC = @(0); ok &= SecDbPerformRead(_db, &error, ^(SecDbConnectionRef dbconn) { ok &= SecDbWithSQL(dbconn, selectPolicyNameSQL, &error, ^bool(sqlite3_stmt *selectPolicyName) { ok &= SecDbBindText(selectPolicyName, 1, [policyName UTF8String], [policyName length], SQLITE_TRANSIENT, &error); @@ -765,6 +783,9 @@ static void verify_create_path(const char *path) return; } [resultRules addObjectsFromArray:(NSArray *)policies]; + + bool transparentConnection = (sqlite3_column_int(selectPolicyName, 1) > 0) ? true : false; + resultTC = @(transparentConnection); } }); return ok; @@ -774,7 +795,7 @@ static void verify_create_path(const char *path) if (!ok || error) { secerror("SecPinningDb: error querying DB for policyName: %@", error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(__bridge NSError *)error + [[TrustAnalytics logger] logHardError:(__bridge NSError *)error withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : @(TAOperationRead)}]; @@ -784,7 +805,9 @@ static void verify_create_path(const char *path) if ([resultRules count] > 0) { NSDictionary *results = @{(__bridge NSString*)kSecPinningDbKeyRules:resultRules, - (__bridge NSString*)kSecPinningDbKeyPolicyName:policyName}; + (__bridge NSString*)kSecPinningDbKeyPolicyName:policyName, + (__bridge NSString*)kSecPinningDbKeyTransparentConnection:resultTC, + }; return results; } return nil; @@ -809,7 +832,7 @@ void SecPinningDbInitialize(void) { if (!ok || error) { secerror("SecPinningDb: unable to initialize db: %@", error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(__bridge NSError *)error + [[TrustAnalytics logger] logHardError:(__bridge NSError *)error withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : @(TAOperationRead)}]; @@ -821,23 +844,22 @@ void SecPinningDbInitialize(void) { } CFDictionaryRef _Nullable SecPinningDbCopyMatching(CFDictionaryRef query) { -#ifdef DARLING - return nil; -#else @autoreleasepool { SecPinningDbInitialize(); - NSDictionary *nsQuery = (__bridge NSDictionary*)query; - NSString *hostname = [nsQuery objectForKey:(__bridge NSString*)kSecPinningDbKeyHostname]; - NSDictionary *results = [pinningDb queryForDomain:hostname]; - if (results) { return CFBridgingRetain(results); } + /* prefer rules queried by policy name */ NSString *policyName = [nsQuery objectForKey:(__bridge NSString*)kSecPinningDbKeyPolicyName]; - results = [pinningDb queryForPolicyName:policyName]; - if (!results) { return nil; } + NSDictionary *results = [pinningDb queryForPolicyName:policyName]; + if (results) { + return CFBridgingRetain(results); + } + + /* then rules queried by hostname */ + NSString *hostname = [nsQuery objectForKey:(__bridge NSString*)kSecPinningDbKeyHostname]; + results = [pinningDb queryForDomain:hostname]; return CFBridgingRetain(results); } -#endif } #if !TARGET_OS_BRIDGE diff --git a/trust/trustd/SecPolicyServer.c b/trust/trustd/SecPolicyServer.c index d17d3bbd..d44e675c 100644 --- a/trust/trustd/SecPolicyServer.c +++ b/trust/trustd/SecPolicyServer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,25 +25,33 @@ * SecPolicyServer.c - Engine for evaluating certificate paths against trust policies. */ -#include "trust/trustd/SecPolicyServer.h" -#include -#include -#include -#include "trust/trustd/policytree.h" -#include "trust/trustd/nameconstraints.h" -#include -#include -#include -#include -#include #include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include #include #include #include #include #include -#include +#include +#include +#include +#include #include #include #include @@ -51,9 +59,10 @@ #include #include #include -#include -#include -#include + +#include "trust/trustd/SecPolicyServer.h" +#include "trust/trustd/policytree.h" +#include "trust/trustd/nameconstraints.h" #include "trust/trustd/SecTrustServer.h" #include "trust/trustd/SecTrustLoggingServer.h" #include "trust/trustd/SecRevocationServer.h" @@ -61,12 +70,9 @@ #include "trust/trustd/SecCertificateSource.h" #include "trust/trustd/SecOCSPResponse.h" #include "trust/trustd/SecTrustStoreServer.h" -#include -#include -#include -#include "OTATrustUtilities.h" -#include "personalization.h" -#include +#include "trust/trustd/OTATrustUtilities.h" +#include "trust/trustd/personalization.h" +#include "trust/trustd/CertificateTransparency.h" #if !TARGET_OS_IPHONE #include @@ -95,9 +101,6 @@ static void secdumpdata(CFDataRef data, const char *name) { ****************** SecPolicy object ******************** ********************************************************/ -static SecCertificateRef SecPVCGetCertificateAtIndex(SecPVCRef pvc, CFIndex ix); -static CFIndex SecPVCGetCertificateCount(SecPVCRef pvc); -static CFAbsoluteTime SecPVCGetVerifyTime(SecPVCRef pvc); static SecTrustSettingsResult SecPVCGetTrustSettingsResult(SecPVCRef pvc, SecCertificateRef certificate, CFArrayRef constraints); static CFMutableDictionaryRef gSecPolicyLeafCallbacks = NULL; @@ -300,6 +303,17 @@ static void SecPolicyCheckKeyUsage(SecPVCRef pvc, } } +static void SecPolicyCheckKeyUsageReportOnly(SecPVCRef pvc, CFStringRef key) +{ + SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0); + SecPolicyRef policy = SecPVCGetPolicy(pvc); + CFTypeRef xku = CFDictionaryGetValue(policy->_options, key); + TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(pvc->builder); + if (analytics && !SecPolicyCheckCertKeyUsage(leaf, xku)) { + analytics->tls_invalid_ku = true; + } +} + /* AUDIT[securityd](done): policy->_options is a caller provided dictionary, only its cf type has been checked. @@ -308,9 +322,26 @@ static void SecPolicyCheckExtendedKeyUsage(SecPVCRef pvc, CFStringRef key) { SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0); SecPolicyRef policy = SecPVCGetPolicy(pvc); CFTypeRef xeku = CFDictionaryGetValue(policy->_options, key); + /* leaf check enforced */ if (!SecPolicyCheckCertExtendedKeyUsage(leaf, xeku)){ SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); } + + /* subCA check produces metrics */ + TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(pvc->builder); + CFIndex ix, count = SecPVCGetCertificateCount(pvc); + if (count > 2 && analytics) { + for (ix = 1; ix < count - 1 ; ++ix) { + SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix); + CFArrayRef ekus = SecCertificateCopyExtendedKeyUsage(cert); + if (ekus && CFArrayGetCount(ekus) && // subCA has ekus + !SecPolicyCheckCertExtendedKeyUsage(cert, CFSTR("2.5.29.37.0")) && // but not the anyEKU + !SecPolicyCheckCertExtendedKeyUsage(cert, xeku)) { // and not the EKUs specified by the policy + analytics->ca_fail_eku_check = true; + } + CFReleaseNull(ekus); + } + } } static void SecPolicyCheckBasicConstraints(SecPVCRef pvc, @@ -557,26 +588,8 @@ static void SecPolicyCheckAnchorSHA256(SecPVCRef pvc, CFStringRef key) { return; } - -/* AUDIT[securityd](done): - policy->_options is a caller provided dictionary, only its cf type has - been checked. - */ -static void SecPolicyCheckAnchorSHA1(SecPVCRef pvc, - CFStringRef key) { - CFIndex count = SecPVCGetCertificateCount(pvc); - SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, count - 1); - CFDataRef anchorSHA1 = SecCertificateGetSHA1Digest(cert); - - if (!isDigestInPolicy(pvc, key, anchorSHA1)) - if (!SecPVCSetResult(pvc, kSecPolicyCheckAnchorSHA1, count-1, kCFBooleanFalse)) - return; - - return; -} - /* - Check the SHA256 of SPKI of the first intermediate CA certificate in the path + Check the SHA256 of SPKI of the first intermediate CA certificate in the path. policy->_options is a caller provided dictionary, only its cf type has been checked. */ @@ -599,6 +612,73 @@ static void SecPolicyCheckIntermediateSPKISHA256(SecPVCRef pvc, CFReleaseNull(digest); } +/* + Check the SPKI SHA256 of CA certificates in the path + policy->_options is a caller provided dictionary, only its cf type has + been checked. + */ +static void SecPolicyCheckCAspkiSHA256(SecPVCRef pvc, + CFStringRef key) { + SecCertificateRef cert = NULL; + CFDataRef digest = NULL; + + if (SecPVCGetCertificateCount(pvc) < 2) { + SecPVCSetResult(pvc, kSecPolicyCheckCAspkiSHA256, 0, kCFBooleanFalse); + return; + } + + bool spkiSHA256match = false; + CFIndex count = SecPVCGetCertificateCount(pvc); + for (CFIndex i = 1; i < count && spkiSHA256match == false; i++) { + cert = SecPVCGetCertificateAtIndex(pvc, i); + digest = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(cert); + + if (isDigestInPolicy(pvc, key, digest)) { + spkiSHA256match = true; + } + + CFReleaseNull(digest); + } + + if (spkiSHA256match == true) { + return; + } + + for (CFIndex i = 1; i < count; i++) { + SecPVCSetResult(pvc, kSecPolicyCheckCAspkiSHA256, i, kCFBooleanFalse); + } +} + +/* + Check the SPKI SHA256 of the leaf certificate. + policy->_options is a caller provided dictionary, only its cf type has + been checked. +*/ +static void SecPolicyCheckLeafSPKISHA256(SecPVCRef pvc, + CFStringRef key) { + SecPolicyRef policy = SecPVCGetPolicy(pvc); + + CFArrayRef leafSPKISHA256 = CFDictionaryGetValue(policy->_options, key); + if (isArray(leafSPKISHA256) == false) { + /* @@@ We can't return an error here and making the evaluation fail + won't help much either. */ + return; + } + + SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0); + CFDataRef digest = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(leaf); + if (!digest) { + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + return; + } + + if (!CFArrayContainsValue(leafSPKISHA256, CFRangeMake(0, CFArrayGetCount(leafSPKISHA256)), digest)) { + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + } + + CFReleaseNull(digest); +} + /* policy->_options is a caller provided dictionary, only its cf type has been checked. @@ -1262,633 +1342,6 @@ certificatePolicies or extendedKeyUsage extensions. */ } - -/* - * MARK: Certificate Transparency support - */ -const CFStringRef kSecCTRetirementDateKey = CFSTR("expiry"); // For backwards compatibility, retirement date is represented with the "expiry" key -const CFStringRef kSecCTReadOnlyDateKey = CFSTR("frozen"); // For backwards compatibility, read-only date is represented with the "frozen" key -const CFStringRef kSecCTShardStartDateKey = CFSTR("start_inclusive"); -const CFStringRef kSecCTShardEndDateKey = CFSTR("end_exclusive"); -const CFStringRef kSecCTPublicKeyKey = CFSTR("key"); - -enum { - kSecCTEntryTypeCert = 0, - kSecCTEntryTypePreCert = 1, -}; - -/*** - -struct { - Version sct_version; // 1 byte - LogID id; // 32 bytes - uint64 timestamp; // 8 bytes - CtExtensions extensions; // 2 bytes len field, + n bytes data - digitally-signed struct { // 1 byte hash alg, 1 byte sig alg, n bytes signature - Version sct_version; - SignatureType signature_type = certificate_timestamp; - uint64 timestamp; - LogEntryType entry_type; - select(entry_type) { - case x509_entry: ASN.1Cert; - case precert_entry: PreCert; - } signed_entry; - CtExtensions extensions; - }; -} SignedCertificateTimestamp; - -***/ - -#include - -static const -SecAsn1Oid *oidForSigAlg(SSL_HashAlgorithm hash, SSL_SignatureAlgorithm alg) -{ - switch(alg) { - case SSL_SignatureAlgorithmRSA: - switch (hash) { - case SSL_HashAlgorithmSHA1: - return &CSSMOID_SHA1WithRSA; - case SSL_HashAlgorithmSHA256: - return &CSSMOID_SHA256WithRSA; - case SSL_HashAlgorithmSHA384: - return &CSSMOID_SHA384WithRSA; - default: - break; - } - case SSL_SignatureAlgorithmECDSA: - switch (hash) { - case SSL_HashAlgorithmSHA1: - return &CSSMOID_ECDSA_WithSHA1; - case SSL_HashAlgorithmSHA256: - return &CSSMOID_ECDSA_WithSHA256; - case SSL_HashAlgorithmSHA384: - return &CSSMOID_ECDSA_WithSHA384; - default: - break; - } - default: - break; - } - - return NULL; -} - - -static size_t SSLDecodeUint16(const uint8_t *p) -{ - return (p[0]<<8 | p[1]); -} - -static uint8_t *SSLEncodeUint16(uint8_t *p, size_t len) -{ - p[0] = (len >> 8)&0xff; - p[1] = (len & 0xff); - return p+2; -} - -static uint8_t *SSLEncodeUint24(uint8_t *p, size_t len) -{ - p[0] = (len >> 16)&0xff; - p[1] = (len >> 8)&0xff; - p[2] = (len & 0xff); - return p+3; -} - - -static -uint64_t SSLDecodeUint64(const uint8_t *p) -{ - uint64_t u = 0; - for(int i=0; i<8; i++) { - u=(u<<8)|p[0]; - p++; - } - return u; -} - -#include -#include -#include - - -static CFDataRef copy_x509_entry_from_chain(SecPVCRef pvc) -{ - SecCertificateRef leafCert = SecPVCGetCertificateAtIndex(pvc, 0); - - CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 3+SecCertificateGetLength(leafCert)); - - CFDataSetLength(data, 3+SecCertificateGetLength(leafCert)); - - uint8_t *q = CFDataGetMutableBytePtr(data); - q = SSLEncodeUint24(q, SecCertificateGetLength(leafCert)); - memcpy(q, SecCertificateGetBytePtr(leafCert), SecCertificateGetLength(leafCert)); - - return data; -} - - -static CFDataRef copy_precert_entry_from_chain(SecPVCRef pvc) -{ - SecCertificateRef leafCert = NULL; - SecCertificateRef issuer = NULL; - CFDataRef issuerKeyHash = NULL; - CFDataRef tbs_precert = NULL; - CFMutableDataRef data= NULL; - - require_quiet(SecPVCGetCertificateCount(pvc)>=2, out); //we need the issuer key for precerts. - leafCert = SecPVCGetCertificateAtIndex(pvc, 0); - issuer = SecPVCGetCertificateAtIndex(pvc, 1); - - require(leafCert, out); - require(issuer, out); // Those two would likely indicate an internal error, since we already checked the chain length above. - issuerKeyHash = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(issuer); - tbs_precert = SecCertificateCopyPrecertTBS(leafCert); - - require(issuerKeyHash, out); - require(tbs_precert, out); - data = CFDataCreateMutable(kCFAllocatorDefault, CFDataGetLength(issuerKeyHash) + 3 + CFDataGetLength(tbs_precert)); - CFDataSetLength(data, CFDataGetLength(issuerKeyHash) + 3 + CFDataGetLength(tbs_precert)); - - uint8_t *q = CFDataGetMutableBytePtr(data); - memcpy(q, CFDataGetBytePtr(issuerKeyHash), CFDataGetLength(issuerKeyHash)); q += CFDataGetLength(issuerKeyHash); // issuer key hash - q = SSLEncodeUint24(q, CFDataGetLength(tbs_precert)); - memcpy(q, CFDataGetBytePtr(tbs_precert), CFDataGetLength(tbs_precert)); - -out: - CFReleaseSafe(issuerKeyHash); - CFReleaseSafe(tbs_precert); - return data; -} - -static -CFAbsoluteTime TimestampToCFAbsoluteTime(uint64_t ts) -{ - return (ts / 1000) - kCFAbsoluteTimeIntervalSince1970; -} - -static -uint64_t TimestampFromCFAbsoluteTime(CFAbsoluteTime at) -{ - return (uint64_t)(at + kCFAbsoluteTimeIntervalSince1970) * 1000; -} - -static bool isSCTValidForLogData(CFDictionaryRef logData, int entry_type, CFAbsoluteTime sct_time, CFAbsoluteTime cert_expiry_date) { - /* only embedded SCTs can be used from retired logs. */ - if(entry_type==kSecCTEntryTypeCert && CFDictionaryContainsKey(logData, kSecCTRetirementDateKey)) { - return false; - } - - /* SCTs from after the transition to read-only are not valid (and indicate a operator failure) */ - CFDateRef frozen_date = CFDictionaryGetValue(logData, kSecCTReadOnlyDateKey); - if (frozen_date && (sct_time > CFDateGetAbsoluteTime(frozen_date))) { - secerror("Frozen CT log issued SCT after freezing (log=%@)\n", logData); - return false; - } - - /* If the log is temporally sharded, the certificate expiry date must be within the temporal shard window */ - CFDateRef start_inclusive = CFDictionaryGetValue(logData, kSecCTShardStartDateKey); - CFDateRef end_exclusive = CFDictionaryGetValue(logData, kSecCTShardEndDateKey); - if (start_inclusive && (cert_expiry_date < CFDateGetAbsoluteTime(start_inclusive))) { - return false; - } - if (end_exclusive && (cert_expiry_date >= CFDateGetAbsoluteTime(end_exclusive))) { - return false; - } - - return true; -} - - -/* - If the 'sct' is valid, add it to the validatingLogs dictionary. - - Inputs: - - validatingLogs: mutable dictionary to which to add the log that validate this SCT. - - sct: the SCT date - - entry_type: 0 for x509 cert, 1 for precert. - - entry: the cert or precert data. - - vt: verification time timestamp (as used in SCTs: ms since 1970 Epoch) - - trustedLog: Dictionary contain the Trusted Logs. - - The SCT is valid if: - - It decodes properly. - - Its timestamp is less than 'verifyTime'. - - It is signed by a log in 'trustedLogs'. - - If entry_type = 0, the log must be currently qualified. - - If entry_type = 1, the log may be expired. - - If the SCT is valid, it's added to the validatinLogs dictionary using the log dictionary as the key, and the timestamp as value. - If an entry for the same log already existing in the dictionary, the entry is replaced only if the timestamp of this SCT is earlier. - - */ -static CFDictionaryRef getSCTValidatingLog(CFDataRef sct, int entry_type, CFDataRef entry, uint64_t vt, CFAbsoluteTime cert_expiry_date, CFDictionaryRef trustedLogs, CFAbsoluteTime *sct_at) -{ - uint8_t version; - const uint8_t *logID; - const uint8_t *timestampData; - uint64_t timestamp; - size_t extensionsLen; - const uint8_t *extensionsData; - uint8_t hashAlg; - uint8_t sigAlg; - size_t signatureLen; - const uint8_t *signatureData; - SecKeyRef pubKey = NULL; - uint8_t *signed_data = NULL; - const SecAsn1Oid *oid = NULL; - SecAsn1AlgId algId; - CFDataRef logIDData = NULL; - CFDictionaryRef result = 0; - - const uint8_t *p = CFDataGetBytePtr(sct); - size_t len = CFDataGetLength(sct); - - require(len>=43, out); - - version = p[0]; p++; len--; - logID = p; p+=32; len-=32; - timestampData = p; p+=8; len-=8; - extensionsLen = SSLDecodeUint16(p); p+=2; len-=2; - - require(len>=extensionsLen, out); - extensionsData = p; p+=extensionsLen; len-=extensionsLen; - - require(len>=4, out); - hashAlg=p[0]; p++; len--; - sigAlg=p[0]; p++; len--; - signatureLen = SSLDecodeUint16(p); p+=2; len-=2; - require(len==signatureLen, out); /* We do not tolerate any extra data after the signature */ - signatureData = p; - - /* verify version: only v1(0) is supported */ - if(version!=0) { - secerror("SCT version unsupported: %d\n", version); - goto out; - } - - /* verify timestamp not in the future */ - timestamp = SSLDecodeUint64(timestampData); - if(timestamp > vt) { - secerror("SCT is in the future: %llu > %llu\n", timestamp, vt); - goto out; - } - - uint8_t *q; - - /* signed entry */ - size_t signed_data_len = 12 + CFDataGetLength(entry) + 2 + extensionsLen ; - signed_data = malloc(signed_data_len); - require(signed_data, out); - q = signed_data; - *q++ = version; - *q++ = 0; // certificate_timestamp - memcpy(q, timestampData, 8); q+=8; - q = SSLEncodeUint16(q, entry_type); // logentry type: 0=cert 1=precert - memcpy(q, CFDataGetBytePtr(entry), CFDataGetLength(entry)); q += CFDataGetLength(entry); - q = SSLEncodeUint16(q, extensionsLen); - memcpy(q, extensionsData, extensionsLen); - - logIDData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, logID, 32, kCFAllocatorNull); - - CFDictionaryRef logData = CFDictionaryGetValue(trustedLogs, logIDData); - CFAbsoluteTime sct_time = TimestampToCFAbsoluteTime(timestamp); - require(logData && isSCTValidForLogData(logData, entry_type, sct_time, cert_expiry_date), out); - - CFDataRef logKeyData = CFDictionaryGetValue(logData, kSecCTPublicKeyKey); - require(logKeyData, out); // This failing would be an internal logic error - pubKey = SecKeyCreateFromSubjectPublicKeyInfoData(kCFAllocatorDefault, logKeyData); - require(pubKey, out); - - oid = oidForSigAlg(hashAlg, sigAlg); - require(oid, out); - - algId.algorithm = *oid; - algId.parameters.Data = NULL; - algId.parameters.Length = 0; - - if(SecKeyDigestAndVerify(pubKey, &algId, signed_data, signed_data_len, signatureData, signatureLen)==0) { - *sct_at = sct_time; - result = logData; - } else { - secerror("SCT signature failed (log=%@)\n", logData); - } - -out: - CFReleaseSafe(logIDData); - CFReleaseSafe(pubKey); - free(signed_data); - return result; -} - - -static void addValidatingLog(CFMutableDictionaryRef validatingLogs, CFDictionaryRef log, CFAbsoluteTime sct_at) -{ - CFDateRef validated_time = CFDictionaryGetValue(validatingLogs, log); - - if(validated_time==NULL || (sct_at < CFDateGetAbsoluteTime(validated_time))) { - CFDateRef sct_time = CFDateCreate(kCFAllocatorDefault, sct_at); - CFDictionarySetValue(validatingLogs, log, sct_time); - CFReleaseSafe(sct_time); - } -} - -static CFArrayRef copy_ocsp_scts(SecPVCRef pvc) -{ - CFMutableArrayRef SCTs = NULL; - SecCertificateRef leafCert = NULL; - SecCertificateRef issuer = NULL; - CFArrayRef ocspResponsesData = NULL; - SecOCSPRequestRef ocspRequest = NULL; - - ocspResponsesData = SecPathBuilderCopyOCSPResponses(pvc->builder); - require_quiet(ocspResponsesData, out); - - require_quiet(SecPVCGetCertificateCount(pvc)>=2, out); //we need the issuer key for precerts. - leafCert = SecPVCGetCertificateAtIndex(pvc, 0); - issuer = SecPVCGetCertificateAtIndex(pvc, 1); - - require(leafCert, out); - require(issuer, out); // not quiet: Those two would likely indicate an internal error, since we already checked the chain length above. - ocspRequest = SecOCSPRequestCreate(leafCert, issuer); - - SCTs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - require(SCTs, out); - - CFArrayForEach(ocspResponsesData, ^(const void *value) { - /* TODO: Should the builder already have the appropriate SecOCSPResponseRef ? */ - SecOCSPResponseRef ocspResponse = SecOCSPResponseCreate(value); - if(ocspResponse && SecOCSPGetResponseStatus(ocspResponse)==kSecOCSPSuccess) { - SecOCSPSingleResponseRef ocspSingleResponse = SecOCSPResponseCopySingleResponse(ocspResponse, ocspRequest); - if(ocspSingleResponse) { - CFArrayRef singleResponseSCTs = SecOCSPSingleResponseCopySCTs(ocspSingleResponse); - if(singleResponseSCTs) { - CFArrayAppendArray(SCTs, singleResponseSCTs, CFRangeMake(0, CFArrayGetCount(singleResponseSCTs))); - CFRelease(singleResponseSCTs); - } - SecOCSPSingleResponseDestroy(ocspSingleResponse); - } - } - if(ocspResponse) SecOCSPResponseFinalize(ocspResponse); - }); - - if(CFArrayGetCount(SCTs)==0) { - CFReleaseNull(SCTs); - } - -out: - CFReleaseSafe(ocspResponsesData); - if(ocspRequest) - SecOCSPRequestFinalize(ocspRequest); - - return SCTs; -} - -static void SecPolicyCheckCT(SecPVCRef pvc) -{ - SecCertificateRef leafCert = SecPVCGetCertificateAtIndex(pvc, 0); - CFArrayRef embeddedScts = SecCertificateCopySignedCertificateTimestamps(leafCert); - CFArrayRef builderScts = SecPathBuilderCopySignedCertificateTimestamps(pvc->builder); - CFDictionaryRef trustedLogs = SecPathBuilderCopyTrustedLogs(pvc->builder); - CFArrayRef ocspScts = copy_ocsp_scts(pvc); - CFDataRef precertEntry = copy_precert_entry_from_chain(pvc); - CFDataRef x509Entry = copy_x509_entry_from_chain(pvc); - __block uint32_t trustedSCTCount = 0; - __block CFAbsoluteTime issuanceTime = SecPVCGetVerifyTime(pvc); - __block CFAbsoluteTime certExpiry = SecCertificateNotValidAfter(leafCert); - TA_CTFailureReason failureReason = TA_CTNoFailure; - - if (!trustedLogs) { - SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef(); - trustedLogs = SecOTAPKICopyTrustedCTLogs(otapkiref); - CFReleaseSafe(otapkiref); - } - - // This eventually contain list of logs who validated the SCT. - CFMutableDictionaryRef currentLogsValidatingScts = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFMutableDictionaryRef logsValidatingEmbeddedScts = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - uint64_t vt = TimestampFromCFAbsoluteTime(SecPVCGetVerifyTime(pvc)); - - __block bool at_least_one_currently_valid_external = 0; - __block bool at_least_one_currently_valid_embedded = 0; - __block bool unknown_log = 0; - __block bool disqualified_log = 0; - - require(logsValidatingEmbeddedScts, out); - require(currentLogsValidatingScts, out); - - /* Skip if there are no SCTs. */ - bool no_scts = (embeddedScts && CFArrayGetCount(embeddedScts) > 0) || - (builderScts && CFArrayGetCount(builderScts) > 0) || - (ocspScts && CFArrayGetCount(ocspScts) > 0); - require_action_quiet(no_scts, out, - TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(pvc->builder); - if (analytics) { - analytics->ct_failure_reason = TA_CTNoSCTs; - } - ); - - if(trustedLogs && CFDictionaryGetCount(trustedLogs) > 0) { // Don't bother trying to validate SCTs if we don't have any trusted logs. - if(embeddedScts && precertEntry) { // Don't bother if we could not get the precert. - CFArrayForEach(embeddedScts, ^(const void *value){ - CFAbsoluteTime sct_at; - CFDictionaryRef log = getSCTValidatingLog(value, 1, precertEntry, vt, certExpiry, trustedLogs, &sct_at); - if(log) { - addValidatingLog(logsValidatingEmbeddedScts, log, sct_at); - if(!CFDictionaryContainsKey(log, kSecCTRetirementDateKey)) { - addValidatingLog(currentLogsValidatingScts, log, sct_at); - at_least_one_currently_valid_embedded = true; - trustedSCTCount++; - } else { - disqualified_log = true; - } - } else { - unknown_log = true; - } - }); - } - - if(builderScts && x509Entry) { // Don't bother if we could not get the cert. - CFArrayForEach(builderScts, ^(const void *value){ - CFAbsoluteTime sct_at; - CFDictionaryRef log = getSCTValidatingLog(value, 0, x509Entry, vt, certExpiry, trustedLogs, &sct_at); - if(log) { - addValidatingLog(currentLogsValidatingScts, log, sct_at); - at_least_one_currently_valid_external = true; - trustedSCTCount++; - } else { - unknown_log = true; - } - }); - } - - if(ocspScts && x509Entry) { - CFArrayForEach(ocspScts, ^(const void *value){ - CFAbsoluteTime sct_at; - CFDictionaryRef log = getSCTValidatingLog(value, 0, x509Entry, vt, certExpiry, trustedLogs, &sct_at); - if(log) { - addValidatingLog(currentLogsValidatingScts, log, sct_at); - at_least_one_currently_valid_external = true; - trustedSCTCount++; - } else { - unknown_log = true; - } - }); - } - } else { - failureReason = TA_CTMissingLogs; - } - - - /* We now have 2 sets of logs that validated those SCTS, count them and make a final decision. - - Current Policy: - is_ct = (A1 AND A2) OR (B1 AND B2). - - A1: embedded SCTs from 2+ to 5+ logs valid at issuance time - A2: At least one embedded SCT from a currently valid log. - - B1: SCTs from 2 currently valid logs (from any source) - B2: At least 1 external SCT from a currently valid log. - - */ - - bool hasValidExternalSCT = (at_least_one_currently_valid_external && CFDictionaryGetCount(currentLogsValidatingScts)>=2); - bool hasValidEmbeddedSCT = (at_least_one_currently_valid_embedded); - SecCertificatePathVCRef path = SecPathBuilderGetPath(pvc->builder); - SecCertificatePathVCSetIsCT(path, false); - - if (hasValidEmbeddedSCT) { - /* Calculate issuance time based on timestamp of SCTs from current logs */ - CFDictionaryForEach(currentLogsValidatingScts, ^(const void *key, const void *value) { - CFDictionaryRef log = key; - if(!CFDictionaryContainsKey(log, kSecCTRetirementDateKey)) { - // Log is still qualified - CFDateRef ts = (CFDateRef) value; - CFAbsoluteTime timestamp = CFDateGetAbsoluteTime(ts); - if(timestamp < issuanceTime) { - issuanceTime = timestamp; - } - } - }); - SecCertificatePathVCSetIssuanceTime(path, issuanceTime); - } - if (hasValidExternalSCT) { - /* Note: since external SCT validates this cert, we do not need to - override issuance time here. If the cert also has a valid embedded - SCT, issuanceTime will be calculated and set in the block above. */ - SecCertificatePathVCSetIsCT(path, true); - } else if (hasValidEmbeddedSCT) { - __block int lifetime; // in Months - __block unsigned once_or_current_qualified_embedded = 0; - - /* Count Logs */ - __block bool failed_once_check = false; - CFDictionaryForEach(logsValidatingEmbeddedScts, ^(const void *key, const void *value) { - CFDictionaryRef log = key; - CFDateRef ts = value; - CFDateRef expiry = CFDictionaryGetValue(log, kSecCTRetirementDateKey); - if (expiry == NULL) { // Currently qualified OR - once_or_current_qualified_embedded++; - } else if (CFDateCompare(ts, expiry, NULL) == kCFCompareLessThan && // Once qualified. That is, qualified at the time of SCT AND - issuanceTime < CFDateGetAbsoluteTime(expiry)) { // at the time of issuance.) - once_or_current_qualified_embedded++; - trustedSCTCount++; - } else { - failed_once_check = true; - } - }); - - SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) { - int _lifetime; - CFCalendarGetComponentDifference(zuluCalendar, - SecCertificateNotValidBefore(leafCert), - SecCertificateNotValidAfter(leafCert), - 0, "M", &_lifetime); - lifetime = _lifetime; - }); - - unsigned requiredEmbeddedSctsCount; - - if (lifetime < 15) { - requiredEmbeddedSctsCount = 2; - } else if (lifetime <= 27) { - requiredEmbeddedSctsCount = 3; - } else if (lifetime <= 39) { - requiredEmbeddedSctsCount = 4; - } else { - requiredEmbeddedSctsCount = 5; - } - - if(once_or_current_qualified_embedded >= requiredEmbeddedSctsCount){ - SecCertificatePathVCSetIsCT(path, true); - } else { - /* Not enough "once or currently qualified" SCTs */ - if (failed_once_check) { - failureReason = TA_CTEmbeddedNotEnoughDisqualified; - } else if (unknown_log) { - failureReason = TA_CTEmbeddedNotEnoughUnknown; - } else { - failureReason = TA_CTEmbeddedNotEnough; - } - } - } else if (!at_least_one_currently_valid_embedded && !at_least_one_currently_valid_external) { - /* No currently valid SCTs */ - if (disqualified_log) { - failureReason = TA_CTNoCurrentSCTsDisqualifiedLog; - } else if (unknown_log) { - failureReason = TA_CTNoCurrentSCTsUnknownLog; - } - } else if (at_least_one_currently_valid_external) { - /* One presented current SCT but failed total current check */ - if (disqualified_log) { - failureReason = TA_CTPresentedNotEnoughDisqualified; - } else if (unknown_log) { - failureReason = TA_CTPresentedNotEnoughUnknown; - } else { - failureReason = TA_CTPresentedNotEnough; - } - } - - /* Record analytics data for CT */ - TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(pvc->builder); - require_quiet(analytics, out); - uint32_t sctCount = 0; - /* Count the total number of SCTs we found and report where we got them */ - if (embeddedScts && CFArrayGetCount(embeddedScts) > 0) { - analytics->sct_sources |= TA_SCTEmbedded; - sctCount += CFArrayGetCount(embeddedScts); - } - if (builderScts && CFArrayGetCount(builderScts) > 0) { - analytics->sct_sources |= TA_SCT_TLS; - sctCount += CFArrayGetCount(builderScts); - } - if (ocspScts && CFArrayGetCount(ocspScts) > 0) { - analytics->sct_sources |= TA_SCT_OCSP; - sctCount += CFArrayGetCount(ocspScts); - } - /* Report how many of those SCTs were once or currently qualified */ - analytics->number_trusted_scts = trustedSCTCount; - /* Report how many SCTs we got */ - analytics->number_scts = sctCount; - /* Why we failed */ - analytics->ct_failure_reason = failureReason; - /* Only one current SCT -- close to failure */ - if (CFDictionaryGetCount(currentLogsValidatingScts) == 1) { - analytics->ct_one_current = true; - } -out: - CFReleaseSafe(logsValidatingEmbeddedScts); - CFReleaseSafe(currentLogsValidatingScts); - CFReleaseSafe(builderScts); - CFReleaseSafe(embeddedScts); - CFReleaseSafe(ocspScts); - CFReleaseSafe(precertEntry); - CFReleaseSafe(trustedLogs); - CFReleaseSafe(x509Entry); -} - static bool checkPolicyOidData(SecPVCRef pvc, CFDataRef oid) { CFIndex ix, count = SecPVCGetCertificateCount(pvc); DERItem key_value; @@ -1984,14 +1437,14 @@ static void SecPolicyCheckKeySize(SecPVCRef pvc, CFStringRef key) { SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0); /* Don't check key size for user-anchored leafs */ -#if TARGET_OS_IPHONE - SecCertificateSourceRef userSource = kSecUserAnchorSource; -#else - SecCertificateSourceRef userSource = kSecLegacyAnchorSource; -#endif - if (SecPVCIsAnchorPerConstraints(pvc, userSource, leaf)) { + if (SecPVCIsAnchorPerConstraints(pvc, kSecUserAnchorSource, leaf)) { return; } +#if TARGET_OS_OSX + if (SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, leaf)) { + return; + } +#endif for (ix = 0; ix < count; ++ix) { SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix); @@ -2020,10 +1473,10 @@ static void SecPolicyCheckSignatureHashAlgorithms(SecPVCRef pvc, CFIndex ix = 0, count = SecPVCGetCertificateCount(pvc); /* Ignore (a non-self-signed) anchor if it's trusted by the user */ -#if TARGET_OS_IPHONE bool userAnchored = SecPVCIsAnchorPerConstraints(pvc, kSecUserAnchorSource, SecPVCGetCertificateAtIndex(pvc, count - 1)); -#else - bool userAnchored = SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, SecPVCGetCertificateAtIndex(pvc, count - 1)); +#if TARGET_OS_OSX + userAnchored = userAnchored || SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, + SecPVCGetCertificateAtIndex(pvc, count - 1)); #endif if (SecPathBuilderIsAnchored(pvc->builder) && userAnchored) { count--; @@ -2178,7 +1631,7 @@ static bool is_configured_test_system_root(SecCertificateRef root, CFStringRef p CFDataRef rootHash = SecCertificateCopySHA256Digest(root); CFTypeRef value = CFPreferencesCopyAppValue(preference, CFSTR("com.apple.security")); require_quiet(isData(value), out); - require_quiet(kCFCompareEqualTo == CFDataCompare(rootHash, value), out); + require_quiet(CFEqual(rootHash, value), out); result = true; out: @@ -2408,6 +1861,7 @@ out: static bool SecPolicyCheckSystemTrustValidityPeriodMaximums(CFAbsoluteTime notBefore, CFAbsoluteTime notAfter) { CFAbsoluteTime jul2016 = 489024000.0; // 1 July 2016 00:00:00 UTC CFAbsoluteTime mar2018 = 541555200.0; // 1 March 2018 00:00:00 UTC + CFAbsoluteTime sep2020 = 620611200.0; // 1 September 2020 00:00:00 UTC if (notBefore < jul2016) { /* Validity Period no greater than 60 months. 60 months is no more than 5 years and 2 leap days (and 1 hour slip). */ @@ -2425,13 +1879,20 @@ static bool SecPolicyCheckSystemTrustValidityPeriodMaximums(CFAbsoluteTime notBe secnotice("policy", "System-trusted leaf validity period longer than 39 months and issued after 30 June 2016"); return false; } - } else { + } else if (notBefore < sep2020) { /* Validity Period no greater than 825 days (and 1 hour slip). */ CFAbsoluteTime maxPeriod = 60*60*24*825 + 3600; if (notAfter - notBefore > maxPeriod) { secnotice("policy", "System-trusted leaf validity period longer than 825 days and issued on or after 1 March 2018"); return false; } + } else { + /* Validity Period no greater than 398 days (and no slip). HT211025 */ + CFAbsoluteTime maxPeriod = 60*60*24*398; + if (notAfter - notBefore > maxPeriod) { + secnotice("policy", "System-trusted leaf validity period longer than 398 days and issued on or after 1 September 2020"); + return false; + } } return true; } @@ -2471,14 +1932,14 @@ static void SecPolicyCheckValidityPeriodMaximums(SecPVCRef pvc, CFStringRef key) } /* Don't check validity periods against maximums for user-anchored leafs */ -#if TARGET_OS_IPHONE - SecCertificateSourceRef userSource = kSecUserAnchorSource; -#else - SecCertificateSourceRef userSource = kSecLegacyAnchorSource; -#endif - if (SecPVCIsAnchorPerConstraints(pvc, userSource, leaf)) { + if (SecPVCIsAnchorPerConstraints(pvc, kSecUserAnchorSource, leaf)) { return; } +#if TARGET_OS_OSX + if (SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, leaf)) { + return; + } +#endif /* all other trust */ if (!SecPolicyCheckOtherTrustValidityPeriodMaximums(notBefore, notAfter)) { @@ -2498,18 +1959,33 @@ static void SecPolicyCheckServerAuthEKU(SecPVCRef pvc, CFStringRef key) { if (!SecPolicyCheckCertExtendedKeyUsage(leaf, CFSTR("1.3.6.1.5.5.7.3.1"))) { // server auth EKU SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); } + /* if any subCA cert has an EKU, it must have the server auth EKU */ + if (count > 2) { // chain has subCAs + for (int ix = 1; ix < count - 1; ix++) { // iterate through subCAs + SecCertificateRef subCA = SecPVCGetCertificateAtIndex(pvc, ix); + CFArrayRef eku = NULL; + if ((eku = SecCertificateCopyExtendedKeyUsage(subCA)) && CFArrayGetCount(eku)) { // subCA has EKU set + if (!SecPolicyCheckCertExtendedKeyUsage(subCA, CFSTR("1.3.6.1.5.5.7.3.1")) && // check server auth EKU + !SecPolicyCheckCertExtendedKeyUsage(subCA, CFSTR("2.5.29.37.0"))) { // check anyEKU + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + } + } + CFReleaseNull(eku); + } + } return; } /* skip user/admin-anchored chains */ -#if TARGET_OS_IPHONE - SecCertificateSourceRef userSource = kSecUserAnchorSource; -#else - SecCertificateSourceRef userSource = kSecLegacyAnchorSource; -#endif - if (SecPVCIsAnchorPerConstraints(pvc, userSource, root)) { + if (SecPVCIsAnchorPerConstraints(pvc, kSecUserAnchorSource, root)) { return; } +#if TARGET_OS_OSX + if (SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, root)) { + return; + } +#endif + /* All other anchor types must be compliant if issued on or after 1 July 2019 */ CFAbsoluteTime notBefore = SecCertificateNotValidBefore(leaf); @@ -2521,6 +1997,33 @@ static void SecPolicyCheckServerAuthEKU(SecPVCRef pvc, CFStringRef key) { } } +static void SecPolicyCheckCTRequired(SecPVCRef pvc, CFStringRef key) { + SecCertificatePathVCRef path = SecPathBuilderGetPath(pvc->builder); + SecCertificatePathVCSetRequiresCT(path, kSecPathCTRequiredOverridable); +} + +static void SecPolicyCheckNotCA(SecPVCRef pvc, CFStringRef key) { + SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0); + if (SecCertificateIsCA(leaf)) { + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + } +} + +static void SecPolicyCheckNonTlsCTRequired(SecPVCRef pvc, CFStringRef key) { + // Skip if kill switch enabled or log list not updated + SecOTAPKIRef otaref = SecOTAPKICopyCurrentOTAPKIRef(); + CFDictionaryRef trustedLogs = SecPathBuilderCopyTrustedLogs(pvc->builder); + if (!SecOTAPKIKillSwitchEnabled(otaref, kOTAPKIKillSwitchNonTLSCT) && + (SecOTAPKIAssetStalenessLessThanSeconds(otaref, kSecOTAPKIAssetStalenessDisable) || trustedLogs)) { + // Check CT against the non-TLS log list + if (!SecPolicyCheckNonTlsCT(pvc)) { + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + } + } + CFReleaseNull(otaref); + CFReleaseNull(trustedLogs); +} + void SecPolicyServerInitialize(void) { gSecPolicyLeafCallbacks = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); @@ -2611,15 +2114,15 @@ SecPolicyRef SecPVCGetPolicy(SecPVCRef pvc) { return (SecPolicyRef)CFArrayGetValueAtIndex(pvc->policies, pvc->policyIX); } -static CFIndex SecPVCGetCertificateCount(SecPVCRef pvc) { +CFIndex SecPVCGetCertificateCount(SecPVCRef pvc) { return SecPathBuilderGetCertificateCount(pvc->builder); } -static SecCertificateRef SecPVCGetCertificateAtIndex(SecPVCRef pvc, CFIndex ix) { +SecCertificateRef SecPVCGetCertificateAtIndex(SecPVCRef pvc, CFIndex ix) { return SecPathBuilderGetCertificateAtIndex(pvc->builder, ix); } -static CFAbsoluteTime SecPVCGetVerifyTime(SecPVCRef pvc) { +CFAbsoluteTime SecPVCGetVerifyTime(SecPVCRef pvc) { return SecPathBuilderGetVerifyTime(pvc->builder); } @@ -2635,6 +2138,9 @@ static bool SecPVCIsExceptedError(SecPVCRef pvc, CFIndex ix, CFStringRef key, CF */ #if TARGET_OS_OSX CFDictionaryRef options = CFArrayGetValueAtIndex(exceptions, 0); + if (!isDictionary(options)) { + return false; + } /* Type 2 */ if (exceptionsCount == 1 && (ix > 0 || !CFDictionaryContainsKey(options, kSecCertificateDetailSHA1Digest))) { /* SHA1Digest not allowed */ @@ -2665,6 +2171,9 @@ static bool SecPVCIsExceptedError(SecPVCRef pvc, CFIndex ix, CFStringRef key, CF /* Type 1 */ if (ix >= exceptionsCount) { return false; } CFDictionaryRef exception = CFArrayGetValueAtIndex(exceptions, ix); + if (!isDictionary(exception)) { + return false; + } /* Compare the cert hash */ if (!CFDictionaryContainsKey(exception, kSecCertificateDetailSHA1Digest)) { return false; } @@ -2783,8 +2292,8 @@ if (__PC_TYPE_MEMBER_##TRUSTRESULT && CFEqual(key,CFSTR(#NAME))) { \ policy->_options is a caller provided dictionary, only its cf type has been checked. */ -bool SecPVCSetResultForced(SecPVCRef pvc, - CFStringRef key, CFIndex ix, CFTypeRef result, bool force) { +bool SecPVCSetResultForcedWithTrustResult(SecPVCRef pvc, CFStringRef key, CFIndex ix, CFTypeRef result, bool force, + SecTrustResultType overrideDefaultTR) { /* If this is not something the current policy cares about ignore this error and return true so our caller continues evaluation. */ @@ -2797,17 +2306,27 @@ bool SecPVCSetResultForced(SecPVCRef pvc, } } - /* Check to see if the SecTrustSettings for the certificate in question - tell us to ignore this error. */ - if (SecPVCIsAllowedError(pvc, ix, key)) { - secinfo("policy", "cert[%d]: skipped allowed error %@", (int) ix, key); - return true; - } + /* Get the default trust result for this key and override it if the caller needs to + * set a different trust result than the default. */ + SecTrustResultType trustResult = trust_result_for_key(key); + if (overrideDefaultTR != kSecTrustResultInvalid) { + trustResult = overrideDefaultTR; + } - /* Check to see if exceptions tells us to ignore this error. */ - if (SecPVCIsExceptedError(pvc, ix, key, result)) { - secinfo("policy", "cert[%d]: skipped exception error %@", (int) ix, key); - return true; + /* only recoverable errors can be allowed/excepted */ + if (trustResult == kSecTrustResultRecoverableTrustFailure) { + /* Check to see if the SecTrustSettings for the certificate in question + tell us to ignore this error. */ + if (SecPVCIsAllowedError(pvc, ix, key)) { + secinfo("policy", "cert[%d]: skipped allowed error %@", (int) ix, key); + return true; + } + + /* Check to see if exceptions tells us to ignore this error. */ + if (SecPVCIsExceptedError(pvc, ix, key, result)) { + secinfo("policy", "cert[%d]: skipped exception error %@", (int) ix, key); + return true; + } } secnotice("policy", "cert[%d]: %@ =(%s)[%s]> %@", (int) ix, key, @@ -2817,7 +2336,6 @@ bool SecPVCSetResultForced(SecPVCRef pvc, (force ? "force" : ""), result); /* Avoid resetting deny or fatal to recoverable */ - SecTrustResultType trustResult = trust_result_for_key(key); if (SecPVCIsOkResult(pvc) || trustResult == kSecTrustResultFatalTrustFailure) { pvc->result = trustResult; } else if (trustResult == kSecTrustResultDeny && @@ -2843,6 +2361,10 @@ bool SecPVCSetResultForced(SecPVCRef pvc, return true; } +bool SecPVCSetResultForced(SecPVCRef pvc, CFStringRef key, CFIndex ix, CFTypeRef result, bool force) { + return SecPVCSetResultForcedWithTrustResult(pvc, key, ix, result, force, kSecTrustResultInvalid); +} + bool SecPVCSetResult(SecPVCRef pvc, CFStringRef key, CFIndex ix, CFTypeRef result) { return SecPVCSetResultForced(pvc, key, ix, result, false); @@ -2932,7 +2454,6 @@ bool SecPVCParentCertificateChecks(SecPVCRef pvc, CFIndex ix) { CFAbsoluteTime verifyTime = SecPVCGetVerifyTime(pvc); SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix); CFIndex anchor_ix = SecPVCGetCertificateCount(pvc) - 1; - bool is_anchor = (ix == anchor_ix && SecPathBuilderIsAnchored(pvc->builder)); if (!SecCertificateIsValid(cert, verifyTime)) { /* Certificate has expired. */ @@ -2955,51 +2476,44 @@ bool SecPVCParentCertificateChecks(SecPVCRef pvc, CFIndex ix) { } } - if (is_anchor) { - /* Perform anchor specific checks. */ - /* Don't think we have any of these. */ - } else { - /* Perform intermediate specific checks. */ - - /* (k) Basic constraints only relevant for v3 and later. */ - if (SecCertificateVersion(cert) >= 3) { - const SecCEBasicConstraints *bc = - SecCertificateGetBasicConstraints(cert); - if (!bc) { - /* Basic constraints not present, illegal. */ - if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraints, - ix, kCFBooleanFalse, true)) { - goto errOut; - } - } else if (!bc->isCA) { - /* Basic constraints not marked as isCA, illegal. */ - if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraintsCA, - ix, kCFBooleanFalse, true)) { - goto errOut; - } - } - } - /* For a v1 or v2 certificate in an intermediate slot (not a leaf and - not an anchor), we additionally require that the certificate chain - does not end in a v3 or later anchor. [rdar://32204517] */ - else if (ix > 0 && ix < anchor_ix) { - SecCertificateRef anchor = SecPVCGetCertificateAtIndex(pvc, anchor_ix); - if (SecCertificateVersion(anchor) >= 3) { - if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraints, - ix, kCFBooleanFalse, true)) { - goto errOut; - } - } - } - /* (l) max_path_length is checked elsewhere. */ - - /* (n) If a key usage extension is present, verify that the keyCertSign bit is set. */ - SecKeyUsage keyUsage = SecCertificateGetKeyUsage(cert); - if (keyUsage && !(keyUsage & kSecKeyUsageKeyCertSign)) { - if (!SecPVCSetResultForced(pvc, kSecPolicyCheckKeyUsage, - ix, kCFBooleanFalse, true)) { + /* (k) Basic constraints only relevant for v3 and later. */ + if (SecCertificateVersion(cert) >= 3) { + const SecCEBasicConstraints *bc = + SecCertificateGetBasicConstraints(cert); + if (!bc) { + /* Basic constraints not present, illegal. */ + if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraints, + ix, kCFBooleanFalse, true)) { goto errOut; } + } else if (!bc->isCA) { + /* Basic constraints not marked as isCA, illegal. */ + if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraintsCA, + ix, kCFBooleanFalse, true)) { + goto errOut; + } + } + } + /* For a v1 or v2 certificate in an intermediate slot (not a leaf and + not an anchor), we additionally require that the certificate chain + does not end in a v3 or later anchor. [rdar://32204517] */ + else if (ix > 0 && ix < anchor_ix) { + SecCertificateRef anchor = SecPVCGetCertificateAtIndex(pvc, anchor_ix); + if (SecCertificateVersion(anchor) >= 3) { + if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicConstraints, + ix, kCFBooleanFalse, true)) { + goto errOut; + } + } + } + /* (l) max_path_length is checked elsewhere. */ + + /* (n) If a key usage extension is present, verify that the keyCertSign bit is set. */ + SecKeyUsage keyUsage = SecCertificateGetKeyUsage(cert); + if (keyUsage && !(keyUsage & kSecKeyUsageKeyCertSign)) { + if (!SecPVCSetResultForced(pvc, kSecPolicyCheckKeyUsage, + ix, kCFBooleanFalse, true)) { + goto errOut; } } @@ -3291,7 +2805,7 @@ static bool SecPVCCallerIsApplication(CFDataRef clientAuditToken, CFTypeRef appR SecRequirementRef requirement = NULL; CFStringRef stringRequirement = NULL; - require(appRef && clientAuditToken, out); + require_quiet(appRef && clientAuditToken, out); require(CFGetTypeID(appRef) == SecTrustedApplicationGetTypeID(), out); require_noerr(SecTrustedApplicationCopyRequirement((SecTrustedApplicationRef)appRef, &requirement), out); require(requirement, out); @@ -3479,16 +2993,16 @@ static void SecPVCCheckUsageConstraints(SecPVCRef pvc) { /* If we already think the PVC is ok and this cert is from one of the user/ * admin anchor sources, trustRoot, trustAsRoot, and Invalid (no constraints), * all mean we should use the special "Proceed" trust result. */ -#if TARGET_OS_IPHONE if (SecPathBuilderIsAnchorSource(pvc->builder, kSecUserAnchorSource) && - SecCertificateSourceContains(kSecUserAnchorSource, cert)) -#else - if (SecPathBuilderIsAnchorSource(pvc->builder, kSecLegacyAnchorSource) && - SecCertificateSourceContains(kSecLegacyAnchorSource, cert)) -#endif - { + SecCertificateSourceContains(kSecUserAnchorSource, cert)) { pvc->result = kSecTrustResultProceed; } +#if TARGET_OS_OSX + if (SecPathBuilderIsAnchorSource(pvc->builder, kSecLegacyAnchorSource) && + SecCertificateSourceContains(kSecLegacyAnchorSource, cert)) { + pvc->result = kSecTrustResultProceed; + } +#endif } } } @@ -3569,7 +3083,10 @@ static void SecPVCCheckIssuerDateConstraints(SecPVCRef pvc) { } } -static bool SecPVCIsSSLServerAuthenticationPolicy(SecPVCRef pvc) { +static bool SecPVCPolicyPermitsCTRequired(SecPVCRef pvc) { +#if TARGET_OS_BRIDGE + return false; +#else // !TARGET_OS_BRIDGE if (!pvc || !pvc->policies) { return false; } @@ -3577,15 +3094,22 @@ static bool SecPVCIsSSLServerAuthenticationPolicy(SecPVCRef pvc) { if (!policy) { return false; } + // SSL policy CFStringRef policyName = SecPolicyGetName(policy); if (CFEqualSafe(policyName, kSecPolicyNameSSLServer)) { return true; } + // SSL policy by another name CFDictionaryRef options = policy->_options; if (options && CFDictionaryGetValue(options, kSecPolicyCheckSSLHostname)) { return true; } + // Policy explicitly requires CT + if (options && CFDictionaryGetValue(options, kSecPolicyCheckCTRequired)) { + return true; + } return false; +#endif // !TARGET_OS_BRIDGE } /* ASSUMPTIONS: @@ -3604,7 +3128,7 @@ static void SecPVCCheckRequireCTConstraints(SecPVCRef pvc) { Note that CT will already be required if there is a not-after date constraint present (set in SecRVCProcessValidDateConstraints). */ - if (SecPVCIsSSLServerAuthenticationPolicy(pvc)) { + if (SecPVCPolicyPermitsCTRequired(pvc)) { CFIndex ix, certCount = SecCertificatePathVCGetCount(path); SecCertificateRef certificate = SecPathBuilderGetCertificateAtIndex(pvc->builder, 0); CFAbsoluteTime earliestNotAfter = 31556908800.0; /* default: 3001-01-01 00:00:00-0000 */ @@ -3639,25 +3163,27 @@ static void SecPVCCheckRequireCTConstraints(SecPVCRef pvc) { /* Path is not CT validated, so check if CT was required. */ SecPathCTPolicy ctp = SecCertificatePathVCRequiresCT(path); - if (ctp <= kSecPathCTNotRequired || !SecPVCIsSSLServerAuthenticationPolicy(pvc)) { + if (ctp <= kSecPathCTNotRequired || !SecPVCPolicyPermitsCTRequired(pvc)) { return; } /* We need to have a recent log list or the CT check may have failed due to the list being out of date. * Also, honor the CT kill switch. */ SecOTAPKIRef otaref = SecOTAPKICopyCurrentOTAPKIRef(); + CFDictionaryRef trustedLogs = SecPathBuilderCopyTrustedLogs(pvc->builder); if (!SecOTAPKIKillSwitchEnabled(otaref, kOTAPKIKillSwitchCT) && - SecOTAPKIAssetStalenessLessThanSeconds(otaref, kSecOTAPKIAssetStalenessDisable)) { + (SecOTAPKIAssetStalenessLessThanSeconds(otaref, kSecOTAPKIAssetStalenessDisable) || trustedLogs)) { /* CT was required. Error is always set on leaf certificate. */ - SecPVCSetResultForced(pvc, kSecPolicyCheckCTRequired, - 0, kCFBooleanFalse, true); if (ctp != kSecPathCTRequiredOverridable) { - /* Normally kSecPolicyCheckCTRequired is recoverable, - so need to manually change trust result here. */ - pvc->result = kSecTrustResultFatalTrustFailure; + /* Normally kSecPolicyCheckCTRequired is recoverable */ + SecPVCSetResultForcedWithTrustResult(pvc, kSecPolicyCheckCTRequired, 0, kCFBooleanFalse, true, + kSecTrustResultFatalTrustFailure); + } else { + SecPVCSetResultForced(pvc, kSecPolicyCheckCTRequired, 0, kCFBooleanFalse, true); } } CFReleaseNull(otaref); + CFReleaseNull(trustedLogs); } /* "Deep" copy the details array */ diff --git a/trust/trustd/SecPolicyServer.h b/trust/trustd/SecPolicyServer.h index fbeebb82..ab22155d 100644 --- a/trust/trustd/SecPolicyServer.h +++ b/trust/trustd/SecPolicyServer.h @@ -45,15 +45,17 @@ void SecPVCInit(SecPVCRef pvc, SecPathBuilderRef builder, CFArrayRef policies); void SecPVCDelete(SecPVCRef pvc); void SecPVCSetPath(SecPVCRef pvc, SecCertificatePathVCRef path); SecPolicyRef SecPVCGetPolicy(SecPVCRef pv); +SecCertificateRef SecPVCGetCertificateAtIndex(SecPVCRef pvc, CFIndex ix); +CFIndex SecPVCGetCertificateCount(SecPVCRef pvc); +CFAbsoluteTime SecPVCGetVerifyTime(SecPVCRef pvc); /* Set the string result as the reason for the sub policy check key failing. The policy check function should continue processing if this function returns true. */ -bool SecPVCSetResult(SecPVCRef pv, CFStringRef key, CFIndex ix, - CFTypeRef result); -bool SecPVCSetResultForced(SecPVCRef pvc, - CFStringRef key, CFIndex ix, CFTypeRef result, bool force); -bool SecPVCIsOkResult(SecPVCRef pvc); +bool SecPVCSetResult(SecPVCRef pv, CFStringRef key, CFIndex ix, CFTypeRef result); +bool SecPVCSetResultForced(SecPVCRef pvc, CFStringRef key, CFIndex ix, CFTypeRef result, bool force); +bool SecPVCSetResultForcedWithTrustResult(SecPVCRef pvc, CFStringRef key, CFIndex ix, CFTypeRef result, bool force, + SecTrustResultType overrideDefaultTR); /* Is the current result considered successful. */ bool SecPVCIsOkResult(SecPVCRef pvc); diff --git a/trust/trustd/SecRevocationDb.c b/trust/trustd/SecRevocationDb.c index b1019681..f950796c 100644 --- a/trust/trustd/SecRevocationDb.c +++ b/trust/trustd/SecRevocationDb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Apple Inc. All Rights Reserved. + * Copyright (c) 2016-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,6 +30,7 @@ #include "trust/trustd/OTATrustUtilities.h" #include "trust/trustd/SecRevocationNetworking.h" #include "trust/trustd/SecTrustLoggingServer.h" +#include "trust/trustd/trustdFileLocations.h" #include #include #include @@ -57,7 +58,6 @@ #include #include #include -#include #include #include #include @@ -203,6 +203,14 @@ static double htond(double h) { return n; } +/* Obtain swapped value of the 32-bit integer referenced by the given pointer. + Since a generic void or char pointer may not be aligned on a 4-byte boundary, + the UB sanitizer does not let us directly dereference it as *(uint32_t*). +*/ +static uint32_t SecSwapInt32Ptr(const void* P) { + uint32_t _i=0; memcpy(&_i,P,sizeof(_i)); return OSSwapInt32(_i); +} + // MARK: - // MARK: Valid definitions @@ -250,7 +258,7 @@ typedef CF_OPTIONS(CFOptionFlags, SecValidInfoFlags) { /* maximum allowed interval */ #define kSecMaxUpdateInterval (60.0 * 60 * 24 * 7) -#define kSecRevocationBasePath "/Library/Keychains/crls" +/* filenames we use, relative to revocation info directory */ #define kSecRevocationCurUpdateFile "update-current" #define kSecRevocationDbFileName "valid.sqlite3" #define kSecRevocationDbReplaceFile ".valid_replace" @@ -319,7 +327,7 @@ bool SecRevocationDbUpdateSchema(SecRevocationDbRef rdb); CFIndex SecRevocationDbGetUpdateFormat(void); bool _SecRevocationDbSetUpdateSource(SecRevocationDbConnectionRef dbc, CFStringRef source, CFErrorRef *error); bool SecRevocationDbSetUpdateSource(SecRevocationDbRef rdb, CFStringRef source); -CFStringRef SecRevocationDbCopyUpdateSource(void); +CF_RETURNS_RETAINED CFStringRef SecRevocationDbCopyUpdateSource(void); bool SecRevocationDbSetNextUpdateTime(CFAbsoluteTime nextUpdate, CFErrorRef *error); CFAbsoluteTime SecRevocationDbGetNextUpdateTime(void); dispatch_queue_t SecRevocationDbGetUpdateQueue(void); @@ -623,8 +631,7 @@ static bool SecValidUpdateProcessData(SecRevocationDbConnectionRef dbc, CFIndex SecError(errSecParam, error, CFSTR("SecValidUpdateProcessData: data length is too short")); return result; } - /* get length of signed data */ - uint32_t dataLength = OSSwapInt32(*((uint32_t *)p)); + uint32_t dataLength = SecSwapInt32Ptr(p); bytesRemaining -= sizeof(uint32_t); p += sizeof(uint32_t); @@ -632,7 +639,7 @@ static bool SecValidUpdateProcessData(SecRevocationDbConnectionRef dbc, CFIndex uint32_t plistCount = 1; uint32_t plistTotal = 1; if (format > kSecValidUpdateFormatG2) { - plistCount = OSSwapInt32(*((uint32_t *)p)); + plistCount = SecSwapInt32Ptr(p); plistTotal = plistCount; bytesRemaining -= sizeof(uint32_t); p += sizeof(uint32_t); @@ -652,7 +659,7 @@ static bool SecValidUpdateProcessData(SecRevocationDbConnectionRef dbc, CFIndex CFPropertyListRef propertyList = NULL; uint32_t plistLength = dataLength; if (format > kSecValidUpdateFormatG2) { - plistLength = OSSwapInt32(*((uint32_t *)p)); + plistLength = SecSwapInt32Ptr(p); bytesRemaining -= sizeof(uint32_t); p += sizeof(uint32_t); } @@ -802,6 +809,11 @@ static bool SecValidUpdateForceReplaceDatabase(void) { result = true; } if (fd >= 0) { + CFErrorRef error = NULL; + if (!TrustdChangeFileProtectionToClassD(utf8String, &error)) { + secerror("failed to change replace valid db flag protection class: %@", error); + CFReleaseNull(error); + } close(fd); } }); @@ -868,7 +880,12 @@ static bool SecValidUpdateSatisfiedLocally(CFStringRef server, CFIndex version, if (retval < 0) { secnotice("validupdate", "copyfile error %d", retval); } else { - result = true; + CFErrorRef localError = NULL; + result = TrustdChangeFileProtectionToClassD(path, &localError); + if (!result) { + secerror("failed to change protection class of copied valid snapshot: %@", localError); + CFReleaseNull(localError); + } } }); } @@ -938,6 +955,22 @@ static CFStringRef SecRevocationDbGetDefaultServer(void) { #endif } +static CF_RETURNS_RETAINED CFStringRef SecRevocationDbCopyServer(void) { + /* Prefer a in-process setting for the update server, as used in testing */ + CFTypeRef value = CFPreferencesCopyAppValue(kUpdateServerKey, kSecPrefsDomain); + if (!value) { + value = CFPreferencesCopyValue(kUpdateServerKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + } + CFStringRef server = NULL; + if (isString(value)) { + server = (CFStringRef)value; + } else { + CFReleaseNull(value); + server = CFRetainSafe(SecRevocationDbGetDefaultServer()); + } + return server; +} + void SecRevocationDbInitialize() { if (!isDbOwner()) { return; } os_transaction_t transaction = os_transaction_create("com.apple.trustd.valid.initialize"); @@ -983,17 +1016,16 @@ void SecRevocationDbInitialize() { } /* initialize database from local asset */ - CFTypeRef value = (CFStringRef)CFPreferencesCopyValue(kUpdateServerKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - CFStringRef server = (isString(value)) ? (CFStringRef)value : (CFStringRef)SecRevocationDbGetDefaultServer(); + CFStringRef server = SecRevocationDbCopyServer(); CFIndex version = 0; secnotice("validupdate", "initializing database"); if (!SecValidUpdateSatisfiedLocally(server, version, true)) { -#if !TARGET_OS_BRIDGE && !defined(DARLING) +#if !TARGET_OS_BRIDGE /* Schedule full update as a maintenance task */ (void)SecValidUpdateRequest(SecRevocationDbGetUpdateQueue(), server, version); #endif } - CFReleaseSafe(value); + CFReleaseSafe(server); os_release(transaction); } @@ -1116,6 +1148,56 @@ static CFStringRef SecValidInfoCopyFormatDescription(CFTypeRef cf, CFDictionaryR ============================================================================== */ +static CFIndex _SecRevocationDbGetUpdateVersion(CFStringRef server) { + // determine version of our current database + CFIndex version = SecRevocationDbGetVersion(); + secdebug("validupdate", "got version %ld from db", (long)version); + if (version <= 0) { + if (gLastVersion > 0) { + secdebug("validupdate", "error getting version; using last good version: %ld", (long)gLastVersion); + } + version = gLastVersion; + } + + // determine source of our current database + // (if this ever changes, we will need to reload the db) + CFStringRef db_source = SecRevocationDbCopyUpdateSource(); + if (!db_source) { + db_source = (CFStringRef) CFRetain(kValidUpdateProdServer); + } + + // determine whether we need to recreate the database + CFIndex db_version = SecRevocationDbGetSchemaVersion(); + CFIndex db_format = SecRevocationDbGetUpdateFormat(); + if (db_version < kSecRevocationDbSchemaVersion || + db_format < kSecRevocationDbUpdateFormat || + kCFCompareEqualTo != CFStringCompare(server, db_source, kCFCompareCaseInsensitive)) { + // we need to fully rebuild the db contents, so we set our version to 0. + version = gLastVersion = 0; + } + CFReleaseNull(db_source); + return version; +} + +static bool _SecRevocationDbIsUpdateEnabled(void) { + CFTypeRef value = NULL; + // determine whether update fetching is enabled +#if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE + // Valid update fetching was initially enabled on macOS 10.13 and iOS 11.0. + // This conditional has been changed to include every platform and version + // except for those where the db should not be updated over the air. + bool updateEnabled = true; +#else + bool updateEnabled = false; +#endif + value = (CFBooleanRef)CFPreferencesCopyValue(kUpdateEnabledKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + if (isBoolean(value)) { + updateEnabled = CFBooleanGetValue((CFBooleanRef)value); + } + CFReleaseNull(value); + return updateEnabled; +} + /* SecRevocationDbCheckNextUpdate returns true if we dispatched an update request, otherwise false. */ @@ -1172,61 +1254,17 @@ static bool _SecRevocationDbCheckNextUpdate(void) { gNextUpdate = minNextUpdate; // determine which server to query - CFStringRef server; - value = (CFStringRef)CFPreferencesCopyValue(kUpdateServerKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (isString(value)) { - server = (CFStringRef) CFRetain(value); - } else { - server = (CFStringRef) CFRetain(SecRevocationDbGetDefaultServer()); - } - CFReleaseNull(value); + CFStringRef server = SecRevocationDbCopyServer(); - // determine version of our current database - CFIndex version = SecRevocationDbGetVersion(); - secdebug("validupdate", "got version %ld from db", (long)version); - if (version <= 0) { - if (gLastVersion > 0) { - secdebug("validupdate", "error getting version; using last good version: %ld", (long)gLastVersion); - } - version = gLastVersion; - } + // determine version to update from + CFIndex version = _SecRevocationDbGetUpdateVersion(server); - // determine source of our current database - // (if this ever changes, we will need to reload the db) - CFStringRef db_source = SecRevocationDbCopyUpdateSource(); - if (!db_source) { - db_source = (CFStringRef) CFRetain(kValidUpdateProdServer); - } - - // determine whether we need to recreate the database - CFIndex db_version = SecRevocationDbGetSchemaVersion(); - CFIndex db_format = SecRevocationDbGetUpdateFormat(); - if (db_version < kSecRevocationDbSchemaVersion || - db_format < kSecRevocationDbUpdateFormat || - kCFCompareEqualTo != CFStringCompare(server, db_source, kCFCompareCaseInsensitive)) { - // we need to fully rebuild the db contents, so we set our version to 0. - version = gLastVersion = 0; - } - - // determine whether update fetching is enabled -#if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE && !defined(DARLING) - // Valid update fetching was initially enabled on macOS 10.13 and iOS 11.0. - // This conditional has been changed to include every platform and version - // except for those where the db should not be updated over the air. - bool updateEnabled = true; -#else - bool updateEnabled = false; -#endif - value = (CFBooleanRef)CFPreferencesCopyValue(kUpdateEnabledKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (isBoolean(value)) { - updateEnabled = CFBooleanGetValue((CFBooleanRef)value); - } - CFReleaseNull(value); + // determine if update is enabled for this device + bool updateEnabled = _SecRevocationDbIsUpdateEnabled(); // Schedule maintenance work bool result = SecValidUpdateSchedule(updateEnabled, server, version); CFReleaseNull(server); - CFReleaseNull(db_source); return result; } @@ -1246,6 +1284,26 @@ void SecRevocationDbCheckNextUpdate(void) { sec_action_perform(action); } +bool SecRevocationDbUpdate(CFErrorRef *error) +{ + // are we the db owner instance? + if (!isDbOwner()) { + return SecError(errSecWrPerm, error, CFSTR("Unable to update Valid DB from user agent")); + } + + if (!_SecRevocationDbIsUpdateEnabled()) { + return SecError(errSecWrPerm, error, CFSTR("Valid updates not enabled on this device")); + } + + CFStringRef server = SecRevocationDbCopyServer(); + CFIndex version = _SecRevocationDbGetUpdateVersion(server); + + secdebug("validupdate", "will fetch v%lu from \"%@\" now", (unsigned long)version, server); + bool result = SecValidUpdateUpdateNow(SecRevocationDbGetUpdateQueue(), server, version); + CFReleaseNull(server); + return result; +} + /* This function verifies an update, in this format: 1) unsigned 32-bit network-byte-order length of binary plist 2) binary plist data @@ -1258,7 +1316,7 @@ bool SecRevocationDbVerifyUpdate(void *update, CFIndex length) { if (!update || length <= (CFIndex)sizeof(uint32_t)) { return false; } - uint32_t plistLength = OSSwapInt32(*((uint32_t *)update)); + uint32_t plistLength = SecSwapInt32Ptr(update); if ((plistLength + (CFIndex)(sizeof(uint32_t)*2)) > (uint64_t) length) { secdebug("validupdate", "ERROR: reported plist length (%lu)+%lu exceeds total length (%lu)\n", (unsigned long)plistLength, (unsigned long)sizeof(uint32_t)*2, (unsigned long)length); @@ -1266,7 +1324,7 @@ bool SecRevocationDbVerifyUpdate(void *update, CFIndex length) { } uint8_t *plistData = (uint8_t *)update + sizeof(uint32_t); uint8_t *sigData = (uint8_t *)plistData + plistLength; - uint32_t sigLength = OSSwapInt32(*((uint32_t *)sigData)); + uint32_t sigLength = SecSwapInt32Ptr(sigData); sigData += sizeof(uint32_t); if ((plistLength + sigLength + (CFIndex)(sizeof(uint32_t) * 2)) != (uint64_t) length) { secdebug("validupdate", "ERROR: reported lengths do not add up to total length\n"); @@ -2387,10 +2445,10 @@ static bool _SecRevocationDbUpdateIssuers(SecRevocationDbConnectionRef dbc, int6 } static SecValidInfoFormat _SecRevocationDbGetGroupFormatForData(SecRevocationDbConnectionRef dbc, int64_t groupId, CFDataRef data) { - /* determine existing format if groupId is supplied and this is a partial update, + /* determine existing format if groupId is supplied, otherwise return the expected format for the given data. */ SecValidInfoFormat format = kSecValidInfoFormatUnknown; - if (groupId >= 0 && !dbc->fullUpdate) { + if (groupId >= 0) { format = _SecRevocationDbGetGroupFormat(dbc, groupId, NULL, NULL, NULL, NULL); } if (format == kSecValidInfoFormatUnknown && data != NULL) { @@ -2585,7 +2643,7 @@ static bool _SecRevocationDbUpdateDateConstraints(SecRevocationDbConnectionRef d return ok; /* no dates supplied, so we have nothing to update for this issuer */ } - if (!(notBeforeDate && notAfterDate) && !dbc->fullUpdate) { + if (!(notBeforeDate && notAfterDate)) { /* only one date was supplied, so check for existing date constraints */ CFDateRef curNotBeforeDate = NULL; CFDateRef curNotAfterDate = NULL; @@ -3168,8 +3226,8 @@ static bool _SecRevocationDbApplyGroupUpdate(SecRevocationDbConnectionRef dbc, C __block CFErrorRef localError = NULL; CFArrayRef issuers = (dict) ? (CFArrayRef)CFDictionaryGetValue(dict, CFSTR("issuer-hash")) : NULL; - /* if this is not a full update, then look for existing group id */ - if (ok && isArray(issuers) && !dbc->fullUpdate) { + /* look for existing group id */ + if (ok && isArray(issuers)) { CFIndex issuerIX, issuerCount = CFArrayGetCount(issuers); /* while we have issuers and haven't found a matching group id */ for (issuerIX=0; issuerIX #include #include +#include #include #include @@ -105,6 +106,12 @@ void SecValidInfoSetAnchor(SecValidInfoRef validInfo, SecCertificateRef anchor); */ void SecRevocationDbCheckNextUpdate(void); +/*! + @function SecRevocationDbUpdate + @abstract Trigger update now. For use in testing and tools. + */ +bool SecRevocationDbUpdate(CFErrorRef *error); + /*! @function SecRevocationDbCopyMatching @abstract Returns a SecValidInfo reference if matching revocation (or allow list) info was found. @@ -177,7 +184,7 @@ extern const CFStringRef kValidUpdateCarryServer; @abstract Returns the server source for updates of the revocation database. @result The base string of the server URI. */ -CFStringRef SecRevocationDbCopyUpdateSource(void); +CF_RETURNS_RETAINED CFStringRef SecRevocationDbCopyUpdateSource(void); __END_DECLS diff --git a/trust/trustd/SecRevocationNetworking.h b/trust/trustd/SecRevocationNetworking.h index e642f193..e87f9eb9 100644 --- a/trust/trustd/SecRevocationNetworking.h +++ b/trust/trustd/SecRevocationNetworking.h @@ -29,6 +29,7 @@ #import "trust/trustd/SecRevocationServer.h" bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex version); +bool SecValidUpdateUpdateNow(dispatch_queue_t queue, CFStringRef server, CFIndex version); bool SecORVCBeginFetches(SecORVCRef orvc, SecCertificateRef cert); #endif /* _SECURITY_SECREVOCATIONNETWORKING_H_ */ diff --git a/trust/trustd/SecRevocationNetworking.m b/trust/trustd/SecRevocationNetworking.m index c1852066..0f61efd0 100644 --- a/trust/trustd/SecRevocationNetworking.m +++ b/trust/trustd/SecRevocationNetworking.m @@ -41,9 +41,11 @@ #include "SecTrustServer.h" #include "SecOCSPRequest.h" #include "SecOCSPResponse.h" +#include "trustdFileLocations.h" #import "SecTrustLoggingServer.h" #import "TrustURLSessionDelegate.h" +#import "trust/trustd/TrustURLSessionCache.h" #import "SecRevocationNetworking.h" @@ -55,10 +57,6 @@ static CFStringRef kUpdateBackgroundKey = CFSTR("ValidUpdateBackground"); extern CFAbsoluteTime gUpdateStarted; extern CFAbsoluteTime gNextUpdate; -static int checkBasePath(const char *basePath) { - return mkpath_np((char*)basePath, 0755); -} - static uint64_t systemUptimeInSeconds() { struct timeval boottime; size_t tv_size = sizeof(boottime); @@ -180,9 +178,6 @@ didReceiveResponse:(NSURLResponse *)response session, dataTask, (long)[(NSHTTPURLResponse *)response statusCode], [response MIMEType], [response expectedContentLength]); - WithPathInRevocationInfoDirectory(NULL, ^(const char *utf8String) { - (void)checkBasePath(utf8String); - }); CFURLRef updateFileURL = SecCopyURLForFileInRevocationInfoDirectory(CFSTR("update-current")); self->_currentUpdateFileURL = (updateFileURL) ? CFBridgingRelease(updateFileURL) : nil; const char *updateFilePath = [self->_currentUpdateFileURL fileSystemRepresentation]; @@ -197,9 +192,8 @@ didReceiveResponse:(NSURLResponse *)response (void)remove(updateFilePath); int fd; - off_t off; fd = open(updateFilePath, O_RDWR | O_CREAT | O_TRUNC, 0644); - if (fd < 0 || (off = lseek(fd, 0, SEEK_SET)) < 0) { + if (fd < 0) { secnotice("validupdate","unable to open %@ (errno %d)", self->_currentUpdateFileURL, errno); } if (fd >= 0) { @@ -218,7 +212,7 @@ didReceiveResponse:(NSURLResponse *)response if (!self->_currentUpdateFile) { secnotice("validupdate", "failed to open %@: %@. canceling task %@", self->_currentUpdateFileURL, error, dataTask); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventValidUpdate hardFailure:NO result:error]; + [[TrustAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventValidUpdate hardFailure:NO result:error]; #endif // ENABLE_TRUSTD_ANALYTICS completionHandler(NSURLSessionResponseCancel); [self reschedule]; @@ -259,7 +253,7 @@ didCompleteWithError:(NSError *)error { if (error) { secnotice("validupdate", "Session %@ task %@ failed with error %@", session, task, error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventValidUpdate hardFailure:NO result:error]; + [[TrustAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventValidUpdate hardFailure:NO result:error]; #endif // ENABLE_TRUSTD_ANALYTICS [self reschedule]; /* close file before we leave */ @@ -288,30 +282,25 @@ didCompleteWithError:(NSError *)error { @interface ValidUpdateRequest : NSObject @property NSTimeInterval updateScheduled; @property NSURLSession *backgroundSession; +@property NSURLSession *ephemeralSession; @end static ValidUpdateRequest *request = nil; @implementation ValidUpdateRequest -- (NSURLSessionConfiguration *)validUpdateConfiguration { - /* preferences to override defaults */ - CFTypeRef value = NULL; - bool updateOnWiFiOnly = true; - value = CFPreferencesCopyValue(kUpdateWiFiOnlyKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (isBoolean(value)) { - updateOnWiFiOnly = CFBooleanGetValue((CFBooleanRef)value); - } - CFReleaseNull(value); - bool updateInBackground = true; - value = CFPreferencesCopyValue(kUpdateBackgroundKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (isBoolean(value)) { - updateInBackground = CFBooleanGetValue((CFBooleanRef)value); - } - CFReleaseNull(value); - +- (NSURLSessionConfiguration *)validUpdateConfiguration:(BOOL)background { NSURLSessionConfiguration *config = nil; - if (updateInBackground) { + if (background) { + /* preferences to override defaults */ + CFTypeRef value = NULL; + bool updateOnWiFiOnly = true; + value = CFPreferencesCopyValue(kUpdateWiFiOnlyKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + if (isBoolean(value)) { + updateOnWiFiOnly = CFBooleanGetValue((CFBooleanRef)value); + } + CFReleaseNull(value); + config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: @"com.apple.trustd.networking.background"]; config.networkServiceType = NSURLNetworkServiceTypeBackground; config.discretionary = YES; @@ -323,7 +312,7 @@ static ValidUpdateRequest *request = nil; config.discretionary = NO; } - config.HTTPAdditionalHeaders = @{ @"User-Agent" : @"com.apple.trustd/2.0", + config.HTTPAdditionalHeaders = @{ @"User-Agent" : TrustdUserAgent, @"Accept" : @"*/*", @"Accept-Encoding" : @"gzip,deflate,br"}; @@ -332,8 +321,9 @@ static ValidUpdateRequest *request = nil; return config; } -- (void) createSession:(dispatch_queue_t)updateQueue forServer:(NSString *)updateServer { - NSURLSessionConfiguration *config = [self validUpdateConfiguration]; +- (NSURLSession *)createSession:(BOOL)background queue:(dispatch_queue_t)updateQueue forServer:(NSString *)updateServer +{ + NSURLSessionConfiguration *config = [self validUpdateConfiguration:background]; ValidDelegate *delegate = [[ValidDelegate alloc] init]; delegate.handler = ^(void) { request.updateScheduled = 0.0; @@ -348,7 +338,23 @@ static ValidUpdateRequest *request = nil; We'll then dispatch the work on updateQueue and return from the callback. */ NSOperationQueue *queue = [[NSOperationQueue alloc] init]; queue.maxConcurrentOperationCount = 1; - _backgroundSession = [NSURLSession sessionWithConfiguration:config delegate:delegate delegateQueue:queue]; + return [NSURLSession sessionWithConfiguration:config delegate:delegate delegateQueue:queue]; +} + +- (void) createSessions:(dispatch_queue_t)updateQueue forServer:(NSString *)updateServer { + self.ephemeralSession = [self createSession:NO queue:updateQueue forServer:updateServer]; + + bool updateInBackground = true; + CFTypeRef value = CFPreferencesCopyValue(kUpdateBackgroundKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + if (isBoolean(value)) { + updateInBackground = CFBooleanGetValue((CFBooleanRef)value); + } + CFReleaseNull(value); + if (updateInBackground) { + self.backgroundSession = [self createSession:YES queue:updateQueue forServer:updateServer]; + } else { + self.backgroundSession = self.ephemeralSession; + } } - (BOOL) scheduleUpdateFromServer:(NSString *)server forVersion:(NSUInteger)version withQueue:(dispatch_queue_t)updateQueue { @@ -399,7 +405,7 @@ static ValidUpdateRequest *request = nil; }); if (!self.backgroundSession) { - [self createSession:updateQueue forServer:server]; + [self createSessions:updateQueue forServer:server]; } else { ValidDelegate *delegate = (ValidDelegate *)[self.backgroundSession delegate]; delegate.currentUpdateServer = [server copy]; @@ -424,20 +430,68 @@ static ValidUpdateRequest *request = nil; return YES; } + +- (BOOL)updateNowFromServer:(NSString *)server version:(NSUInteger)version queue:(dispatch_queue_t)updateQueue +{ + if (!server) { + secnotice("validupdate", "invalid update request"); + return NO; + } + + if (!updateQueue) { + secnotice("validupdate", "missing update queue, skipping update"); + return NO; + } + + if (!self.ephemeralSession) { + [self createSessions:updateQueue forServer:server]; + } else { + ValidDelegate *delegate = (ValidDelegate *)[self.ephemeralSession delegate]; + delegate.currentUpdateServer = [server copy]; + } + + /* POWER LOG EVENT: scheduling our background download session now */ + SecPLLogRegisteredEvent(@"ValidUpdateEvent", @{ + @"timestamp" : @([[NSDate date] timeIntervalSince1970]), + @"event" : @"downloadScheduled", + @"version" : @(version) + }); + + NSURL *validUrl = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@/g3/v%ld", + server, (unsigned long)version]]; + NSURLSessionDataTask *dataTask = [self.ephemeralSession dataTaskWithURL:validUrl]; + dataTask.taskDescription = [NSString stringWithFormat:@"%lu",(unsigned long)version]; + [dataTask resume]; + secnotice("validupdate", "running foreground data task %@ at %f", dataTask, CFAbsoluteTimeGetCurrent()); + return YES; +} + @end +static void SecValidUpdateCreateValidUpdateRequest() +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + @autoreleasepool { + request = [[ValidUpdateRequest alloc] init]; + } + }); +} + bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex version) { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - @autoreleasepool { - request = [[ValidUpdateRequest alloc] init]; - } - }); + SecValidUpdateCreateValidUpdateRequest(); @autoreleasepool { return [request scheduleUpdateFromServer:(__bridge NSString*)server forVersion:version withQueue:queue]; } } +bool SecValidUpdateUpdateNow(dispatch_queue_t queue, CFStringRef server, CFIndex version) { + SecValidUpdateCreateValidUpdateRequest(); + @autoreleasepool { + return [request updateNowFromServer:(__bridge NSString*)server version:version queue:queue]; + } +} + /* MARK: - */ /* MARK: OCSP Fetch Networking */ #define OCSP_REQUEST_THRESHOLD 10 @@ -446,19 +500,19 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v @end @implementation OCSPFetchDelegate -- (BOOL)fetchNext:(NSURLSession *)session { - SecORVCRef orvc = (SecORVCRef)self.context; +- (BOOL)fetchNext:(NSURLSession *)session context:(TrustURLSessionContext *)urlContext { + SecORVCRef orvc = (SecORVCRef)urlContext.context; TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(orvc->builder); BOOL result = true; - if ((result = [super fetchNext:session])) { + if ((result = [super fetchNext:session context:urlContext])) { /* no fetch scheduled */ orvc->done = true; } else { - if (self.URIix > 0) { - orvc->responder = (__bridge CFURLRef)self.URIs[self.URIix - 1]; + if (urlContext.URIix > 0) { + orvc->responder = (__bridge CFURLRef)urlContext.URIs[urlContext.URIix - 1]; } else { - orvc->responder = (__bridge CFURLRef)self.URIs[0]; + orvc->responder = (__bridge CFURLRef)urlContext.URIs[0]; } if (analytics) { analytics->ocsp_fetches++; @@ -471,9 +525,17 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v /* call the superclass's method to set expiration */ [super URLSession:session task:task didCompleteWithError:error]; - __block SecORVCRef orvc = (SecORVCRef)self.context; + NSUUID *taskId = [task.originalRequest taskId]; + TrustURLSessionContext *urlContext = [self contextForTask:taskId]; + if (!urlContext) { + secerror("failed to find context for %@", taskId); + return; + } + + __block SecORVCRef orvc = (SecORVCRef)urlContext.context; if (!orvc || !orvc->builder) { /* We already returned to the PathBuilder state machine. */ + [self removeTask:taskId]; return; } @@ -485,12 +547,12 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v analytics->ocsp_fetch_failed++; } } else { - SecOCSPResponseRef ocspResponse = SecOCSPResponseCreate((__bridge CFDataRef)self.response); + SecOCSPResponseRef ocspResponse = SecOCSPResponseCreate((__bridge CFDataRef)urlContext.response); if (ocspResponse) { - SecORVCConsumeOCSPResponse(orvc, ocspResponse, self.expiration, true, false); + SecORVCConsumeOCSPResponse(orvc, ocspResponse, urlContext.expiration, true, false); if (analytics && !orvc->done) { /* We got an OCSP response that didn't pass validation */ - analytics-> ocsp_validation_failed = true; + analytics->ocsp_validation_failed = true; } } else if (analytics) { /* We got something that wasn't an OCSP response (e.g. captive portal) -- @@ -501,15 +563,14 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v /* If we didn't get a valid OCSP response, try the next URI */ if (!orvc->done) { - (void)[self fetchNext:session]; + (void)[self fetchNext:session context:urlContext]; } /* We got a valid OCSP response or couldn't schedule any more fetches. * Close the session, update the PVCs, decrement the async count, and callback if we're all done. */ if (orvc->done) { secdebug("rvc", "builder %p, done with OCSP fetches for cert: %ld", orvc->builder, orvc->certIX); - self.context = nil; - [session invalidateAndCancel]; + urlContext.context = nil; SecORVCUpdatePVC(orvc); if (0 == SecPathBuilderDecrementAsyncJobCount(orvc->builder)) { /* We're the last async job to finish, jump back into the state machine */ @@ -519,10 +580,12 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v }); } } + // We've either kicked off a new task or returned to the builder, so we're done with this task. + [self removeTask:taskId]; } -- (NSURLRequest *)createNextRequest:(NSURL *)uri { - SecORVCRef orvc = (SecORVCRef)self.context; +- (NSURLRequest *)createNextRequest:(NSURL *)uri context:(TrustURLSessionContext *)urlContext { + SecORVCRef orvc = (SecORVCRef)urlContext.context; CFDataRef ocspDER = CFRetainSafe(SecOCSPRequestGetDER(orvc->ocspRequest)); NSData *nsOcspDER = CFBridgingRelease(ocspDER); NSString *ocspBase64 = [nsOcspDER base64EncodedStringWithOptions:0]; @@ -550,10 +613,10 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v /* Use a GET */ NSString *requestString = [NSString stringWithFormat:@"%@/%@", [uri absoluteString], escapedRequest]; NSURL *requestURL = [NSURL URLWithString:requestString]; - request = [NSURLRequest requestWithURL:requestURL]; + request = [super createNextRequest:requestURL context:urlContext]; } else { /* Use a POST */ - NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:uri]; + NSMutableURLRequest *mutableRequest = [[super createNextRequest:uri context:urlContext] mutableCopy]; mutableRequest.HTTPMethod = @"POST"; mutableRequest.HTTPBody = nsOcspDER; request = mutableRequest; @@ -563,8 +626,15 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)taskMetrics { + NSUUID *taskId = [task.originalRequest taskId]; + TrustURLSessionContext *urlContext = [self contextForTask:taskId]; + if (!urlContext) { + secerror("failed to find context for %@", taskId); + return; + } + secdebug("rvc", "got metrics with task interval %f", taskMetrics.taskInterval.duration); - SecORVCRef orvc = (SecORVCRef)self.context; + SecORVCRef orvc = (SecORVCRef)urlContext.context; if (orvc && orvc->builder) { TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(orvc->builder); if (analytics) { @@ -586,30 +656,17 @@ bool SecORVCBeginFetches(SecORVCRef orvc, SecCertificateRef cert) { return true; } - NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; - config.timeoutIntervalForResource = TrustURLSessionGetResourceTimeout(); - config.HTTPAdditionalHeaders = @{@"User-Agent" : @"com.apple.trustd/2.0"}; + static TrustURLSessionCache *sessionCache = NULL; + static OCSPFetchDelegate *delegate = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + delegate = [[OCSPFetchDelegate alloc] init]; + sessionCache = [[TrustURLSessionCache alloc] initWithDelegate:delegate]; + }); NSData *auditToken = CFBridgingRelease(SecPathBuilderCopyClientAuditToken(orvc->builder)); - if (auditToken) { - config._sourceApplicationAuditTokenData = auditToken; - } - - OCSPFetchDelegate *delegate = [[OCSPFetchDelegate alloc] init]; - delegate.context = orvc; - delegate.URIs = nsResponders; - delegate.URIix = 0; - - NSOperationQueue *queue = [[NSOperationQueue alloc] init]; - - NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:delegate delegateQueue:queue]; - secdebug("rvc", "created URLSession for %@", cert); - - bool result = false; - if ((result = [delegate fetchNext:session])) { - /* no fetch scheduled, close the session */ - [session invalidateAndCancel]; - } - return result; + NSURLSession *session = [sessionCache sessionForAuditToken:auditToken]; + TrustURLSessionContext *context = [[TrustURLSessionContext alloc] initWithContext:orvc uris:nsResponders]; + return [delegate fetchNext:session context:context]; } } diff --git a/trust/trustd/SecRevocationServer.c b/trust/trustd/SecRevocationServer.c index 266bdba3..c55c9b41 100644 --- a/trust/trustd/SecRevocationServer.c +++ b/trust/trustd/SecRevocationServer.c @@ -87,6 +87,7 @@ static bool SecOCSPSingleResponseProcess(SecOCSPSingleResponseRef this, in the info dictionary. */ //cert.revokeCheckGood(true); rvc->nextUpdate = this->nextUpdate == NULL_TIME ? this->thisUpdate + kSecDefaultOCSPResponseTTL : this->nextUpdate; + rvc->thisUpdate = this->thisUpdate; processed = true; break; case CS_Revoked: @@ -127,6 +128,7 @@ void SecORVCUpdatePVC(SecORVCRef rvc) { } if (rvc->ocspResponse) { rvc->nextUpdate = SecOCSPResponseGetExpirationTime(rvc->ocspResponse); + rvc->thisUpdate = SecOCSPResponseProducedAt(rvc->ocspResponse); } } @@ -285,10 +287,18 @@ void SecORVCConsumeOCSPResponse(SecORVCRef rvc, SecOCSPResponseRef ocspResponse sr->certStatus == CS_Revoked ? SecOCSPResponseProducedAt(ocspResponse) : verifyTime), errOut); #endif + TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(rvc->builder); + if (analytics && SecOCSPResponseIsWeakHash(ocspResponse)) { + analytics->ocsp_weak_hash = true; + } + // If we get here, we have a properly signed ocsp response // but we haven't checked dates yet. bool sr_valid = SecOCSPSingleResponseCalculateValidity(sr, kSecDefaultOCSPResponseTTL, verifyTime); + if (sr_valid) { + rvc->rvc->revocation_checked = true; + } if (sr->certStatus == CS_Good) { // Side effect of SecOCSPResponseCalculateValidity sets ocspResponse->expireTime require_quiet(sr_valid && SecOCSPResponseCalculateValidity(ocspResponse, maxAge, kSecDefaultOCSPResponseTTL, verifyTime), errOut); @@ -479,12 +489,11 @@ static void SecRVCProcessValidPolicyConstraints(SecRVCRef rvc) { SecPolicyRef policy = (SecPolicyRef)CFArrayGetValueAtIndex(policies, policyIX); if (!SecRVCPolicyConstraintsPermitPolicy(constraints, count, policy)) { policyDeniedByConstraints = true; - SecPVCSetResultForced(pvc, kSecPolicyCheckIssuerPolicyConstraints, rvc->certIX, - kCFBooleanFalse, true); - pvc->result = kSecTrustResultRecoverableTrustFailure; - if (!rvc->valid_info->overridable) { - /* error for this check should be non-recoverable */ - pvc->result = kSecTrustResultFatalTrustFailure; + if (rvc->valid_info->overridable) { + SecPVCSetResultForcedWithTrustResult(pvc, kSecPolicyCheckIssuerPolicyConstraints, rvc->certIX, + kCFBooleanFalse, true, kSecTrustResultRecoverableTrustFailure); + } else { + SecPVCSetResultForced(pvc, kSecPolicyCheckIssuerPolicyConstraints, rvc->certIX, kCFBooleanFalse, true); } } } @@ -614,6 +623,10 @@ void SecRVCSetValidDeterminedErrorResult(SecRVCRef rvc) { CFReleaseNull(cfreason); } +bool SecRVCRevocationChecked(SecRVCRef rvc) { + return rvc->revocation_checked; +} + static void SecRVCProcessValidInfoResults(SecRVCRef rvc) { if (!rvc || !rvc->valid_info || !rvc->builder) { return; @@ -645,6 +658,7 @@ static void SecRVCProcessValidInfoResults(SecRVCRef rvc) { } else if (allowed) { /* definitely not revoked (allowlisted) */ SecCertificatePathVCSetIsAllowlisted(path, true); + rvc->revocation_checked = true; } /* no-ca is definitive; no need to check further. */ secdebug("validupdate", "rvc: definitely %s cert %" PRIdCFIndex, @@ -1010,12 +1024,16 @@ bool SecPathBuilderCheckRevocation(SecPathBuilderRef builder) { * This check resolves unrevocation events after the nextUpdate time. */ bool old_cached_response = (!rvc->done && rvc->orvc->ocspResponse); + /* Check whether CA revocation additions match an issuer above us in this path. + * If so, we will attempt revocation checking below. */ + bool has_ca_revocation = (certIX < SecCertificatePathVCIndexOfCAWithRevocationAdditions(path)); + /* If the cert is EV or if revocation checking was explicitly enabled, attempt to fire off an async http request for this cert's revocation status, unless we already successfully checked the revocation status of this cert based on the cache or stapled responses. */ bool allow_fetch = SecRevocationCanAccessNetwork(builder, first_check_done) && (SecCertificatePathVCIsEV(path) || SecCertificatePathVCIsOptionallyEV(path) || - SecPathBuilderGetRevocationMethod(builder) || old_cached_response); + SecPathBuilderGetRevocationMethod(builder) || old_cached_response || has_ca_revocation); if (rvc->done || !allow_fetch) { /* We got a cache hit or we aren't allowed to access the network */ SecRVCUpdatePVC(rvc); @@ -1040,3 +1058,8 @@ CFAbsoluteTime SecRVCGetEarliestNextUpdate(SecRVCRef rvc) { enu = rvc->orvc->nextUpdate; return enu; } + +CFAbsoluteTime SecRVCGetLatestThisUpdate(SecRVCRef rvc) { + if (!rvc || !rvc->orvc) { return -DBL_MAX; } + return rvc->orvc->thisUpdate; +} diff --git a/trust/trustd/SecRevocationServer.h b/trust/trustd/SecRevocationServer.h index b3f7a090..7f43f9cb 100644 --- a/trust/trustd/SecRevocationServer.h +++ b/trust/trustd/SecRevocationServer.h @@ -52,6 +52,8 @@ struct OpaqueSecRVC { SecValidInfoRef valid_info; bool done; + + bool revocation_checked; }; typedef struct OpaqueSecRVC *SecRVCRef; @@ -75,7 +77,8 @@ struct OpaqueSecORVC { /* Index of cert in builder that this RVC is for 0 = leaf, etc. */ CFIndex certIX; - /* Date until which this revocation status is valid. */ + /* Validity period for which this revocation status. */ + CFAbsoluteTime thisUpdate; CFAbsoluteTime nextUpdate; /* URL of current responder. For logging purposes. */ @@ -87,10 +90,12 @@ struct OpaqueSecORVC { bool SecPathBuilderCheckRevocation(SecPathBuilderRef builder); void SecPathBuilderCheckKnownIntermediateConstraints(SecPathBuilderRef builder); CFAbsoluteTime SecRVCGetEarliestNextUpdate(SecRVCRef rvc); +CFAbsoluteTime SecRVCGetLatestThisUpdate(SecRVCRef rvc); void SecRVCDelete(SecRVCRef rvc); bool SecRVCHasDefinitiveValidInfo(SecRVCRef rvc); bool SecRVCHasRevokedValidInfo(SecRVCRef rvc); void SecRVCSetValidDeterminedErrorResult(SecRVCRef rvc); +bool SecRVCRevocationChecked(SecRVCRef rvc); /* OCSP verification callbacks */ void SecORVCConsumeOCSPResponse(SecORVCRef rvc, SecOCSPResponseRef ocspResponse /*CF_CONSUMED*/, diff --git a/trust/trustd/SecTrustExceptionResetCount.h b/trust/trustd/SecTrustExceptionResetCount.h index c9cd2dbb..1bf3130e 100644 --- a/trust/trustd/SecTrustExceptionResetCount.h +++ b/trust/trustd/SecTrustExceptionResetCount.h @@ -10,5 +10,6 @@ bool SecTrustServerIncrementExceptionResetCount(CFErrorRef *error); uint64_t SecTrustServerGetExceptionResetCount(CFErrorRef *error); +void SecTrustServerMigrateExceptionsResetCount(void); #endif /* SecTrustExceptionResetCount_h */ diff --git a/trust/trustd/SecTrustExceptionResetCount.m b/trust/trustd/SecTrustExceptionResetCount.m index 4552f3ce..23d8c1eb 100644 --- a/trust/trustd/SecTrustExceptionResetCount.m +++ b/trust/trustd/SecTrustExceptionResetCount.m @@ -8,167 +8,93 @@ #import #import +#import "trust/trustd/trustdFileLocations.h" static NSString *kExceptionResetCountKey = @"ExceptionResetCount"; static NSString *exceptionResetCounterFile = @"com.apple.security.exception_reset_counter.plist"; -/* Returns the path to the, existing or internally-created, 'exceptionResetCounterFile' file. */ -static NSString *SecPlistFileExistsInKeychainDirectory(CFErrorRef *error) { - NSString *status = NULL; - - NSString *path = [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)exceptionResetCounterFile) path]; - if (!path) { - secerror("Unable to address permanent storage for '%{public}@'.", exceptionResetCounterFile); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ENOENT, NULL); - } - return status; - } - secinfo("trust", "'%{public}@' is at '%{public}@'.", exceptionResetCounterFile, path); - - NSFileManager *fm = [NSFileManager defaultManager]; - if (!fm) { - secerror("Failed to initialize the file manager in '%{public}s'.", __func__); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ENOMEM, NULL); - } - return status; - } - - BOOL isDir = false; - bool fileExists = [fm fileExistsAtPath:path isDirectory:&isDir]; - if (isDir) { - secerror("'%{public}@' is a directory. (not a file)", path); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, EISDIR, NULL); - } - return status; - } - if (fileExists) { - secdebug("trust", "'%{public}@' already exists.", path); - status = path; - return status; - } - - if (![fm createFileAtPath:path contents:nil attributes:nil]) { - secerror("Failed to create permanent storage at '%{public}@'.", path); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, EIO, NULL); - } - return status; - } - secinfo("trust", "'%{public}@' has been created.", path); - status = path; - - return status; +static NSURL *ExceptionsResetCounterOldUrl (void) { + return CFBridgingRelease(SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)exceptionResetCounterFile)); } -static uint64_t SecReadPlistFromFileInKeychainDirectory(CFErrorRef *error) { - uint64_t value = 0; - - CFErrorRef localError = NULL; - NSString *path = SecPlistFileExistsInKeychainDirectory(&localError); - if (localError) { - if (error) { - *error = localError; - } - secerror("Permanent storage for the exceptions epoch is unavailable."); - return value; - } - if (!path) { - secinfo("trust", "Permanent storage for the exceptions epoch is missing. Defaulting to value %llu.", value); - return value; - } - - NSMutableDictionary *plDict = [NSMutableDictionary dictionaryWithContentsOfFile:path]; - if (!plDict) { - secerror("Failed to read from permanent storage at '%{public}@' or the data is bad. Defaulting to value %llu.", path, value); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ENXIO, NULL); - } - return value; - } - - id valueObject = [plDict objectForKey:kExceptionResetCountKey]; - if (!valueObject) { - secinfo("trust", "Could not find key '%{public}@'. Defaulting to value %llu.", kExceptionResetCountKey, value); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ENXIO, NULL); - } - return value; - } - if (![valueObject isKindOfClass:[NSNumber class]]) { - secerror("The value for key '%{public}@' is not a number.", kExceptionResetCountKey); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, EDOM, NULL); - } - return value; - } - - value = [valueObject unsignedIntValue]; - - secinfo("trust", "'%{public}@' is %llu.", kExceptionResetCountKey, value); - return value; +static NSURL *ExceptionsResetCounterUrl(void) { + return CFBridgingRelease(SecCopyURLForFileInPrivateUserTrustdDirectory((__bridge CFStringRef)exceptionResetCounterFile)); } -static bool SecWritePlistToFileInKeychainDirectory(uint64_t exceptionResetCount, CFErrorRef *error) { - bool status = false; - - CFErrorRef localError = NULL; - SecPlistFileExistsInKeychainDirectory(&localError); - if (localError) { - if (error) { - *error = localError; +static uint64_t ReadExceptionsCountFromUrl(NSURL *url, CFErrorRef *error) { + @autoreleasepool { + uint64_t value = 0; + NSError *nserror = nil; + NSMutableDictionary *plDict = [[NSDictionary dictionaryWithContentsOfURL:url error:&nserror] mutableCopy]; + if (!plDict) { + secerror("Failed to read from permanent storage at '%{public}@' or the data is bad. Defaulting to value %llu.", url, value); + if (error) { + *error = (CFErrorRef)CFBridgingRetain(nserror); + } + return value; } - secerror("Permanent storage for the exceptions epoch is unavailable."); + + id valueObject = [plDict objectForKey:kExceptionResetCountKey]; + if (!valueObject) { + secinfo("trust", "Could not find key '%{public}@'. Defaulting to value %llu.", kExceptionResetCountKey, value); + if (error) { + *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ENXIO, NULL); + } + return value; + } + if (![valueObject isKindOfClass:[NSNumber class]]) { + secerror("The value for key '%{public}@' is not a number.", kExceptionResetCountKey); + if (error) { + *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, EDOM, NULL); + } + return value; + } + + value = [valueObject unsignedIntValue]; + + secinfo("trust", "'%{public}@' is %llu.", kExceptionResetCountKey, value); + return value; + } +} + +static bool WriteExceptionsCounterToUrl(uint64_t exceptionResetCount, NSURL *url, CFErrorRef *error) { + @autoreleasepool { + bool status = false; + NSMutableDictionary *dataToSave = [NSMutableDictionary new]; + if (!dataToSave) { + secerror("Failed to allocate memory for the exceptions epoch structure."); + if (error) { + *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ENOMEM, NULL); + } + return status; + } + dataToSave[@"Version"] = [NSNumber numberWithUnsignedInteger:1]; + dataToSave[kExceptionResetCountKey] = [NSNumber numberWithUnsignedInteger:exceptionResetCount]; + + NSError *nserror = nil; + status = [dataToSave writeToClassDURL:url permissions:0600 error:&nserror]; + if (!status) { + secerror("Failed to write to permanent storage at '%{public}@'.", url); + if (error) { + *error = (CFErrorRef)CFBridgingRetain(nserror); + } + return status; + } + + secinfo("trust", "'%{public}@' has been committed to permanent storage at '%{public}@'.", kExceptionResetCountKey, url); return status; } - - NSString *path = [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)exceptionResetCounterFile) path]; - if (!path) { - secerror("Unable to address permanent storage for '%{public}@'.", exceptionResetCounterFile); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, EIO, NULL); - } - return status; - } - - NSMutableDictionary *dataToSave = [NSMutableDictionary new]; - if (!dataToSave) { - secerror("Failed to allocate memory for the exceptions epoch structure."); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ENOMEM, NULL); - } - return status; - } - dataToSave[@"Version"] = [NSNumber numberWithUnsignedInteger:1]; - dataToSave[kExceptionResetCountKey] = [NSNumber numberWithUnsignedInteger:exceptionResetCount]; - - status = [dataToSave writeToFile:path atomically:YES]; - if (!status) { - secerror("Failed to write to permanent storage at '%{public}@'.", path); - if (error) { - *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, EIO, NULL); - } - return status; - } - - secinfo("trust", "'%{public}@' has been committed to permanent storage at '%{public}@'.", kExceptionResetCountKey, path); - return status; } uint64_t SecTrustServerGetExceptionResetCount(CFErrorRef *error) { CFErrorRef localError = NULL; - uint64_t exceptionResetCount = SecReadPlistFromFileInKeychainDirectory(&localError); - /* Treat ENXIO as a transient error; I/O seems to be working but we have failed to read the current epoch. - * That's expected when epoch is still 0 and there is nothing to store in permanent storage. (and later read) - */ - if (localError && CFEqualSafe(CFErrorGetDomain(localError), kCFErrorDomainPOSIX) && CFErrorGetCode(localError) == ENXIO) { - CFRelease(localError); - localError = NULL; - } - if (error && localError) { - *error = localError; + uint64_t exceptionResetCount = ReadExceptionsCountFromUrl(ExceptionsResetCounterUrl(), &localError); + if (localError) { + if (error) { + *error = localError; + } else { + CFReleaseNull(localError); + } } secinfo("trust", "exceptionResetCount: %llu (%s)", exceptionResetCount, error ? (*error ? "Error" : "OK") : "N/A"); return exceptionResetCount; @@ -190,5 +116,27 @@ bool SecTrustServerIncrementExceptionResetCount(CFErrorRef *error) { return status; } - return SecWritePlistToFileInKeychainDirectory(currentExceptionResetCount + 1, error); + return WriteExceptionsCounterToUrl(currentExceptionResetCount + 1, ExceptionsResetCounterUrl(), error); +} + +void SecTrustServerMigrateExceptionsResetCount(void) { + CFErrorRef error = NULL; + (void)ReadExceptionsCountFromUrl(ExceptionsResetCounterUrl(), &error); + if (!error) { + secdebug("trust", "already migrated exceptions reset counter"); + return; + } + CFReleaseNull(error); + secdebug("trust", "migrating exceptions reset counter"); + uint64_t currentExceptionResetCount = ReadExceptionsCountFromUrl(ExceptionsResetCounterOldUrl(), NULL); + + if (!WriteExceptionsCounterToUrl(currentExceptionResetCount, ExceptionsResetCounterUrl(), &error)) { + secerror("Failed to migrate exceptions reset count: %@", error); + CFReleaseNull(error); + return; + } + + WithPathInKeychainDirectory((__bridge CFStringRef)exceptionResetCounterFile, ^(const char *utf8String) { + remove(utf8String); + }); } diff --git a/trust/trustd/SecTrustLoggingServer.h b/trust/trustd/SecTrustLoggingServer.h index fbc8b84a..5b15b9a4 100644 --- a/trust/trustd/SecTrustLoggingServer.h +++ b/trust/trustd/SecTrustLoggingServer.h @@ -27,53 +27,7 @@ #ifndef _SECURITY_SECTRUSTLOGGINGSERVER_H_ #define _SECURITY_SECTRUSTLOGGINGSERVER_H_ -#include -#include void DisableLocalization(void); -// i have a sneaking suspicion that Apple neutered this file and that this is where -// `TrustdHealthAnalyticsLogErrorCodeForDatabase` *should* be defined, -// so that's what i'll do: -void TrustdHealthAnalyticsLogErrorCodeForDatabase(int location, int operation, int error_type, int error_code); -// note that i'm not entirely sure about that last parameter type -// and those other parameters are dependent on the types of the following definitions - -// this is also probably where these were supposed to be defined: - -enum /* location */ { - TACAIssuerCache, - TAOCSPCache, - TARevocationDb, - TATrustStore, -}; - -enum /* operation */ { - TAOperationRead, - TAOperationWrite, - TAOperationCreate, - TAOperationOpen, -}; - -enum /* error type (?) */ { - TAFatalError, - TARecoverableError, -}; - -// i'm guessing this is also where this belongs: -bool SecNetworkingAnalyticsReport(CFStringRef event_name, xpc_object_t tls_analytics_attributes, CFErrorRef *error); - -// same with this: -void TrustdHealthAnalyticsLogErrorCode(int event, int error_type, int error_code); - -enum /* event */ { - TAEventValidUpdate, -}; - -// same here: -void TrustdHealthAnalyticsLogEvaluationCompleted(); - -// and you guessed it, same here: -void TrustdHealthAnalyticsLogSuccess(int event); - #endif /* _SECURITY_SECTRUSTLOGGINGSERVER_H_ */ diff --git a/trust/trustd/SecTrustLoggingServer.m b/trust/trustd/SecTrustLoggingServer.m index eca0e5e5..e9dabba3 100644 --- a/trust/trustd/SecTrustLoggingServer.m +++ b/trust/trustd/SecTrustLoggingServer.m @@ -27,24 +27,3 @@ #include #include "SecTrustLoggingServer.h" -void TrustdHealthAnalyticsLogErrorCodeForDatabase(int location, int operation, int error_type, int error_code) { - // a stub -}; - -bool SecNetworkingAnalyticsReport(CFStringRef event_name, xpc_object_t tls_analytics_attributes, CFErrorRef *error) { - // another stub - return true; -}; - -void TrustdHealthAnalyticsLogErrorCode(int event, int error_type, int error_code) { - // yet another stub -}; - -void TrustdHealthAnalyticsLogEvaluationCompleted() { - // YAYAS - // (yet another "yet another stub") -}; - -void TrustdHealthAnalyticsLogSuccess(int event) { - // man, Apple really likes to log and analyze stuff, huh? -}; diff --git a/trust/trustd/SecTrustServer.c b/trust/trustd/SecTrustServer.c index 06f56077..50b5d3aa 100644 --- a/trust/trustd/SecTrustServer.c +++ b/trust/trustd/SecTrustServer.c @@ -26,6 +26,7 @@ */ #include "trust/trustd/SecTrustServer.h" +#include "trust/trustd/SecTrustStoreServer.h" #include "trust/trustd/SecPolicyServer.h" #include "trust/trustd/SecTrustLoggingServer.h" #include "trust/trustd/SecCertificateSource.h" @@ -154,14 +155,11 @@ struct SecPathBuilder { static bool SecPathBuilderProcessLeaf(SecPathBuilderRef builder); static bool SecPathBuilderGetNext(SecPathBuilderRef builder); static bool SecPathBuilderValidatePath(SecPathBuilderRef builder); -static bool SecPathBuilderDidValidatePath(SecPathBuilderRef builder); static bool SecPathBuilderComputeDetails(SecPathBuilderRef builder); -static bool SecPathBuilderReportResult(SecPathBuilderRef builder); /* Forward declarations. */ static bool SecPathBuilderIsAnchor(SecPathBuilderRef builder, SecCertificateRef certificate, SecCertificateSourceRef *foundInSource); -static void SecPathBuilderSetPath(SecPathBuilderRef builder, SecCertificatePathVCRef path); static void SecPathBuilderInit(SecPathBuilderRef builder, dispatch_queue_t builderQueue, CFDataRef clientAuditToken, CFArrayRef certificates, @@ -242,9 +240,7 @@ static void SecPathBuilderInit(SecPathBuilderRef builder, dispatch_queue_t build if we don't explicitly trust them. */ CFArrayAppendValue(builder->parentSources, builder->appleAnchorSource); CFArrayAppendValue(builder->parentSources, kSecSystemAnchorSource); - #if TARGET_OS_IPHONE CFArrayAppendValue(builder->parentSources, kSecUserAnchorSource); - #endif } if (keychainsAllowed && builder->canAccessNetwork) { CFArrayAppendValue(builder->parentSources, kSecCAIssuerSource); @@ -273,13 +269,12 @@ static void SecPathBuilderInit(SecPathBuilderRef builder, dispatch_queue_t build anchorSources if we are supposed to trust them. */ CFArrayAppendValue(builder->anchorSources, builder->appleAnchorSource); if (keychainsAllowed) { -#if TARGET_OS_IPHONE - CFArrayAppendValue(builder->anchorSources, kSecUserAnchorSource); -#else /* TARGET_OS_OSX */ +#if TARGET_OS_OSX if (kSecLegacyAnchorSource->contains && kSecLegacyAnchorSource->copyParents) { CFArrayAppendValue(builder->anchorSources, kSecLegacyAnchorSource); } #endif + CFArrayAppendValue(builder->anchorSources, kSecUserAnchorSource); } CFArrayAppendValue(builder->anchorSources, kSecSystemAnchorSource); } @@ -345,7 +340,7 @@ static void SecPathBuilderForEachPVC(SecPathBuilderRef builder,void (^operation) } } -static void SecPathBuilderDestroy(SecPathBuilderRef builder) { +void SecPathBuilderDestroy(SecPathBuilderRef builder) { secdebug("alloc", "destroy builder %p", builder); dispatch_release_null(builder->queue); if (builder->anchorSource) { @@ -395,7 +390,7 @@ static void SecPathBuilderDestroy(SecPathBuilderRef builder) { } } -static void SecPathBuilderSetPath(SecPathBuilderRef builder, SecCertificatePathVCRef path) { +void SecPathBuilderSetPath(SecPathBuilderRef builder, SecCertificatePathVCRef path) { bool samePath = ((!path && !builder->path) || (path && builder->path && CFEqual(path, builder->path))); if (!samePath) { CFRetainAssign(builder->path, path); @@ -466,6 +461,9 @@ CFSetRef SecPathBuilderGetAllPaths(SecPathBuilderRef builder) TrustAnalyticsBuilder *SecPathBuilderGetAnalyticsData(SecPathBuilderRef builder) { + if (!builder) { + return NULL; + } return builder->analyticsData; } @@ -717,6 +715,53 @@ static void addOptionsToPolicy(SecPolicyRef policy, CFDictionaryRef newOptions) CFAssignRetained(policy->_options, oldOptions); } +static CF_RETURNS_RETAINED CFArrayRef addTransparentConnectionsRules(CFArrayRef rules, CFNumberRef transparentConnection) { + /* Not a Transparent Connection, no change */ + int transparentConnectionValue = 0; + if (!transparentConnection || !CFNumberGetValue(transparentConnection, kCFNumberIntType, &transparentConnectionValue) || transparentConnectionValue != 1) { + return CFRetainSafe(rules); + } + /* Transparent Connections not configured on this device, no change */ + CFArrayRef pins = _SecTrustStoreCopyTransparentConnectionPins(NULL, NULL); + if (!pins || CFArrayGetCount(pins) == 0) { + CFReleaseNull(pins); + return CFRetainSafe(rules); + } + + /* Create the transparent connection rules */ + CFMutableDictionaryRef transparentConnectionOptions = CFDictionaryCreateMutable(NULL, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFMutableArrayRef caSPKIsha256s = CFArrayCreateMutable(NULL, CFArrayGetCount(pins), &kCFTypeArrayCallBacks); + CFArrayForEach(pins, ^(const void *value) { + CFDictionaryRef pin = (CFDictionaryRef)value; + CFStringRef hashAlgorithm = CFDictionaryGetValue(pin, kSecTrustStoreHashAlgorithmKey); + if (!hashAlgorithm || !isString(hashAlgorithm) || + CFStringCompare(CFSTR("sha256"), hashAlgorithm, 0) != kCFCompareEqualTo) { + return; + } + CFDataRef hash = CFDictionaryGetValue(pin, kSecTrustStoreSPKIHashKey); + if (!hash || !isData(hash)) { + return; + } + CFArrayAppendValue(caSPKIsha256s, hash); + }); + if (CFArrayGetCount(caSPKIsha256s) == 0) { + CFReleaseNull(caSPKIsha256s); + CFReleaseNull(transparentConnectionOptions); + CFReleaseNull(pins); + return CFRetainSafe(rules); + } + secnotice("SecPinningDb", "Adding %lu CA pins for Transparent Connection", CFArrayGetCount(caSPKIsha256s)); + CFDictionaryAddValue(transparentConnectionOptions, kSecPolicyCheckCAspkiSHA256, caSPKIsha256s); + CFReleaseNull(caSPKIsha256s); + + /* Add the transparent connection rules as another option in the rules */ + CFMutableArrayRef newRules = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(rules) + 1, rules); + CFArrayAppendValue(newRules, transparentConnectionOptions); + CFReleaseNull(transparentConnectionOptions); + CFReleaseNull(pins); + return newRules; +} + static void SecPathBuilderAddPinningPolicies(SecPathBuilderRef builder) { CFIndex ix, initialPVCCount = builder->pvcCount; for (ix = 0; ix < initialPVCCount; ix++) { @@ -734,13 +779,16 @@ static void SecPathBuilderAddPinningPolicies(SecPathBuilderRef builder) { CFDictionaryAddValue(query, kSecPinningDbKeyHostname, hostname); CFDictionaryRef results = SecPinningDbCopyMatching(query); CFReleaseNull(query); - if (!results) { continue; } //No rules for this hostname or policyName + if (!results) { continue; } // No rules for this hostname or policyName /* Found pinning policies. Apply them to the path builder. */ CFArrayRef newRules = CFDictionaryGetValue(results, kSecPinningDbKeyRules); CFStringRef dbPolicyName = CFDictionaryGetValue(results, kSecPinningDbKeyPolicyName); + CFNumberRef transparentConnection = CFDictionaryGetValue(results, kSecPinningDbKeyTransparentConnection); secinfo("SecPinningDb", "found pinning %lu %@ policies for hostname %@, policyName %@", (unsigned long)CFArrayGetCount(newRules), dbPolicyName, hostname, policyName); + /* If, applicable, add transparent connection rules to the new rules */ + newRules = addTransparentConnectionsRules(newRules, transparentConnection); CFIndex newRulesIX; for (newRulesIX = 0; newRulesIX < CFArrayGetCount(newRules); newRulesIX++) { if (!isDictionary(CFArrayGetValueAtIndex(newRules, newRulesIX))) { @@ -772,6 +820,7 @@ static void SecPathBuilderAddPinningPolicies(SecPathBuilderRef builder) { CFReleaseNull(newPolicies); } CFReleaseNull(results); + CFReleaseNull(newRules); } CFReleaseNull(policies); } @@ -1104,7 +1153,7 @@ static bool SecPathBuilderValidatePath(SecPathBuilderRef builder) { return completed; } -static bool SecPathBuilderDidValidatePath(SecPathBuilderRef builder) { +bool SecPathBuilderDidValidatePath(SecPathBuilderRef builder) { /* We perform the revocation required policy checks here because * this is the state we call back into once all the asynchronous * revocation check calls are done. */ @@ -1153,12 +1202,98 @@ static bool SecPathBuilderComputeDetails(SecPathBuilderRef builder) { return completed; } -static bool SecPathBuilderReportResult(SecPathBuilderRef builder) { +static CFAbsoluteTime SecPathBuilderCalculateTrustNotBefore(SecPathBuilderRef builder) { + /* TrustResult Not Before is the maxmimum of the cert chain NotBefores, ocsp response thisUpdates, and + * the current time minus the leeway*/ + CFAbsoluteTime latestNotBefore = SecCertificatePathVCGetMaximumNotBefore(builder->bestPath); + if (SecCertificatePathVCIsRevocationDone(builder->bestPath)) { + CFAbsoluteTime thisUpdate = SecCertificatePathVCGetLatestThisUpdate(builder->bestPath); + if (thisUpdate > latestNotBefore) { + latestNotBefore = thisUpdate; + } + } + + CFAbsoluteTime before_leeway = CFAbsoluteTimeGetCurrent() - TRUST_TIME_LEEWAY; + if (before_leeway > latestNotBefore) { + latestNotBefore = before_leeway; + } + + return latestNotBefore; +} + +static CFAbsoluteTime SecPathBuilderCalculateTrustNotAfter(SecPathBuilderRef builder) { + /* TrustResult Not After is the minimum of the cert chain NotAfters, ocsp response nextUpdates, and + * the current time plus the leeway*/ + CFAbsoluteTime earliestNotAfter = SecCertificatePathVCGetMinimumNotAfter(builder->bestPath); + if (SecCertificatePathVCIsRevocationDone(builder->bestPath)) { + CFAbsoluteTime nextUpdate = SecCertificatePathVCGetEarliestNextUpdate(builder->bestPath); + if (nextUpdate != 0 && nextUpdate < earliestNotAfter) { // 0.0 is a (really dumb) sentinel for "not checked" + earliestNotAfter = nextUpdate; + } + } + + CFAbsoluteTime after_leeway = CFAbsoluteTimeGetCurrent() + TRUST_TIME_LEEWAY; + if (after_leeway < earliestNotAfter) { + earliestNotAfter = after_leeway; + } + return earliestNotAfter; +} + +static void SecPathBuilderReportTrustValidityPeriod(SecPathBuilderRef builder) { + if (!builder->info) { + return; + } + + CFAbsoluteTime resultNotBefore = SecPathBuilderCalculateTrustNotBefore(builder); + CFAbsoluteTime resultNotAfter = SecPathBuilderCalculateTrustNotAfter(builder); + /* Special cases where validity window is non-existent */ + if (resultNotBefore > resultNotAfter) { + /* "now" can be before notAfter, between notAfter and notBefore, or after notBefore. We want to adjust + * the result validity period to ensure we have some valid period, ensuring we capture when the trust + * result could change. */ + if (CFAbsoluteTimeGetCurrent() < resultNotAfter) { + /* "now" < notAfter < notBefore: + * - caused by a cert with a future validity + * - keep the notAfter date and move the notBefore to "now" */ + resultNotBefore = CFAbsoluteTimeGetCurrent(); + } else if (CFAbsoluteTimeGetCurrent() < resultNotBefore) { + /* notAfter <= "now" < notBefore: + * - caused by a cert with a future validity and either an expired (revoked) OCSP response or cert + * - swap the dates -- the result won't change between these two points */ + CFAbsoluteTime temp = resultNotBefore; + resultNotBefore = resultNotAfter; + resultNotAfter = temp; + } else { + /* notAfter < notBefore <= "now": + * - caused by expired certs (as notBefore will have been adjusted by the leeway) + * - keep the notBefore and move notAfter to "now + leeway" */ + resultNotAfter = CFAbsoluteTimeGetCurrent() + TRUST_TIME_LEEWAY; + } + } + + /* Special case where the entire window is in the past. In order to avoid triggering + * trust evaluations with every trust object access, we're setting the validity period to + * be between notAfter and now + leeway. */ + if (resultNotAfter < CFAbsoluteTimeGetCurrent()) { + resultNotBefore = resultNotAfter; + resultNotAfter = CFAbsoluteTimeGetCurrent() + TRUST_TIME_LEEWAY; + } + + CFDateRef notBeforeDate = CFDateCreate(NULL, resultNotBefore); + CFDateRef notAfterDate = CFDateCreate(NULL, resultNotAfter); + CFDictionarySetValue(builder->info, kSecTrustInfoResultNotBefore, notBeforeDate); + CFDictionarySetValue(builder->info, kSecTrustInfoResultNotAfter, notAfterDate); + CFReleaseNull(notBeforeDate); + CFReleaseNull(notAfterDate); + +} + +bool SecPathBuilderReportResult(SecPathBuilderRef builder) { builder->info = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - + SecPathBuilderReportTrustValidityPeriod(builder); /* isEV is not set unless also CT verified. Here, we need to check that we * got a revocation response as well. */ if (builder->info && SecCertificatePathVCIsEV(builder->bestPath) && SecPathBuilderIsOkResult(builder)) { @@ -1210,6 +1345,11 @@ static bool SecPathBuilderReportResult(SecPathBuilderRef builder) { kCFBooleanFalse); /* iOS key */ CFDictionarySetValue(builder->info, kSecTrustRevocationChecked, kCFBooleanFalse); /* unified API key */ + } else if (SecCertificatePathVCRevocationCheckedAllCerts(builder->bestPath)) { + CFDictionarySetValue(builder->info, kSecTrustInfoRevocationKey, + kCFBooleanTrue); /* iOS key */ + CFDictionarySetValue(builder->info, kSecTrustRevocationChecked, + kCFBooleanTrue); /* unified API key */ } } @@ -1359,6 +1499,20 @@ SecTrustServerEvaluateBlock(dispatch_queue_t builderQueue, CFDataRef clientAudit SecPathBuilderStep(builder); } +static CFDataRef SecTrustServerCopySelfAuditToken(void) +{ + audit_token_t token; + kern_return_t kr; + mach_msg_type_number_t token_size = TASK_AUDIT_TOKEN_COUNT; + kr = task_info(mach_task_self(), TASK_AUDIT_TOKEN, (task_info_t)&token, &token_size); + if (kr != KERN_SUCCESS) { + secwarning("failed to get audit token for ourselves"); + return NULL; + } + + return CFDataCreate(NULL, (uint8_t *)&token, sizeof(token)); +} + // NO_SERVER Shim code only, xpc interface should call SecTrustServerEvaluateBlock() directly SecTrustResultType SecTrustServerEvaluate(CFArrayRef certificates, CFArrayRef anchors, bool anchorsOnly, bool keychainsAllowed, CFArrayRef policies, CFArrayRef responses, CFArrayRef SCTs, CFArrayRef trustedLogs, CFAbsoluteTime verifyTime, __unused CFArrayRef accessGroups, CFArrayRef exceptions, CFArrayRef *pdetails, CFDictionaryRef *pinfo, CFArrayRef *pchain, CFErrorRef *perror) { @@ -1366,13 +1520,16 @@ SecTrustResultType SecTrustServerEvaluate(CFArrayRef certificates, CFArrayRef an __block SecTrustResultType result = kSecTrustResultInvalid; __block dispatch_queue_t queue = dispatch_queue_create("com.apple.trustd.evaluation.recursive", DISPATCH_QUEUE_SERIAL); + /* make an audit token for ourselves */ + CFDataRef audit_token = SecTrustServerCopySelfAuditToken(); + /* We need to use the async call with the semaphore here instead of a synchronous call because we may return from * SecPathBuilderStep while waiting for an asynchronous network call in order to complete the evaluation. That return * is necessary in the XPC interface in order to free up the workloop for other trust evaluations while we wait for * the networking to complete, but here, we need to make sure we wait for the network call (which will async back * onto our queue) to complete and signal us before we return to the "inline" caller. */ dispatch_async(queue, ^{ - SecTrustServerEvaluateBlock(queue, NULL, certificates, anchors, anchorsOnly, keychainsAllowed, policies, responses, SCTs, trustedLogs, verifyTime, accessGroups, exceptions, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, CFArrayRef chain, CFErrorRef error) { + SecTrustServerEvaluateBlock(queue, audit_token, certificates, anchors, anchorsOnly, keychainsAllowed, policies, responses, SCTs, trustedLogs, verifyTime, accessGroups, exceptions, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, CFArrayRef chain, CFErrorRef error) { result = tr; if (tr == kSecTrustResultInvalid) { if (perror) { @@ -1399,6 +1556,7 @@ SecTrustResultType SecTrustServerEvaluate(CFArrayRef certificates, CFArrayRef an dispatch_semaphore_wait(done, DISPATCH_TIME_FOREVER); dispatch_release(done); dispatch_release_null(queue); + CFReleaseNull(audit_token); return result; } diff --git a/trust/trustd/SecTrustServer.h b/trust/trustd/SecTrustServer.h index 898e71f3..26b2c1e6 100644 --- a/trust/trustd/SecTrustServer.h +++ b/trust/trustd/SecTrustServer.h @@ -68,6 +68,11 @@ SecPathBuilderRef SecPathBuilderCreate(dispatch_queue_t builderQueue, CFDataRef CFArrayRef signedCertificateTimestamps, CFArrayRef trustedLogs, CFAbsoluteTime verifyTime, CFArrayRef accessGroups, CFArrayRef exceptions, SecPathBuilderCompleted completed, const void *userData); +void SecPathBuilderDestroy(SecPathBuilderRef builder); + +/* engine states exposed for testing */ +bool SecPathBuilderDidValidatePath(SecPathBuilderRef builder); +bool SecPathBuilderReportResult(SecPathBuilderRef builder); /* Returns true if it's ok to perform network operations for this builder. */ bool SecPathBuilderCanAccessNetwork(SecPathBuilderRef builder); @@ -84,6 +89,7 @@ CFDictionaryRef SecPathBuilderCopyTrustedLogs(SecPathBuilderRef builder); CFSetRef SecPathBuilderGetAllPaths(SecPathBuilderRef builder); SecCertificatePathVCRef SecPathBuilderGetPath(SecPathBuilderRef builder); SecCertificatePathVCRef SecPathBuilderGetBestPath(SecPathBuilderRef builder); +void SecPathBuilderSetPath(SecPathBuilderRef builder, SecCertificatePathVCRef path); CFAbsoluteTime SecPathBuilderGetVerifyTime(SecPathBuilderRef builder); CFIndex SecPathBuilderGetCertificateCount(SecPathBuilderRef builder); SecCertificateRef SecPathBuilderGetCertificateAtIndex(SecPathBuilderRef builder, CFIndex ix); @@ -152,20 +158,6 @@ typedef CF_OPTIONS(uint8_t, TA_SCTSource) { TA_SCT_TLS = 1 << 2, }; -typedef CF_ENUM(uint8_t, TA_CTFailureReason) { - TA_CTNoFailure = 0, - TA_CTNoSCTs = 1, - TA_CTMissingLogs = 2, - TA_CTNoCurrentSCTsUnknownLog = 3, - TA_CTNoCurrentSCTsDisqualifiedLog = 4, - TA_CTPresentedNotEnoughUnknown = 5, - TA_CTPresentedNotEnoughDisqualified = 6, - TA_CTPresentedNotEnough = 7, - TA_CTEmbeddedNotEnoughUnknown = 8, - TA_CTEmbeddedNotEnoughDisqualified = 9, - TA_CTEmbeddedNotEnough = 10, -}; - typedef CF_OPTIONS(uint8_t, TAValidStatus) { TAValidDefinitelyOK = 1 << 0, TAValidProbablyOK = 1 << 1, @@ -180,11 +172,12 @@ typedef CF_OPTIONS(uint8_t, TAValidStatus) { typedef struct { uint64_t start_time; bool suspected_mitm; + bool ca_fail_eku_check; + bool tls_invalid_ku; // Certificate Transparency TA_SCTSource sct_sources; uint32_t number_scts; uint32_t number_trusted_scts; - TA_CTFailureReason ct_failure_reason; bool ct_one_current; // CAIssuer bool ca_issuer_cache_hit; @@ -202,6 +195,7 @@ typedef struct { uint64_t ocsp_fetch_time; uint32_t ocsp_fetch_failed; bool ocsp_validation_failed; + bool ocsp_weak_hash; // Valid TAValidStatus valid_status; bool valid_trigger_ocsp; diff --git a/trust/trustd/SecTrustStoreServer.c b/trust/trustd/SecTrustStoreServer.c index 88de9d23..56eed67c 100644 --- a/trust/trustd/SecTrustStoreServer.c +++ b/trust/trustd/SecTrustStoreServer.c @@ -57,20 +57,27 @@ #include #include #include +#include "trust/trustd/SecCertificateSource.h" +#include "trust/trustd/trustdFileLocations.h" /* uid of the _securityd user. */ #define SECURTYD_UID 64 static dispatch_once_t kSecTrustStoreUserOnce; +static dispatch_once_t kSecTrustStoreSystemOnce; static SecTrustStoreRef kSecTrustStoreUser = NULL; +static SecTrustStoreRef kSecTrustStoreAdmin = NULL; +static SecTrustStoreRef kSecTrustStoreSystem = NULL; +#if TARGET_OS_IPHONE static const char copyParentsSQL[] = "SELECT data FROM tsettings WHERE subj=?"; -static const char containsSQL[] = "SELECT tset FROM tsettings WHERE sha1=?"; -static const char insertSQL[] = "INSERT OR REPLACE INTO tsettings(sha1,subj,tset,data)VALUES(?,?,?,?)"; -static const char deleteSQL[] = "DELETE FROM tsettings WHERE sha1=?"; +static const char containsSQL[] = "SELECT tset FROM tsettings WHERE sha256=?"; +static const char insertSQL[] = "INSERT OR REPLACE INTO tsettings(sha256,subj,tset,data)VALUES(?,?,?,?)"; +static const char deleteSQL[] = "DELETE FROM tsettings WHERE sha256=?"; static const char deleteAllSQL[] = "BEGIN EXCLUSIVE TRANSACTION; DELETE from tsettings; COMMIT TRANSACTION; VACUUM;"; -static const char copyAllSQL[] = "SELECT data,tset FROM tsettings ORDER BY sha1"; +static const char copyAllSQL[] = "SELECT data,tset FROM tsettings ORDER BY sha256"; static const char countAllSQL[] = "SELECT COUNT(*) FROM tsettings"; +#endif #define kSecTrustStoreName CFSTR("TrustStore") #define kSecTrustStoreDbExtension CFSTR("sqlite3") @@ -85,6 +92,7 @@ struct __SecTrustStore { sqlite3_stmt *contains; bool readOnly; bool containsSettings; // For optimization of high-use calls. + SecTrustStoreDomain domain; }; // MARK: - @@ -92,7 +100,7 @@ struct __SecTrustStore { // MARK: - // MARK: Trust store functions - +#if TARGET_OS_IPHONE static int sec_create_path(const char *path) { char pathbuf[PATH_MAX]; @@ -137,7 +145,12 @@ static int sec_sqlite3_open(const char *db_name, sqlite3 **s3h, bool create_path) { int s3e; - s3e = sqlite3_open(db_name, s3h); +#if TARGET_OS_IPHONE + int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FILEPROTECTION_NONE; +#else + int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; +#endif + s3e = sqlite3_open_v2(db_name, s3h, flags, NULL); if (s3e == SQLITE_CANTOPEN && create_path) { /* Make sure the path to db_name exists and is writable, then try again. */ @@ -189,11 +202,11 @@ static SecTrustStoreRef SecTrustStoreCreate(const char *db_name, char *errmsg = NULL; s3e = sqlite3_exec(ts->s3h, "CREATE TABLE tsettings(" - "sha1 BLOB NOT NULL DEFAULT ''," + "sha256 BLOB NOT NULL DEFAULT ''," "subj BLOB NOT NULL DEFAULT ''," "tset BLOB," "data BLOB," - "PRIMARY KEY(sha1)" + "PRIMARY KEY(sha256)" ");" "CREATE INDEX isubj ON tsettings(subj);" , NULL, NULL, &errmsg); @@ -233,10 +246,10 @@ errOut: return NULL; } -static bool SecExtractFilesystemPathForKeychainFile(CFStringRef file, UInt8 *buffer, CFIndex maxBufLen) +static bool SecExtractFilesystemPathForPrivateUserTrustdFile(CFStringRef file, UInt8 *buffer, CFIndex maxBufLen) { bool translated = false; - CFURLRef fileURL = SecCopyURLForFileInKeychainDirectory(file); + CFURLRef fileURL = SecCopyURLForFileInPrivateUserTrustdDirectory(file); if (fileURL && CFURLGetFileSystemRepresentation(fileURL, false, buffer, maxBufLen)) translated = true; @@ -248,22 +261,38 @@ static bool SecExtractFilesystemPathForKeychainFile(CFStringRef file, UInt8 *buf static void SecTrustStoreInitUser(void) { const char path[MAXPATHLEN]; - if (SecExtractFilesystemPathForKeychainFile(kTrustStoreFileName, (UInt8*) path, (CFIndex) sizeof(path))) + if (SecExtractFilesystemPathForPrivateUserTrustdFile(kTrustStoreFileName, (UInt8*) path, (CFIndex) sizeof(path))) { kSecTrustStoreUser = SecTrustStoreCreate(path, true); - if (kSecTrustStoreUser) + if (kSecTrustStoreUser) { kSecTrustStoreUser->readOnly = false; + kSecTrustStoreUser->domain = kSecTrustStoreDomainUser; + } } } +static void SecTrustStoreInitSystem(void) { + kSecTrustStoreSystem = (SecTrustStoreRef)malloc(sizeof(struct __SecTrustStore)); + if (kSecTrustStoreSystem) { + kSecTrustStoreSystem->readOnly = true; + kSecTrustStoreSystem->domain = kSecTrustStoreDomainSystem; + } +} + /* AUDIT[securityd](done): domainName (ok) is a caller provided string of any length (might be 0), only its cf type has been checked. */ SecTrustStoreRef SecTrustStoreForDomainName(CFStringRef domainName, CFErrorRef *error) { - if (CFEqual(CFSTR("user"), domainName)) { + if (CFEqualSafe(CFSTR("user"), domainName)) { dispatch_once(&kSecTrustStoreUserOnce, ^{ SecTrustStoreInitUser(); }); return kSecTrustStoreUser; + } else if (CFEqualSafe(CFSTR("admin"), domainName)) { + SecError(errSecUnimplemented, error, CFSTR("unsupported domain: %@"), domainName); + return kSecTrustStoreAdmin; + } else if (CFEqualSafe(CFSTR("system"), domainName)) { + dispatch_once(&kSecTrustStoreSystemOnce, ^{ SecTrustStoreInitSystem(); }); + return kSecTrustStoreSystem; } else { SecError(errSecParam, error, CFSTR("unknown domain: %@"), domainName); return NULL; @@ -287,12 +316,12 @@ bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, sqlite3_stmt *insert = NULL; CFDataRef xmlData = NULL; CFArrayRef array = NULL; + CFDataRef subject = NULL; + CFDataRef digest = NULL; - CFDataRef subject; require_action_quiet(subject = SecCertificateGetNormalizedSubjectContent(certificate), errOut, ok = SecError(errSecParam, error, CFSTR("get normalized subject failed"))); - CFDataRef digest; - require_action_quiet(digest = SecCertificateGetSHA1Digest(certificate), errOut, ok = SecError(errSecParam, error, CFSTR("get sha1 digest failed"))); + require_action_quiet(digest = SecCertificateCopySHA256Digest(certificate), errOut, ok = SecError(errSecParam, error, CFSTR("get sha256 digest failed"))); /* Do some basic checks on the trust settings passed in. */ if (trustSettingsDictOrArray == NULL) { @@ -315,7 +344,7 @@ bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, int s3e = sqlite3_exec(ts->s3h, "BEGIN EXCLUSIVE TRANSACTION", NULL, NULL, NULL); require_action_quiet(s3e == SQLITE_OK, errOut, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e)); - /* Parameter order is sha1,subj,tset,data. */ + /* Parameter order is sha256,subj,tset,data. */ require_noerr_action_quiet(s3e = sqlite3_prepare_v2(ts->s3h, insertSQL, sizeof(insertSQL), &insert, NULL), errOutSql, ok = SecError(errSecInternal, error, CFSTR("sqlite3 error: %d"), s3e)); require_noerr_action_quiet(s3e = sqlite3_bind_blob_wrapper(insert, 1, @@ -361,19 +390,18 @@ bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, errOut: CFReleaseSafe(xmlData); CFReleaseSafe(array); + CFReleaseNull(digest); }); errOutNotLocked: return ok; } -/* AUDIT[securityd](done): - ts (ok) might be NULL. - digest (ok) is a data of any length (might be 0). - */ -bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts, - CFDataRef digest, CFErrorRef *error) { - require_quiet(ts, errOutNotLocked); - require(!ts->readOnly, errOutNotLocked); +bool _SecTrustStoreRemoveCertificate(SecTrustStoreRef ts, SecCertificateRef cert, CFErrorRef *error) { + bool ok = true; + CFDataRef digest = NULL; + require_action_quiet(ts, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("truststore is NULL"))); + require_action_quiet(!ts->readOnly, errOutNotLocked, ok = SecError(errSecReadOnly, error, CFSTR("truststore is readOnly"))); + require_action_quiet(digest = SecCertificateCopySHA256Digest(cert), errOutNotLocked, ok = SecError(errSecAllocate, error, CFSTR("failed to get cert sha256 digest"))); dispatch_sync(ts->queue, ^{ int s3e = SQLITE_OK; sqlite3_stmt *deleteStmt = NULL; @@ -395,14 +423,15 @@ bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts, } }); errOutNotLocked: - return true; + CFReleaseNull(digest); + return ok; } bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts, CFErrorRef *error) { __block bool removed_all = false; - require(ts, errOutNotLocked); - require(!ts->readOnly, errOutNotLocked); + require_action_quiet(ts, errOutNotLocked, removed_all = SecError(errSecParam, error, CFSTR("truststore is NULL"))); + require_action_quiet(!ts->readOnly, errOutNotLocked, removed_all = SecError(errSecReadOnly, error, CFSTR("truststore is readOnly"))); dispatch_sync(ts->queue, ^{ int s3e =sqlite3_exec(ts->s3h, deleteAllSQL, NULL, NULL, NULL); if (s3e == SQLITE_OK) { @@ -431,6 +460,9 @@ CFArrayRef SecTrustStoreCopyParents(SecTrustStoreRef ts, SecCertificateRef certificate, CFErrorRef *error) { __block CFMutableArrayRef parents = NULL; require(ts, errOutNotLocked); + /* Since only trustd uses the CopyParents interface and only for the CertificateSource, it should never call + * this with the system domain. */ + require(ts->domain != kSecTrustStoreDomainSystem, errOutNotLocked); dispatch_sync(ts->queue, ^{ int s3e = SQLITE_OK; CFDataRef issuer = NULL; @@ -475,12 +507,14 @@ errOutNotLocked: return parents; } -static bool SecTrustStoreQueryCertificateWithDigest(SecTrustStoreRef ts, - CFDataRef digest, bool *contains, CFArrayRef *usageConstraints, CFErrorRef *error) { - if (contains) +static bool SecTrustStoreQueryCertificate(SecTrustStoreRef ts, SecCertificateRef cert, bool *contains, CFArrayRef *usageConstraints, CFErrorRef *error) { + if (contains) { *contains = false; + } __block bool ok = true; + CFDataRef digest = NULL; require_action_quiet(ts, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("ts is NULL"))); + require_action_quiet(digest = SecCertificateCopySHA256Digest(cert), errOutNotLocked, ok = SecError(errSecAllocate, error, CFSTR("failed to get cert sha256 digest"))); dispatch_sync(ts->queue, ^{ CFDataRef xmlData = NULL; CFPropertyListRef trustSettings = NULL; @@ -520,17 +554,30 @@ static bool SecTrustStoreQueryCertificateWithDigest(SecTrustStoreRef ts, CFReleaseNull(trustSettings); }); errOutNotLocked: + CFReleaseNull(digest); return ok; } -bool SecTrustStoreContainsCertificateWithDigest(SecTrustStoreRef ts, - CFDataRef digest, bool *contains, CFErrorRef *error) { - return SecTrustStoreQueryCertificateWithDigest(ts, digest, contains, NULL, error); +bool _SecTrustStoreContainsCertificate(SecTrustStoreRef ts, SecCertificateRef cert, bool *contains, CFErrorRef *error) { + if (ts && ts->domain == kSecTrustStoreDomainSystem) { + // For the system domain, use the system anchor source + if (contains) { + *contains = SecCertificateSourceContains(kSecSystemAnchorSource, cert); + } + return true; + } + return SecTrustStoreQueryCertificate(ts, cert, contains, NULL, error); } -bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, - CFDataRef digest, CFArrayRef *usageConstraints, CFErrorRef *error) { - return SecTrustStoreQueryCertificateWithDigest(ts, digest, NULL, usageConstraints, error); +bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, SecCertificateRef cert, CFArrayRef *usageConstraints, CFErrorRef *error) { + if (ts && ts->domain == kSecTrustStoreDomainSystem) { + // For the system domain, use the system anchor source + if (usageConstraints) { + *usageConstraints = SecCertificateSourceCopyUsageConstraints(kSecSystemAnchorSource, cert); + } + return true; + } + return SecTrustStoreQueryCertificate(ts, cert, NULL, usageConstraints, error); } bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error) { @@ -538,6 +585,7 @@ bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, __block CFMutableArrayRef CertsAndSettings = NULL; require_action_quiet(ts, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("ts is NULL"))); require_action_quiet(trustStoreContents, errOutNotLocked, ok = SecError(errSecParam, error, CFSTR("trustStoreContents is NULL"))); + require_action_quiet(ts->domain != kSecTrustStoreDomainSystem, errOutNotLocked, ok = SecError(errSecUnimplemented, error, CFSTR("Cannot copy system trust store contents"))); // Not allowing system trust store enumeration dispatch_sync(ts->queue, ^{ sqlite3_stmt *copyAllStmt = NULL; CFDataRef cert = NULL; @@ -594,3 +642,193 @@ bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, errOutNotLocked: return ok; } + +static const char copyAllOldSQL[] = "SELECT data,tset FROM tsettings ORDER BY sha1"; +bool _SecTrustStoreMigrateUserStore(CFErrorRef *error) +{ + /* If new trust store file already exists, we don't need to migrate */ + const char path[MAXPATHLEN]; + if (SecExtractFilesystemPathForPrivateUserTrustdFile(kTrustStoreFileName, (UInt8*) path, (CFIndex) sizeof(path))) { + FILE* file = fopen(path, "r"); + if (file != NULL) { + secdebug("config", "already migrated user trust store"); + fclose(file); + return true; + } + } + + secdebug("config", "migrating trust store"); + bool ok = false; + sqlite3 *old_db = NULL; + int s3e = SQLITE_OK; + SecCertificateRef cert = NULL; + CFDataRef xmlData = NULL; + CFArrayRef tsArray = NULL; + sqlite3_stmt *copyAllStmt = NULL; + + /* Open old Trust Store */ + CFURLRef oldURL = SecCopyURLForFileInKeychainDirectory(kTrustStoreFileName); + require_action(oldURL, errOut, ok = SecError(errSecIO, error, CFSTR("failed to get old DB file URL"))); + require_action(CFURLGetFileSystemRepresentation(oldURL, false, (UInt8*) path, (CFIndex) sizeof(path)), errOut, + ok= SecError(errSecIO, error, CFSTR("failed to get old DB file path"))); + require_noerr_action(s3e = sqlite3_open_v2(path, &old_db, SQLITE_OPEN_READONLY, NULL), errOut, + ok = SecDbError(s3e, error, CFSTR("failed to open old trust store database; new trust store will be empty"))); + require_noerr_action(s3e = sqlite3_prepare_v2(old_db, copyAllOldSQL, sizeof(copyAllOldSQL), ©AllStmt, NULL), errOut, + ok = SecDbErrorWithDb(s3e, old_db, error, CFSTR("failed to prepare old trust store read"))); + + /* Open new Trust Store */ + SecTrustStoreRef new_db = SecTrustStoreForDomainName(CFSTR("user"), error); + require_action(new_db, errOut, ok = SecError(errSecAllocate, error, CFSTR("failed to open new trust store"))); + + /* Read each row of the old trust store and set it in the new trust store */ + for(;;) { + s3e = sqlite3_step(copyAllStmt); + if (s3e == SQLITE_ROW) { + require_action(cert = SecCertificateCreateWithBytes(NULL, + sqlite3_column_blob(copyAllStmt, 0), + sqlite3_column_bytes(copyAllStmt, 0)), errOut, + ok = SecError(errSecDecode, error, CFSTR("failed to decode cert in old DB"))); + require_action(xmlData = CFDataCreate(NULL, + sqlite3_column_blob(copyAllStmt, 1), + sqlite3_column_bytes(copyAllStmt, 1)), errOut, + ok = SecError(errSecParam, error, CFSTR("no tset data in old DB"))); + require(tsArray = CFPropertyListCreateWithData(NULL, + xmlData, + kCFPropertyListImmutable, + NULL, error), errOut); + require_action(isArray(tsArray), errOut, + ok = SecError(errSecDecode, error, CFSTR("tset is not an array in old DB"))); + OSStatus status = errSecSuccess; + require(status = _SecTrustStoreSetTrustSettings(new_db, cert, tsArray, error), errOut); + + CFReleaseNull(cert); + CFReleaseNull(xmlData); + CFReleaseNull(tsArray); + } else { + require_action(s3e == SQLITE_DONE || s3e == SQLITE_OK, errOut, ok = SecDbErrorWithStmt(s3e, copyAllStmt, error, CFSTR("sqlite3_step failed"))); + break; + } + } + require_noerr_action(s3e = sqlite3_finalize(copyAllStmt), errOut, + ok = SecDbErrorWithDb(s3e, old_db, error, CFSTR("failed to finalize old trust store read"))); + copyAllStmt = NULL; + require_noerr_action(s3e = sqlite3_close(old_db), errOut, + ok = SecDbError(s3e, error, CFSTR("failed to close old trust store"))); + old_db = NULL; + ok = true; + secdebug("config", "successfully migrated existing trust store"); + + /* Delete the old trust store database */ + WithPathInKeychainDirectory(kTrustStoreFileName, ^(const char *utf8String) { + remove(utf8String); + }); +errOut: + if (copyAllStmt) { + require_noerr_action(s3e = sqlite3_finalize(copyAllStmt), errOut, + ok = SecDbErrorWithDb(s3e, old_db, error, CFSTR("failed to finalize old trust store read"))); + } + if (old_db) { + require_noerr_action(s3e = sqlite3_close(old_db), errOut, + ok = SecDbError(s3e, error, CFSTR("failed to close old trust store"))); + } + CFReleaseNull(cert); + CFReleaseNull(xmlData); + CFReleaseNull(tsArray); + CFReleaseNull(oldURL); + return ok; +} + +#else // !TARGET_OS_IPHONE +/* On macOS the trust store has nothing in it by default */ +static void SecTrustStoreInitUser(void) { + SecTrustStoreRef ts = (SecTrustStoreRef)malloc(sizeof(struct __SecTrustStore)); + memset(ts, 0, sizeof(struct __SecTrustStore)); + ts->readOnly = true; + ts->domain = kSecTrustStoreDomainUser; + kSecTrustStoreUser = ts; +} + +static void SecTrustStoreInitSystem(void) { + SecTrustStoreRef ts = (SecTrustStoreRef)malloc(sizeof(struct __SecTrustStore)); + ts->readOnly = true; + ts->domain = kSecTrustStoreDomainSystem; + kSecTrustStoreSystem = ts; +} + +SecTrustStoreRef SecTrustStoreForDomainName(CFStringRef domainName, CFErrorRef *error) { + if (CFEqualSafe(CFSTR("user"), domainName)) { + dispatch_once(&kSecTrustStoreUserOnce, ^{ SecTrustStoreInitUser(); }); + return kSecTrustStoreUser; + } else if (CFEqualSafe(CFSTR("admin"), domainName)) { + SecError(errSecUnimplemented, error, CFSTR("unsupported domain: %@"), domainName); + return kSecTrustStoreAdmin; + } else if (CFEqualSafe(CFSTR("system"), domainName)) { + dispatch_once(&kSecTrustStoreSystemOnce, ^{ SecTrustStoreInitSystem(); }); + return kSecTrustStoreSystem; + } else { + SecError(errSecParam, error, CFSTR("unknown domain: %@"), domainName); + return NULL; + } +} + +bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, + SecCertificateRef certificate, + CFTypeRef trustSettingsDictOrArray, CFErrorRef *error) { + return SecError(errSecReadOnly, error, CFSTR("trust store is not modifiable on this platform")); +} + +bool _SecTrustStoreRemoveCertificate(SecTrustStoreRef ts, SecCertificateRef cert, CFErrorRef *error) { + return SecError(errSecReadOnly, error, CFSTR("trust store is not modifiable on this platform")); +} + +bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts, CFErrorRef *error) { + return SecError(errSecReadOnly, error, CFSTR("trust store is not modifiable on this platform")); +} + +CFArrayRef SecTrustStoreCopyParents(SecTrustStoreRef ts, + SecCertificateRef certificate, CFErrorRef *error) { + CFArrayRef parents = NULL; + /* Since only trustd uses the CopyParents interface and only for the CertificateSource, it should never call + * this with the system domain. */ + if (ts && ts->domain == kSecTrustStoreDomainSystem) { + return NULL; + } + return parents; +} + +bool _SecTrustStoreContainsCertificate(SecTrustStoreRef ts, SecCertificateRef cert, bool *contains, CFErrorRef *error) { + if (contains) { + *contains = false; + } + if (ts && ts->domain == kSecTrustStoreDomainSystem) { + // For the system domain, use the system anchor source + if (contains) { + *contains = SecCertificateSourceContains(kSecSystemAnchorSource, cert); + } + return true; + } + return true; +} + +bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, SecCertificateRef cert, CFArrayRef *usageConstraints, CFErrorRef *error) { + if (ts && ts->domain == kSecTrustStoreDomainSystem) { + // For the system domain, use the system anchor source + if (usageConstraints) { + *usageConstraints = SecCertificateSourceCopyUsageConstraints(kSecSystemAnchorSource, cert); + } + return true; + } + return true; +} + +bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error) { + if (ts && ts->domain == kSecTrustStoreDomainSystem) { + return SecError(errSecUnimplemented, error, CFSTR("Cannot copy system trust store contents")); + } + CFMutableArrayRef CertsAndSettings = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + if (CertsAndSettings) { + *trustStoreContents = CertsAndSettings; + } + return true; +} +#endif diff --git a/trust/trustd/SecTrustStoreServer.h b/trust/trustd/SecTrustStoreServer.h index 41444de1..958c565f 100644 --- a/trust/trustd/SecTrustStoreServer.h +++ b/trust/trustd/SecTrustStoreServer.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007-2009,2012-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2012-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -41,22 +41,31 @@ bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, SecCertificateRef certificate, CFTypeRef trustSettingsDictOrArray, CFErrorRef *error); -bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts, CFDataRef digest, CFErrorRef *error); +bool _SecTrustStoreRemoveCertificate(SecTrustStoreRef ts, SecCertificateRef cert, CFErrorRef *error); bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts, CFErrorRef *error); -CFArrayRef SecTrustStoreCopyParents(SecTrustStoreRef ts, - SecCertificateRef certificate, CFErrorRef *error); +CFArrayRef SecTrustStoreCopyParents(SecTrustStoreRef ts, SecCertificateRef certificate, CFErrorRef *error); -bool SecTrustStoreContainsCertificateWithDigest(SecTrustStoreRef source, CFDataRef digest, bool *contains, CFErrorRef *error); +bool _SecTrustStoreContainsCertificate(SecTrustStoreRef source, SecCertificateRef cert, bool *contains, CFErrorRef *error); -bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, CFDataRef digest, CFArrayRef *usageConstraints, CFErrorRef *error); +bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, SecCertificateRef cert, CFArrayRef *usageConstraints, CFErrorRef *error); bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error); +bool _SecTrustStoreMigrateUserStore(CFErrorRef *error); + +void _SecTrustStoreMigrateConfigurations(void); + bool _SecTrustStoreSetCTExceptions(CFStringRef appID, CFDictionaryRef exceptions, CFErrorRef *error); CF_RETURNS_RETAINED CFDictionaryRef _SecTrustStoreCopyCTExceptions(CFStringRef appID, CFErrorRef *error); +bool _SecTrustStoreSetCARevocationAdditions(CFStringRef appID, CFDictionaryRef additions, CFErrorRef *error); +CF_RETURNS_RETAINED CFDictionaryRef _SecTrustStoreCopyCARevocationAdditions(CFStringRef appID, CFErrorRef *error); + +bool _SecTrustStoreSetTransparentConnectionPins(CFStringRef appID, CFArrayRef pins, CFErrorRef *error); +CF_RETURNS_RETAINED CFArrayRef _SecTrustStoreCopyTransparentConnectionPins(CFStringRef appID, CFErrorRef *error); + __END_DECLS #endif /* !_SECURITY_SECTRUSTSTORESERVER_H_ */ diff --git a/trust/trustd/SecTrustStoreServer.m b/trust/trustd/SecTrustStoreServer.m index acb0fb48..1f67980d 100644 --- a/trust/trustd/SecTrustStoreServer.m +++ b/trust/trustd/SecTrustStoreServer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2018-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,15 +25,28 @@ #import #include #include +#include #include #include #include #include #include #import "OTATrustUtilities.h" +#include "trustdFileLocations.h" #include "SecTrustStoreServer.h" -typedef bool(*exceptionsArrayValueChecker)(id _Nonnull obj); +/* + * Each config file is a dictionary with NSString keys corresponding to the appIDs. + * The value for each appID is the config and is defined (and verified) by the config callbacks. + */ + +// +// MARK: Shared Configuration helpers +// +typedef bool(*arrayValueChecker)(id _Nonnull obj); +typedef NSDictionary *(^ConfigDiskReader)(NSURL * fileURL, NSError **error); +typedef bool (^ConfigCheckerAndSetter)(id newConfig, id *existingMutableConfig, CFErrorRef *error); +typedef CFTypeRef (^CombineAndCopyAllConfig)(NSDictionary *allConfig, CFErrorRef *error); static bool checkDomainsValuesCompliance(id _Nonnull obj) { if (![obj isKindOfClass:[NSString class]]) { @@ -52,23 +65,23 @@ static bool checkCAsValuesCompliance(id _Nonnull obj) { if (2 != [(NSDictionary*)obj count]) { return false; } - if (nil == ((NSDictionary*)obj)[(__bridge NSString*)kSecCTExceptionsHashAlgorithmKey] || - nil == ((NSDictionary*)obj)[(__bridge NSString*)kSecCTExceptionsSPKIHashKey]) { + if (nil == ((NSDictionary*)obj)[(__bridge NSString*)kSecTrustStoreHashAlgorithmKey] || + nil == ((NSDictionary*)obj)[(__bridge NSString*)kSecTrustStoreSPKIHashKey]) { return false; } - if (![((NSDictionary*)obj)[(__bridge NSString*)kSecCTExceptionsHashAlgorithmKey] isKindOfClass:[NSString class]] || - ![((NSDictionary*)obj)[(__bridge NSString*)kSecCTExceptionsSPKIHashKey] isKindOfClass:[NSData class]]) { + if (![((NSDictionary*)obj)[(__bridge NSString*)kSecTrustStoreHashAlgorithmKey] isKindOfClass:[NSString class]] || + ![((NSDictionary*)obj)[(__bridge NSString*)kSecTrustStoreSPKIHashKey] isKindOfClass:[NSData class]]) { return false; } - if (![((NSDictionary*)obj)[(__bridge NSString*)kSecCTExceptionsHashAlgorithmKey] isEqualToString:@"sha256"]) { + if (![((NSDictionary*)obj)[(__bridge NSString*)kSecTrustStoreHashAlgorithmKey] isEqualToString:@"sha256"]) { return false; } return true; } -static bool checkExceptionsValues(NSString *key, id value, exceptionsArrayValueChecker checker, CFErrorRef *error) { +static bool checkArrayValues(NSString *key, id value, arrayValueChecker checker, CFErrorRef *error) { if (![value isKindOfClass:[NSArray class]]) { - return SecError(errSecParam, error, CFSTR("value for %@ is not an array in exceptions dictionary"), key); + return SecError(errSecParam, error, CFSTR("value for %@ is not an array in configuration"), key); } __block bool result = true; @@ -81,23 +94,160 @@ static bool checkExceptionsValues(NSString *key, id value, exceptionsArrayValueC return result; } -static bool checkInputExceptionsAndSetAppExceptions(NSDictionary *inExceptions, NSMutableDictionary *appExceptions, CFErrorRef *error) { +static bool _SecTrustStoreSetConfiguration(CFStringRef appID, CFTypeRef configuration, CFErrorRef *error, + char *configurationType, NSURL *fileURL, _Atomic bool *cachedConfigExists, + char *notification, ConfigDiskReader readConfigFromDisk, + ConfigCheckerAndSetter checkAndSetConfig) +{ + if (!SecOTAPKIIsSystemTrustd()) { + secerror("Unable to write %{public}s from user agent", configurationType); + return SecError(errSecWrPerm, error, CFSTR("Unable to write %s from user agent"), configurationType); + } + + if (!appID) { + secerror("application-identifier required to set %{public}s", configurationType); + return SecError(errSecParam, error, CFSTR("application-identifier required to set %s"), configurationType); + } + + @autoreleasepool { + NSError *nserror = nil; + NSMutableDictionary *allConfig = [readConfigFromDisk(fileURL, &nserror) mutableCopy]; + id appConfig = NULL; + if (allConfig && allConfig[(__bridge NSString*)appID]) { + appConfig = [allConfig[(__bridge NSString*)appID] mutableCopy]; + } else if (!allConfig) { + allConfig = [NSMutableDictionary dictionary]; + } + + if (configuration) { + id inConfig = (__bridge id)configuration; + if (!checkAndSetConfig(inConfig, &appConfig, error)) { + secerror("%{public}s have error: %@", configurationType, error ? *error : nil); + return false; + } + } + + if (!configuration || [appConfig count] == 0) { + [allConfig removeObjectForKey:(__bridge NSString*)appID]; + } else { + allConfig[(__bridge NSString*)appID] = appConfig; + } + + if (![allConfig writeToClassDURL:fileURL permissions:0644 error:&nserror]) { + secerror("failed to write %{public}s: %@", configurationType, nserror); + if (error) { + *error = CFRetainSafe((__bridge CFErrorRef)nserror); + } + return false; + } + secnotice("config", "wrote %lu configs for %{public}s", (unsigned long)[allConfig count], configurationType); + atomic_store(cachedConfigExists, [allConfig count] != 0); + notify_post(notification); + return true; + } +} + +static void _SecTrustStoreCreateEmptyConfigCache(char *configurationType, _Atomic bool *cachedConfigExists, char *notification, int *notify_token, NSURL *fileURL, ConfigDiskReader readConfigFromDisk) +{ + @autoreleasepool { + NSError *read_error = nil; + NSDictionary *allConfig = readConfigFromDisk(fileURL, &read_error); + if (!allConfig|| [allConfig count] == 0) { + secnotice("config", "skipping further reads. no %{public}s found: %@", configurationType, read_error); + atomic_store(cachedConfigExists, false); + } else { + secnotice("config", "have %{public}s. will need to read.", configurationType); + atomic_store(cachedConfigExists, true); + } + + /* read-only trustds register for notfications from the read-write trustd */ + if (!SecOTAPKIIsSystemTrustd()) { + uint32_t status = notify_register_check(notification, notify_token); + if (status == NOTIFY_STATUS_OK) { + int check = 0; + status = notify_check(*notify_token, &check); + (void)check; // notify_check errors if we don't pass a second parameter, but we don't need the value here + } + if (status != NOTIFY_STATUS_OK) { + secerror("failed to establish notification for %{public}s: %u", configurationType, status); + notify_cancel(*notify_token); + *notify_token = 0; + } + } + } +} + +static CFTypeRef _SecTrustStoreCopyConfiguration(CFStringRef appID, CFErrorRef *error, char *configurationType, + _Atomic bool *cachedConfigExists, char *notification, int *notify_token, + NSURL *fileURL, ConfigDiskReader readConfigFromDisk, CombineAndCopyAllConfig combineAllConfig) { + @autoreleasepool { + /* Read the negative cached value as to whether there is config to read */ + if (!SecOTAPKIIsSystemTrustd()) { + /* Check whether we got a notification. If we didn't, and there is no config set, return NULL. + * Otherwise, we need to read from disk */ + int check = 0; + uint32_t check_status = notify_check(*notify_token, &check); + if (check_status == NOTIFY_STATUS_OK && check == 0 && !atomic_load(cachedConfigExists)) { + return NULL; + } + } else if (!atomic_load(cachedConfigExists)) { + return NULL; + } + + /* We need to read the config from disk */ + NSError *read_error = nil; + NSDictionary *allConfig = readConfigFromDisk(fileURL, &read_error); + if (!allConfig || [allConfig count] == 0) { + secnotice("config", "skipping further reads. no %{public}s found: %@", configurationType, read_error); + atomic_store(cachedConfigExists, false); + return NULL; + } + + /* If the caller specified an appID, return only the config for that appID */ + if (appID) { + return CFBridgingRetain(allConfig[(__bridge NSString*)appID]); + } + + return combineAllConfig(allConfig, error); + } +} + +// +// MARK: CT Exceptions +// + +ConfigCheckerAndSetter checkInputExceptionsAndSetAppExceptions = ^bool(id inConfig, id *appConfig, CFErrorRef *error) { __block bool result = true; + if (![inConfig isKindOfClass:[NSDictionary class]]) { + return SecError(errSecParam, error, CFSTR("value for CT Exceptions is not a dictionary in new configuration")); + } + + if (!appConfig || (*appConfig && ![*appConfig isKindOfClass:[NSMutableDictionary class]])) { + return SecError(errSecParam, error, CFSTR("value for CT Exceptions is not a dictionary in current configuration")); + } else if (!*appConfig) { + *appConfig = [NSMutableDictionary dictionary]; + } + + NSMutableDictionary *appExceptions = (NSMutableDictionary *)*appConfig; + NSDictionary *inExceptions = (NSDictionary *)inConfig; + if (inExceptions.count == 0) { + return true; + } [inExceptions enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { if ([key isEqualToString:(__bridge NSString*)kSecCTExceptionsDomainsKey]) { - if (!checkExceptionsValues(key, obj, checkDomainsValuesCompliance, error)) { + if (!checkArrayValues(key, obj, checkDomainsValuesCompliance, error)) { *stop = YES; result = false; return; } } else if ([key isEqualToString:(__bridge NSString*)kSecCTExceptionsCAsKey]) { - if (!checkExceptionsValues(key, obj, checkCAsValuesCompliance, error)) { + if (!checkArrayValues(key, obj, checkCAsValuesCompliance, error)) { *stop = YES; result = false; return; } } else { - result = SecError(errSecParam, error, CFSTR("unknown key (%@) in exceptions dictionary"), key); + result = SecError(errSecParam, error, CFSTR("unknown key (%@) in configuration dictionary"), key); *stop = YES; result = false; return; @@ -109,160 +259,305 @@ static bool checkInputExceptionsAndSetAppExceptions(NSDictionary *inExceptions, } }]; return result; -} +}; static _Atomic bool gHasCTExceptions = false; #define kSecCTExceptionsChanged "com.apple.trustd.ct.exceptions-changed" -static NSURL *CTExceptionsFileURL() { +static NSURL *CTExceptionsOldFileURL() { return CFBridgingRelease(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("CTExceptions.plist"))); } -static NSDictionary *readExceptionsFromDisk(NSError **error) { +static NSURL *CTExceptionsFileURL() { + return CFBridgingRelease(SecCopyURLForFileInPrivateTrustdDirectory(CFSTR("CTExceptions.plist"))); +} + +ConfigDiskReader readExceptionsFromDisk = ^NSDictionary *(NSURL *fileUrl, NSError **error) { secdebug("ct", "reading CT exceptions from disk"); - NSDictionary *allExceptions = [NSDictionary dictionaryWithContentsOfURL:CTExceptionsFileURL() + NSDictionary *allExceptions = [NSDictionary dictionaryWithContentsOfURL:fileUrl error:error]; return allExceptions; -} +}; bool _SecTrustStoreSetCTExceptions(CFStringRef appID, CFDictionaryRef exceptions, CFErrorRef *error) { - if (!SecOTAPKIIsSystemTrustd()) { - secerror("Unable to write CT exceptions from user agent"); - return SecError(errSecWrPerm, error, CFSTR("Unable to write CT exceptions from user agent")); - } - - if (!appID) { - secerror("application-identifier required to set exceptions"); - return SecError(errSecParam, error, CFSTR("application-identifier required to set exceptions")); - } - - @autoreleasepool { - NSError *nserror = nil; - NSMutableDictionary *allExceptions = [readExceptionsFromDisk(&nserror) mutableCopy]; - NSMutableDictionary *appExceptions = NULL; - if (allExceptions && allExceptions[(__bridge NSString*)appID]) { - appExceptions = [allExceptions[(__bridge NSString*)appID] mutableCopy]; - } else { - appExceptions = [NSMutableDictionary dictionary]; - if (!allExceptions) { - allExceptions = [NSMutableDictionary dictionary]; - } - } - - if (exceptions && (CFDictionaryGetCount(exceptions) > 0)) { - NSDictionary *inExceptions = (__bridge NSDictionary*)exceptions; - if (!checkInputExceptionsAndSetAppExceptions(inExceptions, appExceptions, error)) { - secerror("input exceptions have error: %@", error ? *error : nil); - return false; - } - } - - if (!exceptions || [appExceptions count] == 0) { - [allExceptions removeObjectForKey:(__bridge NSString*)appID]; - } else { - allExceptions[(__bridge NSString*)appID] = appExceptions; - } - - if (![allExceptions writeToURL:CTExceptionsFileURL() error:&nserror]) { - secerror("failed to write CT exceptions: %@", nserror); - if (error) { - *error = CFRetainSafe((__bridge CFErrorRef)nserror); - } - return false; - } - secnotice("ct", "wrote %lu CT exceptions", (unsigned long)[allExceptions count]); - atomic_store(&gHasCTExceptions, [allExceptions count] != 0); - notify_post(kSecCTExceptionsChanged); - return true; - } + return _SecTrustStoreSetConfiguration(appID, exceptions, error, "CT Exceptions", CTExceptionsFileURL(), + &gHasCTExceptions, kSecCTExceptionsChanged, readExceptionsFromDisk, + checkInputExceptionsAndSetAppExceptions); } +CombineAndCopyAllConfig combineAllCTExceptions = ^CFTypeRef(NSDictionary *allExceptions, CFErrorRef *error) { + NSMutableArray *domainExceptions = [NSMutableArray array]; + NSMutableArray *caExceptions = [NSMutableArray array]; + [allExceptions enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull __unused key, id _Nonnull appConfig, + BOOL * _Nonnull __unused stop) { + if (![appConfig isKindOfClass:[NSDictionary class]]) { + return; + } + + NSDictionary *appExceptions = (NSDictionary *)appConfig; + if (appExceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey] && + checkArrayValues((__bridge NSString*)kSecCTExceptionsDomainsKey, appExceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey], + checkDomainsValuesCompliance, error)) { + [domainExceptions addObjectsFromArray:appExceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey]]; + } + if (appExceptions[(__bridge NSString*)kSecCTExceptionsCAsKey] && + checkArrayValues((__bridge NSString*)kSecCTExceptionsCAsKey, appExceptions[(__bridge NSString*)kSecCTExceptionsCAsKey], + checkCAsValuesCompliance, error)) { + [caExceptions addObjectsFromArray:appExceptions[(__bridge NSString*)kSecCTExceptionsCAsKey]]; + } + }]; + NSMutableDictionary *exceptions = [NSMutableDictionary dictionaryWithCapacity:2]; + if ([domainExceptions count] > 0) { + exceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey] = domainExceptions; + } + if ([caExceptions count] > 0) { + exceptions[(__bridge NSString*)kSecCTExceptionsCAsKey] = caExceptions; + } + if ([exceptions count] > 0) { + secdebug("ct", "found %lu CT exceptions on disk", (unsigned long)[exceptions count]); + atomic_store(&gHasCTExceptions, true); + return CFBridgingRetain(exceptions); + } + return NULL; +}; + CFDictionaryRef _SecTrustStoreCopyCTExceptions(CFStringRef appID, CFErrorRef *error) { - @autoreleasepool { - /* Set us up for not reading the disk when there are never exceptions */ - static int notify_token = 0; - int check = 0; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - /* initialize gHashCTExceptions cache */ - NSError *read_error = nil; - NSDictionary *allExceptions = readExceptionsFromDisk(&read_error); - if (!allExceptions || [allExceptions count] == 0) { - secnotice("ct", "skipping further reads. no CT exceptions found: %@", read_error); - atomic_store(&gHasCTExceptions, false); - } else { - secnotice("ct", "have CT exceptions. will need to read."); - atomic_store(&gHasCTExceptions, true); - } - - /* read-only trustds register for notfications from the read-write trustd */ - if (!SecOTAPKIIsSystemTrustd()) { - uint32_t status = notify_register_check(kSecCTExceptionsChanged, ¬ify_token); - if (status == NOTIFY_STATUS_OK) { - status = notify_check(notify_token, NULL); - } - if (status != NOTIFY_STATUS_OK) { - secerror("failed to establish notification for CT exceptions: %ud", status); - notify_cancel(notify_token); - notify_token = 0; - } - } - }); - - /* Read the negative cached value as to whether there are any exceptions to read */ - if (!SecOTAPKIIsSystemTrustd()) { - /* Check whether we got a notification. If we didn't, and there are no exceptions set, return NULL. - * Otherwise, we need to read from disk */ - uint32_t check_status = notify_check(notify_token, &check); - if (check_status == NOTIFY_STATUS_OK && check == 0 && !atomic_load(&gHasCTExceptions)) { - return NULL; - } - } else if (!atomic_load(&gHasCTExceptions)) { - return NULL; - } - - /* We need to read the exceptions from disk */ - NSError *read_error = nil; - NSDictionary *allExceptions = readExceptionsFromDisk(&read_error); - if (!allExceptions || [allExceptions count] == 0) { - secnotice("ct", "skipping further reads. no CT exceptions found: %@", read_error); - atomic_store(&gHasCTExceptions, false); - return NULL; - } - - /* If the caller specified an appID, return only the exceptions for that appID */ - if (appID) { - return CFBridgingRetain(allExceptions[(__bridge NSString*)appID]); - } - - /* Otherwise, combine all the exceptions into one array */ - NSMutableArray *domainExceptions = [NSMutableArray array]; - NSMutableArray *caExceptions = [NSMutableArray array]; - [allExceptions enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull __unused key, NSDictionary * _Nonnull appExceptions, - BOOL * _Nonnull __unused stop) { - if (appExceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey] && - checkExceptionsValues((__bridge NSString*)kSecCTExceptionsDomainsKey, appExceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey], - checkDomainsValuesCompliance, error)) { - [domainExceptions addObjectsFromArray:appExceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey]]; - } - if (appExceptions[(__bridge NSString*)kSecCTExceptionsCAsKey] && - checkExceptionsValues((__bridge NSString*)kSecCTExceptionsCAsKey, appExceptions[(__bridge NSString*)kSecCTExceptionsCAsKey], - checkCAsValuesCompliance, error)) { - [caExceptions addObjectsFromArray:appExceptions[(__bridge NSString*)kSecCTExceptionsCAsKey]]; - } - }]; - NSMutableDictionary *exceptions = [NSMutableDictionary dictionaryWithCapacity:2]; - if ([domainExceptions count] > 0) { - exceptions[(__bridge NSString*)kSecCTExceptionsDomainsKey] = domainExceptions; - } - if ([caExceptions count] > 0) { - exceptions[(__bridge NSString*)kSecCTExceptionsCAsKey] = caExceptions; - } - if ([exceptions count] > 0) { - secdebug("ct", "found %lu CT exceptions on disk", (unsigned long)[exceptions count]); - atomic_store(&gHasCTExceptions, true); - return CFBridgingRetain(exceptions); - } - return NULL; - } + static int notify_token = 0; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _SecTrustStoreCreateEmptyConfigCache("CT Exceptions", + &gHasCTExceptions, kSecCTExceptionsChanged, ¬ify_token, + CTExceptionsFileURL(), readExceptionsFromDisk); + }); + return _SecTrustStoreCopyConfiguration(appID, error, "CT Exceptions", + &gHasCTExceptions, kSecCTExceptionsChanged, ¬ify_token, + CTExceptionsFileURL(), readExceptionsFromDisk, combineAllCTExceptions); +} + +// +// MARK: CA Revocation Additions +// + +ConfigCheckerAndSetter checkInputAdditionsAndSetAppAdditions = ^bool(id inConfig, id *appConfig, CFErrorRef *error) { + __block bool result = true; + if (![inConfig isKindOfClass:[NSDictionary class]]) { + return SecError(errSecParam, error, CFSTR("value for CA revocation additions is not a dictionary in new configuration")); + } + + if (!appConfig || (*appConfig && ![*appConfig isKindOfClass:[NSMutableDictionary class]])) { + return SecError(errSecParam, error, CFSTR("value for CA revocation additions is not a dictionary in existing configuration")); + } else if (!*appConfig) { + *appConfig = [NSMutableDictionary dictionary]; + } + + NSMutableDictionary *appAdditions = (NSMutableDictionary *)*appConfig; + NSDictionary *inAdditions = (NSDictionary *)inConfig; + if (inAdditions.count == 0) { + return true; + } + [inAdditions enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + if ([key isEqualToString:(__bridge NSString*)kSecCARevocationAdditionsKey]) { + if (!checkArrayValues(key, obj, checkCAsValuesCompliance, error)) { + *stop = YES; + result = false; + return; + } + } else { + result = SecError(errSecParam, error, CFSTR("unknown key (%@) in additions dictionary"), key); + *stop = YES; + result = false; + return; + } + if ([(NSArray*)obj count] == 0) { + [appAdditions removeObjectForKey:key]; + } else { + appAdditions[key] = obj; + } + }]; + return result; +}; + +static _Atomic bool gHasCARevocationAdditions = false; +#define kSecCARevocationChanged "com.apple.trustd.ca.revocation-changed" + +static NSURL *CARevocationOldFileURL() { + return CFBridgingRelease(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("CARevocation.plist"))); +} + +static NSURL *CARevocationFileURL() { + return CFBridgingRelease(SecCopyURLForFileInPrivateTrustdDirectory(CFSTR("CARevocation.plist"))); +} + +ConfigDiskReader readRevocationAdditionsFromDisk = ^NSDictionary *(NSURL *fileUrl, NSError **error) { + secdebug("ocsp", "reading CA revocation additions from disk"); + NSDictionary *allAdditions = [NSDictionary dictionaryWithContentsOfURL:fileUrl + error:error]; + return allAdditions; +}; + +bool _SecTrustStoreSetCARevocationAdditions(CFStringRef appID, CFDictionaryRef additions, CFErrorRef *error) { + return _SecTrustStoreSetConfiguration(appID, additions, error, "CA Revocation Additions", CARevocationFileURL(), + &gHasCARevocationAdditions, kSecCARevocationChanged, readRevocationAdditionsFromDisk, + checkInputAdditionsAndSetAppAdditions); +} + +CombineAndCopyAllConfig combineAllCARevocationAdditions = ^CFTypeRef(NSDictionary *allAdditions, CFErrorRef *error) { + NSMutableArray *caAdditions = [NSMutableArray array]; + [allAdditions enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull __unused key, id _Nonnull appConfig, + BOOL * _Nonnull __unused stop) { + if (![appConfig isKindOfClass:[NSDictionary class]]) { + return; + } + + NSDictionary *appAdditions = (NSDictionary *)appConfig; + if (appAdditions[(__bridge NSString*)kSecCARevocationAdditionsKey] && + checkArrayValues((__bridge NSString*)kSecCARevocationAdditionsKey, + appAdditions[(__bridge NSString*)kSecCARevocationAdditionsKey], + checkCAsValuesCompliance, error)) { + [caAdditions addObjectsFromArray:appAdditions[(__bridge NSString*)kSecCARevocationAdditionsKey]]; + } + }]; + NSMutableDictionary *additions = [NSMutableDictionary dictionaryWithCapacity:1]; + if ([caAdditions count] > 0) { + additions[(__bridge NSString*)kSecCARevocationAdditionsKey] = caAdditions; + } + if ([additions count] > 0) { + secdebug("ocsp", "found %lu CA revocation additions on disk", (unsigned long)[additions count]); + atomic_store(&gHasCARevocationAdditions, true); + return CFBridgingRetain(additions); + } + return NULL; +}; + +CFDictionaryRef _SecTrustStoreCopyCARevocationAdditions(CFStringRef appID, CFErrorRef *error) { + static int notify_token = 0; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _SecTrustStoreCreateEmptyConfigCache("CA Revocation Additions", + &gHasCARevocationAdditions, kSecCARevocationChanged, ¬ify_token, + CARevocationFileURL(), readRevocationAdditionsFromDisk); + }); + return _SecTrustStoreCopyConfiguration(appID, error, "CA Revocation Additions", + &gHasCARevocationAdditions, kSecCARevocationChanged, ¬ify_token, + CARevocationFileURL(), readRevocationAdditionsFromDisk, combineAllCARevocationAdditions); +} + +// +// MARK: Transparent Connection Pins +// +static _Atomic bool gHasTransparentConnectionPins = false; +#define kSecTransparentConnectionPinsChanged "com.apple.trustd.hrn.pins-changed" +const NSString *kSecCAPinsKey = @"CAPins"; + +static NSURL *TransparentConnectionPinsOldFileURL() { + return CFBridgingRelease(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("TransparentConnectionPins.plist"))); +} + +static NSURL *TransparentConnectionPinsFileURL() { + return CFBridgingRelease(SecCopyURLForFileInPrivateTrustdDirectory(CFSTR("TransparentConnectionPins.plist"))); +} + +ConfigDiskReader readPinsFromDisk = ^NSDictionary *(NSURL *fileUrl, NSError **error) { + secdebug("config", "reading Pins from disk"); + NSDictionary *allPins = [NSDictionary dictionaryWithContentsOfURL:fileUrl + error:error]; + return allPins; +}; + +ConfigCheckerAndSetter checkInputPinsAndSetPins = ^bool(id inConfig, id *appConfig, CFErrorRef *error) { + if (!appConfig || (*appConfig && ![*appConfig isKindOfClass:[NSMutableArray class]])) { + return SecError(errSecParam, error, CFSTR("value for Transparent Connection pins is not an array in existing configuration")); + } else if (!*appConfig) { + *appConfig = [NSMutableArray array]; + } + + if(!checkArrayValues(@"TransparentConnectionPins", inConfig, checkCAsValuesCompliance, error)) { + return false; + } + + // Replace (null input) or remove config + if (!inConfig) { + [*appConfig removeAllObjects]; + } else if ([inConfig count] > 0) { + *appConfig = [(NSArray*)inConfig mutableCopy]; + } + return true; +}; + +CombineAndCopyAllConfig combineAllPins = ^CFTypeRef(NSDictionary *allConfig, CFErrorRef *error) { + NSMutableArray *pins = [NSMutableArray array]; + [allConfig enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull __unused key, id _Nonnull obj, BOOL * _Nonnull __unused stop) { + if (checkArrayValues(@"TransparentConnectionPins", obj, checkCAsValuesCompliance, error)) { + [pins addObjectsFromArray:(NSArray *)obj]; + } + }]; + if ([pins count] > 0) { + secdebug("config", "found %lu Transparent Connection pins on disk", (unsigned long)[pins count]); + atomic_store(&gHasTransparentConnectionPins, true); + return CFBridgingRetain(pins); + } + return NULL; +}; + +bool _SecTrustStoreSetTransparentConnectionPins(CFStringRef appID, CFArrayRef pins, CFErrorRef *error) { + return _SecTrustStoreSetConfiguration(appID, pins, error, "Transparent Connection Pins", TransparentConnectionPinsFileURL(), + &gHasTransparentConnectionPins, kSecTransparentConnectionPinsChanged, + readPinsFromDisk, checkInputPinsAndSetPins); +} + +CFArrayRef _SecTrustStoreCopyTransparentConnectionPins(CFStringRef appID, CFErrorRef *error) { + static int notify_token = 0; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _SecTrustStoreCreateEmptyConfigCache("Transparent Connection Pins", + &gHasTransparentConnectionPins, kSecTransparentConnectionPinsChanged, ¬ify_token, + TransparentConnectionPinsFileURL(), readPinsFromDisk); + }); + return _SecTrustStoreCopyConfiguration(appID, error, "Transparent Connection Pins", + &gHasTransparentConnectionPins, kSecTransparentConnectionPinsChanged, ¬ify_token, + TransparentConnectionPinsFileURL(), readPinsFromDisk, combineAllPins); +} + +// +// MARK: One-time migration +// +static bool _SecTrustStoreMigrateConfiguration(NSURL *oldFileURL, NSURL *newFileURL, char *configurationType, ConfigDiskReader readConfigFromDisk) +{ + NSError *error; + if (readConfigFromDisk(newFileURL, &error)) { + secdebug("config", "already migrated %{public}s", configurationType); + return true; + } + NSDictionary *config = readConfigFromDisk(oldFileURL, &error); + if (!config) { + // always write something to the new config so that we can use it as a migration indicator + secdebug("config", "no existing %{public}s to migrate: %@", configurationType, error); + config = [NSDictionary dictionary]; + } + + secdebug("config", "migrating %{public}s", configurationType); + if (![config writeToClassDURL:newFileURL permissions:0644 error:&error]) { + secerror("failed to write %{public}s: %@", configurationType, error); + return false; + } + // Delete old file + WithPathInDirectory(CFBridgingRetain(oldFileURL), ^(const char *utf8String) { + remove(utf8String); + }); + return true; + +} + +void _SecTrustStoreMigrateConfigurations(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + if (SecOTAPKIIsSystemTrustd()) { + _SecTrustStoreMigrateConfiguration(CTExceptionsOldFileURL(), CTExceptionsFileURL(), + "CT Exceptions", readExceptionsFromDisk); + _SecTrustStoreMigrateConfiguration(CARevocationOldFileURL(), CARevocationFileURL(), + "CA Revocation Additions", readRevocationAdditionsFromDisk); + _SecTrustStoreMigrateConfiguration(TransparentConnectionPinsOldFileURL(), TransparentConnectionPinsFileURL(), + "Transparent Connection Pins", readPinsFromDisk); + } + }); } diff --git a/keychain/SigninMetrics/SFSignInAnalytics+Internal.h b/trust/trustd/TrustURLSessionCache.h similarity index 61% rename from keychain/SigninMetrics/SFSignInAnalytics+Internal.h rename to trust/trustd/TrustURLSessionCache.h index 9801140a..988d6eb3 100644 --- a/keychain/SigninMetrics/SFSignInAnalytics+Internal.h +++ b/trust/trustd/TrustURLSessionCache.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -19,24 +19,20 @@ * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ + * */ -#if __OBJC2__ -#ifndef SFSignInAnalytics_Internal_h -#define SFSignInAnalytics_Internal_h +#ifndef _SECURITY_TRUSTURLSESSIONCACHE_H_ +#define _SECURITY_TRUSTURLSESSIONCACHE_H_ -#import "SFSignInAnalytics.h" +#include +#include "trust/trustd/TrustURLSessionDelegate.h" -@interface SFSignInAnalytics (Internal) -@property (readonly) NSString *signin_uuid; -@property (readonly) NSString *my_uuid; --(instancetype) initChildWithSignInUUID:(NSString*)signin_uuid andCategory:(NSString*)category andEventName:(NSString*)eventName; +extern const NSString *TrustdUserAgent; + +@interface TrustURLSessionCache : NSObject +- (instancetype)initWithDelegate:(TrustURLSessionDelegate *)delegate; +- (NSURLSession *)sessionForAuditToken:(NSData *)auditToken; @end -@interface SFSIALoggerObject : SFAnalytics -+ (instancetype)logger; -- (instancetype)init NS_UNAVAILABLE; -@end - -#endif /* SFSignInAnalytics+Internal_h */ -#endif +#endif /* _SECURITY_TRUSTURLSESSIONCACHE_H_ */ diff --git a/trust/trustd/TrustURLSessionCache.m b/trust/trustd/TrustURLSessionCache.m new file mode 100644 index 00000000..b4dd9ba7 --- /dev/null +++ b/trust/trustd/TrustURLSessionCache.m @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#import +#import +#include +#include + +#include "trust/trustd/TrustURLSessionDelegate.h" +#include "trust/trustd/TrustURLSessionCache.h" + +#define MAX_CACHED_SESSIONS 20 +const NSString *TrustdUserAgent = @"com.apple.trustd/2.1"; + +static NSTimeInterval TrustURLSessionGetResourceTimeout(void) { + return (NSTimeInterval)3.0; +} + + +@interface TrustURLSessionCache() +@property TrustURLSessionDelegate *delegate; +@property NSMutableDictionary * _clientSessionMap; +@property NSMutableArray * _clientLRUList; +@end + +@implementation TrustURLSessionCache + +- (instancetype)initWithDelegate:(TrustURLSessionDelegate *)delegate +{ + if (self = [super init]) { + self.delegate = delegate; + self._clientSessionMap = [NSMutableDictionary dictionaryWithCapacity:MAX_CACHED_SESSIONS]; + self._clientLRUList = [NSMutableArray arrayWithCapacity:(MAX_CACHED_SESSIONS + 1)]; + } + return self; +} + +- (NSURLSession *)createSessionForAuditToken:(NSData *)auditToken +{ + NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + config.timeoutIntervalForResource = TrustURLSessionGetResourceTimeout(); + config.HTTPAdditionalHeaders = @{@"User-Agent" : TrustdUserAgent}; + config._sourceApplicationAuditTokenData = auditToken; + + NSOperationQueue *queue = [[NSOperationQueue alloc] init]; + + NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self.delegate delegateQueue:queue]; + return session; +} + +- (NSURLSession *)sessionForAuditToken:(NSData *)auditToken +{ + @synchronized (self._clientLRUList) { + NSURLSession *result = [self._clientSessionMap objectForKey:auditToken]; + if (result) { + /* insert the client to the front of the LRU list */ + [self._clientLRUList removeObject:auditToken]; + [self._clientLRUList insertObject:auditToken atIndex:0]; + secdebug("http", "re-using session for %@", auditToken); + return result; + } + /* Cache miss: create new session */ + result = [self createSessionForAuditToken:auditToken]; + [self._clientLRUList insertObject:auditToken atIndex:0]; + [self._clientSessionMap setObject:result forKey:auditToken]; + secdebug("http", "creating session for %@", auditToken); + if (self._clientLRUList.count > MAX_CACHED_SESSIONS) { + /* close the excess NSURLSession and remove it from our cache */ + NSData *removeToken = [self._clientLRUList objectAtIndex:(self._clientLRUList.count - 1)]; + NSURLSession *removeSession = [self._clientSessionMap objectForKey:removeToken]; + [removeSession finishTasksAndInvalidate]; + [self._clientSessionMap removeObjectForKey:removeToken]; + [self._clientLRUList removeLastObject]; + secdebug("http", "removing session for %@", removeToken); + } + return result; + } +} + +@end diff --git a/trust/trustd/TrustURLSessionDelegate.h b/trust/trustd/TrustURLSessionDelegate.h index ff9d4a02..2c6ff9dd 100644 --- a/trust/trustd/TrustURLSessionDelegate.h +++ b/trust/trustd/TrustURLSessionDelegate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2018-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -29,9 +29,8 @@ #include NS_ASSUME_NONNULL_BEGIN -/* This is our abstract NSURLSessionDelegate that handles the elements common to - * fetching data over the network during a trust evaluation */ -@interface TrustURLSessionDelegate : NSObject + +@interface TrustURLSessionContext : NSObject @property (assign, nullable) void *context; @property NSArray *URIs; @property NSUInteger URIix; @@ -39,11 +38,25 @@ NS_ASSUME_NONNULL_BEGIN @property NSTimeInterval expiration; @property NSUInteger numTasks; -- (BOOL)fetchNext:(NSURLSession *)session; -- (NSURLRequest *)createNextRequest:(NSURL *)uri; +- (instancetype)initWithContext:(void *)context uris:(NSArray *)uris; @end -NSTimeInterval TrustURLSessionGetResourceTimeout(void); +@interface NSURLRequest (TrustURLRequest) +- (NSUUID * _Nullable)taskId; +@end + +/* This is our abstract NSURLSessionDelegate that handles the elements common to + * fetching data over the network during a trust evaluation */ +@interface TrustURLSessionDelegate : NSObject + +/* The delegate superclass keeps track of all the tasks that have been kicked off (via fetchNext); + * it is the responsibility of the subclass to remove tasks when it is done with them. */ +- (TrustURLSessionContext *)contextForTask:(NSUUID *)taskId; +- (void)removeTask:(NSUUID *)taskId; + +- (BOOL)fetchNext:(NSURLSession *)session context:(TrustURLSessionContext *)context; +- (NSURLRequest *)createNextRequest:(NSURL *)uri context:(TrustURLSessionContext *)context; +@end NS_ASSUME_NONNULL_END #endif // __OBJC__ diff --git a/trust/trustd/TrustURLSessionDelegate.m b/trust/trustd/TrustURLSessionDelegate.m index 6698130a..06c5d4aa 100644 --- a/trust/trustd/TrustURLSessionDelegate.m +++ b/trust/trustd/TrustURLSessionDelegate.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2018-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,6 +30,8 @@ #include "TrustURLSessionDelegate.h" #define MAX_TASKS 3 +#define MAX_TIMEOUTS 2 +#define TIMEOUT_BACKOFF 60 // 1 minute /* There has got to be an easier way to do this. For now we based this code on CFNetwork/Connection/URLResponse.cpp. */ @@ -126,6 +128,66 @@ static CFStringRef copyParseMaxAge(CFStringRef cacheControlHeader) { return maxAgeValue; } +@implementation TrustURLSessionContext +- (instancetype)initWithContext:(void *)context uris:(NSArray *)uris +{ + if (self = [super init]) { + self.context = context; + self.URIs = uris; + self.URIix = 0; + self.numTasks = 0; + } + return self; +} +@end + +NSString *kSecTrustRequestHeaderUUID = @"X-Apple-Request-UUID"; + +@implementation NSURLRequest (TrustURLRequest) +- (NSUUID *)taskId { + NSString *uuidString = [[self allHTTPHeaderFields] objectForKey:kSecTrustRequestHeaderUUID]; + NSUUID *uuid = nil; + if (uuidString) { + uuid = [[NSUUID alloc] initWithUUIDString:uuidString]; + } + + return uuid; +} +@end + +@interface TimeoutEntry : NSObject +@property NSDate *lastAttemptDate; +@property NSUInteger timeoutCounter; +@end + +@implementation TimeoutEntry +- (instancetype)init +{ + if (self = [super init]) { + self.lastAttemptDate = [NSDate date]; + self.timeoutCounter = 1; + } + return self; +} +@end + +@interface TrustURLSessionDelegate() +@property NSMutableDictionary * _taskContextMap; +@property NSMutableDictionary * _serverMap; +/* + after getting a response: + 1. If no timeout and server is in map, remove the server from the map + 2. If timeout and server is not in map, add to map, setting date to now and counter to 1 + 3. If timeout and server is in map, set date to now and add + 1 to counter + + In terms of deciding whether to make a request: + 1. If not in map, go for it + 2. If in map and counter < MAX_TIMEOUTS, go for it + 3. If in map and counter > MAX_TIMEOUTS and date > TIMEOUT_BACKOFF ago, go for it + 4. otherwise, no network + */ +@end + @implementation TrustURLSessionDelegate - (id)init { /* Protect future developers from themselves */ @@ -135,31 +197,115 @@ static CFStringRef copyParseMaxAge(CFStringRef cacheControlHeader) { userInfo:nil]; @throw e; } else { + self._taskContextMap = [NSMutableDictionary dictionary]; + self._serverMap = [NSMutableDictionary dictionary]; return [super init]; } } -- (NSURLRequest *)createNextRequest:(NSURL *)uri { - return [NSURLRequest requestWithURL:uri]; +- (TrustURLSessionContext *)contextForTask:(NSUUID *)taskId +{ + @synchronized (self._taskContextMap) { + return [self._taskContextMap objectForKey:taskId]; + } } -- (BOOL)fetchNext:(NSURLSession *)session { - if (self.numTasks >= MAX_TASKS) { +- (void)removeTask:(NSUUID *)taskId +{ + @synchronized (self._taskContextMap) { + [self._taskContextMap removeObjectForKey:taskId]; + } +} + +- (NSUUID *)addTask:(TrustURLSessionContext *)context +{ + NSUUID *uuid = [NSUUID UUID]; + @synchronized (self._taskContextMap) { + [self._taskContextMap setObject:context forKey:uuid]; + } + return uuid; +} + +- (void)removeServer:(NSString *)server +{ + @synchronized (self._serverMap) { + [self._serverMap removeObjectForKey:server]; + } +} + +- (void)addServer:(NSString *)server +{ + TimeoutEntry *timeoutEntry = [[TimeoutEntry alloc] init]; + @synchronized (self._serverMap) { + self._serverMap[server] = timeoutEntry; + } +} + +- (void)incrementCountForServer:(NSString *)server +{ + @synchronized (self._serverMap) { + TimeoutEntry *entry = self._serverMap[server]; + if (!entry) { + [self addServer:server]; + } else { + entry.timeoutCounter += 1; + entry.lastAttemptDate = [NSDate date]; + self._serverMap[server] = entry; + } + } +} + +- (TimeoutEntry *)timeoutEntryForServer:(NSString *)server +{ + @synchronized (self._serverMap) { + TimeoutEntry *entry = self._serverMap[server]; + return entry; + } +} + +- (NSURLRequest *)createNextRequest:(NSURL *)uri context:(TrustURLSessionContext *)context { + NSURLComponents *components = [NSURLComponents componentsWithURL:uri resolvingAgainstBaseURL:YES]; + /* For Apple ocsp responders, use https instead of http */ + if ([[components host] isEqualToString:@"ocsp-uat.corp.apple.com"]) { + secdebug("http", "replacing http test ocsp responder URI with https"); + components.scheme = @"https"; + } else if ([[components host] isEqualToString:@"ocsp.apple.com"]) { + secdebug("http", "replacing http prod ocsp responder URI with https"); + components.scheme = @"https"; + components.host = @"ocsp2.apple.com"; + } + NSURL *requestUri = components.URL; + + NSUUID *taskId = [self addTask:context]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestUri]; + [request addValue:[taskId UUIDString] forHTTPHeaderField:kSecTrustRequestHeaderUUID]; + return request; +} + +- (BOOL)fetchNext:(NSURLSession *)session context:(TrustURLSessionContext *)context { + if (context.numTasks >= MAX_TASKS) { secnotice("http", "Too many fetch %@ requests for this cert", [self class]); return true; } - for (NSUInteger ix = self.URIix; ix < [self.URIs count]; ix++) { - NSURL *uri = self.URIs[ix]; - if ([[uri scheme] isEqualToString:@"http"]) { - self.URIix = ix + 1; // Next time we'll start with the next index - self.numTasks++; - NSURLSessionTask *task = [session dataTaskWithRequest:[self createNextRequest:uri]]; - [task resume]; - secinfo("http", "request for uri: %@", uri); - return false; // we scheduled a job + for (NSUInteger ix = context.URIix; ix < [context.URIs count]; ix++) { + NSURL *uri = context.URIs[ix]; + TimeoutEntry *timeoutEntry = [self timeoutEntryForServer:uri.host]; + if (!timeoutEntry || // no recent timeout + timeoutEntry.timeoutCounter < MAX_TIMEOUTS || // too few recent timeouts + [timeoutEntry.lastAttemptDate timeIntervalSinceNow] < -TIMEOUT_BACKOFF) { // last timeout not recent enough + if ([[uri scheme] isEqualToString:@"http"]) { + context.URIix = ix + 1; // Next time we'll start with the next index + context.numTasks++; + NSURLSessionTask *task = [session dataTaskWithRequest:[self createNextRequest:uri context:context]]; + [task resume]; + secinfo("http", "request for uri: %@", uri); + return false; // we scheduled a job + } else { + secnotice("http", "skipping unsupported scheme %@", [uri scheme]); + } } else { - secnotice("http", "skipping unsupported scheme %@", [uri scheme]); + secnotice("http", "skipping host due to too many recent timeouts: %@", uri.host); } } @@ -170,10 +316,18 @@ static CFStringRef copyParseMaxAge(CFStringRef cacheControlHeader) { - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { /* Append the data to the response data*/ - if (!_response) { - _response = [NSMutableData data]; + NSUUID *taskId = [dataTask.originalRequest taskId]; + TrustURLSessionContext *context = [self contextForTask:taskId]; + if (!context) { + secerror("failed to find task for taskId: %@", taskId); + return; } - [_response appendData:data]; + + secdebug("http", "received data for taskId %@", taskId); + if (!context.response) { + context.response = [NSMutableData data]; + } + [context.response appendData:data]; } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { @@ -184,14 +338,33 @@ static CFStringRef copyParseMaxAge(CFStringRef cacheControlHeader) { userInfo:nil]; @throw e; } else { - _expiration = 60.0 * 60.0 * 24.0 * 7; /* Default is 7 days */ - if ([_response length] > 0 && [[task response] isKindOfClass:[NSHTTPURLResponse class]]) { + NSUUID *taskId = [task.originalRequest taskId]; + TrustURLSessionContext *context = [self contextForTask:taskId]; + if (!context) { + secerror("failed to find task for taskId: %@", taskId); + return; + } + + secdebug("http", "completed taskId %@", taskId); + context.expiration = 60.0 * 60.0 * 24.0 * 7; /* Default is 7 days */ + if ([context.response length] > 0 && [[task response] isKindOfClass:[NSHTTPURLResponse class]]) { NSString *cacheControl = [[(NSHTTPURLResponse *)[task response] allHeaderFields] objectForKey:@"cache-control"]; NSString *maxAge = CFBridgingRelease(copyParseMaxAge((__bridge CFStringRef)cacheControl)); - if (maxAge && [maxAge doubleValue] > _expiration) { - _expiration = [maxAge doubleValue]; + if (maxAge && [maxAge doubleValue] > context.expiration) { + context.expiration = [maxAge doubleValue]; } } + + // Update server map for timeout backoffs + NSString *host = task.originalRequest.URL.host; + if (host && error && [error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorTimedOut) { + // timeout error + secdebug("http", "incrementing timeout counter for %@", host); + [self incrementCountForServer:host]; + } else if (host) { + secdebug("http", "removing timeout entry for %@", host); + [self removeServer:host]; + } } } @@ -204,8 +377,37 @@ willPerformHTTPRedirection:(NSHTTPURLResponse *)redirectResponse secnotice("http", "failed redirection for %@", task.originalRequest.URL); [task cancel]; } -@end -NSTimeInterval TrustURLSessionGetResourceTimeout(void) { - return (NSTimeInterval)3.0; +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler +{ + if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { + /* Disable networking during trust evaluation to avoid recursion */ + secdebug("http", "server using TLS; disabling network for trust evaluation"); + SecTrustRef trust = challenge.protectionSpace.serverTrust; + OSStatus status = SecTrustSetNetworkFetchAllowed(trust, false); + if (status != errSecSuccess) { + goto cancel; + } + + CFErrorRef error = nil; + if (!SecTrustEvaluateWithError(trust, &error)) { + secerror("failed to connect to server: %@", error); + CFReleaseNull(error); + goto cancel; + } else { + completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust: trust]); + } + return; + + cancel: + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL); + return; + + } else { + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, NULL); + } } +@end diff --git a/trust/trustd/iOS/com.apple.trustd.plist b/trust/trustd/iOS/com.apple.trustd.plist index fa838619..389907ef 100644 --- a/trust/trustd/iOS/com.apple.trustd.plist +++ b/trust/trustd/iOS/com.apple.trustd.plist @@ -14,7 +14,7 @@ NO GroupName - _securityd + _trustd Label com.apple.trustd MachServices @@ -29,7 +29,7 @@ Umask 54 UserName - _securityd + _trustd POSIXSpawnType Adaptive MinimalBootProfile diff --git a/trust/trustd/iOS/entitlements.plist b/trust/trustd/iOS/entitlements.plist index dc6f6d2e..1b54dc3c 100644 --- a/trust/trustd/iOS/entitlements.plist +++ b/trust/trustd/iOS/entitlements.plist @@ -19,9 +19,17 @@ com.apple.MobileAsset.PKITrustSupplementals com.apple.MobileAsset.SecExperimentAssets + com.apple.private.security.storage.trustd + + com.apple.private.security.storage.trustd-private + + com.apple.private.security.storage.SFAnalytics + seatbelt-profiles trustd + com.apple.private.trustd.FileHelp + diff --git a/trust/trustd/macOS/com.apple.trustd.plist b/trust/trustd/macOS/com.apple.trustd.plist index fac729cb..b3780e3c 100644 --- a/trust/trustd/macOS/com.apple.trustd.plist +++ b/trust/trustd/macOS/com.apple.trustd.plist @@ -26,5 +26,9 @@ /usr/libexec/trustd + UserName + _trustd + Umask + 27 diff --git a/trust/trustd/macOS/com.apple.trustd.sb b/trust/trustd/macOS/com.apple.trustd.sb index f13684b1..9fdd123b 100644 --- a/trust/trustd/macOS/com.apple.trustd.sb +++ b/trust/trustd/macOS/com.apple.trustd.sb @@ -38,6 +38,7 @@ (allow file-read* file-write* (subpath "/private/var/db/mds/") (subpath "/private/var/db/crls/") + (subpath "/private/var/protected/") (subpath "/System/Library/Security/") (subpath "/Library/Keychains/") (subpath "/private/var/root/Library/Caches/com.apple.nsurlsessiond/")) @@ -58,15 +59,34 @@ (global-name "com.apple.ocspd") (global-name "com.apple.SecurityServer") (global-name "com.apple.SystemConfiguration.configd") + (global-name "com.apple.mobileassetd") (global-name "com.apple.mobileassetd.v2") (global-name "com.apple.securityd.xpc") (global-name "com.apple.cfnetwork.cfnetworkagent") (global-name "com.apple.nsurlsessiond") + (global-name "com.apple.dnssd.service") (xpc-service-name "com.apple.powerlog.plxpclogger.xpc") - (global-name "com.apple.nesessionmanager.content-filter")) + (global-name "com.apple.nesessionmanager.content-filter") + (global-name "com.apple.trustdFileHelper") + (global-name "com.apple.AppSSO.service-xpc")) (allow ipc-posix-shm (ipc-posix-name "com.apple.AppleDatabaseChanged")) + ;; Read IOKit properties for personalization + (allow iokit-get-properties + (iokit-property "image4-supported") + (iokit-property "Content") + (iokit-property "boot-uuid") + (iokit-property "IORegistryEntryPropertyKeys") + (iokit-property "IOClassNameOverride") + (iokit-property "Protocol Characteristics") + (iokit-property "board-id") + (iokit-property "chip-id") + (iokit-property "unique-chip-id") + (iokit-property "boot-manifest-hash") + (iokit-property "crypto-hash-method") + (iokit-property "boot-objects-path")) + (allow network-outbound) (allow system-socket) diff --git a/trust/trustd/macOS/entitlements.plist b/trust/trustd/macOS/entitlements.plist index efa5ea47..0cb68648 100644 --- a/trust/trustd/macOS/entitlements.plist +++ b/trust/trustd/macOS/entitlements.plist @@ -19,5 +19,13 @@ com.apple.MobileAsset.PKITrustSupplementals com.apple.MobileAsset.SecExperimentAssets + com.apple.private.security.storage.trustd + + com.apple.private.security.storage.trustd-private + + com.apple.private.security.storage.SFAnalytics + + com.apple.private.trustd.FileHelp + diff --git a/trust/trustd/md.m b/trust/trustd/md.m index c918e7d2..de81408b 100644 --- a/trust/trustd/md.m +++ b/trust/trustd/md.m @@ -40,4 +40,5 @@ #include "trust/trustd/SecCertificateSource.h" #include "trust/trustd/SecPolicyServer.h" #include "trust/trustd/SecTrustLoggingServer.h" +#include "trust/trustd/trustdFileLocations.h" diff --git a/trust/trustd/trustd.c b/trust/trustd/trustd.c index baa86a65..d930984a 100644 --- a/trust/trustd/trustd.c +++ b/trust/trustd/trustd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2017-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -57,9 +57,8 @@ #include "trust/trustd/SecTrustServer.h" #include "keychain/securityd/spi.h" #include "trust/trustd/SecTrustLoggingServer.h" -#if TARGET_OS_IPHONE #include "trust/trustd/SecTrustExceptionResetCount.h" -#endif +#include "trust/trustd/trustdFileLocations.h" #if TARGET_OS_OSX #include @@ -161,14 +160,14 @@ static bool SecXPCTrustStoreContains(SecurityClient * __unused client, xpc_objec bool result = false; SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, error); if (ts) { - CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, error); - if (digest) { + SecCertificateRef cert = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, error); + if (cert) { bool contains; - if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, error)) { + if (_SecTrustStoreContainsCertificate(ts, cert, &contains, error)) { xpc_dictionary_set_bool(reply, kSecXPCKeyResult, contains); result = true; } - CFReleaseNull(digest); + CFReleaseNull(cert); } } return result; @@ -198,11 +197,11 @@ static bool SecXPCTrustStoreRemoveCertificate(SecurityClient * __unused client, xpc_object_t reply, CFErrorRef *error) { SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, error); if (ts) { - CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, error); - if (digest) { - bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, error); + SecCertificateRef cert = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, error); + if (cert) { + bool result = _SecTrustStoreRemoveCertificate(ts, cert, error); xpc_dictionary_set_bool(reply, kSecXPCKeyResult, result); - CFReleaseNull(digest); + CFReleaseNull(cert); return true; } } @@ -228,15 +227,15 @@ static bool SecXPCTrustStoreCopyUsageConstraints(SecurityClient * __unused clien bool result = false; SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, error); if (ts) { - CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, error); - if (digest) { + SecCertificateRef cert = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, error); + if (cert) { CFArrayRef usageConstraints = NULL; - if(_SecTrustStoreCopyUsageConstraints(ts, digest, &usageConstraints, error) && usageConstraints) { + if(_SecTrustStoreCopyUsageConstraints(ts, cert, &usageConstraints, error) && usageConstraints) { SecXPCDictionarySetPList(reply, kSecXPCKeyResult, usageConstraints, error); CFReleaseNull(usageConstraints); result = true; } - CFReleaseNull(digest); + CFReleaseNull(cert); } } return result; @@ -305,7 +304,7 @@ static bool SecXPC_OTASecExperiment_GetAsset(SecurityClient * __unused client, x return result; } -static bool SecXPC_OTAPKI_CopyTrustedCTLogs(SecurityClient * __unused client, xpc_object_t event, +static bool SecXPC_OTAPKI_CopyTrustedCTLogs(SecurityClient * __unused client, xpc_object_t __unused event, xpc_object_t reply, CFErrorRef *error) { bool result = false; CFDictionaryRef trustedLogs = SecOTAPKICopyCurrentTrustedCTLogs(error); @@ -381,7 +380,60 @@ static bool SecXPCTrustStoreCopyCTExceptions(SecurityClient * __unused client, x return false; } -#if TARGET_OS_IPHONE +static bool SecXPCTrustStoreSetCARevocationAdditions(SecurityClient *client, xpc_object_t event, + xpc_object_t reply, CFErrorRef *error) { + CFStringRef appID = NULL; + CFDictionaryRef additions = NULL; + if (!SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error) || !appID) { + /* We always want to set the app ID with the additions */ + appID = SecTaskCopyApplicationIdentifier(client->task); + } + (void)SecXPCDictionaryCopyDictionaryOptional(event, kSecTrustRevocationAdditionsKey, &additions, error); + bool result = _SecTrustStoreSetCARevocationAdditions(appID, additions, error); + xpc_dictionary_set_bool(reply, kSecXPCKeyResult, result); + CFReleaseNull(additions); + CFReleaseNull(appID); + return false; +} + +static bool SecXPCTrustStoreCopyCARevocationAdditions(SecurityClient * __unused client, xpc_object_t event, + xpc_object_t reply, CFErrorRef *error) { + CFStringRef appID = NULL; + (void)SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error); + CFDictionaryRef additions = _SecTrustStoreCopyCARevocationAdditions(appID, error); + SecXPCDictionarySetPListOptional(reply, kSecTrustRevocationAdditionsKey, additions, error); + CFReleaseNull(additions); + CFReleaseNull(appID); + return false; +} + +static bool SecXPCTrustStoreSetTransparentConnectionPins(SecurityClient *client, xpc_object_t event, + xpc_object_t reply, CFErrorRef *error) { + CFStringRef appID = NULL; + CFArrayRef pins = NULL; + if (!SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error) || !appID) { + /* We always want to set the app ID with the additions */ + appID = SecTaskCopyApplicationIdentifier(client->task); + } + (void)SecXPCDictionaryCopyArrayOptional(event, kSecTrustAnchorsKey, &pins, error); + bool result = _SecTrustStoreSetTransparentConnectionPins(appID, pins, error); + xpc_dictionary_set_bool(reply, kSecXPCKeyResult, result); + CFReleaseNull(pins); + CFReleaseNull(appID); + return false; +} + +static bool SecXPCTrustStoreCopyTransparentConnectionPins(SecurityClient * __unused client, xpc_object_t event, + xpc_object_t reply, CFErrorRef *error) { + CFStringRef appID = NULL; + (void)SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error); + CFArrayRef pins = _SecTrustStoreCopyTransparentConnectionPins(appID, error); + SecXPCDictionarySetPListOptional(reply, kSecTrustAnchorsKey, pins, error); + CFReleaseNull(pins); + CFReleaseNull(appID); + return false; +} + static bool SecXPCTrustGetExceptionResetCount(SecurityClient * __unused client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error) { uint64_t exceptionResetCount = SecTrustServerGetExceptionResetCount(error); if (error && *error) { @@ -402,7 +454,12 @@ static bool SecXPCTrustIncrementExceptionResetCount(SecurityClient * __unused cl xpc_dictionary_set_bool(reply, kSecXPCKeyResult, status); return result; } -#endif + +static bool SecXPC_Valid_Update(SecurityClient * __unused client, xpc_object_t __unused event, + xpc_object_t reply, CFErrorRef *error) { + xpc_dictionary_set_uint64(reply, kSecXPCKeyResult, SecRevocationDbUpdate(error)); + return true; +} typedef bool(*SecXPCOperationHandler)(SecurityClient *client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error); @@ -429,10 +486,13 @@ struct trustd_operations { SecXPCServerOperation trust_store_copy_ct_exceptions; SecXPCServerOperation ota_secexperiment_get_asset; SecXPCServerOperation ota_secexperiment_get_new_asset; -#if TARGET_OS_IPHONE SecXPCServerOperation trust_get_exception_reset_count; SecXPCServerOperation trust_increment_exception_reset_count; -#endif + SecXPCServerOperation trust_store_set_ca_revocation_additions; + SecXPCServerOperation trust_store_copy_ca_revocation_additions; + SecXPCServerOperation valid_update; + SecXPCServerOperation trust_store_set_transparent_connection_pins; + SecXPCServerOperation trust_store_copy_transparent_connection_pins; }; static struct trustd_operations trustd_ops = { @@ -453,10 +513,13 @@ static struct trustd_operations trustd_ops = { .networking_analytics_report = { NULL, SecXPC_Networking_AnalyticsReport }, .trust_store_set_ct_exceptions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreSetCTExceptions }, .trust_store_copy_ct_exceptions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyCTExceptions }, -#if TARGET_OS_IPHONE .trust_get_exception_reset_count = { NULL, SecXPCTrustGetExceptionResetCount }, .trust_increment_exception_reset_count = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustIncrementExceptionResetCount }, -#endif + .trust_store_set_ca_revocation_additions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreSetCARevocationAdditions }, + .trust_store_copy_ca_revocation_additions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyCARevocationAdditions }, + .valid_update = { NULL, SecXPC_Valid_Update }, + .trust_store_set_transparent_connection_pins = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreSetTransparentConnectionPins }, + .trust_store_copy_transparent_connection_pins = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyTransparentConnectionPins }, }; static void trustd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) { @@ -610,14 +673,27 @@ static void trustd_xpc_dictionary_handler(const xpc_connection_t connection, xpc case kSecXPCOpCopyCTExceptions: server_op = &trustd_ops.trust_store_copy_ct_exceptions; break; -#if TARGET_OS_IPHONE case sec_trust_get_exception_reset_count_id: server_op = &trustd_ops.trust_get_exception_reset_count; break; case sec_trust_increment_exception_reset_count_id: server_op = &trustd_ops.trust_increment_exception_reset_count; break; -#endif + case kSecXPCOpSetCARevocationAdditions: + server_op = &trustd_ops.trust_store_set_ca_revocation_additions; + break; + case kSecXPCOpCopyCARevocationAdditions: + server_op = &trustd_ops.trust_store_copy_ca_revocation_additions; + break; + case kSecXPCOpValidUpdate: + server_op = &trustd_ops.valid_update; + break; + case kSecXPCOpSetTransparentConnectionPins: + server_op = &trustd_ops.trust_store_set_transparent_connection_pins; + break; + case kSecXPCOpCopyTransparentConnectionPins: + server_op = &trustd_ops.trust_store_copy_transparent_connection_pins; + break; default: break; } @@ -742,6 +818,18 @@ static void trustd_sandbox(void) { #endif // !TARGET_OS_OSX } +static void listen_for_sigterm(dispatch_queue_t queue) +{ + signal(SIGTERM, SIG_IGN); + static dispatch_source_t terminateSource = NULL; + terminateSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, queue); + dispatch_source_set_event_handler(terminateSource, ^ { + secinfo("serverxpc", "Received signal SIGTERM. Will terminate when clean."); + xpc_transaction_exit_clean(); + }); + dispatch_activate(terminateSource); +} + int main(int argc, char *argv[]) { DisableLocalization(); @@ -754,32 +842,20 @@ int main(int argc, char *argv[]) kill(getpid(), SIGSTOP); } - // fails in Darling because launchd sets the wrong HOME for its tasks - // doesn't matter because our libsanbox is a stub anyways (we don't do sandboxing) - // TODO: fix that by changing the user's home directory in our `/etc/passwd` (which is where launchd gets its value for HOME from) -#ifndef DARLING trustd_sandbox(); -#endif + FixTrustdFilePermissions(); + /* set up SQLite before some other component has a chance to create a database connection */ + _SecDbServerSetup(); const char *serviceName = kTrustdXPCServiceName; if (argc > 1 && (!strcmp(argv[1], "--agent"))) { serviceName = kTrustdAgentXPCServiceName; } - /* set up SQLite before some other component has a chance to create a database connection */ - _SecDbServerSetup(); - - gTrustd = &trustd_spi; - - /* Initialize static content */ - SecPolicyServerInitialize(); // set up callbacks for policy checks - SecRevocationDbInitialize(); // set up revocation database if it doesn't already exist, or needs to be replaced - SecPinningDbInitialize(); // set up the pinning database -#if TARGET_OS_OSX - SecTrustLegacySourcesListenForKeychainEvents(); // set up the legacy keychain event listeners (for cache invalidation) -#endif - + /* migrate files and initialize static content */ + trustd_init_server(); /* We're ready now. Go. */ + listen_for_sigterm(SecTrustServerGetWorkloop()); trustd_xpc_init(serviceName); dispatch_main(); } diff --git a/trust/trustd/trustdFileHelper/com.apple.trustdFileHelper.plist b/trust/trustd/trustdFileHelper/com.apple.trustdFileHelper.plist new file mode 100644 index 00000000..58024f76 --- /dev/null +++ b/trust/trustd/trustdFileHelper/com.apple.trustdFileHelper.plist @@ -0,0 +1,34 @@ + + + + + EnablePressuredExit + + EnableTransactions + + EnvironmentVariables + + DEBUGSCOPE + -policy-node,policy-set,policy,alloc,trust,bind,profile,trace,dbconn,OTR,serverxpc,sqlite3,error_thee_well + WAIT4DEBUGGER + NO + + Label + com.apple.trustdFileHelper + MachServices + + com.apple.trustdFileHelper + + + POSIXSpawnType + Adaptive + ProgramArguments + + /usr/libexec/trustdFileHelper + + UserName + root + Umask + 27 + + diff --git a/trust/trustd/trustdFileHelper/com.apple.trustdFileHelper.sb b/trust/trustd/trustdFileHelper/com.apple.trustdFileHelper.sb new file mode 100644 index 00000000..9e66fc65 --- /dev/null +++ b/trust/trustd/trustdFileHelper/com.apple.trustdFileHelper.sb @@ -0,0 +1,41 @@ +(version 1) + +(deny default) +(deny file-map-executable process-info* nvram*) +(deny dynamic-code-generation) + +(deny mach-priv-host-port) + +(import "system.sb") +(import "com.apple.corefoundation.sb") +(corefoundation) + +(allow process-info* (target self)) + +;; For resolving symlinks, realpath(3), and equivalents. +(allow file-read-metadata) + +;; Global preferences +(allow user-preference-read + (preference-domain ".GlobalPreferences")) + +;; For validating the entitlements of clients. +(allow process-info-codesignature) + +;; Read/write access to a temporary directory. +(allow file-read* file-write* + (subpath (param "_TMPDIR")) + (subpath (param "_DARWIN_CACHE_DIR"))) + +;; Delete un-needed files +(allow file-read-metadata file-write-unlink + (subpath "/Library/Keychains/")) + +;; Fix permissions on files in trustd's data vault +(allow file-write-mode file-write-owner + (subpath "/private/var/protected/trustd")) + +(allow file-read* + (literal "/usr/libexec") + (literal "/usr/libexec/trustdFileHelper") + (regex #"/.GlobalPreferences[^/]*\.plist")) diff --git a/trust/trustd/trustdFileHelper/entitlements.plist b/trust/trustd/trustdFileHelper/entitlements.plist new file mode 100644 index 00000000..39be87ac --- /dev/null +++ b/trust/trustd/trustdFileHelper/entitlements.plist @@ -0,0 +1,8 @@ + + + + + com.apple.private.security.storage.trustd + + + diff --git a/trust/trustd/trustdFileHelper/main.m b/trust/trustd/trustdFileHelper/main.m new file mode 100644 index 00000000..f6d166e2 --- /dev/null +++ b/trust/trustd/trustdFileHelper/main.m @@ -0,0 +1,115 @@ +// +// main.m +// trustdFileHelper +// +// Copyright © 2020 Apple Inc. All rights reserved. +// + +#import +#import +#import +#import + +#import +#import +#import + +#import +#include +#include +#include + +#include "trust/trustd/trustdFileLocations.h" +#include "trust/trustd/trustdFileHelper/trustdFileHelper.h" + +@interface ServiceDelegate : NSObject +@end + +@implementation ServiceDelegate + +- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection +{ + if(![[newConnection valueForEntitlement:@"com.apple.private.trustd.FileHelp"] boolValue]) { + SecTaskRef clientTask = SecTaskCreateWithAuditToken(NULL, [newConnection auditToken]); + secerror("rejecting client %@ due to lack of entitlement", clientTask); + CFReleaseNull(clientTask); + return NO; + } + + secdebug("ipc", "opening connection for %d", [newConnection processIdentifier]); + newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(TrustdFileHelper_protocol)]; + TrustdFileHelper *exportedObject = [[TrustdFileHelper alloc] init]; + newConnection.exportedObject = exportedObject; + [newConnection resume]; + return YES; +} + +@end + +static void enter_sandbox(void) { + char buf[PATH_MAX] = ""; + + if (!_set_user_dir_suffix("com.apple.trustd") || + confstr(_CS_DARWIN_USER_TEMP_DIR, buf, sizeof(buf)) == 0 || + (mkdir(buf, 0700) && errno != EEXIST)) { + secerror("failed to initialize temporary directory (%d): %s", errno, strerror(errno)); + exit(EXIT_FAILURE); + } + + char *tempdir = realpath(buf, NULL); + if (tempdir == NULL) { + secerror("failed to resolve temporary directory (%d): %s", errno, strerror(errno)); + exit(EXIT_FAILURE); + } + + if (confstr(_CS_DARWIN_USER_CACHE_DIR, buf, sizeof(buf)) == 0 || + (mkdir(buf, 0700) && errno != EEXIST)) { + secerror("failed to initialize cache directory (%d): %s", errno, strerror(errno)); + exit(EXIT_FAILURE); + } + + char *cachedir = realpath(buf, NULL); + if (cachedir == NULL) { + secerror("failed to resolve cache directory (%d): %s", errno, strerror(errno)); + exit(EXIT_FAILURE); + } + + const char *parameters[] = { + "_TMPDIR", tempdir, + "_DARWIN_CACHE_DIR", cachedir, + NULL + }; + + char *sberror = NULL; + if (sandbox_init_with_parameters("com.apple.trustdFileHelper", SANDBOX_NAMED, parameters, &sberror) != 0) { + secerror("Failed to enter trustdFileHelper sandbox: %{public}s", sberror); + exit(EXIT_FAILURE); + } + + free(tempdir); + free(cachedir); +} + +int +main(int argc, const char *argv[]) +{ + [NSError _setFileNameLocalizationEnabled:NO]; + enter_sandbox(); + + static NSXPCListener *listener = nil; + + ServiceDelegate *delegate = [ServiceDelegate new]; + listener = [[NSXPCListener alloc] initWithMachServiceName:@TrustdFileHelperXPCServiceName]; + listener.delegate = delegate; + + // We're always launched in response to client activity and don't want to sit around idle. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5ull * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + secnotice("lifecycle", "will exit when clean"); + xpc_transaction_exit_clean(); + }); + + [listener resume]; + secdebug("ipc", "trustdFileHelper accepting work"); + + dispatch_main(); +} diff --git a/trust/trustd/trustdFileHelper/trustdFileHelper.8 b/trust/trustd/trustdFileHelper/trustdFileHelper.8 new file mode 100644 index 00000000..4a318113 --- /dev/null +++ b/trust/trustd/trustdFileHelper/trustdFileHelper.8 @@ -0,0 +1,13 @@ +.Dd Thu Dec 17 2020 \" DATE +.Dt trustdFileHelper 8 \" Program name and manual section number +.Os +.Sh NAME \" Section Header - required - don't modify +.Nm trustdFileHelper +.Nd Daemon that helps trustd with files +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Sh DESCRIPTION \" Section Header - required - don't modify +.Nm +provides services to trustd for modifying files. +.Pp +This command is not intended to be invoked directly. diff --git a/trust/trustd/trustdFileHelper/trustdFileHelper.h b/trust/trustd/trustdFileHelper/trustdFileHelper.h new file mode 100644 index 00000000..75c42747 --- /dev/null +++ b/trust/trustd/trustdFileHelper/trustdFileHelper.h @@ -0,0 +1,18 @@ +// +// trustdFileHelper.h +// Security +// +// Copyright © 2020 Apple Inc. All rights reserved. +// + +#ifndef _SECURITY_TRUSTDFILEHELPER_H_ +#define _SECURITY_TRUSTDFILEHELPER_H_ + +#import +#include "trust/trustd/trustdFileLocations.h" + +@interface TrustdFileHelper : NSObject +- (void)fixFiles:(void (^)(BOOL, NSError*))reply; +@end + +#endif /* _SECURITY_TRUSTDFILEHELPER_H_ */ diff --git a/trust/trustd/trustdFileHelper/trustdFileHelper.m b/trust/trustd/trustdFileHelper/trustdFileHelper.m new file mode 100644 index 00000000..6200aa2c --- /dev/null +++ b/trust/trustd/trustdFileHelper/trustdFileHelper.m @@ -0,0 +1,224 @@ +// +// trustdFileHelper.m +// trustdFileHelper +// +// Copyright © 2020 Apple Inc. All rights reserved. +// + +#import +#import +#include + +#include +#include + +#include "trust/trustd/trustdFileLocations.h" +#include "trust/trustd/trustdFileHelper/trustdFileHelper.h" + +@implementation TrustdFileHelper + +- (BOOL)changeOwnerOfValidFile:(NSString *)fileName error:(NSError **)error +{ + __block BOOL result = YES; + __block NSError *localError = nil; + WithPathInRevocationInfoDirectory((__bridge CFStringRef)fileName, ^(const char *utf8String) { + int ret = chown(utf8String, TRUSTD_ROLE_ACCOUNT, TRUSTD_ROLE_ACCOUNT); + if (!(ret == 0)) { + int localErrno = errno; + localError = [NSError errorWithDomain:NSPOSIXErrorDomain code:localErrno + userInfo:@{NSLocalizedDescriptionKey : [NSString localizedStringWithFormat:@"failed to change owner of %s: %s", utf8String, strerror(localErrno)]}]; + if (localErrno != ENOENT) { // missing file is not a failure + secerror("failed to change owner of %s: %s", utf8String, strerror(localErrno)); + result = NO; + } + } + }); + if (!result && error && !*error) { + *error = localError; + } + return result; +} + +- (BOOL)fixValidPermissions:(NSError **)error +{ + secdebug("helper", "fixing permissions on valid database"); + NSString *baseFilename = @"valid.sqlite3"; + BOOL result = [self changeOwnerOfValidFile:baseFilename error:error]; + if (result) { + NSString *shmFile = [NSString stringWithFormat:@"%@-shm", baseFilename]; + result = [self changeOwnerOfValidFile:shmFile error:error]; + } + if (result) { + NSString *walFile = [NSString stringWithFormat:@"%@-wal", baseFilename]; + result = [self changeOwnerOfValidFile:walFile error:error]; + } + if (result) { + NSString *journalFile = [NSString stringWithFormat:@"%@-journal", baseFilename]; + result = [self changeOwnerOfValidFile:journalFile error:error]; + } + // Always change the replacement semaphore if it exists + if (![self changeOwnerOfValidFile:@".valid_replace" error:error]) { + result = NO; + } + return result; +} + +- (BOOL)changePermissionsOfKeychainDirectoryFile:(NSString *)fileName error:(NSError **)error +{ + __block BOOL result = YES; + __block NSError *localError = nil; + WithPathInKeychainDirectory((__bridge CFStringRef)fileName, ^(const char *utf8String) { + int ret = chmod(utf8String, 0644); // allow all users to read so that _trustd user can migrate contents + if (!(ret == 0)) { + int localErrno = errno; + localError = [NSError errorWithDomain:NSPOSIXErrorDomain code:localErrno + userInfo:@{NSLocalizedDescriptionKey : [NSString localizedStringWithFormat:@"failed to change permissions of %s: %s", utf8String, strerror(localErrno)]}]; + if (localErrno != ENOENT) { // missing file is not a failure + secerror("failed to change permissions of %s: %s", utf8String, strerror(localErrno)); + result = NO; + } + } + }); + if (error && !*error) { + *error = localError; + } + return result; +} + +- (BOOL)allowTrustdToReadFilesForMigration:(NSError **)error +{ + secdebug("helper", "fixing permissions files that need migration"); + BOOL result = [self changePermissionsOfKeychainDirectoryFile:@"TrustStore.sqlite3" error:error]; + if (![self changePermissionsOfKeychainDirectoryFile:@"com.apple.security.exception_reset_counter.plist" error:error]) { + result = NO; + } + if (![self changePermissionsOfKeychainDirectoryFile:@"CTExceptions.plist" error:error]) { + result = NO; + } + if (![self changePermissionsOfKeychainDirectoryFile:@"CARevocation.plist" error:error]) { + result = NO; + } + if (![self changePermissionsOfKeychainDirectoryFile:@"TransparentConnectionPins.plist" error:error]) { + result = NO; + } + return result; +} + +- (void)allowTrustdToWriteAnalyticsFiles +{ + WithPathInKeychainDirectory(CFSTR("Analytics"), ^(const char *path) { + /* We need _securityd, _trustd, and root all to be able to write. They share no groups. */ + mode_t permissions = 0777; + int ret = mkpath_np(path, permissions); + if (!(ret == 0 || ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + } + + ret = chmod(path, permissions); + if (!(ret == 0)) { + secerror("failed to change permissions of %s: %s", path, strerror(errno)); + } + }); +} + +- (void)deleteSystemDbFiles:(CFStringRef)baseFilename +{ + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(baseFilename), ^(const char *utf8String) { + (void)remove(utf8String); + }); + CFStringRef shmFile = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@-shm"), baseFilename); + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(shmFile), ^(const char *utf8String) { + (void)remove(utf8String); + }); + CFReleaseNull(shmFile); + CFStringRef walFile = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@-wal"), baseFilename); + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(walFile), ^(const char *utf8String) { + (void)remove(utf8String); + }); + CFReleaseNull(walFile); + CFStringRef journalFile = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@-journal"), baseFilename); + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(journalFile), ^(const char *utf8String) { + (void)remove(utf8String); + }); + CFReleaseNull(journalFile); +} + +- (void)deleteSupplementalsAssetsDir +{ + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("SupplementalsAssets/OTAPKIContext.plist")), ^(const char *utf8String) { + (void)remove(utf8String); + }); + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("SupplementalsAssets/TrustedCTLogs.plist")), ^(const char *utf8String) { + (void)remove(utf8String); + }); + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("SupplementalsAssets/TrustedCTLogs_nonTLS.plist")), ^(const char *utf8String) { + (void)remove(utf8String); + }); + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("SupplementalsAssets/AnalyticsSamplingRates.plist")), ^(const char *utf8String) { + (void)remove(utf8String); + }); + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("SupplementalsAssets/AppleCertificateAuthorities.plist")), ^(const char *utf8String) { + (void)remove(utf8String); + }); + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("SupplementalsAssets")), ^(const char *utf8String) { + (void)remove(utf8String); + }); +} + +- (void)deleteOldFiles +{ + secdebug("helper", "deleting /Library/Keychains/crls/valid.sqlite3"); + [self deleteSystemDbFiles:CFSTR("crls/valid.sqlite3")]; + WithPathInDirectory(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("crls")), ^(const char *utf8String) { + secdebug("helper", "deleting crls directory"); + (void)remove(utf8String); + }); + + secdebug("helper", "deleting /Library/Keychains/pinningrules.sqlite3"); + [self deleteSystemDbFiles:CFSTR("pinningrules.sqlite3")]; + + secdebug("helper", "deleting SupplementalsAssets directory"); + [self deleteSupplementalsAssetsDir]; + + secdebug("helper", "deleting CAIssuer cache"); +#if TARGET_OS_IPHONE + WithPathInKeychainDirectory(CFSTR("caissuercache.sqlite3"), ^(const char *utf8String) { + (void)remove(utf8String); + }); +#else // !TARGET_OS_IPHONE + WithPathInUserCacheDirectory(CFSTR("caissuercache.sqlite3"), ^(const char *utf8String) { + (void)remove(utf8String); + }); +#endif // !TARGET_OS_IPHONE + +#if TARGET_OS_IPHONE + secdebug("helper", "deleting OCSP cache"); + [self deleteSystemDbFiles:CFSTR("ocspcache.sqlite3")]; +#endif // TARGET_OS_IPHONE + +} + +- (void)fixFiles:(void (^)(BOOL, NSError*))reply +{ + secdebug("ipc", "received trustd request to fix files"); + NSError *error = nil; + [self deleteOldFiles]; +#if TARGET_OS_OSX + if (![self fixValidPermissions:&error]) { + secerror("failed to fix Valid permissions for trustd"); + reply(NO, error); + return; + } +#else // !TARGET_OS_OSX + secdebug("helper", "update Analytics directory permissions"); + [self allowTrustdToWriteAnalyticsFiles]; + if (![self allowTrustdToReadFilesForMigration:&error]) { + secerror("failed to change permissions so trustd can read files for migration"); + reply(NO, error); + return; + } +#endif // !TARGET_OS_OSX + reply(YES, error); +} + +@end diff --git a/trust/trustd/trustdFileLocations.h b/trust/trustd/trustdFileLocations.h new file mode 100644 index 00000000..72f9de9e --- /dev/null +++ b/trust/trustd/trustdFileLocations.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +#ifndef _SECURITY_TRUSTDFILELOCATIONS_H_ +#define _SECURITY_TRUSTDFILELOCATIONS_H_ + +#include +#include "utilities/SecFileLocations.h" + +__BEGIN_DECLS + +#define TRUSTD_ROLE_ACCOUNT 282 + +// Returns a boolean for whether the current instance is the system trustd +bool SecOTAPKIIsSystemTrustd(void); + +CFURLRef SecCopyURLForFileInRevocationInfoDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; +CFURLRef SecCopyURLForFileInProtectedTrustdDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; +CFURLRef SecCopyURLForFileInPrivateTrustdDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; +CFURLRef SecCopyURLForFileInPrivateUserTrustdDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; + +void WithPathInRevocationInfoDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); +void WithPathInProtectedTrustdDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); +void WithPathInPrivateTrustdDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); +void WithPathInPrivateUserTrustdDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); + +void FixTrustdFilePermissions(void); +bool TrustdChangeFileProtectionToClassD(const char *filename, CFErrorRef *error); + +#if __OBJC__ +#define TrustdFileHelperXPCServiceName "com.apple.trustdFileHelper" +@protocol TrustdFileHelper_protocol +- (void)fixFiles:(void (^)(BOOL, NSError*))reply; +@end + +@interface NSDictionary (trustdAdditions) +- (BOOL)writeToClassDURL:(NSURL *)url permissions:(mode_t)permissions error:(NSError **)error; +@end +#endif // __OBJC__ + +__END_DECLS + +#endif /* _SECURITY_TRUSTDFILELOCATIONS_H_ */ diff --git a/trust/trustd/trustdFileLocations.m b/trust/trustd/trustdFileLocations.m new file mode 100644 index 00000000..4f334379 --- /dev/null +++ b/trust/trustd/trustdFileLocations.m @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2020 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#import +#include +#include + +#include +#include +#include + +#include "OTATrustUtilities.h" +#include "trustdFileLocations.h" + +#if TARGET_OS_OSX +#include +#endif + +#if !TARGET_OS_SIMULATOR && (TARGET_OS_IPHONE || TARGET_CPU_ARM64) +#include +#endif + +#define ROOT_ACCOUNT 0 + +bool SecOTAPKIIsSystemTrustd() { + static bool result = false; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ +#ifdef NO_SERVER + // Test app running as trustd + result = true; +#else // !NO_SERVER + if (getuid() == TRUSTD_ROLE_ACCOUNT || + (getuid() == ROOT_ACCOUNT && gTrustd)) { // Test app running as trustd + result = true; + } +#endif // !NO_SERVER + }); + return result; +} + +/* + * trustd's data vault hierarchy: + * * /var/protected/trustd - requires an entitlement to write but is available to read by all processes + * used for non-privacy sensitive system data (e.g. Valid DB, pinning DB, MobileAsset files) + * * /var/protected/trustd/private - requires an entitlement to read and write, trustds running as every user can rwx directory + * used for sensitive system data (e.g. administrative configuration and admin trust store) + * * /var/protected/trustd/private/ - inherits the entitlement requirement, but uses unix permissions to restrict rwx to + * the trustd running as the user corresponding to the uuid. Used for sensitive user + * data (e.g. OCSP and CA issuer caches, user trust store) + */ + +CFURLRef SecCopyURLForFileInProtectedTrustdDirectory(CFStringRef fileName) +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + WithPathInProtectedDirectory(CFSTR("trustd"), ^(const char *path) { + mode_t permissions = 0777; // Non-system trustd's create directory with expansive permissions + int ret = mkpath_np(path, permissions); + if (!(ret == 0 || ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + } + if (SecOTAPKIIsSystemTrustd()) { // System trustd fixes them up since only it should be writing + permissions = 0755; + uid_t currentUid = getuid(); + chown(path, currentUid, currentUid); + chmod(path, permissions); + } + }); + }); + NSString *path = @"trustd/"; + if (fileName) { + path = [NSString stringWithFormat:@"trustd/%@", fileName]; + } + return SecCopyURLForFileInProtectedDirectory((__bridge CFStringRef)path); +} + +CFURLRef SecCopyURLForFileInPrivateTrustdDirectory(CFStringRef fileName) +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + WithPathInProtectedTrustdDirectory(CFSTR("private"), ^(const char *path) { + mode_t permissions = 0777; + int ret = mkpath_np(path, permissions); + if (!(ret == 0 || ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + } + chmod(path, permissions); + }); + }); + NSString *path = @"private/"; + if (fileName) { + path = [NSString stringWithFormat:@"private/%@", fileName]; + } + return SecCopyURLForFileInProtectedTrustdDirectory((__bridge CFStringRef)path); +} + +CFURLRef SecCopyURLForFileInPrivateUserTrustdDirectory(CFStringRef fileName) +{ +#if TARGET_OS_OSX + uid_t euid = geteuid(); + uuid_t currentUserUuid; + int ret = mbr_uid_to_uuid(euid, currentUserUuid); + if (ret != 0) { + secerror("failed to get UUID for user(%d) - %d", euid, ret); + return SecCopyURLForFileInPrivateTrustdDirectory(fileName); + } + NSUUID *userUuid = [[NSUUID alloc] initWithUUIDBytes:currentUserUuid]; + NSString *directory = [NSString stringWithFormat:@"/%@",[userUuid UUIDString]]; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + WithPathInPrivateTrustdDirectory((__bridge CFStringRef)directory, ^(const char *path) { + mode_t permissions = 0700; + int mkpath_ret = mkpath_np(path, permissions); + if (!(mkpath_ret == 0 || mkpath_ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + } + chmod(path, permissions); + }); + }); + NSString *path = directory; + if (fileName) { + path = [NSString stringWithFormat:@"%@/%@", directory, fileName]; + } + return SecCopyURLForFileInPrivateTrustdDirectory((__bridge CFStringRef)path); +#else + return SecCopyURLForFileInPrivateTrustdDirectory(fileName); +#endif +} + +CFURLRef SecCopyURLForFileInRevocationInfoDirectory(CFStringRef fileName) +{ + return SecCopyURLForFileInProtectedTrustdDirectory(fileName); +} + +void WithPathInRevocationInfoDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)) +{ + WithPathInDirectory(SecCopyURLForFileInRevocationInfoDirectory(fileName), operation); +} + +void WithPathInProtectedTrustdDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)) +{ + WithPathInDirectory(SecCopyURLForFileInProtectedTrustdDirectory(fileName), operation); +} + +void WithPathInPrivateTrustdDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)) +{ + WithPathInDirectory(SecCopyURLForFileInPrivateTrustdDirectory(fileName), operation); +} + +void WithPathInPrivateUserTrustdDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)) +{ + WithPathInDirectory(SecCopyURLForFileInPrivateUserTrustdDirectory(fileName), operation); +} + +static BOOL needToFixFilePermissions(void) { + __block BOOL result = NO; +#if TARGET_OS_SIMULATOR + // Simulators don't upgrade, so no need to fix file permissions +#elif TARGET_OS_IPHONE + /* Did trust store already migrate */ + WithPathInPrivateTrustdDirectory(CFSTR("TrustStore.sqlite3"), ^(const char *utf8String) { + struct stat sb; + int ret = stat(utf8String, &sb); + if (ret != 0) { + secinfo("helper", "failed to stat TrustStore: %s", strerror(errno)); + result = YES; + } + }); + /* Can we write to the analytics directory */ + WithPathInKeychainDirectory(CFSTR("Analytics"), ^(const char *utf8String) { + struct stat sb; + int ret = stat(utf8String, &sb); + if (ret != 0) { + // Check errno. Missing directory or file errors do not require any fixes + if (errno != ENOTDIR && errno != ENOENT) { + secinfo("helper", "failed to stat Analytics dir: %s", strerror(errno)); + result = YES; + } + } else { + // Check that all users have rwx for Analytics dir + if ((sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != (S_IRWXU | S_IRWXG | S_IRWXO)) { + secinfo("helper", "wrong permissions on Analytics dir: %d", sb.st_mode); + result = YES; + } + } + }); +#else + /* Can we read/write Valid file? */ + WithPathInRevocationInfoDirectory(CFSTR("valid.sqlite3"), ^(const char *utf8String) { + struct stat sb; + int ret = stat(utf8String, &sb); + if (ret != 0) { + // Check errno. Missing directory or file errors do not require any fixes + if (errno != ENOTDIR && errno != ENOENT) { + secinfo("helper", "failed to stat valid db: %s", strerror(errno)); + result = YES; + } + } else { + // Successful call. Check if the file owner has been changed + if (sb.st_uid != TRUSTD_ROLE_ACCOUNT) { + secinfo("helper", "wrong owner for valid db"); + result = YES; + } + } + }); +#endif + return result; +} + +static NSXPCConnection* getConnection() +{ +#if TARGET_OS_OSX + NSString *xpcServiceName = @TrustdFileHelperXPCServiceName; +#else + NSString *xpcServiceName = @"com.apple.securityuploadd"; +#endif + NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:xpcServiceName options:0]; + connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(TrustdFileHelper_protocol)]; + [connection resume]; + return connection; +} + +void FixTrustdFilePermissions(void) +{ +#if TARGET_OS_OSX + const NSString *processName = @"trustdFileHelper"; +#else + const NSString *processName = @"securityuploadd"; +#endif + @autoreleasepool { + if (!needToFixFilePermissions()) { + secinfo("helper", "trustd file permissions already fixed. skipping trustdFileHelper call."); + return; + } + @try { + NSXPCConnection *connection = getConnection(); + if (!connection) { + secerror("failed to ceate %{public}@ connection", processName); + } else { + id protocol = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + secerror("failed to talk to %{public}@: %@", processName, error); + }]; + if (protocol) { + secdebug("ipc", "asking the file helper to fix our files"); + [protocol fixFiles:^(BOOL result, NSError *error) { + if (!result) { + secerror("%{public}@ failed to fix our files: %@", processName, error); + } else { + secdebug("ipc", "file helper successfully completed fixes"); + } + }]; + } + } + } + @catch(id anException) { + secerror("failed to fix files; caught exception: %@", anException); + } + } +} + +bool TrustdChangeFileProtectionToClassD(const char *filename, CFErrorRef *error) { +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR + bool result = true; + int file_fd = open(filename, O_RDONLY); + if (file_fd) { + int retval = fcntl(file_fd, F_SETPROTECTIONCLASS, PROTECTION_CLASS_D); + if (retval < 0) { + NSError *localError = [NSError errorWithDomain:NSPOSIXErrorDomain + code:errno + userInfo:@{NSLocalizedDescriptionKey : [NSString localizedStringWithFormat:@"failed to change protection class of %s: %s", filename, strerror(errno)]}]; + if (error && !*error) { + *error = (CFErrorRef)CFBridgingRetain(localError); + } + result = false; + } + close(file_fd); + } else { + NSError *localError = [NSError errorWithDomain:NSPOSIXErrorDomain + code:errno + userInfo:@{NSLocalizedDescriptionKey : [NSString localizedStringWithFormat:@"failed to open file for protection class change %s: %s", filename, strerror(errno)]}]; + if (error && !*error) { + *error = (CFErrorRef)CFBridgingRetain(localError); + } + result = false; + } + return result; +#else // !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR + return true; +#endif +} + +@implementation NSDictionary (trustdAdditions) +- (BOOL)writeToClassDURL:(NSURL *)url permissions:(mode_t)permissions error:(NSError **)error { + if ([self writeToURL:url error:error]) { + CFErrorRef localError = NULL; + if (!TrustdChangeFileProtectionToClassD([url fileSystemRepresentation], &localError)) { + if (error) { + *error = CFBridgingRelease(localError); + } else { + CFReleaseNull(error); + } + return NO; + } + int ret = chmod([url fileSystemRepresentation], permissions); + if (!(ret == 0)) { + int localErrno = errno; + secerror("failed to change permissions of %s: %s", [url fileSystemRepresentation], strerror(localErrno)); + if (error) { + *error = [NSError errorWithDomain:NSPOSIXErrorDomain code:localErrno + userInfo:@{NSLocalizedDescriptionKey : [NSString localizedStringWithFormat:@"failed to change permissions of %s: %s", [url fileSystemRepresentation], strerror(localErrno)]}]; + } + return NO; + } + return YES; + } + return NO; +} +@end diff --git a/trust/trustd/trustd_spi.c b/trust/trustd/trustd_spi.c index 0ed05260..53fd9606 100644 --- a/trust/trustd/trustd_spi.c +++ b/trust/trustd/trustd_spi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2018-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,6 +25,7 @@ #include #include "../utilities/SecFileLocations.h" +#include "../utilities/debugging.h" #include "../sec/ipc/securityd_client.h" #include "trust/trustd/SecPolicyServer.h" @@ -35,24 +36,21 @@ #include "trust/trustd/SecTrustLoggingServer.h" #include "trust/trustd/SecRevocationDb.h" #include "trust/trustd/SecPinningDb.h" +#include "trust/trustd/SecTrustExceptionResetCount.h" #include "trustd_spi.h" #if TARGET_OS_OSX #include "trust/trustd/macOS/SecTrustOSXEntryPoints.h" #endif -#if TARGET_OS_IPHONE -#include "trust/trustd/SecTrustExceptionResetCount.h" -#endif - #endif // LIBTRUSTD #ifdef LIBTRUSTD struct trustd trustd_spi = { .sec_trust_store_for_domain = SecTrustStoreForDomainName, - .sec_trust_store_contains = SecTrustStoreContainsCertificateWithDigest, + .sec_trust_store_contains = _SecTrustStoreContainsCertificate, .sec_trust_store_set_trust_settings = _SecTrustStoreSetTrustSettings, - .sec_trust_store_remove_certificate = SecTrustStoreRemoveCertificateWithDigest, + .sec_trust_store_remove_certificate = _SecTrustStoreRemoveCertificate, .sec_truststore_remove_all = _SecTrustStoreRemoveAll, .sec_trust_evaluate = SecTrustServerEvaluate, .sec_ota_pki_trust_store_version = SecOTAPKIGetCurrentTrustStoreVersion, @@ -69,26 +67,39 @@ struct trustd trustd_spi = { .sec_networking_analytics_report = SecNetworkingAnalyticsReport, .sec_trust_store_set_ct_exceptions = _SecTrustStoreSetCTExceptions, .sec_trust_store_copy_ct_exceptions = _SecTrustStoreCopyCTExceptions, -#if TARGET_OS_IPHONE .sec_trust_get_exception_reset_count = SecTrustServerGetExceptionResetCount, .sec_trust_increment_exception_reset_count = SecTrustServerIncrementExceptionResetCount, -#endif + .sec_trust_store_set_ca_revocation_additions = _SecTrustStoreSetCARevocationAdditions, + .sec_trust_store_copy_ca_revocation_additions = _SecTrustStoreCopyCARevocationAdditions, + .sec_valid_update = SecRevocationDbUpdate, + .sec_trust_store_set_transparent_connection_pins = _SecTrustStoreSetTransparentConnectionPins, + .sec_trust_store_copy_transparent_connection_pins = _SecTrustStoreCopyTransparentConnectionPins, }; #endif void trustd_init(CFURLRef home_path) { if (home_path) - SetCustomHomeURL(home_path); + SecSetCustomHomeURL(home_path); trustd_init_server(); } void trustd_init_server(void) { -#ifdef LIBTRUSTD gTrustd = &trustd_spi; - SecPolicyServerInitialize(); - SecRevocationDbInitialize(); - SecPinningDbInitialize(); +#ifdef LIBTRUSTD + _SecTrustStoreMigrateConfigurations(); + SecTrustServerMigrateExceptionsResetCount(); +#if TARGET_OS_IPHONE + CFErrorRef error = NULL; + if (!_SecTrustStoreMigrateUserStore(&error)) { + secerror("failed to migrate user trust store; new trust store will be empty: %@", error); + } + CFReleaseNull(error); +#endif + + SecPolicyServerInitialize(); // set up callbacks for policy checks + SecRevocationDbInitialize(); // set up revocation database if it doesn't already exist, or needs to be replaced + SecPinningDbInitialize(); // set up the pinning database #if TARGET_OS_OSX SecTrustLegacySourcesListenForKeychainEvents(); // set up the legacy keychain event listeners (for cache invalidation) #endif diff --git a/xcconfig/PlatformFeatures.xcconfig b/xcconfig/PlatformFeatures.xcconfig index 17f372c2..35f07f11 100644 --- a/xcconfig/PlatformFeatures.xcconfig +++ b/xcconfig/PlatformFeatures.xcconfig @@ -21,23 +21,23 @@ OCTAGON_ON[sdk=appletv*] = 1 TRUSTEDPEERS_ON = 0 TRUSTEDPEERS_ON[sdk=macosx*] = 1 TRUSTEDPEERS_ON[sdk=iphone*] = 1 -TRUSTEDPEERS_ON[sdk=bridgeos*] = 1 +TRUSTEDPEERS_ON[sdk=bridgeos*] = 0 TRUSTEDPEERS_ON[sdk=watch*] = 1 TRUSTEDPEERS_ON[sdk=appletv*] = 1 // SecureObject Sync should only be on on iOS and macOS, but until we have octagon, its on on watch and TV SECUREOBJECTSYNC_ON[sdk=iphone*] = 1 -SECUREOBJECTSYNC_ON[sdk=bridgeos*] = 1 +SECUREOBJECTSYNC_ON[sdk=bridgeos*] = 0 SECUREOBJECTSYNC_ON[sdk=watch*] = 1 SECUREOBJECTSYNC_ON[sdk=appletv*] = 1 SECUREOBJECTSYNC_ON[sdk=macos*] = 1 -// Shared web credentials is only supported on iOS +// Shared web credentials is supported on iOS and macOS and Catalyst SHAREDWEBCREDENTIALS_ON[sdk=iphone*] = 1 SHAREDWEBCREDENTIALS_ON[sdk=bridgeos*] = 0 SHAREDWEBCREDENTIALS_ON[sdk=watch*] = 0 SHAREDWEBCREDENTIALS_ON[sdk=appletv*] = 0 -SHAREDWEBCREDENTIALS_ON[sdk=macos*] = 0 +SHAREDWEBCREDENTIALS_ON[sdk=macos*] = 1 ABC_BUGCAPTURE_ON[sdk=iphoneos*] = 1 ABC_BUGCAPTURE_ON[sdk=iphonesimulator*] = 0 diff --git a/xcconfig/PlatformLibraries.xcconfig b/xcconfig/PlatformLibraries.xcconfig index 1960abdc..eef498f4 100644 --- a/xcconfig/PlatformLibraries.xcconfig +++ b/xcconfig/PlatformLibraries.xcconfig @@ -1,17 +1,18 @@ - -OTHER_LDFLAGS_MOCK_AKS_LIBRARY = -laks_mock -framework SecurityFoundation + +OTHER_LDFLAGS_AKS_ACL_LIBRARY = -laks_acl + +OTHER_LDFLAGS_MOCK_AKS_LIBRARY = -laks_mock $(OTHER_LDFLAGS_AKS_ACL_LIBRARY) -framework SecurityFoundation -framework ProtocolBuffer OTHER_LDFLAGS_AKS_LIBRARY[sdk=macosx*] = -L$(SDKROOT)/usr/local/lib -laks -laks_real_witness OTHER_LDFLAGS_AKS_LIBRARY[sdk=iphoneos*] = -L$(SDKROOT)/usr/local/lib -laks -laks_real_witness OTHER_LDFLAGS_AKS_LIBRARY[sdk=watchos*] = -L$(SDKROOT)/usr/local/lib -laks -laks_real_witness OTHER_LDFLAGS_AKS_LIBRARY[sdk=appletvos*] = -L$(SDKROOT)/usr/local/lib -laks -laks_real_witness -OTHER_LDFLAGS_AKS_LIBRARY[sdk=iphonesimulator*] = -laks_mock -Wl,-upward_framework,SecurityFoundation -Wl,-upward_framework,ProtocolBuffer +OTHER_LDFLAGS_AKS_LIBRARY[sdk=iphonesimulator*] = -laks_mock $(OTHER_LDFLAGS_AKS_ACL_LIBRARY) -Wl,-upward_framework,SecurityFoundation -Wl,-upward_framework,ProtocolBuffer OTHER_LDFLAGS_MOBILE_KEYBAG[sdk=macosx*] = -framework MobileKeyBag OTHER_LDFLAGS_MOBILE_KEYBAG[sdk=iphoneos*] = -framework MobileKeyBag OTHER_LDFLAGS_MOBILE_KEYBAG[sdk=watchos*] = -framework MobileKeyBag OTHER_LDFLAGS_MOBILE_KEYBAG[sdk=appletvos*] = -framework MobileKeyBag -OTHER_LDFLAGS_AKS_ACL_LIBRARY = -laks_acl OTHER_LDFLAGS_ACM_LIBRARY[sdk=macosx*] = -lACM OTHER_LDFLAGS_ACM_LIBRARY[sdk=iphoneos*] = -lACM @@ -24,8 +25,11 @@ OTHER_LDFLAGS_ACM_LIBRARY[sdk=watchsimulator*] = OTHER_LDFLAGS_AGGREGATEDICTIONARY[sdk=embedded] = -framework AggregateDictionary OTHER_LDFLAGS_APPLESYSTEMINFO[sdk=macos*] = -framework AppleSystemInfo OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT[sdk=macosx*] = -lDiagnosticMessagesClient -OTHER_LDFLAGS_MOBILEGESTALT[sdk=embedded*] = -lMobileGestalt +OTHER_LDFLAGS_MOBILEGESTALT = -lMobileGestalt OTHER_LDFLAGS_IMG4DECODE[sdk=embedded] = -lImg4Decode +OTHER_LDFLAGS_IMG4DECODE[sdk=macosx*] = -lImg4Decode +OTHER_LDFLAGS_MSUDATAACCESSOR[sdk=embedded] = -framework MSUDataAccessor +OTHER_LDFLAGS_MSUDATAACCESSOR[sdk=macosx*] = -framework MSUDataAccessor OTHER_LDFLAGS_UPWARD_FOUNDATION = -Wl,-upward_framework,Foundation OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER = -Wl,-upward_framework,ProtocolBuffer OTHER_LDFLAGS_UPWARD_SECURITY = -Wl,-upward_framework,Security @@ -70,7 +74,9 @@ OTHER_LDFLAGS_COREFOLLOWUP[sdk=appletvsimulator*] = // The bridge appears to support protocol buffers. OTHER_LDFLAGS_PROTOBUF = -framework ProtocolBuffer +OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=macos*] = OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=iphoneos*] = -framework SharedWebCredentials +OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=iphonesimulator*] = -framework SharedWebCredentials OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=bridgeos*] = OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=watchos*] = OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=appletvos*] = @@ -87,6 +93,9 @@ OTHER_LDFLAGS_MOBILEASSET[sdk=bridgeos*] = OTHER_LDFLAGS_CORECDP = -weak_framework CoreCDP OTHER_LDFLAGS_CORECDP[sdk=bridgeos*] = +OTHER_LDFLAGS_CLOUDSERVICES = -weak_framework CloudServices +OTHER_LDFLAGS_CLOUDSERVICES[sdk=bridgeos*] = + OTHER_LDFLAGS_SECURITYFOUNDATION = -framework SecurityFoundation OTHER_LDFLAGS_SECURITYFOUNDATION[sdk=bridgeos*] = @@ -98,7 +107,7 @@ OTHER_LDFLAGS_IMCORE[sdk=bridgeos*] = OTHER_LDFLAGS_UserManagement[sdk=iphone*] = -framework UserManagement OTHER_LDFLAGS_UserManagement[sdk=macosx*] = -framework UserManagement OTHER_LDFLAGS_UserManagement[sdk=watch*] = -OTHER_LDFLAGS_UserManagement[sdk=appletv*] = +OTHER_LDFLAGS_UserManagement[sdk=appletv*] = -framework UserManagement OTHER_LDFLAGS_CrashReporterSupport[sdk=iphoneos*] = -framework CrashReporterSupport OTHER_LDFLAGS_CrashReporterSupport[sdk=macosx*] = @@ -112,3 +121,10 @@ OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER_1 = -weak_framework SymptomDiagnosticRep OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER_0 = OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER_ = OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER = $(OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER_$(ABC_BUGCAPTURE_ON)) + +// Convince Xcode to build platform-specific apps from a single target +OTHER_LDFLAGS_AppFrameworks[sdk=macosx*] = -framework AppKit +OTHER_LDFLAGS_AppFrameworks[sdk=embedded*] = -framework UIKit + +TEST_HOST_BINARY_PATH_IN_BUNDLE[sdk=macosx*] = Contents/MacOS/ +TEST_HOST_BINARY_PATH_IN_BUNDLE[sdk=embedded] = diff --git a/xcconfig/Security.xcconfig b/xcconfig/Security.xcconfig index 195db7c3..3351f117 100644 --- a/xcconfig/Security.xcconfig +++ b/xcconfig/Security.xcconfig @@ -1,4 +1,4 @@ -OTHER_CFLAGS = -isystem $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders -fconstant-cfstrings +OTHER_CFLAGS = -isystem $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders -fconstant-cfstrings -Wundef-prefix=TARGET_ -Werror=undef-prefix HEADER_SYMLINKS = $(PROJECT_DIR)/header_symlinks @@ -24,7 +24,10 @@ SECURITY_FUZZER_BASE_DIR = /AppleInternal/CoreOS/Fuzzers/Security // Apple Clang - Code Generation CLANG_TRIVIAL_AUTO_VAR_INIT = pattern -WARNING_CFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-error=deprecated-declarations -Wno-error=implicit-retain-self -Wno-error=#warnings -Wno-error=unused-function -Wno-error=unused-variable +CLANG_CXX_LANGUAGE_STANDARD = gnu++2a +GCC_C_LANGUAGE_STANDARD = gnu2x + +WARNING_CFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-error=deprecated-declarations -Wno-error=deprecated-implementations -Wno-error=implicit-retain-self -Wno-error=#warnings -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=documentation WARNING_CFLAGS[sdk=embedded*] = $(WARNING_CFLAGS) -Wformat=2 @@ -48,6 +51,5 @@ SECURITY_XCTEST_DIRECTORY = /AppleInternal/XCTests/com.apple.security // If you expect to be a 'securityd', use these flags OTHER_LDFLAGS_FOR_SECURITYD = -framework TrustedPeers $(OTHER_LDFLAGS_COREFOLLOWUP) -lnetwork $(OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER) -// Hack for runtime path for OCMock, add to your xctest bundle and embedd OCMock.framework -OCMOCK_RUNTIME_SEARCH_PATH = $(inherited) @executable_path/Frameworks @loader_path/Frameworks -OCMOCK_RUNTIME_SEARCH_PATH[sdk=macos*] = $(inherited) @executable_path/../Frameworks @loader_path/../Frameworks +LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA[sdk=embedded*] = /AppleInternal/XCTests/com.apple.security/Frameworks/OCMockUmbrella.framework/Frameworks +LD_RUNPATH_SEARCH_PATHS_OCMOCKUMBRELLA[sdk=macosx*] = /AppleInternal/XCTests/com.apple.security/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks diff --git a/xcconfig/all_arches.xcconfig b/xcconfig/all_arches.xcconfig deleted file mode 100644 index cf6cff55..00000000 --- a/xcconfig/all_arches.xcconfig +++ /dev/null @@ -1 +0,0 @@ -ARCHS[sdk=macosx*] = $(ARCHS_STANDARD_32_64_BIT) diff --git a/xcconfig/framework_requiring_modern_objc_runtime.xcconfig b/xcconfig/framework_requiring_modern_objc_runtime.xcconfig deleted file mode 100644 index 5c058bc8..00000000 --- a/xcconfig/framework_requiring_modern_objc_runtime.xcconfig +++ /dev/null @@ -1,7 +0,0 @@ - -// For frameworks that should only be built when the modern obj-c runtime is available. -// This file must be updated when new architectures are introduced. - -VALID_ARCHS = armv6 armv7 armv7k arm64 x86_64 x86_64h - -VALID_ARCHS[sdk=*simulator*] = armv6 armv7 armv7k arm64 i386 x86_64 x86_64h diff --git a/xcconfig/lib_ios.xcconfig b/xcconfig/lib_ios.xcconfig index bdbaaffc..334eb30b 100644 --- a/xcconfig/lib_ios.xcconfig +++ b/xcconfig/lib_ios.xcconfig @@ -18,7 +18,7 @@ COPY_PHASE_STRIP = NO SKIP_INSTALL = YES COPY_PHASE_STRIP = NO -GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_C_LANGUAGE_STANDARD = gnu2x HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES = NO diff --git a/xcconfig/swift_binary.xcconfig b/xcconfig/swift_binary.xcconfig index a968320e..f37fad36 100644 --- a/xcconfig/swift_binary.xcconfig +++ b/xcconfig/swift_binary.xcconfig @@ -16,3 +16,9 @@ OCTAGON_FLAG_1 = -D OCTAGON OTHER_SWIFT_FLAGS = $(OCTAGON_FLAG_$(OCTAGON_ON)) SWIFT_VERSION=5 +SWIFT_TREAT_WARNINGS_AS_ERRORS = YES + +// TEST_BUILD_STYLE will only work on macOS for now (rdar://37912414) +TEST_BUILD_STYLE[sdk=macosx*] = _APPLEINTERNAL + +SYSTEM_FRAMEWORK_SEARCH_PATHS[sdk=embedded] = $(inherited) ${PLATFORM_DIR}/Developer/AppleInternal/Library/Frameworks diff --git a/xcscripts/install-test-framework.sh b/xcscripts/install-test-framework.sh deleted file mode 100644 index ae4aae17..00000000 --- a/xcscripts/install-test-framework.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -framework="$1" - -found=no - -for a in ${TEST_FRAMEWORK_SEARCH_PATHS}; do - if test -d "${a}/${framework}" ; then - dst="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}" - - mkdir -p "{dst}" || { echo "mkdir failed with: $?" ; exit 1; } - ditto "${a}/${framework}" "${dst}/${framework}" || { echo "ditto failed with: $?" ; exit 1; } - xcrun codesign -s - -f "${dst}/${framework}" || { echo "codesign failed with: $?" ; exit 1; } - - found=yes - break - fi -done - -test "X${found}" != "Xyes" && exit 1 - -exit 0